Merge .eh_frame without interpretation. Add a 0-CIE to the end.

Add unfinished attempt at using gimli, to be deleted but recorded in case we need it in the future.
This commit is contained in:
Nick Lewycky
2020-06-18 14:01:52 -07:00
parent 77c3ce5a33
commit e9d5c7896c
4 changed files with 109 additions and 12 deletions

View File

@@ -6,8 +6,11 @@ use wasm_common::entity::{EntityRef, PrimaryMap, SecondaryMap};
use wasm_common::LocalFunctionIndex;
use wasmer_compiler::{
Compilation, CompileError, CompileModuleInfo, Compiler, FunctionBodyData,
ModuleTranslationState, RelocationTarget, SectionIndex, Target,
ModuleTranslationState, RelocationTarget, SectionIndex, Target, CustomSection,
SectionBody, CustomSectionProtection, Dwarf,
};
use wasmer_runtime::{MemoryPlan, ModuleInfo, TablePlan};
//use gimli::read::UnwindSection;
//use std::sync::{Arc, Mutex};
@@ -31,6 +34,17 @@ impl LLVMCompiler {
}
}
/*
fn cie_to_cie(read_cie: gimli::read::CommonInformationEntry) -> gimli::write::CommonInformationEntry {
}
fn fde_to_fde(read_fde: gimli::read::FrameDescriptionEntry) -> gimli::write::FrameDescriptionEntry {
let mut write_fde = gimli::write::FrameDescriptionEntry::new(?, read_fde.len())
}
*/
impl Compiler for LLVMCompiler {
/// Compile the module using LLVM, producing a compilation result with
/// associated relocations.
@@ -57,6 +71,9 @@ impl Compiler for LLVMCompiler {
.unwrap_or_else(|| format!("fn{}", func_index.index()));
}
let mut module_custom_sections = PrimaryMap::new();
//let mut frame_table = gimli::write::FrameTable::default();
let mut frame_section_bytes = vec![];
let mut frame_section_relocations = vec![];
let functions = function_body_inputs
.into_iter()
.collect::<Vec<(LocalFunctionIndex, &FunctionBodyData<'_>)>>()
@@ -83,9 +100,9 @@ impl Compiler for LLVMCompiler {
)
.collect::<Result<Vec<_>, CompileError>>()?
.into_iter()
.map(|(mut compiled_function, function_custom_sections, _eh_frame_section_indices)| {
.map(|(mut compiled_function, function_custom_sections, eh_frame_section_indices)| {
let first_section = module_custom_sections.len() as u32;
for (_, custom_section) in function_custom_sections.iter() {
for (section_index, custom_section) in function_custom_sections.iter() {
// TODO: remove this call to clone()
let mut custom_section = custom_section.clone();
for mut reloc in &mut custom_section.relocations {
@@ -95,7 +112,42 @@ impl Compiler for LLVMCompiler {
)
}
}
module_custom_sections.push(custom_section);
if eh_frame_section_indices.contains(&section_index) {
// TODO: pull endianness out of target
/*
let eh_frame = gimli::read::EhFrame::new(custom_section.bytes.as_slice(), gimli::NativeEndian);
let base_addresses = gimli::read::BaseAddresses::default();
let mut entries = eh_frame.entries(&base_addresses);
let mut current_cie = None;
while let Some(entry) = entries.next().unwrap() {
match entry {
gimli::CieOrFde::Cie(cie) => {
current_cie = Some(cie);
frame_table.add_cie(cie.into());
},
gimli::CieOrFde::Fde(partial_fde) => {
// TODO: unwrap safety
let fde = partial_fde.parse(current_cie.unwrap()).unwrap();
frame_table.add_fde(current_cie.unwrap().into(), fde.into());
}
};
}
*/
let offset = frame_section_bytes.len() as u32;
for mut reloc in &mut custom_section.relocations {
reloc.offset += offset;
}
frame_section_bytes.extend_from_slice(custom_section.bytes.as_slice());
frame_section_relocations.extend(custom_section.relocations);
// TODO: we do this to keep the count right, remove it.
module_custom_sections.push(CustomSection {
protection: CustomSectionProtection::Read,
bytes: SectionBody::new_with_vec(vec![]),
relocations: vec![]
});
} else {
module_custom_sections.push(custom_section);
}
}
for mut reloc in &mut compiled_function.relocations {
if let RelocationTarget::CustomSection(index) = reloc.reloc_target {
@@ -108,6 +160,30 @@ impl Compiler for LLVMCompiler {
})
.collect::<PrimaryMap<LocalFunctionIndex, _>>();
let dwarf = if !frame_section_bytes.is_empty() {
let dwarf = Some(Dwarf::new(SectionIndex::from_u32(module_custom_sections.len() as u32)));
// Terminator CIE.
frame_section_bytes.extend(vec!
[0x00, 0x00, 0x00, 0x00, // Length
0x00, 0x00, 0x00, 0x00, // CIE ID
0x10, // Version (must be 1)
0x00, // Augmentation data
0x00, 0x00,
0xa4, 0x2e, 0x00, 0x00,
0x30, 0x73, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00]);
module_custom_sections.push(CustomSection {
protection: CustomSectionProtection::Read,
bytes: SectionBody::new_with_vec(frame_section_bytes),
relocations: frame_section_relocations
});
dwarf
} else {
None
};
let function_call_trampolines = module
.signatures
.values()
@@ -146,7 +222,7 @@ impl Compiler for LLVMCompiler {
module_custom_sections,
function_call_trampolines,
dynamic_function_trampolines,
None,
dwarf,
))
}
}

View File

@@ -146,15 +146,17 @@ where
// Also add any .eh_frame sections.
let mut eh_frame_section_indices = vec![];
// TODO: this constant has been added to goblin, now waiting for release
const SHT_X86_64_UNWIND: u64 = 0x7000_0001;
const SHT_X86_64_UNWIND: u32 = 0x7000_0001;
for (index, shdr) in elf.section_headers.iter().enumerate() {
if shdr.sh_flags & SHT_X86_64_UNWIND != 0 {
if shdr.sh_type == SHT_X86_64_UNWIND {
let index = ElfSectionIndex::from_usize(index)?;
worklist.push(index);
visited.insert(index);
eh_frame_section_indices.push(index);
// This allocates a custom section index for the ELF section.
elf_section_to_target(index);
}
}
}
while let Some(section_index) = worklist.pop() {
for reloc in reloc_sections
@@ -166,6 +168,7 @@ where
// TODO: these constants are not per-arch, we'll need to
// make the whole match per-arch.
goblin::elf::reloc::R_X86_64_64 => RelocationKind::Abs8,
goblin::elf::reloc::R_X86_64_PC64 => RelocationKind::X86PCRel8,
goblin::elf::reloc::R_X86_64_GOT64 => {
return Err(CompileError::Codegen(
"unimplemented PIC relocation R_X86_64_GOT64".into(),
@@ -234,6 +237,21 @@ where
}
}
let eh_frame_section_indices = eh_frame_section_indices
.iter()
.map(|index| {
section_to_custom_section.get(index).map_or_else(
|| {
Err(CompileError::Codegen(format!(
".eh_frame section with index={:?} was never loaded",
index
)))
},
|idx| Ok(*idx),
)
})
.collect::<Result<Vec<SectionIndex>, _>>()?;
let mut custom_sections = section_to_custom_section
.iter()
.map(|(elf_section_index, custom_section_index)| {
@@ -255,8 +273,6 @@ where
.map(|(_, v)| v)
.collect::<PrimaryMap<SectionIndex, _>>();
let eh_frame_section_indices = eh_frame_section_indices.iter().map(|index| section_to_custom_section.get(index).map_or_else(|| Err(CompileError::Codegen(format!(".eh_frame section with index={:?} was never loaded", index))), |idx| Ok(*idx))).collect::<Result<Vec<SectionIndex>, _>>()?;
let function_body = FunctionBody {
body: section_bytes(root_section_index),
unwind_info: None,

View File

@@ -94,18 +94,20 @@ impl FuncTrampoline {
}
let mem_buf_slice = memory_buffer.as_slice();
let (function, sections, _eh_frame_section_indices) =
let (function, _sections, _eh_frame_section_indices) =
load_object_file(mem_buf_slice, FUNCTION_SECTION, None, |name: &String| {
Err(CompileError::Codegen(format!(
"trampoline generation produced reference to unknown function {}",
name
)))
})?;
/*
if !sections.is_empty() {
return Err(CompileError::Codegen(
"trampoline generation produced custom sections".into(),
));
}
*/
if !function.relocations.is_empty() {
return Err(CompileError::Codegen(
"trampoline generation produced relocations".into(),
@@ -175,18 +177,20 @@ impl FuncTrampoline {
}
let mem_buf_slice = memory_buffer.as_slice();
let (function, sections, _eh_frame_section_indices) =
let (function, _sections, _eh_frame_section_indices) =
load_object_file(mem_buf_slice, FUNCTION_SECTION, None, |name: &String| {
Err(CompileError::Codegen(format!(
"trampoline generation produced reference to unknown function {}",
name
)))
})?;
/*
if !sections.is_empty() {
return Err(CompileError::Codegen(
"trampoline generation produced custom sections".into(),
));
}
*/
if !function.relocations.is_empty() {
return Err(CompileError::Codegen(
"trampoline generation produced relocations".into(),