mirror of
https://github.com/QuasarApp/LIEF.git
synced 2025-05-05 00:29:34 +00:00
parent
acc35aa7e5
commit
accf47ebf2
api/python/MachO/objects
examples
include/LIEF
src
Abstract
ELF
Binary.cppBuilder.tccParser.tccSection.cppSegment.cppSymbolVersionDefinition.cppSymbolVersionRequirement.cpp
MachO
PE
iostream.cpptests/macho
@ -102,6 +102,11 @@ void init_MachO_Binary_class(py::module& m) {
|
||||
"Return the " RST_CLASS_REF(lief.MachO.Section) " which contains the offset",
|
||||
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",
|
||||
static_cast<SegmentCommand& (Binary::*)(uint64_t)>(&Binary::segment_from_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",
|
||||
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)
|
||||
|
||||
.def_property_readonly("has_entrypoint",
|
||||
@ -214,6 +219,16 @@ void init_MachO_Binary_class(py::module& m) {
|
||||
"name"_a,
|
||||
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__",
|
||||
[] (const Binary& binary)
|
||||
|
@ -23,6 +23,7 @@ set(LIEF_MACHO_CPP_EXAMPLES
|
||||
set(LIEF_CPP_EXAMPLES
|
||||
abstract_reader.cpp
|
||||
logging.cpp
|
||||
benchmark.cpp
|
||||
)
|
||||
|
||||
if (LIEF_ELF)
|
||||
|
42
examples/cpp/benchmark.cpp
Normal file
42
examples/cpp/benchmark.cpp
Normal 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;
|
||||
|
||||
}
|
||||
|
@ -125,8 +125,8 @@ def print_segments(binary):
|
||||
segment.name,
|
||||
segment.virtual_address,
|
||||
segment.virtual_size,
|
||||
segment.file_size,
|
||||
segment.file_offset,
|
||||
segment.file_size,
|
||||
segment.max_protection,
|
||||
segment.init_protection,
|
||||
sections))
|
||||
@ -425,7 +425,6 @@ def print_relocations(binary):
|
||||
if reloc.has_section:
|
||||
secseg_name = reloc.section.name
|
||||
|
||||
|
||||
print(f_value.format(
|
||||
address=reloc.address,
|
||||
size=reloc.size,
|
||||
|
@ -51,8 +51,20 @@ class DLL_PUBLIC Relocation : public Visitable {
|
||||
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:
|
||||
uint64_t address_;
|
||||
@ -60,5 +72,7 @@ class DLL_PUBLIC Relocation : public Visitable {
|
||||
// type_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -49,7 +49,7 @@ class DLL_PUBLIC Builder {
|
||||
void build(void);
|
||||
|
||||
template<typename ELF_T>
|
||||
void build_header(void);
|
||||
void build(const Header& header);
|
||||
|
||||
template<typename ELF_T>
|
||||
void build_sections(void);
|
||||
|
@ -149,16 +149,16 @@ class DLL_PUBLIC Parser : public LIEF::Parser {
|
||||
//! @brief Parse Dynamic relocations
|
||||
//!
|
||||
//! It use DT_REL/DT_RELA dynamic entries to parse it
|
||||
template<typename ELF_T>
|
||||
void parse_dynamic_relocations(uint64_t relocations_offset, uint64_t size, bool isRela);
|
||||
template<typename ELF_T, typename REL_T>
|
||||
void parse_dynamic_relocations(uint64_t relocations_offset, uint64_t size);
|
||||
|
||||
//! @brief Parse `.plt.got`/`got` relocations
|
||||
//!
|
||||
//! For:
|
||||
//! * ELF32 it uses **DT_JMPREL** and **DT_PLTRELSZ**
|
||||
//! * ELF64 it uses **DT_PLTREL** and **DT_PLTRELSZ**
|
||||
template<typename ELF_T>
|
||||
void parse_pltgot_relocations(uint64_t offset, uint64_t size, bool isRela);
|
||||
template<typename ELF_T, typename REL_T>
|
||||
void parse_pltgot_relocations(uint64_t offset, uint64_t size);
|
||||
|
||||
|
||||
//! @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
|
||||
//! use parse relocations by using LIEF::ELF::Segment. This method parse relocations
|
||||
//! that are not reachable through segments (For example Object file).
|
||||
template<typename ELF_T>
|
||||
void parse_section_relocations(uint64_t offset, uint64_t size, bool isRela);
|
||||
template<typename ELF_T, typename REL_T>
|
||||
void parse_section_relocations(uint64_t offset, uint64_t size);
|
||||
|
||||
//! @brief Parse SymbolVersionRequirement
|
||||
//!
|
||||
|
@ -72,6 +72,8 @@ class DLL_PUBLIC Section : public LIEF::Section {
|
||||
//! @brief Set section content
|
||||
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
|
||||
uint64_t flags(void) const;
|
||||
|
||||
|
@ -80,6 +80,7 @@ class DLL_PUBLIC Segment : public Visitable {
|
||||
void virtual_size(uint64_t virtualSize);
|
||||
void alignment(uint64_t alignment);
|
||||
void content(const std::vector<uint8_t>& content);
|
||||
void content(std::vector<uint8_t>&& content);
|
||||
|
||||
it_sections sections(void);
|
||||
it_const_sections sections(void) const;
|
||||
|
@ -142,10 +142,14 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
|
||||
Section& section_from_offset(uint64_t offset);
|
||||
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
|
||||
uint64_t virtual_address_to_offset(uint64_t virtualAddress) const;
|
||||
|
||||
|
||||
// @brief Return binary's @link MachO::SegmentCommand segment command
|
||||
// which hold the 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);
|
||||
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
|
||||
virtual void accept(LIEF::Visitor& visitor) const override;
|
||||
|
||||
@ -286,6 +297,9 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
|
||||
commands_t commands_;
|
||||
symbols_t symbols_;
|
||||
|
||||
// Cached relocations from segment / sections
|
||||
mutable relocations_t relocations_;
|
||||
|
||||
protected:
|
||||
uint64_t fat_offset_ = 0;
|
||||
};
|
||||
|
@ -104,7 +104,8 @@ class DLL_PUBLIC BinaryParser : public LIEF::Parser {
|
||||
const std::string& symbol_name,
|
||||
int32_t ord,
|
||||
int64_t addend,
|
||||
bool is_weak);
|
||||
bool is_weak,
|
||||
it_segments& segments);
|
||||
|
||||
|
||||
template<class MACHO_T>
|
||||
|
@ -120,6 +120,8 @@ class DLL_PUBLIC Relocation : public LIEF::Relocation {
|
||||
|
||||
DLL_PUBLIC friend std::ostream& operator<<(std::ostream& os, const Relocation& relocation);
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
Symbol* symbol_;
|
||||
uint8_t type_;
|
||||
|
@ -34,10 +34,12 @@ namespace MachO {
|
||||
|
||||
class BinaryParser;
|
||||
class SegmentCommand;
|
||||
class Binary;
|
||||
|
||||
class DLL_PUBLIC Section : public LIEF::Section {
|
||||
|
||||
friend class BinaryParser;
|
||||
friend class Binary;
|
||||
|
||||
public:
|
||||
Section(void);
|
||||
|
@ -32,12 +32,14 @@
|
||||
namespace LIEF {
|
||||
namespace MachO {
|
||||
class BinaryParser;
|
||||
class Binary;
|
||||
|
||||
//! @class SegmentCommand
|
||||
//! @brief Class which represent a MachO Segment
|
||||
class DLL_PUBLIC SegmentCommand : public LoadCommand {
|
||||
|
||||
friend class BinaryParser;
|
||||
friend class Binary;
|
||||
|
||||
public:
|
||||
SegmentCommand(void);
|
||||
|
@ -16,7 +16,9 @@
|
||||
#ifndef LIEF_MACHO_TYPE_TRAITS_H_
|
||||
#define LIEF_MACHO_TYPE_TRAITS_H_
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include "LIEF/iterators.hpp"
|
||||
#include "LIEF/Abstract/Relocation.hpp"
|
||||
|
||||
namespace LIEF {
|
||||
namespace MachO {
|
||||
@ -30,6 +32,12 @@ class Relocation;
|
||||
class BindingInfo;
|
||||
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 commands_t = std::vector<LoadCommand*>;
|
||||
@ -58,9 +66,9 @@ using sections_t = std::vector<Section*>;
|
||||
using it_sections = 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 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 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_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 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_const_export_info = const_ref_iterator<export_info_t>; ///< Iterator's type for export_info_t (const)
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,17 +44,18 @@ class ref_iterator : public std::iterator<
|
||||
using DT = decay_t<T>;
|
||||
|
||||
ref_iterator(T container) :
|
||||
container_{std::forward<T>(container)}
|
||||
container_{std::forward<T>(container)},
|
||||
distance_{0}
|
||||
{
|
||||
this->it_ = std::begin(container_);
|
||||
}
|
||||
|
||||
ref_iterator(const ref_iterator& copy) :
|
||||
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_, d);
|
||||
std::advance(this->it_, this->distance_);
|
||||
}
|
||||
|
||||
|
||||
@ -66,11 +67,13 @@ class ref_iterator : public std::iterator<
|
||||
void swap(ref_iterator& other) {
|
||||
std::swap(this->container_, other.container_);
|
||||
std::swap(this->it_, other.it_);
|
||||
std::swap(this->distance_, other.distance_);
|
||||
}
|
||||
|
||||
|
||||
ref_iterator& operator++(void) {
|
||||
it_++;
|
||||
this->it_ = std::next(this->it_);
|
||||
this->distance_++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -82,7 +85,8 @@ class ref_iterator : public std::iterator<
|
||||
|
||||
ref_iterator& operator--(void) {
|
||||
if (this->it_ != std::begin(container_)) {
|
||||
this->it_--;
|
||||
this->it_ = std::prev(this->it_);
|
||||
this->distance_--;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -96,6 +100,7 @@ class ref_iterator : public std::iterator<
|
||||
|
||||
ref_iterator& operator+=(const typename ref_iterator::difference_type& movement) {
|
||||
std::advance(this->it_, movement);
|
||||
this->distance_ += movement;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -145,7 +150,7 @@ class ref_iterator : public std::iterator<
|
||||
|
||||
|
||||
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 {
|
||||
@ -168,19 +173,18 @@ class ref_iterator : public std::iterator<
|
||||
}
|
||||
|
||||
ref_iterator begin(void) {
|
||||
return {this->container_};
|
||||
return this->container_;
|
||||
}
|
||||
|
||||
ref_iterator end(void) {
|
||||
ref_iterator it = ref_iterator{this->container_};
|
||||
it.it_ = std::end(it.container_);
|
||||
it.distance_ = it.size();
|
||||
return it;
|
||||
}
|
||||
|
||||
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()));
|
||||
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);
|
||||
return (this->size() == other.size() and this->distance_ == other.distance_);
|
||||
}
|
||||
|
||||
bool operator!=(const ref_iterator& other) const {
|
||||
@ -225,6 +229,7 @@ class ref_iterator : public std::iterator<
|
||||
private:
|
||||
T container_;
|
||||
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&> {
|
||||
public:
|
||||
|
||||
using DT = decay_t<CT>;
|
||||
|
||||
const_ref_iterator(CT container) :
|
||||
container_{std::forward<CT>(container)}
|
||||
container_{std::forward<CT>(container)},
|
||||
distance_{0}
|
||||
{
|
||||
this->it_ = this->container_.cbegin();
|
||||
}
|
||||
@ -251,10 +256,10 @@ class const_ref_iterator : public std::iterator<
|
||||
|
||||
const_ref_iterator(const const_ref_iterator& copy) :
|
||||
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_, d);
|
||||
std::advance(this->it_, this->distance_);
|
||||
}
|
||||
|
||||
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) {
|
||||
std::swap(this->container_, other.container_);
|
||||
std::swap(this->it_, other.it_);
|
||||
std::swap(this->distance_, other.distance_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const_ref_iterator& operator++() {
|
||||
it_++;
|
||||
this->it_ = std::next(this->it_);
|
||||
this->distance_++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -282,7 +289,8 @@ class const_ref_iterator : public std::iterator<
|
||||
|
||||
const_ref_iterator& operator--(void) {
|
||||
if (this->it_ != container_.cbegin()) {
|
||||
this->it_--;
|
||||
this->it_ = std::prev(this->it_);
|
||||
this->distance_--;
|
||||
}
|
||||
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) {
|
||||
std::advance(this->it_, movement);
|
||||
this->distance_ += movement;
|
||||
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 {
|
||||
return std::distance(rhs, *this);
|
||||
return this->distance_ - rhs.distance_;
|
||||
}
|
||||
|
||||
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 {
|
||||
return {this->container_};
|
||||
return this->container_;
|
||||
}
|
||||
|
||||
const_ref_iterator cend(void) const {
|
||||
const_ref_iterator it{this->container_};
|
||||
it.it_ = it.container_.cend();
|
||||
it.distance_ = it.size();
|
||||
return it;
|
||||
}
|
||||
|
||||
@ -381,9 +391,7 @@ class const_ref_iterator : public std::iterator<
|
||||
}
|
||||
|
||||
bool operator==(const const_ref_iterator& other) const {
|
||||
size_t d1 = static_cast<size_t>(std::distance(this->it_, this->container_.cend()));
|
||||
size_t d2 = static_cast<size_t>(std::distance(other.it_, other.container_.cend()));
|
||||
return (this->size() == other.size() and d1 == d2);
|
||||
return (this->size() == other.size() and this->distance_ == other.distance_);
|
||||
}
|
||||
|
||||
bool operator!=(const const_ref_iterator& other) const {
|
||||
@ -426,6 +434,7 @@ class const_ref_iterator : public std::iterator<
|
||||
private:
|
||||
T container_;
|
||||
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&)>;
|
||||
|
||||
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_);
|
||||
@ -462,10 +474,10 @@ class filter_iterator : public std::iterator<
|
||||
size_c_{0},
|
||||
container_{copy.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_, d);
|
||||
std::advance(this->it_, this->distance_);
|
||||
}
|
||||
|
||||
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->filter_, other.filter_);
|
||||
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 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;
|
||||
}
|
||||
|
||||
@ -548,11 +564,7 @@ class filter_iterator : public std::iterator<
|
||||
|
||||
|
||||
bool operator==(const filter_iterator& other) const {
|
||||
|
||||
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);
|
||||
return (this->container_.size() == other.container_.size() and this->distance_ == other.distance_);
|
||||
}
|
||||
|
||||
bool operator!=(const filter_iterator& other) const {
|
||||
@ -562,13 +574,14 @@ class filter_iterator : public std::iterator<
|
||||
private:
|
||||
void next(void) {
|
||||
if (this->it_ == std::end(this->container_)) {
|
||||
this->distance_ = this->container_.size();
|
||||
return;
|
||||
}
|
||||
|
||||
this->it_ = std::find_if(
|
||||
std::next(this->it_),
|
||||
std::end(this->container_),
|
||||
this->filter_);
|
||||
do {
|
||||
this->it_ = std::next(this->it_);
|
||||
this->distance_++;
|
||||
} 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_;
|
||||
typename DT::iterator it_;
|
||||
filter_t filter_;
|
||||
typename filter_iterator::difference_type distance_;
|
||||
};
|
||||
|
||||
// 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)>;
|
||||
|
||||
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();
|
||||
|
||||
@ -611,10 +628,10 @@ class const_filter_iterator : public std::iterator<
|
||||
size_c_{0},
|
||||
container_{copy.container_},
|
||||
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_, d);
|
||||
std::advance(this->it_, this->distance_);
|
||||
}
|
||||
|
||||
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->filter_, other.filter_);
|
||||
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 it{this->container_, this->filter_};
|
||||
it.it_ = it.container_.cend();
|
||||
it.it_ = it.container_.cend();
|
||||
it.distance_ = it.container_.size();
|
||||
return it;
|
||||
}
|
||||
|
||||
@ -707,12 +726,8 @@ class const_filter_iterator : public std::iterator<
|
||||
return *it;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool operator==(const const_filter_iterator& other) const {
|
||||
size_t d1 = static_cast<size_t>(std::distance(this->it_, this->container_.cend()));
|
||||
size_t d2 = static_cast<size_t>(std::distance(other.it_, other.container_.cend()));
|
||||
return (this->container_.size() == other.container_.size() and d1 == d2);
|
||||
return (this->container_.size() == other.container_.size() and this->distance_ == other.distance_);
|
||||
}
|
||||
|
||||
bool operator!=(const const_filter_iterator& other) const {
|
||||
@ -723,19 +738,21 @@ class const_filter_iterator : public std::iterator<
|
||||
void next(void) {
|
||||
|
||||
if (this->it_ == this->container_.cend()) {
|
||||
this->distance_ = this->container_.size();
|
||||
return;
|
||||
}
|
||||
|
||||
this->it_ = std::find_if(
|
||||
std::next(this->it_),
|
||||
this->container_.cend(),
|
||||
this->filter_);
|
||||
do {
|
||||
this->it_ = std::next(this->it_);
|
||||
this->distance_++;
|
||||
} while(this->it_ != this->container_.cend() and not this->filter_(*this->it_));
|
||||
}
|
||||
|
||||
mutable size_t size_c_;
|
||||
T container_;
|
||||
typename decay_t<decltype(container_)>::const_iterator it_;
|
||||
filter_t filter_;
|
||||
typename const_filter_iterator::difference_type distance_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -77,6 +77,23 @@ bool Relocation::operator!=(const Relocation& rhs) const {
|
||||
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) {
|
||||
os << std::hex;
|
||||
os << std::left
|
||||
|
@ -80,23 +80,23 @@ LIEF::sections_t Binary::get_abstract_sections(void) {
|
||||
// ========
|
||||
|
||||
it_sections Binary::sections(void) {
|
||||
return it_sections{std::ref(this->sections_)};
|
||||
return this->sections_;
|
||||
}
|
||||
|
||||
|
||||
it_const_sections Binary::sections(void) const {
|
||||
return it_const_sections{std::cref(this->sections_)};
|
||||
return this->sections_;
|
||||
}
|
||||
|
||||
// Segments
|
||||
// ========
|
||||
|
||||
it_segments Binary::segments(void) {
|
||||
return it_segments{std::ref(this->segments_)};
|
||||
return this->segments_;
|
||||
}
|
||||
|
||||
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) {
|
||||
return it_symbols_version{std::ref(this->symbol_version_table_)};
|
||||
return this->symbol_version_table_;
|
||||
}
|
||||
|
||||
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
|
||||
// -------------------------
|
||||
|
||||
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 {
|
||||
return it_const_symbols_version_definition{std::cref(this->symbol_version_definition_)};
|
||||
return this->symbol_version_definition_;
|
||||
}
|
||||
|
||||
// Symbol version requirement
|
||||
// --------------------------
|
||||
|
||||
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 {
|
||||
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) {
|
||||
|
@ -114,7 +114,7 @@ void Builder::build(void) {
|
||||
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>
|
||||
void Builder::build_header(void) {
|
||||
void Builder::build(const Header& header) {;
|
||||
using Elf_Half = typename ELF_T::Elf_Half;
|
||||
using Elf_Word = typename ELF_T::Elf_Word;
|
||||
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;
|
||||
|
||||
const Header& header = this->binary_->header();
|
||||
Elf_Ehdr ehdr;
|
||||
|
||||
ehdr.e_type = static_cast<Elf_Half>(header.file_type());
|
||||
@ -246,9 +245,8 @@ void Builder::build_sections(void) {
|
||||
|
||||
// Write Section's content
|
||||
if (section->size() > 0) {
|
||||
const std::vector<uint8_t>& content = section->content();
|
||||
this->ios_.seekp(section->file_offset());
|
||||
this->ios_.write(content.data(), section->size());
|
||||
this->ios_.seekp(section->file_offset());
|
||||
this->ios_.write(section->content());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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_.write(section_names.data(), section_names.size());
|
||||
//string_names_section->content(section_names);
|
||||
this->ios_.write(std::move(section_names));
|
||||
|
||||
|
||||
}
|
||||
@ -349,13 +345,13 @@ void Builder::build_segments(void) {
|
||||
VLOG(VDEBUG) << "Size: 0x" << std::hex << content.size();
|
||||
|
||||
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();
|
||||
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));
|
||||
}
|
||||
|
||||
symbol_str_section.content(string_table);
|
||||
symbol_section.content(content);
|
||||
symbol_str_section.content(std::move(string_table));
|
||||
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));
|
||||
array_section.content(array_content);
|
||||
array_section.content(std::move(array_content));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -578,7 +574,7 @@ void Builder::build_dynamic_section(void) {
|
||||
Segment dynamic_load;
|
||||
dynamic_load.type(SEGMENT_TYPES::PT_LOAD);
|
||||
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);
|
||||
|
||||
auto&& it_dynamic = std::find_if(
|
||||
@ -615,7 +611,7 @@ void Builder::build_dynamic_section(void) {
|
||||
Segment dynstr;
|
||||
dynstr.type(SEGMENT_TYPES::PT_LOAD);
|
||||
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);
|
||||
dyn_strtab_section.virtual_address(new_segment.virtual_address());
|
||||
@ -633,8 +629,8 @@ void Builder::build_dynamic_section(void) {
|
||||
}
|
||||
|
||||
VLOG(VDEBUG) << dyn_strtab_section;
|
||||
dyn_strtab_section.content(dynamic_strings_raw);
|
||||
dyn_section.content(dynamic_table_raw);
|
||||
dyn_strtab_section.content(std::move(dynamic_strings_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
|
||||
@ -845,7 +841,7 @@ void Builder::build_symbol_gnuhash(void) {
|
||||
}
|
||||
|
||||
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"
|
||||
this->build_empty_symbol_gnuhash();
|
||||
}
|
||||
@ -965,7 +961,7 @@ void Builder::build_dynamic_symbols(void) {
|
||||
Segment dynstr;
|
||||
dynstr.type(SEGMENT_TYPES::PT_LOAD);
|
||||
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);
|
||||
|
||||
@ -987,7 +983,7 @@ void Builder::build_dynamic_symbols(void) {
|
||||
Segment dynsym_load;
|
||||
dynsym_load.type(SEGMENT_TYPES::PT_LOAD);
|
||||
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);
|
||||
|
||||
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";
|
||||
string_table_section.content(string_table_raw);
|
||||
symbol_table_section.content(symbol_table_raw);
|
||||
string_table_section.content(std::move(string_table_raw));
|
||||
symbol_table_section.content(std::move(symbol_table_raw));
|
||||
|
||||
}
|
||||
|
||||
@ -1151,7 +1147,7 @@ void Builder::build_dynamic_relocations(void) {
|
||||
Segment relocation_load;
|
||||
relocation_load.type(SEGMENT_TYPES::PT_LOAD);
|
||||
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);
|
||||
|
||||
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>
|
||||
@ -1290,7 +1286,7 @@ void Builder::build_pltgot_relocations(void) {
|
||||
Segment relocation_load;
|
||||
relocation_load.type(SEGMENT_TYPES::PT_LOAD);
|
||||
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);
|
||||
|
||||
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>();
|
||||
}
|
||||
|
||||
relocation_section.content(content);
|
||||
relocation_section.content(std::move(content));
|
||||
}
|
||||
|
||||
|
||||
@ -1421,7 +1417,7 @@ void Builder::build_symbol_requirement(void) {
|
||||
Segment dynstr;
|
||||
dynstr.type(SEGMENT_TYPES::PT_LOAD);
|
||||
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);
|
||||
|
||||
@ -1439,8 +1435,8 @@ void Builder::build_symbol_requirement(void) {
|
||||
return this->build_symbol_requirement<ELF_T>();
|
||||
}
|
||||
|
||||
this->binary_->section_from_offset(svr_offset).content(svr_raw);
|
||||
dyn_str_section.content(dyn_str_raw);
|
||||
this->binary_->section_from_offset(svr_offset).content(std::move(svr_raw));
|
||||
dyn_str_section.content(std::move(dyn_str_raw));
|
||||
|
||||
}
|
||||
|
||||
@ -1538,7 +1534,7 @@ void Builder::build_symbol_definition(void) {
|
||||
Segment dynstr;
|
||||
dynstr.type(SEGMENT_TYPES::PT_LOAD);
|
||||
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);
|
||||
|
||||
@ -1559,8 +1555,8 @@ void Builder::build_symbol_definition(void) {
|
||||
this->binary_->get(DYNAMIC_TAGS::DT_STRSZ).value(dyn_str_raw.size());
|
||||
this->build_dynamic_section<ELF_T>();
|
||||
|
||||
this->binary_->section_from_offset(svd_offset).content(svd_raw);
|
||||
dyn_str_section.content(dyn_str_raw);
|
||||
this->binary_->section_from_offset(svd_offset).content(std::move(svd_raw));
|
||||
dyn_str_section.content(std::move(dyn_str_raw));
|
||||
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,7 @@ void Parser::parse_binary(void) {
|
||||
const uint64_t size = (*it_dynamic_relocations_size)->value();
|
||||
try {
|
||||
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&) {
|
||||
}
|
||||
}
|
||||
@ -169,7 +169,7 @@ void Parser::parse_binary(void) {
|
||||
const uint64_t size = (*it_dynamic_relocations_size)->value();
|
||||
try {
|
||||
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&) {
|
||||
|
||||
}
|
||||
@ -217,9 +217,11 @@ void Parser::parse_binary(void) {
|
||||
|
||||
try {
|
||||
const uint64_t offset = this->binary_->virtual_address_to_offset(virtual_address);
|
||||
this->parse_pltgot_relocations<ELF_T>(
|
||||
offset, size,
|
||||
type == DYNAMIC_TAGS::DT_RELA ? true : false);
|
||||
if (type == DYNAMIC_TAGS::DT_RELA) {
|
||||
this->parse_pltgot_relocations<ELF_T, typename ELF_T::Elf_Rela>(offset, size);
|
||||
} else {
|
||||
this->parse_pltgot_relocations<ELF_T, typename ELF_T::Elf_Rel>(offset, size);
|
||||
}
|
||||
} catch (const LIEF::exception& e) {
|
||||
LOG(WARNING) << e.what();
|
||||
|
||||
@ -414,20 +416,24 @@ void Parser::parse_binary(void) {
|
||||
}
|
||||
|
||||
// Try to parse using sections
|
||||
for (const Section& section : this->binary_->sections()) {
|
||||
if (section.type() == ELF_SECTION_TYPES::SHT_RELA or
|
||||
section.type() == ELF_SECTION_TYPES::SHT_REL) {
|
||||
if (this->binary_->relocations_.size() == 0) {
|
||||
for (const Section& section : this->binary_->sections()) {
|
||||
try {
|
||||
this->parse_section_relocations<ELF_T>(
|
||||
section.file_offset(),
|
||||
section.size(),
|
||||
section.type() == ELF_SECTION_TYPES::SHT_RELA);
|
||||
if (section.type() == ELF_SECTION_TYPES::SHT_REL) {
|
||||
this->parse_section_relocations<ELF_T, typename ELF_T::Elf_Rel>(
|
||||
section.file_offset(), section.size());
|
||||
|
||||
}
|
||||
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) {
|
||||
LOG(WARNING) << "Unable to parse relocations from section '"
|
||||
<< section.name() << "'"
|
||||
<< " (" << e.what() << ")";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -821,11 +827,11 @@ void Parser::parse_segments(void) {
|
||||
|
||||
|
||||
|
||||
template<typename ELF_T>
|
||||
void Parser::parse_dynamic_relocations(uint64_t relocations_offset, uint64_t size, bool isRela) {
|
||||
template<typename ELF_T, typename REL_T>
|
||||
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";
|
||||
using Elf_Rela = typename ELF_T::Elf_Rela;
|
||||
using Elf_Rel = typename ELF_T::Elf_Rel;
|
||||
|
||||
// Already parsed
|
||||
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;
|
||||
|
||||
if (isRela) {
|
||||
const uint32_t nb_entries = static_cast<uint32_t>(size / sizeof(Elf_Rela));
|
||||
const uint32_t nb_entries = static_cast<uint32_t>(size / sizeof(REL_T));
|
||||
|
||||
const Elf_Rela* relocEntry = reinterpret_cast<const Elf_Rela*>(
|
||||
this->stream_->read(relocations_offset, nb_entries * sizeof(Elf_Rela)));
|
||||
const REL_T* relocEntry = reinterpret_cast<const REL_T*>(
|
||||
this->stream_->read(relocations_offset, nb_entries * sizeof(REL_T)));
|
||||
|
||||
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();
|
||||
const 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++;
|
||||
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();
|
||||
const 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;
|
||||
}
|
||||
} 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(relocations_offset, nb_entries * sizeof(Elf_Rel)));
|
||||
|
||||
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++;
|
||||
}
|
||||
this->binary_->relocations_.push_back(reloc);
|
||||
relocEntry++;
|
||||
}
|
||||
} // build_dynamic_reclocations
|
||||
|
||||
@ -1276,10 +1258,10 @@ void Parser::parse_dynamic_entries(uint64_t offset, uint64_t size) {
|
||||
}
|
||||
|
||||
|
||||
template<typename ELF_T>
|
||||
void Parser::parse_pltgot_relocations(uint64_t offset, uint64_t size, bool isRela) {
|
||||
using Elf_Rela = typename ELF_T::Elf_Rela;
|
||||
using Elf_Rel = typename ELF_T::Elf_Rel;
|
||||
template<typename ELF_T, typename REL_T>
|
||||
void Parser::parse_pltgot_relocations(uint64_t 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");
|
||||
using Elf_Addr = typename ELF_T::Elf_Addr;
|
||||
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 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(Elf_Rela));
|
||||
const Elf_Rela* relocEntry = reinterpret_cast<const Elf_Rela*>(
|
||||
this->stream_->read(offset_relocations, nb_entries * sizeof(Elf_Rela)));
|
||||
const uint32_t nb_entries = static_cast<uint32_t>(size / sizeof(REL_T));
|
||||
const REL_T* relocEntry = reinterpret_cast<const REL_T*>(
|
||||
this->stream_->read(offset_relocations, nb_entries * sizeof(REL_T)));
|
||||
|
||||
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);
|
||||
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);
|
||||
if (idx > 0 and idx < this->binary_->dynamic_symbols_.size()) {
|
||||
reloc->symbol_ = this->binary_->dynamic_symbols_[idx];
|
||||
}
|
||||
|
||||
this->binary_->relocations_.push_back(reloc);
|
||||
relocEntry++;
|
||||
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];
|
||||
}
|
||||
} 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);
|
||||
if (idx > 0 and idx < this->binary_->dynamic_symbols_.size()) {
|
||||
reloc->symbol_ = this->binary_->dynamic_symbols_[idx];
|
||||
}
|
||||
|
||||
this->binary_->relocations_.push_back(reloc);
|
||||
relocEntry++;
|
||||
}
|
||||
this->binary_->relocations_.push_back(reloc);
|
||||
relocEntry++;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ELF_T>
|
||||
void Parser::parse_section_relocations(uint64_t offset, uint64_t size, bool isRela) {
|
||||
using Elf_Rela = typename ELF_T::Elf_Rela;
|
||||
using Elf_Rel = typename ELF_T::Elf_Rel;
|
||||
template<typename ELF_T, typename REL_T>
|
||||
void Parser::parse_section_relocations(uint64_t 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");
|
||||
|
||||
const uint64_t offset_relocations = offset;
|
||||
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(Elf_Rela));
|
||||
const Elf_Rela* relocEntry = reinterpret_cast<const Elf_Rela*>(
|
||||
this->stream_->read(offset_relocations, nb_entries * sizeof(Elf_Rela)));
|
||||
const uint32_t nb_entries = static_cast<uint32_t>(size / sizeof(REL_T));
|
||||
const REL_T* relocEntry = reinterpret_cast<const REL_T*>(
|
||||
this->stream_->read(offset_relocations, nb_entries * sizeof(REL_T)));
|
||||
|
||||
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);
|
||||
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++;
|
||||
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);
|
||||
}
|
||||
} 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);
|
||||
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++;
|
||||
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];
|
||||
} 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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
this->type_ = type;
|
||||
}
|
||||
@ -353,11 +393,11 @@ void Section::entry_size(uint64_t entry_size) {
|
||||
|
||||
|
||||
it_segments Section::segments(void) {
|
||||
return it_segments{std::ref(this->segments_)};
|
||||
return this->segments_;
|
||||
}
|
||||
|
||||
it_const_segments Section::segments(void) const {
|
||||
return it_const_segments{std::cref(this->segments_)};
|
||||
return this->segments_;
|
||||
}
|
||||
|
||||
void Section::accept(Visitor& visitor) const {
|
||||
|
@ -317,6 +317,39 @@ void Segment::content(const std::vector<uint8_t>& content) {
|
||||
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 {
|
||||
|
||||
visitor.visit(this->type());
|
||||
|
@ -102,11 +102,11 @@ uint32_t SymbolVersionDefinition::hash(void) const {
|
||||
}
|
||||
|
||||
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 {
|
||||
return it_const_symbols_version_aux{this->symbol_version_aux_};
|
||||
return this->symbol_version_aux_;
|
||||
|
||||
}
|
||||
|
||||
|
@ -85,12 +85,12 @@ uint32_t SymbolVersionRequirement::cnt(void) const {
|
||||
|
||||
|
||||
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 {
|
||||
return {this->symbol_version_aux_requirement_};
|
||||
return this->symbol_version_aux_requirement_;
|
||||
}
|
||||
|
||||
|
||||
|
@ -182,7 +182,7 @@ Header& Binary::header(void) {
|
||||
// ========
|
||||
|
||||
it_commands Binary::commands(void) {
|
||||
return it_commands{std::ref(this->commands_)};
|
||||
return this->commands_;
|
||||
}
|
||||
|
||||
it_const_commands Binary::commands(void) const {
|
||||
@ -193,18 +193,18 @@ it_const_commands Binary::commands(void) const {
|
||||
// =======
|
||||
|
||||
it_symbols Binary::symbols(void) {
|
||||
return it_symbols{std::ref(this->symbols_)};
|
||||
return this->symbols_;
|
||||
}
|
||||
|
||||
it_const_symbols Binary::symbols(void) const {
|
||||
return it_const_symbols{std::cref(this->symbols_)};
|
||||
return this->symbols_;
|
||||
}
|
||||
|
||||
it_libraries Binary::libraries(void) {
|
||||
libraries_t result;
|
||||
|
||||
for (LoadCommand* library: this->commands_) {
|
||||
if (dynamic_cast<DylibCommand*>(library)) {
|
||||
if (typeid(*library) == typeid(DylibCommand)) {
|
||||
result.push_back(dynamic_cast<DylibCommand*>(library));
|
||||
}
|
||||
}
|
||||
@ -216,7 +216,7 @@ it_const_libraries Binary::libraries(void) const {
|
||||
libraries_t result;
|
||||
|
||||
for (LoadCommand* library: this->commands_) {
|
||||
if (dynamic_cast<DylibCommand*>(library)) {
|
||||
if (typeid(*library) == typeid(DylibCommand)) {
|
||||
result.push_back(dynamic_cast<DylibCommand*>(library));
|
||||
}
|
||||
}
|
||||
@ -225,24 +225,24 @@ it_const_libraries Binary::libraries(void) const {
|
||||
|
||||
it_segments Binary::segments(void) {
|
||||
segments_t result{};
|
||||
|
||||
result.reserve(this->commands_.size());
|
||||
for (LoadCommand* cmd: this->commands_) {
|
||||
if (dynamic_cast<SegmentCommand*>(cmd)) {
|
||||
if (typeid(*cmd) == typeid(SegmentCommand)) {
|
||||
result.push_back(dynamic_cast<SegmentCommand*>(cmd));
|
||||
}
|
||||
}
|
||||
return it_segments{result};
|
||||
return result;
|
||||
}
|
||||
|
||||
it_const_segments Binary::segments(void) const {
|
||||
segments_t result{};
|
||||
|
||||
result.reserve(this->commands_.size());
|
||||
for (LoadCommand* cmd: this->commands_) {
|
||||
if (dynamic_cast<SegmentCommand*>(cmd)) {
|
||||
if (typeid(*cmd) == typeid(SegmentCommand)) {
|
||||
result.push_back(dynamic_cast<SegmentCommand*>(cmd));
|
||||
}
|
||||
}
|
||||
return it_const_segments{result};
|
||||
return result;
|
||||
}
|
||||
|
||||
it_sections Binary::sections(void) {
|
||||
@ -252,7 +252,7 @@ it_sections Binary::sections(void) {
|
||||
result.push_back(&s);
|
||||
}
|
||||
}
|
||||
return it_sections{result};
|
||||
return result;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
return it_const_sections{result};
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -270,35 +270,35 @@ it_const_sections Binary::sections(void) const {
|
||||
it_relocations Binary::relocations(void) {
|
||||
relocations_t result;
|
||||
for (SegmentCommand& segment : this->segments()) {
|
||||
for (Relocation& r: segment.relocations()) {
|
||||
result.push_back(&r);
|
||||
}
|
||||
result.insert(std::begin(segment.relocations_), std::end(segment.relocations_));
|
||||
}
|
||||
|
||||
for (Section& section : this->sections()) {
|
||||
for (Relocation& r: section.relocations()) {
|
||||
result.push_back(&r);
|
||||
}
|
||||
result.insert(std::begin(section.relocations_), std::end(section.relocations_));
|
||||
}
|
||||
|
||||
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 {
|
||||
relocations_t result;
|
||||
for (const SegmentCommand& segment : this->segments()) {
|
||||
for (const Relocation& r: segment.relocations()) {
|
||||
result.push_back(const_cast<Relocation*>(&r));
|
||||
}
|
||||
result.insert(std::begin(segment.relocations_), std::end(segment.relocations_));
|
||||
}
|
||||
|
||||
for (const Section& section : this->sections()) {
|
||||
for (const Relocation& r: section.relocations()) {
|
||||
result.push_back(const_cast<Relocation*>(&r));
|
||||
}
|
||||
result.insert(std::begin(section.relocations_), std::end(section.relocations_));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
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 {
|
||||
it_const_segments segments = this->segments();
|
||||
auto&& it_segment = std::find_if(
|
||||
segments.cbegin(),
|
||||
segments.cend(),
|
||||
std::begin(segments),
|
||||
std::end(segments),
|
||||
[&virtual_address] (const SegmentCommand& segment) {
|
||||
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()) {
|
||||
@ -438,8 +460,8 @@ SegmentCommand& Binary::segment_from_virtual_address(uint64_t virtual_address) {
|
||||
const SegmentCommand& Binary::segment_from_offset(uint64_t offset) const {
|
||||
it_const_segments segments = this->segments();
|
||||
auto&& it_segment = std::find_if(
|
||||
segments.cbegin(),
|
||||
segments.cend(),
|
||||
std::begin(segments),
|
||||
std::end(segments),
|
||||
[&offset] (const SegmentCommand& segment) {
|
||||
return ((segment.file_offset() <= offset) and
|
||||
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 {
|
||||
|
||||
const SegmentCommand& segment = segment_from_virtual_address(virtual_address);
|
||||
|
||||
uint64_t base_address = segment.virtual_address() - segment.file_offset();
|
||||
uint64_t offset = virtual_address - base_address;
|
||||
|
||||
return offset;
|
||||
const uint64_t base_address = segment.virtual_address() - segment.file_offset();
|
||||
return virtual_address - base_address;
|
||||
}
|
||||
|
||||
|
||||
@ -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 header;
|
||||
const std::pair<ARCHITECTURES, std::set<MODES>>& am = this->header().abstract_architecture();
|
||||
|
@ -499,28 +499,25 @@ void BinaryParser::parse_relocations(Section& section) {
|
||||
|
||||
}
|
||||
|
||||
section.relocations_.reserve(numberof_relocations);
|
||||
for (size_t i = 0; i < numberof_relocations; ++i) {
|
||||
int32_t address = this->stream_->read_integer<int32_t>(current_reloc_offset);
|
||||
bool is_scattered = static_cast<bool>(address & R_SCATTERED);
|
||||
RelocationObject* reloc = nullptr;
|
||||
if (is_scattered) {
|
||||
const scattered_relocation_info* reloc_info = reinterpret_cast<const 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_ = §ion;
|
||||
section.relocations_.push_back(reloc);
|
||||
} else {
|
||||
const relocation_info* reloc_info = reinterpret_cast<const relocation_info*>(
|
||||
this->stream_->read(current_reloc_offset, sizeof(relocation_info)));
|
||||
RelocationObject* reloc = new RelocationObject{reloc_info};
|
||||
reloc = new RelocationObject{reloc_info};
|
||||
reloc->section_ = §ion;
|
||||
section.relocations_.push_back(reloc);
|
||||
|
||||
if (reloc_info->r_extern == 1 and reloc_info->r_symbolnum != R_ABS) {
|
||||
if (reloc_info->r_symbolnum < this->binary_->symbols().size()) {
|
||||
Symbol& symbol = this->binary_->symbols()[reloc_info->r_symbolnum];
|
||||
Relocation* relocation = section.relocations_.back();
|
||||
relocation->symbol_ = &symbol;
|
||||
reloc->symbol_ = &symbol;
|
||||
|
||||
VLOG(VDEBUG) << "Symbol: " << symbol.name();
|
||||
} else {
|
||||
@ -531,21 +528,22 @@ void BinaryParser::parse_relocations(Section& section) {
|
||||
if (reloc_info->r_extern == 0) {
|
||||
if (reloc_info->r_symbolnum < this->binary_->sections().size()) {
|
||||
Section& relsec = this->binary_->sections()[reloc_info->r_symbolnum];
|
||||
Relocation* relocation = section.relocations_.back();
|
||||
relocation->section_ = &relsec;
|
||||
reloc->section_ = &relsec;
|
||||
|
||||
VLOG(VDEBUG) << "Section: " << relsec.name();
|
||||
} else {
|
||||
LOG(WARNING) << "Relocation #" << std::dec << i << " of " << section.name() << " seems corrupted";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (not section.relocations_[i]->has_section()) {
|
||||
section.relocations_[i]->section_ = §ion;
|
||||
if (not reloc->has_section()) {
|
||||
reloc->section_ = §ion;
|
||||
}
|
||||
section.relocations_[i]->architecture_ = this->binary_->header().cpu_type();
|
||||
VLOG(VDEBUG) << *section.relocations_.back();;
|
||||
reloc->architecture_ = this->binary_->header().cpu_type();
|
||||
|
||||
section.relocations_.emplace(reloc);
|
||||
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 opcode = this->stream_->read_integer<uint8_t>(current_offset) & REBASE_OPCODE_MASK;
|
||||
current_offset += sizeof(uint8_t);
|
||||
|
||||
switch(static_cast<REBASE_OPCODES>(opcode)) {
|
||||
case REBASE_OPCODES::REBASE_OPCODE_DONE:
|
||||
{
|
||||
@ -704,15 +701,17 @@ void BinaryParser::parse_dyldinfo_rebases() {
|
||||
relocation.segment_ = &segment;
|
||||
}
|
||||
}
|
||||
|
||||
// Tie sections and relocations
|
||||
for (SegmentCommand& segment : segments) {
|
||||
uint64_t offset = 0;
|
||||
|
||||
for (Relocation& relocation : segment.relocations()) {
|
||||
if (not this->binary_->is_valid_addr(relocation.address())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
offset = this->binary_->virtual_address_to_offset(relocation.address());
|
||||
Section& section = this->binary_->section_from_offset(offset);
|
||||
Section& section = this->binary_->section_from_virtual_address(relocation.address());
|
||||
relocation.section_ = §ion;
|
||||
} catch (const not_found& e) {
|
||||
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
|
||||
for (Relocation& relocation : this->binary_->relocations()) {
|
||||
|
||||
if (not this->binary_->is_valid_addr(relocation.address())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint64_t address = relocation.address();
|
||||
auto&& it_symbol = std::find_if(
|
||||
std::begin(this->binary_->symbols_),
|
||||
@ -735,6 +740,7 @@ void BinaryParser::parse_dyldinfo_rebases() {
|
||||
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<int64_t, uint64_t> svalue_delta = {0, 0};
|
||||
|
||||
it_segments segments = this->binary_->segments();
|
||||
while (not done and current_offset < end_offset) {
|
||||
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;
|
||||
@ -900,7 +907,8 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
symbol_name,
|
||||
library_ordinal,
|
||||
addend,
|
||||
is_weak_import);
|
||||
is_weak_import,
|
||||
segments);
|
||||
segment_offset += sizeof(pint_t);
|
||||
break;
|
||||
}
|
||||
@ -915,7 +923,8 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
symbol_name,
|
||||
library_ordinal,
|
||||
addend,
|
||||
is_weak_import);
|
||||
is_weak_import,
|
||||
segments);
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
segment_offset += std::get<0>(value_delta) + sizeof(pint_t);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
@ -932,7 +941,8 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
symbol_name,
|
||||
library_ordinal,
|
||||
addend,
|
||||
is_weak_import);
|
||||
is_weak_import,
|
||||
segments);
|
||||
segment_offset += imm * sizeof(pint_t) + sizeof(pint_t);
|
||||
break;
|
||||
}
|
||||
@ -959,7 +969,8 @@ void BinaryParser::parse_dyldinfo_generic_bind() {
|
||||
symbol_name,
|
||||
library_ordinal,
|
||||
addend,
|
||||
is_weak_import);
|
||||
is_weak_import,
|
||||
segments);
|
||||
segment_offset += skip + sizeof(pint_t);
|
||||
}
|
||||
break;
|
||||
@ -1015,6 +1026,8 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
|
||||
std::pair<uint64_t, uint64_t> value_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) {
|
||||
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;
|
||||
@ -1086,7 +1099,8 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
|
||||
symbol_name,
|
||||
0,
|
||||
addend,
|
||||
is_weak_import);
|
||||
is_weak_import,
|
||||
segments);
|
||||
segment_offset += sizeof(pint_t);
|
||||
break;
|
||||
}
|
||||
@ -1102,7 +1116,8 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
|
||||
symbol_name,
|
||||
0,
|
||||
addend,
|
||||
is_weak_import);
|
||||
is_weak_import,
|
||||
segments);
|
||||
value_delta = this->stream_->read_uleb128(current_offset);
|
||||
segment_offset += std::get<0>(value_delta) + sizeof(pint_t);
|
||||
current_offset += std::get<1>(value_delta);
|
||||
@ -1120,7 +1135,8 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
|
||||
symbol_name,
|
||||
0,
|
||||
addend,
|
||||
is_weak_import);
|
||||
is_weak_import,
|
||||
segments);
|
||||
segment_offset += imm * sizeof(pint_t) + sizeof(pint_t);
|
||||
break;
|
||||
}
|
||||
@ -1148,7 +1164,8 @@ void BinaryParser::parse_dyldinfo_weak_bind() {
|
||||
symbol_name,
|
||||
0,
|
||||
addend,
|
||||
is_weak_import);
|
||||
is_weak_import,
|
||||
segments);
|
||||
segment_offset += skip + sizeof(pint_t);
|
||||
}
|
||||
break;
|
||||
@ -1202,6 +1219,8 @@ void BinaryParser::parse_dyldinfo_lazy_bind() {
|
||||
std::pair<uint64_t, uint64_t> value_delta = {0, 0};
|
||||
std::pair< int64_t, uint64_t> svalue_delta = {0, 0};
|
||||
|
||||
it_segments segments = this->binary_->segments();
|
||||
|
||||
while (current_offset < end_offset) {
|
||||
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;
|
||||
@ -1284,7 +1303,8 @@ void BinaryParser::parse_dyldinfo_lazy_bind() {
|
||||
symbol_name,
|
||||
library_ordinal,
|
||||
addend,
|
||||
is_weak_import);
|
||||
is_weak_import,
|
||||
segments);
|
||||
segment_offset += sizeof(pint_t);
|
||||
break;
|
||||
}
|
||||
@ -1306,12 +1326,12 @@ void BinaryParser::do_bind(BINDING_CLASS cls,
|
||||
const std::string& symbol_name,
|
||||
int32_t ord,
|
||||
int64_t addend,
|
||||
bool is_weak) {
|
||||
bool is_weak,
|
||||
it_segments& segments) {
|
||||
|
||||
|
||||
using pint_t = typename MACHO_T::uint;
|
||||
|
||||
it_segments segments = this->binary_->segments();
|
||||
if (segment_idx >= segments.size()) {
|
||||
LOG(ERROR) << "Wrong index (" << std::dec << segment_idx << ")";
|
||||
return;
|
||||
@ -1381,8 +1401,7 @@ void BinaryParser::do_bind(BINDING_CLASS cls,
|
||||
}
|
||||
|
||||
try {
|
||||
uint64_t offset = this->binary_->virtual_address_to_offset(reloc->address());
|
||||
Section& section = this->binary_->section_from_offset(offset);
|
||||
Section& section = this->binary_->section_from_virtual_address(reloc->address());
|
||||
reloc->section_ = §ion;
|
||||
} catch (const not_found&) {
|
||||
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) {
|
||||
segment.relocations_.push_back(reloc);
|
||||
segment.relocations_.emplace(reloc);
|
||||
}
|
||||
this->binary_->dyld_info().binding_info_.push_back(binding_info);
|
||||
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;
|
||||
bool reloc_exists = false;
|
||||
|
||||
auto&& it_reloc = std::find_if(
|
||||
std::begin(segment.relocations_),
|
||||
std::end(segment.relocations_),
|
||||
[&address] (const Relocation* r) {
|
||||
return r->address() == address;
|
||||
});
|
||||
|
||||
reloc = new RelocationDyld{address, type};
|
||||
auto&& it_reloc = segment.relocations_.find(reloc);
|
||||
if (it_reloc != std::end(segment.relocations_)) {
|
||||
delete reloc;
|
||||
reloc = *it_reloc;
|
||||
reloc_exists = true;
|
||||
} else {
|
||||
reloc = new RelocationDyld{address, 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;
|
||||
}
|
||||
}
|
||||
|
||||
if (not reloc_exists) {
|
||||
segment.relocations_.push_back(reloc);
|
||||
segment.relocations_.insert(it_reloc, reloc);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -67,11 +67,11 @@ const std::string& Export::name(void) const {
|
||||
}
|
||||
|
||||
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 {
|
||||
return it_const_export_entries{std::cref(this->entries_)};
|
||||
return this->entries_;
|
||||
}
|
||||
|
||||
void Export::export_flags(uint32_t flags) {
|
||||
|
@ -63,9 +63,9 @@ vector_iostream& vector_iostream::write(std::vector<uint8_t>&& s) {
|
||||
}
|
||||
auto&& it = std::begin(this->raw_);
|
||||
std::advance(it, static_cast<size_t>(this->tellp()));
|
||||
std::copy(
|
||||
std::make_move_iterator(std::begin(s)),
|
||||
std::make_move_iterator(std::end(s)), it);
|
||||
std::move(
|
||||
std::begin(s),
|
||||
std::end(s), it);
|
||||
|
||||
this->current_pos_ += s.size();
|
||||
return *this;
|
||||
|
@ -49,6 +49,10 @@ class TestMachO(TestCase):
|
||||
self.assertEqual(sshd.version_min.version, [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):
|
||||
micromacho = lief.parse(get_sample('MachO/MachO32_x86_binary_micromacho.bin'))
|
||||
@ -68,30 +72,31 @@ class TestMachO(TestCase):
|
||||
self.assertEqual(len(relocations), 2)
|
||||
|
||||
# 0
|
||||
self.assertEqual(relocations[0].address, 0x233)
|
||||
self.assertEqual(relocations[0].type, 2)
|
||||
self.assertEqual(relocations[0].address, 0x21b)
|
||||
self.assertEqual(relocations[0].type, 1)
|
||||
self.assertEqual(relocations[0].size, 32)
|
||||
|
||||
self.assertEqual(relocations[0].is_scattered, False)
|
||||
|
||||
self.assertEqual(relocations[0].has_symbol, True)
|
||||
self.assertEqual(relocations[0].symbol.name, "_printf")
|
||||
self.assertEqual(relocations[0].has_symbol, False)
|
||||
|
||||
self.assertEqual(relocations[0].has_section, True)
|
||||
self.assertEqual(relocations[0].section.name, text_section.name)
|
||||
|
||||
# 1
|
||||
self.assertEqual(relocations[1].address, 0x21b)
|
||||
self.assertEqual(relocations[1].type, 1)
|
||||
self.assertEqual(relocations[1].address, 0x233)
|
||||
self.assertEqual(relocations[1].type, 2)
|
||||
self.assertEqual(relocations[1].size, 32)
|
||||
|
||||
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].section.name, text_section.name)
|
||||
|
||||
|
||||
# __compact_unwind__LD Section
|
||||
cunwind_section = helloworld.get_section("__compact_unwind")
|
||||
relocations = cunwind_section.relocations
|
||||
|
Loading…
x
Reference in New Issue
Block a user