mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-15 04:31:49 +08:00
fd3619828e
This large patch removes the unnecessary bfd parameter from various bfd section macros and functions. The bfd is hardly ever used and if needed for the bfd_set_section_* or bfd_rename_section functions can be found via section->owner except for the com, und, abs, and ind std_section special sections. Those sections shouldn't be modified anyway. The patch also removes various bfd_get_section_<field> macros, replacing their use with bfd_section_<field>, and adds bfd_set_section_lma. I've also fixed a minor bug in gas where compressed section renaming was done directly rather than calling bfd_rename_section. This would have broken bfd_get_section_by_name and similar functions, but that hardly mattered at such a late stage in gas processing. bfd/ * bfd-in.h (bfd_get_section_name, bfd_get_section_vma), (bfd_get_section_lma, bfd_get_section_alignment), (bfd_get_section_size, bfd_get_section_flags), (bfd_get_section_userdata): Delete. (bfd_section_name, bfd_section_size, bfd_section_vma), (bfd_section_lma, bfd_section_alignment): Lose bfd parameter. (bfd_section_flags, bfd_section_userdata): New. (bfd_is_com_section): Rename parameter. * section.c (bfd_set_section_userdata, bfd_set_section_vma), (bfd_set_section_alignment, bfd_set_section_flags, bfd_rename_section), (bfd_set_section_size): Delete bfd parameter, rename section parameter. (bfd_set_section_lma): New. * bfd-in2.h: Regenerate. * mach-o.c (bfd_mach_o_init_section_from_mach_o): Delete bfd param, update callers. * aoutx.h, * bfd.c, * coff-alpha.c, * coff-arm.c, * coff-mips.c, * coff64-rs6000.c, * coffcode.h, * coffgen.c, * cofflink.c, * compress.c, * ecoff.c, * elf-eh-frame.c, * elf-hppa.h, * elf-ifunc.c, * elf-m10200.c, * elf-m10300.c, * elf-properties.c, * elf-s390-common.c, * elf-vxworks.c, * elf.c, * elf32-arc.c, * elf32-arm.c, * elf32-avr.c, * elf32-bfin.c, * elf32-cr16.c, * elf32-cr16c.c, * elf32-cris.c, * elf32-crx.c, * elf32-csky.c, * elf32-d10v.c, * elf32-epiphany.c, * elf32-fr30.c, * elf32-frv.c, * elf32-ft32.c, * elf32-h8300.c, * elf32-hppa.c, * elf32-i386.c, * elf32-ip2k.c, * elf32-iq2000.c, * elf32-lm32.c, * elf32-m32c.c, * elf32-m32r.c, * elf32-m68hc1x.c, * elf32-m68k.c, * elf32-mcore.c, * elf32-mep.c, * elf32-metag.c, * elf32-microblaze.c, * elf32-moxie.c, * elf32-msp430.c, * elf32-mt.c, * elf32-nds32.c, * elf32-nios2.c, * elf32-or1k.c, * elf32-ppc.c, * elf32-pru.c, * elf32-rl78.c, * elf32-rx.c, * elf32-s390.c, * elf32-score.c, * elf32-score7.c, * elf32-sh.c, * elf32-spu.c, * elf32-tic6x.c, * elf32-tilepro.c, * elf32-v850.c, * elf32-vax.c, * elf32-visium.c, * elf32-xstormy16.c, * elf32-xtensa.c, * elf64-alpha.c, * elf64-bpf.c, * elf64-hppa.c, * elf64-ia64-vms.c, * elf64-mmix.c, * elf64-ppc.c, * elf64-s390.c, * elf64-sparc.c, * elf64-x86-64.c, * elflink.c, * elfnn-aarch64.c, * elfnn-ia64.c, * elfnn-riscv.c, * elfxx-aarch64.c, * elfxx-mips.c, * elfxx-sparc.c, * elfxx-tilegx.c, * elfxx-x86.c, * i386msdos.c, * linker.c, * mach-o.c, * mmo.c, * opncls.c, * pdp11.c, * pei-x86_64.c, * peicode.h, * reloc.c, * section.c, * syms.c, * vms-alpha.c, * xcofflink.c: Update throughout for bfd section macro and function changes. binutils/ * addr2line.c, * bucomm.c, * coffgrok.c, * dlltool.c, * nm.c, * objcopy.c, * objdump.c, * od-elf32_avr.c, * od-macho.c, * od-xcoff.c, * prdbg.c, * rdcoff.c, * rddbg.c, * rescoff.c, * resres.c, * size.c, * srconv.c, * strings.c, * windmc.c: Update throughout for bfd section macro and function changes. gas/ * as.c, * as.h, * dw2gencfi.c, * dwarf2dbg.c, * ecoff.c, * read.c, * stabs.c, * subsegs.c, * subsegs.h, * write.c, * config/obj-coff-seh.c, * config/obj-coff.c, * config/obj-ecoff.c, * config/obj-elf.c, * config/obj-macho.c, * config/obj-som.c, * config/tc-aarch64.c, * config/tc-alpha.c, * config/tc-arc.c, * config/tc-arm.c, * config/tc-avr.c, * config/tc-bfin.c, * config/tc-bpf.c, * config/tc-d10v.c, * config/tc-d30v.c, * config/tc-epiphany.c, * config/tc-fr30.c, * config/tc-frv.c, * config/tc-h8300.c, * config/tc-hppa.c, * config/tc-i386.c, * config/tc-ia64.c, * config/tc-ip2k.c, * config/tc-iq2000.c, * config/tc-lm32.c, * config/tc-m32c.c, * config/tc-m32r.c, * config/tc-m68hc11.c, * config/tc-mep.c, * config/tc-microblaze.c, * config/tc-mips.c, * config/tc-mmix.c, * config/tc-mn10200.c, * config/tc-mn10300.c, * config/tc-msp430.c, * config/tc-mt.c, * config/tc-nds32.c, * config/tc-or1k.c, * config/tc-ppc.c, * config/tc-pru.c, * config/tc-rl78.c, * config/tc-rx.c, * config/tc-s12z.c, * config/tc-s390.c, * config/tc-score.c, * config/tc-score7.c, * config/tc-sh.c, * config/tc-sparc.c, * config/tc-spu.c, * config/tc-tic4x.c, * config/tc-tic54x.c, * config/tc-tic6x.c, * config/tc-tilegx.c, * config/tc-tilepro.c, * config/tc-v850.c, * config/tc-visium.c, * config/tc-wasm32.c, * config/tc-xc16x.c, * config/tc-xgate.c, * config/tc-xstormy16.c, * config/tc-xtensa.c, * config/tc-z8k.c: Update throughout for bfd section macro and function changes. * write.c (compress_debug): Use bfd_rename_section. gdb/ * aarch64-linux-tdep.c, * arm-tdep.c, * auto-load.c, * coff-pe-read.c, * coffread.c, * corelow.c, * dbxread.c, * dicos-tdep.c, * dwarf2-frame.c, * dwarf2read.c, * elfread.c, * exec.c, * fbsd-tdep.c, * gcore.c, * gdb_bfd.c, * gdb_bfd.h, * hppa-tdep.c, * i386-cygwin-tdep.c, * i386-fbsd-tdep.c, * i386-linux-tdep.c, * jit.c, * linux-tdep.c, * machoread.c, * maint.c, * mdebugread.c, * minidebug.c, * mips-linux-tdep.c, * mips-sde-tdep.c, * mips-tdep.c, * mipsread.c, * nto-tdep.c, * objfiles.c, * objfiles.h, * osabi.c, * ppc-linux-tdep.c, * ppc64-tdep.c, * record-btrace.c, * record-full.c, * remote.c, * rs6000-aix-tdep.c, * rs6000-tdep.c, * s390-linux-tdep.c, * s390-tdep.c, * solib-aix.c, * solib-dsbt.c, * solib-frv.c, * solib-spu.c, * solib-svr4.c, * solib-target.c, * spu-linux-nat.c, * spu-tdep.c, * symfile-mem.c, * symfile.c, * symmisc.c, * symtab.c, * target.c, * windows-nat.c, * xcoffread.c, * cli/cli-dump.c, * compile/compile-object-load.c, * mi/mi-interp.c: Update throughout for bfd section macro and function changes. * gcore (gcore_create_callback): Use bfd_set_section_lma. * spu-tdep.c (spu_overlay_new_objfile): Likewise. gprof/ * corefile.c, * symtab.c: Update throughout for bfd section macro and function changes. ld/ * ldcref.c, * ldctor.c, * ldelf.c, * ldlang.c, * pe-dll.c, * emultempl/aarch64elf.em, * emultempl/aix.em, * emultempl/armcoff.em, * emultempl/armelf.em, * emultempl/cr16elf.em, * emultempl/cskyelf.em, * emultempl/m68hc1xelf.em, * emultempl/m68kelf.em, * emultempl/mipself.em, * emultempl/mmix-elfnmmo.em, * emultempl/mmo.em, * emultempl/msp430.em, * emultempl/nios2elf.em, * emultempl/pe.em, * emultempl/pep.em, * emultempl/ppc64elf.em, * emultempl/xtensaelf.em: Update throughout for bfd section macro and function changes. libctf/ * ctf-open-bfd.c: Update throughout for bfd section macro changes. opcodes/ * arc-ext.c: Update throughout for bfd section macro changes. sim/ * common/sim-load.c, * common/sim-utils.c, * cris/sim-if.c, * erc32/func.c, * lm32/sim-if.c, * m32c/load.c, * m32c/trace.c, * m68hc11/interp.c, * ppc/hw_htab.c, * ppc/hw_init.c, * rl78/load.c, * rl78/trace.c, * rx/gdb-if.c, * rx/load.c, * rx/trace.c: Update throughout for bfd section macro changes.
384 lines
9.7 KiB
C
384 lines
9.7 KiB
C
/* ldctor.c -- constructor support routines
|
|
Copyright (C) 1991-2019 Free Software Foundation, Inc.
|
|
By Steve Chamberlain <sac@cygnus.com>
|
|
|
|
This file is part of the GNU Binutils.
|
|
|
|
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.
|
|
|
|
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 this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
|
MA 02110-1301, USA. */
|
|
|
|
#include "sysdep.h"
|
|
#include "bfd.h"
|
|
#include "bfdlink.h"
|
|
#include "safe-ctype.h"
|
|
|
|
#include "ld.h"
|
|
#include "ldexp.h"
|
|
#include "ldlang.h"
|
|
#include "ldmisc.h"
|
|
#include <ldgram.h>
|
|
#include "ldmain.h"
|
|
#include "ldctor.h"
|
|
|
|
/* The list of statements needed to handle constructors. These are
|
|
invoked by the command CONSTRUCTORS in the linker script. */
|
|
lang_statement_list_type constructor_list;
|
|
|
|
/* Whether the constructors should be sorted. Note that this is
|
|
global for the entire link; we assume that there is only a single
|
|
CONSTRUCTORS command in the linker script. */
|
|
bfd_boolean constructors_sorted;
|
|
|
|
/* The sets we have seen. */
|
|
struct set_info *sets;
|
|
|
|
/* Add an entry to a set. H is the entry in the linker hash table.
|
|
RELOC is the relocation to use for an entry in the set. SECTION
|
|
and VALUE are the value to add. This is called during the first
|
|
phase of the link, when we are still gathering symbols together.
|
|
We just record the information now. The ldctor_build_sets
|
|
function will construct the sets. */
|
|
|
|
void
|
|
ldctor_add_set_entry (struct bfd_link_hash_entry *h,
|
|
bfd_reloc_code_real_type reloc,
|
|
const char *name,
|
|
asection *section,
|
|
bfd_vma value)
|
|
{
|
|
struct set_info *p;
|
|
struct set_element *e;
|
|
struct set_element **epp;
|
|
|
|
for (p = sets; p != NULL; p = p->next)
|
|
if (p->h == h)
|
|
break;
|
|
|
|
if (p == NULL)
|
|
{
|
|
p = (struct set_info *) xmalloc (sizeof (struct set_info));
|
|
p->next = sets;
|
|
sets = p;
|
|
p->h = h;
|
|
p->reloc = reloc;
|
|
p->count = 0;
|
|
p->elements = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (p->reloc != reloc)
|
|
{
|
|
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. */
|
|
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 (_("%X%P: different object file formats composing set %s\n"),
|
|
h->root.string);
|
|
return;
|
|
}
|
|
}
|
|
|
|
e = (struct set_element *) xmalloc (sizeof (struct set_element));
|
|
e->next = NULL;
|
|
e->name = name;
|
|
e->section = section;
|
|
e->value = value;
|
|
|
|
for (epp = &p->elements; *epp != NULL; epp = &(*epp)->next)
|
|
;
|
|
*epp = e;
|
|
|
|
++p->count;
|
|
}
|
|
|
|
/* Get the priority of a g++ global constructor or destructor from the
|
|
symbol name. */
|
|
|
|
static int
|
|
ctor_prio (const char *name)
|
|
{
|
|
/* The name will look something like _GLOBAL_$I$65535$test02__Fv.
|
|
There might be extra leading underscores, and the $ characters
|
|
might be something else. The I might be a D. */
|
|
|
|
while (*name == '_')
|
|
++name;
|
|
|
|
if (!CONST_STRNEQ (name, "GLOBAL_"))
|
|
return -1;
|
|
|
|
name += sizeof "GLOBAL_" - 1;
|
|
|
|
if (name[0] != name[2])
|
|
return -1;
|
|
if (name[1] != 'I' && name[1] != 'D')
|
|
return -1;
|
|
if (!ISDIGIT (name[3]))
|
|
return -1;
|
|
|
|
return atoi (name + 3);
|
|
}
|
|
|
|
/* This function is used to sort constructor elements by priority. It
|
|
is called via qsort. */
|
|
|
|
static int
|
|
ctor_cmp (const void *p1, const void *p2)
|
|
{
|
|
const struct set_element *const *pe1
|
|
= (const struct set_element *const *) p1;
|
|
const struct set_element *const *pe2
|
|
= (const struct set_element *const *) p2;
|
|
const char *n1;
|
|
const char *n2;
|
|
int prio1;
|
|
int prio2;
|
|
|
|
n1 = (*pe1)->name;
|
|
if (n1 == NULL)
|
|
n1 = "";
|
|
n2 = (*pe2)->name;
|
|
if (n2 == NULL)
|
|
n2 = "";
|
|
|
|
/* We need to sort in reverse order by priority. When two
|
|
constructors have the same priority, we should maintain their
|
|
current relative position. */
|
|
|
|
prio1 = ctor_prio (n1);
|
|
prio2 = ctor_prio (n2);
|
|
|
|
/* We sort in reverse order because that is what g++ expects. */
|
|
if (prio1 < prio2)
|
|
return 1;
|
|
else if (prio1 > prio2)
|
|
return -1;
|
|
|
|
/* Force a stable sort. */
|
|
|
|
if (pe1 < pe2)
|
|
return -1;
|
|
else if (pe1 > pe2)
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/* This function is called after the first phase of the link and
|
|
before the second phase. At this point all set information has
|
|
been gathered. We now put the statements to build the sets
|
|
themselves into constructor_list. */
|
|
|
|
void
|
|
ldctor_build_sets (void)
|
|
{
|
|
static bfd_boolean called;
|
|
bfd_boolean header_printed;
|
|
struct set_info *p;
|
|
|
|
/* The emulation code may call us directly, but we only want to do
|
|
this once. */
|
|
if (called)
|
|
return;
|
|
called = TRUE;
|
|
|
|
if (constructors_sorted)
|
|
{
|
|
for (p = sets; p != NULL; p = p->next)
|
|
{
|
|
int c, i;
|
|
struct set_element *e;
|
|
struct set_element **array;
|
|
|
|
if (p->elements == NULL)
|
|
continue;
|
|
|
|
c = 0;
|
|
for (e = p->elements; e != NULL; e = e->next)
|
|
++c;
|
|
|
|
array = (struct set_element **) xmalloc (c * sizeof *array);
|
|
|
|
i = 0;
|
|
for (e = p->elements; e != NULL; e = e->next)
|
|
{
|
|
array[i] = e;
|
|
++i;
|
|
}
|
|
|
|
qsort (array, c, sizeof *array, ctor_cmp);
|
|
|
|
e = array[0];
|
|
p->elements = e;
|
|
for (i = 0; i < c - 1; i++)
|
|
array[i]->next = array[i + 1];
|
|
array[i]->next = NULL;
|
|
|
|
free (array);
|
|
}
|
|
}
|
|
|
|
lang_list_init (&constructor_list);
|
|
push_stat_ptr (&constructor_list);
|
|
|
|
header_printed = FALSE;
|
|
for (p = sets; p != NULL; p = p->next)
|
|
{
|
|
struct set_element *e;
|
|
reloc_howto_type *howto;
|
|
int reloc_size, size;
|
|
|
|
/* If the symbol is defined, we may have been invoked from
|
|
collect, and the sets may already have been built, so we do
|
|
not do anything. */
|
|
if (p->h->type == bfd_link_hash_defined
|
|
|| p->h->type == bfd_link_hash_defweak)
|
|
continue;
|
|
|
|
/* For each set we build:
|
|
set:
|
|
.long number_of_elements
|
|
.long element0
|
|
...
|
|
.long elementN
|
|
.long 0
|
|
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 (link_info.output_bfd, p->reloc);
|
|
if (howto == NULL)
|
|
{
|
|
if (bfd_link_relocatable (&link_info))
|
|
{
|
|
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;
|
|
}
|
|
|
|
/* If this is not a relocatable link, all we need is the
|
|
size, which we can get from the input BFD. */
|
|
if (p->elements->section->owner != NULL)
|
|
howto = bfd_reloc_type_lookup (p->elements->section->owner,
|
|
p->reloc);
|
|
if (howto == NULL)
|
|
{
|
|
/* 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;
|
|
}
|
|
}
|
|
|
|
reloc_size = bfd_get_reloc_size (howto);
|
|
switch (reloc_size)
|
|
{
|
|
case 1: size = BYTE; break;
|
|
case 2: size = SHORT; break;
|
|
case 4: size = LONG; break;
|
|
case 8:
|
|
if (howto->complain_on_overflow == complain_overflow_signed)
|
|
size = SQUAD;
|
|
else
|
|
size = QUAD;
|
|
break;
|
|
default:
|
|
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_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)
|
|
{
|
|
if (config.map_file != NULL)
|
|
{
|
|
int len;
|
|
|
|
if (!header_printed)
|
|
{
|
|
minfo (_("\nSet Symbol\n\n"));
|
|
header_printed = TRUE;
|
|
}
|
|
|
|
minfo ("%s", p->h->root.string);
|
|
len = strlen (p->h->root.string);
|
|
|
|
if (len >= 19)
|
|
{
|
|
print_nl ();
|
|
len = 0;
|
|
}
|
|
while (len < 20)
|
|
{
|
|
print_space ();
|
|
++len;
|
|
}
|
|
|
|
if (e->name != NULL)
|
|
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))
|
|
e->section->flags |= SEC_KEEP;
|
|
|
|
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_relop (e->section, e->value));
|
|
}
|
|
|
|
lang_add_data (size, exp_intop (0));
|
|
}
|
|
|
|
pop_stat_ptr ();
|
|
}
|