Skip to content

Commit

Permalink
Use updated gimli
Browse files Browse the repository at this point in the history
  • Loading branch information
yurydelendik committed Mar 7, 2019
1 parent b054994 commit 40db386
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 244 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ wabt = "0.7"
[workspace]

[patch.crates-io]
gimli = { path = "../gimli" }
cranelift-codegen = { path = "../../cranelift/cranelift-codegen" }
cranelift-native = { path = "../../cranelift/cranelift-native" }
cranelift-entity = { path = "../../cranelift/cranelift-entity" }
Expand Down
245 changes: 34 additions & 211 deletions lib/debug/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,186 +7,20 @@ use std::collections::HashMap;
use std::vec::Vec;
use wasmtime_environ::{FrameLayoutCommand, FrameLayouts};

use gimli::write::{EndianVec, Error};
use gimli::{LittleEndian, Register, X86_64};
use gimli::write::{
Address, CallFrameInstruction, CommonInformationEntry as CIEEntry, Error,
FrameDescriptionEntry as FDEEntry, Writer,
};
use gimli::{Register, X86_64};

trait Writer: gimli::write::Writer<Endian = LittleEndian> {}
impl Writer for EndianVec<LittleEndian> {}

enum CallFrameInstruction {
AdvanceLoc {
delta: u32,
},
DefCfa {
register: Register,
offset: u64,
},
DefCfaRegister {
register: Register,
},
DefCfaOffset {
offset: u64,
},
Offset {
register: Register,
factored_offset: u64,
},
}

impl CallFrameInstruction {
fn write(&self, writer: &mut Writer) -> Result<(), Error> {
match *self {
CallFrameInstruction::AdvanceLoc { delta } => {
assert!(delta < 0x40);
// DW_CFA_advance_loc
writer.write_u8(0x40 | delta as u8)?;
}
CallFrameInstruction::DefCfa { register, offset } => {
// DW_CFA_def_cfa
writer.write_u8(0x0c)?;
writer.write_uleb128(register.0 as u64)?;
writer.write_uleb128(offset)?;
}
CallFrameInstruction::DefCfaRegister { register } => {
// DW_CFA_def_cfa_register
writer.write_u8(0x0d)?;
writer.write_uleb128(register.0 as u64)?;
}
CallFrameInstruction::DefCfaOffset { offset } => {
// DW_CFA_def_cfa_offset
writer.write_u8(0x0e)?;
writer.write_uleb128(offset)?;
}
CallFrameInstruction::Offset {
register,
factored_offset,
} => {
assert!(register.0 < 0x40);
// DW_CFA_offset: r at cfa-8
writer.write_u8(0x80 | register.0 as u8)?;
writer.write_uleb128(factored_offset)?;
}
}
Ok(())
}
}

fn pad_with_nop(writer: &mut Writer, len: usize, align: u8) -> Result<(), Error> {
const DW_CFA_nop: u8 = 0;
let tail_len = (!len + 1) & (align as usize - 1);
for _ in 0..tail_len {
writer.write_u8(DW_CFA_nop)?;
}
Ok(())
}

struct FDEEntry {
pub initial_location: u64,
pub address_range: u64,
pub instructions: Vec<CallFrameInstruction>,
}

impl FDEEntry {
fn write(
&self,
writer: &mut Writer,
cie_ptr: u32,
address_size: u8,
relocs: &mut Vec<usize>,
) -> Result<(), Error> {
// Write FDE, patch len at the end
let pos = writer.len();
writer.write_u32(0)?;

writer.write_u32(cie_ptr)?;
// <--- reloc here to function sym
relocs.push(writer.len());
assert!(address_size == 8);
writer.write_u64(/* initial_location */ self.initial_location)?;
writer.write_u64(/* address_range */ self.address_range)?;

for instr in self.instructions.iter() {
instr.write(writer)?;
}

let entry_len = writer.len() - pos;
pad_with_nop(writer, entry_len, address_size)?;

let entry_len = (writer.len() - pos) as u32;
writer.write_u32_at(pos, entry_len - ::std::mem::size_of::<u32>() as u32)?;

Ok(())
}
}

