/* 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.
{
/* PR 17512: file: f057ec89. */
/* xgettext:c-format */
- _bfd_error_handler (_("%B: attempt to load strings from a non-string section (number %d)"),
+ _bfd_error_handler (_("%B: attempt to load strings from"
+ " a non-string section (number %d)"),
abfd, shindex);
return NULL;
}
{
symoffset += (esym - (bfd_byte *) extsym_buf) / extsym_size;
/* xgettext:c-format */
- _bfd_error_handler (_("%B symbol number %lu references "
- "nonexistent SHT_SYMTAB_SHNDX section"),
+ _bfd_error_handler (_("%B symbol number %lu references"
+ " nonexistent SHT_SYMTAB_SHNDX section"),
ibfd, (unsigned long) symoffset);
if (alloc_intsym != NULL)
free (alloc_intsym);
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size);
+ (_("%B: corrupt size field in group section"
+ " header: 0x%lx"), abfd, shdr->sh_size);
bfd_set_error (bfd_error_bad_value);
-- num_group;
continue;
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: invalid size field in group section header: 0x%lx"), abfd, shdr->sh_size);
+ (_("%B: invalid size field in group section"
+ " header: 0x%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;
}
_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;
}
/* There are some unknown sections in the group. */
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: unknown [%d] section `%s' in group [%s]"),
+ (_("%B: unknown [%d] section `%s' in group [%A]"),
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);
+ shdr->bfd_section);
result = FALSE;
}
}
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: warning: multiple symbol tables detected - ignoring the table in section %u"),
+ (_("%B: warning: multiple symbol tables detected"
+ " - ignoring the table in section %u"),
abfd, shindex);
goto success;
}
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: warning: multiple dynamic symbol tables detected - ignoring the table in section %u"),
+ (_("%B: warning: multiple dynamic symbol tables detected"
+ " - ignoring the table in section %u"),
abfd, shindex);
goto success;
}
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[] =
_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;
}
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
asection *kept;
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: sh_link of section `%A' points to discarded section `%A' of `%B'"),
+ (_("%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
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: sh_link of section `%A' points to removed section `%A' of `%B'"),
+ (_("%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;
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;
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;
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);
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;
&& p->p_paddr < (bfd_vma) off))
{
_bfd_error_handler
- (_("%B: Not enough room for program headers, try linking with -N"),
+ (_("%B: Not enough room for program headers,"
+ " try linking with -N"),
abfd);
bfd_set_error (bfd_error_bad_value);
return FALSE;
/* 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)
+ 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, is this intentional ?"),
- ibfd);
+%B: warning: Empty loadable segment detected at vaddr=0x%.8x, is this intentional ?"),
+ ibfd, segment->p_vaddr);
map->count = 0;
*pointer_to_map = map;
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.
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);
}
/* 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. t*/
+ 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, NULL,
+ = BFD_FAKE_SECTION (_bfd_elf_large_com_section, &lcomm_sym,
"LARGE_COMMON", 0, SEC_IS_COMMON);
void