~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to binutils/bfd/tekhex.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* BFD backend for Extended Tektronix Hex Format  objects.
 
2
   Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
 
3
   Free Software Foundation, Inc.
 
4
   Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
 
5
 
 
6
This file is part of BFD, the Binary File Descriptor library.
 
7
 
 
8
This program is free software; you can redistribute it and/or modify
 
9
it under the terms of the GNU General Public License as published by
 
10
the Free Software Foundation; either version 2 of the License, or
 
11
(at your option) any later version.
 
12
 
 
13
This program is distributed in the hope that it will be useful,
 
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
GNU General Public License for more details.
 
17
 
 
18
You should have received a copy of the GNU General Public License
 
19
along with this program; if not, write to the Free Software
 
20
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 descibed 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
        %<block length><type><checksum><stuff><cr>
 
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
 
 
70
#include "bfd.h"
 
71
#include "sysdep.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
 
 
84
    asymbol symbol;
 
85
    struct tekhex_symbol_struct *prev;
 
86
 
 
87
  } tekhex_symbol_type;
 
88
 
 
89
static const char digs[] = "0123456789ABCDEF";
 
90
 
 
91
static 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
 
 
101
static void tekhex_init PARAMS ((void));
 
102
static bfd_vma getvalue PARAMS ((char **));
 
103
static void tekhex_print_symbol
 
104
 PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type));
 
105
static void tekhex_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
 
106
static asymbol *tekhex_make_empty_symbol PARAMS ((bfd *));
 
107
static int tekhex_sizeof_headers PARAMS ((bfd *, boolean));
 
108
static boolean tekhex_write_object_contents PARAMS ((bfd *));
 
109
static void out PARAMS ((bfd *, int, char *, char *));
 
110
static void writesym PARAMS ((char **, const char *));
 
111
static void writevalue PARAMS ((char **, bfd_vma));
 
112
static boolean tekhex_set_section_contents
 
113
 PARAMS ((bfd*, sec_ptr, PTR, file_ptr, bfd_size_type));
 
114
static boolean tekhex_set_arch_mach
 
115
 PARAMS ((bfd *, enum bfd_architecture, unsigned long));
 
116
static boolean tekhex_get_section_contents
 
117
 PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
 
118
static void move_section_contents
 
119
 PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type, boolean));
 
120
static const bfd_target *tekhex_object_p PARAMS ((bfd *));
 
121
static boolean tekhex_mkobject PARAMS ((bfd *));
 
122
static long tekhex_get_symtab_upper_bound PARAMS ((bfd *));
 
123
static long tekhex_get_symtab PARAMS ((bfd *, asymbol **));
 
124
static void pass_over PARAMS ((bfd *, void (*) (bfd*, int, char *)));
 
125
static void first_phase PARAMS ((bfd *, int, char *));
 
126
static void insert_byte PARAMS ((bfd *, int, bfd_vma));
 
127
static struct data_struct *find_chunk PARAMS ((bfd *, bfd_vma));
 
128
static unsigned int getsym PARAMS ((char *, char **));
 
