Commit | Line | Data |
---|---|---|
252b5132 | 1 | /* Support for 32-bit PowerPC NLM (NetWare Loadable Module) |
eea6121a | 2 | Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004 |
0f867abe | 3 | Free Software Foundation, Inc. |
252b5132 RH |
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 | #include "bfd.h" | |
22 | #include "sysdep.h" | |
23 | #include "libbfd.h" | |
24 | ||
25 | /* The format of a PowerPC NLM changed. Define OLDFORMAT to get the | |
26 | old format. */ | |
27 | ||
28 | #define ARCH_SIZE 32 | |
29 | ||
30 | #include "nlm/ppc-ext.h" | |
31 | #define Nlm_External_Fixed_Header Nlm32_powerpc_External_Fixed_Header | |
32 | ||
33 | #include "libnlm.h" | |
34 | ||
35 | #ifdef OLDFORMAT | |
b34976b6 | 36 | static bfd_boolean nlm_powerpc_backend_object_p |
252b5132 | 37 | PARAMS ((bfd *)); |
b34976b6 | 38 | static bfd_boolean nlm_powerpc_write_prefix |
252b5132 RH |
39 | PARAMS ((bfd *)); |
40 | #endif | |
41 | ||
b34976b6 | 42 | static bfd_boolean nlm_powerpc_read_reloc |
252b5132 | 43 | PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *)); |
b34976b6 | 44 | static bfd_boolean nlm_powerpc_mangle_relocs |
0f867abe | 45 | PARAMS ((bfd *, asection *, const PTR, bfd_vma, bfd_size_type)); |
b34976b6 | 46 | static bfd_boolean nlm_powerpc_read_import |
252b5132 RH |
47 | PARAMS ((bfd *, nlmNAME(symbol_type) *)); |
48 | ||
49 | #ifdef OLDFORMAT | |
b34976b6 | 50 | static bfd_boolean nlm_powerpc_write_reloc |
252b5132 RH |
51 | PARAMS ((bfd *, asection *, arelent *, int)); |
52 | #endif | |
53 | ||
b34976b6 | 54 | static bfd_boolean nlm_powerpc_write_import |
252b5132 | 55 | PARAMS ((bfd *, asection *, arelent *)); |
b34976b6 | 56 | static bfd_boolean nlm_powerpc_write_external |
252b5132 RH |
57 | PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *)); |
58 | ||
59 | #ifndef OLDFORMAT | |
b34976b6 | 60 | static bfd_boolean nlm_powerpc_set_public_section |
252b5132 RH |
61 | PARAMS ((bfd *, nlmNAME(symbol_type) *)); |
62 | static bfd_vma nlm_powerpc_get_public_offset | |
63 | PARAMS ((bfd *, asymbol *)); | |
64 | #endif | |
65 | \f | |
66 | #ifdef OLDFORMAT | |
67 | ||
68 | /* The prefix header is only used in the old format. */ | |
69 | ||
70 | /* PowerPC NLM's have a prefix header before the standard NLM. This | |
71 | function reads it in, verifies the version, and seeks the bfd to | |
72 | the location before the regular NLM header. */ | |
73 | ||
b34976b6 | 74 | static bfd_boolean |
252b5132 RH |
75 | nlm_powerpc_backend_object_p (abfd) |
76 | bfd *abfd; | |
77 | { | |
78 | struct nlm32_powerpc_external_prefix_header s; | |
79 | ||
dc810e39 | 80 | if (bfd_bread ((PTR) &s, (bfd_size_type) sizeof s, abfd) != sizeof s) |
b34976b6 | 81 | return FALSE; |
252b5132 RH |
82 | |
83 | if (memcmp (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature) != 0 | |
dc810e39 | 84 | || H_GET_32 (abfd, s.headerVersion) != NLM32_POWERPC_HEADER_VERSION) |
b34976b6 | 85 | return FALSE; |
252b5132 | 86 | |
b34976b6 | 87 | return TRUE; |
252b5132 RH |
88 | } |
89 | ||
90 | /* Write out the prefix. */ | |
91 | ||
b34976b6 | 92 | static bfd_boolean |
252b5132 RH |
93 | nlm_powerpc_write_prefix (abfd) |
94 | bfd *abfd; | |
95 | { | |
96 | struct nlm32_powerpc_external_prefix_header s; | |
97 | ||
98 | memset (&s, 0, sizeof s); | |
99 | memcpy (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature); | |
dc810e39 AM |
100 | H_PUT_32 (abfd, NLM32_POWERPC_HEADER_VERSION, s.headerVersion); |
101 | H_PUT_32 (abfd, 0, s.origins); | |
252b5132 RH |
102 | |
103 | /* FIXME: What should we do about the date? */ | |
104 | ||
dc810e39 | 105 | if (bfd_bwrite ((PTR) &s, (bfd_size_type) sizeof s, abfd) != sizeof s) |
b34976b6 | 106 | return FALSE; |
252b5132 | 107 | |
b34976b6 | 108 | return TRUE; |
252b5132 RH |
109 | } |
110 | ||
111 | #endif /* OLDFORMAT */ | |
112 | \f | |
113 | #ifndef OLDFORMAT | |
114 | ||
115 | /* There is only one type of reloc in a PowerPC NLM. */ | |
116 | ||
117 | static reloc_howto_type nlm_powerpc_howto = | |
118 | HOWTO (0, /* type */ | |
119 | 0, /* rightshift */ | |
120 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
121 | 32, /* bitsize */ | |
b34976b6 | 122 | FALSE, /* pc_relative */ |
252b5132 RH |
123 | 0, /* bitpos */ |
124 | complain_overflow_bitfield, /* complain_on_overflow */ | |
125 | 0, /* special_function */ | |
126 | "32", /* name */ | |
b34976b6 | 127 | TRUE, /* partial_inplace */ |
252b5132 RH |
128 | 0xffffffff, /* src_mask */ |
129 | 0xffffffff, /* dst_mask */ | |
b34976b6 | 130 | FALSE); /* pcrel_offset */ |
252b5132 RH |
131 | |
132 | /* Read a PowerPC NLM reloc. */ | |
133 | ||
b34976b6 | 134 | static bfd_boolean |
252b5132 RH |
135 | nlm_powerpc_read_reloc (abfd, sym, secp, rel) |
136 | bfd *abfd; | |
137 | nlmNAME(symbol_type) *sym; | |
138 | asection **secp; | |
139 | arelent *rel; | |
140 | { | |
141 | bfd_byte temp[4]; | |
142 | bfd_vma val; | |
143 | const char *name; | |
144 | ||
dc810e39 | 145 | if (bfd_bread (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp)) |
b34976b6 | 146 | return FALSE; |
252b5132 RH |
147 | |
148 | val = bfd_get_32 (abfd, temp); | |
149 | ||
150 | /* The value is a word offset into either the code or data segment. | |
151 | This is the location which needs to be adjusted. | |
152 | ||
153 | The high bit is 0 if the value is an offset into the data | |
154 | segment, or 1 if the value is an offset into the text segment. | |
155 | ||
156 | If this is a relocation fixup rather than an imported symbol (the | |
157 | sym argument is NULL), then the second most significant bit is 0 | |
158 | if the address of the data segment should be added to the | |
159 | location addressed by the value, or 1 if the address of the text | |
160 | segment should be added. | |
161 | ||
162 | If this is an imported symbol, the second most significant bit is | |
163 | not used and must be 0. */ | |
164 | ||
165 | if ((val & NLM_HIBIT) == 0) | |
166 | name = NLM_INITIALIZED_DATA_NAME; | |
167 | else | |
168 | { | |
169 | name = NLM_CODE_NAME; | |
170 | val &=~ NLM_HIBIT; | |
171 | } | |
172 | *secp = bfd_get_section_by_name (abfd, name); | |
173 | ||
174 | if (sym == NULL) | |
175 | { | |
176 | if ((val & (NLM_HIBIT >> 1)) == 0) | |
177 | name = NLM_INITIALIZED_DATA_NAME; | |
178 | else | |
179 | { | |
180 | name = NLM_CODE_NAME; | |
181 | val &=~ (NLM_HIBIT >> 1); | |
182 | } | |
183 | rel->sym_ptr_ptr = bfd_get_section_by_name (abfd, name)->symbol_ptr_ptr; | |
184 | } | |
185 | ||
186 | rel->howto = &nlm_powerpc_howto; | |
187 | ||
188 | rel->address = val << 2; | |
189 | rel->addend = 0; | |
190 | ||
b34976b6 | 191 | return TRUE; |
252b5132 RH |
192 | } |
193 | ||
194 | #else /* OLDFORMAT */ | |
195 | ||
196 | /* This reloc handling is only applicable to the old format. */ | |
197 | ||
198 | /* How to process the various reloc types. PowerPC NLMs use XCOFF | |
199 | reloc types, and I have just copied the XCOFF reloc table here. */ | |
200 | ||
201 | static reloc_howto_type nlm_powerpc_howto_table[] = | |
202 | { | |
203 | /* Standard 32 bit relocation. */ | |
1518639e KH |
204 | HOWTO (0, /* type */ |
205 | 0, /* rightshift */ | |
206 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
207 | 32, /* bitsize */ | |
b34976b6 | 208 | FALSE, /* pc_relative */ |
1518639e | 209 | 0, /* bitpos */ |
252b5132 | 210 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
211 | 0, /* special_function */ |
212 | "R_POS", /* name */ | |
b34976b6 | 213 | TRUE, /* partial_inplace */ |
1518639e KH |
214 | 0xffffffff, /* src_mask */ |
215 | 0xffffffff, /* dst_mask */ | |
b34976b6 | 216 | FALSE), /* pcrel_offset */ |
252b5132 RH |
217 | |
218 | /* 32 bit relocation, but store negative value. */ | |
1518639e KH |
219 | HOWTO (1, /* type */ |
220 | 0, /* rightshift */ | |
221 | -2, /* size (0 = byte, 1 = short, 2 = long) */ | |
222 | 32, /* bitsize */ | |
b34976b6 | 223 | FALSE, /* pc_relative */ |
1518639e | 224 | 0, /* bitpos */ |
252b5132 | 225 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
226 | 0, /* special_function */ |
227 | "R_NEG", /* name */ | |
b34976b6 | 228 | TRUE, /* partial_inplace */ |
1518639e KH |
229 | 0xffffffff, /* src_mask */ |
230 | 0xffffffff, /* dst_mask */ | |
b34976b6 | 231 | FALSE), /* pcrel_offset */ |
252b5132 RH |
232 | |
233 | /* 32 bit PC relative relocation. */ | |
1518639e KH |
234 | HOWTO (2, /* type */ |
235 | 0, /* rightshift */ | |
236 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
237 | 32, /* bitsize */ | |
b34976b6 | 238 | TRUE, /* pc_relative */ |
1518639e | 239 | 0, /* bitpos */ |
252b5132 | 240 | complain_overflow_signed, /* complain_on_overflow */ |
1518639e KH |
241 | 0, /* special_function */ |
242 | "R_REL", /* name */ | |
b34976b6 | 243 | TRUE, /* partial_inplace */ |
1518639e KH |
244 | 0xffffffff, /* src_mask */ |
245 | 0xffffffff, /* dst_mask */ | |
b34976b6 | 246 | FALSE), /* pcrel_offset */ |
1518639e | 247 | |
252b5132 | 248 | /* 16 bit TOC relative relocation. */ |
1518639e KH |
249 | HOWTO (3, /* type */ |
250 | 0, /* rightshift */ | |
251 | 1, /* size (0 = byte, 1 = short, 2 = long) */ | |
252 | 16, /* bitsize */ | |
b34976b6 | 253 | FALSE, /* pc_relative */ |
1518639e | 254 | 0, /* bitpos */ |
252b5132 | 255 | complain_overflow_signed, /* complain_on_overflow */ |
1518639e KH |
256 | 0, /* special_function */ |
257 | "R_TOC", /* name */ | |
b34976b6 | 258 | TRUE, /* partial_inplace */ |
1518639e KH |
259 | 0xffff, /* src_mask */ |
260 | 0xffff, /* dst_mask */ | |
b34976b6 | 261 | FALSE), /* pcrel_offset */ |
1518639e | 262 | |
252b5132 | 263 | /* I don't really know what this is. */ |
1518639e KH |
264 | HOWTO (4, /* type */ |
265 | 1, /* rightshift */ | |
266 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
267 | 32, /* bitsize */ | |
b34976b6 | 268 | FALSE, /* pc_relative */ |
1518639e | 269 | 0, /* bitpos */ |
252b5132 | 270 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
271 | 0, /* special_function */ |
272 | "R_RTB", /* name */ | |
b34976b6 | 273 | TRUE, /* partial_inplace */ |
1518639e KH |
274 | 0xffffffff, /* src_mask */ |
275 | 0xffffffff, /* dst_mask */ | |
b34976b6 | 276 | FALSE), /* pcrel_offset */ |
1518639e | 277 | |
252b5132 | 278 | /* External TOC relative symbol. */ |
1518639e KH |
279 | HOWTO (5, /* type */ |
280 | 0, /* rightshift */ | |
281 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
282 | 16, /* bitsize */ | |
b34976b6 | 283 | FALSE, /* pc_relative */ |
1518639e | 284 | 0, /* bitpos */ |
252b5132 | 285 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
286 | 0, /* special_function */ |
287 | "R_GL", /* name */ | |
b34976b6 | 288 | TRUE, /* partial_inplace */ |
1518639e KH |
289 | 0xffff, /* src_mask */ |
290 | 0xffff, /* dst_mask */ | |
b34976b6 | 291 | FALSE), /* pcrel_offset */ |
1518639e | 292 | |
252b5132 | 293 | /* Local TOC relative symbol. */ |
1518639e KH |
294 | HOWTO (6, /* type */ |
295 | 0, /* rightshift */ | |
296 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
297 | 16, /* bitsize */ | |
b34976b6 | 298 | FALSE, /* pc_relative */ |
1518639e | 299 | 0, /* bitpos */ |
252b5132 | 300 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
301 | 0, /* special_function */ |
302 | "R_TCL", /* name */ | |
b34976b6 | 303 | TRUE, /* partial_inplace */ |
1518639e KH |
304 | 0xffff, /* src_mask */ |
305 | 0xffff, /* dst_mask */ | |
b34976b6 | 306 | FALSE), /* pcrel_offset */ |
1518639e | 307 | |
252b5132 | 308 | { 7 }, |
1518639e | 309 | |
252b5132 | 310 | /* Non modifiable absolute branch. */ |
1518639e KH |
311 | HOWTO (8, /* type */ |
312 | 0, /* rightshift */ | |
313 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
314 | 26, /* bitsize */ | |
b34976b6 | 315 | FALSE, /* pc_relative */ |
1518639e | 316 | 0, /* bitpos */ |
252b5132 | 317 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
318 | 0, /* special_function */ |
319 | "R_BA", /* name */ | |
b34976b6 | 320 | TRUE, /* partial_inplace */ |
1518639e KH |
321 | 0x3fffffc, /* src_mask */ |
322 | 0x3fffffc, /* dst_mask */ | |
b34976b6 | 323 | FALSE), /* pcrel_offset */ |
1518639e | 324 | |
252b5132 RH |
325 | { 9 }, |
326 | ||
327 | /* Non modifiable relative branch. */ | |
1518639e KH |
328 | HOWTO (0xa, /* type */ |
329 | 0, /* rightshift */ | |
330 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
331 | 26, /* bitsize */ | |
b34976b6 | 332 | TRUE, /* pc_relative */ |
1518639e | 333 | 0, /* bitpos */ |
252b5132 | 334 | complain_overflow_signed, /* complain_on_overflow */ |
1518639e KH |
335 | 0, /* special_function */ |
336 | "R_BR", /* name */ | |
b34976b6 | 337 | TRUE, /* partial_inplace */ |
1518639e KH |
338 | 0x3fffffc, /* src_mask */ |
339 | 0x3fffffc, /* dst_mask */ | |
b34976b6 | 340 | FALSE), /* pcrel_offset */ |
1518639e | 341 | |
252b5132 RH |
342 | { 0xb }, |
343 | ||
344 | /* Indirect load. */ | |
1518639e KH |
345 | HOWTO (0xc, /* type */ |
346 | 0, /* rightshift */ | |
347 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
348 | 16, /* bitsize */ | |
b34976b6 | 349 | FALSE, /* pc_relative */ |
1518639e | 350 | 0, /* bitpos */ |
252b5132 | 351 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
352 | 0, /* special_function */ |
353 | "R_RL", /* name */ | |
b34976b6 | 354 | TRUE, /* partial_inplace */ |
1518639e KH |
355 | 0xffff, /* src_mask */ |
356 | 0xffff, /* dst_mask */ | |
b34976b6 | 357 | FALSE), /* pcrel_offset */ |
1518639e | 358 | |
252b5132 | 359 | /* Load address. */ |
1518639e KH |
360 | HOWTO (0xd, /* type */ |
361 | 0, /* rightshift */ | |
362 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
363 | 16, /* bitsize */ | |
b34976b6 | 364 | FALSE, /* pc_relative */ |
1518639e | 365 | 0, /* bitpos */ |
252b5132 | 366 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
367 | 0, /* special_function */ |
368 | "R_RLA", /* name */ | |
b34976b6 | 369 | TRUE, /* partial_inplace */ |
1518639e KH |
370 | 0xffff, /* src_mask */ |
371 | 0xffff, /* dst_mask */ | |
b34976b6 | 372 | FALSE), /* pcrel_offset */ |
1518639e | 373 | |
252b5132 | 374 | { 0xe }, |
1518639e | 375 | |
252b5132 | 376 | /* Non-relocating reference. */ |
1518639e KH |
377 | HOWTO (0xf, /* type */ |
378 | 0, /* rightshift */ | |
379 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
380 | 32, /* bitsize */ | |
b34976b6 | 381 | FALSE, /* pc_relative */ |
1518639e | 382 | 0, /* bitpos */ |
252b5132 | 383 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
384 | 0, /* special_function */ |
385 | "R_REF", /* name */ | |
b34976b6 | 386 | FALSE, /* partial_inplace */ |
1518639e KH |
387 | 0, /* src_mask */ |
388 | 0, /* dst_mask */ | |
b34976b6 | 389 | FALSE), /* pcrel_offset */ |
1518639e | 390 | |
252b5132 RH |
391 | { 0x10 }, |
392 | { 0x11 }, | |
1518639e | 393 | |
252b5132 | 394 | /* TOC relative indirect load. */ |
1518639e KH |
395 | HOWTO (0x12, /* type */ |
396 | 0, /* rightshift */ | |
397 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
398 | 16, /* bitsize */ | |
b34976b6 | 399 | FALSE, /* pc_relative */ |
1518639e | 400 | 0, /* bitpos */ |
252b5132 | 401 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
402 | 0, /* special_function */ |
403 | "R_TRL", /* name */ | |
b34976b6 | 404 | TRUE, /* partial_inplace */ |
1518639e KH |
405 | 0xffff, /* src_mask */ |
406 | 0xffff, /* dst_mask */ | |
b34976b6 | 407 | FALSE), /* pcrel_offset */ |
1518639e | 408 | |
252b5132 | 409 | /* TOC relative load address. */ |
1518639e KH |
410 | HOWTO (0x13, /* type */ |
411 | 0, /* rightshift */ | |
412 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
413 | 16, /* bitsize */ | |
b34976b6 | 414 | FALSE, /* pc_relative */ |
1518639e | 415 | 0, /* bitpos */ |
252b5132 | 416 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
417 | 0, /* special_function */ |
418 | "R_TRLA", /* name */ | |
b34976b6 | 419 | TRUE, /* partial_inplace */ |
1518639e KH |
420 | 0xffff, /* src_mask */ |
421 | 0xffff, /* dst_mask */ | |
b34976b6 | 422 | FALSE), /* pcrel_offset */ |
1518639e | 423 | |
252b5132 | 424 | /* Modifiable relative branch. */ |
1518639e KH |
425 | HOWTO (0x14, /* type */ |
426 | 1, /* rightshift */ | |
427 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
428 | 32, /* bitsize */ | |
b34976b6 | 429 | FALSE, /* pc_relative */ |
1518639e | 430 | 0, /* bitpos */ |
252b5132 | 431 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
432 | 0, /* special_function */ |
433 | "R_RRTBI", /* name */ | |
b34976b6 | 434 | TRUE, /* partial_inplace */ |
1518639e KH |
435 | 0xffffffff, /* src_mask */ |
436 | 0xffffffff, /* dst_mask */ | |
b34976b6 | 437 | FALSE), /* pcrel_offset */ |
1518639e | 438 | |
252b5132 | 439 | /* Modifiable absolute branch. */ |
1518639e KH |
440 | HOWTO (0x15, /* type */ |
441 | 1, /* rightshift */ | |
442 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
443 | 32, /* bitsize */ | |
b34976b6 | 444 | FALSE, /* pc_relative */ |
1518639e | 445 | 0, /* bitpos */ |
252b5132 | 446 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
447 | 0, /* special_function */ |
448 | "R_RRTBA", /* name */ | |
b34976b6 | 449 | TRUE, /* partial_inplace */ |
1518639e KH |
450 | 0xffffffff, /* src_mask */ |
451 | 0xffffffff, /* dst_mask */ | |
b34976b6 | 452 | FALSE), /* pcrel_offset */ |
1518639e | 453 | |
252b5132 | 454 | /* Modifiable call absolute indirect. */ |
1518639e KH |
455 | HOWTO (0x16, /* type */ |
456 | 0, /* rightshift */ | |
457 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
458 | 16, /* bitsize */ | |
b34976b6 | 459 | FALSE, /* pc_relative */ |
1518639e | 460 | 0, /* bitpos */ |
252b5132 | 461 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
462 | 0, /* special_function */ |
463 | "R_CAI", /* name */ | |
b34976b6 | 464 | TRUE, /* partial_inplace */ |
1518639e KH |
465 | 0xffff, /* src_mask */ |
466 | 0xffff, /* dst_mask */ | |
b34976b6 | 467 | FALSE), /* pcrel_offset */ |
1518639e | 468 | |
252b5132 | 469 | /* Modifiable call relative. */ |
1518639e KH |
470 | HOWTO (0x17, /* type */ |
471 | 0, /* rightshift */ | |
472 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
473 | 16, /* bitsize */ | |
b34976b6 | 474 | FALSE, /* pc_relative */ |
1518639e | 475 | 0, /* bitpos */ |
252b5132 | 476 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
477 | 0, /* special_function */ |
478 | "R_REL", /* name */ | |
b34976b6 | 479 | TRUE, /* partial_inplace */ |
1518639e KH |
480 | 0xffff, /* src_mask */ |
481 | 0xffff, /* dst_mask */ | |
b34976b6 | 482 | FALSE), /* pcrel_offset */ |
1518639e | 483 | |
252b5132 | 484 | /* Modifiable branch absolute. */ |
1518639e KH |
485 | HOWTO (0x18, /* type */ |
486 | 0, /* rightshift */ | |
487 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
488 | 16, /* bitsize */ | |
b34976b6 | 489 | FALSE, /* pc_relative */ |
1518639e | 490 | 0, /* bitpos */ |
252b5132 | 491 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
492 | 0, /* special_function */ |
493 | "R_RBA", /* name */ | |
b34976b6 | 494 | TRUE, /* partial_inplace */ |
1518639e KH |
495 | 0xffff, /* src_mask */ |
496 | 0xffff, /* dst_mask */ | |
b34976b6 | 497 | FALSE), /* pcrel_offset */ |
1518639e | 498 | |
252b5132 | 499 | /* Modifiable branch absolute. */ |
1518639e KH |
500 | HOWTO (0x19, /* type */ |
501 | 0, /* rightshift */ | |
502 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
503 | 16, /* bitsize */ | |
b34976b6 | 504 | FALSE, /* pc_relative */ |
1518639e | 505 | 0, /* bitpos */ |
252b5132 | 506 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
507 | 0, /* special_function */ |
508 | "R_RBAC", /* name */ | |
b34976b6 | 509 | TRUE, /* partial_inplace */ |
1518639e KH |
510 | 0xffff, /* src_mask */ |
511 | 0xffff, /* dst_mask */ | |
b34976b6 | 512 | FALSE), /* pcrel_offset */ |
1518639e | 513 | |
252b5132 | 514 | /* Modifiable branch relative. */ |
1518639e KH |
515 | HOWTO (0x1a, /* type */ |
516 | 0, /* rightshift */ | |
517 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
518 | 26, /* bitsize */ | |
b34976b6 | 519 | FALSE, /* pc_relative */ |
1518639e | 520 | 0, /* bitpos */ |
252b5132 | 521 | complain_overflow_signed, /* complain_on_overflow */ |
1518639e KH |
522 | 0, /* special_function */ |
523 | "R_REL", /* name */ | |
b34976b6 | 524 | TRUE, /* partial_inplace */ |
1518639e KH |
525 | 0xffff, /* src_mask */ |
526 | 0xffff, /* dst_mask */ | |
b34976b6 | 527 | FALSE), /* pcrel_offset */ |
1518639e | 528 | |
252b5132 | 529 | /* Modifiable branch absolute. */ |
1518639e KH |
530 | HOWTO (0x1b, /* type */ |
531 | 0, /* rightshift */ | |
532 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
533 | 16, /* bitsize */ | |
b34976b6 | 534 | FALSE, /* pc_relative */ |
1518639e | 535 | 0, /* bitpos */ |
252b5132 | 536 | complain_overflow_bitfield, /* complain_on_overflow */ |
1518639e KH |
537 | 0, /* special_function */ |
538 | "R_REL", /* name */ | |
b34976b6 | 539 | TRUE, /* partial_inplace */ |
1518639e KH |
540 | 0xffff, /* src_mask */ |
541 | 0xffff, /* dst_mask */ | |
b34976b6 | 542 | FALSE) /* pcrel_offset */ |
252b5132 RH |
543 | }; |
544 | ||
545 | #define HOWTO_COUNT (sizeof nlm_powerpc_howto_table \ | |
546 | / sizeof nlm_powerpc_howto_table[0]) | |
547 | ||
548 | /* Read a PowerPC NLM reloc. */ | |
549 | ||
b34976b6 | 550 | static bfd_boolean |
252b5132 RH |
551 | nlm_powerpc_read_reloc (abfd, sym, secp, rel) |
552 | bfd *abfd; | |
553 | nlmNAME(symbol_type) *sym; | |
554 | asection **secp; | |
555 | arelent *rel; | |
556 | { | |
557 | struct nlm32_powerpc_external_reloc ext; | |
558 | bfd_vma l_vaddr; | |
559 | unsigned long l_symndx; | |
560 | int l_rtype; | |
561 | int l_rsecnm; | |
562 | asection *code_sec, *data_sec, *bss_sec; | |
563 | ||
564 | /* Read the reloc from the file. */ | |
dc810e39 | 565 | if (bfd_bread (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext) |
b34976b6 | 566 | return FALSE; |
252b5132 RH |
567 | |
568 | /* Swap in the fields. */ | |
dc810e39 AM |
569 | l_vaddr = H_GET_32 (abfd, ext.l_vaddr); |
570 | l_symndx = H_GET_32 (abfd, ext.l_symndx); | |
571 | l_rtype = H_GET_16 (abfd, ext.l_rtype); | |
572 | l_rsecnm = H_GET_16 (abfd, ext.l_rsecnm); | |
252b5132 RH |
573 | |
574 | /* Get the sections now, for convenience. */ | |
575 | code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME); | |
576 | data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME); | |
577 | bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME); | |
578 | ||
579 | /* Work out the arelent fields. */ | |
580 | if (sym != NULL) | |
581 | { | |
582 | /* This is an import. sym_ptr_ptr is filled in by | |
583 | nlm_canonicalize_reloc. */ | |
584 | rel->sym_ptr_ptr = NULL; | |
585 | } | |
586 | else | |
587 | { | |
588 | asection *sec; | |
589 | ||
590 | if (l_symndx == 0) | |
591 | sec = code_sec; | |
592 | else if (l_symndx == 1) | |
593 | sec = data_sec; | |
594 | else if (l_symndx == 2) | |
595 | sec = bss_sec; | |
596 | else | |
597 | { | |
598 | bfd_set_error (bfd_error_bad_value); | |
b34976b6 | 599 | return FALSE; |
252b5132 RH |
600 | } |
601 | ||
602 | rel->sym_ptr_ptr = sec->symbol_ptr_ptr; | |
603 | } | |
604 | ||
605 | rel->addend = 0; | |
606 | ||
607 | BFD_ASSERT ((l_rtype & 0xff) < HOWTO_COUNT); | |
608 | ||
609 | rel->howto = nlm_powerpc_howto_table + (l_rtype & 0xff); | |
610 | ||
611 | BFD_ASSERT (rel->howto->name != NULL | |
612 | && ((l_rtype & 0x8000) != 0 | |
613 | ? (rel->howto->complain_on_overflow | |
614 | == complain_overflow_signed) | |
615 | : (rel->howto->complain_on_overflow | |
616 | == complain_overflow_bitfield)) | |
617 | && ((l_rtype >> 8) & 0x1f) == rel->howto->bitsize - 1); | |
618 | ||
619 | if (l_rsecnm == 0) | |
620 | *secp = code_sec; | |
621 | else if (l_rsecnm == 1) | |
622 | { | |
623 | *secp = data_sec; | |
eea6121a | 624 | l_vaddr -= code_sec->size; |
252b5132 RH |
625 | } |
626 | else | |
627 | { | |
628 | bfd_set_error (bfd_error_bad_value); | |
b34976b6 | 629 | return FALSE; |
252b5132 RH |
630 | } |
631 | ||
632 | rel->address = l_vaddr; | |
633 | ||
b34976b6 | 634 | return TRUE; |
252b5132 RH |
635 | } |
636 | ||
637 | #endif /* OLDFORMAT */ | |
638 | ||
639 | /* Mangle PowerPC NLM relocs for output. */ | |
640 | ||
b34976b6 | 641 | static bfd_boolean |
252b5132 | 642 | nlm_powerpc_mangle_relocs (abfd, sec, data, offset, count) |
5f771d47 ILT |
643 | bfd *abfd ATTRIBUTE_UNUSED; |
644 | asection *sec ATTRIBUTE_UNUSED; | |
0f867abe | 645 | const PTR data ATTRIBUTE_UNUSED; |
5f771d47 ILT |
646 | bfd_vma offset ATTRIBUTE_UNUSED; |
647 | bfd_size_type count ATTRIBUTE_UNUSED; | |
252b5132 | 648 | { |
b34976b6 | 649 | return TRUE; |
252b5132 RH |
650 | } |
651 | ||
652 | /* Read a PowerPC NLM import record */ | |
653 | ||
b34976b6 | 654 | static bfd_boolean |
252b5132 RH |
655 | nlm_powerpc_read_import (abfd, sym) |
656 | bfd *abfd; | |
657 | nlmNAME(symbol_type) *sym; | |
658 | { | |
659 | struct nlm_relent *nlm_relocs; /* relocation records for symbol */ | |
660 | bfd_size_type rcount; /* number of relocs */ | |
661 | bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */ | |
662 | unsigned char symlength; /* length of symbol name */ | |
663 | char *name; | |
664 | ||
dc810e39 | 665 | if (bfd_bread ((PTR) &symlength, (bfd_size_type) sizeof (symlength), abfd) |
252b5132 | 666 | != sizeof (symlength)) |
b34976b6 | 667 | return FALSE; |
252b5132 | 668 | sym -> symbol.the_bfd = abfd; |
dc810e39 | 669 | name = bfd_alloc (abfd, (bfd_size_type) symlength + 1); |
252b5132 | 670 | if (name == NULL) |
b34976b6 | 671 | return FALSE; |
dc810e39 | 672 | if (bfd_bread (name, (bfd_size_type) symlength, abfd) != symlength) |
b34976b6 | 673 | return FALSE; |
252b5132 RH |
674 | name[symlength] = '\0'; |
675 | sym -> symbol.name = name; | |
676 | sym -> symbol.flags = 0; | |
677 | sym -> symbol.value = 0; | |
678 | sym -> symbol.section = bfd_und_section_ptr; | |
dc810e39 AM |
679 | if (bfd_bread ((PTR) temp, (bfd_size_type) sizeof (temp), abfd) |
680 | != sizeof (temp)) | |
b34976b6 | 681 | return FALSE; |
dc810e39 | 682 | rcount = H_GET_32 (abfd, temp); |
252b5132 RH |
683 | nlm_relocs = ((struct nlm_relent *) |
684 | bfd_alloc (abfd, rcount * sizeof (struct nlm_relent))); | |
685 | if (nlm_relocs == (struct nlm_relent *) NULL) | |
b34976b6 | 686 | return FALSE; |
252b5132 RH |
687 | sym -> relocs = nlm_relocs; |
688 | sym -> rcnt = 0; | |
689 | while (sym -> rcnt < rcount) | |
690 | { | |
691 | asection *section; | |
1518639e | 692 | |
82e51918 | 693 | if (! nlm_powerpc_read_reloc (abfd, sym, §ion, &nlm_relocs -> reloc)) |
b34976b6 | 694 | return FALSE; |
252b5132 RH |
695 | nlm_relocs -> section = section; |
696 | nlm_relocs++; | |
697 | sym -> rcnt++; | |
698 | } | |
b34976b6 | 699 | return TRUE; |
252b5132 RH |
700 | } |
701 | ||
702 | #ifndef OLDFORMAT | |
703 | ||
704 | /* Write a PowerPC NLM reloc. */ | |
705 | ||
b34976b6 | 706 | static bfd_boolean |
252b5132 RH |
707 | nlm_powerpc_write_import (abfd, sec, rel) |
708 | bfd *abfd; | |
709 | asection *sec; | |
710 | arelent *rel; | |
711 | { | |
712 | asymbol *sym; | |
713 | bfd_vma val; | |
714 | bfd_byte temp[4]; | |
715 | ||
716 | /* PowerPC NetWare only supports one kind of reloc. */ | |
717 | if (rel->addend != 0 | |
718 | || rel->howto == NULL | |
719 | || rel->howto->rightshift != 0 | |
720 | || rel->howto->size != 2 | |
721 | || rel->howto->bitsize != 32 | |
722 | || rel->howto->bitpos != 0 | |
723 | || rel->howto->pc_relative | |
724 | || (rel->howto->src_mask != 0xffffffff && rel->addend != 0) | |
725 | || rel->howto->dst_mask != 0xffffffff) | |
726 | { | |
727 | bfd_set_error (bfd_error_invalid_operation); | |
b34976b6 | 728 | return FALSE; |
252b5132 RH |
729 | } |
730 | ||
731 | sym = *rel->sym_ptr_ptr; | |
732 | ||
733 | /* The value we write out is the offset into the appropriate | |
734 | segment, rightshifted by two. This offset is the section vma, | |
735 | adjusted by the vma of the lowest section in that segment, plus | |
736 | the address of the relocation. */ | |
737 | val = bfd_get_section_vma (abfd, sec) + rel->address; | |
738 | if ((val & 3) != 0) | |
739 | { | |
740 | bfd_set_error (bfd_error_bad_value); | |
b34976b6 | 741 | return FALSE; |
252b5132 RH |
742 | } |
743 | val >>= 2; | |
744 | ||
745 | /* The high bit is 0 if the reloc is in the data section, or 1 if | |
746 | the reloc is in the code section. */ | |
747 | if (bfd_get_section_flags (abfd, sec) & SEC_DATA) | |
748 | val -= nlm_get_data_low (abfd); | |
749 | else | |
750 | { | |
751 | val -= nlm_get_text_low (abfd); | |
752 | val |= NLM_HIBIT; | |
753 | } | |
1518639e | 754 | |
252b5132 RH |
755 | if (! bfd_is_und_section (bfd_get_section (sym))) |
756 | { | |
757 | /* This is an internal relocation fixup. The second most | |
758 | significant bit is 0 if this is a reloc against the data | |
759 | segment, or 1 if it is a reloc against the text segment. */ | |
760 | if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE) | |
761 | val |= NLM_HIBIT >> 1; | |
762 | } | |
763 | ||
764 | bfd_put_32 (abfd, val, temp); | |
dc810e39 | 765 | if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp)) |
b34976b6 | 766 | return FALSE; |
252b5132 | 767 | |
b34976b6 | 768 | return TRUE; |
252b5132 RH |
769 | } |
770 | ||
771 | #else /* OLDFORMAT */ | |
772 | ||
773 | /* This is used for the reloc handling in the old format. */ | |
774 | ||
775 | /* Write a PowerPC NLM reloc. */ | |
776 | ||
b34976b6 | 777 | static bfd_boolean |
252b5132 RH |
778 | nlm_powerpc_write_reloc (abfd, sec, rel, indx) |
779 | bfd *abfd; | |
780 | asection *sec; | |
781 | arelent *rel; | |
782 | int indx; | |
783 | { | |
784 | struct nlm32_powerpc_external_reloc ext; | |
785 | asection *code_sec, *data_sec, *bss_sec; | |
786 | asymbol *sym; | |
787 | asection *symsec; | |
788 | unsigned long l_symndx; | |
789 | int l_rtype; | |
790 | int l_rsecnm; | |
791 | reloc_howto_type *howto; | |
792 | bfd_size_type address; | |
793 | ||
794 | /* Get the sections now, for convenience. */ | |
795 | code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME); | |
796 | data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME); | |
797 | bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME); | |
798 | ||
799 | sym = *rel->sym_ptr_ptr; | |
800 | symsec = bfd_get_section (sym); | |
801 | if (indx != -1) | |
802 | { | |
803 | BFD_ASSERT (bfd_is_und_section (symsec)); | |
804 | l_symndx = indx + 3; | |
805 | } | |
806 | else | |
807 | { | |
808 | if (symsec == code_sec) | |
809 | l_symndx = 0; | |
810 | else if (symsec == data_sec) | |
811 | l_symndx = 1; | |
812 | else if (symsec == bss_sec) | |
813 | l_symndx = 2; | |
814 | else | |
815 | { | |
816 | bfd_set_error (bfd_error_bad_value); | |
b34976b6 | 817 | return FALSE; |
252b5132 RH |
818 | } |
819 | } | |
820 | ||
dc810e39 | 821 | H_PUT_32 (abfd, l_symndx, ext.l_symndx); |
252b5132 RH |
822 | |
823 | for (howto = nlm_powerpc_howto_table; | |
824 | howto < nlm_powerpc_howto_table + HOWTO_COUNT; | |
825 | howto++) | |
826 | { | |
827 | if (howto->rightshift == rel->howto->rightshift | |
828 | && howto->size == rel->howto->size | |
829 | && howto->bitsize == rel->howto->bitsize | |
830 | && howto->pc_relative == rel->howto->pc_relative | |
831 | && howto->bitpos == rel->howto->bitpos | |
832 | && (howto->partial_inplace == rel->howto->partial_inplace | |
833 | || (! rel->howto->partial_inplace | |
834 | && rel->addend == 0)) | |
835 | && (howto->src_mask == rel->howto->src_mask | |
836 | || (rel->howto->src_mask == 0 | |
837 | && rel->addend == 0)) | |
838 | && howto->dst_mask == rel->howto->dst_mask | |
839 | && howto->pcrel_offset == rel->howto->pcrel_offset) | |
840 | break; | |
841 | } | |
842 | if (howto >= nlm_powerpc_howto_table + HOWTO_COUNT) | |
843 | { | |
844 | bfd_set_error (bfd_error_bad_value); | |
b34976b6 | 845 | return FALSE; |
252b5132 RH |
846 | } |
847 | ||
848 | l_rtype = howto->type; | |
849 | if (howto->complain_on_overflow == complain_overflow_signed) | |
850 | l_rtype |= 0x8000; | |
851 | l_rtype |= (howto->bitsize - 1) << 8; | |
dc810e39 | 852 | H_PUT_16 (abfd, l_rtype, ext.l_rtype); |
252b5132 RH |
853 | |
854 | address = rel->address; | |
855 | ||
856 | if (sec == code_sec) | |
857 | l_rsecnm = 0; | |
858 | else if (sec == data_sec) | |
859 | { | |
860 | l_rsecnm = 1; | |
eea6121a | 861 | address += code_sec->size; |
252b5132 RH |
862 | } |
863 | else | |
864 | { | |
865 | bfd_set_error (bfd_error_bad_value); | |
b34976b6 | 866 | return FALSE; |
252b5132 RH |
867 | } |
868 | ||
dc810e39 AM |
869 | H_PUT_16 (abfd, l_rsecnm, ext.l_rsecnm); |
870 | H_PUT_32 (abfd, address, ext.l_vaddr); | |
252b5132 | 871 | |
dc810e39 | 872 | if (bfd_bwrite (&ext, (bfd_size_type) sizeof ext, abfd) != sizeof ext) |
b34976b6 | 873 | return FALSE; |
252b5132 | 874 | |
b34976b6 | 875 | return TRUE; |
252b5132 RH |
876 | } |
877 | ||
878 | /* Write a PowerPC NLM import. */ | |
879 | ||
b34976b6 | 880 | static bfd_boolean |
252b5132 RH |
881 | nlm_powerpc_write_import (abfd, sec, rel) |
882 | bfd *abfd; | |
883 | asection *sec; | |
884 | arelent *rel; | |
885 | { | |
886 | return nlm_powerpc_write_reloc (abfd, sec, rel, -1); | |
887 | } | |
888 | ||
889 | #endif /* OLDFORMAT */ | |
890 | ||
891 | /* Write a PowerPC NLM external symbol. This routine keeps a static | |
892 | count of the symbol index. FIXME: I don't know if this is | |
893 | necessary, and the index never gets reset. */ | |
894 | ||
b34976b6 | 895 | static bfd_boolean |
252b5132 RH |
896 | nlm_powerpc_write_external (abfd, count, sym, relocs) |
897 | bfd *abfd; | |
898 | bfd_size_type count; | |
899 | asymbol *sym; | |
900 | struct reloc_and_sec *relocs; | |
901 | { | |
902 | unsigned int i; | |
903 | bfd_byte len; | |
904 | unsigned char temp[NLM_TARGET_LONG_SIZE]; | |
905 | #ifdef OLDFORMAT | |
906 | static int indx; | |
907 | #endif | |
908 | ||
909 | len = strlen (sym->name); | |
dc810e39 AM |
910 | if ((bfd_bwrite (&len, (bfd_size_type) sizeof (bfd_byte), abfd) |
911 | != sizeof (bfd_byte)) | |
912 | || bfd_bwrite (sym->name, (bfd_size_type) len, abfd) != len) | |
b34976b6 | 913 | return FALSE; |
252b5132 RH |
914 | |
915 | bfd_put_32 (abfd, count, temp); | |
dc810e39 | 916 | if (bfd_bwrite (temp, (bfd_size_type) sizeof (temp), abfd) != sizeof (temp)) |
b34976b6 | 917 | return FALSE; |
252b5132 RH |
918 | |
919 | for (i = 0; i < count; i++) | |
920 | { | |
921 | #ifndef OLDFORMAT | |
922 | if (! nlm_powerpc_write_import (abfd, relocs[i].sec, relocs[i].rel)) | |
b34976b6 | 923 | return FALSE; |
252b5132 RH |
924 | #else |
925 | if (! nlm_powerpc_write_reloc (abfd, relocs[i].sec, | |
926 | relocs[i].rel, indx)) | |
b34976b6 | 927 | return FALSE; |
252b5132 RH |
928 | #endif |
929 | } | |
930 | ||
931 | #ifdef OLDFORMAT | |
932 | ++indx; | |
933 | #endif | |
934 | ||
b34976b6 | 935 | return TRUE; |
252b5132 RH |
936 | } |
937 | \f | |
938 | #ifndef OLDFORMAT | |
939 | ||
940 | /* PowerPC Netware uses a word offset, not a byte offset, for public | |
941 | symbols. */ | |
942 | ||
943 | /* Set the section for a public symbol. */ | |
944 | ||
b34976b6 | 945 | static bfd_boolean |
252b5132 RH |
946 | nlm_powerpc_set_public_section (abfd, sym) |
947 | bfd *abfd; | |
948 | nlmNAME(symbol_type) *sym; | |
949 | { | |
950 | if (sym->symbol.value & NLM_HIBIT) | |
951 | { | |
952 | sym->symbol.value &= ~NLM_HIBIT; | |
953 | sym->symbol.flags |= BSF_FUNCTION; | |
954 | sym->symbol.section = | |
955 | bfd_get_section_by_name (abfd, NLM_CODE_NAME); | |
956 | } | |
957 | else | |
958 | { | |
959 | sym->symbol.section = | |
960 | bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME); | |
961 | } | |
962 | ||
963 | sym->symbol.value <<= 2; | |
964 | ||
b34976b6 | 965 | return TRUE; |
252b5132 RH |
966 | } |
967 | ||
968 | /* Get the offset to write out for a public symbol. */ | |
969 | ||
970 | static bfd_vma | |
971 | nlm_powerpc_get_public_offset (abfd, sym) | |
972 | bfd *abfd; | |
973 | asymbol *sym; | |
974 | { | |
975 | bfd_vma offset; | |
976 | asection *sec; | |
977 | ||
978 | offset = bfd_asymbol_value (sym); | |
979 | sec = bfd_get_section (sym); | |
980 | if (sec->flags & SEC_CODE) | |
981 | { | |
982 | offset -= nlm_get_text_low (abfd); | |
983 | offset |= NLM_HIBIT; | |
984 | } | |
985 | else if (sec->flags & (SEC_DATA | SEC_ALLOC)) | |
986 | { | |
987 | /* SEC_ALLOC is for the .bss section. */ | |
988 | offset -= nlm_get_data_low (abfd); | |
989 | } | |
990 | else | |
991 | { | |
992 | /* We can't handle an exported symbol that is not in the code or | |
993 | data segment. */ | |
994 | bfd_set_error (bfd_error_invalid_operation); | |
995 | /* FIXME: No way to return error. */ | |
996 | abort (); | |
997 | } | |
998 | ||
999 | return offset; | |
1000 | } | |
1001 | ||
1002 | #endif /* ! defined (OLDFORMAT) */ | |
1003 | \f | |
1004 | #include "nlmswap.h" | |
1005 | ||
1006 | static const struct nlm_backend_data nlm32_powerpc_backend = | |
1007 | { | |
1008 | "NetWare PowerPC Module \032", | |
1009 | sizeof (Nlm32_powerpc_External_Fixed_Header), | |
1010 | #ifndef OLDFORMAT | |
1011 | 0, /* optional_prefix_size */ | |
1012 | #else | |
1013 | sizeof (struct nlm32_powerpc_external_prefix_header), | |
1014 | #endif | |
1015 | bfd_arch_powerpc, | |
1016 | 0, | |
b34976b6 | 1017 | FALSE, |
252b5132 RH |
1018 | #ifndef OLDFORMAT |
1019 | 0, /* backend_object_p */ | |
1020 | 0, /* write_prefix */ | |
1021 | #else | |
1022 | nlm_powerpc_backend_object_p, | |
1023 | nlm_powerpc_write_prefix, | |
1024 | #endif | |
1025 | nlm_powerpc_read_reloc, | |
1026 | nlm_powerpc_mangle_relocs, | |
1027 | nlm_powerpc_read_import, | |
1028 | nlm_powerpc_write_import, | |
1029 | #ifndef OLDFORMAT | |
1030 | nlm_powerpc_set_public_section, | |
1031 | nlm_powerpc_get_public_offset, | |
1032 | #else | |
1033 | 0, /* set_public_section */ | |
1034 | 0, /* get_public_offset */ | |
1035 | #endif | |
1036 | nlm_swap_fixed_header_in, | |
1037 | nlm_swap_fixed_header_out, | |
1038 | nlm_powerpc_write_external, | |
1039 | 0, /* write_export */ | |
1040 | }; | |
1041 | ||
1042 | #define TARGET_BIG_NAME "nlm32-powerpc" | |
1043 | #define TARGET_BIG_SYM nlmNAME(powerpc_vec) | |
1044 | #define TARGET_BACKEND_DATA &nlm32_powerpc_backend | |
1045 | ||
1046 | #include "nlm-target.h" |