133965Sjdp/* Intel 80386/80486-specific support for 32-bit ELF 2130570Sobrien Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 3218822Sdim 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. 433965Sjdp 5130570Sobrien This file is part of BFD, the Binary File Descriptor library. 633965Sjdp 7130570Sobrien This program is free software; you can redistribute it and/or modify 8130570Sobrien it under the terms of the GNU General Public License as published by 9130570Sobrien the Free Software Foundation; either version 2 of the License, or 10130570Sobrien (at your option) any later version. 1133965Sjdp 12130570Sobrien This program is distributed in the hope that it will be useful, 13130570Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 14130570Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15130570Sobrien GNU General Public License for more details. 1633965Sjdp 17130570Sobrien You should have received a copy of the GNU General Public License 18130570Sobrien along with this program; if not, write to the Free Software 19218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2033965Sjdp 21218822Sdim#include "sysdep.h" 2233965Sjdp#include "bfd.h" 2333965Sjdp#include "bfdlink.h" 2433965Sjdp#include "libbfd.h" 2533965Sjdp#include "elf-bfd.h" 26218822Sdim#include "elf-vxworks.h" 2733965Sjdp 28130570Sobrien/* 386 uses REL relocations instead of RELA. */ 29130570Sobrien#define USE_REL 1 30104840Sobrien 3160509Sobrien#include "elf/i386.h" 3233965Sjdp 3333965Sjdpstatic reloc_howto_type elf_howto_table[]= 3433965Sjdp{ 35130570Sobrien HOWTO(R_386_NONE, 0, 0, 0, FALSE, 0, complain_overflow_bitfield, 3677302Sobrien bfd_elf_generic_reloc, "R_386_NONE", 37130570Sobrien TRUE, 0x00000000, 0x00000000, FALSE), 38130570Sobrien HOWTO(R_386_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 3977302Sobrien bfd_elf_generic_reloc, "R_386_32", 40130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 41130570Sobrien HOWTO(R_386_PC32, 0, 2, 32, TRUE, 0, complain_overflow_bitfield, 4277302Sobrien bfd_elf_generic_reloc, "R_386_PC32", 43130570Sobrien TRUE, 0xffffffff, 0xffffffff, TRUE), 44130570Sobrien HOWTO(R_386_GOT32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 4577302Sobrien bfd_elf_generic_reloc, "R_386_GOT32", 46130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 47130570Sobrien HOWTO(R_386_PLT32, 0, 2, 32, TRUE, 0, complain_overflow_bitfield, 4877302Sobrien bfd_elf_generic_reloc, "R_386_PLT32", 49130570Sobrien TRUE, 0xffffffff, 0xffffffff, TRUE), 50130570Sobrien HOWTO(R_386_COPY, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 5177302Sobrien bfd_elf_generic_reloc, "R_386_COPY", 52130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 53130570Sobrien HOWTO(R_386_GLOB_DAT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 5477302Sobrien bfd_elf_generic_reloc, "R_386_GLOB_DAT", 55130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 56130570Sobrien HOWTO(R_386_JUMP_SLOT, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 5777302Sobrien bfd_elf_generic_reloc, "R_386_JUMP_SLOT", 58130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 59130570Sobrien HOWTO(R_386_RELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 6077302Sobrien bfd_elf_generic_reloc, "R_386_RELATIVE", 61130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 62130570Sobrien HOWTO(R_386_GOTOFF, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 6377302Sobrien bfd_elf_generic_reloc, "R_386_GOTOFF", 64130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 65130570Sobrien HOWTO(R_386_GOTPC, 0, 2, 32, TRUE, 0, complain_overflow_bitfield, 6677302Sobrien bfd_elf_generic_reloc, "R_386_GOTPC", 67130570Sobrien TRUE, 0xffffffff, 0xffffffff, TRUE), 6877302Sobrien 6977302Sobrien /* We have a gap in the reloc numbers here. 7077302Sobrien R_386_standard counts the number up to this point, and 7177302Sobrien R_386_ext_offset is the value to subtract from a reloc type of 7277302Sobrien R_386_16 thru R_386_PC8 to form an index into this table. */ 73130570Sobrien#define R_386_standard (R_386_GOTPC + 1) 74130570Sobrien#define R_386_ext_offset (R_386_TLS_TPOFF - R_386_standard) 7577302Sobrien 76104840Sobrien /* These relocs are a GNU extension. */ 77130570Sobrien HOWTO(R_386_TLS_TPOFF, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 78104840Sobrien bfd_elf_generic_reloc, "R_386_TLS_TPOFF", 79130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 80130570Sobrien HOWTO(R_386_TLS_IE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 81104840Sobrien bfd_elf_generic_reloc, "R_386_TLS_IE", 82130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 83130570Sobrien HOWTO(R_386_TLS_GOTIE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 84104840Sobrien bfd_elf_generic_reloc, "R_386_TLS_GOTIE", 85130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 86130570Sobrien HOWTO(R_386_TLS_LE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 87104840Sobrien bfd_elf_generic_reloc, "R_386_TLS_LE", 88130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 89130570Sobrien HOWTO(R_386_TLS_GD, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 90104840Sobrien bfd_elf_generic_reloc, "R_386_TLS_GD", 91130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 92130570Sobrien HOWTO(R_386_TLS_LDM, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 93104840Sobrien bfd_elf_generic_reloc, "R_386_TLS_LDM", 94130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 95130570Sobrien HOWTO(R_386_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, 9677302Sobrien bfd_elf_generic_reloc, "R_386_16", 97130570Sobrien TRUE, 0xffff, 0xffff, FALSE), 98130570Sobrien HOWTO(R_386_PC16, 0, 1, 16, TRUE, 0, complain_overflow_bitfield, 9977302Sobrien bfd_elf_generic_reloc, "R_386_PC16", 100130570Sobrien TRUE, 0xffff, 0xffff, TRUE), 101130570Sobrien HOWTO(R_386_8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, 10277302Sobrien bfd_elf_generic_reloc, "R_386_8", 103130570Sobrien TRUE, 0xff, 0xff, FALSE), 104130570Sobrien HOWTO(R_386_PC8, 0, 0, 8, TRUE, 0, complain_overflow_signed, 10577302Sobrien bfd_elf_generic_reloc, "R_386_PC8", 106130570Sobrien TRUE, 0xff, 0xff, TRUE), 10733965Sjdp 108130570Sobrien#define R_386_ext (R_386_PC8 + 1 - R_386_ext_offset) 109130570Sobrien#define R_386_tls_offset (R_386_TLS_LDO_32 - R_386_ext) 110104840Sobrien /* These are common with Solaris TLS implementation. */ 111130570Sobrien HOWTO(R_386_TLS_LDO_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 112104840Sobrien bfd_elf_generic_reloc, "R_386_TLS_LDO_32", 113130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 114130570Sobrien HOWTO(R_386_TLS_IE_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 115104840Sobrien bfd_elf_generic_reloc, "R_386_TLS_IE_32", 116130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 117130570Sobrien HOWTO(R_386_TLS_LE_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 118104840Sobrien bfd_elf_generic_reloc, "R_386_TLS_LE_32", 119130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 120130570Sobrien HOWTO(R_386_TLS_DTPMOD32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 121104840Sobrien bfd_elf_generic_reloc, "R_386_TLS_DTPMOD32", 122130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 123130570Sobrien HOWTO(R_386_TLS_DTPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 124104840Sobrien bfd_elf_generic_reloc, "R_386_TLS_DTPOFF32", 125130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 126130570Sobrien HOWTO(R_386_TLS_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 127104840Sobrien bfd_elf_generic_reloc, "R_386_TLS_TPOFF32", 128130570Sobrien TRUE, 0xffffffff, 0xffffffff, FALSE), 129218822Sdim EMPTY_HOWTO (38), 130218822Sdim HOWTO(R_386_TLS_GOTDESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 131218822Sdim bfd_elf_generic_reloc, "R_386_TLS_GOTDESC", 132218822Sdim TRUE, 0xffffffff, 0xffffffff, FALSE), 133218822Sdim HOWTO(R_386_TLS_DESC_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont, 134218822Sdim bfd_elf_generic_reloc, "R_386_TLS_DESC_CALL", 135218822Sdim FALSE, 0, 0, FALSE), 136218822Sdim HOWTO(R_386_TLS_DESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, 137218822Sdim bfd_elf_generic_reloc, "R_386_TLS_DESC", 138218822Sdim TRUE, 0xffffffff, 0xffffffff, FALSE), 13977302Sobrien 140104840Sobrien /* Another gap. */ 141218822Sdim#define R_386_tls (R_386_TLS_DESC + 1 - R_386_tls_offset) 142130570Sobrien#define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_tls) 143104840Sobrien 14460509Sobrien/* GNU extension to record C++ vtable hierarchy. */ 14560509Sobrien HOWTO (R_386_GNU_VTINHERIT, /* type */ 14660509Sobrien 0, /* rightshift */ 14760509Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 14860509Sobrien 0, /* bitsize */ 149130570Sobrien FALSE, /* pc_relative */ 15060509Sobrien 0, /* bitpos */ 15160509Sobrien complain_overflow_dont, /* complain_on_overflow */ 15260509Sobrien NULL, /* special_function */ 15360509Sobrien "R_386_GNU_VTINHERIT", /* name */ 154130570Sobrien FALSE, /* partial_inplace */ 15560509Sobrien 0, /* src_mask */ 15660509Sobrien 0, /* dst_mask */ 157130570Sobrien FALSE), /* pcrel_offset */ 15860509Sobrien 15960509Sobrien/* GNU extension to record C++ vtable member usage. */ 16060509Sobrien HOWTO (R_386_GNU_VTENTRY, /* type */ 16160509Sobrien 0, /* rightshift */ 16260509Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 16360509Sobrien 0, /* bitsize */ 164130570Sobrien FALSE, /* pc_relative */ 16560509Sobrien 0, /* bitpos */ 16660509Sobrien complain_overflow_dont, /* complain_on_overflow */ 16760509Sobrien _bfd_elf_rel_vtable_reloc_fn, /* special_function */ 16860509Sobrien "R_386_GNU_VTENTRY", /* name */ 169130570Sobrien FALSE, /* partial_inplace */ 17060509Sobrien 0, /* src_mask */ 17160509Sobrien 0, /* dst_mask */ 172130570Sobrien FALSE) /* pcrel_offset */ 17360509Sobrien 174130570Sobrien#define R_386_vt (R_386_GNU_VTENTRY + 1 - R_386_vt_offset) 17577302Sobrien 17677302Sobrien}; 17777302Sobrien 17833965Sjdp#ifdef DEBUG_GEN_RELOC 179130570Sobrien#define TRACE(str) \ 180130570Sobrien fprintf (stderr, "i386 bfd reloc lookup %d (%s)\n", code, str) 18133965Sjdp#else 18233965Sjdp#define TRACE(str) 18333965Sjdp#endif 18433965Sjdp 18533965Sjdpstatic reloc_howto_type * 186130570Sobrienelf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 187130570Sobrien bfd_reloc_code_real_type code) 18833965Sjdp{ 18933965Sjdp switch (code) 19033965Sjdp { 19133965Sjdp case BFD_RELOC_NONE: 19233965Sjdp TRACE ("BFD_RELOC_NONE"); 193130570Sobrien return &elf_howto_table[R_386_NONE]; 19433965Sjdp 19533965Sjdp case BFD_RELOC_32: 19633965Sjdp TRACE ("BFD_RELOC_32"); 197130570Sobrien return &elf_howto_table[R_386_32]; 19833965Sjdp 19960509Sobrien case BFD_RELOC_CTOR: 20060509Sobrien TRACE ("BFD_RELOC_CTOR"); 201130570Sobrien return &elf_howto_table[R_386_32]; 20260509Sobrien 20333965Sjdp case BFD_RELOC_32_PCREL: 20433965Sjdp TRACE ("BFD_RELOC_PC32"); 205130570Sobrien return &elf_howto_table[R_386_PC32]; 20633965Sjdp 20733965Sjdp case BFD_RELOC_386_GOT32: 20833965Sjdp TRACE ("BFD_RELOC_386_GOT32"); 209130570Sobrien return &elf_howto_table[R_386_GOT32]; 21033965Sjdp 21133965Sjdp case BFD_RELOC_386_PLT32: 21233965Sjdp TRACE ("BFD_RELOC_386_PLT32"); 213130570Sobrien return &elf_howto_table[R_386_PLT32]; 21433965Sjdp 21533965Sjdp case BFD_RELOC_386_COPY: 21633965Sjdp TRACE ("BFD_RELOC_386_COPY"); 217130570Sobrien return &elf_howto_table[R_386_COPY]; 21833965Sjdp 21933965Sjdp case BFD_RELOC_386_GLOB_DAT: 22033965Sjdp TRACE ("BFD_RELOC_386_GLOB_DAT"); 221130570Sobrien return &elf_howto_table[R_386_GLOB_DAT]; 22233965Sjdp 22333965Sjdp case BFD_RELOC_386_JUMP_SLOT: 22433965Sjdp TRACE ("BFD_RELOC_386_JUMP_SLOT"); 225130570Sobrien return &elf_howto_table[R_386_JUMP_SLOT]; 22633965Sjdp 22733965Sjdp case BFD_RELOC_386_RELATIVE: 22833965Sjdp TRACE ("BFD_RELOC_386_RELATIVE"); 229130570Sobrien return &elf_howto_table[R_386_RELATIVE]; 23033965Sjdp 23133965Sjdp case BFD_RELOC_386_GOTOFF: 23233965Sjdp TRACE ("BFD_RELOC_386_GOTOFF"); 233130570Sobrien return &elf_howto_table[R_386_GOTOFF]; 23433965Sjdp 23533965Sjdp case BFD_RELOC_386_GOTPC: 23633965Sjdp TRACE ("BFD_RELOC_386_GOTPC"); 237130570Sobrien return &elf_howto_table[R_386_GOTPC]; 23833965Sjdp 239104840Sobrien /* These relocs are a GNU extension. */ 240104840Sobrien case BFD_RELOC_386_TLS_TPOFF: 241104840Sobrien TRACE ("BFD_RELOC_386_TLS_TPOFF"); 242130570Sobrien return &elf_howto_table[R_386_TLS_TPOFF - R_386_ext_offset]; 243104840Sobrien 244104840Sobrien case BFD_RELOC_386_TLS_IE: 245104840Sobrien TRACE ("BFD_RELOC_386_TLS_IE"); 246130570Sobrien return &elf_howto_table[R_386_TLS_IE - R_386_ext_offset]; 247104840Sobrien 248104840Sobrien case BFD_RELOC_386_TLS_GOTIE: 249104840Sobrien TRACE ("BFD_RELOC_386_TLS_GOTIE"); 250130570Sobrien return &elf_howto_table[R_386_TLS_GOTIE - R_386_ext_offset]; 251104840Sobrien 252104840Sobrien case BFD_RELOC_386_TLS_LE: 253104840Sobrien TRACE ("BFD_RELOC_386_TLS_LE"); 254130570Sobrien return &elf_howto_table[R_386_TLS_LE - R_386_ext_offset]; 255104840Sobrien 256104840Sobrien case BFD_RELOC_386_TLS_GD: 257104840Sobrien TRACE ("BFD_RELOC_386_TLS_GD"); 258130570Sobrien return &elf_howto_table[R_386_TLS_GD - R_386_ext_offset]; 259104840Sobrien 260104840Sobrien case BFD_RELOC_386_TLS_LDM: 261104840Sobrien TRACE ("BFD_RELOC_386_TLS_LDM"); 262130570Sobrien return &elf_howto_table[R_386_TLS_LDM - R_386_ext_offset]; 263104840Sobrien 26433965Sjdp case BFD_RELOC_16: 26533965Sjdp TRACE ("BFD_RELOC_16"); 266130570Sobrien return &elf_howto_table[R_386_16 - R_386_ext_offset]; 26733965Sjdp 26833965Sjdp case BFD_RELOC_16_PCREL: 26933965Sjdp TRACE ("BFD_RELOC_16_PCREL"); 270130570Sobrien return &elf_howto_table[R_386_PC16 - R_386_ext_offset]; 27133965Sjdp 27233965Sjdp case BFD_RELOC_8: 27333965Sjdp TRACE ("BFD_RELOC_8"); 274130570Sobrien return &elf_howto_table[R_386_8 - R_386_ext_offset]; 27533965Sjdp 27633965Sjdp case BFD_RELOC_8_PCREL: 27733965Sjdp TRACE ("BFD_RELOC_8_PCREL"); 278130570Sobrien return &elf_howto_table[R_386_PC8 - R_386_ext_offset]; 27933965Sjdp 280104840Sobrien /* Common with Sun TLS implementation. */ 281104840Sobrien case BFD_RELOC_386_TLS_LDO_32: 282104840Sobrien TRACE ("BFD_RELOC_386_TLS_LDO_32"); 283130570Sobrien return &elf_howto_table[R_386_TLS_LDO_32 - R_386_tls_offset]; 284104840Sobrien 285104840Sobrien case BFD_RELOC_386_TLS_IE_32: 286104840Sobrien TRACE ("BFD_RELOC_386_TLS_IE_32"); 287130570Sobrien return &elf_howto_table[R_386_TLS_IE_32 - R_386_tls_offset]; 288104840Sobrien 289104840Sobrien case BFD_RELOC_386_TLS_LE_32: 290104840Sobrien TRACE ("BFD_RELOC_386_TLS_LE_32"); 291130570Sobrien return &elf_howto_table[R_386_TLS_LE_32 - R_386_tls_offset]; 292104840Sobrien 293104840Sobrien case BFD_RELOC_386_TLS_DTPMOD32: 294104840Sobrien TRACE ("BFD_RELOC_386_TLS_DTPMOD32"); 295130570Sobrien return &elf_howto_table[R_386_TLS_DTPMOD32 - R_386_tls_offset]; 296104840Sobrien 297104840Sobrien case BFD_RELOC_386_TLS_DTPOFF32: 298104840Sobrien TRACE ("BFD_RELOC_386_TLS_DTPOFF32"); 299130570Sobrien return &elf_howto_table[R_386_TLS_DTPOFF32 - R_386_tls_offset]; 300104840Sobrien 301104840Sobrien case BFD_RELOC_386_TLS_TPOFF32: 302104840Sobrien TRACE ("BFD_RELOC_386_TLS_TPOFF32"); 303130570Sobrien return &elf_howto_table[R_386_TLS_TPOFF32 - R_386_tls_offset]; 304104840Sobrien 305218822Sdim case BFD_RELOC_386_TLS_GOTDESC: 306218822Sdim TRACE ("BFD_RELOC_386_TLS_GOTDESC"); 307218822Sdim return &elf_howto_table[R_386_TLS_GOTDESC - R_386_tls_offset]; 308218822Sdim 309218822Sdim case BFD_RELOC_386_TLS_DESC_CALL: 310218822Sdim TRACE ("BFD_RELOC_386_TLS_DESC_CALL"); 311218822Sdim return &elf_howto_table[R_386_TLS_DESC_CALL - R_386_tls_offset]; 312218822Sdim 313218822Sdim case BFD_RELOC_386_TLS_DESC: 314218822Sdim TRACE ("BFD_RELOC_386_TLS_DESC"); 315218822Sdim return &elf_howto_table[R_386_TLS_DESC - R_386_tls_offset]; 316218822Sdim 31760509Sobrien case BFD_RELOC_VTABLE_INHERIT: 31860509Sobrien TRACE ("BFD_RELOC_VTABLE_INHERIT"); 319130570Sobrien return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset]; 32060509Sobrien 32160509Sobrien case BFD_RELOC_VTABLE_ENTRY: 32260509Sobrien TRACE ("BFD_RELOC_VTABLE_ENTRY"); 323130570Sobrien return &elf_howto_table[R_386_GNU_VTENTRY - R_386_vt_offset]; 32460509Sobrien 32533965Sjdp default: 32633965Sjdp break; 32733965Sjdp } 32833965Sjdp 32933965Sjdp TRACE ("Unknown"); 33033965Sjdp return 0; 33133965Sjdp} 33233965Sjdp 333218822Sdimstatic reloc_howto_type * 334218822Sdimelf_i386_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 335218822Sdim const char *r_name) 336218822Sdim{ 337218822Sdim unsigned int i; 338218822Sdim 339218822Sdim for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++) 340218822Sdim if (elf_howto_table[i].name != NULL 341218822Sdim && strcasecmp (elf_howto_table[i].name, r_name) == 0) 342218822Sdim return &elf_howto_table[i]; 343218822Sdim 344218822Sdim return NULL; 345218822Sdim} 346218822Sdim 34733965Sjdpstatic void 348130570Sobrienelf_i386_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED, 349130570Sobrien arelent *cache_ptr, 350130570Sobrien Elf_Internal_Rela *dst) 35133965Sjdp{ 35277302Sobrien unsigned int r_type = ELF32_R_TYPE (dst->r_info); 35377302Sobrien unsigned int indx; 35433965Sjdp 35577302Sobrien if ((indx = r_type) >= R_386_standard 35677302Sobrien && ((indx = r_type - R_386_ext_offset) - R_386_standard 35777302Sobrien >= R_386_ext - R_386_standard) 358104840Sobrien && ((indx = r_type - R_386_tls_offset) - R_386_ext 359104840Sobrien >= R_386_tls - R_386_ext) 360104840Sobrien && ((indx = r_type - R_386_vt_offset) - R_386_tls 361104840Sobrien >= R_386_vt - R_386_tls)) 36260509Sobrien { 363218822Sdim (*_bfd_error_handler) (_("%B: invalid relocation type %d"), 364218822Sdim abfd, (int) r_type); 365130570Sobrien indx = R_386_NONE; 36660509Sobrien } 36777302Sobrien cache_ptr->howto = &elf_howto_table[indx]; 36833965Sjdp} 36933965Sjdp 37033965Sjdp/* Return whether a symbol name implies a local label. The UnixWare 37133965Sjdp 2.1 cc generates temporary symbols that start with .X, so we 37233965Sjdp recognize them here. FIXME: do other SVR4 compilers also use .X?. 37333965Sjdp If so, we should move the .X recognition into 37433965Sjdp _bfd_elf_is_local_label_name. */ 37533965Sjdp 376130570Sobrienstatic bfd_boolean 377130570Sobrienelf_i386_is_local_label_name (bfd *abfd, const char *name) 37833965Sjdp{ 37933965Sjdp if (name[0] == '.' && name[1] == 'X') 380130570Sobrien return TRUE; 38133965Sjdp 38233965Sjdp return _bfd_elf_is_local_label_name (abfd, name); 38333965Sjdp} 38433965Sjdp 38589861Sobrien/* Support for core dump NOTE sections. */ 386130570Sobrien 387130570Sobrienstatic bfd_boolean 388130570Sobrienelf_i386_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) 38989861Sobrien{ 39089861Sobrien int offset; 391218822Sdim size_t size; 39233965Sjdp 393130570Sobrien if (note->namesz == 8 && strcmp (note->namedata, "FreeBSD") == 0) 39489861Sobrien { 395130570Sobrien int pr_version = bfd_get_32 (abfd, note->descdata); 39689861Sobrien 397130570Sobrien if (pr_version != 1) 398130570Sobrien return FALSE; 39989861Sobrien 400130570Sobrien /* pr_cursig */ 401130570Sobrien elf_tdata (abfd)->core_signal = bfd_get_32 (abfd, note->descdata + 20); 40289861Sobrien 403130570Sobrien /* pr_pid */ 404130570Sobrien elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); 40589861Sobrien 406130570Sobrien /* pr_reg */ 407130570Sobrien offset = 28; 408218822Sdim size = bfd_get_32 (abfd, note->descdata + 8); 40989861Sobrien } 410130570Sobrien else 411130570Sobrien { 412130570Sobrien switch (note->descsz) 413130570Sobrien { 414130570Sobrien default: 415130570Sobrien return FALSE; 41689861Sobrien 417130570Sobrien case 144: /* Linux/i386 */ 418130570Sobrien /* pr_cursig */ 419130570Sobrien elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); 420130570Sobrien 421130570Sobrien /* pr_pid */ 422130570Sobrien elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); 423130570Sobrien 424130570Sobrien /* pr_reg */ 425130570Sobrien offset = 72; 426218822Sdim size = 68; 427130570Sobrien 428130570Sobrien break; 429130570Sobrien } 430130570Sobrien } 431130570Sobrien 43289861Sobrien /* Make a ".reg/999" section. */ 43389861Sobrien return _bfd_elfcore_make_pseudosection (abfd, ".reg", 434218822Sdim size, note->descpos + offset); 43589861Sobrien} 43689861Sobrien 437130570Sobrienstatic bfd_boolean 438130570Sobrienelf_i386_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) 43989861Sobrien{ 440130570Sobrien if (note->namesz == 8 && strcmp (note->namedata, "FreeBSD") == 0) 44189861Sobrien { 442130570Sobrien int pr_version = bfd_get_32 (abfd, note->descdata); 44389861Sobrien 444130570Sobrien if (pr_version != 1) 445130570Sobrien return FALSE; 446130570Sobrien 447130570Sobrien elf_tdata (abfd)->core_program 448130570Sobrien = _bfd_elfcore_strndup (abfd, note->descdata + 8, 17); 449130570Sobrien elf_tdata (abfd)->core_command 450130570Sobrien = _bfd_elfcore_strndup (abfd, note->descdata + 25, 81); 45189861Sobrien } 452130570Sobrien else 453130570Sobrien { 454130570Sobrien switch (note->descsz) 455130570Sobrien { 456130570Sobrien default: 457130570Sobrien return FALSE; 45889861Sobrien 459130570Sobrien case 124: /* Linux/i386 elf_prpsinfo. */ 460130570Sobrien elf_tdata (abfd)->core_program 461130570Sobrien = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16); 462130570Sobrien elf_tdata (abfd)->core_command 463130570Sobrien = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80); 464130570Sobrien } 465130570Sobrien } 466130570Sobrien 46789861Sobrien /* Note that for some reason, a spurious space is tacked 46889861Sobrien onto the end of the args in some (at least one anyway) 46989861Sobrien implementations, so strip it off if it exists. */ 47089861Sobrien { 47189861Sobrien char *command = elf_tdata (abfd)->core_command; 47289861Sobrien int n = strlen (command); 47389861Sobrien 47489861Sobrien if (0 < n && command[n - 1] == ' ') 47589861Sobrien command[n - 1] = '\0'; 47689861Sobrien } 47789861Sobrien 478130570Sobrien return TRUE; 47989861Sobrien} 48089861Sobrien 48189861Sobrien/* Functions for the i386 ELF linker. 48289861Sobrien 48389861Sobrien In order to gain some understanding of code in this file without 48489861Sobrien knowing all the intricate details of the linker, note the 48589861Sobrien following: 48689861Sobrien 48789861Sobrien Functions named elf_i386_* are called by external routines, other 48889861Sobrien functions are only called locally. elf_i386_* functions appear 48989861Sobrien in this file more or less in the order in which they are called 49089861Sobrien from external routines. eg. elf_i386_check_relocs is called 49189861Sobrien early in the link process, elf_i386_finish_dynamic_sections is 49289861Sobrien one of the last functions. */ 49389861Sobrien 49489861Sobrien 49533965Sjdp/* The name of the dynamic interpreter. This is put in the .interp 49633965Sjdp section. */ 49733965Sjdp 49868769Sobrien#define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1" 49933965Sjdp 500130570Sobrien/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid 501130570Sobrien copying dynamic variables from a shared lib into an app's dynbss 502130570Sobrien section, and instead use a dynamic relocation to point into the 503130570Sobrien shared lib. */ 504130570Sobrien#define ELIMINATE_COPY_RELOCS 1 505130570Sobrien 50633965Sjdp/* The size in bytes of an entry in the procedure linkage table. */ 50733965Sjdp 50833965Sjdp#define PLT_ENTRY_SIZE 16 50933965Sjdp 51033965Sjdp/* The first entry in an absolute procedure linkage table looks like 511218822Sdim this. See the SVR4 ABI i386 supplement to see how this works. 512218822Sdim Will be padded to PLT_ENTRY_SIZE with htab->plt0_pad_byte. */ 51333965Sjdp 514218822Sdimstatic const bfd_byte elf_i386_plt0_entry[12] = 51533965Sjdp{ 51633965Sjdp 0xff, 0x35, /* pushl contents of address */ 51733965Sjdp 0, 0, 0, 0, /* replaced with address of .got + 4. */ 51833965Sjdp 0xff, 0x25, /* jmp indirect */ 519218822Sdim 0, 0, 0, 0 /* replaced with address of .got + 8. */ 52033965Sjdp}; 52133965Sjdp 52233965Sjdp/* Subsequent entries in an absolute procedure linkage table look like 52333965Sjdp this. */ 52433965Sjdp 52533965Sjdpstatic const bfd_byte elf_i386_plt_entry[PLT_ENTRY_SIZE] = 52633965Sjdp{ 52733965Sjdp 0xff, 0x25, /* jmp indirect */ 52833965Sjdp 0, 0, 0, 0, /* replaced with address of this symbol in .got. */ 52933965Sjdp 0x68, /* pushl immediate */ 53033965Sjdp 0, 0, 0, 0, /* replaced with offset into relocation table. */ 53133965Sjdp 0xe9, /* jmp relative */ 53233965Sjdp 0, 0, 0, 0 /* replaced with offset to start of .plt. */ 53333965Sjdp}; 53433965Sjdp 535218822Sdim/* The first entry in a PIC procedure linkage table look like this. 536218822Sdim Will be padded to PLT_ENTRY_SIZE with htab->plt0_pad_byte. */ 53733965Sjdp 538218822Sdimstatic const bfd_byte elf_i386_pic_plt0_entry[12] = 53933965Sjdp{ 54033965Sjdp 0xff, 0xb3, 4, 0, 0, 0, /* pushl 4(%ebx) */ 541218822Sdim 0xff, 0xa3, 8, 0, 0, 0 /* jmp *8(%ebx) */ 54233965Sjdp}; 54333965Sjdp 54433965Sjdp/* Subsequent entries in a PIC procedure linkage table look like this. */ 54533965Sjdp 54633965Sjdpstatic const bfd_byte elf_i386_pic_plt_entry[PLT_ENTRY_SIZE] = 54733965Sjdp{ 54833965Sjdp 0xff, 0xa3, /* jmp *offset(%ebx) */ 54933965Sjdp 0, 0, 0, 0, /* replaced with offset of this symbol in .got. */ 55033965Sjdp 0x68, /* pushl immediate */ 55133965Sjdp 0, 0, 0, 0, /* replaced with offset into relocation table. */ 55233965Sjdp 0xe9, /* jmp relative */ 55333965Sjdp 0, 0, 0, 0 /* replaced with offset to start of .plt. */ 55433965Sjdp}; 55533965Sjdp 556218822Sdim/* On VxWorks, the .rel.plt.unloaded section has absolute relocations 557218822Sdim for the PLTResolve stub and then for each PLT entry. */ 558218822Sdim#define PLTRESOLVE_RELOCS_SHLIB 0 559218822Sdim#define PLTRESOLVE_RELOCS 2 560218822Sdim#define PLT_NON_JUMP_SLOT_RELOCS 2 561218822Sdim 56233965Sjdp/* The i386 linker needs to keep track of the number of relocs that it 56389861Sobrien decides to copy as dynamic relocs in check_relocs for each symbol. 56489861Sobrien This is so that it can later discard them if they are found to be 56589861Sobrien unnecessary. We store the information in a field extending the 56689861Sobrien regular ELF linker hash table. */ 56733965Sjdp 56889861Sobrienstruct elf_i386_dyn_relocs 56989861Sobrien{ 57089861Sobrien struct elf_i386_dyn_relocs *next; 57133965Sjdp 57289861Sobrien /* The input section of the reloc. */ 57389861Sobrien asection *sec; 57489861Sobrien 57589861Sobrien /* Total number of relocs copied for the input section. */ 57633965Sjdp bfd_size_type count; 57789861Sobrien 57889861Sobrien /* Number of pc-relative relocs copied for the input section. */ 57989861Sobrien bfd_size_type pc_count; 58033965Sjdp}; 58133965Sjdp 58233965Sjdp/* i386 ELF linker hash entry. */ 58333965Sjdp 58433965Sjdpstruct elf_i386_link_hash_entry 58533965Sjdp{ 58689861Sobrien struct elf_link_hash_entry elf; 58733965Sjdp 58889861Sobrien /* Track dynamic relocs copied for this symbol. */ 58989861Sobrien struct elf_i386_dyn_relocs *dyn_relocs; 590104840Sobrien 591104840Sobrien#define GOT_UNKNOWN 0 592104840Sobrien#define GOT_NORMAL 1 593104840Sobrien#define GOT_TLS_GD 2 594104840Sobrien#define GOT_TLS_IE 4 595104840Sobrien#define GOT_TLS_IE_POS 5 596104840Sobrien#define GOT_TLS_IE_NEG 6 597104840Sobrien#define GOT_TLS_IE_BOTH 7 598218822Sdim#define GOT_TLS_GDESC 8 599218822Sdim#define GOT_TLS_GD_BOTH_P(type) \ 600218822Sdim ((type) == (GOT_TLS_GD | GOT_TLS_GDESC)) 601218822Sdim#define GOT_TLS_GD_P(type) \ 602218822Sdim ((type) == GOT_TLS_GD || GOT_TLS_GD_BOTH_P (type)) 603218822Sdim#define GOT_TLS_GDESC_P(type) \ 604218822Sdim ((type) == GOT_TLS_GDESC || GOT_TLS_GD_BOTH_P (type)) 605218822Sdim#define GOT_TLS_GD_ANY_P(type) \ 606218822Sdim (GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type)) 607104840Sobrien unsigned char tls_type; 608218822Sdim 609218822Sdim /* Offset of the GOTPLT entry reserved for the TLS descriptor, 610218822Sdim starting at the end of the jump table. */ 611218822Sdim bfd_vma tlsdesc_got; 61233965Sjdp}; 61333965Sjdp 614104840Sobrien#define elf_i386_hash_entry(ent) ((struct elf_i386_link_hash_entry *)(ent)) 615104840Sobrien 616104840Sobrienstruct elf_i386_obj_tdata 617104840Sobrien{ 618104840Sobrien struct elf_obj_tdata root; 619104840Sobrien 620104840Sobrien /* tls_type for each local got entry. */ 621104840Sobrien char *local_got_tls_type; 622218822Sdim 623218822Sdim /* GOTPLT entries for TLS descriptors. */ 624218822Sdim bfd_vma *local_tlsdesc_gotent; 625104840Sobrien}; 626104840Sobrien 627104840Sobrien#define elf_i386_tdata(abfd) \ 628104840Sobrien ((struct elf_i386_obj_tdata *) (abfd)->tdata.any) 629104840Sobrien 630104840Sobrien#define elf_i386_local_got_tls_type(abfd) \ 631104840Sobrien (elf_i386_tdata (abfd)->local_got_tls_type) 632104840Sobrien 633218822Sdim#define elf_i386_local_tlsdesc_gotent(abfd) \ 634218822Sdim (elf_i386_tdata (abfd)->local_tlsdesc_gotent) 635218822Sdim 636130570Sobrienstatic bfd_boolean 637130570Sobrienelf_i386_mkobject (bfd *abfd) 638104840Sobrien{ 639104840Sobrien if (abfd->tdata.any == NULL) 640218822Sdim { 641218822Sdim bfd_size_type amt = sizeof (struct elf_i386_obj_tdata); 642218822Sdim abfd->tdata.any = bfd_zalloc (abfd, amt); 643218822Sdim if (abfd->tdata.any == NULL) 644218822Sdim return FALSE; 645218822Sdim } 646218822Sdim return bfd_elf_mkobject (abfd); 647104840Sobrien} 648104840Sobrien 64933965Sjdp/* i386 ELF linker hash table. */ 65033965Sjdp 65133965Sjdpstruct elf_i386_link_hash_table 65233965Sjdp{ 65389861Sobrien struct elf_link_hash_table elf; 65433965Sjdp 65589861Sobrien /* Short-cuts to get to dynamic linker sections. */ 65689861Sobrien asection *sgot; 65789861Sobrien asection *sgotplt; 65889861Sobrien asection *srelgot; 65989861Sobrien asection *splt; 66089861Sobrien asection *srelplt; 66189861Sobrien asection *sdynbss; 66289861Sobrien asection *srelbss; 66333965Sjdp 664218822Sdim /* The (unloaded but important) .rel.plt.unloaded section on VxWorks. */ 665218822Sdim asection *srelplt2; 666218822Sdim 667218822Sdim /* True if the target system is VxWorks. */ 668218822Sdim int is_vxworks; 669218822Sdim 670218822Sdim /* Value used to fill the last word of the first plt entry. */ 671218822Sdim bfd_byte plt0_pad_byte; 672218822Sdim 673218822Sdim /* The index of the next unused R_386_TLS_DESC slot in .rel.plt. */ 674218822Sdim bfd_vma next_tls_desc_index; 675218822Sdim 676104840Sobrien union { 677104840Sobrien bfd_signed_vma refcount; 678104840Sobrien bfd_vma offset; 679104840Sobrien } tls_ldm_got; 680104840Sobrien 681218822Sdim /* The amount of space used by the reserved portion of the sgotplt 682218822Sdim section, plus whatever space is used by the jump slots. */ 683218822Sdim bfd_vma sgotplt_jump_table_size; 684218822Sdim 68589861Sobrien /* Small local sym to section mapping cache. */ 68689861Sobrien struct sym_sec_cache sym_sec; 68789861Sobrien}; 68833965Sjdp 68933965Sjdp/* Get the i386 ELF linker hash table from a link_info structure. */ 69033965Sjdp 69133965Sjdp#define elf_i386_hash_table(p) \ 69233965Sjdp ((struct elf_i386_link_hash_table *) ((p)->hash)) 69333965Sjdp 694218822Sdim#define elf_i386_compute_jump_table_size(htab) \ 695218822Sdim ((htab)->next_tls_desc_index * 4) 696218822Sdim 69733965Sjdp/* Create an entry in an i386 ELF linker hash table. */ 69833965Sjdp 69933965Sjdpstatic struct bfd_hash_entry * 700130570Sobrienlink_hash_newfunc (struct bfd_hash_entry *entry, 701130570Sobrien struct bfd_hash_table *table, 702130570Sobrien const char *string) 70333965Sjdp{ 70433965Sjdp /* Allocate the structure if it has not already been allocated by a 70533965Sjdp subclass. */ 70689861Sobrien if (entry == NULL) 70789861Sobrien { 70889861Sobrien entry = bfd_hash_allocate (table, 70989861Sobrien sizeof (struct elf_i386_link_hash_entry)); 71089861Sobrien if (entry == NULL) 71189861Sobrien return entry; 71289861Sobrien } 71333965Sjdp 71433965Sjdp /* Call the allocation method of the superclass. */ 71589861Sobrien entry = _bfd_elf_link_hash_newfunc (entry, table, string); 71689861Sobrien if (entry != NULL) 71733965Sjdp { 71889861Sobrien struct elf_i386_link_hash_entry *eh; 71989861Sobrien 72089861Sobrien eh = (struct elf_i386_link_hash_entry *) entry; 72189861Sobrien eh->dyn_relocs = NULL; 722104840Sobrien eh->tls_type = GOT_UNKNOWN; 723218822Sdim eh->tlsdesc_got = (bfd_vma) -1; 72433965Sjdp } 72533965Sjdp 72689861Sobrien return entry; 72733965Sjdp} 72833965Sjdp 72933965Sjdp/* Create an i386 ELF linker hash table. */ 73033965Sjdp 73133965Sjdpstatic struct bfd_link_hash_table * 732130570Sobrienelf_i386_link_hash_table_create (bfd *abfd) 73333965Sjdp{ 73433965Sjdp struct elf_i386_link_hash_table *ret; 73589861Sobrien bfd_size_type amt = sizeof (struct elf_i386_link_hash_table); 73633965Sjdp 737130570Sobrien ret = bfd_malloc (amt); 73889861Sobrien if (ret == NULL) 73933965Sjdp return NULL; 74033965Sjdp 741218822Sdim if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc, 742218822Sdim sizeof (struct elf_i386_link_hash_entry))) 74333965Sjdp { 744104840Sobrien free (ret); 74533965Sjdp return NULL; 74633965Sjdp } 74733965Sjdp 74889861Sobrien ret->sgot = NULL; 74989861Sobrien ret->sgotplt = NULL; 75089861Sobrien ret->srelgot = NULL; 75189861Sobrien ret->splt = NULL; 75289861Sobrien ret->srelplt = NULL; 75389861Sobrien ret->sdynbss = NULL; 75489861Sobrien ret->srelbss = NULL; 755104840Sobrien ret->tls_ldm_got.refcount = 0; 756218822Sdim ret->next_tls_desc_index = 0; 757218822Sdim ret->sgotplt_jump_table_size = 0; 75889861Sobrien ret->sym_sec.abfd = NULL; 759218822Sdim ret->is_vxworks = 0; 760218822Sdim ret->srelplt2 = NULL; 761218822Sdim ret->plt0_pad_byte = 0; 76289861Sobrien 76389861Sobrien return &ret->elf.root; 76433965Sjdp} 76533965Sjdp 76689861Sobrien/* Create .got, .gotplt, and .rel.got sections in DYNOBJ, and set up 76789861Sobrien shortcuts to them in our hash table. */ 76889861Sobrien 769130570Sobrienstatic bfd_boolean 770130570Sobriencreate_got_section (bfd *dynobj, struct bfd_link_info *info) 77189861Sobrien{ 77289861Sobrien struct elf_i386_link_hash_table *htab; 77389861Sobrien 77489861Sobrien if (! _bfd_elf_create_got_section (dynobj, info)) 775130570Sobrien return FALSE; 77689861Sobrien 77789861Sobrien htab = elf_i386_hash_table (info); 77889861Sobrien htab->sgot = bfd_get_section_by_name (dynobj, ".got"); 77989861Sobrien htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt"); 78089861Sobrien if (!htab->sgot || !htab->sgotplt) 78189861Sobrien abort (); 78289861Sobrien 783218822Sdim htab->srelgot = bfd_make_section_with_flags (dynobj, ".rel.got", 784218822Sdim (SEC_ALLOC | SEC_LOAD 785218822Sdim | SEC_HAS_CONTENTS 786218822Sdim | SEC_IN_MEMORY 787218822Sdim | SEC_LINKER_CREATED 788218822Sdim | SEC_READONLY)); 78989861Sobrien if (htab->srelgot == NULL 79089861Sobrien || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2)) 791130570Sobrien return FALSE; 792130570Sobrien return TRUE; 79389861Sobrien} 79489861Sobrien 79589861Sobrien/* Create .plt, .rel.plt, .got, .got.plt, .rel.got, .dynbss, and 79689861Sobrien .rel.bss sections in DYNOBJ, and set up shortcuts to them in our 79789861Sobrien hash table. */ 79889861Sobrien 799130570Sobrienstatic bfd_boolean 800130570Sobrienelf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) 80189861Sobrien{ 80289861Sobrien struct elf_i386_link_hash_table *htab; 80389861Sobrien 80489861Sobrien htab = elf_i386_hash_table (info); 80589861Sobrien if (!htab->sgot && !create_got_section (dynobj, info)) 806130570Sobrien return FALSE; 80789861Sobrien 80889861Sobrien if (!_bfd_elf_create_dynamic_sections (dynobj, info)) 809130570Sobrien return FALSE; 81089861Sobrien 81189861Sobrien htab->splt = bfd_get_section_by_name (dynobj, ".plt"); 81289861Sobrien htab->srelplt = bfd_get_section_by_name (dynobj, ".rel.plt"); 81389861Sobrien htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss"); 81489861Sobrien if (!info->shared) 81589861Sobrien htab->srelbss = bfd_get_section_by_name (dynobj, ".rel.bss"); 81689861Sobrien 81789861Sobrien if (!htab->splt || !htab->srelplt || !htab->sdynbss 81889861Sobrien || (!info->shared && !htab->srelbss)) 81989861Sobrien abort (); 82089861Sobrien 821218822Sdim if (htab->is_vxworks 822218822Sdim && !elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2)) 823218822Sdim return FALSE; 824218822Sdim 825130570Sobrien return TRUE; 82689861Sobrien} 82789861Sobrien 82889861Sobrien/* Copy the extra info we tack onto an elf_link_hash_entry. */ 82989861Sobrien 83089861Sobrienstatic void 831218822Sdimelf_i386_copy_indirect_symbol (struct bfd_link_info *info, 832130570Sobrien struct elf_link_hash_entry *dir, 833130570Sobrien struct elf_link_hash_entry *ind) 83489861Sobrien{ 83589861Sobrien struct elf_i386_link_hash_entry *edir, *eind; 83689861Sobrien 83789861Sobrien edir = (struct elf_i386_link_hash_entry *) dir; 83889861Sobrien eind = (struct elf_i386_link_hash_entry *) ind; 83989861Sobrien 84089861Sobrien if (eind->dyn_relocs != NULL) 84189861Sobrien { 84289861Sobrien if (edir->dyn_relocs != NULL) 84389861Sobrien { 84489861Sobrien struct elf_i386_dyn_relocs **pp; 84589861Sobrien struct elf_i386_dyn_relocs *p; 84689861Sobrien 847218822Sdim /* Add reloc counts against the indirect sym to the direct sym 84889861Sobrien list. Merge any entries against the same section. */ 84989861Sobrien for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) 85089861Sobrien { 85189861Sobrien struct elf_i386_dyn_relocs *q; 85289861Sobrien 85389861Sobrien for (q = edir->dyn_relocs; q != NULL; q = q->next) 85489861Sobrien if (q->sec == p->sec) 85589861Sobrien { 85689861Sobrien q->pc_count += p->pc_count; 85789861Sobrien q->count += p->count; 85889861Sobrien *pp = p->next; 85989861Sobrien break; 86089861Sobrien } 86189861Sobrien if (q == NULL) 86289861Sobrien pp = &p->next; 86389861Sobrien } 86489861Sobrien *pp = edir->dyn_relocs; 86589861Sobrien } 86689861Sobrien 86789861Sobrien edir->dyn_relocs = eind->dyn_relocs; 86889861Sobrien eind->dyn_relocs = NULL; 86989861Sobrien } 87089861Sobrien 871104840Sobrien if (ind->root.type == bfd_link_hash_indirect 872104840Sobrien && dir->got.refcount <= 0) 873104840Sobrien { 874104840Sobrien edir->tls_type = eind->tls_type; 875104840Sobrien eind->tls_type = GOT_UNKNOWN; 876104840Sobrien } 877130570Sobrien 878130570Sobrien if (ELIMINATE_COPY_RELOCS 879130570Sobrien && ind->root.type != bfd_link_hash_indirect 880218822Sdim && dir->dynamic_adjusted) 881218822Sdim { 882218822Sdim /* If called to transfer flags for a weakdef during processing 883218822Sdim of elf_adjust_dynamic_symbol, don't copy non_got_ref. 884218822Sdim We clear it ourselves for ELIMINATE_COPY_RELOCS. */ 885218822Sdim dir->ref_dynamic |= ind->ref_dynamic; 886218822Sdim dir->ref_regular |= ind->ref_regular; 887218822Sdim dir->ref_regular_nonweak |= ind->ref_regular_nonweak; 888218822Sdim dir->needs_plt |= ind->needs_plt; 889218822Sdim dir->pointer_equality_needed |= ind->pointer_equality_needed; 890218822Sdim } 891130570Sobrien else 892218822Sdim _bfd_elf_link_hash_copy_indirect (info, dir, ind); 89389861Sobrien} 89489861Sobrien 895104840Sobrienstatic int 896130570Sobrienelf_i386_tls_transition (struct bfd_link_info *info, int r_type, int is_local) 897104840Sobrien{ 898104840Sobrien if (info->shared) 899104840Sobrien return r_type; 900104840Sobrien 901104840Sobrien switch (r_type) 902104840Sobrien { 903104840Sobrien case R_386_TLS_GD: 904218822Sdim case R_386_TLS_GOTDESC: 905218822Sdim case R_386_TLS_DESC_CALL: 906104840Sobrien case R_386_TLS_IE_32: 907104840Sobrien if (is_local) 908104840Sobrien return R_386_TLS_LE_32; 909104840Sobrien return R_386_TLS_IE_32; 910104840Sobrien case R_386_TLS_IE: 911104840Sobrien case R_386_TLS_GOTIE: 912104840Sobrien if (is_local) 913104840Sobrien return R_386_TLS_LE_32; 914104840Sobrien return r_type; 915104840Sobrien case R_386_TLS_LDM: 916104840Sobrien return R_386_TLS_LE_32; 917104840Sobrien } 918104840Sobrien 919104840Sobrien return r_type; 920104840Sobrien} 921104840Sobrien 92233965Sjdp/* Look through the relocs for a section during the first phase, and 92389861Sobrien calculate needed space in the global offset table, procedure linkage 92489861Sobrien table, and dynamic reloc sections. */ 92533965Sjdp 926130570Sobrienstatic bfd_boolean 927130570Sobrienelf_i386_check_relocs (bfd *abfd, 928130570Sobrien struct bfd_link_info *info, 929130570Sobrien asection *sec, 930130570Sobrien const Elf_Internal_Rela *relocs) 93133965Sjdp{ 93289861Sobrien struct elf_i386_link_hash_table *htab; 93333965Sjdp Elf_Internal_Shdr *symtab_hdr; 93433965Sjdp struct elf_link_hash_entry **sym_hashes; 93533965Sjdp const Elf_Internal_Rela *rel; 93633965Sjdp const Elf_Internal_Rela *rel_end; 93733965Sjdp asection *sreloc; 93833965Sjdp 939130570Sobrien if (info->relocatable) 940130570Sobrien return TRUE; 94133965Sjdp 94289861Sobrien htab = elf_i386_hash_table (info); 94333965Sjdp symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 94433965Sjdp sym_hashes = elf_sym_hashes (abfd); 94533965Sjdp 94633965Sjdp sreloc = NULL; 94733965Sjdp 94833965Sjdp rel_end = relocs + sec->reloc_count; 94933965Sjdp for (rel = relocs; rel < rel_end; rel++) 95033965Sjdp { 951104840Sobrien unsigned int r_type; 95233965Sjdp unsigned long r_symndx; 95333965Sjdp struct elf_link_hash_entry *h; 95433965Sjdp 95533965Sjdp r_symndx = ELF32_R_SYM (rel->r_info); 956104840Sobrien r_type = ELF32_R_TYPE (rel->r_info); 95733965Sjdp 95878832Sobrien if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) 95978832Sobrien { 960218822Sdim (*_bfd_error_handler) (_("%B: bad symbol index: %d"), 961218822Sdim abfd, 96289861Sobrien r_symndx); 963130570Sobrien return FALSE; 96478832Sobrien } 96578832Sobrien 96633965Sjdp if (r_symndx < symtab_hdr->sh_info) 96733965Sjdp h = NULL; 96833965Sjdp else 969218822Sdim { 970218822Sdim h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 971218822Sdim while (h->root.type == bfd_link_hash_indirect 972218822Sdim || h->root.type == bfd_link_hash_warning) 973218822Sdim h = (struct elf_link_hash_entry *) h->root.u.i.link; 974218822Sdim } 97533965Sjdp 976104840Sobrien r_type = elf_i386_tls_transition (info, r_type, h == NULL); 977104840Sobrien 978104840Sobrien switch (r_type) 97933965Sjdp { 980104840Sobrien case R_386_TLS_LDM: 981104840Sobrien htab->tls_ldm_got.refcount += 1; 982104840Sobrien goto create_got; 983104840Sobrien 984104840Sobrien case R_386_PLT32: 985104840Sobrien /* This symbol requires a procedure linkage table entry. We 986104840Sobrien actually build the entry in adjust_dynamic_symbol, 987104840Sobrien because this might be a case of linking PIC code which is 988104840Sobrien never referenced by a dynamic object, in which case we 989104840Sobrien don't need to generate a procedure linkage table entry 990104840Sobrien after all. */ 991104840Sobrien 992104840Sobrien /* If this is a local symbol, we resolve it directly without 993104840Sobrien creating a procedure linkage table entry. */ 994104840Sobrien if (h == NULL) 995104840Sobrien continue; 996104840Sobrien 997218822Sdim h->needs_plt = 1; 998104840Sobrien h->plt.refcount += 1; 999104840Sobrien break; 1000104840Sobrien 1001104840Sobrien case R_386_TLS_IE_32: 1002104840Sobrien case R_386_TLS_IE: 1003104840Sobrien case R_386_TLS_GOTIE: 1004104840Sobrien if (info->shared) 1005104840Sobrien info->flags |= DF_STATIC_TLS; 1006104840Sobrien /* Fall through */ 1007104840Sobrien 100833965Sjdp case R_386_GOT32: 1009104840Sobrien case R_386_TLS_GD: 1010218822Sdim case R_386_TLS_GOTDESC: 1011218822Sdim case R_386_TLS_DESC_CALL: 101233965Sjdp /* This symbol requires a global offset table entry. */ 1013104840Sobrien { 1014104840Sobrien int tls_type, old_tls_type; 101589861Sobrien 1016104840Sobrien switch (r_type) 1017104840Sobrien { 1018104840Sobrien default: 1019104840Sobrien case R_386_GOT32: tls_type = GOT_NORMAL; break; 1020104840Sobrien case R_386_TLS_GD: tls_type = GOT_TLS_GD; break; 1021218822Sdim case R_386_TLS_GOTDESC: 1022218822Sdim case R_386_TLS_DESC_CALL: 1023218822Sdim tls_type = GOT_TLS_GDESC; break; 1024104840Sobrien case R_386_TLS_IE_32: 1025104840Sobrien if (ELF32_R_TYPE (rel->r_info) == r_type) 1026104840Sobrien tls_type = GOT_TLS_IE_NEG; 1027104840Sobrien else 1028104840Sobrien /* If this is a GD->IE transition, we may use either of 1029104840Sobrien R_386_TLS_TPOFF and R_386_TLS_TPOFF32. */ 1030104840Sobrien tls_type = GOT_TLS_IE; 1031104840Sobrien break; 1032104840Sobrien case R_386_TLS_IE: 1033104840Sobrien case R_386_TLS_GOTIE: 1034104840Sobrien tls_type = GOT_TLS_IE_POS; break; 1035104840Sobrien } 103633965Sjdp 1037104840Sobrien if (h != NULL) 1038104840Sobrien { 1039104840Sobrien h->got.refcount += 1; 1040104840Sobrien old_tls_type = elf_i386_hash_entry(h)->tls_type; 1041104840Sobrien } 1042104840Sobrien else 1043104840Sobrien { 1044104840Sobrien bfd_signed_vma *local_got_refcounts; 1045104840Sobrien 1046104840Sobrien /* This is a global offset table entry for a local symbol. */ 1047104840Sobrien local_got_refcounts = elf_local_got_refcounts (abfd); 1048104840Sobrien if (local_got_refcounts == NULL) 1049104840Sobrien { 1050104840Sobrien bfd_size_type size; 1051104840Sobrien 1052104840Sobrien size = symtab_hdr->sh_info; 1053218822Sdim size *= (sizeof (bfd_signed_vma) 1054218822Sdim + sizeof (bfd_vma) + sizeof(char)); 1055130570Sobrien local_got_refcounts = bfd_zalloc (abfd, size); 1056104840Sobrien if (local_got_refcounts == NULL) 1057130570Sobrien return FALSE; 1058104840Sobrien elf_local_got_refcounts (abfd) = local_got_refcounts; 1059218822Sdim elf_i386_local_tlsdesc_gotent (abfd) 1060218822Sdim = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info); 1061104840Sobrien elf_i386_local_got_tls_type (abfd) 1062218822Sdim = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info); 1063104840Sobrien } 1064104840Sobrien local_got_refcounts[r_symndx] += 1; 1065104840Sobrien old_tls_type = elf_i386_local_got_tls_type (abfd) [r_symndx]; 1066104840Sobrien } 1067104840Sobrien 1068104840Sobrien if ((old_tls_type & GOT_TLS_IE) && (tls_type & GOT_TLS_IE)) 1069104840Sobrien tls_type |= old_tls_type; 1070104840Sobrien /* If a TLS symbol is accessed using IE at least once, 1071104840Sobrien there is no point to use dynamic model for it. */ 1072104840Sobrien else if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN 1073218822Sdim && (! GOT_TLS_GD_ANY_P (old_tls_type) 1074104840Sobrien || (tls_type & GOT_TLS_IE) == 0)) 1075104840Sobrien { 1076218822Sdim if ((old_tls_type & GOT_TLS_IE) && GOT_TLS_GD_ANY_P (tls_type)) 1077104840Sobrien tls_type = old_tls_type; 1078218822Sdim else if (GOT_TLS_GD_ANY_P (old_tls_type) 1079218822Sdim && GOT_TLS_GD_ANY_P (tls_type)) 1080218822Sdim tls_type |= old_tls_type; 1081104840Sobrien else 1082104840Sobrien { 1083104840Sobrien (*_bfd_error_handler) 1084218822Sdim (_("%B: `%s' accessed both as normal and " 1085130570Sobrien "thread local symbol"), 1086218822Sdim abfd, 1087104840Sobrien h ? h->root.root.string : "<local>"); 1088130570Sobrien return FALSE; 1089104840Sobrien } 1090104840Sobrien } 1091104840Sobrien 1092104840Sobrien if (old_tls_type != tls_type) 1093104840Sobrien { 1094104840Sobrien if (h != NULL) 1095104840Sobrien elf_i386_hash_entry (h)->tls_type = tls_type; 1096104840Sobrien else 1097104840Sobrien elf_i386_local_got_tls_type (abfd) [r_symndx] = tls_type; 1098104840Sobrien } 1099104840Sobrien } 110089861Sobrien /* Fall through */ 110133965Sjdp 110289861Sobrien case R_386_GOTOFF: 110389861Sobrien case R_386_GOTPC: 1104104840Sobrien create_got: 110589861Sobrien if (htab->sgot == NULL) 110689861Sobrien { 110789861Sobrien if (htab->elf.dynobj == NULL) 110889861Sobrien htab->elf.dynobj = abfd; 110989861Sobrien if (!create_got_section (htab->elf.dynobj, info)) 1110130570Sobrien return FALSE; 111133965Sjdp } 1112104840Sobrien if (r_type != R_386_TLS_IE) 1113104840Sobrien break; 1114104840Sobrien /* Fall through */ 111533965Sjdp 1116104840Sobrien case R_386_TLS_LE_32: 1117104840Sobrien case R_386_TLS_LE: 1118104840Sobrien if (!info->shared) 1119104840Sobrien break; 1120130570Sobrien info->flags |= DF_STATIC_TLS; 1121130570Sobrien /* Fall through */ 112233965Sjdp 112333965Sjdp case R_386_32: 112433965Sjdp case R_386_PC32: 112589861Sobrien if (h != NULL && !info->shared) 112689861Sobrien { 112789861Sobrien /* If this reloc is in a read-only section, we might 112889861Sobrien need a copy reloc. We can't check reliably at this 112989861Sobrien stage whether the section is read-only, as input 113089861Sobrien sections have not yet been mapped to output sections. 113189861Sobrien Tentatively set the flag for now, and correct in 113289861Sobrien adjust_dynamic_symbol. */ 1133218822Sdim h->non_got_ref = 1; 113460509Sobrien 113589861Sobrien /* We may need a .plt entry if the function this reloc 113689861Sobrien refers to is in a shared lib. */ 113789861Sobrien h->plt.refcount += 1; 1138130570Sobrien if (r_type != R_386_PC32) 1139218822Sdim h->pointer_equality_needed = 1; 114089861Sobrien } 114189861Sobrien 114233965Sjdp /* If we are creating a shared library, and this is a reloc 114377302Sobrien against a global symbol, or a non PC relative reloc 114477302Sobrien against a local symbol, then we need to copy the reloc 114577302Sobrien into the shared library. However, if we are linking with 114677302Sobrien -Bsymbolic, we do not need to copy a reloc against a 114777302Sobrien global symbol which is defined in an object we are 114877302Sobrien including in the link (i.e., DEF_REGULAR is set). At 114977302Sobrien this point we have not seen all the input files, so it is 115077302Sobrien possible that DEF_REGULAR is not set now but will be set 115177302Sobrien later (it is never cleared). In case of a weak definition, 115277302Sobrien DEF_REGULAR may be cleared later by a strong definition in 115389861Sobrien a shared library. We account for that possibility below by 115477302Sobrien storing information in the relocs_copied field of the hash 115577302Sobrien table entry. A similar situation occurs when creating 115677302Sobrien shared libraries and symbol visibility changes render the 115789861Sobrien symbol local. 115889861Sobrien 115989861Sobrien If on the other hand, we are creating an executable, we 116089861Sobrien may need to keep relocations for symbols satisfied by a 116189861Sobrien dynamic library if we manage to avoid copy relocs for the 116289861Sobrien symbol. */ 116389861Sobrien if ((info->shared 116489861Sobrien && (sec->flags & SEC_ALLOC) != 0 1165104840Sobrien && (r_type != R_386_PC32 116689861Sobrien || (h != NULL 1167218822Sdim && (! SYMBOLIC_BIND (info, h) 116889861Sobrien || h->root.type == bfd_link_hash_defweak 1169218822Sdim || !h->def_regular)))) 1170130570Sobrien || (ELIMINATE_COPY_RELOCS 1171130570Sobrien && !info->shared 117289861Sobrien && (sec->flags & SEC_ALLOC) != 0 117389861Sobrien && h != NULL 117489861Sobrien && (h->root.type == bfd_link_hash_defweak 1175218822Sdim || !h->def_regular))) 117633965Sjdp { 117789861Sobrien struct elf_i386_dyn_relocs *p; 117889861Sobrien struct elf_i386_dyn_relocs **head; 117989861Sobrien 118089861Sobrien /* We must copy these reloc types into the output file. 118189861Sobrien Create a reloc section in dynobj and make room for 118289861Sobrien this reloc. */ 118333965Sjdp if (sreloc == NULL) 118433965Sjdp { 118533965Sjdp const char *name; 118689861Sobrien bfd *dynobj; 118794543Sobrien unsigned int strndx = elf_elfheader (abfd)->e_shstrndx; 118894543Sobrien unsigned int shnam = elf_section_data (sec)->rel_hdr.sh_name; 118933965Sjdp 119094543Sobrien name = bfd_elf_string_from_elf_section (abfd, strndx, shnam); 119133965Sjdp if (name == NULL) 1192130570Sobrien return FALSE; 119333965Sjdp 1194218822Sdim if (! CONST_STRNEQ (name, ".rel") 119577302Sobrien || strcmp (bfd_get_section_name (abfd, sec), 119677302Sobrien name + 4) != 0) 119777302Sobrien { 119889861Sobrien (*_bfd_error_handler) 1199218822Sdim (_("%B: bad relocation section name `%s\'"), 1200218822Sdim abfd, name); 120178832Sobrien } 120233965Sjdp 120389861Sobrien if (htab->elf.dynobj == NULL) 120489861Sobrien htab->elf.dynobj = abfd; 120589861Sobrien 120689861Sobrien dynobj = htab->elf.dynobj; 120733965Sjdp sreloc = bfd_get_section_by_name (dynobj, name); 120833965Sjdp if (sreloc == NULL) 120933965Sjdp { 121033965Sjdp flagword flags; 121133965Sjdp 121233965Sjdp flags = (SEC_HAS_CONTENTS | SEC_READONLY 121333965Sjdp | SEC_IN_MEMORY | SEC_LINKER_CREATED); 121433965Sjdp if ((sec->flags & SEC_ALLOC) != 0) 121533965Sjdp flags |= SEC_ALLOC | SEC_LOAD; 1216218822Sdim sreloc = bfd_make_section_with_flags (dynobj, 1217218822Sdim name, 1218218822Sdim flags); 121933965Sjdp if (sreloc == NULL 122033965Sjdp || ! bfd_set_section_alignment (dynobj, sreloc, 2)) 1221130570Sobrien return FALSE; 122233965Sjdp } 122389861Sobrien elf_section_data (sec)->sreloc = sreloc; 122433965Sjdp } 122533965Sjdp 122689861Sobrien /* If this is a global symbol, we count the number of 122789861Sobrien relocations we need for this symbol. */ 122889861Sobrien if (h != NULL) 122933965Sjdp { 123089861Sobrien head = &((struct elf_i386_link_hash_entry *) h)->dyn_relocs; 123189861Sobrien } 123289861Sobrien else 123389861Sobrien { 1234218822Sdim void **vpp; 123589861Sobrien /* Track dynamic relocs needed for local syms too. 123689861Sobrien We really need local syms available to do this 123789861Sobrien easily. Oh well. */ 123833965Sjdp 123989861Sobrien asection *s; 124089861Sobrien s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, 124189861Sobrien sec, r_symndx); 124289861Sobrien if (s == NULL) 1243130570Sobrien return FALSE; 124433965Sjdp 1245218822Sdim vpp = &elf_section_data (s)->local_dynrel; 1246218822Sdim head = (struct elf_i386_dyn_relocs **)vpp; 124789861Sobrien } 124833965Sjdp 124989861Sobrien p = *head; 125089861Sobrien if (p == NULL || p->sec != sec) 125189861Sobrien { 125289861Sobrien bfd_size_type amt = sizeof *p; 1253130570Sobrien p = bfd_alloc (htab->elf.dynobj, amt); 125433965Sjdp if (p == NULL) 1255130570Sobrien return FALSE; 125689861Sobrien p->next = *head; 125789861Sobrien *head = p; 125889861Sobrien p->sec = sec; 125989861Sobrien p->count = 0; 126089861Sobrien p->pc_count = 0; 126189861Sobrien } 126233965Sjdp 126389861Sobrien p->count += 1; 1264104840Sobrien if (r_type == R_386_PC32) 126589861Sobrien p->pc_count += 1; 126633965Sjdp } 126733965Sjdp break; 126833965Sjdp 126960509Sobrien /* This relocation describes the C++ object vtable hierarchy. 127060509Sobrien Reconstruct it for later use during GC. */ 127160509Sobrien case R_386_GNU_VTINHERIT: 1272130570Sobrien if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 1273130570Sobrien return FALSE; 127460509Sobrien break; 127560509Sobrien 127660509Sobrien /* This relocation describes which C++ vtable entries are actually 127760509Sobrien used. Record for later use during GC. */ 127860509Sobrien case R_386_GNU_VTENTRY: 1279130570Sobrien if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) 1280130570Sobrien return FALSE; 128160509Sobrien break; 128260509Sobrien 128333965Sjdp default: 128433965Sjdp break; 128533965Sjdp } 128633965Sjdp } 128733965Sjdp 1288130570Sobrien return TRUE; 128933965Sjdp} 129033965Sjdp 129160509Sobrien/* Return the section that should be marked against GC for a given 129260509Sobrien relocation. */ 129360509Sobrien 129460509Sobrienstatic asection * 1295130570Sobrienelf_i386_gc_mark_hook (asection *sec, 1296218822Sdim struct bfd_link_info *info, 1297130570Sobrien Elf_Internal_Rela *rel, 1298130570Sobrien struct elf_link_hash_entry *h, 1299130570Sobrien Elf_Internal_Sym *sym) 130060509Sobrien{ 130160509Sobrien if (h != NULL) 1302218822Sdim switch (ELF32_R_TYPE (rel->r_info)) 1303218822Sdim { 1304218822Sdim case R_386_GNU_VTINHERIT: 1305218822Sdim case R_386_GNU_VTENTRY: 1306218822Sdim return NULL; 1307218822Sdim } 130860509Sobrien 1309218822Sdim return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); 131060509Sobrien} 131160509Sobrien 131260509Sobrien/* Update the got entry reference counts for the section being removed. */ 131360509Sobrien 1314130570Sobrienstatic bfd_boolean 1315130570Sobrienelf_i386_gc_sweep_hook (bfd *abfd, 1316130570Sobrien struct bfd_link_info *info, 1317130570Sobrien asection *sec, 1318130570Sobrien const Elf_Internal_Rela *relocs) 131960509Sobrien{ 132077302Sobrien Elf_Internal_Shdr *symtab_hdr; 132177302Sobrien struct elf_link_hash_entry **sym_hashes; 132277302Sobrien bfd_signed_vma *local_got_refcounts; 132377302Sobrien const Elf_Internal_Rela *rel, *relend; 132460509Sobrien 132589861Sobrien elf_section_data (sec)->local_dynrel = NULL; 132689861Sobrien 132777302Sobrien symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 132877302Sobrien sym_hashes = elf_sym_hashes (abfd); 132977302Sobrien local_got_refcounts = elf_local_got_refcounts (abfd); 133077302Sobrien 133177302Sobrien relend = relocs + sec->reloc_count; 133277302Sobrien for (rel = relocs; rel < relend; rel++) 1333130570Sobrien { 1334130570Sobrien unsigned long r_symndx; 1335130570Sobrien unsigned int r_type; 1336130570Sobrien struct elf_link_hash_entry *h = NULL; 1337104840Sobrien 1338130570Sobrien r_symndx = ELF32_R_SYM (rel->r_info); 1339130570Sobrien if (r_symndx >= symtab_hdr->sh_info) 1340130570Sobrien { 1341130570Sobrien struct elf_i386_link_hash_entry *eh; 1342130570Sobrien struct elf_i386_dyn_relocs **pp; 1343130570Sobrien struct elf_i386_dyn_relocs *p; 134477302Sobrien 1345130570Sobrien h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 1346218822Sdim while (h->root.type == bfd_link_hash_indirect 1347218822Sdim || h->root.type == bfd_link_hash_warning) 1348218822Sdim h = (struct elf_link_hash_entry *) h->root.u.i.link; 1349130570Sobrien eh = (struct elf_i386_link_hash_entry *) h; 1350104840Sobrien 1351130570Sobrien for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) 1352130570Sobrien if (p->sec == sec) 1353130570Sobrien { 1354130570Sobrien /* Everything must go for SEC. */ 1355130570Sobrien *pp = p->next; 1356130570Sobrien break; 1357130570Sobrien } 1358130570Sobrien } 135989861Sobrien 1360130570Sobrien r_type = ELF32_R_TYPE (rel->r_info); 1361130570Sobrien r_type = elf_i386_tls_transition (info, r_type, h != NULL); 1362130570Sobrien switch (r_type) 1363130570Sobrien { 1364130570Sobrien case R_386_TLS_LDM: 1365130570Sobrien if (elf_i386_hash_table (info)->tls_ldm_got.refcount > 0) 1366130570Sobrien elf_i386_hash_table (info)->tls_ldm_got.refcount -= 1; 1367130570Sobrien break; 136889861Sobrien 1369130570Sobrien case R_386_TLS_GD: 1370218822Sdim case R_386_TLS_GOTDESC: 1371218822Sdim case R_386_TLS_DESC_CALL: 1372130570Sobrien case R_386_TLS_IE_32: 1373130570Sobrien case R_386_TLS_IE: 1374130570Sobrien case R_386_TLS_GOTIE: 1375130570Sobrien case R_386_GOT32: 1376130570Sobrien if (h != NULL) 1377130570Sobrien { 1378130570Sobrien if (h->got.refcount > 0) 1379130570Sobrien h->got.refcount -= 1; 1380130570Sobrien } 1381130570Sobrien else if (local_got_refcounts != NULL) 1382130570Sobrien { 1383130570Sobrien if (local_got_refcounts[r_symndx] > 0) 1384130570Sobrien local_got_refcounts[r_symndx] -= 1; 1385130570Sobrien } 1386130570Sobrien break; 138789861Sobrien 1388130570Sobrien case R_386_32: 1389130570Sobrien case R_386_PC32: 1390130570Sobrien if (info->shared) 1391130570Sobrien break; 1392130570Sobrien /* Fall through */ 139389861Sobrien 1394130570Sobrien case R_386_PLT32: 1395130570Sobrien if (h != NULL) 1396130570Sobrien { 1397130570Sobrien if (h->plt.refcount > 0) 1398130570Sobrien h->plt.refcount -= 1; 1399130570Sobrien } 1400130570Sobrien break; 140189861Sobrien 1402130570Sobrien default: 1403130570Sobrien break; 1404130570Sobrien } 1405130570Sobrien } 140677302Sobrien 1407130570Sobrien return TRUE; 140860509Sobrien} 140960509Sobrien 141033965Sjdp/* Adjust a symbol defined by a dynamic object and referenced by a 141133965Sjdp regular object. The current definition is in some section of the 141233965Sjdp dynamic object, but we're not including those sections. We have to 141333965Sjdp change the definition to something the rest of the link can 141433965Sjdp understand. */ 141533965Sjdp 1416130570Sobrienstatic bfd_boolean 1417130570Sobrienelf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, 1418130570Sobrien struct elf_link_hash_entry *h) 141933965Sjdp{ 142089861Sobrien struct elf_i386_link_hash_table *htab; 142133965Sjdp asection *s; 142233965Sjdp 142333965Sjdp /* If this is a function, put it in the procedure linkage table. We 142433965Sjdp will fill in the contents of the procedure linkage table later, 142533965Sjdp when we know the address of the .got section. */ 142633965Sjdp if (h->type == STT_FUNC 1427218822Sdim || h->needs_plt) 142833965Sjdp { 142989861Sobrien if (h->plt.refcount <= 0 1430130570Sobrien || SYMBOL_CALLS_LOCAL (info, h) 1431130570Sobrien || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT 1432130570Sobrien && h->root.type == bfd_link_hash_undefweak)) 143333965Sjdp { 143433965Sjdp /* This case can occur if we saw a PLT32 reloc in an input 143577302Sobrien file, but the symbol was never referred to by a dynamic 143677302Sobrien object, or if all references were garbage collected. In 143777302Sobrien such a case, we don't actually need to build a procedure 143877302Sobrien linkage table, and we can just do a PC32 reloc instead. */ 143977302Sobrien h->plt.offset = (bfd_vma) -1; 1440218822Sdim h->needs_plt = 0; 144133965Sjdp } 144233965Sjdp 1443130570Sobrien return TRUE; 144433965Sjdp } 144589861Sobrien else 144689861Sobrien /* It's possible that we incorrectly decided a .plt reloc was 144789861Sobrien needed for an R_386_PC32 reloc to a non-function sym in 144889861Sobrien check_relocs. We can't decide accurately between function and 144989861Sobrien non-function syms in check-relocs; Objects loaded later in 145089861Sobrien the link may change h->type. So fix it now. */ 145189861Sobrien h->plt.offset = (bfd_vma) -1; 145233965Sjdp 145333965Sjdp /* If this is a weak symbol, and there is a real definition, the 145433965Sjdp processor independent code will have arranged for us to see the 145533965Sjdp real definition first, and we can just use the same value. */ 1456218822Sdim if (h->u.weakdef != NULL) 145733965Sjdp { 1458218822Sdim BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined 1459218822Sdim || h->u.weakdef->root.type == bfd_link_hash_defweak); 1460218822Sdim h->root.u.def.section = h->u.weakdef->root.u.def.section; 1461218822Sdim h->root.u.def.value = h->u.weakdef->root.u.def.value; 1462130570Sobrien if (ELIMINATE_COPY_RELOCS || info->nocopyreloc) 1463218822Sdim h->non_got_ref = h->u.weakdef->non_got_ref; 1464130570Sobrien return TRUE; 146533965Sjdp } 146633965Sjdp 146733965Sjdp /* This is a reference to a symbol defined by a dynamic object which 146833965Sjdp is not a function. */ 146933965Sjdp 147033965Sjdp /* If we are creating a shared library, we must presume that the 147133965Sjdp only references to the symbol are via the global offset table. 147233965Sjdp For such cases we need not do anything here; the relocations will 147333965Sjdp be handled correctly by relocate_section. */ 147433965Sjdp if (info->shared) 1475130570Sobrien return TRUE; 147633965Sjdp 147760509Sobrien /* If there are no references to this symbol that do not use the 147860509Sobrien GOT, we don't need to generate a copy reloc. */ 1479218822Sdim if (!h->non_got_ref) 1480130570Sobrien return TRUE; 148160509Sobrien 148289861Sobrien /* If -z nocopyreloc was given, we won't generate them either. */ 148389861Sobrien if (info->nocopyreloc) 148489861Sobrien { 1485218822Sdim h->non_got_ref = 0; 1486130570Sobrien return TRUE; 148789861Sobrien } 148889861Sobrien 1489218822Sdim htab = elf_i386_hash_table (info); 1490218822Sdim 1491218822Sdim /* If there aren't any dynamic relocs in read-only sections, then 1492218822Sdim we can keep the dynamic relocs and avoid the copy reloc. This 1493218822Sdim doesn't work on VxWorks, where we can not have dynamic relocations 1494218822Sdim (other than copy and jump slot relocations) in an executable. */ 1495218822Sdim if (ELIMINATE_COPY_RELOCS && !htab->is_vxworks) 149689861Sobrien { 1497130570Sobrien struct elf_i386_link_hash_entry * eh; 1498130570Sobrien struct elf_i386_dyn_relocs *p; 149989861Sobrien 1500130570Sobrien eh = (struct elf_i386_link_hash_entry *) h; 1501130570Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 1502130570Sobrien { 1503130570Sobrien s = p->sec->output_section; 1504130570Sobrien if (s != NULL && (s->flags & SEC_READONLY) != 0) 1505130570Sobrien break; 1506130570Sobrien } 1507130570Sobrien 1508130570Sobrien if (p == NULL) 1509130570Sobrien { 1510218822Sdim h->non_got_ref = 0; 1511130570Sobrien return TRUE; 1512130570Sobrien } 151389861Sobrien } 151489861Sobrien 1515218822Sdim if (h->size == 0) 1516218822Sdim { 1517218822Sdim (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"), 1518218822Sdim h->root.root.string); 1519218822Sdim return TRUE; 1520218822Sdim } 1521218822Sdim 152233965Sjdp /* We must allocate the symbol in our .dynbss section, which will 152333965Sjdp become part of the .bss section of the executable. There will be 152433965Sjdp an entry for this symbol in the .dynsym section. The dynamic 152533965Sjdp object will contain position independent code, so all references 152633965Sjdp from the dynamic object to this symbol will go through the global 152733965Sjdp offset table. The dynamic linker will use the .dynsym entry to 152833965Sjdp determine the address it must put in the global offset table, so 152933965Sjdp both the dynamic object and the regular object will refer to the 153033965Sjdp same memory location for the variable. */ 153133965Sjdp 153233965Sjdp /* We must generate a R_386_COPY reloc to tell the dynamic linker to 153333965Sjdp copy the initial value out of the dynamic object and into the 153489861Sobrien runtime process image. */ 153533965Sjdp if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) 153633965Sjdp { 1537218822Sdim htab->srelbss->size += sizeof (Elf32_External_Rel); 1538218822Sdim h->needs_copy = 1; 153933965Sjdp } 154033965Sjdp 154189861Sobrien s = htab->sdynbss; 154233965Sjdp 1543218822Sdim return _bfd_elf_adjust_dynamic_copy (h, s); 154433965Sjdp} 154533965Sjdp 154689861Sobrien/* Allocate space in .plt, .got and associated reloc sections for 154789861Sobrien dynamic relocs. */ 154889861Sobrien 1549130570Sobrienstatic bfd_boolean 1550130570Sobrienallocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) 155189861Sobrien{ 155289861Sobrien struct bfd_link_info *info; 155389861Sobrien struct elf_i386_link_hash_table *htab; 155489861Sobrien struct elf_i386_link_hash_entry *eh; 155589861Sobrien struct elf_i386_dyn_relocs *p; 155689861Sobrien 155794543Sobrien if (h->root.type == bfd_link_hash_indirect) 1558130570Sobrien return TRUE; 155989861Sobrien 156094543Sobrien if (h->root.type == bfd_link_hash_warning) 156194543Sobrien /* When warning symbols are created, they **replace** the "real" 156294543Sobrien entry in the hash table, thus we never get to see the real 156394543Sobrien symbol in a hash traversal. So look at it now. */ 156494543Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 156594543Sobrien 156689861Sobrien info = (struct bfd_link_info *) inf; 156789861Sobrien htab = elf_i386_hash_table (info); 156889861Sobrien 156989861Sobrien if (htab->elf.dynamic_sections_created 157089861Sobrien && h->plt.refcount > 0) 157189861Sobrien { 157289861Sobrien /* Make sure this symbol is output as a dynamic symbol. 157389861Sobrien Undefined weak syms won't yet be marked as dynamic. */ 157489861Sobrien if (h->dynindx == -1 1575218822Sdim && !h->forced_local) 157689861Sobrien { 1577130570Sobrien if (! bfd_elf_link_record_dynamic_symbol (info, h)) 1578130570Sobrien return FALSE; 157989861Sobrien } 158089861Sobrien 1581130570Sobrien if (info->shared 1582130570Sobrien || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) 158389861Sobrien { 158489861Sobrien asection *s = htab->splt; 158589861Sobrien 158689861Sobrien /* If this is the first .plt entry, make room for the special 158789861Sobrien first entry. */ 1588218822Sdim if (s->size == 0) 1589218822Sdim s->size += PLT_ENTRY_SIZE; 159089861Sobrien 1591218822Sdim h->plt.offset = s->size; 159289861Sobrien 159389861Sobrien /* If this symbol is not defined in a regular file, and we are 159489861Sobrien not generating a shared library, then set the symbol to this 159589861Sobrien location in the .plt. This is required to make function 159689861Sobrien pointers compare as equal between the normal executable and 159789861Sobrien the shared library. */ 159889861Sobrien if (! info->shared 1599218822Sdim && !h->def_regular) 160089861Sobrien { 160189861Sobrien h->root.u.def.section = s; 160289861Sobrien h->root.u.def.value = h->plt.offset; 160389861Sobrien } 160489861Sobrien 160589861Sobrien /* Make room for this entry. */ 1606218822Sdim s->size += PLT_ENTRY_SIZE; 160789861Sobrien 160889861Sobrien /* We also need to make an entry in the .got.plt section, which 160989861Sobrien will be placed in the .got section by the linker script. */ 1610218822Sdim htab->sgotplt->size += 4; 161189861Sobrien 161289861Sobrien /* We also need to make an entry in the .rel.plt section. */ 1613218822Sdim htab->srelplt->size += sizeof (Elf32_External_Rel); 1614218822Sdim htab->next_tls_desc_index++; 1615218822Sdim 1616218822Sdim if (htab->is_vxworks && !info->shared) 1617218822Sdim { 1618218822Sdim /* VxWorks has a second set of relocations for each PLT entry 1619218822Sdim in executables. They go in a separate relocation section, 1620218822Sdim which is processed by the kernel loader. */ 1621218822Sdim 1622218822Sdim /* There are two relocations for the initial PLT entry: an 1623218822Sdim R_386_32 relocation for _GLOBAL_OFFSET_TABLE_ + 4 and an 1624218822Sdim R_386_32 relocation for _GLOBAL_OFFSET_TABLE_ + 8. */ 1625218822Sdim 1626218822Sdim if (h->plt.offset == PLT_ENTRY_SIZE) 1627218822Sdim htab->srelplt2->size += (sizeof (Elf32_External_Rel) * 2); 1628218822Sdim 1629218822Sdim /* There are two extra relocations for each subsequent PLT entry: 1630218822Sdim an R_386_32 relocation for the GOT entry, and an R_386_32 1631218822Sdim relocation for the PLT entry. */ 1632218822Sdim 1633218822Sdim htab->srelplt2->size += (sizeof (Elf32_External_Rel) * 2); 1634218822Sdim } 163589861Sobrien } 163689861Sobrien else 163789861Sobrien { 163889861Sobrien h->plt.offset = (bfd_vma) -1; 1639218822Sdim h->needs_plt = 0; 164089861Sobrien } 164189861Sobrien } 164289861Sobrien else 164389861Sobrien { 164489861Sobrien h->plt.offset = (bfd_vma) -1; 1645218822Sdim h->needs_plt = 0; 164689861Sobrien } 164789861Sobrien 1648218822Sdim eh = (struct elf_i386_link_hash_entry *) h; 1649218822Sdim eh->tlsdesc_got = (bfd_vma) -1; 1650218822Sdim 1651104840Sobrien /* If R_386_TLS_{IE_32,IE,GOTIE} symbol is now local to the binary, 1652104840Sobrien make it a R_386_TLS_LE_32 requiring no TLS entry. */ 1653104840Sobrien if (h->got.refcount > 0 1654104840Sobrien && !info->shared 1655104840Sobrien && h->dynindx == -1 1656104840Sobrien && (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE)) 1657104840Sobrien h->got.offset = (bfd_vma) -1; 1658104840Sobrien else if (h->got.refcount > 0) 165989861Sobrien { 166089861Sobrien asection *s; 1661130570Sobrien bfd_boolean dyn; 1662104840Sobrien int tls_type = elf_i386_hash_entry(h)->tls_type; 166389861Sobrien 166489861Sobrien /* Make sure this symbol is output as a dynamic symbol. 166589861Sobrien Undefined weak syms won't yet be marked as dynamic. */ 166689861Sobrien if (h->dynindx == -1 1667218822Sdim && !h->forced_local) 166889861Sobrien { 1669130570Sobrien if (! bfd_elf_link_record_dynamic_symbol (info, h)) 1670130570Sobrien return FALSE; 167189861Sobrien } 167289861Sobrien 167389861Sobrien s = htab->sgot; 1674218822Sdim if (GOT_TLS_GDESC_P (tls_type)) 1675218822Sdim { 1676218822Sdim eh->tlsdesc_got = htab->sgotplt->size 1677218822Sdim - elf_i386_compute_jump_table_size (htab); 1678218822Sdim htab->sgotplt->size += 8; 1679218822Sdim h->got.offset = (bfd_vma) -2; 1680218822Sdim } 1681218822Sdim if (! GOT_TLS_GDESC_P (tls_type) 1682218822Sdim || GOT_TLS_GD_P (tls_type)) 1683218822Sdim { 1684218822Sdim h->got.offset = s->size; 1685218822Sdim s->size += 4; 1686218822Sdim /* R_386_TLS_GD needs 2 consecutive GOT slots. */ 1687218822Sdim if (GOT_TLS_GD_P (tls_type) || tls_type == GOT_TLS_IE_BOTH) 1688218822Sdim s->size += 4; 1689218822Sdim } 169089861Sobrien dyn = htab->elf.dynamic_sections_created; 1691104840Sobrien /* R_386_TLS_IE_32 needs one dynamic relocation, 1692104840Sobrien R_386_TLS_IE resp. R_386_TLS_GOTIE needs one dynamic relocation, 1693104840Sobrien (but if both R_386_TLS_IE_32 and R_386_TLS_IE is present, we 1694104840Sobrien need two), R_386_TLS_GD needs one if local symbol and two if 1695104840Sobrien global. */ 1696104840Sobrien if (tls_type == GOT_TLS_IE_BOTH) 1697218822Sdim htab->srelgot->size += 2 * sizeof (Elf32_External_Rel); 1698218822Sdim else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1) 1699104840Sobrien || (tls_type & GOT_TLS_IE)) 1700218822Sdim htab->srelgot->size += sizeof (Elf32_External_Rel); 1701218822Sdim else if (GOT_TLS_GD_P (tls_type)) 1702218822Sdim htab->srelgot->size += 2 * sizeof (Elf32_External_Rel); 1703218822Sdim else if (! GOT_TLS_GDESC_P (tls_type) 1704218822Sdim && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT 1705218822Sdim || h->root.type != bfd_link_hash_undefweak) 1706130570Sobrien && (info->shared 1707130570Sobrien || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) 1708218822Sdim htab->srelgot->size += sizeof (Elf32_External_Rel); 1709218822Sdim if (GOT_TLS_GDESC_P (tls_type)) 1710218822Sdim htab->srelplt->size += sizeof (Elf32_External_Rel); 171189861Sobrien } 171289861Sobrien else 171389861Sobrien h->got.offset = (bfd_vma) -1; 171489861Sobrien 171589861Sobrien if (eh->dyn_relocs == NULL) 1716130570Sobrien return TRUE; 171789861Sobrien 171889861Sobrien /* In the shared -Bsymbolic case, discard space allocated for 171989861Sobrien dynamic pc-relative relocs against symbols which turn out to be 172089861Sobrien defined in regular objects. For the normal shared case, discard 172189861Sobrien space for pc-relative relocs that have become local due to symbol 172289861Sobrien visibility changes. */ 172389861Sobrien 172489861Sobrien if (info->shared) 172589861Sobrien { 1726130570Sobrien /* The only reloc that uses pc_count is R_386_PC32, which will 1727130570Sobrien appear on a call or on something like ".long foo - .". We 1728130570Sobrien want calls to protected symbols to resolve directly to the 1729130570Sobrien function rather than going via the plt. If people want 1730130570Sobrien function pointer comparisons to work as expected then they 1731130570Sobrien should avoid writing assembly like ".long foo - .". */ 1732130570Sobrien if (SYMBOL_CALLS_LOCAL (info, h)) 173389861Sobrien { 173489861Sobrien struct elf_i386_dyn_relocs **pp; 173589861Sobrien 173689861Sobrien for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) 173789861Sobrien { 173889861Sobrien p->count -= p->pc_count; 173989861Sobrien p->pc_count = 0; 174089861Sobrien if (p->count == 0) 174189861Sobrien *pp = p->next; 174289861Sobrien else 174389861Sobrien pp = &p->next; 174489861Sobrien } 174589861Sobrien } 1746130570Sobrien 1747130570Sobrien /* Also discard relocs on undefined weak syms with non-default 1748130570Sobrien visibility. */ 1749218822Sdim if (eh->dyn_relocs != NULL 1750130570Sobrien && h->root.type == bfd_link_hash_undefweak) 1751218822Sdim { 1752218822Sdim if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) 1753218822Sdim eh->dyn_relocs = NULL; 1754218822Sdim 1755218822Sdim /* Make sure undefined weak symbols are output as a dynamic 1756218822Sdim symbol in PIEs. */ 1757218822Sdim else if (h->dynindx == -1 1758218822Sdim && !h->forced_local) 1759218822Sdim { 1760218822Sdim if (! bfd_elf_link_record_dynamic_symbol (info, h)) 1761218822Sdim return FALSE; 1762218822Sdim } 1763218822Sdim } 176489861Sobrien } 1765130570Sobrien else if (ELIMINATE_COPY_RELOCS) 176689861Sobrien { 176789861Sobrien /* For the non-shared case, discard space for relocs against 176889861Sobrien symbols which turn out to need copy relocs or are not 176989861Sobrien dynamic. */ 177089861Sobrien 1771218822Sdim if (!h->non_got_ref 1772218822Sdim && ((h->def_dynamic 1773218822Sdim && !h->def_regular) 177489861Sobrien || (htab->elf.dynamic_sections_created 177589861Sobrien && (h->root.type == bfd_link_hash_undefweak 177689861Sobrien || h->root.type == bfd_link_hash_undefined)))) 177789861Sobrien { 177889861Sobrien /* Make sure this symbol is output as a dynamic symbol. 177989861Sobrien Undefined weak syms won't yet be marked as dynamic. */ 178089861Sobrien if (h->dynindx == -1 1781218822Sdim && !h->forced_local) 178289861Sobrien { 1783130570Sobrien if (! bfd_elf_link_record_dynamic_symbol (info, h)) 1784130570Sobrien return FALSE; 178589861Sobrien } 178689861Sobrien 178789861Sobrien /* If that succeeded, we know we'll be keeping all the 178889861Sobrien relocs. */ 178989861Sobrien if (h->dynindx != -1) 179089861Sobrien goto keep; 179189861Sobrien } 179289861Sobrien 179389861Sobrien eh->dyn_relocs = NULL; 179489861Sobrien 179589861Sobrien keep: ; 179689861Sobrien } 179789861Sobrien 179889861Sobrien /* Finally, allocate space. */ 179989861Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 180089861Sobrien { 180189861Sobrien asection *sreloc = elf_section_data (p->sec)->sreloc; 1802218822Sdim sreloc->size += p->count * sizeof (Elf32_External_Rel); 180389861Sobrien } 180489861Sobrien 1805130570Sobrien return TRUE; 180689861Sobrien} 180789861Sobrien 180889861Sobrien/* Find any dynamic relocs that apply to read-only sections. */ 180989861Sobrien 1810130570Sobrienstatic bfd_boolean 1811130570Sobrienreadonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) 181289861Sobrien{ 181389861Sobrien struct elf_i386_link_hash_entry *eh; 181489861Sobrien struct elf_i386_dyn_relocs *p; 181589861Sobrien 181694543Sobrien if (h->root.type == bfd_link_hash_warning) 181794543Sobrien h = (struct elf_link_hash_entry *) h->root.u.i.link; 181894543Sobrien 181989861Sobrien eh = (struct elf_i386_link_hash_entry *) h; 182089861Sobrien for (p = eh->dyn_relocs; p != NULL; p = p->next) 182189861Sobrien { 182289861Sobrien asection *s = p->sec->output_section; 182389861Sobrien 182489861Sobrien if (s != NULL && (s->flags & SEC_READONLY) != 0) 182589861Sobrien { 182689861Sobrien struct bfd_link_info *info = (struct bfd_link_info *) inf; 182789861Sobrien 182889861Sobrien info->flags |= DF_TEXTREL; 182989861Sobrien 183089861Sobrien /* Not an error, just cut short the traversal. */ 1831130570Sobrien return FALSE; 183289861Sobrien } 183389861Sobrien } 1834130570Sobrien return TRUE; 183589861Sobrien} 183689861Sobrien 183733965Sjdp/* Set the sizes of the dynamic sections. */ 183833965Sjdp 1839130570Sobrienstatic bfd_boolean 1840130570Sobrienelf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, 1841130570Sobrien struct bfd_link_info *info) 184233965Sjdp{ 184389861Sobrien struct elf_i386_link_hash_table *htab; 184433965Sjdp bfd *dynobj; 184533965Sjdp asection *s; 1846130570Sobrien bfd_boolean relocs; 184789861Sobrien bfd *ibfd; 184833965Sjdp 184989861Sobrien htab = elf_i386_hash_table (info); 185089861Sobrien dynobj = htab->elf.dynobj; 185189861Sobrien if (dynobj == NULL) 185289861Sobrien abort (); 185333965Sjdp 185489861Sobrien if (htab->elf.dynamic_sections_created) 185533965Sjdp { 185633965Sjdp /* Set the contents of the .interp section to the interpreter. */ 1857130570Sobrien if (info->executable) 185833965Sjdp { 185933965Sjdp s = bfd_get_section_by_name (dynobj, ".interp"); 186089861Sobrien if (s == NULL) 186189861Sobrien abort (); 1862218822Sdim s->size = sizeof ELF_DYNAMIC_INTERPRETER; 186333965Sjdp s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; 186433965Sjdp } 186533965Sjdp } 186633965Sjdp 186789861Sobrien /* Set up .got offsets for local syms, and space for local dynamic 186889861Sobrien relocs. */ 186989861Sobrien for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) 187033965Sjdp { 187189861Sobrien bfd_signed_vma *local_got; 187289861Sobrien bfd_signed_vma *end_local_got; 1873104840Sobrien char *local_tls_type; 1874218822Sdim bfd_vma *local_tlsdesc_gotent; 187589861Sobrien bfd_size_type locsymcount; 187689861Sobrien Elf_Internal_Shdr *symtab_hdr; 187789861Sobrien asection *srel; 187833965Sjdp 187989861Sobrien if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) 188033965Sjdp continue; 188133965Sjdp 188289861Sobrien for (s = ibfd->sections; s != NULL; s = s->next) 188389861Sobrien { 188489861Sobrien struct elf_i386_dyn_relocs *p; 188533965Sjdp 1886218822Sdim for (p = ((struct elf_i386_dyn_relocs *) 1887218822Sdim elf_section_data (s)->local_dynrel); 188889861Sobrien p != NULL; 188989861Sobrien p = p->next) 189033965Sjdp { 189189861Sobrien if (!bfd_is_abs_section (p->sec) 189289861Sobrien && bfd_is_abs_section (p->sec->output_section)) 189389861Sobrien { 189489861Sobrien /* Input section has been discarded, either because 189589861Sobrien it is a copy of a linkonce section or due to 189689861Sobrien linker script /DISCARD/, so we'll be discarding 189789861Sobrien the relocs too. */ 189889861Sobrien } 189991048Sobrien else if (p->count != 0) 190089861Sobrien { 190189861Sobrien srel = elf_section_data (p->sec)->sreloc; 1902218822Sdim srel->size += p->count * sizeof (Elf32_External_Rel); 190391048Sobrien if ((p->sec->output_section->flags & SEC_READONLY) != 0) 190491048Sobrien info->flags |= DF_TEXTREL; 190589861Sobrien } 190633965Sjdp } 190733965Sjdp } 190889861Sobrien 190989861Sobrien local_got = elf_local_got_refcounts (ibfd); 191089861Sobrien if (!local_got) 191189861Sobrien continue; 191289861Sobrien 191389861Sobrien symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; 191489861Sobrien locsymcount = symtab_hdr->sh_info; 191589861Sobrien end_local_got = local_got + locsymcount; 1916104840Sobrien local_tls_type = elf_i386_local_got_tls_type (ibfd); 1917218822Sdim local_tlsdesc_gotent = elf_i386_local_tlsdesc_gotent (ibfd); 191889861Sobrien s = htab->sgot; 191989861Sobrien srel = htab->srelgot; 1920218822Sdim for (; local_got < end_local_got; 1921218822Sdim ++local_got, ++local_tls_type, ++local_tlsdesc_gotent) 192233965Sjdp { 1923218822Sdim *local_tlsdesc_gotent = (bfd_vma) -1; 192489861Sobrien if (*local_got > 0) 192533965Sjdp { 1926218822Sdim if (GOT_TLS_GDESC_P (*local_tls_type)) 1927218822Sdim { 1928218822Sdim *local_tlsdesc_gotent = htab->sgotplt->size 1929218822Sdim - elf_i386_compute_jump_table_size (htab); 1930218822Sdim htab->sgotplt->size += 8; 1931218822Sdim *local_got = (bfd_vma) -2; 1932218822Sdim } 1933218822Sdim if (! GOT_TLS_GDESC_P (*local_tls_type) 1934218822Sdim || GOT_TLS_GD_P (*local_tls_type)) 1935218822Sdim { 1936218822Sdim *local_got = s->size; 1937218822Sdim s->size += 4; 1938218822Sdim if (GOT_TLS_GD_P (*local_tls_type) 1939218822Sdim || *local_tls_type == GOT_TLS_IE_BOTH) 1940218822Sdim s->size += 4; 1941218822Sdim } 1942104840Sobrien if (info->shared 1943218822Sdim || GOT_TLS_GD_ANY_P (*local_tls_type) 1944104840Sobrien || (*local_tls_type & GOT_TLS_IE)) 1945104840Sobrien { 1946104840Sobrien if (*local_tls_type == GOT_TLS_IE_BOTH) 1947218822Sdim srel->size += 2 * sizeof (Elf32_External_Rel); 1948218822Sdim else if (GOT_TLS_GD_P (*local_tls_type) 1949218822Sdim || ! GOT_TLS_GDESC_P (*local_tls_type)) 1950218822Sdim srel->size += sizeof (Elf32_External_Rel); 1951218822Sdim if (GOT_TLS_GDESC_P (*local_tls_type)) 1952218822Sdim htab->srelplt->size += sizeof (Elf32_External_Rel); 1953104840Sobrien } 195433965Sjdp } 195533965Sjdp else 195689861Sobrien *local_got = (bfd_vma) -1; 195789861Sobrien } 195889861Sobrien } 195933965Sjdp 1960104840Sobrien if (htab->tls_ldm_got.refcount > 0) 1961104840Sobrien { 1962104840Sobrien /* Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM 1963104840Sobrien relocs. */ 1964218822Sdim htab->tls_ldm_got.offset = htab->sgot->size; 1965218822Sdim htab->sgot->size += 8; 1966218822Sdim htab->srelgot->size += sizeof (Elf32_External_Rel); 1967104840Sobrien } 1968104840Sobrien else 1969104840Sobrien htab->tls_ldm_got.offset = -1; 1970104840Sobrien 197189861Sobrien /* Allocate global sym .plt and .got entries, and space for global 197289861Sobrien sym dynamic relocs. */ 197389861Sobrien elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info); 197433965Sjdp 1975218822Sdim /* For every jump slot reserved in the sgotplt, reloc_count is 1976218822Sdim incremented. However, when we reserve space for TLS descriptors, 1977218822Sdim it's not incremented, so in order to compute the space reserved 1978218822Sdim for them, it suffices to multiply the reloc count by the jump 1979218822Sdim slot size. */ 1980218822Sdim if (htab->srelplt) 1981218822Sdim htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4; 1982218822Sdim 198389861Sobrien /* We now have determined the sizes of the various dynamic sections. 198489861Sobrien Allocate memory for them. */ 1985130570Sobrien relocs = FALSE; 198689861Sobrien for (s = dynobj->sections; s != NULL; s = s->next) 198789861Sobrien { 1988218822Sdim bfd_boolean strip_section = TRUE; 1989218822Sdim 199089861Sobrien if ((s->flags & SEC_LINKER_CREATED) == 0) 199189861Sobrien continue; 199233965Sjdp 199389861Sobrien if (s == htab->splt 199489861Sobrien || s == htab->sgot 1995218822Sdim || s == htab->sgotplt 1996218822Sdim || s == htab->sdynbss) 199789861Sobrien { 199889861Sobrien /* Strip this section if we don't need it; see the 199989861Sobrien comment below. */ 2000218822Sdim /* We'd like to strip these sections if they aren't needed, but if 2001218822Sdim we've exported dynamic symbols from them we must leave them. 2002218822Sdim It's too late to tell BFD to get rid of the symbols. */ 2003218822Sdim 2004218822Sdim if (htab->elf.hplt != NULL) 2005218822Sdim strip_section = FALSE; 200689861Sobrien } 2007218822Sdim else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rel")) 200889861Sobrien { 2009218822Sdim if (s->size != 0 && s != htab->srelplt && s != htab->srelplt2) 2010130570Sobrien relocs = TRUE; 201133965Sjdp 201289861Sobrien /* We use the reloc_count field as a counter if we need 201389861Sobrien to copy relocs into the output file. */ 201489861Sobrien s->reloc_count = 0; 201533965Sjdp } 201689861Sobrien else 201733965Sjdp { 201833965Sjdp /* It's not one of our sections, so don't allocate space. */ 201933965Sjdp continue; 202033965Sjdp } 202133965Sjdp 2022218822Sdim if (s->size == 0) 202333965Sjdp { 202489861Sobrien /* If we don't need this section, strip it from the 202589861Sobrien output file. This is mostly to handle .rel.bss and 202689861Sobrien .rel.plt. We must create both sections in 202789861Sobrien create_dynamic_sections, because they must be created 202889861Sobrien before the linker maps input sections to output 202989861Sobrien sections. The linker does that before 203089861Sobrien adjust_dynamic_symbol is called, and it is that 203189861Sobrien function which decides whether anything needs to go 203289861Sobrien into these sections. */ 2033218822Sdim if (strip_section) 2034218822Sdim s->flags |= SEC_EXCLUDE; 203533965Sjdp continue; 203633965Sjdp } 203733965Sjdp 2038218822Sdim if ((s->flags & SEC_HAS_CONTENTS) == 0) 2039218822Sdim continue; 2040218822Sdim 204177302Sobrien /* Allocate memory for the section contents. We use bfd_zalloc 204277302Sobrien here in case unused entries are not reclaimed before the 204377302Sobrien section's contents are written out. This should not happen, 204477302Sobrien but this way if it does, we get a R_386_NONE reloc instead 204577302Sobrien of garbage. */ 2046218822Sdim s->contents = bfd_zalloc (dynobj, s->size); 204789861Sobrien if (s->contents == NULL) 2048130570Sobrien return FALSE; 204933965Sjdp } 205033965Sjdp 205189861Sobrien if (htab->elf.dynamic_sections_created) 205233965Sjdp { 205333965Sjdp /* Add some entries to the .dynamic section. We fill in the 205433965Sjdp values later, in elf_i386_finish_dynamic_sections, but we 205533965Sjdp must add the entries now so that we get the correct size for 205633965Sjdp the .dynamic section. The DT_DEBUG entry is filled in by the 205733965Sjdp dynamic linker and used by the debugger. */ 205889861Sobrien#define add_dynamic_entry(TAG, VAL) \ 2059130570Sobrien _bfd_elf_add_dynamic_entry (info, TAG, VAL) 206089861Sobrien 2061130570Sobrien if (info->executable) 206233965Sjdp { 206389861Sobrien if (!add_dynamic_entry (DT_DEBUG, 0)) 2064130570Sobrien return FALSE; 206533965Sjdp } 206633965Sjdp 2067218822Sdim if (htab->splt->size != 0) 206833965Sjdp { 206989861Sobrien if (!add_dynamic_entry (DT_PLTGOT, 0) 207089861Sobrien || !add_dynamic_entry (DT_PLTRELSZ, 0) 207189861Sobrien || !add_dynamic_entry (DT_PLTREL, DT_REL) 207289861Sobrien || !add_dynamic_entry (DT_JMPREL, 0)) 2073130570Sobrien return FALSE; 207433965Sjdp } 207533965Sjdp 207633965Sjdp if (relocs) 207733965Sjdp { 207889861Sobrien if (!add_dynamic_entry (DT_REL, 0) 207989861Sobrien || !add_dynamic_entry (DT_RELSZ, 0) 208089861Sobrien || !add_dynamic_entry (DT_RELENT, sizeof (Elf32_External_Rel))) 2081130570Sobrien return FALSE; 208233965Sjdp 208389861Sobrien /* If any dynamic relocs apply to a read-only section, 208489861Sobrien then we need a DT_TEXTREL entry. */ 208591048Sobrien if ((info->flags & DF_TEXTREL) == 0) 208691048Sobrien elf_link_hash_traverse (&htab->elf, readonly_dynrelocs, 208791048Sobrien (PTR) info); 208889861Sobrien 208989861Sobrien if ((info->flags & DF_TEXTREL) != 0) 209089861Sobrien { 209189861Sobrien if (!add_dynamic_entry (DT_TEXTREL, 0)) 2092130570Sobrien return FALSE; 209389861Sobrien } 209433965Sjdp } 209533965Sjdp } 209689861Sobrien#undef add_dynamic_entry 209733965Sjdp 2098130570Sobrien return TRUE; 209933965Sjdp} 210033965Sjdp 2101218822Sdimstatic bfd_boolean 2102218822Sdimelf_i386_always_size_sections (bfd *output_bfd, 2103218822Sdim struct bfd_link_info *info) 2104218822Sdim{ 2105218822Sdim asection *tls_sec = elf_hash_table (info)->tls_sec; 2106218822Sdim 2107218822Sdim if (tls_sec) 2108218822Sdim { 2109218822Sdim struct elf_link_hash_entry *tlsbase; 2110218822Sdim 2111218822Sdim tlsbase = elf_link_hash_lookup (elf_hash_table (info), 2112218822Sdim "_TLS_MODULE_BASE_", 2113218822Sdim FALSE, FALSE, FALSE); 2114218822Sdim 2115218822Sdim if (tlsbase && tlsbase->type == STT_TLS) 2116218822Sdim { 2117218822Sdim struct bfd_link_hash_entry *bh = NULL; 2118218822Sdim const struct elf_backend_data *bed 2119218822Sdim = get_elf_backend_data (output_bfd); 2120218822Sdim 2121218822Sdim if (!(_bfd_generic_link_add_one_symbol 2122218822Sdim (info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL, 2123218822Sdim tls_sec, 0, NULL, FALSE, 2124218822Sdim bed->collect, &bh))) 2125218822Sdim return FALSE; 2126218822Sdim tlsbase = (struct elf_link_hash_entry *)bh; 2127218822Sdim tlsbase->def_regular = 1; 2128218822Sdim tlsbase->other = STV_HIDDEN; 2129218822Sdim (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE); 2130218822Sdim } 2131218822Sdim } 2132218822Sdim 2133218822Sdim return TRUE; 2134218822Sdim} 2135218822Sdim 213689861Sobrien/* Set the correct type for an x86 ELF section. We do this by the 213789861Sobrien section name, which is a hack, but ought to work. */ 213833965Sjdp 2139130570Sobrienstatic bfd_boolean 2140130570Sobrienelf_i386_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, 2141130570Sobrien Elf_Internal_Shdr *hdr, 2142130570Sobrien asection *sec) 214333965Sjdp{ 214489861Sobrien register const char *name; 214533965Sjdp 214689861Sobrien name = bfd_get_section_name (abfd, sec); 214733965Sjdp 214889861Sobrien /* This is an ugly, but unfortunately necessary hack that is 214989861Sobrien needed when producing EFI binaries on x86. It tells 215089861Sobrien elf.c:elf_fake_sections() not to consider ".reloc" as a section 215189861Sobrien containing ELF relocation info. We need this hack in order to 215289861Sobrien be able to generate ELF binaries that can be translated into 215389861Sobrien EFI applications (which are essentially COFF objects). Those 215489861Sobrien files contain a COFF ".reloc" section inside an ELFNN object, 215589861Sobrien which would normally cause BFD to segfault because it would 215689861Sobrien attempt to interpret this section as containing relocation 215789861Sobrien entries for section "oc". With this hack enabled, ".reloc" 215889861Sobrien will be treated as a normal data section, which will avoid the 215989861Sobrien segfault. However, you won't be able to create an ELFNN binary 216089861Sobrien with a section named "oc" that needs relocations, but that's 216189861Sobrien the kind of ugly side-effects you get when detecting section 216289861Sobrien types based on their names... In practice, this limitation is 216389861Sobrien unlikely to bite. */ 216489861Sobrien if (strcmp (name, ".reloc") == 0) 216589861Sobrien hdr->sh_type = SHT_PROGBITS; 216689861Sobrien 2167130570Sobrien return TRUE; 216833965Sjdp} 216933965Sjdp 2170104840Sobrien/* Return the base VMA address which should be subtracted from real addresses 2171104840Sobrien when resolving @dtpoff relocation. 2172104840Sobrien This is PT_TLS segment p_vaddr. */ 2173104840Sobrien 2174104840Sobrienstatic bfd_vma 2175130570Sobriendtpoff_base (struct bfd_link_info *info) 2176104840Sobrien{ 2177130570Sobrien /* If tls_sec is NULL, we should have signalled an error already. */ 2178130570Sobrien if (elf_hash_table (info)->tls_sec == NULL) 2179104840Sobrien return 0; 2180130570Sobrien return elf_hash_table (info)->tls_sec->vma; 2181104840Sobrien} 2182104840Sobrien 2183104840Sobrien/* Return the relocation value for @tpoff relocation 2184104840Sobrien if STT_TLS virtual address is ADDRESS. */ 2185104840Sobrien 2186104840Sobrienstatic bfd_vma 2187130570Sobrientpoff (struct bfd_link_info *info, bfd_vma address) 2188104840Sobrien{ 2189130570Sobrien struct elf_link_hash_table *htab = elf_hash_table (info); 2190104840Sobrien 2191130570Sobrien /* If tls_sec is NULL, we should have signalled an error already. */ 2192130570Sobrien if (htab->tls_sec == NULL) 2193104840Sobrien return 0; 2194130570Sobrien return htab->tls_size + htab->tls_sec->vma - address; 2195104840Sobrien} 2196104840Sobrien 219733965Sjdp/* Relocate an i386 ELF section. */ 219833965Sjdp 2199130570Sobrienstatic bfd_boolean 2200130570Sobrienelf_i386_relocate_section (bfd *output_bfd, 2201130570Sobrien struct bfd_link_info *info, 2202130570Sobrien bfd *input_bfd, 2203130570Sobrien asection *input_section, 2204130570Sobrien bfd_byte *contents, 2205130570Sobrien Elf_Internal_Rela *relocs, 2206130570Sobrien Elf_Internal_Sym *local_syms, 2207130570Sobrien asection **local_sections) 220833965Sjdp{ 220989861Sobrien struct elf_i386_link_hash_table *htab; 221033965Sjdp Elf_Internal_Shdr *symtab_hdr; 221133965Sjdp struct elf_link_hash_entry **sym_hashes; 221233965Sjdp bfd_vma *local_got_offsets; 2213218822Sdim bfd_vma *local_tlsdesc_gotents; 221433965Sjdp Elf_Internal_Rela *rel; 221533965Sjdp Elf_Internal_Rela *relend; 221633965Sjdp 221789861Sobrien htab = elf_i386_hash_table (info); 221833965Sjdp symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 221933965Sjdp sym_hashes = elf_sym_hashes (input_bfd); 222033965Sjdp local_got_offsets = elf_local_got_offsets (input_bfd); 2221218822Sdim local_tlsdesc_gotents = elf_i386_local_tlsdesc_gotent (input_bfd); 222233965Sjdp 222333965Sjdp rel = relocs; 222433965Sjdp relend = relocs + input_section->reloc_count; 222533965Sjdp for (; rel < relend; rel++) 222633965Sjdp { 2227104840Sobrien unsigned int r_type; 222833965Sjdp reloc_howto_type *howto; 222933965Sjdp unsigned long r_symndx; 223033965Sjdp struct elf_link_hash_entry *h; 223133965Sjdp Elf_Internal_Sym *sym; 223233965Sjdp asection *sec; 2233218822Sdim bfd_vma off, offplt; 223433965Sjdp bfd_vma relocation; 2235130570Sobrien bfd_boolean unresolved_reloc; 223633965Sjdp bfd_reloc_status_type r; 223777302Sobrien unsigned int indx; 2238104840Sobrien int tls_type; 223933965Sjdp 224033965Sjdp r_type = ELF32_R_TYPE (rel->r_info); 2241130570Sobrien if (r_type == R_386_GNU_VTINHERIT 2242130570Sobrien || r_type == R_386_GNU_VTENTRY) 224360509Sobrien continue; 224477302Sobrien 2245130570Sobrien if ((indx = r_type) >= R_386_standard 2246104840Sobrien && ((indx = r_type - R_386_ext_offset) - R_386_standard 2247104840Sobrien >= R_386_ext - R_386_standard) 2248104840Sobrien && ((indx = r_type - R_386_tls_offset) - R_386_ext 2249104840Sobrien >= R_386_tls - R_386_ext)) 225033965Sjdp { 2251218822Sdim (*_bfd_error_handler) 2252218822Sdim (_("%B: unrecognized relocation (0x%x) in section `%A'"), 2253218822Sdim input_bfd, input_section, r_type); 225433965Sjdp bfd_set_error (bfd_error_bad_value); 2255130570Sobrien return FALSE; 225633965Sjdp } 225777302Sobrien howto = elf_howto_table + indx; 225833965Sjdp 225933965Sjdp r_symndx = ELF32_R_SYM (rel->r_info); 226033965Sjdp h = NULL; 226133965Sjdp sym = NULL; 226233965Sjdp sec = NULL; 2263130570Sobrien unresolved_reloc = FALSE; 226433965Sjdp if (r_symndx < symtab_hdr->sh_info) 226533965Sjdp { 226633965Sjdp sym = local_syms + r_symndx; 226733965Sjdp sec = local_sections[r_symndx]; 226833965Sjdp relocation = (sec->output_section->vma 226933965Sjdp + sec->output_offset 227033965Sjdp + sym->st_value); 2271218822Sdim 2272218822Sdim if (ELF_ST_TYPE (sym->st_info) == STT_SECTION 2273218822Sdim && ((sec->flags & SEC_MERGE) != 0 2274218822Sdim || (info->relocatable 2275218822Sdim && sec->output_offset != 0))) 227689861Sobrien { 227789861Sobrien bfd_vma addend; 2278104840Sobrien bfd_byte *where = contents + rel->r_offset; 227989861Sobrien 2280104840Sobrien switch (howto->size) 228189861Sobrien { 2282104840Sobrien case 0: 2283104840Sobrien addend = bfd_get_8 (input_bfd, where); 2284104840Sobrien if (howto->pc_relative) 2285104840Sobrien { 2286104840Sobrien addend = (addend ^ 0x80) - 0x80; 2287104840Sobrien addend += 1; 2288104840Sobrien } 2289104840Sobrien break; 2290104840Sobrien case 1: 2291104840Sobrien addend = bfd_get_16 (input_bfd, where); 2292104840Sobrien if (howto->pc_relative) 2293104840Sobrien { 2294104840Sobrien addend = (addend ^ 0x8000) - 0x8000; 2295104840Sobrien addend += 2; 2296104840Sobrien } 2297104840Sobrien break; 2298104840Sobrien case 2: 2299104840Sobrien addend = bfd_get_32 (input_bfd, where); 2300104840Sobrien if (howto->pc_relative) 2301104840Sobrien { 2302104840Sobrien addend = (addend ^ 0x80000000) - 0x80000000; 2303104840Sobrien addend += 4; 2304104840Sobrien } 2305104840Sobrien break; 2306104840Sobrien default: 2307104840Sobrien abort (); 230889861Sobrien } 230989861Sobrien 2310218822Sdim if (info->relocatable) 2311218822Sdim addend += sec->output_offset; 2312218822Sdim else 2313218822Sdim { 2314218822Sdim asection *msec = sec; 2315218822Sdim addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, 2316218822Sdim addend); 2317218822Sdim addend -= relocation; 2318218822Sdim addend += msec->output_section->vma + msec->output_offset; 2319218822Sdim } 2320104840Sobrien 2321104840Sobrien switch (howto->size) 2322104840Sobrien { 2323104840Sobrien case 0: 2324104840Sobrien /* FIXME: overflow checks. */ 2325104840Sobrien if (howto->pc_relative) 2326104840Sobrien addend -= 1; 2327104840Sobrien bfd_put_8 (input_bfd, addend, where); 2328104840Sobrien break; 2329104840Sobrien case 1: 2330104840Sobrien if (howto->pc_relative) 2331104840Sobrien addend -= 2; 2332104840Sobrien bfd_put_16 (input_bfd, addend, where); 2333104840Sobrien break; 2334104840Sobrien case 2: 2335104840Sobrien if (howto->pc_relative) 2336104840Sobrien addend -= 4; 2337104840Sobrien bfd_put_32 (input_bfd, addend, where); 2338104840Sobrien break; 2339104840Sobrien } 234089861Sobrien } 234133965Sjdp } 234233965Sjdp else 234333965Sjdp { 2344130570Sobrien bfd_boolean warned; 234589861Sobrien 2346130570Sobrien RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 2347130570Sobrien r_symndx, symtab_hdr, sym_hashes, 2348130570Sobrien h, sec, relocation, 2349130570Sobrien unresolved_reloc, warned); 235033965Sjdp } 235133965Sjdp 2352218822Sdim if (sec != NULL && elf_discarded_section (sec)) 2353218822Sdim { 2354218822Sdim /* For relocs against symbols from removed linkonce sections, 2355218822Sdim or sections discarded by a linker script, we just want the 2356218822Sdim section contents zeroed. Avoid any special processing. */ 2357218822Sdim _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); 2358218822Sdim rel->r_info = 0; 2359218822Sdim rel->r_addend = 0; 2360218822Sdim continue; 2361218822Sdim } 2362218822Sdim 2363218822Sdim if (info->relocatable) 2364218822Sdim continue; 2365218822Sdim 236633965Sjdp switch (r_type) 236733965Sjdp { 236833965Sjdp case R_386_GOT32: 236933965Sjdp /* Relocation is to the entry for this symbol in the global 237033965Sjdp offset table. */ 237189861Sobrien if (htab->sgot == NULL) 237289861Sobrien abort (); 237333965Sjdp 237433965Sjdp if (h != NULL) 237533965Sjdp { 2376130570Sobrien bfd_boolean dyn; 237733965Sjdp 237860509Sobrien off = h->got.offset; 237989861Sobrien dyn = htab->elf.dynamic_sections_created; 2380130570Sobrien if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) 238133965Sjdp || (info->shared 2382130570Sobrien && SYMBOL_REFERENCES_LOCAL (info, h)) 2383130570Sobrien || (ELF_ST_VISIBILITY (h->other) 2384130570Sobrien && h->root.type == bfd_link_hash_undefweak)) 238533965Sjdp { 238633965Sjdp /* This is actually a static link, or it is a 238733965Sjdp -Bsymbolic link and the symbol is defined 238838891Sjdp locally, or the symbol was forced to be local 238938891Sjdp because of a version file. We must initialize 239038891Sjdp this entry in the global offset table. Since the 239138891Sjdp offset must always be a multiple of 4, we use the 239238891Sjdp least significant bit to record whether we have 239333965Sjdp initialized it already. 239433965Sjdp 239533965Sjdp When doing a dynamic link, we create a .rel.got 239633965Sjdp relocation entry to initialize the value. This 239733965Sjdp is done in the finish_dynamic_symbol routine. */ 239833965Sjdp if ((off & 1) != 0) 239933965Sjdp off &= ~1; 240033965Sjdp else 240133965Sjdp { 240233965Sjdp bfd_put_32 (output_bfd, relocation, 240389861Sobrien htab->sgot->contents + off); 240460509Sobrien h->got.offset |= 1; 240533965Sjdp } 240633965Sjdp } 240789861Sobrien else 2408130570Sobrien unresolved_reloc = FALSE; 240933965Sjdp } 241033965Sjdp else 241133965Sjdp { 241289861Sobrien if (local_got_offsets == NULL) 241389861Sobrien abort (); 241433965Sjdp 241533965Sjdp off = local_got_offsets[r_symndx]; 241633965Sjdp 241733965Sjdp /* The offset must always be a multiple of 4. We use 241889861Sobrien the least significant bit to record whether we have 241989861Sobrien already generated the necessary reloc. */ 242033965Sjdp if ((off & 1) != 0) 242133965Sjdp off &= ~1; 242233965Sjdp else 242333965Sjdp { 242489861Sobrien bfd_put_32 (output_bfd, relocation, 242589861Sobrien htab->sgot->contents + off); 242633965Sjdp 242733965Sjdp if (info->shared) 242833965Sjdp { 2429130570Sobrien asection *s; 2430130570Sobrien Elf_Internal_Rela outrel; 2431130570Sobrien bfd_byte *loc; 243233965Sjdp 2433130570Sobrien s = htab->srelgot; 2434130570Sobrien if (s == NULL) 243589861Sobrien abort (); 243633965Sjdp 243789861Sobrien outrel.r_offset = (htab->sgot->output_section->vma 243889861Sobrien + htab->sgot->output_offset 243933965Sjdp + off); 244033965Sjdp outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); 2441130570Sobrien loc = s->contents; 2442130570Sobrien loc += s->reloc_count++ * sizeof (Elf32_External_Rel); 244389861Sobrien bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); 244433965Sjdp } 244533965Sjdp 244633965Sjdp local_got_offsets[r_symndx] |= 1; 244733965Sjdp } 244833965Sjdp } 244933965Sjdp 245089861Sobrien if (off >= (bfd_vma) -2) 245189861Sobrien abort (); 245289861Sobrien 2453218822Sdim relocation = htab->sgot->output_section->vma 2454218822Sdim + htab->sgot->output_offset + off 2455218822Sdim - htab->sgotplt->output_section->vma 2456218822Sdim - htab->sgotplt->output_offset; 245733965Sjdp break; 245833965Sjdp 245933965Sjdp case R_386_GOTOFF: 246033965Sjdp /* Relocation is relative to the start of the global offset 246133965Sjdp table. */ 246233965Sjdp 2463218822Sdim /* Check to make sure it isn't a protected function symbol 2464218822Sdim for shared library since it may not be local when used 2465218822Sdim as function address. */ 2466218822Sdim if (info->shared 2467218822Sdim && !info->executable 2468218822Sdim && h 2469218822Sdim && h->def_regular 2470218822Sdim && h->type == STT_FUNC 2471218822Sdim && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED) 2472218822Sdim { 2473218822Sdim (*_bfd_error_handler) 2474218822Sdim (_("%B: relocation R_386_GOTOFF against protected function `%s' can not be used when making a shared object"), 2475218822Sdim input_bfd, h->root.root.string); 2476218822Sdim bfd_set_error (bfd_error_bad_value); 2477218822Sdim return FALSE; 2478218822Sdim } 2479218822Sdim 2480218822Sdim /* Note that sgot is not involved in this 2481218822Sdim calculation. We always want the start of .got.plt. If we 2482218822Sdim defined _GLOBAL_OFFSET_TABLE_ in a different way, as is 248333965Sjdp permitted by the ABI, we might have to change this 248433965Sjdp calculation. */ 2485218822Sdim relocation -= htab->sgotplt->output_section->vma 2486218822Sdim + htab->sgotplt->output_offset; 248733965Sjdp break; 248833965Sjdp 248933965Sjdp case R_386_GOTPC: 249033965Sjdp /* Use global offset table as symbol value. */ 2491218822Sdim relocation = htab->sgotplt->output_section->vma 2492218822Sdim + htab->sgotplt->output_offset; 2493130570Sobrien unresolved_reloc = FALSE; 249433965Sjdp break; 249533965Sjdp 249633965Sjdp case R_386_PLT32: 249733965Sjdp /* Relocation is to the entry for this symbol in the 249833965Sjdp procedure linkage table. */ 249933965Sjdp 250077302Sobrien /* Resolve a PLT32 reloc against a local symbol directly, 250189861Sobrien without using the procedure linkage table. */ 250233965Sjdp if (h == NULL) 250333965Sjdp break; 250433965Sjdp 250577302Sobrien if (h->plt.offset == (bfd_vma) -1 250689861Sobrien || htab->splt == NULL) 250733965Sjdp { 250833965Sjdp /* We didn't make a PLT entry for this symbol. This 250989861Sobrien happens when statically linking PIC code, or when 251089861Sobrien using -Bsymbolic. */ 251133965Sjdp break; 251233965Sjdp } 251333965Sjdp 251489861Sobrien relocation = (htab->splt->output_section->vma 251589861Sobrien + htab->splt->output_offset 251660509Sobrien + h->plt.offset); 2517130570Sobrien unresolved_reloc = FALSE; 251833965Sjdp break; 251933965Sjdp 252033965Sjdp case R_386_32: 252133965Sjdp case R_386_PC32: 2522218822Sdim if ((input_section->flags & SEC_ALLOC) == 0) 252389861Sobrien break; 252489861Sobrien 252589861Sobrien if ((info->shared 2526130570Sobrien && (h == NULL 2527130570Sobrien || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT 2528130570Sobrien || h->root.type != bfd_link_hash_undefweak) 252989861Sobrien && (r_type != R_386_PC32 2530130570Sobrien || !SYMBOL_CALLS_LOCAL (info, h))) 2531130570Sobrien || (ELIMINATE_COPY_RELOCS 2532130570Sobrien && !info->shared 253389861Sobrien && h != NULL 253489861Sobrien && h->dynindx != -1 2535218822Sdim && !h->non_got_ref 2536218822Sdim && ((h->def_dynamic 2537218822Sdim && !h->def_regular) 253889861Sobrien || h->root.type == bfd_link_hash_undefweak 253989861Sobrien || h->root.type == bfd_link_hash_undefined))) 254033965Sjdp { 2541130570Sobrien Elf_Internal_Rela outrel; 2542130570Sobrien bfd_byte *loc; 2543130570Sobrien bfd_boolean skip, relocate; 254489861Sobrien asection *sreloc; 254533965Sjdp 254633965Sjdp /* When generating a shared object, these relocations 254733965Sjdp are copied into the output file to be resolved at run 254833965Sjdp time. */ 254933965Sjdp 2550130570Sobrien skip = FALSE; 2551130570Sobrien relocate = FALSE; 255233965Sjdp 255389861Sobrien outrel.r_offset = 255489861Sobrien _bfd_elf_section_offset (output_bfd, info, input_section, 255589861Sobrien rel->r_offset); 255689861Sobrien if (outrel.r_offset == (bfd_vma) -1) 2557130570Sobrien skip = TRUE; 255891048Sobrien else if (outrel.r_offset == (bfd_vma) -2) 2559130570Sobrien skip = TRUE, relocate = TRUE; 256033965Sjdp outrel.r_offset += (input_section->output_section->vma 256133965Sjdp + input_section->output_offset); 256233965Sjdp 256333965Sjdp if (skip) 256491048Sobrien memset (&outrel, 0, sizeof outrel); 256589861Sobrien else if (h != NULL 256689861Sobrien && h->dynindx != -1 256789861Sobrien && (r_type == R_386_PC32 256889861Sobrien || !info->shared 2569218822Sdim || !SYMBOLIC_BIND (info, h) 2570218822Sdim || !h->def_regular)) 257191048Sobrien outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); 257233965Sjdp else 257333965Sjdp { 257489861Sobrien /* This symbol is local, or marked to become local. */ 2575130570Sobrien relocate = TRUE; 257689861Sobrien outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); 257733965Sjdp } 257833965Sjdp 257989861Sobrien sreloc = elf_section_data (input_section)->sreloc; 258089861Sobrien if (sreloc == NULL) 258189861Sobrien abort (); 258233965Sjdp 2583130570Sobrien loc = sreloc->contents; 2584130570Sobrien loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel); 258589861Sobrien bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); 258689861Sobrien 258733965Sjdp /* If this reloc is against an external symbol, we do 258833965Sjdp not want to fiddle with the addend. Otherwise, we 258933965Sjdp need to include the symbol value so that it becomes 259033965Sjdp an addend for the dynamic reloc. */ 259133965Sjdp if (! relocate) 259233965Sjdp continue; 259333965Sjdp } 259433965Sjdp break; 259533965Sjdp 2596104840Sobrien case R_386_TLS_IE: 2597104840Sobrien if (info->shared) 2598104840Sobrien { 2599130570Sobrien Elf_Internal_Rela outrel; 2600130570Sobrien bfd_byte *loc; 2601104840Sobrien asection *sreloc; 2602104840Sobrien 2603104840Sobrien outrel.r_offset = rel->r_offset 2604104840Sobrien + input_section->output_section->vma 2605104840Sobrien + input_section->output_offset; 2606104840Sobrien outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); 2607104840Sobrien sreloc = elf_section_data (input_section)->sreloc; 2608104840Sobrien if (sreloc == NULL) 2609104840Sobrien abort (); 2610130570Sobrien loc = sreloc->contents; 2611130570Sobrien loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel); 2612104840Sobrien bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); 2613104840Sobrien } 2614104840Sobrien /* Fall through */ 2615104840Sobrien 2616104840Sobrien case R_386_TLS_GD: 2617218822Sdim case R_386_TLS_GOTDESC: 2618218822Sdim case R_386_TLS_DESC_CALL: 2619104840Sobrien case R_386_TLS_IE_32: 2620104840Sobrien case R_386_TLS_GOTIE: 2621104840Sobrien r_type = elf_i386_tls_transition (info, r_type, h == NULL); 2622104840Sobrien tls_type = GOT_UNKNOWN; 2623104840Sobrien if (h == NULL && local_got_offsets) 2624104840Sobrien tls_type = elf_i386_local_got_tls_type (input_bfd) [r_symndx]; 2625104840Sobrien else if (h != NULL) 2626104840Sobrien { 2627104840Sobrien tls_type = elf_i386_hash_entry(h)->tls_type; 2628104840Sobrien if (!info->shared && h->dynindx == -1 && (tls_type & GOT_TLS_IE)) 2629104840Sobrien r_type = R_386_TLS_LE_32; 2630104840Sobrien } 2631104840Sobrien if (tls_type == GOT_TLS_IE) 2632104840Sobrien tls_type = GOT_TLS_IE_NEG; 2633218822Sdim if (r_type == R_386_TLS_GD 2634218822Sdim || r_type == R_386_TLS_GOTDESC 2635218822Sdim || r_type == R_386_TLS_DESC_CALL) 2636104840Sobrien { 2637104840Sobrien if (tls_type == GOT_TLS_IE_POS) 2638104840Sobrien r_type = R_386_TLS_GOTIE; 2639104840Sobrien else if (tls_type & GOT_TLS_IE) 2640104840Sobrien r_type = R_386_TLS_IE_32; 2641104840Sobrien } 2642104840Sobrien 2643104840Sobrien if (r_type == R_386_TLS_LE_32) 2644104840Sobrien { 2645104840Sobrien BFD_ASSERT (! unresolved_reloc); 2646104840Sobrien if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD) 2647104840Sobrien { 2648104840Sobrien unsigned int val, type; 2649104840Sobrien bfd_vma roff; 2650104840Sobrien 2651104840Sobrien /* GD->LE transition. */ 2652104840Sobrien BFD_ASSERT (rel->r_offset >= 2); 2653104840Sobrien type = bfd_get_8 (input_bfd, contents + rel->r_offset - 2); 2654104840Sobrien BFD_ASSERT (type == 0x8d || type == 0x04); 2655218822Sdim BFD_ASSERT (rel->r_offset + 9 <= input_section->size); 2656104840Sobrien BFD_ASSERT (bfd_get_8 (input_bfd, 2657104840Sobrien contents + rel->r_offset + 4) 2658104840Sobrien == 0xe8); 2659104840Sobrien BFD_ASSERT (rel + 1 < relend); 2660104840Sobrien BFD_ASSERT (ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32); 2661104840Sobrien roff = rel->r_offset + 5; 2662104840Sobrien val = bfd_get_8 (input_bfd, 2663104840Sobrien contents + rel->r_offset - 1); 2664104840Sobrien if (type == 0x04) 2665104840Sobrien { 2666104840Sobrien /* leal foo(,%reg,1), %eax; call ___tls_get_addr 2667104840Sobrien Change it into: 2668104840Sobrien movl %gs:0, %eax; subl $foo@tpoff, %eax 2669104840Sobrien (6 byte form of subl). */ 2670104840Sobrien BFD_ASSERT (rel->r_offset >= 3); 2671104840Sobrien BFD_ASSERT (bfd_get_8 (input_bfd, 2672104840Sobrien contents + rel->r_offset - 3) 2673104840Sobrien == 0x8d); 2674104840Sobrien BFD_ASSERT ((val & 0xc7) == 0x05 && val != (4 << 3)); 2675104840Sobrien memcpy (contents + rel->r_offset - 3, 2676104840Sobrien "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12); 2677104840Sobrien } 2678104840Sobrien else 2679104840Sobrien { 2680104840Sobrien BFD_ASSERT ((val & 0xf8) == 0x80 && (val & 7) != 4); 2681218822Sdim if (rel->r_offset + 10 <= input_section->size 2682104840Sobrien && bfd_get_8 (input_bfd, 2683104840Sobrien contents + rel->r_offset + 9) == 0x90) 2684104840Sobrien { 2685104840Sobrien /* leal foo(%reg), %eax; call ___tls_get_addr; nop 2686104840Sobrien Change it into: 2687104840Sobrien movl %gs:0, %eax; subl $foo@tpoff, %eax 2688104840Sobrien (6 byte form of subl). */ 2689104840Sobrien memcpy (contents + rel->r_offset - 2, 2690104840Sobrien "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12); 2691104840Sobrien roff = rel->r_offset + 6; 2692104840Sobrien } 2693104840Sobrien else 2694104840Sobrien { 2695104840Sobrien /* leal foo(%reg), %eax; call ___tls_get_addr 2696104840Sobrien Change it into: 2697104840Sobrien movl %gs:0, %eax; subl $foo@tpoff, %eax 2698104840Sobrien (5 byte form of subl). */ 2699104840Sobrien memcpy (contents + rel->r_offset - 2, 2700104840Sobrien "\x65\xa1\0\0\0\0\x2d\0\0\0", 11); 2701104840Sobrien } 2702104840Sobrien } 2703104840Sobrien bfd_put_32 (output_bfd, tpoff (info, relocation), 2704104840Sobrien contents + roff); 2705104840Sobrien /* Skip R_386_PLT32. */ 2706104840Sobrien rel++; 2707104840Sobrien continue; 2708104840Sobrien } 2709218822Sdim else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC) 2710218822Sdim { 2711218822Sdim /* GDesc -> LE transition. 2712218822Sdim It's originally something like: 2713218822Sdim leal x@tlsdesc(%ebx), %eax 2714218822Sdim 2715218822Sdim leal x@ntpoff, %eax 2716218822Sdim 2717218822Sdim Registers other than %eax may be set up here. */ 2718218822Sdim 2719218822Sdim unsigned int val, type; 2720218822Sdim bfd_vma roff; 2721218822Sdim 2722218822Sdim /* First, make sure it's a leal adding ebx to a 2723218822Sdim 32-bit offset into any register, although it's 2724218822Sdim probably almost always going to be eax. */ 2725218822Sdim roff = rel->r_offset; 2726218822Sdim BFD_ASSERT (roff >= 2); 2727218822Sdim type = bfd_get_8 (input_bfd, contents + roff - 2); 2728218822Sdim BFD_ASSERT (type == 0x8d); 2729218822Sdim val = bfd_get_8 (input_bfd, contents + roff - 1); 2730218822Sdim BFD_ASSERT ((val & 0xc7) == 0x83); 2731218822Sdim BFD_ASSERT (roff + 4 <= input_section->size); 2732218822Sdim 2733218822Sdim /* Now modify the instruction as appropriate. */ 2734218822Sdim /* aoliva FIXME: remove the above and xor the byte 2735218822Sdim below with 0x86. */ 2736218822Sdim bfd_put_8 (output_bfd, val ^ 0x86, 2737218822Sdim contents + roff - 1); 2738218822Sdim bfd_put_32 (output_bfd, -tpoff (info, relocation), 2739218822Sdim contents + roff); 2740218822Sdim continue; 2741218822Sdim } 2742218822Sdim else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL) 2743218822Sdim { 2744218822Sdim /* GDesc -> LE transition. 2745218822Sdim It's originally: 2746218822Sdim call *(%eax) 2747218822Sdim Turn it into: 2748218822Sdim nop; nop */ 2749218822Sdim 2750218822Sdim unsigned int val, type; 2751218822Sdim bfd_vma roff; 2752218822Sdim 2753218822Sdim /* First, make sure it's a call *(%eax). */ 2754218822Sdim roff = rel->r_offset; 2755218822Sdim BFD_ASSERT (roff + 2 <= input_section->size); 2756218822Sdim type = bfd_get_8 (input_bfd, contents + roff); 2757218822Sdim BFD_ASSERT (type == 0xff); 2758218822Sdim val = bfd_get_8 (input_bfd, contents + roff + 1); 2759218822Sdim BFD_ASSERT (val == 0x10); 2760218822Sdim 2761218822Sdim /* Now modify the instruction as appropriate. Use 2762218822Sdim xchg %ax,%ax instead of 2 nops. */ 2763218822Sdim bfd_put_8 (output_bfd, 0x66, contents + roff); 2764218822Sdim bfd_put_8 (output_bfd, 0x90, contents + roff + 1); 2765218822Sdim continue; 2766218822Sdim } 2767104840Sobrien else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_IE) 2768104840Sobrien { 2769104840Sobrien unsigned int val, type; 2770104840Sobrien 2771104840Sobrien /* IE->LE transition: 2772104840Sobrien Originally it can be one of: 2773104840Sobrien movl foo, %eax 2774104840Sobrien movl foo, %reg 2775104840Sobrien addl foo, %reg 2776104840Sobrien We change it into: 2777104840Sobrien movl $foo, %eax 2778104840Sobrien movl $foo, %reg 2779104840Sobrien addl $foo, %reg. */ 2780104840Sobrien BFD_ASSERT (rel->r_offset >= 1); 2781104840Sobrien val = bfd_get_8 (input_bfd, contents + rel->r_offset - 1); 2782218822Sdim BFD_ASSERT (rel->r_offset + 4 <= input_section->size); 2783104840Sobrien if (val == 0xa1) 2784104840Sobrien { 2785104840Sobrien /* movl foo, %eax. */ 2786130570Sobrien bfd_put_8 (output_bfd, 0xb8, 2787130570Sobrien contents + rel->r_offset - 1); 2788104840Sobrien } 2789107497Sobrien else 2790104840Sobrien { 2791107497Sobrien BFD_ASSERT (rel->r_offset >= 2); 2792130570Sobrien type = bfd_get_8 (input_bfd, 2793130570Sobrien contents + rel->r_offset - 2); 2794107497Sobrien switch (type) 2795130570Sobrien { 2796107497Sobrien case 0x8b: 2797107497Sobrien /* movl */ 2798107497Sobrien BFD_ASSERT ((val & 0xc7) == 0x05); 2799107497Sobrien bfd_put_8 (output_bfd, 0xc7, 2800107497Sobrien contents + rel->r_offset - 2); 2801107497Sobrien bfd_put_8 (output_bfd, 2802107497Sobrien 0xc0 | ((val >> 3) & 7), 2803107497Sobrien contents + rel->r_offset - 1); 2804107497Sobrien break; 2805107497Sobrien case 0x03: 2806107497Sobrien /* addl */ 2807107497Sobrien BFD_ASSERT ((val & 0xc7) == 0x05); 2808107497Sobrien bfd_put_8 (output_bfd, 0x81, 2809107497Sobrien contents + rel->r_offset - 2); 2810107497Sobrien bfd_put_8 (output_bfd, 2811107497Sobrien 0xc0 | ((val >> 3) & 7), 2812107497Sobrien contents + rel->r_offset - 1); 2813107497Sobrien break; 2814107497Sobrien default: 2815107497Sobrien BFD_FAIL (); 2816107497Sobrien break; 2817130570Sobrien } 2818104840Sobrien } 2819104840Sobrien bfd_put_32 (output_bfd, -tpoff (info, relocation), 2820104840Sobrien contents + rel->r_offset); 2821104840Sobrien continue; 2822104840Sobrien } 2823104840Sobrien else 2824104840Sobrien { 2825104840Sobrien unsigned int val, type; 2826104840Sobrien 2827104840Sobrien /* {IE_32,GOTIE}->LE transition: 2828104840Sobrien Originally it can be one of: 2829104840Sobrien subl foo(%reg1), %reg2 2830104840Sobrien movl foo(%reg1), %reg2 2831104840Sobrien addl foo(%reg1), %reg2 2832104840Sobrien We change it into: 2833104840Sobrien subl $foo, %reg2 2834104840Sobrien movl $foo, %reg2 (6 byte form) 2835104840Sobrien addl $foo, %reg2. */ 2836104840Sobrien BFD_ASSERT (rel->r_offset >= 2); 2837104840Sobrien type = bfd_get_8 (input_bfd, contents + rel->r_offset - 2); 2838104840Sobrien val = bfd_get_8 (input_bfd, contents + rel->r_offset - 1); 2839218822Sdim BFD_ASSERT (rel->r_offset + 4 <= input_section->size); 2840104840Sobrien BFD_ASSERT ((val & 0xc0) == 0x80 && (val & 7) != 4); 2841104840Sobrien if (type == 0x8b) 2842104840Sobrien { 2843104840Sobrien /* movl */ 2844104840Sobrien bfd_put_8 (output_bfd, 0xc7, 2845104840Sobrien contents + rel->r_offset - 2); 2846104840Sobrien bfd_put_8 (output_bfd, 0xc0 | ((val >> 3) & 7), 2847104840Sobrien contents + rel->r_offset - 1); 2848104840Sobrien } 2849104840Sobrien else if (type == 0x2b) 2850104840Sobrien { 2851104840Sobrien /* subl */ 2852104840Sobrien bfd_put_8 (output_bfd, 0x81, 2853104840Sobrien contents + rel->r_offset - 2); 2854104840Sobrien bfd_put_8 (output_bfd, 0xe8 | ((val >> 3) & 7), 2855104840Sobrien contents + rel->r_offset - 1); 2856104840Sobrien } 2857104840Sobrien else if (type == 0x03) 2858104840Sobrien { 2859104840Sobrien /* addl */ 2860104840Sobrien bfd_put_8 (output_bfd, 0x81, 2861104840Sobrien contents + rel->r_offset - 2); 2862104840Sobrien bfd_put_8 (output_bfd, 0xc0 | ((val >> 3) & 7), 2863104840Sobrien contents + rel->r_offset - 1); 2864104840Sobrien } 2865104840Sobrien else 2866104840Sobrien BFD_FAIL (); 2867104840Sobrien if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTIE) 2868104840Sobrien bfd_put_32 (output_bfd, -tpoff (info, relocation), 2869104840Sobrien contents + rel->r_offset); 2870104840Sobrien else 2871104840Sobrien bfd_put_32 (output_bfd, tpoff (info, relocation), 2872104840Sobrien contents + rel->r_offset); 2873104840Sobrien continue; 2874104840Sobrien } 2875104840Sobrien } 2876104840Sobrien 2877104840Sobrien if (htab->sgot == NULL) 2878104840Sobrien abort (); 2879104840Sobrien 2880104840Sobrien if (h != NULL) 2881218822Sdim { 2882218822Sdim off = h->got.offset; 2883218822Sdim offplt = elf_i386_hash_entry (h)->tlsdesc_got; 2884218822Sdim } 2885104840Sobrien else 2886104840Sobrien { 2887104840Sobrien if (local_got_offsets == NULL) 2888104840Sobrien abort (); 2889104840Sobrien 2890104840Sobrien off = local_got_offsets[r_symndx]; 2891218822Sdim offplt = local_tlsdesc_gotents[r_symndx]; 2892104840Sobrien } 2893104840Sobrien 2894104840Sobrien if ((off & 1) != 0) 2895104840Sobrien off &= ~1; 2896130570Sobrien else 2897104840Sobrien { 2898130570Sobrien Elf_Internal_Rela outrel; 2899130570Sobrien bfd_byte *loc; 2900104840Sobrien int dr_type, indx; 2901218822Sdim asection *sreloc; 2902104840Sobrien 2903104840Sobrien if (htab->srelgot == NULL) 2904104840Sobrien abort (); 2905104840Sobrien 2906218822Sdim indx = h && h->dynindx != -1 ? h->dynindx : 0; 2907218822Sdim 2908218822Sdim if (GOT_TLS_GDESC_P (tls_type)) 2909218822Sdim { 2910218822Sdim outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_DESC); 2911218822Sdim BFD_ASSERT (htab->sgotplt_jump_table_size + offplt + 8 2912218822Sdim <= htab->sgotplt->size); 2913218822Sdim outrel.r_offset = (htab->sgotplt->output_section->vma 2914218822Sdim + htab->sgotplt->output_offset 2915218822Sdim + offplt 2916218822Sdim + htab->sgotplt_jump_table_size); 2917218822Sdim sreloc = htab->srelplt; 2918218822Sdim loc = sreloc->contents; 2919218822Sdim loc += (htab->next_tls_desc_index++ 2920218822Sdim * sizeof (Elf32_External_Rel)); 2921218822Sdim BFD_ASSERT (loc + sizeof (Elf32_External_Rel) 2922218822Sdim <= sreloc->contents + sreloc->size); 2923218822Sdim bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); 2924218822Sdim if (indx == 0) 2925218822Sdim { 2926218822Sdim BFD_ASSERT (! unresolved_reloc); 2927218822Sdim bfd_put_32 (output_bfd, 2928218822Sdim relocation - dtpoff_base (info), 2929218822Sdim htab->sgotplt->contents + offplt 2930218822Sdim + htab->sgotplt_jump_table_size + 4); 2931218822Sdim } 2932218822Sdim else 2933218822Sdim { 2934218822Sdim bfd_put_32 (output_bfd, 0, 2935218822Sdim htab->sgotplt->contents + offplt 2936218822Sdim + htab->sgotplt_jump_table_size + 4); 2937218822Sdim } 2938218822Sdim } 2939218822Sdim 2940218822Sdim sreloc = htab->srelgot; 2941218822Sdim 2942104840Sobrien outrel.r_offset = (htab->sgot->output_section->vma 2943104840Sobrien + htab->sgot->output_offset + off); 2944104840Sobrien 2945218822Sdim if (GOT_TLS_GD_P (tls_type)) 2946104840Sobrien dr_type = R_386_TLS_DTPMOD32; 2947218822Sdim else if (GOT_TLS_GDESC_P (tls_type)) 2948218822Sdim goto dr_done; 2949104840Sobrien else if (tls_type == GOT_TLS_IE_POS) 2950104840Sobrien dr_type = R_386_TLS_TPOFF; 2951104840Sobrien else 2952104840Sobrien dr_type = R_386_TLS_TPOFF32; 2953218822Sdim 2954104840Sobrien if (dr_type == R_386_TLS_TPOFF && indx == 0) 2955104840Sobrien bfd_put_32 (output_bfd, relocation - dtpoff_base (info), 2956104840Sobrien htab->sgot->contents + off); 2957104840Sobrien else if (dr_type == R_386_TLS_TPOFF32 && indx == 0) 2958104840Sobrien bfd_put_32 (output_bfd, dtpoff_base (info) - relocation, 2959104840Sobrien htab->sgot->contents + off); 2960218822Sdim else if (dr_type != R_386_TLS_DESC) 2961104840Sobrien bfd_put_32 (output_bfd, 0, 2962104840Sobrien htab->sgot->contents + off); 2963104840Sobrien outrel.r_info = ELF32_R_INFO (indx, dr_type); 2964218822Sdim 2965218822Sdim loc = sreloc->contents; 2966218822Sdim loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel); 2967218822Sdim BFD_ASSERT (loc + sizeof (Elf32_External_Rel) 2968218822Sdim <= sreloc->contents + sreloc->size); 2969104840Sobrien bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); 2970104840Sobrien 2971218822Sdim if (GOT_TLS_GD_P (tls_type)) 2972104840Sobrien { 2973104840Sobrien if (indx == 0) 2974104840Sobrien { 2975104840Sobrien BFD_ASSERT (! unresolved_reloc); 2976104840Sobrien bfd_put_32 (output_bfd, 2977104840Sobrien relocation - dtpoff_base (info), 2978104840Sobrien htab->sgot->contents + off + 4); 2979104840Sobrien } 2980104840Sobrien else 2981104840Sobrien { 2982104840Sobrien bfd_put_32 (output_bfd, 0, 2983104840Sobrien htab->sgot->contents + off + 4); 2984104840Sobrien outrel.r_info = ELF32_R_INFO (indx, 2985104840Sobrien R_386_TLS_DTPOFF32); 2986104840Sobrien outrel.r_offset += 4; 2987218822Sdim sreloc->reloc_count++; 2988130570Sobrien loc += sizeof (Elf32_External_Rel); 2989218822Sdim BFD_ASSERT (loc + sizeof (Elf32_External_Rel) 2990218822Sdim <= sreloc->contents + sreloc->size); 2991130570Sobrien bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); 2992104840Sobrien } 2993104840Sobrien } 2994104840Sobrien else if (tls_type == GOT_TLS_IE_BOTH) 2995104840Sobrien { 2996104840Sobrien bfd_put_32 (output_bfd, 2997104840Sobrien indx == 0 ? relocation - dtpoff_base (info) : 0, 2998104840Sobrien htab->sgot->contents + off + 4); 2999104840Sobrien outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_TPOFF); 3000104840Sobrien outrel.r_offset += 4; 3001218822Sdim sreloc->reloc_count++; 3002130570Sobrien loc += sizeof (Elf32_External_Rel); 3003104840Sobrien bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); 3004104840Sobrien } 3005104840Sobrien 3006218822Sdim dr_done: 3007104840Sobrien if (h != NULL) 3008104840Sobrien h->got.offset |= 1; 3009104840Sobrien else 3010104840Sobrien local_got_offsets[r_symndx] |= 1; 3011104840Sobrien } 3012104840Sobrien 3013218822Sdim if (off >= (bfd_vma) -2 3014218822Sdim && ! GOT_TLS_GDESC_P (tls_type)) 3015104840Sobrien abort (); 3016218822Sdim if (r_type == R_386_TLS_GOTDESC 3017218822Sdim || r_type == R_386_TLS_DESC_CALL) 3018104840Sobrien { 3019218822Sdim relocation = htab->sgotplt_jump_table_size + offplt; 3020218822Sdim unresolved_reloc = FALSE; 3021218822Sdim } 3022218822Sdim else if (r_type == ELF32_R_TYPE (rel->r_info)) 3023218822Sdim { 3024218822Sdim bfd_vma g_o_t = htab->sgotplt->output_section->vma 3025218822Sdim + htab->sgotplt->output_offset; 3026218822Sdim relocation = htab->sgot->output_section->vma 3027218822Sdim + htab->sgot->output_offset + off - g_o_t; 3028104840Sobrien if ((r_type == R_386_TLS_IE || r_type == R_386_TLS_GOTIE) 3029104840Sobrien && tls_type == GOT_TLS_IE_BOTH) 3030104840Sobrien relocation += 4; 3031104840Sobrien if (r_type == R_386_TLS_IE) 3032218822Sdim relocation += g_o_t; 3033130570Sobrien unresolved_reloc = FALSE; 3034104840Sobrien } 3035218822Sdim else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD) 3036104840Sobrien { 3037104840Sobrien unsigned int val, type; 3038104840Sobrien bfd_vma roff; 3039104840Sobrien 3040104840Sobrien /* GD->IE transition. */ 3041104840Sobrien BFD_ASSERT (rel->r_offset >= 2); 3042104840Sobrien type = bfd_get_8 (input_bfd, contents + rel->r_offset - 2); 3043104840Sobrien BFD_ASSERT (type == 0x8d || type == 0x04); 3044218822Sdim BFD_ASSERT (rel->r_offset + 9 <= input_section->size); 3045104840Sobrien BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4) 3046104840Sobrien == 0xe8); 3047104840Sobrien BFD_ASSERT (rel + 1 < relend); 3048104840Sobrien BFD_ASSERT (ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32); 3049104840Sobrien roff = rel->r_offset - 3; 3050104840Sobrien val = bfd_get_8 (input_bfd, contents + rel->r_offset - 1); 3051104840Sobrien if (type == 0x04) 3052104840Sobrien { 3053104840Sobrien /* leal foo(,%reg,1), %eax; call ___tls_get_addr 3054104840Sobrien Change it into: 3055104840Sobrien movl %gs:0, %eax; subl $foo@gottpoff(%reg), %eax. */ 3056104840Sobrien BFD_ASSERT (rel->r_offset >= 3); 3057104840Sobrien BFD_ASSERT (bfd_get_8 (input_bfd, 3058104840Sobrien contents + rel->r_offset - 3) 3059104840Sobrien == 0x8d); 3060104840Sobrien BFD_ASSERT ((val & 0xc7) == 0x05 && val != (4 << 3)); 3061104840Sobrien val >>= 3; 3062104840Sobrien } 3063104840Sobrien else 3064104840Sobrien { 3065104840Sobrien /* leal foo(%reg), %eax; call ___tls_get_addr; nop 3066104840Sobrien Change it into: 3067104840Sobrien movl %gs:0, %eax; subl $foo@gottpoff(%reg), %eax. */ 3068218822Sdim BFD_ASSERT (rel->r_offset + 10 <= input_section->size); 3069104840Sobrien BFD_ASSERT ((val & 0xf8) == 0x80 && (val & 7) != 4); 3070104840Sobrien BFD_ASSERT (bfd_get_8 (input_bfd, 3071104840Sobrien contents + rel->r_offset + 9) 3072104840Sobrien == 0x90); 3073104840Sobrien roff = rel->r_offset - 2; 3074104840Sobrien } 3075104840Sobrien memcpy (contents + roff, 3076104840Sobrien "\x65\xa1\0\0\0\0\x2b\x80\0\0\0", 12); 3077104840Sobrien contents[roff + 7] = 0x80 | (val & 7); 3078104840Sobrien /* If foo is used only with foo@gotntpoff(%reg) and 3079104840Sobrien foo@indntpoff, but not with foo@gottpoff(%reg), change 3080104840Sobrien subl $foo@gottpoff(%reg), %eax 3081104840Sobrien into: 3082104840Sobrien addl $foo@gotntpoff(%reg), %eax. */ 3083218822Sdim if (tls_type == GOT_TLS_IE_POS) 3084218822Sdim contents[roff + 6] = 0x03; 3085218822Sdim bfd_put_32 (output_bfd, 3086218822Sdim htab->sgot->output_section->vma 3087218822Sdim + htab->sgot->output_offset + off 3088218822Sdim - htab->sgotplt->output_section->vma 3089218822Sdim - htab->sgotplt->output_offset, 3090104840Sobrien contents + roff + 8); 3091104840Sobrien /* Skip R_386_PLT32. */ 3092104840Sobrien rel++; 3093104840Sobrien continue; 3094104840Sobrien } 3095218822Sdim else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC) 3096218822Sdim { 3097218822Sdim /* GDesc -> IE transition. 3098218822Sdim It's originally something like: 3099218822Sdim leal x@tlsdesc(%ebx), %eax 3100218822Sdim 3101218822Sdim Change it to: 3102218822Sdim movl x@gotntpoff(%ebx), %eax # before nop; nop 3103218822Sdim or: 3104218822Sdim movl x@gottpoff(%ebx), %eax # before negl %eax 3105218822Sdim 3106218822Sdim Registers other than %eax may be set up here. */ 3107218822Sdim 3108218822Sdim unsigned int val, type; 3109218822Sdim bfd_vma roff; 3110218822Sdim 3111218822Sdim /* First, make sure it's a leal adding ebx to a 32-bit 3112218822Sdim offset into any register, although it's probably 3113218822Sdim almost always going to be eax. */ 3114218822Sdim roff = rel->r_offset; 3115218822Sdim BFD_ASSERT (roff >= 2); 3116218822Sdim type = bfd_get_8 (input_bfd, contents + roff - 2); 3117218822Sdim BFD_ASSERT (type == 0x8d); 3118218822Sdim val = bfd_get_8 (input_bfd, contents + roff - 1); 3119218822Sdim BFD_ASSERT ((val & 0xc7) == 0x83); 3120218822Sdim BFD_ASSERT (roff + 4 <= input_section->size); 3121218822Sdim 3122218822Sdim /* Now modify the instruction as appropriate. */ 3123218822Sdim /* To turn a leal into a movl in the form we use it, it 3124218822Sdim suffices to change the first byte from 0x8d to 0x8b. 3125218822Sdim aoliva FIXME: should we decide to keep the leal, all 3126218822Sdim we have to do is remove the statement below, and 3127218822Sdim adjust the relaxation of R_386_TLS_DESC_CALL. */ 3128218822Sdim bfd_put_8 (output_bfd, 0x8b, contents + roff - 2); 3129218822Sdim 3130218822Sdim if (tls_type == GOT_TLS_IE_BOTH) 3131218822Sdim off += 4; 3132218822Sdim 3133218822Sdim bfd_put_32 (output_bfd, 3134218822Sdim htab->sgot->output_section->vma 3135218822Sdim + htab->sgot->output_offset + off 3136218822Sdim - htab->sgotplt->output_section->vma 3137218822Sdim - htab->sgotplt->output_offset, 3138218822Sdim contents + roff); 3139218822Sdim continue; 3140218822Sdim } 3141218822Sdim else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL) 3142218822Sdim { 3143218822Sdim /* GDesc -> IE transition. 3144218822Sdim It's originally: 3145218822Sdim call *(%eax) 3146218822Sdim 3147218822Sdim Change it to: 3148218822Sdim nop; nop 3149218822Sdim or 3150218822Sdim negl %eax 3151218822Sdim depending on how we transformed the TLS_GOTDESC above. 3152218822Sdim */ 3153218822Sdim 3154218822Sdim unsigned int val, type; 3155218822Sdim bfd_vma roff; 3156218822Sdim 3157218822Sdim /* First, make sure it's a call *(%eax). */ 3158218822Sdim roff = rel->r_offset; 3159218822Sdim BFD_ASSERT (roff + 2 <= input_section->size); 3160218822Sdim type = bfd_get_8 (input_bfd, contents + roff); 3161218822Sdim BFD_ASSERT (type == 0xff); 3162218822Sdim val = bfd_get_8 (input_bfd, contents + roff + 1); 3163218822Sdim BFD_ASSERT (val == 0x10); 3164218822Sdim 3165218822Sdim /* Now modify the instruction as appropriate. */ 3166218822Sdim if (tls_type != GOT_TLS_IE_NEG) 3167218822Sdim { 3168218822Sdim /* xchg %ax,%ax */ 3169218822Sdim bfd_put_8 (output_bfd, 0x66, contents + roff); 3170218822Sdim bfd_put_8 (output_bfd, 0x90, contents + roff + 1); 3171218822Sdim } 3172218822Sdim else 3173218822Sdim { 3174218822Sdim /* negl %eax */ 3175218822Sdim bfd_put_8 (output_bfd, 0xf7, contents + roff); 3176218822Sdim bfd_put_8 (output_bfd, 0xd8, contents + roff + 1); 3177218822Sdim } 3178218822Sdim 3179218822Sdim continue; 3180218822Sdim } 3181218822Sdim else 3182218822Sdim BFD_ASSERT (FALSE); 3183104840Sobrien break; 3184104840Sobrien 3185104840Sobrien case R_386_TLS_LDM: 3186104840Sobrien if (! info->shared) 3187104840Sobrien { 3188104840Sobrien unsigned int val; 3189104840Sobrien 3190104840Sobrien /* LD->LE transition: 3191104840Sobrien Ensure it is: 3192104840Sobrien leal foo(%reg), %eax; call ___tls_get_addr. 3193104840Sobrien We change it into: 3194104840Sobrien movl %gs:0, %eax; nop; leal 0(%esi,1), %esi. */ 3195104840Sobrien BFD_ASSERT (rel->r_offset >= 2); 3196104840Sobrien BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 2) 3197104840Sobrien == 0x8d); 3198104840Sobrien val = bfd_get_8 (input_bfd, contents + rel->r_offset - 1); 3199104840Sobrien BFD_ASSERT ((val & 0xf8) == 0x80 && (val & 7) != 4); 3200218822Sdim BFD_ASSERT (rel->r_offset + 9 <= input_section->size); 3201104840Sobrien BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4) 3202104840Sobrien == 0xe8); 3203104840Sobrien BFD_ASSERT (rel + 1 < relend); 3204104840Sobrien BFD_ASSERT (ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32); 3205104840Sobrien memcpy (contents + rel->r_offset - 2, 3206104840Sobrien "\x65\xa1\0\0\0\0\x90\x8d\x74\x26", 11); 3207104840Sobrien /* Skip R_386_PLT32. */ 3208104840Sobrien rel++; 3209104840Sobrien continue; 3210104840Sobrien } 3211104840Sobrien 3212104840Sobrien if (htab->sgot == NULL) 3213104840Sobrien abort (); 3214104840Sobrien 3215104840Sobrien off = htab->tls_ldm_got.offset; 3216104840Sobrien if (off & 1) 3217104840Sobrien off &= ~1; 3218104840Sobrien else 3219104840Sobrien { 3220130570Sobrien Elf_Internal_Rela outrel; 3221130570Sobrien bfd_byte *loc; 3222104840Sobrien 3223104840Sobrien if (htab->srelgot == NULL) 3224104840Sobrien abort (); 3225104840Sobrien 3226104840Sobrien outrel.r_offset = (htab->sgot->output_section->vma 3227104840Sobrien + htab->sgot->output_offset + off); 3228104840Sobrien 3229104840Sobrien bfd_put_32 (output_bfd, 0, 3230104840Sobrien htab->sgot->contents + off); 3231104840Sobrien bfd_put_32 (output_bfd, 0, 3232104840Sobrien htab->sgot->contents + off + 4); 3233104840Sobrien outrel.r_info = ELF32_R_INFO (0, R_386_TLS_DTPMOD32); 3234130570Sobrien loc = htab->srelgot->contents; 3235130570Sobrien loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rel); 3236104840Sobrien bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); 3237104840Sobrien htab->tls_ldm_got.offset |= 1; 3238104840Sobrien } 3239218822Sdim relocation = htab->sgot->output_section->vma 3240218822Sdim + htab->sgot->output_offset + off 3241218822Sdim - htab->sgotplt->output_section->vma 3242218822Sdim - htab->sgotplt->output_offset; 3243130570Sobrien unresolved_reloc = FALSE; 3244104840Sobrien break; 3245104840Sobrien 3246104840Sobrien case R_386_TLS_LDO_32: 3247130570Sobrien if (info->shared || (input_section->flags & SEC_CODE) == 0) 3248104840Sobrien relocation -= dtpoff_base (info); 3249104840Sobrien else 3250104840Sobrien /* When converting LDO to LE, we must negate. */ 3251104840Sobrien relocation = -tpoff (info, relocation); 3252104840Sobrien break; 3253104840Sobrien 3254104840Sobrien case R_386_TLS_LE_32: 3255104840Sobrien case R_386_TLS_LE: 3256104840Sobrien if (info->shared) 3257104840Sobrien { 3258130570Sobrien Elf_Internal_Rela outrel; 3259104840Sobrien asection *sreloc; 3260130570Sobrien bfd_byte *loc; 3261104840Sobrien int indx; 3262104840Sobrien 3263104840Sobrien outrel.r_offset = rel->r_offset 3264104840Sobrien + input_section->output_section->vma 3265104840Sobrien + input_section->output_offset; 3266104840Sobrien if (h != NULL && h->dynindx != -1) 3267104840Sobrien indx = h->dynindx; 3268104840Sobrien else 3269104840Sobrien indx = 0; 3270104840Sobrien if (r_type == R_386_TLS_LE_32) 3271104840Sobrien outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_TPOFF32); 3272104840Sobrien else 3273104840Sobrien outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_TPOFF); 3274104840Sobrien sreloc = elf_section_data (input_section)->sreloc; 3275104840Sobrien if (sreloc == NULL) 3276104840Sobrien abort (); 3277130570Sobrien loc = sreloc->contents; 3278130570Sobrien loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel); 3279104840Sobrien bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); 3280104840Sobrien if (indx) 3281104840Sobrien continue; 3282104840Sobrien else if (r_type == R_386_TLS_LE_32) 3283104840Sobrien relocation = dtpoff_base (info) - relocation; 3284104840Sobrien else 3285104840Sobrien relocation -= dtpoff_base (info); 3286104840Sobrien } 3287104840Sobrien else if (r_type == R_386_TLS_LE_32) 3288104840Sobrien relocation = tpoff (info, relocation); 3289104840Sobrien else 3290104840Sobrien relocation = -tpoff (info, relocation); 3291104840Sobrien break; 3292104840Sobrien 329333965Sjdp default: 329433965Sjdp break; 329533965Sjdp } 329633965Sjdp 3297104840Sobrien /* Dynamic relocs are not propagated for SEC_DEBUGGING sections 3298104840Sobrien because such sections are not SEC_ALLOC and thus ld.so will 3299104840Sobrien not process them. */ 330089861Sobrien if (unresolved_reloc 3301104840Sobrien && !((input_section->flags & SEC_DEBUGGING) != 0 3302218822Sdim && h->def_dynamic)) 3303104840Sobrien { 3304104840Sobrien (*_bfd_error_handler) 3305218822Sdim (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), 3306218822Sdim input_bfd, 3307218822Sdim input_section, 3308104840Sobrien (long) rel->r_offset, 3309218822Sdim howto->name, 3310104840Sobrien h->root.root.string); 3311130570Sobrien return FALSE; 3312104840Sobrien } 331389861Sobrien 331433965Sjdp r = _bfd_final_link_relocate (howto, input_bfd, input_section, 331533965Sjdp contents, rel->r_offset, 3316130570Sobrien relocation, 0); 331733965Sjdp 331833965Sjdp if (r != bfd_reloc_ok) 331933965Sjdp { 332089861Sobrien const char *name; 332189861Sobrien 332289861Sobrien if (h != NULL) 332389861Sobrien name = h->root.root.string; 332489861Sobrien else 332533965Sjdp { 332689861Sobrien name = bfd_elf_string_from_elf_section (input_bfd, 332789861Sobrien symtab_hdr->sh_link, 332889861Sobrien sym->st_name); 332989861Sobrien if (name == NULL) 3330130570Sobrien return FALSE; 333189861Sobrien if (*name == '\0') 333289861Sobrien name = bfd_section_name (input_bfd, sec); 333389861Sobrien } 333433965Sjdp 333589861Sobrien if (r == bfd_reloc_overflow) 333689861Sobrien { 333789861Sobrien if (! ((*info->callbacks->reloc_overflow) 3338218822Sdim (info, (h ? &h->root : NULL), name, howto->name, 3339218822Sdim (bfd_vma) 0, input_bfd, input_section, 3340218822Sdim rel->r_offset))) 3341130570Sobrien return FALSE; 334233965Sjdp } 334389861Sobrien else 334489861Sobrien { 334589861Sobrien (*_bfd_error_handler) 3346218822Sdim (_("%B(%A+0x%lx): reloc against `%s': error %d"), 3347218822Sdim input_bfd, input_section, 334889861Sobrien (long) rel->r_offset, name, (int) r); 3349130570Sobrien return FALSE; 335089861Sobrien } 335133965Sjdp } 335233965Sjdp } 335333965Sjdp 3354130570Sobrien return TRUE; 335533965Sjdp} 335633965Sjdp 335733965Sjdp/* Finish up dynamic symbol handling. We set the contents of various 335833965Sjdp dynamic sections here. */ 335933965Sjdp 3360130570Sobrienstatic bfd_boolean 3361130570Sobrienelf_i386_finish_dynamic_symbol (bfd *output_bfd, 3362130570Sobrien struct bfd_link_info *info, 3363130570Sobrien struct elf_link_hash_entry *h, 3364130570Sobrien Elf_Internal_Sym *sym) 336533965Sjdp{ 336689861Sobrien struct elf_i386_link_hash_table *htab; 336733965Sjdp 336889861Sobrien htab = elf_i386_hash_table (info); 336933965Sjdp 337060509Sobrien if (h->plt.offset != (bfd_vma) -1) 337133965Sjdp { 337233965Sjdp bfd_vma plt_index; 337333965Sjdp bfd_vma got_offset; 3374130570Sobrien Elf_Internal_Rela rel; 3375130570Sobrien bfd_byte *loc; 337633965Sjdp 337733965Sjdp /* This symbol has an entry in the procedure linkage table. Set 337833965Sjdp it up. */ 337933965Sjdp 338089861Sobrien if (h->dynindx == -1 338189861Sobrien || htab->splt == NULL 338289861Sobrien || htab->sgotplt == NULL 338389861Sobrien || htab->srelplt == NULL) 338489861Sobrien abort (); 338533965Sjdp 338633965Sjdp /* Get the index in the procedure linkage table which 338733965Sjdp corresponds to this symbol. This is the index of this symbol 338833965Sjdp in all the symbols for which we are making plt entries. The 338933965Sjdp first entry in the procedure linkage table is reserved. */ 339060509Sobrien plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; 339133965Sjdp 339233965Sjdp /* Get the offset into the .got table of the entry that 339333965Sjdp corresponds to this function. Each .got entry is 4 bytes. 339433965Sjdp The first three are reserved. */ 339533965Sjdp got_offset = (plt_index + 3) * 4; 339633965Sjdp 339733965Sjdp /* Fill in the entry in the procedure linkage table. */ 339833965Sjdp if (! info->shared) 339933965Sjdp { 340089861Sobrien memcpy (htab->splt->contents + h->plt.offset, elf_i386_plt_entry, 340133965Sjdp PLT_ENTRY_SIZE); 340233965Sjdp bfd_put_32 (output_bfd, 340389861Sobrien (htab->sgotplt->output_section->vma 340489861Sobrien + htab->sgotplt->output_offset 340533965Sjdp + got_offset), 340689861Sobrien htab->splt->contents + h->plt.offset + 2); 3407218822Sdim 3408218822Sdim if (htab->is_vxworks) 3409218822Sdim { 3410218822Sdim int s, k, reloc_index; 3411218822Sdim 3412218822Sdim /* Create the R_386_32 relocation referencing the GOT 3413218822Sdim for this PLT entry. */ 3414218822Sdim 3415218822Sdim /* S: Current slot number (zero-based). */ 3416218822Sdim s = (h->plt.offset - PLT_ENTRY_SIZE) / PLT_ENTRY_SIZE; 3417218822Sdim /* K: Number of relocations for PLTResolve. */ 3418218822Sdim if (info->shared) 3419218822Sdim k = PLTRESOLVE_RELOCS_SHLIB; 3420218822Sdim else 3421218822Sdim k = PLTRESOLVE_RELOCS; 3422218822Sdim /* Skip the PLTresolve relocations, and the relocations for 3423218822Sdim the other PLT slots. */ 3424218822Sdim reloc_index = k + s * PLT_NON_JUMP_SLOT_RELOCS; 3425218822Sdim loc = (htab->srelplt2->contents + reloc_index 3426218822Sdim * sizeof (Elf32_External_Rel)); 3427218822Sdim 3428218822Sdim rel.r_offset = (htab->splt->output_section->vma 3429218822Sdim + htab->splt->output_offset 3430218822Sdim + h->plt.offset + 2), 3431218822Sdim rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); 3432218822Sdim bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); 3433218822Sdim 3434218822Sdim /* Create the R_386_32 relocation referencing the beginning of 3435218822Sdim the PLT for this GOT entry. */ 3436218822Sdim rel.r_offset = (htab->sgotplt->output_section->vma 3437218822Sdim + htab->sgotplt->output_offset 3438218822Sdim + got_offset); 3439218822Sdim rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_386_32); 3440218822Sdim bfd_elf32_swap_reloc_out (output_bfd, &rel, 3441218822Sdim loc + sizeof (Elf32_External_Rel)); 3442218822Sdim } 344333965Sjdp } 344433965Sjdp else 344533965Sjdp { 344689861Sobrien memcpy (htab->splt->contents + h->plt.offset, elf_i386_pic_plt_entry, 344733965Sjdp PLT_ENTRY_SIZE); 344833965Sjdp bfd_put_32 (output_bfd, got_offset, 344989861Sobrien htab->splt->contents + h->plt.offset + 2); 345033965Sjdp } 345133965Sjdp 345233965Sjdp bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel), 345389861Sobrien htab->splt->contents + h->plt.offset + 7); 345460509Sobrien bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE), 345589861Sobrien htab->splt->contents + h->plt.offset + 12); 345633965Sjdp 345733965Sjdp /* Fill in the entry in the global offset table. */ 345833965Sjdp bfd_put_32 (output_bfd, 345989861Sobrien (htab->splt->output_section->vma 346089861Sobrien + htab->splt->output_offset 346160509Sobrien + h->plt.offset 346233965Sjdp + 6), 346389861Sobrien htab->sgotplt->contents + got_offset); 346433965Sjdp 346533965Sjdp /* Fill in the entry in the .rel.plt section. */ 346689861Sobrien rel.r_offset = (htab->sgotplt->output_section->vma 346789861Sobrien + htab->sgotplt->output_offset 346833965Sjdp + got_offset); 346933965Sjdp rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT); 3470130570Sobrien loc = htab->srelplt->contents + plt_index * sizeof (Elf32_External_Rel); 347189861Sobrien bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); 347233965Sjdp 3473218822Sdim if (!h->def_regular) 347433965Sjdp { 347533965Sjdp /* Mark the symbol as undefined, rather than as defined in 3476130570Sobrien the .plt section. Leave the value if there were any 3477130570Sobrien relocations where pointer equality matters (this is a clue 347889861Sobrien for the dynamic linker, to make function pointer 347989861Sobrien comparisons work between an application and shared 3480130570Sobrien library), otherwise set it to zero. If a function is only 3481130570Sobrien called from a binary, there is no need to slow down 3482130570Sobrien shared libraries because of that. */ 348333965Sjdp sym->st_shndx = SHN_UNDEF; 3484218822Sdim if (!h->pointer_equality_needed) 3485130570Sobrien sym->st_value = 0; 348633965Sjdp } 348733965Sjdp } 348833965Sjdp 3489104840Sobrien if (h->got.offset != (bfd_vma) -1 3490218822Sdim && ! GOT_TLS_GD_ANY_P (elf_i386_hash_entry(h)->tls_type) 3491104840Sobrien && (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE) == 0) 349233965Sjdp { 3493130570Sobrien Elf_Internal_Rela rel; 3494130570Sobrien bfd_byte *loc; 349533965Sjdp 349633965Sjdp /* This symbol has an entry in the global offset table. Set it 349733965Sjdp up. */ 349833965Sjdp 349989861Sobrien if (htab->sgot == NULL || htab->srelgot == NULL) 350089861Sobrien abort (); 350133965Sjdp 350289861Sobrien rel.r_offset = (htab->sgot->output_section->vma 350389861Sobrien + htab->sgot->output_offset 350489861Sobrien + (h->got.offset & ~(bfd_vma) 1)); 350533965Sjdp 350677302Sobrien /* If this is a static link, or it is a -Bsymbolic link and the 350777302Sobrien symbol is defined locally or was forced to be local because 350877302Sobrien of a version file, we just want to emit a RELATIVE reloc. 350938891Sjdp The entry in the global offset table will already have been 351038891Sjdp initialized in the relocate_section function. */ 351189861Sobrien if (info->shared 3512130570Sobrien && SYMBOL_REFERENCES_LOCAL (info, h)) 351377302Sobrien { 351489861Sobrien BFD_ASSERT((h->got.offset & 1) != 0); 351577302Sobrien rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); 351677302Sobrien } 351733965Sjdp else 351833965Sjdp { 351977302Sobrien BFD_ASSERT((h->got.offset & 1) == 0); 352089861Sobrien bfd_put_32 (output_bfd, (bfd_vma) 0, 352189861Sobrien htab->sgot->contents + h->got.offset); 352233965Sjdp rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT); 352333965Sjdp } 352433965Sjdp 3525130570Sobrien loc = htab->srelgot->contents; 3526130570Sobrien loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rel); 352789861Sobrien bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); 352833965Sjdp } 352933965Sjdp 3530218822Sdim if (h->needs_copy) 353133965Sjdp { 3532130570Sobrien Elf_Internal_Rela rel; 3533130570Sobrien bfd_byte *loc; 353433965Sjdp 353533965Sjdp /* This symbol needs a copy reloc. Set it up. */ 353633965Sjdp 353789861Sobrien if (h->dynindx == -1 353889861Sobrien || (h->root.type != bfd_link_hash_defined 353989861Sobrien && h->root.type != bfd_link_hash_defweak) 354089861Sobrien || htab->srelbss == NULL) 354189861Sobrien abort (); 354233965Sjdp 354333965Sjdp rel.r_offset = (h->root.u.def.value 354433965Sjdp + h->root.u.def.section->output_section->vma 354533965Sjdp + h->root.u.def.section->output_offset); 354633965Sjdp rel.r_info = ELF32_R_INFO (h->dynindx, R_386_COPY); 3547130570Sobrien loc = htab->srelbss->contents; 3548130570Sobrien loc += htab->srelbss->reloc_count++ * sizeof (Elf32_External_Rel); 354989861Sobrien bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); 355033965Sjdp } 355133965Sjdp 3552218822Sdim /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. 3553218822Sdim On VxWorks, the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it 3554218822Sdim is relative to the ".got" section. */ 355533965Sjdp if (strcmp (h->root.root.string, "_DYNAMIC") == 0 3556218822Sdim || (!htab->is_vxworks && h == htab->elf.hgot)) 355733965Sjdp sym->st_shndx = SHN_ABS; 355833965Sjdp 3559130570Sobrien return TRUE; 356033965Sjdp} 356133965Sjdp 356289861Sobrien/* Used to decide how to sort relocs in an optimal manner for the 356389861Sobrien dynamic linker, before writing them out. */ 356489861Sobrien 356589861Sobrienstatic enum elf_reloc_type_class 3566130570Sobrienelf_i386_reloc_type_class (const Elf_Internal_Rela *rela) 356789861Sobrien{ 3568130570Sobrien switch (ELF32_R_TYPE (rela->r_info)) 356989861Sobrien { 357089861Sobrien case R_386_RELATIVE: 357189861Sobrien return reloc_class_relative; 357289861Sobrien case R_386_JUMP_SLOT: 357389861Sobrien return reloc_class_plt; 357489861Sobrien case R_386_COPY: 357589861Sobrien return reloc_class_copy; 357689861Sobrien default: 357789861Sobrien return reloc_class_normal; 357889861Sobrien } 357989861Sobrien} 358089861Sobrien 358133965Sjdp/* Finish up the dynamic sections. */ 358233965Sjdp 3583130570Sobrienstatic bfd_boolean 3584130570Sobrienelf_i386_finish_dynamic_sections (bfd *output_bfd, 3585130570Sobrien struct bfd_link_info *info) 358633965Sjdp{ 358789861Sobrien struct elf_i386_link_hash_table *htab; 358833965Sjdp bfd *dynobj; 358933965Sjdp asection *sdyn; 359033965Sjdp 359189861Sobrien htab = elf_i386_hash_table (info); 359289861Sobrien dynobj = htab->elf.dynobj; 359333965Sjdp sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); 359433965Sjdp 359589861Sobrien if (htab->elf.dynamic_sections_created) 359633965Sjdp { 359733965Sjdp Elf32_External_Dyn *dyncon, *dynconend; 359833965Sjdp 359989861Sobrien if (sdyn == NULL || htab->sgot == NULL) 360089861Sobrien abort (); 360133965Sjdp 360233965Sjdp dyncon = (Elf32_External_Dyn *) sdyn->contents; 3603218822Sdim dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); 360433965Sjdp for (; dyncon < dynconend; dyncon++) 360533965Sjdp { 360633965Sjdp Elf_Internal_Dyn dyn; 360733965Sjdp asection *s; 360833965Sjdp 360933965Sjdp bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); 361033965Sjdp 361133965Sjdp switch (dyn.d_tag) 361233965Sjdp { 361333965Sjdp default: 361489861Sobrien continue; 361589861Sobrien 361689861Sobrien case DT_PLTGOT: 3617218822Sdim s = htab->sgotplt; 3618218822Sdim dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; 361933965Sjdp break; 362033965Sjdp 362133965Sjdp case DT_JMPREL: 3622130570Sobrien s = htab->srelplt; 3623130570Sobrien dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; 362433965Sjdp break; 362533965Sjdp 362633965Sjdp case DT_PLTRELSZ: 3627130570Sobrien s = htab->srelplt; 3628218822Sdim dyn.d_un.d_val = s->size; 362933965Sjdp break; 363033965Sjdp 363133965Sjdp case DT_RELSZ: 363233965Sjdp /* My reading of the SVR4 ABI indicates that the 363333965Sjdp procedure linkage table relocs (DT_JMPREL) should be 363433965Sjdp included in the overall relocs (DT_REL). This is 363533965Sjdp what Solaris does. However, UnixWare can not handle 363633965Sjdp that case. Therefore, we override the DT_RELSZ entry 3637130570Sobrien here to make it not include the JMPREL relocs. */ 3638130570Sobrien s = htab->srelplt; 3639130570Sobrien if (s == NULL) 3640130570Sobrien continue; 3641218822Sdim dyn.d_un.d_val -= s->size; 364233965Sjdp break; 3643130570Sobrien 3644130570Sobrien case DT_REL: 3645130570Sobrien /* We may not be using the standard ELF linker script. 3646130570Sobrien If .rel.plt is the first .rel section, we adjust 3647130570Sobrien DT_REL to not include it. */ 3648130570Sobrien s = htab->srelplt; 3649130570Sobrien if (s == NULL) 3650130570Sobrien continue; 3651130570Sobrien if (dyn.d_un.d_ptr != s->output_section->vma + s->output_offset) 3652130570Sobrien continue; 3653218822Sdim dyn.d_un.d_ptr += s->size; 3654130570Sobrien break; 365533965Sjdp } 365689861Sobrien 365789861Sobrien bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); 365833965Sjdp } 365933965Sjdp 366033965Sjdp /* Fill in the first entry in the procedure linkage table. */ 3661218822Sdim if (htab->splt && htab->splt->size > 0) 366233965Sjdp { 366333965Sjdp if (info->shared) 3664218822Sdim { 3665218822Sdim memcpy (htab->splt->contents, elf_i386_pic_plt0_entry, 3666218822Sdim sizeof (elf_i386_pic_plt0_entry)); 3667218822Sdim memset (htab->splt->contents + sizeof (elf_i386_pic_plt0_entry), 3668218822Sdim htab->plt0_pad_byte, 3669218822Sdim PLT_ENTRY_SIZE - sizeof (elf_i386_pic_plt0_entry)); 3670218822Sdim } 367133965Sjdp else 367233965Sjdp { 3673218822Sdim memcpy (htab->splt->contents, elf_i386_plt0_entry, 3674218822Sdim sizeof(elf_i386_plt0_entry)); 3675218822Sdim memset (htab->splt->contents + sizeof (elf_i386_plt0_entry), 3676218822Sdim htab->plt0_pad_byte, 3677218822Sdim PLT_ENTRY_SIZE - sizeof (elf_i386_plt0_entry)); 367833965Sjdp bfd_put_32 (output_bfd, 367989861Sobrien (htab->sgotplt->output_section->vma 368089861Sobrien + htab->sgotplt->output_offset 368189861Sobrien + 4), 368289861Sobrien htab->splt->contents + 2); 368333965Sjdp bfd_put_32 (output_bfd, 368489861Sobrien (htab->sgotplt->output_section->vma 368589861Sobrien + htab->sgotplt->output_offset 368689861Sobrien + 8), 368789861Sobrien htab->splt->contents + 8); 3688218822Sdim 3689218822Sdim if (htab->is_vxworks) 3690218822Sdim { 3691218822Sdim Elf_Internal_Rela rel; 3692218822Sdim 3693218822Sdim /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 4. 3694218822Sdim On IA32 we use REL relocations so the addend goes in 3695218822Sdim the PLT directly. */ 3696218822Sdim rel.r_offset = (htab->splt->output_section->vma 3697218822Sdim + htab->splt->output_offset 3698218822Sdim + 2); 3699218822Sdim rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); 3700218822Sdim bfd_elf32_swap_reloc_out (output_bfd, &rel, 3701218822Sdim htab->srelplt2->contents); 3702218822Sdim /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 8. */ 3703218822Sdim rel.r_offset = (htab->splt->output_section->vma 3704218822Sdim + htab->splt->output_offset 3705218822Sdim + 8); 3706218822Sdim rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); 3707218822Sdim bfd_elf32_swap_reloc_out (output_bfd, &rel, 3708218822Sdim htab->srelplt2->contents + 3709218822Sdim sizeof (Elf32_External_Rel)); 3710218822Sdim } 371133965Sjdp } 371260509Sobrien 371360509Sobrien /* UnixWare sets the entsize of .plt to 4, although that doesn't 371460509Sobrien really seem like the right value. */ 371589861Sobrien elf_section_data (htab->splt->output_section) 371689861Sobrien ->this_hdr.sh_entsize = 4; 3717218822Sdim 3718218822Sdim /* Correct the .rel.plt.unloaded relocations. */ 3719218822Sdim if (htab->is_vxworks && !info->shared) 3720218822Sdim { 3721218822Sdim int num_plts = (htab->splt->size / PLT_ENTRY_SIZE) - 1; 3722218822Sdim unsigned char *p; 3723218822Sdim 3724218822Sdim p = htab->srelplt2->contents; 3725218822Sdim if (info->shared) 3726218822Sdim p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel); 3727218822Sdim else 3728218822Sdim p += PLTRESOLVE_RELOCS * sizeof (Elf32_External_Rel); 3729218822Sdim 3730218822Sdim for (; num_plts; num_plts--) 3731218822Sdim { 3732218822Sdim Elf_Internal_Rela rel; 3733218822Sdim bfd_elf32_swap_reloc_in (output_bfd, p, &rel); 3734218822Sdim rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); 3735218822Sdim bfd_elf32_swap_reloc_out (output_bfd, &rel, p); 3736218822Sdim p += sizeof (Elf32_External_Rel); 3737218822Sdim 3738218822Sdim bfd_elf32_swap_reloc_in (output_bfd, p, &rel); 3739218822Sdim rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_386_32); 3740218822Sdim bfd_elf32_swap_reloc_out (output_bfd, &rel, p); 3741218822Sdim p += sizeof (Elf32_External_Rel); 3742218822Sdim } 3743218822Sdim } 374433965Sjdp } 374533965Sjdp } 374633965Sjdp 374789861Sobrien if (htab->sgotplt) 374833965Sjdp { 374989861Sobrien /* Fill in the first three entries in the global offset table. */ 3750218822Sdim if (htab->sgotplt->size > 0) 375189861Sobrien { 375289861Sobrien bfd_put_32 (output_bfd, 3753130570Sobrien (sdyn == NULL ? 0 375489861Sobrien : sdyn->output_section->vma + sdyn->output_offset), 375589861Sobrien htab->sgotplt->contents); 3756130570Sobrien bfd_put_32 (output_bfd, 0, htab->sgotplt->contents + 4); 3757130570Sobrien bfd_put_32 (output_bfd, 0, htab->sgotplt->contents + 8); 375889861Sobrien } 375989861Sobrien 376089861Sobrien elf_section_data (htab->sgotplt->output_section)->this_hdr.sh_entsize = 4; 376133965Sjdp } 3762218822Sdim 3763218822Sdim if (htab->sgot && htab->sgot->size > 0) 3764218822Sdim elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize = 4; 3765218822Sdim 3766130570Sobrien return TRUE; 376733965Sjdp} 376833965Sjdp 3769218822Sdim/* Return address for Ith PLT stub in section PLT, for relocation REL 3770218822Sdim or (bfd_vma) -1 if it should not be included. */ 3771218822Sdim 3772218822Sdimstatic bfd_vma 3773218822Sdimelf_i386_plt_sym_val (bfd_vma i, const asection *plt, 3774218822Sdim const arelent *rel ATTRIBUTE_UNUSED) 3775218822Sdim{ 3776218822Sdim return plt->vma + (i + 1) * PLT_ENTRY_SIZE; 3777218822Sdim} 3778218822Sdim 3779218822Sdim/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */ 3780218822Sdim 3781218822Sdimstatic bfd_boolean 3782218822Sdimelf_i386_hash_symbol (struct elf_link_hash_entry *h) 3783218822Sdim{ 3784218822Sdim if (h->plt.offset != (bfd_vma) -1 3785218822Sdim && !h->def_regular 3786218822Sdim && !h->pointer_equality_needed) 3787218822Sdim return FALSE; 3788218822Sdim 3789218822Sdim return _bfd_elf_hash_symbol (h); 3790218822Sdim} 3791218822Sdim 379233965Sjdp#define TARGET_LITTLE_SYM bfd_elf32_i386_vec 379333965Sjdp#define TARGET_LITTLE_NAME "elf32-i386" 379433965Sjdp#define ELF_ARCH bfd_arch_i386 379533965Sjdp#define ELF_MACHINE_CODE EM_386 379633965Sjdp#define ELF_MAXPAGESIZE 0x1000 379733965Sjdp 379860509Sobrien#define elf_backend_can_gc_sections 1 379989861Sobrien#define elf_backend_can_refcount 1 380060509Sobrien#define elf_backend_want_got_plt 1 380160509Sobrien#define elf_backend_plt_readonly 1 380260509Sobrien#define elf_backend_want_plt_sym 0 380360509Sobrien#define elf_backend_got_header_size 12 380460509Sobrien 3805130570Sobrien/* Support RELA for objdump of prelink objects. */ 3806130570Sobrien#define elf_info_to_howto elf_i386_info_to_howto_rel 380777302Sobrien#define elf_info_to_howto_rel elf_i386_info_to_howto_rel 380877302Sobrien 3809104840Sobrien#define bfd_elf32_mkobject elf_i386_mkobject 3810104840Sobrien 381177302Sobrien#define bfd_elf32_bfd_is_local_label_name elf_i386_is_local_label_name 381277302Sobrien#define bfd_elf32_bfd_link_hash_table_create elf_i386_link_hash_table_create 381377302Sobrien#define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup 3814218822Sdim#define bfd_elf32_bfd_reloc_name_lookup elf_i386_reloc_name_lookup 381577302Sobrien 381677302Sobrien#define elf_backend_adjust_dynamic_symbol elf_i386_adjust_dynamic_symbol 3817218822Sdim#define elf_backend_relocs_compatible _bfd_elf_relocs_compatible 381877302Sobrien#define elf_backend_check_relocs elf_i386_check_relocs 381989861Sobrien#define elf_backend_copy_indirect_symbol elf_i386_copy_indirect_symbol 382089861Sobrien#define elf_backend_create_dynamic_sections elf_i386_create_dynamic_sections 382189861Sobrien#define elf_backend_fake_sections elf_i386_fake_sections 382277302Sobrien#define elf_backend_finish_dynamic_sections elf_i386_finish_dynamic_sections 382377302Sobrien#define elf_backend_finish_dynamic_symbol elf_i386_finish_dynamic_symbol 382477302Sobrien#define elf_backend_gc_mark_hook elf_i386_gc_mark_hook 382577302Sobrien#define elf_backend_gc_sweep_hook elf_i386_gc_sweep_hook 382689861Sobrien#define elf_backend_grok_prstatus elf_i386_grok_prstatus 382789861Sobrien#define elf_backend_grok_psinfo elf_i386_grok_psinfo 382889861Sobrien#define elf_backend_reloc_type_class elf_i386_reloc_type_class 382977302Sobrien#define elf_backend_relocate_section elf_i386_relocate_section 383077302Sobrien#define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections 3831218822Sdim#define elf_backend_always_size_sections elf_i386_always_size_sections 3832218822Sdim#define elf_backend_omit_section_dynsym \ 3833218822Sdim ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true) 3834218822Sdim#define elf_backend_plt_sym_val elf_i386_plt_sym_val 3835218822Sdim#define elf_backend_hash_symbol elf_i386_hash_symbol 383677302Sobrien 383733965Sjdp#include "elf32-target.h" 3838130570Sobrien 3839130570Sobrien/* FreeBSD support. */ 3840130570Sobrien 3841130570Sobrien#undef TARGET_LITTLE_SYM 3842130570Sobrien#define TARGET_LITTLE_SYM bfd_elf32_i386_freebsd_vec 3843130570Sobrien#undef TARGET_LITTLE_NAME 3844130570Sobrien#define TARGET_LITTLE_NAME "elf32-i386-freebsd" 3845218822Sdim#undef ELF_OSABI 3846218822Sdim#define ELF_OSABI ELFOSABI_FREEBSD 3847130570Sobrien 3848130570Sobrien/* The kernel recognizes executables as valid only if they carry a 3849130570Sobrien "FreeBSD" label in the ELF header. So we put this label on all 3850130570Sobrien executables and (for simplicity) also all other object files. */ 3851130570Sobrien 3852130570Sobrienstatic void 3853130570Sobrienelf_i386_post_process_headers (bfd *abfd, 3854130570Sobrien struct bfd_link_info *info ATTRIBUTE_UNUSED) 3855130570Sobrien{ 3856130570Sobrien Elf_Internal_Ehdr *i_ehdrp; 3857130570Sobrien 3858130570Sobrien i_ehdrp = elf_elfheader (abfd); 3859130570Sobrien 3860130570Sobrien /* Put an ABI label supported by FreeBSD >= 4.1. */ 3861218822Sdim i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi; 3862130570Sobrien#ifdef OLD_FREEBSD_ABI_LABEL 3863130570Sobrien /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */ 3864130570Sobrien memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8); 3865130570Sobrien#endif 3866130570Sobrien} 3867130570Sobrien 3868130570Sobrien#undef elf_backend_post_process_headers 3869130570Sobrien#define elf_backend_post_process_headers elf_i386_post_process_headers 3870130570Sobrien#undef elf32_bed 3871130570Sobrien#define elf32_bed elf32_i386_fbsd_bed 3872130570Sobrien 3873130570Sobrien#include "elf32-target.h" 3874218822Sdim 3875218822Sdim/* VxWorks support. */ 3876218822Sdim 3877218822Sdim#undef TARGET_LITTLE_SYM 3878218822Sdim#define TARGET_LITTLE_SYM bfd_elf32_i386_vxworks_vec 3879218822Sdim#undef TARGET_LITTLE_NAME 3880218822Sdim#define TARGET_LITTLE_NAME "elf32-i386-vxworks" 3881218822Sdim#undef ELF_OSABI 3882218822Sdim 3883218822Sdim/* Like elf_i386_link_hash_table_create but with tweaks for VxWorks. */ 3884218822Sdim 3885218822Sdimstatic struct bfd_link_hash_table * 3886218822Sdimelf_i386_vxworks_link_hash_table_create (bfd *abfd) 3887218822Sdim{ 3888218822Sdim struct bfd_link_hash_table *ret; 3889218822Sdim struct elf_i386_link_hash_table *htab; 3890218822Sdim 3891218822Sdim ret = elf_i386_link_hash_table_create (abfd); 3892218822Sdim if (ret) 3893218822Sdim { 3894218822Sdim htab = (struct elf_i386_link_hash_table *) ret; 3895218822Sdim htab->is_vxworks = 1; 3896218822Sdim htab->plt0_pad_byte = 0x90; 3897218822Sdim } 3898218822Sdim 3899218822Sdim return ret; 3900218822Sdim} 3901218822Sdim 3902218822Sdim 3903218822Sdim#undef elf_backend_relocs_compatible 3904218822Sdim#undef elf_backend_post_process_headers 3905218822Sdim#undef bfd_elf32_bfd_link_hash_table_create 3906218822Sdim#define bfd_elf32_bfd_link_hash_table_create \ 3907218822Sdim elf_i386_vxworks_link_hash_table_create 3908218822Sdim#undef elf_backend_add_symbol_hook 3909218822Sdim#define elf_backend_add_symbol_hook \ 3910218822Sdim elf_vxworks_add_symbol_hook 3911218822Sdim#undef elf_backend_link_output_symbol_hook 3912218822Sdim#define elf_backend_link_output_symbol_hook \ 3913218822Sdim elf_vxworks_link_output_symbol_hook 3914218822Sdim#undef elf_backend_emit_relocs 3915218822Sdim#define elf_backend_emit_relocs elf_vxworks_emit_relocs 3916218822Sdim#undef elf_backend_final_write_processing 3917218822Sdim#define elf_backend_final_write_processing \ 3918218822Sdim elf_vxworks_final_write_processing 3919218822Sdim 3920218822Sdim/* On VxWorks, we emit relocations against _PROCEDURE_LINKAGE_TABLE_, so 3921218822Sdim define it. */ 3922218822Sdim#undef elf_backend_want_plt_sym 3923218822Sdim#define elf_backend_want_plt_sym 1 3924218822Sdim 3925218822Sdim#undef elf32_bed 3926218822Sdim#define elf32_bed elf32_i386_vxworks_bed 3927218822Sdim 3928218822Sdim#include "elf32-target.h" 3929