Merge "linker: add experimental support for SHT_RELR sections."
This commit is contained in:
commit
d00d38b36b
|
@ -194,6 +194,14 @@ typedef struct {
|
|||
Elf64_Word vna_next;
|
||||
} Elf64_Vernaux;
|
||||
|
||||
/* Relocation table entry for relative (in section of type SHT_RELR). */
|
||||
typedef Elf32_Word Elf32_Relr;
|
||||
typedef Elf64_Xword Elf64_Relr;
|
||||
#define ELF32_R_JUMP(val) ((val) >> 24)
|
||||
#define ELF32_R_BITS(val) ((val) & 0xffffff)
|
||||
#define ELF64_R_JUMP(val) ((val) >> 56)
|
||||
#define ELF64_R_BITS(val) ((val) & 0xffffffffffffff)
|
||||
|
||||
/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html */
|
||||
#define DF_ORIGIN 0x00000001
|
||||
#define DF_SYMBOLIC 0x00000002
|
||||
|
@ -242,6 +250,13 @@ typedef struct {
|
|||
#define DT_PREINIT_ARRAY 32
|
||||
#define DT_PREINIT_ARRAYSZ 33
|
||||
|
||||
/* Experimental support for SHT_RELR sections. For details, see proposal
|
||||
at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg */
|
||||
#define DT_RELR 0x6fffe000
|
||||
#define DT_RELRSZ 0x6fffe001
|
||||
#define DT_RELRENT 0x6fffe003
|
||||
#define DT_RELRCOUNT 0x6fffe005
|
||||
|
||||
/* Android compressed rel/rela sections */
|
||||
#define DT_ANDROID_REL (DT_LOOS + 2)
|
||||
#define DT_ANDROID_RELSZ (DT_LOOS + 3)
|
||||
|
@ -494,6 +509,10 @@ typedef struct {
|
|||
#define SHT_LOOS 0x60000000
|
||||
#define SHT_HIOS 0x6fffffff
|
||||
|
||||
/* Experimental support for SHT_RELR sections. For details, see proposal
|
||||
at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg */
|
||||
#define SHT_RELR 0x6fffff00
|
||||
|
||||
/* http://www.sco.com/developers/gabi/latest/ch4.symtab.html */
|
||||
#define STN_UNDEF 0
|
||||
|
||||
|
|
|
@ -2595,6 +2595,35 @@ bool soinfo::lookup_version_info(const VersionTracker& version_tracker, ElfW(Wor
|
|||
return true;
|
||||
}
|
||||
|
||||
// Process relocations in SHT_RELR section (experimental).
|
||||
// See the original proposal for details of the encoding:
|
||||
// - https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
|
||||
bool soinfo::relocate_relr() {
|
||||
ElfW(Relr)* begin = relr_;
|
||||
ElfW(Relr)* end = relr_ + relr_count_;
|
||||
|
||||
ElfW(Addr) offset = 0;
|
||||
for (ElfW(Relr)* current = begin; current < end; ++current) {
|
||||
ElfW(Addr) jump = ELFW(R_JUMP)(*current);
|
||||
ElfW(Addr) bits = ELFW(R_BITS)(*current);
|
||||
offset += jump * sizeof(ElfW(Addr));
|
||||
if (jump == 0) {
|
||||
++current;
|
||||
offset = *current;
|
||||
}
|
||||
ElfW(Addr) r_offset = offset;
|
||||
for (; bits != 0; bits >>= 1) {
|
||||
if ((bits&1) != 0) {
|
||||
ElfW(Addr) reloc = static_cast<ElfW(Addr)>(r_offset + load_bias);
|
||||
ElfW(Addr) addend = *reinterpret_cast<ElfW(Addr)*>(reloc);
|
||||
*reinterpret_cast<ElfW(Addr)*>(reloc) = (load_bias + addend);
|
||||
}
|
||||
r_offset += sizeof(ElfW(Addr));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !defined(__mips__)
|
||||
#if defined(USE_RELA)
|
||||
static ElfW(Addr) get_addend(ElfW(Rela)* rela, ElfW(Addr) reloc_addr __unused) {
|
||||
|
@ -3151,7 +3180,7 @@ bool soinfo::prelink_image() {
|
|||
}
|
||||
break;
|
||||
|
||||
// ignored (see DT_RELCOUNT comments for details)
|
||||
// Ignored (see DT_RELCOUNT comments for details).
|
||||
case DT_RELACOUNT:
|
||||
break;
|
||||
|
||||
|
@ -3212,6 +3241,25 @@ bool soinfo::prelink_image() {
|
|||
return false;
|
||||
|
||||
#endif
|
||||
case DT_RELR:
|
||||
relr_ = reinterpret_cast<ElfW(Relr)*>(load_bias + d->d_un.d_ptr);
|
||||
break;
|
||||
|
||||
case DT_RELRSZ:
|
||||
relr_count_ = d->d_un.d_val / sizeof(ElfW(Relr));
|
||||
break;
|
||||
|
||||
case DT_RELRENT:
|
||||
if (d->d_un.d_val != sizeof(ElfW(Relr))) {
|
||||
DL_ERR("invalid DT_RELRENT: %zd", static_cast<size_t>(d->d_un.d_val));
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
// Ignored (see DT_RELCOUNT comments for details).
|
||||
case DT_RELRCOUNT:
|
||||
break;
|
||||
|
||||
case DT_INIT:
|
||||
init_func_ = reinterpret_cast<linker_ctor_function_t>(load_bias + d->d_un.d_ptr);
|
||||
DEBUG("%s constructors (DT_INIT) found at %p", get_realpath(), init_func_);
|
||||
|
@ -3504,16 +3552,23 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
|
|||
}
|
||||
}
|
||||
|
||||
if (relr_ != nullptr) {
|
||||
DEBUG("[ relocating %s relr ]", get_realpath());
|
||||
if (!relocate_relr()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_RELA)
|
||||
if (rela_ != nullptr) {
|
||||
DEBUG("[ relocating %s ]", get_realpath());
|
||||
DEBUG("[ relocating %s rela ]", get_realpath());
|
||||
if (!relocate(version_tracker,
|
||||
plain_reloc_iterator(rela_, rela_count_), global_group, local_group)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (plt_rela_ != nullptr) {
|
||||
DEBUG("[ relocating %s plt ]", get_realpath());
|
||||
DEBUG("[ relocating %s plt rela ]", get_realpath());
|
||||
if (!relocate(version_tracker,
|
||||
plain_reloc_iterator(plt_rela_, plt_rela_count_), global_group, local_group)) {
|
||||
return false;
|
||||
|
@ -3521,14 +3576,14 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
|
|||
}
|
||||
#else
|
||||
if (rel_ != nullptr) {
|
||||
DEBUG("[ relocating %s ]", get_realpath());
|
||||
DEBUG("[ relocating %s rel ]", get_realpath());
|
||||
if (!relocate(version_tracker,
|
||||
plain_reloc_iterator(rel_, rel_count_), global_group, local_group)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (plt_rel_ != nullptr) {
|
||||
DEBUG("[ relocating %s plt ]", get_realpath());
|
||||
DEBUG("[ relocating %s plt rel ]", get_realpath());
|
||||
if (!relocate(version_tracker,
|
||||
plain_reloc_iterator(plt_rel_, plt_rel_count_), global_group, local_group)) {
|
||||
return false;
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
// unset.
|
||||
#define FLAG_NEW_SOINFO 0x40000000 // new soinfo format
|
||||
|
||||
#define SOINFO_VERSION 3
|
||||
#define SOINFO_VERSION 4
|
||||
|
||||
typedef void (*linker_dtor_function_t)();
|
||||
typedef void (*linker_ctor_function_t)(int, char**, char**);
|
||||
|
@ -309,6 +309,7 @@ struct soinfo {
|
|||
template<typename ElfRelIteratorT>
|
||||
bool relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
|
||||
const soinfo_list_t& global_group, const soinfo_list_t& local_group);
|
||||
bool relocate_relr();
|
||||
|
||||
private:
|
||||
// This part of the structure is only available
|
||||
|
@ -365,6 +366,10 @@ struct soinfo {
|
|||
friend soinfo* get_libdl_info(const char* linker_path,
|
||||
const soinfo& linker_si,
|
||||
const link_map& linker_map);
|
||||
|
||||
// version >= 4
|
||||
ElfW(Relr)* relr_;
|
||||
size_t relr_count_;
|
||||
};
|
||||
|
||||
// This function is used by dlvsym() to calculate hash of sym_ver
|
||||
|
|
Loading…
Reference in New Issue