]> git.proxmox.com Git - rustc.git/blame - vendor/object-0.30.3/src/read/elf/note.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / vendor / object-0.30.3 / src / read / elf / note.rs
CommitLineData
9c376795
FG
1use core::fmt::Debug;
2use core::mem;
3
4use crate::elf;
5use crate::endian;
6use crate::pod::Pod;
7use crate::read::util;
8use crate::read::{self, Bytes, Error, ReadError};
9
10use super::FileHeader;
11
12/// An iterator over the notes in an ELF section or segment.
13#[derive(Debug)]
14pub struct NoteIterator<'data, Elf>
15where
16 Elf: FileHeader,
17{
18 endian: Elf::Endian,
19 align: usize,
20 data: Bytes<'data>,
21}
22
23impl<'data, Elf> NoteIterator<'data, Elf>
24where
25 Elf: FileHeader,
26{
27 /// Returns `Err` if `align` is invalid.
28 pub(super) fn new(
29 endian: Elf::Endian,
30 align: Elf::Word,
31 data: &'data [u8],
32 ) -> read::Result<Self> {
33 let align = match align.into() {
34 0u64..=4 => 4,
35 8 => 8,
36 _ => return Err(Error("Invalid ELF note alignment")),
37 };
38 // TODO: check data alignment?
39 Ok(NoteIterator {
40 endian,
41 align,
42 data: Bytes(data),
43 })
44 }
45
46 /// Returns the next note.
47 pub fn next(&mut self) -> read::Result<Option<Note<'data, Elf>>> {
48 let mut data = self.data;
49 if data.is_empty() {
50 return Ok(None);
51 }
52
53 let header = data
54 .read_at::<Elf::NoteHeader>(0)
55 .read_error("ELF note is too short")?;
56
57 // The name has no alignment requirement.
58 let offset = mem::size_of::<Elf::NoteHeader>();
59 let namesz = header.n_namesz(self.endian) as usize;
60 let name = data
61 .read_bytes_at(offset, namesz)
62 .read_error("Invalid ELF note namesz")?
63 .0;
64
65 // The descriptor must be aligned.
66 let offset = util::align(offset + namesz, self.align);
67 let descsz = header.n_descsz(self.endian) as usize;
68 let desc = data
69 .read_bytes_at(offset, descsz)
70 .read_error("Invalid ELF note descsz")?
71 .0;
72
73 // The next note (if any) must be aligned.
74 let offset = util::align(offset + descsz, self.align);
75 if data.skip(offset).is_err() {
76 data = Bytes(&[]);
77 }
78 self.data = data;
79
80 Ok(Some(Note { header, name, desc }))
81 }
82}
83
84/// A parsed `NoteHeader`.
85#[derive(Debug)]
86pub struct Note<'data, Elf>
87where
88 Elf: FileHeader,
89{
90 header: &'data Elf::NoteHeader,
91 name: &'data [u8],
92 desc: &'data [u8],
93}
94
95impl<'data, Elf: FileHeader> Note<'data, Elf> {
96 /// Return the `n_type` field of the `NoteHeader`.
97 ///
98 /// The meaning of this field is determined by `name`.
99 pub fn n_type(&self, endian: Elf::Endian) -> u32 {
100 self.header.n_type(endian)
101 }
102
103 /// Return the `n_namesz` field of the `NoteHeader`.
104 pub fn n_namesz(&self, endian: Elf::Endian) -> u32 {
105 self.header.n_namesz(endian)
106 }
107
108 /// Return the `n_descsz` field of the `NoteHeader`.
109 pub fn n_descsz(&self, endian: Elf::Endian) -> u32 {
110 self.header.n_descsz(endian)
111 }
112
113 /// Return the bytes for the name field following the `NoteHeader`,
114 /// excluding any null terminator.
115 ///
116 /// This field is usually a string including a null terminator
117 /// (but it is not required to be).
118 ///
119 /// The length of this field (including any null terminator) is given by
120 /// `n_namesz`.
121 pub fn name(&self) -> &'data [u8] {
122 if let Some((last, name)) = self.name.split_last() {
123 if *last == 0 {
124 return name;
125 }
126 }
127 self.name
128 }
129
130 /// Return the bytes for the desc field following the `NoteHeader`.
131 ///
132 /// The length of this field is given by `n_descsz`. The meaning
133 /// of this field is determined by `name` and `n_type`.
134 pub fn desc(&self) -> &'data [u8] {
135 self.desc
136 }
137}
138
139/// A trait for generic access to `NoteHeader32` and `NoteHeader64`.
140#[allow(missing_docs)]
141pub trait NoteHeader: Debug + Pod {
142 type Endian: endian::Endian;
143
144 fn n_namesz(&self, endian: Self::Endian) -> u32;
145 fn n_descsz(&self, endian: Self::Endian) -> u32;
146 fn n_type(&self, endian: Self::Endian) -> u32;
147}
148
149impl<Endian: endian::Endian> NoteHeader for elf::NoteHeader32<Endian> {
150 type Endian = Endian;
151
152 #[inline]
153 fn n_namesz(&self, endian: Self::Endian) -> u32 {
154 self.n_namesz.get(endian)
155 }
156
157 #[inline]
158 fn n_descsz(&self, endian: Self::Endian) -> u32 {
159 self.n_descsz.get(endian)
160 }
161
162 #[inline]
163 fn n_type(&self, endian: Self::Endian) -> u32 {
164 self.n_type.get(endian)
165 }
166}
167
168impl<Endian: endian::Endian> NoteHeader for elf::NoteHeader64<Endian> {
169 type Endian = Endian;
170
171 #[inline]
172 fn n_namesz(&self, endian: Self::Endian) -> u32 {
173 self.n_namesz.get(endian)
174 }
175
176 #[inline]
177 fn n_descsz(&self, endian: Self::Endian) -> u32 {
178 self.n_descsz.get(endian)
179 }
180
181 #[inline]
182 fn n_type(&self, endian: Self::Endian) -> u32 {
183 self.n_type.get(endian)
184 }
185}