129
 
 
130
/*
 
131
Here'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
 
 
147
explanation:
 
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
 
 
175
Turns into
 
176
sac@thepub$ ./objdump -dx -m m68k f
 
177
 
 
178
f:     file format tekhex
 
179
-----x--- 9/55728 -134219416 Sep 29 15:13 1995 f
 
180
architecture: UNKNOWN!, flags 0x00000010:
 
181
HAS_SYMS
 
182
start address 0x00000000
 
183
SECTION 0 [D00000000]   : size 00020000 vma 00000000 align 2**0
 
184
 ALLOC, LOAD
 
185
SECTION 1 [D00008000]   : size 00002001 vma 00008000 align 2**0
 
186
 
 
187
SECTION 2 [T_SEGMENT]   : size ffffffff vma 00000000 align 2**0
 
188
 
 
189
SYMBOL TABLE:
 
190
00000000  g       T_SEGMENT gcc_compiled$
 
191
00000000  g       T_SEGMENT hello$c
 
192
00000000  g       T_SEGMENT int$t1$r1$$21474
 
193
00000000  g       T_SEGMENT char$t2$r2$0$127
 
194
00000000  g       T_SEGMENT long$int$t3$r1$$
 
195
00000000  g       T_SEGMENT unsigned$int$t4$
 
196
00000000  g       T_SEGMENT long$unsigned$in
 
197
00000000  g       T_SEGMENT short$int$t6$r1$
 
198
00000000  g       T_SEGMENT long$long$int$t7
 
199
00000000  g       T_SEGMENT short$unsigned$i
 
200
00000000  g       T_SEGMENT long$long$unsign
 
201
00000000  g       T_SEGMENT signed$char$t10$
 
202
00000000  g       T_SEGMENT unsigned$char$t1
 
203
00000000  g       T_SEGMENT float$t12$r1$4$0
 
204
00000000  g       T_SEGMENT double$t13$r1$8$
 
205
00000000  g       T_SEGMENT long$double$t14$
 
206
00000000  g       T_SEGMENT void$t15$15
 
207
00000000  g       T_SEGMENT _main
 
208
00000000  g       T_SEGMENT $
 
209
00000000  g       T_SEGMENT $
 
210
00000000  g       T_SEGMENT $
 
211
00000010  g       T_SEGMENT $
 
212
00000000  g       T_SEGMENT main$F1
 
213
fcffffff  g       T_SEGMENT i$1
 
214
00000000  g       T_SEGMENT $
 
215
00000010  g       T_SEGMENT $
 
216
 
 
217
RELOCATION RECORDS FOR [D00000000]: (none)
 
218
 
 
219
RELOCATION RECORDS FOR [D00008000]: (none)
 
220
 
 
221
RELOCATION RECORDS FOR [T_SEGMENT]: (none)
 
222
 
 
223
Disassembly of section D00000000:
 
224
...
 
225
00008000 ($+)7ff0 linkw fp,#-4
 
226
00008004 ($+)7ff4 nop
 
227
00008006 ($+)7ff6 movel #99,d0
 
228
00008008 ($+)7ff8 cmpl fp@(-4),d0
 
229
0000800c ($+)7ffc blts 00008014 ($+)8004
 
230
0000800e ($+)7ffe addql #1,fp@(-4)
 
231
00008012 ($+)8002 bras 00008006 ($+)7ff6
 
232
00008014 ($+)8004 unlk fp
 
233
00008016 ($+)8006 rts
 
234
...
 
235
 
 
236
*/
 
237
 
 
238
static void
 
239
tekhex_init ()
 
240
{
 
241
  unsigned int i;
 
242
  static 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
 
 
277
struct 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
};
 
285
typedef struct tekhex_data_list_struct tekhex_data_list_type;
 
286
 
 
287
#define CHUNK_MASK 0x1fff
 
288
 
 
289
struct 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
 
 
297
typedef 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
 
 
307
static bfd_vma
 
