1*9a741119SAndroid Build Coastguard Worker# 2*9a741119SAndroid Build Coastguard Worker# Copyright (C) 2017 The Android Open Source Project 3*9a741119SAndroid Build Coastguard Worker# 4*9a741119SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 5*9a741119SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 6*9a741119SAndroid Build Coastguard Worker# You may obtain a copy of the License at 7*9a741119SAndroid Build Coastguard Worker# 8*9a741119SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 9*9a741119SAndroid Build Coastguard Worker# 10*9a741119SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 11*9a741119SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 12*9a741119SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*9a741119SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 14*9a741119SAndroid Build Coastguard Worker# limitations under the License. 15*9a741119SAndroid Build Coastguard Worker# 16*9a741119SAndroid Build Coastguard Workerr"""This file contains an ELF parser and ELF header structures. 17*9a741119SAndroid Build Coastguard Worker 18*9a741119SAndroid Build Coastguard WorkerExample usage: 19*9a741119SAndroid Build Coastguard Worker import elf_parser 20*9a741119SAndroid Build Coastguard Worker with elf_parser.ElfParser(file) as e: 21*9a741119SAndroid Build Coastguard Worker print('\n'.join(e.ListGlobalDynamicSymbols())) 22*9a741119SAndroid Build Coastguard Worker print('\n'.join(e.ListDependencies()[0])) 23*9a741119SAndroid Build Coastguard Worker""" 24*9a741119SAndroid Build Coastguard Worker 25*9a741119SAndroid Build Coastguard Workerimport ctypes 26*9a741119SAndroid Build Coastguard Workerimport os 27*9a741119SAndroid Build Coastguard Workerimport struct 28*9a741119SAndroid Build Coastguard Worker 29*9a741119SAndroid Build Coastguard Workerfrom vts.utils.python.library.elf import consts 30*9a741119SAndroid Build Coastguard Workerfrom vts.utils.python.library.elf import structs 31*9a741119SAndroid Build Coastguard Workerfrom vts.utils.python.library.elf import utils 32*9a741119SAndroid Build Coastguard Worker 33*9a741119SAndroid Build Coastguard Worker 34*9a741119SAndroid Build Coastguard Workerclass ElfError(Exception): 35*9a741119SAndroid Build Coastguard Worker """The exception raised by ElfParser.""" 36*9a741119SAndroid Build Coastguard Worker pass 37*9a741119SAndroid Build Coastguard Worker 38*9a741119SAndroid Build Coastguard Worker 39*9a741119SAndroid Build Coastguard Workerclass ElfParser(object): 40*9a741119SAndroid Build Coastguard Worker """The class reads information from an ELF file. 41*9a741119SAndroid Build Coastguard Worker 42*9a741119SAndroid Build Coastguard Worker Attributes: 43*9a741119SAndroid Build Coastguard Worker _file: The ELF file object. 44*9a741119SAndroid Build Coastguard Worker _begin_offset: The offset of the ELF object in the file. The value is 45*9a741119SAndroid Build Coastguard Worker non-zero if the ELF is in an archive, such as .a file. 46*9a741119SAndroid Build Coastguard Worker _file_size: Size of the file. 47*9a741119SAndroid Build Coastguard Worker bitness: Bitness of the ELF. 48*9a741119SAndroid Build Coastguard Worker Ehdr: An Elf_Endr, the ELF header structure of the file. 49*9a741119SAndroid Build Coastguard Worker Shdr: A list of Elf_Shdr, the section headers of the file. 50*9a741119SAndroid Build Coastguard Worker Elf_Addr: ELF unsigned program address type. 51*9a741119SAndroid Build Coastguard Worker Elf_Off: ELF unsigned file offset type. 52*9a741119SAndroid Build Coastguard Worker Elf_Half: ELF unsigned medium integer type. 53*9a741119SAndroid Build Coastguard Worker Elf_Word: ELF unsigned integer type. 54*9a741119SAndroid Build Coastguard Worker Elf_Sword: ELF signed integer type. 55*9a741119SAndroid Build Coastguard Worker Elf_Ehdr: ELF header class. 56*9a741119SAndroid Build Coastguard Worker Elf_Shdr: ELF section header class. 57*9a741119SAndroid Build Coastguard Worker Elf_Dyn: ELF dynamic entry class. 58*9a741119SAndroid Build Coastguard Worker Elf_Sym: ELF symbol entry class. 59*9a741119SAndroid Build Coastguard Worker Elf_Rel: ELF relocation entry class. 60*9a741119SAndroid Build Coastguard Worker Elf_Rela: ELF relocation entry class with explicit addend. 61*9a741119SAndroid Build Coastguard Worker Elf_Phdr: ELF program header class. 62*9a741119SAndroid Build Coastguard Worker Elf_Nhdr: ELF note header class. 63*9a741119SAndroid Build Coastguard Worker """ 64*9a741119SAndroid Build Coastguard Worker 65*9a741119SAndroid Build Coastguard Worker def __init__(self, file_path, begin_offset=0): 66*9a741119SAndroid Build Coastguard Worker """Creates a parser to open and read an ELF file. 67*9a741119SAndroid Build Coastguard Worker 68*9a741119SAndroid Build Coastguard Worker Args: 69*9a741119SAndroid Build Coastguard Worker file_path: The path to the file. 70*9a741119SAndroid Build Coastguard Worker begin_offset: The offset of the ELF object in the file. 71*9a741119SAndroid Build Coastguard Worker 72*9a741119SAndroid Build Coastguard Worker Raises: 73*9a741119SAndroid Build Coastguard Worker ElfError: File is not a valid ELF. 74*9a741119SAndroid Build Coastguard Worker """ 75*9a741119SAndroid Build Coastguard Worker self._begin_offset = begin_offset 76*9a741119SAndroid Build Coastguard Worker try: 77*9a741119SAndroid Build Coastguard Worker self._file = open(file_path, 'rb') 78*9a741119SAndroid Build Coastguard Worker except IOError as e: 79*9a741119SAndroid Build Coastguard Worker raise ElfError(e) 80*9a741119SAndroid Build Coastguard Worker try: 81*9a741119SAndroid Build Coastguard Worker self._file_size = os.fstat(self._file.fileno()).st_size 82*9a741119SAndroid Build Coastguard Worker except OSError as e: 83*9a741119SAndroid Build Coastguard Worker self.Close() 84*9a741119SAndroid Build Coastguard Worker raise ElfError(e) 85*9a741119SAndroid Build Coastguard Worker 86*9a741119SAndroid Build Coastguard Worker try: 87*9a741119SAndroid Build Coastguard Worker e_ident = self._SeekRead(0, consts.EI_NIDENT) 88*9a741119SAndroid Build Coastguard Worker 89*9a741119SAndroid Build Coastguard Worker if e_ident[:4] != consts.ELF_MAGIC_NUMBER: 90*9a741119SAndroid Build Coastguard Worker raise ElfError('Unexpected magic bytes: {}'.format(e_ident[:4])) 91*9a741119SAndroid Build Coastguard Worker 92*9a741119SAndroid Build Coastguard Worker if utils.ByteToInt(e_ident[consts.EI_CLASS]) not in ( 93*9a741119SAndroid Build Coastguard Worker consts.ELFCLASS32, consts.ELFCLASS64): 94*9a741119SAndroid Build Coastguard Worker raise ElfError('Unexpected file class: {}' 95*9a741119SAndroid Build Coastguard Worker .format(e_ident[consts.EI_CLASS])) 96*9a741119SAndroid Build Coastguard Worker 97*9a741119SAndroid Build Coastguard Worker if utils.ByteToInt(e_ident[consts.EI_DATA]) != consts.ELFDATA2LSB: 98*9a741119SAndroid Build Coastguard Worker raise ElfError('Unexpected data encoding: {}' 99*9a741119SAndroid Build Coastguard Worker .format(e_ident[consts.EI_DATA])) 100*9a741119SAndroid Build Coastguard Worker except ElfError: 101*9a741119SAndroid Build Coastguard Worker self.Close() 102*9a741119SAndroid Build Coastguard Worker raise 103*9a741119SAndroid Build Coastguard Worker 104*9a741119SAndroid Build Coastguard Worker if utils.ByteToInt(e_ident[consts.EI_CLASS]) == consts.ELFCLASS32: 105*9a741119SAndroid Build Coastguard Worker self.bitness = 32 106*9a741119SAndroid Build Coastguard Worker self.Elf_Addr = structs.Elf32_Addr 107*9a741119SAndroid Build Coastguard Worker self.Elf_Off = structs.Elf32_Off 108*9a741119SAndroid Build Coastguard Worker self.Elf_Half = structs.Elf32_Half 109*9a741119SAndroid Build Coastguard Worker self.Elf_Word = structs.Elf32_Word 110*9a741119SAndroid Build Coastguard Worker self.Elf_Sword = structs.Elf32_Sword 111*9a741119SAndroid Build Coastguard Worker self.Elf_Ehdr = structs.Elf32_Ehdr 112*9a741119SAndroid Build Coastguard Worker self.Elf_Shdr = structs.Elf32_Shdr 113*9a741119SAndroid Build Coastguard Worker self.Elf_Dyn = structs.Elf32_Dyn 114*9a741119SAndroid Build Coastguard Worker self.Elf_Sym = structs.Elf32_Sym 115*9a741119SAndroid Build Coastguard Worker self.Elf_Rel = structs.Elf32_Rel 116*9a741119SAndroid Build Coastguard Worker self.Elf_Rela = structs.Elf32_Rela 117*9a741119SAndroid Build Coastguard Worker self.Elf_Phdr = structs.Elf32_Phdr 118*9a741119SAndroid Build Coastguard Worker self.Elf_Nhdr = structs.Elf32_Nhdr 119*9a741119SAndroid Build Coastguard Worker else: 120*9a741119SAndroid Build Coastguard Worker self.bitness = 64 121*9a741119SAndroid Build Coastguard Worker self.Elf_Addr = structs.Elf64_Addr 122*9a741119SAndroid Build Coastguard Worker self.Elf_Off = structs.Elf64_Off 123*9a741119SAndroid Build Coastguard Worker self.Elf_Half = structs.Elf64_Half 124*9a741119SAndroid Build Coastguard Worker self.Elf_Word = structs.Elf64_Word 125*9a741119SAndroid Build Coastguard Worker self.Elf_Sword = structs.Elf64_Sword 126*9a741119SAndroid Build Coastguard Worker self.Elf_Ehdr = structs.Elf64_Ehdr 127*9a741119SAndroid Build Coastguard Worker self.Elf_Shdr = structs.Elf64_Shdr 128*9a741119SAndroid Build Coastguard Worker self.Elf_Dyn = structs.Elf64_Dyn 129*9a741119SAndroid Build Coastguard Worker self.Elf_Sym = structs.Elf64_Sym 130*9a741119SAndroid Build Coastguard Worker self.Elf_Rel = structs.Elf64_Rel 131*9a741119SAndroid Build Coastguard Worker self.Elf_Rela = structs.Elf64_Rela 132*9a741119SAndroid Build Coastguard Worker self.Elf_Phdr = structs.Elf64_Phdr 133*9a741119SAndroid Build Coastguard Worker self.Elf_Nhdr = structs.Elf64_Nhdr 134*9a741119SAndroid Build Coastguard Worker 135*9a741119SAndroid Build Coastguard Worker try: 136*9a741119SAndroid Build Coastguard Worker self.Ehdr = self._SeekReadStruct(0, self.Elf_Ehdr) 137*9a741119SAndroid Build Coastguard Worker shoff = self.Ehdr.e_shoff 138*9a741119SAndroid Build Coastguard Worker shentsize = self.Ehdr.e_shentsize 139*9a741119SAndroid Build Coastguard Worker self.Shdr = [self._SeekReadStruct(shoff + i * shentsize, 140*9a741119SAndroid Build Coastguard Worker self.Elf_Shdr) 141*9a741119SAndroid Build Coastguard Worker for i in range(self.Ehdr.e_shnum)] 142*9a741119SAndroid Build Coastguard Worker except ElfError: 143*9a741119SAndroid Build Coastguard Worker self.Close() 144*9a741119SAndroid Build Coastguard Worker raise 145*9a741119SAndroid Build Coastguard Worker 146*9a741119SAndroid Build Coastguard Worker def __del__(self): 147*9a741119SAndroid Build Coastguard Worker """Closes the ELF file.""" 148*9a741119SAndroid Build Coastguard Worker self.Close() 149*9a741119SAndroid Build Coastguard Worker 150*9a741119SAndroid Build Coastguard Worker def __enter__(self): 151*9a741119SAndroid Build Coastguard Worker return self 152*9a741119SAndroid Build Coastguard Worker 153*9a741119SAndroid Build Coastguard Worker def __exit__(self, exc_type, exc_value, traceback): 154*9a741119SAndroid Build Coastguard Worker """Closes the ELF file.""" 155*9a741119SAndroid Build Coastguard Worker self.Close() 156*9a741119SAndroid Build Coastguard Worker 157*9a741119SAndroid Build Coastguard Worker def Close(self): 158*9a741119SAndroid Build Coastguard Worker """Closes the ELF file.""" 159*9a741119SAndroid Build Coastguard Worker if hasattr(self, "_file"): 160*9a741119SAndroid Build Coastguard Worker self._file.close() 161*9a741119SAndroid Build Coastguard Worker 162*9a741119SAndroid Build Coastguard Worker def _SeekRead(self, offset, read_size): 163*9a741119SAndroid Build Coastguard Worker """Reads a byte string at specific offset in the file. 164*9a741119SAndroid Build Coastguard Worker 165*9a741119SAndroid Build Coastguard Worker Args: 166*9a741119SAndroid Build Coastguard Worker offset: An integer, the offset from the beginning of the ELF. 167*9a741119SAndroid Build Coastguard Worker read_size: An integer, number of bytes to read. 168*9a741119SAndroid Build Coastguard Worker 169*9a741119SAndroid Build Coastguard Worker Returns: 170*9a741119SAndroid Build Coastguard Worker A bytes object which is the file content. 171*9a741119SAndroid Build Coastguard Worker 172*9a741119SAndroid Build Coastguard Worker Raises: 173*9a741119SAndroid Build Coastguard Worker ElfError: Fails to seek and read. 174*9a741119SAndroid Build Coastguard Worker """ 175*9a741119SAndroid Build Coastguard Worker if offset + read_size > self._file_size: 176*9a741119SAndroid Build Coastguard Worker raise ElfError("Read beyond end of file.") 177*9a741119SAndroid Build Coastguard Worker try: 178*9a741119SAndroid Build Coastguard Worker self._file.seek(self._begin_offset + offset) 179*9a741119SAndroid Build Coastguard Worker return self._file.read(read_size) 180*9a741119SAndroid Build Coastguard Worker except IOError as e: 181*9a741119SAndroid Build Coastguard Worker raise ElfError(e) 182*9a741119SAndroid Build Coastguard Worker 183*9a741119SAndroid Build Coastguard Worker def _SeekRead8(self, offset): 184*9a741119SAndroid Build Coastguard Worker """Reads an 1-byte integer from file.""" 185*9a741119SAndroid Build Coastguard Worker return struct.unpack("B", self._SeekRead(offset, 1))[0] 186*9a741119SAndroid Build Coastguard Worker 187*9a741119SAndroid Build Coastguard Worker def _SeekRead16(self, offset): 188*9a741119SAndroid Build Coastguard Worker """Reads a 2-byte integer from file.""" 189*9a741119SAndroid Build Coastguard Worker return struct.unpack("H", self._SeekRead(offset, 2))[0] 190*9a741119SAndroid Build Coastguard Worker 191*9a741119SAndroid Build Coastguard Worker def _SeekRead32(self, offset): 192*9a741119SAndroid Build Coastguard Worker """Reads a 4-byte integer from file.""" 193*9a741119SAndroid Build Coastguard Worker return struct.unpack("I", self._SeekRead(offset, 4))[0] 194*9a741119SAndroid Build Coastguard Worker 195*9a741119SAndroid Build Coastguard Worker def _SeekRead64(self, offset): 196*9a741119SAndroid Build Coastguard Worker """Reads an 8-byte integer from file.""" 197*9a741119SAndroid Build Coastguard Worker return struct.unpack("Q", self._SeekRead(offset, 8))[0] 198*9a741119SAndroid Build Coastguard Worker 199*9a741119SAndroid Build Coastguard Worker def _SeekReadString(self, offset): 200*9a741119SAndroid Build Coastguard Worker """Reads a null-terminated string starting from specific offset. 201*9a741119SAndroid Build Coastguard Worker 202*9a741119SAndroid Build Coastguard Worker Args: 203*9a741119SAndroid Build Coastguard Worker offset: The offset from the beginning of the ELF object. 204*9a741119SAndroid Build Coastguard Worker 205*9a741119SAndroid Build Coastguard Worker Returns: 206*9a741119SAndroid Build Coastguard Worker A string, excluding the null character. 207*9a741119SAndroid Build Coastguard Worker 208*9a741119SAndroid Build Coastguard Worker Raises: 209*9a741119SAndroid Build Coastguard Worker ElfError: String reaches end of file without null terminator. 210*9a741119SAndroid Build Coastguard Worker """ 211*9a741119SAndroid Build Coastguard Worker ret = b"" 212*9a741119SAndroid Build Coastguard Worker buf_size = 16 213*9a741119SAndroid Build Coastguard Worker self._file.seek(self._begin_offset + offset) 214*9a741119SAndroid Build Coastguard Worker while True: 215*9a741119SAndroid Build Coastguard Worker try: 216*9a741119SAndroid Build Coastguard Worker buf = self._file.read(buf_size) 217*9a741119SAndroid Build Coastguard Worker except IOError as e: 218*9a741119SAndroid Build Coastguard Worker raise ElfError(e) 219*9a741119SAndroid Build Coastguard Worker end_index = buf.find(b"\0") 220*9a741119SAndroid Build Coastguard Worker if end_index < 0: 221*9a741119SAndroid Build Coastguard Worker ret += buf 222*9a741119SAndroid Build Coastguard Worker else: 223*9a741119SAndroid Build Coastguard Worker ret += buf[:end_index] 224*9a741119SAndroid Build Coastguard Worker return utils.BytesToString(ret) 225*9a741119SAndroid Build Coastguard Worker if len(buf) != buf_size: 226*9a741119SAndroid Build Coastguard Worker raise ElfError("Null-terminated string reaches end of file.") 227*9a741119SAndroid Build Coastguard Worker 228*9a741119SAndroid Build Coastguard Worker def _SeekReadStruct(self, offset, struct_type): 229*9a741119SAndroid Build Coastguard Worker """Reads a ctypes.Structure / ctypes.Union from file. 230*9a741119SAndroid Build Coastguard Worker 231*9a741119SAndroid Build Coastguard Worker Args: 232*9a741119SAndroid Build Coastguard Worker offset: An integer, the offset from the beginning of the ELF. 233*9a741119SAndroid Build Coastguard Worker struct_type: A class, the structure type to read. 234*9a741119SAndroid Build Coastguard Worker 235*9a741119SAndroid Build Coastguard Worker Returns: 236*9a741119SAndroid Build Coastguard Worker An object of struct_type. 237*9a741119SAndroid Build Coastguard Worker 238*9a741119SAndroid Build Coastguard Worker Raises: 239*9a741119SAndroid Build Coastguard Worker ElfError: Fails to seek and read. 240*9a741119SAndroid Build Coastguard Worker Fails to create struct_type instance. 241*9a741119SAndroid Build Coastguard Worker """ 242*9a741119SAndroid Build Coastguard Worker raw_bytes = self._SeekRead(offset, ctypes.sizeof(struct_type)) 243*9a741119SAndroid Build Coastguard Worker try: 244*9a741119SAndroid Build Coastguard Worker return struct_type.from_buffer_copy(raw_bytes) 245*9a741119SAndroid Build Coastguard Worker except ValueError as e: 246*9a741119SAndroid Build Coastguard Worker raise ElfError(e) 247*9a741119SAndroid Build Coastguard Worker 248*9a741119SAndroid Build Coastguard Worker def GetString(self, strtab, offset): 249*9a741119SAndroid Build Coastguard Worker """Retrieves a null-terminated string from string table. 250*9a741119SAndroid Build Coastguard Worker 251*9a741119SAndroid Build Coastguard Worker Args: 252*9a741119SAndroid Build Coastguard Worker strtab: Section header of the string table. 253*9a741119SAndroid Build Coastguard Worker offset: Section offset (string index) to start reading from. 254*9a741119SAndroid Build Coastguard Worker 255*9a741119SAndroid Build Coastguard Worker Returns: 256*9a741119SAndroid Build Coastguard Worker A string without the null terminator. 257*9a741119SAndroid Build Coastguard Worker 258*9a741119SAndroid Build Coastguard Worker Raises: 259*9a741119SAndroid Build Coastguard Worker ElfError: Fails to seek and read. 260*9a741119SAndroid Build Coastguard Worker """ 261*9a741119SAndroid Build Coastguard Worker return self._SeekReadString(strtab.sh_offset + offset) 262*9a741119SAndroid Build Coastguard Worker 263*9a741119SAndroid Build Coastguard Worker def GetSectionName(self, sh): 264*9a741119SAndroid Build Coastguard Worker """Returns a section name. 265*9a741119SAndroid Build Coastguard Worker 266*9a741119SAndroid Build Coastguard Worker Args: 267*9a741119SAndroid Build Coastguard Worker sh: A section header. 268*9a741119SAndroid Build Coastguard Worker 269*9a741119SAndroid Build Coastguard Worker Returns: 270*9a741119SAndroid Build Coastguard Worker A String. 271*9a741119SAndroid Build Coastguard Worker 272*9a741119SAndroid Build Coastguard Worker Raises: 273*9a741119SAndroid Build Coastguard Worker ElfError: Fails to seek and read. 274*9a741119SAndroid Build Coastguard Worker """ 275*9a741119SAndroid Build Coastguard Worker strtab = self.Shdr[self.Ehdr.e_shstrndx] 276*9a741119SAndroid Build Coastguard Worker return self.GetString(strtab, sh.sh_name) 277*9a741119SAndroid Build Coastguard Worker 278*9a741119SAndroid Build Coastguard Worker def GetSectionsByName(self, name): 279*9a741119SAndroid Build Coastguard Worker """Returns a generator of section headers from a given name. 280*9a741119SAndroid Build Coastguard Worker 281*9a741119SAndroid Build Coastguard Worker If multiple sections have the same name, yield them all. 282*9a741119SAndroid Build Coastguard Worker 283*9a741119SAndroid Build Coastguard Worker Args: 284*9a741119SAndroid Build Coastguard Worker name: The section name to search for. 285*9a741119SAndroid Build Coastguard Worker 286*9a741119SAndroid Build Coastguard Worker Returns: 287*9a741119SAndroid Build Coastguard Worker A generator of Elf_Shdr. 288*9a741119SAndroid Build Coastguard Worker 289*9a741119SAndroid Build Coastguard Worker Raises: 290*9a741119SAndroid Build Coastguard Worker ElfError: Fails to seek and read. 291*9a741119SAndroid Build Coastguard Worker """ 292*9a741119SAndroid Build Coastguard Worker return (sh for sh in self.Shdr if name == self.GetSectionName(sh)) 293*9a741119SAndroid Build Coastguard Worker 294*9a741119SAndroid Build Coastguard Worker def GetSectionByName(self, name): 295*9a741119SAndroid Build Coastguard Worker """Returns a section header whose name equals a given name. 296*9a741119SAndroid Build Coastguard Worker 297*9a741119SAndroid Build Coastguard Worker Returns only the first match, assuming the section name is unique. 298*9a741119SAndroid Build Coastguard Worker 299*9a741119SAndroid Build Coastguard Worker Args: 300*9a741119SAndroid Build Coastguard Worker name: The section name to search for. 301*9a741119SAndroid Build Coastguard Worker 302*9a741119SAndroid Build Coastguard Worker Returns: 303*9a741119SAndroid Build Coastguard Worker An Elf_Shdr if found. 304*9a741119SAndroid Build Coastguard Worker None if no sections have the given name. 305*9a741119SAndroid Build Coastguard Worker 306*9a741119SAndroid Build Coastguard Worker Raises: 307*9a741119SAndroid Build Coastguard Worker ElfError: Fails to seek and read. 308*9a741119SAndroid Build Coastguard Worker """ 309*9a741119SAndroid Build Coastguard Worker for sh in self.GetSectionsByName(name): 310*9a741119SAndroid Build Coastguard Worker return sh 311*9a741119SAndroid Build Coastguard Worker return None 312*9a741119SAndroid Build Coastguard Worker 313*9a741119SAndroid Build Coastguard Worker def GetDynamic(self, dynamic): 314*9a741119SAndroid Build Coastguard Worker """Yields the _DYNAMIC array. 315*9a741119SAndroid Build Coastguard Worker 316*9a741119SAndroid Build Coastguard Worker Args: 317*9a741119SAndroid Build Coastguard Worker dynamic: Section header of the dynamic section. 318*9a741119SAndroid Build Coastguard Worker 319*9a741119SAndroid Build Coastguard Worker Yields: 320*9a741119SAndroid Build Coastguard Worker Elf_Dyn. 321*9a741119SAndroid Build Coastguard Worker 322*9a741119SAndroid Build Coastguard Worker Raises: 323*9a741119SAndroid Build Coastguard Worker ElfError: Fails to seek and read. 324*9a741119SAndroid Build Coastguard Worker """ 325*9a741119SAndroid Build Coastguard Worker off = dynamic.sh_offset 326*9a741119SAndroid Build Coastguard Worker num = int(dynamic.sh_size // dynamic.sh_entsize) 327*9a741119SAndroid Build Coastguard Worker for _ in range(num): 328*9a741119SAndroid Build Coastguard Worker dyn = self._SeekReadStruct(off, self.Elf_Dyn) 329*9a741119SAndroid Build Coastguard Worker yield dyn 330*9a741119SAndroid Build Coastguard Worker if dyn.d_tag == consts.DT_NULL: 331*9a741119SAndroid Build Coastguard Worker break 332*9a741119SAndroid Build Coastguard Worker off += dynamic.sh_entsize 333*9a741119SAndroid Build Coastguard Worker 334*9a741119SAndroid Build Coastguard Worker def GetSymbol(self, symtab, idx): 335*9a741119SAndroid Build Coastguard Worker """Retrieves a Elf_Sym entry from symbol table. 336*9a741119SAndroid Build Coastguard Worker 337*9a741119SAndroid Build Coastguard Worker Args: 338*9a741119SAndroid Build Coastguard Worker symtab: A symbol table. 339*9a741119SAndroid Build Coastguard Worker idx: An integer, symbol table index. 340*9a741119SAndroid Build Coastguard Worker 341*9a741119SAndroid Build Coastguard Worker Returns: 342*9a741119SAndroid Build Coastguard Worker An Elf_Sym. 343*9a741119SAndroid Build Coastguard Worker 344*9a741119SAndroid Build Coastguard Worker Raises: 345*9a741119SAndroid Build Coastguard Worker ElfError: Fails to seek and read. 346*9a741119SAndroid Build Coastguard Worker """ 347*9a741119SAndroid Build Coastguard Worker off = symtab.sh_offset + idx * symtab.sh_entsize 348*9a741119SAndroid Build Coastguard Worker return self._SeekReadStruct(off, self.Elf_Sym) 349*9a741119SAndroid Build Coastguard Worker 350*9a741119SAndroid Build Coastguard Worker def GetSymbols(self, symtab): 351*9a741119SAndroid Build Coastguard Worker """Returns a generator of Elf_Sym in symbol table. 352*9a741119SAndroid Build Coastguard Worker 353*9a741119SAndroid Build Coastguard Worker Args: 354*9a741119SAndroid Build Coastguard Worker symtab: A symbol table. 355*9a741119SAndroid Build Coastguard Worker 356*9a741119SAndroid Build Coastguard Worker Returns: 357*9a741119SAndroid Build Coastguard Worker A generator of Elf_Sym. 358*9a741119SAndroid Build Coastguard Worker 359*9a741119SAndroid Build Coastguard Worker Raises: 360*9a741119SAndroid Build Coastguard Worker ElfError: Fails to seek and read. 361*9a741119SAndroid Build Coastguard Worker """ 362*9a741119SAndroid Build Coastguard Worker num = int(symtab.sh_size // symtab.sh_entsize) 363*9a741119SAndroid Build Coastguard Worker return (self.GetSymbol(symtab, i) for i in range(num)) 364*9a741119SAndroid Build Coastguard Worker 365*9a741119SAndroid Build Coastguard Worker def GetRelocationSymbol(self, symtab, rel): 366*9a741119SAndroid Build Coastguard Worker """Retrieves the Elf_Sym with respect to an Elf_Rel / Elf_Rela. 367*9a741119SAndroid Build Coastguard Worker 368*9a741119SAndroid Build Coastguard Worker Args: 369*9a741119SAndroid Build Coastguard Worker symtab: A symbol table. 370*9a741119SAndroid Build Coastguard Worker rel: A Elf_Rel or Elf_Rela. 371*9a741119SAndroid Build Coastguard Worker 372*9a741119SAndroid Build Coastguard Worker Returns: 373*9a741119SAndroid Build Coastguard Worker An Elf_Sym. 374*9a741119SAndroid Build Coastguard Worker 375*9a741119SAndroid Build Coastguard Worker Raises: 376*9a741119SAndroid Build Coastguard Worker ElfError: Fails to seek and read. 377*9a741119SAndroid Build Coastguard Worker """ 378*9a741119SAndroid Build Coastguard Worker return self.GetSymbol(symtab, rel.GetSymbol()) 379*9a741119SAndroid Build Coastguard Worker 380*9a741119SAndroid Build Coastguard Worker def _CreateElfRel(self, offset, info): 381*9a741119SAndroid Build Coastguard Worker """Creates an instance of Elf_Rel. 382*9a741119SAndroid Build Coastguard Worker 383*9a741119SAndroid Build Coastguard Worker Args: 384*9a741119SAndroid Build Coastguard Worker offset: The initial value of r_offset. 385*9a741119SAndroid Build Coastguard Worker info: The initial value of r_info. 386*9a741119SAndroid Build Coastguard Worker 387*9a741119SAndroid Build Coastguard Worker Returns: 388*9a741119SAndroid Build Coastguard Worker An Elf_Rel. 389*9a741119SAndroid Build Coastguard Worker """ 390*9a741119SAndroid Build Coastguard Worker elf_rel = self.Elf_Rel() 391*9a741119SAndroid Build Coastguard Worker elf_rel.r_offset = offset 392*9a741119SAndroid Build Coastguard Worker elf_rel.r_info = info 393*9a741119SAndroid Build Coastguard Worker return elf_rel 394*9a741119SAndroid Build Coastguard Worker 395*9a741119SAndroid Build Coastguard Worker def _DecodeAndroidRelr(self, rel): 396*9a741119SAndroid Build Coastguard Worker """Decodes a SHT_RELR / SHT_ANDROID_RELR section. 397*9a741119SAndroid Build Coastguard Worker 398*9a741119SAndroid Build Coastguard Worker Args: 399*9a741119SAndroid Build Coastguard Worker rel: A relocation table. 400*9a741119SAndroid Build Coastguard Worker 401*9a741119SAndroid Build Coastguard Worker Yields: 402*9a741119SAndroid Build Coastguard Worker Elf_Rel. 403*9a741119SAndroid Build Coastguard Worker 404*9a741119SAndroid Build Coastguard Worker Raises: 405*9a741119SAndroid Build Coastguard Worker ElfError: Fails to seek and read. 406*9a741119SAndroid Build Coastguard Worker """ 407*9a741119SAndroid Build Coastguard Worker if self.bitness == 32: 408*9a741119SAndroid Build Coastguard Worker addr_size = 4 409*9a741119SAndroid Build Coastguard Worker seek_read_entry = self._SeekRead32 410*9a741119SAndroid Build Coastguard Worker else: 411*9a741119SAndroid Build Coastguard Worker addr_size = 8 412*9a741119SAndroid Build Coastguard Worker seek_read_entry = self._SeekRead64 413*9a741119SAndroid Build Coastguard Worker 414*9a741119SAndroid Build Coastguard Worker rel_offset = 0 415*9a741119SAndroid Build Coastguard Worker for ent_offset in range(rel.sh_offset, rel.sh_offset + rel.sh_size, 416*9a741119SAndroid Build Coastguard Worker rel.sh_entsize): 417*9a741119SAndroid Build Coastguard Worker relr_entry = seek_read_entry(ent_offset) 418*9a741119SAndroid Build Coastguard Worker if (relr_entry & 1) == 0: 419*9a741119SAndroid Build Coastguard Worker # The entry is an address. 420*9a741119SAndroid Build Coastguard Worker yield self._CreateElfRel(relr_entry, 0) 421*9a741119SAndroid Build Coastguard Worker rel_offset = relr_entry + addr_size 422*9a741119SAndroid Build Coastguard Worker else: 423*9a741119SAndroid Build Coastguard Worker # The entry is a bitmap. 424*9a741119SAndroid Build Coastguard Worker for bit_idx in range(1, rel.sh_entsize * 8): 425*9a741119SAndroid Build Coastguard Worker if (relr_entry >> bit_idx) & 1: 426*9a741119SAndroid Build Coastguard Worker yield self._CreateElfRel(rel_offset, 0) 427*9a741119SAndroid Build Coastguard Worker rel_offset += addr_size 428*9a741119SAndroid Build Coastguard Worker 429*9a741119SAndroid Build Coastguard Worker def GetRelocation(self, rel, idx): 430*9a741119SAndroid Build Coastguard Worker """Retrieves a Elf_Rel / Elf_Rela entry from relocation table. 431*9a741119SAndroid Build Coastguard Worker 432*9a741119SAndroid Build Coastguard Worker Args: 433*9a741119SAndroid Build Coastguard Worker rel: A relocation table. 434*9a741119SAndroid Build Coastguard Worker idx: An integer, relocation table index. 435*9a741119SAndroid Build Coastguard Worker 436*9a741119SAndroid Build Coastguard Worker Returns: 437*9a741119SAndroid Build Coastguard Worker An Elf_Rel or Elf_Rela. 438*9a741119SAndroid Build Coastguard Worker 439*9a741119SAndroid Build Coastguard Worker Raises: 440*9a741119SAndroid Build Coastguard Worker ElfError: Fails to seek and read. 441*9a741119SAndroid Build Coastguard Worker """ 442*9a741119SAndroid Build Coastguard Worker off = rel.sh_offset + idx * rel.sh_entsize 443*9a741119SAndroid Build Coastguard Worker if rel.sh_type == consts.SHT_RELA: 444*9a741119SAndroid Build Coastguard Worker return self._SeekReadStruct(off, self.Elf_Rela) 445*9a741119SAndroid Build Coastguard Worker return self._SeekReadStruct(off, self.Elf_Rel) 446*9a741119SAndroid Build Coastguard Worker 447*9a741119SAndroid Build Coastguard Worker def GetRelocations(self, rel): 448*9a741119SAndroid Build Coastguard Worker """Returns a generator of Elf_Rel / Elf_Rela in relocation table. 449*9a741119SAndroid Build Coastguard Worker 450*9a741119SAndroid Build Coastguard Worker Args: 451*9a741119SAndroid Build Coastguard Worker rel: A relocation table. 452*9a741119SAndroid Build Coastguard Worker 453*9a741119SAndroid Build Coastguard Worker Returns: 454*9a741119SAndroid Build Coastguard Worker A generator of Elf_Rel or Elf_Rela. 455*9a741119SAndroid Build Coastguard Worker 456*9a741119SAndroid Build Coastguard Worker Raises: 457*9a741119SAndroid Build Coastguard Worker ElfError: Fails to seek and read. 458*9a741119SAndroid Build Coastguard Worker """ 459*9a741119SAndroid Build Coastguard Worker if rel.sh_type in (consts.SHT_ANDROID_REL, consts.SHT_ANDROID_RELA): 460*9a741119SAndroid Build Coastguard Worker relocations = self._UnpackAndroidRela(rel) 461*9a741119SAndroid Build Coastguard Worker if rel.sh_type == consts.SHT_ANDROID_REL: 462*9a741119SAndroid Build Coastguard Worker return (self.Elf_Rel(r_offset=rela.r_offset, r_info=rela.r_info) 463*9a741119SAndroid Build Coastguard Worker for rela in relocations) 464*9a741119SAndroid Build Coastguard Worker return relocations 465*9a741119SAndroid Build Coastguard Worker elif rel.sh_type in (consts.SHT_RELR, consts.SHT_ANDROID_RELR): 466*9a741119SAndroid Build Coastguard Worker return self._DecodeAndroidRelr(rel) 467*9a741119SAndroid Build Coastguard Worker else: 468*9a741119SAndroid Build Coastguard Worker num = int(rel.sh_size // rel.sh_entsize) 469*9a741119SAndroid Build Coastguard Worker return (self.GetRelocation(rel, i) for i in range(num)) 470*9a741119SAndroid Build Coastguard Worker 471*9a741119SAndroid Build Coastguard Worker def _UnpackAndroidRela(self, android_rela): 472*9a741119SAndroid Build Coastguard Worker """Unpacks a SHT_ANDROID_REL / SHT_ANDROID_RELA section. 473*9a741119SAndroid Build Coastguard Worker 474*9a741119SAndroid Build Coastguard Worker Args: 475*9a741119SAndroid Build Coastguard Worker android_rela: The packed section's section header. 476*9a741119SAndroid Build Coastguard Worker 477*9a741119SAndroid Build Coastguard Worker Yields: 478*9a741119SAndroid Build Coastguard Worker Elf_Rela. 479*9a741119SAndroid Build Coastguard Worker 480*9a741119SAndroid Build Coastguard Worker Raises: 481*9a741119SAndroid Build Coastguard Worker ElfError: Fails to decode android rela section. 482*9a741119SAndroid Build Coastguard Worker """ 483*9a741119SAndroid Build Coastguard Worker data = self._SeekRead(android_rela.sh_offset, android_rela.sh_size) 484*9a741119SAndroid Build Coastguard Worker # Check packed section header. 485*9a741119SAndroid Build Coastguard Worker if len(data) < 4 or data[:4] != b'APS2': 486*9a741119SAndroid Build Coastguard Worker raise ElfError('Unexpected SHT_ANDROID_RELA header: {}' 487*9a741119SAndroid Build Coastguard Worker .format(data[:4])) 488*9a741119SAndroid Build Coastguard Worker # Decode SLEB128 word stream. 489*9a741119SAndroid Build Coastguard Worker def _PackedWordsGen(): 490*9a741119SAndroid Build Coastguard Worker cur = 4 491*9a741119SAndroid Build Coastguard Worker while cur < len(data): 492*9a741119SAndroid Build Coastguard Worker try: 493*9a741119SAndroid Build Coastguard Worker value, num = utils.DecodeSLEB128(data, cur) 494*9a741119SAndroid Build Coastguard Worker except IndexError: 495*9a741119SAndroid Build Coastguard Worker raise ElfError('Decoding pass end of section.') 496*9a741119SAndroid Build Coastguard Worker yield value 497*9a741119SAndroid Build Coastguard Worker cur += num 498*9a741119SAndroid Build Coastguard Worker raise ElfError('Decoding pass end of section.') 499*9a741119SAndroid Build Coastguard Worker 500*9a741119SAndroid Build Coastguard Worker _packed_words_gen = _PackedWordsGen() 501*9a741119SAndroid Build Coastguard Worker _PopWord = lambda: next(_packed_words_gen) 502*9a741119SAndroid Build Coastguard Worker # Decode delta encoded relocation data. 503*9a741119SAndroid Build Coastguard Worker current_count = 0 504*9a741119SAndroid Build Coastguard Worker total_count = _PopWord() 505*9a741119SAndroid Build Coastguard Worker offset = _PopWord() 506*9a741119SAndroid Build Coastguard Worker addend = 0 507*9a741119SAndroid Build Coastguard Worker while current_count < total_count: 508*9a741119SAndroid Build Coastguard Worker # Read relocaiton group info. 509*9a741119SAndroid Build Coastguard Worker group_size = _PopWord() 510*9a741119SAndroid Build Coastguard Worker group_flags = _PopWord() 511*9a741119SAndroid Build Coastguard Worker group_offset_delta = 0 512*9a741119SAndroid Build Coastguard Worker # Read group flag and prepare delta values. 513*9a741119SAndroid Build Coastguard Worker grouped_by_info = ( 514*9a741119SAndroid Build Coastguard Worker group_flags & consts.RELOCATION_GROUPED_BY_INFO_FLAG) 515*9a741119SAndroid Build Coastguard Worker grouped_by_offset_delta = ( 516*9a741119SAndroid Build Coastguard Worker group_flags & consts.RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG) 517*9a741119SAndroid Build Coastguard Worker grouped_by_addend = ( 518*9a741119SAndroid Build Coastguard Worker group_flags & consts.RELOCATION_GROUPED_BY_ADDEND_FLAG) 519*9a741119SAndroid Build Coastguard Worker group_has_addend = ( 520*9a741119SAndroid Build Coastguard Worker group_flags & consts.RELOCATION_GROUP_HAS_ADDEND_FLAG) 521*9a741119SAndroid Build Coastguard Worker if grouped_by_offset_delta: 522*9a741119SAndroid Build Coastguard Worker group_offset_delta = _PopWord() 523*9a741119SAndroid Build Coastguard Worker if grouped_by_info: 524*9a741119SAndroid Build Coastguard Worker info = _PopWord() 525*9a741119SAndroid Build Coastguard Worker if group_has_addend and grouped_by_addend: 526*9a741119SAndroid Build Coastguard Worker addend += _PopWord() 527*9a741119SAndroid Build Coastguard Worker if not group_has_addend: 528*9a741119SAndroid Build Coastguard Worker addend = 0 529*9a741119SAndroid Build Coastguard Worker # Handle each relocation entry in group. 530*9a741119SAndroid Build Coastguard Worker for _ in range(group_size): 531*9a741119SAndroid Build Coastguard Worker if grouped_by_offset_delta: 532*9a741119SAndroid Build Coastguard Worker offset += group_offset_delta 533*9a741119SAndroid Build Coastguard Worker else: 534*9a741119SAndroid Build Coastguard Worker offset += _PopWord() 535*9a741119SAndroid Build Coastguard Worker if not grouped_by_info: 536*9a741119SAndroid Build Coastguard Worker info = _PopWord() 537*9a741119SAndroid Build Coastguard Worker if group_has_addend and not grouped_by_addend: 538*9a741119SAndroid Build Coastguard Worker addend += _PopWord() 539*9a741119SAndroid Build Coastguard Worker 540*9a741119SAndroid Build Coastguard Worker relocation = self.Elf_Rela(r_offset=offset, 541*9a741119SAndroid Build Coastguard Worker r_info=info, 542*9a741119SAndroid Build Coastguard Worker r_addend=addend) 543*9a741119SAndroid Build Coastguard Worker yield relocation 544*9a741119SAndroid Build Coastguard Worker current_count += group_size 545*9a741119SAndroid Build Coastguard Worker 546*9a741119SAndroid Build Coastguard Worker def _LoadDynamicSection(self, dynamic): 547*9a741119SAndroid Build Coastguard Worker """Reads entries from dynamic section. 548*9a741119SAndroid Build Coastguard Worker 549*9a741119SAndroid Build Coastguard Worker Args: 550*9a741119SAndroid Build Coastguard Worker dynamic: Section header of the dynamic section. 551*9a741119SAndroid Build Coastguard Worker 552*9a741119SAndroid Build Coastguard Worker Returns: 553*9a741119SAndroid Build Coastguard Worker A dict of {DT_NEEDED: [libraries names], DT_RUNPATH: [paths]} 554*9a741119SAndroid Build Coastguard Worker where the library names and the paths are strings. 555*9a741119SAndroid Build Coastguard Worker 556*9a741119SAndroid Build Coastguard Worker Raises: 557*9a741119SAndroid Build Coastguard Worker ElfError: Fails to find dynamic string table. 558*9a741119SAndroid Build Coastguard Worker """ 559*9a741119SAndroid Build Coastguard Worker strtab_addr = None 560*9a741119SAndroid Build Coastguard Worker dt_needed_offsets = [] 561*9a741119SAndroid Build Coastguard Worker dt_runpath_offsets = [] 562*9a741119SAndroid Build Coastguard Worker for dyn in self.GetDynamic(dynamic): 563*9a741119SAndroid Build Coastguard Worker if dyn.d_tag == consts.DT_NEEDED: 564*9a741119SAndroid Build Coastguard Worker dt_needed_offsets.append(dyn.d_un.d_val) 565*9a741119SAndroid Build Coastguard Worker elif dyn.d_tag == consts.DT_RUNPATH: 566*9a741119SAndroid Build Coastguard Worker dt_runpath_offsets.append(dyn.d_un.d_val) 567*9a741119SAndroid Build Coastguard Worker elif dyn.d_tag == consts.DT_STRTAB: 568*9a741119SAndroid Build Coastguard Worker strtab_addr = dyn.d_un.d_ptr 569*9a741119SAndroid Build Coastguard Worker 570*9a741119SAndroid Build Coastguard Worker if strtab_addr is None: 571*9a741119SAndroid Build Coastguard Worker raise ElfError("Cannot find string table address in dynamic " 572*9a741119SAndroid Build Coastguard Worker "section.") 573*9a741119SAndroid Build Coastguard Worker try: 574*9a741119SAndroid Build Coastguard Worker strtab = next(sh for sh in self.Shdr if sh.sh_addr == strtab_addr) 575*9a741119SAndroid Build Coastguard Worker except StopIteration: 576*9a741119SAndroid Build Coastguard Worker raise ElfError("Cannot find dynamic string table.") 577*9a741119SAndroid Build Coastguard Worker dt_needed = [self.GetString(strtab, off) for off in dt_needed_offsets] 578*9a741119SAndroid Build Coastguard Worker dt_runpath = [] 579*9a741119SAndroid Build Coastguard Worker for off in dt_runpath_offsets: 580*9a741119SAndroid Build Coastguard Worker dt_runpath.extend(self.GetString(strtab, off).split(":")) 581*9a741119SAndroid Build Coastguard Worker return {consts.DT_NEEDED: dt_needed, consts.DT_RUNPATH: dt_runpath} 582*9a741119SAndroid Build Coastguard Worker 583*9a741119SAndroid Build Coastguard Worker def IsExecutable(self): 584*9a741119SAndroid Build Coastguard Worker """Returns whether the ELF is executable.""" 585*9a741119SAndroid Build Coastguard Worker return self.Ehdr.e_type == consts.ET_EXEC 586*9a741119SAndroid Build Coastguard Worker 587*9a741119SAndroid Build Coastguard Worker def IsSharedObject(self): 588*9a741119SAndroid Build Coastguard Worker """Returns whether the ELF is a shared object.""" 589*9a741119SAndroid Build Coastguard Worker return self.Ehdr.e_type == consts.ET_DYN 590*9a741119SAndroid Build Coastguard Worker 591*9a741119SAndroid Build Coastguard Worker def HasAndroidIdent(self): 592*9a741119SAndroid Build Coastguard Worker """Returns whether the ELF has a .note.android.ident section.""" 593*9a741119SAndroid Build Coastguard Worker for sh in self.GetSectionsByName(".note.android.ident"): 594*9a741119SAndroid Build Coastguard Worker nh = self._SeekReadStruct(sh.sh_offset, self.Elf_Nhdr) 595*9a741119SAndroid Build Coastguard Worker name = self._SeekRead(sh.sh_offset + ctypes.sizeof(self.Elf_Nhdr), 596*9a741119SAndroid Build Coastguard Worker nh.n_namesz) 597*9a741119SAndroid Build Coastguard Worker if name == b"Android\0": 598*9a741119SAndroid Build Coastguard Worker return True 599*9a741119SAndroid Build Coastguard Worker return False 600*9a741119SAndroid Build Coastguard Worker 601*9a741119SAndroid Build Coastguard Worker def MatchCpuAbi(self, abi): 602*9a741119SAndroid Build Coastguard Worker """Returns whether the ELF matches the ABI. 603*9a741119SAndroid Build Coastguard Worker 604*9a741119SAndroid Build Coastguard Worker Args: 605*9a741119SAndroid Build Coastguard Worker abi: A string, the name of the ABI. 606*9a741119SAndroid Build Coastguard Worker 607*9a741119SAndroid Build Coastguard Worker Returns: 608*9a741119SAndroid Build Coastguard Worker A boolean, whether the ELF matches the ABI. 609*9a741119SAndroid Build Coastguard Worker """ 610*9a741119SAndroid Build Coastguard Worker for abi_prefix, machine in (("arm64", consts.EM_AARCH64), 611*9a741119SAndroid Build Coastguard Worker ("arm", consts.EM_ARM), 612*9a741119SAndroid Build Coastguard Worker ("x86_64", consts.EM_X86_64), 613*9a741119SAndroid Build Coastguard Worker ("x86", consts.EM_386)): 614*9a741119SAndroid Build Coastguard Worker if abi.startswith(abi_prefix): 615*9a741119SAndroid Build Coastguard Worker return self.Ehdr.e_machine == machine 616*9a741119SAndroid Build Coastguard Worker return False 617*9a741119SAndroid Build Coastguard Worker 618*9a741119SAndroid Build Coastguard Worker def ListDependencies(self): 619*9a741119SAndroid Build Coastguard Worker """Lists the shared libraries that the ELF depends on. 620*9a741119SAndroid Build Coastguard Worker 621*9a741119SAndroid Build Coastguard Worker Returns: 622*9a741119SAndroid Build Coastguard Worker 2 lists of strings, the names of the depended libraries and the 623*9a741119SAndroid Build Coastguard Worker search paths. 624*9a741119SAndroid Build Coastguard Worker """ 625*9a741119SAndroid Build Coastguard Worker deps = [] 626*9a741119SAndroid Build Coastguard Worker runpaths = [] 627*9a741119SAndroid Build Coastguard Worker for sh in self.Shdr: 628*9a741119SAndroid Build Coastguard Worker if sh.sh_type == consts.SHT_DYNAMIC: 629*9a741119SAndroid Build Coastguard Worker dynamic = self._LoadDynamicSection(sh) 630*9a741119SAndroid Build Coastguard Worker deps.extend(dynamic[consts.DT_NEEDED]) 631*9a741119SAndroid Build Coastguard Worker runpaths.extend(dynamic[consts.DT_RUNPATH]) 632*9a741119SAndroid Build Coastguard Worker return deps, runpaths 633*9a741119SAndroid Build Coastguard Worker 634*9a741119SAndroid Build Coastguard Worker def ListGlobalSymbols(self, include_weak=False, 635*9a741119SAndroid Build Coastguard Worker symtab_name=consts.SYMTAB, 636*9a741119SAndroid Build Coastguard Worker strtab_name=consts.STRTAB): 637*9a741119SAndroid Build Coastguard Worker """Lists the global symbols defined in the ELF. 638*9a741119SAndroid Build Coastguard Worker 639*9a741119SAndroid Build Coastguard Worker Args: 640*9a741119SAndroid Build Coastguard Worker include_weak: A boolean, whether to include weak symbols. 641*9a741119SAndroid Build Coastguard Worker symtab_name: A string, the name of the symbol table. 642*9a741119SAndroid Build Coastguard Worker strtab_name: A string, the name of the string table. 643*9a741119SAndroid Build Coastguard Worker 644*9a741119SAndroid Build Coastguard Worker Returns: 645*9a741119SAndroid Build Coastguard Worker A list of strings, the names of the symbols. 646*9a741119SAndroid Build Coastguard Worker 647*9a741119SAndroid Build Coastguard Worker Raises: 648*9a741119SAndroid Build Coastguard Worker ElfError: Fails to find symbol table. 649*9a741119SAndroid Build Coastguard Worker """ 650*9a741119SAndroid Build Coastguard Worker symtab = self.GetSectionByName(symtab_name) 651*9a741119SAndroid Build Coastguard Worker strtab = self.GetSectionByName(strtab_name) 652*9a741119SAndroid Build Coastguard Worker if not symtab or not strtab or symtab.sh_size == 0: 653*9a741119SAndroid Build Coastguard Worker raise ElfError("Cannot find symbol table.") 654*9a741119SAndroid Build Coastguard Worker 655*9a741119SAndroid Build Coastguard Worker include_bindings = [consts.STB_GLOBAL] 656*9a741119SAndroid Build Coastguard Worker if include_weak: 657*9a741119SAndroid Build Coastguard Worker include_bindings.append(consts.STB_WEAK) 658*9a741119SAndroid Build Coastguard Worker 659*9a741119SAndroid Build Coastguard Worker sym_names = [] 660*9a741119SAndroid Build Coastguard Worker for sym in self.GetSymbols(symtab): 661*9a741119SAndroid Build Coastguard Worker # Global symbols can be defined at most once at link time, 662*9a741119SAndroid Build Coastguard Worker # while weak symbols may have multiple definitions. 663*9a741119SAndroid Build Coastguard Worker if sym.GetType() == consts.STT_NOTYPE: 664*9a741119SAndroid Build Coastguard Worker continue 665*9a741119SAndroid Build Coastguard Worker if sym.GetBinding() not in include_bindings: 666*9a741119SAndroid Build Coastguard Worker continue 667*9a741119SAndroid Build Coastguard Worker if sym.st_shndx == consts.SHN_UNDEF: 668*9a741119SAndroid Build Coastguard Worker continue 669*9a741119SAndroid Build Coastguard Worker sym_names.append(self.GetString(strtab, sym.st_name)) 670*9a741119SAndroid Build Coastguard Worker return sym_names 671*9a741119SAndroid Build Coastguard Worker 672*9a741119SAndroid Build Coastguard Worker def ListGlobalDynamicSymbols(self, include_weak=False): 673*9a741119SAndroid Build Coastguard Worker """Lists the global dynamic symbols defined in the ELF. 674*9a741119SAndroid Build Coastguard Worker 675*9a741119SAndroid Build Coastguard Worker Args: 676*9a741119SAndroid Build Coastguard Worker include_weak: A boolean, whether to include weak symbols. 677*9a741119SAndroid Build Coastguard Worker 678*9a741119SAndroid Build Coastguard Worker Returns: 679*9a741119SAndroid Build Coastguard Worker A list of strings, the names of the symbols. 680*9a741119SAndroid Build Coastguard Worker 681*9a741119SAndroid Build Coastguard Worker Raises: 682*9a741119SAndroid Build Coastguard Worker ElfError: Fails to find symbol table. 683*9a741119SAndroid Build Coastguard Worker """ 684*9a741119SAndroid Build Coastguard Worker return self.ListGlobalSymbols(include_weak, 685*9a741119SAndroid Build Coastguard Worker consts.DYNSYM, consts.DYNSTR) 686*9a741119SAndroid Build Coastguard Worker 687*9a741119SAndroid Build Coastguard Worker def GetProgramInterpreter(self): 688*9a741119SAndroid Build Coastguard Worker """Gets the path to the program interpreter of the ELF. 689*9a741119SAndroid Build Coastguard Worker 690*9a741119SAndroid Build Coastguard Worker Returns: 691*9a741119SAndroid Build Coastguard Worker A string, the contents of .interp section. 692*9a741119SAndroid Build Coastguard Worker None if the section is not found. 693*9a741119SAndroid Build Coastguard Worker """ 694*9a741119SAndroid Build Coastguard Worker for ph_index in range(self.Ehdr.e_phnum): 695*9a741119SAndroid Build Coastguard Worker ph = self._SeekReadStruct( 696*9a741119SAndroid Build Coastguard Worker self.Ehdr.e_phoff + ph_index * self.Ehdr.e_phentsize, 697*9a741119SAndroid Build Coastguard Worker self.Elf_Phdr) 698*9a741119SAndroid Build Coastguard Worker if ph.p_type == consts.PT_INTERP: 699*9a741119SAndroid Build Coastguard Worker return self._SeekReadString(ph.p_offset) 700