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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [bfd/] [nlm32-i386.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* Support for 32-bit i386 NLM (NetWare Loadable Module)
2
   Copyright 1993, 1994, 2000 Free Software Foundation, Inc.
3
 
4
This file is part of BFD, the Binary File Descriptor library.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
 
20
#include "bfd.h"
21
#include "sysdep.h"
22
#include "libbfd.h"
23
 
24
#define ARCH_SIZE 32
25
 
26
#include "nlm/i386-ext.h"
27
#define Nlm_External_Fixed_Header       Nlm32_i386_External_Fixed_Header
28
 
29
#include "libnlm.h"
30
 
31
static boolean nlm_i386_read_reloc
32
  PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
33
static boolean nlm_i386_write_import
34
  PARAMS ((bfd *, asection *, arelent *));
35
static boolean nlm_i386_mangle_relocs
36
  PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
37
static boolean nlm_i386_read_import
38
  PARAMS ((bfd *, nlmNAME(symbol_type) *));
39
static boolean nlm_i386_write_external
40
  PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
41
 
42
/* Adjust the reloc location by an absolute value.  */
43
 
44
static reloc_howto_type nlm_i386_abs_howto =
45
  HOWTO (0,                      /* type */
46
         0,                      /* rightshift */
47
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
48
         32,                    /* bitsize */
49
         false,                 /* pc_relative */
50
         0,                      /* bitpos */
51
         complain_overflow_bitfield, /* complain_on_overflow */
52
         0,                      /* special_function */
53
         "32",                  /* name */
54
         true,                  /* partial_inplace */
55
         0xffffffff,            /* src_mask */
56
         0xffffffff,            /* dst_mask */
57
         false);                /* pcrel_offset */
58
 
59
/* Adjust the reloc location by a PC relative displacement.  */
60
 
61
static reloc_howto_type nlm_i386_pcrel_howto =
62
  HOWTO (1,                     /* type */
63
         0,                      /* rightshift */
64
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
65
         32,                    /* bitsize */
66
         true,                  /* pc_relative */
67
         0,                      /* bitpos */
68
         complain_overflow_signed, /* complain_on_overflow */
69
         0,                      /* special_function */
70
         "DISP32",              /* name */
71
         true,                  /* partial_inplace */
72
         0xffffffff,            /* src_mask */
73
         0xffffffff,            /* dst_mask */
74
         true);                 /* pcrel_offset */
75
 
76
/* Read a NetWare i386 reloc.  */
77
 
78
static boolean
79
nlm_i386_read_reloc (abfd, sym, secp, rel)
80
     bfd *abfd;
81
     nlmNAME(symbol_type) *sym;
82
     asection **secp;
83
     arelent *rel;
84
{
85
  bfd_byte temp[4];
86
  bfd_vma val;
87
  const char *name;
88
 
89
  if (bfd_read (temp, sizeof (temp), 1, abfd) != sizeof (temp))
90
    return false;
91
 
92
  val = bfd_get_32 (abfd, temp);
93
 
94
  /* The value is an offset into either the code or data segment.
95
     This is the location which needs to be adjusted.
96
 
97
     If this is a relocation fixup rather than an imported symbol (the
98
     sym argument is NULL) then the high bit is 0 if the location
99
     needs to be adjusted by the address of the data segment, or 1 if
100
     the location needs to be adjusted by the address of the code
101
     segment.  If this is an imported symbol, then the high bit is 0
102
     if the location is 0 if the location should be adjusted by the
103
     offset to the symbol, or 1 if the location should adjusted by the
104
     absolute value of the symbol.
105
 
106
     The second most significant bit is 0 if the value is an offset
107
     into the data segment, or 1 if the value is an offset into the
108
     code segment.
109
 
110
     All this translates fairly easily into a BFD reloc.  */
111
 
112
  if (sym == NULL)
113
    {
114
      if ((val & NLM_HIBIT) == 0)
115
        name = NLM_INITIALIZED_DATA_NAME;
116
      else
117
        {
118
          name = NLM_CODE_NAME;
119
          val &=~ NLM_HIBIT;
120
        }
121
      rel->sym_ptr_ptr = bfd_get_section_by_name (abfd, name)->symbol_ptr_ptr;
122
      rel->howto = &nlm_i386_abs_howto;
123
    }
124
  else
125
    {
126
      /* In this case we do not need to set the sym_ptr_ptr field.  */
127
      rel->sym_ptr_ptr = NULL;
128
      if ((val & NLM_HIBIT) == 0)
129
        rel->howto = &nlm_i386_pcrel_howto;
130
      else
131
        {
132
          rel->howto = &nlm_i386_abs_howto;
133
          val &=~ NLM_HIBIT;
134
        }
135
    }
136
 
137
  if ((val & (NLM_HIBIT >> 1)) == 0)
138
    *secp = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
139
  else
140
    {
141
      *secp = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
142
      val &=~ (NLM_HIBIT >> 1);
143
    }
144
 
145
  rel->address = val;
146
  rel->addend = 0;
147
 
148
  return true;
149
}
150
 
151
/* Write a NetWare i386 reloc.  */
152
 
153
static boolean
154
nlm_i386_write_import (abfd, sec, rel)
155
     bfd *abfd;
156
     asection *sec;
157
     arelent *rel;
158
{
159
  asymbol *sym;
160
  bfd_vma val;
161
  bfd_byte temp[4];
162
 
163
  /* NetWare only supports two kinds of relocs.  We should check
164
     special_function here, as well, but at the moment coff-i386
165
     relocs uses a special_function which does not affect what we do
166
     here.  */
167
  if (rel->addend != 0
168
      || rel->howto == NULL
169
      || rel->howto->rightshift != 0
170
      || rel->howto->size != 2
171
      || rel->howto->bitsize != 32
172
      || rel->howto->bitpos != 0
173
      || rel->howto->src_mask != 0xffffffff
174
      || rel->howto->dst_mask != 0xffffffff)
175
    {
176
      bfd_set_error (bfd_error_invalid_operation);
177
      return false;
178
    }
179
 
180
  sym = *rel->sym_ptr_ptr;
181
 
182
  /* The value we write out is the offset into the appropriate
183
     segment.  This offset is the section vma, adjusted by the vma of
184
     the lowest section in that segment, plus the address of the
185
     relocation.  */
186
  val = bfd_get_section_vma (abfd, sec) + rel->address;
187
 
188
  /* The second most significant bit is 0 if the value is an offset
189
     into the data segment, or 1 if the value is an offset into the
190
     code segment.  */
191
  if (bfd_get_section_flags (abfd, sec) & SEC_CODE)
192
    {
193
      val -= nlm_get_text_low (abfd);
194
      val |= NLM_HIBIT >> 1;
195
    }
196
  else
197
    val -= nlm_get_data_low (abfd);
198
 
199
  if (! bfd_is_und_section (bfd_get_section (sym)))
200
    {
201
      /* NetWare only supports absolute internal relocs.  */
202
      if (rel->howto->pc_relative)
203
        {
204
          bfd_set_error (bfd_error_invalid_operation);
205
          return false;
206
        }
207
 
208
      /* The high bit is 1 if the reloc is against the code section, 0
209
         if against the data section.  */
210
      if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
211
        val |= NLM_HIBIT;
212
    }
213
  else
214
    {
215
      /* The high bit is 1 if this is an absolute reloc, 0 if it is PC
216
         relative.  */
217
      if (! rel->howto->pc_relative)
218
        val |= NLM_HIBIT;
219
      else
220
        {
221
          /* PC relative relocs on NetWare must be pcrel_offset.  */
222
          if (! rel->howto->pcrel_offset)
223
            {
224
              bfd_set_error (bfd_error_invalid_operation);
225
              return false;
226
            }
227
        }
228
    }
229
 
230
  bfd_put_32 (abfd, val, temp);
231
  if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
232
    return false;
233
 
234
  return true;
235
}
236
 
237
/* I want to be able to use objcopy to turn a i386 a.out or COFF file
238
   into a NetWare i386 module.  That means that the relocs from the
239
   source file have to be mapped into relocs that apply to the target
240
   file.  This function is called by nlm_set_section_contents to give
241
   it a chance to rework the relocs.
242
 
243
   This is actually a fairly general concept.  However, this is not a
244
   general implementation.  */
245
 
246
static boolean
247
nlm_i386_mangle_relocs (abfd, sec, data, offset, count)
248
     bfd *abfd;
249
     asection *sec;
250
     PTR data;
251
     bfd_vma offset;
252
     bfd_size_type count;
253
{
254
  arelent **rel_ptr_ptr, **rel_end;
255
 
256
  rel_ptr_ptr = sec->orelocation;
257
  rel_end = rel_ptr_ptr + sec->reloc_count;
258
  for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
259
    {
260
      arelent *rel;
261
      asymbol *sym;
262
      bfd_vma addend;
263
 
264
      rel = *rel_ptr_ptr;
265
      sym = *rel->sym_ptr_ptr;
266
 
267
      /* Note that no serious harm will ensue if we fail to change a
268
         reloc.  We will wind up failing in nlm_i386_write_import.  */
269
 
270
      /* Make sure this reloc is within the data we have.  We only 4
271
         byte relocs here, so we insist on having 4 bytes.  */
272
      if (rel->address < offset
273
          || rel->address + 4 > offset + count)
274
        continue;
275
 
276
      /* NetWare doesn't support reloc addends, so we get rid of them
277
         here by simply adding them into the object data.  We handle
278
         the symbol value, if any, the same way.  */
279
      addend = rel->addend + sym->value;
280
 
281
      /* The value of a symbol is the offset into the section.  If the
282
         symbol is in the .bss segment, we need to include the size of
283
         the data segment in the offset as well.  Fortunately, we know
284
         that at this point the size of the data section is in the NLM
285
         header.  */
286
      if (((bfd_get_section_flags (abfd, bfd_get_section (sym))
287
            & SEC_LOAD) == 0)
288
          && ((bfd_get_section_flags (abfd, bfd_get_section (sym))
289
               & SEC_ALLOC) != 0))
290
        addend += nlm_fixed_header (abfd)->dataImageSize;
291
 
292
      if (addend != 0
293
          && rel->howto != NULL
294
          && rel->howto->rightshift == 0
295
          && rel->howto->size == 2
296
          && rel->howto->bitsize == 32
297
          && rel->howto->bitpos == 0
298
          && rel->howto->src_mask == 0xffffffff
299
          && rel->howto->dst_mask == 0xffffffff)
300
        {
301
          bfd_vma val;
302
 
303
          val = bfd_get_32 (abfd, (bfd_byte *) data + rel->address - offset);
304
          val += addend;
305
          bfd_put_32 (abfd, val, (bfd_byte *) data + rel->address - offset);
306
          rel->addend = 0;
307
        }
308
 
309
      /* NetWare uses a reloc with pcrel_offset set.  We adjust
310
         pc_relative relocs accordingly.  We are going to change the
311
         howto field, so we can only do this if the current one is
312
         compatible.  We should check special_function here, but at
313
         the moment coff-i386 uses a special_function which does not
314
         affect what we are doing here.  */
315
      if (rel->howto != NULL
316
          && rel->howto->pc_relative
317
          && ! rel->howto->pcrel_offset
318
          && rel->howto->rightshift == 0
319
          && rel->howto->size == 2
320
          && rel->howto->bitsize == 32
321
          && rel->howto->bitpos == 0
322
          && rel->howto->src_mask == 0xffffffff
323
          && rel->howto->dst_mask == 0xffffffff)
324
        {
325
          bfd_vma val;
326
 
327
          /* When pcrel_offset is not set, it means that the negative
328
             of the address of the memory location is stored in the
329
             memory location.  We must add it back in.  */
330
          val = bfd_get_32 (abfd, (bfd_byte *) data + rel->address - offset);
331
          val += rel->address;
332
          bfd_put_32 (abfd, val, (bfd_byte *) data + rel->address - offset);
333
 
334
          rel->howto = &nlm_i386_pcrel_howto;
335
        }
336
    }
337
 
338
  return true;
339
}
340
 
341
/* Read a NetWare i386 import record */
342
static boolean
343
nlm_i386_read_import (abfd, sym)
344
     bfd *abfd;
345
     nlmNAME(symbol_type) *sym;
346
{
347
  struct nlm_relent *nlm_relocs;        /* relocation records for symbol */
348
  bfd_size_type rcount;                 /* number of relocs */
349
  bfd_byte temp[NLM_TARGET_LONG_SIZE];  /* temporary 32-bit value */
350
  unsigned char symlength;              /* length of symbol name */
351
  char *name;
352
 
353
  if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
354
      != sizeof (symlength))
355
    return false;
356
  sym -> symbol.the_bfd = abfd;
357
  name = bfd_alloc (abfd, symlength + 1);
358
  if (name == NULL)
359
    return false;
360
  if (bfd_read (name, symlength, 1, abfd) != symlength)
361
    return false;
362
  name[symlength] = '\0';
363
  sym -> symbol.name = name;
364
  sym -> symbol.flags = 0;
365
  sym -> symbol.value = 0;
366
  sym -> symbol.section = bfd_und_section_ptr;
367
  if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
368
    return false;
369
  rcount = bfd_h_get_32 (abfd, temp);
370
  nlm_relocs = ((struct nlm_relent *)
371
                bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
372
  if (!nlm_relocs)
373
    return false;
374
  sym -> relocs = nlm_relocs;
375
  sym -> rcnt = 0;
376
  while (sym -> rcnt < rcount)
377
    {
378
      asection *section;
379
 
380
      if (nlm_i386_read_reloc (abfd, sym, &section,
381
                               &nlm_relocs -> reloc)
382
          == false)
383
        return false;
384
      nlm_relocs -> section = section;
385
      nlm_relocs++;
386
      sym -> rcnt++;
387
    }
388
  return true;
389
}
390
 
391
/* Write out an external reference.  */
392
 
393
static boolean
394
nlm_i386_write_external (abfd, count, sym, relocs)
395
     bfd *abfd;
396
     bfd_size_type count;
397
     asymbol *sym;
398
     struct reloc_and_sec *relocs;
399
{
400
  unsigned int i;
401
  bfd_byte len;
402
  unsigned char temp[NLM_TARGET_LONG_SIZE];
403
 
404
  len = strlen (sym->name);
405
  if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof (bfd_byte))
406
      || bfd_write (sym->name, len, 1, abfd) != len)
