From 1284a9ab2be57a8eaf3c384ea6c14cdcf1a878cd Mon Sep 17 00:00:00 2001 From: patacongo Date: Tue, 23 Jun 2009 20:25:07 +0000 Subject: First cut at GOT relocations git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1932 42af7a65-404d-4744-a932-0658087f49c3 --- misc/buildroot/toolchain/nxflat/ldnxflat.c | 198 ++++++++++++--------------- misc/buildroot/toolchain/nxflat/nxflat.h | 17 ++- misc/buildroot/toolchain/nxflat/readnxflat.c | 10 +- 3 files changed, 109 insertions(+), 116 deletions(-) (limited to 'misc/buildroot/toolchain/nxflat') diff --git a/misc/buildroot/toolchain/nxflat/ldnxflat.c b/misc/buildroot/toolchain/nxflat/ldnxflat.c index 7249d0f8d..30464fc48 100644 --- a/misc/buildroot/toolchain/nxflat/ldnxflat.c +++ b/misc/buildroot/toolchain/nxflat/ldnxflat.c @@ -215,6 +215,7 @@ struct nxflat_got_s static int verbose = 0; static int dsyms = 0; static int stack_size = 0; +static int nerrors = 0; static int32_t counter = 0; @@ -1115,6 +1116,8 @@ resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms) case R_ARM_GOTOFF: { + int reltype; + /* Relocation is relative to the start of the global offset * table. This is used for things link known offsets to * constant strings in D-Space. I think we can just ignore @@ -1128,14 +1131,38 @@ resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms) * .word n(GOTOFF) */ - dbg("Skipping GOTOFF reloc at addr %08x [%08x] to sym '%s' [%08x]\n", + dbg("Perfoming GOTOFF reloc at addr %08x [%08x] to sym '%s' [%08x]\n", (int)relpp[j]->address, *target, rel_sym->name, (int)sym_value); + + /* For this location, we need to set the value to the value + * of the symbol in D-Space. (There is obviously a problem if + * the symbol lies in I-Space because the offset is not relative + * to the PIC address which points to the GOT). + */ + + /* Check if symbols lies in I- or D-Space */ + + reltype = get_reloc_type(rel_section, NULL); + if (reltype == NXFLAT_RELOC_TARGET_TEXT) + { + err("Symbol in GOT32 relocation is in TEXT\n"); + err(" At addr %08x to sym '%s' [%08x]\n", + (int)relpp[j]->address, rel_sym->name, (int)sym_value); + } + else + { + vdbg(" Original value: %08x\n", *target); + *target = sym_value; + vdbg(" Modified value: %08x\n", *target); + } } break; case R_ARM_GOT32: case R_ARM_GOT_PREL: { + struct nxflat_got_s *got_entry; + /* Relocation is to the entry for this symbol in the global * offset table. This relocation type is used to set the 32-bit * address of global variables. The usual assembly language sequence @@ -1151,103 +1178,50 @@ resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms) dbg("Performing GOT32 reloc at addr %08x [%08x] to sym '%s' [%08x]\n", (int)relpp[j]->address, *target, rel_sym->name, (int)sym_value); - /* Check if this is TEXT section relocation */ - - if ((inf->subsect[i]->flags & SEC_CODE) && - (inf->subsect[i]->flags & SEC_ALLOC)) - { - int reltype; - - vdbg(" GOT32 relocation in TEXT\n"); - - /* Locate the address referred to by the section type. */ - - reltype = get_reloc_type(rel_section, NULL); - if (reltype == NXFLAT_RELOC_TARGET_TEXT) - { - err("Symbol in GOT32 relocation is in TEXT\n"); - err(" At addr %08x to sym '%s' [%08x]\n", - (int)relpp[j]->address, rel_sym->name, (int)sym_value); - } - else - { - vdbg(" Original value: %08x\n", *target); - *target += sym_value; - vdbg(" Modified value: %08x\n", *target); - } - } - - /* Check for GOT32 relocation in .DATA -- Actually, GOT32 relocations - * should only be in text - */ + /* There should be an entry for the relocation allocated in the GOT */ - else if ((inf->subsect[i]->flags & SEC_DATA) && - (inf->subsect[i]->flags & SEC_ALLOC)) + got_entry = find_got_entry(rel_sym); + if (!got_entry) { -#if 1 /* Actually, GOT32 relocations will only be in text */ - err("Attempted GOT32 relocation in .data\n"); - err(" At addr %08x [%08x] to sym '%s' [%08x]\n", - (int)relpp[j]->address, *target, - rel_sym->name, (int)sym_value); -#else - int reltype; - - vdbg(" GOT32 relocation in DATA -- generating NXFLAT relo info\n"); - - /* Locate the address referred to by the section type. */ - - reltype = get_reloc_type(rel_section, NULL); - if (reltype != NXFLAT_RELOC_TARGET_DATA) - { - err("Symbol in GOT32 relocation is not .data\n"); - err(" At addr %08x to sym '%s' [%08x]\n", - (int)relpp[j]->address, rel_sym->name, (int)sym_value); - } -#endif + err("No GOT entry from for symobl '%s'\n", rel_sym->name); + nerrors++; } else { - err("Attempted GOT32 relocation outside of .data/.text\n"); - err(" At addr %08x [%08x] to sym '%s' [%08x]\n", - (int)relpp[j]->address, *target, - rel_sym->name, (int)sym_value); + /* The fixup is simply to provide the GOT offset as the relocation value */ + + vdbg(" Original value: %08x\n", *target); + *target = got_entry->offset; + vdbg(" Modified value: %08x\n", *target); } } break; case R_ARM_GOTPC: { - /* Relocation is to the entry for this symbol in the global - * offset table. This relocation type is used to set the 32-bit - * address of text references. My belief is that GOTPC is the - * same as GOT32 but the source is an address -- but what do I know. - */ + /* Use the global offset table as a symbol value */ dbg("Performing GOTPC reloc at addr %08x [%08x] to sym '%s' [%08x]\n", (int)relpp[j]->address, *target, rel_sym->name, (int)sym_value); - if (!(inf->subsect[i]->flags & SEC_DATA) || - !(inf->subsect[i]->flags & SEC_ALLOC)) + /* Check if this is TEXT section relocation */ + + if ((inf->subsect[i]->flags & SEC_CODE) != 0 && + (inf->subsect[i]->flags & SEC_ALLOC) != 0) { - err("Attempted GOTPC relocation outside of .data\n"); - err(" At addr %08x to sym '%s' [%08x]\n", - (int)relpp[j]->address, rel_sym->name, (int)sym_value); + /* The GOT always begins at offset 0 */ + + vdbg(" Original value: %08x\n", *target); + *target = 0; + vdbg(" Modified value: %08x\n", *target); } else { - int reltype; - - vdbg(" GOTPC relocation in DATA -- generating NXFLAT relo info\n"); - - /* Locate the address referred to by section type. */ - - reltype = get_reloc_type(rel_section, NULL); - if (reltype != NXFLAT_RELOC_TARGET_TEXT) - { - err("Symbol in GOTPC relocation is not .text\n"); - err(" At addr %08x to sym '%s' [%08x]\n", - (int)relpp[j]->address, rel_sym->name, (int)sym_value); - } + err("Attempted GOTPC relocation in outside of I-Space section\n"); + err(" At addr %08x [%08x] to sym '%s' [%08x]\n", + (int)relpp[j]->address, *target, + rel_sym->name, (int)sym_value); + nerrors++; } } break; @@ -1255,6 +1229,7 @@ resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms) default: err("Do not know how to handle reloc %d type %s @ %p!\n", how_to->type, how_to->name, how_to); + nerrors++; break; } } @@ -1718,51 +1693,54 @@ static void output_got(int fd, struct nxflat_reloc_s **pprelocs) { sym_value |= 1; } - else #endif + /* Determine where the symbol lies */ + + switch (get_reloc_type(rel_section, NULL)) { /* If the symbol lies in D-Space, then we need to add the size of the GOT * table to the symbol value */ - switch (get_reloc_type(rel_section, NULL)) - { - case NXFLAT_RELOC_TARGET_BSS: - case NXFLAT_RELOC_TARGET_DATA: - { - reloc_type = NXFLAT_RELOC_TYPE_REL32D; - sym_value += got_size; - } - break; + case NXFLAT_RELOC_TARGET_BSS: + case NXFLAT_RELOC_TARGET_DATA: + { + vdbg("Symbol '%s' lies in D-Space\n", rel_sym->name); + reloc_type = NXFLAT_RELOC_TYPE_REL32D; + sym_value += got_size; + } + break; - case NXFLAT_RELOC_TARGET_TEXT: - { - reloc_type = NXFLAT_RELOC_TYPE_REL32I; - sym_value += got_size; - } - break; + /* If the symbol lies in I-Space */ - case NXFLAT_RELOC_TARGET_UNKNOWN: - default: - { - err("Relocation type is unknown\n"); - exit(1); - } - } + case NXFLAT_RELOC_TARGET_TEXT: + { + vdbg("Symbol '%s' lies in I-Space\n", rel_sym->name); + reloc_type = NXFLAT_RELOC_TYPE_REL32I; + } + break; + + case NXFLAT_RELOC_TARGET_UNKNOWN: + default: + { + err("Relocation type is unknown\n"); + nerrors++; + continue; + } } /* Then save the symbol offset in the got */ got[i] = sym_value; - vdbg("GOT[%d]: sym '%s' value %08x->%08x\n", + vdbg("GOT[%d]: sym name: '%s' value: %08x->%08x\n", i, rel_sym->name, (int)rel_sym->value, (int)sym_value); /* And output the relocation information associate with the GOT entry */ relocs[i].r_info = NXFLAT_RELOC(reloc_type, sizeof(u_int32_t) * i); - vdbg("GOT[%d]: sym %s value %08x->%08x reloc type %d\n", - i, rel_sym->name, (int)rel_sym->value, (int)sym_value, reloc_type); + vdbg("relocs[%d]: type: %d offset: %08x\n", + i, NXFLAT_RELOC_TYPE(relocs[i].r_info), NXFLAT_RELOC_OFFSET(relocs[i].r_info)); } /* Write the GOT on the provided file descriptor */ @@ -1854,7 +1832,7 @@ static void load_sections(bfd *bfd, segment_info *inf) inf->contents = malloc(inf->size); if (!inf->contents) { - err("Failed to allocatte memory for section contents.\n"); + err("Failed to allocate memory for section contents.\n"); exit(1); } @@ -2284,5 +2262,11 @@ int main(int argc, char **argv, char **envp) /* Finished! */ close(fd); - exit(0); + + if (nerrors > 0) + { + fprintf(stderr, "%d Errors detected\n", nerrors); + return 1; + } + return 0; } diff --git a/misc/buildroot/toolchain/nxflat/nxflat.h b/misc/buildroot/toolchain/nxflat/nxflat.h index a35e6699a..fcdc17b0d 100644 --- a/misc/buildroot/toolchain/nxflat/nxflat.h +++ b/misc/buildroot/toolchain/nxflat/nxflat.h @@ -160,21 +160,24 @@ struct nxflat_reloc_s /* These are possible values for the relocation type: * * NXFLAT_RELOC_TYPE_REL32I Meaning: Object file contains a 32-bit offset - * into I-Space at the the offset. + * into I-Space at the offset. * Fixup: Add mapped I-Space address to the offset. * NXFLAT_RELOC_TYPE_REL32D Meaning: Object file contains a 32-bit offset - * into D-Space at the the offset. + * into D-Space at the offset. * Fixup: Add allocated D-Space address to the * offset. - * NXFLAT_RELOC_TYPE_ABS32 Meaning: Offset refers to a struct nxflat_import_s - * describing a function pointer to be - * imported. - * Fixup: Provide the absolute function address - * in the struct nxflat_import_s instance. + * NXFLAT_RELOC_TYPE_REL32ID Meaning: Object file contains a 32-bit offset + * into I-Space at the offset that will + * unfortunately be references relative + * to the GOT + * Fixup: Add allocated the mapped I-Space + * address MINUS the allocated D-Space + * address to the offset. */ #define NXFLAT_RELOC_TYPE_REL32I 0 #define NXFLAT_RELOC_TYPE_REL32D 1 +#undef NXFLAT_RELOC_TYPE_REL32ID /* May not need */ #define NXFLAT_RELOC_TYPE_NUM 2 /* Number of relocation types */ /**************************************************************************** diff --git a/misc/buildroot/toolchain/nxflat/readnxflat.c b/misc/buildroot/toolchain/nxflat/readnxflat.c index dd56b448b..11d01882d 100644 --- a/misc/buildroot/toolchain/nxflat/readnxflat.c +++ b/misc/buildroot/toolchain/nxflat/readnxflat.c @@ -98,12 +98,18 @@ static const char unknown[] = "UNKNOWN"; static const char hdr_reloc_rel32i[] = "RELOC_REL32I"; static const char hdr_reloc_rel32d[] = "RELOC_REL32D"; -static const char hdr_reloc_abs32[] = "RELOC_ABS32"; +#ifdef NXFLAT_RELOC_TYPE_REL32ID +static const char hdr_reloc_rel32id[] = "RELOC_REL32ID"; +#endif static const char *reloc_type_string[] = { hdr_reloc_rel32i, hdr_reloc_rel32d, - hdr_reloc_abs32, +#ifdef NXFLAT_RELOC_TYPE_REL32ID + hdr_reloc_rel32id, +#else + unknown, +#endif unknown }; -- cgit v1.2.3