22
33import io
44from functools import cached_property , lru_cache
5- from typing import BinaryIO , Callable , Generic , Iterator , Optional , TypeVar , Union
6-
7- from dissect .cstruct import cstruct
5+ from operator import itemgetter
6+ from typing import TYPE_CHECKING , BinaryIO , Callable , Generic , TypeVar
87
98from dissect .executable .elf .c_elf import (
109 SHN ,
1918)
2019from dissect .executable .exception import InvalidSignatureError
2120
21+ if TYPE_CHECKING :
22+ from collections .abc import Iterator
23+
24+ from dissect .cstruct import cstruct
25+
2226
2327class ELF :
2428 def __init__ (self , fh : BinaryIO ):
@@ -48,25 +52,31 @@ def __repr__(self) -> str:
4852 return str (self .header )
4953
5054 def dump (self ) -> bytes :
51- output_data = (
52- [self .segments .dump_table (), self .section_table .dump_table ()]
53- + self .segments .dump_data ()
54- + self .section_table .dump_data ()
55- )
56-
57- output_data .sort (key = lambda tup : tup [0 ])
58- output_buf = bytes ()
59-
55+ output_data = [
56+ self .segments .dump_table (),
57+ self .section_table .dump_table (),
58+ * self .segments .dump_data (),
59+ * self .section_table .dump_data (),
60+ ]
61+ output_data .sort (key = itemgetter (0 ))
62+
63+ result = []
64+ output_size = 0
6065 for offset , output_bytes in output_data :
61- output_offset = offset - len (output_buf )
66+ output_offset = offset - output_size
67+
68+ buf = None
6269 relative_offset = output_offset + len (output_bytes )
6370 if output_offset < 0 and relative_offset > 0 :
64- output_buf + = output_bytes [abs (output_offset ) :]
71+ buf = output_bytes [abs (output_offset ) :]
6572 elif output_offset >= 0 :
66- padding = b"\x00 " * output_offset
67- output_buf += padding
68- output_buf += output_bytes
69- return output_buf
73+ buf = (b"\x00 " * output_offset ) + output_bytes
74+
75+ if buf is not None :
76+ result .append (buf )
77+ output_size += len (buf )
78+
79+ return b"" .join (result )
7080
7181 @property
7282 def dynamic (self ) -> bool :
@@ -91,14 +101,14 @@ def __getitem__(self, idx: int) -> T:
91101 return self .items [idx ]
92102
93103 def _create_item (self , idx : int ) -> T :
94- raise NotImplementedError ()
104+ raise NotImplementedError
95105
96- def find (self , condition : Callable , ** kwargs ) -> list [T ]:
106+ def find (self , condition : Callable [[ T ], bool ] , ** kwargs ) -> list [T ]:
97107 return [item for item in self if condition (item , ** kwargs )]
98108
99109
100110class Section :
101- def __init__ (self , fh : BinaryIO , idx : Optional [ int ] = None , c_elf : cstruct = c_elf_64 ):
111+ def __init__ (self , fh : BinaryIO , idx : int | None = None , c_elf : cstruct = c_elf_64 ):
102112 self .fh = fh
103113 self .idx = idx
104114
@@ -116,14 +126,14 @@ def __init__(self, fh: BinaryIO, idx: Optional[int] = None, c_elf: cstruct = c_e
116126 def __repr__ (self ) -> str :
117127 return (
118128 f"<{ self .__class__ .__name__ } idx={ self .idx } name={ self .name } type={ self .type } "
119- f" offset=0x{ self .offset :x} size=0x{ self .size :x} >"
129+ f" offset=0x{ self .offset :x} size=0x{ self .size :x} >"
120130 )
121131
122- def _set_name (self , table : StringTable ):
132+ def _set_name (self , table : StringTable ) -> None :
123133 if self .header .sh_name != SHN .UNDEF :
124134 self ._name = table [self .header .sh_name ]
125135
126- def _set_link (self , table : SectionTable ):
136+ def _set_link (self , table : SectionTable ) -> None :
127137 if self .header .sh_link != SHN .UNDEF :
128138 self ._link = table [self .header .sh_link ]
129139
@@ -142,14 +152,14 @@ def from_section_table(cls, section_table: SectionTable, idx: int) -> Section:
142152 return result
143153
144154 @property
145- def name (self ) -> Optional [ str ] :
155+ def name (self ) -> str | None :
146156 return self ._name
147157
148158 def is_related (self , segment : Segment ) -> bool :
149159 return segment .is_related (self )
150160
151161 @property
152- def link (self ) -> Optional [ Section ] :
162+ def link (self ) -> Section | None :
153163 return self ._link
154164
155165 @cached_property
@@ -165,7 +175,7 @@ def __init__(
165175 offset : int ,
166176 entries : int ,
167177 size : int ,
168- string_index : Optional [ int ] = None ,
178+ string_index : int | None = None ,
169179 c_elf : cstruct = c_elf_64 ,
170180 ):
171181 super ().__init__ (entries )
@@ -202,7 +212,7 @@ def from_elf(cls, elf: ELF) -> SectionTable:
202212 other_index = elf .header .e_shstrndx
203213 return cls (elf .fh , offset , entries , size , other_index , elf .c_elf )
204214
205- def by_type (self , section_types : Union [ list [int ], int ] ) -> list [Section ]:
215+ def by_type (self , section_types : list [int ] | int ) -> list [Section ]:
206216 types = section_types
207217 if not isinstance (section_types , list ):
208218 types = [types ]
@@ -224,7 +234,7 @@ def dump_data(self) -> list[tuple[int, bytes]]:
224234
225235
226236class Segment :
227- def __init__ (self , fh : BinaryIO , idx : Optional [ int ] = None , c_elf : cstruct = c_elf_64 ):
237+ def __init__ (self , fh : BinaryIO , idx : int | None = None , c_elf : cstruct = c_elf_64 ):
228238 self .fh = fh
229239 self .idx = idx
230240 self .c_elf = c_elf
@@ -246,7 +256,7 @@ def __repr__(self) -> str:
246256 return repr (self .header )
247257
248258 @classmethod
249- def from_segment_table (cls , table : SegmentTable , idx : Optional [ int ] = None ) -> Segment :
259+ def from_segment_table (cls , table : SegmentTable , idx : int | None = None ) -> Segment :
250260 fh = table .fh
251261 return cls (fh , idx , table .c_elf )
252262
@@ -302,7 +312,7 @@ def from_elf(cls, elf: ELF) -> SegmentTable:
302312 def related_segments (self , section : Section ) -> list [Segment ]:
303313 return self .find (lambda x : x .is_related (section ))
304314
305- def by_type (self , segment_types : Union [ list [int ], int ] ) -> list [Segment ]:
315+ def by_type (self , segment_types : list [int ] | int ) -> list [Segment ]:
306316 types = segment_types
307317 if not isinstance (segment_types , list ):
308318 types = [types ]
@@ -318,7 +328,7 @@ def dump_table(self) -> tuple[int, bytearray]:
318328
319329
320330class StringTable (Section ):
321- def __init__ (self , fh : BinaryIO , idx : Optional [ int ] = None , c_elf : cstruct = c_elf_64 ):
331+ def __init__ (self , fh : BinaryIO , idx : int | None = None , c_elf : cstruct = c_elf_64 ):
322332 super ().__init__ (fh , idx , c_elf )
323333
324334 self ._get_string = lru_cache (256 )(self ._get_string )
@@ -333,7 +343,7 @@ def _get_string(self, index: int) -> str:
333343
334344
335345class Symbol :
336- def __init__ (self , fh : BinaryIO , idx : Optional [ int ] = None , c_elf : cstruct = c_elf_64 ):
346+ def __init__ (self , fh : BinaryIO , idx : int | None = None , c_elf : cstruct = c_elf_64 ):
337347 self .symbol = c_elf .Sym (fh )
338348 self .idx = idx
339349 self .c_elf = c_elf
@@ -373,11 +383,7 @@ def name(self) -> str:
373383
374384 @property
375385 def value (self ) -> int :
376- symloc = self .symbol .st_shndx
377- if symloc == SHN .UNDEF :
378- return 0
379- else :
380- return self .symbol .st_value
386+ return 0 if self .symbol .st_shndx == SHN .UNDEF else self .symbol .st_value
381387
382388 def value_based_on_shndx (self , table : SectionTable ) -> int :
383389 symloc = self .symbol .st_shndx
@@ -388,7 +394,7 @@ def value_based_on_shndx(self, table: SectionTable) -> int:
388394
389395
390396class SymbolTable (Section , Table [Symbol ]):
391- def __init__ (self , fh : BinaryIO , idx : Optional [ int ] = None , c_elf : cstruct = c_elf_64 ):
397+ def __init__ (self , fh : BinaryIO , idx : int | None = None , c_elf : cstruct = c_elf_64 ):
392398 # Initializes Section info
393399 Section .__init__ (self , fh , idx , c_elf )
394400 count = self .size // self .entry_size
0 commit comments