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