Import gdb-7.0
[dragonfly.git] / contrib / gdb-6 / bfd / tekhex.c
1 /* BFD backend for Extended Tektronix Hex Format  objects.
2    Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002,
3    2003, 2004, 2007 Free Software Foundation, Inc.
4    Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
5
6    This file is part of BFD, the Binary File Descriptor library.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21    MA 02110-1301, USA.  */
22
23
24 /* SUBSECTION
25         Tektronix Hex Format handling
26
27    DESCRIPTION
28
29         Tek Hex records can hold symbols and data, but not
30         relocations. Their main application is communication with
31         devices like PROM programmers and ICE equipment.
32
33         It seems that the sections are described as being really big,
34         the example I have says that the text section is 0..ffffffff.
35         BFD would barf with this, many apps would try to alloc 4GB to
36         read in the file.
37
38         Tex Hex may contain many sections, but the data which comes in
39         has no tag saying which section it belongs to, so we create
40         one section for each block of data, called "blknnnn" which we
41         stick all the data into.
42
43         TekHex may come out of  order and there is no header, so an
44         initial scan is required  to discover the minimum and maximum
45         addresses used to create the vma and size of the sections we
46         create.
47         We read in the data into pages of CHUNK_MASK+1 size and read
48         them out from that whenever we need to.
49
50         Any number of sections may be created for output, we save them
51         up and output them when it's time to close the bfd.
52
53         A TekHex record looks like:
54   EXAMPLE
55         %<block length><type><checksum><stuff><cr>
56
57   DESCRIPTION
58         Where
59         o length
60         is the number of bytes in the record not including the % sign.
61         o type
62         is one of:
63         3) symbol record
64         6) data record
65         8) termination record
66
67   The data can come out of order, and may be discontigous. This is a
68   serial protocol, so big files are unlikely, so we keep a list of 8k chunks.  */
69
70 #include "sysdep.h"
71 #include "bfd.h"
72 #include "libbfd.h"
73 #include "libiberty.h"
74
75 typedef struct
76 {
77   bfd_vma low;
78   bfd_vma high;
79 } addr_range_type;
80
81 typedef struct tekhex_symbol_struct
82 {
83   asymbol symbol;
84   struct tekhex_symbol_struct *prev;
85 } tekhex_symbol_type;
86
87 static const char digs[] = "0123456789ABCDEF";
88
89 static char sum_block[256];
90
91 #define NOT_HEX      20
92 #define NIBBLE(x)    hex_value(x)
93 #define HEX(buffer) ((NIBBLE ((buffer)[0]) << 4) + NIBBLE ((buffer)[1]))
94 #define ISHEX(x)    hex_p(x)
95 #define TOHEX(d, x) \
96   (d)[1] = digs[(x) & 0xf]; \
97   (d)[0] = digs[((x)>>4)&0xf];
98
99 /* Here's an example
100    %3A6C6480004E56FFFC4E717063B0AEFFFC6D0652AEFFFC60F24E5E4E75
101    %1B3709T_SEGMENT1108FFFFFFFF
102    %2B3AB9T_SEGMENT7Dgcc_compiled$1087hello$c10
103    %373829T_SEGMENT80int$t1$r1$$214741080char$t2$r2$0$12710
104    %373769T_SEGMENT80long$int$t3$r1$$1080unsigned$int$t4$10
105    %373CA9T_SEGMENT80long$unsigned$in1080short$int$t6$r1$10
106    %373049T_SEGMENT80long$long$int$t71080short$unsigned$i10
107    %373A29T_SEGMENT80long$long$unsign1080signed$char$t10$10
108    %373D69T_SEGMENT80unsigned$char$t11080float$t12$r1$4$010
109    %373D19T_SEGMENT80double$t13$r1$8$1080long$double$t14$10
110    %2734D9T_SEGMENT8Bvoid$t15$151035_main10
111    %2F3CA9T_SEGMENT81$1081$1681$1E81$21487main$F110
112    %2832F9T_SEGMENT83i$18FFFFFFFC81$1481$214
113    %07 8 10 10
114
115    explanation:
116    %3A6C6480004E56FFFC4E717063B0AEFFFC6D0652AEFFFC60F24E5E4E75
117     ^ ^^ ^     ^-data
118     | || +------ 4 char integer 0x8000
119     | |+-------- checksum
120     | +--------- type 6 (data record)
121     +----------- length 3a chars
122    <---------------------- 3a (58 chars) ------------------->
123
124    %1B3709T_SEGMENT1108FFFFFFFF
125          ^         ^^ ^- 8 character integer 0xffffffff
126          |         |+-   1 character integer 0
127          |         +--   type 1 symbol (section definition)
128          +------------   9 char symbol T_SEGMENT
129
130    %2B3AB9T_SEGMENT7Dgcc_compiled$1087hello$c10
131    %373829T_SEGMENT80int$t1$r1$$214741080char$t2$r2$0$12710
132    %373769T_SEGMENT80long$int$t3$r1$$1080unsigned$int$t4$10
133    %373CA9T_SEGMENT80long$unsigned$in1080short$int$t6$r1$10
134    %373049T_SEGMENT80long$long$int$t71080short$unsigned$i10
135    %373A29T_SEGMENT80long$long$unsign1080signed$char$t10$10
136    %373D69T_SEGMENT80unsigned$char$t11080float$t12$r1$4$010
137    %373D19T_SEGMENT80double$t13$r1$8$1080long$double$t14$10
138    %2734D9T_SEGMENT8Bvoid$t15$151035_main10
139    %2F3CA9T_SEGMENT81$1081$1681$1E81$21487main$F110
140    %2832F9T_SEGMENT83i$18FFFFFFFC81$1481$214
141    %0781010
142
143    Turns into
144    sac@thepub$ ./objdump -dx -m m68k f
145
146    f:     file format tekhex
147    -----x--- 9/55728 -134219416 Sep 29 15:13 1995 f
148    architecture: UNKNOWN!, flags 0x00000010:
149    HAS_SYMS
150    start address 0x00000000
151    SECTION 0 [D00000000]        : size 00020000 vma 00000000 align 2**0
152    ALLOC, LOAD
153    SECTION 1 [D00008000]        : size 00002001 vma 00008000 align 2**0
154
155    SECTION 2 [T_SEGMENT]        : size ffffffff vma 00000000 align 2**0
156
157    SYMBOL TABLE:
158    00000000  g       T_SEGMENT gcc_compiled$
159    00000000  g       T_SEGMENT hello$c
160    00000000  g       T_SEGMENT int$t1$r1$$21474
161    00000000  g       T_SEGMENT char$t2$r2$0$127
162    00000000  g       T_SEGMENT long$int$t3$r1$$
163    00000000  g       T_SEGMENT unsigned$int$t4$
164    00000000  g       T_SEGMENT long$unsigned$in
165    00000000  g       T_SEGMENT short$int$t6$r1$
166    00000000  g       T_SEGMENT long$long$int$t7
167    00000000  g       T_SEGMENT short$unsigned$i
168    00000000  g       T_SEGMENT long$long$unsign
169    00000000  g       T_SEGMENT signed$char$t10$
170    00000000  g       T_SEGMENT unsigned$char$t1
171    00000000  g       T_SEGMENT float$t12$r1$4$0
172    00000000  g       T_SEGMENT double$t13$r1$8$
173    00000000  g       T_SEGMENT long$double$t14$
174    00000000  g       T_SEGMENT void$t15$15
175    00000000  g       T_SEGMENT _main
176    00000000  g       T_SEGMENT $
177    00000000  g       T_SEGMENT $
178    00000000  g       T_SEGMENT $
179    00000010  g       T_SEGMENT $
180    00000000  g       T_SEGMENT main$F1
181    fcffffff  g       T_SEGMENT i$1
182    00000000  g       T_SEGMENT $
183    00000010  g       T_SEGMENT $
184
185    RELOCATION RECORDS FOR [D00000000]: (none)
186
187    RELOCATION RECORDS FOR [D00008000]: (none)
188
189    RELOCATION RECORDS FOR [T_SEGMENT]: (none)
190
191    Disassembly of section D00000000:
192    ...
193    00008000 ($+)7ff0 linkw fp,#-4
194    00008004 ($+)7ff4 nop
195    00008006 ($+)7ff6 movel #99,d0
196    00008008 ($+)7ff8 cmpl fp@(-4),d0
197    0000800c ($+)7ffc blts 00008014 ($+)8004
198    0000800e ($+)7ffe addql #1,fp@(-4)
199    00008012 ($+)8002 bras 00008006 ($+)7ff6
200    00008014 ($+)8004 unlk fp
201    00008016 ($+)8006 rts
202    ...  */
203
204 static void
205 tekhex_init (void)
206 {
207   unsigned int i;
208   static bfd_boolean inited = FALSE;
209   int val;
210
211   if (! inited)
212     {
213       inited = TRUE;
214       hex_init ();
215       val = 0;
216       for (i = 0; i < 10; i++)
217         sum_block[i + '0'] = val++;
218
219       for (i = 'A'; i <= 'Z'; i++)
220         sum_block[i] = val++;
221
222       sum_block['$'] = val++;
223       sum_block['%'] = val++;
224       sum_block['.'] = val++;
225       sum_block['_'] = val++;
226       for (i = 'a'; i <= 'z'; i++)
227         sum_block[i] = val++;
228     }
229 }
230
231 /* The maximum number of bytes on a line is FF.  */
232 #define MAXCHUNK 0xff
233 /* The number of bytes we fit onto a line on output.  */
234 #define CHUNK 21
235
236 /* We cannot output our tekhexords as we see them, we have to glue them
237    together, this is done in this structure : */
238
239 struct tekhex_data_list_struct
240 {
241   unsigned char *data;
242   bfd_vma where;
243   bfd_size_type size;
244   struct tekhex_data_list_struct *next;
245
246 };
247 typedef struct tekhex_data_list_struct tekhex_data_list_type;
248
249 #define CHUNK_MASK 0x1fff
250
251 struct data_struct
252 {
253   char chunk_data[CHUNK_MASK + 1];
254   char chunk_init[CHUNK_MASK + 1];
255   bfd_vma vma;
256   struct data_struct *next;
257 };
258
259 typedef struct tekhex_data_struct
260 {
261   tekhex_data_list_type *head;
262   unsigned int type;
263   struct tekhex_symbol_struct *symbols;
264   struct data_struct *data;
265 } tdata_type;
266
267 #define enda(x) (x->vma + x->size)
268
269 static bfd_boolean
270 getvalue (char **srcp, bfd_vma *valuep)
271 {
272   char *src = *srcp;
273   bfd_vma value = 0;
274   unsigned int len;
275
276   if (!ISHEX (*src))
277     return FALSE;
278
279   len = hex_value (*src++);
280   if (len == 0)
281     len = 16;
282   while (len--)
283     {
284       if (!ISHEX (*src))
285         return FALSE;
286       value = value << 4 | hex_value (*src++);
287     }
288
289   *srcp = src;
290   *valuep = value;
291   return TRUE;
292 }
293
294 static bfd_boolean
295 getsym (char *dstp, char **srcp, unsigned int *lenp)
296 {
297   char *src = *srcp;
298   unsigned int i;
299   unsigned int len;
300   
301   if (!ISHEX (*src))
302     return FALSE;
303
304   len = hex_value (*src++);
305   if (len == 0)
306     len = 16;
307   for (i = 0; i < len; i++)
308     dstp[i] = src[i];
309   dstp[i] = 0;
310   *srcp = src + i;
311   *lenp = len;
312   return TRUE;
313 }
314
315 static struct data_struct *
316 find_chunk (bfd *abfd, bfd_vma vma)
317 {
318   struct data_struct *d = abfd->tdata.tekhex_data->data;
319
320   vma &= ~CHUNK_MASK;
321   while (d && (d->vma) != vma)
322     d = d->next;
323
324   if (!d)
325     {
326       /* No chunk for this address, so make one up.  */
327       d = bfd_zalloc (abfd, (bfd_size_type) sizeof (struct data_struct));
328
329       if (!d)
330         return NULL;
331
332       d->next = abfd->tdata.tekhex_data->data;
333       d->vma = vma;
334       abfd->tdata.tekhex_data->data = d;
335     }
336   return d;
337 }
338
339 static void
340 insert_byte (bfd *abfd, int value, bfd_vma addr)
341 {
342   /* Find the chunk that this byte needs and put it in.  */
343   struct data_struct *d = find_chunk (abfd, addr);
344
345   d->chunk_data[addr & CHUNK_MASK] = value;
346   d->chunk_init[addr & CHUNK_MASK] = 1;
347 }
348
349 /* The first pass is to find the names of all the sections, and see
350   how big the data is.  */
351
352 static bfd_boolean
353 first_phase (bfd *abfd, int type, char *src)
354 {
355   asection *section = bfd_abs_section_ptr;
356   unsigned int len;
357   bfd_vma val;
358   char sym[17];                 /* A symbol can only be 16chars long.  */
359
360   switch (type)
361     {
362     case '6':
363       /* Data record - read it and store it.  */
364       {
365         bfd_vma addr;
366
367         if (!getvalue (&src, &addr))
368           return FALSE;
369
370         while (*src)
371           {
372             insert_byte (abfd, HEX (src), addr);
373             src += 2;
374             addr++;
375           }
376       }
377
378       return TRUE;
379     case '3':
380       /* Symbol record, read the segment.  */
381       if (!getsym (sym, &src, &len))
382         return FALSE;
383       section = bfd_get_section_by_name (abfd, sym);
384       if (section == NULL)
385         {
386           char *n = bfd_alloc (abfd, (bfd_size_type) len + 1);
387
388           if (!n)
389             return FALSE;
390           memcpy (n, sym, len + 1);
391           section = bfd_make_section (abfd, n);
392           if (section == NULL)
393             return FALSE;
394         }
395       while (*src)
396         {
397           switch (*src)
398             {
399             case '1':           /* Section range.  */
400               src++;
401               if (!getvalue (&src, &section->vma))
402                 return FALSE;
403               if (!getvalue (&src, &val))
404                 return FALSE;
405               section->size = val - section->vma;
406               section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
407               break;
408             case '0':
409             case '2':
410             case '3':
411             case '4':
412             case '6':
413             case '7':
414             case '8':
415               /* Symbols, add to section.  */
416               {
417                 bfd_size_type amt = sizeof (tekhex_symbol_type);
418                 tekhex_symbol_type *new = bfd_alloc (abfd, amt);
419                 char stype = (*src);
420
421                 if (!new)
422                   return FALSE;
423                 new->symbol.the_bfd = abfd;
424                 src++;
425                 abfd->symcount++;
426                 abfd->flags |= HAS_SYMS;
427                 new->prev = abfd->tdata.tekhex_data->symbols;
428                 abfd->tdata.tekhex_data->symbols = new;
429                 if (!getsym (sym, &src, &len))
430                   return FALSE;
431                 new->symbol.name = bfd_alloc (abfd, (bfd_size_type) len + 1);
432                 if (!new->symbol.name)
433                   return FALSE;
434                 memcpy ((char *) (new->symbol.name), sym, len + 1);
435                 new->symbol.section = section;
436                 if (stype <= '4')
437                   new->symbol.flags = (BSF_GLOBAL | BSF_EXPORT);
438                 else
439                   new->symbol.flags = BSF_LOCAL;
440                 if (!getvalue (&src, &val))
441                   return FALSE;
442                 new->symbol.value = val - section->vma;
443                 break;
444               }
445             default:
446               return FALSE;
447             }
448         }
449     }
450
451   return TRUE;
452 }
453
454 /* Pass over a tekhex, calling one of the above functions on each
455    record.  */
456
457 static bfd_boolean
458 pass_over (bfd *abfd, bfd_boolean (*func) (bfd *, int, char *))
459 {
460   unsigned int chars_on_line;
461   bfd_boolean eof = FALSE;
462
463   /* To the front of the file.  */
464   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
465     return FALSE;
466   while (! eof)
467     {
468       char src[MAXCHUNK];
469       char type;
470
471       /* Find first '%'.  */
472       eof = (bfd_boolean) (bfd_bread (src, (bfd_size_type) 1, abfd) != 1);
473       while (*src != '%' && !eof)
474         eof = (bfd_boolean) (bfd_bread (src, (bfd_size_type) 1, abfd) != 1);
475
476       if (eof)
477         break;
478
479       /* Fetch the type and the length and the checksum.  */
480       if (bfd_bread (src, (bfd_size_type) 5, abfd) != 5)
481         return FALSE;
482
483       type = src[2];
484
485       if (!ISHEX (src[0]) || !ISHEX (src[1]))
486         break;
487
488       /* Already read five chars.  */
489       chars_on_line = HEX (src) - 5;
490
491       if (chars_on_line >= MAXCHUNK)
492         return FALSE;
493
494       if (bfd_bread (src, (bfd_size_type) chars_on_line, abfd) != chars_on_line)
495         return FALSE;
496
497       /* Put a null at the end.  */
498       src[chars_on_line] = 0;
499
500       if (!func (abfd, type, src))
501         return FALSE;
502     }
503
504   return TRUE;
505 }
506
507 static long
508 tekhex_canonicalize_symtab (bfd *abfd, asymbol **table)
509 {
510   tekhex_symbol_type *p = abfd->tdata.tekhex_data->symbols;
511   unsigned int c = bfd_get_symcount (abfd);
512
513   table[c] = 0;
514   while (p)
515     {
516       table[--c] = &(p->symbol);
517       p = p->prev;
518     }
519
520   return bfd_get_symcount (abfd);
521 }
522
523 static long
524 tekhex_get_symtab_upper_bound (bfd *abfd)
525 {
526   return (abfd->symcount + 1) * (sizeof (struct tekhex_asymbol_struct *));
527
528 }
529
530 static bfd_boolean
531 tekhex_mkobject (bfd *abfd)
532 {
533   tdata_type *tdata;
534
535   tdata = bfd_alloc (abfd, (bfd_size_type) sizeof (tdata_type));
536   if (!tdata)
537     return FALSE;
538   abfd->tdata.tekhex_data = tdata;
539   tdata->type = 1;
540   tdata->head =  NULL;
541   tdata->symbols = NULL;
542   tdata->data = NULL;
543   return TRUE;
544 }
545
546 /* Return TRUE if the file looks like it's in TekHex format. Just look
547    for a percent sign and some hex digits.  */
548
549 static const bfd_target *
550 tekhex_object_p (bfd *abfd)
551 {
552   char b[4];
553
554   tekhex_init ();
555
556   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
557       || bfd_bread (b, (bfd_size_type) 4, abfd) != 4)
558     return NULL;
559
560   if (b[0] != '%' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
561     return NULL;
562
563   tekhex_mkobject (abfd);
564
565   if (!pass_over (abfd, first_phase))
566     return NULL;
567
568   return abfd->xvec;
569 }
570
571 static void
572 move_section_contents (bfd *abfd,
573                        asection *section,
574                        const void * locationp,
575                        file_ptr offset,
576                        bfd_size_type count,
577                        bfd_boolean get)
578 {
579   bfd_vma addr;
580   char *location = (char *) locationp;
581   bfd_vma prev_number = 1;      /* Nothing can have this as a high bit.  */
582   struct data_struct *d = NULL;
583
584   BFD_ASSERT (offset == 0);
585   for (addr = section->vma; count != 0; count--, addr++)
586     {
587       /* Get high bits of address.  */
588       bfd_vma chunk_number = addr & ~(bfd_vma) CHUNK_MASK;
589       bfd_vma low_bits = addr & CHUNK_MASK;
590
591       if (chunk_number != prev_number)
592         /* Different chunk, so move pointer. */
593         d = find_chunk (abfd, chunk_number);
594
595       if (get)
596         {
597           if (d->chunk_init[low_bits])
598             *location = d->chunk_data[low_bits];
599           else
600             *location = 0;
601         }
602       else
603         {
604           d->chunk_data[low_bits] = *location;
605           d->chunk_init[low_bits] = (*location != 0);
606         }
607
608       location++;
609     }
610 }
611
612 static bfd_boolean
613 tekhex_get_section_contents (bfd *abfd,
614                              asection *section,
615                              void * locationp,
616                              file_ptr offset,
617                              bfd_size_type count)
618 {
619   if (section->flags & (SEC_LOAD | SEC_ALLOC))
620     {
621       move_section_contents (abfd, section, locationp, offset, count, TRUE);
622       return TRUE;
623     }
624
625   return FALSE;
626 }
627
628 static bfd_boolean
629 tekhex_set_arch_mach (bfd *abfd,
630                       enum bfd_architecture arch,
631                       unsigned long machine)
632 {
633   return bfd_default_set_arch_mach (abfd, arch, machine);
634 }
635
636 /* We have to save up all the Tekhexords for a splurge before output.  */
637
638 static bfd_boolean
639 tekhex_set_section_contents (bfd *abfd,
640                              sec_ptr section,
641                              const void * locationp,
642                              file_ptr offset,
643                              bfd_size_type bytes_to_do)
644 {
645   if (! abfd->output_has_begun)
646     {
647       /* The first time around, allocate enough sections to hold all the chunks.  */
648       asection *s = abfd->sections;
649       bfd_vma vma;
650
651       for (s = abfd->sections; s; s = s->next)
652         {
653           if (s->flags & SEC_LOAD)
654             {
655               for (vma = s->vma & ~(bfd_vma) CHUNK_MASK;
656                    vma < s->vma + s->size;
657                    vma += CHUNK_MASK)
658                 find_chunk (abfd, vma);
659             }
660         }
661     }
662
663   if (section->flags & (SEC_LOAD | SEC_ALLOC))
664     {
665       move_section_contents (abfd, section, locationp, offset, bytes_to_do,
666                              FALSE);
667       return TRUE;
668     }
669
670   return FALSE;
671 }
672
673 static void
674 writevalue (char **dst, bfd_vma value)
675 {
676   char *p = *dst;
677   int len;
678   int shift;
679
680   for (len = 8, shift = 28; shift; shift -= 4, len--)
681     {
682       if ((value >> shift) & 0xf)
683         {
684           *p++ = len + '0';
685           while (len)
686             {
687               *p++ = digs[(value >> shift) & 0xf];
688               shift -= 4;
689               len--;
690             }
691           *dst = p;
692           return;
693
694         }
695     }
696   *p++ = '1';
697   *p++ = '0';
698   *dst = p;
699 }
700
701 static void
702 writesym (char **dst, const char *sym)
703 {
704   char *p = *dst;
705   int len = (sym ? strlen (sym) : 0);
706
707   if (len >= 16)
708     {
709       *p++ = '0';
710       len = 16;
711     }
712   else
713     {
714       if (len == 0)
715         {
716           *p++ = '1';
717           sym = "$";
718           len = 1;
719         }
720       else
721         *p++ = digs[len];
722     }
723
724   while (len--)
725     *p++ = *sym++;
726
727   *dst = p;
728 }
729
730 static void
731 out (bfd *abfd, int type, char *start, char *end)
732 {
733   int sum = 0;
734   char *s;
735   char front[6];
736   bfd_size_type wrlen;
737
738   front[0] = '%';
739   TOHEX (front + 1, end - start + 5);
740   front[3] = type;
741
742   for (s = start; s < end; s++)
743     sum += sum_block[(unsigned char) *s];
744
745   sum += sum_block[(unsigned char) front[1]];   /* Length.  */
746   sum += sum_block[(unsigned char) front[2]];
747   sum += sum_block[(unsigned char) front[3]];   /* Type.  */
748   TOHEX (front + 4, sum);
749   if (bfd_bwrite (front, (bfd_size_type) 6, abfd) != 6)
750     abort ();
751   end[0] = '\n';
752   wrlen = end - start + 1;
753   if (bfd_bwrite (start, wrlen, abfd) != wrlen)
754     abort ();
755 }
756
757 static bfd_boolean
758 tekhex_write_object_contents (bfd *abfd)
759 {
760   char buffer[100];
761   asymbol **p;
762   asection *s;
763   struct data_struct *d;
764
765   tekhex_init ();
766
767   /* And the raw data.  */
768   for (d = abfd->tdata.tekhex_data->data;
769        d != NULL;
770        d = d->next)
771     {
772       int low;
773
774       const int span = 32;
775       int addr;
776
777       /* Write it in blocks of 32 bytes.  */
778       for (addr = 0; addr < CHUNK_MASK + 1; addr += span)
779         {
780           int need = 0;
781
782           /* Check to see if necessary.  */
783           for (low = 0; !need && low < span; low++)
784             if (d->chunk_init[addr + low])
785               need = 1;
786
787           if (need)
788             {
789               char *dst = buffer;
790
791               writevalue (&dst, addr + d->vma);
792               for (low = 0; low < span; low++)
793                 {
794                   TOHEX (dst, d->chunk_data[addr + low]);
795                   dst += 2;
796                 }
797               out (abfd, '6', buffer, dst);
798             }
799         }
800     }
801
802   /* Write all the section headers for the sections.  */
803   for (s = abfd->sections; s != NULL; s = s->next)
804     {
805       char *dst = buffer;
806
807       writesym (&dst, s->name);
808       *dst++ = '1';
809       writevalue (&dst, s->vma);
810       writevalue (&dst, s->vma + s->size);
811       out (abfd, '3', buffer, dst);
812     }
813
814   /* And the symbols.  */
815   if (abfd->outsymbols)
816     {
817       for (p = abfd->outsymbols; *p; p++)
818         {
819           int section_code = bfd_decode_symclass (*p);
820
821           if (section_code != '?')
822             {
823               /* Do not include debug symbols.  */
824               asymbol *sym = *p;
825               char *dst = buffer;
826
827               writesym (&dst, sym->section->name);
828
829               switch (section_code)
830                 {
831                 case 'A':
832                   *dst++ = '2';
833                   break;
834                 case 'a':
835                   *dst++ = '6';
836                   break;
837                 case 'D':
838                 case 'B':
839                 case 'O':
840                   *dst++ = '4';
841                   break;
842                 case 'd':
843                 case 'b':
844                 case 'o':
845                   *dst++ = '8';
846                   break;
847                 case 'T':
848                   *dst++ = '3';
849                   break;
850                 case 't':
851                   *dst++ = '7';
852                   break;
853                 case 'C':
854                 case 'U':
855                   bfd_set_error (bfd_error_wrong_format);
856                   return FALSE;
857                 }
858
859               writesym (&dst, sym->name);
860               writevalue (&dst, sym->value + sym->section->vma);
861               out (abfd, '3', buffer, dst);
862             }
863         }
864     }
865
866   /* And the terminator.  */
867   if (bfd_bwrite ("%0781010\n", (bfd_size_type) 9, abfd) != 9)
868     abort ();
869   return TRUE;
870 }
871
872 static int
873 tekhex_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
874                        struct bfd_link_info *info ATTRIBUTE_UNUSED)
875 {
876   return 0;
877 }
878
879 static asymbol *
880 tekhex_make_empty_symbol (bfd *abfd)
881 {
882   bfd_size_type amt = sizeof (struct tekhex_symbol_struct);
883   tekhex_symbol_type *new = bfd_zalloc (abfd, amt);
884
885   if (!new)
886     return NULL;
887   new->symbol.the_bfd = abfd;
888   new->prev =  NULL;
889   return &(new->symbol);
890 }
891
892 static void
893 tekhex_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
894                         asymbol *symbol,
895                         symbol_info *ret)
896 {
897   bfd_symbol_info (symbol, ret);
898 }
899
900 static void
901 tekhex_print_symbol (bfd *abfd,
902                      void * filep,
903                      asymbol *symbol,
904                      bfd_print_symbol_type how)
905 {
906   FILE *file = (FILE *) filep;
907
908   switch (how)
909     {
910     case bfd_print_symbol_name:
911       fprintf (file, "%s", symbol->name);
912       break;
913     case bfd_print_symbol_more:
914       break;
915
916     case bfd_print_symbol_all:
917       {
918         const char *section_name = symbol->section->name;
919
920         bfd_print_symbol_vandf (abfd, (void *) file, symbol);
921
922         fprintf (file, " %-5s %s",
923                  section_name, symbol->name);
924       }
925     }
926 }
927
928 #define tekhex_close_and_cleanup                    _bfd_generic_close_and_cleanup
929 #define tekhex_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
930 #define tekhex_new_section_hook                     _bfd_generic_new_section_hook
931 #define tekhex_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
932 #define tekhex_bfd_is_local_label_name               bfd_generic_is_local_label_name
933 #define tekhex_get_lineno                           _bfd_nosymbols_get_lineno
934 #define tekhex_find_nearest_line                    _bfd_nosymbols_find_nearest_line
935 #define tekhex_find_inliner_info                    _bfd_nosymbols_find_inliner_info
936 #define tekhex_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
937 #define tekhex_read_minisymbols                     _bfd_generic_read_minisymbols
938 #define tekhex_minisymbol_to_symbol                 _bfd_generic_minisymbol_to_symbol
939 #define tekhex_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
940 #define tekhex_bfd_relax_section                    bfd_generic_relax_section
941 #define tekhex_bfd_gc_sections                      bfd_generic_gc_sections
942 #define tekhex_bfd_merge_sections                   bfd_generic_merge_sections
943 #define tekhex_bfd_is_group_section                 bfd_generic_is_group_section
944 #define tekhex_bfd_discard_group                    bfd_generic_discard_group
945 #define tekhex_section_already_linked               _bfd_generic_section_already_linked
946 #define tekhex_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
947 #define tekhex_bfd_link_hash_table_free             _bfd_generic_link_hash_table_free
948 #define tekhex_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
949 #define tekhex_bfd_link_just_syms                   _bfd_generic_link_just_syms
950 #define tekhex_bfd_final_link                       _bfd_generic_final_link
951 #define tekhex_bfd_link_split_section               _bfd_generic_link_split_section
952 #define tekhex_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
953
954 const bfd_target tekhex_vec =
955 {
956   "tekhex",                     /* Name.  */
957   bfd_target_tekhex_flavour,
958   BFD_ENDIAN_UNKNOWN,           /* Target byte order.  */
959   BFD_ENDIAN_UNKNOWN,           /* Target headers byte order.  */
960   (EXEC_P |                     /* Object flags.  */
961    HAS_SYMS | HAS_LINENO | HAS_DEBUG |
962    HAS_RELOC | HAS_LOCALS | WP_TEXT | D_PAGED),
963   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
964    | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags.  */
965   0,                            /* Leading underscore.  */
966   ' ',                          /* AR_pad_char.  */
967   16,                           /* AR_max_namelen.  */
968   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
969   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
970   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Data.  */
971   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
972   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
973   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Headers.  */
974
975   {
976     _bfd_dummy_target,
977     tekhex_object_p,            /* bfd_check_format.  */
978     _bfd_dummy_target,
979     _bfd_dummy_target,
980   },
981   {
982     bfd_false,
983     tekhex_mkobject,
984     _bfd_generic_mkarchive,
985     bfd_false,
986   },
987   {                             /* bfd_write_contents.  */
988     bfd_false,
989     tekhex_write_object_contents,
990     _bfd_write_archive_contents,
991     bfd_false,
992   },
993
994   BFD_JUMP_TABLE_GENERIC (tekhex),
995   BFD_JUMP_TABLE_COPY (_bfd_generic),
996   BFD_JUMP_TABLE_CORE (_bfd_nocore),
997   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
998   BFD_JUMP_TABLE_SYMBOLS (tekhex),
999   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1000   BFD_JUMP_TABLE_WRITE (tekhex),
1001   BFD_JUMP_TABLE_LINK (tekhex),
1002   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1003
1004   NULL,
1005
1006   NULL
1007 };