forked from gimli-rs/object
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
macho: add some objcopy tests (gimli-rs#583)
Currently only x86-64 and AArch64 work. i386 and ARM are missing support for scattered relocations and paired relocations. Also add support for an environment variable called OBJECT_TESTFILES_UPDATE which causes the tests to update the output files.
- Loading branch information
Showing
9 changed files
with
972 additions
and
167 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
use std::collections::HashMap; | ||
use std::process; | ||
|
||
use object::{ | ||
write, Object, ObjectComdat, ObjectKind, ObjectSection, ObjectSymbol, RelocationTarget, | ||
SectionKind, SymbolFlags, SymbolKind, SymbolSection, | ||
}; | ||
|
||
pub fn copy(in_data: &[u8]) -> Vec<u8> { | ||
let in_object = match object::File::parse(in_data) { | ||
Ok(object) => object, | ||
Err(err) => { | ||
eprintln!("Failed to parse file: {}", err); | ||
process::exit(1); | ||
} | ||
}; | ||
if in_object.kind() != ObjectKind::Relocatable { | ||
eprintln!("Unsupported object kind: {:?}", in_object.kind()); | ||
process::exit(1); | ||
} | ||
|
||
let mut out_object = write::Object::new( | ||
in_object.format(), | ||
in_object.architecture(), | ||
in_object.endianness(), | ||
); | ||
out_object.mangling = write::Mangling::None; | ||
out_object.flags = in_object.flags(); | ||
|
||
let mut out_sections = HashMap::new(); | ||
for in_section in in_object.sections() { | ||
if in_section.kind() == SectionKind::Metadata { | ||
continue; | ||
} | ||
let section_id = out_object.add_section( | ||
in_section | ||
.segment_name() | ||
.unwrap() | ||
.unwrap_or("") | ||
.as_bytes() | ||
.to_vec(), | ||
in_section.name().unwrap().as_bytes().to_vec(), | ||
in_section.kind(), | ||
); | ||
let out_section = out_object.section_mut(section_id); | ||
if out_section.is_bss() { | ||
out_section.append_bss(in_section.size(), in_section.align()); | ||
} else { | ||
out_section.set_data(in_section.data().unwrap(), in_section.align()); | ||
} | ||
out_section.flags = in_section.flags(); | ||
out_sections.insert(in_section.index(), section_id); | ||
} | ||
|
||
let mut out_symbols = HashMap::new(); | ||
for in_symbol in in_object.symbols() { | ||
if in_symbol.kind() == SymbolKind::Null { | ||
continue; | ||
} | ||
let (section, value) = match in_symbol.section() { | ||
SymbolSection::None => (write::SymbolSection::None, in_symbol.address()), | ||
SymbolSection::Undefined => (write::SymbolSection::Undefined, in_symbol.address()), | ||
SymbolSection::Absolute => (write::SymbolSection::Absolute, in_symbol.address()), | ||
SymbolSection::Common => (write::SymbolSection::Common, in_symbol.address()), | ||
SymbolSection::Section(index) => { | ||
if let Some(out_section) = out_sections.get(&index) { | ||
( | ||
write::SymbolSection::Section(*out_section), | ||
in_symbol.address() - in_object.section_by_index(index).unwrap().address(), | ||
) | ||
} else { | ||
// Ignore symbols for sections that we have skipped. | ||
assert_eq!(in_symbol.kind(), SymbolKind::Section); | ||
continue; | ||
} | ||
} | ||
_ => panic!("unknown symbol section for {:?}", in_symbol), | ||
}; | ||
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 = | ||
associative_section.map(|index| *out_sections.get(&index).unwrap()); | ||
SymbolFlags::CoffSection { | ||
selection, | ||
associative_section, | ||
} | ||
} | ||
SymbolFlags::Xcoff { | ||
n_sclass, | ||
x_smtyp, | ||
x_smclas, | ||
containing_csect, | ||
} => { | ||
let containing_csect = | ||
containing_csect.map(|index| *out_symbols.get(&index).unwrap()); | ||
SymbolFlags::Xcoff { | ||
n_sclass, | ||
x_smtyp, | ||
x_smclas, | ||
containing_csect, | ||
} | ||
} | ||
_ => panic!("unknown symbol flags for {:?}", in_symbol), | ||
}; | ||
let out_symbol = write::Symbol { | ||
name: in_symbol.name().unwrap_or("").as_bytes().to_vec(), | ||
value, | ||
size: in_symbol.size(), | ||
kind: in_symbol.kind(), | ||
scope: in_symbol.scope(), | ||
weak: in_symbol.is_weak(), | ||
section, | ||
flags, | ||
}; | ||
let symbol_id = out_object.add_symbol(out_symbol); | ||
out_symbols.insert(in_symbol.index(), symbol_id); | ||
} | ||
|
||
for in_section in in_object.sections() { | ||
if in_section.kind() == SectionKind::Metadata { | ||
continue; | ||
} | ||
let out_section = *out_sections.get(&in_section.index()).unwrap(); | ||
for (offset, in_relocation) in in_section.relocations() { | ||
let symbol = match in_relocation.target() { | ||
RelocationTarget::Symbol(symbol) => *out_symbols.get(&symbol).unwrap(), | ||
RelocationTarget::Section(section) => { | ||
out_object.section_symbol(*out_sections.get(§ion).unwrap()) | ||
} | ||
_ => panic!("unknown relocation target for {:?}", in_relocation), | ||
}; | ||
let out_relocation = write::Relocation { | ||
offset, | ||
size: in_relocation.size(), | ||
kind: in_relocation.kind(), | ||
encoding: in_relocation.encoding(), | ||
symbol, | ||
addend: in_relocation.addend(), | ||
}; | ||
out_object | ||
.add_relocation(out_section, out_relocation) | ||
.unwrap(); | ||
} | ||
} | ||
|
||
for in_comdat in in_object.comdats() { | ||
let mut sections = Vec::new(); | ||
for in_section in in_comdat.sections() { | ||
sections.push(*out_sections.get(&in_section).unwrap()); | ||
} | ||
out_object.add_comdat(write::Comdat { | ||
kind: in_comdat.kind(), | ||
symbol: *out_symbols.get(&in_comdat.symbol()).unwrap(), | ||
sections, | ||
}); | ||
} | ||
|
||
out_object.write().unwrap() | ||
} |
Oops, something went wrong.