396 Commits

Author SHA1 Message Date
Christopher Cole
29a604e913
Fix File::symbol_version_table() to properly load strings section data
Previously, it would forget to load and then just try to get the strings section data
This would work if some other processing on the file had already loaded the string table
but not if this was the first method that wanted to inspect those strings.

This class of bugs is really an integration with the CachedReadBytes interface, so it
can only get caught if we're testing with that impl. These interface tests should be parameterized
for both interfaces.
2022-10-29 15:58:59 -07:00
Christopher Cole
2162e6e347
File::symbol_version_table -> Stop iterating the section headers once we've found our shdrs 2022-10-29 14:22:01 -07:00
Christopher Cole
8577748e63
Add File::symbol_version_table() interface to get the GNU extension symbol versioning table 2022-10-29 14:19:33 -07:00
Christopher Cole
37a0da0b64
Add a VersionTable to interface with the GNU symbol versioning VerNeed VerDefs structures
This is a zero-alloc interface which parses on-demand, which can be desireable if you can't
or don't want to allocate, but is less CPU-efficient if you're doing a lot of look ups on the table.
2022-10-28 16:44:20 -07:00
Christopher Cole
c9a50c95cb
Fix StringTable to return a ParseError on index out of bounds instead of panicking 2022-10-28 15:47:02 -07:00
Christopher Cole
84485adf10
Add constants for .gnu symbol version extension sections' flag fields 2022-10-28 14:14:40 -07:00
Christopher Cole
899e6035f6
Add VersionIndex::is_hidden() to check if a symbol should be visible for linking
Also, change VersionIndex methods to act on a reference so that they don't move/consume
the value when called.
2022-10-28 14:08:38 -07:00
Christopher Cole
da3eaf169e
Elide VerNeed.vn_version by treating an invalid value as a ParseError
There's only one valid version number, so there's no need to include this field
in the parsed result.
2022-10-28 13:53:34 -07:00
Christopher Cole
870cab0159
Change the various Ver* struct _need and _aux fields to be private
These are just used as part of parsing and aren't important for users of the interface.
2022-10-28 13:45:10 -07:00
Christopher Cole
e1d71d9447
Add Symbol.undefined() helper to test if a symbol is defined in this object or not 2022-10-27 14:45:33 -07:00
Christopher Cole
7513214a6a
Document that the gnu verneed and verdef sections' sh_info field also contains the number of entries 2022-10-27 14:11:43 -07:00
Christopher Cole
c1b18674f7
Remove unused SymbolIterator type
This is now given to us for free by the ParsingTable's iterator interfaces
2022-10-26 17:33:15 -07:00
Christopher Cole
4bddfe3269
Replace .gnu.version section parsing type from ParsingIterator to ParsingTable
This more closely matches the datastructure and its use-case. Users are likely
wanting to look up the VerNeeds and VerDefs for a particular symbol in the .dynsym
table, and to do so they'll need to look up the VersionIndex by the Symbol's index
in the .dynsym table. The ParsingTable helps provide that interface with its .get(index)
method.

Alternatively, someone could do a variant of zip(SymbolTable.iter(), VersionTable.iter())
to have the Symbol alongside the VersionIndex, which is also supported by VersionTable.
2022-10-26 17:21:19 -07:00
Christopher Cole
b331fdf832
Add a generic ParsingTable impl to go alongside the ParsingIterator
Also, use this ParsingTable to replace the hand-rolled SymbolTable.

This implements a lazily-parsed table/array of structs that can be parsed
with the ParseAt trait that drives the parsing of our ELF structs.

Elements in the table are lazily parsed on-demand via the .get(index)
method. The table can also optionally be converted into a ParsingIterator
with either iter() or into_iter(), meaning the ParsingTable can be used
like so:

```
let table = ParsingTable<Foo>::new(...)
for foo in Table {
    ... do things with parsed Foo
}
```

or
```
let table = ParsingTable<Foo>::new(...)
for foo in Table.iter() {
    ... do things with parsed Foo
}
for foo in Table.iter() {
    ... do another pass of things with parsed Foo
}
```

