OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [bfd/] [coff-stgo32.c] - Blame information for rev 1776

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.