Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5197 serge 1
/* BFD backend for Extended Tektronix Hex Format  objects.
2
   Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002,
3
   2003, 2004, 2005, 2006, 2007, 2009, 2011 Free Software Foundation, Inc.
4
   Written by Steve Chamberlain of Cygnus Support .
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
	%
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 = (struct data_struct *)
328
          bfd_zalloc (abfd, (bfd_size_type) sizeof (struct data_struct));
329
 
330
      if (!d)
331
	return NULL;
332
 
333
      d->next = abfd->tdata.tekhex_data->data;
334
      d->vma = vma;
335
      abfd->tdata.tekhex_data->data = d;
336
    }
337
  return d;
338
}
339
 
340
static void
341
insert_byte (bfd *abfd, int value, bfd_vma addr)
342
{
343
  /* Find the chunk that this byte needs and put it in.  */
344
  struct data_struct *d = find_chunk (abfd, addr);
345
 
346
  d->chunk_data[addr & CHUNK_MASK] = value;
347
  d->chunk_init[addr & CHUNK_MASK] = 1;
348
}
349
 
350
/* The first pass is to find the names of all the sections, and see
351
  how big the data is.  */
352
 
353
static bfd_boolean
354
first_phase (bfd *abfd, int type, char *src)
355
{
356
  asection *section = bfd_abs_section_ptr;
357
  unsigned int len;
358
  bfd_vma val;
359
  char sym[17];			/* A symbol can only be 16chars long.  */
360
 
361
  switch (type)
362
    {
363
    case '6':
364
      /* Data record - read it and store it.  */
365
      {
366
	bfd_vma addr;
367
 
368
	if (!getvalue (&src, &addr))
369
	  return FALSE;
370
 
371
	while (*src)
372
	  {
373
	    insert_byte (abfd, HEX (src), addr);
374
	    src += 2;
375
	    addr++;
376
	  }
377
      }
378
 
379
      return TRUE;
380
    case '3':
381
      /* Symbol record, read the segment.  */
382
      if (!getsym (sym, &src, &len))
383
	return FALSE;
384
      section = bfd_get_section_by_name (abfd, sym);
385
      if (section == NULL)
386
	{
387
	  char *n = (char *) bfd_alloc (abfd, (bfd_size_type) len + 1);
388
 
389
	  if (!n)
390
	    return FALSE;
391
	  memcpy (n, sym, len + 1);
392
	  section = bfd_make_section (abfd, n);
393
	  if (section == NULL)
394
	    return FALSE;
395
	}
396
      while (*src)
397
	{
398
	  switch (*src)
399
	    {
400
	    case '1':		/* Section range.  */
401
	      src++;
402
	      if (!getvalue (&src, §ion->vma))
403
		return FALSE;
404
	      if (!getvalue (&src, &val))
405
		return FALSE;
406
	      section->size = val - section->vma;
407
	      section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
408
	      break;
409
	    case '0':
410
	    case '2':
411
	    case '3':
412
	    case '4':
413
	    case '6':
414
	    case '7':
415
	    case '8':
416
	      /* Symbols, add to section.  */
417
	      {
418
		bfd_size_type amt = sizeof (tekhex_symbol_type);
419
		tekhex_symbol_type *new_symbol = (tekhex_symbol_type *)
420
                    bfd_alloc (abfd, amt);
421
		char stype = (*src);
422
 
423
		if (!new_symbol)
424
		  return FALSE;
425
		new_symbol->symbol.the_bfd = abfd;
426
		src++;
427
		abfd->symcount++;
428
		abfd->flags |= HAS_SYMS;
429
		new_symbol->prev = abfd->tdata.tekhex_data->symbols;
430
		abfd->tdata.tekhex_data->symbols = new_symbol;
431
		if (!getsym (sym, &src, &len))
432
		  return FALSE;
433
		new_symbol->symbol.name = (const char *)
434
                    bfd_alloc (abfd, (bfd_size_type) len + 1);
435
		if (!new_symbol->symbol.name)
436
		  return FALSE;
437
		memcpy ((char *) (new_symbol->symbol.name), sym, len + 1);
438
		new_symbol->symbol.section = section;
439
		if (stype <= '4')
440
		  new_symbol->symbol.flags = (BSF_GLOBAL | BSF_EXPORT);
441
		else
442
		  new_symbol->symbol.flags = BSF_LOCAL;
443
		if (!getvalue (&src, &val))
444
		  return FALSE;
445
		new_symbol->symbol.value = val - section->vma;
446
		break;
447
	      }
448
	    default:
449
	      return FALSE;
450
	    }
451
	}
452
    }
453
 
454
  return TRUE;
455
}
456
 
