/* ELF executable support for BFD.
- Copyright 1993, 94, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
+ Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
static boolean elf_map_symbols PARAMS ((bfd *));
static bfd_size_type get_program_header_size PARAMS ((bfd *));
static boolean elfcore_read_notes PARAMS ((bfd *, bfd_vma, bfd_vma));
+static boolean elf_find_function PARAMS ((bfd *, asection *, asymbol **,
+ bfd_vma, const char **,
+ const char **));
+static int elfcore_make_pid PARAMS ((bfd *));
+static boolean elfcore_maybe_make_sect PARAMS ((bfd *, char *, asection *));
+static boolean elfcore_make_note_pseudosection PARAMS ((bfd *, char *,
+ Elf_Internal_Note *));
+static boolean elfcore_grok_prfpreg PARAMS ((bfd *, Elf_Internal_Note *));
+static boolean elfcore_grok_prxfpreg PARAMS ((bfd *, Elf_Internal_Note *));
+static boolean elfcore_grok_note PARAMS ((bfd *, Elf_Internal_Note *));
/* Swap version information in and out. The version information is
currently size independent. If that ever changes, this code will
/* Read a specified number of bytes at a specified offset in an ELF
file, into a newly allocated buffer, and return a pointer to the
- buffer. */
+ buffer. */
static char *
elf_read (abfd, offset, size)
- bfd * abfd;
+ bfd *abfd;
long offset;
unsigned int size;
{
boolean
bfd_elf_mkobject (abfd)
- bfd * abfd;
+ bfd *abfd;
{
- /* this just does initialization */
- /* coff_mkobject zalloc's space for tdata.coff_obj_data ... */
+ /* This just does initialization. */
+ /* coff_mkobject zalloc's space for tdata.coff_obj_data ... */
elf_tdata (abfd) = (struct elf_obj_tdata *)
bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
if (elf_tdata (abfd) == 0)
return false;
- /* since everything is done at close time, do we need any
- initialization? */
+ /* Since everything is done at close time, do we need any
+ initialization? */
return true;
}
boolean
bfd_elf_mkcorefile (abfd)
- bfd * abfd;
+ bfd *abfd;
{
- /* I think this can be done just like an object file. */
+ /* I think this can be done just like an object file. */
return bfd_elf_mkobject (abfd);
}
char *
bfd_elf_get_str_section (abfd, shindex)
- bfd * abfd;
+ bfd *abfd;
unsigned int shindex;
{
Elf_Internal_Shdr **i_shdrp;
shstrtab = (char *) i_shdrp[shindex]->contents;
if (shstrtab == NULL)
{
- /* No cached one, attempt to read, and cache what we read. */
+ /* No cached one, attempt to read, and cache what we read. */
offset = i_shdrp[shindex]->sh_offset;
shstrtabsize = i_shdrp[shindex]->sh_size;
shstrtab = elf_read (abfd, offset, shstrtabsize);
char *
bfd_elf_string_from_elf_section (abfd, shindex, strindex)
- bfd * abfd;
+ bfd *abfd;
unsigned int shindex;
unsigned int strindex;
{
{
asection *newsect;
flagword flags;
+ struct elf_backend_data *bed;
if (hdr->bfd_section != NULL)
{
flags |= SEC_CODE;
else if ((flags & SEC_LOAD) != 0)
flags |= SEC_DATA;
+ if ((hdr->sh_flags & SHF_MERGE) != 0)
+ {
+ flags |= SEC_MERGE;
+ newsect->entsize = hdr->sh_entsize;
+ if ((hdr->sh_flags & SHF_STRINGS) != 0)
+ flags |= SEC_STRINGS;
+ }
/* The debugging sections appear to be recognized only by name, not
any sort of flag. */
{
- const char * debug_sec_names [] =
+ static const char *debug_sec_names [] =
{
".debug",
".gnu.linkonce.wi.",
if (strncmp (name, ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) == 0)
flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
+ bed = get_elf_backend_data (abfd);
+ if (bed->elf_backend_section_flags)
+ if (! bed->elf_backend_section_flags (&flags, hdr))
+ return false;
+
if (! bfd_set_section_flags (abfd, newsect, flags))
return false;
struct elf_internal_shdr *
bfd_elf_find_section (abfd, name)
- bfd * abfd;
+ bfd *abfd;
char *name;
{
Elf_Internal_Shdr **i_shdrp;
function. It just short circuits the reloc if producing
relocateable output against an external symbol. */
-/*ARGSUSED*/
bfd_reloc_status_type
bfd_elf_generic_reloc (abfd,
reloc_entry,
return bfd_reloc_continue;
}
\f
+/* Finish SHF_MERGE section merging. */
+
+boolean
+_bfd_elf_merge_sections (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ if (elf_hash_table (info)->merge_info)
+ _bfd_merge_sections (abfd, elf_hash_table (info)->merge_info);
+ return true;
+}
+\f
/* Print out the program headers. */
boolean
break;
case bfd_print_symbol_all:
{
- CONST char *section_name;
- CONST char *name = NULL;
+ const char *section_name;
+ const char *name = NULL;
struct elf_backend_data *bed;
unsigned char st_other;
-
+
section_name = symbol->section ? symbol->section->name : "(*none*)";
bed = get_elf_backend_data (abfd);
if (bed->elf_backend_print_symbol_all)
- name = (*bed->elf_backend_print_symbol_all) (abfd, filep, symbol);
+ name = (*bed->elf_backend_print_symbol_all) (abfd, filep, symbol);
if (name == NULL)
{
/* If the st_other field is not zero, print it. */
st_other = ((elf_symbol_type *) symbol)->internal_elf_sym.st_other;
-
+
switch (st_other)
{
case 0: break;
struct elf_link_hash_entry *h;
{
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
- h->dynindx = -1;
h->plt.offset = (bfd_vma) -1;
+ if ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+ h->dynindx = -1;
}
/* Initialize an ELF linker hash table. */
table->runpath = NULL;
table->hgot = NULL;
table->stab_info = NULL;
+ table->merge_info = NULL;
table->dynlocal = NULL;
return _bfd_link_hash_table_init (&table->root, abfd, newfunc);
}
\f
/* ELF .o/exec file reading */
-/* Create a new bfd section from an ELF section header. */
+/* Create a new bfd section from an ELF section header. */
boolean
bfd_section_from_shdr (abfd, shindex)
/* If this reloc section does not use the main symbol table we
don't treat it as a reloc section. BFD can't adequately
represent such a section, so at least for now, we don't
- try. We just present it as a normal section. We also
+ try. We just present it as a normal section. We also
can't use it as a reloc section if it points to the null
- section. */
+ section. */
if (hdr->sh_link != elf_onesymtab (abfd) || hdr->sh_info == SHN_UNDEF)
return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
}
*hdr2 = *hdr;
elf_elfsections (abfd)[shindex] = hdr2;
- target_sect->reloc_count += hdr->sh_size / hdr->sh_entsize;
+ target_sect->reloc_count += NUM_SHDR_ENTRIES (hdr);
target_sect->flags |= SEC_RELOC;
target_sect->relocation = NULL;
target_sect->rel_filepos = hdr->sh_offset;
sec->used_by_bfd = (PTR) sdata;
/* Indicate whether or not this section should use RELA relocations. */
- sdata->use_rela_p
+ sdata->use_rela_p
= get_elf_backend_data (abfd)->default_use_rela_p;
return true;
if (hdr->p_flags & PF_X)
{
/* FIXME: all we known is that it has execute PERMISSION,
- may be data. */
+ may be data. */
newsect->flags |= SEC_CODE;
}
}
default:
/* Check for any processor-specific program segment types.
- If no handler for them, default to making "segment" sections. */
+ If no handler for them, default to making "segment" sections. */
bed = get_elf_backend_data (abfd);
if (bed->elf_backend_section_from_phdr)
return (*bed->elf_backend_section_from_phdr) (abfd, hdr, index);
/* Set up an ELF internal section header for a section. */
-/*ARGSUSED*/
static void
elf_fake_sections (abfd, asect, failedptrarg)
bfd *abfd;
|| this_hdr->sh_info == elf_tdata (abfd)->cverrefs);
}
else if ((asect->flags & SEC_ALLOC) != 0
- && (asect->flags & SEC_LOAD) != 0)
- this_hdr->sh_type = SHT_PROGBITS;
- else if ((asect->flags & SEC_ALLOC) != 0
- && ((asect->flags & SEC_LOAD) == 0))
+ && ((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0))
this_hdr->sh_type = SHT_NOBITS;
else
- {
- /* Who knows? */
- this_hdr->sh_type = SHT_PROGBITS;
- }
+ this_hdr->sh_type = SHT_PROGBITS;
if ((asect->flags & SEC_ALLOC) != 0)
this_hdr->sh_flags |= SHF_ALLOC;
this_hdr->sh_flags |= SHF_WRITE;
if ((asect->flags & SEC_CODE) != 0)
this_hdr->sh_flags |= SHF_EXECINSTR;
+ if ((asect->flags & SEC_MERGE) != 0)
+ {
+ this_hdr->sh_flags |= SHF_MERGE;
+ this_hdr->sh_entsize = asect->entsize;
+ if ((asect->flags & SEC_STRINGS) != 0)
+ this_hdr->sh_flags |= SHF_STRINGS;
+ }
/* Check for processor-specific section types. */
if (bed->elf_backend_fake_sections)
/* If the section has relocs, set up a section header for the
SHT_REL[A] section. If two relocation sections are required for
this section, it is up to the processor-specific back-end to
- create the other. */
+ create the other. */
if ((asect->flags & SEC_RELOC) != 0
- && !_bfd_elf_init_reloc_shdr (abfd,
+ && !_bfd_elf_init_reloc_shdr (abfd,
&elf_section_data (asect)->rel_hdr,
- asect,
+ asect,
elf_section_data (asect)->use_rela_p))
*failedptr = true;
}
for (idx = 0; idx < symcount; idx++)
{
sym = syms[idx];
-
+
if ((sym->flags & BSF_SECTION_SYM) != 0
&& sym->value == 0)
{
{
if (sec->output_offset != 0)
continue;
-
+
sec = sec->output_section;
/* Empty sections in the input files may have had a section
if (TOEND (sec1))
{
if (TOEND (sec2))
- return sec1->target_index - sec2->target_index;
+ {
+ /* If the indicies are the same, do not return 0
+ here, but continue to try the next comparison. */
+ if (sec1->target_index - sec2->target_index != 0)
+ return sec1->target_index - sec2->target_index;
+ }
else
return 1;
}
-
- if (TOEND (sec2))
+ else if (TOEND (sec2))
return -1;
#undef TOEND
- /* Sort by size, to put zero sized sections before others at the
- same address. */
+ /* Sort by size, to put zero sized sections
+ before others at the same address. */
if (sec1->_raw_size < sec2->_raw_size)
return -1;
i_ehdrp->e_machine = EM_S370;
break;
case bfd_arch_i386:
- i_ehdrp->e_machine = EM_386;
+ if (bfd_get_arch_size (abfd) == 64)
+ i_ehdrp->e_machine = EM_X86_64;
+ else
+ i_ehdrp->e_machine = EM_386;
break;
case bfd_arch_ia64:
i_ehdrp->e_machine = EM_IA_64;
case bfd_arch_m68hc12:
i_ehdrp->e_machine = EM_68HC12;
break;
+ case bfd_arch_s390:
+ i_ehdrp->e_machine = EM_S390;
+ break;
case bfd_arch_m68k:
i_ehdrp->e_machine = EM_68K;
break;
case 0: i_ehdrp->e_machine = EM_CYGNUS_V850; break;
}
break;
- case bfd_arch_arc:
+ case bfd_arch_arc:
i_ehdrp->e_machine = EM_CYGNUS_ARC;
break;
- case bfd_arch_arm:
+ case bfd_arch_arm:
i_ehdrp->e_machine = EM_ARM;
break;
case bfd_arch_m32r:
case bfd_arch_cris:
i_ehdrp->e_machine = EM_CRIS;
break;
- /* also note that EM_M32, AT&T WE32100 is unknown to bfd */
+ case bfd_arch_openrisc:
+ i_ehdrp->e_machine = EM_OPENRISC;
+ break;
+ /* Also note that EM_M32, AT&T WE32100 is unknown to bfd. */
default:
i_ehdrp->e_machine = EM_NONE;
}
i_ehdrp->e_version = bed->s->ev_current;
i_ehdrp->e_ehsize = bed->s->sizeof_ehdr;
- /* no program header, for now. */
+ /* No program header, for now. */
i_ehdrp->e_phoff = 0;
i_ehdrp->e_phentsize = 0;
i_ehdrp->e_phnum = 0;
- /* each bfd section is section header entry */
+ /* Each bfd section is section header entry. */
i_ehdrp->e_entry = bfd_get_start_address (abfd);
i_ehdrp->e_shentsize = bed->s->sizeof_shdr;
- /* if we're building an executable, we'll need a program header table */
+ /* If we're building an executable, we'll need a program header table. */
if (abfd->flags & EXEC_P)
{
- /* it all happens later */
+ /* It all happens later. */
#if 0
i_ehdrp->e_phentsize = sizeof (Elf_External_Phdr);
/* elf_build_phdrs() returns a (NULL-terminated) array of
- Elf_Internal_Phdrs */
+ Elf_Internal_Phdrs. */
i_phdrp = elf_build_phdrs (abfd, i_ehdrp, i_shdrp, &i_ehdrp->e_phnum);
i_ehdrp->e_phoff = outbase;
outbase += i_ehdrp->e_phentsize * i_ehdrp->e_phnum;
_bfd_elf_assign_file_positions_for_relocs (abfd);
- /* After writing the headers, we need to write the sections too... */
+ /* After writing the headers, we need to write the sections too... */
for (count = 1; count < i_ehdrp->e_shnum; count++)
{
if (bed->elf_backend_section_processing)
_bfd_elf_write_corefile_contents (abfd)
bfd *abfd;
{
- /* Hopefully this can be done just like an object file. */
+ /* Hopefully this can be done just like an object file. */
return _bfd_elf_write_object_contents (abfd);
}
-/* given a section, search the header to find them... */
+
+/* Given a section, search the header to find them. */
+
int
_bfd_elf_section_from_bfd_section (abfd, asect)
bfd *abfd;
struct elf_segment_map * phdr_adjust_seg = NULL;
unsigned int phdr_adjust_num = 0;
- if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return true;
iehdr = elf_elfheader (ibfd);
map_first = NULL;
- pointer_to_map = & map_first;
+ pointer_to_map = &map_first;
num_segments = elf_elfheader (ibfd)->e_phnum;
maxpagesize = get_elf_backend_data (obfd)->maxpagesize;
(section->vma >= segment->p_vaddr \
&& (section->vma + section->_raw_size) \
<= (SEGMENT_END (segment, segment->p_vaddr)))
-
+
/* Returns true if the given section is contained within
the given segment. LMA addresses are compared. */
#define IS_CONTAINED_BY_LMA(section, segment, base) \
&& (section->lma + section->_raw_size) \
<= SEGMENT_END (segment, base))
- /* Special case: corefile "NOTE" section containing regs, prpsinfo etc. */
+ /* Special case: corefile "NOTE" section containing regs, prpsinfo etc. */
#define IS_COREFILE_NOTE(p, s) \
(p->p_type == PT_NOTE \
&& bfd_get_format (ibfd) == bfd_core \
parameters to objcopy. */
for (i = 0, segment = elf_tdata (ibfd)->phdr;
i < num_segments;
- i ++, segment ++)
+ i++, segment++)
{
unsigned int j;
- Elf_Internal_Phdr * segment2;
+ Elf_Internal_Phdr *segment2;
if (segment->p_type != PT_LOAD)
continue;
-
+
/* Determine if this segment overlaps any previous segments. */
- for (j = 0, segment2 = elf_tdata (ibfd)->phdr; j < i; j ++, segment2 ++)
+ for (j = 0, segment2 = elf_tdata (ibfd)->phdr; j < i; j++, segment2 ++)
{
bfd_signed_vma extra_length;
-
+
if (segment2->p_type != PT_LOAD
|| ! SEGMENT_OVERLAPS (segment, segment2))
continue;
-
+
/* Merge the two segments together. */
if (segment2->p_vaddr < segment->p_vaddr)
{
- /* Extend SEGMENT2 to include SEGMENT and then delete SEGMENT. */
+ /* Extend SEGMENT2 to include SEGMENT and then delete
+ SEGMENT. */
extra_length =
SEGMENT_END (segment, segment->p_vaddr)
- SEGMENT_END (segment2, segment2->p_vaddr);
-
+
if (extra_length > 0)
{
segment2->p_memsz += extra_length;
segment2->p_filesz += extra_length;
}
-
+
segment->p_type = PT_NULL;
-
+
/* Since we have deleted P we must restart the outer loop. */
i = 0;
segment = elf_tdata (ibfd)->phdr;
}
else
{
- /* Extend SEGMENT to include SEGMENT2 and then delete SEGMENT2. */
+ /* Extend SEGMENT to include SEGMENT2 and then delete
+ SEGMENT2. */
extra_length =
SEGMENT_END (segment2, segment2->p_vaddr)
- SEGMENT_END (segment, segment->p_vaddr);
-
+
if (extra_length > 0)
{
segment->p_memsz += extra_length;
segment->p_filesz += extra_length;
}
-
+
segment2->p_type = PT_NULL;
}
}
}
-
+
/* The second scan attempts to assign sections to segments. */
for (i = 0, segment = elf_tdata (ibfd)->phdr;
i < num_segments;
if (segment->p_type == PT_NULL)
continue;
-
+
/* Compute how many sections might be placed into this segment. */
section_count = 0;
for (section = ibfd->sections; section != NULL; section = section->next)
if (INCLUDE_SECTION_IN_SEGMENT (section, segment))
- ++ section_count;
+ ++section_count;
/* Allocate a segment map big enough to contain all of the
sections we have selected. */
&& (segment->p_offset + segment->p_filesz
>= ((bfd_vma) iehdr->e_phoff
+ iehdr->e_phnum * iehdr->e_phentsize)));
-
+
if (segment->p_type == PT_LOAD && map->includes_phdrs)
phdr_included = true;
}
bfd_get_filename (ibfd));
map->count = 0;
- * pointer_to_map = map;
- pointer_to_map = & map->next;
+ *pointer_to_map = map;
+ pointer_to_map = &map->next;
continue;
}
the list of built segments and carry on to process the next
program header in the input BFD. */
map->count = section_count;
- * pointer_to_map = map;
- pointer_to_map = & map->next;
+ *pointer_to_map = map;
+ pointer_to_map = &map->next;
free (sections);
continue;
output_section = section->output_section;
BFD_ASSERT (output_section != NULL);
-
+
if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr)
|| IS_COREFILE_NOTE (segment, section))
{
BFD_ASSERT (map->count > 0);
/* Add the current segment to the list of built segments. */
- * pointer_to_map = map;
- pointer_to_map = & map->next;
+ *pointer_to_map = map;
+ pointer_to_map = &map->next;
if (isec < section_count)
{
if (phdr_adjust_seg != NULL)
{
unsigned int count;
-
+
for (count = 0, map = map_first; map != NULL; map = map->next)
- count ++;
+ count++;
if (count > phdr_adjust_num)
phdr_adjust_seg->p_paddr
-= (count - phdr_adjust_num) * iehdr->e_phentsize;
}
-
+
#if 0
- /* Final Step: Sort the segments into ascending order of physical address. */
+ /* Final Step: Sort the segments into ascending order of physical
+ address. */
if (map_first != NULL)
{
- struct elf_segment_map * prev;
+ struct elf_segment_map *prev;
prev = map_first;
for (map = map_first->next; map != NULL; prev = map, map = map->next)
if (!elf_map_symbols (abfd))
return false;
- /* Dump out the symtabs. */
+ /* Dump out the symtabs. */
{
int symcount = bfd_get_symcount (abfd);
asymbol **syms = bfd_get_outsymbols (abfd);
flagword flags = syms[idx]->flags;
int type;
- if (flags & BSF_SECTION_SYM)
- /* Section symbols have no names. */
- sym.st_name = 0;
+ if ((flags & (BSF_SECTION_SYM | BSF_GLOBAL)) == BSF_SECTION_SYM)
+ {
+ /* Local section symbols have no name. */
+ sym.st_name = 0;
+ }
else
{
sym.st_name = (unsigned long) _bfd_stringtab_add (stt,
type = (*bed->elf_backend_get_symbol_type) (&type_ptr->internal_elf_sym, type);
if (flags & BSF_SECTION_SYM)
- sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
+ {
+ if (flags & BSF_GLOBAL)
+ sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
+ else
+ 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, type);
else if (bfd_is_und_section (syms[idx]->section))
{
_bfd_elf_swap_verdef_in (abfd, everdef, &iverdefmem);
- if ((iverdefmem.vd_ndx & VERSYM_VERSION) > maxidx)
- maxidx = iverdefmem.vd_ndx & VERSYM_VERSION;
+ if ((iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION)) > maxidx)
+ maxidx = iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION);
everdef = ((Elf_External_Verdef *)
((bfd_byte *) everdef + iverdefmem.vd_next));
return bfd_default_set_arch_mach (abfd, arch, machine);
}
-/* Find the nearest line to a particular section and offset, for error
- reporting. */
+/* Find the function to a particular section and offset,
+ for error reporting. */
-boolean
-_bfd_elf_find_nearest_line (abfd,
- section,
- symbols,
- offset,
- filename_ptr,
- functionname_ptr,
- line_ptr)
- bfd *abfd;
+static boolean
+elf_find_function (abfd, section, symbols, offset,
+ filename_ptr, functionname_ptr)
+ bfd *abfd ATTRIBUTE_UNUSED;
asection *section;
asymbol **symbols;
bfd_vma offset;
- CONST char **filename_ptr;
- CONST char **functionname_ptr;
- unsigned int *line_ptr;
+ const char **filename_ptr;
+ const char **functionname_ptr;
{
- boolean found;
const char *filename;
asymbol *func;
bfd_vma low_func;
asymbol **p;
- if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset,
- filename_ptr, functionname_ptr,
- line_ptr))
- return true;
-
- if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
- filename_ptr, functionname_ptr,
- line_ptr, 0))
- return true;
-
- if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
- &found, filename_ptr,
- functionname_ptr, line_ptr,
- &elf_tdata (abfd)->line_info))
- return false;
- if (found)
- return true;
-
- if (symbols == NULL)
- return false;
-
filename = NULL;
func = NULL;
low_func = 0;
if (func == NULL)
return false;
- *filename_ptr = filename;
- *functionname_ptr = bfd_asymbol_name (func);
+ if (filename_ptr)
+ *filename_ptr = filename;
+ if (functionname_ptr)
+ *functionname_ptr = bfd_asymbol_name (func);
+
+ return true;
+}
+
+/* Find the nearest line to a particular section and offset,
+ for error reporting. */
+
+boolean
+_bfd_elf_find_nearest_line (abfd, section, symbols, offset,
+ filename_ptr, functionname_ptr, line_ptr)
+ bfd *abfd;
+ asection *section;
+ asymbol **symbols;
+ bfd_vma offset;
+ const char **filename_ptr;
+ const char **functionname_ptr;
+ unsigned int *line_ptr;
+{
+ boolean found;
+
+ if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset,
+ filename_ptr, functionname_ptr,
+ line_ptr))
+ {
+ if (!*functionname_ptr)
+ elf_find_function (abfd, section, symbols, offset,
+ *filename_ptr ? NULL : filename_ptr,
+ functionname_ptr);
+
+ return true;
+ }
+
+ if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
+ filename_ptr, functionname_ptr,
+ line_ptr, 0,
+ &elf_tdata (abfd)->dwarf2_find_line_info))
+ {
+ if (!*functionname_ptr)
+ elf_find_function (abfd, section, symbols, offset,
+ *filename_ptr ? NULL : filename_ptr,
+ functionname_ptr);
+
+ return true;
+ }
+
+ if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
+ &found, filename_ptr,
+ functionname_ptr, line_ptr,
+ &elf_tdata (abfd)->line_info))
+ return false;
+ if (found)
+ return true;
+
+ if (symbols == NULL)
+ return false;
+
+ if (! elf_find_function (abfd, section, symbols, offset,
+ filename_ptr, functionname_ptr))
+ return false;
+
*line_ptr = 0;
return true;
}
bfd *abfd;
arelent *areloc;
{
- /* Check whether we really have an ELF howto. */
+ /* Check whether we really have an ELF howto. */
if ((*areloc->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec)
{
reloc_howto_type *howto;
/* Alien reloc: Try to determine its type to replace it with an
- equivalent ELF reloc. */
+ equivalent ELF reloc. */
if (areloc->howto->pc_relative)
{
{
return bfd_reloc_ok;
}
-
\f
/* Elf core file support. Much of this only works on native
toolchains, since we rely on knowing the
machine-dependent procfs structure in order to pick
- out details about the corefile. */
+ out details about the corefile. */
#ifdef HAVE_SYS_PROCFS_H
# include <sys/procfs.h>
#endif
-
-/* Define offsetof for those systems which lack it. */
+/* Define offsetof for those systems which lack it. */
#ifndef offsetof
# define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
#endif
-
-/* FIXME: this is kinda wrong, but it's what gdb wants. */
+/* FIXME: this is kinda wrong, but it's what gdb wants. */
static int
elfcore_make_pid (abfd)
- bfd* abfd;
+ bfd *abfd;
{
return ((elf_tdata (abfd)->core_lwpid << 16)
+ (elf_tdata (abfd)->core_pid));
}
-
/* If there isn't a section called NAME, make one, using
data from SECT. Note, this function will generate a
reference to NAME, so you shouldn't deallocate or
- overwrite it. */
+ overwrite it. */
static boolean
elfcore_maybe_make_sect (abfd, name, sect)
- bfd* abfd;
- char* name;
- asection* sect;
+ bfd *abfd;
+ char *name;
+ asection *sect;
{
- asection* sect2;
+ asection *sect2;
if (bfd_get_section_by_name (abfd, name) != NULL)
return true;
return true;
}
+/* Create a pseudosection containing SIZE bytes at FILEPOS. This
+ actually creates up to two pseudosections:
+ - For the single-threaded case, a section named NAME, unless
+ such a section already exists.
+ - For the multi-threaded case, a section named "NAME/PID", where
+ PID is elfcore_make_pid (abfd).
+ Both pseudosections have identical contents. */
+boolean
+_bfd_elfcore_make_pseudosection (abfd, name, size, filepos)
+ bfd *abfd;
+ char *name;
+ int size;
+ int filepos;
+{
+ char buf[100];
+ char *threaded_name;
+ asection *sect;
+
+ /* Build the section name. */
+
+ sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd));
+ threaded_name = bfd_alloc (abfd, strlen (buf) + 1);
+ if (threaded_name == NULL)
+ return false;
+ strcpy (threaded_name, buf);
+
+ sect = bfd_make_section (abfd, threaded_name);
+ if (sect == NULL)
+ return false;
+ sect->_raw_size = size;
+ sect->filepos = filepos;
+ sect->flags = SEC_HAS_CONTENTS;
+ sect->alignment_power = 2;
+
+ return elfcore_maybe_make_sect (abfd, name, sect);
+}
/* prstatus_t exists on:
solaris 2.5+
*/
#if defined (HAVE_PRSTATUS_T)
+static boolean elfcore_grok_prstatus PARAMS ((bfd *, Elf_Internal_Note *));
+
static boolean
elfcore_grok_prstatus (abfd, note)
- bfd* abfd;
- Elf_Internal_Note* note;
+ bfd *abfd;
+ Elf_Internal_Note *note;
{
- char buf[100];
- char* name;
- asection* sect;
int raw_size;
int offset;
return true;
}
- /* Make a ".reg/999" section. */
-
- sprintf (buf, ".reg/%d", elfcore_make_pid (abfd));
- name = bfd_alloc (abfd, strlen (buf) + 1);
- if (name == NULL)
- return false;
- strcpy (name, buf);
-
- sect = bfd_make_section (abfd, name);
- if (sect == NULL)
- return false;
-
- sect->_raw_size = raw_size;
- sect->filepos = note->descpos + offset;
-
- sect->flags = SEC_HAS_CONTENTS;
- sect->alignment_power = 2;
-
- if (! elfcore_maybe_make_sect (abfd, ".reg", sect))
- return false;
-
- return true;
+ /* Make a ".reg/999" section and a ".reg" section. */
+ return _bfd_elfcore_make_pseudosection (abfd, ".reg",
+ raw_size, note->descpos + offset);
}
#endif /* defined (HAVE_PRSTATUS_T) */
-
-/* Create a pseudosection containing the exact contents of NOTE. This
- actually creates up to two pseudosections:
- - For the single-threaded case, a section named NAME, unless
- such a section already exists.
- - For the multi-threaded case, a section named "NAME/PID", where
- PID is elfcore_make_pid (abfd).
- Both pseudosections have identical contents: the contents of NOTE. */
-
+/* Create a pseudosection containing the exact contents of NOTE. */
static boolean
elfcore_make_note_pseudosection (abfd, name, note)
- bfd* abfd;
+ bfd *abfd;
char *name;
- Elf_Internal_Note* note;
+ Elf_Internal_Note *note;
{
- char buf[100];
- char *threaded_name;
- asection* sect;
-
- /* Build the section name. */
-
- sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd));
- threaded_name = bfd_alloc (abfd, strlen (buf) + 1);
- if (threaded_name == NULL)
- return false;
- strcpy (threaded_name, buf);
-
- sect = bfd_make_section (abfd, threaded_name);
- if (sect == NULL)
- return false;
- sect->_raw_size = note->descsz;
- sect->filepos = note->descpos;
- sect->flags = SEC_HAS_CONTENTS;
- sect->alignment_power = 2;
-
- if (! elfcore_maybe_make_sect (abfd, name, sect))
- return false;
-
- return true;
+ return _bfd_elfcore_make_pseudosection (abfd, name,
+ note->descsz, note->descpos);
}
-
/* There isn't a consistent prfpregset_t across platforms,
but it doesn't matter, because we don't have to pick this
- data structure apart. */
+ data structure apart. */
+
static boolean
elfcore_grok_prfpreg (abfd, note)
- bfd* abfd;
- Elf_Internal_Note* note;
+ bfd *abfd;
+ Elf_Internal_Note *note;
{
return elfcore_make_note_pseudosection (abfd, ".reg2", note);
}
-
/* Linux dumps the Intel SSE regs in a note named "LINUX" with a note
type of 5 (NT_PRXFPREG). Just include the whole note's contents
literally. */
+
static boolean
elfcore_grok_prxfpreg (abfd, note)
- bfd* abfd;
- Elf_Internal_Note* note;
+ bfd *abfd;
+ Elf_Internal_Note *note;
{
return elfcore_make_note_pseudosection (abfd, ".reg-xfp", note);
}
-
#if defined (HAVE_PRPSINFO_T)
typedef prpsinfo_t elfcore_psinfo_t;
#if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */
#endif
#endif
-
-#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
-
/* return a malloc'ed copy of a string at START which is at
most MAX bytes long, possibly without a terminating '\0'.
- the copy will always have a terminating '\0'. */
+ the copy will always have a terminating '\0'. */
-static char*
-elfcore_strndup (abfd, start, max)
- bfd* abfd;
- char* start;
+char *
+_bfd_elfcore_strndup (abfd, start, max)
+ bfd *abfd;
+ char *start;
int max;
{
- char* dup;
- char* end = memchr (start, '\0', max);
+ char *dup;
+ char *end = memchr (start, '\0', max);
int len;
if (end == NULL)
return dup;
}
+#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
+static boolean elfcore_grok_psinfo PARAMS ((bfd *, Elf_Internal_Note *));
+
static boolean
elfcore_grok_psinfo (abfd, note)
- bfd* abfd;
- Elf_Internal_Note* note;
+ bfd *abfd;
+ Elf_Internal_Note *note;
{
if (note->descsz == sizeof (elfcore_psinfo_t))
{
memcpy (&psinfo, note->descdata, sizeof (psinfo));
elf_tdata (abfd)->core_program
- = elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname));
+ = _bfd_elfcore_strndup (abfd, psinfo.pr_fname,
+ sizeof (psinfo.pr_fname));
elf_tdata (abfd)->core_command
- = elfcore_strndup (abfd, psinfo.pr_psargs, sizeof (psinfo.pr_psargs));
+ = _bfd_elfcore_strndup (abfd, psinfo.pr_psargs,
+ sizeof (psinfo.pr_psargs));
}
#if defined (HAVE_PRPSINFO32_T) || defined (HAVE_PSINFO32_T)
else if (note->descsz == sizeof (elfcore_psinfo32_t))
memcpy (&psinfo, note->descdata, sizeof (psinfo));
elf_tdata (abfd)->core_program
- = elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname));
+ = _bfd_elfcore_strndup (abfd, psinfo.pr_fname,
+ sizeof (psinfo.pr_fname));
elf_tdata (abfd)->core_command
- = elfcore_strndup (abfd, psinfo.pr_psargs, sizeof (psinfo.pr_psargs));
+ = _bfd_elfcore_strndup (abfd, psinfo.pr_psargs,
+ sizeof (psinfo.pr_psargs));
}
#endif
/* Note that for some reason, a spurious space is tacked
onto the end of the args in some (at least one anyway)
- implementations, so strip it off if it exists. */
+ 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] == ' ')
}
#endif /* defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T) */
-
#if defined (HAVE_PSTATUS_T)
static boolean
elfcore_grok_pstatus (abfd, note)
- bfd* abfd;
- Elf_Internal_Note* note;
+ bfd *abfd;
+ Elf_Internal_Note *note;
{
- if (note->descsz == sizeof (pstatus_t))
+ if (note->descsz == sizeof (pstatus_t)
+#if defined (HAVE_PXSTATUS_T)
+ || note->descsz == sizeof (pxstatus_t)
+#endif
+ )
{
pstatus_t pstat;
#endif
/* Could grab some more details from the "representative"
lwpstatus_t in pstat.pr_lwp, but we'll catch it all in an
- NT_LWPSTATUS note, presumably. */
+ NT_LWPSTATUS note, presumably. */
return true;
}
#endif /* defined (HAVE_PSTATUS_T) */
-
#if defined (HAVE_LWPSTATUS_T)
static boolean
elfcore_grok_lwpstatus (abfd, note)
- bfd* abfd;
- Elf_Internal_Note* note;
+ bfd *abfd;
+ Elf_Internal_Note *note;
{
lwpstatus_t lwpstat;
char buf[100];
- char* name;
- asection* sect;
+ char *name;
+ asection *sect;
- if (note->descsz != sizeof (lwpstat))
+ if (note->descsz != sizeof (lwpstat)
+#if defined (HAVE_LWPXSTATUS_T)
+ && note->descsz != sizeof (lwpxstatus_t)
+#endif
+ )
return true;
memcpy (&lwpstat, note->descdata, sizeof (lwpstat));
elf_tdata (abfd)->core_lwpid = lwpstat.pr_lwpid;
elf_tdata (abfd)->core_signal = lwpstat.pr_cursig;
- /* Make a ".reg/999" section. */
+ /* Make a ".reg/999" section. */
sprintf (buf, ".reg/%d", elfcore_make_pid (abfd));
name = bfd_alloc (abfd, strlen (buf) + 1);
sect->flags = SEC_HAS_CONTENTS;
sect->alignment_power = 2;
- if (!elfcore_maybe_make_sect (abfd, ".reg2", sect))
- return false;
-
- return true;
+ return elfcore_maybe_make_sect (abfd, ".reg2", sect);
}
#endif /* defined (HAVE_LWPSTATUS_T) */
#if defined (HAVE_WIN32_PSTATUS_T)
static boolean
elfcore_grok_win32pstatus (abfd, note)
- bfd * abfd;
- Elf_Internal_Note * note;
+ bfd *abfd;
+ Elf_Internal_Note *note;
{
char buf[30];
- char * name;
- asection * sect;
+ char *name;
+ asection *sect;
win32_pstatus_t pstatus;
if (note->descsz < sizeof (pstatus))
return true;
- memcpy (& pstatus, note->descdata, note->descsz);
-
- switch (pstatus.data_type)
+ memcpy (&pstatus, note->descdata, note->descsz);
+
+ switch (pstatus.data_type)
{
case NOTE_INFO_PROCESS:
/* FIXME: need to add ->core_command. */
elf_tdata (abfd)->core_signal = pstatus.data.process_info.signal;
elf_tdata (abfd)->core_pid = pstatus.data.process_info.pid;
- break ;
+ break;
case NOTE_INFO_THREAD:
/* Make a ".reg/999" section. */
sprintf (buf, ".reg/%d", pstatus.data.thread_info.tid);
-
+
name = bfd_alloc (abfd, strlen (buf) + 1);
if (name == NULL)
- return false;
-
+ return false;
+
strcpy (name, buf);
sect = bfd_make_section (abfd, name);
if (sect == NULL)
- return false;
-
+ return false;
+
sect->_raw_size = sizeof (pstatus.data.thread_info.thread_context);
sect->filepos = note->descpos + offsetof (struct win32_pstatus,
data.thread_info.thread_context);
case NOTE_INFO_MODULE:
/* Make a ".module/xxxxxxxx" section. */
- sprintf (buf, ".module/%08x" , pstatus.data.module_info.base_address);
-
+ sprintf (buf, ".module/%08x", pstatus.data.module_info.base_address);
+
name = bfd_alloc (abfd, strlen (buf) + 1);
if (name == NULL)
return false;
-
+
strcpy (name, buf);
sect = bfd_make_section (abfd, name);
-
+
if (sect == NULL)
return false;
-
+
sect->_raw_size = note->descsz;
sect->filepos = note->descpos;
sect->flags = SEC_HAS_CONTENTS;
static boolean
elfcore_grok_note (abfd, note)
- bfd* abfd;
- Elf_Internal_Note* note;
+ bfd *abfd;
+ Elf_Internal_Note *note;
{
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
switch (note->type)
{
default:
return true;
-#if defined (HAVE_PRSTATUS_T)
case NT_PRSTATUS:
+ if (bed->elf_backend_grok_prstatus)
+ if ((*bed->elf_backend_grok_prstatus) (abfd, note))
+ return true;
+#if defined (HAVE_PRSTATUS_T)
return elfcore_grok_prstatus (abfd, note);
+#else
+ return true;
#endif
#if defined (HAVE_PSTATUS_T)
return elfcore_grok_prfpreg (abfd, note);
#if defined (HAVE_WIN32_PSTATUS_T)
- case NT_WIN32PSTATUS:
+ case NT_WIN32PSTATUS:
return elfcore_grok_win32pstatus (abfd, note);
#endif
- case NT_PRXFPREG: /* Linux SSE extension */
+ case NT_PRXFPREG: /* Linux SSE extension */
if (note->namesz == 5
&& ! strcmp (note->namedata, "LINUX"))
return elfcore_grok_prxfpreg (abfd, note);
else
return true;
-#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
case NT_PRPSINFO:
case NT_PSINFO:
+ if (bed->elf_backend_grok_psinfo)
+ if ((*bed->elf_backend_grok_psinfo) (abfd, note))
+ return true;
+#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
return elfcore_grok_psinfo (abfd, note);
+#else
+ return true;
#endif
}
}
-
static boolean
elfcore_read_notes (abfd, offset, size)
- bfd* abfd;
+ bfd *abfd;
bfd_vma offset;
bfd_vma size;
{
- char* buf;
- char* p;
+ char *buf;
+ char *p;
if (size <= 0)
return true;
p = buf;
while (p < buf + size)
{
- /* FIXME: bad alignment assumption. */
- Elf_External_Note* xnp = (Elf_External_Note*) p;
+ /* FIXME: bad alignment assumption. */
+ Elf_External_Note *xnp = (Elf_External_Note *) p;
Elf_Internal_Note in;
in.type = bfd_h_get_32 (abfd, (bfd_byte *) xnp->type);
free (buf);
return true;
}
-
-
-/* FIXME: This function is now unnecessary. Callers can just call
- bfd_section_from_phdr directly. */
-
-boolean
-_bfd_elfcore_section_from_phdr (abfd, phdr, sec_num)
- bfd* abfd;
- Elf_Internal_Phdr* phdr;
- int sec_num;
-{
- if (! bfd_section_from_phdr (abfd, phdr, sec_num))
- return false;
-
- return true;
-}
-
-
\f
/* Providing external access to the ELF program header table. */
/* Return an upper bound on the number of bytes required to store a
copy of ABFD's program header table entries. Return -1 if an error
occurs; bfd_get_error will return an appropriate code. */
+
long
bfd_get_elf_phdr_upper_bound (abfd)
bfd *abfd;
return -1;
}
- return (elf_elfheader (abfd)->e_phnum
- * sizeof (Elf_Internal_Phdr));
+ return elf_elfheader (abfd)->e_phnum * sizeof (Elf_Internal_Phdr);
}
-
/* Copy ABFD's program header table entries to *PHDRS. The entries
will be stored as an array of Elf_Internal_Phdr structures, as
defined in include/elf/internal.h. To find out how large the
Return the number of program header table entries read, or -1 if an
error occurs; bfd_get_error will return an appropriate code. */
+
int
bfd_get_elf_phdrs (abfd, phdrs)
bfd *abfd;
}
num_phdrs = elf_elfheader (abfd)->e_phnum;
- memcpy (phdrs, elf_tdata (abfd)->phdr,
+ memcpy (phdrs, elf_tdata (abfd)->phdr,
num_phdrs * sizeof (Elf_Internal_Phdr));
return num_phdrs;