Browse Source

Add support for the R_ARM_REL32 relocation

git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5223 42af7a65-404d-4744-a932-0658087f49c3
sbg
patacongo 13 years ago
parent
commit
aae19db5c3
  1. 2
      misc/buildroot/ChangeLog
  2. 235
      misc/buildroot/toolchain/nxflat/ldnxflat.c

2
misc/buildroot/ChangeLog

@ -119,4 +119,6 @@ buildroot-1.11 2011-xx-xx <gnutt@nuttx.org> @@ -119,4 +119,6 @@ buildroot-1.11 2011-xx-xx <gnutt@nuttx.org>
* Add support for binutils 2.22 and GCC 4.6.3.
* Change name of all tools from xxx-elf to xxx-nuttx-elf
* Added an ARM EABI GCC 4.6.3 configuration (tool name is arm-nuttx-eabi-).
* ldnxflat: Add support for the R_ARM_REL32 relocation. This relocation
type was not generated by GCC/LD prior to gcc-4.6.3

235
misc/buildroot/toolchain/nxflat/ldnxflat.c

@ -799,6 +799,134 @@ static void alloc_got_entry(asymbol *sym) @@ -799,6 +799,134 @@ static void alloc_got_entry(asymbol *sym)
}
}
/***********************************************************************
* relocate_arm32
***********************************************************************/
static void
relocate_arm32(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;
struct nxflat_reloc_s *relocs;
int32_t temp;
int32_t saved;
int reloc_type;
/* ABS32 links from .text are easy - since the fetches will
* always be base relative. the ABS32 refs from data will be
* handled the same
*/
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);
/* Offset */
temp += (sym_value + rel_section->vma) >> 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
/* Determine where the symbol lies */
switch (get_reloc_type(rel_section, NULL))
{
case NXFLAT_RELOC_TARGET_UNKNOWN:
default:
{
err("Symbol relocation section type is unknown\n");
nerrors++;
}
/* Fall through and do something wrong */
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;
}
break;
case NXFLAT_RELOC_TARGET_TEXT:
{
vdbg("Symbol '%s' lies in I-Space\n", rel_sym->name);
reloc_type = NXFLAT_RELOC_TYPE_REL32I;
}
break;
}
/* Re-allocate memory to include this relocation */
relocs = (struct nxflat_reloc_s*)
realloc(nxflat_relocs, sizeof(struct nxflat_reloc_s) * nxflat_nrelocs + 1);
if (!relocs)
{
err("Failed to re-allocate memory ABS32 relocations (%d relocations)\n",
nxflat_nrelocs);
nerrors++;
}
else
{
/* Reallocation was successful. Update globals */
nxflat_nrelocs++;
nxflat_relocs = relocs;
/* Then add the relocation at the end of the table */
nxflat_relocs[nxflat_nrelocs-1].r_info =
NXFLAT_RELOC(reloc_type, relp->address + got_size);
vdbg("relocs[%d]: type: %d offset: %08x\n",
nxflat_nrelocs-1,
NXFLAT_RELOC_TYPE(nxflat_relocs[nxflat_nrelocs-1].r_info),
NXFLAT_RELOC_OFFSET(nxflat_relocs[nxflat_nrelocs-1].r_info));
}
}
/***********************************************************************
* resolve_segment_relocs
***********************************************************************/
@ -806,10 +934,8 @@ static void alloc_got_entry(asymbol *sym) @@ -806,10 +934,8 @@ static void alloc_got_entry(asymbol *sym)
static void
resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms)
{
struct nxflat_reloc_s *relocs;
arelent **relpp;
int relsize;
int reloc_type;
int relcount;
int i;
int j;
@ -976,68 +1102,22 @@ resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms) @@ -976,68 +1102,22 @@ resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms)
case R_ARM_ABS32:
{
int32_t temp;
int32_t saved;
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);
/* ABS32 links from .text are easy - since the fetches will
* always be base relative. the ABS32 refs from data will be
* handled the same
*/
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);
/* Offset */
temp += (sym_value + rel_section->vma) >> how_to->rightshift;
/* Mask upper bits from rollover */
temp &= how_to->dst_mask;
/* Replace data that was masked */
relocate_arm32(relpp[j], target, sym_value);
}
break;
temp |= saved & (~how_to->dst_mask);
case R_ARM_REL32:
{
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);
vdbg(" Modified location: %08lx\n", (long)temp);
#ifdef ARCH_BIG_ENDIAN
*target = (long)nxflat_swap32(temp);
#else
*target = (long)temp;
#endif
/* Determine where the symbol lies */
/* 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.
*/
switch (get_reloc_type(rel_section, NULL))
{
@ -1047,51 +1127,24 @@ resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms) @@ -1047,51 +1127,24 @@ resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms)
err("Symbol relocation section type is unknown\n");
nerrors++;
}
/* Fall through and do something wrong */
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;
err("Cannot perform REL32 relocation: Symbol '%s' lies in D-Space\n",
rel_sym->name);
nerrors++;
}
break;
case NXFLAT_RELOC_TARGET_TEXT:
{
vdbg("Symbol '%s' lies in I-Space\n", rel_sym->name);
reloc_type = NXFLAT_RELOC_TYPE_REL32I;
relocate_arm32(relpp[j], target, sym_value - relpp[j]->address);
}
break;
}
/* Re-allocate memory to include this relocation */
relocs = (struct nxflat_reloc_s*)
realloc(nxflat_relocs, sizeof(struct nxflat_reloc_s) * nxflat_nrelocs + 1);
if (!relocs)
{
err("Failed to re-allocate memory ABS32 relocations (%d relocations)\n",
nxflat_nrelocs);
nerrors++;
}
else
{
/* Reallocation was successful. Update globlas */
nxflat_nrelocs++;
nxflat_relocs = relocs;
/* Then add the relocation at the end of the table */
nxflat_relocs[nxflat_nrelocs-1].r_info =
NXFLAT_RELOC(reloc_type, relpp[j]->address + got_size);
vdbg("relocs[%d]: type: %d offset: %08x\n",
nxflat_nrelocs-1,
NXFLAT_RELOC_TYPE(nxflat_relocs[nxflat_nrelocs-1].r_info),
NXFLAT_RELOC_OFFSET(nxflat_relocs[nxflat_nrelocs-1].r_info));
}
}
break;

Loading…
Cancel
Save