aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/Makefile.in4
-rw-r--r--bfd/archures.c1
-rw-r--r--bfd/bfd-in2.h8
-rw-r--r--bfd/bfd.c3
-rw-r--r--bfd/coffgen.c22
-rw-r--r--bfd/doc/chew.c62
-rw-r--r--bfd/doc/local.mk4
-rw-r--r--bfd/ecoff.c8
-rw-r--r--bfd/elf-bfd.h2
-rw-r--r--bfd/elf-eh-frame.c2
-rw-r--r--bfd/elf.c170
-rw-r--r--bfd/elf32-arm.c104
-rw-r--r--bfd/elf32-i386.c56
-rw-r--r--bfd/elf32-v850.c7
-rw-r--r--bfd/elf64-x86-64.c149
-rw-r--r--bfd/elflink.c52
-rw-r--r--bfd/elfnn-loongarch.c548
-rw-r--r--bfd/elfnn-riscv.c2
-rw-r--r--bfd/elfxx-riscv.c46
-rw-r--r--bfd/elfxx-target.h11
-rw-r--r--bfd/elfxx-x86.c133
-rw-r--r--bfd/elfxx-x86.h7
-rw-r--r--bfd/libbfd-in.h42
-rw-r--r--bfd/libbfd.c47
-rw-r--r--bfd/libbfd.h42
-rw-r--r--bfd/merge.c177
-rw-r--r--bfd/pdb.c57
-rw-r--r--bfd/peXXigen.c4
-rw-r--r--bfd/pef.c8
-rw-r--r--bfd/peicode.h162
-rw-r--r--bfd/plugin.c28
-rw-r--r--bfd/syms.c12
-rw-r--r--bfd/tekhex.c81
-rw-r--r--bfd/version.h2
-rw-r--r--bfd/vms-alpha.c46
35 files changed, 1300 insertions, 809 deletions
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index b3d97d4..38364f4 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -1322,7 +1322,7 @@ REGEN_TEXI = \
$(MKDOC) -f $(srcdir)/doc/doc.str < $< > $@.tmp; \
texi=$@; \
texi=$${texi%.stamp}.texi; \
- test -e $$texi || test ! -f $(srcdir)/$$texi || $(LN_S) $(srcdir)/$$texi .; \
+ test -e $$texi || test ! -f $(srcdir)/$$texi || $(LN_S) $(srcdir)/$$texi $$texi; \
$(SHELL) $(srcdir)/../move-if-change $@.tmp $$texi; \
touch $@; \
)
@@ -2497,7 +2497,7 @@ coff-tic54x.lo: coff-tic54x.c
$(MKDOC): doc/chew.stamp ; @true
doc/chew.stamp: $(srcdir)/doc/chew.c doc/$(am__dirstamp)
$(AM_V_CCLD)$(CC_FOR_BUILD) -o doc/chw$$$$$(EXEEXT_FOR_BUILD) $(CFLAGS_FOR_BUILD) \
- $(CPPFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) \
+ $(WARN_CFLAGS_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) \
-I. -I$(srcdir) -Idoc -I$(srcdir)/../include -I$(srcdir)/../intl -I../intl \
$(srcdir)/doc/chew.c && \
$(SHELL) $(srcdir)/../move-if-change \
diff --git a/bfd/archures.c b/bfd/archures.c
index 94118b8..c4decc5 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -947,6 +947,7 @@ bfd_arch_get_compatible (const bfd *abfd,
to assume that they know what they are doing. */
if (accept_unknowns
|| ubfd->plugin_format == bfd_plugin_yes
+ || ubfd->plugin_format == bfd_plugin_yes_unused
|| strcmp (bfd_get_target (ubfd), "binary") == 0)
return kbfd->arch_info;
return NULL;
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index e3b5a8b..3b047d9 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1260,6 +1260,11 @@ typedef struct _symbol_info
const char *stab_name; /* String for stab type. */
} symbol_info;
+/* An empty string that will not match the address of any other
+ symbol name, even unnamed local symbols which will also have empty
+ string names. This can be used to flag a symbol as corrupt if its
+ name uses an out of range string table index. */
+extern const char bfd_symbol_error_name[];
#define bfd_get_symtab_upper_bound(abfd) \
BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd))
@@ -1947,7 +1952,8 @@ enum bfd_plugin_format
{
bfd_plugin_unknown = 0,
bfd_plugin_yes = 1,
- bfd_plugin_no = 2
+ bfd_plugin_yes_unused = 2,
+ bfd_plugin_no = 3
};
struct bfd_build_id
diff --git a/bfd/bfd.c b/bfd/bfd.c
index ae79c64..a93be10 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -65,7 +65,8 @@ EXTERNAL
. {
. bfd_plugin_unknown = 0,
. bfd_plugin_yes = 1,
-. bfd_plugin_no = 2
+. bfd_plugin_yes_unused = 2,
+. bfd_plugin_no = 3
. };
.
.struct bfd_build_id
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index cc1c655..5754dbb 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -1928,7 +1928,7 @@ coff_get_normalized_symtab (bfd *abfd)
if ((bfd_size_type) aux->u.auxent.x_file.x_n.x_n.x_offset
>= obj_coff_strings_len (abfd))
sym->u.syment._n._n_n._n_offset =
- (uintptr_t) _("<corrupt>");
+ (uintptr_t) bfd_symbol_error_name;
else
sym->u.syment._n._n_n._n_offset =
(uintptr_t) (string_table
@@ -1978,7 +1978,7 @@ coff_get_normalized_symtab (bfd *abfd)
if ((bfd_size_type) aux->u.auxent.x_file.x_n.x_n.x_offset
>= obj_coff_strings_len (abfd))
aux->u.auxent.x_file.x_n.x_n.x_offset =
- (uintptr_t) _("<corrupt>");
+ (uintptr_t) bfd_symbol_error_name;
else
aux->u.auxent.x_file.x_n.x_n.x_offset =
(uintptr_t) (string_table
@@ -2028,7 +2028,7 @@ coff_get_normalized_symtab (bfd *abfd)
}
if (sym->u.syment._n._n_n._n_offset >= obj_coff_strings_len (abfd))
sym->u.syment._n._n_n._n_offset =
- (uintptr_t) _("<corrupt>");
+ (uintptr_t) bfd_symbol_error_name;
else
sym->u.syment._n._n_n._n_offset =
(uintptr_t) (string_table
@@ -2047,7 +2047,7 @@ coff_get_normalized_symtab (bfd *abfd)
the debug data. */
if (sym->u.syment._n._n_n._n_offset >= debug_sec->size)
sym->u.syment._n._n_n._n_offset =
- (uintptr_t) _("<corrupt>");
+ (uintptr_t) bfd_symbol_error_name;
else
sym->u.syment._n._n_n._n_offset =
(uintptr_t) (debug_sec_data
@@ -2161,11 +2161,13 @@ coff_print_symbol (bfd *abfd,
bfd_print_symbol_type how)
{
FILE * file = (FILE *) filep;
+ const char *symname = (symbol->name != bfd_symbol_error_name
+ ? symbol->name : _("<corrupt>"));
switch (how)
{
case bfd_print_symbol_name:
- fprintf (file, "%s", symbol->name);
+ fprintf (file, "%s", symname);
break;
case bfd_print_symbol_more:
@@ -2189,7 +2191,7 @@ coff_print_symbol (bfd *abfd,
if (combined < obj_raw_syments (abfd)
|| combined >= obj_raw_syments (abfd) + obj_raw_syment_count (abfd))
{
- fprintf (file, _("<corrupt info> %s"), symbol->name);
+ fprintf (file, _("<corrupt info> %s"), symname);
break;
}
@@ -2207,7 +2209,7 @@ coff_print_symbol (bfd *abfd,
combined->u.syment.n_sclass,
combined->u.syment.n_numaux);
bfd_fprintf_vma (abfd, file, val);
- fprintf (file, " %s", symbol->name);
+ fprintf (file, " %s", symname);
for (aux = 0; aux < combined->u.syment.n_numaux; aux++)
{
@@ -2297,7 +2299,9 @@ coff_print_symbol (bfd *abfd,
if (l)
{
- fprintf (file, "\n%s :", l->u.sym->name);
+ fprintf (file, "\n%s :",
+ l->u.sym->name != bfd_symbol_error_name
+ ? l->u.sym->name : _("<corrupt>"));
l++;
while (l->line_number)
{
@@ -2317,7 +2321,7 @@ coff_print_symbol (bfd *abfd,
symbol->section->name,
coffsymbol (symbol)->native ? "n" : "g",
coffsymbol (symbol)->lineno ? "l" : " ",
- symbol->name);
+ symname);
}
}
}
diff --git a/bfd/doc/chew.c b/bfd/doc/chew.c
index 842d415..469bd80 100644
--- a/bfd/doc/chew.c
+++ b/bfd/doc/chew.c
@@ -132,8 +132,8 @@ int warning;
string_type stack[STACK];
string_type *tos;
-unsigned int idx = 0; /* Pos in input buffer */
-string_type *ptr; /* and the buffer */
+unsigned int pos_idx = 0; /* Pos in input buffer */
+string_type *buf_ptr; /* and the buffer */
intptr_t istack[STACK];
intptr_t *isp = &istack[0];
@@ -149,7 +149,7 @@ die (char *msg)
exit (1);
}
-void *
+static void *
xmalloc (size_t size)
{
void *newmem;
@@ -163,7 +163,7 @@ xmalloc (size_t size)
return newmem;
}
-void *
+static void *
xrealloc (void *oldmem, size_t size)
{
void *newmem;
@@ -180,7 +180,7 @@ xrealloc (void *oldmem, size_t size)
return newmem;
}
-char *
+static char *
xstrdup (const char *s)
{
size_t len = strlen (s) + 1;
@@ -202,22 +202,6 @@ init_string (string_type *buffer)
init_string_with_size (buffer, DEF_SIZE);
}
-static int
-find (string_type *str, char *what)
-{
- unsigned int i;
- char *p;
- p = what;
- for (i = 0; i < str->write_idx && *p; i++)
- {
- if (*p == str->ptr[i])
- p++;
- else
- p = what;
- }
- return (*p == 0);
-}
-
static void
write_buffer (string_type *buffer, FILE *f)
{
@@ -853,7 +837,7 @@ icopy_past_newline (void)
tos++;
check_range ();
init_string (tos);
- idx = copy_past_newline (ptr, idx, tos);
+ pos_idx = copy_past_newline (buf_ptr, pos_idx, tos);
pc++;
}
@@ -1046,11 +1030,11 @@ get_stuff_in_command (void)
check_range ();
init_string (tos);
- while (at (ptr, idx))
+ while (at (buf_ptr, pos_idx))
{
- if (iscommand (ptr, idx))
+ if (iscommand (buf_ptr, pos_idx))
break;
- idx = copy_past_newline (ptr, idx, tos);
+ pos_idx = copy_past_newline (buf_ptr, pos_idx, tos);
}
pc++;
}
@@ -1089,7 +1073,7 @@ icatstr (void)
static void
skip_past_newline (void)
{
- idx = skip_past_newline_1 (ptr, idx);
+ pos_idx = skip_past_newline_1 (buf_ptr, pos_idx);
pc++;
}
@@ -1120,7 +1104,7 @@ catstrif (void)
pc++;
}
-char *
+static char *
nextword (char *string, char **word)
{
char *word_start;
@@ -1208,7 +1192,7 @@ nextword (char *string, char **word)
return NULL;
}
-dict_type *
+static dict_type *
lookup_word (char *word)
{
dict_type *ptr = root;
@@ -1261,15 +1245,15 @@ perform (void)
{
tos = stack;
- while (at (ptr, idx))
+ while (at (buf_ptr, pos_idx))
{
/* It's worth looking through the command list. */
- if (iscommand (ptr, idx))
+ if (iscommand (buf_ptr, pos_idx))
{
char *next;
dict_type *word;
- (void) nextword (addr (ptr, idx), &next);
+ (void) nextword (addr (buf_ptr, pos_idx), &next);
word = lookup_word (next);
@@ -1281,16 +1265,16 @@ perform (void)
{
if (warning)
fprintf (stderr, "warning, %s is not recognised\n", next);
- idx = skip_past_newline_1 (ptr, idx);
+ pos_idx = skip_past_newline_1 (buf_ptr, pos_idx);
}
free (next);
}
else
- idx = skip_past_newline_1 (ptr, idx);
+ pos_idx = skip_past_newline_1 (buf_ptr, pos_idx);
}
}
-dict_type *
+static dict_type *
newentry (char *word)
{
dict_type *new_d = xmalloc (sizeof (*new_d));
@@ -1303,7 +1287,7 @@ newentry (char *word)
return new_d;
}
-unsigned int
+static unsigned int
add_to_definition (dict_type *entry, pcu word)
{
if (entry->code_end == entry->code_length)
@@ -1317,7 +1301,7 @@ add_to_definition (dict_type *entry, pcu word)
return entry->code_end++;
}
-void
+static void
add_intrinsic (char *name, void (*func) (void))
{
dict_type *new_d = newentry (xstrdup (name));
@@ -1345,7 +1329,7 @@ add_intrinsic_variable (const char *name, intptr_t *loc)
add_variable (xstrdup (name), loc);
}
-void
+static void
compile (char *string)
{
/* Add words to the dictionary. */
@@ -1539,7 +1523,7 @@ main (int ac, char *av[])
init_string (&pptr);
init_string (stack + 0);
tos = stack + 1;
- ptr = &pptr;
+ buf_ptr = &pptr;
add_intrinsic ("push_text", push_text);
add_intrinsic ("!", bang);
@@ -1583,7 +1567,7 @@ main (int ac, char *av[])
catchar (&buffer, '\n');
read_in (&buffer, stdin);
- remove_noncomments (&buffer, ptr);
+ remove_noncomments (&buffer, buf_ptr);
for (i = 1; i < (unsigned int) ac; i++)
{
if (av[i][0] == '-')
diff --git a/bfd/doc/local.mk b/bfd/doc/local.mk
index 5e8f486..346dba3 100644
--- a/bfd/doc/local.mk
+++ b/bfd/doc/local.mk
@@ -80,7 +80,7 @@ MKDOC = %D%/chew$(EXEEXT_FOR_BUILD)
$(MKDOC): %D%/chew.stamp ; @true
%D%/chew.stamp: $(srcdir)/%D%/chew.c %D%/$(am__dirstamp)
$(AM_V_CCLD)$(CC_FOR_BUILD) -o %D%/chw$$$$$(EXEEXT_FOR_BUILD) $(CFLAGS_FOR_BUILD) \
- $(CPPFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) \
+ $(WARN_CFLAGS_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) \
-I. -I$(srcdir) -I%D% -I$(srcdir)/../include -I$(srcdir)/../intl -I../intl \
$(srcdir)/%D%/chew.c && \
$(SHELL) $(srcdir)/../move-if-change \
@@ -101,7 +101,7 @@ REGEN_TEXI = \
$(MKDOC) -f $(srcdir)/%D%/doc.str < $< > $@.tmp; \
texi=$@; \
texi=$${texi%.stamp}.texi; \
- test -e $$texi || test ! -f $(srcdir)/$$texi || $(LN_S) $(srcdir)/$$texi .; \
+ test -e $$texi || test ! -f $(srcdir)/$$texi || $(LN_S) $(srcdir)/$$texi $$texi; \
$(SHELL) $(srcdir)/../move-if-change $@.tmp $$texi; \
touch $@; \
)
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index 0450176..d0cb9e1 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -1452,11 +1452,13 @@ _bfd_ecoff_print_symbol (bfd *abfd,
const struct ecoff_debug_swap * const debug_swap
= &ecoff_backend (abfd)->debug_swap;
FILE *file = (FILE *)filep;
+ const char *symname = (symbol->name != bfd_symbol_error_name
+ ? symbol->name : _("<corrupt>"));
switch (how)
{
case bfd_print_symbol_name:
- fprintf (file, "%s", symbol->name);
+ fprintf (file, "%s", symname);
break;
case bfd_print_symbol_more:
if (ecoffsymbol (symbol)->local)
@@ -1526,7 +1528,7 @@ _bfd_ecoff_print_symbol (bfd *abfd,
(unsigned) ecoff_ext.asym.sc,
(unsigned) ecoff_ext.asym.index,
jmptbl, cobol_main, weakext,
- symbol->name);
+ symname);
if (ecoffsymbol (symbol)->fdr != NULL
&& ecoff_ext.asym.index != indexNil)
@@ -3278,8 +3280,8 @@ ecoff_link_hash_newfunc (struct bfd_hash_entry *entry,
ret->abfd = NULL;
ret->written = 0;
ret->small = 0;
+ memset ((void *) &ret->esym, 0, sizeof ret->esym);
}
- memset ((void *) &ret->esym, 0, sizeof ret->esym);
return (struct bfd_hash_entry *) ret;
}
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index b89d3dd..96cf119 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -2540,7 +2540,7 @@ extern long _bfd_elf_link_lookup_local_dynindx
extern bool _bfd_elf_compute_section_file_positions
(bfd *, struct bfd_link_info *);
extern file_ptr _bfd_elf_assign_file_position_for_section
- (Elf_Internal_Shdr *, file_ptr, bool);
+ (Elf_Internal_Shdr *, file_ptr, bool, unsigned char);
extern bool _bfd_elf_modify_headers
(bfd *, struct bfd_link_info *);
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index 902d7c1..ebe162f 100644
--- a/bfd/elf-eh-frame.c
+++ b/bfd/elf-eh-frame.c
@@ -345,7 +345,7 @@ next_cie_fde_offset (const struct eh_cie_fde *ent,
static bool
skip_cfa_op (bfd_byte **iter, bfd_byte *end, unsigned int encoded_ptr_width)
{
- bfd_byte op;
+ bfd_byte op = 0;
bfd_vma length;
if (!read_byte (iter, end, &op))
diff --git a/bfd/elf.c b/bfd/elf.c
index bc4a2de..1a8618a 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -285,26 +285,22 @@ bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
offset = i_shdrp[shindex]->sh_offset;
shstrtabsize = i_shdrp[shindex]->sh_size;
- /* Allocate and clear an extra byte at the end, to prevent crashes
- in case the string table is not terminated. */
- if (shstrtabsize + 1 <= 1
+ if (shstrtabsize == 0
|| bfd_seek (abfd, offset, SEEK_SET) != 0
- || (shstrtab
- = _bfd_mmap_readonly_persistent (abfd, shstrtabsize)) == NULL)
+ || (shstrtab = _bfd_mmap_persistent (abfd, shstrtabsize)) == NULL)
{
/* Once we've failed to read it, make sure we don't keep
trying. Otherwise, we'll keep allocating space for
the string table over and over. */
i_shdrp[shindex]->sh_size = 0;
}
- else if (shstrtab[shstrtabsize - 1] != '\0')
+ else if (shstrtab[shstrtabsize - 1] != 0)
{
/* It is an error if a string table isn't terminated. */
_bfd_error_handler
/* xgettext:c-format */
- (_("%pB(%pA): string table is corrupt"),
- abfd, i_shdrp[shindex]->bfd_section);
- return NULL;
+ (_("%pB: string table [%u] is corrupt"), abfd, shindex);
+ shstrtab[shstrtabsize - 1] = 0;
}
i_shdrp[shindex]->contents = shstrtab;
}
@@ -524,21 +520,19 @@ bfd_elf_get_elf_syms (bfd *ibfd,
}
out1:
- _bfd_munmap_readonly_temporary (alloc_extshndx, alloc_extshndx_size);
+ _bfd_munmap_temporary (alloc_extshndx, alloc_extshndx_size);
out2:
- _bfd_munmap_readonly_temporary (alloc_ext, alloc_ext_size);
+ _bfd_munmap_temporary (alloc_ext, alloc_ext_size);
return intsym_buf;
}
/* Look up a symbol name. */
-const char *
-bfd_elf_sym_name (bfd *abfd,
- Elf_Internal_Shdr *symtab_hdr,
- Elf_Internal_Sym *isym,
- asection *sym_sec)
+static const char *
+bfd_elf_sym_name_raw (bfd *abfd,
+ Elf_Internal_Shdr *symtab_hdr,
+ Elf_Internal_Sym *isym)
{
- const char *name;
unsigned int iname = isym->st_name;
unsigned int shindex = symtab_hdr->sh_link;
@@ -550,9 +544,18 @@ bfd_elf_sym_name (bfd *abfd,
shindex = elf_elfheader (abfd)->e_shstrndx;
}
- name = bfd_elf_string_from_elf_section (abfd, shindex, iname);
+ return bfd_elf_string_from_elf_section (abfd, shindex, iname);
+}
+
+const char *
+bfd_elf_sym_name (bfd *abfd,
+ Elf_Internal_Shdr *symtab_hdr,
+ Elf_Internal_Sym *isym,
+ asection *sym_sec)
+{
+ const char *name = bfd_elf_sym_name_raw (abfd, symtab_hdr, isym);
if (name == NULL)
- name = "(null)";
+ name = bfd_symbol_error_name;
else if (sym_sec && *name == '\0')
name = bfd_section_name (sym_sec);
@@ -585,7 +588,7 @@ group_signature (bfd *abfd, Elf_Internal_Shdr *ghdr)
&isym, esym, &eshndx) == NULL)
return NULL;
- return bfd_elf_sym_name (abfd, hdr, &isym, NULL);
+ return bfd_elf_sym_name_raw (abfd, hdr, &isym);
}
static bool
@@ -1736,8 +1739,7 @@ get_hash_table_data (bfd *abfd, bfd_size_type number,
return NULL;
}
- e_data = _bfd_mmap_readonly_temporary (abfd, size, &e_data_addr,
- &e_data_size);
+ e_data = _bfd_mmap_temporary (abfd, size, &e_data_addr, &e_data_size);
if (e_data == NULL)
return NULL;
@@ -1755,7 +1757,7 @@ get_hash_table_data (bfd *abfd, bfd_size_type number,
while (number--)
i_data[number] = bfd_get_64 (abfd, e_data + number * ent_size);
- _bfd_munmap_readonly_temporary (e_data_addr, e_data_size);
+ _bfd_munmap_temporary (e_data_addr, e_data_size);
return i_data;
}
@@ -1826,8 +1828,7 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
goto error_return;
dynbuf_size = phdr->p_filesz;
- dynbuf = _bfd_mmap_readonly_temporary (abfd, dynbuf_size,
- &dynbuf_addr, &dynbuf_size);
+ dynbuf = _bfd_mmap_temporary (abfd, dynbuf_size, &dynbuf_addr, &dynbuf_size);
if (dynbuf == NULL)
goto error_return;
@@ -1905,7 +1906,7 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
goto error_return;
/* Dynamic string table must be valid until ABFD is closed. */
- strbuf = (char *) _bfd_mmap_readonly_persistent (abfd, dt_strsz);
+ strbuf = (char *) _bfd_mmap_persistent (abfd, dt_strsz);
if (strbuf == NULL)
goto error_return;
if (strbuf[dt_strsz - 1] != 0)
@@ -1914,7 +1915,7 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
_bfd_error_handler
/* xgettext:c-format */
(_("%pB: DT_STRTAB table is corrupt"), abfd);
- goto error_return;
+ strbuf[dt_strsz - 1] = 0;
}
/* Get the real symbol count from DT_HASH or DT_GNU_HASH. Prefer
@@ -2091,9 +2092,8 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
|| bfd_seek (abfd, filepos, SEEK_SET) != 0)
goto error_return;
esymbuf_size = amt;
- esymbuf = _bfd_mmap_readonly_temporary (abfd, esymbuf_size,
- &esymbuf_addr,
- &esymbuf_size);
+ esymbuf = _bfd_mmap_temporary (abfd, esymbuf_size,
+ &esymbuf_addr, &esymbuf_size);
if (esymbuf == NULL)
goto error_return;
@@ -2137,7 +2137,7 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
goto error_return;
/* DT_VERSYM info must be valid until ABFD is closed. */
- versym = _bfd_mmap_readonly_persistent (abfd, amt);
+ versym = _bfd_mmap_persistent (abfd, amt);
if (dt_verdef)
{
@@ -2149,7 +2149,7 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
goto error_return;
/* DT_VERDEF info must be valid until ABFD is closed. */
- verdef = _bfd_mmap_readonly_persistent (abfd, verdef_size);
+ verdef = _bfd_mmap_persistent (abfd, verdef_size);
}
if (dt_verneed)
@@ -2162,7 +2162,7 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
goto error_return;
/* DT_VERNEED info must be valid until ABFD is closed. */
- verneed = _bfd_mmap_readonly_persistent (abfd, verneed_size);
+ verneed = _bfd_mmap_persistent (abfd, verneed_size);
}
}
@@ -2185,8 +2185,8 @@ _bfd_elf_get_dynamic_symbols (bfd *abfd, Elf_Internal_Phdr *phdr,
/* Restore file position for elf_object_p. */
if (bfd_seek (abfd, saved_filepos, SEEK_SET) != 0)
res = false;
- _bfd_munmap_readonly_temporary (dynbuf_addr, dynbuf_size);
- _bfd_munmap_readonly_temporary (esymbuf_addr, esymbuf_size);
+ _bfd_munmap_temporary (dynbuf_addr, dynbuf_size);
+ _bfd_munmap_temporary (esymbuf_addr, esymbuf_size);
free (gnubuckets);
free (gnuchains);
free (mipsxlat);
@@ -2316,10 +2316,13 @@ bfd_elf_print_symbol (bfd *abfd,
bfd_print_symbol_type how)
{
FILE *file = (FILE *) filep;
+ const char *symname = (symbol->name != bfd_symbol_error_name
+ ? symbol->name : _("<corrupt>"));
+
switch (how)
{
case bfd_print_symbol_name:
- fprintf (file, "%s", symbol->name);
+ fprintf (file, "%s", symname);
break;
case bfd_print_symbol_more:
fprintf (file, "elf ");
@@ -2342,11 +2345,10 @@ bfd_elf_print_symbol (bfd *abfd,
if (bed->elf_backend_print_symbol_all)
name = (*bed->elf_backend_print_symbol_all) (abfd, filep, symbol);
- if (name == NULL)
- {
- name = symbol->name;
- bfd_print_symbol_vandf (abfd, file, symbol);
- }
+ if (name != NULL)
+ symname = name;
+ else
+ bfd_print_symbol_vandf (abfd, file, symbol);
fprintf (file, " %s\t", section_name);
/* Print the "other" value for a symbol. For common symbols,
@@ -2393,7 +2395,7 @@ bfd_elf_print_symbol (bfd *abfd,
fprintf (file, " 0x%02x", (unsigned int) st_other);
}
- fprintf (file, " %s", name);
+ fprintf (file, " %s", symname);
}
break;
}
@@ -4550,25 +4552,29 @@ elf_map_symbols (bfd *abfd, unsigned int *pnum_locals)
return true;
}
-/* Align to the maximum file alignment that could be required for any
- ELF data structure. */
-
-static inline file_ptr
-align_file_position (file_ptr off, int align)
-{
- return (off + align - 1) & ~(align - 1);
-}
-
/* Assign a file position to a section, optionally aligning to the
required section alignment. */
file_ptr
_bfd_elf_assign_file_position_for_section (Elf_Internal_Shdr *i_shdrp,
file_ptr offset,
- bool align)
+ bool align,
+ unsigned char log_file_align)
{
- if (align && i_shdrp->sh_addralign > 1)
- offset = BFD_ALIGN (offset, i_shdrp->sh_addralign & -i_shdrp->sh_addralign);
+ if (i_shdrp->sh_addralign > 1)
+ {
+ file_ptr salign = i_shdrp->sh_addralign & -i_shdrp->sh_addralign;
+
+ if (align)
+ offset = BFD_ALIGN (offset, salign);
+ else if (log_file_align)
+ {
+ /* Heuristic: Cap alignment at log_file_align. */
+ file_ptr falign = 1u << log_file_align;
+
+ offset = BFD_ALIGN (offset, salign < falign ? salign : falign);
+ }
+ }
i_shdrp->sh_offset = offset;
if (i_shdrp->bfd_section != NULL)
i_shdrp->bfd_section->filepos = offset;
@@ -4656,18 +4662,18 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
off = elf_next_file_pos (abfd);
hdr = & elf_symtab_hdr (abfd);
- off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, true, 0);
if (elf_symtab_shndx_list (abfd) != NULL)
{
hdr = & elf_symtab_shndx_list (abfd)->hdr;
if (hdr->sh_size != 0)
- off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, true, 0);
/* FIXME: What about other symtab_shndx sections in the list ? */
}
hdr = &elf_tdata (abfd)->strtab_hdr;
- off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, true, 0);
elf_next_file_pos (abfd) = off;
@@ -6541,8 +6547,8 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
else
align = hdr->sh_addralign & -hdr->sh_addralign;
off += vma_page_aligned_bias (hdr->sh_addr, off, align);
- off = _bfd_elf_assign_file_position_for_section (hdr, off,
- false);
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, false,
+ bed->s->log_file_align);
}
else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
&& hdr->bfd_section == NULL)
@@ -6559,7 +6565,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
|| hdr == i_shdrpp[elf_shstrtab_sec (abfd)])
hdr->sh_offset = -1;
else
- off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, true, 0);
}
elf_next_file_pos (abfd) = off;
@@ -6796,7 +6802,8 @@ assign_file_positions_except_relocs (bfd *abfd,
hdr->sh_offset = -1;
}
else
- off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, false,
+ 0);
}
elf_next_file_pos (abfd) = off;
@@ -7011,7 +7018,7 @@ _bfd_elf_assign_file_positions_for_non_load (bfd *abfd)
Elf_Internal_Shdr **shdrpp, **end_shdrpp;
Elf_Internal_Shdr *shdrp;
Elf_Internal_Ehdr *i_ehdrp;
- const struct elf_backend_data *bed;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
/* Skip non-load sections without section header. */
if ((abfd->flags & BFD_NO_SECTION_HEADER) != 0)
@@ -7079,7 +7086,10 @@ _bfd_elf_assign_file_positions_for_non_load (bfd *abfd)
sec->contents = NULL;
}
- off = _bfd_elf_assign_file_position_for_section (shdrp, off, true);
+ off = _bfd_elf_assign_file_position_for_section (shdrp, off,
+ (abfd->flags & (EXEC_P | DYNAMIC))
+ || bfd_get_format (abfd) == bfd_core,
+ bed->s->log_file_align);
}
}
@@ -7088,12 +7098,11 @@ _bfd_elf_assign_file_positions_for_non_load (bfd *abfd)
_bfd_elf_strtab_finalize (elf_shstrtab (abfd));
shdrp = &elf_tdata (abfd)->shstrtab_hdr;
shdrp->sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
- off = _bfd_elf_assign_file_position_for_section (shdrp, off, true);
+ off = _bfd_elf_assign_file_position_for_section (shdrp, off, true, 0);
/* Place the section headers. */
i_ehdrp = elf_elfheader (abfd);
- bed = get_elf_backend_data (abfd);
- off = align_file_position (off, 1 << bed->s->log_file_align);
+ off = BFD_ALIGN (off, 1u << bed->s->log_file_align);
i_ehdrp->e_shoff = off;
off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
elf_next_file_pos (abfd) = off;
@@ -8732,17 +8741,16 @@ swap_out_syms (bfd *abfd,
&& (flags & (BSF_SECTION_SYM | BSF_GLOBAL)) == BSF_SECTION_SYM)
{
/* Local section symbols have no name. */
- sym.st_name = (unsigned long) -1;
+ sym.st_name = 0;
}
else
{
/* Call _bfd_elf_strtab_offset after _bfd_elf_strtab_finalize
to get the final offset for st_name. */
- sym.st_name
- = (unsigned long) _bfd_elf_strtab_add (stt, syms[idx]->name,
- false);
- if (sym.st_name == (unsigned long) -1)
+ size_t stridx = _bfd_elf_strtab_add (stt, syms[idx]->name, false);
+ if (stridx == (size_t) -1)
goto error_return;
+ sym.st_name = stridx;
}
bfd_vma value = syms[idx]->value;
@@ -8953,9 +8961,7 @@ Unable to handle section index %x in ELF symbol. Using ABS instead."),
for (idx = 0; idx < outbound_syms_index; idx++)
{
struct elf_sym_strtab *elfsym = &symstrtab[idx];
- if (elfsym->sym.st_name == (unsigned long) -1)
- elfsym->sym.st_name = 0;
- else
+ if (elfsym->sym.st_name != 0)
elfsym->sym.st_name = _bfd_elf_strtab_offset (stt,
elfsym->sym.st_name);
if (info && info->callbacks->ctf_new_symbol)
@@ -9294,9 +9300,8 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
goto error_return_verref;
contents_size = hdr->sh_size;
- contents = _bfd_mmap_readonly_temporary (abfd, contents_size,
- &contents_addr,
- &contents_size);
+ contents = _bfd_mmap_temporary (abfd, contents_size,
+ &contents_addr, &contents_size);
if (contents == NULL)
goto error_return_verref;
@@ -9429,7 +9434,7 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
elf_tdata (abfd)->cverrefs = i;
if (contents != elf_tdata (abfd)->dt_verneed)
- _bfd_munmap_readonly_temporary (contents_addr, contents_size);
+ _bfd_munmap_temporary (contents_addr, contents_size);
contents = NULL;
contents_addr = NULL;
}
@@ -9473,9 +9478,8 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0)
goto error_return_verdef;
contents_size = hdr->sh_size;
- contents = _bfd_mmap_readonly_temporary (abfd, contents_size,
- &contents_addr,
- &contents_size);
+ contents = _bfd_mmap_temporary (abfd, contents_size,
+ &contents_addr, &contents_size);
if (contents == NULL)
goto error_return_verdef;
@@ -9629,7 +9633,7 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
}
if (contents != elf_tdata (abfd)->dt_verdef)
- _bfd_munmap_readonly_temporary (contents_addr, contents_size);
+ _bfd_munmap_temporary (contents_addr, contents_size);
contents = NULL;
contents_addr = NULL;
}
@@ -9687,7 +9691,7 @@ _bfd_elf_slurp_version_tables (bfd *abfd, bool default_imported_symver)
error_return:
if (contents != elf_tdata (abfd)->dt_verneed
&& contents != elf_tdata (abfd)->dt_verdef)
- _bfd_munmap_readonly_temporary (contents_addr, contents_size);
+ _bfd_munmap_temporary (contents_addr, contents_size);
return false;
}
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index ca76bee..17df8b3 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -4226,12 +4226,33 @@ arm_type_of_stub (struct bfd_link_info *info,
r_type = ELF32_R_TYPE (rel->r_info);
+ /* Don't pretend we know what stub to use (if any) when we target a
+ Thumb-only target and we don't know the actual destination
+ type. */
+ if (branch_type == ST_BRANCH_UNKNOWN && thumb_only)
+ return stub_type;
+
/* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we
are considering a function call relocation. */
if (thumb_only && (r_type == R_ARM_THM_CALL || r_type == R_ARM_THM_JUMP24
|| r_type == R_ARM_THM_JUMP19)
&& branch_type == ST_BRANCH_TO_ARM)
- branch_type = ST_BRANCH_TO_THUMB;
+ {
+ if (sym_sec == bfd_abs_section_ptr)
+ /* As an exception, assume that absolute symbols are of the
+ right kind (Thumb). They are presumably defined in the
+ linker script, where it is not possible to declare them as
+ Thumb (and thus are seen as Arm mode). We'll inform the
+ user with a warning, though, in
+ elf32_arm_final_link_relocate. */
+ branch_type = ST_BRANCH_TO_THUMB;
+ else
+ /* Otherwise do not silently build a stub, and let the users
+ know they have to fix their code. Indeed, we could decide
+ to insert a stub involving Arm code and/or BLX, leading to
+ a run-time crash. */
+ return stub_type;
+ }
/* For TLS call relocs, it is the caller's responsibility to provide
the address of the appropriate trampoline. */
@@ -10382,14 +10403,6 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
else
addend = signed_addend = rel->r_addend;
- /* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we
- are resolving a function call relocation. */
- if (using_thumb_only (globals)
- && (r_type == R_ARM_THM_CALL
- || r_type == R_ARM_THM_JUMP24)
- && branch_type == ST_BRANCH_TO_ARM)
- branch_type = ST_BRANCH_TO_THUMB;
-
/* Record the symbol information that should be used in dynamic
relocations. */
dynreloc_st_type = st_type;
@@ -10452,6 +10465,73 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
gotplt_offset = (bfd_vma) -1;
}
+ /* ST_BRANCH_TO_ARM is nonsense to thumb-only targets when we are
+ resolving a function call relocation. We want to inform the user
+ that something is wrong. */
+ if (using_thumb_only (globals)
+ && (r_type == R_ARM_THM_CALL
+ || r_type == R_ARM_THM_JUMP24)
+ && branch_type == ST_BRANCH_TO_ARM
+ /* Calls through a PLT are special: the assembly source code
+ cannot be annotated with '.type foo(PLT), %function', and
+ they handled specifically below anyway. */
+ && splt == NULL)
+ {
+ if (sym_sec == bfd_abs_section_ptr)
+ {
+ /* As an exception, assume that absolute symbols are of the
+ right kind (Thumb). They are presumably defined in the
+ linker script, where it is not possible to declare them as
+ Thumb (and thus are seen as Arm mode). Inform the user with
+ a warning, though. */
+ branch_type = ST_BRANCH_TO_THUMB;
+
+ if (sym_sec->owner)
+ _bfd_error_handler
+ (_("warning: %pB(%s): Forcing bramch to absolute symbol in Thumb mode (Thumb-only CPU)"
+ " in %pB"),
+ sym_sec->owner, sym_name, input_bfd);
+ else
+ _bfd_error_handler
+ (_("warning: (%s): Forcing branch to absolute symbol in Thumb mode (Thumb-only CPU)"
+ " in %pB"),
+ sym_name, input_bfd);
+ }
+ else
+ /* Otherwise do not silently build a stub, and let the users
+ know they have to fix their code. Indeed, we could decide
+ to insert a stub involving Arm code and/or BLX, leading to
+ a run-time crash. */
+ branch_type = ST_BRANCH_UNKNOWN;
+ }
+
+ /* Fail early if branch_type is ST_BRANCH_UNKNOWN and we target a
+ Thumb-only CPU. We could emit a warning on Arm-capable targets
+ too, but that would be too verbose (a lot of legacy code does not
+ use the .type foo, %function directive). */
+ if (using_thumb_only (globals)
+ && (r_type == R_ARM_THM_CALL
+ || r_type == R_ARM_THM_JUMP24)
+ && branch_type == ST_BRANCH_UNKNOWN
+ /* Exception to the rule above: a branch to an undefined weak
+ symbol is turned into a jump to the next instruction unless a
+ PLT entry will be created (see below). */
+ && !(h && h->root.type == bfd_link_hash_undefweak
+ && plt_offset == (bfd_vma) -1))
+ {
+ if (sym_sec != NULL
+ && sym_sec->owner != NULL)
+ _bfd_error_handler
+ (_("%pB(%s): Unknown destination type (ARM/Thumb) in %pB"),
+ sym_sec->owner, sym_name, input_bfd);
+ else
+ _bfd_error_handler
+ (_("(%s): Unknown destination type (ARM/Thumb) in %pB"),
+ sym_name, input_bfd);
+
+ return bfd_reloc_notsupported;
+ }
+
resolved_to_zero = (h != NULL
&& UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
@@ -17838,7 +17918,7 @@ elf32_arm_output_map_sym (output_arch_syminfo *osi,
sym.st_other = 0;
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE);
sym.st_shndx = osi->sec_shndx;
- sym.st_target_internal = 0;
+ sym.st_target_internal = ST_BRANCH_TO_ARM;
elf32_arm_section_map_add (osi->sec, names[type][1], offset);
return osi->func (osi->flaginfo, names[type], &sym, osi->sec, NULL) == 1;
}
@@ -17995,7 +18075,7 @@ elf32_arm_output_stub_sym (output_arch_syminfo *osi, const char *name,
sym.st_other = 0;
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FUNC);
sym.st_shndx = osi->sec_shndx;
- sym.st_target_internal = 0;
+ sym.st_target_internal = ST_BRANCH_TO_ARM;
return osi->func (osi->flaginfo, name, &sym, osi->sec, NULL) == 1;
}
@@ -19743,7 +19823,7 @@ elf32_arm_swap_symbol_in (bfd * abfd,
{
if (!bfd_elf32_swap_symbol_in (abfd, psrc, pshn, dst))
return false;
- dst->st_target_internal = 0;
+ dst->st_target_internal = ST_BRANCH_TO_ARM;
/* New EABI objects mark thumb function symbols by setting the low bit of
the address. */
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 7d573e7..2e8d595 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -975,15 +975,15 @@ elf_i386_check_tls_transition (asection *sec,
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
+ movl foo@indntpoff, %eax
+ movl foo@indntpoff, %reg
+ addl foo@indntpoff, %reg
*/
if (offset < 1 || (offset + 4) > sec->size)
return elf_x86_tls_error_yes;
- /* Check "movl foo@tpoff(%rip), %eax" first. */
+ /* Check "movl foo@indntpoff, %eax" first. */
val = bfd_get_8 (abfd, contents + offset - 1);
if (val == 0xa1)
return elf_x86_tls_error_none;
@@ -991,7 +991,7 @@ elf_i386_check_tls_transition (asection *sec,
if (offset < 2)
return elf_x86_tls_error_yes;
- /* Check movl|addl foo@tpoff(%rip), %reg. */
+ /* Check movl|addl foo@indntpoff, %reg. */
type = bfd_get_8 (abfd, contents + offset - 2);
if (type != 0x8b && type != 0x03)
return elf_x86_tls_error_add_mov;
@@ -1039,19 +1039,8 @@ elf_i386_check_tls_transition (asection *sec,
: elf_x86_tls_error_yes);
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
- ? elf_x86_tls_error_none
- : elf_x86_tls_error_indirect_call);
- }
-
- return elf_x86_tls_error_yes;
+ /* It has been checked in elf_i386_tls_transition. */
+ return elf_x86_tls_error_none;
default:
abort ();
@@ -1077,6 +1066,8 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
unsigned int to_type = from_type;
bool check = true;
unsigned int to_le_type, to_ie_type;
+ bfd_vma offset;
+ bfd_byte *call;
/* Skip TLS transition for functions. */
if (h != NULL
@@ -1098,9 +1089,34 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
switch (from_type)
{
+ case R_386_TLS_DESC_CALL:
+ /* Check valid GDesc call:
+ call *x@tlscall(%eax)
+ */
+ offset = rel->r_offset;
+ call = NULL;
+ if (offset + 2 <= sec->size)
+ {
+ /* Make sure that it's a call *x@tlscall(%eax). */
+ call = contents + offset;
+ if (call[0] != 0xff || call[1] != 0x10)
+ call = NULL;
+ }
+
+ if (call == NULL)
+ {
+ _bfd_x86_elf_link_report_tls_transition_error
+ (info, abfd, sec, symtab_hdr, h, sym, rel,
+ "R_386_TLS_DESC_CALL", NULL,
+ elf_x86_tls_error_indirect_call);
+
+ return false;
+ }
+
+ /* Fall through. */
+
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:
@@ -1707,7 +1723,7 @@ elf_i386_scan_relocs (bfd *abfd,
name = h->root.root.string;
else
name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
- NULL);
+ NULL);
_bfd_error_handler
/* xgettext:c-format */
(_("%pB: `%s' accessed both as normal and "
diff --git a/bfd/elf32-v850.c b/bfd/elf32-v850.c
index 85cbcbc..bb3ce8d 100644
--- a/bfd/elf32-v850.c
+++ b/bfd/elf32-v850.c
@@ -1933,8 +1933,11 @@ v850_elf_info_to_howto_rela (bfd *abfd,
static bool
v850_elf_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, const char *name)
{
- return ( (name[0] == '.' && (name[1] == 'L' || name[1] == '.'))
- || (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_'));
+ if (name[0] == '.' && (name[1] == 'L' || name[1] == '.'))
+ return true;
+ if (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')
+ return true;
+ return false;
}
static bool
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 83399ea..a62fa62 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -906,6 +906,14 @@ static const sframe_frame_row_entry elf_x86_64_sframe_pltn_fre2 =
SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */
};
+/* .sframe FRE covering the .plt section entry for IBT. */
+static const sframe_frame_row_entry elf_x86_64_sframe_ibt_pltn_fre2 =
+{
+ 9, /* SFrame FRE start address. */
+ {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes. */
+ SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */
+};
+
/* .sframe FRE covering the second .plt section entry. */
static const sframe_frame_row_entry elf_x86_64_sframe_sec_pltn_fre1 =
{
@@ -914,7 +922,7 @@ static const sframe_frame_row_entry elf_x86_64_sframe_sec_pltn_fre1 =
SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info. */
};
-/* SFrame helper object for non-lazy PLT. Also used for IBT enabled PLT. */
+/* SFrame helper object for non-lazy PLT. */
static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_plt =
{
LAZY_PLT_ENTRY_SIZE,
@@ -927,10 +935,34 @@ static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_plt =
{ &elf_x86_64_sframe_sec_pltn_fre1, &elf_x86_64_sframe_null_fre },
0,
0, /* There is no second PLT necessary. */
- { &elf_x86_64_sframe_null_fre }
+ { &elf_x86_64_sframe_null_fre },
+ NON_LAZY_PLT_ENTRY_SIZE,
+ 1, /* Number of FREs for PLT GOT. */
+ /* Array of SFrame FREs for PLT GOT. */
+ { &elf_x86_64_sframe_null_fre },
+};
+
+/* SFrame helper object for non-lazy IBT enabled PLT. */
+static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_ibt_plt =
+{
+ LAZY_PLT_ENTRY_SIZE,
+ 2, /* Number of FREs for PLT0. */
+ /* Array of SFrame FREs for plt0. */
+ { &elf_x86_64_sframe_plt0_fre1, &elf_x86_64_sframe_plt0_fre2 },
+ LAZY_PLT_ENTRY_SIZE,
+ 1, /* Number of FREs for PLTn. */
+ /* Array of SFrame FREs for plt. */
+ { &elf_x86_64_sframe_sec_pltn_fre1, &elf_x86_64_sframe_null_fre },
+ 0,
+ 0, /* There is no second PLT necessary. */
+ { &elf_x86_64_sframe_null_fre },
+ LAZY_PLT_ENTRY_SIZE,
+ 1, /* Number of FREs for PLT GOT. */
+ /* Array of SFrame FREs for PLT GOT. */
+ { &elf_x86_64_sframe_null_fre },
};
-/* SFrame helper object for lazy PLT. Also used for IBT enabled PLT. */
+/* SFrame helper object for lazy PLT. */
static const struct elf_x86_sframe_plt elf_x86_64_sframe_plt =
{
LAZY_PLT_ENTRY_SIZE,
@@ -942,10 +974,34 @@ static const struct elf_x86_sframe_plt elf_x86_64_sframe_plt =
/* Array of SFrame FREs for plt. */
{ &elf_x86_64_sframe_pltn_fre1, &elf_x86_64_sframe_pltn_fre2 },
NON_LAZY_PLT_ENTRY_SIZE,
- 1, /* Number of FREs for PLTn for second PLT. */
- /* FREs for second plt (stack trace info for .plt.got is
- identical). Used when IBT or non-lazy PLT is in effect. */
- { &elf_x86_64_sframe_sec_pltn_fre1 }
+ 1, /* Number of FREs for second PLT. */
+ /* Array of SFrame FREs for second PLT. */
+ { &elf_x86_64_sframe_sec_pltn_fre1 },
+ NON_LAZY_PLT_ENTRY_SIZE,
+ 1, /* Number of FREs for PLT GOT. */
+ /* Array of SFrame FREs for PLT GOT. */
+ { &elf_x86_64_sframe_null_fre },
+};
+
+/* SFrame helper object for lazy PLT with IBT. */
+static const struct elf_x86_sframe_plt elf_x86_64_sframe_ibt_plt =
+{
+ LAZY_PLT_ENTRY_SIZE,
+ 2, /* Number of FREs for PLT0. */
+ /* Array of SFrame FREs for plt0. */
+ { &elf_x86_64_sframe_plt0_fre1, &elf_x86_64_sframe_plt0_fre2 },
+ LAZY_PLT_ENTRY_SIZE,
+ 2, /* Number of FREs for PLTn. */
+ /* Array of SFrame FREs for plt. */
+ { &elf_x86_64_sframe_pltn_fre1, &elf_x86_64_sframe_ibt_pltn_fre2 },
+ LAZY_PLT_ENTRY_SIZE,
+ 1, /* Number of FREs for second PLT. */
+ /* Array of SFrame FREs for second plt. */
+ { &elf_x86_64_sframe_sec_pltn_fre1 },
+ LAZY_PLT_ENTRY_SIZE,
+ 1, /* Number of FREs for PLT GOT. */
+ /* Array of SFrame FREs for PLT GOT. */
+ { &elf_x86_64_sframe_null_fre },
};
/* These are the standard parameters. */
@@ -1409,32 +1465,8 @@ elf_x86_64_check_tls_transition (bfd *abfd,
: elf_x86_tls_error_yes);
case R_X86_64_TLSDESC_CALL:
- /* Check transition from GDesc access model:
- call *x@tlsdesc(%rax) <--- LP64 mode.
- call *x@tlsdesc(%eax) <--- X32 mode.
- */
- if (offset + 2 <= sec->size)
- {
- unsigned int prefix;
- call = contents + offset;
- prefix = 0;
- if (!ABI_64_P (abfd))
- {
- /* Check for call *x@tlsdesc(%eax). */
- if (call[0] == 0x67)
- {
- prefix = 1;
- if (offset + 3 > sec->size)
- return elf_x86_tls_error_yes;
- }
- }
- /* Make sure that it's a call *x@tlsdesc(%rax). */
- return (call[prefix] == 0xff && call[1 + prefix] == 0x10
- ? elf_x86_tls_error_none
- : elf_x86_tls_error_indirect_call);
- }
-
- return elf_x86_tls_error_yes;
+ /* It has been checked in elf_x86_64_tls_transition. */
+ return elf_x86_tls_error_none;
default:
abort ();
@@ -1459,6 +1491,8 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
unsigned int from_type = *r_type;
unsigned int to_type = from_type;
bool check = true;
+ bfd_vma offset;
+ bfd_byte *call;
/* Skip TLS transition for functions. */
if (h != NULL
@@ -1468,10 +1502,49 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
switch (from_type)
{
+ case R_X86_64_TLSDESC_CALL:
+ /* Check valid GDesc call:
+ call *x@tlscall(%rax) <--- LP64 mode.
+ call *x@tlscall(%eax) <--- X32 mode.
+ */
+ offset = rel->r_offset;
+ call = NULL;
+ if (offset + 2 <= sec->size)
+ {
+ unsigned int prefix;
+ call = contents + offset;
+ prefix = 0;
+ if (!ABI_64_P (abfd))
+ {
+ /* Check for call *x@tlscall(%eax). */
+ if (call[0] == 0x67)
+ {
+ prefix = 1;
+ if (offset + 3 > sec->size)
+ call = NULL;
+ }
+ }
+
+ /* Make sure that it's a call *x@tlscall(%rax). */
+ if (call != NULL
+ && (call[prefix] != 0xff || call[1 + prefix] != 0x10))
+ call = NULL;
+ }
+
+ if (call == NULL)
+ {
+ _bfd_x86_elf_link_report_tls_transition_error
+ (info, abfd, sec, symtab_hdr, h, sym, rel,
+ "R_X86_64_TLSDESC_CALL", NULL,
+ elf_x86_tls_error_indirect_call);
+ return false;
+ }
+
+ /* Fall through. */
+
case R_X86_64_TLSGD:
case R_X86_64_GOTPC32_TLSDESC:
case R_X86_64_CODE_4_GOTPC32_TLSDESC:
- case R_X86_64_TLSDESC_CALL:
case R_X86_64_GOTTPOFF:
case R_X86_64_CODE_4_GOTTPOFF:
case R_X86_64_CODE_6_GOTTPOFF:
@@ -3825,7 +3898,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
unsigned int prefix = 0;
if (!ABI_64_P (input_bfd))
{
- /* Check for call *x@tlsdesc(%eax). */
+ /* Check for call *x@tlscall(%eax). */
if (contents[roff] == 0x67)
prefix = 1;
}
@@ -4285,7 +4358,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
unsigned int prefix = 0;
if (!ABI_64_P (input_bfd))
{
- /* Check for call *x@tlsdesc(%eax). */
+ /* Check for call *x@tlscall(%eax). */
if (contents[roff] == 0x67)
prefix = 1;
}
@@ -5661,8 +5734,8 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
{
init_table.sframe_lazy_plt = &elf_x86_64_sframe_plt;
init_table.sframe_non_lazy_plt = &elf_x86_64_sframe_non_lazy_plt;
- init_table.sframe_lazy_ibt_plt = &elf_x86_64_sframe_plt;
- init_table.sframe_non_lazy_ibt_plt = &elf_x86_64_sframe_non_lazy_plt;
+ init_table.sframe_lazy_ibt_plt = &elf_x86_64_sframe_ibt_plt;
+ init_table.sframe_non_lazy_ibt_plt = &elf_x86_64_sframe_non_lazy_ibt_plt;
}
else
{
diff --git a/bfd/elflink.c b/bfd/elflink.c
index a180e59..ef159da 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -64,7 +64,7 @@ _bfd_elf_link_keep_memory (struct bfd_link_info *info)
this is opt-in by each backend. */
const struct elf_backend_data *bed
= get_elf_backend_data (info->output_bfd);
- if (bed->use_mmap)
+ if (bed != NULL && bed->use_mmap)
return false;
#endif
bfd *abfd;
@@ -2877,7 +2877,7 @@ _bfd_elf_link_info_read_relocs (bfd *abfd,
if (keep_memory)
esdo->relocs = internal_relocs;
- _bfd_munmap_readonly_temporary (alloc1, alloc1_size);
+ _bfd_munmap_temporary (alloc1, alloc1_size);
/* Don't free alloc2, since if it was allocated we are passing it
back (under the name of internal_relocs). */
@@ -2885,7 +2885,7 @@ _bfd_elf_link_info_read_relocs (bfd *abfd,
return internal_relocs;
error_return:
- _bfd_munmap_readonly_temporary (alloc1, alloc1_size);
+ _bfd_munmap_temporary (alloc1, alloc1_size);
if (alloc2 != NULL)
{
if (keep_memory)
@@ -3653,6 +3653,7 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
object file is an IR object, give linker LTO plugin a chance to
get the correct symbol table. */
if (abfd->plugin_format == bfd_plugin_yes
+ || abfd->plugin_format == bfd_plugin_yes_unused
#if BFD_SUPPORTS_PLUGINS
|| (abfd->plugin_format == bfd_plugin_unknown
&& bfd_link_plugin_object_p (abfd))
@@ -5694,7 +5695,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
&& !bfd_link_relocatable (info)
&& (abfd->flags & BFD_PLUGIN) == 0
&& !just_syms
- && extsymcount)
+ && extsymcount != 0
+ && is_elf_hash_table (&htab->root))
{
int r_sym_shift;
@@ -5717,9 +5719,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if ((s->flags & SEC_RELOC) == 0
|| s->reloc_count == 0
|| (s->flags & SEC_EXCLUDE) != 0
- || ((info->strip == strip_all
- || info->strip == strip_debugger)
- && (s->flags & SEC_DEBUGGING) != 0))
+ || (s->flags & SEC_DEBUGGING) != 0)
continue;
internal_relocs = _bfd_elf_link_info_read_relocs
@@ -8109,8 +8109,8 @@ _bfd_elf_merge_sections (bfd *obfd, struct bfd_link_info *info)
bfd *ibfd;
asection *sec;
- if (!is_elf_hash_table (info->hash))
- return false;
+ if (ENABLE_CHECKING && !is_elf_hash_table (info->hash))
+ abort ();
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
if ((ibfd->flags & DYNAMIC) == 0
@@ -8133,8 +8133,8 @@ _bfd_elf_merge_sections (bfd *obfd, struct bfd_link_info *info)
}
if (elf_hash_table (info)->merge_info != NULL)
- _bfd_merge_sections (obfd, info, elf_hash_table (info)->merge_info,
- merge_sections_remove_hook);
+ return _bfd_merge_sections (obfd, info, elf_hash_table (info)->merge_info,
+ merge_sections_remove_hook);
return true;
}
@@ -8819,6 +8819,8 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
symp->name = bfd_elf_string_from_elf_section (bfd1,
hdr1->sh_link,
ssym->st_name);
+ if (symp->name == NULL)
+ goto done;
symp++;
}
@@ -8832,6 +8834,8 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
symp->name = bfd_elf_string_from_elf_section (bfd2,
hdr2->sh_link,
ssym->st_name);
+ if (symp->name == NULL)
+ goto done;
symp++;
}
@@ -8878,14 +8882,22 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
goto done;
for (i = 0; i < count1; i++)
- symtable1[i].name
- = bfd_elf_string_from_elf_section (bfd1, hdr1->sh_link,
- symtable1[i].u.isym->st_name);
+ {
+ symtable1[i].name
+ = bfd_elf_string_from_elf_section (bfd1, hdr1->sh_link,
+ symtable1[i].u.isym->st_name);
+ if (symtable1[i].name == NULL)
+ goto done;
+ }
for (i = 0; i < count2; i++)
- symtable2[i].name
- = bfd_elf_string_from_elf_section (bfd2, hdr2->sh_link,
- symtable2[i].u.isym->st_name);
+ {
+ symtable2[i].name
+ = bfd_elf_string_from_elf_section (bfd2, hdr2->sh_link,
+ symtable2[i].u.isym->st_name);
+ if (symtable2[i].name == NULL)
+ goto done;
+ }
/* Sort symbol by name. */
qsort (symtable1, count1, sizeof (struct elf_symbol),
@@ -12914,7 +12926,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
{
file_ptr off = elf_next_file_pos (abfd);
- _bfd_elf_assign_file_position_for_section (symtab_hdr, off, true);
+ _bfd_elf_assign_file_position_for_section (symtab_hdr, off, true, 0);
/* Note that at this point elf_next_file_pos (abfd) is
incorrect. We do not yet know the size of the .symtab section.
@@ -13358,7 +13370,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
symtab_shndx_hdr->sh_size = amt;
off = _bfd_elf_assign_file_position_for_section (symtab_shndx_hdr,
- off, true);
+ off, true, 0);
if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0
|| (bfd_write (flinfo.symshndxbuf, amt, abfd) != amt))
@@ -13382,7 +13394,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
symstrtab_hdr->sh_addralign = 1;
off = _bfd_elf_assign_file_position_for_section (symstrtab_hdr,
- off, true);
+ off, true, 0);
elf_next_file_pos (abfd) = off;
if (bfd_seek (abfd, symstrtab_hdr->sh_offset, SEEK_SET) != 0
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index db6d419..608d179 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -84,6 +84,14 @@ struct _bfd_loongarch_elf_obj_tdata
&& elf_tdata (bfd) != NULL \
&& elf_object_id (bfd) == LARCH_ELF_DATA)
+static bool
+elfNN_loongarch_object (bfd *abfd)
+{
+ return bfd_elf_allocate_object (abfd,
+ sizeof (struct _bfd_loongarch_elf_obj_tdata),
+ LARCH_ELF_DATA);
+}
+
struct relr_entry
{
asection *sec;
@@ -121,6 +129,12 @@ struct loongarch_elf_link_hash_table
/* Layout recomputation count. */
bfd_size_type relr_layout_iter;
+
+ /* In BFD DT_RELR is implemented as a "relaxation." If in a relax trip
+ size_relative_relocs is updating the layout, relax_section may see
+ a partially updated state (some sections have vma updated but the
+ others do not), and it's unsafe to do the normal relaxation. */
+ bool layout_mutating_for_relr;
};
struct loongarch_elf_section_data
@@ -157,9 +171,7 @@ loongarch_elf_new_section_hook (bfd *abfd, asection *sec)
/* Get the LoongArch ELF linker hash table from a link_info structure. */
#define loongarch_elf_hash_table(p) \
- (elf_hash_table_id (elf_hash_table (p)) == LARCH_ELF_DATA \
- ? ((struct loongarch_elf_link_hash_table *) ((p)->hash)) \
- : NULL)
+ ((struct loongarch_elf_link_hash_table *) ((p)->hash)) \
#define MINUS_ONE ((bfd_vma) 0 - 1)
@@ -844,13 +856,15 @@ loongarch_tls_transition (bfd *input_bfd,
}
static bool
-bad_static_reloc (bfd *abfd, const Elf_Internal_Rela *rel, asection *sec,
- unsigned r_type, struct elf_link_hash_entry *h,
+bad_static_reloc (struct bfd_link_info *info,
+ bfd *abfd, const Elf_Internal_Rela *rel,
+ asection *sec, unsigned r_type,
+ struct elf_link_hash_entry *h,
Elf_Internal_Sym *isym)
{
- /* We propably can improve the information to tell users that they should
- be recompile the code with -fPIC or -fPIE, just like what x86 does. */
reloc_howto_type * r = loongarch_elf_rtype_to_howto (abfd, r_type);
+ const char *object;
+ const char *pic;
const char *name = NULL;
if (h)
@@ -862,10 +876,24 @@ bad_static_reloc (bfd *abfd, const Elf_Internal_Rela *rel, asection *sec,
if (name == NULL || *name == '\0')
name ="<nameless>";
+ if (bfd_link_dll (info))
+ {
+ object = _("a shared object");
+ pic = _("; recompile with -fPIC");
+ }
+ else
+ {
+ if (bfd_link_pie (info))
+ object = _("a PIE object");
+ else
+ object = _("a PDE object");
+ pic = _("; recompile with -fPIE");
+ }
+
(*_bfd_error_handler)
(_("%pB:(%pA+%#lx): relocation %s against `%s` can not be used when making "
- "a shared object; recompile with -fPIC"),
- abfd, sec, (long) rel->r_offset, r ? r->name : _("<unknown>"), name);
+ "%s%s"),
+ abfd, sec, (long) rel->r_offset, r ? r->name : _("<unknown>"), name, object, pic);
bfd_set_error (bfd_error_bad_value);
return false;
}
@@ -1035,7 +1063,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_LARCH_TLS_LE_HI20_R:
case R_LARCH_SOP_PUSH_TLS_TPREL:
if (!bfd_link_executable (info))
- return bad_static_reloc (abfd, rel, sec, r_type, h, isym);
+ return bad_static_reloc (info, abfd, rel, sec, r_type, h, isym);
if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
r_symndx,
@@ -1053,7 +1081,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_LARCH_ABS_HI20:
if (bfd_link_pic (info))
- return bad_static_reloc (abfd, rel, sec, r_type, h, isym);
+ return bad_static_reloc (info, abfd, rel, sec, r_type, h, isym);
/* Fall through. */
case R_LARCH_SOP_PUSH_ABSOLUTE:
@@ -1067,6 +1095,18 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
h->non_got_ref = 1;
break;
+ /* Since shared library global symbols interpose, any
+ PC-relative relocations against external symbols
+ should not be used to build shared libraries. */
+ case R_LARCH_PCREL20_S2:
+ if (bfd_link_pic (info)
+ && (sec->flags & SEC_ALLOC) != 0
+ && (sec->flags & SEC_READONLY) != 0
+ && ! LARCH_REF_LOCAL (info, h))
+ return bad_static_reloc (info, abfd, rel, sec, r_type, h, NULL);
+
+ break;
+
/* For normal cmodel, pcalau12i + addi.d/w used to data.
For first version medium cmodel, pcalau12i + jirl are used to
function call, it need to creat PLT entry for STT_FUNC and
@@ -1084,6 +1124,15 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
h->pointer_equality_needed = 1;
}
+ /* PC-relative relocations are allowed For first version
+ medium cmodel function call. */
+ if (h != NULL && !h->needs_plt
+ && bfd_link_pic (info)
+ && (sec->flags & SEC_ALLOC) != 0
+ && (sec->flags & SEC_READONLY) != 0
+ && ! LARCH_REF_LOCAL (info, h))
+ return bad_static_reloc (info, abfd, rel, sec, r_type, h, NULL);
+
break;
case R_LARCH_B16:
@@ -2212,6 +2261,8 @@ loongarch_elf_size_relative_relocs (struct bfd_link_info *info,
*need_layout = false;
}
}
+
+ htab->layout_mutating_for_relr = *need_layout;
return true;
}
@@ -3307,7 +3358,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
/* The r_symndx will be STN_UNDEF (zero) only for relocs against symbols
from removed linkonce sections, or sections discarded by a linker
script. Also for R_*_SOP_PUSH_ABSOLUTE and PCREL to specify const. */
- if (r_symndx == STN_UNDEF || bfd_is_abs_section (sec))
+ if (r_symndx == STN_UNDEF)
{
defined_local = false;
resolved_local = false;
@@ -3536,7 +3587,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
bfd_reloc_notsupported, is_undefweak, name,
"TLS section not be created"));
else
- relocation -= elf_hash_table (info)->tls_sec->vma;
+ relocation = tlsoff (info, relocation);
}
else
fatal = (loongarch_reloc_is_fatal
@@ -3885,73 +3936,71 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
{
Elf_Internal_Rela rela;
asection *srel = htab->elf.srelgot;
- bfd_vma tls_block_off = 0;
- if (LARCH_REF_LOCAL (info, h))
- {
- BFD_ASSERT (elf_hash_table (info)->tls_sec);
- tls_block_off = relocation
- - elf_hash_table (info)->tls_sec->vma;
- }
+ int indx = 0;
+ bool need_reloc = false;
+ LARCH_TLS_GD_IE_NEED_DYN_RELOC (info, is_dyn, h, indx,
+ need_reloc);
if (tls_type & GOT_TLS_GD)
{
- rela.r_offset = sec_addr (got) + got_off;
- rela.r_addend = 0;
- if (LARCH_REF_LOCAL (info, h))
+ if (need_reloc)
{
- /* Local sym, used in exec, set module id 1. */
- if (bfd_link_executable (info))
- bfd_put_NN (output_bfd, 1, got->contents + got_off);
+ /* Dynamic resolved Module ID. */
+ rela.r_offset = sec_addr (got) + got_off;
+ rela.r_addend = 0;
+ rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_DTPMODNN);
+ bfd_put_NN (output_bfd, 0, got->contents + got_off);
+ loongarch_elf_append_rela (output_bfd, srel, &rela);
+
+ if (indx == 0)
+ {
+ /* Local symbol, tp offset has been known. */
+ BFD_ASSERT (! unresolved_reloc);
+ bfd_put_NN (output_bfd,
+ tlsoff (info, relocation),
+ (got->contents + got_off + GOT_ENTRY_SIZE));
+ }
else
{
- rela.r_info = ELFNN_R_INFO (0,
- R_LARCH_TLS_DTPMODNN);
+ /* Dynamic resolved block offset. */
+ bfd_put_NN (output_bfd, 0,
+ got->contents + got_off + GOT_ENTRY_SIZE);
+ rela.r_info = ELFNN_R_INFO (indx,
+ R_LARCH_TLS_DTPRELNN);
+ rela.r_offset += GOT_ENTRY_SIZE;
loongarch_elf_append_rela (output_bfd, srel, &rela);
}
-
- bfd_put_NN (output_bfd, tls_block_off,
- got->contents + got_off + GOT_ENTRY_SIZE);
}
- /* Dynamic resolved. */
else
{
- /* Dynamic relocate module id. */
- rela.r_info = ELFNN_R_INFO (h->dynindx,
- R_LARCH_TLS_DTPMODNN);
- loongarch_elf_append_rela (output_bfd, srel, &rela);
-
- /* Dynamic relocate offset of block. */
- rela.r_offset += GOT_ENTRY_SIZE;
- rela.r_info = ELFNN_R_INFO (h->dynindx,
- R_LARCH_TLS_DTPRELNN);
- loongarch_elf_append_rela (output_bfd, srel, &rela);
+ /* In a static link or an executable link with the symbol
+ binding locally. Mark it as belonging to module 1. */
+ bfd_put_NN (output_bfd, 1, got->contents + got_off);
+ bfd_put_NN (output_bfd, tlsoff (info, relocation),
+ got->contents + got_off + GOT_ENTRY_SIZE);
}
}
if (tls_type & GOT_TLS_IE)
{
- rela.r_offset = sec_addr (got) + got_off + ie_off;
- if (LARCH_REF_LOCAL (info, h))
+ if (need_reloc)
{
- /* Local sym, used in exec, set module id 1. */
- if (!bfd_link_executable (info))
- {
- rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
- rela.r_addend = tls_block_off;
- loongarch_elf_append_rela (output_bfd, srel, &rela);
- }
+ bfd_put_NN (output_bfd, 0,
+ got->contents + got_off + ie_off);
+ rela.r_offset = sec_addr (got) + got_off + ie_off;
+ rela.r_addend = 0;
- bfd_put_NN (output_bfd, tls_block_off,
- got->contents + got_off + ie_off);
+ if (indx == 0)
+ rela.r_addend = tlsoff (info, relocation);
+ rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_TPRELNN);
+ loongarch_elf_append_rela (output_bfd, srel, &rela);
}
- /* Dynamic resolved. */
else
{
- /* Dynamic relocate offset of block. */
- rela.r_info = ELFNN_R_INFO (h->dynindx,
- R_LARCH_TLS_TPRELNN);
- rela.r_addend = 0;
- loongarch_elf_append_rela (output_bfd, srel, &rela);
+ /* In a static link or an executable link with the symbol
+ binding locally, compute offset directly. */
+ bfd_put_NN (output_bfd, tlsoff (info, relocation),
+ got->contents + got_off + ie_off);
}
}
}
@@ -4061,7 +4110,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
/* For 2G jump, generate pcalau12i, jirl. */
/* If use jirl, turns to R_LARCH_B16. */
uint32_t insn = bfd_get (32, input_bfd, contents + rel->r_offset);
- if ((insn & 0x4c000000) == 0x4c000000)
+ if (LARCH_INSN_JIRL (insn))
{
relocation &= 0xfff;
/* Signed extend. */
@@ -4132,8 +4181,10 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn,
bfd_link_pic (info),
h)
+ && !bfd_is_abs_section(h->root.u.def.section)
&& bfd_link_pic (info)
- && LARCH_REF_LOCAL (info, h))
+ && LARCH_REF_LOCAL (info, h)
+ && !info->enable_dt_relr)
{
Elf_Internal_Rela rela;
rela.r_offset = sec_addr (got) + got_off;
@@ -4153,7 +4204,8 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
&& local_got_offsets[r_symndx] != MINUS_ONE);
got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1);
- if ((local_got_offsets[r_symndx] & 1) == 0)
+ if (sym->st_shndx != SHN_ABS
+ && (local_got_offsets[r_symndx] & 1) == 0)
{
if (bfd_link_pic (info) && !info->enable_dt_relr)
{
@@ -4700,7 +4752,7 @@ loongarch_tls_perform_trans (bfd *abfd, asection *sec,
pcalalau12i $a0,%desc_pc_hi20(var) =>
lu12i.w $a0,%le_hi20(var)
*/
- bfd_put (32, abfd, LARCH_LU12I_W | LARCH_RD_A0,
+ bfd_put (32, abfd, LARCH_OP_LU12I_W | LARCH_RD_A0,
contents + rel->r_offset);
rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_TLS_LE_HI20);
}
@@ -4721,8 +4773,8 @@ loongarch_tls_perform_trans (bfd *abfd, asection *sec,
addi.d $a0,$a0,%desc_pc_lo12(var) =>
ori $a0,$a0,le_lo12(var)
*/
- insn = LARCH_ORI | LARCH_RD_RJ_A0;
- bfd_put (32, abfd, LARCH_ORI | LARCH_RD_RJ_A0,
+ insn = LARCH_OP_ORI | LARCH_RD_RJ_A0;
+ bfd_put (32, abfd, LARCH_OP_ORI | LARCH_RD_RJ_A0,
contents + rel->r_offset);
rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_TLS_LE_LO12);
}
@@ -4732,7 +4784,7 @@ loongarch_tls_perform_trans (bfd *abfd, asection *sec,
addi.d $a0,$a0,%desc_pc_lo12(var) =>
ld.d $a0,$a0,%ie_pc_lo12(var)
*/
- bfd_put (32, abfd, LARCH_LD_D | LARCH_RD_RJ_A0,
+ bfd_put (32, abfd, LARCH_OP_LD_D | LARCH_RD_RJ_A0,
contents + rel->r_offset);
rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_TLS_IE_PC_LO12);
}
@@ -4759,7 +4811,7 @@ loongarch_tls_perform_trans (bfd *abfd, asection *sec,
lu12i.w $rd,%le_hi20(var)
*/
insn = bfd_getl32 (contents + rel->r_offset);
- bfd_put (32, abfd, LARCH_LU12I_W | (insn & 0x1f),
+ bfd_put (32, abfd, LARCH_OP_LU12I_W | LARCH_GET_RD(insn),
contents + rel->r_offset);
rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_TLS_LE_HI20);
}
@@ -4773,7 +4825,7 @@ loongarch_tls_perform_trans (bfd *abfd, asection *sec,
ori $rd,$rj,le_lo12(var)
*/
insn = bfd_getl32 (contents + rel->r_offset);
- bfd_put (32, abfd, LARCH_ORI | (insn & 0x3ff),
+ bfd_put (32, abfd, LARCH_OP_ORI | (insn & 0x3ff),
contents + rel->r_offset);
rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_TLS_LE_LO12);
}
@@ -4838,9 +4890,11 @@ loongarch_tls_perform_trans (bfd *abfd, asection *sec,
*/
static bool
loongarch_relax_tls_le (bfd *abfd, asection *sec,
- Elf_Internal_Rela *rel,
+ asection *sym_sec ATTRIBUTE_UNUSED,
+ Elf_Internal_Rela *rel, bfd_vma symval,
struct bfd_link_info *link_info,
- bfd_vma symval)
+ bool *agin ATTRIBUTE_UNUSED,
+ bfd_vma max_alignment ATTRIBUTE_UNUSED)
{
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
uint32_t insn = bfd_get (32, abfd, contents + rel->r_offset);
@@ -4848,7 +4902,7 @@ loongarch_relax_tls_le (bfd *abfd, asection *sec,
symval = symval - elf_hash_table (link_info)->tls_sec->vma;
/* The old LE instruction sequence can be relaxed when the symbol offset
is smaller than the 12-bit range. */
- if (ELFNN_R_TYPE ((rel + 1)->r_info) == R_LARCH_RELAX && (symval <= 0xfff))
+ if (symval <= 0xfff)
{
switch (ELFNN_R_TYPE (rel->r_info))
{
@@ -4871,11 +4925,11 @@ loongarch_relax_tls_le (bfd *abfd, asection *sec,
/* Change rj to $tp. */
insn_rj = 0x2 << 5;
/* Get rd register. */
- insn_rd = insn & 0x1f;
+ insn_rd = LARCH_GET_RD (insn);
/* Write symbol offset. */
symval <<= 10;
/* Writes the modified instruction. */
- insn = insn & 0xffc00000;
+ insn = insn & LARCH_MK_ADDI_D;
insn = insn | symval | insn_rj | insn_rd;
bfd_put (32, abfd, insn, contents + rel->r_offset);
}
@@ -4890,7 +4944,7 @@ loongarch_relax_tls_le (bfd *abfd, asection *sec,
break;
case R_LARCH_TLS_LE_LO12:
- bfd_put (32, abfd, LARCH_ORI | (insn & 0x1f),
+ bfd_put (32, abfd, LARCH_OP_ORI | LARCH_GET_RD (insn),
contents + rel->r_offset);
break;
@@ -4936,7 +4990,7 @@ loongarch_relax_pcala_addi (bfd *abfd, asection *sec, asection *sym_sec,
Elf_Internal_Rela *rel_lo = rel_hi + 2;
uint32_t pca = bfd_get (32, abfd, contents + rel_hi->r_offset);
uint32_t add = bfd_get (32, abfd, contents + rel_lo->r_offset);
- uint32_t rd = pca & 0x1f;
+ uint32_t rd = LARCH_GET_RD (pca);
/* This section's output_offset need to subtract the bytes of instructions
relaxed by the previous sections, so it needs to be updated beforehand.
@@ -4957,18 +5011,14 @@ loongarch_relax_pcala_addi (bfd *abfd, asection *sec, asection *sym_sec,
else if (symval < pc)
pc += (max_alignment > 4 ? max_alignment : 0);
- const uint32_t addi_d = 0x02c00000;
- const uint32_t pcaddi = 0x18000000;
+ const uint32_t pcaddi = LARCH_OP_PCADDI;
/* Is pcalau12i + addi.d insns? */
if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_PCALA_LO12)
- || (ELFNN_R_TYPE ((rel_lo + 1)->r_info) != R_LARCH_RELAX)
- || (ELFNN_R_TYPE ((rel_hi + 1)->r_info) != R_LARCH_RELAX)
- || (rel_hi->r_offset + 4 != rel_lo->r_offset)
- || ((add & addi_d) != addi_d)
+ || !LARCH_INSN_ADDI_D (add)
/* Is pcalau12i $rd + addi.d $rd,$rd? */
- || ((add & 0x1f) != rd)
- || (((add >> 5) & 0x1f) != rd)
+ || (LARCH_GET_RD (add) != rd)
+ || (LARCH_GET_RJ (add) != rd)
/* Can be relaxed to pcaddi? */
|| (symval & 0x3) /* 4 bytes align. */
|| ((bfd_signed_vma)(symval - pc) < (bfd_signed_vma)(int32_t)0xffe00000)
@@ -5001,7 +5051,7 @@ loongarch_relax_call36 (bfd *abfd, asection *sec, asection *sym_sec,
{
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
uint32_t jirl = bfd_get (32, abfd, contents + rel->r_offset + 4);
- uint32_t rd = jirl & 0x1f;
+ uint32_t rd = LARCH_GET_RD (jirl);
/* This section's output_offset need to subtract the bytes of instructions
relaxed by the previous sections, so it needs to be updated beforehand.
@@ -5022,11 +5072,8 @@ loongarch_relax_call36 (bfd *abfd, asection *sec, asection *sym_sec,
else if (symval < pc)
pc += (max_alignment > 4 ? max_alignment : 0);
- const uint32_t jirl_opcode = 0x4c000000;
-
/* Is pcalau12i + addi.d insns? */
- if ((ELFNN_R_TYPE ((rel + 1)->r_info) != R_LARCH_RELAX)
- || ((jirl & jirl_opcode) != jirl_opcode)
+ if (!LARCH_INSN_JIRL (jirl)
|| ((bfd_signed_vma)(symval - pc) < (bfd_signed_vma)(int32_t)0xf8000000)
|| ((bfd_signed_vma)(symval - pc) > (bfd_signed_vma)(int32_t)0x7fffffc))
return false;
@@ -5034,8 +5081,8 @@ loongarch_relax_call36 (bfd *abfd, asection *sec, asection *sym_sec,
/* Continue next relax trip. */
*again = true;
- const uint32_t bl = 0x54000000;
- const uint32_t b = 0x50000000;
+ const uint32_t bl = LARCH_OP_BL;
+ const uint32_t b = LARCH_OP_B;
if (rd)
bfd_put (32, abfd, bl, contents + rel->r_offset);
@@ -5052,23 +5099,24 @@ loongarch_relax_call36 (bfd *abfd, asection *sec, asection *sym_sec,
/* Relax pcalau12i,ld.d => pcalau12i,addi.d. */
static bool
loongarch_relax_pcala_ld (bfd *abfd, asection *sec,
- Elf_Internal_Rela *rel_hi)
+ asection *sym_sec ATTRIBUTE_UNUSED,
+ Elf_Internal_Rela *rel_hi,
+ bfd_vma symval ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ bool *again ATTRIBUTE_UNUSED,
+ bfd_vma max_alignment ATTRIBUTE_UNUSED)
{
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
Elf_Internal_Rela *rel_lo = rel_hi + 2;
uint32_t pca = bfd_get (32, abfd, contents + rel_hi->r_offset);
uint32_t ld = bfd_get (32, abfd, contents + rel_lo->r_offset);
- uint32_t rd = pca & 0x1f;
- const uint32_t ld_d = 0x28c00000;
- uint32_t addi_d = 0x02c00000;
+ uint32_t rd = LARCH_GET_RD (pca);
+ uint32_t addi_d = LARCH_OP_ADDI_D;
if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_GOT_PC_LO12)
- || (ELFNN_R_TYPE ((rel_lo + 1)->r_info) != R_LARCH_RELAX)
- || (ELFNN_R_TYPE ((rel_hi + 1)->r_info) != R_LARCH_RELAX)
- || (rel_hi->r_offset + 4 != rel_lo->r_offset)
- || ((ld & 0x1f) != rd)
- || (((ld >> 5) & 0x1f) != rd)
- || ((ld & ld_d) != ld_d))
+ || (LARCH_GET_RD (ld) != rd)
+ || (LARCH_GET_RJ (ld) != rd)
+ || !LARCH_INSN_LD_D (ld))
return false;
addi_d = addi_d | (rd << 5) | rd;
@@ -5095,11 +5143,12 @@ bfd_elfNN_loongarch_set_data_segment_info (struct bfd_link_info *info,
/* Implement R_LARCH_ALIGN by deleting excess alignment NOPs.
Once we've handled an R_LARCH_ALIGN, we can't relax anything else. */
static bool
-loongarch_relax_align (bfd *abfd, asection *sec,
- asection *sym_sec,
- struct bfd_link_info *link_info,
+loongarch_relax_align (bfd *abfd, asection *sec, asection *sym_sec,
Elf_Internal_Rela *rel,
- bfd_vma symval)
+ bfd_vma symval ATTRIBUTE_UNUSED,
+ struct bfd_link_info *link_info,
+ bool *again ATTRIBUTE_UNUSED,
+ bfd_vma max_alignment ATTRIBUTE_UNUSED)
{
bfd_vma addend, max = 0, alignment = 1;
@@ -5161,7 +5210,7 @@ loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec,
Elf_Internal_Rela *rel_lo = rel_hi + 2;
uint32_t pca = bfd_get (32, abfd, contents + rel_hi->r_offset);
uint32_t add = bfd_get (32, abfd, contents + rel_lo->r_offset);
- uint32_t rd = pca & 0x1f;
+ uint32_t rd = LARCH_GET_RD (pca);
/* This section's output_offset need to subtract the bytes of instructions
relaxed by the previous sections, so it needs to be updated beforehand.
@@ -5182,19 +5231,15 @@ loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec,
else if (symval < pc)
pc += (max_alignment > 4 ? max_alignment : 0);
- const uint32_t addi_d = 0x02c00000;
- const uint32_t pcaddi = 0x18000000;
+ const uint32_t pcaddi = LARCH_OP_PCADDI;
/* Is pcalau12i + addi.d insns? */
if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_GOT_PC_LO12
&& ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_TLS_DESC_PC_LO12)
- || (ELFNN_R_TYPE ((rel_lo + 1)->r_info) != R_LARCH_RELAX)
- || (ELFNN_R_TYPE ((rel_hi + 1)->r_info) != R_LARCH_RELAX)
- || (rel_hi->r_offset + 4 != rel_lo->r_offset)
- || ((add & addi_d) != addi_d)
+ || !LARCH_INSN_ADDI_D (add)
/* Is pcalau12i $rd + addi.d $rd,$rd? */
- || ((add & 0x1f) != rd)
- || (((add >> 5) & 0x1f) != rd)
+ || (LARCH_GET_RD (add) != rd)
+ || (LARCH_GET_RJ (add) != rd)
/* Can be relaxed to pcaddi? */
|| (symval & 0x3) /* 4 bytes align. */
|| ((bfd_signed_vma)(symval - pc) < (bfd_signed_vma)(int32_t)0xffe00000)
@@ -5247,39 +5292,57 @@ loongarch_get_max_alignment (asection *sec)
return (bfd_vma) 1 << max_alignment_power;
}
+typedef bool (*relax_func_t) (bfd *, asection *, asection *,
+ Elf_Internal_Rela *, bfd_vma,
+ struct bfd_link_info *, bool *,
+ bfd_vma);
+
static bool
loongarch_elf_relax_section (bfd *abfd, asection *sec,
- struct bfd_link_info *info,
- bool *again)
+ struct bfd_link_info *info,
+ bool *again)
{
- struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
- struct bfd_elf_section_data *data = elf_section_data (sec);
- Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd);
- Elf_Internal_Rela *relocs;
*again = false;
- bfd_vma max_alignment = 0;
+
+ if (!is_elf_hash_table (info->hash)
+ || elf_hash_table_id (elf_hash_table (info)) != LARCH_ELF_DATA)
+ return true;
+
+ struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
+
+ /* It may happen that some sections have updated vma but the others do
+ not. Go to the next relax trip (size_relative_relocs should have
+ been demending another relax trip anyway). */
+ if (htab->layout_mutating_for_relr)
+ return true;
if (bfd_link_relocatable (info)
|| sec->sec_flg0
- || (sec->flags & SEC_RELOC) == 0
|| sec->reloc_count == 0
+ || (sec->flags & SEC_RELOC) == 0
+ || (sec->flags & SEC_HAS_CONTENTS) == 0
+ /* The exp_seg_relro_adjust is enum phase_enum (0x4). */
+ || *(htab->data_segment_phase) == 4
|| (info->disable_target_specific_optimizations
- && info->relax_pass == 0)
- /* The exp_seg_relro_adjust is enum phase_enum (0x4),
- and defined in ld/ldexp.h. */
- || *(htab->data_segment_phase) == 4)
+ && info->relax_pass == 0))
return true;
+ struct bfd_elf_section_data *data = elf_section_data (sec);
+ Elf_Internal_Rela *relocs;
if (data->relocs)
relocs = data->relocs;
else if (!(relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
info->keep_memory)))
return true;
+ data->relocs = relocs;
+ /* Read this BFD's contents if we haven't done so already. */
if (!data->this_hdr.contents
&& !bfd_malloc_and_get_section (abfd, sec, &data->this_hdr.contents))
return true;
+ /* Read this BFD's symbols if we haven't done so already. */
+ Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd);
if (symtab_hdr->sh_info != 0
&& !symtab_hdr->contents
&& !(symtab_hdr->contents =
@@ -5288,11 +5351,9 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
0, NULL, NULL, NULL)))
return true;
- data->relocs = relocs;
-
/* Estimate the maximum alignment for all output sections once time
should be enough. */
- max_alignment = htab->max_alignment;
+ bfd_vma max_alignment = htab->max_alignment;
if (max_alignment == (bfd_vma) -1)
{
max_alignment = loongarch_get_max_alignment (sec);
@@ -5310,6 +5371,93 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
+ if (r_symndx >= symtab_hdr->sh_info)
+ {
+ h = elf_sym_hashes (abfd)[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;
+ }
+
+ /* If the conditions for tls type transition are met, type
+ transition is performed instead of relax.
+ During the transition from DESC->IE/LE, there are 2 situations
+ depending on the different configurations of the relax/norelax
+ option.
+ If the -relax option is used, the extra nops will be removed,
+ and this transition is performed in pass 0.
+ If the --no-relax option is used, nop will be retained, and
+ this transition is performed in pass 1. */
+ if (IS_LOONGARCH_TLS_TRANS_RELOC (r_type)
+ && (i + 1 != sec->reloc_count)
+ && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX
+ && rel->r_offset == rel[1].r_offset
+ && loongarch_can_trans_tls (abfd, info, h, r_symndx, r_type))
+ {
+ loongarch_tls_perform_trans (abfd, sec, rel, h, info);
+ r_type = ELFNN_R_TYPE (rel->r_info);
+ }
+
+ relax_func_t relax_func = NULL;
+ if (info->relax_pass == 0)
+ {
+ switch (r_type)
+ {
+ case R_LARCH_PCALA_HI20:
+ relax_func = loongarch_relax_pcala_addi;
+ break;
+ case R_LARCH_GOT_PC_HI20:
+ relax_func = loongarch_relax_pcala_ld;
+ break;
+ case R_LARCH_CALL36:
+ relax_func = loongarch_relax_call36;
+ break;
+ case R_LARCH_TLS_LE_HI20_R:
+ case R_LARCH_TLS_LE_LO12_R:
+ case R_LARCH_TLS_LE_ADD_R:
+ case R_LARCH_TLS_LE_HI20:
+ case R_LARCH_TLS_LE_LO12:
+ case R_LARCH_TLS_LE64_LO20:
+ case R_LARCH_TLS_LE64_HI12:
+ relax_func = loongarch_relax_tls_le;
+ break;
+ case R_LARCH_TLS_LD_PC_HI20:
+ case R_LARCH_TLS_GD_PC_HI20:
+ case R_LARCH_TLS_DESC_PC_HI20:
+ relax_func = loongarch_relax_tls_ld_gd_desc;
+ break;
+ default:
+ continue;
+ }
+
+ /* Only relax this reloc if it is paired with R_RISCV_RELAX. */
+ if (r_type == R_LARCH_TLS_LD_PC_HI20
+ || r_type == R_LARCH_TLS_GD_PC_HI20
+ || r_type == R_LARCH_TLS_DESC_PC_HI20
+ || r_type == R_LARCH_PCALA_HI20
+ || r_type == R_LARCH_GOT_PC_HI20)
+ {
+ if ((i + 2) == sec->reloc_count - 1
+ || ELFNN_R_TYPE ((rel + 1)->r_info) != R_LARCH_RELAX
+ || ELFNN_R_TYPE ((rel + 3)->r_info) != R_LARCH_RELAX
+ || rel->r_offset != (rel + 1)->r_offset
+ || (rel + 2)->r_offset != (rel + 3)->r_offset
+ || rel->r_offset + 4 != (rel + 2)->r_offset)
+ continue;
+ }
+ else
+ {
+ if (i == sec->reloc_count - 1
+ || ELFNN_R_TYPE ((rel + 1)->r_info) != R_LARCH_RELAX
+ || rel->r_offset != (rel + 1)->r_offset)
+ continue;
+ }
+ }
+ else if (info->relax_pass == 1 && r_type == R_LARCH_ALIGN)
+ relax_func = loongarch_relax_align;
+ else
+ continue;
+
/* Four kind of relocations:
Normal: symval is the symbol address.
R_LARCH_ALIGN: symval is the address of the last NOP instruction
@@ -5322,29 +5470,28 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
{
Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents
+ r_symndx;
- if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
+
+ if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
+ && r_type != R_LARCH_CALL36)
+ || sym->st_shndx == SHN_ABS)
continue;
/* Only TLS instruction sequences that are accompanied by
R_LARCH_RELAX and cannot perform type transition can be
relaxed. */
- if (R_LARCH_TLS_LD_PC_HI20 == r_type
- || R_LARCH_TLS_GD_PC_HI20 == r_type
- || (R_LARCH_TLS_DESC_PC_HI20 == r_type
- && (i + 1 != sec->reloc_count)
- && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX
- && ! loongarch_can_trans_tls (abfd, info, h,
- r_symndx, r_type)))
+ if (r_type == R_LARCH_TLS_LD_PC_HI20
+ || r_type == R_LARCH_TLS_GD_PC_HI20
+ || r_type == R_LARCH_TLS_DESC_PC_HI20)
{
sym_sec = htab->elf.sgot;
symval = elf_local_got_offsets (abfd)[r_symndx];
char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
r_symndx);
- if (R_LARCH_TLS_DESC_PC_HI20 == r_type
+ if (r_type == R_LARCH_TLS_DESC_PC_HI20
&& GOT_TLS_GD_BOTH_P (tls_type))
symval += 2 * GOT_ENTRY_SIZE;
}
- else if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
+ else if (sym->st_shndx == SHN_UNDEF || r_type == R_LARCH_ALIGN)
{
sym_sec = sec;
symval = rel->r_offset;
@@ -5358,42 +5505,47 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
}
else
{
- r_symndx = ELFNN_R_SYM (rel->r_info) - symtab_hdr->sh_info;
- h = elf_sym_hashes (abfd)[r_symndx];
-
- 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;
-
- /* Disable the relaxation for ifunc. */
- if (h != NULL && h->type == STT_GNU_IFUNC)
+ if (h != NULL
+ && ((h->type == STT_GNU_IFUNC
+ && r_type != R_LARCH_CALL36)
+ || bfd_is_abs_section (h->root.u.def.section)))
continue;
/* The GOT entry of tls symbols must in current execute file or
shared object. */
- if (R_LARCH_TLS_LD_PC_HI20 == r_type
- || R_LARCH_TLS_GD_PC_HI20 == r_type
- || (R_LARCH_TLS_DESC_PC_HI20 == r_type
- && (i + 1 != sec->reloc_count)
- && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX
- && !loongarch_can_trans_tls (abfd, info, h,
- r_symndx, r_type)))
+ if (r_type == R_LARCH_TLS_LD_PC_HI20
+ || r_type == R_LARCH_TLS_GD_PC_HI20
+ || r_type == R_LARCH_TLS_DESC_PC_HI20)
{
sym_sec = htab->elf.sgot;
symval = h->got.offset;
char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
r_symndx);
- if (R_LARCH_TLS_DESC_PC_HI20 == r_type
+ if (r_type == R_LARCH_TLS_DESC_PC_HI20
&& GOT_TLS_GD_BOTH_P (tls_type))
symval += 2 * GOT_ENTRY_SIZE;
}
+ else if (h->plt.offset != MINUS_ONE)
+ {
+ sym_sec = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
+ symval = h->plt.offset;
+ }
+ /* Like loongarch_elf_relocate_section, set relocation(offset) to 0.
+ Undefweak for other relocations handing in the future. */
+ else if (h->root.type == bfd_link_hash_undefweak
+ && !h->root.linker_def
+ && r_type == R_LARCH_CALL36)
+ {
+ sym_sec = sec;
+ symval = rel->r_offset;
+ }
else if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& h->root.u.def.section != NULL
&& h->root.u.def.section->output_section != NULL)
{
- symval = h->root.u.def.value;
sym_sec = h->root.u.def.section;
+ symval = h->root.u.def.value;
}
else
continue;
@@ -5420,7 +5572,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
+ (alingmeng - 4).
If r_symndx is 0, alignmeng-4 is r_addend.
If r_symndx > 0, alignment-4 is 2^(r_addend & 0xff)-4. */
- else if (R_LARCH_ALIGN == r_type)
+ else if (r_type == R_LARCH_ALIGN)
if (r_symndx > 0)
symval += ((1 << (rel->r_addend & 0xff)) - 4);
else
@@ -5430,82 +5582,14 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
symval += sec_addr (sym_sec);
- /* If the conditions for tls type transition are met, type
- transition is performed instead of relax.
- During the transition from DESC->IE/LE, there are 2 situations
- depending on the different configurations of the relax/norelax
- option.
- If the -relax option is used, the extra nops will be removed,
- and this transition is performed in pass 0.
- If the --no-relax option is used, nop will be retained, and
- this transition is performed in pass 1. */
- if (IS_LOONGARCH_TLS_TRANS_RELOC (r_type)
- && (i + 1 != sec->reloc_count)
- && ELFNN_R_TYPE (rel[1].r_info) == R_LARCH_RELAX
- && loongarch_can_trans_tls (abfd, info, h, r_symndx, r_type))
- {
- loongarch_tls_perform_trans (abfd, sec, rel, h, info);
- r_type = ELFNN_R_TYPE (rel->r_info);
- }
-
- switch (r_type)
- {
- case R_LARCH_ALIGN:
- if (1 == info->relax_pass)
- loongarch_relax_align (abfd, sec, sym_sec, info, rel, symval);
- break;
+ if (r_type == R_LARCH_GOT_PC_HI20 && !local_got)
+ continue;
- case R_LARCH_DELETE:
- if (1 == info->relax_pass)
- {
- loongarch_relax_delete_bytes (abfd, sec, rel->r_offset, 4, info);
- rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
- }
- break;
- case R_LARCH_CALL36:
- if (0 == info->relax_pass && (i + 2) <= sec->reloc_count)
- loongarch_relax_call36 (abfd, sec, sym_sec, rel, symval,
+ if (relax_func (abfd, sec, sym_sec, rel, symval,
+ info, again, max_alignment)
+ && relax_func == loongarch_relax_pcala_ld)
+ loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval,
info, again, max_alignment);
- break;
-
- case R_LARCH_TLS_LE_HI20_R:
- case R_LARCH_TLS_LE_LO12_R:
- case R_LARCH_TLS_LE_ADD_R:
- case R_LARCH_TLS_LE_HI20:
- case R_LARCH_TLS_LE_LO12:
- case R_LARCH_TLS_LE64_LO20:
- case R_LARCH_TLS_LE64_HI12:
- if (0 == info->relax_pass && (i + 2) <= sec->reloc_count)
- loongarch_relax_tls_le (abfd, sec, rel, info, symval);
- break;
-
- case R_LARCH_PCALA_HI20:
- if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
- loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval,
- info, again, max_alignment);
- break;
-
- case R_LARCH_GOT_PC_HI20:
- if (local_got && 0 == info->relax_pass
- && (i + 4) <= sec->reloc_count)
- {
- if (loongarch_relax_pcala_ld (abfd, sec, rel))
- loongarch_relax_pcala_addi (abfd, sec, sym_sec, rel, symval,
- info, again, max_alignment);
- }
- break;
-
- case R_LARCH_TLS_LD_PC_HI20:
- case R_LARCH_TLS_GD_PC_HI20:
- case R_LARCH_TLS_DESC_PC_HI20:
- if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
- loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
- info, again, max_alignment);
- break;
-
- default:
- break;
- }
}
return true;
@@ -6132,6 +6216,8 @@ elf_loongarch64_hash_symbol (struct elf_link_hash_entry *h)
#define bfd_elfNN_bfd_reloc_name_lookup loongarch_reloc_name_lookup
#define elf_info_to_howto_rel NULL /* Fall through to elf_info_to_howto. */
#define elf_info_to_howto loongarch_info_to_howto_rela
+#define bfd_elfNN_mkobject \
+ elfNN_loongarch_object
#define bfd_elfNN_bfd_merge_private_bfd_data \
elfNN_loongarch_merge_private_bfd_data
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 90ecc27..c8bf45f 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -5612,7 +5612,7 @@ riscv_elf_is_target_special_symbol (bfd *abfd, asymbol *sym)
{
/* PR27584, local and empty symbols. Since they are usually
generated for pcrel relocations. */
- return (!strcmp (sym->name, "")
+ return (!sym->name[0]
|| _bfd_elf_is_local_label_name (abfd, sym->name)
/* PR27916, mapping symbols. */
|| riscv_elf_is_mapping_symbols (sym->name));
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index b8f314d..4b48d8e 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1182,8 +1182,8 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
{"m", "+zmmul", check_implicit_always},
- {"zabha", "+a", check_implicit_always},
- {"zacas", "+a", check_implicit_always},
+ {"zabha", "+zaamo", check_implicit_always},
+ {"zacas", "+zaamo", check_implicit_always},
{"a", "+zaamo,+zalrsc", check_implicit_always},
{"xsfvcp", "+zve32x", check_implicit_always},
@@ -1213,6 +1213,7 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
{"zcd", "+d,+zca", check_implicit_always},
{"zcf", "+f,+zca", check_implicit_always},
{"zcmp", "+zca", check_implicit_always},
+ {"zcmop", "+zca", check_implicit_always},
{"shcounterenw", "+h", check_implicit_always},
{"shgatpa", "+h", check_implicit_always},
@@ -1344,6 +1345,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
{"zihintntl", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
{"zihpm", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 },
+ {"zimop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"za64rs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"za128rs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
@@ -1420,6 +1422,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
{"zcb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zcf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zcd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"zcmop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zcmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{NULL, 0, 0, 0, 0}
};
@@ -1436,6 +1439,7 @@ static struct riscv_supported_ext riscv_supported_std_s_ext[] =
{"smcsrind", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"smcntrpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"smepmp", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"smrnmi", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"ssaia", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"ssccptr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
@@ -1463,11 +1467,13 @@ static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
{
- {"xcvmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"xcvalu", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
- {"xcvelw", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"xcvbi", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xcvbitmanip", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xcvelw", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xcvmac", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"xcvmem", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
+ {"xcvsimd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"xtheadba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"xtheadbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"xtheadbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
@@ -2556,6 +2562,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
|| riscv_subset_supports (rps, "zca")));
case INSN_CLASS_ZIHINTPAUSE:
return riscv_subset_supports (rps, "zihintpause");
+ case INSN_CLASS_ZIMOP:
+ return riscv_subset_supports (rps, "zimop");
case INSN_CLASS_M:
return riscv_subset_supports (rps, "m");
case INSN_CLASS_ZMMUL:
@@ -2708,22 +2716,28 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
case INSN_CLASS_ZCB_AND_ZMMUL:
return (riscv_subset_supports (rps, "zcb")
&& riscv_subset_supports (rps, "zmmul"));
+ case INSN_CLASS_ZCMOP:
+ return riscv_subset_supports (rps, "zcmop");
case INSN_CLASS_ZCMP:
return riscv_subset_supports (rps, "zcmp");
case INSN_CLASS_SVINVAL:
return riscv_subset_supports (rps, "svinval");
case INSN_CLASS_H:
return riscv_subset_supports (rps, "h");
- case INSN_CLASS_XCVMAC:
- return riscv_subset_supports (rps, "xcvmac");
case INSN_CLASS_XCVALU:
return riscv_subset_supports (rps, "xcvalu");
- case INSN_CLASS_XCVELW:
- return riscv_subset_supports (rps, "xcvelw");
case INSN_CLASS_XCVBI:
return riscv_subset_supports (rps, "xcvbi");
+ case INSN_CLASS_XCVBITMANIP:
+ return riscv_subset_supports (rps, "xcvbitmanip");
+ case INSN_CLASS_XCVELW:
+ return riscv_subset_supports (rps, "xcvelw");
+ case INSN_CLASS_XCVMAC:
+ return riscv_subset_supports (rps, "xcvmac");
case INSN_CLASS_XCVMEM:
return riscv_subset_supports (rps, "xcvmem");
+ case INSN_CLASS_XCVSIMD:
+ return riscv_subset_supports (rps, "xcvsimd");
case INSN_CLASS_XTHEADBA:
return riscv_subset_supports (rps, "xtheadba");
case INSN_CLASS_XTHEADBB:
@@ -2803,6 +2817,8 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
return _("c' or `zca");
case INSN_CLASS_ZIHINTPAUSE:
return "zihintpause";
+ case INSN_CLASS_ZIMOP:
+ return "zimop";
case INSN_CLASS_M:
return "m";
case INSN_CLASS_ZMMUL:
@@ -2982,22 +2998,28 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
return _("zcb' and `zbb");
case INSN_CLASS_ZCB_AND_ZMMUL:
return _("zcb' and `zmmul', or `zcb' and `m");
+ case INSN_CLASS_ZCMOP:
+ return "zcmop";
case INSN_CLASS_ZCMP:
return "zcmp";
case INSN_CLASS_SVINVAL:
return "svinval";
case INSN_CLASS_H:
return _("h");
- case INSN_CLASS_XCVMAC:
- return "xcvmac";
case INSN_CLASS_XCVALU:
return "xcvalu";
- case INSN_CLASS_XCVELW:
- return "xcvelw";
case INSN_CLASS_XCVBI:
return "xcvbi";
+ case INSN_CLASS_XCVBITMANIP:
+ return "xcvbitmanip";
+ case INSN_CLASS_XCVELW:
+ return "xcvelw";
+ case INSN_CLASS_XCVMAC:
+ return "xcvmac";
case INSN_CLASS_XCVMEM:
return "xcvmem";
+ case INSN_CLASS_XCVSIMD:
+ return "xcvsimd";
case INSN_CLASS_XTHEADBA:
return "xtheadba";
case INSN_CLASS_XTHEADBB:
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 075f1bd..d10391d 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -187,11 +187,6 @@
#define bfd_elfNN_bfd_gc_sections bfd_elf_gc_sections
#endif
-#ifndef bfd_elfNN_bfd_merge_sections
-#define bfd_elfNN_bfd_merge_sections \
- _bfd_elf_merge_sections
-#endif
-
#ifndef bfd_elfNN_bfd_is_group_section
#define bfd_elfNN_bfd_is_group_section bfd_elf_is_group_section
#endif
@@ -287,6 +282,9 @@
#ifndef bfd_elfNN_bfd_final_link
#define bfd_elfNN_bfd_final_link bfd_elf_final_link
#endif
+#ifndef bfd_elfNN_bfd_merge_sections
+#define bfd_elfNN_bfd_merge_sections _bfd_elf_merge_sections
+#endif
#else /* ! defined (elf_backend_relocate_section) */
/* If no backend relocate_section routine, use the generic linker.
Note - this will prevent the port from being able to use some of
@@ -310,6 +308,9 @@
#ifndef bfd_elfNN_bfd_final_link
#define bfd_elfNN_bfd_final_link _bfd_generic_final_link
#endif
+#ifndef bfd_elfNN_bfd_merge_sections
+#define bfd_elfNN_bfd_merge_sections bfd_generic_merge_sections
+#endif
#endif /* ! defined (elf_backend_relocate_section) */
#ifndef bfd_elfNN_bfd_link_just_syms
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index 85737fc..0843803 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -745,6 +745,7 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd)
ret->tls_get_addr = "__tls_get_addr";
ret->relative_r_type = R_X86_64_RELATIVE;
ret->relative_r_name = "R_X86_64_RELATIVE";
+ ret->ax_register = "RAX";
ret->elf_append_reloc = elf_append_rela;
ret->elf_write_addend_in_got = _bfd_elf64_write_addend;
}
@@ -776,6 +777,7 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd)
ret->pointer_r_type = R_386_32;
ret->relative_r_type = R_386_RELATIVE;
ret->relative_r_name = "R_386_RELATIVE";
+ ret->ax_register = "EAX";
ret->elf_append_reloc = elf_append_rel;
ret->elf_write_addend = _bfd_elf32_write_addend;
ret->elf_write_addend_in_got = _bfd_elf32_write_addend;
@@ -1815,7 +1817,8 @@ elf_x86_relative_reloc_compare (const void *pa, const void *pb)
enum dynobj_sframe_plt_type
{
SFRAME_PLT = 1,
- SFRAME_PLT_SEC = 2
+ SFRAME_PLT_SEC = 2,
+ SFRAME_PLT_GOT = 3,
};
/* Create SFrame stack trace info for the plt entries in the .plt section
@@ -1829,7 +1832,6 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd,
struct elf_x86_link_hash_table *htab;
const struct elf_backend_data *bed;
- bool plt0_generated_p;
unsigned int plt0_entry_size;
unsigned char func_info;
uint32_t fre_type;
@@ -1843,14 +1845,11 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd,
unsigned plt_entry_size = 0;
unsigned int num_pltn_fres = 0;
unsigned int num_pltn_entries = 0;
+ const sframe_frame_row_entry * const *pltn_fres;
bed = get_elf_backend_data (output_bfd);
htab = elf_x86_hash_table (info, bed->target_id);
/* Whether SFrame stack trace info for plt0 is to be generated. */
- plt0_generated_p = htab->plt.has_plt0;
- plt0_entry_size
- = (plt0_generated_p) ? htab->sframe_plt->plt0_entry_size : 0;
-
switch (plt_sec_type)
{
case SFRAME_PLT:
@@ -1858,7 +1857,10 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd,
ectx = &htab->plt_cfe_ctx;
dpltsec = htab->elf.splt;
- plt_entry_size = htab->plt.plt_entry_size;
+ plt0_entry_size
+ = htab->plt.has_plt0 ? htab->sframe_plt->plt0_entry_size : 0;
+ plt_entry_size = htab->sframe_plt->pltn_entry_size;
+ pltn_fres = htab->sframe_plt->pltn_fres;
num_pltn_fres = htab->sframe_plt->pltn_num_fres;
num_pltn_entries
= (dpltsec->size - plt0_entry_size) / plt_entry_size;
@@ -1868,14 +1870,32 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd,
case SFRAME_PLT_SEC:
{
ectx = &htab->plt_second_cfe_ctx;
- /* FIXME - this or htab->plt_second_sframe ? */
- dpltsec = htab->plt_second_eh_frame;
+ dpltsec = htab->plt_second;
+
+ plt0_entry_size = 0;
plt_entry_size = htab->sframe_plt->sec_pltn_entry_size;
+ pltn_fres = htab->sframe_plt->sec_pltn_fres;
num_pltn_fres = htab->sframe_plt->sec_pltn_num_fres;
num_pltn_entries = dpltsec->size / plt_entry_size;
+
break;
}
+ case SFRAME_PLT_GOT:
+ {
+ ectx = &htab->plt_got_cfe_ctx;
+ dpltsec = htab->plt_got;
+
+ plt0_entry_size = 0;
+
+ plt_entry_size = htab->sframe_plt->plt_got_entry_size;
+ pltn_fres = htab->sframe_plt->plt_got_fres;
+ num_pltn_fres = htab->sframe_plt->plt_got_num_fres;
+ num_pltn_entries = dpltsec->size / plt_entry_size;
+
+ break;
+ }
+
default:
/* No other value is possible. */
return false;
@@ -1895,7 +1915,7 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd,
/* Add SFrame FDE and the associated FREs for plt0 if plt0 has been
generated. */
- if (plt0_generated_p)
+ if (plt0_entry_size)
{
/* Add SFrame FDE for plt0, the function start address is updated later
at _bfd_elf_merge_section_sframe time. */
@@ -1932,16 +1952,17 @@ _bfd_x86_elf_create_sframe_plt (bfd *output_bfd,
plt0_entry_size, /* func start addr. */
dpltsec->size - plt0_entry_size,
func_info,
- 16,
+ plt_entry_size,
0 /* Num FREs. */);
sframe_frame_row_entry pltn_fre;
- /* Now add the FREs for pltn. Simply adding the two FREs suffices due
+ /* Now add the FREs for pltn. Simply adding the FREs suffices due
to the usage of SFRAME_FDE_TYPE_PCMASK above. */
for (unsigned int j = 0; j < num_pltn_fres; j++)
{
- pltn_fre = *(htab->sframe_plt->pltn_fres[j]);
- sframe_encoder_add_fre (*ectx, 1, &pltn_fre);
+ unsigned int func_idx = plt0_entry_size ? 1 : 0;
+ pltn_fre = *(pltn_fres[j]);
+ sframe_encoder_add_fre (*ectx, func_idx, &pltn_fre);
}
}
@@ -1979,6 +2000,10 @@ _bfd_x86_elf_write_sframe_plt (bfd *output_bfd,
ectx = htab->plt_second_cfe_ctx;
sec = htab->plt_second_sframe;
break;
+ case SFRAME_PLT_GOT:
+ ectx = htab->plt_got_cfe_ctx;
+ sec = htab->plt_got_sframe;
+ break;
default:
/* No other value is possible. */
return false;
@@ -2506,7 +2531,18 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
htab->plt_sframe->size = sizeof (sframe_header) + 1;
}
- /* FIXME - generate for .plt.got ? */
+ if (htab->plt_got_sframe != NULL
+ && htab->plt_got != NULL
+ && htab->plt_got->size != 0
+ && !bfd_is_abs_section (htab->plt_got->output_section))
+ {
+ _bfd_x86_elf_create_sframe_plt (output_bfd, info, SFRAME_PLT_GOT);
+ /* FIXME - Dirty Hack. Set the size to something non-zero for now,
+ so that the section does not get stripped out below. The precise
+ size of this section is known only when the contents are
+ serialized in _bfd_x86_elf_write_sframe_plt. */
+ htab->plt_got_sframe->size = sizeof (sframe_header) + 1;
+ }
if (htab->plt_second_sframe != NULL
&& htab->plt_second != NULL
@@ -2573,6 +2609,7 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
|| s == htab->plt_second_eh_frame
|| s == htab->plt_sframe
|| s == htab->plt_second_sframe
+ || s == htab->plt_got_sframe
|| s == htab->elf.sdynbss
|| s == htab->elf.sdynrelro)
{
@@ -2617,7 +2654,8 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
/* Skip allocating contents for .sframe section as it is written
out differently. See below. */
- if ((s == htab->plt_sframe) || (s == htab->plt_second_sframe))
+ if ((s == htab->plt_sframe) || (s == htab->plt_second_sframe)
+ || (s == htab->plt_got_sframe))
continue;
/* NB: Initially, the iplt section has minimal alignment to
@@ -2678,10 +2716,16 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
_bfd_x86_elf_write_sframe_plt (output_bfd, info, SFRAME_PLT);
if (htab->plt_second_sframe != NULL
- && htab->elf.splt != NULL
- && htab->elf.splt->size != 0
+ && htab->plt_second != NULL
+ && htab->plt_second->size != 0
&& htab->plt_second_sframe->contents == NULL)
_bfd_x86_elf_write_sframe_plt (output_bfd, info, SFRAME_PLT_SEC);
+
+ if (htab->plt_got_sframe != NULL
+ && htab->plt_got != NULL
+ && htab->plt_got->size != 0
+ && htab->plt_got_sframe->contents == NULL)
+ _bfd_x86_elf_write_sframe_plt (output_bfd, info, SFRAME_PLT_GOT);
}
if (resolved_plt != NULL
@@ -2992,6 +3036,34 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
return NULL;
}
}
+
+ if (htab->plt_got_sframe != NULL
+ && htab->plt_got_sframe->contents != NULL)
+ {
+ if (htab->plt_got != NULL
+ && htab->plt_got->size != 0
+ && (htab->plt_got->flags & SEC_EXCLUDE) == 0
+ && htab->plt_got->output_section != NULL
+ && htab->plt_got_sframe->output_section != NULL)
+ {
+ bfd_vma plt_start = htab->plt_got->output_section->vma;
+ bfd_vma sframe_start
+ = (htab->plt_got_sframe->output_section->vma
+ + htab->plt_got_sframe->output_offset
+ + PLT_SFRAME_FDE_START_OFFSET);
+ bfd_put_signed_32 (dynobj, plt_start - sframe_start,
+ htab->plt_got_sframe->contents
+ + PLT_SFRAME_FDE_START_OFFSET);
+ }
+ if (htab->plt_got_sframe->sec_info_type == SEC_INFO_TYPE_SFRAME)
+ {
+ if (! _bfd_elf_merge_section_sframe (output_bfd, info,
+ htab->plt_got_sframe,
+ htab->plt_got_sframe->contents))
+ return NULL;
+ }
+ }
+
if (htab->elf.sgot && htab->elf.sgot->size > 0)
elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize
= htab->got_entry_size;
@@ -3211,15 +3283,14 @@ _bfd_x86_elf_link_report_tls_transition_error
enum elf_x86_tls_error_type tls_error)
{
const char *name;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ struct elf_x86_link_hash_table *htab
+ = elf_x86_hash_table (info, bed->target_id);
if (h)
name = h->root.root.string;
else
{
- const struct elf_backend_data *bed
- = get_elf_backend_data (abfd);
- struct elf_x86_link_hash_table *htab
- = elf_x86_hash_table (info, bed->target_id);
if (htab == NULL)
name = "*unknown*";
else
@@ -3265,8 +3336,9 @@ _bfd_x86_elf_link_report_tls_transition_error
info->callbacks->einfo
/* xgettext:c-format */
(_("%pB(%pA+0x%v): relocation %s against `%s' must be used "
- "in indirect CALL only\n"),
- abfd, asect, rel->r_offset, from_reloc_name, name);
+ "in indirect CALL with %s register only\n"),
+ abfd, asect, rel->r_offset, from_reloc_name, name,
+ htab->ax_register);
break;
case elf_x86_tls_error_lea:
@@ -4759,7 +4831,18 @@ _bfd_x86_elf_link_setup_gnu_properties
htab->plt_second_sframe = sec;
}
- /* FIXME - add later for plt_got. */
+
+ /* .plt.got. */
+ if (htab->plt_got != NULL)
+ {
+ sec = bfd_make_section_anyway_with_flags (dynobj,
+ ".sframe",
+ flags);
+ if (sec == NULL)
+ info->callbacks->einfo (_("%F%P: failed to create PLT GOT .sframe section\n"));
+
+ htab->plt_got_sframe = sec;
+ }
}
}
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index 5eef7b0..cd26e8f 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -401,6 +401,10 @@ struct elf_x86_sframe_plt
unsigned int sec_pltn_entry_size;
unsigned int sec_pltn_num_fres;
const sframe_frame_row_entry *sec_pltn_fres[SFRAME_PLTN_MAX_NUM_FRES];
+
+ unsigned int plt_got_entry_size;
+ unsigned int plt_got_num_fres;
+ const sframe_frame_row_entry *plt_got_fres[SFRAME_PLTN_MAX_NUM_FRES];
};
struct elf_x86_lazy_plt_layout
@@ -606,6 +610,8 @@ struct elf_x86_link_hash_table
asection *plt_sframe;
sframe_encoder_ctx *plt_second_cfe_ctx;
asection *plt_second_sframe;
+ sframe_encoder_ctx *plt_got_cfe_ctx;
+ asection *plt_got_sframe;
/* Parameters describing PLT generation, lazy or non-lazy. */
struct elf_x86_plt_layout plt;
@@ -687,6 +693,7 @@ struct elf_x86_link_hash_table
const char *dynamic_interpreter;
const char *tls_get_addr;
const char *relative_r_name;
+ const char *ax_register;
void (*elf_append_reloc) (bfd *, asection *, Elf_Internal_Rela *);
void (*elf_write_addend) (bfd *, uint64_t, void *);
void (*elf_write_addend_in_got) (bfd *, uint64_t, void *);
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index f7f5773..950d797 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -889,22 +889,6 @@ _bfd_alloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
return NULL;
}
-#ifdef USE_MMAP
-extern void *_bfd_mmap_readonly_persistent
- (bfd *, size_t) ATTRIBUTE_HIDDEN;
-extern void *_bfd_mmap_readonly_temporary
- (bfd *, size_t, void **, size_t *) ATTRIBUTE_HIDDEN;
-extern void _bfd_munmap_readonly_temporary
- (void *, size_t) ATTRIBUTE_HIDDEN;
-#else
-#define _bfd_mmap_readonly_persistent(abfd, rsize) \
- _bfd_alloc_and_read (abfd, rsize, rsize)
-#define _bfd_munmap_readonly_temporary(ptr, rsize) free (ptr)
-#endif
-
-extern bool _bfd_mmap_read_temporary
- (void **, size_t *, void **, bfd *, bool) ATTRIBUTE_HIDDEN;
-
static inline void *
_bfd_malloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
{
@@ -928,14 +912,34 @@ _bfd_malloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
return NULL;
}
-#ifndef USE_MMAP
+#ifdef USE_MMAP
+extern void *_bfd_mmap_persistent
+ (bfd *, size_t) ATTRIBUTE_HIDDEN;
+extern void *_bfd_mmap_temporary
+ (bfd *, size_t, void **, size_t *) ATTRIBUTE_HIDDEN;
+extern void _bfd_munmap_temporary
+ (void *, size_t) ATTRIBUTE_HIDDEN;
+#else
+static inline void *
+_bfd_mmap_persistent (bfd *abfd, size_t rsize)
+{
+ return _bfd_alloc_and_read (abfd, rsize, rsize);
+}
static inline void *
-_bfd_mmap_readonly_temporary (bfd *abfd, size_t rsize, void **map_addr,
- size_t *map_size)
+_bfd_mmap_temporary (bfd *abfd, size_t rsize, void **map_addr,
+ size_t *map_size)
{
void *mem = _bfd_malloc_and_read (abfd, rsize, rsize);
*map_addr = mem;
*map_size = rsize;
return mem;
}
+static inline void
+_bfd_munmap_temporary (void *ptr, size_t rsize ATTRIBUTE_UNUSED)
+{
+ free (ptr);
+}
#endif
+
+extern bool _bfd_mmap_read_temporary
+ (void **, size_t *, void **, bfd *, bool) ATTRIBUTE_HIDDEN;
diff --git a/bfd/libbfd.c b/bfd/libbfd.c
index 5386847..4ab5bf4 100644
--- a/bfd/libbfd.c
+++ b/bfd/libbfd.c
@@ -1064,13 +1064,12 @@ bfd_allocate_mmapped_page (bfd *abfd, struct bfd_mmapped_entry **entry)
return mmapped;
}
-/* Mmap a memory region of RSIZE bytes with PROT at the current offset.
+/* Mmap a memory region of RSIZE bytes at the current file offset.
Return mmap address and size in MAP_ADDR and MAP_SIZE. Return NULL
on invalid input and MAP_FAILED for mmap failure. */
static void *
-bfd_mmap_local (bfd *abfd, size_t rsize, int prot, void **map_addr,
- size_t *map_size)
+bfd_mmap_local (bfd *abfd, size_t rsize, void **map_addr, size_t *map_size)
{
/* We mmap on the underlying file. In an archive it might be nice
to limit RSIZE to the element size, but that can be fuzzed and
@@ -1092,18 +1091,18 @@ bfd_mmap_local (bfd *abfd, size_t rsize, int prot, void **map_addr,
}
void *mem;
- mem = bfd_mmap (abfd, NULL, rsize, prot, MAP_PRIVATE, offset,
- map_addr, map_size);
+ mem = bfd_mmap (abfd, NULL, rsize, PROT_READ | PROT_WRITE, MAP_PRIVATE,
+ offset, map_addr, map_size);
return mem;
}
-/* Mmap a readonly memory region of RSIZE bytes at the current offset.
+/* Mmap a memory region of RSIZE bytes at the current offset.
Return mmap address and size in MAP_ADDR and MAP_SIZE. Return NULL
on invalid input and MAP_FAILED for mmap failure. */
void *
-_bfd_mmap_readonly_temporary (bfd *abfd, size_t rsize, void **map_addr,
- size_t *map_size)
+_bfd_mmap_temporary (bfd *abfd, size_t rsize, void **map_addr,
+ size_t *map_size)
{
/* Use mmap only if section size >= the minimum mmap section size. */
if (rsize < _bfd_minimum_mmap_size)
@@ -1116,17 +1115,17 @@ _bfd_mmap_readonly_temporary (bfd *abfd, size_t rsize, void **map_addr,
return mem;
}
- return bfd_mmap_local (abfd, rsize, PROT_READ, map_addr, map_size);
+ return bfd_mmap_local (abfd, rsize, map_addr, map_size);
}
/* Munmap RSIZE bytes at PTR. */
void
-_bfd_munmap_readonly_temporary (void *ptr, size_t rsize)
+_bfd_munmap_temporary (void *ptr, size_t rsize)
{
- /* NB: Since _bfd_munmap_readonly_temporary is called like free, PTR
- may be NULL. Otherwise, PTR and RSIZE must be valid. If RSIZE is
- 0, _bfd_malloc_and_read is called. */
+ /* NB: Since _bfd_munmap_temporary is called like free, PTR may be
+ NULL. Otherwise, PTR and RSIZE must be valid. If RSIZE is 0,
+ free is called. */
if (ptr == NULL)
return;
if (rsize != 0)
@@ -1138,11 +1137,11 @@ _bfd_munmap_readonly_temporary (void *ptr, size_t rsize)
free (ptr);
}
-/* Mmap a readonly memory region of RSIZE bytes at the current offset.
+/* Mmap a memory region of RSIZE bytes at the current offset.
Return NULL on invalid input or mmap failure. */
void *
-_bfd_mmap_readonly_persistent (bfd *abfd, size_t rsize)
+_bfd_mmap_persistent (bfd *abfd, size_t rsize)
{
/* Use mmap only if section size >= the minimum mmap section size. */
if (rsize < _bfd_minimum_mmap_size)
@@ -1150,7 +1149,7 @@ _bfd_mmap_readonly_persistent (bfd *abfd, size_t rsize)
void *mem, *map_addr;
size_t map_size;
- mem = bfd_mmap_local (abfd, rsize, PROT_READ, &map_addr, &map_size);
+ mem = bfd_mmap_local (abfd, rsize, &map_addr, &map_size);
if (mem == NULL)
return mem;
if (mem == MAP_FAILED)
@@ -1213,9 +1212,7 @@ _bfd_mmap_read_temporary (void **data_p, size_t *size_p,
&& (abfd->flags & BFD_PLUGIN) == 0);
if (use_mmmap)
{
- void *mmaped = _bfd_mmap_readonly_temporary (abfd, size,
- mmap_base,
- size_p);
+ void *mmaped = _bfd_mmap_temporary (abfd, size, mmap_base, size_p);
/* MAP_FAILED is returned when called from GDB on an object with
opncls_iovec. Use bfd_read in this case. */
if (mmaped != MAP_FAILED)
@@ -1234,8 +1231,7 @@ _bfd_mmap_read_temporary (void **data_p, size_t *size_p,
if (data == NULL)
return false;
*data_p = data;
- /* NB: _bfd_munmap_readonly_temporary will free *MMAP_BASE if
- *SIZE_P == 0. */
+ /* NB: _bfd_munmap_temporary will free *MMAP_BASE if *SIZE_P == 0. */
*mmap_base = data;
}
else
@@ -1302,12 +1298,9 @@ _bfd_generic_get_section_contents (bfd *abfd,
|| bfd_get_flavour (abfd) != bfd_target_elf_flavour)
abort ();
- int prot = ((section->reloc_count == 0)
- ? PROT_READ : PROT_READ | PROT_WRITE);
-
- location = bfd_mmap_local
- (abfd, count, prot, &elf_section_data (section)->contents_addr,
- &elf_section_data (section)->contents_size);
+ location = bfd_mmap_local (abfd, count,
+ &elf_section_data (section)->contents_addr,
+ &elf_section_data (section)->contents_size);
if (location == NULL)
return false;
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 5e8ed9e..5da7541 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -895,22 +895,6 @@ _bfd_alloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
return NULL;
}
-#ifdef USE_MMAP
-extern void *_bfd_mmap_readonly_persistent
- (bfd *, size_t) ATTRIBUTE_HIDDEN;
-extern void *_bfd_mmap_readonly_temporary
- (bfd *, size_t, void **, size_t *) ATTRIBUTE_HIDDEN;
-extern void _bfd_munmap_readonly_temporary
- (void *, size_t) ATTRIBUTE_HIDDEN;
-#else
-#define _bfd_mmap_readonly_persistent(abfd, rsize) \
- _bfd_alloc_and_read (abfd, rsize, rsize)
-#define _bfd_munmap_readonly_temporary(ptr, rsize) free (ptr)
-#endif
-
-extern bool _bfd_mmap_read_temporary
- (void **, size_t *, void **, bfd *, bool) ATTRIBUTE_HIDDEN;
-
static inline void *
_bfd_malloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
{
@@ -934,17 +918,37 @@ _bfd_malloc_and_read (bfd *abfd, bfd_size_type asize, bfd_size_type rsize)
return NULL;
}
-#ifndef USE_MMAP
+#ifdef USE_MMAP
+extern void *_bfd_mmap_persistent
+ (bfd *, size_t) ATTRIBUTE_HIDDEN;
+extern void *_bfd_mmap_temporary
+ (bfd *, size_t, void **, size_t *) ATTRIBUTE_HIDDEN;
+extern void _bfd_munmap_temporary
+ (void *, size_t) ATTRIBUTE_HIDDEN;
+#else
+static inline void *
+_bfd_mmap_persistent (bfd *abfd, size_t rsize)
+{
+ return _bfd_alloc_and_read (abfd, rsize, rsize);
+}
static inline void *
-_bfd_mmap_readonly_temporary (bfd *abfd, size_t rsize, void **map_addr,
- size_t *map_size)
+_bfd_mmap_temporary (bfd *abfd, size_t rsize, void **map_addr,
+ size_t *map_size)
{
void *mem = _bfd_malloc_and_read (abfd, rsize, rsize);
*map_addr = mem;
*map_size = rsize;
return mem;
}
+static inline void
+_bfd_munmap_temporary (void *ptr, size_t rsize ATTRIBUTE_UNUSED)
+{
+ free (ptr);
+}
#endif
+
+extern bool _bfd_mmap_read_temporary
+ (void **, size_t *, void **, bfd *, bool) ATTRIBUTE_HIDDEN;
/* Extracted from libbfd.c. */
void *bfd_malloc (bfd_size_type /*size*/) ATTRIBUTE_HIDDEN;
diff --git a/bfd/merge.c b/bfd/merge.c
index 5c8e69b..a4b928d 100644
--- a/bfd/merge.c
+++ b/bfd/merge.c
@@ -73,8 +73,6 @@ struct sec_merge_hash_entry
struct sec_merge_hash
{
struct bfd_hash_table table;
- /* Next available index. */
- bfd_size_type size;
/* First entity in the SEC_MERGE sections of this type. */
struct sec_merge_hash_entry *first;
/* Last entity in the SEC_MERGE sections of this type. */
@@ -94,10 +92,6 @@ struct sec_merge_hash
struct sec_merge_hash_entry **values;
};
-/* True when given NEWCOUNT and NBUCKETS indicate that the hash table needs
- resizing. */
-#define NEEDS_RESIZE(newcount, nbuckets) ((newcount) > (nbuckets) / 3 * 2)
-
struct sec_merge_sec_info;
/* Information per merged blob. This is the unit of merging and is
@@ -163,62 +157,75 @@ struct sec_merge_sec_info
};
+/* True when COUNT+ADDED and NBUCKETS indicate that the hash table
+ needs resizing. */
+
+static inline bool
+needs_resize (unsigned int count, unsigned int added, unsigned int nbuckets)
+{
+ /* This doesn't consider the possibility of "count" + "added"
+ overflowing, because that can't happen given current usage. If
+ code calling this function changes then that assumption may no
+ longer be correct. Currently "added" is always 1 and "nbuckets"
+ is limited to 0x80000000. We'll attempt and fail resizing at
+ "count" of 0x55555555. */
+ return count + added > nbuckets / 3 * 2;
+}
+
/* Given a merge hash table TABLE and a number of entries to be
- ADDED, possibly resize the table for this to fit without further
- resizing. */
+ ADDED, resize the table for this to fit.
+ Returns false if that can't be done for whatever reason. */
static bool
-sec_merge_maybe_resize (struct sec_merge_hash *table, unsigned added)
+sec_merge_resize (struct sec_merge_hash *table, unsigned added)
{
struct bfd_hash_table *bfdtab = &table->table;
- if (NEEDS_RESIZE (bfdtab->count + added, table->nbuckets))
- {
- unsigned i;
- unsigned long newnb = table->nbuckets * 2;
- struct sec_merge_hash_entry **newv;
- uint64_t *newl;
- unsigned long alloc;
-
- while (NEEDS_RESIZE (bfdtab->count + added, newnb))
- {
- newnb *= 2;
- if (!newnb)
- return false;
- }
+ unsigned i;
+ unsigned long newnb = table->nbuckets;
+ struct sec_merge_hash_entry **newv;
+ uint64_t *newl;
+ unsigned long alloc;
- alloc = newnb * sizeof (newl[0]);
- if (alloc / sizeof (newl[0]) != newnb)
- return false;
- newl = objalloc_alloc ((struct objalloc *) table->table.memory, alloc);
- if (newl == NULL)
- return false;
- memset (newl, 0, alloc);
- alloc = newnb * sizeof (newv[0]);
- if (alloc / sizeof (newv[0]) != newnb)
- return false;
- newv = objalloc_alloc ((struct objalloc *) table->table.memory, alloc);
- if (newv == NULL)
+ do
+ {
+ if (newnb >> (8 * sizeof(mapofs_type) - 1))
return false;
- memset (newv, 0, alloc);
+ newnb *= 2;
+ }
+ while (needs_resize (bfdtab->count, added, newnb));
- for (i = 0; i < table->nbuckets; i++)
+ alloc = newnb * sizeof (newl[0]);
+ if (alloc / sizeof (newl[0]) != newnb)
+ return false;
+ newl = objalloc_alloc ((struct objalloc *) table->table.memory, alloc);
+ if (newl == NULL)
+ return false;
+ memset (newl, 0, alloc);
+ alloc = newnb * sizeof (newv[0]);
+ if (alloc / sizeof (newv[0]) != newnb)
+ return false;
+ newv = objalloc_alloc ((struct objalloc *) table->table.memory, alloc);
+ if (newv == NULL)
+ return false;
+ memset (newv, 0, alloc);
+
+ for (i = 0; i < table->nbuckets; i++)
+ {
+ struct sec_merge_hash_entry *v = table->values[i];
+ if (v)
{
- struct sec_merge_hash_entry *v = table->values[i];
- if (v)
- {
- uint32_t thishash = table->key_lens[i] >> 32;
- unsigned idx = thishash & (newnb - 1);
- while (newv[idx])
- idx = (idx + 1) & (newnb - 1);
- newl[idx] = table->key_lens[i];
- newv[idx] = v;
- }
+ uint32_t thishash = table->key_lens[i] >> 32;
+ unsigned idx = thishash & (newnb - 1);
+ while (newv[idx])
+ idx = (idx + 1) & (newnb - 1);
+ newl[idx] = table->key_lens[i];
+ newv[idx] = v;
}
-
- table->key_lens = newl;
- table->values = newv;
- table->nbuckets = newnb;
}
+
+ table->key_lens = newl;
+ table->values = newv;
+ table->nbuckets = newnb;
return true;
}
@@ -243,8 +250,23 @@ sec_merge_hash_insert (struct sec_merge_hash *table,
hashp->alignment = 0;
hashp->u.suffix = NULL;
hashp->next = NULL;
- // We must not need resizing, otherwise the estimation was wrong
- BFD_ASSERT (!NEEDS_RESIZE (bfdtab->count + 1, table->nbuckets));
+
+ if (needs_resize (bfdtab->count, 1, table->nbuckets))
+ {
+ if (!sec_merge_resize (table, 1))
+ return NULL;
+ uint64_t *key_lens = table->key_lens;
+ unsigned int nbuckets = table->nbuckets;
+ _index = hash & (nbuckets - 1);
+ while (1)
+ {
+ uint64_t candlen = key_lens[_index];
+ if (!(candlen & (uint32_t)-1))
+ break;
+ _index = (_index + 1) & (nbuckets - 1);
+ }
+ }
+
bfdtab->count++;
table->key_lens[_index] = (hash << 32) | (uint32_t)len;
table->values[_index] = hashp;
@@ -406,8 +428,6 @@ sec_merge_hash_lookup (struct sec_merge_hash *table, const char *string,
return NULL;
hashp->alignment = alignment;
- table->size++;
- BFD_ASSERT (table->size == table->table.count);
if (table->first == NULL)
table->first = hashp;
else
@@ -435,7 +455,6 @@ sec_merge_init (unsigned int entsize, bool strings)
return NULL;
}
- table->size = 0;
table->first = NULL;
table->last = NULL;
table->entsize = entsize;
@@ -698,7 +717,9 @@ _bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec,
}
/* Record one whole input section (described by SECINFO) into the hash table
- SINFO. */
+ SINFO. Returns true when section is completely recorded, and false when
+ it wasn't recorded but we can continue (e.g. by simply not deduplicating
+ this section). */
static bool
record_section (struct sec_merge_info *sinfo,
@@ -732,15 +753,6 @@ record_section (struct sec_merge_info *sinfo,
/* Now populate the hash table and offset mapping. */
- /* Presize the hash table for what we're going to add. We overestimate
- quite a bit, but if it turns out to be too much then other sections
- merged into this area will make use of that as well. */
- if (!sec_merge_maybe_resize (sinfo->htab, 1 + sec->size / 2))
- {
- bfd_set_error (bfd_error_no_memory);
- goto error_return;
- }
-
/* Walk through the contents, calculate hashes and length of all
blobs (strings or fixed-size entries) we find and fill the
hash and offset tables. */
@@ -793,8 +805,6 @@ record_section (struct sec_merge_info *sinfo,
error_return:
free (contents);
contents = NULL;
- for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
- *secinfo->psecinfo = NULL;
return false;
}
@@ -876,7 +886,7 @@ merge_strings (struct sec_merge_info *sinfo)
unsigned int alignment = 0;
/* Now sort the strings */
- amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *);
+ amt = sinfo->htab->table.count * sizeof (struct sec_merge_hash_entry *);
array = (struct sec_merge_hash_entry **) bfd_malloc (amt);
if (array == NULL)
return NULL;
@@ -896,10 +906,10 @@ merge_strings (struct sec_merge_info *sinfo)
}
}
- sinfo->htab->size = a - array;
- if (sinfo->htab->size != 0)
+ size_t asize = a - array;
+ if (asize != 0)
{
- qsort (array, (size_t) sinfo->htab->size,
+ qsort (array, asize,
sizeof (struct sec_merge_hash_entry *),
(alignment != (unsigned) -1 && alignment > sinfo->htab->entsize
? strrevcmp_align : strrevcmp));
@@ -983,24 +993,20 @@ _bfd_merge_sections (bfd *abfd,
/* Record the sections into the hash table. */
align = 1;
for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
- if (secinfo->sec->flags & SEC_EXCLUDE)
+ if (secinfo->sec->flags & SEC_EXCLUDE
+ || !record_section (sinfo, secinfo))
{
*secinfo->psecinfo = NULL;
if (remove_hook)
(*remove_hook) (abfd, secinfo->sec);
}
- else
+ else if (align)
{
- if (!record_section (sinfo, secinfo))
- return false;
- if (align)
- {
- unsigned int opb = bfd_octets_per_byte (abfd, secinfo->sec);
-
- align = (bfd_size_type) 1 << secinfo->sec->alignment_power;
- if (((secinfo->sec->size / opb) & (align - 1)) != 0)
- align = 0;
- }
+ unsigned int opb = bfd_octets_per_byte (abfd, secinfo->sec);
+
+ align = (bfd_size_type) 1 << secinfo->sec->alignment_power;
+ if (((secinfo->sec->size / opb) & (align - 1)) != 0)
+ align = 0;
}
if (sinfo->htab->first == NULL)
@@ -1043,7 +1049,8 @@ _bfd_merge_sections (bfd *abfd,
/* Finally remove all input sections which have not made it into
the hash table at all. */
for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
- if (secinfo->first_str == NULL)
+ if (secinfo->first_str == NULL
+ && secinfo->sec->sec_info_type == SEC_INFO_TYPE_MERGE)
secinfo->sec->flags |= SEC_EXCLUDE | SEC_KEEP;
}
diff --git a/bfd/pdb.c b/bfd/pdb.c
index b0455b0..340cda6 100644
--- a/bfd/pdb.c
+++ b/bfd/pdb.c
@@ -412,7 +412,8 @@ pdb_allocate_block (uint32_t *num_blocks, uint32_t block_size)
static bool
pdb_write_directory (bfd *abfd, uint32_t block_size, uint32_t num_files,
- uint32_t block_map_addr, uint32_t * num_blocks)
+ uint32_t block_map_addr, uint32_t * num_blocks,
+ uint32_t *stream0_start)
{
char tmp[sizeof (uint32_t)];
uint32_t block, left, block_map_off;
@@ -561,6 +562,9 @@ pdb_write_directory (bfd *abfd, uint32_t block_size, uint32_t num_files,
return false;
}
+ if (arelt == abfd->archive_head && i == 0)
+ *stream0_start = file_block;
+
left -= sizeof (uint32_t);
/* Read file contents into buffer. */
@@ -617,7 +621,8 @@ pdb_write_directory (bfd *abfd, uint32_t block_size, uint32_t num_files,
}
static bool
-pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks)
+pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks,
+ uint32_t stream0_start)
{
char *buf;
uint32_t num_intervals = (num_blocks + block_size - 1) / block_size;
@@ -626,8 +631,6 @@ pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks)
if (!buf)
return false;
- num_blocks--; /* Superblock not included. */
-
for (uint32_t i = 0; i < num_intervals; i++)
{
if (bfd_seek (abfd, ((i * block_size) + 1) * block_size, SEEK_SET))
@@ -636,8 +639,8 @@ pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks)
return false;
}
- /* All of our blocks are contiguous, making our free block map simple.
- 0 = used, 1 = free. */
+ /* All of our blocks are contiguous, making our free block map
+ relatively simple. 0 = used, 1 = free. */
if (num_blocks >= 8)
memset (buf, 0,
@@ -650,7 +653,7 @@ pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks)
if (num_blocks % 8)
{
- buf[off] = (1 << (8 - (num_blocks % 8))) - 1;
+ buf[off] = 256 - (1 << (num_blocks % 8));
off++;
}
@@ -658,6 +661,40 @@ pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks)
memset (buf + off, 0xff, block_size - off);
}
+ /* Mark the blocks allocated to stream 0 as free. This is because stream
+ 0 is intended to be used for the previous MSF directory, to allow
+ atomic updates. This doesn't apply to us, as we rewrite the whole
+ file whenever any change is made. */
+
+ if (i == 0 && abfd->archive_head)
+ {
+ bfd *arelt = abfd->archive_head;
+ uint32_t stream0_blocks =
+ (bfd_get_size (arelt) + block_size - 1) / block_size;
+
+ if (stream0_start % 8)
+ {
+ unsigned int high_bit;
+
+ high_bit = (stream0_start % 8) + stream0_blocks;
+ if (high_bit > 8)
+ high_bit = 8;
+
+ buf[stream0_start / 8] |=
+ (1 << high_bit) - (1 << (stream0_start % 8));
+
+ stream0_blocks -= high_bit - (stream0_start % 8);
+ stream0_start += high_bit - (stream0_start % 8);
+ }
+
+ memset (buf + (stream0_start / 8), 0xff, stream0_blocks / 8);
+ stream0_start += stream0_blocks / 8;
+ stream0_blocks %= 8;
+
+ if (stream0_blocks > 0)
+ buf[stream0_start / 8] |= (1 << stream0_blocks) - 1;
+ }
+
if (num_blocks < block_size * 8)
num_blocks = 0;
else
@@ -681,6 +718,7 @@ pdb_write_contents (bfd *abfd)
uint32_t num_blocks;
uint32_t num_files = 0;
uint32_t num_directory_bytes = sizeof (uint32_t);
+ uint32_t stream0_start = 0;
bfd *arelt;
if (bfd_write (pdb_magic, sizeof (pdb_magic), abfd) != sizeof (pdb_magic))
@@ -735,10 +773,11 @@ pdb_write_contents (bfd *abfd)
return false;
if (!pdb_write_directory
- (abfd, block_size, num_files, block_map_addr, &num_blocks))
+ (abfd, block_size, num_files, block_map_addr, &num_blocks,
+ &stream0_start))
return false;
- if (!pdb_write_bitmap (abfd, block_size, num_blocks))
+ if (!pdb_write_bitmap (abfd, block_size, num_blocks, stream0_start))
return false;
/* Write num_blocks now we know it. */
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 51b567e..c09d16e 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -699,8 +699,8 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
for the image size. */
if (coff_section_data (abfd, sec) != NULL
&& pei_section_data (abfd, sec) != NULL)
- isize = (sec->vma - extra->ImageBase
- + SA (FA (pei_section_data (abfd, sec)->virt_size)));
+ isize = SA (sec->vma - extra->ImageBase
+ + FA (pei_section_data (abfd, sec)->virt_size));
}
aouthdr_in->dsize = dsize;
diff --git a/bfd/pef.c b/bfd/pef.c
index f330b92..2d2f559 100644
--- a/bfd/pef.c
+++ b/bfd/pef.c
@@ -210,16 +210,18 @@ bfd_pef_print_symbol (bfd *abfd,
bfd_print_symbol_type how)
{
FILE *file = (FILE *) afile;
+ const char *symname = (symbol->name != bfd_symbol_error_name
+ ? symbol->name : _("<corrupt>"));
switch (how)
{
case bfd_print_symbol_name:
- fprintf (file, "%s", symbol->name);
+ fprintf (file, "%s", symname);
break;
default:
bfd_print_symbol_vandf (abfd, (void *) file, symbol);
- fprintf (file, " %-5s %s", symbol->section->name, symbol->name);
- if (startswith (symbol->name, "__traceback_"))
+ fprintf (file, " %-5s %s", symbol->section->name, symname);
+ if (startswith (symname, "__traceback_"))
{
unsigned char *buf;
size_t offset = symbol->value + 4;
diff --git a/bfd/peicode.h b/bfd/peicode.h
index 11807ef..1a084fd 100644
--- a/bfd/peicode.h
+++ b/bfd/peicode.h
@@ -127,7 +127,7 @@ bfd_cleanup coff_real_object_p
#ifndef NO_COFF_RELOCS
static void
-coff_swap_reloc_in (bfd * abfd, void * src, void * dst)
+coff_swap_reloc_in (bfd *abfd, void *src, void *dst)
{
RELOC *reloc_src = (RELOC *) src;
struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
@@ -141,7 +141,7 @@ coff_swap_reloc_in (bfd * abfd, void * src, void * dst)
}
static unsigned int
-coff_swap_reloc_out (bfd * abfd, void * src, void * dst)
+coff_swap_reloc_out (bfd *abfd, void *src, void *dst)
{
struct internal_reloc *reloc_src = (struct internal_reloc *) src;
struct external_reloc *reloc_dst = (struct external_reloc *) dst;
@@ -166,7 +166,7 @@ coff_swap_reloc_out (bfd * abfd, void * src, void * dst)
#endif
static void
-coff_swap_filehdr_in (bfd * abfd, void * src, void * dst)
+coff_swap_filehdr_in (bfd *abfd, void *src, void *dst)
{
FILHDR *filehdr_src = (FILHDR *) src;
struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst;
@@ -202,7 +202,7 @@ coff_swap_filehdr_in (bfd * abfd, void * src, void * dst)
#endif
static void
-coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
+coff_swap_scnhdr_in (bfd *abfd, void *ext, void *in)
{
SCNHDR *scnhdr_ext = (SCNHDR *) ext;
struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
@@ -233,7 +233,8 @@ coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
{
scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase;
/* Do not cut upper 32-bits for 64-bit vma. */
-#if !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRiscV64)
+#if (!defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) \
+ && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRiscV64))
scnhdr_int->s_vaddr &= 0xffffffff;
#endif
}
@@ -256,7 +257,7 @@ coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
}
static bool
-pe_mkobject (bfd * abfd)
+pe_mkobject (bfd *abfd)
{
/* Some x86 code followed by an ascii string. */
static const char default_dos_message[64] = {
@@ -290,9 +291,9 @@ pe_mkobject (bfd * abfd)
/* Create the COFF backend specific information. */
static void *
-pe_mkobject_hook (bfd * abfd,
- void * filehdr,
- void * aouthdr ATTRIBUTE_UNUSED)
+pe_mkobject_hook (bfd *abfd,
+ void *filehdr,
+ void *aouthdr ATTRIBUTE_UNUSED)
{
struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
pe_data_type *pe;
@@ -344,7 +345,7 @@ pe_mkobject_hook (bfd * abfd,
}
static bool
-pe_print_private_bfd_data (bfd *abfd, void * vfile)
+pe_print_private_bfd_data (bfd *abfd, void *vfile)
{
FILE *file = (FILE *) vfile;
@@ -418,17 +419,17 @@ pe_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
#define NUM_ILF_SECTIONS 6
#define NUM_ILF_SYMS (2 + NUM_ILF_SECTIONS)
-#define SIZEOF_ILF_SYMS (NUM_ILF_SYMS * sizeof (* vars.sym_cache))
-#define SIZEOF_ILF_SYM_TABLE (NUM_ILF_SYMS * sizeof (* vars.sym_table))
-#define SIZEOF_ILF_NATIVE_SYMS (NUM_ILF_SYMS * sizeof (* vars.native_syms))
-#define SIZEOF_ILF_SYM_PTR_TABLE (NUM_ILF_SYMS * sizeof (* vars.sym_ptr_table))
-#define SIZEOF_ILF_EXT_SYMS (NUM_ILF_SYMS * sizeof (* vars.esym_table))
-#define SIZEOF_ILF_RELOCS (NUM_ILF_RELOCS * sizeof (* vars.reltab))
-#define SIZEOF_ILF_INT_RELOCS (NUM_ILF_RELOCS * sizeof (* vars.int_reltab))
+#define SIZEOF_ILF_SYMS (NUM_ILF_SYMS * sizeof (*vars.sym_cache))
+#define SIZEOF_ILF_SYM_TABLE (NUM_ILF_SYMS * sizeof (*vars.sym_table))
+#define SIZEOF_ILF_NATIVE_SYMS (NUM_ILF_SYMS * sizeof (*vars.native_syms))
+#define SIZEOF_ILF_SYM_PTR_TABLE (NUM_ILF_SYMS * sizeof (*vars.sym_ptr_table))
+#define SIZEOF_ILF_EXT_SYMS (NUM_ILF_SYMS * sizeof (*vars.esym_table))
+#define SIZEOF_ILF_RELOCS (NUM_ILF_RELOCS * sizeof (*vars.reltab))
+#define SIZEOF_ILF_INT_RELOCS (NUM_ILF_RELOCS * sizeof (*vars.int_reltab))
#define SIZEOF_ILF_STRINGS (strlen (symbol_name) * 2 + 8 \
- + 21 + strlen (source_dll) \
- + NUM_ILF_SECTIONS * 9 \
- + STRING_SIZE_SIZE)
+ + 21 + strlen (source_dll) \
+ + NUM_ILF_SECTIONS * 9 \
+ + STRING_SIZE_SIZE)
#define SIZEOF_IDATA2 (5 * 4)
/* For PEx64 idata4 & 5 have thumb size of 8 bytes. */
@@ -440,9 +441,10 @@ pe_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
#define SIZEOF_IDATA5 (1 * 4)
#endif
-#define SIZEOF_IDATA6 (2 + strlen (symbol_name) + 1 + 1)
+#define SIZEOF_IDATA6 (2 + strlen (import_name) + 1 + 1)
#define SIZEOF_IDATA7 (strlen (source_dll) + 1 + 1)
-#define SIZEOF_ILF_SECTIONS (NUM_ILF_SECTIONS * sizeof (struct coff_section_tdata))
+#define SIZEOF_ILF_SECTIONS (NUM_ILF_SECTIONS \
+ * sizeof (struct coff_section_tdata))
#define ILF_DATA_SIZE \
+ SIZEOF_ILF_SYMS \
@@ -470,8 +472,8 @@ pe_ILF_make_a_symbol_reloc (pe_ILF_vars * vars,
struct bfd_symbol ** sym,
unsigned int sym_index)
{
- arelent * entry;
- struct internal_reloc * internal;
+ arelent *entry;
+ struct internal_reloc *internal;
entry = vars->reltab + vars->relcount;
internal = vars->int_reltab + vars->relcount;
@@ -505,8 +507,8 @@ pe_ILF_make_a_reloc (pe_ILF_vars * vars,
/* Move the queued relocs into the given section. */
static void
-pe_ILF_save_relocs (pe_ILF_vars * vars,
- asection_ptr sec)
+pe_ILF_save_relocs (pe_ILF_vars *vars,
+ asection_ptr sec)
{
/* Make sure that there is somewhere to store the internal relocs. */
if (coff_section_data (vars->abfd, sec) == NULL)
@@ -535,9 +537,9 @@ pe_ILF_make_a_symbol (pe_ILF_vars * vars,
asection_ptr section,
flagword extra_flags)
{
- coff_symbol_type * sym;
- combined_entry_type * ent;
- SYMENT * esym;
+ coff_symbol_type *sym;
+ combined_entry_type *ent;
+ SYMENT *esym;
unsigned short sclass;
if (extra_flags & BSF_LOCAL)
@@ -590,8 +592,8 @@ pe_ILF_make_a_symbol (pe_ILF_vars * vars,
sym->symbol.section = section;
sym->native = ent;
- * vars->table_ptr = vars->sym_index;
- * vars->sym_ptr_ptr = sym;
+ *vars->table_ptr = vars->sym_index;
+ *vars->sym_ptr_ptr = sym;
/* Adjust pointers for the next symbol. */
vars->sym_index ++;
@@ -792,7 +794,8 @@ pe_ILF_build_a_bfd (bfd * abfd,
char * symbol_name,
char * source_dll,
unsigned int ordinal,
- unsigned int types)
+ unsigned int types,
+ char * import_name)
{
bfd_byte * ptr;
pe_ILF_vars vars;
@@ -834,6 +837,17 @@ pe_ILF_build_a_bfd (bfd * abfd,
case IMPORT_NAME:
case IMPORT_NAME_NOPREFIX:
case IMPORT_NAME_UNDECORATE:
+ import_name = symbol_name;
+ break;
+
+ case IMPORT_NAME_EXPORTAS:
+ if (!import_name || !import_name[0])
+ {
+ _bfd_error_handler (_("%pB: missing import name for "
+ "IMPORT_NAME_EXPORTAS for %s"),
+ abfd, symbol_name);
+ return false;
+ }
break;
default:
@@ -922,8 +936,8 @@ pe_ILF_build_a_bfd (bfd * abfd,
Note we do not create a .idata$3 section as this is
created for us by the linker script. */
- id4 = pe_ILF_make_a_section (& vars, ".idata$4", SIZEOF_IDATA4, 0);
- id5 = pe_ILF_make_a_section (& vars, ".idata$5", SIZEOF_IDATA5, 0);
+ id4 = pe_ILF_make_a_section (&vars, ".idata$4", SIZEOF_IDATA4, 0);
+ id5 = pe_ILF_make_a_section (&vars, ".idata$5", SIZEOF_IDATA5, 0);
if (id4 == NULL || id5 == NULL)
goto error_return;
@@ -934,28 +948,29 @@ pe_ILF_build_a_bfd (bfd * abfd,
/* See PR 20907 for a reproducer. */
goto error_return;
-#if defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined (COFF_WITH_peRiscV64)
+#if (defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) \
+ || defined(COFF_WITH_peLoongArch64) || defined (COFF_WITH_peRiscV64))
((unsigned int *) id4->contents)[0] = ordinal;
((unsigned int *) id4->contents)[1] = 0x80000000;
((unsigned int *) id5->contents)[0] = ordinal;
((unsigned int *) id5->contents)[1] = 0x80000000;
#else
- * (unsigned int *) id4->contents = ordinal | 0x80000000;
- * (unsigned int *) id5->contents = ordinal | 0x80000000;
+ ((unsigned int *) id4->contents)[0] = ordinal | 0x80000000;
+ ((unsigned int *) id5->contents)[0] = ordinal | 0x80000000;
#endif
}
else
{
- char * symbol;
+ char *symbol;
unsigned int len;
/* Create .idata$6 - the Hint Name Table. */
- id6 = pe_ILF_make_a_section (& vars, ".idata$6", SIZEOF_IDATA6, 0);
+ id6 = pe_ILF_make_a_section (&vars, ".idata$6", SIZEOF_IDATA6, 0);
if (id6 == NULL)
goto error_return;
/* If necessary, trim the import symbol name. */
- symbol = symbol_name;
+ symbol = import_name;
/* As used by MS compiler, '_', '@', and '?' are alternative
forms of USER_LABEL_PREFIX, with '?' for c++ mangled names,
@@ -964,7 +979,8 @@ pe_ILF_build_a_bfd (bfd * abfd,
IMPORT_NAME_NOPREFIX and IMPORT_NAME_UNDECORATE as per the
PE COFF 6.0 spec (section 8.3, Import Name Type). */
- if (import_name_type != IMPORT_NAME)
+ if (import_name_type != IMPORT_NAME
+ && import_name_type != IMPORT_NAME_EXPORTAS)
{
char c = symbol[0];
@@ -1002,11 +1018,12 @@ pe_ILF_build_a_bfd (bfd * abfd,
}
/* Create an import symbol. */
- pe_ILF_make_a_symbol (& vars, "__imp_", symbol_name, id5, 0);
+ pe_ILF_make_a_symbol (&vars, "__imp_", symbol_name, id5, 0);
imp_sym = vars.sym_ptr_ptr - 1;
imp_index = vars.sym_index - 1;
- /* Create extra sections depending upon the type of import we are dealing with. */
+ /* Create extra sections depending upon the type of import we are
+ dealing with. */
switch (import_type)
{
int i;
@@ -1027,7 +1044,7 @@ pe_ILF_build_a_bfd (bfd * abfd,
abort ();
/* Create the .text section. */
- text = pe_ILF_make_a_section (& vars, ".text", jtab[i].size, SEC_CODE);
+ text = pe_ILF_make_a_section (&vars, ".text", jtab[i].size, SEC_CODE);
if (text == NULL)
goto error_return;
@@ -1061,7 +1078,7 @@ pe_ILF_build_a_bfd (bfd * abfd,
BFD_RELOC_32, (asymbol **) imp_sym,
imp_index);
- pe_ILF_save_relocs (& vars, text);
+ pe_ILF_save_relocs (&vars, text);
break;
case IMPORT_DATA:
@@ -1076,7 +1093,7 @@ pe_ILF_build_a_bfd (bfd * abfd,
switch (import_type)
{
case IMPORT_CODE:
- pe_ILF_make_a_symbol (& vars, "", symbol_name, text,
+ pe_ILF_make_a_symbol (&vars, "", symbol_name, text,
BSF_NOT_AT_END | BSF_FUNCTION);
break;
@@ -1093,30 +1110,31 @@ pe_ILF_build_a_bfd (bfd * abfd,
/* Create an import symbol for the DLL, without the .dll suffix. */
ptr = (bfd_byte *) strrchr (source_dll, '.');
if (ptr)
- * ptr = 0;
- pe_ILF_make_a_symbol (& vars, "__IMPORT_DESCRIPTOR_", source_dll, NULL, 0);
+ *ptr = 0;
+ pe_ILF_make_a_symbol (&vars, "__IMPORT_DESCRIPTOR_", source_dll, NULL, 0);
if (ptr)
- * ptr = '.';
+ *ptr = '.';
/* Initialise the bfd. */
- memset (& internal_f, 0, sizeof (internal_f));
+ memset (&internal_f, 0, sizeof (internal_f));
internal_f.f_magic = magic;
internal_f.f_symptr = 0;
internal_f.f_nsyms = 0;
internal_f.f_flags = F_AR32WR | F_LNNO; /* XXX is this correct ? */
- if ( ! bfd_set_start_address (abfd, (bfd_vma) 0)
- || ! bfd_coff_set_arch_mach_hook (abfd, & internal_f))
+ if (!bfd_set_start_address (abfd, (bfd_vma) 0)
+ || !bfd_coff_set_arch_mach_hook (abfd, &internal_f))
goto error_return;
- if (bfd_coff_mkobject_hook (abfd, (void *) & internal_f, NULL) == NULL)
+ if (bfd_coff_mkobject_hook (abfd, (void *) &internal_f, NULL) == NULL)
goto error_return;
obj_pe (abfd) = true;
#ifdef THUMBPEMAGIC
if (vars.magic == THUMBPEMAGIC)
- /* Stop some linker warnings about thumb code not supporting interworking. */
+ /* Stop some linker warnings about thumb code not supporting
+ interworking. */
coff_data (abfd)->flags |= F_INTERWORK | F_INTERWORK_SET;
#endif
@@ -1173,12 +1191,13 @@ pe_ILF_cleanup (bfd *abfd)
Decode the element and return the appropriate target. */
static bfd_cleanup
-pe_ILF_object_p (bfd * abfd)
+pe_ILF_object_p (bfd *abfd)
{
bfd_byte buffer[14];
bfd_byte * ptr;
char * symbol_name;
char * source_dll;
+ char * import_name;
unsigned int machine;
bfd_size_type size;
unsigned int ordinal;
@@ -1266,7 +1285,7 @@ pe_ILF_object_p (bfd * abfd)
{
extern const bfd_target TARGET_LITTLE_SYM;
- if (abfd->xvec == & TARGET_LITTLE_SYM)
+ if (abfd->xvec == &TARGET_LITTLE_SYM)
magic = THUMBPEMAGIC;
}
#endif
@@ -1340,9 +1359,24 @@ pe_ILF_object_p (bfd * abfd)
return NULL;
}
+ /* An ILF file may contain a third string, after source_dll; this is
+ used for IMPORT_NAME_EXPORTAS. We know from above that the whole
+ block of data is null terminated, ptr[size-1]==0, but we don't
+ know how many individual null terminated strings we have in there.
+
+ First find the end of source_dll. */
+ import_name = source_dll + strlen (source_dll) + 1;
+ if ((bfd_byte *) import_name >= ptr + size)
+ {
+ /* If this points at the end of the ptr+size block, we only had
+ two strings. */
+ import_name = NULL;
+ }
+
/* Now construct the bfd. */
if (! pe_ILF_build_a_bfd (abfd, magic, symbol_name,
- source_dll, ordinal, types))
+ source_dll, ordinal, types,
+ import_name))
{
bfd_release (abfd, ptr);
return NULL;
@@ -1424,12 +1458,14 @@ pe_bfd_read_buildid (bfd *abfd)
(file_ptr) idd.PointerToRawData,
idd.SizeOfData, cvinfo, NULL))
{
- struct bfd_build_id* build_id = bfd_alloc (abfd,
- sizeof (struct bfd_build_id) + cvinfo->SignatureLength);
+ struct bfd_build_id *build_id;
+ size_t bidlen = sizeof (*build_id) + cvinfo->SignatureLength;
+
+ build_id = bfd_alloc (abfd, bidlen);
if (build_id)
{
build_id->size = cvinfo->SignatureLength;
- memcpy(build_id->data, cvinfo->Signature,
+ memcpy(build_id->data, cvinfo->Signature,
cvinfo->SignatureLength);
abfd->build_id = build_id;
}
@@ -1442,7 +1478,7 @@ pe_bfd_read_buildid (bfd *abfd)
}
static bfd_cleanup
-pe_bfd_object_p (bfd * abfd)
+pe_bfd_object_p (bfd *abfd)
{
bfd_byte buffer[6];
struct external_DOS_hdr dos_hdr;
@@ -1527,7 +1563,7 @@ pe_bfd_object_p (bfd * abfd)
if (opt_hdr_size != 0)
{
bfd_size_type amt = opt_hdr_size;
- bfd_byte * opthdr;
+ bfd_byte *opthdr;
/* PR 17521 file: 230-131433-0.004. */
if (amt < sizeof (PEAOUTHDR))
@@ -1561,7 +1597,7 @@ pe_bfd_object_p (bfd * abfd)
|| a->SectionAlignment >= 0x80000000)
{
_bfd_error_handler (_("%pB: adjusting invalid SectionAlignment"),
- abfd);
+ abfd);
a->SectionAlignment &= -a->SectionAlignment;
if (a->SectionAlignment >= 0x80000000)
a->SectionAlignment = 0x40000000;
diff --git a/bfd/plugin.c b/bfd/plugin.c
index 026654f..de2137f 100644
--- a/bfd/plugin.c
+++ b/bfd/plugin.c
@@ -329,13 +329,23 @@ try_claim (bfd *abfd)
struct ld_plugin_input_file file;
file.handle = abfd;
- if (bfd_plugin_open_input (abfd, &file)
- && current_plugin->claim_file)
+ if (bfd_plugin_open_input (abfd, &file))
{
- current_plugin->claim_file (&file, &claimed);
- bfd_plugin_close_file_descriptor ((abfd->my_archive != NULL
- ? abfd : NULL),
- file.fd);
+ bool claim_file_called = false;
+ if (current_plugin->claim_file_v2)
+ {
+ current_plugin->claim_file_v2 (&file, &claimed, false);
+ claim_file_called = true;
+ }
+ else if (current_plugin->claim_file)
+ {
+ current_plugin->claim_file (&file, &claimed);
+ claim_file_called = true;
+ }
+ if (claim_file_called)
+ bfd_plugin_close_file_descriptor ((abfd->my_archive != NULL
+ ? abfd : NULL),
+ file.fd);
}
return claimed;
@@ -586,8 +596,12 @@ load_plugin (bfd *abfd)
static bfd_cleanup
bfd_plugin_object_p (bfd *abfd)
{
+ /* Since ld_plugin_object_p is called only for linker command-line input
+ objects, pass true to ld_plugin_object_p so that the same input IR
+ file won't be included twice if the LDPT_REGISTER_CLAIM_FILE_HOOK_V2
+ isn't used. */
if (ld_plugin_object_p)
- return ld_plugin_object_p (abfd, false);
+ return ld_plugin_object_p (abfd, true);
if (abfd->plugin_format == bfd_plugin_unknown && !load_plugin (abfd))
return NULL;
diff --git a/bfd/syms.c b/bfd/syms.c
index b370a33..68f0730 100644
--- a/bfd/syms.c
+++ b/bfd/syms.c
@@ -342,6 +342,11 @@ EXTERNAL
. const char *stab_name; {* String for stab type. *}
.} symbol_info;
.
+.{* An empty string that will not match the address of any other
+. symbol name, even unnamed local symbols which will also have empty
+. string names. This can be used to flag a symbol as corrupt if its
+. name uses an out of range string table index. *}
+.extern const char bfd_symbol_error_name[];
*/
#include "sysdep.h"
@@ -351,6 +356,8 @@ EXTERNAL
#include "bfdlink.h"
#include "aout/stab_gnu.h"
+const char bfd_symbol_error_name[] = { 0 };
+
/*
DOCDD
INODE
@@ -394,7 +401,7 @@ bfd_is_local_label (bfd *abfd, asymbol *sym)
if we didn't reject them here. */
if ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_FILE | BSF_SECTION_SYM)) != 0)
return false;
- if (sym->name == NULL)
+ if (sym->name == NULL || sym->name == bfd_symbol_error_name)
return false;
return bfd_is_local_label_name (abfd, sym->name);
}
@@ -777,7 +784,8 @@ bfd_symbol_info (asymbol *symbol, symbol_info *ret)
else
ret->value = symbol->value + symbol->section->vma;
- ret->name = symbol->name;
+ ret->name = (symbol->name != bfd_symbol_error_name
+ ? symbol->name : _("<corrupt>"));
}
/*
diff --git a/bfd/tekhex.c b/bfd/tekhex.c
index 96022c5..b305c1f 100644
--- a/bfd/tekhex.c
+++ b/bfd/tekhex.c
@@ -361,6 +361,7 @@ first_phase (bfd *abfd, int type, char *src, char * src_end)
{
asection *section, *alt_section;
unsigned int len;
+ bfd_vma addr;
bfd_vma val;
char sym[17]; /* A symbol can only be 16chars long. */
@@ -368,20 +369,16 @@ first_phase (bfd *abfd, int type, char *src, char * src_end)
{
case '6':
/* Data record - read it and store it. */
- {
- bfd_vma addr;
-
- if (!getvalue (&src, &addr, src_end))
- return false;
-
- while (*src && src < src_end - 1)
- {
- insert_byte (abfd, HEX (src), addr);
- src += 2;
- addr++;
- }
- return true;
- }
+ if (!getvalue (&src, &addr, src_end))
+ return false;
+
+ while (*src && src < src_end - 1)
+ {
+ insert_byte (abfd, HEX (src), addr);
+ src += 2;
+ addr++;
+ }
+ return true;
case '3':
/* Symbol record, read the segment. */
@@ -395,7 +392,7 @@ first_phase (bfd *abfd, int type, char *src, char * src_end)
if (!n)
return false;
memcpy (n, sym, len + 1);
- section = bfd_make_section (abfd, n);
+ section = bfd_make_section_old_way (abfd, n);
if (section == NULL)
return false;
}
@@ -406,13 +403,16 @@ first_phase (bfd *abfd, int type, char *src, char * src_end)
{
case '1': /* Section range. */
src++;
- if (!getvalue (&src, &section->vma, src_end))
+ if (!getvalue (&src, &addr, src_end))
return false;
if (!getvalue (&src, &val, src_end))
return false;
- if (val < section->vma)
- val = section->vma;
- section->size = val - section->vma;
+ if (bfd_is_const_section (section))
+ break;
+ section->vma = addr;
+ if (val < addr)
+ val = addr;
+ section->size = val - addr;
/* PR 17512: file: objdump-s-endless-loop.tekhex.
Check for overlarge section sizes. */
if (section->size & 0x80000000)
@@ -455,6 +455,8 @@ first_phase (bfd *abfd, int type, char *src, char * src_end)
new_symbol->symbol.flags = BSF_LOCAL;
if (stype == '2' || stype == '6')
new_symbol->symbol.section = bfd_abs_section_ptr;
+ else if (bfd_is_const_section (section))
+ ;
else if (stype == '3' || stype == '7')
{
if ((section->flags & SEC_DATA) == 0)
@@ -719,24 +721,13 @@ writevalue (char **dst, bfd_vma value)
int len;
int shift;
- for (len = 8, shift = 28; shift; shift -= 4, len--)
- {
- if ((value >> shift) & 0xf)
- {
- *p++ = len + '0';
- while (len)
- {
- *p++ = digs[(value >> shift) & 0xf];
- shift -= 4;
- len--;
- }
- *dst = p;
- return;
+ for (len = BFD_ARCH_SIZE / 4, shift = len * 4 - 4; len > 1; shift -= 4, len--)
+ if ((value >> shift) & 0xf)
+ break;
- }
- }
- *p++ = '1';
- *p++ = '0';
+ *p++ = digs[len & 0xf];
+ for (; len; shift -= 4, len--)
+ *p++ = digs[(value >> shift) & 0xf];
*dst = p;
}
@@ -747,22 +738,14 @@ writesym (char **dst, const char *sym)
int len = (sym ? strlen (sym) : 0);
if (len >= 16)
+ len = 16;
+ else if (len == 0)
{
- *p++ = '0';
- len = 16;
- }
- else
- {
- if (len == 0)
- {
- *p++ = '1';
- sym = "$";
- len = 1;
- }
- else
- *p++ = digs[len];
+ len = 1;
+ sym = "$";
}
+ *p++ = digs[len & 0xf];
while (len--)
*p++ = *sym++;
diff --git a/bfd/version.h b/bfd/version.h
index d02f0d3..cdf4189 100644
--- a/bfd/version.h
+++ b/bfd/version.h
@@ -16,7 +16,7 @@
In releases, the date is not included in either version strings or
sonames. */
-#define BFD_VERSION_DATE 20240803
+#define BFD_VERSION_DATE 20241115
#define BFD_VERSION @bfd_version@
#define BFD_VERSION_STRING @bfd_version_package@ @bfd_version_string@
#define REPORT_BUGS_TO @report_bugs_to@
diff --git a/bfd/vms-alpha.c b/bfd/vms-alpha.c
index 6eea61d..df279bc 100644
--- a/bfd/vms-alpha.c
+++ b/bfd/vms-alpha.c
@@ -8330,18 +8330,26 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
}
/* xgettext:c-format */
fprintf (file, _("Image identification: (major: %u, minor: %u)\n"),
- (unsigned)bfd_getl32 (eihi.majorid),
- (unsigned)bfd_getl32 (eihi.minorid));
- fprintf (file, _(" image name : %.*s\n"),
- eihi.imgnam[0], eihi.imgnam + 1);
+ (unsigned) bfd_getl32 (eihi.majorid),
+ (unsigned) bfd_getl32 (eihi.minorid));
+ unsigned int nlen = eihi.imgnam[0];
+ if (nlen > sizeof (eihi.imgnam) - 1)
+ nlen = sizeof (eihi.imgnam) - 1;
+ fprintf (file, _(" image name : %.*s\n"), nlen, eihi.imgnam + 1);
fprintf (file, _(" link time : %s\n"),
vms_time_to_str (eihi.linktime));
- fprintf (file, _(" image ident : %.*s\n"),
- eihi.imgid[0], eihi.imgid + 1);
- fprintf (file, _(" linker ident : %.*s\n"),
- eihi.linkid[0], eihi.linkid + 1);
- fprintf (file, _(" image build ident: %.*s\n"),
- eihi.imgbid[0], eihi.imgbid + 1);
+ nlen = eihi.imgid[0];
+ if (nlen > sizeof (eihi.imgid) - 1)
+ nlen = sizeof (eihi.imgid) - 1;
+ fprintf (file, _(" image ident : %.*s\n"), nlen, eihi.imgid + 1);
+ nlen = eihi.linkid[0];
+ if (nlen > sizeof (eihi.linkid) - 1)
+ nlen = sizeof (eihi.linkid) - 1;
+ fprintf (file, _(" linker ident : %.*s\n"), nlen, eihi.linkid + 1);
+ nlen = eihi.imgbid[0];
+ if (nlen > sizeof (eihi.imgbid) -1 )
+ nlen = sizeof (eihi.imgbid) - 1;
+ fprintf (file, _(" image build ident: %.*s\n"), nlen, eihi.imgbid + 1);
}
if (eihs_off != 0)
{
@@ -8474,10 +8482,15 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
}
fputs (_(")\n"), file);
if (val & EISD__M_GBL)
- /* xgettext:c-format */
- fprintf (file, _(" ident: 0x%08x, name: %.*s\n"),
- (unsigned)bfd_getl32 (eisd.ident),
- eisd.gblnam[0], eisd.gblnam + 1);
+ {
+ unsigned int nlen = eisd.gblnam[0];
+ if (nlen > sizeof (eisd.gblnam) - 1)
+ nlen = sizeof (eisd.gblnam) - 1;
+ /* xgettext:c-format */
+ fprintf (file, _(" ident: 0x%08x, name: %.*s\n"),
+ (unsigned) bfd_getl32 (eisd.ident),
+ nlen, eisd.gblnam + 1);
+ }
eisd_off += len;
}
@@ -8628,11 +8641,14 @@ evax_bfd_print_image (bfd *abfd, FILE *file)
j++, shlstoff += sizeof (struct vms_shl))
{
struct vms_shl *shl = (struct vms_shl *) (buf + shlstoff);
+ unsigned int nlen = shl->imgnam[0];
+ if (nlen > sizeof (shl->imgnam) - 1)
+ nlen = sizeof (shl->imgnam) - 1;
fprintf (file,
/* xgettext:c-format */
_(" %u: size: %u, flags: 0x%02x, name: %.*s\n"),
j, shl->size, shl->flags,
- shl->imgnam[0], shl->imgnam + 1);
+ nlen, shl->imgnam + 1);
}
}
if (qrelfixoff != 0)