1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
|
/* 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
|