1 /* BFD backend for Extended Tektronix Hex Format  objects.
2    Copyright (C) 1992-2024 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
tekhex_init(void)204 tekhex_init (void)
205 {
206   unsigned int i;
207   static bool 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 bool
getvalue(char ** srcp,bfd_vma * valuep,char * endp)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 bool
getsym(char * dstp,char ** srcp,unsigned int * lenp,char * endp)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 *
find_chunk(bfd * abfd,bfd_vma vma,bool create)319 find_chunk (bfd *abfd, bfd_vma vma, bool 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
insert_byte(bfd * abfd,int value,bfd_vma addr)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 bool
first_phase(bfd * abfd,int type,char * src,char * src_end)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                     size_t 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 bool
pass_over(bfd * abfd,bool (* func)(bfd *,int,char *,char *))512 pass_over (bfd *abfd, bool (*func) (bfd *, int, char *, char *))
513 {
514   unsigned int chars_on_line;
515   bool is_eof = false;
516 
517   /* To the front of the file.  */
518   if (bfd_seek (abfd, 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_read (src, 1, abfd) != 1;
528       while (!is_eof && *src != '%')
529           is_eof = bfd_read (src, 1, abfd) != 1;
530 
531       if (is_eof)
532           break;
533 
534       /* Fetch the type and the length and the checksum.  */
535       if (bfd_read (src, 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_read (src, 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
tekhex_canonicalize_symtab(bfd * abfd,asymbol ** table)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
tekhex_get_symtab_upper_bound(bfd * abfd)578 tekhex_get_symtab_upper_bound (bfd *abfd)
579 {
580   return (abfd->symcount + 1) * (sizeof (struct tekhex_asymbol_struct *));
581 
582 }
583 
584 static bool
tekhex_mkobject(bfd * abfd)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 bfd_cleanup
tekhex_object_p(bfd * abfd)604 tekhex_object_p (bfd *abfd)
605 {
606   char b[4];
607 
608   tekhex_init ();
609 
610   if (bfd_seek (abfd, 0, SEEK_SET) != 0
611       || bfd_read (b, 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 _bfd_no_cleanup;
623 }
624 
625 static void
move_section_contents(bfd * abfd,asection * section,const void * locationp,file_ptr offset,bfd_size_type count,bool get)626 move_section_contents (bfd *abfd,
627                            asection *section,
628                            const void * locationp,
629                            file_ptr offset,
630                            bfd_size_type count,
631                            bool 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       bool 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 bool
tekhex_get_section_contents(bfd * abfd,asection * section,void * locationp,file_ptr offset,bfd_size_type count)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 bool
tekhex_set_arch_mach(bfd * abfd,enum bfd_architecture arch,unsigned long machine)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 bool
tekhex_set_section_contents(bfd * abfd,sec_ptr section,const void * locationp,file_ptr offset,bfd_size_type bytes_to_do)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
writevalue(char ** dst,bfd_vma value)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
writesym(char ** dst,const char * sym)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
out(bfd * abfd,int type,char * start,char * end)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_write (front, 6, abfd) != 6)
792     abort ();
793   end[0] = '\n';
794   wrlen = end - start + 1;
795   if (bfd_write (start, wrlen, abfd) != wrlen)
796     abort ();
797 }
798 
799 static bool
tekhex_write_object_contents(bfd * abfd)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_write ("%0781010\n", 9, abfd) != 9)
901     abort ();
902   return true;
903 }
904 
905 static int
tekhex_sizeof_headers(bfd * abfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED)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 *
tekhex_make_empty_symbol(bfd * abfd)913 tekhex_make_empty_symbol (bfd *abfd)
914 {
915   size_t 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
tekhex_get_symbol_info(bfd * abfd ATTRIBUTE_UNUSED,asymbol * symbol,symbol_info * ret)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
tekhex_print_symbol(bfd * abfd,void * filep,asymbol * symbol,bfd_print_symbol_type how)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_nearest_line_with_alt             _bfd_nosymbols_find_nearest_line_with_alt
970 #define tekhex_find_line                              _bfd_nosymbols_find_line
971 #define tekhex_find_inliner_info                      _bfd_nosymbols_find_inliner_info
972 #define tekhex_get_symbol_version_string              _bfd_nosymbols_get_symbol_version_string
973 #define tekhex_bfd_make_debug_symbol                  _bfd_nosymbols_bfd_make_debug_symbol
974 #define tekhex_read_minisymbols                                 _bfd_generic_read_minisymbols
975 #define tekhex_minisymbol_to_symbol                   _bfd_generic_minisymbol_to_symbol
976 #define tekhex_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
977 #define tekhex_bfd_relax_section                      bfd_generic_relax_section
978 #define tekhex_bfd_gc_sections                                  bfd_generic_gc_sections
979 #define tekhex_bfd_lookup_section_flags               bfd_generic_lookup_section_flags
980 #define tekhex_bfd_merge_sections                     bfd_generic_merge_sections
981 #define tekhex_bfd_is_group_section                   bfd_generic_is_group_section
982 #define tekhex_bfd_group_name                         bfd_generic_group_name
983 #define tekhex_bfd_discard_group                      bfd_generic_discard_group
984 #define tekhex_section_already_linked                 _bfd_generic_section_already_linked
985 #define tekhex_bfd_define_common_symbol               bfd_generic_define_common_symbol
986 #define tekhex_bfd_link_hide_symbol                   _bfd_generic_link_hide_symbol
987 #define tekhex_bfd_define_start_stop                  bfd_generic_define_start_stop
988 #define tekhex_bfd_link_hash_table_create             _bfd_generic_link_hash_table_create
989 #define tekhex_bfd_link_add_symbols                   _bfd_generic_link_add_symbols
990 #define tekhex_bfd_link_just_syms                     _bfd_generic_link_just_syms
991 #define tekhex_bfd_copy_link_hash_symbol_type         _bfd_generic_copy_link_hash_symbol_type
992 #define tekhex_bfd_final_link                         _bfd_generic_final_link
993 #define tekhex_bfd_link_split_section                 _bfd_generic_link_split_section
994 #define tekhex_bfd_link_check_relocs                  _bfd_generic_link_check_relocs
995 
996 const bfd_target tekhex_vec =
997 {
998   "tekhex",                             /* Name.  */
999   bfd_target_tekhex_flavour,
1000   BFD_ENDIAN_UNKNOWN,                   /* Target byte order.  */
1001   BFD_ENDIAN_UNKNOWN,                   /* Target headers byte order.  */
1002   (EXEC_P |                             /* Object flags.  */
1003    HAS_SYMS | HAS_LINENO | HAS_DEBUG |
1004    HAS_RELOC | HAS_LOCALS | WP_TEXT | D_PAGED),
1005   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
1006    | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags.  */
1007   0,                                    /* Leading underscore.  */
1008   ' ',                                  /* AR_pad_char.  */
1009   16,                                   /* AR_max_namelen.  */
1010   0,                                    /* match priority.  */
1011   TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
1012   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1013   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1014   bfd_getb16, bfd_getb_signed_16, bfd_putb16,     /* Data.  */
1015   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1016   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1017   bfd_getb16, bfd_getb_signed_16, bfd_putb16,     /* Headers.  */
1018 
1019   {
1020     _bfd_dummy_target,
1021     tekhex_object_p,                    /* bfd_check_format.  */
1022     _bfd_dummy_target,
1023     _bfd_dummy_target,
1024   },
1025   {
1026     _bfd_bool_bfd_false_error,
1027     tekhex_mkobject,
1028     _bfd_generic_mkarchive,
1029     _bfd_bool_bfd_false_error,
1030   },
1031   {                                     /* bfd_write_contents.  */
1032     _bfd_bool_bfd_false_error,
1033     tekhex_write_object_contents,
1034     _bfd_write_archive_contents,
1035     _bfd_bool_bfd_false_error,
1036   },
1037 
1038   BFD_JUMP_TABLE_GENERIC (tekhex),
1039   BFD_JUMP_TABLE_COPY (_bfd_generic),
1040   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1041   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1042   BFD_JUMP_TABLE_SYMBOLS (tekhex),
1043   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1044   BFD_JUMP_TABLE_WRITE (tekhex),
1045   BFD_JUMP_TABLE_LINK (tekhex),
1046   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1047 
1048   NULL,
1049 
1050   NULL
1051 };
1052