xref: /dflybsd-src/contrib/gdb-7/bfd/tekhex.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
15796c8dcSSimon Schubert /* BFD backend for Extended Tektronix Hex Format  objects.
25796c8dcSSimon Schubert    Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002,
3*a45ae5f8SJohn Marino    2003, 2004, 2005, 2006, 2007, 2009, 2011 Free Software Foundation, Inc.
45796c8dcSSimon Schubert    Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
55796c8dcSSimon Schubert 
65796c8dcSSimon Schubert    This file is part of BFD, the Binary File Descriptor library.
75796c8dcSSimon Schubert 
85796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
95796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
105796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
115796c8dcSSimon Schubert    (at your option) any later version.
125796c8dcSSimon Schubert 
135796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
145796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
155796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
165796c8dcSSimon Schubert    GNU General Public License for more details.
175796c8dcSSimon Schubert 
185796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
195796c8dcSSimon Schubert    along with this program; if not, write to the Free Software
205796c8dcSSimon Schubert    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
215796c8dcSSimon Schubert    MA 02110-1301, USA.  */
225796c8dcSSimon Schubert 
235796c8dcSSimon Schubert 
245796c8dcSSimon Schubert /* SUBSECTION
255796c8dcSSimon Schubert 	Tektronix Hex Format handling
265796c8dcSSimon Schubert 
275796c8dcSSimon Schubert    DESCRIPTION
285796c8dcSSimon Schubert 
295796c8dcSSimon Schubert 	Tek Hex records can hold symbols and data, but not
305796c8dcSSimon Schubert 	relocations. Their main application is communication with
315796c8dcSSimon Schubert 	devices like PROM programmers and ICE equipment.
325796c8dcSSimon Schubert 
335796c8dcSSimon Schubert 	It seems that the sections are described as being really big,
345796c8dcSSimon Schubert         the example I have says that the text section is 0..ffffffff.
355796c8dcSSimon Schubert 	BFD would barf with this, many apps would try to alloc 4GB to
365796c8dcSSimon Schubert 	read in the file.
375796c8dcSSimon Schubert 
385796c8dcSSimon Schubert 	Tex Hex may contain many sections, but the data which comes in
395796c8dcSSimon Schubert 	has no tag saying which section it belongs to, so we create
405796c8dcSSimon Schubert 	one section for each block of data, called "blknnnn" which we
415796c8dcSSimon Schubert 	stick all the data into.
425796c8dcSSimon Schubert 
435796c8dcSSimon Schubert 	TekHex may come out of 	order and there is no header, so an
445796c8dcSSimon Schubert 	initial scan is required  to discover the minimum and maximum
455796c8dcSSimon Schubert 	addresses used to create the vma and size of the sections we
465796c8dcSSimon Schubert 	create.
475796c8dcSSimon Schubert 	We read in the data into pages of CHUNK_MASK+1 size and read
485796c8dcSSimon Schubert 	them out from that whenever we need to.
495796c8dcSSimon Schubert 
505796c8dcSSimon Schubert 	Any number of sections may be created for output, we save them
515796c8dcSSimon Schubert 	up and output them when it's time to close the bfd.
525796c8dcSSimon Schubert 
535796c8dcSSimon Schubert 	A TekHex record looks like:
545796c8dcSSimon Schubert   EXAMPLE
555796c8dcSSimon Schubert 	%<block length><type><checksum><stuff><cr>
565796c8dcSSimon Schubert 
575796c8dcSSimon Schubert   DESCRIPTION
585796c8dcSSimon Schubert 	Where
595796c8dcSSimon Schubert 	o length
605796c8dcSSimon Schubert 	is the number of bytes in the record not including the % sign.
615796c8dcSSimon Schubert 	o type
625796c8dcSSimon Schubert 	is one of:
635796c8dcSSimon Schubert 	3) symbol record
645796c8dcSSimon Schubert 	6) data record
655796c8dcSSimon Schubert 	8) termination record
665796c8dcSSimon Schubert 
675796c8dcSSimon Schubert   The data can come out of order, and may be discontigous. This is a
685796c8dcSSimon Schubert   serial protocol, so big files are unlikely, so we keep a list of 8k chunks.  */
695796c8dcSSimon Schubert 
705796c8dcSSimon Schubert #include "sysdep.h"
715796c8dcSSimon Schubert #include "bfd.h"
725796c8dcSSimon Schubert #include "libbfd.h"
735796c8dcSSimon Schubert #include "libiberty.h"
745796c8dcSSimon Schubert 
755796c8dcSSimon Schubert typedef struct
765796c8dcSSimon Schubert {
775796c8dcSSimon Schubert   bfd_vma low;
785796c8dcSSimon Schubert   bfd_vma high;
795796c8dcSSimon Schubert } addr_range_type;
805796c8dcSSimon Schubert 
815796c8dcSSimon Schubert typedef struct tekhex_symbol_struct
825796c8dcSSimon Schubert {
835796c8dcSSimon Schubert   asymbol symbol;
845796c8dcSSimon Schubert   struct tekhex_symbol_struct *prev;
855796c8dcSSimon Schubert } tekhex_symbol_type;
865796c8dcSSimon Schubert 
875796c8dcSSimon Schubert static const char digs[] = "0123456789ABCDEF";
885796c8dcSSimon Schubert 
895796c8dcSSimon Schubert static char sum_block[256];
905796c8dcSSimon Schubert 
915796c8dcSSimon Schubert #define NOT_HEX      20
925796c8dcSSimon Schubert #define NIBBLE(x)    hex_value(x)
935796c8dcSSimon Schubert #define HEX(buffer) ((NIBBLE ((buffer)[0]) << 4) + NIBBLE ((buffer)[1]))
945796c8dcSSimon Schubert #define	ISHEX(x)    hex_p(x)
955796c8dcSSimon Schubert #define TOHEX(d, x) \
965796c8dcSSimon Schubert   (d)[1] = digs[(x) & 0xf]; \
975796c8dcSSimon Schubert   (d)[0] = digs[((x)>>4)&0xf];
985796c8dcSSimon Schubert 
995796c8dcSSimon Schubert /* Here's an example
1005796c8dcSSimon Schubert    %3A6C6480004E56FFFC4E717063B0AEFFFC6D0652AEFFFC60F24E5E4E75
1015796c8dcSSimon Schubert    %1B3709T_SEGMENT1108FFFFFFFF
1025796c8dcSSimon Schubert    %2B3AB9T_SEGMENT7Dgcc_compiled$1087hello$c10
1035796c8dcSSimon Schubert    %373829T_SEGMENT80int$t1$r1$$214741080char$t2$r2$0$12710
1045796c8dcSSimon Schubert    %373769T_SEGMENT80long$int$t3$r1$$1080unsigned$int$t4$10
1055796c8dcSSimon Schubert    %373CA9T_SEGMENT80long$unsigned$in1080short$int$t6$r1$10
1065796c8dcSSimon Schubert    %373049T_SEGMENT80long$long$int$t71080short$unsigned$i10
1075796c8dcSSimon Schubert    %373A29T_SEGMENT80long$long$unsign1080signed$char$t10$10
1085796c8dcSSimon Schubert    %373D69T_SEGMENT80unsigned$char$t11080float$t12$r1$4$010
1095796c8dcSSimon Schubert    %373D19T_SEGMENT80double$t13$r1$8$1080long$double$t14$10
1105796c8dcSSimon Schubert    %2734D9T_SEGMENT8Bvoid$t15$151035_main10
1115796c8dcSSimon Schubert    %2F3CA9T_SEGMENT81$1081$1681$1E81$21487main$F110
1125796c8dcSSimon Schubert    %2832F9T_SEGMENT83i$18FFFFFFFC81$1481$214
1135796c8dcSSimon Schubert    %07 8 10 10
1145796c8dcSSimon Schubert 
1155796c8dcSSimon Schubert    explanation:
1165796c8dcSSimon Schubert    %3A6C6480004E56FFFC4E717063B0AEFFFC6D0652AEFFFC60F24E5E4E75
1175796c8dcSSimon Schubert     ^ ^^ ^     ^-data
1185796c8dcSSimon Schubert     | || +------ 4 char integer 0x8000
1195796c8dcSSimon Schubert     | |+-------- checksum
1205796c8dcSSimon Schubert     | +--------- type 6 (data record)
1215796c8dcSSimon Schubert     +----------- length 3a chars
1225796c8dcSSimon Schubert    <---------------------- 3a (58 chars) ------------------->
1235796c8dcSSimon Schubert 
1245796c8dcSSimon Schubert    %1B3709T_SEGMENT1108FFFFFFFF
1255796c8dcSSimon Schubert          ^         ^^ ^- 8 character integer 0xffffffff
1265796c8dcSSimon Schubert          |         |+-   1 character integer 0
1275796c8dcSSimon Schubert          |         +--   type 1 symbol (section definition)
1285796c8dcSSimon Schubert          +------------   9 char symbol T_SEGMENT
1295796c8dcSSimon Schubert 
1305796c8dcSSimon Schubert    %2B3AB9T_SEGMENT7Dgcc_compiled$1087hello$c10
1315796c8dcSSimon Schubert    %373829T_SEGMENT80int$t1$r1$$214741080char$t2$r2$0$12710
1325796c8dcSSimon Schubert    %373769T_SEGMENT80long$int$t3$r1$$1080unsigned$int$t4$10
1335796c8dcSSimon Schubert    %373CA9T_SEGMENT80long$unsigned$in1080short$int$t6$r1$10
1345796c8dcSSimon Schubert    %373049T_SEGMENT80long$long$int$t71080short$unsigned$i10
1355796c8dcSSimon Schubert    %373A29T_SEGMENT80long$long$unsign1080signed$char$t10$10
1365796c8dcSSimon Schubert    %373D69T_SEGMENT80unsigned$char$t11080float$t12$r1$4$010
1375796c8dcSSimon Schubert    %373D19T_SEGMENT80double$t13$r1$8$1080long$double$t14$10
1385796c8dcSSimon Schubert    %2734D9T_SEGMENT8Bvoid$t15$151035_main10
1395796c8dcSSimon Schubert    %2F3CA9T_SEGMENT81$1081$1681$1E81$21487main$F110
1405796c8dcSSimon Schubert    %2832F9T_SEGMENT83i$18FFFFFFFC81$1481$214
1415796c8dcSSimon Schubert    %0781010
1425796c8dcSSimon Schubert 
1435796c8dcSSimon Schubert    Turns into
1445796c8dcSSimon Schubert    sac@thepub$ ./objdump -dx -m m68k f
1455796c8dcSSimon Schubert 
1465796c8dcSSimon Schubert    f:     file format tekhex
1475796c8dcSSimon Schubert    -----x--- 9/55728 -134219416 Sep 29 15:13 1995 f
1485796c8dcSSimon Schubert    architecture: UNKNOWN!, flags 0x00000010:
1495796c8dcSSimon Schubert    HAS_SYMS
1505796c8dcSSimon Schubert    start address 0x00000000
1515796c8dcSSimon Schubert    SECTION 0 [D00000000]	: size 00020000 vma 00000000 align 2**0
1525796c8dcSSimon Schubert    ALLOC, LOAD
1535796c8dcSSimon Schubert    SECTION 1 [D00008000]	: size 00002001 vma 00008000 align 2**0
1545796c8dcSSimon Schubert 
1555796c8dcSSimon Schubert    SECTION 2 [T_SEGMENT]	: size ffffffff vma 00000000 align 2**0
1565796c8dcSSimon Schubert 
1575796c8dcSSimon Schubert    SYMBOL TABLE:
1585796c8dcSSimon Schubert    00000000  g       T_SEGMENT gcc_compiled$
1595796c8dcSSimon Schubert    00000000  g       T_SEGMENT hello$c
1605796c8dcSSimon Schubert    00000000  g       T_SEGMENT int$t1$r1$$21474
1615796c8dcSSimon Schubert    00000000  g       T_SEGMENT char$t2$r2$0$127
1625796c8dcSSimon Schubert    00000000  g       T_SEGMENT long$int$t3$r1$$
1635796c8dcSSimon Schubert    00000000  g       T_SEGMENT unsigned$int$t4$
1645796c8dcSSimon Schubert    00000000  g       T_SEGMENT long$unsigned$in
1655796c8dcSSimon Schubert    00000000  g       T_SEGMENT short$int$t6$r1$
1665796c8dcSSimon Schubert    00000000  g       T_SEGMENT long$long$int$t7
1675796c8dcSSimon Schubert    00000000  g       T_SEGMENT short$unsigned$i
1685796c8dcSSimon Schubert    00000000  g       T_SEGMENT long$long$unsign
1695796c8dcSSimon Schubert    00000000  g       T_SEGMENT signed$char$t10$
1705796c8dcSSimon Schubert    00000000  g       T_SEGMENT unsigned$char$t1
1715796c8dcSSimon Schubert    00000000  g       T_SEGMENT float$t12$r1$4$0
1725796c8dcSSimon Schubert    00000000  g       T_SEGMENT double$t13$r1$8$
1735796c8dcSSimon Schubert    00000000  g       T_SEGMENT long$double$t14$
1745796c8dcSSimon Schubert    00000000  g       T_SEGMENT void$t15$15
1755796c8dcSSimon Schubert    00000000  g       T_SEGMENT _main
1765796c8dcSSimon Schubert    00000000  g       T_SEGMENT $
1775796c8dcSSimon Schubert    00000000  g       T_SEGMENT $
1785796c8dcSSimon Schubert    00000000  g       T_SEGMENT $
1795796c8dcSSimon Schubert    00000010  g       T_SEGMENT $
1805796c8dcSSimon Schubert    00000000  g       T_SEGMENT main$F1
1815796c8dcSSimon Schubert    fcffffff  g       T_SEGMENT i$1
1825796c8dcSSimon Schubert    00000000  g       T_SEGMENT $
1835796c8dcSSimon Schubert    00000010  g       T_SEGMENT $
1845796c8dcSSimon Schubert 
1855796c8dcSSimon Schubert    RELOCATION RECORDS FOR [D00000000]: (none)
1865796c8dcSSimon Schubert 
1875796c8dcSSimon Schubert    RELOCATION RECORDS FOR [D00008000]: (none)
1885796c8dcSSimon Schubert 
1895796c8dcSSimon Schubert    RELOCATION RECORDS FOR [T_SEGMENT]: (none)
1905796c8dcSSimon Schubert 
1915796c8dcSSimon Schubert    Disassembly of section D00000000:
1925796c8dcSSimon Schubert    ...
1935796c8dcSSimon Schubert    00008000 ($+)7ff0 linkw fp,#-4
1945796c8dcSSimon Schubert    00008004 ($+)7ff4 nop
1955796c8dcSSimon Schubert    00008006 ($+)7ff6 movel #99,d0
1965796c8dcSSimon Schubert    00008008 ($+)7ff8 cmpl fp@(-4),d0
1975796c8dcSSimon Schubert    0000800c ($+)7ffc blts 00008014 ($+)8004
1985796c8dcSSimon Schubert    0000800e ($+)7ffe addql #1,fp@(-4)
1995796c8dcSSimon Schubert    00008012 ($+)8002 bras 00008006 ($+)7ff6
2005796c8dcSSimon Schubert    00008014 ($+)8004 unlk fp
2015796c8dcSSimon Schubert    00008016 ($+)8006 rts
2025796c8dcSSimon Schubert    ...  */
2035796c8dcSSimon Schubert 
2045796c8dcSSimon Schubert static void
tekhex_init(void)2055796c8dcSSimon Schubert tekhex_init (void)
2065796c8dcSSimon Schubert {
2075796c8dcSSimon Schubert   unsigned int i;
2085796c8dcSSimon Schubert   static bfd_boolean inited = FALSE;
2095796c8dcSSimon Schubert   int val;
2105796c8dcSSimon Schubert 
2115796c8dcSSimon Schubert   if (! inited)
2125796c8dcSSimon Schubert     {
2135796c8dcSSimon Schubert       inited = TRUE;
2145796c8dcSSimon Schubert       hex_init ();
2155796c8dcSSimon Schubert       val = 0;
2165796c8dcSSimon Schubert       for (i = 0; i < 10; i++)
2175796c8dcSSimon Schubert 	sum_block[i + '0'] = val++;
2185796c8dcSSimon Schubert 
2195796c8dcSSimon Schubert       for (i = 'A'; i <= 'Z'; i++)
2205796c8dcSSimon Schubert 	sum_block[i] = val++;
2215796c8dcSSimon Schubert 
2225796c8dcSSimon Schubert       sum_block['$'] = val++;
2235796c8dcSSimon Schubert       sum_block['%'] = val++;
2245796c8dcSSimon Schubert       sum_block['.'] = val++;
2255796c8dcSSimon Schubert       sum_block['_'] = val++;
2265796c8dcSSimon Schubert       for (i = 'a'; i <= 'z'; i++)
2275796c8dcSSimon Schubert 	sum_block[i] = val++;
2285796c8dcSSimon Schubert     }
2295796c8dcSSimon Schubert }
2305796c8dcSSimon Schubert 
2315796c8dcSSimon Schubert /* The maximum number of bytes on a line is FF.  */
2325796c8dcSSimon Schubert #define MAXCHUNK 0xff
2335796c8dcSSimon Schubert /* The number of bytes we fit onto a line on output.  */
2345796c8dcSSimon Schubert #define CHUNK 21
2355796c8dcSSimon Schubert 
2365796c8dcSSimon Schubert /* We cannot output our tekhexords as we see them, we have to glue them
2375796c8dcSSimon Schubert    together, this is done in this structure : */
2385796c8dcSSimon Schubert 
2395796c8dcSSimon Schubert struct tekhex_data_list_struct
2405796c8dcSSimon Schubert {
2415796c8dcSSimon Schubert   unsigned char *data;
2425796c8dcSSimon Schubert   bfd_vma where;
2435796c8dcSSimon Schubert   bfd_size_type size;
2445796c8dcSSimon Schubert   struct tekhex_data_list_struct *next;
2455796c8dcSSimon Schubert 
2465796c8dcSSimon Schubert };
2475796c8dcSSimon Schubert typedef struct tekhex_data_list_struct tekhex_data_list_type;
2485796c8dcSSimon Schubert 
2495796c8dcSSimon Schubert #define CHUNK_MASK 0x1fff
2505796c8dcSSimon Schubert 
2515796c8dcSSimon Schubert struct data_struct
2525796c8dcSSimon Schubert {
2535796c8dcSSimon Schubert   char chunk_data[CHUNK_MASK + 1];
2545796c8dcSSimon Schubert   char chunk_init[CHUNK_MASK + 1];
2555796c8dcSSimon Schubert   bfd_vma vma;
2565796c8dcSSimon Schubert   struct data_struct *next;
2575796c8dcSSimon Schubert };
2585796c8dcSSimon Schubert 
2595796c8dcSSimon Schubert typedef struct tekhex_data_struct
2605796c8dcSSimon Schubert {
2615796c8dcSSimon Schubert   tekhex_data_list_type *head;
2625796c8dcSSimon Schubert   unsigned int type;
2635796c8dcSSimon Schubert   struct tekhex_symbol_struct *symbols;
2645796c8dcSSimon Schubert   struct data_struct *data;
2655796c8dcSSimon Schubert } tdata_type;
2665796c8dcSSimon Schubert 
2675796c8dcSSimon Schubert #define enda(x) (x->vma + x->size)
2685796c8dcSSimon Schubert 
2695796c8dcSSimon Schubert static bfd_boolean
getvalue(char ** srcp,bfd_vma * valuep)2705796c8dcSSimon Schubert getvalue (char **srcp, bfd_vma *valuep)
2715796c8dcSSimon Schubert {
2725796c8dcSSimon Schubert   char *src = *srcp;
2735796c8dcSSimon Schubert   bfd_vma value = 0;
2745796c8dcSSimon Schubert   unsigned int len;
2755796c8dcSSimon Schubert 
2765796c8dcSSimon Schubert   if (!ISHEX (*src))
2775796c8dcSSimon Schubert     return FALSE;
2785796c8dcSSimon Schubert 
2795796c8dcSSimon Schubert   len = hex_value (*src++);
2805796c8dcSSimon Schubert   if (len == 0)
2815796c8dcSSimon Schubert     len = 16;
2825796c8dcSSimon Schubert   while (len--)
2835796c8dcSSimon Schubert     {
2845796c8dcSSimon Schubert       if (!ISHEX (*src))
2855796c8dcSSimon Schubert 	return FALSE;
2865796c8dcSSimon Schubert       value = value << 4 | hex_value (*src++);
2875796c8dcSSimon Schubert     }
2885796c8dcSSimon Schubert 
2895796c8dcSSimon Schubert   *srcp = src;
2905796c8dcSSimon Schubert   *valuep = value;
2915796c8dcSSimon Schubert   return TRUE;
2925796c8dcSSimon Schubert }
2935796c8dcSSimon Schubert 
2945796c8dcSSimon Schubert static bfd_boolean
getsym(char * dstp,char ** srcp,unsigned int * lenp)2955796c8dcSSimon Schubert getsym (char *dstp, char **srcp, unsigned int *lenp)
2965796c8dcSSimon Schubert {
2975796c8dcSSimon Schubert   char *src = *srcp;
2985796c8dcSSimon Schubert   unsigned int i;
2995796c8dcSSimon Schubert   unsigned int len;
3005796c8dcSSimon Schubert 
3015796c8dcSSimon Schubert   if (!ISHEX (*src))
3025796c8dcSSimon Schubert     return FALSE;
3035796c8dcSSimon Schubert 
3045796c8dcSSimon Schubert   len = hex_value (*src++);
3055796c8dcSSimon Schubert   if (len == 0)
3065796c8dcSSimon Schubert     len = 16;
3075796c8dcSSimon Schubert   for (i = 0; i < len; i++)
3085796c8dcSSimon Schubert     dstp[i] = src[i];
3095796c8dcSSimon Schubert   dstp[i] = 0;
3105796c8dcSSimon Schubert   *srcp = src + i;
3115796c8dcSSimon Schubert   *lenp = len;
3125796c8dcSSimon Schubert   return TRUE;
3135796c8dcSSimon Schubert }
3145796c8dcSSimon Schubert 
3155796c8dcSSimon Schubert static struct data_struct *
find_chunk(bfd * abfd,bfd_vma vma)3165796c8dcSSimon Schubert find_chunk (bfd *abfd, bfd_vma vma)
3175796c8dcSSimon Schubert {
3185796c8dcSSimon Schubert   struct data_struct *d = abfd->tdata.tekhex_data->data;
3195796c8dcSSimon Schubert 
3205796c8dcSSimon Schubert   vma &= ~CHUNK_MASK;
3215796c8dcSSimon Schubert   while (d && (d->vma) != vma)
3225796c8dcSSimon Schubert     d = d->next;
3235796c8dcSSimon Schubert 
3245796c8dcSSimon Schubert   if (!d)
3255796c8dcSSimon Schubert     {
3265796c8dcSSimon Schubert       /* No chunk for this address, so make one up.  */
3275796c8dcSSimon Schubert       d = (struct data_struct *)
3285796c8dcSSimon Schubert           bfd_zalloc (abfd, (bfd_size_type) sizeof (struct data_struct));
3295796c8dcSSimon Schubert 
3305796c8dcSSimon Schubert       if (!d)
3315796c8dcSSimon Schubert 	return NULL;
3325796c8dcSSimon Schubert 
3335796c8dcSSimon Schubert       d->next = abfd->tdata.tekhex_data->data;
3345796c8dcSSimon Schubert       d->vma = vma;
3355796c8dcSSimon Schubert       abfd->tdata.tekhex_data->data = d;
3365796c8dcSSimon Schubert     }
3375796c8dcSSimon Schubert   return d;
3385796c8dcSSimon Schubert }
3395796c8dcSSimon Schubert 
3405796c8dcSSimon Schubert static void
insert_byte(bfd * abfd,int value,bfd_vma addr)3415796c8dcSSimon Schubert insert_byte (bfd *abfd, int value, bfd_vma addr)
3425796c8dcSSimon Schubert {
3435796c8dcSSimon Schubert   /* Find the chunk that this byte needs and put it in.  */
3445796c8dcSSimon Schubert   struct data_struct *d = find_chunk (abfd, addr);
3455796c8dcSSimon Schubert 
3465796c8dcSSimon Schubert   d->chunk_data[addr & CHUNK_MASK] = value;
3475796c8dcSSimon Schubert   d->chunk_init[addr & CHUNK_MASK] = 1;
3485796c8dcSSimon Schubert }
3495796c8dcSSimon Schubert 
3505796c8dcSSimon Schubert /* The first pass is to find the names of all the sections, and see
3515796c8dcSSimon Schubert   how big the data is.  */
3525796c8dcSSimon Schubert 
3535796c8dcSSimon Schubert static bfd_boolean
first_phase(bfd * abfd,int type,char * src)3545796c8dcSSimon Schubert first_phase (bfd *abfd, int type, char *src)
3555796c8dcSSimon Schubert {
3565796c8dcSSimon Schubert   asection *section = bfd_abs_section_ptr;
3575796c8dcSSimon Schubert   unsigned int len;
3585796c8dcSSimon Schubert   bfd_vma val;
3595796c8dcSSimon Schubert   char sym[17];			/* A symbol can only be 16chars long.  */
3605796c8dcSSimon Schubert 
3615796c8dcSSimon Schubert   switch (type)
3625796c8dcSSimon Schubert     {
3635796c8dcSSimon Schubert     case '6':
3645796c8dcSSimon Schubert       /* Data record - read it and store it.  */
3655796c8dcSSimon Schubert       {
3665796c8dcSSimon Schubert 	bfd_vma addr;
3675796c8dcSSimon Schubert 
3685796c8dcSSimon Schubert 	if (!getvalue (&src, &addr))
3695796c8dcSSimon Schubert 	  return FALSE;
3705796c8dcSSimon Schubert 
3715796c8dcSSimon Schubert 	while (*src)
3725796c8dcSSimon Schubert 	  {
3735796c8dcSSimon Schubert 	    insert_byte (abfd, HEX (src), addr);
3745796c8dcSSimon Schubert 	    src += 2;
3755796c8dcSSimon Schubert 	    addr++;
3765796c8dcSSimon Schubert 	  }
3775796c8dcSSimon Schubert       }
3785796c8dcSSimon Schubert 
3795796c8dcSSimon Schubert       return TRUE;
3805796c8dcSSimon Schubert     case '3':
3815796c8dcSSimon Schubert       /* Symbol record, read the segment.  */
3825796c8dcSSimon Schubert       if (!getsym (sym, &src, &len))
3835796c8dcSSimon Schubert 	return FALSE;
3845796c8dcSSimon Schubert       section = bfd_get_section_by_name (abfd, sym);
3855796c8dcSSimon Schubert       if (section == NULL)
3865796c8dcSSimon Schubert 	{
3875796c8dcSSimon Schubert 	  char *n = (char *) bfd_alloc (abfd, (bfd_size_type) len + 1);
3885796c8dcSSimon Schubert 
3895796c8dcSSimon Schubert 	  if (!n)
3905796c8dcSSimon Schubert 	    return FALSE;
3915796c8dcSSimon Schubert 	  memcpy (n, sym, len + 1);
3925796c8dcSSimon Schubert 	  section = bfd_make_section (abfd, n);
3935796c8dcSSimon Schubert 	  if (section == NULL)
3945796c8dcSSimon Schubert 	    return FALSE;
3955796c8dcSSimon Schubert 	}
3965796c8dcSSimon Schubert       while (*src)
3975796c8dcSSimon Schubert 	{
3985796c8dcSSimon Schubert 	  switch (*src)
3995796c8dcSSimon Schubert 	    {
4005796c8dcSSimon Schubert 	    case '1':		/* Section range.  */
4015796c8dcSSimon Schubert 	      src++;
4025796c8dcSSimon Schubert 	      if (!getvalue (&src, &section->vma))
4035796c8dcSSimon Schubert 		return FALSE;
4045796c8dcSSimon Schubert 	      if (!getvalue (&src, &val))
4055796c8dcSSimon Schubert 		return FALSE;
4065796c8dcSSimon Schubert 	      section->size = val - section->vma;
4075796c8dcSSimon Schubert 	      section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
4085796c8dcSSimon Schubert 	      break;
4095796c8dcSSimon Schubert 	    case '0':
4105796c8dcSSimon Schubert 	    case '2':
4115796c8dcSSimon Schubert 	    case '3':
4125796c8dcSSimon Schubert 	    case '4':
4135796c8dcSSimon Schubert 	    case '6':
4145796c8dcSSimon Schubert 	    case '7':
4155796c8dcSSimon Schubert 	    case '8':
4165796c8dcSSimon Schubert 	      /* Symbols, add to section.  */
4175796c8dcSSimon Schubert 	      {
4185796c8dcSSimon Schubert 		bfd_size_type amt = sizeof (tekhex_symbol_type);
4195796c8dcSSimon Schubert 		tekhex_symbol_type *new_symbol = (tekhex_symbol_type *)
4205796c8dcSSimon Schubert                     bfd_alloc (abfd, amt);
4215796c8dcSSimon Schubert 		char stype = (*src);
4225796c8dcSSimon Schubert 
4235796c8dcSSimon Schubert 		if (!new_symbol)
4245796c8dcSSimon Schubert 		  return FALSE;
4255796c8dcSSimon Schubert 		new_symbol->symbol.the_bfd = abfd;
4265796c8dcSSimon Schubert 		src++;
4275796c8dcSSimon Schubert 		abfd->symcount++;
4285796c8dcSSimon Schubert 		abfd->flags |= HAS_SYMS;
4295796c8dcSSimon Schubert 		new_symbol->prev = abfd->tdata.tekhex_data->symbols;
4305796c8dcSSimon Schubert 		abfd->tdata.tekhex_data->symbols = new_symbol;
4315796c8dcSSimon Schubert 		if (!getsym (sym, &src, &len))
4325796c8dcSSimon Schubert 		  return FALSE;
4335796c8dcSSimon Schubert 		new_symbol->symbol.name = (const char *)
4345796c8dcSSimon Schubert                     bfd_alloc (abfd, (bfd_size_type) len + 1);
4355796c8dcSSimon Schubert 		if (!new_symbol->symbol.name)
4365796c8dcSSimon Schubert 		  return FALSE;
4375796c8dcSSimon Schubert 		memcpy ((char *) (new_symbol->symbol.name), sym, len + 1);
4385796c8dcSSimon Schubert 		new_symbol->symbol.section = section;
4395796c8dcSSimon Schubert 		if (stype <= '4')
4405796c8dcSSimon Schubert 		  new_symbol->symbol.flags = (BSF_GLOBAL | BSF_EXPORT);
4415796c8dcSSimon Schubert 		else
4425796c8dcSSimon Schubert 		  new_symbol->symbol.flags = BSF_LOCAL;
4435796c8dcSSimon Schubert 		if (!getvalue (&src, &val))
4445796c8dcSSimon Schubert 		  return FALSE;
4455796c8dcSSimon Schubert 		new_symbol->symbol.value = val - section->vma;
4465796c8dcSSimon Schubert 		break;
4475796c8dcSSimon Schubert 	      }
4485796c8dcSSimon Schubert 	    default:
4495796c8dcSSimon Schubert 	      return FALSE;
4505796c8dcSSimon Schubert 	    }
4515796c8dcSSimon Schubert 	}
4525796c8dcSSimon Schubert     }
4535796c8dcSSimon Schubert 
4545796c8dcSSimon Schubert   return TRUE;
4555796c8dcSSimon Schubert }
4565796c8dcSSimon Schubert 
4575796c8dcSSimon Schubert /* Pass over a tekhex, calling one of the above functions on each
4585796c8dcSSimon Schubert    record.  */
4595796c8dcSSimon Schubert 
4605796c8dcSSimon Schubert static bfd_boolean
pass_over(bfd * abfd,bfd_boolean (* func)(bfd *,int,char *))4615796c8dcSSimon Schubert pass_over (bfd *abfd, bfd_boolean (*func) (bfd *, int, char *))
4625796c8dcSSimon Schubert {
4635796c8dcSSimon Schubert   unsigned int chars_on_line;
464cf7f2e2dSJohn Marino   bfd_boolean is_eof = FALSE;
4655796c8dcSSimon Schubert 
4665796c8dcSSimon Schubert   /* To the front of the file.  */
4675796c8dcSSimon Schubert   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
4685796c8dcSSimon Schubert     return FALSE;
469cf7f2e2dSJohn Marino   while (! is_eof)
4705796c8dcSSimon Schubert     {
4715796c8dcSSimon Schubert       char src[MAXCHUNK];
4725796c8dcSSimon Schubert       char type;
4735796c8dcSSimon Schubert 
4745796c8dcSSimon Schubert       /* Find first '%'.  */
475cf7f2e2dSJohn Marino       is_eof = (bfd_boolean) (bfd_bread (src, (bfd_size_type) 1, abfd) != 1);
476cf7f2e2dSJohn Marino       while (*src != '%' && !is_eof)
477cf7f2e2dSJohn Marino 	is_eof = (bfd_boolean) (bfd_bread (src, (bfd_size_type) 1, abfd) != 1);
4785796c8dcSSimon Schubert 
479cf7f2e2dSJohn Marino       if (is_eof)
4805796c8dcSSimon Schubert 	break;
4815796c8dcSSimon Schubert 
4825796c8dcSSimon Schubert       /* Fetch the type and the length and the checksum.  */
4835796c8dcSSimon Schubert       if (bfd_bread (src, (bfd_size_type) 5, abfd) != 5)
4845796c8dcSSimon Schubert 	return FALSE;
4855796c8dcSSimon Schubert 
4865796c8dcSSimon Schubert       type = src[2];
4875796c8dcSSimon Schubert 
4885796c8dcSSimon Schubert       if (!ISHEX (src[0]) || !ISHEX (src[1]))
4895796c8dcSSimon Schubert 	break;
4905796c8dcSSimon Schubert 
4915796c8dcSSimon Schubert       /* Already read five chars.  */
4925796c8dcSSimon Schubert       chars_on_line = HEX (src) - 5;
4935796c8dcSSimon Schubert 
4945796c8dcSSimon Schubert       if (chars_on_line >= MAXCHUNK)
4955796c8dcSSimon Schubert 	return FALSE;
4965796c8dcSSimon Schubert 
4975796c8dcSSimon Schubert       if (bfd_bread (src, (bfd_size_type) chars_on_line, abfd) != chars_on_line)
4985796c8dcSSimon Schubert 	return FALSE;
4995796c8dcSSimon Schubert 
5005796c8dcSSimon Schubert       /* Put a null at the end.  */
5015796c8dcSSimon Schubert       src[chars_on_line] = 0;
5025796c8dcSSimon Schubert 
5035796c8dcSSimon Schubert       if (!func (abfd, type, src))
5045796c8dcSSimon Schubert 	return FALSE;
5055796c8dcSSimon Schubert     }
5065796c8dcSSimon Schubert 
5075796c8dcSSimon Schubert   return TRUE;
5085796c8dcSSimon Schubert }
5095796c8dcSSimon Schubert 
5105796c8dcSSimon Schubert static long
tekhex_canonicalize_symtab(bfd * abfd,asymbol ** table)5115796c8dcSSimon Schubert tekhex_canonicalize_symtab (bfd *abfd, asymbol **table)
5125796c8dcSSimon Schubert {
5135796c8dcSSimon Schubert   tekhex_symbol_type *p = abfd->tdata.tekhex_data->symbols;
5145796c8dcSSimon Schubert   unsigned int c = bfd_get_symcount (abfd);
5155796c8dcSSimon Schubert 
5165796c8dcSSimon Schubert   table[c] = 0;
5175796c8dcSSimon Schubert   while (p)
5185796c8dcSSimon Schubert     {
5195796c8dcSSimon Schubert       table[--c] = &(p->symbol);
5205796c8dcSSimon Schubert       p = p->prev;
5215796c8dcSSimon Schubert     }
5225796c8dcSSimon Schubert 
5235796c8dcSSimon Schubert   return bfd_get_symcount (abfd);
5245796c8dcSSimon Schubert }
5255796c8dcSSimon Schubert 
5265796c8dcSSimon Schubert static long
tekhex_get_symtab_upper_bound(bfd * abfd)5275796c8dcSSimon Schubert tekhex_get_symtab_upper_bound (bfd *abfd)
5285796c8dcSSimon Schubert {
5295796c8dcSSimon Schubert   return (abfd->symcount + 1) * (sizeof (struct tekhex_asymbol_struct *));
5305796c8dcSSimon Schubert 
5315796c8dcSSimon Schubert }
5325796c8dcSSimon Schubert 
5335796c8dcSSimon Schubert static bfd_boolean
tekhex_mkobject(bfd * abfd)5345796c8dcSSimon Schubert tekhex_mkobject (bfd *abfd)
5355796c8dcSSimon Schubert {
5365796c8dcSSimon Schubert   tdata_type *tdata;
5375796c8dcSSimon Schubert 
5385796c8dcSSimon Schubert   tdata = (tdata_type *) bfd_alloc (abfd, (bfd_size_type) sizeof (tdata_type));
5395796c8dcSSimon Schubert   if (!tdata)
5405796c8dcSSimon Schubert     return FALSE;
5415796c8dcSSimon Schubert   abfd->tdata.tekhex_data = tdata;
5425796c8dcSSimon Schubert   tdata->type = 1;
5435796c8dcSSimon Schubert   tdata->head =  NULL;
5445796c8dcSSimon Schubert   tdata->symbols = NULL;
5455796c8dcSSimon Schubert   tdata->data = NULL;
5465796c8dcSSimon Schubert   return TRUE;
5475796c8dcSSimon Schubert }
5485796c8dcSSimon Schubert 
5495796c8dcSSimon Schubert /* Return TRUE if the file looks like it's in TekHex format. Just look
5505796c8dcSSimon Schubert    for a percent sign and some hex digits.  */
5515796c8dcSSimon Schubert 
5525796c8dcSSimon Schubert static const bfd_target *
tekhex_object_p(bfd * abfd)5535796c8dcSSimon Schubert tekhex_object_p (bfd *abfd)
5545796c8dcSSimon Schubert {
5555796c8dcSSimon Schubert   char b[4];
5565796c8dcSSimon Schubert 
5575796c8dcSSimon Schubert   tekhex_init ();
5585796c8dcSSimon Schubert 
5595796c8dcSSimon Schubert   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
5605796c8dcSSimon Schubert       || bfd_bread (b, (bfd_size_type) 4, abfd) != 4)
5615796c8dcSSimon Schubert     return NULL;
5625796c8dcSSimon Schubert 
5635796c8dcSSimon Schubert   if (b[0] != '%' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
5645796c8dcSSimon Schubert     return NULL;
5655796c8dcSSimon Schubert 
5665796c8dcSSimon Schubert   tekhex_mkobject (abfd);
5675796c8dcSSimon Schubert 
5685796c8dcSSimon Schubert   if (!pass_over (abfd, first_phase))
5695796c8dcSSimon Schubert     return NULL;
5705796c8dcSSimon Schubert 
5715796c8dcSSimon Schubert   return abfd->xvec;
5725796c8dcSSimon Schubert }
5735796c8dcSSimon Schubert 
5745796c8dcSSimon Schubert static void
move_section_contents(bfd * abfd,asection * section,const void * locationp,file_ptr offset,bfd_size_type count,bfd_boolean get)5755796c8dcSSimon Schubert move_section_contents (bfd *abfd,
5765796c8dcSSimon Schubert 		       asection *section,
5775796c8dcSSimon Schubert 		       const void * locationp,
5785796c8dcSSimon Schubert 		       file_ptr offset,
5795796c8dcSSimon Schubert 		       bfd_size_type count,
5805796c8dcSSimon Schubert 		       bfd_boolean get)
5815796c8dcSSimon Schubert {
5825796c8dcSSimon Schubert   bfd_vma addr;
5835796c8dcSSimon Schubert   char *location = (char *) locationp;
5845796c8dcSSimon Schubert   bfd_vma prev_number = 1;	/* Nothing can have this as a high bit.  */
5855796c8dcSSimon Schubert   struct data_struct *d = NULL;
5865796c8dcSSimon Schubert 
5875796c8dcSSimon Schubert   BFD_ASSERT (offset == 0);
5885796c8dcSSimon Schubert   for (addr = section->vma; count != 0; count--, addr++)
5895796c8dcSSimon Schubert     {
5905796c8dcSSimon Schubert       /* Get high bits of address.  */
5915796c8dcSSimon Schubert       bfd_vma chunk_number = addr & ~(bfd_vma) CHUNK_MASK;
5925796c8dcSSimon Schubert       bfd_vma low_bits = addr & CHUNK_MASK;
5935796c8dcSSimon Schubert 
5945796c8dcSSimon Schubert       if (chunk_number != prev_number)
5955796c8dcSSimon Schubert 	/* Different chunk, so move pointer. */
5965796c8dcSSimon Schubert 	d = find_chunk (abfd, chunk_number);
5975796c8dcSSimon Schubert 
5985796c8dcSSimon Schubert       if (get)
5995796c8dcSSimon Schubert 	{
6005796c8dcSSimon Schubert 	  if (d->chunk_init[low_bits])
6015796c8dcSSimon Schubert 	    *location = d->chunk_data[low_bits];
6025796c8dcSSimon Schubert 	  else
6035796c8dcSSimon Schubert 	    *location = 0;
6045796c8dcSSimon Schubert 	}
6055796c8dcSSimon Schubert       else
6065796c8dcSSimon Schubert 	{
6075796c8dcSSimon Schubert 	  d->chunk_data[low_bits] = *location;
6085796c8dcSSimon Schubert 	  d->chunk_init[low_bits] = (*location != 0);
6095796c8dcSSimon Schubert 	}
6105796c8dcSSimon Schubert 
6115796c8dcSSimon Schubert       location++;
6125796c8dcSSimon Schubert     }
6135796c8dcSSimon Schubert }
6145796c8dcSSimon Schubert 
6155796c8dcSSimon Schubert static bfd_boolean
tekhex_get_section_contents(bfd * abfd,asection * section,void * locationp,file_ptr offset,bfd_size_type count)6165796c8dcSSimon Schubert tekhex_get_section_contents (bfd *abfd,
6175796c8dcSSimon Schubert 			     asection *section,
6185796c8dcSSimon Schubert 			     void * locationp,
6195796c8dcSSimon Schubert 			     file_ptr offset,
6205796c8dcSSimon Schubert 			     bfd_size_type count)
6215796c8dcSSimon Schubert {
6225796c8dcSSimon Schubert   if (section->flags & (SEC_LOAD | SEC_ALLOC))
6235796c8dcSSimon Schubert     {
6245796c8dcSSimon Schubert       move_section_contents (abfd, section, locationp, offset, count, TRUE);
6255796c8dcSSimon Schubert       return TRUE;
6265796c8dcSSimon Schubert     }
6275796c8dcSSimon Schubert 
6285796c8dcSSimon Schubert   return FALSE;
6295796c8dcSSimon Schubert }
6305796c8dcSSimon Schubert 
6315796c8dcSSimon Schubert static bfd_boolean
tekhex_set_arch_mach(bfd * abfd,enum bfd_architecture arch,unsigned long machine)6325796c8dcSSimon Schubert tekhex_set_arch_mach (bfd *abfd,
6335796c8dcSSimon Schubert 		      enum bfd_architecture arch,
6345796c8dcSSimon Schubert 		      unsigned long machine)
6355796c8dcSSimon Schubert {
6365796c8dcSSimon Schubert   return bfd_default_set_arch_mach (abfd, arch, machine);
6375796c8dcSSimon Schubert }
6385796c8dcSSimon Schubert 
6395796c8dcSSimon Schubert /* We have to save up all the Tekhexords for a splurge before output.  */
6405796c8dcSSimon Schubert 
6415796c8dcSSimon Schubert static bfd_boolean
tekhex_set_section_contents(bfd * abfd,sec_ptr section,const void * locationp,file_ptr offset,bfd_size_type bytes_to_do)6425796c8dcSSimon Schubert tekhex_set_section_contents (bfd *abfd,
6435796c8dcSSimon Schubert 			     sec_ptr section,
6445796c8dcSSimon Schubert 			     const void * locationp,
6455796c8dcSSimon Schubert 			     file_ptr offset,
6465796c8dcSSimon Schubert 			     bfd_size_type bytes_to_do)
6475796c8dcSSimon Schubert {
6485796c8dcSSimon Schubert   if (! abfd->output_has_begun)
6495796c8dcSSimon Schubert     {
6505796c8dcSSimon Schubert       /* The first time around, allocate enough sections to hold all the chunks.  */
6515796c8dcSSimon Schubert       asection *s = abfd->sections;
6525796c8dcSSimon Schubert       bfd_vma vma;
6535796c8dcSSimon Schubert 
6545796c8dcSSimon Schubert       for (s = abfd->sections; s; s = s->next)
6555796c8dcSSimon Schubert 	{
6565796c8dcSSimon Schubert 	  if (s->flags & SEC_LOAD)
6575796c8dcSSimon Schubert 	    {
6585796c8dcSSimon Schubert 	      for (vma = s->vma & ~(bfd_vma) CHUNK_MASK;
6595796c8dcSSimon Schubert 		   vma < s->vma + s->size;
6605796c8dcSSimon Schubert 		   vma += CHUNK_MASK)
6615796c8dcSSimon Schubert 		find_chunk (abfd, vma);
6625796c8dcSSimon Schubert 	    }
6635796c8dcSSimon Schubert 	}
6645796c8dcSSimon Schubert     }
6655796c8dcSSimon Schubert 
6665796c8dcSSimon Schubert   if (section->flags & (SEC_LOAD | SEC_ALLOC))
6675796c8dcSSimon Schubert     {
6685796c8dcSSimon Schubert       move_section_contents (abfd, section, locationp, offset, bytes_to_do,
6695796c8dcSSimon Schubert 			     FALSE);
6705796c8dcSSimon Schubert       return TRUE;
6715796c8dcSSimon Schubert     }
6725796c8dcSSimon Schubert 
6735796c8dcSSimon Schubert   return FALSE;
6745796c8dcSSimon Schubert }
6755796c8dcSSimon Schubert 
6765796c8dcSSimon Schubert static void
writevalue(char ** dst,bfd_vma value)6775796c8dcSSimon Schubert writevalue (char **dst, bfd_vma value)
6785796c8dcSSimon Schubert {
6795796c8dcSSimon Schubert   char *p = *dst;
6805796c8dcSSimon Schubert   int len;
6815796c8dcSSimon Schubert   int shift;
6825796c8dcSSimon Schubert 
6835796c8dcSSimon Schubert   for (len = 8, shift = 28; shift; shift -= 4, len--)
6845796c8dcSSimon Schubert     {
6855796c8dcSSimon Schubert       if ((value >> shift) & 0xf)
6865796c8dcSSimon Schubert 	{
6875796c8dcSSimon Schubert 	  *p++ = len + '0';
6885796c8dcSSimon Schubert 	  while (len)
6895796c8dcSSimon Schubert 	    {
6905796c8dcSSimon Schubert 	      *p++ = digs[(value >> shift) & 0xf];
6915796c8dcSSimon Schubert 	      shift -= 4;
6925796c8dcSSimon Schubert 	      len--;
6935796c8dcSSimon Schubert 	    }
6945796c8dcSSimon Schubert 	  *dst = p;
6955796c8dcSSimon Schubert 	  return;
6965796c8dcSSimon Schubert 
6975796c8dcSSimon Schubert 	}
6985796c8dcSSimon Schubert     }
6995796c8dcSSimon Schubert   *p++ = '1';
7005796c8dcSSimon Schubert   *p++ = '0';
7015796c8dcSSimon Schubert   *dst = p;
7025796c8dcSSimon Schubert }
7035796c8dcSSimon Schubert 
7045796c8dcSSimon Schubert static void
writesym(char ** dst,const char * sym)7055796c8dcSSimon Schubert writesym (char **dst, const char *sym)
7065796c8dcSSimon Schubert {
7075796c8dcSSimon Schubert   char *p = *dst;
7085796c8dcSSimon Schubert   int len = (sym ? strlen (sym) : 0);
7095796c8dcSSimon Schubert 
7105796c8dcSSimon Schubert   if (len >= 16)
7115796c8dcSSimon Schubert     {
7125796c8dcSSimon Schubert       *p++ = '0';
7135796c8dcSSimon Schubert       len = 16;
7145796c8dcSSimon Schubert     }
7155796c8dcSSimon Schubert   else
7165796c8dcSSimon Schubert     {
7175796c8dcSSimon Schubert       if (len == 0)
7185796c8dcSSimon Schubert 	{
7195796c8dcSSimon Schubert 	  *p++ = '1';
7205796c8dcSSimon Schubert 	  sym = "$";
7215796c8dcSSimon Schubert 	  len = 1;
7225796c8dcSSimon Schubert 	}
7235796c8dcSSimon Schubert       else
7245796c8dcSSimon Schubert 	*p++ = digs[len];
7255796c8dcSSimon Schubert     }
7265796c8dcSSimon Schubert 
7275796c8dcSSimon Schubert   while (len--)
7285796c8dcSSimon Schubert     *p++ = *sym++;
7295796c8dcSSimon Schubert 
7305796c8dcSSimon Schubert   *dst = p;
7315796c8dcSSimon Schubert }
7325796c8dcSSimon Schubert 
7335796c8dcSSimon Schubert static void
out(bfd * abfd,int type,char * start,char * end)7345796c8dcSSimon Schubert out (bfd *abfd, int type, char *start, char *end)
7355796c8dcSSimon Schubert {
7365796c8dcSSimon Schubert   int sum = 0;
7375796c8dcSSimon Schubert   char *s;
7385796c8dcSSimon Schubert   char front[6];
7395796c8dcSSimon Schubert   bfd_size_type wrlen;
7405796c8dcSSimon Schubert 
7415796c8dcSSimon Schubert   front[0] = '%';
7425796c8dcSSimon Schubert   TOHEX (front + 1, end - start + 5);
7435796c8dcSSimon Schubert   front[3] = type;
7445796c8dcSSimon Schubert 
7455796c8dcSSimon Schubert   for (s = start; s < end; s++)
7465796c8dcSSimon Schubert     sum += sum_block[(unsigned char) *s];
7475796c8dcSSimon Schubert 
7485796c8dcSSimon Schubert   sum += sum_block[(unsigned char) front[1]];	/* Length.  */
7495796c8dcSSimon Schubert   sum += sum_block[(unsigned char) front[2]];
7505796c8dcSSimon Schubert   sum += sum_block[(unsigned char) front[3]];	/* Type.  */
7515796c8dcSSimon Schubert   TOHEX (front + 4, sum);
7525796c8dcSSimon Schubert   if (bfd_bwrite (front, (bfd_size_type) 6, abfd) != 6)
7535796c8dcSSimon Schubert     abort ();
7545796c8dcSSimon Schubert   end[0] = '\n';
7555796c8dcSSimon Schubert   wrlen = end - start + 1;
7565796c8dcSSimon Schubert   if (bfd_bwrite (start, wrlen, abfd) != wrlen)
7575796c8dcSSimon Schubert     abort ();
7585796c8dcSSimon Schubert }
7595796c8dcSSimon Schubert 
7605796c8dcSSimon Schubert static bfd_boolean
tekhex_write_object_contents(bfd * abfd)7615796c8dcSSimon Schubert tekhex_write_object_contents (bfd *abfd)
7625796c8dcSSimon Schubert {
7635796c8dcSSimon Schubert   char buffer[100];
7645796c8dcSSimon Schubert   asymbol **p;
7655796c8dcSSimon Schubert   asection *s;
7665796c8dcSSimon Schubert   struct data_struct *d;
7675796c8dcSSimon Schubert 
7685796c8dcSSimon Schubert   tekhex_init ();
7695796c8dcSSimon Schubert 
7705796c8dcSSimon Schubert   /* And the raw data.  */
7715796c8dcSSimon Schubert   for (d = abfd->tdata.tekhex_data->data;
7725796c8dcSSimon Schubert        d != NULL;
7735796c8dcSSimon Schubert        d = d->next)
7745796c8dcSSimon Schubert     {
7755796c8dcSSimon Schubert       int low;
7765796c8dcSSimon Schubert 
7775796c8dcSSimon Schubert       const int span = 32;
7785796c8dcSSimon Schubert       int addr;
7795796c8dcSSimon Schubert 
7805796c8dcSSimon Schubert       /* Write it in blocks of 32 bytes.  */
7815796c8dcSSimon Schubert       for (addr = 0; addr < CHUNK_MASK + 1; addr += span)
7825796c8dcSSimon Schubert 	{
7835796c8dcSSimon Schubert 	  int need = 0;
7845796c8dcSSimon Schubert 
7855796c8dcSSimon Schubert 	  /* Check to see if necessary.  */
7865796c8dcSSimon Schubert 	  for (low = 0; !need && low < span; low++)
7875796c8dcSSimon Schubert 	    if (d->chunk_init[addr + low])
7885796c8dcSSimon Schubert 	      need = 1;
7895796c8dcSSimon Schubert 
7905796c8dcSSimon Schubert 	  if (need)
7915796c8dcSSimon Schubert 	    {
7925796c8dcSSimon Schubert 	      char *dst = buffer;
7935796c8dcSSimon Schubert 
7945796c8dcSSimon Schubert 	      writevalue (&dst, addr + d->vma);
7955796c8dcSSimon Schubert 	      for (low = 0; low < span; low++)
7965796c8dcSSimon Schubert 		{
7975796c8dcSSimon Schubert 		  TOHEX (dst, d->chunk_data[addr + low]);
7985796c8dcSSimon Schubert 		  dst += 2;
7995796c8dcSSimon Schubert 		}
8005796c8dcSSimon Schubert 	      out (abfd, '6', buffer, dst);
8015796c8dcSSimon Schubert 	    }
8025796c8dcSSimon Schubert 	}
8035796c8dcSSimon Schubert     }
8045796c8dcSSimon Schubert 
8055796c8dcSSimon Schubert   /* Write all the section headers for the sections.  */
8065796c8dcSSimon Schubert   for (s = abfd->sections; s != NULL; s = s->next)
8075796c8dcSSimon Schubert     {
8085796c8dcSSimon Schubert       char *dst = buffer;
8095796c8dcSSimon Schubert 
8105796c8dcSSimon Schubert       writesym (&dst, s->name);
8115796c8dcSSimon Schubert       *dst++ = '1';
8125796c8dcSSimon Schubert       writevalue (&dst, s->vma);
8135796c8dcSSimon Schubert       writevalue (&dst, s->vma + s->size);
8145796c8dcSSimon Schubert       out (abfd, '3', buffer, dst);
8155796c8dcSSimon Schubert     }
8165796c8dcSSimon Schubert 
8175796c8dcSSimon Schubert   /* And the symbols.  */
8185796c8dcSSimon Schubert   if (abfd->outsymbols)
8195796c8dcSSimon Schubert     {
8205796c8dcSSimon Schubert       for (p = abfd->outsymbols; *p; p++)
8215796c8dcSSimon Schubert 	{
8225796c8dcSSimon Schubert 	  int section_code = bfd_decode_symclass (*p);
8235796c8dcSSimon Schubert 
8245796c8dcSSimon Schubert 	  if (section_code != '?')
8255796c8dcSSimon Schubert 	    {
8265796c8dcSSimon Schubert 	      /* Do not include debug symbols.  */
8275796c8dcSSimon Schubert 	      asymbol *sym = *p;
8285796c8dcSSimon Schubert 	      char *dst = buffer;
8295796c8dcSSimon Schubert 
8305796c8dcSSimon Schubert 	      writesym (&dst, sym->section->name);
8315796c8dcSSimon Schubert 
8325796c8dcSSimon Schubert 	      switch (section_code)
8335796c8dcSSimon Schubert 		{
8345796c8dcSSimon Schubert 		case 'A':
8355796c8dcSSimon Schubert 		  *dst++ = '2';
8365796c8dcSSimon Schubert 		  break;
8375796c8dcSSimon Schubert 		case 'a':
8385796c8dcSSimon Schubert 		  *dst++ = '6';
8395796c8dcSSimon Schubert 		  break;
8405796c8dcSSimon Schubert 		case 'D':
8415796c8dcSSimon Schubert 		case 'B':
8425796c8dcSSimon Schubert 		case 'O':
8435796c8dcSSimon Schubert 		  *dst++ = '4';
8445796c8dcSSimon Schubert 		  break;
8455796c8dcSSimon Schubert 		case 'd':
8465796c8dcSSimon Schubert 		case 'b':
8475796c8dcSSimon Schubert 		case 'o':
8485796c8dcSSimon Schubert 		  *dst++ = '8';
8495796c8dcSSimon Schubert 		  break;
8505796c8dcSSimon Schubert 		case 'T':
8515796c8dcSSimon Schubert 		  *dst++ = '3';
8525796c8dcSSimon Schubert 		  break;
8535796c8dcSSimon Schubert 		case 't':
8545796c8dcSSimon Schubert 		  *dst++ = '7';
8555796c8dcSSimon Schubert 		  break;
8565796c8dcSSimon Schubert 		case 'C':
8575796c8dcSSimon Schubert 		case 'U':
8585796c8dcSSimon Schubert 		  bfd_set_error (bfd_error_wrong_format);
8595796c8dcSSimon Schubert 		  return FALSE;
8605796c8dcSSimon Schubert 		}
8615796c8dcSSimon Schubert 
8625796c8dcSSimon Schubert 	      writesym (&dst, sym->name);
8635796c8dcSSimon Schubert 	      writevalue (&dst, sym->value + sym->section->vma);
8645796c8dcSSimon Schubert 	      out (abfd, '3', buffer, dst);
8655796c8dcSSimon Schubert 	    }
8665796c8dcSSimon Schubert 	}
8675796c8dcSSimon Schubert     }
8685796c8dcSSimon Schubert 
8695796c8dcSSimon Schubert   /* And the terminator.  */
8705796c8dcSSimon Schubert   if (bfd_bwrite ("%0781010\n", (bfd_size_type) 9, abfd) != 9)
8715796c8dcSSimon Schubert     abort ();
8725796c8dcSSimon Schubert   return TRUE;
8735796c8dcSSimon Schubert }
8745796c8dcSSimon Schubert 
8755796c8dcSSimon Schubert static int
tekhex_sizeof_headers(bfd * abfd ATTRIBUTE_UNUSED,struct bfd_link_info * info ATTRIBUTE_UNUSED)8765796c8dcSSimon Schubert tekhex_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
8775796c8dcSSimon Schubert 		       struct bfd_link_info *info ATTRIBUTE_UNUSED)
8785796c8dcSSimon Schubert {
8795796c8dcSSimon Schubert   return 0;
8805796c8dcSSimon Schubert }
8815796c8dcSSimon Schubert 
8825796c8dcSSimon Schubert static asymbol *
tekhex_make_empty_symbol(bfd * abfd)8835796c8dcSSimon Schubert tekhex_make_empty_symbol (bfd *abfd)
8845796c8dcSSimon Schubert {
8855796c8dcSSimon Schubert   bfd_size_type amt = sizeof (struct tekhex_symbol_struct);
8865796c8dcSSimon Schubert   tekhex_symbol_type *new_symbol = (tekhex_symbol_type *) bfd_zalloc (abfd,
8875796c8dcSSimon Schubert                                                                       amt);
8885796c8dcSSimon Schubert 
8895796c8dcSSimon Schubert   if (!new_symbol)
8905796c8dcSSimon Schubert     return NULL;
8915796c8dcSSimon Schubert   new_symbol->symbol.the_bfd = abfd;
8925796c8dcSSimon Schubert   new_symbol->prev =  NULL;
8935796c8dcSSimon Schubert   return &(new_symbol->symbol);
8945796c8dcSSimon Schubert }
8955796c8dcSSimon Schubert 
8965796c8dcSSimon Schubert static void
tekhex_get_symbol_info(bfd * abfd ATTRIBUTE_UNUSED,asymbol * symbol,symbol_info * ret)8975796c8dcSSimon Schubert tekhex_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
8985796c8dcSSimon Schubert 			asymbol *symbol,
8995796c8dcSSimon Schubert 			symbol_info *ret)
9005796c8dcSSimon Schubert {
9015796c8dcSSimon Schubert   bfd_symbol_info (symbol, ret);
9025796c8dcSSimon Schubert }
9035796c8dcSSimon Schubert 
9045796c8dcSSimon Schubert static void
tekhex_print_symbol(bfd * abfd,void * filep,asymbol * symbol,bfd_print_symbol_type how)9055796c8dcSSimon Schubert tekhex_print_symbol (bfd *abfd,
9065796c8dcSSimon Schubert 		     void * filep,
9075796c8dcSSimon Schubert 		     asymbol *symbol,
9085796c8dcSSimon Schubert 		     bfd_print_symbol_type how)
9095796c8dcSSimon Schubert {
9105796c8dcSSimon Schubert   FILE *file = (FILE *) filep;
9115796c8dcSSimon Schubert 
9125796c8dcSSimon Schubert   switch (how)
9135796c8dcSSimon Schubert     {
9145796c8dcSSimon Schubert     case bfd_print_symbol_name:
9155796c8dcSSimon Schubert       fprintf (file, "%s", symbol->name);
9165796c8dcSSimon Schubert       break;
9175796c8dcSSimon Schubert     case bfd_print_symbol_more:
9185796c8dcSSimon Schubert       break;
9195796c8dcSSimon Schubert 
9205796c8dcSSimon Schubert     case bfd_print_symbol_all:
9215796c8dcSSimon Schubert       {
9225796c8dcSSimon Schubert 	const char *section_name = symbol->section->name;
9235796c8dcSSimon Schubert 
9245796c8dcSSimon Schubert 	bfd_print_symbol_vandf (abfd, (void *) file, symbol);
9255796c8dcSSimon Schubert 
9265796c8dcSSimon Schubert 	fprintf (file, " %-5s %s",
9275796c8dcSSimon Schubert 		 section_name, symbol->name);
9285796c8dcSSimon Schubert       }
9295796c8dcSSimon Schubert     }
9305796c8dcSSimon Schubert }
9315796c8dcSSimon Schubert 
9325796c8dcSSimon Schubert #define	tekhex_close_and_cleanup                    _bfd_generic_close_and_cleanup
9335796c8dcSSimon Schubert #define tekhex_bfd_free_cached_info                 _bfd_generic_bfd_free_cached_info
9345796c8dcSSimon Schubert #define tekhex_new_section_hook                     _bfd_generic_new_section_hook
9355796c8dcSSimon Schubert #define tekhex_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
9365796c8dcSSimon Schubert #define tekhex_bfd_is_local_label_name               bfd_generic_is_local_label_name
9375796c8dcSSimon Schubert #define tekhex_get_lineno                           _bfd_nosymbols_get_lineno
9385796c8dcSSimon Schubert #define tekhex_find_nearest_line                    _bfd_nosymbols_find_nearest_line
9395796c8dcSSimon Schubert #define tekhex_find_inliner_info                    _bfd_nosymbols_find_inliner_info
9405796c8dcSSimon Schubert #define tekhex_bfd_make_debug_symbol                _bfd_nosymbols_bfd_make_debug_symbol
9415796c8dcSSimon Schubert #define tekhex_read_minisymbols                     _bfd_generic_read_minisymbols
9425796c8dcSSimon Schubert #define tekhex_minisymbol_to_symbol                 _bfd_generic_minisymbol_to_symbol
9435796c8dcSSimon Schubert #define tekhex_bfd_get_relocated_section_contents   bfd_generic_get_relocated_section_contents
9445796c8dcSSimon Schubert #define tekhex_bfd_relax_section                    bfd_generic_relax_section
9455796c8dcSSimon Schubert #define tekhex_bfd_gc_sections                      bfd_generic_gc_sections
946*a45ae5f8SJohn Marino #define tekhex_bfd_lookup_section_flags		    bfd_generic_lookup_section_flags
9475796c8dcSSimon Schubert #define tekhex_bfd_merge_sections                   bfd_generic_merge_sections
9485796c8dcSSimon Schubert #define tekhex_bfd_is_group_section                 bfd_generic_is_group_section
9495796c8dcSSimon Schubert #define tekhex_bfd_discard_group                    bfd_generic_discard_group
9505796c8dcSSimon Schubert #define tekhex_section_already_linked               _bfd_generic_section_already_linked
9515796c8dcSSimon Schubert #define tekhex_bfd_define_common_symbol             bfd_generic_define_common_symbol
9525796c8dcSSimon Schubert #define tekhex_bfd_link_hash_table_create           _bfd_generic_link_hash_table_create
9535796c8dcSSimon Schubert #define tekhex_bfd_link_hash_table_free             _bfd_generic_link_hash_table_free
9545796c8dcSSimon Schubert #define tekhex_bfd_link_add_symbols                 _bfd_generic_link_add_symbols
9555796c8dcSSimon Schubert #define tekhex_bfd_link_just_syms                   _bfd_generic_link_just_syms
956cf7f2e2dSJohn Marino #define tekhex_bfd_copy_link_hash_symbol_type \
957cf7f2e2dSJohn Marino   _bfd_generic_copy_link_hash_symbol_type
9585796c8dcSSimon Schubert #define tekhex_bfd_final_link                       _bfd_generic_final_link
9595796c8dcSSimon Schubert #define tekhex_bfd_link_split_section               _bfd_generic_link_split_section
9605796c8dcSSimon Schubert #define tekhex_get_section_contents_in_window       _bfd_generic_get_section_contents_in_window
9615796c8dcSSimon Schubert 
9625796c8dcSSimon Schubert const bfd_target tekhex_vec =
9635796c8dcSSimon Schubert {
9645796c8dcSSimon Schubert   "tekhex",			/* Name.  */
9655796c8dcSSimon Schubert   bfd_target_tekhex_flavour,
9665796c8dcSSimon Schubert   BFD_ENDIAN_UNKNOWN,		/* Target byte order.  */
9675796c8dcSSimon Schubert   BFD_ENDIAN_UNKNOWN,		/* Target headers byte order.  */
9685796c8dcSSimon Schubert   (EXEC_P |			/* Object flags.  */
9695796c8dcSSimon Schubert    HAS_SYMS | HAS_LINENO | HAS_DEBUG |
9705796c8dcSSimon Schubert    HAS_RELOC | HAS_LOCALS | WP_TEXT | D_PAGED),
9715796c8dcSSimon Schubert   (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
9725796c8dcSSimon Schubert    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),	/* Section flags.  */
9735796c8dcSSimon Schubert   0,				/* Leading underscore.  */
9745796c8dcSSimon Schubert   ' ',				/* AR_pad_char.  */
9755796c8dcSSimon Schubert   16,				/* AR_max_namelen.  */
976*a45ae5f8SJohn Marino   0,				/* match priority.  */
9775796c8dcSSimon Schubert   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
9785796c8dcSSimon Schubert   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
9795796c8dcSSimon Schubert   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Data.  */
9805796c8dcSSimon Schubert   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
9815796c8dcSSimon Schubert   bfd_getb32, bfd_getb_signed_32, bfd_putb32,
9825796c8dcSSimon Schubert   bfd_getb16, bfd_getb_signed_16, bfd_putb16,	/* Headers.  */
9835796c8dcSSimon Schubert 
9845796c8dcSSimon Schubert   {
9855796c8dcSSimon Schubert     _bfd_dummy_target,
9865796c8dcSSimon Schubert     tekhex_object_p,		/* bfd_check_format.  */
9875796c8dcSSimon Schubert     _bfd_dummy_target,
9885796c8dcSSimon Schubert     _bfd_dummy_target,
9895796c8dcSSimon Schubert   },
9905796c8dcSSimon Schubert   {
9915796c8dcSSimon Schubert     bfd_false,
9925796c8dcSSimon Schubert     tekhex_mkobject,
9935796c8dcSSimon Schubert     _bfd_generic_mkarchive,
9945796c8dcSSimon Schubert     bfd_false,
9955796c8dcSSimon Schubert   },
9965796c8dcSSimon Schubert   {				/* bfd_write_contents.  */
9975796c8dcSSimon Schubert     bfd_false,
9985796c8dcSSimon Schubert     tekhex_write_object_contents,
9995796c8dcSSimon Schubert     _bfd_write_archive_contents,
10005796c8dcSSimon Schubert     bfd_false,
10015796c8dcSSimon Schubert   },
10025796c8dcSSimon Schubert 
10035796c8dcSSimon Schubert   BFD_JUMP_TABLE_GENERIC (tekhex),
10045796c8dcSSimon Schubert   BFD_JUMP_TABLE_COPY (_bfd_generic),
10055796c8dcSSimon Schubert   BFD_JUMP_TABLE_CORE (_bfd_nocore),
10065796c8dcSSimon Schubert   BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
10075796c8dcSSimon Schubert   BFD_JUMP_TABLE_SYMBOLS (tekhex),
10085796c8dcSSimon Schubert   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
10095796c8dcSSimon Schubert   BFD_JUMP_TABLE_WRITE (tekhex),
10105796c8dcSSimon Schubert   BFD_JUMP_TABLE_LINK (tekhex),
10115796c8dcSSimon Schubert   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
10125796c8dcSSimon Schubert 
10135796c8dcSSimon Schubert   NULL,
10145796c8dcSSimon Schubert 
10155796c8dcSSimon Schubert   NULL
10165796c8dcSSimon Schubert };
1017