1use std::{
2 backtrace::Backtrace,
3 collections::{BTreeMap, HashMap, btree_map, hash_map},
4 fmt::Display,
5 io::{self, BufRead, BufReader, BufWriter, Write},
6 num::ParseIntError,
7 ops::Range,
8 path::Path,
9 slice,
10};
11
12use snafu::{Snafu, ensure};
13
14use crate::{
15 analysis::{functions::Function, jump_table::JumpTable},
16 util::{
17 io::{FileError, create_file, open_file},
18 parse::parse_u32,
19 },
20};
21
22use super::{ParseContext, config::Config, iter_attributes, module::ModuleKind};
23
24pub struct SymbolMaps {
25 symbol_maps: BTreeMap<ModuleKind, SymbolMap>,
26}
27
28#[derive(Debug, Snafu)]
29pub enum SymbolMapsParseError {
30 #[snafu(transparent)]
31 SymbolMapParse { source: SymbolMapParseError },
32}
33
34#[derive(Debug, Snafu)]
35pub enum SymbolMapsWriteError {
36 #[snafu(display("Symbol map not found for {module}:\n{backtrace}"))]
37 SymbolMapNotFound { module: ModuleKind, backtrace: Backtrace },
38 #[snafu(transparent)]
39 SymbolMapWrite { source: SymbolMapWriteError },
40}
41
42impl SymbolMaps {
43 pub fn new() -> Self {
44 Self { symbol_maps: BTreeMap::new() }
45 }
46
47 pub fn get(&self, module: ModuleKind) -> Option<&SymbolMap> {
48 self.symbol_maps.get(&module)
49 }
50
51 pub fn get_mut(&mut self, module: ModuleKind) -> &mut SymbolMap {
52 self.symbol_maps.entry(module).or_insert_with(SymbolMap::new)
53 }
54
55 pub fn from_config<P: AsRef<Path>>(config_path: P, config: &Config) -> Result<Self, SymbolMapsParseError> {
56 let config_path = config_path.as_ref();
57
58 let mut symbol_maps = SymbolMaps::new();
59 symbol_maps.get_mut(ModuleKind::Arm9).load(config_path.join(&config.main_module.symbols))?;
60 for autoload in &config.autoloads {
61 symbol_maps.get_mut(ModuleKind::Autoload(autoload.kind)).load(config_path.join(&autoload.module.symbols))?;
62 }
63 for overlay in &config.overlays {
64 symbol_maps.get_mut(ModuleKind::Overlay(overlay.id)).load(config_path.join(&overlay.module.symbols))?;
65 }
66
67 Ok(symbol_maps)
68 }
69
70 pub fn to_files<P: AsRef<Path>>(&self, config: &Config, config_path: P) -> Result<(), SymbolMapsWriteError> {
71 let config_path = config_path.as_ref();
72 self.get(ModuleKind::Arm9)
73 .ok_or_else(|| SymbolMapNotFoundSnafu { module: ModuleKind::Arm9 }.build())?
74 .to_file(config_path.join(&config.main_module.symbols))?;
75 for autoload in &config.autoloads {
76 let module = ModuleKind::Autoload(autoload.kind);
77 self.get(module)
78 .ok_or_else(|| SymbolMapNotFoundSnafu { module }.build())?
79 .to_file(config_path.join(&autoload.module.symbols))?;
80 }
81 for overlay in &config.overlays {
82 let module = ModuleKind::Overlay(overlay.id);
83 self.get(module)
84 .ok_or_else(|| SymbolMapNotFoundSnafu { module }.build())?
85 .to_file(config_path.join(&overlay.module.symbols))?;
86 }
87
88 Ok(())
89 }
90
91 pub fn iter(&self) -> impl Iterator<Item = (ModuleKind, &'_ SymbolMap)> {
92 self.symbol_maps.iter().map(|(module, symbol_map)| (*module, symbol_map))
93 }
94
95 pub fn iter_mut(&mut self) -> impl Iterator<Item = (ModuleKind, &'_ mut SymbolMap)> {
96 self.symbol_maps.iter_mut().map(|(module, symbol_map)| (*module, symbol_map))
97 }
98
99 pub fn find_symbols_by_name(&self, name: &str) -> impl Iterator<Item = (ModuleKind, SymbolIndex, &Symbol)> {
100 self.symbol_maps.iter().flat_map(|(module, symbol_map)| {
101 symbol_map
102 .for_name(name)
103 .into_iter()
104 .flat_map(move |symbols| symbols.map(|(index, symbol)| (*module, index, symbol)))
105 })
106 }
107}
108
109#[derive(Clone, Copy, PartialEq, Eq)]
110pub struct SymbolIndex(usize);
111
112pub struct SymbolMap {
113 symbols: Vec<Symbol>,
114 symbols_by_address: BTreeMap<u32, Vec<SymbolIndex>>,
115 symbols_by_name: HashMap<String, Vec<SymbolIndex>>,
116}
117
118#[derive(Debug, Snafu)]
119pub enum SymbolMapParseError {
120 #[snafu(transparent)]
121 File { source: FileError },
122 #[snafu(transparent)]
123 Io { source: io::Error },
124 #[snafu(transparent)]
125 SymbolParse { source: SymbolParseError },
126}
127
128#[derive(Debug, Snafu)]
129pub enum SymbolMapWriteError {
130 #[snafu(transparent)]
131 File { source: FileError },
132 #[snafu(transparent)]
133 Io { source: io::Error },
134}
135
136#[derive(Debug, Snafu)]
137pub enum SymbolMapError {
138 #[snafu(display("multiple symbols at {address:#010x}: {name}, {other_name}:\n{backtrace}"))]
139 MultipleSymbols { address: u32, name: String, other_name: String, backtrace: Backtrace },
140 #[snafu(display("multiple symbols with name '{name}': {old_address:#010x}, {new_address:#010x}:\n{backtrace}"))]
141 DuplicateName { name: String, new_address: u32, old_address: u32, backtrace: Backtrace },
142 #[snafu(display("no symbol at {address:#010x} to rename to '{new_name}':\n{backtrace}"))]
143 NoSymbolToRename { address: u32, new_name: String, backtrace: Backtrace },
144 #[snafu(display("there must be exactly one symbol at {address:#010x} to rename to '{new_name}':\n{backtrace}"))]
145 RenameMultiple { address: u32, new_name: String, backtrace: Backtrace },
146}
147
148impl SymbolMap {
149 pub fn new() -> Self {
150 Self::from_symbols(vec![])
151 }
152
153 pub fn from_symbols(symbols: Vec<Symbol>) -> Self {
154 let mut symbols_by_address = BTreeMap::<u32, Vec<_>>::new();
155 let mut symbols_by_name = HashMap::<String, Vec<_>>::new();
156
157 for (index, symbol) in symbols.iter().enumerate() {
158 symbols_by_address.entry(symbol.addr).or_default().push(SymbolIndex(index));
159 symbols_by_name.entry(symbol.name.clone()).or_default().push(SymbolIndex(index));
160 }
161
162 Self { symbols, symbols_by_address, symbols_by_name }
163 }
164
165 pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, SymbolMapParseError> {
166 let mut symbol_map = Self::new();
167 symbol_map.load(path)?;
168 Ok(symbol_map)
169 }
170
171 pub fn load<P: AsRef<Path>>(&mut self, path: P) -> Result<(), SymbolMapParseError> {
172 let path = path.as_ref();
173 let mut context = ParseContext { file_path: path.to_str().unwrap().to_string(), row: 0 };
174
175 let file = open_file(path)?;
176 let reader = BufReader::new(file);
177
178 for line in reader.lines() {
179 context.row += 1;
180
181 let line = line?;
182 let comment_start = line.find("//").unwrap_or(line.len());
183 let line = &line[..comment_start];
184
185 let Some(symbol) = Symbol::parse(line, &context)? else { continue };
186 self.add(symbol);
187 }
188 Ok(())
189 }
190
191 pub fn to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), SymbolMapWriteError> {
192 let path = path.as_ref();
193
194 let file = create_file(path)?;
195 let mut writer = BufWriter::new(file);
196
197 for indices in self.symbols_by_address.values() {
198 for &index in indices {
199 let symbol = &self.symbols[index.0];
200 if symbol.should_write() {
201 writeln!(writer, "{symbol}")?;
202 }
203 }
204 }
205
206 Ok(())
207 }
208
209 pub fn for_address(&self, address: u32) -> Option<impl DoubleEndedIterator<Item = (SymbolIndex, &Symbol)>> {
210 Some(self.symbols_by_address.get(&address)?.iter().map(|&i| (i, &self.symbols[i.0])))
211 }
212
213 pub fn by_address(&self, address: u32) -> Result<Option<(SymbolIndex, &Symbol)>, SymbolMapError> {
214 let Some(mut symbols) = self.for_address(address) else {
215 return Ok(None);
216 };
217 let (index, symbol) = symbols.next().unwrap();
218 if let Some((_, other)) = symbols.next() {
219 return MultipleSymbolsSnafu { address, name: symbol.name.clone(), other_name: other.name.clone() }.fail();
220 }
221 Ok(Some((index, symbol)))
222 }
223
224 pub fn first_at_address(&self, address: u32) -> Option<(SymbolIndex, &Symbol)> {
225 self.for_address(address)?.next()
226 }
227
228 pub fn for_name(&self, name: &str) -> Option<impl DoubleEndedIterator<Item = (SymbolIndex, &Symbol)>> {
229 Some(self.symbols_by_name.get(name)?.iter().map(|&i| (i, &self.symbols[i.0])))
230 }
231
232 pub fn by_name(&self, name: &str) -> Result<Option<(SymbolIndex, &Symbol)>, SymbolMapError> {
233 let Some(mut symbols) = self.for_name(name) else {
234 return Ok(None);
235 };
236 let (index, symbol) = symbols.next().unwrap();
237 if let Some((_, other)) = symbols.next() {
238 return DuplicateNameSnafu { name, new_address: symbol.addr, old_address: other.addr }.fail();
239 }
240 Ok(Some((index, symbol)))
241 }
242
243 pub fn iter_by_address(&self, range: Range<u32>) -> SymbolIterator {
244 SymbolIterator { symbols_by_address: self.symbols_by_address.range(range), indices: [].iter(), symbols: &self.symbols }
245 }
246
247 pub fn first_symbol_before(&self, max_address: u32) -> Option<Vec<(SymbolIndex, &Symbol)>> {
249 self.symbols_by_address.range(0..=max_address).rev().find_map(|(_, indices)| {
250 let symbols = indices
251 .iter()
252 .filter_map(|&i| {
253 let symbol = &self.symbols[i.0];
254 symbol.is_external().then_some((i, symbol))
255 })
256 .collect::<Vec<_>>();
257 (!symbols.is_empty()).then_some(symbols)
258 })
259 }
260
261 pub fn first_symbol_after(&self, min_address: u32) -> Option<Vec<(SymbolIndex, &Symbol)>> {
263 self.symbols_by_address.range(min_address + 1..).find_map(|(_, indices)| {
264 let symbols = indices
265 .iter()
266 .filter_map(|&i| {
267 let symbol = &self.symbols[i.0];
268 symbol.is_external().then_some((i, symbol))
269 })
270 .collect::<Vec<_>>();
271 (!symbols.is_empty()).then_some(symbols)
272 })
273 }
274
275 pub fn iter(&self) -> impl Iterator<Item = &'_ Symbol> {
276 self.symbols_by_address.values().flat_map(|indices| indices.iter()).map(|&i| &self.symbols[i.0])
277 }
278
279 pub fn indices_by_address(&self) -> impl Iterator<Item = &SymbolIndex> {
280 self.symbols_by_address.values().flat_map(|indices| indices.iter())
281 }
282
283 pub fn get(&self, index: SymbolIndex) -> Option<&Symbol> {
284 self.symbols.get(index.0)
285 }
286
287 pub fn get_mut(&mut self, index: SymbolIndex) -> Option<&mut Symbol> {
288 self.symbols.get_mut(index.0)
289 }
290
291 pub fn get_symbol_containing(&self, addr: u32, section_end: u32) -> Result<Option<(&Symbol, u32)>, SymbolMapError> {
293 let Some(symbols) = self.first_symbol_before(addr) else {
294 return Ok(None);
295 };
296 let (_, symbol) = symbols.first().unwrap();
297 let Some(symbols) = self.first_symbol_after(symbol.addr) else {
298 return Ok(Some((symbol, symbol.size(section_end))));
299 };
300 let next_symbol = symbols.first().unwrap().1;
301
302 Ok(Some((symbol, symbol.size(next_symbol.addr.min(section_end)))))
303 }
304
305 pub fn add(&mut self, symbol: Symbol) -> (SymbolIndex, &Symbol) {
306 let index = SymbolIndex(self.symbols.len());
307 self.symbols_by_address.entry(symbol.addr).or_default().push(index);
308 self.symbols_by_name.entry(symbol.name.clone()).or_default().push(index);
309 self.symbols.push(symbol);
310
311 (index, self.symbols.last().unwrap())
312 }
313
314 pub fn add_if_new_address(&mut self, symbol: Symbol) -> Result<(SymbolIndex, &Symbol), SymbolMapError> {
315 if self.symbols_by_address.contains_key(&symbol.addr) {
316 Ok(self.by_address(symbol.addr)?.unwrap())
317 } else {
318 Ok(self.add(symbol))
319 }
320 }
321
322 pub fn get_function(&self, address: u32) -> Result<Option<(SymFunction, &Symbol)>, SymbolMapError> {
323 let Some(symbols) = self.for_address(address & !1) else {
324 return Ok(None);
325 };
326 let mut symbols = symbols.filter(|(_, sym)| matches!(sym.kind, SymbolKind::Function(_)));
327 let Some((_, symbol)) = symbols.next() else {
328 return Ok(None);
329 };
330 if let Some((_, other)) = symbols.next() {
331 return MultipleSymbolsSnafu { address, name: symbol.name.clone(), other_name: other.name.clone() }.fail();
332 }
333
334 Ok(match symbol.kind {
335 SymbolKind::Function(function) => Some((function, symbol)),
336 _ => None,
337 })
338 }
339
340 pub fn get_function_mut(&mut self, address: u32) -> Result<Option<&mut Symbol>, SymbolMapError> {
341 let Some(symbols) = self.symbols_by_address.get_mut(&(address & !1)) else {
342 return Ok(None);
343 };
344
345 let mut symbols = symbols.iter().filter(|i| matches!(self.symbols[i.0].kind, SymbolKind::Function(_)));
346 let Some(index) = symbols.next() else {
347 return Ok(None);
348 };
349 if let Some(other_index) = symbols.next() {
350 let symbol = &self.symbols[index.0];
351 let other = &self.symbols[other_index.0];
352 return MultipleSymbolsSnafu { address, name: symbol.name.clone(), other_name: other.name.clone() }.fail();
353 }
354 let symbol = &mut self.symbols[index.0];
355
356 Ok(Some(symbol))
357 }
358
359 pub fn get_function_containing(&self, addr: u32) -> Option<(SymFunction, &Symbol)> {
360 self.symbols_by_address
361 .range(0..=addr)
362 .rev()
363 .filter_map(|(_, indices)| {
364 let index = indices.first()?;
365 let symbol = &self.symbols[index.0];
366 if let SymbolKind::Function(func) = symbol.kind {
367 Some((func, symbol))
368 } else {
369 None
370 }
371 })
372 .take_while(|(func, sym)| func.contains(sym, addr))
373 .next()
374 }
375
376 pub fn functions(&self) -> impl Iterator<Item = (SymFunction, &'_ Symbol)> {
377 FunctionSymbolIterator {
378 symbols_by_address: self.symbols_by_address.values(),
379 indices: [].iter(),
380 symbols: &self.symbols,
381 }
382 }
383
384 pub fn clone_functions(&self) -> Vec<(SymFunction, Symbol)> {
385 self.functions().map(|(function, symbol)| (function, symbol.clone())).collect()
386 }
387
388 pub fn data_symbols(&self) -> impl Iterator<Item = (SymData, &'_ Symbol)> {
389 self.symbols.iter().filter_map(|symbol| {
390 if let SymbolKind::Data(sym_data) = symbol.kind {
391 Some((sym_data, symbol))
392 } else {
393 None
394 }
395 })
396 }
397
398 pub fn bss_symbols(&self) -> impl Iterator<Item = (SymBss, &'_ Symbol)> {
399 self.symbols.iter().filter_map(|symbol| {
400 if let SymbolKind::Bss(sym_bss) = symbol.kind {
401 Some((sym_bss, symbol))
402 } else {
403 None
404 }
405 })
406 }
407
408 pub fn label_name(addr: u32) -> String {
409 format!(".L_{addr:08x}")
410 }
411
412 pub fn add_label(&mut self, addr: u32, thumb: bool) -> Result<(SymbolIndex, &Symbol), SymbolMapError> {
413 let name = Self::label_name(addr);
414 self.add_if_new_address(Symbol::new_label(name, addr, thumb))
415 }
416
417 pub fn add_external_label(&mut self, addr: u32, thumb: bool) -> Result<(SymbolIndex, &Symbol), SymbolMapError> {
419 let name = Self::label_name(addr);
420 self.add_if_new_address(Symbol::new_external_label(name, addr, thumb))
421 }
422
423 pub fn get_label(&self, addr: u32) -> Result<Option<&Symbol>, SymbolMapError> {
424 Ok(self.by_address(addr)?.and_then(|(_, s)| (matches!(s.kind, SymbolKind::Label { .. })).then_some(s)))
425 }
426
427 pub fn add_pool_constant(&mut self, addr: u32) -> Result<(SymbolIndex, &Symbol), SymbolMapError> {
428 let name = Self::label_name(addr);
429 self.add_if_new_address(Symbol::new_pool_constant(name, addr))
430 }
431
432 pub fn get_pool_constant(&self, addr: u32) -> Result<Option<&Symbol>, SymbolMapError> {
433 Ok(self.by_address(addr)?.and_then(|(_, s)| (s.kind == SymbolKind::PoolConstant).then_some(s)))
434 }
435
436 pub fn get_jump_table(&self, addr: u32) -> Result<Option<(SymJumpTable, &Symbol)>, SymbolMapError> {
437 Ok(self.by_address(addr)?.and_then(|(_, s)| match s.kind {
438 SymbolKind::JumpTable(jump_table) => Some((jump_table, s)),
439 _ => None,
440 }))
441 }
442
443 fn make_unambiguous(&mut self, addr: u32) -> Result<(), SymbolMapError> {
444 if let Some(index) = self
445 .by_address(addr)?
446 .filter(|(_, symbol)| matches!(symbol.kind, SymbolKind::Data(_) | SymbolKind::Bss(_)))
447 .map(|(index, _)| index)
448 {
449 self.symbols[index.0].ambiguous = false;
450 }
451 Ok(())
452 }
453
454 pub fn add_function(&mut self, function: &Function) -> (SymbolIndex, &Symbol) {
455 self.add(Symbol::from_function(function))
456 }
457
458 pub fn add_unknown_function(&mut self, name: String, addr: u32, thumb: bool) -> (SymbolIndex, &Symbol) {
459 self.add(Symbol::new_unknown_function(name, addr & !1, thumb))
460 }
461
462 pub fn add_jump_table(&mut self, table: &JumpTable) -> Result<(SymbolIndex, &Symbol), SymbolMapError> {
463 let name = Self::label_name(table.address);
464 self.add_if_new_address(Symbol::new_jump_table(name, table.address, table.size, table.code))
465 }
466
467 pub fn add_data(
468 &mut self,
469 name: Option<String>,
470 addr: u32,
471 data: SymData,
472 ) -> Result<(SymbolIndex, &Symbol), SymbolMapError> {
473 let name = name.unwrap_or_else(|| Self::label_name(addr));
474 self.make_unambiguous(addr)?;
475 self.add_if_new_address(Symbol::new_data(name, addr, data, false))
476 }
477
478 pub fn add_ambiguous_data(
479 &mut self,
480 name: Option<String>,
481 addr: u32,
482 data: SymData,
483 ) -> Result<(SymbolIndex, &Symbol), SymbolMapError> {
484 let name = name.unwrap_or_else(|| Self::label_name(addr));
485 self.add_if_new_address(Symbol::new_data(name, addr, data, true))
486 }
487
488 pub fn add_skip_data(
489 &mut self,
490 name: Option<String>,
491 addr: u32,
492 data: SymData,
493 ) -> Result<(SymbolIndex, &Symbol), SymbolMapError> {
494 let name = name.unwrap_or_else(|| Self::label_name(addr));
495 self.add_if_new_address(Symbol::new_skip_data(name, addr, data, true))
496 }
497
498 pub fn get_data(&self, addr: u32) -> Result<Option<(SymData, &Symbol)>, SymbolMapError> {
499 Ok(self.by_address(addr)?.and_then(|(_, s)| match s.kind {
500 SymbolKind::Data(data) => Some((data, s)),
501 _ => None,
502 }))
503 }
504
505 pub fn add_bss(
506 &mut self,
507 name: Option<String>,
508 addr: u32,
509 data: SymBss,
510 ) -> Result<(SymbolIndex, &Symbol), SymbolMapError> {
511 let name = name.unwrap_or_else(|| Self::label_name(addr));
512 self.make_unambiguous(addr)?;
513 self.add_if_new_address(Symbol::new_bss(name, addr, data, false))
514 }
515
516 pub fn add_ambiguous_bss(
517 &mut self,
518 name: Option<String>,
519 addr: u32,
520 data: SymBss,
521 ) -> Result<(SymbolIndex, &Symbol), SymbolMapError> {
522 let name = name.unwrap_or_else(|| Self::label_name(addr));
523 self.add_if_new_address(Symbol::new_bss(name, addr, data, true))
524 }
525
526 pub fn rename_by_address(&mut self, address: u32, new_name: &str) -> Result<bool, SymbolMapError> {
530 let symbol_indices =
531 self.symbols_by_address.get(&address).ok_or_else(|| NoSymbolToRenameSnafu { address, new_name }.build())?;
532 ensure!(symbol_indices.len() == 1, RenameMultipleSnafu { address, new_name });
533
534 let symbol_index = symbol_indices[0];
535 let name = &self.symbols[symbol_index.0].name;
536 if name == new_name {
537 return Ok(false);
538 }
539
540 match self.symbols_by_name.entry(name.clone()) {
541 hash_map::Entry::Occupied(mut entry) => {
542 let symbol_indices = entry.get_mut();
543 if symbol_indices.len() == 1 {
544 entry.remove();
545 } else {
546 let pos = symbol_indices.iter().position(|&i| i == symbol_index).unwrap();
548 symbol_indices.remove(pos);
549 }
550 }
551 hash_map::Entry::Vacant(_) => {
552 panic!("No symbol name entry found for '{name}' when trying to rename to '{new_name}'");
553 }
554 }
555
556 match self.symbols_by_name.entry(new_name.to_string()) {
557 hash_map::Entry::Occupied(mut entry) => {
558 entry.get_mut().push(symbol_index);
559 }
560 hash_map::Entry::Vacant(entry) => {
561 entry.insert(vec![symbol_index]);
562 }
563 }
564
565 self.symbols[symbol_index.0].name = new_name.to_string();
566
567 Ok(true)
568 }
569}
570
571pub struct SymbolIterator<'a> {
572 symbols_by_address: btree_map::Range<'a, u32, Vec<SymbolIndex>>,
573 indices: slice::Iter<'a, SymbolIndex>,
574 symbols: &'a [Symbol],
575}
576
577impl<'a> Iterator for SymbolIterator<'a> {
578 type Item = &'a Symbol;
579
580 fn next(&mut self) -> Option<Self::Item> {
581 if let Some(&index) = self.indices.next() {
582 Some(&self.symbols[index.0])
583 } else if let Some((_, indices)) = self.symbols_by_address.next() {
584 self.indices = indices.iter();
585 self.next()
586 } else {
587 None
588 }
589 }
590}
591
592impl<'a> DoubleEndedIterator for SymbolIterator<'a> {
593 fn next_back(&mut self) -> Option<Self::Item> {
594 if let Some(&index) = self.indices.next_back() {
595 Some(&self.symbols[index.0])
596 } else if let Some((_, indices)) = self.symbols_by_address.next_back() {
597 self.indices = indices.iter();
598 self.next_back()
599 } else {
600 None
601 }
602 }
603}
604
605pub struct FunctionSymbolIterator<'a, I: Iterator<Item = &'a Vec<SymbolIndex>>> {
606 symbols_by_address: I, indices: slice::Iter<'a, SymbolIndex>,
608 symbols: &'a [Symbol],
609}
610
611impl<'a, I: Iterator<Item = &'a Vec<SymbolIndex>>> FunctionSymbolIterator<'a, I> {
612 fn next_function(&mut self) -> Option<(SymFunction, &'a Symbol)> {
613 for &index in self.indices.by_ref() {
614 let symbol = &self.symbols[index.0];
615 if let SymbolKind::Function(function) = symbol.kind {
616 return Some((function, symbol));
617 }
618 }
619 None
620 }
621}
622
623impl<'a, I: Iterator<Item = &'a Vec<SymbolIndex>>> Iterator for FunctionSymbolIterator<'a, I> {
624 type Item = (SymFunction, &'a Symbol);
625
626 fn next(&mut self) -> Option<Self::Item> {
627 if let Some(function) = self.next_function() {
628 return Some(function);
629 }
630 while let Some(indices) = self.symbols_by_address.next() {
631 self.indices = indices.iter();
632 if let Some(function) = self.next_function() {
633 return Some(function);
634 }
635 }
636 None
637 }
638}
639
640#[derive(Clone)]
641pub struct Symbol {
642 pub name: String,
643 pub kind: SymbolKind,
644 pub addr: u32,
645 pub ambiguous: bool,
647 pub local: bool,
649 pub skip: bool,
652}
653
654#[derive(Debug, Snafu)]
655pub enum SymbolParseError {
656 #[snafu(transparent)]
657 SymbolKindParse { source: SymbolKindParseError },
658 #[snafu(display("{context}: failed to parse address '{value}': {error}\n{backtrace}"))]
659 ParseAddress { context: ParseContext, value: String, error: ParseIntError, backtrace: Backtrace },
660 #[snafu(display("{context}: expected symbol attribute 'kind' or 'addr' but got '{key}':\n{backtrace}"))]
661 UnknownAttribute { context: ParseContext, key: String, backtrace: Backtrace },
662 #[snafu(display("{context}: missing '{attribute}' attribute:\n{backtrace}"))]
663 MissingAttribute { context: ParseContext, attribute: String, backtrace: Backtrace },
664}
665
666impl Symbol {
667 fn parse(line: &str, context: &ParseContext) -> Result<Option<Self>, SymbolParseError> {
668 let mut words = line.split_whitespace();
669 let Some(name) = words.next() else { return Ok(None) };
670
671 let mut kind = None;
672 let mut addr = None;
673 let mut ambiguous = false;
674 let mut local = false;
675 for (key, value) in iter_attributes(words) {
676 match key {
677 "kind" => kind = Some(SymbolKind::parse(value, context)?),
678 "addr" => addr = Some(parse_u32(value).map_err(|error| ParseAddressSnafu { context, value, error }.build())?),
679 "ambiguous" => ambiguous = true,
680 "local" => local = true,
681 _ => return UnknownAttributeSnafu { context, key }.fail(),
682 }
683 }
684
685 let name = name.to_string();
686 let kind = kind.ok_or_else(|| MissingAttributeSnafu { context, attribute: "kind" }.build())?;
687 let addr = addr.ok_or_else(|| MissingAttributeSnafu { context, attribute: "addr" }.build())?;
688
689 Ok(Some(Symbol { name, kind, addr, ambiguous, local, skip: false }))
690 }
691
692 fn should_write(&self) -> bool {
693 !self.skip && self.kind.should_write()
694 }
695
696 pub fn from_function(function: &Function) -> Self {
697 Self {
698 name: function.name().to_string(),
699 kind: SymbolKind::Function(SymFunction {
700 mode: InstructionMode::from_thumb(function.is_thumb()),
701 size: function.size(),
702 unknown: false,
703 }),
704 addr: function.first_instruction_address() & !1,
705 ambiguous: false,
706 local: false,
707 skip: false,
708 }
709 }
710
711 pub fn new_unknown_function(name: String, addr: u32, thumb: bool) -> Self {
712 Self {
713 name,
714 kind: SymbolKind::Function(SymFunction { mode: InstructionMode::from_thumb(thumb), size: 0, unknown: true }),
715 addr,
716 ambiguous: false,
717 local: false,
718 skip: false,
719 }
720 }
721
722 pub fn new_label(name: String, addr: u32, thumb: bool) -> Self {
723 Self {
724 name,
725 kind: SymbolKind::Label(SymLabel { external: false, mode: InstructionMode::from_thumb(thumb) }),
726 addr,
727 ambiguous: false,
728 local: true,
729 skip: false,
730 }
731 }
732
733 pub fn new_external_label(name: String, addr: u32, thumb: bool) -> Self {
734 Self {
735 name,
736 kind: SymbolKind::Label(SymLabel { external: true, mode: InstructionMode::from_thumb(thumb) }),
737 addr,
738 ambiguous: false,
739 local: false,
740 skip: false,
741 }
742 }
743
744 pub fn new_pool_constant(name: String, addr: u32) -> Self {
745 Self { name, kind: SymbolKind::PoolConstant, addr, ambiguous: false, local: true, skip: false }
746 }
747
748 pub fn new_jump_table(name: String, addr: u32, size: u32, code: bool) -> Self {
749 Self {
750 name,
751 kind: SymbolKind::JumpTable(SymJumpTable { size, code }),
752 addr,
753 ambiguous: false,
754 local: true,
755 skip: false,
756 }
757 }
758
759 pub fn new_data(name: String, addr: u32, data: SymData, ambiguous: bool) -> Symbol {
760 Self { name, kind: SymbolKind::Data(data), addr, ambiguous, local: false, skip: false }
761 }
762
763 pub fn new_skip_data(name: String, addr: u32, data: SymData, ambiguous: bool) -> Symbol {
764 Self { name, kind: SymbolKind::Data(data), addr, ambiguous, local: false, skip: true }
765 }
766
767 pub fn new_bss(name: String, addr: u32, data: SymBss, ambiguous: bool) -> Symbol {
768 Self { name, kind: SymbolKind::Bss(data), addr, ambiguous, local: false, skip: false }
769 }
770
771 pub fn size(&self, max_address: u32) -> u32 {
772 self.kind.size(max_address - self.addr)
773 }
774
775 pub fn is_external(&self) -> bool {
776 match self.kind {
777 SymbolKind::Label(SymLabel { external, .. }) => external,
778 SymbolKind::PoolConstant => false,
779 SymbolKind::JumpTable(_) => false,
780 _ => true,
781 }
782 }
783}
784
785impl Display for Symbol {
786 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
787 write!(f, "{} kind:{} addr:{:#010x}", self.name, self.kind, self.addr)?;
788 if self.local {
789 write!(f, " local")?;
790 }
791 if self.ambiguous {
792 write!(f, " ambiguous")?;
793 }
794 Ok(())
795 }
796}
797
798#[derive(Clone, Copy, PartialEq, Eq, Debug)]
799pub enum SymbolKind {
800 Undefined,
801 Function(SymFunction),
802 Label(SymLabel),
803 PoolConstant,
804 JumpTable(SymJumpTable),
805 Data(SymData),
806 Bss(SymBss),
807}
808
809#[derive(Debug, Snafu)]
810pub enum SymbolKindParseError {
811 #[snafu(transparent)]
812 SymFunctionParse { source: SymFunctionParseError },
813 #[snafu(transparent)]
814 SymDataParse { source: SymDataParseError },
815 #[snafu(transparent)]
816 SymBssParse { source: SymBssParseError },
817 #[snafu(transparent)]
818 SymLabelParse { source: SymLabelParseError },
819 #[snafu(display("{context}: unknown symbol kind '{kind}', must be one of: function, data, bss, label:\n{backtrace}"))]
820 UnknownKind { context: ParseContext, kind: String, backtrace: Backtrace },
821}
822
823impl SymbolKind {
824 fn parse(text: &str, context: &ParseContext) -> Result<Self, SymbolKindParseError> {
825 let (kind, options) = text.split_once('(').unwrap_or((text, ""));
826 let options = options.strip_suffix(')').unwrap_or(options);
827
828 match kind {
829 "function" => Ok(Self::Function(SymFunction::parse(options, context)?)),
830 "data" => Ok(Self::Data(SymData::parse(options, context)?)),
831 "bss" => Ok(Self::Bss(SymBss::parse(options, context)?)),
832 "label" => Ok(Self::Label(SymLabel::parse(options, context)?)),
833 _ => UnknownKindSnafu { context, kind }.fail(),
834 }
835 }
836
837 fn should_write(&self) -> bool {
838 match self {
839 SymbolKind::Undefined => false,
840 SymbolKind::Function(_) => true,
841 SymbolKind::Label(label) => label.external,
842 SymbolKind::PoolConstant => false,
843 SymbolKind::JumpTable(_) => false,
844 SymbolKind::Data(_) => true,
845 SymbolKind::Bss(_) => true,
846 }
847 }
848
849 pub fn size(&self, max_size: u32) -> u32 {
850 match self {
851 SymbolKind::Undefined => 0,
852 SymbolKind::Function(function) => function.size,
853 SymbolKind::Label(_) => 0,
854 SymbolKind::PoolConstant => 0, SymbolKind::JumpTable(_) => 0,
856 SymbolKind::Data(data) => data.size().unwrap_or(max_size),
857 SymbolKind::Bss(bss) => bss.size.unwrap_or(max_size),
858 }
859 }
860}
861
862impl Display for SymbolKind {
863 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
864 match self {
865 SymbolKind::Undefined => {}
866 SymbolKind::Function(function) => write!(f, "function({function})")?,
867 SymbolKind::Data(data) => write!(f, "data({data})")?,
868 SymbolKind::Bss(bss) => write!(f, "bss{bss}")?,
869 SymbolKind::Label(label) => write!(f, "label({label})")?,
870 SymbolKind::PoolConstant => {}
871 SymbolKind::JumpTable(_) => {}
872 }
873 Ok(())
874 }
875}
876
877#[derive(Clone, Copy, PartialEq, Eq, Debug)]
878pub struct SymFunction {
879 pub mode: InstructionMode,
880 pub size: u32,
881 pub unknown: bool,
884}
885
886#[derive(Debug, Snafu)]
887pub enum SymFunctionParseError {
888 #[snafu(display("{context}: failed to parse size '{value}': {error}\n{backtrace}"))]
889 ParseFunctionSize { context: ParseContext, value: String, error: ParseIntError, backtrace: Backtrace },
890 #[snafu(display(
891 "{context}: unknown function attribute '{key}', must be one of: size, unknown, arm, thumb:\n{backtrace}"
892 ))]
893 UnknownFunctionAttribute { context: ParseContext, key: String, backtrace: Backtrace },
894 #[snafu(transparent)]
895 InstructionModeParse { source: InstructionModeParseError },
896 #[snafu(display("{context}: function must have an instruction mode: arm or thumb"))]
897 MissingInstructionMode { context: ParseContext, backtrace: Backtrace },
898 #[snafu(display("{context}: missing '{attribute}' attribute:\n{backtrace}"))]
899 MissingFunctionAttribute { context: ParseContext, attribute: String, backtrace: Backtrace },
900}
901
902impl SymFunction {
903 fn parse(options: &str, context: &ParseContext) -> Result<Self, SymFunctionParseError> {
904 let mut size = None;
905 let mut mode = None;
906 let mut unknown = false;
907 for option in options.split(',') {
908 if let Some((key, value)) = option.split_once('=') {
909 match key {
910 "size" => {
911 size =
912 Some(parse_u32(value).map_err(|error| ParseFunctionSizeSnafu { context, value, error }.build())?)
913 }
914 _ => return UnknownFunctionAttributeSnafu { context, key }.fail(),
915 }
916 } else {
917 match option {
918 "unknown" => unknown = true,
919 _ => mode = Some(InstructionMode::parse(option, context)?),
920 }
921 }
922 }
923
924 Ok(Self {
925 mode: mode.ok_or_else(|| MissingInstructionModeSnafu { context }.build())?,
926 size: size.ok_or_else(|| MissingFunctionAttributeSnafu { context, attribute: "size" }.build())?,
927 unknown,
928 })
929 }
930
931 fn contains(&self, sym: &Symbol, addr: u32) -> bool {
932 if !self.unknown {
933 let start = sym.addr;
934 let end = start + self.size;
935 addr >= start && addr < end
936 } else {
937 sym.addr == addr
939 }
940 }
941}
942
943impl Display for SymFunction {
944 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
945 write!(f, "{},size={:#x}", self.mode, self.size)?;
946 if self.unknown {
947 write!(f, ",unknown")?;
948 }
949 Ok(())
950 }
951}
952
953#[derive(Clone, Copy, PartialEq, Eq, Debug)]
954pub struct SymLabel {
955 pub external: bool,
959 pub mode: InstructionMode,
960}
961
962#[derive(Debug, Snafu)]
963pub enum SymLabelParseError {
964 #[snafu(transparent)]
965 InstructionModeParse { source: InstructionModeParseError },
966}
967
968impl SymLabel {
969 fn parse(options: &str, context: &ParseContext) -> Result<Self, SymLabelParseError> {
970 Ok(Self { external: true, mode: InstructionMode::parse(options, context)? })
971 }
972}
973
974impl Display for SymLabel {
975 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
976 write!(f, "{}", self.mode)
977 }
978}
979
980#[derive(Clone, Copy, PartialEq, Eq, Debug)]
981pub enum InstructionMode {
982 Arm,
983 Thumb,
984}
985
986#[derive(Debug, Snafu)]
987pub enum InstructionModeParseError {
988 #[snafu(display("{context}: expected instruction mode 'arm' or 'thumb' but got '{value}':\n{backtrace}"))]
989 UnknownInstructionMode { context: ParseContext, value: String, backtrace: Backtrace },
990}
991
992impl InstructionMode {
993 fn parse(value: &str, context: &ParseContext) -> Result<Self, InstructionModeParseError> {
994 match value {
995 "arm" => Ok(Self::Arm),
996 "thumb" => Ok(Self::Thumb),
997 _ => UnknownInstructionModeSnafu { context, value }.fail(),
998 }
999 }
1000
1001 pub fn from_thumb(thumb: bool) -> Self {
1002 if thumb { Self::Thumb } else { Self::Arm }
1003 }
1004
1005 pub fn into_thumb(self) -> Option<bool> {
1006 match self {
1007 Self::Arm => Some(false),
1008 Self::Thumb => Some(true),
1009 }
1010 }
1011}
1012
1013impl Display for InstructionMode {
1014 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1015 match self {
1016 Self::Arm => write!(f, "arm"),
1017 Self::Thumb => write!(f, "thumb"),
1018 }
1019 }
1020}
1021
1022#[derive(Clone, Copy, PartialEq, Eq, Debug)]
1023pub struct SymJumpTable {
1024 pub size: u32,
1025 pub code: bool,
1026}
1027
1028#[derive(Clone, Copy, PartialEq, Eq, Debug)]
1029pub enum SymData {
1030 Any,
1031 Byte { count: Option<u32> },
1032 Short { count: Option<u32> },
1033 Word { count: Option<u32> },
1034}
1035
1036#[derive(Debug, Snafu)]
1037pub enum SymDataParseError {
1038 #[snafu(display("{context}: expected data kind 'any', 'byte', 'short' or 'word' but got nothing:\n{backtrace}"))]
1039 EmptyData { context: ParseContext, backtrace: Backtrace },
1040 #[snafu(display("{context}: failed to parse count '{value}': {error}\n{backtrace}"))]
1041 ParseCount { context: ParseContext, value: String, error: ParseIntError, backtrace: Backtrace },
1042 #[snafu(display("{context}: unexpected characters after ']':\n{backtrace}"))]
1043 CharacterAfterArray { context: ParseContext, backtrace: Backtrace },
1044 #[snafu(display("{context}: data type 'any' cannot be an array:\n{backtrace}"))]
1045 ArrayOfAny { context: ParseContext, backtrace: Backtrace },
1046 #[snafu(display("{context}: expected data kind 'any', 'byte', 'short' or 'word' but got '{kind}':\n{backtrace}"))]
1047 UnknownDataKind { context: ParseContext, kind: String, backtrace: Backtrace },
1048}
1049
1050impl SymData {
1051 fn parse(kind: &str, context: &ParseContext) -> Result<Self, SymDataParseError> {
1052 if kind.is_empty() {
1053 return EmptyDataSnafu { context }.fail();
1054 }
1055
1056 let (kind, rest) = kind.split_once('[').unwrap_or((kind, ""));
1057 let (count, rest) = rest
1058 .split_once(']')
1059 .map(|(count, rest)| {
1060 let count = if count.is_empty() {
1061 Ok(None)
1062 } else {
1063 parse_u32(count).map(Some).map_err(|error| ParseCountSnafu { context, value: count, error }.build())
1064 };
1065 (count, rest)
1066 })
1067 .unwrap_or((Ok(Some(1)), rest));
1068 let count = count?;
1069
1070 if !rest.is_empty() {
1071 return CharacterAfterArraySnafu { context }.fail();
1072 }
1073
1074 match kind {
1075 "any" => {
1076 if count != Some(1) {
1077 ArrayOfAnySnafu { context }.fail()
1078 } else {
1079 Ok(Self::Any)
1080 }
1081 }
1082 "short" => Ok(Self::Short { count }),
1083 "byte" => Ok(Self::Byte { count }),
1084 "word" => Ok(Self::Word { count }),
1085 kind => UnknownDataKindSnafu { context, kind }.fail(),
1086 }
1087 }
1088
1089 pub fn count(self) -> Option<u32> {
1090 match self {
1091 Self::Any => None,
1092 Self::Byte { count } => count,
1093 Self::Short { count } => count,
1094 Self::Word { count } => count,
1095 }
1096 }
1097
1098 pub fn element_size(self) -> u32 {
1099 match self {
1100 Self::Any => 1,
1101 Self::Byte { .. } => 1,
1102 Self::Short { .. } => 2,
1103 Self::Word { .. } => 4,
1104 }
1105 }
1106
1107 pub fn size(&self) -> Option<u32> {
1108 self.count().map(|count| self.element_size() * count)
1109 }
1110}
1111
1112impl Display for SymData {
1113 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1114 match self {
1115 Self::Any => write!(f, "any"),
1116 Self::Byte { count: Some(1) } => write!(f, "byte"),
1117 Self::Short { count: Some(1) } => write!(f, "short"),
1118 Self::Word { count: Some(1) } => write!(f, "word"),
1119 Self::Byte { count: Some(count) } => write!(f, "byte[{count}]"),
1120 Self::Short { count: Some(count) } => write!(f, "short[{count}]"),
1121 Self::Word { count: Some(count) } => write!(f, "word[{count}]"),
1122 Self::Byte { count: None } => write!(f, "byte[]"),
1123 Self::Short { count: None } => write!(f, "short[]"),
1124 Self::Word { count: None } => write!(f, "word[]"),
1125 }
1126 }
1127}
1128
1129#[derive(Clone, Copy, PartialEq, Eq, Debug)]
1130pub struct SymBss {
1131 pub size: Option<u32>,
1132}
1133
1134#[derive(Debug, Snafu)]
1135pub enum SymBssParseError {
1136 #[snafu(display("{context}: failed to parse size '{value}': {error}\n{backtrace}"))]
1137 ParseBssSize { context: ParseContext, value: String, error: ParseIntError, backtrace: Backtrace },
1138 #[snafu(display("{context}: unknown attribute '{key}', must be one of: size:\n{backtrace}'"))]
1139 UnknownBssAttribute { context: ParseContext, key: String, backtrace: Backtrace },
1140}
1141
1142impl SymBss {
1143 fn parse(options: &str, context: &ParseContext) -> Result<Self, SymBssParseError> {
1144 let mut size = None;
1145 if !options.trim().is_empty() {
1146 for option in options.split(',') {
1147 if let Some((key, value)) = option.split_once('=') {
1148 match key {
1149 "size" => {
1150 size = Some(parse_u32(value).map_err(|error| ParseBssSizeSnafu { context, value, error }.build())?)
1151 }
1152 _ => return UnknownBssAttributeSnafu { context, key }.fail(),
1153 }
1154 } else {
1155 return UnknownBssAttributeSnafu { context, key: option }.fail();
1156 }
1157 }
1158 }
1159 Ok(Self { size })
1160 }
1161}
1162
1163impl Display for SymBss {
1164 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1165 if let Some(size) = self.size {
1166 write!(f, "(size={size:#x})")?;
1167 }
1168 Ok(())
1169 }
1170}