update copyright dates
[external/binutils.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, 2005, 2006, 2007, 2009 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_symbol = (tekhex_symbol_type *)
419                     bfd_alloc (abfd, amt);
420                 char stype = (*src);
421
422                 if (!new_symbol)
423                   return FALSE;
424                 new_symbol->symbol.the_bfd = abfd;
425                 src++;
426                 abfd->symcount++;
427                 abfd->flags |= HAS_SYMS;
428                 new_symbol->prev = abfd->tdata.tekhex_data->symbols;
429                 abfd->tdata.tekhex_data->symbols = new_symbol;
430                 if (!getsym (sym, &src, &len))
431                   return FALSE;
432                 new_symbol->symbol.name = (const char *)
433                     bfd_alloc (abfd, (bfd_size_type) len + 1);
434                 if (!new_symbol->symbol.name)
435                   return FALSE;
436                 memcpy ((char *) (new_symbol->symbol.name), sym, len + 1);
437                 new_symbol->symbol.section = section;
438                 if (stype <= '4')
439                   new_symbol->symbol.flags = (BSF_GLOBAL | BSF_EXPORT);
440                 else
441                   new_symbol->symbol.flags = BSF_LOCAL;
442                 if (!getvalue (&src, &val))
443                   return FALSE;
444                 new_symbol->symbol.value = val - section->vma;
445                 break;
446               }
447             default:
448               return FALSE;
449             }
450         }
451     }
452
453   return TRUE;
454 }
455
456 /* Pass over a tekhex, calling one of the above functions on each
457    record.  */
458
459 static bfd_boolean
460 pass_over (bfd *abfd, bfd_boolean (*func) (bfd *, int, char *))
461 {
462   unsigned int chars_on_line;
463   bfd_boolean eof = FALSE;
464
465   /* To the front of the file.  */
466   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
467     return FALSE;
468   while (! eof)
469     {
470       char src[MAXCHUNK];
471       char type;
472
473       /* Find first '%'.  */
474       eof = (bfd_boolean) (bfd_bread (src, (bfd_size_type) 1, abfd) != 1);
475       while (*src != '%' && !eof)
476         eof = (bfd_boolean) (bfd_bread (src, (bfd_size_type) 1, abfd) != 1);
477
478       if (eof)
479         break;
480
481       /* Fetch the type and the length and the checksum.  */
482       if (bfd_bread (src, (bfd_size_type) 5, abfd) != 5)
483         return FALSE;
484
485       type = src[2];
486
487       if (!ISHEX (src[0]) || !ISHEX (src[1]))
488         break;
489
490       /* Already read five chars.  */
491       chars_on_line = HEX (src) - 5;
492
493       if (chars_on_line >= MAXCHUNK)
494         return FALSE;
495
496       if (bfd_bread (src, (bfd_size_type) chars_on_line, abfd) != chars_on_line)
497         return FALSE;
498
499       /* Put a null at the end.  */
500       src[chars_on_line] = 0;
501
502       if (!func (abfd, type, src))
503         return FALSE;
504     }
505
506   return TRUE;
507 }
508
509 static long
510 tekhex_canonicalize_symtab (bfd *abfd, asymbol **table)
511 {
512   tekhex_symbol_type *p = abfd->tdata.tekhex_data->symbols;
513   unsigned int c = bfd_get_symcount (abfd);
514
515   table[c] = 0;
516   while (p)
517     {
518       table[--c] = &(p->symbol);
519       p = p->prev;
520     }
521
522   return bfd_get_symcount (abfd);
523 }
524
525 static long
526 tekhex_get_symtab_upper_bound (bfd *abfd)
527 {
528   return (abfd->symcount + 1) * (sizeof (struct tekhex_asymbol_struct *));
529
530 }
531
532 static bfd_boolean
533 tekhex_mkobject (bfd *abfd)
534 {
535   tdata_type *tdata;
536
537   tdata = bfd_alloc (abfd, (bfd_size_type) sizeof (tdata_type));
538   if (!tdata)
539     return FALSE;
540   abfd->tdata.tekhex_data = tdata;
541   tdata->type = 1;
542   tdata->head =  NULL;
543   tdata->symbols = NULL;
544   tdata->data = NULL;
545   return TRUE;
546 }
547
548 /* Return TRUE if the file looks like it's in TekHex format. Just look
549    for a percent sign and some hex digits.  */
550
551 static const bfd_target *
552 tekhex_object_p (bfd *abfd)
553 {
554   char b[4];
555
556   tekhex_init ();
557
558   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
559       || bfd_bread (b, (bfd_size_type) 4, abfd) != 4)
560     return NULL;
561
562   if (b[0] != '%' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
563     return NULL;
564
565   tekhex_mkobject (abfd);
566
567   if (!pass_over (abfd, first_phase))
568     return NULL;
569
570   return abfd->xvec;
571 }
572
573 static void
574 move_section_contents (bfd *abfd,
575                        asection *section,
576                        const void * locationp,
577                        file_ptr offset,
578                        bfd_size_type count,
579                        bfd_boolean get)
580 {
581   bfd_vma addr;
582   char *location = (char *) locationp;
583   bfd_vma prev_number = 1;      /* Nothing can have this as a high bit.  */
584   struct data_struct *d = NULL;
585
586   BFD_ASSERT (offset == 0);
587   for (addr = section->vma; count != 0; count--, addr++)
588     {
589       /* Get high bits of address.  */
590       bfd_vma chunk_number = addr & ~(bfd_vma) CHUNK_MASK;
591       bfd_vma low_bits = addr & CHUNK_MASK;
592
593       if (chunk_number != prev_number)
594         /* Different chunk, so move pointer. */
595         d = find_chunk (abfd, chunk_number);
596
597       if (get)
598         {
599           if (d->chunk_init[low_bits])
600             *location = d->chunk_data[low_bits];
601           else
602             *location = 0;
603         }
604       else
605         {
606           d->chunk_data[low_bits] = *location;
607           d->chunk_init[low_bits] = (*location != 0);
608         }
609
610       location++;
611     }
612 }
613
614 static bfd_boolean
615 tekhex_get_section_contents (bfd *abfd,
616                              asection *section,
617                              void * locationp,
618                              file_ptr offset,
619                              bfd_size_type count)
620 {
621   if (section->flags & (SEC_LOAD | SEC_ALLOC))
622     {
623       move_section_contents (abfd, section, locationp, offset, count, TRUE);
624       return TRUE;
625     }
626
627   return FALSE;
628 }
629
630 static bfd_boolean
631 tekhex_set_arch_mach (bfd *abfd,
632                       enum bfd_architecture arch,
633                       unsigned long machine)
634 {
635   return bfd_default_set_arch_mach (abfd, arch, machine);
636 }
637
638 /* We have to save up all the Tekhexords for a splurge before output.  */
639
640 static bfd_boolean
641 tekhex_set_section_contents (bfd *abfd,
642                              sec_ptr section,
643                              const void * locationp,
644                              file_ptr offset,
645                              bfd_size_type bytes_to_do)
646 {
647   if (! abfd->output_has_begun)
648     {
649       /* The first time around, allocate enough sections to hold all the chunks.  */
650       asection *s = abfd->sections;
651       bfd_vma vma;
652
653       for (s = abfd->sections; s; s = s->next)
654         {
655           if (s->flags & SEC_LOAD)
656             {
657               for (vma = s->vma & ~(bfd_vma) CHUNK_MASK;
658                    vma < s->vma + s->size;
659                    vma += CHUNK_MASK)
660                 find_chunk (abfd, vma);
661             }
662         }
663     }
664
665   if (section->flags & (SEC_LOAD | SEC_ALLOC))
666     {
667       move_section_contents (abfd, section, locationp, offset, bytes_to_do,
668                              FALSE);
669       return TRUE;
670     }
671
672   return FALSE;
673 }
674
675 static void
676 writevalue (char **dst, bfd_vma value)
677 {
678   char *p = *dst;
679   int len;
680   int shift;
681
682   for (len = 8, shift = 28; shift; shift -= 4, len--)
683     {
684       if ((value >> shift) & 0xf)
685         {
686           *p++ = len + '0';
687           while (len)
688             {
689               *p++ = digs[(value >> shift) & 0xf];
690               shift -= 4;
691               len--;
692             }
693           *dst = p;
694           return;
695
696         }
697     }
698   *p++ = '1';
699   *p++ = '0';
700   *dst = p;
701 }
702
703 static void
704 writesym (char **dst, const char *sym)
705 {
706   char *p = *dst;
707   int len = (sym ? strlen (sym) : 0);
708
709   if (len >= 16)
710     {
711       *p++ = '0';
712       len = 16;
713     }
714   else
715     {
716       if (len == 0)
717         {
718           *p++ = '1';
719           sym = "$";
720           len = 1;
721         }
722       else
723         *p++ = digs[len];
724     }
725
726   while (len--)
727     *p++ = *sym++;
728
729   *dst = p;
730 }
731
732 static void
733 out (bfd *abfd, int type, char *start, char *end)
734 {
735   int sum = 0;
736   char *s;
737   char front[6];
738   bfd_size_type wrlen;
739
740   front[0] = '%';
741   TOHEX (front + 1, end - start + 5);
742   front[3] = type;
743
744   for (s = start; s < end; s++)
745     sum += sum_block[(unsigned char) *s];
746
747   sum += sum_block[(unsigned char) front[1]];   /* Length.  */
748   sum += sum_block[(unsigned char) front[2]];
749   sum += sum_block[(unsigned char) front[3]];   /* Type.  */
750   TOHEX (front + 4, sum);
751   if (bfd_bwrite (front, (bfd_size_type) 6, abfd) != 6)
752     abort ();
753   end[0] = '\n';
754   wrlen = end - start + 1;
755   if (bfd_bwrite (start, wrlen, abfd) != wrlen)
756     abort ();
757 }
758
759 static bfd_boolean
760 tekhex_write_object_contents (bfd *abfd)
761 {
762   char buffer[100];
763   asymbol **p;
764   asection *s;
765   struct data_struct *d;
766
767   tekhex_init ();
768
769   /* And the raw data.  */
770   for (d = abfd->tdata.tekhex_data->data;
771        d != NULL;
772        d = d->next)
773     {
774       int low;
775
776       const int span = 32;
777       int addr;
778
779       /* Write it in blocks of 32 bytes.  */
780       for (addr = 0; addr < CHUNK_MASK + 1; addr += span)
781         {
782           int need = 0;
783
784           /* Check to see if necessary.  */
785           for (low = 0; !need && low < span; low++)
786             if (d->chunk_init[addr + low])
787               need = 1;
788
789           if (need)
790             {
791               char *dst = buffer;
792
793               writevalue (&dst, addr + d->vma);
794               for (low = 0; low < span; low++)
795                 {
796                   TOHEX (dst, d->chunk_data[addr + low]);
797                   dst += 2;
798                 }
799               out (abfd, '6', buffer, dst);
800             }
801         }
802     }
803
804   /* Write all the section headers for the sections.  */
805   for (s = abfd->sections; s != NULL; s = s->next)
806     {
807       char *dst = buffer;
808
809       writesym (&dst, s->name);
810       *dst++ = '1';
811       writevalue (&dst, s->vma);
812       writevalue (&dst, s->vma + s->size);
813       out (abfd, '3', buffer, dst);
814     }
815
816   /* And the symbols.  */
817   if (abfd->outsymbols)
818     {
819       for (p = abfd->outsymbols; *p; p++)
820         {
821           int section_code = bfd_decode_symclass (*p);
822
823           if (section_code != '?')
824             {
825               /* Do not include debug symbols.  */
826               asymbol *sym = *p;
827               char *dst = buffer;
828
829               writesym (&dst, sym->section->name);
830
831               switch (section_code)
832                 {
833                 case 'A':
834                   *dst++ = '2';
835                   break;
836                 case 'a':
837                   *dst++ = '6';
838                   break;
839                 case 'D':
840                 case 'B':
841                 case 'O':
842                   *dst++ = '4';
843                   break;
844                 case 'd':
845                 case 'b':
846                 case 'o':
847                   *dst++ = '8';
848                   break;
849                 case 'T':
850                   *dst++ = '3';
851                   break;
852                 case 't':
853                   *dst++ = '7';
854                   break;
855                 case 'C':
856                 case 'U':
857                   bfd_set_error (bfd_error_wrong_format);
858                   return FALSE;
859                 }
860
861               writesym (&dst, sym->name);
862               writevalue (&dst, sym->value + sym->section->vma);
863               out (abfd, '3', buffer, dst);
864             }
865         }
866     }
867
868   /* And the terminator.  */
869   if (bfd_bwrite ("%0781010\n", (bfd_size_type) 9, abfd) != 9)
870     abort ();
871   return TRUE;
872 }
873
874 static int
875 tekhex_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
876                        struct bfd_link_info *info ATTRIBUTE_UNUSED)
877 {
878   return 0;
879 }
880
881 static asymbol *
882 tekhex_make_empty_symbol (bfd *abfd)
883 {
884   bfd_size_type amt = sizeof (struct tekhex_symbol_struct);
885   tekhex_symbol_type *new_symbol = (tekhex_symbol_type *) bfd_zalloc (abfd,
886                                                                       amt);
887
888   if (!new_symbol)
889     return NULL;
890   new_symbol->symbol.the_bfd = abfd;
891   new_symbol->prev =  NULL;
892   return &(new_symbol->symbol);
893 }
894
895 static void
896 tekhex_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
897                         asymbol *symbol,
898                         symbol_info *ret)
899 {
900   bfd_symbol_info (symbol, ret);
901 }
902
903 static void
904 tekhex_print_symbol (bfd *abfd,
905                      void * filep,
906                      asymbol *symbol,
907                      bfd_print_symbol_type how)
908 {
909   FILE *file = (FILE *) filep;
910
911   switch (how)
912     {
913     case bfd_print_symbol_name:
914       fprintf (file, "%s", symbol->name);
915       break;
916     case bfd_print_symbol_more:
917       break;
918
919     case bfd_print_symbol_all:
920       {
921         const char *section_name = symbol->section->name;
922
923         bfd_print_symbol_vandf (abfd, (void *) file, symbol);
924
925         fprintf (file, " %-5s %s",
926                  section_name, symbol->name);
927       }
928     }
929 }
930
931 #define tekhex_close_and_cleanup                    _bfd_generic_close_and_cleanup
932 #define tekhex_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
933 #define tekhex_new_section_hook                     _bfd_generic_new_section_hook
934 #define tekhex_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
935 #define tekhex_bfd_is_local_label_name               bfd_generic_is_local_label_name
936 #define tekhex_get_lineno                           _bfd_nosymbols_get_lineno
937 #define tekhex_find_nearest_line                    _bfd_nosymbols_find_nearest_line
938 #define tekhex_find_inliner_info                    _bfd_nosymbols_find_inliner_info
939 #define tekhex_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
940 #define tekhex_read_minisymbols                     _bfd_generic_read_minisymbols
941 #define tekhex_minisymbol_to_symbol                 _bfd_generic_minisymbol_to_symbol
942 #define tekhex_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
943 #define tekhex_bfd_relax_section                    bfd_generic_relax_section
944 #define tekhex_bfd_gc_sections                      bfd_generic_gc_sections
945 #define tekhex_bfd_merge_sections                   bfd_generic_merge_sections
946 #define tekhex_bfd_is_group_section                 bfd_generic_is_group_section
947 #define tekhex_bfd_discard_group                    bfd_generic_discard_group
948 #define tekhex_section_already_linked               _bfd_generic_section_already_linked
949 #define tekhex_bfd_define_common_symbol             bfd_generic_define_common_symbol
950 #define tekhex_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
951 #define tekhex_bfd_link_hash_table_free             _bfd_generic_link_hash_table_free
952 #define tekhex_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
953 #define tekhex_bfd_link_just_syms                   _bfd_generic_link_just_syms
954 #define tekhex_bfd_final_link                       _bfd_generic_final_link
955 #define tekhex_bfd_link_split_section               _bfd_generic_link_split_section
956 #define tekhex_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
957
958 const bfd_target tekhex_vec =
959 {
960   "tekhex",                     /* Name.  */
961   bfd_target_tekhex_flavour,
962   BFD_ENDIAN_UNKNOWN,           /* Target byte order.  */
963   BFD_ENDIAN_UNKNOWN,           /* Target headers byte order.  */
964   (EXEC_P |                     /* Object flags.  */
965    HAS_SYMS | HAS_LINENO | HAS_DEBUG |
966    HAS_RELOC | HAS_LOCALS | WP_TEXT | D_PAGED),
967   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
968    | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags.  */
969   0,                            /* Leading underscore.  */
970   ' ',                          /* AR_pad_char.  */
971   16,                           /* AR_max_namelen.  */
972   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
973   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
974   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Data.  */
975   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
976   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
977   bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Headers.  */
978
979   {
980     _bfd_dummy_target,
981     tekhex_object_p,            /* bfd_check_format.  */
982     _bfd_dummy_target,
983     _bfd_dummy_target,
984   },
985   {
986     bfd_false,
987     tekhex_mkobject,
988     _bfd_generic_mkarchive,
989     bfd_false,
990   },
991   {                             /* bfd_write_contents.  */
992     bfd_false,
993     tekhex_write_object_contents,
994     _bfd_write_archive_contents,
995     bfd_false,
996   },
997
998   BFD_JUMP_TABLE_GENERIC (tekhex),
999   BFD_JUMP_TABLE_COPY (_bfd_generic),
1000   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1001   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1002   BFD_JUMP_TABLE_SYMBOLS (tekhex),
1003   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1004   BFD_JUMP_TABLE_WRITE (tekhex),
1005   BFD_JUMP_TABLE_LINK (tekhex),
1006   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1007
1008   NULL,
1009
1010   NULL
1011 };