/* ldctor.c -- constructor support routines
- Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1991-2019 Free Software Foundation, Inc.
By Steve Chamberlain <sac@cygnus.com>
-This file is part of GLD, the Gnu Linker.
+ This file is part of the GNU Binutils.
-GLD is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
-GLD is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with GLD; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "bfdlink.h"
#include "safe-ctype.h"
+#include "ctf-api.h"
#include "ld.h"
#include "ldexp.h"
if (p == NULL)
{
- p = xmalloc (sizeof (struct set_info));
+ p = (struct set_info *) xmalloc (sizeof (struct set_info));
p->next = sets;
sets = p;
p->h = h;
{
if (p->reloc != reloc)
{
- einfo (_("%P%X: Different relocs used in set %s\n"),
+ einfo (_("%X%P: different relocs used in set %s\n"),
h->root.string);
return;
}
/* Don't permit a set to be constructed from different object
- file formats. The same reloc may have different results. We
- actually could sometimes handle this, but the case is
- unlikely to ever arise. Sometimes constructor symbols are in
- unusual sections, such as the absolute section--this appears
- to be the case in Linux a.out--and in such cases we just
- assume everything is OK. */
+ file formats. The same reloc may have different results. We
+ actually could sometimes handle this, but the case is
+ unlikely to ever arise. Sometimes constructor symbols are in
+ unusual sections, such as the absolute section--this appears
+ to be the case in Linux a.out--and in such cases we just
+ assume everything is OK. */
if (p->elements != NULL
&& section->owner != NULL
&& p->elements->section->owner != NULL
&& strcmp (bfd_get_target (section->owner),
bfd_get_target (p->elements->section->owner)) != 0)
{
- einfo (_("%P%X: Different object file formats composing set %s\n"),
+ einfo (_("%X%P: different object file formats composing set %s\n"),
h->root.string);
return;
}
}
- e = xmalloc (sizeof (struct set_element));
- e->next = NULL;
+ e = (struct set_element *) xmalloc (sizeof (struct set_element));
+ e->u.next = NULL;
e->name = name;
e->section = section;
e->value = value;
- for (epp = &p->elements; *epp != NULL; epp = &(*epp)->next)
+ for (epp = &p->elements; *epp != NULL; epp = &(*epp)->u.next)
;
*epp = e;
while (*name == '_')
++name;
- if (strncmp (name, "GLOBAL_", sizeof "GLOBAL_" - 1) != 0)
+ if (!CONST_STRNEQ (name, "GLOBAL_"))
return -1;
name += sizeof "GLOBAL_" - 1;
return -1;
if (name[1] != 'I' && name[1] != 'D')
return -1;
- if (! ISDIGIT (name[3]))
+ if (!ISDIGIT (name[3]))
return -1;
return atoi (name + 3);
static int
ctor_cmp (const void *p1, const void *p2)
{
- const struct set_element * const *pe1 = p1;
- const struct set_element * const *pe2 = p2;
+ const struct set_element *pe1 = *(const struct set_element **) p1;
+ const struct set_element *pe2 = *(const struct set_element **) p2;
const char *n1;
const char *n2;
int prio1;
int prio2;
- n1 = (*pe1)->name;
+ n1 = pe1->name;
if (n1 == NULL)
n1 = "";
- n2 = (*pe2)->name;
+ n2 = pe2->name;
if (n2 == NULL)
n2 = "";
/* We sort in reverse order because that is what g++ expects. */
if (prio1 < prio2)
return 1;
- else if (prio1 > prio2)
+ if (prio1 > prio2)
return -1;
/* Force a stable sort. */
-
- if (pe1 < pe2)
+ if (pe1->u.idx < pe2->u.idx)
return -1;
- else if (pe1 > pe2)
+ if (pe1->u.idx > pe2->u.idx)
return 1;
- else
- return 0;
+ return 0;
}
/* This function is called after the first phase of the link and
ldctor_build_sets (void)
{
static bfd_boolean called;
- lang_statement_list_type *old;
bfd_boolean header_printed;
struct set_info *p;
for (p = sets; p != NULL; p = p->next)
{
int c, i;
- struct set_element *e;
+ struct set_element *e, *enext;
struct set_element **array;
if (p->elements == NULL)
continue;
c = 0;
- for (e = p->elements; e != NULL; e = e->next)
+ for (e = p->elements; e != NULL; e = e->u.next)
++c;
- array = xmalloc (c * sizeof *array);
+ array = (struct set_element **) xmalloc (c * sizeof *array);
i = 0;
- for (e = p->elements; e != NULL; e = e->next)
+ for (e = p->elements; e != NULL; e = enext)
{
array[i] = e;
+ enext = e->u.next;
+ e->u.idx = i;
++i;
}
e = array[0];
p->elements = e;
for (i = 0; i < c - 1; i++)
- array[i]->next = array[i + 1];
- array[i]->next = NULL;
+ array[i]->u.next = array[i + 1];
+ array[i]->u.next = NULL;
free (array);
}
}
- old = stat_ptr;
- stat_ptr = &constructor_list;
-
- lang_list_init (stat_ptr);
+ lang_list_init (&constructor_list);
+ push_stat_ptr (&constructor_list);
header_printed = FALSE;
for (p = sets; p != NULL; p = p->next)
except that we use the right size instead of .long. When
generating relocatable output, we generate relocs instead of
addresses. */
- howto = bfd_reloc_type_lookup (output_bfd, p->reloc);
+ howto = bfd_reloc_type_lookup (link_info.output_bfd, p->reloc);
if (howto == NULL)
{
- if (link_info.relocatable)
+ if (bfd_link_relocatable (&link_info))
{
- einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
- bfd_get_target (output_bfd),
+ einfo (_("%X%P: %s does not support reloc %s for set %s\n"),
+ bfd_get_target (link_info.output_bfd),
bfd_get_reloc_code_name (p->reloc),
p->h->root.string);
continue;
p->reloc);
if (howto == NULL)
{
- einfo (_("%P%X: %s does not support reloc %s for set %s\n"),
- bfd_get_target (p->elements->section->owner),
- bfd_get_reloc_code_name (p->reloc),
- p->h->root.string);
+ /* See PR 20911 for a reproducer. */
+ if (p->elements->section->owner == NULL)
+ einfo (_("%X%P: special section %s does not support reloc %s for set %s\n"),
+ bfd_section_name (p->elements->section),
+ bfd_get_reloc_code_name (p->reloc),
+ p->h->root.string);
+ else
+ einfo (_("%X%P: %s does not support reloc %s for set %s\n"),
+ bfd_get_target (p->elements->section->owner),
+ bfd_get_reloc_code_name (p->reloc),
+ p->h->root.string);
continue;
}
}
size = QUAD;
break;
default:
- einfo (_("%P%X: Unsupported size %d for set %s\n"),
+ einfo (_("%X%P: unsupported size %d for set %s\n"),
bfd_get_reloc_size (howto), p->h->root.string);
size = LONG;
break;
}
- lang_add_assignment (exp_assop ('=', ".",
- exp_unop (ALIGN_K,
- exp_intop (reloc_size))));
- lang_add_assignment (exp_assop ('=', p->h->root.string,
- exp_nameop (NAME, ".")));
+ lang_add_assignment (exp_assign (".",
+ exp_unop (ALIGN_K,
+ exp_intop (reloc_size)),
+ FALSE));
+ lang_add_assignment (exp_assign (p->h->root.string,
+ exp_nameop (NAME, "."),
+ FALSE));
lang_add_data (size, exp_intop (p->count));
- for (e = p->elements; e != NULL; e = e->next)
+ for (e = p->elements; e != NULL; e = e->u.next)
{
if (config.map_file != NULL)
{
int len;
- if (! header_printed)
+ if (!header_printed)
{
minfo (_("\nSet Symbol\n\n"));
header_printed = TRUE;
}
if (e->name != NULL)
- minfo ("%T\n", e->name);
+ minfo ("%pT\n", e->name);
else
minfo ("%G\n", e->section->owner, e->section, e->value);
}
/* Need SEC_KEEP for --gc-sections. */
- if (! bfd_is_abs_section (e->section))
+ if (!bfd_is_abs_section (e->section))
e->section->flags |= SEC_KEEP;
- if (link_info.relocatable)
+ if (bfd_link_relocatable (&link_info))
lang_add_reloc (p->reloc, howto, e->section, e->name,
exp_intop (e->value));
else
lang_add_data (size, exp_intop (0));
}
- stat_ptr = old;
+ pop_stat_ptr ();
}