1 use std
::collections
::HashMap
;
2 use std
::{env, fs, process}
;
5 write
, Object
, ObjectComdat
, ObjectSection
, ObjectSymbol
, RelocationTarget
, SectionKind
,
6 SymbolFlags
, SymbolKind
, SymbolSection
,
10 let mut args
= env
::args();
12 eprintln
!("Usage: {} <infile> <outfile>", args
.next().unwrap());
17 let in_file_path
= args
.next().unwrap();
18 let out_file_path
= args
.next().unwrap();
20 let in_file
= match fs
::File
::open(&in_file_path
) {
23 eprintln
!("Failed to open file '{}': {}", in_file_path
, err
,);
27 let in_file
= match unsafe { memmap2::Mmap::map(&in_file) }
{
30 eprintln
!("Failed to map file '{}': {}", in_file_path
, err
,);
34 let in_object
= match object
::File
::parse(&*in_file
) {
37 eprintln
!("Failed to parse file '{}': {}", in_file_path
, err
);
42 let mut out_object
= write
::Object
::new(
44 in_object
.architecture(),
45 in_object
.endianness(),
47 out_object
.mangling
= write
::Mangling
::None
;
48 out_object
.flags
= in_object
.flags();
50 let mut out_sections
= HashMap
::new();
51 for in_section
in in_object
.sections() {
52 if in_section
.kind() == SectionKind
::Metadata
{
55 let section_id
= out_object
.add_section(
62 in_section
.name().unwrap().as_bytes().to_vec(),
65 let out_section
= out_object
.section_mut(section_id
);
66 if out_section
.is_bss() {
67 out_section
.append_bss(in_section
.size(), in_section
.align());
69 out_section
.set_data(in_section
.data().unwrap().into(), in_section
.align());
71 out_section
.flags
= in_section
.flags();
72 out_sections
.insert(in_section
.index(), section_id
);
75 let mut out_symbols
= HashMap
::new();
76 for in_symbol
in in_object
.symbols() {
77 if in_symbol
.kind() == SymbolKind
::Null
{
80 let (section
, value
) = match in_symbol
.section() {
81 SymbolSection
::None
=> (write
::SymbolSection
::None
, in_symbol
.address()),
82 SymbolSection
::Undefined
=> (write
::SymbolSection
::Undefined
, in_symbol
.address()),
83 SymbolSection
::Absolute
=> (write
::SymbolSection
::Absolute
, in_symbol
.address()),
84 SymbolSection
::Common
=> (write
::SymbolSection
::Common
, in_symbol
.address()),
85 SymbolSection
::Section(index
) => {
86 if let Some(out_section
) = out_sections
.get(&index
) {
88 write
::SymbolSection
::Section(*out_section
),
89 in_symbol
.address() - in_object
.section_by_index(index
).unwrap().address(),
92 // Ignore symbols for sections that we have skipped.
93 assert_eq
!(in_symbol
.kind(), SymbolKind
::Section
);
97 _
=> panic
!("unknown symbol section for {:?}", in_symbol
),
99 let flags
= match in_symbol
.flags() {
100 SymbolFlags
::None
=> SymbolFlags
::None
,
101 SymbolFlags
::Elf { st_info, st_other }
=> SymbolFlags
::Elf { st_info, st_other }
,
102 SymbolFlags
::MachO { n_desc }
=> SymbolFlags
::MachO { n_desc }
,
103 SymbolFlags
::CoffSection
{
107 let associative_section
=
108 associative_section
.map(|index
| *out_sections
.get(&index
).unwrap());
109 SymbolFlags
::CoffSection
{
114 _
=> panic
!("unknown symbol flags for {:?}", in_symbol
),
116 let out_symbol
= write
::Symbol
{
117 name
: in_symbol
.name().unwrap_or("").as_bytes().to_vec(),
119 size
: in_symbol
.size(),
120 kind
: in_symbol
.kind(),
121 scope
: in_symbol
.scope(),
122 weak
: in_symbol
.is_weak(),
126 let symbol_id
= out_object
.add_symbol(out_symbol
);
127 out_symbols
.insert(in_symbol
.index(), symbol_id
);
130 for in_section
in in_object
.sections() {
131 if in_section
.kind() == SectionKind
::Metadata
{
134 let out_section
= *out_sections
.get(&in_section
.index()).unwrap();
135 for (offset
, in_relocation
) in in_section
.relocations() {
136 let symbol
= match in_relocation
.target() {
137 RelocationTarget
::Symbol(symbol
) => *out_symbols
.get(&symbol
).unwrap(),
138 RelocationTarget
::Section(section
) => {
139 out_object
.section_symbol(*out_sections
.get(§ion
).unwrap())
141 _
=> panic
!("unknown relocation target for {:?}", in_relocation
),
143 let out_relocation
= write
::Relocation
{
145 size
: in_relocation
.size(),
146 kind
: in_relocation
.kind(),
147 encoding
: in_relocation
.encoding(),
149 addend
: in_relocation
.addend(),
152 .add_relocation(out_section
, out_relocation
)
157 for in_comdat
in in_object
.comdats() {
158 let mut sections
= Vec
::new();
159 for in_section
in in_comdat
.sections() {
160 sections
.push(*out_sections
.get(&in_section
).unwrap());
162 out_object
.add_comdat(write
::Comdat
{
163 kind
: in_comdat
.kind(),
164 symbol
: *out_symbols
.get(&in_comdat
.symbol()).unwrap(),
169 let out_data
= out_object
.write().unwrap();
170 if let Err(err
) = fs
::write(&out_file_path
, out_data
) {
171 eprintln
!("Failed to write file '{}': {}", out_file_path
, err
);