]> git.wh0rd.org Git - elf2flt.git/commitdiff
nios/nios2 support by Wentao Xu <wentao@microtronix.com>
authorDavid McCullough <davidm@snapgear.com>
Wed, 11 Jan 2006 03:39:16 +0000 (03:39 +0000)
committerDavid McCullough <davidm@snapgear.com>
Wed, 11 Jan 2006 03:39:16 +0000 (03:39 +0000)
cleaned up for inclusion by Mike Frysinger <vapier@gentoo.org>

config.sub
cygwin-elf.h
elf2flt.c

index 98c8b58a59db6e43f200603463326edeba077392..4279c84913a6df6fe8b8d8426742b6c0be7f64d4 100755 (executable)
@@ -256,6 +256,7 @@ case $basic_machine in
        | mipstx39 | mipstx39el \
        | mn10200 | mn10300 \
        | msp430 \
+       | nios | nios2 \
        | ns16k | ns32k \
        | openrisc | or32 \
        | pdp10 | pdp11 | pj | pjl \
@@ -334,6 +335,7 @@ case $basic_machine in
        | mipstx39-* | mipstx39el-* \
        | mmix-* \
        | msp430-* \
+       | nios-* | nios2-* \
        | none-* | np1-* | ns16k-* | ns32k-* \
        | orion-* \
        | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
index bcf7ae7912480f55a8f2cdc40f10513f254aa821..2523c0e04bd071b07b46f6a251c7fe901338ae18 100644 (file)
@@ -2110,8 +2110,62 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_MICROBLAZE_32_SYM_OP_SYM     10
 #define R_MICROBLAZE_GNU_VTINHERIT     11
 #define R_MICROBLAZE_GNU_VTENTRY       12
-   
+
 #define R_MICROBLAZE_NUM               13
 
+/* Altera NIOS specific definitions.  */
+
+#define FLAT_NIOS2_R_32                        0 /* Normal 32-bit reloc */
+#define FLAT_NIOS2_R_HI_LO             1
+#define FLAT_NIOS2_R_HIADJ_LO  2
+#define FLAT_NIOS2_R_CALL26            4
+
+/* NIOS relocations. */
+#define R_NIOS_NONE                            0
+#define R_NIOS_32                              1       /* A 32 bit absolute relocation.*/
+#define R_NIOS_LO16_LO5                        2       /* A LO-16 5 bit absolute relocation.  */
+#define R_NIOS_LO16_HI11               3       /* A LO-16 top 11 bit absolute relocation.  */
+#define R_NIOS_HI16_LO5                        4       /* A HI-16 5 bit absolute relocation.  */
+#define R_NIOS_HI16_HI11               5       /* A HI-16 top 11 bit absolute relocation.  */
+#define R_NIOS_PCREL6                  6       /* A 6 bit relative relocation.  */
+#define R_NIOS_PCREL8                  7       /* An 8 bit relative relocation.  */
+#define R_NIOS_PCREL11                 8       /* An 11 bit relative relocation.  */
+#define R_NIOS_16                              9       /* A 16 bit absolute relocation.  */
+#define R_NIOS_H_LO5                   10      /* Low 5-bits of absolute relocation in halfwords.  */
+#define R_NIOS_H_HI11                  11      /* Top 11 bits of 16-bit absolute relocation in halfwords.  */
+#define R_NIOS_H_XLO5                  12      /* Low 5 bits of top 16-bits of 32-bit absolute relocation in halfwords.  */
+#define R_NIOS_H_XHI11                 13      /* Top 11 bits of top 16-bits of 32-bit absolute relocation in halfwords.  */
+#define R_NIOS_H_16                            14      /* Half-word @h value */
+#define R_NIOS_H_32                            15      /* Word @h value */
+#define R_NIOS_GNU_VTINHERIT   200     /* GNU extension to record C++ vtable hierarchy */
+#define R_NIOS_GNU_VTENTRY             201     /* GNU extension to record C++ vtable member usage */
+/* Keep this the last entry.  */
+#define R_NIOS_NUM                             202
+
+/* NIOS II relocations */
+#define R_NIOS2_NONE                   0
+#define R_NIOS2_S16                            1
+#define R_NIOS2_U16                            2
+#define R_NIOS2_PCREL16                        3
+#define R_NIOS2_CALL26                 4
+#define R_NIOS2_IMM5                   5
+#define R_NIOS2_CACHE_OPX              6
+#define R_NIOS2_IMM6                   7
+#define R_NIOS2_IMM8                   8
+#define R_NIOS2_HI16                   9
+#define R_NIOS2_LO16                   10
+#define R_NIOS2_HIADJ16                11
+#define R_NIOS2_BFD_RELOC_32   12
+#define R_NIOS2_BFD_RELOC_16   13
+#define R_NIOS2_BFD_RELOC_8    14
+#define R_NIOS2_GPREL                  15
+#define R_NIOS2_GNU_VTINHERIT  16
+#define R_NIOS2_GNU_VTENTRY    17
+#define R_NIOS2_UJMP                   18
+#define R_NIOS2_CJMP                   19
+#define R_NIOS2_CALLR                  20
+#define R_NIOS2_ALIGN                  21
+/* Keep this the last entry.  */
+#define R_NIOS2_NUM                            22
 
 #endif /* elf.h */