457
/* Pass over a tekhex, calling one of the above functions on each
458
   record.  */
459
 
460
static bfd_boolean
461
pass_over (bfd *abfd, bfd_boolean (*func) (bfd *, int, char *))
462
{
463
  unsigned int chars_on_line;
464
  bfd_boolean is_eof = FALSE;
465
 
466
  /* To the front of the file.  */
467
  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
468
    return FALSE;
469
  while (! is_eof)
470
    {
471
      char src[MAXCHUNK];
472
      char type;
473
 
474
      /* Find first '%'.  */
475
      is_eof = (bfd_boolean) (bfd_bread (src, (bfd_size_type) 1, abfd) != 1);
476
      while (*src != '%' && !is_eof)
477
	is_eof = (bfd_boolean) (bfd_bread (src, (bfd_size_type) 1, abfd) != 1);
478
 
479
      if (is_eof)
480
	break;
481
 
482
      /* Fetch the type and the length and the checksum.  */
483
      if (bfd_bread (src, (bfd_size_type) 5, abfd) != 5)
484
	return FALSE;
485
 
486
      type = src[2];
487
 
488
      if (!ISHEX (src[0]) || !ISHEX (src[1]))
489
	break;
490
 
491
      /* Already read five chars.  */
492
      chars_on_line = HEX (src) - 5;
493
 
494
      if (chars_on_line >= MAXCHUNK)
495
	return FALSE;
496
 
497
      if (bfd_bread (src, (bfd_size_type) chars_on_line, abfd) != chars_on_line)
498
	return FALSE;
499
 
500
      /* Put a null at the end.  */
501
      src[chars_on_line] = 0;
502
 
503
      if (!func (abfd, type, src))
504
	return FALSE;
505
    }
506
 
507
  return TRUE;
508
}
509
 
510
static long
511
tekhex_canonicalize_symtab (bfd *abfd, asymbol **table)
512
{
513
  tekhex_symbol_type *p = abfd->tdata.tekhex_data->symbols;
514
  unsigned int c = bfd_get_symcount (abfd);
515
 
516
  table[c] = 0;
517
  while (p)
518
    {
519
      table[--c] = &(p->symbol);
520
      p = p->prev;
521
    }
522
 
523
  return bfd_get_symcount (abfd);
524
}
525
 
526
static long
527
tekhex_get_symtab_upper_bound (bfd *abfd)
528
{
529
  return (abfd->symcount + 1) * (sizeof (struct tekhex_asymbol_struct *));
530
 
531
}
532
 
533
static bfd_boolean
534
tekhex_mkobject (bfd *abfd)
535
{
536
  tdata_type *tdata;
537
 
538
  tdata = (tdata_type *) bfd_alloc (abfd, (bfd_size_type) sizeof (tdata_type));
539
  if (!tdata)
540
    return FALSE;
541
  abfd->tdata.tekhex_data = tdata;
542
  tdata->type = 1;
543
  tdata->head =  NULL;
544
  tdata->symbols = NULL;
545
  tdata->data = NULL;
546
  return TRUE;
547
}
548
 
549
/* Return TRUE if the file looks like it's in TekHex format. Just look
550
   for a percent sign and some hex digits.  */
551
 
552
static const bfd_target *
553
tekhex_object_p (bfd *abfd)
554
{
555
  char b[4];
556
 
557
  tekhex_init ();
558
 
559
  if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
560
      || bfd_bread (b, (bfd_size_type) 4, abfd) != 4)
561
    return NULL;
562
 
563
  if (b[0] != '%' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
564
    return NULL;
565
 
566
  tekhex_mkobject (abfd);
567
 
568
  if (!pass_over (abfd, first_phase))
569
    return NULL;
570
 
571
  return abfd->xvec;
572
}
573
 
574
static void
575
move_section_contents (bfd *abfd,
576
		       asection *section,
577
		       const void * locationp,
578
		       file_ptr offset,
579
		       bfd_size_type count,
580
		       bfd_boolean get)
