diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-06-19 17:55:09 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-06-19 17:55:09 +0000 |
commit | 3019d4d5ab7e3e99dcbc39463f6887c0d5ea1bba (patch) | |
tree | 818eeab6636fa670d410783a642d3da24b289337 /misc/buildroot/toolchain/nxflat/ldnxflat.c | |
parent | fba48036d54d157add306013d8aac832e6cc52ad (diff) | |
download | nuttx-3019d4d5ab7e3e99dcbc39463f6887c0d5ea1bba.tar.gz nuttx-3019d4d5ab7e3e99dcbc39463f6887c0d5ea1bba.tar.bz2 nuttx-3019d4d5ab7e3e99dcbc39463f6887c0d5ea1bba.zip |
thunks should not use GOT address
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1910 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'misc/buildroot/toolchain/nxflat/ldnxflat.c')
-rw-r--r-- | misc/buildroot/toolchain/nxflat/ldnxflat.c | 320 |
1 files changed, 82 insertions, 238 deletions
diff --git a/misc/buildroot/toolchain/nxflat/ldnxflat.c b/misc/buildroot/toolchain/nxflat/ldnxflat.c index 65c8133ce..0949d8492 100644 --- a/misc/buildroot/toolchain/nxflat/ldnxflat.c +++ b/misc/buildroot/toolchain/nxflat/ldnxflat.c @@ -127,14 +127,16 @@ * Private Types ***********************************************************************/ +/* Needs to match definition in include/elf/internal.h. This is from binutils-2.19.1 */ + struct elf_internal_sym { - bfd_vma st_value; /* Value of the symbol */ - bfd_vma st_size; /* Associated symbol size */ - u_int32_t st_name; /* Symbol name, index in string tbl */ - u_int8_t st_info; /* Type and binding attributes */ - u_int8_t st_other; /* No defined meaning, 0 */ - u_int16_t st_shndx; /* Associated section index */ + bfd_vma st_value; /* Value of the symbol */ + bfd_vma st_size; /* Associated symbol size */ + unsigned long st_name; /* Symbol name, index in string tbl */ + unsigned char st_info; /* Type and binding attributes */ + unsigned char st_other; /* Visibilty, and target specific */ + unsigned int st_shndx; /* Associated section index */ }; typedef struct @@ -738,12 +740,13 @@ static void resolve_segment_relocs(bfd * input_bfd, segment_info * inf, asymbol ** syms, u_int32_t * n_relocs, struct nxflat_reloc_s **relocs) { - int i; - int j; - int relsize, relcount; - arelent **relpp; struct nxflat_reloc_s *nxflat_relocs; + arelent **relpp; u_int32_t nxflat_reloc_count; + int relsize; + int relcount; + int i; + int j; nxflat_relocs = *relocs; nxflat_reloc_count = *n_relocs; @@ -777,6 +780,7 @@ resolve_segment_relocs(bfd * input_bfd, segment_info * inf, asymbol ** syms, fprintf(stderr, "ERROR: bfd_canonicalize_reloc failed!\n"); exit(1); } + if (verbose) { printf("Section %s can'd %08x relocs\n", @@ -785,9 +789,22 @@ resolve_segment_relocs(bfd * input_bfd, segment_info * inf, asymbol ** syms, for (j = 0; j < relcount; j++) { - reloc_howto_type *how_to = relpp[j]->howto; - asymbol *rel_sym = *relpp[j]->sym_ptr_ptr; - asection *rel_section = rel_sym->section; + /* Get information about this symbol */ + + reloc_howto_type *how_to = relpp[j]->howto; + asymbol *rel_sym = *relpp[j]->sym_ptr_ptr; + asection *rel_section = rel_sym->section; + symvalue sym_value; + + /* If the symbol is a thumb function, then set bit 1 of the value */ + + sym_value = rel_sym->value; +#ifdef NXFLAT_ARM + if ((((elf_symbol_type *)rel_sym)->internal_elf_sym.st_info & 0x0f) == STT_ARM_TFUNC) + { + sym_value |= 1; + } +#endif if (verbose > 1) { @@ -812,7 +829,7 @@ resolve_segment_relocs(bfd * input_bfd, segment_info * inf, asymbol ** syms, printf("performing PC24 link at addr %08x to " "sym [%20s] @ %08x\n", (u_int32_t) relpp[j]->address, rel_sym->name, - (u_int32_t) rel_sym->value); + (u_int32_t) sym_value); } /* Can't fix what we ain't got */ @@ -875,7 +892,7 @@ resolve_segment_relocs(bfd * input_bfd, segment_info * inf, asymbol ** syms, /* offset */ temp += - ((rel_sym->value + rel_sym->section->vma) + ((sym_value + rel_sym->section->vma) - relpp[j]->address) >> how_to->rightshift; /* demote */ @@ -916,7 +933,7 @@ resolve_segment_relocs(bfd * input_bfd, segment_info * inf, asymbol ** syms, printf("performing ABS32 link at addr %08x to " "sym [%20s] @ %08x\n", (u_int32_t) relpp[j]->address, rel_sym->name, - (u_int32_t) rel_sym->value); + (u_int32_t) sym_value); } /* ABS32 links from .text are easy - since the fetches will */ @@ -959,7 +976,7 @@ resolve_segment_relocs(bfd * input_bfd, segment_info * inf, asymbol ** syms, /* offset */ - temp += (rel_sym->value + rel_sym->section->vma) >> + temp += (sym_value + rel_sym->section->vma) >> how_to->rightshift; /* demote */ @@ -988,7 +1005,9 @@ resolve_segment_relocs(bfd * input_bfd, segment_info * inf, asymbol ** syms, int reltype; if (verbose) - printf("RELOCATION in DATA!\n"); + { + printf("RELOCATION in DATA!\n"); + } /* Locate the address referred to by section type. */ @@ -1017,7 +1036,7 @@ resolve_segment_relocs(bfd * input_bfd, segment_info * inf, asymbol ** syms, "Attempted GOTOFF reloc at addr %08x to " "sym [%20s] @ %08x\n", (u_int32_t) relpp[j]->address, rel_sym->name, - (u_int32_t) rel_sym->value); + (u_int32_t) sym_value); goto got_not_supported; case R_ARM_GOT32: @@ -1027,7 +1046,7 @@ resolve_segment_relocs(bfd * input_bfd, segment_info * inf, asymbol ** syms, "Attempted GOT32 reloc at addr %08x to " "sym [%20s] @ %08x\n", (u_int32_t) relpp[j]->address, rel_sym->name, - (u_int32_t) rel_sym->value); + (u_int32_t) sym_value); goto got_not_supported; case R_ARM_GOTPC: @@ -1036,7 +1055,7 @@ resolve_segment_relocs(bfd * input_bfd, segment_info * inf, asymbol ** syms, "Attempted GOTPC reloc at addr %08x to " "sym [%20s] @ %08x\n", (u_int32_t) relpp[j]->address, rel_sym->name, - (u_int32_t) rel_sym->value); + (u_int32_t) sym_value); got_not_supported: fprintf(stderr, @@ -1070,38 +1089,59 @@ resolve_segment_relocs(bfd * input_bfd, segment_info * inf, asymbol ** syms, static void dump_symbol(asymbol * psym) { + struct elf_internal_sym *isym = + (struct elf_internal_sym *)&((elf_symbol_type *)psym)->internal_elf_sym; + if (bfd_is_com_section(psym->section)) { /* Common Global - unplaced */ printf("Sym[%24s] @ sz %04x ", psym->name, (u_int32_t) psym->value); - printf("align %04x ", - (u_int32_t) ((elf_symbol_type *) psym)->internal_elf_sym.st_value); + printf("align %04x ", (u_int32_t)isym->st_value); } else { printf("Sym[%24s] @ %04x align ", psym->name, (u_int32_t) psym->value); - printf("sz %04x ", - (u_int32_t) ((elf_symbol_type *) psym)->internal_elf_sym.st_size); + printf("sz %04x ", (u_int32_t)isym->st_size); + } + + /* Symbol type */ + + printf("tp %02x ", isym->st_info); + + /* Tag thumb specific attributes */ + +#ifdef NXFLAT_ARM + if ((isym->st_info & 0x0f) == STT_ARM_TFUNC || (isym->st_info & 0x0f) == STT_ARM_16BIT) + { + putchar('T'); } - printf("%c", psym->flags & BSF_OBJECT ? 'O' : ' '); - printf("%c", psym->flags & BSF_DYNAMIC ? 'D' : ' '); - printf("%c", psym->flags & BSF_FILE ? 'F' : ' '); - printf("%c", psym->flags & BSF_INDIRECT ? 'I' : ' '); - printf("%c", psym->flags & BSF_WARNING ? 'W' : ' '); - printf("%c", psym->flags & BSF_CONSTRUCTOR ? 'C' : ' '); - printf("%c", psym->flags & BSF_NOT_AT_END ? 'N' : ' '); - printf("%c", psym->flags & BSF_OLD_COMMON ? 'c' : ' '); - printf("%c", psym->flags & BSF_SECTION_SYM ? 'S' : ' '); - printf("%c", psym->flags & BSF_WEAK ? 'w' : ' '); - printf("%c", psym->flags & BSF_KEEP_G ? 'G' : ' '); - printf("%c", psym->flags & BSF_KEEP ? 'K' : ' '); - printf("%c", psym->flags & BSF_FUNCTION ? 'f' : ' '); - printf("%c", psym->flags & BSF_DEBUGGING ? 'd' : ' '); - printf("%c", psym->flags & BSF_GLOBAL ? 'g' : ' '); - printf("%c", psym->flags & BSF_LOCAL ? 'l' : ' '); + else + { + putchar(' '); + } +#endif + + /* Common attributes */ + + printf("|%c", psym->flags & BSF_OBJECT ? 'O' : '.'); + printf("%c", psym->flags & BSF_DYNAMIC ? 'D' : '.'); + printf("%c", psym->flags & BSF_FILE ? 'F' : '.'); + printf("%c", psym->flags & BSF_INDIRECT ? 'I' : '.'); + printf("%c", psym->flags & BSF_WARNING ? 'W' : '.'); + printf("%c", psym->flags & BSF_CONSTRUCTOR ? 'C' : '.'); + printf("%c", psym->flags & BSF_NOT_AT_END ? 'N' : '.'); + printf("%c", psym->flags & BSF_OLD_COMMON ? 'c' : '.'); + printf("%c", psym->flags & BSF_SECTION_SYM ? 'S' : '.'); + printf("%c", psym->flags & BSF_WEAK ? 'w' : '.'); + printf("%c", psym->flags & BSF_KEEP_G ? 'G' : '.'); + printf("%c", psym->flags & BSF_KEEP ? 'K' : '.'); + printf("%c", psym->flags & BSF_FUNCTION ? 'f' : '.'); + printf("%c", psym->flags & BSF_DEBUGGING ? 'd' : '.'); + printf("%c", psym->flags & BSF_GLOBAL ? 'g' : '.'); + printf("%c|", psym->flags & BSF_LOCAL ? 'l' : '.'); printf("\n"); } @@ -1356,17 +1396,8 @@ static struct nxflat_reloc_s *output_relocs(bfd * input_bfd, asymbol ** symbols, u_int32_t * n_relocs) { struct nxflat_reloc_s *nxflat_relocs; - asection *sym_section; - arelent **relpp, **p, *q; - const char *sym_name, *section_name; u_int32_t nxflat_reloc_count; - int relsize, relcount; - int reltype; int rc; - bfd_vma v, addend; - segment_info *relseg, *sym_segment; - u_int32_t seg_offset; - int i; *n_relocs = 0; @@ -1374,10 +1405,6 @@ static struct nxflat_reloc_s *output_relocs(bfd * input_bfd, asymbol ** symbols, nxflat_reloc_count = 0; rc = 0; -#if 1 - - /* new code */ - if (verbose) { printf(" Before mapp high mark %08x cooked %08x raw %08x \n", @@ -1422,188 +1449,6 @@ static struct nxflat_reloc_s *output_relocs(bfd * input_bfd, asymbol ** symbols, /* need to emit relocs for data only */ return nxflat_relocs; - -#endif - - relsize = bfd_get_dynamic_reloc_upper_bound(input_bfd); - if (relsize <= 0) - { - if (verbose) - printf("no relocation entries\n"); - return 0; - } - - relpp = (arelent **) malloc(relsize); - relcount = bfd_canonicalize_dynamic_reloc(input_bfd, relpp, symbols); - if (relcount <= 0) - { - if (verbose) - printf("no relocation entries\n"); - *n_relocs = 0; - return NULL; - } - - for (p = relpp; (relcount && (*p != NULL)); p++, relcount--) - { - q = *p; - if (q->sym_ptr_ptr && *q->sym_ptr_ptr) - { - sym_name = (*(q->sym_ptr_ptr))->name; - sym_section = (*(q->sym_ptr_ptr))->section; - section_name = (*(q->sym_ptr_ptr))->section->name; - - if (verbose) - { - printf("Reloc address %08x type %s\n", - (u_int32_t) q->address, q->howto->name); - } - - switch (q->howto->type) - { - case R_ARM_RELATIVE: - /* This reloc describes an offset from the "program base". We - * need to figure out which segment it actually refers to, fiddle - * the addend and output an appropriate FLAT reloc to be resolved - * at run time. */ - /* XXX In an ideal world, the linker would output different - * relocs for the different sections, so we wouldn't need to grub - * around in the memory map quite so much. */ - - v = q->address; - reltype = -1; - relseg = sym_segment = NULL; - if (v >= text_info.low_mark && v <= text_info.high_mark) - { - /* The existing FLAT binary format only allows relocs to be - * in the .data segment. Relocating in .text would be bad - * practice anyway so this is no great loss. */ - - printf("WARNING: Illegal RELATIVE reloc in text " - "segment ignored.\n"); - continue; - } - else if (v >= data_info.low_mark && v <= data_info.high_mark) - relseg = &data_info; - - if (!relseg) - { - /* This reloc isn't in the text or data segment. Probably it - * refers to debug information and we can just ignore it. */ - - if (verbose) - { - fprintf(stderr, - "WARNING: ignoring reloc at %08x\n", - (u_int32_t) v); - } - continue; - } - - /* Locate the reloc in the appropriate segment and extract the - * existing addend. */ - - seg_offset = v - relseg->low_mark; - addend = *((bfd_vma *) (relseg->contents + seg_offset)); - - if (verbose) - { - printf("RELATIVE reloc at (%s+%08x) addend %08x\n", - relseg->name, seg_offset, (u_int32_t) addend); - } - - /* Locate the address referred to by section type. */ - - reltype = get_reloc_type(sym_section, &sym_segment); - - if (!sym_segment) - { - /* The addend isn't within any of the segments we know about. - * This might mean it was in a section we threw away. In any - * case, there is nothing we can do about it now. */ - - printf("ERROR: reloc at (%s+%08x) has out of " - " range addend %08x or unrecognized " - " section \"%s\"\n", - relseg->name, seg_offset, - (u_int32_t) addend, sym_section->name); - rc = -1; - continue; - } - - /* Verify that the addend offset lies within the address range we - * have identified for the segment. */ - - if (addend < sym_segment->low_mark || - addend > sym_segment->high_mark) - { - fprintf(stderr, - "ERROR: Symbol addend %x does lie within " - "segment address range (%x-%x)\n", - (u_int32_t) addend, (u_int32_t) sym_segment->low_mark, - (u_int32_t) sym_segment->high_mark); - continue; - } - - /* Factor out the starting VMA of the segment, adjust the addend - * in core and output a new reloc. */ - - addend -= sym_segment->low_mark; - - if (verbose) - { - printf("(%s+%08x)\n", - sym_segment->name, (u_int32_t) addend); - } - - *((bfd_vma *) (relseg->contents + seg_offset)) = addend; - - nxflat_relocs = realloc(nxflat_relocs, - (nxflat_reloc_count + 1) - * sizeof(struct nxflat_reloc_s)); - - nxflat_relocs[nxflat_reloc_count].r_info = NXFLAT_RELOC(reltype, seg_offset); - nxflat_reloc_count++; - break; - - case R_ARM_PC24: - case R_ARM_GLOB_DAT: - /* Because we linked with -Bsymbolic, the linker will already - * have resolved all function calls apart from those to undefined - * symbols. So long as this is a weak reference, we do nothing - * and the reloc will be incomplete - it is up to the application - * to avoid executing such branches. Global data relocs are also - * OK to leave unresolved since they will yield zero by default. - * If we encounter an unresolved strong reference we punt; the - * linker should have trapped this case already so this is a - * "can't happen" situation. */ - - if (!((*q->sym_ptr_ptr)->flags & BSF_WEAK)) - { - printf("ERROR: undefined symbolic reference to %s\n", - (*q->sym_ptr_ptr)->name); - rc = -1; - } - break; - - default: - printf("ERROR: unknown reloc type %s\n", q->howto->name); - rc = -1; - break; - } - } - else - { - printf("ERROR: undefined relocation entry\n"); - rc = -1; - continue; - } - } - - if (rc < 0) - return (NULL); - - *n_relocs = nxflat_reloc_count; - return nxflat_relocs; } /*********************************************************************** @@ -2018,8 +1863,7 @@ int main(int argc, char **argv, char **envp) load_sections(bf, &text_info); load_sections(bf, &data_info); - reloc = (u_int32_t *) - output_relocs(bf, symbol_table, number_of_symbols, &reloc_len); + reloc = (u_int32_t*)output_relocs(bf, symbol_table, number_of_symbols, &reloc_len); /* Fill in the xFLT file header */ |