OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [bfd/] [tekhex.c] - Blame information for rev 227

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* 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 Free Software Foundation, Inc.
4
   Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
5
 
6
   This file is part of BFD, the Binary File Descriptor library.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
 
24
/* SUBSECTION
25
        Tektronix Hex Format handling
26
 
27
   DESCRIPTION
28
 
29
        Tek Hex records can hold symbols and data, but not
30
        relocations. Their main application is communication with
31
        devices like PROM programmers and ICE equipment.
32
 
33
        It seems that the sections are described as being really big,
34
        the example I have says that the text section is 0..ffffffff.
35
        BFD would barf with this, many apps would try to alloc 4GB to
36
        read in the file.
37
 
38
        Tex Hex may contain many sections, but the data which comes in
39
        has no tag saying which section it belongs to, so we create
40
        one section for each block of data, called "blknnnn" which we
41
        stick all the data into.
42
 
43
        TekHex may come out of  order and there is no header, so an
44
        initial scan is required  to discover the minimum and maximum
45
        addresses used to create the vma and size of the sections we
46
        create.
47
        We read in the data into pages of CHUNK_MASK+1 size and read
48
        them out from that whenever we need to.
49
 
50
        Any number of sections may be created for output, we save them
51
        up and output them when it's time to close the bfd.
52
 
53
        A TekHex record looks like:
54
  EXAMPLE
55
        %<block length><type><checksum><stuff><cr>
56
 
57
  DESCRIPTION
58
        Where
59
        o length
60
        is the number of bytes in the record not including the % sign.
61
        o type
62
        is one of:
63
        3) symbol record
64
        6) data record
65
        8) termination record
66
 
67
  The data can come out of order, and may be discontigous. This is a
68
  serial protocol, so big files are unlikely, so we keep a list of 8k chunks.  */
69
 
70
#include "sysdep.h"
71
#include "bfd.h"
72
#include "libbfd.h"
73
#include "libiberty.h"
74
 
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, &section->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_merge_sections                   bfd_generic_merge_sections
947
#define tekhex_bfd_is_group_section                 bfd_generic_is_group_section
948
#define tekhex_bfd_discard_group                    bfd_generic_discard_group
949
#define tekhex_section_already_linked               _bfd_generic_section_already_linked
950
#define tekhex_bfd_define_common_symbol             bfd_generic_define_common_symbol
951
#define tekhex_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
952
#define tekhex_bfd_link_hash_table_free             _bfd_generic_link_hash_table_free
953
#define tekhex_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
954
#define tekhex_bfd_link_just_syms                   _bfd_generic_link_just_syms
955
#define tekhex_bfd_copy_link_hash_symbol_type \
956
  _bfd_generic_copy_link_hash_symbol_type
957
#define tekhex_bfd_final_link                       _bfd_generic_final_link
958
#define tekhex_bfd_link_split_section               _bfd_generic_link_split_section
959
#define tekhex_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
960
 
961
const bfd_target tekhex_vec =
962
{
963
  "tekhex",                     /* Name.  */
964
  bfd_target_tekhex_flavour,
965
  BFD_ENDIAN_UNKNOWN,           /* Target byte order.  */
966
  BFD_ENDIAN_UNKNOWN,           /* Target headers byte order.  */
967
  (EXEC_P |                     /* Object flags.  */
968
   HAS_SYMS | HAS_LINENO | HAS_DEBUG |
969
   HAS_RELOC | HAS_LOCALS | WP_TEXT | D_PAGED),
970
  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
971
   | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* Section flags.  */
972
  0,                             /* Leading underscore.  */
973
  ' ',                          /* AR_pad_char.  */
974
  16,                           /* AR_max_namelen.  */
975
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
976
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
977
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Data.  */
978
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
979
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
980
  bfd_getb16, bfd_getb_signed_16, bfd_putb16,   /* Headers.  */
981
 
982
  {
983
    _bfd_dummy_target,
984
    tekhex_object_p,            /* bfd_check_format.  */
985
    _bfd_dummy_target,
986
    _bfd_dummy_target,
987
  },
988
  {
989
    bfd_false,
990
    tekhex_mkobject,
991
    _bfd_generic_mkarchive,
992
    bfd_false,
993
  },
994
  {                             /* bfd_write_contents.  */
995
    bfd_false,
996
    tekhex_write_object_contents,
997
    _bfd_write_archive_contents,
998
    bfd_false,
999
  },
1000
 
1001
  BFD_JUMP_TABLE_GENERIC (tekhex),
1002
  BFD_JUMP_TABLE_COPY (_bfd_generic),
1003
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
1004
  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1005
  BFD_JUMP_TABLE_SYMBOLS (tekhex),
1006
  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1007
  BFD_JUMP_TABLE_WRITE (tekhex),
1008
  BFD_JUMP_TABLE_LINK (tekhex),
1009
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1010
 
1011
  NULL,
1012
 
1013
  NULL
1014
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.