Skip to content

Commit 856edb2

Browse files
authored
adds is-executable and format attributes and fixes glibc rt check (#1198)
We are not using is-executable for the glibc runtime check though, as we have a more precise check now - we can look for the name reference of __libc_start_main and if it is there insert it. fixes #1130
1 parent 27a7a5d commit 856edb2

17 files changed

+141
-79
lines changed

lib/bap/bap.mli

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5606,12 +5606,26 @@ module Std : sig
56065606
val bits : (size, (size -> 'a) -> 'a) Ogre.attribute
56075607

56085608

5609-
(** [is_little_endian yes-or-no] is [true] if the target is
5610-
little endian.
5609+
(** [(format X)] defines the file format to be X.
5610+
5611+
Currently supported formats:
5612+
- ["elf"];
5613+
- ["macho"];
5614+
- ["coff"]
5615+
*)
5616+
val format : (string, (string -> 'a) -> 'a) Ogre.attribute
5617+
5618+
5619+
(** (is-little-endian FLAG)] is set for files with words encoded in the
5620+
little-endian order.
56115621
56125622
@since 2.2.0 *)
56135623
val is_little_endian : (bool, (bool -> 'a) -> 'a) Ogre.attribute
56145624

5625+
(** [(is-executable FLAG)] is set for binaries that executable.
5626+
5627+
@since 2.2.0 *)
5628+
val is_executable : (bool, (bool -> 'a) -> 'a) Ogre.attribute
56155629

56165630
(** [bias offset] the value by which all addresses are biased
56175631
wrt to the real addresses in the binary.
@@ -9342,6 +9356,12 @@ module Std : sig
93429356
(** [arch project] reveals the architecture of a loaded file *)
93439357
val arch : t -> arch
93449358

9359+
9360+
(** [specification p] returns the specification of the binary.
9361+
9362+
@since 2.2.0*)
9363+
val specification : t -> Ogre.doc
9364+
93459365
val state : t -> state
93469366

93479367

lib/bap/bap_project.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ module Spec = struct
7979
let statements = Ogre.all [
8080
Ogre.provide Field.arch (Arch.to_string arch);
8181
Ogre.provide Field.bits bits;
82+
Ogre.provide Field.format "raw";
8283
Ogre.provide Field.is_little_endian @@
8384
match Arch.endian arch with
8485
| LittleEndian -> true
@@ -168,6 +169,7 @@ type state = State.t [@@deriving bin_io]
168169

169170
type t = {
170171
arch : arch;
172+
spec : Ogre.doc;
171173
core : State.t;
172174
disasm : disasm;
173175
memory : value memmap;
@@ -370,6 +372,7 @@ let create
370372
let cfg,symbols,core = State.Toplevel.run spec arch ~code ~data file state in
371373
Result.return @@ finish {
372374
core;
375+
spec;
373376
disasm = Disasm.create cfg;
374377
program = Program.lift symbols;
375378
symbols;
@@ -386,6 +389,8 @@ let create
386389
Error (to_info msg)
387390
| exn -> Or_error.of_exn ~backtrace:`Get exn
388391

392+
let specification = spec
393+
389394
let restore_state _ =
390395
failwith "Project.restore_state: this function should no be used.
391396
Please use the Toplevel module to save/restore the state."

lib/bap/bap_project.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ val create :
3030
input -> t Or_error.t
3131

3232
val arch : t -> arch
33+
val specification : t -> Ogre.doc
3334
val program : t -> program term
3435
val with_program : t -> program term -> t
3536
val symbols : t -> symtab

lib/bap_core_theory/bap_core_theory.mli

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,13 @@ module Theory : sig
11601160
val path : (cls, string option) KB.slot
11611161

11621162

1163+
(** [format] the file format of the unit, e.g., ["elf"].*)
1164+
val format : (cls, string option) KB.slot
1165+
1166+
(** [is-executed] is true if the unit is an executable file ready
1167+
to be executed by the operating system. *)
1168+
val is_executable : (cls, bool option) KB.slot
1169+
11631170
(** [bias] is the bias of all addresses in the unit.
11641171
11651172
If a unit is biased, then all addresses in this unit have

lib/bap_core_theory/bap_core_theory_program.ml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ let path = Knowledge.Domain.optional "path"
2626
~equal:String.equal
2727
~inspect:sexp_of_string
2828

29+
let format = Knowledge.Domain.optional "path"
30+
~equal:String.equal
31+
~inspect:sexp_of_string
32+
2933
let names = Knowledge.Domain.powerset (module String) "names"
3034
~inspect:sexp_of_string
3135

@@ -52,7 +56,20 @@ module Unit = struct
5256
~desc:"a unit of code"
5357

5458
let path = string_property ~domain:path cls "unit-path"
55-
~desc:"a filesytem name of the file that contains the program"
59+
~desc:"a filesystem name of the file that contains the program"
60+
61+
let format = string_property ~domain:format cls "unit-format"
62+
~desc:"the file format that used to encode the unit"
63+
64+
let is_executable =
65+
Knowledge.Class.property ~package cls "unit-is-executable"
66+
Knowledge.Domain.bool
67+
~persistent:(Knowledge.Persistent.of_binable (module struct
68+
type t = bool option [@@deriving bin_io]
69+
end))
70+
~public:true
71+
~desc:"whether the unit is ready to be executed by the OS"
72+
5673

5774
let bias = Knowledge.Class.property ~package cls "unit-bias" word
5875
~persistent:(Knowledge.Persistent.of_binable (module struct

lib/bap_core_theory/bap_core_theory_program.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ module Unit : sig
3030
val for_region : lower:Bitvec.t -> upper:Bitvec.t -> t knowledge
3131

3232
val path : (cls, string option) slot
33+
val format : (cls, string option) slot
34+
val is_executable : (cls, bool option) slot
3335
val bias : (cls, Bitvec.t option) slot
3436

3537
module Target : sig

lib/bap_image/bap_image.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,11 @@ module Scheme = struct
356356
let subarch () = declare "subarch" (scheme name) ident
357357
let vendor () = declare "vendor" (scheme name) ident
358358
let system () = declare "system" (scheme name) ident
359+
let format () = declare "format" (scheme name) ident
359360
let abi () = declare "abi" (scheme name) ident
360361
let bits () = declare "bits" (scheme size) ident
361-
let is_little_endian () = declare "is_little_endian" (scheme flag) ident
362+
let is_little_endian () = declare "is-little-endian" (scheme flag) ident
363+
let is_executable () = declare "is-executable" (scheme flag) ident
362364
let bias () = declare "bias" (scheme off) ident
363365
let section () = declare "section" (location ()) void_region
364366
let code_start () = declare "code-start" (scheme addr) ident

lib/bap_image/bap_image.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,13 @@ module Scheme : sig
9797

9898
val arch : (string, (string -> 'a) -> 'a) Ogre.attribute
9999
val subarch : (string, (string -> 'a) -> 'a) Ogre.attribute
100+
val format : (string, (string -> 'a) -> 'a) Ogre.attribute
100101
val vendor : (string, (string -> 'a) -> 'a) Ogre.attribute
101102
val system : (string, (string -> 'a) -> 'a) Ogre.attribute
102103
val abi : (string, (string -> 'a) -> 'a) Ogre.attribute
103104
val bits : (size, (size -> 'a) -> 'a) Ogre.attribute
104105
val is_little_endian : (bool, (bool -> 'a) -> 'a) Ogre.attribute
106+
val is_executable : (bool, (bool -> 'a) -> 'a) Ogre.attribute
105107

106108
val bias : (off, (off -> 'a) -> 'a) Ogre.attribute
107109
val segment : ((bool * bool * bool) region,

lib/bap_llvm/bap_llvm_loader.ml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ module LLVM = struct
3232

3333
let at = "at" %: int
3434

35-
let file_type () =
36-
Ogre.declare ~name:"llvm:file-type" (scheme name) ident
37-
3835
(** entry point *)
3936
let entry_point () =
4037
Ogre.declare ~name:"llvm:entry-point" (scheme addr) ident
@@ -293,7 +290,7 @@ let provide_coff_segmentation = [
293290
]
294291

295292
let overload file_type info =
296-
Ogre.require LLVM.file_type >>= fun file ->
293+
Ogre.require format >>= fun file ->
297294
Ogre.sequence @@
298295
provide_if (String.equal file file_type) info
299296

lib/bap_llvm/llvm_coff_loader.hpp

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,51 @@ void emit_base_address(const coff_obj &obj, ogre_doc &s) {
5757
s.entry("llvm:base-address") << obj.getImageBase();
5858
}
5959

60+
#if LLVM_VERSION_MAJOR >= 10
61+
62+
error_or<pe32_header> get_pe32_header(const COFFObjectFile &obj) {
63+
const pe32_header *hdr = obj.getPE32Header();
64+
if (!hdr) { return failure("PE header not found"); }
65+
else return success(*hdr);
66+
}
67+
68+
error_or<pe32plus_header> get_pe32plus_header(const COFFObjectFile &obj) {
69+
const pe32plus_header *hdr = obj.getPE32PlusHeader();
70+
if (!hdr) { return failure("PE+ header not found"); }
71+
else return success(*hdr);
72+
}
73+
74+
#else
75+
76+
error_or<pe32_header> get_pe32_header(const COFFObjectFile &obj) {
77+
const pe32_header *hdr = 0;
78+
auto ec = obj.getPE32Header(hdr);
79+
if (ec) return failure(ec.message());
80+
else if (!hdr) { return failure("PE header not found"); }
81+
else return success(*hdr);
82+
}
83+
84+
error_or<pe32plus_header> get_pe32plus_header(const COFFObjectFile &obj) {
85+
const pe32plus_header *hdr = 0;
86+
auto ec = obj.getPE32PlusHeader(hdr);
87+
if (ec) return failure(ec.message());
88+
else if (!hdr) { return failure("PE+ header not found"); }
89+
else return success(*hdr);
90+
}
91+
#endif
92+
93+
bool is_executable(const COFFObjectFile &obj) {
94+
return obj.getCharacteristics() & COFF::IMAGE_FILE_EXECUTABLE_IMAGE;
95+
}
96+
97+
6098
void emit_entry_point(const coff_obj &obj, ogre_doc &s) {
6199
auto entry = 0L;
62100
if (obj.getBytesInAddress() == 4) {
63-
if (auto hdr = prim::get_pe32_header(obj))
101+
if (auto hdr = get_pe32_header(obj))
64102
entry = hdr->AddressOfEntryPoint;
65103
} else {
66-
if (auto hdr = prim::get_pe32plus_header(obj))
104+
if (auto hdr = get_pe32plus_header(obj))
67105
entry = hdr->AddressOfEntryPoint;
68106
}
69107
s.entry("llvm:entry-point") << entry + obj.getImageBase();
@@ -268,7 +306,8 @@ error_or<uint64_t> symbol_file_offset(const coff_obj &obj, const SymbolRef &sym)
268306

269307
error_or<std::string> load(ogre_doc &s, const llvm::object::COFFObjectFile &obj, const char* pdb_path) {
270308
using namespace coff_loader;
271-
s.raw_entry("(llvm:file-type coff)");
309+
s.raw_entry("(format coff)");
310+
s.entry("is-executable") << is_executable(obj);
272311
emit_base_address(obj, s);
273312
emit_entry_point(obj, s);
274313
emit_sections(obj, s);

0 commit comments

Comments
 (0)