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