1 use object
::read
::archive
::ArchiveFile
;
2 use object
::read
::macho
::{DyldCache, FatArch, FatHeader}
;
3 use object
::{Endianness, Object, ObjectComdat, ObjectSection, ObjectSymbol}
;
4 use std
::{env, fs, process}
;
7 let mut args
= env
::args();
8 let cmd
= args
.next().unwrap();
10 eprintln
!("Usage: {} <file> [<member>...]", cmd
);
13 let file_path
= args
.next().unwrap();
14 let mut member_names
: Vec
<_
> = args
.map(|name
| (name
, false)).collect();
16 let file
= match fs
::File
::open(&file_path
) {
19 eprintln
!("Failed to open file '{}': {}", file_path
, err
,);
23 let file
= match unsafe { memmap2::Mmap::map(&file) }
{
26 eprintln
!("Failed to map file '{}': {}", file_path
, err
,);
31 if let Ok(archive
) = ArchiveFile
::parse(&*file
) {
32 eprintln
!("Format: Archive (kind: {:?})", archive
.kind());
33 for member
in archive
.members() {
34 if let Ok(member
) = member
{
35 if find_member(&mut member_names
, member
.name()) {
37 println
!("{}:", String
::from_utf8_lossy(member
.name()));
38 if let Ok(data
) = member
.data(&*file
) {
44 } else if let Ok(arches
) = FatHeader
::parse_arch32(&*file
) {
45 println
!("Format: Mach-O Fat 32");
48 println
!("Fat Arch: {:?}", arch
.architecture());
49 if let Ok(data
) = arch
.data(&*file
) {
53 } else if let Ok(arches
) = FatHeader
::parse_arch64(&*file
) {
54 println
!("Format: Mach-O Fat 64");
57 println
!("Fat Arch: {:?}", arch
.architecture());
58 if let Ok(data
) = arch
.data(&*file
) {
62 } else if let Ok(cache
) = DyldCache
::<Endianness
>::parse(&*file
) {
63 println
!("Format: dyld cache {:?}-endian", cache
.endianness());
64 println
!("Architecture: {:?}", cache
.architecture());
65 for image
in cache
.images() {
66 if let Ok(path
) = image
.path() {
67 if find_member(&mut member_names
, path
.as_bytes()) {
69 println
!("{}:", path
);
70 let file
= match image
.parse_object() {
73 eprintln
!("Failed to parse file: {}", err
);
77 dump_parsed_object(&file
);
85 for (name
, found
) in member_names
{
87 eprintln
!("Failed to find member '{}", name
);
92 fn find_member(member_names
: &mut [(String
, bool
)], name
: &[u8]) -> bool
{
93 if member_names
.is_empty() {
96 match member_names
.iter().position(|x
| x
.0.as_bytes() == name
) {
98 member_names
[i
].1 = true;
105 fn dump_object(data
: &[u8]) {
106 let file
= match object
::File
::parse(data
) {
109 println
!("Failed to parse file: {}", err
);
113 dump_parsed_object(&file
);
116 fn dump_parsed_object(file
: &object
::File
) {
118 "Format: {:?} {:?}-endian {}-bit",
121 if file
.is_64() { "64" }
else { "32" }
123 println
!("Architecture: {:?}", file
.architecture());
124 println
!("Flags: {:x?}", file
.flags());
125 println
!("Relative Address Base: {:x?}", file
.relative_address_base());
126 println
!("Entry Address: {:x?}", file
.entry());
128 match file
.mach_uuid() {
129 Ok(Some(uuid
)) => println
!("Mach UUID: {:x?}", uuid
),
131 Err(e
) => println
!("Failed to parse Mach UUID: {}", e
),
133 match file
.build_id() {
134 Ok(Some(build_id
)) => println
!("Build ID: {:x?}", build_id
),
136 Err(e
) => println
!("Failed to parse build ID: {}", e
),
138 match file
.gnu_debuglink() {
139 Ok(Some((filename
, crc
))) => println
!(
140 "GNU debug link: {} CRC: {:08x}",
141 String
::from_utf8_lossy(filename
),
145 Err(e
) => println
!("Failed to parse GNU debug link: {}", e
),
147 match file
.gnu_debugaltlink() {
148 Ok(Some((filename
, build_id
))) => println
!(
149 "GNU debug alt link: {}, build ID: {:x?}",
150 String
::from_utf8_lossy(filename
),
154 Err(e
) => println
!("Failed to parse GNU debug alt link: {}", e
),
156 match file
.pdb_info() {
157 Ok(Some(info
)) => println
!(
158 "PDB file: {}, GUID: {:x?}, Age: {}",
159 String
::from_utf8_lossy(info
.path()),
164 Err(e
) => println
!("Failed to parse PE CodeView info: {}", e
),
167 for segment
in file
.segments() {
168 println
!("{:x?}", segment
);
171 for section
in file
.sections() {
172 println
!("{}: {:x?}", section
.index().0, section
);
175 for comdat
in file
.comdats() {
176 print
!("{:?} Sections:", comdat
);
177 for section
in comdat
.sections() {
178 print
!(" {}", section
.0);
185 for symbol
in file
.symbols() {
186 println
!("{}: {:x?}", symbol
.index().0, symbol
);
189 for section
in file
.sections() {
190 if section
.relocations().next().is_some() {
193 section
.name().unwrap_or("<invalid name>")
195 for relocation
in section
.relocations() {
196 println
!("{:x?}", relocation
);
202 println
!("Dynamic symbols");
203 for symbol
in file
.dynamic_symbols() {
204 println
!("{}: {:x?}", symbol
.index().0, symbol
);
207 if let Some(relocations
) = file
.dynamic_relocations() {
209 println
!("Dynamic relocations");
210 for relocation
in relocations
{
211 println
!("{:x?}", relocation
);
215 let imports
= file
.imports().unwrap();
216 if !imports
.is_empty() {
218 for import
in imports
{
219 println
!("{:?}", import
);
223 let exports
= file
.exports().unwrap();
224 if !exports
.is_empty() {
226 for export
in exports
{
227 println
!("{:x?}", export
);