wasmer_compiler_llvm/
object_file.rs

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    // Note: on macOS+Mach-O the personality function *must* be called like this, otherwise LLVM
146    // will generate things differently than "normal", wreaking havoc.
147    //
148    // todo: find out if it is a bug in LLVM or it is expected.
149    "___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    // From elf section index to list of Relocations. Although we use a Vec,
202    // the order of relocations is not important.
203    let mut relocations: HashMap<object::read::SectionIndex, Vec<Relocation>> = HashMap::new();
204
205    // Each iteration of this loop pulls a section and the relocations
206    // that apply to it. We begin with the ".root_section"
207    // section, and then parse all relocation sections that apply to that
208    // section. Those relocations may refer to additional sections which we
209    // then add to the worklist until we've visited the closure of
210    // everything needed to run the code in ".root_section".
211    //
212    // `worklist` is the list of sections we have yet to visit. It never
213    // contains any duplicates or sections we've already visited. `visited`
214    // contains all the sections we've ever added to the worklist in a set
215    // so that we can quickly check whether a section is new before adding
216    // it to worklist. `section_to_custom_section` is filled in with all
217    // the sections we want to include.
218    worklist.push(root_section_index);
219
220    // Add any .eh_frame sections.
221    let mut eh_frame_section_indices = vec![];
222
223    // Add macos-specific unwind sections.
224    let mut compact_unwind_section_indices = vec![];
225
226    // .gcc_except_table sections, which contain the actual LSDA data.
227    // We don't need the actual sections for anything (yet), but trampoline
228    // codegen checks custom section counts to verify there aren't any
229    // unexpected custom sections, so we do a bit of book-keeping here.
230    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                // This allocates a custom section index for the ELF section.
246                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                        // Maybe a libcall then?
301                    } 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                            // (caveat: this comment comes from a point in time after the `addend`
333                            // math in the else branch)
334                            //
335                            // (caveat2: this is mach-o + aarch64 only)
336                            //
337                            // The tampering with the addend in the else branch causes some
338                            // problems with GOT-based relocs, as a non-zero addend has no meaning
339                            // when dealing with GOT entries, for our use-case.
340                            //
341                            // However, for some reasons, it happens that we conceptually need to
342                            // have relocations that pretty much mean "the contents of this GOT
343                            // entry plus a non-zero addend". When in this case, we will later
344                            // perform what is known as "GOT relaxation", i.e. we can change the
345                            // `ldr` opcode to an `add`.
346                            //
347                            // For this to make sense we need to fix the addend to be the delta
348                            // between the section whose address is an entry of the GOT and the
349                            // symbol that is the target of the relocation.
350
351                            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                            // TODO: Encode symbol address into addend, I think this is a bit hacky.
359                            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                    // Wasm-produced object files should never have absolute
391                    // addresses in them because none of the parts of the Wasm
392                    // VM, nor the generated code are loaded at fixed addresses.
393                    return Err(CompileError::Codegen(format!(
394                        "relocation targets absolute address {reloc:?}",
395                    )));
396                }
397
398                // `object::read::RelocationTarget` is a
399                // non-exhaustive enum (`#[non_exhaustive]`), so it
400                // could have additional variants added in the
401                // future. Therefore, when matching against variants
402                // of non-exhaustive enums, an extra wildcard arm must
403                // be added to account for any future variants.
404                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_MOVW_UABS_G0_NC,
436                    },
437                    0,
438                ) => RelocationKind::Arm64Movw0,
439                (
440                    object::Architecture::Aarch64,
441                    object::RelocationFlags::Elf {
442                        r_type: object::elf::R_AARCH64_MOVW_UABS_G1_NC,
443                    },
444                    0,
445                ) => RelocationKind::Arm64Movw1,
446                (
447                    object::Architecture::Aarch64,
448                    object::RelocationFlags::Elf {
449                        r_type: object::elf::R_AARCH64_MOVW_UABS_G2_NC,
450                    },
451                    0,
452                ) => RelocationKind::Arm64Movw2,
453                (
454                    object::Architecture::Aarch64,
455                    object::RelocationFlags::Elf {
456                        r_type: object::elf::R_AARCH64_MOVW_UABS_G3,
457                    },
458                    0,
459                ) => RelocationKind::Arm64Movw3,
460                (
461                    object::Architecture::Riscv64 | object::Architecture::Riscv32,
462                    object::RelocationFlags::Elf {
463                        r_type: object::elf::R_RISCV_64,
464                    },
465                    64,
466                ) => RelocationKind::Abs8,
467                (
468                    object::Architecture::Riscv64 | object::Architecture::Riscv32,
469                    object::RelocationFlags::Elf {
470                        r_type: object::elf::R_RISCV_CALL_PLT,
471                    },
472                    0,
473                ) => RelocationKind::RiscvCall,
474                (
475                    object::Architecture::Riscv64 | object::Architecture::Riscv32,
476                    object::RelocationFlags::Elf {
477                        r_type: object::elf::R_RISCV_PCREL_HI20,
478                    },
479                    0,
480                ) => RelocationKind::RiscvPCRelHi20,
481                (
482                    object::Architecture::Riscv64 | object::Architecture::Riscv32,
483                    object::RelocationFlags::Elf {
484                        r_type: object::elf::R_RISCV_PCREL_LO12_I,
485                    },
486                    0,
487                ) => RelocationKind::RiscvPCRelLo12I,
488                (
489                    object::Architecture::Riscv64,
490                    object::RelocationFlags::Elf {
491                        r_type: object::elf::R_RISCV_ADD8,
492                    },
493                    0,
494                ) => RelocationKind::Add,
495                (
496                    object::Architecture::Riscv64,
497                    object::RelocationFlags::Elf {
498                        r_type: object::elf::R_RISCV_ADD16,
499                    },
500                    0,
501                ) => RelocationKind::Add2,
502                (
503                    object::Architecture::Riscv64,
504                    object::RelocationFlags::Elf {
505                        r_type: object::elf::R_RISCV_ADD32,
506                    },
507                    0,
508                ) => RelocationKind::Add4,
509                (
510                    object::Architecture::Riscv64,
511                    object::RelocationFlags::Elf {
512                        r_type: object::elf::R_RISCV_ADD64,
513                    },
514                    0,
515                ) => RelocationKind::Add8,
516                (
517                    object::Architecture::Riscv64,
518                    object::RelocationFlags::Elf {
519                        r_type: object::elf::R_RISCV_SUB6,
520                    },
521                    0,
522                ) => RelocationKind::Sub6Bits,
523                (
524                    object::Architecture::Riscv64,
525                    object::RelocationFlags::Elf {
526                        r_type: object::elf::R_RISCV_SUB8,
527                    },
528                    0,
529                ) => RelocationKind::Sub,
530                (
531                    object::Architecture::Riscv64,
532                    object::RelocationFlags::Elf {
533                        r_type: object::elf::R_RISCV_SUB16,
534                    },
535                    0,
536                ) => RelocationKind::Sub2,
537                (
538                    object::Architecture::Riscv64,
539                    object::RelocationFlags::Elf {
540                        r_type: object::elf::R_RISCV_SUB32,
541                    },
542                    0,
543                ) => RelocationKind::Sub4,
544                (
545                    object::Architecture::Riscv64,
546                    object::RelocationFlags::Elf {
547                        r_type: object::elf::R_RISCV_SUB64,
548                    },
549                    0,
550                ) => RelocationKind::Sub8,
551                (
552                    object::Architecture::Riscv64,
553                    object::RelocationFlags::Elf {
554                        r_type: object::elf::R_RISCV_SET6,
555                    },
556                    0,
557                ) => RelocationKind::Abs6Bits,
558                (
559                    object::Architecture::Riscv64,
560                    object::RelocationFlags::Elf {
561                        r_type: object::elf::R_RISCV_SET8,
562                    },
563                    0,
564                ) => RelocationKind::Abs,
565                (
566                    object::Architecture::Riscv64,
567                    object::RelocationFlags::Elf {
568                        r_type: object::elf::R_RISCV_SET16,
569                    },
570                    0,
571                ) => RelocationKind::Abs2,
572                (
573                    object::Architecture::Riscv64,
574                    object::RelocationFlags::Elf {
575                        r_type: object::elf::R_RISCV_SET32,
576                    },
577                    0,
578                ) => RelocationKind::Abs4,
579                (
580                    object::Architecture::Riscv64,
581                    object::RelocationFlags::Elf {
582                        r_type: object::elf::R_RISCV_32,
583                    },
584                    32,
585                ) => RelocationKind::Abs4,
586                (
587                    object::Architecture::Riscv64,
588                    object::RelocationFlags::Elf {
589                        r_type: object::elf::R_RISCV_32_PCREL,
590                    },
591                    0,
592                ) => RelocationKind::PCRel4,
593                (
594                    object::Architecture::LoongArch64,
595                    object::RelocationFlags::Elf {
596                        r_type: object::elf::R_LARCH_ABS_HI20,
597                    },
598                    0,
599                ) => RelocationKind::LArchAbsHi20,
600                (
601                    object::Architecture::LoongArch64,
602                    object::RelocationFlags::Elf {
603                        r_type: object::elf::R_LARCH_ABS_LO12,
604                    },
605                    0,
606                ) => RelocationKind::LArchAbsLo12,
607                (
608                    object::Architecture::LoongArch64,
609                    object::RelocationFlags::Elf {
610                        r_type: object::elf::R_LARCH_ABS64_HI12,
611                    },
612                    0,
613                ) => RelocationKind::LArchAbs64Hi12,
614                (
615                    object::Architecture::LoongArch64,
616                    object::RelocationFlags::Elf {
617                        r_type: object::elf::R_LARCH_ABS64_LO20,
618                    },
619                    0,
620                ) => RelocationKind::LArchAbs64Lo20,
621                (
622                    object::Architecture::LoongArch64,
623                    object::RelocationFlags::Elf {
624                        r_type: object::elf::R_LARCH_CALL36,
625                    },
626                    0,
627                ) => RelocationKind::LArchCall36,
628                (
629                    object::Architecture::LoongArch64,
630                    object::RelocationFlags::Elf {
631                        r_type: object::elf::R_LARCH_PCALA_HI20,
632                    },
633                    0,
634                ) => RelocationKind::LArchPCAlaHi20,
635                (
636                    object::Architecture::LoongArch64,
637                    object::RelocationFlags::Elf {
638                        r_type: object::elf::R_LARCH_PCALA_LO12,
639                    },
640                    0,
641                ) => RelocationKind::LArchPCAlaLo12,
642                (
643                    object::Architecture::LoongArch64,
644                    object::RelocationFlags::Elf {
645                        r_type: object::elf::R_LARCH_PCALA64_HI12,
646                    },
647                    0,
648                ) => RelocationKind::LArchPCAla64Hi12,
649                (
650                    object::Architecture::LoongArch64,
651                    object::RelocationFlags::Elf {
652                        r_type: object::elf::R_LARCH_PCALA64_LO20,
653                    },
654                    0,
655                ) => RelocationKind::LArchPCAla64Lo20,
656                (
657                    object::Architecture::Aarch64,
658                    object::RelocationFlags::Elf {
659                        r_type: object::elf::R_AARCH64_ADR_PREL_LO21,
660                    },
661                    0,
662                ) => RelocationKind::Aarch64AdrPrelLo21,
663                (
664                    object::Architecture::LoongArch64,
665                    object::RelocationFlags::Elf {
666                        r_type: object::elf::R_LARCH_64,
667                    },
668                    64,
669                ) => RelocationKind::Abs8,
670                (
671                    object::Architecture::LoongArch64,
672                    object::RelocationFlags::Elf {
673                        r_type: object::elf::R_LARCH_32_PCREL,
674                    },
675                    32,
676                ) => RelocationKind::PCRel4,
677                (
678                    object::Architecture::Aarch64,
679                    object::RelocationFlags::Elf {
680                        r_type: object::elf::R_AARCH64_ADR_PREL_PG_HI21,
681                    },
682                    0,
683                ) => RelocationKind::Aarch64AdrPrelPgHi21,
684                (
685                    object::Architecture::Aarch64,
686                    object::RelocationFlags::Elf {
687                        r_type: object::elf::R_AARCH64_LDST128_ABS_LO12_NC,
688                    },
689                    0,
690                ) => RelocationKind::Aarch64Ldst128AbsLo12Nc,
691                (
692                    object::Architecture::Aarch64,
693                    object::RelocationFlags::Elf {
694                        r_type: object::elf::R_AARCH64_ADD_ABS_LO12_NC,
695                    },
696                    0,
697                ) => RelocationKind::Aarch64AddAbsLo12Nc,
698                (
699                    object::Architecture::Aarch64,
700                    object::RelocationFlags::Elf {
701                        r_type: object::elf::R_AARCH64_LDST64_ABS_LO12_NC,
702                    },
703                    0,
704                ) => RelocationKind::Aarch64Ldst64AbsLo12Nc,
705                (
706                    object::Architecture::Aarch64,
707                    object::RelocationFlags::Elf {
708                        r_type: object::elf::R_AARCH64_PREL64,
709                    },
710                    64,
711                ) => RelocationKind::PCRel8,
712                (
713                    object::Architecture::Aarch64,
714                    object::RelocationFlags::Elf {
715                        r_type: object::elf::R_AARCH64_ABS64,
716                    },
717                    64,
718                ) => RelocationKind::Abs8,
719                (
720                    object::Architecture::Aarch64,
721                    object::RelocationFlags::MachO { r_type: value, .. },
722                    _,
723                ) => match value {
724                    object::macho::ARM64_RELOC_UNSIGNED => RelocationKind::MachoArm64RelocUnsigned,
725                    object::macho::ARM64_RELOC_SUBTRACTOR => {
726                        RelocationKind::MachoArm64RelocSubtractor
727                    }
728                    object::macho::ARM64_RELOC_BRANCH26 => RelocationKind::MachoArm64RelocBranch26,
729                    object::macho::ARM64_RELOC_PAGE21 => RelocationKind::MachoArm64RelocPage21,
730                    object::macho::ARM64_RELOC_PAGEOFF12 => {
731                        RelocationKind::MachoArm64RelocPageoff12
732                    }
733                    object::macho::ARM64_RELOC_GOT_LOAD_PAGE21 => {
734                        RelocationKind::MachoArm64RelocGotLoadPage21
735                    }
736                    object::macho::ARM64_RELOC_GOT_LOAD_PAGEOFF12 => {
737                        RelocationKind::MachoArm64RelocGotLoadPageoff12
738                    }
739                    object::macho::ARM64_RELOC_POINTER_TO_GOT => {
740                        RelocationKind::MachoArm64RelocPointerToGot
741                    }
742                    object::macho::ARM64_RELOC_TLVP_LOAD_PAGE21 => {
743                        RelocationKind::MachoArm64RelocTlvpLoadPage21
744                    }
745                    object::macho::ARM64_RELOC_TLVP_LOAD_PAGEOFF12 => {
746                        RelocationKind::MachoArm64RelocTlvpLoadPageoff12
747                    }
748                    object::macho::ARM64_RELOC_ADDEND => RelocationKind::MachoArm64RelocAddend,
749                    _ => {
750                        return Err(CompileError::Codegen(format!(
751                            "unknown relocation {reloc:?}",
752                        )));
753                    }
754                },
755                (
756                    object::Architecture::X86_64,
757                    object::RelocationFlags::MachO { r_type: value, .. },
758                    _,
759                ) => match value {
760                    object::macho::X86_64_RELOC_UNSIGNED => {
761                        RelocationKind::MachoX86_64RelocUnsigned
762                    }
763                    object::macho::X86_64_RELOC_SIGNED => RelocationKind::MachoX86_64RelocSigned,
764                    object::macho::X86_64_RELOC_BRANCH => RelocationKind::MachoX86_64RelocBranch,
765                    object::macho::X86_64_RELOC_GOT_LOAD => RelocationKind::MachoX86_64RelocGotLoad,
766                    object::macho::X86_64_RELOC_GOT => RelocationKind::MachoX86_64RelocGot,
767                    object::macho::X86_64_RELOC_SUBTRACTOR => {
768                        RelocationKind::MachoX86_64RelocSubtractor
769                    }
770                    object::macho::X86_64_RELOC_SIGNED_1 => RelocationKind::MachoX86_64RelocSigned1,
771                    object::macho::X86_64_RELOC_SIGNED_2 => RelocationKind::MachoX86_64RelocSigned2,
772                    object::macho::X86_64_RELOC_SIGNED_4 => RelocationKind::MachoX86_64RelocSigned4,
773                    object::macho::X86_64_RELOC_TLV => RelocationKind::MachoX86_64RelocTlv,
774                    _ => {
775                        return Err(CompileError::Codegen(format!(
776                            "unknown relocation {reloc:?}"
777                        )));
778                    }
779                },
780                _ => {
781                    return Err(CompileError::Codegen(format!(
782                        "unknown relocation {reloc:?}",
783                    )));
784                }
785            };
786
787            relocations
788                .entry(section_index)
789                .or_default()
790                .push(Relocation {
791                    kind,
792                    reloc_target: target,
793                    offset: offset.try_into().map_err(map_tryfromint_err)?,
794                    addend,
795                });
796        }
797    }
798
799    let eh_frame_section_indices = eh_frame_section_indices
800        .iter()
801        .map(|index| {
802            section_to_custom_section.get(index).map_or_else(
803                || {
804                    Err(CompileError::Codegen(format!(
805                        ".eh_frame section with index={index:?} was never loaded",
806                    )))
807                },
808                |idx| Ok(*idx),
809            )
810        })
811        .collect::<Result<Vec<SectionIndex>, _>>()?;
812
813    let compact_unwind_section_indices = compact_unwind_section_indices
814        .iter()
815        .map(|index| {
816            section_to_custom_section.get(index).map_or_else(
817                || {
818                    Err(CompileError::Codegen(format!(
819                        "_compact_unwind section with index={index:?} was never loaded",
820                    )))
821                },
822                |idx| Ok(*idx),
823            )
824        })
825        .collect::<Result<Vec<SectionIndex>, _>>()?;
826
827    let gcc_except_table_section_indices = gcc_except_table_section_indices
828        .iter()
829        .map(|index| {
830            section_to_custom_section.get(index).map_or_else(
831                || {
832                    Err(CompileError::Codegen(format!(
833                        ".gcc_except_table section with index={index:?} was never loaded",
834                    )))
835                },
836                |idx| Ok(*idx),
837            )
838        })
839        .collect::<Result<Vec<SectionIndex>, _>>()?;
840
841    let data_dw_ref_personality_section_indices = data_dw_ref_personality_section_indices
842        .iter()
843        .map(|index| {
844            section_to_custom_section.get(index).map_or_else(
845                || {
846                    Err(CompileError::Codegen(format!(
847                        ".data.DW.ref.wasmer_eh_personality section with index={index:?} was never loaded",
848                    )))
849                },
850                |idx| Ok(*idx),
851            )
852        })
853        .collect::<Result<Vec<SectionIndex>, _>>()?;
854
855    let mut custom_sections = section_to_custom_section
856        .iter()
857        .map(|(elf_section_index, custom_section_index)| {
858            let section = obj.section_by_index(*elf_section_index).unwrap();
859            (
860                custom_section_index,
861                CustomSection {
862                    protection: CustomSectionProtection::Read,
863                    alignment: Some(section.align()),
864                    bytes: SectionBody::new_with_vec(section.data().unwrap().to_vec()),
865                    relocations: relocations
866                        .remove_entry(elf_section_index)
867                        .map_or(vec![], |(_, v)| v),
868                },
869            )
870        })
871        .collect::<Vec<_>>();
872    custom_sections.sort_unstable_by_key(|a| a.0);
873    let custom_sections = custom_sections
874        .into_iter()
875        .map(|(_, v)| v)
876        .collect::<PrimaryMap<SectionIndex, _>>();
877
878    let function_body = FunctionBody {
879        body: obj
880            .section_by_index(root_section_index)
881            .unwrap()
882            .data()
883            .unwrap()
884            .to_vec(),
885        unwind_info: None,
886    };
887
888    let address_map = FunctionAddressMap {
889        instructions: vec![InstructionAddressMap {
890            srcloc: SourceLoc::default(),
891            code_offset: 0,
892            code_len: function_body.body.len(),
893        }],
894        start_srcloc: SourceLoc::default(),
895        end_srcloc: SourceLoc::default(),
896        body_offset: 0,
897        body_len: function_body.body.len(),
898    };
899
900    Ok(CompiledFunction {
901        compiled_function: wasmer_compiler::types::function::CompiledFunction {
902            body: function_body,
903            relocations: relocations
904                .remove_entry(&root_section_index)
905                .map_or(vec![], |(_, v)| v),
906            frame_info: CompiledFunctionFrameInfo {
907                address_map,
908                traps: vec![],
909            },
910        },
911        custom_sections,
912        eh_frame_section_indices,
913        compact_unwind_section_indices,
914        gcc_except_table_section_indices,
915        data_dw_ref_personality_section_indices,
916    })
917}