- _bfd_elf_link_hash_copy_indirect (info, dir, ind);
- }
-}
-
-/* Return TRUE if the TLS access code sequence support transition
- from R_TYPE. */
-
-static bfd_boolean
-elf_i386_check_tls_transition (asection *sec,
- bfd_byte *contents,
- Elf_Internal_Shdr *symtab_hdr,
- struct elf_link_hash_entry **sym_hashes,
- unsigned int r_type,
- const Elf_Internal_Rela *rel,
- const Elf_Internal_Rela *relend)
-{
- unsigned int val, type, reg;
- unsigned long r_symndx;
- struct elf_link_hash_entry *h;
- bfd_vma offset;
- bfd_byte *call;
- bfd_boolean indirect_call, tls_get_addr;
-
- offset = rel->r_offset;
- switch (r_type)
- {
- case R_386_TLS_GD:
- case R_386_TLS_LDM:
- if (offset < 2 || (rel + 1) >= relend)
- return FALSE;
-
- indirect_call = FALSE;
- call = contents + offset + 4;
- val = *(call - 5);
- type = *(call - 6);
- if (r_type == R_386_TLS_GD)
- {
- /* Check transition from GD access model. Only
- leal foo@tlsgd(,%ebx,1), %eax
- call ___tls_get_addr@PLT
- or
- leal foo@tlsgd(%ebx) %eax
- call ___tls_get_addr@PLT
- nop
- or
- leal foo@tlsgd(%reg), %eax
- call *___tls_get_addr@GOT(%reg)
- which may be converted to
- addr32 call ___tls_get_addr
- can transit to different access model. */
- if ((offset + 10) > sec->size
- || (type != 0x8d && type != 0x04))
- return FALSE;
-
- if (type == 0x04)
- {
- /* leal foo@tlsgd(,%ebx,1), %eax
- call ___tls_get_addr@PLT */
- if (offset < 3)
- return FALSE;
-
- if (*(call - 7) != 0x8d
- || val != 0x1d
- || call[0] != 0xe8)
- return FALSE;
- }
- else
- {
- /* This must be
- leal foo@tlsgd(%ebx), %eax
- call ___tls_get_addr@PLT
- nop
- or
- leal foo@tlsgd(%reg), %eax
- call *___tls_get_addr@GOT(%reg)
- which may be converted to
- addr32 call ___tls_get_addr
-
- %eax can't be used as the GOT base register since it
- is used to pass parameter to ___tls_get_addr. */
- reg = val & 7;
- if ((val & 0xf8) != 0x80 || reg == 4 || reg == 0)
- return FALSE;
-
- indirect_call = call[0] == 0xff;
- if (!(reg == 3 && call[0] == 0xe8 && call[5] == 0x90)
- && !(call[0] == 0x67 && call[1] == 0xe8)
- && !(indirect_call
- && (call[1] & 0xf8) == 0x90
- && (call[1] & 0x7) == reg))
- return FALSE;
- }
- }
- else
- {
- /* Check transition from LD access model. Only
- leal foo@tlsldm(%ebx), %eax
- call ___tls_get_addr@PLT
- or
- leal foo@tlsldm(%reg), %eax
- call *___tls_get_addr@GOT(%reg)
- which may be converted to
- addr32 call ___tls_get_addr
- can transit to different access model. */
- if (type != 0x8d || (offset + 9) > sec->size)
- return FALSE;
-
- /* %eax can't be used as the GOT base register since it is
- used to pass parameter to ___tls_get_addr. */
- reg = val & 7;
- if ((val & 0xf8) != 0x80 || reg == 4 || reg == 0)
- return FALSE;
-
- indirect_call = call[0] == 0xff;
- if (!(reg == 3 && call[0] == 0xe8)
- && !(call[0] == 0x67 && call[1] == 0xe8)
- && !(indirect_call
- && (call[1] & 0xf8) == 0x90
- && (call[1] & 0x7) == reg))
- return FALSE;
- }
-
- r_symndx = ELF32_R_SYM (rel[1].r_info);
- if (r_symndx < symtab_hdr->sh_info)
- return FALSE;
-
- tls_get_addr = FALSE;
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- if (h != NULL && h->root.root.string != NULL)
- {
- struct elf_i386_link_hash_entry *eh
- = (struct elf_i386_link_hash_entry *) h;
- tls_get_addr = eh->tls_get_addr == 1;
- if (eh->tls_get_addr > 1)
- {
- /* Use strncmp to check ___tls_get_addr since
- ___tls_get_addr may be versioned. */
- if (strncmp (h->root.root.string, "___tls_get_addr", 15)
- == 0)
- {
- eh->tls_get_addr = 1;
- tls_get_addr = TRUE;
- }
- else
- eh->tls_get_addr = 0;
- }
- }
-
- if (!tls_get_addr)
- return FALSE;
- else if (indirect_call)
- return (ELF32_R_TYPE (rel[1].r_info) == R_386_GOT32X);
- else
- return (ELF32_R_TYPE (rel[1].r_info) == R_386_PC32
- || ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
-
- case R_386_TLS_IE:
- /* Check transition from IE access model:
- movl foo@indntpoff(%rip), %eax
- movl foo@indntpoff(%rip), %reg
- addl foo@indntpoff(%rip), %reg
- */
-
- if (offset < 1 || (offset + 4) > sec->size)
- return FALSE;
-
- /* Check "movl foo@tpoff(%rip), %eax" first. */
- val = bfd_get_8 (abfd, contents + offset - 1);
- if (val == 0xa1)
- return TRUE;
-
- if (offset < 2)
- return FALSE;
-
- /* Check movl|addl foo@tpoff(%rip), %reg. */
- type = bfd_get_8 (abfd, contents + offset - 2);
- return ((type == 0x8b || type == 0x03)
- && (val & 0xc7) == 0x05);
-
- case R_386_TLS_GOTIE:
- case R_386_TLS_IE_32:
- /* Check transition from {IE_32,GOTIE} access model:
- subl foo@{tpoff,gontoff}(%reg1), %reg2
- movl foo@{tpoff,gontoff}(%reg1), %reg2
- addl foo@{tpoff,gontoff}(%reg1), %reg2
- */
-
- if (offset < 2 || (offset + 4) > sec->size)
- return FALSE;
-
- val = bfd_get_8 (abfd, contents + offset - 1);
- if ((val & 0xc0) != 0x80 || (val & 7) == 4)
- return FALSE;
-
- type = bfd_get_8 (abfd, contents + offset - 2);
- return type == 0x8b || type == 0x2b || type == 0x03;
-
- case R_386_TLS_GOTDESC:
- /* Check transition from GDesc access model:
- leal x@tlsdesc(%ebx), %eax
-
- Make sure it's a leal adding ebx to a 32-bit offset
- into any register, although it's probably almost always
- going to be eax. */
-
- if (offset < 2 || (offset + 4) > sec->size)
- return FALSE;
-
- if (bfd_get_8 (abfd, contents + offset - 2) != 0x8d)
- return FALSE;
-
- val = bfd_get_8 (abfd, contents + offset - 1);
- return (val & 0xc7) == 0x83;
-
- case R_386_TLS_DESC_CALL:
- /* Check transition from GDesc access model:
- call *x@tlsdesc(%eax)
- */
- if (offset + 2 <= sec->size)
- {
- /* Make sure that it's a call *x@tlsdesc(%eax). */
- call = contents + offset;
- return call[0] == 0xff && call[1] == 0x10;
- }
-
- return FALSE;
-
- default:
- abort ();
- }
-}
-
-/* Return TRUE if the TLS access transition is OK or no transition
- will be performed. Update R_TYPE if there is a transition. */
-
-static bfd_boolean
-elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
- asection *sec, bfd_byte *contents,
- Elf_Internal_Shdr *symtab_hdr,
- struct elf_link_hash_entry **sym_hashes,
- unsigned int *r_type, int tls_type,
- const Elf_Internal_Rela *rel,
- const Elf_Internal_Rela *relend,
- struct elf_link_hash_entry *h,
- unsigned long r_symndx,
- bfd_boolean from_relocate_section)
-{
- unsigned int from_type = *r_type;
- unsigned int to_type = from_type;
- bfd_boolean check = TRUE;
-
- /* Skip TLS transition for functions. */
- if (h != NULL
- && (h->type == STT_FUNC
- || h->type == STT_GNU_IFUNC))
- return TRUE;
-
- switch (from_type)
- {
- case R_386_TLS_GD:
- case R_386_TLS_GOTDESC:
- case R_386_TLS_DESC_CALL:
- case R_386_TLS_IE_32:
- case R_386_TLS_IE:
- case R_386_TLS_GOTIE:
- if (bfd_link_executable (info))
- {
- if (h == NULL)
- to_type = R_386_TLS_LE_32;
- else if (from_type != R_386_TLS_IE
- && from_type != R_386_TLS_GOTIE)
- to_type = R_386_TLS_IE_32;
- }
-
- /* When we are called from elf_i386_relocate_section, there may
- be additional transitions based on TLS_TYPE. */
- if (from_relocate_section)
- {
- unsigned int new_to_type = to_type;
-
- if (bfd_link_executable (info)
- && h != NULL
- && h->dynindx == -1
- && (tls_type & GOT_TLS_IE))
- new_to_type = R_386_TLS_LE_32;
-
- if (to_type == R_386_TLS_GD
- || to_type == R_386_TLS_GOTDESC
- || to_type == R_386_TLS_DESC_CALL)
- {
- if (tls_type == GOT_TLS_IE_POS)
- new_to_type = R_386_TLS_GOTIE;
- else if (tls_type & GOT_TLS_IE)
- new_to_type = R_386_TLS_IE_32;
- }
-
- /* We checked the transition before when we were called from
- elf_i386_check_relocs. We only want to check the new
- transition which hasn't been checked before. */
- check = new_to_type != to_type && from_type == to_type;
- to_type = new_to_type;
- }
-
- break;
-
- case R_386_TLS_LDM:
- if (bfd_link_executable (info))
- to_type = R_386_TLS_LE_32;
- break;
-
- default:
- return TRUE;
- }
-
- /* Return TRUE if there is no transition. */
- if (from_type == to_type)
- return TRUE;
-
- /* Check if the transition can be performed. */
- if (check
- && ! elf_i386_check_tls_transition (sec, contents,
- symtab_hdr, sym_hashes,
- from_type, rel, relend))
- {
- reloc_howto_type *from, *to;
- const char *name;
-
- from = elf_i386_rtype_to_howto (abfd, from_type);
- to = elf_i386_rtype_to_howto (abfd, to_type);
-
- if (h)
- name = h->root.root.string;
- else
- {
- struct elf_i386_link_hash_table *htab;
-
- htab = elf_i386_hash_table (info);
- if (htab == NULL)
- name = "*unknown*";
- else
- {
- Elf_Internal_Sym *isym;
-
- isym = bfd_sym_from_r_symndx (&htab->sym_cache,
- abfd, r_symndx);
- name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
- }
- }
-
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%B: TLS transition from %s to %s against `%s' at 0x%lx "
- "in section `%A' failed"),
- abfd, from->name, to->name, name,
- (unsigned long) rel->r_offset, sec);
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
-
- *r_type = to_type;
- return TRUE;
-}
-
-/* With the local symbol, foo, we convert
- mov foo@GOT[(%reg1)], %reg2
- to
- lea foo[@GOTOFF(%reg1)], %reg2
- and convert
- call/jmp *foo@GOT[(%reg)]
- to
- nop call foo/jmp foo nop
- When PIC is false, convert
- test %reg1, foo@GOT[(%reg2)]
- to
- test $foo, %reg1
- and convert
- binop foo@GOT[(%reg1)], %reg2
- to
- binop $foo, %reg2
- where binop is one of adc, add, and, cmp, or, sbb, sub, xor
- instructions. */
-
-static
-bfd_boolean
-elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
- bfd_byte *contents,
- Elf_Internal_Rela *irel,
- struct elf_link_hash_entry *h,
- bfd_boolean *converted,
- struct bfd_link_info *link_info)
-{
- struct elf_i386_link_hash_table *htab;
- unsigned int opcode;
- unsigned int modrm;
- bfd_boolean baseless;
- Elf_Internal_Sym *isym;
- unsigned int addend;
- unsigned int nop;
- bfd_vma nop_offset;
- bfd_boolean is_pic;
- bfd_boolean to_reloc_32;
- unsigned int r_type;
- unsigned int r_symndx;
- bfd_vma roff = irel->r_offset;
-
- if (roff < 2)
- return TRUE;
-
- /* Addend for R_386_GOT32X relocations must be 0. */
- addend = bfd_get_32 (abfd, contents + roff);
- if (addend != 0)
- return TRUE;
-
- htab = elf_i386_hash_table (link_info);
- is_pic = bfd_link_pic (link_info);
-
- r_type = ELF32_R_TYPE (irel->r_info);
- r_symndx = ELF32_R_SYM (irel->r_info);
-
- modrm = bfd_get_8 (abfd, contents + roff - 1);
- baseless = (modrm & 0xc7) == 0x5;
-
- if (baseless && is_pic)
- {
- /* For PIC, disallow R_386_GOT32X without a base register
- since we don't know what the GOT base is. */
- const char *name;
-
- if (h == NULL)
- {
- isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd,
- r_symndx);
- name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
- }
- else
- name = h->root.root.string;
-
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%B: direct GOT relocation R_386_GOT32X against `%s' without base"
- " register can not be used when making a shared object"),
- abfd, name);
- return FALSE;
- }
-
- opcode = bfd_get_8 (abfd, contents + roff - 2);
-
- /* Convert to R_386_32 if PIC is false or there is no base
- register. */
- to_reloc_32 = !is_pic || baseless;
-
- /* Try to convert R_386_GOT32X. Get the symbol referred to by the
- reloc. */
- if (h == NULL)
- {
- if (opcode == 0x0ff)
- /* Convert "call/jmp *foo@GOT[(%reg)]". */
- goto convert_branch;
- else
- /* Convert "mov foo@GOT[(%reg1)], %reg2",
- "test %reg1, foo@GOT(%reg2)" and
- "binop foo@GOT[(%reg1)], %reg2". */
- goto convert_load;
- }
-
- /* Undefined weak symbol is only bound locally in executable
- and its reference is resolved as 0. */
- if (UNDEFINED_WEAK_RESOLVED_TO_ZERO (link_info, TRUE,
- elf_i386_hash_entry (h)))
- {
- if (opcode == 0xff)
- {
- /* No direct branch to 0 for PIC. */
- if (is_pic)
- return TRUE;
- else
- goto convert_branch;
- }
- else
- {
- /* We can convert load of address 0 to R_386_32. */
- to_reloc_32 = TRUE;
- goto convert_load;
- }
- }
-
- if (opcode == 0xff)
- {
- /* We have "call/jmp *foo@GOT[(%reg)]". */
- if ((h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && SYMBOL_REFERENCES_LOCAL (link_info, h))
- {
- /* The function is locally defined. */
-convert_branch:
- /* Convert R_386_GOT32X to R_386_PC32. */
- if (modrm == 0x15 || (modrm & 0xf8) == 0x90)
- {
- struct elf_i386_link_hash_entry *eh
- = (struct elf_i386_link_hash_entry *) h;
-
- /* Convert to "nop call foo". ADDR_PREFIX_OPCODE
- is a nop prefix. */
- modrm = 0xe8;
- /* To support TLS optimization, always use addr32 prefix
- for "call *___tls_get_addr@GOT(%reg)". */
- if (eh && eh->tls_get_addr == 1)
- {
- nop = 0x67;
- nop_offset = irel->r_offset - 2;
- }
- else
- {
- nop = link_info->call_nop_byte;
- if (link_info->call_nop_as_suffix)
- {
- nop_offset = roff + 3;
- irel->r_offset -= 1;
- }
- else
- nop_offset = roff - 2;
- }
- }
- else
- {
- /* Convert to "jmp foo nop". */
- modrm = 0xe9;
- nop = NOP_OPCODE;
- nop_offset = roff + 3;
- irel->r_offset -= 1;
- }
-
- bfd_put_8 (abfd, nop, contents + nop_offset);
- bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1);
- /* When converting to PC-relative relocation, we
- need to adjust addend by -4. */
- bfd_put_32 (abfd, -4, contents + irel->r_offset);
- irel->r_info = ELF32_R_INFO (r_symndx, R_386_PC32);
-
- *converted = TRUE;
- }
- }
- else
- {
- /* We have "mov foo@GOT[(%re1g)], %reg2",
- "test %reg1, foo@GOT(%reg2)" and
- "binop foo@GOT[(%reg1)], %reg2".
-
- Avoid optimizing _DYNAMIC since ld.so may use its
- link-time address. */
- if (h == htab->elf.hdynamic)
- return TRUE;
-
- /* def_regular is set by an assignment in a linker script in
- bfd_elf_record_link_assignment. */
- if ((h->def_regular
- || h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && SYMBOL_REFERENCES_LOCAL (link_info, h))
- {
-convert_load:
- if (opcode == 0x8b)
- {
- if (to_reloc_32)
- {
- /* Convert "mov foo@GOT[(%reg1)], %reg2" to
- "mov $foo, %reg2" with R_386_32. */
- r_type = R_386_32;
- modrm = 0xc0 | (modrm & 0x38) >> 3;
- bfd_put_8 (abfd, modrm, contents + roff - 1);
- opcode = 0xc7;
- }
- else
- {
- /* Convert "mov foo@GOT(%reg1), %reg2" to
- "lea foo@GOTOFF(%reg1), %reg2". */
- r_type = R_386_GOTOFF;
- opcode = 0x8d;
- }
- }
- else
- {
- /* Only R_386_32 is supported. */
- if (!to_reloc_32)
- return TRUE;
-
- if (opcode == 0x85)
- {
- /* Convert "test %reg1, foo@GOT(%reg2)" to
- "test $foo, %reg1". */
- modrm = 0xc0 | (modrm & 0x38) >> 3;
- opcode = 0xf7;
- }
- else
- {
- /* Convert "binop foo@GOT(%reg1), %reg2" to
- "binop $foo, %reg2". */
- modrm = (0xc0
- | (modrm & 0x38) >> 3
- | (opcode & 0x3c));
- opcode = 0x81;
- }
- bfd_put_8 (abfd, modrm, contents + roff - 1);
- r_type = R_386_32;
- }
-
- bfd_put_8 (abfd, opcode, contents + roff - 2);
- irel->r_info = ELF32_R_INFO (r_symndx, r_type);
-
- *converted = TRUE;
- }
- }
-
- return TRUE;
-}
-
-/* Rename some of the generic section flags to better document how they
- are used here. */
-#define need_convert_load sec_flg0
-#define check_relocs_failed sec_flg1
-
-/* Look through the relocs for a section during the first phase, and
- calculate needed space in the global offset table, procedure linkage
- table, and dynamic reloc sections. */
-
-static bfd_boolean
-elf_i386_check_relocs (bfd *abfd,
- struct bfd_link_info *info,
- asection *sec,
- const Elf_Internal_Rela *relocs)
-{
- struct elf_i386_link_hash_table *htab;
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- const Elf_Internal_Rela *rel;
- const Elf_Internal_Rela *rel_end;
- asection *sreloc;
- bfd_byte *contents;
-
- if (bfd_link_relocatable (info))
- return TRUE;
-
- /* Don't do anything special with non-loaded, non-alloced sections.
- In particular, any relocs in such sections should not affect GOT
- and PLT reference counting (ie. we don't allow them to create GOT
- or PLT entries), there's no possibility or desire to optimize TLS
- relocs, and there's not much point in propagating relocs to shared
- libs that the dynamic linker won't relocate. */
- if ((sec->flags & SEC_ALLOC) == 0)
- return TRUE;
-
- BFD_ASSERT (is_i386_elf (abfd));
-
- htab = elf_i386_hash_table (info);
- if (htab == NULL)
- {
- sec->check_relocs_failed = 1;
- return FALSE;
- }
-
- /* Get the section contents. */
- if (elf_section_data (sec)->this_hdr.contents != NULL)
- contents = elf_section_data (sec)->this_hdr.contents;
- else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
- {
- sec->check_relocs_failed = 1;
- return FALSE;
- }
-
- symtab_hdr = &elf_symtab_hdr (abfd);
- sym_hashes = elf_sym_hashes (abfd);
-
- sreloc = NULL;
-
- rel_end = relocs + sec->reloc_count;
- for (rel = relocs; rel < rel_end; rel++)
- {
- unsigned int r_type;
- unsigned long r_symndx;
- struct elf_link_hash_entry *h;
- struct elf_i386_link_hash_entry *eh;
- Elf_Internal_Sym *isym;
- const char *name;
- bfd_boolean size_reloc;
-
- r_symndx = ELF32_R_SYM (rel->r_info);
- r_type = ELF32_R_TYPE (rel->r_info);
-
- if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
- {
- /* xgettext:c-format */
- _bfd_error_handler (_("%B: bad symbol index: %d"),
- abfd, r_symndx);
- goto error_return;
- }
-
- if (r_symndx < symtab_hdr->sh_info)
- {
- /* A local symbol. */
- isym = bfd_sym_from_r_symndx (&htab->sym_cache,
- abfd, r_symndx);
- if (isym == NULL)
- goto error_return;
-
- /* Check relocation against local STT_GNU_IFUNC symbol. */
- if (ELF32_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
- {
- h = elf_i386_get_local_sym_hash (htab, abfd, rel, TRUE);
- if (h == NULL)
- goto error_return;
-
- /* Fake a STT_GNU_IFUNC symbol. */
- h->type = STT_GNU_IFUNC;
- h->def_regular = 1;
- h->ref_regular = 1;
- h->forced_local = 1;
- h->root.type = bfd_link_hash_defined;
- }
- else
- h = NULL;
- }
- else
- {
- isym = NULL;
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
- }
-
- eh = (struct elf_i386_link_hash_entry *) h;
- if (h != NULL)
- {
- switch (r_type)
- {
- default:
- break;
-
- case R_386_GOTOFF:
- eh->gotoff_ref = 1;
- /* Fall through. */
- case R_386_32:
- case R_386_PC32:
- case R_386_PLT32:
- case R_386_GOT32:
- case R_386_GOT32X:
- if (htab->elf.dynobj == NULL)
- htab->elf.dynobj = abfd;
- /* Create the ifunc sections for static executables. */
- if (h->type == STT_GNU_IFUNC
- && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj,
- info))
- goto error_return;
- break;
- }
-
- /* It is referenced by a non-shared object. */
- h->ref_regular = 1;
- h->root.non_ir_ref = 1;
-
- if (h->type == STT_GNU_IFUNC)
- elf_tdata (info->output_bfd)->has_gnu_symbols
- |= elf_gnu_symbol_ifunc;
- }
-
- if (! elf_i386_tls_transition (info, abfd, sec, contents,
- symtab_hdr, sym_hashes,
- &r_type, GOT_UNKNOWN,
- rel, rel_end, h, r_symndx, FALSE))
- goto error_return;
-
- switch (r_type)
- {
- case R_386_TLS_LDM:
- htab->tls_ldm_got.refcount += 1;
- goto create_got;
-
- case R_386_PLT32:
- /* This symbol requires a procedure linkage table entry. We
- actually build the entry in adjust_dynamic_symbol,
- because this might be a case of linking PIC code which is
- never referenced by a dynamic object, in which case we
- don't need to generate a procedure linkage table entry
- after all. */
-
- /* If this is a local symbol, we resolve it directly without
- creating a procedure linkage table entry. */
- if (h == NULL)
- continue;
-
- eh->has_got_reloc = 1;
- h->needs_plt = 1;
- h->plt.refcount += 1;
- break;
-
- case R_386_SIZE32:
- size_reloc = TRUE;
- goto do_size;
-
- case R_386_TLS_IE_32:
- case R_386_TLS_IE:
- case R_386_TLS_GOTIE:
- if (!bfd_link_executable (info))
- info->flags |= DF_STATIC_TLS;
- /* Fall through */
-
- case R_386_GOT32:
- case R_386_GOT32X:
- case R_386_TLS_GD:
- case R_386_TLS_GOTDESC:
- case R_386_TLS_DESC_CALL:
- /* This symbol requires a global offset table entry. */
- {
- int tls_type, old_tls_type;
-
- switch (r_type)
- {
- default:
- case R_386_GOT32:
- case R_386_GOT32X:
- tls_type = GOT_NORMAL;
- break;
- case R_386_TLS_GD: tls_type = GOT_TLS_GD; break;
- case R_386_TLS_GOTDESC:
- case R_386_TLS_DESC_CALL:
- tls_type = GOT_TLS_GDESC; break;
- case R_386_TLS_IE_32:
- if (ELF32_R_TYPE (rel->r_info) == r_type)
- tls_type = GOT_TLS_IE_NEG;
- else
- /* If this is a GD->IE transition, we may use either of
- R_386_TLS_TPOFF and R_386_TLS_TPOFF32. */
- tls_type = GOT_TLS_IE;
- break;
- case R_386_TLS_IE:
- case R_386_TLS_GOTIE:
- tls_type = GOT_TLS_IE_POS; break;
- }
-
- if (h != NULL)
- {
- h->got.refcount += 1;
- old_tls_type = elf_i386_hash_entry(h)->tls_type;
- }
- else
- {
- bfd_signed_vma *local_got_refcounts;
-
- /* This is a global offset table entry for a local symbol. */
- local_got_refcounts = elf_local_got_refcounts (abfd);
- if (local_got_refcounts == NULL)
- {
- bfd_size_type size;
-
- size = symtab_hdr->sh_info;
- size *= (sizeof (bfd_signed_vma)
- + sizeof (bfd_vma) + sizeof(char));
- local_got_refcounts = (bfd_signed_vma *)
- bfd_zalloc (abfd, size);
- if (local_got_refcounts == NULL)
- goto error_return;
- elf_local_got_refcounts (abfd) = local_got_refcounts;
- elf_i386_local_tlsdesc_gotent (abfd)
- = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
- elf_i386_local_got_tls_type (abfd)
- = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info);
- }
- local_got_refcounts[r_symndx] += 1;
- old_tls_type = elf_i386_local_got_tls_type (abfd) [r_symndx];
- }
-
- if ((old_tls_type & GOT_TLS_IE) && (tls_type & GOT_TLS_IE))
- tls_type |= old_tls_type;
- /* If a TLS symbol is accessed using IE at least once,
- there is no point to use dynamic model for it. */
- else if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN
- && (! GOT_TLS_GD_ANY_P (old_tls_type)
- || (tls_type & GOT_TLS_IE) == 0))
- {
- if ((old_tls_type & GOT_TLS_IE) && GOT_TLS_GD_ANY_P (tls_type))
- tls_type = old_tls_type;
- else if (GOT_TLS_GD_ANY_P (old_tls_type)
- && GOT_TLS_GD_ANY_P (tls_type))
- tls_type |= old_tls_type;
- else
- {
- if (h)
- name = h->root.root.string;
- else
- name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
- NULL);
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%B: `%s' accessed both as normal and "
- "thread local symbol"),
- abfd, name);
- bfd_set_error (bfd_error_bad_value);
- goto error_return;
- }
- }
-
- if (old_tls_type != tls_type)
- {
- if (h != NULL)
- elf_i386_hash_entry (h)->tls_type = tls_type;
- else
- elf_i386_local_got_tls_type (abfd) [r_symndx] = tls_type;
- }
- }
- /* Fall through */
-
- case R_386_GOTOFF:
- case R_386_GOTPC:
- create_got:
- if (htab->elf.sgot == NULL)
- {
- if (htab->elf.dynobj == NULL)
- htab->elf.dynobj = abfd;
- if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
- goto error_return;
- }
- if (r_type != R_386_TLS_IE)
- {
- if (eh != NULL)
- eh->has_got_reloc = 1;
- break;
- }
- /* Fall through */
-
- case R_386_TLS_LE_32:
- case R_386_TLS_LE:
- if (eh != NULL)
- eh->has_got_reloc = 1;
- if (bfd_link_executable (info))
- break;
- info->flags |= DF_STATIC_TLS;
- goto do_relocation;
-
- case R_386_32:
- case R_386_PC32:
- if (eh != NULL && (sec->flags & SEC_CODE) != 0)
- eh->has_non_got_reloc = 1;
-do_relocation:
- /* We are called after all symbols have been resolved. Only
- relocation against STT_GNU_IFUNC symbol must go through
- PLT. */
- if (h != NULL
- && (bfd_link_executable (info)
- || h->type == STT_GNU_IFUNC))
- {
- /* If this reloc is in a read-only section, we might
- need a copy reloc. We can't check reliably at this
- stage whether the section is read-only, as input
- sections have not yet been mapped to output sections.
- Tentatively set the flag for now, and correct in
- adjust_dynamic_symbol. */
- h->non_got_ref = 1;
-
- /* We may need a .plt entry if the symbol is a function
- defined in a shared lib or is a STT_GNU_IFUNC function
- referenced from the code or read-only section. */
- if (!h->def_regular
- || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
- h->plt.refcount += 1;
-
- if (r_type == R_386_PC32)
- {
- /* Since something like ".long foo - ." may be used
- as pointer, make sure that PLT is used if foo is
- a function defined in a shared library. */
- if ((sec->flags & SEC_CODE) == 0)
- h->pointer_equality_needed = 1;
- else if (h->type == STT_GNU_IFUNC
- && bfd_link_pic (info))
- {
- if (isym == NULL)
- name = h->root.root.string;
- else
- name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
- NULL);
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%B: unsupported non-PIC call to IFUNC `%s'"),
- abfd, name);
- bfd_set_error (bfd_error_bad_value);
- goto error_return;
- }
- }
- else
- {
- h->pointer_equality_needed = 1;
- /* R_386_32 can be resolved at run-time. */
- if (r_type == R_386_32
- && (sec->flags & SEC_READONLY) == 0)
- eh->func_pointer_refcount += 1;
- }
- }
-
- size_reloc = FALSE;
-do_size:
- /* If we are creating a shared library, and this is a reloc
- against a global symbol, or a non PC relative reloc
- against a local symbol, then we need to copy the reloc
- into the shared library. However, if we are linking with
- -Bsymbolic, we do not need to copy a reloc against a
- global symbol which is defined in an object we are
- including in the link (i.e., DEF_REGULAR is set). At
- this point we have not seen all the input files, so it is
- possible that DEF_REGULAR is not set now but will be set
- later (it is never cleared). In case of a weak definition,
- DEF_REGULAR may be cleared later by a strong definition in
- a shared library. We account for that possibility below by
- storing information in the relocs_copied field of the hash
- table entry. A similar situation occurs when creating
- shared libraries and symbol visibility changes render the
- symbol local.
-
- If on the other hand, we are creating an executable, we
- may need to keep relocations for symbols satisfied by a
- dynamic library if we manage to avoid copy relocs for the
- symbol.
-
- Generate dynamic pointer relocation against STT_GNU_IFUNC
- symbol in the non-code section. */
- if ((bfd_link_pic (info)
- && (r_type != R_386_PC32
- || (h != NULL
- && (! (bfd_link_pie (info)
- || SYMBOLIC_BIND (info, h))
- || h->root.type == bfd_link_hash_defweak
- || !h->def_regular))))
- || (h != NULL
- && h->type == STT_GNU_IFUNC
- && r_type == R_386_32
- && (sec->flags & SEC_CODE) == 0)
- || (ELIMINATE_COPY_RELOCS
- && !bfd_link_pic (info)
- && h != NULL
- && (h->root.type == bfd_link_hash_defweak
- || !h->def_regular)))
- {
- struct elf_dyn_relocs *p;
- struct elf_dyn_relocs **head;
-
- /* We must copy these reloc types into the output file.
- Create a reloc section in dynobj and make room for
- this reloc. */
- if (sreloc == NULL)
- {
- if (htab->elf.dynobj == NULL)
- htab->elf.dynobj = abfd;
-
- sreloc = _bfd_elf_make_dynamic_reloc_section
- (sec, htab->elf.dynobj, 2, abfd, /*rela?*/ FALSE);
-
- if (sreloc == NULL)
- goto error_return;
- }
-
- /* If this is a global symbol, we count the number of
- relocations we need for this symbol. */
- if (h != NULL)
- {
- head = &eh->dyn_relocs;
- }
- else
- {
- /* Track dynamic relocs needed for local syms too.
- We really need local syms available to do this
- easily. Oh well. */
- void **vpp;
- asection *s;
-
- isym = bfd_sym_from_r_symndx (&htab->sym_cache,
- abfd, r_symndx);
- if (isym == NULL)
- goto error_return;
-
- s = bfd_section_from_elf_index (abfd, isym->st_shndx);
- if (s == NULL)
- s = sec;
-
- vpp = &elf_section_data (s)->local_dynrel;
- head = (struct elf_dyn_relocs **)vpp;
- }
-
- p = *head;
- if (p == NULL || p->sec != sec)
- {
- bfd_size_type amt = sizeof *p;
- p = (struct elf_dyn_relocs *) bfd_alloc (htab->elf.dynobj,
- amt);
- if (p == NULL)
- goto error_return;
- p->next = *head;
- *head = p;
- p->sec = sec;
- p->count = 0;
- p->pc_count = 0;
- }
-
- p->count += 1;
- /* Count size relocation as PC-relative relocation. */
- if (r_type == R_386_PC32 || size_reloc)
- p->pc_count += 1;
- }
- break;
-
- /* This relocation describes the C++ object vtable hierarchy.
- Reconstruct it for later use during GC. */
- case R_386_GNU_VTINHERIT:
- if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
- goto error_return;
- break;
-
- /* This relocation describes which C++ vtable entries are actually
- used. Record for later use during GC. */
- case R_386_GNU_VTENTRY:
- BFD_ASSERT (h != NULL);
- if (h != NULL
- && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
- goto error_return;
- break;
-
- default:
- break;
- }
-
- if (r_type == R_386_GOT32X
- && (h == NULL || h->type != STT_GNU_IFUNC))
- sec->need_convert_load = 1;
- }
-
- if (elf_section_data (sec)->this_hdr.contents != contents)
- {
- if (!info->keep_memory)
- free (contents);
- else
- {
- /* Cache the section contents for elf_link_input_bfd. */
- elf_section_data (sec)->this_hdr.contents = contents;
- }
- }
-
- return TRUE;
-
-error_return:
- if (elf_section_data (sec)->this_hdr.contents != contents)
- free (contents);
- sec->check_relocs_failed = 1;
- return FALSE;
-}
-
-/* Return the section that should be marked against GC for a given
- relocation. */
-
-static asection *
-elf_i386_gc_mark_hook (asection *sec,
- struct bfd_link_info *info,
- Elf_Internal_Rela *rel,
- struct elf_link_hash_entry *h,
- Elf_Internal_Sym *sym)
-{
- if (h != NULL)
- switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_386_GNU_VTINHERIT:
- case R_386_GNU_VTENTRY:
- return NULL;
- }
-
- return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
-}
-
-/* Remove undefined weak symbol from the dynamic symbol table if it
- is resolved to 0. */
-
-static bfd_boolean
-elf_i386_fixup_symbol (struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
-{
- if (h->dynindx != -1
- && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info,
- elf_i386_hash_entry (h)->has_got_reloc,
- elf_i386_hash_entry (h)))
- {
- h->dynindx = -1;
- _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
- h->dynstr_index);
- }
- return TRUE;
-}
-
-/* Adjust a symbol defined by a dynamic object and referenced by a
- regular object. The current definition is in some section of the
- dynamic object, but we're not including those sections. We have to
- change the definition to something the rest of the link can
- understand. */
-
-static bfd_boolean
-elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
-{
- struct elf_i386_link_hash_table *htab;
- asection *s, *srel;
- struct elf_i386_link_hash_entry *eh;
- struct elf_dyn_relocs *p;
-
- /* STT_GNU_IFUNC symbol must go through PLT. */
- if (h->type == STT_GNU_IFUNC)
- {
- /* All local STT_GNU_IFUNC references must be treate as local
- calls via local PLT. */
- if (h->ref_regular
- && SYMBOL_CALLS_LOCAL (info, h))
- {
- bfd_size_type pc_count = 0, count = 0;
- struct elf_dyn_relocs **pp;
-
- eh = (struct elf_i386_link_hash_entry *) h;
- for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
- {
- pc_count += p->pc_count;
- p->count -= p->pc_count;
- p->pc_count = 0;
- count += p->count;
- if (p->count == 0)
- *pp = p->next;
- else
- pp = &p->next;
- }
-
- if (pc_count || count)
- {
- h->non_got_ref = 1;
- if (pc_count)
- {
- /* Increment PLT reference count only for PC-relative
- references. */
- h->needs_plt = 1;
- if (h->plt.refcount <= 0)
- h->plt.refcount = 1;
- else
- h->plt.refcount += 1;
- }
- }
- }
-
- if (h->plt.refcount <= 0)
- {
- h->plt.offset = (bfd_vma) -1;
- h->needs_plt = 0;
- }
- return TRUE;