Migrating code to object (from faerie) (#1848)
* Using the "object" library everywhere in wasmtime. * scroll_derive
This commit is contained in:
@@ -3,8 +3,10 @@
|
||||
#![allow(clippy::cast_ptr_alignment)]
|
||||
|
||||
use anyhow::Error;
|
||||
use faerie::{Artifact, Decl, SectionKind};
|
||||
use more_asserts::assert_gt;
|
||||
use object::write::{Object, Relocation, StandardSegment};
|
||||
use object::{RelocationEncoding, RelocationKind, SectionKind};
|
||||
use std::collections::HashMap;
|
||||
use target_lexicon::BinaryFormat;
|
||||
use wasmtime_environ::isa::TargetIsa;
|
||||
|
||||
@@ -16,25 +18,35 @@ mod read_debuginfo;
|
||||
mod transform;
|
||||
mod write_debuginfo;
|
||||
|
||||
pub fn write_debugsections(obj: &mut Artifact, sections: Vec<DwarfSection>) -> Result<(), Error> {
|
||||
pub fn write_debugsections(obj: &mut Object, sections: Vec<DwarfSection>) -> Result<(), Error> {
|
||||
let (bodies, relocs) = sections
|
||||
.into_iter()
|
||||
.map(|s| ((s.name.clone(), s.body), (s.name, s.relocs)))
|
||||
.unzip::<_, _, Vec<_>, Vec<_>>();
|
||||
let mut ids = HashMap::new();
|
||||
for (name, body) in bodies {
|
||||
obj.declare_with(name, Decl::section(SectionKind::Debug), body)?;
|
||||
let segment = obj.segment_name(StandardSegment::Debug).to_vec();
|
||||
let section_id = obj.add_section(segment, name.as_bytes().to_vec(), SectionKind::Debug);
|
||||
ids.insert(name, section_id);
|
||||
obj.append_section_data(section_id, &body, 1);
|
||||
}
|
||||
for (name, relocs) in relocs {
|
||||
let section_id = *ids.get(&name).unwrap();
|
||||
for reloc in relocs {
|
||||
obj.link_with(
|
||||
faerie::Link {
|
||||
from: &name,
|
||||
to: &reloc.target,
|
||||
at: reloc.offset as u64,
|
||||
},
|
||||
faerie::Reloc::Debug {
|
||||
size: reloc.size,
|
||||
addend: reloc.addend,
|
||||
let target_symbol = if reloc.target.starts_with("_wasm_function") {
|
||||
obj.symbol_id(reloc.target.as_bytes()).unwrap()
|
||||
} else {
|
||||
obj.section_symbol(*ids.get(&reloc.target).unwrap())
|
||||
};
|
||||
obj.add_relocation(
|
||||
section_id,
|
||||
Relocation {
|
||||
offset: u64::from(reloc.offset),
|
||||
size: reloc.size << 3,
|
||||
kind: RelocationKind::Absolute,
|
||||
encoding: RelocationEncoding::Generic,
|
||||
symbol: target_symbol,
|
||||
addend: i64::from(reloc.addend),
|
||||
},
|
||||
)?;
|
||||
}
|
||||
@@ -79,13 +91,14 @@ pub fn write_debugsections_image(
|
||||
code_region: (*const u8, usize),
|
||||
funcs: &[*const u8],
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
let mut obj = Artifact::new(isa.triple().clone(), String::from("module"));
|
||||
let mut obj = Object::new(BinaryFormat::Elf, isa.triple().architecture);
|
||||
|
||||
assert!(!code_region.0.is_null() && code_region.1 > 0);
|
||||
assert_gt!(funcs.len(), 0);
|
||||
|
||||
let body = unsafe { std::slice::from_raw_parts(code_region.0, code_region.1) };
|
||||
obj.declare_with("all", Decl::function(), body.to_vec())?;
|
||||
let section_id = obj.add_section(vec![], ".text.all".as_bytes().to_vec(), SectionKind::Text);
|
||||
obj.append_section_data(section_id, body, 1);
|
||||
|
||||
// Get DWARF sections and patch relocs
|
||||
patch_dwarf_sections(&mut sections, funcs);
|
||||
@@ -93,17 +106,17 @@ pub fn write_debugsections_image(
|
||||
write_debugsections(&mut obj, sections)?;
|
||||
|
||||
// LLDB is too "magical" about mach-o, generating elf
|
||||
let mut bytes = obj.emit_as(BinaryFormat::Elf)?;
|
||||
let mut bytes = obj.write()?;
|
||||
// elf is still missing details...
|
||||
convert_faerie_elf_to_loadable_file(&mut bytes, code_region.0);
|
||||
convert_object_elf_to_loadable_file(&mut bytes, code_region.0);
|
||||
|
||||
// let mut file = ::std::fs::File::create(::std::path::Path::new("test.o")).expect("file");
|
||||
// ::std::io::Write::write(&mut file, &bytes).expect("write");
|
||||
// ::std::io::Write::write_all(&mut file, &bytes).expect("write");
|
||||
|
||||
Ok(bytes)
|
||||
}
|
||||
|
||||
fn convert_faerie_elf_to_loadable_file(bytes: &mut Vec<u8>, code_ptr: *const u8) {
|
||||
fn convert_object_elf_to_loadable_file(bytes: &mut Vec<u8>, code_ptr: *const u8) {
|
||||
use std::ffi::CStr;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
@@ -117,21 +130,24 @@ fn convert_faerie_elf_to_loadable_file(bytes: &mut Vec<u8>, code_ptr: *const u8)
|
||||
e_phoff == 0 && e_phnum == 0,
|
||||
"program header table is empty"
|
||||
);
|
||||
let e_phentsize = unsafe { *(bytes.as_ptr().offset(0x36) as *const u16) };
|
||||
assert_eq!(e_phentsize, 0x38, "size of ph");
|
||||
let e_shentsize = unsafe { *(bytes.as_ptr().offset(0x3A) as *const u16) };
|
||||
assert_eq!(e_shentsize, 0x40, "size of sh");
|
||||
|
||||
let e_shoff = unsafe { *(bytes.as_ptr().offset(0x28) as *const u64) };
|
||||
let e_shnum = unsafe { *(bytes.as_ptr().offset(0x3C) as *const u16) };
|
||||
let mut shstrtab_off = 0;
|
||||
for i in 0..e_shnum {
|
||||
let off = e_shoff as isize + i as isize * e_shentsize as isize;
|
||||
let sh_type = unsafe { *(bytes.as_ptr().offset(off + 0x4) as *const u32) };
|
||||
if sh_type != /* SHT_SYMTAB */ 3 {
|
||||
continue;
|
||||
}
|
||||
shstrtab_off = unsafe { *(bytes.as_ptr().offset(off + 0x18) as *const u64) };
|
||||
}
|
||||
let mut segment = None;
|
||||
for i in 0..e_shnum {
|
||||
let off = e_shoff as isize + i as isize * e_shentsize as isize;
|
||||
let sh_type = unsafe { *(bytes.as_ptr().offset(off + 0x4) as *const u32) };
|
||||
if sh_type == /* SHT_SYMTAB */ 3 {
|
||||
shstrtab_off = unsafe { *(bytes.as_ptr().offset(off + 0x18) as *const u64) };
|
||||
}
|
||||
if sh_type != /* SHT_PROGBITS */ 1 {
|
||||
continue;
|
||||
}
|
||||
@@ -185,10 +201,11 @@ fn convert_faerie_elf_to_loadable_file(bytes: &mut Vec<u8>, code_ptr: *const u8)
|
||||
}
|
||||
|
||||
// It is somewhat loadable ELF file at this moment.
|
||||
// Update e_flags, e_phoff and e_phnum.
|
||||
// Update e_flags, e_phoff, e_phentsize and e_phnum.
|
||||
unsafe {
|
||||
*(bytes.as_ptr().offset(0x10) as *mut u16) = /* ET_DYN */ 3;
|
||||
*(bytes.as_ptr().offset(0x20) as *mut u64) = ph_off as u64;
|
||||
*(bytes.as_ptr().offset(0x36) as *mut u16) = 0x38 as u16;
|
||||
*(bytes.as_ptr().offset(0x38) as *mut u16) = 1 as u16;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user