1 |
/* MMIX-specific support for 64-bit ELF. |
/* MMIX-specific support for 64-bit ELF. |
2 |
Copyright 2001, 2002 Free Software Foundation, Inc. |
Copyright 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. |
3 |
Contributed by Hans-Peter Nilsson <hp@bitrange.com> |
Contributed by Hans-Peter Nilsson <hp@bitrange.com> |
4 |
|
|
5 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
21 |
/* No specific ABI or "processor-specific supplement" defined. */ |
/* No specific ABI or "processor-specific supplement" defined. */ |
22 |
|
|
23 |
/* TODO: |
/* TODO: |
24 |
- Linker relaxation. */ |
- "Traditional" linker relaxation (shrinking whole sections). |
25 |
|
- Merge reloc stubs jumping to same location. |
26 |
|
- GETA stub relaxation (call a stub for out of range new |
27 |
|
R_MMIX_GETA_STUBBABLE). */ |
28 |
|
|
29 |
#include "bfd.h" |
#include "bfd.h" |
30 |
#include "sysdep.h" |
#include "sysdep.h" |
35 |
|
|
36 |
#define MINUS_ONE (((bfd_vma) 0) - 1) |
#define MINUS_ONE (((bfd_vma) 0) - 1) |
37 |
|
|
38 |
|
#define MAX_PUSHJ_STUB_SIZE (5 * 4) |
39 |
|
|
40 |
/* Put these everywhere in new code. */ |
/* Put these everywhere in new code. */ |
41 |
#define FATAL_DEBUG \ |
#define FATAL_DEBUG \ |
42 |
_bfd_abort (__FILE__, __LINE__, \ |
_bfd_abort (__FILE__, __LINE__, \ |
46 |
_bfd_abort (__FILE__, __LINE__, \ |
_bfd_abort (__FILE__, __LINE__, \ |
47 |
"bad case for " #x) |
"bad case for " #x) |
48 |
|
|
49 |
|
struct _mmix_elf_section_data |
50 |
|
{ |
51 |
|
struct bfd_elf_section_data elf; |
52 |
|
union |
53 |
|
{ |
54 |
|
struct bpo_reloc_section_info *reloc; |
55 |
|
struct bpo_greg_section_info *greg; |
56 |
|
} bpo; |
57 |
|
|
58 |
|
struct pushj_stub_info |
59 |
|
{ |
60 |
|
/* Maximum number of stubs needed for this section. */ |
61 |
|
bfd_size_type n_pushj_relocs; |
62 |
|
|
63 |
|
/* Size of stubs after a mmix_elf_relax_section round. */ |
64 |
|
bfd_size_type stubs_size_sum; |
65 |
|
|
66 |
|
/* Per-reloc stubs_size_sum information. The stubs_size_sum member is the sum |
67 |
|
of these. Allocated in mmix_elf_check_common_relocs. */ |
68 |
|
bfd_size_type *stub_size; |
69 |
|
|
70 |
|
/* Offset of next stub during relocation. Somewhat redundant with the |
71 |
|
above: error coverage is easier and we don't have to reset the |
72 |
|
stubs_size_sum for relocation. */ |
73 |
|
bfd_size_type stub_offset; |
74 |
|
} pjs; |
75 |
|
}; |
76 |
|
|
77 |
|
#define mmix_elf_section_data(sec) \ |
78 |
|
((struct _mmix_elf_section_data *) elf_section_data (sec)) |
79 |
|
|
80 |
/* For each section containing a base-plus-offset (BPO) reloc, we attach |
/* For each section containing a base-plus-offset (BPO) reloc, we attach |
81 |
this struct as elf_section_data (section)->tdata, which is otherwise |
this struct as mmix_elf_section_data (section)->bpo, which is otherwise |
82 |
NULL. */ |
NULL. */ |
83 |
struct bpo_reloc_section_info |
struct bpo_reloc_section_info |
84 |
{ |
{ |
114 |
size_t bpo_reloc_no; |
size_t bpo_reloc_no; |
115 |
|
|
116 |
/* Set when the value is computed. Better than coding "guard values" |
/* Set when the value is computed. Better than coding "guard values" |
117 |
into the other members. Is false only for BPO relocs in a GC:ed |
into the other members. Is FALSE only for BPO relocs in a GC:ed |
118 |
section. */ |
section. */ |
119 |
boolean valid; |
bfd_boolean valid; |
120 |
}; |
}; |
121 |
|
|
122 |
/* We attach this as elf_section_data (sec)->tdata in the linker-allocated |
/* We attach this as mmix_elf_section_data (sec)->bpo in the linker-allocated |
123 |
greg contents section (MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME), |
greg contents section (MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME), |
124 |
which is linked into the register contents section |
which is linked into the register contents section |
125 |
(MMIX_REG_CONTENTS_SECTION_NAME). This section is created by the |
(MMIX_REG_CONTENTS_SECTION_NAME). This section is created by the |
142 |
size_t n_remaining_bpo_relocs_this_relaxation_round; |
size_t n_remaining_bpo_relocs_this_relaxation_round; |
143 |
|
|
144 |
/* The number of linker-allocated GREGs resulting from BPO relocs. |
/* The number of linker-allocated GREGs resulting from BPO relocs. |
145 |
This is an approximation after _bfd_mmix_allocated_gregs_init and |
This is an approximation after _bfd_mmix_before_linker_allocation |
146 |
supposedly accurate after mmix_elf_relax_section is called for all |
and supposedly accurate after mmix_elf_relax_section is called for |
147 |
incoming non-collected sections. */ |
all incoming non-collected sections. */ |
148 |
size_t n_allocated_bpo_gregs; |
size_t n_allocated_bpo_gregs; |
149 |
|
|
150 |
/* Index into reloc_request[], sorted on increasing "value", secondary |
/* Index into reloc_request[], sorted on increasing "value", secondary |
156 |
struct bpo_reloc_request *reloc_request; |
struct bpo_reloc_request *reloc_request; |
157 |
}; |
}; |
158 |
|
|
159 |
static boolean mmix_elf_link_output_symbol_hook |
static bfd_boolean mmix_elf_link_output_symbol_hook |
160 |
PARAMS ((bfd *, struct bfd_link_info *, const char *, |
PARAMS ((struct bfd_link_info *, const char *, Elf_Internal_Sym *, |
161 |
Elf_Internal_Sym *, asection *)); |
asection *, struct elf_link_hash_entry *)); |
162 |
|
|
163 |
static bfd_reloc_status_type mmix_elf_reloc |
static bfd_reloc_status_type mmix_elf_reloc |
164 |
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); |
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); |
167 |
PARAMS ((bfd *, bfd_reloc_code_real_type)); |
PARAMS ((bfd *, bfd_reloc_code_real_type)); |
168 |
|
|
169 |
static void mmix_info_to_howto_rela |
static void mmix_info_to_howto_rela |
170 |
PARAMS ((bfd *, arelent *, Elf64_Internal_Rela *)); |
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); |
171 |
|
|
172 |
static int mmix_elf_sort_relocs PARAMS ((const PTR, const PTR)); |
static int mmix_elf_sort_relocs PARAMS ((const PTR, const PTR)); |
173 |
|
|
174 |
static boolean mmix_elf_check_relocs |
static bfd_boolean mmix_elf_new_section_hook |
175 |
|
PARAMS ((bfd *, asection *)); |
176 |
|
|
177 |
|
static bfd_boolean mmix_elf_check_relocs |
178 |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
179 |
const Elf_Internal_Rela *)); |
const Elf_Internal_Rela *)); |
180 |
|
|
181 |
static boolean mmix_elf_check_common_relocs |
static bfd_boolean mmix_elf_check_common_relocs |
182 |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
183 |
const Elf_Internal_Rela *)); |
const Elf_Internal_Rela *)); |
184 |
|
|
185 |
static boolean mmix_elf_relocate_section |
static bfd_boolean mmix_elf_relocate_section |
186 |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
187 |
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); |
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); |
188 |
|
|
190 |
PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, |
PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, |
191 |
struct elf_link_hash_entry *, Elf_Internal_Sym *)); |
struct elf_link_hash_entry *, Elf_Internal_Sym *)); |
192 |
|
|
193 |
static boolean mmix_elf_gc_sweep_hook |
static bfd_boolean mmix_elf_gc_sweep_hook |
194 |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
195 |
const Elf_Internal_Rela *)); |
const Elf_Internal_Rela *)); |
196 |
|
|
201 |
static bfd_reloc_status_type mmix_elf_perform_relocation |
static bfd_reloc_status_type mmix_elf_perform_relocation |
202 |
PARAMS ((asection *, reloc_howto_type *, PTR, bfd_vma, bfd_vma)); |
PARAMS ((asection *, reloc_howto_type *, PTR, bfd_vma, bfd_vma)); |
203 |
|
|
204 |
static boolean mmix_elf_section_from_bfd_section |
static bfd_boolean mmix_elf_section_from_bfd_section |
205 |
PARAMS ((bfd *, asection *, int *)); |
PARAMS ((bfd *, asection *, int *)); |
206 |
|
|
207 |
static boolean mmix_elf_add_symbol_hook |
static bfd_boolean mmix_elf_add_symbol_hook |
208 |
PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *, |
PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Sym *, |
209 |
const char **, flagword *, asection **, bfd_vma *)); |
const char **, flagword *, asection **, bfd_vma *)); |
210 |
|
|
211 |
static boolean mmix_elf_is_local_label_name |
static bfd_boolean mmix_elf_is_local_label_name |
212 |
PARAMS ((bfd *, const char *)); |
PARAMS ((bfd *, const char *)); |
213 |
|
|
214 |
static int bpo_reloc_request_sort_fn PARAMS ((const PTR, const PTR)); |
static int bpo_reloc_request_sort_fn PARAMS ((const PTR, const PTR)); |
215 |
|
|
216 |
static boolean mmix_elf_relax_section |
static bfd_boolean mmix_elf_relax_section |
217 |
PARAMS ((bfd *abfd, asection *sec, struct bfd_link_info *link_info, |
PARAMS ((bfd *abfd, asection *sec, struct bfd_link_info *link_info, |
218 |
boolean *again)); |
bfd_boolean *again)); |
219 |
|
|
220 |
extern boolean mmix_elf_final_link PARAMS ((bfd *, struct bfd_link_info *)); |
extern bfd_boolean mmix_elf_final_link PARAMS ((bfd *, struct bfd_link_info *)); |
221 |
|
|
222 |
extern void mmix_elf_symbol_processing PARAMS ((bfd *, asymbol *)); |
extern void mmix_elf_symbol_processing PARAMS ((bfd *, asymbol *)); |
223 |
|
|
225 |
extern void mmix_dump_bpo_gregs |
extern void mmix_dump_bpo_gregs |
226 |
PARAMS ((struct bfd_link_info *, bfd_error_handler_type)); |
PARAMS ((struct bfd_link_info *, bfd_error_handler_type)); |
227 |
|
|
228 |
|
static void |
229 |
|
mmix_set_relaxable_size |
230 |
|
PARAMS ((bfd *, asection *, void *)); |
231 |
|
|
232 |
|
|
233 |
/* Watch out: this currently needs to have elements with the same index as |
/* Watch out: this currently needs to have elements with the same index as |
234 |
their R_MMIX_ number. */ |
their R_MMIX_ number. */ |
235 |
static reloc_howto_type elf_mmix_howto_table[] = |
static reloc_howto_type elf_mmix_howto_table[] = |
239 |
0, /* rightshift */ |
0, /* rightshift */ |
240 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
241 |
32, /* bitsize */ |
32, /* bitsize */ |
242 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
243 |
0, /* bitpos */ |
0, /* bitpos */ |
244 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
245 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
246 |
"R_MMIX_NONE", /* name */ |
"R_MMIX_NONE", /* name */ |
247 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
248 |
0, /* src_mask */ |
0, /* src_mask */ |
249 |
0, /* dst_mask */ |
0, /* dst_mask */ |
250 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
251 |
|
|
252 |
/* An 8 bit absolute relocation. */ |
/* An 8 bit absolute relocation. */ |
253 |
HOWTO (R_MMIX_8, /* type */ |
HOWTO (R_MMIX_8, /* type */ |
254 |
0, /* rightshift */ |
0, /* rightshift */ |
255 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
256 |
8, /* bitsize */ |
8, /* bitsize */ |
257 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
258 |
0, /* bitpos */ |
0, /* bitpos */ |
259 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
260 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
261 |
"R_MMIX_8", /* name */ |
"R_MMIX_8", /* name */ |
262 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
263 |
0, /* src_mask */ |
0, /* src_mask */ |
264 |
0xff, /* dst_mask */ |
0xff, /* dst_mask */ |
265 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
266 |
|
|
267 |
/* An 16 bit absolute relocation. */ |
/* An 16 bit absolute relocation. */ |
268 |
HOWTO (R_MMIX_16, /* type */ |
HOWTO (R_MMIX_16, /* type */ |
269 |
0, /* rightshift */ |
0, /* rightshift */ |
270 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
271 |
16, /* bitsize */ |
16, /* bitsize */ |
272 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
273 |
0, /* bitpos */ |
0, /* bitpos */ |
274 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
275 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
276 |
"R_MMIX_16", /* name */ |
"R_MMIX_16", /* name */ |
277 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
278 |
0, /* src_mask */ |
0, /* src_mask */ |
279 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
280 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
281 |
|
|
282 |
/* An 24 bit absolute relocation. */ |
/* An 24 bit absolute relocation. */ |
283 |
HOWTO (R_MMIX_24, /* type */ |
HOWTO (R_MMIX_24, /* type */ |
284 |
0, /* rightshift */ |
0, /* rightshift */ |
285 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
286 |
24, /* bitsize */ |
24, /* bitsize */ |
287 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
288 |
0, /* bitpos */ |
0, /* bitpos */ |
289 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
290 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
291 |
"R_MMIX_24", /* name */ |
"R_MMIX_24", /* name */ |
292 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
293 |
~0xffffff, /* src_mask */ |
~0xffffff, /* src_mask */ |
294 |
0xffffff, /* dst_mask */ |
0xffffff, /* dst_mask */ |
295 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
296 |
|
|
297 |
/* A 32 bit absolute relocation. */ |
/* A 32 bit absolute relocation. */ |
298 |
HOWTO (R_MMIX_32, /* type */ |
HOWTO (R_MMIX_32, /* type */ |
299 |
0, /* rightshift */ |
0, /* rightshift */ |
300 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
301 |
32, /* bitsize */ |
32, /* bitsize */ |
302 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
303 |
0, /* bitpos */ |
0, /* bitpos */ |
304 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
305 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
306 |
"R_MMIX_32", /* name */ |
"R_MMIX_32", /* name */ |
307 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
308 |
0, /* src_mask */ |
0, /* src_mask */ |
309 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
310 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
311 |
|
|
312 |
/* 64 bit relocation. */ |
/* 64 bit relocation. */ |
313 |
HOWTO (R_MMIX_64, /* type */ |
HOWTO (R_MMIX_64, /* type */ |
314 |
0, /* rightshift */ |
0, /* rightshift */ |
315 |
4, /* size (0 = byte, 1 = short, 2 = long) */ |
4, /* size (0 = byte, 1 = short, 2 = long) */ |
316 |
64, /* bitsize */ |
64, /* bitsize */ |
317 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
318 |
0, /* bitpos */ |
0, /* bitpos */ |
319 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
320 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
321 |
"R_MMIX_64", /* name */ |
"R_MMIX_64", /* name */ |
322 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
323 |
0, /* src_mask */ |
0, /* src_mask */ |
324 |
MINUS_ONE, /* dst_mask */ |
MINUS_ONE, /* dst_mask */ |
325 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
326 |
|
|
327 |
/* An 8 bit PC-relative relocation. */ |
/* An 8 bit PC-relative relocation. */ |
328 |
HOWTO (R_MMIX_PC_8, /* type */ |
HOWTO (R_MMIX_PC_8, /* type */ |
329 |
0, /* rightshift */ |
0, /* rightshift */ |
330 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
331 |
8, /* bitsize */ |
8, /* bitsize */ |
332 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
333 |
0, /* bitpos */ |
0, /* bitpos */ |
334 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
335 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
336 |
"R_MMIX_PC_8", /* name */ |
"R_MMIX_PC_8", /* name */ |
337 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
338 |
0, /* src_mask */ |
0, /* src_mask */ |
339 |
0xff, /* dst_mask */ |
0xff, /* dst_mask */ |
340 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
341 |
|
|
342 |
/* An 16 bit PC-relative relocation. */ |
/* An 16 bit PC-relative relocation. */ |
343 |
HOWTO (R_MMIX_PC_16, /* type */ |
HOWTO (R_MMIX_PC_16, /* type */ |
344 |
0, /* rightshift */ |
0, /* rightshift */ |
345 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
346 |
16, /* bitsize */ |
16, /* bitsize */ |
347 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
348 |
0, /* bitpos */ |
0, /* bitpos */ |
349 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
350 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
351 |
"R_MMIX_PC_16", /* name */ |
"R_MMIX_PC_16", /* name */ |
352 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
353 |
0, /* src_mask */ |
0, /* src_mask */ |
354 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
355 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
356 |
|
|
357 |
/* An 24 bit PC-relative relocation. */ |
/* An 24 bit PC-relative relocation. */ |
358 |
HOWTO (R_MMIX_PC_24, /* type */ |
HOWTO (R_MMIX_PC_24, /* type */ |
359 |
0, /* rightshift */ |
0, /* rightshift */ |
360 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
361 |
24, /* bitsize */ |
24, /* bitsize */ |
362 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
363 |
0, /* bitpos */ |
0, /* bitpos */ |
364 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
365 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
366 |
"R_MMIX_PC_24", /* name */ |
"R_MMIX_PC_24", /* name */ |
367 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
368 |
~0xffffff, /* src_mask */ |
~0xffffff, /* src_mask */ |
369 |
0xffffff, /* dst_mask */ |
0xffffff, /* dst_mask */ |
370 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
371 |
|
|
372 |
/* A 32 bit absolute PC-relative relocation. */ |
/* A 32 bit absolute PC-relative relocation. */ |
373 |
HOWTO (R_MMIX_PC_32, /* type */ |
HOWTO (R_MMIX_PC_32, /* type */ |
374 |
0, /* rightshift */ |
0, /* rightshift */ |
375 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
376 |
32, /* bitsize */ |
32, /* bitsize */ |
377 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
378 |
0, /* bitpos */ |
0, /* bitpos */ |
379 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
380 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
381 |
"R_MMIX_PC_32", /* name */ |
"R_MMIX_PC_32", /* name */ |
382 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
383 |
0, /* src_mask */ |
0, /* src_mask */ |
384 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
385 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
386 |
|
|
387 |
/* 64 bit PC-relative relocation. */ |
/* 64 bit PC-relative relocation. */ |
388 |
HOWTO (R_MMIX_PC_64, /* type */ |
HOWTO (R_MMIX_PC_64, /* type */ |
389 |
0, /* rightshift */ |
0, /* rightshift */ |
390 |
4, /* size (0 = byte, 1 = short, 2 = long) */ |
4, /* size (0 = byte, 1 = short, 2 = long) */ |
391 |
64, /* bitsize */ |
64, /* bitsize */ |
392 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
393 |
0, /* bitpos */ |
0, /* bitpos */ |
394 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
395 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
396 |
"R_MMIX_PC_64", /* name */ |
"R_MMIX_PC_64", /* name */ |
397 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
398 |
0, /* src_mask */ |
0, /* src_mask */ |
399 |
MINUS_ONE, /* dst_mask */ |
MINUS_ONE, /* dst_mask */ |
400 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
401 |
|
|
402 |
/* GNU extension to record C++ vtable hierarchy. */ |
/* GNU extension to record C++ vtable hierarchy. */ |
403 |
HOWTO (R_MMIX_GNU_VTINHERIT, /* type */ |
HOWTO (R_MMIX_GNU_VTINHERIT, /* type */ |
404 |
0, /* rightshift */ |
0, /* rightshift */ |
405 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
406 |
0, /* bitsize */ |
0, /* bitsize */ |
407 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
408 |
0, /* bitpos */ |
0, /* bitpos */ |
409 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
410 |
NULL, /* special_function */ |
NULL, /* special_function */ |
411 |
"R_MMIX_GNU_VTINHERIT", /* name */ |
"R_MMIX_GNU_VTINHERIT", /* name */ |
412 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
413 |
0, /* src_mask */ |
0, /* src_mask */ |
414 |
0, /* dst_mask */ |
0, /* dst_mask */ |
415 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
416 |
|
|
417 |
/* GNU extension to record C++ vtable member usage. */ |
/* GNU extension to record C++ vtable member usage. */ |
418 |
HOWTO (R_MMIX_GNU_VTENTRY, /* type */ |
HOWTO (R_MMIX_GNU_VTENTRY, /* type */ |
419 |
0, /* rightshift */ |
0, /* rightshift */ |
420 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
421 |
0, /* bitsize */ |
0, /* bitsize */ |
422 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
423 |
0, /* bitpos */ |
0, /* bitpos */ |
424 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
425 |
_bfd_elf_rel_vtable_reloc_fn, /* special_function */ |
_bfd_elf_rel_vtable_reloc_fn, /* special_function */ |
426 |
"R_MMIX_GNU_VTENTRY", /* name */ |
"R_MMIX_GNU_VTENTRY", /* name */ |
427 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
428 |
0, /* src_mask */ |
0, /* src_mask */ |
429 |
0, /* dst_mask */ |
0, /* dst_mask */ |
430 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
431 |
|
|
432 |
/* The GETA relocation is supposed to get any address that could |
/* The GETA relocation is supposed to get any address that could |
433 |
possibly be reached by the GETA instruction. It can silently expand |
possibly be reached by the GETA instruction. It can silently expand |
437 |
2, /* rightshift */ |
2, /* rightshift */ |
438 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
439 |
19, /* bitsize */ |
19, /* bitsize */ |
440 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
441 |
0, /* bitpos */ |
0, /* bitpos */ |
442 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
443 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
444 |
"R_MMIX_GETA", /* name */ |
"R_MMIX_GETA", /* name */ |
445 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
446 |
~0x0100ffff, /* src_mask */ |
~0x0100ffff, /* src_mask */ |
447 |
0x0100ffff, /* dst_mask */ |
0x0100ffff, /* dst_mask */ |
448 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
449 |
|
|
450 |
HOWTO (R_MMIX_GETA_1, /* type */ |
HOWTO (R_MMIX_GETA_1, /* type */ |
451 |
2, /* rightshift */ |
2, /* rightshift */ |
452 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
453 |
19, /* bitsize */ |
19, /* bitsize */ |
454 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
455 |
0, /* bitpos */ |
0, /* bitpos */ |
456 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
457 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
458 |
"R_MMIX_GETA_1", /* name */ |
"R_MMIX_GETA_1", /* name */ |
459 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
460 |
~0x0100ffff, /* src_mask */ |
~0x0100ffff, /* src_mask */ |
461 |
0x0100ffff, /* dst_mask */ |
0x0100ffff, /* dst_mask */ |
462 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
463 |
|
|
464 |
HOWTO (R_MMIX_GETA_2, /* type */ |
HOWTO (R_MMIX_GETA_2, /* type */ |
465 |
2, /* rightshift */ |
2, /* rightshift */ |
466 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
467 |
19, /* bitsize */ |
19, /* bitsize */ |
468 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
469 |
0, /* bitpos */ |
0, /* bitpos */ |
470 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
471 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
472 |
"R_MMIX_GETA_2", /* name */ |
"R_MMIX_GETA_2", /* name */ |
473 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
474 |
~0x0100ffff, /* src_mask */ |
~0x0100ffff, /* src_mask */ |
475 |
0x0100ffff, /* dst_mask */ |
0x0100ffff, /* dst_mask */ |
476 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
477 |
|
|
478 |
HOWTO (R_MMIX_GETA_3, /* type */ |
HOWTO (R_MMIX_GETA_3, /* type */ |
479 |
2, /* rightshift */ |
2, /* rightshift */ |
480 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
481 |
19, /* bitsize */ |
19, /* bitsize */ |
482 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
483 |
0, /* bitpos */ |
0, /* bitpos */ |
484 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
485 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
486 |
"R_MMIX_GETA_3", /* name */ |
"R_MMIX_GETA_3", /* name */ |
487 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
488 |
~0x0100ffff, /* src_mask */ |
~0x0100ffff, /* src_mask */ |
489 |
0x0100ffff, /* dst_mask */ |
0x0100ffff, /* dst_mask */ |
490 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
491 |
|
|
492 |
/* The conditional branches are supposed to reach any (code) address. |
/* The conditional branches are supposed to reach any (code) address. |
493 |
It can silently expand to a 64-bit operand, but will emit an error if |
It can silently expand to a 64-bit operand, but will emit an error if |
497 |
2, /* rightshift */ |
2, /* rightshift */ |
498 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
499 |
19, /* bitsize */ |
19, /* bitsize */ |
500 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
501 |
0, /* bitpos */ |
0, /* bitpos */ |
502 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
503 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
504 |
"R_MMIX_CBRANCH", /* name */ |
"R_MMIX_CBRANCH", /* name */ |
505 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
506 |
~0x0100ffff, /* src_mask */ |
~0x0100ffff, /* src_mask */ |
507 |
0x0100ffff, /* dst_mask */ |
0x0100ffff, /* dst_mask */ |
508 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
509 |
|
|
510 |
HOWTO (R_MMIX_CBRANCH_J, /* type */ |
HOWTO (R_MMIX_CBRANCH_J, /* type */ |
511 |
2, /* rightshift */ |
2, /* rightshift */ |
512 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
513 |
19, /* bitsize */ |
19, /* bitsize */ |
514 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
515 |
0, /* bitpos */ |
0, /* bitpos */ |
516 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
517 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
518 |
"R_MMIX_CBRANCH_J", /* name */ |
"R_MMIX_CBRANCH_J", /* name */ |
519 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
520 |
~0x0100ffff, /* src_mask */ |
~0x0100ffff, /* src_mask */ |
521 |
0x0100ffff, /* dst_mask */ |
0x0100ffff, /* dst_mask */ |
522 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
523 |
|
|
524 |
HOWTO (R_MMIX_CBRANCH_1, /* type */ |
HOWTO (R_MMIX_CBRANCH_1, /* type */ |
525 |
2, /* rightshift */ |
2, /* rightshift */ |
526 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
527 |
19, /* bitsize */ |
19, /* bitsize */ |
528 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
529 |
0, /* bitpos */ |
0, /* bitpos */ |
530 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
531 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
532 |
"R_MMIX_CBRANCH_1", /* name */ |
"R_MMIX_CBRANCH_1", /* name */ |
533 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
534 |
~0x0100ffff, /* src_mask */ |
~0x0100ffff, /* src_mask */ |
535 |
0x0100ffff, /* dst_mask */ |
0x0100ffff, /* dst_mask */ |
536 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
537 |
|
|
538 |
HOWTO (R_MMIX_CBRANCH_2, /* type */ |
HOWTO (R_MMIX_CBRANCH_2, /* type */ |
539 |
2, /* rightshift */ |
2, /* rightshift */ |
540 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
541 |
19, /* bitsize */ |
19, /* bitsize */ |
542 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
543 |
0, /* bitpos */ |
0, /* bitpos */ |
544 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
545 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
546 |
"R_MMIX_CBRANCH_2", /* name */ |
"R_MMIX_CBRANCH_2", /* name */ |
547 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
548 |
~0x0100ffff, /* src_mask */ |
~0x0100ffff, /* src_mask */ |
549 |
0x0100ffff, /* dst_mask */ |
0x0100ffff, /* dst_mask */ |
550 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
551 |
|
|
552 |
HOWTO (R_MMIX_CBRANCH_3, /* type */ |
HOWTO (R_MMIX_CBRANCH_3, /* type */ |
553 |
2, /* rightshift */ |
2, /* rightshift */ |
554 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
555 |
19, /* bitsize */ |
19, /* bitsize */ |
556 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
557 |
0, /* bitpos */ |
0, /* bitpos */ |
558 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
559 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
560 |
"R_MMIX_CBRANCH_3", /* name */ |
"R_MMIX_CBRANCH_3", /* name */ |
561 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
562 |
~0x0100ffff, /* src_mask */ |
~0x0100ffff, /* src_mask */ |
563 |
0x0100ffff, /* dst_mask */ |
0x0100ffff, /* dst_mask */ |
564 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
565 |
|
|
566 |
/* The PUSHJ instruction can reach any (code) address, as long as it's |
/* The PUSHJ instruction can reach any (code) address, as long as it's |
567 |
the beginning of a function (no usable restriction). It can silently |
the beginning of a function (no usable restriction). It can silently |
568 |
expand to a 64-bit operand, but will emit an error if any of the two |
expand to a 64-bit operand, but will emit an error if any of the two |
569 |
least significant bits are set. The howto members reflect a simple |
least significant bits are set. It can also expand into a call to a |
570 |
|
stub; see R_MMIX_PUSHJ_STUBBABLE. The howto members reflect a simple |
571 |
PUSHJ. */ |
PUSHJ. */ |
572 |
HOWTO (R_MMIX_PUSHJ, /* type */ |
HOWTO (R_MMIX_PUSHJ, /* type */ |
573 |
2, /* rightshift */ |
2, /* rightshift */ |
574 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
575 |
19, /* bitsize */ |
19, /* bitsize */ |
576 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
577 |
0, /* bitpos */ |
0, /* bitpos */ |
578 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
579 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
580 |
"R_MMIX_PUSHJ", /* name */ |
"R_MMIX_PUSHJ", /* name */ |
581 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
582 |
~0x0100ffff, /* src_mask */ |
~0x0100ffff, /* src_mask */ |
583 |
0x0100ffff, /* dst_mask */ |
0x0100ffff, /* dst_mask */ |
584 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
585 |
|
|
586 |
HOWTO (R_MMIX_PUSHJ_1, /* type */ |
HOWTO (R_MMIX_PUSHJ_1, /* type */ |
587 |
2, /* rightshift */ |
2, /* rightshift */ |
588 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
589 |
19, /* bitsize */ |
19, /* bitsize */ |
590 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
591 |
0, /* bitpos */ |
0, /* bitpos */ |
592 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
593 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
594 |
"R_MMIX_PUSHJ_1", /* name */ |
"R_MMIX_PUSHJ_1", /* name */ |
595 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
596 |
~0x0100ffff, /* src_mask */ |
~0x0100ffff, /* src_mask */ |
597 |
0x0100ffff, /* dst_mask */ |
0x0100ffff, /* dst_mask */ |
598 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
599 |
|
|
600 |
HOWTO (R_MMIX_PUSHJ_2, /* type */ |
HOWTO (R_MMIX_PUSHJ_2, /* type */ |
601 |
2, /* rightshift */ |
2, /* rightshift */ |
602 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
603 |
19, /* bitsize */ |
19, /* bitsize */ |
604 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
605 |
0, /* bitpos */ |
0, /* bitpos */ |
606 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
607 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
608 |
"R_MMIX_PUSHJ_2", /* name */ |
"R_MMIX_PUSHJ_2", /* name */ |
609 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
610 |
~0x0100ffff, /* src_mask */ |
~0x0100ffff, /* src_mask */ |
611 |
0x0100ffff, /* dst_mask */ |
0x0100ffff, /* dst_mask */ |
612 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
613 |
|
|
614 |
HOWTO (R_MMIX_PUSHJ_3, /* type */ |
HOWTO (R_MMIX_PUSHJ_3, /* type */ |
615 |
2, /* rightshift */ |
2, /* rightshift */ |
616 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
617 |
19, /* bitsize */ |
19, /* bitsize */ |
618 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
619 |
0, /* bitpos */ |
0, /* bitpos */ |
620 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
621 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
622 |
"R_MMIX_PUSHJ_3", /* name */ |
"R_MMIX_PUSHJ_3", /* name */ |
623 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
624 |
~0x0100ffff, /* src_mask */ |
~0x0100ffff, /* src_mask */ |
625 |
0x0100ffff, /* dst_mask */ |
0x0100ffff, /* dst_mask */ |
626 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
627 |
|
|
628 |
/* A JMP is supposed to reach any (code) address. By itself, it can |
/* A JMP is supposed to reach any (code) address. By itself, it can |
629 |
reach +-64M; the expansion can reach all 64 bits. Note that the 64M |
reach +-64M; the expansion can reach all 64 bits. Note that the 64M |
633 |
2, /* rightshift */ |
2, /* rightshift */ |
634 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
635 |
27, /* bitsize */ |
27, /* bitsize */ |
636 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
637 |
0, /* bitpos */ |
0, /* bitpos */ |
638 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
639 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
640 |
"R_MMIX_JMP", /* name */ |
"R_MMIX_JMP", /* name */ |
641 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
642 |
~0x1ffffff, /* src_mask */ |
~0x1ffffff, /* src_mask */ |
643 |
0x1ffffff, /* dst_mask */ |
0x1ffffff, /* dst_mask */ |
644 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
645 |
|
|
646 |
HOWTO (R_MMIX_JMP_1, /* type */ |
HOWTO (R_MMIX_JMP_1, /* type */ |
647 |
2, /* rightshift */ |
2, /* rightshift */ |
648 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
649 |
27, /* bitsize */ |
27, /* bitsize */ |
650 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
651 |
0, /* bitpos */ |
0, /* bitpos */ |
652 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
653 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
654 |
"R_MMIX_JMP_1", /* name */ |
"R_MMIX_JMP_1", /* name */ |
655 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
656 |
~0x1ffffff, /* src_mask */ |
~0x1ffffff, /* src_mask */ |
657 |
0x1ffffff, /* dst_mask */ |
0x1ffffff, /* dst_mask */ |
658 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
659 |
|
|
660 |
HOWTO (R_MMIX_JMP_2, /* type */ |
HOWTO (R_MMIX_JMP_2, /* type */ |
661 |
2, /* rightshift */ |
2, /* rightshift */ |
662 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
663 |
27, /* bitsize */ |
27, /* bitsize */ |
664 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
665 |
0, /* bitpos */ |
0, /* bitpos */ |
666 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
667 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
668 |
"R_MMIX_JMP_2", /* name */ |
"R_MMIX_JMP_2", /* name */ |
669 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
670 |
~0x1ffffff, /* src_mask */ |
~0x1ffffff, /* src_mask */ |
671 |
0x1ffffff, /* dst_mask */ |
0x1ffffff, /* dst_mask */ |
672 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
673 |
|
|
674 |
HOWTO (R_MMIX_JMP_3, /* type */ |
HOWTO (R_MMIX_JMP_3, /* type */ |
675 |
2, /* rightshift */ |
2, /* rightshift */ |
676 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
677 |
27, /* bitsize */ |
27, /* bitsize */ |
678 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
679 |
0, /* bitpos */ |
0, /* bitpos */ |
680 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
681 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
682 |
"R_MMIX_JMP_3", /* name */ |
"R_MMIX_JMP_3", /* name */ |
683 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
684 |
~0x1ffffff, /* src_mask */ |
~0x1ffffff, /* src_mask */ |
685 |
0x1ffffff, /* dst_mask */ |
0x1ffffff, /* dst_mask */ |
686 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
687 |
|
|
688 |
/* When we don't emit link-time-relaxable code from the assembler, or |
/* When we don't emit link-time-relaxable code from the assembler, or |
689 |
when relaxation has done all it can do, these relocs are used. For |
when relaxation has done all it can do, these relocs are used. For |
692 |
2, /* rightshift */ |
2, /* rightshift */ |
693 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
694 |
19, /* bitsize */ |
19, /* bitsize */ |
695 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
696 |
0, /* bitpos */ |
0, /* bitpos */ |
697 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
698 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
699 |
"R_MMIX_ADDR19", /* name */ |
"R_MMIX_ADDR19", /* name */ |
700 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
701 |
~0x0100ffff, /* src_mask */ |
~0x0100ffff, /* src_mask */ |
702 |
0x0100ffff, /* dst_mask */ |
0x0100ffff, /* dst_mask */ |
703 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
704 |
|
|
705 |
/* For JMP. */ |
/* For JMP. */ |
706 |
HOWTO (R_MMIX_ADDR27, /* type */ |
HOWTO (R_MMIX_ADDR27, /* type */ |
707 |
2, /* rightshift */ |
2, /* rightshift */ |
708 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
709 |
27, /* bitsize */ |
27, /* bitsize */ |
710 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
711 |
0, /* bitpos */ |
0, /* bitpos */ |
712 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
713 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
714 |
"R_MMIX_ADDR27", /* name */ |
"R_MMIX_ADDR27", /* name */ |
715 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
716 |
~0x1ffffff, /* src_mask */ |
~0x1ffffff, /* src_mask */ |
717 |
0x1ffffff, /* dst_mask */ |
0x1ffffff, /* dst_mask */ |
718 |
true), /* pcrel_offset */ |
TRUE), /* pcrel_offset */ |
719 |
|
|
720 |
/* A general register or the value 0..255. If a value, then the |
/* A general register or the value 0..255. If a value, then the |
721 |
instruction (offset -3) needs adjusting. */ |
instruction (offset -3) needs adjusting. */ |
723 |
0, /* rightshift */ |
0, /* rightshift */ |
724 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
725 |
8, /* bitsize */ |
8, /* bitsize */ |
726 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
727 |
0, /* bitpos */ |
0, /* bitpos */ |
728 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
729 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
730 |
"R_MMIX_REG_OR_BYTE", /* name */ |
"R_MMIX_REG_OR_BYTE", /* name */ |
731 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
732 |
0, /* src_mask */ |
0, /* src_mask */ |
733 |
0xff, /* dst_mask */ |
0xff, /* dst_mask */ |
734 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
735 |
|
|
736 |
/* A general register. */ |
/* A general register. */ |
737 |
HOWTO (R_MMIX_REG, /* type */ |
HOWTO (R_MMIX_REG, /* type */ |
738 |
0, /* rightshift */ |
0, /* rightshift */ |
739 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
740 |
8, /* bitsize */ |
8, /* bitsize */ |
741 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
742 |
0, /* bitpos */ |
0, /* bitpos */ |
743 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
744 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
745 |
"R_MMIX_REG", /* name */ |
"R_MMIX_REG", /* name */ |
746 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
747 |
0, /* src_mask */ |
0, /* src_mask */ |
748 |
0xff, /* dst_mask */ |
0xff, /* dst_mask */ |
749 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
750 |
|
|
751 |
/* A register plus an index, corresponding to the relocation expression. |
/* A register plus an index, corresponding to the relocation expression. |
752 |
The sizes must correspond to the valid range of the expression, while |
The sizes must correspond to the valid range of the expression, while |
755 |
0, /* rightshift */ |
0, /* rightshift */ |
756 |
4, /* size (0 = byte, 1 = short, 2 = long) */ |
4, /* size (0 = byte, 1 = short, 2 = long) */ |
757 |
64, /* bitsize */ |
64, /* bitsize */ |
758 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
759 |
0, /* bitpos */ |
0, /* bitpos */ |
760 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
761 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
762 |
"R_MMIX_BASE_PLUS_OFFSET", /* name */ |
"R_MMIX_BASE_PLUS_OFFSET", /* name */ |
763 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
764 |
0, /* src_mask */ |
0, /* src_mask */ |
765 |
0xffff, /* dst_mask */ |
0xffff, /* dst_mask */ |
766 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
767 |
|
|
768 |
/* A "magic" relocation for a LOCAL expression, asserting that the |
/* A "magic" relocation for a LOCAL expression, asserting that the |
769 |
expression is less than the number of global registers. No actual |
expression is less than the number of global registers. No actual |
774 |
0, /* rightshift */ |
0, /* rightshift */ |
775 |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
0, /* size (0 = byte, 1 = short, 2 = long) */ |
776 |
0, /* bitsize */ |
0, /* bitsize */ |
777 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
778 |
0, /* bitpos */ |
0, /* bitpos */ |
779 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
780 |
mmix_elf_reloc, /* special_function */ |
mmix_elf_reloc, /* special_function */ |
781 |
"R_MMIX_LOCAL", /* name */ |
"R_MMIX_LOCAL", /* name */ |
782 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
783 |
0, /* src_mask */ |
0, /* src_mask */ |
784 |
0, /* dst_mask */ |
0, /* dst_mask */ |
785 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
786 |
|
|
787 |
|
HOWTO (R_MMIX_PUSHJ_STUBBABLE, /* type */ |
788 |
|
2, /* rightshift */ |
789 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
790 |
|
19, /* bitsize */ |
791 |
|
TRUE, /* pc_relative */ |
792 |
|
0, /* bitpos */ |
793 |
|
complain_overflow_signed, /* complain_on_overflow */ |
794 |
|
mmix_elf_reloc, /* special_function */ |
795 |
|
"R_MMIX_PUSHJ_STUBBABLE", /* name */ |
796 |
|
FALSE, /* partial_inplace */ |
797 |
|
~0x0100ffff, /* src_mask */ |
798 |
|
0x0100ffff, /* dst_mask */ |
799 |
|
TRUE) /* pcrel_offset */ |
800 |
}; |
}; |
801 |
|
|
802 |
|
|
833 |
{BFD_RELOC_MMIX_REG_OR_BYTE, R_MMIX_REG_OR_BYTE}, |
{BFD_RELOC_MMIX_REG_OR_BYTE, R_MMIX_REG_OR_BYTE}, |
834 |
{BFD_RELOC_MMIX_REG, R_MMIX_REG}, |
{BFD_RELOC_MMIX_REG, R_MMIX_REG}, |
835 |
{BFD_RELOC_MMIX_BASE_PLUS_OFFSET, R_MMIX_BASE_PLUS_OFFSET}, |
{BFD_RELOC_MMIX_BASE_PLUS_OFFSET, R_MMIX_BASE_PLUS_OFFSET}, |
836 |
{BFD_RELOC_MMIX_LOCAL, R_MMIX_LOCAL} |
{BFD_RELOC_MMIX_LOCAL, R_MMIX_LOCAL}, |
837 |
|
{BFD_RELOC_MMIX_PUSHJ_STUBBABLE, R_MMIX_PUSHJ_STUBBABLE} |
838 |
}; |
}; |
839 |
|
|
840 |
static reloc_howto_type * |
static reloc_howto_type * |
855 |
return NULL; |
return NULL; |
856 |
} |
} |
857 |
|
|
858 |
|
static bfd_boolean |
859 |
|
mmix_elf_new_section_hook (abfd, sec) |
860 |
|
bfd *abfd; |
861 |
|
asection *sec; |
862 |
|
{ |
863 |
|
struct _mmix_elf_section_data *sdata; |
864 |
|
bfd_size_type amt = sizeof (*sdata); |
865 |
|
|
866 |
|
sdata = (struct _mmix_elf_section_data *) bfd_zalloc (abfd, amt); |
867 |
|
if (sdata == NULL) |
868 |
|
return FALSE; |
869 |
|
sec->used_by_bfd = (PTR) sdata; |
870 |
|
|
871 |
|
return _bfd_elf_new_section_hook (abfd, sec); |
872 |
|
} |
873 |
|
|
874 |
|
|
875 |
/* This function performs the actual bitfiddling and sanity check for a |
/* This function performs the actual bitfiddling and sanity check for a |
876 |
final relocation. Each relocation gets its *worst*-case expansion |
final relocation. Each relocation gets its *worst*-case expansion |
924 |
asection *isec; |
asection *isec; |
925 |
reloc_howto_type *howto; |
reloc_howto_type *howto; |
926 |
PTR datap; |
PTR datap; |
927 |
bfd_vma addr ATTRIBUTE_UNUSED; |
bfd_vma addr; |
928 |
bfd_vma value; |
bfd_vma value; |
929 |
{ |
{ |
930 |
bfd *abfd = isec->owner; |
bfd *abfd = isec->owner; |
975 |
} |
} |
976 |
break; |
break; |
977 |
|
|
978 |
|
case R_MMIX_PUSHJ_STUBBABLE: |
979 |
|
/* If the address fits, we're fine. */ |
980 |
|
if ((value & 3) == 0 |
981 |
|
/* Note rightshift 0; see R_MMIX_JMP case below. */ |
982 |
|
&& (r = bfd_check_overflow (complain_overflow_signed, |
983 |
|
howto->bitsize, |
984 |
|
0, |
985 |
|
bfd_arch_bits_per_address (abfd), |
986 |
|
value)) == bfd_reloc_ok) |
987 |
|
goto pcrel_mmix_reloc_fits; |
988 |
|
else |
989 |
|
{ |
990 |
|
bfd_size_type size = isec->rawsize ? isec->rawsize : isec->size; |
991 |
|
|
992 |
|
/* We have the bytes at the PUSHJ insn and need to get the |
993 |
|
position for the stub. There's supposed to be room allocated |
994 |
|
for the stub. */ |
995 |
|
bfd_byte *stubcontents |
996 |
|
= ((bfd_byte *) datap |
997 |
|
- (addr - (isec->output_section->vma + isec->output_offset)) |
998 |
|
+ size |
999 |
|
+ mmix_elf_section_data (isec)->pjs.stub_offset); |
1000 |
|
bfd_vma stubaddr; |
1001 |
|
|
1002 |
|
/* The address doesn't fit, so redirect the PUSHJ to the |
1003 |
|
location of the stub. */ |
1004 |
|
r = mmix_elf_perform_relocation (isec, |
1005 |
|
&elf_mmix_howto_table |
1006 |
|
[R_MMIX_ADDR19], |
1007 |
|
datap, |
1008 |
|
addr, |
1009 |
|
isec->output_section->vma |
1010 |
|
+ isec->output_offset |
1011 |
|
+ size |
1012 |
|
+ (mmix_elf_section_data (isec) |
1013 |
|
->pjs.stub_offset) |
1014 |
|
- addr); |
1015 |
|
if (r != bfd_reloc_ok) |
1016 |
|
return r; |
1017 |
|
|
1018 |
|
stubaddr |
1019 |
|
= (isec->output_section->vma |
1020 |
|
+ isec->output_offset |
1021 |
|
+ size |
1022 |
|
+ mmix_elf_section_data (isec)->pjs.stub_offset); |
1023 |
|
|
1024 |
|
/* We generate a simple JMP if that suffices, else the whole 5 |
1025 |
|
insn stub. */ |
1026 |
|
if (bfd_check_overflow (complain_overflow_signed, |
1027 |
|
elf_mmix_howto_table[R_MMIX_ADDR27].bitsize, |
1028 |
|
0, |
1029 |
|
bfd_arch_bits_per_address (abfd), |
1030 |
|
addr + value - stubaddr) == bfd_reloc_ok) |
1031 |
|
{ |
1032 |
|
bfd_put_32 (abfd, JMP_INSN_BYTE << 24, stubcontents); |
1033 |
|
r = mmix_elf_perform_relocation (isec, |
1034 |
|
&elf_mmix_howto_table |
1035 |
|
[R_MMIX_ADDR27], |
1036 |
|
stubcontents, |
1037 |
|
stubaddr, |
1038 |
|
value + addr - stubaddr); |
1039 |
|
mmix_elf_section_data (isec)->pjs.stub_offset += 4; |
1040 |
|
|
1041 |
|
if (size + mmix_elf_section_data (isec)->pjs.stub_offset |
1042 |
|
> isec->size) |
1043 |
|
abort (); |
1044 |
|
|
1045 |
|
return r; |
1046 |
|
} |
1047 |
|
else |
1048 |
|
{ |
1049 |
|
/* Put a "GO $255,0" after the common sequence. */ |
1050 |
|
bfd_put_32 (abfd, |
1051 |
|
((GO_INSN_BYTE | IMM_OFFSET_BIT) << 24) |
1052 |
|
| 0xff00, (bfd_byte *) stubcontents + 16); |
1053 |
|
|
1054 |
|
/* Prepare for the general code to set the first part of the |
1055 |
|
linker stub, and */ |
1056 |
|
value += addr; |
1057 |
|
datap = stubcontents; |
1058 |
|
mmix_elf_section_data (isec)->pjs.stub_offset |
1059 |
|
+= MAX_PUSHJ_STUB_SIZE; |
1060 |
|
} |
1061 |
|
} |
1062 |
|
break; |
1063 |
|
|
1064 |
case R_MMIX_PUSHJ: |
case R_MMIX_PUSHJ: |
1065 |
{ |
{ |
1066 |
int inreg = bfd_get_8 (abfd, (bfd_byte *) datap + 1); |
int inreg = bfd_get_8 (abfd, (bfd_byte *) datap + 1); |
1108 |
/* FALLTHROUGH. */ |
/* FALLTHROUGH. */ |
1109 |
case R_MMIX_ADDR19: |
case R_MMIX_ADDR19: |
1110 |
case R_MMIX_ADDR27: |
case R_MMIX_ADDR27: |
1111 |
|
pcrel_mmix_reloc_fits: |
1112 |
/* These must be in range, or else we emit an error. */ |
/* These must be in range, or else we emit an error. */ |
1113 |
if ((value & 3) == 0 |
if ((value & 3) == 0 |
1114 |
/* Note rightshift 0; see above. */ |
/* Note rightshift 0; see above. */ |
1124 |
|
|
1125 |
if ((bfd_signed_vma) value < 0) |
if ((bfd_signed_vma) value < 0) |
1126 |
{ |
{ |
1127 |
highbit = (1 << 24); |
highbit = 1 << 24; |
1128 |
value += (1 << (howto->bitsize - 1)); |
value += (1 << (howto->bitsize - 1)); |
1129 |
} |
} |
1130 |
else |
else |
1146 |
case R_MMIX_BASE_PLUS_OFFSET: |
case R_MMIX_BASE_PLUS_OFFSET: |
1147 |
{ |
{ |
1148 |
struct bpo_reloc_section_info *bpodata |
struct bpo_reloc_section_info *bpodata |
1149 |
= (struct bpo_reloc_section_info *) |
= mmix_elf_section_data (isec)->bpo.reloc; |
|
elf_section_data (isec)->tdata; |
|
1150 |
asection *bpo_greg_section |
asection *bpo_greg_section |
1151 |
= bpodata->bpo_greg_section; |
= bpodata->bpo_greg_section; |
1152 |
struct bpo_greg_section_info *gregdata |
struct bpo_greg_section_info *gregdata |
1153 |
= (struct bpo_greg_section_info *) |
= mmix_elf_section_data (bpo_greg_section)->bpo.greg; |
|
elf_section_data (bpo_greg_section)->tdata; |
|
1154 |
size_t bpo_index |
size_t bpo_index |
1155 |
= gregdata->bpo_reloc_indexes[bpodata->bpo_index++]; |
= gregdata->bpo_reloc_indexes[bpodata->bpo_index++]; |
1156 |
|
|
1224 |
mmix_info_to_howto_rela (abfd, cache_ptr, dst) |
mmix_info_to_howto_rela (abfd, cache_ptr, dst) |
1225 |
bfd *abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
1226 |
arelent *cache_ptr; |
arelent *cache_ptr; |
1227 |
Elf64_Internal_Rela *dst; |
Elf_Internal_Rela *dst; |
1228 |
{ |
{ |
1229 |
unsigned int r_type; |
unsigned int r_type; |
1230 |
|
|
1269 |
return bfd_reloc_undefined; |
return bfd_reloc_undefined; |
1270 |
|
|
1271 |
/* Is the address of the relocation really within the section? */ |
/* Is the address of the relocation really within the section? */ |
1272 |
if (reloc_entry->address > input_section->_cooked_size) |
if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) |
1273 |
return bfd_reloc_outofrange; |
return bfd_reloc_outofrange; |
1274 |
|
|
1275 |
/* Work out which section the relocation is targetted at and the |
/* Work out which section the relocation is targeted at and the |
1276 |
initial relocation command value. */ |
initial relocation command value. */ |
1277 |
|
|
1278 |
/* Get symbol value. (Common symbols are special.) */ |
/* Get symbol value. (Common symbols are special.) */ |
1318 |
/* Relocate an MMIX ELF section. Modified from elf32-fr30.c; look to it |
/* Relocate an MMIX ELF section. Modified from elf32-fr30.c; look to it |
1319 |
for guidance if you're thinking of copying this. */ |
for guidance if you're thinking of copying this. */ |
1320 |
|
|
1321 |
static boolean |
static bfd_boolean |
1322 |
mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section, |
mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section, |
1323 |
contents, relocs, local_syms, local_sections) |
contents, relocs, local_syms, local_sections) |
1324 |
bfd *output_bfd ATTRIBUTE_UNUSED; |
bfd *output_bfd ATTRIBUTE_UNUSED; |
1334 |
struct elf_link_hash_entry **sym_hashes; |
struct elf_link_hash_entry **sym_hashes; |
1335 |
Elf_Internal_Rela *rel; |
Elf_Internal_Rela *rel; |
1336 |
Elf_Internal_Rela *relend; |
Elf_Internal_Rela *relend; |
1337 |
|
bfd_size_type size; |
1338 |
|
size_t pjsno = 0; |
1339 |
|
|
1340 |
|
size = input_section->rawsize ? input_section->rawsize : input_section->size; |
1341 |
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; |
1342 |
sym_hashes = elf_sym_hashes (input_bfd); |
sym_hashes = elf_sym_hashes (input_bfd); |
1343 |
relend = relocs + input_section->reloc_count; |
relend = relocs + input_section->reloc_count; |
1344 |
|
|
1345 |
|
/* Zero the stub area before we start. */ |
1346 |
|
if (input_section->rawsize != 0 |
1347 |
|
&& input_section->size > input_section->rawsize) |
1348 |
|
memset (contents + input_section->rawsize, 0, |
1349 |
|
input_section->size - input_section->rawsize); |
1350 |
|
|
1351 |
for (rel = relocs; rel < relend; rel ++) |
for (rel = relocs; rel < relend; rel ++) |
1352 |
{ |
{ |
1353 |
reloc_howto_type *howto; |
reloc_howto_type *howto; |
1359 |
bfd_reloc_status_type r; |
bfd_reloc_status_type r; |
1360 |
const char *name = NULL; |
const char *name = NULL; |
1361 |
int r_type; |
int r_type; |
1362 |
boolean undefined_signalled = false; |
bfd_boolean undefined_signalled = FALSE; |
1363 |
|
|
1364 |
r_type = ELF64_R_TYPE (rel->r_info); |
r_type = ELF64_R_TYPE (rel->r_info); |
1365 |
|
|
1369 |
|
|
1370 |
r_symndx = ELF64_R_SYM (rel->r_info); |
r_symndx = ELF64_R_SYM (rel->r_info); |
1371 |
|
|
1372 |
if (info->relocateable) |
if (info->relocatable) |
1373 |
{ |
{ |
1374 |
/* This is a relocateable link. We don't have to change |
/* This is a relocatable link. For most relocs we don't have to |
1375 |
anything, unless the reloc is against a section symbol, |
change anything, unless the reloc is against a section |
1376 |
in which case we have to adjust according to where the |
symbol, in which case we have to adjust according to where |
1377 |
section symbol winds up in the output section. */ |
the section symbol winds up in the output section. */ |
1378 |
if (r_symndx < symtab_hdr->sh_info) |
if (r_symndx < symtab_hdr->sh_info) |
1379 |
{ |
{ |
1380 |
sym = local_syms + r_symndx; |
sym = local_syms + r_symndx; |
1386 |
} |
} |
1387 |
} |
} |
1388 |
|
|
1389 |
|
/* For PUSHJ stub relocs however, we may need to change the |
1390 |
|
reloc and the section contents, if the reloc doesn't reach |
1391 |
|
beyond the end of the output section and previous stubs. |
1392 |
|
Then we change the section contents to be a PUSHJ to the end |
1393 |
|
of the input section plus stubs (we can do that without using |
1394 |
|
a reloc), and then we change the reloc to be a R_MMIX_PUSHJ |
1395 |
|
at the stub location. */ |
1396 |
|
if (r_type == R_MMIX_PUSHJ_STUBBABLE) |
1397 |
|
{ |
1398 |
|
/* We've already checked whether we need a stub; use that |
1399 |
|
knowledge. */ |
1400 |
|
if (mmix_elf_section_data (input_section)->pjs.stub_size[pjsno] |
1401 |
|
!= 0) |
1402 |
|
{ |
1403 |
|
Elf_Internal_Rela relcpy; |
1404 |
|
|
1405 |
|
if (mmix_elf_section_data (input_section) |
1406 |
|
->pjs.stub_size[pjsno] != MAX_PUSHJ_STUB_SIZE) |
1407 |
|
abort (); |
1408 |
|
|
1409 |
|
/* There's already a PUSHJ insn there, so just fill in |
1410 |
|
the offset bits to the stub. */ |
1411 |
|
if (mmix_final_link_relocate (elf_mmix_howto_table |
1412 |
|
+ R_MMIX_ADDR19, |
1413 |
|
input_section, |
1414 |
|
contents, |
1415 |
|
rel->r_offset, |
1416 |
|
0, |
1417 |
|
input_section |
1418 |
|
->output_section->vma |
1419 |
|
+ input_section->output_offset |
1420 |
|
+ size |
1421 |
|
+ mmix_elf_section_data (input_section) |
1422 |
|
->pjs.stub_offset, |
1423 |
|
NULL, NULL) != bfd_reloc_ok) |
1424 |
|
return FALSE; |
1425 |
|
|
1426 |
|
/* Put a JMP insn at the stub; it goes with the |
1427 |
|
R_MMIX_JMP reloc. */ |
1428 |
|
bfd_put_32 (output_bfd, JMP_INSN_BYTE << 24, |
1429 |
|
contents |
1430 |
|
+ size |
1431 |
|
+ mmix_elf_section_data (input_section) |
1432 |
|
->pjs.stub_offset); |
1433 |
|
|
1434 |
|
/* Change the reloc to be at the stub, and to a full |
1435 |
|
R_MMIX_JMP reloc. */ |
1436 |
|
rel->r_info = ELF64_R_INFO (r_symndx, R_MMIX_JMP); |
1437 |
|
rel->r_offset |
1438 |
|
= (size |
1439 |
|
+ mmix_elf_section_data (input_section) |
1440 |
|
->pjs.stub_offset); |
1441 |
|
|
1442 |
|
mmix_elf_section_data (input_section)->pjs.stub_offset |
1443 |
|
+= MAX_PUSHJ_STUB_SIZE; |
1444 |
|
|
1445 |
|
/* Shift this reloc to the end of the relocs to maintain |
1446 |
|
the r_offset sorted reloc order. */ |
1447 |
|
relcpy = *rel; |
1448 |
|
memmove (rel, rel + 1, (char *) relend - (char *) rel); |
1449 |
|
relend[-1] = relcpy; |
1450 |
|
|
1451 |
|
/* Back up one reloc, or else we'd skip the next reloc |
1452 |
|
in turn. */ |
1453 |
|
rel--; |
1454 |
|
} |
1455 |
|
|
1456 |
|
pjsno++; |
1457 |
|
} |
1458 |
continue; |
continue; |
1459 |
} |
} |
1460 |
|
|
1468 |
{ |
{ |
1469 |
sym = local_syms + r_symndx; |
sym = local_syms + r_symndx; |
1470 |
sec = local_sections [r_symndx]; |
sec = local_sections [r_symndx]; |
1471 |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); |
1472 |
|
|
1473 |
name = bfd_elf_string_from_elf_section |
name = bfd_elf_string_from_elf_section (input_bfd, |
1474 |
(input_bfd, symtab_hdr->sh_link, sym->st_name); |
symtab_hdr->sh_link, |
1475 |
name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; |
sym->st_name); |
1476 |
|
if (name == NULL) |
1477 |
|
name = bfd_section_name (input_bfd, sec); |
1478 |
} |
} |
1479 |
else |
else |
1480 |
{ |
{ |
1481 |
h = sym_hashes [r_symndx - symtab_hdr->sh_info]; |
bfd_boolean unresolved_reloc; |
|
|
|
|
while (h->root.type == bfd_link_hash_indirect |
|
|
|| h->root.type == bfd_link_hash_warning) |
|
|
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
|
1482 |
|
|
1483 |
|
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, |
1484 |
|
r_symndx, symtab_hdr, sym_hashes, |
1485 |
|
h, sec, relocation, |
1486 |
|
unresolved_reloc, undefined_signalled); |
1487 |
name = h->root.root.string; |
name = h->root.root.string; |
|
|
|
|
if (h->root.type == bfd_link_hash_defined |
|
|
|| h->root.type == bfd_link_hash_defweak) |
|
|
{ |
|
|
sec = h->root.u.def.section; |
|
|
relocation = (h->root.u.def.value |
|
|
+ sec->output_section->vma |
|
|
+ sec->output_offset); |
|
|
} |
|
|
else if (h->root.type == bfd_link_hash_undefweak) |
|
|
relocation = 0; |
|
|
else if (info->shared |
|
|
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) |
|
|
relocation = 0; |
|
|
else |
|
|
{ |
|
|
/* The test on undefined_signalled is redundant at the |
|
|
moment, but kept for symmetry. */ |
|
|
if (! undefined_signalled |
|
|
&& ! ((*info->callbacks->undefined_symbol) |
|
|
(info, h->root.root.string, input_bfd, |
|
|
input_section, rel->r_offset, true))) |
|
|
return false; |
|
|
undefined_signalled = true; |
|
|
relocation = 0; |
|
|
} |
|
1488 |
} |
} |
1489 |
|
|
1490 |
r = mmix_final_link_relocate (howto, input_section, |
r = mmix_final_link_relocate (howto, input_section, |
1493 |
|
|
1494 |
if (r != bfd_reloc_ok) |
if (r != bfd_reloc_ok) |
1495 |
{ |
{ |
1496 |
boolean check_ok = true; |
bfd_boolean check_ok = TRUE; |
1497 |
const char * msg = (const char *) NULL; |
const char * msg = (const char *) NULL; |
1498 |
|
|
1499 |
switch (r) |
switch (r) |
1500 |
{ |
{ |
1501 |
case bfd_reloc_overflow: |
case bfd_reloc_overflow: |
1502 |
check_ok = info->callbacks->reloc_overflow |
check_ok = info->callbacks->reloc_overflow |
1503 |
(info, name, howto->name, (bfd_vma) 0, |
(info, (h ? &h->root : NULL), name, howto->name, |
1504 |
input_bfd, input_section, rel->r_offset); |
(bfd_vma) 0, input_bfd, input_section, rel->r_offset); |
1505 |
break; |
break; |
1506 |
|
|
1507 |
case bfd_reloc_undefined: |
case bfd_reloc_undefined: |
1509 |
if (! undefined_signalled) |
if (! undefined_signalled) |
1510 |
check_ok = info->callbacks->undefined_symbol |
check_ok = info->callbacks->undefined_symbol |
1511 |
(info, name, input_bfd, input_section, rel->r_offset, |
(info, name, input_bfd, input_section, rel->r_offset, |
1512 |
true); |
TRUE); |
1513 |
undefined_signalled = true; |
undefined_signalled = TRUE; |
1514 |
break; |
break; |
1515 |
|
|
1516 |
case bfd_reloc_outofrange: |
case bfd_reloc_outofrange: |
1535 |
(info, msg, name, input_bfd, input_section, rel->r_offset); |
(info, msg, name, input_bfd, input_section, rel->r_offset); |
1536 |
|
|
1537 |
if (! check_ok) |
if (! check_ok) |
1538 |
return false; |
return FALSE; |
1539 |
} |
} |
1540 |
} |
} |
1541 |
|
|
1542 |
return true; |
return TRUE; |
1543 |
} |
} |
1544 |
|
|
1545 |
/* Perform a single relocation. By default we use the standard BFD |
/* Perform a single relocation. By default we use the standard BFD |
1568 |
switch (howto->type) |
switch (howto->type) |
1569 |
{ |
{ |
1570 |
/* All these are PC-relative. */ |
/* All these are PC-relative. */ |
1571 |
|
case R_MMIX_PUSHJ_STUBBABLE: |
1572 |
case R_MMIX_PUSHJ: |
case R_MMIX_PUSHJ: |
1573 |
case R_MMIX_CBRANCH: |
case R_MMIX_CBRANCH: |
1574 |
case R_MMIX_ADDR19: |
case R_MMIX_ADDR19: |
1781 |
GC (or section merge) and the point when all input sections must be |
GC (or section merge) and the point when all input sections must be |
1782 |
present. Better to waste some memory and (perhaps) a little time. */ |
present. Better to waste some memory and (perhaps) a little time. */ |
1783 |
|
|
1784 |
static boolean |
static bfd_boolean |
1785 |
mmix_elf_gc_sweep_hook (abfd, info, sec, relocs) |
mmix_elf_gc_sweep_hook (abfd, info, sec, relocs) |
1786 |
bfd *abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
1787 |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
1789 |
const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED; |
const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED; |
1790 |
{ |
{ |
1791 |
struct bpo_reloc_section_info *bpodata |
struct bpo_reloc_section_info *bpodata |
1792 |
= (struct bpo_reloc_section_info *) |
= mmix_elf_section_data (sec)->bpo.reloc; |
|
elf_section_data (sec)->tdata; |
|
1793 |
asection *allocated_gregs_section; |
asection *allocated_gregs_section; |
1794 |
|
|
1795 |
/* If no bpodata here, we have nothing to do. */ |
/* If no bpodata here, we have nothing to do. */ |
1796 |
if (bpodata == NULL) |
if (bpodata == NULL) |
1797 |
return true; |
return TRUE; |
1798 |
|
|
1799 |
allocated_gregs_section = bpodata->bpo_greg_section; |
allocated_gregs_section = bpodata->bpo_greg_section; |
1800 |
|
|
1801 |
((struct bpo_greg_section_info *) |
mmix_elf_section_data (allocated_gregs_section)->bpo.greg->n_bpo_relocs |
|
elf_section_data (allocated_gregs_section)->tdata) |
|
|
->n_bpo_relocs |
|
1802 |
-= bpodata->n_bpo_relocs_this_section; |
-= bpodata->n_bpo_relocs_this_section; |
1803 |
|
|
1804 |
return true; |
return TRUE; |
1805 |
} |
} |
1806 |
|
|
1807 |
/* Sort register relocs to come before expanding relocs. */ |
/* Sort register relocs to come before expanding relocs. */ |
1841 |
|
|
1842 |
/* Subset of mmix_elf_check_relocs, common to ELF and mmo linking. */ |
/* Subset of mmix_elf_check_relocs, common to ELF and mmo linking. */ |
1843 |
|
|
1844 |
static boolean |
static bfd_boolean |
1845 |
mmix_elf_check_common_relocs (abfd, info, sec, relocs) |
mmix_elf_check_common_relocs (abfd, info, sec, relocs) |
1846 |
bfd *abfd; |
bfd *abfd; |
1847 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
1855 |
const Elf_Internal_Rela *rel; |
const Elf_Internal_Rela *rel; |
1856 |
const Elf_Internal_Rela *rel_end; |
const Elf_Internal_Rela *rel_end; |
1857 |
|
|
|
if (info->relocateable) |
|
|
return true; |
|
|
|
|
1858 |
/* We currently have to abuse this COFF-specific member, since there's |
/* We currently have to abuse this COFF-specific member, since there's |
1859 |
no target-machine-dedicated member. There's no alternative outside |
no target-machine-dedicated member. There's no alternative outside |
1860 |
the bfd_link_info struct; we can't specialize a hash-table since |
the bfd_link_info struct; we can't specialize a hash-table since |
1872 |
the ELF dynobj for this, since the ELF bits assume lots of |
the ELF dynobj for this, since the ELF bits assume lots of |
1873 |
DSO-related stuff if that member is non-NULL. */ |
DSO-related stuff if that member is non-NULL. */ |
1874 |
case R_MMIX_BASE_PLUS_OFFSET: |
case R_MMIX_BASE_PLUS_OFFSET: |
1875 |
|
/* We don't do anything with this reloc for a relocatable link. */ |
1876 |
|
if (info->relocatable) |
1877 |
|
break; |
1878 |
|
|
1879 |
if (bpo_greg_owner == NULL) |
if (bpo_greg_owner == NULL) |
1880 |
{ |
{ |
1881 |
bpo_greg_owner = abfd; |
bpo_greg_owner = abfd; |
1906 |
|| !bfd_set_section_alignment (bpo_greg_owner, |
|| !bfd_set_section_alignment (bpo_greg_owner, |
1907 |
allocated_gregs_section, |
allocated_gregs_section, |
1908 |
3)) |
3)) |
1909 |
return false; |
return FALSE; |
1910 |
|
|
1911 |
gregdata = (struct bpo_greg_section_info *) |
gregdata = (struct bpo_greg_section_info *) |
1912 |
bfd_zalloc (bpo_greg_owner, sizeof (struct bpo_greg_section_info)); |
bfd_zalloc (bpo_greg_owner, sizeof (struct bpo_greg_section_info)); |
1913 |
if (gregdata == NULL) |
if (gregdata == NULL) |
1914 |
return false; |
return FALSE; |
1915 |
elf_section_data (allocated_gregs_section)->tdata = gregdata; |
mmix_elf_section_data (allocated_gregs_section)->bpo.greg |
1916 |
|
= gregdata; |
1917 |
} |
} |
1918 |
else if (gregdata == NULL) |
else if (gregdata == NULL) |
1919 |
gregdata = elf_section_data (allocated_gregs_section)->tdata; |
gregdata |
1920 |
|
= mmix_elf_section_data (allocated_gregs_section)->bpo.greg; |
1921 |
|
|
1922 |
/* Get ourselves some auxiliary info for the BPO-relocs. */ |
/* Get ourselves some auxiliary info for the BPO-relocs. */ |
1923 |
if (bpodata == NULL) |
if (bpodata == NULL) |
1929 |
sizeof (struct bpo_reloc_section_info) |
sizeof (struct bpo_reloc_section_info) |
1930 |
* (sec->reloc_count + 1)); |
* (sec->reloc_count + 1)); |
1931 |
if (bpodata == NULL) |
if (bpodata == NULL) |
1932 |
return false; |
return FALSE; |
1933 |
elf_section_data (sec)->tdata = bpodata; |
mmix_elf_section_data (sec)->bpo.reloc = bpodata; |
1934 |
bpodata->first_base_plus_offset_reloc |
bpodata->first_base_plus_offset_reloc |
1935 |
= bpodata->bpo_index |
= bpodata->bpo_index |
1936 |
= gregdata->n_max_bpo_relocs; |
= gregdata->n_max_bpo_relocs; |
1943 |
gregdata->n_max_bpo_relocs++; |
gregdata->n_max_bpo_relocs++; |
1944 |
|
|
1945 |
/* We don't get another chance to set this before GC; we've not |
/* We don't get another chance to set this before GC; we've not |
1946 |
set up set up any hook that runs before GC. */ |
set up any hook that runs before GC. */ |
1947 |
gregdata->n_bpo_relocs |
gregdata->n_bpo_relocs |
1948 |
= gregdata->n_max_bpo_relocs; |
= gregdata->n_max_bpo_relocs; |
1949 |
break; |
break; |
1950 |
|
|
1951 |
|
case R_MMIX_PUSHJ_STUBBABLE: |
1952 |
|
mmix_elf_section_data (sec)->pjs.n_pushj_relocs++; |
1953 |
|
break; |
1954 |
} |
} |
1955 |
} |
} |
1956 |
|
|
1957 |
return true; |
/* Allocate per-reloc stub storage and initialize it to the max stub |
1958 |
|
size. */ |
1959 |
|
if (mmix_elf_section_data (sec)->pjs.n_pushj_relocs != 0) |
1960 |
|
{ |
1961 |
|
size_t i; |
1962 |
|
|
1963 |
|
mmix_elf_section_data (sec)->pjs.stub_size |
1964 |
|
= bfd_alloc (abfd, mmix_elf_section_data (sec)->pjs.n_pushj_relocs |
1965 |
|
* sizeof (mmix_elf_section_data (sec) |
1966 |
|
->pjs.stub_size[0])); |
1967 |
|
if (mmix_elf_section_data (sec)->pjs.stub_size == NULL) |
1968 |
|
return FALSE; |
1969 |
|
|
1970 |
|
for (i = 0; i < mmix_elf_section_data (sec)->pjs.n_pushj_relocs; i++) |
1971 |
|
mmix_elf_section_data (sec)->pjs.stub_size[i] = MAX_PUSHJ_STUB_SIZE; |
1972 |
|
} |
1973 |
|
|
1974 |
|
return TRUE; |
1975 |
} |
} |
1976 |
|
|
1977 |
/* Look through the relocs for a section during the first phase. */ |
/* Look through the relocs for a section during the first phase. */ |
1978 |
|
|
1979 |
static boolean |
static bfd_boolean |
1980 |
mmix_elf_check_relocs (abfd, info, sec, relocs) |
mmix_elf_check_relocs (abfd, info, sec, relocs) |
1981 |
bfd *abfd; |
bfd *abfd; |
1982 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
1988 |
const Elf_Internal_Rela *rel; |
const Elf_Internal_Rela *rel; |
1989 |
const Elf_Internal_Rela *rel_end; |
const Elf_Internal_Rela *rel_end; |
1990 |
|
|
|
if (info->relocateable) |
|
|
return true; |
|
|
|
|
1991 |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
1992 |
sym_hashes = elf_sym_hashes (abfd); |
sym_hashes = elf_sym_hashes (abfd); |
1993 |
sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf64_External_Sym); |
sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf64_External_Sym); |
2001 |
|
|
2002 |
/* Do the common part. */ |
/* Do the common part. */ |
2003 |
if (!mmix_elf_check_common_relocs (abfd, info, sec, relocs)) |
if (!mmix_elf_check_common_relocs (abfd, info, sec, relocs)) |
2004 |
return false; |
return FALSE; |
2005 |
|
|
2006 |
|
if (info->relocatable) |
2007 |
|
return TRUE; |
2008 |
|
|
2009 |
rel_end = relocs + sec->reloc_count; |
rel_end = relocs + sec->reloc_count; |
2010 |
for (rel = relocs; rel < rel_end; rel++) |
for (rel = relocs; rel < rel_end; rel++) |
2023 |
/* This relocation describes the C++ object vtable hierarchy. |
/* This relocation describes the C++ object vtable hierarchy. |
2024 |
Reconstruct it for later use during GC. */ |
Reconstruct it for later use during GC. */ |
2025 |
case R_MMIX_GNU_VTINHERIT: |
case R_MMIX_GNU_VTINHERIT: |
2026 |
if (!_bfd_elf64_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) |
if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) |
2027 |
return false; |
return FALSE; |
2028 |
break; |
break; |
2029 |
|
|
2030 |
/* This relocation describes which C++ vtable entries are actually |
/* This relocation describes which C++ vtable entries are actually |
2031 |
used. Record for later use during GC. */ |
used. Record for later use during GC. */ |
2032 |
case R_MMIX_GNU_VTENTRY: |
case R_MMIX_GNU_VTENTRY: |
2033 |
if (!_bfd_elf64_gc_record_vtentry (abfd, sec, h, rel->r_addend)) |
if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) |
2034 |
return false; |
return FALSE; |
2035 |
break; |
break; |
2036 |
} |
} |
2037 |
} |
} |
2038 |
|
|
2039 |
return true; |
return TRUE; |
2040 |
} |
} |
2041 |
|
|
2042 |
/* Wrapper for mmix_elf_check_common_relocs, called when linking to mmo. |
/* Wrapper for mmix_elf_check_common_relocs, called when linking to mmo. |
2043 |
Copied from elf_link_add_object_symbols. */ |
Copied from elf_link_add_object_symbols. */ |
2044 |
|
|
2045 |
boolean |
bfd_boolean |
2046 |
_bfd_mmix_check_all_relocs (abfd, info) |
_bfd_mmix_check_all_relocs (abfd, info) |
2047 |
bfd *abfd; |
bfd *abfd; |
2048 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
2052 |
for (o = abfd->sections; o != NULL; o = o->next) |
for (o = abfd->sections; o != NULL; o = o->next) |
2053 |
{ |
{ |
2054 |
Elf_Internal_Rela *internal_relocs; |
Elf_Internal_Rela *internal_relocs; |
2055 |
boolean ok; |
bfd_boolean ok; |
2056 |
|
|
2057 |
if ((o->flags & SEC_RELOC) == 0 |
if ((o->flags & SEC_RELOC) == 0 |
2058 |
|| o->reloc_count == 0 |
|| o->reloc_count == 0 |
2062 |
continue; |
continue; |
2063 |
|
|
2064 |
internal_relocs |
internal_relocs |
2065 |
= _bfd_elf64_link_read_relocs (abfd, o, (PTR) NULL, |
= _bfd_elf_link_read_relocs (abfd, o, (PTR) NULL, |
2066 |
(Elf_Internal_Rela *) NULL, |
(Elf_Internal_Rela *) NULL, |
2067 |
info->keep_memory); |
info->keep_memory); |
2068 |
if (internal_relocs == NULL) |
if (internal_relocs == NULL) |
2069 |
return false; |
return FALSE; |
2070 |
|
|
2071 |
ok = mmix_elf_check_common_relocs (abfd, info, o, internal_relocs); |
ok = mmix_elf_check_common_relocs (abfd, info, o, internal_relocs); |
2072 |
|
|
2074 |
free (internal_relocs); |
free (internal_relocs); |
2075 |
|
|
2076 |
if (! ok) |
if (! ok) |
2077 |
return false; |
return FALSE; |
2078 |
} |
} |
2079 |
|
|
2080 |
return true; |
return TRUE; |
2081 |
} |
} |
2082 |
|
|
2083 |
/* Change symbols relative to the reg contents section to instead be to |
/* Change symbols relative to the reg contents section to instead be to |
2084 |
the register section, and scale them down to correspond to the register |
the register section, and scale them down to correspond to the register |
2085 |
number. */ |
number. */ |
2086 |
|
|
2087 |
static boolean |
static bfd_boolean |
2088 |
mmix_elf_link_output_symbol_hook (abfd, info, name, sym, input_sec) |
mmix_elf_link_output_symbol_hook (info, name, sym, input_sec, h) |
|
bfd *abfd ATTRIBUTE_UNUSED; |
|
2089 |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
2090 |
const char *name ATTRIBUTE_UNUSED; |
const char *name ATTRIBUTE_UNUSED; |
2091 |
Elf_Internal_Sym *sym; |
Elf_Internal_Sym *sym; |
2092 |
asection *input_sec; |
asection *input_sec; |
2093 |
|
struct elf_link_hash_entry *h ATTRIBUTE_UNUSED; |
2094 |
{ |
{ |
2095 |
if (input_sec != NULL |
if (input_sec != NULL |
2096 |
&& input_sec->name != NULL |
&& input_sec->name != NULL |
2101 |
sym->st_shndx = SHN_REGISTER; |
sym->st_shndx = SHN_REGISTER; |
2102 |
} |
} |
2103 |
|
|
2104 |
return true; |
return TRUE; |
2105 |
} |
} |
2106 |
|
|
2107 |
/* We fake a register section that holds values that are register numbers. |
/* We fake a register section that holds values that are register numbers. |
2112 |
static asymbol mmix_elf_reg_section_symbol; |
static asymbol mmix_elf_reg_section_symbol; |
2113 |
static asymbol *mmix_elf_reg_section_symbol_ptr; |
static asymbol *mmix_elf_reg_section_symbol_ptr; |
2114 |
|
|
2115 |
/* Handle the special MIPS section numbers that a symbol may use. |
/* Handle the special section numbers that a symbol may use. */ |
|
This is used for both the 32-bit and the 64-bit ABI. */ |
|
2116 |
|
|
2117 |
void |
void |
2118 |
mmix_elf_symbol_processing (abfd, asym) |
mmix_elf_symbol_processing (abfd, asym) |
2149 |
/* Given a BFD section, try to locate the corresponding ELF section |
/* Given a BFD section, try to locate the corresponding ELF section |
2150 |
index. */ |
index. */ |
2151 |
|
|
2152 |
static boolean |
static bfd_boolean |
2153 |
mmix_elf_section_from_bfd_section (abfd, sec, retval) |
mmix_elf_section_from_bfd_section (abfd, sec, retval) |
2154 |
bfd * abfd ATTRIBUTE_UNUSED; |
bfd * abfd ATTRIBUTE_UNUSED; |
2155 |
asection * sec; |
asection * sec; |
2158 |
if (strcmp (bfd_get_section_name (abfd, sec), MMIX_REG_SECTION_NAME) == 0) |
if (strcmp (bfd_get_section_name (abfd, sec), MMIX_REG_SECTION_NAME) == 0) |
2159 |
*retval = SHN_REGISTER; |
*retval = SHN_REGISTER; |
2160 |
else |
else |
2161 |
return false; |
return FALSE; |
2162 |
|
|
2163 |
return true; |
return TRUE; |
2164 |
} |
} |
2165 |
|
|
2166 |
/* Hook called by the linker routine which adds symbols from an object |
/* Hook called by the linker routine which adds symbols from an object |
2170 |
symbols, since otherwise having two with the same value would cause |
symbols, since otherwise having two with the same value would cause |
2171 |
them to be "merged", but with the contents serialized. */ |
them to be "merged", but with the contents serialized. */ |
2172 |
|
|
2173 |
boolean |
bfd_boolean |
2174 |
mmix_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) |
mmix_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) |
2175 |
bfd *abfd; |
bfd *abfd; |
2176 |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
2177 |
const Elf_Internal_Sym *sym; |
Elf_Internal_Sym *sym; |
2178 |
const char **namep ATTRIBUTE_UNUSED; |
const char **namep ATTRIBUTE_UNUSED; |
2179 |
flagword *flagsp ATTRIBUTE_UNUSED; |
flagword *flagsp ATTRIBUTE_UNUSED; |
2180 |
asection **secp; |
asection **secp; |
2189 |
/* See if we have another one. */ |
/* See if we have another one. */ |
2190 |
struct bfd_link_hash_entry *h = bfd_link_hash_lookup (info->hash, |
struct bfd_link_hash_entry *h = bfd_link_hash_lookup (info->hash, |
2191 |
*namep, |
*namep, |
2192 |
false, |
FALSE, |
2193 |
false, |
FALSE, |
2194 |
false); |
FALSE); |
2195 |
|
|
2196 |
if (h != NULL && h->type != bfd_link_hash_undefined) |
if (h != NULL && h->type != bfd_link_hash_undefined) |
2197 |
{ |
{ |
2202 |
bfd_get_filename (abfd), *namep, |
bfd_get_filename (abfd), *namep, |
2203 |
*namep + strlen (MMIX_LOC_SECTION_START_SYMBOL_PREFIX))); |
*namep + strlen (MMIX_LOC_SECTION_START_SYMBOL_PREFIX))); |
2204 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
2205 |
return false; |
return FALSE; |
2206 |
} |
} |
2207 |
} |
} |
2208 |
|
|
2209 |
return true; |
return TRUE; |
2210 |
} |
} |
2211 |
|
|
2212 |
/* We consider symbols matching "L.*:[0-9]+" to be local symbols. */ |
/* We consider symbols matching "L.*:[0-9]+" to be local symbols. */ |
2213 |
|
|
2214 |
boolean |
bfd_boolean |
2215 |
mmix_elf_is_local_label_name (abfd, name) |
mmix_elf_is_local_label_name (abfd, name) |
2216 |
bfd *abfd; |
bfd *abfd; |
2217 |
const char *name; |
const char *name; |
2221 |
|
|
2222 |
/* Also include the default local-label definition. */ |
/* Also include the default local-label definition. */ |
2223 |
if (_bfd_elf_is_local_label_name (abfd, name)) |
if (_bfd_elf_is_local_label_name (abfd, name)) |
2224 |
return true; |
return TRUE; |
2225 |
|
|
2226 |
if (*name != 'L') |
if (*name != 'L') |
2227 |
return false; |
return FALSE; |
2228 |
|
|
2229 |
/* If there's no ":", or more than one, it's not a local symbol. */ |
/* If there's no ":", or more than one, it's not a local symbol. */ |
2230 |
colpos = strchr (name, ':'); |
colpos = strchr (name, ':'); |
2231 |
if (colpos == NULL || strchr (colpos + 1, ':') != NULL) |
if (colpos == NULL || strchr (colpos + 1, ':') != NULL) |
2232 |
return false; |
return FALSE; |
2233 |
|
|
2234 |
/* Check that there are remaining characters and that they are digits. */ |
/* Check that there are remaining characters and that they are digits. */ |
2235 |
if (colpos[1] == 0) |
if (colpos[1] == 0) |
2236 |
return false; |
return FALSE; |
2237 |
|
|
2238 |
digits = strspn (colpos + 1, "0123456789"); |
digits = strspn (colpos + 1, "0123456789"); |
2239 |
return digits != 0 && colpos[1 + digits] == 0; |
return digits != 0 && colpos[1 + digits] == 0; |
2241 |
|
|
2242 |
/* We get rid of the register section here. */ |
/* We get rid of the register section here. */ |
2243 |
|
|
2244 |
boolean |
bfd_boolean |
2245 |
mmix_elf_final_link (abfd, info) |
mmix_elf_final_link (abfd, info) |
2246 |
bfd *abfd; |
bfd *abfd; |
2247 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
2268 |
--abfd->section_count; |
--abfd->section_count; |
2269 |
} |
} |
2270 |
|
|
2271 |
if (! bfd_elf64_bfd_final_link (abfd, info)) |
if (! bfd_elf_final_link (abfd, info)) |
2272 |
return false; |
return FALSE; |
2273 |
|
|
2274 |
/* Since this section is marked SEC_LINKER_CREATED, it isn't output by |
/* Since this section is marked SEC_LINKER_CREATED, it isn't output by |
2275 |
the regular linker machinery. We do it here, like other targets with |
the regular linker machinery. We do it here, like other targets with |
2283 |
greg_section->output_section, |
greg_section->output_section, |
2284 |
greg_section->contents, |
greg_section->contents, |
2285 |
(file_ptr) greg_section->output_offset, |
(file_ptr) greg_section->output_offset, |
2286 |
greg_section->_cooked_size)) |
greg_section->size)) |
2287 |
return false; |
return FALSE; |
2288 |
} |
} |
2289 |
return true; |
return TRUE; |
2290 |
|
} |
2291 |
|
|
2292 |
|
/* We need to include the maximum size of PUSHJ-stubs in the initial |
2293 |
|
section size. This is expected to shrink during linker relaxation. */ |
2294 |
|
|
2295 |
|
static void |
2296 |
|
mmix_set_relaxable_size (abfd, sec, ptr) |
2297 |
|
bfd *abfd ATTRIBUTE_UNUSED; |
2298 |
|
asection *sec; |
2299 |
|
void *ptr; |
2300 |
|
{ |
2301 |
|
struct bfd_link_info *info = ptr; |
2302 |
|
|
2303 |
|
/* Make sure we only do this for section where we know we want this, |
2304 |
|
otherwise we might end up resetting the size of COMMONs. */ |
2305 |
|
if (mmix_elf_section_data (sec)->pjs.n_pushj_relocs == 0) |
2306 |
|
return; |
2307 |
|
|
2308 |
|
sec->rawsize = sec->size; |
2309 |
|
sec->size += (mmix_elf_section_data (sec)->pjs.n_pushj_relocs |
2310 |
|
* MAX_PUSHJ_STUB_SIZE); |
2311 |
|
|
2312 |
|
/* For use in relocatable link, we start with a max stubs size. See |
2313 |
|
mmix_elf_relax_section. */ |
2314 |
|
if (info->relocatable && sec->output_section) |
2315 |
|
mmix_elf_section_data (sec->output_section)->pjs.stubs_size_sum |
2316 |
|
+= (mmix_elf_section_data (sec)->pjs.n_pushj_relocs |
2317 |
|
* MAX_PUSHJ_STUB_SIZE); |
2318 |
} |
} |
2319 |
|
|
2320 |
/* Initialize stuff for the linker-generated GREGs to match |
/* Initialize stuff for the linker-generated GREGs to match |
2321 |
R_MMIX_BASE_PLUS_OFFSET relocs seen by the linker. */ |
R_MMIX_BASE_PLUS_OFFSET relocs seen by the linker. */ |
2322 |
|
|
2323 |
boolean |
bfd_boolean |
2324 |
_bfd_mmix_prepare_linker_allocated_gregs (abfd, info) |
_bfd_mmix_before_linker_allocation (abfd, info) |
2325 |
bfd *abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
2326 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
2327 |
{ |
{ |
2332 |
bfd_vma gregs_size; |
bfd_vma gregs_size; |
2333 |
size_t i; |
size_t i; |
2334 |
size_t *bpo_reloc_indexes; |
size_t *bpo_reloc_indexes; |
2335 |
|
bfd *ibfd; |
2336 |
|
|
2337 |
|
/* Set the initial size of sections. */ |
2338 |
|
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) |
2339 |
|
bfd_map_over_sections (ibfd, mmix_set_relaxable_size, info); |
2340 |
|
|
2341 |
/* The bpo_greg_owner bfd is supposed to have been set by |
/* The bpo_greg_owner bfd is supposed to have been set by |
2342 |
mmix_elf_check_relocs when the first R_MMIX_BASE_PLUS_OFFSET is seen. |
mmix_elf_check_relocs when the first R_MMIX_BASE_PLUS_OFFSET is seen. |
2343 |
If there is no such object, there was no R_MMIX_BASE_PLUS_OFFSET. */ |
If there is no such object, there was no R_MMIX_BASE_PLUS_OFFSET. */ |
2344 |
bpo_greg_owner = (bfd *) info->base_file; |
bpo_greg_owner = (bfd *) info->base_file; |
2345 |
if (bpo_greg_owner == NULL) |
if (bpo_greg_owner == NULL) |
2346 |
return true; |
return TRUE; |
2347 |
|
|
2348 |
bpo_gregs_section |
bpo_gregs_section |
2349 |
= bfd_get_section_by_name (bpo_greg_owner, |
= bfd_get_section_by_name (bpo_greg_owner, |
2350 |
MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME); |
MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME); |
2351 |
|
|
2352 |
if (bpo_gregs_section == NULL) |
if (bpo_gregs_section == NULL) |
2353 |
return true; |
return TRUE; |
2354 |
|
|
2355 |
/* We use the target-data handle in the ELF section data. */ |
/* We use the target-data handle in the ELF section data. */ |
2356 |
gregdata = (struct bpo_greg_section_info *) |
gregdata = mmix_elf_section_data (bpo_gregs_section)->bpo.greg; |
|
elf_section_data (bpo_gregs_section)->tdata; |
|
2357 |
if (gregdata == NULL) |
if (gregdata == NULL) |
2358 |
return false; |
return FALSE; |
2359 |
|
|
2360 |
n_gregs = gregdata->n_bpo_relocs; |
n_gregs = gregdata->n_bpo_relocs; |
2361 |
gregdata->n_allocated_bpo_gregs = n_gregs; |
gregdata->n_allocated_bpo_gregs = n_gregs; |
2368 |
gregs_size = n_gregs * 8; |
gregs_size = n_gregs * 8; |
2369 |
|
|
2370 |
if (!bfd_set_section_size (bpo_greg_owner, bpo_gregs_section, gregs_size)) |
if (!bfd_set_section_size (bpo_greg_owner, bpo_gregs_section, gregs_size)) |
2371 |
return false; |
return FALSE; |
2372 |
|
|
2373 |
/* Allocate and set up the GREG arrays. They're filled in at relaxation |
/* Allocate and set up the GREG arrays. They're filled in at relaxation |
2374 |
time. Note that we must use the max number ever noted for the array, |
time. Note that we must use the max number ever noted for the array, |
2384 |
gregdata->n_max_bpo_relocs |
gregdata->n_max_bpo_relocs |
2385 |
* sizeof (size_t)); |
* sizeof (size_t)); |
2386 |
if (bpo_reloc_indexes == NULL) |
if (bpo_reloc_indexes == NULL) |
2387 |
return false; |
return FALSE; |
2388 |
|
|
2389 |
/* The default order is an identity mapping. */ |
/* The default order is an identity mapping. */ |
2390 |
for (i = 0; i < gregdata->n_max_bpo_relocs; i++) |
for (i = 0; i < gregdata->n_max_bpo_relocs; i++) |
2393 |
gregdata->reloc_request[i].bpo_reloc_no = i; |
gregdata->reloc_request[i].bpo_reloc_no = i; |
2394 |
} |
} |
2395 |
|
|
2396 |
return true; |
return TRUE; |
2397 |
} |
} |
2398 |
|
|
2399 |
/* Fill in contents in the linker allocated gregs. Everything is |
/* Fill in contents in the linker allocated gregs. Everything is |
2400 |
calculated at this point; we just move the contents into place here. */ |
calculated at this point; we just move the contents into place here. */ |
2401 |
|
|
2402 |
boolean |
bfd_boolean |
2403 |
_bfd_mmix_finalize_linker_allocated_gregs (abfd, link_info) |
_bfd_mmix_after_linker_allocation (abfd, link_info) |
2404 |
bfd *abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
2405 |
struct bfd_link_info *link_info; |
struct bfd_link_info *link_info; |
2406 |
{ |
{ |
2417 |
object, there was no R_MMIX_BASE_PLUS_OFFSET. */ |
object, there was no R_MMIX_BASE_PLUS_OFFSET. */ |
2418 |
bpo_greg_owner = (bfd *) link_info->base_file; |
bpo_greg_owner = (bfd *) link_info->base_file; |
2419 |
if (bpo_greg_owner == NULL) |
if (bpo_greg_owner == NULL) |
2420 |
return true; |
return TRUE; |
2421 |
|
|
2422 |
bpo_gregs_section |
bpo_gregs_section |
2423 |
= bfd_get_section_by_name (bpo_greg_owner, |
= bfd_get_section_by_name (bpo_greg_owner, |
2427 |
without any R_MMIX_BASE_PLUS_OFFSET seen, there will be no such |
without any R_MMIX_BASE_PLUS_OFFSET seen, there will be no such |
2428 |
section. */ |
section. */ |
2429 |
if (bpo_gregs_section == NULL) |
if (bpo_gregs_section == NULL) |
2430 |
return true; |
return TRUE; |
2431 |
|
|
2432 |
/* We use the target-data handle in the ELF section data. */ |
/* We use the target-data handle in the ELF section data. */ |
2433 |
|
|
2434 |
gregdata = (struct bpo_greg_section_info *) |
gregdata = mmix_elf_section_data (bpo_gregs_section)->bpo.greg; |
|
elf_section_data (bpo_gregs_section)->tdata; |
|
2435 |
if (gregdata == NULL) |
if (gregdata == NULL) |
2436 |
return false; |
return FALSE; |
2437 |
|
|
2438 |
n_gregs = gregdata->n_allocated_bpo_gregs; |
n_gregs = gregdata->n_allocated_bpo_gregs; |
2439 |
|
|
2440 |
bpo_gregs_section->contents |
bpo_gregs_section->contents |
2441 |
= contents = bfd_alloc (bpo_greg_owner, bpo_gregs_section->_cooked_size); |
= contents = bfd_alloc (bpo_greg_owner, bpo_gregs_section->size); |
2442 |
if (contents == NULL) |
if (contents == NULL) |
2443 |
return false; |
return FALSE; |
2444 |
|
|
2445 |
/* Sanity check: If these numbers mismatch, some relocation has not been |
/* Sanity check: If these numbers mismatch, some relocation has not been |
2446 |
accounted for and the rest of gregdata is probably inconsistent. |
accounted for and the rest of gregdata is probably inconsistent. |
2454 |
Please report this bug."), |
Please report this bug."), |
2455 |
gregdata->n_remaining_bpo_relocs_this_relaxation_round, |
gregdata->n_remaining_bpo_relocs_this_relaxation_round, |
2456 |
gregdata->n_bpo_relocs); |
gregdata->n_bpo_relocs); |
2457 |
return false; |
return FALSE; |
2458 |
} |
} |
2459 |
|
|
2460 |
for (lastreg = 255, i = 0, j = 0; j < n_gregs; i++) |
for (lastreg = 255, i = 0, j = 0; j < n_gregs; i++) |
2466 |
j++; |
j++; |
2467 |
} |
} |
2468 |
|
|
2469 |
return true; |
return TRUE; |
2470 |
} |
} |
2471 |
|
|
2472 |
/* Sort valid relocs to come before non-valid relocs, then on increasing |
/* Sort valid relocs to come before non-valid relocs, then on increasing |
2524 |
if (bpo_gregs_section == NULL) |
if (bpo_gregs_section == NULL) |
2525 |
return; |
return; |
2526 |
|
|
2527 |
gregdata = (struct bpo_greg_section_info *) |
gregdata = mmix_elf_section_data (bpo_gregs_section)->bpo.greg; |
|
elf_section_data (bpo_gregs_section)->tdata; |
|
2528 |
if (gregdata == NULL) |
if (gregdata == NULL) |
2529 |
return; |
return; |
2530 |
|
|
2544 |
for (i = 0; i < gregdata->n_max_bpo_relocs; i++) |
for (i = 0; i < gregdata->n_max_bpo_relocs; i++) |
2545 |
(*pf) ("%4u (%4u)/%4u#%u: 0x%08lx%08lx r: %3u o: %3u\n", |
(*pf) ("%4u (%4u)/%4u#%u: 0x%08lx%08lx r: %3u o: %3u\n", |
2546 |
i, |
i, |
2547 |
gregdata->bpo_reloc_indexes != NULL |
(gregdata->bpo_reloc_indexes != NULL |
2548 |
? gregdata->bpo_reloc_indexes[i] : -1, |
? gregdata->bpo_reloc_indexes[i] : (size_t) -1), |
2549 |
gregdata->reloc_request[i].bpo_reloc_no, |
gregdata->reloc_request[i].bpo_reloc_no, |
2550 |
gregdata->reloc_request[i].valid, |
gregdata->reloc_request[i].valid, |
2551 |
|
|
2561 |
from the first allocated register number) and offsets for use in real |
from the first allocated register number) and offsets for use in real |
2562 |
relocation. |
relocation. |
2563 |
|
|
2564 |
|
PUSHJ stub accounting is also done here. |
2565 |
|
|
2566 |
Symbol- and reloc-reading infrastructure copied from elf-m10200.c. */ |
Symbol- and reloc-reading infrastructure copied from elf-m10200.c. */ |
2567 |
|
|
2568 |
static boolean |
static bfd_boolean |
2569 |
mmix_elf_relax_section (abfd, sec, link_info, again) |
mmix_elf_relax_section (abfd, sec, link_info, again) |
2570 |
bfd *abfd; |
bfd *abfd; |
2571 |
asection *sec; |
asection *sec; |
2572 |
struct bfd_link_info *link_info; |
struct bfd_link_info *link_info; |
2573 |
boolean *again; |
bfd_boolean *again; |
2574 |
{ |
{ |
2575 |
Elf_Internal_Shdr *symtab_hdr; |
Elf_Internal_Shdr *symtab_hdr; |
2576 |
Elf_Internal_Rela *internal_relocs; |
Elf_Internal_Rela *internal_relocs; |
2578 |
asection *bpo_gregs_section = NULL; |
asection *bpo_gregs_section = NULL; |
2579 |
struct bpo_greg_section_info *gregdata; |
struct bpo_greg_section_info *gregdata; |
2580 |
struct bpo_reloc_section_info *bpodata |
struct bpo_reloc_section_info *bpodata |
2581 |
= (struct bpo_reloc_section_info *) |
= mmix_elf_section_data (sec)->bpo.reloc; |
2582 |
elf_section_data (sec)->tdata; |
/* The initialization is to quiet compiler warnings. The value is to |
2583 |
size_t bpono; |
spot a missing actual initialization. */ |
2584 |
|
size_t bpono = (size_t) -1; |
2585 |
|
size_t pjsno = 0; |
2586 |
bfd *bpo_greg_owner; |
bfd *bpo_greg_owner; |
2587 |
Elf_Internal_Sym *isymbuf = NULL; |
Elf_Internal_Sym *isymbuf = NULL; |
2588 |
|
bfd_size_type size = sec->rawsize ? sec->rawsize : sec->size; |
2589 |
|
|
2590 |
|
mmix_elf_section_data (sec)->pjs.stubs_size_sum = 0; |
2591 |
|
|
2592 |
/* Assume nothing changes. */ |
/* Assume nothing changes. */ |
2593 |
*again = false; |
*again = FALSE; |
2594 |
|
|
2595 |
/* If this is the first time we have been called for this section, |
/* We don't have to do anything if this section does not have relocs, or |
2596 |
initialize the cooked size. */ |
if this is not a code section. */ |
2597 |
if (sec->_cooked_size == 0) |
if ((sec->flags & SEC_RELOC) == 0 |
|
sec->_cooked_size = sec->_raw_size; |
|
|
|
|
|
/* We don't have to do anything for a relocateable link, if |
|
|
this section does not have relocs, or if this is not a |
|
|
code section. */ |
|
|
if (link_info->relocateable |
|
|
|| (sec->flags & SEC_RELOC) == 0 |
|
2598 |
|| sec->reloc_count == 0 |
|| sec->reloc_count == 0 |
2599 |
|| (sec->flags & SEC_CODE) == 0 |
|| (sec->flags & SEC_CODE) == 0 |
2600 |
|| (sec->flags & SEC_LINKER_CREATED) != 0 |
|| (sec->flags & SEC_LINKER_CREATED) != 0 |
2601 |
/* If no R_MMIX_BASE_PLUS_OFFSET relocs, then nothing to do. */ |
/* If no R_MMIX_BASE_PLUS_OFFSET relocs and no PUSHJ-stub relocs, |
2602 |
|| bpodata == NULL) |
then nothing to do. */ |
2603 |
return true; |
|| (bpodata == NULL |
2604 |
|
&& mmix_elf_section_data (sec)->pjs.n_pushj_relocs == 0)) |
2605 |
|
return TRUE; |
2606 |
|
|
2607 |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
2608 |
|
|
2609 |
bpo_greg_owner = (bfd *) link_info->base_file; |
bpo_greg_owner = (bfd *) link_info->base_file; |
|
bpo_gregs_section = bpodata->bpo_greg_section; |
|
|
gregdata = (struct bpo_greg_section_info *) |
|
|
elf_section_data (bpo_gregs_section)->tdata; |
|
2610 |
|
|
2611 |
bpono = bpodata->first_base_plus_offset_reloc; |
if (bpodata != NULL) |
2612 |
|
{ |
2613 |
|
bpo_gregs_section = bpodata->bpo_greg_section; |
2614 |
|
gregdata = mmix_elf_section_data (bpo_gregs_section)->bpo.greg; |
2615 |
|
bpono = bpodata->first_base_plus_offset_reloc; |
2616 |
|
} |
2617 |
|
else |
2618 |
|
gregdata = NULL; |
2619 |
|
|
2620 |
/* Get a copy of the native relocations. */ |
/* Get a copy of the native relocations. */ |
2621 |
internal_relocs |
internal_relocs |
2622 |
= _bfd_elf64_link_read_relocs (abfd, sec, (PTR) NULL, |
= _bfd_elf_link_read_relocs (abfd, sec, (PTR) NULL, |
2623 |
(Elf_Internal_Rela *) NULL, |
(Elf_Internal_Rela *) NULL, |
2624 |
link_info->keep_memory); |
link_info->keep_memory); |
2625 |
if (internal_relocs == NULL) |
if (internal_relocs == NULL) |
2626 |
goto error_return; |
goto error_return; |
2627 |
|
|
2630 |
for (irel = internal_relocs; irel < irelend; irel++) |
for (irel = internal_relocs; irel < irelend; irel++) |
2631 |
{ |
{ |
2632 |
bfd_vma symval; |
bfd_vma symval; |
2633 |
|
struct elf_link_hash_entry *h = NULL; |
2634 |
|
|
2635 |
if (ELF64_R_TYPE (irel->r_info) != (int) R_MMIX_BASE_PLUS_OFFSET) |
/* We only process two relocs. */ |
2636 |
|
if (ELF64_R_TYPE (irel->r_info) != (int) R_MMIX_BASE_PLUS_OFFSET |
2637 |
|
&& ELF64_R_TYPE (irel->r_info) != (int) R_MMIX_PUSHJ_STUBBABLE) |
2638 |
continue; |
continue; |
2639 |
|
|
2640 |
|
/* We process relocs in a distinctly different way when this is a |
2641 |
|
relocatable link (for one, we don't look at symbols), so we avoid |
2642 |
|
mixing its code with that for the "normal" relaxation. */ |
2643 |
|
if (link_info->relocatable) |
2644 |
|
{ |
2645 |
|
/* The only transformation in a relocatable link is to generate |
2646 |
|
a full stub at the location of the stub calculated for the |
2647 |
|
input section, if the relocated stub location, the end of the |
2648 |
|
output section plus earlier stubs, cannot be reached. Thus |
2649 |
|
relocatable linking can only lead to worse code, but it still |
2650 |
|
works. */ |
2651 |
|
if (ELF64_R_TYPE (irel->r_info) == R_MMIX_PUSHJ_STUBBABLE) |
2652 |
|
{ |
2653 |
|
/* If we can reach the end of the output-section and beyond |
2654 |
|
any current stubs, then we don't need a stub for this |
2655 |
|
reloc. The relaxed order of output stub allocation may |
2656 |
|
not exactly match the straightforward order, so we always |
2657 |
|
assume presence of output stubs, which will allow |
2658 |
|
relaxation only on relocations indifferent to the |
2659 |
|
presence of output stub allocations for other relocations |
2660 |
|
and thus the order of output stub allocation. */ |
2661 |
|
if (bfd_check_overflow (complain_overflow_signed, |
2662 |
|
19, |
2663 |
|
0, |
2664 |
|
bfd_arch_bits_per_address (abfd), |
2665 |
|
/* Output-stub location. */ |
2666 |
|
sec->output_section->rawsize |
2667 |
|
+ (mmix_elf_section_data (sec |
2668 |
|
->output_section) |
2669 |
|
->pjs.stubs_size_sum) |
2670 |
|
/* Location of this PUSHJ reloc. */ |
2671 |
|
- (sec->output_offset + irel->r_offset) |
2672 |
|
/* Don't count *this* stub twice. */ |
2673 |
|
- (mmix_elf_section_data (sec) |
2674 |
|
->pjs.stub_size[pjsno] |
2675 |
|
+ MAX_PUSHJ_STUB_SIZE)) |
2676 |
|
== bfd_reloc_ok) |
2677 |
|
mmix_elf_section_data (sec)->pjs.stub_size[pjsno] = 0; |
2678 |
|
|
2679 |
|
mmix_elf_section_data (sec)->pjs.stubs_size_sum |
2680 |
|
+= mmix_elf_section_data (sec)->pjs.stub_size[pjsno]; |
2681 |
|
|
2682 |
|
pjsno++; |
2683 |
|
} |
2684 |
|
|
2685 |
|
continue; |
2686 |
|
} |
2687 |
|
|
2688 |
/* Get the value of the symbol referred to by the reloc. */ |
/* Get the value of the symbol referred to by the reloc. */ |
2689 |
if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info) |
if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info) |
2690 |
{ |
{ |
2720 |
else |
else |
2721 |
{ |
{ |
2722 |
unsigned long indx; |
unsigned long indx; |
|
struct elf_link_hash_entry *h; |
|
2723 |
|
|
2724 |
/* An external symbol. */ |
/* An external symbol. */ |
2725 |
indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info; |
indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info; |
2728 |
if (h->root.type != bfd_link_hash_defined |
if (h->root.type != bfd_link_hash_defined |
2729 |
&& h->root.type != bfd_link_hash_defweak) |
&& h->root.type != bfd_link_hash_defweak) |
2730 |
{ |
{ |
2731 |
/* This appears to be a reference to an undefined symbol. |
/* This appears to be a reference to an undefined symbol. Just |
2732 |
Just ignore it--it will be caught by the regular reloc |
ignore it--it will be caught by the regular reloc processing. |
2733 |
processing. We need to keep BPO reloc accounting |
We need to keep BPO reloc accounting consistent, though |
2734 |
consistent, though. */ |
else we'll abort instead of emitting an error message. */ |
2735 |
gregdata->n_remaining_bpo_relocs_this_relaxation_round--; |
if (ELF64_R_TYPE (irel->r_info) == R_MMIX_BASE_PLUS_OFFSET |
2736 |
bpono++; |
&& gregdata != NULL) |
2737 |
|
{ |
2738 |
|
gregdata->n_remaining_bpo_relocs_this_relaxation_round--; |
2739 |
|
bpono++; |
2740 |
|
} |
2741 |
continue; |
continue; |
2742 |
} |
} |
2743 |
|
|
2746 |
+ h->root.u.def.section->output_offset); |
+ h->root.u.def.section->output_offset); |
2747 |
} |
} |
2748 |
|
|
2749 |
|
if (ELF64_R_TYPE (irel->r_info) == (int) R_MMIX_PUSHJ_STUBBABLE) |
2750 |
|
{ |
2751 |
|
bfd_vma value = symval + irel->r_addend; |
2752 |
|
bfd_vma dot |
2753 |
|
= (sec->output_section->vma |
2754 |
|
+ sec->output_offset |
2755 |
|
+ irel->r_offset); |
2756 |
|
bfd_vma stubaddr |
2757 |
|
= (sec->output_section->vma |
2758 |
|
+ sec->output_offset |
2759 |
|
+ size |
2760 |
|
+ mmix_elf_section_data (sec)->pjs.stubs_size_sum); |
2761 |
|
|
2762 |
|
if ((value & 3) == 0 |
2763 |
|
&& bfd_check_overflow (complain_overflow_signed, |
2764 |
|
19, |
2765 |
|
0, |
2766 |
|
bfd_arch_bits_per_address (abfd), |
2767 |
|
value - dot |
2768 |
|
- (value > dot |
2769 |
|
? mmix_elf_section_data (sec) |
2770 |
|
->pjs.stub_size[pjsno] |
2771 |
|
: 0)) |
2772 |
|
== bfd_reloc_ok) |
2773 |
|
/* If the reloc fits, no stub is needed. */ |
2774 |
|
mmix_elf_section_data (sec)->pjs.stub_size[pjsno] = 0; |
2775 |
|
else |
2776 |
|
/* Maybe we can get away with just a JMP insn? */ |
2777 |
|
if ((value & 3) == 0 |
2778 |
|
&& bfd_check_overflow (complain_overflow_signed, |
2779 |
|
27, |
2780 |
|
0, |
2781 |
|
bfd_arch_bits_per_address (abfd), |
2782 |
|
value - stubaddr |
2783 |
|
- (value > dot |
2784 |
|
? mmix_elf_section_data (sec) |
2785 |
|
->pjs.stub_size[pjsno] - 4 |
2786 |
|
: 0)) |
2787 |
|
== bfd_reloc_ok) |
2788 |
|
/* Yep, account for a stub consisting of a single JMP insn. */ |
2789 |
|
mmix_elf_section_data (sec)->pjs.stub_size[pjsno] = 4; |
2790 |
|
else |
2791 |
|
/* Nope, go for the full insn stub. It doesn't seem useful to |
2792 |
|
emit the intermediate sizes; those will only be useful for |
2793 |
|
a >64M program assuming contiguous code. */ |
2794 |
|
mmix_elf_section_data (sec)->pjs.stub_size[pjsno] |
2795 |
|
= MAX_PUSHJ_STUB_SIZE; |
2796 |
|
|
2797 |
|
mmix_elf_section_data (sec)->pjs.stubs_size_sum |
2798 |
|
+= mmix_elf_section_data (sec)->pjs.stub_size[pjsno]; |
2799 |
|
pjsno++; |
2800 |
|
continue; |
2801 |
|
} |
2802 |
|
|
2803 |
|
/* We're looking at a R_MMIX_BASE_PLUS_OFFSET reloc. */ |
2804 |
|
|
2805 |
gregdata->reloc_request[gregdata->bpo_reloc_indexes[bpono]].value |
gregdata->reloc_request[gregdata->bpo_reloc_indexes[bpono]].value |
2806 |
= symval + irel->r_addend; |
= symval + irel->r_addend; |
2807 |
gregdata->reloc_request[gregdata->bpo_reloc_indexes[bpono++]].valid = true; |
gregdata->reloc_request[gregdata->bpo_reloc_indexes[bpono++]].valid = TRUE; |
2808 |
gregdata->n_remaining_bpo_relocs_this_relaxation_round--; |
gregdata->n_remaining_bpo_relocs_this_relaxation_round--; |
2809 |
} |
} |
2810 |
|
|
2812 |
calculate how many registers we need to cover them. Set the size of |
calculate how many registers we need to cover them. Set the size of |
2813 |
the linker gregs, and if the number of registers changed, indicate |
the linker gregs, and if the number of registers changed, indicate |
2814 |
that we need to relax some more because we have more work to do. */ |
that we need to relax some more because we have more work to do. */ |
2815 |
if (gregdata->n_remaining_bpo_relocs_this_relaxation_round == 0) |
if (gregdata != NULL |
2816 |
|
&& gregdata->n_remaining_bpo_relocs_this_relaxation_round == 0) |
2817 |
{ |
{ |
2818 |
size_t i; |
size_t i; |
2819 |
bfd_vma prev_base; |
bfd_vma prev_base; |
2838 |
{ |
{ |
2839 |
gregdata->bpo_reloc_indexes[gregdata->reloc_request[i].bpo_reloc_no] |
gregdata->bpo_reloc_indexes[gregdata->reloc_request[i].bpo_reloc_no] |
2840 |
= i; |
= i; |
2841 |
*again = true; |
*again = TRUE; |
2842 |
} |
} |
2843 |
|
|
2844 |
/* Allocate register numbers (indexing from 0). Stop at the first |
/* Allocate register numbers (indexing from 0). Stop at the first |
2864 |
if (gregdata->n_allocated_bpo_gregs != regindex + 1) |
if (gregdata->n_allocated_bpo_gregs != regindex + 1) |
2865 |
{ |
{ |
2866 |
gregdata->n_allocated_bpo_gregs = regindex + 1; |
gregdata->n_allocated_bpo_gregs = regindex + 1; |
2867 |
*again = true; |
*again = TRUE; |
2868 |
} |
} |
2869 |
|
|
2870 |
bpo_gregs_section->_cooked_size = (regindex + 1) * 8; |
bpo_gregs_section->size = (regindex + 1) * 8; |
2871 |
} |
} |
2872 |
|
|
2873 |
if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents) |
if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents) |
2885 |
&& elf_section_data (sec)->relocs != internal_relocs) |
&& elf_section_data (sec)->relocs != internal_relocs) |
2886 |
free (internal_relocs); |
free (internal_relocs); |
2887 |
|
|
2888 |
return true; |
if (sec->size < size + mmix_elf_section_data (sec)->pjs.stubs_size_sum) |
2889 |
|
abort (); |
2890 |
|
|
2891 |
|
if (sec->size > size + mmix_elf_section_data (sec)->pjs.stubs_size_sum) |
2892 |
|
{ |
2893 |
|
sec->size = size + mmix_elf_section_data (sec)->pjs.stubs_size_sum; |
2894 |
|
*again = TRUE; |
2895 |
|
} |
2896 |
|
|
2897 |
|
return TRUE; |
2898 |
|
|
2899 |
error_return: |
error_return: |
2900 |
if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents) |
if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents) |
2902 |
if (internal_relocs != NULL |
if (internal_relocs != NULL |
2903 |
&& elf_section_data (sec)->relocs != internal_relocs) |
&& elf_section_data (sec)->relocs != internal_relocs) |
2904 |
free (internal_relocs); |
free (internal_relocs); |
2905 |
return false; |
return FALSE; |
2906 |
} |
} |
2907 |
|
|
2908 |
#define ELF_ARCH bfd_arch_mmix |
#define ELF_ARCH bfd_arch_mmix |
2949 |
#define elf_backend_section_from_bfd_section \ |
#define elf_backend_section_from_bfd_section \ |
2950 |
mmix_elf_section_from_bfd_section |
mmix_elf_section_from_bfd_section |
2951 |
|
|
2952 |
|
#define bfd_elf64_new_section_hook mmix_elf_new_section_hook |
2953 |
#define bfd_elf64_bfd_final_link mmix_elf_final_link |
#define bfd_elf64_bfd_final_link mmix_elf_final_link |
2954 |
#define bfd_elf64_bfd_relax_section mmix_elf_relax_section |
#define bfd_elf64_bfd_relax_section mmix_elf_relax_section |
2955 |
|
|