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 get_data(&self, addr: u32) -> Result<Option<(SymData, &Symbol)>, SymbolMapError> {
489 Ok(self.by_address(addr)?.and_then(|(_, s)| match s.kind {
490 SymbolKind::Data(data) => Some((data, s)),
491 _ => None,
492 }))
493 }
494
495 pub fn add_bss(
496 &mut self,
497 name: Option<String>,
498 addr: u32,
499 data: SymBss,
500 ) -> Result<(SymbolIndex, &Symbol), SymbolMapError> {
501 let name = name.unwrap_or_else(|| Self::label_name(addr));
502 self.make_unambiguous(addr)?;
503 self.add_if_new_address(Symbol::new_bss(name, addr, data, false))
504 }
505
506 pub fn add_ambiguous_bss(
507 &mut self,
508 name: Option<String>,
509 addr: u32,
510 data: SymBss,
511 ) -> Result<(SymbolIndex, &Symbol), SymbolMapError> {
512 let name = name.unwrap_or_else(|| Self::label_name(addr));
513 self.add_if_new_address(Symbol::new_bss(name, addr, data, true))
514 }
515
516 pub fn rename_by_address(&mut self, address: u32, new_name: &str) -> Result<bool, SymbolMapError> {
520 let symbol_indices =
521 self.symbols_by_address.get(&address).ok_or_else(|| NoSymbolToRenameSnafu { address, new_name }.build())?;
522 ensure!(symbol_indices.len() == 1, RenameMultipleSnafu { address, new_name });
523
524 let symbol_index = symbol_indices[0];
525 let name = &self.symbols[symbol_index.0].name;
526 if name == new_name {
527 return Ok(false);
528 }
529
530 match self.symbols_by_name.entry(name.clone()) {
531 hash_map::Entry::Occupied(mut entry) => {
532 let symbol_indices = entry.get_mut();
533 if symbol_indices.len() == 1 {
534 entry.remove();
535 } else {
536 let pos = symbol_indices.iter().position(|&i| i == symbol_index).unwrap();
538 symbol_indices.remove(pos);
539 }
540 }
541 hash_map::Entry::Vacant(_) => {
542 panic!("No symbol name entry found for '{name}' when trying to rename to '{new_name}'");
543 }
544 }
545
546 match self.symbols_by_name.entry(new_name.to_string()) {
547 hash_map::Entry::Occupied(mut entry) => {
548 entry.get_mut().push(symbol_index);
549 }
550 hash_map::Entry::Vacant(entry) => {
551 entry.insert(vec![symbol_index]);
552 }
553 }
554
555 self.symbols[symbol_index.0].name = new_name.to_string();
556
557 Ok(true)
558 }
559}
560
561pub struct SymbolIterator<'a> {
562 symbols_by_address: btree_map::Range<'a, u32, Vec<SymbolIndex>>,
563 indices: slice::Iter<'a, SymbolIndex>,
564 symbols: &'a [Symbol],
565}
566
567impl<'a> Iterator for SymbolIterator<'a> {
568 type Item = &'a Symbol;
569
570 fn next(&mut self) -> Option<Self::Item> {
571 if let Some(&index) = self.indices.next() {
572 Some(&self.symbols[index.0])
573 } else if let Some((_, indices)) = self.symbols_by_address.next() {
574 self.indices = indices.iter();
575 self.next()
576 } else {
577 None
578 }
579 }
580}
581
582impl<'a> DoubleEndedIterator for SymbolIterator<'a> {
583 fn next_back(&mut self) -> Option<Self::Item> {
584 if let Some(&index) = self.indices.next_back() {
585 Some(&self.symbols[index.0])
586 } else if let Some((_, indices)) = self.symbols_by_address.next_back() {
587 self.indices = indices.iter();
588 self.next_back()
589 } else {
590 None
591 }
592 }
593}
594
595pub struct FunctionSymbolIterator<'a, I: Iterator<Item = &'a Vec<SymbolIndex>>> {
596 symbols_by_address: I, indices: slice::Iter<'a, SymbolIndex>,
598 symbols: &'a [Symbol],
599}
600
601impl<'a, I: Iterator<Item = &'a Vec<SymbolIndex>>> FunctionSymbolIterator<'a, I> {
602 fn next_function(&mut self) -> Option<(SymFunction, &'a Symbol)> {
603 for &index in self.indices.by_ref() {
604 let symbol = &self.symbols[index.0];
605 if let SymbolKind::Function(function) = symbol.kind {
606 return Some((function, symbol));
607 }
608 }
609 None
610 }
611}
612
613impl<'a, I: Iterator<Item = &'a Vec<SymbolIndex>>> Iterator for FunctionSymbolIterator<'a, I> {
614 type Item = (SymFunction, &'a Symbol);
615
616 fn next(&mut self) -> Option<Self::Item> {
617 if let Some(function) = self.next_function() {
618 return Some(function);
619 }
620 while let Some(indices) = self.symbols_by_address.next() {
621 self.indices = indices.iter();
622 if let Some(function) = self.next_function() {
623 return Some(function);
624 }
625 }
626 None
627 }
628}
629
630#[derive(Clone)]
631pub struct Symbol {
632 pub name: String,
633 pub kind: SymbolKind,
634 pub addr: u32,
635 pub ambiguous: bool,
637 pub local: bool,
639}
640
641#[derive(Debug, Snafu)]
642pub enum SymbolParseError {
643 #[snafu(transparent)]
644 SymbolKindParse { source: SymbolKindParseError },
645 #[snafu(display("{context}: failed to parse address '{value}': {error}\n{backtrace}"))]
646 ParseAddress { context: ParseContext, value: String, error: ParseIntError, backtrace: Backtrace },
647 #[snafu(display("{context}: expected symbol attribute 'kind' or 'addr' but got '{key}':\n{backtrace}"))]
648 UnknownAttribute { context: ParseContext, key: String, backtrace: Backtrace },
649 #[snafu(display("{context}: missing '{attribute}' attribute:\n{backtrace}"))]
650 MissingAttribute { context: ParseContext, attribute: String, backtrace: Backtrace },
651}
652
653impl Symbol {
654 fn parse(line: &str, context: &ParseContext) -> Result<Option<Self>, SymbolParseError> {
655 let mut words = line.split_whitespace();
656 let Some(name) = words.next() else { return Ok(None) };
657
658 let mut kind = None;
659 let mut addr = None;
660 let mut ambiguous = false;
661 let mut local = false;
662 for (key, value) in iter_attributes(words) {
663 match key {
664 "kind" => kind = Some(SymbolKind::parse(value, context)?),
665 "addr" => addr = Some(parse_u32(value).map_err(|error| ParseAddressSnafu { context, value, error }.build())?),
666 "ambiguous" => ambiguous = true,
667 "local" => local = true,
668 _ => return UnknownAttributeSnafu { context, key }.fail(),
669 }
670 }
671
672 let name = name.to_string();
673 let kind = kind.ok_or_else(|| MissingAttributeSnafu { context, attribute: "kind" }.build())?;
674 let addr = addr.ok_or_else(|| MissingAttributeSnafu { context, attribute: "addr" }.build())?;
675
676 Ok(Some(Symbol { name, kind, addr, ambiguous, local }))
677 }
678
679 fn should_write(&self) -> bool {
680 self.kind.should_write()
681 }
682
683 pub fn from_function(function: &Function) -> Self {
684 Self {
685 name: function.name().to_string(),
686 kind: SymbolKind::Function(SymFunction {
687 mode: InstructionMode::from_thumb(function.is_thumb()),
688 size: function.size(),
689 unknown: false,
690 }),
691 addr: function.first_instruction_address() & !1,
692 ambiguous: false,
693 local: false,
694 }
695 }
696
697 pub fn new_unknown_function(name: String, addr: u32, thumb: bool) -> Self {
698 Self {
699 name,
700 kind: SymbolKind::Function(SymFunction { mode: InstructionMode::from_thumb(thumb), size: 0, unknown: true }),
701 addr,
702 ambiguous: false,
703 local: false,
704 }
705 }
706
707 pub fn new_label(name: String, addr: u32, thumb: bool) -> Self {
708 Self {
709 name,
710 kind: SymbolKind::Label(SymLabel { external: false, mode: InstructionMode::from_thumb(thumb) }),
711 addr,
712 ambiguous: false,
713 local: true,
714 }
715 }
716
717 pub fn new_external_label(name: String, addr: u32, thumb: bool) -> Self {
718 Self {
719 name,
720 kind: SymbolKind::Label(SymLabel { external: true, mode: InstructionMode::from_thumb(thumb) }),
721 addr,
722 ambiguous: false,
723 local: false,
724 }
725 }
726
727 pub fn new_pool_constant(name: String, addr: u32) -> Self {
728 Self { name, kind: SymbolKind::PoolConstant, addr, ambiguous: false, local: true }
729 }
730
731 pub fn new_jump_table(name: String, addr: u32, size: u32, code: bool) -> Self {
732 Self { name, kind: SymbolKind::JumpTable(SymJumpTable { size, code }), addr, ambiguous: false, local: true }
733 }
734
735 pub fn new_data(name: String, addr: u32, data: SymData, ambiguous: bool) -> Symbol {
736 Self { name, kind: SymbolKind::Data(data), addr, ambiguous, local: false }
737 }
738
739 pub fn new_bss(name: String, addr: u32, data: SymBss, ambiguous: bool) -> Symbol {
740 Self { name, kind: SymbolKind::Bss(data), addr, ambiguous, local: false }
741 }
742
743 pub fn size(&self, max_address: u32) -> u32 {
744 self.kind.size(max_address - self.addr)
745 }
746
747 pub fn is_external(&self) -> bool {
748 match self.kind {
749 SymbolKind::Label(SymLabel { external, .. }) => external,
750 SymbolKind::PoolConstant => false,
751 SymbolKind::JumpTable(_) => false,
752 _ => true,
753 }
754 }
755}
756
757impl Display for Symbol {
758 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
759 write!(f, "{} kind:{} addr:{:#010x}", self.name, self.kind, self.addr)?;
760 if self.local {
761 write!(f, " local")?;
762 }
763 if self.ambiguous {
764 write!(f, " ambiguous")?;
765 }
766 Ok(())
767 }
768}
769
770#[derive(Clone, Copy, PartialEq, Eq, Debug)]
771pub enum SymbolKind {
772 Undefined,
773 Function(SymFunction),
774 Label(SymLabel),
775 PoolConstant,
776 JumpTable(SymJumpTable),
777 Data(SymData),
778 Bss(SymBss),
779}
780
781#[derive(Debug, Snafu)]
782pub enum SymbolKindParseError {
783 #[snafu(transparent)]
784 SymFunctionParse { source: SymFunctionParseError },
785 #[snafu(transparent)]
786 SymDataParse { source: SymDataParseError },
787 #[snafu(transparent)]
788 SymBssParse { source: SymBssParseError },
789 #[snafu(transparent)]
790 SymLabelParse { source: SymLabelParseError },
791 #[snafu(display("{context}: unknown symbol kind '{kind}', must be one of: function, data, bss, label:\n{backtrace}"))]
792 UnknownKind { context: ParseContext, kind: String, backtrace: Backtrace },
793}
794
795impl SymbolKind {
796 fn parse(text: &str, context: &ParseContext) -> Result<Self, SymbolKindParseError> {
797 let (kind, options) = text.split_once('(').unwrap_or((text, ""));
798 let options = options.strip_suffix(')').unwrap_or(options);
799
800 match kind {
801 "function" => Ok(Self::Function(SymFunction::parse(options, context)?)),
802 "data" => Ok(Self::Data(SymData::parse(options, context)?)),
803 "bss" => Ok(Self::Bss(SymBss::parse(options, context)?)),
804 "label" => Ok(Self::Label(SymLabel::parse(options, context)?)),
805 _ => UnknownKindSnafu { context, kind }.fail(),
806 }
807 }
808
809 fn should_write(&self) -> bool {
810 match self {
811 SymbolKind::Undefined => false,
812 SymbolKind::Function(_) => true,
813 SymbolKind::Label(label) => label.external,
814 SymbolKind::PoolConstant => false,
815 SymbolKind::JumpTable(_) => false,
816 SymbolKind::Data(_) => true,
817 SymbolKind::Bss(_) => true,
818 }
819 }
820
821 pub fn size(&self, max_size: u32) -> u32 {
822 match self {
823 SymbolKind::Undefined => 0,
824 SymbolKind::Function(function) => function.size,
825 SymbolKind::Label(_) => 0,
826 SymbolKind::PoolConstant => 0, SymbolKind::JumpTable(_) => 0,
828 SymbolKind::Data(data) => data.size().unwrap_or(max_size),
829 SymbolKind::Bss(bss) => bss.size.unwrap_or(max_size),
830 }
831 }
832}
833
834impl Display for SymbolKind {
835 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
836 match self {
837 SymbolKind::Undefined => {}
838 SymbolKind::Function(function) => write!(f, "function({function})")?,
839 SymbolKind::Data(data) => write!(f, "data({data})")?,
840 SymbolKind::Bss(bss) => write!(f, "bss{bss}")?,
841 SymbolKind::Label(label) => write!(f, "label({label})")?,
842 SymbolKind::PoolConstant => {}
843 SymbolKind::JumpTable(_) => {}
844 }
845 Ok(())
846 }
847}
848
849#[derive(Clone, Copy, PartialEq, Eq, Debug)]
850pub struct SymFunction {
851 pub mode: InstructionMode,
852 pub size: u32,
853 pub unknown: bool,
856}
857
858#[derive(Debug, Snafu)]
859pub enum SymFunctionParseError {
860 #[snafu(display("{context}: failed to parse size '{value}': {error}\n{backtrace}"))]
861 ParseFunctionSize { context: ParseContext, value: String, error: ParseIntError, backtrace: Backtrace },
862 #[snafu(display(
863 "{context}: unknown function attribute '{key}', must be one of: size, unknown, arm, thumb:\n{backtrace}"
864 ))]
865 UnknownFunctionAttribute { context: ParseContext, key: String, backtrace: Backtrace },
866 #[snafu(transparent)]
867 InstructionModeParse { source: InstructionModeParseError },
868 #[snafu(display("{context}: function must have an instruction mode: arm or thumb"))]
869 MissingInstructionMode { context: ParseContext, backtrace: Backtrace },
870 #[snafu(display("{context}: missing '{attribute}' attribute:\n{backtrace}"))]
871 MissingFunctionAttribute { context: ParseContext, attribute: String, backtrace: Backtrace },
872}
873
874impl SymFunction {
875 fn parse(options: &str, context: &ParseContext) -> Result<Self, SymFunctionParseError> {
876 let mut size = None;
877 let mut mode = None;
878 let mut unknown = false;
879 for option in options.split(',') {
880 if let Some((key, value)) = option.split_once('=') {
881 match key {
882 "size" => {
883 size =
884 Some(parse_u32(value).map_err(|error| ParseFunctionSizeSnafu { context, value, error }.build())?)
885 }
886 _ => return UnknownFunctionAttributeSnafu { context, key }.fail(),
887 }
888 } else {
889 match option {
890 "unknown" => unknown = true,
891 _ => mode = Some(InstructionMode::parse(option, context)?),
892 }
893 }
894 }
895
896 Ok(Self {
897 mode: mode.ok_or_else(|| MissingInstructionModeSnafu { context }.build())?,
898 size: size.ok_or_else(|| MissingFunctionAttributeSnafu { context, attribute: "size" }.build())?,
899 unknown,
900 })
901 }
902
903 fn contains(&self, sym: &Symbol, addr: u32) -> bool {
904 if !self.unknown {
905 let start = sym.addr;
906 let end = start + self.size;
907 addr >= start && addr < end
908 } else {
909 sym.addr == addr
911 }
912 }
913}
914
915impl Display for SymFunction {
916 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
917 write!(f, "{},size={:#x}", self.mode, self.size)?;
918 if self.unknown {
919 write!(f, ",unknown")?;
920 }
921 Ok(())
922 }
923}
924
925#[derive(Clone, Copy, PartialEq, Eq, Debug)]
926pub struct SymLabel {
927 pub external: bool,
931 pub mode: InstructionMode,
932}
933
934#[derive(Debug, Snafu)]
935pub enum SymLabelParseError {
936 #[snafu(transparent)]
937 InstructionModeParse { source: InstructionModeParseError },
938}
939
940impl SymLabel {
941 fn parse(options: &str, context: &ParseContext) -> Result<Self, SymLabelParseError> {
942 Ok(Self { external: true, mode: InstructionMode::parse(options, context)? })
943 }
944}
945
946impl Display for SymLabel {
947 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
948 write!(f, "{}", self.mode)
949 }
950}
951
952#[derive(Clone, Copy, PartialEq, Eq, Debug)]
953pub enum InstructionMode {
954 Arm,
955 Thumb,
956}
957
958#[derive(Debug, Snafu)]
959pub enum InstructionModeParseError {
960 #[snafu(display("{context}: expected instruction mode 'arm' or 'thumb' but got '{value}':\n{backtrace}"))]
961 UnknownInstructionMode { context: ParseContext, value: String, backtrace: Backtrace },
962}
963
964impl InstructionMode {
965 fn parse(value: &str, context: &ParseContext) -> Result<Self, InstructionModeParseError> {
966 match value {
967 "arm" => Ok(Self::Arm),
968 "thumb" => Ok(Self::Thumb),
969 _ => UnknownInstructionModeSnafu { context, value }.fail(),
970 }
971 }
972
973 pub fn from_thumb(thumb: bool) -> Self {
974 if thumb { Self::Thumb } else { Self::Arm }
975 }
976
977 pub fn into_thumb(self) -> Option<bool> {
978 match self {
979 Self::Arm => Some(false),
980 Self::Thumb => Some(true),
981 }
982 }
983}
984
985impl Display for InstructionMode {
986 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
987 match self {
988 Self::Arm => write!(f, "arm"),
989 Self::Thumb => write!(f, "thumb"),
990 }
991 }
992}
993
994#[derive(Clone, Copy, PartialEq, Eq, Debug)]
995pub struct SymJumpTable {
996 pub size: u32,
997 pub code: bool,
998}
999
1000#[derive(Clone, Copy, PartialEq, Eq, Debug)]
1001pub enum SymData {
1002 Any,
1003 Byte { count: Option<u32> },
1004 Short { count: Option<u32> },
1005 Word { count: Option<u32> },
1006}
1007
1008#[derive(Debug, Snafu)]
1009pub enum SymDataParseError {
1010 #[snafu(display("{context}: expected data kind 'any', 'byte', 'short' or 'word' but got nothing:\n{backtrace}"))]
1011 EmptyData { context: ParseContext, backtrace: Backtrace },
1012 #[snafu(display("{context}: failed to parse count '{value}': {error}\n{backtrace}"))]
1013 ParseCount { context: ParseContext, value: String, error: ParseIntError, backtrace: Backtrace },
1014 #[snafu(display("{context}: unexpected characters after ']':\n{backtrace}"))]
1015 CharacterAfterArray { context: ParseContext, backtrace: Backtrace },
1016 #[snafu(display("{context}: data type 'any' cannot be an array:\n{backtrace}"))]
1017 ArrayOfAny { context: ParseContext, backtrace: Backtrace },
1018 #[snafu(display("{context}: expected data kind 'any', 'byte', 'short' or 'word' but got '{kind}':\n{backtrace}"))]
1019 UnknownDataKind { context: ParseContext, kind: String, backtrace: Backtrace },
1020}
1021
1022impl SymData {
1023 fn parse(kind: &str, context: &ParseContext) -> Result<Self, SymDataParseError> {
1024 if kind.is_empty() {
1025 return EmptyDataSnafu { context }.fail();
1026 }
1027
1028 let (kind, rest) = kind.split_once('[').unwrap_or((kind, ""));
1029 let (count, rest) = rest
1030 .split_once(']')
1031 .map(|(count, rest)| {
1032 let count = if count.is_empty() {
1033 Ok(None)
1034 } else {
1035 parse_u32(count).map(Some).map_err(|error| ParseCountSnafu { context, value: count, error }.build())
1036 };
1037 (count, rest)
1038 })
1039 .unwrap_or((Ok(Some(1)), rest));
1040 let count = count?;
1041
1042 if !rest.is_empty() {
1043 return CharacterAfterArraySnafu { context }.fail();
1044 }
1045
1046 match kind {
1047 "any" => {
1048 if count != Some(1) {
1049 ArrayOfAnySnafu { context }.fail()
1050 } else {
1051 Ok(Self::Any)
1052 }
1053 }
1054 "short" => Ok(Self::Short { count }),
1055 "byte" => Ok(Self::Byte { count }),
1056 "word" => Ok(Self::Word { count }),
1057 kind => UnknownDataKindSnafu { context, kind }.fail(),
1058 }
1059 }
1060
1061 pub fn count(self) -> Option<u32> {
1062 match self {
1063 Self::Any => None,
1064 Self::Byte { count } => count,
1065 Self::Short { count } => count,
1066 Self::Word { count } => count,
1067 }
1068 }
1069
1070 pub fn element_size(self) -> u32 {
1071 match self {
1072 Self::Any => 1,
1073 Self::Byte { .. } => 1,
1074 Self::Short { .. } => 2,
1075 Self::Word { .. } => 4,
1076 }
1077 }
1078
1079 pub fn size(&self) -> Option<u32> {
1080 self.count().map(|count| self.element_size() * count)
1081 }
1082}
1083
1084impl Display for SymData {
1085 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1086 match self {
1087 Self::Any => write!(f, "any"),
1088 Self::Byte { count: Some(1) } => write!(f, "byte"),
1089 Self::Short { count: Some(1) } => write!(f, "short"),
1090 Self::Word { count: Some(1) } => write!(f, "word"),
1091 Self::Byte { count: Some(count) } => write!(f, "byte[{count}]"),
1092 Self::Short { count: Some(count) } => write!(f, "short[{count}]"),
1093 Self::Word { count: Some(count) } => write!(f, "word[{count}]"),
1094 Self::Byte { count: None } => write!(f, "byte[]"),
1095 Self::Short { count: None } => write!(f, "short[]"),
1096 Self::Word { count: None } => write!(f, "word[]"),
1097 }
1098 }
1099}
1100
1101#[derive(Clone, Copy, PartialEq, Eq, Debug)]
1102pub struct SymBss {
1103 pub size: Option<u32>,
1104}
1105
1106#[derive(Debug, Snafu)]
1107pub enum SymBssParseError {
1108 #[snafu(display("{context}: failed to parse size '{value}': {error}\n{backtrace}"))]
1109 ParseBssSize { context: ParseContext, value: String, error: ParseIntError, backtrace: Backtrace },
1110 #[snafu(display("{context}: unknown attribute '{key}', must be one of: size:\n{backtrace}'"))]
1111 UnknownBssAttribute { context: ParseContext, key: String, backtrace: Backtrace },
1112}
1113
1114impl SymBss {
1115 fn parse(options: &str, context: &ParseContext) -> Result<Self, SymBssParseError> {
1116 let mut size = None;
1117 if !options.trim().is_empty() {
1118 for option in options.split(',') {
1119 if let Some((key, value)) = option.split_once('=') {
1120 match key {
1121 "size" => {
1122 size = Some(parse_u32(value).map_err(|error| ParseBssSizeSnafu { context, value, error }.build())?)
1123 }
1124 _ => return UnknownBssAttributeSnafu { context, key }.fail(),
1125 }
1126 } else {
1127 return UnknownBssAttributeSnafu { context, key: option }.fail();
1128 }
1129 }
1130 }
1131 Ok(Self { size })
1132 }
1133}
1134
1135impl Display for SymBss {
1136 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1137 if let Some(size) = self.size {
1138 write!(f, "(size={size:#x})")?;
1139 }
1140 Ok(())
1141 }
1142}