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