Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions examples/objcopy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use std::collections::HashMap;
use std::{env, fs, process};

use object::{
write, Object, ObjectSection, RelocationTarget, SectionKind, SymbolKind, SymbolSection,
write, Object, ObjectSection, RelocationTarget, SectionKind, SymbolFlags, SymbolKind,
SymbolSection,
};

fn main() {
Expand Down Expand Up @@ -40,7 +41,7 @@ fn main() {

let mut out_object = write::Object::new(in_object.format(), in_object.architecture());
out_object.mangling = write::Mangling::None;
// TODO: copy MH_SUBSECTIONS_VIA_SYMBOLS
out_object.flags = in_object.flags();

let mut out_sections = HashMap::new();
for in_section in in_object.sections() {
Expand All @@ -58,6 +59,7 @@ fn main() {
} else {
out_section.set_data(in_section.uncompressed_data().into(), in_section.align());
}
out_section.flags = in_section.flags();
out_sections.insert(in_section.index(), section_id);
}

Expand All @@ -76,6 +78,21 @@ fn main() {
in_symbol.address() - in_object.section_by_index(index).unwrap().address(),
),
};
let flags = match in_symbol.flags() {
SymbolFlags::None => SymbolFlags::None,
SymbolFlags::Elf { st_info, st_other } => SymbolFlags::Elf { st_info, st_other },
SymbolFlags::MachO { n_desc } => SymbolFlags::MachO { n_desc },
SymbolFlags::CoffSection {
selection,
associative_section,
} => {
let associative_section = *out_sections.get(&associative_section).unwrap();
SymbolFlags::CoffSection {
selection,
associative_section,
}
}
};
let out_symbol = write::Symbol {
name: in_symbol.name().unwrap_or("").as_bytes().to_vec(),
value,
Expand All @@ -84,6 +101,7 @@ fn main() {
scope: in_symbol.scope(),
weak: in_symbol.is_weak(),
section,
flags,
};
let symbol_id = out_object.add_symbol(out_symbol);
out_symbols.insert(symbol_index, symbol_id);
Expand Down
70 changes: 70 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,73 @@ pub enum RelocationEncoding {
/// The `RelocationKind` must be PC relative.
X86Branch,
}

/// File flags that are specific to each file format.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FileFlags {
/// No file flags.
None,
/// ELF file flags.
Elf {
/// `e_flags` field in the ELF file header.
e_flags: u32,
},
/// Mach-O file flags.
MachO {
/// `flags` field in the Mach-O file header.
flags: u32,
},
/// COFF file flags.
Coff {
/// `Characteristics` field in the COFF file header.
characteristics: u16,
},
}

/// Section flags that are specific to each file format.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SectionFlags {
/// No section flags.
None,
/// ELF section flags.
Elf {
/// `sh_flags` field in the section header.
sh_flags: u64,
},
/// Mach-O section flags.
MachO {
/// `flags` field in the section header.
flags: u32,
},
/// COFF section flags.
Coff {
/// `Characteristics` field in the section header.
characteristics: u32,
},
}

/// Symbol flags that are specific to each file format.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SymbolFlags<Section> {
/// No symbol flags.
None,
/// ELF symbol flags.
Elf {
/// `st_info` field in the ELF symbol.
st_info: u8,
/// `st_other` field in the ELF symbol.
st_other: u8,
},
/// Mach-O symbol flags.
MachO {
/// `n_desc` field in the Mach-O symbol.
n_desc: u16,
},
/// COFF flags for a section symbol.
CoffSection {
/// `Selection` field in the auxiliary symbol for the section.
selection: u8,
/// `Number` field in the auxiliary symbol for the section.
associative_section: Section,
},
}
12 changes: 10 additions & 2 deletions src/read/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use uuid::Uuid;
use crate::read::wasm;
use crate::read::{coff, elf, macho, pe};
use crate::read::{
Object, ObjectSection, ObjectSegment, Relocation, SectionIndex, SectionKind, Symbol,
SymbolIndex, SymbolMap,
FileFlags, Object, ObjectSection, ObjectSegment, Relocation, SectionFlags, SectionIndex,
SectionKind, Symbol, SymbolIndex, SymbolMap,
};

/// Evaluate an expression on the contents of a file format enum.
Expand Down Expand Up @@ -241,6 +241,10 @@ where
fn entry(&self) -> u64 {
with_inner!(self.inner, FileInternal, |x| x.entry())
}

