diff options
Diffstat (limited to 'scripts/relocate_sdk.py')
| -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 | |||