index b46d224fba26cc74075128a54043a73e0c38a5bc..c8d6201ac9a360bf39fd4fb7563c1e598994cf0f 100644 (file)
--- a/elf2flt.c
+++ b/elf2flt.c
@@ -6,6 +6,7 @@
  * ELF format file handling. Extended relocation support for all of
  * text and data.
  *
+ * (c) 2004, Nios II support, Wentao Xu <wentao@microtronix.com>
  * (c) 2003, H8 support, ktrace <davidm@snapgear.com>
  * (c) 2003-2004, MicroBlaze support, John Williams <jwilliams@itee.uq.edu.au>
  * (c) 2001-2003, arm/arm-pic/arm-big-endian support <davidm@snapgear.com>
@@ -52,7 +53,7 @@
 
 #if defined(TARGET_h8300)
 #include <elf/h8.h>      /* TARGET_* ELF support for the BFD library            */
-#elif defined(__CYGWIN__) || defined(__MINGW32__)
+#elif defined(__CYGWIN__) || defined(__MINGW32__) || defined(TARGET_nios) || defined(TARGET_nios2)
 #include "cygwin-elf.h"        /* Cygwin uses a local copy */
 #elif defined(TARGET_microblaze)
 #include <elf/microblaze.h>    /* TARGET_* ELF support for the BFD library */
 #define FLAT_RELOC_PART_LO 0
 #define FLAT_RELOC_PART_HI 1
 #define PCREL24_MAGIC_OFFSET -1
+#elif defined(TARGET_nios)
+#define ARCH   "nios"
+#elif defined(TARGET_nios2)
+#define ARCH   "nios2"
 #else
 #error "Don't know how to support your CPU architecture??"
 #endif
