OSDN Git Service

this patch adds Cygwin support to elf2flt. Also include a copy
[uclinux-h8/elf2flt.git] / elf2flt.c
index dce6506..f661d36 100644 (file)
--- a/elf2flt.c
+++ b/elf2flt.c
@@ -6,7 +6,7 @@
  * ELF format file handling. Extended relocation support for all of
  * text and data.
  *
- * (c) 2003, H8 support <davidm@snapgear.com>
+ * (c) 2003, H8 support, ktrace <davidm@snapgear.com>
  * (c) 2001-2003, arm/arm-pic/arm-big-endian support <davidm@snapgear.com>
  * (c) 2001, v850 changes, Mile Bader <miles@lsi.nec.co.jp>
  * (c) 2003, SuperH support, Paul Mundt <lethal@linux-sh.org>
@@ -48,6 +48,8 @@
 
 #if defined(TARGET_h8300)
 #include <elf/h8.h>      /* TARGET_* ELF support for the BFD library            */
+#elif defined(__CYGWIN__)
+#include "cygwin-elf.h"        /* Cygwin uses a local copy */
 #else
 #include <elf.h>      /* TARGET_* ELF support for the BFD library            */
 #endif
@@ -78,6 +80,7 @@
 #error "Don't know how to support your CPU architecture??"
 #endif
 
+#ifdef TARGET_m68k
 /*
  * Define a maximum number of bytes allowed in the offset table.
  * We'll fail if the table is larger than this.
  * 8000 entries is a lot,  trust me :-) (davidm)
  */
 #define GOT_LIMIT 32767
+/*
+ * we have to mask out the shared library id here and there,  this gives
+ * us the real address bits when needed
+ */
+#define        real_address_bits(x)    (pic_with_got ? ((x) & 0xffffff) : (x))
+#else
+#define        real_address_bits(x)    (x)
+#endif
 
 #ifndef O_BINARY
 #define O_BINARY 0
 int verbose = 0;      /* extra output when running */
 int pic_with_got = 0; /* do elf/got processing with PIC code */
 int load_to_ram = 0;  /* instruct loader to allocate everything into RAM */
+int ktrace = 0;       /* instruct loader output kernel trace on load */
 int compress = 0;     /* 1 = compress everything, 2 = compress data only */
 int use_resolved = 0; /* If true, get the value of symbol references from */
                      /* the program contents, not from the relocation table. */
@@ -337,9 +349,9 @@ dump_symbols(symbols, number_of_symbols);
         *      otherwise do text as well
         */
        if (!pic_with_got && (a->flags & SEC_CODE))
-               sectionp = text;
+               sectionp = text + (a->vma - text_vma);
        else if (a->flags & SEC_DATA)
-               sectionp = data;
+               sectionp = data + (a->vma - data_vma);
        else
                continue;
 