struct CIEEntry {
pub version: u8,
pub aug: &'static str,
pub address_size: u8,
pub segment_selector_size: u8,
pub code_alignment_factor: u64,
pub data_alignment_factor: i64,
pub return_address_register: Register,
pub aug_data: Vec<u8>,
pub initial_instructions: Vec<CallFrameInstruction>,
pub fde_entries: Vec<FDEEntry>,
}

impl CIEEntry {
fn write(&self, writer: &mut Writer, relocs: &mut Vec<usize>) -> Result<(), Error> {
// Write CIE, patch len at the end
let pos = writer.len();
writer.write_u32(0)?;
const CIE_ID: u32 = 0xFFFFFFFF;
writer.write_u32(CIE_ID)?;
writer.write_u8(/* version: u8 */ self.version)?;
assert!(self.aug.len() == 0);
writer.write_u8(/* augumentation: utf8z = [0] */ 0x00)?;
writer.write_u8(/* address_size [v4]: u8 */ self.address_size)?;
writer.write_u8(
/* segment_selector_size [v4]: u8 */ self.segment_selector_size,
)?;
writer.write_uleb128(
/* code_alignment_factor: uleb128 */ self.code_alignment_factor,
)?;
writer.write_sleb128(
/* data_alignment_factor: sleb128 */ self.data_alignment_factor,
)?;
writer.write_uleb128(
/* return_address_register [v3]: uleb128 */
self.return_address_register.0.into(),
)?;

if self.aug.len() > 0 {
writer.write(&self.aug_data)?;
}

for instr in self.initial_instructions.iter() {
instr.write(writer)?;
}

let entry_len = writer.len() - pos;
pad_with_nop(writer, entry_len, self.address_size)?;

let entry_len = (writer.len() - pos) as u32;
writer.write_u32_at(pos, entry_len - ::std::mem::size_of::<u32>() as u32)?;

let cie_ptr = pos as u32;
for fde in self.fde_entries.iter() {
fde.write(writer, cie_ptr, self.address_size, relocs)?;
}
Ok(())
}
}

