diff --git a/api/python/ELF/objects/pyRelocation.cpp b/api/python/ELF/objects/pyRelocation.cpp index dc12636..a4c4e8f 100644 --- a/api/python/ELF/objects/pyRelocation.cpp +++ b/api/python/ELF/objects/pyRelocation.cpp @@ -62,6 +62,15 @@ void init_ELF_Relocation_class(py::module& m) { "" RST_CLASS_REF(lief.ELF.Symbol) " associated with the relocation", py::return_value_policy::reference_internal) + .def_property_readonly("has_section", + &Relocation::has_section, + "``True`` if a this relocation has a " RST_CLASS_REF(lief.ELF.Section) " associated") + + .def_property_readonly("section", + static_cast(&Relocation::section), + "" RST_CLASS_REF(lief.ELF.Section) " to which the relocation applies", + py::return_value_policy::reference) + .def_property_readonly("is_rela", static_cast>(&Relocation::is_rela), "``True`` if the relocation uses the :attr:`~lief.ELF.Relocation.addend` proprety") diff --git a/include/LIEF/ELF/Parser.hpp b/include/LIEF/ELF/Parser.hpp index 1e00ca1..9fb3467 100644 --- a/include/LIEF/ELF/Parser.hpp +++ b/include/LIEF/ELF/Parser.hpp @@ -181,7 +181,7 @@ class LIEF_API Parser : public LIEF::Parser { //! use parse relocations by using LIEF::ELF::Segment. This method parse relocations //! that are not reachable through segments (For example Object file). template - void parse_section_relocations(uint64_t offset, uint64_t size); + void parse_section_relocations(uint64_t offset, uint64_t size, Section *applies_to = nullptr); //! @brief Parse SymbolVersionRequirement //! diff --git a/include/LIEF/ELF/Relocation.hpp b/include/LIEF/ELF/Relocation.hpp index e924892..626ea1a 100644 --- a/include/LIEF/ELF/Relocation.hpp +++ b/include/LIEF/ELF/Relocation.hpp @@ -77,6 +77,13 @@ class LIEF_API Relocation : public LIEF::Relocation { Symbol& symbol(void); const Symbol& symbol(void) const; + //! True if the relocation has a section associated + bool has_section(void) const; + + //! Section associated with this relocation + Section& section(void); + const Section& section(void) const; + //void address(uint64_t address); void addend(int64_t addend); void type(uint32_t type); @@ -93,9 +100,10 @@ class LIEF_API Relocation : public LIEF::Relocation { uint32_t type_; int64_t addend_; bool isRela_; - Symbol* symbol_; + Symbol* symbol_{nullptr}; ARCH architecture_; RELOCATION_PURPOSES purpose_; + Section* section_{nullptr}; }; diff --git a/src/ELF/Parser.tcc b/src/ELF/Parser.tcc index d631a24..cb0a3ef 100644 --- a/src/ELF/Parser.tcc +++ b/src/ELF/Parser.tcc @@ -418,15 +418,21 @@ void Parser::parse_binary(void) { // Try to parse using sections if (this->binary_->relocations_.size() == 0) { for (const Section& section : this->binary_->sections()) { + Section* section_associated = nullptr; + if (section.information() > 0 and section.information() < this->binary_->sections_.size()) { + const size_t sh_info = section.information(); + section_associated = this->binary_->sections_[sh_info]; + } + try { if (section.type() == ELF_SECTION_TYPES::SHT_REL) { - this->parse_section_relocations( - section.file_offset(), section.size()); + this->parse_section_relocations( + section.file_offset(), section.size(), section_associated); } else if (section.type() == ELF_SECTION_TYPES::SHT_RELA) { this->parse_section_relocations( - section.file_offset(), section.size()); + section.file_offset(), section.size(), section_associated); } } catch (const exception& e) { @@ -1319,9 +1325,12 @@ void Parser::parse_pltgot_relocations(uint64_t offset, uint64_t size) { } template -void Parser::parse_section_relocations(uint64_t offset, uint64_t size) { - static_assert(std::is_same::value or - std::is_same::value, "REL_T must be Elf_Rel or Elf_Rela"); +void Parser::parse_section_relocations(uint64_t offset, uint64_t size, Section *applies_to) { + using Elf_Rel = typename ELF_T::Elf_Rel; + using Elf_Rela = typename ELF_T::Elf_Rela; + + static_assert(std::is_same::value or + std::is_same::value, "REL_T must be Elf_Rel or Elf_Rela"); const uint64_t offset_relocations = offset; const uint8_t shift = std::is_same::value ? 8 : 32; @@ -1338,6 +1347,7 @@ void Parser::parse_section_relocations(uint64_t offset, uint64_t size) { std::unique_ptr reloc{new Relocation{&rel_hdr}}; reloc->architecture_ = this->binary_->header_.machine_type(); + reloc->section_ = applies_to; if (this->binary_->header().file_type() == ELF::E_TYPE::ET_REL and this->binary_->segments().size() == 0) { reloc->purpose(RELOCATION_PURPOSES::RELOC_PURPOSE_OBJECT); diff --git a/src/ELF/Relocation.cpp b/src/ELF/Relocation.cpp index 64d67f4..9afedee 100644 --- a/src/ELF/Relocation.cpp +++ b/src/ELF/Relocation.cpp @@ -36,7 +36,8 @@ Relocation::Relocation(void) : isRela_{false}, symbol_{nullptr}, architecture_{ARCH::EM_NONE}, - purpose_{RELOCATION_PURPOSES::RELOC_PURPOSE_NONE} + purpose_{RELOCATION_PURPOSES::RELOC_PURPOSE_NONE}, + section_{nullptr} {} @@ -47,7 +48,8 @@ Relocation::Relocation(const Relocation& other) : isRela_{other.isRela_}, symbol_{nullptr}, architecture_{other.architecture_}, - purpose_{RELOCATION_PURPOSES::RELOC_PURPOSE_NONE} + purpose_{RELOCATION_PURPOSES::RELOC_PURPOSE_NONE}, + section_{nullptr} { } @@ -64,7 +66,8 @@ Relocation::Relocation(const Elf32_Rel* header) : isRela_{false}, symbol_{nullptr}, architecture_{ARCH::EM_NONE}, - purpose_{RELOCATION_PURPOSES::RELOC_PURPOSE_NONE} + purpose_{RELOCATION_PURPOSES::RELOC_PURPOSE_NONE}, + section_{nullptr} {} @@ -75,7 +78,8 @@ Relocation::Relocation(const Elf32_Rela* header) : isRela_{true}, symbol_{nullptr}, architecture_{ARCH::EM_NONE}, - purpose_{RELOCATION_PURPOSES::RELOC_PURPOSE_NONE} + purpose_{RELOCATION_PURPOSES::RELOC_PURPOSE_NONE}, + section_{nullptr} {} @@ -86,7 +90,8 @@ Relocation::Relocation(const Elf64_Rel* header) : isRela_{false}, symbol_{nullptr}, architecture_{ARCH::EM_NONE}, - purpose_{RELOCATION_PURPOSES::RELOC_PURPOSE_NONE} + purpose_{RELOCATION_PURPOSES::RELOC_PURPOSE_NONE}, + section_{nullptr} {} @@ -97,7 +102,8 @@ Relocation::Relocation(const Elf64_Rela* header) : isRela_{true}, symbol_{nullptr}, architecture_{ARCH::EM_NONE}, - purpose_{RELOCATION_PURPOSES::RELOC_PURPOSE_NONE} + purpose_{RELOCATION_PURPOSES::RELOC_PURPOSE_NONE}, + section_{nullptr} {} @@ -108,7 +114,8 @@ Relocation::Relocation(uint64_t address, uint32_t type, int64_t addend, bool isR isRela_{isRela}, symbol_{nullptr}, architecture_{ARCH::EM_NONE}, - purpose_{RELOCATION_PURPOSES::RELOC_PURPOSE_NONE} + purpose_{RELOCATION_PURPOSES::RELOC_PURPOSE_NONE}, + section_{nullptr} {} @@ -120,6 +127,7 @@ void Relocation::swap(Relocation& other) { std::swap(this->symbol_, other.symbol_); std::swap(this->architecture_, other.architecture_); std::swap(this->purpose_, other.purpose_); + std::swap(this->section_, other.section_); } int64_t Relocation::addend(void) const { @@ -144,6 +152,17 @@ Symbol& Relocation::symbol(void) { return const_cast(static_cast(this)->symbol()); } +const Section& Relocation::section(void) const { + if (this->has_section()) { + return *this->section_; + } else { + throw not_found("No section associated with this relocation"); + } +} + +Section& Relocation::section(void) { + return const_cast(static_cast(this)->section()); +} bool Relocation::is_rela(void) const { return this->isRela_; @@ -169,6 +188,10 @@ bool Relocation::has_symbol(void) const { return this->symbol_ != nullptr; } +bool Relocation::has_section(void) const { + return this->section_ != nullptr; +} + size_t Relocation::size(void) const { switch (this->architecture()) { diff --git a/src/ELF/json.cpp b/src/ELF/json.cpp index 07b6ada..20ff943 100644 --- a/src/ELF/json.cpp +++ b/src/ELF/json.cpp @@ -318,6 +318,7 @@ void JsonVisitor::visit(const Symbol& symbol) { void JsonVisitor::visit(const Relocation& relocation) { std::string relocation_type = "NOT_TO_STRING"; std::string symbol_name = ""; + std::string section_name = ""; if (relocation.has_symbol()) { const Symbol& s = relocation.symbol(); @@ -328,6 +329,10 @@ void JsonVisitor::visit(const Relocation& relocation) { } } + if (relocation.has_section()) { + section_name = relocation.section().name(); + } + if (relocation.architecture() == ARCH::EM_X86_64) { relocation_type = to_string(static_cast(relocation.type())); @@ -336,6 +341,7 @@ void JsonVisitor::visit(const Relocation& relocation) { this->node_["symbol_name"] = symbol_name; this->node_["address"] = relocation.address(); this->node_["type"] = relocation_type; + this->node_["section"] = section_name; }