OSDN Git Service

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