From 28d780560dd246be31c87400195386870c539ed0 Mon Sep 17 00:00:00 2001 From: patacongo Date: Wed, 10 Oct 2012 19:36:32 +0000 Subject: More fixes for ldnxflat. There are still problems with the GCC 4.6.3 git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5227 42af7a65-404d-4744-a932-0658087f49c3 --- misc/buildroot/toolchain/nxflat/ldnxflat.c | 97 +++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 16 deletions(-) (limited to 'misc/buildroot/toolchain') diff --git a/misc/buildroot/toolchain/nxflat/ldnxflat.c b/misc/buildroot/toolchain/nxflat/ldnxflat.c index 5343e6b43..39fc98ce9 100644 --- a/misc/buildroot/toolchain/nxflat/ldnxflat.c +++ b/misc/buildroot/toolchain/nxflat/ldnxflat.c @@ -800,11 +800,83 @@ static void alloc_got_entry(asymbol *sym) } /*********************************************************************** - * relocate_arm32 + * relocate_rel32 ***********************************************************************/ static void -relocate_arm32(arelent *relp, int32_t *target, symvalue sym_value) +relocate_rel32(arelent *relp, int32_t *target, symvalue sym_value) +{ + reloc_howto_type *how_to = relp->howto; + asymbol *rel_sym = *relp->sym_ptr_ptr; + asection *rel_section = rel_sym->section; + int32_t value; + int32_t temp; + int32_t saved; + int reloc_type; + + if (verbose > 1) + { + vdbg(" Original location %p is %08lx ", +#ifdef ARCH_BIG_ENDIAN + target, (long)nxflat_swap32(*target)); +#else + target, (long)*target); +#endif + if (verbose > 2) + { + printf("rsh %d ", how_to->rightshift); + printf(" sz %d ", how_to->size); + printf("bit %d ", how_to->bitsize); + printf("rel %d ", how_to->pc_relative); + printf("smask %08lx ", (long)how_to->src_mask); + printf("dmask %08lx ", (long)how_to->dst_mask); + printf("off %d ", how_to->pcrel_offset); + } + + printf("\n"); + } + +#ifdef ARCH_BIG_ENDIAN + saved = temp = (int32_t) nxflat_swap32(*target); +#else + saved = temp = *target; +#endif + /* Mask and sign extend */ + + temp &= how_to->src_mask; + temp <<= (32 - how_to->bitsize); + temp >>= (32 - how_to->bitsize); + + /* Calculate the new value: Current value + VMA - current PC */ + + value = temp + sym_value + rel_section->vma - relp->address; + + /* Offset */ + + temp += (value >> how_to->rightshift); + + /* Mask upper bits from rollover */ + + temp &= how_to->dst_mask; + + /* Replace data that was masked */ + + temp |= saved & (~how_to->dst_mask); + + vdbg(" Modified location: %08lx\n", (long)temp); +#ifdef ARCH_BIG_ENDIAN + *target = (long)nxflat_swap32(temp); +#else + *target = (long)temp; +#endif + } + +/*********************************************************************** + * relocate_abs32 + ***********************************************************************/ + +static void +relocate_abs32(arelent *relp, int32_t *target, symvalue sym_value) { reloc_howto_type *how_to = relp->howto; asymbol *rel_sym = *relp->sym_ptr_ptr; @@ -901,7 +973,7 @@ relocate_arm32(arelent *relp, int32_t *target, symvalue sym_value) /* Re-allocate memory to include this relocation */ relocs = (struct nxflat_reloc_s*) - realloc(nxflat_relocs, sizeof(struct nxflat_reloc_s) * nxflat_nrelocs + 1); + realloc(nxflat_relocs, sizeof(struct nxflat_reloc_s) * (nxflat_nrelocs + 1)); if (!relocs) { err("Failed to re-allocate memory ABS32 relocations (%d relocations)\n", @@ -1105,7 +1177,7 @@ resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms) dbg("Performing ABS32 link at addr %08lx [%08lx] to sym '%s' [%08lx]\n", (long)relpp[j]->address, (long)*target, rel_sym->name, (long)sym_value); - relocate_arm32(relpp[j], target, sym_value); + relocate_abs32(relpp[j], target, sym_value); } break; @@ -1114,18 +1186,12 @@ resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms) dbg("Performing REL32 link at addr %08lx [%08lx] to sym '%s' [%08lx]\n", (long)relpp[j]->address, (long)*target, rel_sym->name, (long)sym_value); - /* The REL32 relocation is just like the ABS32 relocation except that (1) - * the symbol value is relative to the PC, and (2) we cannot permit - * REL32 relocations to data in I-Space. That just would not make sense. - */ -#if 1 - /* The logic below may or may not be correct. It has not been verified - * so, for now, it is disabled. + /* The only valid REL32 relocation would be to relocate a reference from + * I-Space to another symbol in I-Space. That should be handled by the + * partially linking logic so we don't expect to see any R_ARM_REL32 + * relocations here. */ - err("REL32 relocation not yet supported\n"); - nerrors++; -#else switch (get_reloc_type(rel_section, NULL)) { case NXFLAT_RELOC_TARGET_UNKNOWN: @@ -1148,11 +1214,10 @@ resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms) case NXFLAT_RELOC_TARGET_TEXT: { vdbg("Symbol '%s' lies in I-Space\n", rel_sym->name); - relocate_arm32(relpp[j], target, sym_value - relpp[j]->address); + relocate_rel32(relpp[j], target, sym_value - relpp[j]->address); } break; } -#endif } break; -- cgit v1.2.3