OSDN Git Service

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