407
    return false;
408
 
409
  bfd_put_32 (abfd, count, temp);
410
  if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
411
    return false;
412
 
413
  for (i = 0; i < count; i++)
414
    {
415
      if (nlm_i386_write_import (abfd, relocs[i].sec,
416
                                 relocs[i].rel) == false)
417
        return false;
418
    }
419
 
420
  return true;
421
}
422
 
423
#include "nlmswap.h"
424
 
425
static const struct nlm_backend_data nlm32_i386_backend =
426
{
427
  "NetWare Loadable Module\032",
428
  sizeof (Nlm32_i386_External_Fixed_Header),
429
  0,     /* optional_prefix_size */
430
  bfd_arch_i386,
431
  0,
432
  false,
433
  0,     /* backend_object_p */
434
  0,     /* write_prefix_func */
435
  nlm_i386_read_reloc,
436
  nlm_i386_mangle_relocs,
437
  nlm_i386_read_import,
438
  nlm_i386_write_import,
439
  0,     /* set_public_section */
440
  0,     /* get_public_offset */
441
  nlm_swap_fixed_header_in,
442
  nlm_swap_fixed_header_out,
443
  nlm_i386_write_external,
444
  0,     /* write_export */
445
};
446
 
447
#define TARGET_LITTLE_NAME              "nlm32-i386"
448
#define TARGET_LITTLE_SYM               nlmNAME(i386_vec)
449
#define TARGET_BACKEND_DATA             &nlm32_i386_backend
450
 
451
#include "nlm-target.h"

powered by: WebSVN 2.1.0

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