Compare commits

...
430 Commits
Author SHA1 Message Date
lief-integration-bot d005663ac7 Merge pull request #1378 from lief-project/dependabot/pip/doc/lxml-6.1.0
build(deps): bump lxml from 6.0.2 to 6.1.0 in /doc
2026-09-06 11:54:00 +02:00
lief-agent 3354b45db2 doc: update headline & icon 2026-09-06 11:50:35 +02:00
dependabot[bot] 4c32abd74e build(deps): bump lxml from 6.0.2 to 6.1.0 in /doc
Bumps [lxml](https://github.com/lxml/lxml) from 6.0.2 to 6.1.0.
- [Release notes](https://github.com/lxml/lxml/releases)
- [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt)
- [Commits](https://github.com/lxml/lxml/compare/lxml-6.0.2...lxml-6.1.0)

---
updated-dependencies:
- dependency-name: lxml
  dependency-version: 6.1.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-06 09:16:43 +00:00
lief-integration-bot 105fbbb714 rust: expose Memory::Chunk::deallocate 2026-09-06 07:12:24 +02:00
lief-integration-bot c7c5a9fc4f docs: publish AI-friendly pages 2026-09-05 22:31:24 +02:00
lief-integration-bot 7fe429a5f0 docs: clarify extended and runtime 2026-09-05 21:58:35 +02:00
Romain Thomas 811a871fdf core: avoid pthread dependency in mbedtls initialization 2026-08-30 15:08:49 +02:00
lief-integration-bot 9a78a15cee runtime: add MemoryLayout API 2026-08-30 14:30:16 +02:00
Romain Thomas 8254a43863 MachO: Fix relocation bitfield conversions 2026-08-30 09:40:46 +02:00
Jeongseok (JS) Lee 27a280e09e Require the supported MbedTLS version exactly (#1376) 2026-08-30 09:09:26 +02:00
Jeongseok (JS) Lee 3ce19013f5 Avoid major/minor macro collisions in runtime version constructors (#1375) 2026-08-30 09:06:06 +02:00
Romain Thomas 934b2b7b95 Fix typing stubs 2026-08-29 17:35:25 +02:00
lief-agent f8db8a714c lint: enforce Rust toolchain for rust hooks 2026-08-29 16:14:34 +02:00
lief-integration-bot 05eee7a67f elf: support the MIPS n64 relocation encoding
close #1367
2026-08-29 15:22:57 +02:00
lief-integration-bot fe8ccaa92d elf: ensure the vector_iostream is initialized 2026-08-29 15:21:34 +02:00
lief-integration-bot d377a74997 elf: fix endianness & bit/bytes confusion 2026-08-29 15:17:13 +02:00
lief-agent 479149510a lint 2026-08-29 15:11:17 +02:00
lief-agent 2f136969fc lint: add custom clang-taidy checks 2026-08-29 14:09:53 +02:00
lief-agent 52199f0518 lint: use the alternate form without prefix 2026-08-29 14:06:59 +02:00
lief-agent 9ec12e299e lint: avoid references for simple types 2026-08-29 13:49:15 +02:00
lief-agent 298468c530 clang-tidy: disable misc-static-assert check
False positives: llvm/llvm-project#213560
2026-08-29 13:46:25 +02:00
lief-integration-bot 8107947d82 runtime: add mmap_hint 2026-08-29 11:36:04 +02:00
lief-integration-bot 0a470d7420 test: fix x86 instruction counts for the LOCK prefix instructions 2026-08-29 11:29:18 +02:00
lief-integration-bot 37ab8a7ef0 test: fix arm64 memory operands 2026-08-29 11:28:03 +02:00
lief-agent e0dd3363ec macho: fix inverted condition 2026-08-29 11:20:53 +02:00
lief-integration-bot 6bc9a38587 api: add support for C++17 std::{string_view, filesystem} 2026-08-29 11:17:09 +02:00
lief-integration-bot 3cc572c3bb python: upgrade nanobind 2.13.0 -> 3.0.1 2026-08-29 08:32:32 +02:00
Romain Thomas 4c9c42c483 binaryninja: 6.0 update 2026-08-22 10:10:32 +02:00
Romain Thomas 1c02380920 binaryninja: rename the bn namespace alias into BN 2026-08-22 10:10:11 +02:00
Romain Thomas cfd60bd66a rust: update cxx, cxx-gen & num-derive 2026-08-20 17:45:43 +02:00
lief-integration-bot c8e6eff6ef tests: update catch2 to 3.15.3 2026-08-20 17:31:38 +02:00
lief-integration-bot 1937d455ec core: fix parsing path whose content can't be read
Resolve #1372
2026-08-20 16:57:00 +02:00
lief-agent 5916c8d2b9 lint: reorder includes 2026-08-20 15:39:32 +02:00
Romain Thomas 6a4edfdf2f windows: fix min/max macro conflict 2026-08-20 14:44:57 +02:00
Romain Thomas f0fcff7f0b tests: FetchContent(catch2) CXX standard definition. 2026-08-20 10:41:17 +02:00
Romain Thomas 9e8d4d5242 test: skip format & IWYU 2026-08-15 21:14:14 +02:00
mccakit 1d228ed1e5 libcxx fix (#1373) 2026-08-15 19:57:05 +02:00
Romain Thomas e5a4126dde lint: install revgate 2026-08-04 23:11:40 +02:00
lief-agent b68429c52d lint: add Harper pre-commit hook 2026-08-04 22:43:29 +02:00
lief-agent b492a5cf34 docs: migrate Sphinx RST sources to MyST Markdown 2026-08-03 23:21:21 +02:00
lief-integration-bot 5da76859ef ELF: fix the layout of the segments added on 64KB-page architectures
Fix: #1366
2026-08-02 21:25:16 +02:00
lief-integration-bot fb73059abb COFF: add Binary::get_section() 2026-08-02 11:44:09 +02:00
lief-integration-bot 372512fc18 Fix missing boundaries checks
These issues have been found by Claude Fable 5 & GPT-5.6-SOL
2026-08-02 09:01:15 +02:00
lief-agent a426b86d75 Add missing references 2026-08-02 03:39:30 +02:00
lief-integration-bot cac3d8fb3f logging: rename LEVEL -> Level with CamelCase enumerators
Resolve #1365
2026-08-01 19:04:04 +02:00
lief-agent aa7586881c Lint code 2026-08-01 18:23:49 +02:00
lief-integration-bot a0a312030e asm: add x86 LOCK prefix API with Python & Rust bindings 2026-08-01 12:59:14 +02:00
lief-agent f3754eb210 test: add test case for #321 2026-08-01 11:34:14 +02:00
lief-integration-bot 884e229971 core: modernize codebase to C++17 and remove legacy C API
- Bumped the minimum C++ standard for public headers, public API, and STL C++11 to C++17
- Fully removed the legacy C API
2026-08-01 06:12:13 +02:00
lief-agent 3174463a64 doc: update 2026-07-26 18:04:57 +02:00
lief-integration-bot a931521fa8 Downgrade build version 2026-07-26 17:38:36 +02:00
lief-integration-bot d41866b597 pe: fix PE relocations parser
resolve #1362
2026-07-26 17:33:26 +02:00
Romain Thomas a01d9d8d0e Bump version 2026-07-12 18:20:03 +02:00
Romain Thomas 5da7ef8723 version: change bump rules 2026-07-12 18:11:49 +02:00
Romain Thomas 2f08559f17 python: fix warning 2026-07-12 18:11:08 +02:00
Romain Thomas 0e340dd897 python: move to [[tool.dynamic-metadata]] 2026-07-12 18:08:52 +02:00
Romain Thomas 916d51868b rust: update targets 2026-07-12 18:08:30 +02:00
Romain Thomas d05b3499b6 Version 1.0.0 2026-07-12 15:17:37 +02:00
lief-integration-bot 46d05fc76b rust: add write_to_bytes bindings 2026-07-12 15:16:05 +02:00
Romain Thomas d61a93b42e Update metrics requirements 2026-07-12 09:13:41 +02:00
Romain Thomas 3437f545bf Update deps 2026-07-12 08:49:58 +02:00
lief-agent 45bb1b0db1 doc: fix missing rust reference 2026-07-11 21:35:25 +02:00
Romain Thomas 469c7d00f1 elf: support for v3/v4 CIE records in .eh_frame
resolve #488
2026-07-11 21:15:01 +02:00
Romain Thomas 2a95290b7e rust: update deps 2026-07-11 19:18:17 +02:00
Romain Thomas d5b1aa3866 runtime: fix missing definitions 2026-07-11 19:08:36 +02:00
Romain Thomas f5f9641a8c test: disable this test for the extended version (only) 2026-07-11 17:02:43 +02:00
Romain Thomas afee9061d9 python: add __match_args__ to assembly Instruction 2026-07-11 17:01:24 +02:00
Romain Thomas f09dd83eac doc: use match-case instead of isinstance 2026-07-11 17:00:51 +02:00
Romain Thomas c6416faefc cleanup 2026-07-11 16:29:32 +02:00
Romain Thomas 1f7c8f7dc3 ELF: fix add_library on MIPS
resolve #210
2026-07-11 14:53:26 +02:00
Romain Thomas daec9c3ff5 ELF: fix relocation size tag when adding RELR/Android relocations
resolve #1342
2026-07-11 14:53:13 +02:00
lief-integration-bot e608952ef4 tests: only for linux 2026-07-11 14:53:00 +02:00
lief-integration-bot 17c244a396 tools: add common crate 2026-07-11 14:52:33 +02:00
lief-agent bb59f8e685 README: fix code examples 2026-07-11 14:52:16 +02:00
Romain Thomas 6e058369f0 Remove unused files 2026-07-11 14:52:11 +02:00
lief-agent 8093e32b76 Cleanup: remove trailing comments after #endif 2026-07-11 14:51:58 +02:00
lief-agent 2d00880302 VDEX: reject out-of-order code-item range in quickening info 2026-07-11 14:51:55 +02:00
lief-agent 673aae77ff VDEX: guard against a null DEX::Parser::parse() result 2026-07-11 14:51:53 +02:00
lief-agent 7e4f53f1a3 VDEX: check read_uleb128 2026-07-11 14:51:51 +02:00
lief-agent 648c1634c4 iostream: make edit_as() returning a nullptr instead of an assert 2026-07-11 14:51:48 +02:00
lief-agent fdea2d1662 iostream: size u16string write capacity check in bytes, not chars 2026-07-11 14:51:47 +02:00
lief-agent 1c637e3dde OAT: reserve raw_oat from the segment content, not st_size 2026-07-11 14:51:45 +02:00
lief-agent 34bf0f5880 OAT: null-check on get_symbol() 2026-07-11 14:51:43 +02:00
lief-agent f1bec5a714 DEX: avoid signed overflow 2026-07-11 14:51:42 +02:00
lief-agent 815ba98c26 DEX: fix off-by-one in type-index bounds checks 2026-07-11 14:51:40 +02:00
lief-agent 5f6908d286 DEX: bound the total string data decoded in parse_strings 2026-07-11 14:51:39 +02:00
lief-agent 2f21a83aee COFF: clamp the BIGOBJ section count to a sane maximum 2026-07-11 14:51:37 +02:00
lief-agent e367104b07 COFF: string-table bounds check 2026-07-11 14:51:35 +02:00
lief-agent 8856a904c1 MachO: bound LC_BUILD_VERSION / LC_TWOLEVEL_HINTS / FunctionVariants counts 2026-07-11 14:51:34 +02:00
lief-agent 6bf76c99e6 MachO: fix stray ternary colon in the section-count bound 2026-07-11 14:51:32 +02:00
lief-agent 59c1b1f797 MachO: avoid an abort(); 2026-07-11 14:51:30 +02:00
lief-agent 49617fb66c MachO: bound a segment's section count by its command size 2026-07-11 14:51:29 +02:00
lief-agent d0b10c2cf9 MachO: widen page offset before the multiplication 2026-07-11 14:51:27 +02:00
lief-agent 6822a9ffc5 MachO: bound dyld rebase counts before any SET_SEGMENT opcode 2026-07-11 14:51:24 +02:00
lief-agent 5a136fe72c MachO: stop parsing on a load command with an invalid cmdsize 2026-07-11 14:51:22 +02:00
lief-agent d89b211807 MachO: bound the LC_SYMTAB fallback allocation against the stream 2026-07-11 14:51:20 +02:00
lief-agent 888b83fc25 MachO: bound the LC_DYLD_CHAINED_FIXUPS payload against __LINKEDIT 2026-07-11 14:51:19 +02:00
lief-agent 5bbd1db78e MachO: bound segment/library indexing in DyldInfo opcode printers 2026-07-11 14:51:17 +02:00
lief-agent 44e9b9f03f MachO: fix OOB read in Section::content() for unmapped sections 2026-07-11 14:51:16 +02:00
lief-agent 4d55e3f6d7 PE: Check read_oid() result 2026-07-11 14:51:14 +02:00
lief-agent e0c8a9a47d PE: Bound SEH/GuardCF/CHPE table loops to the available stream 2026-07-11 14:51:12 +02:00
lief-agent 3cc74890ce PE: Fix 32-bit overflow of the COFF string table offset 2026-07-11 14:51:11 +02:00
lief-agent b9881acbde PE: Fix 32-bit over/underflow in the section content padding read 2026-07-11 14:51:09 +02:00
lief-agent 753779b0c9 PE: Fix underflow when computing the section header padding 2026-07-11 14:51:08 +02:00
lief-agent c1190ff78f PE: Cap the number of data directories to MAX_DATA_DIRECTORIES 2026-07-11 14:51:06 +02:00
lief-agent 707d9669b0 PE: Fix issue when processing corrupted delay imports 2026-07-11 14:51:04 +02:00
lief-agent fc65d29434 ELF: Fix underflow 2026-07-11 14:51:03 +02:00
lief-agent ac4df39892 ELF: fix GNU Hash divides by 0 2026-07-11 14:51:01 +02:00
lief-agent d9153dad43 ELF: fix missing return 2026-07-11 14:50:59 +02:00
lief-agent 663c457579 ELF: fix RELR bitmap parsing 2026-07-11 14:50:58 +02:00
lief-agent 0329c63b14 ELF: apply dynamic entry cap in the parse loop 2026-07-11 14:50:56 +02:00
lief-agent 222bc2bb35 ELF: fix section overflow 2026-07-11 14:50:31 +02:00
lief-agent 1ce7a456f2 ELF: clamp DT_VERDEFNUM 2026-07-11 14:50:28 +02:00
lief-agent af0d738b4c ELF: stop verneed/vernaux next-offset accumulators from wrapping 2026-07-11 14:50:25 +02:00
Romain Thomas 0b1567438a ELF: bound note name size against the stream before allocating
Resolve GHSA-p84g-9fv8-52qw
2026-07-11 14:49:41 +02:00
Romain Thomas 2d82cd19e6 security: improve checks 2026-07-11 14:49:32 +02:00
Romain Thomas 4130bdf127 lint: improvements 2026-07-11 11:14:33 +02:00
Romain Thomas 38b8e4a191 doc: fix warnings 2026-07-11 11:10:53 +02:00
Romain Thomas 83bc9ca17d doc: Update Doxygen config 2026-07-11 10:59:13 +02:00
Romain Thomas cb3a013963 Add prek config 2026-07-11 10:31:11 +02:00
lief-agent 7b033b9015 rust: add ELF Section creation 2026-07-11 10:30:29 +02:00
Romain Thomas 5f8f75cae8 rust: allow warnings in tests 2026-07-11 10:25:04 +02:00
Romain Thomas cad40b6cdc Update 2026-07-11 10:18:04 +02:00
Romain Thomas 0c74c540ce lint: format code 2026-07-11 09:45:00 +02:00
Romain Thomas b09d043b26 rust: add clippy config 2026-07-11 09:40:58 +02:00
lief-agent b3bab67254 doc: pull code snippets from compilable/lintable sources 2026-07-11 09:39:07 +02:00
lief-agent 84a0691cac core: add support for ref/value return type 2026-07-11 09:33:36 +02:00
lief-agent 42c0a08910 Fix missing non-const version 2026-07-11 09:33:27 +02:00
lief-agent ce6e49f6aa Fix unused variable 2026-07-11 09:32:17 +02:00
Romain Thomas 0802130a61 elf: sections are not expected in coredump 2026-07-11 07:14:14 +02:00
lief-integration-bot e4880ee9bb rust: add patch_address API
Close #1361
2026-07-11 07:13:01 +02:00
lief-agent b3be170559 Update documentation 2026-07-11 07:11:36 +02:00
lief-agent 2f1c7a6fe0 Replace 'using namespace fmt' with explicit fmt:: qualification
related to #1357
2026-07-11 06:59:38 +02:00
lief-integration-bot 415680ad41 binaryninja: comments are now supported 2026-07-11 06:35:49 +02:00
lief-integration-bot d5099fa16e Update nanobind: 2.13 2026-07-11 06:34:29 +02:00
lief-integration-bot a80d770619 Fix for setting soname
close #1358
2026-07-11 06:26:03 +02:00
lief-integration-bot 11a8ade305 Avoid crash with malformed symbols in debug printing
close #1360
2026-07-11 06:25:46 +02:00
lief-agent b0e8f9d274 Add __match_args__ 2026-07-11 06:24:59 +02:00
lief-integration-bot 1177cbb56c avoid FSCALE conflict
close #1359
2026-07-11 06:24:29 +02:00
Romain Thomas d22542bd4a enhance bound checks 2026-07-11 06:23:01 +02:00
Romain Thomas c71b0cbc87 More lifetime annotations 2026-07-11 06:11:33 +02:00
Romain Thomas ed6a59a878 Fix linter 2026-07-11 06:01:22 +02:00
Romain Thomas d2b15cd295 objc: resolve #1353 and add support for category 2026-07-11 05:30:33 +02:00
lief-integration-bot 5602aa1e84 runtime: initial version
resolve: #1072
2026-07-11 05:18:14 +02:00
Enzo Le VanandEnzo Le Van 93253ef1d3 fix: c++20 ambiguous namespace fmt (#1357)
In addition to https://github.com/lief-project/LIEF/pull/1339 this commit fix PE files.
LIEF can now be built with CXX_STANDARD set to 20

Co-authored-by: Enzo Le Van <enzo.le-van@asterios-technologies.com>
2026-07-05 21:20:42 +02:00
Romain Thomas e7d2824ada Lint & format 2026-06-28 20:41:49 +02:00
lief-agent 3d3a2c1503 DEX/VDEX/ART: parse version field without throwing
Mythos: finding 16
2026-06-28 20:35:33 +02:00
lief-agent c457dcff11 OAT: validate version digits before numeric conversion
Mythos: finding 15
2026-06-28 20:35:31 +02:00
lief-agent 0fb5f726b8 MachO: fix NoteCommand::owner_str
Mythos: finding 14
2026-06-28 20:35:29 +02:00
lief-agent ec1f0e5184 OAT: bound header key parsing against unterminated key/value store
Mythos: finding 13
2026-06-28 20:35:28 +02:00
lief-agent 3db4f48c96 ELF: bound Android packed relocations against malformed count
Mythos: finding 12
2026-06-28 20:35:26 +02:00
lief-agent 1ee1f04d9f MachO: bound dyld chained-fixup walker against non-terminating chains
Mythos: finding 11
2026-06-28 20:35:25 +02:00
lief-agent 1c038d2aea PE: bound enclave imports against malformed count and entry size
Mythos: finding 10
2026-06-28 20:35:23 +02:00
lief-agent ad8111dd07 OAT: cap class-offset reservations against malformed counts
Mythos: finding 9
2026-06-28 20:35:21 +02:00
lief-agent 71b451d833 MachO: fix export trie pretty printer against cyclic tries
Mythos: finding 8
2026-06-28 20:35:20 +02:00
lief-agent b5182ec963 DEX: cap string table reservation against malformed count
Mythos: finding 7
2026-06-28 20:35:18 +02:00
lief-agent 1acd918396 DEX/VDEX: bound bytecode walkers against malformed instructions
Mythos: finding 6
2026-06-28 20:35:17 +02:00
lief-agent 1e8ca39b4d OAT: validate oatdata/oatexec gap with checked arithmetic
Mythos: finding 5
2026-06-28 20:35:15 +02:00
lief-agent 19ab30f42c DEX: check for empty empty string
Mythos: finding 4
2026-06-28 20:35:13 +02:00
lief-agent 5934632c9a PE: safeguard truncated resource directory entries
Mythos: finding 3
2026-06-28 20:35:12 +02:00
lief-agent 1ca94b13a0 MachO: safeguard dyld rebase/bind opcode counts
Mythos: finding 2
2026-06-28 20:35:10 +02:00
lief-agent 7b9de7b6c3 Strengthen ULEB128/SLEB128
Mythos: finding 1
2026-06-28 20:35:01 +02:00
Romain Thomas 3f51514f64 Fix tests 2026-06-28 17:04:37 +02:00
Romain Thomas 20a0227742 Resolve #1356 2026-06-28 12:46:42 +02:00
Romain Thomas ab1e2bb1e8 PDB/DWARF: option to prefix attributes with their offset 2026-06-28 09:52:59 +02:00
Romain Thomas 5257787eb0 MachO: support writing big endian binaries
Resolve #1355
2026-06-27 19:54:55 +02:00
Romain Thomas b784c6449a core: spread LIEF_LIFETIMEBOUND on span returning function 2026-06-27 19:13:51 +02:00
lief-integration-bot 57b10a2eec asm: implement fmt::Display Instruction 2026-06-27 18:47:42 +02:00
lief-integration-bot f4835af59f Avoid duplicated entries 2026-06-27 18:47:29 +02:00
lief-integration-bot 28508c36bc binaryninja: adapt dwarf-export to BN 5.4 FunctionParameter location API 2026-06-27 18:46:56 +02:00
lief-integration-bot 823272a6cd Enhance lifetime annotations 2026-06-27 18:46:12 +02:00
Romain Thomas 90a9262d48 Skip test_pe_authenticode_check on GHA 2026-06-27 18:14:50 +02:00
Romain Thomas ac2a412d71 Check is_dir() against the expanduser + resolve 2026-06-27 16:24:18 +02:00
Romain Thomas be381b97b7 tests: fix missing private marker 2026-06-27 16:23:41 +02:00
Romain Thomas 00341b040e doc: reorder the sections 2026-06-20 21:43:27 +02:00
dependabot[bot] 3c0bd971a5 build(deps): bump pydantic-settings in /scripts/metrics (#1354)
Bumps [pydantic-settings](https://github.com/pydantic/pydantic-settings) from 2.12.0 to 2.14.2.
- [Release notes](https://github.com/pydantic/pydantic-settings/releases)
- [Commits](https://github.com/pydantic/pydantic-settings/compare/v2.12.0...v2.14.2)

---
updated-dependencies:
- dependency-name: pydantic-settings
  dependency-version: 2.14.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-20 21:12:34 +02:00
Romain Thomas d7dc3e8ee0 DWARF/PDB: use a pointer instead of a reference 2026-06-20 20:30:22 +02:00
Romain Thomas 8d7f5e06a5 Fix forward declaration 2026-06-20 16:33:06 +02:00
lief-integration-bot c7bc5f65e2 extended: add support to emit C/C++ declaration from DWARF & PDB 2026-06-20 16:22:02 +02:00
Romain Thomas e6305498dc Fix tests 2026-06-20 16:21:46 +02:00
Romain Thomas 4ab6992632 rust: pin workspace dependencies to full major.minor.patch 2026-06-20 16:01:27 +02:00
Romain Thomas 76093f3a39 formatting 2026-06-20 14:17:28 +02:00
Romain Thomas cf7d1ccca5 Add missing opcodes 2026-06-20 14:17:17 +02:00
lief-agent 234ecccefc MachO: fix add_exported_function offset & detect it in check_layout 2026-06-20 14:02:52 +02:00
Romain Thomas d1595d7949 add operands info for riscv, ebpf, mips & powerpc 2026-06-20 13:33:42 +02:00
Romain Thomas 85939c66a1 Update tests according to extended updates 2026-06-20 13:28:59 +02:00
Romain Thomas 7a4664a795 Fix missing LIEF_LIFETIMEBOUND 2026-06-20 12:23:33 +02:00
Romain Thomas 1c419a2c92 Add option to run extended tests (only) 2026-06-20 11:01:12 +02:00
lief-integration-bot 3d0ce7545e macho: fix extra byte written after LC_UNIXTHREAD/LC_THREAD state
Fix: #1344
2026-06-20 09:15:34 +02:00
Romain Thomas e9a680377e Resolve #1333 2026-06-20 09:14:06 +02:00
Romain Thomas 340c0ec674 macho: add support for LC_LAZY_LOAD_DYLIB_INFO 2026-06-20 07:42:03 +02:00
Romain Thomas 2cf8334aa0 macho: enhances support for LC_FUNCTION_VARIANTS_{FIXUPS} 2026-06-20 06:15:04 +02:00
Romain Thomas 69876ad0d9 macho: fix typo 2026-06-20 05:40:33 +02:00
iTrooz e09ecffb8f doc: use get_function_address() in ELF transformation tutorial (#1352)
This is a QoL change in ths tutorial, that will allow users to automatically retrieve the address of the function they want to export
2026-06-17 21:56:51 +02:00
Tim Schumacher 0947d84c73 Refactor shifting logic to warn about unspecified shift behavior (#1335)
* Refactor shifting logic to warn about unspecified shift behavior

With the correct compiler settings this should work at build and at
runtime.

* Explicitly mention all known DynamicEntry tags
2026-06-15 18:24:41 +02:00
t-dr 1182334831 add #include <sstream> for gcc-17 (#1351) 2026-06-15 06:08:55 +02:00
Romain Thomas f308f19af5 Fix missing error 2026-06-14 16:01:29 +02:00
Romain Thomas 1a94b7437b Fix Clang strict lifetime-safety build errors 2026-06-14 15:44:24 +02:00
Romain Thomas d335521fda QA: BinaryNinja plugins 2026-06-14 15:43:02 +02:00
Romain Thomas 70caa0db77 binaryninja: fix clang-tidy warnings in plugin sources 2026-06-14 15:42:25 +02:00
Romain Thomas f9b6b77101 elf: add support for AArch64 attributes
Resolve: #1350
2026-06-07 07:15:16 +02:00
Romain Thomas 9233847d66 mark Nanobind headers as system headers 2026-06-07 06:01:33 +02:00
Romain Thomas 07a94b09da qa: fix linter 2026-06-07 05:58:03 +02:00
Romain Thomas 0d91852ac0 elf: resolve #1333 2026-05-23 12:45:30 +02:00
Romain Thomas f0ff7ee3b4 ELF: use = value syntax 2026-05-23 12:28:59 +02:00
lief-agent d18c174062 cleanup: remove unused code 2026-05-23 11:37:58 +02:00
lief-agent 8835d034e0 formats code 2026-05-23 11:33:21 +02:00
lief-agent f714ffc14b cmake: update cpack config 2026-05-23 11:30:42 +02:00
Romain Thomas e23553c613 rust: switch FFI layer from autocxx to plain cxx.rs
Replace the stale autocxx-based binding generator with
cxx.rs bridges.

Bump the MSRV from 1.74.0 to 1.85.0 and rename `api/rust/cargo/` to
`api/rust/crates/`.

close: #1332
2026-05-23 11:26:06 +02:00
lief-integration-bot 2775086371 lint: fix lint error 2026-05-23 10:05:14 +02:00
lief-integration-bot 421a732e8a lint: update clang-tidy rules 2026-05-23 09:44:13 +02:00
Romain Thomas 56603ca2f6 rust: fix compilation error 2026-05-23 09:30:32 +02:00
Romain Thomas da362e6a35 python: fix abi3 compilation 2026-05-23 09:22:51 +02:00
Romain Thomas 807947f7e0 cmake: raise an exception if the directory does not exist 2026-05-23 09:18:56 +02:00
lief-agent a920267cba DWARF/PDB: replace using Type::Type with perfect-forwarding
This change is mainly to address MS ABI issue
2026-05-23 09:01:26 +02:00
lief-agent 478de7829b core: normalize the iterator interface 2026-05-23 08:45:45 +02:00
Romain Thomas d9e1137cb9 lint: disable bugprone-signed-bitwise 2026-05-23 08:31:29 +02:00
bpint f8ca472f7d Fix ELF note section corruption (#1349)
* Fix ELF note section corruption
2026-05-23 08:22:53 +02:00
Josef Johansson d3e6a7986e doc/sphinx/tutorials/12_elf_coredump.rst: Fix typo (#1347) 2026-05-19 20:57:25 +02:00
Romain Thomas 3e9d44510a logging: use std::unique_ptr instead of raw pointer.
This change avoids a conflict between the global `std::mutex` and its
usage in `std::atexit`
2026-05-16 18:45:18 +02:00
lief-integration-bot 497b0c012e pe(signature): workaround CMS CertificateChoices 2026-05-16 18:43:36 +02:00
lief-integration-bot 57a0b95070 pe(debug): add support for SPGO/PGI/PGU 2026-05-16 18:43:28 +02:00
lief-integration-bot e216760b76 python: fix name 2026-05-16 08:38:40 +02:00
lief-integration-bot 80e04d4b43 plugins(binaryninja): support non FragmentTypeClass versions 2026-05-16 08:38:30 +02:00
Frank 164bd1f160 Update rust crates dependencies up to MSRV 1.74.0 (#1341)
* Specify MSRV in Cargo.toml and cleanup

* Bump dependencies

* Bump locked versions

* Fix tools dependencies

* Fix examples dependencies

* Fix warnings in examples

* Downgrade cxx to 1.0.117
2026-05-15 21:31:37 +02:00
Avery 7c3369add4 fix: ensure endianness when parsing inner ELF streams (#1338)
Fixes #795
2026-05-09 19:06:03 +02:00
Enzo Le Van 47467ec03f fix: COFF in C++20 ambiguous namespace 'fmt' (#1339)
This commit fixes an issue for resolving the fmt namespace in c++20. The original error is something like error: static assertion failed: std::formatter must be specialized for each type being formatted
2026-05-09 19:04:34 +02:00
Romain Thomas 82b9718f31 lief-extended: mention direct-link from the **History** 2026-04-26 22:01:28 +02:00
Romain Thomas 2d7805d86e binaryninja: handle FragmentTypeClass 2026-04-26 19:23:18 +02:00
Romain Thomas 53a656aba3 rust: avoid reserved keyword
from PR #1332
2026-04-26 09:48:37 +02:00
Romain Thomas cd3553733b Revert "udpate openssl and openssl-sys without bumping the lock version"
This reverts commit 98240b8210.
2026-04-25 11:13:54 +02:00
Romain Thomas 19cd0cbc38 Revert "rust: update deps"
This reverts commit 5537c2552f.
2026-04-25 11:13:42 +02:00
Romain Thomas 1a6638f644 Revert "rust: downgrade hyper-rustls to keep msrv to 1.74"
This reverts commit 5cfdb05540.
2026-04-25 11:13:24 +02:00
Romain Thomas 5cfdb05540 rust: downgrade hyper-rustls to keep msrv to 1.74 2026-04-25 10:05:33 +02:00
lief-agent 835132af6c examples: update and normalize Python examples 2026-04-25 09:44:02 +02:00
lief-agent 255cd71927 Update 2026-04-25 09:39:23 +02:00
Romain Thomas ac033c4bd0 Fix header 2026-04-25 09:22:10 +02:00
Romain Thomas 401486a6b8 test: forward pytest retcode 2026-04-25 09:14:03 +02:00
Romain Thomas a2484a43b3 python: guard mutating bindings with nb::lock_self()
Ensure Python binding thread-safety on methods that
mutate the underlying binary. Note: this coverage is not exhaustive
but bootstrap the support for free-threaded Python builds.

resolve #1255
2026-04-25 08:24:45 +02:00
Romain Thomas 38ec1e378b mbedtls: ensure mbedtls is thread-safe 2026-04-25 07:45:31 +02:00
Romain Thomas 5537c2552f rust: update deps 2026-04-25 07:21:02 +02:00
Romain Thomas 98240b8210 udpate openssl and openssl-sys without bumping the lock version
related to #1331
2026-04-25 07:03:12 +02:00
dependabot[bot] 9c2e9facc9 build(deps): bump lxml from 6.0.2 to 6.1.0 in /scripts/metrics (#1329)
Bumps [lxml](https://github.com/lxml/lxml) from 6.0.2 to 6.1.0.
- [Release notes](https://github.com/lxml/lxml/releases)
- [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt)
- [Commits](https://github.com/lxml/lxml/compare/lxml-6.0.2...lxml-6.1.0)

---
updated-dependencies:
- dependency-name: lxml
  dependency-version: 6.1.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-25 06:55:58 +02:00
Romain Thomas 418e4756d7 doc: mention Android support 2026-04-25 06:54:58 +02:00
Romain Thomas 373317efc3 core: guard mutable fields with mutex
related to #1255
2026-04-25 06:39:03 +02:00
Romain Thomas bc1a98bb3b tests: add pytest-run-parallel and mark thread-unsafe tests
related to #1255
2026-04-25 05:47:44 +02:00
Romain Thomas 1b964afe28 clang-tidy: remove portability-avoid-pragma-once
This is allowed in non public headers
2026-04-25 05:43:25 +02:00
Romain Thomas b1ac356f2c Guard ts_to_str 2026-04-19 12:14:17 +02:00
Romain Thomas d41f9b7aa2 Disable caching 2026-04-19 12:12:25 +02:00
Romain Thomas 305fdd7204 Fix TSAN runtime library 2026-04-19 12:10:59 +02:00
Romain Thomas f5b7164f45 guard with mutex 2026-04-19 11:57:20 +02:00
Romain Thomas daa95b0530 add mutex for the logging API 2026-04-19 11:55:29 +02:00
Romain Thomas 6269d5d9bc fix: div by zero 2026-04-19 11:15:17 +02:00
Romain Thomas 991586a1ed macho: fix export trie recursion 2026-04-19 10:45:04 +02:00
Romain Thomas 0f2deb05c9 enable all the features 2026-04-19 10:15:02 +02:00
Romain Thomas dfcad82f44 fmt: fix formatting 2026-04-19 09:45:53 +02:00
Romain Thomas 43830eacb1 sanitizer: fix asan 2026-04-19 09:44:37 +02:00
Romain Thomas 6933e5ecab fix memory leak 2026-04-19 09:30:31 +02:00
Romain Thomas cb421fb41c decrease max recursion depth 2026-04-19 09:04:26 +02:00
lief-agent db9c1bd4db tests: more coverage
AI DISCLAIMER: These new tests are 100% AI-generated and humman-reviewed
2026-04-18 21:45:33 +02:00
Romain Thomas 25bddf6019 pe: fix recursion issue found with Codex 5.3 2026-04-18 21:37:02 +02:00
Romain Thomas bed43eb08c python: prefers ft_mutex over the regular std::mutex
related to #1255
2026-04-18 15:12:57 +02:00
Romain Thomas 3cb815ce5d Enable coverage flags 2026-04-18 15:06:08 +02:00
Romain Thomas 48d241cefa fix lifetime 2026-04-18 14:17:32 +02:00
Romain Thomas f5a4f6b272 qa: remove unused headers 2026-04-18 14:17:31 +02:00
dependabot[bot] 21cdf9bac1 build(deps): bump pytest from 9.0.2 to 9.0.3 in /tests (#1327)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 9.0.2 to 9.0.3.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/9.0.2...9.0.3)

---
updated-dependencies:
- dependency-name: pytest
  dependency-version: 9.0.3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-18 13:03:30 +02:00
Romain Thomas c47df2999e Fix CI 2026-04-18 13:02:24 +02:00
Romain Thomas 1cc1b60bf9 Add coverage 2026-04-18 05:18:59 +02:00
Romain Thomas 2274e39c00 Bump version 2026-04-12 21:39:53 +02:00
lief-agent d15b1c7dc6 elf: implement GNU_PROPERTY_1_NEEDED support 2026-04-12 20:18:38 +02:00
Romain Thomas e9764969d5 python: introduce lief-extra-compilation-flags 2026-04-12 19:17:04 +02:00
Romain Thomas 1915b921de Remove TODO 2026-04-12 19:02:53 +02:00
lief-agent b000c38366 elf/macho: modernize Binary::print 2026-04-12 18:03:51 +02:00
Romain Thomas a8b11cf158 pe: add public key info 2026-04-12 14:26:47 +02:00
lief-agent 032780721e Fix typo and standardize comments 2026-04-12 13:11:26 +02:00
lief-agent 9626dda2ba Add LIEF_LIFETIMEBOUND annotations for Clang lifetime analysis
Add a `LIEF_LIFETIMEBOUND` macro wrapping `[[clang::lifetimebound]]` to
leverate lifetime analysis [1].

[1]: https://clang.llvm.org/docs/LifetimeSafety.html
2026-04-12 12:20:31 +02:00
Romain Thomas 2c8b087757 Fix visibility 2026-04-12 09:33:34 +02:00
Romain Thomas 324d102afa Fix compilation error 2026-04-12 09:03:34 +02:00
lief-agent c9f36fc09e rust: improve ELF note bindings 2026-04-12 08:59:29 +02:00
lief-agent e3015ebbf7 rust: expose logging::get_level and logging::Scoped 2026-04-11 15:06:36 +02:00
Romain Thomas 94575d302a linter: rustfmt 2026-04-11 14:35:48 +02:00
Romain Thomas eb6611bca1 ignore third-party/ 2026-04-11 14:13:04 +02:00
lief-agent b4eb53e0fc QA: enable clang-tidy 2026-04-11 13:11:56 +02:00
lief-agent 2ad74fed83 QA: update tests/ code for type checking 2026-04-11 12:41:55 +02:00
lief-agent ec3920229a python: fix typing stubs 2026-04-11 07:07:28 +02:00
lief-agent d35a0ad211 python: fix typo 2026-04-11 07:06:41 +02:00
lief-agent 966e456616 clang-format: update 2026-04-11 07:05:35 +02:00
Romain Thomas 7897f7b09d cmake: ensure that dependencies are not running install 2026-04-11 06:33:40 +02:00
Romain Thomas 762d77f11c Fix warning 2026-04-11 06:02:53 +02:00
Romain Thomas aca974e752 cmake: modernize CMake build system for cmake_minimum_required 3.24 2026-04-05 16:19:47 +02:00
lief-agent 6fa0be53dc doc: improve doc and fix typos 2026-04-05 16:07:17 +02:00
lief-agent 0e4f68093e core: standardize log messages across the codebase 2026-04-05 10:50:21 +02:00
lief-agent 0dfd129b47 Fix color 2026-04-05 08:52:07 +02:00
Romain Thomas 8c0c4c48ff macho: add tlv_initial_content_range()
Abstract the TLV initial content range computation from
`LayoutChecker::check_tls()`
2026-04-05 08:30:51 +02:00
Romain Thomas dfa8c70336 Fix bugs and improve filter_iterator in iterators.hpp 2026-04-05 08:01:14 +02:00
lief-agent c5193a4817 code cleaning 2026-04-05 08:49:52 +02:00
Romain Thomas fee8f64a03 macho: add support for ThreadLocalVariables
Introduce `ThreadLocalVariables` that represents
`S_THREAD_LOCAL_VARIABLES` sections. It exposes the array of TLS
descriptors (Thunk) that dyld uses to lazily initialize thread-local
storage.
2026-04-05 06:30:30 +02:00
Romain Thomas 96fcacf722 elf(core): update DataHandler::from_stream 2026-04-04 20:53:41 +02:00
Romain Thomas 4384b3aba3 Disable PCH 2026-04-04 14:46:31 +02:00
Romain Thomas 492f16baf8 Bootstrap clangd config 2026-04-04 13:44:21 +02:00
lief-agent b3d9008614 core: add as_writable helper 2026-04-04 13:25:54 +02:00
lief-agent f02175670b python: add byte support for dump. 2026-04-04 13:13:08 +02:00
Romain Thomas c9340c36e9 LLVM 22.1.3 update 2026-04-04 11:26:04 +02:00
lief-agent 66fb8e54fa Replace has_private_samples() with pytest.mark.private 2026-04-04 11:13:00 +02:00
Romain Thomas ce04422eda tests: add private marker 2026-04-04 11:01:04 +02:00
Romain Thomas 311ed4f125 macho: add cast() helper 2026-04-04 10:51:12 +02:00
Romain Thomas 5e0fd64160 remove unused include 2026-04-04 10:45:57 +02:00
Romain Thomas 7b217e964a macho: improve code 2026-04-04 10:31:09 +02:00
Andrea Pisaturo 4ed300ac71 Fix typo in 'Timestamp' output format (#1323) 2026-04-04 10:28:09 +02:00
dependabot[bot] 3fb34c778b Bump pygments from 2.19.2 to 2.20.0 in /doc (#1322)
Bumps [pygments](https://github.com/pygments/pygments) from 2.19.2 to 2.20.0.
- [Release notes](https://github.com/pygments/pygments/releases)
- [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES)
- [Commits](https://github.com/pygments/pygments/compare/2.19.2...2.20.0)

---
updated-dependencies:
- dependency-name: pygments
  dependency-version: 2.20.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-04 10:27:56 +02:00
Romain Thomas 4db4e3d62c cmake: remove LIEF_USE_PCH since redundant with CMAKE_DISABLE_PRECOMPILE_HEADERS 2026-04-04 10:23:51 +02:00
lief-agent 986536909b Fix format 2026-04-04 10:21:43 +02:00
Romain Thomas 6ff62e6303 Add downcasting helpers 2026-04-04 09:17:46 +02:00
Romain Thomas 03b153ba17 Refactor u16tou8 to accept raw char16_t buffer 2026-04-04 08:01:35 +02:00
Romain Thomas 80e790d9a7 Update default config 2026-03-29 10:22:08 +02:00
Romain Thomas d91e91d6b9 more compile time improvment 2026-03-28 23:18:12 +01:00
Romain Thomas d795497828 Improve pch 2026-03-28 18:28:13 +01:00
Romain Thomas bc6a8514e3 compilation: enable precompiled headers (PCH)
Add precompiled headers to the main library, Python bindings,
and unit tests to improve compilation times.
2026-03-28 17:24:44 +01:00
Romain Thomas 3dbce30ac9 more $LASTEXITCODE 2026-03-28 16:53:47 +01:00
lief-agent 57671447c6 elf: fix should_swap() for MSVC (missing __BYTE_ORDER__)
MSVC does not define `__BYTE_ORDER__`, causing the entire #ifdef block
to be skipped and the function to always return false. This meant
big-endian ELF files were never byte-swapped on MSVC builds.
2026-03-28 16:44:46 +01:00
Romain Thomas 7c8a0c7c05 compilation: do not force -O0 -g when build type is Debug 2026-03-28 16:35:54 +01:00
Romain Thomas 9ecdfca369 fix: -Wuninitialized 2026-03-28 16:28:15 +01:00
Romain Thomas fe9edfb041 ci: exit with last exit code 2026-03-28 16:25:43 +01:00
Romain Thomas d68e913e09 Disable profile for Windows tests 2026-03-28 15:46:41 +01:00
Romain Thomas 884e1046e5 Add LIEF_MAYBE_UNUSED compiler attribute macro
Leverages C++17 `[[maybe_unused]]` when available, with fallbacks to
`__attribute__((unused))` for GCC/Clang and `__pragma(warning(suppress))`
for MSVC on older standards.
2026-03-28 15:46:04 +01:00
Romain Thomas cc601d961f Pin version 2026-03-28 15:33:18 +01:00
Romain Thomas 1ec74f52a9 Update workflows 2026-03-28 14:51:14 +01:00
dependabot[bot] b7d8074351 Bump requests from 2.32.3 to 2.33.0 in /tests (#1320)
Bumps [requests](https://github.com/psf/requests) from 2.32.3 to 2.33.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.32.3...v2.33.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-version: 2.33.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-28 09:38:22 +01:00
dependabot[bot] 29635eb4db Bump requests from 2.32.5 to 2.33.0 in /doc (#1321)
Bumps [requests](https://github.com/psf/requests) from 2.32.5 to 2.33.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.32.5...v2.33.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-version: 2.33.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-28 09:38:15 +01:00
Romain Thomas 3172dd1992 Fix macOS compilation issue 2026-03-28 07:39:51 +01:00
Romain Thomas 4fa7229678 Add .clang-format configuration matching project style 2026-03-28 07:35:23 +01:00
lief-agent 767fe8253a rust: more bindings 2026-03-28 07:01:51 +01:00
Romain Thomas ff51a337c5 Fix missing COFF 2026-03-28 06:33:04 +01:00
lief-agent 9ac21a5841 Modernize code 2026-03-28 06:30:58 +01:00
lief-agent b17fb37c21 Improve log messages and use fmt alternate hex form 2026-03-28 06:01:23 +01:00
lief-agent 9ae756af30 macho: Add Rust bindings for MachO::ParserConfig 2026-03-28 05:04:13 +01:00
Romain Thomas 88a4d550cd lint: fix warnings 2026-03-21 18:17:07 +01:00
Romain Thomas d336834b11 fix: correct handling of the zero case 2026-03-20 18:17:48 +01:00
Romain Thomas 12e80c5b1d fix: va_end conflicts with variable argument lists usage 2026-03-20 18:05:05 +01:00
Romain Thomas 8da5388b94 pe: add address range checks for LoadConfiguration fields
Add VA range validation for all address fields in LoadConfiguration
that were previously unchecked. It validates that
each address falls within [imagebase, imagebase + virtual_size).
2026-03-20 18:00:41 +01:00
Romain Thomas 69219fdbe7 pe: add setters for iat_value/ilt_value 2026-03-20 16:27:47 +01:00
Romain Thomas f0610149b0 rust: add support for aarch64-linux-android and x86_64-linux-android 2026-03-20 15:56:35 +01:00
Romain Thomas d1382c1863 Bootstrap runtime options 2026-03-20 15:40:36 +01:00
Romain Thomas 347b1b9c8f tests: add pytest slow marker with --skip-slow option 2026-03-19 18:19:40 +01:00
Romain Thomas be0ee74c14 Fix include 2026-03-19 17:14:29 +01:00
lief-agent 35de7f3592 Improve testing log API 2026-03-19 17:08:49 +01:00
Chris Finazzo 92be25bb62 Update the README to improve readability (#1319) 2026-03-19 16:37:32 +01:00
Romain Thomas 1502b48a17 Fix type hint 2026-03-19 09:25:39 +01:00
Romain Thomas 1f190a9fa1 Change level to info 2026-03-19 09:04:58 +01:00
Romain Thomas 7ac083bb73 Add contextmanager API for log level 2026-03-19 07:56:02 +01:00
Romain Thomas 3d86f07199 Improve typing 2026-03-19 07:02:21 +01:00
Romain Thomas daa4b238f4 Resolve #743 2026-03-19 06:41:04 +01:00
Romain Thomas 978dcc3b1a Fix pragma 2026-03-18 16:14:31 +01:00
Romain Thomas 1fafa1745b Update latest version 2026-03-18 08:13:03 +01:00
Romain Thomas d295ee4d8b tests: fix alignment 2026-03-18 06:04:07 +01:00
Romain Thomas f986c6dd17 Resolve #1318 2026-03-17 17:11:44 +01:00
Romain Thomas cfdcc42fcd Fix warnings 2026-03-17 17:11:39 +01:00
Romain Thomas 22894bef5b clang-tidy fixes 2026-03-17 16:13:57 +01:00
Romain Thomas 59eea4c1fc Add Python 3.14 2026-03-17 15:42:43 +01:00
Romain Thomas 07b7d33d06 Update workflows 2026-03-17 15:12:14 +01:00
Romain Thomas 702f4e51b8 Resolve #1310 2026-03-17 15:01:41 +01:00
Romain Thomas 62700dfd05 Update workflows 2026-03-17 14:53:00 +01:00
Romain Thomas bff40d626c Skip NOBITS sections in layout calculations and improve index retrieval
Skips `NOBITS` sections (like `.bss` and `.tbss`) when determining the last
section offset in `LIEF::ELF::Binary::last_offset_section()`.
Since these sections do not occupy space in the file, including them could lead to an unnecessary
increase in the final binary size.
2026-03-17 14:01:23 +01:00
Romain Thomas 87cfc06382 Fix alignment for PHDR/SHDR and improve TLS/RELR handling
This change addresses several issues related to ELF reconstruction.
It ensures compatibility with stricter loaders (like Android's linker)
and fix and issue with `STT_TLS` symbols

Resolve #1315
2026-03-17 14:00:51 +01:00
Romain Thomas 6c2e39cfc0 modernize python API 2026-03-17 14:00:48 +01:00
Romain Thomas 70c842f726 enhance testing 2026-03-17 09:01:40 +01:00
Romain Thomas e1844d4ecc Add check_layout for ELF
This commit implements the check_layout function for ELF binaries
similar to PE and Mach-O. This function aims to ensure that the
ELF binary is consistent according to various loader (e.g., Linux, Android)
2026-03-17 08:30:21 +01:00
Romain Thomas 25dbebb658 Disable hash-opt by default 2026-03-16 11:48:59 +01:00
FrankandRomain Thomas 658297344b Add Rust bindings to modify PE imports and sections (#1317)
* Add set_name to PE Import

* Add creation and adding of PE Section

* Add functions to change Section

* Add docs for adding a section through Rust

* minor refactoring

---------

Co-authored-by: Romain Thomas <me@romainthomas.fr>
2026-03-16 09:58:51 +01:00
FrankandRomain Thomas cb71d0d640 Add Rust bindings to modify MachO libraries and paths (#1316)
* Add set_name to MachO Dylib

* Add rpaths to MachO Binary

* Add set_path to MachO RPath

* Add creation and adding of RPath

* Add remove_commands_by_type to MachO Binary

* Refactor LoadCommandTypes from_value to use From trait

* Add docs for new Rust bindings

* Fix code in documentation

* Some minor refactoring

---------

Co-authored-by: Romain Thomas <me@romainthomas.fr>
2026-03-16 09:50:26 +01:00
Itamar GafniandClaude Opus 4.6 6f21d3902a fix(PE): Add bounds to import thunk parsing to prevent hangs
The import thunk loop in Parser.tcc has no iteration limit and calls
peek_string_at() with no max length. A malformed PE with an unterminated
IAT causes the loop to process hundreds of thousands of fake entries,
each triggering multi-megabyte string reads — hanging indefinitely.

This is a DoS vector against any system using LIEF for PE analysis.

Fixes:
1. Cap the thunk loop at MAX_IMPORT_ENTRIES (65536) per DLL
2. Bound peek_string_at to MAX_IMPORT_NAME_SIZE (4096) bytes
3. Warn when the limit is hit so users know the IAT was truncated

Follows the existing pattern used by MAX_TLS_CALLBACKS and
MAX_RELOCATION_ENTRIES.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 09:45:25 +01:00
Romain Thomas 14f941bab4 optimize the ffigen process by running autocxx_build::Builder
only when `autocxx_ffi.rs` changed
2026-03-08 22:03:47 +01:00
Romain Thomas 2e94b01eb8 Force link against libpythonX.YZ.so on Android
It seems that Android does not support `undefined dynamic_lookup`
as we do for macOS and Linux. Therefore, we force link with the shared
library
2026-03-08 15:15:45 +01:00
Romain Thomas 3847142f1e add support to create a FAT MachO from binaries
Resolve: #1271
2026-03-08 14:10:57 +01:00
lief-agent 83bdf9c8d4 Add support for ELF DT_AUXILIARY and DT_FILTER
Resolve #1159
2026-03-08 11:33:50 +01:00
Romain Thomas 7f01c7e580 expose more functions 2026-03-08 11:29:55 +01:00
Romain Thomas 6fe77f843b Add 0.17.5 2026-03-08 11:28:26 +01:00
Romain Thomas 136aeff77e Fix dynamic entry shifting for Android relocations
Android-specific relocation dynamic entry tags (`ANDROID_REL`, `ANDROID_RELA`,
`ANDROID_RELR`) were missing in `Binary::shift_dynamic_entries()`

Resolve #1309
2026-03-08 07:50:27 +01:00
Charles BousseauandRomain Thomas 63d5500ee7 Add TLSDESC_PLT and TLSDESC_GOT to ELF dynamic tags (#1311)
* Add TLSDESC_PLT and TLSDESC_GOT to ELF dynamic tags

---------

Co-authored-by: Romain Thomas <me@romainthomas.fr>
2026-03-07 20:57:50 +01:00
Romain Thomas 1e40f986b8 Fix #1313 2026-03-07 20:43:10 +01:00
lief-agent 76df01f96a Improve the documentation 2026-03-07 20:32:54 +01:00
Romain Thomas cf890cee8d Fix test 2026-03-07 15:05:04 +01:00
lief-agent cb2a0948d4 Fix ruff lint warnings 2026-03-07 13:50:12 +01:00
lief-agent cbf06a5033 update the documentation 2026-02-28 11:07:12 +01:00
Romain Thomas 4396aec5e9 Update installation 2026-02-22 16:32:59 +01:00
Romain Thomas d6f11cf5cd Update intro 2026-02-22 14:20:50 +01:00
Romain Thomas bc5a0c7254 Fix description 2026-02-22 14:16:45 +01:00
Romain Thomas 05989e1dac Update doc 2026-02-22 12:36:06 +01:00
Romain Thomas b4e355f532 Update the iterator interface to provide a hint on its length 2026-02-22 05:06:36 +01:00
Romain Thomas 0ab32ac170 ensures we correctly handle nullptr return value 2026-02-21 20:56:52 +01:00
Romain Thomas 61d2923941 Add logging macros 2026-02-21 18:52:54 +01:00
Romain Thomas 9f6c798506 Make stable ABI & free threading option aware of LIEF_STABLE_ABI/LIEF_FREE_THREADED 2026-02-21 18:22:37 +01:00
Romain Thomas 872a518693 Update version 2026-02-21 11:02:10 +01:00
Romain Thomas 10a0da37e7 Update changelog 2026-02-21 11:00:12 +01:00
sigewinnefish cd639a011e cmake: LIEFCompilerFlags problems on Windows clang-cl (#1306)
* ignore add clang warning flags if msvc clang

* clang-cl use same as msvc warning flags
2026-02-21 08:01:32 +01:00
Romain Thomas ab3b10bfa1 Disable stable ABI for testing 2026-02-15 17:41:37 +01:00
Romain Thomas 8b659ba3ec better support for EFI/PE-COFF binary like bzImage
resolve #1293
2026-02-15 17:20:45 +01:00
Romain Thomas 91bc6dfd6e Fix typo 2026-02-15 16:20:28 +01:00
Romain Thomas 007646df14 Initiate options to enable free-threaded build
Related to #1255
2026-02-15 16:13:43 +01:00
Romain Thomas 9b647bdd58 Enable stable ABI in the CI 2026-02-15 16:13:36 +01:00
Romain Thomas 188a1231a0 Add LIEF_DOC_MINIFY to driver the doc minification 2026-02-15 12:46:33 +01:00
Romain Thomas f155e94363 Enable stable ABI in the CI 2026-02-15 12:21:53 +01:00
Romain Thomas bedb668860 Add option to enable the stable ABI 2026-02-15 11:54:25 +01:00
Romain Thomas d09a8d53cd Update nanobind 2026-02-15 11:54:14 +01:00
Romain Thomas d19b32f006 Fix version 2026-02-14 21:22:16 +01:00
Romain Thomas a0e7d68f3b Add support for using stable API 2026-02-14 21:21:09 +01:00
Romain Thomas ef3694ba7e Fix typing 2026-02-14 20:29:29 +01:00
Romain Thomas dfc7fb6016 Revert minify_option 2026-02-14 11:27:16 +01:00
Romain Thomas e4ceecd6c4 Add support to insert an import at a specific position
close #1298
2026-02-14 11:09:22 +01:00
Romain Thomas 9c4204a358 Enhance API for MachO fileset
Fix #1297
2026-02-14 11:09:17 +01:00
Romain Thomas e46f1ded86 Refactor Rust macros 2026-02-14 11:09:11 +01:00
Romain Thomas f36b5a5410 Enhance testing 2026-02-14 11:09:05 +01:00
Romain Thomas 28d64ba71b initial support to generate C/C++ code from DWARF/PDB 2026-02-14 11:08:59 +01:00
Romain Thomas 64d13d63e6 enhance the API for PDB LF_ONEMETHOD 2026-02-14 11:08:50 +01:00
Romain Thomas 3b012a0a7f enhance API for PDB _simple_ types 2026-02-14 11:08:45 +01:00
Romain Thomas b19a17ee89 enhance API for PDB LF_ARRAY 2026-02-14 11:07:30 +01:00
Romain Thomas b5fd54aab4 enhance API for PDB LF_PROCEDURE 2026-02-14 11:07:24 +01:00
Romain Thomas f23d3bccd4 enhance API for PDB LF_ENUM 2026-02-14 11:06:19 +01:00
Romain Thomas a89d452efa Add API to access a PDB from its index 2026-02-14 10:55:28 +01:00
Romain Thomas b0502c94d0 Ghidra - Support DWARF generation for raw binaries/firmware
This commit introduces support for generating DWARF debug information
for binaries that LIEF cannot natively parse (e.g., raw firmware or unknown architectures).

Related to #1249
2026-02-14 10:55:23 +01:00
Romain Thomas 38e5565568 Abstract pdb::Type::{size, name} 2026-02-14 10:55:16 +01:00
Romain Thomas 986b7d0177 Update pytest to 9.0.2 2026-02-14 09:47:49 +01:00
Romain Thomas 6c0f19af19 Fix missing file 2026-02-14 09:47:49 +01:00
Romain Thomas 1efd1a3857 Update doc 2026-02-14 09:47:23 +01:00
Romain Thomas 0291fe7236 Fix Windows #define issue
`std::numeric_limits<uint16_t>::max()` can conflict with `#define max`
defined by Windows in `minwindef.h`. Since we are in a public header,
forcing `NOMINMAX` should not be considered.
2026-02-14 09:47:11 +01:00
Romain Thomas 71e6942309 Upgrade MbedTLS to 4.0.0
Updates the internal MbedTLS version from 3.6.4 to 4.0.0.
This major version introduces the TF-PSA-Crypto architecture,
requiring significant changes to the build system and internal API usage.

Added `src/mbedtls_wraps.h` to handle the internalization
of MbedTLS 4.0 structures. This file re-declares private contexts
(like `mbedtls_rsa_context`) and uses `-DMBEDTLS_DECLARE_PRIVATE_IDENTIFIERS`
to allow LIEF to inspect internal key parameters required for PE
signature verification.
2026-02-14 09:46:59 +01:00
Romain Thomas 66a54c6d92 Update deps
close #1295, #1294
2026-02-14 09:45:18 +01:00
Immortale a037769500 Fix address type (#1296) 2026-02-14 09:21:27 +01:00
Javier Lopez-Gomez 59298ccdc7 Fix MachO::Binary::virtual_address_to_offset() for non-file-backed segment (#1301)
Fix #1299.
2026-02-14 09:19:47 +01:00
Javier Lopez-Gomez 81feabd209 Fix LIEF::MachO::Binary::patch_relocation() for tagged pointers (#1302)
Fixes #1300.
2026-02-14 09:18:37 +01:00
3321 changed files with 361457 additions and 275815 deletions
+118
View File
@@ -0,0 +1,118 @@
---
Language: Cpp
BasedOnStyle: LLVM
Standard: c++17
# Column limit
ColumnLimit: 83
# Indentation
IndentWidth: 2
TabWidth: 2
UseTab: Never
ContinuationIndentWidth: 4
ConstructorInitializerIndentWidth: 2
IndentCaseLabels: true
IndentCaseBlocks: false
IndentPPDirectives: BeforeHash
NamespaceIndentation: None
IndentWrappedFunctionNames: true
IndentAccessModifiers: false
# Access modifiers at same level as class members
AccessModifierOffset: 0
# Constructor initializers: colon at end of line, each initializer on new line
BreakConstructorInitializers: AfterColon
PackConstructorInitializers: Never
# Inheritance
BreakInheritanceList: BeforeColon
# Pointer/Reference alignment: attached to type
PointerAlignment: Left
ReferenceAlignment: Pointer
DerivePointerAlignment: false
# Spacing
SpaceBeforeParens: ControlStatements
SpaceBeforeCpp11BracedList: false
SpaceInEmptyBlock: false
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeRangeBasedForLoopColon: true
# Alignment
AlignAfterOpenBracket: Align
AlignOperands: Align
AlignTrailingComments: true
AlignConsecutiveAssignments: None
AlignConsecutiveDeclarations: false
# Short forms
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: true
AllowShortLambdasOnASingleLine: All
AllowShortEnumsOnASingleLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortCaseExpressionOnASingleLine: true
# Packing
BinPackArguments: true
BinPackParameters: true
# Namespaces
CompactNamespaces: false
FixNamespaceComments: false
# Empty lines
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
MaxEmptyLinesToKeep: 2
# Ternary operators stay at end of line
BreakBeforeTernaryOperators: false
# Misc
Cpp11BracedListStyle: true
ReflowComments: true
InsertBraces: true
InsertNewlineAtEOF: true
BreakTemplateDeclarations: Yes
BreakBeforeCloseBracketBracedList: true
BreakBeforeCloseBracketFunction: true
BreakBeforeTemplateCloser: true
EnumTrailingComma: Insert
AlignConsecutiveMacros:
Enabled: true
AcrossEmptyLines: true
AcrossComments: true
BreakAfterReturnType: ExceptShortType
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: true
AfterControlStatement: MultiLine
RemoveEmptyLinesInUnwrappedLines: true
RemoveSemicolon: true
QualifierAlignment: Left
# Includes - preserve existing order
SortIncludes: true
SortUsingDeclarations: LexicographicNumeric
IncludeCategories:
- Regex: '^((<|")(spdlog|nanobind|catch2|utf8)/)'
Priority: 3
- Regex: '<[[:alnum:].]+>'
Priority: 4
- Regex: '.*'
Priority: 1
SortPriority: 0
+4
View File
@@ -0,0 +1,4 @@
api/python/**
third-party/**
src/runtime/osx/utils.h
tests/test_define_conflicts.cpp
+76
View File
@@ -0,0 +1,76 @@
Checks: [
-*,
bugprone-*,
performance-*,
portability-*,
cppcoreguidelines-*,
misc-*,
clang-taidy-*,
modernize-*,
-clang-taidy-avoid-implicit-enum-to-integer-conversion,
-clang-taidy-avoid-high-cyclomatic-complexity,
-modernize-use-trailing-return-type,
-modernize-use-nodiscard,
-modernize-avoid-c-arrays,
# `modernize-avoid-c-style-cast` also rejects the functional-style suggested by
# `clang-taidy-avoid-static-integer-cast` (caught by -Wold-style-cast though)
-modernize-avoid-c-style-cast,
-modernize-use-ranges,
-modernize-use-constraints,
-modernize-use-designated-initializers,
-modernize-use-integer-sign-comparison,
-modernize-use-string-view,
-bugprone-derived-method-shadowing-base-method,
-bugprone-easily-swappable-parameters,
-bugprone-macro-parentheses,
-bugprone-narrowing-conversions,
-bugprone-reserved-identifier,
-bugprone-signed-bitwise,
-bugprone-signed-char-misuse,
-cppcoreguidelines-avoid-c-arrays,
-cppcoreguidelines-avoid-const-or-ref-data-members,
-cppcoreguidelines-avoid-do-while,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-explicit-constructor,
-cppcoreguidelines-macro-to-enum,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-missing-std-forward,
-cppcoreguidelines-narrowing-conversions,
-cppcoreguidelines-non-private-member-variables-in-classes,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-pro-bounds-avoid-unchecked-container-access,
-cppcoreguidelines-pro-bounds-constant-array-index,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-type-const-cast,
-cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-pro-type-static-cast-downcast,
-cppcoreguidelines-pro-type-union-access,
-cppcoreguidelines-special-member-functions,
-cppcoreguidelines-use-enum-class,
-misc-const-correctness,
-misc-explicit-constructor,
-misc-include-cleaner,
-misc-misplaced-const,
-misc-no-recursion,
-misc-non-private-member-variables-in-classes,
-misc-override-with-different-visibility,
-misc-static-assert,
-misc-use-anonymous-namespace,
-misc-use-internal-linkage,
-performance-enum-size,
-performance-no-int-to-ptr,
-portability-avoid-pragma-once,
]
CheckOptions:
bugprone-unused-return-value.CheckedReturnTypes: '^::std::error_code$;^::std::error_condition$;^::std::errc$;^::std::expected$;^::LIEF::result$'
bugprone-unused-return-value.AllowCastToVoid: true
HeaderFilterRegex: '.*'
ExcludeHeaderFilterRegex: '(builds|build|api/rust/include|utils/ordinals_lookup_tables_std|utils/ordinals_lookup_tables)/*'
+70
View File
@@ -0,0 +1,70 @@
Documentation:
CommentFormat: Doxygen
Diagnostics:
Includes:
IgnoreHeader:
- spdlog/fmt/.*
- nanobind/stl/.*
- third-party/.*
ClangTidy:
FastCheckFilter: Strict
Add: [
bugprone-*,
performance-*,
portability-*,
cppcoreguidelines-*,
modernize-*,
misc-*,
clang-taidy-*,
]
Remove: [
bugprone-easily-swappable-parameters,
bugprone-narrowing-conversions,
bugprone-reserved-identifier,
bugprone-signed-char-misuse,
cppcoreguidelines-avoid-c-arrays,
cppcoreguidelines-avoid-const-or-ref-data-members,
cppcoreguidelines-avoid-do-while,
cppcoreguidelines-avoid-magic-numbers,
cppcoreguidelines-explicit-constructor,
cppcoreguidelines-missing-std-forward,
cppcoreguidelines-narrowing-conversions,
cppcoreguidelines-non-private-member-variables-in-classes,
cppcoreguidelines-owning-memory,
cppcoreguidelines-pro-bounds-array-to-pointer-decay,
cppcoreguidelines-pro-bounds-constant-array-index,
cppcoreguidelines-pro-bounds-pointer-arithmetic,
cppcoreguidelines-pro-type-const-cast,
cppcoreguidelines-pro-type-reinterpret-cast,
cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-pro-type-union-access,
misc-explicit-constructor,
misc-misplaced-const,
misc-no-recursion,
misc-non-private-member-variables-in-classes,
misc-use-anonymous-namespace,
misc-use-internal-linkage,
misc-static-assert,
modernize-avoid-c-arrays,
modernize-concat-nested-namespaces,
modernize-make-unique,
modernize-use-nodiscard,
modernize-use-noexcept,
modernize-use-trailing-return-type,
performance-enum-size,
performance-no-int-to-ptr,
]
---
If:
PathMatch:
- api/rust/include/LIEF/.*
CompileFlags:
Remove: [-std=gnu++17]
Add: [-std=gnu++20]
---
If:
PathMatch:
- include/LIEF/.*
PathExclude:
- api/rust/.*
+43
View File
@@ -0,0 +1,43 @@
[paths]
source =
tests/
[run]
branch = True
relative_files = True
omit =
*/api/python/*
*/tests/utils.py
*/tests/conftest.py
*/tests/run_pytest.py
; Require LIEF extended
*/tests/coff/test_disassembler.py
*/tests/api/test_demangle.py
*/tests/dwarf/*
*/tests/objc/*
*/tests/assembly/*
*/tests/pdb/*
*/tests/dyld-shared-cache/*
[report]
; Regexes for lines to exclude from consideration
exclude_also =
; Don't complain about missing debug-only code:
def __repr__
if self\.debug
; Don't complain if tests don't hit defensive assertion code:
raise AssertionError
raise NotImplementedError
raise RuntimeError
; Don't complain if non-runnable code isn't run:
if 0:
if __name__ == .__main__.:
if lief.__extended__:
if stderr:
if not file.exists():
; Don't complain about these markers
@pytest\.mark\.lief_extended
@pytest\.mark\.slow
-138
View File
@@ -1,138 +0,0 @@
# Launch Docker CI when committing
# Inspired from https://medium.com/@zypherman/my-experiences-with-travis-ci-7f5ea26a87c0
import requests
import json
import time
import sys
import logging
import pprint
import os
LOG_LEVEL = logging.INFO
logging.getLogger().addHandler(logging.StreamHandler())
logging.getLogger().setLevel(LOG_LEVEL)
logger = logging.getLogger(__name__)
AUTH_TOKEN = os.getenv("TRAVIS_TOKEN", sys.argv[1] if len(sys.argv) > 1 else None)
if not AUTH_TOKEN:
logger.error("No token found!")
sys.exit(1)
LIEF_ID = 12579556
DOCKER_ID = 15139981
ENDPOINT = 'https://api.travis-ci.org'
LIEF = f"{ENDPOINT}/repo/{LIEF_ID}"
DOCKER = f"{ENDPOINT}/repo/{DOCKER_ID}"
DOCKER_ENV_VARS_ENDPOINT = f"{DOCKER}/env_vars"
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'User-Agent': 'API Explorer',
'Travis-API-Version': '3',
'Authorization': f'token {AUTH_TOKEN}'
}
def last_docker_build():
response = requests.get(f"{DOCKER}/branch/master", headers=headers)
if not response.ok:
logging.error("Error while getting last_docker_build")
sys.exit(1)
href = response.json()["last_build"]["@href"]
build_info = requests.get(f"{ENDPOINT}{href}", headers=headers)
if not build_info.ok:
logging.error("Error while getting build_info")
sys.exit(1)
return build_info.json()
def trigger_build():
response = requests.get(f"{DOCKER}/branch/master", headers=headers)
build_info = last_docker_build()
pprint.pprint(build_info)
# Get last build info
last_build_id = build_info["id"]
last_build_status = build_info["state"]
# Create env variables
env_vars = [
{
"env_var.name": "TRIGGER_COMMIT",
"env_var.value": os.getenv("TRAVIS_COMMIT"),
"env_var.public": False,
},
{
"env_var.name": "TRIGGER_REPO",
"env_var.value": os.getenv("TRAVIS_REPO_SLUG"),
"env_var.public": False,
},
{
"env_var.name": "TRIGGER_ACTION",
"env_var.value": "build-doc",
"env_var.public": False,
},
{
"env_var.name": "DEPENDENT_BUILD",
"env_var.value": "true",
"env_var.public": False,
},
]
env_vars_results = requests.get(DOCKER_ENV_VARS_ENDPOINT, headers=headers)
if not env_vars_results.ok:
logger.error("Error while getting Docker env variables")
sys.exit(1)
env_vars_remote = env_vars_results.json()["env_vars"]
# Set env variables
for env_var in env_vars:
remote_var = next(filter(lambda v : v["name"] == env_var["env_var.name"], env_vars_remote), None)
if remote_var:
r = requests.patch(f"{DOCKER}/env_var/{remote_var['id']}", data=json.dumps(env_var), headers=headers)
if not r.ok:
logger.error(f"Error while setting variable: '{remote_var['name']}'")
sys.exit(1)
else:
result = requests.post(DOCKER_ENV_VARS_ENDPOINT, data=json.dumps(env_var), headers=headers)
if not result.ok:
logger.error(f"Error while setting variable: '{env_var['env_var.name']}'")
sys.exit(1)
# (Re)Start build
result = requests.post(f"{ENDPOINT}/build/{last_build_id}/restart", headers=headers)
if not result.ok:
logger.error("Error while restarting the build")
sys.exit(1)
return 0
def main():
is_pull_request = not (os.getenv("TRAVIS_PULL_REQUEST", "false") == "false")
if is_pull_request:
logger.info("Skipping pull request build...")
return 0
return trigger_build()
if __name__ == "__main__":
sys.exit(main())
+11 -6
View File
@@ -1,5 +1,10 @@
name: 'Android'
on: push
on:
push:
branches:
- 'main'
tags-ignore:
- '**'
jobs:
build-sdk:
@@ -9,7 +14,7 @@ jobs:
arch: ['arm', 'arm64']
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Get Date
@@ -18,7 +23,7 @@ jobs:
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: ccache cache files
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ~/.ccache
key: android-${{ runner.os }}-${{ matrix.arch }}-${{ steps.get-date.outputs.date }}
@@ -38,7 +43,7 @@ jobs:
-v $HOME/.ccache:/ccache \
--rm liefproject/android-${ARCH} bash /work/scripts/docker/android-sdk-${ARCH}
- name: 'Upload Artifact'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: android-sdk-${{ matrix.arch }}
path: build/*.tar.gz
@@ -48,11 +53,11 @@ jobs:
runs-on: ubuntu-latest
needs: build-sdk
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
path: ${{ runner.temp }}/artifacts
- name: Display artifacts
+19 -14
View File
@@ -1,5 +1,10 @@
name: 'Linux x86-64'
on: push
on:
push:
branches:
- 'main'
tags-ignore:
- '**'
jobs:
linux-sdk:
@@ -19,7 +24,7 @@ jobs:
ACTIONS_CACHE_URL: "${{ env.ACTIONS_CACHE_URL }}"
options: --user 1001:1001
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Get Date
@@ -32,7 +37,7 @@ jobs:
run: |
mkdir -p /home/pylief/.ccache/tmp
- name: ccache cache files
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: /home/pylief/.ccache
key: linux-x86-64-${{ runner.os }}-sdk-${{ steps.get-date.outputs.date }}
@@ -71,13 +76,13 @@ jobs:
cd /tmp/build/linux-x86-64
cpack --config $GITHUB_WORKSPACE/cmake/cpack.config.cmake
- name: 'Upload SDK Artifact'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: linux-x86-64-sdk
path: /tmp/build/linux-x86-64/*.tar.gz
retention-days: 3
- name: 'Upload Install Artifact'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: linux-x86-64-install
path: /install
@@ -96,7 +101,7 @@ jobs:
PYTEST_ADDOPTS: "--color=yes"
options: --user 1001:1001
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Get Date
@@ -105,7 +110,7 @@ jobs:
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: ccache cache files
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ~/.ccache
key: linux-x86-64-${{ runner.os }}-test-${{ steps.get-date.outputs.date }}
@@ -186,9 +191,9 @@ jobs:
options: --user 1001:1001
strategy:
matrix:
python-version: [3.9, '3.10', '3.11', '3.12', '3.13']
python-version: ['3.12', '3.13', '3.14']
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Get Date
@@ -201,14 +206,14 @@ jobs:
run: |
mkdir -p /home/pylief/.ccache/tmp
- name: ccache cache files
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: /home/pylief/.ccache
key: linux-x86-64-${{ runner.os }}-${{ matrix.python-version }}-${{ steps.get-date.outputs.date }}
restore-keys: |
linux-x86-64-${{ runner.os }}-${{ matrix.python-version }}
- name: Download LIEF install dir
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: linux-x86-64-install
path: /install
@@ -231,7 +236,7 @@ jobs:
auditwheel repair -w $GITHUB_WORKSPACE/dist {} \;
ls -alh $GITHUB_WORKSPACE/dist
- name: 'Artifact'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: linux-x86-64-python${{ matrix.python-version }}-wheel
path: dist/*.whl
@@ -241,11 +246,11 @@ jobs:
if: ${{ always() }}
needs: [pywheels]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
pattern: linux-x86-64-*
merge-multiple: true
+24 -21
View File
@@ -1,14 +1,19 @@
name: 'macOS'
on: push
on:
push:
branches:
- 'main'
tags-ignore:
- '**'
env:
python-test-version: '3.10'
python-test-version: '3.13'
jobs:
osx-sdk:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Install system dependencies
@@ -24,7 +29,7 @@ jobs:
run: |
mkdir -p $RUNNER_TEMP/.ccache
- name: ccache cache files
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ${{ runner.temp }}/.ccache
key: osx-${{ runner.os }}-sdk-${{ steps.get-date.outputs.date }}
@@ -42,19 +47,19 @@ jobs:
run: |
bash scripts/osx/package_sdk.sh
- name: 'Upload SDK Artifact'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: osx-sdk
path: build/*.tar.gz
retention-days: 3
- name: 'Upload install artifact [arm64]'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: osx-arm64-install
path: install/arm64
retention-days: 1
- name: 'Upload install artifact [x64]'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: osx-x64-install
path: install/x64
@@ -63,11 +68,11 @@ jobs:
runs-on: macos-14
if: "!contains(github.event.commits[0].message, '[skip-test]')"
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Set up Python ${{ env.python-test-version }}
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: ${{ env.python-test-version }}
- name: Install system dependencies
@@ -83,7 +88,7 @@ jobs:
run: |
mkdir -p $RUNNER_TEMP/.ccache
- name: ccache cache files
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ${{ runner.temp }}/.ccache
key: osx-${{ runner.os }}-test-${{ steps.get-date.outputs.date }}
@@ -93,7 +98,7 @@ jobs:
shell: bash
run: |
python -m pip install --upgrade pip
- name: Build Python 3.10 with tests
- name: Build Python 3.13 with tests
shell: bash
env:
LIEF_SAMPLES_DIR: "/tmp/samples"
@@ -128,15 +133,15 @@ jobs:
needs: osx-sdk
strategy:
matrix:
python-version: [3.9, '3.10', '3.11', '3.12', '3.13']
python-version: ['3.12', '3.13', '3.14']
arch: ['x64', 'arm64']
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install system dependencies
@@ -153,14 +158,14 @@ jobs:
run: |
mkdir -p $RUNNER_TEMP/.ccache
- name: ccache cache files
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: ${{ runner.temp }}/.ccache
key: osx-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.python-version }}-${{ steps.get-date.outputs.date }}
restore-keys: |
osx-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.python-version }}
- name: Download LIEF install dir
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: osx-${{ matrix.arch }}-install
path: ~/lief-${{ matrix.arch }}-install
@@ -178,7 +183,7 @@ jobs:
run: |
python -m pip -vv wheel --wheel-dir=dist/ api/python
- name: 'Upload Python wheel artifact - ${{ matrix.python-version }}'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: osx-wheel-${{ matrix.arch }}-${{ matrix.python-version }}
path: dist/*.whl
@@ -188,11 +193,11 @@ jobs:
if: ${{ always() }}
needs: [wheels]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
pattern: osx-*
merge-multiple: true
@@ -217,5 +222,3 @@ jobs:
-e LIEF_S3_SECRET=$LIEF_S3_SECRET \
liefproject/deploy \
python3 /src/.github/deploy.py --skip-sdk /runner_tmp/artifacts
+23 -20
View File
@@ -2,18 +2,18 @@ name: LIEF PR
on: [pull_request, workflow_dispatch]
env:
python-osx-version: '3.10'
python-win-version: '3.10'
python-osx-version: '3.12'
python-win-version: '3.12'
jobs:
osx:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: ${{ env.python-osx-version }}
- name: Install system dependencies
@@ -31,31 +31,31 @@ jobs:
python -m pip install -e api/python
python tests/dl_samples.py ${LIEF_SAMPLES_DIR}
python tests/run_pytest.py
python tests/run_tools_check.py ${BUILD_DIR}
ctest --output-on-failure --test-dir ${BUILD_DIR}
python tests/run_tools_check.py ${LIEF_BUILD_DIR}
ctest --output-on-failure --test-dir ${LIEF_BUILD_DIR}
linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Build & Test
shell: bash
env:
PYTHON_VERSION: 39
PYTHON_VERSION: 312
run: |
docker run --rm \
-e PYTHON_VERSION=$PYTHON_VERSION \
-e PYTHON_BINARY=/opt/python/cp39-cp39/bin/python3.9 \
-e PYTHON_BINARY=/opt/python/cp312-cp312/bin/python3.12 \
-v $GITHUB_WORKSPACE:/src \
liefproject/manylinux_2_28_x86_64 \
bash /src/scripts/docker/test-linux-x64
windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Set up Python ${{ env.python-win-version }}
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: ${{ env.python-win-version }}
architecture: x64
@@ -73,17 +73,20 @@ jobs:
echo ("LIEF_BUILD_DIR=" + $env:RUNNER_TEMP + "/lief-build") >> $env:GITHUB_ENV
echo ("PYLIEF_CONF=" + $env:GITHUB_WORKSPACE + "/scripts/windows/py-x64-test.toml") >> $env:GITHUB_ENV
- name: Build Python ${{ env.python-win-version }}
shell: cmd
shell: pwsh
run: |
python -m pip install -r tests/requirements.txt
python -m pip install api/python
python tests/dl_samples.py %LIEF_SAMPLES_DIR%
- name: Run tests
timeout-minutes: 20
shell: cmd
python tests/dl_samples.py $env:LIEF_SAMPLES_DIR
- name: Run tests - unittests
shell: pwsh
run: |
cd %GITHUB_WORKSPACE%
cd $env:GITHUB_WORKSPACE
ctest --output-on-failure --test-dir $env:LIEF_BUILD_DIR
Exit $LASTEXITCODE
- name: Run tests - python
shell: pwsh
run: |
cd $env:GITHUB_WORKSPACE
python tests/run_pytest.py
ctest --output-on-failure --test-dir %BUILD_DIR%
Exit $LASTEXITCODE
+43 -33
View File
@@ -3,15 +3,18 @@ on:
push:
branches:
- 'main'
- 'master'
- 'release-**'
- 'release/**'
tags:
tags-ignore:
- '**'
env:
python-test-version: '3.10'
python-version: '3.9'
python-test-version: '3.13'
python-version: '3.13'
CLICOLOR_FORCE: "1"
FORCE_COLOR: "1"
GCC_COLORS: "yes"
COLORTERM: "truecolor"
TERM: "screen-256color"
CLICOLOR: "1"
jobs:
build-sdk:
@@ -24,14 +27,15 @@ jobs:
SCCACHE_CACHE_SIZE: 2G
SCCACHE_DIR: ${{ vars.SCCACHE_DIR }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: ${{ env.python-version }}
architecture: ${{ matrix.arch }}
- run: python -m pip install setuptools
- name: Install system dependencies
run: |
choco install ninja
@@ -45,7 +49,7 @@ jobs:
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: Setup sccache
uses: actions/cache@v4
uses: actions/cache@v5
continue-on-error: false
with:
path: ${{ vars.SCCACHE_DIR }}
@@ -58,13 +62,13 @@ jobs:
run: |
python ./scripts/windows/package_sdk.py
- name: 'Upload SDK artifact'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: windows-${{ matrix.arch }}-sdk
path: build/*.zip
retention-days: 3
- name: 'Upload install artifact'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: windows-${{ matrix.arch }}-install
path: ${{ runner.temp }}/lief-install
@@ -84,11 +88,11 @@ jobs:
SCCACHE_CACHE_SIZE: 2G
SCCACHE_DIR: ${{ vars.SCCACHE_DIR }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python ${{ env.python-test-version }}
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: ${{ env.python-test-version }}
architecture: ${{ matrix.arch }}
@@ -105,7 +109,7 @@ jobs:
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: Setup sccache
uses: actions/cache@v4
uses: actions/cache@v5
continue-on-error: false
with:
path: ${{ vars.SCCACHE_DIR }}
@@ -131,23 +135,30 @@ jobs:
echo ("LIEF_SAMPLES_DIR=" + $env:RUNNER_TEMP + "/samples") >> $env:GITHUB_ENV
echo ("LIEF_BUILD_DIR=" + $env:RUNNER_TEMP + "/lief-build") >> $env:GITHUB_ENV
- name: Build Python ${{ env.python-test-version }}
shell: cmd
shell: pwsh
run: |
python -m pip install -r tests/requirements.txt
python tests/dl_samples.py %LIEF_SAMPLES_DIR%
python tests/dl_samples.py $env:LIEF_SAMPLES_DIR
python -m pip -vvv install --user api/python
Exit $LASTEXITCODE
- name: Download samples
shell: cmd
shell: pwsh
run: |
python -m pip install -r tests/requirements.txt
python tests/dl_samples.py %LIEF_SAMPLES_DIR%
- name: Run tests
timeout-minutes: 20
shell: cmd
python tests/dl_samples.py $env:LIEF_SAMPLES_DIR
- name: Run unittests
shell: pwsh
run: |
cd %GITHUB_WORKSPACE%
cd $env:GITHUB_WORKSPACE
ctest --output-on-failure --test-dir $env:LIEF_BUILD_DIR
Exit $LASTEXITCODE
- name: Run Python tests
timeout-minutes: 20
shell: pwsh
run: |
cd $env:GITHUB_WORKSPACE
python tests/run_pytest.py
ctest --output-on-failure --test-dir %LIEF_BUILD_DIR%/
Exit $LASTEXITCODE
- name: sccache stats
run: sccache --show-stats
- name: stop sccache server
@@ -157,18 +168,18 @@ jobs:
needs: build-sdk
strategy:
matrix:
python-version: [3.9, '3.10', '3.11', '3.12', '3.13']
python-version: ['3.12', '3.13', '3.14']
arch: ['x86', 'x64']
fail-fast: false
env:
SCCACHE_CACHE_SIZE: 2G
SCCACHE_DIR: ${{ vars.SCCACHE_DIR }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
architecture: ${{ matrix.arch }}
@@ -186,7 +197,7 @@ jobs:
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: Save sccache
uses: actions/cache@v4
uses: actions/cache@v5
continue-on-error: false
with:
path: ${{ vars.SCCACHE_DIR }}
@@ -194,7 +205,7 @@ jobs:
restore-keys: |
${{ runner.os }}-${{ matrix.arch }}-sccache-${{ matrix.python-version }}
- name: Download LIEF install dir
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: windows-${{ matrix.arch }}-install
path: ~/lief-${{ matrix.arch }}-install
@@ -215,11 +226,11 @@ jobs:
run: |
chcp 65001 #set code page to utf-8
- name: Build Python ${{ matrix.python-version }}
shell: pwsh
run: |
python -m pip -vvv wheel --wheel-dir=dist/ ./api/python
shell: cmd
- name: 'Upload Python artifacts [${{ matrix.python-version }}]'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: windows-${{ matrix.arch }}-wheel-${{ matrix.python-version }}
path: dist/*.whl
@@ -230,11 +241,11 @@ jobs:
#needs: [build-sdk, wheels]
needs: [wheels]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
pattern: windows-*
merge-multiple: true
@@ -255,4 +266,3 @@ jobs:
-e LIEF_S3_KEY=$LIEF_S3_KEY \
-e LIEF_S3_SECRET=$LIEF_S3_SECRET \
liefproject/deploy python3 /src/.github/deploy.py --skip-sdk /runner_tmp/artifacts
-79
View File
@@ -1,79 +0,0 @@
name: LIEF Windows Quick
on:
push:
branches:
- '**'
- '!master'
- '!main'
- '!release-**'
- '!release/**'
tags-ignore:
- "**"
env:
python-version: '3.12'
jobs:
quick-test:
runs-on: windows-2022
strategy:
matrix:
arch: [x64, x86]
fail-fast: false
env:
SCCACHE_CACHE_SIZE: 2G
SCCACHE_DIR: ${{ vars.SCCACHE_DIR }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python ${{ env.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ env.python-version }}
architecture: ${{ matrix.python-version }}
- name: Install system dependencies
run: |
choco install ninja
choco install sccache
python -m pip install --upgrade pip
- uses: ilammy/msvc-dev-cmd@v1
with:
vsversion: "2022"
- name: Get Date
id: get-date
run: |
echo "date=$(/bin/date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
shell: bash
- name: Save sccache
uses: actions/cache@v4
continue-on-error: false
with:
path: ${{ vars.SCCACHE_DIR }}
key: ${{ runner.os }}-${{ matrix.arch }}-quick-${{ steps.get-date.outputs.date }}
restore-keys: |
${{ runner.os }}-${{ matrix.arch }}-quick
- name: Start sccache server
run: sccache --start-server
- name: Set env variables
run: |
chcp 65001 #set code page to utf-8
echo ("LIEF_SAMPLES_DIR=" + $env:RUNNER_TEMP + "/samples") >> $env:GITHUB_ENV
- name: Build Python ${{ env.python-version }}
shell: cmd
run: |
python -m pip install -r tests/requirements.txt
python -m pip -vvv install api/python
- name: Download samples
shell: cmd
run: |
python tests/dl_samples.py %LIEF_SAMPLES_DIR%
- name: Run tests
shell: cmd
timeout-minutes: 20
run: |
python ./tests/run_pytest.py
- name: sccache stats
run: sccache --show-stats
- name: sccache server
run: sccache --stop-server || true
+2
View File
@@ -11,3 +11,5 @@ api/rust/cargo/target/*
api/rust/examples/target/*
tools/target/*
plugins/ghidra/bin/
api/python/tests/lib/
dev-scripts/
+1 -1
View File
@@ -1,3 +1,3 @@
Authors:
Romain Thomas <me@romainthomas.fr> - Quarkslab
Romain Thomas <me@romainthomas.fr>
+3 -6
View File
@@ -4,13 +4,10 @@ Acknowledgements
LIEF makes use of the following open source projects:
- mbedTLS - https://tls.mbed.org/
- pybind11 - https://github.com/pybind/pybind11
- nanobind - https://github.com/wjakob/nanobind
- json - https://nlohmann.github.io/json/
- rang - https://agauniyal.github.io/rang/
- easyloggingpp - https://github.com/muflihun/easyloggingpp
- Catch - https://github.com/philsquared/Catch
- yamlcpp - https://github.com/jbeder/yaml-cpp
- filesystem - https://github.com/wjakob/filesystem
- spdlog - https://github.com/gabime/spdlog
- Catch2 - https://github.com/catchorg/Catch2
- utf8-cpp - https://sourceforge.net/projects/utfcpp/
- llvm - http://llvm.org/ - For the formats enums and structures
- virtualbox - https://www.virtualbox.org/ - For the PE 'LoadConfiguration' structures
+1 -2
View File
@@ -1,5 +1,4 @@
Changelog
=========
see doc/sphinx/changelog.rst
see doc/sphinx/changelog.md
+95 -88
View File
@@ -1,17 +1,6 @@
cmake_minimum_required(VERSION 3.24)
project(LIEF LANGUAGES C CXX)
enable_language(C)
enable_language(CXX)
# Avoid warning about DOWNLOAD_EXTRACT_TIMESTAMP in CMake 3.24:
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
cmake_policy(SET CMP0135 NEW)
endif()
# Enable https://cmake.org/cmake/help/latest/prop_tgt/MSVC_RUNTIME_LIBRARY.html
cmake_policy(SET CMP0091 NEW)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Modules
@@ -19,7 +8,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
include(CheckCXXCompilerFlag)
include(CheckCCompilerFlag)
include(ExternalProject)
include(CMakePackageConfigHelpers)
find_package(Git)
@@ -35,7 +23,7 @@ elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git"
AND IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/.git" AND Git_FOUND)
include(LIEFGit)
else()
set(LIEF_VERSION_MAJOR 1)
set(LIEF_VERSION_MAJOR 2)
set(LIEF_VERSION_MINOR 0)
set(LIEF_VERSION_PATCH 0)
endif()
@@ -67,8 +55,8 @@ message(STATUS "Caching: ${LIEF_USE_CCACHE}")
if(LIEF_USE_CCACHE)
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_FOUND})
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_FOUND})
message(STATUS "Found ccache: ${CCACHE_FOUND}")
else()
find_program(SCCACHE_FOUND sccache)
@@ -96,6 +84,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "")
endif()
set(LIEF_EXTRA_FLAGS)
message(STATUS "LIEF_EXTRA_FLAGS: ${LIEF_EXTRA_FLAGS}")
message(STATUS "CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}")
message(STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO: ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
message(STATUS "CMAKE_CXX_FLAGS_DEBUG: ${CMAKE_CXX_FLAGS_DEBUG}")
@@ -120,31 +111,58 @@ include(GNUInstallDirs)
add_library(LIB_LIEF src/Object.cpp)
add_subdirectory(src)
if(NOT LIEF_PY_LIEF_EXT)
if (LIEF_EXTRA_FLAGS)
target_compile_options(LIB_LIEF PRIVATE ${LIEF_EXTRA_FLAGS})
endif()
if(LIEF_PRECOMPILED)
find_package(lief-extended QUIET)
if (NOT lief-extended_FOUND)
find_package(LIEF REQUIRED)
endif()
else()
add_library(LIEF::LIEF ALIAS LIB_LIEF)
endif()
if(NOT LIEF_OPT_MBEDTLS_EXTERNAL)
set_source_files_properties(${mbedtls_src_files} PROPERTIES GENERATED TRUE)
target_sources(LIB_LIEF PRIVATE ${mbedtls_src_files})
target_compile_definitions(LIB_LIEF PRIVATE -DMBEDTLS_NO_PLATFORM_ENTROPY)
target_include_directories(LIB_LIEF SYSTEM PRIVATE
${MBEDTLS_INCLUDE_DIRS}
"${MBEDTLS_SOURCE_DIR}/library"
)
if (LIEF_PYTHON_FREE_THREADED)
target_compile_definitions(LIB_LIEF PRIVATE
# these must be set at LIB_LIEF compile time to be forwarded to MbedTLS
-DMBEDTLS_THREADING_C
-DMBEDTLS_THREADING_ALT
)
endif()
add_dependencies(LIB_LIEF lief_mbed_tls)
target_compile_definitions(LIB_LIEF PRIVATE
-DTF_PSA_CRYPTO_USER_CONFIG_FILE="${CMAKE_CURRENT_SOURCE_DIR}/config/mbedtls/psa_config.h"
)
else()
find_package(MbedTLS REQUIRED)
find_package(MbedTLS 4.0.0 EXACT REQUIRED)
target_link_libraries(LIB_LIEF PRIVATE
MbedTLS::mbedcrypto MbedTLS::mbedx509)
MbedTLS::tfpsacrypto MbedTLS::mbedx509)
if (LIEF_PYTHON_FREE_THREADED)
message(WARNING "Python free-threading requires the external MbedTLS to have \
been built with threading support. LIEF cannot enforce this.")
endif()
endif()
target_compile_definitions(LIB_LIEF PRIVATE
-DMBEDTLS_CONFIG_FILE="${CMAKE_CURRENT_SOURCE_DIR}/config/mbedtls/config.h"
-DMBEDTLS_X509_USE_C
-DMBEDTLS_PK_PARSE_C
)
if (WIN32)
target_link_libraries(LIB_LIEF PRIVATE bcrypt)
endif()
if(WIN32 AND BUILD_SHARED_LIBS)
target_link_libraries(LIB_LIEF PRIVATE ws2_32)
if (LIEF_IMPORT_SUFFIX)
@@ -153,11 +171,8 @@ if(WIN32 AND BUILD_SHARED_LIBS)
endif()
if(MSVC)
add_compile_options(/bigobj)
endif()
if(CMAKE_BUILD_TYPE MATCHES Debug AND UNIX)
target_compile_options(LIB_LIEF PRIVATE -g -O0)
target_compile_options(LIB_LIEF PRIVATE /bigobj)
target_compile_options(LIB_LIEF PUBLIC /Zc:__cplusplus)
endif()
if(BUILD_SHARED_LIBS OR LIEF_FORCE_API_EXPORTS)
@@ -200,7 +215,6 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/include/LIEF/config.h.in"
set(LIEF_PUBLIC_INCLUDE_DIR
${CMAKE_CURRENT_SOURCE_DIR}/include/
${CMAKE_CURRENT_SOURCE_DIR}/api/c/include/
${CMAKE_CURRENT_BINARY_DIR}/include/)
set(LIEF_PRIVATE_INCLUDE_DIR
@@ -215,21 +229,18 @@ target_include_directories(LIB_LIEF
PUBLIC "$<BUILD_INTERFACE:${LIEF_PUBLIC_INCLUDE_DIR}>"
PRIVATE "${LIEF_PRIVATE_INCLUDE_DIR}")
target_precompile_headers(LIB_LIEF PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/lief-pch.hpp
)
if(LIEF_ENABLE_JSON)
if(LIEF_OPT_NLOHMANN_JSON_EXTERNAL)
find_package(nlohmann_json REQUIRED)
target_link_libraries(LIB_LIEF PRIVATE nlohmann_json::nlohmann_json)
else()
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/internal/nlohmann/json.hpp
COMMAND
${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/internal/nlohmann
COMMAND
${CMAKE_COMMAND} -E copy_directory ${LIBJSON_SOURCE_DIR}/
${CMAKE_CURRENT_BINARY_DIR}/internal/nlohmann/
DEPENDS lief_libjson)
target_sources(LIB_LIEF PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/internal/nlohmann/json.hpp)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/internal/nlohmann)
file(COPY ${LIBJSON_SOURCE_DIR}/
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/internal/nlohmann/)
target_include_directories(LIB_LIEF PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/)
@@ -242,7 +253,6 @@ if(LIEF_FROZEN_ENABLED)
find_package(frozen REQUIRED)
target_link_libraries(LIB_LIEF PRIVATE frozen::frozen)
else()
add_dependencies(LIB_LIEF lief_frozen)
target_include_directories(LIB_LIEF
PRIVATE "${FROZEN_INCLUDE_DIR}")
endif()
@@ -257,37 +267,22 @@ if(LIEF_EXTERNAL_EXPECTED)
find_package(tl-expected REQUIRED)
target_link_libraries(LIB_LIEF PUBLIC tl::expected)
else()
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/internal/expected.hpp
COMMAND
${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/internal/
COMMAND
${CMAKE_COMMAND} -E copy_directory ${EXPECTED_SRC_DIR}/include/tl/
${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/internal/
DEPENDS lief_expected)
target_sources(LIB_LIEF PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/internal/expected.hpp)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/internal/)
file(COPY ${EXPECTED_SRC_DIR}/include/tl/
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/internal/)
endif()
# =======================================
# utfcpp
# =======================================
if(LIEF_OPT_UTFCPP_EXTERNAL)
find_package(utf8cpp REQUIRED)
target_link_libraries(LIB_LIEF PRIVATE utf8cpp::utf8cpp)
else()
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/internal/utfcpp/utf8.h
COMMAND
${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/internal/
COMMAND
${CMAKE_COMMAND} -E copy_directory ${UTFCPP_INCLUDE_DIR}/
${CMAKE_CURRENT_BINARY_DIR}/internal/utfcpp
DEPENDS lief_utfcpp)
target_sources(LIB_LIEF PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/internal/utfcpp/utf8.h)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/internal/)
file(COPY ${UTFCPP_INCLUDE_DIR}/
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/internal/utfcpp)
endif()
# =======================================
@@ -301,16 +296,9 @@ if(LIEF_EXTERNAL_SPAN)
"$<BUILD_INTERFACE:${LIEF_EXTERNAL_SPAN_DIR}>")
endif()
else()
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/internal/span.hpp
COMMAND
${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/internal/
COMMAND
${CMAKE_COMMAND} -E copy_directory ${TCB_SPAN_SRC_DIR}/
${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/internal/
DEPENDS lief_span)
target_sources(LIB_LIEF PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/internal/span.hpp)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/internal/)
file(COPY ${TCB_SPAN_SRC_DIR}/
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/include/LIEF/third-party/internal/)
endif()
target_link_libraries(LIB_LIEF PRIVATE lief_spdlog)
@@ -329,9 +317,31 @@ set_target_properties(LIB_LIEF
CXX_VISIBILITY_PRESET hidden
C_VISIBILITY_PRESET hidden)
if (LIEF_CLANG_TIDY)
find_program(CLANG_TIDY_EXE NAMES "clang-tidy" REQUIRED)
cmake_path(GET CLANG_TIDY_EXE PARENT_PATH CLANG_TIDY_DIR)
set(CLANG_TIDY_COMMAND
"${CLANG_TIDY_EXE}"
"--use-color"
"--load=${CLANG_TIDY_DIR}/clang-taidy.so"
"--config-file=${CMAKE_CURRENT_SOURCE_DIR}/.clang-tidy-core.yaml"
)
if (LIEF_CLANG_TIDY_WARN_ERR)
list(APPEND CLANG_TIDY_COMMAND "--warnings-as-errors=*")
endif()
set_target_properties(LIB_LIEF PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}")
if (TARGET LIB_LIEF_RUNTIME)
set_target_properties(LIB_LIEF_RUNTIME
PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}")
endif()
endif()
if(UNIX AND NOT APPLE)
set_property(TARGET LIB_LIEF APPEND
PROPERTY LINK_FLAGS "-Wl,--gc-sections -Wl,--exclude-libs,ALL")
target_link_options(LIB_LIEF PRIVATE -Wl,--gc-sections -Wl,--exclude-libs,ALL)
endif()
target_compile_definitions(LIB_LIEF PUBLIC -D_GLIBCXX_USE_CXX11_ABI=1)
@@ -341,19 +351,20 @@ target_compile_definitions(LIB_LIEF PUBLIC -D_GLIBCXX_USE_CXX11_ABI=1)
set(SANITIZER_FLAGS -fno-omit-frame-pointer -g -O1)
if(LIEF_ASAN)
message(STATUS "Address sanitizer enabled")
list(APPEND SANITIZER_FLAGS -fsanitize=address)
list(APPEND SANITIZER_FLAGS
-fsanitize=address
-fsanitize-address-use-after-scope
-fsanitize-address-use-after-return=runtime
)
set_property(TARGET LIB_LIEF
APPEND PROPERTY LINK_FLAGS -fsanitize=address)
target_link_libraries(LIB_LIEF INTERFACE libclang_rt.asan.so)
target_link_options(LIB_LIEF PUBLIC -fsanitize=address)
endif()
if(LIEF_LSAN)
message(STATUS "Leak sanitizer enabled")
list(APPEND SANITIZER_FLAGS -fsanitize=leak)
set_property(TARGET LIB_LIEF
APPEND PROPERTY LINK_FLAGS -fsanitize=leak)
target_link_options(LIB_LIEF PUBLIC -fsanitize=leak)
target_link_libraries(LIB_LIEF INTERFACE lsan)
endif()
@@ -362,21 +373,16 @@ if(LIEF_TSAN)
message(STATUS "Thread sanitizer enabled")
list(APPEND SANITIZER_FLAGS -fsanitize=thread)
set_property(TARGET LIB_LIEF
APPEND PROPERTY LINK_FLAGS -fsanitize=thread)
target_link_libraries(LIB_LIEF INTERFACE tsan)
target_link_options(LIB_LIEF PUBLIC -fsanitize=thread)
endif()
if(LIEF_USAN)
message(STATUS "Undefined sanitizer enabled")
list(APPEND SANITIZER_FLAGS -fsanitize=undefined,null,alignment)
set_property(TARGET LIB_LIEF
APPEND PROPERTY LINK_FLAGS -fsanitize=undefined,null,alignment)
target_link_options(LIB_LIEF PUBLIC -fsanitize=undefined,null,alignment)
target_link_libraries(LIB_LIEF PUBLIC ubsan -fsanitize=undefined,null,alignment)
target_link_libraries(LIB_LIEF PUBLIC ubsan)
endif()
set(LIEF_SANITIZER OFF)
@@ -389,15 +395,12 @@ if(LIEF_SANITIZER)
target_compile_options(LIB_LIEF PUBLIC ${SANITIZER_FLAGS})
add_subdirectory(tests/sanitizer)
endif()
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Fuzzing options
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(LIEF_FUZZING)
set(FUZZING_FLAGS -fno-omit-frame-pointer -g -O2 -fsanitize=fuzzer-no-link)
set(FUZZING_LINKER_FLAGS -fsanitize=fuzzer-no-link)
set_property(TARGET LIB_LIEF
APPEND PROPERTY LINK_FLAGS ${FUZZING_LINKER_FLAGS})
target_link_options(LIB_LIEF PUBLIC -fsanitize=fuzzer-no-link)
target_compile_options(LIB_LIEF PRIVATE ${FUZZING_FLAGS})
target_link_libraries(LIB_LIEF PUBLIC pthread)
@@ -451,6 +454,10 @@ if(LIEF_TESTS)
add_subdirectory(tests)
endif()
if(LIEF_COMPILE_DOC_EXAMPLES)
add_subdirectory(doc/code/cpp)
endif()
# Post-build operations
# ======================
if(BUILD_SHARED_LIBS AND CMAKE_BUILD_TYPE MATCHES "Release")
+35 -47
View File
@@ -17,19 +17,20 @@ modify and abstract ELF, PE and MachO formats.
**Main features**:
* **Parsing**: LIEF can parse [ELF](https://lief.re/doc/latest/formats/elf/index.html), [PE](https://lief.re/doc/latest/formats/pe/index.html), [MachO](https://lief.re/doc/latest/formats/macho/index.html), [COFF](https://lief.re/doc/latest/formats/coff/index.html), OAT, DEX, VDEX, ART and provides an user-friendly API to access to internals.
* **Modify**: LIEF can use to modify some parts of these formats (adding a section, changing a symbol's name, ...)
* **Parsing**: LIEF can parse [ELF](https://lief.re/doc/latest/formats/elf/index.html), [PE](https://lief.re/doc/latest/formats/pe/index.html), [MachO](https://lief.re/doc/latest/formats/macho/index.html), [COFF](https://lief.re/doc/latest/formats/coff/index.html), OAT, DEX, VDEX, ART and provides a user-friendly API to access their internals.
* **Modify**: LIEF can be used to modify some parts of these formats (adding a section, changing a symbol's name, ...)
* **Abstract**: Three formats have common features like sections, symbols, entry point... LIEF factors them.
* **API**: LIEF can be used in [C++](https://lief.re/doc/latest/doxygen/), Python, [Rust](https://lief-rs.s3.fr-par.scw.cloud/doc/latest/lief/index.html), C and
* **API**: You can use LIEF via [C++](https://lief.re/doc/latest/doxygen/), Python, [Rust](https://lief-rs.s3.fr-par.scw.cloud/doc/latest/lief/index.html), and
[Node.js](https://github.com/Piebald-AI/node-lief) (unofficial, AI-generated)
**Extended features**:
* [**Runtime**](https://lief.re/doc/latest/runtime/intro.html)
* [**DWARF/PDB** Support](https://lief.re/doc/latest/extended/debug_info/index.html)
* [**Objective-C** Metadata](https://lief.re/doc/latest/extended/objc/index.html)
* [**Dyld Shared Cache**](https://lief.re/doc/latest/extended/dsc/index.html) with support for extracting Dylib
* [**Disassembler**](https://lief.re/doc/latest/extended/disassembler/index.html): AArch64, x86/x86-64, ARM, RISC-V, Mips, PowerPC, eBPF
* [**Assembler**](https://lief.re/doc/latest/extended/assembler/index.html): AArch64, x86/x86-64
* [**Assembler**](https://lief.re/doc/latest/extended/assembler/index.html): AArch64, x86/x86-64, RISC-V
**Plugins**:
@@ -48,7 +49,7 @@ modify and abstract ELF, PE and MachO formats.
# Content
- [About](#about)
- [Download / Install](#downloads--install)
- [Downloads / Install](#downloads--install)
- [Getting started](#getting-started)
- [Blog](https://lief.re/blog/)
- [Documentation](#documentation)
@@ -66,33 +67,39 @@ modify and abstract ELF, PE and MachO formats.
- [ELF Coredump](https://lief.re/doc/latest/tutorials/12_elf_coredump.html)
- [PE Authenticode](https://lief.re/doc/latest/tutorials/13_pe_authenticode.html)
- [Contact](#contact)
- [About](#about)
- [About](#about-1)
- [Authors](#authors)
- [License](#license)
- [Bibtex](#bibtex)
- [BibTeX](#bibtex)
## Downloads / Install
## C++
### C++
```cmake
find_package(LIEF REQUIRED)
target_link_libraries(my-project LIEF::LIEF)
```
## Rust
### Rust
```toml
[package]
name = "my-awesome-project"
version = "0.0.1"
edition = "2021"
edition = "2024"
[dependencies]
lief = "0.17.3"
lief = "1.0.0"
```
## Python
### Homebrew
```console
brew install lief
```
### Python
To install the latest **version** (release):
@@ -103,7 +110,7 @@ pip install lief
To install nightly build:
```console
pip install [--user] --force-reinstall --index-url https://lief.s3-website.fr-par.scw.cloud/latest lief==1.0.0.dev0
pip install [--user] --force-reinstall --index-url https://lief.s3-website.fr-par.scw.cloud/latest lief==2.0.0.dev0
```
### Packages
@@ -112,13 +119,13 @@ pip install [--user] --force-reinstall --index-url https://lief.s3-website.fr-pa
- **Nightly**:
* SDK: https://lief.s3-website.fr-par.scw.cloud/latest/sdk
* Python Wheels: https://lief.s3-website.fr-par.scw.cloud/latest/lief
- **v0.17.3**: https://github.com/lief-project/LIEF/releases/tag/0.17.3
- **v1.0.0**: https://github.com/lief-project/LIEF/releases/tag/1.0.0
Here are guides to install or integrate LIEF:
* [Python](https://lief.re/doc/latest/installation.html#python)
* [Visual Studio](https://lief.re/doc/latest/installation.html#visual-studio-integration)
* [XCode](https://lief.re/doc/latest/installation.html#xcode-integration)
* [Xcode](https://lief.re/doc/latest/installation.html#xcode-integration)
* [CMake](https://lief.re/doc/latest/installation.html#cmake-integration)
## Getting started
@@ -134,15 +141,14 @@ for section in binary.sections:
print(section.name, section.virtual_address)
# PE
binary = lief.parse("C:\\Windows\\explorer.exe")
if rheader := pe.rich_header:
binary = lief.parse(r"C:\Windows\explorer.exe")
if (rheader := binary.rich_header) is not None:
print(rheader.key)
# Mach-O
binary = lief.parse("/usr/bin/ls")
for fixup in binary.dyld_chained_fixups:
print(fixup)
if (fixups := binary.dyld_chained_fixups) is not None:
print(fixups)
```
### Rust
@@ -163,27 +169,30 @@ if let Some(Binary::PE(pe)) = Binary::parse(path.as_str()) {
### C++
```cpp
#include <iostream>
#include <LIEF/LIEF.hpp>
int main(int argc, char** argv) {
// ELF
if (std::unique_ptr<const LIEF::ELF::Binary> elf = LIEF::ELF::Parser::parse("/bin/ls")) {
for (const LIEF::ELF::Section& section : elf->sections()) {
std::cout << section->name() << ' ' << section->virtual_address() << '\n';
std::cout << section.name() << ' ' << section.virtual_address() << '\n';
}
}
// PE
if (std::unique_ptr<const LIEF::PE::Binary> pe = LIEF::PE::Parser::parse("C:\\Windows\\explorer.exe")) {
if (const LIEF::PE::RichHeader* rheader : pe->rich_header()) {
if (const LIEF::PE::RichHeader* rheader = pe->rich_header()) {
std::cout << rheader->key() << '\n';
}
}
// Mach-O
if (std::unique_ptr<LIEF::MachO::FatBinary> macho = LIEF::MachO::Parser::parse("/bin/ls")) {
for (const LIEF::MachO::DyldChainedFixups& fixup : macho->dyld_chained_fixups()) {
std::cout << fixup << '\n';
for (const LIEF::MachO::Binary& bin : *macho) {
if (const LIEF::MachO::DyldChainedFixups* fixups = bin.dyld_chained_fixups()) {
std::cout << *fixups << '\n';
}
}
}
@@ -192,25 +201,6 @@ int main(int argc, char** argv) {
```
### C (Limited API)
```cpp
#include <LIEF/LIEF.h>
int main(int argc, char** argv) {
Elf_Binary_t* elf = elf_parse("/usr/bin/ls");
Elf_Section_t** sections = elf->sections;
for (size_t i = 0; sections[i] != NULL; ++i) {
printf("%s\n", sections[i]->name);
}
elf_binary_destroy(elf);
return 0;
}
```
## Documentation
* [Main documentation](https://lief.re/doc/latest/index.html)
@@ -230,9 +220,9 @@ Romain Thomas ([@rh0main](https://www.romainthomas.fr/)) - Formerly at [Quarksla
### License
LIEF is provided under the [Apache 2.0 license](https://github.com/lief-project/LIEF/blob/0.17.3/LICENSE).
[Apache 2.0](https://github.com/lief-project/LIEF/blob/1.0.0/LICENSE).
### Bibtex
### BibTeX
```bibtex
@MISC {LIEF,
@@ -243,5 +233,3 @@ LIEF is provided under the [Apache 2.0 license](https://github.com/lief-project/
year = "2017"
}
```
-4
View File
@@ -2,10 +2,6 @@ if (LIEF_PYTHON_API)
add_subdirectory(python)
endif()
if(LIEF_C_API)
add_subdirectory(c)
endif()
if(LIEF_RUST_API)
add_subdirectory(rust)
endif()
-15
View File
@@ -1,15 +0,0 @@
if(LIEF_ELF)
add_subdirectory(ELF)
endif()
if(LIEF_PE)
add_subdirectory(PE)
endif()
if(LIEF_MACHO)
add_subdirectory(MachO)
endif()
target_sources(LIB_LIEF PRIVATE logging.cpp)
target_include_directories(LIB_LIEF PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>")
-115
View File
@@ -1,115 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cstring>
#include "LIEF/ELF/Binary.h"
#include "LIEF/ELF/Section.h"
#include "LIEF/ELF/Segment.h"
#include "LIEF/ELF/Header.h"
#include "LIEF/ELF/Symbol.h"
#include "LIEF/ELF/Parser.hpp"
#include "LIEF/ELF/Binary.hpp"
#include "Section.hpp"
#include "Segment.hpp"
#include "DynamicEntry.hpp"
#include "Symbol.hpp"
#include "Header.hpp"
#include "Binary.hpp"
using namespace LIEF::ELF;
namespace LIEF {
namespace ELF {
void init_c_binary(Elf_Binary_t* c_binary, Binary* binary) {
c_binary->handler = reinterpret_cast<void*>(binary);
c_binary->type = static_cast<uint32_t>(binary->type());
c_binary->interpreter = nullptr;
if (binary->has_interpreter()) {
const std::string& interp = binary->interpreter();
c_binary->interpreter = static_cast<char*>(malloc((interp.size() + 1) * sizeof(char)));
std::memcpy(
reinterpret_cast<void*>(const_cast<char*>(c_binary->interpreter)),
reinterpret_cast<const void*>(interp.data()),
interp.size());
reinterpret_cast<char*>(const_cast<char*>(c_binary->interpreter))[interp.size()] = '\0';
}
init_c_header(c_binary, binary);
init_c_sections(c_binary, binary);
init_c_segments(c_binary, binary);
init_c_dynamic_symbols(c_binary, binary);
init_c_symtab_symbols(c_binary, binary);
init_c_dynamic_entries(c_binary, binary);
}
}
}
Elf_Binary_t* elf_parse(const char *file) {
Binary* binary = Parser::parse(file).release();
if (binary == nullptr) {
return nullptr;
}
auto* c_binary = static_cast<Elf_Binary_t*>(malloc(sizeof(Elf_Binary_t)));
memset(c_binary, 0, sizeof(Elf_Binary_t));
init_c_binary(c_binary, binary);
return c_binary;
}
// Binary Methods
// ==============
int elf_binary_save_header(Elf_Binary_t* binary) {
Header& hdr = reinterpret_cast<Binary*>(binary->handler)->header();
hdr.file_type(LIEF::ELF::Header::FILE_TYPE(binary->header.file_type));
hdr.machine_type(LIEF::ELF::ARCH(binary->header.machine_type));
hdr.object_file_version(LIEF::ELF::Header::VERSION(binary->header.object_file_version));
hdr.program_headers_offset(binary->header.program_headers_offset);
hdr.section_headers_offset(binary->header.section_headers_offset);
hdr.processor_flag(binary->header.processor_flags);
hdr.header_size(binary->header.header_size);
hdr.program_header_size(binary->header.program_header_size);
hdr.numberof_segments(binary->header.numberof_segments);
hdr.section_header_size(binary->header.section_header_size);
hdr.numberof_sections(binary->header.numberof_sections);
hdr.section_name_table_idx(binary->header.name_string_table_idx);
hdr.entrypoint(binary->header.entrypoint);
//TODO: identity
return 1;
}
void elf_binary_destroy(Elf_Binary_t* binary) {
destroy_sections(binary);
destroy_segments(binary);
destroy_dynamic_symbols(binary);
destroy_symtab_symbols(binary);
destroy_dynamic_entries(binary);
if (binary->interpreter != nullptr) {
free(const_cast<char*>(binary->interpreter));
}
delete reinterpret_cast<Binary*>(binary->handler);
free(binary);
}
//}
-9
View File
@@ -1,9 +0,0 @@
target_sources(LIB_LIEF PRIVATE
Symbol.cpp
Section.cpp
Segment.cpp
DynamicEntry.cpp
Header.cpp
Binary.cpp
utils.cpp
)
-219
View File
@@ -1,219 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "DynamicEntry.hpp"
#include "LIEF/ELF/DynamicEntryFlags.hpp"
#include "LIEF/ELF/DynamicSharedObject.hpp"
#include "LIEF/ELF/DynamicEntryLibrary.hpp"
#include "LIEF/ELF/DynamicEntryRpath.hpp"
#include "LIEF/ELF/DynamicEntryRunPath.hpp"
#include "LIEF/ELF/DynamicEntryArray.hpp"
namespace LIEF {
namespace ELF {
void init_c_dynamic_entries(Elf_Binary_t* c_binary, Binary* binary) {
Binary::it_dynamic_entries dyn_entries = binary->dynamic_entries();
c_binary->dynamic_entries = static_cast<Elf_DynamicEntry_t**>(
malloc((dyn_entries.size() + 1) * sizeof(Elf_DynamicEntry_t**)));
for (size_t i = 0; i < dyn_entries.size(); ++i) {
DynamicEntry& entry = dyn_entries[i];
switch(entry.tag()) {
case DynamicEntry::TAG::NEEDED:
{
auto* e = static_cast<Elf_DynamicEntry_Library_t*>(
malloc(sizeof(Elf_DynamicEntry_Library_t)));
e->tag = static_cast<uint64_t>(entry.tag());
e->value = entry.value();
e->name = reinterpret_cast<DynamicEntryLibrary*>(&entry)->name().c_str();
c_binary->dynamic_entries[i] = reinterpret_cast<Elf_DynamicEntry_t*>(e);
break;
}
case DynamicEntry::TAG::SONAME:
{
auto* e = static_cast<Elf_DynamicEntry_SharedObject_t*>(
malloc(sizeof(Elf_DynamicEntry_SharedObject_t)));
e->tag = static_cast<uint64_t>(entry.tag());
e->value = entry.value();
e->name = reinterpret_cast<DynamicSharedObject*>(&entry)->name().c_str();
c_binary->dynamic_entries[i] = reinterpret_cast<Elf_DynamicEntry_t*>(e);
break;
}
case DynamicEntry::TAG::RPATH:
{
auto* e = static_cast<Elf_DynamicEntry_Rpath_t*>(
malloc(sizeof(Elf_DynamicEntry_Rpath_t)));
e->tag = static_cast<uint64_t>(entry.tag());
e->value = entry.value();
e->rpath = reinterpret_cast<DynamicEntryRpath*>(&entry)->rpath().c_str();
c_binary->dynamic_entries[i] = reinterpret_cast<Elf_DynamicEntry_t*>(e);
break;
}
case DynamicEntry::TAG::RUNPATH:
{
auto* e = static_cast<Elf_DynamicEntry_RunPath_t*>(
malloc(sizeof(Elf_DynamicEntry_RunPath_t)));
e->tag = static_cast<uint64_t>(entry.tag());
e->value = entry.value();
e->runpath = reinterpret_cast<DynamicEntryRunPath*>(&entry)->runpath().c_str();
c_binary->dynamic_entries[i] = reinterpret_cast<Elf_DynamicEntry_t*>(e);
break;
}
case DynamicEntry::TAG::INIT_ARRAY:
case DynamicEntry::TAG::FINI_ARRAY:
case DynamicEntry::TAG::PREINIT_ARRAY:
{
auto* e = static_cast<Elf_DynamicEntry_Array_t*>(
malloc(sizeof(Elf_DynamicEntry_Array_t)));
e->tag = static_cast<uint64_t>(entry.tag());
e->value = entry.value();
const std::vector<uint64_t>& array = reinterpret_cast<DynamicEntryArray*>(&entry)->array();
e->array = static_cast<uint64_t*>(malloc((array.size() + 1) * sizeof(uint64_t)));
for (size_t i = 0; i < array.size(); ++i) {
e->array[i] = array[i];
}
e->array[array.size()] = 0;
c_binary->dynamic_entries[i] = reinterpret_cast<Elf_DynamicEntry_t*>(e);
break;
}
case DynamicEntry::TAG::FLAGS:
{
auto* e = static_cast<Elf_DynamicEntry_Flags_t*>(
malloc(sizeof(Elf_DynamicEntry_Flags_t)));
e->tag = static_cast<uint64_t>(entry.tag());
e->value = entry.value();
const DynamicEntryFlags::flags_list_t& flags = reinterpret_cast<DynamicEntryFlags*>(&entry)->flags();
c_binary->dynamic_entries[i] = reinterpret_cast<Elf_DynamicEntry_t*>(e);
break;
}
case DynamicEntry::TAG::FLAGS_1:
{
auto* e = static_cast<Elf_DynamicEntry_Flags_t*>(
malloc(sizeof(Elf_DynamicEntry_Flags_t)));
e->tag = static_cast<uint64_t>(entry.tag());
e->value = entry.value();
const DynamicEntryFlags::flags_list_t& flags = reinterpret_cast<DynamicEntryFlags*>(&entry)->flags();
c_binary->dynamic_entries[i] = reinterpret_cast<Elf_DynamicEntry_t*>(e);
break;
}
default:
{
c_binary->dynamic_entries[i] =
static_cast<Elf_DynamicEntry_t*>(malloc(sizeof(Elf_DynamicEntry_t)));
c_binary->dynamic_entries[i]->tag = static_cast<uint64_t>(entry.tag());
c_binary->dynamic_entries[i]->value = entry.value();
break;
}
}
}
c_binary->dynamic_entries[dyn_entries.size()] = nullptr;
}
void destroy_dynamic_entries(Elf_Binary_t* c_binary) {
Elf_DynamicEntry_t **dynamic_entries = c_binary->dynamic_entries;
for (size_t idx = 0; dynamic_entries[idx] != nullptr; ++idx) {
switch(DynamicEntry::TAG(dynamic_entries[idx]->tag)) {
case DynamicEntry::TAG::NEEDED:
{
free(reinterpret_cast<Elf_DynamicEntry_Library_t*>(dynamic_entries[idx]));
break;
}
case DynamicEntry::TAG::SONAME:
{
free(reinterpret_cast<Elf_DynamicEntry_SharedObject_t*>(dynamic_entries[idx]));
break;
}
case DynamicEntry::TAG::RPATH:
{
free(reinterpret_cast<Elf_DynamicEntry_Rpath_t*>(dynamic_entries[idx]));
break;
}
case DynamicEntry::TAG::RUNPATH:
{
free(reinterpret_cast<Elf_DynamicEntry_RunPath_t*>(dynamic_entries[idx]));
break;
}
case DynamicEntry::TAG::INIT_ARRAY:
case DynamicEntry::TAG::FINI_ARRAY:
case DynamicEntry::TAG::PREINIT_ARRAY:
{
Elf_DynamicEntry_Array_t* entry_array=reinterpret_cast<Elf_DynamicEntry_Array_t*>(dynamic_entries[idx]);
free(entry_array->array);
free(entry_array);
break;
}
case DynamicEntry::TAG::FLAGS:
{
Elf_DynamicEntry_Flags_t* entry_flags=reinterpret_cast<Elf_DynamicEntry_Flags_t*>(dynamic_entries[idx]);
free(entry_flags);
break;
}
case DynamicEntry::TAG::FLAGS_1:
{
Elf_DynamicEntry_Flags_t* entry_flags=reinterpret_cast<Elf_DynamicEntry_Flags_t*>(dynamic_entries[idx]);
free(entry_flags);
break;
}
default:
{
free(dynamic_entries[idx]);
}
}
}
free(c_binary->dynamic_entries);
}
}
}
-43
View File
@@ -1,43 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Header.hpp"
namespace LIEF {
namespace ELF {
void init_c_header(Elf_Binary_t* c_binary, Binary* binary) {
const Header& hdr = binary->header();
c_binary->header.file_type = static_cast<uint32_t>(hdr.file_type());
c_binary->header.machine_type = static_cast<uint32_t>(hdr.machine_type());
c_binary->header.object_file_version = static_cast<uint32_t>(hdr.object_file_version());
c_binary->header.program_headers_offset = hdr.program_headers_offset();
c_binary->header.section_headers_offset = hdr.section_headers_offset();
c_binary->header.processor_flags = hdr.processor_flag();
c_binary->header.header_size = hdr.header_size();
c_binary->header.program_header_size = hdr.program_header_size();
c_binary->header.numberof_segments = hdr.numberof_segments();
c_binary->header.section_header_size = hdr.section_header_size();
c_binary->header.numberof_sections = hdr.numberof_sections();
c_binary->header.name_string_table_idx = hdr.section_name_table_idx();
c_binary->header.entrypoint = hdr.entrypoint();
const Header::identity_t& ident = hdr.identity();
std::copy(std::begin(ident), std::end(ident), c_binary->header.identity);
}
}
}
-66
View File
@@ -1,66 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Section.hpp"
namespace LIEF {
namespace ELF {
void init_c_sections(Elf_Binary_t* c_binary, Binary* binary) {
Binary::it_sections sections = binary->sections();
c_binary->sections = static_cast<Elf_Section_t**>(
malloc((sections.size() + 1) * sizeof(Elf_Section_t**)));
for (size_t i = 0; i < sections.size(); ++i) {
Section& b_section = sections[i];
c_binary->sections[i] = static_cast<Elf_Section_t*>(malloc(sizeof(Elf_Section_t)));
span<const uint8_t> section_content = b_section.content();
c_binary->sections[i]->name = b_section.fullname().c_str();
c_binary->sections[i]->flags = b_section.flags();
c_binary->sections[i]->type = static_cast<uint32_t>(b_section.type());
c_binary->sections[i]->virtual_address = b_section.virtual_address();
c_binary->sections[i]->offset = b_section.file_offset();
c_binary->sections[i]->original_size = b_section.original_size();
c_binary->sections[i]->link = b_section.link();
c_binary->sections[i]->info = b_section.information();
c_binary->sections[i]->alignment = b_section.alignment();
c_binary->sections[i]->entry_size = b_section.entry_size();
c_binary->sections[i]->size = section_content.size();
c_binary->sections[i]->entropy = b_section.entropy();
c_binary->sections[i]->content = !section_content.empty() ?
const_cast<uint8_t*>(section_content.data()) : nullptr;
}
c_binary->sections[sections.size()] = nullptr;
}
void destroy_sections(Elf_Binary_t* c_binary) {
Elf_Section_t **sections = c_binary->sections;
for (size_t idx = 0; sections[idx] != nullptr; ++idx) {
free(sections[idx]);
}
free(c_binary->sections);
}
}
}
-59
View File
@@ -1,59 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Segment.hpp"
namespace LIEF {
namespace ELF {
void init_c_segments(Elf_Binary_t* c_binary, Binary* binary) {
Binary::it_segments segments = binary->segments();
c_binary->segments = static_cast<Elf_Segment_t**>(
malloc((segments.size() + 1) * sizeof(Elf_Segment_t**)));
for (size_t i = 0; i < segments.size(); ++i) {
Segment& segment = segments[i];
span<const uint8_t> segment_content = segment.content();
c_binary->segments[i] = static_cast<Elf_Segment_t*>(malloc(sizeof(Elf_Segment_t)));
c_binary->segments[i]->type = static_cast<uint32_t>(segment.type());
c_binary->segments[i]->flags = static_cast<uint32_t>(segment.flags());
c_binary->segments[i]->virtual_address = segment.virtual_address();
c_binary->segments[i]->virtual_size = segment.virtual_size();
c_binary->segments[i]->offset = segment.file_offset();
c_binary->segments[i]->alignment = segment.alignment();
c_binary->segments[i]->size = segment_content.size();
c_binary->segments[i]->content = !segment_content.empty() ?
const_cast<uint8_t*>(segment_content.data()) : nullptr;
}
c_binary->segments[segments.size()] = nullptr;
}
void destroy_segments(Elf_Binary_t* c_binary) {
Elf_Segment_t **segments = c_binary->segments;
for (size_t idx = 0; segments[idx] != nullptr; ++idx) {
free(segments[idx]);
}
free(c_binary->segments);
}
}
}
-92
View File
@@ -1,92 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Symbol.hpp"
namespace LIEF {
namespace ELF {
void init_c_dynamic_symbols(Elf_Binary_t* c_binary, Binary* binary) {
Binary::it_dynamic_symbols dyn_symb = binary->dynamic_symbols();
c_binary->dynamic_symbols = static_cast<Elf_Symbol_t**>(
malloc((dyn_symb.size() + 1) * sizeof(Elf_Symbol_t**)));
for (size_t i = 0; i < dyn_symb.size(); ++i) {
Symbol& b_sym = dyn_symb[i];
c_binary->dynamic_symbols[i] = static_cast<Elf_Symbol_t*>(malloc(sizeof(Elf_Symbol_t)));
c_binary->dynamic_symbols[i]->name = b_sym.name().c_str();
c_binary->dynamic_symbols[i]->type = static_cast<uint32_t>(b_sym.type());
c_binary->dynamic_symbols[i]->binding = static_cast<uint32_t>(b_sym.binding());
c_binary->dynamic_symbols[i]->other = b_sym.other();
c_binary->dynamic_symbols[i]->shndx = b_sym.shndx();
c_binary->dynamic_symbols[i]->value = b_sym.value();
c_binary->dynamic_symbols[i]->size = b_sym.size();
c_binary->dynamic_symbols[i]->information = b_sym.information();
c_binary->dynamic_symbols[i]->is_exported = b_sym.is_exported();
c_binary->dynamic_symbols[i]->is_imported = b_sym.is_imported();
}
c_binary->dynamic_symbols[dyn_symb.size()] = nullptr;
}
void init_c_symtab_symbols(Elf_Binary_t* c_binary, Binary* binary) {
Binary::it_symtab_symbols static_symb = binary->symtab_symbols();
c_binary->symtab_symbols = static_cast<Elf_Symbol_t**>(
malloc((static_symb.size() + 1) * sizeof(Elf_Symbol_t**)));
for (size_t i = 0; i < static_symb.size(); ++i) {
Symbol& b_sym = static_symb[i];
c_binary->symtab_symbols[i] = static_cast<Elf_Symbol_t*>(malloc(sizeof(Elf_Symbol_t)));
c_binary->symtab_symbols[i]->name = b_sym.name().c_str();
c_binary->symtab_symbols[i]->type = static_cast<uint32_t>(b_sym.type());
c_binary->symtab_symbols[i]->binding = static_cast<uint32_t>(b_sym.binding());
c_binary->symtab_symbols[i]->other = b_sym.other();
c_binary->symtab_symbols[i]->shndx = b_sym.shndx();
c_binary->symtab_symbols[i]->value = b_sym.value();
c_binary->symtab_symbols[i]->size = b_sym.size();
c_binary->symtab_symbols[i]->information = b_sym.information();
c_binary->symtab_symbols[i]->is_exported = b_sym.is_exported();
c_binary->symtab_symbols[i]->is_imported = b_sym.is_imported();
}
c_binary->symtab_symbols[static_symb.size()] = nullptr;
}
void destroy_dynamic_symbols(Elf_Binary_t* c_binary) {
Elf_Symbol_t **dynamic_symbols = c_binary->dynamic_symbols;
for (size_t idx = 0; dynamic_symbols[idx] != nullptr; ++idx) {
free(dynamic_symbols[idx]);
}
free(c_binary->dynamic_symbols);
}
void destroy_symtab_symbols(Elf_Binary_t* c_binary) {
Elf_Symbol_t **symtab_symbols = c_binary->symtab_symbols;
for (size_t idx = 0; symtab_symbols[idx] != nullptr; ++idx) {
free(symtab_symbols[idx]);
}
free(c_binary->symtab_symbols);
}
}
}
-37
View File
@@ -1,37 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_ELF_SYMBOL_CPP_C_API_
#define LIEF_ELF_SYMBOL_CPP_C_API_
#include "LIEF/ELF/Binary.h"
#include "LIEF/ELF/Binary.hpp"
#include "LIEF/ELF/Symbol.h"
#include "LIEF/ELF/Symbol.hpp"
namespace LIEF {
namespace ELF {
void init_c_dynamic_symbols(Elf_Binary_t* c_binary, Binary* binary);
void init_c_symtab_symbols(Elf_Binary_t* c_binary, Binary* binary);
void destroy_dynamic_symbols(Elf_Binary_t* c_binary);
void destroy_symtab_symbols(Elf_Binary_t* c_binary);
}
}
#endif
-57
View File
@@ -1,57 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "LIEF/MachO/Binary.h"
#include "LIEF/MachO/Binary.hpp"
#include "Binary.hpp"
#include "Section.hpp"
#include "Header.hpp"
#include "Symbol.hpp"
#include "Segment.hpp"
#include "LoadCommand.hpp"
using namespace LIEF::MachO;
namespace LIEF {
namespace MachO {
void init_c_binary(Macho_Binary_t* c_binary, Binary* binary) {
c_binary->handler = reinterpret_cast<void*>(binary);
c_binary->imagebase = binary->imagebase();
init_c_header(c_binary, binary);
init_c_commands(c_binary, binary);
init_c_symbols(c_binary, binary);
init_c_sections(c_binary, binary);
init_c_segments(c_binary, binary);
}
}
}
void macho_binaries_destroy(Macho_Binary_t** binaries) {
for (size_t i = 0; binaries[i] != nullptr; ++i) {
destroy_sections(binaries[i]);
destroy_commands(binaries[i]);
destroy_symbols(binaries[i]);
destroy_segments(binaries[i]);
delete reinterpret_cast<Binary*>(binaries[i]->handler);
free(binaries[i]);
}
free(binaries);
}
-9
View File
@@ -1,9 +0,0 @@
target_sources(LIB_LIEF PRIVATE
Parser.cpp
LoadCommand.cpp
Segment.cpp
Symbol.cpp
Section.cpp
Header.cpp
Binary.cpp
)
-33
View File
@@ -1,33 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Header.hpp"
namespace LIEF {
namespace MachO {
void init_c_header(Macho_Binary_t* c_binary, Binary* binary) {
Header& header = binary->header();
c_binary->header.magic = static_cast<uint32_t>(header.magic());
c_binary->header.cpu_type = static_cast<enum LIEF_MACHO_CPU_TYPES>(header.cpu_type());
c_binary->header.cpu_subtype = header.cpu_subtype();
c_binary->header.file_type = static_cast<enum LIEF_MACHO_FILE_TYPES>(header.file_type());
c_binary->header.nb_cmds = header.nb_cmds();
c_binary->header.sizeof_cmds = header.sizeof_cmds();
c_binary->header.flags = header.flags();
c_binary->header.reserved = header.reserved();
}
}
}
-62
View File
@@ -1,62 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "LoadCommand.hpp"
namespace LIEF {
namespace MachO {
void init_c_commands(Macho_Binary_t* c_binary, Binary* binary) {
Binary::it_commands commands = binary->commands();
c_binary->commands = static_cast<Macho_Command_t**>(
malloc((commands.size() + 1) * sizeof(Macho_Command_t**)));
for (size_t i = 0; i < commands.size(); ++i) {
LoadCommand& cmd = commands[i];
c_binary->commands[i] = static_cast<Macho_Command_t*>(malloc(sizeof(Macho_Command_t)));
const span<const uint8_t> cmd_content = cmd.data();
auto* content = static_cast<uint8_t*>(malloc(cmd_content.size() * sizeof(uint8_t)));
std::copy(
std::begin(cmd_content),
std::end(cmd_content),
content);
c_binary->commands[i]->command = static_cast<enum LIEF_MACHO_LOAD_COMMAND_TYPES>(cmd.command());
c_binary->commands[i]->size = cmd.size();
c_binary->commands[i]->data = content;
c_binary->commands[i]->offset = cmd.command_offset();
}
c_binary->commands[commands.size()] = nullptr;
}
void destroy_commands(Macho_Binary_t* c_binary) {
Macho_Command_t **commands = c_binary->commands;
for (size_t idx = 0; commands[idx] != nullptr; ++idx) {
free(commands[idx]->data);
free(commands[idx]);
}
free(c_binary->commands);
}
}
}
-34
View File
@@ -1,34 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_MACHO_LOAD_COMMAND_CPP_C_API_
#define LIEF_MACHO_LOAD_COMMAND_CPP_C_API_
#include "LIEF/MachO/Binary.h"
#include "LIEF/MachO/Binary.hpp"
#include "LIEF/MachO/LoadCommand.h"
#include "LIEF/MachO/LoadCommand.hpp"
namespace LIEF {
namespace MachO {
void init_c_commands(Macho_Binary_t* c_binary, Binary* binary);
void destroy_commands(Macho_Binary_t* c_binary);
}
}
#endif
-52
View File
@@ -1,52 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cstring>
#include "LIEF/MachO/Binary.h"
#include "LIEF/MachO/Parser.hpp"
#include "LIEF/MachO/FatBinary.hpp"
#include "Binary.hpp"
using namespace LIEF::MachO;
Macho_Binary_t** macho_parse(const char *file) {
FatBinary* fat = Parser::parse(file).release();
if (fat == nullptr) {
return nullptr;
}
size_t nb_bin = fat->size();
auto** c_macho_binaries = static_cast<Macho_Binary_t**>(
malloc((fat->size() + 1) * sizeof(Macho_Binary_t**)));
for (size_t i = 0; i < nb_bin; ++i) {
Binary* binary = fat->at(i);
if (binary != nullptr) {
c_macho_binaries[i] = static_cast<Macho_Binary_t*>(malloc(sizeof(Macho_Binary_t)));
init_c_binary(c_macho_binaries[i], binary);
}
}
fat->release_all_binaries();
c_macho_binaries[nb_bin] = nullptr;
delete fat;
return c_macho_binaries;
}
-68
View File
@@ -1,68 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Section.hpp"
namespace LIEF {
namespace MachO {
void init_c_sections(Macho_Binary_t* c_binary, Binary* binary) {
Binary::it_sections sections = binary->sections();
c_binary->sections = static_cast<Macho_Section_t**>(
malloc((sections.size() + 1) * sizeof(Macho_Section_t**)));
for (size_t i = 0; i < sections.size(); ++i) {
const Section& section = sections[i];
c_binary->sections[i] = static_cast<Macho_Section_t*>(malloc(sizeof(Macho_Section_t)));
span<const uint8_t> section_content = section.content();
auto* content = static_cast<uint8_t*>(malloc(section_content.size() * sizeof(uint8_t)));
std::copy(std::begin(section_content), std::end(section_content),
content);
c_binary->sections[i]->name = section.fullname().c_str();
c_binary->sections[i]->alignment = section.alignment();
c_binary->sections[i]->relocation_offset = section.relocation_offset();
c_binary->sections[i]->numberof_relocations = section.numberof_relocations();
c_binary->sections[i]->flags = section.raw_flags();
c_binary->sections[i]->type = static_cast<enum LIEF_MACHO_MACHO_SECTION_TYPES>(section.type());
c_binary->sections[i]->reserved1 = section.reserved1();
c_binary->sections[i]->reserved2 = section.reserved2();
c_binary->sections[i]->reserved3 = section.reserved3();
c_binary->sections[i]->virtual_address = section.virtual_address();
c_binary->sections[i]->offset = section.offset();
c_binary->sections[i]->size = section_content.size();
c_binary->sections[i]->content = content;
c_binary->sections[i]->entropy = section.entropy();
}
c_binary->sections[sections.size()] = nullptr;
}
void destroy_sections(Macho_Binary_t* c_binary) {
Macho_Section_t **sections = c_binary->sections;
for (size_t idx = 0; sections[idx] != nullptr; ++idx) {
free(sections[idx]->content);
free(sections[idx]);
}
free(c_binary->sections);
}
}
}
-34
View File
@@ -1,34 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_MACHO_SECTION_CPP_C_API_
#define LIEF_MACHO_SECTION_CPP_C_API_
#include "LIEF/MachO/Binary.h"
#include "LIEF/MachO/Binary.hpp"
#include "LIEF/MachO/Section.h"
#include "LIEF/MachO/Section.hpp"
namespace LIEF {
namespace MachO {
void init_c_sections(Macho_Binary_t* c_binary, Binary* binary);
void destroy_sections(Macho_Binary_t* c_binary);
}
}
#endif
-70
View File
@@ -1,70 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Segment.hpp"
namespace LIEF {
namespace MachO {
void init_c_segments(Macho_Binary_t* c_binary, Binary* binary) {
Binary::it_segments segments = binary->segments();
c_binary->segments = static_cast<Macho_Segment_t**>(
malloc((segments.size() + 1) * sizeof(Macho_Segment_t**)));
for (size_t i = 0; i < segments.size(); ++i) {
SegmentCommand& segment = segments[i];
c_binary->segments[i] = static_cast<Macho_Segment_t*>(malloc(sizeof(Macho_Segment_t)));
span<const uint8_t> segment_content = segment.content();
auto* content = static_cast<uint8_t*>(malloc(segment_content.size() * sizeof(uint8_t)));
std::copy(
std::begin(segment_content),
std::end(segment_content),
content);
c_binary->segments[i]->name = segment.name().c_str();
c_binary->segments[i]->virtual_address = segment.virtual_address();
c_binary->segments[i]->virtual_size = segment.virtual_size();
c_binary->segments[i]->file_size = segment.file_size();
c_binary->segments[i]->file_offset = segment.file_offset();
c_binary->segments[i]->max_protection = segment.max_protection();
c_binary->segments[i]->init_protection = segment.init_protection();
c_binary->segments[i]->numberof_sections = segment.numberof_sections();
c_binary->segments[i]->flags = segment.flags();
c_binary->segments[i]->content = content;
c_binary->segments[i]->size = segment_content.size();
c_binary->segments[i]->sections = nullptr; //TODO
}
c_binary->segments[segments.size()] = nullptr;
}
void destroy_segments(Macho_Binary_t* c_binary) {
Macho_Segment_t **segments = c_binary->segments;
for (size_t idx = 0; segments[idx] != nullptr; ++idx) {
free(segments[idx]->content);
free(segments[idx]);
}
free(c_binary->segments);
}
}
}
-34
View File
@@ -1,34 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_MACHO_SEGMENT_CPP_C_API_
#define LIEF_MACHO_SEGMENT_CPP_C_API_
#include "LIEF/MachO/Binary.h"
#include "LIEF/MachO/Binary.hpp"
#include "LIEF/MachO/Segment.h"
#include "LIEF/MachO/SegmentCommand.hpp"
namespace LIEF {
namespace MachO {
void init_c_segments(Macho_Binary_t* c_binary, Binary* binary);
void destroy_segments(Macho_Binary_t* c_binary);
}
}
#endif
-56
View File
@@ -1,56 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Symbol.hpp"
namespace LIEF {
namespace MachO {
void init_c_symbols(Macho_Binary_t* c_binary, Binary* binary) {
Binary::it_symbols symbols = binary->symbols();
c_binary->symbols = static_cast<Macho_Symbol_t**>(
malloc((symbols.size() + 1) * sizeof(Macho_Symbol_t**)));
for (size_t i = 0; i < symbols.size(); ++i) {
const Symbol& symbol = symbols[i];
c_binary->symbols[i] = static_cast<Macho_Symbol_t*>(malloc(sizeof(Macho_Symbol_t)));
c_binary->symbols[i]->name = symbol.name().c_str();
c_binary->symbols[i]->type = symbol.raw_type();
c_binary->symbols[i]->numberof_sections = symbol.numberof_sections();
c_binary->symbols[i]->description = symbol.description();
c_binary->symbols[i]->value = symbol.value();
}
c_binary->symbols[symbols.size()] = nullptr;
}
void destroy_symbols(Macho_Binary_t* c_binary) {
Macho_Symbol_t **symbols = c_binary->symbols;
for (size_t idx = 0; symbols[idx] != nullptr; ++idx) {
free(symbols[idx]);
}
free(c_binary->symbols);
}
}
}
-71
View File
@@ -1,71 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cstring>
#include "LIEF/PE/Binary.h"
#include "LIEF/PE/Parser.hpp"
#include "LIEF/PE/Binary.hpp"
#include "Binary.hpp"
#include "DosHeader.hpp"
#include "Header.hpp"
#include "OptionalHeader.hpp"
#include "Section.hpp"
#include "DataDirectory.hpp"
#include "Import.hpp"
using namespace LIEF::PE;
namespace LIEF {
namespace PE {
void init_c_binary(Pe_Binary_t* c_binary, Binary* binary) {
c_binary->handler = reinterpret_cast<void*>(binary);
init_c_dos_header(c_binary, binary);
init_c_header(c_binary, binary);
init_c_optional_header(c_binary, binary);
init_c_sections(c_binary, binary);
init_c_data_directories(c_binary, binary);
init_c_imports(c_binary, binary);
}
}
}
Pe_Binary_t* pe_parse(const char *file) {
Binary* binary = Parser::parse(file).release();
if (binary == nullptr) {
return nullptr;
}
auto* c_binary = static_cast<Pe_Binary_t*>(malloc(sizeof(Pe_Binary_t)));
std::memset(c_binary, 0, sizeof(Pe_Binary_t));
init_c_binary(c_binary, binary);
return c_binary;
}
void pe_binary_destroy(Pe_Binary_t* binary) {
destroy_sections(binary);
destroy_data_directories(binary);
destroy_imports(binary);
delete reinterpret_cast<Binary*>(binary->handler);
free(binary);
}
-10
View File
@@ -1,10 +0,0 @@
target_sources(LIB_LIEF PRIVATE
Binary.cpp
DosHeader.cpp
Header.cpp
OptionalHeader.cpp
Section.cpp
DataDirectory.cpp
Import.cpp
ImportEntry.cpp
)
-54
View File
@@ -1,54 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "DataDirectory.hpp"
namespace LIEF {
namespace PE {
void init_c_data_directories(Pe_Binary_t* c_binary, Binary* binary) {
Binary::it_data_directories data_directories = binary->data_directories();
c_binary->data_directories = static_cast<Pe_DataDirectory_t**>(
malloc((data_directories.size() + 1) * sizeof(Pe_DataDirectory_t**)));
for (size_t i = 0; i < data_directories.size(); ++i) {
c_binary->data_directories[i] = static_cast<Pe_DataDirectory_t*>(malloc(sizeof(Pe_DataDirectory_t)));
c_binary->data_directories[i]->rva = data_directories[i].RVA();
c_binary->data_directories[i]->size = data_directories[i].size();
}
c_binary->data_directories[data_directories.size()] = nullptr;
}
void destroy_data_directories(Pe_Binary_t* c_binary) {
Pe_DataDirectory_t **data_directories = c_binary->data_directories;
for (size_t idx = 0; data_directories[idx] != nullptr; ++idx) {
free(data_directories[idx]);
}
free(c_binary->data_directories);
}
}
}
-34
View File
@@ -1,34 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_PE_DATA_DIRECTORY_CPP_C_API
#define LIEF_PE_DATA_DIRECTORY_CPP_C_API
#include "LIEF/PE/Binary.h"
#include "LIEF/PE/Binary.hpp"
#include "LIEF/PE/DataDirectory.h"
#include "LIEF/PE/DataDirectory.hpp"
namespace LIEF {
namespace PE {
void init_c_data_directories(Pe_Binary_t* c_binary, Binary* binary);
void destroy_data_directories(Pe_Binary_t* c_binary);
}
}
#endif
-55
View File
@@ -1,55 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "DosHeader.hpp"
namespace LIEF {
namespace PE {
void init_c_dos_header(Pe_Binary_t* c_binary, Binary* binary) {
const DosHeader& dos_header = binary->dos_header();
c_binary->dos_header.magic = dos_header.magic();
c_binary->dos_header.used_bytes_in_last_page = dos_header.used_bytes_in_last_page();
c_binary->dos_header.file_size_in_pages = dos_header.file_size_in_pages();
c_binary->dos_header.numberof_relocation = dos_header.numberof_relocation();
c_binary->dos_header.header_size_in_paragraphs = dos_header.header_size_in_paragraphs();
c_binary->dos_header.minimum_extra_paragraphs = dos_header.minimum_extra_paragraphs();
c_binary->dos_header.maximum_extra_paragraphs = dos_header.maximum_extra_paragraphs();
c_binary->dos_header.initial_relative_ss = dos_header.initial_relative_ss();
c_binary->dos_header.initial_sp = dos_header.initial_sp();
c_binary->dos_header.checksum = dos_header.checksum();
c_binary->dos_header.initial_ip = dos_header.initial_ip();
c_binary->dos_header.initial_relative_cs = dos_header.initial_relative_cs();
c_binary->dos_header.addressof_relocation_table = dos_header.addressof_relocation_table();
c_binary->dos_header.overlay_number = dos_header.overlay_number();
c_binary->dos_header.oem_id = dos_header.oem_id();
c_binary->dos_header.oem_info = dos_header.oem_info();
c_binary->dos_header.addressof_new_exeheader = dos_header.addressof_new_exeheader();
const DosHeader::reserved_t& reserved = dos_header.reserved();
std::copy(
std::begin(reserved),
std::end(reserved),
c_binary->dos_header.reserved);
const DosHeader::reserved2_t& reserved2 = dos_header.reserved2();
std::copy(
std::begin(reserved2),
std::end(reserved2),
c_binary->dos_header.reserved2);
}
}
}
-33
View File
@@ -1,33 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_PE_DOS_HEADER_CPP_C_API_
#define LIEF_PE_DOS_HEADER_CPP_C_API_
#include "LIEF/PE/Binary.h"
#include "LIEF/PE/Binary.hpp"
#include "LIEF/PE/DosHeader.h"
#include "LIEF/PE/DosHeader.hpp"
namespace LIEF {
namespace PE {
void init_c_dos_header(Pe_Binary_t* c_binary, Binary* binary);
}
}
#endif
-49
View File
@@ -1,49 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Header.hpp"
namespace LIEF {
namespace PE {
void init_c_header(Pe_Binary_t* c_binary, Binary* binary) {
const Header& header = binary->header();
const Header::signature_t& signature = header.signature();
c_binary->header.machine = static_cast<enum LIEF_PE_MACHINE_TYPES>(header.machine());
c_binary->header.numberof_sections = header.numberof_sections();
c_binary->header.time_date_stamp = header.time_date_stamp();
c_binary->header.pointerto_symbol_table = header.pointerto_symbol_table();
c_binary->header.numberof_symbols = header.numberof_symbols();
c_binary->header.sizeof_optional_header = header.sizeof_optional_header();
c_binary->header.characteristics = static_cast<uint16_t>(header.characteristics());
std::copy(std::begin(signature), std::end(signature),
c_binary->header.signature);
}
}
}
const char* lief_pe_header_machine_str(enum LIEF_PE_MACHINE_TYPES e) {
return LIEF::PE::to_string(static_cast<LIEF::PE::Header::MACHINE_TYPES>(e));
}
const char* lief_pe_header_characteristics_str(enum LIEF_PE_HEADER_CHARACTERISTICS e) {
return LIEF::PE::to_string(static_cast<LIEF::PE::Header::CHARACTERISTICS>(e));
}
-33
View File
@@ -1,33 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_PE_HEADER_CPP_C_API_
#define LIEF_PE_HEADER_CPP_C_API_
#include "LIEF/PE/Binary.h"
#include "LIEF/PE/Binary.hpp"
#include "LIEF/PE/Header.h"
#include "LIEF/PE/Header.hpp"
namespace LIEF {
namespace PE {
void init_c_header(Pe_Binary_t* c_binary, Binary* binary);
}
}
#endif
-65
View File
@@ -1,65 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Import.hpp"
#include "ImportEntry.hpp"
namespace LIEF {
namespace PE {
void init_c_imports(Pe_Binary_t* c_binary, Binary* binary) {
if (!binary->has_imports()) {
c_binary->imports = nullptr;
}
Binary::it_imports imports = binary->imports();
c_binary->imports = static_cast<Pe_Import_t**>(
malloc((imports.size() + 1) * sizeof(Pe_Import_t**)));
for (size_t i = 0; i < imports.size(); ++i) {
Import& imp = imports[i];
c_binary->imports[i] = static_cast<Pe_Import_t*>(malloc(sizeof(Pe_Import_t)));
c_binary->imports[i]->name = imp.name().c_str();
c_binary->imports[i]->forwarder_chain = imp.forwarder_chain();
c_binary->imports[i]->timedatestamp = imp.forwarder_chain();
c_binary->imports[i]->import_address_table_rva = imp.import_address_table_rva();
c_binary->imports[i]->import_lookup_table_rva = imp.import_lookup_table_rva();
c_binary->imports[i]->entries = nullptr;
init_c_import_entries(c_binary->imports[i], imp);
}
c_binary->imports[imports.size()] = nullptr;
}
void destroy_imports(Pe_Binary_t* c_binary) {
if (c_binary->imports == nullptr) {
return;
}
Pe_Import_t **imports = c_binary->imports;
for (size_t idx = 0; imports[idx] != nullptr; ++idx) {
destroy_import_entries(imports[idx]);
free(imports[idx]);
}
free(c_binary->imports);
}
}
}
-34
View File
@@ -1,34 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_PE_IMPORT_CPP_C_API_
#define LIEF_PE_IMPORT_CPP_C_API_
#include "LIEF/PE/Binary.h"
#include "LIEF/PE/Binary.hpp"
#include "LIEF/PE/Import.h"
#include "LIEF/PE/Import.hpp"
namespace LIEF {
namespace PE {
void init_c_imports(Pe_Binary_t* c_binary, Binary* binary);
void destroy_imports(Pe_Binary_t* c_binary);
}
}
#endif
-57
View File
@@ -1,57 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ImportEntry.hpp"
namespace LIEF {
namespace PE {
void init_c_import_entries(Pe_Import_t* c_import, Import& imp) {
Import::it_entries entries = imp.entries();
c_import->entries = static_cast<Pe_ImportEntry_t**>(
malloc((entries.size() + 1) * sizeof(Pe_ImportEntry_t**)));
for (size_t i = 0; i < entries.size(); ++i) {
ImportEntry& import_entry = entries[i];
c_import->entries[i] = static_cast<Pe_ImportEntry_t*>(malloc(sizeof(Pe_ImportEntry_t)));
c_import->entries[i]->is_ordinal = import_entry.is_ordinal();
c_import->entries[i]->name = import_entry.is_ordinal() ? nullptr : import_entry.name().c_str();
c_import->entries[i]->ordinal = import_entry.is_ordinal() ? import_entry.ordinal() : 0;
c_import->entries[i]->hint_name_rva = import_entry.hint_name_rva();
c_import->entries[i]->hint = import_entry.hint();
c_import->entries[i]->iat_value = import_entry.iat_value();
c_import->entries[i]->data = import_entry.data();
c_import->entries[i]->iat_address = import_entry.iat_address();
}
c_import->entries[entries.size()] = nullptr;
}
void destroy_import_entries(Pe_Import_t* c_import) {
Pe_ImportEntry_t **entries = c_import->entries;
for (size_t idx = 0; entries[idx] != nullptr; ++idx) {
free(entries[idx]);
}
free(c_import->entries);
}
}
}
-34
View File
@@ -1,34 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_PE_IMPORT_ENTRY_CPP_C_API_
#define LIEF_PE_IMPORT_ENTRY_CPP_C_API_
#include "LIEF/PE/Binary.h"
#include "LIEF/PE/Binary.hpp"
#include "LIEF/PE/ImportEntry.h"
#include "LIEF/PE/ImportEntry.hpp"
namespace LIEF {
namespace PE {
void init_c_import_entries(Pe_Import_t* c_import, Import& imp);
void destroy_import_entries(Pe_Import_t* c_import);
}
}
#endif
-67
View File
@@ -1,67 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "OptionalHeader.hpp"
#include "LIEF/PE/OptionalHeader.h"
namespace LIEF {
namespace PE {
void init_c_optional_header(Pe_Binary_t* c_binary, Binary* binary) {
const OptionalHeader& optional_header = binary->optional_header();
c_binary->optional_header.magic = static_cast<uint16_t>(optional_header.magic());
c_binary->optional_header.major_linker_version = optional_header.major_linker_version();
c_binary->optional_header.minor_linker_version = optional_header.minor_linker_version();
c_binary->optional_header.sizeof_code = optional_header.sizeof_code();
c_binary->optional_header.sizeof_initialized_data = optional_header.sizeof_initialized_data();
c_binary->optional_header.sizeof_uninitialized_data = optional_header.sizeof_uninitialized_data();
c_binary->optional_header.addressof_entrypoint = optional_header.addressof_entrypoint();
c_binary->optional_header.baseof_code = optional_header.baseof_code();
if (optional_header.magic() == PE_TYPE::PE32) {
c_binary->optional_header.baseof_data = optional_header.baseof_data();
} else {
c_binary->optional_header.baseof_data = 0;
}
c_binary->optional_header.imagebase = optional_header.imagebase();
c_binary->optional_header.section_alignment = optional_header.section_alignment();
c_binary->optional_header.file_alignment = optional_header.file_alignment();
c_binary->optional_header.major_operating_system_version = optional_header.major_operating_system_version();
c_binary->optional_header.minor_operating_system_version = optional_header.minor_operating_system_version();
c_binary->optional_header.major_image_version = optional_header.major_image_version();
c_binary->optional_header.minor_image_version = optional_header.minor_image_version();
c_binary->optional_header.major_subsystem_version = optional_header.major_subsystem_version();
c_binary->optional_header.minor_subsystem_version = optional_header.minor_subsystem_version();
c_binary->optional_header.win32_version_value = optional_header.win32_version_value();
c_binary->optional_header.sizeof_image = optional_header.sizeof_image();
c_binary->optional_header.sizeof_headers = optional_header.sizeof_headers();
c_binary->optional_header.checksum = optional_header.checksum();
c_binary->optional_header.subsystem = static_cast<enum LIEF_PE_SUBSYSTEM>(optional_header.subsystem());
c_binary->optional_header.dll_characteristics = optional_header.dll_characteristics();
c_binary->optional_header.sizeof_stack_reserve = optional_header.sizeof_stack_reserve();
c_binary->optional_header.sizeof_stack_commit = optional_header.sizeof_stack_commit();
c_binary->optional_header.sizeof_heap_reserve = optional_header.sizeof_heap_reserve();
c_binary->optional_header.sizeof_heap_commit = optional_header.sizeof_heap_commit();
c_binary->optional_header.loader_flags = optional_header.loader_flags();
c_binary->optional_header.numberof_rva_and_size = optional_header.numberof_rva_and_size();
}
}
}
const char* lief_pe_subsytem_str(enum LIEF_PE_SUBSYSTEM e) {
return LIEF::PE::to_string(static_cast<LIEF::PE::OptionalHeader::SUBSYSTEM>(e));
}
-33
View File
@@ -1,33 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_PE_OPTIONAL_HEADER_CPP_C_API_
#define LIEF_PE_OPTIONAL_HEADER_CPP_C_API_
#include "LIEF/PE/Binary.h"
#include "LIEF/PE/Binary.hpp"
#include "LIEF/PE/OptionalHeader.h"
#include "LIEF/PE/OptionalHeader.hpp"
namespace LIEF {
namespace PE {
void init_c_optional_header(Pe_Binary_t* c_binary, Binary* binary);
}
}
#endif
-71
View File
@@ -1,71 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Section.hpp"
namespace LIEF {
namespace PE {
void init_c_sections(Pe_Binary_t* c_binary, Binary* binary) {
Binary::it_sections sections = binary->sections();
c_binary->sections = static_cast<Pe_Section_t**>(
malloc((sections.size() + 1) * sizeof(Pe_Section_t**)));
for (size_t i = 0; i < sections.size(); ++i) {
Section& b_section = sections[i];
c_binary->sections[i] = static_cast<Pe_Section_t*>(malloc(sizeof(Pe_Section_t)));
span<const uint8_t> section_content = b_section.content();
uint8_t* content = nullptr;
if (!section_content.empty()) {
content = static_cast<uint8_t*>(malloc(section_content.size() * sizeof(uint8_t)));
std::copy(std::begin(section_content), std::end(section_content),
content);
}
c_binary->sections[i]->name = b_section.fullname().c_str();
c_binary->sections[i]->virtual_address = b_section.virtual_address();
c_binary->sections[i]->size = b_section.size();
c_binary->sections[i]->offset = b_section.offset();
c_binary->sections[i]->virtual_size = b_section.virtual_size();
c_binary->sections[i]->pointerto_relocation = b_section.pointerto_relocation();
c_binary->sections[i]->pointerto_line_numbers = b_section.pointerto_line_numbers();
c_binary->sections[i]->characteristics = b_section.characteristics();
c_binary->sections[i]->content = content;
c_binary->sections[i]->content_size = section_content.size();
c_binary->sections[i]->entropy = b_section.entropy();
}
c_binary->sections[sections.size()] = nullptr;
}
void destroy_sections(Pe_Binary_t* c_binary) {
Pe_Section_t **sections = c_binary->sections;
for (size_t idx = 0; sections[idx] != nullptr; ++idx) {
free(sections[idx]->content);
free(sections[idx]);
}
free(c_binary->sections);
}
}
}
-34
View File
@@ -1,34 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_PE_SECTION_CPP_C_API_
#define LIEF_PE_SECTION_CPP_C_API_
#include "LIEF/PE/Binary.h"
#include "LIEF/PE/Binary.hpp"
#include "LIEF/PE/Section.h"
#include "LIEF/PE/Section.hpp"
namespace LIEF {
namespace PE {
void init_c_sections(Pe_Binary_t* c_binary, Binary* binary);
void destroy_sections(Pe_Binary_t* c_binary);
}
}
#endif
-26
View File
@@ -1,26 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef C_LIEF_ELF_H_
#define C_LIEF_ELF_H_
#include "LIEF/ELF/Binary.h"
#include "LIEF/ELF/Symbol.h"
#include "LIEF/ELF/Section.h"
#include "LIEF/ELF/Header.h"
#include "LIEF/ELF/DynamicEntry.h"
#include "LIEF/ELF/utils.h"
#endif
-62
View File
@@ -1,62 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_C_ELF_BINARY_H
#define LIEF_C_ELF_BINARY_H
#include <stddef.h>
#include "LIEF/visibility.h"
#include "LIEF/ELF/enums.h"
#include "LIEF/ELF/Section.h"
#include "LIEF/ELF/Segment.h"
#include "LIEF/ELF/Header.h"
#include "LIEF/ELF/DynamicEntry.h"
#include "LIEF/ELF/Symbol.h"
#ifdef __cplusplus
extern "C" {
#endif
/** LIEF::ELF::Binary C Handler */
struct Elf_Binary_t {
void* handler;
const char* interpreter;
uint32_t type;
Elf_Header_t header;
Elf_Section_t **sections;
Elf_Segment_t **segments;
Elf_DynamicEntry_t **dynamic_entries;
Elf_Symbol_t **dynamic_symbols;
Elf_Symbol_t **symtab_symbols;
};
typedef struct Elf_Binary_t Elf_Binary_t;
/** Wrapper for LIEF::ELF::Parser::parse */
LIEF_API Elf_Binary_t* elf_parse(const char *file);
LIEF_API void elf_binary_destroy(Elf_Binary_t* binary);
/** Update LIEF::ELF::Header object */
LIEF_API int elf_binary_save_header(Elf_Binary_t* binary);
#ifdef __cplusplus
}
#endif
#endif
-77
View File
@@ -1,77 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_C_ELF_DYNAMIC_ENTRY_H
#define LIEF_C_ELF_DYNAMIC_ENTRY_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct Elf_DynamicEntry_t {
uint64_t tag;
uint64_t value;
};
struct Elf_DynamicEntry_Library_t {
uint64_t tag;
uint64_t value;
const char* name;
};
struct Elf_DynamicEntry_SharedObject_t {
uint64_t tag;
uint64_t value;
const char* name;
};
struct Elf_DynamicEntry_Array_t {
uint64_t tag;
uint64_t value;
uint64_t* array;
};
struct Elf_DynamicEntry_Rpath_t {
uint64_t tag;
uint64_t value;
const char* rpath;
};
struct Elf_DynamicEntry_RunPath_t {
uint64_t tag;
uint64_t value;
const char* runpath;
};
struct Elf_DynamicEntry_Flags_t {
uint64_t tag;
uint64_t value;
};
typedef struct Elf_DynamicEntry_t Elf_DynamicEntry_t;
typedef struct Elf_DynamicEntry_Library_t Elf_DynamicEntry_Library_t;
typedef struct Elf_DynamicEntry_SharedObject_t Elf_DynamicEntry_SharedObject_t;
typedef struct Elf_DynamicEntry_Array_t Elf_DynamicEntry_Array_t;
typedef struct Elf_DynamicEntry_Rpath_t Elf_DynamicEntry_Rpath_t;
typedef struct Elf_DynamicEntry_RunPath_t Elf_DynamicEntry_RunPath_t;
typedef struct Elf_DynamicEntry_Flags_t Elf_DynamicEntry_Flags_t;
#ifdef __cplusplus
}
#endif
#endif
-50
View File
@@ -1,50 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_C_ELF_HEADER_H
#define LIEF_C_ELF_HEADER_H
#include <inttypes.h>
#include "LIEF/ELF/enums.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Elf_Header_t {
uint8_t identity[LIEF_EI_NIDENT];
uint32_t file_type;
uint32_t machine_type;
uint32_t object_file_version;
uint64_t entrypoint;
uint64_t program_headers_offset;
uint64_t section_headers_offset;
uint32_t processor_flags;
uint32_t header_size;
uint32_t program_header_size;
uint32_t numberof_segments;
uint32_t section_header_size;
uint32_t numberof_sections;
uint32_t name_string_table_idx;
};
typedef struct Elf_Header_t Elf_Header_t;
#ifdef __cplusplus
}
#endif
#endif
-47
View File
@@ -1,47 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_C_ELF_SECTION_H
#define LIEF_C_ELF_SECTION_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct Elf_Section_t {
const char* name;
uint32_t flags;
uint32_t type;
uint64_t virtual_address;
uint64_t offset;
uint64_t original_size;
uint32_t link;
uint32_t info;
uint64_t alignment;
uint64_t entry_size;
uint64_t size;
uint8_t* content;
double entropy;
};
typedef struct Elf_Section_t Elf_Section_t;
#ifdef __cplusplus
}
#endif
#endif
-45
View File
@@ -1,45 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_C_ELF_SYMBOL_H
#define LIEF_C_ELF_SYMBOL_H
#include <stdint.h>
#include "LIEF/types.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Elf_Symbol_t {
const char* name;
uint32_t type;
uint32_t binding;
uint8_t information;
uint8_t other;
uint16_t shndx;
uint64_t value;
uint64_t size;
uint8_t is_exported; /**< Whether or not the symbol is exported */
uint8_t is_imported; /**< Whether or not the symbol is imported */
};
typedef struct Elf_Symbol_t Elf_Symbol_t;
#ifdef __cplusplus
}
#endif
#endif
File diff suppressed because it is too large Load Diff
-25
View File
@@ -1,25 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef C_LIEF_MACHO_H_
#define C_LIEF_MACHO_H_
#include "LIEF/MachO/Binary.h"
#include "LIEF/MachO/Symbol.h"
#include "LIEF/MachO/Segment.h"
#include "LIEF/MachO/Section.h"
#include "LIEF/MachO/LoadCommand.h"
#include "LIEF/MachO/Header.h"
#endif
-57
View File
@@ -1,57 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef C_LIEF_MACHO_BINARY_H_
#define C_LIEF_MACHO_BINARY_H_
#include <stdint.h>
#include "LIEF/visibility.h"
#include "LIEF/MachO/Header.h"
#include "LIEF/MachO/LoadCommand.h"
#include "LIEF/MachO/Symbol.h"
#include "LIEF/MachO/Section.h"
#include "LIEF/MachO/Segment.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @brief LIEF::MachO::Binary C Handler */
struct Macho_Binary_t {
void* handler;
uint64_t imagebase;
Macho_Header_t header;
Macho_Command_t** commands;
Macho_Symbol_t** symbols;
Macho_Section_t** sections;
Macho_Segment_t** segments;
};
typedef struct Macho_Binary_t Macho_Binary_t;
/** @brief Wrapper on LIEF::MachO::Parser::parse */
LIEF_API Macho_Binary_t** macho_parse(const char *file);
LIEF_API void macho_binaries_destroy(Macho_Binary_t** binaries);
#ifdef __cplusplus
}
#endif
#endif
-44
View File
@@ -1,44 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef C_LIEF_MACHO_HEADER_H_
#define C_LIEF_MACHO_HEADER_H_
#include <inttypes.h>
#include "LIEF/MachO/enums.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Macho_Header_t {
uint32_t magic;
enum LIEF_MACHO_CPU_TYPES cpu_type;
uint32_t cpu_subtype;
enum LIEF_MACHO_FILE_TYPES file_type;
uint32_t nb_cmds;
uint32_t sizeof_cmds;
uint32_t flags;
uint32_t reserved;
};
typedef struct Macho_Header_t Macho_Header_t;
#ifdef __cplusplus
}
#endif
#endif
-50
View File
@@ -1,50 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef C_LIEF_MACHO_SECTION_H_
#define C_LIEF_MACHO_SECTION_H_
#include <inttypes.h>
#include "LIEF/MachO/enums.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Macho_Section_t {
const char* name;
uint32_t alignment;
uint32_t relocation_offset;
uint32_t numberof_relocations;
uint32_t flags;
enum LIEF_MACHO_MACHO_SECTION_TYPES type;
uint32_t reserved1;
uint32_t reserved2;
uint32_t reserved3;
uint64_t virtual_address;
uint64_t offset;
uint64_t size;
uint8_t* content;
double entropy;
};
typedef struct Macho_Section_t Macho_Section_t;
#ifdef __cplusplus
}
#endif
#endif
-48
View File
@@ -1,48 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef C_LIEF_MACHO_SEGMENT_H_
#define C_LIEF_MACHO_SEGMENT_H_
#include <inttypes.h>
#include "LIEF/MachO/enums.h"
#include "LIEF/MachO/Section.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Macho_Segment_t {
const char* name;
uint64_t virtual_address;
uint64_t virtual_size;
uint64_t file_size;
uint64_t file_offset;
uint32_t max_protection;
uint32_t init_protection;
uint32_t numberof_sections;
uint32_t flags;
uint8_t* content;
uint64_t size;
Macho_Section_t** sections;
};
typedef struct Macho_Segment_t Macho_Segment_t;
#ifdef __cplusplus
}
#endif
#endif
-35
View File
@@ -1,35 +0,0 @@
#ifndef LIEF_MACHO_C_ENUMS_H_
#define LIEF_MACHO_C_ENUMS_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _LIEF_EN
#undef _LIEF_EN
#endif
#ifdef _LIEF_EN_2
#undef _LIEF_EN_2
#endif
#ifdef _LIEF_EI
#undef _LIEF_EI
#endif
#define _LIEF_EN(N) LIEF_MACHO_##N
#define _LIEF_EN_2(N, TYPE) LIEF_MACHO_##N
#define _LIEF_EI(X) LIEF_MACHO_##X
#include "LIEF/MachO/enums.inc"
#undef _LIEF_EN
#undef _LIEF_EN_2
#undef _LIEF_EI
#ifdef __cplusplus
}
#endif
#endif
-58
View File
@@ -1,58 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef C_LIEF_PE_BINARY_H_
#define C_LIEF_PE_BINARY_H_
#include <stddef.h>
#include "LIEF/visibility.h"
#include "LIEF/PE/enums.h"
#include "LIEF/PE/DosHeader.h"
#include "LIEF/PE/Header.h"
#include "LIEF/PE/OptionalHeader.h"
#include "LIEF/PE/DataDirectory.h"
#include "LIEF/PE/Section.h"
#include "LIEF/PE/Import.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @brief LIEF::PE::Binary C Handler */
struct Pe_Binary_t {
void* handler;
Pe_DosHeader_t dos_header;
Pe_Header_t header;
Pe_OptionalHeader_t optional_header;
Pe_DataDirectory_t** data_directories;
Pe_Section_t** sections;
Pe_Import_t** imports;
};
typedef struct Pe_Binary_t Pe_Binary_t;
/** Wrapper on LIEF::PE::Parser::parse */
LIEF_API Pe_Binary_t* pe_parse(const char *file);
LIEF_API void pe_binary_destroy(Pe_Binary_t* binary);
#ifdef __cplusplus
}
#endif
#endif
-61
View File
@@ -1,61 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License",;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef C_LIEF_PE_DATA_DIRECTORY_H
#define C_LIEF_PE_DATA_DIRECTORY_H
#include <inttypes.h>
#include "LIEF/PE/enums.h"
#ifdef __cplusplus
extern "C" {
#endif
enum LIEF_PE_DATA_DIRECTORY {
LIEF_PE_DATA_DIR_EXPORT_TABLE = 0,
LIEF_PE_DATA_DIR_IMPORT_TABLE,
LIEF_PE_DATA_DIR_RESOURCE_TABLE,
LIEF_PE_DATA_DIR_EXCEPTION_TABLE,
LIEF_PE_DATA_DIR_CERTIFICATE_TABLE,
LIEF_PE_DATA_DIR_BASE_RELOCATION_TABLE,
LIEF_PE_DATA_DIR_DEBUG,
LIEF_PE_DATA_DIR_ARCHITECTURE,
LIEF_PE_DATA_DIR_GLOBAL_PTR,
LIEF_PE_DATA_DIR_TLS_TABLE,
LIEF_PE_DATA_DIR_LOAD_CONFIG_TABLE,
LIEF_PE_DATA_DIR_BOUND_IMPORT,
LIEF_PE_DATA_DIR_IAT,
LIEF_PE_DATA_DIR_DELAY_IMPORT_DESCRIPTOR,
LIEF_PE_DATA_DIR_CLR_RUNTIME_HEADER,
LIEF_PE_DATA_DIR_RESERVED,
LIEF_PE_DATA_DIR_NONE,
};
struct Pe_DataDirectory_t {
uint32_t rva;
uint32_t size;
};
typedef struct Pe_DataDirectory_t Pe_DataDirectory_t;
#ifdef __cplusplus
}
#endif
#endif
-55
View File
@@ -1,55 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef C_LIEF_PE_DOS_HEADER_H_
#define C_LIEF_PE_DOS_HEADER_H_
#include <inttypes.h>
#include "LIEF/ELF/enums.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Pe_DosHeader_t {
uint16_t magic ;
uint16_t used_bytes_in_last_page;
uint16_t file_size_in_pages;
uint16_t numberof_relocation;
uint16_t header_size_in_paragraphs;
uint16_t minimum_extra_paragraphs;
uint16_t maximum_extra_paragraphs;
uint16_t initial_relative_ss;
uint16_t initial_sp;
uint16_t checksum;
uint16_t initial_ip;
uint16_t initial_relative_cs;
uint16_t addressof_relocation_table;
uint16_t overlay_number;
uint16_t reserved[4];
uint16_t oem_id;
uint16_t oem_info;
uint16_t reserved2[10];
uint32_t addressof_new_exeheader;
};
typedef struct Pe_DosHeader_t Pe_DosHeader_t;
#ifdef __cplusplus
}
#endif
#endif
-95
View File
@@ -1,95 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef C_LIEF_PE_HEADER_H
#define C_LIEF_PE_HEADER_H
#include <inttypes.h>
#include "LIEF/visibility.h"
#ifdef __cplusplus
extern "C" {
#endif
enum LIEF_PE_MACHINE_TYPES {
LIEF_PE_MACHINE_UNKNOWN = 0x0,
LIEF_PE_MACHINE_AM33 = 0x1D3, /**< Matsushita AM33 */
LIEF_PE_MACHINE_AMD64 = 0x8664, /**< AMD x64 */
LIEF_PE_MACHINE_ARM = 0x1C0, /**< ARM little endian */
LIEF_PE_MACHINE_ARMNT = 0x1C4, /**< ARMv7 Thumb mode only */
LIEF_PE_MACHINE_ARM64 = 0xAA64, /**< ARMv8 in 64-bits mode */
LIEF_PE_MACHINE_EBC = 0xEBC, /**< EFI byte code */
LIEF_PE_MACHINE_I386 = 0x14C, /**< Intel 386 or later */
LIEF_PE_MACHINE_IA64 = 0x200, /**< Intel Itanium processor family */
LIEF_PE_MACHINE_M32R = 0x9041, /**< Mitsubishi M32R little endian */
LIEF_PE_MACHINE_MIPS16 = 0x266, /**< MIPS16 */
LIEF_PE_MACHINE_MIPSFPU = 0x366, /**< MIPS with FPU */
LIEF_PE_MACHINE_MIPSFPU16 = 0x466, /**< MIPS16 with FPU */
LIEF_PE_MACHINE_POWERPC = 0x1F0, /**< Power PC little endian */
LIEF_PE_MACHINE_POWERPCFP = 0x1F1, /**< Power PC with floating point */
LIEF_PE_MACHINE_POWERPCBE = 0x1F2, /**< Power PC big endian */
LIEF_PE_MACHINE_R4000 = 0x166, /**< MIPS with little endian */
LIEF_PE_MACHINE_RISCV32 = 0x5032, /**< RISC-V 32-bit address space */
LIEF_PE_MACHINE_RISCV64 = 0x5064, /**< RISC-V 64-bit address space */
LIEF_PE_MACHINE_RISCV128 = 0x5128, /**< RISC-V 128-bit address space */
LIEF_PE_MACHINE_SH3 = 0x1A2, /**< Hitachi SH3 */
LIEF_PE_MACHINE_SH3DSP = 0x1A3, /**< Hitachi SH3 DSP */
LIEF_PE_MACHINE_SH4 = 0x1A6, /**< Hitachi SH4 */
LIEF_PE_MACHINE_SH5 = 0x1A8, /**< Hitachi SH5 */
LIEF_PE_MACHINE_THUMB = 0x1C2, /**< ARM or Thumb */
LIEF_PE_MACHINE_WCEMIPSV2 = 0x169 /**< MIPS little-endian WCE v2 */
};
enum LIEF_PE_HEADER_CHARACTERISTICS {
LIEF_PE_HEADER_CHARACTERISTICS_INVALID = 0x0000,
LIEF_PE_HEADER_CHARACTERISTICS_RELOCS_STRIPPED = 0x0001, /**< The file does not contain base relocations and must be loaded at its preferred base. If this cannot be done, the loader will error.*/
LIEF_PE_HEADER_CHARACTERISTICS_EXECUTABLE_IMAGE = 0x0002, /**< The file is valid and can be run.*/
LIEF_PE_HEADER_CHARACTERISTICS_LINE_NUMS_STRIPPED = 0x0004, /**< COFF line numbers have been stripped. This is deprecated and should be 0*/
LIEF_PE_HEADER_CHARACTERISTICS_LOCAL_SYMS_STRIPPED = 0x0008, /**< COFF symbol table entries for local symbols have been removed. This is deprecated and should be 0.*/
LIEF_PE_HEADER_CHARACTERISTICS_AGGRESSIVE_WS_TRIM = 0x0010, /**< Aggressively trim working set. This is deprecated and must be 0.*/
LIEF_PE_HEADER_CHARACTERISTICS_LARGE_ADDRESS_AWARE = 0x0020, /**< Image can handle > 2GiB addresses. */
LIEF_PE_HEADER_CHARACTERISTICS_BYTES_REVERSED_LO = 0x0080, /**< Little endian: the LSB precedes the MSB in memory. This is deprecated and should be 0.*/
LIEF_PE_HEADER_CHARACTERISTICS_32BIT_MACHINE = 0x0100, /**< Machine is based on a 32bit word architecture. */
LIEF_PE_HEADER_CHARACTERISTICS_DEBUG_STRIPPED = 0x0200, /**< Debugging info has been removed. */
LIEF_PE_HEADER_CHARACTERISTICS_REMOVABLE_RUN_FROM_SWAP = 0x0400, /**< If the image is on removable media, fully load it and copy it to swap. */
LIEF_PE_HEADER_CHARACTERISTICS_NET_RUN_FROM_SWAP = 0x0800, /**< If the image is on network media, fully load it and copy it to swap. */
LIEF_PE_HEADER_CHARACTERISTICS_SYSTEM = 0x1000, /**< The image file is a system file, not a user program.*/
LIEF_PE_HEADER_CHARACTERISTICS_DLL = 0x2000, /**< The image file is a DLL. */
LIEF_PE_HEADER_CHARACTERISTICS_UP_SYSTEM_ONLY = 0x4000, /**< This file should only be run on a uniprocessor machine. */
LIEF_PE_HEADER_CHARACTERISTICS_BYTES_REVERSED_HI = 0x8000 /**< Big endian: the MSB precedes the LSB in memory. This is deprecated */
};
struct Pe_Header_t {
uint8_t signature[4];
enum LIEF_PE_MACHINE_TYPES machine;
uint16_t numberof_sections;
uint32_t time_date_stamp;
uint32_t pointerto_symbol_table;
uint32_t numberof_symbols;
uint16_t sizeof_optional_header;
uint16_t characteristics;
};
typedef struct Pe_Header_t Pe_Header_t;
LIEF_API const char* lief_pe_header_machine_str(enum LIEF_PE_MACHINE_TYPES e);
LIEF_API const char* lief_pe_header_characteristics_str(enum LIEF_PE_HEADER_CHARACTERISTICS e);
#ifdef __cplusplus
}
#endif
#endif
-100
View File
@@ -1,100 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef C_LIEF_PE_OPTIONAL_HEADER_H
#define C_LIEF_PE_OPTIONAL_HEADER_H
#include <inttypes.h>
#include "LIEF/PE/enums.h"
#include "LIEF/visibility.h"
#ifdef __cplusplus
extern "C" {
#endif
enum LIEF_PE_DLL_CHARACTERISTICS {
LIEF_PE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020, /**< ASLR with 64 bit address space. */
LIEF_PE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040, /**< DLL can be relocated at load time. */
LIEF_PE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080, /**< Code integrity checks are enforced. */
LIEF_PE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100, /**< Image is NX compatible. */
LIEF_PE_DLL_CHARACTERISTICS_NO_ISOLATION = 0x0200, /**< Isolation aware, but do not isolate the image. */
LIEF_PE_DLL_CHARACTERISTICS_NO_SEH = 0x0400, /**< Does not use structured exception handling (SEH). No SEH handler may be called in this image. */
LIEF_PE_DLL_CHARACTERISTICS_NO_BIND = 0x0800, /**< Do not bind the image. */
LIEF_PE_DLL_CHARACTERISTICS_APPCONTAINER = 0x1000, /**< Image should execute in an AppContainer. */
LIEF_PE_DLL_CHARACTERISTICS_WDM_DRIVER = 0x2000, /**< A WDM driver. */
LIEF_PE_DLL_CHARACTERISTICS_GUARD_CF = 0x4000, /**< Image supports Control Flow Guard. */
LIEF_PE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000 /**< Terminal Server aware. */
};
enum LIEF_PE_SUBSYSTEM {
LIEF_PE_SUBSYSTEM_UNKNOWN = 0, /**< An unknown subsystem. */
LIEF_PE_SUBSYSTEM_NATIVE = 1, /**< Device drivers and native Windows processes */
LIEF_PE_SUBSYSTEM_WINDOWS_GUI = 2, /**< The Windows GUI subsystem. */
LIEF_PE_SUBSYSTEM_WINDOWS_CUI = 3, /**< The Windows character subsystem. */
LIEF_PE_SUBSYSTEM_OS2_CUI = 5, /**< The OS/2 character subsytem. */
LIEF_PE_SUBSYSTEM_POSIX_CUI = 7, /**< The POSIX character subsystem. */
LIEF_PE_SUBSYSTEM_NATIVE_WINDOWS = 8, /**< Native Windows 9x driver. */
LIEF_PE_SUBSYSTEM_WINDOWS_CE_GUI = 9, /**< Windows CE. */
LIEF_PE_SUBSYSTEM_EFI_APPLICATION = 10, /**< An EFI application. */
LIEF_PE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11, /**< An EFI driver with boot services. */
LIEF_PE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12, /**< An EFI driver with run-time services. */
LIEF_PE_SUBSYSTEM_EFI_ROM = 13, /**< An EFI ROM image. */
LIEF_PE_SUBSYSTEM_XBOX = 14, /**< XBOX. */
LIEF_PE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16, /**< A BCD application. */
LIEF_PE_SUBSYSTEM_XBOX_CODE_CATALOG = 17,
};
struct Pe_OptionalHeader_t {
uint16_t magic;
uint8_t major_linker_version;
uint8_t minor_linker_version;
uint32_t sizeof_code;
uint32_t sizeof_initialized_data;
uint32_t sizeof_uninitialized_data;
uint32_t addressof_entrypoint;
uint32_t baseof_code;
uint32_t baseof_data;
uint64_t imagebase;
uint32_t section_alignment;
uint32_t file_alignment;
uint16_t major_operating_system_version;
uint16_t minor_operating_system_version;
uint16_t major_image_version;
uint16_t minor_image_version;
uint16_t major_subsystem_version;
uint16_t minor_subsystem_version;
uint32_t win32_version_value;
uint32_t sizeof_image;
uint32_t sizeof_headers;
uint32_t checksum;
enum LIEF_PE_SUBSYSTEM subsystem;
uint32_t dll_characteristics;
uint64_t sizeof_stack_reserve;
uint64_t sizeof_stack_commit;
uint64_t sizeof_heap_reserve;
uint64_t sizeof_heap_commit;
uint32_t loader_flags;
uint32_t numberof_rva_and_size;
};
typedef struct Pe_OptionalHeader_t Pe_OptionalHeader_t;
LIEF_API const char* lief_pe_subsytem_str(enum LIEF_PE_SUBSYSTEM e);
#ifdef __cplusplus
}
#endif
#endif
-89
View File
@@ -1,89 +0,0 @@
/* Copyright 2017 - 2026 R. Thomas
* Copyright 2017 - 2026 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef C_LIEF_PE_SECTION_H_
#define C_LIEF_PE_SECTION_H_
#include <inttypes.h>
#include "LIEF/PE/enums.h"
#ifdef __cplusplus
extern "C" {
#endif
enum LIEF_PE_SECTION_CHARACTERISTICS {
LIEF_PE_SECTION_CHARACTERISTICS_TYPE_NO_PAD = 0x00000008,
LIEF_PE_SECTION_CHARACTERISTICS_CNT_CODE = 0x00000020,
LIEF_PE_SECTION_CHARACTERISTICS_CNT_INITIALIZED_DATA = 0x00000040,
LIEF_PE_SECTION_CHARACTERISTICS_CNT_UNINITIALIZED_DATA = 0x00000080,
LIEF_PE_SECTION_CHARACTERISTICS_LNK_OTHER = 0x00000100,
LIEF_PE_SECTION_CHARACTERISTICS_LNK_INFO = 0x00000200,
LIEF_PE_SECTION_CHARACTERISTICS_LNK_REMOVE = 0x00000800,
LIEF_PE_SECTION_CHARACTERISTICS_LNK_COMDAT = 0x00001000,
LIEF_PE_SECTION_CHARACTERISTICS_GPREL = 0x00008000,
LIEF_PE_SECTION_CHARACTERISTICS_MEM_PURGEABLE = 0x00010000,
LIEF_PE_SECTION_CHARACTERISTICS_MEM_16BIT = 0x00020000,
LIEF_PE_SECTION_CHARACTERISTICS_MEM_LOCKED = 0x00040000,
LIEF_PE_SECTION_CHARACTERISTICS_MEM_PRELOAD = 0x00080000,
LIEF_PE_SECTION_CHARACTERISTICS_ALIGN_1BYTES = 0x00100000,
LIEF_PE_SECTION_CHARACTERISTICS_ALIGN_2BYTES = 0x00200000,
LIEF_PE_SECTION_CHARACTERISTICS_ALIGN_4BYTES = 0x00300000,
LIEF_PE_SECTION_CHARACTERISTICS_ALIGN_8BYTES = 0x00400000,
LIEF_PE_SECTION_CHARACTERISTICS_ALIGN_16BYTES = 0x00500000,
LIEF_PE_SECTION_CHARACTERISTICS_ALIGN_32BYTES = 0x00600000,
LIEF_PE_SECTION_CHARACTERISTICS_ALIGN_64BYTES = 0x00700000,
LIEF_PE_SECTION_CHARACTERISTICS_ALIGN_128BYTES = 0x00800000,
LIEF_PE_SECTION_CHARACTERISTICS_ALIGN_256BYTES = 0x00900000,
LIEF_PE_SECTION_CHARACTERISTICS_ALIGN_512BYTES = 0x00A00000,
LIEF_PE_SECTION_CHARACTERISTICS_ALIGN_1024BYTES = 0x00B00000,
LIEF_PE_SECTION_CHARACTERISTICS_ALIGN_2048BYTES = 0x00C00000,
LIEF_PE_SECTION_CHARACTERISTICS_ALIGN_4096BYTES = 0x00D00000,
LIEF_PE_SECTION_CHARACTERISTICS_ALIGN_8192BYTES = 0x00E00000,
LIEF_PE_SECTION_CHARACTERISTICS_LNK_NRELOC_OVFL = 0x01000000,
LIEF_PE_SECTION_CHARACTERISTICS_MEM_DISCARDABLE = 0x02000000,
LIEF_PE_SECTION_CHARACTERISTICS_MEM_NOT_CACHED = 0x04000000,
LIEF_PE_SECTION_CHARACTERISTICS_MEM_NOT_PAGED = 0x08000000,
LIEF_PE_SECTION_CHARACTERISTICS_MEM_SHARED = 0x10000000,
LIEF_PE_SECTION_CHARACTERISTICS_MEM_EXECUTE = 0x20000000,
LIEF_PE_SECTION_CHARACTERISTICS_MEM_READ = 0x40000000,
LIEF_PE_SECTION_CHARACTERISTICS_MEM_WRITE = 0x80000000
};
struct Pe_Section_t {
const char* name;
uint64_t virtual_address;
uint64_t size;
uint64_t offset;
uint32_t virtual_size;
uint32_t pointerto_relocation;
uint32_t pointerto_line_numbers;
uint32_t characteristics;
uint8_t* content;
uint64_t content_size;
double entropy;
};
typedef struct Pe_Section_t Pe_Section_t;
#ifdef __cplusplus
}
#endif
#endif
-24
View File
@@ -1,24 +0,0 @@
#ifndef LIEF_PE_C_ENUMS_H_
#define LIEF_PE_C_ENUMS_H_
#ifdef __cplusplus
extern "C" {
#endif
#define _LIEF_EN(N) LIEF_PE_##N
#define _LIEF_EN_2(N, TYPE) LIEF_PE_##N
#define _LIEF_EI(X) LIEF_PE_##X
#include "LIEF/PE/enums.inc"
#undef _LIEF_EN
#undef _LIEF_EN_2
#undef _LIEF_EI
#ifdef __cplusplus
}
#endif
#endif
+43 -12
View File
@@ -1,5 +1,4 @@
if (LIEF_PY_LIEF_EXT)
if (LIEF_PRECOMPILED)
if (LIEF_PY_LIEF_EXT_SHARED)
find_package(LIEF REQUIRED COMPONENTS SHARED)
else()
@@ -14,17 +13,12 @@ endif()
include(FetchContent)
# Avoid warning about DOWNLOAD_EXTRACT_TIMESTAMP in CMake 3.24:
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
cmake_policy(SET CMP0135 NEW)
endif()
if (LIEF_EXTERNAL_NANOBIND)
find_package(Python REQUIRED COMPONENTS Interpreter Development.Module)
find_package(nanobind REQUIRED)
else()
set(NANOBIND_VERSION 2.11.0.r10.g5f0a380)
set(NANOBIND_SHA256 SHA256=4494b2b580b400e98e4d847b6a9e2a3aeb99581ac7545f6efaa52605335fa806)
set(NANOBIND_VERSION 3.0.1)
set(NANOBIND_SHA256 SHA256=20111f42e0608e4e518bbe6095bdf64ef74d1d21bad22cb6f2aa3aff013e4443)
set(NANOBIND_URL "${THIRD_PARTY_DIRECTORY}/nanobind-${NANOBIND_VERSION}.zip"
CACHE STRING "URL to the Nanobind")
FetchContent_Declare(nanobind
@@ -48,14 +42,26 @@ set(NANOBIND_OPT
NOMINSIZE
)
if (LIEF_PYTHON_STABLE_ABI)
message(STATUS "Stable ABI enabled")
list(APPEND NANOBIND_OPT STABLE_ABI)
endif()
if (LIEF_PYTHON_FREE_THREADED)
message(STATUS "Free threading enabled")
list(APPEND NANOBIND_OPT FREE_THREADED)
endif()
if (LIEF_PYTHON_STATIC)
list(APPEND NANOBIND_OPT NB_EXT_STATIC)
list(APPEND NANOBIND_OPT NB_EXT_STATIC ON)
endif()
nanobind_add_module(
pyLIEF
${NANOBIND_OPT}
NB_SUPPRESS_WARNINGS
src/pyLIEF.cpp
)
@@ -71,12 +77,21 @@ set_target_properties(pyLIEF PROPERTIES
OUTPUT_NAME "_lief"
)
if (LIEF_EXTRA_FLAGS)
target_compile_options(pyLIEF PRIVATE ${LIEF_EXTRA_FLAGS})
endif()
if (MSVC AND NOT CLANG_CL AND NOT LIEF_EXTERNAL_SPDLOG)
target_compile_definitions(pyLIEF PRIVATE FMT_UNICODE=0)
endif()
target_link_libraries(pyLIEF PUBLIC ${LIEF_TARGET} lief_spdlog)
target_precompile_headers(pyLIEF PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/pylief-pch.hpp
)
if(APPLE)
set_target_properties(pyLIEF PROPERTIES
MACOSX_RPATH ON
@@ -102,7 +117,11 @@ endif()
if (WIN32)
target_link_libraries(pyLIEF PUBLIC ${PYTHON_LIBRARIES})
target_link_libraries(pyLIEF PUBLIC ${PYTHON_LIBRARIES} bcrypt)
endif()
if (ANDROID)
target_link_libraries(pyLIEF PUBLIC Python::Module)
endif()
if(SKBUILD)
@@ -113,8 +132,20 @@ if(SKBUILD)
endif()
endif()
if (LIEF_ASAN)
target_link_libraries(pyLIEF INTERFACE libclang_rt.asan.so)
endif()
if (LIEF_TSAN)
target_link_libraries(pyLIEF INTERFACE libclang_rt.tsan.so)
endif()
if (LIEF_PYTHON_STATIC)
install(TARGETS nanobind-static pyLIEF
set(NANOBIND_TARGET nanobind-static)
if (LIEF_PYTHON_STABLE_ABI)
set(NANOBIND_TARGET nanobind-static-abi3)
endif()
install(TARGETS ${NANOBIND_TARGET} pyLIEF
DESTINATION lib/python-${Python_VERSION})
install(
+60
View File
@@ -0,0 +1,60 @@
# About
The purpose of this project is to provide a cross-platform library that can parse, modify and
abstract ELF, PE and MachO formats.
Main features:
> - **Parsing**: LIEF can parse ELF, PE, MachO, OAT, DEX, VDEX, ART and provides a user-friendly API to access format internals.
> - **Modify**: LIEF enables to modify some parts of these formats
> - **Abstract**: Three formats have common features like sections, symbols, entry point... LIEF factors them.
> - **API**: LIEF can be used in C++, Python and Rust
LIEF Extended:
> - DWARF/PDB Support
> - Objective-C Metadata
> - dyld shared cache
Checkout: <https://lief.re/doc/latest/extended/intro.html> for the details
# Getting Started
```console
$ pip install lief
```
```python
import lief
elf = lief.ELF.parse("/bin/ls")
for section in elf.sections:
print(section.name, len(section.content))
pe = lief.PE.parse("cmd.exe")
for imp in pe.imports:
print(imp.name)
fat = lief.MachO.parse("/bin/dyld")
for macho in fat:
for sym in macho.symbols:
print(sym)
```
# Documentation
- [Main documentation](https://lief.re/doc/latest/index.html)
- [API](https://lief.re/doc/latest/api/python/index.html)
# Contact
- **Mail**: contact at lief.re
- **Discord**: [LIEF](https://discord.gg/jGQtyAYChJ)
# Authors
Romain Thomas [@rh0main](https://x.com/rh0main)
______________________________________________________________________
LIEF is provided under the [Apache 2.0 license](https://github.com/lief-project/LIEF/blob/0.15.1/LICENSE)
-65
View File
@@ -1,65 +0,0 @@
About
=====
The purpose of this project is to provide a cross platform library that can parse, modify and
abstract ELF, PE and MachO formats.
Main features:
* **Parsing**: LIEF can parse ELF, PE, MachO, OAT, DEX, VDEX, ART and provides an user-friendly API to access to format internals.
* **Modify**: LIEF enables to modify some parts of these formats
* **Abstract**: Three formats have common features like sections, symbols, entry point... LIEF factors them.
* **API**: LIEF can be used in C, C++, Python and Rust
LIEF Extended:
* DWARF/PDB Support
* Objective-C Metadata
* dyld shared cache
Checkout: https://lief.re/doc/latest/extended/intro.html for the details
Getting Started
================
.. code-block:: console
$ pip install lief
.. code-block:: python
import lief
elf = lief.ELF.parse("/bin/ls")
for section in elf.sections:
print(section.name, len(section.content))
pe = lief.PE.parse("cmd.exe")
for imp in pe.imports:
print(imp.name)
fat = lief.MachO.parse("/bin/dyld")
for macho in fat:
for sym in macho.symbols:
print(sym)
Documentation
=============
* `Main documentation <https://lief.re/doc/latest/index.html>`_
* `API <https://lief.re/doc/latest/api/python/index.html>`_
Contact
=======
* **Mail**: contact at lief.re
* **Discord**: `LIEF <https://discord.gg/jGQtyAYChJ>`_
Authors
=======
Romain Thomas `@rh0main <https://x.com/rh0main>`_
----
LIEF is provided under the `Apache 2.0 license <https://github.com/lief-project/LIEF/blob/0.15.1/LICENSE>`_
View File
+132 -77
View File
@@ -1,32 +1,39 @@
from __future__ import annotations
from pydantic_core import ErrorDetails, core_schema, CoreSchema
from pydantic import BaseModel, ValidationError, Field, GetCoreSchemaHandler
from typing import Any, Optional, Union, List
from pathlib import Path
import tomli
import os
import platform
import sysconfig
from pathlib import Path
from typing import Annotated, Any, Literal
from typing_extensions import Annotated
import tomli
from pydantic import BaseModel, Field, GetCoreSchemaHandler, ValidationError
from pydantic_core import CoreSchema, ErrorDetails, core_schema
from scikit_build_core._logging import rich_print
from scikit_build_core.settings.skbuild_read_settings import rich_print
def cmake_serialize(field: Any):
if isinstance(field, bool):
return "ON" if field else "OFF"
return field
class EnvStringValidator:
def _get_env_string(self, string: str) -> str:
winpy_architecture = os.getenv("LIEF_TARGET_ARCHITECTURE", "")
if winpy_architecture == "x86_64":
winpy_architecture = "amd64"
formatted = string.format(
python_version=os.getenv("LIEF_TARGET_PYTHON_VERSION", ""),
python_version_alt=os.getenv("LIEF_TARGET_PYTHON_VERSION", "").replace('.', ''),
architecture=os.getenv("LIEF_TARGET_ARCHITECTURE", ""),
winpy_architecture=winpy_architecture,
ci_project_dir=os.getenv("CI_PROJECT_DIR", ""),
python_version=os.getenv("LIEF_TARGET_PYTHON_VERSION", ""),
python_version_alt=os.getenv("LIEF_TARGET_PYTHON_VERSION", "").replace(
".", ""
),
architecture=os.getenv("LIEF_TARGET_ARCHITECTURE", ""),
winpy_architecture=winpy_architecture,
ci_project_dir=os.getenv("CI_PROJECT_DIR", ""),
stable_abi=os.getenv("LIEF_STABLE_ABI", ""),
free_threaded=os.getenv("LIEF_FREE_THREADED", ""),
runtime=os.getenv("LIEF_RUNTIME", "false"),
)
return formatted
@@ -37,26 +44,33 @@ class EnvStringValidator:
self._get_env_string, handler(source_type)
)
EnvString = Annotated[str, EnvStringValidator()]
class BuildConfig(BaseModel):
build_type: EnvString = Field("Release", alias="type")
cache: bool = True
ninja: bool = False
stable_abi: bool | EnvString = Field(False, alias="stable-abi")
free_threaded: bool | EnvString | None = Field(None, alias="free-threaded")
default_target: str = Field("pyLIEF", alias="default-target")
parallel_jobs: int = Field(0, alias="parallel-jobs")
compilation_flags: List[str] = Field([], alias="compilation-flags")
build_dir: Optional[EnvString] = Field(None, alias="build-dir")
extra_targets: Union[List[EnvString], EnvString] = Field(None, alias="extra-targets")
extra_cmake: Union[List[EnvString], EnvString] = Field(None, alias="extra-cmake-opt")
lief_install_dir: Optional[EnvString] = Field(None, alias="lief-install-dir")
compilation_flags: list[str] = Field([], alias="compilation-flags")
lief_extra_compilation_flags: list[str] = Field(
[], alias="lief-extra-compilation-flags"
)
build_dir: EnvString | None = Field(None, alias="build-dir")
extra_targets: list[EnvString] | EnvString = Field([], alias="extra-targets")
extra_cmake: list[EnvString] | EnvString = Field([], alias="extra-cmake-opt")
lief_install_dir: EnvString | None = Field(None, alias="lief-install-dir")
py_api: EnvString = Field("", alias="py-api")
c_compiler: Optional[EnvString] = Field(None, alias="c-compiler")
cxx_compiler: Optional[EnvString] = Field(None, alias="cxx-compiler")
c_compiler: EnvString | None = Field(None, alias="c-compiler")
cxx_compiler: EnvString | None = Field(None, alias="cxx-compiler")
@property
def targets(self) -> List[str]:
default_targets: List[str] = [self.default_target]
def targets(self) -> list[str]:
default_targets: list[str] = [self.default_target]
if self.extra_targets is not None:
if isinstance(self.extra_targets, str):
default_targets.append(self.extra_targets)
@@ -65,10 +79,8 @@ class BuildConfig(BaseModel):
return default_targets
def cmake_dump(self) -> List[str]:
out: List[str] = [
f"-DLIEF_USE_CCACHE={cmake_serialize(self.cache)}"
]
def cmake_dump(self) -> list[str]:
out: list[str] = [f"-DLIEF_USE_CCACHE={cmake_serialize(self.cache)}"]
if self.extra_cmake is not None:
if isinstance(self.extra_cmake, str):
@@ -78,66 +90,82 @@ class BuildConfig(BaseModel):
if self.lief_install_dir is not None:
lief_cmake_dir = Path(self.lief_install_dir) / "lib" / "cmake" / "LIEF"
lief_dir = lief_cmake_dir.expanduser().resolve().absolute()
out.extend((
"-DLIEF_PY_LIEF_EXT=on",
"-DLIEF_INSTALL=off",
f"-DLIEF_DIR={lief_dir.as_posix()}"
))
lief_dir = lief_cmake_dir.expanduser().resolve()
if not lief_dir.is_dir():
raise RuntimeError(f"Invalid install dir: {lief_cmake_dir}")
out.extend(
(
"-DLIEF_PY_LIEF_EXT=on",
"-DLIEF_INSTALL=off",
f"-DLIEF_DIR={lief_dir.as_posix()}",
)
)
if self.c_compiler is not None:
out.append(
f"-DCMAKE_C_COMPILER={self.c_compiler}"
)
out.append(f"-DCMAKE_C_COMPILER={self.c_compiler}")
if self.cxx_compiler is not None:
out.append(
f"-DCMAKE_CXX_COMPILER={self.cxx_compiler}"
)
out.append(f"-DCMAKE_CXX_COMPILER={self.cxx_compiler}")
if len(self.compilation_flags) > 0:
flags = " ".join(self.compilation_flags)
out.extend((
f'-DCMAKE_CXX_FLAGS={flags}',
f'-DCMAKE_C_FLAGS={flags}',
))
out.extend(
(
f"-DCMAKE_CXX_FLAGS={flags}",
f"-DCMAKE_C_FLAGS={flags}",
)
)
if len(self.lief_extra_compilation_flags) > 0:
flags = ";".join(self.lief_extra_compilation_flags)
out.extend((f"-DLIEF_EXTRA_FLAGS={flags}",))
free_threaded = self.free_threaded
if free_threaded is None:
free_threaded = bool(sysconfig.get_config_var("Py_GIL_DISABLED"))
out.extend(
[
f"-DLIEF_PYTHON_STABLE_ABI={cmake_serialize(self.stable_abi)}",
f"-DLIEF_PYTHON_FREE_THREADED={cmake_serialize(free_threaded)}",
]
)
return out
class ThirdParty(BaseModel):
spdlog: Optional[EnvString] = None
nanobind: Optional[EnvString] = None
spdlog: EnvString | None = None
nanobind: EnvString | None = None
def cmake_dump(self) -> List[str]:
out: List[str] = []
def cmake_dump(self) -> list[str]:
out: list[str] = []
if self.spdlog is not None:
out.extend((
"-DLIEF_EXTERNAL_SPDLOG=ON",
f"-Dspdlog_DIR={self.spdlog}"
))
out.extend(("-DLIEF_EXTERNAL_SPDLOG=ON", f"-Dspdlog_DIR={self.spdlog}"))
if self.nanobind is not None:
out.extend((
"-DLIEF_OPT_NANOBIND_EXTERNAL=ON",
f"-Dnanobind_DIR={self.nanobind}"
))
out.extend(
("-DLIEF_OPT_NANOBIND_EXTERNAL=ON", f"-Dnanobind_DIR={self.nanobind}")
)
return out
class CrossCompilation(BaseModel):
osx_arch: Optional[EnvString] = Field(None, alias="osx-arch")
platform: Optional[EnvString] = None
pyversion: Optional[EnvString] = None
abi: Optional[EnvString] = None
osx_arch: EnvString | None = Field(None, alias="osx-arch")
platform: EnvString | None = None
pyversion: EnvString | None = None
abi: EnvString | None = None
def cmake_dump(self) -> List[str]:
out: List[str] = []
def cmake_dump(self) -> list[str]:
out: list[str] = []
if self.osx_arch is not None:
out.extend((
f'-DCMAKE_OSX_ARCHITECTURES={self.osx_arch}',
))
out.extend((f"-DCMAKE_OSX_ARCHITECTURES={self.osx_arch}",))
return out
class Formats(BaseModel):
elf: bool = True
pe: bool = True
@@ -148,7 +176,7 @@ class Formats(BaseModel):
oat: bool = True
vdex: bool = True
def cmake_dump(self) -> List[str]:
def cmake_dump(self) -> list[str]:
return [
f"-DLIEF_ELF={cmake_serialize(self.elf)}",
f"-DLIEF_PE={cmake_serialize(self.pe)}",
@@ -160,44 +188,67 @@ class Formats(BaseModel):
f"-DLIEF_VDEX={cmake_serialize(self.vdex)}",
]
class Logging(BaseModel):
enabled: bool = True
debug: bool = False
def cmake_dump(self) -> List[str]:
def cmake_dump(self) -> list[str]:
return [
f"-DLIEF_LOGGING={cmake_serialize(self.enabled)}",
f"-DLIEF_LOGGING_DEBUG={cmake_serialize(self.debug)}",
]
class Features(BaseModel):
# json is an attribute already defined in BaseModel
json_support: bool = Field(True, alias="json")
frozen: bool = True
runtime: bool | EnvString = Field(False)
def cmake_dump(self) -> List[str]:
def cmake_dump(self) -> list[str]:
return [
f"-DLIEF_RUNTIME={cmake_serialize(self.runtime)}",
f"-DLIEF_ENABLE_JSON={cmake_serialize(self.json_support)}",
f"-DLIEF_DISABLE_FROZEN={cmake_serialize(not self.frozen)}",
]
class Runtime(BaseModel):
platform: Literal["linux", "windows", "android", "osx", "ios"] | None = None
architecture: EnvString | Literal["arm64", "x86_64"] | None = None
def cmake_dump(self) -> list[str]:
out: list[str] = []
if self.platform is not None:
out.append(f"-DLIEF_RUNTIME_PLATFORM={self.platform}")
if self.architecture is not None:
out.append(f"-DLIEF_RUNTIME_ARCH={self.architecture}")
return out
class ConfigT(BaseModel):
build: BuildConfig = BuildConfig()
formats: Formats = Formats()
third_party: ThirdParty = Field(ThirdParty(), alias="third-party")
features: Features = Features()
logging: Logging = Logging()
cross_compilation: CrossCompilation = Field(CrossCompilation(),
alias="cross-compilation")
runtime: Runtime = Runtime()
cross_compilation: CrossCompilation = Field(
CrossCompilation(), alias="cross-compilation"
)
def _cmake_base_args(self) -> List[str]:
def _cmake_base_args(self) -> list[str]:
return [
"-DLIEF_PYTHON_API=on",
"-DLIEF_INSTALL=off",
"-DLIEF_INSTALL_COMPILED_EXAMPLES=off",
]
def cmake_dump(self) -> List[str]:
def cmake_dump(self) -> list[str]:
return [
*self._cmake_base_args(),
*self.build.cmake_dump(),
@@ -205,20 +256,22 @@ class ConfigT(BaseModel):
*self.third_party.cmake_dump(),
*self.features.cmake_dump(),
*self.logging.cmake_dump(),
*self.runtime.cmake_dump(),
*self.cross_compilation.cmake_dump(),
]
def pretty_error(err: ErrorDetails, file: Path):
loc = '.'.join(err['loc'])
if err['type'] == 'value_error.missing':
loc = ".".join([str(e) for e in err["loc"]])
if err["type"] == "value_error.missing":
rich_print(f"[red]'{loc}' is missing in {file}")
else:
rich_print(f"[red]Error with '{loc}' in {file} ({err['msg']})")
class Config:
DEFAULT_EXCLUDE: List[str] = [
"*.so", "*.pyd"
]
DEFAULT_EXCLUDE: list[str] = ["*.so", "*.pyd"]
def __init__(self, config: ConfigT):
self._config: ConfigT = config
@@ -248,7 +301,7 @@ class Config:
return ""
def get_cmake_args(self, editable: bool = False) -> List[str]:
def get_cmake_args(self, editable: bool = False) -> list[str]:
cmake_args = self._config.cmake_dump()
if editable:
cmake_args.append(
@@ -257,9 +310,11 @@ class Config:
return cmake_args
@property
def cmake_generator(self) -> List[str]:
def cmake_generator(self) -> list[str]:
if self._config.build.ninja:
return ["-GNinja",]
return [
"-GNinja",
]
return []
@property
+15 -8
View File
@@ -1,13 +1,20 @@
from __future__ import annotations
from collections.abc import Mapping
from typing import Any
from scikit_build_core._logging import rich_print
from setup import BINDING_DIR
from versioning import Versioning
from scikit_build_core.settings.skbuild_read_settings import rich_print
def dynamic_metadata(field, config) -> str:
if field == "version":
version = Versioning().get_version()
rich_print(f"[green]LIEF Version: {version}")
return version
if field == "readme":
return (BINDING_DIR / "README.rst").as_posix()
def dynamic_metadata(
_settings: Mapping[str, Any],
_project: Mapping[str, Any],
) -> dict[str, Any]:
version = Versioning().get_version()
rich_print("{green}LIEF Version: {version}", version=version)
return {
"version": version,
"readme": (BINDING_DIR / "README.md").as_posix(),
}
+72 -47
View File
@@ -1,11 +1,11 @@
from __future__ import annotations
from pathlib import Path
import os
import platform
import sys
import sysconfig
import platform
from functools import lru_cache
from typing import Optional, Union, List
from pathlib import Path
CWD = Path(__file__).parent
ROOT_DIR = CWD / ".." / ".." / ".."
@@ -16,17 +16,21 @@ DEFAULT_CONF = CWD / ".." / "config-default.toml"
_WHEEL_TAG_COMPUTE_BEST = None
@lru_cache(maxsize=1)
def get_config():
from config import Config
if path := os.getenv("PYLIEF_CONF"):
config_path = Path(path).resolve().absolute()
return Config.from_file(config_path)
return Config.from_file(DEFAULT_CONF.as_posix())
return Config.from_file(DEFAULT_CONF)
def _compute_best(cls, *arg, **kwargs):
from scikit_build_core.builder.wheel_tag import WheelTag
assert _WHEEL_TAG_COMPUTE_BEST is not None
best_tag = _WHEEL_TAG_COMPUTE_BEST(cls, *arg, **kwargs)
config = get_config()
@@ -45,52 +49,54 @@ def _compute_best(cls, *arg, **kwargs):
return WheelTag(pyvers, abis, archs)
def _get_vc_env(vc_arch: str) -> dict[str, str]:
try:
from setuptools import distutils # type: ignore[import,attr-defined]
from setuptools import distutils # type: ignore
return distutils._msvccompiler._get_vc_env(vc_arch) # type: ignore[no-any-return]
return distutils._msvccompiler._get_vc_env(vc_arch) # type: ignore
except AttributeError:
from setuptools._distutils import (
_msvccompiler, # type: ignore[import,attr-defined]
)
from setuptools._distutils import _msvccompiler # type: ignore
return _msvccompiler._get_vc_env(vc_arch) # type: ignore
return _msvccompiler._get_vc_env(vc_arch) # type: ignore[no-any-return,attr-defined]
def _fix_env():
config = get_config()
if sys.platform.startswith("win"):
if config.build.ninja:
from setuptools import msvc
is64 = sys.maxsize > 2**32
arch = 'x64' if is64 else 'x86'
arch = "x64" if is64 else "x86"
ninja_env = _get_vc_env(arch)
os.environ.update(ninja_env)
if sys.platform.startswith("darwin"):
deployment_target = (
os.getenv("MACOSX_DEPLOYMENT_TARGET", None) or
sysconfig.get_config_var("MACOSX_DEPLOYMENT_TARGET")
deployment_target = os.getenv(
"MACOSX_DEPLOYMENT_TARGET", None
) or sysconfig.get_config_var("MACOSX_DEPLOYMENT_TARGET")
os.environ["_PYTHON_HOST_PLATFORM"] = (
f"macosx-{deployment_target}-{config.osx_arch}"
)
os.environ["_PYTHON_HOST_PLATFORM"] = f"macosx-{deployment_target}-{config.osx_arch}"
# scikit_build_core is aware of ARCHFLAGS for the wheel arch:
# builder/builder.py:get_archs()
os.environ["ARCHFLAGS"]= f"-arch {config.osx_arch}"
os.environ["ARCHFLAGS"] = f"-arch {config.osx_arch}"
if platform := config.cross_compilation.platform:
global _WHEEL_TAG_COMPUTE_BEST
from scikit_build_core.builder.wheel_tag import WheelTag
_WHEEL_TAG_COMPUTE_BEST = WheelTag.compute_best
WheelTag.compute_best = _compute_best
WheelTag.compute_best = _compute_best # type: ignore
os.environ["_PYTHON_HOST_PLATFORM"] = platform
if os.name == 'nt' and platform == 'win32':
if os.name == "nt" and platform == "win32":
os.environ["VSCMD_ARG_TGT_ARCH"] = "x86"
sys.version = sys.version.lower().replace("amd64", "")
sys.platform = "win32"
def _get_hooked_config(is_editable: bool) -> Optional[dict[str, Union[str, List[str]]]]:
def _get_hooked_config(is_editable: bool) -> dict[str, str | list[str]] | None:
from config import Config
config = get_config()
@@ -103,21 +109,17 @@ def _get_hooked_config(is_editable: bool) -> Optional[dict[str, Union[str, List[
# Make sure that this check is not silently warned since it could lead
# to a wrong .whl filename
minor = int(config.build.py_api[3:])
if (
sys.implementation.name != "cpython" or
minor > sys.version_info.minor
):
if sys.implementation.name != "cpython" or minor > sys.version_info.minor:
msg = f"Ignoring py-api, not a CPython interpreter ({sys.implementation.name}) or version (3.{minor}) is too high"
raise RuntimeError(msg)
config_settings = {
"logging.level": "DEBUG",
"build-dir": config.build_dir,
"build.targets": config.build.targets,
"install.strip": config.strip,
"backport.find-python": "0",
"wheel.py-api": config.build.py_api,
"wheel.py-api": config.build.py_api,
"cmake.source-dir": SRC_DIR.as_posix(),
"cmake.build-type": config.build.build_type,
"cmake.args": [
@@ -128,28 +130,46 @@ def _get_hooked_config(is_editable: bool) -> Optional[dict[str, Union[str, List[
}
return config_settings
def _get_build_requirements(is_editable: bool) -> List[str]:
def _get_build_requirements(is_editable: bool) -> list[str]:
build_req_file = BINDING_DIR / "build-requirements.txt"
if not build_req_file.is_file() and not (BINDING_DIR / "src").is_dir():
# By convention this is an mocked sdist
print(f"LIEF does not provide precompiled wheels for '{sys.platform} - {platform.machine()}'", file=sys.stderr)
# By convention this is a mocked sdist
impl = sys.implementation.name
version = "{0.major}.{0.minor}.{0.micro}".format(sys.version_info)
free_threaded = bool(sysconfig.get_config_var("Py_GIL_DISABLED"))
ft_status = "free-threaded" if free_threaded else "GIL-enabled"
print(
f"LIEF does not provide precompiled wheels for "
f"'{sys.platform} - {platform.machine()}' "
f"(Python: {impl} {version} [{ft_status}])",
file=sys.stderr,
)
sys.exit(1)
reqs = [line for line in build_req_file.read_text().splitlines() if not line.startswith("#")]
reqs = [
line
for line in build_req_file.read_text().splitlines()
if not line.startswith("#")
]
return reqs
def get_requires_for_build_wheel(
config_settings: Optional[dict[str, Union[str, List[str]]]] = None,
config_settings: dict[str, str | list[str]] | None = None,
) -> list[str]:
return _get_build_requirements(is_editable=False)
def prepare_metadata_for_build_wheel(
metadata_directory: str,
config_settings: Optional[dict[str, Union[str, List[str]]]] = None,
config_settings: dict[str, str | list[str]] | None = None,
) -> str:
from scikit_build_core.build import prepare_metadata_for_build_wheel as _impl
_fix_env()
return _impl(metadata_directory, config_settings)
def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
from scikit_build_core.build import build_wheel as _impl
@@ -157,23 +177,27 @@ def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
_fix_env()
return _impl(wheel_directory, config_settings, metadata_directory)
def get_requires_for_build_editable(
config_settings: Optional[dict[str, Union[str, List[str]]]] = None,
) -> List[str]:
config_settings: dict[str, str | list[str]] | None = None,
) -> list[str]:
return _get_build_requirements(is_editable=True)
def prepare_metadata_for_build_editable(
metadata_directory: str,
config_settings: Optional[dict[str, Union[str, List[str]]]] = None,
config_settings: dict[str, str | list[str]] | None = None,
) -> str:
from scikit_build_core.build import prepare_metadata_for_build_editable as _impl
_fix_env()
return _impl(metadata_directory, config_settings)
def build_editable(
wheel_directory: str,
config_settings: Optional[dict[str, Union[str, List[str]]]] = None,
metadata_directory: Optional[str] = None,
config_settings: dict[str, str | list[str]] | None = None,
metadata_directory: str | None = None,
) -> str:
from scikit_build_core.build import build_editable as _impl
@@ -181,20 +205,21 @@ def build_editable(
_fix_env()
return _impl(wheel_directory, config_settings, metadata_directory)
def build_sdist(
sdist_directory: str,
config_settings: Optional[dict[str, Union[str, List[str]]]] = None,
config_settings: dict[str, str | list[str]] | None = None,
) -> str:
from scikit_build_core.build.sdist import build_sdist as _impl
config_settings = _get_hooked_config(is_editable=False)
config_settings['sdist.exclude'].extend([
'*'
])
config_settings['sdist.include'] = [
'pyproject.toml',
'backend/setup.py',
'backend/versioning.py',
'backend/config.py',
'backend/dynamic_provider.py',
assert config_settings is not None
config_settings["sdist.exclude"].extend(["*"]) # type: ignore
config_settings["sdist.include"] = [
"pyproject.toml",
"backend/setup.py",
"backend/versioning.py",
"backend/config.py",
"backend/dynamic_provider.py",
]
return _impl(sdist_directory, config_settings)
+36 -31
View File
@@ -1,14 +1,15 @@
from __future__ import annotations
import os
import re
import shlex
import subprocess
import re
import sys
import os
from setup import ROOT_DIR
from scikit_build_core.settings.skbuild_read_settings import rich_print as _rich_print
from shutil import which
from typing import Optional
from scikit_build_core._logging import rich_print as _rich_print
from setup import ROOT_DIR
def rich_print(*args):
if sys.platform.startswith("win"):
@@ -19,12 +20,13 @@ def rich_print(*args):
return print(*args)
return _rich_print(*args)
class Versioning:
COMMAND = '{git} describe --tags --long --dirty'
GIT_BRANCH = '{git} rev-parse --abbrev-ref HEAD'
IS_TAGGED_CMD = '{git} tag --list --points-at=HEAD'
FMT_DEV = '{tag}.dev0'
FMT_TAGGED = '{tag}'
COMMAND = "{git} describe --tags --long --dirty"
GIT_BRANCH = "{git} rev-parse --abbrev-ref HEAD"
IS_TAGGED_CMD = "{git} tag --list --points-at=HEAD"
FMT_DEV = "{tag}.dev0"
FMT_TAGGED = "{tag}"
CMAKE_VERSION_R = r"set\(LIEF_VERSION_(MAJOR|MINOR|PATCH)\s(\d+)\)"
def __init__(self):
@@ -34,14 +36,14 @@ class Versioning:
args = dict(kwargs)
args["git"] = self._git
cmd_list = shlex.split(cmd.format(**args))
return subprocess.check_output(cmd_list,
text=True,
cwd=ROOT_DIR.as_posix()).strip()
return subprocess.check_output(
cmd_list, text=True, cwd=ROOT_DIR.as_posix()
).strip()
def has_git(self) -> bool:
return self._git is not None and (ROOT_DIR / ".git").is_dir()
def get_branch(self) -> Optional[str]:
def get_branch(self) -> str | None:
if not self.has_git():
return None
@@ -59,16 +61,16 @@ class Versioning:
if branch is not None and branch.startswith("release/"):
_, version = branch.split("release/")
major, minor, patch = version.split('.')
if patch == 'x':
major, minor, patch = version.split(".")
if patch == "x":
return f"{major}.{minor}"
return version
parts = version.split('-')
parts = version.split("-")
assert len(parts) in (3, 4)
dirty = len(parts) == 4
tag, count, sha = parts[:3]
MA, MI, PA = map(int, tag.split(".")) # 0.9.0 -> (0, 9, 0)
MA, MI, PA = map(int, tag.split(".")) # 0.9.0 -> (0, 9, 0)
if is_dev:
if MI == 17:
@@ -76,13 +78,13 @@ class Versioning:
# the 0.X.Y series
tag = "1.0.0"
else:
tag = f"{MA}.{MI + 1}.{0}"
tag = f"{MA + 1}.{MI}.{0}"
if count == '0' and not dirty:
if count == "0" and not dirty:
return tag
return fmt.format(tag=tag, gitsha=sha.lstrip('g'))
return fmt.format(tag=tag, gitsha=sha.lstrip("g"))
def version_from_git(self) -> Optional[str]:
def version_from_git(self) -> str | None:
if not self.has_git():
return None
@@ -90,21 +92,24 @@ class Versioning:
is_tagged = self._exec_git_cmd(Versioning.IS_TAGGED_CMD) != ""
git_version = self._exec_git_cmd(Versioning.COMMAND)
if is_tagged:
return self.format_version(version=git_version, fmt=Versioning.FMT_TAGGED)
return self.format_version(version=git_version, fmt=Versioning.FMT_DEV, is_dev=True)
return self.format_version(
version=git_version, fmt=Versioning.FMT_TAGGED
)
return self.format_version(
version=git_version, fmt=Versioning.FMT_DEV, is_dev=True
)
except Exception as e:
rich_print(f"[red]Error: {e}")
return None
def version_from_cmake(self) -> Optional[str]:
def version_from_cmake(self) -> str | None:
main_cmake = ROOT_DIR / "CMakeLists.txt"
cmakefile = main_cmake.read_text()
major: Optional[int] = None
minor: Optional[int] = None
patch: Optional[int] = None
major: int | None = None
minor: int | None = None
patch: int | None = None
itre = re.finditer(Versioning.CMAKE_VERSION_R, cmakefile,
flags=re.MULTILINE)
itre = re.finditer(Versioning.CMAKE_VERSION_R, cmakefile, flags=re.MULTILINE)
for cmake_version in itre:
typ, value = cmake_version.groups()
+7 -7
View File
@@ -1,10 +1,10 @@
tomli==2.4.0
scikit-build-core==0.11.6
tomli==2.4.1
scikit-build-core==1.0.3
# For Ninja: msvc.msvc14_get_vc_env
setuptools==80.9.0
setuptools==83.0.0
# For the "env" feature
pydantic==2.12.5
pydantic==2.13.4
# Implicit from scikit-build-core
pathspec==1.0.3
build==1.4.0
wheel==0.46.3
pathspec==1.1.1
build==1.5.0
wheel==0.47.0
+1 -9
View File
@@ -17,16 +17,8 @@ dex = true
[lief.features]
json = true
frozen = true
runtime = false
[lief.logging]
enabled = true
debug = false
#[lief.cross-compilation]
#osx-arch = "arm64"
#[lief.third-party]
#spdlog = "/path/to/spdlog-install"
+29 -14
View File
@@ -1,25 +1,40 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#!/usr/bin/env python3
"""Dump the *abstract* view of a binary (ELF / PE / Mach-O) as JSON.
# Description
# -----------
# Dump abstract informations in a JSON format
# see: abstract_reader.py
The abstract layer exposes the subset of information shared by every
supported executable format (sections, symbols, relocations, ...). This
script parses the input file, converts its abstract representation to
JSON via ``lief.to_json`` and pretty-prints it.
Example:
$ python abstract_json.py /bin/ls
"""
import argparse
import sys
import lief
import json
import sys
def main():
parser = argparse.ArgumentParser()
parser.add_argument('binary', help = 'A binary')
import lief
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
parser.add_argument("binary", help="Path to an ELF, PE or Mach-O binary")
args = parser.parse_args()
binary = lief.parse(args.binary)
binary = lief.parse(args.binary)
if binary is None:
print(f"Error: failed to parse '{args.binary}'", file=sys.stderr)
return 1
if isinstance(binary, lief.COFF.Binary):
print("COFF objects do not expose an abstract view", file=sys.stderr)
return 1
json_data = json.loads(lief.to_json(binary.abstract))
print(json.dumps(json_data, sort_keys = True, indent = 4))
print(json.dumps(json_data, sort_keys=True, indent=4))
return 0
if __name__ == "__main__":
sys.exit(main())
+109 -71
View File
@@ -1,21 +1,27 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Format-agnostic binary reader.
# Description
# -----------
# Universal format reader.
# Input can be PE, ELF or Mach-O
Uses the abstract layer of LIEF to render the common subset of
information (header, sections, relocations, symbols, imports,
exports, libraries) for an ELF, PE or Mach-O binary.
Example:
$ python abstract_reader.py -a /bin/ls
"""
import lief
import sys
import argparse
import sys
import traceback
class exceptions_handler(object):
import lief
class exceptions_handler:
func = None
def __init__(self, exceptions, on_except_callback=None):
self.exceptions = exceptions
self.exceptions = exceptions
self.on_except_callback = on_except_callback
def __call__(self, *args, **kwargs):
@@ -29,13 +35,12 @@ class exceptions_handler(object):
self.on_except_callback(e)
else:
print("-" * 60)
print("Exception in {}: {}".format(self.func.__name__, e))
exc_type, exc_value, exc_traceback = sys.exc_info()
print(f"Exception in {self.func.__name__}: {e}")
_exc_type, _exc_value, exc_traceback = sys.exc_info()
traceback.print_tb(exc_traceback)
print("-" * 60)
@exceptions_handler(Exception)
def print_header(binary):
header = binary.header
@@ -43,8 +48,6 @@ def print_header(binary):
print("== Header ==\n")
format_str = "{:<15} {:<30}"
format_hex = "{:<15} 0x{:<13x}"
format_dec = "{:<15} {:<30d}"
modes_str = " - ".join([str(m).split(".")[-1] for m in header.modes])
bitness = ""
@@ -54,14 +57,13 @@ def print_header(binary):
if header.is_64:
bitness = "64-bits"
print(format_str.format("Architecture:", str(header.architecture).split(".")[-1]))
print(format_str.format("Modes:", modes_str))
print(format_hex.format("Entrypoint:", header.entrypoint))
print(format_str.format("Object type:", str(header.object_type).split(".")[-1]))
print(format_str.format("Endianness:", str(header.endianness).split(".")[-1]))
print(format_str.format("Bitness:", bitness))
print("")
print(format_str.format("Modes:", modes_str))
print(format_hex.format("Entrypoint:", header.entrypoint))
print(format_str.format("Object type:", str(header.object_type).split(".")[-1]))
print(format_str.format("Endianness:", str(header.endianness).split(".")[-1]))
print(format_str.format("Bitness:", bitness))
print()
@exceptions_handler(Exception)
@@ -71,13 +73,16 @@ def print_sections(binary):
f_value = "|{:<30} | 0x{:<16x}| 0x{:<16x}| 0x{:<16x}| {:<9.2f}|"
print(f_title.format("Name", "File offset", "Size", "Virtual Address", "Entropy"))
for section in binary.sections:
print(f_value.format(\
section.name,\
section.offset,\
section.size,\
section.virtual_address,\
section.entropy))
print("")
print(
f_value.format(
section.name,
section.offset,
section.size,
section.virtual_address,
section.entropy,
)
)
print()
@exceptions_handler(Exception)
@@ -87,10 +92,9 @@ def print_relocations(binary):
f_value = "|0x{:<16x} | {:<6d}|"
print(f_title.format("Address", "Size"))
for relocation in binary.relocations:
print(f_value.format(\
relocation.address,\
relocation.size))
print("")
print(f_value.format(relocation.address, relocation.size))
print()
@exceptions_handler(Exception)
def print_symbols(binary):
@@ -103,7 +107,7 @@ def print_symbols(binary):
for symbol in binary.symbols:
print(f.format(symbol.name))
print("")
print()
@exceptions_handler(Exception)
@@ -113,8 +117,9 @@ def print_exported_functions(binary):
f = "|{:<30} |"
print(f.format("Name"))
for func in binary.exported_functions:
print(f.format(func))
print("")
print(f.format(func))
print()
@exceptions_handler(Exception)
def print_imported_functions(binary):
@@ -124,7 +129,7 @@ def print_imported_functions(binary):
print(f.format("Name"))
for func in binary.imported_functions:
print(f.format(func))
print("")
print()
@exceptions_handler(Exception)
@@ -135,58 +140,91 @@ def print_imported_libraries(binary):
print(f.format("Name"))
for library in binary.libraries:
print(f.format(library))
print("")
print()
def main():
parser = argparse.ArgumentParser(usage='%(prog)s [options] <elf-pe-macho>')
parser.add_argument('-a', '--all',
action='store_true', dest='show_all',
help='Show all information')
parser = argparse.ArgumentParser(usage="%(prog)s [options] <elf-pe-macho>")
parser.add_argument(
"-a", "--all", action="store_true", dest="show_all", help="Show all information"
)
parser.add_argument('-H', '--header',
action='store_true', dest='show_header',
help='Display header')
parser.add_argument(
"-H", "--header", action="store_true", dest="show_header", help="Display header"
)
parser.add_argument('-i', '--imported',
action='store_true', dest='show_imported_functions',
help='Display imported functions')
parser.add_argument(
"-i",
"--imported",
action="store_true",
dest="show_imported_functions",
help="Display imported functions",
)
parser.add_argument('-L', '--libraries',
action='store_true', dest='show_libraries',
help='Display Imported Libraries')
parser.add_argument(
"-L",
"--libraries",
action="store_true",
dest="show_libraries",
help="Display Imported Libraries",
)
parser.add_argument('-r', '--relocations',
action='store_true', dest='show_relocs',
help='Display the relocations (if present)')
parser.add_argument(
"-r",
"--relocations",
action="store_true",
dest="show_relocs",
help="Display the relocations (if present)",
)
parser.add_argument('-s', '--symbols',
action='store_true', dest='show_symbols',
help='Display Symbols')
parser.add_argument(
"-s",
"--symbols",
action="store_true",
dest="show_symbols",
help="Display Symbols",
)
parser.add_argument('-S', '--sections',
action='store_true', dest='show_sections',
help='Display Sections')
parser.add_argument(
"-S",
"--sections",
action="store_true",
dest="show_sections",
help="Display Sections",
)
parser.add_argument('-x', '--exported',
action='store_true', dest='show_exported_functions',
help='Display exported functions')
parser.add_argument(
"-x",
"--exported",
action="store_true",
dest="show_exported_functions",
help="Display exported functions",
)
parser.add_argument("binary",
metavar="<elf-pe-macho>",
help='Target File')
parser.add_argument("binary", metavar="<elf-pe-macho>", help="Target File")
args = parser.parse_args()
binary = lief.parse(args.binary)
if binary is None:
print(f"Error: failed to parse '{args.binary}'", file=sys.stderr)
return 1
if isinstance(binary, lief.COFF.Binary):
print("COFF objects do not expose an abstract view", file=sys.stderr)
return 1
binary = binary.abstract
if args.show_header or args.show_all:
print_header(binary)
if (args.show_imported_functions or args.show_all) and len(binary.imported_functions) > 0:
if (args.show_imported_functions or args.show_all) and len(
binary.imported_functions
) > 0:
print_imported_functions(binary)
if (args.show_exported_functions or args.show_all) and len(binary.exported_functions) > 0:
if (args.show_exported_functions or args.show_all) and len(
binary.exported_functions
) > 0:
print_exported_functions(binary)
if (args.show_libraries or args.show_all) and len(binary.libraries) > 0:
@@ -201,8 +239,8 @@ def main():
if (args.show_relocs or args.show_all) and len(binary.relocations) > 0:
print_relocations(binary)
return 0
if __name__ == "__main__":
main()
sys.exit(main())
@@ -1,56 +0,0 @@
#!/usr/bin/env python
import lief
import sys
import os
# Parse PE file
pe = lief.parse(sys.argv[1])
sep = (":") if sys.version_info.minor > 7 else ()
# Get authenticode
print(pe.authentihash_md5.hex(*sep)) # 1c:a0:91:53:dc:9a:3a:5f:34:1d:7f:9b:b9:56:69:4d
print(pe.authentihash(lief.PE.ALGORITHMS.SHA_1).hex(*sep)) # 1e:ad:dc:29:1e:db:41:a2:69:c2:ba:ae:4b:fb:9d:31:e7:bb:ab:59
# Check signature according to PKCS #7 and Microsoft documentation
print(pe.verify_signature()) # Return VERIFICATION_FLAGS.OK
bin_ca = None
# Look for the root CA in the PE file
for crt in pe.signatures[0].certificates:
if crt.issuer == "C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root CA":
bin_ca = crt
# Verify CA chain
bundle_path = os.getenv("LIEF_CA_BUNDLE", None) # Path to CA bundle (one can use those from signify:
# signify/certs/authenticode-bundle.pem)
if bundle_path is not None:
# Parse cert bundle and return a list of lief.PE.x509 objects
bundle = lief.PE.x509.parse(bundle_path)
print(bin_ca.is_trusted_by(bundle)) # VERIFICATION_FLAGS.OK
# Get the certificate used by the signer
cert_signer = pe.signatures[0].signers[0].cert
print(cert_signer)
bin_ca.verify(cert_signer) # Verify that cert_signer is signed the CA
# running with:
# LIEF_CA_BUNDLE=signify/signify/certs/authenticode-bundle.pem python ./authenticode.py avast_free_antivirus_setup_online.exe
#
# 1c:a0:91:53:dc:9a:3a:5f:34:1d:7f:9b:b9:56:69:4d
# 1e:ad:dc:29:1e:db:41:a2:69:c2:ba:ae:4b:fb:9d:31:e7:bb:ab:59
# VERIFICATION_FLAGS.OK
# cert. version : 3
# serial number : 04:09:18:1B:5F:D5:BB:66:75:53:43:B5:6F:95:50:08
# issuer name : C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root CA
# subject name : C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert SHA2 Assured ID Code Signing CA
# issued on : 2013-10-22 12:00:00
# expires on : 2028-10-22 12:00:00
# signed using : RSA with SHA-256
# RSA key size : 2048 bits
# basic constraints : CA=true, max_pathlen=0
# key usage : Digital Signature, Key Cert Sign, CRL Sign
# ext key usage : Code Signing
#
# VERIFICATION_FLAGS.OK
@@ -1,68 +0,0 @@
#!/usr/bin/env python
import lief
import argparse
import os
import stat
import sys
def change_interpreter(target, interpreter, output=None):
if not os.path.isfile(target) or not lief.is_elf(target):
print("Wrong target! ({})".format(target))
return 1
if not os.path.isfile(interpreter) or not lief.is_elf(interpreter):
print("Wrong interpreter! ({})".format(interpreter))
return 1
binary = lief.ELF.parse(target)
if not binary.has_interpreter:
print("The given target doesn't have interpreter!")
return 1
binary.interpreter = interpreter
output_path = output
if output_path is None:
output_path = os.path.basename(target)
output_path += "_updated"
if os.path.isfile(output_path):
os.remove(output_path)
binary.write(output_path)
# Set as executable
st = os.stat(output_path)
os.chmod(output_path, st.st_mode | stat.S_IEXEC)
return 0
def main():
parser = argparse.ArgumentParser(description='Change the ELF interpreter of the given binary')
parser.add_argument("-o", "--output",
help = 'Path to the binary rewritten',
action = 'store',
default = None)
parser.add_argument("target",
metavar="<elf>",
help='Target ELF file')
parser.add_argument("interpreter",
metavar="<interpreter>",
help='Path to the new interpreter')
args = parser.parse_args()
status = change_interpreter(args.target, args.interpreter, args.output)
sys.exit(status)
if __name__ == "__main__":
main()
Regular → Executable
+26 -13
View File
@@ -1,27 +1,40 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Dump a DEX file (Android Dalvik bytecode) as JSON.
# Description
# -----------
# Print information about a DEX file in the JSON format
Parses a ``.dex`` file and writes a pretty-printed JSON dump of its
structure (header, classes, methods, strings, ...) using
``lief.to_json``.
Example:
$ python dex_json.py classes.dex
"""
import argparse
import sys
import lief
import json
import sys
def main():
parser = argparse.ArgumentParser()
parser.add_argument('file', help='DEX binary')
import lief
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
parser.add_argument("file", help="Path to a DEX file")
args = parser.parse_args()
if not lief.is_dex(args.file):
print("{} is not a DEX file".format(args.file))
print(f"'{args.file}' is not a DEX file", file=sys.stderr)
return 1
dexfile = lief.DEX.parse(args.file)
dexfile = lief.DEX.parse(args.file)
if dexfile is None:
print(f"Error: failed to parse '{args.file}'", file=sys.stderr)
return 1
json_data = json.loads(lief.to_json(dexfile))
print(json.dumps(json_data, sort_keys = True, indent = 4))
print(json.dumps(json_data, sort_keys=True, indent=4))
return 0
if __name__ == "__main__":
sys.exit(main())
+123 -109
View File
@@ -1,29 +1,34 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Pretty-print the structure of an Android DEX file.
Parses a ``.dex`` file with ``lief.DEX.parse`` and renders header,
classes, methods, fields, strings, types, prototypes and the map
list, selected by command-line flags.
Example:
$ python dex_reader.py -a classes.dex
"""
# Description
# -----------
# Print information about Android DEX files
import sys
import os
import argparse
import shutil
import sys
import traceback
import lief
from lief import DEX
EXIT_STATUS = 0
terminal_rows, terminal_columns = 100, 100
try:
terminal_rows, terminal_columns = os.popen('stty size', 'r').read().split()
except ValueError:
pass
_term_size = shutil.get_terminal_size((100, 100))
terminal_columns = _term_size.columns
terminal_rows = _term_size.lines
class exceptions_handler(object):
class exceptions_handler:
func = None
def __init__(self, exceptions, on_except_callback=None):
self.exceptions = exceptions
self.exceptions = exceptions
self.on_except_callback = on_except_callback
def __call__(self, *args, **kwargs):
@@ -34,93 +39,73 @@ class exceptions_handler(object):
return self.func(*args, **kwargs)
except self.exceptions as e:
global EXIT_STATUS
print("{} raised: {}".format(self.func.__name__, e))
print(f"{self.func.__name__} raised: {e}")
EXIT_STATUS = 1
if self.on_except_callback is not None:
self.on_except_callback(e)
else:
print("-" * 60)
print("Exception in {}: {}".format(self.func.__name__, e))
exc_type, exc_value, exc_traceback = sys.exc_info()
print(f"Exception in {self.func.__name__}: {e}")
_exc_type, _exc_value, exc_traceback = sys.exc_info()
traceback.print_tb(exc_traceback)
print("-" * 60)
@exceptions_handler(Exception)
def print_information(dexfile):
print("== Information ==")
format_str = "{:<30} {:<30}"
format_hex = "{:<30} 0x{:<28x}"
format_dec = "{:<30} {:<30d}"
version = dexfile.version
print("DEX File version: {}".format(version))
print("")
print(f"DEX File version: {dexfile.version}")
print()
@exceptions_handler(Exception)
def print_header(dexfile):
format_str = "{:<33} {:<30}"
format_hex = "{:<33} 0x{:<28x}"
format_dec = "{:<33} {:<30d}"
print("== Header ==")
header = dexfile.header
print(header)
print(dexfile.header)
@exceptions_handler(Exception)
def print_classes(dexfile):
format_str = "{:<33} {:<30}"
format_hex = "{:<33} 0x{:<28x}"
format_dec = "{:<33} {:<30d}"
classes = dexfile.classes
print("== Classes ==")
for cls in classes:
for cls in dexfile.classes:
print(cls)
@exceptions_handler(Exception)
def print_fields(dexfile):
format_str = "{:<33} {:<30}"
format_hex = "{:<33} 0x{:<28x}"
format_dec = "{:<33} {:<30d}"
fields = dexfile.fields
print("== Fields ==")
for f in fields:
for f in dexfile.fields:
print(f)
@exceptions_handler(Exception)
def print_methods(dexfile):
format_str = "{:<33} {:<30}"
format_hex = "{:<33} 0x{:<28x}"
format_dec = "{:<33} {:<30d}"
methods = dexfile.methods
print("== Methods ==")
for m in methods:
for m in dexfile.methods:
print(m)
@exceptions_handler(Exception)
def print_strings(dexfile):
print("== Strings ==")
for s in dexfile.strings:
print(s)
@exceptions_handler(Exception)
def print_types(dexfile):
print("== Types ==")
for t in dexfile.types:
print(t)
@exceptions_handler(Exception)
def print_prototypes(dexfile):
print("== Prototypes ==")
for t in dexfile.prototypes:
print(t)
@exceptions_handler(Exception)
def print_map(dexfile):
print("== Map ==")
@@ -128,87 +113,116 @@ def print_map(dexfile):
def main():
parser = argparse.ArgumentParser(usage='%(prog)s [options] DEX files')
parser.add_argument('-a', '--all',
action='store_true', dest='show_all',
help='Show all information')
parser = argparse.ArgumentParser(usage="%(prog)s [options] DEX files")
parser.add_argument(
"-a", "--all", action="store_true", dest="show_all", help="Show all information"
)
parser.add_argument('-H', '--header',
action='store_true', dest='show_header',
help='Display header')
parser.add_argument(
"-H", "--header", action="store_true", dest="show_header", help="Display header"
)
parser.add_argument('-c', '--classes',
action='store_true', dest='show_classes',
help='Display classes')
parser.add_argument(
"-c",
"--classes",
action="store_true",
dest="show_classes",
help="Display classes",
)
parser.add_argument('-f', '--fields',
action='store_true', dest='show_fields',
help='Display Fields')
parser.add_argument(
"-f", "--fields", action="store_true", dest="show_fields", help="Display Fields"
)
parser.add_argument('-m', '--methods',
action='store_true', dest='show_methods',
help='Display Methods')
parser.add_argument(
"-m",
"--methods",
action="store_true",
dest="show_methods",
help="Display Methods",
)
parser.add_argument('-s', '--strings',
action='store_true', dest='show_strings',
help='Display Strings')
parser.add_argument(
"-s",
"--strings",
action="store_true",
dest="show_strings",
help="Display Strings",
)
parser.add_argument('-t', '--types',
action='store_true', dest='show_types',
help='Display Types')
parser.add_argument(
"-t", "--types", action="store_true", dest="show_types", help="Display Types"
)
parser.add_argument('-p', '--prototypes',
action='store_true', dest='show_prototypes',
help='Display Prototypes')
parser.add_argument(
"-p",
"--prototypes",
action="store_true",
dest="show_prototypes",
help="Display Prototypes",
)
parser.add_argument('-M', '--map',
action='store_true', dest='show_map',
help='Display Map')
parser.add_argument(
"-M", "--map", action="store_true", dest="show_map", help="Display Map"
)
parser.add_argument("file",
metavar="<dex-file>",
help='Target DEX File')
parser.add_argument("file", metavar="<dex-file>", help="Target DEX File")
logger_group = parser.add_argument_group('Logger')
logger_group = parser.add_argument_group("Logger")
verbosity = logger_group.add_mutually_exclusive_group()
verbosity.add_argument('--debug',
dest='main_verbosity',
action='store_const',
const=lief.logging.LEVEL.DEBUG)
verbosity.add_argument(
"--debug",
dest="main_verbosity",
action="store_const",
const=lief.logging.Level.Debug,
)
verbosity.add_argument('--trace',
dest='main_verbosity',
action='store_const',
const=lief.logging.LEVEL.TRACE)
verbosity.add_argument(
"--trace",
dest="main_verbosity",
action="store_const",
const=lief.logging.Level.Trace,
)
verbosity.add_argument('--info',
dest='main_verbosity',
action='store_const',
const=lief.logging.LEVEL.INFO)
verbosity.add_argument(
"--info",
dest="main_verbosity",
action="store_const",
const=lief.logging.Level.Info,
)
verbosity.add_argument('--warn',
dest='main_verbosity',
action='store_const',
const=lief.logging.LEVEL.WARN)
verbosity.add_argument(
"--warn",
dest="main_verbosity",
action="store_const",
const=lief.logging.Level.Warn,
)
verbosity.add_argument('--err',
dest='main_verbosity',
action='store_const',
const=lief.logging.LEVEL.ERROR)
verbosity.add_argument(
"--err",
dest="main_verbosity",
action="store_const",
const=lief.logging.Level.Err,
)
verbosity.add_argument('--critical',
dest='main_verbosity',
action='store_const',
const=lief.logging.LEVEL.CRITICAL)
verbosity.add_argument(
"--critical",
dest="main_verbosity",
action="store_const",
const=lief.logging.Level.Critical,
)
parser.set_defaults(main_verbosity=lief.logging.LEVEL.WARN)
parser.set_defaults(main_verbosity=lief.logging.Level.Warn)
args = parser.parse_args()
lief.logging.set_level(args.main_verbosity)
dexfile = DEX.parse(args.file)
if dexfile is None:
print(f"Error: failed to parse '{args.file}' as DEX", file=sys.stderr)
return 1
print_information(dexfile)
@@ -236,8 +250,8 @@ def main():
if args.show_map or args.show_all:
print_map(dexfile)
sys.exit(EXIT_STATUS)
return EXIT_STATUS
if __name__ == "__main__":
main()
sys.exit(main())
+30 -18
View File
@@ -1,35 +1,47 @@
#!/usr/bin/env python
'''
This script disassembles an ELF/PE/Mach-O binary using LIEF's extended API
"""Disassemble instructions at an address of an ELF/PE/Mach-O binary.
Uses LIEF's extended disassembly API to iterate over the instructions
located at the given virtual address of the binary.
Note: only available with the extended version of LIEF.
Example:
$ python disassembler.py /bin/ls 0x4000
"""
Note: this script is only working with the extended version of LIEF
'''
import argparse
import lief
import sys
from pathlib import Path
def disassemble(target: lief.Binary, addr: int):
import lief
def disassemble(target: lief.Binary, addr: int) -> None:
for inst in target.disassemble(addr):
print(inst)
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("file", help='Target file', type=Path)
parser.add_argument("address", help='Address to disassemble',
type=lambda x: int(x,0))
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
parser.add_argument("file", help="Target binary", type=Path)
parser.add_argument(
"address", help="Address to disassemble", type=lambda x: int(x, 0)
)
args = parser.parse_args()
target_file = args.file
addr = args.address
target = lief.parse(target_file)
target = lief.parse(args.file)
if target is None:
print(f"Can't load: {target_file}")
print(f"Can't load: {args.file}", file=sys.stderr)
return 1
if isinstance(target, lief.COFF.Binary):
print("COFF binaries are not supported by the disassembler", file=sys.stderr)
return 1
disassemble(target, addr)
disassemble(target, args.address)
return 0
if __name__ == "__main__":
raise SystemExit(main())
+58 -17
View File
@@ -1,25 +1,66 @@
#!/usr/bin/env python
"""Create a companion DWARF file from a PE binary.
Demonstrates the DWARF editor API: loads a PE binary, synthesizes a
compilation unit with one function returning a pointer to a
structure and a stack variable, then writes the result to
``/tmp/out.debug``.
Note: only available with the extended version of LIEF.
Example:
$ python dwarf_editor.py program.exe
"""
This example shows how to create a DWARF file by using LIEF's Python API
"""
import lief
import argparse
import sys
if not lief.__extended__:
print("This example requires the extended version of LIEF")
import lief
pe = lief.PE.parse(sys.argv[1])
editor: lief.dwarf.Editor = lief.dwarf.Editor.from_binary(pe)
unit: lief.dwarf.editor.CompilationUnit = editor.create_compilation_unit()
unit.set_producer("LIEF")
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
parser.add_argument("file", help="Input PE binary")
parser.add_argument(
"--output",
default="/tmp/out.debug",
help="Output DWARF file (default: %(default)s)",
)
args = parser.parse_args()
func: lief.dwarf.editor.Function = unit.create_function("hello")
func.set_address(0x123)
func.set_return_type(
unit.create_structure("my_struct_t").pointer_to()
)
if not lief.__extended__:
print("This example requires the extended version of LIEF", file=sys.stderr)
return 1
var: lief.dwarf.editor.Variable = func.create_stack_variable("local_var")
var.set_stack_offset(8)
pe = lief.PE.parse(args.file)
if pe is None:
print(f"Error: failed to parse '{args.file}' as PE", file=sys.stderr)
return 1
editor.write("/tmp/out.debug")
editor = lief.dwarf.Editor.from_binary(pe)
if editor is None:
print("Failed to create a DWARF editor", file=sys.stderr)
return 1
unit = editor.create_compilation_unit()
unit.set_producer("LIEF")
func = unit.create_function("hello")
func.set_address(0x123)
pointer_type = unit.create_structure("my_struct_t").pointer_to()
if pointer_type is None:
print("Failed to create the pointer type", file=sys.stderr)
return 1
func.set_return_type(pointer_type)
var = func.create_stack_variable("local_var")
var.set_stack_offset(8)
editor.write(args.output)
return 0
if __name__ == "__main__":
sys.exit(main())
+32 -15
View File
@@ -1,40 +1,57 @@
#!/usr/bin/env python
'''
This script lists libraries embedded in a dyld shared cache file
"""List the contents of a dyld shared cache.
Note: this script is only working with the extended version of LIEF
'''
Loads an Apple ``dyld`` shared cache (single file or multi-file
directory layout) and prints the embedded libraries, the mapping
information for each page range and the UUID of the sub-caches.
Note: only available with the extended version of LIEF.
Example:
$ python dyld_shared_cache_reader.py /System/Library/dyld/dyld_shared_cache_arm64e
"""
import sys
import lief
import argparse
import sys
from pathlib import Path
from typing import Optional
import lief
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("target", type=Path,
help='Target dyld shared file (file or dir)')
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
parser.add_argument(
"target", type=Path, help="Target dyld shared cache file or directory"
)
args = parser.parse_args()
target: Path = args.target
if not target.exists():
print(f"'{target}' does not exist")
print(f"'{target}' does not exist", file=sys.stderr)
return 1
dyld_cache = lief.dsc.load(target)
if dyld_cache is None:
print(f"Can't parse '{target}'")
print(f"Can't parse '{target}'", file=sys.stderr)
return 1
for lib in dyld_cache.libraries:
print(f"0x{lib.address:016x} {lib.path}")
print(f"{lib.address:#016x} {lib.path}")
for idx, info in enumerate(dyld_cache.mapping_info):
print(f"mapping_info[{idx:02d}]: [{info.address:016x}, {info.end_address:016x}] -> 0x{info.file_offset:016x}")
print(
f"mapping_info[{idx:02d}]: "
f"[{info.address:#016x}, {info.end_address:#016x}] -> "
f"{info.file_offset:#016x}"
)
for idx, subcache in enumerate(dyld_cache.subcaches):
uuid_str = ':'.join(map(lambda e: f"{e:02x}", subcache.uuid))
uuid_str = ":".join(f"{e:02x}" for e in subcache.uuid)
print(f"cache[{idx:02d}]: {uuid_str} {subcache.suffix}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+39 -17
View File
@@ -1,31 +1,53 @@
#!/usr/bin/env python
"""Promote a PIE executable to a shared library by exporting a function.
Takes a PIE ELF executable, declares an exported function at the
given address, and rewrites the binary so that it can be ``dlopen``-ed
and the function invoked via ``dlsym``.
Example:
$ python elf_bin2lib.py -n compute -o libcompute.so ./prog 0x1200
"""
import argparse
import lief
import sys
def bin2lib(binary, address, output, name=""):
import lief
def bin2lib(binary: lief.ELF.Binary, address: int, output: str, name: str = "") -> int:
if not binary.is_pie:
print("It only works with PIE binaries")
sys.exit(1)
print("It only works with PIE binaries", file=sys.stderr)
return 1
function = binary.add_exported_function(address, name)
print("Function created:")
print(function)
print("Function created:", function)
binary.write(output)
return 0
def main():
parser = argparse.ArgumentParser(description="")
parser.add_argument("--name", "-n", default="", help="Name of the function to create")
parser.add_argument("--output", "-o", default="libfoo.so", help="Output name. (Default: %(default)")
parser.add_argument("binary", help="The target binary")
parser.add_argument("address", type=lambda e: int(e, 0), help="Address of the function to export")
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
parser.add_argument(
"--name", "-n", default="", help="Name of the function to create"
)
parser.add_argument(
"--output", "-o", default="libfoo.so", help="Output name (default: %(default)s)"
)
parser.add_argument("binary", help="The target ELF binary")
parser.add_argument(
"address", type=lambda e: int(e, 0), help="Address of the function to export"
)
args = parser.parse_args()
binary = lief.parse(args.binary)
bin2lib(binary, args.address, args.output, name=args.name)
binary = lief.ELF.parse(args.binary)
if binary is None:
print(f"Error: failed to parse '{args.binary}' as ELF", file=sys.stderr)
return 1
return bin2lib(binary, args.address, args.output, name=args.name)
if __name__ == "__main__":
main()
sys.exit(main())
+75
View File
@@ -0,0 +1,75 @@
#!/usr/bin/env python
"""Change the program interpreter of an ELF executable.
Replaces the ``PT_INTERP`` entry (the ``.interp`` section) of a
dynamically-linked ELF executable with the path of another ELF
interpreter, then writes the patched binary to disk with the execute
bit set.
Example:
$ python elf_change_interpreter.py \\
--output /tmp/ls_musl /bin/ls /usr/lib/ld-musl-x86_64.so.1
"""
import argparse
import stat
import sys
from pathlib import Path
import lief
def change_interpreter(
target: Path, interpreter: Path, output: Path | None = None
) -> int:
if not target.is_file() or not lief.is_elf(target):
print(f"Wrong target! ({target})", file=sys.stderr)
return 1
if not interpreter.is_file() or not lief.is_elf(interpreter):
print(f"Wrong interpreter! ({interpreter})", file=sys.stderr)
return 1
binary = lief.ELF.parse(target)
if binary is None:
print(f"Failed to parse '{target}' as ELF", file=sys.stderr)
return 1
if not binary.has_interpreter:
print("The given target doesn't have an interpreter!", file=sys.stderr)
return 1
binary.interpreter = str(interpreter)
output_path = output or Path(f"{target.name}_updated")
output_path.unlink(missing_ok=True)
binary.write(output_path)
# Restore the execute bit that LIEF doesn't propagate.
st = output_path.stat()
output_path.chmod(st.st_mode | stat.S_IEXEC)
return 0
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
parser.add_argument(
"-o", "--output", help="Path to the rewritten binary", default=None, type=Path
)
parser.add_argument("target", metavar="<elf>", help="Target ELF file", type=Path)
parser.add_argument(
"interpreter",
metavar="<interpreter>",
help="Path to the new interpreter",
type=Path,
)
args = parser.parse_args()
return change_interpreter(args.target, args.interpreter, args.output)
if __name__ == "__main__":
sys.exit(main())
+150
View File
@@ -0,0 +1,150 @@
#!/usr/bin/env python3
"""Analyze ELF shared library dependencies and symbol versioning.
A cross-platform alternative to ldd that works without executing the binary.
Lists shared library dependencies, RPATH/RUNPATH search paths, and optionally
shows imported symbol versions (useful for checking glibc compatibility).
Inspired by conda-build's liefldd.py and Bitcoin's symbol-check.py.
Example:
$ python elf_deps.py /usr/bin/ls
Dependencies: /usr/bin/ls
========================================
Interpreter: /lib64/ld-linux-x86-64.so.2
Type: DYN (Position-Independent Executable)
Shared Libraries:
libselinux.so.1
libc.so.6
ld-linux-x86-64.so.2
$ python elf_deps.py --versions /usr/bin/ls
...
Symbol Versions:
GLIBC_2.2.5 (25 symbols)
GLIBC_2.3 (1 symbols)
GLIBC_2.17 (2 symbols)
"""
import argparse
from collections import defaultdict
import lief
HEADER_TYPES = {
lief.ELF.Header.FILE_TYPE.EXEC: "EXEC (Executable)",
lief.ELF.Header.FILE_TYPE.DYN: "DYN (Shared Object / PIE)",
lief.ELF.Header.FILE_TYPE.REL: "REL (Relocatable)",
lief.ELF.Header.FILE_TYPE.CORE: "CORE (Core Dump)",
}
def analyze_deps(filename, show_versions=False):
"""Analyze ELF dependencies and symbol version requirements."""
binary = lief.ELF.parse(filename)
if binary is None:
print(f"Error: failed to parse '{filename}' as ELF")
return False
file_type = HEADER_TYPES.get(binary.header.file_type, str(binary.header.file_type))
interpreter = binary.interpreter or "(none — statically linked)"
print(f"Dependencies: {filename}")
print("=" * 48)
print(f" Interpreter: {interpreter}")
print(f" Type: {file_type}")
print(f" Arch: {binary.header.machine_type.name}")
print()
# Shared libraries (DT_NEEDED entries)
libraries = list(binary.libraries)
if libraries:
print(" Shared Libraries:")
for lib in libraries:
print(f" {lib}")
else:
print(" Shared Libraries: (none — statically linked)")
print()
# RPATH and RUNPATH
rpath = None
runpath = None
for entry in binary.dynamic_entries:
if isinstance(entry, lief.ELF.DynamicEntryRpath):
rpath = entry.rpath
elif isinstance(entry, lief.ELF.DynamicEntryRunPath):
runpath = entry.runpath
if rpath or runpath:
print(" Search Paths:")
if rpath:
print(f" RPATH: {rpath}")
if runpath:
print(f" RUNPATH: {runpath}")
print()
# Symbol versions
if show_versions:
version_counts = defaultdict(int)
version_symbols = defaultdict(list)
for sym in binary.imported_symbols:
if not sym.has_version:
continue
version = sym.symbol_version
if not version.has_auxiliary_version:
continue
ver_name = version.symbol_version_auxiliary.name
version_counts[ver_name] += 1
version_symbols[ver_name].append(sym.name)
if version_counts:
print(" Symbol Versions:")
for ver_name in sorted(version_counts):
count = version_counts[ver_name]
print(f" {ver_name:<24} ({count} symbol{'s' if count != 1 else ''})")
print()
# Show highest required version per library prefix
lib_versions = defaultdict(list)
for ver_name in version_counts:
parts = ver_name.rsplit("_", 1)
if len(parts) == 2:
lib, ver_str = parts
try:
ver_tuple = tuple(int(x) for x in ver_str.split("."))
lib_versions[lib].append((ver_tuple, ver_name))
except ValueError:
pass
if lib_versions:
print(" Minimum Required Versions:")
for lib in sorted(lib_versions):
max_ver = max(lib_versions[lib], key=lambda x: x[0])
print(f" {lib}: {max_ver[1]}")
print()
return True
def main():
parser = argparse.ArgumentParser(
description="Analyze ELF shared library dependencies"
)
parser.add_argument("binaries", nargs="+", help="ELF binaries to analyze")
parser.add_argument(
"-v",
"--versions",
action="store_true",
help="Show imported symbol version requirements",
)
args = parser.parse_args()
for path in args.binaries:
analyze_deps(path, show_versions=args.versions)
if __name__ == "__main__":
main()
Regular → Executable
+22 -29
View File
@@ -1,43 +1,36 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Dump an ELF binary as JSON.
# Description
# -----------
# Print information about a ELF binary in the JSON format
#
# python elf_json.py /bin/ls
#
# {
# "dynamic_entries": [
# {
# "library": "libcap.so.2",
# "tag": "NEEDED",
# "value": 1
# },
# {
# "library": "libc.so.6",
# "tag": "NEEDED",
# "value": 74
# },
# ...
Parses an ELF file and writes a pretty-printed JSON dump of the full
structure (header, sections, segments, dynamic entries, symbols, ...)
using ``lief.to_json``.
Example:
$ python elf_json.py /bin/ls
"""
import argparse
import sys
import lief
import json
import sys
import lief
def main():
parser = argparse.ArgumentParser()
parser.add_argument('binary', help='ELF binary')
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
parser.add_argument("binary", help="Path to an ELF binary")
args = parser.parse_args()
binary = lief.parse(args.binary)
binary = lief.ELF.parse(args.binary)
if binary is None:
print(f"Error: failed to parse '{args.binary}' as ELF", file=sys.stderr)
return 1
json_data = json.loads(lief.to_json(binary))
print(json.dumps(json_data, sort_keys = True, indent = 4))
print(json.dumps(json_data, sort_keys=True, indent=4))
return 0
if __name__ == "__main__":
sys.exit(main())
+392 -229
View File
@@ -1,33 +1,35 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Pretty-print the structure of an ELF binary.
# Description
# -----------
# Print information about an ELF binary
Equivalent to ``readelf`` with a selection of the most useful flags
(``-h``, ``-S``, ``-l``, ``-d``, ``-s``, ``-r``, ``-V`` ...). The
target file is parsed with ``lief.ELF.parse`` and the requested
sections are rendered as formatted tables.
import os
Example:
$ python elf_reader.py -a /bin/ls
"""
import argparse
import shutil
import sys
import textwrap
import traceback
import lief
from lief import ELF
import argparse
terminal_rows, terminal_columns = 100, 110
try:
terminal_rows, terminal_columns = os.popen('stty size', 'r').read().split()
except ValueError:
pass
_term_size = shutil.get_terminal_size((110, 100))
terminal_columns = _term_size.columns - 10
terminal_rows = _term_size.lines
terminal_columns = int(terminal_columns) - 10
terminal_rows = int(terminal_rows)
class exceptions_handler(object):
class exceptions_handler:
func = None
def __init__(self, exceptions, on_except_callback=None):
self.exceptions = exceptions
self.exceptions = exceptions
self.on_except_callback = on_except_callback
def __call__(self, *args, **kwargs):
@@ -41,8 +43,8 @@ class exceptions_handler(object):
self.on_except_callback(e)
else:
print("-" * 60)
print("Exception in {}: {}".format(self.func.__name__, e))
exc_type, exc_value, exc_traceback = sys.exc_info()
print(f"Exception in {self.func.__name__}: {e}")
_exc_type, _exc_value, exc_traceback = sys.exc_info()
traceback.print_tb(exc_traceback)
print("-" * 60)
@@ -52,7 +54,6 @@ def print_header(binary):
header = binary.header
identity = header.identity
print("== Header ==\n")
format_str = "{:<30} {:<30}"
format_hex = "{:<30} 0x{:<13x}"
@@ -63,37 +64,53 @@ def print_header(binary):
if header.machine_type == lief.ELF.ARCH.ARM:
eflags_str = " - ".join([str(s).split(".")[-1] for s in header.arm_flags_list])
if header.machine_type in [lief.ELF.ARCH.MIPS, lief.ELF.ARCH.MIPS_RS3_LE, lief.ELF.ARCH.MIPS_X]:
if header.machine_type in [
lief.ELF.ARCH.MIPS,
lief.ELF.ARCH.MIPS_RS3_LE,
lief.ELF.ARCH.MIPS_X,
]:
eflags_str = " - ".join([str(s).split(".")[-1] for s in header.mips_flags_list])
if header.machine_type == lief.ELF.ARCH.PPC64:
eflags_str = " - ".join([str(s).split(".")[-1] for s in header.ppc64_flags_list])
eflags_str = " - ".join(
[str(s).split(".")[-1] for s in header.ppc64_flags_list]
)
if header.machine_type == lief.ELF.ARCH.HEXAGON:
eflags_str = " - ".join([str(s).split(".")[-1] for s in header.hexagon_flags_list])
eflags_str = " - ".join(
[str(s).split(".")[-1] for s in header.hexagon_flags_list]
)
if header.machine_type == lief.ELF.ARCH.LOONGARCH:
eflags_str = " - ".join([str(s).split(".")[-1] for s in header.loongarch_flags_list])
eflags_str = " - ".join(
[str(s).split(".")[-1] for s in header.loongarch_flags_list]
)
print(identity)
print(format_ide.format("Magic:", identity[0], identity[1], identity[2], identity[3]))
print(format_str.format("Class:", str(header.identity_class).split(".")[-1]))
print(format_str.format("Endianness:", str(header.identity_data).split(".")[-1]))
print(format_str.format("Version:", str(header.identity_version).split(".")[-1]))
print(format_str.format("OS/ABI:", str(header.identity_os_abi).split(".")[-1]))
print(format_dec.format("ABI Version:", header.identity_abi_version))
print(format_str.format("File Type:", str(header.file_type).split(".")[-1]))
print(format_str.format("Machine Type:", str(header.machine_type).split(".")[-1]))
print(format_str.format("Object File Version:", str(header.object_file_version).split(".")[-1]))
print(format_hex.format("Entry Point:", header.entrypoint))
print(
format_ide.format("Magic:", identity[0], identity[1], identity[2], identity[3])
)
print(format_str.format("Class:", str(header.identity_class).split(".")[-1]))
print(format_str.format("Endianness:", str(header.identity_data).split(".")[-1]))
print(format_str.format("Version:", str(header.identity_version).split(".")[-1]))
print(format_str.format("OS/ABI:", str(header.identity_os_abi).split(".")[-1]))
print(format_dec.format("ABI Version:", header.identity_abi_version))
print(format_str.format("File Type:", str(header.file_type).split(".")[-1]))
print(format_str.format("Machine Type:", str(header.machine_type).split(".")[-1]))
print(
format_str.format(
"Object File Version:", str(header.object_file_version).split(".")[-1]
)
)
print(format_hex.format("Entry Point:", header.entrypoint))
print(format_hex.format("Program Header Offset:", header.program_header_offset))
print(format_hex.format("Section Header Offset:", header.section_header_offset))
print(format_hex.format("Processor flags:", header.processor_flag) + eflags_str)
print(format_dec.format("Header Size:", header.header_size))
print(format_dec.format("Program Header Size:", header.program_header_size))
print(format_dec.format("Section Header Size:", header.section_header_size))
print(format_dec.format("Number of segments:", header.numberof_segments))
print(format_dec.format("Number of sections:", header.numberof_sections))
print("")
print(format_hex.format("Processor flags:", header.processor_flag) + eflags_str)
print(format_dec.format("Header Size:", header.header_size))
print(format_dec.format("Program Header Size:", header.program_header_size))
print(format_dec.format("Section Header Size:", header.section_header_size))
print(format_dec.format("Number of segments:", header.numberof_segments))
print(format_dec.format("Number of sections:", header.numberof_sections))
print()
@exceptions_handler(Exception)
@@ -103,22 +120,38 @@ def print_sections(binary):
print("== Sections ==\n")
f_title = "|{:<30} | {:<12}| {:<17}| {:<12}| {:<10}| {:<8}| {:<8}|"
f_value = "|{:<30} | {:<12}| 0x{:<14x} | 0x{:<10x}| 0x{:<8x}| {:<8.2f}| {:<10}"
print(f_title.format("Name", "Type", "Virtual address", "File offset", "Size", "Entropy", "Segment(s)"))
print(
f_title.format(
"Name",
"Type",
"Virtual address",
"File offset",
"Size",
"Entropy",
"Segment(s)",
)
)
for section in sections:
segments_str = " - ".join([str(s.type).split(".")[-1] for s in section.segments])
print(f_value.format(
section.name,
str(section.type).split(".")[-1],
section.virtual_address,
section.file_offset,
section.size,
abs(section.entropy),
segments_str))
print("")
segments_str = " - ".join(
[str(s.type).split(".")[-1] for s in section.segments]
)
print(
f_value.format(
section.name,
str(section.type).split(".")[-1],
section.virtual_address,
section.file_offset,
section.size,
abs(section.entropy),
segments_str,
)
)
print()
else:
print("No sections")
@exceptions_handler(Exception)
def print_segments(binary):
segments = binary.segments
@@ -127,8 +160,17 @@ def print_segments(binary):
print("== Segments ==\n")
f_title = "|{:<30} | {:<10}| {:<18}| {:<17}| {:<17}| {:<17}| {:<19}|"
f_value = "|{:<30} | {:<10}| 0x{:<16x}| 0x{:<15x}| 0x{:<15x}| 0x{:<15x}| {}"
print(f_title.format("Type",
"Flags", "File offset", "Virtual Address", "Virtual Size", "Size", "Sections"))
print(
f_title.format(
"Type",
"Flags",
"File offset",
"Virtual Address",
"Virtual Size",
"Size",
"Sections",
)
)
for segment in segments:
sections = segment.sections
@@ -144,17 +186,22 @@ def print_segments(binary):
flags_str[2] = "x"
flags_str = "".join(flags_str)
print(f_value.format(
str(segment.type).split(".")[-1],
flags_str,
segment.file_offset,
segment.virtual_address,
segment.virtual_size,
segment.physical_size, s))
print("")
print(
f_value.format(
str(segment.type).split(".")[-1],
flags_str,
segment.file_offset,
segment.virtual_address,
segment.virtual_size,
segment.physical_size,
s,
)
)
print()
else:
print("No segments")
@exceptions_handler(Exception)
def print_dynamic_entries(binary):
dynamic_entries = binary.dynamic_entries
@@ -170,20 +217,37 @@ def print_dynamic_entries(binary):
if entry.tag == ELF.DynamicEntry.TAG.NULL:
continue
if entry.tag in [ELF.DynamicEntry.TAG.SONAME, ELF.DynamicEntry.TAG.NEEDED, ELF.DynamicEntry.TAG.RUNPATH, ELF.DynamicEntry.TAG.RPATH]:
print(f_value.format(str(entry.tag).split(".")[-1], entry.value, entry.name))
elif type(entry) is ELF.DynamicEntryArray: # [ELF.DynamicEntry.TAG.INIT_ARRAY,ELF.DynamicEntry.TAG.FINI_ARRAY]:
print(f_value.format(str(entry.tag).split(".")[-1], entry.value, ", ".join(map(hex, entry.array))))
elif entry.tag == ELF.DynamicEntry.TAG.FLAGS:
flags_str = " - ".join([str(ELF.DynamicEntryFlags.FLAG(s)).split(".")[-1] for s in entry.flags])
print(f_value.format(str(entry.tag).split(".")[-1], entry.value, flags_str))
elif entry.tag == ELF.DynamicEntry.TAG.FLAGS_1:
flags_str = " - ".join([str(ELF.DynamicEntryFlags.FLAG(s)).split(".")[-1] for s in entry.flags])
if entry.tag in [
ELF.DynamicEntry.TAG.SONAME,
ELF.DynamicEntry.TAG.NEEDED,
ELF.DynamicEntry.TAG.RUNPATH,
ELF.DynamicEntry.TAG.RPATH,
]:
print(
f_value.format(str(entry.tag).split(".")[-1], entry.value, entry.name)
)
elif (
type(entry) is ELF.DynamicEntryArray
): # [ELF.DynamicEntry.TAG.INIT_ARRAY,ELF.DynamicEntry.TAG.FINI_ARRAY]:
print(
f_value.format(
str(entry.tag).split(".")[-1],
entry.value,
", ".join(map(hex, entry.array)),
)
)
elif (
entry.tag == ELF.DynamicEntry.TAG.FLAGS
or entry.tag == ELF.DynamicEntry.TAG.FLAGS_1
):
flags_str = " - ".join(
[str(ELF.DynamicEntryFlags.FLAG(s)).split(".")[-1] for s in entry.flags]
)
print(f_value.format(str(entry.tag).split(".")[-1], entry.value, flags_str))
else:
print(f_value.format(str(entry.tag).split(".")[-1], entry.value, ""))
print("")
print()
@exceptions_handler(Exception)
@@ -195,12 +259,20 @@ def print_symbols(symbols, no_trunc):
maxsize = max([len(symbol.name) for symbol in symbols])
SIZE = 70
maxsize = min(maxsize, terminal_columns - SIZE) if terminal_columns > SIZE else terminal_columns
maxsize = (
min(maxsize, terminal_columns - SIZE)
if terminal_columns > SIZE
else terminal_columns
)
f_title = "|{:<" + str(maxsize) + "} | {:<7}| {:<8}| {:<10}| {:<8}| {:<4}| {:<14}|"
f_value = "|{:<" + str(maxsize) + "} | {:<7}| {:<8x}| {:<10}| {:<8}| {:<4}| {:<14}|"
print(f_title.format("Name", "Type", "Value", "Visibility", "Binding", "I/E", "Version"))
print(
f_title.format(
"Name", "Type", "Value", "Visibility", "Binding", "I/E", "Version"
)
)
for symbol in symbols:
symbol_version = symbol.symbol_version if symbol.has_version else ""
@@ -218,20 +290,21 @@ def print_symbols(symbols, no_trunc):
wrapped = textwrap.wrap(symbol_name, maxsize)
if len(wrapped) <= 1 or no_trunc:
symbol_name = symbol_name
else:
if len(wrapped) > 1 and not no_trunc:
symbol_name = wrapped[0][:-3] + "..."
print(f_value.format(
symbol_name,
str(symbol.type).split(".")[-1],
symbol.value,
str(symbol.visibility).split(".")[-1],
str(symbol.binding).split(".")[-1],
import_export,
str(symbol_version)
))
print(
f_value.format(
symbol_name,
str(symbol.type).split(".")[-1],
symbol.value,
str(symbol.visibility).split(".")[-1],
str(symbol.binding).split(".")[-1],
import_export,
str(symbol_version),
)
)
@exceptions_handler(Exception)
def print_dynamic_symbols(binary, args):
@@ -244,22 +317,24 @@ def print_symtab_symbols(binary, args):
print("== Symtab symbols ==\n")
print_symbols(binary.symtab_symbols, args.no_trunc)
@exceptions_handler(Exception)
def print_relocations(binary, relocations):
f_title = "|{:<10} | {:<10}| {:<8}| {:<8}| {:<8}| {:<15}| {:<30} |"
f_value = "|0x{:<8x} | {:<10}| {:<8d}| {:<8d}| {:<8x}| {:<15}| {:<30} |"
print(f_title.format("Address", "Type", "Info", "Size", "Addend", "Purpose", "Symbol"))
print(
f_title.format("Address", "Type", "Info", "Size", "Addend", "Purpose", "Symbol")
)
for relocation in relocations:
type = str(relocation.type)
if binary.header.machine_type == ELF.ARCH.x86_64:
type = str(relocation.type)
elif binary.header.machine_type == ELF.ARCH.i386:
type = str(relocation.type)
elif binary.header.machine_type == ELF.ARCH.ARM:
type = str(relocation.type)
elif binary.header.machine_type == ELF.ARCH.AARCH64:
if (
binary.header.machine_type == ELF.ARCH.x86_64
or binary.header.machine_type == ELF.ARCH.i386
or binary.header.machine_type == ELF.ARCH.ARM
or binary.header.machine_type == ELF.ARCH.AARCH64
):
type = str(relocation.type)
symbol_name = ""
@@ -270,20 +345,22 @@ def print_relocations(binary, relocations):
elif symbol.type == lief.ELF.Symbol.TYPE.SECTION:
shndx = symbol.shndx
sections = binary.sections
if 0 < shndx and shndx < len(sections):
if 0 < shndx < len(sections):
symbol_name = sections[shndx].name + " + " + hex(relocation.addend)
else:
symbol_name = "<section #{}>".format(shndx)
symbol_name = f"<section #{shndx}>"
print(f_value.format(
relocation.address,
type.split(".")[-1],
relocation.info,
relocation.size,
relocation.addend,
str(relocation.purpose).split(".")[-1],
symbol_name))
print(
f_value.format(
relocation.address,
type.split(".")[-1],
relocation.info,
relocation.size,
relocation.addend,
str(relocation.purpose).split(".")[-1],
symbol_name,
)
)
@exceptions_handler(Exception)
@@ -296,7 +373,6 @@ def print_all_relocations(binary):
print("== Dynamic Relocations ==\n")
print_relocations(binary, dynamicrelocations)
if len(pltgot_relocations) > 0:
print("== PLT/GOT Relocations ==\n")
print_relocations(binary, pltgot_relocations)
@@ -305,6 +381,7 @@ def print_all_relocations(binary):
print("== Object Relocations ==\n")
print_relocations(binary, object_relocations)
@exceptions_handler(Exception)
def print_exported_symbols(binary, args):
symbols = binary.exported_symbols
@@ -315,6 +392,7 @@ def print_exported_symbols(binary, args):
return
print_symbols(symbols, args.no_trunc)
@exceptions_handler(Exception)
def print_imported_symbols(binary, args):
symbols = binary.imported_symbols
@@ -325,16 +403,17 @@ def print_imported_symbols(binary, args):
return
print_symbols(symbols, args.no_trunc)
@exceptions_handler(Exception)
def print_information(binary):
print("== Information ==\n")
format_str = "{:<30} {:<30}"
format_hex = "{:<30} 0x{:<28x}"
format_dec = "{:<30} {:<30d}"
print(format_hex.format("Address base:", binary.imagebase))
print(format_hex.format("Virtual size:", binary.virtual_size))
print(format_str.format("PIE:", str(binary.is_pie)))
print(format_str.format("NX:", str(binary.has_nx)))
print(format_str.format("PIE:", str(binary.is_pie)))
print(format_str.format("NX:", str(binary.has_nx)))
@exceptions_handler(Exception)
def print_gnu_hash(binary):
@@ -349,12 +428,12 @@ def print_gnu_hash(binary):
format_hex = "{:<30} 0x{:<28x}"
format_dec = "{:<30} {:<30d}"
print(format_dec.format("Number of buckets:", gnu_hash.nb_buckets))
print(format_dec.format("Number of buckets:", gnu_hash.nb_buckets))
print(format_dec.format("First symbol index:", gnu_hash.symbol_index))
print(format_hex.format("Shift Count:", gnu_hash.shift2))
print(format_str.format("Bloom filters:", gnu_hash.bloom_filters))
print(format_str.format("Buckets:", gnu_hash.buckets))
print(format_str.format("Hash values:", gnu_hash.hash_values))
print(format_hex.format("Shift Count:", gnu_hash.shift2))
print(format_str.format("Bloom filters:", gnu_hash.bloom_filters))
print(format_str.format("Buckets:", gnu_hash.buckets))
print(format_str.format("Hash values:", gnu_hash.hash_values))
@exceptions_handler(Exception)
@@ -367,13 +446,12 @@ def print_sysv_hash(binary):
sysv_hash = binary.sysv_hash
format_str = "{:<30} {}"
format_hex = "{:<30} 0x{:<28x}"
format_dec = "{:<30} {:<30d}"
print(format_dec.format("Number of buckets:", sysv_hash.nbucket))
print(format_dec.format("Number of chains:", sysv_hash.nchain))
print(format_str.format("Buckets:", sysv_hash.buckets))
print(format_str.format("Chains:", sysv_hash.chains))
print(format_dec.format("Number of chains:", sysv_hash.nchain))
print(format_str.format("Buckets:", sysv_hash.buckets))
print(format_str.format("Chains:", sysv_hash.chains))
@exceptions_handler(Exception)
@@ -381,37 +459,36 @@ def print_notes(binary):
print("== Notes ==\n")
format_str = "{:<19} {}"
format_hex = "{:<19} 0x{:<28x}"
format_dec = "{:<19} {:<30d}"
notes = binary.notes
for idx, note in enumerate(notes):
description = note.description
description_str = " ".join(map(lambda e : "{:02x}".format(e), description[:16]))
description_str = " ".join(f"{e:02x}" for e in description[:16])
if len(description) > 16:
description_str += " ..."
print("Note #{:d}".format(idx))
print(f"Note #{idx:d}")
type_str = note.type_core if note.is_core else note.type
type_str = str(type_str).split(".")[-1]
print(format_str.format("Name:", note.name))
print(format_str.format("Type:", type_str))
print(format_str.format("Name:", note.name))
print(format_str.format("Type:", type_str))
print(format_str.format("Description:", description_str))
note_details = note.details
if isinstance(note_details, lief.ELF.AndroidIdent):
print(format_dec.format("SDK Version:", note_details.sdk_version))
print(format_str.format("NDK Version:", note_details.ndk_version))
print(format_dec.format("SDK Version:", note_details.sdk_version))
print(format_str.format("NDK Version:", note_details.ndk_version))
print(format_str.format("NDK build number:", note_details.ndk_build_number))
if isinstance(note_details, lief.ELF.NoteAbi):
version = note_details.version
version_str = "{:d}.{:d}.{:d}".format(version[0], version[1], version[2])
version = note_details.version
version_str = f"{version[0]:d}.{version[1]:d}.{version[2]:d}"
print(format_str.format("ABI:", note_details.abi))
print(format_str.format("ABI:", note_details.abi))
print(format_str.format("Version:", version_str))
if note.type == ELF.Note.TYPE.GNU_GOLD_VERSION:
@@ -420,7 +497,6 @@ def print_notes(binary):
if note.is_core:
print(note_details)
print("\n")
@@ -428,19 +504,19 @@ def print_notes(binary):
def print_ctor(binary):
print("== Constructors ==\n")
print("Functions: ({:d})".format(len(binary.ctor_functions)))
print(f"Functions: ({len(binary.ctor_functions):d})")
for idx, f in enumerate(binary.ctor_functions):
print(" [{:d}] {}: 0x{:x}".format(idx, f.name, f.address))
print(f" [{idx:d}] {f.name}: 0x{f.address:x}")
@exceptions_handler(Exception)
def print_strings(binary):
print("== Strings ==\n")
strings = binary.strings
print("Strings: ({:d})".format(len(binary.strings)))
print(f"Strings: ({len(binary.strings):d})")
for s in strings:
print(" {}".format(s))
print(f" {s}")
@exceptions_handler(Exception)
@@ -448,140 +524,223 @@ def print_functions(binary):
print("== Functions ==\n")
functions = binary.functions
print("Functions: ({:d})".format(len(functions)))
print(f"Functions: ({len(functions):d})")
for idx, f in enumerate(functions):
print(" [{:d}] {}: 0x{:x}".format(idx, f.name, f.address))
print(f" [{idx:d}] {f.name}: 0x{f.address:x}")
def main():
parser = argparse.ArgumentParser(add_help=False, prog=sys.argv[0])
parser.add_argument("elf_file")
parser.add_argument('-a', '--all',
action='store_true', dest='show_all',
help='Equivalent to: -h -l -S -s -r -d -V')
parser.add_argument(
"-a",
"--all",
action="store_true",
dest="show_all",
help="Equivalent to: -h -l -S -s -r -d -V",
)
parser.add_argument('-d', '--dynamic',
action='store_true', dest='show_dynamic_tags',
help='Display the dynamic section')
parser.add_argument(
"-d",
"--dynamic",
action="store_true",
dest="show_dynamic_tags",
help="Display the dynamic section",
)
parser.add_argument('-H', '--help',
action='help', dest='help',
help='Display this information')
parser.add_argument(
"-H", "--help", action="help", dest="help", help="Display this information"
)
parser.add_argument('-h', '--file-header',
action='store_true', dest='show_file_header',
help='Display the ELF file header')
parser.add_argument(
"-h",
"--file-header",
action="store_true",
dest="show_file_header",
help="Display the ELF file header",
)
parser.add_argument('-i', '--imported',
action='store_true', dest='show_imported_symbols',
help='Display imported symbols')
parser.add_argument(
"-i",
"--imported",
action="store_true",
dest="show_imported_symbols",
help="Display imported symbols",
)
parser.add_argument('-l', '--program-headers', '--segments',
action='store_true', dest='show_program_header',
help='Display the program headers')
parser.add_argument(
"-l",
"--program-headers",
"--segments",
action="store_true",
dest="show_program_header",
help="Display the program headers",
)
parser.add_argument('-S', '--section-headers', '--sections',
action='store_true', dest='show_section_header',
help="Display the sections' headers")
parser.add_argument(
"-S",
"--section-headers",
"--sections",
action="store_true",
dest="show_section_header",
help="Display the sections' headers",
)
parser.add_argument('-e', '--headers',
action='store_true', dest='show_all_headers',
help='Equivalent to: -h -l -S')
parser.add_argument(
"-e",
"--headers",
action="store_true",
dest="show_all_headers",
help="Equivalent to: -h -l -S",
)
parser.add_argument('-s', '--symbols', '--syms',
action='store_true', dest='show_symbols',
help='Display the symbol table')
parser.add_argument(
"-s",
"--symbols",
"--syms",
action="store_true",
dest="show_symbols",
help="Display the symbol table",
)
parser.add_argument('--dynamic-symbols', '--dsyms',
action='store_true', dest='show_dynamic_symbols',
help='Display the dynamic symbols')
parser.add_argument(
"--dynamic-symbols",
"--dsyms",
action="store_true",
dest="show_dynamic_symbols",
help="Display the dynamic symbols",
)
parser.add_argument('--symtab-symbols', '--ssyms',
action='store_true', dest='show_symtab_symbols',
help='Display the symtab symbols')
parser.add_argument(
"--symtab-symbols",
"--ssyms",
action="store_true",
dest="show_symtab_symbols",
help="Display the symtab symbols",
)
parser.add_argument('-r', '--relocs',
action='store_true', dest='show_relocs',
help='Display the relocations (if present)')
parser.add_argument(
"-r",
"--relocs",
action="store_true",
dest="show_relocs",
help="Display the relocations (if present)",
)
parser.add_argument('-V', '--version-info',
action='store_true', dest='show_version_info',
help='Display the version sections (if present)')
parser.add_argument(
"-V",
"--version-info",
action="store_true",
dest="show_version_info",
help="Display the version sections (if present)",
)
parser.add_argument('-x', '--exported',
action='store_true', dest='show_exported_symbols',
help='Display exported symbols')
parser.add_argument(
"-x",
"--exported",
action="store_true",
dest="show_exported_symbols",
help="Display exported symbols",
)
parser.add_argument('--gnu-hash',
action='store_true', dest='show_gnu_hash',
help='Display GNU Hash')
parser.add_argument(
"--gnu-hash", action="store_true", dest="show_gnu_hash", help="Display GNU Hash"
)
parser.add_argument('--sysv-hash',
action='store_true', dest='show_sysv_hash',
help='Display SYSV Hash')
parser.add_argument(
"--sysv-hash",
action="store_true",
dest="show_sysv_hash",
help="Display SYSV Hash",
)
parser.add_argument('-n', '--notes',
action='store_true', dest='show_notes',
help='Display Notes')
parser.add_argument(
"-n", "--notes", action="store_true", dest="show_notes", help="Display Notes"
)
parser.add_argument('--no-trunc',
action='store_true', dest='no_trunc',
default=False,
help='Do not trunc symbol names ...')
parser.add_argument(
"--no-trunc",
action="store_true",
dest="no_trunc",
default=False,
help="Do not trunc symbol names ...",
)
parser.add_argument('--ctor',
action='store_true', dest='show_ctor',
help='Constructor functions')
parser.add_argument(
"--ctor", action="store_true", dest="show_ctor", help="Constructor functions"
)
parser.add_argument('--strings',
action='store_true', dest='show_strings',
help='Strings present in the current ELF')
parser.add_argument(
"--strings",
action="store_true",
dest="show_strings",
help="Strings present in the current ELF",
)
parser.add_argument('--functions',
action='store_true', dest='show_functions',
help='List all function addresses found')
parser.add_argument(
"--functions",
action="store_true",
dest="show_functions",
help="List all function addresses found",
)
# Logging setup
logger_group = parser.add_argument_group('Logger')
logger_group = parser.add_argument_group("Logger")
verbosity = logger_group.add_mutually_exclusive_group()
verbosity.add_argument('--debug',
dest='main_verbosity',
action='store_const',
const=lief.logging.LEVEL.DEBUG)
verbosity.add_argument(
"--debug",
dest="main_verbosity",
action="store_const",
const=lief.logging.Level.Debug,
)
verbosity.add_argument('--trace',
dest='main_verbosity',
action='store_const',
const=lief.logging.LEVEL.TRACE)
verbosity.add_argument(
"--trace",
dest="main_verbosity",
action="store_const",
const=lief.logging.Level.Trace,
)
verbosity.add_argument('--info',
dest='main_verbosity',
action='store_const',
const=lief.logging.LEVEL.INFO)
verbosity.add_argument(
"--info",
dest="main_verbosity",
action="store_const",
const=lief.logging.Level.Info,
)
verbosity.add_argument('--warn',
dest='main_verbosity',
action='store_const',
const=lief.logging.LEVEL.WARN)
verbosity.add_argument(
"--warn",
dest="main_verbosity",
action="store_const",
const=lief.logging.Level.Warn,
)
verbosity.add_argument('--err',
dest='main_verbosity',
action='store_const',
const=lief.logging.LEVEL.ERROR)
verbosity.add_argument(
"--err",
dest="main_verbosity",
action="store_const",
const=lief.logging.Level.Err,
)
verbosity.add_argument('--critical',
dest='main_verbosity',
action='store_const',
const=lief.logging.LEVEL.CRITICAL)
verbosity.add_argument(
"--critical",
dest="main_verbosity",
action="store_const",
const=lief.logging.Level.Critical,
)
parser.set_defaults(main_verbosity=lief.logging.LEVEL.WARN)
parser.set_defaults(main_verbosity=lief.logging.Level.Warn)
args = parser.parse_args()
lief.logging.set_level(args.main_verbosity)
binary = ELF.parse(args.elf_file)
if binary is None:
print(f"Error: failed to parse '{args.elf_file}' as ELF", file=sys.stderr)
return 1
print_information(binary)
if args.show_all:
do_file_header = do_section_header = do_program_header = True
@@ -589,7 +748,7 @@ def main():
if args.show_all_headers:
do_file_header = do_section_header = do_program_header = True
else:
do_file_header = args.show_file_header
do_file_header = args.show_file_header
do_section_header = args.show_section_header
do_program_header = args.show_program_header
@@ -605,10 +764,14 @@ def main():
if args.show_dynamic_tags or args.show_all:
print_dynamic_entries(binary)
if (args.show_symbols or args.show_all or args.show_dynamic_symbols) and len(binary.dynamic_symbols) > 0:
if (args.show_symbols or args.show_all or args.show_dynamic_symbols) and len(
binary.dynamic_symbols
) > 0:
print_dynamic_symbols(binary, args)
if (args.show_symbols or args.show_all or args.show_symtab_symbols) and len(binary.symtab_symbols) > 0:
if (args.show_symbols or args.show_all or args.show_symtab_symbols) and len(
binary.symtab_symbols
) > 0:
print_symtab_symbols(binary, args)
if args.show_relocs or args.show_all:
@@ -638,8 +801,8 @@ def main():
if args.show_functions:
print_functions(binary)
return 0
if __name__ == "__main__":
main()
sys.exit(main())
+33 -31
View File
@@ -1,43 +1,45 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Strip the section table from an ELF binary.
# Description
# -----------
# Remove the section table from an ELF binary
# so that some tools are blow minded (e.g. gdb)
#
# Example:
# $ python elf_remove_section_table.py /bin/ls ls_without_sections
# $ ls
# elf_remove_section_table.py ls_without_sections
# $ ls_without_sections
# $ elf_remove_section_table.py ls_without_sections
# $ readelf -S ls_without_sections
#
# Il n'y a pas de section dans ce fichier.
# $ gdb ls_without_sections
# "ls_without_sections": not in executable format: File format not recognized
Zeros out the ``e_shoff`` and ``e_shnum`` fields of the ELF header so
that tools relying on the section table (notably ``gdb``, ``readelf
-S``) lose visibility into the binary while the program headers
remain intact and the file still runs.
Example:
$ python elf_remove_section_table.py /bin/ls ls_nosec
$ readelf -S ls_nosec
There are no sections in this file.
$ ./ls_nosec # still runs
"""
import argparse
import sys
import lief
from lief import ELF
def remove_section_table(filename, output):
binary = lief.ELF.parse(filename) # Build an ELF binary
import lief
def remove_section_table(filename: str, output: str) -> int:
binary = lief.ELF.parse(filename)
if binary is None:
print(f"Error: failed to parse '{filename}' as ELF", file=sys.stderr)
return 1
header = binary.header
header.section_header_offset = 0;
header.numberof_sections = 0;
header.section_header_offset = 0
header.numberof_sections = 0
binary.write(output)
return 0
binary.write(output);
def main():
if len(sys.argv) != 3:
print("Usage: {} <elf binary> <output>".format(sys.argv[0]))
sys.exit(1)
remove_section_table(sys.argv[1], sys.argv[2])
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
parser.add_argument("input", metavar="<elf>", help="Input ELF binary")
parser.add_argument("output", metavar="<out>", help="Path to the rewritten binary")
args = parser.parse_args()
return remove_section_table(args.input, args.output)
if __name__ == "__main__":
main()
sys.exit(main())

Some files were not shown because too many files have changed in this diff Show More