struct DebugFrameTable {
pub struct DebugFrameTable {
pub entries: Vec<CIEEntry>,
}

impl DebugFrameTable {
fn write(&self, writer: &mut dyn Writer, relocs: &mut Vec<usize>) -> Result<(), Error> {
pub fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
for cie in self.entries.iter() {
cie.write(writer, relocs)?;
cie.write(writer)?;
}
Ok(())
}
Expand Down Expand Up @@ -225,7 +59,7 @@ pub fn get_debug_frame_bytes(
funcs: &Vec<(*const u8, usize)>,
isa: &TargetIsa,
layouts: &FrameLayouts,
) -> Result<(Vec<u8>, Vec<usize>), Error> {
) -> Result<DebugFrameTable, Error> {
assert!(isa.name() == "x86");
// Expecting all function with System V prologue
for l in layouts.values() {
Expand All @@ -237,32 +71,32 @@ pub fn get_debug_frame_bytes(
}

let address_size = isa.pointer_bytes();
let mut cie = CIEEntry {
version: 4,
aug: "",
address_size,
segment_selector_size: 0,
code_alignment_factor: 1,
data_alignment_factor: -8,
return_address_register: X86_64::RA,
aug_data: vec![],
initial_instructions: vec![
CallFrameInstruction::DefCfa {
register: X86_64::RSP,
offset: 8,
},
CallFrameInstruction::Offset {
register: X86_64::RA,
factored_offset: 1,
},
],
fde_entries: Vec::new(),
};
let mut cie = CIEEntry::new();
cie.version = 4;
cie.address_size = address_size;
cie.code_alignment_factor = 1;
cie.data_alignment_factor = -8;
cie.return_address_register = X86_64::RA;
cie.add_initial_instruction(CallFrameInstruction::DefCfa {
register: X86_64::RSP,
offset: 8,
});
cie.add_initial_instruction(CallFrameInstruction::Offset {
register: X86_64::RA,
factored_offset: 1,
});

for (i, f) in funcs.into_iter().enumerate() {
let mut cfa_def_reg = X86_64::RSP;
let mut cfa_def_offset = 8u64;
let mut instructions = Vec::new();

let f_len = f.1 as u64;
let mut fde = FDEEntry::new();
fde.initial_location = Address::Relative {
symbol: i,
addend: 0,
};
fde.address_range = f_len;

let layout = &layouts[DefinedFuncIndex::new(i)];
for cmd in layout.commands.into_iter() {
Expand Down Expand Up @@ -300,23 +134,12 @@ pub fn get_debug_frame_bytes(
}
}
};
instructions.push(instr);
fde.add_instruction(instr);
}

let f_len = f.1 as u64;
let fde = FDEEntry {
initial_location: 0,
address_range: f_len,
instructions,
};
cie.fde_entries.push(fde);
cie.add_fde_entry(fde);
}

let table = DebugFrameTable { entries: vec![cie] };

let mut result = EndianVec::new(LittleEndian);
let mut relocs = Vec::new();
table.write(&mut result, &mut relocs)?;

Ok((result.into_vec(), relocs))
Ok(table)
}
57 changes: 24 additions & 33 deletions lib/debug/src/write_debuginfo.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::frame::DebugFrameTable;
use crate::transform::TransformedDwarf;

use gimli::write::{
Expand Down Expand Up @@ -60,46 +61,36 @@ pub trait SymbolResolver {
fn write_debug_frame(
artifact: &mut Artifact,
symbol_resolver: &SymbolResolver,
mut bytes: Vec<u8>,
relocs: Vec<usize>,
df_table: DebugFrameTable,
) {
let mut w = WriterRelocate::new(RunTimeEndian::Little, symbol_resolver);
df_table.write(&mut w).unwrap();
artifact
.declare(".debug_frame", Decl::DebugSection)
.expect("debug_frame declared");
for (i, reloc) in relocs.iter().enumerate() {
let addr = symbol_resolver.resolve_symbol(i, /* addend */ 0);
match addr {
ResolvedSymbol::PhysicalAddress(a) => unsafe {
let ptr = bytes.as_mut_ptr().offset((*reloc) as isize) as *mut u64;
*ptr = a;
},
ResolvedSymbol::Reloc { name, addend } => {
artifact
.link_with(
faerie::Link {
from: ".debug_frame",
to: &name,
at: (*reloc) as u64,
},
faerie::Reloc::Debug {
size: 8,
addend: addend as i32,
},
)
.expect("faerie relocation error");
}
}
.declare_with(".debug_frame", Decl::DebugSection, w.writer.into_vec())
.unwrap();

for reloc in w.relocs {
artifact
.link_with(
faerie::Link {
from: ".debug_frame",
to: &reloc.name,
at: u64::from(reloc.offset),
},
faerie::Reloc::Debug {
size: reloc.size,
addend: reloc.addend as i32,
},
)
.expect("faerie relocation error");
}
artifact
.define(".debug_frame", bytes)
.expect("debug_frame defined");
}

pub fn emit_dwarf(
artifact: &mut Artifact,
mut dwarf: TransformedDwarf,
symbol_resolver: &SymbolResolver,
frames: Option<(Vec<u8>, Vec<usize>)>,
frames: Option<DebugFrameTable>,
) {
let endian = RunTimeEndian::Little;
let debug_abbrev = DebugAbbrev::from(WriterRelocate::new(endian, symbol_resolver));
Expand Down Expand Up @@ -145,8 +136,8 @@ pub fn emit_dwarf(
decl_section!(artifact.DebugRngLists = sections.debug_rnglists);
}

if let Some((bytes, relocs)) = frames {
write_debug_frame(artifact, symbol_resolver, bytes, relocs);
if let Some(df_table) = frames {
write_debug_frame(artifact, symbol_resolver, df_table);
}

sect_relocs!(artifact.DebugAbbrev = sections.debug_abbrev);
Expand Down

0 comments on commit 40db386

Please sign in to comment.