@@ -481,21 +493,35 @@ dump_symbols(symbols, number_of_symbols);
                                   still depend on the particular relocation
                                   though.  */
                                switch (q->howto->type) {
+                                       int r2_type;
 #ifdef TARGET_v850
                                case R_V850_HI16_S:
                                        /* We specially handle adjacent
-                                          HI16_S/ZDA_15_16_OFFSET pairs that
-                                          reference the same address (these
-                                          are usually movhi/ld pairs).  */
-                                       if (relcount > 1
-                                           && (p[1]->howto->type
-                                               == R_V850_ZDA_15_16_OFFSET)
+                                          HI16_S/ZDA_15_16_OFFSET and
+                                          HI16_S/LO16 pairs that reference the
+                                          same address (these are usually
+                                          movhi/ld and movhi/movea pairs,
+                                          respectively).  */
+                                       if (relcount == 0)
+                                               r2_type = R_V850_NONE;
+                                       else
+                                               r2_type = p[1]->howto->type;
+                                       if ((r2_type == R_V850_ZDA_15_16_OFFSET
+                                            || r2_type == R_V850_LO16)
                                            && (p[0]->sym_ptr_ptr
                                                == p[1]->sym_ptr_ptr)
                                            && (p[0]->addend == p[1]->addend))
                                        {
                                                relocation_needed = 1;
-                                               pflags = 0x80000000;
+
+                                               switch (r2_type) {
+                                               case R_V850_ZDA_15_16_OFFSET:
+                                                       pflags = 0x10000000;
+                                                       break;
+                                               case R_V850_LO16:
+                                                       pflags = 0x20000000;
+                                                       break;
+                                               }
 
                                                /* We don't really need the
                                                   actual value -- the bits
@@ -516,25 +542,43 @@ dump_symbols(symbols, number_of_symbols);
                                                        /* Sign extend LO.  */
                                                        lo = (lo ^ 0x8000)
                                                                - 0x8000;
-                                                       /* Ignore the LSB of
-                                                          LO, which is
+
+                                                       /* Maybe ignore the LSB
+                                                          of LO, which is
                                                           actually part of the
                                                           instruction.  */
-                                                       lo &= ~1;
+                                                       if (r2_type != R_V850_LO16)
+                                                               lo &= ~1;
+
                                                        sym_addr =
                                                                (hi << 16)
                                                                + lo;
                                                }
                                        } else
-                               case R_V850_HI16:
+                                               goto bad_v850_reloc_err;
+                                       break;
+
                                case R_V850_LO16:
-                                       {
-                                               printf("ERROR: reloc type %s unsupported in this context\n",
-                                                      q->howto->name);
-                                               bad_relocs++;
-                                       }
+                                       /* See if this is actually the
+                                          2nd half of a pair.  */
+                                       if (p > relpp
+                                           && (p[-1]->howto->type
+                                               == R_V850_HI16_S)
+                                           && (p[-1]->sym_ptr_ptr
+                                               == p[0]->sym_ptr_ptr)
+                                           && (p[-1]->addend == p[0]->addend))
+                                               break; /* not an error */
+                                       else
+                                               goto bad_v850_reloc_err;
+
+                               case R_V850_HI16:
+                               bad_v850_reloc_err:
+                                       printf("ERROR: reloc type %s unsupported in this context\n",
+                                              q->howto->name);
+                                       bad_relocs++;
                                        break;
 #endif /* TARGET_V850 */
+
                                default:
                                        /* The default is to assume that the
                                           relocation is relative and has
@@ -742,12 +786,19 @@ dump_symbols(symbols, number_of_symbols);
                                        continue;
                                }
                                case R_MICROBLAZE_32:
-                                       relocation_needed = 1;
+                               {       
+                                       unsigned char *p = r_mem;
+                                       unsigned long offset;
+
+                                       /* grab any offset from the text */
+                                       offset = (p[0]<<24) + (p[1] << 16) + (p[2] << 8) + (p[3]);
                                        //sym_addr = (*(q->sym_ptr_ptr))->value;
                                        sym_vma = bfd_section_vma(abs_bfd, sym_section);
-                                       sym_addr += sym_vma + q->addend;
-                                       break;
+                                       sym_addr += offset + sym_vma + q->addend;
 
+                                       relocation_needed = 1;
+                                       break;
+                               }
                                case R_MICROBLAZE_64_PCREL:
                                        sym_vma = 0;
                                        //sym_addr = (*(q->sym_ptr_ptr))->value;
@@ -1050,6 +1101,7 @@ static void usage(void)
        "[-o <output-file>] <elf-file>\n\n"
        "       -v              : verbose operation\n"
        "       -r              : force load to RAM\n"
+       "       -k              : enable kernel trace on load (for debug)\n"
        "       -z              : compress code/data/relocs\n"
        "       -d              : compress data/relocs\n"
        "       -a              : use existing symbol references\n"
@@ -1073,9 +1125,9 @@ static void write_zeroes (unsigned long num, FILE *stream)
     /* It'd be nice if we could just use fseek, but that doesn't seem to
        work for stdio output files.  */
     bzero(zeroes, 1024);
