return h & 0xffffffff;
}
+/* DT_GNU_HASH hash function. Do not change this function; you will
+ cause invalid hash tables to be generated. */
+
+unsigned long
+bfd_elf_gnu_hash (const char *namearg)
+{
+ const unsigned char *name = (const unsigned char *) namearg;
+ unsigned long h = 5381;
+ unsigned char ch;
+
+ while ((ch = *name++) != '\0')
+ h = (h << 5) + h + ch;
+ return h & 0xffffffff;
+}
+
bfd_boolean
bfd_elf_mkobject (bfd *abfd)
{
- /* This just does initialization. */
- /* coff_mkobject zalloc's space for tdata.coff_obj_data ... */
- elf_tdata (abfd) = bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
- if (elf_tdata (abfd) == 0)
- return FALSE;
- /* Since everything is done at close time, do we need any
- initialization? */
+ if (abfd->tdata.any == NULL)
+ {
+ abfd->tdata.any = bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
+ if (abfd->tdata.any == NULL)
+ return FALSE;
+ }
+
+ elf_tdata (abfd)->program_header_size = (bfd_size_type) -1;
return TRUE;
}
{ "debug", 5 }, /* 'd' */
{ NULL, 0 }, /* 'e' */
{ NULL, 0 }, /* 'f' */
- { "gnu.linkonce.wi.", 17 }, /* 'g' */
+ { "gnu.linkonce.wi.", 16 }, /* 'g' */
{ NULL, 0 }, /* 'h' */
{ NULL, 0 }, /* 'i' */
{ NULL, 0 }, /* 'j' */
case DT_AUXILIARY: name = "AUXILIARY"; stringp = TRUE; break;
case DT_USED: name = "USED"; break;
case DT_FILTER: name = "FILTER"; stringp = TRUE; break;
+ case DT_GNU_HASH: name = "GNU_HASH"; break;
}
fprintf (f, " %-11s ", name);
table->bucketcount = 0;
table->needed = NULL;
table->hgot = NULL;
+ table->hplt = NULL;
table->merge_info = NULL;
memset (&table->stab_info, 0, sizeof (table->stab_info));
memset (&table->eh_info, 0, sizeof (table->eh_info));
case SHT_FINI_ARRAY: /* .fini_array section. */
case SHT_PREINIT_ARRAY: /* .preinit_array section. */
case SHT_GNU_LIBLIST: /* .gnu.liblist section. */
+ case SHT_GNU_HASH: /* .gnu.hash section. */
return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
case SHT_DYNAMIC: /* Dynamic linking information. */
"`%s' [0x%8x]"),
abfd, name, hdr->sh_type);
else if (hdr->sh_type >= SHT_LOOS && hdr->sh_type <= SHT_HIOS)
- /* FIXME: We should handle this section. */
- (*_bfd_error_handler)
- (_("%B: don't know how to handle OS specific section "
- "`%s' [0x%8x]"),
- abfd, name, hdr->sh_type);
+ {
+ /* Unrecognised OS-specific sections. */
+ if ((hdr->sh_flags & SHF_OS_NONCONFORMING) != 0)
+ /* 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);
+ else
+ /* Otherwise it should be processed. */
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ }
else
/* FIXME: We should handle this section. */
(*_bfd_error_handler)
{ ".gnu.version_r", 14, 0, SHT_GNU_verneed, 0 },
{ ".gnu.liblist", 12, 0, SHT_GNU_LIBLIST, SHF_ALLOC },
{ ".gnu.conflict", 13, 0, SHT_RELA, SHF_ALLOC },
+ { ".gnu.hash", 9, 0, SHT_GNU_HASH, SHF_ALLOC },
{ NULL, 0, 0, 0, 0 }
};
case SHT_GROUP:
this_hdr->sh_entsize = 4;
break;
+
+ case SHT_GNU_HASH:
+ this_hdr->sh_entsize = bed->s->arch_size == 64 ? 0 : 4;
+ break;
}
if ((asect->flags & SEC_ALLOC) != 0)
break;
case SHT_HASH:
+ case SHT_GNU_HASH:
case SHT_GNU_versym:
/* sh_link is the section header index of the symbol table
this hash table or version table is for. */
return TRUE;
}
+/* Make an initial estimate of the size of the program header. If we
+ get the number wrong here, we'll redo section placement. */
+
+static bfd_size_type
+get_program_header_size (bfd *abfd, struct bfd_link_info *info)
+{
+ size_t segs;
+ asection *s;
+ const struct elf_backend_data *bed;
+
+ /* Assume we will need exactly two PT_LOAD segments: one for text
+ and one for data. */
+ segs = 2;
+
+ s = bfd_get_section_by_name (abfd, ".interp");
+ if (s != NULL && (s->flags & SEC_LOAD) != 0)
+ {
+ /* If we have a loadable interpreter section, we need a
+ PT_INTERP segment. In this case, assume we also need a
+ PT_PHDR segment, although that may not be true for all
+ targets. */
+ segs += 2;
+ }
+
+ if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
+ {
+ /* We need a PT_DYNAMIC segment. */
+ ++segs;
+
+ if (elf_tdata (abfd)->relro)
+ {
+ /* We need a PT_GNU_RELRO segment only when there is a
+ PT_DYNAMIC segment. */
+ ++segs;
+ }
+ }
+
+ if (elf_tdata (abfd)->eh_frame_hdr)
+ {
+ /* We need a PT_GNU_EH_FRAME segment. */
+ ++segs;
+ }
+
+ if (elf_tdata (abfd)->stack_flags)
+ {
+ /* We need a PT_GNU_STACK segment. */
+ ++segs;
+ }
+
+ for (s = abfd->sections; s != NULL; s = s->next)
+ {
+ if ((s->flags & SEC_LOAD) != 0
+ && strncmp (s->name, ".note", 5) == 0)
+ {
+ /* We need a PT_NOTE segment. */
+ ++segs;
+ }
+ }
+
+ for (s = abfd->sections; s != NULL; s = s->next)
+ {
+ if (s->flags & SEC_THREAD_LOCAL)
+ {
+ /* We need a PT_TLS segment. */
+ ++segs;
+ break;
+ }
+ }
+
+ /* Let the backend count up any program headers it might need. */
+ bed = get_elf_backend_data (abfd);
+ if (bed->elf_backend_additional_program_headers)
+ {
+ int a;
+
+ a = (*bed->elf_backend_additional_program_headers) (abfd, info);
+ if (a == -1)
+ abort ();
+ segs += a;
+ }
+
+ return segs * bed->s->sizeof_phdr;
+}
+
/* Create a mapping from a set of sections to a program segment. */
static struct elf_segment_map *
return m;
}
-/* Set up a mapping from BFD sections to program segments. */
+/* Possibly add or remove segments from the segment map. */
static bfd_boolean
-map_sections_to_segments (bfd *abfd)
+elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
{
- asection **sections = NULL;
- asection *s;
- unsigned int i;
- unsigned int count;
- struct elf_segment_map *mfirst;
- struct elf_segment_map **pm;
- struct elf_segment_map *m;
- asection *last_hdr;
- bfd_vma last_size;
- unsigned int phdr_index;
- bfd_vma maxpagesize;
- asection **hdrpp;
- bfd_boolean phdr_in_segment = TRUE;
- bfd_boolean writable;
- int tls_count = 0;
- asection *first_tls = NULL;
- asection *dynsec, *eh_frame_hdr;
- bfd_size_type amt;
-
- if (elf_tdata (abfd)->segment_map != NULL)
- return TRUE;
+ struct elf_segment_map **m;
+ const struct elf_backend_data *bed;
- if (bfd_count_sections (abfd) == 0)
- return TRUE;
+ /* The placement algorithm assumes that non allocated sections are
+ not in PT_LOAD segments. We ensure this here by removing such
+ sections from the segment map. We also remove excluded
+ sections. Finally, any PT_LOAD segment without sections is
+ removed. */
+ m = &elf_tdata (abfd)->segment_map;
+ while (*m)
+ {
+ unsigned int i, new_count;
- /* Select the allocated sections, and sort them. */
+ for (new_count = 0, i = 0; i < (*m)->count; i++)
+ {
+ if (((*m)->sections[i]->flags & SEC_EXCLUDE) == 0
+ && (((*m)->sections[i]->flags & SEC_ALLOC) != 0
+ || (*m)->p_type != PT_LOAD))
+ {
+ (*m)->sections[new_count] = (*m)->sections[i];
+ new_count++;
+ }
+ }
+ (*m)->count = new_count;
- sections = bfd_malloc2 (bfd_count_sections (abfd), sizeof (asection *));
- if (sections == NULL)
- goto error_return;
+ if ((*m)->p_type == PT_LOAD && (*m)->count == 0)
+ *m = (*m)->next;
+ else
+ m = &(*m)->next;
+ }
- i = 0;
- for (s = abfd->sections; s != NULL; s = s->next)
+ bed = get_elf_backend_data (abfd);
+ if (bed->elf_backend_modify_segment_map != NULL)
{
- if ((s->flags & SEC_ALLOC) != 0)
- {
- sections[i] = s;
- ++i;
- }
+ if (!(*bed->elf_backend_modify_segment_map) (abfd, info))
+ return FALSE;
}
- BFD_ASSERT (i <= bfd_count_sections (abfd));
- count = i;
- qsort (sections, (size_t) count, sizeof (asection *), elf_sort_sections);
+ return TRUE;
+}
- /* Build the mapping. */
+/* Set up a mapping from BFD sections to program segments. */
- mfirst = NULL;
- pm = &mfirst;
+bfd_boolean
+_bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
+{
+ unsigned int count;
+ struct elf_segment_map *m;
+ asection **sections = NULL;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- /* If we have a .interp section, then create a PT_PHDR segment for
- the program headers and a PT_INTERP segment for the .interp
- section. */
- s = bfd_get_section_by_name (abfd, ".interp");
- if (s != NULL && (s->flags & SEC_LOAD) != 0)
+ if (elf_tdata (abfd)->segment_map == NULL
+ && bfd_count_sections (abfd) != 0)
{
- amt = sizeof (struct elf_segment_map);
- m = bfd_zalloc (abfd, amt);
- if (m == NULL)
- goto error_return;
- m->next = NULL;
- m->p_type = PT_PHDR;
- /* FIXME: UnixWare and Solaris set PF_X, Irix 5 does not. */
- m->p_flags = PF_R | PF_X;
- m->p_flags_valid = 1;
- m->includes_phdrs = 1;
+ asection *s;
+ unsigned int i;
+ struct elf_segment_map *mfirst;
+ struct elf_segment_map **pm;
+ asection *last_hdr;
+ bfd_vma last_size;
+ unsigned int phdr_index;
+ bfd_vma maxpagesize;
+ asection **hdrpp;
+ bfd_boolean phdr_in_segment = TRUE;
+ bfd_boolean writable;
+ int tls_count = 0;
+ asection *first_tls = NULL;
+ asection *dynsec, *eh_frame_hdr;
+ bfd_size_type amt;
- *pm = m;
- pm = &m->next;
+ /* Select the allocated sections, and sort them. */
- amt = sizeof (struct elf_segment_map);
- m = bfd_zalloc (abfd, amt);
- if (m == NULL)
+ sections = bfd_malloc2 (bfd_count_sections (abfd), sizeof (asection *));
+ if (sections == NULL)
goto error_return;
- m->next = NULL;
- m->p_type = PT_INTERP;
- m->count = 1;
- m->sections[0] = s;
-
- *pm = m;
- pm = &m->next;
- }
-
- /* Look through the sections. We put sections in the same program
- segment when the start of the second section can be placed within
- a few bytes of the end of the first section. */
- last_hdr = NULL;
- last_size = 0;
- phdr_index = 0;
- maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
- writable = FALSE;
- dynsec = bfd_get_section_by_name (abfd, ".dynamic");
- if (dynsec != NULL
- && (dynsec->flags & SEC_LOAD) == 0)
- dynsec = NULL;
-
- /* Deal with -Ttext or something similar such that the first section
- is not adjacent to the program headers. This is an
- approximation, since at this point we don't know exactly how many
- program headers we will need. */
- if (count > 0)
- {
- bfd_size_type phdr_size;
-
- phdr_size = elf_tdata (abfd)->program_header_size;
- if (phdr_size == 0)
- phdr_size = get_elf_backend_data (abfd)->s->sizeof_phdr;
- if ((abfd->flags & D_PAGED) == 0
- || sections[0]->lma < phdr_size
- || sections[0]->lma % maxpagesize < phdr_size % maxpagesize)
- phdr_in_segment = FALSE;
- }
-
- for (i = 0, hdrpp = sections; i < count; i++, hdrpp++)
- {
- asection *hdr;
- bfd_boolean new_segment;
-
- hdr = *hdrpp;
-
- /* See if this section and the last one will fit in the same
- segment. */
- if (last_hdr == NULL)
- {
- /* If we don't have a segment yet, then we don't need a new
- one (we build the last one after this loop). */
- new_segment = FALSE;
- }
- else if (last_hdr->lma - last_hdr->vma != hdr->lma - hdr->vma)
+ i = 0;
+ for (s = abfd->sections; s != NULL; s = s->next)
{
- /* If this section has a different relation between the
- virtual address and the load address, then we need a new
- segment. */
- new_segment = TRUE;
- }
- else if (BFD_ALIGN (last_hdr->lma + last_size, maxpagesize)
- < BFD_ALIGN (hdr->lma, maxpagesize))
- {
- /* If putting this section in this segment would force us to
- skip a page in the segment, then we need a new segment. */
- new_segment = TRUE;
- }
- else if ((last_hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0
- && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0)
- {
- /* We don't want to put a loadable section after a
- nonloadable section in the same segment.
- Consider .tbss sections as loadable for this purpose. */
- new_segment = TRUE;
- }
- else if ((abfd->flags & D_PAGED) == 0)
- {
- /* If the file is not demand paged, which means that we
- don't require the sections to be correctly aligned in the
- file, then there is no other reason for a new segment. */
- new_segment = FALSE;
+ if ((s->flags & SEC_ALLOC) != 0)
+ {
+ sections[i] = s;
+ ++i;
+ }
}
- else if (! writable
- && (hdr->flags & SEC_READONLY) == 0
- && (((last_hdr->lma + last_size - 1)
- & ~(maxpagesize - 1))
- != (hdr->lma & ~(maxpagesize - 1))))
+ BFD_ASSERT (i <= bfd_count_sections (abfd));
+ count = i;
+
+ qsort (sections, (size_t) count, sizeof (asection *), elf_sort_sections);
+
+ /* Build the mapping. */
+
+ mfirst = NULL;
+ pm = &mfirst;
+
+ /* If we have a .interp section, then create a PT_PHDR segment for
+ the program headers and a PT_INTERP segment for the .interp
+ section. */
+ s = bfd_get_section_by_name (abfd, ".interp");
+ if (s != NULL && (s->flags & SEC_LOAD) != 0)
{
- /* We don't want to put a writable section in a read only
- segment, unless they are on the same page in memory
- anyhow. We already know that the last section does not
- bring us past the current section on the page, so the
- only case in which the new section is not on the same
- page as the previous section is when the previous section
- ends precisely on a page boundary. */
- new_segment = TRUE;
+ amt = sizeof (struct elf_segment_map);
+ m = bfd_zalloc (abfd, amt);
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_PHDR;
+ /* FIXME: UnixWare and Solaris set PF_X, Irix 5 does not. */
+ m->p_flags = PF_R | PF_X;
+ m->p_flags_valid = 1;
+ m->includes_phdrs = 1;
+
+ *pm = m;
+ pm = &m->next;
+
+ amt = sizeof (struct elf_segment_map);
+ m = bfd_zalloc (abfd, amt);
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_INTERP;
+ m->count = 1;
+ m->sections[0] = s;
+
+ *pm = m;
+ pm = &m->next;
}
- else
+
+ /* Look through the sections. We put sections in the same program
+ segment when the start of the second section can be placed within
+ a few bytes of the end of the first section. */
+ last_hdr = NULL;
+ last_size = 0;
+ phdr_index = 0;
+ maxpagesize = bed->maxpagesize;
+ writable = FALSE;
+ dynsec = bfd_get_section_by_name (abfd, ".dynamic");
+ if (dynsec != NULL
+ && (dynsec->flags & SEC_LOAD) == 0)
+ dynsec = NULL;
+
+ /* Deal with -Ttext or something similar such that the first section
+ is not adjacent to the program headers. This is an
+ approximation, since at this point we don't know exactly how many
+ program headers we will need. */
+ if (count > 0)
{
- /* Otherwise, we can use the same segment. */
- new_segment = FALSE;
+ bfd_size_type phdr_size = elf_tdata (abfd)->program_header_size;
+
+ if (phdr_size == (bfd_size_type) -1)
+ phdr_size = get_program_header_size (abfd, info);
+ if ((abfd->flags & D_PAGED) == 0
+ || sections[0]->lma < phdr_size
+ || sections[0]->lma % maxpagesize < phdr_size % maxpagesize)
+ phdr_in_segment = FALSE;
}
- if (! new_segment)
+ for (i = 0, hdrpp = sections; i < count; i++, hdrpp++)
{
+ asection *hdr;
+ bfd_boolean new_segment;
+
+ hdr = *hdrpp;
+
+ /* See if this section and the last one will fit in the same
+ segment. */
+
+ if (last_hdr == NULL)
+ {
+ /* If we don't have a segment yet, then we don't need a new
+ one (we build the last one after this loop). */
+ new_segment = FALSE;
+ }
+ else if (last_hdr->lma - last_hdr->vma != hdr->lma - hdr->vma)
+ {
+ /* If this section has a different relation between the
+ virtual address and the load address, then we need a new
+ segment. */
+ new_segment = TRUE;
+ }
+ else if (BFD_ALIGN (last_hdr->lma + last_size, maxpagesize)
+ < BFD_ALIGN (hdr->lma, maxpagesize))
+ {
+ /* If putting this section in this segment would force us to
+ skip a page in the segment, then we need a new segment. */
+ new_segment = TRUE;
+ }
+ else if ((last_hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0
+ && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0)
+ {
+ /* We don't want to put a loadable section after a
+ nonloadable section in the same segment.
+ Consider .tbss sections as loadable for this purpose. */
+ new_segment = TRUE;
+ }
+ else if ((abfd->flags & D_PAGED) == 0)
+ {
+ /* If the file is not demand paged, which means that we
+ don't require the sections to be correctly aligned in the
+ file, then there is no other reason for a new segment. */
+ new_segment = FALSE;
+ }
+ else if (! writable
+ && (hdr->flags & SEC_READONLY) == 0
+ && (((last_hdr->lma + last_size - 1)
+ & ~(maxpagesize - 1))
+ != (hdr->lma & ~(maxpagesize - 1))))
+ {
+ /* We don't want to put a writable section in a read only
+ segment, unless they are on the same page in memory
+ anyhow. We already know that the last section does not
+ bring us past the current section on the page, so the
+ only case in which the new section is not on the same
+ page as the previous section is when the previous section
+ ends precisely on a page boundary. */
+ new_segment = TRUE;
+ }
+ else
+ {
+ /* Otherwise, we can use the same segment. */
+ new_segment = FALSE;
+ }
+
+ if (! new_segment)
+ {
+ if ((hdr->flags & SEC_READONLY) == 0)
+ writable = TRUE;
+ last_hdr = hdr;
+ /* .tbss sections effectively have zero size. */
+ if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
+ != SEC_THREAD_LOCAL)
+ last_size = hdr->size;
+ else
+ last_size = 0;
+ continue;
+ }
+
+ /* We need a new program segment. We must create a new program
+ header holding all the sections from phdr_index until hdr. */
+
+ m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
+ if (m == NULL)
+ goto error_return;
+
+ *pm = m;
+ pm = &m->next;
+
if ((hdr->flags & SEC_READONLY) == 0)
writable = TRUE;
+ else
+ writable = FALSE;
+
last_hdr = hdr;
/* .tbss sections effectively have zero size. */
if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
last_size = hdr->size;
else
last_size = 0;
- continue;
+ phdr_index = i;
+ phdr_in_segment = FALSE;
}
- /* We need a new program segment. We must create a new program
- header holding all the sections from phdr_index until hdr. */
+ /* Create a final PT_LOAD program segment. */
+ if (last_hdr != NULL)
+ {
+ m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
+ if (m == NULL)
+ goto error_return;
- m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
- if (m == NULL)
- goto error_return;
+ *pm = m;
+ pm = &m->next;
+ }
- *pm = m;
- pm = &m->next;
+ /* If there is a .dynamic section, throw in a PT_DYNAMIC segment. */
+ if (dynsec != NULL)
+ {
+ m = _bfd_elf_make_dynamic_segment (abfd, dynsec);
+ if (m == NULL)
+ goto error_return;
+ *pm = m;
+ pm = &m->next;
+ }
- if ((hdr->flags & SEC_READONLY) == 0)
- writable = TRUE;
- else
- writable = FALSE;
+ /* For each loadable .note section, add a PT_NOTE segment. We don't
+ use bfd_get_section_by_name, because if we link together
+ nonloadable .note sections and loadable .note sections, we will
+ generate two .note sections in the output file. FIXME: Using
+ names for section types is bogus anyhow. */
+ for (s = abfd->sections; s != NULL; s = s->next)
+ {
+ if ((s->flags & SEC_LOAD) != 0
+ && strncmp (s->name, ".note", 5) == 0)
+ {
+ amt = sizeof (struct elf_segment_map);
+ m = bfd_zalloc (abfd, amt);
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_NOTE;
+ m->count = 1;
+ m->sections[0] = s;
- last_hdr = hdr;
- /* .tbss sections effectively have zero size. */
- if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
- last_size = hdr->size;
- else
- last_size = 0;
- phdr_index = i;
- phdr_in_segment = FALSE;
- }
+ *pm = m;
+ pm = &m->next;
+ }
+ if (s->flags & SEC_THREAD_LOCAL)
+ {
+ if (! tls_count)
+ first_tls = s;
+ tls_count++;
+ }
+ }
- /* Create a final PT_LOAD program segment. */
- if (last_hdr != NULL)
- {
- m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
- if (m == NULL)
- goto error_return;
+ /* If there are any SHF_TLS output sections, add PT_TLS segment. */
+ if (tls_count > 0)
+ {
+ int i;
- *pm = m;
- pm = &m->next;
- }
+ amt = sizeof (struct elf_segment_map);
+ amt += (tls_count - 1) * sizeof (asection *);
+ m = bfd_zalloc (abfd, amt);
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_TLS;
+ m->count = tls_count;
+ /* Mandated PF_R. */
+ m->p_flags = PF_R;
+ m->p_flags_valid = 1;
+ for (i = 0; i < tls_count; ++i)
+ {
+ BFD_ASSERT (first_tls->flags & SEC_THREAD_LOCAL);
+ m->sections[i] = first_tls;
+ first_tls = first_tls->next;
+ }
- /* If there is a .dynamic section, throw in a PT_DYNAMIC segment. */
- if (dynsec != NULL)
- {
- m = _bfd_elf_make_dynamic_segment (abfd, dynsec);
- if (m == NULL)
- goto error_return;
- *pm = m;
- pm = &m->next;
- }
+ *pm = m;
+ pm = &m->next;
+ }
- /* For each loadable .note section, add a PT_NOTE segment. We don't
- use bfd_get_section_by_name, because if we link together
- nonloadable .note sections and loadable .note sections, we will
- generate two .note sections in the output file. FIXME: Using
- names for section types is bogus anyhow. */
- for (s = abfd->sections; s != NULL; s = s->next)
- {
- if ((s->flags & SEC_LOAD) != 0
- && strncmp (s->name, ".note", 5) == 0)
+ /* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
+ segment. */
+ eh_frame_hdr = elf_tdata (abfd)->eh_frame_hdr;
+ if (eh_frame_hdr != NULL
+ && (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0)
{
amt = sizeof (struct elf_segment_map);
m = bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
- m->p_type = PT_NOTE;
+ m->p_type = PT_GNU_EH_FRAME;
m->count = 1;
- m->sections[0] = s;
+ m->sections[0] = eh_frame_hdr->output_section;
*pm = m;
pm = &m->next;
}
- if (s->flags & SEC_THREAD_LOCAL)
- {
- if (! tls_count)
- first_tls = s;
- tls_count++;
- }
- }
- /* If there are any SHF_TLS output sections, add PT_TLS segment. */
- if (tls_count > 0)
- {
- int i;
-
- amt = sizeof (struct elf_segment_map);
- amt += (tls_count - 1) * sizeof (asection *);
- m = bfd_zalloc (abfd, amt);
- if (m == NULL)
- goto error_return;
- m->next = NULL;
- m->p_type = PT_TLS;
- m->count = tls_count;
- /* Mandated PF_R. */
- m->p_flags = PF_R;
- m->p_flags_valid = 1;
- for (i = 0; i < tls_count; ++i)
+ if (elf_tdata (abfd)->stack_flags)
{
- BFD_ASSERT (first_tls->flags & SEC_THREAD_LOCAL);
- m->sections[i] = first_tls;
- first_tls = first_tls->next;
- }
-
- *pm = m;
- pm = &m->next;
- }
+ 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_STACK;
+ m->p_flags = elf_tdata (abfd)->stack_flags;
+ m->p_flags_valid = 1;
- /* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
- segment. */
- eh_frame_hdr = elf_tdata (abfd)->eh_frame_hdr;
- if (eh_frame_hdr != NULL
- && (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0)
- {
- 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_EH_FRAME;
- m->count = 1;
- m->sections[0] = eh_frame_hdr->output_section;
+ *pm = m;
+ pm = &m->next;
+ }
- *pm = m;
- pm = &m->next;
- }
+ if (dynsec != NULL && elf_tdata (abfd)->relro)
+ {
+ /* We make a PT_GNU_RELRO segment only when there is a
+ PT_DYNAMIC segment. */
+ 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;
- if (elf_tdata (abfd)->stack_flags)
- {
- 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_STACK;
- m->p_flags = elf_tdata (abfd)->stack_flags;
- m->p_flags_valid = 1;
+ *pm = m;
+ pm = &m->next;
+ }
- *pm = m;
- pm = &m->next;
+ free (sections);
+ elf_tdata (abfd)->segment_map = mfirst;
}
- 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;
- }
+ if (!elf_modify_segment_map (abfd, info))
+ return FALSE;
- free (sections);
- sections = NULL;
+ for (count = 0, m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+ ++count;
+ elf_tdata (abfd)->program_header_size = count * bed->s->sizeof_phdr;
- elf_tdata (abfd)->segment_map = mfirst;
return TRUE;
error_return:
return ((vma - off) % maxpagesize);
}
-static void
-print_segment_map (bfd *abfd)
-{
- struct elf_segment_map *m;
- unsigned int i, j;
-
- fprintf (stderr, _(" Section to Segment mapping:\n"));
- fprintf (stderr, _(" Segment Sections...\n"));
-
- for (i= 0, m = elf_tdata (abfd)->segment_map;
- m != NULL;
- i++, m = m->next)
- {
- const char *pt = get_segment_type (m->p_type);
- char buf[32];
-
- if (pt == NULL)
- {
- if (m->p_type >= PT_LOPROC && m->p_type <= PT_HIPROC)
- sprintf (buf, "LOPROC+%7.7x",
- (unsigned int) (m->p_type - PT_LOPROC));
- else if (m->p_type >= PT_LOOS && m->p_type <= PT_HIOS)
- sprintf (buf, "LOOS+%7.7x",
- (unsigned int) (m->p_type - PT_LOOS));
- else
- snprintf (buf, sizeof (buf), "%8.8x",
- (unsigned int) m->p_type);
- pt = buf;
- }
- fprintf (stderr, " %2.2d: %14.14s: ", i, pt);
- for (j = 0; j < m->count; j++)
- fprintf (stderr, "%s ", m->sections [j]->name);
- putc ('\n',stderr);
- }
-}
-
/* Assign file positions to the sections based on the mapping from
sections to segments. This function also sets up some fields in
the file header. */
Elf_Internal_Phdr *p;
file_ptr off, voff;
bfd_size_type maxpagesize;
- unsigned int count;
unsigned int alloc;
unsigned int i;
- if (elf_tdata (abfd)->segment_map == NULL)
- {
- if (! map_sections_to_segments (abfd))
- return FALSE;
- }
- else
- {
- /* The placement algorithm assumes that non allocated sections are
- not in PT_LOAD segments. We ensure this here by removing such
- sections from the segment map. We also remove excluded
- sections. */
- for (m = elf_tdata (abfd)->segment_map;
- m != NULL;
- m = m->next)
- {
- unsigned int new_count;
-
- new_count = 0;
- for (i = 0; i < m->count; i ++)
- {
- if ((m->sections[i]->flags & SEC_EXCLUDE) == 0
- && ((m->sections[i]->flags & SEC_ALLOC) != 0
- || m->p_type != PT_LOAD))
- {
- if (i != new_count)
- m->sections[new_count] = m->sections[i];
-
- new_count ++;
- }
- }
-
- if (new_count != m->count)
- m->count = new_count;
- }
- }
-
- if (bed->elf_backend_modify_segment_map)
- {
- if (! (*bed->elf_backend_modify_segment_map) (abfd, link_info))
- return FALSE;
- }
+ if (link_info == NULL
+ && !elf_modify_segment_map (abfd, link_info))
+ return FALSE;
- count = 0;
+ alloc = 0;
for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
- ++count;
+ ++alloc;
elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
- elf_elfheader (abfd)->e_phnum = count;
-
- if (count == 0)
- {
- elf_tdata (abfd)->next_file_pos = bed->s->sizeof_ehdr;
- return TRUE;
- }
+ elf_elfheader (abfd)->e_phnum = alloc;
- /* If we already counted the number of program segments, make sure
- that we allocated enough space. This happens when SIZEOF_HEADERS
- is used in a linker script. */
- alloc = elf_tdata (abfd)->program_header_size / bed->s->sizeof_phdr;
- if (alloc != 0 && count > alloc)
- {
- ((*_bfd_error_handler)
- (_("%B: Not enough room for program headers (allocated %u, need %u)"),
- abfd, alloc, count));
- print_segment_map (abfd);
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
- }
+ if (elf_tdata (abfd)->program_header_size == (bfd_size_type) -1)
+ elf_tdata (abfd)->program_header_size = alloc * bed->s->sizeof_phdr;
+ else
+ BFD_ASSERT (elf_tdata (abfd)->program_header_size
+ == alloc * bed->s->sizeof_phdr);
if (alloc == 0)
{
- alloc = count;
- elf_tdata (abfd)->program_header_size = alloc * bed->s->sizeof_phdr;
+ elf_tdata (abfd)->next_file_pos = bed->s->sizeof_ehdr;
+ return TRUE;
}
phdrs = bfd_alloc2 (abfd, alloc, sizeof (Elf_Internal_Phdr));
.tbss, we need to look at the next section to decide
whether the segment has any loadable sections. */
i = 0;
- while ((m->sections[i]->flags & SEC_LOAD) == 0)
+ while ((m->sections[i]->flags & SEC_LOAD) == 0
+ && (m->sections[i]->flags & SEC_HAS_CONTENTS) == 0)
{
if ((m->sections[i]->flags & SEC_THREAD_LOCAL) == 0
|| ++i >= m->count)
{
if (p->p_type == PT_LOAD)
{
- sec->filepos = off;
+ sec->filepos = off + voff;
/* FIXME: The SEC_HAS_CONTENTS test here dates back to
1997, and the exact reason for it isn't clear. One
plausible explanation is that it is to work around
p->p_memsz += o->offset + o->size;
}
- if (align > p->p_align
- && (p->p_type != PT_LOAD
- || (abfd->flags & D_PAGED) == 0))
+ if (p->p_type == PT_GNU_RELRO)
+ p->p_align = 1;
+ else if (align > p->p_align
+ && (p->p_type != PT_LOAD
+ || (abfd->flags & D_PAGED) == 0))
p->p_align = align;
}
}
}
- /* Clear out any program headers we allocated but did not use. */
- for (; count < alloc; count++, p++)
- {
- memset (p, 0, sizeof *p);
- p->p_type = PT_NULL;
- }
-
elf_tdata (abfd)->next_file_pos = off;
return TRUE;
}
hdr = *hdrpp;
if (hdr->bfd_section != NULL
- && hdr->bfd_section->filepos != 0)
+ && (hdr->bfd_section->filepos != 0
+ || (hdr->sh_type == SHT_NOBITS
+ && hdr->contents == NULL)))
hdr->sh_offset = hdr->bfd_section->filepos;
else if ((hdr->sh_flags & SHF_ALLOC) != 0)
{
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)
+ && (lp->p_vaddr + lp->p_filesz
+ >= link_info->relro_end))
break;
}
return TRUE;
}
-/* Get the size of the program header.
-
- If this is called by the linker before any of the section VMA's are set, it
- can't calculate the correct value for a strange memory layout. This only
- happens when SIZEOF_HEADERS is used in a linker script. In this case,
- SORTED_HDRS is NULL and we assume the normal scenario of one text and one
- data segment (exclusive of .interp and .dynamic).
-
- ??? User written scripts must either not use SIZEOF_HEADERS, or assume there
- will be two segments. */
-
-static bfd_size_type
-get_program_header_size (bfd *abfd)
-{
- size_t segs;
- asection *s;
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
- /* We can't return a different result each time we're called. */
- if (elf_tdata (abfd)->program_header_size != 0)
- return elf_tdata (abfd)->program_header_size;
-
- if (elf_tdata (abfd)->segment_map != NULL)
- {
- struct elf_segment_map *m;
-
- segs = 0;
- for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
- ++segs;
- elf_tdata (abfd)->program_header_size = segs * bed->s->sizeof_phdr;
- return elf_tdata (abfd)->program_header_size;
- }
-
- /* Assume we will need exactly two PT_LOAD segments: one for text
- and one for data. */
- segs = 2;
-
- s = bfd_get_section_by_name (abfd, ".interp");
- if (s != NULL && (s->flags & SEC_LOAD) != 0)
- {
- /* If we have a loadable interpreter section, we need a
- PT_INTERP segment. In this case, assume we also need a
- PT_PHDR segment, although that may not be true for all
- targets. */
- segs += 2;
- }
-
- if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
- {
- /* We need a PT_DYNAMIC segment. */
- ++segs;
- }
-
- if (elf_tdata (abfd)->eh_frame_hdr)
- {
- /* We need a PT_GNU_EH_FRAME segment. */
- ++segs;
- }
-
- if (elf_tdata (abfd)->stack_flags)
- {
- /* We need a PT_GNU_STACK segment. */
- ++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
- && strncmp (s->name, ".note", 5) == 0)
- {
- /* We need a PT_NOTE segment. */
- ++segs;
- }
- }
-
- for (s = abfd->sections; s != NULL; s = s->next)
- {
- if (s->flags & SEC_THREAD_LOCAL)
- {
- /* We need a PT_TLS segment. */
- ++segs;
- break;
- }
- }
-
- /* Let the backend count up any program headers it might need. */
- if (bed->elf_backend_additional_program_headers)
- {
- int a;
-
- a = (*bed->elf_backend_additional_program_headers) (abfd);
- if (a == -1)
- abort ();
- segs += a;
- }
-
- elf_tdata (abfd)->program_header_size = segs * bed->s->sizeof_phdr;
- return elf_tdata (abfd)->program_header_size;
-}
-
/* Work out the file positions of all the sections. This is called by
_bfd_elf_compute_section_file_positions. All the section sizes and
VMAs must be known before this is called.
if (!assign_file_positions_for_non_load_sections (abfd, link_info))
return FALSE;
+ if (bed->elf_backend_modify_program_headers != NULL)
+ {
+ if (!(*bed->elf_backend_modify_program_headers) (abfd, link_info))
+ return FALSE;
+ }
+
/* Write out the program headers. */
alloc = tdata->program_header_size / bed->s->sizeof_phdr;
if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
return TRUE;
/* Don't copy the output ELF section type from input if the
- output BFD section flags has been set to something different.
+ 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
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 (need_group)
{
if (elf_sec_group (isec) == NULL
}
int
-_bfd_elf_sizeof_headers (bfd *abfd, bfd_boolean reloc)
+_bfd_elf_sizeof_headers (bfd *abfd, struct bfd_link_info *info)
{
- int ret;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ int ret = bed->s->sizeof_ehdr;
+
+ if (!info->relocatable)
+ {
+ bfd_size_type phdr_size = elf_tdata (abfd)->program_header_size;
+
+ if (phdr_size == (bfd_size_type) -1)
+ {
+ struct elf_segment_map *m;
+
+ phdr_size = 0;
+ for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+ phdr_size += bed->s->sizeof_phdr;
+
+ if (phdr_size == 0)
+ phdr_size = get_program_header_size (abfd, info);
+ }
+
+ elf_tdata (abfd)->program_header_size = phdr_size;
+ ret += phdr_size;
+ }
- ret = get_elf_backend_data (abfd)->s->sizeof_ehdr;
- if (! reloc)
- ret += get_program_header_size (abfd);
return ret;
}
}
static bfd_boolean
-elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, pid_t *tid)
+elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid)
{
void *ddata = note->descdata;
char buf[100];
elf_tdata (abfd)->core_lwpid = *tid;
/* Make a ".qnx_core_status/%d" section. */
- sprintf (buf, ".qnx_core_status/%ld", (long) *tid);
+ sprintf (buf, ".qnx_core_status/%ld", *tid);
name = bfd_alloc (abfd, strlen (buf) + 1);
if (name == NULL)
static bfd_boolean
elfcore_grok_nto_regs (bfd *abfd,
Elf_Internal_Note *note,
- pid_t tid,
+ long tid,
char *base)
{
char buf[100];
asection *sect;
/* Make a "(base)/%d" section. */
- sprintf (buf, "%s/%ld", base, (long) tid);
+ sprintf (buf, "%s/%ld", base, tid);
name = bfd_alloc (abfd, strlen (buf) + 1);
if (name == NULL)
/* Every GREG section has a STATUS section before it. Store the
tid from the previous call to pass down to the next gregs
function. */
- static pid_t tid = 1;
+ static long tid = 1;
switch (note->type)
{