Fix performances issues

Fix #94
This commit is contained in:
Romain Thomas 2017-09-20 07:48:02 +02:00
parent acc35aa7e5
commit accf47ebf2
29 changed files with 567 additions and 366 deletions

View File

@ -102,6 +102,11 @@ void init_MachO_Binary_class(py::module& m) {
"Return the " RST_CLASS_REF(lief.MachO.Section) " which contains the offset", "Return the " RST_CLASS_REF(lief.MachO.Section) " which contains the offset",
py::return_value_policy::reference) py::return_value_policy::reference)
.def("section_from_virtual_address",
static_cast<Section& (Binary::*)(uint64_t)>(&Binary::section_from_virtual_address),
"Return the " RST_CLASS_REF(lief.MachO.Section) " which contains the virtual address",
py::return_value_policy::reference)
.def("segment_from_offset", .def("segment_from_offset",
static_cast<SegmentCommand& (Binary::*)(uint64_t)>(&Binary::segment_from_offset), static_cast<SegmentCommand& (Binary::*)(uint64_t)>(&Binary::segment_from_offset),
"Return the " RST_CLASS_REF(lief.MachO.SegmentCommand) " which contains the offset", "Return the " RST_CLASS_REF(lief.MachO.SegmentCommand) " which contains the offset",
@ -109,7 +114,7 @@ void init_MachO_Binary_class(py::module& m) {
.def("segment_from_virtual_address", .def("segment_from_virtual_address",
static_cast<SegmentCommand& (Binary::*)(uint64_t)>(&Binary::segment_from_virtual_address), static_cast<SegmentCommand& (Binary::*)(uint64_t)>(&Binary::segment_from_virtual_address),
"Return the " RST_CLASS_REF(lief.MachO.SegmentCommand) " which contains the (relative) virtual address", "Return the " RST_CLASS_REF(lief.MachO.SegmentCommand) " which contains the virtual address",
py::return_value_policy::reference) py::return_value_policy::reference)
.def_property_readonly("has_entrypoint", .def_property_readonly("has_entrypoint",
@ -214,6 +219,16 @@ void init_MachO_Binary_class(py::module& m) {
"name"_a, "name"_a,
py::return_value_policy::reference) py::return_value_policy::reference)
.def_property_readonly("va_ranges",
&Binary::va_ranges,
"Return the range of virtual addresses as a tuple ``(va_start, va_end)``")
.def("is_valid_addr",
&Binary::is_valid_addr,
"Check if the given address is comprise between the lowest "
"virtual address and the biggest one",
"address"_a)
.def("__str__", .def("__str__",
[] (const Binary& binary) [] (const Binary& binary)

View File

@ -23,6 +23,7 @@ set(LIEF_MACHO_CPP_EXAMPLES
set(LIEF_CPP_EXAMPLES set(LIEF_CPP_EXAMPLES
abstract_reader.cpp abstract_reader.cpp
logging.cpp logging.cpp
benchmark.cpp
) )
if (LIEF_ELF) if (LIEF_ELF)

View File

@ -0,0 +1,42 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <iostream>
#include <chrono>
#include <LIEF/LIEF.hpp>
int main(int argc, char **argv) {
LIEF::Logger::set_level(LIEF::LOGGING_LEVEL::LOG_INFO);
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " <Binary>" << std::endl;
return EXIT_FAILURE;
}
std::chrono::time_point<std::chrono::system_clock> start, end;
start = std::chrono::system_clock::now();
const LIEF::Binary* binary = LIEF::Parser::parse(argv[1]);
end = std::chrono::system_clock::now();
delete binary;
size_t elapsed_seconds = std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
std::cout << "[Parser] Time: " << std::dec << elapsed_seconds << "s" << std::endl;
}

View File

@ -125,8 +125,8 @@ def print_segments(binary):
segment.name, segment.name,
segment.virtual_address, segment.virtual_address,
segment.virtual_size, segment.virtual_size,
segment.file_size,
segment.file_offset, segment.file_offset,
segment.file_size,
segment.max_protection, segment.max_protection,
segment.init_protection, segment.init_protection,
sections)) sections))
@ -425,7 +425,6 @@ def print_relocations(binary):
if reloc.has_section: if reloc.has_section:
secseg_name = reloc.section.name secseg_name = reloc.section.name
print(f_value.format( print(f_value.format(
address=reloc.address, address=reloc.address,
size=reloc.size, size=reloc.size,

View File

@ -51,8 +51,20 @@ class DLL_PUBLIC Relocation : public Visitable {
bool operator==(const Relocation& rhs) const; bool operator==(const Relocation& rhs) const;
bool operator!=(const Relocation& rhs) const; bool operator!=(const Relocation& rhs) const;
DLL_PUBLIC friend std::ostream& operator<<(std::ostream& os, const Relocation& entry);
//! @brief Comparaison based on the Relocation's **address**
bool operator<(const Relocation& rhs) const;
//! @brief Comparaison based on the Relocation's **address**
bool operator<=(const Relocation& rhs) const;
//! @brief Comparaison based on the Relocation's **address**
bool operator>(const Relocation& rhs) const;
//! @brief Comparaison based on the Relocation's **address**
bool operator>=(const Relocation& rhs) const;
DLL_PUBLIC friend std::ostream& operator<<(std::ostream& os, const Relocation& entry);
protected: protected:
uint64_t address_; uint64_t address_;
@ -60,5 +72,7 @@ class DLL_PUBLIC Relocation : public Visitable {
// type_; // type_;
}; };
} }
#endif #endif

View File

@ -49,7 +49,7 @@ class DLL_PUBLIC Builder {
void build(void); void build(void);
template<typename ELF_T> template<typename ELF_T>
void build_header(void); void build(const Header& header);
template<typename ELF_T> template<typename ELF_T>
void build_sections(void); void build_sections(void);

View File

@ -149,16 +149,16 @@ class DLL_PUBLIC Parser : public LIEF::Parser {
//! @brief Parse Dynamic relocations //! @brief Parse Dynamic relocations
//! //!
//! It use DT_REL/DT_RELA dynamic entries to parse it //! It use DT_REL/DT_RELA dynamic entries to parse it
template<typename ELF_T> template<typename ELF_T, typename REL_T>
void parse_dynamic_relocations(uint64_t relocations_offset, uint64_t size, bool isRela); void parse_dynamic_relocations(uint64_t relocations_offset, uint64_t size);
//! @brief Parse `.plt.got`/`got` relocations //! @brief Parse `.plt.got`/`got` relocations
//! //!
//! For: //! For:
//! * ELF32 it uses **DT_JMPREL** and **DT_PLTRELSZ** //! * ELF32 it uses **DT_JMPREL** and **DT_PLTRELSZ**
//! * ELF64 it uses **DT_PLTREL** and **DT_PLTRELSZ** //! * ELF64 it uses **DT_PLTREL** and **DT_PLTRELSZ**
template<typename ELF_T> template<typename ELF_T, typename REL_T>
void parse_pltgot_relocations(uint64_t offset, uint64_t size, bool isRela); void parse_pltgot_relocations(uint64_t offset, uint64_t size);
//! @brief Parse relocations using LIEF::ELF::Section. //! @brief Parse relocations using LIEF::ELF::Section.
@ -166,8 +166,8 @@ class DLL_PUBLIC Parser : public LIEF::Parser {
//! Parser::parse_dynamic_relocations and Parser::parse_pltgot_relocations //! Parser::parse_dynamic_relocations and Parser::parse_pltgot_relocations
//! use parse relocations by using LIEF::ELF::Segment. This method parse relocations //! use parse relocations by using LIEF::ELF::Segment. This method parse relocations
//! that are not reachable through segments (For example Object file). //! that are not reachable through segments (For example Object file).
template<typename ELF_T> template<typename ELF_T, typename REL_T>
void parse_section_relocations(uint64_t offset, uint64_t size, bool isRela); void parse_section_relocations(uint64_t offset, uint64_t size);
//! @brief Parse SymbolVersionRequirement //! @brief Parse SymbolVersionRequirement
//! //!

View File

@ -72,6 +72,8 @@ class DLL_PUBLIC Section : public LIEF::Section {
//! @brief Set section content //! @brief Set section content
virtual void content(const std::vector<uint8_t>& data) override; virtual void content(const std::vector<uint8_t>& data) override;
void content(std::vector<uint8_t>&& data);
//! @brief Section flags LIEF::ELF::ELF_SECTION_FLAGS //! @brief Section flags LIEF::ELF::ELF_SECTION_FLAGS
uint64_t flags(void) const; uint64_t flags(void) const;

View File

@ -80,6 +80,7 @@ class DLL_PUBLIC Segment : public Visitable {
void virtual_size(uint64_t virtualSize); void virtual_size(uint64_t virtualSize);
void alignment(uint64_t alignment); void alignment(uint64_t alignment);
void content(const std::vector<uint8_t>& content); void content(const std::vector<uint8_t>& content);
void content(std::vector<uint8_t>&& content);
it_sections sections(void); it_sections sections(void);
it_const_sections sections(void) const; it_const_sections sections(void) const;

View File

@ -142,10 +142,14 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
Section& section_from_offset(uint64_t offset); Section& section_from_offset(uint64_t offset);
const Section& section_from_offset(uint64_t offset) const; const Section& section_from_offset(uint64_t offset) const;
//! @brief Return binary's @link MachO::Section section @endlink
//! which holds the given virtual address
Section& section_from_virtual_address(uint64_t virtual_address);
const Section& section_from_virtual_address(uint64_t virtual_address) const;
//! @brief Convert a virtual address to an offset in the file //! @brief Convert a virtual address to an offset in the file
uint64_t virtual_address_to_offset(uint64_t virtualAddress) const; uint64_t virtual_address_to_offset(uint64_t virtualAddress) const;
// @brief Return binary's @link MachO::SegmentCommand segment command // @brief Return binary's @link MachO::SegmentCommand segment command
// which hold the offset // which hold the offset
SegmentCommand& segment_from_offset(uint64_t offset); SegmentCommand& segment_from_offset(uint64_t offset);
@ -159,6 +163,13 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
SegmentCommand& segment_from_virtual_address(uint64_t virtual_address); SegmentCommand& segment_from_virtual_address(uint64_t virtual_address);
const SegmentCommand& segment_from_virtual_address(uint64_t virtual_address) const; const SegmentCommand& segment_from_virtual_address(uint64_t virtual_address) const;
//! @brief Return the range of virtual addresses
std::pair<uint64_t, uint64_t> va_ranges(void) const;
//! @brief Check if the given address is comprise between the lowest
//! virtual address and the biggest one
bool is_valid_addr(uint64_t address) const;
//! @brief Method so that the ``visitor`` can visit us //! @brief Method so that the ``visitor`` can visit us
virtual void accept(LIEF::Visitor& visitor) const override; virtual void accept(LIEF::Visitor& visitor) const override;
@ -286,6 +297,9 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
commands_t commands_; commands_t commands_;
symbols_t symbols_; symbols_t symbols_;
// Cached relocations from segment / sections
mutable relocations_t relocations_;
protected: protected:
uint64_t fat_offset_ = 0; uint64_t fat_offset_ = 0;
}; };

View File

@ -104,7 +104,8 @@ class DLL_PUBLIC BinaryParser : public LIEF::Parser {
const std::string& symbol_name, const std::string& symbol_name,
int32_t ord, int32_t ord,
int64_t addend, int64_t addend,
bool is_weak); bool is_weak,
it_segments& segments);
template<class MACHO_T> template<class MACHO_T>

View File

@ -120,6 +120,8 @@ class DLL_PUBLIC Relocation : public LIEF::Relocation {
DLL_PUBLIC friend std::ostream& operator<<(std::ostream& os, const Relocation& relocation); DLL_PUBLIC friend std::ostream& operator<<(std::ostream& os, const Relocation& relocation);
protected: protected:
Symbol* symbol_; Symbol* symbol_;
uint8_t type_; uint8_t type_;

View File

@ -34,10 +34,12 @@ namespace MachO {
class BinaryParser; class BinaryParser;
class SegmentCommand; class SegmentCommand;
class Binary;
class DLL_PUBLIC Section : public LIEF::Section { class DLL_PUBLIC Section : public LIEF::Section {
friend class BinaryParser; friend class BinaryParser;
friend class Binary;
public: public:
Section(void); Section(void);

View File

@ -32,12 +32,14 @@
namespace LIEF { namespace LIEF {
namespace MachO { namespace MachO {
class BinaryParser; class BinaryParser;
class Binary;
//! @class SegmentCommand //! @class SegmentCommand
//! @brief Class which represent a MachO Segment //! @brief Class which represent a MachO Segment
class DLL_PUBLIC SegmentCommand : public LoadCommand { class DLL_PUBLIC SegmentCommand : public LoadCommand {
friend class BinaryParser; friend class BinaryParser;
friend class Binary;
public: public:
SegmentCommand(void); SegmentCommand(void);

View File

@ -16,7 +16,9 @@
#ifndef LIEF_MACHO_TYPE_TRAITS_H_ #ifndef LIEF_MACHO_TYPE_TRAITS_H_
#define LIEF_MACHO_TYPE_TRAITS_H_ #define LIEF_MACHO_TYPE_TRAITS_H_
#include <vector> #include <vector>
#include <set>
#include "LIEF/iterators.hpp" #include "LIEF/iterators.hpp"
#include "LIEF/Abstract/Relocation.hpp"
namespace LIEF { namespace LIEF {
namespace MachO { namespace MachO {
@ -30,6 +32,12 @@ class Relocation;
class BindingInfo; class BindingInfo;
class ExportInfo; class ExportInfo;
template<class T>
struct KeyCmp {
bool operator() (const T* lhs, const T* rhs) const { return *lhs < *rhs; };
};
using buffer_t = std::vector<uint8_t>; ///< Container used to store raw data using buffer_t = std::vector<uint8_t>; ///< Container used to store raw data
using commands_t = std::vector<LoadCommand*>; using commands_t = std::vector<LoadCommand*>;
@ -58,9 +66,9 @@ using sections_t = std::vector<Section*>;
using it_sections = ref_iterator<sections_t>; using it_sections = ref_iterator<sections_t>;
using it_const_sections = const_ref_iterator<sections_t>; using it_const_sections = const_ref_iterator<sections_t>;
using relocations_t = std::vector<Relocation*>; ///< Container used to store relocations using relocations_t = std::set<Relocation*, KeyCmp<Relocation>>; ///< Container used to store relocations
using it_relocations = ref_iterator<relocations_t>; ///< Iterator's type for relocations using it_relocations = ref_iterator<relocations_t&>; ///< Iterator's type for relocations
using it_const_relocations = const_ref_iterator<relocations_t>; ///< Iterator's type for relocations (const) using it_const_relocations = const_ref_iterator<const relocations_t&>; ///< Iterator's type for relocations (const)
using binding_info_t = std::vector<BindingInfo*>; ///< Container used to store BindinfInfo using binding_info_t = std::vector<BindingInfo*>; ///< Container used to store BindinfInfo
using it_binding_info = ref_iterator<binding_info_t>; ///< Iterator's type for binding_info_t using it_binding_info = ref_iterator<binding_info_t>; ///< Iterator's type for binding_info_t
@ -70,6 +78,7 @@ using export_info_t = std::vector<ExportInfo*>; ///< Conta
using it_export_info = ref_iterator<export_info_t>; ///< Iterator's type for export_info_t using it_export_info = ref_iterator<export_info_t>; ///< Iterator's type for export_info_t
using it_const_export_info = const_ref_iterator<export_info_t>; ///< Iterator's type for export_info_t (const) using it_const_export_info = const_ref_iterator<export_info_t>; ///< Iterator's type for export_info_t (const)
} }
} }

View File

@ -44,17 +44,18 @@ class ref_iterator : public std::iterator<
using DT = decay_t<T>; using DT = decay_t<T>;
ref_iterator(T container) : ref_iterator(T container) :
container_{std::forward<T>(container)} container_{std::forward<T>(container)},
distance_{0}
{ {
this->it_ = std::begin(container_); this->it_ = std::begin(container_);
} }
ref_iterator(const ref_iterator& copy) : ref_iterator(const ref_iterator& copy) :
container_{copy.container_}, container_{copy.container_},
it_{std::begin(container_)} it_{std::begin(container_)},
distance_{copy.distance_}
{ {
size_t d = std::distance(const_cast<ref_iterator&>(copy).container_.begin(), copy.it_); std::advance(this->it_, this->distance_);
std::advance(this->it_, d);
} }
@ -66,11 +67,13 @@ class ref_iterator : public std::iterator<
void swap(ref_iterator& other) { void swap(ref_iterator& other) {
std::swap(this->container_, other.container_); std::swap(this->container_, other.container_);
std::swap(this->it_, other.it_); std::swap(this->it_, other.it_);
std::swap(this->distance_, other.distance_);
} }
ref_iterator& operator++(void) { ref_iterator& operator++(void) {
it_++; this->it_ = std::next(this->it_);
this->distance_++;
return *this; return *this;
} }
@ -82,7 +85,8 @@ class ref_iterator : public std::iterator<
ref_iterator& operator--(void) { ref_iterator& operator--(void) {
if (this->it_ != std::begin(container_)) { if (this->it_ != std::begin(container_)) {
this->it_--; this->it_ = std::prev(this->it_);
this->distance_--;
} }
return *this; return *this;
} }
@ -96,6 +100,7 @@ class ref_iterator : public std::iterator<
ref_iterator& operator+=(const typename ref_iterator::difference_type& movement) { ref_iterator& operator+=(const typename ref_iterator::difference_type& movement) {
std::advance(this->it_, movement); std::advance(this->it_, movement);
this->distance_ += movement;
return *this; return *this;
} }
@ -145,7 +150,7 @@ class ref_iterator : public std::iterator<
typename ref_iterator::difference_type operator-(const ref_iterator& rhs) const { typename ref_iterator::difference_type operator-(const ref_iterator& rhs) const {
return std::distance(rhs, *this); return this->distance_ - rhs.distance_;
} }
bool operator<(const ref_iterator& rhs) const { bool operator<(const ref_iterator& rhs) const {
@ -168,19 +173,18 @@ class ref_iterator : public std::iterator<
} }
ref_iterator begin(void) { ref_iterator begin(void) {
return {this->container_}; return this->container_;
} }
ref_iterator end(void) { ref_iterator end(void) {
ref_iterator it = ref_iterator{this->container_}; ref_iterator it = ref_iterator{this->container_};
it.it_ = std::end(it.container_); it.it_ = std::end(it.container_);
it.distance_ = it.size();
return it; return it;
} }
bool operator==(const ref_iterator& other) const { bool operator==(const ref_iterator& other) const {
size_t d1 = static_cast<size_t>(std::distance(this->it_, const_cast<ref_iterator*>(this)->container_.end())); return (this->size() == other.size() and this->distance_ == other.distance_);
size_t d2 = static_cast<size_t>(std::distance(other.it_, const_cast<ref_iterator&>(other).container_.end()));
return (this->size() == other.size() and d1 == d2);
} }
bool operator!=(const ref_iterator& other) const { bool operator!=(const ref_iterator& other) const {
@ -225,6 +229,7 @@ class ref_iterator : public std::iterator<
private: private:
T container_; T container_;
typename DT::iterator it_; typename DT::iterator it_;
typename ref_iterator::difference_type distance_;
}; };
@ -239,11 +244,11 @@ class const_ref_iterator : public std::iterator<
const typename std::remove_pointer<typename decay_t<T>::value_type>::type*, const typename std::remove_pointer<typename decay_t<T>::value_type>::type*,
const typename std::remove_pointer<typename decay_t<T>::value_type>::type&> { const typename std::remove_pointer<typename decay_t<T>::value_type>::type&> {
public: public:
using DT = decay_t<CT>; using DT = decay_t<CT>;
const_ref_iterator(CT container) : const_ref_iterator(CT container) :
container_{std::forward<CT>(container)} container_{std::forward<CT>(container)},
distance_{0}
{ {
this->it_ = this->container_.cbegin(); this->it_ = this->container_.cbegin();
} }
@ -251,10 +256,10 @@ class const_ref_iterator : public std::iterator<
const_ref_iterator(const const_ref_iterator& copy) : const_ref_iterator(const const_ref_iterator& copy) :
container_{copy.container_}, container_{copy.container_},
it_{container_.cbegin()} it_{container_.cbegin()},
distance_{copy.distance_}
{ {
size_t d = std::distance(copy.container_.cbegin(), copy.it_); std::advance(this->it_, this->distance_);
std::advance(this->it_, d);
} }
const_ref_iterator operator=(const_ref_iterator other) { const_ref_iterator operator=(const_ref_iterator other) {
@ -265,12 +270,14 @@ class const_ref_iterator : public std::iterator<
void swap(const_ref_iterator& other) { void swap(const_ref_iterator& other) {
std::swap(this->container_, other.container_); std::swap(this->container_, other.container_);
std::swap(this->it_, other.it_); std::swap(this->it_, other.it_);
std::swap(this->distance_, other.distance_);
} }
const_ref_iterator& operator++() { const_ref_iterator& operator++() {
it_++; this->it_ = std::next(this->it_);
this->distance_++;
return *this; return *this;
} }
@ -282,7 +289,8 @@ class const_ref_iterator : public std::iterator<
const_ref_iterator& operator--(void) { const_ref_iterator& operator--(void) {
if (this->it_ != container_.cbegin()) { if (this->it_ != container_.cbegin()) {
this->it_--; this->it_ = std::prev(this->it_);
this->distance_--;
} }
return *this; return *this;
} }
@ -296,6 +304,7 @@ class const_ref_iterator : public std::iterator<
const_ref_iterator& operator+=(const typename const_ref_iterator::difference_type& movement) { const_ref_iterator& operator+=(const typename const_ref_iterator::difference_type& movement) {
std::advance(this->it_, movement); std::advance(this->it_, movement);
this->distance_ += movement;
return *this; return *this;
} }
@ -341,7 +350,7 @@ class const_ref_iterator : public std::iterator<
typename const_ref_iterator::difference_type operator-(const const_ref_iterator& rhs) const { typename const_ref_iterator::difference_type operator-(const const_ref_iterator& rhs) const {
return std::distance(rhs, *this); return this->distance_ - rhs.distance_;
} }
bool operator<(const const_ref_iterator& rhs) const { bool operator<(const const_ref_iterator& rhs) const {
@ -363,12 +372,13 @@ class const_ref_iterator : public std::iterator<
} }
const_ref_iterator cbegin(void) const { const_ref_iterator cbegin(void) const {
return {this->container_}; return this->container_;
} }
const_ref_iterator cend(void) const { const_ref_iterator cend(void) const {
const_ref_iterator it{this->container_}; const_ref_iterator it{this->container_};
it.it_ = it.container_.cend(); it.it_ = it.container_.cend();
it.distance_ = it.size();
return it; return it;
} }
@ -381,9 +391,7 @@ class const_ref_iterator : public std::iterator<
} }
bool operator==(const const_ref_iterator& other) const { bool operator==(const const_ref_iterator& other) const {
size_t d1 = static_cast<size_t>(std::distance(this->it_, this->container_.cend())); return (this->size() == other.size() and this->distance_ == other.distance_);
size_t d2 = static_cast<size_t>(std::distance(other.it_, other.container_.cend()));
return (this->size() == other.size() and d1 == d2);
} }
bool operator!=(const const_ref_iterator& other) const { bool operator!=(const const_ref_iterator& other) const {
@ -426,6 +434,7 @@ class const_ref_iterator : public std::iterator<
private: private:
T container_; T container_;
typename decay_t<decltype(container_)>::const_iterator it_; typename decay_t<decltype(container_)>::const_iterator it_;
typename const_ref_iterator::difference_type distance_;
}; };
@ -446,7 +455,10 @@ class filter_iterator : public std::iterator<
using filter_t = std::function<bool (const typename DT::value_type&)>; using filter_t = std::function<bool (const typename DT::value_type&)>;
filter_iterator(T container, filter_t filter) : filter_iterator(T container, filter_t filter) :
size_c_{0}, container_{std::forward<T>(container)}, filter_{filter} size_c_{0},
container_{std::forward<T>(container)},
filter_{filter},
distance_{0}
{ {
this->it_ = std::begin(this->container_); this->it_ = std::begin(this->container_);
@ -462,10 +474,10 @@ class filter_iterator : public std::iterator<
size_c_{0}, size_c_{0},
container_{copy.container_}, container_{copy.container_},
it_{std::begin(container_)}, it_{std::begin(container_)},
filter_{copy.filter_} filter_{copy.filter_},
distance_{copy.distance_}
{ {
size_t d = std::distance(const_cast<filter_iterator&>(copy).container_.begin(), copy.it_); std::advance(this->it_, this->distance_);
std::advance(this->it_, d);
} }
filter_iterator operator=(filter_iterator other) { filter_iterator operator=(filter_iterator other) {
@ -478,6 +490,7 @@ class filter_iterator : public std::iterator<
std::swap(this->it_, other.it_); std::swap(this->it_, other.it_);
std::swap(this->filter_, other.filter_); std::swap(this->filter_, other.filter_);
std::swap(this->size_c_, other.size_c_); std::swap(this->size_c_, other.size_c_);
std::swap(this->distance_, other.distance_);
} }
@ -504,7 +517,10 @@ class filter_iterator : public std::iterator<
filter_iterator end(void) { filter_iterator end(void) {
filter_iterator it_end{this->container_, this->filter_}; filter_iterator it_end{this->container_, this->filter_};
it_end.it_ = it_end.container_.end();
it_end.it_ = it_end.container_.end();
it_end.distance_ = it_end.container_.size();
return it_end; return it_end;
} }
@ -548,11 +564,7 @@ class filter_iterator : public std::iterator<
bool operator==(const filter_iterator& other) const { bool operator==(const filter_iterator& other) const {
return (this->container_.size() == other.container_.size() and this->distance_ == other.distance_);
size_t d1 = std::distance(this->it_, const_cast<filter_iterator*>(this)->container_.end());
size_t d2 = std::distance(other.it_, const_cast<filter_iterator&>(other).container_.end());
return (this->container_.size() == other.container_.size() and d1 == d2);
} }
bool operator!=(const filter_iterator& other) const { bool operator!=(const filter_iterator& other) const {
@ -562,13 +574,14 @@ class filter_iterator : public std::iterator<
private: private:
void next(void) { void next(void) {
if (this->it_ == std::end(this->container_)) { if (this->it_ == std::end(this->container_)) {
this->distance_ = this->container_.size();
return; return;
} }
this->it_ = std::find_if( do {
std::next(this->it_), this->it_ = std::next(this->it_);
std::end(this->container_), this->distance_++;
this->filter_); } while(this->it_ != std::end(this->container_) and not this->filter_(*this->it_));
} }
@ -577,6 +590,7 @@ class filter_iterator : public std::iterator<
T container_; T container_;
typename DT::iterator it_; typename DT::iterator it_;
filter_t filter_; filter_t filter_;
typename filter_iterator::difference_type distance_;
}; };
// Iterator which return a const ref on container's values given a predicated // Iterator which return a const ref on container's values given a predicated
@ -596,7 +610,10 @@ class const_filter_iterator : public std::iterator<
using filter_t = std::function<bool (const typename DT::value_type)>; using filter_t = std::function<bool (const typename DT::value_type)>;
const_filter_iterator(CT container, filter_t filter) : const_filter_iterator(CT container, filter_t filter) :
size_c_{0}, container_{std::forward<CT>(container)}, filter_{filter} size_c_{0},
container_{std::forward<CT>(container)},
filter_{filter},
distance_{0}
{ {
this->it_ = this->container_.cbegin(); this->it_ = this->container_.cbegin();
@ -611,10 +628,10 @@ class const_filter_iterator : public std::iterator<
size_c_{0}, size_c_{0},
container_{copy.container_}, container_{copy.container_},
it_{container_.cbegin()}, it_{container_.cbegin()},
filter_{copy.filter_} filter_{copy.filter_},
distance_{copy.distance_}
{ {
size_t d = std::distance(copy.container_.cbegin(), copy.it_); std::advance(this->it_, this->distance_);
std::advance(this->it_, d);
} }
const_filter_iterator operator=(const_filter_iterator other) { const_filter_iterator operator=(const_filter_iterator other) {
@ -627,6 +644,7 @@ class const_filter_iterator : public std::iterator<
std::swap(this->it_, other.it_); std::swap(this->it_, other.it_);
std::swap(this->filter_, other.filter_); std::swap(this->filter_, other.filter_);
std::swap(this->size_c_, other.size_c_); std::swap(this->size_c_, other.size_c_);
std::swap(this->distance_, other.distance_);
} }
@ -654,7 +672,8 @@ class const_filter_iterator : public std::iterator<
const_filter_iterator cend(void) const { const_filter_iterator cend(void) const {
const_filter_iterator it{this->container_, this->filter_}; const_filter_iterator it{this->container_, this->filter_};
it.it_ = it.container_.cend(); it.it_ = it.container_.cend();
it.distance_ = it.container_.size();
return it; return it;
} }
@ -707,12 +726,8 @@ class const_filter_iterator : public std::iterator<
return *it; return *it;
} }
bool operator==(const const_filter_iterator& other) const { bool operator==(const const_filter_iterator& other) const {
size_t d1 = static_cast<size_t>(std::distance(this->it_, this->container_.cend())); return (this->container_.size() == other.container_.size() and this->distance_ == other.distance_);
size_t d2 = static_cast<size_t>(std::distance(other.it_, other.container_.cend()));
return (this->container_.size() == other.container_.size() and d1 == d2);
} }
bool operator!=(const const_filter_iterator& other) const { bool operator!=(const const_filter_iterator& other) const {
@ -723,19 +738,21 @@ class const_filter_iterator : public std::iterator<
void next(void) { void next(void) {
if (this->it_ == this->container_.cend()) { if (this->it_ == this->container_.cend()) {
this->distance_ = this->container_.size();
return; return;
} }
this->it_ = std::find_if( do {
std::next(this->it_), this->it_ = std::next(this->it_);
this->container_.cend(), this->distance_++;
this->filter_); } while(this->it_ != this->container_.cend() and not this->filter_(*this->it_));
} }
mutable size_t size_c_; mutable size_t size_c_;
T container_; T container_;
typename decay_t<decltype(container_)>::const_iterator it_; typename decay_t<decltype(container_)>::const_iterator it_;
filter_t filter_; filter_t filter_;
typename const_filter_iterator::difference_type distance_;
}; };

View File

@ -77,6 +77,23 @@ bool Relocation::operator!=(const Relocation& rhs) const {
return not (*this == rhs); return not (*this == rhs);
} }
bool Relocation::operator<(const Relocation& rhs) const {
return this->address() < rhs.address();
}
bool Relocation::operator<=(const Relocation& rhs) const {
return not (this->address() > rhs.address());
}
bool Relocation::operator>(const Relocation& rhs) const {
return this->address() > rhs.address();
}
bool Relocation::operator>=(const Relocation& rhs) const {
return not (this->address() < rhs.address());
}
std::ostream& operator<<(std::ostream& os, const Relocation& entry) { std::ostream& operator<<(std::ostream& os, const Relocation& entry) {
os << std::hex; os << std::hex;
os << std::left os << std::left

View File

@ -80,23 +80,23 @@ LIEF::sections_t Binary::get_abstract_sections(void) {
// ======== // ========
it_sections Binary::sections(void) { it_sections Binary::sections(void) {
return it_sections{std::ref(this->sections_)}; return this->sections_;
} }
it_const_sections Binary::sections(void) const { it_const_sections Binary::sections(void) const {
return it_const_sections{std::cref(this->sections_)}; return this->sections_;
} }
// Segments // Segments
// ======== // ========
it_segments Binary::segments(void) { it_segments Binary::segments(void) {
return it_segments{std::ref(this->segments_)}; return this->segments_;
} }
it_const_segments Binary::segments(void) const { it_const_segments Binary::segments(void) const {
return it_const_segments{std::ref(this->segments_)}; return this->segments_;
} }
@ -336,33 +336,33 @@ it_const_imported_symbols Binary::imported_symbols(void) const {
// -------------- // --------------
it_symbols_version Binary::symbols_version(void) { it_symbols_version Binary::symbols_version(void) {
return it_symbols_version{std::ref(this->symbol_version_table_)}; return this->symbol_version_table_;
} }
it_const_symbols_version Binary::symbols_version(void) const { it_const_symbols_version Binary::symbols_version(void) const {
return it_const_symbols_version{std::cref(this->symbol_version_table_)}; return this->symbol_version_table_;
} }
// Symbol version definition // Symbol version definition
// ------------------------- // -------------------------
it_symbols_version_definition Binary::symbols_version_definition(void) { it_symbols_version_definition Binary::symbols_version_definition(void) {
return it_symbols_version_definition{std::ref(this->symbol_version_definition_)}; return this->symbol_version_definition_;
} }
it_const_symbols_version_definition Binary::symbols_version_definition(void) const { it_const_symbols_version_definition Binary::symbols_version_definition(void) const {
return it_const_symbols_version_definition{std::cref(this->symbol_version_definition_)}; return this->symbol_version_definition_;
} }
// Symbol version requirement // Symbol version requirement
// -------------------------- // --------------------------
it_symbols_version_requirement Binary::symbols_version_requirement(void) { it_symbols_version_requirement Binary::symbols_version_requirement(void) {
return it_symbols_version_requirement{std::ref(this->symbol_version_requirements_)}; return this->symbol_version_requirements_;
} }
it_const_symbols_version_requirement Binary::symbols_version_requirement(void) const { it_const_symbols_version_requirement Binary::symbols_version_requirement(void) const {
return it_const_symbols_version_requirement{std::cref(this->symbol_version_requirements_)}; return this->symbol_version_requirements_;
} }
void Binary::remove_symbol(const std::string& name) { void Binary::remove_symbol(const std::string& name) {

View File

@ -114,7 +114,7 @@ void Builder::build(void) {
LOG(WARNING) << "Segments offset is null"; LOG(WARNING) << "Segments offset is null";
} }
this->build_header<ELF_T>(); this->build<ELF_T>(this->binary_->header());
} }
@ -162,7 +162,7 @@ std::vector<std::string> Builder::optimize(const HANDLER& e) {
template<typename ELF_T> template<typename ELF_T>
void Builder::build_header(void) { void Builder::build(const Header& header) {;
using Elf_Half = typename ELF_T::Elf_Half; using Elf_Half = typename ELF_T::Elf_Half;
using Elf_Word = typename ELF_T::Elf_Word; using Elf_Word = typename ELF_T::Elf_Word;
using Elf_Addr = typename ELF_T::Elf_Addr; using Elf_Addr = typename ELF_T::Elf_Addr;
@ -171,7 +171,6 @@ void Builder::build_header(void) {
using Elf_Ehdr = typename ELF_T::Elf_Ehdr; using Elf_Ehdr = typename ELF_T::Elf_Ehdr;
const Header& header = this->binary_->header();
Elf_Ehdr ehdr; Elf_Ehdr ehdr;
ehdr.e_type = static_cast<Elf_Half>(header.file_type()); ehdr.e_type = static_cast<Elf_Half>(header.file_type());
@ -246,9 +245,8 @@ void Builder::build_sections(void) {
// Write Section's content // Write Section's content
if (section->size() > 0) { if (section->size() > 0) {
const std::vector<uint8_t>& content = section->content(); this->ios_.seekp(section->file_offset());
this->ios_.seekp(section->file_offset()); this->ios_.write(section->content());
this->ios_.write(content.data(), section->size());
} }
} }
@ -287,10 +285,8 @@ void Builder::build_sections(void) {
} }
} }
// TODO: Assert sh_size == content.size()
this->ios_.seekp(string_names_section->file_offset()); this->ios_.seekp(string_names_section->file_offset());
this->ios_.write(section_names.data(), section_names.size()); this->ios_.write(std::move(section_names));
//string_names_section->content(section_names);
} }
@ -349,13 +345,13 @@ void Builder::build_segments(void) {
VLOG(VDEBUG) << "Size: 0x" << std::hex << content.size(); VLOG(VDEBUG) << "Size: 0x" << std::hex << content.size();
this->ios_.seekp(segment->file_offset()); this->ios_.seekp(segment->file_offset());
this->ios_.write(content); this->ios_.write(std::move(content));
} }
} }
const Elf_Off segment_header_offset = this->binary_->header().program_headers_offset(); const Elf_Off segment_header_offset = this->binary_->header().program_headers_offset();
this->ios_.seekp(segment_header_offset); this->ios_.seekp(segment_header_offset);
this->ios_.write(pheaders); this->ios_.write(std::move(pheaders));
} }
@ -431,8 +427,8 @@ void Builder::build_static_symbols(void) {
reinterpret_cast<uint8_t*>(&sym_hdr) + sizeof(Elf_Sym)); reinterpret_cast<uint8_t*>(&sym_hdr) + sizeof(Elf_Sym));
} }
symbol_str_section.content(string_table); symbol_str_section.content(std::move(string_table));
symbol_section.content(content); symbol_section.content(std::move(content));
} }
@ -550,7 +546,7 @@ void Builder::build_dynamic_section(void) {
} }
dt_array_size->value((array.size()) * sizeof(Elf_Addr)); dt_array_size->value((array.size()) * sizeof(Elf_Addr));
array_section.content(array_content); array_section.content(std::move(array_content));
break; break;
} }
@ -578,7 +574,7 @@ void Builder::build_dynamic_section(void) {
Segment dynamic_load; Segment dynamic_load;
dynamic_load.type(SEGMENT_TYPES::PT_LOAD); dynamic_load.type(SEGMENT_TYPES::PT_LOAD);
dynamic_load.flags(ELF_SEGMENT_FLAGS::PF_R | ELF_SEGMENT_FLAGS::PF_W); dynamic_load.flags(ELF_SEGMENT_FLAGS::PF_R | ELF_SEGMENT_FLAGS::PF_W);
dynamic_load.content(dynamic_table_raw); dynamic_load.content(std::move(dynamic_table_raw));
Segment& new_dynamic_load = this->binary_->add(dynamic_load); Segment& new_dynamic_load = this->binary_->add(dynamic_load);
auto&& it_dynamic = std::find_if( auto&& it_dynamic = std::find_if(
@ -615,7 +611,7 @@ void Builder::build_dynamic_section(void) {
Segment dynstr; Segment dynstr;
dynstr.type(SEGMENT_TYPES::PT_LOAD); dynstr.type(SEGMENT_TYPES::PT_LOAD);
dynstr.flags(ELF_SEGMENT_FLAGS::PF_R); dynstr.flags(ELF_SEGMENT_FLAGS::PF_R);
dynstr.content(dynamic_strings_raw); dynstr.content(std::move(dynamic_strings_raw));
Segment& new_segment = this->binary_->add(dynstr); Segment& new_segment = this->binary_->add(dynstr);
dyn_strtab_section.virtual_address(new_segment.virtual_address()); dyn_strtab_section.virtual_address(new_segment.virtual_address());
@ -633,8 +629,8 @@ void Builder::build_dynamic_section(void) {
} }
VLOG(VDEBUG) << dyn_strtab_section; VLOG(VDEBUG) << dyn_strtab_section;
dyn_strtab_section.content(dynamic_strings_raw); dyn_strtab_section.content(std::move(dynamic_strings_raw));
dyn_section.content(dynamic_table_raw); dyn_section.content(std::move(dynamic_table_raw));
} }
@ -696,7 +692,7 @@ void Builder::build_symbol_hash(void) {
} }
(*it_hash_section)->content(new_hash_table); (*it_hash_section)->content(std::move(new_hash_table));
} }
// Mainly inspired from // Mainly inspired from
@ -845,7 +841,7 @@ void Builder::build_symbol_gnuhash(void) {
} }
if (raw_gnuhash.size() <= (*it_gnuhash)->size()) { if (raw_gnuhash.size() <= (*it_gnuhash)->size()) {
return (*it_gnuhash)->content(raw_gnuhash); return (*it_gnuhash)->content(std::move(raw_gnuhash));
} else { // Write a "null hash table" } else { // Write a "null hash table"
this->build_empty_symbol_gnuhash(); this->build_empty_symbol_gnuhash();
} }
@ -965,7 +961,7 @@ void Builder::build_dynamic_symbols(void) {
Segment dynstr; Segment dynstr;
dynstr.type(SEGMENT_TYPES::PT_LOAD); dynstr.type(SEGMENT_TYPES::PT_LOAD);
dynstr.flags(ELF_SEGMENT_FLAGS::PF_R); dynstr.flags(ELF_SEGMENT_FLAGS::PF_R);
dynstr.content(string_table_raw); dynstr.content(std::move(string_table_raw));
Segment& new_segment = this->binary_->add(dynstr); Segment& new_segment = this->binary_->add(dynstr);
@ -987,7 +983,7 @@ void Builder::build_dynamic_symbols(void) {
Segment dynsym_load; Segment dynsym_load;
dynsym_load.type(SEGMENT_TYPES::PT_LOAD); dynsym_load.type(SEGMENT_TYPES::PT_LOAD);
dynsym_load.flags(ELF_SEGMENT_FLAGS::PF_R | ELF_SEGMENT_FLAGS::PF_W); dynsym_load.flags(ELF_SEGMENT_FLAGS::PF_R | ELF_SEGMENT_FLAGS::PF_W);
dynsym_load.content(symbol_table_raw); dynsym_load.content(std::move(symbol_table_raw));
Segment& new_dynsym_load = this->binary_->add(dynsym_load); Segment& new_dynsym_load = this->binary_->add(dynsym_load);
symbol_table_section.virtual_address(new_dynsym_load.virtual_address()); symbol_table_section.virtual_address(new_dynsym_load.virtual_address());
@ -1005,8 +1001,8 @@ void Builder::build_dynamic_symbols(void) {
} }
VLOG(VDEBUG) << "Write back symbol table"; VLOG(VDEBUG) << "Write back symbol table";
string_table_section.content(string_table_raw); string_table_section.content(std::move(string_table_raw));
symbol_table_section.content(symbol_table_raw); symbol_table_section.content(std::move(symbol_table_raw));
} }
@ -1151,7 +1147,7 @@ void Builder::build_dynamic_relocations(void) {
Segment relocation_load; Segment relocation_load;
relocation_load.type(SEGMENT_TYPES::PT_LOAD); relocation_load.type(SEGMENT_TYPES::PT_LOAD);
relocation_load.flags(ELF_SEGMENT_FLAGS::PF_R | ELF_SEGMENT_FLAGS::PF_W); relocation_load.flags(ELF_SEGMENT_FLAGS::PF_R | ELF_SEGMENT_FLAGS::PF_W);
relocation_load.content(content); relocation_load.content(std::move(content));
Segment& new_relocation_load = this->binary_->add(relocation_load); Segment& new_relocation_load = this->binary_->add(relocation_load);
relocation_section.virtual_address(new_relocation_load.virtual_address()); relocation_section.virtual_address(new_relocation_load.virtual_address());
@ -1169,7 +1165,7 @@ void Builder::build_dynamic_relocations(void) {
} }
relocation_section.content(content); relocation_section.content(std::move(content));
} }
template<typename ELF_T> template<typename ELF_T>
@ -1290,7 +1286,7 @@ void Builder::build_pltgot_relocations(void) {
Segment relocation_load; Segment relocation_load;
relocation_load.type(SEGMENT_TYPES::PT_LOAD); relocation_load.type(SEGMENT_TYPES::PT_LOAD);
relocation_load.flags(ELF_SEGMENT_FLAGS::PF_R | ELF_SEGMENT_FLAGS::PF_W); relocation_load.flags(ELF_SEGMENT_FLAGS::PF_R | ELF_SEGMENT_FLAGS::PF_W);
relocation_load.content(content); relocation_load.content(std::move(content));
Segment& new_relocation_load = this->binary_->add(relocation_load); Segment& new_relocation_load = this->binary_->add(relocation_load);
relocation_section.virtual_address(new_relocation_load.virtual_address()); relocation_section.virtual_address(new_relocation_load.virtual_address());
@ -1307,7 +1303,7 @@ void Builder::build_pltgot_relocations(void) {
return this->build_pltgot_relocations<ELF_T>(); return this->build_pltgot_relocations<ELF_T>();
} }
relocation_section.content(content); relocation_section.content(std::move(content));
} }
@ -1421,7 +1417,7 @@ void Builder::build_symbol_requirement(void) {
Segment dynstr; Segment dynstr;
dynstr.type(SEGMENT_TYPES::PT_LOAD); dynstr.type(SEGMENT_TYPES::PT_LOAD);
dynstr.flags(ELF_SEGMENT_FLAGS::PF_R); dynstr.flags(ELF_SEGMENT_FLAGS::PF_R);
dynstr.content(dyn_str_raw); dynstr.content(std::move(dyn_str_raw));
Segment& new_segment = this->binary_->add(dynstr); Segment& new_segment = this->binary_->add(dynstr);
@ -1439,8 +1435,8 @@ void Builder::build_symbol_requirement(void) {
return this->build_symbol_requirement<ELF_T>(); return this->build_symbol_requirement<ELF_T>();
} }
this->binary_->section_from_offset(svr_offset).content(svr_raw); this->binary_->section_from_offset(svr_offset).content(std::move(svr_raw));
dyn_str_section.content(dyn_str_raw); dyn_str_section.content(std::move(dyn_str_raw));
} }
@ -1538,7 +1534,7 @@ void Builder::build_symbol_definition(void) {
Segment dynstr; Segment dynstr;
dynstr.type(SEGMENT_TYPES::PT_LOAD); dynstr.type(SEGMENT_TYPES::PT_LOAD);
dynstr.flags(ELF_SEGMENT_FLAGS::PF_R); dynstr.flags(ELF_SEGMENT_FLAGS::PF_R);
dynstr.content(dyn_str_raw); dynstr.content(std::move(dyn_str_raw));
Segment& new_segment = this->binary_->add(dynstr); Segment& new_segment = this->binary_->add(dynstr);
@ -1559,8 +1555,8 @@ void Builder::build_symbol_definition(void) {
this->binary_->get(DYNAMIC_TAGS::DT_STRSZ).value(dyn_str_raw.size()); this->binary_->get(DYNAMIC_TAGS::DT_STRSZ).value(dyn_str_raw.size());
this->build_dynamic_section<ELF_T>(); this->build_dynamic_section<ELF_T>();
this->binary_->section_from_offset(svd_offset).content(svd_raw); this->binary_->section_from_offset(svd_offset).content(std::move(svd_raw));
dyn_str_section.content(dyn_str_raw); dyn_str_section.content(std::move(dyn_str_raw));
} }

