From 40db386283a501a4704c15bdf2dc04e16852a748 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 1 Mar 2019 10:56:08 -0600 Subject: [PATCH] Use updated gimli https://github.com/gimli-rs/gimli/pull/394 --- Cargo.toml | 1 + lib/debug/src/frame.rs | 245 +++++-------------------------- lib/debug/src/write_debuginfo.rs | 57 +++---- 3 files changed, 59 insertions(+), 244 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 593a7df9d775..8cf3cf898fa2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" } diff --git a/lib/debug/src/frame.rs b/lib/debug/src/frame.rs index e4919d071c29..1710a909d767 100644 --- a/lib/debug/src/frame.rs +++ b/lib/debug/src/frame.rs @@ -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 {} -impl Writer for EndianVec {} - -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, -} - -impl FDEEntry { - fn write( - &self, - writer: &mut Writer, - cie_ptr: u32, - address_size: u8, - relocs: &mut Vec, - ) -> 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::() 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, - pub initial_instructions: Vec, - pub fde_entries: Vec, -} - -impl CIEEntry { - fn write(&self, writer: &mut Writer, relocs: &mut Vec) -> 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::() 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, } impl DebugFrameTable { - fn write(&self, writer: &mut dyn Writer, relocs: &mut Vec) -> Result<(), Error> { + pub fn write(&self, writer: &mut W) -> Result<(), Error> { for cie in self.entries.iter() { - cie.write(writer, relocs)?; + cie.write(writer)?; } Ok(()) } @@ -225,7 +59,7 @@ pub fn get_debug_frame_bytes( funcs: &Vec<(*const u8, usize)>, isa: &TargetIsa, layouts: &FrameLayouts, -) -> Result<(Vec, Vec), Error> { +) -> Result { assert!(isa.name() == "x86"); // Expecting all function with System V prologue for l in layouts.values() { @@ -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() { @@ -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) } diff --git a/lib/debug/src/write_debuginfo.rs b/lib/debug/src/write_debuginfo.rs index dac56406f757..15a735688738 100644 --- a/lib/debug/src/write_debuginfo.rs +++ b/lib/debug/src/write_debuginfo.rs @@ -1,3 +1,4 @@ +use crate::frame::DebugFrameTable; use crate::transform::TransformedDwarf; use gimli::write::{ @@ -60,46 +61,36 @@ pub trait SymbolResolver { fn write_debug_frame( artifact: &mut Artifact, symbol_resolver: &SymbolResolver, - mut bytes: Vec, - relocs: Vec, + 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, Vec)>, + frames: Option, ) { let endian = RunTimeEndian::Little; let debug_abbrev = DebugAbbrev::from(WriterRelocate::new(endian, symbol_resolver)); @@ -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);