2020-05-01 20:57:51 +02:00
|
|
|
use std::convert::TryInto;
|
|
|
|
|
2020-04-05 14:01:02 +02:00
|
|
|
use rustc_data_structures::fx::FxHashMap;
|
2019-11-12 20:52:32 +01:00
|
|
|
|
2020-05-01 19:21:29 +02:00
|
|
|
use gimli::write::{Address, AttributeValue, EndianVec, Result, Sections, Writer};
|
2019-11-12 20:52:32 +01:00
|
|
|
use gimli::{RunTimeEndian, SectionId};
|
|
|
|
|
|
|
|
use crate::backend::WriteDebugInfo;
|
|
|
|
|
|
|
|
use super::DebugContext;
|
|
|
|
|
|
|
|
impl DebugContext<'_> {
|
2020-03-27 12:14:45 +01:00
|
|
|
pub(crate) fn emit<P: WriteDebugInfo>(&mut self, product: &mut P) {
|
2019-11-12 20:52:32 +01:00
|
|
|
let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone());
|
|
|
|
let root = self.dwarf.unit.root();
|
|
|
|
let root = self.dwarf.unit.get_mut(root);
|
|
|
|
root.set(
|
|
|
|
gimli::DW_AT_ranges,
|
|
|
|
AttributeValue::RangeListRef(unit_range_list_id),
|
|
|
|
);
|
|
|
|
|
2020-05-01 19:21:29 +02:00
|
|
|
let mut sections = Sections::new(WriterRelocate::new(self.endian));
|
2019-11-12 20:52:32 +01:00
|
|
|
self.dwarf.write(&mut sections).unwrap();
|
|
|
|
|
2020-04-05 14:01:02 +02:00
|
|
|
let mut section_map = FxHashMap::default();
|
2019-11-12 20:52:32 +01:00
|
|
|
let _: Result<()> = sections.for_each_mut(|id, section| {
|
|
|
|
if !section.writer.slice().is_empty() {
|
|
|
|
let section_id = product.add_debug_section(id, section.writer.take());
|
|
|
|
section_map.insert(id, section_id);
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
|
|
|
|
let _: Result<()> = sections.for_each(|id, section| {
|
|
|
|
if let Some(section_id) = section_map.get(&id) {
|
|
|
|
for reloc in §ion.relocs {
|
2020-05-01 19:21:29 +02:00
|
|
|
product.add_debug_reloc(§ion_map, section_id, reloc);
|
2019-11-12 20:52:32 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
2020-03-27 12:14:45 +01:00
|
|
|
pub(crate) struct DebugReloc {
|
|
|
|
pub(crate) offset: u32,
|
|
|
|
pub(crate) size: u8,
|
|
|
|
pub(crate) name: DebugRelocName,
|
|
|
|
pub(crate) addend: i64,
|
2019-11-12 20:52:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
2020-03-27 12:14:45 +01:00
|
|
|
pub(crate) enum DebugRelocName {
|
2019-11-12 20:52:32 +01:00
|
|
|
Section(SectionId),
|
|
|
|
Symbol(usize),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
2020-05-01 19:21:29 +02:00
|
|
|
pub(super) struct WriterRelocate {
|
|
|
|
pub(super) relocs: Vec<DebugReloc>,
|
|
|
|
pub(super) writer: EndianVec<RunTimeEndian>,
|
2019-11-12 20:52:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl WriterRelocate {
|
2020-05-01 19:21:29 +02:00
|
|
|
pub(super) fn new(endian: RunTimeEndian) -> Self {
|
2019-11-12 20:52:32 +01:00
|
|
|
WriterRelocate {
|
|
|
|
relocs: Vec::new(),
|
2020-05-01 19:21:29 +02:00
|
|
|
writer: EndianVec::new(endian),
|
2019-11-12 20:52:32 +01:00
|
|
|
}
|
|
|
|
}
|
2020-05-01 20:57:51 +02:00
|
|
|
|
|
|
|
pub(super) fn relocate_for_jit(
|
|
|
|
mut self,
|
|
|
|
jit_module: &mut cranelift_module::Module<cranelift_simplejit::SimpleJITBackend>,
|
|
|
|
) -> Vec<u8> {
|
|
|
|
for reloc in self.relocs.drain(..) {
|
|
|
|
match reloc.name {
|
|
|
|
super::DebugRelocName::Section(_) => unreachable!(),
|
|
|
|
super::DebugRelocName::Symbol(sym) => {
|
|
|
|
let addr = jit_module.get_finalized_function(
|
|
|
|
cranelift_module::FuncId::from_u32(sym.try_into().unwrap()),
|
|
|
|
);
|
|
|
|
let val = (addr as u64 as i64 + reloc.addend) as u64;
|
|
|
|
self.writer.write_udata_at(reloc.offset as usize, val, reloc.size).unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.writer.into_vec()
|
|
|
|
}
|
2019-11-12 20:52:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Writer for WriterRelocate {
|
|
|
|
type Endian = RunTimeEndian;
|
|
|
|
|
|
|
|
fn endian(&self) -> Self::Endian {
|
|
|
|
self.writer.endian()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn len(&self) -> usize {
|
|
|
|
self.writer.len()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write(&mut self, bytes: &[u8]) -> Result<()> {
|
|
|
|
self.writer.write(bytes)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_at(&mut self, offset: usize, bytes: &[u8]) -> Result<()> {
|
|
|
|
self.writer.write_at(offset, bytes)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_address(&mut self, address: Address, size: u8) -> Result<()> {
|
|
|
|
match address {
|
|
|
|
Address::Constant(val) => self.write_udata(val, size),
|
|
|
|
Address::Symbol { symbol, addend } => {
|
|
|
|
let offset = self.len() as u64;
|
|
|
|
self.relocs.push(DebugReloc {
|
|
|
|
offset: offset as u32,
|
|
|
|
size,
|
|
|
|
name: DebugRelocName::Symbol(symbol),
|
|
|
|
addend: addend as i64,
|
|
|
|
});
|
|
|
|
self.write_udata(0, size)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: implement write_eh_pointer
|
|
|
|
|
|
|
|
fn write_offset(&mut self, val: usize, section: SectionId, size: u8) -> Result<()> {
|
|
|
|
let offset = self.len() as u32;
|
|
|
|
self.relocs.push(DebugReloc {
|
|
|
|
offset,
|
|
|
|
size,
|
|
|
|
name: DebugRelocName::Section(section),
|
|
|
|
addend: val as i64,
|
|
|
|
});
|
|
|
|
self.write_udata(0, size)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_offset_at(
|
|
|
|
&mut self,
|
|
|
|
offset: usize,
|
|
|
|
val: usize,
|
|
|
|
section: SectionId,
|
|
|
|
size: u8,
|
|
|
|
) -> Result<()> {
|
|
|
|
self.relocs.push(DebugReloc {
|
|
|
|
offset: offset as u32,
|
|
|
|
size,
|
|
|
|
name: DebugRelocName::Section(section),
|
|
|
|
addend: val as i64,
|
|
|
|
});
|
|
|
|
self.write_udata_at(offset, 0, size)
|
|
|
|
}
|
|
|
|
}
|