compression_header.rs |
|
9207 |
constants_header.rs |
|
15902 |
constants_relocation.rs |
|
58259 |
dynamic.rs |
Reverse order! |
31242 |
gnu_hash.rs |
A Gnu Hash table as 4 sections:
1. Header
2. Bloom Filter
3. Hash Buckets
4. Chains
The header has is an array of four `u32`s:
1. nbuckets
2. symndx
3. maskwords
4. shift2
See more:
* <http://www.linker-aliens.org/blogs/ali/entry/gnu_hash_elf_sections>
or <https://blogs.oracle.com/solaris/gnu-hash-elf-sections-v2>
* <https://flapenguin.me/2017/05/10/elf-lookup-dt-gnu-hash/> |
9066 |
header.rs |
|
24372 |
mod.rs |
The generic ELF module, which gives access to ELF constants and other helper functions, which are independent of ELF bithood. Also defines an `Elf` struct which implements a unified parser that returns a wrapped `Elf64` or `Elf32` binary.
To access the exact 32-bit or 64-bit versions, use [goblin::elf32::Header](header/header32/struct.Header.html)/[goblin::elf64::Header](header/header64/struct.Header.html), etc., for the various 32/64-bit structs.
# Example
```rust
use std::fs::File;
pub fn read (bytes: &[u8]) {
match goblin::elf::Elf::parse(&bytes) {
Ok(binary) => {
let entry = binary.entry;
for ph in binary.program_headers {
if ph.p_type == goblin::elf::program_header::PT_LOAD {
// TODO: you should validate p_filesz before allocating.
let mut _buf = vec![0u8; ph.p_filesz as usize];
// read responsibly
}
}
},
Err(_) => ()
}
}
```
This will properly access the underlying 32-bit or 64-bit binary automatically. Note that since
32-bit binaries typically have shorter 32-bit values in some cases (specifically for addresses and pointer
values), these values are upcasted to u64/i64s when appropriate.
See [goblin::elf::Elf](struct.Elf.html) for more information.
You are still free to use the specific 32-bit or 64-bit versions by accessing them through `goblin::elf64`, etc., but you will have to parse and/or construct the various components yourself.
In other words, there is no unified 32/64-bit `Elf` struct.
# Note
To use the automagic ELF datatype union parser, you _must_ enable/opt-in to the `elf64`, `elf32`, and
`endian_fd` features if you disable `default`. |
23443 |
note.rs |
|
11073 |
program_header.rs |
Legal values for p_type (segment type). |
14799 |
reloc.rs |
# Relocation computations
The following notation is used to describe relocation computations
specific to x86_64 ELF.
* A: The addend used to compute the value of the relocatable field.
* B: The base address at which a shared object is loaded into memory
during execution. Generally, a shared object file is built with a
base virtual address of 0. However, the execution address of the
shared object is different.
* G: The offset into the global offset table at which the address of
the relocation entry's symbol resides during execution.
* GOT: The address of the global offset table.
* L: The section offset or address of the procedure linkage table entry
for a symbol.
* P: The section offset or address of the storage unit being relocated,
computed using r_offset.
* S: The value of the symbol whose index resides in the relocation entry.
* Z: The size of the symbol whose index resides in the relocation entry.
Below are some common x86_64 relocation computations you might find useful:
| Relocation | Value | Size | Formula |
|:--------------------------|:------|:----------|:------------------|
| `R_X86_64_NONE` | 0 | NONE | NONE |
| `R_X86_64_64` | 1 | 64 | S + A |
| `R_X86_64_PC32` | 2 | 32 | S + A - P |
| `R_X86_64_GOT32` | 3 | 32 | G + A |
| `R_X86_64_PLT32` | 4 | 32 | L + A - P |
| `R_X86_64_COPY` | 5 | NONE | NONE |
| `R_X86_64_GLOB_DAT` | 6 | 64 | S |
| `R_X86_64_JUMP_SLOT` | 7 | 64 | S |
| `R_X86_64_RELATIVE` | 8 | 64 | B + A |
| `R_X86_64_GOTPCREL` | 9 | 32 | G + GOT + A - P |
| `R_X86_64_32` | 10 | 32 | S + A |
| `R_X86_64_32S` | 11 | 32 | S + A |
| `R_X86_64_16` | 12 | 16 | S + A |
| `R_X86_64_PC16` | 13 | 16 | S + A - P |
| `R_X86_64_8` | 14 | 8 | S + A |
| `R_X86_64_PC8` | 15 | 8 | S + A - P |
| `R_X86_64_DTPMOD64` | 16 | 64 | |
| `R_X86_64_DTPOFF64` | 17 | 64 | |
| `R_X86_64_TPOFF64` | 18 | 64 | |
| `R_X86_64_TLSGD` | 19 | 32 | |
| `R_X86_64_TLSLD` | 20 | 32 | |
| `R_X86_64_DTPOFF32` | 21 | 32 | |
| `R_X86_64_GOTTPOFF` | 22 | 32 | |
| `R_X86_64_TPOFF32` | 23 | 32 | |
| `R_X86_64_PC64` | 24 | 64 | S + A - P |
| `R_X86_64_GOTOFF64` | 25 | 64 | S + A - GOT |
| `R_X86_64_GOTPC32` | 26 | 32 | GOT + A - P |
| `R_X86_64_SIZE32` | 32 | 32 | Z + A |
| `R_X86_64_SIZE64` | 33 | 64 | Z + A |
| `R_X86_64_GOTPC32_TLSDESC`| 34 | 32 | |
| `R_X86_64_TLSDESC_CALL` | 35 | NONE | |
| `R_X86_64_TLSDESC` | 36 | 64 × 2 | |
| `R_X86_64_IRELATIVE` | 37 | 64 | indirect (B + A) |
TLS information is at <http://people.redhat.com/aoliva/writeups/TLS/RFC-TLSDESC-x86.txt>
`R_X86_64_IRELATIVE` is similar to `R_X86_64_RELATIVE` except that
the value used in this relocation is the program address returned by the function,
which takes no arguments, at the address of the result of the corresponding
`R_X86_64_RELATIVE` relocation.
Read more <https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-54839.html> |
19379 |
section_header.rs |
|
21568 |
sym.rs |
|
18574 |
symver.rs |
Symbol versioning
Implementation of the GNU symbol versioning extension according to
[LSB Core Specification - Symbol Versioning][lsb-symver].
# Examples
List the dependencies of an ELF file that have [version needed][lsb-verneed] information along
with the versions needed for each dependency.
```rust
use goblin::error::Error;
pub fn show_verneed(bytes: &[u8]) -> Result<(), Error> {
let binary = goblin::elf::Elf::parse(&bytes)?;
if let Some(verneed) = binary.verneed {
for need_file in verneed.iter() {
println!(
"Depend on {:?} with version(s):",
binary.dynstrtab.get_at(need_file.vn_file)
);
for need_ver in need_file.iter() {
println!("{:?}", binary.dynstrtab.get_at(need_ver.vna_name));
}
}
}
Ok(())
}
```
List the [version defined][lsb-verdef] information of an ELF file, effectively listing the version
defined by this ELF file.
```rust
use goblin::error::Error;
pub fn show_verdef(bytes: &[u8]) -> Result<(), Error> {
let binary = goblin::elf::Elf::parse(&bytes)?;
if let Some(verdef) = &binary.verdef {
for def in verdef.iter() {
for (n, aux) in def.iter().enumerate() {
let name = binary.dynstrtab.get_at(aux.vda_name);
match n {
0 => print!("Name: {:?}", name),
1 => print!(" Parent: {:?}", name),
_ => print!(", {:?}", name),
}
}
print!("\n");
}
}
Ok(())
}
```
[lsb-symver]: https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/symversion.html
[lsb-verneed]: https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/symversion.html#SYMVERRQMTS
[lsb-verdef]: https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/symversion.html#SYMVERDEFS |
25897 |