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