A library for parsing and navigating ELF files.
- Pure Rust
- Zero allocation (minimal allocation for interpreting the data)
- Strongly, statically typed.
elf parser and navigation tool, pure Rust
License: Other
I don't think I use anything from std itself, just re-exports, but I might be wrong
Hi, I'm using your library for ELF executable parsing in my UEFI boot loader. I'm looking up the .bss section so I can zero it out, but the library is panicking instead:
[ERROR]: C:\Users\Visual\.cargo\registry\src\github.com-1ecc6299db9ec823\uefi-services-0.9.0\src\lib.rs@133: Panic in C:\Users\Visual\.cargo\registry\src\github.com-1ecc6299db9ec823\xmas-elf-0.8.0\src\lib.rs at (113, 25):
[ERROR]: C:\Users\Visual\.cargo\registry\src\github.com-1ecc6299db9ec823\uefi-services-0.9.0\src\lib.rs@140: range start index 3564710587087271204 out of range for slice of length 1033888
Related code:
let bss = elf
.find_section_by_name(".bss")
.expect("No .bss section found");
unsafe {
(bss.address() as *mut u8).write_bytes(0, bss.size().try_into().unwrap());
}
Linker script: https://gist.github.com/VisualDevelopment/70c6aa6bd1cf0558f3c18909682bfd03
We can't guarantee that the raw data is valid, so it's not safe to interpret it as an enum value. It should use a new type instead.
This is causing the interpret_class
test to fail when giving a value of 42u8
for the class.
I notice that this is already done for struct Type_
, with an enum Type
for the constants. Should the rest of the enums be converted to this style?
3617fa5 is now required to compile on nightly.
Running cargo +nightly miri test
causes the following error:
Preparing a sysroot for Miri (target: x86_64-unknown-linux-gnu)... done
Finished test [unoptimized + debuginfo] target(s) in 0.01s
Running unittests src/lib.rs (target/miri/x86_64-unknown-linux-gnu/debug/deps/xmas_elf-3090fb77e8659e43)
running 1 test
test test::interpret_class ... error: Undefined Behavior: constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
--> /home/freax13/.cargo/registry/src/github.com-1ecc6299db9ec823/zero-0.1.2/src/lib.rs:107:5
|
107 | mem::transmute(input as *const [u8] as *const u8 as *const T)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `zero::read_unsafe::<header::HeaderPt2_<u32>>` at /home/freax13/.cargo/registry/src/github.com-1ecc6299db9ec823/zero-0.1.2/src/lib.rs:107:5
= note: inside `zero::read::<header::HeaderPt2_<u32>>` at /home/freax13/.cargo/registry/src/github.com-1ecc6299db9ec823/zero-0.1.2/src/lib.rs:42:9
note: inside `header::parse_header` at src/header.rs:27:17
--> src/header.rs:27:17
|
27 | read(&input[size_pt1..size_pt1 + mem::size_of::<HeaderPt2_<P32>>()]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `ElfFile::<'_>::new` at src/lib.rs:50:22
--> src/lib.rs:50:22
|
50 | let header = header::parse_header(input)?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `test::interpret_class` at src/lib.rs:196:17
--> src/lib.rs:196:17
|
196 | assert!(ElfFile::new(&mk_elf_header(1)).is_ok());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside closure at src/lib.rs:194:5
--> src/lib.rs:194:5
|
193 | #[test]
| ------- in this procedural macro expansion
194 | / fn interpret_class() {
195 | | assert!(ElfFile::new(&mk_elf_header(0)).is_err());
196 | | assert!(ElfFile::new(&mk_elf_header(1)).is_ok());
197 | | assert!(ElfFile::new(&mk_elf_header(2)).is_ok());
198 | | assert!(ElfFile::new(&mk_elf_header(42u8)).is_err());
199 | | }
| |_____^
= note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to previous error
error: test failed, to rerun pass `--lib`
Caused by:
process didn't exit successfully: `/home/freax13/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner /home/freax13/code/xmas-elf/target/miri/x86_64-unknown-linux-gnu/debug/deps/xmas_elf-3090fb77e8659e43` (exit status: 1)
The unaligned reference is created by the zero
dependency. This dependency has already been patched to panic on unaligned references (nrc/zero@1d571c9), but there's no release containing this patch.
We probably want to prevent both UB and panics; I'm not sure what other parts of the code suffer from similar problems. Worst case scenario, we can probably put #[repr(packed)]
on all the structs.
Except for the type named HeaderPt1
, the rest of the ELF data uses the byte order indicated by the e_ident. Currently data will be read using the host's native byte order, which isn't correct in general.
It's not clear to me how to fix this, as the parsing approach taken by zero
isn't particularly friendly to reinterpreting data.
If the original input
slice is unaligned, subsequent values will be as well.
This would be the converse of find_section_by_name. Useful e.g. for finding the dynamic section.
Sometimes they don't give you the length ๐ข
Parses header and scans program header, section header and sections for largest offset. Creates a slice from raw parts and calls ::new...
Some enums should really implement Eq, such as xmas_elf::header::Class
and probably others.
Line 195 in ae8acad
Flags are not useful because you cannot check the value of the flags element (flags.0
doesn't work) to see which flags are set (W, R, X) because the pub struct Flags(u32)
is not public. It should either be public, or there should be getter/contain methods such as Flags::is_read()
/is_write()
/is_execute()
.
I have wanted so badly to have someone else solve the problem of 'bfd for rust'. I am so happy you have done this.
It seems the current documentation of xmas-elf is affected by: rust-lang/docs.rs#190
AFAICT releasing a new version should fix this issue for the xmas-elf crate since the newer rustdocs do not have the bug anymore.
for parse_string_array
parse_str
can violate memory safety: it can go beyond the input
slice while looking for 0
. The initial offset
also can point outside of the slice. My understanding is that in Rust such functions should either be marked with unsafe
or use assert
to enforce memory safety.
I'm getting ready to release one of my projects depending on xmas-elf, but I can't put it on crates.io because of the git dependency.
Found with honggfuzz.
The following input causes the panic: \x7F\x45\x4C\x46\x02\x07\x35\x38\x35\x33\x30\x38\x32\x30\x37\x30\x34\x32\x31\x36\x34\x37\x33\x32\x37\x35
thread 'main' panicked at 'index 64 out of range for slice of length 26', libcore/slice/mod.rs:2256:5
stack backtrace:
0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
at libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
1: std::sys_common::backtrace::print
at libstd/sys_common/backtrace.rs:71
at libstd/sys_common/backtrace.rs:59
2: std::panicking::default_hook::{{closure}}
at libstd/panicking.rs:211
3: std::panicking::default_hook
at libstd/panicking.rs:227
4: std::panicking::rust_panic_with_hook
at libstd/panicking.rs:463
5: std::panicking::begin_panic_fmt
at libstd/panicking.rs:350
6: rust_begin_unwind
at libstd/panicking.rs:328
7: core::panicking::panic_fmt
at libcore/panicking.rs:71
8: core::slice::slice_index_len_fail
at libcore/slice/mod.rs:2256
9: <core::ops::range::Range<usize> as core::slice::SliceIndex<[T]>>::index
at /checkout/src/libcore/slice/mod.rs:2387
10: core::slice::<impl core::ops::index::Index<I> for [T]>::index
at /checkout/src/libcore/slice/mod.rs:2238
11: xmas_elf::header::parse_header
at /home/user/.cargo/git/checkouts/xmas-elf-0bb86b20f57b2942/720e94d/src/header.rs:28
12: xmas_elf::ElfFile::new
at /home/user/.cargo/git/checkouts/xmas-elf-0bb86b20f57b2942/720e94d/src/lib.rs:50
13: elf_parse::main::{{closure}}
at /home/user/daniel/targets/common/src/lib.rs:967
at fuzzer-honggfuzz/src/bin/elf_parse.rs:8
14: honggfuzz::fuzz
at /home/user/.cargo/registry/src/github.com-1ecc6299db9ec823/honggfuzz-0.5.20/src/lib.rs:301
15: elf_parse::main
at fuzzer-honggfuzz/src/bin/elf_parse.rs:7
16: std::rt::lang_start::{{closure}}
at /checkout/src/libstd/rt.rs:74
17: std::panicking::try::do_call
at libstd/rt.rs:59
at libstd/panicking.rs:310
18: __rust_maybe_catch_panic
at libpanic_unwind/lib.rs:105
19: std::rt::lang_start_internal
at libstd/panicking.rs:289
at libstd/panic.rs:374
at libstd/rt.rs:58
20: std::rt::lang_start
at /checkout/src/libstd/rt.rs:74
21: main
22: __libc_start_main
23: _start
Just wanted to get a sense if you would want to include specific type meanings (as an enum) for relocation types or is this out of scope for the library?
Line 500 in dda8236
It's a bit tricky because values will be different for x86-64, x86-32, AARCH64 etc. But if you think it makes sense, I can prepare a pull request.
While parsing the attached RISC-V 32-bit binary, xmas-elf crashes with the following error:
thread 'main' panicked at 'range end index 139232 out of range for slice of length 138600', library/core/src/slice/index.rs:73:5
The method that panics is sections.rs.SectionHeader.raw_data()
, line 171.
readelf -e
doesn't seem to complain at all:
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: RISC-V
Version: 0x1
Entry point address: 0x2c9e0
Start of program headers: 52 (bytes into file)
Start of section headers: 138160 (bytes into file)
Flags: 0x1, RVC, soft-float ABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 6
Size of section headers: 40 (bytes)
Number of section headers: 11
Section header string table index: 10
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .rodata PROGBITS 000100f4 0000f4 0050ba 00 AM 0 0 4
[ 2] .eh_frame_hdr PROGBITS 000151b0 0051b0 00077c 00 A 0 0 4
[ 3] .eh_frame PROGBITS 0001592c 00592c 0019a0 00 A 0 0 4
[ 4] .text PROGBITS 000182cc 0072cc 01a7f2 00 AX 0 0 2
[ 5] .sdata PROGBITS 00033ac0 021ac0 000054 00 WA 0 0 8
[ 6] .sbss NOBITS 00033b14 021b14 000040 00 WA 0 0 4
[ 7] .bss NOBITS 00033b54 021b14 0004cc 00 WA 0 0 4
[ 8] .riscv.attributes RISCV_ATTRIBUTE 00000000 021b14 00002b 00 0 0 1
[ 9] .comment PROGBITS 00000000 021b3f 000013 01 MS 0 0 1
[10] .shstrtab STRTAB 00000000 021b52 00005e 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x00010034 0x00010034 0x000c0 0x000c0 R 0x4
LOAD 0x000000 0x00010000 0x00010000 0x072cc 0x072cc R 0x1000
LOAD 0x0072cc 0x000182cc 0x000182cc 0x1a7f2 0x1a7f2 R E 0x1000
LOAD 0x021ac0 0x00033ac0 0x00033ac0 0x00054 0x00560 RW 0x1000
GNU_EH_FRAME 0x0051b0 0x000151b0 0x000151b0 0x0077c 0x0077c R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0
Section to Segment mapping:
Segment Sections...
00
01 .rodata .eh_frame_hdr .eh_frame
02 .text
03 .sdata .sbss .bss
04 .eh_frame_hdr
05
keyboard-backlight.zip (since this is an executable, here's the VirusTotal analysis :-)
rather than transmuting
There are several issues with note sections:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.