/* ELF executable support for BFD.
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
phdr = elf_tdata (abfd)->phdr;
for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
{
- if (phdr->p_type == PT_LOAD
+ if (((phdr->p_type == PT_LOAD
+ && (hdr->sh_flags & SHF_TLS) == 0)
+ || phdr->p_type == PT_TLS)
&& ELF_SECTION_IN_SEGMENT (hdr, phdr))
{
if ((flags & SEC_LOAD) == 0)
if (hdr->sh_entsize != bed->s->sizeof_sym)
return FALSE;
if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
- return FALSE;
+ {
+ if (hdr->sh_size != 0)
+ return FALSE;
+ /* Some assemblers erroneously set sh_info to one with a
+ zero sh_size. ld sees this as a global symbol count
+ of (unsigned) -1. Fix it here. */
+ hdr->sh_info = 0;
+ return TRUE;
+ }
BFD_ASSERT (elf_onesymtab (abfd) == 0);
elf_onesymtab (abfd) = shindex;
elf_tdata (abfd)->symtab_hdr = *hdr;
if (hdr->sh_entsize != bed->s->sizeof_sym)
return FALSE;
+ if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
+ {
+ if (hdr->sh_size != 0)
+ return FALSE;
+ /* Some linkers erroneously set sh_info to one with a
+ zero sh_size. ld sees this as a global symbol count
+ of (unsigned) -1. Fix it here. */
+ hdr->sh_info = 0;
+ return TRUE;
+ }
BFD_ASSERT (elf_dynsymtab (abfd) == 0);
elf_dynsymtab (abfd) = shindex;
elf_tdata (abfd)->dynsymtab_hdr = *hdr;
{ NULL, 0, 0, 0, 0 }
};
-static const struct bfd_elf_special_section *special_sections[] =
+static const struct bfd_elf_special_section * const special_sections[] =
{
special_sections_b, /* 'b' */
special_sections_c, /* 'c' */
rel_hdr = bfd_zalloc (abfd, amt);
reldata->hdr = rel_hdr;
- amt = sizeof ".rela" + strlen (asect->name);
+ amt = sizeof ".rela" + strlen (asect->name);
name = (char *) bfd_alloc (abfd, amt);
if (name == NULL)
return FALSE;
if (link_info != NULL)
{
/* Check discarded linkonce section. */
- if (elf_discarded_section (s))
+ if (discarded_section (s))
{
asection *kept;
(*_bfd_error_handler)
return TRUE;
}
-/* Map symbol from it's internal number to the external number, moving
- all local symbols to be at the head of the list. */
-
static bfd_boolean
sym_is_global (bfd *abfd, asymbol *sym)
{
}
/* Don't output section symbols for sections that are not going to be
- output. */
+ output, or that are duplicates. */
static bfd_boolean
ignore_section_sym (bfd *abfd, asymbol *sym)
return ((sym->flags & BSF_SECTION_SYM) != 0
&& !(sym->section->owner == abfd
|| (sym->section->output_section->owner == abfd
- && sym->section->output_offset == 0)));
+ && sym->section->output_offset == 0)
+ || bfd_is_abs_section (sym->section)));
}
+/* Map symbol from it's internal number to the external number, moving
+ all local symbols to be at the head of the list. */
+
static bfd_boolean
elf_map_symbols (bfd *abfd)
{
if ((sym->flags & BSF_SECTION_SYM) != 0
&& sym->value == 0
- && !ignore_section_sym (abfd, sym))
+ && !ignore_section_sym (abfd, sym)
+ && !bfd_is_abs_section (sym->section))
{
asection *sec = sym->section;
/* Classify all of the symbols. */
for (idx = 0; idx < symcount; idx++)
{
- if (ignore_section_sym (abfd, syms[idx]))
- continue;
- if (!sym_is_global (abfd, syms[idx]))
- num_locals++;
- else
+ if (sym_is_global (abfd, syms[idx]))
num_globals++;
+ else if (!ignore_section_sym (abfd, syms[idx]))
+ num_locals++;
}
/* We will be adding a section symbol for each normal BFD section. Most
asymbol *sym = syms[idx];
unsigned int i;
- if (ignore_section_sym (abfd, sym))
- continue;
- if (!sym_is_global (abfd, sym))
+ if (sym_is_global (abfd, sym))
+ i = num_locals + num_globals2++;
+ else if (!ignore_section_sym (abfd, sym))
i = num_locals2++;
else
- i = num_locals + num_globals2++;
+ continue;
new_syms[i] = sym;
sym->udata.i = i + 1;
}
bfd_boolean no_user_phdrs;
no_user_phdrs = elf_tdata (abfd)->segment_map == NULL;
+
+ if (info != NULL)
+ info->user_phdrs = !no_user_phdrs;
+
if (no_user_phdrs && bfd_count_sections (abfd) != 0)
{
asection *s;
phdr_in_segment = FALSE;
}
- /* Create a final PT_LOAD program segment. */
- if (last_hdr != NULL)
+ /* Create a final PT_LOAD program segment, but not if it's just
+ for .tbss. */
+ if (last_hdr != NULL
+ && (i - phdr_index != 1
+ || ((last_hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
+ != SEC_THREAD_LOCAL)))
{
m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
if (m == NULL)
{
for (m = mfirst; m != NULL; m = m->next)
{
- if (m->p_type == PT_LOAD)
+ if (m->p_type == PT_LOAD
+ && m->count != 0
+ && m->sections[0]->vma >= info->relro_start
+ && m->sections[0]->vma < info->relro_end)
{
- asection *last = m->sections[m->count - 1];
- bfd_vma vaddr = m->sections[0]->vma;
- bfd_vma filesz = last->vma - vaddr + last->size;
+ i = m->count;
+ while (--i != (unsigned) -1)
+ if ((m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS))
+ == (SEC_LOAD | SEC_HAS_CONTENTS))
+ break;
- if (vaddr < info->relro_end
- && vaddr >= info->relro_start
- && (vaddr + filesz) >= info->relro_end)
+ if (i == (unsigned) -1)
+ continue;
+
+ if (m->sections[i]->vma + m->sections[i]->size
+ >= info->relro_end)
break;
}
- }
+ }
/* Make a PT_GNU_RELRO segment only when it isn't empty. */
if (m != NULL)
(unsigned int) m->p_type);
pt = buf;
}
+ fflush (stdout);
fprintf (stderr, "%s:", pt);
for (j = 0; j < m->count; j++)
fprintf (stderr, " %s", m->sections [j]->name);
putc ('\n',stderr);
+ fflush (stderr);
}
static bfd_boolean
header_pad = m->header_size;
}
- elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
- elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
+ if (alloc)
+ {
+ elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
+ elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
+ }
+ else
+ {
+ /* PR binutils/12467. */
+ elf_elfheader (abfd)->e_phoff = 0;
+ elf_elfheader (abfd)->e_phentsize = 0;
+ }
+
elf_elfheader (abfd)->e_phnum = alloc;
if (elf_tdata (abfd)->program_header_size == (bfd_size_type) -1)
if (this_hdr->sh_type != SHT_NOBITS)
off += this_hdr->sh_size;
}
+ else if (this_hdr->sh_type == SHT_NOBITS
+ && (this_hdr->sh_flags & SHF_TLS) != 0
+ && this_hdr->sh_offset == 0)
+ {
+ /* This is a .tbss section that didn't get a PT_LOAD.
+ (See _bfd_elf_map_sections_to_segments "Create a
+ final PT_LOAD".) Set sh_offset to the value it
+ would have if we had created a zero p_filesz and
+ p_memsz PT_LOAD header for the section. This
+ also makes the PT_TLS header have the same
+ p_offset value. */
+ bfd_vma adjust = vma_page_aligned_bias (this_hdr->sh_addr,
+ off, align);
+ this_hdr->sh_offset = sec->filepos = off + adjust;
+ }
if (this_hdr->sh_type != SHT_NOBITS)
{
sec = m->sections[i];
this_hdr = &(elf_section_data(sec)->this_hdr);
- if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0))
+ if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0)
+ && !ELF_TBSS_SPECIAL (this_hdr, p))
{
(*_bfd_error_handler)
(_("%B: section `%A' can't be allocated in segment %d"),
BFD_ASSERT (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 (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,
&& lp->p_vaddr + lp->p_filesz >= link_info->relro_end)
break;
}
+
+ /* PR ld/14207. If the RELRO segment doesn't fit in the
+ LOAD segment, it should be removed. */
+ if (lp == (phdrs + count))
+ abort ();
}
else
{
else
abort ();
p->p_memsz = p->p_filesz;
- p->p_align = 1;
- p->p_flags = (lp->p_flags & ~PF_W);
+ /* Preserve the alignment and flags if they are valid. The
+ gold linker generates RW/4 for the PT_GNU_RELRO section.
+ It is better for objcopy/strip to honor these attributes
+ otherwise gdb will choke when using separate debug files.
+ */
+ if (!m->p_align_valid)
+ p->p_align = 1;
+ if (!m->p_flags_valid)
+ p->p_flags = (lp->p_flags & ~PF_W);
}
else
{
&& (p->p_type != PT_NOTE
|| bfd_get_format (abfd) != bfd_core))
{
- Elf_Internal_Shdr *hdr;
- asection *sect;
-
BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
- sect = m->sections[m->count - 1];
- hdr = &elf_section_data (sect)->this_hdr;
- p->p_filesz = sect->filepos - m->sections[0]->filepos;
- if (hdr->sh_type != SHT_NOBITS)
- p->p_filesz += hdr->sh_size;
+ p->p_filesz = 0;
p->p_offset = m->sections[0]->filepos;
+ for (i = m->count; i-- != 0;)
+ {
+ asection *sect = m->sections[i];
+ Elf_Internal_Shdr *hdr = &elf_section_data (sect)->this_hdr;
+ if (hdr->sh_type != SHT_NOBITS)
+ {
+ p->p_filesz = (sect->filepos - m->sections[0]->filepos
+ + hdr->sh_size);
+ break;
+ }
+ }
}
}
else if (m->includes_filehdr)
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 section or a NOTE section in a PT_NOTE
- segment.
+ 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.
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)
|| obfd->xvec->flavour != bfd_target_elf_flavour)
return TRUE;
+ BFD_ASSERT (elf_section_data (osec) != NULL);
+
/* For objcopy and relocatable link, don't copy the output ELF
section type from input if the output BFD section flags have been
set to something different. For a final link allow some flags
sym.st_info = 0;
sym.st_other = 0;
sym.st_shndx = SHN_UNDEF;
+ sym.st_target_internal = 0;
bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx);
outbound_syms += bed->s->sizeof_sym;
if (outbound_shndx != NULL)
}
if (type_ptr != NULL)
- sym.st_other = type_ptr->internal_elf_sym.st_other;
+ {
+ sym.st_other = type_ptr->internal_elf_sym.st_other;
+ sym.st_target_internal
+ = type_ptr->internal_elf_sym.st_target_internal;
+ }
else
- sym.st_other = 0;
+ {
+ sym.st_other = 0;
+ sym.st_target_internal = 0;
+ }
bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx);
outbound_syms += bed->s->sizeof_sym;
const char **filename_ptr,
const char **functionname_ptr)
{
- const char *filename;
- asymbol *func, *file;
- bfd_vma low_func;
- asymbol **p;
- /* ??? Given multiple file symbols, it is impossible to reliably
- choose the right file name for global symbols. File symbols are
- local symbols, and thus all file symbols must sort before any
- global symbols. The ELF spec may be interpreted to say that a
- file symbol must sort before other local symbols, but currently
- ld -r doesn't do this. So, for ld -r output, it is possible to
- make a better choice of file name for local symbols by ignoring
- file symbols appearing after a given local symbol. */
- enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ static asection *last_section;
+ static asymbol *func;
+ static const char *filename;
+ static bfd_size_type func_size;
- filename = NULL;
- func = NULL;
- file = NULL;
- low_func = 0;
- state = nothing_seen;
-
- for (p = symbols; *p != NULL; p++)
- {
- elf_symbol_type *q;
- unsigned int type;
+ if (symbols == NULL)
+ return FALSE;
- q = (elf_symbol_type *) *p;
+ if (last_section != section
+ || func == NULL
+ || offset < func->value
+ || offset >= func->value + func_size)
+ {
+ asymbol *file;
+ bfd_vma low_func;
+ asymbol **p;
+ /* ??? Given multiple file symbols, it is impossible to reliably
+ choose the right file name for global symbols. File symbols are
+ local symbols, and thus all file symbols must sort before any
+ global symbols. The ELF spec may be interpreted to say that a
+ file symbol must sort before other local symbols, but currently
+ ld -r doesn't do this. So, for ld -r output, it is possible to
+ make a better choice of file name for local symbols by ignoring
+ file symbols appearing after a given local symbol. */
+ enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ filename = NULL;
+ func = NULL;
+ file = NULL;
+ low_func = 0;
+ state = nothing_seen;
+ func_size = 0;
+ last_section = section;
+
+ for (p = symbols; *p != NULL; p++)
+ {
+ asymbol *sym = *p;
+ bfd_vma code_off;
+ bfd_size_type size;
+
+ if ((sym->flags & BSF_FILE) != 0)
+ {
+ file = sym;
+ if (state == symbol_seen)
+ state = file_after_symbol_seen;
+ continue;
+ }
- type = ELF_ST_TYPE (q->internal_elf_sym.st_info);
- switch (type)
- {
- case STT_FILE:
- file = &q->symbol;
- if (state == symbol_seen)
- state = file_after_symbol_seen;
- continue;
- default:
- if (!bed->is_function_type (type))
- break;
- case STT_NOTYPE:
- if (bfd_get_section (&q->symbol) == section
- && q->symbol.value >= low_func
- && q->symbol.value <= offset)
+ size = bed->maybe_function_sym (sym, section, &code_off);
+ if (size != 0
+ && code_off <= offset
+ && (code_off > low_func
+ || (code_off == low_func
+ && size > func_size)))
{
- func = (asymbol *) q;
- low_func = q->symbol.value;
+ func = sym;
+ func_size = size;
+ low_func = code_off;
filename = NULL;
if (file != NULL
- && (ELF_ST_BIND (q->internal_elf_sym.st_info) == STB_LOCAL
+ && ((sym->flags & BSF_LOCAL) != 0
|| state != file_after_symbol_seen))
filename = bfd_asymbol_name (file);
}
- break;
+ if (state == nothing_seen)
+ state = symbol_seen;
}
- if (state == nothing_seen)
- state = symbol_seen;
}
if (func == NULL)
return TRUE;
}
- if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
+ if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections,
+ section, symbols, offset,
filename_ptr, functionname_ptr,
line_ptr, 0,
&elf_tdata (abfd)->dwarf2_find_line_info))
bfd_boolean
_bfd_elf_close_and_cleanup (bfd *abfd)
{
- if (bfd_get_format (abfd) == bfd_object)
+ struct elf_obj_tdata *tdata = elf_tdata (abfd);
+ if (bfd_get_format (abfd) == bfd_object && tdata != NULL)
{
- if (elf_tdata (abfd) != NULL && elf_shstrtab (abfd) != NULL)
+ if (elf_shstrtab (abfd) != NULL)
_bfd_elf_strtab_free (elf_shstrtab (abfd));
- _bfd_dwarf2_cleanup_debug_info (abfd);
+ _bfd_dwarf2_cleanup_debug_info (abfd, &tdata->dwarf2_find_line_info);
}
return _bfd_generic_close_and_cleanup (abfd);
return elfcore_make_note_pseudosection (abfd, ".reg-s390-prefix", note);
}
+static bfd_boolean
+elfcore_grok_s390_last_break (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-s390-last-break", note);
+}
+
+static bfd_boolean
+elfcore_grok_s390_system_call (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-s390-system-call", note);
+}
+
+static bfd_boolean
+elfcore_grok_arm_vfp (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-arm-vfp", note);
+}
+
#if defined (HAVE_PRPSINFO_T)
typedef prpsinfo_t elfcore_psinfo_t;
#if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */
memcpy (&psinfo, note->descdata, sizeof (psinfo));
+#if defined (HAVE_PSINFO_T_PR_PID) || defined (HAVE_PRPSINFO_T_PR_PID)
+ elf_tdata (abfd)->core_pid = psinfo.pr_pid;
+#endif
elf_tdata (abfd)->core_program
= _bfd_elfcore_strndup (abfd, psinfo.pr_fname,
sizeof (psinfo.pr_fname));
memcpy (&psinfo, note->descdata, sizeof (psinfo));
+#if defined (HAVE_PSINFO32_T_PR_PID) || defined (HAVE_PRPSINFO32_T_PR_PID)
+ elf_tdata (abfd)->core_pid = psinfo.pr_pid;
+#endif
elf_tdata (abfd)->core_program
= _bfd_elfcore_strndup (abfd, psinfo.pr_fname,
sizeof (psinfo.pr_fname));
else
return TRUE;
+ case NT_S390_LAST_BREAK:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_s390_last_break (abfd, note);
+ else
+ return TRUE;
+
+ case NT_S390_SYSTEM_CALL:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_s390_system_call (abfd, note);
+ else
+ return TRUE;
+
+ case NT_ARM_VFP:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_arm_vfp (abfd, note);
+ else
+ return TRUE;
+
case NT_PRPSINFO:
case NT_PSINFO:
if (bed->elf_backend_grok_psinfo)
}
}
+static bfd_boolean
+elfobj_grok_stapsdt_note_1 (bfd *abfd, Elf_Internal_Note *note)
+{
+ struct sdt_note *cur =
+ (struct sdt_note *) bfd_alloc (abfd, sizeof (struct sdt_note)
+ + note->descsz);
+
+ cur->next = (struct sdt_note *) (elf_tdata (abfd))->sdt_note_head;
+ cur->size = (bfd_size_type) note->descsz;
+ memcpy (cur->data, note->descdata, note->descsz);
+
+ elf_tdata (abfd)->sdt_note_head = cur;
+
+ return TRUE;
+}
+
+static bfd_boolean
+elfobj_grok_stapsdt_note (bfd *abfd, Elf_Internal_Note *note)
+{
+ switch (note->type)
+ {
+ case NT_STAPSDT:
+ return elfobj_grok_stapsdt_note_1 (abfd, note);
+
+ default:
+ return TRUE;
+ }
+}
+
static bfd_boolean
elfcore_netbsd_get_lwpid (Elf_Internal_Note *note, int *lwpidp)
{
return buf;
}
-#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
char *
elfcore_write_prpsinfo (bfd *abfd,
char *buf,
const char *fname,
const char *psargs)
{
- const char *note_name = "CORE";
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
if (bed->elf_backend_write_core_note != NULL)
return ret;
}
+#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
#if defined (HAVE_PRPSINFO32_T) || defined (HAVE_PSINFO32_T)
if (bed->s->elfclass == ELFCLASS32)
{
strncpy (data.pr_fname, fname, sizeof (data.pr_fname));
strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs));
return elfcore_write_note (abfd, buf, bufsiz,
- note_name, note_type, &data, sizeof (data));
+ "CORE", note_type, &data, sizeof (data));
}
else
#endif
strncpy (data.pr_fname, fname, sizeof (data.pr_fname));
strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs));
return elfcore_write_note (abfd, buf, bufsiz,
- note_name, note_type, &data, sizeof (data));
+ "CORE", note_type, &data, sizeof (data));
}
-}
#endif /* PSINFO_T or PRPSINFO_T */
-#if defined (HAVE_PRSTATUS_T)
+ free (buf);
+ return NULL;
+}
+
char *
elfcore_write_prstatus (bfd *abfd,
char *buf,
int cursig,
const void *gregs)
{
- const char *note_name = "CORE";
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
if (bed->elf_backend_write_core_note != NULL)
return ret;
}
+#if defined (HAVE_PRSTATUS_T)
#if defined (HAVE_PRSTATUS32_T)
if (bed->s->elfclass == ELFCLASS32)
{
prstat.pr_pid = pid;
prstat.pr_cursig = cursig;
memcpy (&prstat.pr_reg, gregs, sizeof (prstat.pr_reg));
- return elfcore_write_note (abfd, buf, bufsiz, note_name,
+ return elfcore_write_note (abfd, buf, bufsiz, "CORE",
NT_PRSTATUS, &prstat, sizeof (prstat));
}
else
prstat.pr_pid = pid;
prstat.pr_cursig = cursig;
memcpy (&prstat.pr_reg, gregs, sizeof (prstat.pr_reg));
- return elfcore_write_note (abfd, buf, bufsiz, note_name,
+ return elfcore_write_note (abfd, buf, bufsiz, "CORE",
NT_PRSTATUS, &prstat, sizeof (prstat));
}
-}
#endif /* HAVE_PRSTATUS_T */
+ free (buf);
+ return NULL;
+}
+
#if defined (HAVE_LWPSTATUS_T)
char *
elfcore_write_lwpstatus (bfd *abfd,
note_name, NT_S390_PREFIX, s390_prefix, size);
}
+char *
+elfcore_write_s390_last_break (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *s390_last_break,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_S390_LAST_BREAK,
+ s390_last_break, size);
+}
+
+char *
+elfcore_write_s390_system_call (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *s390_system_call,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_S390_SYSTEM_CALL,
+ s390_system_call, size);
+}
+
+char *
+elfcore_write_arm_vfp (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *arm_vfp,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_ARM_VFP, arm_vfp, size);
+}
+
char *
elfcore_write_register_note (bfd *abfd,
char *buf,
return elfcore_write_s390_ctrs (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-s390-prefix") == 0)
return elfcore_write_s390_prefix (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-s390-last-break") == 0)
+ return elfcore_write_s390_last_break (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-s390-system-call") == 0)
+ return elfcore_write_s390_system_call (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-arm-vfp") == 0)
+ return elfcore_write_arm_vfp (abfd, buf, bufsiz, data, size);
return NULL;
}
if (! elfobj_grok_gnu_note (abfd, &in))
return FALSE;
}
+ else if (in.namesz == sizeof "stapsdt"
+ && strcmp (in.namedata, "stapsdt") == 0)
+ {
+ if (! elfobj_grok_stapsdt_note (abfd, &in))
+ return FALSE;
+ }
break;
}
+ sym->st_value);
if ((sec->flags & SEC_MERGE)
&& ELF_ST_TYPE (sym->st_info) == STT_SECTION
- && sec->sec_info_type == ELF_INFO_TYPE_MERGE)
+ && sec->sec_info_type == SEC_INFO_TYPE_MERGE)
{
rel->r_addend =
_bfd_merged_section_offset (abfd, psec,
{
asection *sec = *psec;
- if (sec->sec_info_type != ELF_INFO_TYPE_MERGE)
+ if (sec->sec_info_type != SEC_INFO_TYPE_MERGE)
return sym->st_value + addend;
return _bfd_merged_section_offset (abfd, psec,
{
switch (sec->sec_info_type)
{
- case ELF_INFO_TYPE_STABS:
+ case SEC_INFO_TYPE_STABS:
return _bfd_stab_section_offset (sec, elf_section_data (sec)->sec_info,
offset);
- case ELF_INFO_TYPE_EH_FRAME:
+ case SEC_INFO_TYPE_EH_FRAME:
return _bfd_elf_eh_frame_section_offset (abfd, info, sec, offset);
default:
+ if ((sec->flags & SEC_ELF_REVERSE_COPY) != 0)
+ {
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ bfd_size_type address_size = bed->s->arch_size / 8;
+ offset = sec->size - offset - address_size;
+ }
return offset;
}
}
(bfd *templ,
bfd_vma ehdr_vma,
bfd_vma *loadbasep,
- int (*target_read_memory) (bfd_vma, bfd_byte *, int))
+ int (*target_read_memory) (bfd_vma, bfd_byte *, bfd_size_type))
{
return (*get_elf_backend_data (templ)->elf_backend_bfd_from_remote_memory)
(templ, ehdr_vma, loadbasep, target_read_memory);
if (p->addend != 0)
{
char buf[30], *a;
-
+
memcpy (names, "+0x", sizeof ("+0x") - 1);
names += sizeof ("+0x") - 1;
bfd_sprintf_vma (abfd, buf, p->addend);
i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
/* To make things simpler for the loader on Linux systems we set the
- osabi field to ELFOSABI_LINUX if the binary contains symbols of
- the STT_GNU_IFUNC type. */
+ osabi field to ELFOSABI_GNU if the binary contains symbols of
+ the STT_GNU_IFUNC type or STB_GNU_UNIQUE binding. */
if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE
- && elf_tdata (abfd)->has_ifunc_symbols)
- i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;
+ && elf_tdata (abfd)->has_gnu_symbols)
+ i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_GNU;
}
return (type == STT_FUNC
|| type == STT_GNU_IFUNC);
}
+
+/* If the ELF symbol SYM might be a function in SEC, return the
+ function size and set *CODE_OFF to the function's entry point,
+ otherwise return zero. */
+
+bfd_size_type
+_bfd_elf_maybe_function_sym (const asymbol *sym, asection *sec,
+ bfd_vma *code_off)
+{
+ bfd_size_type size;
+
+ if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT
+ | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0
+ || sym->section != sec)
+ return 0;
+
+ *code_off = sym->value;
+ size = 0;
+ if (!(sym->flags & BSF_SYNTHETIC))
+ size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
+ if (size == 0)
+ size = 1;
+ return size;
+}