#include "libiberty.h"
#include "safe-ctype.h"
+#ifdef CORE_HEADER
+#include CORE_HEADER
+#endif
+
static int elf_sort_sections (const void *, const void *);
static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *);
static bfd_boolean prep_headers (bfd *);
bfd_boolean
-bfd_elf_make_generic_object (bfd *abfd)
+bfd_elf_make_object (bfd *abfd)
{
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
return bfd_elf_allocate_object (abfd, sizeof (struct elf_obj_tdata),
- GENERIC_ELF_DATA);
+ bed->target_id);
}
bfd_boolean
bfd_elf_mkcorefile (bfd *abfd)
{
/* I think this can be done just like an object file. */
- return bfd_elf_make_generic_object (abfd);
+ return abfd->xvec->_bfd_set_format[(int) bfd_object] (abfd);
}
static char *
return FALSE;
if ((hdr->sh_flags & SHF_TLS) != 0)
flags |= SEC_THREAD_LOCAL;
+ if ((hdr->sh_flags & SHF_EXCLUDE) != 0)
+ flags |= SEC_EXCLUDE;
if ((flags & SEC_ALLOC) == 0)
{
for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
{
if (phdr->p_type == PT_LOAD
- && ELF_IS_SECTION_IN_SEGMENT (hdr, phdr))
+ && ELF_SECTION_IN_SEGMENT (hdr, phdr))
{
if ((flags & SEC_LOAD) == 0)
newsect->lma = (phdr->p_paddr
}
}
}
+ if ((asect->flags & (SEC_GROUP | SEC_EXCLUDE)) == SEC_EXCLUDE)
+ this_hdr->sh_flags |= SHF_EXCLUDE;
/* Check for processor-specific section types. */
sh_type = this_hdr->sh_type;
asection *first_tls = NULL;
asection *dynsec, *eh_frame_hdr;
bfd_size_type amt;
+ bfd_vma addr_mask, wrap_to = 0;
/* Select the allocated sections, and sort them. */
if (sections == NULL)
goto error_return;
+ /* Calculate top address, avoiding undefined behaviour of shift
+ left operator when shift count is equal to size of type
+ being shifted. */
+ addr_mask = ((bfd_vma) 1 << (bfd_arch_bits_per_address (abfd) - 1)) - 1;
+ addr_mask = (addr_mask << 1) + 1;
+
i = 0;
for (s = abfd->sections; s != NULL; s = s->next)
{
{
sections[i] = s;
++i;
+ /* A wrapping section potentially clashes with header. */
+ if (((s->lma + s->size) & addr_mask) < (s->lma & addr_mask))
+ wrap_to = (s->lma + s->size) & addr_mask;
}
}
BFD_ASSERT (i <= bfd_count_sections (abfd));
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)
+ || (sections[0]->lma & addr_mask) < phdr_size
+ || ((sections[0]->lma & addr_mask) % maxpagesize
+ < phdr_size % maxpagesize)
+ || (sections[0]->lma & addr_mask & -maxpagesize) < wrap_to)
phdr_in_segment = FALSE;
}
segment. */
new_segment = TRUE;
}
+ else if (hdr->lma < last_hdr->lma + last_size
+ || last_hdr->lma + last_size < last_hdr->lma)
+ {
+ /* If this section has a load address that makes it overlap
+ the previous section, then we need a new segment. */
+ new_segment = TRUE;
+ }
/* In the next test we have to be careful when last_hdr->lma is close
to the end of the address space. If the aligned address wraps
around to the start of the address space, then there are no more
}
else if (! writable
&& (hdr->flags & SEC_READONLY) == 0
- && (((last_hdr->lma + last_size - 1)
- & ~(maxpagesize - 1))
- != (hdr->lma & ~(maxpagesize - 1))))
+ && (((last_hdr->lma + last_size - 1) & -maxpagesize)
+ != (hdr->lma & -maxpagesize)))
{
/* We don't want to put a writable section in a read only
segment, unless they are on the same page in memory
if (s2->next->alignment_power == 2
&& (s2->next->flags & SEC_LOAD) != 0
&& CONST_STRNEQ (s2->next->name, ".note")
- && align_power (s2->vma + s2->size, 2)
- == s2->next->vma)
+ && align_power (s2->lma + s2->size, 2)
+ == s2->next->lma)
count++;
else
break;
break;
}
- off_adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align);
+ off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align);
off += off_adjust;
if (no_contents)
{
&& ((this_hdr->sh_flags & SHF_TLS) == 0
|| p->p_type == PT_TLS))))
{
- bfd_signed_vma adjust = sec->vma - (p->p_vaddr + p->p_memsz);
-
- if (sec->vma < p->p_vaddr + p->p_memsz)
+ bfd_vma p_start = p->p_paddr;
+ bfd_vma p_end = p_start + p->p_memsz;
+ bfd_vma s_start = sec->lma;
+ bfd_vma adjust = s_start - p_end;
+
+ if (adjust != 0
+ && (s_start < p_end
+ || p_end < p_start))
{
(*_bfd_error_handler)
- (_("%B: section %A vma 0x%lx overlaps previous sections"),
- abfd, sec, (unsigned long) sec->vma);
+ (_("%B: section %A lma %#lx adjusted to %#lx"), abfd, sec,
+ (unsigned long) s_start, (unsigned long) p_end);
adjust = 0;
+ sec->lma = p_end;
}
p->p_memsz += adjust;
- if (p->p_paddr + p->p_memsz != sec->lma)
- {
- /* This behavior is a compromise--ld has long
- silently changed the lma of sections when
- lma - vma is not equal for every section in a
- pheader--but only in the internal elf structures.
- Silently changing the lma is probably a bug, but
- changing it would have subtle and unknown
- consequences for existing scripts.
-
- Instead modify the bfd data structure to reflect
- what happened. This at least fixes the values
- for the lma in the mapfile. */
- sec->lma = p->p_paddr + p->p_memsz;
- }
-
if (this_hdr->sh_type != SHT_NOBITS)
{
if (p->p_filesz + adjust < p->p_memsz)
/* Check that all sections are in a PT_LOAD segment.
Don't check funky gdb generated core files. */
if (p->p_type == PT_LOAD && bfd_get_format (abfd) != bfd_core)
- for (i = 0, secpp = m->sections; i < m->count; i++, secpp++)
- {
- Elf_Internal_Shdr *this_hdr;
- asection *sec;
-
- sec = *secpp;
- this_hdr = &(elf_section_data(sec)->this_hdr);
- if (this_hdr->sh_size != 0
- && !ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, p))
+ {
+ bfd_boolean check_vma = TRUE;
+
+ for (i = 1; i < m->count; i++)
+ if (m->sections[i]->vma == m->sections[i - 1]->vma
+ && ELF_SECTION_SIZE (&(elf_section_data (m->sections[i])
+ ->this_hdr), p) != 0
+ && ELF_SECTION_SIZE (&(elf_section_data (m->sections[i - 1])
+ ->this_hdr), p) != 0)
{
- (*_bfd_error_handler)
- (_("%B: section `%A' can't be allocated in segment %d"),
- abfd, sec, j);
- print_segment_map (m);
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ /* Looks like we have overlays packed into the segment. */
+ check_vma = FALSE;
+ break;
}
- }
+
+ for (i = 0; i < m->count; i++)
+ {
+ Elf_Internal_Shdr *this_hdr;
+ asection *sec;
+
+ sec = m->sections[i];
+ this_hdr = &(elf_section_data(sec)->this_hdr);
+ if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0))
+ {
+ (*_bfd_error_handler)
+ (_("%B: section `%A' can't be allocated in segment %d"),
+ abfd, sec, j);
+ print_segment_map (m);
+ }
+ }
+ }
}
elf_tdata (abfd)->next_file_pos = off;
BFD_ASSERT (hdr->sh_offset == hdr->bfd_section->filepos);
else if ((hdr->sh_flags & SHF_ALLOC) != 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)));
+ (*_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,
bfd_size_type amt;
Elf_Internal_Shdr *this_hdr;
asection *first_section = NULL;
- asection *lowest_section = NULL;
+ asection *lowest_section;
/* Compute how many sections are in this segment. */
for (section = ibfd->sections, section_count = 0;
section = section->next)
{
this_hdr = &(elf_section_data(section)->this_hdr);
- if (ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, segment))
+ if (ELF_SECTION_IN_SEGMENT (this_hdr, segment))
{
- if (!first_section)
- first_section = lowest_section = section;
- if (section->lma < lowest_section->lma)
- lowest_section = section;
+ if (first_section == NULL)
+ first_section = section;
section_count++;
}
}
phdr_included = TRUE;
}
- if (map->includes_filehdr && first_section)
- /* We need to keep the space used by the headers fixed. */
- map->header_size = first_section->vma - segment->p_vaddr;
-
- if (!map->includes_phdrs
- && !map->includes_filehdr
- && map->p_paddr_valid)
- /* There is some other padding before the first section. */
- map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0)
- - segment->p_paddr);
-
+ lowest_section = first_section;
if (section_count != 0)
{
unsigned int isec = 0;
section = section->next)
{
this_hdr = &(elf_section_data(section)->this_hdr);
- if (ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, segment))
+ if (ELF_SECTION_IN_SEGMENT (this_hdr, segment))
{
map->sections[isec++] = section->output_section;
+ if (section->lma < lowest_section->lma)
+ lowest_section = section;
+ if ((section->flags & SEC_ALLOC) != 0)
+ {
+ bfd_vma seg_off;
+
+ /* Section lmas are set up from PT_LOAD header
+ p_paddr in _bfd_elf_make_section_from_shdr.
+ If this header has a p_paddr that disagrees
+ with the section lma, flag the p_paddr as
+ invalid. */
+ if ((section->flags & SEC_LOAD) != 0)
+ seg_off = this_hdr->sh_offset - segment->p_offset;
+ else
+ seg_off = this_hdr->sh_addr - segment->p_vaddr;
+ if (section->lma - segment->p_paddr != seg_off)
+ map->p_paddr_valid = FALSE;
+ }
if (isec == section_count)
break;
}
}
}
+ if (map->includes_filehdr && lowest_section != NULL)
+ /* We need to keep the space used by the headers fixed. */
+ map->header_size = lowest_section->vma - segment->p_vaddr;
+
+ if (!map->includes_phdrs
+ && !map->includes_filehdr
+ && map->p_paddr_valid)
+ /* There is some other padding before the first section. */
+ map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0)
+ - segment->p_paddr);
+
map->count = section_count;
*pointer_to_map = map;
pointer_to_map = &map->next;
/* Check if this section is covered by the segment. */
this_hdr = &(elf_section_data(section)->this_hdr);
- if (ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, segment))
+ if (ELF_SECTION_IN_SEGMENT (this_hdr, segment))
{
/* FIXME: Check if its output section is changed or
removed. What else do we need to check? */
# include <sys/procfs.h>
#endif
-/* FIXME: this is kinda wrong, but it's what gdb wants. */
+/* Return a PID that identifies a "thread" for threaded cores, or the
+ PID of the main process for non-threaded cores. */
static int
elfcore_make_pid (bfd *abfd)
{
- return ((elf_tdata (abfd)->core_lwpid << 16)
- + (elf_tdata (abfd)->core_pid));
+ int pid;
+
+ pid = elf_tdata (abfd)->core_lwpid;
+ if (pid == 0)
+ pid = elf_tdata (abfd)->core_pid;
+
+ return pid;
}
/* If there isn't a section called NAME, make one, using
has already been set by another thread. */
if (elf_tdata (abfd)->core_signal == 0)
elf_tdata (abfd)->core_signal = prstat.pr_cursig;
- elf_tdata (abfd)->core_pid = prstat.pr_pid;
+ if (elf_tdata (abfd)->core_pid == 0)
+ elf_tdata (abfd)->core_pid = prstat.pr_pid;
/* pr_who exists on:
solaris 2.5+
*/
#if defined (HAVE_PRSTATUS_T_PR_WHO)
elf_tdata (abfd)->core_lwpid = prstat.pr_who;
+#else
+ elf_tdata (abfd)->core_lwpid = prstat.pr_pid;
#endif
}
#if defined (HAVE_PRSTATUS32_T)
has already been set by another thread. */
if (elf_tdata (abfd)->core_signal == 0)
elf_tdata (abfd)->core_signal = prstat.pr_cursig;
- elf_tdata (abfd)->core_pid = prstat.pr_pid;
+ if (elf_tdata (abfd)->core_pid == 0)
+ elf_tdata (abfd)->core_pid = prstat.pr_pid;
/* pr_who exists on:
solaris 2.5+
*/
#if defined (HAVE_PRSTATUS32_T_PR_WHO)
elf_tdata (abfd)->core_lwpid = prstat.pr_who;
+#else
+ elf_tdata (abfd)->core_lwpid = prstat.pr_pid;
#endif
}
#endif /* HAVE_PRSTATUS32_T */