OSDN Git Service

048e424dba16b6cf83e29c9205550e851619a080
[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                                 {       
788                                         unsigned char *p = r_mem;
789                                         unsigned long offset;
790
791                                         /* grab any offset from the text */
792                                         offset = (p[0]<<24) + (p[1] << 16) + (p[2] << 8) + (p[3]);
793                                         //sym_addr = (*(q->sym_ptr_ptr))->value;
794                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
795                                         sym_addr += offset + sym_vma + q->addend;
796
797                                         relocation_needed = 1;
798                                         break;
799                                 }
800                                 case R_MICROBLAZE_64_PCREL:
801                                         sym_vma = 0;
802                                         //sym_addr = (*(q->sym_ptr_ptr))->value;
803                                         sym_addr += sym_vma + q->addend;
804                                         sym_addr -= (q->address + 4);
805                                         sym_addr = htonl(sym_addr);
806                                         /* insert 16 MSB */
807                                         * ((unsigned short *) (r_mem+2)) |= (sym_addr) & 0xFFFF;
808                                         /* then 16 LSB */
809                                         * ((unsigned short *) (r_mem+6)) |= (sym_addr >> 16) & 0xFFFF;
810                                         /* We've done all the work, so continue
811                                            to next reloc instead of break */
812                                         continue;
813
814 #endif /* TARGET_microblaze */
815                                         
816 #ifdef TARGET_sparc
817                                 case R_SPARC_32:
818                                 case R_SPARC_UA32:
819                                         relocation_needed = 1;
820                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
821                                         sym_addr += sym_vma + q->addend;
822                                         break;
823                                 case R_SPARC_PC22:
824                                         sym_vma = 0;
825                                         sym_addr += sym_vma + q->addend;
826                                         sym_addr -= q->address;
827                                         break;
828                                 case R_SPARC_WDISP30:
829                                         sym_addr = (((*(q->sym_ptr_ptr))->value-
830                                                 q->address) >> 2) & 0x3fffffff;
831                                         sym_addr |= (
832                                                 ntohl(*(unsigned long *)r_mem)
833                                                 & 0xc0000000
834                                                 );
835                                         break;
836                                 case R_SPARC_HI22:
837                                         relocation_needed = 1;
838                                         pflags = 0x80000000;
839                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
840                                         sym_addr += sym_vma + q->addend;
841                                         sym_addr |= (
842                                                 htonl(*(unsigned long *)r_mem)
843                                                 & 0xffc00000
844                                                 );
845                                         break;
846                                 case R_SPARC_LO10:
847                                         relocation_needed = 1;
848                                         pflags = 0x40000000;
849                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
850                                         sym_addr += sym_vma + q->addend;
851                                         sym_addr &= 0x000003ff;
852                                         sym_addr |= (
853                                                 htonl(*(unsigned long *)r_mem)
854                                                 & 0xfffffc00
855                                                 );
856                                         break;
857 #endif /* TARGET_sparc */
858
859 #ifdef TARGET_sh
860                                 case R_SH_DIR32:
861                                         relocation_needed = 1;
862                                         sym_vma = bfd_section_vma(abs_bfd, sym_section);
863                                         sym_addr += sym_vma + q->addend;
864                                         break;
865                                 case R_SH_REL32:
866                                         sym_vma = 0;
867                                         sym_addr += sym_vma + q->addend;
868                                         sym_addr -= q->address;
869                                         break;
870 #endif /* TARGET_sh */
871
872                                 default:
873                                         /* missing support for other types of relocs */
874                                         printf("ERROR: bad reloc type %d\n", (*p)->howto->type);
875                                         bad_relocs++;
876                                         continue;
877                                 }
878                         }
879
880                         sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
881                                          bfd_section_vma(abs_bfd, sym_section));
882
883
884                         /*
885                          * for full elf relocation we have to write back the
886                          * start_code relative value to use.
887                          */
888                         if (!pic_with_got) {
889 #if defined(TARGET_arm)
890                                 union {
891                                         unsigned char c[4];
892                                         unsigned long l;
893                                 } tmp;
894                                 long hl;
895                                 int i0, i1, i2, i3;
896
897                                 /*
898                                  * horrible nasty hack to support different endianess
899                                  */
900                                 if (!bfd_big_endian(abs_bfd)) {
901                                         i0 = 0;
902                                         i1 = 1;
903                                         i2 = 2;
904                                         i3 = 3;
905                                 } else {
906                                         i0 = 3;
907                                         i1 = 2;
908                                         i2 = 1;
909                                         i3 = 0;
910                                 }
911
912                                 tmp.l = *(unsigned long *)r_mem;
913                                 hl = tmp.c[i0] | (tmp.c[i1] << 8) | (tmp.c[i2] << 16);
914                                 if (((*p)->howto->type != R_ARM_PC24) &&
915                                     ((*p)->howto->type != R_ARM_PLT32))
916                                         hl |= (tmp.c[i3] << 24);
917                                 else if (tmp.c[i2] & 0x80)
918                                         hl |= 0xff000000; /* sign extend */
919                                 hl += sym_addr;
920                                 tmp.c[i0] = hl & 0xff;
921                                 tmp.c[i1] = (hl >> 8) & 0xff;
922                                 tmp.c[i2] = (hl >> 16) & 0xff;
923                                 if (((*p)->howto->type != R_ARM_PC24) &&
924                                     ((*p)->howto->type != R_ARM_PLT32))
925                                         tmp.c[i3] = (hl >> 24) & 0xff;
926                                 if ((*p)->howto->type == R_ARM_ABS32)
927                                         *(unsigned long *)r_mem = htonl(hl);
928                                 else
929                                         *(unsigned long *)r_mem = tmp.l;
930
931 #else /* ! TARGET_arm */
932
933                                 switch (q->howto->type) {
934 #ifdef TARGET_v850
935                                 case R_V850_HI16_S:
936                                 case R_V850_HI16:
937                                 case R_V850_LO16:
938                                         /* Do nothing -- for cases we handle,
939                                            the bits produced by the linker are
940                                            what we want in the final flat file
941                                            (and other cases are errors).  Note
942                                            that unlike most relocated values,
943                                            it is stored in little-endian order,
944                                            but this is necessary to avoid
945                                            trashing the low-bit, and the float
946                                            loaders knows about it.  */
947                                         break;
948 #endif /* TARGET_V850 */
949                                 default:
950                                         /* The alignment of the build host
951                                            might be stricter than that of the
952                                            target, so be careful.  We store in
953                                            network byte order. */
954                                         r_mem[0] = (sym_addr >> 24) & 0xff;
955                                         r_mem[1] = (sym_addr >> 16) & 0xff;
956                                         r_mem[2] = (sym_addr >>  8) & 0xff;
957                                         r_mem[3] =  sym_addr        & 0xff;
958                                 }
959 #endif /* !TARGET_arm */
960                         }
961
962                         if (verbose)
963                                 printf("  RELOC[%d]: offset=0x%x symbol=%s%s "
964                                         "section=%s size=%d "
965                                         "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
966                                         q->address, sym_name, addstr,
967                                         section_name, sym_reloc_size,
968                                         sym_addr, section_vma + q->address);
969
970                         /*
971                          *      Create relocation entry (PC relative doesn't need this).
972                          */
973                         if (relocation_needed) {
974                                 flat_relocs = realloc(flat_relocs,
975                                         (flat_reloc_count + 1) * sizeof(unsigned long));
976                                 flat_relocs[flat_reloc_count] = pflags |
977                                         (section_vma + q->address);
978
979                                 if (verbose)
980                                         printf("reloc[%d] = 0x%x\n", flat_reloc_count,
981                                                         section_vma + q->address);
982                                 flat_reloc_count++;
983                                 relocation_needed = 0;
984                                 pflags = 0;
985                         }
986
987 #if 0
988 printf("%s(%d): symbol name=%s address=0x%x section=%s -> RELOC=0x%x\n",
989         __FILE__, __LINE__, sym_name, q->address, section_name,
990         flat_relocs[flat_reloc_count]);
991 #endif
992                 }
993         }
994   }
995
996   if (bad_relocs) {
997           printf("%d bad relocs\n", bad_relocs);
998           exit(1);
999   }
1000
1001   if (rc < 0)
1002         return(0);
1003
1004   *n_relocs = flat_reloc_count;
1005   return flat_relocs;
1006 }
1007
1008
1009
1010 #if 0
1011 /* shared lib symbols stuff */
1012
1013 long
1014 get_symbol(char *name, asection *sec, asymbol **symbol_table, long number_of_symbols)
1015 {
1016   long i;
1017   for (i=0; i<number_of_symbols; i++) {
1018     if (symbol_table[i]->section == sec) {
1019       if (!strcmp(symbol_table[i]->name, name)) {
1020         return symbol_table[i]->value;
1021       }
1022     }
1023   }
1024   return -1;
1025 }  
1026
1027 int
1028 output_offset_table(int fd, char *ename, bfd *abfd, asymbol **symbol_table, long number_of_symbols)
1029 {
1030   long i;
1031   FILE *ef;
1032   char buf[80];
1033   char libname[80];
1034   long etext_addr;
1035   long sym_addr;
1036
1037   int foobar = 0;
1038   int count = 0;
1039   signed short *tab = malloc(32768); /* we don't know how many yet*/
1040
1041   asection *text_section = bfd_get_section_by_name (abfd, ".text");
1042
1043   if (!(ef = fopen(ename, "r"))) {
1044     fprintf (stderr,"Can't open %s\n",ename);
1045     exit(1);
1046   }
1047
1048   fgets(libname, 80, ef);
1049
1050   if (number_of_symbols < 0) {
1051     fprintf (stderr,"Corrupt symbol table!\n");
1052     exit(1);
1053   }
1054
1055   if ((etext_addr = get_symbol("etext",
1056                                text_section,
1057                                symbol_table,
1058                                number_of_symbols)) == -1) {
1059     fprintf (stderr,"Can't find the symbol etext\n");
1060     exit(1);
1061   }
1062
1063   fgets(buf, 80, ef);
1064   while (!feof(ef)) {
1065     buf[strlen(buf)-1] = 0; /* Arrrgh! linefeeds */
1066
1067     if ((sym_addr = get_symbol(buf,
1068                                text_section,
1069                                symbol_table,
1070                                number_of_symbols)) == -1) {
1071       fprintf (stderr,"Can't find the symbol %s\n",buf);
1072       foobar++;
1073     } else {
1074       tab[++count] = htons(sym_addr - etext_addr);
1075     }
1076     fgets(buf, 80, ef);
1077   }
1078
1079   fclose(ef);
1080
1081   if (foobar) {
1082     fprintf (stderr,"*** %d symbols not found\n",foobar);
1083     exit(10);
1084   }
1085
1086   strcpy((char *)&tab[++count],libname);
1087   tab[0] = htons(count * 2);
1088   write(fd, tab, count * 2 + strlen(libname) + 2);
1089   return 0;
1090 }
1091 #endif
1092
1093
1094 static char * program;
1095
1096 static void usage(void)
1097 {  
1098     fprintf(stderr, "Usage: %s [vrzd] [-p <abs-pic-file>] [-s stack-size] "
1099         "[-o <output-file>] <elf-file>\n\n"
1100         "       -v              : verbose operation\n"
1101         "       -r              : force load to RAM\n"
1102         "       -k              : enable kernel trace on load (for debug)\n"
1103         "       -z              : compress code/data/relocs\n"
1104         "       -d              : compress data/relocs\n"
1105         "       -a              : use existing symbol references\n"
1106         "                         instead of recalculating from\n"
1107         "                         relocation info\n"
1108         "       -R reloc-file   : read relocations from a separate file\n"
1109         "       -p abs-pic-file : GOT/PIC processing with files\n"
1110         "       -s stacksize    : set application stack size\n"
1111         "       -o output-file  : output file name\n\n",
1112         program);
1113         fprintf(stderr, "Compiled for " ARCH " architecture\n\n");
1114     exit(2);
1115 }
1116
1117
1118 /* Write NUM zeroes to STREAM.  */
1119 static void write_zeroes (unsigned long num, FILE *stream)
1120 {
1121   char zeroes[1024];
1122   if (num > 0) {
1123     /* It'd be nice if we could just use fseek, but that doesn't seem to
1124        work for stdio output files.  */
1125     bzero(zeroes, 1024);
1126     while (num > sizeof(zeroes)) {
1127       fwrite(zeroes, sizeof(zeroes), 1, stream);
1128       num -= sizeof(zeroes);
1129     }
1130     if (num > 0)
1131       fwrite(zeroes, num, 1, stream);
1132   }
1133 }
1134
1135
1136 int main(int argc, char *argv[])
1137 {
1138   int fd;
1139   bfd *rel_bfd, *abs_bfd;
1140   asection *s;
1141   char *ofile=NULL, *pfile=NULL, *abs_file = NULL, *rel_file = NULL;
1142   char *fname = NULL;
1143   int opt;
1144   int i;
1145   int stack;
1146   char  cmd[1024];
1147   FILE *gf = NULL;
1148
1149
1150   asymbol **symbol_table;
1151   long number_of_symbols;
1152
1153   unsigned long data_len = 0;
1154   unsigned long bss_len = 0;
1155   unsigned long text_len = 0;
1156   unsigned long reloc_len;
1157
1158   unsigned long data_vma = ~0;
1159   unsigned long bss_vma = ~0;
1160   unsigned long text_vma = ~0;
1161
1162   unsigned long text_offs;
1163
1164   void *text;
1165   void *data;
1166   unsigned long *reloc;
1167   
1168   struct flat_hdr hdr;
1169
1170
1171   program = argv[0];
1172   progname = argv[0];
1173
1174   if (argc < 2)
1175         usage();
1176   
1177   stack = 4096;
1178
1179   while ((opt = getopt(argc, argv, "avzdrkp:s:o:R:")) != -1) {
1180     switch (opt) {
1181     case 'v':
1182       verbose++;
1183       break;
1184     case 'r':
1185       load_to_ram++;
1186       break;
1187     case 'k':
1188       ktrace++;
1189       break;
1190     case 'z':
1191       compress = 1;
1192       break;
1193     case 'd':
1194       compress = 2;
1195       break;
1196     case 'p':
1197       pfile = optarg;
1198       break;
1199     case 'o':
1200       ofile = optarg;
1201       break;
1202     case 'a':
1203       use_resolved = 1;
1204       break;
1205     case 's':
1206       stack = atoi(optarg);
1207       break;
1208     case 'R':
1209       rel_file = optarg;
1210       break;
1211     default:
1212       fprintf(stderr, "%s Unknown option\n", argv[0]);
1213       usage();
1214       break;
1215     }
1216   }
1217   
1218   /*
1219    * if neither the -r or -p options was given,  default to
1220    * a RAM load as that is the only option that makes sense.
1221    */
1222   if (!load_to_ram && !pfile)
1223     load_to_ram = 1;
1224
1225   filename = fname = argv[argc-1];
1226
1227   if (pfile) {
1228     pic_with_got = 1;
1229     abs_file = pfile;
1230   } else
1231     abs_file = fname;
1232
1233   if (! rel_file)
1234     rel_file = fname;
1235
1236   if (!(rel_bfd = bfd_openr(rel_file, 0))) {
1237     fprintf(stderr, "Can't open %s\n", rel_file);
1238     exit(1);
1239   }
1240
1241   if (bfd_check_format (rel_bfd, bfd_object) == 0) {
1242     fprintf(stderr, "File is not an object file\n");
1243     exit(2);
1244   }
1245
1246   if (abs_file == rel_file)
1247     abs_bfd = rel_bfd; /* one file does all */
1248   else {
1249     if (!(abs_bfd = bfd_openr(abs_file, 0))) {
1250       fprintf(stderr, "Can't open %s\n", abs_file);
1251       exit(1);
1252     }
1253
1254     if (bfd_check_format (abs_bfd, bfd_object) == 0) {
1255       fprintf(stderr, "File is not an object file\n");
1256       exit(2);
1257     }
1258   }
1259
1260   if (! (bfd_get_file_flags(rel_bfd) & HAS_RELOC)) {
1261     fprintf (stderr, "%s: Input file contains no relocation info\n", rel_file);
1262     exit (2);
1263   }
1264
1265   if (use_resolved && !(bfd_get_file_flags(abs_bfd) & EXEC_P)) {
1266     /* `Absolute' file is not absolute, so neither are address
1267        contained therein.  */
1268     fprintf (stderr,
1269              "%s: `-a' option specified with non-fully-resolved input file\n",
1270              bfd_get_filename (abs_bfd));
1271     exit (2);
1272   }
1273
1274   symbol_table = get_symbols(abs_bfd, &number_of_symbols);
1275
1276   /* Group output sections into text, data, and bss, and calc their sizes.  */
1277   for (s = abs_bfd->sections; s != NULL; s = s->next) {
1278     unsigned long *vma, *len;
1279
1280     if (s->flags & SEC_CODE) {
1281       vma = &text_vma;
1282       len = &text_len;
1283     } else if (s->flags & SEC_DATA) {
1284       vma = &data_vma;
1285       len = &data_len;
1286     } else if (s->flags & SEC_ALLOC) {
1287       vma = &bss_vma;
1288       len = &bss_len;
1289     } else
1290       continue;
1291
1292     if (s->vma < *vma) {
1293       if (*len > 0)
1294         *len += s->vma - *vma;
1295       else
1296         *len = s->_raw_size;
1297       *vma = s->vma;
1298     } else if (s->vma + s->_raw_size > *vma + *len)
1299       *len = s->vma + s->_raw_size - *vma;
1300   }
1301
1302   if (text_len == 0) {
1303     fprintf (stderr, "%s: no .text section", abs_file);
1304     exit (2);
1305   }
1306
1307   text = malloc(text_len);
1308
1309   if (verbose)
1310     printf("TEXT -> vma=0x%x len=0x%x\n", text_vma, text_len);
1311
1312   /* Read in all text sections.  */
1313   for (s = abs_bfd->sections; s != NULL; s = s->next)
1314     if (s->flags & SEC_CODE) 
1315       if (!bfd_get_section_contents(abs_bfd, s,
1316                                    text + (s->vma - text_vma), 0,
1317                                    s->_raw_size))
1318       {
1319         fprintf(stderr, "read error section %s\n", s->name);
1320         exit(2);
1321       }
1322
1323   if (data_len == 0) {
1324     fprintf (stderr, "%s: no .data section", abs_file);
1325     exit (2);
1326   }
1327   data = malloc(data_len);
1328
1329   if (verbose)
1330     printf("DATA -> vma=0x%x len=0x%x\n", data_vma, data_len);
1331
1332   if ((text_vma + text_len) != data_vma) {
1333     if ((text_vma + text_len) > data_vma) {
1334       printf("ERROR: text=0x%x overlaps data=0x%x ?\n", text_len, data_vma);
1335       exit(1);
1336     }
1337     if (verbose)
1338       printf("WARNING: data=0x%x does not directly follow text=0x%x\n",
1339                         data_vma, text_len);
1340     text_len = data_vma - text_vma;
1341   }
1342
1343   /* Read in all data sections.  */
1344   for (s = abs_bfd->sections; s != NULL; s = s->next)
1345     if (s->flags & SEC_DATA) 
1346       if (!bfd_get_section_contents(abs_bfd, s,
1347                                    data + (s->vma - data_vma), 0,
1348                                    s->_raw_size))
1349       {
1350         fprintf(stderr, "read error section %s\n", s->name);
1351         exit(2);
1352       }
1353
1354   /* Put common symbols in bss.  */
1355   bss_len += add_com_to_bss(symbol_table, number_of_symbols, bss_len);
1356
1357   if (verbose)
1358     printf("BSS  -> vma=0x%x len=0x%x\n", bss_vma, bss_len);
1359
1360   if ((data_vma + data_len) != bss_vma) {
1361     if ((data_vma + data_len) > bss_vma) {
1362       printf("ERROR: text=0x%x + data=0x%x overlaps bss=0x%x ?\n", text_len,
1363                         data_len, bss_vma);
1364       exit(1);
1365     }
1366     if (verbose)
1367       printf("WARNING: bss=0x%x does not directly follow text=0x%x + data=0x%x(0x%x)\n",
1368                 bss_vma, text_len, data_len, text_len + data_len);
1369     data_len = bss_vma - data_vma;
1370   }
1371
1372   reloc = (unsigned long *)
1373     output_relocs(abs_bfd, symbol_table, number_of_symbols, &reloc_len,
1374                   text, text_len, text_vma, data, data_len, data_vma, rel_bfd);
1375
1376   if (reloc == NULL)
1377     printf("No relocations in code!\n");
1378
1379   text_offs = real_address_bits(text_vma);
1380
1381   /* Fill in the binflt_flat header */
1382   memcpy(hdr.magic,"bFLT",4);
1383   hdr.rev         = htonl(FLAT_VERSION);
1384   hdr.entry       = htonl(16 * 4 + bfd_get_start_address(abs_bfd));
1385   hdr.data_start  = htonl(16 * 4 + text_offs + text_len);
1386   hdr.data_end    = htonl(16 * 4 + text_offs + text_len + data_len);
1387   hdr.bss_end     = htonl(16 * 4 + text_offs + text_len + data_len + bss_len);
1388   hdr.stack_size  = htonl(stack); /* FIXME */
1389   hdr.reloc_start = htonl(16 * 4 + text_offs + text_len + data_len);
1390   hdr.reloc_count = htonl(reloc_len);
1391   hdr.flags       = htonl(0
1392           | (load_to_ram ? FLAT_FLAG_RAM : 0)
1393           | (ktrace ? FLAT_FLAG_KTRACE : 0)
1394           | (pic_with_got ? FLAT_FLAG_GOTPIC : 0)
1395           | (compress ? (compress == 2 ? FLAT_FLAG_GZDATA : FLAT_FLAG_GZIP) : 0)
1396           );
1397   hdr.build_date = htonl((unsigned long)time(NULL));
1398   bzero(hdr.filler, sizeof(hdr.filler));
1399
1400   for (i=0; i<reloc_len; i++) reloc[i] = htonl(reloc[i]);
1401
1402   if (verbose) {
1403     printf("SIZE: .text=0x%04x, .data=0x%04x, .bss=0x%04x",
1404         text_len, data_len, bss_len);
1405     if (reloc)
1406       printf(", relocs=0x%04x", reloc_len);
1407     printf("\n");
1408   }
1409   
1410   if (!ofile) {
1411     ofile = malloc(strlen(fname) + 5 + 1); /* 5 to add suffix */
1412     strcpy(ofile, fname);
1413     strcat(ofile, ".bflt");
1414   }
1415
1416   if ((fd = open (ofile, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0744)) < 0) {
1417     fprintf (stderr, "Can't open output file %s\n", ofile);
1418     exit(4);
1419   }
1420
1421   write(fd, &hdr, sizeof(hdr));
1422   close(fd);
1423
1424   /*
1425    * get the compression command ready
1426    */
1427   sprintf(cmd, "gzip -f -9 >> %s", ofile);
1428
1429 #define START_COMPRESSOR do { \
1430                 if (gf) fclose(gf); \
1431                 if (!(gf = popen(cmd, "w"))) { \
1432                         fprintf(stderr, "Can't run cmd %s\n", cmd); \
1433                         exit(4); \
1434                 } \
1435         } while (0)
1436
1437   gf = fopen(ofile, "a");
1438   if (!gf) {
1439         fprintf(stderr, "Can't opne file %s for writing\n", ofile); \
1440         exit(4);
1441   }
1442
1443   if (compress == 1)
1444         START_COMPRESSOR;
1445
1446   /* Fill in any hole at the beginning of the text segment.  */
1447   if (verbose)
1448           printf("ZERO before text len=0x%x\n", text_offs);
1449   write_zeroes(text_offs, gf);
1450
1451   /* Write the text segment.  */
1452   fwrite(text, text_len, 1, gf);
1453
1454   if (compress == 2)
1455         START_COMPRESSOR;
1456
1457   /* Write the data segment.  */
1458   fwrite(data, data_len, 1, gf);
1459
1460   if (reloc)
1461     fwrite(reloc, reloc_len * 4, 1, gf);
1462
1463   fclose(gf);
1464
1465   exit(0);
1466 }