1 |
/* Support for 32-bit i386 NLM (NetWare Loadable Module) |
/* Support for 32-bit i386 NLM (NetWare Loadable Module) |
2 |
Copyright 1993, 1994, 2000, 2001, 2002 Free Software Foundation, Inc. |
Copyright 1993, 1994, 2000, 2001, 2002, 2003 |
3 |
|
Free Software Foundation, Inc. |
4 |
|
|
5 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
6 |
|
|
29 |
|
|
30 |
#include "libnlm.h" |
#include "libnlm.h" |
31 |
|
|
32 |
static boolean nlm_i386_read_reloc |
static bfd_boolean nlm_i386_read_reloc |
33 |
PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *)); |
PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *)); |
34 |
static boolean nlm_i386_write_import |
static bfd_boolean nlm_i386_write_import |
35 |
PARAMS ((bfd *, asection *, arelent *)); |
PARAMS ((bfd *, asection *, arelent *)); |
36 |
static boolean nlm_i386_mangle_relocs |
static bfd_boolean nlm_i386_mangle_relocs |
37 |
PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type)); |
PARAMS ((bfd *, asection *, const PTR, bfd_vma, bfd_size_type)); |
38 |
static boolean nlm_i386_read_import |
static bfd_boolean nlm_i386_read_import |
39 |
PARAMS ((bfd *, nlmNAME(symbol_type) *)); |
PARAMS ((bfd *, nlmNAME(symbol_type) *)); |
40 |
static boolean nlm_i386_write_external |
static bfd_boolean nlm_i386_write_external |
41 |
PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *)); |
PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *)); |
42 |
|
|
43 |
/* Adjust the reloc location by an absolute value. */ |
/* Adjust the reloc location by an absolute value. */ |
47 |
0, /* rightshift */ |
0, /* rightshift */ |
48 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
49 |
32, /* bitsize */ |
32, /* bitsize */ |
50 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
51 |
0, /* bitpos */ |
0, /* bitpos */ |
52 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
53 |
0, /* special_function */ |
0, /* special_function */ |
54 |
"32", /* name */ |
"32", /* name */ |
55 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
56 |
0xffffffff, /* src_mask */ |
0xffffffff, /* src_mask */ |
57 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
58 |
false); /* pcrel_offset */ |
FALSE); /* pcrel_offset */ |
59 |
|
|
60 |
/* Adjust the reloc location by a PC relative displacement. */ |
/* Adjust the reloc location by a PC relative displacement. */ |
61 |
|
|
64 |
0, /* rightshift */ |
0, /* rightshift */ |
65 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
66 |
32, /* bitsize */ |
32, /* bitsize */ |
67 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
68 |
0, /* bitpos */ |
0, /* bitpos */ |
69 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
70 |
0, /* special_function */ |
0, /* special_function */ |
71 |
"DISP32", /* name */ |
"DISP32", /* name */ |
72 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
73 |
0xffffffff, /* src_mask */ |
0xffffffff, /* src_mask */ |
74 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
75 |
true); /* pcrel_offset */ |
TRUE); /* pcrel_offset */ |
76 |
|
|
77 |
/* Read a NetWare i386 reloc. */ |
/* Read a NetWare i386 reloc. */ |
78 |
|
|
79 |
static boolean |
static bfd_boolean |
80 |
nlm_i386_read_reloc (abfd, sym, secp, rel) |
nlm_i386_read_reloc (abfd, sym, secp, rel) |
81 |
bfd *abfd; |
bfd *abfd; |
82 |
nlmNAME(symbol_type) *sym; |
nlmNAME(symbol_type) *sym; |
88 |
const char *name; |
const char *name; |
89 |
|
|
90 |
if (bfd_bread (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp)) |
if (bfd_bread (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp)) |
91 |
return false; |
return FALSE; |
92 |
|
|
93 |
val = bfd_get_32 (abfd, temp); |
val = bfd_get_32 (abfd, temp); |
94 |
|
|
146 |
rel->address = val; |
rel->address = val; |
147 |
rel->addend = 0; |
rel->addend = 0; |
148 |
|
|
149 |
return true; |
return TRUE; |
150 |
} |
} |
151 |
|
|
152 |
/* Write a NetWare i386 reloc. */ |
/* Write a NetWare i386 reloc. */ |
153 |
|
|
154 |
static boolean |
static bfd_boolean |
155 |
nlm_i386_write_import (abfd, sec, rel) |
nlm_i386_write_import (abfd, sec, rel) |
156 |
bfd *abfd; |
bfd *abfd; |
157 |
asection *sec; |
asection *sec; |
175 |
|| rel->howto->dst_mask != 0xffffffff) |
|| rel->howto->dst_mask != 0xffffffff) |
176 |
{ |
{ |
177 |
bfd_set_error (bfd_error_invalid_operation); |
bfd_set_error (bfd_error_invalid_operation); |
178 |
return false; |
return FALSE; |
179 |
} |
} |
180 |
|
|
181 |
sym = *rel->sym_ptr_ptr; |
sym = *rel->sym_ptr_ptr; |
203 |
if (rel->howto->pc_relative) |
if (rel->howto->pc_relative) |
204 |
{ |
{ |
205 |
bfd_set_error (bfd_error_invalid_operation); |
bfd_set_error (bfd_error_invalid_operation); |
206 |
return false; |
return FALSE; |
207 |
} |
} |
208 |
|
|
209 |
/* The high bit is 1 if the reloc is against the code section, 0 |
/* The high bit is 1 if the reloc is against the code section, 0 |
223 |
if (! rel->howto->pcrel_offset) |
if (! rel->howto->pcrel_offset) |
224 |
{ |
{ |
225 |
bfd_set_error (bfd_error_invalid_operation); |
bfd_set_error (bfd_error_invalid_operation); |
226 |
return false; |
return FALSE; |
227 |
} |
} |
228 |
} |
} |
229 |
} |
} |
230 |
|
|
231 |
bfd_put_32 (abfd, val, temp); |
bfd_put_32 (abfd, val, temp); |
232 |
if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp)) |
if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp)) |
233 |
return false; |
return FALSE; |
234 |
|
|
235 |
return true; |
return TRUE; |
236 |
} |
} |
237 |
|
|
238 |
/* I want to be able to use objcopy to turn an i386 a.out or COFF file |
/* I want to be able to use objcopy to turn an i386 a.out or COFF file |
244 |
This is actually a fairly general concept. However, this is not a |
This is actually a fairly general concept. However, this is not a |
245 |
general implementation. */ |
general implementation. */ |
246 |
|
|
247 |
static boolean |
static bfd_boolean |
248 |
nlm_i386_mangle_relocs (abfd, sec, data, offset, count) |
nlm_i386_mangle_relocs (abfd, sec, data, offset, count) |
249 |
bfd *abfd; |
bfd *abfd; |
250 |
asection *sec; |
asection *sec; |
251 |
PTR data; |
const PTR data; |
252 |
bfd_vma offset; |
bfd_vma offset; |
253 |
bfd_size_type count; |
bfd_size_type count; |
254 |
{ |
{ |
336 |
} |
} |
337 |
} |
} |
338 |
|
|
339 |
return true; |
return TRUE; |
340 |
} |
} |
341 |
|
|
342 |
/* Read a NetWare i386 import record */ |
/* Read a NetWare i386 import record */ |
343 |
static boolean |
static bfd_boolean |
344 |
nlm_i386_read_import (abfd, sym) |
nlm_i386_read_import (abfd, sym) |
345 |
bfd *abfd; |
bfd *abfd; |
346 |
nlmNAME(symbol_type) *sym; |
nlmNAME(symbol_type) *sym; |
353 |
|
|
354 |
if (bfd_bread ((PTR) &symlength, (bfd_size_type) sizeof (symlength), abfd) |
if (bfd_bread ((PTR) &symlength, (bfd_size_type) sizeof (symlength), abfd) |
355 |
!= sizeof (symlength)) |
!= sizeof (symlength)) |
356 |
return false; |
return FALSE; |
357 |
sym -> symbol.the_bfd = abfd; |
sym -> symbol.the_bfd = abfd; |
358 |
name = bfd_alloc (abfd, (bfd_size_type) symlength + 1); |
name = bfd_alloc (abfd, (bfd_size_type) symlength + 1); |
359 |
if (name == NULL) |
if (name == NULL) |
360 |
return false; |
return FALSE; |
361 |
if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength) |
if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength) |
362 |
return false; |
return FALSE; |
363 |
name[symlength] = '\0'; |
name[symlength] = '\0'; |
364 |
sym -> symbol.name = name; |
sym -> symbol.name = name; |
365 |
sym -> symbol.flags = 0; |
sym -> symbol.flags = 0; |
367 |
sym -> symbol.section = bfd_und_section_ptr; |
sym -> symbol.section = bfd_und_section_ptr; |
368 |
if (bfd_bread ((PTR) temp, (bfd_size_type) sizeof (temp), abfd) |
if (bfd_bread ((PTR) temp, (bfd_size_type) sizeof (temp), abfd) |
369 |
!= sizeof (temp)) |
!= sizeof (temp)) |
370 |
return false; |
return FALSE; |
371 |
rcount = H_GET_32 (abfd, temp); |
rcount = H_GET_32 (abfd, temp); |
372 |
nlm_relocs = ((struct nlm_relent *) |
nlm_relocs = ((struct nlm_relent *) |
373 |
bfd_alloc (abfd, rcount * sizeof (struct nlm_relent))); |
bfd_alloc (abfd, rcount * sizeof (struct nlm_relent))); |
374 |
if (!nlm_relocs) |
if (!nlm_relocs) |
375 |
return false; |
return FALSE; |
376 |
sym -> relocs = nlm_relocs; |
sym -> relocs = nlm_relocs; |
377 |
sym -> rcnt = 0; |
sym -> rcnt = 0; |
378 |
while (sym -> rcnt < rcount) |
while (sym -> rcnt < rcount) |
380 |
asection *section; |
asection *section; |
381 |
|
|
382 |
if (! nlm_i386_read_reloc (abfd, sym, §ion, &nlm_relocs -> reloc)) |
if (! nlm_i386_read_reloc (abfd, sym, §ion, &nlm_relocs -> reloc)) |
383 |
return false; |
return FALSE; |
384 |
nlm_relocs -> section = section; |
nlm_relocs -> section = section; |
385 |
nlm_relocs++; |
nlm_relocs++; |
386 |
sym -> rcnt++; |
sym -> rcnt++; |
387 |
} |
} |
388 |
return true; |
return TRUE; |
389 |
} |
} |
390 |
|
|
391 |
/* Write out an external reference. */ |
/* Write out an external reference. */ |
392 |
|
|
393 |
static boolean |
static bfd_boolean |
394 |
nlm_i386_write_external (abfd, count, sym, relocs) |
nlm_i386_write_external (abfd, count, sym, relocs) |
395 |
bfd *abfd; |
bfd *abfd; |
396 |
bfd_size_type count; |
bfd_size_type count; |
405 |
if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd) |
if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd) |
406 |
!= sizeof (bfd_byte)) |
!= sizeof (bfd_byte)) |
407 |
|| bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len) |
|| bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len) |
408 |
return false; |
return FALSE; |
409 |
|
|
410 |
bfd_put_32 (abfd, count, temp); |
bfd_put_32 (abfd, count, temp); |
411 |
if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp)) |
if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp)) |
412 |
return false; |
return FALSE; |
413 |
|
|
414 |
for (i = 0; i < count; i++) |
for (i = 0; i < count; i++) |
415 |
{ |
{ |
416 |
if (! nlm_i386_write_import (abfd, relocs[i].sec, relocs[i].rel)) |
if (! nlm_i386_write_import (abfd, relocs[i].sec, relocs[i].rel)) |
417 |
return false; |
return FALSE; |
418 |
} |
} |
419 |
|
|
420 |
return true; |
return TRUE; |
421 |
} |
} |
422 |
|
|
423 |
#include "nlmswap.h" |
#include "nlmswap.h" |
429 |
0, /* optional_prefix_size */ |
0, /* optional_prefix_size */ |
430 |
bfd_arch_i386, |
bfd_arch_i386, |
431 |
0, |
0, |
432 |
false, |
FALSE, |
433 |
0, /* backend_object_p */ |
0, /* backend_object_p */ |
434 |
0, /* write_prefix_func */ |
0, /* write_prefix_func */ |
435 |
nlm_i386_read_reloc, |
nlm_i386_read_reloc, |