1use super::error::ObjectError;
2use crate::types::{
3 function::Compilation,
4 relocation::{RelocationKind as Reloc, RelocationTarget},
5 section::{CustomSectionProtection, SectionIndex},
6 symbols::{Symbol, SymbolRegistry},
7 target::{Architecture, BinaryFormat, Endianness, Triple},
8};
9use object::{
10 elf, macho,
11 write::{
12 Object, Relocation, StandardSection, StandardSegment, Symbol as ObjSymbol, SymbolSection,
13 },
14 FileFlags, RelocationEncoding, RelocationKind, SectionKind, SymbolFlags, SymbolKind,
15 SymbolScope,
16};
17use wasmer_types::entity::PrimaryMap;
18use wasmer_types::LocalFunctionIndex;
19
20const DWARF_SECTION_NAME: &[u8] = b".eh_frame";
21
22pub fn get_object_for_target(triple: &Triple) -> Result<Object, ObjectError> {
37 let obj_binary_format = match triple.binary_format {
38 BinaryFormat::Elf => object::BinaryFormat::Elf,
39 BinaryFormat::Macho => object::BinaryFormat::MachO,
40 BinaryFormat::Coff => object::BinaryFormat::Coff,
41 binary_format => {
42 return Err(ObjectError::UnsupportedBinaryFormat(format!(
43 "{}",
44 binary_format
45 )));
46 }
47 };
48 let obj_architecture = match triple.architecture {
49 Architecture::X86_64 => object::Architecture::X86_64,
50 Architecture::Aarch64(_) => object::Architecture::Aarch64,
51 Architecture::Riscv64(_) => object::Architecture::Riscv64,
52 Architecture::LoongArch64 => object::Architecture::LoongArch64,
53 architecture => {
54 return Err(ObjectError::UnsupportedArchitecture(format!(
55 "{}",
56 architecture
57 )));
58 }
59 };
60 let obj_endianness = match triple
61 .endianness()
62 .map_err(|_| ObjectError::UnknownEndianness)?
63 {
64 Endianness::Little => object::Endianness::Little,
65 Endianness::Big => object::Endianness::Big,
66 };
67
68 let mut object = Object::new(obj_binary_format, obj_architecture, obj_endianness);
69
70 if let Architecture::Riscv64(_) = triple.architecture {
71 object.flags = FileFlags::Elf {
72 e_flags: elf::EF_RISCV_FLOAT_ABI_DOUBLE,
73 os_abi: 2,
74 abi_version: 0,
75 };
76 }
77
78 Ok(object)
79}
80
81pub fn emit_data(
97 obj: &mut Object,
98 name: &[u8],
99 data: &[u8],
100 align: u64,
101) -> Result<(), ObjectError> {
102 let symbol_id = obj.add_symbol(ObjSymbol {
103 name: name.to_vec(),
104 value: 0,
105 size: 0,
106 kind: SymbolKind::Data,
107 scope: SymbolScope::Dynamic,
108 weak: false,
109 section: SymbolSection::Undefined,
110 flags: SymbolFlags::None,
111 });
112 let section_id = obj.section_id(StandardSection::Data);
113 obj.add_symbol_data(symbol_id, section_id, data, align);
114
115 Ok(())
116}
117
118pub fn emit_compilation(
137 obj: &mut Object,
138 compilation: Compilation,
139 symbol_registry: &impl SymbolRegistry,
140 triple: &Triple,
141) -> Result<(), ObjectError> {
142 let mut function_bodies = PrimaryMap::with_capacity(compilation.functions.len());
143 let mut function_relocations = PrimaryMap::with_capacity(compilation.functions.len());
144 for (_, func) in compilation.functions.into_iter() {
145 function_bodies.push(func.body);
146 function_relocations.push(func.relocations);
147 }
148 let custom_section_relocations = compilation
149 .custom_sections
150 .iter()
151 .map(|(_, section)| section.relocations.clone())
152 .collect::<PrimaryMap<SectionIndex, _>>();
153
154 let debug_index = compilation.debug.map(|d| d.eh_frame);
155
156 let align = match triple.architecture {
157 Architecture::X86_64 => 1,
158 Architecture::Aarch64(_) => 4,
160 _ => 1,
161 };
162
163 let custom_section_ids = compilation
165 .custom_sections
166 .into_iter()
167 .map(|(section_index, custom_section)| {
168 if debug_index.map_or(false, |d| d == section_index) {
169 let segment = obj.segment_name(StandardSegment::Debug).to_vec();
171 let section_id =
172 obj.add_section(segment, DWARF_SECTION_NAME.to_vec(), SectionKind::Debug);
173 obj.append_section_data(section_id, custom_section.bytes.as_slice(), align);
174 let section_name = symbol_registry.symbol_to_name(Symbol::Section(section_index));
175 let symbol_id = obj.add_symbol(ObjSymbol {
176 name: section_name.into_bytes(),
177 value: 0,
178 size: custom_section.bytes.len() as _,
179 kind: SymbolKind::Data,
180 scope: SymbolScope::Compilation,
181 weak: false,
182 section: SymbolSection::Section(section_id),
183 flags: SymbolFlags::None,
184 });
185 (section_id, symbol_id)
186 } else {
187 let section_name = symbol_registry.symbol_to_name(Symbol::Section(section_index));
188 let (section_kind, standard_section) = match custom_section.protection {
189 CustomSectionProtection::ReadExecute => {
190 (SymbolKind::Text, StandardSection::Text)
191 }
192 CustomSectionProtection::Read => (SymbolKind::Data, StandardSection::Data),
193 };
194 let section_id = obj.section_id(standard_section);
195 let symbol_id = obj.add_symbol(ObjSymbol {
196 name: section_name.into_bytes(),
197 value: 0,
198 size: custom_section.bytes.len() as _,
199 kind: section_kind,
200 scope: SymbolScope::Dynamic,
201 weak: false,
202 section: SymbolSection::Section(section_id),
203 flags: SymbolFlags::None,
204 });
205 obj.add_symbol_data(
206 symbol_id,
207 section_id,
208 custom_section.bytes.as_slice(),
209 align,
210 );
211 (section_id, symbol_id)
212 }
213 })
214 .collect::<PrimaryMap<SectionIndex, _>>();
215
216 let function_symbol_ids = function_bodies
218 .into_iter()
219 .map(|(function_local_index, function)| {
220 let function_name =
221 symbol_registry.symbol_to_name(Symbol::LocalFunction(function_local_index));
222 let section_id = obj.section_id(StandardSection::Text);
223 let symbol_id = obj.add_symbol(ObjSymbol {
224 name: function_name.into_bytes(),
225 value: 0,
226 size: function.body.len() as _,
227 kind: SymbolKind::Text,
228 scope: SymbolScope::Dynamic,
229 weak: false,
230 section: SymbolSection::Section(section_id),
231 flags: SymbolFlags::None,
232 });
233 obj.add_symbol_data(symbol_id, section_id, &function.body, align);
234 (section_id, symbol_id)
235 })
236 .collect::<PrimaryMap<LocalFunctionIndex, _>>();
237
238 for (signature_index, function) in compilation.function_call_trampolines.into_iter() {
240 let function_name =
241 symbol_registry.symbol_to_name(Symbol::FunctionCallTrampoline(signature_index));
242 let section_id = obj.section_id(StandardSection::Text);
243 let symbol_id = obj.add_symbol(ObjSymbol {
244 name: function_name.into_bytes(),
245 value: 0,
246 size: function.body.len() as _,
247 kind: SymbolKind::Text,
248 scope: SymbolScope::Dynamic,
249 weak: false,
250 section: SymbolSection::Section(section_id),
251 flags: SymbolFlags::None,
252 });
253 obj.add_symbol_data(symbol_id, section_id, &function.body, align);
254 }
255
256 for (func_index, function) in compilation.dynamic_function_trampolines.into_iter() {
258 let function_name =
259 symbol_registry.symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index));
260 let section_id = obj.section_id(StandardSection::Text);
261 let symbol_id = obj.add_symbol(ObjSymbol {
262 name: function_name.into_bytes(),
263 value: 0,
264 size: function.body.len() as _,
265 kind: SymbolKind::Text,
266 scope: SymbolScope::Dynamic,
267 weak: false,
268 section: SymbolSection::Section(section_id),
269 flags: SymbolFlags::None,
270 });
271 obj.add_symbol_data(symbol_id, section_id, &function.body, align);
272 }
273
274 let mut all_relocations = Vec::new();
275
276 for (function_local_index, relocations) in function_relocations.into_iter() {
277 let (section_id, symbol_id) = function_symbol_ids.get(function_local_index).unwrap();
278 all_relocations.push((*section_id, *symbol_id, relocations))
279 }
280
281 for (section_index, relocations) in custom_section_relocations.into_iter() {
282 if !debug_index.map_or(false, |d| d == section_index) {
283 let (section_id, symbol_id) = custom_section_ids.get(section_index).unwrap();
285 all_relocations.push((*section_id, *symbol_id, relocations));
286 }
287 }
288
289 for (section_id, symbol_id, relocations) in all_relocations.into_iter() {
290 let (_symbol_id, section_offset) = obj.symbol_section_and_offset(symbol_id).unwrap();
291
292 for r in relocations {
293 let relocation_address = section_offset + r.offset as u64;
294
295 let (relocation_kind, relocation_encoding, relocation_size) = match r.kind {
296 Reloc::Abs4 => (RelocationKind::Absolute, RelocationEncoding::Generic, 32),
297 Reloc::Abs8 => (RelocationKind::Absolute, RelocationEncoding::Generic, 64),
298 Reloc::X86PCRel4 => (RelocationKind::Relative, RelocationEncoding::Generic, 32),
299 Reloc::X86CallPCRel4 => {
300 (RelocationKind::Relative, RelocationEncoding::X86Branch, 32)
301 }
302 Reloc::X86CallPLTRel4 => (
303 RelocationKind::PltRelative,
304 RelocationEncoding::X86Branch,
305 32,
306 ),
307 Reloc::X86GOTPCRel4 => {
308 (RelocationKind::GotRelative, RelocationEncoding::Generic, 32)
309 }
310 Reloc::Arm64Call => (
311 match obj.format() {
312 object::BinaryFormat::Elf => RelocationKind::Elf(elf::R_AARCH64_CALL26),
313 object::BinaryFormat::MachO => RelocationKind::MachO {
314 value: macho::ARM64_RELOC_BRANCH26,
315 relative: true,
316 },
317 fmt => panic!("unsupported binary format {:?}", fmt),
318 },
319 RelocationEncoding::Generic,
320 32,
321 ),
322 Reloc::ElfX86_64TlsGd => (
323 RelocationKind::Elf(elf::R_X86_64_TLSGD),
324 RelocationEncoding::Generic,
325 32,
326 ),
327 other => {
328 return Err(ObjectError::UnsupportedArchitecture(format!(
329 "{} (relocation: {}",
330 triple.architecture, other
331 )))
332 }
333 };
334
335 match r.reloc_target {
336 RelocationTarget::LocalFunc(index) => {
337 let (_, target_symbol) = function_symbol_ids.get(index).unwrap();
338 obj.add_relocation(
339 section_id,
340 Relocation {
341 offset: relocation_address,
342 size: relocation_size,
343 kind: relocation_kind,
344 encoding: relocation_encoding,
345 symbol: *target_symbol,
346 addend: r.addend,
347 },
348 )
349 .map_err(ObjectError::Write)?;
350 }
351 RelocationTarget::LibCall(libcall) => {
352 let libcall_fn_name = libcall.to_function_name().as_bytes();
353 let target_symbol = obj.symbol_id(libcall_fn_name).unwrap_or_else(|| {
355 obj.add_symbol(ObjSymbol {
356 name: libcall_fn_name.to_vec(),
357 value: 0,
358 size: 0,
359 kind: SymbolKind::Unknown,
360 scope: SymbolScope::Unknown,
361 weak: false,
362 section: SymbolSection::Undefined,
363 flags: SymbolFlags::None,
364 })
365 });
366 obj.add_relocation(
367 section_id,
368 Relocation {
369 offset: relocation_address,
370 size: relocation_size,
371 kind: relocation_kind,
372 encoding: relocation_encoding,
373 symbol: target_symbol,
374 addend: r.addend,
375 },
376 )
377 .map_err(ObjectError::Write)?;
378 }
379 RelocationTarget::CustomSection(section_index) => {
380 let (_, target_symbol) = custom_section_ids.get(section_index).unwrap();
381 obj.add_relocation(
382 section_id,
383 Relocation {
384 offset: relocation_address,
385 size: relocation_size,
386 kind: relocation_kind,
387 encoding: relocation_encoding,
388 symbol: *target_symbol,
389 addend: r.addend,
390 },
391 )
392 .map_err(ObjectError::Write)?;
393 }
394 };
395 }
396 }
397
398 Ok(())
399}
400
401pub fn emit_serialized(
421 obj: &mut Object,
422 sercomp: &[u8],
423 triple: &Triple,
424 object_name: &str,
425) -> Result<(), ObjectError> {
426 obj.set_mangling(object::write::Mangling::None);
427 let len_name = format!("{}_LENGTH", object_name);
429 let data_name = format!("{}_DATA", object_name);
430 let align = match triple.architecture {
433 Architecture::X86_64 => 1,
434 Architecture::Aarch64(_) => 4,
436 _ => 1,
437 };
438
439 let len = sercomp.len();
440 let section_id = obj.section_id(StandardSection::Data);
441 let symbol_id = obj.add_symbol(ObjSymbol {
442 name: len_name.as_bytes().to_vec(),
443 value: 0,
444 size: len.to_le_bytes().len() as _,
445 kind: SymbolKind::Data,
446 scope: SymbolScope::Dynamic,
447 weak: false,
448 section: SymbolSection::Section(section_id),
449 flags: SymbolFlags::None,
450 });
451 obj.add_symbol_data(symbol_id, section_id, &len.to_le_bytes(), align);
452
453 let section_id = obj.section_id(StandardSection::Data);
454 let symbol_id = obj.add_symbol(ObjSymbol {
455 name: data_name.as_bytes().to_vec(),
456 value: 0,
457 size: sercomp.len() as _,
458 kind: SymbolKind::Data,
459 scope: SymbolScope::Dynamic,
460 weak: false,
461 section: SymbolSection::Section(section_id),
462 flags: SymbolFlags::None,
463 });
464 obj.add_symbol_data(symbol_id, section_id, sercomp, align);
465
466 Ok(())
467}