Skip to content

Commit

Permalink
read/pe: add support for base relocations
Browse files Browse the repository at this point in the history
  • Loading branch information
philipc committed Sep 21, 2021
1 parent 27f097a commit 5a4ac36
Show file tree
Hide file tree
Showing 8 changed files with 398 additions and 29 deletions.
92 changes: 67 additions & 25 deletions crates/examples/src/readobj/pe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ fn print_pe<Pe: ImageNtHeaders>(p: &mut Printer<'_>, data: &[u8]) {
p.field_hex("Signature", nt_headers.signature());
});
let header = nt_headers.file_header();
let machine = header.machine.get(LE);
let sections = header.sections(data, offset).print_err(p);
let symbols = header.symbols(data).print_err(p);
print_file(p, header);
Expand All @@ -68,27 +69,15 @@ fn print_pe<Pe: ImageNtHeaders>(p: &mut Printer<'_>, data: &[u8]) {
});
}
if let Some(ref sections) = sections {
print_sections(p, data, header.machine.get(LE), symbols.as_ref(), sections);
print_sections(p, data, machine, symbols.as_ref(), sections);
}
if let Some(ref symbols) = symbols {
print_symbols(p, sections.as_ref(), &symbols);
}
if let Some(ref sections) = sections {
for (index, dir) in data_directories.iter().enumerate() {
if dir.virtual_address.get(LE) == 0 {
continue;
}
match index {
IMAGE_DIRECTORY_ENTRY_EXPORT => {
print_export_dir(p, data, &sections, dir);
}
IMAGE_DIRECTORY_ENTRY_IMPORT => {
print_import_dir::<Pe>(p, data, &sections, dir);
}
// TODO
_ => {}
}
}
print_export_dir(p, data, &sections, &data_directories);
print_import_dir::<Pe>(p, data, &sections, &data_directories);
print_reloc_dir(p, data, machine, &sections, &data_directories);
}
}
}
Expand Down Expand Up @@ -164,10 +153,9 @@ fn print_export_dir(
p: &mut Printer<'_>,
data: &[u8],
sections: &SectionTable,
dir: &ImageDataDirectory,
data_directories: &DataDirectories,
) -> Option<()> {
let dir_data = dir.data(data, sections).print_err(p)?;
let export_dir = ExportTable::parse_directory(data).print_err(p)?;
let export_dir = data_directories.export_dir(data, sections).print_err(p)??;
p.group("ImageExportDirectory", |p| {
p.field_hex("Characteristics", export_dir.characteristics.get(LE));
p.field_hex("TimeDateStamp", export_dir.time_date_stamp.get(LE));
Expand All @@ -186,8 +174,7 @@ fn print_export_dir(
"AddressOfNameOrdinals",
export_dir.address_of_name_ordinals.get(LE),
);
if let Some(export_table) =
ExportTable::parse(dir_data, dir.virtual_address.get(LE)).print_err(p)
if let Some(Some(export_table)) = data_directories.export_table(data, sections).print_err(p)
{
// TODO: the order of the name pointers might be interesting?
let mut names = vec![None; export_table.addresses().len()];
Expand Down Expand Up @@ -240,11 +227,11 @@ fn print_import_dir<Pe: ImageNtHeaders>(
p: &mut Printer<'_>,
data: &[u8],
sections: &SectionTable,
dir: &ImageDataDirectory,
data_directories: &DataDirectories,
) -> Option<()> {
let import_address = dir.virtual_address.get(LE);
let (section_data, section_address) = sections.pe_data_containing(data, import_address)?;
let import_table = ImportTable::new(section_data, section_address, import_address);
let import_table = data_directories
.import_table(data, sections)
.print_err(p)??;
let mut import_descs = import_table.descriptors().print_err(p)?;
p.group("ImageImportDirectory", |p| {
while let Some(Some(import_desc)) = import_descs.next().print_err(p) {
Expand Down Expand Up @@ -454,6 +441,38 @@ fn print_symbols(p: &mut Printer<'_>, sections: Option<&SectionTable>, symbols:
}
}

fn print_reloc_dir(
p: &mut Printer<'_>,
data: &[u8],
machine: u16,
sections: &SectionTable,
data_directories: &DataDirectories,
) -> Option<()> {
let proc = match machine {
IMAGE_FILE_MACHINE_IA64 => FLAGS_IMAGE_REL_IA64_BASED,
IMAGE_FILE_MACHINE_MIPS16 | IMAGE_FILE_MACHINE_MIPSFPU | IMAGE_FILE_MACHINE_MIPSFPU16 => {
FLAGS_IMAGE_REL_MIPS_BASED
}
IMAGE_FILE_MACHINE_ARM => FLAGS_IMAGE_REL_ARM_BASED,
IMAGE_FILE_MACHINE_RISCV32 | IMAGE_FILE_MACHINE_RISCV64 | IMAGE_FILE_MACHINE_RISCV128 => {
FLAGS_IMAGE_REL_RISCV_BASED
}
_ => &[],
};
let mut blocks = data_directories
.relocation_blocks(data, sections)
.print_err(p)??;
while let Some(block) = blocks.next().print_err(p)? {
for reloc in block {
p.group("ImageBaseRelocation", |p| {
p.field_hex("VirtualAddress", reloc.virtual_address);
p.field_enums("Type", reloc.typ, &[FLAGS_IMAGE_REL_BASED, proc]);
});
}
}
Some(())
}

static FLAGS_IMAGE_FILE: &[Flag<u16>] = &flags!(
IMAGE_FILE_RELOCS_STRIPPED,
IMAGE_FILE_EXECUTABLE_IMAGE,
Expand Down Expand Up @@ -930,3 +949,26 @@ static FLAGS_IMAGE_DIRECTORY_ENTRY: &[Flag<usize>] = &flags!(
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT,
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR,
);
static FLAGS_IMAGE_REL_BASED: &[Flag<u16>] = &flags!(
IMAGE_REL_BASED_ABSOLUTE,
IMAGE_REL_BASED_HIGH,
IMAGE_REL_BASED_LOW,
IMAGE_REL_BASED_HIGHLOW,
IMAGE_REL_BASED_HIGHADJ,
IMAGE_REL_BASED_MACHINE_SPECIFIC_5,
IMAGE_REL_BASED_RESERVED,
IMAGE_REL_BASED_MACHINE_SPECIFIC_7,
IMAGE_REL_BASED_MACHINE_SPECIFIC_8,
IMAGE_REL_BASED_MACHINE_SPECIFIC_9,
IMAGE_REL_BASED_DIR64,
);
static FLAGS_IMAGE_REL_IA64_BASED: &[Flag<u16>] = &flags!(IMAGE_REL_BASED_IA64_IMM64,);
static FLAGS_IMAGE_REL_MIPS_BASED: &[Flag<u16>] =
&flags!(IMAGE_REL_BASED_MIPS_JMPADDR, IMAGE_REL_BASED_MIPS_JMPADDR16,);
static FLAGS_IMAGE_REL_ARM_BASED: &[Flag<u16>] =
&flags!(IMAGE_REL_BASED_ARM_MOV32, IMAGE_REL_BASED_THUMB_MOV32,);
static FLAGS_IMAGE_REL_RISCV_BASED: &[Flag<u16>] = &flags!(
IMAGE_REL_BASED_RISCV_HIGH20,
IMAGE_REL_BASED_RISCV_LOW12I,
IMAGE_REL_BASED_RISCV_LOW12S,
);
196 changes: 196 additions & 0 deletions crates/examples/testfiles/pe/base-gnu.exe.readobj
Original file line number Diff line number Diff line change
Expand Up @@ -15441,3 +15441,199 @@ ImageImportDirectory {
}
}
}
ImageBaseRelocation {
VirtualAddress: 0x7BD8
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x8010
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x8080
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x8090
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x80A0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x80A8
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x80B0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x80B8
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x80C0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x80D0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x80E0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9020
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9040
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9048
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9050
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9058
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9680
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9690
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x96A0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x96B0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x96C0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x96D0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x96E0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x96F0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9700
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9710
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9720
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9730
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9740
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9750
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9760
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9770
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9780
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9790
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x97A0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x97B0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x97C0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x97D0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x97E0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x97F0
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9800
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9810
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9820
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9830
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0x9840
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0xE008
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0xE020
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0xE038
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
ImageBaseRelocation {
VirtualAddress: 0xE040
Type: IMAGE_REL_BASED_DIR64 (0xA)
}
8 changes: 8 additions & 0 deletions crates/examples/testfiles/pe/base.exe.readobj.reloc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ImageBaseRelocation {
VirtualAddress: 0x1004
Type: IMAGE_REL_BASED_HIGHLOW (0x3)
}
ImageBaseRelocation {
VirtualAddress: 0x1024
Type: IMAGE_REL_BASED_HIGHLOW (0x3)
}
5 changes: 2 additions & 3 deletions src/pe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1715,12 +1715,11 @@ pub struct ImageLinenumber {
// Based relocation format.
//

// This struct has alignment 1.
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct ImageBaseRelocation {
pub virtual_address: U32Bytes<LE>,
pub size_of_block: U32Bytes<LE>,
pub virtual_address: U32<LE>,
pub size_of_block: U32<LE>,
// pub type_offset[1]: U16<LE>,
}

Expand Down
Loading

0 comments on commit 5a4ac36

Please sign in to comment.