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