/* ELF executable support for BFD.
- Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright 1993-2014 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#include "elf-bfd.h"
#include "libiberty.h"
#include "safe-ctype.h"
+#include "elf-linux-psinfo.h"
#ifdef CORE_HEADER
#include CORE_HEADER
return FALSE;
elf_object_id (abfd) = object_id;
- elf_program_header_size (abfd) = (bfd_size_type) -1;
+ if (abfd->direction != read_direction)
+ {
+ struct output_elf_obj_tdata *o = bfd_zalloc (abfd, sizeof *o);
+ if (o == NULL)
+ return FALSE;
+ elf_tdata (abfd)->o = o;
+ elf_program_header_size (abfd) = (bfd_size_type) -1;
+ }
return TRUE;
}
bfd_elf_mkcorefile (bfd *abfd)
{
/* I think this can be done just like an object file. */
- return abfd->xvec->_bfd_set_format[(int) bfd_object] (abfd);
+ if (!abfd->xvec->_bfd_set_format[(int) bfd_object] (abfd))
+ return FALSE;
+ elf_tdata (abfd)->core = bfd_zalloc (abfd, sizeof (*elf_tdata (abfd)->core));
+ return elf_tdata (abfd)->core != NULL;
}
static char *
shnum = elf_numsections (abfd);
num_group = 0;
-#define IS_VALID_GROUP_SECTION_HEADER(shdr) \
+#define IS_VALID_GROUP_SECTION_HEADER(shdr, minsize) \
( (shdr)->sh_type == SHT_GROUP \
- && (shdr)->sh_size >= (2 * GRP_ENTRY_SIZE) \
+ && (shdr)->sh_size >= minsize \
&& (shdr)->sh_entsize == GRP_ENTRY_SIZE \
&& ((shdr)->sh_size % GRP_ENTRY_SIZE) == 0)
{
Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i];
- if (IS_VALID_GROUP_SECTION_HEADER (shdr))
+ if (IS_VALID_GROUP_SECTION_HEADER (shdr, 2 * GRP_ENTRY_SIZE))
num_group += 1;
}
{
Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i];
- if (IS_VALID_GROUP_SECTION_HEADER (shdr))
+ if (IS_VALID_GROUP_SECTION_HEADER (shdr, 2 * GRP_ENTRY_SIZE))
{
unsigned char *src;
Elf_Internal_Group *dest;
{
/* The debugging sections appear to be recognized only by name,
not any sort of flag. Their SEC_ALLOC bits are cleared. */
- static const struct
- {
- const char *name;
- int len;
- } debug_sections [] =
- {
- { STRING_COMMA_LEN ("debug") }, /* 'd' */
- { NULL, 0 }, /* 'e' */
- { NULL, 0 }, /* 'f' */
- { STRING_COMMA_LEN ("gnu.linkonce.wi.") }, /* 'g' */
- { NULL, 0 }, /* 'h' */
- { NULL, 0 }, /* 'i' */
- { NULL, 0 }, /* 'j' */
- { NULL, 0 }, /* 'k' */
- { STRING_COMMA_LEN ("line") }, /* 'l' */
- { NULL, 0 }, /* 'm' */
- { NULL, 0 }, /* 'n' */
- { NULL, 0 }, /* 'o' */
- { NULL, 0 }, /* 'p' */
- { NULL, 0 }, /* 'q' */
- { NULL, 0 }, /* 'r' */
- { STRING_COMMA_LEN ("stab") }, /* 's' */
- { NULL, 0 }, /* 't' */
- { NULL, 0 }, /* 'u' */
- { NULL, 0 }, /* 'v' */
- { NULL, 0 }, /* 'w' */
- { NULL, 0 }, /* 'x' */
- { NULL, 0 }, /* 'y' */
- { STRING_COMMA_LEN ("zdebug") } /* 'z' */
- };
-
if (name [0] == '.')
{
- int i = name [1] - 'd';
- if (i >= 0
- && i < (int) ARRAY_SIZE (debug_sections)
- && debug_sections [i].name != NULL
- && strncmp (&name [1], debug_sections [i].name,
- debug_sections [i].len) == 0)
+ const char *p;
+ int n;
+ if (name[1] == 'd')
+ p = ".debug", n = 6;
+ else if (name[1] == 'g' && name[2] == 'n')
+ p = ".gnu.linkonce.wi.", n = 17;
+ else if (name[1] == 'g' && name[2] == 'd')
+ p = ".gdb_index", n = 11; /* yes we really do mean 11. */
+ else if (name[1] == 'l')
+ p = ".line", n = 5;
+ else if (name[1] == 's')
+ p = ".stab", n = 5;
+ else if (name[1] == 'z')
+ p = ".zdebug", n = 7;
+ else
+ p = NULL, n = 0;
+ if (p != NULL && strncmp (name, p, n) == 0)
flags |= SEC_DEBUGGING;
}
}
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)
else
{
/* Normal section. Check if we should compress. */
- if ((abfd->flags & BFD_COMPRESS))
+ if ((abfd->flags & BFD_COMPRESS) && newsect->size != 0)
action = compress;
}
if (!bfd_init_section_compress_status (abfd, newsect))
{
(*_bfd_error_handler)
- (_("%B: unable to initialize commpress status for section %s"),
+ (_("%B: unable to initialize compress status for section %s"),
abfd, name);
return FALSE;
}
if (!bfd_init_section_decompress_status (abfd, newsect))
{
(*_bfd_error_handler)
- (_("%B: unable to initialize decommpress status for section %s"),
+ (_("%B: unable to initialize decompress status for section %s"),
abfd, name);
return FALSE;
}
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return TRUE;
- BFD_ASSERT (!elf_flags_init (obfd)
- || (elf_elfheader (obfd)->e_flags
- == elf_elfheader (ibfd)->e_flags));
+ if (!elf_flags_init (obfd))
+ {
+ elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
+ elf_flags_init (obfd) = TRUE;
+ }
elf_gp (obfd) = elf_gp (ibfd);
- elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
- elf_flags_init (obfd) = TRUE;
+
+ /* Also copy the EI_OSABI field. */
+ elf_elfheader (obfd)->e_ident[EI_OSABI] =
+ elf_elfheader (ibfd)->e_ident[EI_OSABI];
/* Copy object attributes. */
_bfd_elf_copy_obj_attributes (ibfd, obfd);
bfd_fprintf_vma (abfd, file, val);
/* If we have version information, print it. */
- if (elf_tdata (abfd)->dynversym_section != 0
- && (elf_tdata (abfd)->dynverdef_section != 0
- || elf_tdata (abfd)->dynverref_section != 0))
+ if (elf_dynversym (abfd) != 0
+ && (elf_dynverdef (abfd) != 0
+ || elf_dynverref (abfd) != 0))
{
unsigned int vernum;
const char *version_string;
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;
return TRUE;
case SHT_GROUP:
- if (! IS_VALID_GROUP_SECTION_HEADER (hdr))
+ if (! IS_VALID_GROUP_SECTION_HEADER (hdr, GRP_ENTRY_SIZE))
return FALSE;
if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
return FALSE;
{
{ STRING_COMMA_LEN (".data"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".data1"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ /* There are more DWARF sections than these, but they needn't be added here
+ unless you have to cope with broken compilers that don't emit section
+ attributes or you want to help the user writing assembler. */
{ STRING_COMMA_LEN (".debug"), 0, SHT_PROGBITS, 0 },
{ STRING_COMMA_LEN (".debug_line"), 0, SHT_PROGBITS, 0 },
{ STRING_COMMA_LEN (".debug_info"), 0, SHT_PROGBITS, 0 },
USE_RELA_P is TRUE, we use RELA relocations; otherwise, we use REL
relocations. */
-bfd_boolean
+static bfd_boolean
_bfd_elf_init_reloc_shdr (bfd *abfd,
struct bfd_elf_section_reloc_data *reldata,
asection *asect,
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;
d->rela.idx = 0;
}
- t->shstrtab_section = section_number++;
+ elf_shstrtab_sec (abfd) = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->shstrtab_hdr.sh_name);
- elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section;
+ elf_elfheader (abfd)->e_shstrndx = elf_shstrtab_sec (abfd);
need_symtab = (bfd_get_symcount (abfd) > 0
|| (link_info == NULL
== HAS_RELOC)));
if (need_symtab)
{
- t->symtab_section = section_number++;
+ elf_onesymtab (abfd) = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF))
{
- t->symtab_shndx_section = section_number++;
+ elf_symtab_shndx (abfd) = section_number++;
t->symtab_shndx_hdr.sh_name
= (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
".symtab_shndx", FALSE);
if (t->symtab_shndx_hdr.sh_name == (unsigned int) -1)
return FALSE;
}
- t->strtab_section = section_number++;
+ elf_strtab_sec (abfd) = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name);
}
+ if (section_number >= SHN_LORESERVE)
+ {
+ _bfd_error_handler (_("%B: too many sections: %u"),
+ abfd, section_number);
+ return FALSE;
+ }
+
_bfd_elf_strtab_finalize (elf_shstrtab (abfd));
t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
elf_elfsections (abfd) = i_shdrp;
- i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr;
+ i_shdrp[elf_shstrtab_sec (abfd)] = &t->shstrtab_hdr;
if (need_symtab)
{
- i_shdrp[t->symtab_section] = &t->symtab_hdr;
+ i_shdrp[elf_onesymtab (abfd)] = &t->symtab_hdr;
if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF))
{
- i_shdrp[t->symtab_shndx_section] = &t->symtab_shndx_hdr;
- t->symtab_shndx_hdr.sh_link = t->symtab_section;
+ i_shdrp[elf_symtab_shndx (abfd)] = &t->symtab_shndx_hdr;
+ t->symtab_shndx_hdr.sh_link = elf_onesymtab (abfd);
}
- i_shdrp[t->strtab_section] = &t->strtab_hdr;
- t->symtab_hdr.sh_link = t->strtab_section;
+ i_shdrp[elf_strtab_sec (abfd)] = &t->strtab_hdr;
+ t->symtab_hdr.sh_link = elf_strtab_sec (abfd);
}
for (sec = abfd->sections; sec; sec = sec->next)
the relocation entries apply. */
if (d->rel.idx != 0)
{
- d->rel.hdr->sh_link = t->symtab_section;
+ d->rel.hdr->sh_link = elf_onesymtab (abfd);
d->rel.hdr->sh_info = d->this_idx;
+ d->rel.hdr->sh_flags |= SHF_INFO_LINK;
}
if (d->rela.idx != 0)
{
- d->rela.hdr->sh_link = t->symtab_section;
+ d->rela.hdr->sh_link = elf_onesymtab (abfd);
d->rela.hdr->sh_info = d->this_idx;
+ d->rela.hdr->sh_flags |= SHF_INFO_LINK;
}
/* We need to set up sh_link for SHF_LINK_ORDER. */
if (link_info != NULL)
{
/* Check discarded linkonce section. */
- if (elf_discarded_section (s))
+ if (discarded_section (s))
{
asection *kept;
(*_bfd_error_handler)
name += 5;
s = bfd_get_section_by_name (abfd, name);
if (s != NULL)
- d->this_hdr.sh_info = elf_section_data (s)->this_idx;
+ {
+ d->this_hdr.sh_info = elf_section_data (s)->this_idx;
+ d->this_hdr.sh_flags |= SHF_INFO_LINK;
+ }
break;
case SHT_STRTAB:
break;
case SHT_GROUP:
- d->this_hdr.sh_link = t->symtab_section;
+ d->this_hdr.sh_link = elf_onesymtab (abfd);
}
}
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, that are duplicates or there is no BFD section. */
static bfd_boolean
ignore_section_sym (bfd *abfd, asymbol *sym)
{
- return ((sym->flags & BSF_SECTION_SYM) != 0
- && !(sym->section->owner == abfd
+ elf_symbol_type *type_ptr;
+
+ if ((sym->flags & BSF_SECTION_SYM) == 0)
+ return FALSE;
+
+ type_ptr = elf_symbol_from (abfd, sym);
+ return ((type_ptr != NULL
+ && type_ptr->internal_elf_sym.st_shndx != 0
+ && bfd_is_abs_section (sym->section))
+ || !(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)
+elf_map_symbols (bfd *abfd, unsigned int *pnum_locals)
{
unsigned int symcount = bfd_get_symcount (abfd);
asymbol **syms = bfd_get_outsymbols (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_set_symtab (abfd, new_syms, num_locals + num_globals);
- elf_num_locals (abfd) = num_locals;
- elf_num_globals (abfd) = num_globals;
+ *pnum_locals = num_locals;
return TRUE;
}
return FALSE;
/* Post process the headers if necessary. */
- if (bed->elf_backend_post_process_headers)
- (*bed->elf_backend_post_process_headers) (abfd, link_info);
+ (*bed->elf_backend_post_process_headers) (abfd, link_info);
fsargs.failed = FALSE;
fsargs.link_info = link_info;
file_ptr off;
Elf_Internal_Shdr *hdr;
- off = elf_tdata (abfd)->next_file_pos;
+ off = elf_next_file_pos (abfd);
hdr = &elf_tdata (abfd)->symtab_hdr;
off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
hdr = &elf_tdata (abfd)->strtab_hdr;
off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
- elf_tdata (abfd)->next_file_pos = off;
+ elf_next_file_pos (abfd) = off;
/* Now that we know where the .strtab section goes, write it
out. */
++segs;
}
- if (elf_tdata (abfd)->eh_frame_hdr)
+ if (elf_eh_frame_hdr (abfd))
{
/* We need a PT_GNU_EH_FRAME segment. */
++segs;
}
- if (elf_tdata (abfd)->stack_flags)
+ if (elf_stack_flags (abfd))
{
/* We need a PT_GNU_STACK segment. */
++segs;
struct elf_segment_map *m;
Elf_Internal_Phdr *p;
- for (m = elf_tdata (abfd)->segment_map,
- p = elf_tdata (abfd)->phdr;
+ for (m = elf_seg_map (abfd), p = elf_tdata (abfd)->phdr;
m != NULL;
m = m->next, p++)
{
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;
+ m = &elf_seg_map (abfd);
while (*m)
{
unsigned int i, new_count;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
bfd_boolean no_user_phdrs;
- no_user_phdrs = elf_tdata (abfd)->segment_map == NULL;
+ no_user_phdrs = elf_seg_map (abfd) == NULL;
+
+ if (info != NULL)
+ info->user_phdrs = !no_user_phdrs;
+
if (no_user_phdrs && bfd_count_sections (abfd) != 0)
{
asection *s;
program headers we will need. */
if (count > 0)
{
- bfd_size_type phdr_size = elf_tdata (abfd)->program_header_size;
+ bfd_size_type phdr_size = elf_program_header_size (abfd);
if (phdr_size == (bfd_size_type) -1)
phdr_size = get_program_header_size (abfd, info);
+ phdr_size += bed->s->sizeof_ehdr;
if ((abfd->flags & D_PAGED) == 0
|| (sections[0]->lma & addr_mask) < phdr_size
|| ((sections[0]->lma & addr_mask) % maxpagesize
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)
/* 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;
+ eh_frame_hdr = elf_eh_frame_hdr (abfd);
if (eh_frame_hdr != NULL
&& (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0)
{
pm = &m->next;
}
- if (elf_tdata (abfd)->stack_flags)
+ if (elf_stack_flags (abfd))
{
amt = sizeof (struct elf_segment_map);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
goto error_return;
m->next = NULL;
m->p_type = PT_GNU_STACK;
- m->p_flags = elf_tdata (abfd)->stack_flags;
+ m->p_flags = elf_stack_flags (abfd);
+ m->p_align = bed->stack_align;
m->p_flags_valid = 1;
+ m->p_align_valid = m->p_align != 0;
+ if (info->stacksize > 0)
+ {
+ m->p_size = info->stacksize;
+ m->p_size_valid = 1;
+ }
*pm = m;
pm = &m->next;
{
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)
break;
}
- }
+ }
/* Make a PT_GNU_RELRO segment only when it isn't empty. */
if (m != NULL)
}
free (sections);
- elf_tdata (abfd)->segment_map = mfirst;
+ elf_seg_map (abfd) = mfirst;
}
if (!elf_modify_segment_map (abfd, info, no_user_phdrs))
return FALSE;
- for (count = 0, m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+ for (count = 0, m = elf_seg_map (abfd); m != NULL; m = m->next)
++count;
- elf_tdata (abfd)->program_header_size = count * bed->s->sizeof_phdr;
+ elf_program_header_size (abfd) = count * bed->s->sizeof_phdr;
return TRUE;
static file_ptr
vma_page_aligned_bias (bfd_vma vma, ufile_ptr off, bfd_vma maxpagesize)
{
+ /* PR binutils/16199: Handle an alignment of zero. */
+ if (maxpagesize == 0)
+ maxpagesize = 1;
return ((vma - off) % maxpagesize);
}
return FALSE;
alloc = 0;
- for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+ for (m = elf_seg_map (abfd); m != NULL; m = m->next)
{
++alloc;
if (m->header_size)
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)
- elf_tdata (abfd)->program_header_size = alloc * bed->s->sizeof_phdr;
+ if (elf_program_header_size (abfd) == (bfd_size_type) -1)
+ elf_program_header_size (abfd) = alloc * bed->s->sizeof_phdr;
else
- BFD_ASSERT (elf_tdata (abfd)->program_header_size
+ BFD_ASSERT (elf_program_header_size (abfd)
>= alloc * bed->s->sizeof_phdr);
if (alloc == 0)
{
- elf_tdata (abfd)->next_file_pos = bed->s->sizeof_ehdr;
+ elf_next_file_pos (abfd) = bed->s->sizeof_ehdr;
return TRUE;
}
- /* We're writing the size in elf_tdata (abfd)->program_header_size,
+ /* We're writing the size in elf_program_header_size (abfd),
see assign_file_positions_except_relocs, so make sure we have
that amount allocated, with trailing space cleared.
- The variable alloc contains the computed need, while elf_tdata
- (abfd)->program_header_size contains the size used for the
+ The variable alloc contains the computed need, while
+ elf_program_header_size (abfd) contains the size used for the
layout.
See ld/emultempl/elf-generic.em:gld${EMULATION_NAME}_map_segments
where the layout is forced to according to a larger size in the
last iterations for the testcase ld-elf/header. */
- BFD_ASSERT (elf_tdata (abfd)->program_header_size % bed->s->sizeof_phdr
+ BFD_ASSERT (elf_program_header_size (abfd) % bed->s->sizeof_phdr
== 0);
phdrs = (Elf_Internal_Phdr *)
bfd_zalloc2 (abfd,
- (elf_tdata (abfd)->program_header_size / bed->s->sizeof_phdr),
+ (elf_program_header_size (abfd) / bed->s->sizeof_phdr),
sizeof (Elf_Internal_Phdr));
elf_tdata (abfd)->phdr = phdrs;
if (phdrs == NULL)
header_pad -= off;
off += header_pad;
- for (m = elf_tdata (abfd)->segment_map, p = phdrs, j = 0;
+ for (m = elf_seg_map (abfd), p = phdrs, j = 0;
m != NULL;
m = m->next, p++, j++)
{
p->p_memsz = bed->s->sizeof_ehdr;
if (m->count > 0)
{
- BFD_ASSERT (p->p_type == PT_LOAD);
-
if (p->p_vaddr < (bfd_vma) off)
{
(*_bfd_error_handler)
if (m->count > 0)
{
- BFD_ASSERT (p->p_type == PT_LOAD);
p->p_vaddr -= off - p->p_offset;
if (!m->p_paddr_valid)
p->p_paddr -= off - p->p_offset;
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)
{
p->p_flags |= PF_W;
}
}
+
off -= off_adjust;
/* Check that all sections are in a PT_LOAD segment.
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"),
}
}
- elf_tdata (abfd)->next_file_pos = off;
+ elf_next_file_pos (abfd) = off;
return TRUE;
}
Elf_Internal_Phdr *phdrs;
Elf_Internal_Phdr *p;
struct elf_segment_map *m;
+ struct elf_segment_map *hdrs_segment;
bfd_vma filehdr_vaddr, filehdr_paddr;
bfd_vma phdrs_vaddr, phdrs_paddr;
file_ptr off;
i_shdrpp = elf_elfsections (abfd);
num_sec = elf_numsections (abfd);
- off = elf_tdata (abfd)->next_file_pos;
+ off = elf_next_file_pos (abfd);
for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++)
{
- struct elf_obj_tdata *tdata = elf_tdata (abfd);
Elf_Internal_Shdr *hdr;
hdr = *hdrpp;
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,
}
else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
&& hdr->bfd_section == NULL)
- || hdr == i_shdrpp[tdata->symtab_section]
- || hdr == i_shdrpp[tdata->symtab_shndx_section]
- || hdr == i_shdrpp[tdata->strtab_section])
+ || hdr == i_shdrpp[elf_onesymtab (abfd)]
+ || hdr == i_shdrpp[elf_symtab_shndx (abfd)]
+ || hdr == i_shdrpp[elf_strtab_sec (abfd)])
hdr->sh_offset = -1;
else
off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
filehdr_paddr = 0;
phdrs_vaddr = bed->maxpagesize + bed->s->sizeof_ehdr;
phdrs_paddr = 0;
+ hdrs_segment = NULL;
phdrs = elf_tdata (abfd)->phdr;
- for (m = elf_tdata (abfd)->segment_map, p = phdrs;
- m != NULL;
- m = m->next, p++)
+ for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++)
{
++count;
if (p->p_type != PT_LOAD)
phdrs_paddr = p->p_paddr;
if (m->includes_filehdr)
{
+ hdrs_segment = m;
phdrs_vaddr += bed->s->sizeof_ehdr;
phdrs_paddr += bed->s->sizeof_ehdr;
}
}
}
- for (m = elf_tdata (abfd)->segment_map, p = phdrs;
- m != NULL;
- m = m->next, p++)
+ if (hdrs_segment != NULL && link_info != NULL)
+ {
+ /* There is a segment that contains both the file headers and the
+ program headers, so provide a symbol __ehdr_start pointing there.
+ A program can use this to examine itself robustly. */
+
+ struct elf_link_hash_entry *hash
+ = elf_link_hash_lookup (elf_hash_table (link_info), "__ehdr_start",
+ FALSE, FALSE, TRUE);
+ /* If the symbol was referenced and not defined, define it. */
+ if (hash != NULL
+ && (hash->root.type == bfd_link_hash_new
+ || hash->root.type == bfd_link_hash_undefined
+ || hash->root.type == bfd_link_hash_undefweak
+ || hash->root.type == bfd_link_hash_common))
+ {
+ asection *s = NULL;
+ if (hdrs_segment->count != 0)
+ /* The segment contains sections, so use the first one. */
+ s = hdrs_segment->sections[0];
+ else
+ /* Use the first (i.e. lowest-addressed) section in any segment. */
+ for (m = elf_seg_map (abfd); m != NULL; m = m->next)
+ if (m->count != 0)
+ {
+ s = m->sections[0];
+ break;
+ }
+
+ if (s != NULL)
+ {
+ hash->root.u.def.value = filehdr_vaddr - s->vma;
+ hash->root.u.def.section = s;
+ }
+ else
+ {
+ hash->root.u.def.value = filehdr_vaddr;
+ hash->root.u.def.section = bfd_abs_section_ptr;
+ }
+
+ hash->root.type = bfd_link_hash_defined;
+ hash->def_regular = 1;
+ hash->non_elf = 0;
+ }
+ }
+
+ for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++)
{
if (p->p_type == PT_GNU_RELRO)
{
const Elf_Internal_Phdr *lp;
-
- BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
+ struct elf_segment_map *lm;
if (link_info != NULL)
{
/* During linking the range of the RELRO segment is passed
in link_info. */
- for (lp = phdrs; lp < phdrs + count; ++lp)
+ for (lm = elf_seg_map (abfd), lp = phdrs;
+ lm != NULL;
+ lm = lm->next, lp++)
{
if (lp->p_type == PT_LOAD
- && lp->p_vaddr >= link_info->relro_start
&& lp->p_vaddr < link_info->relro_end
- && lp->p_vaddr + lp->p_filesz >= link_info->relro_end)
+ && lm->count != 0
+ && lm->sections[0]->vma >= link_info->relro_start)
break;
}
+
+ BFD_ASSERT (lm != NULL);
}
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_NULL;
}
}
+ else if (p->p_type == PT_GNU_STACK)
+ {
+ if (m->p_size_valid)
+ p->p_memsz = m->p_size;
+ }
else if (m->count != 0)
{
if (p->p_type != PT_LOAD
&& (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)
}
}
- elf_tdata (abfd)->next_file_pos = off;
+ elf_next_file_pos (abfd) = off;
return TRUE;
}
hdr = *hdrpp;
if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
&& hdr->bfd_section == NULL)
- || i == tdata->symtab_section
- || i == tdata->symtab_shndx_section
- || i == tdata->strtab_section)
+ || i == elf_onesymtab (abfd)
+ || i == elf_symtab_shndx (abfd)
+ || i == elf_strtab_sec (abfd))
{
hdr->sh_offset = -1;
}
return FALSE;
}
+ /* Set e_type in ELF header to ET_EXEC for -pie -Ttext-segment=. */
+ if (link_info != NULL
+ && link_info->executable
+ && link_info->shared)
+ {
+ unsigned int num_segments = elf_elfheader (abfd)->e_phnum;
+ Elf_Internal_Phdr *segment = elf_tdata (abfd)->phdr;
+ Elf_Internal_Phdr *end_segment = &segment[num_segments];
+
+ /* Find the lowest p_vaddr in PT_LOAD segments. */
+ bfd_vma p_vaddr = (bfd_vma) -1;
+ for (; segment < end_segment; segment++)
+ if (segment->p_type == PT_LOAD && p_vaddr > segment->p_vaddr)
+ p_vaddr = segment->p_vaddr;
+
+ /* Set e_type to ET_EXEC if the lowest p_vaddr in PT_LOAD
+ segments is non-zero. */
+ if (p_vaddr)
+ i_ehdrp->e_type = ET_EXEC;
+ }
+
/* Write out the program headers. */
- alloc = tdata->program_header_size / bed->s->sizeof_phdr;
+ alloc = elf_program_header_size (abfd) / bed->s->sizeof_phdr;
if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
|| bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0)
return FALSE;
- off = tdata->next_file_pos;
+ off = elf_next_file_pos (abfd);
}
/* Place the section headers. */
i_ehdrp->e_shoff = off;
off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
- tdata->next_file_pos = off;
+ elf_next_file_pos (abfd) = off;
return TRUE;
}
unsigned int i, num_sec;
Elf_Internal_Shdr **shdrpp;
- off = elf_tdata (abfd)->next_file_pos;
+ off = elf_next_file_pos (abfd);
num_sec = elf_numsections (abfd);
for (i = 1, shdrpp = elf_elfsections (abfd) + 1; i < num_sec; i++, shdrpp++)
off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE);
}
- elf_tdata (abfd)->next_file_pos = off;
+ elf_next_file_pos (abfd) = off;
}
bfd_boolean
Elf_Internal_Shdr **i_shdrp;
bfd_boolean failed;
unsigned int count, num_sec;
+ struct elf_obj_tdata *t;
if (! abfd->output_has_begun
&& ! _bfd_elf_compute_section_file_positions (abfd, NULL))
}
/* Write out the section header names. */
+ t = elf_tdata (abfd);
if (elf_shstrtab (abfd) != NULL
- && (bfd_seek (abfd, elf_tdata (abfd)->shstrtab_hdr.sh_offset, SEEK_SET) != 0
+ && (bfd_seek (abfd, t->shstrtab_hdr.sh_offset, SEEK_SET) != 0
|| !_bfd_elf_strtab_emit (abfd, elf_shstrtab (abfd))))
return FALSE;
if (bed->elf_backend_final_write_processing)
- (*bed->elf_backend_final_write_processing) (abfd,
- elf_tdata (abfd)->linker);
+ (*bed->elf_backend_final_write_processing) (abfd, elf_linker (abfd));
if (!bed->s->write_shdrs_and_ehdr (abfd))
return FALSE;
/* This is last since write_shdrs_and_ehdr can touch i_shdrp[0]. */
- if (elf_tdata (abfd)->after_write_object_contents)
- return (*elf_tdata (abfd)->after_write_object_contents) (abfd);
+ if (t->o->build_id.after_write_object_contents != NULL)
+ return (*t->o->build_id.after_write_object_contents) (abfd);
return TRUE;
}
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.
and carry on looping. */
amt = sizeof (struct elf_segment_map);
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
- map = (struct elf_segment_map *) bfd_alloc (obfd, amt);
+ map = (struct elf_segment_map *) bfd_zalloc (obfd, amt);
if (map == NULL)
{
free (sections);
free (sections);
}
- elf_tdata (obfd)->segment_map = map_first;
+ elf_seg_map (obfd) = map_first;
/* If we had to estimate the number of program headers that were
going to be needed, then check our estimate now and adjust
map->p_align_valid = 1;
map->p_vaddr_offset = 0;
- if (map->p_type == PT_GNU_RELRO)
+ if (map->p_type == PT_GNU_RELRO
+ || map->p_type == PT_GNU_STACK)
{
/* The PT_GNU_RELRO segment may contain the first a few
bytes in the .got.plt section even if the whole .got.plt
section isn't in the PT_GNU_RELRO segment. We won't
- change the size of the PT_GNU_RELRO segment. */
+ change the size of the PT_GNU_RELRO segment.
+ Similarly, PT_GNU_STACK size is significant on uclinux
+ systems. */
map->p_size = segment->p_memsz;
map->p_size_valid = 1;
}
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;
+ if (section->lma < lowest_section->lma)
+ lowest_section = section;
+
/* 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
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)
pointer_to_map = &map->next;
}
- elf_tdata (obfd)->segment_map = map_first;
+ elf_seg_map (obfd) = map_first;
return TRUE;
}
}
rewrite:
+ if (ibfd->xvec == obfd->xvec)
+ {
+ /* When rewriting program header, set the output maxpagesize to
+ the maximum alignment of input PT_LOAD segments. */
+ Elf_Internal_Phdr *segment;
+ unsigned int i;
+ unsigned int num_segments = elf_elfheader (ibfd)->e_phnum;
+ bfd_vma maxpagesize = 0;
+
+ for (i = 0, segment = elf_tdata (ibfd)->phdr;
+ i < num_segments;
+ i++, segment++)
+ if (segment->p_type == PT_LOAD
+ && maxpagesize < segment->p_align)
+ maxpagesize = segment->p_align;
+
+ if (maxpagesize != get_elf_backend_data (obfd)->maxpagesize)
+ bfd_emul_set_maxpagesize (bfd_get_target (obfd), maxpagesize);
+ }
+
return rewrite_elf_program_header (ibfd, obfd);
}
|| 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
entry point, because the latter is called after the section
contents have been set, which means that the program headers have
already been worked out. */
- if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL)
+ if (elf_seg_map (obfd) == NULL && elf_tdata (ibfd)->phdr != NULL)
{
if (! copy_private_bfd_data (ibfd, obfd))
return FALSE;
shndx = MAP_ONESYMTAB;
else if (shndx == elf_dynsymtab (ibfd))
shndx = MAP_DYNSYMTAB;
- else if (shndx == elf_tdata (ibfd)->strtab_section)
+ else if (shndx == elf_strtab_sec (ibfd))
shndx = MAP_STRTAB;
- else if (shndx == elf_tdata (ibfd)->shstrtab_section)
+ else if (shndx == elf_shstrtab_sec (ibfd))
shndx = MAP_SHSTRTAB;
- else if (shndx == elf_tdata (ibfd)->symtab_shndx_section)
+ else if (shndx == elf_symtab_shndx (ibfd))
shndx = MAP_SYM_SHNDX;
osym->internal_elf_sym.st_shndx = shndx;
}
bfd_byte *outbound_syms;
bfd_byte *outbound_shndx;
int idx;
+ unsigned int num_locals;
bfd_size_type amt;
bfd_boolean name_local_sections;
- if (!elf_map_symbols (abfd))
+ if (!elf_map_symbols (abfd, &num_locals))
return FALSE;
/* Dump out the symtabs. */
symtab_hdr->sh_type = SHT_SYMTAB;
symtab_hdr->sh_entsize = bed->s->sizeof_sym;
symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1);
- symtab_hdr->sh_info = elf_num_locals (abfd) + 1;
+ symtab_hdr->sh_info = num_locals + 1;
symtab_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
shndx = elf_dynsymtab (abfd);
break;
case MAP_STRTAB:
- shndx = elf_tdata (abfd)->strtab_section;
+ shndx = elf_strtab_sec (abfd);
break;
case MAP_SHSTRTAB:
- shndx = elf_tdata (abfd)->shstrtab_section;
+ shndx = elf_shstrtab_sec (abfd);
break;
case MAP_SYM_SHNDX:
- shndx = elf_tdata (abfd)->symtab_shndx_section;
+ shndx = elf_symtab_shndx (abfd);
break;
default:
+ shndx = SHN_ABS;
break;
}
}
Elf_Internal_Verdef *iverdef;
Elf_Internal_Verdaux *iverdaux;
- iverdef = &elf_tdata (abfd)->verdef[freeidx - 1];;
+ iverdef = &elf_tdata (abfd)->verdef[freeidx - 1];
iverdef->vd_version = VER_DEF_CURRENT;
iverdef->vd_flags = 0;
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);
+ struct elf_find_function_cache
+ {
+ asection *last_section;
+ asymbol *func;
+ const char *filename;
+ bfd_size_type func_size;
+ } *cache;
- filename = NULL;
- func = NULL;
- file = NULL;
- low_func = 0;
- state = nothing_seen;
+ if (symbols == NULL)
+ return FALSE;
- for (p = symbols; *p != NULL; p++)
+ cache = elf_tdata (abfd)->elf_find_function_cache;
+ if (cache == NULL)
{
- elf_symbol_type *q;
- unsigned int type;
-
- q = (elf_symbol_type *) *p;
+ cache = bfd_zalloc (abfd, sizeof (*cache));
+ elf_tdata (abfd)->elf_find_function_cache = cache;
+ if (cache == NULL)
+ return FALSE;
+ }
+ if (cache->last_section != section
+ || cache->func == NULL
+ || offset < cache->func->value
+ || offset >= cache->func->value + cache->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);
+
+ file = NULL;
+ low_func = 0;
+ state = nothing_seen;
+ cache->filename = NULL;
+ cache->func = NULL;
+ cache->func_size = 0;
+ cache->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 > cache->func_size)))
{
- func = (asymbol *) q;
- low_func = q->symbol.value;
- filename = NULL;
+ cache->func = sym;
+ cache->func_size = size;
+ cache->filename = NULL;
+ low_func = code_off;
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);
+ cache->filename = bfd_asymbol_name (file);
}
- break;
+ if (state == nothing_seen)
+ state = symbol_seen;
}
- if (state == nothing_seen)
- state = symbol_seen;
}
- if (func == NULL)
+ if (cache->func == NULL)
return FALSE;
if (filename_ptr)
- *filename_ptr = filename;
+ *filename_ptr = cache->filename;
if (functionname_ptr)
- *functionname_ptr = bfd_asymbol_name (func);
+ *functionname_ptr = bfd_asymbol_name (cache->func);
return TRUE;
}
const char **filename_ptr,
const char **functionname_ptr,
unsigned int *line_ptr)
+{
+ return _bfd_elf_find_nearest_line_discriminator (abfd, section, symbols,
+ offset, filename_ptr,
+ functionname_ptr,
+ line_ptr,
+ NULL);
+}
+
+bfd_boolean
+_bfd_elf_find_nearest_line_discriminator (bfd *abfd,
+ asection *section,
+ asymbol **symbols,
+ bfd_vma offset,
+ const char **filename_ptr,
+ const char **functionname_ptr,
+ unsigned int *line_ptr,
+ unsigned int *discriminator_ptr)
{
bfd_boolean found;
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,
+ line_ptr, discriminator_ptr, 0,
&elf_tdata (abfd)->dwarf2_find_line_info))
{
if (!*functionname_ptr)
bfd_boolean
_bfd_elf_find_line (bfd *abfd, asymbol **symbols, asymbol *symbol,
const char **filename_ptr, unsigned int *line_ptr)
+{
+ return _bfd_elf_find_line_discriminator (abfd, symbols, symbol,
+ filename_ptr, line_ptr,
+ NULL);
+}
+
+bfd_boolean
+_bfd_elf_find_line_discriminator (bfd *abfd, asymbol **symbols, asymbol *symbol,
+ const char **filename_ptr,
+ unsigned int *line_ptr,
+ unsigned int *discriminator_ptr)
{
return _bfd_dwarf2_find_line (abfd, symbols, symbol,
- filename_ptr, line_ptr, 0,
+ filename_ptr, line_ptr, discriminator_ptr, 0,
&elf_tdata (abfd)->dwarf2_find_line_info);
}
if (!info->relocatable)
{
- bfd_size_type phdr_size = elf_tdata (abfd)->program_header_size;
+ bfd_size_type phdr_size = elf_program_header_size (abfd);
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)
+ for (m = elf_seg_map (abfd); 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;
+ elf_program_header_size (abfd) = phdr_size;
ret += phdr_size;
}
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_tdata (abfd)->o != NULL && 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);
{
int pid;
- pid = elf_tdata (abfd)->core_lwpid;
+ pid = elf_tdata (abfd)->core->lwpid;
if (pid == 0)
- pid = elf_tdata (abfd)->core_pid;
+ pid = elf_tdata (abfd)->core->pid;
return pid;
}
/* Do not overwrite the core signal if it
has already been set by another thread. */
- if (elf_tdata (abfd)->core_signal == 0)
- elf_tdata (abfd)->core_signal = prstat.pr_cursig;
- if (elf_tdata (abfd)->core_pid == 0)
- elf_tdata (abfd)->core_pid = prstat.pr_pid;
+ if (elf_tdata (abfd)->core->signal == 0)
+ elf_tdata (abfd)->core->signal = prstat.pr_cursig;
+ if (elf_tdata (abfd)->core->pid == 0)
+ elf_tdata (abfd)->core->pid = prstat.pr_pid;
/* pr_who exists on:
solaris 2.5+
linux 2.[01]
*/
#if defined (HAVE_PRSTATUS_T_PR_WHO)
- elf_tdata (abfd)->core_lwpid = prstat.pr_who;
+ elf_tdata (abfd)->core->lwpid = prstat.pr_who;
#else
- elf_tdata (abfd)->core_lwpid = prstat.pr_pid;
+ elf_tdata (abfd)->core->lwpid = prstat.pr_pid;
#endif
}
#if defined (HAVE_PRSTATUS32_T)
/* Do not overwrite the core signal if it
has already been set by another thread. */
- if (elf_tdata (abfd)->core_signal == 0)
- elf_tdata (abfd)->core_signal = prstat.pr_cursig;
- if (elf_tdata (abfd)->core_pid == 0)
- elf_tdata (abfd)->core_pid = prstat.pr_pid;
+ if (elf_tdata (abfd)->core->signal == 0)
+ elf_tdata (abfd)->core->signal = prstat.pr_cursig;
+ if (elf_tdata (abfd)->core->pid == 0)
+ elf_tdata (abfd)->core->pid = prstat.pr_pid;
/* pr_who exists on:
solaris 2.5+
linux 2.[01]
*/
#if defined (HAVE_PRSTATUS32_T_PR_WHO)
- elf_tdata (abfd)->core_lwpid = prstat.pr_who;
+ elf_tdata (abfd)->core->lwpid = prstat.pr_who;
#else
- elf_tdata (abfd)->core_lwpid = prstat.pr_pid;
+ elf_tdata (abfd)->core->lwpid = prstat.pr_pid;
#endif
}
#endif /* HAVE_PRSTATUS32_T */
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_s390_tdb (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-s390-tdb", note);
+}
+
+static bfd_boolean
+elfcore_grok_arm_vfp (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-arm-vfp", note);
+}
+
+static bfd_boolean
+elfcore_grok_aarch_tls (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-aarch-tls", note);
+}
+
+static bfd_boolean
+elfcore_grok_aarch_hw_break (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-aarch-hw-break", note);
+}
+
+static bfd_boolean
+elfcore_grok_aarch_hw_watch (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-aarch-hw-watch", 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;
+ elf_tdata (abfd)->core->pid = psinfo.pr_pid;
#endif
- elf_tdata (abfd)->core_program
+ elf_tdata (abfd)->core->program
= _bfd_elfcore_strndup (abfd, psinfo.pr_fname,
sizeof (psinfo.pr_fname));
- elf_tdata (abfd)->core_command
+ elf_tdata (abfd)->core->command
= _bfd_elfcore_strndup (abfd, psinfo.pr_psargs,
sizeof (psinfo.pr_psargs));
}
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;
+ elf_tdata (abfd)->core->pid = psinfo.pr_pid;
#endif
- elf_tdata (abfd)->core_program
+ elf_tdata (abfd)->core->program
= _bfd_elfcore_strndup (abfd, psinfo.pr_fname,
sizeof (psinfo.pr_fname));
- elf_tdata (abfd)->core_command
+ elf_tdata (abfd)->core->command
= _bfd_elfcore_strndup (abfd, psinfo.pr_psargs,
sizeof (psinfo.pr_psargs));
}
implementations, so strip it off if it exists. */
{
- char *command = elf_tdata (abfd)->core_command;
+ char *command = elf_tdata (abfd)->core->command;
int n = strlen (command);
if (0 < n && command[n - 1] == ' ')
memcpy (&pstat, note->descdata, sizeof (pstat));
- elf_tdata (abfd)->core_pid = pstat.pr_pid;
+ elf_tdata (abfd)->core->pid = pstat.pr_pid;
}
#if defined (HAVE_PSTATUS32_T)
else if (note->descsz == sizeof (pstatus32_t))
memcpy (&pstat, note->descdata, sizeof (pstat));
- elf_tdata (abfd)->core_pid = pstat.pr_pid;
+ elf_tdata (abfd)->core->pid = pstat.pr_pid;
}
#endif
/* Could grab some more details from the "representative"
memcpy (&lwpstat, note->descdata, sizeof (lwpstat));
- elf_tdata (abfd)->core_lwpid = lwpstat.pr_lwpid;
+ elf_tdata (abfd)->core->lwpid = lwpstat.pr_lwpid;
/* Do not overwrite the core signal if it has already been set by
another thread. */
- if (elf_tdata (abfd)->core_signal == 0)
- elf_tdata (abfd)->core_signal = lwpstat.pr_cursig;
+ if (elf_tdata (abfd)->core->signal == 0)
+ elf_tdata (abfd)->core->signal = lwpstat.pr_cursig;
/* Make a ".reg/999" section. */
switch (type)
{
case 1 /* NOTE_INFO_PROCESS */:
- /* FIXME: need to add ->core_command. */
+ /* FIXME: need to add ->core->command. */
/* process_info.pid */
- elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 8);
+ elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 8);
/* process_info.signal */
- elf_tdata (abfd)->core_signal = bfd_get_32 (abfd, note->descdata + 12);
+ elf_tdata (abfd)->core->signal = bfd_get_32 (abfd, note->descdata + 12);
break;
case 2 /* NOTE_INFO_THREAD */:
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_S390_TDB:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_s390_tdb (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_ARM_TLS:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_aarch_tls (abfd, note);
+ else
+ return TRUE;
+
+ case NT_ARM_HW_BREAK:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_aarch_hw_break (abfd, note);
+ else
+ return TRUE;
+
+ case NT_ARM_HW_WATCH:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_aarch_hw_watch (abfd, note);
+ else
+ return TRUE;
+
case NT_PRPSINFO:
case NT_PSINFO:
if (bed->elf_backend_grok_psinfo)
return TRUE;
}
+
+ case NT_FILE:
+ return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.file",
+ note);
+
+ case NT_SIGINFO:
+ return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.siginfo",
+ note);
}
}
static bfd_boolean
elfobj_grok_gnu_build_id (bfd *abfd, Elf_Internal_Note *note)
{
- elf_tdata (abfd)->build_id_size = note->descsz;
- elf_tdata (abfd)->build_id = (bfd_byte *) bfd_alloc (abfd, note->descsz);
- if (elf_tdata (abfd)->build_id == NULL)
+ struct elf_obj_tdata *t;
+
+ if (note->descsz == 0)
return FALSE;
- memcpy (elf_tdata (abfd)->build_id, note->descdata, note->descsz);
+ t = elf_tdata (abfd);
+ t->build_id = bfd_alloc (abfd, sizeof (*t->build_id) - 1 + note->descsz);
+ if (t->build_id == NULL)
+ return FALSE;
+
+ t->build_id->size = note->descsz;
+ memcpy (t->build_id->data, note->descdata, note->descsz);
return TRUE;
}
elfcore_grok_netbsd_procinfo (bfd *abfd, Elf_Internal_Note *note)
{
/* Signal number at offset 0x08. */
- elf_tdata (abfd)->core_signal
+ elf_tdata (abfd)->core->signal
= bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x08);
/* Process ID at offset 0x50. */
- elf_tdata (abfd)->core_pid
+ elf_tdata (abfd)->core->pid
= bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x50);
/* Command name at 0x7c (max 32 bytes, including nul). */
- elf_tdata (abfd)->core_command
+ elf_tdata (abfd)->core->command
= _bfd_elfcore_strndup (abfd, note->descdata + 0x7c, 31);
return elfcore_make_note_pseudosection (abfd, ".note.netbsdcore.procinfo",
int lwp;
if (elfcore_netbsd_get_lwpid (note, &lwp))
- elf_tdata (abfd)->core_lwpid = lwp;
+ elf_tdata (abfd)->core->lwpid = lwp;
if (note->type == NT_NETBSDCORE_PROCINFO)
{
elfcore_grok_openbsd_procinfo (bfd *abfd, Elf_Internal_Note *note)
{
/* Signal number at offset 0x08. */
- elf_tdata (abfd)->core_signal
+ elf_tdata (abfd)->core->signal
= bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x08);
/* Process ID at offset 0x20. */
- elf_tdata (abfd)->core_pid
+ elf_tdata (abfd)->core->pid
= bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x20);
/* Command name at 0x48 (max 32 bytes, including nul). */
- elf_tdata (abfd)->core_command
+ elf_tdata (abfd)->core->command
= _bfd_elfcore_strndup (abfd, note->descdata + 0x48, 31);
return TRUE;
unsigned flags;
/* nto_procfs_status 'pid' field is at offset 0. */
- elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, (bfd_byte *) ddata);
+ elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, (bfd_byte *) ddata);
/* nto_procfs_status 'tid' field is at offset 4. Pass it back. */
*tid = bfd_get_32 (abfd, (bfd_byte *) ddata + 4);
/* nto_procfs_status 'what' field is at offset 14. */
if ((sig = bfd_get_16 (abfd, (bfd_byte *) ddata + 14)) > 0)
{
- elf_tdata (abfd)->core_signal = sig;
- elf_tdata (abfd)->core_lwpid = *tid;
+ elf_tdata (abfd)->core->signal = sig;
+ elf_tdata (abfd)->core->lwpid = *tid;
}
/* _DEBUG_FLAG_CURTID (current thread) is 0x80. Some cores
do not come from signals so we make sure we set the current
thread just in case. */
if (flags & 0x00000080)
- elf_tdata (abfd)->core_lwpid = *tid;
+ elf_tdata (abfd)->core->lwpid = *tid;
/* Make a ".qnx_core_status/%d" section. */
sprintf (buf, ".qnx_core_status/%ld", *tid);
sect->alignment_power = 2;
/* This is the current thread. */
- if (elf_tdata (abfd)->core_lwpid == tid)
+ if (elf_tdata (abfd)->core->lwpid == tid)
return elfcore_maybe_make_sect (abfd, base, sect);
return TRUE;
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_linux_prpsinfo32
+ (bfd *abfd, char *buf, int *bufsiz,
+ const struct elf_internal_linux_prpsinfo *prpsinfo)
+{
+ struct elf_external_linux_prpsinfo32 data;
+
+ memset (&data, 0, sizeof (data));
+ LINUX_PRPSINFO32_SWAP_FIELDS (abfd, prpsinfo, data);
+
+ return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO,
+ &data, sizeof (data));
+}
+
+char *
+elfcore_write_linux_prpsinfo64
+ (bfd *abfd, char *buf, int *bufsiz,
+ const struct elf_internal_linux_prpsinfo *prpsinfo)
+{
+ struct elf_external_linux_prpsinfo64 data;
+
+ memset (&data, 0, sizeof (data));
+ LINUX_PRPSINFO64_SWAP_FIELDS (abfd, prpsinfo, data);
+
+ return elfcore_write_note (abfd, buf, bufsiz,
+ "CORE", NT_PRPSINFO, &data, sizeof (data));
+}
+
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_s390_tdb (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *s390_tdb,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_S390_TDB, s390_tdb, 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_aarch_tls (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *aarch_tls,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_ARM_TLS, aarch_tls, size);
+}
+
+char *
+elfcore_write_aarch_hw_break (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *aarch_hw_break,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_ARM_HW_BREAK, aarch_hw_break, size);
+}
+
+char *
+elfcore_write_aarch_hw_watch (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *aarch_hw_watch,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_ARM_HW_WATCH, aarch_hw_watch, 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-s390-tdb") == 0)
+ return elfcore_write_s390_tdb (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-arm-vfp") == 0)
+ return elfcore_write_arm_vfp (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-aarch-tls") == 0)
+ return elfcore_write_aarch_tls (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-aarch-hw-break") == 0)
+ return elfcore_write_aarch_hw_break (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-aarch-hw-watch") == 0)
+ return elfcore_write_aarch_hw_watch (abfd, buf, bufsiz, data, size);
return NULL;
}
}
enum elf_reloc_type_class
-_bfd_elf_reloc_type_class (const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED)
+_bfd_elf_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ const asection *rel_sec ATTRIBUTE_UNUSED,
+ const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED)
{
return reloc_class_normal;
}
+ 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)
(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);
SEC_IS_COMMON, NULL, "LARGE_COMMON", 0);
void
-_bfd_elf_set_osabi (bfd * abfd,
- struct bfd_link_info * link_info ATTRIBUTE_UNUSED)
+_bfd_elf_post_process_headers (bfd * abfd,
+ struct bfd_link_info * link_info ATTRIBUTE_UNUSED)
{
Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */
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
+ 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_gnu_symbols)
- i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;
+ 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;
+}