]> git.lizzy.rs Git - rust.git/blobdiff - src/debuginfo/emit.rs
Rustfmt
[rust.git] / src / debuginfo / emit.rs
index e49e13a5be5a827d54ff0563e50a8fbf18dcf2d7..6160f9b78d8b3a6d9cd3cefde854f4ca60813f67 100644 (file)
@@ -1,6 +1,8 @@
+//! Write the debuginfo into an object file.
+
 use rustc_data_structures::fx::FxHashMap;
 
-use gimli::write::{Address, AttributeValue, EhFrame, EndianVec, Result, Sections, Writer, Section};
+use gimli::write::{Address, AttributeValue, EndianVec, Result, Sections, Writer};
 use gimli::{RunTimeEndian, SectionId};
 
 use crate::backend::WriteDebugInfo;
@@ -17,12 +19,9 @@ pub(crate) fn emit<P: WriteDebugInfo>(&mut self, product: &mut P) {
             AttributeValue::RangeListRef(unit_range_list_id),
         );
 
-        let mut sections = Sections::new(WriterRelocate::new(self));
+        let mut sections = Sections::new(WriterRelocate::new(self.endian));
         self.dwarf.write(&mut sections).unwrap();
 
-        let mut eh_frame = EhFrame::from(WriterRelocate::new(self));
-        self.frame_table.write_eh_frame(&mut eh_frame).unwrap();
-
         let mut section_map = FxHashMap::default();
         let _: Result<()> = sections.for_each_mut(|id, section| {
             if !section.writer.slice().is_empty() {
@@ -35,21 +34,11 @@ pub(crate) fn emit<P: WriteDebugInfo>(&mut self, product: &mut P) {
         let _: Result<()> = sections.for_each(|id, section| {
             if let Some(section_id) = section_map.get(&id) {
                 for reloc in &section.relocs {
-                    product.add_debug_reloc(&section_map, &self.symbols, section_id, reloc);
+                    product.add_debug_reloc(&section_map, section_id, reloc);
                 }
             }
             Ok(())
         });
-
-        if !eh_frame.0.writer.slice().is_empty() {
-            let id = eh_frame.id();
-            let section_id = product.add_debug_section(id, eh_frame.0.writer.into_vec());
-            section_map.insert(id, section_id);
-
-            for reloc in &eh_frame.0.relocs {
-                product.add_debug_reloc(&section_map, &self.symbols, &section_id, reloc);
-            }
-        }
     }
 }
 
@@ -59,6 +48,7 @@ pub(crate) struct DebugReloc {
     pub(crate) size: u8,
     pub(crate) name: DebugRelocName,
     pub(crate) addend: i64,
+    pub(crate) kind: object::RelocationKind,
 }
 
 #[derive(Clone)]
@@ -67,18 +57,41 @@ pub(crate) enum DebugRelocName {
     Symbol(usize),
 }
 
+/// A [`Writer`] that collects all necessary relocations.
 #[derive(Clone)]
-struct WriterRelocate {
-    relocs: Vec<DebugReloc>,
-    writer: EndianVec<RunTimeEndian>,
+pub(super) struct WriterRelocate {
+    pub(super) relocs: Vec<DebugReloc>,
+    pub(super) writer: EndianVec<RunTimeEndian>,
 }
 
 impl WriterRelocate {
-    fn new(ctx: &DebugContext<'_>) -> Self {
+    pub(super) fn new(endian: RunTimeEndian) -> Self {
         WriterRelocate {
             relocs: Vec::new(),
-            writer: EndianVec::new(ctx.endian),
+            writer: EndianVec::new(endian),
+        }
+    }
+
+    /// Perform the collected relocations to be usable for JIT usage.
+    #[cfg(feature = "jit")]
+    pub(super) fn relocate_for_jit(mut self, jit_module: &cranelift_jit::JITModule) -> Vec<u8> {
+        use std::convert::TryInto;
+
+        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()
     }
 }
 
@@ -111,14 +124,13 @@ fn write_address(&mut self, address: Address, size: u8) -> Result<()> {
                     size,
                     name: DebugRelocName::Symbol(symbol),
                     addend: addend as i64,
+                    kind: object::RelocationKind::Absolute,
                 });
                 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 {
@@ -126,6 +138,7 @@ fn write_offset(&mut self, val: usize, section: SectionId, size: u8) -> Result<(
             size,
             name: DebugRelocName::Section(section),
             addend: val as i64,
+            kind: object::RelocationKind::Absolute,
         });
         self.write_udata(0, size)
     }
@@ -142,7 +155,46 @@ fn write_offset_at(
             size,
             name: DebugRelocName::Section(section),
             addend: val as i64,
+            kind: object::RelocationKind::Absolute,
         });
         self.write_udata_at(offset, 0, size)
     }
+
+    fn write_eh_pointer(&mut self, address: Address, eh_pe: gimli::DwEhPe, size: u8) -> Result<()> {
+        match address {
+            // Address::Constant arm copied from gimli
+            Address::Constant(val) => {
+                // Indirect doesn't matter here.
+                let val = match eh_pe.application() {
+                    gimli::DW_EH_PE_absptr => val,
+                    gimli::DW_EH_PE_pcrel => {
+                        // TODO: better handling of sign
+                        let offset = self.len() as u64;
+                        offset.wrapping_sub(val)
+                    }
+                    _ => {
+                        return Err(gimli::write::Error::UnsupportedPointerEncoding(eh_pe));
+                    }
+                };
+                self.write_eh_pointer_data(val, eh_pe.format(), size)
+            }
+            Address::Symbol { symbol, addend } => match eh_pe.application() {
+                gimli::DW_EH_PE_pcrel => {
+                    let size = match eh_pe.format() {
+                        gimli::DW_EH_PE_sdata4 => 4,
+                        _ => return Err(gimli::write::Error::UnsupportedPointerEncoding(eh_pe)),
+                    };
+                    self.relocs.push(DebugReloc {
+                        offset: self.len() as u32,
+                        size,
+                        name: DebugRelocName::Symbol(symbol),
+                        addend,
+                        kind: object::RelocationKind::Relative,
+                    });
+                    self.write_udata(0, size)
+                }
+                _ => Err(gimli::write::Error::UnsupportedPointerEncoding(eh_pe)),
+            },
+        }
+    }
 }