@@ -270,6 +275,19 @@ get_symbol_offset(char *name, asection *sec, asymbol **symbol_table, long number
 
 
 
+long
+get_gp_value(asymbol **symbol_table, long number_of_symbols)
+{
+  long i;
+  for (i=0; i<number_of_symbols; i++) {
+      if (!strcmp(symbol_table[i]->name, "_gp"))
+               return symbol_table[i]->value;
+  }
+  return -1;
+}
+
+
 long
 add_com_to_bss(asymbol **symbol_table, long number_of_symbols, long bss_len)
 {
@@ -607,7 +625,167 @@ dump_symbols(symbols, number_of_symbols);
                                continue;
                        }
 #endif /* TARGET_microblaze */
-                          
+
+#ifdef TARGET_nios2
+#define  htoniosl(x)   (x)
+#define  niostohl(x)   (x)
+                       switch ((*p)->howto->type) 
+                       {
+                               case R_NIOS2_BFD_RELOC_32:
+                                       relocation_needed = 1;
+                                       pflags = (FLAT_NIOS2_R_32 << 28);
+                                       sym_vma = bfd_section_vma(abs_bfd, sym_section);
+                                       sym_addr += sym_vma + q->addend;
+                                       /* modify target, in target order */
+                                       *(unsigned long *)r_mem = htoniosl(sym_addr);
+                                       break;
+                               case R_NIOS2_CALL26:
+                               {
+                                       unsigned long exist_val;
+                                       relocation_needed = 1;
+                                       pflags = (FLAT_NIOS2_R_CALL26 << 28);
+                                       sym_vma = bfd_section_vma(abs_bfd, sym_section);
+                                       sym_addr += sym_vma + q->addend;
+                                       
+                                       /* modify target, in target order */
+                                       // exist_val = niostohl(*(unsigned long *)r_mem);
+                                       exist_val = ((sym_addr >> 2) << 6);
+                                       *(unsigned long *)r_mem = htoniosl(exist_val);
+                                       break;
+                               }
+                               case R_NIOS2_HIADJ16:
+                               case R_NIOS2_HI16:
+                               {
+                                       unsigned long exist_val;
+                                       int r2_type;
+                                       /* handle the adjacent HI/LO pairs */
+                                       if (relcount == 0)
+                                               r2_type = R_NIOS2_NONE;
+                                       else
+                                               r2_type = p[1]->howto->type;
+                                       if ((r2_type == R_NIOS2_LO16)
+                                           && (p[0]->sym_ptr_ptr == p[1]->sym_ptr_ptr)
+                                           && (p[0]->addend == p[1]->addend)) 
+                                           {
+                                                       unsigned char * r2_mem = sectionp + p[1]->address;
+                                                       if (p[1]->address - q->address!=4)
+                                                               printf("Err: HI/LO not adjacent %d\n", p[1]->address - q->address);
+                                                       relocation_needed = 1;
+                                                       pflags = (q->howto->type == R_NIOS2_HIADJ16) 
+                                                               ? FLAT_NIOS2_R_HIADJ_LO : FLAT_NIOS2_R_HI_LO;
+                                                       pflags <<= 28;
+                                               
+                                                       sym_vma = bfd_section_vma(abs_bfd, sym_section);
+                                                       sym_addr += sym_vma + q->addend;
+
+                                                       /* modify high 16 bits, in target order */
+                                                       exist_val = niostohl(*(unsigned long *)r_mem);
+                                                       exist_val =  ((exist_val >> 22) << 22) | (exist_val & 0x3f);
+                                                       if (q->howto->type == R_NIOS2_HIADJ16)
+                                                               exist_val |= ((((sym_addr >> 16) + ((sym_addr >> 15) & 1)) & 0xFFFF) << 6);
+                                                       else
+                                                               exist_val |= (((sym_addr >> 16) & 0xFFFF) << 6);
+                                                       *(unsigned long *)r_mem = htoniosl(exist_val);
+
+                                                       /* modify low 16 bits, in target order */
+                                                       exist_val = niostohl(*(unsigned long *)r2_mem);
+                                                       exist_val =  ((exist_val >> 22) << 22) | (exist_val & 0x3f);
+                                                       exist_val |= ((sym_addr & 0xFFFF) << 6);
+                                                       *(unsigned long *)r2_mem = htoniosl(exist_val);
+                                               
+                                               } else 
+                                                       goto NIOS2_RELOC_ERR;
+                                       }
+                                       break;
+
+                               case R_NIOS2_GPREL:
+                               {
+                                       unsigned long exist_val, temp;
+                                       //long gp = get_symbol_offset("_gp", sym_section, symbols, number_of_symbols);
+                                       long gp = get_gp_value(symbols, number_of_symbols);
+                                       if (gp == -1) {
+                                               printf("Err: unresolved symbol _gp when relocating %s\n", sym_name);
+                                               goto NIOS2_RELOC_ERR;
+                                       }
+                                       /* _gp holds a absolute value, otherwise the ld cannot generate correct code */
+                                       sym_vma = bfd_section_vma(abs_bfd, sym_section);
+                                       //printf("sym=%x, %d, _gp=%x, %d\n", sym_addr+sym_vma, sym_addr+sym_vma, gp, gp);
+                                       sym_addr += sym_vma + q->addend;
+                                       sym_addr -= gp;
+                                       //printf("sym - _gp=%x, %d\n", sym_addr, sym_addr);
+                                       /* modify the target, in target order (little_endian) */
+                                       exist_val = niostohl(*(unsigned long *)r_mem);
+                                       temp = ((exist_val >> 6) & 0x3ff0000) | (sym_addr & 0xffff);
+                                       temp <<= 6;
+                                       temp |= (exist_val & 0x3f);
+                                       *(unsigned long *)r_mem = htoniosl(temp);
+                                       if (verbose)
+                                               printf("omit: offset=0x%x symbol=%s%s "
+                                                               "section=%s size=%d "
+                                                               "fixup=0x%x (reloc=0x%x) GPREL\n", 
+                                                               q->address, sym_name, addstr,
+                                                               section_name, sym_reloc_size,
+                                                               sym_addr, section_vma + q->address);
+                                       continue;
+                               }
+                               case R_NIOS2_PCREL16:
+                               {
+                                       unsigned long exist_val;
+                                       sym_vma = 0;
+                                       sym_addr += sym_vma + q->addend;
+                                       sym_addr -= (q->address + 4);
+                                       /* modify the target, in target order (little_endian) */
+                                       exist_val = niostohl(*(unsigned long *)r_mem);
+                                       exist_val =  ((exist_val >> 22) << 22) | (exist_val & 0x3f);
+                                       exist_val |= ((sym_addr & 0xFFFF) << 6);
+                                       *(unsigned long *)r_mem = htoniosl(exist_val);
+                                       if (verbose)
+                                               printf("omit: offset=0x%x symbol=%s%s "
+                                                               "section=%s size=%d "
+                                                               "fixup=0x%x (reloc=0x%x) PCREL\n", 
+                                                               q->address, sym_name, addstr,
+                                                               section_name, sym_reloc_size,
+                                                               sym_addr, section_vma + q->address);
+                                       continue;
+                               }
+
+                               case R_NIOS2_LO16:
+                                       /* check if this is actually the 2nd half of a pair */
+                                       if ((p > relpp)
+                                               && ((p[-1]->howto->type == R_NIOS2_HIADJ16) 
+                                                       || (p[-1]->howto->type == R_NIOS2_HI16))
+                                           && (p[-1]->sym_ptr_ptr == p[0]->sym_ptr_ptr)
+                                           && (p[-1]->addend == p[0]->addend)) {
+                                               if (verbose)
+                                                       printf("omit: offset=0x%x symbol=%s%s "
+                                                               "section=%s size=%d LO16\n", 
+                                                               q->address, sym_name, addstr,
+                                                               section_name, sym_reloc_size);
+                                               continue;
+                                       }
+
+                                       /* error, fall through */
+
+                               case R_NIOS2_S16:
+                               case R_NIOS2_U16:
+                               case R_NIOS2_CACHE_OPX:
+                               case R_NIOS2_IMM5:
+                               case R_NIOS2_IMM6:
+                               case R_NIOS2_IMM8:
+                               case R_NIOS2_BFD_RELOC_16:
+                               case R_NIOS2_BFD_RELOC_8:
+                               case R_NIOS2_GNU_VTINHERIT:
+                               case R_NIOS2_GNU_VTENTRY:
+                               case R_NIOS2_UJMP:
+                               case R_NIOS2_CJMP:
+                               case R_NIOS2_CALLR:
+NIOS2_RELOC_ERR:
+                                       printf("Err: unexpected reloc type %s(%d)\n", q->howto->name, q->howto->type);
+                                       bad_relocs++;
+                                       continue;
+                       }
+#endif /* TARGET_nios2 */
+
 #ifdef TARGET_v850
                        /* Skip this relocation entirely if possible (we
                           do this early, before doing any other
@@ -1549,6 +1727,16 @@ DIS29_RELOCATION:
                                           loaders knows about it.  */
                                        break;
 #endif /* TARGET_V850 */
+
+#ifdef TARGET_nios2
+                               case R_NIOS2_BFD_RELOC_32:
+                               case R_NIOS2_CALL26:
+                               case R_NIOS2_HIADJ16:
+                               case R_NIOS2_HI16:
+                                       /* do nothing */
+                                       break;
+#endif /* TARGET_nios2 */
+
                                default:
                                        /* The alignment of the build host
                                           might be stricter than that of the