1use object::{Object, ObjectSection, ObjectSymbol};
2use target_lexicon::BinaryFormat;
3
4use std::collections::{HashMap, HashSet};
5use std::convert::TryInto;
6use std::num::TryFromIntError;
7
8use wasmer_types::{CompileError, SourceLoc, entity::PrimaryMap};
9
10use wasmer_compiler::types::{
11 address_map::{FunctionAddressMap, InstructionAddressMap},
12 function::{CompiledFunctionFrameInfo, CustomSections, FunctionBody},
13 relocation::{Relocation, RelocationKind, RelocationTarget},
14 section::{CustomSection, CustomSectionProtection, SectionBody, SectionIndex},
15};
16
17use wasmer_vm::libcalls::LibCall;
18
19fn map_tryfromint_err(error: TryFromIntError) -> CompileError {
20 CompileError::Codegen(format!("int doesn't fit: {error}"))
21}
22
23fn map_object_err(error: object::read::Error) -> CompileError {
24 CompileError::Codegen(format!("error parsing object file: {error}"))
25}
26
27#[derive(Debug)]
28pub struct CompiledFunction {
29 pub compiled_function: wasmer_compiler::types::function::CompiledFunction,
30 pub custom_sections: CustomSections,
31 pub eh_frame_section_indices: Vec<SectionIndex>,
32 pub compact_unwind_section_indices: Vec<SectionIndex>,
33 pub gcc_except_table_section_indices: Vec<SectionIndex>,
34 pub data_dw_ref_personality_section_indices: Vec<SectionIndex>,
35}
36
37impl wasmer_compiler::CompiledFunction for CompiledFunction {}
38
39static LIBCALLS_ELF: phf::Map<&'static str, LibCall> = phf::phf_map! {
40 "ceilf" => LibCall::CeilF32,
41 "ceil" => LibCall::CeilF64,
42 "floorf" => LibCall::FloorF32,
43 "floor" => LibCall::FloorF64,
44 "nearbyintf" => LibCall::NearestF32,
45 "nearbyint" => LibCall::NearestF64,
46 "truncf" => LibCall::TruncF32,
47 "trunc" => LibCall::TruncF64,
48 "__chkstk" => LibCall::Probestack,
49 "wasmer_vm_f32_ceil" => LibCall::CeilF32,
50 "wasmer_vm_f64_ceil" => LibCall::CeilF64,
51 "wasmer_vm_f32_floor" => LibCall::FloorF32,
52 "wasmer_vm_f64_floor" => LibCall::FloorF64,
53 "wasmer_vm_f32_nearest" => LibCall::NearestF32,
54 "wasmer_vm_f64_nearest" => LibCall::NearestF64,
55 "wasmer_vm_f32_trunc" => LibCall::TruncF32,
56 "wasmer_vm_f64_trunc" => LibCall::TruncF64,
57 "wasmer_vm_memory32_size" => LibCall::Memory32Size,
58 "wasmer_vm_imported_memory32_size" => LibCall::ImportedMemory32Size,
59 "wasmer_vm_table_copy" => LibCall::TableCopy,
60 "wasmer_vm_table_init" => LibCall::TableInit,
61 "wasmer_vm_table_fill" => LibCall::TableFill,
62 "wasmer_vm_table_size" => LibCall::TableSize,
63 "wasmer_vm_imported_table_size" => LibCall::ImportedTableSize,
64 "wasmer_vm_table_get" => LibCall::TableGet,
65 "wasmer_vm_imported_table_get" => LibCall::ImportedTableGet,
66 "wasmer_vm_table_set" => LibCall::TableSet,
67 "wasmer_vm_imported_table_set" => LibCall::ImportedTableSet,
68 "wasmer_vm_table_grow" => LibCall::TableGrow,
69 "wasmer_vm_imported_table_grow" => LibCall::ImportedTableGrow,
70 "wasmer_vm_func_ref" => LibCall::FuncRef,
71 "wasmer_vm_elem_drop" => LibCall::ElemDrop,
72 "wasmer_vm_memory32_copy" => LibCall::Memory32Copy,
73 "wasmer_vm_imported_memory32_copy" => LibCall::ImportedMemory32Copy,
74 "wasmer_vm_memory32_fill" => LibCall::Memory32Fill,
75 "wasmer_vm_imported_memory32_fill" => LibCall::ImportedMemory32Fill,
76 "wasmer_vm_memory32_init" => LibCall::Memory32Init,
77 "wasmer_vm_data_drop" => LibCall::DataDrop,
78 "wasmer_vm_raise_trap" => LibCall::RaiseTrap,
79 "wasmer_vm_memory32_atomic_wait32" => LibCall::Memory32AtomicWait32,
80 "wasmer_vm_imported_memory32_atomic_wait32" => LibCall::ImportedMemory32AtomicWait32,
81 "wasmer_vm_memory32_atomic_wait64" => LibCall::Memory32AtomicWait64,
82 "wasmer_vm_imported_memory32_atomic_wait64" => LibCall::ImportedMemory32AtomicWait64,
83 "wasmer_vm_memory32_atomic_notify" => LibCall::Memory32AtomicNotify,
84 "wasmer_vm_imported_memory32_atomic_notify" => LibCall::ImportedMemory32AtomicNotify,
85 "wasmer_vm_throw" => LibCall::Throw,
86 "wasmer_vm_alloc_exception" => LibCall::AllocException,
87 "wasmer_vm_read_exnref" => LibCall::ReadExnRef,
88 "wasmer_vm_exception_into_exnref" => LibCall::LibunwindExceptionIntoExnRef,
89 "wasmer_eh_personality" => LibCall::EHPersonality,
90 "wasmer_eh_personality2" => LibCall::EHPersonality2,
91 "wasmer_vm_dbg_usize" => LibCall::DebugUsize,
92 "wasmer_vm_dbg_str" => LibCall::DebugStr,
93};
94
95static LIBCALLS_MACHO: phf::Map<&'static str, LibCall> = phf::phf_map! {
96 "_ceilf" => LibCall::CeilF32,
97 "_ceil" => LibCall::CeilF64,
98 "_floorf" => LibCall::FloorF32,
99 "_floor" => LibCall::FloorF64,
100 "_nearbyintf" => LibCall::NearestF32,
101 "_nearbyint" => LibCall::NearestF64,
102 "_truncf" => LibCall::TruncF32,
103 "_trunc" => LibCall::TruncF64,
104 "_wasmer_vm_f32_ceil" => LibCall::CeilF32,
105 "_wasmer_vm_f64_ceil" => LibCall::CeilF64,
106 "_wasmer_vm_f32_floor" => LibCall::FloorF32,
107 "_wasmer_vm_f64_floor" => LibCall::FloorF64,
108 "_wasmer_vm_f32_nearest" => LibCall::NearestF32,
109 "_wasmer_vm_f64_nearest" => LibCall::NearestF64,
110 "_wasmer_vm_f32_trunc" => LibCall::TruncF32,
111 "_wasmer_vm_f64_trunc" => LibCall::TruncF64,
112 "_wasmer_vm_memory32_size" => LibCall::Memory32Size,
113 "_wasmer_vm_imported_memory32_size" => LibCall::ImportedMemory32Size,
114 "_wasmer_vm_table_copy" => LibCall::TableCopy,
115 "_wasmer_vm_table_init" => LibCall::TableInit,
116 "_wasmer_vm_table_fill" => LibCall::TableFill,
117 "_wasmer_vm_table_size" => LibCall::TableSize,
118 "_wasmer_vm_imported_table_size" => LibCall::ImportedTableSize,
119 "_wasmer_vm_table_get" => LibCall::TableGet,
120 "_wasmer_vm_imported_table_get" => LibCall::ImportedTableGet,
121 "_wasmer_vm_table_set" => LibCall::TableSet,
122 "_wasmer_vm_imported_table_set" => LibCall::ImportedTableSet,
123 "_wasmer_vm_table_grow" => LibCall::TableGrow,
124 "_wasmer_vm_imported_table_grow" => LibCall::ImportedTableGrow,
125 "_wasmer_vm_func_ref" => LibCall::FuncRef,
126 "_wasmer_vm_elem_drop" => LibCall::ElemDrop,
127 "_wasmer_vm_memory32_copy" => LibCall::Memory32Copy,
128 "_wasmer_vm_imported_memory32_copy" => LibCall::ImportedMemory32Copy,
129 "_wasmer_vm_memory32_fill" => LibCall::Memory32Fill,
130 "_wasmer_vm_imported_memory32_fill" => LibCall::ImportedMemory32Fill,
131 "_wasmer_vm_memory32_init" => LibCall::Memory32Init,
132 "_wasmer_vm_data_drop" => LibCall::DataDrop,
133 "_wasmer_vm_raise_trap" => LibCall::RaiseTrap,
134 "_wasmer_vm_memory32_atomic_wait32" => LibCall::Memory32AtomicWait32,
135 "_wasmer_vm_imported_memory32_atomic_wait32" => LibCall::ImportedMemory32AtomicWait32,
136 "_wasmer_vm_memory32_atomic_wait64" => LibCall::Memory32AtomicWait64,
137 "_wasmer_vm_imported_memory32_atomic_wait64" => LibCall::ImportedMemory32AtomicWait64,
138 "_wasmer_vm_memory32_atomic_notify" => LibCall::Memory32AtomicNotify,
139 "_wasmer_vm_imported_memory32_atomic_notify" => LibCall::ImportedMemory32AtomicNotify,
140
141 "_wasmer_vm_throw" => LibCall::Throw,
142 "_wasmer_vm_alloc_exception" => LibCall::AllocException,
143 "_wasmer_vm_read_exnref" => LibCall::ReadExnRef,
144 "_wasmer_vm_exception_into_exnref" => LibCall::LibunwindExceptionIntoExnRef,
145 "___gxx_personality_v0" => LibCall::EHPersonality,
150 "_wasmer_eh_personality2" => LibCall::EHPersonality2,
151 "_wasmer_vm_dbg_usize" => LibCall::DebugUsize,
152 "_wasmer_vm_dbg_str" => LibCall::DebugStr,
153};
154
155pub fn load_object_file<F>(
156 contents: &[u8],
157 root_section: &str,
158 root_section_reloc_target: RelocationTarget,
159 mut symbol_name_to_relocation_target: F,
160 binary_fmt: BinaryFormat,
161) -> Result<CompiledFunction, CompileError>
162where
163 F: FnMut(&str) -> Result<Option<RelocationTarget>, CompileError>,
164{
165 let obj = object::File::parse(contents).map_err(map_object_err)?;
166
167 let libcalls = match binary_fmt {
168 BinaryFormat::Elf => &LIBCALLS_ELF,
169 BinaryFormat::Macho => &LIBCALLS_MACHO,
170 _ => {
171 return Err(CompileError::UnsupportedTarget(format!(
172 "Unsupported binary format {binary_fmt:?}"
173 )));
174 }
175 };
176
177 let mut worklist: Vec<object::read::SectionIndex> = Vec::new();
178 let mut section_targets: HashMap<object::read::SectionIndex, RelocationTarget> = HashMap::new();
179
180 let root_section_index = obj
181 .section_by_name(root_section)
182 .ok_or_else(|| CompileError::Codegen(format!("no section named {root_section}")))?
183 .index();
184
185 let mut section_to_custom_section = HashMap::new();
186
187 section_targets.insert(root_section_index, root_section_reloc_target);
188
189 let mut next_custom_section: u32 = 0;
190
191 let mut elf_section_to_target = |elf_section_index: object::read::SectionIndex| {
192 *section_targets.entry(elf_section_index).or_insert_with(|| {
193 let next = SectionIndex::from_u32(next_custom_section);
194 section_to_custom_section.insert(elf_section_index, next);
195 let target = RelocationTarget::CustomSection(next);
196 next_custom_section += 1;
197 target
198 })
199 };
200
201 let mut relocations: HashMap<object::read::SectionIndex, Vec<Relocation>> = HashMap::new();
204
205 worklist.push(root_section_index);
219
220 let mut eh_frame_section_indices = vec![];
222
223 let mut compact_unwind_section_indices = vec![];
225
226 let mut gcc_except_table_section_indices = vec![];
231
232 let mut data_dw_ref_personality_section_indices = vec![];
233
234 for section in obj.sections() {
235 let index = section.index();
236 let Ok(section_name) = section.name() else {
237 continue;
238 };
239
240 match section_name {
241 "__eh_frame" | ".eh_frame" => {
242 worklist.push(index);
243 eh_frame_section_indices.push(index);
244
245 elf_section_to_target(index);
247 }
248 "__compact_unwind" => {
249 worklist.push(index);
250 compact_unwind_section_indices.push(index);
251
252 elf_section_to_target(index);
253 }
254 ".gcc_except_table" => {
255 worklist.push(index);
256 gcc_except_table_section_indices.push(index);
257
258 elf_section_to_target(index);
259 }
260 ".data.DW.ref.wasmer_eh_personality" => {
261 worklist.push(index);
262 data_dw_ref_personality_section_indices.push(index);
263
264 elf_section_to_target(index);
265 }
266 _ => {}
267 }
268 }
269
270 let mut visited: HashSet<_> = HashSet::from_iter(worklist.iter().copied());
271 while let Some(section_index) = worklist.pop() {
272 let sec = obj
273 .section_by_index(section_index)
274 .map_err(map_object_err)?;
275 let relocs = sec.relocations();
276 for (offset, reloc) in relocs {
277 let mut addend = reloc.addend();
278 let target = match reloc.target() {
279 object::read::RelocationTarget::Symbol(index) => {
280 let symbol = obj.symbol_by_index(index).map_err(map_object_err)?;
281 let symbol_name = symbol.name().map_err(map_object_err)?;
282 if symbol.kind() == object::SymbolKind::Section {
283 match symbol.section() {
284 object::SymbolSection::Section(section_index) => {
285 if section_index == root_section_index {
286 root_section_reloc_target
287 } else {
288 if visited.insert(section_index) {
289 worklist.push(section_index);
290 }
291 elf_section_to_target(section_index)
292 }
293 }
294 _ => {
295 return Err(CompileError::Codegen(format!(
296 "relocation targets unknown section {reloc:?}",
297 )));
298 }
299 }
300 } else if let Some(libcall) = libcalls.get(symbol_name) {
302 RelocationTarget::LibCall(*libcall)
303 } else if let Ok(Some(reloc_target)) =
304 symbol_name_to_relocation_target(symbol_name)
305 {
306 reloc_target
307 } else if let object::SymbolSection::Section(section_index) = symbol.section() {
308 if matches!(
309 reloc.flags(),
310 object::RelocationFlags::MachO {
311 r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12,
312 r_pcrel: false,
313 ..
314 } | object::RelocationFlags::MachO {
315 r_type: object::macho::ARM64_RELOC_POINTER_TO_GOT,
316 r_pcrel: true,
317 ..
318 } | object::RelocationFlags::MachO {
319 r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGE21,
320 r_pcrel: true,
321 ..
322 } | object::RelocationFlags::MachO {
323 r_type: object::macho::ARM64_RELOC_PAGE21,
324 r_pcrel: true,
325 ..
326 } | object::RelocationFlags::MachO {
327 r_type: object::macho::ARM64_RELOC_PAGEOFF12,
328 r_pcrel: false,
329 ..
330 }
331 ) {
332 let symbol_sec = obj
352 .section_by_index(section_index)
353 .map_err(map_object_err)?;
354
355 addend = addend
356 .wrapping_add((symbol.address() - symbol_sec.address()) as i64);
357 } else {
358 addend = addend.wrapping_add(symbol.address() as i64);
360 }
361
362 if section_index == root_section_index {
363 root_section_reloc_target
364 } else {
365 if visited.insert(section_index) {
366 worklist.push(section_index);
367 }
368
369 elf_section_to_target(section_index)
370 }
371 } else {
372 return Err(CompileError::Codegen(format!(
373 "relocation {reloc:?} targets unknown symbol '{symbol:?}'",
374 )));
375 }
376 }
377
378 object::read::RelocationTarget::Section(index) => {
379 if index == root_section_index {
380 root_section_reloc_target
381 } else {
382 if visited.insert(index) {
383 worklist.push(index);
384 }
385 elf_section_to_target(index)
386 }
387 }
388
389 object::read::RelocationTarget::Absolute => {
390 return Err(CompileError::Codegen(format!(
394 "relocation targets absolute address {reloc:?}",
395 )));
396 }
397
398 t => {
405 return Err(CompileError::Codegen(format!(
406 "relocation target is unknown `{t:?}`",
407 )));
408 }
409 };
410 let kind = match (obj.architecture(), reloc.flags(), reloc.size()) {
411 (
412 _,
413 object::RelocationFlags::Elf {
414 r_type: object::elf::R_X86_64_64,
415 },
416 64,
417 ) => RelocationKind::Abs8,
418 (
419 object::Architecture::X86_64,
420 object::RelocationFlags::Elf {
421 r_type: object::elf::R_X86_64_PC64,
422 },
423 0,
424 ) => RelocationKind::PCRel8,
425 (
426 object::Architecture::Aarch64,
427 object::RelocationFlags::Elf {
428 r_type: object::elf::R_AARCH64_CALL26,
429 },
430 26,
431 ) => RelocationKind::Arm64Call,
432 (
433 object::Architecture::Aarch64,
434 object::RelocationFlags::Elf {
435 r_type: object::elf::R_AARCH64_JUMP26,
436 },
437 0,
438 ) => RelocationKind::Arm64Call,
439 (
440 object::Architecture::Aarch64,
441 object::RelocationFlags::Elf {
442 r_type: object::elf::R_AARCH64_MOVW_UABS_G0_NC,
443 },
444 0,
445 ) => RelocationKind::Arm64Movw0,
446 (
447 object::Architecture::Aarch64,
448 object::RelocationFlags::Elf {
449 r_type: object::elf::R_AARCH64_MOVW_UABS_G1_NC,
450 },
451 0,
452 ) => RelocationKind::Arm64Movw1,
453 (
454 object::Architecture::Aarch64,
455 object::RelocationFlags::Elf {
456 r_type: object::elf::R_AARCH64_MOVW_UABS_G2_NC,
457 },
458 0,
459 ) => RelocationKind::Arm64Movw2,
460 (
461 object::Architecture::Aarch64,
462 object::RelocationFlags::Elf {
463 r_type: object::elf::R_AARCH64_MOVW_UABS_G3,
464 },
465 0,
466 ) => RelocationKind::Arm64Movw3,
467 (
468 object::Architecture::Riscv64 | object::Architecture::Riscv32,
469 object::RelocationFlags::Elf {
470 r_type: object::elf::R_RISCV_64,
471 },
472 64,
473 ) => RelocationKind::Abs8,
474 (
475 object::Architecture::Riscv64 | object::Architecture::Riscv32,
476 object::RelocationFlags::Elf {
477 r_type: object::elf::R_RISCV_CALL_PLT,
478 },
479 0,
480 ) => RelocationKind::RiscvCall,
481 (
482 object::Architecture::Riscv64 | object::Architecture::Riscv32,
483 object::RelocationFlags::Elf {
484 r_type: object::elf::R_RISCV_PCREL_HI20,
485 },
486 0,
487 ) => RelocationKind::RiscvPCRelHi20,
488 (
489 object::Architecture::Riscv64 | object::Architecture::Riscv32,
490 object::RelocationFlags::Elf {
491 r_type: object::elf::R_RISCV_PCREL_LO12_I,
492 },
493 0,
494 ) => RelocationKind::RiscvPCRelLo12I,
495 (
496 object::Architecture::Riscv64,
497 object::RelocationFlags::Elf {
498 r_type: object::elf::R_RISCV_ADD8,
499 },
500 0,
501 ) => RelocationKind::Add,
502 (
503 object::Architecture::Riscv64,
504 object::RelocationFlags::Elf {
505 r_type: object::elf::R_RISCV_ADD16,
506 },
507 0,
508 ) => RelocationKind::Add2,
509 (
510 object::Architecture::Riscv64,
511 object::RelocationFlags::Elf {
512 r_type: object::elf::R_RISCV_ADD32,
513 },
514 0,
515 ) => RelocationKind::Add4,
516 (
517 object::Architecture::Riscv64,
518 object::RelocationFlags::Elf {
519 r_type: object::elf::R_RISCV_ADD64,
520 },
521 0,
522 ) => RelocationKind::Add8,
523 (
524 object::Architecture::Riscv64,
525 object::RelocationFlags::Elf {
526 r_type: object::elf::R_RISCV_SUB6,
527 },
528 0,
529 ) => RelocationKind::Sub6Bits,
530 (
531 object::Architecture::Riscv64,
532 object::RelocationFlags::Elf {
533 r_type: object::elf::R_RISCV_SUB8,
534 },
535 0,
536 ) => RelocationKind::Sub,
537 (
538 object::Architecture::Riscv64,
539 object::RelocationFlags::Elf {
540 r_type: object::elf::R_RISCV_SUB16,
541 },
542 0,
543 ) => RelocationKind::Sub2,
544 (
545 object::Architecture::Riscv64,
546 object::RelocationFlags::Elf {
547 r_type: object::elf::R_RISCV_SUB32,
548 },
549 0,
550 ) => RelocationKind::Sub4,
551 (
552 object::Architecture::Riscv64,
553 object::RelocationFlags::Elf {
554 r_type: object::elf::R_RISCV_SUB64,
555 },
556 0,
557 ) => RelocationKind::Sub8,
558 (
559 object::Architecture::Riscv64,
560 object::RelocationFlags::Elf {
561 r_type: object::elf::R_RISCV_SET6,
562 },
563 0,
564 ) => RelocationKind::Abs6Bits,
565 (
566 object::Architecture::Riscv64,
567 object::RelocationFlags::Elf {
568 r_type: object::elf::R_RISCV_SET8,
569 },
570 0,
571 ) => RelocationKind::Abs,
572 (
573 object::Architecture::Riscv64,
574 object::RelocationFlags::Elf {
575 r_type: object::elf::R_RISCV_SET16,
576 },
577 0,
578 ) => RelocationKind::Abs2,
579 (
580 object::Architecture::Riscv64,
581 object::RelocationFlags::Elf {
582 r_type: object::elf::R_RISCV_SET32,
583 },
584 0,
585 ) => RelocationKind::Abs4,
586 (
587 object::Architecture::Riscv64,
588 object::RelocationFlags::Elf {
589 r_type: object::elf::R_RISCV_32,
590 },
591 32,
592 ) => RelocationKind::Abs4,
593 (
594 object::Architecture::Riscv64,
595 object::RelocationFlags::Elf {
596 r_type: object::elf::R_RISCV_32_PCREL,
597 },
598 0,
599 ) => RelocationKind::PCRel4,
600 (
601 object::Architecture::LoongArch64,
602 object::RelocationFlags::Elf {
603 r_type: object::elf::R_LARCH_ABS_HI20,
604 },
605 0,
606 ) => RelocationKind::LArchAbsHi20,
607 (
608 object::Architecture::LoongArch64,
609 object::RelocationFlags::Elf {
610 r_type: object::elf::R_LARCH_ABS_LO12,
611 },
612 0,
613 ) => RelocationKind::LArchAbsLo12,
614 (
615 object::Architecture::LoongArch64,
616 object::RelocationFlags::Elf {
617 r_type: object::elf::R_LARCH_ABS64_HI12,
618 },
619 0,
620 ) => RelocationKind::LArchAbs64Hi12,
621 (
622 object::Architecture::LoongArch64,
623 object::RelocationFlags::Elf {
624 r_type: object::elf::R_LARCH_ABS64_LO20,
625 },
626 0,
627 ) => RelocationKind::LArchAbs64Lo20,
628 (
629 object::Architecture::LoongArch64,
630 object::RelocationFlags::Elf {
631 r_type: object::elf::R_LARCH_CALL36,
632 },
633 0,
634 ) => RelocationKind::LArchCall36,
635 (
636 object::Architecture::LoongArch64,
637 object::RelocationFlags::Elf {
638 r_type: object::elf::R_LARCH_PCALA_HI20,
639 },
640 0,
641 ) => RelocationKind::LArchPCAlaHi20,
642 (
643 object::Architecture::LoongArch64,
644 object::RelocationFlags::Elf {
645 r_type: object::elf::R_LARCH_PCALA_LO12,
646 },
647 0,
648 ) => RelocationKind::LArchPCAlaLo12,
649 (
650 object::Architecture::LoongArch64,
651 object::RelocationFlags::Elf {
652 r_type: object::elf::R_LARCH_PCALA64_HI12,
653 },
654 0,
655 ) => RelocationKind::LArchPCAla64Hi12,
656 (
657 object::Architecture::LoongArch64,
658 object::RelocationFlags::Elf {
659 r_type: object::elf::R_LARCH_PCALA64_LO20,
660 },
661 0,
662 ) => RelocationKind::LArchPCAla64Lo20,
663 (
664 object::Architecture::Aarch64,
665 object::RelocationFlags::Elf {
666 r_type: object::elf::R_AARCH64_ADR_PREL_LO21,
667 },
668 0,
669 ) => RelocationKind::Aarch64AdrPrelLo21,
670 (
671 object::Architecture::LoongArch64,
672 object::RelocationFlags::Elf {
673 r_type: object::elf::R_LARCH_64,
674 },
675 64,
676 ) => RelocationKind::Abs8,
677 (
678 object::Architecture::LoongArch64,
679 object::RelocationFlags::Elf {
680 r_type: object::elf::R_LARCH_32_PCREL,
681 },
682 32,
683 ) => RelocationKind::PCRel4,
684 (
685 object::Architecture::Aarch64,
686 object::RelocationFlags::Elf {
687 r_type: object::elf::R_AARCH64_ADR_PREL_PG_HI21,
688 },
689 0,
690 ) => RelocationKind::Aarch64AdrPrelPgHi21,
691 (
692 object::Architecture::Aarch64,
693 object::RelocationFlags::Elf {
694 r_type: object::elf::R_AARCH64_LDST128_ABS_LO12_NC,
695 },
696 0,
697 ) => RelocationKind::Aarch64Ldst128AbsLo12Nc,
698 (
699 object::Architecture::Aarch64,
700 object::RelocationFlags::Elf {
701 r_type: object::elf::R_AARCH64_ADD_ABS_LO12_NC,
702 },
703 0,
704 ) => RelocationKind::Aarch64AddAbsLo12Nc,
705 (
706 object::Architecture::Aarch64,
707 object::RelocationFlags::Elf {
708 r_type: object::elf::R_AARCH64_LDST64_ABS_LO12_NC,
709 },
710 0,
711 ) => RelocationKind::Aarch64Ldst64AbsLo12Nc,
712 (
713 object::Architecture::Aarch64,
714 object::RelocationFlags::Elf {
715 r_type: object::elf::R_AARCH64_PREL64,
716 },
717 64,
718 ) => RelocationKind::PCRel8,
719 (
720 object::Architecture::Aarch64,
721 object::RelocationFlags::Elf {
722 r_type: object::elf::R_AARCH64_ABS64,
723 },
724 64,
725 ) => RelocationKind::Abs8,
726 (
727 object::Architecture::Aarch64,
728 object::RelocationFlags::MachO { r_type: value, .. },
729 _,
730 ) => match value {
731 object::macho::ARM64_RELOC_UNSIGNED => RelocationKind::MachoArm64RelocUnsigned,
732 object::macho::ARM64_RELOC_SUBTRACTOR => {
733 RelocationKind::MachoArm64RelocSubtractor
734 }
735 object::macho::ARM64_RELOC_BRANCH26 => RelocationKind::MachoArm64RelocBranch26,
736 object::macho::ARM64_RELOC_PAGE21 => RelocationKind::MachoArm64RelocPage21,
737 object::macho::ARM64_RELOC_PAGEOFF12 => {
738 RelocationKind::MachoArm64RelocPageoff12
739 }
740 object::macho::ARM64_RELOC_GOT_LOAD_PAGE21 => {
741 RelocationKind::MachoArm64RelocGotLoadPage21
742 }
743 object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12 => {
744 RelocationKind::MachoArm64RelocGotLoadPageoff12
745 }
746 object::macho::ARM64_RELOC_POINTER_TO_GOT => {
747 RelocationKind::MachoArm64RelocPointerToGot
748 }
749 object::macho::ARM64_RELOC_TLVP_LOAD_PAGE21 => {
750 RelocationKind::MachoArm64RelocTlvpLoadPage21
751 }
752 object::macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12 => {
753 RelocationKind::MachoArm64RelocTlvpLoadPageoff12
754 }
755 object::macho::ARM64_RELOC_ADDEND => RelocationKind::MachoArm64RelocAddend,
756 _ => {
757 return Err(CompileError::Codegen(format!(
758 "unknown relocation {reloc:?}",
759 )));
760 }
761 },
762 (
763 object::Architecture::X86_64,
764 object::RelocationFlags::MachO { r_type: value, .. },
765 _,
766 ) => match value {
767 object::macho::X86_64_RELOC_UNSIGNED => {
768 RelocationKind::MachoX86_64RelocUnsigned
769 }
770 object::macho::X86_64_RELOC_SIGNED => RelocationKind::MachoX86_64RelocSigned,
771 object::macho::X86_64_RELOC_BRANCH => RelocationKind::MachoX86_64RelocBranch,
772 object::macho::X86_64_RELOC_GOT_LOAD => RelocationKind::MachoX86_64RelocGotLoad,
773 object::macho::X86_64_RELOC_GOT => RelocationKind::MachoX86_64RelocGot,
774 object::macho::X86_64_RELOC_SUBTRACTOR => {
775 RelocationKind::MachoX86_64RelocSubtractor
776 }
777 object::macho::X86_64_RELOC_SIGNED_1 => RelocationKind::MachoX86_64RelocSigned1,
778 object::macho::X86_64_RELOC_SIGNED_2 => RelocationKind::MachoX86_64RelocSigned2,
779 object::macho::X86_64_RELOC_SIGNED_4 => RelocationKind::MachoX86_64RelocSigned4,
780 object::macho::X86_64_RELOC_TLV => RelocationKind::MachoX86_64RelocTlv,
781 _ => {
782 return Err(CompileError::Codegen(format!(
783 "unknown relocation {reloc:?}"
784 )));
785 }
786 },
787 _ => {
788 return Err(CompileError::Codegen(format!(
789 "unknown relocation {reloc:?}",
790 )));
791 }
792 };
793
794 relocations
795 .entry(section_index)
796 .or_default()
797 .push(Relocation {
798 kind,
799 reloc_target: target,
800 offset: offset.try_into().map_err(map_tryfromint_err)?,
801 addend,
802 });
803 }
804 }
805
806 let eh_frame_section_indices = eh_frame_section_indices
807 .iter()
808 .map(|index| {
809 section_to_custom_section.get(index).map_or_else(
810 || {
811 Err(CompileError::Codegen(format!(
812 ".eh_frame section with index={index:?} was never loaded",
813 )))
814 },
815 |idx| Ok(*idx),
816 )
817 })
818 .collect::<Result<Vec<SectionIndex>, _>>()?;
819
820 let compact_unwind_section_indices = compact_unwind_section_indices
821 .iter()
822 .map(|index| {
823 section_to_custom_section.get(index).map_or_else(
824 || {
825 Err(CompileError::Codegen(format!(
826 "_compact_unwind section with index={index:?} was never loaded",
827 )))
828 },
829 |idx| Ok(*idx),
830 )
831 })
832 .collect::<Result<Vec<SectionIndex>, _>>()?;
833
834 let gcc_except_table_section_indices = gcc_except_table_section_indices
835 .iter()
836 .map(|index| {
837 section_to_custom_section.get(index).map_or_else(
838 || {
839 Err(CompileError::Codegen(format!(
840 ".gcc_except_table section with index={index:?} was never loaded",
841 )))
842 },
843 |idx| Ok(*idx),
844 )
845 })
846 .collect::<Result<Vec<SectionIndex>, _>>()?;
847
848 let data_dw_ref_personality_section_indices = data_dw_ref_personality_section_indices
849 .iter()
850 .map(|index| {
851 section_to_custom_section.get(index).map_or_else(
852 || {
853 Err(CompileError::Codegen(format!(
854 ".data.DW.ref.wasmer_eh_personality section with index={index:?} was never loaded",
855 )))
856 },
857 |idx| Ok(*idx),
858 )
859 })
860 .collect::<Result<Vec<SectionIndex>, _>>()?;
861
862 let mut custom_sections = section_to_custom_section
863 .iter()
864 .map(|(elf_section_index, custom_section_index)| {
865 let section = obj.section_by_index(*elf_section_index).unwrap();
866 (
867 custom_section_index,
868 CustomSection {
869 protection: CustomSectionProtection::Read,
870 alignment: Some(section.align()),
871 bytes: SectionBody::new_with_vec(section.data().unwrap().to_vec()),
872 relocations: relocations
873 .remove_entry(elf_section_index)
874 .map_or(vec![], |(_, v)| v),
875 },
876 )
877 })
878 .collect::<Vec<_>>();
879 custom_sections.sort_unstable_by_key(|a| a.0);
880 let custom_sections = custom_sections
881 .into_iter()
882 .map(|(_, v)| v)
883 .collect::<PrimaryMap<SectionIndex, _>>();
884
885 let function_body = FunctionBody {
886 body: obj
887 .section_by_index(root_section_index)
888 .unwrap()
889 .data()
890 .unwrap()
891 .to_vec(),
892 unwind_info: None,
893 };
894
895 let address_map = FunctionAddressMap {
896 instructions: vec![InstructionAddressMap {
897 srcloc: SourceLoc::default(),
898 code_offset: 0,
899 code_len: function_body.body.len(),
900 }],
901 start_srcloc: SourceLoc::default(),
902 end_srcloc: SourceLoc::default(),
903 body_offset: 0,
904 body_len: function_body.body.len(),
905 };
906
907 Ok(CompiledFunction {
908 compiled_function: wasmer_compiler::types::function::CompiledFunction {
909 body: function_body,
910 relocations: relocations
911 .remove_entry(&root_section_index)
912 .map_or(vec![], |(_, v)| v),
913 frame_info: CompiledFunctionFrameInfo {
914 address_map,
915 traps: vec![],
916 },
917 },
918 custom_sections,
919 eh_frame_section_indices,
920 compact_unwind_section_indices,
921 gcc_except_table_section_indices,
922 data_dw_ref_personality_section_indices,
923 })
924}