#![allow(dead_code)]
use super::*;
pub type DwarfDIE = DIE;
impl DIE {
pub fn set_offset(&mut self, offset: u64) {
self.offset = offset;
}
pub fn add_ref4(&mut self, attr: u16, form: u16, value: u32) {
self.attributes.push(DwarfAttribute {
attr,
form,
value: value.to_le_bytes().to_vec(),
});
}
pub fn add_sec_offset(&mut self, attr: u16, value: u64, offset_size: u8) {
let value_bytes = match offset_size {
4 => (value as u32).to_le_bytes().to_vec(),
8 => value.to_le_bytes().to_vec(),
_ => value.to_le_bytes().to_vec(),
};
self.attributes.push(DwarfAttribute {
attr,
form: dwarf_forms::DW_FORM_sec_offset,
value: value_bytes,
});
}
pub fn add_exprloc(&mut self, attr: u16, expr: &[u8]) {
let mut value = Vec::new();
encode_uleb128(&mut value, expr.len() as u64);
value.extend_from_slice(expr);
self.attributes.push(DwarfAttribute {
attr,
form: dwarf_forms::DW_FORM_exprloc,
value,
});
}
pub fn add_ref_addr(&mut self, attr: u16, value: u64, addr_size: u8) {
let value_bytes = match addr_size {
4 => (value as u32).to_le_bytes().to_vec(),
8 => value.to_le_bytes().to_vec(),
_ => value.to_le_bytes().to_vec(),
};
self.attributes.push(DwarfAttribute {
attr,
form: dwarf_forms::DW_FORM_ref_addr,
value: value_bytes,
});
}
pub fn add_strp(&mut self, attr: u16, str_offset: u64, offset_size: u8) {
let value_bytes = match offset_size {
4 => (str_offset as u32).to_le_bytes().to_vec(),
8 => str_offset.to_le_bytes().to_vec(),
_ => str_offset.to_le_bytes().to_vec(),
};
self.attributes.push(DwarfAttribute {
attr,
form: dwarf_forms::DW_FORM_strp,
value: value_bytes,
});
}
pub fn add_udata(&mut self, attr: u16, value: u64) {
let mut value_bytes = Vec::new();
encode_uleb128(&mut value_bytes, value);
self.attributes.push(DwarfAttribute {
attr,
form: dwarf_forms::DW_FORM_udata,
value: value_bytes,
});
}
pub fn add_sdata(&mut self, attr: u16, value: i64) {
let mut value_bytes = Vec::new();
encode_sleb128(&mut value_bytes, value);
self.attributes.push(DwarfAttribute {
attr,
form: dwarf_forms::DW_FORM_sdata,
value: value_bytes,
});
}
pub fn add_flag_present(&mut self, attr: u16) {
self.attributes.push(DwarfAttribute {
attr,
form: dwarf_forms::DW_FORM_flag_present,
value: Vec::new(),
});
}
pub fn add_block1(&mut self, attr: u16, data: &[u8]) {
let mut value = Vec::new();
let len = data.len().min(255) as u8;
value.push(len);
value.extend_from_slice(&data[..len as usize]);
self.attributes.push(DwarfAttribute {
attr,
form: dwarf_forms::DW_FORM_block1,
value,
});
}
pub fn add_block(&mut self, attr: u16, data: &[u8]) {
self.add_block1(attr, data);
}
pub fn add_ref1(&mut self, attr: u16, value: u8) {
self.attributes.push(DwarfAttribute {
attr,
form: dwarf_forms::DW_FORM_ref1,
value: vec![value],
});
}
pub fn add_ref2(&mut self, attr: u16, value: u16) {
self.attributes.push(DwarfAttribute {
attr,
form: dwarf_forms::DW_FORM_ref2,
value: value.to_le_bytes().to_vec(),
});
}
pub fn add_ref8(&mut self, attr: u16, value: u64) {
self.attributes.push(DwarfAttribute {
attr,
form: dwarf_forms::DW_FORM_ref8,
value: value.to_le_bytes().to_vec(),
});
}
pub fn abbrev_signature(&self) -> String {
let children = if self.has_children {
dwarf_children::DW_CHILDREN_yes
} else {
dwarf_children::DW_CHILDREN_no
};
let mut pairs: Vec<(u16, u16)> = self.attributes.iter().map(|a| (a.attr, a.form)).collect();
pairs.sort_by_key(|&(attr, _form)| attr);
format!("{}:{}:{:?}", self.tag, children, pairs)
}
pub fn emit(&self, abbrev_code: u64, addr_size: u8) -> Vec<u8> {
let mut out = Vec::new();
encode_uleb128(&mut out, abbrev_code);
for attr in &self.attributes {
out.extend_from_slice(&attr.value);
let _ = addr_size; }
for child in &self.children {
let child_data = child.emit(abbrev_code, addr_size);
out.extend_from_slice(&child_data);
}
if self.has_children {
out.push(0);
}
out
}
}
pub struct DIEBuilder {
pub die: DIE,
pub abbrev_table: AbbrevTable,
}
impl DIEBuilder {
pub fn new(tag: u16) -> Self {
Self {
die: DIE::new(tag),
abbrev_table: AbbrevTable::new(),
}
}
pub fn with_table(tag: u16, table: AbbrevTable) -> Self {
Self {
die: DIE::new(tag),
abbrev_table: table,
}
}
pub fn add_string(&mut self, attr: u16, value: &str) {
self.die.add_string(attr, value);
}
pub fn add_data1(&mut self, attr: u16, value: u8) {
self.die.add_data1(attr, value);
}
pub fn add_data2(&mut self, attr: u16, value: u16) {
self.die.add_data2(attr, value);
}
pub fn add_data4(&mut self, attr: u16, value: u32) {
self.die.add_data4(attr, value);
}
pub fn add_data8(&mut self, attr: u16, value: u64) {
self.die.add_data8(attr, value);
}
pub fn add_addr(&mut self, attr: u16, value: u64) {
self.die.add_addr(attr, value);
}
pub fn add_flag(&mut self, attr: u16, value: bool) {
self.die.add_flag(attr, value);
}
pub fn add_flag_present(&mut self, attr: u16) {
self.die.add_flag_present(attr);
}
pub fn add_udata(&mut self, attr: u16, value: u64) {
self.die.add_udata(attr, value);
}
pub fn add_sdata(&mut self, attr: u16, value: i64) {
self.die.add_sdata(attr, value);
}
pub fn add_ref4(&mut self, attr: u16, value: u32) {
self.die.add_ref4(attr, dwarf_forms::DW_FORM_ref4, value);
}
pub fn add_exprloc(&mut self, attr: u16, expr: &[u8]) {
self.die.add_exprloc(attr, expr);
}
pub fn add_strp(&mut self, attr: u16, str_offset: u64, offset_size: u8) {
self.die.add_strp(attr, str_offset, offset_size);
}
pub fn add_child(&mut self, child: DIE) {
self.die.add_child(child);
}
pub fn add_child_builder(&mut self, child_builder: DIEBuilder) {
self.die.add_child(child_builder.die);
}
pub fn register_abbrev(&mut self) -> u64 {
let children = if self.die.has_children {
dwarf_children::DW_CHILDREN_yes
} else {
dwarf_children::DW_CHILDREN_no
};
let pairs: Vec<(u16, u16)> = self
.die
.attributes
.iter()
.map(|a| (a.attr, a.form))
.collect();
self.abbrev_table
.get_or_create_code(self.die.tag, children, pairs)
}
pub fn emit(&mut self, addr_size: u8) -> Vec<u8> {
let code = self.register_abbrev();
self.die.emit(code, addr_size)
}
}
pub fn encode_attr_value(
form: u16,
value: u64,
addr_size: u8,
offset_size: u8,
extra_data: Option<&[u8]>,
) -> Vec<u8> {
match form {
f if f == dwarf_forms::DW_FORM_addr => match addr_size {
4 => (value as u32).to_le_bytes().to_vec(),
8 => value.to_le_bytes().to_vec(),
_ => value.to_le_bytes().to_vec(),
},
f if f == dwarf_forms::DW_FORM_data1 => {
vec![value as u8]
}
f if f == dwarf_forms::DW_FORM_data2 => (value as u16).to_le_bytes().to_vec(),
f if f == dwarf_forms::DW_FORM_data4 => (value as u32).to_le_bytes().to_vec(),
f if f == dwarf_forms::DW_FORM_data8 => value.to_le_bytes().to_vec(),
f if f == dwarf_forms::DW_FORM_string => {
if let Some(data) = extra_data {
data.to_vec()
} else {
vec![]
}
}
f if f == dwarf_forms::DW_FORM_flag => {
vec![if value != 0 { 1u8 } else { 0u8 }]
}
f if f == dwarf_forms::DW_FORM_flag_present => {
vec![] }
f if f == dwarf_forms::DW_FORM_udata => {
let mut out = Vec::new();
encode_uleb128(&mut out, value);
out
}
f if f == dwarf_forms::DW_FORM_sdata => {
let mut out = Vec::new();
encode_sleb128(&mut out, value as i64);
out
}
f if f == dwarf_forms::DW_FORM_ref1 => {
vec![value as u8]
}
f if f == dwarf_forms::DW_FORM_ref2 => (value as u16).to_le_bytes().to_vec(),
f if f == dwarf_forms::DW_FORM_ref4 => (value as u32).to_le_bytes().to_vec(),
f if f == dwarf_forms::DW_FORM_ref8 => value.to_le_bytes().to_vec(),
f if f == dwarf_forms::DW_FORM_ref_addr => match addr_size {
4 => (value as u32).to_le_bytes().to_vec(),
8 => value.to_le_bytes().to_vec(),
_ => value.to_le_bytes().to_vec(),
},
f if f == dwarf_forms::DW_FORM_sec_offset => match offset_size {
4 => (value as u32).to_le_bytes().to_vec(),
8 => value.to_le_bytes().to_vec(),
_ => (value as u32).to_le_bytes().to_vec(),
},
f if f == dwarf_forms::DW_FORM_strp => match offset_size {
4 => (value as u32).to_le_bytes().to_vec(),
8 => value.to_le_bytes().to_vec(),
_ => (value as u32).to_le_bytes().to_vec(),
},
f if f == dwarf_forms::DW_FORM_exprloc => {
let mut out = Vec::new();
if let Some(data) = extra_data {
encode_uleb128(&mut out, data.len() as u64);
out.extend_from_slice(data);
} else {
encode_uleb128(&mut out, 0);
}
out
}
f if f == dwarf_forms::DW_FORM_block1 => {
let mut out = Vec::new();
if let Some(data) = extra_data {
let len = data.len().min(255) as u8;
out.push(len);
out.extend_from_slice(&data[..len as usize]);
} else {
out.push(0);
}
out
}
f if f == dwarf_forms::DW_FORM_block2 => {
let mut out = Vec::new();
if let Some(data) = extra_data {
let len = data.len().min(65535) as u16;
out.extend_from_slice(&len.to_le_bytes());
out.extend_from_slice(&data[..len as usize]);
} else {
out.extend_from_slice(&0u16.to_le_bytes());
}
out
}
f if f == dwarf_forms::DW_FORM_block4 => {
let mut out = Vec::new();
if let Some(data) = extra_data {
let len = data.len().min(u32::MAX as usize) as u32;
out.extend_from_slice(&len.to_le_bytes());
out.extend_from_slice(&data[..len as usize]);
} else {
out.extend_from_slice(&0u32.to_le_bytes());
}
out
}
_ => vec![],
}
}
pub fn make_compile_unit_die(
name: &str,
producer: &str,
comp_dir: &str,
language: u16,
low_pc: u64,
high_pc: u64,
stmt_list_offset: u64,
addr_size: u8,
str_offsets: &mut dyn FnMut(&str) -> u64,
) -> DIE {
let mut cu = DIE::new(dwarf_tags::DW_TAG_compile_unit);
let name_off = str_offsets(name);
cu.add_strp(dwarf_attributes::DW_AT_name, name_off, 4);
let prod_off = str_offsets(producer);
cu.add_strp(dwarf_attributes::DW_AT_producer, prod_off, 4);
let dir_off = str_offsets(comp_dir);
cu.add_strp(dwarf_attributes::DW_AT_comp_dir, dir_off, 4);
cu.add_data2(dwarf_attributes::DW_AT_language, language);
cu.add_addr(dwarf_attributes::DW_AT_low_pc, low_pc);
cu.add_data8(dwarf_attributes::DW_AT_high_pc, high_pc);
cu.add_data4(dwarf_attributes::DW_AT_stmt_list, stmt_list_offset as u32);
let _ = addr_size;
cu
}
pub fn make_subprogram_die(
name: &str,
low_pc: u64,
high_pc: u64,
decl_file: u64,
decl_line: u64,
external: bool,
str_offsets: &mut dyn FnMut(&str) -> u64,
) -> DIE {
let mut sp = DIE::new(dwarf_tags::DW_TAG_subprogram);
let name_off = str_offsets(name);
sp.add_strp(dwarf_attributes::DW_AT_name, name_off, 4);
sp.add_addr(dwarf_attributes::DW_AT_low_pc, low_pc);
sp.add_data8(dwarf_attributes::DW_AT_high_pc, high_pc);
sp.add_data1(dwarf_attributes::DW_AT_decl_file, decl_file as u8);
sp.add_data4(dwarf_attributes::DW_AT_decl_line, decl_line as u32);
if external {
sp.add_flag_present(dwarf_attributes::DW_AT_external);
}
sp
}
pub fn make_variable_die(
name: &str,
type_die_offset: u64,
location_expr: &[u8],
decl_file: u64,
decl_line: u64,
str_offsets: &mut dyn FnMut(&str) -> u64,
) -> DIE {
let mut var = DIE::new(dwarf_tags::DW_TAG_variable);
let name_off = str_offsets(name);
var.add_strp(dwarf_attributes::DW_AT_name, name_off, 4);
var.add_ref4(
dwarf_attributes::DW_AT_type,
dwarf_forms::DW_FORM_ref4,
type_die_offset as u32,
);
var.add_exprloc(dwarf_attributes::DW_AT_location, location_expr);
var.add_data1(dwarf_attributes::DW_AT_decl_file, decl_file as u8);
var.add_data4(dwarf_attributes::DW_AT_decl_line, decl_line as u32);
var
}
#[cfg(test)]
mod tests {
use super::*;
fn mock_str_offset(_s: &str) -> u64 {
0
}
#[test]
fn test_die_set_offset() {
let mut die = DIE::new(dwarf_tags::DW_TAG_compile_unit);
die.set_offset(0x1000);
assert_eq!(die.offset, 0x1000);
}
#[test]
fn test_die_add_ref4() {
let mut die = DIE::new(dwarf_tags::DW_TAG_variable);
die.add_ref4(
dwarf_attributes::DW_AT_type,
dwarf_forms::DW_FORM_ref4,
0x42,
);
assert_eq!(die.attributes.len(), 1);
assert_eq!(die.attributes[0].attr, dwarf_attributes::DW_AT_type);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_ref4);
let val = u32::from_le_bytes(die.attributes[0].value[..4].try_into().unwrap());
assert_eq!(val, 0x42);
}
#[test]
fn test_die_add_sec_offset_32() {
let mut die = DIE::new(dwarf_tags::DW_TAG_compile_unit);
die.add_sec_offset(dwarf_attributes::DW_AT_stmt_list, 0xABCD, 4);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_sec_offset);
assert_eq!(die.attributes[0].value.len(), 4);
}
#[test]
fn test_die_add_sec_offset_64() {
let mut die = DIE::new(dwarf_tags::DW_TAG_compile_unit);
die.add_sec_offset(dwarf_attributes::DW_AT_stmt_list, 0xDEADBEEF, 8);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_sec_offset);
assert_eq!(die.attributes[0].value.len(), 8);
}
#[test]
fn test_die_add_exprloc() {
let mut die = DIE::new(dwarf_tags::DW_TAG_variable);
let expr = vec![0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; die.add_exprloc(dwarf_attributes::DW_AT_location, &expr);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_exprloc);
assert_eq!(die.attributes[0].value[0], 9); assert_eq!(&die.attributes[0].value[1..], &expr[..]);
}
#[test]
fn test_die_add_ref_addr_32() {
let mut die = DIE::new(dwarf_tags::DW_TAG_compile_unit);
die.add_ref_addr(dwarf_attributes::DW_AT_type, 0x12345678, 4);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_ref_addr);
assert_eq!(die.attributes[0].value.len(), 4);
}
#[test]
fn test_die_add_ref_addr_64() {
let mut die = DIE::new(dwarf_tags::DW_TAG_compile_unit);
die.add_ref_addr(dwarf_attributes::DW_AT_type, 0x123456789ABCDEF0, 8);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_ref_addr);
assert_eq!(die.attributes[0].value.len(), 8);
}
#[test]
fn test_die_add_strp_32() {
let mut die = DIE::new(dwarf_tags::DW_TAG_compile_unit);
die.add_strp(dwarf_attributes::DW_AT_name, 0x42, 4);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_strp);
assert_eq!(die.attributes[0].value.len(), 4);
let off = u32::from_le_bytes(die.attributes[0].value[..4].try_into().unwrap());
assert_eq!(off, 0x42);
}
#[test]
fn test_die_add_strp_64() {
let mut die = DIE::new(dwarf_tags::DW_TAG_compile_unit);
die.add_strp(dwarf_attributes::DW_AT_name, 0xDEADBEEF, 8);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_strp);
assert_eq!(die.attributes[0].value.len(), 8);
}
#[test]
fn test_die_add_udata() {
let mut die = DIE::new(dwarf_tags::DW_TAG_subprogram);
die.add_udata(dwarf_attributes::DW_AT_byte_size, 42);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_udata);
assert_eq!(die.attributes[0].value, vec![42]);
}
#[test]
fn test_die_add_sdata_positive() {
let mut die = DIE::new(dwarf_tags::DW_TAG_subprogram);
die.add_sdata(dwarf_attributes::DW_AT_byte_size, 100);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_sdata);
assert!(!die.attributes[0].value.is_empty());
}
#[test]
fn test_die_add_sdata_negative() {
let mut die = DIE::new(dwarf_tags::DW_TAG_subprogram);
die.add_sdata(dwarf_attributes::DW_AT_byte_size, -42);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_sdata);
assert!(!die.attributes[0].value.is_empty());
}
#[test]
fn test_die_add_sdata_zero() {
let mut die = DIE::new(dwarf_tags::DW_TAG_subprogram);
die.add_sdata(dwarf_attributes::DW_AT_byte_size, 0);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_sdata);
assert_eq!(die.attributes[0].value, vec![0]);
}
#[test]
fn test_die_add_flag_present() {
let mut die = DIE::new(dwarf_tags::DW_TAG_subprogram);
die.add_flag_present(dwarf_attributes::DW_AT_external);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_flag_present);
assert!(die.attributes[0].value.is_empty());
}
#[test]
fn test_die_add_block1() {
let mut die = DIE::new(dwarf_tags::DW_TAG_variable);
die.add_block1(dwarf_attributes::DW_AT_location, &[0x01, 0x02, 0x03]);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_block1);
assert_eq!(die.attributes[0].value[0], 3); assert_eq!(&die.attributes[0].value[1..], &[0x01, 0x02, 0x03]);
}
#[test]
fn test_die_add_ref1() {
let mut die = DIE::new(dwarf_tags::DW_TAG_variable);
die.add_ref1(dwarf_attributes::DW_AT_type, 0x42);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_ref1);
assert_eq!(die.attributes[0].value, vec![0x42]);
}
#[test]
fn test_die_add_ref2() {
let mut die = DIE::new(dwarf_tags::DW_TAG_variable);
die.add_ref2(dwarf_attributes::DW_AT_type, 0x1234);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_ref2);
assert_eq!(die.attributes[0].value.len(), 2);
}
#[test]
fn test_die_add_ref8() {
let mut die = DIE::new(dwarf_tags::DW_TAG_variable);
die.add_ref8(dwarf_attributes::DW_AT_type, 0x123456789ABCDEF0);
assert_eq!(die.attributes[0].form, dwarf_forms::DW_FORM_ref8);
assert_eq!(die.attributes[0].value.len(), 8);
}
#[test]
fn test_die_abbrev_signature() {
let mut die = DIE::new(dwarf_tags::DW_TAG_compile_unit);
die.add_string(dwarf_attributes::DW_AT_name, "test");
die.add_data1(dwarf_attributes::DW_AT_decl_file, 1);
let sig = die.abbrev_signature();
assert!(sig.contains("test") == false); assert!(sig.starts_with("17")); }
#[test]
fn test_die_emit_basic() {
let mut die = DIE::new(dwarf_tags::DW_TAG_compile_unit);
die.add_string(dwarf_attributes::DW_AT_name, "test.cu");
die.add_data1(dwarf_attributes::DW_AT_decl_file, 1);
let data = die.emit(1, 8);
assert_eq!(data[0], 1);
let s = String::from_utf8_lossy(&data);
assert!(s.contains("test.cu"));
}
#[test]
fn test_die_emit_with_children() {
let mut parent = DIE::new(dwarf_tags::DW_TAG_compile_unit);
parent.add_string(dwarf_attributes::DW_AT_name, "cu");
parent.add_child(DIE::new(dwarf_tags::DW_TAG_subprogram));
let data = parent.emit(1, 8);
assert_eq!(data.last(), Some(&0));
}
#[test]
fn test_die_emit_no_children_no_null() {
let die = DIE::new(dwarf_tags::DW_TAG_base_type);
let data = die.emit(1, 8);
assert_eq!(data.len(), 1);
assert_eq!(data[0], 1);
}
#[test]
fn test_die_builder_create() {
let builder = DIEBuilder::new(dwarf_tags::DW_TAG_compile_unit);
assert_eq!(builder.die.tag, dwarf_tags::DW_TAG_compile_unit);
assert_eq!(builder.abbrev_table.declarations.len(), 0);
}
#[test]
fn test_die_builder_with_table() {
let table = AbbrevTable::new();
let builder = DIEBuilder::with_table(dwarf_tags::DW_TAG_subprogram, table);
assert_eq!(builder.die.tag, dwarf_tags::DW_TAG_subprogram);
}
#[test]
fn test_die_builder_add_attributes() {
let mut builder = DIEBuilder::new(dwarf_tags::DW_TAG_subprogram);
builder.add_string(dwarf_attributes::DW_AT_name, "main");
builder.add_data1(dwarf_attributes::DW_AT_decl_file, 1);
builder.add_data4(dwarf_attributes::DW_AT_decl_line, 42);
assert_eq!(builder.die.attributes.len(), 3);
}
#[test]
fn test_die_builder_add_child() {
let mut builder = DIEBuilder::new(dwarf_tags::DW_TAG_compile_unit);
let child = DIE::new(dwarf_tags::DW_TAG_subprogram);
builder.add_child(child);
assert!(builder.die.has_children);
assert_eq!(builder.die.children.len(), 1);
}
#[test]
fn test_die_builder_register_abbrev() {
let mut builder = DIEBuilder::new(dwarf_tags::DW_TAG_compile_unit);
builder.add_string(dwarf_attributes::DW_AT_name, "test.cu");
builder.add_data4(dwarf_attributes::DW_AT_decl_line, 10);
let code = builder.register_abbrev();
assert_eq!(code, 1);
assert_eq!(builder.abbrev_table.declarations.len(), 1);
}
#[test]
fn test_die_builder_emit() {
let mut builder = DIEBuilder::new(dwarf_tags::DW_TAG_compile_unit);
builder.add_string(dwarf_attributes::DW_AT_name, "test.cu");
let data = builder.emit(8);
assert!(!data.is_empty());
assert_eq!(data[0], 1);
}
#[test]
fn test_encode_attr_addr_64() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_addr, 0x123456789ABCDEF0, 8, 4, None);
assert_eq!(bytes.len(), 8);
let val = u64::from_le_bytes(bytes.try_into().unwrap());
assert_eq!(val, 0x123456789ABCDEF0);
}
#[test]
fn test_encode_attr_addr_32() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_addr, 0x12345678, 4, 4, None);
assert_eq!(bytes.len(), 4);
let val = u32::from_le_bytes(bytes.try_into().unwrap());
assert_eq!(val, 0x12345678);
}
#[test]
fn test_encode_attr_data1() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_data1, 0x42, 0, 0, None);
assert_eq!(bytes, vec![0x42]);
}
#[test]
fn test_encode_attr_data2() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_data2, 0x1234, 0, 0, None);
assert_eq!(bytes.len(), 2);
let val = u16::from_le_bytes(bytes.try_into().unwrap());
assert_eq!(val, 0x1234);
}
#[test]
fn test_encode_attr_data4() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_data4, 0xDEADBEEF, 0, 0, None);
assert_eq!(bytes.len(), 4);
let val = u32::from_le_bytes(bytes.try_into().unwrap());
assert_eq!(val, 0xDEADBEEF);
}
#[test]
fn test_encode_attr_data8() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_data8, 0x123456789ABCDEF0, 0, 0, None);
assert_eq!(bytes.len(), 8);
}
#[test]
fn test_encode_attr_string() {
let s = b"hello\0";
let bytes = encode_attr_value(dwarf_forms::DW_FORM_string, 0, 0, 0, Some(s));
assert_eq!(bytes, s);
}
#[test]
fn test_encode_attr_flag_true() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_flag, 1, 0, 0, None);
assert_eq!(bytes, vec![1]);
}
#[test]
fn test_encode_attr_flag_false() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_flag, 0, 0, 0, None);
assert_eq!(bytes, vec![0]);
}
#[test]
fn test_encode_attr_flag_present() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_flag_present, 0, 0, 0, None);
assert!(bytes.is_empty());
}
#[test]
fn test_encode_attr_udata_small() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_udata, 42, 0, 0, None);
assert_eq!(bytes, vec![42]);
}
#[test]
fn test_encode_attr_udata_large() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_udata, 624485, 0, 0, None);
assert_eq!(bytes.len(), 3);
}
#[test]
fn test_encode_attr_sdata_positive() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_sdata, 100, 0, 0, None);
assert!(!bytes.is_empty());
}
#[test]
fn test_encode_attr_sdata_negative() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_sdata, (-42i64) as u64, 0, 0, None);
assert!(!bytes.is_empty());
}
#[test]
fn test_encode_attr_ref1() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_ref1, 0xAB, 0, 0, None);
assert_eq!(bytes, vec![0xAB]);
}
#[test]
fn test_encode_attr_ref4() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_ref4, 0x12345678, 0, 0, None);
assert_eq!(bytes.len(), 4);
}
#[test]
fn test_encode_attr_sec_offset_32() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_sec_offset, 0xABCD, 0, 4, None);
assert_eq!(bytes.len(), 4);
}
#[test]
fn test_encode_attr_sec_offset_64() {
let bytes = encode_attr_value(dwarf_forms::DW_FORM_sec_offset, 0xDEADBEEF, 0, 8, None);
assert_eq!(bytes.len(), 8);
}
#[test]
fn test_encode_attr_exprloc() {
let expr = vec![0x9f]; let bytes = encode_attr_value(dwarf_forms::DW_FORM_exprloc, 0, 0, 0, Some(&expr));
assert_eq!(bytes[0], 1); assert_eq!(bytes[1], 0x9f);
}
#[test]
fn test_encode_attr_block1() {
let data = vec![0x01, 0x02, 0x03, 0x04];
let bytes = encode_attr_value(dwarf_forms::DW_FORM_block1, 0, 0, 0, Some(&data));
assert_eq!(bytes[0], 4); assert_eq!(&bytes[1..], &[0x01, 0x02, 0x03, 0x04]);
}
#[test]
fn test_encode_attr_unknown_form() {
let bytes = encode_attr_value(0xFFFF, 42, 8, 4, None);
assert!(bytes.is_empty());
}
#[test]
fn test_make_compile_unit_die() {
let die = make_compile_unit_die(
"test.c",
"clang",
"/tmp",
dwarf_languages::DW_LANG_C,
0x1000,
0x200,
0x500,
8,
&mut mock_str_offset,
);
assert_eq!(die.tag, dwarf_tags::DW_TAG_compile_unit);
assert_eq!(die.attributes.len(), 7);
}
#[test]
fn test_make_subprogram_die() {
let die = make_subprogram_die("main", 0x4000, 0x100, 1, 10, true, &mut mock_str_offset);
assert_eq!(die.tag, dwarf_tags::DW_TAG_subprogram);
assert!(die.attributes.len() >= 5);
}
#[test]
fn test_make_variable_die() {
let die = make_variable_die(
"x",
0x42,
&[dwarf_types::dwarf_ops::DW_OP_reg0],
1,
5,
&mut mock_str_offset,
);
assert_eq!(die.tag, dwarf_tags::DW_TAG_variable);
assert!(die.attributes.len() >= 4);
}
}