OSDN Git Service

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