1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#![deny(missing_docs)]
extern crate goblin;
use goblin::{elf, mach};
use std::io::Cursor;
pub struct File<'a> {
kind: ObjectKind<'a>,
data: &'a [u8],
}
enum ObjectKind<'a> {
Elf(elf::Elf<'a>),
MachO(mach::MachO<'a>),
}
impl<'a> File<'a> {
pub fn parse(data: &'a [u8]) -> Result<Self, &'static str> {
let mut cursor = Cursor::new(data);
let kind = match goblin::peek(&mut cursor)
.map_err(|_| "Could not parse file magic")? {
goblin::Hint::Elf(_) => {
let elf = elf::Elf::parse(data)
.map_err(|_| "Could not parse ELF header")?;
ObjectKind::Elf(elf)
}
goblin::Hint::Mach(_) => {
let macho = mach::MachO::parse(data, 0)
.map_err(|_| "Could not parse Mach-O header")?;
ObjectKind::MachO(macho)
}
_ => return Err("Unknown file magic"),
};
Ok(File { kind, data })
}
pub fn get_section(&self, section_name: &str) -> Option<&[u8]> {
match self.kind {
ObjectKind::Elf(ref elf) => elf_get_section(elf, section_name, self.data),
ObjectKind::MachO(ref macho) => macho_get_section(macho, section_name),
}
}
pub fn is_little_endian(&self) -> bool {
match self.kind {
ObjectKind::Elf(ref elf) => elf.little_endian,
ObjectKind::MachO(ref macho) => macho.header.is_little_endian(),
}
}
}
fn elf_get_section<'a>(elf: &elf::Elf<'a>, section_name: &str, data: &'a [u8]) -> Option<&'a [u8]> {
for header in &elf.section_headers {
if let Ok(name) = elf.shdr_strtab.get(header.sh_name) {
if name == section_name {
return Some(&data[header.sh_offset as usize..][..header.sh_size as usize]);
}
}
}
None
}
fn macho_get_section<'a>(macho: &mach::MachO<'a>, section_name: &str) -> Option<&'a [u8]> {
let segment_name = "__DWARF";
let section_name = macho_translate_section_name(section_name);
for segment in &*macho.segments {
if let Ok(name) = segment.name() {
if name == segment_name {
if let Ok(sections) = segment.sections() {
for section in sections {
if let Ok(name) = section.name() {
if name.as_bytes() == &*section_name {
return Some(section.data);
}
}
}
}
}
}
}
None
}
fn macho_translate_section_name(section_name: &str) -> Vec<u8> {
let mut name = Vec::with_capacity(section_name.len() + 1);
name.push(b'_');
name.push(b'_');
for ch in §ion_name.as_bytes()[1..] {
name.push(*ch);
}
name
}
#[doc(hidden)]
#[deprecated]
pub trait Object {}