581
{
582
  bfd_vma addr;
583
  char *location = (char *) locationp;
584
  bfd_vma prev_number = 1;	/* Nothing can have this as a high bit.  */
585
  struct data_struct *d = NULL;
586
 
587
  BFD_ASSERT (offset == 0);
588
  for (addr = section->vma; count != 0; count--, addr++)
589
    {
590
      /* Get high bits of address.  */
591
      bfd_vma chunk_number = addr & ~(bfd_vma) CHUNK_MASK;
592
      bfd_vma low_bits = addr & CHUNK_MASK;
593
 
594
      if (chunk_number != prev_number)
595
	/* Different chunk, so move pointer. */
596
	d = find_chunk (abfd, chunk_number);
597
 
598
      if (get)
599
	{
600
	  if (d->chunk_init[low_bits])
601
	    *location = d->chunk_data[low_bits];
602
	  else
603
	    *location = 0;
604
	}
605
      else
606
	{
607
	  d->chunk_data[low_bits] = *location;
608
	  d->chunk_init[low_bits] = (*location != 0);
609
	}
610
 
611
      location++;
612
    }
613
}
614
 
615
static bfd_boolean
616
tekhex_get_section_contents (bfd *abfd,
617
			     asection *section,
618
			     void * locationp,
619
			     file_ptr offset,
620
			     bfd_size_type count)
621
{
622
  if (section->flags & (SEC_LOAD | SEC_ALLOC))
623
    {
624
      move_section_contents (abfd, section, locationp, offset, count, TRUE);
625
      return TRUE;
626
    }
627
 
628
  return FALSE;
629
}
630
 
631
static bfd_boolean
632
tekhex_set_arch_mach (bfd *abfd,
633
		      enum bfd_architecture arch,
634
		      unsigned long machine)
635
{
636
  return bfd_default_set_arch_mach (abfd, arch, machine);
637
}
638
 
639
/* We have to save up all the Tekhexords for a splurge before output.  */
640
 
641
static bfd_boolean
642
tekhex_set_section_contents (bfd *abfd,
643
			     sec_ptr section,
644
			     const void * locationp,
645
			     file_ptr offset,
646
			     bfd_size_type bytes_to_do)
647
{
648
  if (! abfd->output_has_begun)
649
    {
650
      /* The first time around, allocate enough sections to hold all the chunks.  */
651
      asection *s = abfd->sections;
652
      bfd_vma vma;
653
 
654
      for (s = abfd->sections; s; s = s->next)
655
	{
656
	  if (s->flags & SEC_LOAD)
657
	    {
658
	      for (vma = s->vma & ~(bfd_vma) CHUNK_MASK;
659
		   vma < s->vma + s->size;
660
		   vma += CHUNK_MASK)
661
		find_chunk (abfd, vma);
662
	    }
663
	}
664
    }
665
 
666
  if (section->flags & (SEC_LOAD | SEC_ALLOC))
667
    {
668
      move_section_contents (abfd, section, locationp, offset, bytes_to_do,
669
			     FALSE);
670
      return TRUE;
671
    }
672
 
673
  return FALSE;
674
}
675
 
676
static void
677
writevalue (char **dst, bfd_vma value)
678
{
679
  char *p = *dst;
680
  int len;
681
  int shift;
682
 
683
  for (len = 8, shift = 28; shift; shift -= 4, len--)
684
    {
685
      if ((value >> shift) & 0xf)
686
	{
687
	  *p++ = len + '0';
688
	  while (len)
689
	    {
690
	      *p++ = digs[(value >> shift) & 0xf];
691
	      shift -= 4;
692
	      len--;
693
	    }
694
	  *dst = p;
695
	  return;
696
 
697
	}
698
    }
699
  *p++ = '1';
700
  *p++ = '0';
701
  *dst = p;
702
}
703
 
704
static void
705
writesym (char **dst, const char *sym)
706
{
707
  char *p = *dst;
708
  int len = (sym ? strlen (sym) : 0);
709
 
710
  if (len >= 16)
711
    {
712
      *p++ = '0';
713
      len = 16;
714
    }
715
  else
716
    {
717
      if (len == 0)
718
	{
719
	  *p++ = '1';
720
	  sym = "$";
721
	  len = 1;
722
	}
723
      else
724
	*p++ = digs[len];
725
    }
726
 
727
  while (len--)
728
    *p++ = *sym++;
729
 
730
  *dst = p;
731
}
732
 
733
static void
734
out (bfd *abfd, int type, char *start, char *end)
735
{
736
  int sum = 0;
737
  char *s;
738
  char front[6];
739
  bfd_size_type wrlen;
740
 
741
  front[0] = '%';
742
  TOHEX (front + 1, end - start + 5);
743
  front[3] = type;
744
 
745
  for (s = start; s < end; s++)
746
    sum += sum_block[(unsigned char) *s];
747
 
748
  sum += sum_block[(unsigned char) front[1]];	/* Length.  */
749
  sum += sum_block[(unsigned char) front[2]];
750
  sum += sum_block[(unsigned char) front[3]];	/* Type.  */
751
  TOHEX (front + 4, sum);
752
  if (bfd_bwrite (front, (bfd_size_type) 6, abfd) != 6)
753
    abort ();
754
  end[0] = '\n';
755
  wrlen = end - start + 1;
756
  if (bfd_bwrite (start, wrlen, abfd) != wrlen)
757
    abort ();
758
}
759
 
