arm_attr/
tag.rs

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    /// Tag_File
13    File { end_offset: u32 },
14    /// Tag_Section
15    Section { end_offset: u32, sections: &'a [u8] },
16    /// Tag_Symbol
17    Symbol { end_offset: u32, symbols: &'a [u8] },
18    /// Tag_CPU_raw_name
19    CpuRawName(&'a str),
20    /// Tag_CPU_name
21    CpuName(CpuName<'a>),
22    /// Tag_CPU_arch
23    CpuArch(CpuArch),
24    /// Tag_CPU_arch_profile
25    CpuArchProfile(CpuArchProfile),
26    /// Tag_ARM_ISA_use
27    ArmIsaUse(ArmIsaUse),
28    /// Tag_THUMB_ISA_use
29    ThumbIsaUse(ThumbIsaUse),
30    /// Tag_FP_arch
31    FpArch(FpArch),
32    /// Tag_WMMX_arch
33    WmmxArch(WmmxArch),
34    /// Tag_Advanced_SIMD_arch
35    AsimdArch(AsimdArch),
36    /// Tag_PCS_config
37    PcsConfig(PcsConfig),
38    /// Tag_ABI_PCS_R9_use
39    AbiPcsR9Use(AbiPcsR9Use),
40    /// Tag_ABI_PCS_RW_data
41    AbiPcsRwData(AbiPcsRwData),
42    /// Tag_ABI_PCS_RO_data
43    AbiPcsRoData(AbiPcsRoData),
44    /// Tag_ABI_PCS_GOT_use
45    AbiPcsGotUse(AbiPcsGotUse),
46    /// Tag_ABI_PCS_wchar_t
47    AbiPcsWcharT(AbiPcsWcharT),
48    /// Tag_ABI_FP_rounding
49    AbiFpRounding(AbiFpRounding),
50    /// Tag_ABI_FP_denormal
51    AbiFpDenormal(AbiFpDenormal),
52    /// Tag_ABI_FP_exceptions
53    AbiFpExceptions(AbiFpExceptions),
54    /// Tag_ABI_FP_user_exceptions
55    AbiFpUserExceptions(AbiFpUserExceptions),
56    /// Tag_ABI_FP_number_model
57    AbiFpNumberModel(AbiFpNumberModel),
58    /// Tag_ABI_align_needed
59    AbiAlignNeeded(AbiAlignNeeded),
60    /// Tag_ABI_align_preserved
61    AbiAlignPreserved(AbiAlignPreserved),
62    /// Tag_ABI_enum_size
63    AbiEnumSize(AbiEnumSize),
64    /// Tag_ABI_HardFP_use
65    AbiHardFpUse(AbiHardFpUse),
66    /// Tag_ABI_VFP_args
67    AbiVfpArgs(AbiVfpArgs),
68    /// Tag_ABI_WMMX_args
69    AbiWmmxArgs(AbiWmmxArgs),
70    /// Tag_ABI_optimization_goals
71    AbiOptGoals(AbiOptGoals),
72    /// Tag_ABI_FP_optimization_goals
73    AbiFpOptGoals(AbiFpOptGoals),
74    /// Tag_compatibility
75    Compat(Compat<'a>),
76    /// Tag_CPU_unaligned_access
77    CpuUnalignedAccess(CpuUnalignedAccess),
78    /// Tag_FP_HP_extension
79    FpHpExt(FpHpExt),
80    /// Tag_ABI_FP_16bit_format
81    AbiFp16BitFormat(AbiFp16BitFormat),
82    /// Tag_MPextension_use
83    MpExtUse(MpExtUse),
84    /// Tag_DIV_use
85    DivUse(DivUse),
86    /// Tag_DSP_extension
87    DspExt(DspExt),
88    /// Tag_MVE_arch
89    MveArch(MveArch),
90    /// Tag_PAC_extension
91    PacExt(PacExt),
92    /// Tag_BTI_extension
93    BtiExt(BtiExt),
94    /// Tag_nodefaults
95    NoDefaults,
96    /// Tag_also_compatible_with
97    AlsoCompatWith(AlsoCompatWith<'a>),
98    /// Tag_conformance
99    Conform(Conform<'a>),
100    /// Tag_T2EE_use
101    T2EeUse(T2EeUse),
102    /// Tag_Virtualization_use
103    VirtualUse(VirtualUse),
104    /// Tag_FramePointer_use
105    FramePointerUse(FramePointerUse),
106    /// Tag_BTI_use
107    BtiUse(BtiUse),
108    /// Tag_PACRET_use
109    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}