| # |
| # Copyright (C) 2018 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| """This file contains ELF C structs and data types.""" |
| |
| import ctypes |
| |
| from vts.utils.python.library.elf import consts |
| |
| |
| # ELF data types. |
| |
| |
| Elf32_Addr = ctypes.c_uint32 |
| Elf32_Off = ctypes.c_uint32 |
| Elf32_Half = ctypes.c_uint16 |
| Elf32_Word = ctypes.c_uint32 |
| Elf32_Sword = ctypes.c_int32 |
| |
| Elf64_Addr = ctypes.c_uint64 |
| Elf64_Off = ctypes.c_uint64 |
| Elf64_Half = ctypes.c_uint16 |
| Elf64_Word = ctypes.c_uint32 |
| Elf64_Sword = ctypes.c_int32 |
| Elf64_Xword = ctypes.c_uint64 |
| Elf64_Sxword = ctypes.c_int64 |
| |
| |
| # ELF C structs. |
| |
| |
| class CStructure(ctypes.LittleEndianStructure): |
| """Little endian C structure base class.""" |
| pass |
| |
| |
| class CUnion(ctypes.Union): |
| """Native endian C union base class.""" |
| pass |
| |
| |
| class _Ehdr(CStructure): |
| """ELF header base class.""" |
| |
| def GetFileClass(self): |
| """Returns the file class.""" |
| return self.e_ident[consts.EI_CLASS] |
| |
| def GetDataEncoding(self): |
| """Returns the data encoding of the file.""" |
| return self.e_ident[consts.EI_DATA] |
| |
| |
| class Elf32_Ehdr(_Ehdr): |
| """ELF 32-bit header.""" |
| _fields_ = [('e_ident', ctypes.c_uint8 * consts.EI_NIDENT), |
| ('e_type', Elf32_Half), |
| ('e_machine', Elf32_Half), |
| ('e_version', Elf32_Word), |
| ('e_entry', Elf32_Addr), |
| ('e_phoff', Elf32_Off), |
| ('e_shoff', Elf32_Off), |
| ('e_flags', Elf32_Word), |
| ('e_ehsize', Elf32_Half), |
| ('e_phentsize', Elf32_Half), |
| ('e_phnum', Elf32_Half), |
| ('e_shentsize', Elf32_Half), |
| ('e_shnum', Elf32_Half), |
| ('e_shstrndx', Elf32_Half)] |
| |
| |
| class Elf64_Ehdr(_Ehdr): |
| """ELF 64-bit header.""" |
| _fields_ = [('e_ident', ctypes.c_uint8 * consts.EI_NIDENT), |
| ('e_type', Elf64_Half), |
| ('e_machine', Elf64_Half), |
| ('e_version', Elf64_Word), |
| ('e_entry', Elf64_Addr), |
| ('e_phoff', Elf64_Off), |
| ('e_shoff', Elf64_Off), |
| ('e_flags', Elf64_Word), |
| ('e_ehsize', Elf64_Half), |
| ('e_phentsize', Elf64_Half), |
| ('e_phnum', Elf64_Half), |
| ('e_shentsize', Elf64_Half), |
| ('e_shnum', Elf64_Half), |
| ('e_shstrndx', Elf64_Half)] |
| |
| |
| class Elf32_Shdr(CStructure): |
| """ELF 32-bit section header.""" |
| _fields_ = [('sh_name', Elf32_Word), |
| ('sh_type', Elf32_Word), |
| ('sh_flags', Elf32_Word), |
| ('sh_addr', Elf32_Addr), |
| ('sh_offset', Elf32_Off), |
| ('sh_size', Elf32_Word), |
| ('sh_link', Elf32_Word), |
| ('sh_info', Elf32_Word), |
| ('sh_addralign', Elf32_Word), |
| ('sh_entsize', Elf32_Word)] |
| |
| |
| class Elf64_Shdr(CStructure): |
| """ELF 64-bit section header.""" |
| _fields_ = [('sh_name', Elf64_Word), |
| ('sh_type', Elf64_Word), |
| ('sh_flags', Elf64_Xword), |
| ('sh_addr', Elf64_Addr), |
| ('sh_offset', Elf64_Off), |
| ('sh_size', Elf64_Xword), |
| ('sh_link', Elf64_Word), |
| ('sh_info', Elf64_Word), |
| ('sh_addralign', Elf64_Xword), |
| ('sh_entsize', Elf64_Xword)] |
| |
| |
| class Elf32_Dyn(CStructure): |
| """ELF 32-bit dynamic section entry.""" |
| class _Elf32_Dyn__d_un(CUnion): |
| _fields_ = [('d_val', Elf32_Word), |
| ('d_ptr', Elf32_Addr)] |
| _fields_ = [('d_tag', Elf32_Sword), |
| ('d_un', _Elf32_Dyn__d_un)] |
| |
| |
| class Elf64_Dyn(CStructure): |
| """ELF 64-bit dynamic section entry.""" |
| class _Elf64_Dyn__d_un(CUnion): |
| _fields_ = [('d_val', Elf64_Xword), |
| ('d_ptr', Elf64_Addr)] |
| _fields_ = [('d_tag', Elf64_Sxword), |
| ('d_un', _Elf64_Dyn__d_un)] |
| |
| |
| class _Sym(CStructure): |
| """ELF symbol table entry base class.""" |
| |
| def GetBinding(self): |
| """Returns the symbol binding.""" |
| return self.st_info >> 4 |
| |
| def GetType(self): |
| """Returns the symbol type.""" |
| return self.st_info & 0xf |
| |
| def SetBinding(self, binding): |
| """Sets the symbol binding. |
| |
| Args: |
| binding: An integer specifying the new binding. |
| """ |
| self.SetSymbolAndType(binding, self.GetType()) |
| |
| def SetType(self, type_): |
| """Sets the symbol type. |
| |
| Args: |
| type_: An integer specifying the new type. |
| """ |
| self.SetSymbolAndType(self.GetBinding(), type_) |
| |
| def SetBindingAndType(self, binding, type_): |
| """Sets the symbol binding and type. |
| |
| Args: |
| binding: An integer specifying the new binding. |
| type_: An integer specifying the new type. |
| """ |
| self.st_info = (binding << 4) | (type_ & 0xf) |
| |
| |
| class Elf32_Sym(_Sym): |
| """ELF 32-bit symbol table entry.""" |
| _fields_ = [('st_name', Elf32_Word), |
| ('st_value', Elf32_Addr), |
| ('st_size', Elf32_Word), |
| ('st_info', ctypes.c_uint8), |
| ('st_other', ctypes.c_uint8), |
| ('st_shndx', Elf32_Half)] |
| |
| |
| class Elf64_Sym(_Sym): |
| """ELF 64-bit symbol table entry.""" |
| _fields_ = [('st_name', Elf64_Word), |
| ('st_info', ctypes.c_uint8), |
| ('st_other', ctypes.c_uint8), |
| ('st_shndx', Elf64_Half), |
| ('st_value', Elf64_Addr), |
| ('st_size', Elf64_Xword)] |
| |
| |
| class _32_Rel(CStructure): |
| """ELF 32-bit relocation table entry base class.""" |
| |
| def GetSymbol(self): |
| """Returns the symbol table index with respect to the relocation. |
| |
| Symbol table index with respect to which the relocation must be made. |
| """ |
| return self.r_info >> 8 |
| |
| def GetType(self): |
| """Returns the relocation type.""" |
| return self.r_info & 0xff |
| |
| def SetSymbol(self, symndx): |
| """Sets the relocation's symbol table index. |
| |
| Args: |
| symndx: An integer specifying the new symbol table index. |
| """ |
| self.SetSymbolAndType(symndx, self.GetType()) |
| |
| def SetType(self, type_): |
| """Sets the relocation type. |
| |
| Args: |
| type_: An integer specifying the new relocation type. |
| """ |
| self.SetSymbolAndType(self.GetSymbol(), type_) |
| |
| def SetSymbolAndType(self, symndx, type_): |
| """Sets the relocation's symbol table index and type. |
| |
| Args: |
| symndx: An integer specifying the new symbol table index. |
| type_: An integer specifying the new relocation type. |
| """ |
| self.r_info = (symndx << 8) | (type_ & 0xff) |
| |
| |
| class Elf32_Rel(_32_Rel): |
| """ELF 32-bit relocation table entry.""" |
| _fields_ = [('r_offset', Elf32_Addr), |
| ('r_info', Elf32_Word)] |
| |
| |
| class Elf32_Rela(_32_Rel): |
| """ELF 32-bit relocation table entry with explicit addend.""" |
| _fields_ = [('r_offset', Elf32_Addr), |
| ('r_info', Elf32_Word), |
| ('r_addend', Elf32_Sword)] |
| |
| |
| class _64_Rel(CStructure): |
| """ELF 64-bit relocation table entry base class.""" |
| |
| def GetSymbol(self): |
| """Returns the symbol table index with respect to the relocation. |
| |
| Symbol table index with respect to which the relocation must be made. |
| """ |
| return self.r_info >> 32 |
| |
| def GetType(self): |
| """Returns the relocation type.""" |
| return self.r_info & 0xffffffff |
| |
| def SetSymbol(self, symndx): |
| """Sets the relocation's symbol table index. |
| |
| Args: |
| symndx: An integer specifying the new symbol table index. |
| """ |
| self.SetSymbolAndType(symndx, self.GetType()) |
| |
| def SetType(self, type_): |
| """Sets the relocation type. |
| |
| Args: |
| type_: An integer specifying the new relocation type. |
| """ |
| self.SetSymbolAndType(self.GetSymbol(), type_) |
| |
| def SetSymbolAndType(self, symndx, type_): |
| """Sets the relocation's symbol table index and type. |
| |
| Args: |
| symndx: An integer specifying the new symbol table index. |
| type_: An integer specifying the new relocation type. |
| """ |
| self.r_info = (symndx << 32) | (type_ & 0xffffffff) |
| |
| |
| class Elf64_Rel(_64_Rel): |
| """ELF 64-bit relocation table entry.""" |
| _fields_ = [('r_offset', Elf64_Addr), |
| ('r_info', Elf64_Xword)] |
| |
| |
| class Elf64_Rela(_64_Rel): |
| """ELF 64-bit relocation table entry with explicit addend.""" |
| _fields_ = [('r_offset', Elf64_Addr), |
| ('r_info', Elf64_Xword), |
| ('r_addend', Elf64_Sxword)] |
| |
| |
| class Elf32_Phdr(CStructure): |
| """ELF 32-bit program header.""" |
| _fields_ = [('p_type', Elf32_Word), |
| ('p_offset', Elf32_Off), |
| ('p_vaddr', Elf32_Addr), |
| ('p_paddr', Elf32_Addr), |
| ('p_filesz', Elf32_Word), |
| ('p_memsz', Elf32_Word), |
| ('p_flags', Elf32_Word), |
| ('p_align', Elf32_Word)] |
| |
| |
| class Elf64_Phdr(CStructure): |
| """ELF 64-bit program header.""" |
| _fields_ = [('p_type', Elf64_Word), |
| ('p_flags', Elf64_Word), |
| ('p_offset', Elf64_Off), |
| ('p_vaddr', Elf64_Addr), |
| ('p_paddr', Elf64_Addr), |
| ('p_filesz', Elf64_Xword), |
| ('p_memsz', Elf64_Xword), |
| ('p_align', Elf64_Xword)] |
| |
| |
| class Elf32_Nhdr(CStructure): |
| """ELF 32-bit note header.""" |
| _fields_ = [('n_namesz', Elf32_Word), |
| ('n_descsz', Elf32_Word), |
| ('n_type', Elf32_Word)] |
| |
| |
| class Elf64_Nhdr(CStructure): |
| """ELF 64-bit note header.""" |
| _fields_ = [('n_namesz', Elf64_Word), |
| ('n_descsz', Elf64_Word), |
| ('n_type', Elf64_Word)] |