Note that the second pattern will re-parse the second time. Useful
if you're wanting to avoid allocations, but otherwise it's probably
more useful to .collect() the iterator into a Vec<Foo>.
2022-10-26 17:10:45 -07:00
Christopher Cole
4600c54657
Handle the case where the _cnt field expects more entries than there are
I think that ideally this would be able to yield a ParseError in some way,
as it likely indicates corrupted section data. All of our iterators silently
end iteration on ParseErrors currently, though, so this is in line with
existing patterns of behavior.
2022-10-26 15:30:44 -07:00
Christopher Cole
273b0e6182
Move around some code in gnu_symver.rs
move iters to come after the types they iterate over. I think this
reads a bit easier
2022-10-26 15:17:10 -07:00
Christopher Cole
e70d43d03d
Add VerNeedIterator which parses Version Need/Requirements and their associated Auxilliary info lists
This represents an iterative parser for the contents of the .gnu.version_r
section - the interspersed lists of VerNeed and VerNeedAux structs.
2022-10-26 15:14:50 -07:00
Christopher Cole
a8fb4bfb16
Add VerNeedAuxIterator which parses Version Need/Requirement Auxillary info lists
These are found in the .gnu.version_r section interspersed with VerNeed entries.
2022-10-26 15:09:49 -07:00
Christopher Cole
cca2c02a31
Add some more figlets in gnu_symver.rs
This helps the eye track groups of related code when scrolling through the file
2022-10-26 14:47:53 -07:00
Christopher Cole
d401c17d10
Get rid of unnecessary EndianParseExt trait
There was only one implementer of this trait, on &[u8], and the indirection
didn't serve any real purpose. The indirection via the double &&[u8] impl was
more expensive than necessary, and the indirection also added a layer of unnecessary
cognitive overhead to reading the code.

This goes back to having simple parse methods for the endian-aware integer parsing
which operate on byte slices.
2022-10-26 14:24:23 -07:00
Christopher Cole
37e0904787
Elide VerDef.vd_version by treating an invalid value as a ParseError
There's only one valid version number, so there's no need to include this field
in the parsed result.
2022-10-26 00:47:43 -07:00
Christopher Cole
6ba37955db
Add VerDefIterator which parses Version Definition and their associated Auxilliary info lists
This represents an iterative parser for the contents of the .gnu.version_d
section - the interspersed lists of VerDef and VerDefAux structs.
2022-10-26 00:11:48 -07:00
Christopher Cole
8ac79d37c2
Add VerDefAuxIterator which parses Version Definition Auxillary info lists
These are found in the .gnu.version_d section interspersed with VerDef entries.
2022-10-25 23:34:23 -07:00
Christopher Cole
cbda6b3d99
Properly escape some [] in a doc comment 2022-10-25 19:03:13 -07:00
Christopher Cole
b01eb0e79d
Add VerNeedAux parsing for entries in the GNU extension section .gnu.version_r
These other type of entries are found in the .gnu.version_r section of type SHT_GNU_VERNEED.
This only parses the type, and is not hooked up to anything else yet.
2022-10-25 18:29:56 -07:00
Christopher Cole
ea1439d2ee
Remove some extraneous and erroneous copy-pasted comments in some unit test set up code 2022-10-25 18:21:17 -07:00
Christopher Cole
929e099769
Add VerNeed parsing for entries in the GNU extension section .gnu.version_r
These are one type of entries found in the .gnu.version_r section of type SHT_GNU_VERNEED.
This only parses the type, and is not hooked up to anything else yet.
2022-10-25 18:19:06 -07:00
Christopher Cole
c8cb21089e
Add VerDefAux parsing for entries in the GNU extension section .gnu.version_d
These other type of entries are found in the .gnu.version_d section of type SHT_GNU_VERDEF.
This only parses the type, and is not hooked up to anything else yet.
2022-10-25 17:31:16 -07:00
Christopher Cole
f35a2936b4
Add VerDef parsing for entries in the GNU extension section .gnu.version_d
These type of entries are found in the .gnu.version_d section of type SHT_GNU_VERDEF,
alongside VerDefAux (not yet defined).
This only parses the type, and is not hooked up to anything else yet.
2022-10-25 17:22:28 -07:00
Christopher Cole
2142af70e0
Add VersionIndex parsing for entries in the GNU extension section .gnu.version
These are the entries found in the .gnu.version section of type SHT_GNU_VERSYM.
This only parses the entry type, and is not hooked up to anything in File yet.
2022-10-25 13:06:58 -07:00
Christopher Cole
8206eed68e
Add more OS and application-specific constants for .dynamic section types 2022-10-25 00:13:03 -07:00
Christopher Cole
720e54b377
Add some processor-specific SHT_ definitions 2022-10-24 20:45:21 -07:00
Christopher Cole
59274c16f7
Restructure use imports in file.rs to make code less verbose
The module paths are pretty intuitive, so I think it actually hurts
code legibility by having them spelled out as they were before.
2022-10-24 18:39:44 -07:00
Christopher Cole
d3ca1bf095
Add File::section_data() which opportunistically parses the CompressionHeader if present
I don't plan on implementing any actual compression as part of this library and think that
it is reasonable for users to do the decompression themselves based on the description
provided by the parsed CompressionHeader.

