/* 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);
- 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
{
/* 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;
return TRUE;
error_return:
- if (dynbuf != NULL)
- free (dynbuf);
+ free (dynbuf);
return FALSE;
}
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);
-
- /* PR 26005: Do not use bfd_zalloc here as the memory might
- be released before the bfd has been fully scanned. */
- sections_being_created = (bfd_boolean *) bfd_malloc (amt);
- if (sections_being_created == NULL)
- return FALSE;
- memset (sections_being_created, FALSE, amt);
- 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);
fail:
ret = FALSE;
success:
- if (sections_being_created && sections_being_created_abfd == abfd)
- sections_being_created [shindex] = FALSE;
- if (-- nesting == 0)
- {
- free (sections_being_created);
- sections_being_created = NULL;
- sections_being_created_abfd = NULL;
- }
+ 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 }
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;
/* 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);
- 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)
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)
{
phdr_size += bed->s->sizeof_ehdr;
/* phdr_size is compared to LMA values which are in bytes. */
phdr_size /= opb;
- maxpagesize = bed->maxpagesize;
+ if (info != NULL)
+ maxpagesize = info->maxpagesize;
+ else
+ maxpagesize = bed->maxpagesize;
if (maxpagesize == 0)
maxpagesize = 1;
phdr_in_segment = info != NULL && info->load_phdrs;
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))
{
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;
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);
/* 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;
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) \
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. */
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. */
|| 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
_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
}
#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;
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;
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)
return FALSE;
}
- osection->sh_info =
- elf_section_data (isection->bfd_section->output_section)->this_idx;
-
+ 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)
int last_sym_idx;
unsigned int reloc_count;
unsigned int idx;
+ unsigned int entsize;
arelent * src_irel;
bfd_byte * dst_rela;
continue;
}
- reloc_count = hdr->sh_size / hdr->sh_entsize;
+ 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
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;
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);
}
}
}