Commit | Line | Data |
---|---|---|
b3c0fc57 | 1 | /* MIPS-specific support for 32-bit ELF |
9783e04a | 2 | Copyright 1993, 1994 Free Software Foundation, Inc. |
6b4b4d17 | 3 | |
b3c0fc57 ILT |
4 | Most of the information added by Ian Lance Taylor, Cygnus Support, |
5 | <ian@cygnus.com>. | |
6 | ||
6b4b4d17 JK |
7 | This file is part of BFD, the Binary File Descriptor library. |
8 | ||
9 | This program is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License as published by | |
11 | the Free Software Foundation; either version 2 of the License, or | |
12 | (at your option) any later version. | |
13 | ||
14 | This program is distributed in the hope that it will be useful, | |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | GNU General Public License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
20 | along with this program; if not, write to the Free Software | |
21 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
22 | ||
23 | #include "bfd.h" | |
24 | #include "sysdep.h" | |
25 | #include "libbfd.h" | |
6e07e54f ILT |
26 | #include "bfdlink.h" |
27 | #include "genlink.h" | |
6b4b4d17 | 28 | #include "libelf.h" |
b3c0fc57 ILT |
29 | #include "elf/mips.h" |
30 | ||
6e07e54f ILT |
31 | /* Get the ECOFF swapping routines. */ |
32 | #include "coff/sym.h" | |
33 | #include "coff/symconst.h" | |
34 | #include "coff/internal.h" | |
35 | #include "coff/ecoff.h" | |
36 | #include "coff/mips.h" | |
37 | #define ECOFF_32 | |
38 | #include "ecoffswap.h" | |
39 | ||
b3c0fc57 ILT |
40 | static bfd_reloc_status_type mips_elf_hi16_reloc PARAMS ((bfd *abfd, |
41 | arelent *reloc, | |
42 | asymbol *symbol, | |
43 | PTR data, | |
44 | asection *section, | |
6e07e54f ILT |
45 | bfd *output_bfd, |
46 | char **error)); | |
47 | static bfd_reloc_status_type mips_elf_got16_reloc PARAMS ((bfd *abfd, | |
48 | arelent *reloc, | |
49 | asymbol *symbol, | |
50 | PTR data, | |
51 | asection *section, | |
52 | bfd *output_bfd, | |
53 | char **error)); | |
b3c0fc57 ILT |
54 | static bfd_reloc_status_type mips_elf_lo16_reloc PARAMS ((bfd *abfd, |
55 | arelent *reloc, | |
56 | asymbol *symbol, | |
57 | PTR data, | |
58 | asection *section, | |
6e07e54f ILT |
59 | bfd *output_bfd, |
60 | char **error)); | |
b3c0fc57 ILT |
61 | static bfd_reloc_status_type mips_elf_gprel16_reloc PARAMS ((bfd *abfd, |
62 | arelent *reloc, | |
63 | asymbol *symbol, | |
64 | PTR data, | |
65 | asection *section, | |
6e07e54f ILT |
66 | bfd *output_bfd, |
67 | char **error)); | |
b3c0fc57 ILT |
68 | |
69 | #define USE_REL 1 /* MIPS uses REL relocations instead of RELA */ | |
70 | ||
71 | enum reloc_type | |
72 | { | |
73 | R_MIPS_NONE = 0, | |
74 | R_MIPS_16, R_MIPS_32, | |
75 | R_MIPS_REL32, R_MIPS_26, | |
76 | R_MIPS_HI16, R_MIPS_LO16, | |
77 | R_MIPS_GPREL16, R_MIPS_LITERAL, | |
78 | R_MIPS_GOT16, R_MIPS_PC16, | |
79 | R_MIPS_CALL16, R_MIPS_GPREL32, | |
80 | R_MIPS_max | |
81 | }; | |
82 | ||
83 | static reloc_howto_type elf_mips_howto_table[] = | |
84 | { | |
85 | /* No relocation. */ | |
86 | HOWTO (R_MIPS_NONE, /* type */ | |
87 | 0, /* rightshift */ | |
88 | 0, /* size (0 = byte, 1 = short, 2 = long) */ | |
89 | 0, /* bitsize */ | |
90 | false, /* pc_relative */ | |
91 | 0, /* bitpos */ | |
92 | complain_overflow_dont, /* complain_on_overflow */ | |
93 | bfd_elf_generic_reloc, /* special_function */ | |
94 | "R_MIPS_NONE", /* name */ | |
95 | false, /* partial_inplace */ | |
96 | 0, /* src_mask */ | |
97 | 0, /* dst_mask */ | |
98 | false), /* pcrel_offset */ | |
99 | ||
100 | /* 16 bit relocation. */ | |
101 | HOWTO (R_MIPS_16, /* type */ | |
102 | 0, /* rightshift */ | |
103 | 1, /* size (0 = byte, 1 = short, 2 = long) */ | |
104 | 16, /* bitsize */ | |
105 | false, /* pc_relative */ | |
106 | 0, /* bitpos */ | |
107 | complain_overflow_bitfield, /* complain_on_overflow */ | |
108 | bfd_elf_generic_reloc, /* special_function */ | |
109 | "R_MIPS_16", /* name */ | |
110 | true, /* partial_inplace */ | |
111 | 0xffff, /* src_mask */ | |
112 | 0xffff, /* dst_mask */ | |
113 | false), /* pcrel_offset */ | |
114 | ||
115 | /* 32 bit relocation. */ | |
116 | HOWTO (R_MIPS_32, /* type */ | |
117 | 0, /* rightshift */ | |
118 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
119 | 32, /* bitsize */ | |
120 | false, /* pc_relative */ | |
121 | 0, /* bitpos */ | |
122 | complain_overflow_bitfield, /* complain_on_overflow */ | |
123 | bfd_elf_generic_reloc, /* special_function */ | |
124 | "R_MIPS_32", /* name */ | |
125 | true, /* partial_inplace */ | |
126 | 0xffffffff, /* src_mask */ | |
127 | 0xffffffff, /* dst_mask */ | |
128 | false), /* pcrel_offset */ | |
129 | ||
130 | /* 32 bit symbol relative relocation. */ | |
131 | HOWTO (R_MIPS_REL32, /* type */ | |
132 | 0, /* rightshift */ | |
133 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
134 | 32, /* bitsize */ | |
135 | false, /* pc_relative */ | |
136 | 0, /* bitpos */ | |
137 | complain_overflow_bitfield, /* complain_on_overflow */ | |
138 | bfd_elf_generic_reloc, /* special_function */ | |
139 | "R_MIPS_REL32", /* name */ | |
140 | true, /* partial_inplace */ | |
141 | 0xffffffff, /* src_mask */ | |
142 | 0xffffffff, /* dst_mask */ | |
143 | false), /* pcrel_offset */ | |
144 | ||
145 | /* 26 bit branch address. */ | |
146 | HOWTO (R_MIPS_26, /* type */ | |
147 | 2, /* rightshift */ | |
148 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
149 | 26, /* bitsize */ | |
150 | false, /* pc_relative */ | |
151 | 0, /* bitpos */ | |
6e07e54f ILT |
152 | complain_overflow_dont, /* complain_on_overflow */ |
153 | /* This needs complex overflow | |
154 | detection, because the upper four | |
155 | bits must match the PC. */ | |
b3c0fc57 ILT |
156 | bfd_elf_generic_reloc, /* special_function */ |
157 | "R_MIPS_26", /* name */ | |
158 | true, /* partial_inplace */ | |
159 | 0x3ffffff, /* src_mask */ | |
160 | 0x3ffffff, /* dst_mask */ | |
161 | false), /* pcrel_offset */ | |
162 | ||
163 | /* High 16 bits of symbol value. */ | |
164 | HOWTO (R_MIPS_HI16, /* type */ | |
165 | 0, /* rightshift */ | |
166 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
167 | 16, /* bitsize */ | |
168 | false, /* pc_relative */ | |
169 | 0, /* bitpos */ | |
170 | complain_overflow_dont, /* complain_on_overflow */ | |
171 | mips_elf_hi16_reloc, /* special_function */ | |
172 | "R_MIPS_HI16", /* name */ | |
173 | true, /* partial_inplace */ | |
174 | 0xffff, /* src_mask */ | |
175 | 0xffff, /* dst_mask */ | |
176 | false), /* pcrel_offset */ | |
177 | ||
178 | /* Low 16 bits of symbol value. */ | |
179 | HOWTO (R_MIPS_LO16, /* type */ | |
180 | 0, /* rightshift */ | |
181 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
182 | 16, /* bitsize */ | |
183 | false, /* pc_relative */ | |
184 | 0, /* bitpos */ | |
185 | complain_overflow_dont, /* complain_on_overflow */ | |
186 | mips_elf_lo16_reloc, /* special_function */ | |
187 | "R_MIPS_LO16", /* name */ | |
188 | true, /* partial_inplace */ | |
189 | 0xffff, /* src_mask */ | |
190 | 0xffff, /* dst_mask */ | |
191 | false), /* pcrel_offset */ | |
192 | ||
193 | /* GP relative reference. */ | |
194 | HOWTO (R_MIPS_GPREL16, /* type */ | |
195 | 0, /* rightshift */ | |
196 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
197 | 16, /* bitsize */ | |
198 | false, /* pc_relative */ | |
199 | 0, /* bitpos */ | |
200 | complain_overflow_signed, /* complain_on_overflow */ | |
201 | mips_elf_gprel16_reloc, /* special_function */ | |
202 | "R_MIPS_GPREL16", /* name */ | |
203 | true, /* partial_inplace */ | |
204 | 0xffff, /* src_mask */ | |
205 | 0xffff, /* dst_mask */ | |
206 | false), /* pcrel_offset */ | |
207 | ||
208 | /* Reference to literal section. */ | |
209 | HOWTO (R_MIPS_LITERAL, /* type */ | |
210 | 0, /* rightshift */ | |
211 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
212 | 16, /* bitsize */ | |
213 | false, /* pc_relative */ | |
214 | 0, /* bitpos */ | |
215 | complain_overflow_signed, /* complain_on_overflow */ | |
216 | mips_elf_gprel16_reloc, /* special_function */ | |
217 | "R_MIPS_LITERAL", /* name */ | |
218 | true, /* partial_inplace */ | |
219 | 0xffff, /* src_mask */ | |
220 | 0xffff, /* dst_mask */ | |
221 | false), /* pcrel_offset */ | |
222 | ||
223 | /* Reference to global offset table. */ | |
224 | /* FIXME: This is not handled correctly. */ | |
225 | HOWTO (R_MIPS_GOT16, /* type */ | |
226 | 0, /* rightshift */ | |
227 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
228 | 16, /* bitsize */ | |
229 | false, /* pc_relative */ | |
230 | 0, /* bitpos */ | |
231 | complain_overflow_signed, /* complain_on_overflow */ | |
6e07e54f | 232 | mips_elf_got16_reloc, /* special_function */ |
b3c0fc57 ILT |
233 | "R_MIPS_GOT16", /* name */ |
234 | false, /* partial_inplace */ | |
235 | 0, /* src_mask */ | |
236 | 0xffff, /* dst_mask */ | |
237 | false), /* pcrel_offset */ | |
238 | ||
239 | /* 16 bit PC relative reference. */ | |
240 | HOWTO (R_MIPS_PC16, /* type */ | |
241 | 0, /* rightshift */ | |
242 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
243 | 16, /* bitsize */ | |
244 | true, /* pc_relative */ | |
245 | 0, /* bitpos */ | |
246 | complain_overflow_signed, /* complain_on_overflow */ | |
247 | bfd_elf_generic_reloc, /* special_function */ | |
248 | "R_MIPS_PC16", /* name */ | |
249 | true, /* partial_inplace */ | |
250 | 0xffff, /* src_mask */ | |
251 | 0xffff, /* dst_mask */ | |
252 | false), /* pcrel_offset */ | |
253 | ||
254 | /* 16 bit call through global offset table. */ | |
255 | /* FIXME: This is not handled correctly. */ | |
256 | HOWTO (R_MIPS_CALL16, /* type */ | |
257 | 0, /* rightshift */ | |
258 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
259 | 16, /* bitsize */ | |
260 | false, /* pc_relative */ | |
261 | 0, /* bitpos */ | |
262 | complain_overflow_signed, /* complain_on_overflow */ | |
263 | bfd_elf_generic_reloc, /* special_function */ | |
264 | "R_MIPS_CALL16", /* name */ | |
265 | false, /* partial_inplace */ | |
266 | 0, /* src_mask */ | |
267 | 0xffff, /* dst_mask */ | |
268 | false), /* pcrel_offset */ | |
269 | ||
270 | /* 32 bit GP relative reference. */ | |
271 | /* FIXME: This is not handled correctly. */ | |
272 | HOWTO (R_MIPS_GPREL32, /* type */ | |
273 | 0, /* rightshift */ | |
274 | 2, /* size (0 = byte, 1 = short, 2 = long) */ | |
275 | 32, /* bitsize */ | |
276 | false, /* pc_relative */ | |
277 | 0, /* bitpos */ | |
278 | complain_overflow_bitfield, /* complain_on_overflow */ | |
279 | bfd_elf_generic_reloc, /* special_function */ | |
280 | "R_MIPS_GPREL32", /* name */ | |
281 | true, /* partial_inplace */ | |
282 | 0xffffffff, /* src_mask */ | |
283 | 0xffffffff, /* dst_mask */ | |
284 | false) /* pcrel_offset */ | |
285 | }; | |
286 | ||
287 | /* Do a R_MIPS_HI16 relocation. This has to be done in combination | |
288 | with a R_MIPS_LO16 reloc, because there is a carry from the LO16 to | |
289 | the HI16. Here we just save the information we need; we do the | |
290 | actual relocation when we see the LO16. MIPS ELF requires that the | |
291 | LO16 immediately follow the HI16, so this ought to work. */ | |
292 | ||
293 | static bfd_byte *mips_hi16_addr; | |
294 | static bfd_vma mips_hi16_addend; | |
295 | ||
296 | static bfd_reloc_status_type | |
297 | mips_elf_hi16_reloc (abfd, | |
298 | reloc_entry, | |
299 | symbol, | |
300 | data, | |
301 | input_section, | |
6e07e54f ILT |
302 | output_bfd, |
303 | error_message) | |
b3c0fc57 ILT |
304 | bfd *abfd; |
305 | arelent *reloc_entry; | |
306 | asymbol *symbol; | |
307 | PTR data; | |
308 | asection *input_section; | |
309 | bfd *output_bfd; | |
6e07e54f | 310 | char **error_message; |
b3c0fc57 ILT |
311 | { |
312 | bfd_reloc_status_type ret; | |
313 | bfd_vma relocation; | |
314 | ||
b3c0fc57 ILT |
315 | /* If we're relocating, and this an external symbol, we don't want |
316 | to change anything. */ | |
317 | if (output_bfd != (bfd *) NULL | |
318 | && (symbol->flags & BSF_SECTION_SYM) == 0 | |
319 | && reloc_entry->addend == 0) | |
320 | { | |
321 | reloc_entry->address += input_section->output_offset; | |
322 | return bfd_reloc_ok; | |
323 | } | |
324 | ||
6e07e54f ILT |
325 | /* FIXME: The symbol _gp_disp requires special handling, which we do |
326 | not do. */ | |
327 | if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0) | |
328 | abort (); | |
329 | ||
b3c0fc57 ILT |
330 | ret = bfd_reloc_ok; |
331 | if (symbol->section == &bfd_und_section | |
332 | && output_bfd == (bfd *) NULL) | |
333 | ret = bfd_reloc_undefined; | |
334 | ||
335 | if (bfd_is_com_section (symbol->section)) | |
336 | relocation = 0; | |
337 | else | |
338 | relocation = symbol->value; | |
339 | ||
340 | relocation += symbol->section->output_section->vma; | |
341 | relocation += symbol->section->output_offset; | |
342 | relocation += reloc_entry->addend; | |
343 | ||
344 | if (reloc_entry->address > input_section->_cooked_size) | |
345 | return bfd_reloc_outofrange; | |
346 | ||
347 | /* Save the information, and let LO16 do the actual relocation. */ | |
348 | mips_hi16_addr = (bfd_byte *) data + reloc_entry->address; | |
349 | mips_hi16_addend = relocation; | |
350 | ||
351 | if (output_bfd != (bfd *) NULL) | |
352 | reloc_entry->address += input_section->output_offset; | |
353 | ||
354 | return ret; | |
355 | } | |
356 | ||
357 | /* Do a R_MIPS_LO16 relocation. This is a straightforward 16 bit | |
358 | inplace relocation; this function exists in order to do the | |
359 | R_MIPS_HI16 relocation described above. */ | |
360 | ||
361 | static bfd_reloc_status_type | |
362 | mips_elf_lo16_reloc (abfd, | |
363 | reloc_entry, | |
364 | symbol, | |
365 | data, | |
366 | input_section, | |
6e07e54f ILT |
367 | output_bfd, |
368 | error_message) | |
b3c0fc57 ILT |
369 | bfd *abfd; |
370 | arelent *reloc_entry; | |
371 | asymbol *symbol; | |
372 | PTR data; | |
373 | asection *input_section; | |
374 | bfd *output_bfd; | |
6e07e54f | 375 | char **error_message; |
b3c0fc57 ILT |
376 | { |
377 | /* FIXME: The symbol _gp_disp requires special handling, which we do | |
378 | not do. */ | |
6e07e54f ILT |
379 | if (output_bfd == (bfd *) NULL |
380 | && strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0) | |
b3c0fc57 ILT |
381 | abort (); |
382 | ||
383 | if (mips_hi16_addr != (bfd_byte *) NULL) | |
384 | { | |
385 | unsigned long insn; | |
386 | unsigned long val; | |
387 | unsigned long vallo; | |
388 | ||
389 | /* Do the HI16 relocation. Note that we actually don't need to | |
390 | know anything about the LO16 itself, except where to find the | |
391 | low 16 bits of the addend needed by the LO16. */ | |
392 | insn = bfd_get_32 (abfd, mips_hi16_addr); | |
393 | vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address) | |
394 | & 0xffff); | |
395 | val = ((insn & 0xffff) << 16) + vallo; | |
396 | val += mips_hi16_addend; | |
397 | ||
398 | /* The low order 16 bits are always treated as a signed value. | |
399 | Therefore, a negative value in the low order bits requires an | |
400 | adjustment in the high order bits. We need to make this | |
401 | adjustment in two ways: once for the bits we took from the | |
402 | data, and once for the bits we are putting back in to the | |
403 | data. */ | |
404 | if ((vallo & 0x8000) != 0) | |
405 | val -= 0x10000; | |
406 | if ((val & 0x8000) != 0) | |
407 | val += 0x10000; | |
408 | ||
409 | insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff); | |
410 | bfd_put_32 (abfd, insn, mips_hi16_addr); | |
411 | ||
412 | mips_hi16_addr = (bfd_byte *) NULL; | |
413 | } | |
414 | ||
415 | /* Now do the LO16 reloc in the usual way. */ | |
416 | return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, | |
6e07e54f ILT |
417 | input_section, output_bfd, error_message); |
418 | } | |
419 | ||
420 | /* Do a R_MIPS_GOT16 reloc. This is a reloc against the global offset | |
421 | table used for PIC code. If the symbol is an external symbol, the | |
422 | instruction is modified to contain the offset of the appropriate | |
423 | entry in the global offset table. If the symbol is a section | |
424 | symbol, the next reloc is a R_MIPS_LO16 reloc. The two 16 bit | |
425 | addends are combined to form the real addend against the section | |
426 | symbol; the GOT16 is modified to contain the offset of an entry in | |
427 | the global offset table, and the LO16 is modified to offset it | |
428 | appropriately. Thus an offset larger than 16 bits requires a | |
429 | modified value in the global offset table. | |
430 | ||
431 | This implementation suffices for the assembler, but the linker does | |
432 | not yet know how to create global offset tables. */ | |
433 | ||
434 | static bfd_reloc_status_type | |
435 | mips_elf_got16_reloc (abfd, | |
436 | reloc_entry, | |
437 | symbol, | |
438 | data, | |
439 | input_section, | |
440 | output_bfd, | |
441 | error_message) | |
442 | bfd *abfd; | |
443 | arelent *reloc_entry; | |
444 | asymbol *symbol; | |
445 | PTR data; | |
446 | asection *input_section; | |
447 | bfd *output_bfd; | |
448 | char **error_message; | |
449 | { | |
450 | /* If we're relocating, and this an external symbol, we don't want | |
451 | to change anything. */ | |
452 | if (output_bfd != (bfd *) NULL | |
453 | && (symbol->flags & BSF_SECTION_SYM) == 0 | |
454 | && reloc_entry->addend == 0) | |
455 | { | |
456 | reloc_entry->address += input_section->output_offset; | |
457 | return bfd_reloc_ok; | |
458 | } | |
459 | ||
460 | /* If we're relocating, and this is a local symbol, we can handle it | |
461 | just like HI16. */ | |
462 | if (output_bfd != (bfd *) NULL | |
463 | && (symbol->flags & BSF_SECTION_SYM) != 0) | |
464 | return mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data, | |
465 | input_section, output_bfd, error_message); | |
466 | ||
467 | abort (); | |
b3c0fc57 ILT |
468 | } |
469 | ||
470 | /* Do a R_MIPS_GPREL16 relocation. This is a 16 bit value which must | |
471 | become the offset from the gp register. This function also handles | |
472 | R_MIPS_LITERAL relocations, although those can be handled more | |
473 | cleverly because the entries in the .lit8 and .lit4 sections can be | |
474 | merged. */ | |
475 | ||
476 | static bfd_reloc_status_type | |
477 | mips_elf_gprel16_reloc (abfd, | |
478 | reloc_entry, | |
479 | symbol, | |
480 | data, | |
481 | input_section, | |
6e07e54f ILT |
482 | output_bfd, |
483 | error_message) | |
b3c0fc57 ILT |
484 | bfd *abfd; |
485 | arelent *reloc_entry; | |
486 | asymbol *symbol; | |
487 | PTR data; | |
488 | asection *input_section; | |
489 | bfd *output_bfd; | |
6e07e54f | 490 | char **error_message; |
b3c0fc57 ILT |
491 | { |
492 | boolean relocateable; | |
493 | bfd_vma relocation; | |
494 | unsigned long val; | |
495 | unsigned long insn; | |
496 | ||
497 | /* If we're relocating, and this is an external symbol with no | |
498 | addend, we don't want to change anything. We will only have an | |
499 | addend if this is a newly created reloc, not read from an ELF | |
500 | file. */ | |
501 | if (output_bfd != (bfd *) NULL | |
502 | && (symbol->flags & BSF_SECTION_SYM) == 0 | |
503 | && reloc_entry->addend == 0) | |
504 | { | |
505 | reloc_entry->address += input_section->output_offset; | |
506 | return bfd_reloc_ok; | |
507 | } | |
508 | ||
509 | if (output_bfd != (bfd *) NULL) | |
510 | relocateable = true; | |
511 | else | |
512 | { | |
513 | relocateable = false; | |
514 | output_bfd = symbol->section->output_section->owner; | |
515 | } | |
516 | ||
517 | if (symbol->section == &bfd_und_section | |
518 | && relocateable == false) | |
519 | return bfd_reloc_undefined; | |
520 | ||
521 | /* We have to figure out the gp value, so that we can adjust the | |
522 | symbol value correctly. We look up the symbol _gp in the output | |
523 | BFD. If we can't find it, we're stuck. We cache it in the ELF | |
524 | target data. We don't need to adjust the symbol value for an | |
525 | external symbol if we are producing relocateable output. */ | |
526 | if (elf_gp (output_bfd) == 0 | |
527 | && (relocateable == false | |
528 | || (symbol->flags & BSF_SECTION_SYM) != 0)) | |
529 | { | |
530 | if (relocateable != false) | |
531 | { | |
532 | /* Make up a value. */ | |
533 | elf_gp (output_bfd) = | |
534 | symbol->section->output_section->vma + 0x4000; | |
535 | } | |
536 | else | |
537 | { | |
538 | unsigned int count; | |
539 | asymbol **sym; | |
540 | unsigned int i; | |
541 | ||
542 | count = bfd_get_symcount (output_bfd); | |
543 | sym = bfd_get_outsymbols (output_bfd); | |
544 | ||
545 | if (sym == (asymbol **) NULL) | |
546 | i = count; | |
547 | else | |
548 | { | |
549 | for (i = 0; i < count; i++, sym++) | |
550 | { | |
551 | register CONST char *name; | |
552 | ||
553 | name = bfd_asymbol_name (*sym); | |
554 | if (*name == '_' && strcmp (name, "_gp") == 0) | |
555 | { | |
556 | elf_gp (output_bfd) = bfd_asymbol_value (*sym); | |
557 | break; | |
558 | } | |
559 | } | |
560 | } | |
561 | ||
562 | if (i >= count) | |
563 | { | |
564 | /* Only get the error once. */ | |
565 | elf_gp (output_bfd) = 4; | |
6e07e54f ILT |
566 | *error_message = |
567 | (char *) "GP relative relocation when _gp not defined"; | |
b3c0fc57 ILT |
568 | return bfd_reloc_dangerous; |
569 | } | |
570 | } | |
571 | } | |
572 | ||
573 | if (bfd_is_com_section (symbol->section)) | |
574 | relocation = 0; | |
575 | else | |
576 | relocation = symbol->value; | |
577 | ||
578 | relocation += symbol->section->output_section->vma; | |
579 | relocation += symbol->section->output_offset; | |
580 | ||
581 | if (reloc_entry->address > input_section->_cooked_size) | |
582 | return bfd_reloc_outofrange; | |
583 | ||
584 | insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); | |
585 | ||
586 | /* Set val to the offset into the section or symbol. */ | |
587 | val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff; | |
588 | if (val & 0x8000) | |
589 | val -= 0x10000; | |
590 | ||
591 | /* Adjust val for the final section location and GP value. If we | |
592 | are producing relocateable output, we don't want to do this for | |
593 | an external symbol. */ | |
594 | if (relocateable == false | |
595 | || (symbol->flags & BSF_SECTION_SYM) != 0) | |
596 | val += relocation - elf_gp (output_bfd); | |
597 | ||
598 | insn = (insn &~ 0xffff) | (val & 0xffff); | |
599 | bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address); | |
600 | ||
601 | if (relocateable != false) | |
602 | reloc_entry->address += input_section->output_offset; | |
603 | ||
604 | /* Make sure it fit in 16 bits. */ | |
605 | if (val >= 0x8000 && val < 0xffff8000) | |
6e07e54f | 606 | return bfd_reloc_overflow; |
b3c0fc57 ILT |
607 | |
608 | return bfd_reloc_ok; | |
609 | } | |
6b4b4d17 | 610 | |
b3c0fc57 | 611 | /* A mapping from BFD reloc types to MIPS ELF reloc types. */ |
6b4b4d17 | 612 | |
b3c0fc57 ILT |
613 | struct elf_reloc_map { |
614 | bfd_reloc_code_real_type bfd_reloc_val; | |
615 | enum reloc_type elf_reloc_val; | |
616 | }; | |
617 | ||
618 | static CONST struct elf_reloc_map mips_reloc_map[] = | |
619 | { | |
620 | { BFD_RELOC_NONE, R_MIPS_NONE, }, | |
621 | { BFD_RELOC_16, R_MIPS_16 }, | |
622 | { BFD_RELOC_32, R_MIPS_32 }, | |
623 | { BFD_RELOC_CTOR, R_MIPS_32 }, | |
624 | { BFD_RELOC_32_PCREL, R_MIPS_REL32 }, | |
625 | { BFD_RELOC_MIPS_JMP, R_MIPS_26 }, | |
626 | { BFD_RELOC_HI16_S, R_MIPS_HI16 }, | |
627 | { BFD_RELOC_LO16, R_MIPS_LO16 }, | |
628 | { BFD_RELOC_MIPS_GPREL, R_MIPS_GPREL16 }, | |
629 | { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL }, | |
630 | { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 }, | |
631 | { BFD_RELOC_16_PCREL, R_MIPS_PC16 }, | |
632 | { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 }, | |
633 | { BFD_RELOC_MIPS_GPREL32, R_MIPS_GPREL32 } | |
634 | }; | |
635 | ||
636 | /* Given a BFD reloc type, return a howto structure. */ | |
637 | ||
638 | static CONST struct reloc_howto_struct * | |
639 | bfd_elf32_bfd_reloc_type_lookup (abfd, code) | |
640 | bfd *abfd; | |
641 | bfd_reloc_code_real_type code; | |
642 | { | |
643 | int i; | |
644 | ||
645 | for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); i++) | |
646 | { | |
647 | if (mips_reloc_map[i].bfd_reloc_val == code) | |
648 | return &elf_mips_howto_table[(int) mips_reloc_map[i].elf_reloc_val]; | |
649 | } | |
650 | return NULL; | |
651 | } | |
652 | ||
653 | /* Given a MIPS reloc type, fill in an arelent structure. */ | |
654 | ||
655 | static void | |
656 | mips_info_to_howto_rel (abfd, cache_ptr, dst) | |
657 | bfd *abfd; | |
658 | arelent *cache_ptr; | |
659 | Elf32_Internal_Rel *dst; | |
660 | { | |
661 | unsigned int r_type; | |
662 | ||
663 | r_type = ELF32_R_TYPE (dst->r_info); | |
664 | BFD_ASSERT (r_type < (unsigned int) R_MIPS_max); | |
665 | cache_ptr->howto = &elf_mips_howto_table[r_type]; | |
666 | ||
667 | /* The addend for a GPREL16 or LITERAL relocation comes from the GP | |
668 | value for the object file. We get the addend now, rather than | |
669 | when we do the relocation, because the symbol manipulations done | |
670 | by the linker may cause us to lose track of the input BFD. */ | |
671 | if (((*cache_ptr->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0 | |
672 | && (r_type == (unsigned int) R_MIPS_GPREL16 | |
673 | || r_type == (unsigned int) R_MIPS_LITERAL)) | |
674 | cache_ptr->addend = elf_gp (abfd); | |
675 | } | |
676 | \f | |
677 | /* A .reginfo section holds a single Elf32_RegInfo structure. These | |
678 | routines swap this structure in and out. They are used outside of | |
679 | BFD, so they are globally visible. */ | |
680 | ||
681 | void | |
682 | bfd_mips_elf32_swap_reginfo_in (abfd, ex, in) | |
683 | bfd *abfd; | |
684 | const Elf32_External_RegInfo *ex; | |
685 | Elf32_RegInfo *in; | |
686 | { | |
687 | in->ri_gprmask = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_gprmask); | |
688 | in->ri_cprmask[0] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[0]); | |
689 | in->ri_cprmask[1] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[1]); | |
690 | in->ri_cprmask[2] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[2]); | |
691 | in->ri_cprmask[3] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[3]); | |
692 | in->ri_gp_value = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_gp_value); | |
693 | } | |
694 | ||
695 | void | |
696 | bfd_mips_elf32_swap_reginfo_out (abfd, in, ex) | |
697 | bfd *abfd; | |
698 | const Elf32_RegInfo *in; | |
699 | Elf32_External_RegInfo *ex; | |
700 | { | |
701 | bfd_h_put_32 (abfd, (bfd_vma) in->ri_gprmask, | |
702 | (bfd_byte *) ex->ri_gprmask); | |
703 | bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[0], | |
704 | (bfd_byte *) ex->ri_cprmask[0]); | |
705 | bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[1], | |
706 | (bfd_byte *) ex->ri_cprmask[1]); | |
707 | bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[2], | |
708 | (bfd_byte *) ex->ri_cprmask[2]); | |
709 | bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[3], | |
710 | (bfd_byte *) ex->ri_cprmask[3]); | |
711 | bfd_h_put_32 (abfd, (bfd_vma) in->ri_gp_value, | |
712 | (bfd_byte *) ex->ri_gp_value); | |
713 | } | |
714 | \f | |
6e07e54f ILT |
715 | /* Determine whether a symbol is global for the purposes of splitting |
716 | the symbol table into global symbols and local symbols. At least | |
717 | on Irix 5, this split must be between section symbols and all other | |
718 | symbols. On most ELF targets the split is between static symbols | |
719 | and externally visible symbols. */ | |
720 | ||
721 | /*ARGSUSED*/ | |
722 | static boolean | |
723 | mips_elf_sym_is_global (abfd, sym) | |
724 | bfd *abfd; | |
725 | asymbol *sym; | |
726 | { | |
727 | return (sym->flags & BSF_SECTION_SYM) == 0 ? true : false; | |
728 | } | |
729 | \f | |
730 | /* Set the right machine number for a MIPS ELF file. */ | |
731 | ||
732 | static boolean | |
733 | mips_elf_object_p (abfd) | |
734 | bfd *abfd; | |
735 | { | |
736 | switch (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) | |
737 | { | |
738 | default: | |
739 | case E_MIPS_ARCH_1: | |
740 | /* Just use the default, which was set in elfcode.h. */ | |
741 | break; | |
742 | ||
743 | case E_MIPS_ARCH_2: | |
744 | (void) bfd_default_set_arch_mach (abfd, bfd_arch_mips, 6000); | |
745 | break; | |
746 | ||
747 | case E_MIPS_ARCH_3: | |
748 | (void) bfd_default_set_arch_mach (abfd, bfd_arch_mips, 4000); | |
749 | break; | |
750 | } | |
751 | ||
752 | return true; | |
753 | } | |
754 | ||
755 | /* The final processing done just before writing out a MIPS ELF object | |
756 | file. This gets the MIPS architecture right based on the machine | |
757 | number. */ | |
758 | ||
759 | static void | |
760 | mips_elf_final_write_processing (abfd) | |
761 | bfd *abfd; | |
762 | { | |
763 | unsigned long val; | |
764 | ||
765 | switch (bfd_get_mach (abfd)) | |
766 | { | |
767 | case 3000: | |
768 | val = E_MIPS_ARCH_1; | |
769 | break; | |
770 | ||
771 | case 6000: | |
772 | val = E_MIPS_ARCH_2; | |
773 | break; | |
774 | ||
775 | case 4000: | |
776 | val = E_MIPS_ARCH_3; | |
777 | break; | |
778 | ||
779 | default: | |
780 | return; | |
781 | } | |
782 | ||
783 | elf_elfheader (abfd)->e_flags &=~ EF_MIPS_ARCH; | |
784 | elf_elfheader (abfd)->e_flags |= val; | |
785 | } | |
786 | \f | |
b3c0fc57 ILT |
787 | /* Handle a MIPS specific section when reading an object file. This |
788 | is called when elfcode.h finds a section with an unknown type. | |
789 | FIXME: We need to handle the SHF_MIPS_GPREL flag, but I'm not sure | |
790 | how to. */ | |
791 | ||
792 | static boolean | |
793 | mips_elf_section_from_shdr (abfd, hdr, name) | |
794 | bfd *abfd; | |
795 | Elf32_Internal_Shdr *hdr; | |
796 | char *name; | |
797 | { | |
798 | /* There ought to be a place to keep ELF backend specific flags, but | |
799 | at the moment there isn't one. We just keep track of the | |
800 | sections by their name, instead. Fortunately, the ABI gives | |
801 | suggested names for all the MIPS specific sections, so we will | |
802 | probably get away with this. */ | |
803 | switch (hdr->sh_type) | |
804 | { | |
805 | case SHT_MIPS_LIBLIST: | |
806 | if (strcmp (name, ".liblist") != 0) | |
807 | return false; | |
808 | break; | |
809 | case SHT_MIPS_CONFLICT: | |
810 | if (strcmp (name, ".conflict") != 0) | |
811 | return false; | |
812 | break; | |
813 | case SHT_MIPS_GPTAB: | |
814 | if (strncmp (name, ".gptab.", sizeof ".gptab." - 1) != 0) | |
815 | return false; | |
816 | break; | |
817 | case SHT_MIPS_UCODE: | |
818 | if (strcmp (name, ".ucode") != 0) | |
819 | return false; | |
820 | break; | |
821 | case SHT_MIPS_DEBUG: | |
822 | if (strcmp (name, ".mdebug") != 0) | |
823 | return false; | |
824 | break; | |
825 | case SHT_MIPS_REGINFO: | |
826 | if (strcmp (name, ".reginfo") != 0 | |
827 | || hdr->sh_size != sizeof (Elf32_External_RegInfo)) | |
828 | return false; | |
829 | break; | |
6e07e54f ILT |
830 | case SHT_MIPS_OPTIONS: |
831 | if (strcmp (name, ".options") != 0) | |
832 | return false; | |
833 | break; | |
b3c0fc57 ILT |
834 | default: |
835 | return false; | |
836 | } | |
837 | ||
838 | if (hdr->rawdata == NULL) | |
839 | { | |
840 | asection *newsect; | |
841 | ||
842 | newsect = bfd_make_section (abfd, name); | |
843 | if (newsect != NULL) | |
844 | { | |
845 | newsect->filepos = hdr->sh_offset; | |
846 | newsect->flags |= SEC_HAS_CONTENTS; | |
847 | newsect->vma = hdr->sh_addr; | |
848 | newsect->_raw_size = hdr->sh_size; | |
849 | newsect->alignment_power = bfd_log2 (hdr->sh_addralign); | |
850 | ||
851 | if (hdr->sh_flags & SHF_ALLOC) | |
852 | { | |
853 | newsect->flags |= SEC_ALLOC; | |
854 | newsect->flags |= SEC_LOAD; | |
855 | } | |
856 | ||
857 | if (!(hdr->sh_flags & SHF_WRITE)) | |
858 | newsect->flags |= SEC_READONLY; | |
859 | ||
860 | if (hdr->sh_flags & SHF_EXECINSTR) | |
861 | newsect->flags |= SEC_CODE; | |
862 | else if (newsect->flags & SEC_ALLOC) | |
863 | newsect->flags |= SEC_DATA; | |
864 | ||
865 | if (hdr->sh_type == SHT_MIPS_DEBUG) | |
866 | newsect->flags |= SEC_DEBUGGING; | |
867 | ||
868 | hdr->rawdata = (void *) newsect; | |
869 | ||
870 | /* FIXME: We should record the sh_info field for a .gptab | |
871 | section. */ | |
872 | ||
873 | /* For a .reginfo section, set the gp value in the tdata | |
874 | information from the contents of this section. We need | |
875 | the gp value while processing relocs, so we just get it | |
876 | now. */ | |
877 | if (hdr->sh_type == SHT_MIPS_REGINFO) | |
878 | { | |
879 | Elf32_External_RegInfo ext; | |
880 | Elf32_RegInfo s; | |
881 | ||
882 | if (bfd_get_section_contents (abfd, newsect, (PTR) &ext, | |
883 | (file_ptr) 0, | |
884 | sizeof ext) == false) | |
885 | return false; | |
886 | bfd_mips_elf32_swap_reginfo_in (abfd, &ext, &s); | |
887 | elf_gp (abfd) = s.ri_gp_value; | |
888 | } | |
889 | } | |
890 | else | |
891 | hdr->rawdata = (void *) bfd_get_section_by_name (abfd, name); | |
892 | } | |
893 | ||
894 | return true; | |
895 | } | |
896 | ||
897 | /* Set the correct type for a MIPS ELF section. We do this by the | |
898 | section name, which is a hack, but ought to work. */ | |
899 | ||
900 | static boolean | |
901 | mips_elf_fake_sections (abfd, hdr, sec) | |
902 | bfd *abfd; | |
903 | Elf32_Internal_Shdr *hdr; | |
904 | asection *sec; | |
905 | { | |
906 | register const char *name; | |
907 | ||
908 | name = bfd_get_section_name (abfd, sec); | |
909 | ||
910 | if (strcmp (name, ".liblist") == 0) | |
911 | { | |
912 | hdr->sh_type = SHT_MIPS_LIBLIST; | |
913 | hdr->sh_info = sec->_raw_size / sizeof (Elf32_Lib); | |
914 | /* FIXME: Set the sh_link field. */ | |
915 | } | |
916 | else if (strcmp (name, ".conflict") == 0) | |
917 | hdr->sh_type = SHT_MIPS_CONFLICT; | |
918 | else if (strncmp (name, ".gptab.", sizeof ".gptab." - 1) == 0) | |
919 | { | |
920 | hdr->sh_type = SHT_MIPS_GPTAB; | |
921 | /* FIXME: Set the sh_info field. */ | |
922 | } | |
923 | else if (strcmp (name, ".ucode") == 0) | |
924 | hdr->sh_type = SHT_MIPS_UCODE; | |
925 | else if (strcmp (name, ".mdebug") == 0) | |
6e07e54f ILT |
926 | { |
927 | hdr->sh_type = SHT_MIPS_DEBUG; | |
928 | hdr->sh_entsize = 1; | |
929 | } | |
b3c0fc57 ILT |
930 | else if (strcmp (name, ".reginfo") == 0) |
931 | { | |
932 | hdr->sh_type = SHT_MIPS_REGINFO; | |
6e07e54f | 933 | hdr->sh_entsize = 1; |
b3c0fc57 ILT |
934 | |
935 | /* Force the section size to the correct value, even if the | |
936 | linker thinks it is larger. The link routine below will only | |
937 | write out this much data for .reginfo. */ | |
938 | hdr->sh_size = sec->_raw_size = sizeof (Elf32_External_RegInfo); | |
939 | } | |
6e07e54f ILT |
940 | else if (strcmp (name, ".options") == 0) |
941 | { | |
942 | hdr->sh_type = SHT_MIPS_OPTIONS; | |
943 | hdr->sh_entsize = 1; | |
944 | } | |
b3c0fc57 ILT |
945 | |
946 | return true; | |
947 | } | |
948 | ||
949 | /* Given a BFD section, try to locate the corresponding ELF section | |
950 | index. */ | |
951 | ||
952 | static boolean | |
953 | mips_elf_section_from_bfd_section (abfd, hdr, sec, retval) | |
954 | bfd *abfd; | |
955 | Elf32_Internal_Shdr *hdr; | |
956 | asection *sec; | |
957 | int *retval; | |
958 | { | |
959 | if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0) | |
960 | { | |
961 | *retval = SHN_MIPS_SCOMMON; | |
962 | return true; | |
963 | } | |
964 | if ((asection *) hdr->rawdata == sec) | |
965 | return true; | |
966 | return false; | |
967 | } | |
968 | ||
969 | /* Work over a section just before writing it out. We update the GP | |
970 | value in the .reginfo section based on the value we are using. | |
971 | FIXME: We recognize sections that need the SHF_MIPS_GPREL flag by | |
972 | name; there has to be a better way. */ | |
973 | ||
974 | static boolean | |
975 | mips_elf_section_processing (abfd, hdr) | |
976 | bfd *abfd; | |
977 | Elf32_Internal_Shdr *hdr; | |
978 | { | |
979 | if (hdr->sh_type == SHT_MIPS_REGINFO) | |
980 | { | |
981 | bfd_byte buf[4]; | |
982 | ||
983 | BFD_ASSERT (hdr->sh_size == sizeof (Elf32_External_RegInfo)); | |
984 | BFD_ASSERT (hdr->contents == NULL); | |
985 | ||
986 | if (bfd_seek (abfd, | |
987 | hdr->sh_offset + sizeof (Elf32_External_RegInfo) - 4, | |
988 | SEEK_SET) == -1) | |
989 | return false; | |
990 | bfd_h_put_32 (abfd, (bfd_vma) elf_gp (abfd), buf); | |
991 | if (bfd_write (buf, (bfd_size_type) 1, (bfd_size_type) 4, abfd) != 4) | |
992 | return false; | |
993 | } | |
994 | ||
995 | if (hdr->rawdata != NULL) | |
996 | { | |
997 | const char *name = ((asection *) hdr->rawdata)->name; | |
998 | ||
999 | if (strcmp (name, ".sdata") == 0) | |
1000 | { | |
1001 | hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL; | |
1002 | hdr->sh_type = SHT_PROGBITS; | |
1003 | } | |
1004 | else if (strcmp (name, ".sbss") == 0) | |
1005 | { | |
1006 | hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL; | |
1007 | hdr->sh_type = SHT_NOBITS; | |
1008 | } | |
1009 | else if (strcmp (name, ".lit8") == 0 | |
1010 | || strcmp (name, ".lit4") == 0) | |
1011 | { | |
1012 | hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL; | |
1013 | hdr->sh_type = SHT_PROGBITS; | |
1014 | } | |
1015 | } | |
1016 | ||
1017 | return true; | |
1018 | } | |
1019 | \f | |
6e07e54f ILT |
1020 | /* Read ECOFF debugging information from a .mdebug section into a |
1021 | ecoff_debug_info structure. */ | |
b3c0fc57 ILT |
1022 | |
1023 | static boolean | |
6e07e54f | 1024 | mips_elf_read_ecoff_info (abfd, section, debug) |
b3c0fc57 | 1025 | bfd *abfd; |
6e07e54f ILT |
1026 | asection *section; |
1027 | struct ecoff_debug_info *debug; | |
b3c0fc57 | 1028 | { |
6e07e54f ILT |
1029 | HDRR *symhdr; |
1030 | const struct ecoff_debug_swap *swap; | |
1031 | char *ext_hdr; | |
1032 | ||
1033 | swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; | |
1034 | ||
1035 | ext_hdr = (char *) alloca (swap->external_hdr_size); | |
1036 | ||
1037 | if (bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0, | |
1038 | swap->external_hdr_size) | |
1039 | == false) | |
1040 | return false; | |
1041 | ||
1042 | symhdr = &debug->symbolic_header; | |
1043 | (*swap->swap_hdr_in) (abfd, ext_hdr, symhdr); | |
1044 | ||
1045 | /* The symbolic header contains absolute file offsets and sizes to | |
1046 | read. */ | |
1047 | #define READ(ptr, offset, count, size, type) \ | |
1048 | if (symhdr->count == 0) \ | |
1049 | debug->ptr = NULL; \ | |
1050 | else \ | |
1051 | { \ | |
1052 | debug->ptr = (type) malloc (size * symhdr->count); \ | |
1053 | if (debug->ptr == NULL) \ | |
1054 | { \ | |
1055 | bfd_error = no_memory; \ | |
1056 | return false; \ | |
1057 | } \ | |
1058 | if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \ | |
1059 | || (bfd_read (debug->ptr, size, symhdr->count, \ | |
1060 | abfd) != size * symhdr->count)) \ | |
1061 | return false; \ | |
1062 | } | |
1063 | ||
9783e04a | 1064 | READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR); |
6e07e54f ILT |
1065 | READ (line, cbLineOffset, cbLine, sizeof (unsigned char), unsigned char *); |
1066 | READ (external_dnr, cbDnOffset, idnMax, swap->external_dnr_size, PTR); | |
1067 | READ (external_pdr, cbPdOffset, ipdMax, swap->external_pdr_size, PTR); | |
1068 | READ (external_sym, cbSymOffset, isymMax, swap->external_sym_size, PTR); | |
1069 | READ (external_opt, cbOptOffset, ioptMax, swap->external_opt_size, PTR); | |
1070 | READ (external_aux, cbAuxOffset, iauxMax, sizeof (union aux_ext), | |
1071 | union aux_ext *); | |
1072 | READ (ss, cbSsOffset, issMax, sizeof (char), char *); | |
1073 | READ (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *); | |
1074 | READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR); | |
1075 | READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR); | |
9783e04a DM |
1076 | |
1077 | debug->fdr = NULL; | |
6e07e54f ILT |
1078 | |
1079 | return true; | |
1080 | } | |
1081 | ||
1082 | /* Get EXTR information for a symbol. */ | |
1083 | ||
1084 | static boolean | |
1085 | mips_elf_get_extr (sym, esym) | |
1086 | asymbol *sym; | |
1087 | EXTR *esym; | |
1088 | { | |
9783e04a DM |
1089 | const struct ecoff_debug_swap *swap; |
1090 | ||
6e07e54f ILT |
1091 | if (sym->flags & BSF_SECTION_SYM) |
1092 | return false; | |
1093 | ||
1094 | if (bfd_asymbol_flavour (sym) != bfd_target_elf_flavour | |
1095 | || ((elf_symbol_type *) sym)->tc_data.mips_extr == NULL) | |
1096 | { | |
1097 | esym->jmptbl = 0; | |
1098 | esym->cobol_main = 0; | |
1099 | esym->weakext = 0; | |
1100 | esym->reserved = 0; | |
1101 | esym->ifd = ifdNil; | |
1102 | /* FIXME: we can do better than this for st and sc. */ | |
1103 | esym->asym.st = stGlobal; | |
1104 | esym->asym.sc = scAbs; | |
1105 | esym->asym.reserved = 0; | |
1106 | esym->asym.index = indexNil; | |
1107 | return true; | |
1108 | } | |
1109 | ||
9783e04a DM |
1110 | swap = (get_elf_backend_data (bfd_asymbol_bfd (sym)) |
1111 | ->elf_backend_ecoff_debug_swap); | |
1112 | (*swap->swap_ext_in) (bfd_asymbol_bfd (sym), | |
1113 | ((elf_symbol_type *) sym)->tc_data.mips_extr, | |
1114 | esym); | |
6e07e54f ILT |
1115 | |
1116 | return true; | |
1117 | } | |
1118 | ||
1119 | /* Set the symbol index for an external symbol. This is actually not | |
1120 | needed for ELF. */ | |
1121 | ||
1122 | /*ARGSUSED*/ | |
1123 | static void | |
1124 | mips_elf_set_index (sym, indx) | |
1125 | asymbol *sym; | |
1126 | bfd_size_type indx; | |
1127 | { | |
1128 | } | |
1129 | ||
1130 | /* We need to use a special link routine to handle the .reginfo and | |
1131 | the .mdebug sections. We need to merge all instances of these | |
1132 | sections together, not write them all out sequentially. */ | |
1133 | ||
1134 | static boolean | |
1135 | mips_elf_final_link (abfd, info) | |
1136 | bfd *abfd; | |
1137 | struct bfd_link_info *info; | |
1138 | { | |
1139 | bfd *sub; | |
1140 | size_t outsymalloc; | |
1141 | struct generic_write_global_symbol_info wginfo; | |
1142 | asection **secpp; | |
1143 | asection *o; | |
1144 | struct bfd_link_order *p; | |
1145 | asection *reginfo_sec, *mdebug_sec; | |
b3c0fc57 | 1146 | Elf32_RegInfo reginfo; |
6e07e54f ILT |
1147 | struct ecoff_debug_info debug; |
1148 | const struct ecoff_debug_swap *swap | |
1149 | = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap; | |
1150 | HDRR *symhdr = &debug.symbolic_header; | |
9783e04a | 1151 | PTR mdebug_handle = NULL; |
6e07e54f ILT |
1152 | |
1153 | abfd->outsymbols = (asymbol **) NULL; | |
1154 | abfd->symcount = 0; | |
1155 | outsymalloc = 0; | |
1156 | ||
1157 | /* Build the output symbol table. This also reads in the symbols | |
1158 | for all the input BFDs, keeping them in the outsymbols field. */ | |
1159 | for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next) | |
1160 | if (! _bfd_generic_link_output_symbols (abfd, sub, info, &outsymalloc)) | |
1161 | return false; | |
b3c0fc57 | 1162 | |
6e07e54f | 1163 | /* Accumulate the global symbols. */ |
9783e04a | 1164 | wginfo.info = info; |
6e07e54f ILT |
1165 | wginfo.output_bfd = abfd; |
1166 | wginfo.psymalloc = &outsymalloc; | |
1167 | _bfd_generic_link_hash_traverse (_bfd_generic_hash_table (info), | |
1168 | _bfd_generic_link_write_global_symbol, | |
1169 | (PTR) &wginfo); | |
1170 | ||
1171 | /* Remove empty sections. Also drop the .options section, since it | |
1172 | has special semantics which I haven't bothered to figure out. | |
1173 | Also drop the .gptab sections, which also require special | |
1174 | handling which is not currently done. Removing the .gptab | |
1175 | sections is required for Irix 5 compatibility; I don't know about | |
1176 | the other sections. */ | |
1177 | secpp = &abfd->sections; | |
1178 | while (*secpp != NULL) | |
1179 | { | |
9783e04a DM |
1180 | if (((*secpp)->_raw_size == 0 |
1181 | && strcmp ((*secpp)->name, ".data") != 0 | |
1182 | && strcmp ((*secpp)->name, ".text") != 0 | |
1183 | && strcmp ((*secpp)->name, ".bss") != 0) | |
6e07e54f ILT |
1184 | || strcmp ((*secpp)->name, ".options") == 0 |
1185 | || strncmp ((*secpp)->name, ".gptab", 6) == 0) | |
1186 | { | |
1187 | *secpp = (*secpp)->next; | |
1188 | --abfd->section_count; | |
1189 | } | |
1190 | else | |
1191 | secpp = &(*secpp)->next; | |
1192 | } | |
b3c0fc57 | 1193 | |
6e07e54f ILT |
1194 | /* Go through the sections and collect the .reginfo and .mdebug |
1195 | information. We don't write out the information until we have | |
1196 | set the section sizes, because the ELF backend only assigns space | |
1197 | in the file once. */ | |
9783e04a DM |
1198 | reginfo_sec = NULL; |
1199 | mdebug_sec = NULL; | |
6e07e54f | 1200 | for (o = abfd->sections; o != (asection *) NULL; o = o->next) |
b3c0fc57 | 1201 | { |
6e07e54f | 1202 | if (strcmp (o->name, ".reginfo") == 0) |
b3c0fc57 | 1203 | { |
6e07e54f | 1204 | memset (®info, 0, sizeof reginfo); |
b3c0fc57 ILT |
1205 | |
1206 | /* We have found the .reginfo section in the output file. | |
6e07e54f ILT |
1207 | Look through all the link_orders comprising it and merge |
1208 | the information together. */ | |
1209 | for (p = o->link_order_head; | |
1210 | p != (struct bfd_link_order *) NULL; | |
b3c0fc57 ILT |
1211 | p = p->next) |
1212 | { | |
6e07e54f ILT |
1213 | asection *input_section; |
1214 | bfd *input_bfd; | |
1215 | Elf32_External_RegInfo ext; | |
1216 | Elf32_RegInfo sub; | |
1217 | ||
1218 | if (p->type != bfd_indirect_link_order) | |
1219 | continue; | |
1220 | ||
1221 | input_section = p->u.indirect.section; | |
1222 | input_bfd = input_section->owner; | |
1223 | BFD_ASSERT (input_section->_raw_size | |
1224 | == sizeof (Elf32_External_RegInfo)); | |
1225 | if (! bfd_get_section_contents (input_bfd, input_section, | |
1226 | (PTR) &ext, | |
1227 | (file_ptr) 0, | |
1228 | sizeof ext)) | |
1229 | return false; | |
1230 | ||
1231 | bfd_mips_elf32_swap_reginfo_in (input_bfd, &ext, &sub); | |
1232 | ||
1233 | reginfo.ri_gprmask |= sub.ri_gprmask; | |
1234 | reginfo.ri_cprmask[0] |= sub.ri_cprmask[0]; | |
1235 | reginfo.ri_cprmask[1] |= sub.ri_cprmask[1]; | |
1236 | reginfo.ri_cprmask[2] |= sub.ri_cprmask[2]; | |
1237 | reginfo.ri_cprmask[3] |= sub.ri_cprmask[3]; | |
1238 | ||
1239 | /* ri_gp_value is set by the function | |
1240 | mips_elf_section_processing when the section is | |
1241 | finally written out. */ | |
1242 | } | |
1243 | ||
1244 | /* Force the section size to the value we want. */ | |
1245 | o->_raw_size = sizeof (Elf32_External_RegInfo); | |
1246 | ||
1247 | /* Skip this section later on. */ | |
1248 | o->link_order_head = (struct bfd_link_order *) NULL; | |
1249 | ||
1250 | reginfo_sec = o; | |
1251 | } | |
1252 | ||
1253 | if (strcmp (o->name, ".mdebug") == 0) | |
1254 | { | |
1255 | /* We have found the .mdebug section in the output file. | |
1256 | Look through all the link_orders comprising it and merge | |
1257 | the information together. */ | |
1258 | symhdr->magic = swap->sym_magic; | |
1259 | /* FIXME: What should the version stamp be? */ | |
1260 | symhdr->vstamp = 0; | |
1261 | symhdr->ilineMax = 0; | |
1262 | symhdr->cbLine = 0; | |
1263 | symhdr->idnMax = 0; | |
1264 | symhdr->ipdMax = 0; | |
1265 | symhdr->isymMax = 0; | |
1266 | symhdr->ioptMax = 0; | |
1267 | symhdr->iauxMax = 0; | |
1268 | symhdr->issMax = 0; | |
1269 | symhdr->issExtMax = 0; | |
1270 | symhdr->ifdMax = 0; | |
1271 | symhdr->crfd = 0; | |
1272 | symhdr->iextMax = 0; | |
1273 | ||
1274 | /* We accumulate the debugging information itself in the | |
1275 | debug_info structure. */ | |
9783e04a DM |
1276 | debug.line = NULL; |
1277 | debug.external_dnr = NULL; | |
1278 | debug.external_pdr = NULL; | |
1279 | debug.external_sym = NULL; | |
1280 | debug.external_opt = NULL; | |
1281 | debug.external_aux = NULL; | |
1282 | debug.ss = NULL; | |
6e07e54f | 1283 | debug.ssext = debug.ssext_end = NULL; |
9783e04a DM |
1284 | debug.external_fdr = NULL; |
1285 | debug.external_rfd = NULL; | |
6e07e54f ILT |
1286 | debug.external_ext = debug.external_ext_end = NULL; |
1287 | ||
9783e04a DM |
1288 | mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info); |
1289 | if (mdebug_handle == (PTR) NULL) | |
1290 | return false; | |
1291 | ||
6e07e54f ILT |
1292 | for (p = o->link_order_head; |
1293 | p != (struct bfd_link_order *) NULL; | |
1294 | p = p->next) | |
1295 | { | |
1296 | asection *input_section; | |
1297 | bfd *input_bfd; | |
1298 | const struct ecoff_debug_swap *input_swap; | |
1299 | struct ecoff_debug_info input_debug; | |
1300 | ||
1301 | if (p->type != bfd_indirect_link_order) | |
1302 | continue; | |
1303 | ||
9783e04a DM |
1304 | #ifndef alloca |
1305 | alloca (0); | |
1306 | #endif | |
1307 | ||
6e07e54f ILT |
1308 | input_section = p->u.indirect.section; |
1309 | input_bfd = input_section->owner; | |
1310 | ||
1311 | if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour | |
1312 | || (get_elf_backend_data (input_bfd) | |
1313 | ->elf_backend_ecoff_debug_swap) == NULL) | |
b3c0fc57 | 1314 | { |
6e07e54f ILT |
1315 | /* I don't know what a non MIPS ELF bfd would be |
1316 | doing with a .mdebug section, but I don't really | |
1317 | want to deal with it. */ | |
1318 | continue; | |
b3c0fc57 | 1319 | } |
6e07e54f ILT |
1320 | |
1321 | input_swap = (get_elf_backend_data (input_bfd) | |
1322 | ->elf_backend_ecoff_debug_swap); | |
1323 | ||
1324 | BFD_ASSERT (p->size == input_section->_raw_size); | |
1325 | ||
1326 | /* The ECOFF linking code expects that we have already | |
1327 | read in the debugging information and set up an | |
1328 | ecoff_debug_info structure, so we do that now. */ | |
1329 | if (! mips_elf_read_ecoff_info (input_bfd, input_section, | |
1330 | &input_debug)) | |
1331 | return false; | |
1332 | ||
1333 | if (! (bfd_ecoff_debug_accumulate | |
9783e04a DM |
1334 | (mdebug_handle, abfd, &debug, swap, input_bfd, |
1335 | &input_debug, input_swap, info))) | |
6e07e54f ILT |
1336 | return false; |
1337 | ||
1338 | /* Loop through the external symbols. For each one with | |
1339 | interesting information, try to find the symbol on | |
1340 | the symbol table of abfd and save the information in | |
1341 | order to put it into the final external symbols. */ | |
1342 | if (info->hash->creator == input_bfd->xvec) | |
1343 | { | |
1344 | char *eraw_src; | |
1345 | char *eraw_end; | |
1346 | ||
1347 | eraw_src = input_debug.external_ext; | |
1348 | eraw_end = (eraw_src | |
1349 | + (input_debug.symbolic_header.iextMax | |
1350 | * input_swap->external_ext_size)); | |
1351 | for (; | |
1352 | eraw_src < eraw_end; | |
1353 | eraw_src += input_swap->external_ext_size) | |
1354 | { | |
1355 | EXTR ext; | |
1356 | const char *name; | |
1357 | struct generic_link_hash_entry *h; | |
1358 | elf_symbol_type *elf_sym; | |
1359 | ||
1360 | (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, | |
1361 | &ext); | |
1362 | if (ext.asym.sc == scNil | |
1363 | || ext.asym.sc == scUndefined | |
1364 | || ext.asym.sc == scSUndefined) | |
1365 | continue; | |
1366 | ||
1367 | name = input_debug.ssext + ext.asym.iss; | |
1368 | h = ((struct generic_link_hash_entry *) | |
1369 | bfd_link_hash_lookup (info->hash, name, false, | |
1370 | false, true)); | |
1371 | if (h == (struct generic_link_hash_entry *) NULL | |
1372 | || h->sym == (asymbol *) NULL) | |
1373 | continue; | |
1374 | ||
1375 | elf_sym = (elf_symbol_type *) (h->sym); | |
1376 | ||
1377 | if (elf_sym->tc_data.mips_extr != NULL) | |
1378 | continue; | |
1379 | ||
9783e04a DM |
1380 | if (ext.ifd != -1) |
1381 | { | |
1382 | BFD_ASSERT (ext.ifd | |
1383 | < input_debug.symbolic_header.ifdMax); | |
1384 | ext.ifd = input_debug.ifdmap[ext.ifd]; | |
1385 | } | |
6e07e54f | 1386 | |
9783e04a DM |
1387 | (*input_swap->swap_ext_out) (input_bfd, &ext, |
1388 | (PTR) eraw_src); | |
1389 | elf_sym->tc_data.mips_extr = (PTR) eraw_src; | |
6e07e54f ILT |
1390 | } |
1391 | } | |
1392 | ||
9783e04a DM |
1393 | /* Free up the information we just read, except for the |
1394 | external symbols which we may have pointers to. */ | |
6e07e54f ILT |
1395 | free (input_debug.line); |
1396 | free (input_debug.external_dnr); | |
1397 | free (input_debug.external_pdr); | |
1398 | free (input_debug.external_sym); | |
1399 | free (input_debug.external_opt); | |
1400 | free (input_debug.external_aux); | |
1401 | free (input_debug.ss); | |
1402 | free (input_debug.ssext); | |
1403 | free (input_debug.external_fdr); | |
1404 | free (input_debug.external_rfd); | |
b3c0fc57 ILT |
1405 | } |
1406 | ||
6e07e54f ILT |
1407 | /* Build the external symbol information. */ |
1408 | if (! bfd_ecoff_debug_externals (abfd, &debug, swap, | |
1409 | info->relocateable, | |
1410 | mips_elf_get_extr, | |
1411 | mips_elf_set_index)) | |
b3c0fc57 ILT |
1412 | return false; |
1413 | ||
6e07e54f ILT |
1414 | /* Set the size of the section. */ |
1415 | o->_raw_size = bfd_ecoff_debug_size (abfd, &debug, swap); | |
1416 | ||
1417 | /* Skip this section later on. */ | |
1418 | o->link_order_head = (struct bfd_link_order *) NULL; | |
1419 | ||
1420 | mdebug_sec = o; | |
1421 | } | |
1422 | } | |
1423 | ||
1424 | if (info->relocateable) | |
1425 | { | |
1426 | /* Allocate space for the output relocs for each section. */ | |
1427 | for (o = abfd->sections; | |
1428 | o != (asection *) NULL; | |
1429 | o = o->next) | |
1430 | { | |
1431 | o->reloc_count = 0; | |
1432 | for (p = o->link_order_head; | |
1433 | p != (struct bfd_link_order *) NULL; | |
1434 | p = p->next) | |
1435 | { | |
1436 | if (p->type == bfd_indirect_link_order) | |
1437 | { | |
1438 | asection *input_section; | |
1439 | bfd *input_bfd; | |
1440 | bfd_size_type relsize; | |
1441 | arelent **relocs; | |
1442 | bfd_size_type reloc_count; | |
1443 | ||
1444 | input_section = p->u.indirect.section; | |
1445 | input_bfd = input_section->owner; | |
1446 | relsize = bfd_get_reloc_upper_bound (input_bfd, | |
1447 | input_section); | |
9783e04a DM |
1448 | relocs = (arelent **) malloc (relsize); |
1449 | if (!relocs) | |
1450 | { | |
1451 | bfd_error = no_memory; | |
1452 | return false; | |
1453 | } | |
6e07e54f ILT |
1454 | reloc_count = |
1455 | bfd_canonicalize_reloc (input_bfd, input_section, | |
1456 | relocs, | |
1457 | bfd_get_outsymbols (input_bfd)); | |
1458 | BFD_ASSERT (reloc_count == input_section->reloc_count); | |
1459 | o->reloc_count += reloc_count; | |
1460 | free (relocs); | |
1461 | } | |
1462 | } | |
1463 | if (o->reloc_count > 0) | |
1464 | { | |
1465 | o->orelocation = ((arelent **) | |
1466 | bfd_alloc (abfd, | |
1467 | (o->reloc_count | |
1468 | * sizeof (arelent *)))); | |
9783e04a DM |
1469 | if (!o->orelocation) |
1470 | { | |
1471 | bfd_error = no_memory; | |
1472 | return false; | |
1473 | } | |
6e07e54f ILT |
1474 | /* Reset the count so that it can be used as an index |
1475 | when putting in the output relocs. */ | |
1476 | o->reloc_count = 0; | |
1477 | } | |
1478 | } | |
1479 | } | |
b3c0fc57 | 1480 | |
6e07e54f ILT |
1481 | /* Write out the information we have accumulated. */ |
1482 | if (reginfo_sec != (asection *) NULL) | |
1483 | { | |
1484 | Elf32_External_RegInfo ext; | |
1485 | ||
1486 | bfd_mips_elf32_swap_reginfo_out (abfd, ®info, &ext); | |
1487 | if (! bfd_set_section_contents (abfd, reginfo_sec, (PTR) &ext, | |
1488 | (file_ptr) 0, sizeof ext)) | |
1489 | return false; | |
1490 | } | |
b3c0fc57 | 1491 | |
6e07e54f ILT |
1492 | if (mdebug_sec != (asection *) NULL) |
1493 | { | |
1494 | if (! abfd->output_has_begun) | |
1495 | { | |
1496 | /* Force the section to be given a file position. */ | |
1497 | bfd_set_section_contents (abfd, mdebug_sec, (PTR) NULL, | |
1498 | (file_ptr) 0, (bfd_size_type) 0); | |
1499 | BFD_ASSERT (abfd->output_has_begun); | |
b3c0fc57 | 1500 | } |
9783e04a DM |
1501 | if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug, |
1502 | swap, info, | |
1503 | mdebug_sec->filepos)) | |
6e07e54f | 1504 | return false; |
9783e04a DM |
1505 | |
1506 | bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info); | |
b3c0fc57 ILT |
1507 | } |
1508 | ||
6e07e54f ILT |
1509 | /* Handle all the link order information for the sections. */ |
1510 | for (o = abfd->sections; | |
1511 | o != (asection *) NULL; | |
1512 | o = o->next) | |
1513 | { | |
1514 | for (p = o->link_order_head; | |
1515 | p != (struct bfd_link_order *) NULL; | |
1516 | p = p->next) | |
1517 | { | |
1518 | if (! _bfd_default_link_order (abfd, info, o, p)) | |
1519 | return false; | |
1520 | } | |
1521 | } | |
1522 | ||
1523 | return true; | |
b3c0fc57 ILT |
1524 | } |
1525 | \f | |
1526 | /* MIPS ELF uses two common sections. One is the usual one, and the | |
1527 | other is for small objects. All the small objects are kept | |
1528 | together, and then referenced via the gp pointer, which yields | |
1529 | faster assembler code. This is what we use for the small common | |
1530 | section. This approach is copied from ecoff.c. */ | |
1531 | static asection mips_elf_scom_section; | |
1532 | static asymbol mips_elf_scom_symbol; | |
1533 | static asymbol *mips_elf_scom_symbol_ptr; | |
1534 | ||
6e07e54f ILT |
1535 | /* MIPS ELF also uses an acommon section, which represents an |
1536 | allocated common symbol which may be overridden by a | |
1537 | definition in a shared library. */ | |
1538 | static asection mips_elf_acom_section; | |
1539 | static asymbol mips_elf_acom_symbol; | |
1540 | static asymbol *mips_elf_acom_symbol_ptr; | |
1541 | ||
b3c0fc57 ILT |
1542 | /* Handle the special MIPS section numbers that a symbol may use. */ |
1543 | ||
1544 | static void | |
1545 | mips_elf_symbol_processing (abfd, asym) | |
1546 | bfd *abfd; | |
1547 | asymbol *asym; | |
1548 | { | |
1549 | elf_symbol_type *elfsym; | |
1550 | ||
1551 | elfsym = (elf_symbol_type *) asym; | |
1552 | switch (elfsym->internal_elf_sym.st_shndx) | |
1553 | { | |
1554 | case SHN_MIPS_ACOMMON: | |
6e07e54f ILT |
1555 | /* This section is used in a dynamically linked executable file. |
1556 | It is an allocated common section. The dynamic linker can | |
1557 | either resolve these symbols to something in a shared | |
1558 | library, or it can just leave them here. For our purposes, | |
1559 | we can consider these symbols to be in a new section. */ | |
1560 | if (mips_elf_acom_section.name == NULL) | |
1561 | { | |
1562 | /* Initialize the acommon section. */ | |
1563 | mips_elf_acom_section.name = ".acommon"; | |
1564 | mips_elf_acom_section.flags = SEC_NO_FLAGS; | |
1565 | mips_elf_acom_section.output_section = &mips_elf_acom_section; | |
1566 | mips_elf_acom_section.symbol = &mips_elf_acom_symbol; | |
1567 | mips_elf_acom_section.symbol_ptr_ptr = &mips_elf_acom_symbol_ptr; | |
1568 | mips_elf_acom_symbol.name = ".acommon"; | |
1569 | mips_elf_acom_symbol.flags = BSF_SECTION_SYM; | |
1570 | mips_elf_acom_symbol.section = &mips_elf_acom_section; | |
1571 | mips_elf_acom_symbol_ptr = &mips_elf_acom_symbol; | |
1572 | } | |
1573 | asym->section = &mips_elf_acom_section; | |
b3c0fc57 ILT |
1574 | break; |
1575 | ||
1576 | case SHN_COMMON: | |
1577 | /* Common symbols less than the GP size are automatically | |
1578 | treated as SHN_MIPS_SCOMMON symbols. */ | |
1579 | if (asym->value > elf_gp_size (abfd)) | |
1580 | break; | |
1581 | /* Fall through. */ | |
1582 | case SHN_MIPS_SCOMMON: | |
1583 | if (mips_elf_scom_section.name == NULL) | |
1584 | { | |
1585 | /* Initialize the small common section. */ | |
1586 | mips_elf_scom_section.name = ".scommon"; | |
1587 | mips_elf_scom_section.flags = SEC_IS_COMMON; | |
1588 | mips_elf_scom_section.output_section = &mips_elf_scom_section; | |
1589 | mips_elf_scom_section.symbol = &mips_elf_scom_symbol; | |
1590 | mips_elf_scom_section.symbol_ptr_ptr = &mips_elf_scom_symbol_ptr; | |
1591 | mips_elf_scom_symbol.name = ".scommon"; | |
1592 | mips_elf_scom_symbol.flags = BSF_SECTION_SYM; | |
1593 | mips_elf_scom_symbol.section = &mips_elf_scom_section; | |
1594 | mips_elf_scom_symbol_ptr = &mips_elf_scom_symbol; | |
1595 | } | |
1596 | asym->section = &mips_elf_scom_section; | |
1597 | asym->value = elfsym->internal_elf_sym.st_size; | |
1598 | break; | |
1599 | ||
1600 | case SHN_MIPS_SUNDEFINED: | |
1601 | asym->section = &bfd_und_section; | |
1602 | break; | |
1603 | } | |
1604 | } | |
1605 | \f | |
6e07e54f ILT |
1606 | /* ECOFF swapping routines. These are used when dealing with the |
1607 | .mdebug section, which is in the ECOFF debugging format. */ | |
1608 | static const struct ecoff_debug_swap mips_elf_ecoff_debug_swap = | |
1609 | { | |
1610 | /* Symbol table magic number. */ | |
1611 | magicSym, | |
1612 | /* Alignment of debugging information. E.g., 4. */ | |
1613 | 4, | |
1614 | /* Sizes of external symbolic information. */ | |
1615 | sizeof (struct hdr_ext), | |
1616 | sizeof (struct dnr_ext), | |
1617 | sizeof (struct pdr_ext), | |
1618 | sizeof (struct sym_ext), | |
1619 | sizeof (struct opt_ext), | |
1620 | sizeof (struct fdr_ext), | |
1621 | sizeof (struct rfd_ext), | |
1622 | sizeof (struct ext_ext), | |
1623 | /* Functions to swap in external symbolic data. */ | |
1624 | ecoff_swap_hdr_in, | |
1625 | ecoff_swap_dnr_in, | |
1626 | ecoff_swap_pdr_in, | |
1627 | ecoff_swap_sym_in, | |
1628 | ecoff_swap_opt_in, | |
1629 | ecoff_swap_fdr_in, | |
1630 | ecoff_swap_rfd_in, | |
1631 | ecoff_swap_ext_in, | |
1632 | /* Functions to swap out external symbolic data. */ | |
1633 | ecoff_swap_hdr_out, | |
1634 | ecoff_swap_dnr_out, | |
1635 | ecoff_swap_pdr_out, | |
1636 | ecoff_swap_sym_out, | |
1637 | ecoff_swap_opt_out, | |
1638 | ecoff_swap_fdr_out, | |
1639 | ecoff_swap_rfd_out, | |
1640 | ecoff_swap_ext_out | |
1641 | }; | |
1642 | \f | |
6b4b4d17 JK |
1643 | #define TARGET_LITTLE_SYM bfd_elf32_littlemips_vec |
1644 | #define TARGET_LITTLE_NAME "elf32-littlemips" | |
1645 | #define TARGET_BIG_SYM bfd_elf32_bigmips_vec | |
1646 | #define TARGET_BIG_NAME "elf32-bigmips" | |
1647 | #define ELF_ARCH bfd_arch_mips | |
6e07e54f | 1648 | #define ELF_MACHINE_CODE EM_MIPS |
b3c0fc57 ILT |
1649 | #define ELF_MAXPAGESIZE 0x10000 |
1650 | #define elf_info_to_howto 0 | |
1651 | #define elf_info_to_howto_rel mips_info_to_howto_rel | |
6e07e54f ILT |
1652 | #define elf_backend_sym_is_global mips_elf_sym_is_global |
1653 | #define elf_backend_object_p mips_elf_object_p | |
b3c0fc57 ILT |
1654 | #define elf_backend_section_from_shdr mips_elf_section_from_shdr |
1655 | #define elf_backend_fake_sections mips_elf_fake_sections | |
1656 | #define elf_backend_section_from_bfd_section \ | |
1657 | mips_elf_section_from_bfd_section | |
1658 | #define elf_backend_section_processing mips_elf_section_processing | |
1659 | #define elf_backend_symbol_processing mips_elf_symbol_processing | |
6e07e54f ILT |
1660 | #define elf_backend_final_write_processing \ |
1661 | mips_elf_final_write_processing | |
1662 | #define elf_backend_ecoff_debug_swap &mips_elf_ecoff_debug_swap | |
b3c0fc57 | 1663 | |
6e07e54f | 1664 | #define bfd_elf32_bfd_final_link mips_elf_final_link |
6b4b4d17 JK |
1665 | |
1666 | #include "elf32-target.h" |