]> git.proxmox.com Git - rustc.git/blob - vendor/object/examples/objcopy.rs
New upstream version 1.54.0+dfsg1
[rustc.git] / vendor / object / examples / objcopy.rs
1 use std::collections::HashMap;
2 use std::{env, fs, process};
3
4 use object::{
5 write, Object, ObjectComdat, ObjectSection, ObjectSymbol, RelocationTarget, SectionKind,
6 SymbolFlags, SymbolKind, SymbolSection,
7 };
8
9 fn main() {
10 let mut args = env::args();
11 if args.len() != 3 {
12 eprintln!("Usage: {} <infile> <outfile>", args.next().unwrap());
13 process::exit(1);
14 }
15
16 args.next();
17 let in_file_path = args.next().unwrap();
18 let out_file_path = args.next().unwrap();
19
20 let in_file = match fs::File::open(&in_file_path) {
21 Ok(file) => file,
22 Err(err) => {
23 eprintln!("Failed to open file '{}': {}", in_file_path, err,);
24 process::exit(1);
25 }
26 };
27 let in_file = match unsafe { memmap2::Mmap::map(&in_file) } {
28 Ok(mmap) => mmap,
29 Err(err) => {
30 eprintln!("Failed to map file '{}': {}", in_file_path, err,);
31 process::exit(1);
32 }
33 };
34 let in_object = match object::File::parse(&*in_file) {
35 Ok(object) => object,
36 Err(err) => {
37 eprintln!("Failed to parse file '{}': {}", in_file_path, err);
38 process::exit(1);
39 }
40 };
41
42 let mut out_object = write::Object::new(
43 in_object.format(),
44 in_object.architecture(),
45 in_object.endianness(),
46 );
47 out_object.mangling = write::Mangling::None;
48 out_object.flags = in_object.flags();
49
50 let mut out_sections = HashMap::new();
51 for in_section in in_object.sections() {
52 if in_section.kind() == SectionKind::Metadata {
53 continue;
54 }
55 let section_id = out_object.add_section(
56 in_section
57 .segment_name()
58 .unwrap()
59 .unwrap_or("")
60 .as_bytes()
61 .to_vec(),
62 in_section.name().unwrap().as_bytes().to_vec(),
63 in_section.kind(),
64 );
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());
68 } else {
69 out_section.set_data(in_section.data().unwrap().into(), in_section.align());
70 }
71 out_section.flags = in_section.flags();
72 out_sections.insert(in_section.index(), section_id);
73 }
74
75 let mut out_symbols = HashMap::new();
76 for in_symbol in in_object.symbols() {
77 if in_symbol.kind() == SymbolKind::Null {
78 continue;
79 }
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) {
87 (
88 write::SymbolSection::Section(*out_section),
89 in_symbol.address() - in_object.section_by_index(index).unwrap().address(),
90 )
91 } else {
92 // Ignore symbols for sections that we have skipped.
93 assert_eq!(in_symbol.kind(), SymbolKind::Section);
94 continue;
95 }
96 }
97 _ => panic!("unknown symbol section for {:?}", in_symbol),
98 };
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 {
104 selection,
105 associative_section,
106 } => {
107 let associative_section =
108 associative_section.map(|index| *out_sections.get(&index).unwrap());
109 SymbolFlags::CoffSection {
110 selection,
111 associative_section,
112 }
113 }
114 _ => panic!("unknown symbol flags for {:?}", in_symbol),
115 };
116 let out_symbol = write::Symbol {
117 name: in_symbol.name().unwrap_or("").as_bytes().to_vec(),
118 value,
119 size: in_symbol.size(),
120 kind: in_symbol.kind(),
121 scope: in_symbol.scope(),
122 weak: in_symbol.is_weak(),
123 section,
124 flags,
125 };
126 let symbol_id = out_object.add_symbol(out_symbol);
127 out_symbols.insert(in_symbol.index(), symbol_id);
128 }
129
130 for in_section in in_object.sections() {
131 if in_section.kind() == SectionKind::Metadata {
132 continue;
133 }
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(&section).unwrap())
140 }
141 _ => panic!("unknown relocation target for {:?}", in_relocation),
142 };
143 let out_relocation = write::Relocation {
144 offset,
145 size: in_relocation.size(),
146 kind: in_relocation.kind(),
147 encoding: in_relocation.encoding(),
148 symbol,
149 addend: in_relocation.addend(),
150 };
151 out_object
152 .add_relocation(out_section, out_relocation)
153 .unwrap();
154 }
155 }
156
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());
161 }
162 out_object.add_comdat(write::Comdat {
163 kind: in_comdat.kind(),
164 symbol: *out_symbols.get(&in_comdat.symbol()).unwrap(),
165 sections,
166 });
167 }
168
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);
172 process::exit(1);
173 }
174 }