OSDN Git Service

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