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