308
getvalue (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
 
 
325
static unsigned int
 
326
getsym (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
 
 
343
static struct data_struct *
 
344
find_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
 
 
371
static void
 
372
insert_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 */
 
386
static void
 
387
first_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->_raw_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 an tekhex, calling one of the above functions on each
 
475
   record.  */
 
476
 
 
477
static void
 
478
pass_over (abfd, func)
 
479
     bfd *abfd;
 
480
     void (*func) PARAMS ((bfd *, int, char *));
 
481
{
 
482
  unsigned int chars_on_line;
 
483
  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 = (boolean) (bfd_bread (src, (bfd_size_type) 1, abfd) != 1);
 
496
      while (*src != '%' && !eof)
 
497
        {
 
498
          eof = (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
 
 
524
static long
 
525
tekhex_get_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
 
 
542
static long
 
543
tekhex_get_symtab_upper_bound (abfd)
 
544
     bfd *abfd;
 
545
{
 
546
  return (abfd->symcount + 1) * (sizeof (struct tekhex_asymbol_struct *));
 
547
 
 
548
}
 
549
 
 
550
static boolean
 
551
tekhex_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
 
 
571
static const bfd_target *
 
572
tekhex_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
 
 
592
static void
 
593
move_section_contents (abfd, section, locationp, offset, count, get)
 
594
     bfd *abfd;
 
595
     asection *section;
 
596
     PTR locationp;
 
597
     file_ptr offset;
 
598
     bfd_size_type count;
 
599
     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
 
 
642
static boolean
 
643
tekhex_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
 
 
659
static boolean
 
660
tekhex_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
 
 
671
static boolean
 
672
tekhex_set_section_contents (abfd, section, locationp, offset, bytes_to_do)
 
673
     bfd *abfd;
 
674
     sec_ptr section;
 
675
     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->_raw_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
 
 
709
static void
 
710
writevalue (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
 
 
739
static void
 
740
writesym (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
 
 
774
static void
 
775
out (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
 
 
807
static boolean
 
808
tekhex_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->_raw_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
 
 
926
static int
 
927
tekhex_sizeof_headers (abfd, exec)
 
928
     bfd *abfd ATTRIBUTE_UNUSED;
 
929
     boolean exec ATTRIBUTE_UNUSED;
 
930
 
 
931
{
 
932
  return 0;
 
933
}
 
934
 
 
935
static asymbol *
 
936
tekhex_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
 
 
949
static void
 
950
tekhex_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
 
 
958
static void
 
959
tekhex_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_local_label_name bfd_generic_is_local_label_name
 
993
#define tekhex_get_lineno _bfd_nosymbols_get_lineno
 
994
#define tekhex_find_nearest_line _bfd_nosymbols_find_nearest_line
 
995
#define tekhex_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
 
996
#define tekhex_read_minisymbols _bfd_generic_read_minisymbols
 
997
#define tekhex_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
 
998
 
 
999
#define tekhex_bfd_get_relocated_section_contents \
 
1000
  bfd_generic_get_relocated_section_contents
 
1001
#define tekhex_bfd_relax_section bfd_generic_relax_section
 
1002
#define tekhex_bfd_gc_sections bfd_generic_gc_sections
 
1003
#define tekhex_bfd_merge_sections bfd_generic_merge_sections
 
1004
#define tekhex_bfd_discard_group bfd_generic_discard_group
 
1005
#define tekhex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
 
1006
#define tekhex_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
 
1007
#define tekhex_bfd_link_add_symbols _bfd_generic_link_add_symbols
 
1008
#define tekhex_bfd_link_just_syms _bfd_generic_link_just_syms
 
1009
#define tekhex_bfd_final_link _bfd_generic_final_link
 
1010
#define tekhex_bfd_link_split_section _bfd_generic_link_split_section
 
1011
 
 
1012
#define tekhex_get_section_contents_in_window \
 
1013
  _bfd_generic_get_section_contents_in_window
 
1014
 
 
1015
const bfd_target tekhex_vec =
 
1016
{
 
1017
  "tekhex",                     /* name */
 
1018
  bfd_target_tekhex_flavour,
 
1019
  BFD_ENDIAN_UNKNOWN,           /* target byte order */
 
1020
  BFD_ENDIAN_UNKNOWN,           /* target headers byte order */
 
1021
  (EXEC_P |                     /* object flags */
 
1022
   HAS_SYMS | HAS_LINENO | HAS_DEBUG | HAS_RELOC | HAS_LOCALS |
 
1023
   WP_TEXT | D_PAGED),
 
1024
  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
 
1025
   | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
 
1026
  0,                            /* leading underscore */
 
1027
  ' ',                          /* ar_pad_char */
 
1028
  16,                           /* ar_max_namelen */
 
1029
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
 
1030
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
 
1031
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* data */
 
1032
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
 
1033
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
 
1034
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* hdrs */
 
1035
 
 
1036
  {
 
1037
    _bfd_dummy_target,
 
1038
    tekhex_object_p,            /* bfd_check_format */
 
1039
    _bfd_dummy_target,
 
1040
    _bfd_dummy_target,
 
1041
  },
 
1042
  {
 
1043
    bfd_false,
 
1044
    tekhex_mkobject,
 
1045
    _bfd_generic_mkarchive,
 
1046
    bfd_false,
 
1047
  },
 
1048
  {                             /* bfd_write_contents */
 
1049
    bfd_false,
 
1050
    tekhex_write_object_contents,
 
1051
    _bfd_write_archive_contents,
 
1052
    bfd_false,
 
1053
  },
 
1054
 
 
1055
  BFD_JUMP_TABLE_GENERIC (tekhex),
 
1056
  BFD_JUMP_TABLE_COPY (_bfd_generic),
 
1057
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
 
1058
  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
 
1059
  BFD_JUMP_TABLE_SYMBOLS (tekhex),
 
1060
  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
 
1061
  BFD_JUMP_TABLE_WRITE (tekhex),
 
1062
  BFD_JUMP_TABLE_LINK (tekhex),
 
1063
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
 
1064
 
 
1065
  NULL,
 
1066
 
 
1067
  (PTR) 0
 
1068
};