1#![allow(non_upper_case_globals)]
2
3use crate::{
4 enums::*,
5 error::TagError,
6 globals::*,
7 read::{read_string, read_u32, read_u8, read_uleb128, read_uleb128_list, Cursor, Endian},
8};
9
10#[derive(Clone, PartialEq, Eq, Debug, Hash)]
11pub enum Tag<'a> {
12 File { end_offset: u32 },
14 Section { end_offset: u32, sections: &'a [u8] },
16 Symbol { end_offset: u32, symbols: &'a [u8] },
18 CpuRawName(&'a str),
20 CpuName(CpuName<'a>),
22 CpuArch(CpuArch),
24 CpuArchProfile(CpuArchProfile),
26 ArmIsaUse(ArmIsaUse),
28 ThumbIsaUse(ThumbIsaUse),
30 FpArch(FpArch),
32 WmmxArch(WmmxArch),
34 AsimdArch(AsimdArch),
36 PcsConfig(PcsConfig),
38 AbiPcsR9Use(AbiPcsR9Use),
40 AbiPcsRwData(AbiPcsRwData),
42 AbiPcsRoData(AbiPcsRoData),
44 AbiPcsGotUse(AbiPcsGotUse),
46 AbiPcsWcharT(AbiPcsWcharT),
48 AbiFpRounding(AbiFpRounding),
50 AbiFpDenormal(AbiFpDenormal),
52 AbiFpExceptions(AbiFpExceptions),
54 AbiFpUserExceptions(AbiFpUserExceptions),
56 AbiFpNumberModel(AbiFpNumberModel),
58 AbiAlignNeeded(AbiAlignNeeded),
60 AbiAlignPreserved(AbiAlignPreserved),
62 AbiEnumSize(AbiEnumSize),
64 AbiHardFpUse(AbiHardFpUse),
66 AbiVfpArgs(AbiVfpArgs),
68 AbiWmmxArgs(AbiWmmxArgs),
70 AbiOptGoals(AbiOptGoals),
72 AbiFpOptGoals(AbiFpOptGoals),
74 Compat(Compat<'a>),
76 CpuUnalignedAccess(CpuUnalignedAccess),
78 FpHpExt(FpHpExt),
80 AbiFp16BitFormat(AbiFp16BitFormat),
82 MpExtUse(MpExtUse),
84 DivUse(DivUse),
86 DspExt(DspExt),
88 MveArch(MveArch),
90 PacExt(PacExt),
92 BtiExt(BtiExt),
94 NoDefaults,
96 AlsoCompatWith(AlsoCompatWith<'a>),
98 Conform(Conform<'a>),
100 T2EeUse(T2EeUse),
102 VirtualUse(VirtualUse),
104 FramePointerUse(FramePointerUse),
106 BtiUse(BtiUse),
108 PacretUse(PacretUse),
110}
111
112impl<'a> Tag<'a> {
113 pub fn is_uleb128(&self) -> bool {
114 !matches!(
115 self,
116 Tag::File { end_offset: _ }
117 | Tag::Section {
118 end_offset: _,
119 sections: _
120 }
121 | Tag::Symbol {
122 end_offset: _,
123 symbols: _
124 }
125 | Tag::CpuRawName(_)
126 | Tag::CpuName(_)
127 | Tag::Compat(_)
128 | Tag::AlsoCompatWith(_)
129 | Tag::Conform(_)
130 )
131 }
132
133 pub fn is_scope(&self) -> bool {
134 matches!(
135 self,
136 Tag::File { end_offset: _ }
137 | Tag::Section {
138 end_offset: _,
139 sections: _
140 }
141 | Tag::Symbol {
142 end_offset: _,
143 symbols: _
144 }
145 )
146 }
147
148 pub fn raw_tag(&self) -> u8 {
149 match self {
150 Tag::File { end_offset: _ } => Tag_File,
151 Tag::Section {
152 end_offset: _,
153 sections: _,
154 } => Tag_Section,
155 Tag::Symbol {
156 end_offset: _,
157 symbols: _,
158 } => Tag_Symbol,
159 Tag::CpuRawName(_) => Tag_CPU_raw_name,
160 Tag::CpuName(_) => Tag_CPU_name,
161 Tag::CpuArch(_) => Tag_CPU_arch,
162 Tag::CpuArchProfile(_) => Tag_CPU_arch_profile,
163 Tag::ArmIsaUse(_) => Tag_ARM_ISA_use,
164 Tag::ThumbIsaUse(_) => Tag_THUMB_ISA_use,
165 Tag::FpArch(_) => Tag_FP_arch,
166 Tag::WmmxArch(_) => Tag_WMMX_arch,
167 Tag::AsimdArch(_) => Tag_Advanced_SIMD_arch,
168 Tag::PcsConfig(_) => Tag_PCS_config,
169 Tag::AbiPcsR9Use(_) => Tag_ABI_PCS_R9_use,
170 Tag::AbiPcsRwData(_) => Tag_ABI_PCS_RW_data,
171 Tag::AbiPcsRoData(_) => Tag_ABI_PCS_RO_data,
172 Tag::AbiPcsGotUse(_) => Tag_ABI_PCS_GOT_use,
173 Tag::AbiPcsWcharT(_) => Tag_ABI_PCS_wchar_t,
174 Tag::AbiFpRounding(_) => Tag_ABI_FP_rounding,
175 Tag::AbiFpDenormal(_) => Tag_ABI_FP_denormal,
176 Tag::AbiFpExceptions(_) => Tag_ABI_FP_exceptions,
177 Tag::AbiFpUserExceptions(_) => Tag_ABI_FP_user_exceptions,
178 Tag::AbiFpNumberModel(_) => Tag_ABI_FP_number_model,
179 Tag::AbiAlignNeeded(_) => Tag_ABI_align_needed,
180 Tag::AbiAlignPreserved(_) => Tag_ABI_align_preserved,
181 Tag::AbiEnumSize(_) => Tag_ABI_enum_size,
182 Tag::AbiHardFpUse(_) => Tag_ABI_HardFP_use,
183 Tag::AbiVfpArgs(_) => Tag_ABI_VFP_args,
184 Tag::AbiWmmxArgs(_) => Tag_ABI_WMMX_args,
185 Tag::AbiOptGoals(_) => Tag_ABI_optimization_goals,
186 Tag::AbiFpOptGoals(_) => Tag_ABI_FP_optimization_goals,
187 Tag::Compat(_) => Tag_compatibility,
188 Tag::CpuUnalignedAccess(_) => Tag_CPU_unaligned_access,
189 Tag::FpHpExt(_) => Tag_FP_HP_extension,
190 Tag::AbiFp16BitFormat(_) => Tag_ABI_FP_16bit_format,
191 Tag::MpExtUse(_) => Tag_MPextension_use,
192 Tag::DivUse(_) => Tag_DIV_use,
193 Tag::DspExt(_) => Tag_DSP_extension,
194 Tag::MveArch(_) => Tag_MVE_arch,
195 Tag::PacExt(_) => Tag_PAC_extension,
196 Tag::BtiExt(_) => Tag_BTI_extension,
197 Tag::NoDefaults => Tag_nodefaults,
198 Tag::AlsoCompatWith(_) => Tag_also_compatible_with,
199 Tag::Conform(_) => Tag_conformance,
200 Tag::T2EeUse(_) => Tag_T2EE_use,
201 Tag::VirtualUse(_) => Tag_Virtualization_use,
202 Tag::FramePointerUse(_) => Tag_FramePointer_use,
203 Tag::BtiUse(_) => Tag_BTI_use,
204 Tag::PacretUse(_) => Tag_PACRET_use,
205 }
206 }
207
208 pub(crate) fn read(cursor: &mut Cursor<'a>, endian: Endian) -> Result<Self, TagError> {
209 let pos = cursor.position() as u32;
210 let tag = read_uleb128(cursor).map_err(TagError::Read)?;
211 let tag = match tag {
212 Tag_File => Tag::File {
213 end_offset: pos + read_u32(cursor, endian).map_err(TagError::Read)?,
214 },
215 Tag_Section => Tag::Section {
216 end_offset: pos + read_u32(cursor, endian).map_err(TagError::Read)?,
217 sections: read_uleb128_list(cursor).map_err(TagError::Read)?,
218 },
219 Tag_Symbol => Tag::Symbol {
220 end_offset: pos + read_u32(cursor, endian).map_err(TagError::Read)?,
221 symbols: read_uleb128_list(cursor).map_err(TagError::Read)?,
222 },
223 Tag_CPU_raw_name => Tag::CpuRawName(read_string(cursor).map_err(TagError::Read)?),
224 Tag_CPU_name => Tag::CpuName(CpuName::from(read_string(cursor).map_err(TagError::Read)?)),
225 Tag_CPU_arch => Tag::CpuArch(CpuArch::from(read_uleb128(cursor).map_err(TagError::Read)?)),
226 Tag_CPU_arch_profile => Tag::CpuArchProfile(CpuArchProfile::from(read_uleb128(cursor).map_err(TagError::Read)?)),
227 Tag_ARM_ISA_use => Tag::ArmIsaUse(ArmIsaUse::from(read_uleb128(cursor).map_err(TagError::Read)?)),
228 Tag_THUMB_ISA_use => Tag::ThumbIsaUse(ThumbIsaUse::from(read_uleb128(cursor).map_err(TagError::Read)?)),
229 Tag_FP_arch => Tag::FpArch(FpArch::from(read_uleb128(cursor).map_err(TagError::Read)?)),
230 Tag_WMMX_arch => Tag::WmmxArch(WmmxArch::from(read_uleb128(cursor).map_err(TagError::Read)?)),
231 Tag_Advanced_SIMD_arch => Tag::AsimdArch(AsimdArch::from(read_uleb128(cursor).map_err(TagError::Read)?)),
232 Tag_PCS_config => Tag::PcsConfig(PcsConfig::from(read_uleb128(cursor).map_err(TagError::Read)?)),
233 Tag_ABI_PCS_R9_use => Tag::AbiPcsR9Use(AbiPcsR9Use::from(read_uleb128(cursor).map_err(TagError::Read)?)),
234 Tag_ABI_PCS_RW_data => Tag::AbiPcsRwData(AbiPcsRwData::from(read_uleb128(cursor).map_err(TagError::Read)?)),
235 Tag_ABI_PCS_RO_data => Tag::AbiPcsRoData(AbiPcsRoData::from(read_uleb128(cursor).map_err(TagError::Read)?)),
236 Tag_ABI_PCS_GOT_use => Tag::AbiPcsGotUse(AbiPcsGotUse::from(read_uleb128(cursor).map_err(TagError::Read)?)),
237 Tag_ABI_PCS_wchar_t => Tag::AbiPcsWcharT(AbiPcsWcharT::from(read_uleb128(cursor).map_err(TagError::Read)?)),
238 Tag_ABI_FP_rounding => Tag::AbiFpRounding(AbiFpRounding::from(read_uleb128(cursor).map_err(TagError::Read)?)),
239 Tag_ABI_FP_denormal => Tag::AbiFpDenormal(AbiFpDenormal::from(read_uleb128(cursor).map_err(TagError::Read)?)),
240 Tag_ABI_FP_exceptions => {
241 Tag::AbiFpExceptions(AbiFpExceptions::from(read_uleb128(cursor).map_err(TagError::Read)?))
242 }
243 Tag_ABI_FP_user_exceptions => {
244 Tag::AbiFpUserExceptions(AbiFpUserExceptions::from(read_uleb128(cursor).map_err(TagError::Read)?))
245 }
246 Tag_ABI_FP_number_model => {
247 Tag::AbiFpNumberModel(AbiFpNumberModel::from(read_uleb128(cursor).map_err(TagError::Read)?))
248 }
249 Tag_ABI_align_needed => Tag::AbiAlignNeeded(AbiAlignNeeded::from(read_uleb128(cursor).map_err(TagError::Read)?)),
250 Tag_ABI_align_preserved => {
251 Tag::AbiAlignPreserved(AbiAlignPreserved::from(read_uleb128(cursor).map_err(TagError::Read)?))
252 }
253 Tag_ABI_enum_size => Tag::AbiEnumSize(AbiEnumSize::from(read_uleb128(cursor).map_err(TagError::Read)?)),
254 Tag_ABI_HardFP_use => Tag::AbiHardFpUse(AbiHardFpUse::from(read_uleb128(cursor).map_err(TagError::Read)?)),
255 Tag_ABI_VFP_args => Tag::AbiVfpArgs(AbiVfpArgs::from(read_uleb128(cursor).map_err(TagError::Read)?)),
256 Tag_ABI_WMMX_args => Tag::AbiWmmxArgs(AbiWmmxArgs::from(read_uleb128(cursor).map_err(TagError::Read)?)),
257 Tag_ABI_optimization_goals => Tag::AbiOptGoals(AbiOptGoals::from(read_uleb128(cursor).map_err(TagError::Read)?)),
258 Tag_ABI_FP_optimization_goals => {
259 Tag::AbiFpOptGoals(AbiFpOptGoals::from(read_uleb128(cursor).map_err(TagError::Read)?))
260 }
261 Tag_compatibility => {
262 let flag = read_uleb128(cursor).map_err(TagError::Read)?;
263 Tag::Compat(Compat::new(
264 flag,
265 if flag != 0 {
266 read_string(cursor).map_err(TagError::Read)?
267 } else {
268 ""
269 },
270 ))
271 }
272 Tag_CPU_unaligned_access => {
273 Tag::CpuUnalignedAccess(CpuUnalignedAccess::from(read_uleb128(cursor).map_err(TagError::Read)?))
274 }
275 Tag_FP_HP_extension => Tag::FpHpExt(FpHpExt::from(read_uleb128(cursor).map_err(TagError::Read)?)),
276 Tag_ABI_FP_16bit_format => {
277 Tag::AbiFp16BitFormat(AbiFp16BitFormat::from(read_uleb128(cursor).map_err(TagError::Read)?))
278 }
279 Tag_MPextension_use => Tag::MpExtUse(MpExtUse::from(read_uleb128(cursor).map_err(TagError::Read)?)),
280 Tag_DIV_use => Tag::DivUse(DivUse::from(read_uleb128(cursor).map_err(TagError::Read)?)),
281 Tag_DSP_extension => Tag::DspExt(DspExt::from(read_uleb128(cursor).map_err(TagError::Read)?)),
282 Tag_MVE_arch => Tag::MveArch(MveArch::from(read_uleb128(cursor).map_err(TagError::Read)?)),
283 Tag_PAC_extension => Tag::PacExt(PacExt::from(read_uleb128(cursor).map_err(TagError::Read)?)),
284 Tag_BTI_extension => Tag::BtiExt(BtiExt::from(read_uleb128(cursor).map_err(TagError::Read)?)),
285 Tag_nodefaults => {
286 let ignored = read_u8(cursor).map_err(TagError::Read)?;
287 if ignored != 0 {
288 return Err(TagError::ExpectedNull);
289 }
290 Tag::NoDefaults
291 }
292 Tag_also_compatible_with => {
293 let sub_tag = Tag::read(cursor, endian)?;
294 if sub_tag.is_uleb128() {
295 let null = read_u8(cursor).map_err(TagError::Read)?;
296 if null != 0 {
297 return Err(TagError::ExpectedNull);
298 }
299 }
300 if sub_tag.is_scope() {
301 return Err(TagError::NestedScopeTag);
302 }
303 Tag::AlsoCompatWith(AlsoCompatWith::new(sub_tag))
304 }
305 Tag_conformance => Tag::Conform(Conform::from(read_string(cursor).map_err(TagError::Read)?)),
306 Tag_T2EE_use => Tag::T2EeUse(T2EeUse::from(read_uleb128(cursor).map_err(TagError::Read)?)),
307 Tag_Virtualization_use => Tag::VirtualUse(VirtualUse::from(read_uleb128(cursor).map_err(TagError::Read)?)),
308 Tag_FramePointer_use => Tag::FramePointerUse(FramePointerUse::from(read_uleb128(cursor).map_err(TagError::Read)?)),
309 Tag_BTI_use => Tag::BtiUse(BtiUse::from(read_uleb128(cursor).map_err(TagError::Read)?)),
310 Tag_PACRET_use => Tag::PacretUse(PacretUse::from(read_uleb128(cursor).map_err(TagError::Read)?)),
311 _ => return Err(TagError::IncompatibleTagValue(tag)),
312 };
313 Ok(tag)
314 }
315}