fn flags(&self) -> FileFlags {
with_inner!(self.inner, FileInternal, |x| x.flags())
}
}

/// An iterator over the segments of a `File`.
Expand Down Expand Up @@ -460,6 +464,10 @@ impl<'data, 'file> ObjectSection<'data> for Section<'data, 'file> {
),
}
}

fn flags(&self) -> SectionFlags {
with_inner!(self.inner, SectionInternal, |x| x.flags())
}
}

/// An iterator over symbol table entries.
Expand Down
55 changes: 40 additions & 15 deletions src/read/coff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use std::{iter, slice};
use target_lexicon::Architecture;

use crate::read::{
self, Object, ObjectSection, ObjectSegment, Relocation, RelocationEncoding, RelocationKind,
RelocationTarget, SectionIndex, SectionKind, Symbol, SymbolIndex, SymbolKind, SymbolMap,
SymbolScope, SymbolSection,
self, FileFlags, Object, ObjectSection, ObjectSegment, Relocation, RelocationEncoding,
RelocationKind, RelocationTarget, SectionFlags, SectionIndex, SectionKind, Symbol, SymbolFlags,
SymbolIndex, SymbolKind, SymbolMap, SymbolScope, SymbolSection,
};

/// A COFF object file.
Expand Down Expand Up @@ -186,6 +186,12 @@ where
fn entry(&self) -> u64 {
0
}

fn flags(&self) -> FileFlags {
FileFlags::Coff {
characteristics: self.coff.header.characteristics,
}
}
}

impl<'data, 'file> Iterator for CoffSegmentIterator<'data, 'file> {
Expand Down Expand Up @@ -272,9 +278,13 @@ impl<'data, 'file> Iterator for CoffSectionIterator<'data, 'file> {

impl<'data, 'file> CoffSection<'data, 'file> {
fn raw_data(&self) -> &'data [u8] {
let offset = self.section.pointer_to_raw_data as usize;
let size = self.section.size_of_raw_data as usize;
&self.file.data[offset..][..size]
if self.section.characteristics & pe::section_table::IMAGE_SCN_CNT_UNINITIALIZED_DATA != 0 {
&[]
} else {
let offset = self.section.pointer_to_raw_data as usize;
let size = self.section.size_of_raw_data as usize;
&self.file.data[offset..][..size]
}
}
}

Expand Down Expand Up @@ -304,10 +314,14 @@ impl<'data, 'file> ObjectSection<'data> for CoffSection<'data, 'file> {

#[inline]
fn file_range(&self) -> Option<(u64, u64)> {
Some((
self.section.pointer_to_raw_data as u64,
self.section.size_of_raw_data as u64,
))
if self.section.characteristics & pe::section_table::IMAGE_SCN_CNT_UNINITIALIZED_DATA != 0 {
None
} else {
Some((
self.section.pointer_to_raw_data as u64,
self.section.size_of_raw_data as u64,
))
}
}

fn data(&self) -> Cow<'data, [u8]> {
Expand Down Expand Up @@ -366,6 +380,12 @@ impl<'data, 'file> ObjectSection<'data> for CoffSection<'data, 'file> {
relocations: self.section.relocations(self.file.data).unwrap_or_default(),
}
}

fn flags(&self) -> SectionFlags {
SectionFlags::Coff {
characteristics: self.section.characteristics,
}
}
}

