xref: /netbsd/external/gpl3/binutils/dist/bfd/tekhex.c (revision 6550d01e)
1 /* BFD backend for Extended Tektronix Hex Format  objects.
2    Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002,
3    2003, 2004, 2007 Free Software Foundation, Inc.
4    Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
5 
6    This file is part of BFD, the Binary File Descriptor library.
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21    MA 02110-1301, USA.  */
22 
23 
24 /* SUBSECTION
25 	Tektronix Hex Format handling
26 
27    DESCRIPTION
28 
29 	Tek Hex records can hold symbols and data, but not
30 	relocations. Their main application is communication with
31 	devices like PROM programmers and ICE equipment.
32 
33 	It seems that the sections are described as being really big,
34         the example I have says that the text section is 0..ffffffff.
35 	BFD would barf with this, many apps would try to alloc 4GB to
36 	read in the file.
37 
38 	Tex Hex may contain many sections, but the data which comes in
39 	has no tag saying which section it belongs to, so we create
40 	one section for each block of data, called "blknnnn" which we
41 	stick all the data into.
42 
43 	TekHex may come out of 	order and there is no header, so an
44 	initial scan is required  to discover the minimum and maximum
45 	addresses used to create the vma and size of the sections we
46 	create.
47 	We read in the data into pages of CHUNK_MASK+1 size and read
48 	them out from that whenever we need to.
49 
50 	Any number of sections may be created for output, we save them
51 	up and output them when it's time to close the bfd.
52 
53 	A TekHex record looks like:
54   EXAMPLE
55 	%<block length><type><checksum><stuff><cr>
56 
57   DESCRIPTION
58 	Where
59 	o length
60 	is the number of bytes in the record not including the % sign.
61 	o type
62 	is one of:
63 	3) symbol record
64 	6) data record
65 	8) termination record
66 
67   The data can come out of order, and may be discontigous. This is a
68   serial protocol, so big files are unlikely, so we keep a list of 8k chunks.  */
69 
70 #include "sysdep.h"
71 #include "bfd.h"
72 #include "libbfd.h"
73 #include "libiberty.h"
74 
75 typedef struct
76 {
77   bfd_vma low;
78   bfd_vma high;
79 } addr_range_type;
80 
81 typedef struct tekhex_symbol_struct
82 {
83   asymbol symbol;
84   struct tekhex_symbol_struct *prev;
85 } tekhex_symbol_type;
86 
87 static const char digs[] = "0123456789ABCDEF";
88 
89 static char sum_block[256];
90 
91 #define NOT_HEX      20
92 #define NIBBLE(x)    hex_value(x)
93 #define HEX(buffer) ((NIBBLE ((buffer)[0]) << 4) + NIBBLE ((buffer)[1]))
94 #define	ISHEX(x)    hex_p(x)
95 #define TOHEX(d, x) \
96   (d)[1] = digs[(x) & 0xf]; \
97   (d)[0] = digs[((x)>>4)&0xf];
98 
99 /* Here's an example
100    %3A6C6480004E56FFFC4E717063B0AEFFFC6D0652AEFFFC60F24E5E4E75
101    %1B3709T_SEGMENT1108FFFFFFFF
102    %2B3AB9T_SEGMENT7Dgcc_compiled$1087hello$c10
103    %373829T_SEGMENT80int$t1$r1$$214741080char$t2$r2$0$12710
104    %373769T_SEGMENT80long$int$t3$r1$$1080unsigned$int$t4$10
105    %373CA9T_SEGMENT80long$unsigned$in1080short$int$t6$r1$10
106    %373049T_SEGMENT80long$long$int$t71080short$unsigned$i10
107    %373A29T_SEGMENT80long$long$unsign1080signed$char$t10$10
108    %373D69T_SEGMENT80unsigned$char$t11080float$t12$r1$4$010
109    %373D19T_SEGMENT80double$t13$r1$8$1080long$double$t14$10
110    %2734D9T_SEGMENT8Bvoid$t15$151035_main10
111    %2F3CA9T_SEGMENT81$1081$1681$1E81$21487main$F110
112    %2832F9T_SEGMENT83i$18FFFFFFFC81$1481$214
113    %07 8 10 10
114 
115    explanation:
116    %3A6C6480004E56FFFC4E717063B0AEFFFC6D0652AEFFFC60F24E5E4E75
117     ^ ^^ ^     ^-data
118     | || +------ 4 char integer 0x8000
119     | |+-------- checksum
120     | +--------- type 6 (data record)
121     +----------- length 3a chars
122    <---------------------- 3a (58 chars) ------------------->
123 
124    %1B3709T_SEGMENT1108FFFFFFFF
125          ^         ^^ ^- 8 character integer 0xffffffff
126          |         |+-   1 character integer 0
127          |         +--   type 1 symbol (section definition)
128          +------------   9 char symbol T_SEGMENT
129 
130    %2B3AB9T_SEGMENT7Dgcc_compiled$1087hello$c10
131    %373829T_SEGMENT80int$t1$r1$$214741080char$t2$r2$0$12710
132    %373769T_SEGMENT80long$int$t3$r1$$1080unsigned$int$t4$10
133    %373CA9T_SEGMENT80long$unsigned$in1080short$int$t6$r1$10
134    %373049T_SEGMENT80long$long$int$t71080short$unsigned$i10
135    %373A29T_SEGMENT80long$long$unsign1080signed$char$t10$10
136    %373D69T_SEGMENT80unsigned$char$t11080float$t12$r1$4$010
137    %373D19T_SEGMENT80double$t13$r1$8$1080long$double$t14$10
138    %2734D9T_SEGMENT8Bvoid$t15$151035_main10
139    %2F3CA9T_SEGMENT81$1081$1681$1E81$21487main$F110
140    %2832F9T_SEGMENT83i$18FFFFFFFC81$1481$214
141    %0781010
142 
143    Turns into
144    sac@thepub$ ./objdump -dx -m m68k f
145 
146    f:     file format tekhex
147    -----x--- 9/55728 -134219416 Sep 29 15:13 1995 f
148    architecture: UNKNOWN!, flags 0x00000010:
149    HAS_SYMS
150    start address 0x00000000
151    SECTION 0 [D00000000]	: size 00020000 vma 00000000 align 2**0
152    ALLOC, LOAD
153    SECTION 1 [D00008000]	: size 00002001 vma 00008000 align 2**0
154 
155    SECTION 2 [T_SEGMENT]	: size ffffffff vma 00000000 align 2**0
156 
157    SYMBOL TABLE:
158    00000000  g       T_SEGMENT gcc_compiled$
159    00000000  g       T_SEGMENT hello$c
160    00000000  g       T_SEGMENT int$t1$r1$$21474
161    00000000  g       T_SEGMENT char$t2$r2$0$127
162    00000000  g       T_SEGMENT long$int$t3$r1$$
163    00000000  g       T_SEGMENT unsigned$int$t4$
164    00000000  g       T_SEGMENT long$unsigned$in
165    00000000  g       T_SEGMENT short$int$t6$r1$
166    00000000  g       T_SEGMENT long$long$int$t7
167    00000000  g       T_SEGMENT short$unsigned$i
168    00000000  g       T_SEGMENT long$long$unsign
169    00000000  g       T_SEGMENT signed$char$t10$
170    00000000  g       T_SEGMENT unsigned$char$t1
171    00000000  g       T_SEGMENT float$t12$r1$4$0
172    00000000  g       T_SEGMENT double$t13$r1$8$
173    00000000  g       T_SEGMENT long$double$t14$
174    00000000  g       T_SEGMENT void$t15$15
175    00000000  g       T_SEGMENT _main
176    00000000  g       T_SEGMENT $
177    00000000  g       T_SEGMENT $
178    00000000  g       T_SEGMENT $
179    00000010  g       T_SEGMENT $
180    00000000  g       T_SEGMENT main$F1
181    fcffffff  g       T_SEGMENT i$1
182    00000000  g       T_SEGMENT $
183    00000010  g       T_SEGMENT $
184 
185    RELOCATION RECORDS FOR [D00000000]: (none)
186 
187    RELOCATION RECORDS FOR [D00008000]: (none)
188 
189    RELOCATION RECORDS FOR [T_SEGMENT]: (none)
190 
191    Disassembly of section D00000000:
192    ...
193    00008000 ($+)7ff0 linkw fp,#-4
194    00008004 ($+)7ff4 nop
195    00008006 ($+)7ff6 movel #99,d0
196    00008008 ($+)7ff8 cmpl fp@(-4),d0
197    0000800c ($+)7ffc blts 00008014 ($+)8004
198    0000800e ($+)7ffe addql #1,fp@(-4)
199    00008012 ($+)8002 bras 00008006 ($+)7ff6
200    00008014 ($+)8004 unlk fp
201    00008016 ($+)8006 rts
202    ...  */
203 
204 static void
205 tekhex_init (void)
206 {
207   unsigned int i;
208   static bfd_boolean inited = FALSE;
209   int val;
210 
211   if (! inited)
212     {
213       inited = TRUE;
214       hex_init ();
215       val = 0;
216       for (i = 0; i < 10; i++)
217 	sum_block[i + '0'] = val++;
218 
219       for (i = 'A'; i <= 'Z'; i++)
220 	sum_block[i] = val++;
221 
222       sum_block['$'] = val++;
223       sum_block['%'] = val++;
224       sum_block['.'] = val++;
225       sum_block['_'] = val++;
226       for (i = 'a'; i <= 'z'; i++)
227 	sum_block[i] = val++;
228     }
229 }
230 
231 /* The maximum number of bytes on a line is FF.  */
232 #define MAXCHUNK 0xff
233 /* The number of bytes we fit onto a line on output.  */
234 #define CHUNK 21
235 
236 /* We cannot output our tekhexords as we see them, we have to glue them
237    together, this is done in this structure : */
238 
239 struct tekhex_data_list_struct
240 {
241   unsigned char *data;
242   bfd_vma where;
243   bfd_size_type size;
244   struct tekhex_data_list_struct *next;
245 
246 };
247 typedef struct tekhex_data_list_struct tekhex_data_list_type;
248 
249 #define CHUNK_MASK 0x1fff
250 
251 struct data_struct
252 {
253   char chunk_data[CHUNK_MASK + 1];
254   char chunk_init[CHUNK_MASK + 1];
255   bfd_vma vma;
256   struct data_struct *next;
257 };
258 
259 typedef struct tekhex_data_struct
260 {
261   tekhex_data_list_type *head;
262   unsigned int type;
263   struct tekhex_symbol_struct *symbols;
264   struct data_struct *data;
265 } tdata_type;
266 
267 #define enda(x) (x->vma + x->size)
268 
269 static bfd_boolean
270 getvalue (char **srcp, bfd_vma *valuep)
271 {
272   char *src = *srcp;
273   bfd_vma value = 0;
274   unsigned int len;
275 
276   if (!ISHEX (*src))
277     return FALSE;
278 
279   len = hex_value (*src++);
280   if (len == 0)
281     len = 16;
282   while (len--)
283     {
284       if (!ISHEX (*src))
285 	return FALSE;
286       value = value << 4 | hex_value (*src++);
287     }
288 
289   *srcp = src;
290   *valuep = value;
291   return TRUE;
292 }
293 
294 static bfd_boolean
295 getsym (char *dstp, char **srcp, unsigned int *lenp)
296 {
297   char *src = *srcp;
298   unsigned int i;
299   unsigned int len;
300 
301   if (!ISHEX (*src))
302     return FALSE;
303 
304   len = hex_value (*src++);
305   if (len == 0)
306     len = 16;
307   for (i = 0; i < len; i++)
308     dstp[i] = src[i];
309   dstp[i] = 0;
310   *srcp = src + i;
311   *lenp = len;
312   return TRUE;
313 }
314 
315 static struct data_struct *
316 find_chunk (bfd *abfd, bfd_vma vma)
317 {
318   struct data_struct *d = abfd->tdata.tekhex_data->data;
319 
320   vma &= ~CHUNK_MASK;
321   while (d && (d->vma) != vma)
322     d = d->next;
323 
324   if (!d)
325     {
326       /* No chunk for this address, so make one up.  */
327       d = bfd_zalloc (abfd, (bfd_size_type) sizeof (struct data_struct));
328 
329       if (!d)
330 	return NULL;
331 
332       d->next = abfd->tdata.tekhex_data->data;
333       d->vma = vma;
334       abfd->tdata.tekhex_data->data = d;
335     }
336   return d;
337 }
338 
339 static void
340 insert_byte (bfd *abfd, int value, bfd_vma addr)
341 {
342   /* Find the chunk that this byte needs and put it in.  */
343   struct data_struct *d = find_chunk (abfd, addr);
344 
345   d->chunk_data[addr & CHUNK_MASK] = value;
346   d->chunk_init[addr & CHUNK_MASK] = 1;
347 }
348 
349 /* The first pass is to find the names of all the sections, and see
350   how big the data is.  */
351 
352 static bfd_boolean
353 first_phase (bfd *abfd, int type, char *src)
354 {
355   asection *section = bfd_abs_section_ptr;
356   unsigned int len;
357   bfd_vma val;
358   char sym[17];			/* A symbol can only be 16chars long.  */
359 
360   switch (type)
361     {
362     case '6':
363       /* Data record - read it and store it.  */
364       {
365 	bfd_vma addr;
366 
367 	if (!getvalue (&src, &addr))
368 	  return FALSE;
369 
370 	while (*src)
371 	  {
372 	    insert_byte (abfd, HEX (src), addr);
373 	    src += 2;
374 	    addr++;
375 	  }
376       }
377 
378       return TRUE;
379     case '3':
380       /* Symbol record, read the segment.  */
381       if (!getsym (sym, &src, &len))
382 	return FALSE;
383       section = bfd_get_section_by_name (abfd, sym);
384       if (section == NULL)
385 	{
386 	  char *n = bfd_alloc (abfd, (bfd_size_type) len + 1);
387 
388 	  if (!n)
389 	    return FALSE;
390 	  memcpy (n, sym, len + 1);
391 	  section = bfd_make_section (abfd, n);
392 	  if (section == NULL)
393 	    return FALSE;
394 	}
395       while (*src)
396 	{
397 	  switch (*src)
398 	    {
399 	    case '1':		/* Section range.  */
400 	      src++;
401 	      if (!getvalue (&src, &section->vma))
402 		return FALSE;
403 	      if (!getvalue (&src, &val))
404 		return FALSE;
405 	      section->size = val - section->vma;
406 	      section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
407 	      break;
408 	    case '0':
409 	    case '2':
410 	    case '3':
411 	    case '4':
412 	    case '6':
413 	    case '7':
414 	    case '8':
415 	      /* Symbols, add to section.  */
416 	      {
417 		bfd_size_type amt = sizeof (tekhex_symbol_type);
418 		tekhex_symbol_type *new = bfd_alloc (abfd, amt);
419 		char stype = (*src);
420 
421 		if (!new)
422 		  return FALSE;
423 		new->symbol.the_bfd = abfd;
424 		src++;
425 		abfd->symcount++;
426 		abfd->flags |= HAS_SYMS;
427 		new->prev = abfd->tdata.tekhex_data->symbols;
428 		abfd->tdata.tekhex_data->symbols = new;
429 		if (!getsym (sym, &src, &len))
430 		  return FALSE;
431 		new->symbol.name = bfd_alloc (abfd, (bfd_size_type) len + 1);
432 		if (!new->symbol.name)
433 		  return FALSE;
434 		memcpy ((char *) (new->symbol.name), sym, len + 1);
435 		new->symbol.section = section;
436 		if (stype <= '4')
437 		  new->symbol.flags = (BSF_GLOBAL | BSF_EXPORT);
438 		else
439 		  new->symbol.flags = BSF_LOCAL;
440 		if (!getvalue (&src, &val))
441 		  return FALSE;
442 		new->symbol.value = val - section->vma;
443 		break;
444 	      }
445 	    default:
446 	      return FALSE;
447 	    }
448 	}
449     }
450 
451   return TRUE;
452 }
453 
454 /* Pass over a tekhex, calling one of the above functions on each
455    record.  */
456 
457 static bfd_boolean
458 pass_over (bfd *abfd, bfd_boolean (*func) (bfd *, int, char *))
459 {
460   unsigned int chars_on_line;
461   bfd_boolean eof = FALSE;
462 
463   /* To the front of the file.  */
464   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
465     return FALSE;
466   while (! eof)
467     {
468       char src[MAXCHUNK];
469       char type;
470 
471       /* Find first '%'.  */
472       eof = (bfd_boolean) (bfd_bread (src, (bfd_size_type) 1, abfd) != 1);
473       while (*src != '%' && !eof)
474 	eof = (bfd_boolean) (bfd_bread (src, (bfd_size_type) 1, abfd) != 1);
475 
476       if (eof)
477 	break;
478 
479       /* Fetch the type and the length and the checksum.  */
480       if (bfd_bread (src, (bfd_size_type) 5, abfd) != 5)
481 	return FALSE;
482 
483       type = src[2];
484 
485       if (!ISHEX (src[0]) || !ISHEX (src[1]))
486 	break;
487 
488       /* Already read five chars.  */
489       chars_on_line = HEX (src) - 5;
490 
491       if (chars_on_line >= MAXCHUNK)
492 	return FALSE;
493 
494       if (bfd_bread (src, (bfd_size_type) chars_on_line, abfd) != chars_on_line)
495 	return FALSE;
496 
497       /* Put a null at the end.  */
498       src[chars_on_line] = 0;
499 
500       if (!func (abfd, type, src))
501 	return FALSE;
502     }
503 
504   return TRUE;
505 }
506 
507 static long
508 tekhex_canonicalize_symtab (bfd *abfd, asymbol **table)
509 {
510   tekhex_symbol_type *p = abfd->tdata.tekhex_data->symbols;
511   unsigned int c = bfd_get_symcount (abfd);
512 
513   table[c] = 0;
514   while (p)
515     {
516       table[--c] = &(p->symbol);
517       p = p->prev;
518     }
519 
520   return bfd_get_symcount (abfd);
521 }
522 
523 static long
524 tekhex_get_symtab_upper_bound (bfd *abfd)
525 {
526   return (abfd->symcount + 1) * (sizeof (struct tekhex_asymbol_struct *));
527 
528 }
529 
530 static bfd_boolean
531 tekhex_mkobject (bfd *abfd)
532 {
533   tdata_type *tdata;
534 
535   tdata = bfd_alloc (abfd, (bfd_size_type) sizeof (tdata_type));
536   if (!tdata)
537     return FALSE;
538   abfd->tdata.tekhex_data = tdata;
539   tdata->type = 1;
540   tdata->head =  NULL;
541   tdata->symbols = NULL;
542   tdata->data = NULL;
543   return TRUE;
544 }
545 
546 /* Return TRUE if the file looks like it's in TekHex format. Just look
547    for a percent sign and some hex digits.  */
548 
549 static const bfd_target *
550 tekhex_object_p (bfd *abfd)
551 {
552   char b[4];
553 
554   tekhex_init ();
555 
556   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
557       || bfd_bread (b, (bfd_size_type) 4, abfd) != 4)
558     return NULL;
559 
560   if (b[0] != '%' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
561     return NULL;
562 
563   tekhex_mkobject (abfd);
564 
565   if (!pass_over (abfd, first_phase))
566     return NULL;
567 
568   return abfd->xvec;
569 }
570 
571 static void
572 move_section_contents (bfd *abfd,
573 		       asection *section,
574 		       const void * locationp,
575 		       file_ptr offset,
576 		       bfd_size_type count,
577 		       bfd_boolean get)
578 {
579   bfd_vma addr;
580   char *location = (char *) locationp;
581   bfd_vma prev_number = 1;	/* Nothing can have this as a high bit.  */
582   struct data_struct *d = NULL;
583 
584   BFD_ASSERT (offset == 0);
585   for (addr = section->vma; count != 0; count--, addr++)
586     {
587       /* Get high bits of address.  */
588       bfd_vma chunk_number = addr & ~(bfd_vma) CHUNK_MASK;
589       bfd_vma low_bits = addr & CHUNK_MASK;
590 
591       if (chunk_number != prev_number)
592 	/* Different chunk, so move pointer. */
593 	d = find_chunk (abfd, chunk_number);
594 
595       if (get)
596 	{
597 	  if (d->chunk_init[low_bits])
598 	    *location = d->chunk_data[low_bits];
599 	  else
600 	    *location = 0;
601 	}
602       else
603 	{
604 	  d->chunk_data[low_bits] = *location;
605 	  d->chunk_init[low_bits] = (*location != 0);
606 	}
607 
608       location++;
609     }
610 }
611 
612 static bfd_boolean
613 tekhex_get_section_contents (bfd *abfd,
614 			     asection *section,
615 			     void * locationp,
616 			     file_ptr offset,
617 			     bfd_size_type count)
618 {
619   if (section->flags & (SEC_LOAD | SEC_ALLOC))
620     {
621       move_section_contents (abfd, section, locationp, offset, count, TRUE);
622       return TRUE;
623     }
624 
625   return FALSE;
626 }
627 
628 static bfd_boolean
629 tekhex_set_arch_mach (bfd *abfd,
630 		      enum bfd_architecture arch,
631 		      unsigned long machine)
632 {
633   return bfd_default_set_arch_mach (abfd, arch, machine);
634 }
635 
636 /* We have to save up all the Tekhexords for a splurge before output.  */
637 
638 static bfd_boolean
639 tekhex_set_section_contents (bfd *abfd,
640 			     sec_ptr section,
641 			     const void * locationp,
642 			     file_ptr offset,
643 			     bfd_size_type bytes_to_do)
644 {
645   if (! abfd->output_has_begun)
646     {
647       /* The first time around, allocate enough sections to hold all the chunks.  */
648       asection *s = abfd->sections;
649       bfd_vma vma;
650 
651       for (s = abfd->sections; s; s = s->next)
652 	{
653 	  if (s->flags & SEC_LOAD)
654 	    {
655 	      for (vma = s->vma & ~(bfd_vma) CHUNK_MASK;
656 		   vma < s->vma + s->size;
657 		   vma += CHUNK_MASK)
658 		find_chunk (abfd, vma);
659 	    }
660 	}
661     }
662 
663   if (section->flags & (SEC_LOAD | SEC_ALLOC))
664     {
665       move_section_contents (abfd, section, locationp, offset, bytes_to_do,
666 			     FALSE);
667       return TRUE;
668     }
669 
670   return FALSE;
671 }
672 
673 static void
674 writevalue (char **dst, bfd_vma value)
675 {
676   char *p = *dst;
677   int len;
678   int shift;
679 
680   for (len = 8, shift = 28; shift; shift -= 4, len--)
681     {
682       if ((value >> shift) & 0xf)
683 	{
684 	  *p++ = len + '0';
685 	  while (len)
686 	    {
687 	      *p++ = digs[(value >> shift) & 0xf];
688 	      shift -= 4;
689 	      len--;
690 	    }
691 	  *dst = p;
692 	  return;
693 
694 	}
695     }
696   *p++ = '1';
697   *p++ = '0';
698   *dst = p;
699 }
700 
701 static void
702 writesym (char **dst, const char *sym)
703 {
704   char *p = *dst;
705   int len = (sym ? strlen (sym) : 0);
706 
707   if (len >= 16)
708     {
709       *p++ = '0';
710       len = 16;
711     }
712   else
713     {
714       if (len == 0)
715 	{
716 	  *p++ = '1';
717 	  sym = "$";
718 	  len = 1;
719 	}
720       else
721 	*p++ = digs[len];
722     }
723 
724   while (len--)
725     *p++ = *sym++;
726 
727   *dst = p;
728 }
729 
730 static void
731 out (bfd *abfd, int type, char *start, char *end)
732 {
733   int sum = 0;
734   char *s;
735   char front[6];
736   bfd_size_type wrlen;
737 
738   front[0] = '%';
739   TOHEX (front + 1, end - start + 5);
740   front[3] = type;
741 
742   for (s = start; s < end; s++)
743     sum += sum_block[(unsigned char) *s];
744 
745   sum += sum_block[(unsigned char) front[1]];	/* Length.  */
746   sum += sum_block[(unsigned char) front[2]];
747   sum += sum_block[(unsigned char) front[3]];	/* Type.  */
748   TOHEX (front + 4, sum);
749   if (bfd_bwrite (front, (bfd_size_type) 6, abfd) != 6)
750     abort ();
751   end[0] = '\n';
752   wrlen = end - start + 1;
753   if (bfd_bwrite (start, wrlen, abfd) != wrlen)
754     abort ();
755 }
756 
757 static bfd_boolean
758 tekhex_write_object_contents (bfd *abfd)
759 {
760   char buffer[100];
761   asymbol **p;
762   asection *s;
763   struct data_struct *d;
764 
765   tekhex_init ();
766 
767   /* And the raw data.  */
768   for (d = abfd->tdata.tekhex_data->data;
769        d != NULL;
770        d = d->next)
771     {
772       int low;
773 
774       const int span = 32;
775       int addr;
776 
777       /* Write it in blocks of 32 bytes.  */
778       for (addr = 0; addr < CHUNK_MASK + 1; addr += span)
779 	{
780 	  int need = 0;
781 
782 	  /* Check to see if necessary.  */
783 	  for (low = 0; !need && low < span; low++)
784 	    if (d->chunk_init[addr + low])
785 	      need = 1;
786 
787 	  if (need)
788 	    {
789 	      char *dst = buffer;
790 
791 	      writevalue (&dst, addr + d->vma);
792 	      for (low = 0; low < span; low++)
793 		{
794 		  TOHEX (dst, d->chunk_data[addr + low]);
795 		  dst += 2;
796 		}
797 	      out (abfd, '6', buffer, dst);
798 	    }
799 	}
800     }
801 
802   /* Write all the section headers for the sections.  */
803   for (s = abfd->sections; s != NULL; s = s->next)
804     {
805       char *dst = buffer;
806 
807       writesym (&dst, s->name);
808       *dst++ = '1';
809       writevalue (&dst, s->vma);
810       writevalue (&dst, s->vma + s->size);
811       out (abfd, '3', buffer, dst);
812     }
813 
814   /* And the symbols.  */
815   if (abfd->outsymbols)
816     {
817       for (p = abfd->outsymbols; *p; p++)
818 	{
819 	  int section_code = bfd_decode_symclass (*p);
820 
821 	  if (section_code != '?')
822 	    {
823 	      /* Do not include debug symbols.  */
824 	      asymbol *sym = *p;
825 	      char *dst = buffer;
826 
827 	      writesym (&dst, sym->section->name);
828 
829 	      switch (section_code)
830 		{
831 		case 'A':
832 		  *dst++ = '2';
833 		  break;
834 		case 'a':
835 		  *dst++ = '6';
836 		  break;
837 		case 'D':
838 		case 'B':
839 		case 'O':
840 		  *dst++ = '4';
841 		  break;
842 		case 'd':
843 		case 'b':
844 		case 'o':
845 		  *dst++ = '8';
846 		  break;
847 		case 'T':
848 		  *dst++ = '3';
849 		  break;
850 		case 't':
851 		  *dst++ = '7';
852 		  break;
853 		case 'C':
854 		case 'U':
855 		  bfd_set_error (bfd_error_wrong_format);
856 		  return FALSE;
857 		}
858 
859 	      writesym (&dst, sym->name);
860 	      writevalue (&dst, sym->value + sym->section->vma);
861 	      out (abfd, '3', buffer, dst);
862 	    }
863 	}
864     }
865 
866   /* And the terminator.  */
867   if (bfd_bwrite ("%0781010\n", (bfd_size_type) 9, abfd) != 9)
868     abort ();
869   return TRUE;
870 }
871 
872 static int
873 tekhex_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
874 		       struct bfd_link_info *info ATTRIBUTE_UNUSED)
875 {
876   return 0;
877 }
878 
879 static asymbol *
880 tekhex_make_empty_symbol (bfd *abfd)
881 {
882   bfd_size_type amt = sizeof (struct tekhex_symbol_struct);
883   tekhex_symbol_type *new = bfd_zalloc (abfd, amt);
884 
885   if (!new)
886     return NULL;
887   new->symbol.the_bfd = abfd;
888   new->prev =  NULL;
889   return &(new->symbol);
890 }
891 
892 static void
893 tekhex_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
894 			asymbol *symbol,
895 			symbol_info *ret)
896 {
897   bfd_symbol_info (symbol, ret);
898 }
899 
900 static void
901 tekhex_print_symbol (bfd *abfd,
902 		     void * filep,
903 		     asymbol *symbol,
904 		     bfd_print_symbol_type how)
905 {
906   FILE *file = (FILE *) filep;
907 
908   switch (how)
909     {
910     case bfd_print_symbol_name:
911       fprintf (file, "%s", symbol->name);
912       break;
913     case bfd_print_symbol_more:
914       break;
915 
916     case bfd_print_symbol_all:
917       {
918 	const char *section_name = symbol->section->name;
919 
920 	bfd_print_symbol_vandf (abfd, (void *) file, symbol);
921 
922 	fprintf (file, " %-5s %s",
923 		 section_name, symbol->name);
924       }
925     }
926 }
927 
928 #define	tekhex_close_and_cleanup                    _bfd_generic_close_and_cleanup
929 #define tekhex_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
930 #define tekhex_new_section_hook                     _bfd_generic_new_section_hook
931 #define tekhex_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
932 #define tekhex_bfd_is_local_label_name               bfd_generic_is_local_label_name
933 #define tekhex_get_lineno                           _bfd_nosymbols_get_lineno
934 #define tekhex_find_nearest_line                    _bfd_nosymbols_find_nearest_line
935 #define tekhex_find_inliner_info                    _bfd_nosymbols_find_inliner_info
936 #define tekhex_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
937 #define tekhex_read_minisymbols                     _bfd_generic_read_minisymbols
938 #define tekhex_minisymbol_to_symbol                 _bfd_generic_minisymbol_to_symbol
939 #define tekhex_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
940 #define tekhex_bfd_relax_section                    bfd_generic_relax_section
941 #define tekhex_bfd_gc_sections                      bfd_generic_gc_sections
942 #define tekhex_bfd_merge_sections                   bfd_generic_merge_sections
943 #define tekhex_bfd_is_group_section                 bfd_generic_is_group_section
944 #define tekhex_bfd_discard_group                    bfd_generic_discard_group
945 #define tekhex_section_already_linked               _bfd_generic_section_already_linked
946 #define tekhex_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
947 #define tekhex_bfd_link_hash_table_free             _bfd_generic_link_hash_table_free
948 #define tekhex_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
949 #define tekhex_bfd_link_just_syms                   _bfd_generic_link_just_syms
950 #define tekhex_bfd_final_link                       _bfd_generic_final_link
951 #define tekhex_bfd_link_split_section               _bfd_generic_link_split_section
952 #define tekhex_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
953 
954 const bfd_target tekhex_vec =
955 {
956   "tekhex",			/* Name.  */
957   bfd_target_tekhex_flavour,
958   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
959   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
960   (EXEC_P |			/* Object flags.  */
961    HAS_SYMS | HAS_LINENO | HAS_DEBUG |
962    HAS_RELOC | HAS_LOCALS | WP_TEXT | D_PAGED),
963   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
964    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
965   0,				/* Leading underscore.  */
966   ' ',				/* AR_pad_char.  */
967   16,				/* AR_max_namelen.  */
968   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
969   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
970   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
971   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
972   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
973   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers.  */
974 
975   {
976     _bfd_dummy_target,
977     tekhex_object_p,		/* bfd_check_format.  */
978     _bfd_dummy_target,
979     _bfd_dummy_target,
980   },
981   {
982     bfd_false,
983     tekhex_mkobject,
984     _bfd_generic_mkarchive,
985     bfd_false,
986   },
987   {				/* bfd_write_contents.  */
988     bfd_false,
989     tekhex_write_object_contents,
990     _bfd_write_archive_contents,
991     bfd_false,
992   },
993 
994   BFD_JUMP_TABLE_GENERIC (tekhex),
995   BFD_JUMP_TABLE_COPY (_bfd_generic),
996   BFD_JUMP_TABLE_CORE (_bfd_nocore),
997   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
998   BFD_JUMP_TABLE_SYMBOLS (tekhex),
999   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1000   BFD_JUMP_TABLE_WRITE (tekhex),
1001   BFD_JUMP_TABLE_LINK (tekhex),
1002   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1003 
1004   NULL,
1005 
1006   NULL
1007 };
1008