0
# ELF Format
1
2
Comprehensive support for ELF (Executable and Linkable Format) files including executables, shared libraries, object files, and core dumps. ELF is the standard binary format for Linux and Unix systems, providing rich metadata for dynamic linking, debugging, and system integration.
3
4
## Capabilities
5
6
### ELF Parsing
7
8
Parse ELF files with format-specific configuration options and validation.
9
10
```python { .api }
11
def parse(filename: str, config: ParserConfig = None) -> Optional[Binary]:
12
"""Parse ELF file from filesystem path."""
13
14
def parse(raw: Sequence[int], config: ParserConfig = None) -> Optional[Binary]:
15
"""Parse ELF from raw bytes."""
16
17
def parse(obj: Union[io.IOBase, os.PathLike], config: ParserConfig = None) -> Optional[Binary]:
18
"""Parse ELF from file-like object."""
19
20
class ParserConfig:
21
parse_relocations: bool
22
parse_dyn_symbols: bool
23
parse_static_symbols: bool
24
parse_symbol_versions: bool
25
parse_notes: bool
26
parse_overlay: bool
27
```
28
29
Usage example:
30
```python
31
import lief.ELF as ELF
32
33
# Basic parsing
34
binary = ELF.parse("/bin/ls")
35
36
# Parse with configuration
37
config = ELF.ParserConfig()
38
config.parse_relocations = True
39
config.parse_dyn_symbols = True
40
binary = ELF.parse("/lib/x86_64-linux-gnu/libc.so.6", config)
41
```
42
43
### ELF Binary Operations
44
45
ELF-specific binary manipulation with support for dynamic linking, symbol management, and section operations.
46
47
```python { .api }
48
class Binary(lief.Binary):
49
header: Header
50
sections: Iterator[Section]
51
segments: Iterator[Segment]
52
dynamic_entries: Iterator[DynamicEntry]
53
symbols: Iterator[Symbol]
54
relocations: Iterator[Relocation]
55
gnu_hash: Optional[GnuHash]
56
sysv_hash: Optional[SysvHash]
57
notes: Iterator[Note]
58
interpreter: str
59
60
def add_section(self, section: Section) -> Section
61
def remove_section(self, name: str, clear: bool = False) -> None
62
def add_segment(self, segment: Segment) -> Segment
63
def add_library(self, library: str) -> DynamicEntryLibrary
64
def remove_library(self, library: str) -> None
65
def add_dynamic_entry(self, entry: DynamicEntry) -> DynamicEntry
66
def get_dynamic_entry(self, tag: DYNAMIC_TAGS) -> Optional[DynamicEntry]
67
def add_symbol(self, symbol: Symbol) -> Symbol
68
def get_relocation(self, address: int) -> Optional[Relocation]
69
def add_relocation(self, relocation: Relocation) -> Relocation
70
```
71
72
Usage example:
73
```python
74
binary = ELF.parse("/bin/ls")
75
76
# Add new library dependency
77
lib_entry = binary.add_library("libcustom.so")
78
print(f"Added library: {lib_entry.name}")
79
80
# Add new section
81
section = ELF.Section()
82
section.name = ".custom"
83
section.type = ELF.SECTION_TYPES.PROGBITS
84
section.flags = ELF.SECTION_FLAGS.ALLOC | ELF.SECTION_FLAGS.WRITE
85
section.content = b"Custom data"
86
binary.add_section(section)
87
88
# Symbol manipulation
89
symbol = ELF.Symbol()
90
symbol.name = "custom_function"
91
symbol.value = 0x1000
92
symbol.size = 64
93
symbol.type = ELF.SYMBOL_TYPES.FUNC
94
binary.add_symbol(symbol)
95
```
96
97
### ELF Header Analysis
98
99
Analyze ELF header information including architecture, ABI, and file type details.
100
101
```python { .api }
102
class Header(lief.Object):
103
file_type: E_TYPE
104
machine_type: ARCH
105
object_file_version: VERSION
106
entry_point: int
107
program_header_offset: int
108
section_header_offset: int
109
processor_flags: int
110
header_size: int
111
program_header_size: int
112
program_header_num: int
113
section_header_size: int
114
section_header_num: int
115
section_name_table_idx: int
116
identity_class: ELF_CLASS
117
identity_data: ELF_DATA
118
identity_version: VERSION
119
identity_os_abi: OS_ABI
120
identity_abi_version: int
121
122
enum E_TYPE:
123
NONE = 0
124
REL = 1
125
EXEC = 2
126
DYN = 3
127
CORE = 4
128
129
enum ARCH:
130
NONE = 0
131
I386 = 3
132
ARM = 40
133
X86_64 = 62
134
AARCH64 = 183
135
RISCV = 243
136
```
137
138
Usage example:
139
```python
140
binary = ELF.parse("/bin/bash")
141
header = binary.header
142
143
print(f"File type: {header.file_type}")
144
print(f"Architecture: {header.machine_type}")
145
print(f"Entry point: 0x{header.entry_point:x}")
146
print(f"ABI: {header.identity_os_abi}")
147
print(f"Class: {header.identity_class}") # 32-bit or 64-bit
148
```
149
150
### Section Management
151
152
Manipulate ELF sections with format-specific properties and operations.
153
154
```python { .api }
155
class Section(lief.Section):
156
type: SECTION_TYPES
157
flags: SECTION_FLAGS
158
link: int
159
information: int
160
alignment: int
161
entry_size: int
162
original_size: int
163
164
def clear(self, value: int = 0) -> None
165
166
enum SECTION_TYPES:
167
SHT_NULL = 0
168
SHT_PROGBITS = 1
169
SHT_SYMTAB = 2
170
SHT_STRTAB = 3
171
SHT_RELA = 4
172
SHT_HASH = 5
173
SHT_DYNAMIC = 6
174
SHT_NOTE = 7
175
SHT_NOBITS = 8
176
SHT_REL = 9
177
SHT_DYNSYM = 11
178
SHT_GNU_HASH = 0x6ffffff6
179
180
enum SECTION_FLAGS:
181
SHF_WRITE = 0x1
182
SHF_ALLOC = 0x2
183
SHF_EXECINSTR = 0x4
184
SHF_MERGE = 0x10
185
SHF_STRINGS = 0x20
186
SHF_INFO_LINK = 0x40
187
SHF_LINK_ORDER = 0x80
188
SHF_OS_NONCONFORMING = 0x100
189
SHF_GROUP = 0x200
190
SHF_TLS = 0x400
191
```
192
193
Usage example:
194
```python
195
binary = ELF.parse("/lib/x86_64-linux-gnu/libc.so.6")
196
197
# Analyze sections
198
for section in binary.sections:
199
print(f"Section: {section.name}")
200
print(f" Type: {section.type}")
201
print(f" Flags: {section.flags}")
202
print(f" Address: 0x{section.virtual_address:x}")
203
print(f" Size: {section.size}")
204
205
# Check for executable sections
206
if section.flags & ELF.SECTION_FLAGS.EXECINSTR:
207
print(f" Executable section with {section.size} bytes")
208
```
209
210
### Dynamic Linking
211
212
Manage dynamic linking information, dependencies, and runtime configuration.
213
214
```python { .api }
215
class DynamicEntry(lief.Object):
216
tag: DYNAMIC_TAGS
217
value: int
218
219
class DynamicEntryLibrary(DynamicEntry):
220
name: str
221
222
class DynamicEntryRpath(DynamicEntry):
223
paths: List[str]
224
225
class DynamicEntryRunPath(DynamicEntry):
226
paths: List[str]
227
228
enum DYNAMIC_TAGS:
229
DT_NULL = 0
230
DT_NEEDED = 1
231
DT_PLTRELSZ = 2
232
DT_PLTGOT = 3
233
DT_HASH = 4
234
DT_STRTAB = 5
235
DT_SYMTAB = 6
236
DT_RELA = 7
237
DT_RELASZ = 8
238
DT_RELAENT = 9
239
DT_STRSZ = 10
240
DT_SYMENT = 11
241
DT_INIT = 12
242
DT_FINI = 13
243
DT_SONAME = 14
244
DT_RPATH = 15
245
DT_SYMBOLIC = 16
246
DT_REL = 17
247
DT_RELSZ = 18
248
DT_RELENT = 19
249
DT_PLTREL = 20
250
DT_DEBUG = 21
251
DT_TEXTREL = 22
252
DT_JMPREL = 23
253
DT_RUNPATH = 29
254
```
255
256
Usage example:
257
```python
258
binary = ELF.parse("/usr/bin/python3")
259
260
# List library dependencies
261
print("Library dependencies:")
262
for entry in binary.dynamic_entries:
263
if entry.tag == ELF.DYNAMIC_TAGS.NEEDED:
264
lib_entry = ELF.DynamicEntryLibrary(entry)
265
print(f" {lib_entry.name}")
266
267
# Check for RPATH/RUNPATH
268
rpath_entry = binary.get_dynamic_entry(ELF.DYNAMIC_TAGS.RPATH)
269
if rpath_entry:
270
rpath = ELF.DynamicEntryRpath(rpath_entry)
271
print(f"RPATH: {':'.join(rpath.paths)}")
272
273
runpath_entry = binary.get_dynamic_entry(ELF.DYNAMIC_TAGS.RUNPATH)
274
if runpath_entry:
275
runpath = ELF.DynamicEntryRunPath(runpath_entry)
276
print(f"RUNPATH: {':'.join(runpath.paths)}")
277
```
278
279
### Symbol Analysis
280
281
Advanced symbol table analysis with binding, visibility, and versioning support.
282
283
```python { .api }
284
class Symbol(lief.Symbol):
285
type: SYMBOL_TYPES
286
binding: SYMBOL_BINDINGS
287
visibility: SYMBOL_VISIBILITY
288
shndx: int
289
symbol_version: Optional[SymbolVersion]
290
291
def is_static(self) -> bool
292
def is_function(self) -> bool
293
def is_variable(self) -> bool
294
295
enum SYMBOL_TYPES:
296
STT_NOTYPE = 0
297
STT_OBJECT = 1
298
STT_FUNC = 2
299
STT_SECTION = 3
300
STT_FILE = 4
301
STT_COMMON = 5
302
STT_TLS = 6
303
STT_GNU_IFUNC = 10
304
305
enum SYMBOL_BINDINGS:
306
STB_LOCAL = 0
307
STB_GLOBAL = 1
308
STB_WEAK = 2
309
STB_GNU_UNIQUE = 10
310
311
enum SYMBOL_VISIBILITY:
312
STV_DEFAULT = 0
313
STV_INTERNAL = 1
314
STV_HIDDEN = 2
315
STV_PROTECTED = 3
316
```
317
318
Usage example:
319
```python
320
binary = ELF.parse("/lib/x86_64-linux-gnu/libc.so.6")
321
322
# Analyze exported functions
323
print("Exported functions:")
324
for symbol in binary.symbols:
325
if (symbol.binding == ELF.SYMBOL_BINDINGS.GLOBAL and
326
symbol.type == ELF.SYMBOL_TYPES.FUNC and
327
symbol.shndx != 0): # Not undefined
328
print(f" {symbol.name} @ 0x{symbol.value:x}")
329
330
# Check symbol version if available
331
if symbol.symbol_version:
332
print(f" Version: {symbol.symbol_version.symbol_version_auxiliary.name}")
333
```
334
335
### Note Sections
336
337
Parse and analyze ELF note sections containing build information, ABI details, and system metadata.
338
339
```python { .api }
340
class Note(lief.Object):
341
name: str
342
type: int
343
description: memoryview
344
345
class NoteAbi(Note):
346
version: List[int] # ABI version tuple
347
348
class AndroidIdent(Note):
349
sdk_version: int
350
ndk_version: str
351
ndk_build_number: str
352
353
class CoreFile(Note):
354
count: int
355
page_size: int
356
file_mapping: Iterator[CoreFileEntry]
357
358
class CorePrStatus(Note):
359
info: CorePrStatus.siginfo_t
360
cursig: int
361
sigpend: int
362
sighold: int
363
pid: int
364
ppid: int
365
pgrp: int
366
sid: int
367
register_values: memoryview
368
```
369
370
Usage example:
371
```python
372
binary = ELF.parse("/bin/ls")
373
374
# Analyze note sections
375
for note in binary.notes:
376
print(f"Note: {note.name} (type: {note.type})")
377
378
# Check for GNU build ID
379
if note.name == "GNU" and note.type == 3: # NT_GNU_BUILD_ID
380
build_id = note.description.hex()
381
print(f" Build ID: {build_id}")
382
383
# Check for ABI information
384
elif isinstance(note, ELF.NoteAbi):
385
print(f" ABI version: {'.'.join(map(str, note.version))}")
386
```
387
388
## Types
389
390
```python { .api }
391
class Segment(lief.Object):
392
type: SEGMENT_TYPES
393
flags: SEGMENT_FLAGS
394
file_offset: int
395
virtual_address: int
396
physical_address: int
397
physical_size: int
398
virtual_size: int
399
alignment: int
400
sections: Iterator[Section]
401
402
enum SEGMENT_TYPES:
403
PT_NULL = 0
404
PT_LOAD = 1
405
PT_DYNAMIC = 2
406
PT_INTERP = 3
407
PT_NOTE = 4
408
PT_SHLIB = 5
409
PT_PHDR = 6
410
PT_TLS = 7
411
PT_GNU_EH_FRAME = 0x6474e550
412
PT_GNU_STACK = 0x6474e551
413
PT_GNU_RELRO = 0x6474e552
414
415
enum SEGMENT_FLAGS:
416
PF_X = 0x1 # Execute
417
PF_W = 0x2 # Write
418
PF_R = 0x4 # Read
419
420
class GnuHash(lief.Object):
421
nb_buckets: int
422
symbol_index: int
423
shift2: int
424
bloom_filters: List[int]
425
buckets: List[int]
426
hash_values: List[int]
427
428
class SysvHash(lief.Object):
429
nbucket: int
430
nchain: int
431
buckets: List[int]
432
chains: List[int]
433
434
class Builder:
435
def build(self) -> None
436
def write(self, output: str) -> None
437
def get_build_warnings(self) -> List[str]
438
```