More fixes for ldnxflat. There are still problems with the GCC 4.6.3

git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5227 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2012-10-10 19:36:32 +00:00
parent 6cb1bc7e67
commit b71fcbb0de
5 changed files with 131 additions and 18 deletions
+3
View File
@@ -123,4 +123,7 @@ buildroot-1.11 2011-xx-xx <gnutt@nuttx.org>
type was not generated by GCC/LD prior to gcc-4.6.3
* R_ARM_REL32 logic is conditionally disabled because it has not been
tested.
* ldnxflat: Correct a memory allocation error that could cause written
past the end of allocated memory. Partial restoration of R_ARM_REL32
logic. There are lots of issues that I still do not understand here.
+81 -16
View File
@@ -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;