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