impl<'data, 'file> fmt::Debug for CoffSymbolIterator<'data, 'file> {
Expand Down Expand Up @@ -411,15 +431,19 @@ fn parse_symbol<'data>(
} else {
SymbolKind::Data
};
let mut flags = SymbolFlags::None;
// FIXME: symbol.value is a section offset for non-absolute symbols, not an address
let (kind, address, size) = match symbol.storage_class {
pe::symbol::IMAGE_SYM_CLASS_STATIC => {
if symbol.value == 0 && symbol.number_of_aux_symbols > 0 {
let size = coff
.symbols
.aux_section_definition(index + 1)
.map(|aux| u64::from(aux.length))
.unwrap_or(0);
let mut size = 0;
if let Some(aux) = coff.symbols.aux_section_definition(index + 1) {
size = u64::from(aux.length);
flags = SymbolFlags::CoffSection {
selection: aux.selection,
associative_section: SectionIndex(aux.number as usize),
};
}
(SymbolKind::Section, 0, size)
} else {
(derived_kind, u64::from(symbol.value), 0)
Expand Down Expand Up @@ -481,6 +505,7 @@ fn parse_symbol<'data>(
section,
weak,
scope,
flags,
}
}

Expand Down
23 changes: 20 additions & 3 deletions src/read/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ use std::{iter, slice};
use target_lexicon::{Aarch64Architecture, Architecture, ArmArchitecture};

use crate::read::{
self, Object, ObjectSection, ObjectSegment, Relocation, RelocationEncoding, RelocationKind,
RelocationTarget, SectionIndex, SectionKind, Symbol, SymbolIndex, SymbolKind, SymbolMap,
SymbolScope, SymbolSection,
self, FileFlags, Object, ObjectSection, ObjectSegment, Relocation, RelocationEncoding,
RelocationKind, RelocationTarget, SectionFlags, SectionIndex, SectionKind, Symbol, SymbolFlags,
SymbolIndex, SymbolKind, SymbolMap, SymbolScope, SymbolSection,
};

/// An ELF object file.
Expand Down Expand Up @@ -224,6 +224,12 @@ where
fn entry(&self) -> u64 {
self.elf.entry
}

fn flags(&self) -> FileFlags {
FileFlags::Elf {
e_flags: self.elf.header.e_flags,
}
}
}

/// An iterator over the segments of an `ElfFile`.
Expand Down Expand Up @@ -530,6 +536,12 @@ impl<'data, 'file> ObjectSection<'data> for ElfSection<'data, 'file> {
relocations: None,
}
}

fn flags(&self) -> SectionFlags {
SectionFlags::Elf {
sh_flags: self.section.sh_flags,
}
}
}

/// An iterator over the symbols of an `ElfFile`.
Expand Down Expand Up @@ -597,6 +609,10 @@ fn parse_symbol<'data>(
}
_ => SymbolScope::Unknown,
};
let flags = SymbolFlags::Elf {
st_info: symbol.st_info,
st_other: symbol.st_other,
};
Symbol {
name,
address: symbol.st_value,
Expand All @@ -605,6 +621,7 @@ fn parse_symbol<'data>(
section,
weak,
scope,
flags,
}
}

Expand Down
23 changes: 20 additions & 3 deletions src/read/macho.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use target_lexicon::{Aarch64Architecture, Architecture, ArmArchitecture};
use uuid::Uuid;

use crate::read::{
self, Object, ObjectSection, ObjectSegment, Relocation, RelocationEncoding, RelocationKind,
RelocationTarget, SectionIndex, SectionKind, Symbol, SymbolIndex, SymbolKind, SymbolMap,
SymbolScope, SymbolSection,
self, FileFlags, Object, ObjectSection, ObjectSegment, Relocation, RelocationEncoding,
RelocationKind, RelocationTarget, SectionFlags, SectionIndex, SectionKind, Symbol, SymbolFlags,
SymbolIndex, SymbolKind, SymbolMap, SymbolScope, SymbolSection,
};

/// A Mach-O object file.
Expand Down Expand Up @@ -173,6 +173,7 @@ where
section: SymbolSection::Undefined,
weak: false,
scope: SymbolScope::Compilation,
flags: SymbolFlags::None,
});
}

Expand Down Expand Up @@ -226,6 +227,12 @@ where
fn entry(&self) -> u64 {
self.macho.entry
}

fn flags(&self) -> FileFlags {
FileFlags::MachO {
flags: self.macho.header.flags,
}
}
}

/// An iterator over the segments of a `MachOFile`.
Expand Down Expand Up @@ -403,6 +410,12 @@ impl<'data, 'file> ObjectSection<'data> for MachOSection<'data, 'file> {
.iter_relocations(self.file.data, self.file.ctx),
}
}

fn flags(&self) -> SectionFlags {
SectionFlags::MachO {
flags: self.internal().section.flags,
}
}
}

#[derive(Debug)]
Expand Down Expand Up @@ -509,6 +522,9 @@ fn parse_symbol<'data>(
} else {
SymbolScope::Dynamic
};
let flags = SymbolFlags::MachO {
n_desc: nlist.n_desc,
};
Some(Symbol {
name: Some(name),
address: nlist.n_value,
Expand All @@ -518,6 +534,7 @@ fn parse_symbol<'data>(
section,
weak,
scope,
flags,
})
}

Expand Down
Loading