Skip to content

Commit

Permalink
fixes the base calculation
Browse files Browse the repository at this point in the history
1. For ELF files we compute base as the difference between the address of
any loadable code segment and its offset. If there are no loadable code
segments, then we find a section with minimal offset value and
substract its address from its offset.

2. For MachO, when the file is relocatable, i.e., it doesn't have addresses we
compute base as $vaddr - offset$, the same as we do in ELF. This
gives us results that match objdump (but do not match radare2, however
radare2 is not seeing any symbols, so it doesn't really matter)

3. For COFF nothing is done, and I am not sure that we need
to do anything.

4. Removed special computation of the base
address (Base.from_sections_offset) from ELF, MachO, and COFF.

It is not tested on LLVM versions below 6, but I believe it should
work up to 3.4.

resolves #1183

Co-authored-by: gitoleg <forown@yandex.ru>
  • Loading branch information
ivg and gitoleg committed Jul 24, 2020
1 parent 4d756d3 commit 161c0b4
Show file tree
Hide file tree
Showing 12 changed files with 116 additions and 187 deletions.
8 changes: 3 additions & 5 deletions lib/bap_llvm/bap_llvm_ogre_coff.ml
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,8 @@ module Relocatable = struct
module Make(Fact : Ogre.S) = struct
open Fact.Syntax

module Base = Base_address(Fact)

let segments =
Base.from_sections_offset >>= fun base ->
Fact.require base_address >>= fun base ->
Fact.foreach Ogre.Query.(
select (from section_entry
$ virtual_section_header
Expand All @@ -75,7 +73,7 @@ module Relocatable = struct
Fact.provide mapped addr size start)

let sections =
Base.from_sections_offset >>= fun base ->
Fact.require base_address >>= fun base ->
Fact.foreach Ogre.Query.(
select (from section_entry))
~f:(fun (name,_,size,off) -> name,off,size) >>= fun s ->
Expand All @@ -86,7 +84,7 @@ module Relocatable = struct
Fact.provide named_region addr size name)

let code_regions =
Base.from_sections_offset >>= fun base ->
Fact.require base_address >>= fun base ->
Fact.foreach Ogre.Query.(
select (from section_entry $ code_entry)
~join:[[field name];
Expand Down
4 changes: 1 addition & 3 deletions lib/bap_llvm/bap_llvm_ogre_elf.ml
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,8 @@ module Relocatable = struct
module Make(Fact : Ogre.S) = struct
open Fact.Syntax

module Base = Base_address(Fact)

let segments =
Base.from_sections_offset >>= fun base ->
Fact.require base_address >>= fun base ->
Fact.foreach Ogre.Query.(begin
select (from section_entry $ section_flags)
~join:[[field name]]
Expand Down
11 changes: 1 addition & 10 deletions lib/bap_llvm/bap_llvm_ogre_loader.ml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ module type Parameters = sig
val pdb_path : string
end

(** default image base for relocatable files *)
let relocatable_base = 0x0L

module Fact(M : Monad.S) = struct
include Ogre.Make(M)
type 'a m = 'a M.t
Expand Down Expand Up @@ -53,15 +50,9 @@ module Ogre_loader(P : Parameters) = struct
| Macho -> make (module Macho)
| Unknown -> Fact.failf "file type is not supported" ()

let image_base =
Fact.require is_relocatable >>= fun is_rel ->
if Option.is_none P.image_base && is_rel
then Fact.return (Some relocatable_base)
else Fact.return P.image_base

let provide_base =
Fact.require default_base_address >>= fun real ->
image_base >>= function
match P.image_base with
| None -> Fact.provide base_address real
| Some base ->
let base_bias = Int64.(base - real) in
Expand Down
4 changes: 1 addition & 3 deletions lib/bap_llvm/bap_llvm_ogre_macho.ml
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,8 @@ module Relocatable = struct
module Make(Fact : Ogre.S) = struct
open Fact.Syntax

module Base = Base_address(Fact)

let segments =
Base.from_sections_offset >>= fun base ->
Fact.require base_address >>= fun base ->
Fact.foreach Ogre.Query.(begin
select (from section_entry $ code_entry)
~join:[[field name];
Expand Down
32 changes: 4 additions & 28 deletions lib/bap_llvm/bap_llvm_ogre_samples.ml
Original file line number Diff line number Diff line change
Expand Up @@ -36,34 +36,11 @@ module Sections(Fact : Ogre.S) = struct
Fact.provide named_region addr size name)
end


module Base_address(Fact : Ogre.S) = struct
open Scheme
open Fact.Syntax

let from_sections_offset =
Fact.require base_address >>= fun base ->
Fact.foreach Ogre.Query.(begin
select (from section_entry $ code_entry)
~join:[[field name];
[field size ~from:section_entry;
field size ~from:code_entry]]
end)
~f:(fun (_,_,_,off) _ -> off) >>= fun s ->
match Seq.min_elt s ~compare:Int64.compare with
| None -> Fact.return base
| Some x -> Fact.return Int64.(base - x)

end

module Relocatable_symbols(Fact : Ogre.S) = struct
open Scheme
open Fact.Syntax

module Base = Base_address(Fact)

let relocations =
Base.from_sections_offset >>= fun base ->
Fact.require base_address >>= fun base ->
Fact.collect
Ogre.Query.(select (from ref_internal)) >>= fun ints ->
Fact.Seq.iter ints ~f:(fun (sym_off, rel_off) ->
Expand All @@ -72,7 +49,7 @@ module Relocatable_symbols(Fact : Ogre.S) = struct
Fact.provide relocation relocation_addr symbol_addr)

let externals =
Base.from_sections_offset >>= fun base ->
Fact.require base_address >>= fun base ->
Fact.collect
Ogre.Query.(select (from ref_external)) >>= fun exts ->
Fact.Seq.iter exts ~f:(fun (off, name) ->
Expand All @@ -81,7 +58,7 @@ module Relocatable_symbols(Fact : Ogre.S) = struct
let symbols =
relocations >>= fun () ->
externals >>= fun () ->
Base.from_sections_offset >>= fun base ->
Fact.require base_address >>= fun base ->
Fact.collect Ogre.Query.(select (from symbol_entry)) >>= fun s ->
Fact.Seq.iter s ~f:(fun (name, _, size, off) ->
if Int64.(size = 0L) then Fact.return ()
Expand All @@ -100,10 +77,9 @@ module Relocatable_sections(Fact : Ogre.S) = struct
open Scheme
open Fact.Syntax

module Base = Base_address(Fact)

let sections =
Base.from_sections_offset >>= fun base ->
Fact.require base_address >>= fun base ->
Fact.collect Ogre.Query.(select (from section_entry)) >>= fun s ->
Fact.Seq.iter s
~f:(fun (name, _, size, off) ->
Expand Down
4 changes: 0 additions & 4 deletions lib/bap_llvm/bap_llvm_ogre_samples.mli
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,3 @@ end
module Code_regions(Fact : Ogre.S) : sig
val code_regions : unit Fact.t
end

module Base_address(Fact : Ogre.S) : sig
val from_sections_offset : int64 Fact.t
end
13 changes: 6 additions & 7 deletions lib/bap_llvm/llvm_coff_loader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void section(const coff_section &sec, uint64_t image_base, ogre_doc &s) {
s.entry("code-entry") << sec.Name << sec.PointerToRawData << sec.SizeOfRawData;
}

void symbol(const std::string &name, int64_t relative_addr, uint64_t size, uint64_t off, SymbolRef::Type typ, ogre_doc &s) {
void symbol(const std::string &name, uint64_t relative_addr, uint64_t size, uint64_t off, SymbolRef::Type typ, ogre_doc &s) {
s.entry("symbol-entry") << name << relative_addr << size << off;
if (typ == SymbolRef::ST_Function)
s.entry("code-entry") << name << off << size;
Expand All @@ -51,7 +51,7 @@ error_or<uint64_t> symbol_file_offset(const coff_obj &obj, const SymbolRef &sym)
const coff_section* get_coff_section(const coff_obj &obj, const SectionRef &sec);
error_or<int> section_number(const coff_obj &obj, const SymbolRef &sym);
error_or<uint64_t> symbol_value(const coff_obj &obj, const SymbolRef &sym);
error_or<int64_t> symbol_relative_address(const coff_obj &obj, const SymbolRef &sym);
error_or<uint64_t> symbol_relative_address(const coff_obj &obj, const SymbolRef &sym);

const coff_section * get_coff_section(const coff_obj &obj, std::size_t index) {
const coff_section *sec = nullptr;
Expand Down Expand Up @@ -249,12 +249,11 @@ void exported_symbols(const coff_obj &obj, ogre_doc &s) {
#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR == 8 \
|| LLVM_VERSION_MAJOR >= 4

error_or<int64_t> symbol_relative_address(const coff_obj &obj, const SymbolRef &sym) {
error_or<uint64_t> symbol_relative_address(const coff_obj &obj, const SymbolRef &sym) {
auto base = obj.getImageBase();
auto addr = symbol_address(obj, sym);
if (!addr) return addr;
auto raddr = prim::relative_address(base, *addr);
return success(raddr);
return success(*addr - base);
}

error_or<int> section_number(const coff_obj &obj, const SymbolRef &s) {
Expand Down Expand Up @@ -305,10 +304,10 @@ error_or<uint64_t> get_image_base(const coff_obj &obj) {
#elif LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR == 4

// symbol address for 3.4 is already relative, i.e. doesn't include image base
error_or<int64_t> symbol_relative_address(const coff_obj &obj, const SymbolRef &sym) {
error_or<uint64_t> symbol_relative_address(const coff_obj &obj, const SymbolRef &sym) {
auto addr = symbol_address(obj, sym);
if (!addr) return addr;
else return success(int64_t(*addr));
else return success(uint64_t(*addr));
}

bool is_relocatable(const coff_obj &obj) {
Expand Down
Loading

0 comments on commit 161c0b4

Please sign in to comment.