/* ELF executable support for BFD.
- Copyright (C) 1993-2020 Free Software Foundation, Inc.
+ Copyright (C) 1993-2021 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
static int elf_sort_sections (const void *, const void *);
static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *);
-static bfd_boolean swap_out_syms (bfd *, struct elf_strtab_hash **, int) ;
+static bfd_boolean swap_out_syms (bfd *, struct elf_strtab_hash **, int,
+ struct bfd_link_info *);
static bfd_boolean elf_parse_notes (bfd *abfd, char *buf, size_t size,
file_ptr offset, size_t align);
_bfd_error_handler (_("%pB symbol number %lu references"
" nonexistent SHT_SYMTAB_SHNDX section"),
ibfd, (unsigned long) symoffset);
- if (alloc_intsym != NULL)
- free (alloc_intsym);
+ free (alloc_intsym);
intsym_buf = NULL;
goto out;
}
out:
- if (alloc_ext != NULL)
- free (alloc_ext);
- if (alloc_extshndx != NULL)
- free (alloc_extshndx);
+ free (alloc_ext);
+ free (alloc_extshndx);
return intsym_buf;
}
if ((this_hdr->sh_flags & SHF_LINK_ORDER) != 0)
{
unsigned int elfsec = this_hdr->sh_link;
- /* FIXME: The old Intel compiler and old strip/objcopy may
- not set the sh_link or sh_info fields. Hence we could
- get the situation where elfsec is 0. */
+ /* An sh_link value of 0 is now allowed. It indicates that linked
+ to section has already been discarded, but that the current
+ section has been retained for some other reason. This linking
+ section is still a candidate for later garbage collection
+ however. */
if (elfsec == 0)
{
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- if (bed->link_order_error_handler)
- bed->link_order_error_handler
- /* xgettext:c-format */
- (_("%pB: warning: sh_link not set for section `%pA'"),
- abfd, s);
+ elf_linked_to_section (s) = NULL;
}
else
{
asection *newsect;
flagword flags;
const struct elf_backend_data *bed;
+ unsigned int opb = bfd_octets_per_byte (abfd, NULL);
if (hdr->bfd_section != NULL)
return TRUE;
newsect->filepos = hdr->sh_offset;
- if (!bfd_set_section_vma (newsect, hdr->sh_addr)
- || !bfd_set_section_size (newsect, hdr->sh_size)
- || !bfd_set_section_alignment (newsect, bfd_log2 (hdr->sh_addralign)))
- return FALSE;
-
flags = SEC_NO_FLAGS;
if (hdr->sh_type != SHT_NOBITS)
flags |= SEC_HAS_CONTENTS;
/* FIXME: We should not recognize SHF_GNU_MBIND for ELFOSABI_NONE,
but binutils as of 2019-07-23 did not set the EI_OSABI header
byte. */
- case ELFOSABI_NONE:
case ELFOSABI_GNU:
case ELFOSABI_FREEBSD:
+ if ((hdr->sh_flags & SHF_GNU_RETAIN) != 0)
+ elf_tdata (abfd)->has_gnu_osabi |= elf_gnu_osabi_retain;
+ /* Fall through */
+ case ELFOSABI_NONE:
if ((hdr->sh_flags & SHF_GNU_MBIND) != 0)
elf_tdata (abfd)->has_gnu_osabi |= elf_gnu_osabi_mbind;
break;
flags |= SEC_DEBUGGING | SEC_ELF_OCTETS;
else if (strncmp (name, GNU_BUILD_ATTRS_SECTION_NAME, 21) == 0
|| strncmp (name, ".note.gnu", 9) == 0)
- flags |= SEC_ELF_OCTETS;
+ {
+ flags |= SEC_ELF_OCTETS;
+ opb = 1;
+ }
else if (strncmp (name, ".line", 5) == 0
|| strncmp (name, ".stab", 5) == 0
|| strcmp (name, ".gdb_index") == 0)
}
}
+ if (!bfd_set_section_vma (newsect, hdr->sh_addr / opb)
+ || !bfd_set_section_size (newsect, hdr->sh_size)
+ || !bfd_set_section_alignment (newsect, bfd_log2 (hdr->sh_addralign)))
+ return FALSE;
+
/* As a GNU extension, if the name begins with .gnu.linkonce, we
only link a single copy of the section. This is used to support
g++. g++ will emit each template expansion in its own section.
{
if ((newsect->flags & SEC_LOAD) == 0)
newsect->lma = (phdr->p_paddr
- + hdr->sh_addr - phdr->p_vaddr);
+ + hdr->sh_addr - phdr->p_vaddr) / opb;
else
/* We used to use the same adjustment for SEC_LOAD
sections, but that doesn't work if the segment
segment will contain sections with contiguous
LMAs, even if the VMAs are not. */
newsect->lma = (phdr->p_paddr
- + hdr->sh_offset - phdr->p_offset);
+ + hdr->sh_offset - phdr->p_offset) / opb;
/* With contiguous segments, we can't tell from file
offsets whether a section with zero size should
}
/* Allow the target a chance to decide how these fields should be set. */
- if (bed->elf_backend_copy_special_section_fields != NULL
- && bed->elf_backend_copy_special_section_fields
- (ibfd, obfd, iheader, oheader))
+ if (bed->elf_backend_copy_special_section_fields (ibfd, obfd,
+ iheader, oheader))
return TRUE;
/* We have an iheader which might match oheader, and which has non-zero
{
/* Final attempt. Call the backend copy function
with a NULL input section. */
- if (bed->elf_backend_copy_special_section_fields != NULL)
- (void) bed->elf_backend_copy_special_section_fields (ibfd, obfd, NULL, oheader);
+ (void) bed->elf_backend_copy_special_section_fields (ibfd, obfd,
+ NULL, oheader);
}
}
return TRUE;
error_return:
- if (dynbuf != NULL)
- free (dynbuf);
+ free (dynbuf);
return FALSE;
}
-/* Get version string. */
+/* Get version name. If BASE_P is TRUE, return "Base" for VER_FLG_BASE
+ and return symbol version for symbol version itself. */
const char *
_bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol,
+ bfd_boolean base_p,
bfd_boolean *hidden)
{
const char *version_string = NULL;
&& (vernum > elf_tdata (abfd)->cverdefs
|| (elf_tdata (abfd)->verdef[0].vd_flags
== VER_FLG_BASE)))
- version_string = "Base";
+ version_string = base_p ? "Base" : "";
else if (vernum <= elf_tdata (abfd)->cverdefs)
- version_string =
- elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
+ {
+ const char *nodename
+ = elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
+ version_string = "";
+ if (base_p
+ || nodename == NULL
+ || symbol->name == NULL
+ || strcmp (symbol->name, nodename) != 0)
+ version_string = nodename;
+ }
else
{
Elf_Internal_Verneed *t;
/* If we have version information, print it. */
version_string = _bfd_elf_get_symbol_version_string (abfd,
symbol,
+ TRUE,
&hidden);
if (version_string)
{
const struct elf_backend_data *bed;
const char *name;
bfd_boolean ret = TRUE;
- static bfd_boolean * sections_being_created = NULL;
- static bfd * sections_being_created_abfd = NULL;
- static unsigned int nesting = 0;
if (shindex >= elf_numsections (abfd))
return FALSE;
- if (++ nesting > 3)
+ /* PR17512: A corrupt ELF binary might contain a loop of sections via
+ sh_link or sh_info. Detect this here, by refusing to load a
+ section that we are already in the process of loading. */
+ if (elf_tdata (abfd)->being_created[shindex])
{
- /* PR17512: A corrupt ELF binary might contain a recursive group of
- sections, with each the string indices pointing to the next in the
- loop. Detect this here, by refusing to load a section that we are
- already in the process of loading. We only trigger this test if
- we have nested at least three sections deep as normal ELF binaries
- can expect to recurse at least once.
-
- FIXME: It would be better if this array was attached to the bfd,
- rather than being held in a static pointer. */
-
- if (sections_being_created_abfd != abfd)
- sections_being_created = NULL;
- if (sections_being_created == NULL)
- {
- size_t amt = elf_numsections (abfd) * sizeof (bfd_boolean);
- sections_being_created = (bfd_boolean *) bfd_zalloc (abfd, amt);
- if (sections_being_created == NULL)
- return FALSE;
- sections_being_created_abfd = abfd;
- }
- if (sections_being_created [shindex])
- {
- _bfd_error_handler
- (_("%pB: warning: loop in section dependencies detected"), abfd);
- return FALSE;
- }
- sections_being_created [shindex] = TRUE;
+ _bfd_error_handler
+ (_("%pB: warning: loop in section dependencies detected"), abfd);
+ return FALSE;
}
+ elf_tdata (abfd)->being_created[shindex] = TRUE;
hdr = elf_elfsections (abfd)[shindex];
ehdr = elf_elfheader (abfd);
sections. */
if (*p_hdr != NULL)
{
- if (bed->init_secondary_reloc_section == NULL
- || ! bed->init_secondary_reloc_section (abfd, hdr, name, shindex))
+ if (!bed->init_secondary_reloc_section (abfd, hdr, name, shindex))
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%pB: warning: secondary relocation section '%s' for section %pA found - ignoring"),
+ (_("%pB: warning: secondary relocation section '%s' "
+ "for section %pA found - ignoring"),
abfd, name, target_sect);
}
goto success;
fail:
ret = FALSE;
success:
- if (sections_being_created && sections_being_created_abfd == abfd)
- sections_being_created [shindex] = FALSE;
- if (-- nesting == 0)
- {
- sections_being_created = NULL;
- sections_being_created_abfd = abfd;
- }
+ elf_tdata (abfd)->being_created[shindex] = FALSE;
return ret;
}
static const struct bfd_elf_special_section special_sections_g[] =
{
{ STRING_COMMA_LEN (".gnu.linkonce.b"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".gnu.linkonce.n"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".gnu.linkonce.p"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".gnu.lto_"), -1, SHT_PROGBITS, SHF_EXCLUDE },
{ STRING_COMMA_LEN (".got"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".gnu.version"), 0, SHT_GNU_versym, 0 },
static const struct bfd_elf_special_section special_sections_n[] =
{
+ { STRING_COMMA_LEN (".noinit"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".note.GNU-stack"), 0, SHT_PROGBITS, 0 },
{ STRING_COMMA_LEN (".note"), -1, SHT_NOTE, 0 },
{ NULL, 0, 0, 0, 0 }
static const struct bfd_elf_special_section special_sections_p[] =
{
+ { STRING_COMMA_LEN (".persistent"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".preinit_array"), -2, SHT_PREINIT_ARRAY, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".plt"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
{ NULL, 0, 0, 0, 0 }
char namebuf[64];
size_t len;
int split;
+ unsigned int opb = bfd_octets_per_byte (abfd, NULL);
split = ((hdr->p_memsz > 0)
&& (hdr->p_filesz > 0)
newsect = bfd_make_section (abfd, name);
if (newsect == NULL)
return FALSE;
- newsect->vma = hdr->p_vaddr;
- newsect->lma = hdr->p_paddr;
+ newsect->vma = hdr->p_vaddr / opb;
+ newsect->lma = hdr->p_paddr / opb;
newsect->size = hdr->p_filesz;
newsect->filepos = hdr->p_offset;
newsect->flags |= SEC_HAS_CONTENTS;
newsect = bfd_make_section (abfd, name);
if (newsect == NULL)
return FALSE;
- newsect->vma = hdr->p_vaddr + hdr->p_filesz;
- newsect->lma = hdr->p_paddr + hdr->p_filesz;
+ newsect->vma = (hdr->p_vaddr + hdr->p_filesz) / opb;
+ newsect->lma = (hdr->p_paddr + hdr->p_filesz) / opb;
newsect->size = hdr->p_memsz - hdr->p_filesz;
newsect->filepos = hdr->p_offset + hdr->p_filesz;
align = newsect->vma & -newsect->vma;
newsect->alignment_power = bfd_log2 (align);
if (hdr->p_type == PT_LOAD)
{
- /* Hack for gdb. Segments that have not been modified do
- not have their contents written to a core file, on the
- assumption that a debugger can find the contents in the
- executable. We flag this case by setting the fake
- section size to zero. Note that "real" bss sections will
- always have their contents dumped to the core file. */
- if (bfd_get_format (abfd) == bfd_core)
- newsect->size = 0;
newsect->flags |= SEC_ALLOC;
if (hdr->p_flags & PF_X)
newsect->flags |= SEC_CODE;
/* Set SEC_ELF_COMPRESS to indicate this section should be
compressed. */
asect->flags |= SEC_ELF_COMPRESS;
-
/* If this section will be compressed, delay adding section
name to section name section after it is compressed in
_bfd_elf_assign_file_positions_for_non_load. */
if ((asect->flags & SEC_ALLOC) != 0
|| asect->user_set_vma)
- this_hdr->sh_addr = asect->vma;
+ this_hdr->sh_addr = asect->vma * bfd_octets_per_byte (abfd, asect);
else
this_hdr->sh_addr = 0;
if (symindx == 0)
{
/* If called from the assembler, swap_out_syms will have set up
- elf_section_syms. */
- BFD_ASSERT (elf_section_syms (abfd) != NULL);
+ elf_section_syms.
+ PR 25699: A corrupt input file could contain bogus group info. */
+ if (elf_section_syms (abfd) == NULL)
+ {
+ *failedptr = TRUE;
+ return;
+ }
symindx = elf_section_syms (abfd)[sec->index]->udata.i;
}
elf_section_data (sec)->this_hdr.sh_info = symindx;
/* Assign all ELF section numbers. The dummy first section is handled here
too. The link/info pointers for the standard section types are filled
- in here too, while we're at it. */
+ in here too, while we're at it. LINK_INFO will be 0 when arriving
+ here for objcopy, and when using the generic ELF linker. */
static bfd_boolean
assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
if ((d->this_hdr.sh_flags & SHF_LINK_ORDER) != 0)
{
s = elf_linked_to_section (sec);
+ /* We can now have a NULL linked section pointer.
+ This happens when the sh_link field is 0, which is done
+ when a linked to section is discarded but the linking
+ section has been retained for some reason. */
if (s)
{
- /* elf_linked_to_section points to the input section. */
- if (link_info != NULL)
+ /* Check discarded linkonce section. */
+ if (discarded_section (s))
{
- /* Check discarded linkonce section. */
- if (discarded_section (s))
- {
- asection *kept;
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%pB: sh_link of section `%pA' points to"
- " discarded section `%pA' of `%pB'"),
- abfd, d->this_hdr.bfd_section,
- s, s->owner);
- /* Point to the kept section if it has the same
- size as the discarded one. */
- kept = _bfd_elf_check_kept_section (s, link_info);
- if (kept == NULL)
- {
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
- s = kept;
- }
-
- s = s->output_section;
- BFD_ASSERT (s != NULL);
- }
- else
- {
- /* Handle objcopy. */
- if (s->output_section == NULL)
+ asection *kept;
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: sh_link of section `%pA' points to"
+ " discarded section `%pA' of `%pB'"),
+ abfd, d->this_hdr.bfd_section, s, s->owner);
+ /* Point to the kept section if it has the same
+ size as the discarded one. */
+ kept = _bfd_elf_check_kept_section (s, link_info);
+ if (kept == NULL)
{
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%pB: sh_link of section `%pA' points to"
- " removed section `%pA' of `%pB'"),
- abfd, d->this_hdr.bfd_section, s, s->owner);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
- s = s->output_section;
+ s = kept;
}
+ /* Handle objcopy. */
+ else if (s->output_section == NULL)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: sh_link of section `%pA' points to"
+ " removed section `%pA' of `%pB'"),
+ abfd, d->this_hdr.bfd_section, s, s->owner);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ s = s->output_section;
d->this_hdr.sh_link = elf_section_data (s)->this_idx;
}
- else
- {
- /* PR 290:
- The Intel C compiler generates SHT_IA_64_UNWIND with
- SHF_LINK_ORDER. But it doesn't set the sh_link or
- sh_info fields. Hence we could get the situation
- where s is NULL. */
- const struct elf_backend_data *bed
- = get_elf_backend_data (abfd);
- if (bed->link_order_error_handler)
- bed->link_order_error_handler
- /* xgettext:c-format */
- (_("%pB: warning: sh_link not set for section `%pA'"),
- abfd, sec);
- }
}
switch (d->this_hdr.sh_type)
elf_section_data (s)->this_hdr.sh_link = d->this_idx;
/* This is a .stab section. */
- if (elf_section_data (s)->this_hdr.sh_entsize == 0)
- elf_section_data (s)->this_hdr.sh_entsize
- = 4 + 2 * bfd_get_arch_size (abfd) / 8;
+ elf_section_data (s)->this_hdr.sh_entsize = 12;
}
}
break;
if (sym->section == NULL)
return TRUE;
- type_ptr = elf_symbol_from (abfd, sym);
+ type_ptr = elf_symbol_from (sym);
return ((type_ptr != NULL
&& type_ptr->internal_elf_sym.st_shndx != 0
&& bfd_is_abs_section (sym->section))
/* Non-zero if doing a relocatable link. */
int relocatable_p = ! (abfd->flags & (EXEC_P | DYNAMIC));
- if (! swap_out_syms (abfd, &strtab, relocatable_p))
+ if (! swap_out_syms (abfd, &strtab, relocatable_p, link_info))
return FALSE;
}
&& (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_mbind) != 0)
{
/* Add a PT_GNU_MBIND segment for each mbind section. */
- unsigned int page_align_power = bfd_log2 (bed->commonpagesize);
+ bfd_vma commonpagesize;
+ unsigned int page_align_power;
+
+ if (info != NULL)
+ commonpagesize = info->commonpagesize;
+ else
+ commonpagesize = bed->commonpagesize;
+ page_align_power = bfd_log2 (commonpagesize);
for (s = abfd->sections; s != NULL; s = s->next)
if (elf_section_flags (s) & SHF_GNU_MBIND)
{
asection *first_mbind = NULL;
asection *dynsec, *eh_frame_hdr;
size_t amt;
- bfd_vma addr_mask, wrap_to = 0;
- bfd_size_type phdr_size;
+ bfd_vma addr_mask, wrap_to = 0; /* Bytes. */
+ bfd_size_type phdr_size; /* Octets/bytes. */
+ unsigned int opb = bfd_octets_per_byte (abfd, NULL);
/* Select the allocated sections, and sort them. */
sections[i] = s;
++i;
/* A wrapping section potentially clashes with header. */
- if (((s->lma + s->size) & addr_mask) < (s->lma & addr_mask))
- wrap_to = (s->lma + s->size) & addr_mask;
+ if (((s->lma + s->size / opb) & addr_mask) < (s->lma & addr_mask))
+ wrap_to = (s->lma + s->size / opb) & addr_mask;
}
}
BFD_ASSERT (i <= bfd_count_sections (abfd));
if (phdr_size == (bfd_size_type) -1)
phdr_size = get_program_header_size (abfd, info);
phdr_size += bed->s->sizeof_ehdr;
- maxpagesize = bed->maxpagesize;
+ /* phdr_size is compared to LMA values which are in bytes. */
+ phdr_size /= opb;
+ if (info != NULL)
+ maxpagesize = info->maxpagesize;
+ else
+ maxpagesize = bed->maxpagesize;
if (maxpagesize == 0)
maxpagesize = 1;
phdr_in_segment = info != NULL && info->load_phdrs;
program headers we will need. */
if (phdr_in_segment && count > 0)
{
- bfd_vma phdr_lma;
+ bfd_vma phdr_lma; /* Bytes. */
bfd_boolean separate_phdr = FALSE;
phdr_lma = (sections[0]->lma - phdr_size) & addr_mask & -maxpagesize;
m = make_mapping (abfd, sections, 0, 0, phdr_in_segment);
if (m == NULL)
goto error_return;
- m->p_paddr = phdr_lma;
+ m->p_paddr = phdr_lma * opb;
m->p_vaddr_offset
= (sections[0]->vma - phdr_size) & addr_mask & -maxpagesize;
m->p_paddr_valid = 1;
executable = TRUE;
last_hdr = hdr;
/* .tbss sections effectively have zero size. */
- last_size = !IS_TBSS (hdr) ? hdr->size : 0;
+ last_size = (!IS_TBSS (hdr) ? hdr->size : 0) / opb;
continue;
}
last_hdr = hdr;
/* .tbss sections effectively have zero size. */
- last_size = !IS_TBSS (hdr) ? hdr->size : 0;
+ last_size = (!IS_TBSS (hdr) ? hdr->size : 0) / opb;
hdr_index = i;
phdr_in_segment = FALSE;
}
if (s2->next->alignment_power == alignment_power
&& (s2->next->flags & SEC_LOAD) != 0
&& elf_section_type (s2->next) == SHT_NOTE
- && align_power (s2->lma + s2->size,
+ && align_power (s2->lma + s2->size / opb,
alignment_power)
== s2->next->lma)
count++;
{
i = m->count;
while (--i != (unsigned) -1)
- if ((m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS))
- == (SEC_LOAD | SEC_HAS_CONTENTS))
- break;
+ {
+ if (m->sections[i]->size > 0
+ && (m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS))
+ == (SEC_LOAD | SEC_HAS_CONTENTS))
+ break;
+ }
if (i != (unsigned) -1)
break;
return TRUE;
error_return:
- if (sections != NULL)
- free (sections);
+ free (sections);
return FALSE;
}
/* Put !SEC_LOAD sections after SEC_LOAD ones. */
-#define TOEND(x) (((x)->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0)
+#define TOEND(x) (((x)->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0 \
+ && (x)->size != 0)
if (TOEND (sec1))
{
return m1->no_sort_lma ? -1 : 1;
if (m1->p_type == PT_LOAD && !m1->no_sort_lma)
{
- bfd_vma lma1, lma2;
+ bfd_vma lma1, lma2; /* Octets. */
lma1 = 0;
if (m1->p_paddr_valid)
lma1 = m1->p_paddr;
else if (m1->count != 0)
- lma1 = m1->sections[0]->lma + m1->p_vaddr_offset;
+ {
+ unsigned int opb = bfd_octets_per_byte (m1->sections[0]->owner,
+ m1->sections[0]);
+ lma1 = (m1->sections[0]->lma + m1->p_vaddr_offset) * opb;
+ }
lma2 = 0;
if (m2->p_paddr_valid)
lma2 = m2->p_paddr;
else if (m2->count != 0)
- lma2 = m2->sections[0]->lma + m2->p_vaddr_offset;
+ {
+ unsigned int opb = bfd_octets_per_byte (m2->sections[0]->owner,
+ m2->sections[0]);
+ lma2 = (m2->sections[0]->lma + m2->p_vaddr_offset) * opb;
+ }
if (lma1 != lma2)
return lma1 < lma2 ? -1 : 1;
}
struct elf_segment_map *phdr_load_seg;
Elf_Internal_Phdr *phdrs;
Elf_Internal_Phdr *p;
- file_ptr off;
+ file_ptr off; /* Octets. */
bfd_size_type maxpagesize;
unsigned int alloc, actual;
unsigned int i, j;
struct elf_segment_map **sorted_seg_map;
+ unsigned int opb = bfd_octets_per_byte (abfd, NULL);
if (link_info == NULL
&& !_bfd_elf_map_sections_to_segments (abfd, link_info))
maxpagesize = 1;
if ((abfd->flags & D_PAGED) != 0)
- maxpagesize = bed->maxpagesize;
+ {
+ if (link_info != NULL)
+ maxpagesize = link_info->maxpagesize;
+ else
+ maxpagesize = bed->maxpagesize;
+ }
/* Sections must map to file offsets past the ELF file header. */
off = bed->s->sizeof_ehdr;
for (j = 0; j < alloc; j++)
{
asection **secpp;
- bfd_vma off_adjust;
+ bfd_vma off_adjust; /* Octets. */
bfd_boolean no_contents;
/* An ELF segment (described by Elf_Internal_Phdr) may contain a
p->p_flags = m->p_flags;
if (m->count == 0)
- p->p_vaddr = m->p_vaddr_offset;
+ p->p_vaddr = m->p_vaddr_offset * opb;
else
- p->p_vaddr = m->sections[0]->vma + m->p_vaddr_offset;
+ p->p_vaddr = (m->sections[0]->vma + m->p_vaddr_offset) * opb;
if (m->p_paddr_valid)
p->p_paddr = m->p_paddr;
else if (m->count == 0)
p->p_paddr = 0;
else
- p->p_paddr = m->sections[0]->lma + m->p_vaddr_offset;
+ p->p_paddr = (m->sections[0]->lma + m->p_vaddr_offset) * opb;
if (p->p_type == PT_LOAD
&& (abfd->flags & D_PAGED) != 0)
if (p->p_type == PT_LOAD
&& m->count > 0)
{
- bfd_size_type align;
+ bfd_size_type align; /* Bytes. */
unsigned int align_power = 0;
if (m->p_align_valid)
break;
}
- off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align);
+ off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align * opb);
/* Broken hardware and/or kernel require that files do not
map the same page with different permissions on some hppa
&& (abfd->flags & D_PAGED) != 0
&& bed->no_page_alias
&& (off & (maxpagesize - 1)) != 0
- && (off & -maxpagesize) == ((off + off_adjust) & -maxpagesize))
+ && ((off & -maxpagesize)
+ == ((off + off_adjust) & -maxpagesize)))
off_adjust += maxpagesize;
off += off_adjust;
if (no_contents)
else if (phdr_load_seg != NULL)
{
Elf_Internal_Phdr *phdr = phdrs + phdr_load_seg->idx;
- bfd_vma phdr_off = 0;
+ bfd_vma phdr_off = 0; /* Octets. */
if (phdr_load_seg->includes_filehdr)
phdr_off = bed->s->sizeof_ehdr;
p->p_vaddr = phdr->p_vaddr + phdr_off;
}
else
{
- file_ptr adjust;
+ file_ptr adjust; /* Octets. */
adjust = off - (p->p_offset + p->p_filesz);
if (!no_contents)
&& ((this_hdr->sh_flags & SHF_TLS) == 0
|| p->p_type == PT_TLS))))
{
- bfd_vma p_start = p->p_paddr;
- bfd_vma p_end = p_start + p->p_memsz;
- bfd_vma s_start = sec->lma;
- bfd_vma adjust = s_start - p_end;
+ bfd_vma p_start = p->p_paddr; /* Octets. */
+ bfd_vma p_end = p_start + p->p_memsz; /* Octets. */
+ bfd_vma s_start = sec->lma * opb; /* Octets. */
+ bfd_vma adjust = s_start - p_end; /* Octets. */
if (adjust != 0
&& (s_start < p_end
_bfd_error_handler
/* xgettext:c-format */
(_("%pB: section %pA lma %#" PRIx64 " adjusted to %#" PRIx64),
- abfd, sec, (uint64_t) s_start, (uint64_t) p_end);
+ abfd, sec, (uint64_t) s_start / opb,
+ (uint64_t) p_end / opb);
adjust = 0;
- sec->lma = p_end;
+ sec->lma = p_end / opb;
}
p->p_memsz += adjust;
- if (this_hdr->sh_type != SHT_NOBITS)
+ if (p->p_type == PT_LOAD)
{
- if (p->p_type == PT_LOAD)
+ if (this_hdr->sh_type != SHT_NOBITS)
{
+ off_adjust = 0;
if (p->p_filesz + adjust < p->p_memsz)
{
/* We have a PROGBITS section following NOBITS ones.
if (!write_zeros (abfd, off, adjust))
return FALSE;
}
+ }
+ /* We only adjust sh_offset in SHT_NOBITS sections
+ as would seem proper for their address when the
+ section is first in the segment. sh_offset
+ doesn't really have any significance for
+ SHT_NOBITS anyway, apart from a notional position
+ relative to other sections. Historically we
+ didn't bother with adjusting sh_offset and some
+ programs depend on it not being adjusted. See
+ pr12921 and pr25662. */
+ if (this_hdr->sh_type != SHT_NOBITS || i == 0)
+ {
off += adjust;
+ if (this_hdr->sh_type == SHT_NOBITS)
+ off_adjust += adjust;
}
- p->p_filesz += adjust;
}
+ if (this_hdr->sh_type != SHT_NOBITS)
+ p->p_filesz += adjust;
}
if (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core)
|| hash->root.type == bfd_link_hash_common))
{
asection *s = NULL;
- bfd_vma filehdr_vaddr = phdrs[phdr_load_seg->idx].p_vaddr;
+ bfd_vma filehdr_vaddr = phdrs[phdr_load_seg->idx].p_vaddr / opb;
if (phdr_load_seg->count != 0)
/* The segment contains sections, so use the first one. */
Elf_Internal_Phdr *p;
struct elf_segment_map *m;
file_ptr off;
+ unsigned int opb = bfd_octets_per_byte (abfd, NULL);
+ bfd_vma maxpagesize;
+ if (link_info != NULL)
+ maxpagesize = link_info->maxpagesize;
+ else
+ maxpagesize = bed->maxpagesize;
i_shdrpp = elf_elfsections (abfd);
end_hdrpp = i_shdrpp + elf_numsections (abfd);
off = elf_next_file_pos (abfd);
/* We don't need to page align empty sections. */
if ((abfd->flags & D_PAGED) != 0 && hdr->sh_size != 0)
off += vma_page_aligned_bias (hdr->sh_addr, off,
- bed->maxpagesize);
+ maxpagesize);
else
off += vma_page_aligned_bias (hdr->sh_addr, off,
hdr->sh_addralign);
{
if (p->p_type == PT_GNU_RELRO)
{
- bfd_vma start, end;
+ bfd_vma start, end; /* Bytes. */
bfd_boolean ok;
if (link_info != NULL)
if (!m->p_size_valid)
abort ();
start = m->sections[0]->vma;
- end = start + m->p_size;
+ end = start + m->p_size / opb;
}
else
{
&& lm->count != 0
&& (lm->sections[lm->count - 1]->vma
+ (!IS_TBSS (lm->sections[lm->count - 1])
- ? lm->sections[lm->count - 1]->size
+ ? lm->sections[lm->count - 1]->size / opb
: 0)) > start
&& lm->sections[0]->vma < end)
break;
if (i < lm->count)
{
- p->p_vaddr = lm->sections[i]->vma;
- p->p_paddr = lm->sections[i]->lma;
+ p->p_vaddr = lm->sections[i]->vma * opb;
+ p->p_paddr = lm->sections[i]->lma * opb;
p->p_offset = lm->sections[i]->filepos;
- p->p_memsz = end - p->p_vaddr;
+ p->p_memsz = end * opb - p->p_vaddr;
p->p_filesz = p->p_memsz;
/* The RELRO segment typically ends a few bytes
/* Rewrite program header information. */
static bfd_boolean
-rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
+rewrite_elf_program_header (bfd *ibfd, bfd *obfd, bfd_vma maxpagesize)
{
Elf_Internal_Ehdr *iehdr;
struct elf_segment_map *map;
unsigned int num_segments;
bfd_boolean phdr_included = FALSE;
bfd_boolean p_paddr_valid;
- bfd_vma maxpagesize;
struct elf_segment_map *phdr_adjust_seg = NULL;
unsigned int phdr_adjust_num = 0;
const struct elf_backend_data *bed;
+ unsigned int opb = bfd_octets_per_byte (ibfd, NULL);
bed = get_elf_backend_data (ibfd);
iehdr = elf_elfheader (ibfd);
pointer_to_map = &map_first;
num_segments = elf_elfheader (ibfd)->e_phnum;
- maxpagesize = get_elf_backend_data (obfd)->maxpagesize;
/* Returns the end address of the segment + 1. */
#define SEGMENT_END(segment, start) \
/* Returns TRUE if the given section is contained within
the given segment. VMA addresses are compared. */
-#define IS_CONTAINED_BY_VMA(section, segment) \
- (section->vma >= segment->p_vaddr \
- && (section->vma + SECTION_SIZE (section, segment) \
+#define IS_CONTAINED_BY_VMA(section, segment, opb) \
+ (section->vma * (opb) >= segment->p_vaddr \
+ && (section->vma * (opb) + SECTION_SIZE (section, segment) \
<= (SEGMENT_END (segment, segment->p_vaddr))))
/* Returns TRUE if the given section is contained within
the given segment. LMA addresses are compared. */
-#define IS_CONTAINED_BY_LMA(section, segment, base) \
- (section->lma >= base \
- && (section->lma + SECTION_SIZE (section, segment) >= section->lma) \
- && (section->lma + SECTION_SIZE (section, segment) \
+#define IS_CONTAINED_BY_LMA(section, segment, base, opb) \
+ (section->lma * (opb) >= base \
+ && (section->lma + SECTION_SIZE (section, segment) / (opb) >= section->lma) \
+ && (section->lma * (opb) + SECTION_SIZE (section, segment) \
<= SEGMENT_END (segment, base)))
/* Handle PT_NOTE segment. */
7. SHF_TLS sections are only in PT_TLS or PT_LOAD segments.
8. PT_DYNAMIC should not contain empty sections at the beginning
(with the possible exception of .dynamic). */
-#define IS_SECTION_IN_INPUT_SEGMENT(section, segment, bed) \
+#define IS_SECTION_IN_INPUT_SEGMENT(section, segment, bed, opb) \
((((segment->p_paddr \
- ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr) \
- : IS_CONTAINED_BY_VMA (section, segment)) \
+ ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr, opb) \
+ : IS_CONTAINED_BY_VMA (section, segment, opb)) \
&& (section->flags & SEC_ALLOC) != 0) \
|| IS_NOTE (segment, section)) \
&& segment->p_type != PT_GNU_STACK \
&& (segment->p_type != PT_DYNAMIC \
|| SECTION_SIZE (section, segment) > 0 \
|| (segment->p_paddr \
- ? segment->p_paddr != section->lma \
- : segment->p_vaddr != section->vma) \
+ ? segment->p_paddr != section->lma * (opb) \
+ : segment->p_vaddr != section->vma * (opb)) \
|| (strcmp (bfd_section_name (section), ".dynamic") == 0)) \
&& (segment->p_type != PT_LOAD || !section->segment_mark))
/* If the output section of a section in the input segment is NULL,
it is removed from the corresponding output segment. */
-#define INCLUDE_SECTION_IN_SEGMENT(section, segment, bed) \
- (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed) \
+#define INCLUDE_SECTION_IN_SEGMENT(section, segment, bed, opb) \
+ (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed, opb) \
&& section->output_section != NULL)
/* Returns TRUE iff seg1 starts after the end of seg2. */
{
/* Mininal change so that the normal section to segment
assignment code will work. */
- segment->p_vaddr = section->vma;
+ segment->p_vaddr = section->vma * opb;
break;
}
{
/* Find the first section in the input segment, which may be
removed from the corresponding output segment. */
- if (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed))
+ if (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed, opb))
{
if (first_section == NULL)
first_section = section;
map->p_flags = segment->p_flags;
map->p_flags_valid = 1;
+ if (map->p_type == PT_LOAD
+ && (ibfd->flags & D_PAGED) != 0
+ && maxpagesize > 1
+ && segment->p_align > 1)
+ {
+ map->p_align = segment->p_align;
+ if (segment->p_align > maxpagesize)
+ map->p_align = maxpagesize;
+ map->p_align_valid = 1;
+ }
+
/* If the first section in the input segment is removed, there is
no need to preserve segment physical address in the corresponding
output segment. */
" at vaddr=%#" PRIx64 ", is this intentional?"),
ibfd, (uint64_t) segment->p_vaddr);
- map->p_vaddr_offset = segment->p_vaddr;
+ map->p_vaddr_offset = segment->p_vaddr / opb;
map->count = 0;
*pointer_to_map = map;
pointer_to_map = &map->next;
section != NULL;
section = section->next)
{
- if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed))
+ if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed, opb))
{
output_section = section->output_section;
+ (map->includes_phdrs
? iehdr->e_phnum * iehdr->e_phentsize
: 0),
- output_section->alignment_power)
- == output_section->vma))
+ output_section->alignment_power * opb)
+ == (output_section->vma * opb)))
map->p_paddr = segment->p_vaddr;
/* Match up the physical address of the segment with the
LMA address of the output section. */
- if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr)
+ if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr,
+ opb)
|| IS_COREFILE_NOTE (segment, section)
|| (bed->want_p_paddr_set_to_zero
- && IS_CONTAINED_BY_VMA (output_section, segment)))
+ && IS_CONTAINED_BY_VMA (output_section, segment, opb)))
{
if (matching_lma == NULL
|| output_section->lma < matching_lma->lma)
/* Account for padding before the first section in the
segment. */
- map->p_vaddr_offset = map->p_paddr + hdr_size - matching_lma->lma;
+ map->p_vaddr_offset = ((map->p_paddr + hdr_size) / opb
+ - matching_lma->lma);
}
free (sections);
if (matching_lma == NULL)
matching_lma = suggested_lma;
- map->p_paddr = matching_lma->lma;
+ map->p_paddr = matching_lma->lma * opb;
/* Offset the segment physical address from the lma
to allow for space taken up by elf headers. */
the same alignment. */
if (segment->p_align != 0 && segment->p_align < align)
align = segment->p_align;
- map->p_paddr &= -align;
+ map->p_paddr &= -(align * opb);
}
}
BFD_ASSERT (output_section != NULL);
- if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr)
+ if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr,
+ opb)
|| IS_COREFILE_NOTE (segment, section))
{
if (map->count == 0)
+ (map->includes_phdrs
? iehdr->e_phnum * iehdr->e_phentsize
: 0),
- output_section->alignment_power)
- != output_section->lma)
+ output_section->alignment_power * opb)
+ != output_section->lma * opb)
goto sorry;
}
else
map->p_type = segment->p_type;
map->p_flags = segment->p_flags;
map->p_flags_valid = 1;
- map->p_paddr = suggested_lma->lma;
+ map->p_paddr = suggested_lma->lma * opb;
map->p_paddr_valid = p_paddr_valid;
map->includes_filehdr = 0;
map->includes_phdrs = 0;
unsigned int num_segments;
bfd_boolean phdr_included = FALSE;
bfd_boolean p_paddr_valid;
+ unsigned int opb = bfd_octets_per_byte (ibfd, NULL);
iehdr = elf_elfheader (ibfd);
seg_off = this_hdr->sh_offset - segment->p_offset;
else
seg_off = this_hdr->sh_addr - segment->p_vaddr;
- if (section->lma - segment->p_paddr != seg_off)
+ if (section->lma * opb - segment->p_paddr != seg_off)
map->p_paddr_valid = FALSE;
}
if (isec == section_count)
}
if (section_count == 0)
- map->p_vaddr_offset = segment->p_vaddr;
+ map->p_vaddr_offset = segment->p_vaddr / opb;
else if (map->p_paddr_valid)
{
/* Account for padding before the first section in the segment. */
if (map->includes_phdrs)
hdr_size += iehdr->e_phnum * iehdr->e_phentsize;
- map->p_vaddr_offset = (map->p_paddr + hdr_size
+ map->p_vaddr_offset = ((map->p_paddr + hdr_size) / opb
- (lowest_section ? lowest_section->lma : 0));
}
static bfd_boolean
copy_private_bfd_data (bfd *ibfd, bfd *obfd)
{
+ bfd_vma maxpagesize;
+
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return TRUE;
}
rewrite:
+ maxpagesize = 0;
if (ibfd->xvec == obfd->xvec)
{
/* When rewriting program header, set the output maxpagesize to
Elf_Internal_Phdr *segment;
unsigned int i;
unsigned int num_segments = elf_elfheader (ibfd)->e_phnum;
- bfd_vma maxpagesize = 0;
for (i = 0, segment = elf_tdata (ibfd)->phdr;
i < num_segments;
else
maxpagesize = segment->p_align;
}
-
- if (maxpagesize != get_elf_backend_data (obfd)->maxpagesize)
- bfd_emul_set_maxpagesize (bfd_get_target (obfd), maxpagesize);
}
+ if (maxpagesize == 0)
+ maxpagesize = get_elf_backend_data (obfd)->maxpagesize;
- return rewrite_elf_program_header (ibfd, obfd);
+ return rewrite_elf_program_header (ibfd, obfd, maxpagesize);
}
/* Initialize private output section information from input section. */
elf_section_flags (s->output_section) &= ~SHF_GROUP;
elf_group_name (s->output_section) = NULL;
}
- /* Conversely, if the member section is not being output
- but the SHT_GROUP section is, then adjust its size. */
- else if (s->output_section == discarded
- && isec->output_section != discarded)
+ else
{
struct bfd_elf_section_data *elf_sec = elf_section_data (s);
- removed += 4;
- if (elf_sec->rel.hdr != NULL
- && (elf_sec->rel.hdr->sh_flags & SHF_GROUP) != 0)
- removed += 4;
- if (elf_sec->rela.hdr != NULL
- && (elf_sec->rela.hdr->sh_flags & SHF_GROUP) != 0)
- removed += 4;
+ if (s->output_section == discarded
+ && isec->output_section != discarded)
+ {
+ /* Conversely, if the member section is not being
+ output but the SHT_GROUP section is, then adjust
+ its size. */
+ removed += 4;
+ if (elf_sec->rel.hdr != NULL
+ && (elf_sec->rel.hdr->sh_flags & SHF_GROUP) != 0)
+ removed += 4;
+ if (elf_sec->rela.hdr != NULL
+ && (elf_sec->rela.hdr->sh_flags & SHF_GROUP) != 0)
+ removed += 4;
+ }
+ else
+ {
+ /* Also adjust for zero-sized relocation member
+ section. */
+ if (elf_sec->rel.hdr != NULL
+ && elf_sec->rel.hdr->sh_size == 0)
+ removed += 4;
+ if (elf_sec->rela.hdr != NULL
+ && elf_sec->rela.hdr->sh_size == 0)
+ removed += 4;
+ }
}
s = elf_next_in_group (s);
if (s == first)
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return TRUE;
- isym = elf_symbol_from (ibfd, isymarg);
- osym = elf_symbol_from (obfd, osymarg);
+ isym = elf_symbol_from (isymarg);
+ osym = elf_symbol_from (osymarg);
if (isym != NULL
&& isym->internal_elf_sym.st_shndx != 0
static bfd_boolean
swap_out_syms (bfd *abfd,
struct elf_strtab_hash **sttp,
- int relocatable_p)
+ int relocatable_p,
+ struct bfd_link_info *info)
{
const struct elf_backend_data *bed;
unsigned int symcount;
goto error_return;
}
- type_ptr = elf_symbol_from (abfd, syms[idx]);
+ type_ptr = elf_symbol_from (syms[idx]);
if ((flags & BSF_SECTION_SYM) == 0
&& bfd_is_com_section (syms[idx]->section))
else
elfsym->sym.st_name = _bfd_elf_strtab_offset (stt,
elfsym->sym.st_name);
+ if (info && info->callbacks->ctf_new_symbol)
+ info->callbacks->ctf_new_symbol (elfsym->dest_index,
+ &elfsym->sym);
+
+ /* Inform the linker of the addition of this symbol. */
+
bed->s->swap_symbol_out (abfd, &elfsym->sym,
(outbound_syms
+ (elfsym->dest_index
Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->symtab_hdr;
symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
- if (symcount >= LONG_MAX / sizeof (asymbol *))
+ if (symcount > LONG_MAX / sizeof (asymbol *))
{
bfd_set_error (bfd_error_file_too_big);
return -1;
}
- symtab_size = (symcount + 1) * (sizeof (asymbol *));
- if (symcount > 0)
- symtab_size -= sizeof (asymbol *);
+ symtab_size = symcount * (sizeof (asymbol *));
+ if (symcount == 0)
+ symtab_size = sizeof (asymbol *);
+ else if (!bfd_write_p (abfd))
+ {
+ ufile_ptr filesize = bfd_get_file_size (abfd);
+
+ if (filesize != 0 && (unsigned long) symtab_size > filesize)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return -1;
+ }
+ }
return symtab_size;
}
}
symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
- if (symcount >= LONG_MAX / sizeof (asymbol *))
+ if (symcount > LONG_MAX / sizeof (asymbol *))
{
bfd_set_error (bfd_error_file_too_big);
return -1;
}
- symtab_size = (symcount + 1) * (sizeof (asymbol *));
- if (symcount > 0)
- symtab_size -= sizeof (asymbol *);
+ symtab_size = symcount * (sizeof (asymbol *));
+ if (symcount == 0)
+ symtab_size = sizeof (asymbol *);
+ else if (!bfd_write_p (abfd))
+ {
+ ufile_ptr filesize = bfd_get_file_size (abfd);
+
+ if (filesize != 0 && (unsigned long) symtab_size > filesize)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return -1;
+ }
+ }
return symtab_size;
}
long
-_bfd_elf_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
- sec_ptr asect)
+_bfd_elf_get_reloc_upper_bound (bfd *abfd, sec_ptr asect)
{
+ if (asect->reloc_count != 0 && !bfd_write_p (abfd))
+ {
+ /* Sanity check reloc section size. */
+ struct bfd_elf_section_data *d = elf_section_data (asect);
+ Elf_Internal_Shdr *rel_hdr = &d->this_hdr;
+ bfd_size_type ext_rel_size = rel_hdr->sh_size;
+ ufile_ptr filesize = bfd_get_file_size (abfd);
+
+ if (filesize != 0 && ext_rel_size > filesize)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return -1;
+ }
+ }
+
#if SIZEOF_LONG == SIZEOF_INT
if (asect->reloc_count >= LONG_MAX / sizeof (arelent *))
{
long
_bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
{
- bfd_size_type count;
+ bfd_size_type count, ext_rel_size;
asection *s;
if (elf_dynsymtab (abfd) == 0)
}
count = 1;
+ ext_rel_size = 0;
for (s = abfd->sections; s != NULL; s = s->next)
if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
&& (elf_section_data (s)->this_hdr.sh_type == SHT_REL
|| elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
{
+ ext_rel_size += s->size;
+ if (ext_rel_size < s->size)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return -1;
+ }
count += s->size / elf_section_data (s)->this_hdr.sh_entsize;
if (count > LONG_MAX / sizeof (arelent *))
{
return -1;
}
}
+ if (count > 1 && !bfd_write_p (abfd))
+ {
+ /* Sanity check reloc section sizes. */
+ ufile_ptr filesize = bfd_get_file_size (abfd);
+ if (filesize != 0 && ext_rel_size > filesize)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return -1;
+ }
+ }
return count * sizeof (arelent *);
}
return TRUE;
error_return:
- if (contents != NULL)
- free (contents);
+ free (contents);
return FALSE;
}
\f
hdr = &elf_section_data (section)->this_hdr;
if (hdr->sh_offset == (file_ptr) -1)
{
+ unsigned char *contents;
+
if (bfd_section_is_ctf (section))
/* Nothing to do with this section: the contents are generated
later. */
return TRUE;
- /* We must compress this section. Write output to the buffer. */
- unsigned char *contents = hdr->contents;
- if ((offset + count) > hdr->sh_size
- || (section->flags & SEC_ELF_COMPRESS) == 0
- || contents == NULL)
- abort ();
+ if ((section->flags & SEC_ELF_COMPRESS) == 0)
+ {
+ _bfd_error_handler
+ (_("%pB:%pA: error: attempting to write into an unallocated compressed section"),
+ abfd, section);
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
+ }
+
+ if ((offset + count) > hdr->sh_size)
+ {
+ _bfd_error_handler
+ (_("%pB:%pA: error: attempting to write over the end of the section"),
+ abfd, section);
+
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
+ }
+
+ contents = hdr->contents;
+ if (contents == NULL)
+ {
+ _bfd_error_handler
+ (_("%pB:%pA: error: attempting to write section into an empty buffer"),
+ abfd, section);
+
+ bfd_set_error (bfd_error_invalid_operation);
+ return FALSE;
+ }
+
memcpy (contents + offset, location, count);
return TRUE;
}
+
pos = hdr->sh_offset + offset;
if (bfd_seek (abfd, pos, SEEK_SET) != 0
|| bfd_bwrite (location, count, abfd) != count)
_bfd_elf_close_and_cleanup (bfd *abfd)
{
struct elf_obj_tdata *tdata = elf_tdata (abfd);
- if (bfd_get_format (abfd) == bfd_object && tdata != NULL)
+ if (tdata != NULL
+ && (bfd_get_format (abfd) == bfd_object
+ || bfd_get_format (abfd) == bfd_core))
{
if (elf_tdata (abfd)->o != NULL && elf_shstrtab (abfd) != NULL)
_bfd_elf_strtab_free (elf_shstrtab (abfd));
out details about the corefile. */
#ifdef HAVE_SYS_PROCFS_H
-/* Needed for new procfs interface on sparc-solaris. */
-# define _STRUCTURED_PROC 1
# include <sys/procfs.h>
#endif
return elfcore_make_note_pseudosection (abfd, ".reg-aarch-pauth", note);
}
+static bfd_boolean
+elfcore_grok_arc_v2 (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-arc-v2", note);
+}
+
#if defined (HAVE_PRPSINFO_T)
typedef prpsinfo_t elfcore_psinfo_t;
#if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */
}
#endif /* defined (HAVE_LWPSTATUS_T) */
+/* These constants, and the structure offsets used below, are defined by
+ Cygwin's core_dump.h */
+#define NOTE_INFO_PROCESS 1
+#define NOTE_INFO_THREAD 2
+#define NOTE_INFO_MODULE 3
+#define NOTE_INFO_MODULE64 4
+
static bfd_boolean
elfcore_grok_win32pstatus (bfd *abfd, Elf_Internal_Note *note)
{
char buf[30];
char *name;
size_t len;
+ unsigned int name_size;
asection *sect;
- int type;
+ unsigned int type;
int is_active_thread;
bfd_vma base_addr;
- if (note->descsz < 728)
+ if (note->descsz < 4)
return TRUE;
if (! CONST_STRNEQ (note->namedata, "win32"))
type = bfd_get_32 (abfd, note->descdata);
+ struct {
+ const char *type_name;
+ unsigned long min_size;
+ } size_check[] =
+ {
+ { "NOTE_INFO_PROCESS", 12 },
+ { "NOTE_INFO_THREAD", 12 },
+ { "NOTE_INFO_MODULE", 12 },
+ { "NOTE_INFO_MODULE64", 16 },
+ };
+
+ if (type > (sizeof(size_check)/sizeof(size_check[0])))
+ return TRUE;
+
+ if (note->descsz < size_check[type - 1].min_size)
+ {
+ _bfd_error_handler (_("%pB: warning: win32pstatus %s of size %lu bytes is too small"),
+ abfd, size_check[type - 1].type_name, note->descsz);
+ return TRUE;
+ }
+
switch (type)
{
- case 1 /* NOTE_INFO_PROCESS */:
+ case NOTE_INFO_PROCESS:
/* FIXME: need to add ->core->command. */
- /* process_info.pid */
- elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 8);
- /* process_info.signal */
- elf_tdata (abfd)->core->signal = bfd_get_32 (abfd, note->descdata + 12);
+ elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 4);
+ elf_tdata (abfd)->core->signal = bfd_get_32 (abfd, note->descdata + 8);
break;
- case 2 /* NOTE_INFO_THREAD */:
- /* Make a ".reg/999" section. */
+ case NOTE_INFO_THREAD:
+ /* Make a ".reg/<tid>" section containing the Win32 API thread CONTEXT
+ structure. */
/* thread_info.tid */
- sprintf (buf, ".reg/%ld", (long) bfd_get_32 (abfd, note->descdata + 8));
+ sprintf (buf, ".reg/%ld", (long) bfd_get_32 (abfd, note->descdata + 4));
len = strlen (buf) + 1;
name = (char *) bfd_alloc (abfd, len);
return FALSE;
/* sizeof (thread_info.thread_context) */
- sect->size = 716;
+ sect->size = note->descsz - 12;
/* offsetof (thread_info.thread_context) */
sect->filepos = note->descpos + 12;
sect->alignment_power = 2;
return FALSE;
break;
- case 3 /* NOTE_INFO_MODULE */:
+ case NOTE_INFO_MODULE:
+ case NOTE_INFO_MODULE64:
/* Make a ".module/xxxxxxxx" section. */
- /* module_info.base_address */
- base_addr = bfd_get_32 (abfd, note->descdata + 4);
- sprintf (buf, ".module/%08lx", (unsigned long) base_addr);
+ if (type == NOTE_INFO_MODULE)
+ {
+ /* module_info.base_address */
+ base_addr = bfd_get_32 (abfd, note->descdata + 4);
+ sprintf (buf, ".module/%08lx", (unsigned long) base_addr);
+ /* module_info.module_name_size */
+ name_size = bfd_get_32 (abfd, note->descdata + 8);
+ }
+ else /* NOTE_INFO_MODULE64 */
+ {
+ /* module_info.base_address */
+ base_addr = bfd_get_64 (abfd, note->descdata + 4);
+ sprintf (buf, ".module/%016lx", (unsigned long) base_addr);
+ /* module_info.module_name_size */
+ name_size = bfd_get_32 (abfd, note->descdata + 12);
+ }
len = strlen (buf) + 1;
name = (char *) bfd_alloc (abfd, len);
if (sect == NULL)
return FALSE;
+ if (note->descsz < 12 + name_size)
+ {
+ _bfd_error_handler (_("%pB: win32pstatus NOTE_INFO_MODULE of size %lu is too small to contain a name of size %u"),
+ abfd, note->descsz, name_size);
+ return TRUE;
+ }
+
sect->size = note->descsz;
sect->filepos = note->descpos;
sect->alignment_power = 2;
else
return TRUE;
+ case NT_ARC_V2:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_arc_v2 (abfd, note);
+ else
+ return TRUE;
+
case NT_ARM_VFP:
if (note->namesz == 6
&& strcmp (note->namedata, "LINUX") == 0)
case NT_NETBSDCORE_AUXV:
/* NetBSD-specific Elf Auxiliary Vector data. */
return elfcore_make_auxv_note_section (abfd, note, 4);
+#endif
+#ifdef NT_NETBSDCORE_LWPSTATUS
+ case NT_NETBSDCORE_LWPSTATUS:
+ return elfcore_make_note_pseudosection (abfd,
+ ".note.netbsdcore.lwpstatus",
+ note);
#endif
default:
break;
}
- /* As of March 2017 there are no other machine-independent notes
+ /* As of March 2020 there are no other machine-independent notes
defined for NetBSD core files. If the note type is less
than the start of the machine-dependent note types, we don't
understand it. */
/* On the Alpha, SPARC (32-bit and 64-bit), PT_GETREGS == mach+0 and
PT_GETFPREGS == mach+2. */
+ case bfd_arch_aarch64:
case bfd_arch_alpha:
case bfd_arch_sparc:
switch (note->type)
note_name, NT_ARM_PAC_MASK, aarch_pauth, size);
}
+char *
+elfcore_write_arc_v2 (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *arc_v2,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_ARC_V2, arc_v2, size);
+}
+
char *
elfcore_write_register_note (bfd *abfd,
char *buf,
return elfcore_write_aarch_sve (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-aarch-pauth") == 0)
return elfcore_write_aarch_pauth (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-arc-v2") == 0)
+ return elfcore_write_arc_v2 (abfd, buf, bufsiz, data, size);
return NULL;
}
i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
/* Set the osabi field to ELFOSABI_GNU if the binary contains
- SHF_GNU_MBIND sections or symbols of STT_GNU_IFUNC type or
- STB_GNU_UNIQUE binding. */
+ SHF_GNU_MBIND or SHF_GNU_RETAIN sections or symbols of STT_GNU_IFUNC type
+ or STB_GNU_UNIQUE binding. */
if (elf_tdata (abfd)->has_gnu_osabi != 0)
{
if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE)
&& i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_FREEBSD)
{
if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_mbind)
- _bfd_error_handler (_("GNU_MBIND section is unsupported"));
+ _bfd_error_handler (_("GNU_MBIND section is supported only by GNU "
+ "and FreeBSD targets"));
if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_ifunc)
- _bfd_error_handler (_("symbol type STT_GNU_IFUNC is unsupported"));
+ _bfd_error_handler (_("symbol type STT_GNU_IFUNC is supported "
+ "only by GNU and FreeBSD targets"));
if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_unique)
- _bfd_error_handler (_("symbol binding STB_GNU_UNIQUE is unsupported"));
+ _bfd_error_handler (_("symbol binding STB_GNU_UNIQUE is supported "
+ "only by GNU and FreeBSD targets"));
+ if (elf_tdata (abfd)->has_gnu_osabi & elf_gnu_osabi_retain)
+ _bfd_error_handler (_("GNU_RETAIN section is supported "
+ "only by GNU and FreeBSD targets"));
bfd_set_error (bfd_error_sorry);
return FALSE;
}
/* Read in any secondary relocs associated with SEC. */
bfd_boolean
-_bfd_elf_slurp_secondary_reloc_section (bfd * abfd,
- asection * sec,
- asymbol ** symbols)
+_bfd_elf_slurp_secondary_reloc_section (bfd * abfd,
+ asection * sec,
+ asymbol ** symbols,
+ bfd_boolean dynamic)
{
const struct elf_backend_data * const ebd = get_elf_backend_data (abfd);
asection * relsec;
Elf_Internal_Shdr * hdr = & elf_section_data (relsec)->this_hdr;
if (hdr->sh_type == SHT_SECONDARY_RELOC
- && hdr->sh_info == (unsigned) elf_section_data (sec)->this_idx)
+ && hdr->sh_info == (unsigned) elf_section_data (sec)->this_idx
+ && (hdr->sh_entsize == ebd->s->sizeof_rel
+ || hdr->sh_entsize == ebd->s->sizeof_rela))
{
bfd_byte * native_relocs;
bfd_byte * native_reloc;
reloc_count = NUM_SHDR_ENTRIES (hdr);
if (_bfd_mul_overflow (reloc_count, sizeof (arelent), & amt))
{
+ free (native_relocs);
bfd_set_error (bfd_error_file_too_big);
result = FALSE;
continue;
!= hdr->sh_size))
{
free (native_relocs);
- free (internal_relocs);
+ /* The internal_relocs will be freed when
+ the memory for the bfd is released. */
result = FALSE;
continue;
}
- symcount = bfd_get_symcount (abfd);
+ if (dynamic)
+ symcount = bfd_get_dynamic_symcount (abfd);
+ else
+ symcount = bfd_get_symcount (abfd);
for (i = 0, internal_reloc = internal_relocs,
native_reloc = native_relocs;
bfd_boolean res;
Elf_Internal_Rela rela;
- ebd->s->swap_reloca_in (abfd, native_reloc, & rela);
+ if (entsize == ebd->s->sizeof_rel)
+ ebd->s->swap_reloc_in (abfd, native_reloc, & rela);
+ else /* entsize == ebd->s->sizeof_rela */
+ ebd->s->swap_reloca_in (abfd, native_reloc, & rela);
/* The address of an ELF reloc is section relative for an object
file, and absolute for an executable file or shared library.
asymbol **ps;
ps = symbols + r_sym (rela.r_info) - 1;
-
internal_reloc->sym_ptr_ptr = ps;
/* Make sure that this symbol is not removed by strip. */
(*ps)->flags |= BSF_KEEP;
{
asection * isec;
asection * osec;
+ struct bfd_elf_section_data * esd;
if (isection == NULL)
return FALSE;
if (osec == NULL)
return FALSE;
- BFD_ASSERT (elf_section_data (osec)->sec_info == NULL);
- elf_section_data (osec)->sec_info = elf_section_data (isec)->sec_info;
+ esd = elf_section_data (osec);
+ BFD_ASSERT (esd->sec_info == NULL);
+ esd->sec_info = elf_section_data (isec)->sec_info;
osection->sh_type = SHT_RELA;
osection->sh_link = elf_onesymtab (obfd);
if (osection->sh_link == 0)
}
/* Find the output section that corresponds to the isection's sh_info link. */
- BFD_ASSERT (isection->sh_info > 0
- && isection->sh_info < elf_numsections (ibfd));
+ if (isection->sh_info == 0
+ || isection->sh_info >= elf_numsections (ibfd))
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB(%pA): info section index is invalid"),
+ obfd, osec);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
isection = elf_elfsections (ibfd)[isection->sh_info];
- BFD_ASSERT (isection != NULL);
- BFD_ASSERT (isection->bfd_section != NULL);
- BFD_ASSERT (isection->bfd_section->output_section != NULL);
- osection->sh_info =
- elf_section_data (isection->bfd_section->output_section)->this_idx;
+ if (isection == NULL
+ || isection->bfd_section == NULL
+ || isection->bfd_section->output_section == NULL)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB(%pA): info section index cannot be set because the section is not in the output"),
+ obfd, osec);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ esd = elf_section_data (isection->bfd_section->output_section);
+ BFD_ASSERT (esd != NULL);
+ osection->sh_info = esd->this_idx;
+ esd->has_secondary_relocs = TRUE;
#if DEBUG_SECONDARY_RELOCS
fprintf (stderr, "update header of %s, sh_link = %u, sh_info = %u\n",
osec->name, osection->sh_link, osection->sh_info);
+ fprintf (stderr, "mark section %s as having secondary relocs\n",
+ bfd_section_name (isection->bfd_section->output_section));
#endif
return TRUE;
}
-/* Write out a secondary reloc section. */
+/* Write out a secondary reloc section.
+
+ FIXME: Currently this function can result in a serious performance penalty
+ for files with secondary relocs and lots of sections. The proper way to
+ fix this is for _bfd_elf_copy_special_section_fields() to chain secondary
+ relocs together and then to have this function just walk that chain. */
bfd_boolean
_bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec)
bfd_vma addr_offset;
asection * relsec;
bfd_vma (*r_info) (bfd_vma, bfd_vma);
+ bfd_boolean result = TRUE;
+
+ if (sec == NULL)
+ return FALSE;
#if BFD_DEFAULT_TARGET_SIZE > 32
if (bfd_arch_bits_per_address (abfd) != 32)
#endif
r_info = elf32_r_info;
- if (sec == NULL)
- return FALSE;
-
/* The address of an ELF reloc is section relative for an object
file, and absolute for an executable file or shared library.
The address of a BFD reloc is always section relative. */
int last_sym_idx;
unsigned int reloc_count;
unsigned int idx;
+ unsigned int entsize;
arelent * src_irel;
bfd_byte * dst_rela;
- BFD_ASSERT (hdr->contents == NULL);
+ if (hdr->contents != NULL)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB(%pA): error: secondary reloc section processed twice"),
+ abfd, relsec);
+ bfd_set_error (bfd_error_bad_value);
+ result = FALSE;
+ continue;
+ }
- reloc_count = hdr->sh_size / hdr->sh_entsize;
- BFD_ASSERT (reloc_count > 0);
+ entsize = hdr->sh_entsize;
+ if (entsize == 0)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB(%pA): error: secondary reloc section has zero sized entries"),
+ abfd, relsec);
+ bfd_set_error (bfd_error_bad_value);
+ result = FALSE;
+ continue;
+ }
+ else if (entsize != ebd->s->sizeof_rel
+ && entsize != ebd->s->sizeof_rela)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB(%pA): error: secondary reloc section has non-standard sized entries"),
+ abfd, relsec);
+ bfd_set_error (bfd_error_bad_value);
+ result = FALSE;
+ continue;
+ }
+
+ reloc_count = hdr->sh_size / entsize;
+ if (reloc_count <= 0)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB(%pA): error: secondary reloc section is empty!"),
+ abfd, relsec);
+ bfd_set_error (bfd_error_bad_value);
+ result = FALSE;
+ continue;
+ }
hdr->contents = bfd_alloc (abfd, hdr->sh_size);
if (hdr->contents == NULL)
last_sym_idx = 0;
dst_rela = hdr->contents;
src_irel = (arelent *) esd->sec_info;
- BFD_ASSERT (src_irel != NULL);
+ if (src_irel == NULL)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB(%pA): error: internal relocs missing for secondary reloc section"),
+ abfd, relsec);
+ bfd_set_error (bfd_error_bad_value);
+ result = FALSE;
+ continue;
+ }
- for (idx = 0; idx < reloc_count; idx++, dst_rela += hdr->sh_entsize)
+ for (idx = 0; idx < reloc_count; idx++, dst_rela += entsize)
{
Elf_Internal_Rela src_rela;
arelent *ptr;
int n;
ptr = src_irel + idx;
- sym = *ptr->sym_ptr_ptr;
+ if (ptr == NULL)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB(%pA): error: reloc table entry %u is empty"),
+ abfd, relsec, idx);
+ bfd_set_error (bfd_error_bad_value);
+ result = FALSE;
+ break;
+ }
- if (sym == last_sym)
- n = last_sym_idx;
+ if (ptr->sym_ptr_ptr == NULL)
+ {
+ /* FIXME: Is this an error ? */
+ n = 0;
+ }
else
{
- last_sym = sym;
- n = _bfd_elf_symbol_from_bfd_symbol (abfd, & sym);
- if (n < 0)
+ sym = *ptr->sym_ptr_ptr;
+
+ if (sym == last_sym)
+ n = last_sym_idx;
+ else
{
-#if DEBUG_SECONDARY_RELOCS
- fprintf (stderr, "failed to find symbol %s whilst rewriting relocs\n",
- sym->name);
-#endif
- /* FIXME: Signal failure somehow. */
- n = 0;
+ n = _bfd_elf_symbol_from_bfd_symbol (abfd, & sym);
+ if (n < 0)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB(%pA): error: secondary reloc %u references a missing symbol"),
+ abfd, relsec, idx);
+ bfd_set_error (bfd_error_bad_value);
+ result = FALSE;
+ n = 0;
+ }
+
+ last_sym = sym;
+ last_sym_idx = n;
}
- last_sym_idx = n;
- }
- if ((*ptr->sym_ptr_ptr)->the_bfd != NULL
- && (*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
- && ! _bfd_elf_validate_reloc (abfd, ptr))
- {
-#if DEBUG_SECONDARY_RELOCS
- fprintf (stderr, "symbol %s is not in the output bfd\n",
- sym->name);
-#endif
- /* FIXME: Signal failure somehow. */
- n = 0;
+ if (sym->the_bfd != NULL
+ && sym->the_bfd->xvec != abfd->xvec
+ && ! _bfd_elf_validate_reloc (abfd, ptr))
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB(%pA): error: secondary reloc %u references a deleted symbol"),
+ abfd, relsec, idx);
+ bfd_set_error (bfd_error_bad_value);
+ result = FALSE;
+ n = 0;
+ }
}
+ src_rela.r_offset = ptr->address + addr_offset;
if (ptr->howto == NULL)
{
-#if DEBUG_SECONDARY_RELOCS
- fprintf (stderr, "reloc for symbol %s does not have a howto associated with it\n",
- sym->name);
-#endif
- /* FIXME: Signal failure somehow. */
- n = 0;
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB(%pA): error: secondary reloc %u is of an unknown type"),
+ abfd, relsec, idx);
+ bfd_set_error (bfd_error_bad_value);
+ result = FALSE;
+ src_rela.r_info = r_info (0, 0);
}
-
- src_rela.r_offset = ptr->address + addr_offset;
- src_rela.r_info = r_info (n, ptr->howto->type);
+ else
+ src_rela.r_info = r_info (n, ptr->howto->type);
src_rela.r_addend = ptr->addend;
- ebd->s->swap_reloca_out (abfd, &src_rela, dst_rela);
+
+ if (entsize == ebd->s->sizeof_rel)
+ ebd->s->swap_reloc_out (abfd, &src_rela, dst_rela);
+ else /* entsize == ebd->s->sizeof_rela */
+ ebd->s->swap_reloca_out (abfd, &src_rela, dst_rela);
}
}
}
- return TRUE;
+ return result;
}