mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-22 19:09:31 +08:00
(bfd_elf_hash): Optimize the hash function a bit.
This commit is contained in:
465
bfd/elf.c
465
bfd/elf.c
@ -199,8 +199,7 @@ _bfd_elf_swap_versym_out (abfd, src, dst)
|
||||
}
|
||||
|
||||
/* Standard ELF hash function. Do not change this function; you will
|
||||
cause invalid hash tables to be generated. (Well, you would if this
|
||||
were being used yet.) */
|
||||
cause invalid hash tables to be generated. */
|
||||
unsigned long
|
||||
bfd_elf_hash (name)
|
||||
CONST unsigned char *name;
|
||||
@ -215,7 +214,9 @@ bfd_elf_hash (name)
|
||||
if ((g = (h & 0xf0000000)) != 0)
|
||||
{
|
||||
h ^= g >> 24;
|
||||
h &= ~g;
|
||||
/* The ELF ABI says `h &= ~g', but this is equivalent in
|
||||
this case and on some machines one insn instead of two. */
|
||||
h ^= g;
|
||||
}
|
||||
}
|
||||
return h;
|
||||
@ -3916,7 +3917,8 @@ swap_out_syms (abfd, sttp, relocatable_p)
|
||||
|
||||
type_ptr = elf_symbol_from (abfd, syms[idx]);
|
||||
|
||||
if (bfd_is_com_section (syms[idx]->section))
|
||||
if ((flags & BSF_SECTION_SYM) == 0
|
||||
&& bfd_is_com_section (syms[idx]->section))
|
||||
{
|
||||
/* ELF common symbols put the alignment into the `value' field,
|
||||
and the size into the `size' field. This is backwards from
|
||||
@ -4006,17 +4008,17 @@ swap_out_syms (abfd, sttp, relocatable_p)
|
||||
|
||||
/* Processor-specific types */
|
||||
if (bed->elf_backend_get_symbol_type)
|
||||
type = (*bed->elf_backend_get_symbol_type) (&type_ptr->internal_elf_sym);
|
||||
type = (*bed->elf_backend_get_symbol_type) (&type_ptr->internal_elf_sym, type);
|
||||
|
||||
if (bfd_is_com_section (syms[idx]->section))
|
||||
if (flags & BSF_SECTION_SYM)
|
||||
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))
|
||||
sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK)
|
||||
? STB_WEAK
|
||||
: STB_GLOBAL),
|
||||
type);
|
||||
else if (flags & BSF_SECTION_SYM)
|
||||
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
|
||||
else if (flags & BSF_FILE)
|
||||
sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
|
||||
else
|
||||
@ -4517,6 +4519,11 @@ _bfd_elf_find_nearest_line (abfd,
|
||||
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))
|
||||
@ -4761,3 +4768,445 @@ _bfd_elf_rel_vtable_reloc_fn (abfd, re, symbol, data, is, obfd, errmsg)
|
||||
{
|
||||
return bfd_reloc_ok;
|
||||
}
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
#ifdef HAVE_SYS_PROCFS_H
|
||||
# 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
|
||||
elfcore_make_pid (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. */
|
||||
|
||||
static boolean
|
||||
elfcore_maybe_make_sect (abfd, name, sect)
|
||||
bfd* abfd;
|
||||
char* name;
|
||||
asection* sect;
|
||||
{
|
||||
asection* sect2;
|
||||
|
||||
if (bfd_get_section_by_name (abfd, name) != NULL)
|
||||
return true;
|
||||
|
||||
sect2 = bfd_make_section (abfd, name);
|
||||
if (sect2 == NULL)
|
||||
return false;
|
||||
|
||||
sect2->_raw_size = sect->_raw_size;
|
||||
sect2->filepos = sect->filepos;
|
||||
sect2->flags = sect->flags;
|
||||
sect2->alignment_power = sect->alignment_power;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* prstatus_t exists on:
|
||||
solaris 2.[567]
|
||||
linux 2.[01] + glibc
|
||||
unixware 4.2
|
||||
*/
|
||||
|
||||
#if defined (HAVE_PRSTATUS_T)
|
||||
static boolean
|
||||
elfcore_grok_prstatus (abfd, note)
|
||||
bfd* abfd;
|
||||
Elf_Internal_Note* note;
|
||||
{
|
||||
prstatus_t prstat;
|
||||
char buf[100];
|
||||
char* name;
|
||||
asection* sect;
|
||||
|
||||
if (note->descsz != sizeof (prstat))
|
||||
return true;
|
||||
|
||||
memcpy (&prstat, note->descdata, sizeof (prstat));
|
||||
|
||||
elf_tdata (abfd)->core_signal = prstat.pr_cursig;
|
||||
elf_tdata (abfd)->core_pid = prstat.pr_pid;
|
||||
|
||||
/* pr_who exists on:
|
||||
solaris 2.[567]
|
||||
unixware 4.2
|
||||
pr_who doesn't exist on:
|
||||
linux 2.[01]
|
||||
*/
|
||||
#if defined (HAVE_PRSTATUS_T_PR_WHO)
|
||||
elf_tdata (abfd)->core_lwpid = prstat.pr_who;
|
||||
#endif
|
||||
|
||||
/* 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 = sizeof (prstat.pr_reg);
|
||||
sect->filepos = note->descpos + offsetof (prstatus_t, pr_reg);
|
||||
sect->flags = SEC_HAS_CONTENTS;
|
||||
sect->alignment_power = 2;
|
||||
|
||||
if (! elfcore_maybe_make_sect (abfd, ".reg", sect))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif /* defined (HAVE_PRSTATUS_T) */
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
static boolean
|
||||
elfcore_grok_prfpreg (abfd, note)
|
||||
bfd* abfd;
|
||||
Elf_Internal_Note* note;
|
||||
{
|
||||
char buf[100];
|
||||
char* name;
|
||||
asection* sect;
|
||||
|
||||
/* Make a ".reg2/999" section. */
|
||||
|
||||
sprintf (buf, ".reg2/%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 = note->descsz;
|
||||
sect->filepos = note->descpos;
|
||||
sect->flags = SEC_HAS_CONTENTS;
|
||||
sect->alignment_power = 2;
|
||||
|
||||
if (! elfcore_maybe_make_sect (abfd, ".reg2", sect))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
bfd* abfd;
|
||||
char* start;
|
||||
int max;
|
||||
{
|
||||
char* dup;
|
||||
char* end = memchr (start, '\0', max);
|
||||
int len;
|
||||
|
||||
if (end == NULL)
|
||||
len = max;
|
||||
else
|
||||
len = end - start;
|
||||
|
||||
dup = bfd_alloc (abfd, len + 1);
|
||||
if (dup == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy (dup, start, len);
|
||||
dup[len] = '\0';
|
||||
|
||||
return dup;
|
||||
}
|
||||
|
||||
|
||||
#if defined (HAVE_PRPSINFO_T)
|
||||
# define elfcore_psinfo_t prpsinfo_t
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_PSINFO_T)
|
||||
# define elfcore_psinfo_t psinfo_t
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
|
||||
static boolean
|
||||
elfcore_grok_psinfo (abfd, note)
|
||||
bfd* abfd;
|
||||
Elf_Internal_Note* note;
|
||||
{
|
||||
elfcore_psinfo_t psinfo;
|
||||
|
||||
if (note->descsz != sizeof (elfcore_psinfo_t))
|
||||
return true;
|
||||
|
||||
memcpy (&psinfo, note->descdata, note->descsz);
|
||||
|
||||
elf_tdata (abfd)->core_program
|
||||
= 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));
|
||||
|
||||
/* 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. */
|
||||
|
||||
{
|
||||
char* command = elf_tdata (abfd)->core_command;
|
||||
int n = strlen (command);
|
||||
|
||||
if (0 < n && command[n - 1] == ' ')
|
||||
command[n - 1] = '\0';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#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;
|
||||
{
|
||||
pstatus_t pstat;
|
||||
|
||||
if (note->descsz != sizeof (pstat))
|
||||
return true;
|
||||
|
||||
memcpy (&pstat, note->descdata, sizeof (pstat));
|
||||
|
||||
elf_tdata (abfd)->core_pid = pstat.pr_pid;
|
||||
|
||||
/* 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. */
|
||||
|
||||
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;
|
||||
{
|
||||
lwpstatus_t lwpstat;
|
||||
char buf[100];
|
||||
char* name;
|
||||
asection* sect;
|
||||
|
||||
if (note->descsz != sizeof (lwpstat))
|
||||
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. */
|
||||
|
||||
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;
|
||||
|
||||
#if defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
|
||||
sect->_raw_size = sizeof (lwpstat.pr_context.uc_mcontext.gregs);
|
||||
sect->filepos = note->descpos
|
||||
+ offsetof (lwpstatus_t, pr_context.uc_mcontext.gregs);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_LWPSTATUS_T_PR_REG)
|
||||
sect->_raw_size = sizeof (lwpstat.pr_reg);
|
||||
sect->filepos = note->descpos + offsetof (lwpstatus_t, pr_reg);
|
||||
#endif
|
||||
|
||||
sect->flags = SEC_HAS_CONTENTS;
|
||||
sect->alignment_power = 2;
|
||||
|
||||
if (!elfcore_maybe_make_sect (abfd, ".reg", sect))
|
||||
return false;
|
||||
|
||||
/* Make a ".reg2/999" section */
|
||||
|
||||
sprintf (buf, ".reg2/%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;
|
||||
|
||||
#if defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
|
||||
sect->_raw_size = sizeof (lwpstat.pr_context.uc_mcontext.fpregs);
|
||||
sect->filepos = note->descpos
|
||||
+ offsetof (lwpstatus_t, pr_context.uc_mcontext.fpregs);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_LWPSTATUS_T_PR_FPREG)
|
||||
sect->_raw_size = sizeof (lwpstat.pr_fpreg);
|
||||
sect->filepos = note->descpos + offsetof (lwpstatus_t, pr_fpreg);
|
||||
#endif
|
||||
|
||||
sect->flags = SEC_HAS_CONTENTS;
|
||||
sect->alignment_power = 2;
|
||||
|
||||
if (!elfcore_maybe_make_sect (abfd, ".reg2", sect))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif /* defined (HAVE_LWPSTATUS_T) */
|
||||
|
||||
|
||||
|
||||
static boolean
|
||||
elfcore_grok_note (abfd, note)
|
||||
bfd* abfd;
|
||||
Elf_Internal_Note* note;
|
||||
{
|
||||
switch (note->type)
|
||||
{
|
||||
default:
|
||||
return true;
|
||||
|
||||
#if defined (HAVE_PRSTATUS_T)
|
||||
case NT_PRSTATUS:
|
||||
return elfcore_grok_prstatus (abfd, note);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_PSTATUS_T)
|
||||
case NT_PSTATUS:
|
||||
return elfcore_grok_pstatus (abfd, note);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_LWPSTATUS_T)
|
||||
case NT_LWPSTATUS:
|
||||
return elfcore_grok_lwpstatus (abfd, note);
|
||||
#endif
|
||||
|
||||
case NT_FPREGSET: /* FIXME: rename to NT_PRFPREG */
|
||||
return elfcore_grok_prfpreg (abfd, note);
|
||||
|
||||
#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
|
||||
case NT_PRPSINFO:
|
||||
case NT_PSINFO:
|
||||
return elfcore_grok_psinfo (abfd, note);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static boolean
|
||||
elfcore_read_notes (abfd, offset, size)
|
||||
bfd* abfd;
|
||||
bfd_vma offset;
|
||||
bfd_vma size;
|
||||
{
|
||||
char* buf;
|
||||
char* p;
|
||||
|
||||
if (size <= 0)
|
||||
return true;
|
||||
|
||||
if (bfd_seek (abfd, offset, SEEK_SET) == -1)
|
||||
return false;
|
||||
|
||||
buf = bfd_malloc ((size_t) size);
|
||||
if (buf == NULL)
|
||||
return false;
|
||||
|
||||
if (bfd_read (buf, size, 1, abfd) != size)
|
||||
{
|
||||
error:
|
||||
free (buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
p = buf;
|
||||
while (p < buf + size)
|
||||
{
|
||||
/* 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);
|
||||
|
||||
in.namesz = bfd_h_get_32 (abfd, (bfd_byte *) xnp->namesz);
|
||||
in.namedata = xnp->name;
|
||||
|
||||
in.descsz = bfd_h_get_32 (abfd, (bfd_byte *) xnp->descsz);
|
||||
in.descdata = in.namedata + BFD_ALIGN (in.namesz, 4);
|
||||
in.descpos = offset + (in.descdata - buf);
|
||||
|
||||
if (! elfcore_grok_note (abfd, &in))
|
||||
goto error;
|
||||
|
||||
p = in.descdata + BFD_ALIGN (in.descsz, 4);
|
||||
}
|
||||
|
||||
free (buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
||||
if (phdr->p_type == PT_NOTE
|
||||
&& ! elfcore_read_notes (abfd, phdr->p_offset, phdr->p_filesz))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user