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}
35
36static LIBCALLS_ELF: phf::Map<&'static str, LibCall> = phf::phf_map! {
37 "ceilf" => LibCall::CeilF32,
38 "ceil" => LibCall::CeilF64,
39 "floorf" => LibCall::FloorF32,
40 "floor" => LibCall::FloorF64,
41 "nearbyintf" => LibCall::NearestF32,
42 "nearbyint" => LibCall::NearestF64,
43 "truncf" => LibCall::TruncF32,
44 "trunc" => LibCall::TruncF64,
45 "wasmer_vm_f32_ceil" => LibCall::CeilF32,
46 "wasmer_vm_f64_ceil" => LibCall::CeilF64,
47 "wasmer_vm_f32_floor" => LibCall::FloorF32,
48 "wasmer_vm_f64_floor" => LibCall::FloorF64,
49 "wasmer_vm_f32_nearest" => LibCall::NearestF32,
50 "wasmer_vm_f64_nearest" => LibCall::NearestF64,
51 "wasmer_vm_f32_trunc" => LibCall::TruncF32,
52 "wasmer_vm_f64_trunc" => LibCall::TruncF64,
53 "wasmer_vm_memory32_size" => LibCall::Memory32Size,
54 "wasmer_vm_imported_memory32_size" => LibCall::ImportedMemory32Size,
55 "wasmer_vm_table_copy" => LibCall::TableCopy,
56 "wasmer_vm_table_init" => LibCall::TableInit,
57 "wasmer_vm_table_fill" => LibCall::TableFill,
58 "wasmer_vm_table_size" => LibCall::TableSize,
59 "wasmer_vm_imported_table_size" => LibCall::ImportedTableSize,
60 "wasmer_vm_table_get" => LibCall::TableGet,
61 "wasmer_vm_imported_table_get" => LibCall::ImportedTableGet,
62 "wasmer_vm_table_set" => LibCall::TableSet,
63 "wasmer_vm_imported_table_set" => LibCall::ImportedTableSet,
64 "wasmer_vm_table_grow" => LibCall::TableGrow,
65 "wasmer_vm_imported_table_grow" => LibCall::ImportedTableGrow,
66 "wasmer_vm_func_ref" => LibCall::FuncRef,
67 "wasmer_vm_elem_drop" => LibCall::ElemDrop,
68 "wasmer_vm_memory32_copy" => LibCall::Memory32Copy,
69 "wasmer_vm_imported_memory32_copy" => LibCall::ImportedMemory32Copy,
70 "wasmer_vm_memory32_fill" => LibCall::Memory32Fill,
71 "wasmer_vm_imported_memory32_fill" => LibCall::ImportedMemory32Fill,
72 "wasmer_vm_memory32_init" => LibCall::Memory32Init,
73 "wasmer_vm_data_drop" => LibCall::DataDrop,
74 "wasmer_vm_raise_trap" => LibCall::RaiseTrap,
75 "wasmer_vm_memory32_atomic_wait32" => LibCall::Memory32AtomicWait32,
76 "wasmer_vm_imported_memory32_atomic_wait32" => LibCall::ImportedMemory32AtomicWait32,
77 "wasmer_vm_memory32_atomic_wait64" => LibCall::Memory32AtomicWait64,
78 "wasmer_vm_imported_memory32_atomic_wait64" => LibCall::ImportedMemory32AtomicWait64,
79 "wasmer_vm_memory32_atomic_notify" => LibCall::Memory32AtomicNotify,
80 "wasmer_vm_imported_memory32_atomic_notify" => LibCall::ImportedMemory32AtomicNotify,
81 "wasmer_vm_throw" => LibCall::Throw,
82 "wasmer_vm_alloc_exception" => LibCall::AllocException,
83 "wasmer_vm_read_exnref" => LibCall::ReadExnRef,
84 "wasmer_vm_exception_into_exnref" => LibCall::LibunwindExceptionIntoExnRef,
85 "wasmer_eh_personality" => LibCall::EHPersonality,
86 "wasmer_eh_personality2" => LibCall::EHPersonality2,
87 "wasmer_vm_dbg_usize" => LibCall::DebugUsize,
88 "wasmer_vm_dbg_str" => LibCall::DebugStr,
89};
90
91static LIBCALLS_MACHO: phf::Map<&'static str, LibCall> = phf::phf_map! {
92 "_ceilf" => LibCall::CeilF32,
93 "_ceil" => LibCall::CeilF64,
94 "_floorf" => LibCall::FloorF32,
95 "_floor" => LibCall::FloorF64,
96 "_nearbyintf" => LibCall::NearestF32,
97 "_nearbyint" => LibCall::NearestF64,
98 "_truncf" => LibCall::TruncF32,
99 "_trunc" => LibCall::TruncF64,
100 "_wasmer_vm_f32_ceil" => LibCall::CeilF32,
101 "_wasmer_vm_f64_ceil" => LibCall::CeilF64,
102 "_wasmer_vm_f32_floor" => LibCall::FloorF32,
103 "_wasmer_vm_f64_floor" => LibCall::FloorF64,
104 "_wasmer_vm_f32_nearest" => LibCall::NearestF32,
105 "_wasmer_vm_f64_nearest" => LibCall::NearestF64,
106 "_wasmer_vm_f32_trunc" => LibCall::TruncF32,
107 "_wasmer_vm_f64_trunc" => LibCall::TruncF64,
108 "_wasmer_vm_memory32_size" => LibCall::Memory32Size,
109 "_wasmer_vm_imported_memory32_size" => LibCall::ImportedMemory32Size,
110 "_wasmer_vm_table_copy" => LibCall::TableCopy,
111 "_wasmer_vm_table_init" => LibCall::TableInit,
112 "_wasmer_vm_table_fill" => LibCall::TableFill,
113 "_wasmer_vm_table_size" => LibCall::TableSize,
114 "_wasmer_vm_imported_table_size" => LibCall::ImportedTableSize,
115 "_wasmer_vm_table_get" => LibCall::TableGet,
116 "_wasmer_vm_imported_table_get" => LibCall::ImportedTableGet,
117 "_wasmer_vm_table_set" => LibCall::TableSet,
118 "_wasmer_vm_imported_table_set" => LibCall::ImportedTableSet,
119 "_wasmer_vm_table_grow" => LibCall::TableGrow,
120 "_wasmer_vm_imported_table_grow" => LibCall::ImportedTableGrow,
121 "_wasmer_vm_func_ref" => LibCall::FuncRef,
122 "_wasmer_vm_elem_drop" => LibCall::ElemDrop,
123 "_wasmer_vm_memory32_copy" => LibCall::Memory32Copy,
124 "_wasmer_vm_imported_memory32_copy" => LibCall::ImportedMemory32Copy,
125 "_wasmer_vm_memory32_fill" => LibCall::Memory32Fill,
126 "_wasmer_vm_imported_memory32_fill" => LibCall::ImportedMemory32Fill,
127 "_wasmer_vm_memory32_init" => LibCall::Memory32Init,
128 "_wasmer_vm_data_drop" => LibCall::DataDrop,
129 "_wasmer_vm_raise_trap" => LibCall::RaiseTrap,
130 "_wasmer_vm_memory32_atomic_wait32" => LibCall::Memory32AtomicWait32,
131 "_wasmer_vm_imported_memory32_atomic_wait32" => LibCall::ImportedMemory32AtomicWait32,
132 "_wasmer_vm_memory32_atomic_wait64" => LibCall::Memory32AtomicWait64,
133 "_wasmer_vm_imported_memory32_atomic_wait64" => LibCall::ImportedMemory32AtomicWait64,
134 "_wasmer_vm_memory32_atomic_notify" => LibCall::Memory32AtomicNotify,
135 "_wasmer_vm_imported_memory32_atomic_notify" => LibCall::ImportedMemory32AtomicNotify,
136
137 "_wasmer_vm_throw" => LibCall::Throw,
138 "_wasmer_vm_alloc_exception" => LibCall::AllocException,
139 "_wasmer_vm_read_exnref" => LibCall::ReadExnRef,
140 "_wasmer_vm_exception_into_exnref" => LibCall::LibunwindExceptionIntoExnRef,
141 "___gxx_personality_v0" => LibCall::EHPersonality,
146 "_wasmer_eh_personality2" => LibCall::EHPersonality2,
147 "_wasmer_vm_dbg_usize" => LibCall::DebugUsize,
148 "_wasmer_vm_dbg_str" => LibCall::DebugStr,
149};
150
151pub fn load_object_file<F>(
152 contents: &[u8],
153 root_section: &str,
154 root_section_reloc_target: RelocationTarget,
155 mut symbol_name_to_relocation_target: F,
156 binary_fmt: BinaryFormat,
157) -> Result<CompiledFunction, CompileError>
158where
159 F: FnMut(&str) -> Result<Option<RelocationTarget>, CompileError>,
160{
161 let obj = object::File::parse(contents).map_err(map_object_err)?;
162
163 let libcalls = match binary_fmt {
164 BinaryFormat::Elf => &LIBCALLS_ELF,
165 BinaryFormat::Macho => &LIBCALLS_MACHO,
166 _ => {
167 return Err(CompileError::UnsupportedTarget(format!(
168 "Unsupported binary format {binary_fmt:?}"
169 )));
170 }
171 };
172
173 let mut visited: HashSet<object::read::SectionIndex> = HashSet::new();
174 let mut worklist: Vec<object::read::SectionIndex> = Vec::new();
175 let mut section_targets: HashMap<object::read::SectionIndex, RelocationTarget> = HashMap::new();
176
177 let root_section_index = obj
178 .section_by_name(root_section)
179 .ok_or_else(|| CompileError::Codegen(format!("no section named {root_section}")))?
180 .index();
181
182 let mut section_to_custom_section = HashMap::new();
183
184 section_targets.insert(root_section_index, root_section_reloc_target);
185
186 let mut next_custom_section: u32 = 0;
187
188 let mut elf_section_to_target = |elf_section_index: object::read::SectionIndex| {
189 *section_targets.entry(elf_section_index).or_insert_with(|| {
190 let next = SectionIndex::from_u32(next_custom_section);
191 section_to_custom_section.insert(elf_section_index, next);
192 let target = RelocationTarget::CustomSection(next);
193 next_custom_section += 1;
194 target
195 })
196 };
197
198 let mut relocations: HashMap<object::read::SectionIndex, Vec<Relocation>> = HashMap::new();
201
202 worklist.push(root_section_index);
216 visited.insert(root_section_index);
217
218 let mut eh_frame_section_indices = vec![];
220
221 let mut compact_unwind_section_indices = vec![];
223
224 let mut gcc_except_table_section_indices = vec![];
229
230 for section in obj.sections() {
231 let index = section.index();
232 if section.kind() == object::SectionKind::Elf(object::elf::SHT_X86_64_UNWIND)
233 || section.name().unwrap_or_default() == "__eh_frame"
234 {
235 worklist.push(index);
236 eh_frame_section_indices.push(index);
237
238 elf_section_to_target(index);
240 } else if section.name().unwrap_or_default() == "__compact_unwind" {
241 worklist.push(index);
242 compact_unwind_section_indices.push(index);
243
244 elf_section_to_target(index);
245 } else if section.name().unwrap_or_default() == ".gcc_except_table" {
246 worklist.push(index);
247 gcc_except_table_section_indices.push(index);
248
249 elf_section_to_target(index);
250 }
251 }
252
253 while let Some(section_index) = worklist.pop() {
254 let sec = obj
255 .section_by_index(section_index)
256 .map_err(map_object_err)?;
257 let relocs = sec.relocations();
258 for (offset, reloc) in relocs {
259 let mut addend = reloc.addend();
260 let target = match reloc.target() {
261 object::read::RelocationTarget::Symbol(index) => {
262 let symbol = obj.symbol_by_index(index).map_err(map_object_err)?;
263 let symbol_name = symbol.name().map_err(map_object_err)?;
264 if symbol.kind() == object::SymbolKind::Section {
265 match symbol.section() {
266 object::SymbolSection::Section(section_index) => {
267 if section_index == root_section_index {
268 root_section_reloc_target
269 } else {
270 if visited.insert(section_index) {
271 worklist.push(section_index);
272 }
273 elf_section_to_target(section_index)
274 }
275 }
276 _ => {
277 return Err(CompileError::Codegen(format!(
278 "relocation targets unknown section {reloc:?}",
279 )));
280 }
281 }
282 } else if let Some(libcall) = libcalls.get(symbol_name) {
284 RelocationTarget::LibCall(*libcall)
285 } else if let Ok(Some(reloc_target)) =
286 symbol_name_to_relocation_target(symbol_name)
287 {
288 reloc_target
289 } else if let object::SymbolSection::Section(section_index) = symbol.section() {
290 if matches!(
291 reloc.flags(),
292 object::RelocationFlags::MachO {
293 r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12,
294 r_pcrel: false,
295 ..
296 } | object::RelocationFlags::MachO {
297 r_type: object::macho::ARM64_RELOC_POINTER_TO_GOT,
298 r_pcrel: true,
299 ..
300 } | object::RelocationFlags::MachO {
301 r_type: object::macho::ARM64_RELOC_GOT_LOAD_PAGE21,
302 r_pcrel: true,
303 ..
304 } | object::RelocationFlags::MachO {
305 r_type: object::macho::ARM64_RELOC_PAGE21,
306 r_pcrel: true,
307 ..
308 } | object::RelocationFlags::MachO {
309 r_type: object::macho::ARM64_RELOC_PAGEOFF12,
310 r_pcrel: false,
311 ..
312 }
313 ) {
314 let symbol_sec = obj
334 .section_by_index(section_index)
335 .map_err(map_object_err)?;
336
337 addend = addend
338 .wrapping_add((symbol.address() - symbol_sec.address()) as i64);
339 } else {
340 addend = addend.wrapping_add(symbol.address() as i64);
342 }
343
344 if section_index == root_section_index {
345 root_section_reloc_target
346 } else {
347 if visited.insert(section_index) {
348 worklist.push(section_index);
349 }
350
351 elf_section_to_target(section_index)
352 }
353 } else {
354 return Err(CompileError::Codegen(format!(
355 "relocation {reloc:?} targets unknown symbol '{symbol:?}'",
356 )));
357 }
358 }
359
360 object::read::RelocationTarget::Section(index) => {
361 if index == root_section_index {
362 root_section_reloc_target
363 } else {
364 if visited.insert(index) {
365 worklist.push(index);
366 }
367 elf_section_to_target(index)
368 }
369 }
370
371 object::read::RelocationTarget::Absolute => {
372 return Err(CompileError::Codegen(format!(
376 "relocation targets absolute address {reloc:?}",
377 )));
378 }
379
380 t => {
387 return Err(CompileError::Codegen(format!(
388 "relocation target is unknown `{t:?}`",
389 )));
390 }
391 };
392 let kind = match (obj.architecture(), reloc.flags(), reloc.size()) {
393 (
394 _,
395 object::RelocationFlags::Elf {
396 r_type: object::elf::R_X86_64_64,
397 },
398 64,
399 ) => RelocationKind::Abs8,
400 (
401 _,
402 object::RelocationFlags::Elf {
403 r_type: object::elf::R_386_32,
404 },
405 32,
406 ) => RelocationKind::Abs4,
407 (
408 object::Architecture::X86_64,
409 object::RelocationFlags::Elf {
410 r_type: object::elf::R_X86_64_PC64,
411 },
412 0,
413 ) => RelocationKind::X86PCRel8,
414 (
415 object::Architecture::Aarch64,
416 object::RelocationFlags::Elf {
417 r_type: object::elf::R_AARCH64_CALL26,
418 },
419 26,
420 ) => RelocationKind::Arm64Call,
421 (
422 object::Architecture::Aarch64,
423 object::RelocationFlags::Elf {
424 r_type: object::elf::R_AARCH64_MOVW_UABS_G0_NC,
425 },
426 0,
427 ) => RelocationKind::Arm64Movw0,
428 (
429 object::Architecture::Aarch64,
430 object::RelocationFlags::Elf {
431 r_type: object::elf::R_AARCH64_MOVW_UABS_G1_NC,
432 },
433 0,
434 ) => RelocationKind::Arm64Movw1,
435 (
436 object::Architecture::Aarch64,
437 object::RelocationFlags::Elf {
438 r_type: object::elf::R_AARCH64_MOVW_UABS_G2_NC,
439 },
440 0,
441 ) => RelocationKind::Arm64Movw2,
442 (
443 object::Architecture::Aarch64,
444 object::RelocationFlags::Elf {
445 r_type: object::elf::R_AARCH64_MOVW_UABS_G3,
446 },
447 0,
448 ) => RelocationKind::Arm64Movw3,
449 (
450 object::Architecture::Riscv64,
451 object::RelocationFlags::Elf {
452 r_type: object::elf::R_RISCV_CALL_PLT,
453 },
454 0,
455 ) => RelocationKind::RiscvCall,
456 (
457 object::Architecture::Riscv64,
458 object::RelocationFlags::Elf {
459 r_type: object::elf::R_RISCV_PCREL_HI20,
460 },
461 0,
462 ) => RelocationKind::RiscvPCRelHi20,
463 (
464 object::Architecture::Riscv64,
465 object::RelocationFlags::Elf {
466 r_type: object::elf::R_RISCV_PCREL_LO12_I,
467 },
468 0,
469 ) => RelocationKind::RiscvPCRelLo12I,
470 (
471 object::Architecture::LoongArch64,
472 object::RelocationFlags::Elf {
473 r_type: object::elf::R_LARCH_ABS_HI20,
474 },
475 0,
476 ) => RelocationKind::LArchAbsHi20,
477 (
478 object::Architecture::LoongArch64,
479 object::RelocationFlags::Elf {
480 r_type: object::elf::R_LARCH_ABS_LO12,
481 },
482 0,
483 ) => RelocationKind::LArchAbsLo12,
484 (
485 object::Architecture::LoongArch64,
486 object::RelocationFlags::Elf {
487 r_type: object::elf::R_LARCH_ABS64_HI12,
488 },
489 0,
490 ) => RelocationKind::LArchAbs64Hi12,
491 (
492 object::Architecture::LoongArch64,
493 object::RelocationFlags::Elf {
494 r_type: object::elf::R_LARCH_ABS64_LO20,
495 },
496 0,
497 ) => RelocationKind::LArchAbs64Lo20,
498 (
499 object::Architecture::LoongArch64,
500 object::RelocationFlags::Elf {
501 r_type: object::elf::R_LARCH_CALL36,
502 },
503 0,
504 ) => RelocationKind::LArchCall36,
505 (
506 object::Architecture::LoongArch64,
507 object::RelocationFlags::Elf {
508 r_type: object::elf::R_LARCH_PCALA_HI20,
509 },
510 0,
511 ) => RelocationKind::LArchPCAlaHi20,
512 (
513 object::Architecture::LoongArch64,
514 object::RelocationFlags::Elf {
515 r_type: object::elf::R_LARCH_PCALA_LO12,
516 },
517 0,
518 ) => RelocationKind::LArchPCAlaLo12,
519 (
520 object::Architecture::LoongArch64,
521 object::RelocationFlags::Elf {
522 r_type: object::elf::R_LARCH_PCALA64_HI12,
523 },
524 0,
525 ) => RelocationKind::LArchPCAla64Hi12,
526 (
527 object::Architecture::LoongArch64,
528 object::RelocationFlags::Elf {
529 r_type: object::elf::R_LARCH_PCALA64_LO20,
530 },
531 0,
532 ) => RelocationKind::LArchPCAla64Lo20,
533 (
534 object::Architecture::Aarch64,
535 object::RelocationFlags::Elf {
536 r_type: object::elf::R_AARCH64_ADR_PREL_LO21,
537 },
538 0,
539 ) => RelocationKind::Aarch64AdrPrelLo21,
540 (
541 object::Architecture::Aarch64,
542 object::RelocationFlags::Elf {
543 r_type: object::elf::R_AARCH64_ADR_PREL_PG_HI21,
544 },
545 0,
546 ) => RelocationKind::Aarch64AdrPrelPgHi21,
547 (
548 object::Architecture::Aarch64,
549 object::RelocationFlags::Elf {
550 r_type: object::elf::R_AARCH64_LDST128_ABS_LO12_NC,
551 },
552 0,
553 ) => RelocationKind::Aarch64Ldst128AbsLo12Nc,
554 (
555 object::Architecture::Aarch64,
556 object::RelocationFlags::Elf {
557 r_type: object::elf::R_AARCH64_ADD_ABS_LO12_NC,
558 },
559 0,
560 ) => RelocationKind::Aarch64AddAbsLo12Nc,
561 (
562 object::Architecture::Aarch64,
563 object::RelocationFlags::Elf {
564 r_type: object::elf::R_AARCH64_LDST64_ABS_LO12_NC,
565 },
566 0,
567 ) => RelocationKind::Aarch64Ldst64AbsLo12Nc,
568 (
569 object::Architecture::Aarch64,
570 object::RelocationFlags::MachO { r_type: value, .. },
571 _,
572 ) => match value {
573 object::macho::ARM64_RELOC_UNSIGNED => RelocationKind::MachoArm64RelocUnsigned,
574 object::macho::ARM64_RELOC_SUBTRACTOR => {
575 RelocationKind::MachoArm64RelocSubtractor
576 }
577 object::macho::ARM64_RELOC_BRANCH26 => RelocationKind::MachoArm64RelocBranch26,
578 object::macho::ARM64_RELOC_PAGE21 => RelocationKind::MachoArm64RelocPage21,
579 object::macho::ARM64_RELOC_PAGEOFF12 => {
580 RelocationKind::MachoArm64RelocPageoff12
581 }
582 object::macho::ARM64_RELOC_GOT_LOAD_PAGE21 => {
583 RelocationKind::MachoArm64RelocGotLoadPage21
584 }
585 object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12 => {
586 RelocationKind::MachoArm64RelocGotLoadPageoff12
587 }
588 object::macho::ARM64_RELOC_POINTER_TO_GOT => {
589 RelocationKind::MachoArm64RelocPointerToGot
590 }
591 object::macho::ARM64_RELOC_TLVP_LOAD_PAGE21 => {
592 RelocationKind::MachoArm64RelocTlvpLoadPage21
593 }
594 object::macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12 => {
595 RelocationKind::MachoArm64RelocTlvpLoadPageoff12
596 }
597 object::macho::ARM64_RELOC_ADDEND => RelocationKind::MachoArm64RelocAddend,
598 _ => {
599 return Err(CompileError::Codegen(format!(
600 "unknown relocation {reloc:?}",
601 )));
602 }
603 },
604 (
605 object::Architecture::X86_64,
606 object::RelocationFlags::MachO { r_type: value, .. },
607 _,
608 ) => match value {
609 object::macho::X86_64_RELOC_UNSIGNED => {
610 RelocationKind::MachoX86_64RelocUnsigned
611 }
612 object::macho::X86_64_RELOC_SIGNED => RelocationKind::MachoX86_64RelocSigned,
613 object::macho::X86_64_RELOC_BRANCH => RelocationKind::MachoX86_64RelocBranch,
614 object::macho::X86_64_RELOC_GOT_LOAD => RelocationKind::MachoX86_64RelocGotLoad,
615 object::macho::X86_64_RELOC_GOT => RelocationKind::MachoX86_64RelocGot,
616 object::macho::X86_64_RELOC_SUBTRACTOR => {
617 RelocationKind::MachoX86_64RelocSubtractor
618 }
619 object::macho::X86_64_RELOC_SIGNED_1 => RelocationKind::MachoX86_64RelocSigned1,
620 object::macho::X86_64_RELOC_SIGNED_2 => RelocationKind::MachoX86_64RelocSigned2,
621 object::macho::X86_64_RELOC_SIGNED_4 => RelocationKind::MachoX86_64RelocSigned4,
622 object::macho::X86_64_RELOC_TLV => RelocationKind::MachoX86_64RelocTlv,
623 _ => {
624 return Err(CompileError::Codegen(format!(
625 "unknown relocation {reloc:?}"
626 )));
627 }
628 },
629 _ => {
630 return Err(CompileError::Codegen(format!(
631 "unknown relocation {reloc:?}",
632 )));
633 }
634 };
635
636 relocations
637 .entry(section_index)
638 .or_default()
639 .push(Relocation {
640 kind,
641 reloc_target: target,
642 offset: offset.try_into().map_err(map_tryfromint_err)?,
643 addend,
644 });
645 }
646 }
647
648 let eh_frame_section_indices = eh_frame_section_indices
649 .iter()
650 .map(|index| {
651 section_to_custom_section.get(index).map_or_else(
652 || {
653 Err(CompileError::Codegen(format!(
654 ".eh_frame section with index={index:?} was never loaded",
655 )))
656 },
657 |idx| Ok(*idx),
658 )
659 })
660 .collect::<Result<Vec<SectionIndex>, _>>()?;
661
662 let compact_unwind_section_indices = compact_unwind_section_indices
663 .iter()
664 .map(|index| {
665 section_to_custom_section.get(index).map_or_else(
666 || {
667 Err(CompileError::Codegen(format!(
668 "_compact_unwind section with index={index:?} was never loaded",
669 )))
670 },
671 |idx| Ok(*idx),
672 )
673 })
674 .collect::<Result<Vec<SectionIndex>, _>>()?;
675
676 let gcc_except_table_section_indices = gcc_except_table_section_indices
677 .iter()
678 .map(|index| {
679 section_to_custom_section.get(index).map_or_else(
680 || {
681 Err(CompileError::Codegen(format!(
682 ".gcc_except_table section with index={index:?} was never loaded",
683 )))
684 },
685 |idx| Ok(*idx),
686 )
687 })
688 .collect::<Result<Vec<SectionIndex>, _>>()?;
689
690 let mut custom_sections = section_to_custom_section
691 .iter()
692 .map(|(elf_section_index, custom_section_index)| {
693 let section = obj.section_by_index(*elf_section_index).unwrap();
694 (
695 custom_section_index,
696 CustomSection {
697 protection: CustomSectionProtection::Read,
698 alignment: Some(section.align()),
699 bytes: SectionBody::new_with_vec(section.data().unwrap().to_vec()),
700 relocations: relocations
701 .remove_entry(elf_section_index)
702 .map_or(vec![], |(_, v)| v),
703 },
704 )
705 })
706 .collect::<Vec<_>>();
707 custom_sections.sort_unstable_by_key(|a| a.0);
708 let custom_sections = custom_sections
709 .into_iter()
710 .map(|(_, v)| v)
711 .collect::<PrimaryMap<SectionIndex, _>>();
712
713 let function_body = FunctionBody {
714 body: obj
715 .section_by_index(root_section_index)
716 .unwrap()
717 .data()
718 .unwrap()
719 .to_vec(),
720 unwind_info: None,
721 };
722
723 let address_map = FunctionAddressMap {
724 instructions: vec![InstructionAddressMap {
725 srcloc: SourceLoc::default(),
726 code_offset: 0,
727 code_len: function_body.body.len(),
728 }],
729 start_srcloc: SourceLoc::default(),
730 end_srcloc: SourceLoc::default(),
731 body_offset: 0,
732 body_len: function_body.body.len(),
733 };
734
735 Ok(CompiledFunction {
736 compiled_function: wasmer_compiler::types::function::CompiledFunction {
737 body: function_body,
738 relocations: relocations
739 .remove_entry(&root_section_index)
740 .map_or(vec![], |(_, v)| v),
741 frame_info: CompiledFunctionFrameInfo {
742 address_map,
743 traps: vec![],
744 },
745 },
746 custom_sections,
747 eh_frame_section_indices,
748 compact_unwind_section_indices,
749 gcc_except_table_section_indices,
750 })
751}