]>
crepu.dev Git - config.git/blob - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/packaging/_elffile.py
4 This provides a class ``ELFFile`` that parses an ELF executable in a similar
5 interface to ``ZipFile``. Only the read interface is implemented.
7 Based on: https://gist.github.com/lyssdod/f51579ae8d93c8657a5564aefc2ffbca
8 ELF header: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html
14 from typing
import IO
, Optional
, Tuple
17 class ELFInvalid(ValueError):
21 class EIClass(enum
.IntEnum
):
26 class EIData(enum
.IntEnum
):
31 class EMachine(enum
.IntEnum
):
41 Representation of an ELF executable.
44 def __init__(self
, f
: IO
[bytes
]) -> None:
48 ident
= self
._read
("16B")
50 raise ELFInvalid("unable to parse identification")
51 magic
= bytes(ident
[:4])
52 if magic
!= b
"\x7fELF":
53 raise ELFInvalid(f
"invalid magic: {magic!r}")
55 self
.capacity
= ident
[4] # Format for program header (bitness).
56 self
.encoding
= ident
[5] # Data structure encoding (endianness).
59 # e_fmt: Format for program header.
60 # p_fmt: Format for section header.
61 # p_idx: Indexes to find p_type, p_offset, and p_filesz.
62 e_fmt
, self
._p
_fmt
, self
._p
_idx
= {
63 (1, 1): ("<HHIIIIIHHH", "<IIIIIIII", (0, 1, 4)), # 32-bit LSB.
64 (1, 2): (">HHIIIIIHHH", ">IIIIIIII", (0, 1, 4)), # 32-bit MSB.
65 (2, 1): ("<HHIQQQIHHH", "<IIQQQQQQ", (0, 2, 5)), # 64-bit LSB.
66 (2, 2): (">HHIQQQIHHH", ">IIQQQQQQ", (0, 2, 5)), # 64-bit MSB.
67 }[(self
.capacity
, self
.encoding
)]
70 f
"unrecognized capacity ({self.capacity}) or "
71 f
"encoding ({self.encoding})"
77 self
.machine
, # Architecture type.
80 self
._e
_phoff
, # Offset of program header.
82 self
.flags
, # Processor-specific flags.
84 self
._e
_phentsize
, # Size of section.
85 self
._e
_phnum
, # Number of sections.
87 except struct
.error
as e
:
88 raise ELFInvalid("unable to parse machine and section information") from e
90 def _read(self
, fmt
: str) -> Tuple
[int, ...]:
91 return struct
.unpack(fmt
, self
._f
.read(struct
.calcsize(fmt
)))
94 def interpreter(self
) -> Optional
[str]:
96 The path recorded in the ``PT_INTERP`` section header.
98 for index
in range(self
._e
_phnum
):
99 self
._f
.seek(self
._e
_phoff
+ self
._e
_phentsize
* index
)
101 data
= self
._read
(self
._p
_fmt
)
104 if data
[self
._p
_idx
[0]] != 3: # Not PT_INTERP.
106 self
._f
.seek(data
[self
._p
_idx
[1]])
107 return os
.fsdecode(self
._f
.read(data
[self
._p
_idx
[2]])).strip("\0")