Also, deprecate File::section_data_for_header() in favor of section_data()
2022-10-24 18:17:57 -07:00
Christopher Cole
90eb25f8b6
Add rust type and parsing for CompressionHeader
This header is found at the start of sections whose flags contain SHF_COMPRESSED,
indicating that the section's data in the file is compressed with a given algorithm.
2022-10-24 17:55:12 -07:00
Christopher Cole
5e73835772
Add ELFCOMPRESS constants to gabi.rs
These define possible values for the elf compression header's ch_type field, which
signals the compression algorithm used for compressed sections (shdr.sh_flags & SHF_COMPRESSED)
2022-10-24 17:51:53 -07:00
Christopher Cole
531ad77d04
Fix File::section_data_as_rels to properly parse Rels (not Relas) 2022-10-24 17:27:14 -07:00
Christopher Cole
f44860bfc5
Bump crate version to v0.4.0
New Features:
* .note section and segment parsing
* .dynamic section and segment parsing
* .rel and .rela section parsing
* File::section_headers_with_strtab to get both a header iter and strtab concurrently.
  This is useful if you want to iterate over shdrs and get their names at the same time.

Interface changes:
The ReadBytesAt trait was changed to be implemented for an owned CachedReadBytes.
This means that File::open_stream now expects to move-own the CachedReadBytes
as opposed to taking a mutable reference.
2022-10-24 14:42:43 -07:00
Christopher Cole
59f298d54b
Make NoteHeader private to note.rs
The implementation panned out where this header is parsed but then
only used to drive the further parsed Note but not included in the result,
so there's no need for pub(crate) here.
2022-10-24 14:27:47 -07:00
Christopher Cole
d24a57fb3b
Fix doc comments for File::section_data_as_rel and File::section_data_as_rela 2022-10-24 14:22:29 -07:00
Christopher Cole
bcb12eeaff
Add File::segment_data_as_notes() for an iterator which yields parsed Notes 2022-10-24 14:21:19 -07:00
Christopher Cole
485338bc23
Add File::section_data_as_notes() for an iterator which yields parsed Notes 2022-10-24 14:12:50 -07:00
Christopher Cole
5b57ff1c4f
Add Note and NoteIterator to yield parsed Notes
Note: (haha) It looks like gcc/clang choose to emit 32-bit note headers
even for 64-bit objects. I discovered this when writing the parse tests
with data from a 64-bit LSB ELF object that I slurped the .note.gnu.build-id
section from. I kept the 64-bit nhdr parsing around in case someone finds
a use-case for it in the future.
2022-10-24 14:11:12 -07:00
Christopher Cole
269c86c85e
Add parsing of .note section entry headers
These fixed size headers prefix and describe variable-sized note data.
I made it pub(crate) to keep this out of the public interface, since
I plan to have the actual note iterator parse out the name and desc and
have that result be the actual public interface. pub(crate) might still
be more visibility than is needed, but it's a safe place to start.
2022-10-24 12:08:41 -07:00
Christopher Cole
b937ef93a1
Add File::section_headers_with_strtab() to get both shdr iterator and strtab
This allows for a more convenient way of interacting with the SectionHeaders so
that you can concurrently look up the names of the sections as you're iterating
through the SectionHeaderIterator
2022-10-23 20:06:19 -07:00
Christopher Cole
674ed56d57
Add simple interfaces to File to get Rel and Rela iterators for a given section
Note, while this may satisfy some use-cases, it is likely insufficient for those
who want to actually do linking and to concurrently iterate over the returned Rels
while also looking at the sectin's associated SymbolTable and the section to which
they're applied.
2022-10-23 19:02:44 -07:00
Christopher Cole
26b7a6d66c
Add Rel and Rela parsing and parsing iterators
I didn't have a strong motivating factor for deciding whether to represent this as I did,
with r_sym and r_type parsed out as data members, or as an alternative approach where
the rust type keeps a private r_info and then parses out those data members as needed with
getter methods. So I arbitrarily chose to parse them out up front.
2022-10-23 19:02:43 -07:00
Christopher Cole
f7a801bf6a Implement ReadBytesAt for owned CachedReadBytes
As suggested in #21
This changes it from being implemented for a &mut CachedReadBytes, which forced
users to keep a separate variable for the reader when passing it to File::open_stream().
There wasn't a specific reason for it to be implemented that way, and it's actually
something that tenuously even desireable, since ultimately CachedReadBytes is
a more an internal wrapper used within the File for lazy parsing than something
that a user of the interface will want to keep around and use themselves for other things.
2022-10-23 17:15:42 -07:00
Christopher Cole
1f09b43e5b
Dedupe the various lazy parsing iterators into ParsingIterator
This centralizes the iter implementation to one place and leverages the new ParseAt
trait which was already functionally being implemented by all the various types
being iteratively parsed.
2022-10-22 14:44:40 -07:00
Christopher Cole
d28e14a68e
Fix Dyn::d_un type to be unsigned
I accidentally read this as signed when I was looking at the ELF spec, but
upon a second look, only d_tag is signed - d_un is unsigned.
2022-10-21 18:59:41 -07:00