1d2201f2fSdrahn /* MMIX-specific support for 64-bit ELF.
2*cf2f2c56Smiod Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
3d2201f2fSdrahn Contributed by Hans-Peter Nilsson <hp@bitrange.com>
4d2201f2fSdrahn
5d2201f2fSdrahn This file is part of BFD, the Binary File Descriptor library.
6d2201f2fSdrahn
7d2201f2fSdrahn This program is free software; you can redistribute it and/or modify
8d2201f2fSdrahn it under the terms of the GNU General Public License as published by
9d2201f2fSdrahn the Free Software Foundation; either version 2 of the License, or
10d2201f2fSdrahn (at your option) any later version.
11d2201f2fSdrahn
12d2201f2fSdrahn This program is distributed in the hope that it will be useful,
13d2201f2fSdrahn but WITHOUT ANY WARRANTY; without even the implied warranty of
14d2201f2fSdrahn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15d2201f2fSdrahn GNU General Public License for more details.
16d2201f2fSdrahn
17d2201f2fSdrahn You should have received a copy of the GNU General Public License
18d2201f2fSdrahn along with this program; if not, write to the Free Software
19d2201f2fSdrahn Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20d2201f2fSdrahn
21d2201f2fSdrahn /* No specific ABI or "processor-specific supplement" defined. */
22d2201f2fSdrahn
23d2201f2fSdrahn /* TODO:
24*cf2f2c56Smiod - "Traditional" linker relaxation (shrinking whole sections).
25*cf2f2c56Smiod - Merge reloc stubs jumping to same location.
26*cf2f2c56Smiod - GETA stub relaxation (call a stub for out of range new
27*cf2f2c56Smiod R_MMIX_GETA_STUBBABLE). */
28d2201f2fSdrahn
29d2201f2fSdrahn #include "bfd.h"
30d2201f2fSdrahn #include "sysdep.h"
31d2201f2fSdrahn #include "libbfd.h"
32d2201f2fSdrahn #include "elf-bfd.h"
33d2201f2fSdrahn #include "elf/mmix.h"
34d2201f2fSdrahn #include "opcode/mmix.h"
35d2201f2fSdrahn
36d2201f2fSdrahn #define MINUS_ONE (((bfd_vma) 0) - 1)
37d2201f2fSdrahn
38*cf2f2c56Smiod #define MAX_PUSHJ_STUB_SIZE (5 * 4)
39*cf2f2c56Smiod
40d2201f2fSdrahn /* Put these everywhere in new code. */
41d2201f2fSdrahn #define FATAL_DEBUG \
42d2201f2fSdrahn _bfd_abort (__FILE__, __LINE__, \
43d2201f2fSdrahn "Internal: Non-debugged code (test-case missing)")
44d2201f2fSdrahn
45d2201f2fSdrahn #define BAD_CASE(x) \
46d2201f2fSdrahn _bfd_abort (__FILE__, __LINE__, \
47d2201f2fSdrahn "bad case for " #x)
48d2201f2fSdrahn
49d2201f2fSdrahn struct _mmix_elf_section_data
50d2201f2fSdrahn {
51d2201f2fSdrahn struct bfd_elf_section_data elf;
52d2201f2fSdrahn union
53d2201f2fSdrahn {
54d2201f2fSdrahn struct bpo_reloc_section_info *reloc;
55d2201f2fSdrahn struct bpo_greg_section_info *greg;
56d2201f2fSdrahn } bpo;
57*cf2f2c56Smiod
58*cf2f2c56Smiod struct pushj_stub_info
59*cf2f2c56Smiod {
60*cf2f2c56Smiod /* Maximum number of stubs needed for this section. */
61*cf2f2c56Smiod bfd_size_type n_pushj_relocs;
62*cf2f2c56Smiod
63*cf2f2c56Smiod /* Size of stubs after a mmix_elf_relax_section round. */
64*cf2f2c56Smiod bfd_size_type stubs_size_sum;
65*cf2f2c56Smiod
66*cf2f2c56Smiod /* Per-reloc stubs_size_sum information. The stubs_size_sum member is the sum
67*cf2f2c56Smiod of these. Allocated in mmix_elf_check_common_relocs. */
68*cf2f2c56Smiod bfd_size_type *stub_size;
69*cf2f2c56Smiod
70*cf2f2c56Smiod /* Offset of next stub during relocation. Somewhat redundant with the
71*cf2f2c56Smiod above: error coverage is easier and we don't have to reset the
72*cf2f2c56Smiod stubs_size_sum for relocation. */
73*cf2f2c56Smiod bfd_size_type stub_offset;
74*cf2f2c56Smiod } pjs;
75d2201f2fSdrahn };
76d2201f2fSdrahn
77d2201f2fSdrahn #define mmix_elf_section_data(sec) \
78d2201f2fSdrahn ((struct _mmix_elf_section_data *) elf_section_data (sec))
79d2201f2fSdrahn
80d2201f2fSdrahn /* For each section containing a base-plus-offset (BPO) reloc, we attach
81d2201f2fSdrahn this struct as mmix_elf_section_data (section)->bpo, which is otherwise
82d2201f2fSdrahn NULL. */
83d2201f2fSdrahn struct bpo_reloc_section_info
84d2201f2fSdrahn {
85d2201f2fSdrahn /* The base is 1; this is the first number in this section. */
86d2201f2fSdrahn size_t first_base_plus_offset_reloc;
87d2201f2fSdrahn
88d2201f2fSdrahn /* Number of BPO-relocs in this section. */
89d2201f2fSdrahn size_t n_bpo_relocs_this_section;
90d2201f2fSdrahn
91d2201f2fSdrahn /* Running index, used at relocation time. */
92d2201f2fSdrahn size_t bpo_index;
93d2201f2fSdrahn
94d2201f2fSdrahn /* We don't have access to the bfd_link_info struct in
95d2201f2fSdrahn mmix_final_link_relocate. What we really want to get at is the
96d2201f2fSdrahn global single struct greg_relocation, so we stash it here. */
97d2201f2fSdrahn asection *bpo_greg_section;
98d2201f2fSdrahn };
99d2201f2fSdrahn
100d2201f2fSdrahn /* Helper struct (in global context) for the one below.
101d2201f2fSdrahn There's one of these created for every BPO reloc. */
102d2201f2fSdrahn struct bpo_reloc_request
103d2201f2fSdrahn {
104d2201f2fSdrahn bfd_vma value;
105d2201f2fSdrahn
106d2201f2fSdrahn /* Valid after relaxation. The base is 0; the first register number
107d2201f2fSdrahn must be added. The offset is in range 0..255. */
108d2201f2fSdrahn size_t regindex;
109d2201f2fSdrahn size_t offset;
110d2201f2fSdrahn
111d2201f2fSdrahn /* The order number for this BPO reloc, corresponding to the order in
112d2201f2fSdrahn which BPO relocs were found. Used to create an index after reloc
113d2201f2fSdrahn requests are sorted. */
114d2201f2fSdrahn size_t bpo_reloc_no;
115d2201f2fSdrahn
116d2201f2fSdrahn /* Set when the value is computed. Better than coding "guard values"
117d2201f2fSdrahn into the other members. Is FALSE only for BPO relocs in a GC:ed
118d2201f2fSdrahn section. */
119d2201f2fSdrahn bfd_boolean valid;
120d2201f2fSdrahn };
121d2201f2fSdrahn
122d2201f2fSdrahn /* We attach this as mmix_elf_section_data (sec)->bpo in the linker-allocated
123d2201f2fSdrahn greg contents section (MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME),
124d2201f2fSdrahn which is linked into the register contents section
125d2201f2fSdrahn (MMIX_REG_CONTENTS_SECTION_NAME). This section is created by the
126d2201f2fSdrahn linker; using the same hook as for usual with BPO relocs does not
127d2201f2fSdrahn collide. */
128d2201f2fSdrahn struct bpo_greg_section_info
129d2201f2fSdrahn {
130d2201f2fSdrahn /* After GC, this reflects the number of remaining, non-excluded
131d2201f2fSdrahn BPO-relocs. */
132d2201f2fSdrahn size_t n_bpo_relocs;
133d2201f2fSdrahn
134d2201f2fSdrahn /* This is the number of allocated bpo_reloc_requests; the size of
135d2201f2fSdrahn sorted_indexes. Valid after the check.*relocs functions are called
136d2201f2fSdrahn for all incoming sections. It includes the number of BPO relocs in
137d2201f2fSdrahn sections that were GC:ed. */
138d2201f2fSdrahn size_t n_max_bpo_relocs;
139d2201f2fSdrahn
140d2201f2fSdrahn /* A counter used to find out when to fold the BPO gregs, since we
141d2201f2fSdrahn don't have a single "after-relaxation" hook. */
142d2201f2fSdrahn size_t n_remaining_bpo_relocs_this_relaxation_round;
143d2201f2fSdrahn
144d2201f2fSdrahn /* The number of linker-allocated GREGs resulting from BPO relocs.
145*cf2f2c56Smiod This is an approximation after _bfd_mmix_before_linker_allocation
146*cf2f2c56Smiod and supposedly accurate after mmix_elf_relax_section is called for
147*cf2f2c56Smiod all incoming non-collected sections. */
148d2201f2fSdrahn size_t n_allocated_bpo_gregs;
149d2201f2fSdrahn
150d2201f2fSdrahn /* Index into reloc_request[], sorted on increasing "value", secondary
151d2201f2fSdrahn by increasing index for strict sorting order. */
152d2201f2fSdrahn size_t *bpo_reloc_indexes;
153d2201f2fSdrahn
154d2201f2fSdrahn /* An array of all relocations, with the "value" member filled in by
155d2201f2fSdrahn the relaxation function. */
156d2201f2fSdrahn struct bpo_reloc_request *reloc_request;
157d2201f2fSdrahn };
158d2201f2fSdrahn
159d2201f2fSdrahn static bfd_boolean mmix_elf_link_output_symbol_hook
160*cf2f2c56Smiod PARAMS ((struct bfd_link_info *, const char *, Elf_Internal_Sym *,
161*cf2f2c56Smiod asection *, struct elf_link_hash_entry *));
162d2201f2fSdrahn
163d2201f2fSdrahn static bfd_reloc_status_type mmix_elf_reloc
164d2201f2fSdrahn PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
165d2201f2fSdrahn
166d2201f2fSdrahn static reloc_howto_type *bfd_elf64_bfd_reloc_type_lookup
167d2201f2fSdrahn PARAMS ((bfd *, bfd_reloc_code_real_type));
168d2201f2fSdrahn
169d2201f2fSdrahn static void mmix_info_to_howto_rela
170d2201f2fSdrahn PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
171d2201f2fSdrahn
172d2201f2fSdrahn static int mmix_elf_sort_relocs PARAMS ((const PTR, const PTR));
173d2201f2fSdrahn
174d2201f2fSdrahn static bfd_boolean mmix_elf_new_section_hook
175d2201f2fSdrahn PARAMS ((bfd *, asection *));
176d2201f2fSdrahn
177d2201f2fSdrahn static bfd_boolean mmix_elf_check_relocs
178d2201f2fSdrahn PARAMS ((bfd *, struct bfd_link_info *, asection *,
179d2201f2fSdrahn const Elf_Internal_Rela *));
180d2201f2fSdrahn
181d2201f2fSdrahn static bfd_boolean mmix_elf_check_common_relocs
182d2201f2fSdrahn PARAMS ((bfd *, struct bfd_link_info *, asection *,
183d2201f2fSdrahn const Elf_Internal_Rela *));
184d2201f2fSdrahn
185d2201f2fSdrahn static bfd_boolean mmix_elf_relocate_section
186d2201f2fSdrahn PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
187d2201f2fSdrahn Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
188d2201f2fSdrahn
189d2201f2fSdrahn static asection * mmix_elf_gc_mark_hook
190d2201f2fSdrahn PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
191d2201f2fSdrahn struct elf_link_hash_entry *, Elf_Internal_Sym *));
192d2201f2fSdrahn
193d2201f2fSdrahn static bfd_boolean mmix_elf_gc_sweep_hook
194d2201f2fSdrahn PARAMS ((bfd *, struct bfd_link_info *, asection *,
195d2201f2fSdrahn const Elf_Internal_Rela *));
196d2201f2fSdrahn
197d2201f2fSdrahn static bfd_reloc_status_type mmix_final_link_relocate
198d2201f2fSdrahn PARAMS ((reloc_howto_type *, asection *, bfd_byte *,
199d2201f2fSdrahn bfd_vma, bfd_signed_vma, bfd_vma, const char *, asection *));
200d2201f2fSdrahn
201d2201f2fSdrahn static bfd_reloc_status_type mmix_elf_perform_relocation
202d2201f2fSdrahn PARAMS ((asection *, reloc_howto_type *, PTR, bfd_vma, bfd_vma));
203d2201f2fSdrahn
204d2201f2fSdrahn static bfd_boolean mmix_elf_section_from_bfd_section
205d2201f2fSdrahn PARAMS ((bfd *, asection *, int *));
206d2201f2fSdrahn
207d2201f2fSdrahn static bfd_boolean mmix_elf_add_symbol_hook
208*cf2f2c56Smiod PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Sym *,
209d2201f2fSdrahn const char **, flagword *, asection **, bfd_vma *));
210d2201f2fSdrahn
211d2201f2fSdrahn static bfd_boolean mmix_elf_is_local_label_name
212d2201f2fSdrahn PARAMS ((bfd *, const char *));
213d2201f2fSdrahn
214d2201f2fSdrahn static int bpo_reloc_request_sort_fn PARAMS ((const PTR, const PTR));
215d2201f2fSdrahn
216d2201f2fSdrahn static bfd_boolean mmix_elf_relax_section
217d2201f2fSdrahn PARAMS ((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
218d2201f2fSdrahn bfd_boolean *again));
219d2201f2fSdrahn
220d2201f2fSdrahn extern bfd_boolean mmix_elf_final_link PARAMS ((bfd *, struct bfd_link_info *));
221d2201f2fSdrahn
222d2201f2fSdrahn extern void mmix_elf_symbol_processing PARAMS ((bfd *, asymbol *));
223d2201f2fSdrahn
224d2201f2fSdrahn /* Only intended to be called from a debugger. */
225d2201f2fSdrahn extern void mmix_dump_bpo_gregs
226d2201f2fSdrahn PARAMS ((struct bfd_link_info *, bfd_error_handler_type));
227d2201f2fSdrahn
228*cf2f2c56Smiod static void
229*cf2f2c56Smiod mmix_set_relaxable_size
230*cf2f2c56Smiod PARAMS ((bfd *, asection *, void *));
231*cf2f2c56Smiod
232*cf2f2c56Smiod static bfd_boolean
233*cf2f2c56Smiod mmix_elf_get_section_contents
234*cf2f2c56Smiod PARAMS ((bfd *, sec_ptr, void *, file_ptr, bfd_size_type));
235*cf2f2c56Smiod
236*cf2f2c56Smiod
237d2201f2fSdrahn /* Watch out: this currently needs to have elements with the same index as
238d2201f2fSdrahn their R_MMIX_ number. */
239d2201f2fSdrahn static reloc_howto_type elf_mmix_howto_table[] =
240d2201f2fSdrahn {
241d2201f2fSdrahn /* This reloc does nothing. */
242d2201f2fSdrahn HOWTO (R_MMIX_NONE, /* type */
243d2201f2fSdrahn 0, /* rightshift */
244d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
245d2201f2fSdrahn 32, /* bitsize */
246d2201f2fSdrahn FALSE, /* pc_relative */
247d2201f2fSdrahn 0, /* bitpos */
248d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
249d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
250d2201f2fSdrahn "R_MMIX_NONE", /* name */
251d2201f2fSdrahn FALSE, /* partial_inplace */
252d2201f2fSdrahn 0, /* src_mask */
253d2201f2fSdrahn 0, /* dst_mask */
254d2201f2fSdrahn FALSE), /* pcrel_offset */
255d2201f2fSdrahn
256d2201f2fSdrahn /* An 8 bit absolute relocation. */
257d2201f2fSdrahn HOWTO (R_MMIX_8, /* type */
258d2201f2fSdrahn 0, /* rightshift */
259d2201f2fSdrahn 0, /* size (0 = byte, 1 = short, 2 = long) */
260d2201f2fSdrahn 8, /* bitsize */
261d2201f2fSdrahn FALSE, /* pc_relative */
262d2201f2fSdrahn 0, /* bitpos */
263d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
264d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
265d2201f2fSdrahn "R_MMIX_8", /* name */
266d2201f2fSdrahn FALSE, /* partial_inplace */
267d2201f2fSdrahn 0, /* src_mask */
268d2201f2fSdrahn 0xff, /* dst_mask */
269d2201f2fSdrahn FALSE), /* pcrel_offset */
270d2201f2fSdrahn
271d2201f2fSdrahn /* An 16 bit absolute relocation. */
272d2201f2fSdrahn HOWTO (R_MMIX_16, /* type */
273d2201f2fSdrahn 0, /* rightshift */
274d2201f2fSdrahn 1, /* size (0 = byte, 1 = short, 2 = long) */
275d2201f2fSdrahn 16, /* bitsize */
276d2201f2fSdrahn FALSE, /* pc_relative */
277d2201f2fSdrahn 0, /* bitpos */
278d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
279d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
280d2201f2fSdrahn "R_MMIX_16", /* name */
281d2201f2fSdrahn FALSE, /* partial_inplace */
282d2201f2fSdrahn 0, /* src_mask */
283d2201f2fSdrahn 0xffff, /* dst_mask */
284d2201f2fSdrahn FALSE), /* pcrel_offset */
285d2201f2fSdrahn
286d2201f2fSdrahn /* An 24 bit absolute relocation. */
287d2201f2fSdrahn HOWTO (R_MMIX_24, /* type */
288d2201f2fSdrahn 0, /* rightshift */
289d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
290d2201f2fSdrahn 24, /* bitsize */
291d2201f2fSdrahn FALSE, /* pc_relative */
292d2201f2fSdrahn 0, /* bitpos */
293d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
294d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
295d2201f2fSdrahn "R_MMIX_24", /* name */
296d2201f2fSdrahn FALSE, /* partial_inplace */
297d2201f2fSdrahn ~0xffffff, /* src_mask */
298d2201f2fSdrahn 0xffffff, /* dst_mask */
299d2201f2fSdrahn FALSE), /* pcrel_offset */
300d2201f2fSdrahn
301d2201f2fSdrahn /* A 32 bit absolute relocation. */
302d2201f2fSdrahn HOWTO (R_MMIX_32, /* type */
303d2201f2fSdrahn 0, /* rightshift */
304d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
305d2201f2fSdrahn 32, /* bitsize */
306d2201f2fSdrahn FALSE, /* pc_relative */
307d2201f2fSdrahn 0, /* bitpos */
308d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
309d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
310d2201f2fSdrahn "R_MMIX_32", /* name */
311d2201f2fSdrahn FALSE, /* partial_inplace */
312d2201f2fSdrahn 0, /* src_mask */
313d2201f2fSdrahn 0xffffffff, /* dst_mask */
314d2201f2fSdrahn FALSE), /* pcrel_offset */
315d2201f2fSdrahn
316d2201f2fSdrahn /* 64 bit relocation. */
317d2201f2fSdrahn HOWTO (R_MMIX_64, /* type */
318d2201f2fSdrahn 0, /* rightshift */
319d2201f2fSdrahn 4, /* size (0 = byte, 1 = short, 2 = long) */
320d2201f2fSdrahn 64, /* bitsize */
321d2201f2fSdrahn FALSE, /* pc_relative */
322d2201f2fSdrahn 0, /* bitpos */
323d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
324d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
325d2201f2fSdrahn "R_MMIX_64", /* name */
326d2201f2fSdrahn FALSE, /* partial_inplace */
327d2201f2fSdrahn 0, /* src_mask */
328d2201f2fSdrahn MINUS_ONE, /* dst_mask */
329d2201f2fSdrahn FALSE), /* pcrel_offset */
330d2201f2fSdrahn
331d2201f2fSdrahn /* An 8 bit PC-relative relocation. */
332d2201f2fSdrahn HOWTO (R_MMIX_PC_8, /* type */
333d2201f2fSdrahn 0, /* rightshift */
334d2201f2fSdrahn 0, /* size (0 = byte, 1 = short, 2 = long) */
335d2201f2fSdrahn 8, /* bitsize */
336d2201f2fSdrahn TRUE, /* pc_relative */
337d2201f2fSdrahn 0, /* bitpos */
338d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
339d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
340d2201f2fSdrahn "R_MMIX_PC_8", /* name */
341d2201f2fSdrahn FALSE, /* partial_inplace */
342d2201f2fSdrahn 0, /* src_mask */
343d2201f2fSdrahn 0xff, /* dst_mask */
344d2201f2fSdrahn TRUE), /* pcrel_offset */
345d2201f2fSdrahn
346d2201f2fSdrahn /* An 16 bit PC-relative relocation. */
347d2201f2fSdrahn HOWTO (R_MMIX_PC_16, /* type */
348d2201f2fSdrahn 0, /* rightshift */
349d2201f2fSdrahn 1, /* size (0 = byte, 1 = short, 2 = long) */
350d2201f2fSdrahn 16, /* bitsize */
351d2201f2fSdrahn TRUE, /* pc_relative */
352d2201f2fSdrahn 0, /* bitpos */
353d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
354d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
355d2201f2fSdrahn "R_MMIX_PC_16", /* name */
356d2201f2fSdrahn FALSE, /* partial_inplace */
357d2201f2fSdrahn 0, /* src_mask */
358d2201f2fSdrahn 0xffff, /* dst_mask */
359d2201f2fSdrahn TRUE), /* pcrel_offset */
360d2201f2fSdrahn
361d2201f2fSdrahn /* An 24 bit PC-relative relocation. */
362d2201f2fSdrahn HOWTO (R_MMIX_PC_24, /* type */
363d2201f2fSdrahn 0, /* rightshift */
364d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
365d2201f2fSdrahn 24, /* bitsize */
366d2201f2fSdrahn TRUE, /* pc_relative */
367d2201f2fSdrahn 0, /* bitpos */
368d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
369d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
370d2201f2fSdrahn "R_MMIX_PC_24", /* name */
371d2201f2fSdrahn FALSE, /* partial_inplace */
372d2201f2fSdrahn ~0xffffff, /* src_mask */
373d2201f2fSdrahn 0xffffff, /* dst_mask */
374d2201f2fSdrahn TRUE), /* pcrel_offset */
375d2201f2fSdrahn
376d2201f2fSdrahn /* A 32 bit absolute PC-relative relocation. */
377d2201f2fSdrahn HOWTO (R_MMIX_PC_32, /* type */
378d2201f2fSdrahn 0, /* rightshift */
379d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
380d2201f2fSdrahn 32, /* bitsize */
381d2201f2fSdrahn TRUE, /* pc_relative */
382d2201f2fSdrahn 0, /* bitpos */
383d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
384d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
385d2201f2fSdrahn "R_MMIX_PC_32", /* name */
386d2201f2fSdrahn FALSE, /* partial_inplace */
387d2201f2fSdrahn 0, /* src_mask */
388d2201f2fSdrahn 0xffffffff, /* dst_mask */
389d2201f2fSdrahn TRUE), /* pcrel_offset */
390d2201f2fSdrahn
391d2201f2fSdrahn /* 64 bit PC-relative relocation. */
392d2201f2fSdrahn HOWTO (R_MMIX_PC_64, /* type */
393d2201f2fSdrahn 0, /* rightshift */
394d2201f2fSdrahn 4, /* size (0 = byte, 1 = short, 2 = long) */
395d2201f2fSdrahn 64, /* bitsize */
396d2201f2fSdrahn TRUE, /* pc_relative */
397d2201f2fSdrahn 0, /* bitpos */
398d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
399d2201f2fSdrahn bfd_elf_generic_reloc, /* special_function */
400d2201f2fSdrahn "R_MMIX_PC_64", /* name */
401d2201f2fSdrahn FALSE, /* partial_inplace */
402d2201f2fSdrahn 0, /* src_mask */
403d2201f2fSdrahn MINUS_ONE, /* dst_mask */
404d2201f2fSdrahn TRUE), /* pcrel_offset */
405d2201f2fSdrahn
406d2201f2fSdrahn /* GNU extension to record C++ vtable hierarchy. */
407d2201f2fSdrahn HOWTO (R_MMIX_GNU_VTINHERIT, /* type */
408d2201f2fSdrahn 0, /* rightshift */
409d2201f2fSdrahn 0, /* size (0 = byte, 1 = short, 2 = long) */
410d2201f2fSdrahn 0, /* bitsize */
411d2201f2fSdrahn FALSE, /* pc_relative */
412d2201f2fSdrahn 0, /* bitpos */
413d2201f2fSdrahn complain_overflow_dont, /* complain_on_overflow */
414d2201f2fSdrahn NULL, /* special_function */
415d2201f2fSdrahn "R_MMIX_GNU_VTINHERIT", /* name */
416d2201f2fSdrahn FALSE, /* partial_inplace */
417d2201f2fSdrahn 0, /* src_mask */
418d2201f2fSdrahn 0, /* dst_mask */
419d2201f2fSdrahn TRUE), /* pcrel_offset */
420d2201f2fSdrahn
421d2201f2fSdrahn /* GNU extension to record C++ vtable member usage. */
422d2201f2fSdrahn HOWTO (R_MMIX_GNU_VTENTRY, /* type */
423d2201f2fSdrahn 0, /* rightshift */
424d2201f2fSdrahn 0, /* size (0 = byte, 1 = short, 2 = long) */
425d2201f2fSdrahn 0, /* bitsize */
426d2201f2fSdrahn FALSE, /* pc_relative */
427d2201f2fSdrahn 0, /* bitpos */
428d2201f2fSdrahn complain_overflow_dont, /* complain_on_overflow */
429d2201f2fSdrahn _bfd_elf_rel_vtable_reloc_fn, /* special_function */
430d2201f2fSdrahn "R_MMIX_GNU_VTENTRY", /* name */
431d2201f2fSdrahn FALSE, /* partial_inplace */
432d2201f2fSdrahn 0, /* src_mask */
433d2201f2fSdrahn 0, /* dst_mask */
434d2201f2fSdrahn FALSE), /* pcrel_offset */
435d2201f2fSdrahn
436d2201f2fSdrahn /* The GETA relocation is supposed to get any address that could
437d2201f2fSdrahn possibly be reached by the GETA instruction. It can silently expand
438d2201f2fSdrahn to get a 64-bit operand, but will complain if any of the two least
439d2201f2fSdrahn significant bits are set. The howto members reflect a simple GETA. */
440d2201f2fSdrahn HOWTO (R_MMIX_GETA, /* type */
441d2201f2fSdrahn 2, /* rightshift */
442d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
443d2201f2fSdrahn 19, /* bitsize */
444d2201f2fSdrahn TRUE, /* pc_relative */
445d2201f2fSdrahn 0, /* bitpos */
446d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
447d2201f2fSdrahn mmix_elf_reloc, /* special_function */
448d2201f2fSdrahn "R_MMIX_GETA", /* name */
449d2201f2fSdrahn FALSE, /* partial_inplace */
450d2201f2fSdrahn ~0x0100ffff, /* src_mask */
451d2201f2fSdrahn 0x0100ffff, /* dst_mask */
452d2201f2fSdrahn TRUE), /* pcrel_offset */
453d2201f2fSdrahn
454d2201f2fSdrahn HOWTO (R_MMIX_GETA_1, /* type */
455d2201f2fSdrahn 2, /* rightshift */
456d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
457d2201f2fSdrahn 19, /* bitsize */
458d2201f2fSdrahn TRUE, /* pc_relative */
459d2201f2fSdrahn 0, /* bitpos */
460d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
461d2201f2fSdrahn mmix_elf_reloc, /* special_function */
462d2201f2fSdrahn "R_MMIX_GETA_1", /* name */
463d2201f2fSdrahn FALSE, /* partial_inplace */
464d2201f2fSdrahn ~0x0100ffff, /* src_mask */
465d2201f2fSdrahn 0x0100ffff, /* dst_mask */
466d2201f2fSdrahn TRUE), /* pcrel_offset */
467d2201f2fSdrahn
468d2201f2fSdrahn HOWTO (R_MMIX_GETA_2, /* type */
469d2201f2fSdrahn 2, /* rightshift */
470d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
471d2201f2fSdrahn 19, /* bitsize */
472d2201f2fSdrahn TRUE, /* pc_relative */
473d2201f2fSdrahn 0, /* bitpos */
474d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
475d2201f2fSdrahn mmix_elf_reloc, /* special_function */
476d2201f2fSdrahn "R_MMIX_GETA_2", /* name */
477d2201f2fSdrahn FALSE, /* partial_inplace */
478d2201f2fSdrahn ~0x0100ffff, /* src_mask */
479d2201f2fSdrahn 0x0100ffff, /* dst_mask */
480d2201f2fSdrahn TRUE), /* pcrel_offset */
481d2201f2fSdrahn
482d2201f2fSdrahn HOWTO (R_MMIX_GETA_3, /* type */
483d2201f2fSdrahn 2, /* rightshift */
484d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
485d2201f2fSdrahn 19, /* bitsize */
486d2201f2fSdrahn TRUE, /* pc_relative */
487d2201f2fSdrahn 0, /* bitpos */
488d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
489d2201f2fSdrahn mmix_elf_reloc, /* special_function */
490d2201f2fSdrahn "R_MMIX_GETA_3", /* name */
491d2201f2fSdrahn FALSE, /* partial_inplace */
492d2201f2fSdrahn ~0x0100ffff, /* src_mask */
493d2201f2fSdrahn 0x0100ffff, /* dst_mask */
494d2201f2fSdrahn TRUE), /* pcrel_offset */
495d2201f2fSdrahn
496d2201f2fSdrahn /* The conditional branches are supposed to reach any (code) address.
497d2201f2fSdrahn It can silently expand to a 64-bit operand, but will emit an error if
498d2201f2fSdrahn any of the two least significant bits are set. The howto members
499d2201f2fSdrahn reflect a simple branch. */
500d2201f2fSdrahn HOWTO (R_MMIX_CBRANCH, /* type */
501d2201f2fSdrahn 2, /* rightshift */
502d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
503d2201f2fSdrahn 19, /* bitsize */
504d2201f2fSdrahn TRUE, /* pc_relative */
505d2201f2fSdrahn 0, /* bitpos */
506d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
507d2201f2fSdrahn mmix_elf_reloc, /* special_function */
508d2201f2fSdrahn "R_MMIX_CBRANCH", /* name */
509d2201f2fSdrahn FALSE, /* partial_inplace */
510d2201f2fSdrahn ~0x0100ffff, /* src_mask */
511d2201f2fSdrahn 0x0100ffff, /* dst_mask */
512d2201f2fSdrahn TRUE), /* pcrel_offset */
513d2201f2fSdrahn
514d2201f2fSdrahn HOWTO (R_MMIX_CBRANCH_J, /* type */
515d2201f2fSdrahn 2, /* rightshift */
516d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
517d2201f2fSdrahn 19, /* bitsize */
518d2201f2fSdrahn TRUE, /* pc_relative */
519d2201f2fSdrahn 0, /* bitpos */
520d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
521d2201f2fSdrahn mmix_elf_reloc, /* special_function */
522d2201f2fSdrahn "R_MMIX_CBRANCH_J", /* name */
523d2201f2fSdrahn FALSE, /* partial_inplace */
524d2201f2fSdrahn ~0x0100ffff, /* src_mask */
525d2201f2fSdrahn 0x0100ffff, /* dst_mask */
526d2201f2fSdrahn TRUE), /* pcrel_offset */
527d2201f2fSdrahn
528d2201f2fSdrahn HOWTO (R_MMIX_CBRANCH_1, /* type */
529d2201f2fSdrahn 2, /* rightshift */
530d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
531d2201f2fSdrahn 19, /* bitsize */
532d2201f2fSdrahn TRUE, /* pc_relative */
533d2201f2fSdrahn 0, /* bitpos */
534d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
535d2201f2fSdrahn mmix_elf_reloc, /* special_function */
536d2201f2fSdrahn "R_MMIX_CBRANCH_1", /* name */
537d2201f2fSdrahn FALSE, /* partial_inplace */
538d2201f2fSdrahn ~0x0100ffff, /* src_mask */
539d2201f2fSdrahn 0x0100ffff, /* dst_mask */
540d2201f2fSdrahn TRUE), /* pcrel_offset */
541d2201f2fSdrahn
542d2201f2fSdrahn HOWTO (R_MMIX_CBRANCH_2, /* type */
543d2201f2fSdrahn 2, /* rightshift */
544d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
545d2201f2fSdrahn 19, /* bitsize */
546d2201f2fSdrahn TRUE, /* pc_relative */
547d2201f2fSdrahn 0, /* bitpos */
548d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
549d2201f2fSdrahn mmix_elf_reloc, /* special_function */
550d2201f2fSdrahn "R_MMIX_CBRANCH_2", /* name */
551d2201f2fSdrahn FALSE, /* partial_inplace */
552d2201f2fSdrahn ~0x0100ffff, /* src_mask */
553d2201f2fSdrahn 0x0100ffff, /* dst_mask */
554d2201f2fSdrahn TRUE), /* pcrel_offset */
555d2201f2fSdrahn
556d2201f2fSdrahn HOWTO (R_MMIX_CBRANCH_3, /* type */
557d2201f2fSdrahn 2, /* rightshift */
558d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
559d2201f2fSdrahn 19, /* bitsize */
560d2201f2fSdrahn TRUE, /* pc_relative */
561d2201f2fSdrahn 0, /* bitpos */
562d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
563d2201f2fSdrahn mmix_elf_reloc, /* special_function */
564d2201f2fSdrahn "R_MMIX_CBRANCH_3", /* name */
565d2201f2fSdrahn FALSE, /* partial_inplace */
566d2201f2fSdrahn ~0x0100ffff, /* src_mask */
567d2201f2fSdrahn 0x0100ffff, /* dst_mask */
568d2201f2fSdrahn TRUE), /* pcrel_offset */
569d2201f2fSdrahn
570d2201f2fSdrahn /* The PUSHJ instruction can reach any (code) address, as long as it's
571d2201f2fSdrahn the beginning of a function (no usable restriction). It can silently
572d2201f2fSdrahn expand to a 64-bit operand, but will emit an error if any of the two
573*cf2f2c56Smiod least significant bits are set. It can also expand into a call to a
574*cf2f2c56Smiod stub; see R_MMIX_PUSHJ_STUBBABLE. The howto members reflect a simple
575d2201f2fSdrahn PUSHJ. */
576d2201f2fSdrahn HOWTO (R_MMIX_PUSHJ, /* type */
577d2201f2fSdrahn 2, /* rightshift */
578d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
579d2201f2fSdrahn 19, /* bitsize */
580d2201f2fSdrahn TRUE, /* pc_relative */
581d2201f2fSdrahn 0, /* bitpos */
582d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
583d2201f2fSdrahn mmix_elf_reloc, /* special_function */
584d2201f2fSdrahn "R_MMIX_PUSHJ", /* name */
585d2201f2fSdrahn FALSE, /* partial_inplace */
586d2201f2fSdrahn ~0x0100ffff, /* src_mask */
587d2201f2fSdrahn 0x0100ffff, /* dst_mask */
588d2201f2fSdrahn TRUE), /* pcrel_offset */
589d2201f2fSdrahn
590d2201f2fSdrahn HOWTO (R_MMIX_PUSHJ_1, /* type */
591d2201f2fSdrahn 2, /* rightshift */
592d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
593d2201f2fSdrahn 19, /* bitsize */
594d2201f2fSdrahn TRUE, /* pc_relative */
595d2201f2fSdrahn 0, /* bitpos */
596d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
597d2201f2fSdrahn mmix_elf_reloc, /* special_function */
598d2201f2fSdrahn "R_MMIX_PUSHJ_1", /* name */
599d2201f2fSdrahn FALSE, /* partial_inplace */
600d2201f2fSdrahn ~0x0100ffff, /* src_mask */
601d2201f2fSdrahn 0x0100ffff, /* dst_mask */
602d2201f2fSdrahn TRUE), /* pcrel_offset */
603d2201f2fSdrahn
604d2201f2fSdrahn HOWTO (R_MMIX_PUSHJ_2, /* type */
605d2201f2fSdrahn 2, /* rightshift */
606d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
607d2201f2fSdrahn 19, /* bitsize */
608d2201f2fSdrahn TRUE, /* pc_relative */
609d2201f2fSdrahn 0, /* bitpos */
610d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
611d2201f2fSdrahn mmix_elf_reloc, /* special_function */
612d2201f2fSdrahn "R_MMIX_PUSHJ_2", /* name */
613d2201f2fSdrahn FALSE, /* partial_inplace */
614d2201f2fSdrahn ~0x0100ffff, /* src_mask */
615d2201f2fSdrahn 0x0100ffff, /* dst_mask */
616d2201f2fSdrahn TRUE), /* pcrel_offset */
617d2201f2fSdrahn
618d2201f2fSdrahn HOWTO (R_MMIX_PUSHJ_3, /* type */
619d2201f2fSdrahn 2, /* rightshift */
620d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
621d2201f2fSdrahn 19, /* bitsize */
622d2201f2fSdrahn TRUE, /* pc_relative */
623d2201f2fSdrahn 0, /* bitpos */
624d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
625d2201f2fSdrahn mmix_elf_reloc, /* special_function */
626d2201f2fSdrahn "R_MMIX_PUSHJ_3", /* name */
627d2201f2fSdrahn FALSE, /* partial_inplace */
628d2201f2fSdrahn ~0x0100ffff, /* src_mask */
629d2201f2fSdrahn 0x0100ffff, /* dst_mask */
630d2201f2fSdrahn TRUE), /* pcrel_offset */
631d2201f2fSdrahn
632d2201f2fSdrahn /* A JMP is supposed to reach any (code) address. By itself, it can
633d2201f2fSdrahn reach +-64M; the expansion can reach all 64 bits. Note that the 64M
634d2201f2fSdrahn limit is soon reached if you link the program in wildly different
635d2201f2fSdrahn memory segments. The howto members reflect a trivial JMP. */
636d2201f2fSdrahn HOWTO (R_MMIX_JMP, /* type */
637d2201f2fSdrahn 2, /* rightshift */
638d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
639d2201f2fSdrahn 27, /* bitsize */
640d2201f2fSdrahn TRUE, /* pc_relative */
641d2201f2fSdrahn 0, /* bitpos */
642d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
643d2201f2fSdrahn mmix_elf_reloc, /* special_function */
644d2201f2fSdrahn "R_MMIX_JMP", /* name */
645d2201f2fSdrahn FALSE, /* partial_inplace */
646d2201f2fSdrahn ~0x1ffffff, /* src_mask */
647d2201f2fSdrahn 0x1ffffff, /* dst_mask */
648d2201f2fSdrahn TRUE), /* pcrel_offset */
649d2201f2fSdrahn
650d2201f2fSdrahn HOWTO (R_MMIX_JMP_1, /* type */
651d2201f2fSdrahn 2, /* rightshift */
652d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
653d2201f2fSdrahn 27, /* bitsize */
654d2201f2fSdrahn TRUE, /* pc_relative */
655d2201f2fSdrahn 0, /* bitpos */
656d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
657d2201f2fSdrahn mmix_elf_reloc, /* special_function */
658d2201f2fSdrahn "R_MMIX_JMP_1", /* name */
659d2201f2fSdrahn FALSE, /* partial_inplace */
660d2201f2fSdrahn ~0x1ffffff, /* src_mask */
661d2201f2fSdrahn 0x1ffffff, /* dst_mask */
662d2201f2fSdrahn TRUE), /* pcrel_offset */
663d2201f2fSdrahn
664d2201f2fSdrahn HOWTO (R_MMIX_JMP_2, /* type */
665d2201f2fSdrahn 2, /* rightshift */
666d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
667d2201f2fSdrahn 27, /* bitsize */
668d2201f2fSdrahn TRUE, /* pc_relative */
669d2201f2fSdrahn 0, /* bitpos */
670d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
671d2201f2fSdrahn mmix_elf_reloc, /* special_function */
672d2201f2fSdrahn "R_MMIX_JMP_2", /* name */
673d2201f2fSdrahn FALSE, /* partial_inplace */
674d2201f2fSdrahn ~0x1ffffff, /* src_mask */
675d2201f2fSdrahn 0x1ffffff, /* dst_mask */
676d2201f2fSdrahn TRUE), /* pcrel_offset */
677d2201f2fSdrahn
678d2201f2fSdrahn HOWTO (R_MMIX_JMP_3, /* type */
679d2201f2fSdrahn 2, /* rightshift */
680d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
681d2201f2fSdrahn 27, /* bitsize */
682d2201f2fSdrahn TRUE, /* pc_relative */
683d2201f2fSdrahn 0, /* bitpos */
684d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
685d2201f2fSdrahn mmix_elf_reloc, /* special_function */
686d2201f2fSdrahn "R_MMIX_JMP_3", /* name */
687d2201f2fSdrahn FALSE, /* partial_inplace */
688d2201f2fSdrahn ~0x1ffffff, /* src_mask */
689d2201f2fSdrahn 0x1ffffff, /* dst_mask */
690d2201f2fSdrahn TRUE), /* pcrel_offset */
691d2201f2fSdrahn
692d2201f2fSdrahn /* When we don't emit link-time-relaxable code from the assembler, or
693d2201f2fSdrahn when relaxation has done all it can do, these relocs are used. For
694d2201f2fSdrahn GETA/PUSHJ/branches. */
695d2201f2fSdrahn HOWTO (R_MMIX_ADDR19, /* type */
696d2201f2fSdrahn 2, /* rightshift */
697d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
698d2201f2fSdrahn 19, /* bitsize */
699d2201f2fSdrahn TRUE, /* pc_relative */
700d2201f2fSdrahn 0, /* bitpos */
701d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
702d2201f2fSdrahn mmix_elf_reloc, /* special_function */
703d2201f2fSdrahn "R_MMIX_ADDR19", /* name */
704d2201f2fSdrahn FALSE, /* partial_inplace */
705d2201f2fSdrahn ~0x0100ffff, /* src_mask */
706d2201f2fSdrahn 0x0100ffff, /* dst_mask */
707d2201f2fSdrahn TRUE), /* pcrel_offset */
708d2201f2fSdrahn
709d2201f2fSdrahn /* For JMP. */
710d2201f2fSdrahn HOWTO (R_MMIX_ADDR27, /* type */
711d2201f2fSdrahn 2, /* rightshift */
712d2201f2fSdrahn 2, /* size (0 = byte, 1 = short, 2 = long) */
713d2201f2fSdrahn 27, /* bitsize */
714d2201f2fSdrahn TRUE, /* pc_relative */
715d2201f2fSdrahn 0, /* bitpos */
716d2201f2fSdrahn complain_overflow_signed, /* complain_on_overflow */
717d2201f2fSdrahn mmix_elf_reloc, /* special_function */
718d2201f2fSdrahn "R_MMIX_ADDR27", /* name */
719d2201f2fSdrahn FALSE, /* partial_inplace */
720d2201f2fSdrahn ~0x1ffffff, /* src_mask */
721d2201f2fSdrahn 0x1ffffff, /* dst_mask */
722d2201f2fSdrahn TRUE), /* pcrel_offset */
723d2201f2fSdrahn
724d2201f2fSdrahn /* A general register or the value 0..255. If a value, then the
725d2201f2fSdrahn instruction (offset -3) needs adjusting. */
726d2201f2fSdrahn HOWTO (R_MMIX_REG_OR_BYTE, /* type */
727d2201f2fSdrahn 0, /* rightshift */
728d2201f2fSdrahn 1, /* size (0 = byte, 1 = short, 2 = long) */
729d2201f2fSdrahn 8, /* bitsize */
730d2201f2fSdrahn FALSE, /* pc_relative */
731d2201f2fSdrahn 0, /* bitpos */
732d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
733d2201f2fSdrahn mmix_elf_reloc, /* special_function */
734d2201f2fSdrahn "R_MMIX_REG_OR_BYTE", /* name */
735d2201f2fSdrahn FALSE, /* partial_inplace */
736d2201f2fSdrahn 0, /* src_mask */
737d2201f2fSdrahn 0xff, /* dst_mask */
738d2201f2fSdrahn FALSE), /* pcrel_offset */
739d2201f2fSdrahn
740d2201f2fSdrahn /* A general register. */
741d2201f2fSdrahn HOWTO (R_MMIX_REG, /* type */
742d2201f2fSdrahn 0, /* rightshift */
743d2201f2fSdrahn 1, /* size (0 = byte, 1 = short, 2 = long) */
744d2201f2fSdrahn 8, /* bitsize */
745d2201f2fSdrahn FALSE, /* pc_relative */
746d2201f2fSdrahn 0, /* bitpos */
747d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
748d2201f2fSdrahn mmix_elf_reloc, /* special_function */
749d2201f2fSdrahn "R_MMIX_REG", /* name */
750d2201f2fSdrahn FALSE, /* partial_inplace */
751d2201f2fSdrahn 0, /* src_mask */
752d2201f2fSdrahn 0xff, /* dst_mask */
753d2201f2fSdrahn FALSE), /* pcrel_offset */
754d2201f2fSdrahn
755d2201f2fSdrahn /* A register plus an index, corresponding to the relocation expression.
756d2201f2fSdrahn The sizes must correspond to the valid range of the expression, while
757d2201f2fSdrahn the bitmasks correspond to what we store in the image. */
758d2201f2fSdrahn HOWTO (R_MMIX_BASE_PLUS_OFFSET, /* type */
759d2201f2fSdrahn 0, /* rightshift */
760d2201f2fSdrahn 4, /* size (0 = byte, 1 = short, 2 = long) */
761d2201f2fSdrahn 64, /* bitsize */
762d2201f2fSdrahn FALSE, /* pc_relative */
763d2201f2fSdrahn 0, /* bitpos */
764d2201f2fSdrahn complain_overflow_bitfield, /* complain_on_overflow */
765d2201f2fSdrahn mmix_elf_reloc, /* special_function */
766d2201f2fSdrahn "R_MMIX_BASE_PLUS_OFFSET", /* name */
767d2201f2fSdrahn FALSE, /* partial_inplace */
768d2201f2fSdrahn 0, /* src_mask */
769d2201f2fSdrahn 0xffff, /* dst_mask */
770d2201f2fSdrahn FALSE), /* pcrel_offset */
771d2201f2fSdrahn
772d2201f2fSdrahn /* A "magic" relocation for a LOCAL expression, asserting that the
773d2201f2fSdrahn expression is less than the number of global registers. No actual
774d2201f2fSdrahn modification of the contents is done. Implementing this as a
775d2201f2fSdrahn relocation was less intrusive than e.g. putting such expressions in a
776d2201f2fSdrahn section to discard *after* relocation. */
777d2201f2fSdrahn HOWTO (R_MMIX_LOCAL, /* type */
778d2201f2fSdrahn 0, /* rightshift */
779d2201f2fSdrahn 0, /* size (0 = byte, 1 = short, 2 = long) */
780d2201f2fSdrahn 0, /* bitsize */
781d2201f2fSdrahn FALSE, /* pc_relative */
782d2201f2fSdrahn 0, /* bitpos */
783d2201f2fSdrahn complain_overflow_dont, /* complain_on_overflow */
784d2201f2fSdrahn mmix_elf_reloc, /* special_function */
785d2201f2fSdrahn "R_MMIX_LOCAL", /* name */
786d2201f2fSdrahn FALSE, /* partial_inplace */
787d2201f2fSdrahn 0, /* src_mask */
788d2201f2fSdrahn 0, /* dst_mask */
789d2201f2fSdrahn FALSE), /* pcrel_offset */
790*cf2f2c56Smiod
791*cf2f2c56Smiod HOWTO (R_MMIX_PUSHJ_STUBBABLE, /* type */
792*cf2f2c56Smiod 2, /* rightshift */
793*cf2f2c56Smiod 2, /* size (0 = byte, 1 = short, 2 = long) */
794*cf2f2c56Smiod 19, /* bitsize */
795*cf2f2c56Smiod TRUE, /* pc_relative */
796*cf2f2c56Smiod 0, /* bitpos */
797*cf2f2c56Smiod complain_overflow_signed, /* complain_on_overflow */
798*cf2f2c56Smiod mmix_elf_reloc, /* special_function */
799*cf2f2c56Smiod "R_MMIX_PUSHJ_STUBBABLE", /* name */
800*cf2f2c56Smiod FALSE, /* partial_inplace */
801*cf2f2c56Smiod ~0x0100ffff, /* src_mask */
802*cf2f2c56Smiod 0x0100ffff, /* dst_mask */
803*cf2f2c56Smiod TRUE) /* pcrel_offset */
804d2201f2fSdrahn };
805d2201f2fSdrahn
806d2201f2fSdrahn
807d2201f2fSdrahn /* Map BFD reloc types to MMIX ELF reloc types. */
808d2201f2fSdrahn
809d2201f2fSdrahn struct mmix_reloc_map
810d2201f2fSdrahn {
811d2201f2fSdrahn bfd_reloc_code_real_type bfd_reloc_val;
812d2201f2fSdrahn enum elf_mmix_reloc_type elf_reloc_val;
813d2201f2fSdrahn };
814d2201f2fSdrahn
815d2201f2fSdrahn
816d2201f2fSdrahn static const struct mmix_reloc_map mmix_reloc_map[] =
817d2201f2fSdrahn {
818d2201f2fSdrahn {BFD_RELOC_NONE, R_MMIX_NONE},
819d2201f2fSdrahn {BFD_RELOC_8, R_MMIX_8},
820d2201f2fSdrahn {BFD_RELOC_16, R_MMIX_16},
821d2201f2fSdrahn {BFD_RELOC_24, R_MMIX_24},
822d2201f2fSdrahn {BFD_RELOC_32, R_MMIX_32},
823d2201f2fSdrahn {BFD_RELOC_64, R_MMIX_64},
824d2201f2fSdrahn {BFD_RELOC_8_PCREL, R_MMIX_PC_8},
825d2201f2fSdrahn {BFD_RELOC_16_PCREL, R_MMIX_PC_16},
826d2201f2fSdrahn {BFD_RELOC_24_PCREL, R_MMIX_PC_24},
827d2201f2fSdrahn {BFD_RELOC_32_PCREL, R_MMIX_PC_32},
828d2201f2fSdrahn {BFD_RELOC_64_PCREL, R_MMIX_PC_64},
829d2201f2fSdrahn {BFD_RELOC_VTABLE_INHERIT, R_MMIX_GNU_VTINHERIT},
830d2201f2fSdrahn {BFD_RELOC_VTABLE_ENTRY, R_MMIX_GNU_VTENTRY},
831d2201f2fSdrahn {BFD_RELOC_MMIX_GETA, R_MMIX_GETA},
832d2201f2fSdrahn {BFD_RELOC_MMIX_CBRANCH, R_MMIX_CBRANCH},
833d2201f2fSdrahn {BFD_RELOC_MMIX_PUSHJ, R_MMIX_PUSHJ},
834d2201f2fSdrahn {BFD_RELOC_MMIX_JMP, R_MMIX_JMP},
835d2201f2fSdrahn {BFD_RELOC_MMIX_ADDR19, R_MMIX_ADDR19},
836d2201f2fSdrahn {BFD_RELOC_MMIX_ADDR27, R_MMIX_ADDR27},
837d2201f2fSdrahn {BFD_RELOC_MMIX_REG_OR_BYTE, R_MMIX_REG_OR_BYTE},
838d2201f2fSdrahn {BFD_RELOC_MMIX_REG, R_MMIX_REG},
839d2201f2fSdrahn {BFD_RELOC_MMIX_BASE_PLUS_OFFSET, R_MMIX_BASE_PLUS_OFFSET},
840*cf2f2c56Smiod {BFD_RELOC_MMIX_LOCAL, R_MMIX_LOCAL},
841*cf2f2c56Smiod {BFD_RELOC_MMIX_PUSHJ_STUBBABLE, R_MMIX_PUSHJ_STUBBABLE}
842d2201f2fSdrahn };
843d2201f2fSdrahn
844d2201f2fSdrahn static reloc_howto_type *
bfd_elf64_bfd_reloc_type_lookup(abfd,code)845d2201f2fSdrahn bfd_elf64_bfd_reloc_type_lookup (abfd, code)
846d2201f2fSdrahn bfd *abfd ATTRIBUTE_UNUSED;
847d2201f2fSdrahn bfd_reloc_code_real_type code;
848d2201f2fSdrahn {
849d2201f2fSdrahn unsigned int i;
850d2201f2fSdrahn
851d2201f2fSdrahn for (i = 0;
852d2201f2fSdrahn i < sizeof (mmix_reloc_map) / sizeof (mmix_reloc_map[0]);
853d2201f2fSdrahn i++)
854d2201f2fSdrahn {
855d2201f2fSdrahn if (mmix_reloc_map[i].bfd_reloc_val == code)
856d2201f2fSdrahn return &elf_mmix_howto_table[mmix_reloc_map[i].elf_reloc_val];
857d2201f2fSdrahn }
858d2201f2fSdrahn
859d2201f2fSdrahn return NULL;
860d2201f2fSdrahn }
861d2201f2fSdrahn
862d2201f2fSdrahn static bfd_boolean
mmix_elf_new_section_hook(abfd,sec)863d2201f2fSdrahn mmix_elf_new_section_hook (abfd, sec)
864d2201f2fSdrahn bfd *abfd;
865d2201f2fSdrahn asection *sec;
866d2201f2fSdrahn {
867d2201f2fSdrahn struct _mmix_elf_section_data *sdata;
868d2201f2fSdrahn bfd_size_type amt = sizeof (*sdata);
869d2201f2fSdrahn
870d2201f2fSdrahn sdata = (struct _mmix_elf_section_data *) bfd_zalloc (abfd, amt);
871d2201f2fSdrahn if (sdata == NULL)
872d2201f2fSdrahn return FALSE;
873d2201f2fSdrahn sec->used_by_bfd = (PTR) sdata;
874d2201f2fSdrahn
875d2201f2fSdrahn return _bfd_elf_new_section_hook (abfd, sec);
876d2201f2fSdrahn }
877d2201f2fSdrahn
878d2201f2fSdrahn
879d2201f2fSdrahn /* This function performs the actual bitfiddling and sanity check for a
880d2201f2fSdrahn final relocation. Each relocation gets its *worst*-case expansion
881d2201f2fSdrahn in size when it arrives here; any reduction in size should have been
882d2201f2fSdrahn caught in linker relaxation earlier. When we get here, the relocation
883d2201f2fSdrahn looks like the smallest instruction with SWYM:s (nop:s) appended to the
884d2201f2fSdrahn max size. We fill in those nop:s.
885d2201f2fSdrahn
886d2201f2fSdrahn R_MMIX_GETA: (FIXME: Relaxation should break this up in 1, 2, 3 tetra)
887d2201f2fSdrahn GETA $N,foo
888d2201f2fSdrahn ->
889d2201f2fSdrahn SETL $N,foo & 0xffff
890d2201f2fSdrahn INCML $N,(foo >> 16) & 0xffff
891d2201f2fSdrahn INCMH $N,(foo >> 32) & 0xffff
892d2201f2fSdrahn INCH $N,(foo >> 48) & 0xffff
893d2201f2fSdrahn
894d2201f2fSdrahn R_MMIX_CBRANCH: (FIXME: Relaxation should break this up, but
895d2201f2fSdrahn condbranches needing relaxation might be rare enough to not be
896d2201f2fSdrahn worthwhile.)
897d2201f2fSdrahn [P]Bcc $N,foo
898d2201f2fSdrahn ->
899d2201f2fSdrahn [~P]B~cc $N,.+20
900d2201f2fSdrahn SETL $255,foo & ...
901d2201f2fSdrahn INCML ...
902d2201f2fSdrahn INCMH ...
903d2201f2fSdrahn INCH ...
904d2201f2fSdrahn GO $255,$255,0
905d2201f2fSdrahn
906d2201f2fSdrahn R_MMIX_PUSHJ: (FIXME: Relaxation...)
907d2201f2fSdrahn PUSHJ $N,foo
908d2201f2fSdrahn ->
909d2201f2fSdrahn SETL $255,foo & ...
910d2201f2fSdrahn INCML ...
911d2201f2fSdrahn INCMH ...
912d2201f2fSdrahn INCH ...
913d2201f2fSdrahn PUSHGO $N,$255,0
914d2201f2fSdrahn
915d2201f2fSdrahn R_MMIX_JMP: (FIXME: Relaxation...)
916d2201f2fSdrahn JMP foo
917d2201f2fSdrahn ->
918d2201f2fSdrahn SETL $255,foo & ...
919d2201f2fSdrahn INCML ...
920d2201f2fSdrahn INCMH ...
921d2201f2fSdrahn INCH ...
922d2201f2fSdrahn GO $255,$255,0
923d2201f2fSdrahn
924d2201f2fSdrahn R_MMIX_ADDR19 and R_MMIX_ADDR27 are just filled in. */
925d2201f2fSdrahn
926d2201f2fSdrahn static bfd_reloc_status_type
mmix_elf_perform_relocation(isec,howto,datap,addr,value)927d2201f2fSdrahn mmix_elf_perform_relocation (isec, howto, datap, addr, value)
928d2201f2fSdrahn asection *isec;
929d2201f2fSdrahn reloc_howto_type *howto;
930d2201f2fSdrahn PTR datap;
931*cf2f2c56Smiod bfd_vma addr;
932d2201f2fSdrahn bfd_vma value;
933d2201f2fSdrahn {
934d2201f2fSdrahn bfd *abfd = isec->owner;
935d2201f2fSdrahn bfd_reloc_status_type flag = bfd_reloc_ok;
936d2201f2fSdrahn bfd_reloc_status_type r;
937d2201f2fSdrahn int offs = 0;
938d2201f2fSdrahn int reg = 255;
939d2201f2fSdrahn
940d2201f2fSdrahn /* The worst case bits are all similar SETL/INCML/INCMH/INCH sequences.
941d2201f2fSdrahn We handle the differences here and the common sequence later. */
942d2201f2fSdrahn switch (howto->type)
943d2201f2fSdrahn {
944d2201f2fSdrahn case R_MMIX_GETA:
945d2201f2fSdrahn offs = 0;
946d2201f2fSdrahn reg = bfd_get_8 (abfd, (bfd_byte *) datap + 1);
947d2201f2fSdrahn
948d2201f2fSdrahn /* We change to an absolute value. */
949d2201f2fSdrahn value += addr;
950d2201f2fSdrahn break;
951d2201f2fSdrahn
952d2201f2fSdrahn case R_MMIX_CBRANCH:
953d2201f2fSdrahn {
954d2201f2fSdrahn int in1 = bfd_get_16 (abfd, (bfd_byte *) datap) << 16;
955d2201f2fSdrahn
956d2201f2fSdrahn /* Invert the condition and prediction bit, and set the offset
957d2201f2fSdrahn to five instructions ahead.
958d2201f2fSdrahn
959d2201f2fSdrahn We *can* do better if we want to. If the branch is found to be
960d2201f2fSdrahn within limits, we could leave the branch as is; there'll just
961d2201f2fSdrahn be a bunch of NOP:s after it. But we shouldn't see this
962d2201f2fSdrahn sequence often enough that it's worth doing it. */
963d2201f2fSdrahn
964d2201f2fSdrahn bfd_put_32 (abfd,
965d2201f2fSdrahn (((in1 ^ ((PRED_INV_BIT | COND_INV_BIT) << 24)) & ~0xffff)
966d2201f2fSdrahn | (24/4)),
967d2201f2fSdrahn (bfd_byte *) datap);
968d2201f2fSdrahn
969d2201f2fSdrahn /* Put a "GO $255,$255,0" after the common sequence. */
970d2201f2fSdrahn bfd_put_32 (abfd,
971d2201f2fSdrahn ((GO_INSN_BYTE | IMM_OFFSET_BIT) << 24) | 0xffff00,
972d2201f2fSdrahn (bfd_byte *) datap + 20);
973d2201f2fSdrahn
974d2201f2fSdrahn /* Common sequence starts at offset 4. */
975d2201f2fSdrahn offs = 4;
976d2201f2fSdrahn
977d2201f2fSdrahn /* We change to an absolute value. */
978d2201f2fSdrahn value += addr;
979d2201f2fSdrahn }
980d2201f2fSdrahn break;
981d2201f2fSdrahn
982*cf2f2c56Smiod case R_MMIX_PUSHJ_STUBBABLE:
983*cf2f2c56Smiod /* If the address fits, we're fine. */
984*cf2f2c56Smiod if ((value & 3) == 0
985*cf2f2c56Smiod /* Note rightshift 0; see R_MMIX_JMP case below. */
986*cf2f2c56Smiod && (r = bfd_check_overflow (complain_overflow_signed,
987*cf2f2c56Smiod howto->bitsize,
988*cf2f2c56Smiod 0,
989*cf2f2c56Smiod bfd_arch_bits_per_address (abfd),
990*cf2f2c56Smiod value)) == bfd_reloc_ok)
991*cf2f2c56Smiod goto pcrel_mmix_reloc_fits;
992*cf2f2c56Smiod else
993*cf2f2c56Smiod {
994*cf2f2c56Smiod bfd_size_type raw_size
995*cf2f2c56Smiod = (isec->_raw_size
996*cf2f2c56Smiod - mmix_elf_section_data (isec)->pjs.n_pushj_relocs
997*cf2f2c56Smiod * MAX_PUSHJ_STUB_SIZE);
998*cf2f2c56Smiod
999*cf2f2c56Smiod /* We have the bytes at the PUSHJ insn and need to get the
1000*cf2f2c56Smiod position for the stub. There's supposed to be room allocated
1001*cf2f2c56Smiod for the stub. */
1002*cf2f2c56Smiod bfd_byte *stubcontents
1003*cf2f2c56Smiod = ((char *) datap
1004*cf2f2c56Smiod - (addr - (isec->output_section->vma + isec->output_offset))
1005*cf2f2c56Smiod + raw_size
1006*cf2f2c56Smiod + mmix_elf_section_data (isec)->pjs.stub_offset);
1007*cf2f2c56Smiod bfd_vma stubaddr;
1008*cf2f2c56Smiod
1009*cf2f2c56Smiod /* The address doesn't fit, so redirect the PUSHJ to the
1010*cf2f2c56Smiod location of the stub. */
1011*cf2f2c56Smiod r = mmix_elf_perform_relocation (isec,
1012*cf2f2c56Smiod &elf_mmix_howto_table
1013*cf2f2c56Smiod [R_MMIX_ADDR19],
1014*cf2f2c56Smiod datap,
1015*cf2f2c56Smiod addr,
1016*cf2f2c56Smiod isec->output_section->vma
1017*cf2f2c56Smiod + isec->output_offset
1018*cf2f2c56Smiod + raw_size
1019*cf2f2c56Smiod + (mmix_elf_section_data (isec)
1020*cf2f2c56Smiod ->pjs.stub_offset)
1021*cf2f2c56Smiod - addr);
1022*cf2f2c56Smiod if (r != bfd_reloc_ok)
1023*cf2f2c56Smiod return r;
1024*cf2f2c56Smiod
1025*cf2f2c56Smiod stubaddr
1026*cf2f2c56Smiod = (isec->output_section->vma
1027*cf2f2c56Smiod + isec->output_offset
1028*cf2f2c56Smiod + raw_size
1029*cf2f2c56Smiod + mmix_elf_section_data (isec)->pjs.stub_offset);
1030*cf2f2c56Smiod
1031*cf2f2c56Smiod /* We generate a simple JMP if that suffices, else the whole 5
1032*cf2f2c56Smiod insn stub. */
1033*cf2f2c56Smiod if (bfd_check_overflow (complain_overflow_signed,
1034*cf2f2c56Smiod elf_mmix_howto_table[R_MMIX_ADDR27].bitsize,
1035*cf2f2c56Smiod 0,
1036*cf2f2c56Smiod bfd_arch_bits_per_address (abfd),
1037*cf2f2c56Smiod addr + value - stubaddr) == bfd_reloc_ok)
1038*cf2f2c56Smiod {
1039*cf2f2c56Smiod bfd_put_32 (abfd, JMP_INSN_BYTE << 24, stubcontents);
1040*cf2f2c56Smiod r = mmix_elf_perform_relocation (isec,
1041*cf2f2c56Smiod &elf_mmix_howto_table
1042*cf2f2c56Smiod [R_MMIX_ADDR27],
1043*cf2f2c56Smiod stubcontents,
1044*cf2f2c56Smiod stubaddr,
1045*cf2f2c56Smiod value + addr - stubaddr);
1046*cf2f2c56Smiod mmix_elf_section_data (isec)->pjs.stub_offset += 4;
1047*cf2f2c56Smiod
1048*cf2f2c56Smiod if (raw_size
1049*cf2f2c56Smiod + mmix_elf_section_data (isec)->pjs.stub_offset
1050*cf2f2c56Smiod > isec->_cooked_size)
1051*cf2f2c56Smiod abort ();
1052*cf2f2c56Smiod
1053*cf2f2c56Smiod return r;
1054*cf2f2c56Smiod }
1055*cf2f2c56Smiod else
1056*cf2f2c56Smiod {
1057*cf2f2c56Smiod /* Put a "GO $255,0" after the common sequence. */
1058*cf2f2c56Smiod bfd_put_32 (abfd,
1059*cf2f2c56Smiod ((GO_INSN_BYTE | IMM_OFFSET_BIT) << 24)
1060*cf2f2c56Smiod | 0xff00, (bfd_byte *) stubcontents + 16);
1061*cf2f2c56Smiod
1062*cf2f2c56Smiod /* Prepare for the general code to set the first part of the
1063*cf2f2c56Smiod linker stub, and */
1064*cf2f2c56Smiod value += addr;
1065*cf2f2c56Smiod datap = stubcontents;
1066*cf2f2c56Smiod mmix_elf_section_data (isec)->pjs.stub_offset
1067*cf2f2c56Smiod += MAX_PUSHJ_STUB_SIZE;
1068*cf2f2c56Smiod }
1069*cf2f2c56Smiod }
1070*cf2f2c56Smiod break;
1071*cf2f2c56Smiod
1072d2201f2fSdrahn case R_MMIX_PUSHJ:
1073d2201f2fSdrahn {
1074d2201f2fSdrahn int inreg = bfd_get_8 (abfd, (bfd_byte *) datap + 1);
1075d2201f2fSdrahn
1076d2201f2fSdrahn /* Put a "PUSHGO $N,$255,0" after the common sequence. */
1077d2201f2fSdrahn bfd_put_32 (abfd,
1078d2201f2fSdrahn ((PUSHGO_INSN_BYTE | IMM_OFFSET_BIT) << 24)
1079d2201f2fSdrahn | (inreg << 16)
1080d2201f2fSdrahn | 0xff00,
1081d2201f2fSdrahn (bfd_byte *) datap + 16);
1082d2201f2fSdrahn
1083d2201f2fSdrahn /* We change to an absolute value. */
1084d2201f2fSdrahn value += addr;
1085d2201f2fSdrahn }
1086d2201f2fSdrahn break;
1087d2201f2fSdrahn
1088d2201f2fSdrahn case R_MMIX_JMP:
1089d2201f2fSdrahn /* This one is a little special. If we get here on a non-relaxing
1090d2201f2fSdrahn link, and the destination is actually in range, we don't need to
1091d2201f2fSdrahn execute the nops.
1092d2201f2fSdrahn If so, we fall through to the bit-fiddling relocs.
1093d2201f2fSdrahn
1094d2201f2fSdrahn FIXME: bfd_check_overflow seems broken; the relocation is
1095d2201f2fSdrahn rightshifted before testing, so supply a zero rightshift. */
1096d2201f2fSdrahn
1097d2201f2fSdrahn if (! ((value & 3) == 0
1098d2201f2fSdrahn && (r = bfd_check_overflow (complain_overflow_signed,
1099d2201f2fSdrahn howto->bitsize,
1100d2201f2fSdrahn 0,
1101d2201f2fSdrahn bfd_arch_bits_per_address (abfd),
1102d2201f2fSdrahn value)) == bfd_reloc_ok))
1103d2201f2fSdrahn {
1104d2201f2fSdrahn /* If the relocation doesn't fit in a JMP, we let the NOP:s be
1105d2201f2fSdrahn modified below, and put a "GO $255,$255,0" after the
1106d2201f2fSdrahn address-loading sequence. */
1107d2201f2fSdrahn bfd_put_32 (abfd,
1108d2201f2fSdrahn ((GO_INSN_BYTE | IMM_OFFSET_BIT) << 24)
1109d2201f2fSdrahn | 0xffff00,
1110d2201f2fSdrahn (bfd_byte *) datap + 16);
1111d2201f2fSdrahn
1112d2201f2fSdrahn /* We change to an absolute value. */
1113d2201f2fSdrahn value += addr;
1114d2201f2fSdrahn break;
1115d2201f2fSdrahn }
1116d2201f2fSdrahn /* FALLTHROUGH. */
1117d2201f2fSdrahn case R_MMIX_ADDR19:
1118d2201f2fSdrahn case R_MMIX_ADDR27:
1119*cf2f2c56Smiod pcrel_mmix_reloc_fits:
1120d2201f2fSdrahn /* These must be in range, or else we emit an error. */
1121d2201f2fSdrahn if ((value & 3) == 0
1122d2201f2fSdrahn /* Note rightshift 0; see above. */
1123d2201f2fSdrahn && (r = bfd_check_overflow (complain_overflow_signed,
1124d2201f2fSdrahn howto->bitsize,
1125d2201f2fSdrahn 0,
1126d2201f2fSdrahn bfd_arch_bits_per_address (abfd),
1127d2201f2fSdrahn value)) == bfd_reloc_ok)
1128d2201f2fSdrahn {
1129d2201f2fSdrahn bfd_vma in1
1130d2201f2fSdrahn = bfd_get_32 (abfd, (bfd_byte *) datap);
1131d2201f2fSdrahn bfd_vma highbit;
1132d2201f2fSdrahn
1133d2201f2fSdrahn if ((bfd_signed_vma) value < 0)
1134d2201f2fSdrahn {
1135*cf2f2c56Smiod highbit = 1 << 24;
1136d2201f2fSdrahn value += (1 << (howto->bitsize - 1));
1137d2201f2fSdrahn }
1138d2201f2fSdrahn else
1139d2201f2fSdrahn highbit = 0;
1140d2201f2fSdrahn
1141d2201f2fSdrahn value >>= 2;
1142d2201f2fSdrahn
1143d2201f2fSdrahn bfd_put_32 (abfd,
1144d2201f2fSdrahn (in1 & howto->src_mask)
1145d2201f2fSdrahn | highbit
1146d2201f2fSdrahn | (value & howto->dst_mask),
1147d2201f2fSdrahn (bfd_byte *) datap);
1148d2201f2fSdrahn
1149d2201f2fSdrahn return bfd_reloc_ok;
1150d2201f2fSdrahn }
1151d2201f2fSdrahn else
1152d2201f2fSdrahn return bfd_reloc_overflow;
1153d2201f2fSdrahn
1154d2201f2fSdrahn case R_MMIX_BASE_PLUS_OFFSET:
1155d2201f2fSdrahn {
1156d2201f2fSdrahn struct bpo_reloc_section_info *bpodata
1157d2201f2fSdrahn = mmix_elf_section_data (isec)->bpo.reloc;
1158d2201f2fSdrahn asection *bpo_greg_section
1159d2201f2fSdrahn = bpodata->bpo_greg_section;
1160d2201f2fSdrahn struct bpo_greg_section_info *gregdata
1161d2201f2fSdrahn = mmix_elf_section_data (bpo_greg_section)->bpo.greg;
1162d2201f2fSdrahn size_t bpo_index
1163d2201f2fSdrahn = gregdata->bpo_reloc_indexes[bpodata->bpo_index++];
1164d2201f2fSdrahn
1165d2201f2fSdrahn /* A consistency check: The value we now have in "relocation" must
1166d2201f2fSdrahn be the same as the value we stored for that relocation. It
1167d2201f2fSdrahn doesn't cost much, so can be left in at all times. */
1168d2201f2fSdrahn if (value != gregdata->reloc_request[bpo_index].value)
1169d2201f2fSdrahn {
1170d2201f2fSdrahn (*_bfd_error_handler)
1171d2201f2fSdrahn (_("%s: Internal inconsistency error for value for\n\
1172d2201f2fSdrahn linker-allocated global register: linked: 0x%lx%08lx != relaxed: 0x%lx%08lx\n"),
1173d2201f2fSdrahn bfd_get_filename (isec->owner),
1174d2201f2fSdrahn (unsigned long) (value >> 32), (unsigned long) value,
1175d2201f2fSdrahn (unsigned long) (gregdata->reloc_request[bpo_index].value
1176d2201f2fSdrahn >> 32),
1177d2201f2fSdrahn (unsigned long) gregdata->reloc_request[bpo_index].value);
1178d2201f2fSdrahn bfd_set_error (bfd_error_bad_value);
1179d2201f2fSdrahn return bfd_reloc_overflow;
1180d2201f2fSdrahn }
1181d2201f2fSdrahn
1182d2201f2fSdrahn /* Then store the register number and offset for that register
1183d2201f2fSdrahn into datap and datap + 1 respectively. */
1184d2201f2fSdrahn bfd_put_8 (abfd,
1185d2201f2fSdrahn gregdata->reloc_request[bpo_index].regindex
1186d2201f2fSdrahn + bpo_greg_section->output_section->vma / 8,
1187d2201f2fSdrahn datap);
1188d2201f2fSdrahn bfd_put_8 (abfd,
1189d2201f2fSdrahn gregdata->reloc_request[bpo_index].offset,
1190d2201f2fSdrahn ((unsigned char *) datap) + 1);
1191d2201f2fSdrahn return bfd_reloc_ok;
1192d2201f2fSdrahn }
1193d2201f2fSdrahn
1194d2201f2fSdrahn case R_MMIX_REG_OR_BYTE:
1195d2201f2fSdrahn case R_MMIX_REG:
1196d2201f2fSdrahn if (value > 255)
1197d2201f2fSdrahn return bfd_reloc_overflow;
1198d2201f2fSdrahn bfd_put_8 (abfd, value, datap);
1199d2201f2fSdrahn return bfd_reloc_ok;
1200d2201f2fSdrahn
1201d2201f2fSdrahn default:
1202d2201f2fSdrahn BAD_CASE (howto->type);
1203d2201f2fSdrahn }
1204d2201f2fSdrahn
1205d2201f2fSdrahn /* This code adds the common SETL/INCML/INCMH/INCH worst-case
1206d2201f2fSdrahn sequence. */
1207d2201f2fSdrahn
1208d2201f2fSdrahn /* Lowest two bits must be 0. We return bfd_reloc_overflow for
1209d2201f2fSdrahn everything that looks strange. */
1210d2201f2fSdrahn if (value & 3)
1211d2201f2fSdrahn flag = bfd_reloc_overflow;
1212d2201f2fSdrahn
1213d2201f2fSdrahn bfd_put_32 (abfd,
1214d2201f2fSdrahn (SETL_INSN_BYTE << 24) | (value & 0xffff) | (reg << 16),
1215d2201f2fSdrahn (bfd_byte *) datap + offs);
1216d2201f2fSdrahn bfd_put_32 (abfd,
1217d2201f2fSdrahn (INCML_INSN_BYTE << 24) | ((value >> 16) & 0xffff) | (reg << 16),
1218d2201f2fSdrahn (bfd_byte *) datap + offs + 4);
1219d2201f2fSdrahn bfd_put_32 (abfd,
1220d2201f2fSdrahn (INCMH_INSN_BYTE << 24) | ((value >> 32) & 0xffff) | (reg << 16),
1221d2201f2fSdrahn (bfd_byte *) datap + offs + 8);
1222d2201f2fSdrahn bfd_put_32 (abfd,
1223d2201f2fSdrahn (INCH_INSN_BYTE << 24) | ((value >> 48) & 0xffff) | (reg << 16),
1224d2201f2fSdrahn (bfd_byte *) datap + offs + 12);
1225d2201f2fSdrahn
1226d2201f2fSdrahn return flag;
1227d2201f2fSdrahn }
1228d2201f2fSdrahn
1229d2201f2fSdrahn /* Set the howto pointer for an MMIX ELF reloc (type RELA). */
1230d2201f2fSdrahn
1231d2201f2fSdrahn static void
mmix_info_to_howto_rela(abfd,cache_ptr,dst)1232d2201f2fSdrahn mmix_info_to_howto_rela (abfd, cache_ptr, dst)
1233d2201f2fSdrahn bfd *abfd ATTRIBUTE_UNUSED;
1234d2201f2fSdrahn arelent *cache_ptr;
1235d2201f2fSdrahn Elf_Internal_Rela *dst;
1236d2201f2fSdrahn {
1237d2201f2fSdrahn unsigned int r_type;
1238d2201f2fSdrahn
1239d2201f2fSdrahn r_type = ELF64_R_TYPE (dst->r_info);
1240d2201f2fSdrahn BFD_ASSERT (r_type < (unsigned int) R_MMIX_max);
1241d2201f2fSdrahn cache_ptr->howto = &elf_mmix_howto_table[r_type];
1242d2201f2fSdrahn }
1243d2201f2fSdrahn
1244d2201f2fSdrahn /* Any MMIX-specific relocation gets here at assembly time or when linking
1245d2201f2fSdrahn to other formats (such as mmo); this is the relocation function from
1246d2201f2fSdrahn the reloc_table. We don't get here for final pure ELF linking. */
1247d2201f2fSdrahn
1248d2201f2fSdrahn static bfd_reloc_status_type
mmix_elf_reloc(abfd,reloc_entry,symbol,data,input_section,output_bfd,error_message)1249d2201f2fSdrahn mmix_elf_reloc (abfd, reloc_entry, symbol, data, input_section,
1250d2201f2fSdrahn output_bfd, error_message)
1251d2201f2fSdrahn bfd *abfd;
1252d2201f2fSdrahn arelent *reloc_entry;
1253d2201f2fSdrahn asymbol *symbol;
1254d2201f2fSdrahn PTR data;
1255d2201f2fSdrahn asection *input_section;
1256d2201f2fSdrahn bfd *output_bfd;
1257d2201f2fSdrahn char **error_message ATTRIBUTE_UNUSED;
1258d2201f2fSdrahn {
1259d2201f2fSdrahn bfd_vma relocation;
1260d2201f2fSdrahn bfd_reloc_status_type r;
1261d2201f2fSdrahn asection *reloc_target_output_section;
1262d2201f2fSdrahn bfd_reloc_status_type flag = bfd_reloc_ok;
1263d2201f2fSdrahn bfd_vma output_base = 0;
1264d2201f2fSdrahn bfd_vma addr;
1265d2201f2fSdrahn
1266d2201f2fSdrahn r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
1267d2201f2fSdrahn input_section, output_bfd, error_message);
1268d2201f2fSdrahn
1269d2201f2fSdrahn /* If that was all that was needed (i.e. this isn't a final link, only
1270d2201f2fSdrahn some segment adjustments), we're done. */
1271d2201f2fSdrahn if (r != bfd_reloc_continue)
1272d2201f2fSdrahn return r;
1273d2201f2fSdrahn
1274d2201f2fSdrahn if (bfd_is_und_section (symbol->section)
1275d2201f2fSdrahn && (symbol->flags & BSF_WEAK) == 0
1276d2201f2fSdrahn && output_bfd == (bfd *) NULL)
1277d2201f2fSdrahn return bfd_reloc_undefined;
1278d2201f2fSdrahn
1279d2201f2fSdrahn /* Is the address of the relocation really within the section? */
1280d2201f2fSdrahn if (reloc_entry->address > input_section->_cooked_size)
1281d2201f2fSdrahn return bfd_reloc_outofrange;
1282d2201f2fSdrahn
1283*cf2f2c56Smiod /* Work out which section the relocation is targeted at and the
1284d2201f2fSdrahn initial relocation command value. */
1285d2201f2fSdrahn
1286d2201f2fSdrahn /* Get symbol value. (Common symbols are special.) */
1287d2201f2fSdrahn if (bfd_is_com_section (symbol->section))
1288d2201f2fSdrahn relocation = 0;
1289d2201f2fSdrahn else
1290d2201f2fSdrahn relocation = symbol->value;
1291d2201f2fSdrahn
1292d2201f2fSdrahn reloc_target_output_section = bfd_get_output_section (symbol);
1293d2201f2fSdrahn
1294d2201f2fSdrahn /* Here the variable relocation holds the final address of the symbol we
1295d2201f2fSdrahn are relocating against, plus any addend. */
1296d2201f2fSdrahn if (output_bfd)
1297d2201f2fSdrahn output_base = 0;
1298d2201f2fSdrahn else
1299d2201f2fSdrahn output_base = reloc_target_output_section->vma;
1300d2201f2fSdrahn
1301d2201f2fSdrahn relocation += output_base + symbol->section->output_offset;
1302d2201f2fSdrahn
1303d2201f2fSdrahn /* Get position of relocation. */
1304d2201f2fSdrahn addr = (reloc_entry->address + input_section->output_section->vma
1305d2201f2fSdrahn + input_section->output_offset);
1306d2201f2fSdrahn if (output_bfd != (bfd *) NULL)
1307d2201f2fSdrahn {
1308d2201f2fSdrahn /* Add in supplied addend. */
1309d2201f2fSdrahn relocation += reloc_entry->addend;
1310d2201f2fSdrahn
1311d2201f2fSdrahn /* This is a partial relocation, and we want to apply the
1312d2201f2fSdrahn relocation to the reloc entry rather than the raw data.
1313d2201f2fSdrahn Modify the reloc inplace to reflect what we now know. */
1314d2201f2fSdrahn reloc_entry->addend = relocation;
1315d2201f2fSdrahn reloc_entry->address += input_section->output_offset;
1316d2201f2fSdrahn return flag;
1317d2201f2fSdrahn }
1318d2201f2fSdrahn
1319d2201f2fSdrahn return mmix_final_link_relocate (reloc_entry->howto, input_section,
1320d2201f2fSdrahn data, reloc_entry->address,
1321d2201f2fSdrahn reloc_entry->addend, relocation,
1322d2201f2fSdrahn bfd_asymbol_name (symbol),
1323d2201f2fSdrahn reloc_target_output_section);
1324d2201f2fSdrahn }
1325d2201f2fSdrahn
1326d2201f2fSdrahn /* Relocate an MMIX ELF section. Modified from elf32-fr30.c; look to it
1327d2201f2fSdrahn for guidance if you're thinking of copying this. */
1328d2201f2fSdrahn
1329d2201f2fSdrahn static bfd_boolean
mmix_elf_relocate_section(output_bfd,info,input_bfd,input_section,contents,relocs,local_syms,local_sections)1330d2201f2fSdrahn mmix_elf_relocate_section (output_bfd, info, input_bfd, input_section,
1331d2201f2fSdrahn contents, relocs, local_syms, local_sections)
1332d2201f2fSdrahn bfd *output_bfd ATTRIBUTE_UNUSED;
1333d2201f2fSdrahn struct bfd_link_info *info;
1334d2201f2fSdrahn bfd *input_bfd;
1335d2201f2fSdrahn asection *input_section;
1336d2201f2fSdrahn bfd_byte *contents;
1337d2201f2fSdrahn Elf_Internal_Rela *relocs;
1338d2201f2fSdrahn Elf_Internal_Sym *local_syms;
1339d2201f2fSdrahn asection **local_sections;
1340d2201f2fSdrahn {
1341d2201f2fSdrahn Elf_Internal_Shdr *symtab_hdr;
1342d2201f2fSdrahn struct elf_link_hash_entry **sym_hashes;
1343d2201f2fSdrahn Elf_Internal_Rela *rel;
1344d2201f2fSdrahn Elf_Internal_Rela *relend;
1345*cf2f2c56Smiod bfd_size_type raw_size
1346*cf2f2c56Smiod = (input_section->_raw_size
1347*cf2f2c56Smiod - mmix_elf_section_data (input_section)->pjs.n_pushj_relocs
1348*cf2f2c56Smiod * MAX_PUSHJ_STUB_SIZE);
1349*cf2f2c56Smiod size_t pjsno = 0;
1350d2201f2fSdrahn
1351d2201f2fSdrahn symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
1352d2201f2fSdrahn sym_hashes = elf_sym_hashes (input_bfd);
1353d2201f2fSdrahn relend = relocs + input_section->reloc_count;
1354d2201f2fSdrahn
1355d2201f2fSdrahn for (rel = relocs; rel < relend; rel ++)
1356d2201f2fSdrahn {
1357d2201f2fSdrahn reloc_howto_type *howto;
1358d2201f2fSdrahn unsigned long r_symndx;
1359d2201f2fSdrahn Elf_Internal_Sym *sym;
1360d2201f2fSdrahn asection *sec;
1361d2201f2fSdrahn struct elf_link_hash_entry *h;
1362d2201f2fSdrahn bfd_vma relocation;
1363d2201f2fSdrahn bfd_reloc_status_type r;
1364d2201f2fSdrahn const char *name = NULL;
1365d2201f2fSdrahn int r_type;
1366d2201f2fSdrahn bfd_boolean undefined_signalled = FALSE;
1367d2201f2fSdrahn
1368d2201f2fSdrahn r_type = ELF64_R_TYPE (rel->r_info);
1369d2201f2fSdrahn
1370d2201f2fSdrahn if (r_type == R_MMIX_GNU_VTINHERIT
1371d2201f2fSdrahn || r_type == R_MMIX_GNU_VTENTRY)
1372d2201f2fSdrahn continue;
1373d2201f2fSdrahn
1374d2201f2fSdrahn r_symndx = ELF64_R_SYM (rel->r_info);
1375d2201f2fSdrahn
1376*cf2f2c56Smiod if (info->relocatable)
1377d2201f2fSdrahn {
1378*cf2f2c56Smiod /* This is a relocatable link. For most relocs we don't have to
1379*cf2f2c56Smiod change anything, unless the reloc is against a section
1380*cf2f2c56Smiod symbol, in which case we have to adjust according to where
1381*cf2f2c56Smiod the section symbol winds up in the output section. */
1382d2201f2fSdrahn if (r_symndx < symtab_hdr->sh_info)
1383d2201f2fSdrahn {
1384d2201f2fSdrahn sym = local_syms + r_symndx;
1385d2201f2fSdrahn
1386d2201f2fSdrahn if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
1387d2201f2fSdrahn {
1388d2201f2fSdrahn sec = local_sections [r_symndx];
1389d2201f2fSdrahn rel->r_addend += sec->output_offset + sym->st_value;
1390d2201f2fSdrahn }
1391d2201f2fSdrahn }
1392d2201f2fSdrahn
1393*cf2f2c56Smiod /* For PUSHJ stub relocs however, we may need to change the
1394*cf2f2c56Smiod reloc and the section contents, if the reloc doesn't reach
1395*cf2f2c56Smiod beyond the end of the output section and previous stubs.
1396*cf2f2c56Smiod Then we change the section contents to be a PUSHJ to the end
1397*cf2f2c56Smiod of the input section plus stubs (we can do that without using
1398*cf2f2c56Smiod a reloc), and then we change the reloc to be a R_MMIX_PUSHJ
1399*cf2f2c56Smiod at the stub location. */
1400*cf2f2c56Smiod if (r_type == R_MMIX_PUSHJ_STUBBABLE)
1401*cf2f2c56Smiod {
1402*cf2f2c56Smiod /* We've already checked whether we need a stub; use that
1403*cf2f2c56Smiod knowledge. */
1404*cf2f2c56Smiod if (mmix_elf_section_data (input_section)->pjs.stub_size[pjsno]
1405*cf2f2c56Smiod != 0)
1406*cf2f2c56Smiod {
1407*cf2f2c56Smiod Elf_Internal_Rela relcpy;
1408*cf2f2c56Smiod
1409*cf2f2c56Smiod if (mmix_elf_section_data (input_section)
1410*cf2f2c56Smiod ->pjs.stub_size[pjsno] != MAX_PUSHJ_STUB_SIZE)
1411*cf2f2c56Smiod abort ();
1412*cf2f2c56Smiod
1413*cf2f2c56Smiod /* There's already a PUSHJ insn there, so just fill in
1414*cf2f2c56Smiod the offset bits to the stub. */
1415*cf2f2c56Smiod if (mmix_final_link_relocate (elf_mmix_howto_table
1416*cf2f2c56Smiod + R_MMIX_ADDR19,
1417*cf2f2c56Smiod input_section,
1418*cf2f2c56Smiod contents,
1419*cf2f2c56Smiod rel->r_offset,
1420*cf2f2c56Smiod 0,
1421*cf2f2c56Smiod input_section
1422*cf2f2c56Smiod ->output_section->vma
1423*cf2f2c56Smiod + input_section->output_offset
1424*cf2f2c56Smiod + raw_size
1425*cf2f2c56Smiod + mmix_elf_section_data (input_section)
1426*cf2f2c56Smiod ->pjs.stub_offset,
1427*cf2f2c56Smiod NULL, NULL) != bfd_reloc_ok)
1428*cf2f2c56Smiod return FALSE;
1429*cf2f2c56Smiod
1430*cf2f2c56Smiod /* Put a JMP insn at the stub; it goes with the
1431*cf2f2c56Smiod R_MMIX_JMP reloc. */
1432*cf2f2c56Smiod bfd_put_32 (output_bfd, JMP_INSN_BYTE << 24,
1433*cf2f2c56Smiod contents
1434*cf2f2c56Smiod + raw_size
1435*cf2f2c56Smiod + mmix_elf_section_data (input_section)
1436*cf2f2c56Smiod ->pjs.stub_offset);
1437*cf2f2c56Smiod
1438*cf2f2c56Smiod /* Change the reloc to be at the stub, and to a full
1439*cf2f2c56Smiod R_MMIX_JMP reloc. */
1440*cf2f2c56Smiod rel->r_info = ELF64_R_INFO (r_symndx, R_MMIX_JMP);
1441*cf2f2c56Smiod rel->r_offset
1442*cf2f2c56Smiod = (raw_size
1443*cf2f2c56Smiod + mmix_elf_section_data (input_section)
1444*cf2f2c56Smiod ->pjs.stub_offset);
1445*cf2f2c56Smiod
1446*cf2f2c56Smiod mmix_elf_section_data (input_section)->pjs.stub_offset
1447*cf2f2c56Smiod += MAX_PUSHJ_STUB_SIZE;
1448*cf2f2c56Smiod
1449*cf2f2c56Smiod /* Shift this reloc to the end of the relocs to maintain
1450*cf2f2c56Smiod the r_offset sorted reloc order. */
1451*cf2f2c56Smiod relcpy = *rel;
1452*cf2f2c56Smiod memmove (rel, rel + 1, (char *) relend - (char *) rel);
1453*cf2f2c56Smiod relend[-1] = relcpy;
1454*cf2f2c56Smiod
1455*cf2f2c56Smiod /* Back up one reloc, or else we'd skip the next reloc
1456*cf2f2c56Smiod in turn. */
1457*cf2f2c56Smiod rel--;
1458*cf2f2c56Smiod }
1459*cf2f2c56Smiod
1460*cf2f2c56Smiod pjsno++;
1461*cf2f2c56Smiod }
1462d2201f2fSdrahn continue;
1463d2201f2fSdrahn }
1464d2201f2fSdrahn
1465d2201f2fSdrahn /* This is a final link. */
1466d2201f2fSdrahn howto = elf_mmix_howto_table + ELF64_R_TYPE (rel->r_info);
1467d2201f2fSdrahn h = NULL;
1468d2201f2fSdrahn sym = NULL;
1469d2201f2fSdrahn sec = NULL;
1470d2201f2fSdrahn
1471d2201f2fSdrahn if (r_symndx < symtab_hdr->sh_info)
1472d2201f2fSdrahn {
1473d2201f2fSdrahn sym = local_syms + r_symndx;
1474d2201f2fSdrahn sec = local_sections [r_symndx];
1475*cf2f2c56Smiod relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1476d2201f2fSdrahn
1477*cf2f2c56Smiod name = bfd_elf_string_from_elf_section (input_bfd,
1478*cf2f2c56Smiod symtab_hdr->sh_link,
1479*cf2f2c56Smiod sym->st_name);
1480*cf2f2c56Smiod if (name == NULL)
1481*cf2f2c56Smiod name = bfd_section_name (input_bfd, sec);
1482d2201f2fSdrahn }
1483d2201f2fSdrahn else
1484d2201f2fSdrahn {
1485*cf2f2c56Smiod bfd_boolean unresolved_reloc;
1486d2201f2fSdrahn
1487*cf2f2c56Smiod RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1488*cf2f2c56Smiod r_symndx, symtab_hdr, sym_hashes,
1489*cf2f2c56Smiod h, sec, relocation,
1490*cf2f2c56Smiod unresolved_reloc, undefined_signalled);
1491d2201f2fSdrahn name = h->root.root.string;
1492d2201f2fSdrahn }
1493d2201f2fSdrahn
1494d2201f2fSdrahn r = mmix_final_link_relocate (howto, input_section,
1495d2201f2fSdrahn contents, rel->r_offset,
1496d2201f2fSdrahn rel->r_addend, relocation, name, sec);
1497d2201f2fSdrahn
1498d2201f2fSdrahn if (r != bfd_reloc_ok)
1499d2201f2fSdrahn {
1500d2201f2fSdrahn bfd_boolean check_ok = TRUE;
1501d2201f2fSdrahn const char * msg = (const char *) NULL;
1502d2201f2fSdrahn
1503d2201f2fSdrahn switch (r)
1504d2201f2fSdrahn {
1505d2201f2fSdrahn case bfd_reloc_overflow:
1506d2201f2fSdrahn check_ok = info->callbacks->reloc_overflow
1507d2201f2fSdrahn (info, name, howto->name, (bfd_vma) 0,
1508d2201f2fSdrahn input_bfd, input_section, rel->r_offset);
1509d2201f2fSdrahn break;
1510d2201f2fSdrahn
1511d2201f2fSdrahn case bfd_reloc_undefined:
1512d2201f2fSdrahn /* We may have sent this message above. */
1513d2201f2fSdrahn if (! undefined_signalled)
1514d2201f2fSdrahn check_ok = info->callbacks->undefined_symbol
1515d2201f2fSdrahn (info, name, input_bfd, input_section, rel->r_offset,
1516d2201f2fSdrahn TRUE);
1517d2201f2fSdrahn undefined_signalled = TRUE;
1518d2201f2fSdrahn break;
1519d2201f2fSdrahn
1520d2201f2fSdrahn case bfd_reloc_outofrange:
1521d2201f2fSdrahn msg = _("internal error: out of range error");
1522d2201f2fSdrahn break;
1523d2201f2fSdrahn
1524d2201f2fSdrahn case bfd_reloc_notsupported:
1525d2201f2fSdrahn msg = _("internal error: unsupported relocation error");
1526d2201f2fSdrahn break;
1527d2201f2fSdrahn
1528d2201f2fSdrahn case bfd_reloc_dangerous:
1529d2201f2fSdrahn msg = _("internal error: dangerous relocation");
1530d2201f2fSdrahn break;
1531d2201f2fSdrahn
1532d2201f2fSdrahn default:
1533d2201f2fSdrahn msg = _("internal error: unknown error");
1534d2201f2fSdrahn break;
1535d2201f2fSdrahn }
1536d2201f2fSdrahn
1537d2201f2fSdrahn if (msg)
1538d2201f2fSdrahn check_ok = info->callbacks->warning
1539d2201f2fSdrahn (info, msg, name, input_bfd, input_section, rel->r_offset);
1540d2201f2fSdrahn
1541d2201f2fSdrahn if (! check_ok)
1542d2201f2fSdrahn return FALSE;
1543d2201f2fSdrahn }
1544d2201f2fSdrahn }
1545d2201f2fSdrahn
1546d2201f2fSdrahn return TRUE;
1547d2201f2fSdrahn }
1548d2201f2fSdrahn
1549d2201f2fSdrahn /* Perform a single relocation. By default we use the standard BFD
1550d2201f2fSdrahn routines. A few relocs we have to do ourselves. */
1551d2201f2fSdrahn
1552d2201f2fSdrahn static bfd_reloc_status_type
mmix_final_link_relocate(howto,input_section,contents,r_offset,r_addend,relocation,symname,symsec)1553d2201f2fSdrahn mmix_final_link_relocate (howto, input_section, contents,
1554d2201f2fSdrahn r_offset, r_addend, relocation, symname, symsec)
1555d2201f2fSdrahn reloc_howto_type *howto;
1556d2201f2fSdrahn asection *input_section;
1557d2201f2fSdrahn bfd_byte *contents;
1558d2201f2fSdrahn bfd_vma r_offset;
1559d2201f2fSdrahn bfd_signed_vma r_addend;
1560d2201f2fSdrahn bfd_vma relocation;
1561d2201f2fSdrahn const char *symname;
1562d2201f2fSdrahn asection *symsec;
1563d2201f2fSdrahn {
1564d2201f2fSdrahn bfd_reloc_status_type r = bfd_reloc_ok;
1565d2201f2fSdrahn bfd_vma addr
1566d2201f2fSdrahn = (input_section->output_section->vma
1567d2201f2fSdrahn + input_section->output_offset
1568d2201f2fSdrahn + r_offset);
1569d2201f2fSdrahn bfd_signed_vma srel
1570d2201f2fSdrahn = (bfd_signed_vma) relocation + r_addend;
1571d2201f2fSdrahn
1572d2201f2fSdrahn switch (howto->type)
1573d2201f2fSdrahn {
1574d2201f2fSdrahn /* All these are PC-relative. */
1575*cf2f2c56Smiod case R_MMIX_PUSHJ_STUBBABLE:
1576d2201f2fSdrahn case R_MMIX_PUSHJ:
1577d2201f2fSdrahn case R_MMIX_CBRANCH:
1578d2201f2fSdrahn case R_MMIX_ADDR19:
1579d2201f2fSdrahn case R_MMIX_GETA:
1580d2201f2fSdrahn case R_MMIX_ADDR27:
1581d2201f2fSdrahn case R_MMIX_JMP:
1582d2201f2fSdrahn contents += r_offset;
1583d2201f2fSdrahn
1584d2201f2fSdrahn srel -= (input_section->output_section->vma
1585d2201f2fSdrahn + input_section->output_offset
1586d2201f2fSdrahn + r_offset);
1587d2201f2fSdrahn
1588d2201f2fSdrahn r = mmix_elf_perform_relocation (input_section, howto, contents,
1589d2201f2fSdrahn addr, srel);
1590d2201f2fSdrahn break;
1591d2201f2fSdrahn
1592d2201f2fSdrahn case R_MMIX_BASE_PLUS_OFFSET:
1593d2201f2fSdrahn if (symsec == NULL)
1594d2201f2fSdrahn return bfd_reloc_undefined;
1595d2201f2fSdrahn
1596d2201f2fSdrahn /* Check that we're not relocating against a register symbol. */
1597d2201f2fSdrahn if (strcmp (bfd_get_section_name (symsec->owner, symsec),
1598d2201f2fSdrahn MMIX_REG_CONTENTS_SECTION_NAME) == 0
1599d2201f2fSdrahn || strcmp (bfd_get_section_name (symsec->owner, symsec),
1600d2201f2fSdrahn MMIX_REG_SECTION_NAME) == 0)
1601d2201f2fSdrahn {
1602d2201f2fSdrahn /* Note: This is separated out into two messages in order
1603d2201f2fSdrahn to ease the translation into other languages. */
1604d2201f2fSdrahn if (symname == NULL || *symname == 0)
1605d2201f2fSdrahn (*_bfd_error_handler)
1606d2201f2fSdrahn (_("%s: base-plus-offset relocation against register symbol: (unknown) in %s"),
1607d2201f2fSdrahn bfd_get_filename (input_section->owner),
1608d2201f2fSdrahn bfd_get_section_name (symsec->owner, symsec));
1609d2201f2fSdrahn else
1610d2201f2fSdrahn (*_bfd_error_handler)
1611d2201f2fSdrahn (_("%s: base-plus-offset relocation against register symbol: %s in %s"),
1612d2201f2fSdrahn bfd_get_filename (input_section->owner), symname,
1613d2201f2fSdrahn bfd_get_section_name (symsec->owner, symsec));
1614d2201f2fSdrahn return bfd_reloc_overflow;
1615d2201f2fSdrahn }
1616d2201f2fSdrahn goto do_mmix_reloc;
1617d2201f2fSdrahn
1618d2201f2fSdrahn case R_MMIX_REG_OR_BYTE:
1619d2201f2fSdrahn case R_MMIX_REG:
1620d2201f2fSdrahn /* For now, we handle these alike. They must refer to an register
1621d2201f2fSdrahn symbol, which is either relative to the register section and in
1622d2201f2fSdrahn the range 0..255, or is in the register contents section with vma
1623d2201f2fSdrahn regno * 8. */
1624d2201f2fSdrahn
1625d2201f2fSdrahn /* FIXME: A better way to check for reg contents section?
1626d2201f2fSdrahn FIXME: Postpone section->scaling to mmix_elf_perform_relocation? */
1627d2201f2fSdrahn if (symsec == NULL)
1628d2201f2fSdrahn return bfd_reloc_undefined;
1629d2201f2fSdrahn
1630d2201f2fSdrahn if (strcmp (bfd_get_section_name (symsec->owner, symsec),
1631d2201f2fSdrahn MMIX_REG_CONTENTS_SECTION_NAME) == 0)
1632d2201f2fSdrahn {
1633d2201f2fSdrahn if ((srel & 7) != 0 || srel < 32*8 || srel > 255*8)
1634d2201f2fSdrahn {
1635d2201f2fSdrahn /* The bfd_reloc_outofrange return value, though intuitively
1636d2201f2fSdrahn a better value, will not get us an error. */
1637d2201f2fSdrahn return bfd_reloc_overflow;
1638d2201f2fSdrahn }
1639d2201f2fSdrahn srel /= 8;
1640d2201f2fSdrahn }
1641d2201f2fSdrahn else if (strcmp (bfd_get_section_name (symsec->owner, symsec),
1642d2201f2fSdrahn MMIX_REG_SECTION_NAME) == 0)
1643d2201f2fSdrahn {
1644d2201f2fSdrahn if (srel < 0 || srel > 255)
1645d2201f2fSdrahn /* The bfd_reloc_outofrange return value, though intuitively a
1646d2201f2fSdrahn better value, will not get us an error. */
1647d2201f2fSdrahn return bfd_reloc_overflow;
1648d2201f2fSdrahn }
1649d2201f2fSdrahn else
1650d2201f2fSdrahn {
1651d2201f2fSdrahn /* Note: This is separated out into two messages in order
1652d2201f2fSdrahn to ease the translation into other languages. */
1653d2201f2fSdrahn if (symname == NULL || *symname == 0)
1654d2201f2fSdrahn (*_bfd_error_handler)
1655d2201f2fSdrahn (_("%s: register relocation against non-register symbol: (unknown) in %s"),
1656d2201f2fSdrahn bfd_get_filename (input_section->owner),
1657d2201f2fSdrahn bfd_get_section_name (symsec->owner, symsec));
1658d2201f2fSdrahn else
1659d2201f2fSdrahn (*_bfd_error_handler)
1660d2201f2fSdrahn (_("%s: register relocation against non-register symbol: %s in %s"),
1661d2201f2fSdrahn bfd_get_filename (input_section->owner), symname,
1662d2201f2fSdrahn bfd_get_section_name (symsec->owner, symsec));
1663d2201f2fSdrahn
1664d2201f2fSdrahn /* The bfd_reloc_outofrange return value, though intuitively a
1665d2201f2fSdrahn better value, will not get us an error. */
1666d2201f2fSdrahn return bfd_reloc_overflow;
1667d2201f2fSdrahn }
1668d2201f2fSdrahn do_mmix_reloc:
1669d2201f2fSdrahn contents += r_offset;
1670d2201f2fSdrahn r = mmix_elf_perform_relocation (input_section, howto, contents,
1671d2201f2fSdrahn addr, srel);
1672d2201f2fSdrahn break;
1673d2201f2fSdrahn
1674d2201f2fSdrahn case R_MMIX_LOCAL:
1675d2201f2fSdrahn /* This isn't a real relocation, it's just an assertion that the
1676d2201f2fSdrahn final relocation value corresponds to a local register. We
1677d2201f2fSdrahn ignore the actual relocation; nothing is changed. */
1678d2201f2fSdrahn {
1679d2201f2fSdrahn asection *regsec
1680d2201f2fSdrahn = bfd_get_section_by_name (input_section->output_section->owner,
1681d2201f2fSdrahn MMIX_REG_CONTENTS_SECTION_NAME);
1682d2201f2fSdrahn bfd_vma first_global;
1683d2201f2fSdrahn
1684d2201f2fSdrahn /* Check that this is an absolute value, or a reference to the
1685d2201f2fSdrahn register contents section or the register (symbol) section.
1686d2201f2fSdrahn Absolute numbers can get here as undefined section. Undefined
1687d2201f2fSdrahn symbols are signalled elsewhere, so there's no conflict in us
1688d2201f2fSdrahn accidentally handling it. */
1689d2201f2fSdrahn if (!bfd_is_abs_section (symsec)
1690d2201f2fSdrahn && !bfd_is_und_section (symsec)
1691d2201f2fSdrahn && strcmp (bfd_get_section_name (symsec->owner, symsec),
1692d2201f2fSdrahn MMIX_REG_CONTENTS_SECTION_NAME) != 0
1693d2201f2fSdrahn && strcmp (bfd_get_section_name (symsec->owner, symsec),
1694d2201f2fSdrahn MMIX_REG_SECTION_NAME) != 0)
1695d2201f2fSdrahn {
1696d2201f2fSdrahn (*_bfd_error_handler)
1697d2201f2fSdrahn (_("%s: directive LOCAL valid only with a register or absolute value"),
1698d2201f2fSdrahn bfd_get_filename (input_section->owner));
1699d2201f2fSdrahn
1700d2201f2fSdrahn return bfd_reloc_overflow;
1701d2201f2fSdrahn }
1702d2201f2fSdrahn
1703d2201f2fSdrahn /* If we don't have a register contents section, then $255 is the
1704d2201f2fSdrahn first global register. */
1705d2201f2fSdrahn if (regsec == NULL)
1706d2201f2fSdrahn first_global = 255;
1707d2201f2fSdrahn else
1708d2201f2fSdrahn {
1709d2201f2fSdrahn first_global = bfd_get_section_vma (abfd, regsec) / 8;
1710d2201f2fSdrahn if (strcmp (bfd_get_section_name (symsec->owner, symsec),
1711d2201f2fSdrahn MMIX_REG_CONTENTS_SECTION_NAME) == 0)
1712d2201f2fSdrahn {
1713d2201f2fSdrahn if ((srel & 7) != 0 || srel < 32*8 || srel > 255*8)
1714d2201f2fSdrahn /* The bfd_reloc_outofrange return value, though
1715d2201f2fSdrahn intuitively a better value, will not get us an error. */
1716d2201f2fSdrahn return bfd_reloc_overflow;
1717d2201f2fSdrahn srel /= 8;
1718d2201f2fSdrahn }
1719d2201f2fSdrahn }
1720d2201f2fSdrahn
1721d2201f2fSdrahn if ((bfd_vma) srel >= first_global)
1722d2201f2fSdrahn {
1723d2201f2fSdrahn /* FIXME: Better error message. */
1724d2201f2fSdrahn (*_bfd_error_handler)
1725d2201f2fSdrahn (_("%s: LOCAL directive: Register $%ld is not a local register. First global register is $%ld."),
1726d2201f2fSdrahn bfd_get_filename (input_section->owner), (long) srel, (long) first_global);
1727d2201f2fSdrahn
1728d2201f2fSdrahn return bfd_reloc_overflow;
1729d2201f2fSdrahn }
1730d2201f2fSdrahn }
1731d2201f2fSdrahn r = bfd_reloc_ok;
1732d2201f2fSdrahn break;
1733d2201f2fSdrahn
1734d2201f2fSdrahn default:
1735d2201f2fSdrahn r = _bfd_final_link_relocate (howto, input_section->owner, input_section,
1736d2201f2fSdrahn contents, r_offset,
1737d2201f2fSdrahn relocation, r_addend);
1738d2201f2fSdrahn }
1739d2201f2fSdrahn
1740d2201f2fSdrahn return r;
1741d2201f2fSdrahn }
1742d2201f2fSdrahn
1743d2201f2fSdrahn /* Return the section that should be marked against GC for a given
1744d2201f2fSdrahn relocation. */
1745d2201f2fSdrahn
1746d2201f2fSdrahn static asection *
mmix_elf_gc_mark_hook(sec,info,rel,h,sym)1747d2201f2fSdrahn mmix_elf_gc_mark_hook (sec, info, rel, h, sym)
1748d2201f2fSdrahn asection *sec;
1749d2201f2fSdrahn struct bfd_link_info *info ATTRIBUTE_UNUSED;
1750d2201f2fSdrahn Elf_Internal_Rela *rel;
1751d2201f2fSdrahn struct elf_link_hash_entry *h;
1752d2201f2fSdrahn Elf_Internal_Sym *sym;
1753d2201f2fSdrahn {
1754d2201f2fSdrahn if (h != NULL)
1755d2201f2fSdrahn {
1756d2201f2fSdrahn switch (ELF64_R_TYPE (rel->r_info))
1757d2201f2fSdrahn {
1758d2201f2fSdrahn case R_MMIX_GNU_VTINHERIT:
1759d2201f2fSdrahn case R_MMIX_GNU_VTENTRY:
1760d2201f2fSdrahn break;
1761d2201f2fSdrahn
1762d2201f2fSdrahn default:
1763d2201f2fSdrahn switch (h->root.type)
1764d2201f2fSdrahn {
1765d2201f2fSdrahn case bfd_link_hash_defined:
1766d2201f2fSdrahn case bfd_link_hash_defweak:
1767d2201f2fSdrahn return h->root.u.def.section;
1768d2201f2fSdrahn
1769d2201f2fSdrahn case bfd_link_hash_common:
1770d2201f2fSdrahn return h->root.u.c.p->section;
1771d2201f2fSdrahn
1772d2201f2fSdrahn default:
1773d2201f2fSdrahn break;
1774d2201f2fSdrahn }
1775d2201f2fSdrahn }
1776d2201f2fSdrahn }
1777d2201f2fSdrahn else
1778d2201f2fSdrahn return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1779d2201f2fSdrahn
1780d2201f2fSdrahn return NULL;
1781d2201f2fSdrahn }
1782d2201f2fSdrahn
1783d2201f2fSdrahn /* Update relocation info for a GC-excluded section. We could supposedly
1784d2201f2fSdrahn perform the allocation after GC, but there's no suitable hook between
1785d2201f2fSdrahn GC (or section merge) and the point when all input sections must be
1786d2201f2fSdrahn present. Better to waste some memory and (perhaps) a little time. */
1787d2201f2fSdrahn
1788d2201f2fSdrahn static bfd_boolean
mmix_elf_gc_sweep_hook(abfd,info,sec,relocs)1789d2201f2fSdrahn mmix_elf_gc_sweep_hook (abfd, info, sec, relocs)
1790d2201f2fSdrahn bfd *abfd ATTRIBUTE_UNUSED;
1791d2201f2fSdrahn struct bfd_link_info *info ATTRIBUTE_UNUSED;
1792d2201f2fSdrahn asection *sec ATTRIBUTE_UNUSED;
1793d2201f2fSdrahn const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
1794d2201f2fSdrahn {
1795d2201f2fSdrahn struct bpo_reloc_section_info *bpodata
1796d2201f2fSdrahn = mmix_elf_section_data (sec)->bpo.reloc;
1797d2201f2fSdrahn asection *allocated_gregs_section;
1798d2201f2fSdrahn
1799d2201f2fSdrahn /* If no bpodata here, we have nothing to do. */
1800d2201f2fSdrahn if (bpodata == NULL)
1801d2201f2fSdrahn return TRUE;
1802d2201f2fSdrahn
1803d2201f2fSdrahn allocated_gregs_section = bpodata->bpo_greg_section;
1804d2201f2fSdrahn
1805d2201f2fSdrahn mmix_elf_section_data (allocated_gregs_section)->bpo.greg->n_bpo_relocs
1806d2201f2fSdrahn -= bpodata->n_bpo_relocs_this_section;
1807d2201f2fSdrahn
1808d2201f2fSdrahn return TRUE;
1809d2201f2fSdrahn }
1810d2201f2fSdrahn
1811d2201f2fSdrahn /* Sort register relocs to come before expanding relocs. */
1812d2201f2fSdrahn
1813d2201f2fSdrahn static int
mmix_elf_sort_relocs(p1,p2)1814d2201f2fSdrahn mmix_elf_sort_relocs (p1, p2)
1815d2201f2fSdrahn const PTR p1;
1816d2201f2fSdrahn const PTR p2;
1817d2201f2fSdrahn {
1818d2201f2fSdrahn const Elf_Internal_Rela *r1 = (const Elf_Internal_Rela *) p1;
1819d2201f2fSdrahn const Elf_Internal_Rela *r2 = (const Elf_Internal_Rela *) p2;
1820d2201f2fSdrahn int r1_is_reg, r2_is_reg;
1821d2201f2fSdrahn
1822d2201f2fSdrahn /* Sort primarily on r_offset & ~3, so relocs are done to consecutive
1823d2201f2fSdrahn insns. */
1824d2201f2fSdrahn if ((r1->r_offset & ~(bfd_vma) 3) > (r2->r_offset & ~(bfd_vma) 3))
1825d2201f2fSdrahn return 1;
1826d2201f2fSdrahn else if ((r1->r_offset & ~(bfd_vma) 3) < (r2->r_offset & ~(bfd_vma) 3))
1827d2201f2fSdrahn return -1;
1828d2201f2fSdrahn
1829d2201f2fSdrahn r1_is_reg
1830d2201f2fSdrahn = (ELF64_R_TYPE (r1->r_info) == R_MMIX_REG_OR_BYTE
1831d2201f2fSdrahn || ELF64_R_TYPE (r1->r_info) == R_MMIX_REG);
1832d2201f2fSdrahn r2_is_reg
1833d2201f2fSdrahn = (ELF64_R_TYPE (r2->r_info) == R_MMIX_REG_OR_BYTE
1834d2201f2fSdrahn || ELF64_R_TYPE (r2->r_info) == R_MMIX_REG);
1835d2201f2fSdrahn if (r1_is_reg != r2_is_reg)
1836d2201f2fSdrahn return r2_is_reg - r1_is_reg;
1837d2201f2fSdrahn
1838d2201f2fSdrahn /* Neither or both are register relocs. Then sort on full offset. */
1839d2201f2fSdrahn if (r1->r_offset > r2->r_offset)
1840d2201f2fSdrahn return 1;
1841d2201f2fSdrahn else if (r1->r_offset < r2->r_offset)
1842d2201f2fSdrahn return -1;
1843d2201f2fSdrahn return 0;
1844d2201f2fSdrahn }
1845d2201f2fSdrahn
1846d2201f2fSdrahn /* Subset of mmix_elf_check_relocs, common to ELF and mmo linking. */
1847d2201f2fSdrahn
1848d2201f2fSdrahn static bfd_boolean
mmix_elf_check_common_relocs(abfd,info,sec,relocs)1849d2201f2fSdrahn mmix_elf_check_common_relocs (abfd, info, sec, relocs)
1850d2201f2fSdrahn bfd *abfd;
1851d2201f2fSdrahn struct bfd_link_info *info;
1852d2201f2fSdrahn asection *sec;
1853d2201f2fSdrahn const Elf_Internal_Rela *relocs;
1854d2201f2fSdrahn {
1855d2201f2fSdrahn bfd *bpo_greg_owner = NULL;
1856d2201f2fSdrahn asection *allocated_gregs_section = NULL;
1857d2201f2fSdrahn struct bpo_greg_section_info *gregdata = NULL;
1858d2201f2fSdrahn struct bpo_reloc_section_info *bpodata = NULL;
1859d2201f2fSdrahn const Elf_Internal_Rela *rel;
1860d2201f2fSdrahn const Elf_Internal_Rela *rel_end;
1861d2201f2fSdrahn
1862d2201f2fSdrahn /* We currently have to abuse this COFF-specific member, since there's
1863d2201f2fSdrahn no target-machine-dedicated member. There's no alternative outside
1864d2201f2fSdrahn the bfd_link_info struct; we can't specialize a hash-table since
1865d2201f2fSdrahn they're different between ELF and mmo. */
1866d2201f2fSdrahn bpo_greg_owner = (bfd *) info->base_file;
1867d2201f2fSdrahn
1868d2201f2fSdrahn rel_end = relocs + sec->reloc_count;
1869d2201f2fSdrahn for (rel = relocs; rel < rel_end; rel++)
1870d2201f2fSdrahn {
1871d2201f2fSdrahn switch (ELF64_R_TYPE (rel->r_info))
1872d2201f2fSdrahn {
1873d2201f2fSdrahn /* This relocation causes a GREG allocation. We need to count
1874d2201f2fSdrahn them, and we need to create a section for them, so we need an
1875d2201f2fSdrahn object to fake as the owner of that section. We can't use
1876d2201f2fSdrahn the ELF dynobj for this, since the ELF bits assume lots of
1877d2201f2fSdrahn DSO-related stuff if that member is non-NULL. */
1878d2201f2fSdrahn case R_MMIX_BASE_PLUS_OFFSET:
1879*cf2f2c56Smiod /* We don't do anything with this reloc for a relocatable link. */
1880*cf2f2c56Smiod if (info->relocatable)
1881*cf2f2c56Smiod break;
1882*cf2f2c56Smiod
1883d2201f2fSdrahn if (bpo_greg_owner == NULL)
1884d2201f2fSdrahn {
1885d2201f2fSdrahn bpo_greg_owner = abfd;
1886d2201f2fSdrahn info->base_file = (PTR) bpo_greg_owner;
1887d2201f2fSdrahn }
1888d2201f2fSdrahn
1889d2201f2fSdrahn if (allocated_gregs_section == NULL)
1890d2201f2fSdrahn allocated_gregs_section
1891d2201f2fSdrahn = bfd_get_section_by_name (bpo_greg_owner,
1892d2201f2fSdrahn MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
1893d2201f2fSdrahn
1894d2201f2fSdrahn if (allocated_gregs_section == NULL)
1895d2201f2fSdrahn {
1896d2201f2fSdrahn allocated_gregs_section
1897d2201f2fSdrahn = bfd_make_section (bpo_greg_owner,
1898d2201f2fSdrahn MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
1899d2201f2fSdrahn /* Setting both SEC_ALLOC and SEC_LOAD means the section is
1900d2201f2fSdrahn treated like any other section, and we'd get errors for
1901d2201f2fSdrahn address overlap with the text section. Let's set none of
1902d2201f2fSdrahn those flags, as that is what currently happens for usual
1903d2201f2fSdrahn GREG allocations, and that works. */
1904d2201f2fSdrahn if (allocated_gregs_section == NULL
1905d2201f2fSdrahn || !bfd_set_section_flags (bpo_greg_owner,
1906d2201f2fSdrahn allocated_gregs_section,
1907d2201f2fSdrahn (SEC_HAS_CONTENTS
1908d2201f2fSdrahn | SEC_IN_MEMORY
1909d2201f2fSdrahn | SEC_LINKER_CREATED))
1910d2201f2fSdrahn || !bfd_set_section_alignment (bpo_greg_owner,
1911d2201f2fSdrahn allocated_gregs_section,
1912d2201f2fSdrahn 3))
1913d2201f2fSdrahn return FALSE;
1914d2201f2fSdrahn
1915d2201f2fSdrahn gregdata = (struct bpo_greg_section_info *)
1916d2201f2fSdrahn bfd_zalloc (bpo_greg_owner, sizeof (struct bpo_greg_section_info));
1917d2201f2fSdrahn if (gregdata == NULL)
1918d2201f2fSdrahn return FALSE;
1919d2201f2fSdrahn mmix_elf_section_data (allocated_gregs_section)->bpo.greg
1920d2201f2fSdrahn = gregdata;
1921d2201f2fSdrahn }
1922d2201f2fSdrahn else if (gregdata == NULL)
1923d2201f2fSdrahn gregdata
1924d2201f2fSdrahn = mmix_elf_section_data (allocated_gregs_section)->bpo.greg;
1925d2201f2fSdrahn
1926d2201f2fSdrahn /* Get ourselves some auxiliary info for the BPO-relocs. */
1927d2201f2fSdrahn if (bpodata == NULL)
1928d2201f2fSdrahn {
1929d2201f2fSdrahn /* No use doing a separate iteration pass to find the upper
1930d2201f2fSdrahn limit - just use the number of relocs. */
1931d2201f2fSdrahn bpodata = (struct bpo_reloc_section_info *)
1932d2201f2fSdrahn bfd_alloc (bpo_greg_owner,
1933d2201f2fSdrahn sizeof (struct bpo_reloc_section_info)
1934d2201f2fSdrahn * (sec->reloc_count + 1));
1935d2201f2fSdrahn if (bpodata == NULL)
1936d2201f2fSdrahn return FALSE;
1937d2201f2fSdrahn mmix_elf_section_data (sec)->bpo.reloc = bpodata;
1938d2201f2fSdrahn bpodata->first_base_plus_offset_reloc
1939d2201f2fSdrahn = bpodata->bpo_index
1940d2201f2fSdrahn = gregdata->n_max_bpo_relocs;
1941d2201f2fSdrahn bpodata->bpo_greg_section
1942d2201f2fSdrahn = allocated_gregs_section;
1943d2201f2fSdrahn bpodata->n_bpo_relocs_this_section = 0;
1944d2201f2fSdrahn }
1945d2201f2fSdrahn
1946d2201f2fSdrahn bpodata->n_bpo_relocs_this_section++;
1947d2201f2fSdrahn gregdata->n_max_bpo_relocs++;
1948d2201f2fSdrahn
1949d2201f2fSdrahn /* We don't get another chance to set this before GC; we've not
1950*cf2f2c56Smiod set up any hook that runs before GC. */
1951d2201f2fSdrahn gregdata->n_bpo_relocs
1952d2201f2fSdrahn = gregdata->n_max_bpo_relocs;
1953d2201f2fSdrahn break;
1954*cf2f2c56Smiod
1955*cf2f2c56Smiod case R_MMIX_PUSHJ_STUBBABLE:
1956*cf2f2c56Smiod mmix_elf_section_data (sec)->pjs.n_pushj_relocs++;
1957*cf2f2c56Smiod break;
1958d2201f2fSdrahn }
1959d2201f2fSdrahn }
1960d2201f2fSdrahn
1961*cf2f2c56Smiod /* Allocate per-reloc stub storage and initialize it to the max stub
1962*cf2f2c56Smiod size. */
1963*cf2f2c56Smiod if (mmix_elf_section_data (sec)->pjs.n_pushj_relocs != 0)
1964*cf2f2c56Smiod {
1965*cf2f2c56Smiod size_t i;
1966*cf2f2c56Smiod
1967*cf2f2c56Smiod mmix_elf_section_data (sec)->pjs.stub_size
1968*cf2f2c56Smiod = bfd_alloc (abfd, mmix_elf_section_data (sec)->pjs.n_pushj_relocs
1969*cf2f2c56Smiod * sizeof (mmix_elf_section_data (sec)
1970*cf2f2c56Smiod ->pjs.stub_size[0]));
1971*cf2f2c56Smiod if (mmix_elf_section_data (sec)->pjs.stub_size == NULL)
1972*cf2f2c56Smiod return FALSE;
1973*cf2f2c56Smiod
1974*cf2f2c56Smiod for (i = 0; i < mmix_elf_section_data (sec)->pjs.n_pushj_relocs; i++)
1975*cf2f2c56Smiod mmix_elf_section_data (sec)->pjs.stub_size[i] = MAX_PUSHJ_STUB_SIZE;
1976*cf2f2c56Smiod }
1977*cf2f2c56Smiod
1978d2201f2fSdrahn return TRUE;
1979d2201f2fSdrahn }
1980d2201f2fSdrahn
1981d2201f2fSdrahn /* Look through the relocs for a section during the first phase. */
1982d2201f2fSdrahn
1983d2201f2fSdrahn static bfd_boolean
mmix_elf_check_relocs(abfd,info,sec,relocs)1984d2201f2fSdrahn mmix_elf_check_relocs (abfd, info, sec, relocs)
1985d2201f2fSdrahn bfd *abfd;
1986d2201f2fSdrahn struct bfd_link_info *info;
1987d2201f2fSdrahn asection *sec;
1988d2201f2fSdrahn const Elf_Internal_Rela *relocs;
1989d2201f2fSdrahn {
1990d2201f2fSdrahn Elf_Internal_Shdr *symtab_hdr;
1991d2201f2fSdrahn struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
1992d2201f2fSdrahn const Elf_Internal_Rela *rel;
1993d2201f2fSdrahn const Elf_Internal_Rela *rel_end;
1994d2201f2fSdrahn
1995d2201f2fSdrahn symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1996d2201f2fSdrahn sym_hashes = elf_sym_hashes (abfd);
1997d2201f2fSdrahn sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf64_External_Sym);
1998d2201f2fSdrahn if (!elf_bad_symtab (abfd))
1999d2201f2fSdrahn sym_hashes_end -= symtab_hdr->sh_info;
2000d2201f2fSdrahn
2001d2201f2fSdrahn /* First we sort the relocs so that any register relocs come before
2002d2201f2fSdrahn expansion-relocs to the same insn. FIXME: Not done for mmo. */
2003d2201f2fSdrahn qsort ((PTR) relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
2004d2201f2fSdrahn mmix_elf_sort_relocs);
2005d2201f2fSdrahn
2006d2201f2fSdrahn /* Do the common part. */
2007d2201f2fSdrahn if (!mmix_elf_check_common_relocs (abfd, info, sec, relocs))
2008d2201f2fSdrahn return FALSE;
2009d2201f2fSdrahn
2010*cf2f2c56Smiod if (info->relocatable)
2011*cf2f2c56Smiod return TRUE;
2012*cf2f2c56Smiod
2013d2201f2fSdrahn rel_end = relocs + sec->reloc_count;
2014d2201f2fSdrahn for (rel = relocs; rel < rel_end; rel++)
2015d2201f2fSdrahn {
2016d2201f2fSdrahn struct elf_link_hash_entry *h;
2017d2201f2fSdrahn unsigned long r_symndx;
2018d2201f2fSdrahn
2019d2201f2fSdrahn r_symndx = ELF64_R_SYM (rel->r_info);
2020d2201f2fSdrahn if (r_symndx < symtab_hdr->sh_info)
2021d2201f2fSdrahn h = NULL;
2022d2201f2fSdrahn else
2023d2201f2fSdrahn h = sym_hashes[r_symndx - symtab_hdr->sh_info];
2024d2201f2fSdrahn
2025d2201f2fSdrahn switch (ELF64_R_TYPE (rel->r_info))
2026d2201f2fSdrahn {
2027d2201f2fSdrahn /* This relocation describes the C++ object vtable hierarchy.
2028d2201f2fSdrahn Reconstruct it for later use during GC. */
2029d2201f2fSdrahn case R_MMIX_GNU_VTINHERIT:
2030*cf2f2c56Smiod if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
2031d2201f2fSdrahn return FALSE;
2032d2201f2fSdrahn break;
2033d2201f2fSdrahn
2034d2201f2fSdrahn /* This relocation describes which C++ vtable entries are actually
2035d2201f2fSdrahn used. Record for later use during GC. */
2036d2201f2fSdrahn case R_MMIX_GNU_VTENTRY:
2037*cf2f2c56Smiod if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
2038d2201f2fSdrahn return FALSE;
2039d2201f2fSdrahn break;
2040d2201f2fSdrahn }
2041d2201f2fSdrahn }
2042d2201f2fSdrahn
2043d2201f2fSdrahn return TRUE;
2044d2201f2fSdrahn }
2045d2201f2fSdrahn
2046d2201f2fSdrahn /* Wrapper for mmix_elf_check_common_relocs, called when linking to mmo.
2047d2201f2fSdrahn Copied from elf_link_add_object_symbols. */
2048d2201f2fSdrahn
2049d2201f2fSdrahn bfd_boolean
_bfd_mmix_check_all_relocs(abfd,info)2050d2201f2fSdrahn _bfd_mmix_check_all_relocs (abfd, info)
2051d2201f2fSdrahn bfd *abfd;
2052d2201f2fSdrahn struct bfd_link_info *info;
2053d2201f2fSdrahn {
2054d2201f2fSdrahn asection *o;
2055d2201f2fSdrahn
2056d2201f2fSdrahn for (o = abfd->sections; o != NULL; o = o->next)
2057d2201f2fSdrahn {
2058d2201f2fSdrahn Elf_Internal_Rela *internal_relocs;
2059d2201f2fSdrahn bfd_boolean ok;
2060d2201f2fSdrahn
2061d2201f2fSdrahn if ((o->flags & SEC_RELOC) == 0
2062d2201f2fSdrahn || o->reloc_count == 0
2063d2201f2fSdrahn || ((info->strip == strip_all || info->strip == strip_debugger)
2064d2201f2fSdrahn && (o->flags & SEC_DEBUGGING) != 0)
2065d2201f2fSdrahn || bfd_is_abs_section (o->output_section))
2066d2201f2fSdrahn continue;
2067d2201f2fSdrahn
2068d2201f2fSdrahn internal_relocs
2069*cf2f2c56Smiod = _bfd_elf_link_read_relocs (abfd, o, (PTR) NULL,
2070d2201f2fSdrahn (Elf_Internal_Rela *) NULL,
2071d2201f2fSdrahn info->keep_memory);
2072d2201f2fSdrahn if (internal_relocs == NULL)
2073d2201f2fSdrahn return FALSE;
2074d2201f2fSdrahn
2075d2201f2fSdrahn ok = mmix_elf_check_common_relocs (abfd, info, o, internal_relocs);
2076d2201f2fSdrahn
2077d2201f2fSdrahn if (! info->keep_memory)
2078d2201f2fSdrahn free (internal_relocs);
2079d2201f2fSdrahn
2080d2201f2fSdrahn if (! ok)
2081d2201f2fSdrahn return FALSE;
2082d2201f2fSdrahn }
2083d2201f2fSdrahn
2084d2201f2fSdrahn return TRUE;
2085d2201f2fSdrahn }
2086d2201f2fSdrahn
2087d2201f2fSdrahn /* Change symbols relative to the reg contents section to instead be to
2088d2201f2fSdrahn the register section, and scale them down to correspond to the register
2089d2201f2fSdrahn number. */
2090d2201f2fSdrahn
2091d2201f2fSdrahn static bfd_boolean
mmix_elf_link_output_symbol_hook(info,name,sym,input_sec,h)2092*cf2f2c56Smiod mmix_elf_link_output_symbol_hook (info, name, sym, input_sec, h)
2093d2201f2fSdrahn struct bfd_link_info *info ATTRIBUTE_UNUSED;
2094d2201f2fSdrahn const char *name ATTRIBUTE_UNUSED;
2095d2201f2fSdrahn Elf_Internal_Sym *sym;
2096d2201f2fSdrahn asection *input_sec;
2097*cf2f2c56Smiod struct elf_link_hash_entry *h ATTRIBUTE_UNUSED;
2098d2201f2fSdrahn {
2099d2201f2fSdrahn if (input_sec != NULL
2100d2201f2fSdrahn && input_sec->name != NULL
2101d2201f2fSdrahn && ELF_ST_TYPE (sym->st_info) != STT_SECTION
2102d2201f2fSdrahn && strcmp (input_sec->name, MMIX_REG_CONTENTS_SECTION_NAME) == 0)
2103d2201f2fSdrahn {
2104d2201f2fSdrahn sym->st_value /= 8;
2105d2201f2fSdrahn sym->st_shndx = SHN_REGISTER;
2106d2201f2fSdrahn }
2107d2201f2fSdrahn
2108d2201f2fSdrahn return TRUE;
2109d2201f2fSdrahn }
2110d2201f2fSdrahn
2111d2201f2fSdrahn /* We fake a register section that holds values that are register numbers.
2112d2201f2fSdrahn Having a SHN_REGISTER and register section translates better to other
2113d2201f2fSdrahn formats (e.g. mmo) than for example a STT_REGISTER attribute.
2114d2201f2fSdrahn This section faking is based on a construct in elf32-mips.c. */
2115d2201f2fSdrahn static asection mmix_elf_reg_section;
2116d2201f2fSdrahn static asymbol mmix_elf_reg_section_symbol;
2117d2201f2fSdrahn static asymbol *mmix_elf_reg_section_symbol_ptr;
2118d2201f2fSdrahn
2119*cf2f2c56Smiod /* Handle the special section numbers that a symbol may use. */
2120d2201f2fSdrahn
2121d2201f2fSdrahn void
mmix_elf_symbol_processing(abfd,asym)2122d2201f2fSdrahn mmix_elf_symbol_processing (abfd, asym)
2123d2201f2fSdrahn bfd *abfd ATTRIBUTE_UNUSED;
2124d2201f2fSdrahn asymbol *asym;
2125d2201f2fSdrahn {
2126d2201f2fSdrahn elf_symbol_type *elfsym;
2127d2201f2fSdrahn
2128d2201f2fSdrahn elfsym = (elf_symbol_type *) asym;
2129d2201f2fSdrahn switch (elfsym->internal_elf_sym.st_shndx)
2130d2201f2fSdrahn {
2131d2201f2fSdrahn case SHN_REGISTER:
2132d2201f2fSdrahn if (mmix_elf_reg_section.name == NULL)
2133d2201f2fSdrahn {
2134d2201f2fSdrahn /* Initialize the register section. */
2135d2201f2fSdrahn mmix_elf_reg_section.name = MMIX_REG_SECTION_NAME;
2136d2201f2fSdrahn mmix_elf_reg_section.flags = SEC_NO_FLAGS;
2137d2201f2fSdrahn mmix_elf_reg_section.output_section = &mmix_elf_reg_section;
2138d2201f2fSdrahn mmix_elf_reg_section.symbol = &mmix_elf_reg_section_symbol;
2139d2201f2fSdrahn mmix_elf_reg_section.symbol_ptr_ptr = &mmix_elf_reg_section_symbol_ptr;
2140d2201f2fSdrahn mmix_elf_reg_section_symbol.name = MMIX_REG_SECTION_NAME;
2141d2201f2fSdrahn mmix_elf_reg_section_symbol.flags = BSF_SECTION_SYM;
2142d2201f2fSdrahn mmix_elf_reg_section_symbol.section = &mmix_elf_reg_section;
2143d2201f2fSdrahn mmix_elf_reg_section_symbol_ptr = &mmix_elf_reg_section_symbol;
2144d2201f2fSdrahn }
2145d2201f2fSdrahn asym->section = &mmix_elf_reg_section;
2146d2201f2fSdrahn break;
2147d2201f2fSdrahn
2148d2201f2fSdrahn default:
2149d2201f2fSdrahn break;
2150d2201f2fSdrahn }
2151d2201f2fSdrahn }
2152d2201f2fSdrahn
2153d2201f2fSdrahn /* Given a BFD section, try to locate the corresponding ELF section
2154d2201f2fSdrahn index. */
2155d2201f2fSdrahn
2156d2201f2fSdrahn static bfd_boolean
mmix_elf_section_from_bfd_section(abfd,sec,retval)2157d2201f2fSdrahn mmix_elf_section_from_bfd_section (abfd, sec, retval)
2158d2201f2fSdrahn bfd * abfd ATTRIBUTE_UNUSED;
2159d2201f2fSdrahn asection * sec;
2160d2201f2fSdrahn int * retval;
2161d2201f2fSdrahn {
2162d2201f2fSdrahn if (strcmp (bfd_get_section_name (abfd, sec), MMIX_REG_SECTION_NAME) == 0)
2163d2201f2fSdrahn *retval = SHN_REGISTER;
2164d2201f2fSdrahn else
2165d2201f2fSdrahn return FALSE;
2166d2201f2fSdrahn
2167d2201f2fSdrahn return TRUE;
2168d2201f2fSdrahn }
2169d2201f2fSdrahn
2170d2201f2fSdrahn /* Hook called by the linker routine which adds symbols from an object
2171d2201f2fSdrahn file. We must handle the special SHN_REGISTER section number here.
2172d2201f2fSdrahn
2173d2201f2fSdrahn We also check that we only have *one* each of the section-start
2174d2201f2fSdrahn symbols, since otherwise having two with the same value would cause
2175d2201f2fSdrahn them to be "merged", but with the contents serialized. */
2176d2201f2fSdrahn
2177d2201f2fSdrahn bfd_boolean
mmix_elf_add_symbol_hook(abfd,info,sym,namep,flagsp,secp,valp)2178d2201f2fSdrahn mmix_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
2179d2201f2fSdrahn bfd *abfd;
2180d2201f2fSdrahn struct bfd_link_info *info ATTRIBUTE_UNUSED;
2181*cf2f2c56Smiod Elf_Internal_Sym *sym;
2182d2201f2fSdrahn const char **namep ATTRIBUTE_UNUSED;
2183d2201f2fSdrahn flagword *flagsp ATTRIBUTE_UNUSED;
2184d2201f2fSdrahn asection **secp;
2185d2201f2fSdrahn bfd_vma *valp ATTRIBUTE_UNUSED;
2186d2201f2fSdrahn {
2187d2201f2fSdrahn if (sym->st_shndx == SHN_REGISTER)
2188d2201f2fSdrahn *secp = bfd_make_section_old_way (abfd, MMIX_REG_SECTION_NAME);
2189d2201f2fSdrahn else if ((*namep)[0] == '_' && (*namep)[1] == '_' && (*namep)[2] == '.'
2190d2201f2fSdrahn && strncmp (*namep, MMIX_LOC_SECTION_START_SYMBOL_PREFIX,
2191d2201f2fSdrahn strlen (MMIX_LOC_SECTION_START_SYMBOL_PREFIX)) == 0)
2192d2201f2fSdrahn {
2193d2201f2fSdrahn /* See if we have another one. */
2194d2201f2fSdrahn struct bfd_link_hash_entry *h = bfd_link_hash_lookup (info->hash,
2195d2201f2fSdrahn *namep,
2196d2201f2fSdrahn FALSE,
2197d2201f2fSdrahn FALSE,
2198d2201f2fSdrahn FALSE);
2199d2201f2fSdrahn
2200d2201f2fSdrahn if (h != NULL && h->type != bfd_link_hash_undefined)
2201d2201f2fSdrahn {
2202d2201f2fSdrahn /* How do we get the asymbol (or really: the filename) from h?
2203d2201f2fSdrahn h->u.def.section->owner is NULL. */
2204d2201f2fSdrahn ((*_bfd_error_handler)
2205d2201f2fSdrahn (_("%s: Error: multiple definition of `%s'; start of %s is set in a earlier linked file\n"),
2206d2201f2fSdrahn bfd_get_filename (abfd), *namep,
2207d2201f2fSdrahn *namep + strlen (MMIX_LOC_SECTION_START_SYMBOL_PREFIX)));
2208d2201f2fSdrahn bfd_set_error (bfd_error_bad_value);
2209d2201f2fSdrahn return FALSE;
2210d2201f2fSdrahn }
2211d2201f2fSdrahn }
2212d2201f2fSdrahn
2213d2201f2fSdrahn return TRUE;
2214d2201f2fSdrahn }
2215d2201f2fSdrahn
2216d2201f2fSdrahn /* We consider symbols matching "L.*:[0-9]+" to be local symbols. */
2217d2201f2fSdrahn
2218d2201f2fSdrahn bfd_boolean
mmix_elf_is_local_label_name(abfd,name)2219d2201f2fSdrahn mmix_elf_is_local_label_name (abfd, name)
2220d2201f2fSdrahn bfd *abfd;
2221d2201f2fSdrahn const char *name;
2222d2201f2fSdrahn {
2223d2201f2fSdrahn const char *colpos;
2224d2201f2fSdrahn int digits;
2225d2201f2fSdrahn
2226d2201f2fSdrahn /* Also include the default local-label definition. */
2227d2201f2fSdrahn if (_bfd_elf_is_local_label_name (abfd, name))
2228d2201f2fSdrahn return TRUE;
2229d2201f2fSdrahn
2230d2201f2fSdrahn if (*name != 'L')
2231d2201f2fSdrahn return FALSE;
2232d2201f2fSdrahn
2233d2201f2fSdrahn /* If there's no ":", or more than one, it's not a local symbol. */
2234d2201f2fSdrahn colpos = strchr (name, ':');
2235d2201f2fSdrahn if (colpos == NULL || strchr (colpos + 1, ':') != NULL)
2236d2201f2fSdrahn return FALSE;
2237d2201f2fSdrahn
2238d2201f2fSdrahn /* Check that there are remaining characters and that they are digits. */
2239d2201f2fSdrahn if (colpos[1] == 0)
2240d2201f2fSdrahn return FALSE;
2241d2201f2fSdrahn
2242d2201f2fSdrahn digits = strspn (colpos + 1, "0123456789");
2243d2201f2fSdrahn return digits != 0 && colpos[1 + digits] == 0;
2244d2201f2fSdrahn }
2245d2201f2fSdrahn
2246d2201f2fSdrahn /* We get rid of the register section here. */
2247d2201f2fSdrahn
2248d2201f2fSdrahn bfd_boolean
mmix_elf_final_link(abfd,info)2249d2201f2fSdrahn mmix_elf_final_link (abfd, info)
2250d2201f2fSdrahn bfd *abfd;
2251d2201f2fSdrahn struct bfd_link_info *info;
2252d2201f2fSdrahn {
2253d2201f2fSdrahn /* We never output a register section, though we create one for
2254d2201f2fSdrahn temporary measures. Check that nobody entered contents into it. */
2255d2201f2fSdrahn asection *reg_section;
2256d2201f2fSdrahn asection **secpp;
2257d2201f2fSdrahn
2258d2201f2fSdrahn reg_section = bfd_get_section_by_name (abfd, MMIX_REG_SECTION_NAME);
2259d2201f2fSdrahn
2260d2201f2fSdrahn if (reg_section != NULL)
2261d2201f2fSdrahn {
2262d2201f2fSdrahn /* FIXME: Pass error state gracefully. */
2263d2201f2fSdrahn if (bfd_get_section_flags (abfd, reg_section) & SEC_HAS_CONTENTS)
2264d2201f2fSdrahn _bfd_abort (__FILE__, __LINE__, _("Register section has contents\n"));
2265d2201f2fSdrahn
2266d2201f2fSdrahn /* Really remove the section. */
2267d2201f2fSdrahn for (secpp = &abfd->sections;
2268d2201f2fSdrahn *secpp != reg_section;
2269d2201f2fSdrahn secpp = &(*secpp)->next)
2270d2201f2fSdrahn ;
2271d2201f2fSdrahn bfd_section_list_remove (abfd, secpp);
2272d2201f2fSdrahn --abfd->section_count;
2273d2201f2fSdrahn }
2274d2201f2fSdrahn
2275*cf2f2c56Smiod if (! bfd_elf_final_link (abfd, info))
2276d2201f2fSdrahn return FALSE;
2277d2201f2fSdrahn
2278d2201f2fSdrahn /* Since this section is marked SEC_LINKER_CREATED, it isn't output by
2279d2201f2fSdrahn the regular linker machinery. We do it here, like other targets with
2280d2201f2fSdrahn special sections. */
2281d2201f2fSdrahn if (info->base_file != NULL)
2282d2201f2fSdrahn {
2283d2201f2fSdrahn asection *greg_section
2284d2201f2fSdrahn = bfd_get_section_by_name ((bfd *) info->base_file,
2285d2201f2fSdrahn MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
2286d2201f2fSdrahn if (!bfd_set_section_contents (abfd,
2287d2201f2fSdrahn greg_section->output_section,
2288d2201f2fSdrahn greg_section->contents,
2289d2201f2fSdrahn (file_ptr) greg_section->output_offset,
2290d2201f2fSdrahn greg_section->_cooked_size))
2291d2201f2fSdrahn return FALSE;
2292d2201f2fSdrahn }
2293d2201f2fSdrahn return TRUE;
2294d2201f2fSdrahn }
2295d2201f2fSdrahn
2296*cf2f2c56Smiod /* We need to include the maximum size of PUSHJ-stubs in the initial
2297*cf2f2c56Smiod section size. This is expected to shrink during linker relaxation.
2298*cf2f2c56Smiod
2299*cf2f2c56Smiod You might think that we should set *only* _cooked_size, but that won't
2300*cf2f2c56Smiod work: section contents allocation will be using _raw_size in mixed
2301*cf2f2c56Smiod format linking and not enough storage will be allocated. FIXME: That's
2302*cf2f2c56Smiod a major bug, including the name bfd_get_section_size_before_reloc; it
2303*cf2f2c56Smiod should be bfd_get_section_size_before_relax. The relaxation functions
2304*cf2f2c56Smiod set _cooked size. Relaxation happens before relocation. All functions
2305*cf2f2c56Smiod *after relaxation* should be using _cooked size. */
2306*cf2f2c56Smiod
2307*cf2f2c56Smiod static void
mmix_set_relaxable_size(abfd,sec,ptr)2308*cf2f2c56Smiod mmix_set_relaxable_size (abfd, sec, ptr)
2309*cf2f2c56Smiod bfd *abfd ATTRIBUTE_UNUSED;
2310*cf2f2c56Smiod asection *sec;
2311*cf2f2c56Smiod void *ptr;
2312*cf2f2c56Smiod {
2313*cf2f2c56Smiod struct bfd_link_info *info = ptr;
2314*cf2f2c56Smiod
2315*cf2f2c56Smiod /* Make sure we only do this for section where we know we want this,
2316*cf2f2c56Smiod otherwise we might end up resetting the size of COMMONs. */
2317*cf2f2c56Smiod if (mmix_elf_section_data (sec)->pjs.n_pushj_relocs == 0)
2318*cf2f2c56Smiod return;
2319*cf2f2c56Smiod
2320*cf2f2c56Smiod sec->_cooked_size
2321*cf2f2c56Smiod = (sec->_raw_size
2322*cf2f2c56Smiod + mmix_elf_section_data (sec)->pjs.n_pushj_relocs
2323*cf2f2c56Smiod * MAX_PUSHJ_STUB_SIZE);
2324*cf2f2c56Smiod sec->_raw_size = sec->_cooked_size;
2325*cf2f2c56Smiod
2326*cf2f2c56Smiod /* For use in relocatable link, we start with a max stubs size. See
2327*cf2f2c56Smiod mmix_elf_relax_section. */
2328*cf2f2c56Smiod if (info->relocatable && sec->output_section)
2329*cf2f2c56Smiod mmix_elf_section_data (sec->output_section)->pjs.stubs_size_sum
2330*cf2f2c56Smiod += (mmix_elf_section_data (sec)->pjs.n_pushj_relocs
2331*cf2f2c56Smiod * MAX_PUSHJ_STUB_SIZE);
2332*cf2f2c56Smiod }
2333*cf2f2c56Smiod
2334d2201f2fSdrahn /* Initialize stuff for the linker-generated GREGs to match
2335d2201f2fSdrahn R_MMIX_BASE_PLUS_OFFSET relocs seen by the linker. */
2336d2201f2fSdrahn
2337d2201f2fSdrahn bfd_boolean
_bfd_mmix_before_linker_allocation(abfd,info)2338*cf2f2c56Smiod _bfd_mmix_before_linker_allocation (abfd, info)
2339d2201f2fSdrahn bfd *abfd ATTRIBUTE_UNUSED;
2340d2201f2fSdrahn struct bfd_link_info *info;
2341d2201f2fSdrahn {
2342d2201f2fSdrahn asection *bpo_gregs_section;
2343d2201f2fSdrahn bfd *bpo_greg_owner;
2344d2201f2fSdrahn struct bpo_greg_section_info *gregdata;
2345d2201f2fSdrahn size_t n_gregs;
2346d2201f2fSdrahn bfd_vma gregs_size;
2347d2201f2fSdrahn size_t i;
2348d2201f2fSdrahn size_t *bpo_reloc_indexes;
2349*cf2f2c56Smiod bfd *ibfd;
2350*cf2f2c56Smiod
2351*cf2f2c56Smiod /* Set the initial size of sections. */
2352*cf2f2c56Smiod for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
2353*cf2f2c56Smiod bfd_map_over_sections (ibfd, mmix_set_relaxable_size, info);
2354d2201f2fSdrahn
2355d2201f2fSdrahn /* The bpo_greg_owner bfd is supposed to have been set by
2356d2201f2fSdrahn mmix_elf_check_relocs when the first R_MMIX_BASE_PLUS_OFFSET is seen.
2357d2201f2fSdrahn If there is no such object, there was no R_MMIX_BASE_PLUS_OFFSET. */
2358d2201f2fSdrahn bpo_greg_owner = (bfd *) info->base_file;
2359d2201f2fSdrahn if (bpo_greg_owner == NULL)
2360d2201f2fSdrahn return TRUE;
2361d2201f2fSdrahn
2362d2201f2fSdrahn bpo_gregs_section
2363d2201f2fSdrahn = bfd_get_section_by_name (bpo_greg_owner,
2364d2201f2fSdrahn MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
2365d2201f2fSdrahn
2366d2201f2fSdrahn if (bpo_gregs_section == NULL)
2367d2201f2fSdrahn return TRUE;
2368d2201f2fSdrahn
2369d2201f2fSdrahn /* We use the target-data handle in the ELF section data. */
2370d2201f2fSdrahn gregdata = mmix_elf_section_data (bpo_gregs_section)->bpo.greg;
2371d2201f2fSdrahn if (gregdata == NULL)
2372d2201f2fSdrahn return FALSE;
2373d2201f2fSdrahn
2374d2201f2fSdrahn n_gregs = gregdata->n_bpo_relocs;
2375d2201f2fSdrahn gregdata->n_allocated_bpo_gregs = n_gregs;
2376d2201f2fSdrahn
2377d2201f2fSdrahn /* When this reaches zero during relaxation, all entries have been
2378d2201f2fSdrahn filled in and the size of the linker gregs can be calculated. */
2379d2201f2fSdrahn gregdata->n_remaining_bpo_relocs_this_relaxation_round = n_gregs;
2380d2201f2fSdrahn
2381d2201f2fSdrahn /* Set the zeroth-order estimate for the GREGs size. */
2382d2201f2fSdrahn gregs_size = n_gregs * 8;
2383d2201f2fSdrahn
2384d2201f2fSdrahn if (!bfd_set_section_size (bpo_greg_owner, bpo_gregs_section, gregs_size))
2385d2201f2fSdrahn return FALSE;
2386d2201f2fSdrahn
2387d2201f2fSdrahn /* Allocate and set up the GREG arrays. They're filled in at relaxation
2388d2201f2fSdrahn time. Note that we must use the max number ever noted for the array,
2389d2201f2fSdrahn since the index numbers were created before GC. */
2390d2201f2fSdrahn gregdata->reloc_request
2391d2201f2fSdrahn = bfd_zalloc (bpo_greg_owner,
2392d2201f2fSdrahn sizeof (struct bpo_reloc_request)
2393d2201f2fSdrahn * gregdata->n_max_bpo_relocs);
2394d2201f2fSdrahn
2395d2201f2fSdrahn gregdata->bpo_reloc_indexes
2396d2201f2fSdrahn = bpo_reloc_indexes
2397d2201f2fSdrahn = bfd_alloc (bpo_greg_owner,
2398d2201f2fSdrahn gregdata->n_max_bpo_relocs
2399d2201f2fSdrahn * sizeof (size_t));
2400d2201f2fSdrahn if (bpo_reloc_indexes == NULL)
2401d2201f2fSdrahn return FALSE;
2402d2201f2fSdrahn
2403d2201f2fSdrahn /* The default order is an identity mapping. */
2404d2201f2fSdrahn for (i = 0; i < gregdata->n_max_bpo_relocs; i++)
2405d2201f2fSdrahn {
2406d2201f2fSdrahn bpo_reloc_indexes[i] = i;
2407d2201f2fSdrahn gregdata->reloc_request[i].bpo_reloc_no = i;
2408d2201f2fSdrahn }
2409d2201f2fSdrahn
2410d2201f2fSdrahn return TRUE;
2411d2201f2fSdrahn }
2412d2201f2fSdrahn
2413d2201f2fSdrahn /* Fill in contents in the linker allocated gregs. Everything is
2414d2201f2fSdrahn calculated at this point; we just move the contents into place here. */
2415d2201f2fSdrahn
2416d2201f2fSdrahn bfd_boolean
_bfd_mmix_after_linker_allocation(abfd,link_info)2417*cf2f2c56Smiod _bfd_mmix_after_linker_allocation (abfd, link_info)
2418d2201f2fSdrahn bfd *abfd ATTRIBUTE_UNUSED;
2419d2201f2fSdrahn struct bfd_link_info *link_info;
2420d2201f2fSdrahn {
2421d2201f2fSdrahn asection *bpo_gregs_section;
2422d2201f2fSdrahn bfd *bpo_greg_owner;
2423d2201f2fSdrahn struct bpo_greg_section_info *gregdata;
2424d2201f2fSdrahn size_t n_gregs;
2425d2201f2fSdrahn size_t i, j;
2426d2201f2fSdrahn size_t lastreg;
2427d2201f2fSdrahn bfd_byte *contents;
2428d2201f2fSdrahn
2429d2201f2fSdrahn /* The bpo_greg_owner bfd is supposed to have been set by mmix_elf_check_relocs
2430d2201f2fSdrahn when the first R_MMIX_BASE_PLUS_OFFSET is seen. If there is no such
2431d2201f2fSdrahn object, there was no R_MMIX_BASE_PLUS_OFFSET. */
2432d2201f2fSdrahn bpo_greg_owner = (bfd *) link_info->base_file;
2433d2201f2fSdrahn if (bpo_greg_owner == NULL)
2434d2201f2fSdrahn return TRUE;
2435d2201f2fSdrahn
2436d2201f2fSdrahn bpo_gregs_section
2437d2201f2fSdrahn = bfd_get_section_by_name (bpo_greg_owner,
2438d2201f2fSdrahn MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
2439d2201f2fSdrahn
2440d2201f2fSdrahn /* This can't happen without DSO handling. When DSOs are handled
2441d2201f2fSdrahn without any R_MMIX_BASE_PLUS_OFFSET seen, there will be no such
2442d2201f2fSdrahn section. */
2443d2201f2fSdrahn if (bpo_gregs_section == NULL)
2444d2201f2fSdrahn return TRUE;
2445d2201f2fSdrahn
2446d2201f2fSdrahn /* We use the target-data handle in the ELF section data. */
2447d2201f2fSdrahn
2448d2201f2fSdrahn gregdata = mmix_elf_section_data (bpo_gregs_section)->bpo.greg;
2449d2201f2fSdrahn if (gregdata == NULL)
2450d2201f2fSdrahn return FALSE;
2451d2201f2fSdrahn
2452d2201f2fSdrahn n_gregs = gregdata->n_allocated_bpo_gregs;
2453d2201f2fSdrahn
2454d2201f2fSdrahn /* We need to have a _raw_size contents even though there's only
2455d2201f2fSdrahn _cooked_size worth of data, since the generic relocation machinery
2456d2201f2fSdrahn will allocate and copy that much temporarily. */
2457d2201f2fSdrahn bpo_gregs_section->contents
2458d2201f2fSdrahn = contents = bfd_alloc (bpo_greg_owner, bpo_gregs_section->_raw_size);
2459d2201f2fSdrahn if (contents == NULL)
2460d2201f2fSdrahn return FALSE;
2461d2201f2fSdrahn
2462d2201f2fSdrahn /* Sanity check: If these numbers mismatch, some relocation has not been
2463d2201f2fSdrahn accounted for and the rest of gregdata is probably inconsistent.
2464d2201f2fSdrahn It's a bug, but it's more helpful to identify it than segfaulting
2465d2201f2fSdrahn below. */
2466d2201f2fSdrahn if (gregdata->n_remaining_bpo_relocs_this_relaxation_round
2467d2201f2fSdrahn != gregdata->n_bpo_relocs)
2468d2201f2fSdrahn {
2469d2201f2fSdrahn (*_bfd_error_handler)
2470d2201f2fSdrahn (_("Internal inconsistency: remaining %u != max %u.\n\
2471d2201f2fSdrahn Please report this bug."),
2472d2201f2fSdrahn gregdata->n_remaining_bpo_relocs_this_relaxation_round,
2473d2201f2fSdrahn gregdata->n_bpo_relocs);
2474d2201f2fSdrahn return FALSE;
2475d2201f2fSdrahn }
2476d2201f2fSdrahn
2477d2201f2fSdrahn for (lastreg = 255, i = 0, j = 0; j < n_gregs; i++)
2478d2201f2fSdrahn if (gregdata->reloc_request[i].regindex != lastreg)
2479d2201f2fSdrahn {
2480d2201f2fSdrahn bfd_put_64 (bpo_greg_owner, gregdata->reloc_request[i].value,
2481d2201f2fSdrahn contents + j * 8);
2482d2201f2fSdrahn lastreg = gregdata->reloc_request[i].regindex;
2483d2201f2fSdrahn j++;
2484d2201f2fSdrahn }
2485d2201f2fSdrahn
2486d2201f2fSdrahn return TRUE;
2487d2201f2fSdrahn }
2488d2201f2fSdrahn
2489d2201f2fSdrahn /* Sort valid relocs to come before non-valid relocs, then on increasing
2490d2201f2fSdrahn value. */
2491d2201f2fSdrahn
2492d2201f2fSdrahn static int
bpo_reloc_request_sort_fn(p1,p2)2493d2201f2fSdrahn bpo_reloc_request_sort_fn (p1, p2)
2494d2201f2fSdrahn const PTR p1;
2495d2201f2fSdrahn const PTR p2;
2496d2201f2fSdrahn {
2497d2201f2fSdrahn const struct bpo_reloc_request *r1 = (const struct bpo_reloc_request *) p1;
2498d2201f2fSdrahn const struct bpo_reloc_request *r2 = (const struct bpo_reloc_request *) p2;
2499d2201f2fSdrahn
2500d2201f2fSdrahn /* Primary function is validity; non-valid relocs sorted after valid
2501d2201f2fSdrahn ones. */
2502d2201f2fSdrahn if (r1->valid != r2->valid)
2503d2201f2fSdrahn return r2->valid - r1->valid;
2504d2201f2fSdrahn
2505d2201f2fSdrahn /* Then sort on value. Don't simplify and return just the difference of
2506d2201f2fSdrahn the values: the upper bits of the 64-bit value would be truncated on
2507d2201f2fSdrahn a host with 32-bit ints. */
2508d2201f2fSdrahn if (r1->value != r2->value)
2509d2201f2fSdrahn return r1->value > r2->value ? 1 : -1;
2510d2201f2fSdrahn
2511d2201f2fSdrahn /* As a last re-sort, use the relocation number, so we get a stable
2512d2201f2fSdrahn sort. The *addresses* aren't stable since items are swapped during
2513d2201f2fSdrahn sorting. It depends on the qsort implementation if this actually
2514d2201f2fSdrahn happens. */
2515d2201f2fSdrahn return r1->bpo_reloc_no > r2->bpo_reloc_no
2516d2201f2fSdrahn ? 1 : (r1->bpo_reloc_no < r2->bpo_reloc_no ? -1 : 0);
2517d2201f2fSdrahn }
2518d2201f2fSdrahn
2519d2201f2fSdrahn /* For debug use only. Dumps the global register allocations resulting
2520d2201f2fSdrahn from base-plus-offset relocs. */
2521d2201f2fSdrahn
2522d2201f2fSdrahn void
mmix_dump_bpo_gregs(link_info,pf)2523d2201f2fSdrahn mmix_dump_bpo_gregs (link_info, pf)
2524d2201f2fSdrahn struct bfd_link_info *link_info;
2525d2201f2fSdrahn bfd_error_handler_type pf;
2526d2201f2fSdrahn {
2527d2201f2fSdrahn bfd *bpo_greg_owner;
2528d2201f2fSdrahn asection *bpo_gregs_section;
2529d2201f2fSdrahn struct bpo_greg_section_info *gregdata;
2530d2201f2fSdrahn unsigned int i;
2531d2201f2fSdrahn
2532d2201f2fSdrahn if (link_info == NULL || link_info->base_file == NULL)
2533d2201f2fSdrahn return;
2534d2201f2fSdrahn
2535d2201f2fSdrahn bpo_greg_owner = (bfd *) link_info->base_file;
2536d2201f2fSdrahn
2537d2201f2fSdrahn bpo_gregs_section
2538d2201f2fSdrahn = bfd_get_section_by_name (bpo_greg_owner,
2539d2201f2fSdrahn MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
2540d2201f2fSdrahn
2541d2201f2fSdrahn if (bpo_gregs_section == NULL)
2542d2201f2fSdrahn return;
2543d2201f2fSdrahn
2544d2201f2fSdrahn gregdata = mmix_elf_section_data (bpo_gregs_section)->bpo.greg;
2545d2201f2fSdrahn if (gregdata == NULL)
2546d2201f2fSdrahn return;
2547d2201f2fSdrahn
2548d2201f2fSdrahn if (pf == NULL)
2549d2201f2fSdrahn pf = _bfd_error_handler;
2550d2201f2fSdrahn
2551d2201f2fSdrahn /* These format strings are not translated. They are for debug purposes
2552d2201f2fSdrahn only and never displayed to an end user. Should they escape, we
2553d2201f2fSdrahn surely want them in original. */
2554d2201f2fSdrahn (*pf) (" n_bpo_relocs: %u\n n_max_bpo_relocs: %u\n n_remain...round: %u\n\
2555d2201f2fSdrahn n_allocated_bpo_gregs: %u\n", gregdata->n_bpo_relocs,
2556d2201f2fSdrahn gregdata->n_max_bpo_relocs,
2557d2201f2fSdrahn gregdata->n_remaining_bpo_relocs_this_relaxation_round,
2558d2201f2fSdrahn gregdata->n_allocated_bpo_gregs);
2559d2201f2fSdrahn
2560d2201f2fSdrahn if (gregdata->reloc_request)
2561d2201f2fSdrahn for (i = 0; i < gregdata->n_max_bpo_relocs; i++)
2562d2201f2fSdrahn (*pf) ("%4u (%4u)/%4u#%u: 0x%08lx%08lx r: %3u o: %3u\n",
2563d2201f2fSdrahn i,
2564d2201f2fSdrahn (gregdata->bpo_reloc_indexes != NULL
2565d2201f2fSdrahn ? gregdata->bpo_reloc_indexes[i] : (size_t) -1),
2566d2201f2fSdrahn gregdata->reloc_request[i].bpo_reloc_no,
2567d2201f2fSdrahn gregdata->reloc_request[i].valid,
2568d2201f2fSdrahn
2569d2201f2fSdrahn (unsigned long) (gregdata->reloc_request[i].value >> 32),
2570d2201f2fSdrahn (unsigned long) gregdata->reloc_request[i].value,
2571d2201f2fSdrahn gregdata->reloc_request[i].regindex,
2572d2201f2fSdrahn gregdata->reloc_request[i].offset);
2573d2201f2fSdrahn }
2574d2201f2fSdrahn
2575d2201f2fSdrahn /* This links all R_MMIX_BASE_PLUS_OFFSET relocs into a special array, and
2576d2201f2fSdrahn when the last such reloc is done, an index-array is sorted according to
2577d2201f2fSdrahn the values and iterated over to produce register numbers (indexed by 0
2578d2201f2fSdrahn from the first allocated register number) and offsets for use in real
2579d2201f2fSdrahn relocation.
2580d2201f2fSdrahn
2581*cf2f2c56Smiod PUSHJ stub accounting is also done here.
2582*cf2f2c56Smiod
2583d2201f2fSdrahn Symbol- and reloc-reading infrastructure copied from elf-m10200.c. */
2584d2201f2fSdrahn
2585d2201f2fSdrahn static bfd_boolean
mmix_elf_relax_section(abfd,sec,link_info,again)2586d2201f2fSdrahn mmix_elf_relax_section (abfd, sec, link_info, again)
2587d2201f2fSdrahn bfd *abfd;
2588d2201f2fSdrahn asection *sec;
2589d2201f2fSdrahn struct bfd_link_info *link_info;
2590d2201f2fSdrahn bfd_boolean *again;
2591d2201f2fSdrahn {
2592d2201f2fSdrahn Elf_Internal_Shdr *symtab_hdr;
2593d2201f2fSdrahn Elf_Internal_Rela *internal_relocs;
2594d2201f2fSdrahn Elf_Internal_Rela *irel, *irelend;
2595d2201f2fSdrahn asection *bpo_gregs_section = NULL;
2596d2201f2fSdrahn struct bpo_greg_section_info *gregdata;
2597d2201f2fSdrahn struct bpo_reloc_section_info *bpodata
2598d2201f2fSdrahn = mmix_elf_section_data (sec)->bpo.reloc;
2599*cf2f2c56Smiod /* The initialization is to quiet compiler warnings. The value is to
2600*cf2f2c56Smiod spot a missing actual initialization. */
2601*cf2f2c56Smiod size_t bpono = (size_t) -1;
2602*cf2f2c56Smiod size_t pjsno = 0;
2603d2201f2fSdrahn bfd *bpo_greg_owner;
2604d2201f2fSdrahn Elf_Internal_Sym *isymbuf = NULL;
2605*cf2f2c56Smiod bfd_size_type raw_size
2606*cf2f2c56Smiod = (sec->_raw_size
2607*cf2f2c56Smiod - mmix_elf_section_data (sec)->pjs.n_pushj_relocs
2608*cf2f2c56Smiod * MAX_PUSHJ_STUB_SIZE);
2609*cf2f2c56Smiod
2610*cf2f2c56Smiod mmix_elf_section_data (sec)->pjs.stubs_size_sum = 0;
2611d2201f2fSdrahn
2612d2201f2fSdrahn /* Assume nothing changes. */
2613d2201f2fSdrahn *again = FALSE;
2614d2201f2fSdrahn
2615d2201f2fSdrahn /* If this is the first time we have been called for this section,
2616d2201f2fSdrahn initialize the cooked size. */
2617*cf2f2c56Smiod if (sec->_cooked_size == 0 && sec->_raw_size != 0)
2618*cf2f2c56Smiod abort ();
2619d2201f2fSdrahn
2620*cf2f2c56Smiod /* We don't have to do anything if this section does not have relocs, or
2621*cf2f2c56Smiod if this is not a code section. */
2622*cf2f2c56Smiod if ((sec->flags & SEC_RELOC) == 0
2623d2201f2fSdrahn || sec->reloc_count == 0
2624d2201f2fSdrahn || (sec->flags & SEC_CODE) == 0
2625d2201f2fSdrahn || (sec->flags & SEC_LINKER_CREATED) != 0
2626*cf2f2c56Smiod /* If no R_MMIX_BASE_PLUS_OFFSET relocs and no PUSHJ-stub relocs,
2627*cf2f2c56Smiod then nothing to do. */
2628*cf2f2c56Smiod || (bpodata == NULL
2629*cf2f2c56Smiod && mmix_elf_section_data (sec)->pjs.n_pushj_relocs == 0))
2630d2201f2fSdrahn return TRUE;
2631d2201f2fSdrahn
2632d2201f2fSdrahn symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
2633d2201f2fSdrahn
2634d2201f2fSdrahn bpo_greg_owner = (bfd *) link_info->base_file;
2635*cf2f2c56Smiod
2636*cf2f2c56Smiod if (bpodata != NULL)
2637*cf2f2c56Smiod {
2638d2201f2fSdrahn bpo_gregs_section = bpodata->bpo_greg_section;
2639d2201f2fSdrahn gregdata = mmix_elf_section_data (bpo_gregs_section)->bpo.greg;
2640d2201f2fSdrahn bpono = bpodata->first_base_plus_offset_reloc;
2641*cf2f2c56Smiod }
2642*cf2f2c56Smiod else
2643*cf2f2c56Smiod gregdata = NULL;
2644d2201f2fSdrahn
2645d2201f2fSdrahn /* Get a copy of the native relocations. */
2646d2201f2fSdrahn internal_relocs
2647*cf2f2c56Smiod = _bfd_elf_link_read_relocs (abfd, sec, (PTR) NULL,
2648d2201f2fSdrahn (Elf_Internal_Rela *) NULL,
2649d2201f2fSdrahn link_info->keep_memory);
2650d2201f2fSdrahn if (internal_relocs == NULL)
2651d2201f2fSdrahn goto error_return;
2652d2201f2fSdrahn
2653d2201f2fSdrahn /* Walk through them looking for relaxing opportunities. */
2654d2201f2fSdrahn irelend = internal_relocs + sec->reloc_count;
2655d2201f2fSdrahn for (irel = internal_relocs; irel < irelend; irel++)
2656d2201f2fSdrahn {
2657d2201f2fSdrahn bfd_vma symval;
2658*cf2f2c56Smiod struct elf_link_hash_entry *h = NULL;
2659d2201f2fSdrahn
2660*cf2f2c56Smiod /* We only process two relocs. */
2661*cf2f2c56Smiod if (ELF64_R_TYPE (irel->r_info) != (int) R_MMIX_BASE_PLUS_OFFSET
2662*cf2f2c56Smiod && ELF64_R_TYPE (irel->r_info) != (int) R_MMIX_PUSHJ_STUBBABLE)
2663d2201f2fSdrahn continue;
2664d2201f2fSdrahn
2665*cf2f2c56Smiod /* We process relocs in a distinctly different way when this is a
2666*cf2f2c56Smiod relocatable link (for one, we don't look at symbols), so we avoid
2667*cf2f2c56Smiod mixing its code with that for the "normal" relaxation. */
2668*cf2f2c56Smiod if (link_info->relocatable)
2669*cf2f2c56Smiod {
2670*cf2f2c56Smiod /* The only transformation in a relocatable link is to generate
2671*cf2f2c56Smiod a full stub at the location of the stub calculated for the
2672*cf2f2c56Smiod input section, if the relocated stub location, the end of the
2673*cf2f2c56Smiod output section plus earlier stubs, cannot be reached. Thus
2674*cf2f2c56Smiod relocatable linking can only lead to worse code, but it still
2675*cf2f2c56Smiod works. */
2676*cf2f2c56Smiod if (ELF64_R_TYPE (irel->r_info) == R_MMIX_PUSHJ_STUBBABLE)
2677*cf2f2c56Smiod {
2678*cf2f2c56Smiod /* If we can reach the end of the output-section and beyond
2679*cf2f2c56Smiod any current stubs, then we don't need a stub for this
2680*cf2f2c56Smiod reloc. The relaxed order of output stub allocation may
2681*cf2f2c56Smiod not exactly match the straightforward order, so we always
2682*cf2f2c56Smiod assume presence of output stubs, which will allow
2683*cf2f2c56Smiod relaxation only on relocations indifferent to the
2684*cf2f2c56Smiod presence of output stub allocations for other relocations
2685*cf2f2c56Smiod and thus the order of output stub allocation. */
2686*cf2f2c56Smiod if (bfd_check_overflow (complain_overflow_signed,
2687*cf2f2c56Smiod 19,
2688*cf2f2c56Smiod 0,
2689*cf2f2c56Smiod bfd_arch_bits_per_address (abfd),
2690*cf2f2c56Smiod /* Output-stub location. */
2691*cf2f2c56Smiod sec->output_section->_cooked_size
2692*cf2f2c56Smiod + (mmix_elf_section_data (sec
2693*cf2f2c56Smiod ->output_section)
2694*cf2f2c56Smiod ->pjs.stubs_size_sum)
2695*cf2f2c56Smiod /* Location of this PUSHJ reloc. */
2696*cf2f2c56Smiod - (sec->output_offset + irel->r_offset)
2697*cf2f2c56Smiod /* Don't count *this* stub twice. */
2698*cf2f2c56Smiod - (mmix_elf_section_data (sec)
2699*cf2f2c56Smiod ->pjs.stub_size[pjsno]
2700*cf2f2c56Smiod + MAX_PUSHJ_STUB_SIZE))
2701*cf2f2c56Smiod == bfd_reloc_ok)
2702*cf2f2c56Smiod mmix_elf_section_data (sec)->pjs.stub_size[pjsno] = 0;
2703*cf2f2c56Smiod
2704*cf2f2c56Smiod mmix_elf_section_data (sec)->pjs.stubs_size_sum
2705*cf2f2c56Smiod += mmix_elf_section_data (sec)->pjs.stub_size[pjsno];
2706*cf2f2c56Smiod
2707*cf2f2c56Smiod pjsno++;
2708*cf2f2c56Smiod }
2709*cf2f2c56Smiod
2710*cf2f2c56Smiod continue;
2711*cf2f2c56Smiod }
2712*cf2f2c56Smiod
2713d2201f2fSdrahn /* Get the value of the symbol referred to by the reloc. */
2714d2201f2fSdrahn if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
2715d2201f2fSdrahn {
2716d2201f2fSdrahn /* A local symbol. */
2717d2201f2fSdrahn Elf_Internal_Sym *isym;
2718d2201f2fSdrahn asection *sym_sec;
2719d2201f2fSdrahn
2720d2201f2fSdrahn /* Read this BFD's local symbols if we haven't already. */
2721d2201f2fSdrahn if (isymbuf == NULL)
2722d2201f2fSdrahn {
2723d2201f2fSdrahn isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
2724d2201f2fSdrahn if (isymbuf == NULL)
2725d2201f2fSdrahn isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
2726d2201f2fSdrahn symtab_hdr->sh_info, 0,
2727d2201f2fSdrahn NULL, NULL, NULL);
2728d2201f2fSdrahn if (isymbuf == 0)
2729d2201f2fSdrahn goto error_return;
2730d2201f2fSdrahn }
2731d2201f2fSdrahn
2732d2201f2fSdrahn isym = isymbuf + ELF64_R_SYM (irel->r_info);
2733d2201f2fSdrahn if (isym->st_shndx == SHN_UNDEF)
2734d2201f2fSdrahn sym_sec = bfd_und_section_ptr;
2735d2201f2fSdrahn else if (isym->st_shndx == SHN_ABS)
2736d2201f2fSdrahn sym_sec = bfd_abs_section_ptr;
2737d2201f2fSdrahn else if (isym->st_shndx == SHN_COMMON)
2738d2201f2fSdrahn sym_sec = bfd_com_section_ptr;
2739d2201f2fSdrahn else
2740d2201f2fSdrahn sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
2741d2201f2fSdrahn symval = (isym->st_value
2742d2201f2fSdrahn + sym_sec->output_section->vma
2743d2201f2fSdrahn + sym_sec->output_offset);
2744d2201f2fSdrahn }
2745d2201f2fSdrahn else
2746d2201f2fSdrahn {
2747d2201f2fSdrahn unsigned long indx;
2748d2201f2fSdrahn
2749d2201f2fSdrahn /* An external symbol. */
2750d2201f2fSdrahn indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info;
2751d2201f2fSdrahn h = elf_sym_hashes (abfd)[indx];
2752d2201f2fSdrahn BFD_ASSERT (h != NULL);
2753d2201f2fSdrahn if (h->root.type != bfd_link_hash_defined
2754d2201f2fSdrahn && h->root.type != bfd_link_hash_defweak)
2755d2201f2fSdrahn {
2756*cf2f2c56Smiod /* This appears to be a reference to an undefined symbol. Just
2757*cf2f2c56Smiod ignore it--it will be caught by the regular reloc processing.
2758*cf2f2c56Smiod We need to keep BPO reloc accounting consistent, though
2759*cf2f2c56Smiod else we'll abort instead of emitting an error message. */
2760*cf2f2c56Smiod if (ELF64_R_TYPE (irel->r_info) == R_MMIX_BASE_PLUS_OFFSET
2761*cf2f2c56Smiod && gregdata != NULL)
2762*cf2f2c56Smiod {
2763d2201f2fSdrahn gregdata->n_remaining_bpo_relocs_this_relaxation_round--;
2764d2201f2fSdrahn bpono++;
2765*cf2f2c56Smiod }
2766d2201f2fSdrahn continue;
2767d2201f2fSdrahn }
2768d2201f2fSdrahn
2769d2201f2fSdrahn symval = (h->root.u.def.value
2770d2201f2fSdrahn + h->root.u.def.section->output_section->vma
2771d2201f2fSdrahn + h->root.u.def.section->output_offset);
2772d2201f2fSdrahn }
2773d2201f2fSdrahn
2774*cf2f2c56Smiod if (ELF64_R_TYPE (irel->r_info) == (int) R_MMIX_PUSHJ_STUBBABLE)
2775*cf2f2c56Smiod {
2776*cf2f2c56Smiod bfd_vma value = symval + irel->r_addend;
2777*cf2f2c56Smiod bfd_vma dot
2778*cf2f2c56Smiod = (sec->output_section->vma
2779*cf2f2c56Smiod + sec->output_offset
2780*cf2f2c56Smiod + irel->r_offset);
2781*cf2f2c56Smiod bfd_vma stubaddr
2782*cf2f2c56Smiod = (sec->output_section->vma
2783*cf2f2c56Smiod + sec->output_offset
2784*cf2f2c56Smiod + raw_size
2785*cf2f2c56Smiod + mmix_elf_section_data (sec)->pjs.stubs_size_sum);
2786*cf2f2c56Smiod
2787*cf2f2c56Smiod if ((value & 3) == 0
2788*cf2f2c56Smiod && bfd_check_overflow (complain_overflow_signed,
2789*cf2f2c56Smiod 19,
2790*cf2f2c56Smiod 0,
2791*cf2f2c56Smiod bfd_arch_bits_per_address (abfd),
2792*cf2f2c56Smiod value - dot
2793*cf2f2c56Smiod - (value > dot
2794*cf2f2c56Smiod ? mmix_elf_section_data (sec)
2795*cf2f2c56Smiod ->pjs.stub_size[pjsno]
2796*cf2f2c56Smiod : 0))
2797*cf2f2c56Smiod == bfd_reloc_ok)
2798*cf2f2c56Smiod /* If the reloc fits, no stub is needed. */
2799*cf2f2c56Smiod mmix_elf_section_data (sec)->pjs.stub_size[pjsno] = 0;
2800*cf2f2c56Smiod else
2801*cf2f2c56Smiod /* Maybe we can get away with just a JMP insn? */
2802*cf2f2c56Smiod if ((value & 3) == 0
2803*cf2f2c56Smiod && bfd_check_overflow (complain_overflow_signed,
2804*cf2f2c56Smiod 27,
2805*cf2f2c56Smiod 0,
2806*cf2f2c56Smiod bfd_arch_bits_per_address (abfd),
2807*cf2f2c56Smiod value - stubaddr
2808*cf2f2c56Smiod - (value > dot
2809*cf2f2c56Smiod ? mmix_elf_section_data (sec)
2810*cf2f2c56Smiod ->pjs.stub_size[pjsno] - 4
2811*cf2f2c56Smiod : 0))
2812*cf2f2c56Smiod == bfd_reloc_ok)
2813*cf2f2c56Smiod /* Yep, account for a stub consisting of a single JMP insn. */
2814*cf2f2c56Smiod mmix_elf_section_data (sec)->pjs.stub_size[pjsno] = 4;
2815*cf2f2c56Smiod else
2816*cf2f2c56Smiod /* Nope, go for the full insn stub. It doesn't seem useful to
2817*cf2f2c56Smiod emit the intermediate sizes; those will only be useful for
2818*cf2f2c56Smiod a >64M program assuming contiguous code. */
2819*cf2f2c56Smiod mmix_elf_section_data (sec)->pjs.stub_size[pjsno]
2820*cf2f2c56Smiod = MAX_PUSHJ_STUB_SIZE;
2821*cf2f2c56Smiod
2822*cf2f2c56Smiod mmix_elf_section_data (sec)->pjs.stubs_size_sum
2823*cf2f2c56Smiod += mmix_elf_section_data (sec)->pjs.stub_size[pjsno];
2824*cf2f2c56Smiod pjsno++;
2825*cf2f2c56Smiod continue;
2826*cf2f2c56Smiod }
2827*cf2f2c56Smiod
2828*cf2f2c56Smiod /* We're looking at a R_MMIX_BASE_PLUS_OFFSET reloc. */
2829*cf2f2c56Smiod
2830d2201f2fSdrahn gregdata->reloc_request[gregdata->bpo_reloc_indexes[bpono]].value
2831d2201f2fSdrahn = symval + irel->r_addend;
2832d2201f2fSdrahn gregdata->reloc_request[gregdata->bpo_reloc_indexes[bpono++]].valid = TRUE;
2833d2201f2fSdrahn gregdata->n_remaining_bpo_relocs_this_relaxation_round--;
2834d2201f2fSdrahn }
2835d2201f2fSdrahn
2836d2201f2fSdrahn /* Check if that was the last BPO-reloc. If so, sort the values and
2837d2201f2fSdrahn calculate how many registers we need to cover them. Set the size of
2838d2201f2fSdrahn the linker gregs, and if the number of registers changed, indicate
2839d2201f2fSdrahn that we need to relax some more because we have more work to do. */
2840*cf2f2c56Smiod if (gregdata != NULL
2841*cf2f2c56Smiod && gregdata->n_remaining_bpo_relocs_this_relaxation_round == 0)
2842d2201f2fSdrahn {
2843d2201f2fSdrahn size_t i;
2844d2201f2fSdrahn bfd_vma prev_base;
2845d2201f2fSdrahn size_t regindex;
2846d2201f2fSdrahn
2847d2201f2fSdrahn /* First, reset the remaining relocs for the next round. */
2848d2201f2fSdrahn gregdata->n_remaining_bpo_relocs_this_relaxation_round
2849d2201f2fSdrahn = gregdata->n_bpo_relocs;
2850d2201f2fSdrahn
2851d2201f2fSdrahn qsort ((PTR) gregdata->reloc_request,
2852d2201f2fSdrahn gregdata->n_max_bpo_relocs,
2853d2201f2fSdrahn sizeof (struct bpo_reloc_request),
2854d2201f2fSdrahn bpo_reloc_request_sort_fn);
2855d2201f2fSdrahn
2856d2201f2fSdrahn /* Recalculate indexes. When we find a change (however unlikely
2857d2201f2fSdrahn after the initial iteration), we know we need to relax again,
2858d2201f2fSdrahn since items in the GREG-array are sorted by increasing value and
2859d2201f2fSdrahn stored in the relaxation phase. */
2860d2201f2fSdrahn for (i = 0; i < gregdata->n_max_bpo_relocs; i++)
2861d2201f2fSdrahn if (gregdata->bpo_reloc_indexes[gregdata->reloc_request[i].bpo_reloc_no]
2862d2201f2fSdrahn != i)
2863d2201f2fSdrahn {
2864d2201f2fSdrahn gregdata->bpo_reloc_indexes[gregdata->reloc_request[i].bpo_reloc_no]
2865d2201f2fSdrahn = i;
2866d2201f2fSdrahn *again = TRUE;
2867d2201f2fSdrahn }
2868d2201f2fSdrahn
2869d2201f2fSdrahn /* Allocate register numbers (indexing from 0). Stop at the first
2870d2201f2fSdrahn non-valid reloc. */
2871d2201f2fSdrahn for (i = 0, regindex = 0, prev_base = gregdata->reloc_request[0].value;
2872d2201f2fSdrahn i < gregdata->n_bpo_relocs;
2873d2201f2fSdrahn i++)
2874d2201f2fSdrahn {
2875d2201f2fSdrahn if (gregdata->reloc_request[i].value > prev_base + 255)
2876d2201f2fSdrahn {
2877d2201f2fSdrahn regindex++;
2878d2201f2fSdrahn prev_base = gregdata->reloc_request[i].value;
2879d2201f2fSdrahn }
2880d2201f2fSdrahn gregdata->reloc_request[i].regindex = regindex;
2881d2201f2fSdrahn gregdata->reloc_request[i].offset
2882d2201f2fSdrahn = gregdata->reloc_request[i].value - prev_base;
2883d2201f2fSdrahn }
2884d2201f2fSdrahn
2885d2201f2fSdrahn /* If it's not the same as the last time, we need to relax again,
2886d2201f2fSdrahn because the size of the section has changed. I'm not sure we
2887d2201f2fSdrahn actually need to do any adjustments since the shrinking happens
2888d2201f2fSdrahn at the start of this section, but better safe than sorry. */
2889d2201f2fSdrahn if (gregdata->n_allocated_bpo_gregs != regindex + 1)
2890d2201f2fSdrahn {
2891d2201f2fSdrahn gregdata->n_allocated_bpo_gregs = regindex + 1;
2892d2201f2fSdrahn *again = TRUE;
2893d2201f2fSdrahn }
2894d2201f2fSdrahn
2895d2201f2fSdrahn bpo_gregs_section->_cooked_size = (regindex + 1) * 8;
2896d2201f2fSdrahn }
2897d2201f2fSdrahn
2898d2201f2fSdrahn if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents)
2899d2201f2fSdrahn {
2900d2201f2fSdrahn if (! link_info->keep_memory)
2901d2201f2fSdrahn free (isymbuf);
2902d2201f2fSdrahn else
2903d2201f2fSdrahn {
2904d2201f2fSdrahn /* Cache the symbols for elf_link_input_bfd. */
2905d2201f2fSdrahn symtab_hdr->contents = (unsigned char *) isymbuf;
2906d2201f2fSdrahn }
2907d2201f2fSdrahn }
2908d2201f2fSdrahn
2909d2201f2fSdrahn if (internal_relocs != NULL
2910d2201f2fSdrahn && elf_section_data (sec)->relocs != internal_relocs)
2911d2201f2fSdrahn free (internal_relocs);
2912d2201f2fSdrahn
2913*cf2f2c56Smiod if (sec->_cooked_size
2914*cf2f2c56Smiod < raw_size + mmix_elf_section_data (sec)->pjs.stubs_size_sum)
2915*cf2f2c56Smiod abort ();
2916*cf2f2c56Smiod
2917*cf2f2c56Smiod if (sec->_cooked_size
2918*cf2f2c56Smiod > raw_size + mmix_elf_section_data (sec)->pjs.stubs_size_sum)
2919*cf2f2c56Smiod {
2920*cf2f2c56Smiod sec->_cooked_size
2921*cf2f2c56Smiod = raw_size + mmix_elf_section_data (sec)->pjs.stubs_size_sum;
2922*cf2f2c56Smiod *again = TRUE;
2923*cf2f2c56Smiod }
2924*cf2f2c56Smiod
2925d2201f2fSdrahn return TRUE;
2926d2201f2fSdrahn
2927d2201f2fSdrahn error_return:
2928d2201f2fSdrahn if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents)
2929d2201f2fSdrahn free (isymbuf);
2930d2201f2fSdrahn if (internal_relocs != NULL
2931d2201f2fSdrahn && elf_section_data (sec)->relocs != internal_relocs)
2932d2201f2fSdrahn free (internal_relocs);
2933d2201f2fSdrahn return FALSE;
2934d2201f2fSdrahn }
2935*cf2f2c56Smiod
2936*cf2f2c56Smiod /* Because we set _raw_size to include the max size of pushj stubs,
2937*cf2f2c56Smiod i.e. larger than the actual section input size (see
2938*cf2f2c56Smiod mmix_set_relaxable_raw_size), we have to take care of that when reading
2939*cf2f2c56Smiod the section. */
2940*cf2f2c56Smiod
2941*cf2f2c56Smiod static bfd_boolean
mmix_elf_get_section_contents(abfd,section,location,offset,count)2942*cf2f2c56Smiod mmix_elf_get_section_contents (abfd, section, location, offset, count)
2943*cf2f2c56Smiod bfd *abfd;
2944*cf2f2c56Smiod sec_ptr section;
2945*cf2f2c56Smiod void *location;
2946*cf2f2c56Smiod file_ptr offset;
2947*cf2f2c56Smiod bfd_size_type count;
2948*cf2f2c56Smiod {
2949*cf2f2c56Smiod bfd_size_type raw_size
2950*cf2f2c56Smiod = (section->_raw_size
2951*cf2f2c56Smiod - mmix_elf_section_data (section)->pjs.n_pushj_relocs
2952*cf2f2c56Smiod * MAX_PUSHJ_STUB_SIZE);
2953*cf2f2c56Smiod
2954*cf2f2c56Smiod if (offset + count > section->_raw_size)
2955*cf2f2c56Smiod {
2956*cf2f2c56Smiod abort();
2957*cf2f2c56Smiod bfd_set_error (bfd_error_invalid_operation);
2958*cf2f2c56Smiod return FALSE;
2959*cf2f2c56Smiod }
2960*cf2f2c56Smiod
2961*cf2f2c56Smiod /* Check bounds against the faked raw_size. */
2962*cf2f2c56Smiod if (offset + count > raw_size)
2963*cf2f2c56Smiod {
2964*cf2f2c56Smiod /* Clear the part in the faked area. */
2965*cf2f2c56Smiod memset (location + raw_size - offset, 0, count - (raw_size - offset));
2966*cf2f2c56Smiod
2967*cf2f2c56Smiod /* If there's no initial part within the "real" contents, we're
2968*cf2f2c56Smiod done. */
2969*cf2f2c56Smiod if ((bfd_size_type) offset >= raw_size)
2970*cf2f2c56Smiod return TRUE;
2971*cf2f2c56Smiod
2972*cf2f2c56Smiod /* Else adjust the count and fall through to call the generic
2973*cf2f2c56Smiod function. */
2974*cf2f2c56Smiod count = raw_size - offset;
2975*cf2f2c56Smiod }
2976*cf2f2c56Smiod
2977*cf2f2c56Smiod return
2978*cf2f2c56Smiod _bfd_generic_get_section_contents (abfd, section, location, offset,
2979*cf2f2c56Smiod count);
2980*cf2f2c56Smiod }
2981*cf2f2c56Smiod
2982d2201f2fSdrahn
2983d2201f2fSdrahn #define ELF_ARCH bfd_arch_mmix
2984d2201f2fSdrahn #define ELF_MACHINE_CODE EM_MMIX
2985d2201f2fSdrahn
2986d2201f2fSdrahn /* According to mmix-doc page 36 (paragraph 45), this should be (1LL << 48LL).
2987d2201f2fSdrahn However, that's too much for something somewhere in the linker part of
2988d2201f2fSdrahn BFD; perhaps the start-address has to be a non-zero multiple of this
2989d2201f2fSdrahn number, or larger than this number. The symptom is that the linker
2990d2201f2fSdrahn complains: "warning: allocated section `.text' not in segment". We
2991d2201f2fSdrahn settle for 64k; the page-size used in examples is 8k.
2992d2201f2fSdrahn #define ELF_MAXPAGESIZE 0x10000
2993d2201f2fSdrahn
2994d2201f2fSdrahn Unfortunately, this causes excessive padding in the supposedly small
2995d2201f2fSdrahn for-education programs that are the expected usage (where people would
2996d2201f2fSdrahn inspect output). We stick to 256 bytes just to have *some* default
2997d2201f2fSdrahn alignment. */
2998d2201f2fSdrahn #define ELF_MAXPAGESIZE 0x100
2999d2201f2fSdrahn
3000d2201f2fSdrahn #define TARGET_BIG_SYM bfd_elf64_mmix_vec
3001d2201f2fSdrahn #define TARGET_BIG_NAME "elf64-mmix"
3002d2201f2fSdrahn
3003d2201f2fSdrahn #define elf_info_to_howto_rel NULL
3004d2201f2fSdrahn #define elf_info_to_howto mmix_info_to_howto_rela
3005d2201f2fSdrahn #define elf_backend_relocate_section mmix_elf_relocate_section
3006d2201f2fSdrahn #define elf_backend_gc_mark_hook mmix_elf_gc_mark_hook
3007d2201f2fSdrahn #define elf_backend_gc_sweep_hook mmix_elf_gc_sweep_hook
3008d2201f2fSdrahn
3009d2201f2fSdrahn #define elf_backend_link_output_symbol_hook \
3010d2201f2fSdrahn mmix_elf_link_output_symbol_hook
3011d2201f2fSdrahn #define elf_backend_add_symbol_hook mmix_elf_add_symbol_hook
3012d2201f2fSdrahn
3013d2201f2fSdrahn #define elf_backend_check_relocs mmix_elf_check_relocs
3014d2201f2fSdrahn #define elf_backend_symbol_processing mmix_elf_symbol_processing
3015d2201f2fSdrahn
3016d2201f2fSdrahn #define bfd_elf64_bfd_is_local_label_name \
3017d2201f2fSdrahn mmix_elf_is_local_label_name
3018d2201f2fSdrahn
3019d2201f2fSdrahn #define elf_backend_may_use_rel_p 0
3020d2201f2fSdrahn #define elf_backend_may_use_rela_p 1
3021d2201f2fSdrahn #define elf_backend_default_use_rela_p 1
3022d2201f2fSdrahn
3023d2201f2fSdrahn #define elf_backend_can_gc_sections 1
3024d2201f2fSdrahn #define elf_backend_section_from_bfd_section \
3025d2201f2fSdrahn mmix_elf_section_from_bfd_section
3026d2201f2fSdrahn
3027d2201f2fSdrahn #define bfd_elf64_new_section_hook mmix_elf_new_section_hook
3028d2201f2fSdrahn #define bfd_elf64_bfd_final_link mmix_elf_final_link
3029d2201f2fSdrahn #define bfd_elf64_bfd_relax_section mmix_elf_relax_section
3030*cf2f2c56Smiod #define bfd_elf64_get_section_contents mmix_elf_get_section_contents
3031d2201f2fSdrahn
3032d2201f2fSdrahn #include "elf64-target.h"
3033