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
|
#!/usr/bin/env python3
import subprocess
import sys
import os
import shutil
import re
import stat
import tarfile
def get_executable_dynamic_libraries(filepath):
libs = []
process = subprocess.Popen(["ldd", filepath], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = process.communicate()
if process.returncode != 0:
raise RuntimeError("Failed to execute ldd on executable %s, error:\n%s" % (filepath, stderr))
lines = stdout.splitlines()
for line in lines:
s = line.split()
if b"=>" in s:
if len(s) >= 3:
libs.append(os.path.realpath(s[2].decode("UTF-8")))
return libs
def make_executable(filepath):
mode = os.stat(filepath).st_mode
os.chmod(filepath, mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
def main():
if len(sys.argv) <= 2:
print("usage: %s executable_path destination_path" % sys.argv[0])
exit(1)
os.makedirs(sys.argv[2], exist_ok=True)
libs = get_executable_dynamic_libraries(sys.argv[1])
so_loader_pattern = re.compile("ld-[0-9.]+\\.so.*")
so_loader = None
for lib in libs:
lib_filename = os.path.basename(lib)
if so_loader_pattern.match(lib_filename):
if so_loader != None:
print("Unexpected error: found multiple so loaders, unable to recover")
exit(2)
so_loader = lib_filename
executable_filename = os.path.basename(sys.argv[1])
new_executable_path = os.path.join(sys.argv[2], executable_filename)
shutil.copyfile(sys.argv[1], new_executable_path)
make_executable(new_executable_path)
print("Patching executable")
process = subprocess.Popen(["patchelf", "--set-interpreter", so_loader, new_executable_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = process.communicate()
if process.returncode != 0:
print("Failed to execute patchelf --set-interpreter on executable %s, error: %s" % (new_executable_path, stderr))
exit(3)
process = subprocess.Popen(["patchelf", "--set-rpath", ".", new_executable_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = process.communicate()
if process.returncode != 0:
print("Failed to execute patchelf --set-rpath on executable %s, error: %s" % (new_executable_path, stderr))
exit(4)
package_name = new_executable_path + ".tar.gz"
print("Creating package %s" % os.path.basename(package_name))
with tarfile.open(package_name, "w:gz") as tar:
for lib in libs:
print("Adding shared library %s to tar" % lib)
tar.add(lib, arcname=os.path.basename(lib))
print("Adding executable %s to tar" % sys.argv[1])
tar.add(new_executable_path, arcname=os.path.basename(new_executable_path))
print("Removing temporary file %s" % new_executable_path)
os.remove(new_executable_path)
print("Package has been created at %s" % package_name)
if __name__ == "__main__":
main()
|