1 /* BFD backend for Extended Tektronix Hex Format  objects.
2    Copyright (C) 1992-2020 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_group_name			    bfd_generic_group_name
982 #define tekhex_bfd_discard_group		    bfd_generic_discard_group
983 #define tekhex_section_already_linked		    _bfd_generic_section_already_linked
984 #define tekhex_bfd_define_common_symbol		    bfd_generic_define_common_symbol
985 #define tekhex_bfd_link_hide_symbol		    _bfd_generic_link_hide_symbol
986 #define tekhex_bfd_define_start_stop		    bfd_generic_define_start_stop
987 #define tekhex_bfd_link_hash_table_create	    _bfd_generic_link_hash_table_create
988 #define tekhex_bfd_link_add_symbols		    _bfd_generic_link_add_symbols
989 #define tekhex_bfd_link_just_syms		    _bfd_generic_link_just_syms
990 #define tekhex_bfd_copy_link_hash_symbol_type	    _bfd_generic_copy_link_hash_symbol_type
991 #define tekhex_bfd_final_link			    _bfd_generic_final_link
992 #define tekhex_bfd_link_split_section		    _bfd_generic_link_split_section
993 #define tekhex_get_section_contents_in_window	    _bfd_generic_get_section_contents_in_window
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   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1012   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1013   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
1014   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1015   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1016   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers.  */
1017 
1018   {
1019     _bfd_dummy_target,
1020     tekhex_object_p,		/* bfd_check_format.  */
1021     _bfd_dummy_target,
1022     _bfd_dummy_target,
1023   },
1024   {
1025     _bfd_bool_bfd_false_error,
1026     tekhex_mkobject,
1027     _bfd_generic_mkarchive,
1028     _bfd_bool_bfd_false_error,
1029   },
1030   {				/* bfd_write_contents.  */
1031     _bfd_bool_bfd_false_error,
1032     tekhex_write_object_contents,
1033     _bfd_write_archive_contents,
1034     _bfd_bool_bfd_false_error,
1035   },
1036 
1037   BFD_JUMP_TABLE_GENERIC (tekhex),
1038   BFD_JUMP_TABLE_COPY (_bfd_generic),
1039   BFD_JUMP_TABLE_CORE (_bfd_nocore),
1040   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1041   BFD_JUMP_TABLE_SYMBOLS (tekhex),
1042   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1043   BFD_JUMP_TABLE_WRITE (tekhex),
1044   BFD_JUMP_TABLE_LINK (tekhex),
1045   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1046 
1047   NULL,
1048 
1049   NULL
1050 };
1051