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_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}