Skip to content

Commit 7b897db

Browse files
authored
read/macho: split object names in ObjectMap (#686)
1 parent aa2f5ad commit 7b897db

File tree

3 files changed

+54
-11
lines changed

3 files changed

+54
-11
lines changed

crates/examples/src/bin/objectmap.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,16 @@ fn main() {
5757
}
5858

5959
fn print_symbol(symbol: &object::ObjectMapEntry<'_>, map: &object::ObjectMap<'_>) {
60-
println!(
60+
let file = symbol.object(map);
61+
print!(
6162
"{:x} {:x} {} {}",
6263
symbol.address(),
6364
symbol.size(),
6465
String::from_utf8_lossy(symbol.name()),
65-
String::from_utf8_lossy(symbol.object(map)),
66+
String::from_utf8_lossy(file.path()),
6667
);
68+
if let Some(member) = file.member() {
69+
print!("({})", String::from_utf8_lossy(member));
70+
}
71+
println!();
6772
}

src/read/macho/symbol.rs

+17-4
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ use crate::macho;
77
use crate::pod::Pod;
88
use crate::read::util::StringTable;
99
use crate::read::{
10-
self, ObjectMap, ObjectMapEntry, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, Result,
11-
SectionIndex, SectionKind, SymbolFlags, SymbolIndex, SymbolKind, SymbolMap, SymbolMapEntry,
12-
SymbolScope, SymbolSection,
10+
self, ObjectMap, ObjectMapEntry, ObjectMapFile, ObjectSymbol, ObjectSymbolTable, ReadError,
11+
ReadRef, Result, SectionIndex, SectionKind, SymbolFlags, SymbolIndex, SymbolKind, SymbolMap,
12+
SymbolMapEntry, SymbolScope, SymbolSection,
1313
};
1414

1515
use super::{MachHeader, MachOFile};
@@ -115,7 +115,20 @@ impl<'data, Mach: MachHeader, R: ReadRef<'data>> SymbolTable<'data, Mach, R> {
115115
if let Ok(name) = nlist.name(endian, self.strings) {
116116
if !name.is_empty() {
117117
object = Some(objects.len());
118-
objects.push(name);
118+
// `N_OSO` symbol names can be either `/path/to/object.o`
119+
// or `/path/to/archive.a(object.o)`.
120+
let (path, member) = name
121+
.split_last()
122+
.and_then(|(last, head)| {
123+
if *last != b')' {
124+
return None;
125+
}
126+
let index = head.iter().position(|&x| x == b'(')?;
127+
let (archive, rest) = head.split_at(index);
128+
Some((archive, Some(&rest[1..])))
129+
})
130+
.unwrap_or((name, None));
131+
objects.push(ObjectMapFile::new(path, member));
119132
}
120133
}
121134
}

src/read/mod.rs

+30-5
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ impl<'data> SymbolMapEntry for SymbolMapName<'data> {
512512
#[derive(Debug, Default, Clone)]
513513
pub struct ObjectMap<'data> {
514514
symbols: SymbolMap<ObjectMapEntry<'data>>,
515-
objects: Vec<&'data [u8]>,
515+
objects: Vec<ObjectMapFile<'data>>,
516516
}
517517

518518
impl<'data> ObjectMap<'data> {
@@ -531,12 +531,12 @@ impl<'data> ObjectMap<'data> {
531531

532532
/// Get all objects in the map.
533533
#[inline]
534-
pub fn objects(&self) -> &[&'data [u8]] {
534+
pub fn objects(&self) -> &[ObjectMapFile<'data>] {
535535
&self.objects
536536
}
537537
}
538538

539-
/// An [`ObjectMap`] entry.
539+
/// A symbol in an [`ObjectMap`].
540540
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
541541
pub struct ObjectMapEntry<'data> {
542542
address: u64,
@@ -574,8 +574,8 @@ impl<'data> ObjectMapEntry<'data> {
574574

575575
/// Get the object file name.
576576
#[inline]
577-
pub fn object(&self, map: &ObjectMap<'data>) -> &'data [u8] {
578-
map.objects[self.object]
577+
pub fn object<'a>(&self, map: &'a ObjectMap<'data>) -> &'a ObjectMapFile<'data> {
578+
&map.objects[self.object]
579579
}
580580
}
581581

@@ -586,6 +586,31 @@ impl<'data> SymbolMapEntry for ObjectMapEntry<'data> {
586586
}
587587
}
588588

589+
/// An object file name in an [`ObjectMap`].
590+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
591+
pub struct ObjectMapFile<'data> {
592+
path: &'data [u8],
593+
member: Option<&'data [u8]>,
594+
}
595+
596+
impl<'data> ObjectMapFile<'data> {
597+
fn new(path: &'data [u8], member: Option<&'data [u8]>) -> Self {
598+
ObjectMapFile { path, member }
599+
}
600+
601+
/// Get the path to the file containing the object.
602+
#[inline]
603+
pub fn path(&self) -> &'data [u8] {
604+
self.path
605+
}
606+
607+
/// If the file is an archive, get the name of the member containing the object.
608+
#[inline]
609+
pub fn member(&self) -> Option<&'data [u8]> {
610+
self.member
611+
}
612+
}
613+
589614
/// An imported symbol.
590615
///
591616
/// Returned by [`Object::imports`].

0 commit comments

Comments
 (0)