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
75typedef struct
76{
77  bfd_vma low;
78  bfd_vma high;
79} addr_range_type;
80
81typedef struct tekhex_symbol_struct
82{
83  asymbol symbol;
84  struct tekhex_symbol_struct *prev;
85} tekhex_symbol_type;
86
87static const char digs[] = "0123456789ABCDEF";
88
89static 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
204static void
205tekhex_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
239struct 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};
247typedef struct tekhex_data_list_struct tekhex_data_list_type;
248
249#define CHUNK_MASK 0x1fff
250
251struct 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
259typedef 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
269static bfd_boolean
270getvalue (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
294static bfd_boolean
295getsym (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
315static struct data_struct *
316find_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
339static void
340insert_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
352static bfd_boolean
353first_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
457static bfd_boolean
458pass_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
507static long
508tekhex_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
523static long
524tekhex_get_symtab_upper_bound (bfd *abfd)
525{
526  return (abfd->symcount + 1) * (sizeof (struct tekhex_asymbol_struct *));
527
528}
529
530static bfd_boolean
531tekhex_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
549static const bfd_target *
550tekhex_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
571static void
572move_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
612static bfd_boolean
613tekhex_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
628static bfd_boolean
629tekhex_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
638static bfd_boolean
639tekhex_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
673static void
674writevalue (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
701static void
702writesym (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
730static void
731out (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
757static bfd_boolean
758tekhex_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
872static int
873tekhex_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
874		       struct bfd_link_info *info ATTRIBUTE_UNUSED)
875{
876  return 0;
877}
878
879static asymbol *
880tekhex_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
892static void
893tekhex_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
894			asymbol *symbol,
895			symbol_info *ret)
896{
897  bfd_symbol_info (symbol, ret);
898}
899
900static void
901tekhex_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
954const 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