mirror of https://github.com/Nonannet/pelfy.git
flake8 suggestions applied
This commit is contained in:
parent
f68167c386
commit
482957a6f9
|
@ -0,0 +1,20 @@
|
||||||
|
[flake8]
|
||||||
|
# Specify the maximum allowed line length
|
||||||
|
max-line-length = 88
|
||||||
|
|
||||||
|
# Ignore specific rules
|
||||||
|
# For example, E501: Line too long, W503: Line break before binary operator
|
||||||
|
ignore = E501, W503, W504
|
||||||
|
|
||||||
|
# Exclude specific files or directories
|
||||||
|
exclude =
|
||||||
|
.git,
|
||||||
|
__pycache__,
|
||||||
|
build,
|
||||||
|
dist,
|
||||||
|
.conda
|
||||||
|
.venv
|
||||||
|
|
||||||
|
# Enable specific plugins or options
|
||||||
|
# Example: Enabling flake8-docstrings
|
||||||
|
select = C,E,F,W,D
|
|
@ -1,11 +1,14 @@
|
||||||
from . import fields_data as fdat
|
from . import fields_data as fdat
|
||||||
from . import format_output as fout
|
from . import output_formatter
|
||||||
from typing import TypeVar, Literal, Iterable, Generic
|
from typing import TypeVar, Literal, Iterable, Generic
|
||||||
|
|
||||||
T = TypeVar('T')
|
_T = TypeVar('_T')
|
||||||
|
|
||||||
|
|
||||||
def open_elf_file(file_path: str):
|
def open_elf_file(file_path: str):
|
||||||
return elf_file(file_path)
|
with open(file_path, mode='rb') as f:
|
||||||
|
return elf_file(f.read())
|
||||||
|
|
||||||
|
|
||||||
class elf_symbol():
|
class elf_symbol():
|
||||||
def __init__(self, file: 'elf_file', fields: dict[str, int], index: int):
|
def __init__(self, file: 'elf_file', fields: dict[str, int], index: int):
|
||||||
|
@ -63,16 +66,14 @@ class elf_section():
|
||||||
self.file = file
|
self.file = file
|
||||||
self.index = index
|
self.index = index
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.data = self.file.read_bytes(self['sh_offset'], self['sh_size'])
|
||||||
|
|
||||||
assert fields['sh_type'] in fdat.section_header_types, f"Unknown section type: {hex(fields['sh_type'])}"
|
assert fields['sh_type'] in fdat.section_header_types, f"Unknown section type: {hex(fields['sh_type'])}"
|
||||||
self.description = fdat.section_header_types[fields['sh_type']]['description']
|
self.description = fdat.section_header_types[fields['sh_type']]['description']
|
||||||
self.type = fdat.section_header_types[fields['sh_type']]['name']
|
self.type = fdat.section_header_types[fields['sh_type']]['name']
|
||||||
|
|
||||||
def read_data(self):
|
def get_data_hex(self):
|
||||||
return self.file.read_bytes(self['sh_offset'], self['sh_size'])
|
return ' '.join(f'{d:02X}' for d in self.data)
|
||||||
|
|
||||||
def read_data_hex(self):
|
|
||||||
return ' '.join(f'{d:02X}' for d in self.read_data())
|
|
||||||
|
|
||||||
def __getitem__(self, key: str):
|
def __getitem__(self, key: str):
|
||||||
assert key in self.fields, f'Unknown field name: {key}'
|
assert key in self.fields, f'Unknown field name: {key}'
|
||||||
|
@ -104,8 +105,8 @@ class elf_relocation():
|
||||||
'\n'.join(f'{k:18} {v:4}' for k, v in self.fields.items()) + '\n'
|
'\n'.join(f'{k:18} {v:4}' for k, v in self.fields.items()) + '\n'
|
||||||
|
|
||||||
|
|
||||||
class elf_list(Generic[T]):
|
class elf_list(Generic[_T]):
|
||||||
def __init__(self, data: Iterable[T]):
|
def __init__(self, data: Iterable[_T]):
|
||||||
self._data = list(data)
|
self._data = list(data)
|
||||||
|
|
||||||
def __getitem__(self, key: int | str):
|
def __getitem__(self, key: int | str):
|
||||||
|
@ -113,13 +114,10 @@ class elf_list(Generic[T]):
|
||||||
elements = [el for el in self._data if getattr(el, 'name', '') == key]
|
elements = [el for el in self._data if getattr(el, 'name', '') == key]
|
||||||
assert elements, f'Unknown name: {key}'
|
assert elements, f'Unknown name: {key}'
|
||||||
return elements[0]
|
return elements[0]
|
||||||
#elif isinstance(key, slice):
|
|
||||||
# return elf_list(self._data.__getitem__(key))
|
|
||||||
else:
|
else:
|
||||||
return self._data.__getitem__(key)
|
return self._data.__getitem__(key)
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
"""Return an iterator for the list."""
|
|
||||||
return iter(self._data)
|
return iter(self._data)
|
||||||
|
|
||||||
def _repr_table(self, format: Literal['text', 'markdown', 'html']) -> str:
|
def _repr_table(self, format: Literal['text', 'markdown', 'html']) -> str:
|
||||||
|
@ -142,34 +140,33 @@ class section_list(elf_list[elf_section]):
|
||||||
|
|
||||||
def _repr_table(self, format: Literal['text', 'markdown', 'html']):
|
def _repr_table(self, format: Literal['text', 'markdown', 'html']):
|
||||||
columns = ['index', 'name', 'type', 'description']
|
columns = ['index', 'name', 'type', 'description']
|
||||||
data: list[list[str|int]] = [[item.index, item.name, item.type,
|
data: list[list[str | int]] = [[item.index, item.name, item.type,
|
||||||
item.description] for item in self]
|
item.description] for item in self]
|
||||||
return fout.generate_table(data, columns, ['index'], format)
|
return output_formatter.generate_table(data, columns, ['index'], format)
|
||||||
|
|
||||||
|
|
||||||
class symbol_list(elf_list[elf_symbol]):
|
class symbol_list(elf_list[elf_symbol]):
|
||||||
|
|
||||||
def _repr_table(self, format: Literal['text', 'markdown', 'html']):
|
def _repr_table(self, format: Literal['text', 'markdown', 'html']):
|
||||||
columns = ['index', 'name', 'info', 'size', 'stb', 'description']
|
columns = ['index', 'name', 'info', 'size', 'stb', '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.description] for item in self]
|
||||||
return fout.generate_table(data, columns, ['index', 'size'], format)
|
return output_formatter.generate_table(data, columns, ['index', 'size'], format)
|
||||||
|
|
||||||
|
|
||||||
class relocation_list(elf_list[elf_relocation]):
|
class relocation_list(elf_list[elf_relocation]):
|
||||||
|
|
||||||
def _repr_table(self, format: Literal['text', 'markdown', 'html']):
|
def _repr_table(self, format: Literal['text', 'markdown', 'html']):
|
||||||
columns = ['symbol name', 'type', 'description']
|
columns = ['symbol name', 'type', 'description']
|
||||||
data: list[list[str|int]] = [[item.symbol.name, item.type, item.description] for item in self]
|
data: list[list[str | int]] = [[item.symbol.name, item.type, item.description] for item in self]
|
||||||
return fout.generate_table(data, columns, format=format)
|
return output_formatter.generate_table(data, columns, format=format)
|
||||||
|
|
||||||
|
|
||||||
class elf_file:
|
class elf_file:
|
||||||
def __init__(self, file_path: str):
|
def __init__(self, data: bytes):
|
||||||
with open(file_path, mode='rb') as f:
|
self._data = data
|
||||||
self._data = f.read()
|
|
||||||
|
|
||||||
#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 = 'little'
|
self.byteorder = 'little'
|
||||||
|
|
||||||
|
@ -215,21 +212,21 @@ class elf_file:
|
||||||
if self.symbol_table:
|
if self.symbol_table:
|
||||||
offs = self.symbol_table['sh_offset']
|
offs = self.symbol_table['sh_offset']
|
||||||
|
|
||||||
for j, i in enumerate(range(offs, self.symbol_table['sh_size']+offs, self.symbol_table['sh_entsize'])):
|
for j, i in enumerate(range(offs, self.symbol_table['sh_size'] + offs, self.symbol_table['sh_entsize'])):
|
||||||
ret = {'st_name': self.read_int(i, 4)}
|
ret = {'st_name': self.read_int(i, 4)}
|
||||||
|
|
||||||
if self.bit_width == 32:
|
if self.bit_width == 32:
|
||||||
ret['st_value'] = self.read_int(i+4, 4)
|
ret['st_value'] = self.read_int(i + 4, 4)
|
||||||
ret['st_size'] = self.read_int(i+8, 4)
|
ret['st_size'] = self.read_int(i + 8, 4)
|
||||||
ret['st_info'] = self.read_int(i+12, 1)
|
ret['st_info'] = self.read_int(i + 12, 1)
|
||||||
ret['st_other'] = self.read_int(i+13, 1)
|
ret['st_other'] = self.read_int(i + 13, 1)
|
||||||
ret['st_shndx'] = self.read_int(i+14, 2)
|
ret['st_shndx'] = self.read_int(i + 14, 2)
|
||||||
elif self.bit_width == 64:
|
elif self.bit_width == 64:
|
||||||
ret['st_info'] = self.read_int(i+4, 1)
|
ret['st_info'] = self.read_int(i + 4, 1)
|
||||||
ret['st_other'] = self.read_int(i+5, 1)
|
ret['st_other'] = self.read_int(i + 5, 1)
|
||||||
ret['st_shndx'] = self.read_int(i+6, 2)
|
ret['st_shndx'] = self.read_int(i + 6, 2)
|
||||||
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)
|
||||||
|
|
||||||
yield elf_symbol(self, ret, j)
|
yield elf_symbol(self, ret, j)
|
||||||
|
|
||||||
|
@ -247,31 +244,30 @@ class elf_file:
|
||||||
return relocation_list(relocations)
|
return relocation_list(relocations)
|
||||||
|
|
||||||
def _list_relocations(self, sh: elf_section):
|
def _list_relocations(self, sh: elf_section):
|
||||||
assert sh.type == 'SHT_RELA', \
|
assert sh.type == 'SHT_RELA', 'Section must be a relocation section (currently only SHT_RELA is supported)'
|
||||||
'Section must be a relocation section (currently only SHT_RELA is supported)'
|
|
||||||
|
|
||||||
offs = sh['sh_offset']
|
offs = sh['sh_offset']
|
||||||
for i in range(offs, sh['sh_size']+offs, sh['sh_entsize']):
|
for i in range(offs, sh['sh_size'] + offs, sh['sh_entsize']):
|
||||||
ret: dict[str, int] = dict()
|
ret: dict[str, int] = dict()
|
||||||
|
|
||||||
if self.bit_width == 32:
|
if self.bit_width == 32:
|
||||||
ret['r_offset'] = self.read_int(i, 4)
|
ret['r_offset'] = self.read_int(i, 4)
|
||||||
r_info = self.read_int(i+4, 4)
|
r_info = self.read_int(i + 4, 4)
|
||||||
ret['r_info'] = r_info
|
ret['r_info'] = r_info
|
||||||
ret['r_addend'] = self.read_int(i+8, 4, True)
|
ret['r_addend'] = self.read_int(i + 8, 4, True)
|
||||||
yield elf_relocation(self, ret, r_info >> 8, r_info & 0xFF, sh['sh_info'])
|
yield elf_relocation(self, ret, r_info >> 8, r_info & 0xFF, sh['sh_info'])
|
||||||
elif self.bit_width == 64:
|
elif self.bit_width == 64:
|
||||||
ret['r_offset'] = self.read_int(i, 8)
|
ret['r_offset'] = self.read_int(i, 8)
|
||||||
r_info = self.read_int(i+8, 8)
|
r_info = self.read_int(i + 8, 8)
|
||||||
ret['r_info'] = r_info
|
ret['r_info'] = r_info
|
||||||
ret['r_addend'] = self.read_int(i+16, 8, True)
|
ret['r_addend'] = self.read_int(i + 16, 8, True)
|
||||||
yield elf_relocation(self, ret, r_info >> 32, r_info & 0xFFFFFFFF, sh['sh_info'])
|
yield elf_relocation(self, ret, r_info >> 32, r_info & 0xFFFFFFFF, sh['sh_info'])
|
||||||
|
|
||||||
def read_bytes(self, offset: int, num_bytes: int):
|
def read_bytes(self, offset: int, num_bytes: int):
|
||||||
return self._data[offset:offset + num_bytes]
|
return self._data[offset:offset + num_bytes]
|
||||||
|
|
||||||
def read_int(self, offset: int, num_bytes: int, signed: bool = False) -> int:
|
def read_int(self, offset: int, num_bytes: int, signed: bool = False) -> int:
|
||||||
return int.from_bytes(self._data[offset:offset+num_bytes], self.byteorder, signed=signed)
|
return int.from_bytes(self._data[offset:offset + num_bytes], self.byteorder, signed=signed)
|
||||||
|
|
||||||
# def int_to_bytes(self, value: int, num_bytes: int = 4, signed: bool = False) -> int:
|
# def int_to_bytes(self, value: int, num_bytes: int = 4, signed: bool = False) -> int:
|
||||||
# return value.to_bytes(length=num_bytes, byteorder=self.byteorder, signed=signed)
|
# return value.to_bytes(length=num_bytes, byteorder=self.byteorder, signed=signed)
|
||||||
|
@ -305,4 +301,3 @@ class elf_file:
|
||||||
def __getitem__(self, key: str):
|
def __getitem__(self, key: str):
|
||||||
assert key in self.fields, f'Unknown field name: {key}'
|
assert key in self.fields, f'Unknown field name: {key}'
|
||||||
return self.fields[key]
|
return self.fields[key]
|
||||||
|
|
|
@ -195,6 +195,5 @@ e_machine_dict = {
|
||||||
0x0032: {"name": "EM_S390", "description": "IBM S/390"},
|
0x0032: {"name": "EM_S390", "description": "IBM S/390"},
|
||||||
0x003E: {"name": "EM_X86_64", "description": "x86-64 (64-bit)"},
|
0x003E: {"name": "EM_X86_64", "description": "x86-64 (64-bit)"},
|
||||||
0x00F3: {"name": "EM_AARCH64", "description": "ARM64 (64-bit)"},
|
0x00F3: {"name": "EM_AARCH64", "description": "ARM64 (64-bit)"},
|
||||||
0x0103: {"name": "EM_RISCV", "description": "RISC-V (32/64-bit)"},
|
0x0103: {"name": "EM_RISCV", "description": "RISC-V (32/64-bit)"}
|
||||||
0xF3: {"name": "EM_BPF", "description": "BPF (Berkeley Packet Filter)"}
|
|
||||||
}
|
}
|
|
@ -39,7 +39,7 @@ def generate_html_table(data: list[list[Any]], columns: list[str], right_adj_col
|
||||||
|
|
||||||
table_html += "<thead>\n<tr>\n"
|
table_html += "<thead>\n<tr>\n"
|
||||||
for column in columns:
|
for column in columns:
|
||||||
table_html += f" <th>{column}</th>\n"
|
table_html += f" <th style='text-align:left'>{column}</th>\n"
|
||||||
table_html += "</tr>\n</thead>\n"
|
table_html += "</tr>\n</thead>\n"
|
||||||
|
|
||||||
table_html += "<tbody>\n"
|
table_html += "<tbody>\n"
|
||||||
|
@ -49,7 +49,7 @@ def generate_html_table(data: list[list[Any]], columns: list[str], right_adj_col
|
||||||
if columns[i] in right_adj_col:
|
if columns[i] in right_adj_col:
|
||||||
table_html += f" <td style='text-align:right'>{item}</td>\n"
|
table_html += f" <td style='text-align:right'>{item}</td>\n"
|
||||||
else:
|
else:
|
||||||
table_html += f" <td>{item}</td>\n"
|
table_html += f" <td style='text-align:left'>{item}</td>\n"
|
||||||
table_html += "</tr>\n"
|
table_html += "</tr>\n"
|
||||||
table_html += "</tbody>\n"
|
table_html += "</tbody>\n"
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import pelfy
|
import pelfy
|
||||||
|
|
||||||
|
|
||||||
def test_simple_c():
|
def test_simple_c():
|
||||||
elf = pelfy.elf_file('tests/obj/test3_o3.o')
|
elf = pelfy.open_elf_file('tests/obj/test3_o3.o')
|
||||||
|
|
||||||
print(elf.sections)
|
print(elf.sections)
|
||||||
print(elf.symbols)
|
print(elf.symbols)
|
||||||
print(elf.code_relocations)
|
print(elf.code_relocations)
|
||||||
|
|
||||||
if __name__ == '__main__':#
|
|
||||||
|
if __name__ == '__main__':
|
||||||
test_simple_c()
|
test_simple_c()
|
Loading…
Reference in New Issue