mirror of https://github.com/Nonannet/pelfy.git
Compare commits
5 Commits
fd650d3dff
...
1762c8c435
Author | SHA1 | Date |
---|---|---|
|
1762c8c435 | |
|
d4c68c8e42 | |
|
553355cc12 | |
|
675146e744 | |
|
99bd71f9b8 |
|
@ -33,6 +33,8 @@ class elf_symbol():
|
||||||
|
|
||||||
name: Name of the symbol
|
name: Name of the symbol
|
||||||
|
|
||||||
|
section: section where the symbol data is placed
|
||||||
|
|
||||||
index: Absolut index in the symbol table
|
index: Absolut index in the symbol table
|
||||||
|
|
||||||
info: Type of the symbol
|
info: Type of the symbol
|
||||||
|
@ -55,6 +57,8 @@ class elf_symbol():
|
||||||
else:
|
else:
|
||||||
self.name = ''
|
self.name = ''
|
||||||
|
|
||||||
|
self.section: elf_section | None = self.file.sections[self['st_shndx']] if self['st_shndx'] < len(self.file.sections) else None
|
||||||
|
|
||||||
self.index = index
|
self.index = index
|
||||||
|
|
||||||
self.info, self.description = fdat.st_info_values[fields['st_info'] & 0x0F]
|
self.info, self.description = fdat.st_info_values[fields['st_info'] & 0x0F]
|
||||||
|
@ -68,7 +72,11 @@ class elf_symbol():
|
||||||
Returns:
|
Returns:
|
||||||
Symbol data
|
Symbol data
|
||||||
"""
|
"""
|
||||||
offset = self.file.sections[self['st_shndx']]['sh_offset'] + self['st_value']
|
assert self.section, 'This symbol is not associated to a data section'
|
||||||
|
if self.section.type == 'SHT_NOBITS':
|
||||||
|
return b'\x00' * self['st_size']
|
||||||
|
else:
|
||||||
|
offset = self.section['sh_offset'] + self['st_value']
|
||||||
return self.file.read_bytes(offset, self['st_size'])
|
return self.file.read_bytes(offset, self['st_size'])
|
||||||
|
|
||||||
def read_data_hex(self) -> str:
|
def read_data_hex(self) -> str:
|
||||||
|
@ -76,7 +84,7 @@ class elf_symbol():
|
||||||
|
|
||||||
def get_relocations(self) -> 'relocation_list':
|
def get_relocations(self) -> 'relocation_list':
|
||||||
"""List all relocations that are pointing to this symbol.
|
"""List all relocations that are pointing to this symbol.
|
||||||
The symbol must be of type SHT_PROGBITS (program code). Therefore
|
The symbol section must be of type SHT_PROGBITS (program code). Therefore
|
||||||
this function lists typically all relocations that will be
|
this function lists typically all relocations that will be
|
||||||
applied to the function represented by the symbol.
|
applied to the function represented by the symbol.
|
||||||
|
|
||||||
|
@ -84,10 +92,9 @@ class elf_symbol():
|
||||||
List of relocations
|
List of relocations
|
||||||
"""
|
"""
|
||||||
ret: list[elf_relocation] = list()
|
ret: list[elf_relocation] = list()
|
||||||
section = self.file.sections[self.fields['st_shndx']]
|
assert self.section and self.section.type == 'SHT_PROGBITS'
|
||||||
assert section.type == 'SHT_PROGBITS'
|
|
||||||
for reloc in self.file.get_relocations():
|
for reloc in self.file.get_relocations():
|
||||||
if reloc.target_section == section:
|
if reloc.target_section == self.section:
|
||||||
offset = reloc['r_offset'] - self['st_value']
|
offset = reloc['r_offset'] - self['st_value']
|
||||||
if 0 <= offset < self['st_size']:
|
if 0 <= offset < self['st_size']:
|
||||||
ret.append(reloc)
|
ret.append(reloc)
|
||||||
|
@ -105,7 +112,7 @@ class elf_symbol():
|
||||||
f'name {self.name}\n' +\
|
f'name {self.name}\n' +\
|
||||||
f'stb {self.stb} ({self.stb_description})\n' +\
|
f'stb {self.stb} ({self.stb_description})\n' +\
|
||||||
f'info {self.info} ({self.description})\n' +\
|
f'info {self.info} ({self.description})\n' +\
|
||||||
'\n'.join(f'{k:18} {v:4}' for k, v in self.fields.items()) + '\n'
|
'\n'.join(f"{k:18} {v:4} {fdat.symbol_fields[k]}" for k, v in self.fields.items()) + '\n'
|
||||||
|
|
||||||
|
|
||||||
class elf_section():
|
class elf_section():
|
||||||
|
@ -156,8 +163,19 @@ class elf_section():
|
||||||
Returns:
|
Returns:
|
||||||
Data of the section
|
Data of the section
|
||||||
"""
|
"""
|
||||||
|
if self.type == 'SHT_NOBITS':
|
||||||
|
return b'\x00' * self['sh_size']
|
||||||
|
else:
|
||||||
return self.file.read_bytes(self['sh_offset'], self['sh_size'])
|
return self.file.read_bytes(self['sh_offset'], self['sh_size'])
|
||||||
|
|
||||||
|
def get_symbols(self) -> 'symbol_list':
|
||||||
|
"""Lists all ELF symbols associated with this section
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Symbol list
|
||||||
|
"""
|
||||||
|
return symbol_list(self.file._list_symbols(self.index))
|
||||||
|
|
||||||
def get_data_hex(self) -> str:
|
def get_data_hex(self) -> str:
|
||||||
data = self.file.read_bytes(self['sh_offset'], self['sh_size'])
|
data = self.file.read_bytes(self['sh_offset'], self['sh_size'])
|
||||||
return ' '.join(f'{d:02X}' for d in data)
|
return ' '.join(f'{d:02X}' for d in data)
|
||||||
|
@ -320,9 +338,9 @@ class symbol_list(elf_list[elf_symbol]):
|
||||||
"""A class for representing a list of ELF symbols
|
"""A class for representing a list of ELF symbols
|
||||||
"""
|
"""
|
||||||
def _compact_table(self) -> tuple[list[str], list[list[int | str]], list[str]]:
|
def _compact_table(self) -> tuple[list[str], list[list[int | str]], list[str]]:
|
||||||
columns = ['index', 'name', 'info', 'size', 'stb', 'description']
|
columns = ['index', 'name', 'info', 'size', 'stb', 'section', 'description']
|
||||||
data: list[list[str | int]] = [[item.index, item.name, item.info, item.fields['st_size'],
|
data: list[list[str | int]] = [[item.index, item.name, item.info, item.fields['st_size'],
|
||||||
item.stb, item.description] for item in self]
|
item.stb, item.section.name if item.section else '', item.description] for item in self]
|
||||||
return columns, data, ['index', 'size']
|
return columns, data, ['index', 'size']
|
||||||
|
|
||||||
|
|
||||||
|
@ -369,14 +387,15 @@ class elf_file:
|
||||||
string_table_section: The string table section (first section with
|
string_table_section: The string table section (first section with
|
||||||
the name .strtab)
|
the name .strtab)
|
||||||
"""
|
"""
|
||||||
def __init__(self, data: bytes):
|
def __init__(self, data: bytes | bytearray):
|
||||||
|
assert isinstance(data, (bytes, bytearray)), 'Binary ELF data must be provided as bytes or bytearray.'
|
||||||
self._data = data
|
self._data = data
|
||||||
|
|
||||||
# Defaults required for function _read_int_from_elf_field
|
# Defaults required for function _read_int_from_elf_field
|
||||||
self.bit_width = 32
|
self.bit_width = 32
|
||||||
self.byteorder: Literal['little', 'big'] = 'little'
|
self.byteorder: Literal['little', 'big'] = 'little'
|
||||||
|
|
||||||
assert self._read_bytes_from_elf_field('e_ident[EI_MAG]') == bytes([0x7F, 0x45, 0x4c, 0x46]), 'Not an ELF file'
|
assert self._read_bytes_from_elf_field('e_ident[EI_MAG]') == b'\x7fELF', 'Not an ELF file'
|
||||||
|
|
||||||
self.bit_width = {1: 32, 2: 64}[self._read_int_from_elf_field('e_ident[EI_CLASS]')]
|
self.bit_width = {1: 32, 2: 64}[self._read_int_from_elf_field('e_ident[EI_CLASS]')]
|
||||||
|
|
||||||
|
@ -414,7 +433,7 @@ class elf_file:
|
||||||
offs = self.fields['e_shoff'] + i * self.fields['e_shentsize']
|
offs = self.fields['e_shoff'] + i * self.fields['e_shentsize']
|
||||||
yield {fn: self._read_from_sh_field(offs, fn) for fn in fdat.section_header.keys()}
|
yield {fn: self._read_from_sh_field(offs, fn) for fn in fdat.section_header.keys()}
|
||||||
|
|
||||||
def _list_symbols(self) -> Generator[elf_symbol, None, None]:
|
def _list_symbols(self, section_index: int | None = None) -> Generator[elf_symbol, None, None]:
|
||||||
if self.symbol_table_section:
|
if self.symbol_table_section:
|
||||||
offs = self.symbol_table_section['sh_offset']
|
offs = self.symbol_table_section['sh_offset']
|
||||||
|
|
||||||
|
@ -434,6 +453,7 @@ class elf_file:
|
||||||
ret['st_value'] = self.read_int(i + 8, 8)
|
ret['st_value'] = self.read_int(i + 8, 8)
|
||||||
ret['st_size'] = self.read_int(i + 16, 8)
|
ret['st_size'] = self.read_int(i + 16, 8)
|
||||||
|
|
||||||
|
if section_index is None or section_index == ret['st_shndx']:
|
||||||
yield elf_symbol(self, ret, j)
|
yield elf_symbol(self, ret, j)
|
||||||
|
|
||||||
def get_relocations(self, reloc_section: elf_section | str | list[str] | None = None) -> relocation_list:
|
def get_relocations(self, reloc_section: elf_section | str | list[str] | None = None) -> relocation_list:
|
||||||
|
|
|
@ -271,7 +271,7 @@ section_header = {
|
||||||
},
|
},
|
||||||
"sh_size": {
|
"sh_size": {
|
||||||
"32": "0x14", "64": "0x20", "size32": "4", "size64": "8", "field_name": "sh_size",
|
"32": "0x14", "64": "0x20", "size32": "4", "size64": "8", "field_name": "sh_size",
|
||||||
"description": "Size in bytes of the section in the file image. May be 0."
|
"description": "Size in bytes of the section in memory or 0. May be equal to size in file."
|
||||||
},
|
},
|
||||||
"sh_link": {
|
"sh_link": {
|
||||||
"32": "0x18", "64": "0x28", "size32": "4", "size64": "4", "field_name": "sh_link",
|
"32": "0x18", "64": "0x28", "size32": "4", "size64": "4", "field_name": "sh_link",
|
||||||
|
@ -316,16 +316,25 @@ section_header_types_ex = {0x60000000: 'OS-specific',
|
||||||
0x70000000: 'Processor-specific',
|
0x70000000: 'Processor-specific',
|
||||||
0x80000000: 'Application-specific'}
|
0x80000000: 'Application-specific'}
|
||||||
|
|
||||||
|
symbol_fields = {
|
||||||
|
"st_name": "Index into the string table for the symbol's name",
|
||||||
|
"st_info": "Encodes the symbol's type and its binding attribute",
|
||||||
|
"st_other": "Defines symbol visibility within and outside the object file",
|
||||||
|
"st_shndx": "Specifies which section this symbol is associated with",
|
||||||
|
"st_value": "Holds the symbol's address or offset, depending on context",
|
||||||
|
"st_size": "Specifies the size of the symbol (e.g., function length or variable size)"
|
||||||
|
}
|
||||||
|
|
||||||
st_info_values = {
|
st_info_values = {
|
||||||
0: ("STT_NOTYPE", "Symbol type is unspecified"),
|
0: ("STT_NOTYPE", "Type is unspecified"),
|
||||||
1: ("STT_OBJECT", "Symbol is a data object"),
|
1: ("STT_OBJECT", "Data object"),
|
||||||
2: ("STT_FUNC", "Symbol is a code object"),
|
2: ("STT_FUNC", "Code object"),
|
||||||
3: ("STT_SECTION", "Symbol associated with a section"),
|
3: ("STT_SECTION", "Section associated"),
|
||||||
4: ("STT_FILE", "Symbol's name is file name"),
|
4: ("STT_FILE", "File name"),
|
||||||
5: ("STT_COMMON", "Symbol is a common data object"),
|
5: ("STT_COMMON", "Common data object"),
|
||||||
6: ("STT_TLS", "Symbol is thread-local data object"),
|
6: ("STT_TLS", "Thread-local data object"),
|
||||||
7: ("STT_NUM", "Number of defined types"),
|
7: ("STT_NUM", "Number of defined types"),
|
||||||
10: ("STT_GNU_IFUNC", "Symbol is indirect code object")
|
10: ("STT_GNU_IFUNC", "Indirect code object")
|
||||||
}
|
}
|
||||||
|
|
||||||
stb_values = {
|
stb_values = {
|
||||||
|
|
Loading…
Reference in New Issue