Skip to content

Commit b7b0bde

Browse files
committed
Add a *purpose* property to ELF relocations
Adding such property enables to store plt/got and dynamic relocations in a same container. (related to #51)
1 parent 44d5df3 commit b7b0bde

18 files changed

+184
-86
lines changed

api/python/ELF/objects/pyBinary.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ void init_ELF_Binary_class(py::module& m) {
3030

3131
// Binary object
3232
py::class_<Binary, LIEF::Binary>(m, "Binary", "ELF binary representation")
33-
.def(py::init<const std::string &, ELF_CLASS>())
33+
.def(py::init<const std::string&, ELF_CLASS>())
3434

3535
.def_property_readonly("type",
3636
&Binary::type,
@@ -77,12 +77,12 @@ void init_ELF_Binary_class(py::module& m) {
7777
py::return_value_policy::reference_internal)
7878

7979
.def_property_readonly("dynamic_relocations",
80-
static_cast<no_const_getter<it_relocations>>(&Binary::get_dynamic_relocations),
80+
static_cast<no_const_getter<it_dynamic_relocations>>(&Binary::get_dynamic_relocations),
8181
"Return an iterator to PLT/GOT " RST_CLASS_REF(lief.ELF.Relocation) "",
8282
py::return_value_policy::reference_internal)
8383

8484
.def_property_readonly("pltgot_relocations",
85-
static_cast<no_const_getter<it_relocations>>(&Binary::get_pltgot_relocations),
85+
static_cast<no_const_getter<it_pltgot_relocations>>(&Binary::get_pltgot_relocations),
8686
"Return an iterator to dynamics " RST_CLASS_REF(lief.ELF.Relocation) "",
8787
py::return_value_policy::reference_internal)
8888

api/python/ELF/objects/pyRelocation.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ void init_ELF_Relocation_class(py::module& m) {
4040
static_cast<setter_t<int64_t>>(&Relocation::addend),
4141
"Additional value")
4242

43+
.def_property("purpose",
44+
static_cast<getter_t<RELOCATION_PURPOSES>>(&Relocation::purpose),
45+
static_cast<setter_t<RELOCATION_PURPOSES>>(&Relocation::purpose),
46+
"Purpose (" RST_CLASS_REF(lief.ELF.RELOCATION_PURPOSES) ") of the relocation")
47+
4348
.def_property("type",
4449
static_cast<getter_t<uint32_t>>(&Relocation::type),
4550
static_cast<setter_t<uint32_t>>(&Relocation::type),

api/python/ELF/pyELFStructures.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -905,4 +905,12 @@ void init_ELF_Structures_enum(py::module& m) {
905905
.value(PY_ENUM(NOTE_ABIS::ELF_NOTE_OS_NETBSD))
906906
.value(PY_ENUM(NOTE_ABIS::ELF_NOTE_OS_SYLLABLE))
907907
.export_values();
908+
909+
910+
py::enum_<RELOCATION_PURPOSES>(m, "RELOCATION_PURPOSES")
911+
.value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_NONE))
912+
.value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_PLTGOT))
913+
.value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_DYNAMIC))
914+
.value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_OBJECT))
915+
.export_values();
908916
}

