}
void
-bfd_elf_set_dyn_lib_class (bfd *abfd, int lib_class)
+bfd_elf_set_dyn_lib_class (bfd *abfd, enum dynamic_lib_link_class lib_class)
{
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& bfd_get_format (abfd) == bfd_object)
abfd->flags |= HAS_RELOC;
return TRUE;
}
- break;
case SHT_GNU_verdef:
elf_dynverdef (abfd) = shindex;
elf_tdata (abfd)->dynverdef_hdr = *hdr;
return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
- break;
case SHT_GNU_versym:
if (hdr->sh_entsize != sizeof (Elf_External_Versym))
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);
+ kept = _bfd_elf_check_kept_section (s, link_info);
if (kept == NULL)
{
bfd_set_error (bfd_error_bad_value);
hdr->sh_offset = hdr->bfd_section->filepos;
else if ((hdr->sh_flags & SHF_ALLOC) != 0)
{
- ((*_bfd_error_handler)
- (_("%B: warning: allocated section `%s' not in segment"),
- abfd,
- (hdr->bfd_section == NULL
- ? "*unknown*"
- : hdr->bfd_section->name)));
- if ((abfd->flags & D_PAGED) != 0)
+ if (hdr->sh_size != 0)
+ ((*_bfd_error_handler)
+ (_("%B: warning: allocated section `%s' not in segment"),
+ abfd,
+ (hdr->bfd_section == NULL
+ ? "*unknown*"
+ : hdr->bfd_section->name)));
+ /* 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);
else
7. SHF_TLS sections are only in PT_TLS or PT_LOAD segments.
8. PT_DYNAMIC should not contain empty sections at the beginning
(with the possible exception of .dynamic). */
-#define INCLUDE_SECTION_IN_SEGMENT(section, segment, bed) \
+#define IS_SECTION_IN_INPUT_SEGMENT(section, segment, bed) \
((((segment->p_paddr \
? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr) \
: IS_CONTAINED_BY_VMA (section, segment)) \
&& (section->flags & SEC_ALLOC) != 0) \
|| IS_COREFILE_NOTE (segment, section)) \
- && section->output_section != NULL \
&& segment->p_type != PT_GNU_STACK \
&& (segment->p_type != PT_TLS \
|| (section->flags & SEC_THREAD_LOCAL)) \
== 0)) \
&& ! section->segment_mark)
+/* If the output section of a section in the input segment is NULL,
+ it is removed from the corresponding output segment. */
+#define INCLUDE_SECTION_IN_SEGMENT(section, segment, bed) \
+ (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed) \
+ && section->output_section != NULL)
+
/* Returns TRUE iff seg1 starts after the end of seg2. */
#define SEGMENT_AFTER_SEGMENT(seg1, seg2, field) \
(seg1->field >= SEGMENT_END (seg2, seg2->field))
bfd_vma suggested_lma;
unsigned int j;
bfd_size_type amt;
+ asection * first_section;
if (segment->p_type == PT_NULL)
continue;
+ first_section = NULL;
/* Compute how many sections might be placed into this segment. */
for (section = ibfd->sections, section_count = 0;
section != NULL;
section = section->next)
- if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed))
- ++section_count;
+ {
+ /* Find the first section in the input segment, which may be
+ removed from the corresponding output segment. */
+ if (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed))
+ {
+ if (first_section == NULL)
+ first_section = section;
+ if (section->output_section != NULL)
+ ++section_count;
+ }
+ }
/* Allocate a segment map big enough to contain
all of the sections we have selected. */
amt = sizeof (struct elf_segment_map);
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
- map = bfd_alloc (obfd, amt);
+ map = bfd_zalloc (obfd, amt);
if (map == NULL)
return FALSE;
map->p_type = segment->p_type;
map->p_flags = segment->p_flags;
map->p_flags_valid = 1;
- map->p_paddr = segment->p_paddr;
- map->p_paddr_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. */
+ if (!first_section || first_section->output_section != NULL)
+ {
+ map->p_paddr = segment->p_paddr;
+ map->p_paddr_valid = 1;
+ }
/* Determine if this segment contains the ELF file header
and if it contains the program headers themselves. */
#undef IS_CONTAINED_BY_LMA
#undef IS_COREFILE_NOTE
#undef IS_SOLARIS_PT_INTERP
+#undef IS_SECTION_IN_INPUT_SEGMENT
#undef INCLUDE_SECTION_IN_SEGMENT
#undef SEGMENT_AFTER_SEGMENT
#undef SEGMENT_OVERLAPS
amt = sizeof (struct elf_segment_map);
if (section_count != 0)
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
- map = bfd_alloc (obfd, amt);
+ map = bfd_zalloc (obfd, amt);
if (map == NULL)
return FALSE;
output BFD section flags have been set to something different.
elf_fake_sections will set ELF section type based on BFD
section flags. */
- if (osec->flags == isec->flags
- || (osec->flags == 0 && elf_section_type (osec) == SHT_NULL))
- elf_section_type (osec) = elf_section_type (isec);
+ if (osec->flags == isec->flags || !osec->flags)
+ {
+ BFD_ASSERT (osec->flags == isec->flags
+ || (!osec->flags
+ && elf_section_type (osec) == SHT_NULL));
+ elf_section_type (osec) = elf_section_type (isec);
+ }
+
+ /* FIXME: Is this correct for all OS/PROC specific flags? */
+ elf_section_flags (osec) |= (elf_section_flags (isec)
+ & (SHF_MASKOS | SHF_MASKPROC));
/* Set things up for objcopy and relocatable link. The output
SHT_GROUP section will have its elf_next_in_group pointing back
/* Function: elfcore_write_note
Inputs:
- buffer to hold note
+ buffer to hold note, and current size of buffer
name of note
type of note
data for note
size of data for note
+ Writes note to end of buffer. ELF64 notes are written exactly as
+ for ELF32, despite the current (as of 2006) ELF gabi specifying
+ that they ought to have 8-byte namesz and descsz field, and have
+ 8-byte alignment. Other writers, eg. Linux kernel, do the same.
+
Return:
- End of buffer containing note. */
+ Pointer to realloc'd buffer, *BUFSIZ updated. */
char *
-elfcore_write_note (bfd *abfd,
+elfcore_write_note (bfd *abfd,
char *buf,
- int *bufsiz,
+ int *bufsiz,
const char *name,
- int type,
+ int type,
const void *input,
- int size)
+ int size)
{
Elf_External_Note *xnp;
size_t namesz;
- size_t pad;
size_t newspace;
- char *p, *dest;
+ char *dest;
namesz = 0;
- pad = 0;
if (name != NULL)
- {
- const struct elf_backend_data *bed;
-
- namesz = strlen (name) + 1;
- bed = get_elf_backend_data (abfd);
- pad = -namesz & ((1 << bed->s->log_file_align) - 1);
- }
+ namesz = strlen (name) + 1;
- newspace = 12 + namesz + pad + size;
+ newspace = 12 + ((namesz + 3) & -4) + ((size + 3) & -4);
- p = realloc (buf, *bufsiz + newspace);
- dest = p + *bufsiz;
+ buf = realloc (buf, *bufsiz + newspace);
+ dest = buf + *bufsiz;
*bufsiz += newspace;
xnp = (Elf_External_Note *) dest;
H_PUT_32 (abfd, namesz, xnp->namesz);
{
memcpy (dest, name, namesz);
dest += namesz;
- while (pad != 0)
+ while (namesz & 3)
{
*dest++ = '\0';
- --pad;
+ ++namesz;
}
}
memcpy (dest, input, size);
- return p;
+ dest += size;
+ while (size & 3)
+ {
+ *dest++ = '\0';
+ ++size;
+ }
+ return buf;
}
#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
symbols. */
bfd_boolean
-bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2)
+bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
+ struct bfd_link_info *info)
{
bfd *bfd1, *bfd2;
const struct elf_backend_data *bed1, *bed2;
if (symcount1 == 0 || symcount2 == 0)
return FALSE;
- isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0,
- NULL, NULL, NULL);
- isymbuf2 = bfd_elf_get_elf_syms (bfd2, hdr2, symcount2, 0,
- NULL, NULL, NULL);
-
result = FALSE;
- if (isymbuf1 == NULL || isymbuf2 == NULL)
- goto done;
+ isymbuf1 = elf_tdata (bfd1)->symbuf;
+ isymbuf2 = elf_tdata (bfd2)->symbuf;
+
+ if (isymbuf1 == NULL)
+ {
+ isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0,
+ NULL, NULL, NULL);
+ if (isymbuf1 == NULL)
+ goto done;
+ /* Sort symbols by binding and section. Global definitions are at
+ the beginning. */
+ qsort (isymbuf1, symcount1, sizeof (Elf_Internal_Sym),
+ elf_sort_elf_symbol);
+ if (!info->reduce_memory_overheads)
+ elf_tdata (bfd1)->symbuf = isymbuf1;
+ }
- /* Sort symbols by binding and section. Global definitions are at
- the beginning. */
- qsort (isymbuf1, symcount1, sizeof (Elf_Internal_Sym),
- elf_sort_elf_symbol);
- qsort (isymbuf2, symcount2, sizeof (Elf_Internal_Sym),
- elf_sort_elf_symbol);
+ if (isymbuf2 == NULL)
+ {
+ isymbuf2 = bfd_elf_get_elf_syms (bfd2, hdr2, symcount2, 0,
+ NULL, NULL, NULL);
+ if (isymbuf2 == NULL)
+ goto done;
+ /* Sort symbols by binding and section. Global definitions are at
+ the beginning. */
+ qsort (isymbuf2, symcount2, sizeof (Elf_Internal_Sym),
+ elf_sort_elf_symbol);
+ if (!info->reduce_memory_overheads)
+ elf_tdata (bfd2)->symbuf = isymbuf2;
+ }
/* Count definitions in the section. */
count1 = 0;
free (symtable1);
if (symtable2)
free (symtable2);
- if (isymbuf1)
- free (isymbuf1);
- if (isymbuf2)
- free (isymbuf2);
+ if (info->reduce_memory_overheads)
+ {
+ if (isymbuf1)
+ free (isymbuf1);
+ if (isymbuf2)
+ free (isymbuf2);
+ }
return result;
}