OSDN Git Service

I hit a random failure in elf2flt (not elf2flt's fault, I was screwing with
[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 = xmalloc (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 && !use_resolved) {
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 = xmalloc(relsize);
496
497         relcount = bfd_canonicalize_reloc(rel_bfd, r, relpp, symb);
498         if (relcount <= 0) {
499                 if (verbose)
500                         printf("%s(%d): no relocation entries section=%s\n",
501                         __FILE__, __LINE__, r->name);
502                 continue;
503         } else {
504                 for (p = relpp; (relcount && (*p != NULL)); p++, relcount--) {
505                         unsigned char *r_mem;
506                         int relocation_needed = 0;
507
508 #ifdef TARGET_microblaze
509                         /* The MICROBLAZE_XX_NONE relocs can be skipped.
510                            They represent PC relative branches that the
511                            linker has already resolved */
512                                 
513                         switch ((*p)->howto->type) 
514                         {
515                         case R_MICROBLAZE_NONE:
516                         case R_MICROBLAZE_64_NONE:
517                                 continue;
518                         }
519 #endif /* TARGET_microblaze */
520
521 #ifdef TARGET_v850
522                         /* Skip this relocation entirely if possible (we
523                            do this early, before doing any other
524                            processing on it).  */
525                         switch ((*p)->howto->type) {
526 #ifdef R_V850_9_PCREL
527                         case R_V850_9_PCREL:
528 #endif
529 #ifdef R_V850_22_PCREL
530                         case R_V850_22_PCREL:
531 #endif
532 #ifdef R_V850_SDA_16_16_OFFSET
533                         case R_V850_SDA_16_16_OFFSET:
534 #endif
535 #ifdef R_V850_SDA_15_16_OFFSET
536                         case R_V850_SDA_15_16_OFFSET:
537 #endif
538 #ifdef R_V850_ZDA_15_16_OFFSET
539                         case R_V850_ZDA_15_16_OFFSET:
540 #endif
541 #ifdef R_V850_TDA_6_8_OFFSET
542                         case R_V850_TDA_6_8_OFFSET:
543 #endif
544 #ifdef R_V850_TDA_7_8_OFFSET
545                         case R_V850_TDA_7_8_OFFSET:
546 #endif
547 #ifdef R_V850_TDA_7_7_OFFSET
548                         case R_V850_TDA_7_7_OFFSET:
549 #endif
550 #ifdef R_V850_TDA_16_16_OFFSET
551                         case R_V850_TDA_16_16_OFFSET:
552 #endif
553 #ifdef R_V850_TDA_4_5_OFFSET
554                         case R_V850_TDA_4_5_OFFSET:
555 #endif
556 #ifdef R_V850_TDA_4_4_OFFSET
557                         case R_V850_TDA_4_4_OFFSET:
558 #endif
559 #ifdef R_V850_SDA_16_16_SPLIT_OFFSET
560                         case R_V850_SDA_16_16_SPLIT_OFFSET:
561 #endif
562 #ifdef R_V850_CALLT_6_7_OFFSET
563                         case R_V850_CALLT_6_7_OFFSET:
564 #endif
565 #ifdef R_V850_CALLT_16_16_OFFSET
566                         case R_V850_CALLT_16_16_OFFSET:
567 #endif
568                                 /* These are relative relocations, which
569                                    have already been fixed up by the
570                                    linker at this point, so just ignore
571                                    them.  */ 
572                                 continue;
573                         }
574 #endif /* USE_V850_RELOCS */
575
576                         q = *p;
577                         if (q->sym_ptr_ptr && *q->sym_ptr_ptr) {
578                                 sym_name = (*(q->sym_ptr_ptr))->name;
579                                 sym_section = (*(q->sym_ptr_ptr))->section;
580                                 section_name=(*(q->sym_ptr_ptr))->section->name;
581                         } else {
582                                 printf("ERROR: undefined relocation entry\n");
583                                 rc = -1;
584                                 continue;
585                         }
586 #ifndef TARGET_bfin
587                         /* Adjust the address to account for the GOT table which wasn't
588                          * present in the relative file link.
589                          */
590                         if (pic_with_got && !use_resolved)
591                           q->address += got_size;
592 #endif
593
594                         /* A pointer to what's being relocated, used often
595                            below.  */
596                         r_mem = sectionp + q->address;
597
598                         /*
599                          *      Fixup offset in the actual section.
600                          */
601                         addstr[0] = 0;
602 #ifndef TARGET_e1
603                         if ((sym_addr = get_symbol_offset((char *) sym_name,
604                             sym_section, symbols, number_of_symbols)) == -1) {
605                                 sym_addr = 0;
606                         }
607 #else
608                         sym_addr = (*(q->sym_ptr_ptr))->value;
609 #endif                  
610                         if (use_resolved) {
611                                 /* Use the address of the symbol already in
612                                    the program text.  How this is handled may
613                                    still depend on the particular relocation
614                                    though.  */
615                                 switch (q->howto->type) {
616                                         int r2_type;
617 #ifdef TARGET_v850
618                                 case R_V850_HI16_S:
619                                         /* We specially handle adjacent
620                                            HI16_S/ZDA_15_16_OFFSET and
621                                            HI16_S/LO16 pairs that reference the
622                                            same address (these are usually
623                                            movhi/ld and movhi/movea pairs,
624                                            respectively).  */
625                                         if (relcount == 0)
626                                                 r2_type = R_V850_NONE;
627                                         else
628                                                 r2_type = p[1]->howto->type;
629                                         if ((r2_type == R_V850_ZDA_15_16_OFFSET
630                                              || r2_type == R_V850_LO16)
631                                             && (p[0]->sym_ptr_ptr
632                                                 == p[1]->sym_ptr_ptr)
633                                             && (p[0]->addend == p[1]->addend))
634                                         {
635                                                 relocation_needed = 1;
636
637                                                 switch (r2_type) {
638                                                 case R_V850_ZDA_15_16_OFFSET:
639                                                         pflags = 0x10000000;
640                                                         break;
641                                                 case R_V850_LO16:
642                                                         pflags = 0x20000000;
643                                                         break;
644                                                 }
645
646                                                 /* We don't really need the
647                                                    actual value -- the bits
648                                                    produced by the linker are
649                                                    what we want in the final
650                                                    flat file -- but get it
651                                                    anyway if useful for
652                                                    debugging.  */
653                                                 if (verbose) {
654                                                         unsigned char *r2_mem =
655                                                                 sectionp
656                                                                 + p[1]->address;
657                                                         /* little-endian */
658                                                         int hi = r_mem[0]
659                                                                 + (r_mem[1] << 8);
660                                                         int lo = r2_mem[0]
661                                                                 + (r2_mem[1] << 8);
662                                                         /* Sign extend LO.  */
663                                                         lo = (lo ^ 0x8000)
664                                                                 - 0x8000;
665
666                                                         /* Maybe ignore the LSB
667                                                            of LO, which is
668                                                            actually part of the
669                                                            instruction.  */
670                                                         if (r2_type != R_V850_LO16)
671                                                                 lo &= ~1;
672
673                                                         sym_addr =
674                                                                 (hi << 16)
675                                                                 + lo;
676                                                 }
677                                         } else
678                                                 goto bad_resolved_reloc;
679                                         break;
680
681                                 case R_V850_LO16:
682                                         /* See if this is actually the
683                                            2nd half of a pair.  */
684                                         if (p > relpp
685                                             && (p[-1]->howto->type
686                                                 == R_V850_HI16_S)
687                                             && (p[-1]->sym_ptr_ptr
688                                                 == p[0]->sym_ptr_ptr)
689                                             && (p[-1]->addend == p[0]->addend))
690                                                 break; /* not an error */
691                                         else
692                                                 goto bad_resolved_reloc;
693
694                                 case R_V850_HI16:
695                                         goto bad_resolved_reloc;
696                                 default:
697                                         goto good_32bit_resolved_reloc;
698 #elif defined(TARGET_arm)
699                                 case R_ARM_ABS32:
700                                         relocation_needed = 1;
701                                         break;
702                                 case R_ARM_REL32:
703                                 case R_ARM_THM_PC11:
704                                 case R_ARM_THM_PC22:
705                                         relocation_needed = 0;
706                                         break;
707                                 default:
708                                         goto bad_resolved_reloc;
709 #elif defined(TARGET_m68k)
710                                 case R_68K_32:
711                                         goto good_32bit_resolved_reloc;
712                                 case R_68K_PC32:
713                                 case R_68K_PC16:
714                                         /* The linker has already resolved
715                                            PC relocs for us.  In PIC links,
716                                            the symbol must be in the data
717                                            segment.  */
718                                 case R_68K_NONE:
719                                         continue;
720                                 default:
721                                         goto bad_resolved_reloc;
722 #else
723                                 default:
724                                         /* The default is to assume that the
725                                            relocation is relative and has
726                                            already been fixed up by the
727                                            linker (perhaps we ought to make
728                                            give an error by default, and
729                                            require `safe' relocations to be
730                                            enumberated explicitly?).  */
731                                         goto good_32bit_resolved_reloc;
732 #endif
733                                 good_32bit_resolved_reloc:
734                                         if (bfd_big_endian (abs_bfd))
735                                                 sym_addr =
736                                                         (r_mem[0] << 24)
737                                                         + (r_mem[1] << 16)
738                                                         + (r_mem[2] << 8) 
739                                                         + r_mem[3];
740                                         else
741                                                 sym_addr =
742                                                         r_mem[0]
743                                                         + (r_mem[1] << 8)
744                                                         + (r_mem[2] << 16)
745                                                         + (r_mem[3] << 24);
746                                         relocation_needed = 1;
747                                         break;
748
749                                 bad_resolved_reloc:
750                                         printf("ERROR: reloc type %s unsupported in this context\n",
751                                                q->howto->name);
752                                         bad_relocs++;
753                                         break;
754                                 }
755                         } else {
756                                 /* Calculate the sym address ourselves.  */
757                                 sym_reloc_size = bfd_get_reloc_size(q->howto);
758
759 #if !defined(TARGET_h8300) && !defined(TARGET_e1) && !defined(TARGET_bfin) && !defined(TARGET_m68k)
760                                 if (sym_reloc_size != 4) {
761                                         printf("ERROR: bad reloc type %d size=%d for symbol=%s\n",
762                                                         (*p)->howto->type, sym_reloc_size, sym_name);
763                                         bad_relocs++;
764                                         rc = -1;
765                                         continue;
766                                 }
767 #endif
768
769                                 switch ((*p)->howto->type) {
770
771 #if defined(TARGET_m68k)
772                                 case R_68K_32:
773                                         relocation_needed = 1;
774                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
775                                         sym_addr += sym_vma + q->addend;
776                                         break;
777                                 case R_68K_PC16:
778                                 case R_68K_PC32:
779                                         sym_vma = 0;
780                                         sym_addr += sym_vma + q->addend;
781                                         sym_addr -= q->address;
782                                         break;
783 #endif
784
785 #if defined(TARGET_arm)
786                                 case R_ARM_ABS32:
787                                         relocation_needed = 1;
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                                                         "ABS32",
793                                                         sym_vma, (*(q->sym_ptr_ptr))->value,
794                                                         q->address, sym_addr,
795                                                         (*p)->howto->rightshift,
796                                                         *(unsigned long *)r_mem);
797                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
798                                         sym_addr += sym_vma + q->addend;
799                                         break;
800                                 case R_ARM_GOT32:
801                                 case R_ARM_GOTPC:
802                                         /* Should be fine as is */
803                                         break;
804                                 case R_ARM_PLT32:
805                                         if (verbose)
806                                                 fprintf(stderr,
807                                                         "%s vma=0x%x, value=0x%x, address=0x%x "
808                                                         "sym_addr=0x%x rs=0x%x, opcode=0x%x\n",
809                                                         "PLT32",
810                                                         sym_vma, (*(q->sym_ptr_ptr))->value,
811                                                         q->address, sym_addr,
812                                                         (*p)->howto->rightshift,
813                                                         *(unsigned long *)r_mem);
814                                 case R_ARM_PC24:
815                                         sym_vma = 0;
816                                         sym_addr = (sym_addr-q->address)>>(*p)->howto->rightshift;
817                                         break;
818 #endif
819
820 #ifdef TARGET_v850
821                                 case R_V850_32:
822                                         relocation_needed = 1;
823                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
824                                         sym_addr += sym_vma + q->addend;
825                                         break;
826 #if defined(R_V850_ZDA_16_16_OFFSET) || defined(R_V850_ZDA_16_16_SPLIT_OFFSET)
827 #ifdef R_V850_ZDA_16_16_OFFSET
828                                 case R_V850_ZDA_16_16_OFFSET:
829 #endif
830 #ifdef R_V850_ZDA_16_16_SPLIT_OFFSET
831                                 case R_V850_ZDA_16_16_SPLIT_OFFSET:
832 #endif
833                                         /* Can't support zero-relocations.  */
834                                         printf ("ERROR: %s+0x%x: zero relocations not supported\n",
835                                                         sym_name, q->addend);
836                                         continue;
837 #endif /* R_V850_ZDA_16_16_OFFSET || R_V850_ZDA_16_16_SPLIT_OFFSET */
838 #endif /* TARGET_v850 */
839
840 #ifdef TARGET_h8300
841                                 case R_H8_DIR24R8:
842                                         if (sym_reloc_size != 4) {
843                                                 printf("R_H8_DIR24R8 size %d\n", sym_reloc_size);
844                                                 bad_relocs++;
845                                                 continue;
846                                         }
847                                         relocation_needed = 1;
848                                         sym_addr = (*(q->sym_ptr_ptr))->value;
849                                         q->address -= 1;
850                                         r_mem -= 1; /* tracks q->address */
851                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
852                                         sym_addr += sym_vma + q->addend;
853                                         sym_addr |= (*(unsigned char *)r_mem<<24);
854                                         break;
855                                 case R_H8_DIR24A8:
856                                         if (sym_reloc_size != 4) {
857                                                 printf("R_H8_DIR24A8 size %d\n", sym_reloc_size);
858                                                 bad_relocs++;
859                                                 continue;
860                                         }
861                                         /* Absolute symbol done not relocation */
862                                         relocation_needed = !bfd_is_abs_section(sym_section);
863                                         sym_addr = (*(q->sym_ptr_ptr))->value;
864                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
865                                         sym_addr += sym_vma + q->addend;
866                                         break;
867                                 case R_H8_DIR32:
868                                 case R_H8_DIR32A16: /* currently 32,  could be made 16 */
869                                         if (sym_reloc_size != 4) {
870                                                 printf("R_H8_DIR32 size %d\n", sym_reloc_size);
871                                                 bad_relocs++;
872                                                 continue;
873                                         }
874                                         relocation_needed = 1;
875                                         sym_addr = (*(q->sym_ptr_ptr))->value;
876                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
877                                         sym_addr += sym_vma + q->addend;
878                                         break;
879                                 case R_H8_PCREL16:
880                                         sym_vma = 0;
881                                         sym_addr = (*(q->sym_ptr_ptr))->value;
882                                         sym_addr += sym_vma + q->addend;
883                                         sym_addr -= (q->address + 2);
884                                         if (bfd_big_endian(abs_bfd))
885                                         *(unsigned short *)r_mem =
886                                                 bfd_big_endian(abs_bfd) ? htons(sym_addr) : sym_addr;
887                                         continue;
888                                 case R_H8_PCREL8:
889                                         sym_vma = 0;
890                                         sym_addr = (*(q->sym_ptr_ptr))->value;
891                                         sym_addr += sym_vma + q->addend;
892                                         sym_addr -= (q->address + 1);
893                                         *(unsigned char *)r_mem = sym_addr;
894                                         continue;
895 #endif
896
897 #ifdef TARGET_microblaze
898                                 case R_MICROBLAZE_64:
899                 /* The symbol is split over two consecutive instructions.  
900                    Flag this to the flat loader by setting the high bit of 
901                    the relocation symbol. */
902                                 {
903                                         unsigned char *p = r_mem;
904                                         unsigned long offset;
905                                         pflags=0x80000000;
906
907                                         /* work out the relocation */
908                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
909                                         /* grab any offset from the text */
910                                         offset = (p[2]<<24) + (p[3] << 16) + (p[6] << 8) + (p[7]);
911                                         /* Update the address */
912                                         sym_addr += offset + sym_vma + q->addend;
913                                         /* Write relocated pointer back */
914                                         p[2] = (sym_addr >> 24) & 0xff;
915                                         p[3] = (sym_addr >> 16) & 0xff;
916                                         p[6] = (sym_addr >>  8) & 0xff;
917                                         p[7] =  sym_addr        & 0xff;
918
919                                         /* create a new reloc entry */
920                                         flat_relocs = realloc(flat_relocs,
921                                                 (flat_reloc_count + 1) * sizeof(uint32_t));
922                                         flat_relocs[flat_reloc_count] = pflags | (section_vma + q->address);
923                                         flat_reloc_count++;
924                                         relocation_needed = 0;
925                                         pflags = 0;
926                         sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
927                                          bfd_section_vma(abs_bfd, sym_section));
928                         if (verbose)
929                                 printf("  RELOC[%d]: offset=0x%x symbol=%s%s "
930                                         "section=%s size=%d "
931                                         "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
932                                         q->address, sym_name, addstr,
933                                         section_name, sym_reloc_size,
934                                         sym_addr, section_vma + q->address);
935                         if (verbose)
936                                 printf("reloc[%d] = 0x%x\n", flat_reloc_count,
937                                          section_vma + q->address);
938
939                                         continue;
940                                 }
941                                 case R_MICROBLAZE_32:
942                                 {       
943                                         unsigned char *p = r_mem;
944                                         unsigned long offset;
945
946                                         /* grab any offset from the text */
947                                         offset = (p[0]<<24) + (p[1] << 16) + (p[2] << 8) + (p[3]);
948                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
949                                         /* This is a horrible kludge.  For some
950                                            reason, *sometimes* the offset is in
951                                            both addend and the code.  Detect
952                                            it, and cancel the effect.  Otherwise
953                                            the offset gets added twice - ouch.
954                                            There should be a better test
955                                            for this condition, based on the
956                                            BFD data structures */
957                                         if(offset==q->addend)
958                                                 offset=0;
959
960                                         sym_addr += offset + sym_vma + q->addend;
961                                         relocation_needed = 1;
962                                         break;
963                                 }
964                                 case R_MICROBLAZE_64_PCREL:
965                                         sym_vma = 0;
966                                         //sym_addr = (*(q->sym_ptr_ptr))->value;
967                                         sym_addr += sym_vma + q->addend;
968                                         sym_addr -= (q->address + 4);
969                                         sym_addr = htonl(sym_addr);
970                                         /* insert 16 MSB */
971                                         * ((unsigned short *) (r_mem+2)) |= (sym_addr) & 0xFFFF;
972                                         /* then 16 LSB */
973                                         * ((unsigned short *) (r_mem+6)) |= (sym_addr >> 16) & 0xFFFF;
974                                         /* We've done all the work, so continue
975                                            to next reloc instead of break */
976                                         continue;
977
978 #endif /* TARGET_microblaze */
979                                         
980 #ifdef TARGET_nios2
981 #define  htoniosl(x)    (x)
982 #define  niostohl(x)    (x)
983                                 case R_NIOS2_BFD_RELOC_32:
984                                         relocation_needed = 1;
985                                         pflags = (FLAT_NIOS2_R_32 << 28);
986                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
987                                         sym_addr += sym_vma + q->addend;
988                                         /* modify target, in target order */
989                                         *(unsigned long *)r_mem = htoniosl(sym_addr);
990                                         break;
991                                 case R_NIOS2_CALL26:
992                                 {
993                                         unsigned long exist_val;
994                                         relocation_needed = 1;
995                                         pflags = (FLAT_NIOS2_R_CALL26 << 28);
996                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
997                                         sym_addr += sym_vma + q->addend;
998                                         
999                                         /* modify target, in target order */
1000                                         // exist_val = niostohl(*(unsigned long *)r_mem);
1001                                         exist_val = ((sym_addr >> 2) << 6);
1002                                         *(unsigned long *)r_mem = htoniosl(exist_val);
1003                                         break;
1004                                 }
1005                                 case R_NIOS2_HIADJ16:
1006                                 case R_NIOS2_HI16:
1007                                 {
1008                                         unsigned long exist_val;
1009                                         int r2_type;
1010                                         /* handle the adjacent HI/LO pairs */
1011                                         if (relcount == 0)
1012                                                 r2_type = R_NIOS2_NONE;
1013                                         else
1014                                                 r2_type = p[1]->howto->type;
1015                                         if ((r2_type == R_NIOS2_LO16)
1016                                             && (p[0]->sym_ptr_ptr == p[1]->sym_ptr_ptr)
1017                                             && (p[0]->addend == p[1]->addend)) 
1018                                             {
1019                                                         unsigned char * r2_mem = sectionp + p[1]->address;
1020                                                         if (p[1]->address - q->address!=4)
1021                                                                 printf("Err: HI/LO not adjacent %d\n", p[1]->address - q->address);
1022                                                         relocation_needed = 1;
1023                                                         pflags = (q->howto->type == R_NIOS2_HIADJ16) 
1024                                                                 ? FLAT_NIOS2_R_HIADJ_LO : FLAT_NIOS2_R_HI_LO;
1025                                                         pflags <<= 28;
1026                                                 
1027                                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
1028                                                         sym_addr += sym_vma + q->addend;
1029
1030                                                         /* modify high 16 bits, in target order */
1031                                                         exist_val = niostohl(*(unsigned long *)r_mem);
1032                                                         exist_val =  ((exist_val >> 22) << 22) | (exist_val & 0x3f);
1033                                                         if (q->howto->type == R_NIOS2_HIADJ16)
1034                                                                 exist_val |= ((((sym_addr >> 16) + ((sym_addr >> 15) & 1)) & 0xFFFF) << 6);
1035                                                         else
1036                                                                 exist_val |= (((sym_addr >> 16) & 0xFFFF) << 6);
1037                                                         *(unsigned long *)r_mem = htoniosl(exist_val);
1038
1039                                                         /* modify low 16 bits, in target order */
1040                                                         exist_val = niostohl(*(unsigned long *)r2_mem);
1041                                                         exist_val =  ((exist_val >> 22) << 22) | (exist_val & 0x3f);
1042                                                         exist_val |= ((sym_addr & 0xFFFF) << 6);
1043                                                         *(unsigned long *)r2_mem = htoniosl(exist_val);
1044                                                 
1045                                                 } else 
1046                                                         goto NIOS2_RELOC_ERR;
1047                                         }
1048                                         break;
1049
1050                                 case R_NIOS2_GPREL:
1051                                 {
1052                                         unsigned long exist_val, temp;
1053                                         //long gp = get_symbol_offset("_gp", sym_section, symbols, number_of_symbols);
1054                                         long gp = get_gp_value(symbols, number_of_symbols);
1055                                         if (gp == -1) {
1056                                                 printf("Err: unresolved symbol _gp when relocating %s\n", sym_name);
1057                                                 goto NIOS2_RELOC_ERR;
1058                                         }
1059                                         /* _gp holds a absolute value, otherwise the ld cannot generate correct code */
1060                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
1061                                         //printf("sym=%x, %d, _gp=%x, %d\n", sym_addr+sym_vma, sym_addr+sym_vma, gp, gp);
1062                                         sym_addr += sym_vma + q->addend;
1063                                         sym_addr -= gp;
1064                                         //printf("sym - _gp=%x, %d\n", sym_addr, sym_addr);
1065                                         /* modify the target, in target order (little_endian) */
1066                                         exist_val = niostohl(*(unsigned long *)r_mem);
1067                                         temp = ((exist_val >> 6) & 0x3ff0000) | (sym_addr & 0xffff);
1068                                         temp <<= 6;
1069                                         temp |= (exist_val & 0x3f);
1070                                         *(unsigned long *)r_mem = htoniosl(temp);
1071                                         if (verbose)
1072                                                 printf("omit: offset=0x%x symbol=%s%s "
1073                                                                 "section=%s size=%d "
1074                                                                 "fixup=0x%x (reloc=0x%x) GPREL\n", 
1075                                                                 q->address, sym_name, addstr,
1076                                                                 section_name, sym_reloc_size,
1077                                                                 sym_addr, section_vma + q->address);
1078                                         continue;
1079                                 }
1080                                 case R_NIOS2_PCREL16:
1081                                 {
1082                                         unsigned long exist_val;
1083                                         sym_vma = 0;
1084                                         sym_addr += sym_vma + q->addend;
1085                                         sym_addr -= (q->address + 4);
1086                                         /* modify the target, in target order (little_endian) */
1087                                         exist_val = niostohl(*(unsigned long *)r_mem);
1088                                         exist_val =  ((exist_val >> 22) << 22) | (exist_val & 0x3f);
1089                                         exist_val |= ((sym_addr & 0xFFFF) << 6);
1090                                         *(unsigned long *)r_mem = htoniosl(exist_val);
1091                                         if (verbose)
1092                                                 printf("omit: offset=0x%x symbol=%s%s "
1093                                                                 "section=%s size=%d "
1094                                                                 "fixup=0x%x (reloc=0x%x) PCREL\n", 
1095                                                                 q->address, sym_name, addstr,
1096                                                                 section_name, sym_reloc_size,
1097                                                                 sym_addr, section_vma + q->address);
1098                                         continue;
1099                                 }
1100
1101                                 case R_NIOS2_LO16:
1102                                         /* check if this is actually the 2nd half of a pair */
1103                                         if ((p > relpp)
1104                                                 && ((p[-1]->howto->type == R_NIOS2_HIADJ16) 
1105                                                         || (p[-1]->howto->type == R_NIOS2_HI16))
1106                                             && (p[-1]->sym_ptr_ptr == p[0]->sym_ptr_ptr)
1107                                             && (p[-1]->addend == p[0]->addend)) {
1108                                                 if (verbose)
1109                                                         printf("omit: offset=0x%x symbol=%s%s "
1110                                                                 "section=%s size=%d LO16\n", 
1111                                                                 q->address, sym_name, addstr,
1112                                                                 section_name, sym_reloc_size);
1113                                                 continue;
1114                                         }
1115
1116                                         /* error, fall through */
1117
1118                                 case R_NIOS2_S16:
1119                                 case R_NIOS2_U16:
1120                                 case R_NIOS2_CACHE_OPX:
1121                                 case R_NIOS2_IMM5:
1122                                 case R_NIOS2_IMM6:
1123                                 case R_NIOS2_IMM8:
1124                                 case R_NIOS2_BFD_RELOC_16:
1125                                 case R_NIOS2_BFD_RELOC_8:
1126                                 case R_NIOS2_GNU_VTINHERIT:
1127                                 case R_NIOS2_GNU_VTENTRY:
1128                                 case R_NIOS2_UJMP:
1129                                 case R_NIOS2_CJMP:
1130                                 case R_NIOS2_CALLR:
1131 NIOS2_RELOC_ERR:
1132                                         printf("Err: unexpected reloc type %s(%d)\n", q->howto->name, q->howto->type);
1133                                         bad_relocs++;
1134                                         continue;
1135 #endif /* TARGET_nios2 */
1136
1137 #ifdef TARGET_sparc
1138                                 case R_SPARC_32:
1139                                 case R_SPARC_UA32:
1140                                         relocation_needed = 1;
1141                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
1142                                         sym_addr += sym_vma + q->addend;
1143                                         break;
1144                                 case R_SPARC_PC22:
1145                                         sym_vma = 0;
1146                                         sym_addr += sym_vma + q->addend;
1147                                         sym_addr -= q->address;
1148                                         break;
1149                                 case R_SPARC_WDISP30:
1150                                         sym_addr = (((*(q->sym_ptr_ptr))->value-
1151                                                 q->address) >> 2) & 0x3fffffff;
1152                                         sym_addr |= (
1153                                                 ntohl(*(unsigned long *)r_mem)
1154                                                 & 0xc0000000
1155                                                 );
1156                                         break;
1157                                 case R_SPARC_HI22:
1158                                         relocation_needed = 1;
1159                                         pflags = 0x80000000;
1160                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
1161                                         sym_addr += sym_vma + q->addend;
1162                                         sym_addr |= (
1163                                                 htonl(*(unsigned long *)r_mem)
1164                                                 & 0xffc00000
1165                                                 );
1166                                         break;
1167                                 case R_SPARC_LO10:
1168                                         relocation_needed = 1;
1169                                         pflags = 0x40000000;
1170                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
1171                                         sym_addr += sym_vma + q->addend;
1172                                         sym_addr &= 0x000003ff;
1173                                         sym_addr |= (
1174                                                 htonl(*(unsigned long *)r_mem)
1175                                                 & 0xfffffc00
1176                                                 );
1177                                         break;
1178 #endif /* TARGET_sparc */
1179
1180 #ifdef TARGET_bfin
1181                                 case R_pcrel12_jump:
1182                                 case R_pcrel12_jump_s:
1183                                 case R_pcrel24:
1184                                 case R_pcrel24_jump_l:
1185                                 case R_pcrel24_jump_x:
1186                                 case R_pcrel24_call_x:
1187                                 case R_pcrel10:
1188                                 case R_pcrel11:
1189                                 case R_pcrel5m2:
1190                                   sym_addr += q->addend;// get the symbol addr
1191                                   sym_vma = bfd_section_vma(abs_bfd, sym_section);
1192                                   sym_addr -= q->address; // make it PC relative 
1193                                   // implicitly assumes code section and symbol section are same
1194                                   break;
1195                                 case R_got:
1196                                     /* Ignore these.  */
1197                                     break;
1198
1199                                 case R_rimm16:
1200                                     sym_addr += q->addend;
1201                                     if(weak_und_symbol(sym_section->name, (*(q->sym_ptr_ptr))))
1202                                         continue;
1203                                     if(0xFFFF0000 & sym_addr){
1204                                         fprintf (stderr, "Relocation overflow for rN = %s\n",sym_name);
1205                                         bad_relocs++;
1206                                     }
1207                                     flat_relocs = (uint32_t *)
1208                                         (realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));
1209                                     if (bfin_set_reloc (flat_relocs + flat_reloc_count, 
1210                                                         sym_section->name, sym_name,
1211                                                         (*(q->sym_ptr_ptr)),
1212                                                         0, FLAT_RELOC_PART_LO, 
1213                                                         section_vma + q->address))
1214                                         bad_relocs++;
1215                                     flat_reloc_count++;
1216                                     break;
1217                                     
1218                                 case R_luimm16:
1219                                 case R_huimm16:
1220                                 {
1221                                     unsigned int sp;
1222                                     unsigned int reloc_count_incr;
1223                                     unsigned int hi_lo;
1224
1225                                     if (q->howto->type == R_luimm16)
1226                                         hi_lo = FLAT_RELOC_PART_LO;
1227                                     else
1228                                         hi_lo = FLAT_RELOC_PART_HI;
1229                                 
1230                                     sym_addr += q->addend;
1231
1232                                     flat_relocs = (uint32_t *)
1233                                         (realloc (flat_relocs, (flat_reloc_count + 2) * sizeof (uint32_t)));
1234                                     reloc_count_incr = 1;
1235                                     if (weak_und_symbol (sym_section->name, (*(q->sym_ptr_ptr))))
1236                                         continue;
1237                                     if (0xFFFF0000 & sym_addr) {
1238                                         /* value is > 16 bits - use an extra field */
1239                                         /* see if we have already output that symbol */
1240                                         /* reloc may be addend from symbol and       */
1241                                         /* we can only store 16 bit offsets          */
1242                                         sp = 1;
1243                                         if ((*(q->sym_ptr_ptr))->udata.i == 0
1244                                             || flat_relocs[(*(q->sym_ptr_ptr))->udata.i] != sym_addr
1245                                             || ((*(q->sym_ptr_ptr))->udata.i & 0xFFFF0000))
1246                                         {
1247                                             reloc_count_incr = 2;
1248                                             flat_relocs[flat_reloc_count + 1] = sym_addr;
1249                                             (*(q->sym_ptr_ptr))->udata.i = flat_reloc_count + 1;
1250                                             sym_addr = 0; // indication to loader to read next
1251                                         } else{
1252                                             sym_addr = (*(q->sym_ptr_ptr))->udata.i;
1253                                         }
1254                                     } else {
1255                                         sp = 0;
1256                                     }
1257
1258                                     if (bfin_set_reloc (flat_relocs + flat_reloc_count, 
1259                                                         sym_section->name, sym_name,
1260                                                         (*(q->sym_ptr_ptr)),
1261                                                         sp, hi_lo,
1262                                                         section_vma + q->address))
1263                                         bad_relocs++;
1264                                     flat_reloc_count += reloc_count_incr;
1265                                     break;
1266                                 }
1267                                 case R_byte4_data:
1268                                     sym_addr += q->addend;
1269
1270                                     if (weak_und_symbol (sym_section->name, *q->sym_ptr_ptr))
1271                                         continue;
1272
1273                                     flat_relocs = (uint32_t *)
1274                                         (realloc (flat_relocs, (flat_reloc_count + 1) * sizeof (uint32_t)));
1275                                     if (bfin_set_reloc (flat_relocs + flat_reloc_count, 
1276                                                         sym_section->name, sym_name,
1277                                                         (*(q->sym_ptr_ptr)),
1278                                                         2, FLAT_RELOC_PART_LO, 
1279                                                         section_vma + q->address))
1280                                         bad_relocs++;
1281
1282                                     flat_reloc_count++;
1283                                     break;
1284
1285 #endif //TARGET_bfin
1286
1287 #ifdef TARGET_sh
1288                                 case R_SH_DIR32:
1289                                         relocation_needed = 1;
1290                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
1291                                         sym_addr += sym_vma + q->addend;
1292                                         break;
1293                                 case R_SH_REL32:
1294                                         sym_vma = 0;
1295                                         sym_addr += sym_vma + q->addend;
1296                                         sym_addr -= q->address;
1297                                         break;
1298 #endif /* TARGET_sh */
1299
1300 #ifdef TARGET_e1
1301 #define  htoe1l(x)              htonl(x)
1302                                         
1303 #if 0 
1304 #define  DEBUG_E1
1305 #endif
1306
1307 #ifdef   DEBUG_E1
1308 #define  DBG_E1                 printf
1309 #else
1310 #define  DBG_E1(x, ...  )
1311 #endif
1312
1313 #define _32BITS_RELOC 0x00000000
1314 #define _30BITS_RELOC 0x80000000
1315 #define _28BITS_RELOC 0x40000000
1316                                         {
1317                                 char *p;
1318                                 unsigned long   sec_vma, exist_val, S;
1319                                 case R_E1_CONST31:
1320                                                 relocation_needed = 1;
1321                                                 DBG_E1("Handling Reloc <CONST31>\n");
1322                                                 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1323                                                 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
1324                                                                                 sec_vma, sym_addr, q->address);
1325                                                 sym_addr = sec_vma + sym_addr;
1326                                                 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);        
1327                                                 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
1328                                                 exist_val = htoe1l(exist_val);
1329                                                 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
1330                                                 sym_addr += exist_val;
1331                                                 pflags = _30BITS_RELOC;
1332                                                 break;
1333                                 case R_E1_CONST31_PCREL:
1334                                                 relocation_needed = 0;
1335                                                 DBG_E1("Handling Reloc <CONST31_PCREL>\n");
1336                                                 DBG_E1("DONT RELOCATE AT LOADING\n");
1337                                                 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1338                                                 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
1339                                                                                 sec_vma, sym_addr, q->address);
1340                                                 sym_addr =  sec_vma + sym_addr;
1341                                                 DBG_E1("sym_addr =  sec_vma + sym_addr : [0x%x]\n", sym_addr );
1342
1343                                                 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
1344                                                                                                                                                 section_vma );
1345                                                 q->address = q->address + section_vma;
1346                                                 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
1347
1348                                                 if( (sym_addr = (sym_addr - q->address - 6)) < 0 )
1349                                                                 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
1350                                                 DBG_E1( "sym_addr := sym_addr - q->address  - "
1351                                                                 "sizeof(CONST31_PCREL): [0x%x]\n",
1352                                                                 sym_addr );
1353                                                 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);              
1354                                                 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
1355                                                 exist_val = htoe1l(exist_val);
1356                                                 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
1357                                                 sym_addr |= exist_val;
1358                                                 DBG_E1("sym_addr |=  exist_val) : [0x%x]\n", sym_addr );
1359                                                 break;
1360                                 case R_E1_DIS29W_PCREL:
1361                                                 relocation_needed = 0;
1362                                                 DBG_E1("Handling Reloc <DIS29W_PCREL>\n");
1363                                                 DBG_E1("DONT RELOCATE AT LOADING\n");
1364                                                 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1365                                                 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x], q->address : [0x%x]\n",
1366                                                                                 sec_vma, sym_addr, q->address);
1367                                                 sym_addr =  sec_vma + sym_addr;
1368                                                 DBG_E1("sym_addr =  sec_vma + sym_addr : [0x%x]\n", sym_addr );
1369
1370                                                 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
1371                                                                                                                                                 section_vma );
1372                                                 q->address = q->address + section_vma;
1373                                                 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
1374
1375                                                 if( (sym_addr = (sym_addr - q->address - 6)) < 0 )
1376                                                                 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
1377                                                 DBG_E1( "sym_addr := sym_addr - q->address  - "
1378                                                                 "sizeof(CONST31_PCREL): [0x%x]\n",
1379                                                                 sym_addr );
1380                                                 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
1381                                                 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);       
1382                                                 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
1383                                                 exist_val = htoe1l(exist_val);
1384                                                 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
1385                                                 sym_addr += exist_val;
1386                                                 break;
1387                                 case R_E1_DIS29W:
1388                                                 DBG_E1("Handling Reloc <DIS29W>\n");
1389                                                 goto DIS29_RELOCATION;
1390                                 case R_E1_DIS29H:
1391                                                 DBG_E1("Handling Reloc <DIS29H>\n");
1392                                                 goto DIS29_RELOCATION;
1393                                 case R_E1_DIS29B:
1394                                                 DBG_E1("Handling Reloc <DIS29B>\n");
1395 DIS29_RELOCATION:
1396                                                 relocation_needed = 1;
1397                                                 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1398                                                 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%08x]\n",
1399                                                                                 sec_vma, sym_addr);
1400                                                 sym_addr =  sec_vma + sym_addr;
1401                                                 DBG_E1("sym_addr =  sec_vma + sym_addr : [0x%08x]\n", sym_addr);
1402                                                 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);                
1403                                                 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
1404                                                 exist_val = htoe1l(exist_val);
1405                                                 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
1406                                                 sym_addr +=  exist_val;
1407                                                 DBG_E1("sym_addr +=  exist_val : [0x%08x]\n", sym_addr);
1408                                                 pflags = _28BITS_RELOC;
1409                                                 break;
1410                                 case R_E1_IMM32_PCREL:
1411                                                 relocation_needed = 0;
1412                                                 DBG_E1("Handling Reloc <IMM32_PCREL>\n");
1413                                                 DBG_E1("DONT RELOCATE AT LOADING\n");
1414                                                 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1415                                                 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1416                                                                                 sec_vma, sym_addr);
1417                                                 sym_addr =  sec_vma + sym_addr;
1418
1419                                                 DBG_E1("sym_addr =  sec_vma + sym_addr : [0x%x]\n", sym_addr );
1420                                                 DBG_E1("q->address : 0x%x, section_vma : 0x%x\n", q->address,
1421                                                                                                                                                 section_vma );
1422                                                 q->address = q->address + section_vma;
1423                                                 DBG_E1("q->address += section_vma : 0x%x\n", q->address );
1424
1425                                                 if( (sym_addr = (sym_addr - q->address - 6 )) < 0 )
1426                                                                 DBG_E1("NEGATIVE OFFSET in PC Relative instruction\n");
1427                                                 DBG_E1( "sym_addr := sym_addr - q->address  - "
1428                                                                 "sizeof(CONST31_PCREL): [0x%x]\n",
1429                                                                 sym_addr );
1430                                                 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
1431                                                 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);                 
1432                                                 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
1433                                                 exist_val = htoe1l(exist_val);
1434                                                 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
1435                                                 sym_addr += exist_val;
1436                                                 break;
1437                                 case R_E1_IMM32:
1438                                                 relocation_needed = 1;
1439                                                 DBG_E1("Handling Reloc <IMM32>\n");
1440                                                 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1441                                                 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1442                                                                                 sec_vma, sym_addr);
1443                                                 sym_addr =  sec_vma + sym_addr;
1444                                                 DBG_E1("sym_addr =  sec_vma + sym_addr : [0x%x]\n", sym_addr );
1445                                                 DBG_E1("sectionp:[0x%x], q->address:[0x%x]\n", sectionp, q->address );
1446                                                 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address + 2);                     
1447                                                 DBG_E1("Original:exist_val : [0x%08x]\n",exist_val);
1448                                                 exist_val = htoe1l(exist_val);
1449                                                 DBG_E1("HtoBE:exist_val : [0x%08x]\n",exist_val);
1450                                                 sym_addr += exist_val;
1451                                                 pflags = _32BITS_RELOC;
1452                                                 break;
1453                                 case R_E1_WORD:
1454                                                 relocation_needed = 1;
1455                                                 DBG_E1("Handling Reloc <WORD>\n");
1456                                                 sec_vma = bfd_section_vma(abs_bfd, sym_section);
1457                                                 DBG_E1("sec_vma : [0x%x], sym_addr : [0x%x]\n",
1458                                                                                 sec_vma, sym_addr);
1459                                                 sym_addr =  sec_vma + sym_addr;
1460                                                 DBG_E1("sym_addr =  sec_vma + sym_addr : [0x%x]\n", sym_addr );
1461                                                 exist_val = *(unsigned long*)((unsigned long)sectionp + q->address );
1462                                                 DBG_E1("Orig:exist_val : [0x%08x]\n", exist_val);
1463                                                 exist_val = htoe1l(exist_val);
1464                                                 DBG_E1("HtoBE:exist_val : [0x%08x]\n", exist_val);
1465                                                 sym_addr +=  exist_val;
1466                                                 DBG_E1("sym_addr +=  exist_val : [0x%08x]\n", sym_addr);
1467                                                 pflags = _32BITS_RELOC;
1468                                                 break;
1469                                 }
1470 #undef _32BITS_RELOC
1471 #undef _30BITS_RELOC
1472 #undef _28BITS_RELOC
1473 #endif
1474                                 default:
1475                                         /* missing support for other types of relocs */
1476                                         printf("ERROR: bad reloc type %d\n", (*p)->howto->type);
1477                                         bad_relocs++;
1478                                         continue;
1479                                 }
1480                         }
1481
1482                         sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
1483                                          bfd_section_vma(abs_bfd, sym_section));
1484
1485
1486                         /*
1487                          * for full elf relocation we have to write back the
1488                          * start_code relative value to use.
1489                          */
1490                         if (!pic_with_got) {
1491 #if defined(TARGET_arm)
1492                                 union {
1493                                         unsigned char c[4];
1494                                         unsigned long l;
1495                                 } tmp;
1496                                 long hl;
1497                                 int i0, i1, i2, i3;
1498
1499                                 /*
1500                                  * horrible nasty hack to support different endianess
1501                                  */
1502                                 if (!bfd_big_endian(abs_bfd)) {
1503                                         i0 = 0;
1504                                         i1 = 1;
1505                                         i2 = 2;
1506                                         i3 = 3;
1507                                 } else {
1508                                         i0 = 3;
1509                                         i1 = 2;
1510                                         i2 = 1;
1511                                         i3 = 0;
1512                                 }
1513
1514                                 tmp.l = *(unsigned long *)r_mem;
1515                                 hl = tmp.c[i0] | (tmp.c[i1] << 8) | (tmp.c[i2] << 16);
1516                                 if (use_resolved ||
1517                                         (((*p)->howto->type != R_ARM_PC24) &&
1518                                         ((*p)->howto->type != R_ARM_PLT32)))
1519                                         hl |= (tmp.c[i3] << 24);
1520                                 else if (tmp.c[i2] & 0x80)
1521                                         hl |= 0xff000000; /* sign extend */
1522                                 if (!use_resolved)
1523                                         hl += sym_addr;
1524                                 tmp.c[i0] = hl & 0xff;
1525                                 tmp.c[i1] = (hl >> 8) & 0xff;
1526                                 tmp.c[i2] = (hl >> 16) & 0xff;
1527                                 if (use_resolved ||
1528                                         (((*p)->howto->type != R_ARM_PC24) &&
1529                                         ((*p)->howto->type != R_ARM_PLT32)))
1530                                         tmp.c[i3] = (hl >> 24) & 0xff;
1531                                 if ((*p)->howto->type == R_ARM_ABS32)
1532                                         *(unsigned long *)r_mem = htonl(hl);
1533                                 else
1534                                         *(unsigned long *)r_mem = tmp.l;
1535
1536 #elif defined(TARGET_bfin)
1537                                 if ((*p)->howto->type == R_pcrel24
1538                                     || (*p)->howto->type == R_pcrel24_jump_l
1539                                     || (*p)->howto->type == R_pcrel24_jump_x
1540                                     || (*p)->howto->type == R_pcrel24_call_x)
1541                                 {
1542                                     sym_addr += 2*-1*PCREL24_MAGIC_OFFSET;
1543                                     *((unsigned short *)(sectionp + q->address) + 1 + PCREL24_MAGIC_OFFSET)
1544                                         = (sym_addr >> 1) & 0xffff;
1545                                     *((unsigned short *)(sectionp + q->address) + PCREL24_MAGIC_OFFSET)
1546                                         = (0xff00 & *((unsigned short *) (sectionp + q->address) + PCREL24_MAGIC_OFFSET)
1547                                            | ((sym_addr >> 17) & 0xff));
1548                                 } else if ((*p)->howto->type == R_byte4_data) {
1549                                     *((uint32_t *)(sectionp + q->address)) = sym_addr;
1550                                 } else if ((*p)->howto->type == R_pcrel12_jump
1551                                            || (*p)->howto->type == R_pcrel12_jump_s) {
1552                                     *((unsigned short *)(sectionp + q->address))
1553                                         = (0xf000 & *((unsigned short *)(sectionp + q->address))
1554                                            | ((sym_addr >> 1) & 0xfff));
1555                                 } else if ((*p)->howto->type == R_pcrel10) {
1556                                     *((unsigned short *)(sectionp + q->address))
1557                                         = (~0x3ff & *((unsigned short *)(sectionp + q->address))
1558                                            | ((sym_addr >> 1) & 0x3ff));
1559                                 } else if ((*p)->howto->type == R_rimm16
1560                                            || (*p)->howto->type == R_huimm16
1561                                            || (*p)->howto->type == R_luimm16) {
1562                                     /* for l and h we set the lower 16 bits which is only when it will be used */
1563                                     *((unsigned short *) (sectionp + q->address)) = (unsigned short) sym_addr;
1564                                 } else if ((*p)->howto->type == R_pcrel5m2) {
1565                                     *((unsigned short *)(sectionp + q->address))
1566                                         = (0xfff0 & *((unsigned short *)(sectionp + q->address))
1567                                            | ((sym_addr >> 1) & 0xf));
1568                                 } else if ((*p)->howto->type == R_pcrel11){
1569                                     *((unsigned short *)(sectionp + q->address))
1570                                         = (0xfc00 & *((unsigned short *)(sectionp + q->address))
1571                                            | ((sym_addr >> 1) & 0x3ff));
1572                                 } else if (0xE0 <= (*p)->howto->type && 0xF3 >= (*p)->howto->type) {
1573                                     //arith relocs dont generate a real relocation
1574                                 } else {
1575                                     printf("Blackfin relocation fail for reloc type: 0x%x\n", (*p)->howto->type);
1576                                 }
1577 #elif defined(TARGET_e1)
1578 #define OPCODE_SIZE 2           /* Add 2 bytes, counting the opcode size*/
1579                                 switch ((*p)->howto->type) {
1580                                 case R_E1_CONST31:
1581                                 case R_E1_CONST31_PCREL:
1582                                 case R_E1_DIS29W_PCREL:
1583                                 case R_E1_DIS29W:
1584                                 case R_E1_DIS29H:
1585                                 case R_E1_DIS29B:
1586                                 case R_E1_IMM32_PCREL:
1587                                 case R_E1_IMM32:
1588                                                 DBG_E1("In addr + 2:[0x%x] <- write [0x%x]\n",
1589                                                                 (sectionp + q->address + 2), sym_addr );
1590                                                 *((unsigned long *) (sectionp + q->address + OPCODE_SIZE)) =
1591                                                 htonl(sym_addr);
1592                                 break;
1593                                 case R_E1_WORD:
1594                                                 DBG_E1("In addr : [0x%x] <- write [0x%x]\n",
1595                                                                 (sectionp + q->address), sym_addr );
1596                                                 *((unsigned long *) (sectionp + q->address )) = htonl(sym_addr);
1597                                 break;
1598                                 default:
1599                                                 printf("ERROR:Unhandled Relocation. Exiting...\n");
1600                                                 exit(0);
1601                                 break;
1602                                 }
1603 #else /* ! TARGET_arm && ! TARGET_e1 */
1604
1605                                 switch (q->howto->type) {
1606 #ifdef TARGET_v850
1607                                 case R_V850_HI16_S:
1608                                 case R_V850_HI16:
1609                                 case R_V850_LO16:
1610                                         /* Do nothing -- for cases we handle,
1611                                            the bits produced by the linker are
1612                                            what we want in the final flat file
1613                                            (and other cases are errors).  Note
1614                                            that unlike most relocated values,
1615                                            it is stored in little-endian order,
1616                                            but this is necessary to avoid
1617                                            trashing the low-bit, and the float
1618                                            loaders knows about it.  */
1619                                         break;
1620 #endif /* TARGET_V850 */
1621
1622 #ifdef TARGET_nios2
1623                                 case R_NIOS2_BFD_RELOC_32:
1624                                 case R_NIOS2_CALL26:
1625                                 case R_NIOS2_HIADJ16:
1626                                 case R_NIOS2_HI16:
1627                                         /* do nothing */
1628                                         break;
1629 #endif /* TARGET_nios2 */
1630
1631 #if defined(TARGET_m68k)
1632                                 case R_68K_PC16:
1633                                         if (sym_addr < -0x8000 || sym_addr > 0x7fff) {
1634                                                 fprintf (stderr, "Relocation overflow for R_68K_PC16 relocation against %s\n", sym_name);
1635                                                 bad_relocs++;
1636                                         } else {
1637                                                 r_mem[0] = (sym_addr >>  8) & 0xff;
1638                                                 r_mem[1] =  sym_addr        & 0xff;
1639                                         }
1640                                         break;
1641 #endif
1642
1643                                 default:
1644                                         /* The alignment of the build host
1645                                            might be stricter than that of the
1646                                            target, so be careful.  We store in
1647                                            network byte order. */
1648                                         r_mem[0] = (sym_addr >> 24) & 0xff;
1649                                         r_mem[1] = (sym_addr >> 16) & 0xff;
1650                                         r_mem[2] = (sym_addr >>  8) & 0xff;
1651                                         r_mem[3] =  sym_addr        & 0xff;
1652                                 }
1653 #endif /* !TARGET_arm */
1654                         }
1655
1656 #ifdef TARGET_bfin
1657                         else {
1658                             if ((*p)->howto->type == R_rimm16
1659                                 || (*p)->howto->type == R_huimm16
1660                                 || (*p)->howto->type == R_luimm16)
1661                             {
1662                                 /* for l and h we set the lower 16 bits which is only when it will be used */
1663                                 *((unsigned short *) (sectionp + q->address)) = (unsigned short) sym_addr;
1664                             } else if ((*p)->howto->type == R_byte4_data) {
1665                                 *((uint32_t *)(sectionp + q->address)) = sym_addr;
1666                             }
1667                         }
1668 #endif
1669                         if (verbose)
1670                                 printf("  RELOC[%d]: offset=0x%x symbol=%s%s "
1671                                         "section=%s size=%d "
1672                                         "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
1673                                         q->address, sym_name, addstr,
1674                                         section_name, sym_reloc_size,
1675                                         sym_addr, section_vma + q->address);
1676
1677                         /*
1678                          *      Create relocation entry (PC relative doesn't need this).
1679                          */
1680                         if (relocation_needed) {
1681 #ifndef TARGET_bfin
1682                                 flat_relocs = realloc(flat_relocs,
1683                                         (flat_reloc_count + 1) * sizeof(uint32_t));
1684 #ifndef TARGET_e1
1685                                 flat_relocs[flat_reloc_count] = pflags |
1686                                         (section_vma + q->address);
1687
1688                                 if (verbose)
1689                                         printf("reloc[%d] = 0x%x\n", flat_reloc_count,
1690                                                         section_vma + q->address);
1691 #else
1692                                 switch ((*p)->howto->type) {
1693                                 case R_E1_CONST31:
1694                                 case R_E1_CONST31_PCREL:
1695                                 case R_E1_DIS29W_PCREL:
1696                                 case R_E1_DIS29W:
1697                                 case R_E1_DIS29H:
1698                                 case R_E1_DIS29B:
1699                                 case R_E1_IMM32_PCREL:
1700                                 case R_E1_IMM32:
1701                                 flat_relocs[flat_reloc_count] = pflags |
1702                                                 (section_vma + q->address + OPCODE_SIZE);
1703                                 if (verbose)
1704                                                 printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count,
1705                                                                                  flat_relocs[flat_reloc_count] );
1706                                 break;
1707                                 case R_E1_WORD:
1708                                 flat_relocs[flat_reloc_count] = pflags |
1709                                                 (section_vma + q->address);
1710                                 if (verbose)
1711                                                 printf("RELOCATION TABLE : reloc[%d] = [0x%x]\n", flat_reloc_count,
1712                                                                                  flat_relocs[flat_reloc_count] );
1713                                 break;
1714                                 }
1715 #endif
1716                                 flat_reloc_count++;
1717 #endif
1718                                 relocation_needed = 0;
1719                                 pflags = 0;
1720                         }
1721
1722 #if 0
1723 printf("%s(%d): symbol name=%s address=0x%x section=%s -> RELOC=0x%x\n",
1724         __FILE__, __LINE__, sym_name, q->address, section_name,
1725         flat_relocs[flat_reloc_count]);
1726 #endif
1727                 }
1728         }
1729   }
1730
1731   if (bad_relocs) {
1732           printf("%d bad relocs\n", bad_relocs);
1733           exit(1);
1734   }
1735
1736   if (rc < 0)
1737         return(0);
1738
1739   *n_relocs = flat_reloc_count;
1740   return flat_relocs;
1741 }
1742
1743
1744
1745 static char * program;
1746
1747 static void usage(void)
1748 {  
1749     fprintf(stderr, "Usage: %s [vrzd] [-p <abs-pic-file>] [-s stack-size] "
1750         "[-o <output-file>] <elf-file>\n\n"
1751         "       -v              : verbose operation\n"
1752         "       -r              : force load to RAM\n"
1753         "       -k              : enable kernel trace on load (for debug)\n"
1754         "       -z              : compress code/data/relocs\n"
1755         "       -d              : compress data/relocs\n"
1756         "       -a              : use existing symbol references\n"
1757         "                         instead of recalculating from\n"
1758         "                         relocation info\n"
1759         "       -R reloc-file   : read relocations from a separate file\n"
1760         "       -p abs-pic-file : GOT/PIC processing with files\n"
1761         "       -s stacksize    : set application stack size\n"
1762         "       -o output-file  : output file name\n\n",
1763         program);
1764         fprintf(stderr, "Compiled for " ARCH " architecture\n\n");
1765     exit(2);
1766 }
1767
1768
1769 /* Write NUM zeroes to STREAM.  */
1770 static void write_zeroes (unsigned long num, FILE *stream)
1771 {
1772   char zeroes[1024];
1773   if (num > 0) {
1774     /* It'd be nice if we could just use fseek, but that doesn't seem to
1775        work for stdio output files.  */
1776     memset(zeroes, 0x00, 1024);
1777     while (num > sizeof(zeroes)) {
1778       fwrite(zeroes, sizeof(zeroes), 1, stream);
1779       num -= sizeof(zeroes);
1780     }
1781     if (num > 0)
1782       fwrite(zeroes, num, 1, stream);
1783   }
1784 }
1785
1786
1787 int main(int argc, char *argv[])
1788 {
1789   int fd;
1790   bfd *rel_bfd, *abs_bfd;
1791   asection *s;
1792   char *ofile=NULL, *pfile=NULL, *abs_file = NULL, *rel_file = NULL;
1793   char *fname = NULL;
1794   int opt;
1795   int i;
1796   int stack;
1797   char  cmd[1024];
1798   FILE *gf = NULL;
1799
1800   asymbol **symbol_table;
1801   long number_of_symbols;
1802
1803   unsigned long data_len = 0;
1804   unsigned long bss_len = 0;
1805   unsigned long text_len = 0;
1806   unsigned long reloc_len;
1807
1808   unsigned long data_vma = ~0;
1809   unsigned long bss_vma = ~0;
1810   unsigned long text_vma = ~0;
1811
1812   unsigned long text_offs;
1813
1814   void *text;
1815   void *data;
1816   uint32_t *reloc;
1817   
1818   struct flat_hdr hdr;
1819
1820   int gf_is_pipe = 0;
1821
1822   program = argv[0];
1823   progname = argv[0];
1824   xmalloc_set_program_name(program);
1825
1826   if (argc < 2)
1827         usage();
1828   
1829   if (sizeof(hdr) != 64) {
1830     fprintf(stderr,
1831             "Potential flat header incompatibility detected\n"
1832             "header size should be 64 but is %d\n",
1833             sizeof(hdr));
1834     exit(64);
1835   }
1836
1837 #ifndef TARGET_e1
1838   stack = 4096;
1839 #else /* We need plenty of stack for both of them (Aggregate and Register) */
1840   stack = 0x2020;
1841 #endif
1842
1843   while ((opt = getopt(argc, argv, "avzdrkp:s:o:R:")) != -1) {
1844     switch (opt) {
1845     case 'v':
1846       verbose++;
1847       break;
1848     case 'r':
1849       load_to_ram++;
1850       break;
1851     case 'k':
1852       ktrace++;
1853       break;
1854     case 'z':
1855       compress = 1;
1856       break;
1857     case 'd':
1858       compress = 2;
1859       break;
1860     case 'p':
1861       pfile = optarg;
1862       break;
1863     case 'o':
1864       ofile = optarg;
1865       break;
1866     case 'a':
1867       use_resolved = 1;
1868       break;
1869     case 's':
1870       if (sscanf(optarg, "%i", &stack) != 1) {
1871         fprintf(stderr, "%s invalid stack size %s\n", argv[0], optarg);
1872         usage();
1873       }
1874       break;
1875     case 'R':
1876       rel_file = optarg;
1877       break;
1878     default:
1879       fprintf(stderr, "%s Unknown option\n", argv[0]);
1880       usage();
1881       break;
1882     }
1883   }
1884   
1885   /*
1886    * if neither the -r or -p options was given,  default to
1887    * a RAM load as that is the only option that makes sense.
1888    */
1889   if (!load_to_ram && !pfile)
1890     load_to_ram = 1;
1891
1892   filename = fname = argv[argc-1];
1893
1894   if (pfile) {
1895     pic_with_got = 1;
1896     abs_file = pfile;
1897   } else
1898     abs_file = fname;
1899
1900   if (! rel_file)
1901     rel_file = fname;
1902
1903   if (!(rel_bfd = bfd_openr(rel_file, 0))) {
1904     fprintf(stderr, "Can't open %s\n", rel_file);
1905     exit(1);
1906   }
1907
1908   if (bfd_check_format (rel_bfd, bfd_object) == 0) {
1909     fprintf(stderr, "File is not an object file\n");
1910     exit(2);
1911   }
1912
1913   if (abs_file == rel_file)
1914     abs_bfd = rel_bfd; /* one file does all */
1915   else {
1916     if (!(abs_bfd = bfd_openr(abs_file, 0))) {
1917       fprintf(stderr, "Can't open %s\n", abs_file);
1918       exit(1);
1919     }
1920
1921     if (bfd_check_format (abs_bfd, bfd_object) == 0) {
1922       fprintf(stderr, "File is not an object file\n");
1923       exit(2);
1924     }
1925   }
1926
1927   if (! (bfd_get_file_flags(rel_bfd) & HAS_RELOC)) {
1928     fprintf (stderr, "%s: Input file contains no relocation info\n", rel_file);
1929     exit (2);
1930   }
1931
1932   if (use_resolved && !(bfd_get_file_flags(abs_bfd) & EXEC_P)) {
1933     /* `Absolute' file is not absolute, so neither are address
1934        contained therein.  */
1935     fprintf (stderr,
1936              "%s: `-a' option specified with non-fully-resolved input file\n",
1937              bfd_get_filename (abs_bfd));
1938     exit (2);
1939   }
1940
1941   symbol_table = get_symbols(abs_bfd, &number_of_symbols);
1942
1943   /* Group output sections into text, data, and bss, and calc their sizes.  */
1944   for (s = abs_bfd->sections; s != NULL; s = s->next) {
1945     unsigned long *vma, *len;
1946     bfd_size_type sec_size;
1947     bfd_vma sec_vma;
1948
1949     if (s->flags & SEC_CODE) {
1950       vma = &text_vma;
1951       len = &text_len;
1952     } else if (s->flags & SEC_DATA) {
1953       vma = &data_vma;
1954       len = &data_len;
1955     } else if (s->flags & SEC_ALLOC) {
1956       vma = &bss_vma;
1957       len = &bss_len;
1958     } else
1959       continue;
1960
1961     sec_size = bfd_section_size(abs_bfd, s);
1962     sec_vma  = bfd_section_vma(abs_bfd, s);
1963
1964     if (sec_vma < *vma) {
1965       if (*len > 0)
1966         *len += sec_vma - *vma;
1967       else
1968         *len = sec_size;
1969       *vma = sec_vma;
1970     } else if (sec_vma + sec_size > *vma + *len)
1971       *len = sec_vma + sec_size - *vma;
1972   }
1973
1974   if (text_len == 0) {
1975     fprintf (stderr, "%s: no .text section", abs_file);
1976     exit (2);
1977   }
1978
1979   text = xmalloc(text_len);
1980
1981   if (verbose)
1982     printf("TEXT -> vma=0x%x len=0x%x\n", text_vma, text_len);
1983
1984   /* Read in all text sections.  */
1985   for (s = abs_bfd->sections; s != NULL; s = s->next)
1986     if (s->flags & SEC_CODE) 
1987       if (!bfd_get_section_contents(abs_bfd, s,
1988                                    text + (s->vma - text_vma), 0,
1989                                    bfd_section_size(abs_bfd, s)))
1990       {
1991         fprintf(stderr, "read error section %s\n", s->name);
1992         exit(2);
1993       }
1994
1995   if (data_len == 0) {
1996     fprintf (stderr, "%s: no .data section", abs_file);
1997     exit (2);
1998   }
1999   data = xmalloc(data_len);
2000
2001   if (verbose)
2002     printf("DATA -> vma=0x%x len=0x%x\n", data_vma, data_len);
2003
2004   if ((text_vma + text_len) != data_vma) {
2005     if ((text_vma + text_len) > data_vma) {
2006       printf("ERROR: text=0x%x overlaps data=0x%x ?\n", text_len, data_vma);
2007       exit(1);
2008     }
2009     if (verbose)
2010       printf("WARNING: data=0x%x does not directly follow text=0x%x\n",
2011                         data_vma, text_len);
2012     text_len = data_vma - text_vma;
2013   }
2014
2015   /* Read in all data sections.  */
2016   for (s = abs_bfd->sections; s != NULL; s = s->next)
2017     if (s->flags & SEC_DATA) 
2018       if (!bfd_get_section_contents(abs_bfd, s,
2019                                    data + (s->vma - data_vma), 0,
2020                                    bfd_section_size(abs_bfd, s)))
2021       {
2022         fprintf(stderr, "read error section %s\n", s->name);
2023         exit(2);
2024       }
2025
2026   /* Put common symbols in bss.  */
2027   bss_len += add_com_to_bss(symbol_table, number_of_symbols, bss_len);
2028
2029   if (verbose)
2030     printf("BSS  -> vma=0x%x len=0x%x\n", bss_vma, bss_len);
2031
2032   if ((data_vma + data_len) != bss_vma) {
2033     if ((data_vma + data_len) > bss_vma) {
2034       printf("ERROR: text=0x%x + data=0x%x overlaps bss=0x%x ?\n", text_len,
2035                         data_len, bss_vma);
2036       exit(1);
2037     }
2038     if (verbose)
2039       printf("WARNING: bss=0x%x does not directly follow text=0x%x + data=0x%x(0x%x)\n",
2040                 bss_vma, text_len, data_len, text_len + data_len);
2041     data_len = bss_vma - data_vma;
2042   }
2043
2044   reloc = output_relocs(abs_bfd, symbol_table, number_of_symbols, &reloc_len,
2045                         text, text_len, text_vma, data, data_len, data_vma,
2046                         rel_bfd);
2047
2048   if (reloc == NULL)
2049     printf("No relocations in code!\n");
2050
2051   text_offs = real_address_bits(text_vma);
2052
2053   /* Fill in the binflt_flat header */
2054   memcpy(hdr.magic,"bFLT",4);
2055   hdr.rev         = htonl(FLAT_VERSION);
2056   hdr.entry       = htonl(sizeof(hdr) + bfd_get_start_address(abs_bfd));
2057   hdr.data_start  = htonl(sizeof(hdr) + text_offs + text_len);
2058   hdr.data_end    = htonl(sizeof(hdr) + text_offs + text_len +data_len);
2059   hdr.bss_end     = htonl(sizeof(hdr) + text_offs + text_len +data_len+bss_len);
2060   hdr.stack_size  = htonl(stack); /* FIXME */
2061   hdr.reloc_start = htonl(sizeof(hdr) + text_offs + text_len +data_len);
2062   hdr.reloc_count = htonl(reloc_len);
2063   hdr.flags       = htonl(0
2064           | (load_to_ram ? FLAT_FLAG_RAM : 0)
2065           | (ktrace ? FLAT_FLAG_KTRACE : 0)
2066           | (pic_with_got ? FLAT_FLAG_GOTPIC : 0)
2067           | (compress ? (compress == 2 ? FLAT_FLAG_GZDATA : FLAT_FLAG_GZIP) : 0)
2068           );
2069   hdr.build_date = htonl((unsigned long)time(NULL));
2070   memset(hdr.filler, 0x00, sizeof(hdr.filler));
2071
2072   for (i=0; i<reloc_len; i++) reloc[i] = htonl(reloc[i]);
2073
2074   if (verbose) {
2075     printf("SIZE: .text=0x%04x, .data=0x%04x, .bss=0x%04x",
2076         text_len, data_len, bss_len);
2077     if (reloc)
2078       printf(", relocs=0x%04x", reloc_len);
2079     printf("\n");
2080   }
2081   
2082   if (!ofile) {
2083     ofile = xmalloc(strlen(fname) + 5 + 1); /* 5 to add suffix */
2084     strcpy(ofile, fname);
2085     strcat(ofile, ".bflt");
2086   }
2087
2088   if ((fd = open (ofile, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0744)) < 0) {
2089     fprintf (stderr, "Can't open output file %s\n", ofile);
2090     exit(4);
2091   }
2092
2093   write(fd, &hdr, sizeof(hdr));
2094   close(fd);
2095
2096   /*
2097    * get the compression command ready
2098    */
2099   sprintf(cmd, "gzip -f -9 >> %s", ofile);
2100
2101 #define START_COMPRESSOR do { \
2102                 if (gf) \
2103                         if (gf_is_pipe) \
2104                                 pclose(gf); \
2105                         else \
2106                                 fclose(gf); \
2107                 if (!(gf = popen(cmd, "w" BINARY_FILE_OPTS))) { \
2108                         fprintf(stderr, "Can't run cmd %s\n", cmd); \
2109                         exit(4); \
2110                 } \
2111                 gf_is_pipe = 1; \
2112         } while (0)
2113
2114   gf = fopen(ofile, "ab");      /* Add 'b' to support non-posix (ie windows) */
2115   if (!gf) {
2116         fprintf(stderr, "Can't open file %s for writing\n", ofile); \
2117         exit(4);
2118   }
2119
2120   if (compress == 1)
2121         START_COMPRESSOR;
2122
2123   /* Fill in any hole at the beginning of the text segment.  */
2124   if (verbose)
2125           printf("ZERO before text len=0x%x\n", text_offs);
2126   write_zeroes(text_offs, gf);
2127
2128   /* Write the text segment.  */
2129   fwrite(text, text_len, 1, gf);
2130
2131   if (compress == 2)
2132         START_COMPRESSOR;
2133
2134   /* Write the data segment.  */
2135   fwrite(data, data_len, 1, gf);
2136
2137   if (reloc)
2138     fwrite(reloc, reloc_len * 4, 1, gf);
2139
2140   if(gf_is_pipe)
2141     pclose(gf);
2142   else
2143   fclose(gf);
2144
2145   exit(0);
2146 }
2147
2148
2149 /*
2150  * this __MUST__ be at the VERY end of the file - do NOT move!!
2151  *
2152  * Local Variables:
2153  * c-basic-offset: 4
2154  * tab-width: 8
2155  * end:
2156  * vi: tabstop=8 shiftwidth=4 textwidth=79 noexpandtab
2157  */