]>
Commit | Line | Data |
---|---|---|
9c376795 | 1 | use object::read::elf::{FileHeader, SectionHeader}; |
fe692bf9 | 2 | use object::read::{Object, ObjectSection, ObjectSymbol}; |
9c376795 FG |
3 | use object::{ |
4 | elf, read, write, Architecture, BinaryFormat, Endianness, LittleEndian, SectionIndex, | |
5 | SectionKind, SymbolFlags, SymbolKind, SymbolScope, SymbolSection, U32, | |
6 | }; | |
7 | use std::io::Write; | |
8 | ||
9 | #[test] | |
10 | fn symtab_shndx() { | |
11 | let mut object = | |
12 | write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); | |
13 | ||
14 | for i in 0..0x10000 { | |
15 | let name = format!("func{}", i).into_bytes(); | |
16 | let (section, offset) = | |
17 | object.add_subsection(write::StandardSection::Text, &name, &[0xcc], 1); | |
18 | object.add_symbol(write::Symbol { | |
19 | name, | |
20 | value: offset, | |
21 | size: 1, | |
22 | kind: SymbolKind::Text, | |
23 | scope: SymbolScope::Linkage, | |
24 | weak: false, | |
25 | section: write::SymbolSection::Section(section), | |
26 | flags: SymbolFlags::None, | |
27 | }); | |
28 | } | |
29 | let bytes = object.write().unwrap(); | |
30 | ||
31 | //std::fs::write(&"symtab_shndx.o", &bytes).unwrap(); | |
32 | ||
33 | let object = read::File::parse(&*bytes).unwrap(); | |
34 | assert_eq!(object.format(), BinaryFormat::Elf); | |
35 | assert_eq!(object.architecture(), Architecture::X86_64); | |
36 | ||
37 | for symbol in object.symbols().skip(1) { | |
38 | assert_eq!( | |
39 | symbol.section(), | |
40 | SymbolSection::Section(SectionIndex(symbol.index().0)) | |
41 | ); | |
42 | } | |
43 | } | |
44 | ||
fe692bf9 FG |
45 | #[test] |
46 | fn aligned_sections() { | |
47 | let mut object = | |
48 | write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); | |
49 | ||
50 | let text_section_id = object.add_section(vec![], b".text".to_vec(), SectionKind::Text); | |
51 | let text_section = object.section_mut(text_section_id); | |
52 | text_section.set_data(&[][..], 4096); | |
53 | ||
54 | let data_section_id = object.add_section(vec![], b".data".to_vec(), SectionKind::Data); | |
55 | let data_section = object.section_mut(data_section_id); | |
56 | data_section.set_data(&b"1234"[..], 16); | |
57 | ||
58 | let bytes = object.write().unwrap(); | |
59 | ||
60 | let object = read::File::parse(&*bytes).unwrap(); | |
61 | assert_eq!(object.format(), BinaryFormat::Elf); | |
62 | assert_eq!(object.architecture(), Architecture::X86_64); | |
63 | ||
64 | let mut sections = object.sections(); | |
65 | let _ = sections.next().unwrap(); | |
66 | ||
67 | let section = sections.next().unwrap(); | |
68 | assert_eq!(section.name(), Ok(".text")); | |
69 | assert_eq!(section.file_range(), Some((4096, 0))); | |
70 | ||
71 | let section = sections.next().unwrap(); | |
72 | assert_eq!(section.name(), Ok(".data")); | |
73 | assert_eq!(section.file_range(), Some((4096, 4))); | |
74 | } | |
75 | ||
9c376795 FG |
76 | #[cfg(feature = "compression")] |
77 | #[test] | |
78 | fn compression_zlib() { | |
79 | use object::read::ObjectSection; | |
80 | use object::LittleEndian as LE; | |
81 | ||
82 | let data = b"test data data data"; | |
83 | let len = data.len() as u64; | |
84 | ||
85 | let mut ch = object::elf::CompressionHeader64::<LE>::default(); | |
86 | ch.ch_type.set(LE, object::elf::ELFCOMPRESS_ZLIB); | |
87 | ch.ch_size.set(LE, len); | |
88 | ch.ch_addralign.set(LE, 1); | |
89 | ||
90 | let mut buf = Vec::new(); | |
91 | buf.write(object::bytes_of(&ch)).unwrap(); | |
92 | let mut encoder = flate2::write::ZlibEncoder::new(buf, flate2::Compression::default()); | |
93 | encoder.write_all(data).unwrap(); | |
94 | let compressed = encoder.finish().unwrap(); | |
95 | ||
96 | let mut object = | |
97 | write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); | |
98 | let section = object.add_section( | |
99 | Vec::new(), | |
100 | b".debug_info".to_vec(), | |
101 | object::SectionKind::Other, | |
102 | ); | |
103 | object.section_mut(section).set_data(compressed, 1); | |
104 | object.section_mut(section).flags = object::SectionFlags::Elf { | |
105 | sh_flags: object::elf::SHF_COMPRESSED.into(), | |
106 | }; | |
107 | let bytes = object.write().unwrap(); | |
108 | ||
109 | //std::fs::write(&"compression.o", &bytes).unwrap(); | |
110 | ||
111 | let object = read::File::parse(&*bytes).unwrap(); | |
112 | assert_eq!(object.format(), BinaryFormat::Elf); | |
113 | assert_eq!(object.architecture(), Architecture::X86_64); | |
114 | ||
115 | let section = object.section_by_name(".debug_info").unwrap(); | |
116 | let uncompressed = section.uncompressed_data().unwrap(); | |
117 | assert_eq!(data, &*uncompressed); | |
118 | } | |
119 | ||
120 | #[cfg(feature = "compression")] | |
121 | #[test] | |
122 | fn compression_gnu() { | |
123 | use object::read::ObjectSection; | |
124 | use std::io::Write; | |
125 | ||
126 | let data = b"test data data data"; | |
127 | let len = data.len() as u32; | |
128 | ||
129 | let mut buf = Vec::new(); | |
130 | buf.write_all(b"ZLIB\0\0\0\0").unwrap(); | |
131 | buf.write_all(&len.to_be_bytes()).unwrap(); | |
132 | let mut encoder = flate2::write::ZlibEncoder::new(buf, flate2::Compression::default()); | |
133 | encoder.write_all(data).unwrap(); | |
134 | let compressed = encoder.finish().unwrap(); | |
135 | ||
136 | let mut object = | |
137 | write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); | |
138 | let section = object.add_section( | |
139 | Vec::new(), | |
140 | b".zdebug_info".to_vec(), | |
141 | object::SectionKind::Other, | |
142 | ); | |
143 | object.section_mut(section).set_data(compressed, 1); | |
144 | let bytes = object.write().unwrap(); | |
145 | ||
146 | //std::fs::write(&"compression.o", &bytes).unwrap(); | |
147 | ||
148 | let object = read::File::parse(&*bytes).unwrap(); | |
149 | assert_eq!(object.format(), BinaryFormat::Elf); | |
150 | assert_eq!(object.architecture(), Architecture::X86_64); | |
151 | ||
152 | let section = object.section_by_name(".zdebug_info").unwrap(); | |
153 | let uncompressed = section.uncompressed_data().unwrap(); | |
154 | assert_eq!(data, &*uncompressed); | |
155 | } | |
156 | ||
157 | #[test] | |
158 | fn note() { | |
159 | let endian = Endianness::Little; | |
160 | let mut object = write::Object::new(BinaryFormat::Elf, Architecture::X86_64, endian); | |
161 | ||
162 | // Add note section with align = 4. | |
163 | let mut buffer = Vec::new(); | |
164 | ||
165 | buffer | |
166 | .write(object::bytes_of(&elf::NoteHeader32 { | |
167 | n_namesz: U32::new(endian, 6), | |
168 | n_descsz: U32::new(endian, 11), | |
169 | n_type: U32::new(endian, 1), | |
170 | })) | |
171 | .unwrap(); | |
172 | buffer.write(b"name1\0\0\0").unwrap(); | |
173 | buffer.write(b"descriptor\0\0").unwrap(); | |
174 | ||
175 | buffer | |
176 | .write(object::bytes_of(&elf::NoteHeader32 { | |
177 | n_namesz: U32::new(endian, 6), | |
178 | n_descsz: U32::new(endian, 11), | |
179 | n_type: U32::new(endian, 2), | |
180 | })) | |
181 | .unwrap(); | |
182 | buffer.write(b"name2\0\0\0").unwrap(); | |
183 | buffer.write(b"descriptor\0\0").unwrap(); | |
184 | ||
185 | let section = object.add_section(Vec::new(), b".note4".to_vec(), SectionKind::Note); | |
186 | object.section_mut(section).set_data(buffer, 4); | |
187 | ||
188 | // Add note section with align = 8. | |
189 | let mut buffer = Vec::new(); | |
190 | ||
191 | buffer | |
192 | .write(object::bytes_of(&elf::NoteHeader32 { | |
193 | n_namesz: U32::new(endian, 6), | |
194 | n_descsz: U32::new(endian, 11), | |
195 | n_type: U32::new(endian, 1), | |
196 | })) | |
197 | .unwrap(); | |
198 | buffer.write(b"name1\0\0\0\0\0\0\0").unwrap(); | |
199 | buffer.write(b"descriptor\0\0\0\0\0\0").unwrap(); | |
200 | ||
201 | buffer | |
202 | .write(object::bytes_of(&elf::NoteHeader32 { | |
203 | n_namesz: U32::new(endian, 4), | |
204 | n_descsz: U32::new(endian, 11), | |
205 | n_type: U32::new(endian, 2), | |
206 | })) | |
207 | .unwrap(); | |
208 | buffer.write(b"abc\0").unwrap(); | |
209 | buffer.write(b"descriptor\0\0\0\0\0\0").unwrap(); | |
210 | ||
211 | let section = object.add_section(Vec::new(), b".note8".to_vec(), SectionKind::Note); | |
212 | object.section_mut(section).set_data(buffer, 8); | |
213 | ||
214 | let bytes = &*object.write().unwrap(); | |
215 | ||
216 | //std::fs::write(&"note.o", &bytes).unwrap(); | |
217 | ||
218 | let header = elf::FileHeader64::parse(bytes).unwrap(); | |
219 | let endian: LittleEndian = header.endian().unwrap(); | |
220 | let sections = header.sections(endian, bytes).unwrap(); | |
221 | ||
222 | let section = sections.section(SectionIndex(1)).unwrap(); | |
223 | assert_eq!(sections.section_name(endian, section).unwrap(), b".note4"); | |
224 | assert_eq!(section.sh_addralign(endian), 4); | |
225 | let mut notes = section.notes(endian, bytes).unwrap().unwrap(); | |
226 | let note = notes.next().unwrap().unwrap(); | |
227 | assert_eq!(note.name(), b"name1"); | |
228 | assert_eq!(note.desc(), b"descriptor\0"); | |
229 | assert_eq!(note.n_type(endian), 1); | |
230 | let note = notes.next().unwrap().unwrap(); | |
231 | assert_eq!(note.name(), b"name2"); | |
232 | assert_eq!(note.desc(), b"descriptor\0"); | |
233 | assert_eq!(note.n_type(endian), 2); | |
234 | assert!(notes.next().unwrap().is_none()); | |
235 | ||
236 | let section = sections.section(SectionIndex(2)).unwrap(); | |
237 | assert_eq!(sections.section_name(endian, section).unwrap(), b".note8"); | |
238 | assert_eq!(section.sh_addralign(endian), 8); | |
239 | let mut notes = section.notes(endian, bytes).unwrap().unwrap(); | |
240 | let note = notes.next().unwrap().unwrap(); | |
241 | assert_eq!(note.name(), b"name1"); | |
242 | assert_eq!(note.desc(), b"descriptor\0"); | |
243 | assert_eq!(note.n_type(endian), 1); | |
244 | let note = notes.next().unwrap().unwrap(); | |
245 | assert_eq!(note.name(), b"abc"); | |
246 | assert_eq!(note.desc(), b"descriptor\0"); | |
247 | assert_eq!(note.n_type(endian), 2); | |
248 | assert!(notes.next().unwrap().is_none()); | |
249 | } | |
fe692bf9 FG |
250 | |
251 | #[test] | |
252 | fn gnu_property() { | |
253 | gnu_property_inner::<elf::FileHeader32<Endianness>>(Architecture::I386); | |
254 | gnu_property_inner::<elf::FileHeader64<Endianness>>(Architecture::X86_64); | |
255 | } | |
256 | ||
257 | fn gnu_property_inner<Elf: FileHeader<Endian = Endianness>>(architecture: Architecture) { | |
258 | let endian = Endianness::Little; | |
259 | let mut object = write::Object::new(BinaryFormat::Elf, architecture, endian); | |
260 | object.add_elf_gnu_property_u32( | |
261 | elf::GNU_PROPERTY_X86_FEATURE_1_AND, | |
262 | elf::GNU_PROPERTY_X86_FEATURE_1_IBT | elf::GNU_PROPERTY_X86_FEATURE_1_SHSTK, | |
263 | ); | |
264 | ||
265 | let bytes = &*object.write().unwrap(); | |
266 | ||
267 | //std::fs::write(&"note.o", &bytes).unwrap(); | |
268 | ||
269 | let header = Elf::parse(bytes).unwrap(); | |
270 | assert_eq!(header.endian().unwrap(), endian); | |
271 | let sections = header.sections(endian, bytes).unwrap(); | |
272 | let section = sections.section(SectionIndex(1)).unwrap(); | |
273 | assert_eq!( | |
274 | sections.section_name(endian, section).unwrap(), | |
275 | b".note.gnu.property" | |
276 | ); | |
277 | assert_eq!(section.sh_flags(endian).into(), u64::from(elf::SHF_ALLOC)); | |
278 | let mut notes = section.notes(endian, bytes).unwrap().unwrap(); | |
279 | let note = notes.next().unwrap().unwrap(); | |
280 | let mut props = note.gnu_properties(endian).unwrap(); | |
281 | let prop = props.next().unwrap().unwrap(); | |
282 | assert_eq!(prop.pr_type(), elf::GNU_PROPERTY_X86_FEATURE_1_AND); | |
283 | assert_eq!( | |
284 | prop.data_u32(endian).unwrap(), | |
285 | elf::GNU_PROPERTY_X86_FEATURE_1_IBT | elf::GNU_PROPERTY_X86_FEATURE_1_SHSTK | |
286 | ); | |
287 | assert!(props.next().unwrap().is_none()); | |
288 | assert!(notes.next().unwrap().is_none()); | |
289 | } |