xref: /openbsd-src/gnu/usr.bin/binutils/bfd/tekhex.c (revision 68302baffabd4be1150ed1917a47eda05ae0388d)
12159047fSniklas /* BFD backend for Extended Tektronix Hex Format  objects.
2007c2a45Smiod    Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003
3b305b0f1Sespie    Free Software Foundation, Inc.
42159047fSniklas    Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
52159047fSniklas 
62159047fSniklas This file is part of BFD, the Binary File Descriptor library.
72159047fSniklas 
82159047fSniklas This program is free software; you can redistribute it and/or modify
92159047fSniklas it under the terms of the GNU General Public License as published by
102159047fSniklas the Free Software Foundation; either version 2 of the License, or
112159047fSniklas (at your option) any later version.
122159047fSniklas 
132159047fSniklas This program is distributed in the hope that it will be useful,
142159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
152159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
162159047fSniklas GNU General Public License for more details.
172159047fSniklas 
182159047fSniklas You should have received a copy of the GNU General Public License
192159047fSniklas along with this program; if not, write to the Free Software
202159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
212159047fSniklas 
222159047fSniklas /*
232159047fSniklas SUBSECTION
242159047fSniklas 	Tektronix Hex Format handling
252159047fSniklas 
262159047fSniklas DESCRIPTION
272159047fSniklas 
282159047fSniklas 	Tek Hex records can hold symbols and data, but not
292159047fSniklas 	relocations. Their main application is communication with
302159047fSniklas 	devices like PROM programmers and ICE equipment.
312159047fSniklas 
32007c2a45Smiod 	It seems that the sections are described as being really big,
332159047fSniklas         the example I have says that the text section is 0..ffffffff.
342159047fSniklas 	BFD would barf with this, many apps would try to alloc 4GB to
352159047fSniklas 	read in the file.
362159047fSniklas 
372159047fSniklas 	Tex Hex may contain many sections, but the data which comes in
382159047fSniklas 	has no tag saying which section it belongs to, so we create
392159047fSniklas 	one section for each block of data, called "blknnnn" which we
402159047fSniklas 	stick all the data into.
412159047fSniklas 
422159047fSniklas 	TekHex may come out of 	order and there is no header, so an
432159047fSniklas 	initial scan is required  to discover the minimum and maximum
442159047fSniklas 	addresses used to create the vma and size of the sections we
452159047fSniklas 	create.
462159047fSniklas 	We read in the data into pages of CHUNK_MASK+1 size and read
472159047fSniklas 	them out from that whenever we need to.
482159047fSniklas 
492159047fSniklas 	Any number of sections may be created for output, we save them
502159047fSniklas 	up and output them when it's time to close the bfd.
512159047fSniklas 
522159047fSniklas 	A TekHex record looks like:
532159047fSniklas EXAMPLE
542159047fSniklas 	%<block length><type><checksum><stuff><cr>
552159047fSniklas 
562159047fSniklas DESCRIPTION
572159047fSniklas 	Where
582159047fSniklas 	o length
592159047fSniklas 	is the number of bytes in the record not including the % sign.
602159047fSniklas 	o type
612159047fSniklas 	is one of:
622159047fSniklas 	3) symbol record
632159047fSniklas 	6) data record
642159047fSniklas 	8) termination record
652159047fSniklas 
662159047fSniklas The data can come out of order, and may be discontigous. This is a
672159047fSniklas serial protocol, so big files are unlikely, so we keep a list of 8k chunks
682159047fSniklas */
692159047fSniklas 
702159047fSniklas #include "bfd.h"
712159047fSniklas #include "sysdep.h"
722159047fSniklas #include "libbfd.h"
732159047fSniklas #include "libiberty.h"
742159047fSniklas 
752159047fSniklas typedef struct
762159047fSniklas   {
772159047fSniklas     bfd_vma low;
782159047fSniklas     bfd_vma high;
792159047fSniklas   } addr_range_type;
802159047fSniklas 
812159047fSniklas typedef struct tekhex_symbol_struct
822159047fSniklas   {
832159047fSniklas 
842159047fSniklas     asymbol symbol;
852159047fSniklas     struct tekhex_symbol_struct *prev;
862159047fSniklas 
872159047fSniklas   } tekhex_symbol_type;
882159047fSniklas 
892159047fSniklas static const char digs[] = "0123456789ABCDEF";
902159047fSniklas 
912159047fSniklas static char sum_block[256];
922159047fSniklas 
932159047fSniklas #define NOT_HEX 20
942159047fSniklas #define NIBBLE(x) hex_value(x)
952159047fSniklas #define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
962159047fSniklas #define TOHEX(d,x) \
972159047fSniklas (d)[1] = digs[(x) & 0xf]; \
982159047fSniklas (d)[0] = digs[((x)>>4)&0xf];
992159047fSniklas #define	ISHEX(x)  hex_p(x)
1002159047fSniklas 
101b305b0f1Sespie static void tekhex_init PARAMS ((void));
102*68302bafSotto static bfd_boolean getvalue PARAMS ((char **, bfd_vma *));
103e93f7393Sniklas static void tekhex_print_symbol
104e93f7393Sniklas  PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type));
105e93f7393Sniklas static void tekhex_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
106e93f7393Sniklas static asymbol *tekhex_make_empty_symbol PARAMS ((bfd *));
107c074d1c9Sdrahn static int tekhex_sizeof_headers PARAMS ((bfd *, bfd_boolean));
108c074d1c9Sdrahn static bfd_boolean tekhex_write_object_contents PARAMS ((bfd *));
109e93f7393Sniklas static void out PARAMS ((bfd *, int, char *, char *));
110c074d1c9Sdrahn static void writesym PARAMS ((char **, const char *));
111e93f7393Sniklas static void writevalue PARAMS ((char **, bfd_vma));
112c074d1c9Sdrahn static bfd_boolean tekhex_set_section_contents
113007c2a45Smiod  PARAMS ((bfd*, sec_ptr, const PTR, file_ptr, bfd_size_type));
114c074d1c9Sdrahn static bfd_boolean tekhex_set_arch_mach
115e93f7393Sniklas  PARAMS ((bfd *, enum bfd_architecture, unsigned long));
116c074d1c9Sdrahn static bfd_boolean tekhex_get_section_contents
117e93f7393Sniklas  PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
118e93f7393Sniklas static void move_section_contents
119007c2a45Smiod  PARAMS ((bfd *, asection *, const PTR, file_ptr, bfd_size_type, bfd_boolean));
120e93f7393Sniklas static const bfd_target *tekhex_object_p PARAMS ((bfd *));
121c074d1c9Sdrahn static bfd_boolean tekhex_mkobject PARAMS ((bfd *));
122e93f7393Sniklas static long tekhex_get_symtab_upper_bound PARAMS ((bfd *));
123007c2a45Smiod static long tekhex_canonicalize_symtab PARAMS ((bfd *, asymbol **));
124*68302bafSotto static bfd_boolean pass_over PARAMS ((bfd *, bfd_boolean (*) (bfd*, int, char *)));
125*68302bafSotto static bfd_boolean first_phase PARAMS ((bfd *, int, char *));
126e93f7393Sniklas static void insert_byte PARAMS ((bfd *, int, bfd_vma));
127e93f7393Sniklas static struct data_struct *find_chunk PARAMS ((bfd *, bfd_vma));
128*68302bafSotto static bfd_boolean getsym PARAMS ((char *, char **, unsigned int *));
129e93f7393Sniklas 
1302159047fSniklas /*
1312159047fSniklas Here's an example
1322159047fSniklas %3A6C6480004E56FFFC4E717063B0AEFFFC6D0652AEFFFC60F24E5E4E75
1332159047fSniklas %1B3709T_SEGMENT1108FFFFFFFF
1342159047fSniklas %2B3AB9T_SEGMENT7Dgcc_compiled$1087hello$c10
1352159047fSniklas %373829T_SEGMENT80int$t1$r1$$214741080char$t2$r2$0$12710
1362159047fSniklas %373769T_SEGMENT80long$int$t3$r1$$1080unsigned$int$t4$10
1372159047fSniklas %373CA9T_SEGMENT80long$unsigned$in1080short$int$t6$r1$10
1382159047fSniklas %373049T_SEGMENT80long$long$int$t71080short$unsigned$i10
1392159047fSniklas %373A29T_SEGMENT80long$long$unsign1080signed$char$t10$10
1402159047fSniklas %373D69T_SEGMENT80unsigned$char$t11080float$t12$r1$4$010
1412159047fSniklas %373D19T_SEGMENT80double$t13$r1$8$1080long$double$t14$10
1422159047fSniklas %2734D9T_SEGMENT8Bvoid$t15$151035_main10
1432159047fSniklas %2F3CA9T_SEGMENT81$1081$1681$1E81$21487main$F110
1442159047fSniklas %2832F9T_SEGMENT83i$18FFFFFFFC81$1481$214
1452159047fSniklas %07 8 10 10
1462159047fSniklas 
1472159047fSniklas explanation:
1482159047fSniklas %3A6C6480004E56FFFC4E717063B0AEFFFC6D0652AEFFFC60F24E5E4E75
1492159047fSniklas  ^ ^^ ^     ^-data
1502159047fSniklas  | || +------ 4 char integer 0x8000
1512159047fSniklas  | |+-------- checksum
1522159047fSniklas  | +--------- type 6 (data record)
1532159047fSniklas  +----------- length 3a chars
1542159047fSniklas  <---------------------- 3a (58 chars) ------------------->
1552159047fSniklas 
1562159047fSniklas %1B3709T_SEGMENT1108FFFFFFFF
1572159047fSniklas       ^         ^^ ^- 8 character integer 0xffffffff
1582159047fSniklas       |         |+-   1 character integer 0
1592159047fSniklas       |         +--   type 1 symbol (section definition)
1602159047fSniklas       +------------   9 char symbol T_SEGMENT
1612159047fSniklas 
1622159047fSniklas %2B3AB9T_SEGMENT7Dgcc_compiled$1087hello$c10
1632159047fSniklas %373829T_SEGMENT80int$t1$r1$$214741080char$t2$r2$0$12710
1642159047fSniklas %373769T_SEGMENT80long$int$t3$r1$$1080unsigned$int$t4$10
1652159047fSniklas %373CA9T_SEGMENT80long$unsigned$in1080short$int$t6$r1$10
1662159047fSniklas %373049T_SEGMENT80long$long$int$t71080short$unsigned$i10
1672159047fSniklas %373A29T_SEGMENT80long$long$unsign1080signed$char$t10$10
1682159047fSniklas %373D69T_SEGMENT80unsigned$char$t11080float$t12$r1$4$010
1692159047fSniklas %373D19T_SEGMENT80double$t13$r1$8$1080long$double$t14$10
1702159047fSniklas %2734D9T_SEGMENT8Bvoid$t15$151035_main10
1712159047fSniklas %2F3CA9T_SEGMENT81$1081$1681$1E81$21487main$F110
1722159047fSniklas %2832F9T_SEGMENT83i$18FFFFFFFC81$1481$214
1732159047fSniklas %0781010
1742159047fSniklas 
1752159047fSniklas Turns into
1762159047fSniklas sac@thepub$ ./objdump -dx -m m68k f
1772159047fSniklas 
1782159047fSniklas f:     file format tekhex
1792159047fSniklas -----x--- 9/55728 -134219416 Sep 29 15:13 1995 f
1802159047fSniklas architecture: UNKNOWN!, flags 0x00000010:
1812159047fSniklas HAS_SYMS
1822159047fSniklas start address 0x00000000
1832159047fSniklas SECTION 0 [D00000000]	: size 00020000 vma 00000000 align 2**0
1842159047fSniklas  ALLOC, LOAD
1852159047fSniklas SECTION 1 [D00008000]	: size 00002001 vma 00008000 align 2**0
1862159047fSniklas 
1872159047fSniklas SECTION 2 [T_SEGMENT]	: size ffffffff vma 00000000 align 2**0
1882159047fSniklas 
1892159047fSniklas SYMBOL TABLE:
1902159047fSniklas 00000000  g       T_SEGMENT gcc_compiled$
1912159047fSniklas 00000000  g       T_SEGMENT hello$c
1922159047fSniklas 00000000  g       T_SEGMENT int$t1$r1$$21474
1932159047fSniklas 00000000  g       T_SEGMENT char$t2$r2$0$127
1942159047fSniklas 00000000  g       T_SEGMENT long$int$t3$r1$$
1952159047fSniklas 00000000  g       T_SEGMENT unsigned$int$t4$
1962159047fSniklas 00000000  g       T_SEGMENT long$unsigned$in
1972159047fSniklas 00000000  g       T_SEGMENT short$int$t6$r1$
1982159047fSniklas 00000000  g       T_SEGMENT long$long$int$t7
1992159047fSniklas 00000000  g       T_SEGMENT short$unsigned$i
2002159047fSniklas 00000000  g       T_SEGMENT long$long$unsign
2012159047fSniklas 00000000  g       T_SEGMENT signed$char$t10$
2022159047fSniklas 00000000  g       T_SEGMENT unsigned$char$t1
2032159047fSniklas 00000000  g       T_SEGMENT float$t12$r1$4$0
2042159047fSniklas 00000000  g       T_SEGMENT double$t13$r1$8$
2052159047fSniklas 00000000  g       T_SEGMENT long$double$t14$
2062159047fSniklas 00000000  g       T_SEGMENT void$t15$15
2072159047fSniklas 00000000  g       T_SEGMENT _main
2082159047fSniklas 00000000  g       T_SEGMENT $
2092159047fSniklas 00000000  g       T_SEGMENT $
2102159047fSniklas 00000000  g       T_SEGMENT $
2112159047fSniklas 00000010  g       T_SEGMENT $
2122159047fSniklas 00000000  g       T_SEGMENT main$F1
2132159047fSniklas fcffffff  g       T_SEGMENT i$1
2142159047fSniklas 00000000  g       T_SEGMENT $
2152159047fSniklas 00000010  g       T_SEGMENT $
2162159047fSniklas 
2172159047fSniklas RELOCATION RECORDS FOR [D00000000]: (none)
2182159047fSniklas 
2192159047fSniklas RELOCATION RECORDS FOR [D00008000]: (none)
2202159047fSniklas 
2212159047fSniklas RELOCATION RECORDS FOR [T_SEGMENT]: (none)
2222159047fSniklas 
2232159047fSniklas Disassembly of section D00000000:
2242159047fSniklas ...
2252159047fSniklas 00008000 ($+)7ff0 linkw fp,#-4
2262159047fSniklas 00008004 ($+)7ff4 nop
2272159047fSniklas 00008006 ($+)7ff6 movel #99,d0
2282159047fSniklas 00008008 ($+)7ff8 cmpl fp@(-4),d0
2292159047fSniklas 0000800c ($+)7ffc blts 00008014 ($+)8004
2302159047fSniklas 0000800e ($+)7ffe addql #1,fp@(-4)
2312159047fSniklas 00008012 ($+)8002 bras 00008006 ($+)7ff6
2322159047fSniklas 00008014 ($+)8004 unlk fp
2332159047fSniklas 00008016 ($+)8006 rts
2342159047fSniklas ...
2352159047fSniklas 
2362159047fSniklas */
2372159047fSniklas 
2382159047fSniklas static void
tekhex_init()2392159047fSniklas tekhex_init ()
2402159047fSniklas {
2412159047fSniklas   unsigned int i;
242c074d1c9Sdrahn   static bfd_boolean inited = FALSE;
2432159047fSniklas   int val;
2442159047fSniklas 
245c074d1c9Sdrahn   if (! inited)
2462159047fSniklas     {
247c074d1c9Sdrahn       inited = TRUE;
2482159047fSniklas       hex_init ();
2492159047fSniklas       val = 0;
2502159047fSniklas       for (i = 0; i < 10; i++)
2512159047fSniklas 	{
2522159047fSniklas 	  sum_block[i + '0'] = val++;
2532159047fSniklas 	}
2542159047fSniklas       for (i = 'A'; i <= 'Z'; i++)
2552159047fSniklas 	{
2562159047fSniklas 	  sum_block[i] = val++;
2572159047fSniklas 	}
2582159047fSniklas       sum_block['$'] = val++;
2592159047fSniklas       sum_block['%'] = val++;
2602159047fSniklas       sum_block['.'] = val++;
2612159047fSniklas       sum_block['_'] = val++;
2622159047fSniklas       for (i = 'a'; i <= 'z'; i++)
2632159047fSniklas 	{
2642159047fSniklas 	  sum_block[i] = val++;
2652159047fSniklas 	}
2662159047fSniklas     }
2672159047fSniklas }
2682159047fSniklas 
2692159047fSniklas /* The maximum number of bytes on a line is FF */
2702159047fSniklas #define MAXCHUNK 0xff
2712159047fSniklas /* The number of bytes we fit onto a line on output */
2722159047fSniklas #define CHUNK 21
2732159047fSniklas 
2742159047fSniklas /* We cannot output our tekhexords as we see them, we have to glue them
2752159047fSniklas    together, this is done in this structure : */
2762159047fSniklas 
2772159047fSniklas struct tekhex_data_list_struct
2782159047fSniklas {
2792159047fSniklas   unsigned char *data;
2802159047fSniklas   bfd_vma where;
2812159047fSniklas   bfd_size_type size;
2822159047fSniklas   struct tekhex_data_list_struct *next;
2832159047fSniklas 
2842159047fSniklas };
2852159047fSniklas typedef struct tekhex_data_list_struct tekhex_data_list_type;
2862159047fSniklas 
2872159047fSniklas #define CHUNK_MASK 0x1fff
2882159047fSniklas 
2892159047fSniklas struct data_struct
2902159047fSniklas   {
2912159047fSniklas     char chunk_data[CHUNK_MASK + 1];
2922159047fSniklas     char chunk_init[CHUNK_MASK + 1];
2932159047fSniklas     bfd_vma vma;
2942159047fSniklas     struct data_struct *next;
2952159047fSniklas   };
2962159047fSniklas 
2972159047fSniklas typedef struct tekhex_data_struct
2982159047fSniklas {
2992159047fSniklas   tekhex_data_list_type *head;
3002159047fSniklas   unsigned int type;
3012159047fSniklas   struct tekhex_symbol_struct *symbols;
3022159047fSniklas   struct data_struct *data;
3032159047fSniklas } tdata_type;
3042159047fSniklas 
3052159047fSniklas #define enda(x) (x->vma + x->size)
3062159047fSniklas 
307*68302bafSotto static bfd_boolean
getvalue(char ** srcp,bfd_vma * valuep)308*68302bafSotto getvalue (char **srcp, bfd_vma *valuep)
3092159047fSniklas {
3102159047fSniklas   char *src = *srcp;
3112159047fSniklas   bfd_vma value = 0;
312*68302bafSotto   unsigned int len;
313*68302bafSotto 
314*68302bafSotto   if (!ISHEX (*src))
315*68302bafSotto     return FALSE;
316*68302bafSotto 
317*68302bafSotto   len = hex_value(*src++);
3182159047fSniklas 
3192159047fSniklas   if (len == 0)
3202159047fSniklas     len = 16;
3212159047fSniklas   while (len--)
3222159047fSniklas     {
323*68302bafSotto       if (!ISHEX (*src))
324*68302bafSotto 	return FALSE;
3252159047fSniklas       value = value << 4 | hex_value(*src++);
3262159047fSniklas     }
3272159047fSniklas   *srcp = src;
328*68302bafSotto   *valuep = value;
329*68302bafSotto   return TRUE;
3302159047fSniklas }
3312159047fSniklas 
332*68302bafSotto static bfd_boolean
getsym(char * dstp,char ** srcp,unsigned int * lenp)333*68302bafSotto getsym (char *dstp, char **srcp, unsigned int *lenp)
3342159047fSniklas {
3352159047fSniklas   char *src = *srcp;
3362159047fSniklas   unsigned int i;
337*68302bafSotto   unsigned int len;
3382159047fSniklas 
339*68302bafSotto   if (!ISHEX (*src))
340*68302bafSotto 	return FALSE;
341*68302bafSotto 
342*68302bafSotto   len = hex_value(*src++);
3432159047fSniklas   if (len == 0)
3442159047fSniklas     len = 16;
3452159047fSniklas   for (i = 0; i < len; i++)
3462159047fSniklas     dstp[i] = src[i];
3472159047fSniklas   dstp[i] = 0;
3482159047fSniklas   *srcp = src + i;
349*68302bafSotto   *lenp = len;
350*68302bafSotto   return TRUE;
3512159047fSniklas }
3522159047fSniklas 
353e93f7393Sniklas static struct data_struct *
find_chunk(abfd,vma)3542159047fSniklas find_chunk (abfd, vma)
3552159047fSniklas      bfd *abfd;
3562159047fSniklas      bfd_vma vma;
3572159047fSniklas {
3582159047fSniklas   struct data_struct *d = abfd->tdata.tekhex_data->data;
3592159047fSniklas 
3602159047fSniklas   vma &= ~CHUNK_MASK;
3612159047fSniklas   while (d && (d->vma) != vma)
3622159047fSniklas     {
3632159047fSniklas       d = d->next;
3642159047fSniklas     }
3652159047fSniklas   if (!d)
3662159047fSniklas     {
3672159047fSniklas       /* No chunk for this address, so make one up */
368c074d1c9Sdrahn       d = ((struct data_struct *)
369c074d1c9Sdrahn 	   bfd_zalloc (abfd, (bfd_size_type) sizeof (struct data_struct)));
3702159047fSniklas 
371c074d1c9Sdrahn       if (!d)
3722159047fSniklas 	return NULL;
3732159047fSniklas 
3742159047fSniklas       d->next = abfd->tdata.tekhex_data->data;
3752159047fSniklas       d->vma = vma;
3762159047fSniklas       abfd->tdata.tekhex_data->data = d;
3772159047fSniklas     }
3782159047fSniklas   return d;
3792159047fSniklas }
3802159047fSniklas 
3812159047fSniklas static void
insert_byte(abfd,value,addr)3822159047fSniklas insert_byte (abfd, value, addr)
3832159047fSniklas      bfd *abfd;
3842159047fSniklas      int value;
3852159047fSniklas      bfd_vma addr;
3862159047fSniklas {
3872159047fSniklas   /* Find the chunk that this byte needs and put it in */
3882159047fSniklas   struct data_struct *d = find_chunk (abfd, addr);
3892159047fSniklas 
3902159047fSniklas   d->chunk_data[addr & CHUNK_MASK] = value;
3912159047fSniklas   d->chunk_init[addr & CHUNK_MASK] = 1;
3922159047fSniklas }
3932159047fSniklas 
3942159047fSniklas /* The first pass is to find the names of all the sections, and see
3952159047fSniklas   how big the data is */
396*68302bafSotto static bfd_boolean
first_phase(abfd,type,src)3972159047fSniklas first_phase (abfd, type, src)
3982159047fSniklas      bfd *abfd;
399e93f7393Sniklas      int type;
4002159047fSniklas      char *src;
4012159047fSniklas {
4022159047fSniklas   asection *section = bfd_abs_section_ptr;
403c074d1c9Sdrahn   unsigned int len;
404*68302bafSotto   bfd_vma val;
4052159047fSniklas   char sym[17];			/* A symbol can only be 16chars long */
4062159047fSniklas 
4072159047fSniklas   switch (type)
4082159047fSniklas     {
4092159047fSniklas     case '6':
4102159047fSniklas       /* Data record - read it and store it */
4112159047fSniklas       {
412*68302bafSotto 	bfd_vma addr;
413*68302bafSotto 
414*68302bafSotto 	if (!getvalue (&src, &addr))
415*68302bafSotto 	  return FALSE;
4162159047fSniklas 
4172159047fSniklas 	while (*src)
4182159047fSniklas 	  {
4192159047fSniklas 	    insert_byte (abfd, HEX (src), addr);
4202159047fSniklas 	    src += 2;
4212159047fSniklas 	    addr++;
4222159047fSniklas 	  }
4232159047fSniklas       }
4242159047fSniklas 
425*68302bafSotto       return TRUE;
4262159047fSniklas     case '3':
4272159047fSniklas       /* Symbol record, read the segment */
428*68302bafSotto       if (!getsym (sym, &src, &len))
429*68302bafSotto 	return FALSE;
4302159047fSniklas       section = bfd_get_section_by_name (abfd, sym);
4312159047fSniklas       if (section == (asection *) NULL)
4322159047fSniklas 	{
433c074d1c9Sdrahn 	  char *n = bfd_alloc (abfd, (bfd_size_type) len + 1);
4342159047fSniklas 
4352159047fSniklas 	  if (!n)
436*68302bafSotto 	    return FALSE;
4372159047fSniklas 	  memcpy (n, sym, len + 1);
4382159047fSniklas 	  section = bfd_make_section (abfd, n);
4392159047fSniklas 	}
4402159047fSniklas       while (*src)
4412159047fSniklas 	{
4422159047fSniklas 	  switch (*src)
4432159047fSniklas 	    {
4442159047fSniklas 	    case '1':		/* section range */
4452159047fSniklas 	      src++;
446*68302bafSotto 	      if (!getvalue (&src, &section->vma))
447*68302bafSotto 		return FALSE;
448*68302bafSotto 	      if (!getvalue (&src, &val))
449*68302bafSotto 		return FALSE;
450*68302bafSotto 	      section->_raw_size = val - section->vma;
4512159047fSniklas 	      section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
4522159047fSniklas 	      break;
4532159047fSniklas 	    case '0':
4542159047fSniklas 	    case '2':
4552159047fSniklas 	    case '3':
4562159047fSniklas 	    case '4':
4572159047fSniklas 	    case '6':
4582159047fSniklas 	    case '7':
4592159047fSniklas 	    case '8':
4602159047fSniklas 	      /* Symbols, add to section */
4612159047fSniklas 	      {
462c074d1c9Sdrahn 		bfd_size_type amt = sizeof (tekhex_symbol_type);
4632159047fSniklas 		tekhex_symbol_type *new =
464c074d1c9Sdrahn 		  (tekhex_symbol_type *) bfd_alloc (abfd, amt);
465c074d1c9Sdrahn 		char stype = (*src);
4662159047fSniklas 
4672159047fSniklas 		if (!new)
468*68302bafSotto 		  return FALSE;
4692159047fSniklas 		new->symbol.the_bfd = abfd;
4702159047fSniklas 		src++;
4712159047fSniklas 		abfd->symcount++;
4722159047fSniklas 		abfd->flags |= HAS_SYMS;
4732159047fSniklas 		new->prev = abfd->tdata.tekhex_data->symbols;
4742159047fSniklas 		abfd->tdata.tekhex_data->symbols = new;
475*68302bafSotto 		if (!getsym (sym, &src, &len))
476*68302bafSotto 		  return FALSE;
477c074d1c9Sdrahn 		new->symbol.name = bfd_alloc (abfd, (bfd_size_type) len + 1);
4782159047fSniklas 		if (!new->symbol.name)
479*68302bafSotto 		  return FALSE;
4802159047fSniklas 		memcpy ((char *) (new->symbol.name), sym, len + 1);
4812159047fSniklas 		new->symbol.section = section;
482c074d1c9Sdrahn 		if (stype <= '4')
4832159047fSniklas 		  new->symbol.flags = (BSF_GLOBAL | BSF_EXPORT);
4842159047fSniklas 		else
4852159047fSniklas 		  new->symbol.flags = BSF_LOCAL;
486*68302bafSotto 		if (!getvalue (&src, &val))
487*68302bafSotto 		  return FALSE;
488*68302bafSotto 		new->symbol.value = val - section->vma;
489*68302bafSotto 	      }
490*68302bafSotto 	    default:
491*68302bafSotto 	      return FALSE;
4922159047fSniklas 	    }
4932159047fSniklas 	}
4942159047fSniklas     }
495*68302bafSotto 
496*68302bafSotto   return TRUE;
4972159047fSniklas }
4982159047fSniklas 
499c074d1c9Sdrahn /* Pass over a tekhex, calling one of the above functions on each
5002159047fSniklas    record.  */
5012159047fSniklas 
502*68302bafSotto static bfd_boolean
pass_over(abfd,func)5032159047fSniklas pass_over (abfd, func)
5042159047fSniklas      bfd *abfd;
505*68302bafSotto      bfd_boolean (*func) PARAMS ((bfd *, int, char *));
5062159047fSniklas {
5072159047fSniklas   unsigned int chars_on_line;
508c074d1c9Sdrahn   bfd_boolean eof = FALSE;
5092159047fSniklas 
5102159047fSniklas   /* To the front of the file */
5112159047fSniklas   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
5122159047fSniklas     abort ();
513c074d1c9Sdrahn   while (! eof)
5142159047fSniklas     {
5152159047fSniklas       char buffer[MAXCHUNK];
5162159047fSniklas       char *src = buffer;
5172159047fSniklas       char type;
5182159047fSniklas 
5192159047fSniklas       /* Find first '%' */
520c074d1c9Sdrahn       eof = (bfd_boolean) (bfd_bread (src, (bfd_size_type) 1, abfd) != 1);
5212159047fSniklas       while (*src != '%' && !eof)
5222159047fSniklas 	{
523c074d1c9Sdrahn 	  eof = (bfd_boolean) (bfd_bread (src, (bfd_size_type) 1, abfd) != 1);
5242159047fSniklas 	}
5252159047fSniklas       if (eof)
5262159047fSniklas 	break;
5272159047fSniklas       src++;
5282159047fSniklas 
5292159047fSniklas       /* Fetch the type and the length and the checksum */
530c074d1c9Sdrahn       if (bfd_bread (src, (bfd_size_type) 5, abfd) != 5)
5312159047fSniklas 	abort (); /* FIXME */
5322159047fSniklas 
5332159047fSniklas       type = src[2];
5342159047fSniklas 
5352159047fSniklas       if (!ISHEX (src[0]) || !ISHEX (src[1]))
5362159047fSniklas 	break;
5372159047fSniklas 
5382159047fSniklas       chars_on_line = HEX (src) - 5;	/* Already read five char */
5392159047fSniklas 
540c074d1c9Sdrahn       if (bfd_bread (src, (bfd_size_type) chars_on_line, abfd) != chars_on_line)
5412159047fSniklas 	abort (); /* FIXME */
5422159047fSniklas       src[chars_on_line] = 0;	/* put a null at the end */
5432159047fSniklas 
544*68302bafSotto       if (!func (abfd, type, src))
545*68302bafSotto 	return FALSE;
5462159047fSniklas     }
5472159047fSniklas 
548*68302bafSotto   return TRUE;
5492159047fSniklas }
5502159047fSniklas 
551e93f7393Sniklas static long
tekhex_canonicalize_symtab(abfd,table)552007c2a45Smiod tekhex_canonicalize_symtab (abfd, table)
5532159047fSniklas      bfd *abfd;
5542159047fSniklas      asymbol **table;
5552159047fSniklas {
5562159047fSniklas   tekhex_symbol_type *p = abfd->tdata.tekhex_data->symbols;
5572159047fSniklas   unsigned int c = bfd_get_symcount (abfd);
5582159047fSniklas 
5592159047fSniklas   table[c] = 0;
5602159047fSniklas   while (p)
5612159047fSniklas     {
5622159047fSniklas       table[--c] = &(p->symbol);
5632159047fSniklas       p = p->prev;
5642159047fSniklas     }
5652159047fSniklas 
5662159047fSniklas   return bfd_get_symcount (abfd);
5672159047fSniklas }
5682159047fSniklas 
569e93f7393Sniklas static long
tekhex_get_symtab_upper_bound(abfd)5702159047fSniklas tekhex_get_symtab_upper_bound (abfd)
5712159047fSniklas      bfd *abfd;
5722159047fSniklas {
5732159047fSniklas   return (abfd->symcount + 1) * (sizeof (struct tekhex_asymbol_struct *));
5742159047fSniklas 
5752159047fSniklas }
5762159047fSniklas 
577c074d1c9Sdrahn static bfd_boolean
tekhex_mkobject(abfd)5782159047fSniklas tekhex_mkobject (abfd)
5792159047fSniklas      bfd *abfd;
5802159047fSniklas {
581c074d1c9Sdrahn   tdata_type *tdata;
5822159047fSniklas 
583c074d1c9Sdrahn   tdata = (tdata_type *) bfd_alloc (abfd, (bfd_size_type) sizeof (tdata_type));
5842159047fSniklas   if (!tdata)
585c074d1c9Sdrahn     return FALSE;
5862159047fSniklas   abfd->tdata.tekhex_data = tdata;
5872159047fSniklas   tdata->type = 1;
5882159047fSniklas   tdata->head = (tekhex_data_list_type *) NULL;
5892159047fSniklas   tdata->symbols = (struct tekhex_symbol_struct *) NULL;
5902159047fSniklas   tdata->data = (struct data_struct *) NULL;
591c074d1c9Sdrahn   return TRUE;
5922159047fSniklas }
5932159047fSniklas 
5942159047fSniklas /*
595c074d1c9Sdrahn   Return TRUE if the file looks like it's in TekHex format. Just look
5962159047fSniklas   for a percent sign and some hex digits */
5972159047fSniklas 
5982159047fSniklas static const bfd_target *
tekhex_object_p(abfd)5992159047fSniklas tekhex_object_p (abfd)
6002159047fSniklas      bfd *abfd;
6012159047fSniklas {
6022159047fSniklas   char b[4];
6032159047fSniklas 
6042159047fSniklas   tekhex_init ();
6052159047fSniklas 
6062159047fSniklas   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
607c074d1c9Sdrahn       || bfd_bread (b, (bfd_size_type) 4, abfd) != 4)
6082159047fSniklas     return NULL;
6092159047fSniklas 
6102159047fSniklas   if (b[0] != '%' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
6112159047fSniklas     return (const bfd_target *) NULL;
6122159047fSniklas 
6132159047fSniklas   tekhex_mkobject (abfd);
6142159047fSniklas 
615*68302bafSotto   if (!pass_over (abfd, first_phase))
616*68302bafSotto     return NULL;
617*68302bafSotto 
6182159047fSniklas   return abfd->xvec;
6192159047fSniklas }
6202159047fSniklas 
6212159047fSniklas static void
move_section_contents(abfd,section,locationp,offset,count,get)6222159047fSniklas move_section_contents (abfd, section, locationp, offset, count, get)
6232159047fSniklas      bfd *abfd;
6242159047fSniklas      asection *section;
625007c2a45Smiod      const PTR locationp;
626c074d1c9Sdrahn      file_ptr offset;
6272159047fSniklas      bfd_size_type count;
628c074d1c9Sdrahn      bfd_boolean get;
6292159047fSniklas {
6302159047fSniklas   bfd_vma addr;
6312159047fSniklas   char *location = (char *) locationp;
6322159047fSniklas   bfd_vma prev_number = 1;	/* Nothing can have this as a high bit*/
6332159047fSniklas   struct data_struct *d = (struct data_struct *) NULL;
6342159047fSniklas 
635c074d1c9Sdrahn   BFD_ASSERT (offset == 0);
6362159047fSniklas   for (addr = section->vma; count != 0; count--, addr++)
6372159047fSniklas     {
638c074d1c9Sdrahn       /* Get high bits of address.  */
639c074d1c9Sdrahn       bfd_vma chunk_number = addr & ~(bfd_vma) CHUNK_MASK;
6402159047fSniklas       bfd_vma low_bits = addr & CHUNK_MASK;
6412159047fSniklas 
6422159047fSniklas       if (chunk_number != prev_number)
6432159047fSniklas 	{
6442159047fSniklas 	  /* Different chunk, so move pointer */
6452159047fSniklas 	  d = find_chunk (abfd, chunk_number);
6462159047fSniklas 	}
6472159047fSniklas 
6482159047fSniklas       if (get)
6492159047fSniklas 	{
6502159047fSniklas 	  if (d->chunk_init[low_bits])
6512159047fSniklas 	    {
6522159047fSniklas 	      *location = d->chunk_data[low_bits];
6532159047fSniklas 	    }
6542159047fSniklas 	  else
6552159047fSniklas 	    {
6562159047fSniklas 	      *location = 0;
6572159047fSniklas 	    }
6582159047fSniklas 	}
6592159047fSniklas       else
6602159047fSniklas 	{
6612159047fSniklas 	  d->chunk_data[low_bits] = *location;
6622159047fSniklas 	  d->chunk_init[low_bits] = (*location != 0);
6632159047fSniklas 	}
6642159047fSniklas 
6652159047fSniklas       location++;
6662159047fSniklas 
6672159047fSniklas     }
6682159047fSniklas 
6692159047fSniklas }
670e93f7393Sniklas 
671c074d1c9Sdrahn static bfd_boolean
tekhex_get_section_contents(abfd,section,locationp,offset,count)6722159047fSniklas tekhex_get_section_contents (abfd, section, locationp, offset, count)
6732159047fSniklas      bfd *abfd;
6742159047fSniklas      asection *section;
6752159047fSniklas      PTR locationp;
6762159047fSniklas      file_ptr offset;
6772159047fSniklas      bfd_size_type count;
6782159047fSniklas {
6792159047fSniklas   if (section->flags & (SEC_LOAD | SEC_ALLOC))
6802159047fSniklas     {
681c074d1c9Sdrahn       move_section_contents (abfd, section, locationp, offset, count, TRUE);
682c074d1c9Sdrahn       return TRUE;
6832159047fSniklas     }
6842159047fSniklas   else
685c074d1c9Sdrahn     return FALSE;
6862159047fSniklas }
6872159047fSniklas 
688c074d1c9Sdrahn static bfd_boolean
tekhex_set_arch_mach(abfd,arch,machine)6892159047fSniklas tekhex_set_arch_mach (abfd, arch, machine)
6902159047fSniklas      bfd *abfd;
6912159047fSniklas      enum bfd_architecture arch;
6922159047fSniklas      unsigned long machine;
6932159047fSniklas {
6942159047fSniklas   return bfd_default_set_arch_mach (abfd, arch, machine);
6952159047fSniklas }
6962159047fSniklas 
6972159047fSniklas /* we have to save up all the Tekhexords for a splurge before output,
6982159047fSniklas     */
6992159047fSniklas 
700c074d1c9Sdrahn static bfd_boolean
tekhex_set_section_contents(abfd,section,locationp,offset,bytes_to_do)7012159047fSniklas tekhex_set_section_contents (abfd, section, locationp, offset, bytes_to_do)
7022159047fSniklas      bfd *abfd;
7032159047fSniklas      sec_ptr section;
704007c2a45Smiod      const PTR locationp;
7052159047fSniklas      file_ptr offset;
7062159047fSniklas      bfd_size_type bytes_to_do;
7072159047fSniklas {
7082159047fSniklas 
709c074d1c9Sdrahn   if (! abfd->output_has_begun)
7102159047fSniklas     {
7112159047fSniklas       /* The first time around, allocate enough sections to hold all the chunks */
7122159047fSniklas       asection *s = abfd->sections;
7132159047fSniklas       bfd_vma vma;
7142159047fSniklas 
7152159047fSniklas       for (s = abfd->sections; s; s = s->next)
7162159047fSniklas 	{
7172159047fSniklas 	  if (s->flags & SEC_LOAD)
7182159047fSniklas 	    {
719c074d1c9Sdrahn 	      for (vma = s->vma & ~(bfd_vma) CHUNK_MASK;
7202159047fSniklas 		   vma < s->vma + s->_raw_size;
7212159047fSniklas 		   vma += CHUNK_MASK)
7222159047fSniklas 		find_chunk (abfd, vma);
7232159047fSniklas 	    }
7242159047fSniklas 	}
7252159047fSniklas 
7262159047fSniklas     }
7272159047fSniklas   if (section->flags & (SEC_LOAD | SEC_ALLOC))
7282159047fSniklas     {
729c074d1c9Sdrahn       move_section_contents (abfd, section, locationp, offset, bytes_to_do,
730c074d1c9Sdrahn 			     FALSE);
731c074d1c9Sdrahn       return TRUE;
7322159047fSniklas     }
7332159047fSniklas   else
734c074d1c9Sdrahn     return FALSE;
7352159047fSniklas 
7362159047fSniklas }
7372159047fSniklas 
7382159047fSniklas static void
writevalue(dst,value)7392159047fSniklas writevalue (dst, value)
7402159047fSniklas      char **dst;
7412159047fSniklas      bfd_vma value;
7422159047fSniklas {
7432159047fSniklas   char *p = *dst;
7442159047fSniklas   int len;
7452159047fSniklas   int shift;
7462159047fSniklas 
7472159047fSniklas   for (len = 8, shift = 28; shift; shift -= 4, len--)
7482159047fSniklas     {
7492159047fSniklas       if ((value >> shift) & 0xf)
7502159047fSniklas 	{
7512159047fSniklas 	  *p++ = len + '0';
7522159047fSniklas 	  while (len)
7532159047fSniklas 	    {
7542159047fSniklas 	      *p++ = digs[(value >> shift) & 0xf];
7552159047fSniklas 	      shift -= 4;
7562159047fSniklas 	      len--;
7572159047fSniklas 	    }
7582159047fSniklas 	  *dst = p;
7592159047fSniklas 	  return;
7602159047fSniklas 
7612159047fSniklas 	}
7622159047fSniklas     }
7632159047fSniklas   *p++ = '1';
7642159047fSniklas   *p++ = '0';
7652159047fSniklas   *dst = p;
7662159047fSniklas }
7672159047fSniklas 
7682159047fSniklas static void
writesym(dst,sym)7692159047fSniklas writesym (dst, sym)
7702159047fSniklas      char **dst;
771c074d1c9Sdrahn      const char *sym;
7722159047fSniklas {
7732159047fSniklas   char *p = *dst;
7742159047fSniklas   int len = (sym ? strlen (sym) : 0);
7752159047fSniklas 
7762159047fSniklas   if (len >= 16)
7772159047fSniklas     {
7782159047fSniklas       *p++ = '0';
7792159047fSniklas       len = 16;
7802159047fSniklas     }
7812159047fSniklas 
7822159047fSniklas   else
7832159047fSniklas     {
7842159047fSniklas       if (len == 0)
7852159047fSniklas 	{
7862159047fSniklas 	  *p++ = '1';
7872159047fSniklas 	  sym = "$";
7882159047fSniklas 	  len = 1;
7892159047fSniklas 	}
7902159047fSniklas       else
7912159047fSniklas 	{
7922159047fSniklas 	  *p++ = digs[len];
7932159047fSniklas 	}
7942159047fSniklas     }
7952159047fSniklas 
7962159047fSniklas   while (len--)
7972159047fSniklas     {
7982159047fSniklas       *p++ = *sym++;
7992159047fSniklas     }
8002159047fSniklas   *dst = p;
8012159047fSniklas }
8022159047fSniklas 
8032159047fSniklas static void
out(abfd,type,start,end)8042159047fSniklas out (abfd, type, start, end)
8052159047fSniklas      bfd *abfd;
806e93f7393Sniklas      int type;
8072159047fSniklas      char *start;
8082159047fSniklas      char *end;
8092159047fSniklas {
8102159047fSniklas   int sum = 0;
8112159047fSniklas   char *s;
8122159047fSniklas   char front[6];
8132159047fSniklas   bfd_size_type wrlen;
8142159047fSniklas 
8152159047fSniklas   front[0] = '%';
8162159047fSniklas   TOHEX (front + 1, end - start + 5);
8172159047fSniklas   front[3] = type;
8182159047fSniklas 
8192159047fSniklas   for (s = start; s < end; s++)
8202159047fSniklas     {
8212159047fSniklas       sum += sum_block[(unsigned char) *s];
8222159047fSniklas     }
8232159047fSniklas 
8242159047fSniklas   sum += sum_block[(unsigned char) front[1]];	/*  length */
8252159047fSniklas   sum += sum_block[(unsigned char) front[2]];
8262159047fSniklas   sum += sum_block[(unsigned char) front[3]];	/* type */
8272159047fSniklas   TOHEX (front + 4, sum);
828c074d1c9Sdrahn   if (bfd_bwrite (front, (bfd_size_type) 6, abfd) != 6)
8292159047fSniklas     abort ();
8302159047fSniklas   end[0] = '\n';
8312159047fSniklas   wrlen = end - start + 1;
832c074d1c9Sdrahn   if (bfd_bwrite (start, wrlen, abfd) != wrlen)
8332159047fSniklas     abort ();
8342159047fSniklas }
8352159047fSniklas 
836c074d1c9Sdrahn static bfd_boolean
tekhex_write_object_contents(abfd)8372159047fSniklas tekhex_write_object_contents (abfd)
8382159047fSniklas      bfd *abfd;
8392159047fSniklas {
8402159047fSniklas   int bytes_written;
8412159047fSniklas   char buffer[100];
8422159047fSniklas   asymbol **p;
8432159047fSniklas   asection *s;
8442159047fSniklas   struct data_struct *d;
8452159047fSniklas 
846b305b0f1Sespie   tekhex_init ();
847b305b0f1Sespie 
8482159047fSniklas   bytes_written = 0;
8492159047fSniklas 
8502159047fSniklas   /* And the raw data */
8512159047fSniklas   for (d = abfd->tdata.tekhex_data->data;
8522159047fSniklas        d != (struct data_struct *) NULL;
8532159047fSniklas        d = d->next)
8542159047fSniklas     {
8552159047fSniklas       int low;
8562159047fSniklas 
857c074d1c9Sdrahn       const int span = 32;
8582159047fSniklas       int addr;
8592159047fSniklas 
8602159047fSniklas       /* Write it in blocks of 32 bytes */
8612159047fSniklas 
8622159047fSniklas       for (addr = 0; addr < CHUNK_MASK + 1; addr += span)
8632159047fSniklas 	{
8642159047fSniklas 	  int need = 0;
8652159047fSniklas 
8662159047fSniklas 	  /* Check to see if necessary */
8672159047fSniklas 	  for (low = 0; !need && low < span; low++)
8682159047fSniklas 	    {
8692159047fSniklas 	      if (d->chunk_init[addr + low])
8702159047fSniklas 		need = 1;
8712159047fSniklas 	    }
8722159047fSniklas 	  if (need)
8732159047fSniklas 	    {
8742159047fSniklas 	      char *dst = buffer;
8752159047fSniklas 
8762159047fSniklas 	      writevalue (&dst, addr + d->vma);
8772159047fSniklas 	      for (low = 0; low < span; low++)
8782159047fSniklas 		{
8792159047fSniklas 		  TOHEX (dst, d->chunk_data[addr + low]);
8802159047fSniklas 		  dst += 2;
8812159047fSniklas 		}
8822159047fSniklas 	      out (abfd, '6', buffer, dst);
8832159047fSniklas 	    }
8842159047fSniklas 	}
8852159047fSniklas     }
8862159047fSniklas   /* write all the section headers for the sections */
8872159047fSniklas   for (s = abfd->sections; s != (asection *) NULL; s = s->next)
8882159047fSniklas     {
8892159047fSniklas       char *dst = buffer;
8902159047fSniklas 
8912159047fSniklas       writesym (&dst, s->name);
8922159047fSniklas       *dst++ = '1';
8932159047fSniklas       writevalue (&dst, s->vma);
8942159047fSniklas       writevalue (&dst, s->vma + s->_raw_size);
8952159047fSniklas       out (abfd, '3', buffer, dst);
8962159047fSniklas     }
8972159047fSniklas 
8982159047fSniklas   /* And the symbols */
899b305b0f1Sespie   if (abfd->outsymbols)
900b305b0f1Sespie     {
9012159047fSniklas       for (p = abfd->outsymbols; *p; p++)
9022159047fSniklas 	{
9032159047fSniklas 	  int section_code = bfd_decode_symclass (*p);
9042159047fSniklas 
9052159047fSniklas 	  if (section_code != '?')
9062159047fSniklas 	    {			/* do not include debug symbols */
907c074d1c9Sdrahn 	      asymbol *sym = *p;
9082159047fSniklas 	      char *dst = buffer;
9092159047fSniklas 
910c074d1c9Sdrahn 	      writesym (&dst, sym->section->name);
9112159047fSniklas 
9122159047fSniklas 	      switch (section_code)
9132159047fSniklas 		{
9142159047fSniklas 		case 'A':
9152159047fSniklas 		  *dst++ = '2';
9162159047fSniklas 		  break;
9172159047fSniklas 		case 'a':
9182159047fSniklas 		  *dst++ = '6';
9192159047fSniklas 		  break;
9202159047fSniklas 		case 'D':
9212159047fSniklas 		case 'B':
9222159047fSniklas 		case 'O':
9232159047fSniklas 		  *dst++ = '4';
9242159047fSniklas 		  break;
9252159047fSniklas 		case 'd':
9262159047fSniklas 		case 'b':
9272159047fSniklas 		case 'o':
9282159047fSniklas 		  *dst++ = '8';
9292159047fSniklas 		  break;
9302159047fSniklas 		case 'T':
9312159047fSniklas 		  *dst++ = '3';
9322159047fSniklas 		  break;
9332159047fSniklas 		case 't':
9342159047fSniklas 		  *dst++ = '7';
9352159047fSniklas 		  break;
9362159047fSniklas 		case 'C':
9372159047fSniklas 		case 'U':
9382159047fSniklas 		  bfd_set_error (bfd_error_wrong_format);
939c074d1c9Sdrahn 		  return FALSE;
9402159047fSniklas 		}
9412159047fSniklas 
942c074d1c9Sdrahn 	      writesym (&dst, sym->name);
943c074d1c9Sdrahn 	      writevalue (&dst, sym->value + sym->section->vma);
9442159047fSniklas 	      out (abfd, '3', buffer, dst);
9452159047fSniklas 	    }
9462159047fSniklas 	}
947b305b0f1Sespie     }
9482159047fSniklas 
9492159047fSniklas   /* And the terminator */
950c074d1c9Sdrahn   if (bfd_bwrite ("%0781010\n", (bfd_size_type) 9, abfd) != 9)
9512159047fSniklas     abort ();
952c074d1c9Sdrahn   return TRUE;
9532159047fSniklas }
9542159047fSniklas 
9552159047fSniklas static int
tekhex_sizeof_headers(abfd,exec)9562159047fSniklas tekhex_sizeof_headers (abfd, exec)
957b305b0f1Sespie      bfd *abfd ATTRIBUTE_UNUSED;
958c074d1c9Sdrahn      bfd_boolean exec ATTRIBUTE_UNUSED;
9592159047fSniklas 
9602159047fSniklas {
9612159047fSniklas   return 0;
9622159047fSniklas }
9632159047fSniklas 
9642159047fSniklas static asymbol *
tekhex_make_empty_symbol(abfd)9652159047fSniklas tekhex_make_empty_symbol (abfd)
9662159047fSniklas      bfd *abfd;
9672159047fSniklas {
968c074d1c9Sdrahn   bfd_size_type amt = sizeof (struct tekhex_symbol_struct);
969c074d1c9Sdrahn   tekhex_symbol_type *new = (tekhex_symbol_type *) bfd_zalloc (abfd, amt);
9702159047fSniklas 
9712159047fSniklas   if (!new)
9722159047fSniklas     return NULL;
9732159047fSniklas   new->symbol.the_bfd = abfd;
9742159047fSniklas   new->prev = (struct tekhex_symbol_struct *) NULL;
9752159047fSniklas   return &(new->symbol);
9762159047fSniklas }
9772159047fSniklas 
9782159047fSniklas static void
tekhex_get_symbol_info(ignore_abfd,symbol,ret)9792159047fSniklas tekhex_get_symbol_info (ignore_abfd, symbol, ret)
980b305b0f1Sespie      bfd *ignore_abfd ATTRIBUTE_UNUSED;
9812159047fSniklas      asymbol *symbol;
9822159047fSniklas      symbol_info *ret;
9832159047fSniklas {
9842159047fSniklas   bfd_symbol_info (symbol, ret);
9852159047fSniklas }
9862159047fSniklas 
9872159047fSniklas static void
tekhex_print_symbol(abfd,filep,symbol,how)988c074d1c9Sdrahn tekhex_print_symbol (abfd, filep, symbol, how)
989c074d1c9Sdrahn      bfd *abfd;
9902159047fSniklas      PTR filep;
9912159047fSniklas      asymbol *symbol;
9922159047fSniklas      bfd_print_symbol_type how;
9932159047fSniklas {
9942159047fSniklas   FILE *file = (FILE *) filep;
9952159047fSniklas 
9962159047fSniklas   switch (how)
9972159047fSniklas     {
9982159047fSniklas     case bfd_print_symbol_name:
9992159047fSniklas       fprintf (file, "%s", symbol->name);
10002159047fSniklas       break;
10012159047fSniklas     case bfd_print_symbol_more:
10022159047fSniklas       break;
10032159047fSniklas 
10042159047fSniklas     case bfd_print_symbol_all:
10052159047fSniklas       {
1006c074d1c9Sdrahn 	const char *section_name = symbol->section->name;
10072159047fSniklas 
1008c074d1c9Sdrahn 	bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
10092159047fSniklas 
10102159047fSniklas 	fprintf (file, " %-5s %s",
10112159047fSniklas 		 section_name,
10122159047fSniklas 		 symbol->name);
10132159047fSniklas       }
10142159047fSniklas     }
10152159047fSniklas }
10162159047fSniklas 
10172159047fSniklas #define	tekhex_close_and_cleanup _bfd_generic_close_and_cleanup
10182159047fSniklas #define tekhex_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
10192159047fSniklas #define tekhex_new_section_hook _bfd_generic_new_section_hook
10202159047fSniklas 
1021b305b0f1Sespie #define tekhex_bfd_is_local_label_name bfd_generic_is_local_label_name
10222159047fSniklas #define tekhex_get_lineno _bfd_nosymbols_get_lineno
10232159047fSniklas #define tekhex_find_nearest_line _bfd_nosymbols_find_nearest_line
10242159047fSniklas #define tekhex_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
10252159047fSniklas #define tekhex_read_minisymbols _bfd_generic_read_minisymbols
10262159047fSniklas #define tekhex_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
10272159047fSniklas 
10282159047fSniklas #define tekhex_bfd_get_relocated_section_contents \
10292159047fSniklas   bfd_generic_get_relocated_section_contents
10302159047fSniklas #define tekhex_bfd_relax_section bfd_generic_relax_section
1031b305b0f1Sespie #define tekhex_bfd_gc_sections bfd_generic_gc_sections
1032c074d1c9Sdrahn #define tekhex_bfd_merge_sections bfd_generic_merge_sections
1033c074d1c9Sdrahn #define tekhex_bfd_discard_group bfd_generic_discard_group
10342159047fSniklas #define tekhex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
1035c074d1c9Sdrahn #define tekhex_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
10362159047fSniklas #define tekhex_bfd_link_add_symbols _bfd_generic_link_add_symbols
1037c074d1c9Sdrahn #define tekhex_bfd_link_just_syms _bfd_generic_link_just_syms
10382159047fSniklas #define tekhex_bfd_final_link _bfd_generic_final_link
10392159047fSniklas #define tekhex_bfd_link_split_section _bfd_generic_link_split_section
10402159047fSniklas 
10412159047fSniklas #define tekhex_get_section_contents_in_window \
10422159047fSniklas   _bfd_generic_get_section_contents_in_window
10432159047fSniklas 
10442159047fSniklas const bfd_target tekhex_vec =
10452159047fSniklas {
10462159047fSniklas   "tekhex",			/* name */
10472159047fSniklas   bfd_target_tekhex_flavour,
1048c88b1d6cSniklas   BFD_ENDIAN_UNKNOWN,		/* target byte order */
1049c88b1d6cSniklas   BFD_ENDIAN_UNKNOWN,		/* target headers byte order */
10502159047fSniklas   (EXEC_P |			/* object flags */
10512159047fSniklas    HAS_SYMS | HAS_LINENO | HAS_DEBUG | HAS_RELOC | HAS_LOCALS |
10522159047fSniklas    WP_TEXT | D_PAGED),
10532159047fSniklas   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
10542159047fSniklas    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* section flags */
10552159047fSniklas   0,				/* leading underscore */
10562159047fSniklas   ' ',				/* ar_pad_char */
10572159047fSniklas   16,				/* ar_max_namelen */
10582159047fSniklas   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
10592159047fSniklas   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
10602159047fSniklas   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* data */
10612159047fSniklas   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
10622159047fSniklas   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
10632159047fSniklas   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* hdrs */
10642159047fSniklas 
10652159047fSniklas   {
10662159047fSniklas     _bfd_dummy_target,
10672159047fSniklas     tekhex_object_p,		/* bfd_check_format */
10682159047fSniklas     _bfd_dummy_target,
10692159047fSniklas     _bfd_dummy_target,
10702159047fSniklas   },
10712159047fSniklas   {
10722159047fSniklas     bfd_false,
10732159047fSniklas     tekhex_mkobject,
10742159047fSniklas     _bfd_generic_mkarchive,
10752159047fSniklas     bfd_false,
10762159047fSniklas   },
10772159047fSniklas   {				/* bfd_write_contents */
10782159047fSniklas     bfd_false,
10792159047fSniklas     tekhex_write_object_contents,
10802159047fSniklas     _bfd_write_archive_contents,
10812159047fSniklas     bfd_false,
10822159047fSniklas   },
10832159047fSniklas 
10842159047fSniklas   BFD_JUMP_TABLE_GENERIC (tekhex),
10852159047fSniklas   BFD_JUMP_TABLE_COPY (_bfd_generic),
10862159047fSniklas   BFD_JUMP_TABLE_CORE (_bfd_nocore),
10872159047fSniklas   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
10882159047fSniklas   BFD_JUMP_TABLE_SYMBOLS (tekhex),
10892159047fSniklas   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
10902159047fSniklas   BFD_JUMP_TABLE_WRITE (tekhex),
10912159047fSniklas   BFD_JUMP_TABLE_LINK (tekhex),
10922159047fSniklas   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
10932159047fSniklas 
1094b305b0f1Sespie   NULL,
1095b305b0f1Sespie 
10962159047fSniklas   (PTR) 0
10972159047fSniklas };
1098