1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/* SPDX-FileCopyrightText: © 2024-2025 Decompollaborate */
/* SPDX-License-Identifier: MIT */
use core::fmt;
use crate::section_type::SectionType;
use super::{OwnerSegmentKind, SymbolMetadata, SymbolType};
// Avoid duplicating this function here and in label_metadata_name_display
fn should_quote_symbol(name: &str) -> bool {
name.contains('@')
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, PartialOrd)]
#[must_use]
pub struct SymbolMetadataNameDisplay<'sym> {
sym: &'sym SymbolMetadata,
}
impl<'sym> SymbolMetadataNameDisplay<'sym> {
pub fn new(sym: &'sym SymbolMetadata) -> Self {
Self { sym }
}
}
impl SymbolMetadataNameDisplay<'_> {
fn display_section_prefix(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.sym.sym_type() {
Some(SymbolType::Function)
| Some(SymbolType::Jumptable)
| Some(SymbolType::GccExceptTable) => {
// Functions and tables don't get a section prefix because most of the time they are in
// their respective sections.
// But if the section type is missing, then we haven't seen this symbol actually defined anywhere, so
// we tell the user by using this prefix.
match self.sym.section_type() {
Some(_) => Ok(()),
None => write!(f, "UNK_"),
}
}
_ => match self.sym.section_type() {
Some(SectionType::Text) => write!(f, "T_"),
Some(SectionType::Data) => write!(f, "D_"),
Some(SectionType::Rodata) => write!(f, "R_"),
Some(SectionType::Bss) => write!(f, "B_"),
Some(SectionType::GccExceptTable) => write!(f, "ET_"),
None => write!(f, "UNK_"),
},
}
}
fn display_type_prefix(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.sym.sym_type() {
Some(SymbolType::Function) => write!(f, "func_"),
Some(SymbolType::Jumptable) => write!(f, "jtbl_"),
Some(SymbolType::GccExceptTable) => write!(f, "ehtbl_"),
Some(SymbolType::Byte) => Ok(()),
Some(SymbolType::Short) => Ok(()),
Some(SymbolType::Word) => Ok(()),
Some(SymbolType::DWord) => Ok(()),
// GlobalConfig.AUTOGENERATED_NAMES_BASED_ON_DATA_TYPE
Some(SymbolType::Float32) => {
if self.sym.symbol_name_generation_settings().use_type_prefix() {
write!(f, "FLT_")
} else {
Ok(())
}
}
Some(SymbolType::Float64) => {
if self.sym.symbol_name_generation_settings().use_type_prefix() {
write!(f, "DBL_")
} else {
Ok(())
}
}
Some(SymbolType::CString) => {
if self.sym.symbol_name_generation_settings().use_type_prefix() {
write!(f, "STR_")
} else {
Ok(())
}
}
Some(SymbolType::VirtualTable) => {
if self.sym.symbol_name_generation_settings().use_type_prefix() {
write!(f, "VTBL_")
} else {
Ok(())
}
}
Some(SymbolType::UserCustom) => Ok(()),
None => Ok(()),
}
}
fn display_suffix(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let OwnerSegmentKind::Overlay(name) = self.sym.owner_segment_kind() {
write!(f, "_{name}")?;
}
if let Some(custom_suffix) = self.sym.symbol_name_generation_settings().custom_suffix() {
write!(f, "{custom_suffix}")?;
}
Ok(())
}
fn display_unique_identifier(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
/*
if GlobalConfig.SEQUENTIAL_LABEL_NAMES and self.parentFunction is not None:
if symType in {SymbolSpecialType.branchlabel, SymbolSpecialType.jumptablelabel}:
index = self.parentFunction.branchLabels.index(self.vram)
if index is not None:
return f"{self.parentFunction.getName()}_{index + 1}"
elif symType == SymbolSpecialType.jumptable:
index = self.parentFunction.jumpTables.index(self.vram)
if index is not None:
return f"{self.parentFunction.getName()}_{index + 1}"
if GlobalConfig.AUTOGENERATED_NAMES_BASED_ON_FILE_NAME:
if self.parentFileName is not None and self.inFileOffset is not None and symType != SymbolSpecialType.function:
sectionName = self.sectionType.toStr().replace(".", "_")
return f"{self.parentFileName}{sectionName}_{self.inFileOffset:06X}"
*/
write!(f, "{}", self.sym.vram())?;
self.display_suffix(f)
}
pub fn autogenerate_name(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.display_section_prefix(f)?;
self.display_type_prefix(f)?;
self.display_unique_identifier(f)
}
}
impl fmt::Display for SymbolMetadataNameDisplay<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(user_declared_name) = &self.sym.user_declared_name() {
let should_escape = should_quote_symbol(user_declared_name);
if should_escape {
write!(f, "\"")?;
}
write!(f, "{user_declared_name}")?;
if should_escape {
write!(f, "\"")?;
}
Ok(())
} else {
self.autogenerate_name(f)
}
}
}