-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathoc_objdump.ml
More file actions
131 lines (110 loc) · 4.11 KB
/
Copy pathoc_objdump.ml
File metadata and controls
131 lines (110 loc) · 4.11 KB
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
(** OCaml implementation of objdump for object files. Supports ELF, Mach-O, and
PE formats. Should be equivalent to objdump --section-headers <binaries> *)
let print_macho_summary file (header : Object.Macho.header) =
let open Object in
Printf.printf "\n%s:\tfile format mach-o %s\n\n" file
(Macho.cpu_type_to_string header.cpu_type)
let print_pe_summary file (pe_obj : Object.Pe.pe_object) =
let open Object in
let format_str = if Pe.is_64bit pe_obj then "coff-x86-64" else "coff-i386" in
Printf.printf "\n%s:\tfile format %s\n\n" file format_str
let print_macho_sections file =
let open Printf in
let open Object in
let buffer = Buffer.parse file in
let header, commands = Macho.read buffer in
print_macho_summary file header;
printf "Sections:\n";
printf "%3s %-13s %-8s %-16s %s\n" "Idx" "Name" "Size" "VMA" "Type";
let section_index = ref 0 in
let print_section (_segment : Macho.segment) (section : Macho.section) =
let section_type =
if section.sec_segname = "__TEXT" then "TEXT" else "DATA"
in
printf "%3i %-13s %08Lx %016Lx %s\n" !section_index section.sec_sectname
(Unsigned.UInt64.to_int64 section.sec_size)
(Unsigned.UInt64.to_int64 section.sec_addr)
section_type;
incr section_index
in
let process_segment = function
| Macho.LC_SEGMENT_64 segment | Macho.LC_SEGMENT_32 segment ->
let (lazy segment) = segment in
Array.iter (print_section segment) segment.Macho.seg_sections
| _ -> ()
in
List.iter process_segment commands
let print_pe_sections file =
let open Printf in
let open Object in
let buffer = Buffer.parse file in
let pe_obj = Pe.read buffer in
print_pe_summary file pe_obj;
printf "Sections:\n";
printf "%3s %-13s %-8s %-16s %s\n" "Idx" "Name" "Size" "VMA" "Type";
let sections = pe_obj.Pe.section_headers in
let image_base =
match pe_obj.optional_header with
| Some opt -> opt.image_base
| None -> Unsigned.UInt64.zero
in
Array.iteri
(fun i section ->
(* Get section name *)
let name = section.Pe.name in
let clean_name =
if String.length name = 0 then sprintf ".sec%d" i else name
in
(* Use virtual_size if size_of_raw_data is 0 (like for .bss) *)
let size =
let raw_size = Unsigned.UInt32.to_int64 section.Pe.size_of_raw_data in
if raw_size = 0L then Unsigned.UInt32.to_int64 section.Pe.virtual_size
else raw_size
in
(* Calculate proper VMA by adding image_base to virtual_address *)
let vma =
Unsigned.UInt64.add image_base
(Unsigned.UInt64.of_int
(Unsigned.UInt32.to_int section.Pe.virtual_address))
in
let vma_int64 = Unsigned.UInt64.to_int64 vma in
let section_type =
Pe.section_characteristics_to_type_string section.Pe.characteristics
in
printf "%3i %-13s %08Lx %016Lx %s\n" i clean_name size vma_int64
section_type)
sections
let print_section_headers file =
let open Object in
let buffer = Buffer.parse file in
if Pe.is_pe buffer then print_pe_sections file
else
try
(* Try to read as Mach-O *)
let _ = Macho.read buffer in
print_macho_sections file
with _ -> Printf.printf "Error: Unsupported file format for %s\n" file
let run section_headers files () =
match section_headers with
| true -> List.iter print_section_headers files
| false ->
Printf.printf
"Section headers flag required please call with `-h` or \
`--section-headers`.\n";
exit 2
open Cmdliner
let section_headers =
(* Documentation string *)
let doc = "Display summaries of the headers for each section." in
(* Add both -h and --section-headers options *)
let info = Arg.(info [ "h"; "section-headers" ] ~doc) in
Arg.value (Arg.flag info)
let files =
let doc = "Object FILEs to read." in
Arg.(non_empty & pos_all file [] & info [] ~docv:"FILE" ~doc)
let section_headers_t = Term.(const run $ section_headers $ files $ const ())
let cmd =
let doc = "OCaml object file dumper." in
let info = Cmd.info "objdump" ~doc in
Cmd.v info section_headers_t
let () = exit @@ Cmd.eval ~catch:true cmd