Skip to content

Commit

Permalink
handle offset values other than zero in SYMBOL_LINK
Browse files Browse the repository at this point in the history
Fixes issue #42
  • Loading branch information
DanielT committed Dec 13, 2024
1 parent f72e89a commit 7e380a1
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::ffi::OsStr;
use std::fmt::Display;

mod dwarf;
mod iter;
pub(crate) mod iter;
mod pdb;

#[derive(Debug)]
Expand Down
45 changes: 35 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1194,8 +1194,13 @@ mod test {
// cleanup_test.a2l has unused items, but --cleanup should remove them
core(args.into_iter()).unwrap();

let a2l_input =
a2lfile::load("fixtures/a2l/cleanup_test.a2l", None, &mut Vec::new(), false).unwrap();
let a2l_input = a2lfile::load(
"fixtures/a2l/cleanup_test.a2l",
None,
&mut Vec::new(),
false,
)
.unwrap();
let a2l_output = a2lfile::load(outfile, None, &mut Vec::new(), false).unwrap();
assert_ne!(a2l_input, a2l_output);
// all items in cleanup_test.a2l are used
Expand Down Expand Up @@ -1399,8 +1404,13 @@ mod test {
OsString::from(outfile.clone()),
];
core(args.into_iter()).unwrap();
let a2l_input =
a2lfile::load("fixtures/a2l/update_test1.a2l", None, &mut Vec::new(), false).unwrap();
let a2l_input = a2lfile::load(
"fixtures/a2l/update_test1.a2l",
None,
&mut Vec::new(),
false,
)
.unwrap();
let a2l_output = a2lfile::load(outfile, None, &mut Vec::new(), false).unwrap();
// there should be only one MODULE in the output
assert_eq!(a2l_output.project.module.len(), 1);
Expand Down Expand Up @@ -1438,8 +1448,13 @@ mod test {
OsString::from(outfile.clone()),
];
core(args.into_iter()).unwrap();
let a2l_input =
a2lfile::load("fixtures/a2l/update_test1.a2l", None, &mut Vec::new(), false).unwrap();
let a2l_input = a2lfile::load(
"fixtures/a2l/update_test1.a2l",
None,
&mut Vec::new(),
false,
)
.unwrap();
let a2l_output = a2lfile::load(outfile, None, &mut Vec::new(), false).unwrap();
// there should be two MODULEs in the output
assert_eq!(a2l_output.project.module.len(), 2);
Expand All @@ -1459,8 +1474,13 @@ mod test {
#[test]
fn test_option_remove() {
// items can be removed by name with --remove
let a2l_input =
a2lfile::load("fixtures/a2l/update_test1.a2l", None, &mut Vec::new(), false).unwrap();
let a2l_input = a2lfile::load(
"fixtures/a2l/update_test1.a2l",
None,
&mut Vec::new(),
false,
)
.unwrap();
// get the names of the first characteristic and measurement, so they can be removed
let characteristic_name = a2l_input.project.module[0].characteristic[0].name.clone();
let measurement_name = a2l_input.project.module[0].measurement[0].name.clone();
Expand Down Expand Up @@ -1559,8 +1579,13 @@ mod test {
OsString::from(outfile.clone()),
];
core(args.into_iter()).unwrap();
let a2l_input =
a2lfile::load("fixtures/a2l/update_test1.a2l", None, &mut Vec::new(), false).unwrap();
let a2l_input = a2lfile::load(
"fixtures/a2l/update_test1.a2l",
None,
&mut Vec::new(),
false,
)
.unwrap();
let a2l_output = a2lfile::load(outfile, None, &mut Vec::new(), false).unwrap();

// Though sorting does not change the meaning of the file, the order of the items in the output is different.
Expand Down
38 changes: 38 additions & 0 deletions src/symbol.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::debuginfo::iter::TypeInfoIter;
use crate::debuginfo::{make_simple_unit_name, DebugData, TypeInfo};
use crate::debuginfo::{DbgDataType, VarInfo};

Expand Down Expand Up @@ -320,6 +321,43 @@ fn get_index(idxstr: &str) -> Option<usize> {
}
}

/// find a component of a symbol based on an offset from the base address
/// For example this could be a particular array element or struct member
pub(crate) fn find_symbol_by_offset<'a>(
base_symbol: &SymbolInfo<'a>,
offset: i32,
debug_data: &'a DebugData,
) -> Result<SymbolInfo<'a>, String> {
if offset < 0 || offset > base_symbol.typeinfo.get_size() as i32 {
return Err(format!(
"Offset {} is out of bounds for symbol \"{}\"",
offset, base_symbol.name
));
}

let offset = offset as u64;

let iter = TypeInfoIter::new(&debug_data.types, base_symbol.typeinfo, false);
for (name, typeinfo, item_offset) in iter {
if item_offset == offset {
return Ok(SymbolInfo {
name: format!("{}{}", base_symbol.name, name),
address: item_offset + base_symbol.address,
typeinfo,
unit_idx: base_symbol.unit_idx,
function_name: base_symbol.function_name,
namespaces: base_symbol.namespaces,
is_unique: base_symbol.is_unique,
});
}
}

Err(format!(
"Could not find a symbol component at offset {offset} from \"{}\"",
base_symbol.name
))
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
65 changes: 63 additions & 2 deletions src/update/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub(crate) mod typedef;

use crate::datatype::{get_a2l_datatype, get_type_limits};
use crate::debuginfo::DbgDataType;
use crate::symbol::{find_symbol, SymbolInfo};
use crate::symbol::{find_symbol, find_symbol_by_offset, SymbolInfo};
use axis_pts::*;
use blob::{cleanup_removed_blobs, update_all_module_blobs};
use characteristic::*;
Expand Down Expand Up @@ -245,7 +245,16 @@ fn get_symbol_info<'a>(
// preferred: get symbol information from a SYMBOL_LINK attribute
if let Some(symbol_link) = opt_symbol_link {
match find_symbol(&symbol_link.symbol_name, debug_data) {
Ok(sym_info) => return Ok(sym_info),
Ok(sym_info) => {
if symbol_link.offset == 0 {
return Ok(sym_info);
} else {
match find_symbol_by_offset(&sym_info, symbol_link.offset, debug_data) {
Ok(sym_info) => return Ok(sym_info),
Err(errmsg) => return Err(vec![errmsg]),
}
}
}
Err(errmsg) => symbol_link_errmsg = Some(errmsg),
};
}
Expand Down Expand Up @@ -1137,4 +1146,56 @@ mod test {
assert_eq!(summary.instance_updated, 1);
assert!(log_msgs.is_empty());
}

#[test]
fn test_symbol_with_offset() {
// load update_test.elf
// This file contains:
// struct UpdateTest_ComplexBlobData {
// uint32_t value_1[16];
// struct {
// uint16_t value_2_1;
// uint32_t value_2_2;
// } value_2[8];
// };
// struct UpdateTest_ComplexBlobData Blob_1;
let debug_data = crate::debuginfo::DebugData::load_dwarf(
&OsString::from("fixtures/bin/update_test.elf"),
false,
)
.unwrap();

let symbol_link_base = a2lfile::SymbolLink::new("Blob_1".to_string(), 0);
let sym_info = get_symbol_info("", &Some(symbol_link_base), &[], &debug_data).unwrap();
let base_address = sym_info.address;
assert!(base_address != 0);
assert!(matches!(
sym_info.typeinfo.datatype,
DbgDataType::Struct { .. }
));

// offset 8 is inside the first array of the struct, so the symbol name should be "Blob_1.value_1[2]"
let symbol_link_elem = a2lfile::SymbolLink::new("Blob_1".to_string(), 8);
let sym_info = get_symbol_info("", &Some(symbol_link_elem), &[], &debug_data).unwrap();
assert_eq!(sym_info.address, base_address + 8);
assert_eq!(sym_info.name, "Blob_1.value_1._2_");
assert!(matches!(sym_info.typeinfo.datatype, DbgDataType::Uint32));

// offset 68 is inside the second array of the struct
let symbol_link_elem = a2lfile::SymbolLink::new("Blob_1".to_string(), 68);
let sym_info = get_symbol_info("", &Some(symbol_link_elem), &[], &debug_data).unwrap();
assert_eq!(sym_info.address, base_address + 68);
assert_eq!(sym_info.name, "Blob_1.value_2._0_.value_2_2");
assert!(matches!(sym_info.typeinfo.datatype, DbgDataType::Uint32));

// offset 1000 is outside the struct, which should trigger an error
let symbol_link_elem = a2lfile::SymbolLink::new("Blob_1".to_string(), 1000);
let sym_info_result = get_symbol_info("", &Some(symbol_link_elem), &[], &debug_data);
assert!(sym_info_result.is_err());

// a2l allows negative offsets, which makes no sense at all. This also triggers an error
let symbol_link_elem = a2lfile::SymbolLink::new("Blob_1".to_string(), -1);
let sym_info_result = get_symbol_info("", &Some(symbol_link_elem), &[], &debug_data);
assert!(sym_info_result.is_err());
}
}
9 changes: 7 additions & 2 deletions src/update/typedef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2189,8 +2189,13 @@ mod test {
);

let mut log_msgs = Vec::new();
let mut reference_a2l =
a2lfile::load("fixtures/a2l/update_typedef_test4.a2l", None, &mut log_msgs, true).unwrap();
let mut reference_a2l = a2lfile::load(
"fixtures/a2l/update_typedef_test4.a2l",
None,
&mut log_msgs,
true,
)
.unwrap();

// ordering is not guaranteed, so sort both files before comparing them
a2l.sort();
Expand Down

0 comments on commit 7e380a1

Please sign in to comment.