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