OSDN Git Service

Build elf2flt with headers from binutils 2.15.94+.
[uclinux-h8/elf2flt.git] / elf2flt.c
1 /*
2  * elf2flt.c: Convert ELF (or any BFD format) to FLAT binary format
3  *
4  * (c) 1999-2002, Greg Ungerer <gerg@snapgear.com>
5  * Created elf2flt from coff2flt (see copyrights below). Added all the
6  * ELF format file handling. Extended relocation support for all of
7  * text and data.
8  *
9  * (c) 2003, H8 support, ktrace <davidm@snapgear.com>
10  * (c) 2001-2003, arm/arm-pic/arm-big-endian support <davidm@snapgear.com>
11  * (c) 2001, v850 changes, Mile Bader <miles@lsi.nec.co.jp>
12  * (c) 2003, SuperH support, Paul Mundt <lethal@linux-sh.org>
13  * (c) 2001, zflat support <davidm@snapgear.com>
14  * (c) 2001, Changes for GOT entries Paul Dale <pauli@snapgear.com> and
15  *           David McCullough <davidm@snapgear.com>
16  *
17  * Now supports PIC with GOT tables.  This works by taking a '.elf' file
18  * and a fully linked elf executable (at address 0) and produces a flat
19  * file that can be loaded with some fixups.  It still supports the old
20  * style fully relocatable elf format files.
21  *
22  * Originally obj-res.c
23  *
24  * (c) 1998, Kenneth Albanowski <kjahds@kjahds.com>
25  * (c) 1998, D. Jeff Dionne
26  * (c) 1998, The Silver Hammer Group Ltd.
27  * (c) 1996, 1997 Dionne & Associates <jeff@ryeham.ee.ryerson.ca>
28  *
29  * This is Free Software, under the GNU Public Licence v2 or greater.
30  *
31  * Relocation added March 1997, Kresten Krab Thorup 
32  * krab@california.daimi.aau.dk
33  */
34  
35 #include <stdio.h>    /* Userland pieces of the ANSI C standard I/O package  */
36 #include <stdlib.h>   /* Userland prototypes of the ANSI C std lib functions */
37 #include <stdarg.h>   /* Allows va_list to exist in the these namespaces     */
38 #include <string.h>   /* Userland prototypes of the string handling funcs    */
39 #include <strings.h>
40 #include <unistd.h>   /* Userland prototypes of the Unix std system calls    */
41 #include <fcntl.h>    /* Flag value for file handling functions              */
42 #include <time.h>
43 #ifndef WIN32
44 #include <netinet/in.h> /* Consts and structs defined by the internet system */
45 #else
46 #include <winsock2.h>
47 #endif
48
49 /* from $(INSTALLDIR)/include       */
50 #include <bfd.h>      /* Main header file for the BFD library                */
51
52 #if defined(TARGET_h8300)
53 #include <elf/h8.h>      /* TARGET_* ELF support for the BFD library            */
54 #elif defined(TARGET_microblaze)
55 #include <elf/microblaze.h>     /* TARGET_* ELF support for the BFD library */
56 #elif defined(__CYGWIN__)
57 #include "cygwin-elf.h" /* Cygwin uses a local copy */
58 #else
59 #include <elf.h>      /* TARGET_* ELF support for the BFD library            */
60 #endif
61
62 /* from uClinux-x.x.x/include/linux */
63 #include "flat.h"     /* Binary flat header description                      */
64
65 #ifdef TARGET_e1
66 #include <e1.h>
67 #endif
68
69 #ifdef TARGET_v850e
70 #define TARGET_v850
71 #endif
72
73 #if defined(TARGET_m68k)
74 #define ARCH    "m68k/coldfire"
75 #elif defined(TARGET_arm)
76 #define ARCH    "arm"
77 #elif defined(TARGET_sparc)
78 #define ARCH    "sparc"
79 #elif defined(TARGET_v850)
80 #define ARCH    "v850"
81 #elif defined(TARGET_sh)
82 #define ARCH    "sh"
83 #elif defined(TARGET_h8300)
84 #define ARCH    "h8300"
85 #elif defined(TARGET_microblaze)
86 #define ARCH    "microblaze"
87 #elif defined(TARGET_e1)
88 #define ARCH    "e1-coff"
89 #else
90 #error "Don't know how to support your CPU architecture??"
91 #endif
92
93 #if defined(TARGET_m68k) || defined(TARGET_h8300)
94 /*
95  * Define a maximum number of bytes allowed in the offset table.
96  * We'll fail if the table is larger than this.
97  *
98  * This limit may be different for platforms other than m68k, but
99  * 8000 entries is a lot,  trust me :-) (davidm)
100  */
101 #define GOT_LIMIT 32767
102 /*
103  * we have to mask out the shared library id here and there,  this gives
104  * us the real address bits when needed
105  */
106 #define real_address_bits(x)    (pic_with_got ? ((x) & 0xffffff) : (x))
107 #else
108 #define real_address_bits(x)    (x)
109 #endif
110
111 #ifndef O_BINARY
112 #define O_BINARY 0
113 #endif
114
115
116 int verbose = 0;      /* extra output when running */
117 int pic_with_got = 0; /* do elf/got processing with PIC code */
118 int load_to_ram = 0;  /* instruct loader to allocate everything into RAM */
119 int ktrace = 0;       /* instruct loader output kernel trace on load */
120 int compress = 0;     /* 1 = compress everything, 2 = compress data only */
121 int use_resolved = 0; /* If true, get the value of symbol references from */
122                       /* the program contents, not from the relocation table. */
123                       /* In this case, the input ELF file must be already */
124                       /* fully resolved (using the `-q' flag with recent */
125                       /* versions of GNU ld will give you a fully resolved */
126                       /* output file with relocation entries).  */
127
128 const char *progname, *filename;
129 int lineno;
130
131 int nerrors = 0;
132 int nwarnings = 0;
133
134 static char where[200];
135
136 enum {
137   /* Use exactly one of these: */
138   E_NOFILE = 0,         /* "progname: " */
139   E_FILE = 1,           /* "filename: " */
140   E_FILELINE = 2,       /* "filename:lineno: " */
141   E_FILEWHERE = 3,      /* "filename:%s: " -- set %s with ewhere() */
142           
143   /* Add in any of these with |': */
144   E_WARNING = 0x10,
145   E_PERROR = 0x20
146 };
147                   
148 void ewhere (const char *format, ...);
149 void einfo (int type, const char *format, ...);
150                   
151
152 void
153 ewhere (const char *format, ...) {
154   va_list args;
155   va_start (args, format);
156   vsprintf (where, format, args);
157   va_end (args);
158 }
159
160
161 void
162 einfo (int type, const char *format, ...) {
163   va_list args;
164
165   switch (type & 0x0f) {
166   case E_NOFILE:
167     fprintf (stderr, "%s: ", progname);
168     break;
169   case E_FILE:
170     fprintf (stderr, "%s: ", filename);
171     break;
172   case E_FILELINE:
173     ewhere ("%d", lineno);
174     /* fall-through */
175   case E_FILEWHERE:
176     fprintf (stderr, "%s:%s: ", filename, where);
177     break;
178   }
179
180   if (type & E_WARNING) {
181     fprintf (stderr, "warning: ");
182     nwarnings++;
183   } else {
184     nerrors++;
185   }
186
187   va_start (args, format);
188   vfprintf (stderr, format, args);
189   va_end (args);
190
191   if (type & E_PERROR)
192     perror ("");
193   else
194     fprintf (stderr, "\n");
195 }
196
197
198 asymbol**
199 get_symbols (bfd *abfd, long *num)
200 {
201   long storage_needed;
202   asymbol **symbol_table;
203   long number_of_symbols;
204   
205   storage_needed = bfd_get_symtab_upper_bound (abfd);
206           
207   if (storage_needed < 0)
208     abort ();
209       
210   if (storage_needed == 0)
211     return NULL;
212
213   symbol_table = (asymbol **) malloc (storage_needed);
214
215   number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
216   
217   if (number_of_symbols < 0) 
218     abort ();
219
220   *num = number_of_symbols;
221   return symbol_table;
222 }
223
224
225
226 int
227 dump_symbols(asymbol **symbol_table, long number_of_symbols)
228 {
229   long i;
230   printf("SYMBOL TABLE:\n");
231   for (i=0; i<number_of_symbols; i++) {
232         printf("  NAME=%s  VALUE=0x%x\n", symbol_table[i]->name,
233                 symbol_table[i]->value);
234   }
235   printf("\n");
236   return(0);
237 }  
238
239
240
241 long
242 get_symbol_offset(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols)
243 {
244   long i;
245   for (i=0; i<number_of_symbols; i++) {
246     if (symbol_table[i]->section == sec) {
247       if (!strcmp(symbol_table[i]->name, name)) {
248         return symbol_table[i]->value;
249       }
250     }
251   }
252   return -1;
253 }  
254
255
256
257 long
258 add_com_to_bss(asymbol **symbol_table, long number_of_symbols, long bss_len)
259 {
260   long i, comsize;
261   long offset;
262
263   comsize = 0;
264   for (i=0; i<number_of_symbols; i++) {
265     if (strcmp("*COM*", symbol_table[i]->section->name) == 0) {
266       offset = bss_len + comsize;
267       comsize += symbol_table[i]->value;
268       symbol_table[i]->value = offset;
269     }
270   }
271   return comsize;
272 }  
273
274
275
276 unsigned long *
277 output_relocs (
278   bfd *abs_bfd,
279   asymbol **symbols,
280   int number_of_symbols,
281   unsigned long *n_relocs,
282   unsigned char *text, int text_len, unsigned long text_vma,
283   unsigned char *data, int data_len, unsigned long data_vma,
284   bfd *rel_bfd)
285 {
286   unsigned long         *flat_relocs;
287   asection              *a, *sym_section, *r;
288   arelent               **relpp, **p, *q;
289   const char            *sym_name, *section_name;
290   unsigned char         *sectionp;
291   unsigned long         pflags;
292   char                  addstr[16];
293   long                  sym_addr, sym_vma, section_vma;
294   int                   relsize, relcount;
295   int                   flat_reloc_count;
296   int                   sym_reloc_size, rc;
297   int                   got_size = 0;
298   int                   bad_relocs = 0;
299   asymbol               **symb;
300   long                  nsymb;
301   
302 #if 0
303   printf("%s(%d): output_relocs(abs_bfd=%d,synbols=0x%x,number_of_symbols=%d"
304         "n_relocs=0x%x,text=0x%x,text_len=%d,data=0x%x,data_len=%d)\n",
305         __FILE__, __LINE__, abs_bfd, symbols, number_of_symbols, n_relocs,
306         text, text_len, data, data_len);
307 #endif
308
309 #if 0
310 dump_symbols(symbols, number_of_symbols);
311 #endif
312
313   *n_relocs = 0;
314   flat_relocs = NULL;
315   flat_reloc_count = 0;
316   rc = 0;
317   pflags = 0;
318
319   /* Determine how big our offset table is in bytes.
320    * This isn't too difficult as we've terminated the table with -1.
321    * Also note that both the relocatable and absolute versions have this
322    * terminator even though the relocatable one doesn't have the GOT!
323    */
324   if (pic_with_got) {
325     unsigned long *lp = (unsigned long *)data;
326     /* Should call ntohl(*lp) here but is isn't going to matter */
327     while (*lp != 0xffffffff) lp++;
328     got_size = ((unsigned char *)lp) - data;
329     if (verbose)
330             printf("GOT table contains %d entries (%d bytes)\n",
331                             got_size/sizeof(unsigned long), got_size);
332 #ifdef TARGET_m68k
333     if (got_size > GOT_LIMIT) {
334             fprintf(stderr, "GOT too large: %d bytes (limit = %d bytes)\n",
335                             got_size, GOT_LIMIT);
336             exit(1);
337     }
338 #endif
339   }
340
341   for (a = abs_bfd->sections; (a != (asection *) NULL); a = a->next) {
342         section_vma = bfd_section_vma(abs_bfd, a);
343
344         if (verbose)
345                 printf("SECTION: %s [0x%x]: flags=0x%x vma=0x%x\n", a->name, a,
346                         a->flags, section_vma);
347
348 //      if (bfd_is_abs_section(a))
349 //              continue;
350         if (bfd_is_und_section(a))
351                 continue;
352         if (bfd_is_com_section(a))
353                 continue;
354 //      if ((a->flags & SEC_RELOC) == 0)
355 //              continue;
356
357         /*
358          *      Only relocate things in the data sections if we are PIC/GOT.
359          *      otherwise do text as well
360          */
361         if (!pic_with_got && (a->flags & SEC_CODE))
362                 sectionp = text + (a->vma - text_vma);
363         else if (a->flags & SEC_DATA)
364                 sectionp = data + (a->vma - data_vma);
365         else
366                 continue;
367
368         /* Now search for the equivalent section in the relocation binary
369          * and use that relocation information to build reloc entries
370          * for this one.
371          */
372         for (r=rel_bfd->sections; r != NULL; r=r->next)
373                 if (strcmp(a->name, r->name) == 0)
374                         break;
375         if (r == NULL)
376           continue;
377         if (verbose)
378           printf(" RELOCS: %s [0x%x]: flags=0x%x vma=0x%x\n", r->name, r,
379                         r->flags, bfd_section_vma(abs_bfd, r));
380         if ((r->flags & SEC_RELOC) == 0)
381           continue;
382         relsize = bfd_get_reloc_upper_bound(rel_bfd, r);
383         if (relsize <= 0) {
384                 if (verbose)
385                         printf("%s(%d): no relocation entries section=0x%x\n",
386                                 __FILE__, __LINE__, r->name);
387                 continue;
388         }
389
390         symb = get_symbols(rel_bfd, &nsymb);
391         relpp = (arelent **) xmalloc(relsize);
392         relcount = bfd_canonicalize_reloc(rel_bfd, r, relpp, symb);
393         if (relcount <= 0) {
394                 if (verbose)
395                         printf("%s(%d): no relocation entries section=%s\n",
396                         __FILE__, __LINE__, r->name);
397                 continue;
398         } else {
399                 for (p = relpp; (relcount && (*p != NULL)); p++, relcount--) {
400                         unsigned char *r_mem;
401                         int relocation_needed = 0;
402
403 #ifdef TARGET_microblaze
404                         /* The MICROBLAZE_XX_NONE relocs can be skipped.
405                            They represent PC relative branches that the
406                            linker has already resolved */
407                                 
408                         switch ((*p)->howto->type) 
409                         {
410                         case R_MICROBLAZE_NONE:
411                         case R_MICROBLAZE_64_NONE:
412                                 continue;
413                         }
414 #endif /* TARGET_microblaze */
415                            
416 #ifdef TARGET_v850
417                         /* Skip this relocation entirely if possible (we
418                            do this early, before doing any other
419                            processing on it).  */
420                         switch ((*p)->howto->type) {
421 #ifdef R_V850_9_PCREL
422                         case R_V850_9_PCREL:
423 #endif
424 #ifdef R_V850_22_PCREL
425                         case R_V850_22_PCREL:
426 #endif
427 #ifdef R_V850_SDA_16_16_OFFSET
428                         case R_V850_SDA_16_16_OFFSET:
429 #endif
430 #ifdef R_V850_SDA_15_16_OFFSET
431                         case R_V850_SDA_15_16_OFFSET:
432 #endif
433 #ifdef R_V850_ZDA_15_16_OFFSET
434                         case R_V850_ZDA_15_16_OFFSET:
435 #endif
436 #ifdef R_V850_TDA_6_8_OFFSET
437                         case R_V850_TDA_6_8_OFFSET:
438 #endif
439 #ifdef R_V850_TDA_7_8_OFFSET
440                         case R_V850_TDA_7_8_OFFSET:
441 #endif
442 #ifdef R_V850_TDA_7_7_OFFSET
443                         case R_V850_TDA_7_7_OFFSET:
444 #endif
445 #ifdef R_V850_TDA_16_16_OFFSET
446                         case R_V850_TDA_16_16_OFFSET:
447 #endif
448 #ifdef R_V850_TDA_4_5_OFFSET
449                         case R_V850_TDA_4_5_OFFSET:
450 #endif
451 #ifdef R_V850_TDA_4_4_OFFSET
452                         case R_V850_TDA_4_4_OFFSET:
453 #endif
454 #ifdef R_V850_SDA_16_16_SPLIT_OFFSET
455                         case R_V850_SDA_16_16_SPLIT_OFFSET:
456 #endif
457 #ifdef R_V850_CALLT_6_7_OFFSET
458                         case R_V850_CALLT_6_7_OFFSET:
459 #endif
460 #ifdef R_V850_CALLT_16_16_OFFSET
461                         case R_V850_CALLT_16_16_OFFSET:
462 #endif
463                                 /* These are relative relocations, which
464                                    have already been fixed up by the
465                                    linker at this point, so just ignore
466                                    them.  */ 
467                                 continue;
468                         }
469 #endif /* USE_V850_RELOCS */
470
471                         q = *p;
472                         if (q->sym_ptr_ptr && *q->sym_ptr_ptr) {
473                                 sym_name = (*(q->sym_ptr_ptr))->name;
474                                 sym_section = (*(q->sym_ptr_ptr))->section;
475                                 section_name=(*(q->sym_ptr_ptr))->section->name;
476                         } else {
477                                 printf("ERROR: undefined relocation entry\n");
478                                 rc = -1;
479                                 continue;
480                         }
481                         /* Adjust the address to account for the GOT table which wasn't
482                          * present in the relative file link.
483                          */
484                         if (pic_with_got)
485                           q->address += got_size;
486                                         
487                         /* A pointer to what's being relocated, used often
488                            below.  */
489                         r_mem = sectionp + q->address;
490
491                         /*
492                          *      Fixup offset in the actual section.
493                          */
494                         addstr[0] = 0;
495 #ifndef TARGET_e1
496                         if ((sym_addr = get_symbol_offset((char *) sym_name,
497                             sym_section, symbols, number_of_symbols)) == -1) {
498                                 sym_addr = 0;
499                         }
500 #else
501                         sym_addr = (*(q->sym_ptr_ptr))->value;
502 #endif                  
503                         if (use_resolved) {
504                                 /* Use the address of the symbol already in
505                                    the program text.  How this is handled may
506                                    still depend on the particular relocation
507                                    though.  */
508                                 switch (q->howto->type) {
509                                         int r2_type;
510 #ifdef TARGET_v850
511                                 case R_V850_HI16_S:
512                                         /* We specially handle adjacent
513                                            HI16_S/ZDA_15_16_OFFSET and
514                                            HI16_S/LO16 pairs that reference the
515                                            same address (these are usually
516                                            movhi/ld and movhi/movea pairs,
517                                            respectively).  */
518                                         if (relcount == 0)
519                                                 r2_type = R_V850_NONE;
520                                         else
521                                                 r2_type = p[1]->howto->type;
522                                         if ((r2_type == R_V850_ZDA_15_16_OFFSET
523                                              || r2_type == R_V850_LO16)
524                                             && (p[0]->sym_ptr_ptr
525                                                 == p[1]->sym_ptr_ptr)
526                                             && (p[0]->addend == p[1]->addend))
527                                         {
528                                                 relocation_needed = 1;
529
530                                                 switch (r2_type) {
531                                                 case R_V850_ZDA_15_16_OFFSET:
532                                                         pflags = 0x10000000;
533                                                         break;
534                                                 case R_V850_LO16:
535                                                         pflags = 0x20000000;
536                                                         break;
537                                                 }
538
539                                                 /* We don't really need the
540                                                    actual value -- the bits
541                                                    produced by the linker are
542                                                    what we want in the final
543                                                    flat file -- but get it
544                                                    anyway if useful for
545                                                    debugging.  */
546                                                 if (verbose) {
547                                                         unsigned char *r2_mem =
548                                                                 sectionp
549                                                                 + p[1]->address;
550                                                         /* little-endian */
551                                                         int hi = r_mem[0]
552                                                                 + (r_mem[1] << 8);
553                                                         int lo = r2_mem[0]
554                                                                 + (r2_mem[1] << 8);
555                                                         /* Sign extend LO.  */
556                                                         lo = (lo ^ 0x8000)
557                                                                 - 0x8000;
558
559                                                         /* Maybe ignore the LSB
560                                                            of LO, which is
561                                                            actually part of the
562                                                            instruction.  */
563                                                         if (r2_type != R_V850_LO16)
564                                                                 lo &= ~1;
565
566                                                         sym_addr =
567                                                                 (hi << 16)
568                                                                 + lo;
569                                                 }
570                                         } else
571                                                 goto bad_v850_reloc_err;
572                                         break;
573
574                                 case R_V850_LO16:
575                                         /* See if this is actually the
576                                            2nd half of a pair.  */
577                                         if (p > relpp
578                                             && (p[-1]->howto->type
579                                                 == R_V850_HI16_S)
580                                             && (p[-1]->sym_ptr_ptr
581                                                 == p[0]->sym_ptr_ptr)
582                                             && (p[-1]->addend == p[0]->addend))
583                                                 break; /* not an error */
584                                         else
585                                                 goto bad_v850_reloc_err;
586
587                                 case R_V850_HI16:
588                                 bad_v850_reloc_err:
589                                         printf("ERROR: reloc type %s unsupported in this context\n",
590                                                q->howto->name);
591                                         bad_relocs++;
592                                         break;
593 #endif /* TARGET_V850 */
594
595                                 default:
596                                         /* The default is to assume that the
597                                            relocation is relative and has
598                                            already been fixed up by the
599                                            linker (perhaps we ought to make
600                                            give an error by default, and
601                                            require `safe' relocations to be
602                                            enumberated explicitly?).  */
603                                         if (bfd_big_endian (abs_bfd))
604                                                 sym_addr =
605                                                         (r_mem[0] << 24)
606                                                         + (r_mem[1] << 16)
607                                                         + (r_mem[2] << 8) 
608                                                         + r_mem[3];
609                                         else
610                                                 sym_addr =
611                                                         r_mem[0]
612                                                         + (r_mem[1] << 8)
613                                                         + (r_mem[2] << 16)
614                                                         + (r_mem[3] << 24);
615                                         relocation_needed = 1;
616                                 }
617                         } else {
618                                 /* Calculate the sym address ourselves.  */
619                                 sym_reloc_size = bfd_get_reloc_size(q->howto);
620
621 #if !defined(TARGET_h8300) && !defined(TARGET_e1)
622                                 if (sym_reloc_size != 4) {
623                                         printf("ERROR: bad reloc type %d size=%d for symbol=%s\n",
624                                                         (*p)->howto->type, sym_reloc_size, sym_name);
625                                         bad_relocs++;
626                                         rc = -1;
627                                         continue;
628                                 }
629 #endif
630
631                                 switch ((*p)->howto->type) {
632
633 #if defined(TARGET_m68k)
634                                 case R_68K_32:
635                                         relocation_needed = 1;
636                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
637                                         sym_addr += sym_vma + q->addend;
638                                         break;
639                                 case R_68K_PC32:
640                                         sym_vma = 0;
641                                         sym_addr += sym_vma + q->addend;
642                                         sym_addr -= q->address;
643                                         break;
644 #endif
645
646 #if defined(TARGET_arm)
647                                 case R_ARM_ABS32:
648                                         relocation_needed = 1;
649                                         if (verbose)
650                                                 fprintf(stderr,
651                                                         "%s vma=0x%x, value=0x%x, address=0x%x "
652                                                         "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
653                                                         "ABS32",
654                                                         sym_vma, (*(q->sym_ptr_ptr))->value,
655                                                         q->address, sym_addr,
656                                                         (*p)->howto->rightshift,
657                                                         *(unsigned long *)r_mem);
658                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
659                                         sym_addr += sym_vma + q->addend;
660                                         break;
661                                 case R_ARM_GOT32:
662                                 case R_ARM_GOTPC:
663                                         /* Should be fine as is */
664                                         break;
665                                 case R_ARM_PLT32:
666                                         if (verbose)
667                                                 fprintf(stderr,
668                                                         "%s vma=0x%x, value=0x%x, address=0x%x "
669                                                         "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
670                                                         "PLT32",
671                                                         sym_vma, (*(q->sym_ptr_ptr))->value,
672                                                         q->address, sym_addr,
673                                                         (*p)->howto->rightshift,
674                                                         *(unsigned long *)r_mem);
675                                 case R_ARM_PC24:
676                                         sym_vma = 0;
677                                         sym_addr = (sym_addr-q->address)>>(*p)->howto->rightshift;
678                                         break;
679 #endif
680
681 #ifdef TARGET_v850
682                                 case R_V850_32:
683                                         relocation_needed = 1;
684                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
685                                         sym_addr += sym_vma + q->addend;
686                                         break;
687 #if defined(R_V850_ZDA_16_16_OFFSET) || defined(R_V850_ZDA_16_16_SPLIT_OFFSET)
688 #ifdef R_V850_ZDA_16_16_OFFSET
689                                 case R_V850_ZDA_16_16_OFFSET:
690 #endif
691 #ifdef R_V850_ZDA_16_16_SPLIT_OFFSET
692                                 case R_V850_ZDA_16_16_SPLIT_OFFSET:
693 #endif
694                                         /* Can't support zero-relocations.  */
695                                         printf ("ERROR: %s+0x%x: zero relocations not supported\n",
696                                                         sym_name, q->addend);
697                                         continue;
698 #endif /* R_V850_ZDA_16_16_OFFSET || R_V850_ZDA_16_16_SPLIT_OFFSET */
699 #endif /* TARGET_v850 */
700
701 #ifdef TARGET_h8300
702                                 case R_H8_DIR24R8:
703                                         if (sym_reloc_size != 4) {
704                                                 printf("R_H8_DIR24R8 size %d\n", sym_reloc_size);
705                                                 bad_relocs++;
706                                                 continue;
707                                         }
708                                         relocation_needed = 1;
709                                         sym_addr = (*(q->sym_ptr_ptr))->value;
710                                         q->address -= 1;
711                                         r_mem -= 1; /* tracks q->address */
712                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
713                                         sym_addr += sym_vma + q->addend;
714                                         sym_addr |= (*(unsigned char *)r_mem<<24);
715                                         break;
716                                 case R_H8_DIR24A8:
717                                         if (sym_reloc_size != 4) {
718                                                 printf("R_H8_DIR24A8 size %d\n", sym_reloc_size);
719                                                 bad_relocs++;
720                                                 continue;
721                                         }
722                                         /* Absolute symbol done not relocation */
723                                         relocation_needed = !bfd_is_abs_section(sym_section);
724                                         sym_addr = (*(q->sym_ptr_ptr))->value;
725                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
726                                         sym_addr += sym_vma + q->addend;
727                                         break;
728                                 case R_H8_DIR32:
729                                 case R_H8_DIR32A16: /* currently 32,  could be made 16 */
730                                         if (sym_reloc_size != 4) {
731                                                 printf("R_H8_DIR32 size %d\n", sym_reloc_size);
732                                                 bad_relocs++;
733                                                 continue;
734                                         }
735                                         relocation_needed = 1;
736                                         sym_addr = (*(q->sym_ptr_ptr))->value;
737                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
738                                         sym_addr += sym_vma + q->addend;
739                                         break;
740                                 case R_H8_PCREL16:
741                                         sym_vma = 0;
742                                         sym_addr = (*(q->sym_ptr_ptr))->value;
743                                         sym_addr += sym_vma + q->addend;
744                                         sym_addr -= (q->address + 2);
745                                         if (bfd_big_endian(abs_bfd))
746                                         *(unsigned short *)r_mem =
747                                                 bfd_big_endian(abs_bfd) ? htons(sym_addr) : sym_addr;
748                                         continue;
749                                 case R_H8_PCREL8:
750                                         sym_vma = 0;
751                                         sym_addr = (*(q->sym_ptr_ptr))->value;
752                                         sym_addr += sym_vma + q->addend;
753                                         sym_addr -= (q->address + 1);
754                                         *(unsigned char *)r_mem = sym_addr;
755                                         continue;
756 #endif
757
758 #ifdef TARGET_microblaze
759                                 case R_MICROBLAZE_64:
760                 /* The symbol is split over two consecutive instructions.  
761                    Flag this to the flat loader by setting the high bit of 
762                    the relocation symbol. */
763                                 {
764                                         unsigned char *p = r_mem;
765                                         unsigned long offset;
766                                         pflags=0x80000000;
767
768                                         /* work out the relocation */
769                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
770                                         /* grab any offset from the text */
771                                         offset = (p[2]<<24) + (p[3] << 16) + (p[6] << 8) + (p[7]);
772                                         /* Update the address */
773                                         sym_addr += offset + sym_vma + q->addend;
774                                         /* Write relocated pointer back */
775                                         p[2] = (sym_addr >> 24) & 0xff;
776                                         p[3] = (sym_addr >> 16) & 0xff;
777                                         p[6] = (sym_addr >>  8) & 0xff;
778                                         p[7] =  sym_addr        & 0xff;
779
780                                         /* create a new reloc entry */
781                                         flat_relocs = realloc(flat_relocs,
782                                                 (flat_reloc_count + 1) * sizeof(unsigned long));
783                                         flat_relocs[flat_reloc_count] = pflags | (section_vma + q->address);
784                                         flat_reloc_count++;
785                                         relocation_needed = 0;
786                                         pflags = 0;
787                         sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
788                                          bfd_section_vma(abs_bfd, sym_section));
789                         if (verbose)
790                                 printf("  RELOC[%d]: offset=0x%x symbol=%s%s "
791                                         "section=%s size=%d "
792                                         "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
793                                         q->address, sym_name, addstr,
794                                         section_name, sym_reloc_size,
795                                         sym_addr, section_vma + q->address);
796                         if (verbose)
797                                 printf("reloc[%d] = 0x%x\n", flat_reloc_count,
798                                          section_vma + q->address);
799
800                                         continue;
801                                 }
802                                 case R_MICROBLAZE_32:
803                                 {       
804                                         unsigned char *p = r_mem;
805                                         unsigned long offset;
806
807                                         /* grab any offset from the text */
808                                         offset = (p[0]<<24) + (p[1] << 16) + (p[2] << 8) + (p[3]);
809                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
810                                         /* This is a horrible kludge.  For some
811                                            reason, *sometimes* the offset is in
812                                            both addend and the code.  Detect
813                                            it, and cancel the effect.  Otherwise
814                                            the offset gets added twice - ouch.
815                                            There should be a better test
816                                            for this condition, based on the
817                                            BFD data structures */
818                                         if(offset==q->addend)
819                                                 offset=0;
820
821                                         sym_addr += offset + sym_vma + q->addend;
822                                         relocation_needed = 1;
823                                         break;
824                                 }
825                                 case R_MICROBLAZE_64_PCREL:
826                                         sym_vma = 0;
827                                         //sym_addr = (*(q->sym_ptr_ptr))->value;
828                                         sym_addr += sym_vma + q->addend;
829                                         sym_addr -= (q->address + 4);
830                                         sym_addr = htonl(sym_addr);
831                                         /* insert 16 MSB */
832                                         * ((unsigned short *) (r_mem+2)) |= (sym_addr) & 0xFFFF;
833                                         /* then 16 LSB */
834                                         * ((unsigned short *) (r_mem+6)) |= (sym_addr >> 16) & 0xFFFF;
835                                         /* We've done all the work, so continue
836                                            to next reloc instead of break */
837                                         continue;
838
839 #endif /* TARGET_microblaze */
840                                         
841 #ifdef TARGET_sparc
842                                 case R_SPARC_32:
843                                 case R_SPARC_UA32:
844                                         relocation_needed = 1;
845                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
846                                         sym_addr += sym_vma + q->addend;
847                                         break;
848                                 case R_SPARC_PC22:
849                                         sym_vma = 0;
850                                         sym_addr += sym_vma + q->addend;
851                                         sym_addr -= q->address;
852                                         break;
853                                 case R_SPARC_WDISP30:
854                                         sym_addr = (((*(q->sym_ptr_ptr))->value-
855                                                 q->address) >> 2) & 0x3fffffff;
856                                         sym_addr |= (
857                                                 ntohl(*(unsigned long *)r_mem)
858                                                 & 0xc0000000
859                                                 );
860                                         break;
861                                 case R_SPARC_HI22:
862                                         relocation_needed = 1;
863                                         pflags = 0x80000000;
864                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
865                                         sym_addr += sym_vma + q->addend;
866                                         sym_addr |= (
867                                                 htonl(*(unsigned long *)r_mem)
868                                                 & 0xffc00000
869                                                 );
870                                         break;
871                                 case R_SPARC_LO10:
872                                         relocation_needed = 1;
873                                         pflags = 0x40000000;
874                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
875                                         sym_addr += sym_vma + q->addend;
876                                         sym_addr &= 0x000003ff;
877                                         sym_addr |= (
878                                                 htonl(*(unsigned long *)r_mem)
879                                                 & 0xfffffc00
880                                                 );
881                                         break;
882 #endif /* TARGET_sparc */
883
884 #ifdef TARGET_sh
885                                 case R_SH_DIR32:
886                                         relocation_needed = 1;
887                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
888                                         sym_addr += sym_vma + q->addend;
889                                         break;
890                                 case R_SH_REL32:
891                                         sym_vma = 0;
892                                         sym_addr += sym_vma + q->addend;
893                                         sym_addr -= q->address;
894                                         break;
895 #endif /* TARGET_sh */
896
897 #ifdef TARGET_e1
898 #define  htoe1l(x)              htonl(x)
899                                         
900 #if 0 
901 #define  DEBUG_E1
902 #endif
903
904 #ifdef   DEBUG_E1
905 #define  DBG_E1                 printf
906 #else
907 #define  DBG_E1(x, ...  )
908 #endif
909
910 #define _32BITS_RELOC 0x00000000
911 #define _30BITS_RELOC 0x80000000
912 #define _28BITS_RELOC 0x40000000
913                                         {
914                                 char *p;
915                                 unsigned long   sec_vma, exist_val, S;
916                                 case R_E1_CONST31:
917                                                 relocation_needed = 1;
918                                                 DBG_E1("Handling Reloc <CONST31>\n");
919                                                 sec_vma = bfd_section_vma(abs_bfd, sym_section);
920                                                 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
921                                                                                 sec_vma, sym_addr, q->address);
922                                                 sym_addr = sec_vma + sym_addr;
923                                                 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);        
924                                                 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
925                                                 exist_val = htoe1l(exist_val);
926                                                 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
927                                                 sym_addr += exist_val;
928                                                 pflags = _30BITS_RELOC;
929                                                 break;
930                                 case R_E1_CONST31_PCREL:
931                                                 relocation_needed = 0;
932                                                 DBG_E1("Handling Reloc <CONST31_PCREL>\n");
933                                                 DBG_E1("DONT RELOCATE AT LOADING\n");
934                                                 sec_vma = bfd_section_vma(abs_bfd, sym_section);
935                                                 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
936                                                                                 sec_vma, sym_addr, q->address);
937                                                 sym_addr =  sec_vma + sym_addr;
938                                                 DBG_E1("sym_addr =  sec_vma + sym_addr : [0x%x]\n", sym_addr );
939
940                                                 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
941                                                                                                                                                 section_vma );
942                                                 q->address = q->address + section_vma;
943                                                 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
944
945                                                 if( (sym_addr = (sym_addr - q->address - 6)) < 0 )
946                                                                 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
947                                                 DBG_E1( "sym_addr := sym_addr - q->address  - "
948                                                                 "sizeof(CONST31_PCREL): [0x%x]\n",
949                                                                 sym_addr );
950                                                 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);              
951                                                 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
952                                                 exist_val = htoe1l(exist_val);
953                                                 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
954                                                 sym_addr |= exist_val;
955                                                 DBG_E1("sym_addr |=  exist_val) : [0x%x]\n", sym_addr );
956                                                 break;
957                                 case R_E1_DIS29W_PCREL:
958                                                 relocation_needed = 0;
959                                                 DBG_E1("Handling Reloc <DIS29W_PCREL>\n");
960                                                 DBG_E1("DONT RELOCATE AT LOADING\n");
961                                                 sec_vma = bfd_section_vma(abs_bfd, sym_section);
962                                                 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
963                                                                                 sec_vma, sym_addr, q->address);
964                                                 sym_addr =  sec_vma + sym_addr;
965                                                 DBG_E1("sym_addr =  sec_vma + sym_addr : [0x%x]\n", sym_addr );
966
967                                                 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
968                                                                                                                                                 section_vma );
969                                                 q->address = q->address + section_vma;
970                                                 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
971
972                                                 if( (sym_addr = (sym_addr - q->address - 6)) < 0 )
973                                                                 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
974                                                 DBG_E1( "sym_addr := sym_addr - q->address  - "
975                                                                 "sizeof(CONST31_PCREL): [0x%x]\n",
976                                                                 sym_addr );
977                                                 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
978                                                 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);       
979                                                 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
980                                                 exist_val = htoe1l(exist_val);
981                                                 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
982                                                 sym_addr += exist_val;
983                                                 break;
984                                 case R_E1_DIS29W:
985                                                 DBG_E1("Handling Reloc <DIS29W>\n");
986                                                 goto DIS29_RELOCATION;
987                                 case R_E1_DIS29H:
988                                                 DBG_E1("Handling Reloc <DIS29H>\n");
989                                                 goto DIS29_RELOCATION;
990                                 case R_E1_DIS29B:
991                                                 DBG_E1("Handling Reloc <DIS29B>\n");
992 DIS29_RELOCATION:
993                                                 relocation_needed = 1;
994                                                 sec_vma = bfd_section_vma(abs_bfd, sym_section);
995                                                 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%08x]\n",
996                                                                                 sec_vma, sym_addr);
997                                                 sym_addr =  sec_vma + sym_addr;
998                                                 DBG_E1("sym_addr =  sec_vma + sym_addr : [0x%08x]\n", sym_addr);
999                                                 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);                
1000                                                 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
1001                                                 exist_val = htoe1l(exist_val);
1002                                                 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
1003                                                 sym_addr +=  exist_val;
1004                                                 DBG_E1("sym_addr +=  exist_val : [0x%08x]\n", sym_addr);
1005                                                 pflags = _28BITS_RELOC;
1006                                                 break;
1007                                 case R_E1_IMM32_PCREL:
1008                                                 relocation_needed = 0;
1009                                                 DBG_E1("Handling Reloc <IMM32_PCREL>\n");
1010                                                 DBG_E1("DONT RELOCATE AT LOADING\n");
1011                                                 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1012                                                 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1013                                                                                 sec_vma, sym_addr);
1014                                                 sym_addr =  sec_vma + sym_addr;
1015
1016                                                 DBG_E1("sym_addr =  sec_vma + sym_addr : [0x%x]\n", sym_addr );
1017                                                 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
1018                                                                                                                                                 section_vma );
1019                                                 q->address = q->address + section_vma;
1020                                                 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
1021
1022                                                 if( (sym_addr = (sym_addr - q->address - 6 )) < 0 )
1023                                                                 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
1024                                                 DBG_E1( "sym_addr := sym_addr - q->address  - "
1025                                                                 "sizeof(CONST31_PCREL): [0x%x]\n",
1026                                                                 sym_addr );
1027                                                 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
1028                                                 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);                 
1029                                                 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
1030                                                 exist_val = htoe1l(exist_val);
1031                                                 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
1032                                                 sym_addr += exist_val;
1033                                                 break;
1034                                 case R_E1_IMM32:
1035                                                 relocation_needed = 1;
1036                                                 DBG_E1("Handling Reloc <IMM32>\n");
1037                                                 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1038                                                 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1039                                                                                 sec_vma, sym_addr);
1040                                                 sym_addr =  sec_vma + sym_addr;
1041                                                 DBG_E1("sym_addr =  sec_vma + sym_addr : [0x%x]\n", sym_addr );
1042                                                 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
1043                                                 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);                     
1044                                                 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
1045                                                 exist_val = htoe1l(exist_val);
1046                                                 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
1047                                                 sym_addr += exist_val;
1048                                                 pflags = _32BITS_RELOC;
1049                                                 break;
1050                                 case R_E1_WORD:
1051                                                 relocation_needed = 1;
1052                                                 DBG_E1("Handling Reloc <WORD>\n");
1053                                                 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1054                                                 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1055                                                                                 sec_vma, sym_addr);
1056                                                 sym_addr =  sec_vma + sym_addr;
1057                                                 DBG_E1("sym_addr =  sec_vma + sym_addr : [0x%x]\n", sym_addr );
1058                                                 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address );
1059                                                 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
1060                                                 exist_val = htoe1l(exist_val);
1061                                                 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
1062                                                 sym_addr +=  exist_val;
1063                                                 DBG_E1("sym_addr +=  exist_val : [0x%08x]\n", sym_addr);
1064                                                 pflags = _32BITS_RELOC;
1065                                                 break;
1066                                 }
1067 #undef _32BITS_RELOC
1068 #undef _30BITS_RELOC
1069 #undef _28BITS_RELOC
1070 #endif
1071                                 default:
1072                                         /* missing support for other types of relocs */
1073                                         printf("ERROR: bad reloc type %d\n", (*p)->howto->type);
1074                                         bad_relocs++;
1075                                         continue;
1076                                 }
1077                         }
1078
1079                         sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
1080                                          bfd_section_vma(abs_bfd, sym_section));
1081
1082
1083                         /*
1084                          * for full elf relocation we have to write back the
1085                          * start_code relative value to use.
1086                          */
1087                         if (!pic_with_got) {
1088 #if defined(TARGET_arm)
1089                                 union {
1090                                         unsigned char c[4];
1091                                         unsigned long l;
1092                                 } tmp;
1093                                 long hl;
1094                                 int i0, i1, i2, i3;
1095
1096                                 /*
1097                                  * horrible nasty hack to support different endianess
1098                                  */
1099                                 if (!bfd_big_endian(abs_bfd)) {
1100                                         i0 = 0;
1101                                         i1 = 1;
1102                                         i2 = 2;
1103                                         i3 = 3;
1104                                 } else {
1105                                         i0 = 3;
1106                                         i1 = 2;
1107                                         i2 = 1;
1108                                         i3 = 0;
1109                                 }
1110
1111                                 tmp.l = *(unsigned long *)r_mem;
1112                                 hl = tmp.c[i0] | (tmp.c[i1] << 8) | (tmp.c[i2] << 16);
1113                                 if (((*p)->howto->type != R_ARM_PC24) &&
1114                                     ((*p)->howto->type != R_ARM_PLT32))
1115                                         hl |= (tmp.c[i3] << 24);
1116                                 else if (tmp.c[i2] & 0x80)
1117                                         hl |= 0xff000000; /* sign extend */
1118                                 hl += sym_addr;
1119                                 tmp.c[i0] = hl & 0xff;
1120                                 tmp.c[i1] = (hl >> 8) & 0xff;
1121                                 tmp.c[i2] = (hl >> 16) & 0xff;
1122                                 if (((*p)->howto->type != R_ARM_PC24) &&
1123                                     ((*p)->howto->type != R_ARM_PLT32))
1124                                         tmp.c[i3] = (hl >> 24) & 0xff;
1125                                 if ((*p)->howto->type == R_ARM_ABS32)
1126                                         *(unsigned long *)r_mem = htonl(hl);
1127                                 else
1128                                         *(unsigned long *)r_mem = tmp.l;
1129
1130 #elif defined(TARGET_e1)
1131 #define OPCODE_SIZE 2           /* Add 2 bytes, counting the opcode size*/
1132                                 switch ((*p)->howto->type) {
1133                                 case R_E1_CONST31:
1134                                 case R_E1_CONST31_PCREL:
1135                                 case R_E1_DIS29W_PCREL:
1136                                 case R_E1_DIS29W:
1137                                 case R_E1_DIS29H:
1138                                 case R_E1_DIS29B:
1139                                 case R_E1_IMM32_PCREL:
1140                                 case R_E1_IMM32:
1141                                                 DBG_E1("In addr + 2:[0x%x] <- write [0x%x]\n",
1142                                                                 (sectionp + q->address + 2), sym_addr );
1143                                                 *((unsigned long *) (sectionp + q->address + OPCODE_SIZE)) =
1144                                                 htonl(sym_addr);
1145                                 break;
1146                                 case R_E1_WORD:
1147                                                 DBG_E1("In addr : [0x%x] <- write [0x%x]\n",
1148                                                                 (sectionp + q->address), sym_addr );
1149                                                 *((unsigned long *) (sectionp + q->address )) = htonl(sym_addr);
1150                                 break;
1151                                 default:
1152                                                 printf("ERROR:Unhandled Relocation. Exiting...\n");
1153                                                 exit(0);
1154                                 break;
1155                                 }
1156 #else /* ! TARGET_arm && ! TARGET_e1 */
1157
1158                                 switch (q->howto->type) {
1159 #ifdef TARGET_v850
1160                                 case R_V850_HI16_S:
1161                                 case R_V850_HI16:
1162                                 case R_V850_LO16:
1163                                         /* Do nothing -- for cases we handle,
1164                                            the bits produced by the linker are
1165                                            what we want in the final flat file
1166                                            (and other cases are errors).  Note
1167                                            that unlike most relocated values,
1168                                            it is stored in little-endian order,
1169                                            but this is necessary to avoid
1170                                            trashing the low-bit, and the float
1171                                            loaders knows about it.  */
1172                                         break;
1173 #endif /* TARGET_V850 */
1174                                 default:
1175                                         /* The alignment of the build host
1176                                            might be stricter than that of the
1177                                            target, so be careful.  We store in
1178                                            network byte order. */
1179                                         r_mem[0] = (sym_addr >> 24) & 0xff;
1180                                         r_mem[1] = (sym_addr >> 16) & 0xff;
1181                                         r_mem[2] = (sym_addr >>  8) & 0xff;
1182                                         r_mem[3] =  sym_addr        & 0xff;
1183                                 }
1184 #endif /* !TARGET_arm */
1185                         }
1186
1187                         if (verbose)
1188                                 printf("  RELOC[%d]: offset=0x%x symbol=%s%s "
1189                                         "section=%s size=%d "
1190                                         "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
1191                                         q->address, sym_name, addstr,
1192                                         section_name, sym_reloc_size,
1193                                         sym_addr, section_vma + q->address);
1194
1195                         /*
1196                          *      Create relocation entry (PC relative doesn't need this).
1197                          */
1198                         if (relocation_needed) {
1199                                 flat_relocs = realloc(flat_relocs,
1200                                         (flat_reloc_count + 1) * sizeof(unsigned long));
1201 #ifndef TARGET_e1
1202                                 flat_relocs[flat_reloc_count] = pflags |
1203                                         (section_vma + q->address);
1204
1205                                 if (verbose)
1206                                         printf("reloc[%d] = 0x%x\n", flat_reloc_count,
1207                                                         section_vma + q->address);
1208 #else
1209                                 switch ((*p)->howto->type) {
1210                                 case R_E1_CONST31:
1211                                 case R_E1_CONST31_PCREL:
1212                                 case R_E1_DIS29W_PCREL:
1213                                 case R_E1_DIS29W:
1214                                 case R_E1_DIS29H:
1215                                 case R_E1_DIS29B:
1216                                 case R_E1_IMM32_PCREL:
1217                                 case R_E1_IMM32:
1218                                 flat_relocs[flat_reloc_count] = pflags |
1219                                                 (section_vma + q->address + OPCODE_SIZE);
1220                                 if (verbose)
1221                                                 printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count,
1222                                                                                  flat_relocs[flat_reloc_count] );
1223                                 break;
1224                                 case R_E1_WORD:
1225                                 flat_relocs[flat_reloc_count] = pflags |
1226                                                 (section_vma + q->address);
1227                                 if (verbose)
1228                                                 printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count,
1229                                                                                  flat_relocs[flat_reloc_count] );
1230                                 break;
1231                                 }
1232 #endif
1233                                 flat_reloc_count++;
1234                                 relocation_needed = 0;
1235                                 pflags = 0;
1236                         }
1237
1238 #if 0
1239 printf("%s(%d): symbol name=%s address=0x%x section=%s -> RELOC=0x%x\n",
1240         __FILE__, __LINE__, sym_name, q->address, section_name,
1241         flat_relocs[flat_reloc_count]);
1242 #endif
1243                 }
1244         }
1245   }
1246
1247   if (bad_relocs) {
1248           printf("%d bad relocs\n", bad_relocs);
1249           exit(1);
1250   }
1251
1252   if (rc < 0)
1253         return(0);
1254
1255   *n_relocs = flat_reloc_count;
1256   return flat_relocs;
1257 }
1258
1259
1260
1261 #if 0
1262 /* shared lib symbols stuff */
1263
1264 long
1265 get_symbol(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols)
1266 {
1267   long i;
1268   for (i=0; i<number_of_symbols; i++) {
1269     if (symbol_table[i]->section == sec) {
1270       if (!strcmp(symbol_table[i]->name, name)) {
1271         return symbol_table[i]->value;
1272       }
1273     }
1274   }
1275   return -1;
1276 }  
1277
1278 int
1279 output_offset_table(int fd, char *ename, bfd *abfd, asymbol **symbol_table, long number_of_symbols)
1280 {
1281   long i;
1282   FILE *ef;
1283   char buf[80];
1284   char libname[80];
1285   long etext_addr;
1286   long sym_addr;
1287
1288   int foobar = 0;
1289   int count = 0;
1290   signed short *tab = malloc(32768); /* we don't know how many yet*/
1291
1292   asection *text_section = bfd_get_section_by_name (abfd, ".text");
1293
1294   if (!(ef = fopen(ename, "rb"))) {
1295     fprintf (stderr,"Can't open %s\n",ename);
1296     exit(1);
1297   }
1298
1299   fgets(libname, 80, ef);
1300
1301   if (number_of_symbols < 0) {
1302     fprintf (stderr,"Corrupt symbol table!\n");
1303     exit(1);
1304   }
1305
1306   if ((etext_addr = get_symbol("etext",
1307                                text_section,
1308                                symbol_table,
1309                                number_of_symbols)) == -1) {
1310     fprintf (stderr,"Can't find the symbol etext\n");
1311     exit(1);
1312   }
1313
1314   fgets(buf, 80, ef);
1315   while (!feof(ef)) {
1316     buf[strlen(buf)-1] = 0; /* Arrrgh! linefeeds */
1317
1318     if ((sym_addr = get_symbol(buf,
1319                                text_section,
1320                                symbol_table,
1321                                number_of_symbols)) == -1) {
1322       fprintf (stderr,"Can't find the symbol %s\n",buf);
1323       foobar++;
1324     } else {
1325       tab[++count] = htons(sym_addr - etext_addr);
1326     }
1327     fgets(buf, 80, ef);
1328   }
1329
1330   fclose(ef);
1331
1332   if (foobar) {
1333     fprintf (stderr,"*** %d symbols not found\n",foobar);
1334     exit(10);
1335   }
1336
1337   strcpy((char *)&tab[++count],libname);
1338   tab[0] = htons(count * 2);
1339   write(fd, tab, count * 2 + strlen(libname) + 2);
1340   return 0;
1341 }
1342 #endif
1343
1344
1345 static char * program;
1346
1347 static void usage(void)
1348 {  
1349     fprintf(stderr, "Usage: %s [vrzd] [-p <abs-pic-file>] [-s stack-size] "
1350         "[-o <output-file>] <elf-file>\n\n"
1351         "       -v              : verbose operation\n"
1352         "       -r              : force load to RAM\n"
1353         "       -k              : enable kernel trace on load (for debug)\n"
1354         "       -z              : compress code/data/relocs\n"
1355         "       -d              : compress data/relocs\n"
1356         "       -a              : use existing symbol references\n"
1357         "                         instead of recalculating from\n"
1358         "                         relocation info\n"
1359         "       -R reloc-file   : read relocations from a separate file\n"
1360         "       -p abs-pic-file : GOT/PIC processing with files\n"
1361         "       -s stacksize    : set application stack size\n"
1362         "       -o output-file  : output file name\n\n",
1363         program);
1364         fprintf(stderr, "Compiled for " ARCH " architecture\n\n");
1365     exit(2);
1366 }
1367
1368
1369 /* Write NUM zeroes to STREAM.  */
1370 static void write_zeroes (unsigned long num, FILE *stream)
1371 {
1372   char zeroes[1024];
1373   if (num > 0) {
1374     /* It'd be nice if we could just use fseek, but that doesn't seem to
1375        work for stdio output files.  */
1376     bzero(zeroes, 1024);
1377     while (num > sizeof(zeroes)) {
1378       fwrite(zeroes, sizeof(zeroes), 1, stream);
1379       num -= sizeof(zeroes);
1380     }
1381     if (num > 0)
1382       fwrite(zeroes, num, 1, stream);
1383   }
1384 }
1385
1386
1387 int main(int argc, char *argv[])
1388 {
1389   int fd;
1390   bfd *rel_bfd, *abs_bfd;
1391   asection *s;
1392   char *ofile=NULL, *pfile=NULL, *abs_file = NULL, *rel_file = NULL;
1393   char *fname = NULL;
1394   int opt;
1395   int i;
1396   int stack;
1397   char  cmd[1024];
1398   FILE *gf = NULL;
1399
1400
1401   asymbol **symbol_table;
1402   long number_of_symbols;
1403
1404   unsigned long data_len = 0;
1405   unsigned long bss_len = 0;
1406   unsigned long text_len = 0;
1407   unsigned long reloc_len;
1408
1409   unsigned long data_vma = ~0;
1410   unsigned long bss_vma = ~0;
1411   unsigned long text_vma = ~0;
1412
1413   unsigned long text_offs;
1414
1415   void *text;
1416   void *data;
1417   unsigned long *reloc;
1418   
1419   struct flat_hdr hdr;
1420
1421   int gf_is_pipe = 0;
1422
1423   program = argv[0];
1424   progname = argv[0];
1425
1426   if (argc < 2)
1427         usage();
1428   
1429 #ifndef TARGET_e1
1430   stack = 4096;
1431 #else /* We need plenty of stack for both of them (Aggregate and Register) */
1432   stack = 0x2020;
1433 #endif
1434
1435   while ((opt = getopt(argc, argv, "avzdrkp:s:o:R:")) != -1) {
1436     switch (opt) {
1437     case 'v':
1438       verbose++;
1439       break;
1440     case 'r':
1441       load_to_ram++;
1442       break;
1443     case 'k':
1444       ktrace++;
1445       break;
1446     case 'z':
1447       compress = 1;
1448       break;
1449     case 'd':
1450       compress = 2;
1451       break;
1452     case 'p':
1453       pfile = optarg;
1454       break;
1455     case 'o':
1456       ofile = optarg;
1457       break;
1458     case 'a':
1459       use_resolved = 1;
1460       break;
1461     case 's':
1462       stack = atoi(optarg);
1463       break;
1464     case 'R':
1465       rel_file = optarg;
1466       break;
1467     default:
1468       fprintf(stderr, "%s Unknown option\n", argv[0]);
1469       usage();
1470       break;
1471     }
1472   }
1473   
1474   /*
1475    * if neither the -r or -p options was given,  default to
1476    * a RAM load as that is the only option that makes sense.
1477    */
1478   if (!load_to_ram && !pfile)
1479     load_to_ram = 1;
1480
1481   filename = fname = argv[argc-1];
1482
1483   if (pfile) {
1484     pic_with_got = 1;
1485     abs_file = pfile;
1486   } else
1487     abs_file = fname;
1488
1489   if (! rel_file)
1490     rel_file = fname;
1491
1492   if (!(rel_bfd = bfd_openr(rel_file, 0))) {
1493     fprintf(stderr, "Can't open %s\n", rel_file);
1494     exit(1);
1495   }
1496
1497   if (bfd_check_format (rel_bfd, bfd_object) == 0) {
1498     fprintf(stderr, "File is not an object file\n");
1499     exit(2);
1500   }
1501
1502   if (abs_file == rel_file)
1503     abs_bfd = rel_bfd; /* one file does all */
1504   else {
1505     if (!(abs_bfd = bfd_openr(abs_file, 0))) {
1506       fprintf(stderr, "Can't open %s\n", abs_file);
1507       exit(1);
1508     }
1509
1510     if (bfd_check_format (abs_bfd, bfd_object) == 0) {
1511       fprintf(stderr, "File is not an object file\n");
1512       exit(2);
1513     }
1514   }
1515
1516   if (! (bfd_get_file_flags(rel_bfd) & HAS_RELOC)) {
1517     fprintf (stderr, "%s: Input file contains no relocation info\n", rel_file);
1518     exit (2);
1519   }
1520
1521   if (use_resolved && !(bfd_get_file_flags(abs_bfd) & EXEC_P)) {
1522     /* `Absolute' file is not absolute, so neither are address
1523        contained therein.  */
1524     fprintf (stderr,
1525              "%s: `-a' option specified with non-fully-resolved input file\n",
1526              bfd_get_filename (abs_bfd));
1527     exit (2);
1528   }
1529
1530   symbol_table = get_symbols(abs_bfd, &number_of_symbols);
1531
1532   /* Group output sections into text, data, and bss, and calc their sizes.  */
1533   for (s = abs_bfd->sections; s != NULL; s = s->next) {
1534     unsigned long *vma, *len;
1535     bfd_size_type sec_size;
1536     bfd_vma sec_vma;
1537
1538     if (s->flags & SEC_CODE) {
1539       vma = &text_vma;
1540       len = &text_len;
1541     } else if (s->flags & SEC_DATA) {
1542       vma = &data_vma;
1543       len = &data_len;
1544     } else if (s->flags & SEC_ALLOC) {
1545       vma = &bss_vma;
1546       len = &bss_len;
1547     } else
1548       continue;
1549
1550     sec_size = bfd_section_size(abs_bfd, s);
1551     sec_vma  = bfd_section_vma(abs_bfd, s);
1552
1553     if (sec_vma < *vma) {
1554       if (*len > 0)
1555         *len += sec_vma - *vma;
1556       else
1557         *len = sec_size;
1558       *vma = sec_vma;
1559     } else if (sec_vma + sec_size > *vma + *len)
1560       *len = sec_vma + sec_size - *vma;
1561   }
1562
1563   if (text_len == 0) {
1564     fprintf (stderr, "%s: no .text section", abs_file);
1565     exit (2);
1566   }
1567
1568   text = malloc(text_len);
1569
1570   if (verbose)
1571     printf("TEXT -> vma=0x%x len=0x%x\n", text_vma, text_len);
1572
1573   /* Read in all text sections.  */
1574   for (s = abs_bfd->sections; s != NULL; s = s->next)
1575     if (s->flags & SEC_CODE) 
1576       if (!bfd_get_section_contents(abs_bfd, s,
1577                                    text + (s->vma - text_vma), 0,
1578                                    bfd_section_size(abs_bfd, s)))
1579       {
1580         fprintf(stderr, "read error section %s\n", s->name);
1581         exit(2);
1582       }
1583
1584   if (data_len == 0) {
1585     fprintf (stderr, "%s: no .data section", abs_file);
1586     exit (2);
1587   }
1588   data = malloc(data_len);
1589
1590   if (verbose)
1591     printf("DATA -> vma=0x%x len=0x%x\n", data_vma, data_len);
1592
1593   if ((text_vma + text_len) != data_vma) {
1594     if ((text_vma + text_len) > data_vma) {
1595       printf("ERROR: text=0x%x overlaps data=0x%x ?\n", text_len, data_vma);
1596       exit(1);
1597     }
1598     if (verbose)
1599       printf("WARNING: data=0x%x does not directly follow text=0x%x\n",
1600                         data_vma, text_len);
1601     text_len = data_vma - text_vma;
1602   }
1603
1604   /* Read in all data sections.  */
1605   for (s = abs_bfd->sections; s != NULL; s = s->next)
1606     if (s->flags & SEC_DATA) 
1607       if (!bfd_get_section_contents(abs_bfd, s,
1608                                    data + (s->vma - data_vma), 0,
1609                                    bfd_section_size(abs_bfd, s)))
1610       {
1611         fprintf(stderr, "read error section %s\n", s->name);
1612         exit(2);
1613       }
1614
1615   /* Put common symbols in bss.  */
1616   bss_len += add_com_to_bss(symbol_table, number_of_symbols, bss_len);
1617
1618   if (verbose)
1619     printf("BSS  -> vma=0x%x len=0x%x\n", bss_vma, bss_len);
1620
1621   if ((data_vma + data_len) != bss_vma) {
1622     if ((data_vma + data_len) > bss_vma) {
1623       printf("ERROR: text=0x%x + data=0x%x overlaps bss=0x%x ?\n", text_len,
1624                         data_len, bss_vma);
1625       exit(1);
1626     }
1627     if (verbose)
1628       printf("WARNING: bss=0x%x does not directly follow text=0x%x + data=0x%x(0x%x)\n",
1629                 bss_vma, text_len, data_len, text_len + data_len);
1630     data_len = bss_vma - data_vma;
1631   }
1632
1633   reloc = (unsigned long *)
1634     output_relocs(abs_bfd, symbol_table, number_of_symbols, &reloc_len,
1635                   text, text_len, text_vma, data, data_len, data_vma, rel_bfd);
1636
1637   if (reloc == NULL)
1638     printf("No relocations in code!\n");
1639
1640   text_offs = real_address_bits(text_vma);
1641
1642   /* Fill in the binflt_flat header */
1643   memcpy(hdr.magic,"bFLT",4);
1644   hdr.rev         = htonl(FLAT_VERSION);
1645   hdr.entry       = htonl(16 * 4 + bfd_get_start_address(abs_bfd));
1646   hdr.data_start  = htonl(16 * 4 + text_offs + text_len);
1647   hdr.data_end    = htonl(16 * 4 + text_offs + text_len + data_len);
1648   hdr.bss_end     = htonl(16 * 4 + text_offs + text_len + data_len + bss_len);
1649   hdr.stack_size  = htonl(stack); /* FIXME */
1650   hdr.reloc_start = htonl(16 * 4 + text_offs + text_len + data_len);
1651   hdr.reloc_count = htonl(reloc_len);
1652   hdr.flags       = htonl(0
1653           | (load_to_ram ? FLAT_FLAG_RAM : 0)
1654           | (ktrace ? FLAT_FLAG_KTRACE : 0)
1655           | (pic_with_got ? FLAT_FLAG_GOTPIC : 0)
1656           | (compress ? (compress == 2 ? FLAT_FLAG_GZDATA : FLAT_FLAG_GZIP) : 0)
1657           );
1658   hdr.build_date = htonl((unsigned long)time(NULL));
1659   bzero(hdr.filler, sizeof(hdr.filler));
1660
1661   for (i=0; i<reloc_len; i++) reloc[i] = htonl(reloc[i]);
1662
1663   if (verbose) {
1664     printf("SIZE: .text=0x%04x, .data=0x%04x, .bss=0x%04x",
1665         text_len, data_len, bss_len);
1666     if (reloc)
1667       printf(", relocs=0x%04x", reloc_len);
1668     printf("\n");
1669   }
1670   
1671   if (!ofile) {
1672     ofile = malloc(strlen(fname) + 5 + 1); /* 5 to add suffix */
1673     strcpy(ofile, fname);
1674     strcat(ofile, ".bflt");
1675   }
1676
1677   if ((fd = open (ofile, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0744)) < 0) {
1678     fprintf (stderr, "Can't open output file %s\n", ofile);
1679     exit(4);
1680   }
1681
1682   write(fd, &hdr, sizeof(hdr));
1683   close(fd);
1684
1685   /*
1686    * get the compression command ready
1687    */
1688   sprintf(cmd, "gzip -f -9 >> %s", ofile);
1689
1690 #define START_COMPRESSOR do { \
1691                 if (gf) \
1692                         if (gf_is_pipe) \
1693                                 pclose(gf); \
1694                         else \
1695                                 fclose(gf); \
1696                 if (!(gf = popen(cmd, "wb"))) { \
1697                         fprintf(stderr, "Can't run cmd %s\n", cmd); \
1698                         exit(4); \
1699                 } \
1700                 gf_is_pipe = 1; \
1701         } while (0)
1702
1703   gf = fopen(ofile, "ab");      /* Add 'b' to support non-posix (ie windows) */
1704   if (!gf) {
1705         fprintf(stderr, "Can't open file %s for writing\n", ofile); \
1706         exit(4);
1707   }
1708
1709   if (compress == 1)
1710         START_COMPRESSOR;
1711
1712   /* Fill in any hole at the beginning of the text segment.  */
1713   if (verbose)
1714           printf("ZERO before text len=0x%x\n", text_offs);
1715   write_zeroes(text_offs, gf);
1716
1717   /* Write the text segment.  */
1718   fwrite(text, text_len, 1, gf);
1719
1720   if (compress == 2)
1721         START_COMPRESSOR;
1722
1723   /* Write the data segment.  */
1724   fwrite(data, data_len, 1, gf);
1725
1726   if (reloc)
1727     fwrite(reloc, reloc_len * 4, 1, gf);
1728
1729   if(gf_is_pipe)
1730     pclose(gf);
1731   else
1732   fclose(gf);
1733
1734   exit(0);
1735 }