package binsec

  1. Overview
  2. Docs

doc/src/binsec.dwarf/loclist.ml.html

Source file loclist.ml

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
(**************************************************************************)
(*  This file is part of BINSEC.                                          *)
(*                                                                        *)
(*  Copyright (C) 2016-2026                                               *)
(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
(*         alternatives)                                                  *)
(*                                                                        *)
(*  you can redistribute it and/or modify it under the terms of the GNU   *)
(*  Lesser General Public License as published by the Free Software       *)
(*  Foundation, version 2.1.                                              *)
(*                                                                        *)
(*  It is distributed in the hope that it will be useful,                 *)
(*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *)
(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *)
(*  GNU Lesser General Public License for more details.                   *)
(*                                                                        *)
(*  See the GNU Lesser General Public License version 2.1                 *)
(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
(*                                                                        *)
(**************************************************************************)

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