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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [bfd/] [tekhex.c] - Blame information for rev 24

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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