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