-
Notifications
You must be signed in to change notification settings - Fork 5
/
elf-move.py
executable file
·148 lines (122 loc) · 4.94 KB
/
elf-move.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python3
import argparse
import itertools
import os
import sys
from collections import OrderedDict
def setup_parser():
"""Create commandline argument parser."""
parser = argparse.ArgumentParser()
parser.add_argument("btype", help="Binary type [avx2, avx512, apx]")
parser.add_argument("installdir", help="Content directory to scan")
parser.add_argument("targetdir", help="Target directory for output")
parser.add_argument("outfile", nargs='?', default="",
help="Deprecated: unused")
parser.add_argument("-s", "--skip", action="store_true",
default=False,
help="Don't process elf binaries")
parser.add_argument("-v", "--verbose", action="store_true",
default=False,
help="Add output for unused files in the installdir")
parser.add_argument("-S", "--skip-path", default=[], nargs=1,
action="append",
help="Don't process files with the target path(s)")
parser.add_argument("-p", "--path", default=[], nargs=1,
action="append",
help="Handle path regardless of file type (overrides skip)")
return parser
def process_install(args):
"""Create output based on the installdir.
Also output to stdout the non-elf file paths and hashes (useful to compare
different build types).
"""
always_process = set()
for item in args.path:
always_process.add(item[0])
args.path = always_process
filemap = OrderedDict()
for root, _, files in os.walk(args.installdir):
for name in files:
filepath = os.path.join(root, name)
if os.path.islink(filepath):
continue
try:
if os.stat(filepath).st_mode & os.path.stat.S_ISUID != 0:
continue
except:
continue
data = bytearray(4096)
memv = memoryview(data)
virtpath = os.path.join('/',
filepath.removeprefix(args.installdir))
with open(filepath, 'rb', buffering=0) as ifile:
ifile.readinto(memv)
elf = memv[:4] == b'\x7fELF'
if elf or virtpath in args.path:
filemap[virtpath] = [True,
filepath]
else:
filemap[virtpath] = [False,
filepath]
return filemap
def move_content(args, filemap):
"""Use the filemap to populate targetidr."""
if len(filemap) == 0:
return
skips = set(itertools.chain.from_iterable(args.skip_path))
if args.btype == 'avx2':
optimized_prefix = 'V3'
elif args.btype == 'avx512':
optimized_prefix = 'V4'
elif args.btype == 'apx':
optimized_prefix = 'VA'
else:
return
optimized_dir = os.path.join(args.targetdir, optimized_prefix)
os.makedirs(optimized_dir, exist_ok=True)
for virtpath, val in filemap.items():
elf = val[0]
source = val[1]
if virtpath in skips:
if args.verbose:
print(f"Skipping path {virtpath}")
continue
if elf:
if args.skip and virtpath not in args.path:
if args.verbose:
print(f"Skipping elf file {virtpath}")
continue
vdname = os.path.dirname(virtpath)
vbname = os.path.basename(virtpath)
if vdname in ('/bin', '/sbin', '/usr/sbin'):
virtpath = os.path.join('/usr/bin', vbname)
elif vdname == '/lib':
virtpath = os.path.join('/usr/lib', vbname)
elif vdname == '/lib64':
virtpath = os.path.join('/usr/lib64', vbname)
dest = os.path.join(optimized_dir, virtpath[1:])
os.makedirs(os.path.dirname(dest), exist_ok=True)
if args.verbose:
print(f"Installing {dest}")
os.rename(source, dest)
elif args.verbose:
print(f"{virtpath} not installed")
def main():
"""Entry point function."""
parser = setup_parser()
args = parser.parse_args()
if args.btype not in ("avx2", "avx512", "apx"):
print(f"Error: btype '{args.btype}' not supported (needs to be either avx2, avx512 or apx)")
sys.exit(-1)
if args.outfile:
print('Warning: outfile argument is longer used, ignoring.')
if args.targetdir.endswith('/usr/share/clear/optimized-elf/'):
# Catch previous invocation with targetdir being the
# optimized-elf directory that is no longer correct.
print('Error: Full path for optimized-elf detected!')
print(' targetdir should be the root of the output directory.')
sys.exit(-1)
filemap = process_install(args)
move_content(args, filemap)
if __name__ == '__main__':
main()