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