/* Xtensa-specific support for 32-bit ELF.
- Copyright (C) 2003-2019 Free Software Foundation, Inc.
+ Copyright (C) 2003-2021 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#include "xtensa-isa.h"
#include "xtensa-config.h"
+/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */
+#define OCTETS_PER_BYTE(ABFD, SEC) 1
+
#define XTENSA_NO_NOP_REMOVAL 0
+#ifndef XSHAL_ABI
+#define XSHAL_ABI 0
+#endif
+
+#ifndef XTHAL_ABI_UNDEFINED
+#define XTHAL_ABI_UNDEFINED -1
+#endif
+
+#ifndef XTHAL_ABI_WINDOWED
+#define XTHAL_ABI_WINDOWED 0
+#endif
+
+#ifndef XTHAL_ABI_CALL0
+#define XTHAL_ABI_CALL0 1
+#endif
+
/* Local helper functions. */
static bfd_boolean add_extra_plt_sections (struct bfd_link_info *, int);
static bfd_boolean is_operand_relocation (int);
static bfd_size_type insn_decode_len
(bfd_byte *, bfd_size_type, bfd_size_type);
+static int insn_num_slots
+ (bfd_byte *, bfd_size_type, bfd_size_type);
static xtensa_opcode insn_decode_opcode
(bfd_byte *, bfd_size_type, bfd_size_type, int);
static bfd_boolean check_branch_target_aligned
bfd_boolean elf32xtensa_separate_props = FALSE;
+/* Xtensa ABI. It affects PLT entry code. */
+
+int elf32xtensa_abi = XTHAL_ABI_UNDEFINED;
+
/* Rename one of the generic section flags to better document how it
is used here. */
/* Whether relocations have been processed. */
HOWTO (R_XTENSA_TLS_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
bfd_elf_xtensa_reloc, "R_XTENSA_TLS_CALL",
FALSE, 0, 0, FALSE),
+
+ HOWTO (R_XTENSA_PDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
+ bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF8", FALSE, 0, 0xff, FALSE),
+ HOWTO (R_XTENSA_PDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
+ bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF16", FALSE, 0, 0xffff, FALSE),
+ HOWTO (R_XTENSA_PDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+ bfd_elf_xtensa_reloc, "R_XTENSA_PDIFF32", FALSE, 0, 0xffffffff, FALSE),
+
+ HOWTO (R_XTENSA_NDIFF8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
+ bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF8", FALSE, 0, 0xff, FALSE),
+ HOWTO (R_XTENSA_NDIFF16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
+ bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF16", FALSE, 0, 0xffff, FALSE),
+ HOWTO (R_XTENSA_NDIFF32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+ bfd_elf_xtensa_reloc, "R_XTENSA_NDIFF32", FALSE, 0, 0xffffffff, FALSE),
};
#if DEBUG_GEN_RELOC
TRACE ("BFD_RELOC_XTENSA_DIFF32");
return &elf_howto_table[(unsigned) R_XTENSA_DIFF32 ];
+ case BFD_RELOC_XTENSA_PDIFF8:
+ TRACE ("BFD_RELOC_XTENSA_PDIFF8");
+ return &elf_howto_table[(unsigned) R_XTENSA_PDIFF8 ];
+
+ case BFD_RELOC_XTENSA_PDIFF16:
+ TRACE ("BFD_RELOC_XTENSA_PDIFF16");
+ return &elf_howto_table[(unsigned) R_XTENSA_PDIFF16 ];
+
+ case BFD_RELOC_XTENSA_PDIFF32:
+ TRACE ("BFD_RELOC_XTENSA_PDIFF32");
+ return &elf_howto_table[(unsigned) R_XTENSA_PDIFF32 ];
+
+ case BFD_RELOC_XTENSA_NDIFF8:
+ TRACE ("BFD_RELOC_XTENSA_NDIFF8");
+ return &elf_howto_table[(unsigned) R_XTENSA_NDIFF8 ];
+
+ case BFD_RELOC_XTENSA_NDIFF16:
+ TRACE ("BFD_RELOC_XTENSA_NDIFF16");
+ return &elf_howto_table[(unsigned) R_XTENSA_NDIFF16 ];
+
+ case BFD_RELOC_XTENSA_NDIFF32:
+ TRACE ("BFD_RELOC_XTENSA_NDIFF32");
+ return &elf_howto_table[(unsigned) R_XTENSA_NDIFF32 ];
+
case BFD_RELOC_XTENSA_RTLD:
TRACE ("BFD_RELOC_XTENSA_RTLD");
return &elf_howto_table[(unsigned) R_XTENSA_RTLD ];
/* Get the Xtensa ELF linker hash table from a link_info structure. */
#define elf_xtensa_hash_table(p) \
- (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
- == XTENSA_ELF_DATA ? ((struct elf_xtensa_link_hash_table *) ((p)->hash)) : NULL)
+ ((is_elf_hash_table ((p)->hash) \
+ && elf_hash_table_id (elf_hash_table (p)) == XTENSA_ELF_DATA) \
+ ? (struct elf_xtensa_link_hash_table *) (p)->hash : NULL)
/* Create an entry in an Xtensa ELF linker hash table. */
{
struct elf_link_hash_entry *tlsbase;
struct elf_xtensa_link_hash_table *ret;
- bfd_size_type amt = sizeof (struct elf_xtensa_link_hash_table);
+ size_t amt = sizeof (struct elf_xtensa_link_hash_table);
ret = bfd_zmalloc (amt);
if (ret == NULL)
tlsbase->root.type = bfd_link_hash_new;
tlsbase->root.u.undef.abfd = NULL;
tlsbase->non_elf = 0;
+ ret->elf.dt_pltgot_required = TRUE;
ret->tlsbase = elf_xtensa_hash_entry (tlsbase);
ret->tlsbase->tls_type = GOT_UNKNOWN;
const Elf_Internal_Rela *rel;
const Elf_Internal_Rela *rel_end;
- if (bfd_link_relocatable (info) || (sec->flags & SEC_ALLOC) == 0)
+ if (bfd_link_relocatable (info))
return TRUE;
BFD_ASSERT (is_xtensa_elf (abfd));
/* Mark the ".got.plt" section READONLY. */
if (htab->elf.sgotplt == NULL
- || ! bfd_set_section_flags (dynobj, htab->elf.sgotplt, flags))
+ || !bfd_set_section_flags (htab->elf.sgotplt, flags))
return FALSE;
/* Create ".got.loc" (literal tables for use by dynamic linker). */
htab->sgotloc = bfd_make_section_anyway_with_flags (dynobj, ".got.loc",
flags);
if (htab->sgotloc == NULL
- || ! bfd_set_section_alignment (dynobj, htab->sgotloc, 2))
+ || !bfd_set_section_alignment (htab->sgotloc, 2))
return FALSE;
/* Create ".xt.lit.plt" (literal table for ".got.plt*"). */
htab->spltlittbl = bfd_make_section_anyway_with_flags (dynobj, ".xt.lit.plt",
noalloc_flags);
if (htab->spltlittbl == NULL
- || ! bfd_set_section_alignment (dynobj, htab->spltlittbl, 2))
+ || !bfd_set_section_alignment (htab->spltlittbl, 2))
return FALSE;
return TRUE;
sprintf (sname, ".plt.%u", chunk);
s = bfd_make_section_anyway_with_flags (dynobj, sname, flags | SEC_CODE);
if (s == NULL
- || ! bfd_set_section_alignment (dynobj, s, 2))
+ || !bfd_set_section_alignment (s, 2))
return FALSE;
sname = (char *) bfd_malloc (14);
sprintf (sname, ".got.plt.%u", chunk);
s = bfd_make_section_anyway_with_flags (dynobj, sname, flags);
if (s == NULL
- || ! bfd_set_section_alignment (dynobj, s, 2))
+ || !bfd_set_section_alignment (s, 2))
return FALSE;
}
/* It's OK to base decisions on the section name, because none
of the dynobj section names depend upon the input files. */
- name = bfd_get_section_name (dynobj, s);
+ name = bfd_section_name (s);
if (CONST_STRNEQ (name, ".rela"))
{
#define add_dynamic_entry(TAG, VAL) \
_bfd_elf_add_dynamic_entry (info, TAG, VAL)
- if (bfd_link_executable (info))
- {
- if (!add_dynamic_entry (DT_DEBUG, 0))
- return FALSE;
- }
-
- if (relplt)
- {
- if (!add_dynamic_entry (DT_PLTRELSZ, 0)
- || !add_dynamic_entry (DT_PLTREL, DT_RELA)
- || !add_dynamic_entry (DT_JMPREL, 0))
- return FALSE;
- }
-
- if (relgot)
- {
- if (!add_dynamic_entry (DT_RELA, 0)
- || !add_dynamic_entry (DT_RELASZ, 0)
- || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
- return FALSE;
- }
+ if (!_bfd_elf_add_dynamic_tags (output_bfd, info,
+ relplt || relgot))
+ return FALSE;
- if (!add_dynamic_entry (DT_PLTGOT, 0)
- || !add_dynamic_entry (DT_XTENSA_GOT_LOC_OFF, 0)
+ if (!add_dynamic_entry (DT_XTENSA_GOT_LOC_OFF, 0)
|| !add_dynamic_entry (DT_XTENSA_GOT_LOC_SZ, 0))
return FALSE;
}
case R_XTENSA_DIFF8:
case R_XTENSA_DIFF16:
case R_XTENSA_DIFF32:
+ case R_XTENSA_PDIFF8:
+ case R_XTENSA_PDIFF16:
+ case R_XTENSA_PDIFF32:
+ case R_XTENSA_NDIFF8:
+ case R_XTENSA_NDIFF16:
+ case R_XTENSA_NDIFF32:
case R_XTENSA_TLS_FUNC:
case R_XTENSA_TLS_ARG:
case R_XTENSA_TLS_CALL:
{
bfd_vma relocation;
bfd_reloc_status_type flag;
- bfd_size_type octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+ bfd_size_type octets = (reloc_entry->address
+ * OCTETS_PER_BYTE (abfd, input_section));
bfd_vma output_base = 0;
reloc_howto_type *howto = reloc_entry->howto;
asection *reloc_target_output_section;
return flag;
}
+int xtensa_abi_choice (void)
+{
+ if (elf32xtensa_abi == XTHAL_ABI_UNDEFINED)
+ return XSHAL_ABI;
+ else
+ return elf32xtensa_abi;
+}
/* Set up an entry in the procedure linkage table. */
bfd_vma plt_base, got_base;
bfd_vma code_offset, lit_offset, abi_offset;
int chunk;
+ int abi = xtensa_abi_choice ();
chunk = reloc_index / PLT_ENTRIES_PER_CHUNK;
splt = elf_xtensa_get_plt_section (info, chunk);
/* Fill in the entry in the procedure linkage table. */
memcpy (splt->contents + code_offset,
(bfd_big_endian (output_bfd)
- ? elf_xtensa_be_plt_entry[XSHAL_ABI != XTHAL_ABI_WINDOWED]
- : elf_xtensa_le_plt_entry[XSHAL_ABI != XTHAL_ABI_WINDOWED]),
+ ? elf_xtensa_be_plt_entry[abi != XTHAL_ABI_WINDOWED]
+ : elf_xtensa_le_plt_entry[abi != XTHAL_ABI_WINDOWED]),
PLT_ENTRY_SIZE);
- abi_offset = XSHAL_ABI == XTHAL_ABI_WINDOWED ? 3 : 0;
+ abi_offset = abi == XTHAL_ABI_WINDOWED ? 3 : 0;
bfd_put_16 (output_bfd, l32r_offset (got_base + 0,
plt_base + code_offset + abi_offset),
splt->contents + code_offset + abi_offset + 1);
name = (bfd_elf_string_from_elf_section
(input_bfd, symtab_hdr->sh_link, sym->st_name));
if (name == NULL || *name == '\0')
- name = bfd_section_name (input_bfd, sec);
+ name = bfd_section_name (sec);
}
if (r_symndx != STN_UNDEF
}
}
- if (lit_table)
- free (lit_table);
-
+ free (lit_table);
input_section->reloc_done = TRUE;
return TRUE;
int n, m, num;
section_size = sxtlit->size;
+ if (section_size == 0)
+ return 0;
+
BFD_ASSERT (section_size % 8 == 0);
num = section_size / 8;
if (!bfd_malloc_and_get_section (output_bfd, sxtlit, &contents))
{
- if (contents != 0)
- free (contents);
+ free (contents);
free (table);
return -1;
}
}
+static xtensa_opcode
+get_rsr_lend_opcode (void)
+{
+ static xtensa_opcode rsr_lend_opcode = XTENSA_UNDEFINED;
+ static bfd_boolean done_lookup = FALSE;
+ if (!done_lookup)
+ {
+ rsr_lend_opcode = xtensa_opcode_lookup (xtensa_default_isa, "rsr.lend");
+ done_lookup = TRUE;
+ }
+ return rsr_lend_opcode;
+}
+
+static xtensa_opcode
+get_wsr_lbeg_opcode (void)
+{
+ static xtensa_opcode wsr_lbeg_opcode = XTENSA_UNDEFINED;
+ static bfd_boolean done_lookup = FALSE;
+ if (!done_lookup)
+ {
+ wsr_lbeg_opcode = xtensa_opcode_lookup (xtensa_default_isa, "wsr.lbeg");
+ done_lookup = TRUE;
+ }
+ return wsr_lbeg_opcode;
+}
+
+
static int
get_relocation_opnd (xtensa_opcode opcode, int r_type)
{
return insn_len;
}
+int
+insn_num_slots (bfd_byte *contents,
+ bfd_size_type content_len,
+ bfd_size_type offset)
+{
+ xtensa_isa isa = xtensa_default_isa;
+ xtensa_format fmt;
+ static xtensa_insnbuf ibuff = NULL;
+
+ if (offset + MIN_INSN_LENGTH > content_len)
+ return XTENSA_UNDEFINED;
+
+ if (ibuff == NULL)
+ ibuff = xtensa_insnbuf_alloc (isa);
+ xtensa_insnbuf_from_chars (isa, ibuff, &contents[offset],
+ content_len - offset);
+ fmt = xtensa_format_decode (isa, ibuff);
+ if (fmt == XTENSA_UNDEFINED)
+ return XTENSA_UNDEFINED;
+ return xtensa_format_num_slots (isa, fmt);
+}
+
/* Decode the opcode for a single slot instruction.
Return 0 if it fails to decode or the instruction is multi-slot. */
return FALSE;
}
+ /* If this is relaxed loop, analyze first instruction of the actual loop
+ body. It must be at offset 27 from the loop instruction address. */
+ if (insn_len == 3
+ && insn_num_slots (contents, content_length, offset + loop_len) == 1
+ && insn_decode_opcode (contents, content_length,
+ offset + loop_len, 0) == get_rsr_lend_opcode()
+ && insn_decode_len (contents, content_length, offset + loop_len + 3) == 3
+ && insn_num_slots (contents, content_length, offset + loop_len + 3) == 1
+ && insn_decode_opcode (contents, content_length,
+ offset + loop_len + 3, 0) == get_wsr_lbeg_opcode())
+ {
+ loop_len = 27;
+ insn_len = insn_decode_len (contents, content_length, offset + loop_len);
+ }
return check_branch_target_aligned_address (address + loop_len, insn_len);
}
const char *narrow;
};
-struct string_pair narrowable[] =
+const struct string_pair narrowable[] =
{
{ "add", "add.n" },
{ "addi", "addi.n" },
{ "or", "mov.n" } /* special case only when op1 == op2 */
};
-struct string_pair widenable[] =
+const struct string_pair widenable[] =
{
{ "add", "add.n" },
{ "addi", "addi.n" },
static int
removed_literal_compare (const void *a, const void *b)
{
- const removed_literal_map_entry *pa = a;
- const removed_literal_map_entry *pb = b;
+ const bfd_vma *key = a;
+ const removed_literal_map_entry *memb = b;
- if (pa->addr == pb->addr)
+ if (*key == memb->addr)
return 0;
else
- return pa->addr < pb->addr ? -1 : 1;
+ return *key < memb->addr ? -1 : 1;
}
/* Check if the list of removed literals contains an entry for the
if (removed_list->map == NULL)
map_removed_literal (removed_list);
- p = bsearch (&addr, removed_list->map, removed_list->n_map,
- sizeof (*removed_list->map), removed_literal_compare);
- if (p)
+ if (removed_list->map != NULL)
{
- while (p != removed_list->map && (p - 1)->addr == addr)
- --p;
- r = p->literal;
+ p = bsearch (&addr, removed_list->map, removed_list->n_map,
+ sizeof (*removed_list->map), removed_literal_compare);
+ if (p)
+ {
+ while (p != removed_list->map && (p - 1)->addr == addr)
+ --p;
+ r = p->literal;
+ }
}
return r;
}
if (!sec->used_by_bfd)
{
struct elf_xtensa_section_data *sdata;
- bfd_size_type amt = sizeof (*sdata);
+ size_t amt = sizeof (*sdata);
sdata = bfd_zalloc (abfd, amt);
if (sdata == NULL)
{
release_contents (sec_cache->sec, sec_cache->contents);
release_internal_relocs (sec_cache->sec, sec_cache->relocs);
- if (sec_cache->ptbl)
- free (sec_cache->ptbl);
+ free (sec_cache->ptbl);
}
}
err:
release_contents (sec, contents);
release_internal_relocs (sec, internal_relocs);
- if (prop_table)
- free (prop_table);
+ free (prop_table);
return FALSE;
}
static void
free_ebb_constraint (ebb_constraint *c)
{
- if (c->actions)
- free (c->actions);
+ free (c->actions);
}
for (i = 0; i < c->action_count; i++)
new_actions[i] = c->actions[i];
- if (c->actions)
- free (c->actions);
+ free (c->actions);
c->actions = new_actions;
c->action_allocated = new_allocated;
}
static void
release_internal_relocs (asection *sec, Elf_Internal_Rela *internal_relocs)
{
- if (internal_relocs
- && elf_section_data (sec)->relocs != internal_relocs)
+ if (elf_section_data (sec)->relocs != internal_relocs)
free (internal_relocs);
}
{
if (!bfd_malloc_and_get_section (abfd, sec, &contents))
{
- if (contents)
- free (contents);
+ free (contents);
return NULL;
}
if (keep_memory)
static void
release_contents (asection *sec, bfd_byte *contents)
{
- if (contents && elf_section_data (sec)->this_hdr.contents != contents)
+ if (elf_section_data (sec)->this_hdr.contents != contents)
free (contents);
}
print_action_list (stderr, &relax_info->action_list);
#endif
-error_return:
+ error_return:
release_contents (sec, contents);
release_internal_relocs (sec, internal_relocs);
- if (prop_table)
- free (prop_table);
- if (reloc_opcodes)
- free (reloc_opcodes);
+ free (prop_table);
+ free (reloc_opcodes);
return ok;
}
static void
free_xlate_map (xlate_map_t *map)
{
- if (map && map->entry)
- free (map->entry);
if (map)
- free (map);
+ {
+ free (map->entry);
+ free (map);
+ }
}
}
}
- if (xmap)
- free_xlate_map (xmap);
+ free_xlate_map (xmap);
return ok;
}
print_action_list (stderr, &relax_info->action_list);
#endif /* DEBUG */
-error_return:
- if (prop_table)
- free (prop_table);
+ error_return:
+ free (prop_table);
free_section_cache (&target_sec_cache);
release_contents (sec, contents);
if (r_type == R_XTENSA_DIFF8
|| r_type == R_XTENSA_DIFF16
- || r_type == R_XTENSA_DIFF32)
+ || r_type == R_XTENSA_DIFF32
+ || r_type == R_XTENSA_PDIFF8
+ || r_type == R_XTENSA_PDIFF16
+ || r_type == R_XTENSA_PDIFF32
+ || r_type == R_XTENSA_NDIFF8
+ || r_type == R_XTENSA_NDIFF16
+ || r_type == R_XTENSA_NDIFF32)
{
bfd_signed_vma diff_value = 0;
bfd_vma new_end_offset, diff_mask = 0;
switch (r_type)
{
case R_XTENSA_DIFF8:
+ diff_mask = 0x7f;
diff_value =
bfd_get_signed_8 (abfd, &contents[old_source_offset]);
break;
case R_XTENSA_DIFF16:
+ diff_mask = 0x7fff;
diff_value =
bfd_get_signed_16 (abfd, &contents[old_source_offset]);
break;
case R_XTENSA_DIFF32:
+ diff_mask = 0x7fffffff;
diff_value =
bfd_get_signed_32 (abfd, &contents[old_source_offset]);
break;
+ case R_XTENSA_PDIFF8:
+ case R_XTENSA_NDIFF8:
+ diff_mask = 0xff;
+ diff_value =
+ bfd_get_8 (abfd, &contents[old_source_offset]);
+ break;
+ case R_XTENSA_PDIFF16:
+ case R_XTENSA_NDIFF16:
+ diff_mask = 0xffff;
+ diff_value =
+ bfd_get_16 (abfd, &contents[old_source_offset]);
+ break;
+ case R_XTENSA_PDIFF32:
+ case R_XTENSA_NDIFF32:
+ diff_mask = 0xffffffff;
+ diff_value =
+ bfd_get_32 (abfd, &contents[old_source_offset]);
+ break;
}
+ if (r_type >= R_XTENSA_NDIFF8
+ && r_type <= R_XTENSA_NDIFF32
+ && diff_value)
+ diff_value |= ~diff_mask;
+
new_end_offset = offset_with_removed_text_map
(&target_relax_info->action_list,
r_rel.target_offset + diff_value);
switch (r_type)
{
case R_XTENSA_DIFF8:
- diff_mask = 0x7f;
bfd_put_signed_8 (abfd, diff_value,
&contents[old_source_offset]);
break;
case R_XTENSA_DIFF16:
- diff_mask = 0x7fff;
bfd_put_signed_16 (abfd, diff_value,
&contents[old_source_offset]);
break;
case R_XTENSA_DIFF32:
- diff_mask = 0x7fffffff;
bfd_put_signed_32 (abfd, diff_value,
&contents[old_source_offset]);
break;
+ case R_XTENSA_PDIFF8:
+ case R_XTENSA_NDIFF8:
+ bfd_put_8 (abfd, diff_value,
+ &contents[old_source_offset]);
+ break;
+ case R_XTENSA_PDIFF16:
+ case R_XTENSA_NDIFF16:
+ bfd_put_16 (abfd, diff_value,
+ &contents[old_source_offset]);
+ break;
+ case R_XTENSA_PDIFF32:
+ case R_XTENSA_NDIFF32:
+ bfd_put_32 (abfd, diff_value,
+ &contents[old_source_offset]);
+ break;
}
- /* Check for overflow. Sign bits must be all zeroes or all ones */
- if ((diff_value & ~diff_mask) != 0 &&
- (diff_value & ~diff_mask) != (-1 & ~diff_mask))
+ /* Check for overflow. Sign bits must be all zeroes or
+ all ones. When sign bits are all ones diff_value
+ may not be zero. */
+ if (((diff_value & ~diff_mask) != 0
+ && (diff_value & ~diff_mask) != ~diff_mask)
+ || (diff_value && (bfd_vma) diff_value == ~diff_mask))
{
(*link_info->callbacks->reloc_dangerous)
(link_info, _("overflow after relaxation"),
if ((r_type == R_XTENSA_32 || r_type == R_XTENSA_PLT)
&& (input_section->flags & SEC_ALLOC) != 0
- && (dynamic_symbol || bfd_link_pic (info))
- && (!h || h->root.type != bfd_link_hash_undefweak
- || (dynamic_symbol
- && (bfd_link_dll (info) || info->export_dynamic))))
+ && (dynamic_symbol
+ || (bfd_link_pic (info)
+ && (!h || h->root.type != bfd_link_hash_undefweak))))
{
asection *srel;
bfd_boolean is_plt = FALSE;
if (! prop_sec)
{
flagword flags = (SEC_RELOC | SEC_HAS_CONTENTS | SEC_READONLY);
- flags |= (bfd_get_section_flags (sec->owner, sec)
+ flags |= (bfd_section_flags (sec)
& (SEC_LINK_ONCE | SEC_LINK_DUPLICATES));
prop_sec = bfd_make_section_anyway_with_flags