4
0
mirror of https://github.com/QuasarApp/LIEF.git synced 2025-05-05 00:29:34 +00:00

Fix performances issues

Fix 
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

@ -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)

@ -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_ = &section;
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_ = &section;
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_ = &section;
if (not reloc->has_section()) {
reloc->section_ = &section;
}
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_ = &section;
} 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_ = &section;
} 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