api/python/pyIterators.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ void init_LIEF_iterators(py::module& m) {
3131
init_ref_iterator<LIEF::ELF::it_segments>(m);
3232
init_ref_iterator<LIEF::ELF::it_dynamic_entries>(m);
3333
init_ref_iterator<LIEF::ELF::it_symbols>(m);
34-
init_ref_iterator<LIEF::ELF::it_relocations>(m);
34+
init_ref_iterator<LIEF::filter_iterator<LIEF::ELF::relocations_t>>(m);
3535
init_ref_iterator<LIEF::ELF::it_symbols_version>(m);
3636
init_ref_iterator<LIEF::ELF::it_symbols_version_requirement>(m);
3737
init_ref_iterator<LIEF::ELF::it_symbols_version_definition>(m);

doc/sphinx/api/cpp/elf.rst

+3
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,6 @@ Enums
211211

212212
.. doxygenenum:: LIEF::ELF::NOTE_ABIS
213213
:project: lief
214+
215+
.. doxygenenum:: LIEF::ELF::RELOCATION_PURPOSES
216+
:project: lief

doc/sphinx/api/python/elf.rst

+9
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,15 @@ Note ABIs
385385
:inherited-members:
386386
:undoc-members:
387387

388+
Relocation purposes
389+
~~~~~~~~~~~~~~~~~~~
390+
391+
.. autoclass:: lief.ELF.RELOCATION_PURPOSES
392+
:members:
393+
:inherited-members:
394+
:undoc-members:
395+
396+
388397

389398

390399

include/LIEF/ELF/Binary.hpp

+5-9
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,12 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
124124
it_const_symbols_version_requirement get_symbols_version_requirement(void) const;
125125

126126
//! @brief Return dynamic relocations
127-
it_relocations get_dynamic_relocations(void);
128-
it_const_relocations get_dynamic_relocations(void) const;
127+
it_dynamic_relocations get_dynamic_relocations(void);
128+
it_const_dynamic_relocations get_dynamic_relocations(void) const;
129129

130130
//! @brief Return `plt.got` relocations
131-
it_relocations get_pltgot_relocations(void);
132-
it_const_relocations get_pltgot_relocations(void) const;
131+
it_pltgot_relocations get_pltgot_relocations(void);
132+
it_const_pltgot_relocations get_pltgot_relocations(void) const;
133133

134134
//! @brief ``true`` if GNU hash is used
135135
//!
@@ -411,11 +411,7 @@ class DLL_PUBLIC Binary : public LIEF::Binary {
411411
//! A list of static symbols
412412
symbols_t static_symbols_;
413413

414-
//! The binary's dynamic Relocations if any
415-
relocations_t dynamic_relocations_;
416-
417-
//! .rela.plt
418-
relocations_t pltgot_relocations_;
414+
relocations_t relocations_;
419415

420416
//! .gnu.version
421417
symbols_version_t symbol_version_table_;

include/LIEF/ELF/EnumToString.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ DLL_PUBLIC const char* to_string(OS_ABI e);
4040
DLL_PUBLIC const char* to_string(DYNSYM_COUNT_METHODS e);
4141
DLL_PUBLIC const char* to_string(NOTE_TYPES e);
4242
DLL_PUBLIC const char* to_string(NOTE_ABIS e);
43+
DLL_PUBLIC const char* to_string(RELOCATION_PURPOSES e);
4344
} // namespace ELF
4445
} // namespace LIEF
4546

include/LIEF/ELF/Relocation.hpp

