return TRUE;
}
+bfd_boolean
+bfd_elf_is_group_section (bfd *abfd ATTRIBUTE_UNUSED, const asection *sec)
+{
+ return elf_next_in_group (sec) != NULL;
+}
+
bfd_boolean
bfd_elf_discard_group (bfd *abfd ATTRIBUTE_UNUSED, asection *group)
{
bfd_boolean
_bfd_elf_merge_sections (bfd *abfd, struct bfd_link_info *info)
{
+ bfd *ibfd;
+ asection *sec;
+
if (!is_elf_hash_table (info->hash))
return FALSE;
- if (elf_hash_table (info)->merge_info)
- _bfd_merge_sections (abfd, elf_hash_table (info)->merge_info,
+
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ if ((ibfd->flags & DYNAMIC) == 0)
+ for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+ if ((sec->flags & SEC_MERGE) != 0
+ && !bfd_is_abs_section (sec->output_section))
+ {
+ struct bfd_elf_section_data *secdata;
+
+ secdata = elf_section_data (sec);
+ if (! _bfd_add_merge_section (abfd,
+ &elf_hash_table (info)->merge_info,
+ sec, &secdata->sec_info))
+ return FALSE;
+ else if (secdata->sec_info)
+ sec->sec_info_type = ELF_INFO_TYPE_MERGE;
+ }
+
+ if (elf_hash_table (info)->merge_info != NULL)
+ _bfd_merge_sections (abfd, info, elf_hash_table (info)->merge_info,
merge_sections_remove_hook);
return TRUE;
}
case PT_TLS: pt = "TLS"; break;
case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break;
case PT_GNU_STACK: pt = "STACK"; break;
+ case PT_GNU_RELRO: pt = "RELRO"; break;
default: sprintf (buf, "0x%lx", p->p_type); pt = buf; break;
}
fprintf (f, "%8s off 0x", pt);
fprintf (f, _("\nDynamic Section:\n"));
- dynbuf = bfd_malloc (s->_raw_size);
- if (dynbuf == NULL)
- goto error_return;
- if (! bfd_get_section_contents (abfd, s, dynbuf, 0, s->_raw_size))
+ if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
goto error_return;
elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
extdyn = dynbuf;
- extdynend = extdyn + s->_raw_size;
+ extdynend = extdyn + s->size;
for (; extdyn < extdynend; extdyn += extdynsize)
{
Elf_Internal_Dyn dyn;
return TRUE;
s = bfd_get_section_by_name (abfd, ".dynamic");
- if (s == NULL || s->_raw_size == 0)
+ if (s == NULL || s->size == 0)
return TRUE;
- dynbuf = bfd_malloc (s->_raw_size);
- if (dynbuf == NULL)
- goto error_return;
-
- if (! bfd_get_section_contents (abfd, s, dynbuf, 0, s->_raw_size))
+ if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
goto error_return;
elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
extdyn = dynbuf;
- extdynend = extdyn + s->_raw_size;
+ extdynend = extdyn + s->size;
for (; extdyn < extdynend; extdyn += extdynsize)
{
Elf_Internal_Dyn dyn;
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)
- if ((s = (++idx)->shdr->bfd_section) != NULL
+ if ((s = (--idx)->shdr->bfd_section) != NULL
&& elf_next_in_group (s) != NULL)
{
elf_next_in_group (hdr->bfd_section) = s;
{ ".gnu.version", 12, 0, SHT_GNU_versym, 0 },
{ ".gnu.version_d", 14, 0, SHT_GNU_verdef, 0 },
{ ".gnu.version_r", 14, 0, SHT_GNU_verneed, 0 },
+ { ".note.GNU-stack",15, 0, SHT_PROGBITS, 0 },
{ ".note", 5, -1, SHT_NOTE, 0 },
{ ".rela", 5, -1, SHT_RELA, 0 },
{ ".rel", 4, -1, SHT_REL, 0 },
return FALSE;
newsect->vma = hdr->p_vaddr;
newsect->lma = hdr->p_paddr;
- newsect->_raw_size = hdr->p_filesz;
+ newsect->size = hdr->p_filesz;
newsect->filepos = hdr->p_offset;
newsect->flags |= SEC_HAS_CONTENTS;
newsect->alignment_power = bfd_log2 (hdr->p_align);
return FALSE;
newsect->vma = hdr->p_vaddr + hdr->p_filesz;
newsect->lma = hdr->p_paddr + hdr->p_filesz;
- newsect->_raw_size = hdr->p_memsz - hdr->p_filesz;
+ newsect->size = hdr->p_memsz - hdr->p_filesz;
if (hdr->p_type == PT_LOAD)
{
newsect->flags |= SEC_ALLOC;
case PT_GNU_STACK:
return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "stack");
+ case PT_GNU_RELRO:
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "relro");
+
default:
/* Check for any processor-specific program segment types.
If no handler for them, default to making "segment" sections. */
this_hdr->sh_addr = 0;
this_hdr->sh_offset = 0;
- this_hdr->sh_size = asect->_raw_size;
+ this_hdr->sh_size = asect->size;
this_hdr->sh_link = 0;
this_hdr->sh_addralign = 1 << asect->alignment_power;
/* The sh_entsize and sh_info fields may have been set already by
asect->flags. */
if (this_hdr->sh_type == SHT_NULL)
{
- if ((asect->flags & SEC_ALLOC) != 0
+ if ((asect->flags & SEC_GROUP) != 0)
+ {
+ /* We also need to mark SHF_GROUP here for relocatable
+ link. */
+ struct bfd_link_order *l;
+ asection *elt;
+
+ for (l = asect->link_order_head; l != NULL; l = l->next)
+ if (l->type == bfd_indirect_link_order
+ && (elt = elf_next_in_group (l->u.indirect.section)) != NULL)
+ do
+ {
+ /* The name is not important. Anything will do. */
+ elf_group_name (elt->output_section) = "G";
+ elf_section_flags (elt->output_section) |= SHF_GROUP;
+
+ elt = elf_next_in_group (elt);
+ /* During a relocatable link, the lists are
+ circular. */
+ }
+ while (elt != elf_next_in_group (l->u.indirect.section));
+
+ this_hdr->sh_type = SHT_GROUP;
+ }
+ else if ((asect->flags & SEC_ALLOC) != 0
&& (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
|| (asect->flags & SEC_NEVER_LOAD) != 0))
this_hdr->sh_type = SHT_NOBITS;
if ((asect->flags & SEC_THREAD_LOCAL) != 0)
{
this_hdr->sh_flags |= SHF_TLS;
- if (asect->_raw_size == 0 && (asect->flags & SEC_HAS_CONTENTS) == 0)
+ if (asect->size == 0 && (asect->flags & SEC_HAS_CONTENTS) == 0)
{
struct bfd_link_order *o;
if (sec->contents == NULL)
{
gas = FALSE;
- sec->contents = bfd_alloc (abfd, sec->_raw_size);
+ sec->contents = bfd_alloc (abfd, sec->size);
/* Arrange for the section to be written out. */
elf_section_data (sec)->this_hdr.contents = sec->contents;
}
}
- loc = sec->contents + sec->_raw_size;
+ loc = sec->contents + sec->size;
/* Get the pointer to the first section in the group that gas
squirreled away here. objcopy arranges for this to be set to the
last_hdr = hdr;
/* .tbss sections effectively have zero size. */
if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
- last_size = hdr->_raw_size;
+ last_size = hdr->size;
else
last_size = 0;
continue;
last_hdr = hdr;
/* .tbss sections effectively have zero size. */
if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
- last_size = hdr->_raw_size;
+ last_size = hdr->size;
else
last_size = 0;
phdr_index = i;
pm = &m->next;
}
+ if (elf_tdata (abfd)->relro)
+ {
+ amt = sizeof (struct elf_segment_map);
+ m = bfd_zalloc (abfd, amt);
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_GNU_RELRO;
+ m->p_flags = PF_R;
+ m->p_flags_valid = 1;
+
+ *pm = m;
+ pm = &m->next;
+ }
+
free (sections);
sections = NULL;
/* Sort by size, to put zero sized sections
before others at the same address. */
- size1 = (sec1->flags & SEC_LOAD) ? sec1->_raw_size : 0;
- size2 = (sec2->flags & SEC_LOAD) ? sec2->_raw_size : 0;
+ size1 = (sec1->flags & SEC_LOAD) ? sec1->size : 0;
+ size2 = (sec2->flags & SEC_LOAD) ? sec2->size : 0;
if (size1 < size2)
return -1;
contents. */
if ((flags & SEC_LOAD) != 0
|| (flags & SEC_HAS_CONTENTS) != 0)
- off += sec->_raw_size;
+ off += sec->size;
if ((flags & SEC_ALLOC) != 0
&& ((flags & SEC_LOAD) != 0
|| (flags & SEC_THREAD_LOCAL) == 0))
- voff += sec->_raw_size;
+ voff += sec->size;
}
if (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core)
if (i == 0)
{
sec->filepos = off;
- p->p_filesz = sec->_raw_size;
- off += sec->_raw_size;
+ p->p_filesz = sec->size;
+ off += sec->size;
voff = off;
}
else
{
/* Fake sections -- don't need to be written. */
sec->filepos = 0;
- sec->_raw_size = 0;
+ sec->size = 0;
flags = sec->flags = 0;
}
p->p_memsz = 0;
if ((sec->flags & SEC_LOAD) != 0
|| (sec->flags & SEC_THREAD_LOCAL) == 0
|| p->p_type == PT_TLS)
- p->p_memsz += sec->_raw_size;
+ p->p_memsz += sec->size;
if ((flags & SEC_LOAD) != 0)
- p->p_filesz += sec->_raw_size;
+ p->p_filesz += sec->size;
if (p->p_type == PT_TLS
- && sec->_raw_size == 0
+ && sec->size == 0
&& (sec->flags & SEC_HAS_CONTENTS) == 0)
{
struct bfd_link_order *o;
if (! m->p_paddr_valid)
p->p_paddr = phdrs_paddr;
}
+ else if (p->p_type == PT_GNU_RELRO)
+ {
+ Elf_Internal_Phdr *lp;
+
+ for (lp = phdrs; lp < phdrs + count; ++lp)
+ {
+ if (lp->p_type == PT_LOAD
+ && lp->p_vaddr <= link_info->relro_end
+ && lp->p_vaddr >= link_info->relro_start
+ && lp->p_vaddr + lp->p_filesz
+ >= link_info->relro_end)
+ break;
+ }
+
+ if (lp < phdrs + count
+ && link_info->relro_end > lp->p_vaddr)
+ {
+ p->p_vaddr = lp->p_vaddr;
+ p->p_paddr = lp->p_paddr;
+ p->p_offset = lp->p_offset;
+ p->p_filesz = link_info->relro_end - lp->p_vaddr;
+ p->p_memsz = p->p_filesz;
+ p->p_align = 1;
+ p->p_flags = (lp->p_flags & ~PF_W);
+ }
+ else
+ {
+ memset (p, 0, sizeof *p);
+ p->p_type = PT_NULL;
+ }
+ }
}
}
++segs;
}
+ if (elf_tdata (abfd)->relro)
+ {
+ /* We need a PT_GNU_RELRO segment. */
+ ++segs;
+ }
+
for (s = abfd->sections; s != NULL; s = s->next)
{
if ((s->flags & SEC_LOAD) != 0
#define SECTION_SIZE(section, segment) \
(((section->flags & (SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) \
!= SEC_THREAD_LOCAL || segment->p_type == PT_TLS) \
- ? section->_raw_size : 0)
+ ? section->size : 0)
/* Returns TRUE if the given section is contained within
the given segment. VMA addresses are compared. */
&& bfd_get_format (ibfd) == bfd_core \
&& s->vma == 0 && s->lma == 0 \
&& (bfd_vma) s->filepos >= p->p_offset \
- && ((bfd_vma) s->filepos + s->_raw_size \
+ && ((bfd_vma) s->filepos + s->size \
<= p->p_offset + p->p_filesz))
/* The complicated case when p_vaddr is 0 is to handle the Solaris
&& p->p_memsz == 0 \
&& p->p_filesz > 0 \
&& (s->flags & SEC_HAS_CONTENTS) != 0 \
- && s->_raw_size > 0 \
+ && s->size > 0 \
&& (bfd_vma) s->filepos >= p->p_offset \
- && ((bfd_vma) s->filepos + s->_raw_size \
+ && ((bfd_vma) s->filepos + s->size \
<= p->p_offset + p->p_filesz))
/* Decide if the given section should be included in the given segment.
/* If the gap between the end of the previous section
and the start of this section is more than
maxpagesize then we need to start a new segment. */
- if ((BFD_ALIGN (prev_sec->lma + prev_sec->_raw_size,
+ if ((BFD_ALIGN (prev_sec->lma + prev_sec->size,
maxpagesize)
< BFD_ALIGN (output_section->lma, maxpagesize))
- || ((prev_sec->lma + prev_sec->_raw_size)
+ || ((prev_sec->lma + prev_sec->size)
> output_section->lma))
{
if (suggested_lma == 0)
|| obfd->xvec->flavour != bfd_target_elf_flavour)
return TRUE;
- if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL)
- {
- asection *s;
-
- /* Only set up the segments if there are no more SEC_ALLOC
- sections. FIXME: This won't do the right thing if objcopy is
- used to remove the last SEC_ALLOC section, since objcopy
- won't call this routine in that case. */
- for (s = isec->next; s != NULL; s = s->next)
- if ((s->flags & SEC_ALLOC) != 0)
- break;
- if (s == NULL)
- {
- if (! copy_private_bfd_data (ibfd, obfd))
- return FALSE;
- }
- }
-
ihdr = &elf_section_data (isec)->this_hdr;
ohdr = &elf_section_data (osec)->this_hdr;
return TRUE;
}
+/* Copy private header information. */
+
+bfd_boolean
+_bfd_elf_copy_private_header_data (bfd *ibfd, bfd *obfd)
+{
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return TRUE;
+
+ /* Copy over private BFD data if it has not already been copied.
+ This must be done here, rather than in the copy_private_bfd_data
+ entry point, because the latter is called after the section
+ contents have been set, which means that the program headers have
+ already been worked out. */
+ if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL)
+ {
+ if (! copy_private_bfd_data (ibfd, obfd))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/* Copy private symbol information. If this symbol is in a section
which we did not map into a BFD section, try to map the section
index correctly. We use special macro definitions for the mapped
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))
- ret += ((s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize)
+ ret += ((s->size / elf_section_data (s)->this_hdr.sh_entsize)
* sizeof (arelent *));
return ret;
if (! (*slurp_relocs) (abfd, s, syms, TRUE))
return -1;
- count = s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize;
+ count = s->size / elf_section_data (s)->this_hdr.sh_entsize;
p = s->relocation;
for (i = 0; i < count; i++)
*storage++ = p++;
if (sect2 == NULL)
return FALSE;
- sect2->_raw_size = sect->_raw_size;
+ sect2->size = sect->size;
sect2->filepos = sect->filepos;
sect2->flags = sect->flags;
sect2->alignment_power = sect->alignment_power;
sect = bfd_make_section_anyway (abfd, threaded_name);
if (sect == NULL)
return FALSE;
- sect->_raw_size = size;
+ sect->size = size;
sect->filepos = filepos;
sect->flags = SEC_HAS_CONTENTS;
sect->alignment_power = 2;
static bfd_boolean
elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
{
- size_t raw_size;
+ size_t size;
int offset;
if (note->descsz == sizeof (prstatus_t))
{
prstatus_t prstat;
- raw_size = sizeof (prstat.pr_reg);
+ size = sizeof (prstat.pr_reg);
offset = offsetof (prstatus_t, pr_reg);
memcpy (&prstat, note->descdata, sizeof (prstat));
/* 64-bit host, 32-bit corefile */
prstatus32_t prstat;
- raw_size = sizeof (prstat.pr_reg);
+ size = sizeof (prstat.pr_reg);
offset = offsetof (prstatus32_t, pr_reg);
memcpy (&prstat, note->descdata, sizeof (prstat));
/* Make a ".reg/999" section and a ".reg" section. */
return _bfd_elfcore_make_pseudosection (abfd, ".reg",
- raw_size, note->descpos + offset);
+ size, note->descpos + offset);
}
#endif /* defined (HAVE_PRSTATUS_T) */
return FALSE;
#if defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
- sect->_raw_size = sizeof (lwpstat.pr_context.uc_mcontext.gregs);
+ sect->size = sizeof (lwpstat.pr_context.uc_mcontext.gregs);
sect->filepos = note->descpos
+ offsetof (lwpstatus_t, pr_context.uc_mcontext.gregs);
#endif
#if defined (HAVE_LWPSTATUS_T_PR_REG)
- sect->_raw_size = sizeof (lwpstat.pr_reg);
+ sect->size = sizeof (lwpstat.pr_reg);
sect->filepos = note->descpos + offsetof (lwpstatus_t, pr_reg);
#endif
return FALSE;
#if defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
- sect->_raw_size = sizeof (lwpstat.pr_context.uc_mcontext.fpregs);
+ sect->size = sizeof (lwpstat.pr_context.uc_mcontext.fpregs);
sect->filepos = note->descpos
+ offsetof (lwpstatus_t, pr_context.uc_mcontext.fpregs);
#endif
#if defined (HAVE_LWPSTATUS_T_PR_FPREG)
- sect->_raw_size = sizeof (lwpstat.pr_fpreg);
+ sect->size = sizeof (lwpstat.pr_fpreg);
sect->filepos = note->descpos + offsetof (lwpstatus_t, pr_fpreg);
#endif
if (sect == NULL)
return FALSE;
- sect->_raw_size = sizeof (pstatus.data.thread_info.thread_context);
+ sect->size = sizeof (pstatus.data.thread_info.thread_context);
sect->filepos = (note->descpos
+ offsetof (struct win32_pstatus,
data.thread_info.thread_context));
if (sect == NULL)
return FALSE;
- sect->_raw_size = note->descsz;
+ sect->size = note->descsz;
sect->filepos = note->descpos;
sect->flags = SEC_HAS_CONTENTS;
sect->alignment_power = 2;
if (sect == NULL)
return FALSE;
- sect->_raw_size = note->descsz;
+ sect->size = note->descsz;
sect->filepos = note->descpos;
sect->flags = SEC_HAS_CONTENTS;
sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
if (sect == NULL)
return FALSE;
- sect->_raw_size = note->descsz;
+ sect->size = note->descsz;
sect->filepos = note->descpos;
sect->flags = SEC_HAS_CONTENTS;
sect->alignment_power = 2;
if (sect == NULL)
return FALSE;
- sect->_raw_size = note->descsz;
+ sect->size = note->descsz;
sect->filepos = note->descpos;
sect->flags = SEC_HAS_CONTENTS;
sect->alignment_power = 2;
rel->r_addend =
_bfd_merged_section_offset (abfd, psec,
elf_section_data (sec)->sec_info,
- sym->st_value + rel->r_addend,
- 0);
- sec = *psec;
+ sym->st_value + rel->r_addend);
+ if (sec != *psec)
+ {
+ /* If we have changed the section, and our original section is
+ marked with SEC_EXCLUDE, it means that the original
+ SEC_MERGE section has been completely subsumed in some
+ other SEC_MERGE section. In this case, we need to leave
+ some info around for --emit-relocs. */
+ if ((sec->flags & SEC_EXCLUDE) != 0)
+ sec->kept_section = *psec;
+ sec = *psec;
+ }
rel->r_addend -= relocation;
rel->r_addend += sec->output_section->vma + sec->output_offset;
}
return _bfd_merged_section_offset (abfd, psec,
elf_section_data (sec)->sec_info,
- sym->st_value + addend, 0);
+ sym->st_value + addend);
}
bfd_vma
_bfd_elf_section_offset (bfd *abfd,
- struct bfd_link_info *info,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
asection *sec,
bfd_vma offset)
{
- struct bfd_elf_section_data *sec_data;
-
- sec_data = elf_section_data (sec);
switch (sec->sec_info_type)
{
case ELF_INFO_TYPE_STABS:
- return _bfd_stab_section_offset (abfd,
- &elf_hash_table (info)->merge_info,
- sec, &sec_data->sec_info, offset);
+ return _bfd_stab_section_offset (sec, elf_section_data (sec)->sec_info,
+ offset);
case ELF_INFO_TYPE_EH_FRAME:
return _bfd_elf_eh_frame_section_offset (abfd, sec, offset);
default:
if (! (*slurp_relocs) (abfd, relplt, dynsyms, TRUE))
return -1;
- count = relplt->_raw_size / hdr->sh_entsize;
+ count = relplt->size / hdr->sh_entsize;
size = count * sizeof (asymbol);
p = relplt->relocation;
for (i = 0; i < count; i++, s++, p++)