OSDN Git Service

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