+9-6
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class DLL_PUBLIC Relocation : public Visitable {
5353
bool is_rela(void) const;
5454
bool is_rel(void) const;
5555
ARCH architecture(void) const;
56+
RELOCATION_PURPOSES purpose(void) const;
5657

5758
//! @brief Return the **bit** size of the value to patch
5859
uint32_t size(void) const;
@@ -64,6 +65,7 @@ class DLL_PUBLIC Relocation : public Visitable {
6465
void address(uint64_t address);
6566
void addend(int64_t addend);
6667
void type(uint32_t type);
68+
void purpose(RELOCATION_PURPOSES purpose);
6769

6870
virtual void accept(Visitor& visitor) const override;
6971

@@ -73,12 +75,13 @@ class DLL_PUBLIC Relocation : public Visitable {
7375
DLL_PUBLIC friend std::ostream& operator<<(std::ostream& os, const Relocation& entry);
7476

7577
private:
76-
uint64_t address_;
77-
uint32_t type_;
78-
int64_t addend_;
79-
bool isRela_;
80-
Symbol* symbol_;
81-
ARCH architecture_;
78+
uint64_t address_;
79+
uint32_t type_;
80+
int64_t addend_;
81+
bool isRela_;
82+
Symbol* symbol_;
83+
ARCH architecture_;
84+
RELOCATION_PURPOSES purpose_;
8285
};
8386

8487
}

include/LIEF/ELF/enums.inc

+7
Original file line numberDiff line numberDiff line change
@@ -976,3 +976,10 @@ enum NOTE_ABIS {
976976
ELF_NOTE_OS_SYLLABLE = 5,
977977
};
978978

979+
enum RELOCATION_PURPOSES {
980+
RELOC_PURPOSE_NONE = 0,
981+
RELOC_PURPOSE_PLTGOT = 1,
982+
RELOC_PURPOSE_DYNAMIC = 2,
983+
RELOC_PURPOSE_OBJECT = 3,
984+
};
985+

include/LIEF/ELF/type_traits.hpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,12 @@ using it_symbols = ref_iterator<symbols_t&>;
5050
using it_const_symbols = const_ref_iterator<const symbols_t&>;
5151

5252
using relocations_t = std::vector<Relocation*>;
53-
using it_relocations = ref_iterator<relocations_t&>;
54-
using it_const_relocations = const_ref_iterator<const relocations_t&>;
53+
54+
using it_pltgot_relocations = filter_iterator<relocations_t>;
55+
using it_const_pltgot_relocations = const_filter_iterator<const relocations_t>;
56+
57+
using it_dynamic_relocations = filter_iterator<relocations_t>;
58+
using it_const_dynamic_relocations = const_filter_iterator<const relocations_t>;
5559

5660
using symbols_version_t = std::vector<SymbolVersion*>;
5761
using it_symbols_version = ref_iterator<symbols_version_t&>;

src/ELF/Binary.cpp

+51-30
Original file line numberDiff line numberDiff line change
@@ -319,28 +319,35 @@ void Binary::remove_dynamic_symbol(Symbol* symbol) {
319319

320320
// Update relocations
321321
auto&& it_relocation = std::find_if(
322-
std::begin(this->pltgot_relocations_),
323-
std::end(this->pltgot_relocations_),
322+
std::begin(this->relocations_),
323+
std::end(this->relocations_),
324324
[&symbol] (const Relocation* relocation) {
325-
return relocation != nullptr and relocation->has_symbol() and relocation->symbol() == *symbol;
325+
return relocation != nullptr and
326+
relocation->purpose() == RELOCATION_PURPOSES::RELOC_PURPOSE_PLTGOT and
327+
relocation->has_symbol() and
328+
relocation->symbol() == *symbol;
326329
});
327330

328-
if (it_relocation != std::end(this->pltgot_relocations_)) {
331+
if (it_relocation != std::end(this->relocations_)) {
329332
delete *it_relocation;
330-
this->pltgot_relocations_.erase(it_relocation);
333+
this->relocations_.erase(it_relocation);
331334
} else {
332335
}
333336

334337

335338
it_relocation = std::find_if(
336-
std::begin(this->dynamic_relocations_),
337-
std::end(this->dynamic_relocations_),
339+
std::begin(this->relocations_),
340+
std::end(this->relocations_),
338341
[&symbol] (const Relocation* relocation) {
339-
return relocation != nullptr and relocation->has_symbol() and relocation->symbol() == *symbol;
342+
return relocation != nullptr and
343+
relocation->purpose() == RELOCATION_PURPOSES::RELOC_PURPOSE_DYNAMIC and
344+
relocation->has_symbol() and
345+
relocation->symbol() == *symbol;
340346
});
341-
if (it_relocation != std::end(this->dynamic_relocations_)) {
347+
348+
if (it_relocation != std::end(this->relocations_)) {
342349
delete *it_relocation;
343-
this->dynamic_relocations_.erase(it_relocation);
350+
this->relocations_.erase(it_relocation);
344351
}
345352

346353
// Update symbol versions
@@ -368,22 +375,40 @@ void Binary::remove_dynamic_symbol(Symbol* symbol) {
368375
// Dynamics
369376
// --------
370377

371-
it_relocations Binary::get_dynamic_relocations(void) {
372-
return it_relocations{std::ref(this->dynamic_relocations_)};
378+
it_dynamic_relocations Binary::get_dynamic_relocations(void) {
379+
return filter_iterator<relocations_t>{std::ref(this->relocations_),
380+
[] (const Relocation* reloc) {
381+
return reloc->purpose() == RELOCATION_PURPOSES::RELOC_PURPOSE_DYNAMIC;
382+
}
383+
};
384+
373385
}
374386

375-
it_const_relocations Binary::get_dynamic_relocations(void) const {
376-
return it_const_relocations{std::cref(this->dynamic_relocations_)};
387+
it_const_dynamic_relocations Binary::get_dynamic_relocations(void) const {
388+
return const_filter_iterator<const relocations_t>{std::cref(this->relocations_),
389+
[] (const Relocation* reloc) {
390+
return reloc->purpose() == RELOCATION_PURPOSES::RELOC_PURPOSE_DYNAMIC;
391+
}
392+
};
393+
377394
}
378395

379396
// plt/got
380397
// -------
381-
it_relocations Binary::get_pltgot_relocations(void) {
382-
return it_relocations{std::ref(this->pltgot_relocations_)};
398+
it_pltgot_relocations Binary::get_pltgot_relocations(void) {
399+
return filter_iterator<relocations_t>{std::ref(this->relocations_),
400+
[] (const Relocation* reloc) {
401+
return reloc->purpose() == RELOCATION_PURPOSES::RELOC_PURPOSE_PLTGOT;
402+
}
403+
};
383404
}
384405

385-
it_const_relocations Binary::get_pltgot_relocations(void) const {
386-
return it_const_relocations{std::cref(this->pltgot_relocations_)};
406+
it_const_pltgot_relocations Binary::get_pltgot_relocations(void) const {
407+
return const_filter_iterator<const relocations_t>{std::cref(this->relocations_),
408+
[] (const Relocation* reloc) {
409+
return reloc->purpose() == RELOCATION_PURPOSES::RELOC_PURPOSE_PLTGOT;
410+
}
411+
};
387412
}
388413

389414
LIEF::symbols_t Binary::get_abstract_symbols(void) {
@@ -788,18 +813,19 @@ void Binary::patch_address(uint64_t address, uint64_t patch_value, size_t size)
788813

789814

790815
void Binary::patch_pltgot(const Symbol& symbol, uint64_t address) {
816+
it_pltgot_relocations pltgot_relocations = this->get_pltgot_relocations();
791817
auto&& it_relocation = std::find_if(
792-
std::begin(this->pltgot_relocations_),
793-
std::end(this->pltgot_relocations_),
794-
[&symbol] (const Relocation* relocation) {
795-
return relocation->has_symbol() and relocation->symbol() == symbol;
818+
std::begin(pltgot_relocations),
819+
std::end(pltgot_relocations),
820+
[&symbol] (const Relocation& relocation) {
821+
return relocation.has_symbol() and relocation.symbol() == symbol;
796822
});
797823

798-
if (it_relocation == std::end(this->pltgot_relocations_)) {
824+
if (it_relocation == std::end(pltgot_relocations)) {
799825
throw not_found("Unable to find the relocation associated with symbol '" + symbol.name() + "'");
800826
}
801827

802-
uint64_t got_address = (*it_relocation)->address();
828+
uint64_t got_address = (*it_relocation).address();
803829
this->patch_address(got_address, address, sizeof(uint64_t));
804830
//(*it_relocation)->address(0);
805831
//delete *it_relocation;
@@ -1641,12 +1667,7 @@ std::ostream& Binary::print(std::ostream& os) const {
16411667

16421668
Binary::~Binary(void) {
16431669

1644-
for (Relocation* relocation : this->pltgot_relocations_) {
1645-
delete relocation;
1646-
}
1647-
1648-
1649-
for (Relocation* relocation : this->dynamic_relocations_) {
1670+
for (Relocation* relocation : this->relocations_) {
16501671
delete relocation;
16511672
}
16521673

src/ELF/Builder.tcc

+21-16
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ void Builder::build(void) {
5050
}
5151
}
5252

53-
if (this->binary_->dynamic_relocations_.size() > 0) {
53+
if (this->binary_->get_dynamic_relocations().size() > 0) {
5454
this->build_dynamic_relocations<ELF_T>();
5555
}
5656

57-
if (this->binary_->pltgot_relocations_.size() > 0) {
57+
if (this->binary_->get_pltgot_relocations().size() > 0) {
5858
this->build_pltgot_relocations<ELF_T>();
5959
}
6060

@@ -831,12 +831,14 @@ void Builder::build_dynamic_relocations(void) {
831831
using Elf_Rel = typename ELF_T::Elf_Rel;
832832
LOG(DEBUG) << "[+] Building dynamic relocations";
833833

834-
bool isRela = this->binary_->dynamic_relocations_[0]->is_rela();
834+
it_dynamic_relocations dynamic_relocations = this->binary_->get_dynamic_relocations();
835+
836+
bool isRela = dynamic_relocations[0].is_rela();
835837
if (not std::all_of(
836-
std::begin(this->binary_->dynamic_relocations_),
837-
std::end(this->binary_->dynamic_relocations_),
838-
[isRela] (const Relocation* relocation) {
839-
return relocation != nullptr and relocation->is_rela() == isRela;
838+
std::begin(dynamic_relocations),
839+
std::end(dynamic_relocations),
840+
[isRela] (const Relocation& relocation) {
841+
return relocation.is_rela() == isRela;
840842
})) {
841843
throw LIEF::type_error("Relocation are not of the same type");
842844
}
@@ -889,9 +891,9 @@ void Builder::build_dynamic_relocations(void) {
889891
Section& relocation_section = this->binary_->section_from_virtual_address((*it_dyn_relocation)->value());
890892

891893
if (isRela) {
892-
(*it_dyn_relocation_size)->value(this->binary_->dynamic_relocations_.size() * sizeof(Elf_Rela));
894+
(*it_dyn_relocation_size)->value(dynamic_relocations.size() * sizeof(Elf_Rela));
893895
} else {
894-
(*it_dyn_relocation_size)->value(this->binary_->dynamic_relocations_.size() * sizeof(Elf_Rel));
896+
(*it_dyn_relocation_size)->value(dynamic_relocations.size() * sizeof(Elf_Rel));
895897
}
896898

897899
std::vector<uint8_t> content;
@@ -961,13 +963,16 @@ void Builder::build_pltgot_relocations(void) {
961963
using Elf_Rel = typename ELF_T::Elf_Rel;
962964

963965
LOG(DEBUG) << "[+] Building .plt.got relocations";
964-
bool isRela = this->binary_->pltgot_relocations_[0]->is_rela();
966+
967+
it_pltgot_relocations pltgot_relocations = this->binary_->get_pltgot_relocations();
968+
969+
bool isRela = pltgot_relocations[0].is_rela();
965970

966971
if (not std::all_of(
967-
std::begin(this->binary_->pltgot_relocations_),
968-
std::end(this->binary_->pltgot_relocations_),
969-
[isRela] (const Relocation* relocation) {
970-
return relocation != nullptr and relocation->is_rela() == isRela;
972+
std::begin(pltgot_relocations),
973+
std::end(pltgot_relocations),
974+
[isRela] (const Relocation& relocation) {
975+
return relocation.is_rela() == isRela;
971976
})) {
972977
throw LIEF::type_error("Relocation are not of the same type");
973978
}
@@ -999,9 +1004,9 @@ void Builder::build_pltgot_relocations(void) {
9991004

10001005
Section& relocation_section = this->binary_->section_from_virtual_address((*it_dyn_relocation)->value());
10011006
if (isRela) {
1002-
(*it_dyn_relocation_size)->value(this->binary_->pltgot_relocations_.size() * sizeof(Elf_Rela));
1007+
(*it_dyn_relocation_size)->value(pltgot_relocations.size() * sizeof(Elf_Rela));
10031008
} else {
1004-
(*it_dyn_relocation_size)->value(this->binary_->pltgot_relocations_.size() * sizeof(Elf_Rel));
1009+
(*it_dyn_relocation_size)->value(pltgot_relocations.size() * sizeof(Elf_Rel));
10051010
}
10061011

10071012
std::vector<uint8_t> content; // Section's content

0 commit comments

Comments
 (0)