OSDN Git Service

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