Subversion Repositories Kolibri OS

Rev

Rev 5197 | Details | Compare with Previous | Last modification | View Log | RSS feed

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