diff options
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/relocate_sdk.py | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/scripts/relocate_sdk.py b/scripts/relocate_sdk.py new file mode 100755 index 0000000000..b247e65ce3 --- /dev/null +++ b/scripts/relocate_sdk.py | |||
@@ -0,0 +1,200 @@ | |||
1 | #!/usr/bin/env python | ||
2 | # | ||
3 | # Copyright (c) 2012 Intel Corporation | ||
4 | # | ||
5 | # This program is free software; you can redistribute it and/or modify | ||
6 | # it under the terms of the GNU General Public License version 2 as | ||
7 | # published by the Free Software Foundation. | ||
8 | # | ||
9 | # This program is distributed in the hope that it will be useful, | ||
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
12 | # See the GNU General Public License for more details. | ||
13 | # | ||
14 | # You should have received a copy of the GNU General Public License | ||
15 | # along with this program; if not, write to the Free Software | ||
16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | # | ||
18 | # DESCRIPTION | ||
19 | # This script is called by the SDK installer script. It replaces the dynamic | ||
20 | # loader path in all binaries and also fixes the SYSDIR paths/lengths and the | ||
21 | # location of ld.so.cache in the dynamic loader binary | ||
22 | # | ||
23 | # AUTHORS | ||
24 | # Laurentiu Palcu <laurentiu.palcu@intel.com> | ||
25 | # | ||
26 | |||
27 | import struct | ||
28 | import sys | ||
29 | import stat | ||
30 | import os | ||
31 | import re | ||
32 | |||
33 | old_prefix = re.compile("##DEFAULT_INSTALL_DIR##") | ||
34 | |||
35 | def get_arch(): | ||
36 | f.seek(0) | ||
37 | e_ident =f.read(16) | ||
38 | ei_mag0,ei_mag1_3,ei_class = struct.unpack("<B3sB11x", e_ident) | ||
39 | |||
40 | if (ei_mag0 != 0x7f and ei_mag1_3 != "ELF") or ei_class == 0: | ||
41 | return 0 | ||
42 | |||
43 | if ei_class == 1: | ||
44 | return 32 | ||
45 | elif ei_class == 2: | ||
46 | return 64 | ||
47 | |||
48 | def parse_elf_header(): | ||
49 | global e_type, e_machine, e_version, e_entry, e_phoff, e_shoff, e_flags,\ | ||
50 | e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum, e_shstrndx | ||
51 | |||
52 | f.seek(0) | ||
53 | elf_header = f.read(64) | ||
54 | |||
55 | if arch == 32: | ||
56 | # 32bit | ||
57 | hdr_struct = struct.Struct("<HHILLLIHHHHHH") | ||
58 | hdr_size = 52 | ||
59 | else: | ||
60 | # 64bit | ||
61 | hdr_struct = struct.Struct("<HHIQQQIHHHHHH") | ||
62 | hdr_size = 64 | ||
63 | |||
64 | e_type, e_machine, e_version, e_entry, e_phoff, e_shoff, e_flags,\ | ||
65 | e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum, e_shstrndx =\ | ||
66 | hdr_struct.unpack(elf_header[16:hdr_size]) | ||
67 | |||
68 | def change_interpreter(): | ||
69 | if arch == 32: | ||
70 | ph_struct = struct.Struct("<IIIIIIII") | ||
71 | else: | ||
72 | ph_struct = struct.Struct("<IIQQQQQQ") | ||
73 | |||
74 | """ look for PT_INTERP section """ | ||
75 | for i in range(0,e_phnum): | ||
76 | f.seek(e_phoff + i * e_phentsize) | ||
77 | ph_hdr = f.read(e_phentsize) | ||
78 | if arch == 32: | ||
79 | # 32bit | ||
80 | p_type, p_offset, p_vaddr, p_paddr, p_filesz,\ | ||
81 | p_memsz, p_flags, p_align = ph_struct.unpack(ph_hdr) | ||
82 | else: | ||
83 | # 64bit | ||
84 | p_type, p_flags, p_offset, p_vaddr, p_paddr, \ | ||
85 | p_filesz, p_memsz, p_align = ph_struct.unpack(ph_hdr) | ||
86 | |||
87 | """ change interpreter """ | ||
88 | if p_type == 3: | ||
89 | # PT_INTERP section | ||
90 | f.seek(p_offset) | ||
91 | dl_path = new_dl_path + "\0" * (e_phentsize - len(new_dl_path)) | ||
92 | f.write(new_dl_path) | ||
93 | break | ||
94 | |||
95 | def change_dl_sysdirs(): | ||
96 | if arch == 32: | ||
97 | sh_struct = struct.Struct("<IIIIIIIIII") | ||
98 | else: | ||
99 | sh_struct = struct.Struct("<IIQQQQIIQQ") | ||
100 | |||
101 | """ read section string table """ | ||
102 | f.seek(e_shoff + e_shstrndx * e_shentsize) | ||
103 | sh_hdr = f.read(e_shentsize) | ||
104 | if arch == 32: | ||
105 | sh_offset, sh_size = struct.unpack("<16xII16x", sh_hdr) | ||
106 | else: | ||
107 | sh_offset, sh_size = struct.unpack("<24xQQ24x", sh_hdr) | ||
108 | |||
109 | f.seek(sh_offset) | ||
110 | sh_strtab = f.read(sh_size) | ||
111 | |||
112 | sysdirs = sysdirs_len = "" | ||
113 | |||
114 | """ change ld.so.cache path and default libs path for dynamic loader """ | ||
115 | for i in range(0,e_shnum): | ||
116 | f.seek(e_shoff + i * e_shentsize) | ||
117 | sh_hdr = f.read(e_shentsize) | ||
118 | |||
119 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link,\ | ||
120 | sh_info, sh_addralign, sh_entsize = sh_struct.unpack(sh_hdr) | ||
121 | |||
122 | name = sh_strtab[sh_name:sh_strtab.find("\0", sh_name)] | ||
123 | |||
124 | """ look only into SHT_PROGBITS sections """ | ||
125 | if sh_type == 1: | ||
126 | f.seek(sh_offset) | ||
127 | """ default library paths cannot be changed on the fly because """ | ||
128 | """ the string lengths have to be changed too. """ | ||
129 | if name == ".sysdirs": | ||
130 | sysdirs = f.read(sh_size) | ||
131 | sysdirs_off = sh_offset | ||
132 | sysdirs_sect_size = sh_size | ||
133 | elif name == ".sysdirslen": | ||
134 | sysdirslen = f.read(sh_size) | ||
135 | sysdirslen_off = sh_offset | ||
136 | elif name == ".ldsocache": | ||
137 | ldsocache_path = f.read(sh_size) | ||
138 | new_ldsocache_path = old_prefix.sub(new_prefix, ldsocache_path) | ||
139 | # pad with zeros | ||
140 | new_ldsocache_path += "\0" * (sh_size - len(new_ldsocache_path)) | ||
141 | # write it back | ||
142 | f.seek(sh_offset) | ||
143 | f.write(new_ldsocache_path) | ||
144 | |||
145 | if sysdirs != "" and sysdirslen != "": | ||
146 | paths = sysdirs.split("\0") | ||
147 | sysdirs = "" | ||
148 | sysdirslen = "" | ||
149 | for path in paths: | ||
150 | """ exit the loop when we encounter first empty string """ | ||
151 | if path == "": | ||
152 | break | ||
153 | |||
154 | new_path = old_prefix.sub(new_prefix, path) | ||
155 | sysdirs += new_path + "\0" | ||
156 | |||
157 | if arch == 32: | ||
158 | sysdirslen += struct.pack("<L", len(new_path)) | ||
159 | else: | ||
160 | sysdirslen += struct.pack("<Q", len(new_path)) | ||
161 | |||
162 | """ pad with zeros """ | ||
163 | sysdirs += "\0" * (sysdirs_sect_size - len(sysdirs)) | ||
164 | |||
165 | """ write the sections back """ | ||
166 | f.seek(sysdirs_off) | ||
167 | f.write(sysdirs) | ||
168 | f.seek(sysdirslen_off) | ||
169 | f.write(sysdirslen) | ||
170 | |||
171 | |||
172 | # MAIN | ||
173 | if len(sys.argv) < 4: | ||
174 | exit(1) | ||
175 | |||
176 | new_prefix = sys.argv[1] | ||
177 | new_dl_path = sys.argv[2] | ||
178 | executables_list = sys.argv[3:] | ||
179 | |||
180 | for e in executables_list: | ||
181 | perms = os.stat(e)[stat.ST_MODE] | ||
182 | if os.access(e, os.W_OK|os.R_OK): | ||
183 | perms = None | ||
184 | else: | ||
185 | os.chmod(e, perms|stat.S_IRWXU) | ||
186 | |||
187 | f = open(e, "r+b") | ||
188 | |||
189 | arch = get_arch() | ||
190 | if arch: | ||
191 | parse_elf_header() | ||
192 | change_interpreter() | ||
193 | change_dl_sysdirs() | ||
194 | |||
195 | """ change permissions back """ | ||
196 | if perms: | ||
197 | os.chmod(e, perms) | ||
198 | |||
199 | f.close() | ||
200 | |||