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 7da6c7a
Show file tree
Hide file tree
Showing 8 changed files with 374 additions and 5 deletions.
60 changes: 59 additions & 1 deletion 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,7 +69,7 @@ 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);
Expand All @@ -85,6 +86,9 @@ fn print_pe<Pe: ImageNtHeaders>(p: &mut Printer<'_>, data: &[u8]) {
IMAGE_DIRECTORY_ENTRY_IMPORT => {
print_import_dir::<Pe>(p, data, &sections, dir);
}
IMAGE_DIRECTORY_ENTRY_BASERELOC => {
print_reloc_dir(p, data, machine, &sections, dir);
}
// TODO
_ => {}
}
Expand Down Expand Up @@ -454,6 +458,37 @@ fn print_symbols(p: &mut Printer<'_>, sections: Option<&SectionTable>, symbols:
}
}

fn print_reloc_dir(
p: &mut Printer<'_>,
data: &[u8],
machine: u16,
sections: &SectionTable,
dir: &ImageDataDirectory,
) -> 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 dir_data = dir.data(data, sections).print_err(p)?;
let mut blocks = RelocationBlockIterator::new(dir_data);
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 +965,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
18 changes: 17 additions & 1 deletion src/read/pe/data_directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use core::slice;
use crate::read::{ReadError, ReadRef, Result};
use crate::{pe, LittleEndian as LE};

use super::{ExportTable, ImportTable, SectionTable};
use super::{ExportTable, ImportTable, RelocationBlockIterator, SectionTable};

/// The table of data directories in a PE file.
#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -77,6 +77,22 @@ impl<'data> DataDirectories<'data> {
.read_error("Invalid import data dir virtual address")?;
Ok(Some(ImportTable::new(section_data, section_va, import_va)))
}

/// Returns the blocks in the base relocation directory.
///
/// `data` must be the entire file data.
pub fn relocation_blocks<R: ReadRef<'data>>(
&self,
data: R,
sections: &SectionTable<'data>,
) -> Result<Option<RelocationBlockIterator<'data>>> {
let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_BASERELOC) {
Some(data_dir) => data_dir,
None => return Ok(None),
};
let reloc_data = data_dir.data(data, sections)?;
Ok(Some(RelocationBlockIterator::new(reloc_data)))
}
}

impl pe::ImageDataDirectory {
Expand Down
3 changes: 3 additions & 0 deletions src/read/pe/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ pub use export::*;
mod import;
pub use import::*;

mod relocation;
pub use relocation::*;

mod rich;
pub use rich::*;

Expand Down
Loading

0 comments on commit 7da6c7a

Please sign in to comment.