blob: 8c0fdb986aa1ba6865e18164317a9c20a93c84a5 [file] [log] [blame]
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001#!/usr/bin/env python3
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002#
3# Copyright (c) 2012 Intel Corporation
4#
Brad Bishopc342db32019-05-15 21:57:59 -04005# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -05006#
7# DESCRIPTION
8# This script is called by the SDK installer script. It replaces the dynamic
9# loader path in all binaries and also fixes the SYSDIR paths/lengths and the
10# location of ld.so.cache in the dynamic loader binary
11#
12# AUTHORS
13# Laurentiu Palcu <laurentiu.palcu@intel.com>
14#
15
16import struct
17import sys
18import stat
19import os
20import re
21import errno
22
23if sys.version < '3':
24 def b(x):
25 return x
26else:
27 def b(x):
28 return x.encode(sys.getfilesystemencoding())
29
30old_prefix = re.compile(b("##DEFAULT_INSTALL_DIR##"))
31
32def get_arch():
33 f.seek(0)
34 e_ident =f.read(16)
35 ei_mag0,ei_mag1_3,ei_class = struct.unpack("<B3sB11x", e_ident)
36
37 if (ei_mag0 != 0x7f and ei_mag1_3 != "ELF") or ei_class == 0:
38 return 0
39
40 if ei_class == 1:
41 return 32
42 elif ei_class == 2:
43 return 64
44
45def parse_elf_header():
46 global e_type, e_machine, e_version, e_entry, e_phoff, e_shoff, e_flags,\
47 e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum, e_shstrndx
48
49 f.seek(0)
50 elf_header = f.read(64)
51
52 if arch == 32:
53 # 32bit
54 hdr_fmt = "<HHILLLIHHHHHH"
55 hdr_size = 52
56 else:
57 # 64bit
58 hdr_fmt = "<HHIQQQIHHHHHH"
59 hdr_size = 64
60
61 e_type, e_machine, e_version, e_entry, e_phoff, e_shoff, e_flags,\
62 e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum, e_shstrndx =\
63 struct.unpack(hdr_fmt, elf_header[16:hdr_size])
64
65def change_interpreter(elf_file_name):
66 if arch == 32:
67 ph_fmt = "<IIIIIIII"
68 else:
69 ph_fmt = "<IIQQQQQQ"
70
71 """ look for PT_INTERP section """
72 for i in range(0,e_phnum):
73 f.seek(e_phoff + i * e_phentsize)
74 ph_hdr = f.read(e_phentsize)
75 if arch == 32:
76 # 32bit
77 p_type, p_offset, p_vaddr, p_paddr, p_filesz,\
78 p_memsz, p_flags, p_align = struct.unpack(ph_fmt, ph_hdr)
79 else:
80 # 64bit
81 p_type, p_flags, p_offset, p_vaddr, p_paddr, \
82 p_filesz, p_memsz, p_align = struct.unpack(ph_fmt, ph_hdr)
83
84 """ change interpreter """
85 if p_type == 3:
86 # PT_INTERP section
87 f.seek(p_offset)
88 # External SDKs with mixed pre-compiled binaries should not get
89 # relocated so look for some variant of /lib
90 fname = f.read(11)
91 if fname.startswith(b("/lib/")) or fname.startswith(b("/lib64/")) or \
92 fname.startswith(b("/lib32/")) or fname.startswith(b("/usr/lib32/")) or \
93 fname.startswith(b("/usr/lib32/")) or fname.startswith(b("/usr/lib64/")):
94 break
Brad Bishop6e60e8b2018-02-01 10:27:11 -050095 if p_filesz == 0:
96 break
Patrick Williamsc124f4f2015-09-15 14:41:29 -050097 if (len(new_dl_path) >= p_filesz):
98 print("ERROR: could not relocate %s, interp size = %i and %i is needed." \
99 % (elf_file_name, p_memsz, len(new_dl_path) + 1))
100 break
101 dl_path = new_dl_path + b("\0") * (p_filesz - len(new_dl_path))
102 f.seek(p_offset)
103 f.write(dl_path)
104 break
105
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500106def change_dl_sysdirs(elf_file_name):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500107 if arch == 32:
108 sh_fmt = "<IIIIIIIIII"
109 else:
110 sh_fmt = "<IIQQQQIIQQ"
111
112 """ read section string table """
113 f.seek(e_shoff + e_shstrndx * e_shentsize)
114 sh_hdr = f.read(e_shentsize)
115 if arch == 32:
116 sh_offset, sh_size = struct.unpack("<16xII16x", sh_hdr)
117 else:
118 sh_offset, sh_size = struct.unpack("<24xQQ24x", sh_hdr)
119
120 f.seek(sh_offset)
121 sh_strtab = f.read(sh_size)
122
123 sysdirs = sysdirs_len = ""
124
125 """ change ld.so.cache path and default libs path for dynamic loader """
126 for i in range(0,e_shnum):
127 f.seek(e_shoff + i * e_shentsize)
128 sh_hdr = f.read(e_shentsize)
129
130 sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link,\
131 sh_info, sh_addralign, sh_entsize = struct.unpack(sh_fmt, sh_hdr)
132
133 name = sh_strtab[sh_name:sh_strtab.find(b("\0"), sh_name)]
134
135 """ look only into SHT_PROGBITS sections """
136 if sh_type == 1:
137 f.seek(sh_offset)
138 """ default library paths cannot be changed on the fly because """
139 """ the string lengths have to be changed too. """
140 if name == b(".sysdirs"):
141 sysdirs = f.read(sh_size)
142 sysdirs_off = sh_offset
143 sysdirs_sect_size = sh_size
144 elif name == b(".sysdirslen"):
145 sysdirslen = f.read(sh_size)
146 sysdirslen_off = sh_offset
147 elif name == b(".ldsocache"):
148 ldsocache_path = f.read(sh_size)
149 new_ldsocache_path = old_prefix.sub(new_prefix, ldsocache_path)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500150 new_ldsocache_path = new_ldsocache_path.rstrip(b("\0"))
151 if (len(new_ldsocache_path) >= sh_size):
152 print("ERROR: could not relocate %s, .ldsocache section size = %i and %i is needed." \
153 % (elf_file_name, sh_size, len(new_ldsocache_path)))
154 sys.exit(-1)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500155 # pad with zeros
156 new_ldsocache_path += b("\0") * (sh_size - len(new_ldsocache_path))
157 # write it back
158 f.seek(sh_offset)
159 f.write(new_ldsocache_path)
160 elif name == b(".gccrelocprefix"):
161 offset = 0
162 while (offset + 4096) <= sh_size:
163 path = f.read(4096)
164 new_path = old_prefix.sub(new_prefix, path)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500165 new_path = new_path.rstrip(b("\0"))
166 if (len(new_path) >= 4096):
167 print("ERROR: could not relocate %s, max path size = 4096 and %i is needed." \
168 % (elf_file_name, len(new_path)))
169 sys.exit(-1)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500170 # pad with zeros
171 new_path += b("\0") * (4096 - len(new_path))
172 #print "Changing %s to %s at %s" % (str(path), str(new_path), str(offset))
173 # write it back
174 f.seek(sh_offset + offset)
175 f.write(new_path)
176 offset = offset + 4096
177 if sysdirs != "" and sysdirslen != "":
178 paths = sysdirs.split(b("\0"))
179 sysdirs = b("")
180 sysdirslen = b("")
181 for path in paths:
182 """ exit the loop when we encounter first empty string """
183 if path == b(""):
184 break
185
186 new_path = old_prefix.sub(new_prefix, path)
187 sysdirs += new_path + b("\0")
188
189 if arch == 32:
190 sysdirslen += struct.pack("<L", len(new_path))
191 else:
192 sysdirslen += struct.pack("<Q", len(new_path))
193
194 """ pad with zeros """
195 sysdirs += b("\0") * (sysdirs_sect_size - len(sysdirs))
196
197 """ write the sections back """
198 f.seek(sysdirs_off)
199 f.write(sysdirs)
200 f.seek(sysdirslen_off)
201 f.write(sysdirslen)
202
203# MAIN
204if len(sys.argv) < 4:
205 sys.exit(-1)
206
207# In python > 3, strings may also contain Unicode characters. So, convert
208# them to bytes
209if sys.version_info < (3,):
210 new_prefix = sys.argv[1]
211 new_dl_path = sys.argv[2]
212else:
213 new_prefix = sys.argv[1].encode()
214 new_dl_path = sys.argv[2].encode()
215
216executables_list = sys.argv[3:]
217
218for e in executables_list:
219 perms = os.stat(e)[stat.ST_MODE]
220 if os.access(e, os.W_OK|os.R_OK):
221 perms = None
222 else:
223 os.chmod(e, perms|stat.S_IRWXU)
224
225 try:
226 f = open(e, "r+b")
227 except IOError:
228 exctype, ioex = sys.exc_info()[:2]
229 if ioex.errno == errno.ETXTBSY:
230 print("Could not open %s. File used by another process.\nPlease "\
231 "make sure you exit all processes that might use any SDK "\
232 "binaries." % e)
233 else:
234 print("Could not open %s: %s(%d)" % (e, ioex.strerror, ioex.errno))
235 sys.exit(-1)
236
237 # Save old size and do a size check at the end. Just a safety measure.
238 old_size = os.path.getsize(e)
239 if old_size >= 64:
240 arch = get_arch()
241 if arch:
242 parse_elf_header()
243 change_interpreter(e)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500244 change_dl_sysdirs(e)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500245
246 """ change permissions back """
247 if perms:
248 os.chmod(e, perms)
249
250 f.close()
251
252 if old_size != os.path.getsize(e):
253 print("New file size for %s is different. Looks like a relocation error!", e)
254 sys.exit(-1)
255