2727class ELF :
2828 def __init__ (self , fh : BinaryIO ):
2929 self .fh = fh
30- offset = fh .tell ()
30+
31+ fh .seek (0 )
3132 self .e_ident = fh .read (0x10 )
32- fh .seek (offset )
3333
3434 if self .e_ident [:4 ] != c_common_elf .ELFMAG :
35- raise InvalidSignatureError ("Invalid header magic" )
35+ raise InvalidSignatureError (
36+ f"Invalid ELF header magic, expected { c_common_elf .ELFMAG !r} , got { self .e_ident [:4 ]!r} "
37+ )
3638
3739 c_elf_version = c_elf_32
3840 if self .e_ident [c_common_elf .EI_CLASS ] == c_common_elf .ELFCLASS64 :
@@ -43,20 +45,22 @@ def __init__(self, fh: BinaryIO):
4345 is_little = self .e_ident [c_common_elf .EI_DATA ] == c_common_elf .ELFDATA2LSB
4446 self .c_elf .endian = "<" if is_little else ">"
4547
48+ fh .seek (0 )
4649 self .header = self .c_elf .Ehdr (fh )
50+
4751 self .segments = SegmentTable .from_elf (self )
48- self .section_table = SectionTable .from_elf (self )
49- self .symbol_tables : list [SymbolTable ] = self .section_table .by_type ([SHT .SYMTAB , SHT .DYNSYM ])
52+ self .sections = SectionTable .from_elf (self )
53+ self .symbol_tables : list [SymbolTable ] = self .sections .by_type ([SHT .SYMTAB , SHT .DYNSYM ])
5054
5155 def __repr__ (self ) -> str :
5256 return str (self .header )
5357
5458 def dump (self ) -> bytes :
5559 output_data = [
5660 self .segments .dump_table (),
57- self .section_table .dump_table (),
61+ self .sections .dump_table (),
5862 * self .segments .dump_data (),
59- * self .section_table .dump_data (),
63+ * self .sections .dump_data (),
6064 ]
6165 output_data .sort (key = itemgetter (0 ))
6266
@@ -87,12 +91,12 @@ def dynamic(self) -> bool:
8791
8892
8993class Table (Generic [T ]):
90- def __init__ (self , entries : int ) -> None :
91- self .entries = entries
92- self .items : list [T ] = [None ] * entries
94+ def __init__ (self , num : int ) -> None :
95+ self .num = num
96+ self .items : list [T ] = [None ] * num
9397
9498 def __iter__ (self ) -> Iterator [T ]:
95- for idx in range (self .entries ):
99+ for idx in range (self .num ):
96100 yield self [idx ]
97101
98102 def __getitem__ (self , idx : int ) -> T :
@@ -125,7 +129,7 @@ def __init__(self, fh: BinaryIO, idx: int | None = None, c_elf: cstruct = c_elf_
125129
126130 def __repr__ (self ) -> str :
127131 return (
128- f"<{ self .__class__ .__name__ } idx={ self .idx } name={ self .name } type={ self .type } "
132+ f"<{ self .__class__ .__name__ } idx={ self .idx } name={ self .name !r } type={ self .type } "
129133 f" offset=0x{ self .offset :x} size=0x{ self .size :x} >"
130134 )
131135
@@ -138,16 +142,12 @@ def _set_link(self, table: SectionTable) -> None:
138142 self ._link = table [self .header .sh_link ]
139143
140144 @classmethod
141- def from_section_table (cls , section_table : SectionTable , idx : int ) -> Section :
142- result = cls (section_table .fh , idx = idx , c_elf = section_table .c_elf )
143- result ._set_link (section_table )
144-
145- string_table = section_table .string_table
146- if isinstance (result , StringTable ):
147- string_table = result
145+ def from_section_table (cls , table : SectionTable , idx : int ) -> Section :
146+ result = cls (table .fh , idx = idx , c_elf = table .c_elf )
147+ result ._set_link (table )
148148
149- if string_table :
150- result ._set_name (string_table )
149+ if sh_strtab := ( result if idx == table . _sh_strtab_idx else table . _sh_strtab ) :
150+ result ._set_name (sh_strtab )
151151
152152 return result
153153
@@ -163,7 +163,7 @@ def link(self) -> Section | None:
163163 return self ._link
164164
165165 @cached_property
166- def contents (self ) -> bytes :
166+ def data (self ) -> bytes :
167167 self .fh .seek (self .offset )
168168 return self .fh .read (self .size )
169169
@@ -173,20 +173,22 @@ def __init__(
173173 self ,
174174 fh : BinaryIO ,
175175 offset : int ,
176- entries : int ,
176+ num : int ,
177177 size : int ,
178- string_index : int | None = None ,
178+ sh_strtab_idx : int | None = None ,
179179 c_elf : cstruct = c_elf_64 ,
180180 ):
181- super ().__init__ (entries )
181+ super ().__init__ (num )
182182 self .fh = fh
183183 self .offset = offset
184184 self .size = size
185- self .string_table = None
186185 self .c_elf = c_elf
187186
188- if string_index :
189- self .string_table : StringTable = self [string_index ]
187+ self ._sh_strtab_idx = sh_strtab_idx
188+ self ._sh_strtab = None
189+
190+ if sh_strtab_idx :
191+ self ._sh_strtab : StringTable = self [sh_strtab_idx ]
190192
191193 def __repr__ (self ) -> str :
192194 return f"<SectionTable offset=0x{ self .offset :x} size=0x{ self .size :x} >"
@@ -206,11 +208,14 @@ def _create_item(self, idx: int) -> Section:
206208
207209 @classmethod
208210 def from_elf (cls , elf : ELF ) -> SectionTable :
209- offset = elf .header .e_shoff
210- entries = elf .header .e_shnum
211- size = elf .header .e_shentsize
212- other_index = elf .header .e_shstrndx
213- return cls (elf .fh , offset , entries , size , other_index , elf .c_elf )
211+ return cls (
212+ elf .fh ,
213+ elf .header .e_shoff ,
214+ elf .header .e_shnum ,
215+ elf .header .e_shentsize ,
216+ elf .header .e_shstrndx ,
217+ elf .c_elf ,
218+ )
214219
215220 def by_type (self , section_types : list [int ] | int ) -> list [Section ]:
216221 types = section_types
@@ -223,14 +228,14 @@ def related_sections(self, segment: Segment) -> list[Section]:
223228 return self .find (lambda x : x .is_related (segment ))
224229
225230 def by_name (self , name : str ) -> list [Section ]:
226- return self .find (lambda x : x . name in name )
231+ return self .find (lambda x : name == x . name )
227232
228233 def dump_table (self ) -> tuple [int , bytes ]:
229234 buf = bytearray ()
230235 return self .offset , buf .join ([x .header .dumps () for x in self ])
231236
232237 def dump_data (self ) -> list [tuple [int , bytes ]]:
233- return [(x .offset , x .contents ) for x in self ]
238+ return [(x .offset , x .data ) for x in self ]
234239
235240
236241class Segment :
@@ -268,7 +273,7 @@ def is_related(self, section: Section) -> bool:
268273 return self .offset <= section .offset < self .end
269274
270275 @property
271- def contents (self ) -> bytes :
276+ def data (self ) -> bytes :
272277 if not self ._data :
273278 self .fh .seek (self .offset )
274279 self ._data = self .fh .read (self .size )
@@ -320,7 +325,7 @@ def by_type(self, segment_types: list[int] | int) -> list[Segment]:
320325 return self .find (lambda x : x .type in types )
321326
322327 def dump_data (self ) -> list [tuple [int , bytearray ]]:
323- return [(x .offset , x .contents ) for x in self ]
328+ return [(x .offset , x .data ) for x in self ]
324329
325330 def dump_table (self ) -> tuple [int , bytearray ]:
326331 buf = bytearray ()
@@ -337,9 +342,9 @@ def __getitem__(self, offset: int) -> str:
337342 return self ._get_string (offset )
338343
339344 def _get_string (self , index : int ) -> str :
340- if index > len ( self .contents ) or index == SHN .UNDEF :
345+ if index > self .size or index == SHN .UNDEF :
341346 return None
342- return self .c_elf .char [None ](self .contents [index :]).decode ("utf8" )
347+ return self .c_elf .char [None ](self .data [index :]).decode ("utf8" )
343348
344349
345350class Symbol :
@@ -372,7 +377,7 @@ def _set_name(self, table: StringTable) -> None:
372377 @classmethod
373378 def from_symbol_table (cls , table : SymbolTable , idx : int ) -> Symbol :
374379 offset = idx * table .entry_size
375- data = table .contents [offset : offset + table .entry_size ]
380+ data = table .data [offset : offset + table .entry_size ]
376381 output = cls (io .BytesIO (data ), idx , table .c_elf )
377382 output ._set_name (table .link )
378383 return output
0 commit comments