View File

@ -141,7 +141,7 @@ void Parser::parse_binary(void) {
const uint64_t size = (*it_dynamic_relocations_size)->value(); const uint64_t size = (*it_dynamic_relocations_size)->value();
try { try {
uint64_t offset = this->binary_->virtual_address_to_offset(virtual_address); uint64_t offset = this->binary_->virtual_address_to_offset(virtual_address);
this->parse_dynamic_relocations<ELF_T>(offset, size, true); this->parse_dynamic_relocations<ELF_T, typename ELF_T::Elf_Rela>(offset, size);
} catch (const LIEF::exception&) { } catch (const LIEF::exception&) {
} }
} }
@ -169,7 +169,7 @@ void Parser::parse_binary(void) {
const uint64_t size = (*it_dynamic_relocations_size)->value(); const uint64_t size = (*it_dynamic_relocations_size)->value();
try { try {
const uint64_t offset = this->binary_->virtual_address_to_offset(virtual_address); const uint64_t offset = this->binary_->virtual_address_to_offset(virtual_address);
this->parse_dynamic_relocations<ELF_T>(offset, size, false); this->parse_dynamic_relocations<ELF_T, typename ELF_T::Elf_Rel>(offset, size);
} catch (const LIEF::exception&) { } catch (const LIEF::exception&) {
} }
@ -217,9 +217,11 @@ void Parser::parse_binary(void) {
try { try {
const uint64_t offset = this->binary_->virtual_address_to_offset(virtual_address); const uint64_t offset = this->binary_->virtual_address_to_offset(virtual_address);
this->parse_pltgot_relocations<ELF_T>( if (type == DYNAMIC_TAGS::DT_RELA) {
offset, size, this->parse_pltgot_relocations<ELF_T, typename ELF_T::Elf_Rela>(offset, size);
type == DYNAMIC_TAGS::DT_RELA ? true : false); } else {
this->parse_pltgot_relocations<ELF_T, typename ELF_T::Elf_Rel>(offset, size);
}
} catch (const LIEF::exception& e) { } catch (const LIEF::exception& e) {
LOG(WARNING) << e.what(); LOG(WARNING) << e.what();
@ -414,20 +416,24 @@ void Parser::parse_binary(void) {
} }
// Try to parse using sections // Try to parse using sections
for (const Section& section : this->binary_->sections()) { if (this->binary_->relocations_.size() == 0) {
if (section.type() == ELF_SECTION_TYPES::SHT_RELA or for (const Section& section : this->binary_->sections()) {
section.type() == ELF_SECTION_TYPES::SHT_REL) {
try { try {
this->parse_section_relocations<ELF_T>( if (section.type() == ELF_SECTION_TYPES::SHT_REL) {
section.file_offset(), this->parse_section_relocations<ELF_T, typename ELF_T::Elf_Rel>(
section.size(), section.file_offset(), section.size());
section.type() == ELF_SECTION_TYPES::SHT_RELA);
}
else if (section.type() == ELF_SECTION_TYPES::SHT_RELA) {
this->parse_section_relocations<ELF_T, typename ELF_T::Elf_Rela>(
section.file_offset(), section.size());
}
} catch (const exception& e) { } catch (const exception& e) {
LOG(WARNING) << "Unable to parse relocations from section '" LOG(WARNING) << "Unable to parse relocations from section '"
<< section.name() << "'" << section.name() << "'"
<< " (" << e.what() << ")"; << " (" << e.what() << ")";
} }
} }
} }
@ -821,11 +827,11 @@ void Parser::parse_segments(void) {
template<typename ELF_T> template<typename ELF_T, typename REL_T>
void Parser::parse_dynamic_relocations(uint64_t relocations_offset, uint64_t size, bool isRela) { void Parser::parse_dynamic_relocations(uint64_t relocations_offset, uint64_t size) {
static_assert(std::is_same<REL_T, typename ELF_T::Elf_Rel>::value or
std::is_same<REL_T, typename ELF_T::Elf_Rela>::value, "REL_T must be Elf_Rel or Elf_Rela");
VLOG(VDEBUG) << "[+] Parsing dynamic relocations"; VLOG(VDEBUG) << "[+] Parsing dynamic relocations";
using Elf_Rela = typename ELF_T::Elf_Rela;
using Elf_Rel = typename ELF_T::Elf_Rel;
// Already parsed // Already parsed
if (this->binary_->dynamic_relocations().size() > 0) { if (this->binary_->dynamic_relocations().size() > 0) {
@ -834,50 +840,26 @@ void Parser::parse_dynamic_relocations(uint64_t relocations_offset, uint64_t siz
const uint8_t shift = std::is_same<ELF_T, ELF32>::value ? 8 : 32; const uint8_t shift = std::is_same<ELF_T, ELF32>::value ? 8 : 32;
if (isRela) { const uint32_t nb_entries = static_cast<uint32_t>(size / sizeof(REL_T));
const uint32_t nb_entries = static_cast<uint32_t>(size / sizeof(Elf_Rela));
const Elf_Rela* relocEntry = reinterpret_cast<const Elf_Rela*>( const REL_T* relocEntry = reinterpret_cast<const REL_T*>(
this->stream_->read(relocations_offset, nb_entries * sizeof(Elf_Rela))); this->stream_->read(relocations_offset, nb_entries * sizeof(REL_T)));
for (uint32_t i = 0; i < nb_entries; ++i) { for (uint32_t i = 0; i < nb_entries; ++i) {
Relocation* reloc = new Relocation{relocEntry}; Relocation* reloc = new Relocation{relocEntry};
reloc->purpose(RELOCATION_PURPOSES::RELOC_PURPOSE_DYNAMIC); reloc->purpose(RELOCATION_PURPOSES::RELOC_PURPOSE_DYNAMIC);
reloc->architecture_ = this->binary_->header().machine_type(); reloc->architecture_ = this->binary_->header().machine_type();
const uint32_t idx = static_cast<uint32_t>(relocEntry->r_info >> shift); const uint32_t idx = static_cast<uint32_t>(relocEntry->r_info >> shift);
if (idx < this->binary_->dynamic_symbols_.size()) { if (idx < this->binary_->dynamic_symbols_.size()) {
reloc->symbol_ = this->binary_->dynamic_symbols_[idx]; reloc->symbol_ = this->binary_->dynamic_symbols_[idx];
} else { } else {
LOG(WARNING) << "Unable to find the symbol associated with the relocation (idx: " LOG(WARNING) << "Unable to find the symbol associated with the relocation (idx: "
<< std::dec << idx << ")" << std::endl << std::dec << idx << ")" << std::endl
<< reloc; << reloc;
}
this->binary_->relocations_.push_back(reloc);
relocEntry++;
} }
} else {
const uint32_t nb_entries = static_cast<uint32_t>(size / sizeof(Elf_Rel));
const Elf_Rel* relocEntry = reinterpret_cast<const Elf_Rel*>( this->binary_->relocations_.push_back(reloc);
this->stream_->read(relocations_offset, nb_entries * sizeof(Elf_Rel))); relocEntry++;
for (uint32_t i = 0; i < nb_entries; ++i) {
Relocation* reloc = new Relocation{relocEntry};
reloc->purpose(RELOCATION_PURPOSES::RELOC_PURPOSE_DYNAMIC);
reloc->architecture_ = this->binary_->header().machine_type();
uint32_t idx = static_cast<uint32_t>(relocEntry->r_info >> shift);
if (idx < this->binary_->dynamic_symbols_.size()) {
reloc->symbol_ = this->binary_->dynamic_symbols_[idx];
} else {
LOG(WARNING) << "Unable to find the symbol associated with the relocation (idx: "
<< std::dec << idx << ")" << std::endl
<< reloc;
}
this->binary_->relocations_.push_back(reloc);
relocEntry++;
}
} }
} // build_dynamic_reclocations } // build_dynamic_reclocations
@ -1276,10 +1258,10 @@ void Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) {
} }
template<typename ELF_T> template<typename ELF_T, typename REL_T>
void Parser::parse_pltgot_relocations(uint64_t offset, uint64_t size, bool isRela) { void Parser::parse_pltgot_relocations(uint64_t offset, uint64_t size) {
using Elf_Rela = typename ELF_T::Elf_Rela; static_assert(std::is_same<REL_T, typename ELF_T::Elf_Rel>::value or
using Elf_Rel = typename ELF_T::Elf_Rel; std::is_same<REL_T, typename ELF_T::Elf_Rela>::value, "REL_T must be Elf_Rel or Elf_Rela");
using Elf_Addr = typename ELF_T::Elf_Addr; using Elf_Addr = typename ELF_T::Elf_Addr;
using Elf_Off = typename ELF_T::Elf_Off; using Elf_Off = typename ELF_T::Elf_Off;
@ -1291,116 +1273,65 @@ void Parser::parse_pltgot_relocations(uint64_t offset, uint64_t size, bool isRel
const Elf_Off offset_relocations = offset; const Elf_Off offset_relocations = offset;
const uint8_t shift = std::is_same<ELF_T, ELF32>::value ? 8 : 32; const uint8_t shift = std::is_same<ELF_T, ELF32>::value ? 8 : 32;
if (isRela) { const uint32_t nb_entries = static_cast<uint32_t>(size / sizeof(REL_T));
const uint32_t nb_entries = static_cast<uint32_t>(size / sizeof(Elf_Rela)); const REL_T* relocEntry = reinterpret_cast<const REL_T*>(
const Elf_Rela* relocEntry = reinterpret_cast<const Elf_Rela*>( this->stream_->read(offset_relocations, nb_entries * sizeof(REL_T)));
this->stream_->read(offset_relocations, nb_entries * sizeof(Elf_Rela)));
for (uint32_t i = 0; i < nb_entries; ++i) { for (uint32_t i = 0; i < nb_entries; ++i) {
Relocation* reloc = new Relocation{relocEntry}; Relocation* reloc = new Relocation{relocEntry};
reloc->architecture_ = this->binary_->header_.machine_type(); reloc->architecture_ = this->binary_->header_.machine_type();
reloc->purpose(RELOCATION_PURPOSES::RELOC_PURPOSE_PLTGOT); reloc->purpose(RELOCATION_PURPOSES::RELOC_PURPOSE_PLTGOT);
const uint32_t idx = static_cast<uint32_t>(relocEntry->r_info >> shift); const uint32_t idx = static_cast<uint32_t>(relocEntry->r_info >> shift);
if (idx > 0 and idx < this->binary_->dynamic_symbols_.size()) { if (idx > 0 and idx < this->binary_->dynamic_symbols_.size()) {
reloc->symbol_ = this->binary_->dynamic_symbols_[idx]; reloc->symbol_ = this->binary_->dynamic_symbols_[idx];
}
this->binary_->relocations_.push_back(reloc);
relocEntry++;
} }
} else {
const uint32_t nb_entries = static_cast<uint32_t>(size / sizeof(Elf_Rel));
const Elf_Rel* relocEntry = reinterpret_cast<const Elf_Rel*>(
this->stream_->read(offset_relocations, nb_entries * sizeof(Elf_Rel)));
for (uint32_t i = 0; i < nb_entries; ++i) {
Relocation* reloc = new Relocation{relocEntry};
reloc->architecture_ = this->binary_->header_.machine_type();
reloc->purpose(RELOCATION_PURPOSES::RELOC_PURPOSE_PLTGOT);
const uint32_t idx = static_cast<uint32_t>(relocEntry->r_info >> shift); this->binary_->relocations_.push_back(reloc);
if (idx > 0 and idx < this->binary_->dynamic_symbols_.size()) { relocEntry++;
reloc->symbol_ = this->binary_->dynamic_symbols_[idx];
}
this->binary_->relocations_.push_back(reloc);
relocEntry++;
}
} }
} }
template<typename ELF_T> template<typename ELF_T, typename REL_T>
void Parser::parse_section_relocations(uint64_t offset, uint64_t size, bool isRela) { void Parser::parse_section_relocations(uint64_t offset, uint64_t size) {
using Elf_Rela = typename ELF_T::Elf_Rela; static_assert(std::is_same<REL_T, typename ELF_T::Elf_Rel>::value or
using Elf_Rel = typename ELF_T::Elf_Rel; std::is_same<REL_T, typename ELF_T::Elf_Rela>::value, "REL_T must be Elf_Rel or Elf_Rela");
const uint64_t offset_relocations = offset; const uint64_t offset_relocations = offset;
const uint8_t shift = std::is_same<ELF_T, ELF32>::value ? 8 : 32; const uint8_t shift = std::is_same<ELF_T, ELF32>::value ? 8 : 32;
if (isRela) { const uint32_t nb_entries = static_cast<uint32_t>(size / sizeof(REL_T));
const uint32_t nb_entries = static_cast<uint32_t>(size / sizeof(Elf_Rela)); const REL_T* relocEntry = reinterpret_cast<const REL_T*>(
const Elf_Rela* relocEntry = reinterpret_cast<const Elf_Rela*>( this->stream_->read(offset_relocations, nb_entries * sizeof(REL_T)));
this->stream_->read(offset_relocations, nb_entries * sizeof(Elf_Rela)));
for (uint32_t i = 0; i < nb_entries; ++i) { for (uint32_t i = 0; i < nb_entries; ++i) {
Relocation* reloc = new Relocation{relocEntry}; Relocation* reloc = new Relocation{relocEntry};
reloc->architecture_ = this->binary_->header_.machine_type(); reloc->architecture_ = this->binary_->header_.machine_type();
if (this->binary_->header().file_type() == ELF::E_TYPE::ET_REL and if (this->binary_->header().file_type() == ELF::E_TYPE::ET_REL and
this->binary_->segments().size() == 0) { this->binary_->segments().size() == 0) {
reloc->purpose(RELOCATION_PURPOSES::RELOC_PURPOSE_OBJECT); reloc->purpose(RELOCATION_PURPOSES::RELOC_PURPOSE_OBJECT);
}
const uint32_t idx = static_cast<uint32_t>(relocEntry->r_info >> shift);
if (idx > 0 and idx < this->binary_->dynamic_symbols_.size()) {
reloc->symbol_ = this->binary_->dynamic_symbols_[idx];
}
if (std::find_if(
std::begin(this->binary_->relocations_),
std::end(this->binary_->relocations_),
[&reloc] (const Relocation* r) {
return r->address() == reloc->address() and
r->type() == reloc->type() and
r->addend() == reloc->addend();
}) != std::end(this->binary_->relocations_)) {
delete reloc;
} else {
this->binary_->relocations_.push_back(reloc);
}
relocEntry++;
} }
} else {
const uint32_t nb_entries = static_cast<uint32_t>(size / sizeof(Elf_Rel));
const Elf_Rel* relocEntry = reinterpret_cast<const Elf_Rel*>(
this->stream_->read(offset_relocations, nb_entries * sizeof(Elf_Rel)));
for (uint32_t i = 0; i < nb_entries; ++i) {
Relocation* reloc = new Relocation{relocEntry};
reloc->architecture_ = this->binary_->header_.machine_type();
if (this->binary_->header().file_type() == ELF::E_TYPE::ET_REL and
this->binary_->segments().size() == 0) {
reloc->purpose(RELOCATION_PURPOSES::RELOC_PURPOSE_OBJECT);
}
const uint32_t idx = static_cast<uint32_t>(relocEntry->r_info >> shift);
const uint32_t idx = static_cast<uint32_t>(relocEntry->r_info >> shift); if (idx > 0 and idx < this->binary_->dynamic_symbols_.size()) {
if (idx > 0 and idx < this->binary_->dynamic_symbols_.size()) { reloc->symbol_ = this->binary_->dynamic_symbols_[idx];
reloc->symbol_ = this->binary_->dynamic_symbols_[idx]; } else if (idx < this->binary_->static_symbols_.size()) {
} reloc->symbol_ = this->binary_->static_symbols_[idx];
if (std::find_if(
std::begin(this->binary_->relocations_),
std::end(this->binary_->relocations_),
[&reloc] (const Relocation* r) {
return r->address() == reloc->address() and
r->type() == reloc->type() and
r->addend() == reloc->addend();
}) != std::end(this->binary_->relocations_)) {
delete reloc;
} else {
this->binary_->relocations_.push_back(reloc);
}
relocEntry++;
} }
if (std::find_if(
std::begin(this->binary_->relocations_),
std::end(this->binary_->relocations_),
[&reloc] (const Relocation* r) {
return r->address() == reloc->address() and
r->type() == reloc->type() and
r->addend() == reloc->addend();
}) != std::end(this->binary_->relocations_)) {
delete reloc;
} else {
this->binary_->relocations_.push_back(reloc);
}
relocEntry++;
} }
} }

View File

@ -311,6 +311,46 @@ void Section::content(const std::vector<uint8_t>& content) {
} }
void Section::content(std::vector<uint8_t>&& content) {
if (content.size() > 0 and this->type() == ELF_SECTION_TYPES::SHT_NOBITS) {
LOG(WARNING) << "You insert data (" << std::hex << content.size() << ") in section '"
<< this->name() << "' which has SHT_NOBITS type !" << std::endl;
}
if (this->datahandler_ == nullptr) {
VLOG(VDEBUG) << "Set content in the cache";
this->content_c_ = std::move(content);
this->size(content.size());
return;
}
VLOG(VDEBUG) << "Set content in the data handler [0x" << std::hex
<< this->file_offset() << ", 0x" << content.size() << "]";
DataHandler::Node& node = this->datahandler_->get(
this->file_offset(),
this->size(),
DataHandler::Node::SECTION);
std::vector<uint8_t>& binary_content = this->datahandler_->content();
this->datahandler_->reserve(node.offset(), content.size());
if (node.size() < content.size()) {
LOG(WARNING) << "You insert data in section '"
<< this->name() << "' It may lead to overaly! (" << std::hex << node.size() << " < " << content.size() << ")" << std::endl;
}
this->size(content.size());
std::move(
std::begin(content),
std::end(content),
std::begin(binary_content) + node.offset());
}
void Section::type(ELF_SECTION_TYPES type) { void Section::type(ELF_SECTION_TYPES type) {
this->type_ = type; this->type_ = type;
} }
@ -353,11 +393,11 @@ void Section::entry_size(uint64_t entry_size) {
it_segments Section::segments(void) { it_segments Section::segments(void) {
return it_segments{std::ref(this->segments_)}; return this->segments_;
} }
it_const_segments Section::segments(void) const { it_const_segments Section::segments(void) const {
return it_const_segments{std::cref(this->segments_)}; return this->segments_;
} }
void Section::accept(Visitor& visitor) const { void Section::accept(Visitor& visitor) const {

View File

@ -317,6 +317,39 @@ void Segment::content(const std::vector<uint8_t>& content) {
std::begin(binary_content) + node.offset()); std::begin(binary_content) + node.offset());
} }
void Segment::content(std::vector<uint8_t>&& content) {
if (this->datahandler_ == nullptr) {
VLOG(VDEBUG) << "Set content in the cache";
this->content_c_ = std::move(content);
this->physical_size(content.size());
return;
}
VLOG(VDEBUG) << "Set content in the data handler [0x" << std::hex << this->file_offset() << ", 0x" << content.size() << "]";
DataHandler::Node& node = this->datahandler_->get(
this->file_offset(),
this->physical_size(),
DataHandler::Node::SEGMENT);
std::vector<uint8_t>& binary_content = this->datahandler_->content();
this->datahandler_->reserve(node.offset(), content.size());
if (node.size() < content.size()) {
LOG(WARNING) << "You insert data in segment '"
<< to_string(this->type()) << "' It may lead to overaly!" << std::endl;
}
this->physical_size(node.size());
std::move(
std::begin(content),
std::end(content),
std::begin(binary_content) + node.offset());
}
void Segment::accept(Visitor& visitor) const { void Segment::accept(Visitor& visitor) const {
visitor.visit(this->type()); visitor.visit(this->type());

View File

@ -102,11 +102,11 @@ uint32_t SymbolVersionDefinition::hash(void) const {
} }
it_symbols_version_aux SymbolVersionDefinition::symbols_aux(void) { it_symbols_version_aux SymbolVersionDefinition::symbols_aux(void) {
return it_symbols_version_aux{this->symbol_version_aux_}; return this->symbol_version_aux_;
} }
it_const_symbols_version_aux SymbolVersionDefinition::symbols_aux(void) const { it_const_symbols_version_aux SymbolVersionDefinition::symbols_aux(void) const {
return it_const_symbols_version_aux{this->symbol_version_aux_}; return this->symbol_version_aux_;
} }

View File

@ -85,12 +85,12 @@ uint32_t SymbolVersionRequirement::cnt(void) const {
it_symbols_version_aux_requirement SymbolVersionRequirement::get_auxiliary_symbols(void) { it_symbols_version_aux_requirement SymbolVersionRequirement::get_auxiliary_symbols(void) {
return {this->symbol_version_aux_requirement_}; return this->symbol_version_aux_requirement_;
} }
it_const_symbols_version_aux_requirement SymbolVersionRequirement::get_auxiliary_symbols(void) const { it_const_symbols_version_aux_requirement SymbolVersionRequirement::get_auxiliary_symbols(void) const {
return {this->symbol_version_aux_requirement_}; return this->symbol_version_aux_requirement_;
} }

View File

@ -182,7 +182,7 @@ Header& Binary::header(void) {
// ======== // ========
it_commands Binary::commands(void) { it_commands Binary::commands(void) {
return it_commands{std::ref(this->commands_)}; return this->commands_;
} }
it_const_commands Binary::commands(void) const { it_const_commands Binary::commands(void) const {
@ -193,18 +193,18 @@ it_const_commands Binary::commands(void) const {
// ======= // =======
it_symbols Binary::symbols(void) { it_symbols Binary::symbols(void) {
return it_symbols{std::ref(this->symbols_)}; return this->symbols_;
} }
it_const_symbols Binary::symbols(void) const { it_const_symbols Binary::symbols(void) const {
return it_const_symbols{std::cref(this->symbols_)}; return this->symbols_;
} }
it_libraries Binary::libraries(void) { it_libraries Binary::libraries(void) {
libraries_t result; libraries_t result;
for (LoadCommand* library: this->commands_) { for (LoadCommand* library: this->commands_) {
if (dynamic_cast<DylibCommand*>(library)) { if (typeid(*library) == typeid(DylibCommand)) {
result.push_back(dynamic_cast<DylibCommand*>(library)); result.push_back(dynamic_cast<DylibCommand*>(library));
} }
} }
@ -216,7 +216,7 @@ it_const_libraries Binary::libraries(void) const {
libraries_t result; libraries_t result;
for (LoadCommand* library: this->commands_) { for (LoadCommand* library: this->commands_) {
if (dynamic_cast<DylibCommand*>(library)) { if (typeid(*library) == typeid(DylibCommand)) {
result.push_back(dynamic_cast<DylibCommand*>(library)); result.push_back(dynamic_cast<DylibCommand*>(library));
} }
} }
@ -225,24 +225,24 @@ it_const_libraries Binary::libraries(void) const {
it_segments Binary::segments(void) { it_segments Binary::segments(void) {
segments_t result{}; segments_t result{};
result.reserve(this->commands_.size());
for (LoadCommand* cmd: this->commands_) { for (LoadCommand* cmd: this->commands_) {
if (dynamic_cast<SegmentCommand*>(cmd)) { if (typeid(*cmd) == typeid(SegmentCommand)) {
result.push_back(dynamic_cast<SegmentCommand*>(cmd)); result.push_back(dynamic_cast<SegmentCommand*>(cmd));
} }
} }
return it_segments{result}; return result;
} }
it_const_segments Binary::segments(void) const { it_const_segments Binary::segments(void) const {
segments_t result{}; segments_t result{};
result.reserve(this->commands_.size());
for (LoadCommand* cmd: this->commands_) { for (LoadCommand* cmd: this->commands_) {
if (dynamic_cast<SegmentCommand*>(cmd)) { if (typeid(*cmd) == typeid(SegmentCommand)) {
result.push_back(dynamic_cast<SegmentCommand*>(cmd)); result.push_back(dynamic_cast<SegmentCommand*>(cmd));
} }
} }
return it_const_segments{result}; return result;
} }
it_sections Binary::sections(void) { it_sections Binary::sections(void) {
@ -252,7 +252,7 @@ it_sections Binary::sections(void) {
result.push_back(&s); result.push_back(&s);
} }
} }
return it_sections{result}; return result;
} }
it_const_sections Binary::sections(void) const { it_const_sections Binary::sections(void) const {
@ -262,7 +262,7 @@ it_const_sections Binary::sections(void) const {
result.push_back(const_cast<Section*>(&s)); result.push_back(const_cast<Section*>(&s));
} }
} }
return it_const_sections{result}; return result;
} }
@ -270,35 +270,35 @@ it_const_sections Binary::sections(void) const {
it_relocations Binary::relocations(void) { it_relocations Binary::relocations(void) {
relocations_t result; relocations_t result;
for (SegmentCommand& segment : this->segments()) { for (SegmentCommand& segment : this->segments()) {
for (Relocation& r: segment.relocations()) { result.insert(std::begin(segment.relocations_), std::end(segment.relocations_));
result.push_back(&r);
}
} }
for (Section& section : this->sections()) { for (Section& section : this->sections()) {
for (Relocation& r: section.relocations()) { result.insert(std::begin(section.relocations_), std::end(section.relocations_));
result.push_back(&r);
}
} }
return it_relocations{result}; if (result.size() != this->relocations_.size()) {
this->relocations_ = std::move(result);
}
return this->relocations_;
} }
it_const_relocations Binary::relocations(void) const { it_const_relocations Binary::relocations(void) const {
relocations_t result; relocations_t result;
for (const SegmentCommand& segment : this->segments()) { for (const SegmentCommand& segment : this->segments()) {
for (const Relocation& r: segment.relocations()) { result.insert(std::begin(segment.relocations_), std::end(segment.relocations_));
result.push_back(const_cast<Relocation*>(&r));
}
} }
for (const Section& section : this->sections()) { for (const Section& section : this->sections()) {
for (const Relocation& r: section.relocations()) { result.insert(std::begin(section.relocations_), std::end(section.relocations_));
result.push_back(const_cast<Relocation*>(&r));
}
} }
return it_const_relocations{result}; if (result.size() != this->relocations_.size()) {
this->relocations_ = std::move(result);
}
return this->relocations_;
} }
@ -412,14 +412,36 @@ Section& Binary::section_from_offset(uint64_t offset) {
return const_cast<Section&>(static_cast<const Binary*>(this)->section_from_offset(offset)); return const_cast<Section&>(static_cast<const Binary*>(this)->section_from_offset(offset));
} }
const Section& Binary::section_from_virtual_address(uint64_t address) const {
it_const_sections sections = this->sections();
auto&& it_section = std::find_if(
sections.cbegin(),
sections.cend(),
[&address] (const Section& section) {
return ((section.virtual_address() <= address) and
address <= (section.virtual_address() + section.size()));
});
if (it_section == sections.cend()) {
throw not_found("Unable to find the section");
}
return *it_section;
}
Section& Binary::section_from_virtual_address(uint64_t address) {
return const_cast<Section&>(static_cast<const Binary*>(this)->section_from_virtual_address(address));
}
const SegmentCommand& Binary::segment_from_virtual_address(uint64_t virtual_address) const { const SegmentCommand& Binary::segment_from_virtual_address(uint64_t virtual_address) const {
it_const_segments segments = this->segments(); it_const_segments segments = this->segments();
auto&& it_segment = std::find_if( auto&& it_segment = std::find_if(
segments.cbegin(), std::begin(segments),
segments.cend(), std::end(segments),
[&virtual_address] (const SegmentCommand& segment) { [&virtual_address] (const SegmentCommand& segment) {
return ((segment.virtual_address() <= virtual_address) and return ((segment.virtual_address() <= virtual_address) and
virtual_address < (segment.virtual_address() + segment.virtual_size())); virtual_address <= (segment.virtual_address() + segment.virtual_size()));
}); });
if (it_segment == segments.cend()) { if (it_segment == segments.cend()) {
@ -438,8 +460,8 @@ SegmentCommand& Binary::segment_from_virtual_address(uint64_t virtual_address) {
const SegmentCommand& Binary::segment_from_offset(uint64_t offset) const { const SegmentCommand& Binary::segment_from_offset(uint64_t offset) const {
it_const_segments segments = this->segments(); it_const_segments segments = this->segments();
auto&& it_segment = std::find_if( auto&& it_segment = std::find_if(
segments.cbegin(), std::begin(segments),
segments.cend(), std::end(segments),
[&offset] (const SegmentCommand& segment) { [&offset] (const SegmentCommand& segment) {
return ((segment.file_offset() <= offset) and return ((segment.file_offset() <= offset) and
offset <= (segment.file_offset() + segment.file_size())); offset <= (segment.file_offset() + segment.file_size()));
@ -500,13 +522,9 @@ std::vector<uint8_t> Binary::raw(void) {
} }
uint64_t Binary::virtual_address_to_offset(uint64_t virtual_address) const { uint64_t Binary::virtual_address_to_offset(uint64_t virtual_address) const {
const SegmentCommand& segment = segment_from_virtual_address(virtual_address); const SegmentCommand& segment = segment_from_virtual_address(virtual_address);
const uint64_t base_address = segment.virtual_address() - segment.file_offset();
uint64_t base_address = segment.virtual_address() - segment.file_offset(); return virtual_address - base_address;
uint64_t offset = virtual_address - base_address;
return offset;
} }
@ -577,6 +595,34 @@ uint64_t Binary::fat_offset(void) const {
} }
bool Binary::is_valid_addr(uint64_t address) const {
std::pair<uint64_t, uint64_t> r = this->va_ranges();
return address <= r.second and address >= r.first;
}
std::pair<uint64_t, uint64_t> Binary::va_ranges(void) const {
it_const_segments segments = this->segments();
uint64_t min = std::accumulate(
std::begin(segments),
std::end(segments), uint64_t(-1),
[] (uint64_t va, const SegmentCommand& segment) {
return std::min<uint64_t>(segment.virtual_address(), va);
});
uint64_t max = std::accumulate(
std::begin(segments),
std::end(segments), 0,
[] (uint64_t va, const SegmentCommand& segment) {
return std::max<uint64_t>(segment.virtual_address() + segment.virtual_size(), va);
});
return {min, max};
}
LIEF::Header Binary::get_abstract_header(void) const { LIEF::Header Binary::get_abstract_header(void) const {
LIEF::Header header; LIEF::Header header;
const std::pair<ARCHITECTURES, std::set<MODES>>& am = this->header().abstract_architecture(); const std::pair<ARCHITECTURES, std::set<MODES>>& am = this->header().abstract_architecture();

View File

@ -499,28 +499,25 @@ void BinaryParser::parse_relocations(Section& section) {
} }
section.relocations_.reserve(numberof_relocations);
for (size_t i = 0; i < numberof_relocations; ++i) { for (size_t i = 0; i < numberof_relocations; ++i) {
int32_t address = this->stream_->read_integer<int32_t>(current_reloc_offset); int32_t address = this->stream_->read_integer<int32_t>(current_reloc_offset);
bool is_scattered = static_cast<bool>(address & R_SCATTERED); bool is_scattered = static_cast<bool>(address & R_SCATTERED);
RelocationObject* reloc = nullptr;
if (is_scattered) { if (is_scattered) {
const scattered_relocation_info* reloc_info = reinterpret_cast<const scattered_relocation_info*>( const scattered_relocation_info* reloc_info = reinterpret_cast<const scattered_relocation_info*>(
this->stream_->read(current_reloc_offset, sizeof(scattered_relocation_info))); this->stream_->read(current_reloc_offset, sizeof(scattered_relocation_info)));
RelocationObject* reloc = new RelocationObject{reloc_info}; reloc = new RelocationObject{reloc_info};
reloc->section_ = &section; reloc->section_ = &section;
section.relocations_.push_back(reloc);
} else { } else {
const relocation_info* reloc_info = reinterpret_cast<const relocation_info*>( const relocation_info* reloc_info = reinterpret_cast<const relocation_info*>(
this->stream_->read(current_reloc_offset, sizeof(relocation_info))); this->stream_->read(current_reloc_offset, sizeof(relocation_info)));
RelocationObject* reloc = new RelocationObject{reloc_info}; reloc = new RelocationObject{reloc_info};
reloc->section_ = &section; reloc->section_ = &section;
section.relocations_.push_back(reloc);
if (reloc_info->r_extern == 1 and reloc_info->r_symbolnum != R_ABS) { if (reloc_info->r_extern == 1 and reloc_info->r_symbolnum != R_ABS) {
if (reloc_info->r_symbolnum < this->binary_->symbols().size()) { if (reloc_info->r_symbolnum < this->binary_->symbols().size()) {
Symbol& symbol = this->binary_->symbols()[reloc_info->r_symbolnum]; Symbol& symbol = this->binary_->symbols()[reloc_info->r_symbolnum];
Relocation* relocation = section.relocations_.back(); reloc->symbol_ = &symbol;
relocation->symbol_ = &symbol;
VLOG(VDEBUG) << "Symbol: " << symbol.name(); VLOG(VDEBUG) << "Symbol: " << symbol.name();
} else { } else {
@ -531,21 +528,22 @@ void BinaryParser::parse_relocations(Section& section) {
if (reloc_info->r_extern == 0) { if (reloc_info->r_extern == 0) {
if (reloc_info->r_symbolnum < this->binary_->sections().size()) { if (reloc_info->r_symbolnum < this->binary_->sections().size()) {
Section& relsec = this->binary_->sections()[reloc_info->r_symbolnum]; Section& relsec = this->binary_->sections()[reloc_info->r_symbolnum];
Relocation* relocation = section.relocations_.back(); reloc->section_ = &relsec;
relocation->section_ = &relsec;
VLOG(VDEBUG) << "Section: " << relsec.name(); VLOG(VDEBUG) << "Section: " << relsec.name();
} else { } else {
LOG(WARNING) << "Relocation #" << std::dec << i << " of " << section.name() << " seems corrupted"; LOG(WARNING) << "Relocation #" << std::dec << i << " of " << section.name() << " seems corrupted";
} }
} }
} }
if (not section.relocations_[i]->has_section()) { if (not reloc->has_section()) {
section.relocations_[i]->section_ = &section; reloc->section_ = &section;
} }
section.relocations_[i]->architecture_ = this->binary_->header().cpu_type(); reloc->architecture_ = this->binary_->header().cpu_type();
VLOG(VDEBUG) << *section.relocations_.back();;
section.relocations_.emplace(reloc);
current_reloc_offset += 2 * sizeof(uint32_t); current_reloc_offset += 2 * sizeof(uint32_t);
} }
@ -585,7 +583,6 @@ void BinaryParser::parse_dyldinfo_rebases() {
uint8_t imm = this->stream_->read_integer<uint8_t>(current_offset) & REBASE_IMMEDIATE_MASK; uint8_t imm = this->stream_->read_integer<uint8_t>(current_offset) & REBASE_IMMEDIATE_MASK;
uint8_t opcode = this->stream_->read_integer<uint8_t>(current_offset) & REBASE_OPCODE_MASK; uint8_t opcode = this->stream_->read_integer<uint8_t>(current_offset) & REBASE_OPCODE_MASK;
current_offset += sizeof(uint8_t); current_offset += sizeof(uint8_t);
switch(static_cast<REBASE_OPCODES>(opcode)) { switch(static_cast<REBASE_OPCODES>(opcode)) {
case REBASE_OPCODES::REBASE_OPCODE_DONE: case REBASE_OPCODES::REBASE_OPCODE_DONE:
{ {
@ -704,15 +701,17 @@ void BinaryParser::parse_dyldinfo_rebases() {
relocation.segment_ = &segment; relocation.segment_ = &segment;
} }
} }
// Tie sections and relocations // Tie sections and relocations
for (SegmentCommand& segment : segments) { for (SegmentCommand& segment : segments) {
uint64_t offset = 0; uint64_t offset = 0;
for (Relocation& relocation : segment.relocations()) { for (Relocation& relocation : segment.relocations()) {
if (not this->binary_->is_valid_addr(relocation.address())) {
continue;
}
try { try {
offset = this->binary_->virtual_address_to_offset(relocation.address()); Section& section = this->binary_->section_from_virtual_address(relocation.address());
Section& section = this->binary_->section_from_offset(offset);
relocation.section_ = &section; relocation.section_ = &section;
} catch (const not_found& e) { } catch (const not_found& e) {
VLOG(VDEBUG) << "Unable to tie a section with dyld relocation at 0x" << std::hex << relocation.address() << " - 0x" << offset; VLOG(VDEBUG) << "Unable to tie a section with dyld relocation at 0x" << std::hex << relocation.address() << " - 0x" << offset;
@ -721,8 +720,14 @@ void BinaryParser::parse_dyldinfo_rebases() {
} }
// Tie symbols and relocations // Tie symbols and relocations
for (Relocation& relocation : this->binary_->relocations()) { for (Relocation& relocation : this->binary_->relocations()) {
if (not this->binary_->is_valid_addr(relocation.address())) {
continue;
}
uint64_t address = relocation.address(); uint64_t address = relocation.address();
auto&& it_symbol = std::find_if( auto&& it_symbol = std::find_if(
std::begin(this->binary_->symbols_), std::begin(this->binary_->symbols_),
@ -735,6 +740,7 @@ void BinaryParser::parse_dyldinfo_rebases() {
relocation.symbol_ = *it_symbol; relocation.symbol_ = *it_symbol;
} }
} }
} }
@ -804,6 +810,7 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
std::pair<uint64_t, uint64_t> value_delta = {0, 0}; std::pair<uint64_t, uint64_t> value_delta = {0, 0};
std::pair<int64_t, uint64_t> svalue_delta = {0, 0}; std::pair<int64_t, uint64_t> svalue_delta = {0, 0};
it_segments segments = this->binary_->segments();
while (not done and current_offset < end_offset) { while (not done and current_offset < end_offset) {
uint8_t imm = this->stream_->read_integer<uint8_t>(current_offset) & BIND_IMMEDIATE_MASK; uint8_t imm = this->stream_->read_integer<uint8_t>(current_offset) & BIND_IMMEDIATE_MASK;
uint8_t opcode = this->stream_->read_integer<uint8_t>(current_offset) & BIND_OPCODE_MASK; uint8_t opcode = this->stream_->read_integer<uint8_t>(current_offset) & BIND_OPCODE_MASK;
@ -900,7 +907,8 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
symbol_name, symbol_name,
library_ordinal, library_ordinal,
addend, addend,
is_weak_import); is_weak_import,
segments);
segment_offset += sizeof(pint_t); segment_offset += sizeof(pint_t);
break; break;
} }
@ -915,7 +923,8 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
symbol_name, symbol_name,
library_ordinal, library_ordinal,
addend, addend,
is_weak_import); is_weak_import,
segments);
value_delta = this->stream_->read_uleb128(current_offset); value_delta = this->stream_->read_uleb128(current_offset);
segment_offset += std::get<0>(value_delta) + sizeof(pint_t); segment_offset += std::get<0>(value_delta) + sizeof(pint_t);
current_offset += std::get<1>(value_delta); current_offset += std::get<1>(value_delta);
@ -932,7 +941,8 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
symbol_name, symbol_name,
library_ordinal, library_ordinal,
addend, addend,
is_weak_import); is_weak_import,
segments);
segment_offset += imm * sizeof(pint_t) + sizeof(pint_t); segment_offset += imm * sizeof(pint_t) + sizeof(pint_t);
break; break;
} }
@ -959,7 +969,8 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
symbol_name, symbol_name,
library_ordinal, library_ordinal,
addend, addend,
is_weak_import); is_weak_import,
segments);
segment_offset += skip + sizeof(pint_t); segment_offset += skip + sizeof(pint_t);
} }
break; break;
@ -1015,6 +1026,8 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
std::pair<uint64_t, uint64_t> value_delta = {0, 0}; std::pair<uint64_t, uint64_t> value_delta = {0, 0};
std::pair<int64_t, uint64_t> svalue_delta = {0, 0}; std::pair<int64_t, uint64_t> svalue_delta = {0, 0};
it_segments segments = this->binary_->segments();
while (not done and current_offset < end_offset) { while (not done and current_offset < end_offset) {
uint8_t imm = this->stream_->read_integer<uint8_t>(current_offset) & BIND_IMMEDIATE_MASK; uint8_t imm = this->stream_->read_integer<uint8_t>(current_offset) & BIND_IMMEDIATE_MASK;
uint8_t opcode = this->stream_->read_integer<uint8_t>(current_offset) & BIND_OPCODE_MASK; uint8_t opcode = this->stream_->read_integer<uint8_t>(current_offset) & BIND_OPCODE_MASK;
@ -1086,7 +1099,8 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
symbol_name, symbol_name,
0, 0,
addend, addend,
is_weak_import); is_weak_import,
segments);
segment_offset += sizeof(pint_t); segment_offset += sizeof(pint_t);
break; break;
} }
@ -1102,7 +1116,8 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
symbol_name, symbol_name,
0, 0,
addend, addend,
is_weak_import); is_weak_import,
segments);
value_delta = this->stream_->read_uleb128(current_offset); value_delta = this->stream_->read_uleb128(current_offset);
segment_offset += std::get<0>(value_delta) + sizeof(pint_t); segment_offset += std::get<0>(value_delta) + sizeof(pint_t);
current_offset += std::get<1>(value_delta); current_offset += std::get<1>(value_delta);
@ -1120,7 +1135,8 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
symbol_name, symbol_name,
0, 0,
addend, addend,
is_weak_import); is_weak_import,
segments);
segment_offset += imm * sizeof(pint_t) + sizeof(pint_t); segment_offset += imm * sizeof(pint_t) + sizeof(pint_t);
break; break;
} }
@ -1148,7 +1164,8 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
symbol_name, symbol_name,
0, 0,
addend, addend,
is_weak_import); is_weak_import,
segments);
segment_offset += skip + sizeof(pint_t); segment_offset += skip + sizeof(pint_t);
} }
break; break;
@ -1202,6 +1219,8 @@ void BinaryParser::parse_dyldinfo_lazy_bind() {
std::pair<uint64_t, uint64_t> value_delta = {0, 0}; std::pair<uint64_t, uint64_t> value_delta = {0, 0};
std::pair< int64_t, uint64_t> svalue_delta = {0, 0}; std::pair< int64_t, uint64_t> svalue_delta = {0, 0};
it_segments segments = this->binary_->segments();
while (current_offset < end_offset) { while (current_offset < end_offset) {
uint8_t imm = this->stream_->read_integer<uint8_t>(current_offset) & BIND_IMMEDIATE_MASK; uint8_t imm = this->stream_->read_integer<uint8_t>(current_offset) & BIND_IMMEDIATE_MASK;
uint8_t opcode = this->stream_->read_integer<uint8_t>(current_offset) & BIND_OPCODE_MASK; uint8_t opcode = this->stream_->read_integer<uint8_t>(current_offset) & BIND_OPCODE_MASK;
@ -1284,7 +1303,8 @@ void BinaryParser::parse_dyldinfo_lazy_bind() {
symbol_name, symbol_name,
library_ordinal, library_ordinal,
addend, addend,
is_weak_import); is_weak_import,
segments);
segment_offset += sizeof(pint_t); segment_offset += sizeof(pint_t);
break; break;
} }
@ -1306,12 +1326,12 @@ void BinaryParser::do_bind(BINDING_CLASS cls,
const std::string& symbol_name, const std::string& symbol_name,
int32_t ord, int32_t ord,
int64_t addend, int64_t addend,
bool is_weak) { bool is_weak,
it_segments& segments) {
using pint_t = typename MACHO_T::uint; using pint_t = typename MACHO_T::uint;
it_segments segments = this->binary_->segments();
if (segment_idx >= segments.size()) { if (segment_idx >= segments.size()) {
LOG(ERROR) << "Wrong index (" << std::dec << segment_idx << ")"; LOG(ERROR) << "Wrong index (" << std::dec << segment_idx << ")";
return; return;
@ -1381,8 +1401,7 @@ void BinaryParser::do_bind(BINDING_CLASS cls,
} }
try { try {
uint64_t offset = this->binary_->virtual_address_to_offset(reloc->address()); Section& section = this->binary_->section_from_virtual_address(reloc->address());
Section& section = this->binary_->section_from_offset(offset);
reloc->section_ = &section; reloc->section_ = &section;
} catch (const not_found&) { } catch (const not_found&) {
VLOG(VDEBUG) << "Unable to tie a section with dyld relocation at 0x" << std::hex << reloc->address(); VLOG(VDEBUG) << "Unable to tie a section with dyld relocation at 0x" << std::hex << reloc->address();
@ -1399,7 +1418,7 @@ void BinaryParser::do_bind(BINDING_CLASS cls,
} }
if (not reloc_exists) { if (not reloc_exists) {
segment.relocations_.push_back(reloc); segment.relocations_.emplace(reloc);
} }
this->binary_->dyld_info().binding_info_.push_back(binding_info); this->binary_->dyld_info().binding_info_.push_back(binding_info);
VLOG(VDEBUG) << to_string(cls) << segment.name() << " - " << symbol_name; VLOG(VDEBUG) << to_string(cls) << segment.name() << " - " << symbol_name;
@ -1423,18 +1442,12 @@ void BinaryParser::do_rebase(uint8_t type, uint8_t segment_idx, uint64_t segment
Relocation* reloc = nullptr; Relocation* reloc = nullptr;
bool reloc_exists = false; bool reloc_exists = false;
auto&& it_reloc = std::find_if( reloc = new RelocationDyld{address, type};
std::begin(segment.relocations_), auto&& it_reloc = segment.relocations_.find(reloc);
std::end(segment.relocations_),
[&address] (const Relocation* r) {
return r->address() == address;
});
if (it_reloc != std::end(segment.relocations_)) { if (it_reloc != std::end(segment.relocations_)) {
delete reloc;
reloc = *it_reloc; reloc = *it_reloc;
reloc_exists = true; reloc_exists = true;
} else {
reloc = new RelocationDyld{address, type};
} }
reloc->architecture_ = this->binary_->header().cpu_type(); reloc->architecture_ = this->binary_->header().cpu_type();
@ -1459,11 +1472,10 @@ void BinaryParser::do_rebase(uint8_t type, uint8_t segment_idx, uint64_t segment
LOG(ERROR) << "Unsuported relocation type: 0x" << std::hex << type; LOG(ERROR) << "Unsuported relocation type: 0x" << std::hex << type;
} }
} }
if (not reloc_exists) { if (not reloc_exists) {
segment.relocations_.push_back(reloc); segment.relocations_.insert(it_reloc, reloc);
} }
}; }

View File

@ -67,11 +67,11 @@ const std::string& Export::name(void) const {
} }
it_export_entries Export::entries(void) { it_export_entries Export::entries(void) {
return it_export_entries{std::ref(this->entries_)}; return this->entries_;
} }
it_const_export_entries Export::entries(void) const { it_const_export_entries Export::entries(void) const {
return it_const_export_entries{std::cref(this->entries_)}; return this->entries_;
} }
void Export::export_flags(uint32_t flags) { void Export::export_flags(uint32_t flags) {

View File

@ -63,9 +63,9 @@ vector_iostream& vector_iostream::write(std::vector<uint8_t>&& s) {
} }
auto&& it = std::begin(this->raw_); auto&& it = std::begin(this->raw_);
std::advance(it, static_cast<size_t>(this->tellp())); std::advance(it, static_cast<size_t>(this->tellp()));
std::copy( std::move(
std::make_move_iterator(std::begin(s)), std::begin(s),
std::make_move_iterator(std::end(s)), it); std::end(s), it);
this->current_pos_ += s.size(); this->current_pos_ += s.size();
return *this; return *this;

View File

@ -49,6 +49,10 @@ class TestMachO(TestCase):
self.assertEqual(sshd.version_min.version, [10, 11, 0]) self.assertEqual(sshd.version_min.version, [10, 11, 0])
self.assertEqual(sshd.version_min.sdk, [10, 11, 0]) self.assertEqual(sshd.version_min.sdk, [10, 11, 0])
def test_va2offset(self):
dd = lief.parse(get_sample('MachO/MachO64_x86-64_binary_dd.bin'))
self.assertEqual(dd.virtual_address_to_offset(0x100004054), 0x4054)
def test_thread_cmd(self): def test_thread_cmd(self):
micromacho = lief.parse(get_sample('MachO/MachO32_x86_binary_micromacho.bin')) micromacho = lief.parse(get_sample('MachO/MachO32_x86_binary_micromacho.bin'))
@ -68,30 +72,31 @@ class TestMachO(TestCase):
self.assertEqual(len(relocations), 2) self.assertEqual(len(relocations), 2)
# 0 # 0
self.assertEqual(relocations[0].address, 0x233) self.assertEqual(relocations[0].address, 0x21b)
self.assertEqual(relocations[0].type, 2) self.assertEqual(relocations[0].type, 1)
self.assertEqual(relocations[0].size, 32) self.assertEqual(relocations[0].size, 32)
self.assertEqual(relocations[0].is_scattered, False) self.assertEqual(relocations[0].is_scattered, False)
self.assertEqual(relocations[0].has_symbol, True) self.assertEqual(relocations[0].has_symbol, False)
self.assertEqual(relocations[0].symbol.name, "_printf")
self.assertEqual(relocations[0].has_section, True) self.assertEqual(relocations[0].has_section, True)
self.assertEqual(relocations[0].section.name, text_section.name) self.assertEqual(relocations[0].section.name, text_section.name)
# 1 # 1
self.assertEqual(relocations[1].address, 0x21b) self.assertEqual(relocations[1].address, 0x233)
self.assertEqual(relocations[1].type, 1) self.assertEqual(relocations[1].type, 2)
self.assertEqual(relocations[1].size, 32) self.assertEqual(relocations[1].size, 32)
self.assertEqual(relocations[1].is_scattered, False) self.assertEqual(relocations[1].is_scattered, False)
self.assertEqual(relocations[1].has_symbol, False) self.assertEqual(relocations[1].has_symbol, True)
self.assertEqual(relocations[1].symbol.name, "_printf")
self.assertEqual(relocations[1].has_section, True) self.assertEqual(relocations[1].has_section, True)
self.assertEqual(relocations[1].section.name, text_section.name) self.assertEqual(relocations[1].section.name, text_section.name)
# __compact_unwind__LD Section # __compact_unwind__LD Section
cunwind_section = helloworld.get_section("__compact_unwind") cunwind_section = helloworld.get_section("__compact_unwind")
relocations = cunwind_section.relocations relocations = cunwind_section.relocations