1 |
/* Support for 32-bit Alpha NLM (NetWare Loadable Module) |
/* Support for 32-bit Alpha NLM (NetWare Loadable Module) |
2 |
Copyright 1993, 1994, 2000, 2001, 2002 Free Software Foundation, Inc. |
Copyright 1993, 1994, 2000, 2001, 2002, 2003, 2004 |
3 |
|
Free Software Foundation, Inc. |
4 |
Written by Ian Lance Taylor, Cygnus Support. |
Written by Ian Lance Taylor, Cygnus Support. |
5 |
|
|
6 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
34 |
|
|
35 |
#include "libnlm.h" |
#include "libnlm.h" |
36 |
|
|
37 |
static boolean nlm_alpha_backend_object_p |
static bfd_boolean nlm_alpha_backend_object_p |
38 |
PARAMS ((bfd *)); |
PARAMS ((bfd *)); |
39 |
static boolean nlm_alpha_write_prefix |
static bfd_boolean nlm_alpha_write_prefix |
40 |
PARAMS ((bfd *)); |
PARAMS ((bfd *)); |
41 |
static boolean nlm_alpha_read_reloc |
static bfd_boolean nlm_alpha_read_reloc |
42 |
PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *)); |
PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *)); |
43 |
static boolean nlm_alpha_mangle_relocs |
static bfd_boolean nlm_alpha_mangle_relocs |
44 |
PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type)); |
PARAMS ((bfd *, asection *, const PTR, bfd_vma, bfd_size_type)); |
45 |
static boolean nlm_alpha_read_import |
static bfd_boolean nlm_alpha_read_import |
46 |
PARAMS ((bfd *, nlmNAME(symbol_type) *)); |
PARAMS ((bfd *, nlmNAME(symbol_type) *)); |
47 |
static boolean nlm_alpha_write_import |
static bfd_boolean nlm_alpha_write_import |
48 |
PARAMS ((bfd *, asection *, arelent *)); |
PARAMS ((bfd *, asection *, arelent *)); |
49 |
static boolean nlm_alpha_set_public_section |
static bfd_boolean nlm_alpha_set_public_section |
50 |
PARAMS ((bfd *, nlmNAME(symbol_type) *)); |
PARAMS ((bfd *, nlmNAME(symbol_type) *)); |
51 |
static bfd_vma nlm_alpha_get_public_offset |
static bfd_vma nlm_alpha_get_public_offset |
52 |
PARAMS ((bfd *, asymbol *)); |
PARAMS ((bfd *, asymbol *)); |
53 |
static boolean nlm_alpha_write_external |
static bfd_boolean nlm_alpha_write_external |
54 |
PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *)); |
PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *)); |
55 |
|
|
56 |
/* Alpha NLM's have a prefix header before the standard NLM. This |
/* Alpha NLM's have a prefix header before the standard NLM. This |
57 |
function reads it in, verifies the version, and seeks the bfd to |
function reads it in, verifies the version, and seeks the bfd to |
58 |
the location before the regular NLM header. */ |
the location before the regular NLM header. */ |
59 |
|
|
60 |
static boolean |
static bfd_boolean |
61 |
nlm_alpha_backend_object_p (abfd) |
nlm_alpha_backend_object_p (abfd) |
62 |
bfd *abfd; |
bfd *abfd; |
63 |
{ |
{ |
65 |
file_ptr size; |
file_ptr size; |
66 |
|
|
67 |
if (bfd_bread ((PTR) &s, (bfd_size_type) sizeof s, abfd) != sizeof s) |
if (bfd_bread ((PTR) &s, (bfd_size_type) sizeof s, abfd) != sizeof s) |
68 |
return false; |
return FALSE; |
69 |
|
|
70 |
if (H_GET_32 (abfd, s.magic) != NLM32_ALPHA_MAGIC) |
if (H_GET_32 (abfd, s.magic) != NLM32_ALPHA_MAGIC) |
71 |
return false; |
return FALSE; |
72 |
|
|
73 |
/* FIXME: Should we check the format number? */ |
/* FIXME: Should we check the format number? */ |
74 |
|
|
75 |
/* Skip to the end of the header. */ |
/* Skip to the end of the header. */ |
76 |
size = H_GET_32 (abfd, s.size); |
size = H_GET_32 (abfd, s.size); |
77 |
if (bfd_seek (abfd, size, SEEK_SET) != 0) |
if (bfd_seek (abfd, size, SEEK_SET) != 0) |
78 |
return false; |
return FALSE; |
79 |
|
|
80 |
return true; |
return TRUE; |
81 |
} |
} |
82 |
|
|
83 |
/* Write out the prefix. */ |
/* Write out the prefix. */ |
84 |
|
|
85 |
static boolean |
static bfd_boolean |
86 |
nlm_alpha_write_prefix (abfd) |
nlm_alpha_write_prefix (abfd) |
87 |
bfd *abfd; |
bfd *abfd; |
88 |
{ |
{ |
93 |
H_PUT_32 (abfd, 2, s.format); |
H_PUT_32 (abfd, 2, s.format); |
94 |
H_PUT_32 (abfd, sizeof s, s.size); |
H_PUT_32 (abfd, sizeof s, s.size); |
95 |
if (bfd_bwrite ((PTR) &s, (bfd_size_type) sizeof s, abfd) != sizeof s) |
if (bfd_bwrite ((PTR) &s, (bfd_size_type) sizeof s, abfd) != sizeof s) |
96 |
return false; |
return FALSE; |
97 |
return true; |
return TRUE; |
98 |
} |
} |
99 |
|
|
100 |
|
#define ONES(n) (((bfd_vma) 1 << ((n) - 1) << 1) - 1) |
101 |
|
|
102 |
/* How to process the various reloc types. */ |
/* How to process the various reloc types. */ |
103 |
|
|
104 |
static reloc_howto_type nlm32_alpha_howto_table[] = |
static reloc_howto_type nlm32_alpha_howto_table[] = |
110 |
0, /* rightshift */ |
0, /* rightshift */ |
111 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
112 |
8, /* bitsize */ |
8, /* bitsize */ |
113 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
114 |
0, /* bitpos */ |
0, /* bitpos */ |
115 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
116 |
0, /* special_function */ |
0, /* special_function */ |
117 |
"IGNORE", /* name */ |
"IGNORE", /* name */ |
118 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
119 |
0, /* src_mask */ |
0, /* src_mask */ |
120 |
0, /* dst_mask */ |
0, /* dst_mask */ |
121 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
122 |
|
|
123 |
/* A 32 bit reference to a symbol. */ |
/* A 32 bit reference to a symbol. */ |
124 |
HOWTO (ALPHA_R_REFLONG, /* type */ |
HOWTO (ALPHA_R_REFLONG, /* type */ |
125 |
0, /* rightshift */ |
0, /* rightshift */ |
126 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
127 |
32, /* bitsize */ |
32, /* bitsize */ |
128 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
129 |
0, /* bitpos */ |
0, /* bitpos */ |
130 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
131 |
0, /* special_function */ |
0, /* special_function */ |
132 |
"REFLONG", /* name */ |
"REFLONG", /* name */ |
133 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
134 |
0xffffffff, /* src_mask */ |
0xffffffff, /* src_mask */ |
135 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
136 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
137 |
|
|
138 |
/* A 64 bit reference to a symbol. */ |
/* A 64 bit reference to a symbol. */ |
139 |
HOWTO (ALPHA_R_REFQUAD, /* type */ |
HOWTO (ALPHA_R_REFQUAD, /* type */ |
140 |
0, /* rightshift */ |
0, /* rightshift */ |
141 |
4, /* size (0 = byte, 1 = short, 2 = long) */ |
4, /* size (0 = byte, 1 = short, 2 = long) */ |
142 |
64, /* bitsize */ |
64, /* bitsize */ |
143 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
144 |
0, /* bitpos */ |
0, /* bitpos */ |
145 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
146 |
0, /* special_function */ |
0, /* special_function */ |
147 |
"REFQUAD", /* name */ |
"REFQUAD", /* name */ |
148 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
149 |
0xffffffffffffffff, /* src_mask */ |
ONES (64), /* src_mask */ |
150 |
0xffffffffffffffff, /* dst_mask */ |
ONES (64), /* dst_mask */ |
151 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
152 |
|
|
153 |
/* A 32 bit GP relative offset. This is just like REFLONG except |
/* A 32 bit GP relative offset. This is just like REFLONG except |
154 |
that when the value is used the value of the gp register will be |
that when the value is used the value of the gp register will be |
157 |
0, /* rightshift */ |
0, /* rightshift */ |
158 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
159 |
32, /* bitsize */ |
32, /* bitsize */ |
160 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
161 |
0, /* bitpos */ |
0, /* bitpos */ |
162 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
163 |
0, /* special_function */ |
0, /* special_function */ |
164 |
"GPREL32", /* name */ |
"GPREL32", /* name */ |
165 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
166 |
0xffffffff, /* src_mask */ |
0xffffffff, /* src_mask */ |
167 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
168 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
169 |
|
|
170 |
/* Used for an instruction that refers to memory off the GP |
/* Used for an instruction that refers to memory off the GP |
171 |
register. The offset is 16 bits of the 32 bit instruction. This |
register. The offset is 16 bits of the 32 bit instruction. This |
174 |
0, /* rightshift */ |
0, /* rightshift */ |
175 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
176 |
16, /* bitsize */ |
16, /* bitsize */ |
177 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
178 |
0, /* bitpos */ |
0, /* bitpos */ |
179 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
180 |
0, /* special_function */ |
0, /* special_function */ |
181 |
"LITERAL", /* name */ |
"LITERAL", /* name */ |
182 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
183 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
184 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
185 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
186 |
|
|
187 |
/* This reloc only appears immediately following a LITERAL reloc. |
/* This reloc only appears immediately following a LITERAL reloc. |
188 |
It identifies a use of the literal. It seems that the linker can |
It identifies a use of the literal. It seems that the linker can |
197 |
0, /* rightshift */ |
0, /* rightshift */ |
198 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
199 |
32, /* bitsize */ |
32, /* bitsize */ |
200 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
201 |
0, /* bitpos */ |
0, /* bitpos */ |
202 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
203 |
0, /* special_function */ |
0, /* special_function */ |
204 |
"LITUSE", /* name */ |
"LITUSE", /* name */ |
205 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
206 |
0, /* src_mask */ |
0, /* src_mask */ |
207 |
0, /* dst_mask */ |
0, /* dst_mask */ |
208 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
209 |
|
|
210 |
/* Load the gp register. This is always used for a ldah instruction |
/* Load the gp register. This is always used for a ldah instruction |
211 |
which loads the upper 16 bits of the gp register. The next reloc |
which loads the upper 16 bits of the gp register. The next reloc |
222 |
16, /* rightshift */ |
16, /* rightshift */ |
223 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
224 |
16, /* bitsize */ |
16, /* bitsize */ |
225 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
226 |
0, /* bitpos */ |
0, /* bitpos */ |
227 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
228 |
0, /* special_function */ |
0, /* special_function */ |
229 |
"GPDISP", /* name */ |
"GPDISP", /* name */ |
230 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
231 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
232 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
233 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
234 |
|
|
235 |
/* A 21 bit branch. The native assembler generates these for |
/* A 21 bit branch. The native assembler generates these for |
236 |
branches within the text segment, and also fills in the PC |
branches within the text segment, and also fills in the PC |
240 |
2, /* rightshift */ |
2, /* rightshift */ |
241 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
242 |
21, /* bitsize */ |
21, /* bitsize */ |
243 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
244 |
0, /* bitpos */ |
0, /* bitpos */ |
245 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
246 |
0, /* special_function */ |
0, /* special_function */ |
247 |
"BRADDR", /* name */ |
"BRADDR", /* name */ |
248 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
249 |
0, /* src_mask */ |
0, /* src_mask */ |
250 |
0x1fffff, /* dst_mask */ |
0x1fffff, /* dst_mask */ |
251 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
252 |
|
|
253 |
/* A hint for a jump to a register. */ |
/* A hint for a jump to a register. */ |
254 |
HOWTO (ALPHA_R_HINT, /* type */ |
HOWTO (ALPHA_R_HINT, /* type */ |
255 |
2, /* rightshift */ |
2, /* rightshift */ |
256 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
257 |
14, /* bitsize */ |
14, /* bitsize */ |
258 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
259 |
0, /* bitpos */ |
0, /* bitpos */ |
260 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
261 |
0, /* special_function */ |
0, /* special_function */ |
262 |
"HINT", /* name */ |
"HINT", /* name */ |
263 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
264 |
0x3fff, /* src_mask */ |
0x3fff, /* src_mask */ |
265 |
0x3fff, /* dst_mask */ |
0x3fff, /* dst_mask */ |
266 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
267 |
|
|
268 |
/* 16 bit PC relative offset. */ |
/* 16 bit PC relative offset. */ |
269 |
HOWTO (ALPHA_R_SREL16, /* type */ |
HOWTO (ALPHA_R_SREL16, /* type */ |
270 |
0, /* rightshift */ |
0, /* rightshift */ |
271 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
272 |
16, /* bitsize */ |
16, /* bitsize */ |
273 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
274 |
0, /* bitpos */ |
0, /* bitpos */ |
275 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
276 |
0, /* special_function */ |
0, /* special_function */ |
277 |
"SREL16", /* name */ |
"SREL16", /* name */ |
278 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
279 |
0xffff, /* src_mask */ |
0xffff, /* src_mask */ |
280 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
281 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
282 |
|
|
283 |
/* 32 bit PC relative offset. */ |
/* 32 bit PC relative offset. */ |
284 |
HOWTO (ALPHA_R_SREL32, /* type */ |
HOWTO (ALPHA_R_SREL32, /* type */ |
285 |
0, /* rightshift */ |
0, /* rightshift */ |
286 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
287 |
32, /* bitsize */ |
32, /* bitsize */ |
288 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
289 |
0, /* bitpos */ |
0, /* bitpos */ |
290 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
291 |
0, /* special_function */ |
0, /* special_function */ |
292 |
"SREL32", /* name */ |
"SREL32", /* name */ |
293 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
294 |
0xffffffff, /* src_mask */ |
0xffffffff, /* src_mask */ |
295 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
296 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
297 |
|
|
298 |
/* A 64 bit PC relative offset. */ |
/* A 64 bit PC relative offset. */ |
299 |
HOWTO (ALPHA_R_SREL64, /* type */ |
HOWTO (ALPHA_R_SREL64, /* type */ |
300 |
0, /* rightshift */ |
0, /* rightshift */ |
301 |
4, /* size (0 = byte, 1 = short, 2 = long) */ |
4, /* size (0 = byte, 1 = short, 2 = long) */ |
302 |
64, /* bitsize */ |
64, /* bitsize */ |
303 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
304 |
0, /* bitpos */ |
0, /* bitpos */ |
305 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
306 |
0, /* special_function */ |
0, /* special_function */ |
307 |
"SREL64", /* name */ |
"SREL64", /* name */ |
308 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
309 |
0xffffffffffffffff, /* src_mask */ |
ONES (64), /* src_mask */ |
310 |
0xffffffffffffffff, /* dst_mask */ |
ONES (64), /* dst_mask */ |
311 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
312 |
|
|
313 |
/* Push a value on the reloc evaluation stack. */ |
/* Push a value on the reloc evaluation stack. */ |
314 |
HOWTO (ALPHA_R_OP_PUSH, /* type */ |
HOWTO (ALPHA_R_OP_PUSH, /* type */ |
315 |
0, /* rightshift */ |
0, /* rightshift */ |
316 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
317 |
0, /* bitsize */ |
0, /* bitsize */ |
318 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
319 |
0, /* bitpos */ |
0, /* bitpos */ |
320 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
321 |
0, /* special_function */ |
0, /* special_function */ |
322 |
"OP_PUSH", /* name */ |
"OP_PUSH", /* name */ |
323 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
324 |
0, /* src_mask */ |
0, /* src_mask */ |
325 |
0, /* dst_mask */ |
0, /* dst_mask */ |
326 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
327 |
|
|
328 |
/* Store the value from the stack at the given address. Store it in |
/* Store the value from the stack at the given address. Store it in |
329 |
a bitfield of size r_size starting at bit position r_offset. */ |
a bitfield of size r_size starting at bit position r_offset. */ |
331 |
0, /* rightshift */ |
0, /* rightshift */ |
332 |
4, /* size (0 = byte, 1 = short, 2 = long) */ |
4, /* size (0 = byte, 1 = short, 2 = long) */ |
333 |
64, /* bitsize */ |
64, /* bitsize */ |
334 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
335 |
0, /* bitpos */ |
0, /* bitpos */ |
336 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
337 |
0, /* special_function */ |
0, /* special_function */ |
338 |
"OP_STORE", /* name */ |
"OP_STORE", /* name */ |
339 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
340 |
0, /* src_mask */ |
0, /* src_mask */ |
341 |
0xffffffffffffffff, /* dst_mask */ |
ONES (64), /* dst_mask */ |
342 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
343 |
|
|
344 |
/* Subtract the reloc address from the value on the top of the |
/* Subtract the reloc address from the value on the top of the |
345 |
relocation stack. */ |
relocation stack. */ |
347 |
0, /* rightshift */ |
0, /* rightshift */ |
348 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
349 |
0, /* bitsize */ |
0, /* bitsize */ |
350 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
351 |
0, /* bitpos */ |
0, /* bitpos */ |
352 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
353 |
0, /* special_function */ |
0, /* special_function */ |
354 |
"OP_PSUB", /* name */ |
"OP_PSUB", /* name */ |
355 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
356 |
0, /* src_mask */ |
0, /* src_mask */ |
357 |
0, /* dst_mask */ |
0, /* dst_mask */ |
358 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
359 |
|
|
360 |
/* Shift the value on the top of the relocation stack right by the |
/* Shift the value on the top of the relocation stack right by the |
361 |
given value. */ |
given value. */ |
363 |
0, /* rightshift */ |
0, /* rightshift */ |
364 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
365 |
0, /* bitsize */ |
0, /* bitsize */ |
366 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
367 |
0, /* bitpos */ |
0, /* bitpos */ |
368 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
369 |
0, /* special_function */ |
0, /* special_function */ |
370 |
"OP_PRSHIFT", /* name */ |
"OP_PRSHIFT", /* name */ |
371 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
372 |
0, /* src_mask */ |
0, /* src_mask */ |
373 |
0, /* dst_mask */ |
0, /* dst_mask */ |
374 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
375 |
|
|
376 |
/* Adjust the GP value for a new range in the object file. */ |
/* Adjust the GP value for a new range in the object file. */ |
377 |
HOWTO (ALPHA_R_GPVALUE, /* type */ |
HOWTO (ALPHA_R_GPVALUE, /* type */ |
378 |
0, /* rightshift */ |
0, /* rightshift */ |
379 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
380 |
0, /* bitsize */ |
0, /* bitsize */ |
381 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
382 |
0, /* bitpos */ |
0, /* bitpos */ |
383 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
384 |
0, /* special_function */ |
0, /* special_function */ |
385 |
"GPVALUE", /* name */ |
"GPVALUE", /* name */ |
386 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
387 |
0, /* src_mask */ |
0, /* src_mask */ |
388 |
0, /* dst_mask */ |
0, /* dst_mask */ |
389 |
false) /* pcrel_offset */ |
FALSE) /* pcrel_offset */ |
390 |
}; |
}; |
391 |
|
|
392 |
static reloc_howto_type nlm32_alpha_nw_howto = |
static reloc_howto_type nlm32_alpha_nw_howto = |
394 |
0, /* rightshift */ |
0, /* rightshift */ |
395 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
396 |
0, /* bitsize */ |
0, /* bitsize */ |
397 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
398 |
0, /* bitpos */ |
0, /* bitpos */ |
399 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
400 |
0, /* special_function */ |
0, /* special_function */ |
401 |
"NW_RELOC", /* name */ |
"NW_RELOC", /* name */ |
402 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
403 |
0, /* src_mask */ |
0, /* src_mask */ |
404 |
0, /* dst_mask */ |
0, /* dst_mask */ |
405 |
false); /* pcrel_offset */ |
FALSE); /* pcrel_offset */ |
406 |
|
|
407 |
/* Read an Alpha NLM reloc. This routine keeps some static data which |
/* Read an Alpha NLM reloc. This routine keeps some static data which |
408 |
it uses when handling local relocs. This only works correctly |
it uses when handling local relocs. This only works correctly |
409 |
because all the local relocs are read at once. */ |
because all the local relocs are read at once. */ |
410 |
|
|
411 |
static boolean |
static bfd_boolean |
412 |
nlm_alpha_read_reloc (abfd, sym, secp, rel) |
nlm_alpha_read_reloc (abfd, sym, secp, rel) |
413 |
bfd *abfd; |
bfd *abfd; |
414 |
nlmNAME(symbol_type) *sym; |
nlmNAME(symbol_type) *sym; |
425 |
|
|
426 |
/* Read the reloc from the file. */ |
/* Read the reloc from the file. */ |
427 |
if (bfd_bread (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext) |
if (bfd_bread (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext) |
428 |
return false; |
return FALSE; |
429 |
|
|
430 |
/* Swap in the reloc information. */ |
/* Swap in the reloc information. */ |
431 |
r_vaddr = H_GET_64 (abfd, ext.r_vaddr); |
r_vaddr = H_GET_64 (abfd, ext.r_vaddr); |
490 |
or .data section. R_NW_RELOC relocs don't really have a section, |
or .data section. R_NW_RELOC relocs don't really have a section, |
491 |
so we put them in .text. */ |
so we put them in .text. */ |
492 |
if (r_type == ALPHA_R_NW_RELOC |
if (r_type == ALPHA_R_NW_RELOC |
493 |
|| r_vaddr < bfd_section_size (abfd, code_sec)) |
|| r_vaddr < code_sec->size) |
494 |
{ |
{ |
495 |
*secp = code_sec; |
*secp = code_sec; |
496 |
rel->address = r_vaddr; |
rel->address = r_vaddr; |
498 |
else |
else |
499 |
{ |
{ |
500 |
*secp = data_sec; |
*secp = data_sec; |
501 |
rel->address = r_vaddr - bfd_section_size (abfd, code_sec); |
rel->address = r_vaddr - code_sec->size; |
502 |
} |
} |
503 |
|
|
504 |
/* We must adjust the addend based on the type. */ |
/* We must adjust the addend based on the type. */ |
599 |
else |
else |
600 |
rel->howto = &nlm32_alpha_howto_table[r_type]; |
rel->howto = &nlm32_alpha_howto_table[r_type]; |
601 |
|
|
602 |
return true; |
return TRUE; |
603 |
} |
} |
604 |
|
|
605 |
/* Mangle Alpha NLM relocs for output. */ |
/* Mangle Alpha NLM relocs for output. */ |
606 |
|
|
607 |
static boolean |
static bfd_boolean |
608 |
nlm_alpha_mangle_relocs (abfd, sec, data, offset, count) |
nlm_alpha_mangle_relocs (abfd, sec, data, offset, count) |
609 |
bfd *abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
610 |
asection *sec ATTRIBUTE_UNUSED; |
asection *sec ATTRIBUTE_UNUSED; |
611 |
PTR data ATTRIBUTE_UNUSED; |
const PTR data ATTRIBUTE_UNUSED; |
612 |
bfd_vma offset ATTRIBUTE_UNUSED; |
bfd_vma offset ATTRIBUTE_UNUSED; |
613 |
bfd_size_type count ATTRIBUTE_UNUSED; |
bfd_size_type count ATTRIBUTE_UNUSED; |
614 |
{ |
{ |
615 |
return true; |
return TRUE; |
616 |
} |
} |
617 |
|
|
618 |
/* Read an ALPHA NLM import record */ |
/* Read an ALPHA NLM import record */ |
619 |
|
|
620 |
static boolean |
static bfd_boolean |
621 |
nlm_alpha_read_import (abfd, sym) |
nlm_alpha_read_import (abfd, sym) |
622 |
bfd *abfd; |
bfd *abfd; |
623 |
nlmNAME(symbol_type) *sym; |
nlmNAME(symbol_type) *sym; |
631 |
|
|
632 |
if (bfd_bread ((PTR) &symlength, (bfd_size_type) sizeof (symlength), abfd) |
if (bfd_bread ((PTR) &symlength, (bfd_size_type) sizeof (symlength), abfd) |
633 |
!= sizeof (symlength)) |
!= sizeof (symlength)) |
634 |
return false; |
return FALSE; |
635 |
sym -> symbol.the_bfd = abfd; |
sym -> symbol.the_bfd = abfd; |
636 |
name = bfd_alloc (abfd, (bfd_size_type) symlength + 1); |
name = bfd_alloc (abfd, (bfd_size_type) symlength + 1); |
637 |
if (name == NULL) |
if (name == NULL) |
638 |
return false; |
return FALSE; |
639 |
if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength) |
if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength) |
640 |
return false; |
return FALSE; |
641 |
name[symlength] = '\0'; |
name[symlength] = '\0'; |
642 |
sym -> symbol.name = name; |
sym -> symbol.name = name; |
643 |
sym -> symbol.flags = 0; |
sym -> symbol.flags = 0; |
645 |
sym -> symbol.section = bfd_und_section_ptr; |
sym -> symbol.section = bfd_und_section_ptr; |
646 |
if (bfd_bread ((PTR) temp, (bfd_size_type) sizeof (temp), abfd) |
if (bfd_bread ((PTR) temp, (bfd_size_type) sizeof (temp), abfd) |
647 |
!= sizeof (temp)) |
!= sizeof (temp)) |
648 |
return false; |
return FALSE; |
649 |
rcount = H_GET_32 (abfd, temp); |
rcount = H_GET_32 (abfd, temp); |
650 |
amt = rcount * sizeof (struct nlm_relent); |
amt = rcount * sizeof (struct nlm_relent); |
651 |
nlm_relocs = (struct nlm_relent *) bfd_alloc (abfd, amt); |
nlm_relocs = (struct nlm_relent *) bfd_alloc (abfd, amt); |
652 |
if (!nlm_relocs) |
if (!nlm_relocs) |
653 |
return false; |
return FALSE; |
654 |
sym -> relocs = nlm_relocs; |
sym -> relocs = nlm_relocs; |
655 |
sym -> rcnt = 0; |
sym -> rcnt = 0; |
656 |
while (sym -> rcnt < rcount) |
while (sym -> rcnt < rcount) |
658 |
asection *section; |
asection *section; |
659 |
|
|
660 |
if (! nlm_alpha_read_reloc (abfd, sym, §ion, &nlm_relocs -> reloc)) |
if (! nlm_alpha_read_reloc (abfd, sym, §ion, &nlm_relocs -> reloc)) |
661 |
return false; |
return FALSE; |
662 |
nlm_relocs -> section = section; |
nlm_relocs -> section = section; |
663 |
nlm_relocs++; |
nlm_relocs++; |
664 |
sym -> rcnt++; |
sym -> rcnt++; |
665 |
} |
} |
666 |
|
|
667 |
return true; |
return TRUE; |
668 |
} |
} |
669 |
|
|
670 |
/* Write an Alpha NLM reloc. */ |
/* Write an Alpha NLM reloc. */ |
671 |
|
|
672 |
static boolean |
static bfd_boolean |
673 |
nlm_alpha_write_import (abfd, sec, rel) |
nlm_alpha_write_import (abfd, sec, rel) |
674 |
bfd *abfd; |
bfd *abfd; |
675 |
asection *sec; |
asection *sec; |
689 |
{ |
{ |
690 |
r_vaddr = bfd_get_section_vma (abfd, sec) + rel->address; |
r_vaddr = bfd_get_section_vma (abfd, sec) + rel->address; |
691 |
if ((sec->flags & SEC_CODE) == 0) |
if ((sec->flags & SEC_CODE) == 0) |
692 |
r_vaddr += bfd_section_size (abfd, |
r_vaddr += bfd_get_section_by_name (abfd, NLM_CODE_NAME) -> size; |
|
bfd_get_section_by_name (abfd, |
|
|
NLM_CODE_NAME)); |
|
693 |
if (bfd_is_und_section (bfd_get_section (sym))) |
if (bfd_is_und_section (bfd_get_section (sym))) |
694 |
{ |
{ |
695 |
r_extern = 1; |
r_extern = 1; |
767 |
|
|
768 |
/* Write out the relocation. */ |
/* Write out the relocation. */ |
769 |
if (bfd_bwrite (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext) |
if (bfd_bwrite (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext) |
770 |
return false; |
return FALSE; |
771 |
|
|
772 |
return true; |
return TRUE; |
773 |
} |
} |
774 |
|
|
775 |
/* Alpha NetWare does not use the high bit to determine whether a |
/* Alpha NetWare does not use the high bit to determine whether a |
780 |
|
|
781 |
/* Set the section for a public symbol. */ |
/* Set the section for a public symbol. */ |
782 |
|
|
783 |
static boolean |
static bfd_boolean |
784 |
nlm_alpha_set_public_section (abfd, sym) |
nlm_alpha_set_public_section (abfd, sym) |
785 |
bfd *abfd; |
bfd *abfd; |
786 |
nlmNAME(symbol_type) *sym; |
nlmNAME(symbol_type) *sym; |
789 |
|
|
790 |
code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME); |
code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME); |
791 |
data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME); |
data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME); |
792 |
if (sym->symbol.value < bfd_section_size (abfd, code_sec)) |
if (sym->symbol.value < code_sec->size) |
793 |
{ |
{ |
794 |
sym->symbol.section = code_sec; |
sym->symbol.section = code_sec; |
795 |
sym->symbol.flags |= BSF_FUNCTION; |
sym->symbol.flags |= BSF_FUNCTION; |
797 |
else |
else |
798 |
{ |
{ |
799 |
sym->symbol.section = data_sec; |
sym->symbol.section = data_sec; |
800 |
sym->symbol.value -= bfd_section_size (abfd, code_sec); |
sym->symbol.value -= code_sec->size; |
801 |
/* The data segment had better be aligned. */ |
/* The data segment had better be aligned. */ |
802 |
BFD_ASSERT ((bfd_section_size (abfd, code_sec) & 0xf) == 0); |
BFD_ASSERT ((code_sec->size & 0xf) == 0); |
803 |
} |
} |
804 |
return true; |
return TRUE; |
805 |
} |
} |
806 |
|
|
807 |
/* Get the offset to write out for a public symbol. */ |
/* Get the offset to write out for a public symbol. */ |
816 |
|
|
817 |
/* Write an Alpha NLM external symbol. */ |
/* Write an Alpha NLM external symbol. */ |
818 |
|
|
819 |
static boolean |
static bfd_boolean |
820 |
nlm_alpha_write_external (abfd, count, sym, relocs) |
nlm_alpha_write_external (abfd, count, sym, relocs) |
821 |
bfd *abfd; |
bfd *abfd; |
822 |
bfd_size_type count; |
bfd_size_type count; |
832 |
if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd) |
if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd) |
833 |
!= sizeof (bfd_byte)) |
!= sizeof (bfd_byte)) |
834 |
|| bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len) |
|| bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len) |
835 |
return false; |
return FALSE; |
836 |
|
|
837 |
bfd_put_32 (abfd, count + 2, temp); |
bfd_put_32 (abfd, count + 2, temp); |
838 |
if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp)) |
if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp)) |
839 |
return false; |
return FALSE; |
840 |
|
|
841 |
/* The first two relocs for each external symbol are the .lita |
/* The first two relocs for each external symbol are the .lita |
842 |
address and the GP value. */ |
address and the GP value. */ |
846 |
r.address = nlm_alpha_backend_data (abfd)->lita_address; |
r.address = nlm_alpha_backend_data (abfd)->lita_address; |
847 |
r.addend = nlm_alpha_backend_data (abfd)->lita_size + 1; |
r.addend = nlm_alpha_backend_data (abfd)->lita_size + 1; |
848 |
if (! nlm_alpha_write_import (abfd, (asection *) NULL, &r)) |
if (! nlm_alpha_write_import (abfd, (asection *) NULL, &r)) |
849 |
return false; |
return FALSE; |
850 |
|
|
851 |
r.address = nlm_alpha_backend_data (abfd)->gp; |
r.address = nlm_alpha_backend_data (abfd)->gp; |
852 |
r.addend = 0; |
r.addend = 0; |
853 |
if (! nlm_alpha_write_import (abfd, (asection *) NULL, &r)) |
if (! nlm_alpha_write_import (abfd, (asection *) NULL, &r)) |
854 |
return false; |
return FALSE; |
855 |
|
|
856 |
for (i = 0; i < count; i++) |
for (i = 0; i < count; i++) |
857 |
{ |
{ |
858 |
if (! nlm_alpha_write_import (abfd, relocs[i].sec, relocs[i].rel)) |
if (! nlm_alpha_write_import (abfd, relocs[i].sec, relocs[i].rel)) |
859 |
return false; |
return FALSE; |
860 |
} |
} |
861 |
|
|
862 |
return true; |
return TRUE; |
863 |
} |
} |
864 |
|
|
865 |
#include "nlmswap.h" |
#include "nlmswap.h" |
871 |
sizeof (struct nlm32_alpha_external_prefix_header), |
sizeof (struct nlm32_alpha_external_prefix_header), |
872 |
bfd_arch_alpha, |
bfd_arch_alpha, |
873 |
0, |
0, |
874 |
true, /* no uninitialized data permitted by Alpha NetWare. */ |
TRUE, /* no uninitialized data permitted by Alpha NetWare. */ |
875 |
nlm_alpha_backend_object_p, |
nlm_alpha_backend_object_p, |
876 |
nlm_alpha_write_prefix, |
nlm_alpha_write_prefix, |
877 |
nlm_alpha_read_reloc, |
nlm_alpha_read_reloc, |