├── .cargo └── config.toml ├── .github └── workflows │ └── rust.yml ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── build.rs ├── crates ├── examples │ ├── Cargo.toml │ ├── src │ │ ├── bin │ │ │ ├── ar.rs │ │ │ ├── dyldcachedump.rs │ │ │ ├── elftoefi.rs │ │ │ ├── nm.rs │ │ │ ├── objcopy.rs │ │ │ ├── objdump.rs │ │ │ ├── objectmap.rs │ │ │ ├── pecopy.rs │ │ │ ├── readobj.rs │ │ │ └── simple_write.rs │ │ ├── lib.rs │ │ ├── objcopy.rs │ │ ├── objdump.rs │ │ └── readobj │ │ │ ├── elf.rs │ │ │ ├── macho.rs │ │ │ ├── mod.rs │ │ │ ├── pe.rs │ │ │ └── xcoff.rs │ ├── testfiles │ │ ├── archive │ │ │ ├── bsd.a.readobj │ │ │ ├── gnu.a.readobj │ │ │ └── thin.a.readobj │ │ ├── coff │ │ │ ├── import_msvc.lib.objdump │ │ │ └── import_msvc.lib.readobj │ │ ├── elf │ │ │ ├── base-aarch64-gnu-properties.o.readobj-elf-note │ │ │ ├── base-aarch64.o.objdump │ │ │ ├── base-aarch64.o.readobj │ │ │ ├── base-aarch64.objdump │ │ │ ├── base-aarch64.readobj │ │ │ ├── base-debug-zlib.o.readobj-section │ │ │ ├── base-debug-zstd.o.readobj-section │ │ │ ├── base-mips64el.o.readobj │ │ │ ├── base-mips64el.readobj │ │ │ ├── base-relr-i686.objdump │ │ │ ├── base-relr-i686.readobj │ │ │ ├── base-relr-x86_64.objdump │ │ │ ├── base-relr-x86_64.readobj │ │ │ ├── base-strip.objdump │ │ │ ├── base-strip.readobj │ │ │ ├── base-x86_64-gnu-properties.o.readobj-elf-note │ │ │ ├── base.o.objdump │ │ │ ├── base.o.readobj │ │ │ ├── base.objdump │ │ │ ├── base.readobj │ │ │ ├── comdat.o.objdump-comdat │ │ │ ├── comdat.o.readobj-section │ │ │ ├── nostd-mipsel.o.readobj │ │ │ ├── nostd-mipsel.readobj │ │ │ └── symtab_shndx.o.objdump-shndx │ │ ├── macho │ │ │ ├── base-aarch64-debug.o.objdump │ │ │ ├── base-aarch64-debug.o.readobj │ │ │ ├── base-aarch64.o.objcopy │ │ │ ├── base-aarch64.o.objdump │ │ │ ├── base-aarch64.o.readobj │ │ │ ├── base-aarch64.objdump │ │ │ ├── base-aarch64.readobj │ │ │ ├── base-x86_64-debug.o.objdump │ │ │ ├── base-x86_64-debug.o.readobj │ │ │ ├── base-x86_64.o.objcopy │ │ │ ├── base-x86_64.o.objdump │ │ │ ├── base-x86_64.o.readobj │ │ │ ├── base-x86_64.objdump │ │ │ ├── base-x86_64.readobj │ │ │ ├── reloc-aarch64.o.objcopy │ │ │ ├── reloc-aarch64.o.objdump │ │ │ ├── reloc-aarch64.o.readobj │ │ │ ├── reloc-arm.o.objdump │ │ │ ├── reloc-arm.o.readobj │ │ │ ├── reloc-i386.o.objdump │ │ │ ├── reloc-i386.o.readobj │ │ │ ├── reloc-x86_64.o.objcopy │ │ │ ├── reloc-x86_64.o.objdump │ │ │ └── reloc-x86_64.o.readobj │ │ ├── pe │ │ │ ├── base-bigobj.o.objdump │ │ │ ├── base-bigobj.o.readobj │ │ │ ├── base-bigobj.obj.objdump │ │ │ ├── base-bigobj.obj.readobj │ │ │ ├── base-gnu.exe.objdump │ │ │ ├── base-gnu.exe.readobj │ │ │ ├── base-gnu.exe.readobj-pe-base-reloc │ │ │ ├── base.exe.objdump │ │ │ ├── base.exe.readobj │ │ │ ├── base.o.objdump │ │ │ ├── base.o.readobj │ │ │ ├── base.obj.objdump │ │ │ ├── base.obj.readobj │ │ │ ├── resource.exe.readobj-pe-resource │ │ │ ├── weak-extern.o.objdump │ │ │ └── weak-extern.o.readobj │ │ ├── wasm │ │ │ ├── base.o.objdump │ │ │ ├── base.wasm.objdump │ │ │ ├── global-wasm32.objdump │ │ │ ├── global-wasm64-import.objdump │ │ │ └── global-wasm64.objdump │ │ └── xcoff │ │ │ ├── base.o.objdump │ │ │ ├── base.o.readobj │ │ │ ├── base.xcoff.objdump │ │ │ ├── base.xcoff.readobj │ │ │ ├── base32.o.objdump │ │ │ ├── base32.o.readobj │ │ │ ├── base32.xcoff.objdump │ │ │ └── base32.xcoff.readobj │ └── tests │ │ └── testfiles.rs └── rewrite │ ├── Cargo.toml │ ├── src │ ├── elf.rs │ ├── error.rs │ ├── lib.rs │ ├── main.rs │ └── rewriter.rs │ ├── testfiles │ └── elf │ │ ├── annobin-strtab │ │ ├── base-relr-i686.noop │ │ ├── base-relr-x86_64.noop │ │ ├── base.add-needed │ │ ├── base.add-rpath │ │ ├── base.add-runpath │ │ ├── base.delete-needed │ │ ├── base.delete-section │ │ ├── base.delete-symbol │ │ ├── base.noop │ │ ├── base.rename-section │ │ ├── base.rename-symbol │ │ ├── base.replace-needed │ │ ├── base.set-interpreter │ │ ├── base.set-runpath │ │ └── libbase.so.noop │ └── tests │ └── testfiles.rs ├── src ├── archive.rs ├── build │ ├── bytes.rs │ ├── elf.rs │ ├── error.rs │ ├── mod.rs │ └── table.rs ├── common.rs ├── elf.rs ├── endian.rs ├── lib.rs ├── macho.rs ├── pe.rs ├── pod.rs ├── read │ ├── any.rs │ ├── archive.rs │ ├── coff │ │ ├── comdat.rs │ │ ├── file.rs │ │ ├── import.rs │ │ ├── mod.rs │ │ ├── relocation.rs │ │ ├── section.rs │ │ └── symbol.rs │ ├── elf │ │ ├── attributes.rs │ │ ├── comdat.rs │ │ ├── compression.rs │ │ ├── dynamic.rs │ │ ├── file.rs │ │ ├── hash.rs │ │ ├── mod.rs │ │ ├── note.rs │ │ ├── relocation.rs │ │ ├── section.rs │ │ ├── segment.rs │ │ ├── symbol.rs │ │ └── version.rs │ ├── gnu_compression.rs │ ├── macho │ │ ├── dyld_cache.rs │ │ ├── fat.rs │ │ ├── file.rs │ │ ├── load_command.rs │ │ ├── mod.rs │ │ ├── relocation.rs │ │ ├── section.rs │ │ ├── segment.rs │ │ └── symbol.rs │ ├── mod.rs │ ├── pe │ │ ├── data_directory.rs │ │ ├── export.rs │ │ ├── file.rs │ │ ├── import.rs │ │ ├── mod.rs │ │ ├── relocation.rs │ │ ├── resource.rs │ │ ├── rich.rs │ │ └── section.rs │ ├── read_cache.rs │ ├── read_ref.rs │ ├── traits.rs │ ├── util.rs │ ├── wasm.rs │ └── xcoff │ │ ├── comdat.rs │ │ ├── file.rs │ │ ├── mod.rs │ │ ├── relocation.rs │ │ ├── section.rs │ │ ├── segment.rs │ │ └── symbol.rs ├── write │ ├── coff │ │ ├── mod.rs │ │ ├── object.rs │ │ └── writer.rs │ ├── elf │ │ ├── mod.rs │ │ ├── object.rs │ │ └── writer.rs │ ├── macho.rs │ ├── mod.rs │ ├── pe.rs │ ├── string.rs │ ├── util.rs │ └── xcoff.rs └── xcoff.rs ├── tests ├── build │ ├── elf.rs │ └── mod.rs ├── integration.rs ├── parse_self.rs ├── read │ ├── coff.rs │ ├── elf.rs │ ├── macho.rs │ └── mod.rs └── round_trip │ ├── bss.rs │ ├── coff.rs │ ├── comdat.rs │ ├── common.rs │ ├── elf.rs │ ├── macho.rs │ ├── mod.rs │ ├── section_flags.rs │ └── tls.rs └── xtask ├── Cargo.toml └── src └── main.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [alias] 2 | xtask = "run --manifest-path ./xtask/Cargo.toml --" 3 | -------------------------------------------------------------------------------- /.github/workflows/rust.yml: -------------------------------------------------------------------------------- 1 | name: Rust 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | os: ["ubuntu-latest"] 14 | rust_channel: ["stable", "beta", "nightly"] 15 | include: 16 | - rust_channel: "stable" 17 | os: "macOS-latest" 18 | runs-on: ${{matrix.os}} 19 | steps: 20 | - uses: actions/checkout@v4 21 | with: 22 | submodules: true 23 | - uses: dtolnay/rust-toolchain@master 24 | with: 25 | toolchain: ${{matrix.rust_channel}} 26 | - run: cargo xtask check 27 | - run: cargo xtask test 28 | - run: cargo xtask test-release 29 | 30 | features: 31 | runs-on: ubuntu-latest 32 | steps: 33 | - uses: actions/checkout@v4 34 | with: 35 | submodules: true 36 | - uses: dtolnay/rust-toolchain@stable 37 | - run: cargo xtask features 38 | 39 | cross: 40 | runs-on: ubuntu-latest 41 | steps: 42 | - uses: actions/checkout@v4 43 | with: 44 | submodules: true 45 | - uses: dtolnay/rust-toolchain@stable 46 | with: 47 | targets: i686-unknown-linux-gnu, powerpc64-unknown-linux-gnu 48 | - uses: taiki-e/install-action@v2 49 | with: 50 | tool: cross 51 | - run: cargo xtask cross 52 | 53 | msrv: 54 | runs-on: ubuntu-latest 55 | steps: 56 | - uses: actions/checkout@v4 57 | with: 58 | submodules: true 59 | - uses: dtolnay/rust-toolchain@1.65.0 60 | - uses: dtolnay/rust-toolchain@1.76.0 61 | - run: cargo xtask msrv 62 | 63 | rustfmt: 64 | runs-on: ubuntu-latest 65 | steps: 66 | - uses: actions/checkout@v4 67 | - uses: dtolnay/rust-toolchain@stable 68 | with: 69 | components: rustfmt 70 | - run: cargo xtask fmt 71 | 72 | doc: 73 | runs-on: ubuntu-latest 74 | steps: 75 | - uses: actions/checkout@v4 76 | - uses: dtolnay/rust-toolchain@stable 77 | - run: cargo xtask doc 78 | 79 | coverage: 80 | runs-on: ubuntu-latest 81 | container: 82 | image: xd009642/tarpaulin 83 | options: --security-opt seccomp=unconfined 84 | steps: 85 | - uses: actions/checkout@v4 86 | with: 87 | submodules: true 88 | - uses: dtolnay/rust-toolchain@stable 89 | - run: cargo xtask coverage_lcov 90 | - name: Upload to Coveralls 91 | uses: coverallsapp/github-action@master 92 | with: 93 | github-token: ${{ secrets.GITHUB_TOKEN }} 94 | path-to-lcov: './lcov.info' 95 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | /xtask/Cargo.lock 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "testfiles"] 2 | path = testfiles 3 | url = https://github.com/gimli-rs/object-testfiles 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "object" 3 | version = "0.37.0" 4 | edition = "2018" 5 | keywords = ["object", "elf", "mach-o", "pe", "coff"] 6 | license = "Apache-2.0 OR MIT" 7 | repository = "https://github.com/gimli-rs/object" 8 | # NB: if this number increases to 1.81-or-later delete the `build.rs` script 9 | # as it's no longer necessary. 10 | rust-version = "1.65" 11 | description = "A unified interface for reading and writing object file formats." 12 | include = [ 13 | "/build.rs", 14 | "/Cargo.toml", 15 | "/CHANGELOG.md", 16 | "/README.md", 17 | "/LICENSE-APACHE", 18 | "/LICENSE-MIT", 19 | "/src", 20 | "/tests", 21 | ] 22 | 23 | [package.metadata.docs.rs] 24 | features = ['doc'] 25 | 26 | [dependencies] 27 | crc32fast = { version = "1.2", default-features = false, optional = true } 28 | flate2 = { version = "1", optional = true } 29 | indexmap = { version = "2.0", default-features = false, optional = true } 30 | wasmparser = { version = "0.232.0", default-features = false, optional = true } 31 | memchr = { version = "2.4.1", default-features = false } 32 | hashbrown = { version = "0.15.0", features = ["default-hasher"], default-features = false, optional = true } 33 | ruzstd = { version = "0.8.1", optional = true } 34 | 35 | # Internal feature, only used when building as part of libstd, not part of the 36 | # stable interface of this crate. 37 | core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' } 38 | compiler_builtins = { version = '0.1.2', optional = true } 39 | alloc = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-alloc' } 40 | 41 | [features] 42 | #======================================= 43 | # Read/write features. 44 | 45 | # Core read support. You will need to enable some file formats too. 46 | read_core = [] 47 | # Read support for most file formats (including unaligned files). 48 | read = ["read_core", "archive", "coff", "elf", "macho", "pe", "xcoff", "unaligned"] 49 | # Core write support. You will need to enable some file formats too. 50 | write_core = ["dep:crc32fast", "dep:indexmap", "dep:hashbrown"] 51 | # Core write support with libstd features. You will need to enable some file formats too. 52 | write_std = ["write_core", "std", "indexmap?/std", "crc32fast?/std"] 53 | # Write support for all file formats, including libstd features. 54 | write = ["write_std", "coff", "elf", "macho", "pe", "xcoff"] 55 | # Core builder support. You will need to enable some file formats too. 56 | build_core = ["read_core", "write_core"] 57 | # Builder support for all file formats. 58 | build = ["build_core", "write_std", "elf"] 59 | 60 | #======================================= 61 | # Misc features. 62 | 63 | # Enable things that require libstd. 64 | # Currently, this provides an `Error` implementation. 65 | std = ["memchr/std"] 66 | # Enable decompression of compressed sections. 67 | # This feature is not required if you want to do your own decompression. 68 | compression = ["dep:flate2", "dep:ruzstd", "std"] 69 | # Treat all types as unaligned. 70 | # Normally types use the alignment required by the specifications, but 71 | # sometimes files do not strictly follow the specifications. 72 | # This may be useful to enable when processing files for architectures 73 | # that have no alignment constraints. 74 | unaligned = [] 75 | 76 | #======================================= 77 | # File format features. 78 | archive = [] 79 | coff = [] 80 | elf = [] 81 | macho = [] 82 | pe = ["coff"] 83 | wasm = ["dep:wasmparser"] 84 | xcoff = [] 85 | 86 | #======================================= 87 | # By default, support all read features. 88 | default = ["read", "compression"] 89 | 90 | #======================================= 91 | # Umbrella feature for enabling all user-facing features of this crate. Does not 92 | # enable internal features like `rustc-dep-of-std`. 93 | all = ["read", "write", "build", "std", "compression", "wasm"] 94 | 95 | # Use of --all-features is not supported. 96 | # This is a dummy feature to detect when --all-features is used. 97 | cargo-all = [] 98 | 99 | #======================================= 100 | # Documentation should be generated with everything in "all" except for "unaligned". 101 | doc = [ 102 | "read_core", "write_std", "build_core", 103 | "std", "compression", 104 | "archive", "coff", "elf", "macho", "pe", "wasm", "xcoff", 105 | ] 106 | 107 | #======================================= 108 | # Unstable features. Breaking changes in these features will not affect versioning. 109 | unstable = [] 110 | unstable-all = ["all", "unstable"] 111 | 112 | #======================================= 113 | # Internal feature, only used when building as part of libstd, not part of the 114 | # stable interface of this crate. 115 | rustc-dep-of-std = ['core', 'compiler_builtins', 'alloc', 'memchr/rustc-dep-of-std'] 116 | 117 | [workspace] 118 | members = ["crates/*"] 119 | default-members = [".", "crates/examples"] 120 | resolver = "2" 121 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 The Gimli Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `object` 2 | 3 | The `object` crate provides a unified interface to working with object files 4 | across platforms. It supports reading relocatable object files and executable files, 5 | and writing COFF/ELF/Mach-O/XCOFF relocatable object files and ELF/PE executable files. 6 | 7 | For reading files, it provides multiple levels of support: 8 | 9 | * raw struct definitions suitable for zero copy access 10 | * low level APIs for accessing the raw structs ([example](crates/examples/src/readobj/)) 11 | * a higher level unified API for accessing common features of object files, such 12 | as sections and symbols ([example](crates/examples/src/objdump.rs)) 13 | 14 | Supported file formats for reading: ELF, Mach-O, Windows PE/COFF, Wasm, XCOFF, and Unix archive. 15 | 16 | For writing files, it provides: 17 | 18 | * low level writers for ELF, PE, and COFF 19 | * higher level builder for ELF ([example](crates/rewrite/src)) 20 | * a unified API for writing relocatable object files (ELF, Mach-O, COFF, XCOFF) 21 | ([example](crates/examples/src/bin/simple_write.rs)) 22 | 23 | ## Example for unified read API 24 | ```rust 25 | use object::{Object, ObjectSection}; 26 | use std::error::Error; 27 | use std::fs; 28 | 29 | /// Reads a file and displays the name of each section. 30 | fn main() -> Result<(), Box> { 31 | let binary_data = fs::read("path/to/binary")?; 32 | let file = object::File::parse(&*binary_data)?; 33 | for section in file.sections() { 34 | println!("{}", section.name()?); 35 | } 36 | Ok(()) 37 | } 38 | ``` 39 | 40 | See [`crates/examples`](crates/examples) for more examples. 41 | 42 | ## Minimum Supported Rust Version (MSRV) 43 | 44 | Changes to MSRV are considered breaking changes. We are conservative about changing the MSRV, 45 | but sometimes are required to due to dependencies. The MSRV with all features enabled is 1.81.0. 46 | The MSRV with some features disabled is 1.65.0. 47 | 48 | ## License 49 | 50 | Licensed under either of 51 | 52 | * Apache License, Version 2.0 ([`LICENSE-APACHE`](./LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0) 53 | * MIT license ([`LICENSE-MIT`](./LICENSE-MIT) or https://opensource.org/licenses/MIT) 54 | 55 | at your option. 56 | 57 | ## Contribution 58 | 59 | Unless you explicitly state otherwise, any contribution intentionally submitted 60 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 61 | dual licensed as above, without any additional terms or conditions. 62 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | use std::str; 3 | 4 | fn main() { 5 | // Temporary check to see if the rustc version >= 1.81 in which case the 6 | // `Error` trait is always available. This is temporary because in the 7 | // future the MSRV of this crate will be beyond 1.81 in which case this 8 | // build script can be deleted. 9 | let minor = rustc_minor_version().unwrap_or(0); 10 | if minor >= 81 { 11 | println!("cargo:rustc-cfg=core_error"); 12 | } 13 | if minor >= 80 { 14 | println!("cargo:rustc-check-cfg=cfg(core_error)"); 15 | } 16 | } 17 | 18 | fn rustc_minor_version() -> Option { 19 | let rustc = std::env::var("RUSTC").unwrap(); 20 | let output = Command::new(rustc).arg("--version").output().ok()?; 21 | let version = str::from_utf8(&output.stdout).ok()?; 22 | let mut pieces = version.split('.'); 23 | if pieces.next() != Some("rustc 1") { 24 | return None; 25 | } 26 | pieces.next()?.parse().ok() 27 | } 28 | -------------------------------------------------------------------------------- /crates/examples/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "object-examples" 3 | version = "0.0.0" 4 | edition = "2018" 5 | 6 | [dependencies] 7 | clap = "4.3.24" 8 | memmap2 = "0.9.4" 9 | object = { path = "../..", default-features = false } 10 | 11 | [features] 12 | read = ["object/read"] 13 | write = ["object/write"] 14 | wasm = ["object/wasm"] 15 | xcoff = ["object/xcoff"] 16 | all = ["read", "write", "wasm", "xcoff"] 17 | unstable-all = ["all"] 18 | default = ["read"] 19 | 20 | [[bin]] 21 | name = "ar" 22 | required-features = ["object/read_core", "object/archive"] 23 | 24 | [[bin]] 25 | name = "dyldcachedump" 26 | required-features = ["object/read"] 27 | 28 | [[bin]] 29 | name = "elftoefi" 30 | required-features = ["object/read_core", "object/write_core", "object/elf", "object/pe", "object/std"] 31 | 32 | [[bin]] 33 | name = "objcopy" 34 | required-features = ["read", "write"] 35 | 36 | [[bin]] 37 | name = "objdump" 38 | required-features = ["read"] 39 | 40 | [[bin]] 41 | name = "objectmap" 42 | required-features = ["object/read"] 43 | 44 | [[bin]] 45 | name = "nm" 46 | required-features = ["object/read"] 47 | 48 | [[bin]] 49 | name = "pecopy" 50 | required-features = ["object/read_core", "object/write_core", "object/pe", "object/std"] 51 | 52 | [[bin]] 53 | name = "readobj" 54 | required-features = ["read"] 55 | 56 | [[bin]] 57 | name = "simple_write" 58 | required-features = ["write"] 59 | -------------------------------------------------------------------------------- /crates/examples/src/bin/ar.rs: -------------------------------------------------------------------------------- 1 | use std::{env, fs, process}; 2 | 3 | fn main() { 4 | let mut args = env::args().skip(1); 5 | if args.len() < 2 { 6 | eprintln!( 7 | "Usage: {} [...]", 8 | env::args().next().unwrap() 9 | ); 10 | process::exit(1); 11 | } 12 | 13 | let op = args.next().unwrap(); 14 | let file_path = args.next().unwrap(); 15 | 16 | let file = match fs::File::open(&file_path) { 17 | Ok(file) => file, 18 | Err(err) => { 19 | println!("Failed to open file '{}': {}", file_path, err,); 20 | return; 21 | } 22 | }; 23 | let file = match unsafe { memmap2::Mmap::map(&file) } { 24 | Ok(mmap) => mmap, 25 | Err(err) => { 26 | println!("Failed to map file '{}': {}", file_path, err,); 27 | return; 28 | } 29 | }; 30 | let archive = match object::read::archive::ArchiveFile::parse(&*file) { 31 | Ok(file) => file, 32 | Err(err) => { 33 | println!("Failed to parse file '{}': {}", file_path, err); 34 | return; 35 | } 36 | }; 37 | match op.chars().next().unwrap() { 38 | 't' => { 39 | for member in archive.members() { 40 | let member = member.unwrap(); 41 | println!("{}", String::from_utf8_lossy(member.name())); 42 | } 43 | } 44 | op => println!("Invalid operation: {}", op), 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /crates/examples/src/bin/dyldcachedump.rs: -------------------------------------------------------------------------------- 1 | use object::read::macho::DyldCache; 2 | use object::Endianness; 3 | use std::{env, fs, process}; 4 | 5 | fn main() { 6 | let arg_len = env::args().len(); 7 | if arg_len <= 1 { 8 | eprintln!("Usage: {} ...", env::args().next().unwrap()); 9 | process::exit(1); 10 | } 11 | 12 | for file_path in env::args().skip(1) { 13 | if arg_len > 2 { 14 | println!(); 15 | println!("{}:", file_path); 16 | } 17 | 18 | let file = match fs::File::open(&file_path) { 19 | Ok(file) => file, 20 | Err(err) => { 21 | println!("Failed to open file '{}': {}", file_path, err,); 22 | continue; 23 | } 24 | }; 25 | let mmap = match unsafe { memmap2::Mmap::map(&file) } { 26 | Ok(mmap) => mmap, 27 | Err(err) => { 28 | println!("Failed to map file '{}': {}", file_path, err,); 29 | continue; 30 | } 31 | }; 32 | let data = &*mmap; 33 | 34 | let subcache_suffixes = match DyldCache::::subcache_suffixes(data) { 35 | Ok(subcaches_suffixes) => subcaches_suffixes, 36 | Err(err) => { 37 | println!( 38 | "Failed to parse Dyld shared cache file '{}': {}", 39 | file_path, err, 40 | ); 41 | continue; 42 | } 43 | }; 44 | let Ok(subcache_files) = subcache_suffixes 45 | .into_iter() 46 | .map(|suffix| { 47 | let subcache_path = format!("{}{}", file_path, suffix); 48 | let file = match fs::File::open(&subcache_path) { 49 | Ok(file) => file, 50 | Err(err) => { 51 | println!("Failed to open file '{}': {}", subcache_path, err); 52 | return Err(()); 53 | } 54 | }; 55 | let mmap = match unsafe { memmap2::Mmap::map(&file) } { 56 | Ok(mmap) => mmap, 57 | Err(err) => { 58 | println!("Failed to map file '{}': {}", subcache_path, err); 59 | return Err(()); 60 | } 61 | }; 62 | Ok(mmap) 63 | }) 64 | .collect::, _>>() 65 | else { 66 | continue; 67 | }; 68 | let subcache_data: Vec<&[u8]> = subcache_files.iter().map(|f| &**f).collect(); 69 | 70 | let cache = match DyldCache::::parse(data, &subcache_data) { 71 | Ok(cache) => cache, 72 | Err(err) => { 73 | println!( 74 | "Failed to parse Dyld shared cache file '{}': {}", 75 | file_path, err, 76 | ); 77 | continue; 78 | } 79 | }; 80 | 81 | // Print the list of image paths in this file. 82 | for image in cache.images() { 83 | if let Ok(path) = image.path() { 84 | println!("{}", path); 85 | } 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /crates/examples/src/bin/nm.rs: -------------------------------------------------------------------------------- 1 | use object::{ 2 | Object, ObjectSection, ObjectSymbol, SectionIndex, SectionKind, Symbol, SymbolKind, 3 | SymbolSection, 4 | }; 5 | use std::collections::HashMap; 6 | use std::{env, fs, process}; 7 | 8 | fn main() { 9 | let arg_len = env::args().len(); 10 | if arg_len <= 1 { 11 | eprintln!("Usage: {} ...", env::args().next().unwrap()); 12 | process::exit(1); 13 | } 14 | 15 | for file_path in env::args().skip(1) { 16 | if arg_len > 2 { 17 | println!(); 18 | println!("{}:", file_path); 19 | } 20 | 21 | let file = match fs::File::open(&file_path) { 22 | Ok(file) => file, 23 | Err(err) => { 24 | println!("Failed to open file '{}': {}", file_path, err,); 25 | continue; 26 | } 27 | }; 28 | let file = match unsafe { memmap2::Mmap::map(&file) } { 29 | Ok(mmap) => mmap, 30 | Err(err) => { 31 | println!("Failed to map file '{}': {}", file_path, err,); 32 | continue; 33 | } 34 | }; 35 | let file = match object::File::parse(&*file) { 36 | Ok(file) => file, 37 | Err(err) => { 38 | println!("Failed to parse file '{}': {}", file_path, err); 39 | continue; 40 | } 41 | }; 42 | 43 | let section_kinds = file.sections().map(|s| (s.index(), s.kind())).collect(); 44 | 45 | println!("Debugging symbols:"); 46 | for symbol in file.symbols() { 47 | print_symbol(&symbol, §ion_kinds); 48 | } 49 | println!(); 50 | 51 | println!("Dynamic symbols:"); 52 | for symbol in file.dynamic_symbols() { 53 | print_symbol(&symbol, §ion_kinds); 54 | } 55 | } 56 | } 57 | 58 | fn print_symbol(symbol: &Symbol<'_, '_>, section_kinds: &HashMap) { 59 | if let SymbolKind::Section | SymbolKind::File = symbol.kind() { 60 | return; 61 | } 62 | 63 | let mut kind = match symbol.section() { 64 | SymbolSection::Undefined => 'U', 65 | SymbolSection::Absolute => 'A', 66 | SymbolSection::Common => 'C', 67 | SymbolSection::Section(index) => match section_kinds.get(&index) { 68 | Some(SectionKind::Text) => 't', 69 | Some(SectionKind::Data) | Some(SectionKind::Tls) | Some(SectionKind::TlsVariables) => { 70 | 'd' 71 | } 72 | Some(SectionKind::ReadOnlyData) | Some(SectionKind::ReadOnlyString) => 'r', 73 | Some(SectionKind::UninitializedData) | Some(SectionKind::UninitializedTls) => 'b', 74 | Some(SectionKind::Common) => 'C', 75 | _ => '?', 76 | }, 77 | _ => '?', 78 | }; 79 | 80 | if symbol.is_global() { 81 | kind = kind.to_ascii_uppercase(); 82 | } 83 | 84 | if symbol.is_undefined() { 85 | print!("{:16} ", ""); 86 | } else { 87 | print!("{:016x} ", symbol.address()); 88 | } 89 | println!( 90 | "{:016x} {} {}", 91 | symbol.size(), 92 | kind, 93 | symbol.name().unwrap_or(""), 94 | ); 95 | } 96 | -------------------------------------------------------------------------------- /crates/examples/src/bin/objcopy.rs: -------------------------------------------------------------------------------- 1 | use object_examples::objcopy; 2 | 3 | use std::{env, fs, process}; 4 | 5 | fn main() { 6 | let mut args = env::args(); 7 | if args.len() != 3 { 8 | eprintln!("Usage: {} ", args.next().unwrap()); 9 | process::exit(1); 10 | } 11 | 12 | args.next(); 13 | let in_file_path = args.next().unwrap(); 14 | let out_file_path = args.next().unwrap(); 15 | 16 | let in_file = match fs::File::open(&in_file_path) { 17 | Ok(file) => file, 18 | Err(err) => { 19 | eprintln!("Failed to open file '{}': {}", in_file_path, err,); 20 | process::exit(1); 21 | } 22 | }; 23 | let in_data = match unsafe { memmap2::Mmap::map(&in_file) } { 24 | Ok(mmap) => mmap, 25 | Err(err) => { 26 | eprintln!("Failed to map file '{}': {}", in_file_path, err,); 27 | process::exit(1); 28 | } 29 | }; 30 | 31 | let out_data = objcopy::copy(&in_data); 32 | 33 | if let Err(err) = fs::write(&out_file_path, out_data) { 34 | eprintln!("Failed to write file '{}': {}", out_file_path, err); 35 | process::exit(1); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /crates/examples/src/bin/objdump.rs: -------------------------------------------------------------------------------- 1 | use object::read::macho::DyldCache; 2 | use object::Endianness; 3 | use object_examples::objdump; 4 | use std::{env, fs, io, process}; 5 | 6 | fn main() { 7 | let mut args = env::args(); 8 | let cmd = args.next().unwrap(); 9 | if args.len() == 0 { 10 | eprintln!("Usage: {} [...]", cmd); 11 | process::exit(1); 12 | } 13 | let file_path = args.next().unwrap(); 14 | let member_names: Vec<_> = args.collect(); 15 | 16 | let file = match fs::File::open(&file_path) { 17 | Ok(file) => file, 18 | Err(err) => { 19 | eprintln!("Failed to open file '{}': {}", file_path, err,); 20 | process::exit(1); 21 | } 22 | }; 23 | let mmap = match unsafe { memmap2::Mmap::map(&file) } { 24 | Ok(mmap) => mmap, 25 | Err(err) => { 26 | eprintln!("Failed to map file '{}': {}", file_path, err,); 27 | process::exit(1); 28 | } 29 | }; 30 | let data = &*mmap; 31 | 32 | let subcache_suffixes = DyldCache::::subcache_suffixes(data).unwrap_or_default(); 33 | let subcache_files = subcache_suffixes 34 | .into_iter() 35 | .map(|suffix| { 36 | let subcache_path = format!("{}{}", file_path, suffix); 37 | let file = match fs::File::open(&subcache_path) { 38 | Ok(file) => file, 39 | Err(err) => { 40 | eprintln!("Failed to open file '{}': {}", subcache_path, err); 41 | process::exit(1); 42 | } 43 | }; 44 | match unsafe { memmap2::Mmap::map(&file) } { 45 | Ok(mmap) => mmap, 46 | Err(err) => { 47 | eprintln!("Failed to map file '{}': {}", subcache_path, err); 48 | process::exit(1); 49 | } 50 | } 51 | }) 52 | .collect::>(); 53 | let extra_file_data: Vec<&[u8]> = subcache_files.iter().map(|f| &**f).collect(); 54 | 55 | let stdout = io::stdout(); 56 | let stderr = io::stderr(); 57 | objdump::print( 58 | &mut stdout.lock(), 59 | &mut stderr.lock(), 60 | data, 61 | &extra_file_data, 62 | member_names, 63 | ) 64 | .unwrap(); 65 | } 66 | -------------------------------------------------------------------------------- /crates/examples/src/bin/objectmap.rs: -------------------------------------------------------------------------------- 1 | use object::Object; 2 | use std::{env, fs, process}; 3 | 4 | fn main() { 5 | let mut args = env::args().skip(1); 6 | if args.len() == 0 { 7 | eprintln!( 8 | "Usage: {} [address] ...", 9 | env::args().next().unwrap() 10 | ); 11 | process::exit(1); 12 | } 13 | 14 | let file_path = args.next().unwrap(); 15 | let file = match fs::File::open(&file_path) { 16 | Ok(file) => file, 17 | Err(err) => { 18 | println!("Failed to open file '{}': {}", file_path, err,); 19 | process::exit(1); 20 | } 21 | }; 22 | let file = match unsafe { memmap2::Mmap::map(&file) } { 23 | Ok(mmap) => mmap, 24 | Err(err) => { 25 | println!("Failed to map file '{}': {}", file_path, err,); 26 | process::exit(1); 27 | } 28 | }; 29 | let file = match object::File::parse(&*file) { 30 | Ok(file) => file, 31 | Err(err) => { 32 | println!("Failed to parse file '{}': {}", file_path, err); 33 | process::exit(1); 34 | } 35 | }; 36 | 37 | let map = file.object_map(); 38 | 39 | if args.len() == 0 { 40 | for symbol in map.symbols() { 41 | print_symbol(symbol, &map); 42 | } 43 | } else { 44 | for arg in args { 45 | let mut arg = &arg[..]; 46 | if arg.starts_with("0x") { 47 | arg = &arg[2..]; 48 | } 49 | let address = u64::from_str_radix(arg, 16).expect("Failed to parse address"); 50 | if let Some(symbol) = map.get(address) { 51 | print_symbol(symbol, &map); 52 | } else { 53 | println!("{:} not found", address); 54 | } 55 | } 56 | } 57 | } 58 | 59 | fn print_symbol(symbol: &object::ObjectMapEntry<'_>, map: &object::ObjectMap<'_>) { 60 | let file = symbol.object(map); 61 | print!( 62 | "{:x} {:x} {} {}", 63 | symbol.address(), 64 | symbol.size(), 65 | String::from_utf8_lossy(symbol.name()), 66 | String::from_utf8_lossy(file.path()), 67 | ); 68 | if let Some(member) = file.member() { 69 | print!("({})", String::from_utf8_lossy(member)); 70 | } 71 | println!(); 72 | } 73 | -------------------------------------------------------------------------------- /crates/examples/src/bin/simple_write.rs: -------------------------------------------------------------------------------- 1 | /// This example demonstrates how to create an object file with a simple main function that 2 | /// calls puts("Hello, world!"). 3 | /// 4 | /// The resulting object file can be linked with a C runtime to create a complete executable: 5 | /// ```sh 6 | /// $ cargo run --features write --bin simple_write 7 | /// $ gcc -o hello hello.o 8 | /// $ ./hello 9 | /// Hello, world! 10 | /// ``` 11 | use object::write::{Object, Relocation, StandardSection, Symbol, SymbolScope, SymbolSection}; 12 | use object::{ 13 | Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationFlags, RelocationKind, 14 | SymbolFlags, SymbolKind, 15 | }; 16 | 17 | fn main() -> Result<(), Box> { 18 | let mut obj = Object::new( 19 | BinaryFormat::native_object(), 20 | Architecture::X86_64, 21 | Endianness::Little, 22 | ); 23 | 24 | // Add a file symbol (STT_FILE or equivalent). 25 | obj.add_file_symbol(b"hello.c".into()); 26 | 27 | // Generate code for the equivalent of this C function: 28 | // int main() { 29 | // puts("Hello, world!"); 30 | // return 0; 31 | // } 32 | let mut main_data = Vec::new(); 33 | // sub $0x28, %rsp 34 | main_data.extend_from_slice(&[0x48, 0x83, 0xec, 0x28]); 35 | // Handle different calling convention on Windows. 36 | if cfg!(target_os = "windows") { 37 | // lea 0x0(%rip), %rcx 38 | main_data.extend_from_slice(&[0x48, 0x8d, 0x0d, 0x00, 0x00, 0x00, 0x00]); 39 | } else { 40 | // lea 0x0(%rip), %rdi 41 | main_data.extend_from_slice(&[0x48, 0x8d, 0x3d, 0x00, 0x00, 0x00, 0x00]); 42 | } 43 | // R_X86_64_PC32 .rodata-0x4 44 | let s_reloc_offset = main_data.len() - 4; 45 | let s_reloc_addend = -4; 46 | let s_reloc_flags = RelocationFlags::Generic { 47 | kind: RelocationKind::Relative, 48 | encoding: RelocationEncoding::Generic, 49 | size: 32, 50 | }; 51 | // call 14 52 | main_data.extend_from_slice(&[0xe8, 0x00, 0x00, 0x00, 0x00]); 53 | // R_X86_64_PLT32 puts-0x4 54 | let puts_reloc_offset = main_data.len() - 4; 55 | let puts_reloc_addend = -4; 56 | let puts_reloc_flags = RelocationFlags::Generic { 57 | kind: RelocationKind::PltRelative, 58 | encoding: RelocationEncoding::X86Branch, 59 | size: 32, 60 | }; 61 | // xor %eax, %eax 62 | main_data.extend_from_slice(&[0x31, 0xc0]); 63 | // add $0x28, %rsp 64 | main_data.extend_from_slice(&[0x48, 0x83, 0xc4, 0x28]); 65 | // ret 66 | main_data.extend_from_slice(&[0xc3]); 67 | 68 | // Add a globally visible symbol for the main function. 69 | let main_symbol = obj.add_symbol(Symbol { 70 | name: b"main".into(), 71 | value: 0, 72 | size: 0, 73 | kind: SymbolKind::Text, 74 | scope: SymbolScope::Linkage, 75 | weak: false, 76 | section: SymbolSection::Undefined, 77 | flags: SymbolFlags::None, 78 | }); 79 | // Add the main function in its own subsection (equivalent to -ffunction-sections). 80 | let main_section = obj.add_subsection(StandardSection::Text, b"main"); 81 | let main_offset = obj.add_symbol_data(main_symbol, main_section, &main_data, 1); 82 | 83 | // Add a read only string constant for the puts argument. 84 | // We don't create a symbol for the constant, but instead refer to it by 85 | // the section symbol and section offset. 86 | let rodata_section = obj.section_id(StandardSection::ReadOnlyData); 87 | let rodata_symbol = obj.section_symbol(rodata_section); 88 | let s_offset = obj.append_section_data(rodata_section, b"Hello, world!\0", 1); 89 | 90 | // Relocation for the string constant. 91 | obj.add_relocation( 92 | main_section, 93 | Relocation { 94 | offset: main_offset + s_reloc_offset as u64, 95 | symbol: rodata_symbol, 96 | addend: s_offset as i64 + s_reloc_addend, 97 | flags: s_reloc_flags, 98 | }, 99 | )?; 100 | 101 | // External symbol for puts. 102 | let puts_symbol = obj.add_symbol(Symbol { 103 | name: b"puts".into(), 104 | value: 0, 105 | size: 0, 106 | kind: SymbolKind::Text, 107 | scope: SymbolScope::Dynamic, 108 | weak: false, 109 | section: SymbolSection::Undefined, 110 | flags: SymbolFlags::None, 111 | }); 112 | 113 | // Relocation for the call to puts. 114 | obj.add_relocation( 115 | main_section, 116 | Relocation { 117 | offset: puts_reloc_offset as u64, 118 | symbol: puts_symbol, 119 | addend: puts_reloc_addend, 120 | flags: puts_reloc_flags, 121 | }, 122 | )?; 123 | 124 | // Finally, write the object file. 125 | let file = std::fs::File::create("hello.o")?; 126 | obj.write_stream(file)?; 127 | Ok(()) 128 | } 129 | -------------------------------------------------------------------------------- /crates/examples/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Style. 2 | #![allow(clippy::nonminimal_bool)] 3 | #![allow(clippy::single_match)] 4 | 5 | #[cfg(all(feature = "read", feature = "write"))] 6 | pub mod objcopy; 7 | 8 | #[cfg(feature = "read")] 9 | pub mod objdump; 10 | 11 | #[cfg(feature = "read")] 12 | pub mod readobj; 13 | -------------------------------------------------------------------------------- /crates/examples/testfiles/archive/thin.a.readobj: -------------------------------------------------------------------------------- 1 | Format: Archive (Gnu) (thin) 2 | 3 | Member: "a.o" 4 | Size: 1320 5 | 6 | Member: "b.o" 7 | Size: 1320 8 | 9 | Member: "c.o" 10 | Size: 1320 11 | 12 | Symbol { 13 | Name: "a_one" 14 | Member: "a.o" 15 | } 16 | Symbol { 17 | Name: "a_two" 18 | Member: "a.o" 19 | } 20 | Symbol { 21 | Name: "b_one" 22 | Member: "b.o" 23 | } 24 | Symbol { 25 | Name: "b_two" 26 | Member: "b.o" 27 | } 28 | Symbol { 29 | Name: "c_one" 30 | Member: "c.o" 31 | } 32 | Symbol { 33 | Name: "c_two" 34 | Member: "c.o" 35 | } 36 | -------------------------------------------------------------------------------- /crates/examples/testfiles/elf/base-aarch64-gnu-properties.o.readobj-elf-note: -------------------------------------------------------------------------------- 1 | Format: ELF 64-bit 2 | SectionHeader { 3 | Index: 8 4 | Name: ".note.gnu.property" (0x52) 5 | Type: SHT_NOTE (0x7) 6 | Flags: 0x2 7 | SHF_ALLOC (0x2) 8 | Address: 0x0 9 | Offset: 0xA8 10 | Size: 0x20 11 | Link: 0 12 | Info: 0 13 | AddressAlign: 0x8 14 | EntrySize: 0x0 15 | Note { 16 | Name: "GNU" (0x4) 17 | Type: NT_GNU_PROPERTY_TYPE_0 (0x5) 18 | Property { 19 | Type: GNU_PROPERTY_AARCH64_FEATURE_1_AND (0xC0000000) 20 | Value: 0x3 21 | GNU_PROPERTY_AARCH64_FEATURE_1_BTI (0x1) 22 | GNU_PROPERTY_AARCH64_FEATURE_1_PAC (0x2) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /crates/examples/testfiles/elf/base-aarch64.o.objdump: -------------------------------------------------------------------------------- 1 | Format: Elf Little-endian 64-bit 2 | Kind: Relocatable 3 | Architecture: Aarch64 4 | Flags: Elf { os_abi: 0, abi_version: 0, e_flags: 0 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | 1: Section { name: ".text", address: 0, size: 20, align: 4, kind: Text, flags: Elf { sh_flags: 6 } } 8 | 2: Section { name: ".rela.text", address: 0, size: 48, align: 8, kind: Metadata, flags: Elf { sh_flags: 40 } } 9 | 3: Section { name: ".data", address: 0, size: 0, align: 1, kind: Data, flags: Elf { sh_flags: 3 } } 10 | 4: Section { name: ".bss", address: 0, size: 0, align: 1, kind: UninitializedData, flags: Elf { sh_flags: 3 } } 11 | 5: Section { name: ".rodata", address: 0, size: d, align: 8, kind: ReadOnlyData, flags: Elf { sh_flags: 2 } } 12 | 6: Section { name: ".comment", address: 0, size: 31, align: 1, kind: OtherString, flags: Elf { sh_flags: 30 } } 13 | 7: Section { name: ".note.GNU-stack", address: 0, size: 0, align: 1, kind: Other, flags: Elf { sh_flags: 0 } } 14 | 8: Section { name: ".symtab", address: 0, size: 120, align: 8, kind: Metadata, flags: Elf { sh_flags: 0 } } 15 | 9: Section { name: ".strtab", address: 0, size: 1a, align: 1, kind: Metadata, flags: Elf { sh_flags: 0 } } 16 | 10: Section { name: ".shstrtab", address: 0, size: 52, align: 1, kind: Metadata, flags: Elf { sh_flags: 0 } } 17 | 18 | Symbols 19 | 1: Symbol { name: "base.c", address: 0, size: 0, kind: File, section: None, scope: Compilation, weak: false, flags: Elf { st_info: 4, st_other: 0 } } 20 | 2: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 21 | 3: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(3)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 22 | 4: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(4)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 23 | 5: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(5)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 24 | 6: Symbol { name: "$d", address: 0, size: 0, kind: Unknown, section: Section(SectionIndex(5)), scope: Compilation, weak: false, flags: Elf { st_info: 0, st_other: 0 } } 25 | 7: Symbol { name: "$x", address: 0, size: 0, kind: Unknown, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: Elf { st_info: 0, st_other: 0 } } 26 | 8: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(7)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 27 | 9: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(6)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 28 | 10: Symbol { name: "main", address: 0, size: 20, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: Elf { st_info: 12, st_other: 0 } } 29 | 11: Symbol { name: "printf", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: Elf { st_info: 10, st_other: 0 } } 30 | 31 | .text relocations 32 | (8, Relocation { kind: Unknown, encoding: Generic, size: 0, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: false, flags: Elf { r_type: 113 } }) 33 | (c, Relocation { kind: Unknown, encoding: Generic, size: 0, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: false, flags: Elf { r_type: 115 } }) 34 | (10, Relocation { kind: PltRelative, encoding: AArch64Call, size: 1a, target: Symbol(SymbolIndex(b)), addend: 0, implicit_addend: false, flags: Elf { r_type: 11b } }) 35 | 36 | Dynamic symbols 37 | 38 | Dynamic relocations 39 | 40 | Symbol map 41 | 0x0 "main" 42 | -------------------------------------------------------------------------------- /crates/examples/testfiles/elf/base-strip.objdump: -------------------------------------------------------------------------------- 1 | Format: Elf Little-endian 64-bit 2 | Kind: Dynamic 3 | Architecture: X86_64 4 | Flags: Elf { os_abi: 0, abi_version: 0, e_flags: 0 } 5 | Relative Address Base: 0 6 | Entry Address: 570 7 | Build ID: [d4, 46, a0, 61, bb, 9a, c2, 7a, b4, 3b, 11, 71, 8f, de, df, 5b, 7f, 3a, f6, f4] 8 | Segment { address: 0, size: 878 } 9 | Segment { address: 200da8, size: 270 } 10 | 11 | Symbols 12 | 13 | Dynamic symbols 14 | 15 | Dynamic relocations 16 | 17 | Symbol map 18 | -------------------------------------------------------------------------------- /crates/examples/testfiles/elf/base-x86_64-gnu-properties.o.readobj-elf-note: -------------------------------------------------------------------------------- 1 | Format: ELF 64-bit 2 | SectionHeader { 3 | Index: 8 4 | Name: ".note.gnu.property" (0x52) 5 | Type: SHT_NOTE (0x7) 6 | Flags: 0x2 7 | SHF_ALLOC (0x2) 8 | Address: 0x0 9 | Offset: 0xA0 10 | Size: 0x20 11 | Link: 0 12 | Info: 0 13 | AddressAlign: 0x8 14 | EntrySize: 0x0 15 | Note { 16 | Name: "GNU" (0x4) 17 | Type: NT_GNU_PROPERTY_TYPE_0 (0x5) 18 | Property { 19 | Type: GNU_PROPERTY_X86_FEATURE_1_AND (0xC0000002) 20 | Value: 0x3 21 | GNU_PROPERTY_X86_FEATURE_1_IBT (0x1) 22 | GNU_PROPERTY_X86_FEATURE_1_SHSTK (0x2) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /crates/examples/testfiles/elf/base.o.objdump: -------------------------------------------------------------------------------- 1 | Format: Elf Little-endian 64-bit 2 | Kind: Relocatable 3 | Architecture: X86_64 4 | Flags: Elf { os_abi: 0, abi_version: 0, e_flags: 0 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | 1: Section { name: ".text", address: 0, size: 1c, align: 1, kind: Text, flags: Elf { sh_flags: 6 } } 8 | 2: Section { name: ".rela.text", address: 0, size: 30, align: 8, kind: Metadata, flags: Elf { sh_flags: 40 } } 9 | 3: Section { name: ".data", address: 0, size: 0, align: 1, kind: Data, flags: Elf { sh_flags: 3 } } 10 | 4: Section { name: ".bss", address: 0, size: 0, align: 1, kind: UninitializedData, flags: Elf { sh_flags: 3 } } 11 | 5: Section { name: ".rodata", address: 0, size: d, align: 1, kind: ReadOnlyData, flags: Elf { sh_flags: 2 } } 12 | 6: Section { name: ".comment", address: 0, size: 2a, align: 1, kind: OtherString, flags: Elf { sh_flags: 30 } } 13 | 7: Section { name: ".note.GNU-stack", address: 0, size: 0, align: 1, kind: Other, flags: Elf { sh_flags: 0 } } 14 | 8: Section { name: ".eh_frame", address: 0, size: 38, align: 8, kind: ReadOnlyData, flags: Elf { sh_flags: 2 } } 15 | 9: Section { name: ".rela.eh_frame", address: 0, size: 18, align: 8, kind: Metadata, flags: Elf { sh_flags: 40 } } 16 | 10: Section { name: ".symtab", address: 0, size: 120, align: 8, kind: Metadata, flags: Elf { sh_flags: 0 } } 17 | 11: Section { name: ".strtab", address: 0, size: 2a, align: 1, kind: Metadata, flags: Elf { sh_flags: 0 } } 18 | 12: Section { name: ".shstrtab", address: 0, size: 61, align: 1, kind: Metadata, flags: Elf { sh_flags: 0 } } 19 | 20 | Symbols 21 | 1: Symbol { name: "base.c", address: 0, size: 0, kind: File, section: None, scope: Compilation, weak: false, flags: Elf { st_info: 4, st_other: 0 } } 22 | 2: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 23 | 3: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(3)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 24 | 4: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(4)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 25 | 5: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(5)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 26 | 6: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(7)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 27 | 7: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(8)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 28 | 8: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(6)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 29 | 9: Symbol { name: "main", address: 0, size: 1c, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: Elf { st_info: 12, st_other: 0 } } 30 | 10: Symbol { name: "_GLOBAL_OFFSET_TABLE_", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: Elf { st_info: 10, st_other: 0 } } 31 | 11: Symbol { name: "printf", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: Elf { st_info: 10, st_other: 0 } } 32 | 33 | .text relocations 34 | (7, Relocation { kind: Relative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: fffffffffffffffc, implicit_addend: false, flags: Elf { r_type: 2 } }) 35 | (11, Relocation { kind: PltRelative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(b)), addend: fffffffffffffffc, implicit_addend: false, flags: Elf { r_type: 4 } }) 36 | 37 | .eh_frame relocations 38 | (20, Relocation { kind: Relative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(2)), addend: 0, implicit_addend: false, flags: Elf { r_type: 2 } }) 39 | 40 | Dynamic symbols 41 | 42 | Dynamic relocations 43 | 44 | Symbol map 45 | 0x0 "main" 46 | -------------------------------------------------------------------------------- /crates/examples/testfiles/elf/comdat.o.objdump-comdat: -------------------------------------------------------------------------------- 1 | Comdat { symbol: SymbolIndex(12), name: "_Z4foo1i", kind: Any } Sections: 7 2 | Comdat { symbol: SymbolIndex(13), name: "_Z4foo2i", kind: Any } Sections: 8 3 | -------------------------------------------------------------------------------- /crates/examples/testfiles/elf/comdat.o.readobj-section: -------------------------------------------------------------------------------- 1 | Format: ELF 64-bit 2 | SectionHeader { 3 | Index: 0 4 | Name: "" (0x0) 5 | Type: SHT_NULL (0x0) 6 | Flags: 0x0 7 | Address: 0x0 8 | Offset: 0x0 9 | Size: 0x0 10 | Link: 0 11 | Info: 0 12 | AddressAlign: 0x0 13 | EntrySize: 0x0 14 | } 15 | SectionHeader { 16 | Index: 1 17 | Name: ".group" (0x77) 18 | Type: SHT_GROUP (0x11) 19 | Flags: 0x0 20 | Address: 0x0 21 | Offset: 0x40 22 | Size: 0x8 23 | Link: 13 24 | Info: 12 25 | AddressAlign: 0x4 26 | EntrySize: 0x4 27 | GroupFlag: GRP_COMDAT (0x1) 28 | GroupSections { 29 | ".text._Z4foo1i" (7) 30 | } 31 | } 32 | SectionHeader { 33 | Index: 2 34 | Name: ".group" (0x77) 35 | Type: SHT_GROUP (0x11) 36 | Flags: 0x0 37 | Address: 0x0 38 | Offset: 0x48 39 | Size: 0x8 40 | Link: 13 41 | Info: 13 42 | AddressAlign: 0x4 43 | EntrySize: 0x4 44 | GroupFlag: GRP_COMDAT (0x1) 45 | GroupSections { 46 | ".text._Z4foo2i" (8) 47 | } 48 | } 49 | SectionHeader { 50 | Index: 3 51 | Name: ".text" (0x20) 52 | Type: SHT_PROGBITS (0x1) 53 | Flags: 0x6 54 | SHF_ALLOC (0x2) 55 | SHF_EXECINSTR (0x4) 56 | Address: 0x0 57 | Offset: 0x50 58 | Size: 0x25 59 | Link: 0 60 | Info: 0 61 | AddressAlign: 0x1 62 | EntrySize: 0x0 63 | } 64 | SectionHeader { 65 | Index: 4 66 | Name: ".rela.text" (0x1B) 67 | Type: SHT_RELA (0x4) 68 | Flags: 0x40 69 | SHF_INFO_LINK (0x40) 70 | Address: 0x0 71 | Offset: 0x348 72 | Size: 0x30 73 | Link: 13 74 | Info: 3 75 | AddressAlign: 0x8 76 | EntrySize: 0x18 77 | } 78 | SectionHeader { 79 | Index: 5 80 | Name: ".data" (0x26) 81 | Type: SHT_PROGBITS (0x1) 82 | Flags: 0x3 83 | SHF_WRITE (0x1) 84 | SHF_ALLOC (0x2) 85 | Address: 0x0 86 | Offset: 0x75 87 | Size: 0x0 88 | Link: 0 89 | Info: 0 90 | AddressAlign: 0x1 91 | EntrySize: 0x0 92 | } 93 | SectionHeader { 94 | Index: 6 95 | Name: ".bss" (0x2C) 96 | Type: SHT_NOBITS (0x8) 97 | Flags: 0x3 98 | SHF_WRITE (0x1) 99 | SHF_ALLOC (0x2) 100 | Address: 0x0 101 | Offset: 0x75 102 | Size: 0x0 103 | Link: 0 104 | Info: 0 105 | AddressAlign: 0x1 106 | EntrySize: 0x0 107 | } 108 | SectionHeader { 109 | Index: 7 110 | Name: ".text._Z4foo1i" (0x31) 111 | Type: SHT_PROGBITS (0x1) 112 | Flags: 0x206 113 | SHF_ALLOC (0x2) 114 | SHF_EXECINSTR (0x4) 115 | SHF_GROUP (0x200) 116 | Address: 0x0 117 | Offset: 0x75 118 | Size: 0x10 119 | Link: 0 120 | Info: 0 121 | AddressAlign: 0x1 122 | EntrySize: 0x0 123 | } 124 | SectionHeader { 125 | Index: 8 126 | Name: ".text._Z4foo2i" (0x40) 127 | Type: SHT_PROGBITS (0x1) 128 | Flags: 0x206 129 | SHF_ALLOC (0x2) 130 | SHF_EXECINSTR (0x4) 131 | SHF_GROUP (0x200) 132 | Address: 0x0 133 | Offset: 0x85 134 | Size: 0xE 135 | Link: 0 136 | Info: 0 137 | AddressAlign: 0x1 138 | EntrySize: 0x0 139 | } 140 | SectionHeader { 141 | Index: 9 142 | Name: ".comment" (0x4F) 143 | Type: SHT_PROGBITS (0x1) 144 | Flags: 0x30 145 | SHF_MERGE (0x10) 146 | SHF_STRINGS (0x20) 147 | Address: 0x0 148 | Offset: 0x93 149 | Size: 0x2A 150 | Link: 0 151 | Info: 0 152 | AddressAlign: 0x1 153 | EntrySize: 0x1 154 | } 155 | SectionHeader { 156 | Index: 10 157 | Name: ".note.GNU-stack" (0x58) 158 | Type: SHT_PROGBITS (0x1) 159 | Flags: 0x0 160 | Address: 0x0 161 | Offset: 0xBD 162 | Size: 0x0 163 | Link: 0 164 | Info: 0 165 | AddressAlign: 0x1 166 | EntrySize: 0x0 167 | } 168 | SectionHeader { 169 | Index: 11 170 | Name: ".eh_frame" (0x6D) 171 | Type: SHT_PROGBITS (0x1) 172 | Flags: 0x2 173 | SHF_ALLOC (0x2) 174 | Address: 0x0 175 | Offset: 0xC0 176 | Size: 0xB8 177 | Link: 0 178 | Info: 0 179 | AddressAlign: 0x8 180 | EntrySize: 0x0 181 | } 182 | SectionHeader { 183 | Index: 12 184 | Name: ".rela.eh_frame" (0x68) 185 | Type: SHT_RELA (0x4) 186 | Flags: 0x40 187 | SHF_INFO_LINK (0x40) 188 | Address: 0x0 189 | Offset: 0x378 190 | Size: 0x78 191 | Link: 13 192 | Info: 11 193 | AddressAlign: 0x8 194 | EntrySize: 0x18 195 | } 196 | SectionHeader { 197 | Index: 13 198 | Name: ".symtab" (0x1) 199 | Type: SHT_SYMTAB (0x2) 200 | Flags: 0x0 201 | Address: 0x0 202 | Offset: 0x178 203 | Size: 0x198 204 | Link: 14 205 | Info: 12 206 | AddressAlign: 0x8 207 | EntrySize: 0x18 208 | } 209 | SectionHeader { 210 | Index: 14 211 | Name: ".strtab" (0x9) 212 | Type: SHT_STRTAB (0x3) 213 | Flags: 0x0 214 | Address: 0x0 215 | Offset: 0x310 216 | Size: 0x34 217 | Link: 0 218 | Info: 0 219 | AddressAlign: 0x1 220 | EntrySize: 0x0 221 | } 222 | SectionHeader { 223 | Index: 15 224 | Name: ".shstrtab" (0x11) 225 | Type: SHT_STRTAB (0x3) 226 | Flags: 0x0 227 | Address: 0x0 228 | Offset: 0x3F0 229 | Size: 0x7E 230 | Link: 0 231 | Info: 0 232 | AddressAlign: 0x1 233 | EntrySize: 0x0 234 | } 235 | -------------------------------------------------------------------------------- /crates/examples/testfiles/elf/symtab_shndx.o.objdump-shndx: -------------------------------------------------------------------------------- 1 | 65530: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(fff9)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 2 | 65531: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(fffa)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 3 | 65532: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(fffb)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 4 | 65533: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(fffc)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 5 | 65534: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(fffd)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 6 | 65535: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(fffe)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 7 | 65536: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(ffff)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 8 | 65537: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(10000)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 9 | 65538: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(10001)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 10 | 65539: Symbol { name: "", address: 0, size: 0, kind: Section, section: Section(SectionIndex(10002)), scope: Compilation, weak: false, flags: Elf { st_info: 3, st_other: 0 } } 11 | -------------------------------------------------------------------------------- /crates/examples/testfiles/macho/base-aarch64-debug.o.objdump: -------------------------------------------------------------------------------- 1 | Format: MachO Little-endian 64-bit 2 | Kind: Relocatable 3 | Architecture: Aarch64 4 | Flags: MachO { flags: 2000 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | Segment { name: "", address: 0, size: 2ca } 8 | 1: Section { segment: "__TEXT", name: "__text", address: 0, size: 34, align: 4, kind: Text, flags: MachO { flags: 80000400 } } 9 | 2: Section { segment: "__TEXT", name: "__cstring", address: 34, size: d, align: 1, kind: ReadOnlyString, flags: MachO { flags: 2 } } 10 | 3: Section { segment: "__DWARF", name: "__debug_abbrev", address: 41, size: 3a, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 11 | 4: Section { segment: "__DWARF", name: "__debug_info", address: 7b, size: 53, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 12 | 5: Section { segment: "__DWARF", name: "__debug_str", address: ce, size: cb, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 13 | 6: Section { segment: "__DWARF", name: "__apple_names", address: 199, size: 3c, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 14 | 7: Section { segment: "__DWARF", name: "__apple_objc", address: 1d5, size: 24, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 15 | 8: Section { segment: "__DWARF", name: "__apple_namespac", address: 1f9, size: 24, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 16 | 9: Section { segment: "__DWARF", name: "__apple_types", address: 21d, size: 47, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 17 | 10: Section { segment: "__LD", name: "__compact_unwind", address: 268, size: 20, align: 8, kind: Unknown, flags: MachO { flags: 2000000 } } 18 | 11: Section { segment: "__DWARF", name: "__debug_line", address: 288, size: 42, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 19 | 20 | Symbols 21 | 0: Symbol { name: "ltmp0", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 22 | 1: Symbol { name: "l_.str", address: 34, size: 0, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 23 | 2: Symbol { name: "ltmp1", address: 34, size: 0, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 24 | 3: Symbol { name: "ltmp2", address: 268, size: 0, kind: Unknown, section: Section(SectionIndex(a)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 25 | 4: Symbol { name: "_main", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: MachO { n_desc: 0 } } 26 | 5: Symbol { name: "_printf", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 0 } } 27 | 28 | __text relocations 29 | (20, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: true, flags: MachO { r_type: 2, r_pcrel: true, r_length: 2 } }) 30 | (1c, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 4, r_pcrel: false, r_length: 2 } }) 31 | (18, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 3, r_pcrel: true, r_length: 2 } }) 32 | 33 | __debug_info relocations 34 | (33, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Section(SectionIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 35 | (26, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Section(SectionIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 36 | 37 | __compact_unwind relocations 38 | (0, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Section(SectionIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 39 | 40 | __debug_line relocations 41 | (2b, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Section(SectionIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 42 | 43 | Dynamic symbols 44 | 45 | Import { library: "", name: "_printf" } 46 | 47 | Export { name: "_main", address: 0 } 48 | 49 | Symbol map 50 | 0x0 "_main" 51 | 0x34 "ltmp1" 52 | 0x268 "ltmp2" 53 | -------------------------------------------------------------------------------- /crates/examples/testfiles/macho/base-aarch64.o.objcopy: -------------------------------------------------------------------------------- 1 | Format: Mach-O 64-bit 2 | MachHeader { 3 | Magic: 0xCFFAEDFE 4 | CpuType: CPU_TYPE_ARM64 (0x100000C) 5 | CpuSubtype: 0x0 6 | CPU_SUBTYPE_ARM64_ALL (0x0) 7 | FileType: MH_OBJECT (0x1) 8 | NumberOfCmds: 4 9 | SizeOfCmds: 0x1B8 10 | Flags: MH_SUBSECTIONS_VIA_SYMBOLS (0x2000) 11 | } 12 | SegmentCommand { 13 | Cmd: LC_SEGMENT_64 (0x19) 14 | CmdSize: 0x138 15 | SegmentName: "" 16 | VmAddress: 0x0 17 | VmSize: 0x68 18 | FileOffset: 0x1D8 19 | FileSize: 0x68 20 | MaxProt: 0x7 21 | VM_PROT_READ (0x1) 22 | VM_PROT_WRITE (0x2) 23 | VM_PROT_EXECUTE (0x4) 24 | InitProt: 0x7 25 | VM_PROT_READ (0x1) 26 | VM_PROT_WRITE (0x2) 27 | VM_PROT_EXECUTE (0x4) 28 | NumberOfSections: 3 29 | Flags: 0x0 30 | Section { 31 | Index: 1 32 | SectionName: "__text" 33 | SegmentName: "__TEXT" 34 | Address: 0x0 35 | Size: 0x34 36 | Offset: 0x1D8 37 | Align: 0x2 38 | RelocationOffset: 0x240 39 | NumberOfRelocations: 0x3 40 | Flags: 0x80000400 41 | S_REGULAR (0x0) 42 | S_ATTR_PURE_INSTRUCTIONS (0x80000000) 43 | S_ATTR_SOME_INSTRUCTIONS (0x400) 44 | RelocationInfo { 45 | Address: 0x20 46 | Extern: yes 47 | Symbol: "_printf" (0x5) 48 | PcRel: yes 49 | Length: 2 50 | Type: ARM64_RELOC_BRANCH26 (0x2) 51 | } 52 | RelocationInfo { 53 | Address: 0x1C 54 | Extern: yes 55 | Symbol: "l_.str" (0x1) 56 | PcRel: no 57 | Length: 2 58 | Type: ARM64_RELOC_PAGEOFF12 (0x4) 59 | } 60 | RelocationInfo { 61 | Address: 0x18 62 | Extern: yes 63 | Symbol: "l_.str" (0x1) 64 | PcRel: yes 65 | Length: 2 66 | Type: ARM64_RELOC_PAGE21 (0x3) 67 | } 68 | } 69 | Section { 70 | Index: 2 71 | SectionName: "__cstring" 72 | SegmentName: "__TEXT" 73 | Address: 0x34 74 | Size: 0xD 75 | Offset: 0x20C 76 | Align: 0x0 77 | RelocationOffset: 0x0 78 | NumberOfRelocations: 0x0 79 | Flags: S_CSTRING_LITERALS (0x2) 80 | } 81 | Section { 82 | Index: 3 83 | SectionName: "__compact_unwind" 84 | SegmentName: "__LD" 85 | Address: 0x48 86 | Size: 0x20 87 | Offset: 0x220 88 | Align: 0x3 89 | RelocationOffset: 0x258 90 | NumberOfRelocations: 0x1 91 | Flags: 0x2000000 92 | S_REGULAR (0x0) 93 | S_ATTR_DEBUG (0x2000000) 94 | RelocationInfo { 95 | Address: 0x0 96 | Extern: no 97 | Section: "__TEXT,__text" (0x1) 98 | PcRel: no 99 | Length: 3 100 | Type: ARM64_RELOC_UNSIGNED (0x0) 101 | } 102 | } 103 | } 104 | BuildVersionCommand { 105 | Cmd: LC_BUILD_VERSION (0x32) 106 | CmdSize: 0x18 107 | Platform: PLATFORM_MACOS (0x1) 108 | MinOs: 0xD0000 109 | Sdk: 0xD0300 110 | NumberOfTools: 0x0 111 | } 112 | SymtabCommand { 113 | Cmd: LC_SYMTAB (0x2) 114 | CmdSize: 0x18 115 | SymbolOffset: 0x260 116 | NumberOfSymbols: 0x6 117 | StringOffset: 0x2C0 118 | StringSize: 0x28 119 | Nlist { 120 | Index: 0 121 | String: "ltmp0" (0x22) 122 | Type: N_SECT (0xE) 123 | Section: "__TEXT,__text" (0x1) 124 | Desc: 0x0 125 | Value: 0x0 126 | } 127 | Nlist { 128 | Index: 1 129 | String: "l_.str" (0x1) 130 | Type: N_SECT (0xE) 131 | Section: "__TEXT,__cstring" (0x2) 132 | Desc: 0x0 133 | Value: 0x34 134 | } 135 | Nlist { 136 | Index: 2 137 | String: "ltmp1" (0x1C) 138 | Type: N_SECT (0xE) 139 | Section: "__TEXT,__cstring" (0x2) 140 | Desc: 0x0 141 | Value: 0x34 142 | } 143 | Nlist { 144 | Index: 3 145 | String: "ltmp2" (0x16) 146 | Type: N_SECT (0xE) 147 | Section: "__LD,__compact_unwind" (0x3) 148 | Desc: 0x0 149 | Value: 0x48 150 | } 151 | Nlist { 152 | Index: 4 153 | String: "_main" (0x8) 154 | Type: 0xF 155 | N_SECT (0xE) 156 | N_EXT (0x1) 157 | Section: "__TEXT,__text" (0x1) 158 | Desc: 0x0 159 | Value: 0x0 160 | } 161 | Nlist { 162 | Index: 5 163 | String: "_printf" (0xE) 164 | Type: 0x1 165 | N_UNDF (0x0) 166 | N_EXT (0x1) 167 | Section: "" (0x0) 168 | Desc: 0x0 169 | REFERENCE_FLAG_UNDEFINED_NON_LAZY (0x0) 170 | Value: 0x0 171 | } 172 | } 173 | DysymtabCommand { 174 | Cmd: LC_DYSYMTAB (0xB) 175 | CmdSize: 0x50 176 | IndexOfLocalSymbols: 0 177 | NumberOfLocalSymbols: 4 178 | IndexOfExternallyDefinedSymbols: 4 179 | NumberOfExternallyDefinedSymbols: 1 180 | IndexOfUndefinedSymbols: 5 181 | NumberOfUndefinedSymbols: 1 182 | TocOffset: 0x0 183 | NumberOfTocEntries: 0 184 | ModuleTableOffset: 0x0 185 | NumberOfModuleTableEntries: 0 186 | ExternalRefSymbolOffset: 0x0 187 | NumberOfExternalRefSymbols: 0 188 | IndirectSymbolOffset: 0x0 189 | NumberOfIndirectSymbols: 0 190 | ExternalRelocationOffset: 0x0 191 | NumberOfExternalRelocations: 0 192 | LocalRelocationOffset: 0x0 193 | NumberOfLocalRelocations: 0 194 | } 195 | -------------------------------------------------------------------------------- /crates/examples/testfiles/macho/base-aarch64.o.objdump: -------------------------------------------------------------------------------- 1 | Format: MachO Little-endian 64-bit 2 | Kind: Relocatable 3 | Architecture: Aarch64 4 | Flags: MachO { flags: 2000 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | Segment { name: "", address: 0, size: 68 } 8 | 1: Section { segment: "__TEXT", name: "__text", address: 0, size: 34, align: 4, kind: Text, flags: MachO { flags: 80000400 } } 9 | 2: Section { segment: "__TEXT", name: "__cstring", address: 34, size: d, align: 1, kind: ReadOnlyString, flags: MachO { flags: 2 } } 10 | 3: Section { segment: "__LD", name: "__compact_unwind", address: 48, size: 20, align: 8, kind: Unknown, flags: MachO { flags: 2000000 } } 11 | 12 | Symbols 13 | 0: Symbol { name: "ltmp0", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 14 | 1: Symbol { name: "l_.str", address: 34, size: 0, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 15 | 2: Symbol { name: "ltmp1", address: 34, size: 0, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 16 | 3: Symbol { name: "ltmp2", address: 48, size: 0, kind: Unknown, section: Section(SectionIndex(3)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 17 | 4: Symbol { name: "_main", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: MachO { n_desc: 0 } } 18 | 5: Symbol { name: "_printf", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 0 } } 19 | 20 | __text relocations 21 | (20, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: true, flags: MachO { r_type: 2, r_pcrel: true, r_length: 2 } }) 22 | (1c, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 4, r_pcrel: false, r_length: 2 } }) 23 | (18, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 3, r_pcrel: true, r_length: 2 } }) 24 | 25 | __compact_unwind relocations 26 | (0, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Section(SectionIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 27 | 28 | Dynamic symbols 29 | 30 | Import { library: "", name: "_printf" } 31 | 32 | Export { name: "_main", address: 0 } 33 | 34 | Symbol map 35 | 0x0 "_main" 36 | 0x34 "ltmp1" 37 | 0x48 "ltmp2" 38 | -------------------------------------------------------------------------------- /crates/examples/testfiles/macho/base-aarch64.objdump: -------------------------------------------------------------------------------- 1 | Format: MachO Little-endian 64-bit 2 | Kind: Executable 3 | Architecture: Aarch64 4 | Flags: MachO { flags: 200085 } 5 | Relative Address Base: 0 6 | Entry Address: 3f68 7 | Mach UUID: [46, dd, c8, b7, f0, 47, 38, 6b, b2, 75, 9a, ec, a4, dc, de, 6f] 8 | Segment { name: "__PAGEZERO", address: 0, size: 100000000 } 9 | Segment { name: "__TEXT", address: 100000000, size: 4000 } 10 | Segment { name: "__DATA_CONST", address: 100004000, size: 4000 } 11 | Segment { name: "__LINKEDIT", address: 100008000, size: 4000 } 12 | 1: Section { segment: "__TEXT", name: "__text", address: 100003f68, size: 34, align: 4, kind: Text, flags: MachO { flags: 80000400 } } 13 | 2: Section { segment: "__TEXT", name: "__stubs", address: 100003f9c, size: c, align: 4, kind: Unknown, flags: MachO { flags: 80000408 } } 14 | 3: Section { segment: "__TEXT", name: "__cstring", address: 100003fa8, size: d, align: 1, kind: ReadOnlyString, flags: MachO { flags: 2 } } 15 | 4: Section { segment: "__TEXT", name: "__unwind_info", address: 100003fb8, size: 48, align: 4, kind: Unknown, flags: MachO { flags: 0 } } 16 | 5: Section { segment: "__DATA_CONST", name: "__got", address: 100004000, size: 8, align: 8, kind: Unknown, flags: MachO { flags: 6 } } 17 | 18 | Symbols 19 | 0: Symbol { name: "__mh_execute_header", address: 100000000, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: MachO { n_desc: 10 } } 20 | 1: Symbol { name: "_main", address: 100003f68, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: MachO { n_desc: 0 } } 21 | 2: Symbol { name: "_printf", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 100 } } 22 | 23 | Dynamic symbols 24 | 25 | Import { library: "/usr/lib/libSystem.B.dylib", name: "_printf" } 26 | 27 | Export { name: "__mh_execute_header", address: 100000000 } 28 | Export { name: "_main", address: 100003f68 } 29 | 30 | Symbol map 31 | 0x100000000 "__mh_execute_header" 32 | 0x100003f68 "_main" 33 | -------------------------------------------------------------------------------- /crates/examples/testfiles/macho/base-x86_64-debug.o.objdump: -------------------------------------------------------------------------------- 1 | Format: MachO Little-endian 64-bit 2 | Kind: Relocatable 3 | Architecture: X86_64 4 | Flags: MachO { flags: 2000 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | Segment { name: "", address: 0, size: 2f6 } 8 | 1: Section { segment: "__TEXT", name: "__text", address: 0, size: 25, align: 10, kind: Text, flags: MachO { flags: 80000400 } } 9 | 2: Section { segment: "__TEXT", name: "__cstring", address: 25, size: d, align: 1, kind: ReadOnlyString, flags: MachO { flags: 2 } } 10 | 3: Section { segment: "__DWARF", name: "__debug_abbrev", address: 32, size: 3a, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 11 | 4: Section { segment: "__DWARF", name: "__debug_info", address: 6c, size: 53, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 12 | 5: Section { segment: "__DWARF", name: "__debug_str", address: bf, size: c8, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 13 | 6: Section { segment: "__DWARF", name: "__apple_names", address: 187, size: 3c, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 14 | 7: Section { segment: "__DWARF", name: "__apple_objc", address: 1c3, size: 24, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 15 | 8: Section { segment: "__DWARF", name: "__apple_namespac", address: 1e7, size: 24, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 16 | 9: Section { segment: "__DWARF", name: "__apple_types", address: 20b, size: 47, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 17 | 10: Section { segment: "__LD", name: "__compact_unwind", address: 258, size: 20, align: 8, kind: Unknown, flags: MachO { flags: 2000000 } } 18 | 11: Section { segment: "__TEXT", name: "__eh_frame", address: 278, size: 40, align: 8, kind: ReadOnlyData, flags: MachO { flags: 6800000b } } 19 | 12: Section { segment: "__DWARF", name: "__debug_line", address: 2b8, size: 3e, align: 1, kind: Debug, flags: MachO { flags: 2000000 } } 20 | 21 | Symbols 22 | 0: Symbol { name: "_main", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: MachO { n_desc: 0 } } 23 | 1: Symbol { name: "_printf", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 0 } } 24 | 25 | __text relocations 26 | (19, Relocation { kind: Relative, encoding: X86Branch, size: 20, target: Symbol(SymbolIndex(1)), addend: fffffffffffffffc, implicit_addend: true, flags: MachO { r_type: 2, r_pcrel: true, r_length: 2 } }) 27 | (12, Relocation { kind: Relative, encoding: X86RipRelative, size: 20, target: Section(SectionIndex(2)), addend: fffffffffffffffc, implicit_addend: true, flags: MachO { r_type: 1, r_pcrel: true, r_length: 2 } }) 28 | 29 | __debug_info relocations 30 | (33, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Section(SectionIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 31 | (26, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Section(SectionIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 32 | 33 | __compact_unwind relocations 34 | (0, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Section(SectionIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 35 | 36 | __debug_line relocations 37 | (2b, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Section(SectionIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 38 | 39 | Dynamic symbols 40 | 41 | Import { library: "", name: "_printf" } 42 | 43 | Export { name: "_main", address: 0 } 44 | 45 | Symbol map 46 | 0x0 "_main" 47 | -------------------------------------------------------------------------------- /crates/examples/testfiles/macho/base-x86_64.o.objcopy: -------------------------------------------------------------------------------- 1 | Format: Mach-O 64-bit 2 | MachHeader { 3 | Magic: 0xCFFAEDFE 4 | CpuType: CPU_TYPE_X86_64 (0x1000007) 5 | CpuSubtype: 0x3 6 | CPU_SUBTYPE_X86_64_ALL (0x3) 7 | FileType: MH_OBJECT (0x1) 8 | NumberOfCmds: 4 9 | SizeOfCmds: 0x208 10 | Flags: MH_SUBSECTIONS_VIA_SYMBOLS (0x2000) 11 | } 12 | SegmentCommand { 13 | Cmd: LC_SEGMENT_64 (0x19) 14 | CmdSize: 0x188 15 | SegmentName: "" 16 | VmAddress: 0x0 17 | VmSize: 0x98 18 | FileOffset: 0x228 19 | FileSize: 0x98 20 | MaxProt: 0x7 21 | VM_PROT_READ (0x1) 22 | VM_PROT_WRITE (0x2) 23 | VM_PROT_EXECUTE (0x4) 24 | InitProt: 0x7 25 | VM_PROT_READ (0x1) 26 | VM_PROT_WRITE (0x2) 27 | VM_PROT_EXECUTE (0x4) 28 | NumberOfSections: 4 29 | Flags: 0x0 30 | Section { 31 | Index: 1 32 | SectionName: "__text" 33 | SegmentName: "__TEXT" 34 | Address: 0x0 35 | Size: 0x25 36 | Offset: 0x228 37 | Align: 0x4 38 | RelocationOffset: 0x2C0 39 | NumberOfRelocations: 0x2 40 | Flags: 0x80000400 41 | S_REGULAR (0x0) 42 | S_ATTR_PURE_INSTRUCTIONS (0x80000000) 43 | S_ATTR_SOME_INSTRUCTIONS (0x400) 44 | RelocationInfo { 45 | Address: 0x19 46 | Extern: yes 47 | Symbol: "_printf" (0x1) 48 | PcRel: yes 49 | Length: 2 50 | Type: X86_64_RELOC_BRANCH (0x2) 51 | } 52 | RelocationInfo { 53 | Address: 0x12 54 | Extern: no 55 | Section: "__TEXT,__cstring" (0x2) 56 | PcRel: yes 57 | Length: 2 58 | Type: X86_64_RELOC_SIGNED (0x1) 59 | } 60 | } 61 | Section { 62 | Index: 2 63 | SectionName: "__cstring" 64 | SegmentName: "__TEXT" 65 | Address: 0x25 66 | Size: 0xD 67 | Offset: 0x24D 68 | Align: 0x0 69 | RelocationOffset: 0x0 70 | NumberOfRelocations: 0x0 71 | Flags: S_CSTRING_LITERALS (0x2) 72 | } 73 | Section { 74 | Index: 3 75 | SectionName: "__compact_unwind" 76 | SegmentName: "__LD" 77 | Address: 0x38 78 | Size: 0x20 79 | Offset: 0x260 80 | Align: 0x3 81 | RelocationOffset: 0x2D0 82 | NumberOfRelocations: 0x1 83 | Flags: 0x2000000 84 | S_REGULAR (0x0) 85 | S_ATTR_DEBUG (0x2000000) 86 | RelocationInfo { 87 | Address: 0x0 88 | Extern: no 89 | Section: "__TEXT,__text" (0x1) 90 | PcRel: no 91 | Length: 3 92 | Type: X86_64_RELOC_UNSIGNED (0x0) 93 | } 94 | } 95 | Section { 96 | Index: 4 97 | SectionName: "__eh_frame" 98 | SegmentName: "__TEXT" 99 | Address: 0x58 100 | Size: 0x40 101 | Offset: 0x280 102 | Align: 0x3 103 | RelocationOffset: 0x0 104 | NumberOfRelocations: 0x0 105 | Flags: 0x6800000B 106 | S_COALESCED (0xB) 107 | S_ATTR_NO_TOC (0x40000000) 108 | S_ATTR_STRIP_STATIC_SYMS (0x20000000) 109 | S_ATTR_LIVE_SUPPORT (0x8000000) 110 | } 111 | } 112 | BuildVersionCommand { 113 | Cmd: LC_BUILD_VERSION (0x32) 114 | CmdSize: 0x18 115 | Platform: PLATFORM_MACOS (0x1) 116 | MinOs: 0xC0000 117 | Sdk: 0xD0100 118 | NumberOfTools: 0x0 119 | } 120 | SymtabCommand { 121 | Cmd: LC_SYMTAB (0x2) 122 | CmdSize: 0x18 123 | SymbolOffset: 0x2D8 124 | NumberOfSymbols: 0x2 125 | StringOffset: 0x2F8 126 | StringSize: 0x10 127 | Nlist { 128 | Index: 0 129 | String: "_main" (0x1) 130 | Type: 0xF 131 | N_SECT (0xE) 132 | N_EXT (0x1) 133 | Section: "__TEXT,__text" (0x1) 134 | Desc: 0x0 135 | Value: 0x0 136 | } 137 | Nlist { 138 | Index: 1 139 | String: "_printf" (0x7) 140 | Type: 0x1 141 | N_UNDF (0x0) 142 | N_EXT (0x1) 143 | Section: "" (0x0) 144 | Desc: 0x0 145 | REFERENCE_FLAG_UNDEFINED_NON_LAZY (0x0) 146 | Value: 0x0 147 | } 148 | } 149 | DysymtabCommand { 150 | Cmd: LC_DYSYMTAB (0xB) 151 | CmdSize: 0x50 152 | IndexOfLocalSymbols: 0 153 | NumberOfLocalSymbols: 0 154 | IndexOfExternallyDefinedSymbols: 0 155 | NumberOfExternallyDefinedSymbols: 1 156 | IndexOfUndefinedSymbols: 1 157 | NumberOfUndefinedSymbols: 1 158 | TocOffset: 0x0 159 | NumberOfTocEntries: 0 160 | ModuleTableOffset: 0x0 161 | NumberOfModuleTableEntries: 0 162 | ExternalRefSymbolOffset: 0x0 163 | NumberOfExternalRefSymbols: 0 164 | IndirectSymbolOffset: 0x0 165 | NumberOfIndirectSymbols: 0 166 | ExternalRelocationOffset: 0x0 167 | NumberOfExternalRelocations: 0 168 | LocalRelocationOffset: 0x0 169 | NumberOfLocalRelocations: 0 170 | } 171 | -------------------------------------------------------------------------------- /crates/examples/testfiles/macho/base-x86_64.o.objdump: -------------------------------------------------------------------------------- 1 | Format: MachO Little-endian 64-bit 2 | Kind: Relocatable 3 | Architecture: X86_64 4 | Flags: MachO { flags: 2000 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | Segment { name: "", address: 0, size: 98 } 8 | 1: Section { segment: "__TEXT", name: "__text", address: 0, size: 25, align: 10, kind: Text, flags: MachO { flags: 80000400 } } 9 | 2: Section { segment: "__TEXT", name: "__cstring", address: 25, size: d, align: 1, kind: ReadOnlyString, flags: MachO { flags: 2 } } 10 | 3: Section { segment: "__LD", name: "__compact_unwind", address: 38, size: 20, align: 8, kind: Unknown, flags: MachO { flags: 2000000 } } 11 | 4: Section { segment: "__TEXT", name: "__eh_frame", address: 58, size: 40, align: 8, kind: ReadOnlyData, flags: MachO { flags: 6800000b } } 12 | 13 | Symbols 14 | 0: Symbol { name: "_main", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: MachO { n_desc: 0 } } 15 | 1: Symbol { name: "_printf", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 0 } } 16 | 17 | __text relocations 18 | (19, Relocation { kind: Relative, encoding: X86Branch, size: 20, target: Symbol(SymbolIndex(1)), addend: fffffffffffffffc, implicit_addend: true, flags: MachO { r_type: 2, r_pcrel: true, r_length: 2 } }) 19 | (12, Relocation { kind: Relative, encoding: X86RipRelative, size: 20, target: Section(SectionIndex(2)), addend: fffffffffffffffc, implicit_addend: true, flags: MachO { r_type: 1, r_pcrel: true, r_length: 2 } }) 20 | 21 | __compact_unwind relocations 22 | (0, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Section(SectionIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 23 | 24 | Dynamic symbols 25 | 26 | Import { library: "", name: "_printf" } 27 | 28 | Export { name: "_main", address: 0 } 29 | 30 | Symbol map 31 | 0x0 "_main" 32 | -------------------------------------------------------------------------------- /crates/examples/testfiles/macho/base-x86_64.o.readobj: -------------------------------------------------------------------------------- 1 | Format: Mach-O 64-bit 2 | MachHeader { 3 | Magic: 0xCFFAEDFE 4 | CpuType: CPU_TYPE_X86_64 (0x1000007) 5 | CpuSubtype: 0x3 6 | CPU_SUBTYPE_X86_64_ALL (0x3) 7 | FileType: MH_OBJECT (0x1) 8 | NumberOfCmds: 4 9 | SizeOfCmds: 0x208 10 | Flags: MH_SUBSECTIONS_VIA_SYMBOLS (0x2000) 11 | } 12 | SegmentCommand { 13 | Cmd: LC_SEGMENT_64 (0x19) 14 | CmdSize: 0x188 15 | SegmentName: "" 16 | VmAddress: 0x0 17 | VmSize: 0x98 18 | FileOffset: 0x228 19 | FileSize: 0x98 20 | MaxProt: 0x7 21 | VM_PROT_READ (0x1) 22 | VM_PROT_WRITE (0x2) 23 | VM_PROT_EXECUTE (0x4) 24 | InitProt: 0x7 25 | VM_PROT_READ (0x1) 26 | VM_PROT_WRITE (0x2) 27 | VM_PROT_EXECUTE (0x4) 28 | NumberOfSections: 4 29 | Flags: 0x0 30 | Section { 31 | Index: 1 32 | SectionName: "__text" 33 | SegmentName: "__TEXT" 34 | Address: 0x0 35 | Size: 0x25 36 | Offset: 0x228 37 | Align: 0x4 38 | RelocationOffset: 0x2C0 39 | NumberOfRelocations: 0x2 40 | Flags: 0x80000400 41 | S_REGULAR (0x0) 42 | S_ATTR_PURE_INSTRUCTIONS (0x80000000) 43 | S_ATTR_SOME_INSTRUCTIONS (0x400) 44 | RelocationInfo { 45 | Address: 0x19 46 | Extern: yes 47 | Symbol: "_printf" (0x1) 48 | PcRel: yes 49 | Length: 2 50 | Type: X86_64_RELOC_BRANCH (0x2) 51 | } 52 | RelocationInfo { 53 | Address: 0x12 54 | Extern: no 55 | Section: "__TEXT,__cstring" (0x2) 56 | PcRel: yes 57 | Length: 2 58 | Type: X86_64_RELOC_SIGNED (0x1) 59 | } 60 | } 61 | Section { 62 | Index: 2 63 | SectionName: "__cstring" 64 | SegmentName: "__TEXT" 65 | Address: 0x25 66 | Size: 0xD 67 | Offset: 0x24D 68 | Align: 0x0 69 | RelocationOffset: 0x0 70 | NumberOfRelocations: 0x0 71 | Flags: S_CSTRING_LITERALS (0x2) 72 | } 73 | Section { 74 | Index: 3 75 | SectionName: "__compact_unwind" 76 | SegmentName: "__LD" 77 | Address: 0x38 78 | Size: 0x20 79 | Offset: 0x260 80 | Align: 0x3 81 | RelocationOffset: 0x2D0 82 | NumberOfRelocations: 0x1 83 | Flags: 0x2000000 84 | S_REGULAR (0x0) 85 | S_ATTR_DEBUG (0x2000000) 86 | RelocationInfo { 87 | Address: 0x0 88 | Extern: no 89 | Section: "__TEXT,__text" (0x1) 90 | PcRel: no 91 | Length: 3 92 | Type: X86_64_RELOC_UNSIGNED (0x0) 93 | } 94 | } 95 | Section { 96 | Index: 4 97 | SectionName: "__eh_frame" 98 | SegmentName: "__TEXT" 99 | Address: 0x58 100 | Size: 0x40 101 | Offset: 0x280 102 | Align: 0x3 103 | RelocationOffset: 0x0 104 | NumberOfRelocations: 0x0 105 | Flags: 0x6800000B 106 | S_COALESCED (0xB) 107 | S_ATTR_NO_TOC (0x40000000) 108 | S_ATTR_STRIP_STATIC_SYMS (0x20000000) 109 | S_ATTR_LIVE_SUPPORT (0x8000000) 110 | } 111 | } 112 | BuildVersionCommand { 113 | Cmd: LC_BUILD_VERSION (0x32) 114 | CmdSize: 0x18 115 | Platform: PLATFORM_MACOS (0x1) 116 | MinOs: 0xC0000 117 | Sdk: 0xD0100 118 | NumberOfTools: 0x0 119 | } 120 | SymtabCommand { 121 | Cmd: LC_SYMTAB (0x2) 122 | CmdSize: 0x18 123 | SymbolOffset: 0x2D8 124 | NumberOfSymbols: 0x2 125 | StringOffset: 0x2F8 126 | StringSize: 0x10 127 | Nlist { 128 | Index: 0 129 | String: "_main" (0x1) 130 | Type: 0xF 131 | N_SECT (0xE) 132 | N_EXT (0x1) 133 | Section: "__TEXT,__text" (0x1) 134 | Desc: 0x0 135 | Value: 0x0 136 | } 137 | Nlist { 138 | Index: 1 139 | String: "_printf" (0x7) 140 | Type: 0x1 141 | N_UNDF (0x0) 142 | N_EXT (0x1) 143 | Section: "" (0x0) 144 | Desc: 0x0 145 | REFERENCE_FLAG_UNDEFINED_NON_LAZY (0x0) 146 | Value: 0x0 147 | } 148 | } 149 | DysymtabCommand { 150 | Cmd: LC_DYSYMTAB (0xB) 151 | CmdSize: 0x50 152 | IndexOfLocalSymbols: 0 153 | NumberOfLocalSymbols: 0 154 | IndexOfExternallyDefinedSymbols: 0 155 | NumberOfExternallyDefinedSymbols: 1 156 | IndexOfUndefinedSymbols: 1 157 | NumberOfUndefinedSymbols: 1 158 | TocOffset: 0x0 159 | NumberOfTocEntries: 0 160 | ModuleTableOffset: 0x0 161 | NumberOfModuleTableEntries: 0 162 | ExternalRefSymbolOffset: 0x0 163 | NumberOfExternalRefSymbols: 0 164 | IndirectSymbolOffset: 0x0 165 | NumberOfIndirectSymbols: 0 166 | ExternalRelocationOffset: 0x0 167 | NumberOfExternalRelocations: 0 168 | LocalRelocationOffset: 0x0 169 | NumberOfLocalRelocations: 0 170 | } 171 | -------------------------------------------------------------------------------- /crates/examples/testfiles/macho/base-x86_64.objdump: -------------------------------------------------------------------------------- 1 | Format: MachO Little-endian 64-bit 2 | Kind: Executable 3 | Architecture: X86_64 4 | Flags: MachO { flags: 200085 } 5 | Relative Address Base: 0 6 | Entry Address: 3f60 7 | Mach UUID: [ab, a4, a9, 90, 5c, 28, 30, b4, 84, b3, 89, 8e, 5d, 67, 4, be] 8 | Segment { name: "__PAGEZERO", address: 0, size: 100000000 } 9 | Segment { name: "__TEXT", address: 100000000, size: 4000 } 10 | Segment { name: "__DATA_CONST", address: 100004000, size: 4000 } 11 | Segment { name: "__DATA", address: 100008000, size: 4000 } 12 | Segment { name: "__LINKEDIT", address: 10000c000, size: 4000 } 13 | 1: Section { segment: "__TEXT", name: "__text", address: 100003f60, size: 25, align: 10, kind: Text, flags: MachO { flags: 80000400 } } 14 | 2: Section { segment: "__TEXT", name: "__stubs", address: 100003f86, size: 6, align: 2, kind: Unknown, flags: MachO { flags: 80000408 } } 15 | 3: Section { segment: "__TEXT", name: "__stub_helper", address: 100003f8c, size: 1a, align: 4, kind: Unknown, flags: MachO { flags: 80000400 } } 16 | 4: Section { segment: "__TEXT", name: "__cstring", address: 100003fa6, size: d, align: 1, kind: ReadOnlyString, flags: MachO { flags: 2 } } 17 | 5: Section { segment: "__TEXT", name: "__unwind_info", address: 100003fb4, size: 48, align: 4, kind: Unknown, flags: MachO { flags: 0 } } 18 | 6: Section { segment: "__DATA_CONST", name: "__got", address: 100004000, size: 8, align: 8, kind: Unknown, flags: MachO { flags: 6 } } 19 | 7: Section { segment: "__DATA", name: "__la_symbol_ptr", address: 100008000, size: 8, align: 8, kind: Unknown, flags: MachO { flags: 7 } } 20 | 8: Section { segment: "__DATA", name: "__data", address: 100008008, size: 8, align: 8, kind: Data, flags: MachO { flags: 0 } } 21 | 22 | Symbols 23 | 0: Symbol { name: "__dyld_private", address: 100008008, size: 0, kind: Data, section: Section(SectionIndex(8)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 24 | 1: Symbol { name: "__mh_execute_header", address: 100000000, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: MachO { n_desc: 10 } } 25 | 2: Symbol { name: "_main", address: 100003f60, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: MachO { n_desc: 0 } } 26 | 3: Symbol { name: "_printf", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 100 } } 27 | 4: Symbol { name: "dyld_stub_binder", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 100 } } 28 | 29 | Dynamic symbols 30 | 31 | Import { library: "/usr/lib/libSystem.B.dylib", name: "_printf" } 32 | Import { library: "/usr/lib/libSystem.B.dylib", name: "dyld_stub_binder" } 33 | 34 | Export { name: "__mh_execute_header", address: 100000000 } 35 | Export { name: "_main", address: 100003f60 } 36 | 37 | Symbol map 38 | 0x100000000 "__mh_execute_header" 39 | 0x100003f60 "_main" 40 | 0x100008008 "__dyld_private" 41 | -------------------------------------------------------------------------------- /crates/examples/testfiles/macho/reloc-aarch64.o.objdump: -------------------------------------------------------------------------------- 1 | Format: MachO Little-endian 64-bit 2 | Kind: Relocatable 3 | Architecture: Aarch64 4 | Flags: MachO { flags: 2000 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | Segment { name: "", address: 0, size: 48 } 8 | 1: Section { segment: "__TEXT", name: "__text", address: 0, size: 28, align: 1, kind: Text, flags: MachO { flags: 80000400 } } 9 | 2: Section { segment: "__DATA", name: "__data", address: 28, size: 20, align: 1, kind: Data, flags: MachO { flags: 0 } } 10 | 11 | Symbols 12 | 0: Symbol { name: "ltmp0", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 13 | 1: Symbol { name: "ltmp1", address: 28, size: 0, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 14 | 2: Symbol { name: "_data", address: 28, size: 0, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 15 | 3: Symbol { name: "_g0", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 0 } } 16 | 4: Symbol { name: "_g1", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 0 } } 17 | 18 | __text relocations 19 | (24, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 9, r_pcrel: false, r_length: 2 } }) 20 | (20, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 8, r_pcrel: true, r_length: 2 } }) 21 | (1c, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 6, r_pcrel: false, r_length: 2 } }) 22 | (18, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 5, r_pcrel: true, r_length: 2 } }) 23 | (14, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 14, implicit_addend: false, flags: MachO { r_type: 4, r_pcrel: false, r_length: 2 } }) 24 | (10, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 14, implicit_addend: false, flags: MachO { r_type: 3, r_pcrel: true, r_length: 2 } }) 25 | (c, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 4, r_pcrel: false, r_length: 2 } }) 26 | (8, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 3, r_pcrel: true, r_length: 2 } }) 27 | (4, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 14, implicit_addend: false, flags: MachO { r_type: 2, r_pcrel: true, r_length: 2 } }) 28 | (0, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 2, r_pcrel: true, r_length: 2 } }) 29 | 30 | __data relocations 31 | (1c, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 7, r_pcrel: true, r_length: 2 } }) 32 | (14, Relocation { kind: Unknown, encoding: Generic, size: 40, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 7, r_pcrel: false, r_length: 3 } }) 33 | (10, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(4)), addend: 0, implicit_addend: true, flags: MachO { r_type: 1, r_pcrel: false, r_length: 2 } }) 34 | (10, Relocation { kind: Absolute, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 2 } }) 35 | (8, Relocation { kind: Unknown, encoding: Generic, size: 40, target: Symbol(SymbolIndex(4)), addend: 0, implicit_addend: true, flags: MachO { r_type: 1, r_pcrel: false, r_length: 3 } }) 36 | (8, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 37 | (0, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 38 | 39 | Dynamic symbols 40 | 41 | Import { library: "", name: "_g0" } 42 | Import { library: "", name: "_g1" } 43 | 44 | Symbol map 45 | 0x0 "ltmp0" 46 | 0x28 "_data" 47 | -------------------------------------------------------------------------------- /crates/examples/testfiles/macho/reloc-arm.o.objdump: -------------------------------------------------------------------------------- 1 | Format: MachO Little-endian 32-bit 2 | Kind: Relocatable 3 | Architecture: Arm 4 | Flags: MachO { flags: 2000 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | Segment { name: "", address: 0, size: 3c } 8 | 1: Section { segment: "__TEXT", name: "__text", address: 0, size: 28, align: 4, kind: Text, flags: MachO { flags: 80000400 } } 9 | 2: Section { segment: "__DATA", name: "__data", address: 28, size: 14, align: 1, kind: Data, flags: MachO { flags: 0 } } 10 | 11 | Symbols 12 | 0: Symbol { name: "_g1", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 13 | 1: Symbol { name: "_g3", address: 14, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 14 | 2: Symbol { name: "_g2", address: 14, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: MachO { n_desc: 0 } } 15 | 3: Symbol { name: "_g0", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 0 } } 16 | 17 | __text relocations 18 | (24, Relocation { kind: Unknown, encoding: Generic, size: 40, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 8, r_pcrel: false, r_length: 3 } }) 19 | (14, Relocation { kind: Unknown, encoding: Generic, size: 40, target: Section(SectionIndex(ffffff)), addend: 0, implicit_addend: true, flags: MachO { r_type: 1, r_pcrel: false, r_length: 3 } }) 20 | (20, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 8, r_pcrel: false, r_length: 2 } }) 21 | (0, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Section(SectionIndex(ffffff)), addend: 0, implicit_addend: true, flags: MachO { r_type: 1, r_pcrel: false, r_length: 2 } }) 22 | (18, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Section(SectionIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 6, r_pcrel: true, r_length: 2 } }) 23 | (14, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 6, r_pcrel: true, r_length: 2 } }) 24 | (10, Relocation { kind: Unknown, encoding: Generic, size: 10, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 8, r_pcrel: false, r_length: 1 } }) 25 | (14, Relocation { kind: Unknown, encoding: Generic, size: 10, target: Section(SectionIndex(ffffff)), addend: 0, implicit_addend: true, flags: MachO { r_type: 1, r_pcrel: false, r_length: 1 } }) 26 | (c, Relocation { kind: Unknown, encoding: Generic, size: 8, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 8, r_pcrel: false, r_length: 0 } }) 27 | (0, Relocation { kind: Unknown, encoding: Generic, size: 8, target: Section(SectionIndex(ffffff)), addend: 0, implicit_addend: true, flags: MachO { r_type: 1, r_pcrel: false, r_length: 0 } }) 28 | (4, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(2)), addend: 0, implicit_addend: true, flags: MachO { r_type: 5, r_pcrel: true, r_length: 2 } }) 29 | (0, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 5, r_pcrel: true, r_length: 2 } }) 30 | 31 | __data relocations 32 | (4, Relocation { kind: Absolute, encoding: Generic, size: 20, target: Section(SectionIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 2 } }) 33 | (0, Relocation { kind: Absolute, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 2 } }) 34 | 35 | Dynamic symbols 36 | 37 | Import { library: "", name: "_g0" } 38 | 39 | Export { name: "_g2", address: 14 } 40 | 41 | Symbol map 42 | 0x0 "_g1" 43 | 0x14 "_g2" 44 | -------------------------------------------------------------------------------- /crates/examples/testfiles/macho/reloc-i386.o.objdump: -------------------------------------------------------------------------------- 1 | Format: MachO Little-endian 32-bit 2 | Kind: Relocatable 3 | Architecture: I386 4 | Flags: MachO { flags: 2000 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | Segment { name: "", address: 0, size: 25 } 8 | 1: Section { segment: "__TEXT", name: "__text", address: 0, size: 11, align: 4, kind: Text, flags: MachO { flags: 80000400 } } 9 | 2: Section { segment: "__DATA", name: "__data", address: 11, size: 14, align: 1, kind: Data, flags: MachO { flags: 0 } } 10 | 11 | Symbols 12 | 0: Symbol { name: "_g1", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 13 | 1: Symbol { name: "_g3", address: 10, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 14 | 2: Symbol { name: "_g2", address: 10, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: MachO { n_desc: 0 } } 15 | 3: Symbol { name: "_g0", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: MachO { n_desc: 0 } } 16 | 17 | __text relocations 18 | (6, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Section(SectionIndex(1)), addend: fffffffffffffffc, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: true, r_length: 2 } }) 19 | (1, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: fffffffffffffffc, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: true, r_length: 2 } }) 20 | 21 | __data relocations 22 | (4, Relocation { kind: Absolute, encoding: Generic, size: 20, target: Section(SectionIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 2 } }) 23 | (0, Relocation { kind: Absolute, encoding: Generic, size: 20, target: Symbol(SymbolIndex(3)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 2 } }) 24 | 25 | Dynamic symbols 26 | 27 | Import { library: "", name: "_g0" } 28 | 29 | Export { name: "_g2", address: 10 } 30 | 31 | Symbol map 32 | 0x0 "_g1" 33 | 0x10 "_g2" 34 | -------------------------------------------------------------------------------- /crates/examples/testfiles/macho/reloc-x86_64.o.objdump: -------------------------------------------------------------------------------- 1 | Format: MachO Little-endian 64-bit 2 | Kind: Relocatable 3 | Architecture: X86_64 4 | Flags: MachO { flags: 0 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | Segment { name: "", address: 0, size: 6b } 8 | 1: Section { segment: "__TEXT", name: "__text", address: 0, size: 53, align: 1, kind: Text, flags: MachO { flags: 80000400 } } 9 | 2: Section { segment: "__DATA", name: "__data", address: 53, size: 18, align: 1, kind: Data, flags: MachO { flags: 0 } } 10 | 11 | Symbols 12 | 0: Symbol { name: "_g1", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 13 | 1: Symbol { name: "_g2", address: 5, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: MachO { n_desc: 0 } } 14 | 15 | __text relocations 16 | (4f, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(0)), addend: fffffffffffffffc, implicit_addend: true, flags: MachO { r_type: 9, r_pcrel: true, r_length: 2 } }) 17 | (48, Relocation { kind: GotRelative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(0)), addend: fffffffffffffffc, implicit_addend: true, flags: MachO { r_type: 4, r_pcrel: true, r_length: 2 } }) 18 | (42, Relocation { kind: GotRelative, encoding: X86RipRelativeMovq, size: 20, target: Symbol(SymbolIndex(0)), addend: fffffffffffffffc, implicit_addend: true, flags: MachO { r_type: 3, r_pcrel: true, r_length: 2 } }) 19 | (37, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Section(SectionIndex(2)), addend: fffffffffffffff8, implicit_addend: true, flags: MachO { r_type: 8, r_pcrel: true, r_length: 2 } }) 20 | (2f, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Section(SectionIndex(2)), addend: fffffffffffffffa, implicit_addend: true, flags: MachO { r_type: 7, r_pcrel: true, r_length: 2 } }) 21 | (27, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Section(SectionIndex(2)), addend: fffffffffffffffb, implicit_addend: true, flags: MachO { r_type: 6, r_pcrel: true, r_length: 2 } }) 22 | (1d, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(0)), addend: fffffffffffffff8, implicit_addend: true, flags: MachO { r_type: 8, r_pcrel: true, r_length: 2 } }) 23 | (15, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(0)), addend: fffffffffffffffa, implicit_addend: true, flags: MachO { r_type: 7, r_pcrel: true, r_length: 2 } }) 24 | (d, Relocation { kind: Unknown, encoding: Generic, size: 20, target: Symbol(SymbolIndex(0)), addend: fffffffffffffffb, implicit_addend: true, flags: MachO { r_type: 6, r_pcrel: true, r_length: 2 } }) 25 | (7, Relocation { kind: Relative, encoding: X86RipRelative, size: 20, target: Symbol(SymbolIndex(0)), addend: fffffffffffffffc, implicit_addend: true, flags: MachO { r_type: 1, r_pcrel: true, r_length: 2 } }) 26 | (1, Relocation { kind: Relative, encoding: X86Branch, size: 20, target: Symbol(SymbolIndex(1)), addend: fffffffffffffffc, implicit_addend: true, flags: MachO { r_type: 2, r_pcrel: true, r_length: 2 } }) 27 | 28 | __data relocations 29 | (10, Relocation { kind: Unknown, encoding: Generic, size: 40, target: Symbol(SymbolIndex(1)), addend: 0, implicit_addend: true, flags: MachO { r_type: 5, r_pcrel: false, r_length: 3 } }) 30 | (10, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Symbol(SymbolIndex(0)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 31 | (8, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Section(SectionIndex(2)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 32 | (0, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Symbol(SymbolIndex(0)), addend: 0, implicit_addend: true, flags: MachO { r_type: 0, r_pcrel: false, r_length: 3 } }) 33 | 34 | Dynamic symbols 35 | 36 | Symbol map 37 | 0x0 "_g1" 38 | 0x5 "_g2" 39 | -------------------------------------------------------------------------------- /crates/examples/testfiles/pe/base-bigobj.o.objdump: -------------------------------------------------------------------------------- 1 | Format: Coff Little-endian 32-bit 2 | Kind: Relocatable 3 | Architecture: X86_64 4 | Flags: Coff { characteristics: 0 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | Segment { name: ".text", address: 0, size: 0 } 8 | Segment { name: ".data", address: 0, size: 0 } 9 | Segment { name: ".bss", address: 0, size: 0 } 10 | Segment { name: ".xdata", address: 0, size: 0 } 11 | Segment { name: ".pdata", address: 0, size: 0 } 12 | Segment { name: ".rdata", address: 0, size: 0 } 13 | Segment { name: ".rdata$zzz", address: 0, size: 0 } 14 | 1: Section { name: ".text", address: 0, size: 80, align: 10, kind: Text, flags: Coff { characteristics: 60500020 } } 15 | 2: Section { name: ".data", address: 0, size: 0, align: 10, kind: Data, flags: Coff { characteristics: c0500040 } } 16 | 3: Section { name: ".bss", address: 0, size: 0, align: 10, kind: UninitializedData, flags: Coff { characteristics: c0500080 } } 17 | 4: Section { name: ".xdata", address: 0, size: 18, align: 4, kind: ReadOnlyData, flags: Coff { characteristics: 40300040 } } 18 | 5: Section { name: ".pdata", address: 0, size: 18, align: 4, kind: ReadOnlyData, flags: Coff { characteristics: 40300040 } } 19 | 6: Section { name: ".rdata", address: 0, size: 10, align: 10, kind: ReadOnlyData, flags: Coff { characteristics: 40500040 } } 20 | 7: Section { name: ".rdata$zzz", address: 0, size: 30, align: 10, kind: ReadOnlyData, flags: Coff { characteristics: 40500040 } } 21 | 22 | Symbols 23 | 0: Symbol { name: "base.c", address: 0, size: 0, kind: File, section: None, scope: Compilation, weak: false, flags: None } 24 | 2: Symbol { name: "printf", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: None } 25 | 4: Symbol { name: "main", address: 51, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Linkage, weak: false, flags: None } 26 | 5: Symbol { name: ".text", address: 0, size: 75, kind: Section, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 27 | 7: Symbol { name: ".data", address: 0, size: 0, kind: Section, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 28 | 9: Symbol { name: ".bss", address: 0, size: 0, kind: Section, section: Section(SectionIndex(3)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 29 | 11: Symbol { name: ".xdata", address: 0, size: 18, kind: Section, section: Section(SectionIndex(4)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 30 | 13: Symbol { name: ".pdata", address: 0, size: 18, kind: Section, section: Section(SectionIndex(5)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 31 | 15: Symbol { name: ".rdata", address: 0, size: d, kind: Section, section: Section(SectionIndex(6)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 32 | 17: Symbol { name: ".rdata$zzz", address: 0, size: 2b, kind: Section, section: Section(SectionIndex(7)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 33 | 19: Symbol { name: "__imp___acrt_iob_func", address: 0, size: 0, kind: Data, section: Undefined, scope: Linkage, weak: false, flags: None } 34 | 20: Symbol { name: "__main", address: 0, size: 0, kind: Text, section: Undefined, scope: Linkage, weak: false, flags: None } 35 | 21: Symbol { name: "__mingw_vfprintf", address: 0, size: 0, kind: Text, section: Undefined, scope: Linkage, weak: false, flags: None } 36 | 37 | .text relocations 38 | (2f, Relocation { kind: Relative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(13)), addend: fffffffffffffffc, implicit_addend: true, flags: Coff { typ: 4 } }) 39 | (40, Relocation { kind: Relative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(15)), addend: fffffffffffffffc, implicit_addend: true, flags: Coff { typ: 4 } }) 40 | (5a, Relocation { kind: Relative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(14)), addend: fffffffffffffffc, implicit_addend: true, flags: Coff { typ: 4 } }) 41 | (61, Relocation { kind: Relative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(f)), addend: fffffffffffffffc, implicit_addend: true, flags: Coff { typ: 4 } }) 42 | 43 | .pdata relocations 44 | (0, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 45 | (4, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 46 | (8, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(b)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 47 | (c, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 48 | (10, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 49 | (14, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(b)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 50 | 51 | Dynamic symbols 52 | 53 | Symbol map 54 | 0x0 "printf" 55 | 0x51 "main" 56 | -------------------------------------------------------------------------------- /crates/examples/testfiles/pe/base.exe.objdump: -------------------------------------------------------------------------------- 1 | Format: Pe Little-endian 32-bit 2 | Kind: Executable 3 | Architecture: I386 4 | Flags: Coff { characteristics: 102 } 5 | Relative Address Base: 400000 6 | Entry Address: 4012e1 7 | Segment { name: ".text", address: 401000, size: 104d3 } 8 | Segment { name: ".rdata", address: 412000, size: 6808 } 9 | Segment { name: ".data", address: 419000, size: 12f4 } 10 | Segment { name: ".reloc", address: 41b000, size: ec8 } 11 | 1: Section { name: ".text", address: 401000, size: 104d3, align: 1000, kind: Text, flags: Coff { characteristics: 60000020 } } 12 | 2: Section { name: ".rdata", address: 412000, size: 6808, align: 1000, kind: ReadOnlyData, flags: Coff { characteristics: 40000040 } } 13 | 3: Section { name: ".data", address: 419000, size: 12f4, align: 1000, kind: Data, flags: Coff { characteristics: c0000040 } } 14 | 4: Section { name: ".reloc", address: 41b000, size: ec8, align: 1000, kind: Other, flags: Coff { characteristics: 42000040 } } 15 | 16 | Symbols 17 | 18 | Dynamic symbols 19 | 20 | Import { library: "KERNEL32.dll", name: "QueryPerformanceCounter" } 21 | Import { library: "KERNEL32.dll", name: "GetCurrentProcessId" } 22 | Import { library: "KERNEL32.dll", name: "GetCurrentThreadId" } 23 | Import { library: "KERNEL32.dll", name: "GetSystemTimeAsFileTime" } 24 | Import { library: "KERNEL32.dll", name: "InitializeSListHead" } 25 | Import { library: "KERNEL32.dll", name: "IsDebuggerPresent" } 26 | Import { library: "KERNEL32.dll", name: "UnhandledExceptionFilter" } 27 | Import { library: "KERNEL32.dll", name: "SetUnhandledExceptionFilter" } 28 | Import { library: "KERNEL32.dll", name: "GetStartupInfoW" } 29 | Import { library: "KERNEL32.dll", name: "IsProcessorFeaturePresent" } 30 | Import { library: "KERNEL32.dll", name: "GetModuleHandleW" } 31 | Import { library: "KERNEL32.dll", name: "GetCurrentProcess" } 32 | Import { library: "KERNEL32.dll", name: "TerminateProcess" } 33 | Import { library: "KERNEL32.dll", name: "WriteConsoleW" } 34 | Import { library: "KERNEL32.dll", name: "RtlUnwind" } 35 | Import { library: "KERNEL32.dll", name: "GetLastError" } 36 | Import { library: "KERNEL32.dll", name: "SetLastError" } 37 | Import { library: "KERNEL32.dll", name: "EnterCriticalSection" } 38 | Import { library: "KERNEL32.dll", name: "LeaveCriticalSection" } 39 | Import { library: "KERNEL32.dll", name: "DeleteCriticalSection" } 40 | Import { library: "KERNEL32.dll", name: "InitializeCriticalSectionAndSpinCount" } 41 | Import { library: "KERNEL32.dll", name: "TlsAlloc" } 42 | Import { library: "KERNEL32.dll", name: "TlsGetValue" } 43 | Import { library: "KERNEL32.dll", name: "TlsSetValue" } 44 | Import { library: "KERNEL32.dll", name: "TlsFree" } 45 | Import { library: "KERNEL32.dll", name: "FreeLibrary" } 46 | Import { library: "KERNEL32.dll", name: "GetProcAddress" } 47 | Import { library: "KERNEL32.dll", name: "LoadLibraryExW" } 48 | Import { library: "KERNEL32.dll", name: "RaiseException" } 49 | Import { library: "KERNEL32.dll", name: "GetStdHandle" } 50 | Import { library: "KERNEL32.dll", name: "WriteFile" } 51 | Import { library: "KERNEL32.dll", name: "GetModuleFileNameW" } 52 | Import { library: "KERNEL32.dll", name: "ExitProcess" } 53 | Import { library: "KERNEL32.dll", name: "GetModuleHandleExW" } 54 | Import { library: "KERNEL32.dll", name: "GetCommandLineA" } 55 | Import { library: "KERNEL32.dll", name: "GetCommandLineW" } 56 | Import { library: "KERNEL32.dll", name: "HeapAlloc" } 57 | Import { library: "KERNEL32.dll", name: "HeapFree" } 58 | Import { library: "KERNEL32.dll", name: "CompareStringW" } 59 | Import { library: "KERNEL32.dll", name: "LCMapStringW" } 60 | Import { library: "KERNEL32.dll", name: "GetFileType" } 61 | Import { library: "KERNEL32.dll", name: "FindClose" } 62 | Import { library: "KERNEL32.dll", name: "FindFirstFileExW" } 63 | Import { library: "KERNEL32.dll", name: "FindNextFileW" } 64 | Import { library: "KERNEL32.dll", name: "IsValidCodePage" } 65 | Import { library: "KERNEL32.dll", name: "GetACP" } 66 | Import { library: "KERNEL32.dll", name: "GetOEMCP" } 67 | Import { library: "KERNEL32.dll", name: "GetCPInfo" } 68 | Import { library: "KERNEL32.dll", name: "MultiByteToWideChar" } 69 | Import { library: "KERNEL32.dll", name: "WideCharToMultiByte" } 70 | Import { library: "KERNEL32.dll", name: "GetEnvironmentStringsW" } 71 | Import { library: "KERNEL32.dll", name: "FreeEnvironmentStringsW" } 72 | Import { library: "KERNEL32.dll", name: "SetEnvironmentVariableW" } 73 | Import { library: "KERNEL32.dll", name: "SetStdHandle" } 74 | Import { library: "KERNEL32.dll", name: "GetStringTypeW" } 75 | Import { library: "KERNEL32.dll", name: "GetProcessHeap" } 76 | Import { library: "KERNEL32.dll", name: "FlushFileBuffers" } 77 | Import { library: "KERNEL32.dll", name: "GetConsoleOutputCP" } 78 | Import { library: "KERNEL32.dll", name: "GetConsoleMode" } 79 | Import { library: "KERNEL32.dll", name: "GetFileSizeEx" } 80 | Import { library: "KERNEL32.dll", name: "SetFilePointerEx" } 81 | Import { library: "KERNEL32.dll", name: "HeapSize" } 82 | Import { library: "KERNEL32.dll", name: "HeapReAlloc" } 83 | Import { library: "KERNEL32.dll", name: "CloseHandle" } 84 | Import { library: "KERNEL32.dll", name: "CreateFileW" } 85 | Import { library: "KERNEL32.dll", name: "DecodePointer" } 86 | 87 | Symbol map 88 | -------------------------------------------------------------------------------- /crates/examples/testfiles/pe/base.o.objdump: -------------------------------------------------------------------------------- 1 | Format: Coff Little-endian 32-bit 2 | Kind: Relocatable 3 | Architecture: X86_64 4 | Flags: Coff { characteristics: 4 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | Segment { name: ".text", address: 0, size: 0 } 8 | Segment { name: ".data", address: 0, size: 0 } 9 | Segment { name: ".bss", address: 0, size: 0 } 10 | Segment { name: ".xdata", address: 0, size: 0 } 11 | Segment { name: ".pdata", address: 0, size: 0 } 12 | Segment { name: ".rdata", address: 0, size: 0 } 13 | Segment { name: ".rdata$zzz", address: 0, size: 0 } 14 | 1: Section { name: ".text", address: 0, size: 80, align: 10, kind: Text, flags: Coff { characteristics: 60500020 } } 15 | 2: Section { name: ".data", address: 0, size: 0, align: 10, kind: Data, flags: Coff { characteristics: c0500040 } } 16 | 3: Section { name: ".bss", address: 0, size: 0, align: 10, kind: UninitializedData, flags: Coff { characteristics: c0500080 } } 17 | 4: Section { name: ".xdata", address: 0, size: 18, align: 4, kind: ReadOnlyData, flags: Coff { characteristics: 40300040 } } 18 | 5: Section { name: ".pdata", address: 0, size: 18, align: 4, kind: ReadOnlyData, flags: Coff { characteristics: 40300040 } } 19 | 6: Section { name: ".rdata", address: 0, size: 10, align: 10, kind: ReadOnlyData, flags: Coff { characteristics: 40500040 } } 20 | 7: Section { name: ".rdata$zzz", address: 0, size: 30, align: 10, kind: ReadOnlyData, flags: Coff { characteristics: 40500040 } } 21 | 22 | Symbols 23 | 0: Symbol { name: "base.c", address: 0, size: 0, kind: File, section: None, scope: Compilation, weak: false, flags: None } 24 | 2: Symbol { name: "printf", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: None } 25 | 4: Symbol { name: "main", address: 51, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Linkage, weak: false, flags: None } 26 | 5: Symbol { name: ".text", address: 0, size: 75, kind: Section, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 27 | 7: Symbol { name: ".data", address: 0, size: 0, kind: Section, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 28 | 9: Symbol { name: ".bss", address: 0, size: 0, kind: Section, section: Section(SectionIndex(3)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 29 | 11: Symbol { name: ".xdata", address: 0, size: 18, kind: Section, section: Section(SectionIndex(4)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 30 | 13: Symbol { name: ".pdata", address: 0, size: 18, kind: Section, section: Section(SectionIndex(5)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 31 | 15: Symbol { name: ".rdata", address: 0, size: d, kind: Section, section: Section(SectionIndex(6)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 32 | 17: Symbol { name: ".rdata$zzz", address: 0, size: 2b, kind: Section, section: Section(SectionIndex(7)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 33 | 19: Symbol { name: "__imp___acrt_iob_func", address: 0, size: 0, kind: Data, section: Undefined, scope: Linkage, weak: false, flags: None } 34 | 20: Symbol { name: "__main", address: 0, size: 0, kind: Text, section: Undefined, scope: Linkage, weak: false, flags: None } 35 | 21: Symbol { name: "__mingw_vfprintf", address: 0, size: 0, kind: Text, section: Undefined, scope: Linkage, weak: false, flags: None } 36 | 37 | .text relocations 38 | (2f, Relocation { kind: Relative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(13)), addend: fffffffffffffffc, implicit_addend: true, flags: Coff { typ: 4 } }) 39 | (40, Relocation { kind: Relative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(15)), addend: fffffffffffffffc, implicit_addend: true, flags: Coff { typ: 4 } }) 40 | (5a, Relocation { kind: Relative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(14)), addend: fffffffffffffffc, implicit_addend: true, flags: Coff { typ: 4 } }) 41 | (61, Relocation { kind: Relative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(f)), addend: fffffffffffffffc, implicit_addend: true, flags: Coff { typ: 4 } }) 42 | 43 | .pdata relocations 44 | (0, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 45 | (4, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 46 | (8, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(b)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 47 | (c, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 48 | (10, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 49 | (14, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(b)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 50 | 51 | Dynamic symbols 52 | 53 | Symbol map 54 | 0x0 "printf" 55 | 0x51 "main" 56 | -------------------------------------------------------------------------------- /crates/examples/testfiles/pe/resource.exe.readobj-pe-resource: -------------------------------------------------------------------------------- 1 | Format: PE 64-bit 2 | ImageResourceDirectory { 3 | Characteristics: 0 4 | TimeDateStamp: 0 5 | MajorVersion: 0 6 | MinorVersion: 0 7 | NumberOfNamedEntries: 0 8 | NumberOfIdEntries: 1 9 | ImageResourceDirectoryEntry { 10 | NameOrId: RT_VERSION (0x10) 11 | OffsetToDataOrDirectory: 0x80000018 12 | ImageResourceDirectory { 13 | Characteristics: 0 14 | TimeDateStamp: 0 15 | MajorVersion: 0 16 | MinorVersion: 0 17 | NumberOfNamedEntries: 1 18 | NumberOfIdEntries: 0 19 | ImageResourceDirectoryEntry { 20 | NameOrId: "MY VERSION" (0x80000048) 21 | OffsetToDataOrDirectory: 0x80000030 22 | ImageResourceDirectory { 23 | Characteristics: 0 24 | TimeDateStamp: 0 25 | MajorVersion: 0 26 | MinorVersion: 0 27 | NumberOfNamedEntries: 0 28 | NumberOfIdEntries: 1 29 | ImageResourceDirectoryEntry { 30 | NameOrId: 1033 31 | OffsetToDataOrDirectory: 0x60 32 | ImageResourceDataEntry { 33 | VirtualAddress: 0x10070 34 | Size: 92 35 | CodePage: 0 36 | Reserved: 0x0 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /crates/examples/testfiles/pe/weak-extern.o.objdump: -------------------------------------------------------------------------------- 1 | Format: Coff Little-endian 32-bit 2 | Kind: Relocatable 3 | Architecture: X86_64 4 | Flags: Coff { characteristics: 4 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | Segment { name: ".text", address: 0, size: 0 } 8 | Segment { name: ".data", address: 0, size: 0 } 9 | Segment { name: ".bss", address: 0, size: 0 } 10 | Segment { name: ".xdata", address: 0, size: 0 } 11 | Segment { name: ".pdata", address: 0, size: 0 } 12 | Segment { name: ".rdata$zzz", address: 0, size: 0 } 13 | 1: Section { name: ".text", address: 0, size: 10, align: 10, kind: Text, flags: Coff { characteristics: 60500020 } } 14 | 2: Section { name: ".data", address: 0, size: 0, align: 10, kind: Data, flags: Coff { characteristics: c0500040 } } 15 | 3: Section { name: ".bss", address: 0, size: 0, align: 10, kind: UninitializedData, flags: Coff { characteristics: c0500080 } } 16 | 4: Section { name: ".xdata", address: 0, size: 8, align: 4, kind: ReadOnlyData, flags: Coff { characteristics: 40300040 } } 17 | 5: Section { name: ".pdata", address: 0, size: c, align: 4, kind: ReadOnlyData, flags: Coff { characteristics: 40300040 } } 18 | 6: Section { name: ".rdata$zzz", address: 0, size: 40, align: 10, kind: ReadOnlyData, flags: Coff { characteristics: 40500040 } } 19 | 20 | Symbols 21 | 0: Symbol { name: "weak-extern.c", address: 0, size: 0, kind: File, section: None, scope: Compilation, weak: false, flags: None } 22 | 2: Symbol { name: ".text", address: 0, size: 7, kind: Section, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 23 | 4: Symbol { name: ".data", address: 0, size: 0, kind: Section, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 24 | 6: Symbol { name: ".bss", address: 0, size: 0, kind: Section, section: Section(SectionIndex(3)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 25 | 8: Symbol { name: ".xdata", address: 0, size: 8, kind: Section, section: Section(SectionIndex(4)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 26 | 10: Symbol { name: ".pdata", address: 0, size: c, kind: Section, section: Section(SectionIndex(5)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 27 | 12: Symbol { name: ".rdata$zzz", address: 0, size: 38, kind: Section, section: Section(SectionIndex(6)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } } 28 | 14: Symbol { name: ".weak.weak_symbol.", address: 0, size: 0, kind: Data, section: Section(SectionIndex(1)), scope: Linkage, weak: false, flags: None } 29 | 15: Symbol { name: "weak_symbol", address: 0, size: 0, kind: Text, section: Unknown, scope: Linkage, weak: true, flags: None } 30 | 31 | .pdata relocations 32 | (0, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(2)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 33 | (4, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(2)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 34 | (8, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(8)), addend: 0, implicit_addend: true, flags: Coff { typ: 3 } }) 35 | 36 | Dynamic symbols 37 | 38 | Symbol map 39 | 0x0 ".weak.weak_symbol." 40 | -------------------------------------------------------------------------------- /crates/examples/testfiles/wasm/base.o.objdump: -------------------------------------------------------------------------------- 1 | Format: Wasm Little-endian 32-bit 2 | Kind: Unknown 3 | Architecture: Wasm32 4 | Flags: None 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | 1: Section { name: "", address: 0, size: b, align: 1, kind: Metadata, flags: None } 8 | 2: Section { name: "", address: 0, size: 5e, align: 1, kind: Linker, flags: None } 9 | 3: Section { name: "", address: 0, size: 3, align: 1, kind: Metadata, flags: None } 10 | 12: Section { name: "", address: 0, size: 1, align: 1, kind: UninitializedData, flags: None } 11 | 10: Section { name: "", address: 0, size: 6d, align: 1, kind: Text, flags: None } 12 | 11: Section { name: "", address: 0, size: 13, align: 1, kind: Data, flags: None } 13 | 0: Section { name: "linking", address: 0, size: 5d, align: 1, kind: Linker, flags: None } 14 | 0: Section { name: "reloc.CODE", address: 0, size: 15, align: 1, kind: Other, flags: None } 15 | 0: Section { name: "producers", address: 0, size: 6c, align: 1, kind: Other, flags: None } 16 | 17 | Symbols 18 | 0: Symbol { name: "__original_main", address: 2, size: 5b, kind: Text, section: Section(SectionIndex(a)), scope: Linkage, weak: false, flags: None } 19 | 1: Symbol { name: "__stack_pointer", address: 0, size: 0, kind: Data, section: Undefined, scope: Dynamic, weak: false, flags: None } 20 | 2: Symbol { name: ".L.str", address: 0, size: d, kind: Data, section: Unknown, scope: Compilation, weak: false, flags: None } 21 | 3: Symbol { name: "printf", address: 0, size: 0, kind: Text, section: Undefined, scope: Dynamic, weak: false, flags: None } 22 | 4: Symbol { name: "main", address: 5e, size: f, kind: Text, section: Section(SectionIndex(a)), scope: Linkage, weak: false, flags: None } 23 | 5: Symbol { name: "__main_void", address: 2, size: 5b, kind: Text, section: Section(SectionIndex(a)), scope: Dynamic, weak: false, flags: None } 24 | 25 | Dynamic symbols 26 | 27 | Symbol map 28 | 0x0 ".L.str" 29 | 0x2 "__main_void" 30 | 0x5e "main" 31 | -------------------------------------------------------------------------------- /crates/examples/testfiles/wasm/global-wasm32.objdump: -------------------------------------------------------------------------------- 1 | Format: Wasm Little-endian 32-bit 2 | Kind: Unknown 3 | Architecture: Wasm32 4 | Flags: None 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | 1: Section { name: "", address: 0, size: 8, align: 1, kind: Metadata, flags: None } 8 | 2: Section { name: "", address: 0, size: 13, align: 1, kind: Linker, flags: None } 9 | 3: Section { name: "", address: 0, size: 3, align: 1, kind: Metadata, flags: None } 10 | 5: Section { name: "", address: 0, size: 3, align: 1, kind: UninitializedData, flags: None } 11 | 6: Section { name: "", address: 0, size: 4b, align: 1, kind: Data, flags: None } 12 | 7: Section { name: "", address: 0, size: bd, align: 1, kind: Linker, flags: None } 13 | 10: Section { name: "", address: 0, size: 38, align: 1, kind: Text, flags: None } 14 | 11: Section { name: "", address: 0, size: f, align: 1, kind: Data, flags: None } 15 | 0: Section { name: "name", address: 0, size: 48, align: 1, kind: Other, flags: None } 16 | 0: Section { name: "producers", address: 0, size: 5c, align: 1, kind: Other, flags: None } 17 | 0: Section { name: "target_features", address: 0, size: 1c, align: 1, kind: Other, flags: None } 18 | 19 | Symbols 20 | 0: Symbol { name: "env", address: 0, size: 0, kind: File, section: None, scope: Dynamic, weak: false, flags: None } 21 | 1: Symbol { name: "console_log", address: 0, size: 0, kind: Text, section: Undefined, scope: Dynamic, weak: false, flags: None } 22 | 2: Symbol { name: "", address: 0, size: 0, kind: File, section: None, scope: Compilation, weak: false, flags: None } 23 | 3: Symbol { name: "memory", address: 0, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 24 | 4: Symbol { name: "__wasm_call_ctors", address: 2, size: 2, kind: Text, section: Section(SectionIndex(a)), scope: Dynamic, weak: false, flags: None } 25 | 5: Symbol { name: "print", address: 5, size: 33, kind: Text, section: Section(SectionIndex(a)), scope: Dynamic, weak: false, flags: None } 26 | 6: Symbol { name: "global1", address: 400, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 27 | 7: Symbol { name: "global2", address: 404, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 28 | 8: Symbol { name: "__dso_handle", address: 400, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 29 | 9: Symbol { name: "__data_end", address: 408, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 30 | 10: Symbol { name: "__stack_low", address: 410, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 31 | 11: Symbol { name: "__stack_high", address: 10410, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 32 | 12: Symbol { name: "__global_base", address: 400, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 33 | 13: Symbol { name: "__heap_base", address: 10410, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 34 | 14: Symbol { name: "__heap_end", address: 20000, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 35 | 15: Symbol { name: "__memory_base", address: 0, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 36 | 16: Symbol { name: "__table_base", address: 1, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 37 | 38 | Dynamic symbols 39 | 40 | Symbol map 41 | 0x0 "__memory_base" 42 | 0x1 "__table_base" 43 | 0x2 "__wasm_call_ctors" 44 | 0x5 "print" 45 | 0x400 "__global_base" 46 | 0x404 "global2" 47 | 0x408 "__data_end" 48 | 0x410 "__stack_low" 49 | 0x10410 "__heap_base" 50 | 0x20000 "__heap_end" 51 | -------------------------------------------------------------------------------- /crates/examples/testfiles/wasm/global-wasm64-import.objdump: -------------------------------------------------------------------------------- 1 | Format: Wasm Little-endian 64-bit 2 | Kind: Unknown 3 | Architecture: Wasm64 4 | Flags: None 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | 1: Section { name: "", address: 0, size: 8, align: 1, kind: Metadata, flags: None } 8 | 2: Section { name: "", address: 0, size: 21, align: 1, kind: Linker, flags: None } 9 | 3: Section { name: "", address: 0, size: 3, align: 1, kind: Metadata, flags: None } 10 | 6: Section { name: "", address: 0, size: 50, align: 1, kind: Data, flags: None } 11 | 7: Section { name: "", address: 0, size: c5, align: 1, kind: Linker, flags: None } 12 | 10: Section { name: "", address: 0, size: 48, align: 1, kind: Text, flags: None } 13 | 11: Section { name: "", address: 0, size: f, align: 1, kind: Data, flags: None } 14 | 0: Section { name: "name", address: 0, size: 48, align: 1, kind: Other, flags: None } 15 | 0: Section { name: "producers", address: 0, size: 5c, align: 1, kind: Other, flags: None } 16 | 0: Section { name: "target_features", address: 0, size: 26, align: 1, kind: Other, flags: None } 17 | 18 | Symbols 19 | 0: Symbol { name: "env", address: 0, size: 0, kind: File, section: None, scope: Dynamic, weak: false, flags: None } 20 | 1: Symbol { name: "memory", address: 0, size: 0, kind: Data, section: Undefined, scope: Dynamic, weak: false, flags: None } 21 | 2: Symbol { name: "console_log", address: 0, size: 0, kind: Text, section: Undefined, scope: Dynamic, weak: false, flags: None } 22 | 3: Symbol { name: "", address: 0, size: 0, kind: File, section: None, scope: Compilation, weak: false, flags: None } 23 | 4: Symbol { name: "__wasm_call_ctors", address: 2, size: 2, kind: Text, section: Section(SectionIndex(a)), scope: Dynamic, weak: false, flags: None } 24 | 5: Symbol { name: "print", address: 5, size: 43, kind: Text, section: Section(SectionIndex(a)), scope: Dynamic, weak: false, flags: None } 25 | 6: Symbol { name: "global1", address: 400, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 26 | 7: Symbol { name: "global2", address: 404, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 27 | 8: Symbol { name: "__dso_handle", address: 400, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 28 | 9: Symbol { name: "__data_end", address: 408, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 29 | 10: Symbol { name: "__stack_low", address: 410, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 30 | 11: Symbol { name: "__stack_high", address: 10410, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 31 | 12: Symbol { name: "__global_base", address: 400, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 32 | 13: Symbol { name: "__heap_base", address: 10410, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 33 | 14: Symbol { name: "__heap_end", address: 20000, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 34 | 15: Symbol { name: "__memory_base", address: 0, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 35 | 16: Symbol { name: "__table_base", address: 1, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 36 | 17: Symbol { name: "__table_base32", address: 1, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 37 | 38 | Dynamic symbols 39 | 40 | Symbol map 41 | 0x0 "__memory_base" 42 | 0x1 "__table_base32" 43 | 0x2 "__wasm_call_ctors" 44 | 0x5 "print" 45 | 0x400 "__global_base" 46 | 0x404 "global2" 47 | 0x408 "__data_end" 48 | 0x410 "__stack_low" 49 | 0x10410 "__heap_base" 50 | 0x20000 "__heap_end" 51 | -------------------------------------------------------------------------------- /crates/examples/testfiles/wasm/global-wasm64.objdump: -------------------------------------------------------------------------------- 1 | Format: Wasm Little-endian 64-bit 2 | Kind: Unknown 3 | Architecture: Wasm64 4 | Flags: None 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | 1: Section { name: "", address: 0, size: 8, align: 1, kind: Metadata, flags: None } 8 | 2: Section { name: "", address: 0, size: 13, align: 1, kind: Linker, flags: None } 9 | 3: Section { name: "", address: 0, size: 3, align: 1, kind: Metadata, flags: None } 10 | 5: Section { name: "", address: 0, size: 3, align: 1, kind: UninitializedData, flags: None } 11 | 6: Section { name: "", address: 0, size: 50, align: 1, kind: Data, flags: None } 12 | 7: Section { name: "", address: 0, size: ce, align: 1, kind: Linker, flags: None } 13 | 10: Section { name: "", address: 0, size: 48, align: 1, kind: Text, flags: None } 14 | 11: Section { name: "", address: 0, size: f, align: 1, kind: Data, flags: None } 15 | 0: Section { name: "name", address: 0, size: 48, align: 1, kind: Other, flags: None } 16 | 0: Section { name: "producers", address: 0, size: 5c, align: 1, kind: Other, flags: None } 17 | 0: Section { name: "target_features", address: 0, size: 26, align: 1, kind: Other, flags: None } 18 | 19 | Symbols 20 | 0: Symbol { name: "env", address: 0, size: 0, kind: File, section: None, scope: Dynamic, weak: false, flags: None } 21 | 1: Symbol { name: "console_log", address: 0, size: 0, kind: Text, section: Undefined, scope: Dynamic, weak: false, flags: None } 22 | 2: Symbol { name: "", address: 0, size: 0, kind: File, section: None, scope: Compilation, weak: false, flags: None } 23 | 3: Symbol { name: "memory", address: 0, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 24 | 4: Symbol { name: "__wasm_call_ctors", address: 2, size: 2, kind: Text, section: Section(SectionIndex(a)), scope: Dynamic, weak: false, flags: None } 25 | 5: Symbol { name: "print", address: 5, size: 43, kind: Text, section: Section(SectionIndex(a)), scope: Dynamic, weak: false, flags: None } 26 | 6: Symbol { name: "global1", address: 400, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 27 | 7: Symbol { name: "global2", address: 404, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 28 | 8: Symbol { name: "__dso_handle", address: 400, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 29 | 9: Symbol { name: "__data_end", address: 408, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 30 | 10: Symbol { name: "__stack_low", address: 410, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 31 | 11: Symbol { name: "__stack_high", address: 10410, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 32 | 12: Symbol { name: "__global_base", address: 400, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 33 | 13: Symbol { name: "__heap_base", address: 10410, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 34 | 14: Symbol { name: "__heap_end", address: 20000, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 35 | 15: Symbol { name: "__memory_base", address: 0, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 36 | 16: Symbol { name: "__table_base", address: 1, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 37 | 17: Symbol { name: "__table_base32", address: 1, size: 0, kind: Data, section: Section(SectionIndex(b)), scope: Dynamic, weak: false, flags: None } 38 | 39 | Dynamic symbols 40 | 41 | Symbol map 42 | 0x0 "__memory_base" 43 | 0x1 "__table_base32" 44 | 0x2 "__wasm_call_ctors" 45 | 0x5 "print" 46 | 0x400 "__global_base" 47 | 0x404 "global2" 48 | 0x408 "__data_end" 49 | 0x410 "__stack_low" 50 | 0x10410 "__heap_base" 51 | 0x20000 "__heap_end" 52 | -------------------------------------------------------------------------------- /crates/examples/testfiles/xcoff/base.o.objdump: -------------------------------------------------------------------------------- 1 | Format: Xcoff Big-endian 64-bit 2 | Kind: Relocatable 3 | Architecture: PowerPc64 4 | Flags: Xcoff { f_flags: 0 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | 1: Section { name: ".text", address: 0, size: 68, align: 4, kind: Text, flags: Xcoff { s_flags: 20 } } 8 | 2: Section { name: ".data", address: 68, size: 20, align: 4, kind: Data, flags: Xcoff { s_flags: 40 } } 9 | 10 | Symbols 11 | 0: Symbol { name: "base.c", address: 0, size: 0, kind: File, section: None, scope: Compilation, weak: false, flags: Xcoff { n_sclass: 67, x_smtyp: 0, x_smclas: 0, containing_csect: None } } 12 | 3: Symbol { name: ".printf", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: Xcoff { n_sclass: 2, x_smtyp: 0, x_smclas: 0, containing_csect: None } } 13 | 5: Symbol { name: "printf", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: Xcoff { n_sclass: 2, x_smtyp: 0, x_smclas: a, containing_csect: None } } 14 | 7: Symbol { name: ".text", address: 0, size: 57, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: Xcoff { n_sclass: 6b, x_smtyp: 29, x_smclas: 0, containing_csect: None } } 15 | 9: Symbol { name: ".main", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: Xcoff { n_sclass: 2, x_smtyp: 2, x_smclas: 0, containing_csect: Some(SymbolIndex(7)) } } 16 | 11: Symbol { name: ".rodata.str1.1L...str", address: 58, size: d, kind: Data, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: Xcoff { n_sclass: 6b, x_smtyp: 11, x_smclas: 1, containing_csect: None } } 17 | 13: Symbol { name: "main", address: 68, size: 18, kind: Data, section: Section(SectionIndex(2)), scope: Dynamic, weak: false, flags: Xcoff { n_sclass: 2, x_smtyp: 19, x_smclas: a, containing_csect: None } } 18 | 15: Symbol { name: "TOC", address: 80, size: 0, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: Xcoff { n_sclass: 6b, x_smtyp: 19, x_smclas: f, containing_csect: None } } 19 | 17: Symbol { name: ".rodata.str1.1L...str", address: 80, size: 8, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: Xcoff { n_sclass: 6b, x_smtyp: 19, x_smclas: 3, containing_csect: None } } 20 | 21 | .text relocations 22 | (1e, Relocation { kind: Got, encoding: Generic, size: 10, target: Symbol(SymbolIndex(11)), addend: 0, implicit_addend: true, flags: Xcoff { r_rtype: 3, r_rsize: f } }) 23 | (20, Relocation { kind: Relative, encoding: Generic, size: 1a, target: Symbol(SymbolIndex(3)), addend: fffffffffffffffc, implicit_addend: true, flags: Xcoff { r_rtype: 1a, r_rsize: 99 } }) 24 | 25 | .data relocations 26 | (68, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Symbol(SymbolIndex(9)), addend: 0, implicit_addend: true, flags: Xcoff { r_rtype: 0, r_rsize: 3f } }) 27 | (70, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Symbol(SymbolIndex(f)), addend: 0, implicit_addend: true, flags: Xcoff { r_rtype: 0, r_rsize: 3f } }) 28 | (80, Relocation { kind: Absolute, encoding: Generic, size: 40, target: Symbol(SymbolIndex(b)), addend: 0, implicit_addend: true, flags: Xcoff { r_rtype: 0, r_rsize: 3f } }) 29 | 30 | Dynamic symbols 31 | 32 | Symbol map 33 | 0x0 ".main" 34 | 0x58 ".rodata.str1.1L...str" 35 | 0x68 "main" 36 | 0x80 ".rodata.str1.1L...str" 37 | -------------------------------------------------------------------------------- /crates/examples/testfiles/xcoff/base32.o.objdump: -------------------------------------------------------------------------------- 1 | Format: Xcoff Big-endian 32-bit 2 | Kind: Relocatable 3 | Architecture: PowerPc 4 | Flags: Xcoff { f_flags: 0 } 5 | Relative Address Base: 0 6 | Entry Address: 0 7 | 1: Section { name: ".text", address: 0, size: 6c, align: 4, kind: Text, flags: Xcoff { s_flags: 20 } } 8 | 2: Section { name: ".data", address: 6c, size: 10, align: 4, kind: Data, flags: Xcoff { s_flags: 40 } } 9 | 10 | Symbols 11 | 0: Symbol { name: "base.c", address: 0, size: 0, kind: File, section: None, scope: Compilation, weak: false, flags: Xcoff { n_sclass: 67, x_smtyp: 0, x_smclas: 0, containing_csect: None } } 12 | 3: Symbol { name: ".printf", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: Xcoff { n_sclass: 2, x_smtyp: 0, x_smclas: 0, containing_csect: None } } 13 | 5: Symbol { name: "printf", address: 0, size: 0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: Xcoff { n_sclass: 2, x_smtyp: 0, x_smclas: a, containing_csect: None } } 14 | 7: Symbol { name: ".text", address: 0, size: 5b, kind: Text, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: Xcoff { n_sclass: 6b, x_smtyp: 29, x_smclas: 0, containing_csect: None } } 15 | 9: Symbol { name: ".main", address: 0, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Dynamic, weak: false, flags: Xcoff { n_sclass: 2, x_smtyp: 2, x_smclas: 0, containing_csect: Some(SymbolIndex(7)) } } 16 | 11: Symbol { name: ".rodata.str1.1L...str", address: 5c, size: d, kind: Data, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: Xcoff { n_sclass: 6b, x_smtyp: 11, x_smclas: 1, containing_csect: None } } 17 | 13: Symbol { name: "main", address: 6c, size: c, kind: Data, section: Section(SectionIndex(2)), scope: Dynamic, weak: false, flags: Xcoff { n_sclass: 2, x_smtyp: 11, x_smclas: a, containing_csect: None } } 18 | 15: Symbol { name: "TOC", address: 78, size: 0, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: Xcoff { n_sclass: 6b, x_smtyp: 11, x_smclas: f, containing_csect: None } } 19 | 17: Symbol { name: ".rodata.str1.1L...str", address: 78, size: 4, kind: Data, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: Xcoff { n_sclass: 6b, x_smtyp: 11, x_smclas: 3, containing_csect: None } } 20 | 21 | .text relocations 22 | (22, Relocation { kind: Got, encoding: Generic, size: 10, target: Symbol(SymbolIndex(11)), addend: 0, implicit_addend: true, flags: Xcoff { r_rtype: 3, r_rsize: f } }) 23 | (24, Relocation { kind: Relative, encoding: Generic, size: 1a, target: Symbol(SymbolIndex(3)), addend: fffffffffffffffc, implicit_addend: true, flags: Xcoff { r_rtype: 1a, r_rsize: 99 } }) 24 | 25 | .data relocations 26 | (6c, Relocation { kind: Absolute, encoding: Generic, size: 20, target: Symbol(SymbolIndex(9)), addend: 0, implicit_addend: true, flags: Xcoff { r_rtype: 0, r_rsize: 1f } }) 27 | (70, Relocation { kind: Absolute, encoding: Generic, size: 20, target: Symbol(SymbolIndex(f)), addend: 0, implicit_addend: true, flags: Xcoff { r_rtype: 0, r_rsize: 1f } }) 28 | (78, Relocation { kind: Absolute, encoding: Generic, size: 20, target: Symbol(SymbolIndex(b)), addend: 0, implicit_addend: true, flags: Xcoff { r_rtype: 0, r_rsize: 1f } }) 29 | 30 | Dynamic symbols 31 | 32 | Symbol map 33 | 0x0 ".main" 34 | 0x5c ".rodata.str1.1L...str" 35 | 0x6c "main" 36 | 0x78 ".rodata.str1.1L...str" 37 | -------------------------------------------------------------------------------- /crates/rewrite/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "object-rewrite" 3 | version = "0.1.1" 4 | edition = "2021" 5 | license = "Apache-2.0 OR MIT" 6 | repository = "https://github.com/gimli-rs/object/tree/master/crates/rewrite" 7 | description = "Rewrite object files with modifications" 8 | include = [ 9 | "/Cargo.lock", 10 | "/Cargo.toml", 11 | "/src", 12 | ] 13 | 14 | [package.metadata.docs.rs] 15 | features = ['doc'] 16 | 17 | [dependencies] 18 | object = { version = "0.37.0", default-features = false, features = ["build", "elf"], path = "../.." } 19 | 20 | # Dependencies for the cli 21 | anyhow = { version = "1.0.79", optional = true } 22 | clap = { version = "4.3.24", features = ["cargo"], optional = true } 23 | env_logger = { version = "0.11.2", default-features = false, optional = true } 24 | log = { version = "0.4.20", optional = true } 25 | memmap2 = { version = "0.9.4", optional = true } 26 | 27 | [dev-dependencies] 28 | object-examples = { path = "../examples" } 29 | 30 | [features] 31 | logging = ["dep:log"] 32 | cli = ["logging", "dep:anyhow", "dep:clap", "dep:env_logger", "dep:memmap2"] 33 | 34 | default = [] 35 | all = ["cli", "logging"] 36 | doc = [] 37 | 38 | [[bin]] 39 | name = "object-rewrite" 40 | path = "src/main.rs" 41 | required-features = ["cli"] 42 | -------------------------------------------------------------------------------- /crates/rewrite/src/error.rs: -------------------------------------------------------------------------------- 1 | use object::build; 2 | use std::{error, fmt, io}; 3 | 4 | /// An error that occurred while rewriting a file. 5 | #[derive(Debug)] 6 | pub struct Error { 7 | inner: ErrorInner, 8 | } 9 | 10 | #[derive(Debug)] 11 | enum ErrorInner { 12 | Io(io::Error), 13 | Parse(build::Error), 14 | Write(build::Error), 15 | Modify(String), 16 | } 17 | 18 | /// The kind of error. 19 | #[derive(Debug, Clone, PartialEq, Eq)] 20 | pub enum ErrorKind { 21 | /// A parse error occurred while reading the file. 22 | Parse, 23 | /// A validation error occurred while writing the file. 24 | Write, 25 | /// An I/O error occurred while writing the file. 26 | Io(io::ErrorKind), 27 | /// A validation error occurred while modifying the file. 28 | Modify, 29 | } 30 | 31 | impl fmt::Display for Error { 32 | #[inline] 33 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 34 | match &self.inner { 35 | ErrorInner::Io(e) => e.fmt(f), 36 | ErrorInner::Parse(e) => e.fmt(f), 37 | ErrorInner::Write(e) => e.fmt(f), 38 | ErrorInner::Modify(e) => e.fmt(f), 39 | } 40 | } 41 | } 42 | 43 | impl error::Error for Error {} 44 | 45 | impl Error { 46 | /// Get the kind of error. 47 | pub fn kind(&self) -> ErrorKind { 48 | match &self.inner { 49 | ErrorInner::Io(e) => ErrorKind::Io(e.kind()), 50 | ErrorInner::Parse(_) => ErrorKind::Parse, 51 | ErrorInner::Write(_) => ErrorKind::Write, 52 | ErrorInner::Modify(_) => ErrorKind::Modify, 53 | } 54 | } 55 | 56 | pub(crate) fn io(error: io::Error) -> Self { 57 | Self { 58 | inner: ErrorInner::Io(error), 59 | } 60 | } 61 | 62 | pub(crate) fn parse(error: build::Error) -> Self { 63 | Self { 64 | inner: ErrorInner::Parse(error), 65 | } 66 | } 67 | 68 | pub(crate) fn write(error: build::Error) -> Self { 69 | Self { 70 | inner: ErrorInner::Write(error), 71 | } 72 | } 73 | 74 | pub(crate) fn modify(message: impl Into) -> Self { 75 | Self { 76 | inner: ErrorInner::Modify(message.into()), 77 | } 78 | } 79 | } 80 | 81 | /// The `Result` type for this library. 82 | pub type Result = std::result::Result; 83 | -------------------------------------------------------------------------------- /crates/rewrite/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! A library for rewriting object and executable files. 2 | //! 3 | //! Use the [`Rewriter`] struct to read a file, modify it, and write it back. 4 | //! Modifications can be performed using methods on the [`Rewriter`] struct, or 5 | //! by passing an [`Options`] struct to the [`Rewriter::modify`] method. 6 | //! 7 | //! Currently, only ELF files are supported, and not many modifications are 8 | //! possible yet. 9 | //! 10 | //! # Example 11 | //! ```no_run 12 | //! use object_rewrite::{Options, Rewriter}; 13 | //! 14 | //! fn main() -> Result<(), Box> { 15 | //! let mut options = Options::default(); 16 | //! options.delete_symbols.insert(b"main".to_vec()); 17 | //! 18 | //! let input = std::fs::read("path/to/input")?; 19 | //! let mut rewriter = Rewriter::read(&input)?; 20 | //! rewriter.modify(options)?; 21 | //! let mut output = std::fs::File::create("path/to/output")?; 22 | //! rewriter.write(&mut output)?; 23 | //! Ok(()) 24 | //! } 25 | //! ``` 26 | 27 | #![warn(missing_docs)] 28 | #![warn(missing_debug_implementations)] 29 | 30 | mod error; 31 | pub use error::{Error, ErrorKind, Result}; 32 | 33 | mod rewriter; 34 | pub use rewriter::{Options, Rewriter}; 35 | 36 | mod elf; 37 | pub use elf::ElfOptions; 38 | -------------------------------------------------------------------------------- /crates/rewrite/src/rewriter.rs: -------------------------------------------------------------------------------- 1 | use std::collections::{HashMap, HashSet}; 2 | 3 | use object::build; 4 | 5 | use super::{Error, Result}; 6 | 7 | /// Options for modifying a file. 8 | /// 9 | /// This is used as an argument to the [`Rewriter::modify`] method. 10 | /// 11 | /// The options are listed in the order they are processed. 12 | #[derive(Debug, Default)] 13 | #[non_exhaustive] 14 | pub struct Options { 15 | /// Delete symbols from the symbol table. 16 | /// 17 | /// See [`Rewriter::delete_symbols`]. 18 | pub delete_symbols: HashSet>, 19 | /// Rename symbols in the symbol table. 20 | /// 21 | /// See [`Rewriter::rename_symbols`]. 22 | pub rename_symbols: HashMap, Vec>, 23 | /// Delete sections from the file. 24 | /// 25 | /// See [`Rewriter::delete_sections`]. 26 | pub delete_sections: HashSet>, 27 | /// Rename sections in the file. 28 | /// 29 | /// See [`Rewriter::rename_sections`]. 30 | pub rename_sections: HashMap, Vec>, 31 | /// Options that are specific to ELF files. 32 | pub elf: super::ElfOptions, 33 | } 34 | 35 | /// A rewriter for object and executable files. 36 | /// 37 | /// This struct provides a way to read a file, modify it, and write it back. 38 | #[derive(Debug)] 39 | pub struct Rewriter<'data> { 40 | pub(crate) builder: build::elf::Builder<'data>, 41 | pub(crate) modified: bool, 42 | } 43 | 44 | impl<'data> Rewriter<'data> { 45 | /// Read a file and create a new rewriter. 46 | pub fn read(data: &'data [u8]) -> Result { 47 | let builder = build::elf::Builder::read(data).map_err(Error::parse)?; 48 | Ok(Self { 49 | builder, 50 | modified: false, 51 | }) 52 | } 53 | 54 | /// Write the file to an output stream. 55 | pub fn write(mut self, w: W) -> Result<()> { 56 | self.elf_finalize()?; 57 | let mut buffer = object::write::StreamingBuffer::new(w); 58 | self.builder.write(&mut buffer).map_err(Error::write)?; 59 | buffer.result().map_err(Error::io) 60 | } 61 | 62 | /// Modify the file according to the given options. 63 | pub fn modify(&mut self, options: Options) -> Result<()> { 64 | if !options.delete_symbols.is_empty() { 65 | self.delete_symbols(&options.delete_symbols); 66 | } 67 | if !options.rename_symbols.is_empty() { 68 | self.rename_symbols(&options.rename_symbols); 69 | } 70 | if !options.delete_sections.is_empty() { 71 | self.delete_sections(&options.delete_sections); 72 | } 73 | if !options.rename_sections.is_empty() { 74 | self.rename_sections(&options.rename_sections); 75 | } 76 | self.elf_modify(options.elf)?; 77 | Ok(()) 78 | } 79 | 80 | /// Delete symbols from the symbol table. 81 | /// 82 | /// For ELF files, this deletes symbols from both the symbol table and the 83 | /// dynamic symbol table. 84 | pub fn delete_symbols(&mut self, names: &HashSet>) { 85 | self.elf_delete_symbols(names); 86 | self.elf_delete_dynamic_symbols(names); 87 | } 88 | 89 | /// Rename symbols in the symbol table. 90 | /// 91 | /// For ELF files, this renames symbols in both the symbol table and the 92 | /// dynamic symbol table. 93 | /// 94 | /// The `names` map is from old names to new names. 95 | pub fn rename_symbols(&mut self, names: &HashMap, Vec>) { 96 | self.elf_rename_symbols(names); 97 | self.elf_rename_dynamic_symbols(names); 98 | } 99 | 100 | /// Delete sections from the file. 101 | pub fn delete_sections(&mut self, names: &HashSet>) { 102 | self.elf_delete_sections(names); 103 | } 104 | 105 | /// Rename sections in the file. 106 | /// 107 | /// The `names` map is from old names to new names. 108 | pub fn rename_sections(&mut self, names: &HashMap, Vec>) { 109 | self.elf_rename_sections(names); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/archive.rs: -------------------------------------------------------------------------------- 1 | //! Archive definitions. 2 | //! 3 | //! These definitions are independent of read/write support, although we do implement 4 | //! some traits useful for those. 5 | 6 | use crate::pod::Pod; 7 | 8 | /// File identification bytes stored at the beginning of the file. 9 | pub const MAGIC: [u8; 8] = *b"!\n"; 10 | 11 | /// File identification bytes at the beginning of AIX big archive. 12 | pub const AIX_BIG_MAGIC: [u8; 8] = *b"\n"; 13 | 14 | /// File identification bytes stored at the beginning of a thin archive. 15 | /// 16 | /// A thin archive only contains a symbol table and file names. 17 | pub const THIN_MAGIC: [u8; 8] = *b"!\n"; 18 | 19 | /// The terminator for each archive member header. 20 | pub const TERMINATOR: [u8; 2] = *b"`\n"; 21 | 22 | /// The header at the start of an archive member. 23 | #[derive(Debug, Clone, Copy)] 24 | #[repr(C)] 25 | pub struct Header { 26 | /// The file name. 27 | pub name: [u8; 16], 28 | /// File modification timestamp in decimal. 29 | pub date: [u8; 12], 30 | /// User ID in decimal. 31 | pub uid: [u8; 6], 32 | /// Group ID in decimal. 33 | pub gid: [u8; 6], 34 | /// File mode in octal. 35 | pub mode: [u8; 8], 36 | /// File size in decimal. 37 | pub size: [u8; 10], 38 | /// Must be equal to `TERMINATOR`. 39 | pub terminator: [u8; 2], 40 | } 41 | 42 | /// The header at the start of an AIX big archive member, without name. 43 | #[derive(Debug, Clone, Copy)] 44 | #[repr(C)] 45 | pub struct AixHeader { 46 | /// File member size in decimal. 47 | pub size: [u8; 20], 48 | /// Next member offset in decimal. 49 | pub nxtmem: [u8; 20], 50 | /// Previous member offset in decimal. 51 | pub prvmem: [u8; 20], 52 | /// File member date in decimal. 53 | pub date: [u8; 12], 54 | /// File member user id in decimal. 55 | pub uid: [u8; 12], 56 | /// File member group id in decimal. 57 | pub gid: [u8; 12], 58 | /// File member mode in octal. 59 | pub mode: [u8; 12], 60 | /// File member name length in decimal. 61 | pub namlen: [u8; 4], 62 | } 63 | 64 | /// The AIX big archive's fixed length header at file beginning. 65 | #[derive(Debug, Clone, Copy)] 66 | #[repr(C)] 67 | pub struct AixFileHeader { 68 | /// Archive magic string. 69 | pub magic: [u8; 8], 70 | /// Offset of member table. 71 | pub memoff: [u8; 20], 72 | /// Offset of global symbol table. 73 | pub gstoff: [u8; 20], 74 | /// Offset of global symbol table for 64-bit objects. 75 | pub gst64off: [u8; 20], 76 | /// Offset of first member. 77 | pub fstmoff: [u8; 20], 78 | /// Offset of last member. 79 | pub lstmoff: [u8; 20], 80 | /// Offset of first member on free list. 81 | pub freeoff: [u8; 20], 82 | } 83 | 84 | /// Offset of a member in an AIX big archive. 85 | /// 86 | /// This is used in the member index. 87 | #[derive(Debug, Clone, Copy)] 88 | #[repr(C)] 89 | pub struct AixMemberOffset(pub [u8; 20]); 90 | 91 | unsafe_impl_pod!(Header, AixHeader, AixFileHeader, AixMemberOffset,); 92 | -------------------------------------------------------------------------------- /src/build/bytes.rs: -------------------------------------------------------------------------------- 1 | use alloc::borrow::Cow; 2 | use alloc::string::String; 3 | use alloc::vec::Vec; 4 | use core::fmt; 5 | 6 | /// A byte slice. 7 | /// 8 | /// Uses copy-on-write to avoid unnecessary allocations. The bytes can be 9 | /// accessed as a slice using the `Deref` trait, or as a mutable `Vec` using the 10 | /// `to_mut` method. 11 | /// 12 | /// Provides a `Debug` implementation that shows the first 8 bytes and the length. 13 | #[derive(Default, Clone, PartialEq, Eq)] 14 | pub struct Bytes<'a>(Cow<'a, [u8]>); 15 | 16 | impl<'a> Bytes<'a> { 17 | /// Acquire a mutable reference to the bytes. 18 | /// 19 | /// Clones the bytes if they are shared. 20 | pub fn to_mut(&mut self) -> &mut Vec { 21 | self.0.to_mut() 22 | } 23 | 24 | /// Get the bytes as a slice. 25 | pub fn as_slice(&self) -> &[u8] { 26 | self.0.as_ref() 27 | } 28 | } 29 | 30 | impl<'a> core::ops::Deref for Bytes<'a> { 31 | type Target = [u8]; 32 | fn deref(&self) -> &[u8] { 33 | self.0.deref() 34 | } 35 | } 36 | 37 | impl<'a> From<&'a [u8]> for Bytes<'a> { 38 | fn from(bytes: &'a [u8]) -> Self { 39 | Bytes(Cow::Borrowed(bytes)) 40 | } 41 | } 42 | 43 | impl<'a> From> for Bytes<'a> { 44 | fn from(bytes: Vec) -> Self { 45 | Bytes(Cow::Owned(bytes)) 46 | } 47 | } 48 | 49 | impl<'a> fmt::Debug for Bytes<'a> { 50 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 51 | debug_list_bytes(&self.0, f) 52 | } 53 | } 54 | 55 | // Only for Debug impl of `Bytes`. 56 | fn debug_list_bytes(bytes: &[u8], fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 57 | let mut list = fmt.debug_list(); 58 | list.entries(bytes.iter().take(8).copied().map(DebugByte)); 59 | if bytes.len() > 8 { 60 | list.entry(&DebugLen(bytes.len())); 61 | } 62 | list.finish() 63 | } 64 | 65 | struct DebugByte(u8); 66 | 67 | impl fmt::Debug for DebugByte { 68 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 69 | write!(fmt, "0x{:02x}", self.0) 70 | } 71 | } 72 | 73 | struct DebugLen(usize); 74 | 75 | impl fmt::Debug for DebugLen { 76 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 77 | write!(fmt, "...; {}", self.0) 78 | } 79 | } 80 | 81 | /// A byte slice that is a string of an unknown encoding. 82 | /// 83 | /// Uses copy-on-write to avoid unnecessary allocations. The bytes can be 84 | /// accessed as a slice using the `Deref` trait, or as a mutable `Vec` using the 85 | /// `to_mut` method. 86 | /// 87 | /// Provides a `Debug` implementation that interprets the bytes as UTF-8. 88 | #[derive(Default, Clone, PartialEq, Eq, Hash)] 89 | pub struct ByteString<'a>(Cow<'a, [u8]>); 90 | 91 | impl<'a> ByteString<'a> { 92 | /// Acquire a mutable reference to the bytes. 93 | /// 94 | /// Clones the bytes if they are shared. 95 | pub fn to_mut(&mut self) -> &mut Vec { 96 | self.0.to_mut() 97 | } 98 | 99 | /// Get the bytes as a slice. 100 | pub fn as_slice(&self) -> &[u8] { 101 | self.0.as_ref() 102 | } 103 | } 104 | 105 | impl<'a> core::borrow::Borrow<[u8]> for ByteString<'a> { 106 | fn borrow(&self) -> &[u8] { 107 | self.0.borrow() 108 | } 109 | } 110 | 111 | impl<'a> core::ops::Deref for ByteString<'a> { 112 | type Target = [u8]; 113 | fn deref(&self) -> &[u8] { 114 | self.0.deref() 115 | } 116 | } 117 | 118 | impl<'a> From<&'a [u8]> for ByteString<'a> { 119 | fn from(bytes: &'a [u8]) -> Self { 120 | ByteString(Cow::Borrowed(bytes)) 121 | } 122 | } 123 | 124 | impl<'a> From> for ByteString<'a> { 125 | fn from(bytes: Vec) -> Self { 126 | ByteString(Cow::Owned(bytes)) 127 | } 128 | } 129 | 130 | impl<'a> From<&'a str> for ByteString<'a> { 131 | fn from(s: &'a str) -> Self { 132 | ByteString(Cow::Borrowed(s.as_bytes())) 133 | } 134 | } 135 | 136 | impl<'a> fmt::Debug for ByteString<'a> { 137 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 138 | write!(fmt, "\"{}\"", String::from_utf8_lossy(&self.0)) 139 | } 140 | } 141 | 142 | impl<'a> fmt::Display for ByteString<'a> { 143 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 144 | write!(fmt, "{}", String::from_utf8_lossy(&self.0)) 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/build/error.rs: -------------------------------------------------------------------------------- 1 | use alloc::string::String; 2 | use core::{fmt, result}; 3 | #[cfg(feature = "std")] 4 | use std::error; 5 | 6 | use crate::{read, write}; 7 | 8 | /// The error type used within the build module. 9 | #[derive(Debug, Clone, PartialEq, Eq)] 10 | pub struct Error(pub(super) String); 11 | 12 | impl Error { 13 | pub(super) fn new(message: impl Into) -> Self { 14 | Error(message.into()) 15 | } 16 | } 17 | 18 | impl fmt::Display for Error { 19 | #[inline] 20 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 21 | f.write_str(&self.0) 22 | } 23 | } 24 | 25 | #[cfg(feature = "std")] 26 | impl error::Error for Error {} 27 | #[cfg(all(not(feature = "std"), core_error))] 28 | impl core::error::Error for Error {} 29 | 30 | impl From for Error { 31 | fn from(error: read::Error) -> Error { 32 | Error(format!("{}", error)) 33 | } 34 | } 35 | 36 | impl From for Error { 37 | fn from(error: write::Error) -> Error { 38 | Error(error.0) 39 | } 40 | } 41 | 42 | /// The result type used within the build module. 43 | pub type Result = result::Result; 44 | -------------------------------------------------------------------------------- /src/build/mod.rs: -------------------------------------------------------------------------------- 1 | //! Interface for building object files. 2 | //! 3 | //! This module provides common types and traits used in the builders. 4 | //! 5 | //! The submodules define the builders for each file format. 6 | 7 | mod error; 8 | pub use error::{Error, Result}; 9 | 10 | mod bytes; 11 | pub use bytes::{ByteString, Bytes}; 12 | 13 | mod table; 14 | use table::IdPrivate; 15 | pub use table::{Id, Item, Table}; 16 | 17 | #[cfg(feature = "elf")] 18 | pub mod elf; 19 | -------------------------------------------------------------------------------- /src/build/table.rs: -------------------------------------------------------------------------------- 1 | use alloc::vec::Vec; 2 | 3 | /// An item in a [`Table`]. 4 | pub trait Item { 5 | /// The type of identifier for the item. 6 | type Id: Id; 7 | 8 | /// Return `True` if the item is deleted. 9 | fn is_deleted(&self) -> bool; 10 | } 11 | 12 | /// An identifier for referring to an item in a [`Table`]. 13 | pub trait Id: IdPrivate { 14 | /// Return the index of the item in the table. 15 | fn index(&self) -> usize; 16 | } 17 | 18 | mod id_private { 19 | pub trait IdPrivate { 20 | fn new(id: usize) -> Self; 21 | } 22 | } 23 | pub(super) use id_private::IdPrivate; 24 | 25 | /// A table of items. 26 | /// 27 | /// Each item has a unique identifier. 28 | /// Items can be deleted without changing the identifiers of other items. 29 | #[derive(Debug)] 30 | pub struct Table(Vec); 31 | 32 | impl Table { 33 | pub(super) fn new() -> Self { 34 | Table(Vec::new()) 35 | } 36 | } 37 | 38 | impl Table { 39 | pub(super) fn next_id(&self) -> T::Id { 40 | T::Id::new(self.0.len()) 41 | } 42 | 43 | pub(super) fn push(&mut self, item: T) -> &mut T { 44 | self.0.push(item); 45 | self.0.last_mut().unwrap() 46 | } 47 | 48 | /// Number of items, including deleted items. 49 | pub(super) fn len(&self) -> usize { 50 | self.0.len() 51 | } 52 | 53 | /// Return `True` if there are no non-deleted items. 54 | pub fn is_empty(&self) -> bool { 55 | self.into_iter().next().is_none() 56 | } 57 | 58 | /// Number of non-deleted items. 59 | pub fn count(&self) -> usize { 60 | self.into_iter().count() 61 | } 62 | 63 | /// Return a reference to an item. 64 | pub fn get(&self, id: T::Id) -> &T { 65 | self.0.get(id.index()).unwrap() 66 | } 67 | 68 | /// Return a mutable reference to a segment. 69 | pub fn get_mut(&mut self, id: T::Id) -> &mut T { 70 | self.0.get_mut(id.index()).unwrap() 71 | } 72 | 73 | /// Return an iterator for the segments. 74 | pub fn iter(&self) -> TableIter<'_, T> { 75 | self.into_iter() 76 | } 77 | 78 | /// Return a mutable iterator for the segments. 79 | pub fn iter_mut(&mut self) -> TableIterMut<'_, T> { 80 | self.into_iter() 81 | } 82 | } 83 | 84 | impl<'a, T: Item> IntoIterator for &'a Table { 85 | type Item = &'a T; 86 | type IntoIter = TableIter<'a, T>; 87 | fn into_iter(self) -> TableIter<'a, T> { 88 | TableIter { 89 | iter: self.0.iter(), 90 | } 91 | } 92 | } 93 | 94 | impl<'a, T: Item> IntoIterator for &'a mut Table { 95 | type Item = &'a mut T; 96 | type IntoIter = TableIterMut<'a, T>; 97 | fn into_iter(self) -> TableIterMut<'a, T> { 98 | TableIterMut { 99 | iter: self.0.iter_mut(), 100 | } 101 | } 102 | } 103 | 104 | /// An iterator for non-deleted items in a [`Table`]. 105 | #[derive(Debug)] 106 | pub struct TableIter<'a, T> { 107 | iter: core::slice::Iter<'a, T>, 108 | } 109 | 110 | impl<'a, T: Item> Iterator for TableIter<'a, T> { 111 | type Item = &'a T; 112 | fn next(&mut self) -> Option<&'a T> { 113 | self.iter.find(|item| !item.is_deleted()) 114 | } 115 | } 116 | 117 | /// An iterator for non-deleted items in a [`Table`]. 118 | #[derive(Debug)] 119 | pub struct TableIterMut<'a, T> { 120 | iter: core::slice::IterMut<'a, T>, 121 | } 122 | 123 | impl<'a, T: Item> Iterator for TableIterMut<'a, T> { 124 | type Item = &'a mut T; 125 | fn next(&mut self) -> Option<&'a mut T> { 126 | self.iter.find(|item| !item.is_deleted()) 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # `object` 2 | //! 3 | //! The `object` crate provides a unified interface to working with object files 4 | //! across platforms. It supports reading relocatable object files and executable files, 5 | //! and writing relocatable object files and some executable files. 6 | //! 7 | //! ## Raw struct definitions 8 | //! 9 | //! Raw structs are defined for: [ELF](elf), [Mach-O](macho), [PE/COFF](pe), 10 | //! [XCOFF](xcoff), [archive]. 11 | //! Types and traits for zerocopy support are defined in the [`pod`] and [`endian`] modules. 12 | //! 13 | //! ## Unified read API 14 | //! 15 | //! The [`read`] module provides a unified read API using the [`read::Object`] trait. 16 | //! There is an implementation of this trait for [`read::File`], which allows reading any 17 | //! file format, as well as implementations for each file format. 18 | //! 19 | //! ## Low level read API 20 | //! 21 | //! The [`read#modules`] submodules define helpers that operate on the raw structs. 22 | //! These can be used instead of the unified API, or in conjunction with it to access 23 | //! details that are not available via the unified API. 24 | //! 25 | //! ## Unified write API 26 | //! 27 | //! The [`mod@write`] module provides a unified write API for relocatable object files 28 | //! using [`write::Object`]. This does not support writing executable files. 29 | //! 30 | //! ## Low level write API 31 | //! 32 | //! The [`mod@write#modules`] submodules define helpers for writing the raw structs. 33 | //! 34 | //! ## Build API 35 | //! 36 | //! The [`mod@build`] submodules define helpers for building object files, either from 37 | //! scratch or by modifying existing files. 38 | //! 39 | //! ## Shared definitions 40 | //! 41 | //! The crate provides a number of definitions that are used by both the read and write 42 | //! APIs. These are defined at the top level module, but none of these are the main entry 43 | //! points of the crate. 44 | 45 | #![deny(missing_docs)] 46 | #![deny(missing_debug_implementations)] 47 | #![no_std] 48 | #![warn(rust_2018_idioms)] 49 | // Style. 50 | #![allow(clippy::collapsible_else_if)] 51 | #![allow(clippy::collapsible_if)] 52 | #![allow(clippy::collapsible_match)] 53 | #![allow(clippy::comparison_chain)] 54 | #![allow(clippy::field_reassign_with_default)] 55 | #![allow(clippy::manual_flatten)] 56 | #![allow(clippy::match_like_matches_macro)] 57 | #![allow(clippy::needless_lifetimes)] 58 | #![allow(clippy::single_match)] 59 | #![allow(clippy::type_complexity)] 60 | // Occurs due to fallible iteration. 61 | #![allow(clippy::should_implement_trait)] 62 | // Unit errors are converted to other types by callers. 63 | #![allow(clippy::result_unit_err)] 64 | 65 | #[cfg(feature = "cargo-all")] 66 | compile_error!("'--all-features' is not supported; use '--features all' instead"); 67 | 68 | #[cfg(any(feature = "read_core", feature = "write_core"))] 69 | #[allow(unused_imports)] 70 | #[macro_use] 71 | extern crate alloc; 72 | 73 | #[cfg(feature = "std")] 74 | #[allow(unused_imports)] 75 | #[macro_use] 76 | extern crate std; 77 | 78 | mod common; 79 | pub use common::*; 80 | 81 | #[macro_use] 82 | pub mod endian; 83 | pub use endian::*; 84 | 85 | #[macro_use] 86 | pub mod pod; 87 | pub use pod::*; 88 | 89 | #[cfg(feature = "read_core")] 90 | pub mod read; 91 | #[cfg(feature = "read_core")] 92 | pub use read::*; 93 | 94 | #[cfg(feature = "write_core")] 95 | pub mod write; 96 | 97 | #[cfg(feature = "build_core")] 98 | pub mod build; 99 | 100 | #[cfg(feature = "archive")] 101 | pub mod archive; 102 | #[cfg(feature = "elf")] 103 | pub mod elf; 104 | #[cfg(feature = "macho")] 105 | pub mod macho; 106 | #[cfg(any(feature = "coff", feature = "pe"))] 107 | pub mod pe; 108 | #[cfg(feature = "xcoff")] 109 | pub mod xcoff; 110 | -------------------------------------------------------------------------------- /src/read/coff/mod.rs: -------------------------------------------------------------------------------- 1 | //! Support for reading Windows COFF files. 2 | //! 3 | //! Traits are used to abstract over the difference between COFF object files 4 | //! and COFF bigobj files. The primary trait for this is [`CoffHeader`]. 5 | //! 6 | //! ## High level API 7 | //! 8 | //! [`CoffFile`] implements the [`Object`](crate::read::Object) trait for 9 | //! COFF files. [`CoffFile`] is parameterised by [`CoffHeader`]. 10 | //! The default parameter allows reading regular COFF object files, 11 | //! while the type alias [`CoffBigFile`] allows reading COFF bigobj files. 12 | //! 13 | //! [`ImportFile`] allows reading COFF short imports that are used in import 14 | //! libraries. Currently these are not integrated with the unified read API. 15 | //! 16 | //! ## Low level API 17 | //! 18 | //! The [`CoffHeader`] trait can be directly used to parse both COFF 19 | //! object files (which start with [`pe::ImageFileHeader`]) and COFF bigobj 20 | //! files (which start with [`pe::AnonObjectHeaderBigobj`]). 21 | //! 22 | //! ### Example for low level API 23 | //! ```no_run 24 | //! use object::pe; 25 | //! use object::read::coff::{CoffHeader, ImageSymbol as _}; 26 | //! use std::error::Error; 27 | //! use std::fs; 28 | //! 29 | //! /// Reads a file and displays the name of each section and symbol. 30 | //! fn main() -> Result<(), Box> { 31 | //! # #[cfg(feature = "std")] { 32 | //! let data = fs::read("path/to/binary")?; 33 | //! let mut offset = 0; 34 | //! let header = pe::ImageFileHeader::parse(&*data, &mut offset)?; 35 | //! let sections = header.sections(&*data, offset)?; 36 | //! let symbols = header.symbols(&*data)?; 37 | //! for section in sections.iter() { 38 | //! println!("{}", String::from_utf8_lossy(section.name(symbols.strings())?)); 39 | //! } 40 | //! for (_index, symbol) in symbols.iter() { 41 | //! println!("{}", String::from_utf8_lossy(symbol.name(symbols.strings())?)); 42 | //! } 43 | //! # } 44 | //! Ok(()) 45 | //! } 46 | //! ``` 47 | #[cfg(doc)] 48 | use crate::pe; 49 | 50 | mod file; 51 | pub use file::*; 52 | 53 | mod section; 54 | pub use section::*; 55 | 56 | mod symbol; 57 | pub use symbol::*; 58 | 59 | mod relocation; 60 | pub use relocation::*; 61 | 62 | mod comdat; 63 | pub use comdat::*; 64 | 65 | mod import; 66 | pub use import::*; 67 | -------------------------------------------------------------------------------- /src/read/elf/compression.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::Debug; 2 | 3 | use crate::elf; 4 | use crate::endian; 5 | use crate::pod::Pod; 6 | 7 | /// A trait for generic access to [`elf::CompressionHeader32`] and [`elf::CompressionHeader64`]. 8 | #[allow(missing_docs)] 9 | pub trait CompressionHeader: Debug + Pod { 10 | type Word: Into; 11 | type Endian: endian::Endian; 12 | 13 | fn ch_type(&self, endian: Self::Endian) -> u32; 14 | fn ch_size(&self, endian: Self::Endian) -> Self::Word; 15 | fn ch_addralign(&self, endian: Self::Endian) -> Self::Word; 16 | } 17 | 18 | impl CompressionHeader for elf::CompressionHeader32 { 19 | type Word = u32; 20 | type Endian = Endian; 21 | 22 | #[inline] 23 | fn ch_type(&self, endian: Self::Endian) -> u32 { 24 | self.ch_type.get(endian) 25 | } 26 | 27 | #[inline] 28 | fn ch_size(&self, endian: Self::Endian) -> Self::Word { 29 | self.ch_size.get(endian) 30 | } 31 | 32 | #[inline] 33 | fn ch_addralign(&self, endian: Self::Endian) -> Self::Word { 34 | self.ch_addralign.get(endian) 35 | } 36 | } 37 | 38 | impl CompressionHeader for elf::CompressionHeader64 { 39 | type Word = u64; 40 | type Endian = Endian; 41 | 42 | #[inline] 43 | fn ch_type(&self, endian: Self::Endian) -> u32 { 44 | self.ch_type.get(endian) 45 | } 46 | 47 | #[inline] 48 | fn ch_size(&self, endian: Self::Endian) -> Self::Word { 49 | self.ch_size.get(endian) 50 | } 51 | 52 | #[inline] 53 | fn ch_addralign(&self, endian: Self::Endian) -> Self::Word { 54 | self.ch_addralign.get(endian) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/read/elf/dynamic.rs: -------------------------------------------------------------------------------- 1 | use core::convert::TryInto; 2 | use core::fmt::Debug; 3 | 4 | use crate::elf; 5 | use crate::endian; 6 | use crate::pod::Pod; 7 | use crate::read::{ReadError, Result, StringTable}; 8 | 9 | /// A trait for generic access to [`elf::Dyn32`] and [`elf::Dyn64`]. 10 | #[allow(missing_docs)] 11 | pub trait Dyn: Debug + Pod { 12 | type Word: Into; 13 | type Endian: endian::Endian; 14 | 15 | fn d_tag(&self, endian: Self::Endian) -> Self::Word; 16 | fn d_val(&self, endian: Self::Endian) -> Self::Word; 17 | 18 | /// Try to convert the tag to a `u32`. 19 | fn tag32(&self, endian: Self::Endian) -> Option { 20 | self.d_tag(endian).into().try_into().ok() 21 | } 22 | 23 | /// Try to convert the value to a `u32`. 24 | fn val32(&self, endian: Self::Endian) -> Option { 25 | self.d_val(endian).into().try_into().ok() 26 | } 27 | 28 | /// Return true if the value is an offset in the dynamic string table. 29 | fn is_string(&self, endian: Self::Endian) -> bool { 30 | if let Some(tag) = self.tag32(endian) { 31 | match tag { 32 | elf::DT_NEEDED 33 | | elf::DT_SONAME 34 | | elf::DT_RPATH 35 | | elf::DT_RUNPATH 36 | | elf::DT_AUXILIARY 37 | | elf::DT_FILTER => true, 38 | _ => false, 39 | } 40 | } else { 41 | false 42 | } 43 | } 44 | 45 | /// Use the value to get a string in a string table. 46 | /// 47 | /// Does not check for an appropriate tag. 48 | fn string<'data>( 49 | &self, 50 | endian: Self::Endian, 51 | strings: StringTable<'data>, 52 | ) -> Result<&'data [u8]> { 53 | self.val32(endian) 54 | .and_then(|val| strings.get(val).ok()) 55 | .read_error("Invalid ELF dyn string") 56 | } 57 | 58 | /// Return true if the value is an address. 59 | fn is_address(&self, endian: Self::Endian) -> bool { 60 | if let Some(tag) = self.tag32(endian) { 61 | match tag { 62 | elf::DT_PLTGOT 63 | | elf::DT_HASH 64 | | elf::DT_STRTAB 65 | | elf::DT_SYMTAB 66 | | elf::DT_RELA 67 | | elf::DT_INIT 68 | | elf::DT_FINI 69 | | elf::DT_SYMBOLIC 70 | | elf::DT_REL 71 | | elf::DT_DEBUG 72 | | elf::DT_JMPREL 73 | | elf::DT_FINI_ARRAY 74 | | elf::DT_INIT_ARRAY 75 | | elf::DT_PREINIT_ARRAY 76 | | elf::DT_SYMTAB_SHNDX 77 | | elf::DT_VERDEF 78 | | elf::DT_VERNEED 79 | | elf::DT_VERSYM 80 | | elf::DT_ADDRRNGLO..=elf::DT_ADDRRNGHI => true, 81 | _ => false, 82 | } 83 | } else { 84 | false 85 | } 86 | } 87 | } 88 | 89 | impl Dyn for elf::Dyn32 { 90 | type Word = u32; 91 | type Endian = Endian; 92 | 93 | #[inline] 94 | fn d_tag(&self, endian: Self::Endian) -> Self::Word { 95 | self.d_tag.get(endian) 96 | } 97 | 98 | #[inline] 99 | fn d_val(&self, endian: Self::Endian) -> Self::Word { 100 | self.d_val.get(endian) 101 | } 102 | } 103 | 104 | impl Dyn for elf::Dyn64 { 105 | type Word = u64; 106 | type Endian = Endian; 107 | 108 | #[inline] 109 | fn d_tag(&self, endian: Self::Endian) -> Self::Word { 110 | self.d_tag.get(endian) 111 | } 112 | 113 | #[inline] 114 | fn d_val(&self, endian: Self::Endian) -> Self::Word { 115 | self.d_val.get(endian) 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/read/elf/mod.rs: -------------------------------------------------------------------------------- 1 | //! Support for reading ELF files. 2 | //! 3 | //! Traits are used to abstract over the difference between 32-bit and 64-bit ELF. 4 | //! The primary trait for this is [`FileHeader`]. 5 | //! 6 | //! ## High level API 7 | //! 8 | //! [`ElfFile`] implements the [`Object`](crate::read::Object) trait for ELF files. 9 | //! [`ElfFile`] is parameterised by [`FileHeader`] to allow reading both 32-bit and 10 | //! 64-bit ELF. There are type aliases for these parameters ([`ElfFile32`] and 11 | //! [`ElfFile64`]). 12 | //! 13 | //! ## Low level API 14 | //! 15 | //! The [`FileHeader`] trait can be directly used to parse both [`elf::FileHeader32`] 16 | //! and [`elf::FileHeader64`]. 17 | //! 18 | //! ### Example for low level API 19 | //! ```no_run 20 | //! use object::elf; 21 | //! use object::read::elf::{FileHeader, Sym}; 22 | //! use std::error::Error; 23 | //! use std::fs; 24 | //! 25 | //! /// Reads a file and displays the name of each symbol. 26 | //! fn main() -> Result<(), Box> { 27 | //! # #[cfg(feature = "std")] { 28 | //! let data = fs::read("path/to/binary")?; 29 | //! let elf = elf::FileHeader64::::parse(&*data)?; 30 | //! let endian = elf.endian()?; 31 | //! let sections = elf.sections(endian, &*data)?; 32 | //! let symbols = sections.symbols(endian, &*data, elf::SHT_SYMTAB)?; 33 | //! for symbol in symbols.iter() { 34 | //! let name = symbol.name(endian, symbols.strings())?; 35 | //! println!("{}", String::from_utf8_lossy(name)); 36 | //! } 37 | //! # } 38 | //! Ok(()) 39 | //! } 40 | //! ``` 41 | #[cfg(doc)] 42 | use crate::elf; 43 | 44 | mod file; 45 | pub use file::*; 46 | 47 | mod segment; 48 | pub use segment::*; 49 | 50 | mod section; 51 | pub use section::*; 52 | 53 | mod symbol; 54 | pub use symbol::*; 55 | 56 | mod relocation; 57 | pub use relocation::*; 58 | 59 | mod comdat; 60 | pub use comdat::*; 61 | 62 | mod dynamic; 63 | pub use dynamic::*; 64 | 65 | mod compression; 66 | pub use compression::*; 67 | 68 | mod note; 69 | pub use note::*; 70 | 71 | mod hash; 72 | pub use hash::*; 73 | 74 | mod version; 75 | pub use version::*; 76 | 77 | mod attributes; 78 | pub use attributes::*; 79 | -------------------------------------------------------------------------------- /src/read/gnu_compression.rs: -------------------------------------------------------------------------------- 1 | use crate::read::{self, Error, ReadError as _}; 2 | use crate::{endian, CompressedFileRange, CompressionFormat, ReadRef, U32Bytes}; 3 | 4 | // Attempt to parse the the CompressedFileRange for a section using the GNU-style 5 | // inline compression header format. This is used by the Go compiler in Mach-O files 6 | // as well as by the GNU linker in some ELF files. 7 | pub(super) fn compressed_file_range<'data, R: ReadRef<'data>>( 8 | file_data: R, 9 | section_offset: u64, 10 | section_size: u64, 11 | ) -> read::Result { 12 | let mut offset = section_offset; 13 | // Assume ZLIB-style uncompressed data is no more than 4GB to avoid accidentally 14 | // huge allocations. This also reduces the chance of accidentally matching on a 15 | // .debug_str that happens to start with "ZLIB". 16 | let header = file_data 17 | .read_bytes(&mut offset, 8) 18 | .read_error("GNU compressed section is too short")?; 19 | if header != b"ZLIB\0\0\0\0" { 20 | return Err(Error("Invalid GNU compressed section header")); 21 | } 22 | let uncompressed_size = file_data 23 | .read::>(&mut offset) 24 | .read_error("GNU compressed section is too short")? 25 | .get(endian::BigEndian) 26 | .into(); 27 | let compressed_size = section_size 28 | .checked_sub(offset - section_offset) 29 | .read_error("GNU compressed section is too short")?; 30 | Ok(CompressedFileRange { 31 | format: CompressionFormat::Zlib, 32 | offset, 33 | compressed_size, 34 | uncompressed_size, 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /src/read/macho/fat.rs: -------------------------------------------------------------------------------- 1 | use crate::endian::BigEndian; 2 | use crate::macho; 3 | use crate::pod::Pod; 4 | use crate::read::{Architecture, Error, ReadError, ReadRef, Result}; 5 | 6 | pub use macho::{FatArch32, FatArch64, FatHeader}; 7 | 8 | /// A 32-bit Mach-O universal binary. 9 | /// 10 | /// This is a file that starts with [`macho::FatHeader`], and corresponds 11 | /// to [`crate::FileKind::MachOFat32`]. 12 | pub type MachOFatFile32<'data> = MachOFatFile<'data, macho::FatArch32>; 13 | 14 | /// A 64-bit Mach-O universal binary. 15 | /// 16 | /// This is a file that starts with [`macho::FatHeader`], and corresponds 17 | /// to [`crate::FileKind::MachOFat64`]. 18 | pub type MachOFatFile64<'data> = MachOFatFile<'data, macho::FatArch64>; 19 | 20 | /// A Mach-O universal binary. 21 | /// 22 | /// This is a file that starts with [`macho::FatHeader`], and corresponds 23 | /// to [`crate::FileKind::MachOFat32`] or [`crate::FileKind::MachOFat64`]. 24 | #[derive(Debug, Clone)] 25 | pub struct MachOFatFile<'data, Fat: FatArch> { 26 | header: &'data macho::FatHeader, 27 | arches: &'data [Fat], 28 | } 29 | 30 | impl<'data, Fat: FatArch> MachOFatFile<'data, Fat> { 31 | /// Attempt to parse the fat header and fat arches. 32 | pub fn parse>(data: R) -> Result { 33 | let mut offset = 0; 34 | let header = data 35 | .read::(&mut offset) 36 | .read_error("Invalid fat header size or alignment")?; 37 | if header.magic.get(BigEndian) != Fat::MAGIC { 38 | return Err(Error("Invalid fat magic")); 39 | } 40 | let arches = data 41 | .read_slice::(&mut offset, header.nfat_arch.get(BigEndian) as usize) 42 | .read_error("Invalid nfat_arch")?; 43 | Ok(MachOFatFile { header, arches }) 44 | } 45 | 46 | /// Return the fat header 47 | pub fn header(&self) -> &'data macho::FatHeader { 48 | self.header 49 | } 50 | 51 | /// Return the array of fat arches. 52 | pub fn arches(&self) -> &'data [Fat] { 53 | self.arches 54 | } 55 | } 56 | 57 | /// A trait for generic access to [`macho::FatArch32`] and [`macho::FatArch64`]. 58 | #[allow(missing_docs)] 59 | pub trait FatArch: Pod { 60 | type Word: Into; 61 | const MAGIC: u32; 62 | 63 | fn cputype(&self) -> u32; 64 | fn cpusubtype(&self) -> u32; 65 | fn offset(&self) -> Self::Word; 66 | fn size(&self) -> Self::Word; 67 | fn align(&self) -> u32; 68 | 69 | fn architecture(&self) -> Architecture { 70 | match self.cputype() { 71 | macho::CPU_TYPE_ARM => Architecture::Arm, 72 | macho::CPU_TYPE_ARM64 => Architecture::Aarch64, 73 | macho::CPU_TYPE_X86 => Architecture::I386, 74 | macho::CPU_TYPE_X86_64 => Architecture::X86_64, 75 | macho::CPU_TYPE_MIPS => Architecture::Mips, 76 | macho::CPU_TYPE_POWERPC => Architecture::PowerPc, 77 | macho::CPU_TYPE_POWERPC64 => Architecture::PowerPc64, 78 | _ => Architecture::Unknown, 79 | } 80 | } 81 | 82 | fn file_range(&self) -> (u64, u64) { 83 | (self.offset().into(), self.size().into()) 84 | } 85 | 86 | fn data<'data, R: ReadRef<'data>>(&self, file: R) -> Result<&'data [u8]> { 87 | file.read_bytes_at(self.offset().into(), self.size().into()) 88 | .read_error("Invalid fat arch offset or size") 89 | } 90 | } 91 | 92 | impl FatArch for FatArch32 { 93 | type Word = u32; 94 | const MAGIC: u32 = macho::FAT_MAGIC; 95 | 96 | fn cputype(&self) -> u32 { 97 | self.cputype.get(BigEndian) 98 | } 99 | 100 | fn cpusubtype(&self) -> u32 { 101 | self.cpusubtype.get(BigEndian) 102 | } 103 | 104 | fn offset(&self) -> Self::Word { 105 | self.offset.get(BigEndian) 106 | } 107 | 108 | fn size(&self) -> Self::Word { 109 | self.size.get(BigEndian) 110 | } 111 | 112 | fn align(&self) -> u32 { 113 | self.align.get(BigEndian) 114 | } 115 | } 116 | 117 | impl FatArch for FatArch64 { 118 | type Word = u64; 119 | const MAGIC: u32 = macho::FAT_MAGIC_64; 120 | 121 | fn cputype(&self) -> u32 { 122 | self.cputype.get(BigEndian) 123 | } 124 | 125 | fn cpusubtype(&self) -> u32 { 126 | self.cpusubtype.get(BigEndian) 127 | } 128 | 129 | fn offset(&self) -> Self::Word { 130 | self.offset.get(BigEndian) 131 | } 132 | 133 | fn size(&self) -> Self::Word { 134 | self.size.get(BigEndian) 135 | } 136 | 137 | fn align(&self) -> u32 { 138 | self.align.get(BigEndian) 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/read/macho/mod.rs: -------------------------------------------------------------------------------- 1 | //! Support for reading Mach-O files. 2 | //! 3 | //! Traits are used to abstract over the difference between 32-bit and 64-bit Mach-O 4 | //! files. The primary trait for this is [`MachHeader`]. 5 | //! 6 | //! ## High level API 7 | //! 8 | //! [`MachOFile`] implements the [`Object`](crate::read::Object) trait for Mach-O files. 9 | //! [`MachOFile`] is parameterised by [`MachHeader`] to allow reading both 32-bit and 10 | //! 64-bit Mach-O files. There are type aliases for these parameters ([`MachOFile32`] and 11 | //! [`MachOFile64`]). 12 | //! 13 | //! ## Low level API 14 | //! 15 | //! The [`MachHeader`] trait can be directly used to parse both [`macho::MachHeader32`] 16 | //! and [`macho::MachHeader64`]. Additionally, [`FatHeader`] and the [`FatArch`] trait 17 | //! can be used to iterate images in multi-architecture binaries, and [`DyldCache`] can 18 | //! be used to locate images in a dyld shared cache. 19 | //! 20 | //! ### Example for low level API 21 | //! ```no_run 22 | //! use object::macho; 23 | //! use object::read::macho::{MachHeader, Nlist}; 24 | //! use std::error::Error; 25 | //! use std::fs; 26 | //! 27 | //! /// Reads a file and displays the name of each symbol. 28 | //! fn main() -> Result<(), Box> { 29 | //! # #[cfg(feature = "std")] { 30 | //! let data = fs::read("path/to/binary")?; 31 | //! let header = macho::MachHeader64::::parse(&*data, 0)?; 32 | //! let endian = header.endian()?; 33 | //! let mut commands = header.load_commands(endian, &*data, 0)?; 34 | //! while let Some(command) = commands.next()? { 35 | //! if let Some(symtab_command) = command.symtab()? { 36 | //! let symbols = symtab_command.symbols::, _>(endian, &*data)?; 37 | //! for symbol in symbols.iter() { 38 | //! let name = symbol.name(endian, symbols.strings())?; 39 | //! println!("{}", String::from_utf8_lossy(name)); 40 | //! } 41 | //! } 42 | //! } 43 | //! # } 44 | //! Ok(()) 45 | //! } 46 | //! ``` 47 | #[cfg(doc)] 48 | use crate::macho; 49 | 50 | mod dyld_cache; 51 | pub use dyld_cache::*; 52 | 53 | mod fat; 54 | pub use fat::*; 55 | 56 | mod file; 57 | pub use file::*; 58 | 59 | mod load_command; 60 | pub use load_command::*; 61 | 62 | mod segment; 63 | pub use segment::*; 64 | 65 | mod section; 66 | pub use section::*; 67 | 68 | mod symbol; 69 | pub use symbol::*; 70 | 71 | mod relocation; 72 | pub use relocation::*; 73 | -------------------------------------------------------------------------------- /src/read/pe/mod.rs: -------------------------------------------------------------------------------- 1 | //! Support for reading PE files. 2 | //! 3 | //! Traits are used to abstract over the difference between PE32 and PE32+. 4 | //! The primary trait for this is [`ImageNtHeaders`]. 5 | //! 6 | //! ## High level API 7 | //! 8 | //! [`PeFile`] implements the [`Object`](crate::read::Object) trait for 9 | //! PE files. [`PeFile`] is parameterised by [`ImageNtHeaders`] to allow 10 | //! reading both PE32 and PE32+. There are type aliases for these parameters 11 | //! ([`PeFile32`] and [`PeFile64`]). 12 | //! 13 | //! ## Low level API 14 | //! 15 | //! The [`ImageNtHeaders`] trait can be directly used to parse both 16 | //! [`pe::ImageNtHeaders32`] and [`pe::ImageNtHeaders64`]. 17 | //! 18 | //! ### Example for low level API 19 | //! ```no_run 20 | //! use object::pe; 21 | //! use object::read::pe::ImageNtHeaders; 22 | //! use std::error::Error; 23 | //! use std::fs; 24 | //! 25 | //! /// Reads a file and displays the name of each section. 26 | //! fn main() -> Result<(), Box> { 27 | //! # #[cfg(feature = "std")] { 28 | //! let data = fs::read("path/to/binary")?; 29 | //! let dos_header = pe::ImageDosHeader::parse(&*data)?; 30 | //! let mut offset = dos_header.nt_headers_offset().into(); 31 | //! let (nt_headers, data_directories) = pe::ImageNtHeaders64::parse(&*data, &mut offset)?; 32 | //! let sections = nt_headers.sections(&*data, offset)?; 33 | //! let symbols = nt_headers.symbols(&*data)?; 34 | //! for section in sections.iter() { 35 | //! println!("{}", String::from_utf8_lossy(section.name(symbols.strings())?)); 36 | //! } 37 | //! # } 38 | //! Ok(()) 39 | //! } 40 | //! ``` 41 | #[cfg(doc)] 42 | use crate::pe; 43 | 44 | mod file; 45 | pub use file::*; 46 | 47 | mod section; 48 | pub use section::*; 49 | 50 | mod data_directory; 51 | pub use data_directory::*; 52 | 53 | mod export; 54 | pub use export::*; 55 | 56 | mod import; 57 | pub use import::*; 58 | 59 | mod relocation; 60 | pub use relocation::*; 61 | 62 | mod resource; 63 | pub use resource::*; 64 | 65 | mod rich; 66 | pub use rich::*; 67 | 68 | pub use super::coff::{SectionTable, SymbolTable}; 69 | -------------------------------------------------------------------------------- /src/read/pe/relocation.rs: -------------------------------------------------------------------------------- 1 | use core::slice; 2 | 3 | use crate::endian::{LittleEndian as LE, U16}; 4 | use crate::pe; 5 | use crate::read::{Bytes, Error, ReadError, Result}; 6 | 7 | /// An iterator over the relocation blocks in the `.reloc` section of a PE file. 8 | /// 9 | /// Returned by [`DataDirectories::relocation_blocks`](super::DataDirectories::relocation_blocks). 10 | #[derive(Debug, Default, Clone, Copy)] 11 | pub struct RelocationBlockIterator<'data> { 12 | data: Bytes<'data>, 13 | } 14 | 15 | impl<'data> RelocationBlockIterator<'data> { 16 | /// Construct a new iterator from the data of the `.reloc` section. 17 | pub fn new(data: &'data [u8]) -> Self { 18 | RelocationBlockIterator { data: Bytes(data) } 19 | } 20 | 21 | /// Read the next relocation page. 22 | pub fn next(&mut self) -> Result>> { 23 | if self.data.is_empty() { 24 | return Ok(None); 25 | } 26 | 27 | let result = self.parse().map(Some); 28 | if result.is_err() { 29 | self.data = Bytes(&[]); 30 | } 31 | result 32 | } 33 | 34 | fn parse(&mut self) -> Result> { 35 | let header = self 36 | .data 37 | .read::() 38 | .read_error("Invalid PE reloc section size")?; 39 | let virtual_address = header.virtual_address.get(LE); 40 | let size = header.size_of_block.get(LE); 41 | if size <= 8 || size & 3 != 0 { 42 | return Err(Error("Invalid PE reloc block size")); 43 | } 44 | let count = (size - 8) / 2; 45 | let relocs = self 46 | .data 47 | .read_slice::>(count as usize) 48 | .read_error("Invalid PE reloc block size")? 49 | .iter(); 50 | Ok(RelocationIterator { 51 | virtual_address, 52 | size, 53 | relocs, 54 | }) 55 | } 56 | } 57 | 58 | impl<'data> Iterator for RelocationBlockIterator<'data> { 59 | type Item = Result>; 60 | 61 | fn next(&mut self) -> Option { 62 | self.next().transpose() 63 | } 64 | } 65 | 66 | /// An iterator of the relocations in a block in the `.reloc` section of a PE file. 67 | #[derive(Debug, Clone)] 68 | pub struct RelocationIterator<'data> { 69 | virtual_address: u32, 70 | size: u32, 71 | relocs: slice::Iter<'data, U16>, 72 | } 73 | 74 | impl<'data> RelocationIterator<'data> { 75 | /// Return the virtual address of the page that this block of relocations applies to. 76 | pub fn virtual_address(&self) -> u32 { 77 | self.virtual_address 78 | } 79 | 80 | /// Return the size in bytes of this block of relocations. 81 | pub fn size(&self) -> u32 { 82 | self.size 83 | } 84 | } 85 | 86 | impl<'data> Iterator for RelocationIterator<'data> { 87 | type Item = Relocation; 88 | 89 | fn next(&mut self) -> Option { 90 | loop { 91 | let reloc = self.relocs.next()?.get(LE); 92 | if reloc != 0 { 93 | return Some(Relocation { 94 | virtual_address: self.virtual_address.wrapping_add((reloc & 0xfff) as u32), 95 | typ: reloc >> 12, 96 | }); 97 | } 98 | } 99 | } 100 | } 101 | 102 | /// A relocation in the `.reloc` section of a PE file. 103 | #[derive(Debug, Default, Clone, Copy)] 104 | pub struct Relocation { 105 | /// The virtual address of the relocation. 106 | pub virtual_address: u32, 107 | /// One of the `pe::IMAGE_REL_BASED_*` constants. 108 | pub typ: u16, 109 | } 110 | -------------------------------------------------------------------------------- /src/read/pe/rich.rs: -------------------------------------------------------------------------------- 1 | //! PE rich header handling 2 | 3 | use core::mem; 4 | 5 | use crate::endian::{LittleEndian as LE, U32}; 6 | use crate::pe; 7 | use crate::pod::bytes_of_slice; 8 | use crate::read::{Bytes, ReadRef}; 9 | 10 | /// Parsed information about a Rich Header. 11 | #[derive(Debug, Clone, Copy)] 12 | pub struct RichHeaderInfo<'data> { 13 | /// The offset at which the rich header starts. 14 | pub offset: usize, 15 | /// The length (in bytes) of the rich header. 16 | /// 17 | /// This includes the payload, but also the 16-byte start sequence and the 18 | /// 8-byte final "Rich" and XOR key. 19 | pub length: usize, 20 | /// The XOR key used to mask the rich header. 21 | /// 22 | /// Unless the file has been tampered with, it should be equal to a checksum 23 | /// of the file header. 24 | pub xor_key: u32, 25 | masked_entries: &'data [pe::MaskedRichHeaderEntry], 26 | } 27 | 28 | /// A PE rich header entry after it has been unmasked. 29 | /// 30 | /// See [`pe::MaskedRichHeaderEntry`]. 31 | #[derive(Debug, Clone, Copy)] 32 | #[repr(C)] 33 | pub struct RichHeaderEntry { 34 | /// ID of the component. 35 | pub comp_id: u32, 36 | /// Number of times this component has been used when building this PE. 37 | pub count: u32, 38 | } 39 | 40 | impl<'data> RichHeaderInfo<'data> { 41 | /// Try to locate a rich header and its entries in the current PE file. 42 | pub fn parse>(data: R, nt_header_offset: u64) -> Option { 43 | // Locate the rich header, if any. 44 | // It ends with the "Rich" string and an XOR key, before the NT header. 45 | let data = data.read_bytes_at(0, nt_header_offset).map(Bytes).ok()?; 46 | let end_marker_offset = memmem(data.0, b"Rich", 4)?; 47 | let xor_key = *data.read_at::>(end_marker_offset + 4).ok()?; 48 | 49 | // It starts at the masked "DanS" string and 3 masked zeroes. 50 | let masked_start_marker = U32::new(LE, 0x536e_6144 ^ xor_key.get(LE)); 51 | let start_header = [masked_start_marker, xor_key, xor_key, xor_key]; 52 | let start_sequence = bytes_of_slice(&start_header); 53 | let start_marker_offset = memmem(&data.0[..end_marker_offset], start_sequence, 4)?; 54 | 55 | // Extract the items between the markers. 56 | let items_offset = start_marker_offset + start_sequence.len(); 57 | let items_len = end_marker_offset - items_offset; 58 | let item_count = items_len / mem::size_of::(); 59 | let items = data.read_slice_at(items_offset, item_count).ok()?; 60 | Some(RichHeaderInfo { 61 | offset: start_marker_offset, 62 | // Includes "Rich" marker and the XOR key. 63 | length: end_marker_offset - start_marker_offset + 8, 64 | xor_key: xor_key.get(LE), 65 | masked_entries: items, 66 | }) 67 | } 68 | 69 | /// Returns an iterator over the unmasked entries. 70 | pub fn unmasked_entries(&self) -> impl Iterator + 'data { 71 | let xor_key = self.xor_key; 72 | self.masked_entries 73 | .iter() 74 | .map(move |entry| RichHeaderEntry { 75 | comp_id: entry.masked_comp_id.get(LE) ^ xor_key, 76 | count: entry.masked_count.get(LE) ^ xor_key, 77 | }) 78 | } 79 | } 80 | 81 | /// Find the offset of the first occurrence of needle in the data. 82 | /// 83 | /// The offset must have the given alignment. 84 | fn memmem(data: &[u8], needle: &[u8], align: usize) -> Option { 85 | let mut offset = 0; 86 | loop { 87 | if data.get(offset..)?.get(..needle.len())? == needle { 88 | return Some(offset); 89 | } 90 | offset += align; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/read/xcoff/comdat.rs: -------------------------------------------------------------------------------- 1 | //! XCOFF doesn't support the COMDAT section. 2 | 3 | use core::fmt::Debug; 4 | 5 | use crate::read::{self, ComdatKind, ObjectComdat, ReadRef, Result, SectionIndex, SymbolIndex}; 6 | use crate::xcoff; 7 | 8 | use super::{FileHeader, XcoffFile}; 9 | 10 | /// An iterator for the COMDAT section groups in a [`XcoffFile32`](super::XcoffFile32). 11 | pub type XcoffComdatIterator32<'data, 'file, R = &'data [u8]> = 12 | XcoffComdatIterator<'data, 'file, xcoff::FileHeader32, R>; 13 | /// An iterator for the COMDAT section groups in a [`XcoffFile64`](super::XcoffFile64). 14 | pub type XcoffComdatIterator64<'data, 'file, R = &'data [u8]> = 15 | XcoffComdatIterator<'data, 'file, xcoff::FileHeader64, R>; 16 | 17 | /// An iterator for the COMDAT section groups in a [`XcoffFile`]. 18 | /// 19 | /// This is a stub that doesn't implement any functionality. 20 | #[derive(Debug)] 21 | pub struct XcoffComdatIterator<'data, 'file, Xcoff, R = &'data [u8]> 22 | where 23 | Xcoff: FileHeader, 24 | R: ReadRef<'data>, 25 | { 26 | #[allow(unused)] 27 | pub(crate) file: &'file XcoffFile<'data, Xcoff, R>, 28 | } 29 | 30 | impl<'data, 'file, Xcoff, R> Iterator for XcoffComdatIterator<'data, 'file, Xcoff, R> 31 | where 32 | Xcoff: FileHeader, 33 | R: ReadRef<'data>, 34 | { 35 | type Item = XcoffComdat<'data, 'file, Xcoff, R>; 36 | 37 | #[inline] 38 | fn next(&mut self) -> Option { 39 | None 40 | } 41 | } 42 | 43 | /// A COMDAT section group in a [`XcoffFile32`](super::XcoffFile32). 44 | pub type XcoffComdat32<'data, 'file, R = &'data [u8]> = 45 | XcoffComdat<'data, 'file, xcoff::FileHeader32, R>; 46 | 47 | /// A COMDAT section group in a [`XcoffFile64`](super::XcoffFile64). 48 | pub type XcoffComdat64<'data, 'file, R = &'data [u8]> = 49 | XcoffComdat<'data, 'file, xcoff::FileHeader64, R>; 50 | 51 | /// A COMDAT section group in a [`XcoffFile`]. 52 | /// 53 | /// This is a stub that doesn't implement any functionality. 54 | #[derive(Debug)] 55 | pub struct XcoffComdat<'data, 'file, Xcoff, R = &'data [u8]> 56 | where 57 | Xcoff: FileHeader, 58 | R: ReadRef<'data>, 59 | { 60 | #[allow(unused)] 61 | file: &'file XcoffFile<'data, Xcoff, R>, 62 | } 63 | 64 | impl<'data, 'file, Xcoff, R> read::private::Sealed for XcoffComdat<'data, 'file, Xcoff, R> 65 | where 66 | Xcoff: FileHeader, 67 | R: ReadRef<'data>, 68 | { 69 | } 70 | 71 | impl<'data, 'file, Xcoff, R> ObjectComdat<'data> for XcoffComdat<'data, 'file, Xcoff, R> 72 | where 73 | Xcoff: FileHeader, 74 | R: ReadRef<'data>, 75 | { 76 | type SectionIterator = XcoffComdatSectionIterator<'data, 'file, Xcoff, R>; 77 | 78 | #[inline] 79 | fn kind(&self) -> ComdatKind { 80 | unreachable!(); 81 | } 82 | 83 | #[inline] 84 | fn symbol(&self) -> SymbolIndex { 85 | unreachable!(); 86 | } 87 | 88 | #[inline] 89 | fn name_bytes(&self) -> Result<&'data [u8]> { 90 | unreachable!(); 91 | } 92 | 93 | #[inline] 94 | fn name(&self) -> Result<&'data str> { 95 | unreachable!(); 96 | } 97 | 98 | #[inline] 99 | fn sections(&self) -> Self::SectionIterator { 100 | unreachable!(); 101 | } 102 | } 103 | 104 | /// An iterator for the sections in a COMDAT section group in a [`XcoffFile32`](super::XcoffFile32). 105 | pub type XcoffComdatSectionIterator32<'data, 'file, R = &'data [u8]> = 106 | XcoffComdatSectionIterator<'data, 'file, xcoff::FileHeader32, R>; 107 | /// An iterator for the sections in a COMDAT section group in a [`XcoffFile64`](super::XcoffFile64). 108 | pub type XcoffComdatSectionIterator64<'data, 'file, R = &'data [u8]> = 109 | XcoffComdatSectionIterator<'data, 'file, xcoff::FileHeader64, R>; 110 | 111 | /// An iterator for the sections in a COMDAT section group in a [`XcoffFile`]. 112 | /// 113 | /// This is a stub that doesn't implement any functionality. 114 | #[derive(Debug)] 115 | pub struct XcoffComdatSectionIterator<'data, 'file, Xcoff, R = &'data [u8]> 116 | where 117 | Xcoff: FileHeader, 118 | R: ReadRef<'data>, 119 | { 120 | #[allow(unused)] 121 | file: &'file XcoffFile<'data, Xcoff, R>, 122 | } 123 | 124 | impl<'data, 'file, Xcoff, R> Iterator for XcoffComdatSectionIterator<'data, 'file, Xcoff, R> 125 | where 126 | Xcoff: FileHeader, 127 | R: ReadRef<'data>, 128 | { 129 | type Item = SectionIndex; 130 | 131 | fn next(&mut self) -> Option { 132 | None 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/read/xcoff/mod.rs: -------------------------------------------------------------------------------- 1 | //! Support for reading AIX XCOFF files. 2 | //! 3 | //! Traits are used to abstract over the difference between 32-bit and 64-bit XCOFF. 4 | //! The primary trait for this is [`FileHeader`]. 5 | //! 6 | //! ## High level API 7 | //! 8 | //! [`XcoffFile`] implements the [`Object`](crate::read::Object) trait for XCOFF files. 9 | //! [`XcoffFile`] is parameterised by [`FileHeader`] to allow reading both 32-bit and 10 | //! 64-bit XCOFF. There are type aliases for these parameters ([`XcoffFile32`] and 11 | //! [`XcoffFile64`]). 12 | //! 13 | //! ## Low level API 14 | //! 15 | //! The [`FileHeader`] trait can be directly used to parse both [`xcoff::FileHeader32`] 16 | //! and [`xcoff::FileHeader64`]. 17 | //! 18 | //! ### Example for low level API 19 | //! ```no_run 20 | //! use object::xcoff; 21 | //! use object::read::xcoff::{FileHeader, SectionHeader, Symbol}; 22 | //! use std::error::Error; 23 | //! use std::fs; 24 | //! 25 | //! /// Reads a file and displays the name of each section and symbol. 26 | //! fn main() -> Result<(), Box> { 27 | //! # #[cfg(feature = "std")] { 28 | //! let data = fs::read("path/to/binary")?; 29 | //! let mut offset = 0; 30 | //! let header = xcoff::FileHeader64::parse(&*data, &mut offset)?; 31 | //! let aux_header = header.aux_header(&*data, &mut offset)?; 32 | //! let sections = header.sections(&*data, &mut offset)?; 33 | //! let symbols = header.symbols(&*data)?; 34 | //! for section in sections.iter() { 35 | //! println!("{}", String::from_utf8_lossy(section.name())); 36 | //! } 37 | //! for (_index, symbol) in symbols.iter() { 38 | //! println!("{}", String::from_utf8_lossy(symbol.name(symbols.strings())?)); 39 | //! } 40 | //! # } 41 | //! Ok(()) 42 | //! } 43 | //! ``` 44 | #[cfg(doc)] 45 | use crate::xcoff; 46 | 47 | mod file; 48 | pub use file::*; 49 | 50 | mod section; 51 | pub use section::*; 52 | 53 | mod symbol; 54 | pub use symbol::*; 55 | 56 | mod relocation; 57 | pub use relocation::*; 58 | 59 | mod comdat; 60 | pub use comdat::*; 61 | 62 | mod segment; 63 | pub use segment::*; 64 | -------------------------------------------------------------------------------- /src/read/xcoff/relocation.rs: -------------------------------------------------------------------------------- 1 | use alloc::fmt; 2 | use core::fmt::Debug; 3 | use core::slice; 4 | 5 | use crate::endian::BigEndian as BE; 6 | use crate::pod::Pod; 7 | use crate::read::{ 8 | ReadRef, Relocation, RelocationEncoding, RelocationFlags, RelocationKind, RelocationTarget, 9 | SymbolIndex, 10 | }; 11 | use crate::xcoff; 12 | 13 | use super::{FileHeader, SectionHeader, XcoffFile}; 14 | 15 | /// An iterator for the relocations in an [`XcoffSection32`](super::XcoffSection32). 16 | pub type XcoffRelocationIterator32<'data, 'file, R = &'data [u8]> = 17 | XcoffRelocationIterator<'data, 'file, xcoff::FileHeader32, R>; 18 | /// An iterator for the relocations in an [`XcoffSection64`](super::XcoffSection64). 19 | pub type XcoffRelocationIterator64<'data, 'file, R = &'data [u8]> = 20 | XcoffRelocationIterator<'data, 'file, xcoff::FileHeader64, R>; 21 | 22 | /// An iterator for the relocations in an [`XcoffSection`](super::XcoffSection). 23 | pub struct XcoffRelocationIterator<'data, 'file, Xcoff, R = &'data [u8]> 24 | where 25 | Xcoff: FileHeader, 26 | R: ReadRef<'data>, 27 | { 28 | #[allow(unused)] 29 | pub(super) file: &'file XcoffFile<'data, Xcoff, R>, 30 | pub(super) relocations: 31 | slice::Iter<'data, <::SectionHeader as SectionHeader>::Rel>, 32 | } 33 | 34 | impl<'data, 'file, Xcoff, R> Iterator for XcoffRelocationIterator<'data, 'file, Xcoff, R> 35 | where 36 | Xcoff: FileHeader, 37 | R: ReadRef<'data>, 38 | { 39 | type Item = (u64, Relocation); 40 | 41 | fn next(&mut self) -> Option { 42 | self.relocations.next().map(|relocation| { 43 | let r_rtype = relocation.r_rtype(); 44 | let r_rsize = relocation.r_rsize(); 45 | let flags = RelocationFlags::Xcoff { r_rtype, r_rsize }; 46 | let encoding = RelocationEncoding::Generic; 47 | let (kind, addend) = match r_rtype { 48 | xcoff::R_POS 49 | | xcoff::R_RL 50 | | xcoff::R_RLA 51 | | xcoff::R_BA 52 | | xcoff::R_RBA 53 | | xcoff::R_TLS => (RelocationKind::Absolute, 0), 54 | xcoff::R_REL | xcoff::R_BR | xcoff::R_RBR => (RelocationKind::Relative, -4), 55 | xcoff::R_TOC | xcoff::R_TOCL | xcoff::R_TOCU => (RelocationKind::Got, 0), 56 | _ => (RelocationKind::Unknown, 0), 57 | }; 58 | let size = (r_rsize & 0x3F) + 1; 59 | let target = RelocationTarget::Symbol(relocation.symbol()); 60 | ( 61 | relocation.r_vaddr().into(), 62 | Relocation { 63 | kind, 64 | encoding, 65 | size, 66 | target, 67 | addend, 68 | implicit_addend: true, 69 | flags, 70 | }, 71 | ) 72 | }) 73 | } 74 | } 75 | 76 | impl<'data, 'file, Xcoff, R> fmt::Debug for XcoffRelocationIterator<'data, 'file, Xcoff, R> 77 | where 78 | Xcoff: FileHeader, 79 | R: ReadRef<'data>, 80 | { 81 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 82 | f.debug_struct("XcoffRelocationIterator").finish() 83 | } 84 | } 85 | 86 | /// A trait for generic access to [`xcoff::Rel32`] and [`xcoff::Rel64`]. 87 | #[allow(missing_docs)] 88 | pub trait Rel: Debug + Pod { 89 | type Word: Into; 90 | fn r_vaddr(&self) -> Self::Word; 91 | fn r_symndx(&self) -> u32; 92 | fn r_rsize(&self) -> u8; 93 | fn r_rtype(&self) -> u8; 94 | 95 | fn symbol(&self) -> SymbolIndex { 96 | SymbolIndex(self.r_symndx() as usize) 97 | } 98 | } 99 | 100 | impl Rel for xcoff::Rel32 { 101 | type Word = u32; 102 | 103 | fn r_vaddr(&self) -> Self::Word { 104 | self.r_vaddr.get(BE) 105 | } 106 | 107 | fn r_symndx(&self) -> u32 { 108 | self.r_symndx.get(BE) 109 | } 110 | 111 | fn r_rsize(&self) -> u8 { 112 | self.r_rsize 113 | } 114 | 115 | fn r_rtype(&self) -> u8 { 116 | self.r_rtype 117 | } 118 | } 119 | 120 | impl Rel for xcoff::Rel64 { 121 | type Word = u64; 122 | 123 | fn r_vaddr(&self) -> Self::Word { 124 | self.r_vaddr.get(BE) 125 | } 126 | 127 | fn r_symndx(&self) -> u32 { 128 | self.r_symndx.get(BE) 129 | } 130 | 131 | fn r_rsize(&self) -> u8 { 132 | self.r_rsize 133 | } 134 | 135 | fn r_rtype(&self) -> u8 { 136 | self.r_rtype 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/read/xcoff/segment.rs: -------------------------------------------------------------------------------- 1 | //! TODO: Support the segment for XCOFF when auxiliary file header and loader section is ready. 2 | 3 | use core::fmt::Debug; 4 | use core::str; 5 | 6 | use crate::read::{self, ObjectSegment, ReadRef, Result, SegmentFlags}; 7 | use crate::xcoff; 8 | 9 | use super::{FileHeader, XcoffFile}; 10 | 11 | /// An iterator for the segments in an [`XcoffFile32`](super::XcoffFile32). 12 | pub type XcoffSegmentIterator32<'data, 'file, R = &'data [u8]> = 13 | XcoffSegmentIterator<'data, 'file, xcoff::FileHeader32, R>; 14 | /// An iterator for the segments in an [`XcoffFile64`](super::XcoffFile64). 15 | pub type XcoffSegmentIterator64<'data, 'file, R = &'data [u8]> = 16 | XcoffSegmentIterator<'data, 'file, xcoff::FileHeader64, R>; 17 | 18 | /// An iterator for the segments in an [`XcoffFile`]. 19 | /// 20 | /// This is a stub that doesn't implement any functionality. 21 | #[derive(Debug)] 22 | pub struct XcoffSegmentIterator<'data, 'file, Xcoff, R = &'data [u8]> 23 | where 24 | Xcoff: FileHeader, 25 | R: ReadRef<'data>, 26 | { 27 | #[allow(unused)] 28 | pub(super) file: &'file XcoffFile<'data, Xcoff, R>, 29 | } 30 | 31 | impl<'data, 'file, Xcoff, R> Iterator for XcoffSegmentIterator<'data, 'file, Xcoff, R> 32 | where 33 | Xcoff: FileHeader, 34 | R: ReadRef<'data>, 35 | { 36 | type Item = XcoffSegment<'data, 'file, Xcoff, R>; 37 | 38 | fn next(&mut self) -> Option { 39 | None 40 | } 41 | } 42 | 43 | /// A segment in an [`XcoffFile32`](super::XcoffFile32). 44 | pub type XcoffSegment32<'data, 'file, R = &'data [u8]> = 45 | XcoffSegment<'data, 'file, xcoff::FileHeader32, R>; 46 | /// A segment in an [`XcoffFile64`](super::XcoffFile64). 47 | pub type XcoffSegment64<'data, 'file, R = &'data [u8]> = 48 | XcoffSegment<'data, 'file, xcoff::FileHeader64, R>; 49 | 50 | /// A loadable section in an [`XcoffFile`]. 51 | /// 52 | /// This is a stub that doesn't implement any functionality. 53 | #[derive(Debug)] 54 | pub struct XcoffSegment<'data, 'file, Xcoff, R = &'data [u8]> 55 | where 56 | Xcoff: FileHeader, 57 | R: ReadRef<'data>, 58 | { 59 | #[allow(unused)] 60 | pub(super) file: &'file XcoffFile<'data, Xcoff, R>, 61 | } 62 | 63 | impl<'data, 'file, Xcoff, R> XcoffSegment<'data, 'file, Xcoff, R> 64 | where 65 | Xcoff: FileHeader, 66 | R: ReadRef<'data>, 67 | { 68 | } 69 | 70 | impl<'data, 'file, Xcoff, R> read::private::Sealed for XcoffSegment<'data, 'file, Xcoff, R> 71 | where 72 | Xcoff: FileHeader, 73 | R: ReadRef<'data>, 74 | { 75 | } 76 | 77 | impl<'data, 'file, Xcoff, R> ObjectSegment<'data> for XcoffSegment<'data, 'file, Xcoff, R> 78 | where 79 | Xcoff: FileHeader, 80 | R: ReadRef<'data>, 81 | { 82 | fn address(&self) -> u64 { 83 | unreachable!(); 84 | } 85 | 86 | fn size(&self) -> u64 { 87 | unreachable!(); 88 | } 89 | 90 | fn align(&self) -> u64 { 91 | unreachable!(); 92 | } 93 | 94 | fn file_range(&self) -> (u64, u64) { 95 | unreachable!(); 96 | } 97 | 98 | fn data(&self) -> Result<&'data [u8]> { 99 | unreachable!(); 100 | } 101 | 102 | fn data_range(&self, _address: u64, _size: u64) -> Result> { 103 | unreachable!(); 104 | } 105 | 106 | fn name_bytes(&self) -> Result> { 107 | unreachable!(); 108 | } 109 | 110 | fn name(&self) -> Result> { 111 | unreachable!(); 112 | } 113 | 114 | fn flags(&self) -> SegmentFlags { 115 | unreachable!(); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/write/coff/mod.rs: -------------------------------------------------------------------------------- 1 | //! Support for writing COFF files. 2 | //! 3 | //! Provides [`Writer`] for low level writing of COFF files. 4 | //! This is also used to provide COFF support for [`write::Object`](crate::write::Object). 5 | 6 | mod object; 7 | pub use self::object::*; 8 | 9 | mod writer; 10 | pub use writer::*; 11 | -------------------------------------------------------------------------------- /src/write/elf/mod.rs: -------------------------------------------------------------------------------- 1 | //! Support for writing ELF files. 2 | //! 3 | //! Provides [`Writer`] for low level writing of ELF files. 4 | //! This is also used to provide ELF support for [`write::Object`](crate::write::Object). 5 | 6 | mod object; 7 | 8 | mod writer; 9 | pub use writer::*; 10 | -------------------------------------------------------------------------------- /tests/build/mod.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "build")] 2 | 3 | mod elf; 4 | -------------------------------------------------------------------------------- /tests/integration.rs: -------------------------------------------------------------------------------- 1 | mod build; 2 | mod read; 3 | mod round_trip; 4 | -------------------------------------------------------------------------------- /tests/parse_self.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "read")] 2 | use object::{File, Object}; 3 | use std::{env, fs}; 4 | 5 | #[test] 6 | fn parse_self() { 7 | let exe = env::current_exe().unwrap(); 8 | let data = fs::read(exe).unwrap(); 9 | let object = File::parse(&*data).unwrap(); 10 | assert!(object.entry() != 0); 11 | assert!(object.sections().count() != 0); 12 | } 13 | 14 | #[cfg(feature = "std")] 15 | #[test] 16 | fn parse_self_cache() { 17 | use object::read::{ReadCache, ReadRef}; 18 | let exe = env::current_exe().unwrap(); 19 | let file = fs::File::open(exe).unwrap(); 20 | let cache = ReadCache::new(file); 21 | let data = cache.range(0, cache.len().unwrap()); 22 | let object = File::parse(data).unwrap(); 23 | assert!(object.entry() != 0); 24 | assert!(object.sections().count() != 0); 25 | } 26 | -------------------------------------------------------------------------------- /tests/read/coff.rs: -------------------------------------------------------------------------------- 1 | use object::{pe, read, Object, ObjectSection}; 2 | use std::fs; 3 | use std::path::PathBuf; 4 | 5 | #[cfg(feature = "coff")] 6 | #[test] 7 | fn coff_extended_relocations() { 8 | let path_to_obj: PathBuf = ["testfiles", "coff", "relocs_overflow.o"].iter().collect(); 9 | let contents = fs::read(path_to_obj).expect("Could not read relocs_overflow.o"); 10 | let file = 11 | read::coff::CoffFile::<_>::parse(&contents[..]).expect("Could not parse relocs_overflow.o"); 12 | let code_section = file 13 | .section_by_name(".text") 14 | .expect("Could not find .text section in relocs_overflow.o"); 15 | match code_section.flags() { 16 | object::SectionFlags::Coff { characteristics } => { 17 | assert!(characteristics & pe::IMAGE_SCN_LNK_NRELOC_OVFL != 0) 18 | } 19 | _ => panic!("Invalid section flags flavour."), 20 | }; 21 | let relocations = code_section.relocations().collect::>(); 22 | assert_eq!(relocations.len(), 65536); 23 | } 24 | -------------------------------------------------------------------------------- /tests/read/elf.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "std")] 2 | use std::path::{Path, PathBuf}; 3 | 4 | #[cfg(feature = "std")] 5 | fn get_buildid(path: &Path) -> Result>, object::read::Error> { 6 | use object::Object; 7 | let file = std::fs::File::open(path).unwrap(); 8 | let reader = object::read::ReadCache::new(file); 9 | let object = object::read::File::parse(&reader)?; 10 | object 11 | .build_id() 12 | .map(|option| option.map(ToOwned::to_owned)) 13 | } 14 | 15 | #[cfg(feature = "std")] 16 | #[test] 17 | /// Regression test: used to attempt to allocate 5644418395173552131 bytes 18 | fn get_buildid_bad_elf() { 19 | let path: PathBuf = [ 20 | "testfiles", 21 | "elf", 22 | "yara-fuzzing", 23 | "crash-7dc27920ae1cb85333e7f2735a45014488134673", 24 | ] 25 | .iter() 26 | .collect(); 27 | let _ = get_buildid(&path); 28 | } 29 | 30 | #[cfg(feature = "std")] 31 | #[test] 32 | fn get_buildid_less_bad_elf() { 33 | let path: PathBuf = [ 34 | "testfiles", 35 | "elf", 36 | "yara-fuzzing", 37 | "crash-f1fd008da535b110853885221ebfaac3f262a1c1e280f10929f7b353c44996c8", 38 | ] 39 | .iter() 40 | .collect(); 41 | let buildid = get_buildid(&path).unwrap().unwrap(); 42 | // ground truth obtained from GNU binutils's readelf 43 | assert_eq!( 44 | buildid, 45 | b"\xf9\xc0\xc6\x05\xd3\x76\xbb\xa5\x7e\x02\xf5\x74\x50\x9d\x16\xcc\xe9\x9c\x1b\xf1" 46 | ); 47 | } 48 | 49 | #[cfg(feature = "std")] 50 | #[test] 51 | fn zero_sized_section_works() { 52 | use object::{Object as _, ObjectSection as _}; 53 | let path: PathBuf = ["testfiles", "elf", "base.debug"].iter().collect(); 54 | let data = std::fs::read(&path).unwrap(); 55 | let object = object::read::File::parse(&data[..]).unwrap(); 56 | 57 | // The unwrap here should not fail, even though the section has an invalid offset, its size is 58 | // zero so this should succeed. 59 | let section = object.section_by_name(".bss").unwrap(); 60 | let data = section.data().unwrap(); 61 | assert_eq!(data.len(), 0); 62 | } 63 | -------------------------------------------------------------------------------- /tests/read/macho.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "std")] 2 | use object::{Object, ObjectSection as _}; 3 | 4 | // Test that we can read compressed sections in Mach-O files as produced 5 | // by the Go compiler. 6 | #[cfg(feature = "std")] 7 | #[test] 8 | fn test_go_macho() { 9 | let macho_testfiles = std::path::Path::new("testfiles/macho"); 10 | 11 | // Section names we expect to find, whether they should be 12 | // compressed, and the actual name of the section in the file. 13 | const EXPECTED: &[(&str, bool, &str)] = &[ 14 | (".debug_abbrev", true, "__zdebug_abbrev"), 15 | (".debug_gdb_scripts", false, "__debug_gdb_scri"), 16 | (".debug_ranges", true, "__zdebug_ranges"), 17 | ("__data", false, "__data"), 18 | ]; 19 | 20 | for file in &["go-aarch64", "go-x86_64"] { 21 | let path = macho_testfiles.join(file); 22 | let file = std::fs::File::open(path).unwrap(); 23 | let reader = object::read::ReadCache::new(file); 24 | let object = object::read::File::parse(&reader).unwrap(); 25 | for &(name, compressed, actual_name) in EXPECTED { 26 | let section = object.section_by_name(name).unwrap(); 27 | assert_eq!(section.name(), Ok(actual_name)); 28 | let compressed_file_range = section.compressed_file_range().unwrap(); 29 | let size = section.size(); 30 | if compressed { 31 | assert_eq!( 32 | compressed_file_range.format, 33 | object::CompressionFormat::Zlib 34 | ); 35 | assert_eq!(compressed_file_range.compressed_size, size - 12); 36 | assert!( 37 | compressed_file_range.uncompressed_size > compressed_file_range.compressed_size, 38 | "decompressed size is greater than compressed size" 39 | ); 40 | } else { 41 | assert_eq!( 42 | compressed_file_range.format, 43 | object::CompressionFormat::None 44 | ); 45 | assert_eq!(compressed_file_range.compressed_size, size); 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/read/mod.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "read")] 2 | 3 | mod coff; 4 | mod elf; 5 | mod macho; 6 | -------------------------------------------------------------------------------- /tests/round_trip/coff.rs: -------------------------------------------------------------------------------- 1 | use object::read::{Object, ObjectSection}; 2 | use object::{read, write}; 3 | use object::{ 4 | Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationFlags, RelocationKind, 5 | SymbolFlags, SymbolKind, SymbolScope, 6 | }; 7 | 8 | #[test] 9 | fn reloc_overflow() { 10 | let mut object = 11 | write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); 12 | let text = object.section_id(write::StandardSection::Text); 13 | object.append_section_data(text, &[0; 4], 4); 14 | let symbol = object.add_symbol(write::Symbol { 15 | name: b"f".to_vec(), 16 | value: 0, 17 | size: 4, 18 | kind: SymbolKind::Text, 19 | scope: SymbolScope::Linkage, 20 | weak: false, 21 | section: write::SymbolSection::Section(text), 22 | flags: SymbolFlags::None, 23 | }); 24 | for i in 0..0x10000 { 25 | object 26 | .add_relocation( 27 | text, 28 | write::Relocation { 29 | offset: i, 30 | symbol, 31 | addend: 0, 32 | flags: RelocationFlags::Generic { 33 | kind: RelocationKind::Absolute, 34 | encoding: RelocationEncoding::Generic, 35 | size: 64, 36 | }, 37 | }, 38 | ) 39 | .unwrap(); 40 | } 41 | let bytes = object.write().unwrap(); 42 | 43 | //std::fs::write(&"reloc_overflow.o", &bytes).unwrap(); 44 | 45 | let object = read::File::parse(&*bytes).unwrap(); 46 | assert_eq!(object.format(), BinaryFormat::Coff); 47 | assert_eq!(object.architecture(), Architecture::X86_64); 48 | 49 | let section = object.sections().next().unwrap(); 50 | assert_eq!(section.name(), Ok(".text")); 51 | 52 | let mut i = 0; 53 | for (offset, _relocation) in section.relocations() { 54 | assert_eq!(offset, i); 55 | i += 1; 56 | } 57 | assert_eq!(i, 0x10000); 58 | } 59 | -------------------------------------------------------------------------------- /tests/round_trip/macho.rs: -------------------------------------------------------------------------------- 1 | use object::read::macho::MachHeader; 2 | use object::read::{Object, ObjectSection}; 3 | use object::{macho, read, write, Architecture, BinaryFormat, Endianness}; 4 | 5 | // Test that segment size is valid when the first section needs alignment. 6 | #[test] 7 | fn issue_286_segment_file_size() { 8 | let mut object = write::Object::new( 9 | BinaryFormat::MachO, 10 | Architecture::X86_64, 11 | Endianness::Little, 12 | ); 13 | 14 | let text = object.section_id(write::StandardSection::Text); 15 | object.append_section_data(text, &[1; 30], 0x1000); 16 | 17 | let bytes = &*object.write().unwrap(); 18 | let header = macho::MachHeader64::parse(bytes, 0).unwrap(); 19 | let endian: Endianness = header.endian().unwrap(); 20 | let mut commands = header.load_commands(endian, bytes, 0).unwrap(); 21 | let command = commands.next().unwrap().unwrap(); 22 | let (segment, _) = command.segment_64().unwrap().unwrap(); 23 | assert_eq!(segment.vmsize.get(endian), 30); 24 | assert_eq!(segment.filesize.get(endian), 30); 25 | } 26 | 27 | // We were emitting section file alignment padding that didn't match the address alignment padding. 28 | #[test] 29 | fn issue_552_section_file_alignment() { 30 | let mut object = write::Object::new( 31 | BinaryFormat::MachO, 32 | Architecture::X86_64, 33 | Endianness::Little, 34 | ); 35 | 36 | // The starting file offset is not a multiple of 32 (checked later). 37 | // Length of 32 ensures that the file offset of the end of this section is still not a 38 | // multiple of 32. 39 | let section = object.add_section(vec![], vec![], object::SectionKind::ReadOnlyDataWithRel); 40 | object.append_section_data(section, &[0u8; 32], 1); 41 | 42 | // Address is already aligned correctly, so there must not any padding, 43 | // even though file offset is not aligned. 44 | let section = object.add_section(vec![], vec![], object::SectionKind::ReadOnlyData); 45 | object.append_section_data(section, &[0u8; 1], 32); 46 | 47 | let bytes = &*object.write().unwrap(); 48 | //std::fs::write(&"align.o", &bytes).unwrap(); 49 | let object = read::File::parse(bytes).unwrap(); 50 | let mut sections = object.sections(); 51 | 52 | let section = sections.next().unwrap(); 53 | let offset = section.file_range().unwrap().0; 54 | // Check file offset is not aligned to 32. 55 | assert_ne!(offset % 32, 0); 56 | assert_eq!(section.address(), 0); 57 | assert_eq!(section.size(), 32); 58 | 59 | let section = sections.next().unwrap(); 60 | // Check there is no padding. 61 | assert_eq!(section.file_range(), Some((offset + 32, 1))); 62 | assert_eq!(section.address(), 32); 63 | assert_eq!(section.size(), 1); 64 | } 65 | -------------------------------------------------------------------------------- /tests/round_trip/section_flags.rs: -------------------------------------------------------------------------------- 1 | #![cfg(all(feature = "read", feature = "write"))] 2 | 3 | use object::read::{Object, ObjectSection}; 4 | use object::{read, write}; 5 | use object::{Architecture, BinaryFormat, Endianness, SectionFlags, SectionKind}; 6 | 7 | #[test] 8 | fn coff_x86_64_section_flags() { 9 | let mut object = 10 | write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); 11 | 12 | let section = object.add_section(Vec::new(), b".text".to_vec(), SectionKind::Text); 13 | object.section_mut(section).flags = SectionFlags::Coff { 14 | characteristics: object::pe::IMAGE_SCN_MEM_WRITE, 15 | }; 16 | 17 | let bytes = object.write().unwrap(); 18 | 19 | let object = read::File::parse(&*bytes).unwrap(); 20 | assert_eq!(object.format(), BinaryFormat::Coff); 21 | assert_eq!(object.architecture(), Architecture::X86_64); 22 | 23 | let mut sections = object.sections(); 24 | let section = sections.next().unwrap(); 25 | assert_eq!(section.name(), Ok(".text")); 26 | assert_eq!( 27 | section.flags(), 28 | SectionFlags::Coff { 29 | characteristics: object::pe::IMAGE_SCN_MEM_WRITE | object::pe::IMAGE_SCN_ALIGN_1BYTES, 30 | } 31 | ); 32 | } 33 | 34 | #[test] 35 | fn elf_x86_64_section_flags() { 36 | let mut object = 37 | write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); 38 | 39 | let section = object.add_section(Vec::new(), b".text".to_vec(), SectionKind::Text); 40 | object.section_mut(section).flags = SectionFlags::Elf { 41 | sh_flags: object::elf::SHF_WRITE.into(), 42 | }; 43 | 44 | let bytes = object.write().unwrap(); 45 | 46 | let object = read::File::parse(&*bytes).unwrap(); 47 | assert_eq!(object.format(), BinaryFormat::Elf); 48 | assert_eq!(object.architecture(), Architecture::X86_64); 49 | 50 | let mut sections = object.sections(); 51 | let section = sections.next().unwrap(); 52 | assert_eq!(section.name(), Ok(".text")); 53 | assert_eq!( 54 | section.flags(), 55 | SectionFlags::Elf { 56 | sh_flags: object::elf::SHF_WRITE.into(), 57 | } 58 | ); 59 | } 60 | 61 | #[test] 62 | fn macho_x86_64_section_flags() { 63 | let mut object = write::Object::new( 64 | BinaryFormat::MachO, 65 | Architecture::X86_64, 66 | Endianness::Little, 67 | ); 68 | 69 | let section = object.add_section(Vec::new(), b".text".to_vec(), SectionKind::Text); 70 | object.section_mut(section).flags = SectionFlags::MachO { 71 | flags: object::macho::S_ATTR_SELF_MODIFYING_CODE, 72 | }; 73 | 74 | let bytes = object.write().unwrap(); 75 | 76 | let object = read::File::parse(&*bytes).unwrap(); 77 | assert_eq!(object.format(), BinaryFormat::MachO); 78 | assert_eq!(object.architecture(), Architecture::X86_64); 79 | 80 | let mut sections = object.sections(); 81 | let section = sections.next().unwrap(); 82 | assert_eq!(section.name(), Ok(".text")); 83 | assert_eq!( 84 | section.flags(), 85 | SectionFlags::MachO { 86 | flags: object::macho::S_ATTR_SELF_MODIFYING_CODE, 87 | } 88 | ); 89 | } 90 | -------------------------------------------------------------------------------- /xtask/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xtask" 3 | version = "0.0.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | 8 | [workspace] 9 | --------------------------------------------------------------------------------