-    while (num > sizeof zeroes) {
-      fwrite(zeroes, num, 1, stream);
-      num -= sizeof zeroes;
+    while (num > sizeof(zeroes)) {
+      fwrite(zeroes, sizeof(zeroes), 1, stream);
+      num -= sizeof(zeroes);
     }
     if (num > 0)
       fwrite(zeroes, num, 1, stream);
@@ -1109,6 +1161,8 @@ int main(int argc, char *argv[])
   unsigned long bss_vma = ~0;
   unsigned long text_vma = ~0;
 
+  unsigned long text_offs;
+
   void *text;
   void *data;
   unsigned long *reloc;
@@ -1124,7 +1178,7 @@ int main(int argc, char *argv[])
   
   stack = 4096;
 
-  while ((opt = getopt(argc, argv, "avzdrp:s:o:R:")) != -1) {
+  while ((opt = getopt(argc, argv, "avzdrkp:s:o:R:")) != -1) {
     switch (opt) {
     case 'v':
       verbose++;
@@ -1132,6 +1186,9 @@ int main(int argc, char *argv[])
     case 'r':
       load_to_ram++;
       break;
+    case 'k':
+      ktrace++;
+      break;
     case 'z':
       compress = 1;
       break;
@@ -1257,9 +1314,9 @@ int main(int argc, char *argv[])
   /* Read in all text sections.  */
   for (s = abs_bfd->sections; s != NULL; s = s->next)
     if (s->flags & SEC_CODE) 
-      if (bfd_get_section_contents(abs_bfd, s,
+      if (!bfd_get_section_contents(abs_bfd, s,
                                   text + (s->vma - text_vma), 0,
-                                  s->_raw_size) == false)
+                                  s->_raw_size))
       {
        fprintf(stderr, "read error section %s\n", s->name);
        exit(2);
@@ -1288,9 +1345,9 @@ int main(int argc, char *argv[])
   /* Read in all data sections.  */
   for (s = abs_bfd->sections; s != NULL; s = s->next)
     if (s->flags & SEC_DATA) 
-      if (bfd_get_section_contents(abs_bfd, s,
+      if (!bfd_get_section_contents(abs_bfd, s,
                                   data + (s->vma - data_vma), 0,
-                                  s->_raw_size) == false)
+                                  s->_raw_size))
       {
        fprintf(stderr, "read error section %s\n", s->name);
        exit(2);
@@ -1302,8 +1359,8 @@ int main(int argc, char *argv[])
   if (verbose)
     printf("BSS  -> vma=0x%x len=0x%x\n", bss_vma, bss_len);
 
-  if ((text_vma + text_len + data_len) != bss_vma) {
-    if ((text_vma + text_len + data_len) > bss_vma) {
+  if ((data_vma + data_len) != bss_vma) {
+    if ((data_vma + data_len) > bss_vma) {
       printf("ERROR: text=0x%x + data=0x%x overlaps bss=0x%x ?\n", text_len,
                        data_len, bss_vma);
       exit(1);
@@ -1311,7 +1368,7 @@ int main(int argc, char *argv[])
     if (verbose)
       printf("WARNING: bss=0x%x does not directly follow text=0x%x + data=0x%x(0x%x)\n",
                bss_vma, text_len, data_len, text_len + data_len);
-      data_len = bss_vma - data_vma;
+    data_len = bss_vma - data_vma;
   }
 
   reloc = (unsigned long *)
@@ -1321,18 +1378,21 @@ int main(int argc, char *argv[])
   if (reloc == NULL)
     printf("No relocations in code!\n");
 
+  text_offs = real_address_bits(text_vma);
+
   /* Fill in the binflt_flat header */
   memcpy(hdr.magic,"bFLT",4);
   hdr.rev         = htonl(FLAT_VERSION);
   hdr.entry       = htonl(16 * 4 + bfd_get_start_address(abs_bfd));
-  hdr.data_start  = htonl(16 * 4 + text_len);
-  hdr.data_end    = htonl(16 * 4 + text_len + data_len);
-  hdr.bss_end     = htonl(16 * 4 + text_len + data_len + bss_len);
+  hdr.data_start  = htonl(16 * 4 + text_offs + text_len);
+  hdr.data_end    = htonl(16 * 4 + text_offs + text_len + data_len);
+  hdr.bss_end     = htonl(16 * 4 + text_offs + text_len + data_len + bss_len);
   hdr.stack_size  = htonl(stack); /* FIXME */
-  hdr.reloc_start = htonl(16 * 4 + data_vma + data_len);
+  hdr.reloc_start = htonl(16 * 4 + text_offs + text_len + data_len);
   hdr.reloc_count = htonl(reloc_len);
   hdr.flags       = htonl(0
          | (load_to_ram ? FLAT_FLAG_RAM : 0)
+         | (ktrace ? FLAT_FLAG_KTRACE : 0)
          | (pic_with_got ? FLAT_FLAG_GOTPIC : 0)
          | (compress ? (compress == 2 ? FLAT_FLAG_GZDATA : FLAT_FLAG_GZIP) : 0)
          );
@@ -1386,7 +1446,9 @@ int main(int argc, char *argv[])
        START_COMPRESSOR;
 
   /* Fill in any hole at the beginning of the text segment.  */
-  write_zeroes (text_vma, gf);
+  if (verbose)
+         printf("ZERO before text len=0x%x\n", text_offs);
+  write_zeroes(text_offs, gf);
 
   /* Write the text segment.  */
   fwrite(text, text_len, 1, gf);
@@ -1394,14 +1456,11 @@ int main(int argc, char *argv[])
   if (compress == 2)
        START_COMPRESSOR;
 
-  /* Fill in any hole at the beginning of the data segment.  */
-  write_zeroes (data_vma - (text_vma + text_len), gf);
-
   /* Write the data segment.  */
   fwrite(data, data_len, 1, gf);
 
   if (reloc)
-    fwrite(reloc, reloc_len*4, 1, gf);
+    fwrite(reloc, reloc_len * 4, 1, gf);
 
   fclose(gf);