Skip to content

Commit

Permalink
[DEBUG] starting debug information
Browse files Browse the repository at this point in the history
  • Loading branch information
Cr0a3 committed Aug 31, 2024
1 parent 2da23e1 commit e80719f
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 13 deletions.
24 changes: 24 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ keywords = ["compiler", "codegen", "llvm"]
rustdoc-args = ["--allow", "warnings"]

[dependencies]
gimli = { version = "0.31.0", features = ["write"] }
logos = "0.14.0"
object = { version = "0.36.1", features = ["write"] }
proc = { workspace = true }
157 changes: 144 additions & 13 deletions src/Obj/wrapper.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
use object::write::{Relocation, SectionId, Symbol, SymbolId, SymbolSection};
use object::{Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationFlags, RelocationKind, SectionKind, SymbolFlags, SymbolKind, SymbolScope};

use gimli::write::{Dwarf, DwarfUnit, EndianVec, RelocateWriter};
use gimli::LittleEndian;
use object::write::{Object, Relocation, SectionId, Symbol, SymbolId, SymbolSection};
use object::{Architecture, BinaryFormat, Endianness, RelocationEncoding,
RelocationFlags, RelocationKind, SectionKind, SymbolFlags, SymbolKind,
SymbolScope};

use crate::debug::DebugRegistry;
use crate::prelude::Triple;
use crate::Target::{self, Arch, CallConv};
use std::collections::BTreeMap;
Expand All @@ -24,6 +29,39 @@ impl std::fmt::Display for ObjectError {

impl std::error::Error for ObjectError {}

#[derive(Clone)]
struct Section {
data: EndianVec<LittleEndian>,
relocations: Vec<gimli::write::Relocation>,
id: Option<object::write::SectionId>,
}

impl Section {
fn new() -> Self {
Self {
data: EndianVec::new(LittleEndian),
relocations: Vec::new(),
id: None,
}
}
}

impl RelocateWriter for Section {
type Writer = EndianVec<LittleEndian>;

fn writer(&self) -> &Self::Writer {
&self.data
}

fn writer_mut(&mut self) -> &mut Self::Writer {
&mut self.data
}

fn relocate(&mut self, relocation: gimli::write::Relocation) {
self.relocations.push(relocation);
}
}

/// A decl to say what's the label/func
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Decl {
Expand Down Expand Up @@ -68,7 +106,10 @@ pub struct ObjectBuilder {

decls: Vec<(String, Decl, Linkage)>,

triple: Triple
triple: Triple,

/// include debugging information
debug: bool,
}

impl ObjectBuilder {
Expand All @@ -78,10 +119,11 @@ impl ObjectBuilder {
defines: BTreeMap::new(),

links: vec![],

decls: vec![],

triple: triple
triple: triple,

debug: false,
}
}

Expand All @@ -108,8 +150,7 @@ impl ObjectBuilder {
}

/// Writes the object file into the the specified file
pub fn emit(&self, file: File) -> Result<(), Box<dyn Error>> {

pub fn emit(&self, file: File, debug: Option<DebugRegistry>) -> Result<(), Box<dyn Error>> {
let align = 1;

let mut obj = object::write::Object::new({
Expand Down Expand Up @@ -172,7 +213,7 @@ impl ObjectBuilder {
let secData = obj.add_section(vec![], ".data".as_bytes().to_vec(), SectionKind::Data);
let secConsts = obj.add_section(vec![], ".rodata".as_bytes().to_vec(), SectionKind::ReadOnlyData);

let mut syms: BTreeMap<String, (Option<SectionId>, Option</*offsest*/u64>, SymbolId, Decl)> = BTreeMap::new();
let mut syms: BTreeMap<String, (Option<SectionId>, Option</*offsest*/u64>, SymbolId, Decl, /*size*/u64)> = BTreeMap::new();

for (name, data) in &self.defines {
let name = name.to_owned();
Expand Down Expand Up @@ -247,15 +288,15 @@ impl ObjectBuilder {
Decl::Constant => obj.add_symbol_data(sym, secConsts, &data, align),
};

syms.insert(name.clone(), (None, Some(def_offset), sym, *decl));
syms.insert(name.clone(), (None, Some(def_offset), sym, *decl, data.len() as u64));
} else {
syms.insert(name.clone(), (None, None, sym, *decl));
syms.insert(name.clone(), (None, None, sym, *decl, data.len() as u64));
}
}

for link in &self.links {
let (_, off, _, _) = syms.get(&link.from).unwrap();
let (_, _, to_sym, ty) = syms.get(&link.to).unwrap();
let (_, off, _, _, _) = syms.get(&link.from).unwrap();
let (_, _, to_sym, ty, _) = syms.get(&link.to).unwrap();

let mut addend = 0;
let mut offset = 0;
Expand Down Expand Up @@ -291,8 +332,98 @@ impl ObjectBuilder {
})?;
}

if let Some(debug) = debug {
if self.debug {
self.emit_dwarf(&mut obj, &syms, debug)?;
}
}

obj.write_stream(file)?;

Ok(())
}

fn emit_debug_info(&self, dwarf: &mut DwarfUnit, name: &String, id: &SymbolId, size: u64, debug: &DebugRegistry) {

}

fn emit_dwarf(&self, obj: &mut Object<'_>, syms: &BTreeMap<String, (Option<SectionId>, Option</*offsest*/u64>, SymbolId, Decl, u64)>, debug: DebugRegistry) -> Result<(), Box<dyn Error>> {
use gimli::write::*;
let encoding = gimli::Encoding {
address_size: 8,
format: gimli::Format::Dwarf32,
version: 5,
};

let mut dwarf = DwarfUnit::new(encoding);
let root = dwarf.unit.root();
let entry = dwarf.unit.get_mut(root);

entry.set(gimli::DW_AT_producer,
AttributeValue::String(debug.producer.as_bytes().to_vec())
);

entry.set(gimli::DW_AT_language,
AttributeValue::Language(debug.lang)
);
entry.set(gimli::DW_AT_name, AttributeValue::String(debug.file.as_bytes().to_vec()));
entry.set(gimli::DW_AT_comp_dir, AttributeValue::String(debug.dir.as_bytes().to_vec()));

let mut sections = Sections::new(self::Section::new());
dwarf.write(&mut sections)?;

for (name, (_, _, id, decl, size)) in syms {
if *decl == Decl::Function {
self.emit_debug_info(&mut dwarf, name, id, *size, &debug);
}
}

sections.for_each_mut(|id, section| -> object::write::Result<()> {
if section.data.len() == 0 {
return Ok(());
}
let section_id = obj.add_section(Vec::new(), id.name().into(), object::SectionKind::Debug);
obj.set_section_data(section_id, section.data.take(), 1);

section.id = Some(section_id);
Ok(())
})?;

sections.for_each(|_, section| -> object::write::Result<()> {
let Some(section_id) = section.id else {
debug_assert!(section.relocations.is_empty());
return Ok(());
};
for reloc in &section.relocations {
// The `eh_pe` field is not used in this example because we are not writing
// unwind information.
debug_assert!(reloc.eh_pe.is_none());
let symbol = match reloc.target {
RelocationTarget::Section(id) => {
obj.section_symbol(sections.get(id).unwrap().id.unwrap())
}
RelocationTarget::Symbol(_) => todo!(),
};
obj.add_relocation(
section_id,
object::write::Relocation {
offset: reloc.offset as u64,
symbol,
addend: reloc.addend,
flags: object::RelocationFlags::Generic {
kind: match reloc.target {
RelocationTarget::Section(_) => object::RelocationKind::SectionOffset,
_ => object::RelocationKind::Absolute
},
encoding: object::RelocationEncoding::Generic,
size: reloc.size * 8,
},
},
)?;
}
Ok(())
})?;

Ok(())
}
}
62 changes: 62 additions & 0 deletions src/debug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use std::path::Path;

use gimli::DwLang;

/// The debugging location
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DebugLocation {
/// the line which the debug location is refering to
pub line: u64,
/// the coloumn which the debug location is refering to
pub col: u64,
}

/// A variable to debug
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct DebugVariable {
pub(crate) name: String,
}

impl DebugVariable {
/// Creates a new debug variable
pub fn new(name: String) -> Self {
Self {
name: name
}
}
}

/// The debug register is used to store files and their file id
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DebugRegistry {
pub(crate) file: String,
pub(crate) dir: String,
current_id: u64,

pub(crate) locs: Vec<DebugLocation>,
pub(crate) vars: Vec<DebugVariable>,

pub(crate) producer: String,
pub(crate) lang: DwLang
}

impl DebugRegistry {
/// Creates a new debug registry
pub fn new(producer: String, lang: DwLang, infile: &Path) -> Self {
let file = infile.file_name().expect("expected filename").to_str().unwrap().to_string();
let mut tmp = format!("{}", file).chars().rev().collect::<String>();
tmp.remove(file.chars().count());
Self {
file: file,
dir: tmp.chars().rev().collect::<String>(),
locs: vec![],
vars: vec![],

lang: lang,

producer: producer,

current_id: 0,
}
}
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ pub mod Obj;
/// Shared code generation classes (mainly used for register based architectures like x86_64, aarch64, ...)
pub mod CodeGen;

/// Debugging information
pub mod debug;

/// Most common used functions, classes, enums of this Libary
pub mod prelude {
pub use crate::IR::*;
Expand Down

0 comments on commit e80719f

Please sign in to comment.