760
static bfd_boolean
761
tekhex_write_object_contents (bfd *abfd)
762
{
763
  char buffer[100];
764
  asymbol **p;
765
  asection *s;
766
  struct data_struct *d;
767
 
768
  tekhex_init ();
769
 
770
  /* And the raw data.  */
771
  for (d = abfd->tdata.tekhex_data->data;
772
       d != NULL;
773
       d = d->next)
774
    {
775
      int low;
776
 
777
      const int span = 32;
778
      int addr;
779
 
780
      /* Write it in blocks of 32 bytes.  */
781
      for (addr = 0; addr < CHUNK_MASK + 1; addr += span)
782
	{
783
	  int need = 0;
784
 
785
	  /* Check to see if necessary.  */
786
	  for (low = 0; !need && low < span; low++)
787
	    if (d->chunk_init[addr + low])
788
	      need = 1;
789
 
790
	  if (need)
791
	    {
792
	      char *dst = buffer;
793
 
794
	      writevalue (&dst, addr + d->vma);
795
	      for (low = 0; low < span; low++)
796
		{
797
		  TOHEX (dst, d->chunk_data[addr + low]);
798
		  dst += 2;
799
		}
800
	      out (abfd, '6', buffer, dst);
801
	    }
802
	}
803
    }
804
 
805
  /* Write all the section headers for the sections.  */
806
  for (s = abfd->sections; s != NULL; s = s->next)
807
    {
808
      char *dst = buffer;
809
 
810
      writesym (&dst, s->name);
811
      *dst++ = '1';
812
      writevalue (&dst, s->vma);
813
      writevalue (&dst, s->vma + s->size);
814
      out (abfd, '3', buffer, dst);
815
    }
816
 
817
  /* And the symbols.  */
818
  if (abfd->outsymbols)
819
    {
820
      for (p = abfd->outsymbols; *p; p++)
821
	{
822
	  int section_code = bfd_decode_symclass (*p);
823
 
824
	  if (section_code != '?')
825
	    {
826
	      /* Do not include debug symbols.  */
827
	      asymbol *sym = *p;
828
	      char *dst = buffer;
829
 
830
	      writesym (&dst, sym->section->name);
831
 
832
	      switch (section_code)
833
		{
834
		case 'A':
835
		  *dst++ = '2';
836
		  break;
837
		case 'a':
838
		  *dst++ = '6';
839
		  break;
840
		case 'D':
841
		case 'B':
842
		case 'O':
843
		  *dst++ = '4';
844
		  break;
845
		case 'd':
846
		case 'b':
847
		case 'o':
848
		  *dst++ = '8';
849
		  break;
850
		case 'T':
851
		  *dst++ = '3';
852
		  break;
853
		case 't':
854
		  *dst++ = '7';
855
		  break;
856
		case 'C':
857
		case 'U':
858
		  bfd_set_error (bfd_error_wrong_format);
859
		  return FALSE;
860
		}
861
 
862
	      writesym (&dst, sym->name);
863
	      writevalue (&dst, sym->value + sym->section->vma);
864
	      out (abfd, '3', buffer, dst);
865
	    }
866
	}
867
    }
868
 
869
  /* And the terminator.  */
870
  if (bfd_bwrite ("%0781010\n", (bfd_size_type) 9, abfd) != 9)
871
    abort ();
872
  return TRUE;
873
}
874
 
875
static int
876
tekhex_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
877
		       struct bfd_link_info *info ATTRIBUTE_UNUSED)
878
{
879
  return 0;
880
}
881
 
882
static asymbol *
883
tekhex_make_empty_symbol (bfd *abfd)
884
{
885
  bfd_size_type amt = sizeof (struct tekhex_symbol_struct);
886
  tekhex_symbol_type *new_symbol = (tekhex_symbol_type *) bfd_zalloc (abfd,
887
                                                                      amt);
888
 
889
  if (!new_symbol)
890
    return NULL;
891
  new_symbol->symbol.the_bfd = abfd;
892
  new_symbol->prev =  NULL;
893
  return &(new_symbol->symbol);
894
}
895
 
896
static void
897
tekhex_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
898
			asymbol *symbol,
899
			symbol_info *ret)
900
{
901
  bfd_symbol_info (symbol, ret);
902
}
903
 
