summaryrefslogtreecommitdiffstats
path: root/contrib/binutils/bfd/elf.c
diff options
context:
space:
mode:
authorjdp <jdp@FreeBSD.org>1998-09-06 23:00:35 +0000
committerjdp <jdp@FreeBSD.org>1998-09-06 23:00:35 +0000
commit5759d4576755e035821ae7e46f25f80e4e64b127 (patch)
tree8c03749b0394a8137a721b6cbdcdfd12cc792d76 /contrib/binutils/bfd/elf.c
parent088484c9efa7b42bc7fcc180fd78fed96df31c63 (diff)
downloadFreeBSD-src-5759d4576755e035821ae7e46f25f80e4e64b127.zip
FreeBSD-src-5759d4576755e035821ae7e46f25f80e4e64b127.tar.gz
Resolve conflicts from import of binutils-2.9.1.
Submitted by: Doug Rabson <dfr>
Diffstat (limited to 'contrib/binutils/bfd/elf.c')
-rw-r--r--contrib/binutils/bfd/elf.c230
1 files changed, 197 insertions, 33 deletions
diff --git a/contrib/binutils/bfd/elf.c b/contrib/binutils/bfd/elf.c
index ee60483..6f43e9e 100644
--- a/contrib/binutils/bfd/elf.c
+++ b/contrib/binutils/bfd/elf.c
@@ -1,5 +1,5 @@
/* ELF executable support for BFD.
- Copyright 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -305,6 +305,18 @@ bfd_elf_string_from_elf_section (abfd, shindex, strindex)
&& bfd_elf_get_str_section (abfd, shindex) == NULL)
return NULL;
+ if (strindex >= hdr->sh_size)
+ {
+ (*_bfd_error_handler)
+ ("%s: invalid string offset %u >= %lu for section `%s'",
+ bfd_get_filename (abfd), strindex, (unsigned long) hdr->sh_size,
+ ((shindex == elf_elfheader(abfd)->e_shstrndx
+ && strindex == hdr->sh_name)
+ ? ".shstrtab"
+ : elf_string_from_elf_strtab (abfd, hdr->sh_name)));
+ return "";
+ }
+
return ((char *) hdr->contents) + strindex;
}
@@ -389,7 +401,7 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
&& phdr->p_vaddr <= hdr->sh_addr
&& phdr->p_vaddr + phdr->p_memsz >= hdr->sh_addr + hdr->sh_size
&& ((flags & SEC_LOAD) == 0
- || (phdr->p_offset <= hdr->sh_offset
+ || (phdr->p_offset <= (bfd_vma) hdr->sh_offset
&& (phdr->p_offset + phdr->p_filesz
>= hdr->sh_offset + hdr->sh_size))))
{
@@ -929,6 +941,91 @@ bfd_elf_get_dt_soname (abfd)
return elf_dt_name (abfd);
return NULL;
}
+
+/* Get the list of DT_NEEDED entries from a BFD. This is a hook for
+ the ELF linker emulation code. */
+
+boolean
+bfd_elf_get_bfd_needed_list (abfd, pneeded)
+ bfd *abfd;
+ struct bfd_link_needed_list **pneeded;
+{
+ asection *s;
+ bfd_byte *dynbuf = NULL;
+ int elfsec;
+ unsigned long link;
+ bfd_byte *extdyn, *extdynend;
+ size_t extdynsize;
+ void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *));
+
+ *pneeded = NULL;
+
+ if (bfd_get_flavour (abfd) != bfd_target_elf_flavour
+ || bfd_get_format (abfd) != bfd_object)
+ return true;
+
+ s = bfd_get_section_by_name (abfd, ".dynamic");
+ if (s == NULL || s->_raw_size == 0)
+ return true;
+
+ dynbuf = (bfd_byte *) bfd_malloc (s->_raw_size);
+ if (dynbuf == NULL)
+ goto error_return;
+
+ if (! bfd_get_section_contents (abfd, s, (PTR) dynbuf, (file_ptr) 0,
+ s->_raw_size))
+ goto error_return;
+
+ elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
+ if (elfsec == -1)
+ goto error_return;
+
+ link = elf_elfsections (abfd)[elfsec]->sh_link;
+
+ extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn;
+ swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
+
+ extdyn = dynbuf;
+ extdynend = extdyn + s->_raw_size;
+ for (; extdyn < extdynend; extdyn += extdynsize)
+ {
+ Elf_Internal_Dyn dyn;
+
+ (*swap_dyn_in) (abfd, (PTR) extdyn, &dyn);
+
+ if (dyn.d_tag == DT_NULL)
+ break;
+
+ if (dyn.d_tag == DT_NEEDED)
+ {
+ const char *string;
+ struct bfd_link_needed_list *l;
+
+ string = bfd_elf_string_from_elf_section (abfd, link,
+ dyn.d_un.d_val);
+ if (string == NULL)
+ goto error_return;
+
+ l = (struct bfd_link_needed_list *) bfd_alloc (abfd, sizeof *l);
+ if (l == NULL)
+ goto error_return;
+
+ l->by = abfd;
+ l->name = string;
+ l->next = *pneeded;
+ *pneeded = l;
+ }
+ }
+
+ free (dynbuf);
+
+ return true;
+
+ error_return:
+ if (dynbuf != NULL)
+ free (dynbuf);
+ return false;
+}
/* Allocate an ELF string table--force the first byte to be zero. */
@@ -2106,19 +2203,12 @@ map_sections_to_segments (abfd)
new_segment = true;
}
else if (BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
- < hdr->lma)
+ < 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 ((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 ((last_hdr->flags & SEC_LOAD) == 0
&& (hdr->flags & SEC_LOAD) != 0)
{
@@ -2126,6 +2216,13 @@ map_sections_to_segments (abfd)
nonloadable section in the same segment. */
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
&& (BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
@@ -2264,10 +2361,12 @@ elf_sort_sections (arg1, arg2)
#define TOEND(x) (((x)->flags & SEC_LOAD) == 0)
if (TOEND (sec1))
- if (TOEND (sec2))
- return sec1->target_index - sec2->target_index;
- else
- return 1;
+ {
+ if (TOEND (sec2))
+ return sec1->target_index - sec2->target_index;
+ else
+ return 1;
+ }
if (TOEND (sec2))
return -1;
@@ -2419,6 +2518,15 @@ assign_file_positions_for_segments (abfd)
if (m->count > 0)
{
BFD_ASSERT (p->p_type == PT_LOAD);
+
+ if (p->p_vaddr < (bfd_vma) off)
+ {
+ _bfd_error_handler ("%s: Not enough room for program headers, try linking with -N",
+ bfd_get_filename (abfd));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
p->p_vaddr -= off;
if (! m->p_paddr_valid)
p->p_paddr -= off;
@@ -2491,29 +2599,42 @@ assign_file_positions_for_segments (abfd)
{
bfd_vma adjust;
- /* The section VMA must equal the file position modulo
- the page size. */
- if ((flags & SEC_ALLOC) != 0)
+ if ((flags & SEC_LOAD) != 0)
+ adjust = sec->lma - (p->p_paddr + p->p_memsz);
+ else if ((flags & SEC_ALLOC) != 0)
{
+ /* The section VMA must equal the file position
+ modulo the page size. FIXME: I'm not sure if
+ this adjustment is really necessary. We used to
+ not have the SEC_LOAD case just above, and then
+ this was necessary, but now I'm not sure. */
if ((abfd->flags & D_PAGED) != 0)
adjust = (sec->vma - voff) % bed->maxpagesize;
else
adjust = (sec->vma - voff) % align;
- if (adjust != 0)
- {
- if (i == 0)
- abort ();
- p->p_memsz += adjust;
- off += adjust;
- voff += adjust;
- if ((flags & SEC_LOAD) != 0)
- p->p_filesz += adjust;
- }
+ }
+ else
+ adjust = 0;
+
+ if (adjust != 0)
+ {
+ if (i == 0)
+ abort ();
+ p->p_memsz += adjust;
+ off += adjust;
+ voff += adjust;
+ if ((flags & SEC_LOAD) != 0)
+ p->p_filesz += adjust;
}
sec->filepos = off;
- if ((flags & SEC_LOAD) != 0)
+ /* We check SEC_HAS_CONTENTS here because if NOLOAD is
+ used in a linker script we may have a section with
+ SEC_LOAD clear but which is supposed to have
+ contents. */
+ if ((flags & SEC_LOAD) != 0
+ || (flags & SEC_HAS_CONTENTS) != 0)
off += sec->_raw_size;
if ((flags & SEC_ALLOC) != 0)
voff += sec->_raw_size;
@@ -2853,6 +2974,16 @@ prep_headers (abfd)
case bfd_arch_d10v:
i_ehdrp->e_machine = EM_CYGNUS_D10V;
break;
+ case bfd_arch_v850:
+ switch (bfd_get_mach (abfd))
+ {
+ default:
+ case 0: i_ehdrp->e_machine = EM_CYGNUS_V850; break;
+ }
+ break;
+ case bfd_arch_arc:
+ i_ehdrp->e_machine = EM_CYGNUS_ARC;
+ break;
case bfd_arch_m32r:
i_ehdrp->e_machine = EM_CYGNUS_M32R;
break;
@@ -3107,6 +3238,7 @@ copy_private_bfd_data (ibfd, obfd)
Elf_Internal_Ehdr *iehdr;
struct elf_segment_map *mfirst;
struct elf_segment_map **pm;
+ struct elf_segment_map *m;
Elf_Internal_Phdr *p;
unsigned int i, c;
@@ -3127,7 +3259,6 @@ copy_private_bfd_data (ibfd, obfd)
{
unsigned int csecs;
asection *s;
- struct elf_segment_map *m;
unsigned int isec;
csecs = 0;
@@ -3197,6 +3328,19 @@ copy_private_bfd_data (ibfd, obfd)
pm = &m->next;
}
+ /* The Solaris linker creates program headers in which all the
+ p_paddr fields are zero. When we try to objcopy or strip such a
+ file, we get confused. Check for this case, and if we find it
+ reset the p_paddr_valid fields. */
+ for (m = mfirst; m != NULL; m = m->next)
+ if (m->p_paddr != 0)
+ break;
+ if (m == NULL)
+ {
+ for (m = mfirst; m != NULL; m = m->next)
+ m->p_paddr_valid = 0;
+ }
+
elf_tdata (obfd)->segment_map = mfirst;
return true;
@@ -3228,10 +3372,12 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
{
asection *s;
- /* Only set up the segments when all the sections have been set
- up. */
- for (s = ibfd->sections; s != NULL; s = s->next)
- if (s->output_section == NULL)
+ /* 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)
{
@@ -3972,6 +4118,11 @@ _bfd_elf_find_nearest_line (abfd,
bfd_vma low_func;
asymbol **p;
+ if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
+ filename_ptr, functionname_ptr,
+ line_ptr))
+ return true;
+
if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
&found, filename_ptr,
functionname_ptr, line_ptr,
@@ -4179,3 +4330,16 @@ _bfd_elf_validate_reloc (abfd, areloc)
bfd_set_error (bfd_error_bad_value);
return false;
}
+
+boolean
+_bfd_elf_close_and_cleanup (abfd)
+ bfd *abfd;
+{
+ if (bfd_get_format (abfd) == bfd_object)
+ {
+ if (elf_shstrtab (abfd) != NULL)
+ _bfd_stringtab_free (elf_shstrtab (abfd));
+ }
+
+ return _bfd_generic_close_and_cleanup (abfd);
+}
OpenPOWER on IntegriCloud