/* ELF executable support for BFD.
- Copyright (C) 1993-2016 Free Software Foundation, Inc.
+ Copyright (C) 1993-2017 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
if (hdr->sh_type != SHT_STRTAB && hdr->sh_type < SHT_LOOS)
{
/* PR 17512: file: f057ec89. */
- _bfd_error_handler (_("%B: attempt to load strings from a non-string section (number %d)"),
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: attempt to load strings from"
+ " a non-string section (number %d)"),
abfd, shindex);
return NULL;
}
if (strindex >= hdr->sh_size)
{
unsigned int shstrndx = elf_elfheader(abfd)->e_shstrndx;
- (*_bfd_error_handler)
- (_("%B: invalid string offset %u >= %lu for section `%s'"),
- abfd, strindex, (unsigned long) hdr->sh_size,
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: invalid string offset %u >= %Lu for section `%s'"),
+ abfd, strindex, hdr->sh_size,
(shindex == shstrndx && strindex == hdr->sh_name
? ".shstrtab"
: bfd_elf_string_from_elf_section (abfd, shstrndx, hdr->sh_name)));
if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym))
{
symoffset += (esym - (bfd_byte *) extsym_buf) / extsym_size;
- (*_bfd_error_handler) (_("%B symbol number %lu references "
- "nonexistent SHT_SYMTAB_SHNDX section"),
- ibfd, (unsigned long) symoffset);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B symbol number %lu references"
+ " nonexistent SHT_SYMTAB_SHNDX section"),
+ ibfd, (unsigned long) symoffset);
if (alloc_intsym != NULL)
free (alloc_intsym);
intsym_buf = NULL;
{
num_group = (unsigned) -1;
elf_tdata (abfd)->num_group = num_group;
+ elf_tdata (abfd)->group_sect_ptr = NULL;
}
else
{
bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *));
if (elf_tdata (abfd)->group_sect_ptr == NULL)
return FALSE;
-
+ memset (elf_tdata (abfd)->group_sect_ptr, 0, num_group * sizeof (Elf_Internal_Shdr *));
num_group = 0;
+
for (i = 0; i < shnum; i++)
{
Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i];
unsigned char *src;
Elf_Internal_Group *dest;
+ /* Make sure the group section has a BFD section
+ attached to it. */
+ if (!bfd_section_from_shdr (abfd, i))
+ return FALSE;
+
/* Add to list of sections. */
elf_tdata (abfd)->group_sect_ptr[num_group] = shdr;
num_group += 1;
if (shdr->contents == NULL)
{
_bfd_error_handler
- (_("%B: corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size);
+ /* xgettext:c-format */
+ (_("%B: corrupt size field in group section"
+ " header: %#Lx"), abfd, shdr->sh_size);
bfd_set_error (bfd_error_bad_value);
-- num_group;
continue;
!= shdr->sh_size))
{
_bfd_error_handler
- (_("%B: invalid size field in group section header: 0x%lx"), abfd, shdr->sh_size);
+ /* xgettext:c-format */
+ (_("%B: invalid size field in group section"
+ " header: %#Lx"), abfd, shdr->sh_size);
bfd_set_error (bfd_error_bad_value);
-- num_group;
- /* PR 17510: If the group contents are even partially
- corrupt, do not allow any of the contents to be used. */
+ /* PR 17510: If the group contents are even
+ partially corrupt, do not allow any of the
+ contents to be used. */
memset (shdr->contents, 0, amt);
continue;
}
}
if (idx >= shnum)
{
- ((*_bfd_error_handler)
- (_("%B: invalid SHT_GROUP entry"), abfd));
+ _bfd_error_handler
+ (_("%B: invalid SHT_GROUP entry"), abfd);
idx = 0;
}
dest->shdr = elf_elfsections (abfd)[idx];
{
elf_tdata (abfd)->group_sect_ptr = NULL;
elf_tdata (abfd)->num_group = num_group = -1;
- (*_bfd_error_handler) (_("%B: no valid group sections found"), abfd);
+ _bfd_error_handler
+ (_("%B: no valid group sections found"), abfd);
bfd_set_error (bfd_error_bad_value);
}
}
for (i = 0; i < num_group; i++)
{
Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i];
- Elf_Internal_Group *idx = (Elf_Internal_Group *) shdr->contents;
- unsigned int n_elt = shdr->sh_size / 4;
+ Elf_Internal_Group *idx;
+ bfd_size_type n_elt;
+
+ if (shdr == NULL)
+ continue;
+
+ idx = (Elf_Internal_Group *) shdr->contents;
+ if (idx == NULL || shdr->sh_size < 4)
+ {
+ /* See PR 21957 for a reproducer. */
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: group section '%A' has no contents"),
+ abfd, shdr->bfd_section);
+ elf_tdata (abfd)->group_sect_ptr[i] = NULL;
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ n_elt = shdr->sh_size / 4;
/* Look through this group's sections to see if current
section is a member. */
if (elf_group_name (newsect) == NULL)
{
- (*_bfd_error_handler) (_("%B: no group info for section %A"),
- abfd, newsect);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: no group info for section '%A'"),
+ abfd, newsect);
return FALSE;
}
return TRUE;
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 */
(_("%B: warning: sh_link not set for section `%A'"),
abfd, s);
}
sh_link. We don't want to proceed. */
if (linksec == NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: sh_link [%d] in section `%A' is incorrect"),
- s->owner, s, elfsec);
+ s->owner, elfsec, s);
result = FALSE;
}
elf_linked_to_section (s) = linksec;
}
}
+ else if (this_hdr->sh_type == SHT_GROUP
+ && elf_next_in_group (s) == NULL)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: SHT_GROUP section [index %d] has no SHF_GROUP sections"),
+ abfd, elf_section_data (s)->this_idx);
+ result = FALSE;
+ }
}
/* Process section groups. */
/* PR binutils/18758: Beware of corrupt binaries with invalid group data. */
if (shdr == NULL || shdr->bfd_section == NULL || shdr->contents == NULL)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: section group entry number %u is corrupt"),
abfd, i);
result = FALSE;
n_elt = shdr->sh_size / 4;
while (--n_elt != 0)
- if ((++idx)->shdr->bfd_section)
- elf_sec_group (idx->shdr->bfd_section) = shdr->bfd_section;
- else if (idx->shdr->sh_type == SHT_RELA
- || idx->shdr->sh_type == SHT_REL)
- /* We won't include relocation sections in section groups in
- output object files. We adjust the group section size here
- so that relocatable link will work correctly when
- relocation sections are in section group in input object
- files. */
- shdr->bfd_section->size -= 4;
- else
- {
- /* There are some unknown sections in the group. */
- (*_bfd_error_handler)
- (_("%B: unknown [%d] section `%s' in group [%s]"),
- abfd,
- (unsigned int) idx->shdr->sh_type,
- bfd_elf_string_from_elf_section (abfd,
- (elf_elfheader (abfd)
- ->e_shstrndx),
- idx->shdr->sh_name),
- shdr->bfd_section->name);
- result = FALSE;
- }
+ {
+ ++ idx;
+
+ if (idx->shdr == NULL)
+ continue;
+ else if (idx->shdr->bfd_section)
+ elf_sec_group (idx->shdr->bfd_section) = shdr->bfd_section;
+ else if (idx->shdr->sh_type != SHT_RELA
+ && idx->shdr->sh_type != SHT_REL)
+ {
+ /* There are some unknown sections in the group. */
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: unknown type [%#x] section `%s' in group [%A]"),
+ abfd,
+ idx->shdr->sh_type,
+ bfd_elf_string_from_elf_section (abfd,
+ (elf_elfheader (abfd)
+ ->e_shstrndx),
+ idx->shdr->sh_name),
+ shdr->bfd_section);
+ result = FALSE;
+ }
+ }
}
+
return result;
}
if (hdr->sh_type != SHT_NOBITS)
flags |= SEC_HAS_CONTENTS;
if (hdr->sh_type == SHT_GROUP)
- flags |= SEC_GROUP | SEC_EXCLUDE;
+ flags |= SEC_GROUP;
if ((hdr->sh_flags & SHF_ALLOC) != 0)
{
flags |= SEC_ALLOC;
if (!bfd_malloc_and_get_section (abfd, newsect, &contents))
return FALSE;
- elf_parse_notes (abfd, (char *) contents, hdr->sh_size, -1);
+ elf_parse_notes (abfd, (char *) contents, hdr->sh_size, hdr->sh_offset);
free (contents);
}
{
if (!bfd_init_section_compress_status (abfd, newsect))
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: unable to initialize compress status for section %s"),
abfd, name);
return FALSE;
{
if (!bfd_init_section_decompress_status (abfd, newsect))
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: unable to initialize decompress status for section %s"),
abfd, name);
return FALSE;
to be the correct section. */
static unsigned int
-find_link (const bfd * obfd, const Elf_Internal_Shdr * iheader, const unsigned int hint)
+find_link (const bfd *obfd, const Elf_Internal_Shdr *iheader,
+ const unsigned int hint)
{
Elf_Internal_Shdr ** oheaders = elf_elfsections (obfd);
unsigned int i;
- if (section_match (oheaders[hint], iheader))
+ BFD_ASSERT (iheader != NULL);
+
+ /* See PR 20922 for a reproducer of the NULL test. */
+ if (hint < elf_numsections (obfd)
+ && oheaders[hint] != NULL
+ && section_match (oheaders[hint], iheader))
return hint;
for (i = 1; i < elf_numsections (obfd); i++)
{
Elf_Internal_Shdr * oheader = oheaders[i];
+ if (oheader == NULL)
+ continue;
if (section_match (oheader, iheader))
/* FIXME: Do we care if there is a potential for
multiple matches ? */
in the input bfd. */
if (iheader->sh_link != SHN_UNDEF)
{
+ /* See PR 20931 for a reproducer. */
+ if (iheader->sh_link >= elf_numsections (ibfd))
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: Invalid sh_link field (%d) in section number %d"),
+ ibfd, iheader->sh_link, secnum);
+ return FALSE;
+ }
+
sh_link = find_link (obfd, iheaders[iheader->sh_link], iheader->sh_link);
if (sh_link != SHN_UNDEF)
{
else
/* FIXME: Should we install iheader->sh_link
if we could not find a match ? */
- (* _bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: Failed to find link section for section %d"), obfd, secnum);
}
changed = TRUE;
}
else
- (* _bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: Failed to find info section for section %d"), obfd, secnum);
}
if (!strcmp (name, ""))
{
- sprintf (ab, "0x%lx", (unsigned long) dyn.d_tag);
+ sprintf (ab, "%#" BFD_VMA_FMT "x", dyn.d_tag);
name = ab;
}
break;
case bfd_print_symbol_more:
fprintf (file, "elf ");
bfd_fprintf_vma (abfd, file, symbol->value);
- fprintf (file, " %lx", (unsigned long) symbol->flags);
+ fprintf (file, " %x", symbol->flags);
break;
case bfd_print_symbol_all:
{
}
if (sections_being_created [shindex])
{
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%B: warning: loop in section dependencies detected"), abfd);
return FALSE;
}
Unusual, but possible. Warn, but continue. */
if (elf_onesymtab (abfd) != 0)
{
- (*_bfd_error_handler)
- (_("%B: warning: multiple symbol tables detected - ignoring the table in section %u"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: warning: multiple symbol tables detected"
+ " - ignoring the table in section %u"),
abfd, shindex);
goto success;
}
Unusual, but possible. Warn, but continue. */
if (elf_dynsymtab (abfd) != 0)
{
- (*_bfd_error_handler)
- (_("%B: warning: multiple dynamic symbol tables detected - ignoring the table in section %u"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: warning: multiple dynamic symbol tables detected"
+ " - ignoring the table in section %u"),
abfd, shindex);
goto success;
}
/* Check for a bogus link to avoid crashing. */
if (hdr->sh_link >= num_sec)
{
- ((*_bfd_error_handler)
- (_("%B: invalid link %lu for reloc section %s (index %u)"),
- abfd, hdr->sh_link, name, shindex));
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: invalid link %u for reloc section %s (index %u)"),
+ abfd, hdr->sh_link, name, shindex);
ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
shindex);
goto success;
*hdr2 = *hdr;
*p_hdr = hdr2;
elf_elfsections (abfd)[shindex] = hdr2;
- target_sect->reloc_count += NUM_SHDR_ENTRIES (hdr);
+ target_sect->reloc_count += (NUM_SHDR_ENTRIES (hdr)
+ * bed->s->int_rels_per_ext_rel);
target_sect->flags |= SEC_RELOC;
target_sect->relocation = NULL;
target_sect->rel_filepos = hdr->sh_offset;
if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
goto fail;
- if (hdr->contents != NULL)
- {
- Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
- unsigned int n_elt = hdr->sh_size / sizeof (* idx);
- asection *s;
-
- if (n_elt == 0)
- goto fail;
- if (idx->flags & GRP_COMDAT)
- hdr->bfd_section->flags
- |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
-
- /* We try to keep the same section order as it comes in. */
- idx += n_elt;
-
- while (--n_elt != 0)
- {
- --idx;
-
- if (idx->shdr != NULL
- && (s = idx->shdr->bfd_section) != NULL
- && elf_next_in_group (s) != NULL)
- {
- elf_next_in_group (hdr->bfd_section) = s;
- break;
- }
- }
- }
goto success;
default:
if ((hdr->sh_flags & SHF_ALLOC) != 0)
/* FIXME: How to properly handle allocated section reserved
for applications? */
- (*_bfd_error_handler)
- (_("%B: don't know how to handle allocated, application "
- "specific section `%s' [0x%8x]"),
- abfd, name, hdr->sh_type);
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: unknown type [%#x] section `%s'"),
+ abfd, hdr->sh_type, name);
else
{
/* Allow sections reserved for applications. */
else if (hdr->sh_type >= SHT_LOPROC
&& hdr->sh_type <= SHT_HIPROC)
/* FIXME: We should handle this section. */
- (*_bfd_error_handler)
- (_("%B: don't know how to handle processor specific section "
- "`%s' [0x%8x]"),
- abfd, name, hdr->sh_type);
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: unknown type [%#x] section `%s'"),
+ abfd, hdr->sh_type, name);
else if (hdr->sh_type >= SHT_LOOS && hdr->sh_type <= SHT_HIOS)
{
/* Unrecognised OS-specific sections. */
/* SHF_OS_NONCONFORMING indicates that special knowledge is
required to correctly process the section and the file should
be rejected with an error message. */
- (*_bfd_error_handler)
- (_("%B: don't know how to handle OS specific section "
- "`%s' [0x%8x]"),
- abfd, name, hdr->sh_type);
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: unknown type [%#x] section `%s'"),
+ abfd, hdr->sh_type, name);
else
{
/* Otherwise it should be processed. */
}
else
/* FIXME: We should handle this section. */
- (*_bfd_error_handler)
- (_("%B: don't know how to handle section `%s' [0x%8x]"),
- abfd, name, hdr->sh_type);
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: unknown type [%#x] section `%s'"),
+ abfd, hdr->sh_type, name);
goto fail;
}
static const struct bfd_elf_special_section special_sections_f[] =
{
- { STRING_COMMA_LEN (".fini"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
- { STRING_COMMA_LEN (".fini_array"), 0, SHT_FINI_ARRAY, SHF_ALLOC + SHF_WRITE },
- { NULL, 0, 0, 0, 0 }
+ { STRING_COMMA_LEN (".fini"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { STRING_COMMA_LEN (".fini_array"), -2, SHT_FINI_ARRAY, SHF_ALLOC + SHF_WRITE },
+ { NULL, 0 , 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_g[] =
static const struct bfd_elf_special_section special_sections_i[] =
{
- { STRING_COMMA_LEN (".init"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
- { STRING_COMMA_LEN (".init_array"), 0, SHT_INIT_ARRAY, SHF_ALLOC + SHF_WRITE },
- { STRING_COMMA_LEN (".interp"), 0, SHT_PROGBITS, 0 },
- { NULL, 0, 0, 0, 0 }
+ { STRING_COMMA_LEN (".init"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { STRING_COMMA_LEN (".init_array"), -2, SHT_INIT_ARRAY, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".interp"), 0, SHT_PROGBITS, 0 },
+ { NULL, 0, 0, 0, 0 }
};
static const struct bfd_elf_special_section special_sections_l[] =
static const struct bfd_elf_special_section special_sections_p[] =
{
- { STRING_COMMA_LEN (".preinit_array"), 0, SHT_PREINIT_ARRAY, SHF_ALLOC + SHF_WRITE },
- { STRING_COMMA_LEN (".plt"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
- { NULL, 0, 0, 0, 0 }
+ { 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 }
};
static const struct bfd_elf_special_section special_sections_r[] =
static bfd_boolean
_bfd_elf_init_reloc_shdr (bfd *abfd,
struct bfd_elf_section_reloc_data *reldata,
+ const Elf_Internal_Shdr *sec_hdr,
const char *sec_name,
bfd_boolean use_rela_p,
bfd_boolean delay_st_name_p)
? bed->s->sizeof_rela
: bed->s->sizeof_rel);
rel_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
- rel_hdr->sh_flags = 0;
+ rel_hdr->sh_flags = sec_hdr->sh_flags & SHF_GROUP;
rel_hdr->sh_addr = 0;
rel_hdr->sh_size = 0;
rel_hdr->sh_offset = 0;
compressed. */
asect->flags |= SEC_ELF_COMPRESS;
- /* If this section will be compressed, delay adding setion
+ /* 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. */
delay_st_name_p = TRUE;
/* PR 17512: file: 0eb809fe, 8b0535ee. */
if (asect->alignment_power >= (sizeof (bfd_vma) * 8) - 1)
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: error: Alignment power %d of section `%A' is too big"),
- abfd, asect, asect->alignment_power);
+ abfd, asect->alignment_power, asect);
arg->failed = TRUE;
return;
}
allow the link to proceed. This can happen when users link
non-bss input sections to bss output sections, or emit data
to a bss output section via a linker script. */
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("warning: section `%A' type changed to PROGBITS"), asect);
this_hdr->sh_type = sh_type;
}
|| arg->link_info->emitrelocations))
{
if (esd->rel.count && esd->rel.hdr == NULL
- && !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, name, FALSE,
- delay_st_name_p))
+ && !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, this_hdr, name,
+ FALSE, delay_st_name_p))
{
arg->failed = TRUE;
return;
}
if (esd->rela.count && esd->rela.hdr == NULL
- && !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, name, TRUE,
- delay_st_name_p))
+ && !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, this_hdr, name,
+ TRUE, delay_st_name_p))
{
arg->failed = TRUE;
return;
else if (!_bfd_elf_init_reloc_shdr (abfd,
(asect->use_rela_p
? &esd->rela : &esd->rel),
+ this_hdr,
name,
asect->use_rela_p,
delay_st_name_p))
+ {
arg->failed = TRUE;
+ return;
+ }
}
/* Check for processor-specific section types. */
sh_type = this_hdr->sh_type;
if (bed->elf_backend_fake_sections
&& !(*bed->elf_backend_fake_sections) (abfd, this_hdr, asect))
- arg->failed = TRUE;
+ {
+ arg->failed = TRUE;
+ return;
+ }
if (sh_type == SHT_NOBITS && asect->size != 0)
{
/* The ELF backend linker sets sh_info to -2 when the group
signature symbol is global, and thus the index can't be
set until all local symbols are output. */
- asection *igroup = elf_sec_group (elf_next_in_group (sec));
- struct bfd_elf_section_data *sec_data = elf_section_data (igroup);
- unsigned long symndx = sec_data->this_hdr.sh_info;
- unsigned long extsymoff = 0;
+ asection *igroup;
+ struct bfd_elf_section_data *sec_data;
+ unsigned long symndx;
+ unsigned long extsymoff;
struct elf_link_hash_entry *h;
+ /* The point of this little dance to the first SHF_GROUP section
+ then back to the SHT_GROUP section is that this gets us to
+ the SHT_GROUP in the input object. */
+ igroup = elf_sec_group (elf_next_in_group (sec));
+ sec_data = elf_section_data (igroup);
+ symndx = sec_data->this_hdr.sh_info;
+ extsymoff = 0;
if (!elf_bad_symtab (igroup->owner))
{
Elf_Internal_Shdr *symtab_hdr;
if (s != NULL
&& !bfd_is_abs_section (s))
{
- unsigned int idx = elf_section_data (s)->this_idx;
-
+ struct bfd_elf_section_data *elf_sec = elf_section_data (s);
+ if (elf_sec->rel.hdr != NULL)
+ {
+ loc -= 4;
+ H_PUT_32 (abfd, elf_sec->rel.idx, loc);
+ }
+ if (elf_sec->rela.hdr != NULL)
+ {
+ loc -= 4;
+ H_PUT_32 (abfd, elf_sec->rela.idx, loc);
+ }
loc -= 4;
- H_PUT_32 (abfd, idx, loc);
+ H_PUT_32 (abfd, elf_sec->this_idx, loc);
}
elt = elf_next_in_group (elt);
if (elt == first)
break;
}
- if ((loc -= 4) != sec->contents)
- abort ();
+ loc -= 4;
+ BFD_ASSERT (loc == sec->contents);
H_PUT_32 (abfd, sec->flags & SEC_LINK_ONCE ? GRP_COMDAT : 0, loc);
}
-/* Return the section which RELOC_SEC applies to. */
+/* Given NAME, the name of a relocation section stripped of its
+ .rel/.rela prefix, return the section in ABFD to which the
+ relocations apply. */
asection *
-_bfd_elf_get_reloc_section (asection *reloc_sec)
+_bfd_elf_plt_get_reloc_section (bfd *abfd, const char *name)
+{
+ /* If a target needs .got.plt section, relocations in rela.plt/rel.plt
+ section likely apply to .got.plt or .got section. */
+ if (get_elf_backend_data (abfd)->want_got_plt
+ && strcmp (name, ".plt") == 0)
+ {
+ asection *sec;
+
+ name = ".got.plt";
+ sec = bfd_get_section_by_name (abfd, name);
+ if (sec != NULL)
+ return sec;
+ name = ".got";
+ }
+
+ return bfd_get_section_by_name (abfd, name);
+}
+
+/* Return the section to which RELOC_SEC applies. */
+
+static asection *
+elf_get_reloc_section (asection *reloc_sec)
{
const char *name;
unsigned int type;
bfd *abfd;
-
- if (reloc_sec == NULL)
- return NULL;
+ const struct elf_backend_data *bed;
type = elf_section_data (reloc_sec)->this_hdr.sh_type;
if (type != SHT_REL && type != SHT_RELA)
/* We look up the section the relocs apply to by name. */
name = reloc_sec->name;
- if (type == SHT_REL)
- name += 4;
- else
- name += 5;
+ if (strncmp (name, ".rel", 4) != 0)
+ return NULL;
+ name += 4;
+ if (type == SHT_RELA && *name++ != 'a')
+ return NULL;
- /* If a target needs .got.plt section, relocations in rela.plt/rel.plt
- section apply to .got.plt section. */
abfd = reloc_sec->owner;
- if (get_elf_backend_data (abfd)->want_got_plt
- && strcmp (name, ".plt") == 0)
- {
- /* .got.plt is a linker created input section. It may be mapped
- to some other output section. Try two likely sections. */
- name = ".got.plt";
- reloc_sec = bfd_get_section_by_name (abfd, name);
- if (reloc_sec != NULL)
- return reloc_sec;
- name = ".got";
- }
-
- reloc_sec = bfd_get_section_by_name (abfd, name);
- return reloc_sec;
+ bed = get_elf_backend_data (abfd);
+ return bed->get_reloc_section (abfd, name);
}
/* Assign all ELF section numbers. The dummy first section is handled here
_bfd_elf_strtab_clear_all_refs (elf_shstrtab (abfd));
/* SHT_GROUP sections are in relocatable files only. */
- if (link_info == NULL || bfd_link_relocatable (link_info))
+ if (link_info == NULL || !link_info->resolve_section_groups)
{
size_t reloc_count = 0;
d->rela.idx = 0;
}
- elf_shstrtab_sec (abfd) = section_number++;
- _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->shstrtab_hdr.sh_name);
- elf_elfheader (abfd)->e_shstrndx = elf_shstrtab_sec (abfd);
-
need_symtab = (bfd_get_symcount (abfd) > 0
|| (link_info == NULL
&& ((abfd->flags & (EXEC_P | DYNAMIC | HAS_RELOC))
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name);
}
+ elf_shstrtab_sec (abfd) = section_number++;
+ _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->shstrtab_hdr.sh_name);
+ elf_elfheader (abfd)->e_shstrndx = elf_shstrtab_sec (abfd);
+
if (section_number >= SHN_LORESERVE)
{
+ /* xgettext:c-format */
_bfd_error_handler (_("%B: too many sections: %u"),
abfd, section_number);
return FALSE;
if (discarded_section (s))
{
asection *kept;
- (*_bfd_error_handler)
- (_("%B: sh_link of section `%A' points to discarded section `%A' of `%B'"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: sh_link of section `%A' points to"
+ " discarded section `%A' of `%B'"),
abfd, d->this_hdr.bfd_section,
s, s->owner);
/* Point to the kept section if it has the same
/* Handle objcopy. */
if (s->output_section == NULL)
{
- (*_bfd_error_handler)
- (_("%B: sh_link of section `%A' points to removed section `%A' of `%B'"),
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: sh_link of section `%A' points to"
+ " removed section `%A' of `%B'"),
abfd, d->this_hdr.bfd_section, s, s->owner);
bfd_set_error (bfd_error_bad_value);
return FALSE;
= get_elf_backend_data (abfd);
if (bed->link_order_error_handler)
bed->link_order_error_handler
+ /* xgettext:c-format */
(_("%B: warning: sh_link not set for section `%A'"),
abfd, sec);
}
if (s != NULL)
d->this_hdr.sh_link = elf_section_data (s)->this_idx;
- s = get_elf_backend_data (abfd)->get_reloc_section (sec);
+ s = elf_get_reloc_section (sec);
if (s != NULL)
{
d->this_hdr.sh_info = elf_section_data (s)->this_idx;
}
}
- /* Let the backend count up any program headers it might need. */
bed = get_elf_backend_data (abfd);
- if (bed->elf_backend_additional_program_headers)
+
+ if ((abfd->flags & D_PAGED) != 0)
+ {
+ /* Add a PT_GNU_MBIND segment for each mbind section. */
+ unsigned int page_align_power = bfd_log2 (bed->commonpagesize);
+ for (s = abfd->sections; s != NULL; s = s->next)
+ if (elf_section_flags (s) & SHF_GNU_MBIND)
+ {
+ if (elf_section_data (s)->this_hdr.sh_info
+ > PT_GNU_MBIND_NUM)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: GNU_MBIN section `%A' has invalid sh_info field: %d"),
+ abfd, s, elf_section_data (s)->this_hdr.sh_info);
+ continue;
+ }
+ /* Align mbind section to page size. */
+ if (s->alignment_power < page_align_power)
+ s->alignment_power = page_align_power;
+ segs ++;
+ }
+ }
+
+ /* Let the backend count up any program headers it might need. */
+ if (bed->elf_backend_additional_program_headers)
{
int a;
}
(*m)->count = new_count;
- if (remove_empty_load && (*m)->p_type == PT_LOAD && (*m)->count == 0)
+ if (remove_empty_load
+ && (*m)->p_type == PT_LOAD
+ && (*m)->count == 0
+ && !(*m)->includes_phdrs)
*m = (*m)->next;
else
m = &(*m)->next;
bfd_boolean writable;
int tls_count = 0;
asection *first_tls = NULL;
+ asection *first_mbind = NULL;
asection *dynsec, *eh_frame_hdr;
bfd_size_type amt;
bfd_vma addr_mask, wrap_to = 0;
+ bfd_boolean linker_created_pt_phdr_segment = FALSE;
/* Select the allocated sections, and sort them. */
m->p_flags = PF_R | PF_X;
m->p_flags_valid = 1;
m->includes_phdrs = 1;
-
+ linker_created_pt_phdr_segment = TRUE;
*pm = m;
pm = &m->next;
|| ((sections[0]->lma & addr_mask) % maxpagesize
< phdr_size % maxpagesize)
|| (sections[0]->lma & addr_mask & -maxpagesize) < wrap_to)
- phdr_in_segment = FALSE;
+ {
+ /* PR 20815: The ELF standard says that a PT_PHDR segment, if
+ present, must be included as part of the memory image of the
+ program. Ie it must be part of a PT_LOAD segment as well.
+ If we have had to create our own PT_PHDR segment, but it is
+ not going to be covered by the first PT_LOAD segment, then
+ force the inclusion if we can... */
+ if ((abfd->flags & D_PAGED) != 0
+ && linker_created_pt_phdr_segment)
+ phdr_in_segment = TRUE;
+ else
+ phdr_in_segment = FALSE;
+ }
}
for (i = 0, hdrpp = sections; i < count; i++, hdrpp++)
first_tls = s;
tls_count++;
}
+ if (first_mbind == NULL
+ && (elf_section_flags (s) & SHF_GNU_MBIND) != 0)
+ first_mbind = s;
}
/* If there are any SHF_TLS output sections, add PT_TLS segment. */
pm = &m->next;
}
+ if (first_mbind && (abfd->flags & D_PAGED) != 0)
+ for (s = first_mbind; s != NULL; s = s->next)
+ if ((elf_section_flags (s) & SHF_GNU_MBIND) != 0
+ && (elf_section_data (s)->this_hdr.sh_info
+ <= PT_GNU_MBIND_NUM))
+ {
+ /* Mandated PF_R. */
+ unsigned long p_flags = PF_R;
+ if ((s->flags & SEC_READONLY) == 0)
+ p_flags |= PF_W;
+ if ((s->flags & SEC_CODE) != 0)
+ p_flags |= PF_X;
+
+ amt = sizeof (struct elf_segment_map) + sizeof (asection *);
+ m = bfd_zalloc (abfd, amt);
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = (PT_GNU_MBIND_LO
+ + elf_section_data (s)->this_hdr.sh_info);
+ m->count = 1;
+ m->p_flags_valid = 1;
+ m->sections[0] = s;
+ m->p_flags = p_flags;
+
+ *pm = m;
+ pm = &m->next;
+ }
+
/* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
segment. */
eh_frame_hdr = elf_eh_frame_hdr (abfd);
else
adjustment = vma_offset - off_offset;
- which can can be collapsed into the expression below. */
+ which can be collapsed into the expression below. */
static file_ptr
vma_page_aligned_bias (bfd_vma vma, ufile_ptr off, bfd_vma maxpagesize)
Elf_Internal_Phdr *p;
file_ptr off;
bfd_size_type maxpagesize;
+ unsigned int pt_load_count = 0;
unsigned int alloc;
unsigned int i, j;
bfd_vma header_pad = 0;
maxpagesize = m->p_align;
p->p_align = maxpagesize;
+ pt_load_count += 1;
}
else if (m->p_align_valid)
p->p_align = m->p_align;
}
off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align);
+
+ /* Broken hardware and/or kernel require that files do not
+ map the same page with different permissions on some hppa
+ processors. */
+ if (pt_load_count > 1
+ && bed->no_page_alias
+ && (off & (maxpagesize - 1)) != 0
+ && (off & -maxpagesize) == ((off + off_adjust) & -maxpagesize))
+ off_adjust += maxpagesize;
off += off_adjust;
if (no_contents)
{
&& strcmp (m->sections[0]->name, ".dynamic") != 0)
{
_bfd_error_handler
- (_("%B: The first section in the PT_DYNAMIC segment is not the .dynamic section"),
+ (_("%B: The first section in the PT_DYNAMIC segment"
+ " is not the .dynamic section"),
abfd);
bfd_set_error (bfd_error_bad_value);
return FALSE;
|| (!m->p_paddr_valid
&& p->p_paddr < (bfd_vma) off))
{
- (*_bfd_error_handler)
- (_("%B: Not enough room for program headers, try linking with -N"),
+ _bfd_error_handler
+ (_("%B: Not enough room for program headers,"
+ " try linking with -N"),
abfd);
bfd_set_error (bfd_error_bad_value);
return FALSE;
&& (s_start < p_end
|| p_end < p_start))
{
- (*_bfd_error_handler)
- (_("%B: section %A lma %#lx adjusted to %#lx"), abfd, sec,
- (unsigned long) s_start, (unsigned long) p_end);
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: section %A lma %#Lx adjusted to %#Lx"),
+ abfd, sec, s_start, p_end);
adjust = 0;
sec->lma = p_end;
}
if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0)
&& !ELF_TBSS_SPECIAL (this_hdr, p))
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: section `%A' can't be allocated in segment %d"),
abfd, sec, j);
print_segment_map (m);
else if ((hdr->sh_flags & SHF_ALLOC) != 0)
{
if (hdr->sh_size != 0)
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: warning: allocated section `%s' not in segment"),
abfd,
(hdr->bfd_section == NULL
else if (m->count != 0)
{
unsigned int i;
+
if (p->p_type != PT_LOAD
&& (p->p_type != PT_NOTE
|| bfd_get_format (abfd) != bfd_core))
{
+ /* A user specified segment layout may include a PHDR
+ segment that overlaps with a LOAD segment... */
+ if (p->p_type == PT_PHDR)
+ {
+ m->count = 0;
+ continue;
+ }
+
if (m->includes_filehdr || m->includes_phdrs)
{
/* PR 17512: file: 2195325e. */
- (*_bfd_error_handler)
- (_("%B: warning: non-load segment includes file header and/or program header"),
- abfd);
+ _bfd_error_handler
+ (_("%B: error: non-load segment %d includes file header "
+ "and/or program header"),
+ abfd, (int) (p - phdrs));
return FALSE;
}
/* Write out the program headers. */
alloc = elf_program_header_size (abfd) / bed->s->sizeof_phdr;
+
+ /* Sort the program headers into the ordering required by the ELF standard. */
+ if (alloc == 0)
+ return TRUE;
+
+ /* PR ld/20815 - Check that the program header segment, if present, will
+ be loaded into memory. FIXME: The check below is not sufficient as
+ really all PT_LOAD segments should be checked before issuing an error
+ message. Plus the PHDR segment does not have to be the first segment
+ in the program header table. But this version of the check should
+ catch all real world use cases.
+
+ FIXME: We used to have code here to sort the PT_LOAD segments into
+ ascending order, as per the ELF spec. But this breaks some programs,
+ including the Linux kernel. But really either the spec should be
+ changed or the programs updated. */
+ if (alloc > 1
+ && tdata->phdr[0].p_type == PT_PHDR
+ && ! bed->elf_backend_allow_non_load_phdr (abfd, tdata->phdr, alloc)
+ && tdata->phdr[1].p_type == PT_LOAD
+ && (tdata->phdr[1].p_vaddr > tdata->phdr[0].p_vaddr
+ || (tdata->phdr[1].p_vaddr + tdata->phdr[1].p_memsz)
+ < (tdata->phdr[0].p_vaddr + tdata->phdr[0].p_memsz)))
+ {
+ /* The fix for this error is usually to edit the linker script being
+ used and set up the program headers manually. Either that or
+ leave room for the headers at the start of the SECTIONS. */
+ _bfd_error_handler (_("\
+%B: error: PHDR segment not covered by LOAD segment"),
+ abfd);
+ return FALSE;
+ }
+
if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
|| bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0)
return FALSE;
return FALSE;
name = new_name;
}
- /* Add setion name to section name section. */
+ /* Add section name to section name section. */
if (shdrp->sh_name != (unsigned int) -1)
abort ();
shdrp->sh_name
name, FALSE);
d = elf_section_data (sec);
- /* Add reloc setion name to section name section. */
+ /* Add reloc section name to section name section. */
if (d->rel.hdr
&& !_bfd_elf_set_reloc_sh_name (abfd,
d->rel.hdr,
{
/* This case can occur when using --strip-symbol on a symbol
which is used in a relocation entry. */
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: symbol `%s' required but not present"),
abfd, bfd_asymbol_name (asym_ptr));
bfd_set_error (bfd_error_no_symbols);
#if DEBUG & 4
{
fprintf (stderr,
- "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx\n",
- (long) asym_ptr, asym_ptr->name, idx, (long) flags);
+ "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8x\n",
+ (long) asym_ptr, asym_ptr->name, idx, flags);
fflush (stderr);
}
#endif
/* Special segments, such as the PT_PHDR segment, may contain
no sections, but ordinary, loadable segments should contain
something. They are allowed by the ELF spec however, so only
- a warning is produced. */
- if (segment->p_type == PT_LOAD)
- (*_bfd_error_handler) (_("\
-%B: warning: Empty loadable segment detected, is this intentional ?"),
- ibfd);
+ a warning is produced.
+ There is however the valid use case of embedded systems which
+ have segments with p_filesz of 0 and a p_memsz > 0 to initialize
+ flash memory with zeros. No warning is shown for that case. */
+ if (segment->p_type == PT_LOAD
+ && (segment->p_filesz > 0 || segment->p_memsz == 0))
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: warning: Empty loadable segment detected"
+ " at vaddr=%#Lx, is this intentional?"),
+ ibfd, segment->p_vaddr);
map->count = 0;
*pointer_to_map = map;
for (section = obfd->sections; section != NULL;
section = section->next)
{
- if (section->segment_mark == FALSE)
+ if (!section->segment_mark)
goto rewrite;
else
section->segment_mark = FALSE;
{
/* PR 17512: file: f17299af. */
if (segment->p_align > (bfd_vma) 1 << ((sizeof (bfd_vma) * 8) - 2))
- (*_bfd_error_handler) (_("\
-%B: warning: segment alignment of 0x%llx is too large"),
- ibfd, (long long) segment->p_align);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: warning: segment alignment of %#Lx"
+ " is too large"),
+ ibfd, segment->p_align);
else
maxpagesize = segment->p_align;
}
elf_section_flags (osec) |= (elf_section_flags (isec)
& (SHF_MASKOS | SHF_MASKPROC));
+ /* Copy sh_info from input for mbind section. */
+ if (elf_section_flags (isec) & SHF_GNU_MBIND)
+ elf_section_data (osec)->this_hdr.sh_info
+ = elf_section_data (isec)->this_hdr.sh_info;
+
/* Set things up for objcopy and relocatable link. The output
SHT_GROUP section will have its elf_next_in_group pointing back
to the input group members. Ignore linker created group section.
See elfNN_ia64_object_p in elfxx-ia64.c. */
- if (!final_link)
+ if ((link_info == NULL
+ || !link_info->resolve_section_groups)
+ && (elf_sec_group (isec) == NULL
+ || (elf_sec_group (isec)->flags & SEC_LINKER_CREATED) == 0))
{
- if (elf_sec_group (isec) == NULL
- || (elf_sec_group (isec)->flags & SEC_LINKER_CREATED) == 0)
- {
- if (elf_section_flags (isec) & SHF_GROUP)
- elf_section_flags (osec) |= SHF_GROUP;
- elf_next_in_group (osec) = elf_next_in_group (isec);
- elf_section_data (osec)->group = elf_section_data (isec)->group;
- }
-
- /* If not decompress, preserve SHF_COMPRESSED. */
- if ((ibfd->flags & BFD_DECOMPRESS) == 0)
- elf_section_flags (osec) |= (elf_section_flags (isec)
- & SHF_COMPRESSED);
+ if (elf_section_flags (isec) & SHF_GROUP)
+ elf_section_flags (osec) |= SHF_GROUP;
+ elf_next_in_group (osec) = elf_next_in_group (isec);
+ elf_section_data (osec)->group = elf_section_data (isec)->group;
}
+ /* If not decompress, preserve SHF_COMPRESSED. */
+ if (!final_link && (ibfd->flags & BFD_DECOMPRESS) == 0)
+ elf_section_flags (osec) |= (elf_section_flags (isec)
+ & SHF_COMPRESSED);
+
ihdr = &elf_section_data (isec)->this_hdr;
/* We need to handle elf_linked_to_section for SHF_LINK_ORDER. We
shndx = _bfd_elf_section_from_bfd_section (abfd, sec2);
if (shndx == SHN_BAD)
{
+ /* xgettext:c-format */
_bfd_error_handler (_("\
Unable to find equivalent output section for symbol '%s' from section '%s'"),
syms[idx]->name ? syms[idx]->name : "<Local sym>",
hdr = &elf_tdata (abfd)->dynverref_hdr;
- if (hdr->sh_info == 0 || hdr->sh_size < sizeof (Elf_External_Verneed))
+ if (hdr->sh_info == 0
+ || hdr->sh_info > hdr->sh_size / sizeof (Elf_External_Verneed))
{
error_return_bad_verref:
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%B: .gnu.version_r invalid entry"), abfd);
bfd_set_error (bfd_error_bad_value);
error_return_verref:
goto error_return_verref;
elf_tdata (abfd)->verref = (Elf_Internal_Verneed *)
- bfd_zalloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed));
+ bfd_alloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed));
if (elf_tdata (abfd)->verref == NULL)
goto error_return_verref;
if (hdr->sh_info == 0 || hdr->sh_size < sizeof (Elf_External_Verdef))
{
error_return_bad_verdef:
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%B: .gnu.version_d invalid entry"), abfd);
bfd_set_error (bfd_error_bad_value);
error_return_verdef:
return TRUE;
fail:
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B: unsupported relocation type %s"),
abfd, areloc->howto->name);
bfd_set_error (bfd_error_bad_value);
such a section already exists.
- For the multi-threaded case, a section named "NAME/PID", where
PID is elfcore_make_pid (abfd).
- Both pseudosections have identical contents. */
+ Both pseudosections have identical contents. */
bfd_boolean
_bfd_elfcore_make_pseudosection (bfd *abfd,
char *name,
return elfcore_make_note_pseudosection (abfd, ".reg-s390-vxrs-high", note);
}
+static bfd_boolean
+elfcore_grok_s390_gs_cb (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-s390-gs-cb", note);
+}
+
+static bfd_boolean
+elfcore_grok_s390_gs_bc (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-s390-gs-bc", note);
+}
+
static bfd_boolean
elfcore_grok_arm_vfp (bfd *abfd, Elf_Internal_Note *note)
{
else
return TRUE;
+ case NT_S390_GS_CB:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_s390_gs_cb (abfd, note);
+ else
+ return TRUE;
+
+ case NT_S390_GS_BC:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_s390_gs_bc (abfd, note);
+ else
+ return TRUE;
+
case NT_ARM_VFP:
if (note->namesz == 6
&& strcmp (note->namedata, "LINUX") == 0)
default:
return TRUE;
+ case NT_GNU_PROPERTY_TYPE_0:
+ return _bfd_elf_parse_gnu_properties (abfd, note);
+
case NT_GNU_BUILD_ID:
return elfobj_grok_gnu_build_id (abfd, note);
}
{
size_t offset;
- switch (abfd->arch_info->bits_per_word)
+ switch (elf_elfheader (abfd)->e_ident[EI_CLASS])
{
- case 32:
+ case ELFCLASS32:
if (note->descsz < 108)
return FALSE;
break;
- case 64:
+ case ELFCLASS64:
if (note->descsz < 120)
return FALSE;
break;
offset = 4;
/* Skip over pr_psinfosz. */
- if (abfd->arch_info->bits_per_word == 32)
+ if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS32)
offset += 4;
else
{
{
size_t offset;
size_t size;
+ size_t min_size;
- /* Check for version 1 in pr_version. */
- if (bfd_h_get_32 (abfd, (bfd_byte *) note->descdata) != 1)
- return FALSE;
- offset = 4;
-
- /* Skip over pr_statussz. */
- switch (abfd->arch_info->bits_per_word)
+ /* Compute offset of pr_getregsz, skipping over pr_statussz.
+ Also compute minimum size of this note. */
+ switch (elf_elfheader (abfd)->e_ident[EI_CLASS])
{
- case 32:
- offset += 4;
+ case ELFCLASS32:
+ offset = 4 + 4;
+ min_size = offset + (4 * 2) + 4 + 4 + 4;
break;
- case 64:
- offset += 4; /* Padding before pr_statussz. */
- offset += 8;
+ case ELFCLASS64:
+ offset = 4 + 4 + 8; /* Includes padding before pr_statussz. */
+ min_size = offset + (8 * 2) + 4 + 4 + 4 + 4;
break;
default:
return FALSE;
}
+ if (note->descsz < min_size)
+ return FALSE;
+
+ /* Check for version 1 in pr_version. */
+ if (bfd_h_get_32 (abfd, (bfd_byte *) note->descdata) != 1)
+ return FALSE;
+
/* Extract size of pr_reg from pr_gregsetsz. */
- if (abfd->arch_info->bits_per_word == 32)
- size = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
+ /* Skip over pr_gregsetsz and pr_fpregsetsz. */
+ if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS32)
+ {
+ size = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
+ offset += 4 * 2;
+ }
else
- size = bfd_h_get_64 (abfd, (bfd_byte *) note->descdata + offset);
-
- /* Skip over pr_gregsetsz and pr_fpregsetsz. */
- offset += (abfd->arch_info->bits_per_word / 8) * 2;
+ {
+ size = bfd_h_get_64 (abfd, (bfd_byte *) note->descdata + offset);
+ offset += 8 * 2;
+ }
- /* Skip over pr_osreldate. */
+ /* Skip over pr_osreldate. */
offset += 4;
- /* Read signal from pr_cursig. */
+ /* Read signal from pr_cursig. */
if (elf_tdata (abfd)->core->signal == 0)
elf_tdata (abfd)->core->signal
= bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
offset += 4;
- /* Read TID from pr_pid. */
+ /* Read TID from pr_pid. */
elf_tdata (abfd)->core->lwpid
= bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + offset);
offset += 4;
- /* Padding before pr_reg. */
- if (abfd->arch_info->bits_per_word == 64)
+ /* Padding before pr_reg. */
+ if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64)
offset += 4;
+ /* Make sure that there is enough data remaining in the note. */
+ if ((note->descsz - offset) < size)
+ return FALSE;
+
/* Make a ".reg/999" section and a ".reg" section. */
return _bfd_elfcore_make_pseudosection (abfd, ".reg",
size, note->descpos + offset);
static bfd_boolean
elfcore_grok_freebsd_note (bfd *abfd, Elf_Internal_Note *note)
{
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
switch (note->type)
{
case NT_PRSTATUS:
+ if (bed->elf_backend_grok_freebsd_prstatus)
+ if ((*bed->elf_backend_grok_freebsd_prstatus) (abfd, note))
+ return TRUE;
return elfcore_grok_freebsd_prstatus (abfd, note);
case NT_FPREGSET:
else
return TRUE;
+ case NT_FREEBSD_PTLWPINFO:
+ return elfcore_make_note_pseudosection (abfd, ".note.freebsdcore.lwpinfo",
+ note);
+
+ case NT_ARM_VFP:
+ return elfcore_grok_arm_vfp (abfd, note);
+
default:
return TRUE;
}
(bfd *abfd, char *buf, int *bufsiz,
const struct elf_internal_linux_prpsinfo *prpsinfo)
{
- struct elf_external_linux_prpsinfo32 data;
+ if (get_elf_backend_data (abfd)->linux_prpsinfo32_ugid16)
+ {
+ struct elf_external_linux_prpsinfo32_ugid16 data;
- swap_linux_prpsinfo32_out (abfd, prpsinfo, &data);
- return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO,
- &data, sizeof (data));
+ swap_linux_prpsinfo32_ugid16_out (abfd, prpsinfo, &data);
+ return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO,
+ &data, sizeof (data));
+ }
+ else
+ {
+ struct elf_external_linux_prpsinfo32_ugid32 data;
+
+ swap_linux_prpsinfo32_ugid32_out (abfd, prpsinfo, &data);
+ return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO,
+ &data, sizeof (data));
+ }
}
char *
(bfd *abfd, char *buf, int *bufsiz,
const struct elf_internal_linux_prpsinfo *prpsinfo)
{
- struct elf_external_linux_prpsinfo64 data;
+ if (get_elf_backend_data (abfd)->linux_prpsinfo64_ugid16)
+ {
+ struct elf_external_linux_prpsinfo64_ugid16 data;
- swap_linux_prpsinfo64_out (abfd, prpsinfo, &data);
- return elfcore_write_note (abfd, buf, bufsiz,
- "CORE", NT_PRPSINFO, &data, sizeof (data));
+ swap_linux_prpsinfo64_ugid16_out (abfd, prpsinfo, &data);
+ return elfcore_write_note (abfd, buf, bufsiz,
+ "CORE", NT_PRPSINFO, &data, sizeof (data));
+ }
+ else
+ {
+ struct elf_external_linux_prpsinfo64_ugid32 data;
+
+ swap_linux_prpsinfo64_ugid32_out (abfd, prpsinfo, &data);
+ return elfcore_write_note (abfd, buf, bufsiz,
+ "CORE", NT_PRPSINFO, &data, sizeof (data));
+ }
}
char *
s390_vxrs_high, size);
}
+char *
+elfcore_write_s390_gs_cb (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *s390_gs_cb,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_S390_GS_CB,
+ s390_gs_cb, size);
+}
+
+char *
+elfcore_write_s390_gs_bc (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *s390_gs_bc,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_S390_GS_BC,
+ s390_gs_bc, size);
+}
+
char *
elfcore_write_arm_vfp (bfd *abfd,
char *buf,
return elfcore_write_s390_vxrs_low (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-s390-vxrs-high") == 0)
return elfcore_write_s390_vxrs_high (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-s390-gs-cb") == 0)
+ return elfcore_write_s390_gs_cb (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-s390-gs-bc") == 0)
+ return elfcore_write_s390_gs_bc (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-arm-vfp") == 0)
return elfcore_write_arm_vfp (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-aarch-tls") == 0)
{
char *buf;
- if (size <= 0)
+ if (size == 0 || (size + 1) == 0)
return TRUE;
if (bfd_seek (abfd, offset, SEEK_SET) != 0)
return n;
}
-/* It is only used by x86-64 so far. */
+/* It is only used by x86-64 so far.
+ ??? This repeats *COM* id of zero. sec->id is supposed to be unique,
+ but current usage would allow all of _bfd_std_section to be zero. */
+static const asymbol lcomm_sym
+ = GLOBAL_SYM_INIT ("LARGE_COMMON", &_bfd_elf_large_com_section);
asection _bfd_elf_large_com_section
- = BFD_FAKE_SECTION (_bfd_elf_large_com_section,
- SEC_IS_COMMON, NULL, "LARGE_COMMON", 0);
+ = BFD_FAKE_SECTION (_bfd_elf_large_com_section, &lcomm_sym,
+ "LARGE_COMMON", 0, SEC_IS_COMMON);
void
_bfd_elf_post_process_headers (bfd * abfd,