1 |
/* Motorola 68k series support for 32-bit ELF |
/* Motorola 68k series support for 32-bit ELF |
2 |
Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 |
Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, |
3 |
Free Software Foundation, Inc. |
2004, 2005 Free Software Foundation, Inc. |
4 |
|
|
5 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
6 |
|
|
7 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
8 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
9 |
the Free Software Foundation; either version 2 of the License, or |
the Free Software Foundation; either version 2 of the License, or |
10 |
(at your option) any later version. |
(at your option) any later version. |
11 |
|
|
12 |
This program is distributed in the hope that it will be useful, |
This program is distributed in the hope that it will be useful, |
13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
GNU General Public License for more details. |
GNU General Public License for more details. |
16 |
|
|
17 |
You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
18 |
along with this program; if not, write to the Free Software |
along with this program; if not, write to the Free Software |
19 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
20 |
|
|
21 |
#include "bfd.h" |
#include "bfd.h" |
22 |
#include "sysdep.h" |
#include "sysdep.h" |
28 |
static reloc_howto_type *reloc_type_lookup |
static reloc_howto_type *reloc_type_lookup |
29 |
PARAMS ((bfd *, bfd_reloc_code_real_type)); |
PARAMS ((bfd *, bfd_reloc_code_real_type)); |
30 |
static void rtype_to_howto |
static void rtype_to_howto |
31 |
PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *)); |
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); |
32 |
static struct bfd_hash_entry *elf_m68k_link_hash_newfunc |
static struct bfd_hash_entry *elf_m68k_link_hash_newfunc |
33 |
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); |
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); |
34 |
static struct bfd_link_hash_table *elf_m68k_link_hash_table_create |
static struct bfd_link_hash_table *elf_m68k_link_hash_table_create |
35 |
PARAMS ((bfd *)); |
PARAMS ((bfd *)); |
36 |
static boolean elf_m68k_check_relocs |
static bfd_boolean elf_m68k_check_relocs |
37 |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
38 |
const Elf_Internal_Rela *)); |
const Elf_Internal_Rela *)); |
39 |
static asection *elf_m68k_gc_mark_hook |
static asection *elf_m68k_gc_mark_hook |
40 |
PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, |
PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, |
41 |
struct elf_link_hash_entry *, Elf_Internal_Sym *)); |
struct elf_link_hash_entry *, Elf_Internal_Sym *)); |
42 |
static boolean elf_m68k_gc_sweep_hook |
static bfd_boolean elf_m68k_gc_sweep_hook |
43 |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
44 |
const Elf_Internal_Rela *)); |
const Elf_Internal_Rela *)); |
45 |
static boolean elf_m68k_adjust_dynamic_symbol |
static bfd_boolean elf_m68k_adjust_dynamic_symbol |
46 |
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); |
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); |
47 |
static boolean elf_m68k_size_dynamic_sections |
static bfd_boolean elf_m68k_size_dynamic_sections |
48 |
PARAMS ((bfd *, struct bfd_link_info *)); |
PARAMS ((bfd *, struct bfd_link_info *)); |
49 |
static boolean elf_m68k_relocate_section |
static bfd_boolean elf_m68k_discard_copies |
50 |
|
PARAMS ((struct elf_link_hash_entry *, PTR)); |
51 |
|
static bfd_boolean elf_m68k_relocate_section |
52 |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
53 |
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); |
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); |
54 |
static boolean elf_m68k_finish_dynamic_symbol |
static bfd_boolean elf_m68k_finish_dynamic_symbol |
55 |
PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, |
PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, |
56 |
Elf_Internal_Sym *)); |
Elf_Internal_Sym *)); |
57 |
static boolean elf_m68k_finish_dynamic_sections |
static bfd_boolean elf_m68k_finish_dynamic_sections |
58 |
PARAMS ((bfd *, struct bfd_link_info *)); |
PARAMS ((bfd *, struct bfd_link_info *)); |
59 |
|
|
60 |
static boolean elf32_m68k_set_private_flags |
static bfd_boolean elf32_m68k_set_private_flags |
61 |
PARAMS ((bfd *, flagword)); |
PARAMS ((bfd *, flagword)); |
62 |
static boolean elf32_m68k_merge_private_bfd_data |
static bfd_boolean elf32_m68k_merge_private_bfd_data |
63 |
PARAMS ((bfd *, bfd *)); |
PARAMS ((bfd *, bfd *)); |
64 |
static boolean elf32_m68k_print_private_bfd_data |
static bfd_boolean elf32_m68k_print_private_bfd_data |
65 |
PARAMS ((bfd *, PTR)); |
PARAMS ((bfd *, PTR)); |
66 |
static enum elf_reloc_type_class elf32_m68k_reloc_type_class |
static enum elf_reloc_type_class elf32_m68k_reloc_type_class |
67 |
PARAMS ((const Elf_Internal_Rela *)); |
PARAMS ((const Elf_Internal_Rela *)); |
68 |
|
|
69 |
static reloc_howto_type howto_table[] = { |
static reloc_howto_type howto_table[] = { |
70 |
HOWTO(R_68K_NONE, 0, 0, 0, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_NONE", false, 0, 0x00000000,false), |
HOWTO(R_68K_NONE, 0, 0, 0, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_NONE", FALSE, 0, 0x00000000,FALSE), |
71 |
HOWTO(R_68K_32, 0, 2,32, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_32", false, 0, 0xffffffff,false), |
HOWTO(R_68K_32, 0, 2,32, FALSE,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_32", FALSE, 0, 0xffffffff,FALSE), |
72 |
HOWTO(R_68K_16, 0, 1,16, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_16", false, 0, 0x0000ffff,false), |
HOWTO(R_68K_16, 0, 1,16, FALSE,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_16", FALSE, 0, 0x0000ffff,FALSE), |
73 |
HOWTO(R_68K_8, 0, 0, 8, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_8", false, 0, 0x000000ff,false), |
HOWTO(R_68K_8, 0, 0, 8, FALSE,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_8", FALSE, 0, 0x000000ff,FALSE), |
74 |
HOWTO(R_68K_PC32, 0, 2,32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PC32", false, 0, 0xffffffff,true), |
HOWTO(R_68K_PC32, 0, 2,32, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PC32", FALSE, 0, 0xffffffff,TRUE), |
75 |
HOWTO(R_68K_PC16, 0, 1,16, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PC16", false, 0, 0x0000ffff,true), |
HOWTO(R_68K_PC16, 0, 1,16, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PC16", FALSE, 0, 0x0000ffff,TRUE), |
76 |
HOWTO(R_68K_PC8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PC8", false, 0, 0x000000ff,true), |
HOWTO(R_68K_PC8, 0, 0, 8, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PC8", FALSE, 0, 0x000000ff,TRUE), |
77 |
HOWTO(R_68K_GOT32, 0, 2,32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_GOT32", false, 0, 0xffffffff,true), |
HOWTO(R_68K_GOT32, 0, 2,32, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_GOT32", FALSE, 0, 0xffffffff,TRUE), |
78 |
HOWTO(R_68K_GOT16, 0, 1,16, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT16", false, 0, 0x0000ffff,true), |
HOWTO(R_68K_GOT16, 0, 1,16, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT16", FALSE, 0, 0x0000ffff,TRUE), |
79 |
HOWTO(R_68K_GOT8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT8", false, 0, 0x000000ff,true), |
HOWTO(R_68K_GOT8, 0, 0, 8, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT8", FALSE, 0, 0x000000ff,TRUE), |
80 |
HOWTO(R_68K_GOT32O, 0, 2,32, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_GOT32O", false, 0, 0xffffffff,false), |
HOWTO(R_68K_GOT32O, 0, 2,32, FALSE,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_GOT32O", FALSE, 0, 0xffffffff,FALSE), |
81 |
HOWTO(R_68K_GOT16O, 0, 1,16, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT16O", false, 0, 0x0000ffff,false), |
HOWTO(R_68K_GOT16O, 0, 1,16, FALSE,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT16O", FALSE, 0, 0x0000ffff,FALSE), |
82 |
HOWTO(R_68K_GOT8O, 0, 0, 8, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT8O", false, 0, 0x000000ff,false), |
HOWTO(R_68K_GOT8O, 0, 0, 8, FALSE,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT8O", FALSE, 0, 0x000000ff,FALSE), |
83 |
HOWTO(R_68K_PLT32, 0, 2,32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PLT32", false, 0, 0xffffffff,true), |
HOWTO(R_68K_PLT32, 0, 2,32, TRUE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PLT32", FALSE, 0, 0xffffffff,TRUE), |
84 |
HOWTO(R_68K_PLT16, 0, 1,16, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT16", false, 0, 0x0000ffff,true), |
HOWTO(R_68K_PLT16, 0, 1,16, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT16", FALSE, 0, 0x0000ffff,TRUE), |
85 |
HOWTO(R_68K_PLT8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT8", false, 0, 0x000000ff,true), |
HOWTO(R_68K_PLT8, 0, 0, 8, TRUE, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT8", FALSE, 0, 0x000000ff,TRUE), |
86 |
HOWTO(R_68K_PLT32O, 0, 2,32, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PLT32O", false, 0, 0xffffffff,false), |
HOWTO(R_68K_PLT32O, 0, 2,32, FALSE,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PLT32O", FALSE, 0, 0xffffffff,FALSE), |
87 |
HOWTO(R_68K_PLT16O, 0, 1,16, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT16O", false, 0, 0x0000ffff,false), |
HOWTO(R_68K_PLT16O, 0, 1,16, FALSE,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT16O", FALSE, 0, 0x0000ffff,FALSE), |
88 |
HOWTO(R_68K_PLT8O, 0, 0, 8, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT8O", false, 0, 0x000000ff,false), |
HOWTO(R_68K_PLT8O, 0, 0, 8, FALSE,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT8O", FALSE, 0, 0x000000ff,FALSE), |
89 |
HOWTO(R_68K_COPY, 0, 0, 0, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_COPY", false, 0, 0xffffffff,false), |
HOWTO(R_68K_COPY, 0, 0, 0, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_COPY", FALSE, 0, 0xffffffff,FALSE), |
90 |
HOWTO(R_68K_GLOB_DAT, 0, 2,32, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_GLOB_DAT", false, 0, 0xffffffff,false), |
HOWTO(R_68K_GLOB_DAT, 0, 2,32, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_GLOB_DAT", FALSE, 0, 0xffffffff,FALSE), |
91 |
HOWTO(R_68K_JMP_SLOT, 0, 2,32, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_JMP_SLOT", false, 0, 0xffffffff,false), |
HOWTO(R_68K_JMP_SLOT, 0, 2,32, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_JMP_SLOT", FALSE, 0, 0xffffffff,FALSE), |
92 |
HOWTO(R_68K_RELATIVE, 0, 2,32, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_RELATIVE", false, 0, 0xffffffff,false), |
HOWTO(R_68K_RELATIVE, 0, 2,32, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_RELATIVE", FALSE, 0, 0xffffffff,FALSE), |
93 |
/* GNU extension to record C++ vtable hierarchy */ |
/* GNU extension to record C++ vtable hierarchy. */ |
94 |
HOWTO (R_68K_GNU_VTINHERIT, /* type */ |
HOWTO (R_68K_GNU_VTINHERIT, /* type */ |
95 |
0, /* rightshift */ |
0, /* rightshift */ |
96 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
97 |
0, /* bitsize */ |
0, /* bitsize */ |
98 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
99 |
0, /* bitpos */ |
0, /* bitpos */ |
100 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
101 |
NULL, /* special_function */ |
NULL, /* special_function */ |
102 |
"R_68K_GNU_VTINHERIT", /* name */ |
"R_68K_GNU_VTINHERIT", /* name */ |
103 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
104 |
0, /* src_mask */ |
0, /* src_mask */ |
105 |
0, /* dst_mask */ |
0, /* dst_mask */ |
106 |
false), |
FALSE), |
107 |
/* GNU extension to record C++ vtable member usage */ |
/* GNU extension to record C++ vtable member usage. */ |
108 |
HOWTO (R_68K_GNU_VTENTRY, /* type */ |
HOWTO (R_68K_GNU_VTENTRY, /* type */ |
109 |
0, /* rightshift */ |
0, /* rightshift */ |
110 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
111 |
0, /* bitsize */ |
0, /* bitsize */ |
112 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
113 |
0, /* bitpos */ |
0, /* bitpos */ |
114 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
115 |
_bfd_elf_rel_vtable_reloc_fn, /* special_function */ |
_bfd_elf_rel_vtable_reloc_fn, /* special_function */ |
116 |
"R_68K_GNU_VTENTRY", /* name */ |
"R_68K_GNU_VTENTRY", /* name */ |
117 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
118 |
0, /* src_mask */ |
0, /* src_mask */ |
119 |
0, /* dst_mask */ |
0, /* dst_mask */ |
120 |
false), |
FALSE), |
121 |
}; |
}; |
122 |
|
|
123 |
static void |
static void |
181 |
|
|
182 |
#define bfd_elf32_bfd_reloc_type_lookup reloc_type_lookup |
#define bfd_elf32_bfd_reloc_type_lookup reloc_type_lookup |
183 |
#define ELF_ARCH bfd_arch_m68k |
#define ELF_ARCH bfd_arch_m68k |
|
/* end code generated by elf.el */ |
|
|
|
|
|
#define USE_RELA |
|
184 |
|
|
185 |
/* Functions for the m68k ELF linker. */ |
/* Functions for the m68k ELF linker. */ |
186 |
|
|
273 |
struct elf_m68k_pcrel_relocs_copied *pcrel_relocs_copied; |
struct elf_m68k_pcrel_relocs_copied *pcrel_relocs_copied; |
274 |
}; |
}; |
275 |
|
|
276 |
|
#define elf_m68k_hash_entry(ent) ((struct elf_m68k_link_hash_entry *) (ent)) |
277 |
|
|
278 |
/* m68k ELF linker hash table. */ |
/* m68k ELF linker hash table. */ |
279 |
|
|
280 |
struct elf_m68k_link_hash_table |
struct elf_m68k_link_hash_table |
281 |
{ |
{ |
282 |
struct elf_link_hash_table root; |
struct elf_link_hash_table root; |
|
}; |
|
|
|
|
|
/* Declare this now that the above structures are defined. */ |
|
283 |
|
|
284 |
static boolean elf_m68k_discard_copies |
/* Small local sym to section mapping cache. */ |
285 |
PARAMS ((struct elf_m68k_link_hash_entry *, PTR)); |
struct sym_sec_cache sym_sec; |
286 |
|
}; |
|
/* Traverse an m68k ELF linker hash table. */ |
|
|
|
|
|
#define elf_m68k_link_hash_traverse(table, func, info) \ |
|
|
(elf_link_hash_traverse \ |
|
|
(&(table)->root, \ |
|
|
(boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \ |
|
|
(info))) |
|
287 |
|
|
288 |
/* Get the m68k ELF linker hash table from a link_info structure. */ |
/* Get the m68k ELF linker hash table from a link_info structure. */ |
289 |
|
|
298 |
struct bfd_hash_table *table; |
struct bfd_hash_table *table; |
299 |
const char *string; |
const char *string; |
300 |
{ |
{ |
301 |
struct elf_m68k_link_hash_entry *ret = |
struct bfd_hash_entry *ret = entry; |
|
(struct elf_m68k_link_hash_entry *) entry; |
|
302 |
|
|
303 |
/* Allocate the structure if it has not already been allocated by a |
/* Allocate the structure if it has not already been allocated by a |
304 |
subclass. */ |
subclass. */ |
305 |
if (ret == (struct elf_m68k_link_hash_entry *) NULL) |
if (ret == NULL) |
306 |
ret = ((struct elf_m68k_link_hash_entry *) |
ret = bfd_hash_allocate (table, |
307 |
bfd_hash_allocate (table, |
sizeof (struct elf_m68k_link_hash_entry)); |
308 |
sizeof (struct elf_m68k_link_hash_entry))); |
if (ret == NULL) |
309 |
if (ret == (struct elf_m68k_link_hash_entry *) NULL) |
return ret; |
|
return (struct bfd_hash_entry *) ret; |
|
310 |
|
|
311 |
/* Call the allocation method of the superclass. */ |
/* Call the allocation method of the superclass. */ |
312 |
ret = ((struct elf_m68k_link_hash_entry *) |
ret = _bfd_elf_link_hash_newfunc (ret, table, string); |
313 |
_bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, |
if (ret != NULL) |
314 |
table, string)); |
elf_m68k_hash_entry (ret)->pcrel_relocs_copied = NULL; |
|
if (ret != (struct elf_m68k_link_hash_entry *) NULL) |
|
|
{ |
|
|
ret->pcrel_relocs_copied = NULL; |
|
|
} |
|
315 |
|
|
316 |
return (struct bfd_hash_entry *) ret; |
return ret; |
317 |
} |
} |
318 |
|
|
319 |
/* Create an m68k ELF linker hash table. */ |
/* Create an m68k ELF linker hash table. */ |
336 |
return NULL; |
return NULL; |
337 |
} |
} |
338 |
|
|
339 |
|
ret->sym_sec.abfd = NULL; |
340 |
|
|
341 |
return &ret->root.root; |
return &ret->root.root; |
342 |
} |
} |
343 |
|
|
344 |
/* Keep m68k-specific flags in the ELF header */ |
/* Keep m68k-specific flags in the ELF header. */ |
345 |
static boolean |
static bfd_boolean |
346 |
elf32_m68k_set_private_flags (abfd, flags) |
elf32_m68k_set_private_flags (abfd, flags) |
347 |
bfd *abfd; |
bfd *abfd; |
348 |
flagword flags; |
flagword flags; |
349 |
{ |
{ |
350 |
elf_elfheader (abfd)->e_flags = flags; |
elf_elfheader (abfd)->e_flags = flags; |
351 |
elf_flags_init (abfd) = true; |
elf_flags_init (abfd) = TRUE; |
352 |
return true; |
return TRUE; |
353 |
} |
} |
354 |
|
|
355 |
/* Merge backend specific data from an object file to the output |
/* Merge backend specific data from an object file to the output |
356 |
object file when linking. */ |
object file when linking. */ |
357 |
static boolean |
static bfd_boolean |
358 |
elf32_m68k_merge_private_bfd_data (ibfd, obfd) |
elf32_m68k_merge_private_bfd_data (ibfd, obfd) |
359 |
bfd *ibfd; |
bfd *ibfd; |
360 |
bfd *obfd; |
bfd *obfd; |
364 |
|
|
365 |
if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
366 |
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
367 |
return true; |
return TRUE; |
368 |
|
|
369 |
in_flags = elf_elfheader (ibfd)->e_flags; |
in_flags = elf_elfheader (ibfd)->e_flags; |
370 |
out_flags = elf_elfheader (obfd)->e_flags; |
out_flags = elf_elfheader (obfd)->e_flags; |
371 |
|
|
372 |
if (!elf_flags_init (obfd)) |
if (!elf_flags_init (obfd)) |
373 |
{ |
{ |
374 |
elf_flags_init (obfd) = true; |
elf_flags_init (obfd) = TRUE; |
375 |
elf_elfheader (obfd)->e_flags = in_flags; |
elf_elfheader (obfd)->e_flags = in_flags; |
376 |
} |
} |
377 |
|
|
378 |
return true; |
return TRUE; |
379 |
} |
} |
380 |
|
|
381 |
/* Display the flags field */ |
/* Display the flags field. */ |
382 |
static boolean |
static bfd_boolean |
383 |
elf32_m68k_print_private_bfd_data (abfd, ptr) |
elf32_m68k_print_private_bfd_data (abfd, ptr) |
384 |
bfd *abfd; |
bfd *abfd; |
385 |
PTR ptr; |
PTR ptr; |
404 |
|
|
405 |
fputc ('\n', file); |
fputc ('\n', file); |
406 |
|
|
407 |
return true; |
return TRUE; |
408 |
} |
} |
409 |
/* Look through the relocs for a section during the first phase, and |
/* Look through the relocs for a section during the first phase, and |
410 |
allocate space in the global offset table or procedure linkage |
allocate space in the global offset table or procedure linkage |
411 |
table. */ |
table. */ |
412 |
|
|
413 |
static boolean |
static bfd_boolean |
414 |
elf_m68k_check_relocs (abfd, info, sec, relocs) |
elf_m68k_check_relocs (abfd, info, sec, relocs) |
415 |
bfd *abfd; |
bfd *abfd; |
416 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
427 |
asection *srelgot; |
asection *srelgot; |
428 |
asection *sreloc; |
asection *sreloc; |
429 |
|
|
430 |
if (info->relocateable) |
if (info->relocatable) |
431 |
return true; |
return TRUE; |
432 |
|
|
433 |
dynobj = elf_hash_table (info)->dynobj; |
dynobj = elf_hash_table (info)->dynobj; |
434 |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
471 |
/* Create the .got section. */ |
/* Create the .got section. */ |
472 |
elf_hash_table (info)->dynobj = dynobj = abfd; |
elf_hash_table (info)->dynobj = dynobj = abfd; |
473 |
if (!_bfd_elf_create_got_section (dynobj, info)) |
if (!_bfd_elf_create_got_section (dynobj, info)) |
474 |
return false; |
return FALSE; |
475 |
} |
} |
476 |
|
|
477 |
if (sgot == NULL) |
if (sgot == NULL) |
496 |
| SEC_LINKER_CREATED |
| SEC_LINKER_CREATED |
497 |
| SEC_READONLY)) |
| SEC_READONLY)) |
498 |
|| !bfd_set_section_alignment (dynobj, srelgot, 2)) |
|| !bfd_set_section_alignment (dynobj, srelgot, 2)) |
499 |
return false; |
return FALSE; |
500 |
} |
} |
501 |
} |
} |
502 |
|
|
505 |
if (h->got.refcount == 0) |
if (h->got.refcount == 0) |
506 |
{ |
{ |
507 |
/* Make sure this symbol is output as a dynamic symbol. */ |
/* Make sure this symbol is output as a dynamic symbol. */ |
508 |
if (h->dynindx == -1) |
if (h->dynindx == -1 |
509 |
|
&& !h->forced_local) |
510 |
{ |
{ |
511 |
if (!bfd_elf32_link_record_dynamic_symbol (info, h)) |
if (!bfd_elf_link_record_dynamic_symbol (info, h)) |
512 |
return false; |
return FALSE; |
513 |
} |
} |
514 |
|
|
515 |
/* Allocate space in the .got section. */ |
/* Allocate space in the .got section. */ |
516 |
sgot->_raw_size += 4; |
sgot->size += 4; |
517 |
/* Allocate relocation space. */ |
/* Allocate relocation space. */ |
518 |
srelgot->_raw_size += sizeof (Elf32_External_Rela); |
srelgot->size += sizeof (Elf32_External_Rela); |
519 |
} |
} |
520 |
h->got.refcount++; |
h->got.refcount++; |
521 |
} |
} |
531 |
local_got_refcounts = ((bfd_signed_vma *) |
local_got_refcounts = ((bfd_signed_vma *) |
532 |
bfd_zalloc (abfd, size)); |
bfd_zalloc (abfd, size)); |
533 |
if (local_got_refcounts == NULL) |
if (local_got_refcounts == NULL) |
534 |
return false; |
return FALSE; |
535 |
elf_local_got_refcounts (abfd) = local_got_refcounts; |
elf_local_got_refcounts (abfd) = local_got_refcounts; |
536 |
} |
} |
537 |
if (local_got_refcounts[r_symndx] == 0) |
if (local_got_refcounts[r_symndx] == 0) |
538 |
{ |
{ |
539 |
sgot->_raw_size += 4; |
sgot->size += 4; |
540 |
if (info->shared) |
if (info->shared) |
541 |
{ |
{ |
542 |
/* If we are generating a shared object, we need to |
/* If we are generating a shared object, we need to |
543 |
output a R_68K_RELATIVE reloc so that the dynamic |
output a R_68K_RELATIVE reloc so that the dynamic |
544 |
linker can adjust this GOT entry. */ |
linker can adjust this GOT entry. */ |
545 |
srelgot->_raw_size += sizeof (Elf32_External_Rela); |
srelgot->size += sizeof (Elf32_External_Rela); |
546 |
} |
} |
547 |
} |
} |
548 |
local_got_refcounts[r_symndx]++; |
local_got_refcounts[r_symndx]++; |
564 |
if (h == NULL) |
if (h == NULL) |
565 |
continue; |
continue; |
566 |
|
|
567 |
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; |
h->needs_plt = 1; |
568 |
h->plt.refcount++; |
h->plt.refcount++; |
569 |
break; |
break; |
570 |
|
|
579 |
local symbol. FIXME: does it? How to handle it if |
local symbol. FIXME: does it? How to handle it if |
580 |
it does make sense? */ |
it does make sense? */ |
581 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
582 |
return false; |
return FALSE; |
583 |
} |
} |
584 |
|
|
585 |
/* Make sure this symbol is output as a dynamic symbol. */ |
/* Make sure this symbol is output as a dynamic symbol. */ |
586 |
if (h->dynindx == -1) |
if (h->dynindx == -1 |
587 |
|
&& !h->forced_local) |
588 |
{ |
{ |
589 |
if (!bfd_elf32_link_record_dynamic_symbol (info, h)) |
if (!bfd_elf_link_record_dynamic_symbol (info, h)) |
590 |
return false; |
return FALSE; |
591 |
} |
} |
592 |
|
|
593 |
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; |
h->needs_plt = 1; |
594 |
h->plt.refcount++; |
h->plt.refcount++; |
595 |
break; |
break; |
596 |
|
|
611 |
&& (sec->flags & SEC_ALLOC) != 0 |
&& (sec->flags & SEC_ALLOC) != 0 |
612 |
&& h != NULL |
&& h != NULL |
613 |
&& (!info->symbolic |
&& (!info->symbolic |
614 |
|| (h->elf_link_hash_flags |
|| h->root.type == bfd_link_hash_defweak |
615 |
& ELF_LINK_HASH_DEF_REGULAR) == 0))) |
|| !h->def_regular))) |
616 |
{ |
{ |
617 |
if (h != NULL) |
if (h != NULL) |
618 |
{ |
{ |
651 |
elf_elfheader (abfd)->e_shstrndx, |
elf_elfheader (abfd)->e_shstrndx, |
652 |
elf_section_data (sec)->rel_hdr.sh_name)); |
elf_section_data (sec)->rel_hdr.sh_name)); |
653 |
if (name == NULL) |
if (name == NULL) |
654 |
return false; |
return FALSE; |
655 |
|
|
656 |
BFD_ASSERT (strncmp (name, ".rela", 5) == 0 |
BFD_ASSERT (strncmp (name, ".rela", 5) == 0 |
657 |
&& strcmp (bfd_get_section_name (abfd, sec), |
&& strcmp (bfd_get_section_name (abfd, sec), |
670 |
| SEC_LINKER_CREATED |
| SEC_LINKER_CREATED |
671 |
| SEC_READONLY)) |
| SEC_READONLY)) |
672 |
|| !bfd_set_section_alignment (dynobj, sreloc, 2)) |
|| !bfd_set_section_alignment (dynobj, sreloc, 2)) |
673 |
return false; |
return FALSE; |
674 |
} |
} |
675 |
if (sec->flags & SEC_READONLY) |
elf_section_data (sec)->sreloc = sreloc; |
|
info->flags |= DF_TEXTREL; |
|
676 |
} |
} |
677 |
|
|
678 |
sreloc->_raw_size += sizeof (Elf32_External_Rela); |
if (sec->flags & SEC_READONLY |
679 |
|
/* Don't set DF_TEXTREL yet for PC relative |
680 |
|
relocations, they might be discarded later. */ |
681 |
|
&& !(ELF32_R_TYPE (rel->r_info) == R_68K_PC8 |
682 |
|
|| ELF32_R_TYPE (rel->r_info) == R_68K_PC16 |
683 |
|
|| ELF32_R_TYPE (rel->r_info) == R_68K_PC32)) |
684 |
|
info->flags |= DF_TEXTREL; |
685 |
|
|
686 |
|
sreloc->size += sizeof (Elf32_External_Rela); |
687 |
|
|
688 |
/* If we are linking with -Bsymbolic, we count the number of |
/* We count the number of PC relative relocations we have |
689 |
PC relative relocations we have entered for this symbol, |
entered for this symbol, so that we can discard them |
690 |
so that we can discard them again if the symbol is later |
again if, in the -Bsymbolic case, the symbol is later |
691 |
defined by a regular object. Note that this function is |
defined by a regular object, or, in the normal shared |
692 |
only called if we are using an m68kelf linker hash table, |
case, the symbol is forced to be local. Note that this |
693 |
which means that h is really a pointer to an |
function is only called if we are using an m68kelf linker |
694 |
|
hash table, which means that h is really a pointer to an |
695 |
elf_m68k_link_hash_entry. */ |
elf_m68k_link_hash_entry. */ |
696 |
if ((ELF32_R_TYPE (rel->r_info) == R_68K_PC8 |
if (ELF32_R_TYPE (rel->r_info) == R_68K_PC8 |
697 |
|| ELF32_R_TYPE (rel->r_info) == R_68K_PC16 |
|| ELF32_R_TYPE (rel->r_info) == R_68K_PC16 |
698 |
|| ELF32_R_TYPE (rel->r_info) == R_68K_PC32) |
|| ELF32_R_TYPE (rel->r_info) == R_68K_PC32) |
|
&& info->symbolic) |
|
699 |
{ |
{ |
|
struct elf_m68k_link_hash_entry *eh; |
|
700 |
struct elf_m68k_pcrel_relocs_copied *p; |
struct elf_m68k_pcrel_relocs_copied *p; |
701 |
|
struct elf_m68k_pcrel_relocs_copied **head; |
702 |
|
|
703 |
|
if (h != NULL) |
704 |
|
{ |
705 |
|
struct elf_m68k_link_hash_entry *eh |
706 |
|
= elf_m68k_hash_entry (h); |
707 |
|
head = &eh->pcrel_relocs_copied; |
708 |
|
} |
709 |
|
else |
710 |
|
{ |
711 |
|
asection *s; |
712 |
|
s = (bfd_section_from_r_symndx |
713 |
|
(abfd, &elf_m68k_hash_table (info)->sym_sec, |
714 |
|
sec, r_symndx)); |
715 |
|
if (s == NULL) |
716 |
|
return FALSE; |
717 |
|
|
718 |
eh = (struct elf_m68k_link_hash_entry *) h; |
head = ((struct elf_m68k_pcrel_relocs_copied **) |
719 |
|
&elf_section_data (s)->local_dynrel); |
720 |
|
} |
721 |
|
|
722 |
for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next) |
for (p = *head; p != NULL; p = p->next) |
723 |
if (p->section == sreloc) |
if (p->section == sreloc) |
724 |
break; |
break; |
725 |
|
|
728 |
p = ((struct elf_m68k_pcrel_relocs_copied *) |
p = ((struct elf_m68k_pcrel_relocs_copied *) |
729 |
bfd_alloc (dynobj, (bfd_size_type) sizeof *p)); |
bfd_alloc (dynobj, (bfd_size_type) sizeof *p)); |
730 |
if (p == NULL) |
if (p == NULL) |
731 |
return false; |
return FALSE; |
732 |
p->next = eh->pcrel_relocs_copied; |
p->next = *head; |
733 |
eh->pcrel_relocs_copied = p; |
*head = p; |
734 |
p->section = sreloc; |
p->section = sreloc; |
735 |
p->count = 0; |
p->count = 0; |
736 |
} |
} |
744 |
/* This relocation describes the C++ object vtable hierarchy. |
/* This relocation describes the C++ object vtable hierarchy. |
745 |
Reconstruct it for later use during GC. */ |
Reconstruct it for later use during GC. */ |
746 |
case R_68K_GNU_VTINHERIT: |
case R_68K_GNU_VTINHERIT: |
747 |
if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) |
if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) |
748 |
return false; |
return FALSE; |
749 |
break; |
break; |
750 |
|
|
751 |
/* This relocation describes which C++ vtable entries are actually |
/* This relocation describes which C++ vtable entries are actually |
752 |
used. Record for later use during GC. */ |
used. Record for later use during GC. */ |
753 |
case R_68K_GNU_VTENTRY: |
case R_68K_GNU_VTENTRY: |
754 |
if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) |
if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) |
755 |
return false; |
return FALSE; |
756 |
break; |
break; |
757 |
|
|
758 |
default: |
default: |
760 |
} |
} |
761 |
} |
} |
762 |
|
|
763 |
return true; |
return TRUE; |
764 |
} |
} |
765 |
|
|
766 |
/* Return the section that should be marked against GC for a given |
/* Return the section that should be marked against GC for a given |
805 |
|
|
806 |
/* Update the got entry reference counts for the section being removed. */ |
/* Update the got entry reference counts for the section being removed. */ |
807 |
|
|
808 |
static boolean |
static bfd_boolean |
809 |
elf_m68k_gc_sweep_hook (abfd, info, sec, relocs) |
elf_m68k_gc_sweep_hook (abfd, info, sec, relocs) |
810 |
bfd *abfd; |
bfd *abfd; |
811 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
816 |
struct elf_link_hash_entry **sym_hashes; |
struct elf_link_hash_entry **sym_hashes; |
817 |
bfd_signed_vma *local_got_refcounts; |
bfd_signed_vma *local_got_refcounts; |
818 |
const Elf_Internal_Rela *rel, *relend; |
const Elf_Internal_Rela *rel, *relend; |
|
unsigned long r_symndx; |
|
|
struct elf_link_hash_entry *h; |
|
819 |
bfd *dynobj; |
bfd *dynobj; |
820 |
asection *sgot; |
asection *sgot; |
821 |
asection *srelgot; |
asection *srelgot; |
822 |
|
|
823 |
|
dynobj = elf_hash_table (info)->dynobj; |
824 |
|
if (dynobj == NULL) |
825 |
|
return TRUE; |
826 |
|
|
827 |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
828 |
sym_hashes = elf_sym_hashes (abfd); |
sym_hashes = elf_sym_hashes (abfd); |
829 |
local_got_refcounts = elf_local_got_refcounts (abfd); |
local_got_refcounts = elf_local_got_refcounts (abfd); |
830 |
|
|
|
dynobj = elf_hash_table (info)->dynobj; |
|
|
if (dynobj == NULL) |
|
|
return true; |
|
|
|
|
831 |
sgot = bfd_get_section_by_name (dynobj, ".got"); |
sgot = bfd_get_section_by_name (dynobj, ".got"); |
832 |
srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); |
srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); |
833 |
|
|
834 |
relend = relocs + sec->reloc_count; |
relend = relocs + sec->reloc_count; |
835 |
for (rel = relocs; rel < relend; rel++) |
for (rel = relocs; rel < relend; rel++) |
836 |
{ |
{ |
837 |
|
unsigned long r_symndx; |
838 |
|
struct elf_link_hash_entry *h = NULL; |
839 |
|
|
840 |
|
r_symndx = ELF32_R_SYM (rel->r_info); |
841 |
|
if (r_symndx >= symtab_hdr->sh_info) |
842 |
|
{ |
843 |
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
844 |
|
while (h->root.type == bfd_link_hash_indirect |
845 |
|
|| h->root.type == bfd_link_hash_warning) |
846 |
|
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
847 |
|
} |
848 |
|
|
849 |
switch (ELF32_R_TYPE (rel->r_info)) |
switch (ELF32_R_TYPE (rel->r_info)) |
850 |
{ |
{ |
851 |
case R_68K_GOT8: |
case R_68K_GOT8: |
854 |
case R_68K_GOT8O: |
case R_68K_GOT8O: |
855 |
case R_68K_GOT16O: |
case R_68K_GOT16O: |
856 |
case R_68K_GOT32O: |
case R_68K_GOT32O: |
857 |
r_symndx = ELF32_R_SYM (rel->r_info); |
if (h != NULL) |
|
if (r_symndx >= symtab_hdr->sh_info) |
|
858 |
{ |
{ |
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
|
859 |
if (h->got.refcount > 0) |
if (h->got.refcount > 0) |
860 |
{ |
{ |
861 |
--h->got.refcount; |
--h->got.refcount; |
862 |
if (h->got.refcount == 0) |
if (h->got.refcount == 0) |
863 |
{ |
{ |
864 |
/* We don't need the .got entry any more. */ |
/* We don't need the .got entry any more. */ |
865 |
sgot->_raw_size -= 4; |
sgot->size -= 4; |
866 |
srelgot->_raw_size -= sizeof (Elf32_External_Rela); |
srelgot->size -= sizeof (Elf32_External_Rela); |
867 |
} |
} |
868 |
} |
} |
869 |
} |
} |
875 |
if (local_got_refcounts[r_symndx] == 0) |
if (local_got_refcounts[r_symndx] == 0) |
876 |
{ |
{ |
877 |
/* We don't need the .got entry any more. */ |
/* We don't need the .got entry any more. */ |
878 |
sgot->_raw_size -= 4; |
sgot->size -= 4; |
879 |
if (info->shared) |
if (info->shared) |
880 |
srelgot->_raw_size -= sizeof (Elf32_External_Rela); |
srelgot->size -= sizeof (Elf32_External_Rela); |
881 |
} |
} |
882 |
} |
} |
883 |
} |
} |
895 |
case R_68K_8: |
case R_68K_8: |
896 |
case R_68K_16: |
case R_68K_16: |
897 |
case R_68K_32: |
case R_68K_32: |
898 |
r_symndx = ELF32_R_SYM (rel->r_info); |
if (h != NULL) |
|
if (r_symndx >= symtab_hdr->sh_info) |
|
899 |
{ |
{ |
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
|
900 |
if (h->plt.refcount > 0) |
if (h->plt.refcount > 0) |
901 |
--h->plt.refcount; |
--h->plt.refcount; |
902 |
} |
} |
907 |
} |
} |
908 |
} |
} |
909 |
|
|
910 |
return true; |
return TRUE; |
911 |
} |
} |
912 |
|
|
913 |
/* Adjust a symbol defined by a dynamic object and referenced by a |
/* Adjust a symbol defined by a dynamic object and referenced by a |
916 |
change the definition to something the rest of the link can |
change the definition to something the rest of the link can |
917 |
understand. */ |
understand. */ |
918 |
|
|
919 |
static boolean |
static bfd_boolean |
920 |
elf_m68k_adjust_dynamic_symbol (info, h) |
elf_m68k_adjust_dynamic_symbol (info, h) |
921 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
922 |
struct elf_link_hash_entry *h; |
struct elf_link_hash_entry *h; |
929 |
|
|
930 |
/* Make sure we know what is going on here. */ |
/* Make sure we know what is going on here. */ |
931 |
BFD_ASSERT (dynobj != NULL |
BFD_ASSERT (dynobj != NULL |
932 |
&& ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) |
&& (h->needs_plt |
933 |
|| h->weakdef != NULL |
|| h->u.weakdef != NULL |
934 |
|| ((h->elf_link_hash_flags |
|| (h->def_dynamic |
935 |
& ELF_LINK_HASH_DEF_DYNAMIC) != 0 |
&& h->ref_regular |
936 |
&& (h->elf_link_hash_flags |
&& !h->def_regular))); |
|
& ELF_LINK_HASH_REF_REGULAR) != 0 |
|
|
&& (h->elf_link_hash_flags |
|
|
& ELF_LINK_HASH_DEF_REGULAR) == 0))); |
|
937 |
|
|
938 |
/* If this is a function, put it in the procedure linkage table. We |
/* If this is a function, put it in the procedure linkage table. We |
939 |
will fill in the contents of the procedure linkage table later, |
will fill in the contents of the procedure linkage table later, |
940 |
when we know the address of the .got section. */ |
when we know the address of the .got section. */ |
941 |
if (h->type == STT_FUNC |
if (h->type == STT_FUNC |
942 |
|| (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) |
|| h->needs_plt) |
943 |
{ |
{ |
944 |
if (! info->shared |
if ((h->plt.refcount <= 0 |
945 |
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 |
|| SYMBOL_CALLS_LOCAL (info, h) |
946 |
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0 |
|| (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT |
947 |
|
&& h->root.type == bfd_link_hash_undefweak)) |
948 |
/* We must always create the plt entry if it was referenced |
/* We must always create the plt entry if it was referenced |
949 |
by a PLTxxO relocation. In this case we already recorded |
by a PLTxxO relocation. In this case we already recorded |
950 |
it as a dynamic symbol. */ |
it as a dynamic symbol. */ |
952 |
{ |
{ |
953 |
/* This case can occur if we saw a PLTxx reloc in an input |
/* This case can occur if we saw a PLTxx reloc in an input |
954 |
file, but the symbol was never referred to by a dynamic |
file, but the symbol was never referred to by a dynamic |
955 |
object. In such a case, we don't actually need to build |
object, or if all references were garbage collected. In |
956 |
a procedure linkage table, and we can just do a PCxx |
such a case, we don't actually need to build a procedure |
957 |
reloc instead. */ |
linkage table, and we can just do a PCxx reloc instead. */ |
|
BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0); |
|
958 |
h->plt.offset = (bfd_vma) -1; |
h->plt.offset = (bfd_vma) -1; |
959 |
return true; |
h->needs_plt = 0; |
960 |
} |
return TRUE; |
|
|
|
|
/* GC may have rendered this entry unused. */ |
|
|
if (h->plt.refcount <= 0) |
|
|
{ |
|
|
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; |
|
|
h->plt.offset = (bfd_vma) -1; |
|
|
return true; |
|
961 |
} |
} |
962 |
|
|
963 |
/* Make sure this symbol is output as a dynamic symbol. */ |
/* Make sure this symbol is output as a dynamic symbol. */ |
964 |
if (h->dynindx == -1) |
if (h->dynindx == -1 |
965 |
|
&& !h->forced_local) |
966 |
{ |
{ |
967 |
if (! bfd_elf32_link_record_dynamic_symbol (info, h)) |
if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
968 |
return false; |
return FALSE; |
969 |
} |
} |
970 |
|
|
971 |
s = bfd_get_section_by_name (dynobj, ".plt"); |
s = bfd_get_section_by_name (dynobj, ".plt"); |
973 |
|
|
974 |
/* If this is the first .plt entry, make room for the special |
/* If this is the first .plt entry, make room for the special |
975 |
first entry. */ |
first entry. */ |
976 |
if (s->_raw_size == 0) |
if (s->size == 0) |
977 |
{ |
{ |
978 |
if (CPU32_FLAG (dynobj)) |
if (CPU32_FLAG (dynobj)) |
979 |
s->_raw_size += PLT_CPU32_ENTRY_SIZE; |
s->size += PLT_CPU32_ENTRY_SIZE; |
980 |
else |
else |
981 |
s->_raw_size += PLT_ENTRY_SIZE; |
s->size += PLT_ENTRY_SIZE; |
982 |
} |
} |
983 |
|
|
984 |
/* If this symbol is not defined in a regular file, and we are |
/* If this symbol is not defined in a regular file, and we are |
987 |
pointers compare as equal between the normal executable and |
pointers compare as equal between the normal executable and |
988 |
the shared library. */ |
the shared library. */ |
989 |
if (!info->shared |
if (!info->shared |
990 |
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) |
&& !h->def_regular) |
991 |
{ |
{ |
992 |
h->root.u.def.section = s; |
h->root.u.def.section = s; |
993 |
h->root.u.def.value = s->_raw_size; |
h->root.u.def.value = s->size; |
994 |
} |
} |
995 |
|
|
996 |
h->plt.offset = s->_raw_size; |
h->plt.offset = s->size; |
997 |
|
|
998 |
/* Make room for this entry. */ |
/* Make room for this entry. */ |
999 |
if (CPU32_FLAG (dynobj)) |
if (CPU32_FLAG (dynobj)) |
1000 |
s->_raw_size += PLT_CPU32_ENTRY_SIZE; |
s->size += PLT_CPU32_ENTRY_SIZE; |
1001 |
else |
else |
1002 |
s->_raw_size += PLT_ENTRY_SIZE; |
s->size += PLT_ENTRY_SIZE; |
1003 |
|
|
1004 |
/* We also need to make an entry in the .got.plt section, which |
/* We also need to make an entry in the .got.plt section, which |
1005 |
will be placed in the .got section by the linker script. */ |
will be placed in the .got section by the linker script. */ |
|
|
|
1006 |
s = bfd_get_section_by_name (dynobj, ".got.plt"); |
s = bfd_get_section_by_name (dynobj, ".got.plt"); |
1007 |
BFD_ASSERT (s != NULL); |
BFD_ASSERT (s != NULL); |
1008 |
s->_raw_size += 4; |
s->size += 4; |
1009 |
|
|
1010 |
/* We also need to make an entry in the .rela.plt section. */ |
/* We also need to make an entry in the .rela.plt section. */ |
|
|
|
1011 |
s = bfd_get_section_by_name (dynobj, ".rela.plt"); |
s = bfd_get_section_by_name (dynobj, ".rela.plt"); |
1012 |
BFD_ASSERT (s != NULL); |
BFD_ASSERT (s != NULL); |
1013 |
s->_raw_size += sizeof (Elf32_External_Rela); |
s->size += sizeof (Elf32_External_Rela); |
1014 |
|
|
1015 |
return true; |
return TRUE; |
1016 |
} |
} |
1017 |
|
|
1018 |
/* Reinitialize the plt offset now that it is not used as a reference |
/* Reinitialize the plt offset now that it is not used as a reference |
1022 |
/* If this is a weak symbol, and there is a real definition, the |
/* If this is a weak symbol, and there is a real definition, the |
1023 |
processor independent code will have arranged for us to see the |
processor independent code will have arranged for us to see the |
1024 |
real definition first, and we can just use the same value. */ |
real definition first, and we can just use the same value. */ |
1025 |
if (h->weakdef != NULL) |
if (h->u.weakdef != NULL) |
1026 |
{ |
{ |
1027 |
BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined |
BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined |
1028 |
|| h->weakdef->root.type == bfd_link_hash_defweak); |
|| h->u.weakdef->root.type == bfd_link_hash_defweak); |
1029 |
h->root.u.def.section = h->weakdef->root.u.def.section; |
h->root.u.def.section = h->u.weakdef->root.u.def.section; |
1030 |
h->root.u.def.value = h->weakdef->root.u.def.value; |
h->root.u.def.value = h->u.weakdef->root.u.def.value; |
1031 |
return true; |
return TRUE; |
1032 |
} |
} |
1033 |
|
|
1034 |
/* This is a reference to a symbol defined by a dynamic object which |
/* This is a reference to a symbol defined by a dynamic object which |
1039 |
For such cases we need not do anything here; the relocations will |
For such cases we need not do anything here; the relocations will |
1040 |
be handled correctly by relocate_section. */ |
be handled correctly by relocate_section. */ |
1041 |
if (info->shared) |
if (info->shared) |
1042 |
return true; |
return TRUE; |
1043 |
|
|
1044 |
/* We must allocate the symbol in our .dynbss section, which will |
/* We must allocate the symbol in our .dynbss section, which will |
1045 |
become part of the .bss section of the executable. There will be |
become part of the .bss section of the executable. There will be |
1064 |
|
|
1065 |
srel = bfd_get_section_by_name (dynobj, ".rela.bss"); |
srel = bfd_get_section_by_name (dynobj, ".rela.bss"); |
1066 |
BFD_ASSERT (srel != NULL); |
BFD_ASSERT (srel != NULL); |
1067 |
srel->_raw_size += sizeof (Elf32_External_Rela); |
srel->size += sizeof (Elf32_External_Rela); |
1068 |
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; |
h->needs_copy = 1; |
1069 |
} |
} |
1070 |
|
|
1071 |
/* We need to figure out the alignment required for this symbol. I |
/* We need to figure out the alignment required for this symbol. I |
1075 |
power_of_two = 3; |
power_of_two = 3; |
1076 |
|
|
1077 |
/* Apply the required alignment. */ |
/* Apply the required alignment. */ |
1078 |
s->_raw_size = BFD_ALIGN (s->_raw_size, |
s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two)); |
|
(bfd_size_type) (1 << power_of_two)); |
|
1079 |
if (power_of_two > bfd_get_section_alignment (dynobj, s)) |
if (power_of_two > bfd_get_section_alignment (dynobj, s)) |
1080 |
{ |
{ |
1081 |
if (!bfd_set_section_alignment (dynobj, s, power_of_two)) |
if (!bfd_set_section_alignment (dynobj, s, power_of_two)) |
1082 |
return false; |
return FALSE; |
1083 |
} |
} |
1084 |
|
|
1085 |
/* Define the symbol as being at this point in the section. */ |
/* Define the symbol as being at this point in the section. */ |
1086 |
h->root.u.def.section = s; |
h->root.u.def.section = s; |
1087 |
h->root.u.def.value = s->_raw_size; |
h->root.u.def.value = s->size; |
1088 |
|
|
1089 |
/* Increment the section size to make room for the symbol. */ |
/* Increment the section size to make room for the symbol. */ |
1090 |
s->_raw_size += h->size; |
s->size += h->size; |
1091 |
|
|
1092 |
return true; |
return TRUE; |
1093 |
} |
} |
1094 |
|
|
1095 |
/* Set the sizes of the dynamic sections. */ |
/* Set the sizes of the dynamic sections. */ |
1096 |
|
|
1097 |
static boolean |
static bfd_boolean |
1098 |
elf_m68k_size_dynamic_sections (output_bfd, info) |
elf_m68k_size_dynamic_sections (output_bfd, info) |
1099 |
bfd *output_bfd ATTRIBUTE_UNUSED; |
bfd *output_bfd ATTRIBUTE_UNUSED; |
1100 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
1101 |
{ |
{ |
1102 |
bfd *dynobj; |
bfd *dynobj; |
1103 |
asection *s; |
asection *s; |
1104 |
boolean plt; |
bfd_boolean plt; |
1105 |
boolean relocs; |
bfd_boolean relocs; |
1106 |
|
|
1107 |
dynobj = elf_hash_table (info)->dynobj; |
dynobj = elf_hash_table (info)->dynobj; |
1108 |
BFD_ASSERT (dynobj != NULL); |
BFD_ASSERT (dynobj != NULL); |
1110 |
if (elf_hash_table (info)->dynamic_sections_created) |
if (elf_hash_table (info)->dynamic_sections_created) |
1111 |
{ |
{ |
1112 |
/* Set the contents of the .interp section to the interpreter. */ |
/* Set the contents of the .interp section to the interpreter. */ |
1113 |
if (!info->shared) |
if (info->executable) |
1114 |
{ |
{ |
1115 |
s = bfd_get_section_by_name (dynobj, ".interp"); |
s = bfd_get_section_by_name (dynobj, ".interp"); |
1116 |
BFD_ASSERT (s != NULL); |
BFD_ASSERT (s != NULL); |
1117 |
s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; |
s->size = sizeof ELF_DYNAMIC_INTERPRETER; |
1118 |
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; |
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; |
1119 |
} |
} |
1120 |
} |
} |
1127 |
below. */ |
below. */ |
1128 |
s = bfd_get_section_by_name (dynobj, ".rela.got"); |
s = bfd_get_section_by_name (dynobj, ".rela.got"); |
1129 |
if (s != NULL) |
if (s != NULL) |
1130 |
s->_raw_size = 0; |
s->size = 0; |
1131 |
} |
} |
1132 |
|
|
1133 |
/* If this is a -Bsymbolic shared link, then we need to discard all PC |
/* If this is a -Bsymbolic shared link, then we need to discard all |
1134 |
relative relocs against symbols defined in a regular object. We |
PC relative relocs against symbols defined in a regular object. |
1135 |
allocated space for them in the check_relocs routine, but we will not |
For the normal shared case we discard the PC relative relocs |
1136 |
fill them in in the relocate_section routine. */ |
against symbols that have become local due to visibility changes. |
1137 |
if (info->shared && info->symbolic) |
We allocated space for them in the check_relocs routine, but we |
1138 |
elf_m68k_link_hash_traverse (elf_m68k_hash_table (info), |
will not fill them in in the relocate_section routine. */ |
1139 |
elf_m68k_discard_copies, |
if (info->shared) |
1140 |
(PTR) NULL); |
elf_link_hash_traverse (elf_hash_table (info), |
1141 |
|
elf_m68k_discard_copies, |
1142 |
|
(PTR) info); |
1143 |
|
|
1144 |
/* The check_relocs and adjust_dynamic_symbol entry points have |
/* The check_relocs and adjust_dynamic_symbol entry points have |
1145 |
determined the sizes of the various dynamic sections. Allocate |
determined the sizes of the various dynamic sections. Allocate |
1146 |
memory for them. */ |
memory for them. */ |
1147 |
plt = false; |
plt = FALSE; |
1148 |
relocs = false; |
relocs = FALSE; |
1149 |
for (s = dynobj->sections; s != NULL; s = s->next) |
for (s = dynobj->sections; s != NULL; s = s->next) |
1150 |
{ |
{ |
1151 |
const char *name; |
const char *name; |
1152 |
boolean strip; |
bfd_boolean strip; |
1153 |
|
|
1154 |
if ((s->flags & SEC_LINKER_CREATED) == 0) |
if ((s->flags & SEC_LINKER_CREATED) == 0) |
1155 |
continue; |
continue; |
1158 |
of the dynobj section names depend upon the input files. */ |
of the dynobj section names depend upon the input files. */ |
1159 |
name = bfd_get_section_name (dynobj, s); |
name = bfd_get_section_name (dynobj, s); |
1160 |
|
|
1161 |
strip = false; |
strip = FALSE; |
1162 |
|
|
1163 |
if (strcmp (name, ".plt") == 0) |
if (strcmp (name, ".plt") == 0) |
1164 |
{ |
{ |
1165 |
if (s->_raw_size == 0) |
if (s->size == 0) |
1166 |
{ |
{ |
1167 |
/* Strip this section if we don't need it; see the |
/* Strip this section if we don't need it; see the |
1168 |
comment below. */ |
comment below. */ |
1169 |
strip = true; |
strip = TRUE; |
1170 |
} |
} |
1171 |
else |
else |
1172 |
{ |
{ |
1173 |
/* Remember whether there is a PLT. */ |
/* Remember whether there is a PLT. */ |
1174 |
plt = true; |
plt = TRUE; |
1175 |
} |
} |
1176 |
} |
} |
1177 |
else if (strncmp (name, ".rela", 5) == 0) |
else if (strncmp (name, ".rela", 5) == 0) |
1178 |
{ |
{ |
1179 |
if (s->_raw_size == 0) |
if (s->size == 0) |
1180 |
{ |
{ |
1181 |
/* If we don't need this section, strip it from the |
/* If we don't need this section, strip it from the |
1182 |
output file. This is mostly to handle .rela.bss and |
output file. This is mostly to handle .rela.bss and |
1187 |
adjust_dynamic_symbol is called, and it is that |
adjust_dynamic_symbol is called, and it is that |
1188 |
function which decides whether anything needs to go |
function which decides whether anything needs to go |
1189 |
into these sections. */ |
into these sections. */ |
1190 |
strip = true; |
strip = TRUE; |
1191 |
} |
} |
1192 |
else |
else |
1193 |
{ |
{ |
1194 |
relocs = true; |
relocs = TRUE; |
1195 |
|
|
1196 |
/* We use the reloc_count field as a counter if we need |
/* We use the reloc_count field as a counter if we need |
1197 |
to copy relocs into the output file. */ |
to copy relocs into the output file. */ |
1216 |
are written out, but at the moment this does not happen. Thus in |
are written out, but at the moment this does not happen. Thus in |
1217 |
order to prevent writing out garbage, we initialise the section's |
order to prevent writing out garbage, we initialise the section's |
1218 |
contents to zero. */ |
contents to zero. */ |
1219 |
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); |
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size); |
1220 |
if (s->contents == NULL && s->_raw_size != 0) |
if (s->contents == NULL && s->size != 0) |
1221 |
return false; |
return FALSE; |
1222 |
} |
} |
1223 |
|
|
1224 |
if (elf_hash_table (info)->dynamic_sections_created) |
if (elf_hash_table (info)->dynamic_sections_created) |
1229 |
the .dynamic section. The DT_DEBUG entry is filled in by the |
the .dynamic section. The DT_DEBUG entry is filled in by the |
1230 |
dynamic linker and used by the debugger. */ |
dynamic linker and used by the debugger. */ |
1231 |
#define add_dynamic_entry(TAG, VAL) \ |
#define add_dynamic_entry(TAG, VAL) \ |
1232 |
bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL)) |
_bfd_elf_add_dynamic_entry (info, TAG, VAL) |
1233 |
|
|
1234 |
if (!info->shared) |
if (!info->shared) |
1235 |
{ |
{ |
1236 |
if (!add_dynamic_entry (DT_DEBUG, 0)) |
if (!add_dynamic_entry (DT_DEBUG, 0)) |
1237 |
return false; |
return FALSE; |
1238 |
} |
} |
1239 |
|
|
1240 |
if (plt) |
if (plt) |
1243 |
|| !add_dynamic_entry (DT_PLTRELSZ, 0) |
|| !add_dynamic_entry (DT_PLTRELSZ, 0) |
1244 |
|| !add_dynamic_entry (DT_PLTREL, DT_RELA) |
|| !add_dynamic_entry (DT_PLTREL, DT_RELA) |
1245 |
|| !add_dynamic_entry (DT_JMPREL, 0)) |
|| !add_dynamic_entry (DT_JMPREL, 0)) |
1246 |
return false; |
return FALSE; |
1247 |
} |
} |
1248 |
|
|
1249 |
if (relocs) |
if (relocs) |
1251 |
if (!add_dynamic_entry (DT_RELA, 0) |
if (!add_dynamic_entry (DT_RELA, 0) |
1252 |
|| !add_dynamic_entry (DT_RELASZ, 0) |
|| !add_dynamic_entry (DT_RELASZ, 0) |
1253 |
|| !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela))) |
|| !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela))) |
1254 |
return false; |
return FALSE; |
1255 |
} |
} |
1256 |
|
|
1257 |
if ((info->flags & DF_TEXTREL) != 0) |
if ((info->flags & DF_TEXTREL) != 0) |
1258 |
{ |
{ |
1259 |
if (!add_dynamic_entry (DT_TEXTREL, 0)) |
if (!add_dynamic_entry (DT_TEXTREL, 0)) |
1260 |
return false; |
return FALSE; |
1261 |
} |
} |
1262 |
} |
} |
1263 |
#undef add_dynamic_entry |
#undef add_dynamic_entry |
1264 |
|
|
1265 |
return true; |
return TRUE; |
1266 |
} |
} |
1267 |
|
|
1268 |
/* This function is called via elf_m68k_link_hash_traverse if we are |
/* This function is called via elf_link_hash_traverse if we are |
1269 |
creating a shared object with -Bsymbolic. It discards the space |
creating a shared object. In the -Bsymbolic case it discards the |
1270 |
allocated to copy PC relative relocs against symbols which are defined |
space allocated to copy PC relative relocs against symbols which |
1271 |
in regular objects. We allocated space for them in the check_relocs |
are defined in regular objects. For the normal shared case, it |
1272 |
routine, but we won't fill them in in the relocate_section routine. */ |
discards space for pc-relative relocs that have become local due to |
1273 |
|
symbol visibility changes. We allocated space for them in the |
1274 |
static boolean |
check_relocs routine, but we won't fill them in in the |
1275 |
elf_m68k_discard_copies (h, ignore) |
relocate_section routine. |
1276 |
struct elf_m68k_link_hash_entry *h; |
|
1277 |
PTR ignore ATTRIBUTE_UNUSED; |
We also check whether any of the remaining relocations apply |
1278 |
|
against a readonly section, and set the DF_TEXTREL flag in this |
1279 |
|
case. */ |
1280 |
|
|
1281 |
|
static bfd_boolean |
1282 |
|
elf_m68k_discard_copies (h, inf) |
1283 |
|
struct elf_link_hash_entry *h; |
1284 |
|
PTR inf; |
1285 |
{ |
{ |
1286 |
|
struct bfd_link_info *info = (struct bfd_link_info *) inf; |
1287 |
struct elf_m68k_pcrel_relocs_copied *s; |
struct elf_m68k_pcrel_relocs_copied *s; |
1288 |
|
|
1289 |
if (h->root.root.type == bfd_link_hash_warning) |
if (h->root.type == bfd_link_hash_warning) |
1290 |
h = (struct elf_m68k_link_hash_entry *) h->root.root.u.i.link; |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
1291 |
|
|
1292 |
|
if (!h->def_regular |
1293 |
|
|| (!info->symbolic |
1294 |
|
&& !h->forced_local)) |
1295 |
|
{ |
1296 |
|
if ((info->flags & DF_TEXTREL) == 0) |
1297 |
|
{ |
1298 |
|
/* Look for relocations against read-only sections. */ |
1299 |
|
for (s = elf_m68k_hash_entry (h)->pcrel_relocs_copied; |
1300 |
|
s != NULL; |
1301 |
|
s = s->next) |
1302 |
|
if ((s->section->flags & SEC_READONLY) != 0) |
1303 |
|
{ |
1304 |
|
info->flags |= DF_TEXTREL; |
1305 |
|
break; |
1306 |
|
} |
1307 |
|
} |
1308 |
|
|
1309 |
/* We only discard relocs for symbols defined in a regular object. */ |
return TRUE; |
1310 |
if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) |
} |
|
return true; |
|
1311 |
|
|
1312 |
for (s = h->pcrel_relocs_copied; s != NULL; s = s->next) |
for (s = elf_m68k_hash_entry (h)->pcrel_relocs_copied; |
1313 |
s->section->_raw_size -= s->count * sizeof (Elf32_External_Rela); |
s != NULL; |
1314 |
|
s = s->next) |
1315 |
|
s->section->size -= s->count * sizeof (Elf32_External_Rela); |
1316 |
|
|
1317 |
return true; |
return TRUE; |
1318 |
} |
} |
1319 |
|
|
1320 |
/* Relocate an M68K ELF section. */ |
/* Relocate an M68K ELF section. */ |
1321 |
|
|
1322 |
static boolean |
static bfd_boolean |
1323 |
elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, |
elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, |
1324 |
contents, relocs, local_syms, local_sections) |
contents, relocs, local_syms, local_sections) |
1325 |
bfd *output_bfd; |
bfd *output_bfd; |
1341 |
Elf_Internal_Rela *rel; |
Elf_Internal_Rela *rel; |
1342 |
Elf_Internal_Rela *relend; |
Elf_Internal_Rela *relend; |
1343 |
|
|
1344 |
if (info->relocateable) |
if (info->relocatable) |
1345 |
return true; |
return TRUE; |
1346 |
|
|
1347 |
dynobj = elf_hash_table (info)->dynobj; |
dynobj = elf_hash_table (info)->dynobj; |
1348 |
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; |
1364 |
Elf_Internal_Sym *sym; |
Elf_Internal_Sym *sym; |
1365 |
asection *sec; |
asection *sec; |
1366 |
bfd_vma relocation; |
bfd_vma relocation; |
1367 |
|
bfd_boolean unresolved_reloc; |
1368 |
bfd_reloc_status_type r; |
bfd_reloc_status_type r; |
1369 |
|
|
1370 |
r_type = ELF32_R_TYPE (rel->r_info); |
r_type = ELF32_R_TYPE (rel->r_info); |
1371 |
if (r_type < 0 || r_type >= (int) R_68K_max) |
if (r_type < 0 || r_type >= (int) R_68K_max) |
1372 |
{ |
{ |
1373 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
1374 |
return false; |
return FALSE; |
1375 |
} |
} |
1376 |
howto = howto_table + r_type; |
howto = howto_table + r_type; |
1377 |
|
|
1380 |
h = NULL; |
h = NULL; |
1381 |
sym = NULL; |
sym = NULL; |
1382 |
sec = NULL; |
sec = NULL; |
1383 |
|
unresolved_reloc = FALSE; |
1384 |
|
|
1385 |
if (r_symndx < symtab_hdr->sh_info) |
if (r_symndx < symtab_hdr->sh_info) |
1386 |
{ |
{ |
1387 |
sym = local_syms + r_symndx; |
sym = local_syms + r_symndx; |
1388 |
sec = local_sections[r_symndx]; |
sec = local_sections[r_symndx]; |
1389 |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); |
1390 |
} |
} |
1391 |
else |
else |
1392 |
{ |
{ |
1393 |
h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
bfd_boolean warned; |
1394 |
while (h->root.type == bfd_link_hash_indirect |
|
1395 |
|| h->root.type == bfd_link_hash_warning) |
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, |
1396 |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
r_symndx, symtab_hdr, sym_hashes, |
1397 |
if (h->root.type == bfd_link_hash_defined |
h, sec, relocation, |
1398 |
|| h->root.type == bfd_link_hash_defweak) |
unresolved_reloc, warned); |
|
{ |
|
|
sec = h->root.u.def.section; |
|
|
if (((r_type == R_68K_PLT8 |
|
|
|| r_type == R_68K_PLT16 |
|
|
|| r_type == R_68K_PLT32 |
|
|
|| r_type == R_68K_PLT8O |
|
|
|| r_type == R_68K_PLT16O |
|
|
|| r_type == R_68K_PLT32O) |
|
|
&& h->plt.offset != (bfd_vma) -1 |
|
|
&& elf_hash_table (info)->dynamic_sections_created) |
|
|
|| ((r_type == R_68K_GOT8O |
|
|
|| r_type == R_68K_GOT16O |
|
|
|| r_type == R_68K_GOT32O |
|
|
|| ((r_type == R_68K_GOT8 |
|
|
|| r_type == R_68K_GOT16 |
|
|
|| r_type == R_68K_GOT32) |
|
|
&& strcmp (h->root.root.string, |
|
|
"_GLOBAL_OFFSET_TABLE_") != 0)) |
|
|
&& elf_hash_table (info)->dynamic_sections_created |
|
|
&& (! info->shared |
|
|
|| (! info->symbolic && h->dynindx != -1) |
|
|
|| (h->elf_link_hash_flags |
|
|
& ELF_LINK_HASH_DEF_REGULAR) == 0)) |
|
|
|| (info->shared |
|
|
&& ((! info->symbolic && h->dynindx != -1) |
|
|
|| (h->elf_link_hash_flags |
|
|
& ELF_LINK_HASH_DEF_REGULAR) == 0) |
|
|
&& ((input_section->flags & SEC_ALLOC) != 0 |
|
|
/* DWARF will emit R_68K_32 relocations in its |
|
|
sections against symbols defined externally |
|
|
in shared libraries. We can't do anything |
|
|
with them here. */ |
|
|
|| ((input_section->flags & SEC_DEBUGGING) != 0 |
|
|
&& (h->elf_link_hash_flags |
|
|
& ELF_LINK_HASH_DEF_DYNAMIC) != 0)) |
|
|
&& (r_type == R_68K_8 |
|
|
|| r_type == R_68K_16 |
|
|
|| r_type == R_68K_32 |
|
|
|| r_type == R_68K_PC8 |
|
|
|| r_type == R_68K_PC16 |
|
|
|| r_type == R_68K_PC32))) |
|
|
{ |
|
|
/* In these cases, we don't need the relocation |
|
|
value. We check specially because in some |
|
|
obscure cases sec->output_section will be NULL. */ |
|
|
relocation = 0; |
|
|
} |
|
|
else |
|
|
relocation = (h->root.u.def.value |
|
|
+ sec->output_section->vma |
|
|
+ sec->output_offset); |
|
|
} |
|
|
else if (h->root.type == bfd_link_hash_undefweak) |
|
|
relocation = 0; |
|
|
else if (info->shared |
|
|
&& (!info->symbolic || info->allow_shlib_undefined) |
|
|
&& !info->no_undefined |
|
|
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) |
|
|
relocation = 0; |
|
|
else |
|
|
{ |
|
|
if (!(info->callbacks->undefined_symbol |
|
|
(info, h->root.root.string, input_bfd, |
|
|
input_section, rel->r_offset, |
|
|
(!info->shared || info->no_undefined |
|
|
|| ELF_ST_VISIBILITY (h->other))))) |
|
|
return false; |
|
|
relocation = 0; |
|
|
} |
|
1399 |
} |
} |
1400 |
|
|
1401 |
switch (r_type) |
switch (r_type) |
1426 |
|
|
1427 |
if (h != NULL) |
if (h != NULL) |
1428 |
{ |
{ |
1429 |
|
bfd_boolean dyn; |
1430 |
|
|
1431 |
off = h->got.offset; |
off = h->got.offset; |
1432 |
BFD_ASSERT (off != (bfd_vma) -1); |
BFD_ASSERT (off != (bfd_vma) -1); |
1433 |
|
|
1434 |
if (!elf_hash_table (info)->dynamic_sections_created |
dyn = elf_hash_table (info)->dynamic_sections_created; |
1435 |
|
if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) |
1436 |
|| (info->shared |
|| (info->shared |
1437 |
&& (info->symbolic || h->dynindx == -1) |
&& (info->symbolic |
1438 |
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) |
|| h->dynindx == -1 |
1439 |
|
|| h->forced_local) |
1440 |
|
&& h->def_regular)) |
1441 |
{ |
{ |
1442 |
/* This is actually a static link, or it is a |
/* This is actually a static link, or it is a |
1443 |
-Bsymbolic link and the symbol is defined |
-Bsymbolic link and the symbol is defined |
1460 |
h->got.offset |= 1; |
h->got.offset |= 1; |
1461 |
} |
} |
1462 |
} |
} |
1463 |
|
else |
1464 |
|
unresolved_reloc = FALSE; |
1465 |
} |
} |
1466 |
else |
else |
1467 |
{ |
{ |
1481 |
|
|
1482 |
if (info->shared) |
if (info->shared) |
1483 |
{ |
{ |
1484 |
asection *srelgot; |
asection *s; |
1485 |
Elf_Internal_Rela outrel; |
Elf_Internal_Rela outrel; |
1486 |
|
bfd_byte *loc; |
1487 |
|
|
1488 |
srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); |
s = bfd_get_section_by_name (dynobj, ".rela.got"); |
1489 |
BFD_ASSERT (srelgot != NULL); |
BFD_ASSERT (s != NULL); |
1490 |
|
|
1491 |
outrel.r_offset = (sgot->output_section->vma |
outrel.r_offset = (sgot->output_section->vma |
1492 |
+ sgot->output_offset |
+ sgot->output_offset |
1493 |
+ off); |
+ off); |
1494 |
outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); |
outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); |
1495 |
outrel.r_addend = relocation; |
outrel.r_addend = relocation; |
1496 |
bfd_elf32_swap_reloca_out (output_bfd, &outrel, |
loc = s->contents; |
1497 |
(((Elf32_External_Rela *) |
loc += s->reloc_count++ * sizeof (Elf32_External_Rela); |
1498 |
srelgot->contents) |
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); |
|
+ srelgot->reloc_count)); |
|
|
++srelgot->reloc_count; |
|
1499 |
} |
} |
1500 |
|
|
1501 |
local_got_offsets[r_symndx] |= 1; |
local_got_offsets[r_symndx] |= 1; |
1544 |
relocation = (splt->output_section->vma |
relocation = (splt->output_section->vma |
1545 |
+ splt->output_offset |
+ splt->output_offset |
1546 |
+ h->plt.offset); |
+ h->plt.offset); |
1547 |
|
unresolved_reloc = FALSE; |
1548 |
break; |
break; |
1549 |
|
|
1550 |
case R_68K_PLT8O: |
case R_68K_PLT8O: |
1561 |
} |
} |
1562 |
|
|
1563 |
relocation = h->plt.offset; |
relocation = h->plt.offset; |
1564 |
|
unresolved_reloc = FALSE; |
1565 |
|
|
1566 |
/* This relocation does not use the addend. */ |
/* This relocation does not use the addend. */ |
1567 |
rel->r_addend = 0; |
rel->r_addend = 0; |
1571 |
case R_68K_PC8: |
case R_68K_PC8: |
1572 |
case R_68K_PC16: |
case R_68K_PC16: |
1573 |
case R_68K_PC32: |
case R_68K_PC32: |
1574 |
if (h == NULL) |
if (h == NULL |
1575 |
|
|| (info->shared |
1576 |
|
&& h->forced_local)) |
1577 |
break; |
break; |
1578 |
/* Fall through. */ |
/* Fall through. */ |
1579 |
case R_68K_8: |
case R_68K_8: |
1582 |
if (info->shared |
if (info->shared |
1583 |
&& r_symndx != 0 |
&& r_symndx != 0 |
1584 |
&& (input_section->flags & SEC_ALLOC) != 0 |
&& (input_section->flags & SEC_ALLOC) != 0 |
1585 |
|
&& (h == NULL |
1586 |
|
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT |
1587 |
|
|| h->root.type != bfd_link_hash_undefweak) |
1588 |
&& ((r_type != R_68K_PC8 |
&& ((r_type != R_68K_PC8 |
1589 |
&& r_type != R_68K_PC16 |
&& r_type != R_68K_PC16 |
1590 |
&& r_type != R_68K_PC32) |
&& r_type != R_68K_PC32) |
1591 |
|| (!info->symbolic |
|| (h != NULL |
1592 |
|| (h->elf_link_hash_flags |
&& h->dynindx != -1 |
1593 |
& ELF_LINK_HASH_DEF_REGULAR) == 0))) |
&& (!info->symbolic |
1594 |
|
|| !h->def_regular)))) |
1595 |
{ |
{ |
1596 |
Elf_Internal_Rela outrel; |
Elf_Internal_Rela outrel; |
1597 |
boolean skip, relocate; |
bfd_byte *loc; |
1598 |
|
bfd_boolean skip, relocate; |
1599 |
|
|
1600 |
/* When generating a shared object, these relocations |
/* When generating a shared object, these relocations |
1601 |
are copied into the output file to be resolved at run |
are copied into the output file to be resolved at run |
1602 |
time. */ |
time. */ |
1603 |
|
|
1604 |
if (sreloc == NULL) |
skip = FALSE; |
1605 |
{ |
relocate = FALSE; |
|
const char *name; |
|
|
|
|
|
name = (bfd_elf_string_from_elf_section |
|
|
(input_bfd, |
|
|
elf_elfheader (input_bfd)->e_shstrndx, |
|
|
elf_section_data (input_section)->rel_hdr.sh_name)); |
|
|
if (name == NULL) |
|
|
return false; |
|
|
|
|
|
BFD_ASSERT (strncmp (name, ".rela", 5) == 0 |
|
|
&& strcmp (bfd_get_section_name (input_bfd, |
|
|
input_section), |
|
|
name + 5) == 0); |
|
|
|
|
|
sreloc = bfd_get_section_by_name (dynobj, name); |
|
|
BFD_ASSERT (sreloc != NULL); |
|
|
} |
|
|
|
|
|
skip = false; |
|
|
relocate = false; |
|
1606 |
|
|
1607 |
outrel.r_offset = |
outrel.r_offset = |
1608 |
_bfd_elf_section_offset (output_bfd, info, input_section, |
_bfd_elf_section_offset (output_bfd, info, input_section, |
1609 |
rel->r_offset); |
rel->r_offset); |
1610 |
if (outrel.r_offset == (bfd_vma) -1) |
if (outrel.r_offset == (bfd_vma) -1) |
1611 |
skip = true; |
skip = TRUE; |
1612 |
else if (outrel.r_offset == (bfd_vma) -2) |
else if (outrel.r_offset == (bfd_vma) -2) |
1613 |
skip = true, relocate = true; |
skip = TRUE, relocate = TRUE; |
1614 |
outrel.r_offset += (input_section->output_section->vma |
outrel.r_offset += (input_section->output_section->vma |
1615 |
+ input_section->output_offset); |
+ input_section->output_offset); |
1616 |
|
|
1617 |
if (skip) |
if (skip) |
1618 |
memset (&outrel, 0, sizeof outrel); |
memset (&outrel, 0, sizeof outrel); |
|
/* h->dynindx may be -1 if the symbol was marked to |
|
|
become local. */ |
|
1619 |
else if (h != NULL |
else if (h != NULL |
1620 |
&& ((! info->symbolic && h->dynindx != -1) |
&& h->dynindx != -1 |
1621 |
|| (h->elf_link_hash_flags |
&& (r_type == R_68K_PC8 |
1622 |
& ELF_LINK_HASH_DEF_REGULAR) == 0)) |
|| r_type == R_68K_PC16 |
1623 |
|
|| r_type == R_68K_PC32 |
1624 |
|
|| !info->shared |
1625 |
|
|| !info->symbolic |
1626 |
|
|| !h->def_regular)) |
1627 |
{ |
{ |
|
BFD_ASSERT (h->dynindx != -1); |
|
1628 |
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); |
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); |
1629 |
outrel.r_addend = relocation + rel->r_addend; |
outrel.r_addend = rel->r_addend; |
1630 |
} |
} |
1631 |
else |
else |
1632 |
{ |
{ |
1633 |
|
/* This symbol is local, or marked to become local. */ |
1634 |
if (r_type == R_68K_32) |
if (r_type == R_68K_32) |
1635 |
{ |
{ |
1636 |
relocate = true; |
relocate = TRUE; |
1637 |
outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); |
outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); |
1638 |
outrel.r_addend = relocation + rel->r_addend; |
outrel.r_addend = relocation + rel->r_addend; |
1639 |
} |
} |
1641 |
{ |
{ |
1642 |
long indx; |
long indx; |
1643 |
|
|
1644 |
if (h == NULL) |
if (bfd_is_abs_section (sec)) |
|
sec = local_sections[r_symndx]; |
|
|
else |
|
|
{ |
|
|
BFD_ASSERT (h->root.type == bfd_link_hash_defined |
|
|
|| (h->root.type |
|
|
== bfd_link_hash_defweak)); |
|
|
sec = h->root.u.def.section; |
|
|
} |
|
|
if (sec != NULL && bfd_is_abs_section (sec)) |
|
1645 |
indx = 0; |
indx = 0; |
1646 |
else if (sec == NULL || sec->owner == NULL) |
else if (sec == NULL || sec->owner == NULL) |
1647 |
{ |
{ |
1648 |
bfd_set_error (bfd_error_bad_value); |
bfd_set_error (bfd_error_bad_value); |
1649 |
return false; |
return FALSE; |
1650 |
} |
} |
1651 |
else |
else |
1652 |
{ |
{ |
1662 |
} |
} |
1663 |
} |
} |
1664 |
|
|
1665 |
bfd_elf32_swap_reloca_out (output_bfd, &outrel, |
sreloc = elf_section_data (input_section)->sreloc; |
1666 |
(((Elf32_External_Rela *) |
if (sreloc == NULL) |
1667 |
sreloc->contents) |
abort (); |
1668 |
+ sreloc->reloc_count)); |
|
1669 |
++sreloc->reloc_count; |
loc = sreloc->contents; |
1670 |
|
loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela); |
1671 |
|
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); |
1672 |
|
|
1673 |
/* This reloc will be computed at runtime, so there's no |
/* This reloc will be computed at runtime, so there's no |
1674 |
need to do anything now, except for R_68K_32 |
need to do anything now, except for R_68K_32 |
1689 |
break; |
break; |
1690 |
} |
} |
1691 |
|
|
1692 |
|
/* Dynamic relocs are not propagated for SEC_DEBUGGING sections |
1693 |
|
because such sections are not SEC_ALLOC and thus ld.so will |
1694 |
|
not process them. */ |
1695 |
|
if (unresolved_reloc |
1696 |
|
&& !((input_section->flags & SEC_DEBUGGING) != 0 |
1697 |
|
&& h->def_dynamic)) |
1698 |
|
{ |
1699 |
|
(*_bfd_error_handler) |
1700 |
|
(_("%B(%A+0x%lx): unresolvable relocation against symbol `%s'"), |
1701 |
|
input_bfd, |
1702 |
|
input_section, |
1703 |
|
(long) rel->r_offset, |
1704 |
|
h->root.root.string); |
1705 |
|
return FALSE; |
1706 |
|
} |
1707 |
|
|
1708 |
r = _bfd_final_link_relocate (howto, input_bfd, input_section, |
r = _bfd_final_link_relocate (howto, input_bfd, input_section, |
1709 |
contents, rel->r_offset, |
contents, rel->r_offset, |
1710 |
relocation, rel->r_addend); |
relocation, rel->r_addend); |
1711 |
|
|
1712 |
if (r != bfd_reloc_ok) |
if (r != bfd_reloc_ok) |
1713 |
{ |
{ |
1714 |
switch (r) |
const char *name; |
|
{ |
|
|
default: |
|
|
case bfd_reloc_outofrange: |
|
|
abort (); |
|
|
case bfd_reloc_overflow: |
|
|
{ |
|
|
const char *name; |
|
1715 |
|
|
1716 |
if (h != NULL) |
if (h != NULL) |
1717 |
name = h->root.root.string; |
name = h->root.root.string; |
1718 |
else |
else |
1719 |
{ |
{ |
1720 |
name = bfd_elf_string_from_elf_section (input_bfd, |
name = bfd_elf_string_from_elf_section (input_bfd, |
1721 |
symtab_hdr->sh_link, |
symtab_hdr->sh_link, |
1722 |
sym->st_name); |
sym->st_name); |
1723 |
if (name == NULL) |
if (name == NULL) |
1724 |
return false; |
return FALSE; |
1725 |
if (*name == '\0') |
if (*name == '\0') |
1726 |
name = bfd_section_name (input_bfd, sec); |
name = bfd_section_name (input_bfd, sec); |
1727 |
} |
} |
1728 |
if (!(info->callbacks->reloc_overflow |
|
1729 |
(info, name, howto->name, (bfd_vma) 0, |
if (r == bfd_reloc_overflow) |
1730 |
input_bfd, input_section, rel->r_offset))) |
{ |
1731 |
return false; |
if (!(info->callbacks->reloc_overflow |
1732 |
} |
(info, (h ? &h->root : NULL), name, howto->name, |
1733 |
break; |
(bfd_vma) 0, input_bfd, input_section, |
1734 |
|
rel->r_offset))) |
1735 |
|
return FALSE; |
1736 |
|
} |
1737 |
|
else |
1738 |
|
{ |
1739 |
|
(*_bfd_error_handler) |
1740 |
|
(_("%B(%A+0x%lx): reloc against `%s': error %d"), |
1741 |
|
input_bfd, input_section, |
1742 |
|
(long) rel->r_offset, name, (int) r); |
1743 |
|
return FALSE; |
1744 |
} |
} |
1745 |
} |
} |
1746 |
} |
} |
1747 |
|
|
1748 |
return true; |
return TRUE; |
1749 |
} |
} |
1750 |
|
|
1751 |
/* Finish up dynamic symbol handling. We set the contents of various |
/* Finish up dynamic symbol handling. We set the contents of various |
1752 |
dynamic sections here. */ |
dynamic sections here. */ |
1753 |
|
|
1754 |
static boolean |
static bfd_boolean |
1755 |
elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym) |
elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym) |
1756 |
bfd *output_bfd; |
bfd *output_bfd; |
1757 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
1771 |
bfd_vma plt_index; |
bfd_vma plt_index; |
1772 |
bfd_vma got_offset; |
bfd_vma got_offset; |
1773 |
Elf_Internal_Rela rela; |
Elf_Internal_Rela rela; |
1774 |
|
bfd_byte *loc; |
1775 |
|
|
1776 |
/* This symbol has an entry in the procedure linkage table. Set |
/* This symbol has an entry in the procedure linkage table. Set |
1777 |
it up. */ |
it up. */ |
1844 |
+ got_offset); |
+ got_offset); |
1845 |
rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_JMP_SLOT); |
rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_JMP_SLOT); |
1846 |
rela.r_addend = 0; |
rela.r_addend = 0; |
1847 |
bfd_elf32_swap_reloca_out (output_bfd, &rela, |
loc = srela->contents + plt_index * sizeof (Elf32_External_Rela); |
1848 |
((Elf32_External_Rela *) srela->contents |
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); |
|
+ plt_index)); |
|
1849 |
|
|
1850 |
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) |
if (!h->def_regular) |
1851 |
{ |
{ |
1852 |
/* Mark the symbol as undefined, rather than as defined in |
/* Mark the symbol as undefined, rather than as defined in |
1853 |
the .plt section. Leave the value alone. */ |
the .plt section. Leave the value alone. */ |
1860 |
asection *sgot; |
asection *sgot; |
1861 |
asection *srela; |
asection *srela; |
1862 |
Elf_Internal_Rela rela; |
Elf_Internal_Rela rela; |
1863 |
|
bfd_byte *loc; |
1864 |
|
|
1865 |
/* This symbol has an entry in the global offset table. Set it |
/* This symbol has an entry in the global offset table. Set it |
1866 |
up. */ |
up. */ |
1879 |
The entry in the global offset table will already have been |
The entry in the global offset table will already have been |
1880 |
initialized in the relocate_section function. */ |
initialized in the relocate_section function. */ |
1881 |
if (info->shared |
if (info->shared |
1882 |
&& (info->symbolic || h->dynindx == -1) |
&& (info->symbolic |
1883 |
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) |
|| h->dynindx == -1 |
1884 |
|
|| h->forced_local) |
1885 |
|
&& h->def_regular) |
1886 |
{ |
{ |
1887 |
rela.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); |
rela.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); |
1888 |
rela.r_addend = bfd_get_signed_32 (output_bfd, |
rela.r_addend = bfd_get_signed_32 (output_bfd, |
1897 |
rela.r_addend = 0; |
rela.r_addend = 0; |
1898 |
} |
} |
1899 |
|
|
1900 |
bfd_elf32_swap_reloca_out (output_bfd, &rela, |
loc = srela->contents; |
1901 |
((Elf32_External_Rela *) srela->contents |
loc += srela->reloc_count++ * sizeof (Elf32_External_Rela); |
1902 |
+ srela->reloc_count)); |
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); |
|
++srela->reloc_count; |
|
1903 |
} |
} |
1904 |
|
|
1905 |
if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) |
if (h->needs_copy) |
1906 |
{ |
{ |
1907 |
asection *s; |
asection *s; |
1908 |
Elf_Internal_Rela rela; |
Elf_Internal_Rela rela; |
1909 |
|
bfd_byte *loc; |
1910 |
|
|
1911 |
/* This symbol needs a copy reloc. Set it up. */ |
/* This symbol needs a copy reloc. Set it up. */ |
1912 |
|
|
1923 |
+ h->root.u.def.section->output_offset); |
+ h->root.u.def.section->output_offset); |
1924 |
rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_COPY); |
rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_COPY); |
1925 |
rela.r_addend = 0; |
rela.r_addend = 0; |
1926 |
bfd_elf32_swap_reloca_out (output_bfd, &rela, |
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela); |
1927 |
((Elf32_External_Rela *) s->contents |
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); |
|
+ s->reloc_count)); |
|
|
++s->reloc_count; |
|
1928 |
} |
} |
1929 |
|
|
1930 |
/* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */ |
/* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */ |
1932 |
|| strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) |
|| strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) |
1933 |
sym->st_shndx = SHN_ABS; |
sym->st_shndx = SHN_ABS; |
1934 |
|
|
1935 |
return true; |
return TRUE; |
1936 |
} |
} |
1937 |
|
|
1938 |
/* Finish up the dynamic sections. */ |
/* Finish up the dynamic sections. */ |
1939 |
|
|
1940 |
static boolean |
static bfd_boolean |
1941 |
elf_m68k_finish_dynamic_sections (output_bfd, info) |
elf_m68k_finish_dynamic_sections (output_bfd, info) |
1942 |
bfd *output_bfd; |
bfd *output_bfd; |
1943 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
1961 |
BFD_ASSERT (splt != NULL && sdyn != NULL); |
BFD_ASSERT (splt != NULL && sdyn != NULL); |
1962 |
|
|
1963 |
dyncon = (Elf32_External_Dyn *) sdyn->contents; |
dyncon = (Elf32_External_Dyn *) sdyn->contents; |
1964 |
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size); |
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); |
1965 |
for (; dyncon < dynconend; dyncon++) |
for (; dyncon < dynconend; dyncon++) |
1966 |
{ |
{ |
1967 |
Elf_Internal_Dyn dyn; |
Elf_Internal_Dyn dyn; |
1990 |
case DT_PLTRELSZ: |
case DT_PLTRELSZ: |
1991 |
s = bfd_get_section_by_name (output_bfd, ".rela.plt"); |
s = bfd_get_section_by_name (output_bfd, ".rela.plt"); |
1992 |
BFD_ASSERT (s != NULL); |
BFD_ASSERT (s != NULL); |
1993 |
if (s->_cooked_size != 0) |
dyn.d_un.d_val = s->size; |
|
dyn.d_un.d_val = s->_cooked_size; |
|
|
else |
|
|
dyn.d_un.d_val = s->_raw_size; |
|
1994 |
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); |
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); |
1995 |
break; |
break; |
1996 |
|
|
2004 |
about changing the DT_RELA entry. */ |
about changing the DT_RELA entry. */ |
2005 |
s = bfd_get_section_by_name (output_bfd, ".rela.plt"); |
s = bfd_get_section_by_name (output_bfd, ".rela.plt"); |
2006 |
if (s != NULL) |
if (s != NULL) |
2007 |
{ |
dyn.d_un.d_val -= s->size; |
|
if (s->_cooked_size != 0) |
|
|
dyn.d_un.d_val -= s->_cooked_size; |
|
|
else |
|
|
dyn.d_un.d_val -= s->_raw_size; |
|
|
} |
|
2008 |
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); |
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); |
2009 |
break; |
break; |
2010 |
} |
} |
2011 |
} |
} |
2012 |
|
|
2013 |
/* Fill in the first entry in the procedure linkage table. */ |
/* Fill in the first entry in the procedure linkage table. */ |
2014 |
if (splt->_raw_size > 0) |
if (splt->size > 0) |
2015 |
{ |
{ |
2016 |
if (!CPU32_FLAG (output_bfd)) |
if (!CPU32_FLAG (output_bfd)) |
2017 |
{ |
{ |
2049 |
} |
} |
2050 |
|
|
2051 |
/* Fill in the first three entries in the global offset table. */ |
/* Fill in the first three entries in the global offset table. */ |
2052 |
if (sgot->_raw_size > 0) |
if (sgot->size > 0) |
2053 |
{ |
{ |
2054 |
if (sdyn == NULL) |
if (sdyn == NULL) |
2055 |
bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents); |
bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents); |
2063 |
|
|
2064 |
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; |
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; |
2065 |
|
|
2066 |
return true; |
return TRUE; |
2067 |
} |
} |
2068 |
|
|
2069 |
/* Given a .data section and a .emreloc in-memory section, store |
/* Given a .data section and a .emreloc in-memory section, store |
2073 |
after the add_symbols entry point has been called for all the |
after the add_symbols entry point has been called for all the |
2074 |
objects, and before the final_link entry point is called. */ |
objects, and before the final_link entry point is called. */ |
2075 |
|
|
2076 |
boolean |
bfd_boolean |
2077 |
bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) |
bfd_m68k_elf32_create_embedded_relocs (abfd, info, datasec, relsec, errmsg) |
2078 |
bfd *abfd; |
bfd *abfd; |
2079 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
2088 |
bfd_byte *p; |
bfd_byte *p; |
2089 |
bfd_size_type amt; |
bfd_size_type amt; |
2090 |
|
|
2091 |
BFD_ASSERT (! info->relocateable); |
BFD_ASSERT (! info->relocatable); |
2092 |
|
|
2093 |
*errmsg = NULL; |
*errmsg = NULL; |
2094 |
|
|
2095 |
if (datasec->reloc_count == 0) |
if (datasec->reloc_count == 0) |
2096 |
return true; |
return TRUE; |
2097 |
|
|
2098 |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
2099 |
|
|
2100 |
/* Get a copy of the native relocations. */ |
/* Get a copy of the native relocations. */ |
2101 |
internal_relocs = (_bfd_elf32_link_read_relocs |
internal_relocs = (_bfd_elf_link_read_relocs |
2102 |
(abfd, datasec, (PTR) NULL, (Elf_Internal_Rela *) NULL, |
(abfd, datasec, (PTR) NULL, (Elf_Internal_Rela *) NULL, |
2103 |
info->keep_memory)); |
info->keep_memory)); |
2104 |
if (internal_relocs == NULL) |
if (internal_relocs == NULL) |
2170 |
bfd_put_32 (abfd, irel->r_offset + datasec->output_offset, p); |
bfd_put_32 (abfd, irel->r_offset + datasec->output_offset, p); |
2171 |
memset (p + 4, 0, 8); |
memset (p + 4, 0, 8); |
2172 |
if (targetsec != NULL) |
if (targetsec != NULL) |
2173 |
strncpy (p + 4, targetsec->output_section->name, 8); |
strncpy ((char *) p + 4, targetsec->output_section->name, 8); |
2174 |
} |
} |
2175 |
|
|
2176 |
if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) |
if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) |
2178 |
if (internal_relocs != NULL |
if (internal_relocs != NULL |
2179 |
&& elf_section_data (datasec)->relocs != internal_relocs) |
&& elf_section_data (datasec)->relocs != internal_relocs) |
2180 |
free (internal_relocs); |
free (internal_relocs); |
2181 |
return true; |
return TRUE; |
2182 |
|
|
2183 |
error_return: |
error_return: |
2184 |
if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) |
if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) |
2186 |
if (internal_relocs != NULL |
if (internal_relocs != NULL |
2187 |
&& elf_section_data (datasec)->relocs != internal_relocs) |
&& elf_section_data (datasec)->relocs != internal_relocs) |
2188 |
free (internal_relocs); |
free (internal_relocs); |
2189 |
return false; |
return FALSE; |
2190 |
} |
} |
2191 |
|
|
2192 |
static enum elf_reloc_type_class |
static enum elf_reloc_type_class |
2206 |
} |
} |
2207 |
} |
} |
2208 |
|
|
2209 |
|
/* Return address for Ith PLT stub in section PLT, for relocation REL |
2210 |
|
or (bfd_vma) -1 if it should not be included. */ |
2211 |
|
|
2212 |
|
static bfd_vma |
2213 |
|
elf_m68k_plt_sym_val (bfd_vma i, const asection *plt, |
2214 |
|
const arelent *rel ATTRIBUTE_UNUSED) |
2215 |
|
{ |
2216 |
|
if (CPU32_FLAG (plt->owner)) |
2217 |
|
return plt->vma + (i + 1) * PLT_CPU32_ENTRY_SIZE; |
2218 |
|
return plt->vma + (i + 1) * PLT_ENTRY_SIZE; |
2219 |
|
} |
2220 |
|
|
2221 |
#define TARGET_BIG_SYM bfd_elf32_m68k_vec |
#define TARGET_BIG_SYM bfd_elf32_m68k_vec |
2222 |
#define TARGET_BIG_NAME "elf32-m68k" |
#define TARGET_BIG_NAME "elf32-m68k" |
2223 |
#define ELF_MACHINE_CODE EM_68K |
#define ELF_MACHINE_CODE EM_68K |
2226 |
_bfd_elf_create_dynamic_sections |
_bfd_elf_create_dynamic_sections |
2227 |
#define bfd_elf32_bfd_link_hash_table_create \ |
#define bfd_elf32_bfd_link_hash_table_create \ |
2228 |
elf_m68k_link_hash_table_create |
elf_m68k_link_hash_table_create |
2229 |
#define bfd_elf32_bfd_final_link _bfd_elf32_gc_common_final_link |
#define bfd_elf32_bfd_final_link bfd_elf_gc_common_final_link |
2230 |
|
|
2231 |
#define elf_backend_check_relocs elf_m68k_check_relocs |
#define elf_backend_check_relocs elf_m68k_check_relocs |
2232 |
#define elf_backend_adjust_dynamic_symbol \ |
#define elf_backend_adjust_dynamic_symbol \ |
2247 |
#define bfd_elf32_bfd_print_private_bfd_data \ |
#define bfd_elf32_bfd_print_private_bfd_data \ |
2248 |
elf32_m68k_print_private_bfd_data |
elf32_m68k_print_private_bfd_data |
2249 |
#define elf_backend_reloc_type_class elf32_m68k_reloc_type_class |
#define elf_backend_reloc_type_class elf32_m68k_reloc_type_class |
2250 |
|
#define elf_backend_plt_sym_val elf_m68k_plt_sym_val |
2251 |
|
|
2252 |
#define elf_backend_can_gc_sections 1 |
#define elf_backend_can_gc_sections 1 |
2253 |
#define elf_backend_can_refcount 1 |
#define elf_backend_can_refcount 1 |