396 Commits

Author SHA1 Message Date
Christopher Cole
5494189ffa
Add File::dynamic_section() interface an iterator over .dynamic section entries
ELF Object files can have either or both a ProgramHeader and SectionHeader that
describes how to locate the .dynamic entries in the file. We try the SectionHeaders
first, and if there are none (a loadable-only ELF object) then we check for it in
the ProgramHeaders. It is also Ok for there to be no .dynamic entries in the file.
2022-10-21 18:28:05 -07:00
Christopher Cole
9bb0b310ce
Add DynIterator which can yield Dyn structs from a .dynamic section's data 2022-10-21 18:28:05 -07:00
Christopher Cole
89c1a34575
Add parser and rust representation of Elf(32|64)_Dyn
These are the entries that make up the .dynamic section
2022-10-21 18:28:05 -07:00
Christopher Cole
1739773778
Add GABI constants for DF_* 2022-10-21 18:28:05 -07:00
Christopher Cole
969bb74628
Add GABI constants for DT_* 2022-10-21 18:28:04 -07:00
Christopher Cole
3d0a090ab2
Add parse methods for parsing signed integers 2022-10-21 18:28:04 -07:00
Christopher Cole
d1022af46f
Add no_std build step to github action 2022-10-21 14:51:37 -07:00
Christopher Cole
2332a54a29
Bump crate version to v0.3.1
This picks up the fixes to section table parsing for large table sizes,
and provides the new File::section_data_for_header() method.
2022-10-21 13:49:37 -07:00
Christopher Cole
dd2685a864
Add some categories to Cargo.toml 2022-10-21 13:48:10 -07:00
Christopher Cole
f715bd7a2b
Add File::section_data_for_header() for reading the section data as found in the file 2022-10-21 12:03:58 -07:00
Christopher Cole
dae40248b8
Properly handle reading section header string table with index > SHN_XINDEX 2022-10-21 11:29:55 -07:00
Christopher Cole
5469c59037
Properly handle reading section header tables with > SHN_LORESERVE number of sections 2022-10-21 11:20:28 -07:00
Christopher Cole
5a4e556d68
Bump crate version to v0.3.0
This fully moves the parser over to the lazy zero-alloc approach which enables
a no_std option.
2022-10-20 23:17:10 -07:00
Christopher Cole
af28e55c30
Expose CachedReadBytes in the public interface
This is necessary for users of this crate to utilize the lazy i/o parsing interface
2022-10-20 23:13:05 -07:00
Christopher Cole
a010016831
Add documentation calling out this parser's is zero-alloc capability 2022-10-20 23:07:31 -07:00
Christopher Cole
1be248c4bb
Add default std feature to allow no_std use-cases
This addresses the ask in #19
2022-10-20 23:00:57 -07:00
Christopher Cole
9c5e4b62d6
Remove now-unused SectionTable impl that eagerly parses all headers and section data 2022-10-20 22:55:55 -07:00
Christopher Cole
7abba88d76
Fix up some copy-pasted rustdoc markdown in README.md
third time's a charm :)
2022-10-20 22:50:57 -07:00
Christopher Cole
3ffb08a11c
Remove typoed duplicate header in README.md 2022-10-20 22:48:28 -07:00
Christopher Cole
e9bc799ec7
Remove eager symbol table parsing from File::open_stream
Now, all section parsing is done lazily on-demand by the other File methods

Also, update README.md and lib.rs doc comment to reflect current library development state
2022-10-20 22:45:27 -07:00
Christopher Cole
4e706431e3
Reimplement File::symbol_table() and File::dynamic_symbol_table() using lazy parsing
These use the lazy parsing methods to read the section headers and section data when requested
as opposed to reading and parsing the section headers and section data all up front when the File
is created.
2022-10-20 22:15:03 -07:00
Christopher Cole
c74566cf9f
Extend the ReadAtExt trait with a pair of load/get methods
These can drive use-cases where we need to read and work with multiple
references to disjoint parts of the ELF file data at the same time.
2022-10-20 21:38:38 -07:00
Christopher Cole
5a6f99c451
Add interface test for File::segments() 2022-10-20 20:59:01 -07:00
Christopher Cole
31689794ba
Add interfaces for reading and interpreting a section's data as a strtab 2022-10-20 20:50:17 -07:00
Christopher Cole
c029fe4b88
Add interface for parsing a single SectionHeader at a given index 2022-10-20 20:09:13 -07:00
Christopher Cole
6ec11531d2
Add File::section_headers() iterator method for lazy header parsing
When called, this reads the section header table and wraps the data reference
in an iterator which lazily parses SectionHeader structs out of it.
2022-10-20 19:19:08 -07:00
Christopher Cole
bab7e10ca4
Bump crate version to 0.2.0 2022-10-20 14:13:39 -07:00
Christopher Cole
ebd2cfd7d8
Add doc comments explaining the ParseError variants 2022-10-20 14:05:23 -07:00
Christopher Cole
556b901023
Rework ParseError to be more useful
This changes ParseError into a variated enum which allows users (and tests) to
easily match on specific error conditions.

It also encodes helpful associated data into the various enum variants in order
to provide more helpful error messages for the various error conditions.

This pattern of enum error construction also defers string formatting to the
user rather than forcing an expensive format! when the error is generated.

This also properly implements std::error::Error's .source() as requested in #15

