mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-11-02 06:11:37 +08:00
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
This commit is contained in:
@@ -119,4 +119,6 @@ buildroot-1.11 2011-xx-xx <gnutt@nuttx.org>
|
|||||||
* Add support for binutils 2.22 and GCC 4.6.3.
|
* Add support for binutils 2.22 and GCC 4.6.3.
|
||||||
* Change name of all tools from xxx-elf to xxx-nuttx-elf
|
* 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-).
|
* 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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
* resolve_segment_relocs
|
||||||
***********************************************************************/
|
***********************************************************************/
|
||||||
@@ -806,10 +934,8 @@ static void alloc_got_entry(asymbol *sym)
|
|||||||
static void
|
static void
|
||||||
resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms)
|
resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms)
|
||||||
{
|
{
|
||||||
struct nxflat_reloc_s *relocs;
|
|
||||||
arelent **relpp;
|
arelent **relpp;
|
||||||
int relsize;
|
int relsize;
|
||||||
int reloc_type;
|
|
||||||
int relcount;
|
int relcount;
|
||||||
int i;
|
int i;
|
||||||
int j;
|
int j;
|
||||||
@@ -976,69 +1102,23 @@ resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms)
|
|||||||
|
|
||||||
case R_ARM_ABS32:
|
case R_ARM_ABS32:
|
||||||
{
|
{
|
||||||
int32_t temp;
|
|
||||||
int32_t saved;
|
|
||||||
|
|
||||||
dbg("Performing ABS32 link at addr %08lx [%08lx] to sym '%s' [%08lx]\n",
|
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);
|
(long)relpp[j]->address, (long)*target, rel_sym->name, (long)sym_value);
|
||||||
|
|
||||||
/* ABS32 links from .text are easy - since the fetches will
|
relocate_arm32(relpp[j], target, sym_value);
|
||||||
* always be base relative. the ABS32 refs from data will be
|
}
|
||||||
* handled the same
|
break;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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 (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))
|
switch (get_reloc_type(rel_section, NULL))
|
||||||
{
|
{
|
||||||
case NXFLAT_RELOC_TARGET_UNKNOWN:
|
case NXFLAT_RELOC_TARGET_UNKNOWN:
|
||||||
@@ -1047,51 +1127,24 @@ resolve_segment_relocs(bfd *input_bfd, segment_info *inf, asymbol **syms)
|
|||||||
err("Symbol relocation section type is unknown\n");
|
err("Symbol relocation section type is unknown\n");
|
||||||
nerrors++;
|
nerrors++;
|
||||||
}
|
}
|
||||||
/* Fall through and do something wrong */
|
break;
|
||||||
|
|
||||||
case NXFLAT_RELOC_TARGET_BSS:
|
case NXFLAT_RELOC_TARGET_BSS:
|
||||||
case NXFLAT_RELOC_TARGET_DATA:
|
case NXFLAT_RELOC_TARGET_DATA:
|
||||||
{
|
{
|
||||||
vdbg("Symbol '%s' lies in D-Space\n", rel_sym->name);
|
err("Cannot perform REL32 relocation: Symbol '%s' lies in D-Space\n",
|
||||||
reloc_type = NXFLAT_RELOC_TYPE_REL32D;
|
rel_sym->name);
|
||||||
|
nerrors++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NXFLAT_RELOC_TARGET_TEXT:
|
case NXFLAT_RELOC_TARGET_TEXT:
|
||||||
{
|
{
|
||||||
vdbg("Symbol '%s' lies in I-Space\n", rel_sym->name);
|
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;
|
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;
|
break;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user