* coffgen.c (coff_find_nearest_line): Correct cached line index.
[deliverable/binutils-gdb.git] / bfd / coff-stgo32.c
CommitLineData
a4f68544 1/* BFD back-end for Intel 386 COFF files (DJGPP variant with a stub).
cd123cb7
NC
2 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2006, 2007
3 Free Software Foundation, Inc.
252b5132
RH
4 Written by Robert Hoehne.
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
cd123cb7 10 the Free Software Foundation; either version 3 of the License, or
252b5132
RH
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
cd123cb7
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
252b5132
RH
22
23/* This file handles now also stubbed coff images. The stub is a small
24 DOS executable program before the coff image to load it in memory
25 and execute it. This is needed, because DOS cannot run coff files.
26
27 All the functions below are called by the corresponding functions
28 from coffswap.h.
29 The only thing what they do is to adjust the information stored in
30 the COFF file which are offset into the file.
31 This is needed, because DJGPP uses a very special way to load and run
32 the coff image. It loads the image in memory and assumes then, that the
33 image had no stub by using the filepointers as pointers in the coff
34 image and NOT in the file.
35
36 To be compatible with any existing executables I have fixed this
246178f2 37 here and NOT in the DJGPP startup code. */
252b5132
RH
38
39#define TARGET_SYM go32stubbedcoff_vec
40#define TARGET_NAME "coff-go32-exe"
41#define TARGET_UNDERSCORE '_'
42#define COFF_GO32_EXE
242eabea
ILT
43#define COFF_LONG_SECTION_NAMES
44#define COFF_SUPPORT_GNU_LINKONCE
a4f68544 45#define COFF_LONG_FILENAMES
252b5132 46
5dccc1dd
ILT
47#define COFF_SECTION_ALIGNMENT_ENTRIES \
48{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \
49 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
50{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \
a7bda527
DD
51 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
52{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
26cd54bf 53 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
4f6fbb1a 54{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi"), \
a7bda527 55 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
5dccc1dd 56
252b5132
RH
57#include "bfd.h"
58
246178f2 59/* At first the prototypes. */
252b5132
RH
60
61static void
246178f2 62adjust_filehdr_in_post PARAMS ((bfd *, PTR, PTR));
252b5132 63static void
246178f2 64adjust_filehdr_out_pre PARAMS ((bfd *, PTR, PTR));
252b5132 65static void
246178f2 66adjust_filehdr_out_post PARAMS ((bfd *, PTR, PTR));
252b5132 67static void
246178f2 68adjust_scnhdr_in_post PARAMS ((bfd *, PTR, PTR));
252b5132 69static void
246178f2 70adjust_scnhdr_out_pre PARAMS ((bfd *, PTR, PTR));
252b5132 71static void
246178f2 72adjust_scnhdr_out_post PARAMS ((bfd *, PTR, PTR));
252b5132 73static void
246178f2 74adjust_aux_in_post PARAMS ((bfd *, PTR, int, int, int, int, PTR));
252b5132 75static void
246178f2 76adjust_aux_out_pre PARAMS ((bfd *, PTR, int, int, int, int, PTR));
252b5132 77static void
246178f2 78adjust_aux_out_post PARAMS ((bfd *, PTR, int, int, int, int, PTR));
252b5132 79static void
246178f2 80create_go32_stub PARAMS ((bfd *));
252b5132 81
246178f2 82/* All that ..._PRE and ...POST functions are called from the corresponding
252b5132 83 coff_swap... functions. The ...PRE functions are called at the beginning
246178f2 84 of the function and the ...POST functions at the end of the swap routines. */
252b5132
RH
85
86#define COFF_ADJUST_FILEHDR_IN_POST adjust_filehdr_in_post
87#define COFF_ADJUST_FILEHDR_OUT_PRE adjust_filehdr_out_pre
88#define COFF_ADJUST_FILEHDR_OUT_POST adjust_filehdr_out_post
89
90#define COFF_ADJUST_SCNHDR_IN_POST adjust_scnhdr_in_post
91#define COFF_ADJUST_SCNHDR_OUT_PRE adjust_scnhdr_out_pre
92#define COFF_ADJUST_SCNHDR_OUT_POST adjust_scnhdr_out_post
93
94#define COFF_ADJUST_AUX_IN_POST adjust_aux_in_post
95#define COFF_ADJUST_AUX_OUT_PRE adjust_aux_out_pre
96#define COFF_ADJUST_AUX_OUT_POST adjust_aux_out_post
97
b34976b6 98static bfd_boolean
246178f2 99 go32_stubbed_coff_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *));
252b5132
RH
100
101#define coff_bfd_copy_private_bfd_data go32_stubbed_coff_bfd_copy_private_bfd_data
102
103#include "coff-i386.c"
104
246178f2 105/* I hold in the usrdata the stub. */
252b5132
RH
106#define bfd_coff_go32stub bfd_usrdata
107
108/* This macro is used, because I cannot assume the endianess of the
246178f2 109 host system. */
dc810e39 110#define _H(index) (H_GET_16 (abfd, (header+index*2)))
252b5132 111
252b5132 112/* These bytes are a 2048-byte DOS executable, which loads the COFF
246178f2 113 image into memory and then runs it. It is called 'stub'. */
252b5132 114
246178f2 115static const unsigned char stub_bytes[STUBSIZE] =
252b5132
RH
116{
117#include "go32stub.h"
118};
119
120/*
121 I have not commented each swap function below, because the
122 technique is in any function the same. For the ...in function,
123 all the pointers are adjusted by adding STUBSIZE and for the
124 ...out function, it is subtracted first and after calling the
246178f2 125 standard swap function it is reset to the old value. */
252b5132
RH
126
127/* This macro is used for adjusting the filepointers, which
246178f2 128 is done only, if the pointer is nonzero. */
252b5132
RH
129
130#define ADJUST_VAL(val,diff) \
131 if (val != 0) val += diff
132
133static void
134adjust_filehdr_in_post (abfd, src, dst)
135 bfd *abfd;
136 PTR src;
137 PTR dst;
138{
139 FILHDR *filehdr_src = (FILHDR *) src;
140 struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst;
141
142 ADJUST_VAL (filehdr_dst->f_symptr, STUBSIZE);
143
246178f2 144 /* Save now the stub to be used later. */
dc810e39 145 bfd_coff_go32stub (abfd) = (PTR) bfd_alloc (abfd, (bfd_size_type) STUBSIZE);
252b5132
RH
146
147 /* Since this function returns no status, I do not set here
148 any bfd_error_...
149 That means, before the use of bfd_coff_go32stub (), this value
246178f2 150 should be checked if it is != NULL. */
252b5132
RH
151 if (bfd_coff_go32stub (abfd) == NULL)
152 return;
153 memcpy (bfd_coff_go32stub (abfd), filehdr_src->stub, STUBSIZE);
154}
155
156static void
157adjust_filehdr_out_pre (abfd, in, out)
158 bfd *abfd;
159 PTR in;
160 PTR out;
161{
162 struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in;
163 FILHDR *filehdr_out = (FILHDR *) out;
164
246178f2 165 /* Generate the stub. */
252b5132
RH
166 create_go32_stub (abfd);
167
246178f2 168 /* Copy the stub to the file header. */
252b5132
RH
169 if (bfd_coff_go32stub (abfd) != NULL)
170 memcpy (filehdr_out->stub, bfd_coff_go32stub (abfd), STUBSIZE);
171 else
246178f2 172 /* Use the default. */
252b5132
RH
173 memcpy (filehdr_out->stub, stub_bytes, STUBSIZE);
174
175 ADJUST_VAL (filehdr_in->f_symptr, -STUBSIZE);
176}
177
178static void
179adjust_filehdr_out_post (abfd, in, out)
5f771d47 180 bfd *abfd ATTRIBUTE_UNUSED;
252b5132 181 PTR in;
5f771d47 182 PTR out ATTRIBUTE_UNUSED;
252b5132
RH
183{
184 struct internal_filehdr *filehdr_in = (struct internal_filehdr *) in;
246178f2 185 /* Undo the above change. */
252b5132
RH
186 ADJUST_VAL (filehdr_in->f_symptr, STUBSIZE);
187}
188
189static void
190adjust_scnhdr_in_post (abfd, ext, in)
5f771d47
ILT
191 bfd *abfd ATTRIBUTE_UNUSED;
192 PTR ext ATTRIBUTE_UNUSED;
252b5132
RH
193 PTR in;
194{
195 struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
196
197 ADJUST_VAL (scnhdr_int->s_scnptr, STUBSIZE);
198 ADJUST_VAL (scnhdr_int->s_relptr, STUBSIZE);
199 ADJUST_VAL (scnhdr_int->s_lnnoptr, STUBSIZE);
200}
201
202static void
203adjust_scnhdr_out_pre (abfd, in, out)
5f771d47 204 bfd *abfd ATTRIBUTE_UNUSED;
252b5132 205 PTR in;
5f771d47 206 PTR out ATTRIBUTE_UNUSED;
252b5132
RH
207{
208 struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
209
210 ADJUST_VAL (scnhdr_int->s_scnptr, -STUBSIZE);
211 ADJUST_VAL (scnhdr_int->s_relptr, -STUBSIZE);
212 ADJUST_VAL (scnhdr_int->s_lnnoptr, -STUBSIZE);
213}
214
215static void
216adjust_scnhdr_out_post (abfd, in, out)
5f771d47 217 bfd *abfd ATTRIBUTE_UNUSED;
252b5132 218 PTR in;
5f771d47 219 PTR out ATTRIBUTE_UNUSED;
252b5132
RH
220{
221 struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
222
223 ADJUST_VAL (scnhdr_int->s_scnptr, STUBSIZE);
224 ADJUST_VAL (scnhdr_int->s_relptr, STUBSIZE);
225 ADJUST_VAL (scnhdr_int->s_lnnoptr, STUBSIZE);
226}
227
228static void
229adjust_aux_in_post (abfd, ext1, type, class, indx, numaux, in1)
5f771d47
ILT
230 bfd *abfd ATTRIBUTE_UNUSED;
231 PTR ext1 ATTRIBUTE_UNUSED;
252b5132
RH
232 int type;
233 int class;
5f771d47
ILT
234 int indx ATTRIBUTE_UNUSED;
235 int numaux ATTRIBUTE_UNUSED;
252b5132
RH
236 PTR in1;
237{
238 union internal_auxent *in = (union internal_auxent *) in1;
239
240 if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
241 {
242 ADJUST_VAL (in->x_sym.x_fcnary.x_fcn.x_lnnoptr, STUBSIZE);
243 }
244}
245
246static void
247adjust_aux_out_pre (abfd, inp, type, class, indx, numaux, extp)
5f771d47 248 bfd *abfd ATTRIBUTE_UNUSED;
252b5132
RH
249 PTR inp;
250 int type;
251 int class;
5f771d47
ILT
252 int indx ATTRIBUTE_UNUSED;
253 int numaux ATTRIBUTE_UNUSED;
254 PTR extp ATTRIBUTE_UNUSED;
252b5132
RH
255{
256 union internal_auxent *in = (union internal_auxent *) inp;
257
258 if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
259 {
260 ADJUST_VAL (in->x_sym.x_fcnary.x_fcn.x_lnnoptr, -STUBSIZE);
261 }
262}
263
264static void
265adjust_aux_out_post (abfd, inp, type, class, indx, numaux, extp)
5f771d47 266 bfd *abfd ATTRIBUTE_UNUSED;
252b5132
RH
267 PTR inp;
268 int type;
269 int class;
5f771d47
ILT
270 int indx ATTRIBUTE_UNUSED;
271 int numaux ATTRIBUTE_UNUSED;
272 PTR extp ATTRIBUTE_UNUSED;
252b5132
RH
273{
274 union internal_auxent *in = (union internal_auxent *) inp;
275
276 if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
277 {
278 ADJUST_VAL (in->x_sym.x_fcnary.x_fcn.x_lnnoptr, STUBSIZE);
279 }
280}
281
246178f2 282/* That's the function, which creates the stub. There are
252b5132
RH
283 different cases from where the stub is taken.
284 At first the environment variable $(GO32STUB) is checked and then
285 $(STUB) if it was not set.
286 If it exists and points to a valid stub the stub is taken from
287 that file. This file can be also a whole executable file, because
288 the stub is computed from the exe information at the start of that
289 file.
290
291 If there was any error, the standard stub (compiled in this file)
246178f2 292 is taken. */
252b5132
RH
293
294static void
295create_go32_stub (abfd)
296 bfd *abfd;
297{
246178f2 298 /* Do it only once. */
252b5132
RH
299 if (bfd_coff_go32stub (abfd) == NULL)
300 {
301 char *stub;
302 struct stat st;
303 int f;
304 unsigned char header[10];
305 char magic[8];
dc810e39
AM
306 unsigned long coff_start;
307 long exe_start;
252b5132 308
246178f2 309 /* Check at first the environment variable $(GO32STUB). */
252b5132 310 stub = getenv ("GO32STUB");
246178f2 311 /* Now check the environment variable $(STUB). */
252b5132
RH
312 if (stub == NULL)
313 stub = getenv ("STUB");
314 if (stub == NULL)
315 goto stub_end;
316 if (stat (stub, &st) != 0)
317 goto stub_end;
318#ifdef O_BINARY
319 f = open (stub, O_RDONLY | O_BINARY);
320#else
321 f = open (stub, O_RDONLY);
322#endif
323 if (f < 0)
324 goto stub_end;
325 if (read (f, &header, sizeof (header)) < 0)
326 {
327 close (f);
328 goto stub_end;
329 }
246178f2 330 if (_H (0) != 0x5a4d) /* It is not an exe file. */
252b5132
RH
331 {
332 close (f);
333 goto stub_end;
334 }
335 /* Compute the size of the stub (it is every thing up
246178f2 336 to the beginning of the coff image). */
252b5132
RH
337 coff_start = (long) _H (2) * 512L;
338 if (_H (1))
339 coff_start += (long) _H (1) - 512L;
340
341 /* Currently there is only a fixed stub size of 2048 bytes
246178f2 342 supported. */
252b5132
RH
343 if (coff_start != 2048)
344 {
345 close (f);
346 goto stub_end;
347 }
348 exe_start = _H (4) * 16;
dc810e39 349 if ((long) lseek (f, exe_start, SEEK_SET) != exe_start)
252b5132
RH
350 {
351 close (f);
352 goto stub_end;
353 }
354 if (read (f, &magic, 8) != 8)
355 {
356 close (f);
357 goto stub_end;
358 }
0112cd26 359 if (! CONST_STRNEQ (magic, "go32stub"))
252b5132
RH
360 {
361 close (f);
362 goto stub_end;
363 }
246178f2 364 /* Now we found a correct stub (hopefully). */
dc810e39
AM
365 bfd_coff_go32stub (abfd)
366 = (PTR) bfd_alloc (abfd, (bfd_size_type) coff_start);
252b5132
RH
367 if (bfd_coff_go32stub (abfd) == NULL)
368 {
369 close (f);
370 return;
371 }
372 lseek (f, 0L, SEEK_SET);
373 if ((unsigned long) read (f, bfd_coff_go32stub (abfd), coff_start)
374 != coff_start)
375 {
376 bfd_release (abfd, bfd_coff_go32stub (abfd));
377 bfd_coff_go32stub (abfd) = NULL;
378 }
379 close (f);
380 }
381stub_end:
382 /* There was something wrong above, so use now the standard builtin
246178f2 383 stub. */
252b5132
RH
384 if (bfd_coff_go32stub (abfd) == NULL)
385 {
dc810e39
AM
386 bfd_coff_go32stub (abfd)
387 = (PTR) bfd_alloc (abfd, (bfd_size_type) STUBSIZE);
252b5132 388 if (bfd_coff_go32stub (abfd) == NULL)
246178f2 389 return;
252b5132
RH
390 memcpy (bfd_coff_go32stub (abfd), stub_bytes, STUBSIZE);
391 }
392}
393
394/* If ibfd was a stubbed coff image, copy the stub from that bfd
246178f2 395 to the new obfd. */
252b5132 396
b34976b6 397static bfd_boolean
252b5132
RH
398go32_stubbed_coff_bfd_copy_private_bfd_data (ibfd, obfd)
399 bfd *ibfd;
400 bfd *obfd;
401{
246178f2 402 /* Check if both are the same targets. */
252b5132 403 if (ibfd->xvec != obfd->xvec)
b34976b6 404 return TRUE;
252b5132 405
246178f2 406 /* Check if both have a valid stub. */
252b5132
RH
407 if (bfd_coff_go32stub (ibfd) == NULL
408 || bfd_coff_go32stub (obfd) == NULL)
b34976b6 409 return TRUE;
252b5132 410
246178f2 411 /* Now copy the stub. */
252b5132
RH
412 memcpy (bfd_coff_go32stub (obfd), bfd_coff_go32stub (ibfd), STUBSIZE);
413
b34976b6 414 return TRUE;
252b5132 415}
This page took 0.552763 seconds and 4 git commands to generate.