/* ELF executable support for BFD.
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
return h & 0xffffffff;
}
+/* Create a tdata field OBJECT_SIZE bytes in length, zeroed out and with
+ the object_id field of an elf_obj_tdata field set to OBJECT_ID. */
bfd_boolean
-bfd_elf_mkobject (bfd *abfd)
+bfd_elf_allocate_object (bfd *abfd,
+ size_t object_size,
+ enum elf_object_id object_id)
{
+ BFD_ASSERT (object_size >= sizeof (struct elf_obj_tdata));
+ abfd->tdata.any = bfd_zalloc (abfd, object_size);
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 FALSE;
+ elf_object_id (abfd) = object_id;
+ elf_program_header_size (abfd) = (bfd_size_type) -1;
return TRUE;
}
+
+bfd_boolean
+bfd_elf_make_generic_object (bfd *abfd)
+{
+ return bfd_elf_allocate_object (abfd, sizeof (struct elf_obj_tdata),
+ GENERIC_ELF_TDATA);
+}
+
bfd_boolean
bfd_elf_mkcorefile (bfd *abfd)
{
/* I think this can be done just like an object file. */
- return bfd_elf_mkobject (abfd);
+ return bfd_elf_make_generic_object (abfd);
}
char *
SYMCOUNT specifies the number of symbols to read, starting from
symbol SYMOFFSET. If any of INTSYM_BUF, EXTSYM_BUF or EXTSHNDX_BUF
are non-NULL, they are used to store the internal symbols, external
- symbols, and symbol section index extensions, respectively. */
+ symbols, and symbol section index extensions, respectively.
+ Returns a pointer to the internal symbol buffer (malloced if necessary)
+ or NULL if there were no symbols or some kind of problem. */
Elf_Internal_Sym *
bfd_elf_get_elf_syms (bfd *ibfd,
bfd_size_type amt;
file_ptr pos;
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
+ abort ();
+
if (symcount == 0)
return intsym_buf;
s = bfd_get_section_by_name (abfd, ".dynamic");
if (s != NULL)
{
- int elfsec;
+ unsigned int elfsec;
unsigned long shlink;
bfd_byte *extdyn, *extdynend;
size_t extdynsize;
goto error_return;
elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
- if (elfsec == -1)
+ if (elfsec == SHN_BAD)
goto error_return;
shlink = elf_elfsections (abfd)[elfsec]->sh_link;
for (; extdyn < extdynend; extdyn += extdynsize)
{
Elf_Internal_Dyn dyn;
- const char *name;
+ const char *name = "";
char ab[20];
bfd_boolean stringp;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
(*swap_dyn_in) (abfd, extdyn, &dyn);
switch (dyn.d_tag)
{
default:
- sprintf (ab, "0x%lx", (unsigned long) dyn.d_tag);
- name = ab;
+ if (bed->elf_backend_get_target_dtag)
+ name = (*bed->elf_backend_get_target_dtag) (dyn.d_tag);
+
+ if (!strcmp (name, ""))
+ {
+ sprintf (ab, "0x%lx", (unsigned long) dyn.d_tag);
+ name = ab;
+ }
break;
case DT_NEEDED: name = "NEEDED"; stringp = TRUE; break;
case DT_GNU_HASH: name = "GNU_HASH"; break;
}
- fprintf (f, " %-11s ", name);
+ fprintf (f, " %-20s ", name);
if (! stringp)
fprintf (f, "0x%lx", (unsigned long) dyn.d_un.d_val);
else
non-bss input sections to bss output sections, or emit data
to a bss output section via a linker script. */
(*_bfd_error_handler)
- (_("section `%A' type changed to PROGBITS"), asect);
+ (_("warning: section `%A' type changed to PROGBITS"), asect);
this_hdr->sh_type = sh_type;
}
return segs * bed->s->sizeof_phdr;
}
+/* Find the segment that contains the output_section of section. */
+
+Elf_Internal_Phdr *
+_bfd_elf_find_segment_containing_section (bfd * abfd, asection * section)
+{
+ struct elf_segment_map *m;
+ Elf_Internal_Phdr *p;
+
+ for (m = elf_tdata (abfd)->segment_map,
+ p = elf_tdata (abfd)->phdr;
+ m != NULL;
+ m = m->next, p++)
+ {
+ int i;
+
+ for (i = m->count - 1; i >= 0; i--)
+ if (m->sections[i] == section)
+ return p;
+ }
+
+ return NULL;
+}
+
/* Create a mapping from a set of sections to a program segment. */
static struct elf_segment_map *
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
+ /* Set the note section type to SHT_NOTE. */
+ else if (p->p_type == PT_NOTE)
+ for (i = 0; i < m->count; i++)
+ elf_section_type (m->sections[i]) = SHT_NOTE;
p->p_offset = 0;
p->p_filesz = 0;
/* Given a section, search the header to find them. */
-int
+unsigned int
_bfd_elf_section_from_bfd_section (bfd *abfd, struct bfd_section *asect)
{
const struct elf_backend_data *bed;
- int index;
+ unsigned int index;
if (elf_section_data (asect) != NULL
&& elf_section_data (asect)->this_idx != 0)
else if (bfd_is_und_section (asect))
index = SHN_UNDEF;
else
- index = -1;
+ index = SHN_BAD;
bed = get_elf_backend_data (abfd);
if (bed->elf_backend_section_from_bfd_section)
return retval;
}
- if (index == -1)
+ if (index == SHN_BAD)
bfd_set_error (bfd_error_nonrepresentable_section);
return index;
&& (section->lma + SECTION_SIZE (section, segment) \
<= SEGMENT_END (segment, base)))
- /* Special case: corefile "NOTE" section containing regs, prpsinfo etc. */
-#define IS_COREFILE_NOTE(p, s) \
+ /* Handle PT_NOTE segment. */
+#define IS_NOTE(p, s) \
(p->p_type == PT_NOTE \
- && bfd_get_format (ibfd) == bfd_core \
- && s->vma == 0 && s->lma == 0 \
+ && elf_section_type (s) == SHT_NOTE \
&& (bfd_vma) s->filepos >= p->p_offset \
&& ((bfd_vma) s->filepos + s->size \
<= p->p_offset + p->p_filesz))
+ /* Special case: corefile "NOTE" section containing regs, prpsinfo
+ etc. */
+#define IS_COREFILE_NOTE(p, s) \
+ (IS_NOTE (p, s) \
+ && bfd_get_format (ibfd) == bfd_core \
+ && s->vma == 0 \
+ && s->lma == 0)
+
/* The complicated case when p_vaddr is 0 is to handle the Solaris
linker, which generates a PT_INTERP section with p_vaddr and
p_memsz set to 0. */
A section will be included if:
1. It is within the address space of the segment -- we use the LMA
if that is set for the segment and the VMA otherwise,
- 2. It is an allocated segment,
+ 2. It is an allocated section or a NOTE section in a PT_NOTE
+ segment.
3. There is an output section associated with it,
4. The section has not already been allocated to a previous segment.
5. PT_GNU_STACK segments do not include any sections.
? 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)) \
+ || IS_NOTE (segment, section)) \
&& segment->p_type != PT_GNU_STACK \
&& (segment->p_type != PT_TLS \
|| (section->flags & SEC_THREAD_LOCAL)) \
first_matching_lma = TRUE;
first_suggested_lma = TRUE;
- for (j = 0, section = ibfd->sections;
+ for (section = ibfd->sections;
section != NULL;
section = section->next)
+ if (section == first_section)
+ break;
+
+ for (j = 0; section != NULL; section = section->next)
{
if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed))
{
suggested_lma = output_section->lma;
first_suggested_lma = FALSE;
}
+
+ if (j == section_count)
+ break;
}
}
*pointer_to_map = map;
pointer_to_map = &map->next;
- if (matching_lma != map->p_paddr
+ if (!bed->want_p_paddr_set_to_zero
+ && matching_lma != map->p_paddr
&& !map->includes_filehdr && !map->includes_phdrs)
/* There is some padding before the first section in the
segment. So, we must account for that in the output
#undef SECTION_SIZE
#undef IS_CONTAINED_BY_VMA
#undef IS_CONTAINED_BY_LMA
+#undef IS_NOTE
#undef IS_COREFILE_NOTE
#undef IS_SOLARIS_PT_INTERP
#undef IS_SECTION_IN_INPUT_SEGMENT
asection *section, *osec;
unsigned int i, num_segments;
Elf_Internal_Shdr *this_hdr;
+ const struct elf_backend_data *bed;
+
+ bed = get_elf_backend_data (ibfd);
+
+ /* Regenerate the segment map if p_paddr is set to 0. */
+ if (bed->want_p_paddr_set_to_zero)
+ goto rewrite;
/* Initialize the segment mark field. */
for (section = obfd->sections; section != NULL;
osym = elf_symbol_from (obfd, osymarg);
if (isym != NULL
+ && isym->internal_elf_sym.st_shndx != 0
&& osym != NULL
&& bfd_is_abs_section (isym->symbol.section))
{
else
{
asection *sec = syms[idx]->section;
- int shndx;
+ unsigned int shndx;
if (sec->output_section)
{
{
shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
- if (shndx == -1)
+ if (shndx == SHN_BAD)
{
asection *sec2;
}
shndx = _bfd_elf_section_from_bfd_section (abfd, sec2);
- BFD_ASSERT (shndx != -1);
+ BFD_ASSERT (shndx != SHN_BAD);
}
}
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
}
else if (bfd_is_com_section (syms[idx]->section))
- sym.st_info = ELF_ST_INFO (STB_GLOBAL,
+ {
#ifdef USE_STT_COMMON
- type == STT_OBJECT ? STT_COMMON :
+ if (type == STT_OBJECT)
+ sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_COMMON);
+ else
+#else
+ sym.st_info = ELF_ST_INFO (STB_GLOBAL, type);
#endif
- type);
+ }
else if (bfd_is_und_section (syms[idx]->section))
sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK)
? STB_WEAK