Skip to content

Commit

Permalink
read: add COFF bigobj support (gimli-rs#502)
Browse files Browse the repository at this point in the history
  • Loading branch information
philipc committed Apr 3, 2023
1 parent 2f49511 commit e838b42
Show file tree
Hide file tree
Showing 22 changed files with 1,867 additions and 374 deletions.
1 change: 1 addition & 0 deletions crates/examples/src/bin/pecopy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::error::Error;
use std::{env, fs, process};

use object::pe;
use object::read::coff::CoffHeader;
use object::read::pe::{ImageNtHeaders, ImageOptionalHeader};
use object::LittleEndian as LE;

Expand Down
17 changes: 17 additions & 0 deletions crates/examples/src/readobj/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,22 @@ impl<'a> Printer<'a> {
self.field_hex(name, value);
}

fn field_enum_display<T: Eq + fmt::Display>(
&mut self,
name: &str,
value: T,
flags: &[Flag<T>],
) {
for flag in flags {
if value == flag.value {
self.field_name(name);
writeln!(self.w, "{} ({})", flag.name, value).unwrap();
return;
}
}
self.field(name, value);
}

fn field_enums<T: Eq + fmt::UpperHex>(&mut self, name: &str, value: T, enums: &[&[Flag<T>]]) {
for flags in enums {
for flag in *flags {
Expand Down Expand Up @@ -176,6 +192,7 @@ fn print_object(p: &mut Printer<'_>, data: &[u8]) {
match kind {
object::FileKind::Archive => print_archive(p, data),
object::FileKind::Coff => pe::print_coff(p, data),
object::FileKind::CoffBig => pe::print_coff_big(p, data),
object::FileKind::DyldCache => macho::print_dyld_cache(p, data),
object::FileKind::Elf32 => elf::print_elf32(p, data),
object::FileKind::Elf64 => elf::print_elf64(p, data),
Expand Down
91 changes: 77 additions & 14 deletions crates/examples/src/readobj/pe.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use super::*;
use object::pe::*;
use object::read::coff::ImageSymbol as _;
use object::read::coff::*;
use object::read::pe::*;
use object::LittleEndian as LE;
use object::{Bytes, U32Bytes, U64Bytes};
Expand All @@ -20,6 +22,22 @@ pub(super) fn print_coff(p: &mut Printer<'_>, data: &[u8]) {
}
}

pub(super) fn print_coff_big(p: &mut Printer<'_>, data: &[u8]) {
let mut offset = 0;
if let Some(header) = AnonObjectHeaderBigobj::parse(data, &mut offset).print_err(p) {
writeln!(p.w(), "Format: COFF bigobj").unwrap();
print_bigobj(p, header);
let sections = header.sections(data, offset).print_err(p);
let symbols = header.symbols(data).print_err(p);
if let Some(ref sections) = sections {
print_sections(p, data, header.machine.get(LE), symbols.as_ref(), sections);
}
if let Some(ref symbols) = symbols {
print_symbols(p, sections.as_ref(), symbols);
}
}
}

pub(super) fn print_pe32(p: &mut Printer<'_>, data: &[u8]) {
writeln!(p.w(), "Format: PE 32-bit").unwrap();
print_pe::<ImageNtHeaders32>(p, data);
Expand Down Expand Up @@ -166,6 +184,43 @@ fn print_optional(p: &mut Printer<'_>, header: &impl ImageOptionalHeader) {
});
}

fn print_bigobj(p: &mut Printer<'_>, header: &AnonObjectHeaderBigobj) {
p.group("AnonObjectHeaderBigObj", |p| {
p.field_hex("Signature1", header.sig1.get(LE));
p.field_hex("Signature2", header.sig2.get(LE));
p.field("Version", header.version.get(LE));
p.field_enum("Machine", header.machine.get(LE), FLAGS_IMAGE_FILE_MACHINE);
p.field("TimeDateStamp", header.time_date_stamp.get(LE));
p.field(
"ClassId",
format!(
"{:08X}-{:04X}-{:04X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}",
header.class_id.data1().get(LE),
header.class_id.data2().get(LE),
header.class_id.data3().get(LE),
header.class_id.data4()[0],
header.class_id.data4()[1],
header.class_id.data4()[2],
header.class_id.data4()[3],
header.class_id.data4()[4],
header.class_id.data4()[5],
header.class_id.data4()[6],
header.class_id.data4()[7],
),
);
p.field_hex("SizeOfData", header.size_of_data.get(LE));
p.field_hex("Flags", header.flags.get(LE));
p.field_hex("MetaDataSize", header.meta_data_size.get(LE));
p.field_hex("MetaDataOffset", header.meta_data_offset.get(LE));
p.field("NumberOfSections", header.number_of_sections.get(LE));
p.field_hex(
"PointerToSymbolTable",
header.pointer_to_symbol_table.get(LE),
);
p.field("NumberOfSymbols", header.number_of_symbols.get(LE));
});
}

fn print_export_dir(
p: &mut Printer<'_>,
data: &[u8],
Expand Down Expand Up @@ -443,11 +498,11 @@ fn print_resource_table(
})
}

fn print_sections(
fn print_sections<'data, Coff: CoffHeader>(
p: &mut Printer<'_>,
data: &[u8],
machine: u16,
symbols: Option<&SymbolTable>,
symbols: Option<&SymbolTable<'data, &'data [u8], Coff>>,
sections: &SectionTable,
) {
for (index, section) in sections.iter().enumerate() {
Expand Down Expand Up @@ -543,36 +598,44 @@ fn print_sections(
}
}

fn print_symbols(p: &mut Printer<'_>, sections: Option<&SectionTable>, symbols: &SymbolTable) {
fn print_symbols<'data, Coff: CoffHeader>(
p: &mut Printer<'_>,
sections: Option<&SectionTable>,
symbols: &SymbolTable<'data, &'data [u8], Coff>,
) {
for (index, symbol) in symbols.iter() {
p.group("ImageSymbol", |p| {
p.field("Index", index);
if let Some(name) = symbol.name(symbols.strings()).print_err(p) {
p.field_inline_string("Name", name);
} else {
p.field("Name", format!("{:X?}", symbol.name));
p.field("Name", format!("{:X?}", symbol.raw_name()));
}
p.field_hex("Value", symbol.value.get(LE));
let section = symbol.section_number.get(LE);
if section == 0 || section >= IMAGE_SYM_SECTION_MAX {
p.field_enum("Section", section, FLAGS_IMAGE_SYM);
p.field_hex("Value", symbol.value());
let section = symbol.section_number();
if section <= 0 {
p.field_enum_display("Section", section, FLAGS_IMAGE_SYM);
} else {
let section_name = sections.and_then(|sections| {
sections
.section(section.into())
.section(section as usize)
.and_then(|section| section.name(symbols.strings()))
.print_err(p)
});
p.field_string_option("Section", section, section_name);
}
p.field_hex("Type", symbol.typ.get(LE));
p.field_hex("Type", symbol.typ());
p.field_enum("BaseType", symbol.base_type(), FLAGS_IMAGE_SYM_TYPE);
p.field_enum("DerivedType", symbol.derived_type(), FLAGS_IMAGE_SYM_DTYPE);
p.field_enum("StorageClass", symbol.storage_class, FLAGS_IMAGE_SYM_CLASS);
p.field_hex("NumberOfAuxSymbols", symbol.number_of_aux_symbols);
p.field_enum(
"StorageClass",
symbol.storage_class(),
FLAGS_IMAGE_SYM_CLASS,
);
p.field_hex("NumberOfAuxSymbols", symbol.number_of_aux_symbols());
if symbol.has_aux_file_name() {
if let Some(name) = symbols
.aux_file_name(index, symbol.number_of_aux_symbols)
.aux_file_name(index, symbol.number_of_aux_symbols())
.print_err(p)
{
p.group("ImageAuxSymbolFile", |p| {
Expand Down Expand Up @@ -1021,7 +1084,7 @@ static FLAGS_IMAGE_REL_EBC: &[Flag<u16>] = &flags!(
IMAGE_REL_EBC_SECTION,
IMAGE_REL_EBC_SECREL,
);
static FLAGS_IMAGE_SYM: &[Flag<u16>] =
static FLAGS_IMAGE_SYM: &[Flag<i32>] =
&flags!(IMAGE_SYM_UNDEFINED, IMAGE_SYM_ABSOLUTE, IMAGE_SYM_DEBUG,);
static FLAGS_IMAGE_SYM_TYPE: &[Flag<u16>] = &flags!(
IMAGE_SYM_TYPE_NULL,
Expand Down
51 changes: 51 additions & 0 deletions crates/examples/testfiles/pe/base-bigobj.o.objdump
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
Format: Coff Little-endian 32-bit
Kind: Relocatable
Architecture: X86_64
Flags: Coff { characteristics: 0 }
Relative Address Base: 0
Entry Address: 0
Segment { name: ".text", address: 0, size: 0 }
Segment { name: ".data", address: 0, size: 0 }
Segment { name: ".bss", address: 0, size: 0 }
Segment { name: ".xdata", address: 0, size: 0 }
Segment { name: ".pdata", address: 0, size: 0 }
Segment { name: ".rdata", address: 0, size: 0 }
Segment { name: ".rdata$zzz", address: 0, size: 0 }
1: Section { name: ".text", address: 0, size: 80, align: 10, kind: Text, flags: Coff { characteristics: 60500020 } }
2: Section { name: ".data", address: 0, size: 0, align: 10, kind: Data, flags: Coff { characteristics: c0500040 } }
3: Section { name: ".bss", address: 0, size: 0, align: 10, kind: UninitializedData, flags: Coff { characteristics: c0500080 } }
4: Section { name: ".xdata", address: 0, size: 18, align: 4, kind: ReadOnlyData, flags: Coff { characteristics: 40300040 } }
5: Section { name: ".pdata", address: 0, size: 18, align: 4, kind: ReadOnlyData, flags: Coff { characteristics: 40300040 } }
6: Section { name: ".rdata", address: 0, size: 10, align: 10, kind: ReadOnlyData, flags: Coff { characteristics: 40500040 } }
7: Section { name: ".rdata$zzz", address: 0, size: 30, align: 10, kind: ReadOnlyData, flags: Coff { characteristics: 40500040 } }

Symbols
0: Symbol { name: "base.c", address: 0, size: 0, kind: File, section: None, scope: Compilation, weak: false, flags: None }
2: Symbol { name: "printf", address: 0, size: 0, kind: Section, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } }
4: Symbol { name: "main", address: 51, size: 0, kind: Text, section: Section(SectionIndex(1)), scope: Linkage, weak: false, flags: None }
5: Symbol { name: ".text", address: 0, size: 75, kind: Section, section: Section(SectionIndex(1)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } }
7: Symbol { name: ".data", address: 0, size: 0, kind: Section, section: Section(SectionIndex(2)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } }
9: Symbol { name: ".bss", address: 0, size: 0, kind: Section, section: Section(SectionIndex(3)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } }
11: Symbol { name: ".xdata", address: 0, size: 18, kind: Section, section: Section(SectionIndex(4)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } }
13: Symbol { name: ".pdata", address: 0, size: 18, kind: Section, section: Section(SectionIndex(5)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } }
15: Symbol { name: ".rdata", address: 0, size: d, kind: Section, section: Section(SectionIndex(6)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } }
17: Symbol { name: ".rdata$zzz", address: 0, size: 2b, kind: Section, section: Section(SectionIndex(7)), scope: Compilation, weak: false, flags: CoffSection { selection: 0, associative_section: None } }
19: Symbol { name: "__imp___acrt_iob_func", address: 0, size: 0, kind: Data, section: Undefined, scope: Linkage, weak: false, flags: None }
20: Symbol { name: "__main", address: 0, size: 0, kind: Text, section: Undefined, scope: Linkage, weak: false, flags: None }
21: Symbol { name: "__mingw_vfprintf", address: 0, size: 0, kind: Text, section: Undefined, scope: Linkage, weak: false, flags: None }

.text relocations
(2f, Relocation { kind: Relative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(13)), addend: fffffffffffffffc, implicit_addend: true })
(40, Relocation { kind: Relative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(15)), addend: fffffffffffffffc, implicit_addend: true })
(5a, Relocation { kind: Relative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(14)), addend: fffffffffffffffc, implicit_addend: true })
(61, Relocation { kind: Relative, encoding: Generic, size: 20, target: Symbol(SymbolIndex(f)), addend: fffffffffffffffc, implicit_addend: true })

.pdata relocations
(0, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: true })
(4, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: true })
(8, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(b)), addend: 0, implicit_addend: true })
(c, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: true })
(10, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(5)), addend: 0, implicit_addend: true })
(14, Relocation { kind: ImageOffset, encoding: Generic, size: 20, target: Symbol(SymbolIndex(b)), addend: 0, implicit_addend: true })

Dynamic symbols
Loading

0 comments on commit e838b42

Please sign in to comment.