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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [nlm32-i386.c] - Blame information for rev 14

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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