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