Skip to content
Snippets Groups Projects
Commit 82693938 authored by Moritz Angermann's avatar Moritz Angermann Committed by Marge Bot
Browse files

Add _GLOBAL_OFFSET_TABLE_ support

This adds lookup logic for _GLOBAL_OFFSET_TABLE_ as well as
relocation logic for R_ARM_BASE_PREL and R_ARM_GOT_BREL which
the gnu toolchain (gas, gcc, ...) prefers to produce.  Apparently
recent llvm toolchains will produce those as well.
parent bd660ede
No related branches found
No related tags found
No related merge requests found
......@@ -1019,6 +1019,19 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
return 1;
}
/* The following nomenclature is used for the operation:
* - S -- (when used on its own) is the address of the symbol.
* - A -- is the addend for the relocation.
* - P -- is the address of the place being relocated (derived from r_offset).
* - Pa - is the adjusted address of the place being relocated, defined as (P & 0xFFFFFFFC).
* - T -- is 1 if the target symbol S has type STT_FUNC and the symbol addresses a Thumb instruction; it is 0 otherwise.
* - B(S) is the addressing origin of the output segment defining the symbol S. The origin is not required to be the
* base address of the segment. This value must always be word-aligned.
* - GOT_ORG is the addressing origin of the Global Offset Table (the indirection table for imported data addresses).
* This value must always be word-aligned. See §4.6.1.8, Proxy generating relocations.
* - GOT(S) is the address of the GOT entry for the symbol S.
*/
for (j = 0; j < nent; j++) {
Elf_Addr offset = rtab[j].r_offset;
Elf_Addr info = rtab[j].r_info;
......@@ -1113,19 +1126,35 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
# endif
# ifdef arm_HOST_ARCH
case COMPAT_R_ARM_ABS32:
case COMPAT_R_ARM_ABS32: /* (S + A) | T */
// Specified by Linux ARM ABI to be equivalent to ABS32
case COMPAT_R_ARM_TARGET1:
*(Elf32_Word *)P += S;
*(Elf32_Word *)P |= T;
break;
case COMPAT_R_ARM_REL32:
case COMPAT_R_ARM_REL32: /* ((S + A) | T) – P */
*(Elf32_Word *)P += S;
*(Elf32_Word *)P |= T;
*(Elf32_Word *)P -= P;
break;
case COMPAT_R_ARM_BASE_PREL: /* B(S) + A – P */
{
int32_t A = *pP;
// bfd used to encode sb (B(S)) as 0.
*(uint32_t *)P += 0 + A - P;
break;
}
case COMPAT_R_ARM_GOT_BREL: /* GOT(S) + A – GOT_ORG */
{
int32_t A = *pP;
void* GOT_S = symbol->got_addr;
*(uint32_t *)P = (uint32_t) GOT_S + A - (uint32_t) oc->info->got_start;
break;
}
case COMPAT_R_ARM_CALL:
case COMPAT_R_ARM_JUMP24:
{
......
......@@ -86,9 +86,13 @@ fillGot(ObjectCode * oc) {
if(0x0 == symbol->addr) {
symbol->addr = lookupSymbol_(symbol->name);
if(0x0 == symbol->addr) {
errorBelch("Failed to lookup symbol: %s\n",
symbol->name);
return EXIT_FAILURE;
if(0 == strncmp(symbol->name,"_GLOBAL_OFFSET_TABLE_",21)) {
symbol->addr = oc->info->got_start;
} else {
errorBelch("Failed to lookup symbol: %s\n",
symbol->name);
return EXIT_FAILURE;
}
}
} else {
// we already have the address.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment