/* 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
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. */
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;
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);
}
}
*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;
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 (sect_syms == NULL)
return false;
elf_section_syms (abfd) = sect_syms;
+ elf_num_section_syms (abfd) = max_index;
for (idx = 0; idx < symcount; idx++)
{
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;
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;
}
indx = asym_ptr->section->output_section->index;
else
indx = asym_ptr->section->index;
- if (elf_section_syms (abfd)[indx])
+ if (indx < elf_num_section_syms (abfd)
+ && elf_section_syms (abfd)[indx] != NULL)
asym_ptr->udata.i = elf_section_syms (abfd)[indx]->udata.i;
}
flagword flags = syms[idx]->flags;
int type;
- if ((flags & BSF_SECTION_SYM) != 0)
+ if ((flags & (BSF_SECTION_SYM | BSF_GLOBAL)) == BSF_SECTION_SYM)
{
- /* Section symbols have no name. */
+ /* Local section symbols have no name. */
sym.st_name = 0;
}
else
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,
- &elf_tdata (abfd)->dwarf2_find_line_info))
- 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;
}
# include <sys/procfs.h>
#endif
-/* 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. */
static int
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+
linux 2.[01] + glibc
*/
#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;
{
- 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;
char *name;
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,
#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'. */
-static char*
-elfcore_strndup (abfd, start, max)
+char *
+_bfd_elfcore_strndup (abfd, start, max)
bfd *abfd;
char *start;
int max;
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;
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
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) */
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)
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
}
}
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 -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
return num_phdrs;
}
+
+void
+_bfd_elf_sprintf_vma (abfd, buf, value)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ char *buf;
+ bfd_vma value;
+{
+#ifdef BFD64
+ Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
+
+ i_ehdrp = elf_elfheader (abfd);
+ if (i_ehdrp == NULL)
+ sprintf_vma (buf, value);
+ else
+ {
+ if (i_ehdrp->e_ident[EI_CLASS] == ELFCLASS64)
+ {
+#if BFD_HOST_64BIT_LONG
+ sprintf (buf, "%016lx", value);
+#else
+ sprintf (buf, "%08lx%08lx", _bfd_int64_high (value),
+ _bfd_int64_low (value));
+#endif
+ }
+ else
+ sprintf (buf, "%08lx", (unsigned long) (value & 0xffffffff));
+ }
+#else
+ sprintf_vma (buf, value);
+#endif
+}
+
+void
+_bfd_elf_fprintf_vma (abfd, stream, value)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ PTR stream;
+ bfd_vma value;
+{
+#ifdef BFD64
+ Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
+
+ i_ehdrp = elf_elfheader (abfd);
+ if (i_ehdrp == NULL)
+ fprintf_vma ((FILE *) stream, value);
+ else
+ {
+ if (i_ehdrp->e_ident[EI_CLASS] == ELFCLASS64)
+ {
+#if BFD_HOST_64BIT_LONG
+ fprintf ((FILE *) stream, "%016lx", value);
+#else
+ fprintf ((FILE *) stream, "%08lx%08lx",
+ _bfd_int64_high (value), _bfd_int64_low (value));
+#endif
+ }
+ else
+ fprintf ((FILE *) stream, "%08lx",
+ (unsigned long) (value & 0xffffffff));
+ }
+#else
+ fprintf_vma ((FILE *) stream, value);
+#endif
+}