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
open Basic_types.Integers
module Map = Basic_types.Integers.Int.Map
type entry =
| Entry of {
offset : int;
addresses : Virtual_address.t Interval.t;
expr : Expr.t;
}
| Eol of int
type t = entry list
let pp =
let columns =
[|
Prettytbl.Column.default;
Prettytbl.Column.default;
Prettytbl.Column.default;
Prettytbl.Column.default;
|]
in
fun ppf (isa, l) ->
Format.pp_open_vbox ppf 0;
let t = Prettytbl.make columns in
Prettytbl.append t [| "Offset"; "Begin"; "End"; "Expression" |];
List.iter
(function
| Entry { offset; addresses = { lo; hi }; expr } ->
Prettytbl.append t
[|
Format.sprintf "%08x" offset;
Utils.addr_to_string isa lo;
Utils.addr_to_string isa hi;
Format.asprintf "%a" Expr.pp expr;
|]
| Eol offset ->
Prettytbl.append t
[| Format.sprintf "%08x" offset; "<End of list>"; ""; "" |])
l;
Prettytbl.pp ppf t;
Format.pp_close_box ppf ()
let load img : t Map.t =
let isa = Loader.Img.arch img in
match Loader_utils.find_section_by_name ".debug_loc" img with
| exception Not_found -> Map.empty
| section ->
let bits =
match Machine.ISA.bits isa with
| `x32 -> `x32
| `x64 -> `x64
| _ -> assert false
in
let at = (Loader.Section.pos section).raw in
let length = (Loader.Section.size section).raw in
let cursor = Reader.Read.sub (Loader.Img.cursor ~at img) length in
let rec loop isa rev_entries cursor =
if Reader.at_end cursor then rev_entries
else
let offset = Reader.get_pos cursor in
let lo = Utils.read_addr isa cursor in
if Utils.is_max_addr isa lo then
Logger.fatal "Unsuported base address selection entry"
else
let hi = Utils.read_addr isa cursor in
if
Virtual_address.equal lo Virtual_address.zero
&& Virtual_address.equal hi Virtual_address.zero
then loop isa (Eol offset :: rev_entries) cursor
else
let size = Uint16.to_int (Reader.Read.u16 cursor) in
let expr = Expr.load isa bits size cursor in
loop isa
(Entry { offset; addresses = { lo; hi }; expr } :: rev_entries)
cursor
in
let rev_entries = loop isa [] cursor in
let rec loop rev_entries entries links =
match rev_entries with
| [] -> links
| (Entry { offset; _ } as e) :: rev_entries
| (Eol offset as e) :: rev_entries ->
let entries = e :: entries in
loop rev_entries entries (Map.add offset entries links)
in
loop rev_entries [] Map.empty