1use gimli::{Encoding, EndianSlice, RunTimeEndian, UnitIndex};
2use object::{Endianness, ObjectSection};
3
4use crate::{relocate::RelocationMap, Session};
5
6pub(crate) trait EndianityExt {
8 fn as_runtime_endian(&self) -> RunTimeEndian;
9}
10
11impl EndianityExt for Endianness {
12 fn as_runtime_endian(&self) -> RunTimeEndian {
13 match *self {
14 Endianness::Little => RunTimeEndian::Little,
15 Endianness::Big => RunTimeEndian::Big,
16 }
17 }
18}
19
20pub(crate) trait CompressedDataRangeExt<'input, 'session: 'input>:
22 ObjectSection<'input>
23{
24 fn compressed_data_range(
28 &self,
29 sess: &'session impl Session<RelocationMap>,
30 address: u64,
31 size: u64,
32 ) -> object::Result<Option<&'input [u8]>>;
33}
34
35impl<'input, 'session: 'input, S> CompressedDataRangeExt<'input, 'session> for S
36where
37 S: ObjectSection<'input>,
38{
39 fn compressed_data_range(
40 &self,
41 sess: &'session impl Session<RelocationMap>,
42 address: u64,
43 size: u64,
44 ) -> object::Result<Option<&'input [u8]>> {
45 let data = self.compressed_data()?.decompress()?;
46
47 fn data_range(
50 data: &[u8],
51 data_address: u64,
52 range_address: u64,
53 size: u64,
54 ) -> Option<&[u8]> {
55 let offset = range_address.checked_sub(data_address)?;
56 data.get(offset.try_into().ok()?..)?.get(..size.try_into().ok()?)
57 }
58
59 let data_ref = sess.alloc_owned_cow(data);
60 Ok(data_range(data_ref, self.address(), address, size))
61 }
62}
63
64pub(crate) trait IndexSectionExt<'input, Endian: gimli::Endianity, R: gimli::Reader>:
66 gimli::Section<R>
67{
68 fn new(section: &'input [u8], endian: Endian) -> Self;
69
70 fn index(self) -> gimli::read::Result<UnitIndex<R>>;
71}
72
73impl<'input, Endian: gimli::Endianity> IndexSectionExt<'input, Endian, EndianSlice<'input, Endian>>
74 for gimli::DebugCuIndex<EndianSlice<'input, Endian>>
75{
76 fn new(section: &'input [u8], endian: Endian) -> Self {
77 Self::new(section, endian)
78 }
79
80 fn index(self) -> gimli::read::Result<UnitIndex<EndianSlice<'input, Endian>>> {
81 Self::index(self)
82 }
83}
84
85impl<'input, Endian: gimli::Endianity> IndexSectionExt<'input, Endian, EndianSlice<'input, Endian>>
86 for gimli::DebugTuIndex<EndianSlice<'input, Endian>>
87{
88 fn new(section: &'input [u8], endian: Endian) -> Self {
89 Self::new(section, endian)
90 }
91
92 fn index(self) -> gimli::read::Result<UnitIndex<EndianSlice<'input, Endian>>> {
93 Self::index(self)
94 }
95}
96
97pub(crate) trait PackageFormatExt {
99 fn is_std_dwarf_package_format(&self) -> bool;
105
106 fn is_gnu_extension_dwarf_package_format(&self) -> bool;
111
112 fn dwarf_package_index_version(&self) -> u16;
114
115 fn is_compatible_dwarf_package_index_version(&self, index_version: u16) -> bool;
118}
119
120impl PackageFormatExt for Encoding {
121 fn is_gnu_extension_dwarf_package_format(&self) -> bool {
122 !self.is_std_dwarf_package_format()
123 }
124
125 fn is_std_dwarf_package_format(&self) -> bool {
126 self.version >= 5
127 }
128
129 fn dwarf_package_index_version(&self) -> u16 {
130 if self.is_gnu_extension_dwarf_package_format() {
131 2
132 } else {
133 5
134 }
135 }
136
137 fn is_compatible_dwarf_package_index_version(&self, index_version: u16) -> bool {
138 if self.is_gnu_extension_dwarf_package_format() {
139 index_version == 2
140 } else {
141 index_version >= 5
142 }
143 }
144}