904
static void
905
tekhex_print_symbol (bfd *abfd,
906
		     void * filep,
907
		     asymbol *symbol,
908
		     bfd_print_symbol_type how)
909
{
910
  FILE *file = (FILE *) filep;
911
 
912
  switch (how)
913
    {
914
    case bfd_print_symbol_name:
915
      fprintf (file, "%s", symbol->name);
916
      break;
917
    case bfd_print_symbol_more:
918
      break;
919
 
920
    case bfd_print_symbol_all:
921
      {
922
	const char *section_name = symbol->section->name;
923
 
924
	bfd_print_symbol_vandf (abfd, (void *) file, symbol);
925
 
926
	fprintf (file, " %-5s %s",
927
		 section_name, symbol->name);
928
      }
929
    }
930
}
931
 
932
#define	tekhex_close_and_cleanup                    _bfd_generic_close_and_cleanup
933
#define tekhex_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
934
#define tekhex_new_section_hook                     _bfd_generic_new_section_hook
935
#define tekhex_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
936
#define tekhex_bfd_is_local_label_name               bfd_generic_is_local_label_name
937
#define tekhex_get_lineno                           _bfd_nosymbols_get_lineno
938
#define tekhex_find_nearest_line                    _bfd_nosymbols_find_nearest_line
939
#define tekhex_find_inliner_info                    _bfd_nosymbols_find_inliner_info
940
#define tekhex_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
941
#define tekhex_read_minisymbols                     _bfd_generic_read_minisymbols
942
#define tekhex_minisymbol_to_symbol                 _bfd_generic_minisymbol_to_symbol
943
#define tekhex_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
944
#define tekhex_bfd_relax_section                    bfd_generic_relax_section
945
#define tekhex_bfd_gc_sections                      bfd_generic_gc_sections
946
#define tekhex_bfd_lookup_section_flags		    bfd_generic_lookup_section_flags
947
#define tekhex_bfd_merge_sections                   bfd_generic_merge_sections
948
#define tekhex_bfd_is_group_section                 bfd_generic_is_group_section
949
#define tekhex_bfd_discard_group                    bfd_generic_discard_group
950
#define tekhex_section_already_linked               _bfd_generic_section_already_linked
951
#define tekhex_bfd_define_common_symbol             bfd_generic_define_common_symbol
952
#define tekhex_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
953
#define tekhex_bfd_link_hash_table_free             _bfd_generic_link_hash_table_free
954
#define tekhex_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
955
#define tekhex_bfd_link_just_syms                   _bfd_generic_link_just_syms
956
#define tekhex_bfd_copy_link_hash_symbol_type \
957
  _bfd_generic_copy_link_hash_symbol_type
958
#define tekhex_bfd_final_link                       _bfd_generic_final_link
959
#define tekhex_bfd_link_split_section               _bfd_generic_link_split_section
960
#define tekhex_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
961
 
962
const bfd_target tekhex_vec =
963
{
964
  "tekhex",			/* Name.  */
965
  bfd_target_tekhex_flavour,
966
  BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
967
  BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
968
  (EXEC_P |			/* Object flags.  */
969
   HAS_SYMS | HAS_LINENO | HAS_DEBUG |
970
   HAS_RELOC | HAS_LOCALS | WP_TEXT | D_PAGED),
971
  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
972
   | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
973
  0,				/* Leading underscore.  */
974
  ' ',				/* AR_pad_char.  */
975
  16,				/* AR_max_namelen.  */
976
  0,				/* match priority.  */
977
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
978
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
979
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
980
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
981
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
982
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers.  */
983
 
984
  {
985
    _bfd_dummy_target,
986
    tekhex_object_p,		/* bfd_check_format.  */
987
    _bfd_dummy_target,
988
    _bfd_dummy_target,
989
  },
990
  {
991
    bfd_false,
992
    tekhex_mkobject,
993
    _bfd_generic_mkarchive,
994
    bfd_false,
995
  },
996
  {				/* bfd_write_contents.  */
997
    bfd_false,
998
    tekhex_write_object_contents,
999
    _bfd_write_archive_contents,
1000
    bfd_false,
1001
  },
1002
 
1003
  BFD_JUMP_TABLE_GENERIC (tekhex),
1004
  BFD_JUMP_TABLE_COPY (_bfd_generic),
1005
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
1006
  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1007
  BFD_JUMP_TABLE_SYMBOLS (tekhex),
1008
  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1009
  BFD_JUMP_TABLE_WRITE (tekhex),
1010
  BFD_JUMP_TABLE_LINK (tekhex),
1011
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1012
 
1013
  NULL,
1014
 
1015
  NULL
1016
};