Skip to content

Commit

Permalink
Merge branch 'm4b:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
ideeockus authored Jul 29, 2024
2 parents ac439f7 + 6177758 commit 2a5534c
Show file tree
Hide file tree
Showing 27 changed files with 1,575 additions and 85 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ Before 1.0, this project does not adhere to [Semantic Versioning](http://semver.

Goblin is now 0.8, which means we will try our best to ease breaking changes. Tracking issue is here: https://github.com/m4b/goblin/issues/97

## [0.8.1] - 2024-04-27
### Docs
pe: document pe header, thanks @JohnScience: https://github.com/m4b/goblin/pull/399
pe, elf: fix doc warnings, thanks @5225225: https://github.com/m4b/goblin/pull/395
pe: document dos header, thanks @JohnScience: https://github.com/m4b/goblin/pull/393
### Added
pe: add TE (terse executable) support, big thanks @Javagedes: https://github.com/m4b/goblin/pull/397
elf: allow parsing section headers from raw bytes, thanks @lissyx: https://github.com/m4b/goblin/pull/391
mach: add support for lossy parsing, thanks @h33p: https://github.com/m4b/goblin/pull/386
elf: add convenience functions, thanks @tiann : https://github.com/m4b/goblin/pull/387
### Fixed
pe: read reserved dos headers, thanks @kkent030315: https://github.com/m4b/goblin/pull/405


## [0.8.0] - 2023-12-31 - Happy New Years!
### Breaking
msrv: bumped to 1.63.0 since scroll bumped as well
Expand Down
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "goblin"
version = "0.8.0"
version = "0.8.1"
authors = [
"m4b <[email protected]>",
"seu <[email protected]>",
Expand Down Expand Up @@ -38,7 +38,7 @@ version = "0.12"
default_features = false

[features]
default = ["std", "elf32", "elf64", "mach32", "mach64", "pe32", "pe64", "archive", "endian_fd"]
default = ["std", "elf32", "elf64", "mach32", "mach64", "pe32", "pe64", "te", "archive", "endian_fd"]
std = ["alloc", "scroll/std"]
alloc = ["scroll/derive", "log"]
endian_fd = ["alloc"]
Expand All @@ -49,6 +49,7 @@ mach32 = ["alloc", "endian_fd", "archive"]
mach64 = ["alloc", "endian_fd", "archive"]
pe32 = ["alloc", "endian_fd"]
pe64 = ["alloc", "endian_fd"]
te = ["alloc", "endian_fd"]
archive = ["alloc"]

[badges.travis-ci]
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ Here are some things you could do with this crate (or help to implement so they
* mach32 - 32-bit mach-o `repr(C)` struct defs
* pe32 - 32-bit PE `repr(C)` struct defs
* pe64 - 64-bit PE `repr(C)` struct defs
+ te - Terse Executable (TE) `repr(C)` struct defs
* archive - a Unix Archive parser
* endian_fd - parses according to the endianness in the binary
* std - to allow `no_std` environments
Expand All @@ -108,6 +109,7 @@ Thank you all :heart: !
In lexicographic order:

- [@2vg]
- [@5225225]
- [@alessandrod]
- [@amanieu]
- [@anfedotoff]
Expand All @@ -121,21 +123,26 @@ In lexicographic order:
- [@ExPixel]
- [@flanfly]
- [@glandium]
- [@h33p]
- [@ibabushkin]
- [@jackcmay]
- [@jan-auer]
- [@Javagedes]
- [@jessehui]
- [@jdub]
- [@Jhynjhiruu]
- [@johannst]
- [@JohnScience]
- [@jrmuizel]
- [@jsgf]
- [@keith]
- [@kjempelodott]
- [@kkent030315]
- [@ko1n]
- [@le-jzr]
- [@Lichtso]
- [@lion128]
- [@lissyx]
- [@llogiq]
- [@lumag]
- [@lzutao]
Expand Down Expand Up @@ -168,6 +175,7 @@ In lexicographic order:
- [@SquareMan]
- [@tathanhdinh]
- [@Techno-coder]
- [@tiann]
- [@ticki]
- [@Timmmm]
- [@Tiwalun]
Expand All @@ -183,6 +191,7 @@ In lexicographic order:
<!-- Contributors -->

[@2vg]: https://github.com/2vg
[@5225225]: https://github.com/5225225
[@alessandrod]: https://github.com/alessandrod
[@amanieu]: https://github.com/amanieu
[@anfedotoff]: https://github.com/anfedotoff
Expand All @@ -197,21 +206,26 @@ In lexicographic order:
[@ExPixel]: https://github.com/ExPixel
[@flanfly]: https://github.com/flanfly
[@glandium]: https://github.com/glandium
[@h33p]: https://github.com/h33p
[@ibabushkin]: https://github.com/ibabushkin
[@jackcmay]: https://github.com/jackcmay
[@jan-auer]: https://github.com/jan-auer
[@Javagedes]: https://github.com/Javagedes
[@jessehui]: https://github.com/jessehui
[@Jhynjhiruu]: https://github.com/Jhynjhiruu
[@JohnScience]: https://github.com/JohnScience
[@johannst]: https://github.com/johannst
[@jdub]: https://github.com/jdub
[@jrmuizel]: https://github.com/jrmuizel
[@jsgf]: https://github.com/jsgf
[@keith]: https://github.com/keith
[@kjempelodott]: https://github.com/kjempelodott
[@kkent030315]: https://github.com/kkent030315
[@ko1N]: https://github.com/ko1N
[@le-jzr]: https://github.com/le-jzr
[@Lichtso]: https://github.com/Lichtso
[@lion128]: https://github.com/lion128
[@lissyx]: https://github.com/lissyx
[@llogiq]: https://github.com/llogiq
[@lumag]: https://github.com/lumag
[@lzutao]: https://github.com/lzutao
Expand Down Expand Up @@ -245,6 +259,7 @@ In lexicographic order:
[@SquareMan]: https://github.com/SquareMan
[@tathanhdinh]: https://github.com/tathanhdinh
[@Techno-coder]: https://github.com/Techno-coder
[@tiann]: https://github.com/tiann
[@ticki]: https://github.com/ticki
[@Timmmm]: https://github.com/Timmmm
[@Tiwalun]: https://github.com/Tiwalun
Expand Down
6 changes: 3 additions & 3 deletions src/elf/constants_relocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ pub const R_ARM_GOT32: u32 = 26;
pub const R_ARM_PLT32: u32 = 27;
/// PC relative 24 bit (BL, BLX)
pub const R_ARM_CALL: u32 = 28;
/// PC relative 24 bit (B, BL<cond>)
/// PC relative 24 bit (B, BL&lt;cond&gt;)
pub const R_ARM_JUMP24: u32 = 29;
/// PC relative 24 bit (Thumb32 B.W)
pub const R_ARM_THM_JUMP24: u32 = 30;
Expand Down Expand Up @@ -539,7 +539,7 @@ pub const R_ARM_THM_MOVT_ABS: u32 = 48;
pub const R_ARM_THM_MOVW_PREL_NC: u32 = 49;
/// PC relative high 16 bit (Thumb32 MOVT)
pub const R_ARM_THM_MOVT_PREL: u32 = 50;
/// PC relative 20 bit (Thumb32 B<cond>.W)
/// PC relative 20 bit (Thumb32 B&lt;cond&gt;.W)
pub const R_ARM_THM_JUMP19: u32 = 51;
/// PC relative X & 0x7E (Thumb16 CBZ, CBNZ)
pub const R_ARM_THM_JUMP6: u32 = 52;
Expand Down Expand Up @@ -636,7 +636,7 @@ pub const R_ARM_GNU_VTENTRY: u32 = 100;
pub const R_ARM_GNU_VTINHERIT: u32 = 101;
/// PC relative & 0xFFE (Thumb16 B)
pub const R_ARM_THM_PC11: u32 = 102;
/// PC relative & 0x1FE (Thumb16 B/B<cond>)
/// PC relative & 0x1FE (Thumb16 B/B&lt;cond&gt;)
pub const R_ARM_THM_PC9: u32 = 103;
/// PC-rel 32 bit for global dynamic thread local data
pub const R_ARM_TLS_GD32: u32 = 104;
Expand Down
2 changes: 1 addition & 1 deletion src/elf/dynamic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ macro_rules! elf_dyn_std_impl {
}

// TODO: these bare functions have always seemed awkward, but not sure where they should go...
/// Maybe gets and returns the dynamic array with the same lifetime as the [phdrs], using the provided bias with wrapping addition.
/// Maybe gets and returns the dynamic array with the same lifetime as the `phdrs`, using the provided bias with wrapping addition.
/// If the bias is wrong, it will either segfault or give you incorrect values, beware
pub unsafe fn from_phdrs(bias: usize, phdrs: &[$phdr]) -> Option<&[Dyn]> {
for phdr in phdrs {
Expand Down
6 changes: 3 additions & 3 deletions src/elf/gnu_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
//! 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/
//! * <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/>
/// GNU hash function: accepts a symbol name and returns a value that may be
/// used to compute a bucket index.
Expand Down
6 changes: 2 additions & 4 deletions src/elf/reloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@
//! | `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
//! 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
//! Read more <https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-54839.html>
include!("constants_relocation.rs");

Expand Down Expand Up @@ -129,8 +129,6 @@ macro_rules! elf_reloc {
macro_rules! elf_rela_std_impl {
($size:ident, $isize:ty) => {
if_alloc! {
use crate::elf::reloc::Reloc;

use core::slice;

if_std! {
Expand Down
2 changes: 1 addition & 1 deletion src/elf/section_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ if_alloc! {
}

impl SectionHeader {
/// Return the size of the underlying program header, given a `container`
/// Return the size of the underlying section header, given a `Ctx`
#[inline]
pub fn size(ctx: Ctx) -> usize {
use scroll::ctx::SizeWith;
Expand Down
7 changes: 6 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,14 +229,15 @@ pub enum Hint {
Mach(HintData),
MachFat(usize),
PE,
TE,
COFF,
Archive,
Unknown(u64),
}

macro_rules! if_everything {
($($i:item)*) => ($(
#[cfg(all(feature = "endian_fd", feature = "elf64", feature = "elf32", feature = "pe64", feature = "pe32", feature = "mach64", feature = "mach32", feature = "archive"))]
#[cfg(all(feature = "endian_fd", feature = "elf64", feature = "elf32", feature = "pe64", feature = "pe32", feature = "te", feature = "mach64", feature = "mach32", feature = "archive"))]
$i
)*)
}
Expand All @@ -262,6 +263,7 @@ if_everything! {
} else {
match *&bytes[0..2].pread_with::<u16>(0, LE)? {
pe::header::DOS_MAGIC => Ok(Hint::PE),
pe::header::TE_MAGIC => Ok(Hint::TE),
pe::header::COFF_MACHINE_X86 |
pe::header::COFF_MACHINE_X86_64 |
pe::header::COFF_MACHINE_ARM64 => Ok(Hint::COFF),
Expand Down Expand Up @@ -290,6 +292,8 @@ if_everything! {
Elf(elf::Elf<'a>),
/// A PE32/PE32+!
PE(pe::PE<'a>),
/// A TE!
TE(pe::TE<'a>),
/// A COFF
COFF(pe::Coff<'a>),
/// A 32/64-bit Mach-o binary _OR_ it is a multi-architecture binary container!
Expand All @@ -309,6 +313,7 @@ if_everything! {
Hint::Mach(_) | Hint::MachFat(_) => Ok(Object::Mach(mach::Mach::parse(bytes)?)),
Hint::Archive => Ok(Object::Archive(archive::Archive::parse(bytes)?)),
Hint::PE => Ok(Object::PE(pe::PE::parse(bytes)?)),
Hint::TE => Ok(Object::TE(pe::TE::parse(bytes)?)),
Hint::COFF => Ok(Object::COFF(pe::Coff::parse(bytes)?)),
Hint::Unknown(magic) => Ok(Object::Unknown(magic)),
}
Expand Down
76 changes: 59 additions & 17 deletions src/mach/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,17 @@ impl<'a> MachO<'a> {
}
}
/// Parses the Mach-o binary from `bytes` at `offset`
pub fn parse(bytes: &'a [u8], mut offset: usize) -> error::Result<MachO<'a>> {
pub fn parse(bytes: &'a [u8], offset: usize) -> error::Result<MachO<'a>> {
Self::parse_impl(bytes, offset, false)
}

/// Parses the Mach-o binary from `bytes` at `offset` in lossy mode
pub fn parse_lossy(bytes: &'a [u8], offset: usize) -> error::Result<MachO<'a>> {
Self::parse_impl(bytes, offset, true)
}

/// Parses the Mach-o binary from `bytes` at `offset` in `lossy` mode
fn parse_impl(bytes: &'a [u8], mut offset: usize, lossy: bool) -> error::Result<MachO<'a>> {
let (magic, maybe_ctx) = parse_magic_and_ctx(bytes, offset)?;
let ctx = if let Some(ctx) = maybe_ctx {
ctx
Expand Down Expand Up @@ -183,27 +193,42 @@ impl<'a> MachO<'a> {
let cmd = load_command::LoadCommand::parse(bytes, offset, ctx.le)?;
debug!("{} - {:?}", i, cmd);
match cmd.command {
load_command::CommandVariant::Segment32(command) => {
// FIXME: we may want to be less strict about failure here, and just return an empty segment to allow parsing to continue?
segments.push(segment::Segment::from_32(bytes, &command, cmd.offset, ctx)?)
}
load_command::CommandVariant::Segment64(command) => {
segments.push(segment::Segment::from_64(bytes, &command, cmd.offset, ctx)?)
}
load_command::CommandVariant::Segment32(command) => segments.push(
segment::Segment::from_32_impl(bytes, &command, cmd.offset, ctx, lossy)?,
),
load_command::CommandVariant::Segment64(command) => segments.push(
segment::Segment::from_64_impl(bytes, &command, cmd.offset, ctx, lossy)?,
),
load_command::CommandVariant::Symtab(command) => {
symbols = Some(symbols::Symbols::parse(bytes, &command, ctx)?);
match symbols::Symbols::parse(bytes, &command, ctx) {
Ok(s) => symbols = Some(s),
Err(e) if lossy => {
debug!("CommandVariant::Symtab failed: {e}");
}
Err(e) => return Err(e),
}
}
load_command::CommandVariant::LoadDylib(command)
| load_command::CommandVariant::LoadUpwardDylib(command)
| load_command::CommandVariant::ReexportDylib(command)
| load_command::CommandVariant::LoadWeakDylib(command)
| load_command::CommandVariant::LazyLoadDylib(command) => {
let lib = bytes.pread::<&str>(cmd.offset + command.dylib.name as usize)?;
libs.push(lib);
match bytes.pread::<&str>(cmd.offset + command.dylib.name as usize) {
Ok(lib) => libs.push(lib),
Err(e) if lossy => {
debug!("CommandVariant::Load/Reexport Dylib failed: {e}");
}
Err(e) => return Err(e.into()),
}
}
load_command::CommandVariant::Rpath(command) => {
let rpath = bytes.pread::<&str>(cmd.offset + command.path as usize)?;
rpaths.push(rpath);
match bytes.pread::<&str>(cmd.offset + command.path as usize) {
Ok(rpath) => rpaths.push(rpath),
Err(e) if lossy => {
debug!("CommandVariant::Rpath failed: {e}");
}
Err(e) => return Err(e.into()),
}
}
load_command::CommandVariant::DyldInfo(command)
| load_command::CommandVariant::DyldInfoOnly(command) => {
Expand All @@ -229,9 +254,16 @@ impl<'a> MachO<'a> {
}
}
load_command::CommandVariant::IdDylib(command) => {
let id = bytes.pread::<&str>(cmd.offset + command.dylib.name as usize)?;
libs[0] = id;
name = Some(id);
match bytes.pread::<&str>(cmd.offset + command.dylib.name as usize) {
Ok(id) => {
libs[0] = id;
name = Some(id);
}
Err(e) if lossy => {
debug!("CommandVariant::IdDylib failed: {e}");
}
Err(e) => return Err(e.into()),
}
}
_ => (),
}
Expand Down Expand Up @@ -502,6 +534,16 @@ pub enum Mach<'a> {
impl<'a> Mach<'a> {
/// Parse from `bytes` either a multi-arch binary or a regular mach-o binary
pub fn parse(bytes: &'a [u8]) -> error::Result<Self> {
Self::parse_impl(bytes, false)
}

/// Parse from `bytes` either a multi-arch binary or a regular mach-o binary in lossy mode
pub fn parse_lossy(bytes: &'a [u8]) -> error::Result<Self> {
Self::parse_impl(bytes, true)
}

/// Parse from `bytes` either a multi-arch binary or a regular mach-o binary
fn parse_impl(bytes: &'a [u8], lossy: bool) -> error::Result<Self> {
let size = bytes.len();
if size < 4 {
let error = error::Error::Malformed("size is smaller than a magical number".into());
Expand All @@ -515,7 +557,7 @@ impl<'a> Mach<'a> {
}
// we might be a regular binary
_ => {
let binary = MachO::parse(bytes, 0)?;
let binary = MachO::parse_impl(bytes, 0, lossy)?;
Ok(Mach::Binary(binary))
}
}
Expand Down
Loading

0 comments on commit 2a5534c

Please sign in to comment.