Support address in config symbol references

Example: `symbol_name!.data:0x1234`
Allows disambiguating local symbols
with the same name.

Supported in `extract` and
`add_relocations` in config.yml

Resolves #58
This commit is contained in:
Luke Street 2024-06-03 18:08:06 -06:00
parent 4701de32f6
commit 61cd72cd11
2 changed files with 40 additions and 7 deletions

View File

@ -947,11 +947,10 @@ fn split_write_obj(
let (_, symbol) = module let (_, symbol) = module
.obj .obj
.symbols .symbols
.by_name(&extract.symbol)? .by_ref(&module.obj.sections, &extract.symbol)?
.with_context(|| format!("Failed to locate symbol '{}'", extract.symbol))?; .with_context(|| format!("Failed to locate symbol '{}'", extract.symbol))?;
let section_index = symbol let section_index =
.section symbol.section.with_context(|| format!("Symbol '{}' has no section", symbol.name))?;
.with_context(|| format!("Symbol '{}' has no section", extract.symbol))?;
let section = &module.obj.sections[section_index]; let section = &module.obj.sections[section_index];
let data = section.symbol_data(symbol)?; let data = section.symbol_data(symbol)?;
@ -1893,7 +1892,7 @@ fn apply_block_relocations(
fn apply_add_relocations(obj: &mut ObjInfo, relocations: &[AddRelocationConfig]) -> Result<()> { fn apply_add_relocations(obj: &mut ObjInfo, relocations: &[AddRelocationConfig]) -> Result<()> {
for reloc in relocations { for reloc in relocations {
let SectionAddress { section, address } = reloc.source.resolve(obj)?; let SectionAddress { section, address } = reloc.source.resolve(obj)?;
let (target_symbol, _) = match obj.symbols.by_name(&reloc.target)? { let (target_symbol, _) = match obj.symbols.by_ref(&obj.sections, &reloc.target)? {
Some(v) => v, Some(v) => v,
None => { None => {
// Assume external symbol // Assume external symbol

View File

@ -12,9 +12,9 @@ use serde_repr::{Deserialize_repr, Serialize_repr};
use crate::{ use crate::{
analysis::cfa::SectionAddress, analysis::cfa::SectionAddress,
obj::{ObjKind, ObjRelocKind}, obj::{ObjKind, ObjRelocKind, ObjSections},
util::{ util::{
config::{is_auto_jump_table, is_auto_label, is_auto_symbol}, config::{is_auto_jump_table, is_auto_label, is_auto_symbol, parse_u32},
nested::NestedVec, nested::NestedVec,
split::is_linker_generated_label, split::is_linker_generated_label,
}, },
@ -477,6 +477,40 @@ impl ObjSymbols {
Ok(result) Ok(result)
} }
/// Locate a symbol by name, with optional reference attributes. Example:
/// `symbol_name!.data:0x1234` will find the symbol named `symbol_name`
/// in the `.data` section at address `0x1234`.
pub fn by_ref<'a>(
&'a self,
sections: &ObjSections,
symbol_ref: &str,
) -> Result<Option<(SymbolIndex, &'a ObjSymbol)>> {
if let Some((name, rest)) = symbol_ref.split_once('!') {
let (section_index, address) = if let Some((section_name, rest)) = rest.split_once(':')
{
let section_index = sections
.by_name(section_name)?
.map(|(idx, _)| idx)
.ok_or_else(|| anyhow!("Section not found: {}", section_name))?;
(Some(section_index), parse_u32(rest)?)
} else {
(None, parse_u32(rest)?)
};
let mut out = None;
for (index, symbol) in self.for_name(name) {
if (section_index.is_none() || symbol.section == section_index)
&& symbol.address == address as u64
{
ensure!(out.is_none(), "Multiple symbols matched {}", symbol_ref);
out = Some((index, symbol));
}
}
Ok(out)
} else {
self.by_name(symbol_ref)
}
}
pub fn by_kind( pub fn by_kind(
&self, &self,
kind: ObjSymbolKind, kind: ObjSymbolKind,