Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android Packed Relocations #991

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions api/python/src/ELF/enums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1225,6 +1225,8 @@ void init_enums(nb::module_& m) {
.value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_NONE))
.value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_PLTGOT))
.value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_DYNAMIC))
.value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_ANDROID_DYNAMIC))
.value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_RELR_DYNAMIC))
.value(PY_ENUM(RELOCATION_PURPOSES::RELOC_PURPOSE_OBJECT));


Expand Down
2 changes: 2 additions & 0 deletions api/python/src/ELF/objects/pyBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ void create<Builder>(nb::module_& m) {
.def_rw("force_relocate", &Builder::config_t::force_relocate,
"Force to relocate all the ELF structures that can be relocated (mostly for testing)"_doc)

.def_rw("android_rela", &Builder::config_t::android_rela, "Rebuild :attr:`~lief.ELF.DYNAMIC_TAGS.ANDROID_RELA`"_doc)
.def_rw("dt_hash", &Builder::config_t::dt_hash, "Rebuild :attr:`~lief.ELF.DYNAMIC_TAGS.HASH`"_doc)
.def_rw("dyn_str", &Builder::config_t::dyn_str, "Rebuild :attr:`~lief.ELF.DYNAMIC_TAGS.STRTAB`"_doc)
.def_rw("dynamic_section", &Builder::config_t::dynamic_section, "Rebuild the `PT_DYNAMIC` segment"_doc)
Expand All @@ -47,6 +48,7 @@ void create<Builder>(nb::module_& m) {
.def_rw("notes", &Builder::config_t::notes, "Rebuild `PT_NOTES` segment(s)"_doc)
.def_rw("preinit_array", &Builder::config_t::preinit_array, "Rebuild :attr:`~lief.ELF.DYNAMIC_TAGS.PREINIT_ARRAY`"_doc)
.def_rw("rela", &Builder::config_t::rela, "Rebuild :attr:`~lief.ELF.DYNAMIC_TAGS.RELA`"_doc)
.def_rw("relr", &Builder::config_t::rela, "Rebuild :attr:`~lief.ELF.DYNAMIC_TAGS.RELR`"_doc)
.def_rw("static_symtab", &Builder::config_t::static_symtab, "Rebuild `.symtab` section"_doc)
.def_rw("sym_verdef", &Builder::config_t::sym_verdef, "Rebuild :attr:`~lief.ELF.DYNAMIC_TAGS.VERDEF`"_doc)
.def_rw("sym_verneed", &Builder::config_t::sym_verneed, "Rebuild :attr:`~lief.ELF.DYNAMIC_TAGS.VERNEED`"_doc)
Expand Down
3 changes: 2 additions & 1 deletion include/LIEF/BinaryStream/BinaryStream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ class BinaryStream {
}

result<uint64_t> read_uleb128() const;
result<uint64_t> read_sleb128() const;
result<int64_t> read_sleb128() const;
int64_t try_read_sleb128(bool &fail_fuse) const;

result<int64_t> read_dwarf_encoded(uint8_t encoding) const;

Expand Down
20 changes: 20 additions & 0 deletions include/LIEF/ELF/Binary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@ class LIEF_API Binary : public LIEF::Binary {
//! Iterator which outputs plt/got const Relocation& object
using it_const_pltgot_relocations = const_filter_iterator<const relocations_t&, const Relocation*>;

//! Iterator which outputs Android Relocation& object
using it_android_relocations = filter_iterator<relocations_t&, Relocation*>;

//! Iterator which outputs Android const Relocation& object
using it_const_android_relocations = const_filter_iterator<const relocations_t&, const Relocation*>;

//! Iterator which outputs `relr.dyn` Relocation& object
using it_relrdyn_relocations = filter_iterator<relocations_t&, Relocation*>;

//! Iterator which outputs `relr.dyn` const Relocation& object
using it_const_relrdyn_relocations = const_filter_iterator<const relocations_t&, const Relocation*>;

//! Iterator which outputs dynamic Relocation& object (not related to the PLT/GOT mechanism)
using it_dynamic_relocations = filter_iterator<relocations_t&, Relocation*>;

Expand Down Expand Up @@ -341,6 +353,14 @@ class LIEF_API Binary : public LIEF::Binary {
//! the relocation added.
Relocation* add_object_relocation(const Relocation& relocation, const Section& section);

//! Return android dynamic relocations
it_android_relocations android_relocations();
it_const_android_relocations android_relocations() const;

//! Return relative relocations
it_relrdyn_relocations relrdyn_relocations();
it_const_relrdyn_relocations relrdyn_relocations() const;

//! Return `plt.got` relocations
it_pltgot_relocations pltgot_relocations();
it_const_pltgot_relocations pltgot_relocations() const;
Expand Down
14 changes: 11 additions & 3 deletions include/LIEF/ELF/Builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class LIEF_API Builder {
public:
//! Configuration options to tweak the building process
struct config_t {
bool android_rela = true; /// Rebuild DT_ANDROID_REL[A]
bool dt_hash = true; /// Rebuild DT_HASH
bool dyn_str = true; /// Rebuild DT_STRTAB
bool dynamic_section = true; /// Rebuild PT_DYNAMIC segment
Expand All @@ -67,6 +68,7 @@ class LIEF_API Builder {
bool notes = false; /// Disable note building since it can break the default layout
bool preinit_array = true; /// Rebuild DT_PREINIT_ARRAY
bool rela = true; /// Rebuild DT_REL[A]
bool relr = true; /// Rebuild DT_RELR
bool static_symtab = true; /// Rebuild `.symtab`
bool sym_verdef = true; /// Rebuild DT_VERDEF
bool sym_verneed = true; /// Rebuild DT_VERNEED
Expand Down Expand Up @@ -125,9 +127,6 @@ class LIEF_API Builder {
template<typename ELF_T>
ok_error_t build_static_symbols();

template<typename ELF_T>
ok_error_t build_dynamic();

template<typename ELF_T>
ok_error_t build_dynamic_section();

Expand All @@ -137,6 +136,14 @@ class LIEF_API Builder {
template<typename ELF_T>
ok_error_t build_obj_symbols();

//! @see https://github.com/llvm/llvm-project/blob/llvmorg-17.0.3/lld/ELF/SyntheticSections.cpp#L1747
template<typename ELF_T, typename Binary_T>
static result<uint64_t> build_android_relocations(Binary_T *binary);

//! @see https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
template<typename ELF_T, typename Binary_T>
static result<uint64_t> build_relrdyn_relocations(Binary_T *binary);

template<typename ELF_T>
ok_error_t build_dynamic_relocations();

Expand Down Expand Up @@ -177,6 +184,7 @@ class LIEF_API Builder {
ok_error_t build_overlay();

bool should_swap() const;
static bool should_swap(const Binary *binary);

template<class ELF_T>
ok_error_t process_object_relocations();
Expand Down
9 changes: 9 additions & 0 deletions include/LIEF/ELF/Parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,15 @@ class LIEF_API Parser : public LIEF::Parser {
ok_error_t parse_pltgot_relocations(uint64_t offset, uint64_t size);


//! Parse Android packed relocations
template<typename ELF_T, typename REL_T>
ok_error_t parse_android_relocations(uint64_t offset, uint64_t size);

//! Parse `.relr.dyn` relocations
template<typename ELF_T, typename REL_T>
ok_error_t parse_relrdyn_relocations(uint64_t offset, uint64_t size, uint64_t entry_size);


//! Parse relocations using LIEF::ELF::Section.
//! Section relocations are usually found in object files
template<typename ELF_T, typename REL_T>
Expand Down
3 changes: 3 additions & 0 deletions include/LIEF/ELF/Relocation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ class LIEF_API Relocation : public LIEF::Relocation {
//! * RELOC_LOONGARCH
uint32_t type() const;

//! Check if the relocation type is relative
bool type_is_relative() const;

//! Check if the relocation uses the explicit addend() field (this is usually the case for 64 bits binaries)
bool is_rela() const;

Expand Down
19 changes: 15 additions & 4 deletions include/LIEF/ELF/enums.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1000,10 +1000,20 @@ enum class NOTE_ABIS: size_t {
};

enum class RELOCATION_PURPOSES: size_t {
RELOC_PURPOSE_NONE = 0,
RELOC_PURPOSE_PLTGOT = 1,
RELOC_PURPOSE_DYNAMIC = 2,
RELOC_PURPOSE_OBJECT = 3,
RELOC_PURPOSE_NONE = 0,
RELOC_PURPOSE_PLTGOT = 1,
RELOC_PURPOSE_DYNAMIC = 2,
RELOC_PURPOSE_OBJECT = 3,
RELOC_PURPOSE_ANDROID_DYNAMIC = 4,
RELOC_PURPOSE_RELR_DYNAMIC = 5,
};

enum class ANDROID_RELOCATION_FLAGS: size_t {
RELOCATION_GROUPED_BY_NONE = 0,
RELOCATION_GROUPED_BY_INFO_FLAG = 1,
RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG = 2,
RELOCATION_GROUPED_BY_ADDEND_FLAG = 4,
RELOCATION_GROUP_HAS_ADDEND_FLAG = 8,
};

}
Expand All @@ -1017,5 +1027,6 @@ ENABLE_BITMASK_OPERATORS(LIEF::ELF::LOONGARCH_EFLAGS)
ENABLE_BITMASK_OPERATORS(LIEF::ELF::ELF_SECTION_FLAGS)
ENABLE_BITMASK_OPERATORS(LIEF::ELF::DYNAMIC_FLAGS)
ENABLE_BITMASK_OPERATORS(LIEF::ELF::DYNAMIC_FLAGS_1)
ENABLE_BITMASK_OPERATORS(LIEF::ELF::ANDROID_RELOCATION_FLAGS)

#endif
29 changes: 21 additions & 8 deletions include/LIEF/ELF/enums.inc
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,10 @@ enum _LIEF_EN(DYNAMIC_TAGS) {

_LIEF_EI(DT_PREINIT_ARRAY) = 32, /**< Pointer to array of preinit functions. */
_LIEF_EI(DT_PREINIT_ARRAYSZ) = 33, /**< Size of the DT_PREINIT_ARRAY array. */
_LIEF_EI(DT_SYMTAB_SHNDX) = 34, /**< Address of SYMTAB_SHNDX section */
_LIEF_EI(DT_RELRSZ) = 35, /**< Total size of RELR relative relocations */
_LIEF_EI(DT_RELR) = 36, /**< Address of RELR relative relocations */
_LIEF_EI(DT_RELRENT) = 37, /**< Size of one RELR relative relocaction */

_LIEF_EI(DT_LOOS) = 0x60000000, /**< Start of environment specific tags. */
_LIEF_EI(DT_HIOS) = 0x6FFFFFFF, /**< End of environment specific tags. */
Expand Down Expand Up @@ -759,10 +763,10 @@ enum _LIEF_EN(DYNAMIC_TAGS) {
_LIEF_EI(DT_ANDROID_RELSZ) = 0x60000010, /**< The size of packed relocation data in bytes (Android specific). */
_LIEF_EI(DT_ANDROID_RELA) = 0x60000011, /**< The offset of packed relocation data (Android specific). */
_LIEF_EI(DT_ANDROID_RELASZ) = 0x60000012, /**< The size of packed relocation data in bytes (Android specific). */
_LIEF_EI(DT_RELR) = 0x6FFFE000, /**< The offset of new relr relocation data (Android specific). */
_LIEF_EI(DT_RELRSZ) = 0x6FFFE001, /**< The size of nre relr relocation data in bytes (Android specific). */
_LIEF_EI(DT_RELRENT) = 0x6FFFE003, /**< The size of a new relr relocation entry (Android specific). */
_LIEF_EI(DT_RELRCOUNT) = 0x6FFFE005 /**< Specifies the relative count of new relr relocation entries (Android specific). */
_LIEF_EI(DT_ANDROID_RELR) = 0x6FFFE000, /**< The offset of new relr relocation data (Android specific). */
_LIEF_EI(DT_ANDROID_RELRSZ) = 0x6FFFE001, /**< The size of nre relr relocation data in bytes (Android specific). */
_LIEF_EI(DT_ANDROID_RELRENT) = 0x6FFFE003, /**< The size of a new relr relocation entry (Android specific). */
_LIEF_EI(DT_ANDROID_RELRCOUNT) = 0x6FFFE005 /**< Specifies the relative count of new relr relocation entries (Android specific). */
};

/** DT_FLAGS and DT_FLAGS_1 values. */
Expand Down Expand Up @@ -971,9 +975,18 @@ enum _LIEF_EN(NOTE_ABIS) {
};

enum _LIEF_EN(RELOCATION_PURPOSES) {
_LIEF_EI(RELOC_PURPOSE_NONE) = 0,
_LIEF_EI(RELOC_PURPOSE_PLTGOT) = 1,
_LIEF_EI(RELOC_PURPOSE_DYNAMIC) = 2,
_LIEF_EI(RELOC_PURPOSE_OBJECT) = 3,
_LIEF_EI(RELOC_PURPOSE_NONE) = 0,
_LIEF_EI(RELOC_PURPOSE_PLTGOT) = 1,
_LIEF_EI(RELOC_PURPOSE_DYNAMIC) = 2,
_LIEF_EI(RELOC_PURPOSE_OBJECT) = 3,
_LIEF_EI(RELOC_PURPOSE_ANDROID_DYNAMIC) = 4,
_LIEF_EI(RELOC_PURPOSE_RELR_DYNAMIC) = 5,
};

enum _LIEF_EN(ANDROID_RELOCATION_FLAGS) {
_LIEF_EI(RELOCATION_GROUPED_BY_INFO_FLAG) = 1,
_LIEF_EI(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG) = 2,
_LIEF_EI(RELOCATION_GROUPED_BY_ADDEND_FLAG) = 4,
_LIEF_EI(RELOCATION_GROUP_HAS_ADDEND_FLAG) = 8,
};

4 changes: 4 additions & 0 deletions include/LIEF/ELF/undef.h
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,10 @@
#undef DT_ANDROID_RELSZ
#undef DT_ANDROID_RELA
#undef DT_ANDROID_RELASZ
#undef DT_ANDROID_RELR
#undef DT_ANDROID_RELRSZ
#undef DT_ANDROID_RELRENT
#undef DT_ANDROID_RELRCOUNT
#undef DT_RELR
#undef DT_RELRSZ
#undef DT_RELRENT
Expand Down
11 changes: 10 additions & 1 deletion src/BinaryStream/BinaryStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ result<uint64_t> BinaryStream::read_uleb128() const {
return value;
}

result<uint64_t> BinaryStream::read_sleb128() const {
result<int64_t> BinaryStream::read_sleb128() const {
int64_t value = 0;
unsigned shift = 0;
result<uint8_t> byte_read = 0;
Expand All @@ -161,6 +161,15 @@ result<uint64_t> BinaryStream::read_sleb128() const {
return value;
}

int64_t BinaryStream::try_read_sleb128(bool &fail_fuse) const {
if (const auto val = read_sleb128()) {
return val.value();
} else {
fail_fuse = true;
return 0;
}
}

result<std::string> BinaryStream::read_string(size_t maxsize) const {
result<std::string> str = peek_string(maxsize);
if (!str) {
Expand Down
39 changes: 38 additions & 1 deletion src/ELF/Binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,39 @@ Relocation* Binary::add_object_relocation(const Relocation& relocation, const Se
return relocations_.back().get();
}

// Android format
// --------------
Binary::it_android_relocations Binary::android_relocations() {
return {relocations_, [] (const std::unique_ptr<Relocation>& reloc) {
return reloc->purpose() == RELOCATION_PURPOSES::RELOC_PURPOSE_ANDROID_DYNAMIC;
}
};
}

Binary::it_const_android_relocations Binary::android_relocations() const {
return {relocations_, [] (const std::unique_ptr<Relocation>& reloc) {
return reloc->purpose() == RELOCATION_PURPOSES::RELOC_PURPOSE_ANDROID_DYNAMIC;
}
};
}

// .relr.dyn
// ---------
Binary::it_relrdyn_relocations Binary::relrdyn_relocations() {
return {relocations_, [] (const std::unique_ptr<Relocation>& reloc) {
return reloc->purpose() == RELOCATION_PURPOSES::RELOC_PURPOSE_RELR_DYNAMIC;
}
};
}

Binary::it_const_relrdyn_relocations Binary::relrdyn_relocations() const {
return {relocations_, [] (const std::unique_ptr<Relocation>& reloc) {
return reloc->purpose() == RELOCATION_PURPOSES::RELOC_PURPOSE_RELR_DYNAMIC;
}
};
}


// plt/got
// -------
Binary::it_pltgot_relocations Binary::pltgot_relocations() {
Expand Down Expand Up @@ -2042,6 +2075,10 @@ void Binary::shift_dynamic_entries(uint64_t from, uint64_t shift) {
case DYNAMIC_TAGS::DT_GNU_HASH:
case DYNAMIC_TAGS::DT_STRTAB:
case DYNAMIC_TAGS::DT_SYMTAB:
case DYNAMIC_TAGS::DT_ANDROID_RELA:
case DYNAMIC_TAGS::DT_ANDROID_REL:
case DYNAMIC_TAGS::DT_ANDROID_RELR:
case DYNAMIC_TAGS::DT_RELR:
case DYNAMIC_TAGS::DT_RELA:
case DYNAMIC_TAGS::DT_REL:
case DYNAMIC_TAGS::DT_JMPREL:
Expand Down Expand Up @@ -2081,7 +2118,7 @@ void Binary::shift_dynamic_entries(uint64_t from, uint64_t shift) {

default:
{
//LIEF_DEBUG("{} not supported", to_string(entry->tag()));
LIEF_DEBUG("{} not supported", to_string(entry->tag()));
}
}
LIEF_DEBUG("[AFTER ] {}", *entry);
Expand Down
6 changes: 5 additions & 1 deletion src/ELF/Builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ Builder::Builder(Binary& binary) :


bool Builder::should_swap() const {
switch (binary_->header().abstract_endianness()) {
return Builder::should_swap(binary_);
}

bool Builder::should_swap(const Binary *binary) {
switch (binary->header().abstract_endianness()) {
#ifdef __BYTE_ORDER__
#if defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
case ENDIANNESS::ENDIAN_BIG:
Expand Down
Loading
Loading