| 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, 2003, |
Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, |
| 3 |
2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. |
2004, 2005, 2006, 2007, 2008, 2009 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 |
|
|
| 114 |
0, /* src_mask */ |
0, /* src_mask */ |
| 115 |
0, /* dst_mask */ |
0, /* dst_mask */ |
| 116 |
FALSE), |
FALSE), |
| 117 |
|
|
| 118 |
|
/* TLS general dynamic variable reference. */ |
| 119 |
|
HOWTO (R_68K_TLS_GD32, /* type */ |
| 120 |
|
0, /* rightshift */ |
| 121 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 122 |
|
32, /* bitsize */ |
| 123 |
|
FALSE, /* pc_relative */ |
| 124 |
|
0, /* bitpos */ |
| 125 |
|
complain_overflow_bitfield, /* complain_on_overflow */ |
| 126 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 127 |
|
"R_68K_TLS_GD32", /* name */ |
| 128 |
|
FALSE, /* partial_inplace */ |
| 129 |
|
0, /* src_mask */ |
| 130 |
|
0xffffffff, /* dst_mask */ |
| 131 |
|
FALSE), /* pcrel_offset */ |
| 132 |
|
|
| 133 |
|
HOWTO (R_68K_TLS_GD16, /* type */ |
| 134 |
|
0, /* rightshift */ |
| 135 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 136 |
|
16, /* bitsize */ |
| 137 |
|
FALSE, /* pc_relative */ |
| 138 |
|
0, /* bitpos */ |
| 139 |
|
complain_overflow_signed, /* complain_on_overflow */ |
| 140 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 141 |
|
"R_68K_TLS_GD16", /* name */ |
| 142 |
|
FALSE, /* partial_inplace */ |
| 143 |
|
0, /* src_mask */ |
| 144 |
|
0x0000ffff, /* dst_mask */ |
| 145 |
|
FALSE), /* pcrel_offset */ |
| 146 |
|
|
| 147 |
|
HOWTO (R_68K_TLS_GD8, /* type */ |
| 148 |
|
0, /* rightshift */ |
| 149 |
|
0, /* size (0 = byte, 1 = short, 2 = long) */ |
| 150 |
|
8, /* bitsize */ |
| 151 |
|
FALSE, /* pc_relative */ |
| 152 |
|
0, /* bitpos */ |
| 153 |
|
complain_overflow_signed, /* complain_on_overflow */ |
| 154 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 155 |
|
"R_68K_TLS_GD8", /* name */ |
| 156 |
|
FALSE, /* partial_inplace */ |
| 157 |
|
0, /* src_mask */ |
| 158 |
|
0x000000ff, /* dst_mask */ |
| 159 |
|
FALSE), /* pcrel_offset */ |
| 160 |
|
|
| 161 |
|
/* TLS local dynamic variable reference. */ |
| 162 |
|
HOWTO (R_68K_TLS_LDM32, /* type */ |
| 163 |
|
0, /* rightshift */ |
| 164 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 165 |
|
32, /* bitsize */ |
| 166 |
|
FALSE, /* pc_relative */ |
| 167 |
|
0, /* bitpos */ |
| 168 |
|
complain_overflow_bitfield, /* complain_on_overflow */ |
| 169 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 170 |
|
"R_68K_TLS_LDM32", /* name */ |
| 171 |
|
FALSE, /* partial_inplace */ |
| 172 |
|
0, /* src_mask */ |
| 173 |
|
0xffffffff, /* dst_mask */ |
| 174 |
|
FALSE), /* pcrel_offset */ |
| 175 |
|
|
| 176 |
|
HOWTO (R_68K_TLS_LDM16, /* type */ |
| 177 |
|
0, /* rightshift */ |
| 178 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 179 |
|
16, /* bitsize */ |
| 180 |
|
FALSE, /* pc_relative */ |
| 181 |
|
0, /* bitpos */ |
| 182 |
|
complain_overflow_signed, /* complain_on_overflow */ |
| 183 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 184 |
|
"R_68K_TLS_LDM16", /* name */ |
| 185 |
|
FALSE, /* partial_inplace */ |
| 186 |
|
0, /* src_mask */ |
| 187 |
|
0x0000ffff, /* dst_mask */ |
| 188 |
|
FALSE), /* pcrel_offset */ |
| 189 |
|
|
| 190 |
|
HOWTO (R_68K_TLS_LDM8, /* type */ |
| 191 |
|
0, /* rightshift */ |
| 192 |
|
0, /* size (0 = byte, 1 = short, 2 = long) */ |
| 193 |
|
8, /* bitsize */ |
| 194 |
|
FALSE, /* pc_relative */ |
| 195 |
|
0, /* bitpos */ |
| 196 |
|
complain_overflow_signed, /* complain_on_overflow */ |
| 197 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 198 |
|
"R_68K_TLS_LDM8", /* name */ |
| 199 |
|
FALSE, /* partial_inplace */ |
| 200 |
|
0, /* src_mask */ |
| 201 |
|
0x000000ff, /* dst_mask */ |
| 202 |
|
FALSE), /* pcrel_offset */ |
| 203 |
|
|
| 204 |
|
HOWTO (R_68K_TLS_LDO32, /* type */ |
| 205 |
|
0, /* rightshift */ |
| 206 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 207 |
|
32, /* bitsize */ |
| 208 |
|
FALSE, /* pc_relative */ |
| 209 |
|
0, /* bitpos */ |
| 210 |
|
complain_overflow_bitfield, /* complain_on_overflow */ |
| 211 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 212 |
|
"R_68K_TLS_LDO32", /* name */ |
| 213 |
|
FALSE, /* partial_inplace */ |
| 214 |
|
0, /* src_mask */ |
| 215 |
|
0xffffffff, /* dst_mask */ |
| 216 |
|
FALSE), /* pcrel_offset */ |
| 217 |
|
|
| 218 |
|
HOWTO (R_68K_TLS_LDO16, /* type */ |
| 219 |
|
0, /* rightshift */ |
| 220 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 221 |
|
16, /* bitsize */ |
| 222 |
|
FALSE, /* pc_relative */ |
| 223 |
|
0, /* bitpos */ |
| 224 |
|
complain_overflow_signed, /* complain_on_overflow */ |
| 225 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 226 |
|
"R_68K_TLS_LDO16", /* name */ |
| 227 |
|
FALSE, /* partial_inplace */ |
| 228 |
|
0, /* src_mask */ |
| 229 |
|
0x0000ffff, /* dst_mask */ |
| 230 |
|
FALSE), /* pcrel_offset */ |
| 231 |
|
|
| 232 |
|
HOWTO (R_68K_TLS_LDO8, /* type */ |
| 233 |
|
0, /* rightshift */ |
| 234 |
|
0, /* size (0 = byte, 1 = short, 2 = long) */ |
| 235 |
|
8, /* bitsize */ |
| 236 |
|
FALSE, /* pc_relative */ |
| 237 |
|
0, /* bitpos */ |
| 238 |
|
complain_overflow_signed, /* complain_on_overflow */ |
| 239 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 240 |
|
"R_68K_TLS_LDO8", /* name */ |
| 241 |
|
FALSE, /* partial_inplace */ |
| 242 |
|
0, /* src_mask */ |
| 243 |
|
0x000000ff, /* dst_mask */ |
| 244 |
|
FALSE), /* pcrel_offset */ |
| 245 |
|
|
| 246 |
|
/* TLS initial execution variable reference. */ |
| 247 |
|
HOWTO (R_68K_TLS_IE32, /* type */ |
| 248 |
|
0, /* rightshift */ |
| 249 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 250 |
|
32, /* bitsize */ |
| 251 |
|
FALSE, /* pc_relative */ |
| 252 |
|
0, /* bitpos */ |
| 253 |
|
complain_overflow_bitfield, /* complain_on_overflow */ |
| 254 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 255 |
|
"R_68K_TLS_IE32", /* name */ |
| 256 |
|
FALSE, /* partial_inplace */ |
| 257 |
|
0, /* src_mask */ |
| 258 |
|
0xffffffff, /* dst_mask */ |
| 259 |
|
FALSE), /* pcrel_offset */ |
| 260 |
|
|
| 261 |
|
HOWTO (R_68K_TLS_IE16, /* type */ |
| 262 |
|
0, /* rightshift */ |
| 263 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 264 |
|
16, /* bitsize */ |
| 265 |
|
FALSE, /* pc_relative */ |
| 266 |
|
0, /* bitpos */ |
| 267 |
|
complain_overflow_signed, /* complain_on_overflow */ |
| 268 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 269 |
|
"R_68K_TLS_IE16", /* name */ |
| 270 |
|
FALSE, /* partial_inplace */ |
| 271 |
|
0, /* src_mask */ |
| 272 |
|
0x0000ffff, /* dst_mask */ |
| 273 |
|
FALSE), /* pcrel_offset */ |
| 274 |
|
|
| 275 |
|
HOWTO (R_68K_TLS_IE8, /* type */ |
| 276 |
|
0, /* rightshift */ |
| 277 |
|
0, /* size (0 = byte, 1 = short, 2 = long) */ |
| 278 |
|
8, /* bitsize */ |
| 279 |
|
FALSE, /* pc_relative */ |
| 280 |
|
0, /* bitpos */ |
| 281 |
|
complain_overflow_signed, /* complain_on_overflow */ |
| 282 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 283 |
|
"R_68K_TLS_IE8", /* name */ |
| 284 |
|
FALSE, /* partial_inplace */ |
| 285 |
|
0, /* src_mask */ |
| 286 |
|
0x000000ff, /* dst_mask */ |
| 287 |
|
FALSE), /* pcrel_offset */ |
| 288 |
|
|
| 289 |
|
/* TLS local execution variable reference. */ |
| 290 |
|
HOWTO (R_68K_TLS_LE32, /* type */ |
| 291 |
|
0, /* rightshift */ |
| 292 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 293 |
|
32, /* bitsize */ |
| 294 |
|
FALSE, /* pc_relative */ |
| 295 |
|
0, /* bitpos */ |
| 296 |
|
complain_overflow_bitfield, /* complain_on_overflow */ |
| 297 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 298 |
|
"R_68K_TLS_LE32", /* name */ |
| 299 |
|
FALSE, /* partial_inplace */ |
| 300 |
|
0, /* src_mask */ |
| 301 |
|
0xffffffff, /* dst_mask */ |
| 302 |
|
FALSE), /* pcrel_offset */ |
| 303 |
|
|
| 304 |
|
HOWTO (R_68K_TLS_LE16, /* type */ |
| 305 |
|
0, /* rightshift */ |
| 306 |
|
1, /* size (0 = byte, 1 = short, 2 = long) */ |
| 307 |
|
16, /* bitsize */ |
| 308 |
|
FALSE, /* pc_relative */ |
| 309 |
|
0, /* bitpos */ |
| 310 |
|
complain_overflow_signed, /* complain_on_overflow */ |
| 311 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 312 |
|
"R_68K_TLS_LE16", /* name */ |
| 313 |
|
FALSE, /* partial_inplace */ |
| 314 |
|
0, /* src_mask */ |
| 315 |
|
0x0000ffff, /* dst_mask */ |
| 316 |
|
FALSE), /* pcrel_offset */ |
| 317 |
|
|
| 318 |
|
HOWTO (R_68K_TLS_LE8, /* type */ |
| 319 |
|
0, /* rightshift */ |
| 320 |
|
0, /* size (0 = byte, 1 = short, 2 = long) */ |
| 321 |
|
8, /* bitsize */ |
| 322 |
|
FALSE, /* pc_relative */ |
| 323 |
|
0, /* bitpos */ |
| 324 |
|
complain_overflow_signed, /* complain_on_overflow */ |
| 325 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 326 |
|
"R_68K_TLS_LE8", /* name */ |
| 327 |
|
FALSE, /* partial_inplace */ |
| 328 |
|
0, /* src_mask */ |
| 329 |
|
0x000000ff, /* dst_mask */ |
| 330 |
|
FALSE), /* pcrel_offset */ |
| 331 |
|
|
| 332 |
|
/* TLS GD/LD dynamic relocations. */ |
| 333 |
|
HOWTO (R_68K_TLS_DTPMOD32, /* type */ |
| 334 |
|
0, /* rightshift */ |
| 335 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 336 |
|
32, /* bitsize */ |
| 337 |
|
FALSE, /* pc_relative */ |
| 338 |
|
0, /* bitpos */ |
| 339 |
|
complain_overflow_dont, /* complain_on_overflow */ |
| 340 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 341 |
|
"R_68K_TLS_DTPMOD32", /* name */ |
| 342 |
|
FALSE, /* partial_inplace */ |
| 343 |
|
0, /* src_mask */ |
| 344 |
|
0xffffffff, /* dst_mask */ |
| 345 |
|
FALSE), /* pcrel_offset */ |
| 346 |
|
|
| 347 |
|
HOWTO (R_68K_TLS_DTPREL32, /* type */ |
| 348 |
|
0, /* rightshift */ |
| 349 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 350 |
|
32, /* bitsize */ |
| 351 |
|
FALSE, /* pc_relative */ |
| 352 |
|
0, /* bitpos */ |
| 353 |
|
complain_overflow_dont, /* complain_on_overflow */ |
| 354 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 355 |
|
"R_68K_TLS_DTPREL32", /* name */ |
| 356 |
|
FALSE, /* partial_inplace */ |
| 357 |
|
0, /* src_mask */ |
| 358 |
|
0xffffffff, /* dst_mask */ |
| 359 |
|
FALSE), /* pcrel_offset */ |
| 360 |
|
|
| 361 |
|
HOWTO (R_68K_TLS_TPREL32, /* type */ |
| 362 |
|
0, /* rightshift */ |
| 363 |
|
2, /* size (0 = byte, 1 = short, 2 = long) */ |
| 364 |
|
32, /* bitsize */ |
| 365 |
|
FALSE, /* pc_relative */ |
| 366 |
|
0, /* bitpos */ |
| 367 |
|
complain_overflow_dont, /* complain_on_overflow */ |
| 368 |
|
bfd_elf_generic_reloc, /* special_function */ |
| 369 |
|
"R_68K_TLS_TPREL32", /* name */ |
| 370 |
|
FALSE, /* partial_inplace */ |
| 371 |
|
0, /* src_mask */ |
| 372 |
|
0xffffffff, /* dst_mask */ |
| 373 |
|
FALSE), /* pcrel_offset */ |
| 374 |
}; |
}; |
| 375 |
|
|
| 376 |
static void |
static void |
| 389 |
{ |
{ |
| 390 |
bfd_reloc_code_real_type bfd_val; |
bfd_reloc_code_real_type bfd_val; |
| 391 |
int elf_val; |
int elf_val; |
| 392 |
} reloc_map[] = { |
} |
| 393 |
|
reloc_map[] = |
| 394 |
|
{ |
| 395 |
{ BFD_RELOC_NONE, R_68K_NONE }, |
{ BFD_RELOC_NONE, R_68K_NONE }, |
| 396 |
{ BFD_RELOC_32, R_68K_32 }, |
{ BFD_RELOC_32, R_68K_32 }, |
| 397 |
{ BFD_RELOC_16, R_68K_16 }, |
{ BFD_RELOC_16, R_68K_16 }, |
| 418 |
{ BFD_RELOC_CTOR, R_68K_32 }, |
{ BFD_RELOC_CTOR, R_68K_32 }, |
| 419 |
{ BFD_RELOC_VTABLE_INHERIT, R_68K_GNU_VTINHERIT }, |
{ BFD_RELOC_VTABLE_INHERIT, R_68K_GNU_VTINHERIT }, |
| 420 |
{ BFD_RELOC_VTABLE_ENTRY, R_68K_GNU_VTENTRY }, |
{ BFD_RELOC_VTABLE_ENTRY, R_68K_GNU_VTENTRY }, |
| 421 |
|
{ BFD_RELOC_68K_TLS_GD32, R_68K_TLS_GD32 }, |
| 422 |
|
{ BFD_RELOC_68K_TLS_GD16, R_68K_TLS_GD16 }, |
| 423 |
|
{ BFD_RELOC_68K_TLS_GD8, R_68K_TLS_GD8 }, |
| 424 |
|
{ BFD_RELOC_68K_TLS_LDM32, R_68K_TLS_LDM32 }, |
| 425 |
|
{ BFD_RELOC_68K_TLS_LDM16, R_68K_TLS_LDM16 }, |
| 426 |
|
{ BFD_RELOC_68K_TLS_LDM8, R_68K_TLS_LDM8 }, |
| 427 |
|
{ BFD_RELOC_68K_TLS_LDO32, R_68K_TLS_LDO32 }, |
| 428 |
|
{ BFD_RELOC_68K_TLS_LDO16, R_68K_TLS_LDO16 }, |
| 429 |
|
{ BFD_RELOC_68K_TLS_LDO8, R_68K_TLS_LDO8 }, |
| 430 |
|
{ BFD_RELOC_68K_TLS_IE32, R_68K_TLS_IE32 }, |
| 431 |
|
{ BFD_RELOC_68K_TLS_IE16, R_68K_TLS_IE16 }, |
| 432 |
|
{ BFD_RELOC_68K_TLS_IE8, R_68K_TLS_IE8 }, |
| 433 |
|
{ BFD_RELOC_68K_TLS_LE32, R_68K_TLS_LE32 }, |
| 434 |
|
{ BFD_RELOC_68K_TLS_LE16, R_68K_TLS_LE16 }, |
| 435 |
|
{ BFD_RELOC_68K_TLS_LE8, R_68K_TLS_LE8 }, |
| 436 |
}; |
}; |
| 437 |
|
|
| 438 |
static reloc_howto_type * |
static reloc_howto_type * |
| 693 |
|
|
| 694 |
/* Symbol index. Either local symbol index or h->got_entry_key. */ |
/* Symbol index. Either local symbol index or h->got_entry_key. */ |
| 695 |
unsigned long symndx; |
unsigned long symndx; |
| 696 |
|
|
| 697 |
|
/* Type is one of R_68K_GOT{8, 16, 32}O, R_68K_TLS_GD{8, 16, 32}, |
| 698 |
|
R_68K_TLS_LDM{8, 16, 32} or R_68K_TLS_IE{8, 16, 32}. |
| 699 |
|
|
| 700 |
|
From perspective of hashtable key, only elf_m68k_got_reloc_type (type) |
| 701 |
|
matters. That is, we distinguish between, say, R_68K_GOT16O |
| 702 |
|
and R_68K_GOT32O when allocating offsets, but they are considered to be |
| 703 |
|
the same when searching got->entries. */ |
| 704 |
|
enum elf_m68k_reloc_type type; |
| 705 |
}; |
}; |
| 706 |
|
|
| 707 |
|
/* Size of the GOT offset suitable for relocation. */ |
| 708 |
|
enum elf_m68k_got_offset_size { R_8, R_16, R_32, R_LAST }; |
| 709 |
|
|
| 710 |
/* Entry of the GOT. */ |
/* Entry of the GOT. */ |
| 711 |
struct elf_m68k_got_entry |
struct elf_m68k_got_entry |
| 712 |
{ |
{ |
| 721 |
/* Number of times this entry is referenced. It is used to |
/* Number of times this entry is referenced. It is used to |
| 722 |
filter out unnecessary GOT slots in elf_m68k_gc_sweep_hook. */ |
filter out unnecessary GOT slots in elf_m68k_gc_sweep_hook. */ |
| 723 |
bfd_vma refcount; |
bfd_vma refcount; |
|
|
|
|
/* Type is one of R_68K_GOT8O, R_68K_GOT16O or R_68K_GOT32O. */ |
|
|
int type; |
|
| 724 |
} s1; |
} s1; |
| 725 |
|
|
| 726 |
struct |
struct |
| 739 |
} u; |
} u; |
| 740 |
}; |
}; |
| 741 |
|
|
| 742 |
|
/* Return representative type for relocation R_TYPE. |
| 743 |
|
This is used to avoid enumerating many relocations in comparisons, |
| 744 |
|
switches etc. */ |
| 745 |
|
|
| 746 |
|
static enum elf_m68k_reloc_type |
| 747 |
|
elf_m68k_reloc_got_type (enum elf_m68k_reloc_type r_type) |
| 748 |
|
{ |
| 749 |
|
switch (r_type) |
| 750 |
|
{ |
| 751 |
|
/* In most cases R_68K_GOTx relocations require the very same |
| 752 |
|
handling as R_68K_GOT32O relocation. In cases when we need |
| 753 |
|
to distinguish between the two, we use explicitly compare against |
| 754 |
|
r_type. */ |
| 755 |
|
case R_68K_GOT32: |
| 756 |
|
case R_68K_GOT16: |
| 757 |
|
case R_68K_GOT8: |
| 758 |
|
case R_68K_GOT32O: |
| 759 |
|
case R_68K_GOT16O: |
| 760 |
|
case R_68K_GOT8O: |
| 761 |
|
return R_68K_GOT32O; |
| 762 |
|
|
| 763 |
|
case R_68K_TLS_GD32: |
| 764 |
|
case R_68K_TLS_GD16: |
| 765 |
|
case R_68K_TLS_GD8: |
| 766 |
|
return R_68K_TLS_GD32; |
| 767 |
|
|
| 768 |
|
case R_68K_TLS_LDM32: |
| 769 |
|
case R_68K_TLS_LDM16: |
| 770 |
|
case R_68K_TLS_LDM8: |
| 771 |
|
return R_68K_TLS_LDM32; |
| 772 |
|
|
| 773 |
|
case R_68K_TLS_IE32: |
| 774 |
|
case R_68K_TLS_IE16: |
| 775 |
|
case R_68K_TLS_IE8: |
| 776 |
|
return R_68K_TLS_IE32; |
| 777 |
|
|
| 778 |
|
default: |
| 779 |
|
BFD_ASSERT (FALSE); |
| 780 |
|
return 0; |
| 781 |
|
} |
| 782 |
|
} |
| 783 |
|
|
| 784 |
|
/* Return size of the GOT entry offset for relocation R_TYPE. */ |
| 785 |
|
|
| 786 |
|
static enum elf_m68k_got_offset_size |
| 787 |
|
elf_m68k_reloc_got_offset_size (enum elf_m68k_reloc_type r_type) |
| 788 |
|
{ |
| 789 |
|
switch (r_type) |
| 790 |
|
{ |
| 791 |
|
case R_68K_GOT32: case R_68K_GOT16: case R_68K_GOT8: |
| 792 |
|
case R_68K_GOT32O: case R_68K_TLS_GD32: case R_68K_TLS_LDM32: |
| 793 |
|
case R_68K_TLS_IE32: |
| 794 |
|
return R_32; |
| 795 |
|
|
| 796 |
|
case R_68K_GOT16O: case R_68K_TLS_GD16: case R_68K_TLS_LDM16: |
| 797 |
|
case R_68K_TLS_IE16: |
| 798 |
|
return R_16; |
| 799 |
|
|
| 800 |
|
case R_68K_GOT8O: case R_68K_TLS_GD8: case R_68K_TLS_LDM8: |
| 801 |
|
case R_68K_TLS_IE8: |
| 802 |
|
return R_8; |
| 803 |
|
|
| 804 |
|
default: |
| 805 |
|
BFD_ASSERT (FALSE); |
| 806 |
|
return 0; |
| 807 |
|
} |
| 808 |
|
} |
| 809 |
|
|
| 810 |
|
/* Return number of GOT entries we need to allocate in GOT for |
| 811 |
|
relocation R_TYPE. */ |
| 812 |
|
|
| 813 |
|
static bfd_vma |
| 814 |
|
elf_m68k_reloc_got_n_slots (enum elf_m68k_reloc_type r_type) |
| 815 |
|
{ |
| 816 |
|
switch (elf_m68k_reloc_got_type (r_type)) |
| 817 |
|
{ |
| 818 |
|
case R_68K_GOT32O: |
| 819 |
|
case R_68K_TLS_IE32: |
| 820 |
|
return 1; |
| 821 |
|
|
| 822 |
|
case R_68K_TLS_GD32: |
| 823 |
|
case R_68K_TLS_LDM32: |
| 824 |
|
return 2; |
| 825 |
|
|
| 826 |
|
default: |
| 827 |
|
BFD_ASSERT (FALSE); |
| 828 |
|
return 0; |
| 829 |
|
} |
| 830 |
|
} |
| 831 |
|
|
| 832 |
|
/* Return TRUE if relocation R_TYPE is a TLS one. */ |
| 833 |
|
|
| 834 |
|
static bfd_boolean |
| 835 |
|
elf_m68k_reloc_tls_p (enum elf_m68k_reloc_type r_type) |
| 836 |
|
{ |
| 837 |
|
switch (r_type) |
| 838 |
|
{ |
| 839 |
|
case R_68K_TLS_GD32: case R_68K_TLS_GD16: case R_68K_TLS_GD8: |
| 840 |
|
case R_68K_TLS_LDM32: case R_68K_TLS_LDM16: case R_68K_TLS_LDM8: |
| 841 |
|
case R_68K_TLS_LDO32: case R_68K_TLS_LDO16: case R_68K_TLS_LDO8: |
| 842 |
|
case R_68K_TLS_IE32: case R_68K_TLS_IE16: case R_68K_TLS_IE8: |
| 843 |
|
case R_68K_TLS_LE32: case R_68K_TLS_LE16: case R_68K_TLS_LE8: |
| 844 |
|
case R_68K_TLS_DTPMOD32: case R_68K_TLS_DTPREL32: case R_68K_TLS_TPREL32: |
| 845 |
|
return TRUE; |
| 846 |
|
|
| 847 |
|
default: |
| 848 |
|
return FALSE; |
| 849 |
|
} |
| 850 |
|
} |
| 851 |
|
|
| 852 |
/* Data structure representing a single GOT. */ |
/* Data structure representing a single GOT. */ |
| 853 |
struct elf_m68k_got |
struct elf_m68k_got |
| 854 |
{ |
{ |
| 857 |
R_68K_GOT8O entries. */ |
R_68K_GOT8O entries. */ |
| 858 |
htab_t entries; |
htab_t entries; |
| 859 |
|
|
| 860 |
/* Number of R_68K_GOT8O entries in this GOT. |
/* Number of R_x slots in this GOT. Some (e.g., TLS) entries require |
| 861 |
This is used to detect the overflow of number of such entries. */ |
several GOT slots. |
| 862 |
bfd_vma rel_8o_n_entries; |
|
| 863 |
|
n_slots[R_8] is the count of R_8 slots in this GOT. |
| 864 |
/* Cumulative count of R_68K_GOT8O and R_68K_GOT16O entries in this GOT. |
n_slots[R_16] is the cumulative count of R_8 and R_16 slots |
| 865 |
This is used to detect the overflow of number of such entries. */ |
in this GOT. |
| 866 |
bfd_vma rel_8o_16o_n_entries; |
n_slots[R_32] is the cumulative count of R_8, R_16 and R_32 slots |
| 867 |
|
in this GOT. This is the total number of slots. */ |
| 868 |
|
bfd_vma n_slots[R_LAST]; |
| 869 |
|
|
| 870 |
/* Number of local (entry->key_.h == NULL) entries in this GOT. |
/* Number of local (entry->key_.h == NULL) slots in this GOT. |
| 871 |
This is only used to properly calculate size of .rela.got section; |
This is only used to properly calculate size of .rela.got section; |
| 872 |
see elf_m68k_partition_multi_got. */ |
see elf_m68k_partition_multi_got. */ |
| 873 |
bfd_vma local_n_entries; |
bfd_vma local_n_slots; |
| 874 |
|
|
| 875 |
/* Offset of this GOT relative to beginning of .got section. */ |
/* Offset of this GOT relative to beginning of .got section. */ |
| 876 |
bfd_vma offset; |
bfd_vma offset; |
| 909 |
{ |
{ |
| 910 |
struct elf_link_hash_table root; |
struct elf_link_hash_table root; |
| 911 |
|
|
| 912 |
/* Small local sym to section mapping cache. */ |
/* Small local sym cache. */ |
| 913 |
struct sym_sec_cache sym_sec; |
struct sym_cache sym_cache; |
| 914 |
|
|
| 915 |
/* The PLT format used by this link, or NULL if the format has not |
/* The PLT format used by this link, or NULL if the format has not |
| 916 |
yet been chosen. */ |
yet been chosen. */ |
| 989 |
return NULL; |
return NULL; |
| 990 |
} |
} |
| 991 |
|
|
| 992 |
ret->sym_sec.abfd = NULL; |
ret->sym_cache.abfd = NULL; |
| 993 |
ret->plt_info = NULL; |
ret->plt_info = NULL; |
| 994 |
ret->local_gp_p = FALSE; |
ret->local_gp_p = FALSE; |
| 995 |
ret->use_neg_got_offsets_p = FALSE; |
ret->use_neg_got_offsets_p = FALSE; |
| 1277 |
|
|
| 1278 |
Notes: |
Notes: |
| 1279 |
|
|
| 1280 |
GOT entry type: We have 3 types of GOT entries. |
GOT entry type: We have several types of GOT entries. |
| 1281 |
* R_68K_GOT8O type is used in entries for symbols that have |
* R_8 type is used in entries for symbols that have at least one |
| 1282 |
at least one R_68K_GOT8O relocation. We can have at most 0x40 |
R_68K_GOT8O or R_68K_TLS_*8 relocation. We can have at most 0x40 |
| 1283 |
such entries in one GOT. |
such entries in one GOT. |
| 1284 |
* R_68K_GOT16O type is used in entries for symbols that have |
* R_16 type is used in entries for symbols that have at least one |
| 1285 |
at least one R_68K_GOT16O relocation and no R_68K_GOT8O relocations. |
R_68K_GOT16O or R_68K_TLS_*16 relocation and no R_8 relocations. |
| 1286 |
We can have at most 0x4000 such entries in one GOT. |
We can have at most 0x4000 such entries in one GOT. |
| 1287 |
* R_68K_GOT32O type is used in all other cases. We can have as many |
* R_32 type is used in all other cases. We can have as many |
| 1288 |
such entries in one GOT as we like. |
such entries in one GOT as we'd like. |
| 1289 |
When counting relocations we have to include the count of the smaller |
When counting relocations we have to include the count of the smaller |
| 1290 |
ranged relocations in the counts of the larger ranged ones in order |
ranged relocations in the counts of the larger ranged ones in order |
| 1291 |
to correctly detect overflow. |
to correctly detect overflow. |
| 1292 |
|
|
| 1293 |
Sorting the GOT: In each GOT starting offsets are assigned to |
Sorting the GOT: In each GOT starting offsets are assigned to |
| 1294 |
R_68K_GOT8O entries, which are followed by R_68K_GOT16O entries, and |
R_8 entries, which are followed by R_16 entries, and |
| 1295 |
R_68K_GOT32O entries go at the end. See finalize_got_offsets for details. |
R_32 entries go at the end. See finalize_got_offsets for details. |
| 1296 |
|
|
| 1297 |
Negative GOT offsets: To double usable offset range of GOTs we use |
Negative GOT offsets: To double usable offset range of GOTs we use |
| 1298 |
negative offsets. As we assign entries with GOT offsets relative to |
negative offsets. As we assign entries with GOT offsets relative to |
| 1316 |
/* Initialize GOT. */ |
/* Initialize GOT. */ |
| 1317 |
|
|
| 1318 |
static void |
static void |
| 1319 |
elf_m68k_init_got (struct elf_m68k_got *got, |
elf_m68k_init_got (struct elf_m68k_got *got) |
| 1320 |
htab_t entries, |
{ |
| 1321 |
bfd_vma rel_8o_n_entries, |
got->entries = NULL; |
| 1322 |
bfd_vma rel_8o_16o_n_entries, |
got->n_slots[R_8] = 0; |
| 1323 |
bfd_vma local_n_entries, |
got->n_slots[R_16] = 0; |
| 1324 |
bfd_vma offset) |
got->n_slots[R_32] = 0; |
| 1325 |
{ |
got->local_n_slots = 0; |
| 1326 |
got->entries = entries; |
got->offset = (bfd_vma) -1; |
|
got->rel_8o_n_entries = rel_8o_n_entries; |
|
|
got->rel_8o_16o_n_entries = rel_8o_16o_n_entries; |
|
|
got->local_n_entries = local_n_entries; |
|
|
got->offset = offset; |
|
| 1327 |
} |
} |
| 1328 |
|
|
| 1329 |
/* Destruct GOT. */ |
/* Destruct GOT. */ |
| 1350 |
if (got == NULL) |
if (got == NULL) |
| 1351 |
return NULL; |
return NULL; |
| 1352 |
|
|
| 1353 |
elf_m68k_init_got (got, NULL, 0, 0, 0, (bfd_vma) -1); |
elf_m68k_init_got (got); |
| 1354 |
|
|
| 1355 |
return got; |
return got; |
| 1356 |
} |
} |
| 1360 |
static void |
static void |
| 1361 |
elf_m68k_init_got_entry_key (struct elf_m68k_got_entry_key *key, |
elf_m68k_init_got_entry_key (struct elf_m68k_got_entry_key *key, |
| 1362 |
struct elf_link_hash_entry *h, |
struct elf_link_hash_entry *h, |
| 1363 |
const bfd *abfd, unsigned long symndx) |
const bfd *abfd, unsigned long symndx, |
| 1364 |
|
enum elf_m68k_reloc_type reloc_type) |
| 1365 |
{ |
{ |
| 1366 |
if (h != NULL) |
if (elf_m68k_reloc_got_type (reloc_type) == R_68K_TLS_LDM32) |
| 1367 |
|
/* All TLS_LDM relocations share a single GOT entry. */ |
| 1368 |
|
{ |
| 1369 |
|
key->bfd = NULL; |
| 1370 |
|
key->symndx = 0; |
| 1371 |
|
} |
| 1372 |
|
else if (h != NULL) |
| 1373 |
|
/* Global symbols are identified with their got_entry_key. */ |
| 1374 |
{ |
{ |
| 1375 |
key->bfd = NULL; |
key->bfd = NULL; |
| 1376 |
key->symndx = elf_m68k_hash_entry (h)->got_entry_key; |
key->symndx = elf_m68k_hash_entry (h)->got_entry_key; |
| 1377 |
BFD_ASSERT (key->symndx != 0); |
BFD_ASSERT (key->symndx != 0); |
| 1378 |
} |
} |
| 1379 |
else |
else |
| 1380 |
|
/* Local symbols are identified by BFD they appear in and symndx. */ |
| 1381 |
{ |
{ |
| 1382 |
key->bfd = abfd; |
key->bfd = abfd; |
| 1383 |
key->symndx = symndx; |
key->symndx = symndx; |
| 1384 |
} |
} |
| 1385 |
|
|
| 1386 |
|
key->type = reloc_type; |
| 1387 |
} |
} |
| 1388 |
|
|
| 1389 |
/* Calculate hash of got_entry. |
/* Calculate hash of got_entry. |
| 1396 |
|
|
| 1397 |
key = &((const struct elf_m68k_got_entry *) _entry)->key_; |
key = &((const struct elf_m68k_got_entry *) _entry)->key_; |
| 1398 |
|
|
| 1399 |
return key->symndx + (key->bfd != NULL |
return (key->symndx |
| 1400 |
? (int) key->bfd->id |
+ (key->bfd != NULL ? (int) key->bfd->id : -1) |
| 1401 |
: -1); |
+ elf_m68k_reloc_got_type (key->type)); |
| 1402 |
} |
} |
| 1403 |
|
|
| 1404 |
/* Check if two got entries are equal. */ |
/* Check if two got entries are equal. */ |
| 1413 |
key2 = &((const struct elf_m68k_got_entry *) _entry2)->key_; |
key2 = &((const struct elf_m68k_got_entry *) _entry2)->key_; |
| 1414 |
|
|
| 1415 |
return (key1->bfd == key2->bfd |
return (key1->bfd == key2->bfd |
| 1416 |
&& key1->symndx == key2->symndx); |
&& key1->symndx == key2->symndx |
| 1417 |
|
&& (elf_m68k_reloc_got_type (key1->type) |
| 1418 |
|
== elf_m68k_reloc_got_type (key2->type))); |
| 1419 |
} |
} |
| 1420 |
|
|
| 1421 |
/* Maximal number of R_68K_GOT8O entries in a single GOT. */ |
/* When using negative offsets, we allocate one extra R_8, one extra R_16 |
| 1422 |
#define ELF_M68K_REL_8O_MAX_N_ENTRIES_IN_GOT(INFO) \ |
and one extra R_32 slots to simplify handling of 2-slot entries during |
| 1423 |
|
offset allocation -- hence -1 for R_8 slots and -2 for R_16 slots. */ |
| 1424 |
|
|
| 1425 |
|
/* Maximal number of R_8 slots in a single GOT. */ |
| 1426 |
|
#define ELF_M68K_R_8_MAX_N_SLOTS_IN_GOT(INFO) \ |
| 1427 |
(elf_m68k_hash_table (INFO)->use_neg_got_offsets_p \ |
(elf_m68k_hash_table (INFO)->use_neg_got_offsets_p \ |
| 1428 |
? 0x40 \ |
? (0x40 - 1) \ |
| 1429 |
: 0x20) |
: 0x20) |
| 1430 |
|
|
| 1431 |
/* Maximal number of R_68K_GOT8O and R_68K_GOT16O entries in a single GOT. */ |
/* Maximal number of R_8 and R_16 slots in a single GOT. */ |
| 1432 |
#define ELF_M68K_REL_8O_16O_MAX_N_ENTRIES_IN_GOT(INFO) \ |
#define ELF_M68K_R_8_16_MAX_N_SLOTS_IN_GOT(INFO) \ |
| 1433 |
(elf_m68k_hash_table (INFO)->use_neg_got_offsets_p \ |
(elf_m68k_hash_table (INFO)->use_neg_got_offsets_p \ |
| 1434 |
? 0x4000 \ |
? (0x4000 - 2) \ |
| 1435 |
: 0x2000) |
: 0x2000) |
| 1436 |
|
|
| 1437 |
/* SEARCH - simply search the hashtable, don't insert new entries or fail when |
/* SEARCH - simply search the hashtable, don't insert new entries or fail when |
| 1470 |
if (howto == SEARCH) |
if (howto == SEARCH) |
| 1471 |
return NULL; |
return NULL; |
| 1472 |
|
|
| 1473 |
got->entries = htab_try_create (ELF_M68K_REL_8O_MAX_N_ENTRIES_IN_GOT |
got->entries = htab_try_create (ELF_M68K_R_8_MAX_N_SLOTS_IN_GOT |
| 1474 |
(info), |
(info), |
| 1475 |
elf_m68k_got_entry_hash, |
elf_m68k_got_entry_hash, |
| 1476 |
elf_m68k_got_entry_eq, NULL); |
elf_m68k_got_entry_eq, NULL); |
| 1508 |
entry->key_ = *key; |
entry->key_ = *key; |
| 1509 |
|
|
| 1510 |
entry->u.s1.refcount = 0; |
entry->u.s1.refcount = 0; |
| 1511 |
entry->u.s1.type = R_68K_GOT32O; |
|
| 1512 |
|
/* Mark the entry as not initialized. */ |
| 1513 |
|
entry->key_.type = R_68K_max; |
| 1514 |
|
|
| 1515 |
*ptr = entry; |
*ptr = entry; |
| 1516 |
} |
} |
| 1528 |
/* Update GOT counters when merging entry of WAS type with entry of NEW type. |
/* Update GOT counters when merging entry of WAS type with entry of NEW type. |
| 1529 |
Return the value to which ENTRY's type should be set. */ |
Return the value to which ENTRY's type should be set. */ |
| 1530 |
|
|
| 1531 |
static int |
static enum elf_m68k_reloc_type |
| 1532 |
elf_m68k_update_got_entry_type (struct elf_m68k_got *got, int was, int new) |
elf_m68k_update_got_entry_type (struct elf_m68k_got *got, |
| 1533 |
{ |
enum elf_m68k_reloc_type was, |
| 1534 |
if (new == R_68K_GOT8O && was != R_68K_GOT8O) |
enum elf_m68k_reloc_type new) |
| 1535 |
/* NEW overrides WAS. */ |
{ |
| 1536 |
|
enum elf_m68k_got_offset_size was_size; |
| 1537 |
|
enum elf_m68k_got_offset_size new_size; |
| 1538 |
|
bfd_vma n_slots; |
| 1539 |
|
|
| 1540 |
|
if (was == R_68K_max) |
| 1541 |
|
/* The type of the entry is not initialized yet. */ |
| 1542 |
{ |
{ |
| 1543 |
++got->rel_8o_n_entries; |
/* Update all got->n_slots counters, including n_slots[R_32]. */ |
| 1544 |
|
was_size = R_LAST; |
| 1545 |
|
|
| 1546 |
if (was != R_68K_GOT16O) |
was = new; |
|
/* Update this counter too. */ |
|
|
++got->rel_8o_16o_n_entries; |
|
| 1547 |
} |
} |
|
else if (new == R_68K_GOT16O && was != R_68K_GOT8O && was != R_68K_GOT16O) |
|
|
/* NEW overrides WAS. */ |
|
|
++got->rel_8o_16o_n_entries; |
|
| 1548 |
else |
else |
| 1549 |
/* NEW doesn't override WAS. */ |
{ |
| 1550 |
new = was; |
/* !!! We, probably, should emit an error rather then fail on assert |
| 1551 |
|
in such a case. */ |
| 1552 |
|
BFD_ASSERT (elf_m68k_reloc_got_type (was) |
| 1553 |
|
== elf_m68k_reloc_got_type (new)); |
| 1554 |
|
|
| 1555 |
|
was_size = elf_m68k_reloc_got_offset_size (was); |
| 1556 |
|
} |
| 1557 |
|
|
| 1558 |
|
new_size = elf_m68k_reloc_got_offset_size (new); |
| 1559 |
|
n_slots = elf_m68k_reloc_got_n_slots (new); |
| 1560 |
|
|
| 1561 |
return new; |
while (was_size > new_size) |
| 1562 |
|
{ |
| 1563 |
|
--was_size; |
| 1564 |
|
got->n_slots[was_size] += n_slots; |
| 1565 |
|
} |
| 1566 |
|
|
| 1567 |
|
if (new > was) |
| 1568 |
|
/* Relocations are ordered from bigger got offset size to lesser, |
| 1569 |
|
so choose the relocation type with lesser offset size. */ |
| 1570 |
|
was = new; |
| 1571 |
|
|
| 1572 |
|
return was; |
| 1573 |
} |
} |
| 1574 |
|
|
| 1575 |
/* Update GOT counters when removing an entry of type TYPE. */ |
/* Update GOT counters when removing an entry of type TYPE. */ |
| 1576 |
|
|
| 1577 |
static void |
static void |
| 1578 |
elf_m68k_remove_got_entry_type (struct elf_m68k_got *got, int type) |
elf_m68k_remove_got_entry_type (struct elf_m68k_got *got, |
| 1579 |
|
enum elf_m68k_reloc_type type) |
| 1580 |
{ |
{ |
| 1581 |
switch (type) |
enum elf_m68k_got_offset_size os; |
| 1582 |
{ |
bfd_vma n_slots; |
|
case R_68K_GOT8O: |
|
|
BFD_ASSERT (got->rel_8o_n_entries > 0); |
|
|
|
|
|
--got->rel_8o_n_entries; |
|
|
/* FALLTHRU */ |
|
| 1583 |
|
|
| 1584 |
case R_68K_GOT16O: |
n_slots = elf_m68k_reloc_got_n_slots (type); |
|
BFD_ASSERT (got->rel_8o_16o_n_entries >= got->rel_8o_n_entries); |
|
|
|
|
|
--got->rel_8o_16o_n_entries; |
|
|
/* FALLTHRU */ |
|
| 1585 |
|
|
| 1586 |
case R_68K_GOT32O: |
/* Decrese counter of slots with offset size corresponding to TYPE |
| 1587 |
break; |
and all greater offset sizes. */ |
| 1588 |
|
for (os = elf_m68k_reloc_got_offset_size (type); os <= R_32; ++os) |
| 1589 |
|
{ |
| 1590 |
|
BFD_ASSERT (got->n_slots[os] >= n_slots); |
| 1591 |
|
|
| 1592 |
default: |
got->n_slots[os] -= n_slots; |
|
BFD_ASSERT (FALSE); |
|
| 1593 |
} |
} |
| 1594 |
} |
} |
| 1595 |
|
|
| 1601 |
elf_m68k_add_entry_to_got (struct elf_m68k_got *got, |
elf_m68k_add_entry_to_got (struct elf_m68k_got *got, |
| 1602 |
struct elf_link_hash_entry *h, |
struct elf_link_hash_entry *h, |
| 1603 |
const bfd *abfd, |
const bfd *abfd, |
| 1604 |
int type, unsigned long symndx, |
enum elf_m68k_reloc_type reloc_type, |
| 1605 |
|
unsigned long symndx, |
| 1606 |
struct bfd_link_info *info) |
struct bfd_link_info *info) |
| 1607 |
{ |
{ |
| 1608 |
struct elf_m68k_got_entry_key key_; |
struct elf_m68k_got_entry_key key_; |
| 1612 |
elf_m68k_hash_entry (h)->got_entry_key |
elf_m68k_hash_entry (h)->got_entry_key |
| 1613 |
= elf_m68k_multi_got (info)->global_symndx++; |
= elf_m68k_multi_got (info)->global_symndx++; |
| 1614 |
|
|
| 1615 |
elf_m68k_init_got_entry_key (&key_, h, abfd, symndx); |
elf_m68k_init_got_entry_key (&key_, h, abfd, symndx, reloc_type); |
| 1616 |
|
|
| 1617 |
entry = elf_m68k_get_got_entry (got, &key_, FIND_OR_CREATE, info); |
entry = elf_m68k_get_got_entry (got, &key_, FIND_OR_CREATE, info); |
| 1618 |
if (entry == NULL) |
if (entry == NULL) |
| 1619 |
return NULL; |
return NULL; |
| 1620 |
|
|
| 1621 |
|
/* Determine entry's type and update got->n_slots counters. */ |
| 1622 |
|
entry->key_.type = elf_m68k_update_got_entry_type (got, |
| 1623 |
|
entry->key_.type, |
| 1624 |
|
reloc_type); |
| 1625 |
|
|
| 1626 |
/* Update refcount. */ |
/* Update refcount. */ |
| 1627 |
++entry->u.s1.refcount; |
++entry->u.s1.refcount; |
| 1628 |
|
|
| 1630 |
/* We see this entry for the first time. */ |
/* We see this entry for the first time. */ |
| 1631 |
{ |
{ |
| 1632 |
if (entry->key_.bfd != NULL) |
if (entry->key_.bfd != NULL) |
| 1633 |
++got->local_n_entries; |
got->local_n_slots += elf_m68k_reloc_got_n_slots (entry->key_.type); |
| 1634 |
} |
} |
| 1635 |
|
|
| 1636 |
/* Determine entry's type and update got->rel_*_n_entries counters. */ |
BFD_ASSERT (got->n_slots[R_32] >= got->local_n_slots); |
|
entry->u.s1.type = elf_m68k_update_got_entry_type (got, entry->u.s1.type, |
|
|
type); |
|
| 1637 |
|
|
| 1638 |
if ((got->rel_8o_n_entries |
if ((got->n_slots[R_8] |
| 1639 |
> ELF_M68K_REL_8O_MAX_N_ENTRIES_IN_GOT (info)) |
> ELF_M68K_R_8_MAX_N_SLOTS_IN_GOT (info)) |
| 1640 |
|| (got->rel_8o_16o_n_entries |
|| (got->n_slots[R_16] |
| 1641 |
> ELF_M68K_REL_8O_16O_MAX_N_ENTRIES_IN_GOT (info))) |
> ELF_M68K_R_8_16_MAX_N_SLOTS_IN_GOT (info))) |
| 1642 |
/* This BFD has too many relocation. */ |
/* This BFD has too many relocation. */ |
| 1643 |
{ |
{ |
| 1644 |
if (got->rel_8o_n_entries |
if (got->n_slots[R_8] > ELF_M68K_R_8_MAX_N_SLOTS_IN_GOT (info)) |
|
> ELF_M68K_REL_8O_MAX_N_ENTRIES_IN_GOT (info)) |
|
| 1645 |
(*_bfd_error_handler) (_("%B: GOT overflow: " |
(*_bfd_error_handler) (_("%B: GOT overflow: " |
| 1646 |
"Number of R_68K_GOT8O relocations > %d"), |
"Number of relocations with 8-bit " |
| 1647 |
|
"offset > %d"), |
| 1648 |
abfd, |
abfd, |
| 1649 |
ELF_M68K_REL_8O_MAX_N_ENTRIES_IN_GOT (info)); |
ELF_M68K_R_8_MAX_N_SLOTS_IN_GOT (info)); |
| 1650 |
else |
else |
| 1651 |
(*_bfd_error_handler) (_("%B: GOT overflow: " |
(*_bfd_error_handler) (_("%B: GOT overflow: " |
| 1652 |
"Number of R_68K_GOT8O and R_68K_GOT16O " |
"Number of relocations with 8- or 16-bit " |
| 1653 |
"relocations > %d"), |
"offset > %d"), |
| 1654 |
abfd, |
abfd, |
| 1655 |
ELF_M68K_REL_8O_16O_MAX_N_ENTRIES_IN_GOT (info)); |
ELF_M68K_R_8_16_MAX_N_SLOTS_IN_GOT (info)); |
| 1656 |
|
|
| 1657 |
return NULL; |
return NULL; |
| 1658 |
} |
} |
| 1799 |
const struct elf_m68k_got_entry *entry1; |
const struct elf_m68k_got_entry *entry1; |
| 1800 |
struct elf_m68k_can_merge_gots_arg *arg; |
struct elf_m68k_can_merge_gots_arg *arg; |
| 1801 |
const struct elf_m68k_got_entry *entry2; |
const struct elf_m68k_got_entry *entry2; |
| 1802 |
int type; |
enum elf_m68k_reloc_type type; |
| 1803 |
|
|
| 1804 |
entry1 = (const struct elf_m68k_got_entry *) *_entry_ptr; |
entry1 = (const struct elf_m68k_got_entry *) *_entry_ptr; |
| 1805 |
arg = (struct elf_m68k_can_merge_gots_arg *) _arg; |
arg = (struct elf_m68k_can_merge_gots_arg *) _arg; |
| 1807 |
entry2 = elf_m68k_get_got_entry (arg->big, &entry1->key_, SEARCH, NULL); |
entry2 = elf_m68k_get_got_entry (arg->big, &entry1->key_, SEARCH, NULL); |
| 1808 |
|
|
| 1809 |
if (entry2 != NULL) |
if (entry2 != NULL) |
| 1810 |
|
/* We found an existing entry. Check if we should update it. */ |
| 1811 |
{ |
{ |
| 1812 |
type = elf_m68k_update_got_entry_type (arg->diff, entry2->u.s1.type, |
type = elf_m68k_update_got_entry_type (arg->diff, |
| 1813 |
entry1->u.s1.type); |
entry2->key_.type, |
| 1814 |
|
entry1->key_.type); |
| 1815 |
|
|
| 1816 |
if (type == entry2->u.s1.type) |
if (type == entry2->key_.type) |
| 1817 |
/* ENTRY1 doesn't update data in ENTRY2. Skip it. |
/* ENTRY1 doesn't update data in ENTRY2. Skip it. |
| 1818 |
To skip creation of difference entry we use the type, |
To skip creation of difference entry we use the type, |
| 1819 |
which we won't see in GOT entries for sure. */ |
which we won't see in GOT entries for sure. */ |
| 1820 |
type = R_68K_32; |
type = R_68K_max; |
| 1821 |
} |
} |
| 1822 |
else |
else |
| 1823 |
|
/* We didn't find the entry. Add entry1 to DIFF. */ |
| 1824 |
{ |
{ |
| 1825 |
BFD_ASSERT (entry1->u.s1.type != R_68K_32); |
BFD_ASSERT (entry1->key_.type != R_68K_max); |
| 1826 |
|
|
| 1827 |
type = elf_m68k_update_got_entry_type (arg->diff, R_68K_GOT32O, |
type = elf_m68k_update_got_entry_type (arg->diff, |
| 1828 |
entry1->u.s1.type); |
R_68K_max, entry1->key_.type); |
| 1829 |
|
|
|
/* Update local counter. */ |
|
| 1830 |
if (entry1->key_.bfd != NULL) |
if (entry1->key_.bfd != NULL) |
| 1831 |
++arg->diff->local_n_entries; |
arg->diff->local_n_slots += elf_m68k_reloc_got_n_slots (type); |
| 1832 |
} |
} |
| 1833 |
|
|
| 1834 |
if (type != R_68K_32) |
if (type != R_68K_max) |
| 1835 |
/* Create an entry in DIFF. */ |
/* Create an entry in DIFF. */ |
| 1836 |
{ |
{ |
| 1837 |
struct elf_m68k_got_entry *entry; |
struct elf_m68k_got_entry *entry; |
| 1844 |
return 0; |
return 0; |
| 1845 |
} |
} |
| 1846 |
|
|
| 1847 |
entry->u.s1.type = type; |
entry->key_.type = type; |
| 1848 |
} |
} |
| 1849 |
|
|
| 1850 |
return 1; |
return 1; |
| 1877 |
} |
} |
| 1878 |
|
|
| 1879 |
/* Check for overflow. */ |
/* Check for overflow. */ |
| 1880 |
if ((big->rel_8o_n_entries + arg_.diff->rel_8o_n_entries |
if ((big->n_slots[R_8] + arg_.diff->n_slots[R_8] |
| 1881 |
> ELF_M68K_REL_8O_MAX_N_ENTRIES_IN_GOT (info)) |
> ELF_M68K_R_8_MAX_N_SLOTS_IN_GOT (info)) |
| 1882 |
|| (big->rel_8o_16o_n_entries + arg_.diff->rel_8o_16o_n_entries |
|| (big->n_slots[R_16] + arg_.diff->n_slots[R_16] |
| 1883 |
> ELF_M68K_REL_8O_16O_MAX_N_ENTRIES_IN_GOT (info))) |
> ELF_M68K_R_8_16_MAX_N_SLOTS_IN_GOT (info))) |
| 1884 |
return FALSE; |
return FALSE; |
| 1885 |
|
|
| 1886 |
return TRUE; |
return TRUE; |
| 1921 |
|
|
| 1922 |
BFD_ASSERT (to->u.s1.refcount == 0); |
BFD_ASSERT (to->u.s1.refcount == 0); |
| 1923 |
/* All we need to merge is TYPE. */ |
/* All we need to merge is TYPE. */ |
| 1924 |
to->u.s1.type = from->u.s1.type; |
to->key_.type = from->key_.type; |
| 1925 |
|
|
| 1926 |
return 1; |
return 1; |
| 1927 |
} |
} |
| 1948 |
return FALSE; |
return FALSE; |
| 1949 |
|
|
| 1950 |
/* Merge counters. */ |
/* Merge counters. */ |
| 1951 |
big->rel_8o_n_entries += diff->rel_8o_n_entries; |
big->n_slots[R_8] += diff->n_slots[R_8]; |
| 1952 |
big->rel_8o_16o_n_entries += diff->rel_8o_16o_n_entries; |
big->n_slots[R_16] += diff->n_slots[R_16]; |
| 1953 |
big->local_n_entries += diff->local_n_entries; |
big->n_slots[R_32] += diff->n_slots[R_32]; |
| 1954 |
|
big->local_n_slots += diff->local_n_slots; |
| 1955 |
} |
} |
| 1956 |
else |
else |
| 1957 |
/* DIFF is empty. */ |
/* DIFF is empty. */ |
| 1958 |
{ |
{ |
| 1959 |
BFD_ASSERT (diff->rel_8o_n_entries == 0); |
BFD_ASSERT (diff->n_slots[R_8] == 0); |
| 1960 |
BFD_ASSERT (diff->rel_8o_16o_n_entries == 0); |
BFD_ASSERT (diff->n_slots[R_16] == 0); |
| 1961 |
BFD_ASSERT (diff->local_n_entries == 0); |
BFD_ASSERT (diff->n_slots[R_32] == 0); |
| 1962 |
|
BFD_ASSERT (diff->local_n_slots == 0); |
| 1963 |
} |
} |
| 1964 |
|
|
| 1965 |
BFD_ASSERT (!elf_m68k_hash_table (info)->allow_multigot_p |
BFD_ASSERT (!elf_m68k_hash_table (info)->allow_multigot_p |
| 1966 |
|| ((big->rel_8o_n_entries |
|| ((big->n_slots[R_8] |
| 1967 |
<= ELF_M68K_REL_8O_MAX_N_ENTRIES_IN_GOT (info)) |
<= ELF_M68K_R_8_MAX_N_SLOTS_IN_GOT (info)) |
| 1968 |
&& (big->rel_8o_16o_n_entries |
&& (big->n_slots[R_16] |
| 1969 |
<= ELF_M68K_REL_8O_16O_MAX_N_ENTRIES_IN_GOT (info)))); |
<= ELF_M68K_R_8_16_MAX_N_SLOTS_IN_GOT (info)))); |
| 1970 |
|
|
| 1971 |
return TRUE; |
return TRUE; |
| 1972 |
} |
} |
| 1973 |
|
|
| 1974 |
struct elf_m68k_finalize_got_offsets_arg |
struct elf_m68k_finalize_got_offsets_arg |
| 1975 |
{ |
{ |
| 1976 |
/* Offset for the next R_68K_GOT8O entry. */ |
/* Ranges of the offsets for GOT entries. |
| 1977 |
bfd_vma rel_8o_offset; |
R_x entries receive offsets between offset1[R_x] and offset2[R_x]. |
| 1978 |
|
R_x is R_8, R_16 and R_32. */ |
| 1979 |
/* Offset for the next R_68K_GOT16O entry. */ |
bfd_vma *offset1; |
| 1980 |
bfd_vma rel_16o_offset; |
bfd_vma *offset2; |
|
|
|
|
/* Offset for the next R_68K_GOT32O entry. */ |
|
|
bfd_vma rel_32o_offset; |
|
|
|
|
|
/* Should we use negative (relative to GP) offsets for GOT entries. */ |
|
|
bfd_boolean use_neg_got_offsets_p; |
|
|
|
|
|
/* Offset of this GOT relative to .got section. */ |
|
|
bfd_vma got_offset; |
|
| 1981 |
|
|
| 1982 |
/* Mapping from global symndx to global symbols. |
/* Mapping from global symndx to global symbols. |
| 1983 |
This is used to build lists of got entries for global symbols. */ |
This is used to build lists of got entries for global symbols. */ |
| 1984 |
struct elf_m68k_link_hash_entry **symndx2h; |
struct elf_m68k_link_hash_entry **symndx2h; |
| 1985 |
|
|
| 1986 |
|
bfd_vma n_ldm_entries; |
| 1987 |
}; |
}; |
| 1988 |
|
|
| 1989 |
/* Assign ENTRY an offset. Build list of GOT entries for global symbols |
/* Assign ENTRY an offset. Build list of GOT entries for global symbols |
| 1995 |
struct elf_m68k_got_entry *entry; |
struct elf_m68k_got_entry *entry; |
| 1996 |
struct elf_m68k_finalize_got_offsets_arg *arg; |
struct elf_m68k_finalize_got_offsets_arg *arg; |
| 1997 |
|
|
| 1998 |
|
enum elf_m68k_got_offset_size got_offset_size; |
| 1999 |
|
bfd_vma entry_size; |
| 2000 |
|
|
| 2001 |
entry = (struct elf_m68k_got_entry *) *entry_ptr; |
entry = (struct elf_m68k_got_entry *) *entry_ptr; |
| 2002 |
arg = (struct elf_m68k_finalize_got_offsets_arg *) _arg; |
arg = (struct elf_m68k_finalize_got_offsets_arg *) _arg; |
| 2003 |
|
|
| 2004 |
/* This should be a fresh entry created in elf_m68k_can_merge_gots. */ |
/* This should be a fresh entry created in elf_m68k_can_merge_gots. */ |
| 2005 |
BFD_ASSERT (entry->u.s1.refcount == 0); |
BFD_ASSERT (entry->u.s1.refcount == 0); |
| 2006 |
|
|
| 2007 |
switch (entry->u.s1.type) |
/* Get GOT offset size for the entry . */ |
| 2008 |
{ |
got_offset_size = elf_m68k_reloc_got_offset_size (entry->key_.type); |
|
case R_68K_GOT8O: |
|
|
entry->u.s2.offset = arg->rel_8o_offset; |
|
|
|
|
|
if (arg->use_neg_got_offsets_p) |
|
|
{ |
|
|
if (arg->rel_8o_offset >= arg->got_offset) |
|
|
/* We've assigned a positive offset to this entry, |
|
|
next entry should get (-abs(offset) - 4). */ |
|
|
arg->rel_8o_offset = (arg->got_offset |
|
|
- (arg->rel_8o_offset - arg->got_offset) |
|
|
- 4); |
|
|
else |
|
|
/* We've assigned a negative offset to this entry, |
|
|
next entry should get (+abs(offset) + 0). */ |
|
|
arg->rel_8o_offset = (arg->got_offset |
|
|
+ (arg->got_offset - arg->rel_8o_offset)); |
|
|
} |
|
|
else |
|
|
/* Next entry will simply get next offset. */ |
|
|
arg->rel_8o_offset += 4; |
|
|
|
|
|
break; |
|
|
|
|
|
case R_68K_GOT16O: |
|
|
entry->u.s2.offset = arg->rel_16o_offset; |
|
|
|
|
|
if (arg->use_neg_got_offsets_p) |
|
|
{ |
|
|
if (arg->rel_16o_offset >= arg->got_offset) |
|
|
/* We've assigned a positive offset to this entry, |
|
|
next entry should get (-abs(offset) - 4). */ |
|
|
arg->rel_16o_offset = (arg->got_offset |
|
|
- (arg->rel_16o_offset - arg->got_offset) |
|
|
- 4); |
|
|
else |
|
|
/* We've assigned a negative offset to this entry, |
|
|
next entry should get (+abs(offset) + 0). */ |
|
|
arg->rel_16o_offset = (arg->got_offset |
|
|
+ (arg->got_offset - arg->rel_16o_offset)); |
|
|
} |
|
|
else |
|
|
/* Next entry will simply get next offset. */ |
|
|
arg->rel_16o_offset += 4; |
|
|
|
|
|
break; |
|
|
|
|
|
case R_68K_GOT32O: |
|
|
entry->u.s2.offset = arg->rel_32o_offset; |
|
| 2009 |
|
|
| 2010 |
if (arg->use_neg_got_offsets_p) |
/* Calculate entry size in bytes. */ |
| 2011 |
{ |
entry_size = 4 * elf_m68k_reloc_got_n_slots (entry->key_.type); |
|
if (arg->rel_32o_offset >= arg->got_offset) |
|
|
/* We've assigned a positive offset to this entry, |
|
|
next entry should get (-abs(offset) - 4). */ |
|
|
arg->rel_32o_offset = (arg->got_offset |
|
|
- (arg->rel_32o_offset - arg->got_offset) |
|
|
- 4); |
|
|
else |
|
|
/* We've assigned a negative offset to this entry, |
|
|
next entry should get (+abs(offset) + 0). */ |
|
|
arg->rel_32o_offset = (arg->got_offset |
|
|
+ (arg->got_offset - arg->rel_32o_offset)); |
|
|
} |
|
|
else |
|
|
/* Next entry will simply get next offset. */ |
|
|
arg->rel_32o_offset += 4; |
|
| 2012 |
|
|
| 2013 |
break; |
/* Check if we should switch to negative range of the offsets. */ |
| 2014 |
|
if (arg->offset1[got_offset_size] + entry_size |
| 2015 |
default: |
> arg->offset2[got_offset_size]) |
| 2016 |
BFD_ASSERT (FALSE); |
{ |
| 2017 |
break; |
/* Verify that this is the only switch to negative range for |
| 2018 |
} |
got_offset_size. If this assertion fails, then we've miscalculated |
| 2019 |
|
range for got_offset_size entries in |
| 2020 |
|
elf_m68k_finalize_got_offsets. */ |
| 2021 |
|
BFD_ASSERT (arg->offset2[got_offset_size] |
| 2022 |
|
!= arg->offset2[-(int) got_offset_size - 1]); |
| 2023 |
|
|
| 2024 |
|
/* Switch. */ |
| 2025 |
|
arg->offset1[got_offset_size] = arg->offset1[-(int) got_offset_size - 1]; |
| 2026 |
|
arg->offset2[got_offset_size] = arg->offset2[-(int) got_offset_size - 1]; |
| 2027 |
|
|
| 2028 |
|
/* Verify that now we have enough room for the entry. */ |
| 2029 |
|
BFD_ASSERT (arg->offset1[got_offset_size] + entry_size |
| 2030 |
|
<= arg->offset2[got_offset_size]); |
| 2031 |
|
} |
| 2032 |
|
|
| 2033 |
|
/* Assign offset to entry. */ |
| 2034 |
|
entry->u.s2.offset = arg->offset1[got_offset_size]; |
| 2035 |
|
arg->offset1[got_offset_size] += entry_size; |
| 2036 |
|
|
| 2037 |
if (entry->key_.bfd == NULL) |
if (entry->key_.bfd == NULL) |
| 2038 |
/* Hook up this entry into the list of got_entries of H. */ |
/* Hook up this entry into the list of got_entries of H. */ |
| 2039 |
{ |
{ |
| 2040 |
struct elf_m68k_link_hash_entry *h; |
struct elf_m68k_link_hash_entry *h; |
| 2041 |
|
|
|
BFD_ASSERT (entry->key_.symndx != 0); |
|
| 2042 |
h = arg->symndx2h[entry->key_.symndx]; |
h = arg->symndx2h[entry->key_.symndx]; |
| 2043 |
BFD_ASSERT (h != NULL); |
if (h != NULL) |
| 2044 |
|
{ |
| 2045 |
|
entry->u.s2.next = h->glist; |
| 2046 |
|
h->glist = entry; |
| 2047 |
|
} |
| 2048 |
|
else |
| 2049 |
|
/* This should be the entry for TLS_LDM relocation then. */ |
| 2050 |
|
{ |
| 2051 |
|
BFD_ASSERT ((elf_m68k_reloc_got_type (entry->key_.type) |
| 2052 |
|
== R_68K_TLS_LDM32) |
| 2053 |
|
&& entry->key_.symndx == 0); |
| 2054 |
|
|
| 2055 |
entry->u.s2.next = h->glist; |
++arg->n_ldm_entries; |
| 2056 |
h->glist = entry; |
} |
| 2057 |
} |
} |
| 2058 |
else |
else |
| 2059 |
/* This entry is for local symbol. */ |
/* This entry is for local symbol. */ |
| 2066 |
should use negative offsets. |
should use negative offsets. |
| 2067 |
Build list of GOT entries for global symbols along the way. |
Build list of GOT entries for global symbols along the way. |
| 2068 |
SYMNDX2H is mapping from global symbol indices to actual |
SYMNDX2H is mapping from global symbol indices to actual |
| 2069 |
global symbols. */ |
global symbols. |
| 2070 |
|
Return offset at which next GOT should start. */ |
| 2071 |
|
|
| 2072 |
static void |
static void |
| 2073 |
elf_m68k_finalize_got_offsets (struct elf_m68k_got *got, |
elf_m68k_finalize_got_offsets (struct elf_m68k_got *got, |
| 2074 |
bfd_boolean use_neg_got_offsets_p, |
bfd_boolean use_neg_got_offsets_p, |
| 2075 |
struct elf_m68k_link_hash_entry **symndx2h) |
struct elf_m68k_link_hash_entry **symndx2h, |
| 2076 |
|
bfd_vma *final_offset, bfd_vma *n_ldm_entries) |
| 2077 |
{ |
{ |
| 2078 |
struct elf_m68k_finalize_got_offsets_arg arg_; |
struct elf_m68k_finalize_got_offsets_arg arg_; |
| 2079 |
|
bfd_vma offset1_[2 * R_LAST]; |
| 2080 |
|
bfd_vma offset2_[2 * R_LAST]; |
| 2081 |
|
int i; |
| 2082 |
|
bfd_vma start_offset; |
| 2083 |
|
|
| 2084 |
BFD_ASSERT (got->offset != (bfd_vma) -1); |
BFD_ASSERT (got->offset != (bfd_vma) -1); |
| 2085 |
|
|
| 2086 |
/* We set entry offsets relative to the .got section (and not the |
/* We set entry offsets relative to the .got section (and not the |
| 2087 |
start of a particular GOT), so that we can use them in |
start of a particular GOT), so that we can use them in |
| 2088 |
finish_dynamic_symbol without needing to know the GOT they come |
finish_dynamic_symbol without needing to know the GOT which they come |
| 2089 |
from. */ |
from. */ |
| 2090 |
|
|
| 2091 |
|
/* Put offset1 in the middle of offset1_, same for offset2. */ |
| 2092 |
|
arg_.offset1 = offset1_ + R_LAST; |
| 2093 |
|
arg_.offset2 = offset2_ + R_LAST; |
| 2094 |
|
|
| 2095 |
|
start_offset = got->offset; |
| 2096 |
|
|
| 2097 |
if (use_neg_got_offsets_p) |
if (use_neg_got_offsets_p) |
| 2098 |
|
/* Setup both negative and positive ranges for R_8, R_16 and R_32. */ |
| 2099 |
|
i = -(int) R_32 - 1; |
| 2100 |
|
else |
| 2101 |
|
/* Setup positives ranges for R_8, R_16 and R_32. */ |
| 2102 |
|
i = (int) R_8; |
| 2103 |
|
|
| 2104 |
|
for (; i <= (int) R_32; ++i) |
| 2105 |
{ |
{ |
| 2106 |
|
int j; |
| 2107 |
size_t n; |
size_t n; |
| 2108 |
|
|
| 2109 |
/* Put GOT pointer in the middle of GOT. */ |
/* Set beginning of the range of offsets I. */ |
| 2110 |
n = htab_elements (got->entries); |
arg_.offset1[i] = start_offset; |
|
if ((n & 1) == 0) |
|
|
/* Even number of GOT entries. */ |
|
|
got->offset += 2 * n; |
|
|
else |
|
|
/* Odd number of GOT entries. */ |
|
|
got->offset += 2 * (n - 1); |
|
| 2111 |
|
|
| 2112 |
/* R_68K_GOT8O entries shall start at GOT offset. */ |
/* Calculate number of slots that require I offsets. */ |
| 2113 |
arg_.rel_8o_offset = got->offset; |
j = (i >= 0) ? i : -i - 1; |
| 2114 |
|
n = (j >= 1) ? got->n_slots[j - 1] : 0; |
| 2115 |
|
n = got->n_slots[j] - n; |
| 2116 |
|
|
| 2117 |
|
if (use_neg_got_offsets_p && n != 0) |
| 2118 |
|
{ |
| 2119 |
|
if (i < 0) |
| 2120 |
|
/* We first fill the positive side of the range, so we might |
| 2121 |
|
end up with one empty slot at that side when we can't fit |
| 2122 |
|
whole 2-slot entry. Account for that at negative side of |
| 2123 |
|
the interval with one additional entry. */ |
| 2124 |
|
n = n / 2 + 1; |
| 2125 |
|
else |
| 2126 |
|
/* When the number of slots is odd, make positive side of the |
| 2127 |
|
range one entry bigger. */ |
| 2128 |
|
n = (n + 1) / 2; |
| 2129 |
|
} |
| 2130 |
|
|
| 2131 |
n = got->rel_8o_n_entries; |
/* N is the number of slots that require I offsets. |
| 2132 |
if ((n & 1) == 0) |
Calculate length of the range for I offsets. */ |
| 2133 |
/* Even number of R_68K_GOT8O entries. |
n = 4 * n; |
|
The last R_68K_GOT8O entry will be at |
|
|
(got->offset - 2 * n). Hence the first R_68K_GOT16O |
|
|
entry will be at offset ... */ |
|
|
arg_.rel_16o_offset = got->offset + 2 * n; |
|
|
else |
|
|
/* Odd number of R_68K_GOT8O entries. |
|
|
The last R_68K_GOT8O entry will be at |
|
|
(got->offset + 2 * (n - 1)). Hence the first R_68K_GOT16O |
|
|
entry will be at offset ... */ |
|
|
arg_.rel_16o_offset = got->offset - 2 * (n - 1) - 4; |
|
|
|
|
|
n = got->rel_8o_16o_n_entries; |
|
|
if ((n & 1) == 0) |
|
|
/* Even number of R_68K_GOT8O and R_68K_GOT16O entries. |
|
|
The last R_68K_GOT8O entry will be at |
|
|
(got->offset - 2 * n). Hence the first R_68K_GOT32O |
|
|
entry will be at offset ... */ |
|
|
arg_.rel_32o_offset = got->offset + 2 * n; |
|
|
else |
|
|
/* Odd number of R_68K_GOT8O and R_68K_GOT16O entries. |
|
|
The last R_68K_GOT16O entry will be at |
|
|
(got->offset + 2 * (n - 1)). Hence the first R_68K_GOT32O |
|
|
entry will be at offset ... */ |
|
|
arg_.rel_32o_offset = got->offset - 2 * (n - 1) - 4; |
|
| 2134 |
|
|
| 2135 |
arg_.use_neg_got_offsets_p = TRUE; |
/* Set end of the range. */ |
| 2136 |
|
arg_.offset2[i] = start_offset + n; |
| 2137 |
|
|
| 2138 |
arg_.got_offset = got->offset; |
start_offset = arg_.offset2[i]; |
| 2139 |
} |
} |
|
else |
|
|
{ |
|
|
arg_.rel_8o_offset = got->offset; |
|
|
arg_.rel_16o_offset = 4 * got->rel_8o_n_entries + got->offset; |
|
|
arg_.rel_32o_offset = 4 * got->rel_8o_16o_n_entries + got->offset; |
|
| 2140 |
|
|
| 2141 |
arg_.use_neg_got_offsets_p = FALSE; |
if (!use_neg_got_offsets_p) |
| 2142 |
|
/* Make sure that if we try to switch to negative offsets in |
| 2143 |
|
elf_m68k_finalize_got_offsets_1, the assert therein will catch |
| 2144 |
|
the bug. */ |
| 2145 |
|
for (i = R_8; i <= R_32; ++i) |
| 2146 |
|
arg_.offset2[-i - 1] = arg_.offset2[i]; |
| 2147 |
|
|
| 2148 |
/* This shouldn't be used. */ |
/* Setup got->offset. offset1[R_8] is either in the middle or at the |
| 2149 |
arg_.got_offset = (bfd_vma) -1; |
beginning of GOT depending on use_neg_got_offsets_p. */ |
| 2150 |
} |
got->offset = arg_.offset1[R_8]; |
| 2151 |
|
|
| 2152 |
arg_.symndx2h = symndx2h; |
arg_.symndx2h = symndx2h; |
| 2153 |
|
arg_.n_ldm_entries = 0; |
| 2154 |
|
|
| 2155 |
|
/* Assign offsets. */ |
| 2156 |
htab_traverse (got->entries, elf_m68k_finalize_got_offsets_1, &arg_); |
htab_traverse (got->entries, elf_m68k_finalize_got_offsets_1, &arg_); |
| 2157 |
|
|
| 2158 |
/* Calculate offset ranges we have actually assigned. */ |
/* Check offset ranges we have actually assigned. */ |
| 2159 |
if (use_neg_got_offsets_p) |
for (i = (int) R_8; i <= (int) R_32; ++i) |
| 2160 |
{ |
BFD_ASSERT (arg_.offset2[i] - arg_.offset1[i] <= 4); |
|
if (arg_.rel_8o_offset == (bfd_vma) -4 |
|
|
|| arg_.rel_8o_offset < got->offset) |
|
|
arg_.rel_8o_offset = 2 * (got->offset - arg_.rel_8o_offset) - 4; |
|
|
else |
|
|
arg_.rel_8o_offset = 2 * (arg_.rel_8o_offset - got->offset); |
|
| 2161 |
|
|
| 2162 |
if (arg_.rel_16o_offset == (bfd_vma) -4 |
*final_offset = start_offset; |
| 2163 |
|| arg_.rel_16o_offset < got->offset) |
*n_ldm_entries = arg_.n_ldm_entries; |
|
arg_.rel_16o_offset = 2 * (got->offset - arg_.rel_16o_offset) - 4; |
|
|
else |
|
|
arg_.rel_16o_offset = 2 * (arg_.rel_16o_offset - got->offset); |
|
|
|
|
|
if (arg_.rel_32o_offset == (bfd_vma) -4 |
|
|
|| arg_.rel_32o_offset < got->offset) |
|
|
arg_.rel_32o_offset = 2 * (got->offset - arg_.rel_32o_offset) - 4; |
|
|
else |
|
|
arg_.rel_32o_offset = 2 * (arg_.rel_32o_offset - got->offset); |
|
|
} |
|
|
else |
|
|
{ |
|
|
arg_.rel_8o_offset -= got->offset; |
|
|
arg_.rel_16o_offset -= got->offset; |
|
|
arg_.rel_32o_offset -= got->offset; |
|
|
} |
|
|
|
|
|
/* These asserts check that we got counting of entries right. */ |
|
|
BFD_ASSERT (arg_.rel_8o_offset == 4 * got->rel_8o_n_entries); |
|
|
BFD_ASSERT (arg_.rel_16o_offset == 4 * got->rel_8o_16o_n_entries); |
|
|
BFD_ASSERT (arg_.rel_32o_offset == 4 * htab_elements (got->entries)); |
|
| 2164 |
} |
} |
| 2165 |
|
|
| 2166 |
struct elf_m68k_partition_multi_got_arg |
struct elf_m68k_partition_multi_got_arg |
| 2174 |
/* Context where memory should be allocated. */ |
/* Context where memory should be allocated. */ |
| 2175 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
| 2176 |
|
|
| 2177 |
/* Total number of entries in the .got section. |
/* Total number of slots in the .got section. |
| 2178 |
This is used to calculate size of the .got and .rela.got sections. */ |
This is used to calculate size of the .got and .rela.got sections. */ |
| 2179 |
bfd_vma n_entries; |
bfd_vma n_slots; |
| 2180 |
|
|
| 2181 |
/* Total number of local entries in the .got section. |
/* Difference in numbers of allocated slots in the .got section |
| 2182 |
|
and necessary relocations in the .rela.got section. |
| 2183 |
This is used to calculate size of the .rela.got section. */ |
This is used to calculate size of the .rela.got section. */ |
| 2184 |
bfd_vma local_n_entries; |
bfd_vma slots_relas_diff; |
| 2185 |
|
|
| 2186 |
/* Error flag. */ |
/* Error flag. */ |
| 2187 |
bfd_boolean error_p; |
bfd_boolean error_p; |
| 2191 |
struct elf_m68k_link_hash_entry **symndx2h; |
struct elf_m68k_link_hash_entry **symndx2h; |
| 2192 |
}; |
}; |
| 2193 |
|
|
| 2194 |
|
static void |
| 2195 |
|
elf_m68k_partition_multi_got_2 (struct elf_m68k_partition_multi_got_arg *arg) |
| 2196 |
|
{ |
| 2197 |
|
bfd_vma n_ldm_entries; |
| 2198 |
|
|
| 2199 |
|
elf_m68k_finalize_got_offsets (arg->current_got, |
| 2200 |
|
(elf_m68k_hash_table (arg->info) |
| 2201 |
|
->use_neg_got_offsets_p), |
| 2202 |
|
arg->symndx2h, |
| 2203 |
|
&arg->offset, &n_ldm_entries); |
| 2204 |
|
|
| 2205 |
|
arg->n_slots += arg->current_got->n_slots[R_32]; |
| 2206 |
|
|
| 2207 |
|
if (!arg->info->shared) |
| 2208 |
|
/* If we are generating a shared object, we need to |
| 2209 |
|
output a R_68K_RELATIVE reloc so that the dynamic |
| 2210 |
|
linker can adjust this GOT entry. Overwise we |
| 2211 |
|
don't need space in .rela.got for local symbols. */ |
| 2212 |
|
arg->slots_relas_diff += arg->current_got->local_n_slots; |
| 2213 |
|
|
| 2214 |
|
/* @LDM relocations require a 2-slot GOT entry, but only |
| 2215 |
|
one relocation. Account for that. */ |
| 2216 |
|
arg->slots_relas_diff += n_ldm_entries; |
| 2217 |
|
|
| 2218 |
|
BFD_ASSERT (arg->slots_relas_diff <= arg->n_slots); |
| 2219 |
|
} |
| 2220 |
|
|
| 2221 |
|
|
| 2222 |
/* Process a single BFD2GOT entry and either merge GOT to CURRENT_GOT |
/* Process a single BFD2GOT entry and either merge GOT to CURRENT_GOT |
| 2223 |
or start a new CURRENT_GOT. */ |
or start a new CURRENT_GOT. */ |
| 2224 |
|
|
| 2228 |
struct elf_m68k_bfd2got_entry *entry; |
struct elf_m68k_bfd2got_entry *entry; |
| 2229 |
struct elf_m68k_partition_multi_got_arg *arg; |
struct elf_m68k_partition_multi_got_arg *arg; |
| 2230 |
struct elf_m68k_got *got; |
struct elf_m68k_got *got; |
|
struct elf_m68k_got *current_got; |
|
| 2231 |
struct elf_m68k_got diff_; |
struct elf_m68k_got diff_; |
| 2232 |
struct elf_m68k_got *diff; |
struct elf_m68k_got *diff; |
| 2233 |
|
|
| 2244 |
/* Construct diff. */ |
/* Construct diff. */ |
| 2245 |
{ |
{ |
| 2246 |
diff = &diff_; |
diff = &diff_; |
| 2247 |
elf_m68k_init_got (diff, NULL, 0, 0, 0, (bfd_vma) -1); |
elf_m68k_init_got (diff); |
| 2248 |
|
|
| 2249 |
if (!elf_m68k_can_merge_gots (arg->current_got, got, arg->info, diff)) |
if (!elf_m68k_can_merge_gots (arg->current_got, got, arg->info, diff)) |
| 2250 |
{ |
{ |
| 2258 |
if (elf_m68k_hash_table (arg->info)->allow_multigot_p) |
if (elf_m68k_hash_table (arg->info)->allow_multigot_p) |
| 2259 |
{ |
{ |
| 2260 |
elf_m68k_clear_got (diff); |
elf_m68k_clear_got (diff); |
| 2261 |
/* Schedule to finish up CURRENT_GOT and start new one. */ |
/* Schedule to finish up current_got and start new one. */ |
| 2262 |
diff = NULL; |
diff = NULL; |
| 2263 |
} |
} |
| 2264 |
/* else |
/* else |
| 2271 |
else |
else |
| 2272 |
/* Diff of got against empty current_got is got itself. */ |
/* Diff of got against empty current_got is got itself. */ |
| 2273 |
{ |
{ |
| 2274 |
/* Create empty CURRENT_GOT to subsequent GOTs to. */ |
/* Create empty current_got to put subsequent GOTs to. */ |
| 2275 |
arg->current_got = elf_m68k_create_empty_got (arg->info); |
arg->current_got = elf_m68k_create_empty_got (arg->info); |
| 2276 |
if (arg->current_got == NULL) |
if (arg->current_got == NULL) |
| 2277 |
{ |
{ |
| 2284 |
diff = got; |
diff = got; |
| 2285 |
} |
} |
| 2286 |
|
|
|
current_got = arg->current_got; |
|
|
|
|
| 2287 |
if (diff != NULL) |
if (diff != NULL) |
| 2288 |
{ |
{ |
| 2289 |
if (!elf_m68k_merge_gots (current_got, diff, arg->info)) |
if (!elf_m68k_merge_gots (arg->current_got, diff, arg->info)) |
| 2290 |
{ |
{ |
| 2291 |
arg->error_p = TRUE; |
arg->error_p = TRUE; |
| 2292 |
goto final_return; |
goto final_return; |
| 2295 |
/* Now we can free GOT. */ |
/* Now we can free GOT. */ |
| 2296 |
elf_m68k_clear_got (got); |
elf_m68k_clear_got (got); |
| 2297 |
|
|
| 2298 |
entry->got = current_got; |
entry->got = arg->current_got; |
| 2299 |
} |
} |
| 2300 |
else |
else |
| 2301 |
{ |
{ |
|
/* Schedule to start a new current_got. */ |
|
|
arg->current_got = NULL; |
|
|
arg->offset = (current_got->offset |
|
|
+ 4 * htab_elements (current_got->entries)); |
|
|
|
|
| 2302 |
/* Finish up current_got. */ |
/* Finish up current_got. */ |
| 2303 |
{ |
elf_m68k_partition_multi_got_2 (arg); |
|
elf_m68k_finalize_got_offsets (current_got, |
|
|
elf_m68k_hash_table (arg->info) |
|
|
->use_neg_got_offsets_p, |
|
|
arg->symndx2h); |
|
| 2304 |
|
|
| 2305 |
arg->n_entries += htab_elements (current_got->entries); |
/* Schedule to start a new current_got. */ |
| 2306 |
arg->local_n_entries += current_got->local_n_entries; |
arg->current_got = NULL; |
|
|
|
|
BFD_ASSERT (arg->local_n_entries <= arg->n_entries); |
|
|
} |
|
| 2307 |
|
|
| 2308 |
/* Retry. */ |
/* Retry. */ |
| 2309 |
if (!elf_m68k_partition_multi_got_1 (_entry, _arg)) |
if (!elf_m68k_partition_multi_got_1 (_entry, _arg)) |
| 2359 |
arg_.current_got = NULL; |
arg_.current_got = NULL; |
| 2360 |
arg_.offset = 0; |
arg_.offset = 0; |
| 2361 |
arg_.info = info; |
arg_.info = info; |
| 2362 |
arg_.n_entries = 0; |
arg_.n_slots = 0; |
| 2363 |
arg_.local_n_entries = 0; |
arg_.slots_relas_diff = 0; |
| 2364 |
arg_.error_p = FALSE; |
arg_.error_p = FALSE; |
| 2365 |
|
|
| 2366 |
if (multi_got->bfd2got != NULL) |
if (multi_got->bfd2got != NULL) |
| 2388 |
} |
} |
| 2389 |
|
|
| 2390 |
/* Finish up last current_got. */ |
/* Finish up last current_got. */ |
| 2391 |
{ |
elf_m68k_partition_multi_got_2 (&arg_); |
|
elf_m68k_finalize_got_offsets (arg_.current_got, |
|
|
elf_m68k_hash_table (info) |
|
|
->use_neg_got_offsets_p, arg_.symndx2h); |
|
|
|
|
|
arg_.n_entries += htab_elements (arg_.current_got->entries); |
|
|
arg_.local_n_entries += arg_.current_got->local_n_entries; |
|
|
|
|
|
BFD_ASSERT (arg_.local_n_entries <= arg_.n_entries); |
|
|
} |
|
| 2392 |
|
|
| 2393 |
free (arg_.symndx2h); |
free (arg_.symndx2h); |
| 2394 |
} |
} |
| 2400 |
|
|
| 2401 |
s = bfd_get_section_by_name (elf_hash_table (info)->dynobj, ".got"); |
s = bfd_get_section_by_name (elf_hash_table (info)->dynobj, ".got"); |
| 2402 |
if (s != NULL) |
if (s != NULL) |
| 2403 |
s->size = arg_.n_entries * 4; |
s->size = arg_.offset; |
| 2404 |
else |
else |
| 2405 |
BFD_ASSERT (arg_.n_entries == 0); |
BFD_ASSERT (arg_.offset == 0); |
| 2406 |
|
|
| 2407 |
/* If we are generating a shared object, we need to |
BFD_ASSERT (arg_.slots_relas_diff <= arg_.n_slots); |
| 2408 |
output a R_68K_RELATIVE reloc so that the dynamic |
arg_.n_slots -= arg_.slots_relas_diff; |
|
linker can adjust this GOT entry. Overwise we |
|
|
don't need space in .rela.got for local symbols. */ |
|
|
if (!info->shared) |
|
|
{ |
|
|
BFD_ASSERT (arg_.local_n_entries <= arg_.n_entries); |
|
|
arg_.n_entries -= arg_.local_n_entries; |
|
|
} |
|
| 2409 |
|
|
| 2410 |
s = bfd_get_section_by_name (elf_hash_table (info)->dynobj, ".rela.got"); |
s = bfd_get_section_by_name (elf_hash_table (info)->dynobj, ".rela.got"); |
| 2411 |
if (s != NULL) |
if (s != NULL) |
| 2412 |
s->size = arg_.n_entries * sizeof (Elf32_External_Rela); |
s->size = arg_.n_slots * sizeof (Elf32_External_Rela); |
| 2413 |
else |
else |
| 2414 |
BFD_ASSERT (arg_.n_entries == 0); |
BFD_ASSERT (arg_.n_slots == 0); |
| 2415 |
} |
} |
| 2416 |
else |
else |
| 2417 |
BFD_ASSERT (multi_got->bfd2got == NULL); |
BFD_ASSERT (multi_got->bfd2got == NULL); |
| 2455 |
/* Check that this entry is indeed unused. */ |
/* Check that this entry is indeed unused. */ |
| 2456 |
BFD_ASSERT (entry->u.s1.refcount == 0); |
BFD_ASSERT (entry->u.s1.refcount == 0); |
| 2457 |
|
|
| 2458 |
elf_m68k_remove_got_entry_type (got, entry->u.s1.type); |
elf_m68k_remove_got_entry_type (got, entry->key_.type); |
| 2459 |
|
|
| 2460 |
if (entry->key_.bfd != NULL) |
if (entry->key_.bfd != NULL) |
| 2461 |
--got->local_n_entries; |
got->local_n_slots -= elf_m68k_reloc_got_n_slots (entry->key_.type); |
| 2462 |
|
|
| 2463 |
|
BFD_ASSERT (got->n_slots[R_32] >= got->local_n_slots); |
| 2464 |
|
|
| 2465 |
htab_clear_slot (got->entries, (void **) entry_ptr); |
htab_clear_slot (got->entries, (void **) entry_ptr); |
| 2466 |
} |
} |
| 2563 |
&& strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) |
&& strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) |
| 2564 |
break; |
break; |
| 2565 |
/* Fall through. */ |
/* Fall through. */ |
| 2566 |
|
|
| 2567 |
|
/* Relative GOT relocations. */ |
| 2568 |
case R_68K_GOT8O: |
case R_68K_GOT8O: |
| 2569 |
case R_68K_GOT16O: |
case R_68K_GOT16O: |
| 2570 |
case R_68K_GOT32O: |
case R_68K_GOT32O: |
| 2571 |
|
/* Fall through. */ |
| 2572 |
|
|
| 2573 |
|
/* TLS relocations. */ |
| 2574 |
|
case R_68K_TLS_GD8: |
| 2575 |
|
case R_68K_TLS_GD16: |
| 2576 |
|
case R_68K_TLS_GD32: |
| 2577 |
|
case R_68K_TLS_LDM8: |
| 2578 |
|
case R_68K_TLS_LDM16: |
| 2579 |
|
case R_68K_TLS_LDM32: |
| 2580 |
|
case R_68K_TLS_IE8: |
| 2581 |
|
case R_68K_TLS_IE16: |
| 2582 |
|
case R_68K_TLS_IE32: |
| 2583 |
|
|
| 2584 |
/* This symbol requires a global offset table entry. */ |
/* This symbol requires a global offset table entry. */ |
| 2585 |
|
|
| 2586 |
if (dynobj == NULL) |
if (dynobj == NULL) |
| 2651 |
if (!bfd_elf_link_record_dynamic_symbol (info, h)) |
if (!bfd_elf_link_record_dynamic_symbol (info, h)) |
| 2652 |
return FALSE; |
return FALSE; |
| 2653 |
} |
} |
|
|
|
|
/* Allocate space in the .got section. */ |
|
|
sgot->size += 4; |
|
|
|
|
|
/* Allocate relocation space. */ |
|
|
if (h != NULL |
|
|
|| info->shared) |
|
|
srelgot->size += sizeof (Elf32_External_Rela); |
|
| 2654 |
} |
} |
| 2655 |
} |
} |
| 2656 |
|
|
| 2793 |
{ |
{ |
| 2794 |
asection *s; |
asection *s; |
| 2795 |
void *vpp; |
void *vpp; |
| 2796 |
|
Elf_Internal_Sym *isym; |
| 2797 |
|
|
| 2798 |
s = (bfd_section_from_r_symndx |
isym = bfd_sym_from_r_symndx (&elf_m68k_hash_table (info)->sym_cache, |
| 2799 |
(abfd, &elf_m68k_hash_table (info)->sym_sec, |
abfd, r_symndx); |
| 2800 |
sec, r_symndx)); |
if (isym == NULL) |
|
if (s == NULL) |
|
| 2801 |
return FALSE; |
return FALSE; |
| 2802 |
|
|
| 2803 |
|
s = bfd_section_from_elf_index (abfd, isym->st_shndx); |
| 2804 |
|
if (s == NULL) |
| 2805 |
|
s = sec; |
| 2806 |
|
|
| 2807 |
vpp = &elf_section_data (s)->local_dynrel; |
vpp = &elf_section_data (s)->local_dynrel; |
| 2808 |
head = (struct elf_m68k_pcrel_relocs_copied **) vpp; |
head = (struct elf_m68k_pcrel_relocs_copied **) vpp; |
| 2809 |
} |
} |
| 2933 |
case R_68K_GOT8O: |
case R_68K_GOT8O: |
| 2934 |
case R_68K_GOT16O: |
case R_68K_GOT16O: |
| 2935 |
case R_68K_GOT32O: |
case R_68K_GOT32O: |
| 2936 |
|
/* Fall through. */ |
| 2937 |
|
|
| 2938 |
|
/* TLS relocations. */ |
| 2939 |
|
case R_68K_TLS_GD8: |
| 2940 |
|
case R_68K_TLS_GD16: |
| 2941 |
|
case R_68K_TLS_GD32: |
| 2942 |
|
case R_68K_TLS_LDM8: |
| 2943 |
|
case R_68K_TLS_LDM16: |
| 2944 |
|
case R_68K_TLS_LDM32: |
| 2945 |
|
case R_68K_TLS_IE8: |
| 2946 |
|
case R_68K_TLS_IE16: |
| 2947 |
|
case R_68K_TLS_IE32: |
| 2948 |
|
|
| 2949 |
if (got == NULL) |
if (got == NULL) |
| 2950 |
{ |
{ |
| 2951 |
got = elf_m68k_get_bfd2got_entry (elf_m68k_multi_got (info), |
got = elf_m68k_get_bfd2got_entry (elf_m68k_multi_got (info), |
| 2958 |
struct elf_m68k_got_entry **got_entry_ptr; |
struct elf_m68k_got_entry **got_entry_ptr; |
| 2959 |
struct elf_m68k_got_entry *got_entry; |
struct elf_m68k_got_entry *got_entry; |
| 2960 |
|
|
| 2961 |
elf_m68k_init_got_entry_key (&key_, h, abfd, r_symndx); |
elf_m68k_init_got_entry_key (&key_, h, abfd, r_symndx, |
| 2962 |
|
ELF32_R_TYPE (rel->r_info)); |
| 2963 |
got_entry_ptr = elf_m68k_find_got_entry_ptr (got, &key_); |
got_entry_ptr = elf_m68k_find_got_entry_ptr (got, &key_); |
| 2964 |
|
|
| 2965 |
got_entry = *got_entry_ptr; |
got_entry = *got_entry_ptr; |
| 3407 |
return TRUE; |
return TRUE; |
| 3408 |
} |
} |
| 3409 |
|
|
| 3410 |
|
|
| 3411 |
|
/* Install relocation RELA. */ |
| 3412 |
|
|
| 3413 |
|
static void |
| 3414 |
|
elf_m68k_install_rela (bfd *output_bfd, |
| 3415 |
|
asection *srela, |
| 3416 |
|
Elf_Internal_Rela *rela) |
| 3417 |
|
{ |
| 3418 |
|
bfd_byte *loc; |
| 3419 |
|
|
| 3420 |
|
loc = srela->contents; |
| 3421 |
|
loc += srela->reloc_count++ * sizeof (Elf32_External_Rela); |
| 3422 |
|
bfd_elf32_swap_reloca_out (output_bfd, rela, loc); |
| 3423 |
|
} |
| 3424 |
|
|
| 3425 |
|
/* Return the base VMA address which should be subtracted from real addresses |
| 3426 |
|
when resolving @dtpoff relocation. |
| 3427 |
|
This is PT_TLS segment p_vaddr. */ |
| 3428 |
|
|
| 3429 |
|
static bfd_vma |
| 3430 |
|
dtpoff_base (struct bfd_link_info *info) |
| 3431 |
|
{ |
| 3432 |
|
/* If tls_sec is NULL, we should have signalled an error already. */ |
| 3433 |
|
if (elf_hash_table (info)->tls_sec == NULL) |
| 3434 |
|
return 0; |
| 3435 |
|
return elf_hash_table (info)->tls_sec->vma; |
| 3436 |
|
} |
| 3437 |
|
|
| 3438 |
|
/* Return the relocation value for @tpoff relocation |
| 3439 |
|
if STT_TLS virtual address is ADDRESS. */ |
| 3440 |
|
|
| 3441 |
|
static bfd_vma |
| 3442 |
|
tpoff (struct bfd_link_info *info, bfd_vma address) |
| 3443 |
|
{ |
| 3444 |
|
struct elf_link_hash_table *htab = elf_hash_table (info); |
| 3445 |
|
bfd_vma base; |
| 3446 |
|
|
| 3447 |
|
/* If tls_sec is NULL, we should have signalled an error already. */ |
| 3448 |
|
if (htab->tls_sec == NULL) |
| 3449 |
|
return 0; |
| 3450 |
|
base = align_power ((bfd_vma) 8, htab->tls_sec->alignment_power); |
| 3451 |
|
return address - htab->tls_sec->vma + base; |
| 3452 |
|
} |
| 3453 |
|
|
| 3454 |
/* Relocate an M68K ELF section. */ |
/* Relocate an M68K ELF section. */ |
| 3455 |
|
|
| 3456 |
static bfd_boolean |
static bfd_boolean |
| 3613 |
case R_68K_GOT8O: |
case R_68K_GOT8O: |
| 3614 |
case R_68K_GOT16O: |
case R_68K_GOT16O: |
| 3615 |
case R_68K_GOT32O: |
case R_68K_GOT32O: |
| 3616 |
|
|
| 3617 |
|
case R_68K_TLS_LDM32: |
| 3618 |
|
case R_68K_TLS_LDM16: |
| 3619 |
|
case R_68K_TLS_LDM8: |
| 3620 |
|
|
| 3621 |
|
case R_68K_TLS_GD8: |
| 3622 |
|
case R_68K_TLS_GD16: |
| 3623 |
|
case R_68K_TLS_GD32: |
| 3624 |
|
|
| 3625 |
|
case R_68K_TLS_IE8: |
| 3626 |
|
case R_68K_TLS_IE16: |
| 3627 |
|
case R_68K_TLS_IE32: |
| 3628 |
|
|
| 3629 |
/* Relocation is the offset of the entry for this symbol in |
/* Relocation is the offset of the entry for this symbol in |
| 3630 |
the global offset table. */ |
the global offset table. */ |
| 3631 |
|
|
| 3649 |
} |
} |
| 3650 |
|
|
| 3651 |
/* Get GOT offset for this symbol. */ |
/* Get GOT offset for this symbol. */ |
| 3652 |
elf_m68k_init_got_entry_key (&key_, h, input_bfd, r_symndx); |
elf_m68k_init_got_entry_key (&key_, h, input_bfd, r_symndx, |
| 3653 |
|
r_type); |
| 3654 |
off_ptr = &elf_m68k_get_got_entry (got, &key_, MUST_FIND, |
off_ptr = &elf_m68k_get_got_entry (got, &key_, MUST_FIND, |
| 3655 |
NULL)->u.s2.offset; |
NULL)->u.s2.offset; |
| 3656 |
off = *off_ptr; |
off = *off_ptr; |
| 3657 |
|
|
| 3658 |
if (h != NULL) |
/* The offset must always be a multiple of 4. We use |
| 3659 |
|
the least significant bit to record whether we have |
| 3660 |
|
already generated the necessary reloc. */ |
| 3661 |
|
if ((off & 1) != 0) |
| 3662 |
|
off &= ~1; |
| 3663 |
|
else |
| 3664 |
{ |
{ |
| 3665 |
bfd_boolean dyn; |
if (h != NULL |
| 3666 |
|
/* @TLSLDM relocations are bounded to the module, in |
| 3667 |
dyn = elf_hash_table (info)->dynamic_sections_created; |
which the symbol is defined -- not to the symbol |
| 3668 |
if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) |
itself. */ |
| 3669 |
|| (info->shared |
&& elf_m68k_reloc_got_type (r_type) != R_68K_TLS_LDM32) |
|
&& SYMBOL_REFERENCES_LOCAL (info, h)) |
|
|
|| (ELF_ST_VISIBILITY (h->other) |
|
|
&& h->root.type == bfd_link_hash_undefweak)) |
|
| 3670 |
{ |
{ |
| 3671 |
/* This is actually a static link, or it is a |
bfd_boolean dyn; |
| 3672 |
-Bsymbolic link and the symbol is defined |
|
| 3673 |
locally, or the symbol was forced to be local |
dyn = elf_hash_table (info)->dynamic_sections_created; |
| 3674 |
because of a version file.. We must initialize |
if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) |
| 3675 |
this entry in the global offset table. Since |
|| (info->shared |
| 3676 |
the offset must always be a multiple of 4, we |
&& SYMBOL_REFERENCES_LOCAL (info, h)) |
| 3677 |
use the least significant bit to record whether |
|| (ELF_ST_VISIBILITY (h->other) |
| 3678 |
we have initialized it already. |
&& h->root.type == bfd_link_hash_undefweak)) |
|
|
|
|
When doing a dynamic link, we create a .rela.got |
|
|
relocation entry to initialize the value. This |
|
|
is done in the finish_dynamic_symbol routine. */ |
|
|
if ((off & 1) != 0) |
|
|
off &= ~1; |
|
|
else |
|
| 3679 |
{ |
{ |
| 3680 |
bfd_put_32 (output_bfd, relocation, |
/* This is actually a static link, or it is a |
| 3681 |
sgot->contents + off); |
-Bsymbolic link and the symbol is defined |
| 3682 |
|
locally, or the symbol was forced to be local |
| 3683 |
|
because of a version file.. We must initialize |
| 3684 |
|
this entry in the global offset table. Since |
| 3685 |
|
the offset must always be a multiple of 4, we |
| 3686 |
|
use the least significant bit to record whether |
| 3687 |
|
we have initialized it already. |
| 3688 |
|
|
| 3689 |
|
When doing a dynamic link, we create a .rela.got |
| 3690 |
|
relocation entry to initialize the value. This |
| 3691 |
|
is done in the finish_dynamic_symbol routine. */ |
| 3692 |
|
|
| 3693 |
|
if (elf_m68k_reloc_got_type (r_type) == R_68K_GOT32O) |
| 3694 |
|
bfd_put_32 (output_bfd, relocation, |
| 3695 |
|
sgot->contents + off); |
| 3696 |
|
else if (elf_m68k_reloc_got_type (r_type) |
| 3697 |
|
== R_68K_TLS_GD32) |
| 3698 |
|
/* Mark it as belonging to module 1, |
| 3699 |
|
the executable. */ |
| 3700 |
|
{ |
| 3701 |
|
bfd_put_32 (output_bfd, 1, |
| 3702 |
|
sgot->contents + off); |
| 3703 |
|
bfd_put_32 (output_bfd, (relocation |
| 3704 |
|
- dtpoff_base (info)), |
| 3705 |
|
sgot->contents + off + 4); |
| 3706 |
|
} |
| 3707 |
|
else if (elf_m68k_reloc_got_type (r_type) |
| 3708 |
|
== R_68K_TLS_IE32) |
| 3709 |
|
bfd_put_32 (output_bfd, tpoff (info, relocation), |
| 3710 |
|
sgot->contents + off); |
| 3711 |
|
else |
| 3712 |
|
BFD_ASSERT (FALSE); |
| 3713 |
|
|
| 3714 |
*off_ptr |= 1; |
*off_ptr |= 1; |
| 3715 |
} |
} |
| 3716 |
|
else |
| 3717 |
|
unresolved_reloc = FALSE; |
| 3718 |
} |
} |
| 3719 |
else |
else if (info->shared) /* && h == NULL */ |
|
unresolved_reloc = FALSE; |
|
|
} |
|
|
else |
|
|
{ |
|
|
/* The offset must always be a multiple of 4. We use |
|
|
the least significant bit to record whether we have |
|
|
already generated the necessary reloc. */ |
|
|
if ((off & 1) != 0) |
|
|
off &= ~1; |
|
|
else |
|
| 3720 |
{ |
{ |
| 3721 |
bfd_put_32 (output_bfd, relocation, sgot->contents + off); |
asection *srela; |
| 3722 |
|
Elf_Internal_Rela outrel; |
| 3723 |
|
|
| 3724 |
|
srela = bfd_get_section_by_name (dynobj, ".rela.got"); |
| 3725 |
|
BFD_ASSERT (srela != NULL); |
| 3726 |
|
|
| 3727 |
if (info->shared) |
if (elf_m68k_reloc_got_type (r_type) == R_68K_GOT32O) |
| 3728 |
{ |
{ |
| 3729 |
asection *s; |
/* Emit RELATIVE relocation to initialize GOT slot |
| 3730 |
Elf_Internal_Rela outrel; |
at run-time. */ |
| 3731 |
bfd_byte *loc; |
outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); |
| 3732 |
|
outrel.r_addend = relocation; |
| 3733 |
|
outrel.r_offset = (sgot->output_section->vma |
| 3734 |
|
+ sgot->output_offset |
| 3735 |
|
+ off); |
| 3736 |
|
|
| 3737 |
s = bfd_get_section_by_name (dynobj, ".rela.got"); |
elf_m68k_install_rela (output_bfd, srela, &outrel); |
| 3738 |
BFD_ASSERT (s != NULL); |
} |
| 3739 |
|
else if (elf_m68k_reloc_got_type (r_type) |
| 3740 |
|
== R_68K_TLS_LDM32) |
| 3741 |
|
{ |
| 3742 |
|
/* If we don't know the module number, create |
| 3743 |
|
a relocation for it. */ |
| 3744 |
|
outrel.r_info = ELF32_R_INFO (0, R_68K_TLS_DTPMOD32); |
| 3745 |
|
outrel.r_addend = 0; |
| 3746 |
|
outrel.r_offset = (sgot->output_section->vma |
| 3747 |
|
+ sgot->output_offset |
| 3748 |
|
+ off); |
| 3749 |
|
|
| 3750 |
|
elf_m68k_install_rela (output_bfd, srela, &outrel); |
| 3751 |
|
} |
| 3752 |
|
else if (elf_m68k_reloc_got_type (r_type) |
| 3753 |
|
== R_68K_TLS_GD32) |
| 3754 |
|
{ |
| 3755 |
|
/* If we don't know the module number, create |
| 3756 |
|
a relocation for it. */ |
| 3757 |
|
outrel.r_info = ELF32_R_INFO (0, R_68K_TLS_DTPMOD32); |
| 3758 |
|
outrel.r_addend = 0; |
| 3759 |
outrel.r_offset = (sgot->output_section->vma |
outrel.r_offset = (sgot->output_section->vma |
| 3760 |
+ sgot->output_offset |
+ sgot->output_offset |
| 3761 |
+ off); |
+ off); |
| 3762 |
outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); |
|
| 3763 |
outrel.r_addend = relocation; |
elf_m68k_install_rela (output_bfd, srela, &outrel); |
| 3764 |
loc = s->contents; |
|
| 3765 |
loc += s->reloc_count++ * sizeof (Elf32_External_Rela); |
bfd_put_32 (output_bfd, (relocation |
| 3766 |
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); |
- dtpoff_base (info)), |
| 3767 |
|
sgot->contents + off + 4); |
| 3768 |
|
} |
| 3769 |
|
else if (elf_m68k_reloc_got_type (r_type) |
| 3770 |
|
== R_68K_TLS_IE32) |
| 3771 |
|
{ |
| 3772 |
|
outrel.r_info = ELF32_R_INFO (0, R_68K_TLS_TPREL32); |
| 3773 |
|
outrel.r_addend = relocation - dtpoff_base (info); |
| 3774 |
|
outrel.r_offset = (sgot->output_section->vma |
| 3775 |
|
+ sgot->output_offset |
| 3776 |
|
+ off); |
| 3777 |
|
|
| 3778 |
|
elf_m68k_install_rela (output_bfd, srela, &outrel); |
| 3779 |
} |
} |
| 3780 |
|
else |
| 3781 |
|
BFD_ASSERT (FALSE); |
| 3782 |
|
|
| 3783 |
|
bfd_put_32 (output_bfd, outrel.r_addend, |
| 3784 |
|
sgot->contents + off); |
| 3785 |
|
|
| 3786 |
|
*off_ptr |= 1; |
| 3787 |
|
} |
| 3788 |
|
else /* h == NULL && !info->shared */ |
| 3789 |
|
{ |
| 3790 |
|
if (elf_m68k_reloc_got_type (r_type) == R_68K_GOT32O) |
| 3791 |
|
bfd_put_32 (output_bfd, relocation, |
| 3792 |
|
sgot->contents + off); |
| 3793 |
|
else if (elf_m68k_reloc_got_type (r_type) |
| 3794 |
|
== R_68K_TLS_LDM32) |
| 3795 |
|
/* If this is a static link, put the number of the |
| 3796 |
|
only module in the GOT slot. */ |
| 3797 |
|
bfd_put_32 (output_bfd, 1, sgot->contents + off); |
| 3798 |
|
else if (elf_m68k_reloc_got_type (r_type) |
| 3799 |
|
== R_68K_TLS_GD32) |
| 3800 |
|
{ |
| 3801 |
|
/* If we are not emitting relocations for a |
| 3802 |
|
general dynamic reference, then we must be in a |
| 3803 |
|
static link or an executable link with the |
| 3804 |
|
symbol binding locally. Mark it as belonging |
| 3805 |
|
to module 1, the executable. */ |
| 3806 |
|
bfd_put_32 (output_bfd, 1, sgot->contents + off); |
| 3807 |
|
bfd_put_32 (output_bfd, (relocation |
| 3808 |
|
- dtpoff_base (info)), |
| 3809 |
|
sgot->contents + off + 4); |
| 3810 |
|
} |
| 3811 |
|
else if (elf_m68k_reloc_got_type (r_type) |
| 3812 |
|
== R_68K_TLS_IE32) |
| 3813 |
|
bfd_put_32 (output_bfd, tpoff (info, relocation), |
| 3814 |
|
sgot->contents + off); |
| 3815 |
|
else |
| 3816 |
|
BFD_ASSERT (FALSE); |
| 3817 |
|
|
| 3818 |
*off_ptr |= 1; |
*off_ptr |= 1; |
| 3819 |
} |
} |
| 3820 |
} |
} |
| 3821 |
|
|
| 3822 |
if (r_type == R_68K_GOT8O |
/* We don't use elf_m68k_reloc_got_type in the condition below |
| 3823 |
|
because this is the only place where difference between |
| 3824 |
|
R_68K_GOTx and R_68K_GOTxO relocations matters. */ |
| 3825 |
|
if (r_type == R_68K_GOT32O |
| 3826 |
|| r_type == R_68K_GOT16O |
|| r_type == R_68K_GOT16O |
| 3827 |
|| r_type == R_68K_GOT32O) |
|| r_type == R_68K_GOT8O |
| 3828 |
|
|| elf_m68k_reloc_got_type (r_type) == R_68K_TLS_GD32 |
| 3829 |
|
|| elf_m68k_reloc_got_type (r_type) == R_68K_TLS_LDM32 |
| 3830 |
|
|| elf_m68k_reloc_got_type (r_type) == R_68K_TLS_IE32) |
| 3831 |
{ |
{ |
| 3832 |
/* GOT pointer is adjusted to point to the start/middle |
/* GOT pointer is adjusted to point to the start/middle |
| 3833 |
of local GOT. Adjust the offset accordingly. */ |
of local GOT. Adjust the offset accordingly. */ |
| 3852 |
} |
} |
| 3853 |
break; |
break; |
| 3854 |
|
|
| 3855 |
|
case R_68K_TLS_LDO32: |
| 3856 |
|
case R_68K_TLS_LDO16: |
| 3857 |
|
case R_68K_TLS_LDO8: |
| 3858 |
|
relocation -= dtpoff_base (info); |
| 3859 |
|
break; |
| 3860 |
|
|
| 3861 |
|
case R_68K_TLS_LE32: |
| 3862 |
|
case R_68K_TLS_LE16: |
| 3863 |
|
case R_68K_TLS_LE8: |
| 3864 |
|
if (info->shared) |
| 3865 |
|
{ |
| 3866 |
|
(*_bfd_error_handler) |
| 3867 |
|
(_("%B(%A+0x%lx): R_68K_TLS_LE32 relocation not permitted " |
| 3868 |
|
"in shared object"), |
| 3869 |
|
input_bfd, input_section, (long) rel->r_offset, howto->name); |
| 3870 |
|
|
| 3871 |
|
return FALSE; |
| 3872 |
|
} |
| 3873 |
|
else |
| 3874 |
|
relocation = tpoff (info, relocation); |
| 3875 |
|
|
| 3876 |
|
break; |
| 3877 |
|
|
| 3878 |
case R_68K_PLT8: |
case R_68K_PLT8: |
| 3879 |
case R_68K_PLT16: |
case R_68K_PLT16: |
| 3880 |
case R_68K_PLT32: |
case R_68K_PLT32: |
| 4070 |
return FALSE; |
return FALSE; |
| 4071 |
} |
} |
| 4072 |
|
|
| 4073 |
|
if (r_symndx != 0 |
| 4074 |
|
&& r_type != R_68K_NONE |
| 4075 |
|
&& (h == NULL |
| 4076 |
|
|| h->root.type == bfd_link_hash_defined |
| 4077 |
|
|| h->root.type == bfd_link_hash_defweak)) |
| 4078 |
|
{ |
| 4079 |
|
char sym_type; |
| 4080 |
|
|
| 4081 |
|
sym_type = (sym != NULL) ? ELF32_ST_TYPE (sym->st_info) : h->type; |
| 4082 |
|
|
| 4083 |
|
if (elf_m68k_reloc_tls_p (r_type) != (sym_type == STT_TLS)) |
| 4084 |
|
{ |
| 4085 |
|
const char *name; |
| 4086 |
|
|
| 4087 |
|
if (h != NULL) |
| 4088 |
|
name = h->root.root.string; |
| 4089 |
|
else |
| 4090 |
|
{ |
| 4091 |
|
name = (bfd_elf_string_from_elf_section |
| 4092 |
|
(input_bfd, symtab_hdr->sh_link, sym->st_name)); |
| 4093 |
|
if (name == NULL || *name == '\0') |
| 4094 |
|
name = bfd_section_name (input_bfd, sec); |
| 4095 |
|
} |
| 4096 |
|
|
| 4097 |
|
(*_bfd_error_handler) |
| 4098 |
|
((sym_type == STT_TLS |
| 4099 |
|
? _("%B(%A+0x%lx): %s used with TLS symbol %s") |
| 4100 |
|
: _("%B(%A+0x%lx): %s used with non-TLS symbol %s")), |
| 4101 |
|
input_bfd, |
| 4102 |
|
input_section, |
| 4103 |
|
(long) rel->r_offset, |
| 4104 |
|
howto->name, |
| 4105 |
|
name); |
| 4106 |
|
} |
| 4107 |
|
} |
| 4108 |
|
|
| 4109 |
r = _bfd_final_link_relocate (howto, input_bfd, input_section, |
r = _bfd_final_link_relocate (howto, input_bfd, input_section, |
| 4110 |
contents, rel->r_offset, |
contents, rel->r_offset, |
| 4111 |
relocation, rel->r_addend); |
relocation, rel->r_addend); |
| 4271 |
while (got_entry != NULL) |
while (got_entry != NULL) |
| 4272 |
{ |
{ |
| 4273 |
Elf_Internal_Rela rela; |
Elf_Internal_Rela rela; |
| 4274 |
bfd_byte *loc; |
bfd_vma got_entry_offset; |
| 4275 |
|
|
| 4276 |
|
got_entry_offset = got_entry->u.s2.offset &~ (bfd_vma) 1; |
| 4277 |
|
|
| 4278 |
rela.r_offset = (sgot->output_section->vma |
rela.r_offset = (sgot->output_section->vma |
| 4279 |
+ sgot->output_offset |
+ sgot->output_offset |
| 4280 |
+ (got_entry->u.s2.offset &~ (bfd_vma) 1)); |
+ got_entry_offset); |
| 4281 |
|
|
| 4282 |
/* If this is a -Bsymbolic link, and the symbol is defined |
/* If this is a -Bsymbolic link, and the symbol is defined |
| 4283 |
locally, we just want to emit a RELATIVE reloc. Likewise if |
locally, we just want to emit a RELATIVE reloc. Likewise if |
| 4284 |
the symbol was forced to be local because of a version file. |
the symbol was forced to be local because of a version file. |
| 4285 |
The entry in the global offset table will already have been |
The entry in the global offset table already have been |
| 4286 |
initialized in the relocate_section function. */ |
initialized in the relocate_section function. */ |
| 4287 |
if (info->shared |
if (info->shared |
| 4288 |
&& SYMBOL_REFERENCES_LOCAL (info, h)) |
&& SYMBOL_REFERENCES_LOCAL (info, h)) |
| 4289 |
{ |
{ |
|
rela.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); |
|
| 4290 |
rela.r_addend = bfd_get_signed_32 (output_bfd, |
rela.r_addend = bfd_get_signed_32 (output_bfd, |
| 4291 |
(sgot->contents |
(sgot->contents |
| 4292 |
+ (got_entry->u.s2.offset |
+ got_entry_offset)); |
| 4293 |
&~ (bfd_vma) 1))); |
|
| 4294 |
|
switch (elf_m68k_reloc_got_type (got_entry->key_.type)) |
| 4295 |
|
{ |
| 4296 |
|
case R_68K_GOT32O: |
| 4297 |
|
rela.r_info = ELF32_R_INFO (0, R_68K_RELATIVE); |
| 4298 |
|
break; |
| 4299 |
|
|
| 4300 |
|
case R_68K_TLS_GD32: |
| 4301 |
|
rela.r_info = ELF32_R_INFO (0, R_68K_TLS_DTPMOD32); |
| 4302 |
|
break; |
| 4303 |
|
|
| 4304 |
|
case R_68K_TLS_IE32: |
| 4305 |
|
rela.r_info = ELF32_R_INFO (0, R_68K_TLS_TPREL32); |
| 4306 |
|
break; |
| 4307 |
|
|
| 4308 |
|
default: |
| 4309 |
|
BFD_ASSERT (FALSE); |
| 4310 |
|
break; |
| 4311 |
|
} |
| 4312 |
|
|
| 4313 |
|
elf_m68k_install_rela (output_bfd, srela, &rela); |
| 4314 |
} |
} |
| 4315 |
else |
else |
| 4316 |
{ |
{ |
| 4317 |
bfd_put_32 (output_bfd, (bfd_vma) 0, |
/* Put zeros to GOT slots that will be initialized |
| 4318 |
sgot->contents + (got_entry->u.s2.offset |
at run-time. */ |
| 4319 |
&~ (bfd_vma) 1)); |
{ |
| 4320 |
rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_GLOB_DAT); |
bfd_vma n_slots; |
| 4321 |
|
|
| 4322 |
|
n_slots = elf_m68k_reloc_got_n_slots (got_entry->key_.type); |
| 4323 |
|
while (n_slots--) |
| 4324 |
|
bfd_put_32 (output_bfd, (bfd_vma) 0, |
| 4325 |
|
(sgot->contents + got_entry_offset |
| 4326 |
|
+ 4 * n_slots)); |
| 4327 |
|
} |
| 4328 |
|
|
| 4329 |
rela.r_addend = 0; |
rela.r_addend = 0; |
|
} |
|
| 4330 |
|
|
| 4331 |
loc = srela->contents; |
switch (elf_m68k_reloc_got_type (got_entry->key_.type)) |
| 4332 |
loc += srela->reloc_count++ * sizeof (Elf32_External_Rela); |
{ |
| 4333 |
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); |
case R_68K_GOT32O: |
| 4334 |
|
rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_GLOB_DAT); |
| 4335 |
|
elf_m68k_install_rela (output_bfd, srela, &rela); |
| 4336 |
|
break; |
| 4337 |
|
|
| 4338 |
|
case R_68K_TLS_GD32: |
| 4339 |
|
rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_TLS_DTPMOD32); |
| 4340 |
|
elf_m68k_install_rela (output_bfd, srela, &rela); |
| 4341 |
|
|
| 4342 |
|
rela.r_offset += 4; |
| 4343 |
|
rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_TLS_DTPREL32); |
| 4344 |
|
elf_m68k_install_rela (output_bfd, srela, &rela); |
| 4345 |
|
break; |
| 4346 |
|
|
| 4347 |
|
case R_68K_TLS_IE32: |
| 4348 |
|
rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_TLS_TPREL32); |
| 4349 |
|
elf_m68k_install_rela (output_bfd, srela, &rela); |
| 4350 |
|
break; |
| 4351 |
|
|
| 4352 |
|
default: |
| 4353 |
|
BFD_ASSERT (FALSE); |
| 4354 |
|
break; |
| 4355 |
|
} |
| 4356 |
|
} |
| 4357 |
|
|
| 4358 |
got_entry = got_entry->u.s2.next; |
got_entry = got_entry->u.s2.next; |
| 4359 |
} |
} |