094e34f221
This unfortunately means conditionalizing out all the libctf code, but the result is not too unbearably ugly, if a bit repetitive. I have stubbed out code in the !ENABLE_LIBCTF path to avoid extra redundant ifdefs where it seems that might be helpful. (The stubs are not too disruptive, but I've tried to keep them on one line where possible to avoid filling up the screen with stubs that nobody would care about. If this is too much of a coding style violation I can change it.) Changes since v2: use GCC_ENABLE rather than repeating all the AC_ARG_ENABLE stuff over and over again. ld/ * configure.ac [--enable-libctf]: New, default yes. Set ENABLE_LIBCTF accordingly. * Makefile.am [!ENABLE_LIBCTF]: Empty LIBCTF. * configure: Regenerate. * config.in: Regenerate. * Makefile.in: Regenerate. * aclocal.m4: Regenerate. * ldlang.c (ctf_output): Conditionalize on ENABLE_LIBCTF. (ldlang_open_ctf): Likewise. (lang_merge_ctf): Likewise. (ldlang_ctf_apply_strsym): Likewise. (lang_write_ctf): Likewise. (ldlang_write_ctf_late): Likewise. (ldlang_open_ctf) [!ENABLE_LIBCTF]: Warn about the presence of CTF sections. (lang_merge_ctf) [!ENABLE_LIBCTF]: New stub. (ldlang_ctf_apply_strsym) [!ENABLE_LIBCTF]: Likewise. (lang_write_ctf) [!ENABLE_LIBCTF]: Likewise. (ldlang_write_ctf_late) [!ENABLE_LIBCTF]: Likewise. * ldelfgen.c (ldelf_emit_ctf_early): Conditionalize on ENABLE_LIBCTF. (struct ctf_strsym_iter_cb_arg): Likewise. (ldelf_ctf_strtab_iter_cb): Likewise. (ldelf_ctf_symbols_iter_cb): Likewise. (ldelf_examine_strtab_for_ctf): Likewise. (ldelf_emit_ctf_early) [!ENABLE_LIBCTF]: New stub. (ldelf_examine_strtab_for_ctf) [!ENABLE_LIBCTF]: New stub. binutils/ * configure.ac [--enable-libctf]: New, default yes. Set ENABLE_LIBCTF accordingly. * Makefile.am [!ENABLE_LIBCTF]: Empty LIBCTF and LIBCTF_NOBFD. * configure: Regenerate. * config.in: Regenerate. * Makefile.in: Regenerate. * aclocal.m4: Regenerate. * objdump.c (usage): Conditionalize portions on ENABLE_LIBCTF. (option_values): Likewise. (long_options): Likewise. (main): Likewise. (dump_ctf_indent_lines): Conditionalize out when !ENABLE_LIBCTF. (make_ctfsect): Likewise. (dump_ctf_archive_member): Likewise. (dump_ctf) [ENABLE_LIBCTF]: Likewise. (dump_ctf) [!ENABLE_LIBCTF]: New empty stub. * readelf.c (options): Conditionalize portions on ENABLE_LIBCTF. (usage): Likewise. (process_section_contents): Likewise. (shdr_to_ctf_sect): Conditionalize out when !ENABLE_LIBCTF. (dump_ctf_indent_lines): Likewise. (dump_section_as_ctf) [ENABLE_LIBCTF]: Likewise.
214 lines
6.1 KiB
C
214 lines
6.1 KiB
C
/* Emulation code used by all ELF targets.
|
|
Copyright (C) 1991-2020 Free Software Foundation, Inc.
|
|
|
|
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 "ctf-api.h"
|
|
#include "ld.h"
|
|
#include "ldmain.h"
|
|
#include "ldmisc.h"
|
|
#include "ldexp.h"
|
|
#include "ldlang.h"
|
|
#include "elf-bfd.h"
|
|
#include "ldelfgen.h"
|
|
|
|
void
|
|
ldelf_map_segments (bfd_boolean need_layout)
|
|
{
|
|
int tries = 10;
|
|
|
|
do
|
|
{
|
|
lang_relax_sections (need_layout);
|
|
need_layout = FALSE;
|
|
|
|
if (link_info.output_bfd->xvec->flavour == bfd_target_elf_flavour
|
|
&& !bfd_link_relocatable (&link_info))
|
|
{
|
|
bfd_size_type phdr_size;
|
|
|
|
phdr_size = elf_program_header_size (link_info.output_bfd);
|
|
/* If we don't have user supplied phdrs, throw away any
|
|
previous linker generated program headers. */
|
|
if (lang_phdr_list == NULL)
|
|
elf_seg_map (link_info.output_bfd) = NULL;
|
|
if (!_bfd_elf_map_sections_to_segments (link_info.output_bfd,
|
|
&link_info))
|
|
einfo (_("%F%P: map sections to segments failed: %E\n"));
|
|
|
|
if (phdr_size != elf_program_header_size (link_info.output_bfd))
|
|
{
|
|
if (tries > 6)
|
|
/* The first few times we allow any change to
|
|
phdr_size . */
|
|
need_layout = TRUE;
|
|
else if (phdr_size
|
|
< elf_program_header_size (link_info.output_bfd))
|
|
/* After that we only allow the size to grow. */
|
|
need_layout = TRUE;
|
|
else
|
|
elf_program_header_size (link_info.output_bfd) = phdr_size;
|
|
}
|
|
}
|
|
}
|
|
while (need_layout && --tries);
|
|
|
|
if (tries == 0)
|
|
einfo (_("%F%P: looping in map_segments"));
|
|
|
|
if (link_info.output_bfd->xvec->flavour == bfd_target_elf_flavour
|
|
&& lang_phdr_list == NULL)
|
|
{
|
|
/* If we don't have user supplied phdrs, strip zero-sized dynamic
|
|
sections and regenerate program headers. */
|
|
const struct elf_backend_data *bed
|
|
= get_elf_backend_data (link_info.output_bfd);
|
|
if (bed->elf_backend_strip_zero_sized_dynamic_sections
|
|
&& !bed->elf_backend_strip_zero_sized_dynamic_sections
|
|
(&link_info))
|
|
einfo (_("%F%P: failed to strip zero-sized dynamic sections"));
|
|
}
|
|
}
|
|
|
|
#ifdef ENABLE_LIBCTF
|
|
/* We want to emit CTF early if and only if we are not targetting ELF with this
|
|
invocation. */
|
|
|
|
int
|
|
ldelf_emit_ctf_early (void)
|
|
{
|
|
if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/* Callbacks used to map from bfd types to libctf types, under libctf's
|
|
control. */
|
|
|
|
struct ctf_strsym_iter_cb_arg
|
|
{
|
|
struct elf_sym_strtab *syms;
|
|
bfd_size_type symcount;
|
|
struct elf_strtab_hash *symstrtab;
|
|
size_t next_i;
|
|
size_t next_idx;
|
|
};
|
|
|
|
/* Return strings from the strtab to libctf, one by one. Returns NULL when
|
|
iteration is complete. */
|
|
|
|
static const char *
|
|
ldelf_ctf_strtab_iter_cb (uint32_t *offset, void *arg_)
|
|
{
|
|
bfd_size_type off;
|
|
const char *ret;
|
|
|
|
struct ctf_strsym_iter_cb_arg *arg =
|
|
(struct ctf_strsym_iter_cb_arg *) arg_;
|
|
|
|
/* There is no zeroth string. */
|
|
if (arg->next_i == 0)
|
|
arg->next_i = 1;
|
|
|
|
if (arg->next_i >= _bfd_elf_strtab_len (arg->symstrtab))
|
|
{
|
|
arg->next_i = 0;
|
|
return NULL;
|
|
}
|
|
|
|
ret = _bfd_elf_strtab_str (arg->symstrtab, arg->next_i++, &off);
|
|
*offset = off;
|
|
|
|
/* If we've overflowed, we cannot share any further strings: the CTF
|
|
format cannot encode strings with such high offsets. */
|
|
if (*offset != off)
|
|
return NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Return symbols from the symbol table to libctf, one by one. We assume (and
|
|
assert) that the symbols in the elf_link_hash_table are in strictly ascending
|
|
order, and that none will be added in between existing ones. Returns NULL
|
|
when iteration is complete. */
|
|
|
|
static struct ctf_link_sym *
|
|
ldelf_ctf_symbols_iter_cb (struct ctf_link_sym *dest,
|
|
void *arg_)
|
|
{
|
|
struct ctf_strsym_iter_cb_arg *arg =
|
|
(struct ctf_strsym_iter_cb_arg *) arg_;
|
|
|
|
if (arg->next_i > arg->symcount)
|
|
{
|
|
arg->next_i = 0;
|
|
arg->next_idx = 0;
|
|
return NULL;
|
|
}
|
|
|
|
ASSERT (arg->syms[arg->next_i].dest_index == arg->next_idx);
|
|
dest->st_name = _bfd_elf_strtab_str (arg->symstrtab, arg->next_i, NULL);
|
|
dest->st_shndx = arg->syms[arg->next_i].sym.st_shndx;
|
|
dest->st_type = ELF_ST_TYPE (arg->syms[arg->next_i].sym.st_info);
|
|
dest->st_value = arg->syms[arg->next_i].sym.st_value;
|
|
arg->next_i++;
|
|
return dest;
|
|
}
|
|
|
|
void
|
|
ldelf_examine_strtab_for_ctf
|
|
(struct ctf_file *ctf_output, struct elf_sym_strtab *syms,
|
|
bfd_size_type symcount, struct elf_strtab_hash *symstrtab)
|
|
{
|
|
struct ctf_strsym_iter_cb_arg args = { syms, symcount, symstrtab,
|
|
0, 0 };
|
|
if (!ctf_output)
|
|
return;
|
|
|
|
if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour
|
|
&& !bfd_link_relocatable (&link_info))
|
|
{
|
|
if (ctf_link_add_strtab (ctf_output, ldelf_ctf_strtab_iter_cb,
|
|
&args) < 0)
|
|
einfo (_("%F%P: warning: CTF strtab association failed; strings will "
|
|
"not be shared: %s\n"),
|
|
ctf_errmsg (ctf_errno (ctf_output)));
|
|
|
|
if (ctf_link_shuffle_syms (ctf_output, ldelf_ctf_symbols_iter_cb,
|
|
&args) < 0)
|
|
einfo (_("%F%P: warning: CTF symbol shuffling failed; slight space "
|
|
"cost: %s\n"), ctf_errmsg (ctf_errno (ctf_output)));
|
|
}
|
|
}
|
|
#else
|
|
extern int ldelf_emit_ctf_early (void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
extern void ldelf_examine_strtab_for_ctf
|
|
(struct ctf_file *ctf_output ATTRIBUTE_UNUSED,
|
|
struct elf_sym_strtab *syms ATTRIBUTE_UNUSED,
|
|
bfd_size_type symcount ATTRIBUTE_UNUSED,
|
|
struct elf_strtab_hash *symstrtab ATTRIBUTE_UNUSED)
|
|
{}
|
|
#endif
|