This also exposes ParseError in the public interface as requested in #20
2022-10-20 13:38:26 -07:00
Christopher Cole
471729fee3
Remove now-unused Reader and ReadExt traits
Also switch over the endian-aware uint parsing unit test to cover the
ParseAtEXt trait impl
2022-10-19 22:25:50 -07:00
Christopher Cole
a22d21c1fd
Change ELF File interface to take a ReadBytesAt trait as the data reader
This enables the two use-cases:
1. Parsing ELF structures out of a &[u8] that contains the whole file contents
2. Parsing ELF structures with on-demand I/O out of a Read + Seek through
   the CachedReadBytes

Currently, the File still allocates its own internal vec<u8> buffers in which
to copy the section data.
2022-10-19 22:12:43 -07:00
Christopher Cole
b7487db30a
Parse an empty SectionTable if the file header's e_phnum field is 0 2022-10-19 20:00:56 -07:00
Christopher Cole
0a8bf16d6d
Use ELF{32|64}SHDRSIZE constants in shdr parse tests 2022-10-19 19:21:35 -07:00
Christopher Cole
d0796b1451
Remove now-unused Parse trait 2022-10-19 19:16:13 -07:00
Christopher Cole
92cb601605
Change SectionHeader parsing to use ParseAtExt 2022-10-19 19:14:39 -07:00
Christopher Cole
e4a5c7007a
Hide File::sections behind a getter method
This will allow us to change section parsing into on-demand lazy
parsing as opposed to always reading and parsing all of the sections
up front as part of open_stream().
2022-10-18 13:58:56 -07:00
Christopher Cole
eb1fb44c25
Remove currently-unused named lifetime 'data from File impl block 2022-10-18 13:40:14 -07:00
Christopher Cole
a4747cb5df
Add a doc comment for File::segments() 2022-10-18 13:35:35 -07:00
Christopher Cole
9cb7fa0463
Use shorthand struct member init syntax in ProgramHeader::parse_at 2022-10-18 12:59:35 -07:00
Christopher Cole
d170ea89ae
Use shorthand struct member init syntax in FileHeader::parse 2022-10-18 12:52:46 -07:00
Christopher Cole
0f60bec6db
Change File::segments() to return an iterator
This avoids the up front Vec allocation and parsing in favor of lazily parsing
ProgramHeaders iteratively out of the segment table bytes that were read from
the file. I opted to read the whole segment table up front with the thought that
one larger for the whole table I/O is likely faster than lots of small I/Os to get
each phdr, though that assumes that the segment table isn't huge (multi-MBs) which
is likely the common case.
2022-10-18 12:45:28 -07:00
Christopher Cole
40fd8d39bf
Use new CachedReadBytes in File to parse segment ProgramHeaders 2022-10-17 16:31:29 -07:00
Christopher Cole
0921b2945c
Add CachedReadBytes impl of ReadBytesAt trait
This wraps a Read + Seek for our lazy file i/o use-case and allocates and caches
in-memory buffers in which to read file data which can then be used by
ParseAtExt when parsing ELF structures.
2022-10-17 15:57:22 -07:00
Christopher Cole
4dda102d3e
Split ReadAtExt into ParseAtExt and ReadBytesAt traits
ParseAtExt is an extension trait on byte slices which can parse uints
of various sizes in an endian-aware way. This will be used for all parsing
uses.

ReadBytesAt is a trait which will allow us to provide byte slices
from which to parse ELF data in two different ways:
1. directly on an already read byte slice (the user reads the whole file
   contents up front)
2. in a streaming method where the user provides a <Read + Seek>.
2022-10-17 15:00:21 -07:00
Christopher Cole
fe18351e45
Remove explicit lifetime bounds for various File methods
The lifetime elision rules make it such that we don't need to explicitly state
these, since the only criteria we're trying to maintain is that the lifetime
of method outputs are the same or shorter than the lifetime of &self.
2022-10-17 01:04:28 -07:00
Christopher Cole
f3a2e1a7ed
Change File::segments() to lazily parse program headers on demand 2022-10-17 00:59:14 -07:00
Christopher Cole
33aa3ef878
Remove impls of Display and Debug on elf::File
These contents can be huge and it is not clear what a useful representation
of an entire ELF file would be that would be usable by any given user of
this crate. Users can implement and define their own string interpretation.
2022-10-17 00:41:15 -07:00
Christopher Cole
51fd9c7914
Make File remember the Reader data provider
This will later be used in order to lazily read file contents on demand rather than
reading them all up front as part of open_stream.
2022-10-17 00:13:28 -07:00
Christopher Cole
229742f08f
Hide ELF File segment headers behind getter method
This will allow us to lazily parse them on demand
2022-10-16 23:58:46 -07:00
Christopher Cole
13fd2bb58d
Add ReadAtExt::read_bytes_at to get a byte slice of a given range in its data
My thought is that this trait method will be able to drive the difference between
the two desired parsing strategies:

1. All I/O is done up-front by giving us the full object file contents in a
   &[u8]. This could drive a zero-allocations parser which lazily parses ELF
   structures from byte slices on demand.
2. Lazy I/O done on demand by giving a File stream to some sort of ReadAtExt
   trait interpreter which internally allocates Vec::<u8> on demand for requested
   read_bytes_at requests and caches the results internally. This tradeoff uses
   allocations but can reduce the amount of i/o performed for users who only
   want to inspect small subsets of the file contents.
2022-10-16 23:46:36 -07:00