+2007-08-23 Roland McGrath <roland@redhat.com>
+
+ * x86_64_regs.c (x86_64_register_info): Put %rflags in "integer" set.
+
+2007-08-22 Roland McGrath <roland@redhat.com>
+
+ * linux-core-note.c (prstatus_items): Add .group initializers.
+ (prpsinfo_items): Likewise.
+ * x86_64_corenote.c (PRSTATUS_REGSET_ITEMS): Likewise.
+ * i386_corenote.c (PRSTATUS_REGSET_ITEMS): Likewise.
+ * ppc_corenote.c (PRSTATUS_REGSET_ITEMS): Likewise.
+
+2007-08-20 Roland McGrath <roland@redhat.com>
+
+ * ppc_symbol.c (ppc_check_special_symbol): For _GLOBAL_OFFSET_TABLE_
+ when DT_PPC_GOT is not found, anywhere in the section is valid.
+
+2007-08-19 Roland McGrath <roland@redhat.com>
+
+ * i386_auxv.c: New file.
+ * Makefile.am (i386_SRCS, x86_64_SRCS): Add it.
+ * ppc_auxv.c: New file.
+ * Makefile.am (ppc_SRCS, ppc64_SRCS): Add it.
+ * i386_init.c (i386_init): Initialize auxv_info hook.
+ * x86_64_init.c (x86_64_init): Likewise.
+ * ppc_init.c (ppc_init): Likewise.
+ * ppc64_init.c (ppc64_init): Likewise.
+
+ * alpha_corenote.c: New file.
+ * Makefile.am (alpha_SRCS): Add it.
+ * alpha_init.c (alpha_init): Initialize core_note hook.
+
+ * ppc_corenote.c: New file.
+ * ppc64_corenote.c: New file.
+ * Makefile.am (ppc_SRCS, ppc64_SRCS): Add them.
+ * ppc_init.c (ppc_init): Initialize core_note hook.
+ * ppc64_init.c (ppc64_init): Likewise.
+
+ * linux-core-note.c: New file.
+ * Makefile.am (noinst_HEADERS): Add it.
+ * i386_corenote.c: Rewritten.
+ * x86_64_corenote.c: Likewise.
+
2007-05-23 Roland McGrath <roland@redhat.com>
* alpha_regs.c (alpha_register_info): fp -> s6
## Process this file with automake to create Makefile.in
##
-## Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
+## Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Red Hat, Inc.
## This file is part of Red Hat elfutils.
##
## Red Hat elfutils is free software; you can redistribute it and/or modify
i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c \
- i386_retval.c i386_regs.c
+ i386_retval.c i386_regs.c i386_auxv.c
libebl_i386_pic_a_SOURCES = $(i386_SRCS)
am_libebl_i386_pic_a_OBJECTS = $(i386_SRCS:.c=.os)
am_libebl_sh_pic_a_OBJECTS = $(sh_SRCS:.c=.os)
x86_64_SRCS = x86_64_init.c x86_64_symbol.c x86_64_corenote.c \
- x86_64_retval.c x86_64_regs.c
+ x86_64_retval.c x86_64_regs.c i386_auxv.c
libebl_x86_64_pic_a_SOURCES = $(x86_64_SRCS)
am_libebl_x86_64_pic_a_OBJECTS = $(x86_64_SRCS:.c=.os)
libebl_ia64_pic_a_SOURCES = $(ia64_SRCS)
am_libebl_ia64_pic_a_OBJECTS = $(ia64_SRCS:.c=.os)
-alpha_SRCS = alpha_init.c alpha_symbol.c alpha_retval.c alpha_regs.c
+alpha_SRCS = alpha_init.c alpha_symbol.c alpha_retval.c alpha_regs.c \
+ alpha_corenote.c
libebl_alpha_pic_a_SOURCES = $(alpha_SRCS)
am_libebl_alpha_pic_a_OBJECTS = $(alpha_SRCS:.c=.os)
libebl_sparc_pic_a_SOURCES = $(sparc_SRCS)
am_libebl_sparc_pic_a_OBJECTS = $(sparc_SRCS:.c=.os)
-ppc_SRCS = ppc_init.c ppc_symbol.c ppc_retval.c ppc_regs.c
+ppc_SRCS = ppc_init.c ppc_symbol.c ppc_retval.c ppc_regs.c \
+ ppc_corenote.c ppc_auxv.c
libebl_ppc_pic_a_SOURCES = $(ppc_SRCS)
am_libebl_ppc_pic_a_OBJECTS = $(ppc_SRCS:.c=.os)
-ppc64_SRCS = ppc64_init.c ppc64_symbol.c ppc64_retval.c ppc_regs.c
+ppc64_SRCS = ppc64_init.c ppc64_symbol.c ppc64_retval.c \
+ ppc64_corenote.c ppc_regs.c ppc_auxv.c
libebl_ppc64_pic_a_SOURCES = $(ppc64_SRCS)
am_libebl_ppc64_pic_a_OBJECTS = $(ppc64_SRCS:.c=.os)
done
rmdir --ignore-fail-on-non-empty $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)
-noinst_HEADERS = libebl_CPU.h common-reloc.c
+noinst_HEADERS = libebl_CPU.h common-reloc.c linux-core-note.c
EXTRA_DIST = $(foreach m,$(modules),$($(m)_SRCS)) $(modules:=_reloc.def)
CLEANFILES = *.gcno *.gcda \
--- /dev/null
+/* PowerPC specific core note handling.
+ Copyright (C) 2007 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+
+ Red Hat elfutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by the
+ Free Software Foundation; version 2 of the License.
+
+ Red Hat elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND alpha_
+#include "libebl_CPU.h"
+
+static const Ebl_Register_Location prstatus_regs[] =
+ {
+ { .offset = 0, .regno = 0, .count = 31, .bits = 64 }, /* r0-r30 */
+ { .offset = 32 * 8, .regno = 64, .count = 1, .bits = 64 }, /* pc */
+ { .offset = 33 * 8, .regno = 66, .count = 1, .bits = 64 }, /* unique */
+ };
+#define PRSTATUS_REGS_SIZE (33 * 8)
+
+static const Ebl_Register_Location fpregset_regs[] =
+ {
+ { .offset = 0, .regno = 32, .count = 32, .bits = 64 }, /* f0-f30, fpcr */
+ };
+#define FPREGSET_SIZE (32 * 8)
+
+#define ULONG uint64_t
+#define ALIGN_ULONG 8
+#define TYPE_ULONG ELF_T_XWORD
+#define TYPE_LONG ELF_T_SXWORD
+#define PID_T int32_t
+#define UID_T uint32_t
+#define GID_T uint32_t
+#define ALIGN_PID_T 4
+#define ALIGN_UID_T 4
+#define ALIGN_GID_T 4
+#define TYPE_PID_T ELF_T_SWORD
+#define TYPE_UID_T ELF_T_WORD
+#define TYPE_GID_T ELF_T_WORD
+
+#include "linux-core-note.c"
HOOK (eh, dynamic_tag_check);
HOOK (eh, reloc_simple_type);
HOOK (eh, return_value_location);
- HOOK (eh, register_info);
HOOK (eh, machine_section_flag_check);
+ HOOK (eh, register_info);
+ HOOK (eh, core_note);
eh->sysvhash_entrysize = sizeof (Elf64_Xword);
return MODVERSION;
--- /dev/null
+/* i386 specific auxv handling.
+ Copyright (C) 2007 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+
+ Red Hat elfutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by the
+ Free Software Foundation; version 2 of the License.
+
+ Red Hat elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+int
+EBLHOOK(auxv_info) (GElf_Xword a_type, const char **name, const char **format)
+{
+ if (a_type != AT_HWCAP)
+ return 0;
+
+ *name = "HWCAP";
+ *format = "b"
+ "fpu\0" "vme\0" "de\0" "pse\0" "tsc\0" "msr\0" "pae\0" "mce\0"
+ "cx8\0" "apic\0" "10\0" "sep\0" "mtrr\0" "pge\0" "mca\0" "cmov\0"
+ "pat\0" "pse36\0" "pn\0" "clflush\0" "20\0" "dts\0" "acpi\0" "mmx\0"
+ "fxsr\0" "sse\0" "sse2\0" "ss\0" "ht\0" "tm\0" "ia64\0" "pbe\0" "\0";
+ return 1;
+}
+
+__typeof (i386_auxv_info) x86_64_auxv_info
+ __attribute__ ((alias ("i386_auxv_info")));
/* i386 specific core note handling.
- Copyright (C) 2002, 2005 Red Hat, Inc.
+ Copyright (C) 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
- Written by Ulrich Drepper <drepper@redhat.com>, 2002.
Red Hat elfutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by the
#include "libebl_CPU.h"
-/* We cannot include <sys/procfs.h> since the definition would be for
- the host platform and not always x86 as required here. */
-struct elf_prstatus
+static const Ebl_Register_Location prstatus_regs[] =
{
- struct
- {
- int32_t si_signo; /* Signal number. */
- int32_t si_code; /* Extra code. */
- int32_t si_errno; /* Errno. */
- } pr_info; /* Info associated with signal. */
- int16_t pr_cursig; /* Current signal. */
- uint32_t pr_sigpend; /* Set of pending signals. */
- uint32_t pr_sighold; /* Set of held signals. */
- int32_t pr_pid;
- int32_t pr_ppid;
- int32_t pr_pgrp;
- int32_t pr_sid;
- struct i386_timeval
- {
- int32_t tv_sec;
- int32_t tv_usec;
- } pr_utime; /* User time. */
- struct i386_timeval pr_stime; /* System time. */
- struct i386_timeval pr_cutime; /* Cumulative user time. */
- struct i386_timeval pr_cstime; /* Cumulative system time. */
- uint32_t pr_reg[17]; /* GP registers. */
- int32_t pr_fpvalid; /* True if math copro being used. */
+#define GR(at, n, dwreg) \
+ { .offset = at * 4, .regno = dwreg, .count = n, .bits = 32 }
+#define SR(at, n, dwreg) \
+ { .offset = at * 4, .regno = dwreg, .count = n, .bits = 16, .pad = 2 }
+
+ GR (0, 1, 3), /* %ebx */
+ GR (1, 2, 1), /* %ecx-%edx */
+ GR (3, 2, 6), /* %esi-%edi */
+ GR (5, 1, 5), /* %ebp */
+ GR (6, 1, 0), /* %eax */
+ SR (7, 1, 43), /* %ds */
+ SR (8, 1, 40), /* %es */
+ SR (9, 1, 44), /* %fs */
+ SR (10, 1, 45), /* %gs */
+ /* 11, 1, orig_eax */
+ GR (12, 1, 8), /* %eip */
+ SR (13, 1, 41), /* %cs */
+ GR (14, 1, 9), /* eflags */
+ GR (15, 1, 4), /* %esp */
+ SR (16, 1, 42), /* %ss */
+
+#undef GR
+#undef SR
};
-
-
-struct elf_prpsinfo
+#define PRSTATUS_REGS_SIZE (17 * 4)
+
+#define ULONG uint32_t
+#define PID_T int32_t
+#define UID_T uint16_t
+#define GID_T uint16_t
+#define ALIGN_ULONG 4
+#define ALIGN_PID_T 4
+#define ALIGN_UID_T 2
+#define ALIGN_GID_T 2
+#define TYPE_ULONG ELF_T_WORD
+#define TYPE_PID_T ELF_T_SWORD
+#define TYPE_UID_T ELF_T_HALF
+#define TYPE_GID_T ELF_T_HALF
+
+#define PRSTATUS_REGSET_ITEMS \
+ { \
+ .name = "orig_eax", .type = ELF_T_SWORD, .format = 'd', \
+ .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + (4 * 11), \
+ .group = "register" \
+ }
+
+static const Ebl_Register_Location fpregset_regs[] =
{
- char pr_state; /* Numeric process state. */
- char pr_sname; /* Char for pr_state. */
- char pr_zomb; /* Zombie. */
- char pr_nice; /* Nice val. */
- uint32_t pr_flag; /* Flags. */
- uint16_t pr_uid;
- uint16_t pr_gid;
- int32_t pr_pid;
- int32_t pr_ppid;
- int32_t pr_pgrp;
- int32_t pr_sid;
- /* Lots missing */
- char pr_fname[16]; /* Filename of executable. */
- char pr_psargs[80]; /* Initial part of arg list. */
+ { .offset = 0, .regno = 37, .count = 2, .bits = 32 }, /* fctrl-fstat */
+ { .offset = 7 * 4, .regno = 11, .count = 8, .bits = 80 }, /* stN */
};
+#define FPREGSET_SIZE 108
+static const Ebl_Register_Location prxfpreg_regs[] =
+ {
+ { .offset = 0, .regno = 37, .count = 2, .bits = 16 }, /* fctrl-fstat */
+ { .offset = 24, .regno = 39, .count = 1, .bits = 32 }, /* mxcsr */
+ { .offset = 32, .regno = 11, .count = 8, .bits = 80, .pad = 6 }, /* stN */
+ { .offset = 32 + 128, .regno = 21, .count = 8, .bits = 128 }, /* xmm */
+ };
+#define PRXFPREG_SIZE 512
-bool
-i386_core_note (name, type, descsz, desc)
- const char *name __attribute__ ((unused));
- uint32_t type;
- uint32_t descsz;
- const char *desc;
-{
- bool result = false;
-
- switch (type)
- {
- case NT_PRSTATUS:
- if (descsz < sizeof (struct elf_prstatus))
- /* Not enough data. */
- break;
-
- struct elf_prstatus *stat = (struct elf_prstatus *) desc;
-
- printf (" SIGINFO: signo: %" PRId32 ", code = %" PRId32
- ", errno = %" PRId32 "\n"
- " signal: %" PRId16 ", pending: %08" PRIx32
- ", holding: %8" PRIx32 "\n"
- " pid: %" PRId32 ", ppid = %" PRId32 ", pgrp = %" PRId32
- ", sid = %" PRId32 "\n"
- " utime: %6" PRId32 ".%06" PRId32
- "s, stime: %6" PRId32 ".%06" PRId32 "s\n"
- " cutime: %6" PRId32 ".%06" PRId32
- "s, cstime: %6" PRId32 ".%06" PRId32 "s\n"
- " eax: %08" PRIx32 " ebx: %08" PRIx32 " ecx: %08" PRIx32
- " edx: %08" PRIx32 "\n"
- " esi: %08" PRIx32 " edi: %08" PRIx32 " ebp: %08" PRIx32
- " esp: %08" PRIx32 "\n"
- " eip: %08" PRIx32 " eflags: %08" PRIx32
- " original eax: %08" PRIx32 "\n"
- " cs: %04" PRIx32 " ds: %04" PRIx32 " es: %04" PRIx32
- " fs: %04" PRIx32 " gs: %04" PRIx32 " ss: %04" PRIx32 "\n\n",
- stat->pr_info.si_signo,
- stat->pr_info.si_code,
- stat->pr_info.si_errno,
- stat->pr_cursig,
- stat->pr_sigpend, stat->pr_sighold,
- stat->pr_pid, stat->pr_ppid, stat->pr_pgrp, stat->pr_sid,
- stat->pr_utime.tv_sec, stat->pr_utime.tv_usec,
- stat->pr_stime.tv_sec, stat->pr_stime.tv_usec,
- stat->pr_cutime.tv_sec, stat->pr_cutime.tv_usec,
- stat->pr_cstime.tv_sec, stat->pr_cstime.tv_usec,
- stat->pr_reg[6], stat->pr_reg[0], stat->pr_reg[1],
- stat->pr_reg[2], stat->pr_reg[3], stat->pr_reg[4],
- stat->pr_reg[5], stat->pr_reg[15], stat->pr_reg[12],
- stat->pr_reg[14], stat->pr_reg[11], stat->pr_reg[13] & 0xffff,
- stat->pr_reg[7] & 0xffff, stat->pr_reg[8] & 0xffff,
- stat->pr_reg[9] & 0xffff, stat->pr_reg[10] & 0xffff,
- stat->pr_reg[16]);
-
- /* We handled this entry. */
- result = true;
- break;
-
- case NT_PRPSINFO:
- if (descsz < sizeof (struct elf_prpsinfo))
- /* Not enough data. */
- break;
-
- struct elf_prpsinfo *info = (struct elf_prpsinfo *) desc;
-
- printf (" state: %c (%hhd), zombie: %hhd, nice: %hhd\n"
- " flags: %08" PRIx32 ", uid: %" PRId16 ", gid: %" PRId16"\n"
- " pid: %" PRId32 ", ppid: %" PRId32 ", pgrp: %" PRId32
- ", sid: %" PRId32 "\n"
- " fname: %.16s\n"
- " args: %.80s\n\n",
- info->pr_sname, info->pr_state, info->pr_zomb, info->pr_nice,
- info->pr_flag, info->pr_uid, info->pr_gid,
- info->pr_pid, info->pr_ppid, info->pr_pgrp, info->pr_sid,
- info->pr_fname, info->pr_psargs);
-
- /* We handled this entry. */
- result = true;
- break;
-
- default:
- break;
- }
-
- return result;
-}
+#include "linux-core-note.c"
/* Initialization of i386 specific backend library.
- Copyright (C) 2000, 2001, 2002, 2005, 2006 Red Hat, Inc.
+ Copyright (C) 2000, 2001, 2002, 2005, 2006, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
HOOK (eh, debugscn_p);
HOOK (eh, return_value_location);
HOOK (eh, register_info);
+ HOOK (eh, auxv_info);
return MODVERSION;
}
--- /dev/null
+/* Common core note type descriptions for Linux.
+ Copyright (C) 2007 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+
+ Red Hat elfutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by the
+ Free Software Foundation; version 2 of the License.
+
+ Red Hat elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+/* The including CPU_corenote.c file provides prstatus_regs and
+ defines macros ULONG, [PUG]ID_T, and ALIGN_*, TYPE_*.
+
+ Here we describe the common layout used in <linux/elfcore.h>. */
+
+#define CHAR int8_t
+#define ALIGN_CHAR 1
+#define TYPE_CHAR ELF_T_BYTE
+#define SHORT uint16_t
+#define ALIGN_SHORT 2
+#define TYPE_SHORT ELF_T_HALF
+#define INT int32_t
+#define ALIGN_INT 4
+#define TYPE_INT ELF_T_SWORD
+
+#define FIELD(type, name) type name __attribute__ ((aligned (ALIGN_##type)))
+
+struct EBLHOOK(siginfo)
+{
+ FIELD (INT, si_signo);
+ FIELD (INT, si_code);
+ FIELD (INT, si_errno);
+};
+
+struct EBLHOOK(timeval)
+{
+ FIELD (ULONG, tv_sec);
+ FIELD (ULONG, tv_usec);
+};
+
+struct EBLHOOK(prstatus)
+{
+ struct EBLHOOK(siginfo) pr_info;
+ FIELD (SHORT, pr_cursig);
+ FIELD (ULONG, pr_sigpend);
+ FIELD (ULONG, pr_sighold);
+ FIELD (PID_T, pr_pid);
+ FIELD (PID_T, pr_ppid);
+ FIELD (PID_T, pr_pgrp);
+ FIELD (PID_T, pr_sid);
+ struct EBLHOOK(timeval) pr_utime;
+ struct EBLHOOK(timeval) pr_stime;
+ struct EBLHOOK(timeval) pr_cutime;
+ struct EBLHOOK(timeval) pr_cstime;
+ FIELD (ULONG, pr_reg[PRSTATUS_REGS_SIZE / sizeof (ULONG)]);
+ FIELD (INT, pr_fpvalid);
+};
+
+#define FNAMESZ 16
+#define PRARGSZ 80
+
+struct EBLHOOK(prpsinfo)
+{
+ FIELD (CHAR, pr_state);
+ FIELD (CHAR, pr_sname);
+ FIELD (CHAR, pr_zomb);
+ FIELD (CHAR, pr_nice);
+ FIELD (ULONG, pr_flag);
+ FIELD (UID_T, pr_uid);
+ FIELD (GID_T, pr_gid);
+ FIELD (PID_T, pr_pid);
+ FIELD (PID_T, pr_ppid);
+ FIELD (PID_T, pr_pgrp);
+ FIELD (PID_T, pr_sid);
+ FIELD (CHAR, pr_fname[FNAMESZ]);
+ FIELD (CHAR, pr_psargs[PRARGSZ]);
+};
+
+#undef FIELD
+
+#define FIELD(igroup, itype, item, fmt, ...) \
+ { \
+ .name = #item, \
+ .group = #igroup, \
+ .offset = offsetof (struct EBLHOOK(prstatus), pr_##item), \
+ .type = TYPE_##itype, \
+ .format = fmt, \
+ __VA_ARGS__ \
+ }
+
+static const Ebl_Core_Item prstatus_items[] =
+ {
+ FIELD (signal, INT, info.si_signo, 'd'),
+ FIELD (signal, INT, info.si_code, 'd'),
+ FIELD (signal, INT, info.si_errno, 'd'),
+ FIELD (signal, SHORT, cursig, 'd'),
+ FIELD (signal, ULONG, sigpend, 'b'),
+ FIELD (signal, ULONG, sighold, 'b'),
+ FIELD (identity, PID_T, pid, 'd', .thread_identifier = true),
+ FIELD (identity, PID_T, ppid, 'd'),
+ FIELD (identity, PID_T, pgrp, 'd'),
+ FIELD (identity, PID_T, sid, 'd'),
+ FIELD (time, ULONG, utime, 'T', .count = 2),
+ FIELD (time, ULONG, stime, 'T', .count = 2),
+ FIELD (time, ULONG, cutime, 'T', .count = 2),
+ FIELD (time, ULONG, cstime, 'T', .count = 2),
+#ifdef PRSTATUS_REGSET_ITEMS
+ PRSTATUS_REGSET_ITEMS,
+#endif
+ FIELD (register, INT, fpvalid, 'd'),
+ };
+
+#undef FIELD
+
+#define FIELD(igroup, itype, item, fmt, ...) \
+ { \
+ .name = #item, \
+ .group = #igroup, \
+ .offset = offsetof (struct EBLHOOK(prpsinfo), pr_##item), \
+ .type = TYPE_##itype, \
+ .format = fmt, \
+ __VA_ARGS__ \
+ }
+
+static const Ebl_Core_Item prpsinfo_items[] =
+ {
+ FIELD (state, CHAR, state, 'd'),
+ FIELD (state, CHAR, sname, 'c'),
+ FIELD (state, CHAR, zomb, 'd'),
+ FIELD (state, CHAR, nice, 'd'),
+ FIELD (state, ULONG, flag, 'x'),
+ FIELD (identity, UID_T, uid, 'd'),
+ FIELD (identity, GID_T, gid, 'd'),
+ FIELD (identity, PID_T, pid, 'd'),
+ FIELD (identity, PID_T, ppid, 'd'),
+ FIELD (identity, PID_T, pgrp, 'd'),
+ FIELD (identity, PID_T, sid, 'd'),
+ FIELD (command, CHAR, fname, 's', .count = FNAMESZ),
+ FIELD (command, CHAR, psargs, 's', .count = PRARGSZ),
+ };
+
+#undef FIELD
+
+int
+EBLHOOK(core_note) (n_type, descsz,
+ regs_offset, nregloc, reglocs, nitems, items)
+ GElf_Word n_type;
+ GElf_Word descsz;
+ GElf_Word *regs_offset;
+ size_t *nregloc;
+ const Ebl_Register_Location **reglocs;
+ size_t *nitems;
+ const Ebl_Core_Item **items;
+{
+ switch (n_type)
+ {
+ case NT_PRSTATUS:
+ if (descsz != sizeof (struct EBLHOOK(prstatus)))
+ return 0;
+ *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg);
+ *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0];
+ *reglocs = prstatus_regs;
+ *nitems = sizeof prstatus_items / sizeof prstatus_items[0];
+ *items = prstatus_items;
+ return 1;
+
+ case NT_PRPSINFO:
+ if (descsz != sizeof (struct EBLHOOK(prpsinfo)))
+ return 0;
+ *regs_offset = 0;
+ *nregloc = 0;
+ *reglocs = NULL;
+ *nitems = sizeof prpsinfo_items / sizeof prpsinfo_items[0];
+ *items = prpsinfo_items;
+ return 1;
+
+#ifdef FPREGSET_SIZE
+ case NT_FPREGSET:
+ if (descsz != FPREGSET_SIZE)
+ return 0;
+ *regs_offset = 0;
+ *nregloc = sizeof fpregset_regs / sizeof fpregset_regs[0];
+ *reglocs = fpregset_regs;
+ *nitems = 0;
+ *items = NULL;
+ return 1;
+#endif
+
+#ifdef PRXFPREG_SIZE
+ case NT_PRXFPREG:
+ if (descsz != PRXFPREG_SIZE)
+ return 0;
+ *regs_offset = 0;
+ *nregloc = sizeof prxfpreg_regs / sizeof prxfpreg_regs[0];
+ *reglocs = prxfpreg_regs;
+ *nitems = 0;
+ *items = NULL;
+ return 1;
+#endif
+ }
+
+ return 0;
+}
--- /dev/null
+#define BITS 64
+#include "ppc_corenote.c"
/* Initialization of PPC64 specific backend library.
- Copyright (C) 2004, 2005, 2006 Red Hat, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2004.
HOOK (eh, bss_plt_p);
HOOK (eh, return_value_location);
HOOK (eh, register_info);
+ HOOK (eh, core_note);
+ HOOK (eh, auxv_info);
return MODVERSION;
}
--- /dev/null
+/* i386 specific auxv handling.
+ Copyright (C) 2007 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+
+ Red Hat elfutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by the
+ Free Software Foundation; version 2 of the License.
+
+ Red Hat elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+int
+EBLHOOK(auxv_info) (GElf_Xword a_type, const char **name, const char **format)
+{
+ if (a_type != AT_HWCAP)
+ return 0;
+
+ *name = "HWCAP";
+ *format = "b"
+ "ppcle\0" "truele\0" "3\0" "4\0" "5\0" "6\0" "7\0" "8\0" "9\0"
+ "power6x\0" "dfp\0" "pa6t\0" "arch_2_05\0"
+ "ic_snoop\0" "smt\0" "booke\0" "cellbe\0"
+ "power5+\0" "power5\0" "power4\0" "notb\0"
+ "efpdouble\0" "efpsingle\0" "spe\0" "ucache\0"
+ "4xxmac\0" "mmu\0" "fpu\0" "altivec\0"
+ "ppc601\0" "ppc64\0" "ppc32\0" "\0";
+ return 1;
+}
+
+__typeof (ppc_auxv_info) ppc64_auxv_info
+ __attribute__ ((alias ("ppc_auxv_info")));
--- /dev/null
+/* PowerPC specific core note handling.
+ Copyright (C) 2007 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+
+ Red Hat elfutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by the
+ Free Software Foundation; version 2 of the License.
+
+ Red Hat elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#ifndef BITS
+# define BITS 32
+# define BACKEND ppc_
+#else
+# define BITS 64
+# define BACKEND ppc64_
+#endif
+#include "libebl_CPU.h"
+
+static const Ebl_Register_Location prstatus_regs[] =
+ {
+#define GR(at, n, dwreg) \
+ { .offset = at * BITS/8, .regno = dwreg, .count = n, .bits = BITS }
+
+ GR (0, 32, 0), /* r0-r31 */
+ /* 32, 1, nip */
+ GR (33, 1, 66), /* msr */
+ /* 34, 1, orig_gpr3 */
+ GR (35, 1, 109), /* ctr */
+ GR (36, 1, 108), /* lr */
+ GR (37, 1, 101), /* xer */
+ GR (38, 1, 64), /* cr */
+ GR (39, 1, 100), /* mq */
+ /* 40, 1, trap */
+ GR (41, 1, 119), /* dar */
+ GR (42, 1, 118), /* dsisr */
+
+#undef GR
+ };
+#define PRSTATUS_REGS_SIZE (BITS / 8 * 48)
+
+static const Ebl_Register_Location fpregset_regs[] =
+ {
+ { .offset = 0, .regno = 32, .count = 32, .bits = 64 }, /* f0-f31 */
+ { .offset = 32 * 8 + 4, .regno = 65, .count = 1, .bits = 32 } /* fpscr */
+ };
+#define FPREGSET_SIZE (33 * 8)
+
+#if BITS == 32
+# define ULONG uint32_t
+# define ALIGN_ULONG 4
+# define TYPE_ULONG ELF_T_WORD
+# define TYPE_LONG ELF_T_SWORD
+#else
+# define ULONG uint64_t
+# define ALIGN_ULONG 8
+# define TYPE_ULONG ELF_T_XWORD
+# define TYPE_LONG ELF_T_SXWORD
+#endif
+#define PID_T int32_t
+#define UID_T uint32_t
+#define GID_T uint32_t
+#define ALIGN_PID_T 4
+#define ALIGN_UID_T 4
+#define ALIGN_GID_T 4
+#define TYPE_PID_T ELF_T_SWORD
+#define TYPE_UID_T ELF_T_WORD
+#define TYPE_GID_T ELF_T_WORD
+
+#define PRSTATUS_REGSET_ITEMS \
+ { \
+ .name = "orig_gpr3", .type = TYPE_LONG, .format = 'd', \
+ .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + (4 * 34), \
+ .group = "register" \
+ }
+
+#include "linux-core-note.c"
/* Initialization of PPC specific backend library.
- Copyright (C) 2004, 2005, 2006 Red Hat, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2004.
HOOK (eh, bss_plt_p);
HOOK (eh, return_value_location);
HOOK (eh, register_info);
+ HOOK (eh, core_note);
+ HOOK (eh, auxv_info);
return MODVERSION;
}
/* PPC specific symbolic name handling.
- Copyright (C) 2004, 2005 Red Hat, Inc.
+ Copyright (C) 2004, 2005, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2004.
if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
{
+ /* In -msecure-plt mode, DT_PPC_GOT is present and must match. */
GElf_Addr gotaddr;
if (find_dyn_got (elf, ehdr, &gotaddr))
return sym->st_value == gotaddr;
- return sym->st_value == destshdr->sh_addr + 4;
+
+ /* In -mbss-plt mode, any place in the section is valid. */
+ return true;
}
const char *sname = elf_strptr (elf, ehdr->e_shstrndx, destshdr->sh_name);
/* x86-64 specific core note handling.
- Copyright (C) 2005 Red Hat, Inc.
+ Copyright (C) 2005, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
- Written by Ulrich Drepper <drepper@redhat.com>, 2005.
Red Hat elfutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by the
#include "libebl_CPU.h"
-/* We cannot include <sys/procfs.h> since the definition would be for
- the host platform and not always x86-64 as required here. */
-struct elf_prstatus
+static const Ebl_Register_Location prstatus_regs[] =
{
- struct
- {
- int32_t si_signo; /* Signal number. */
- int32_t si_code; /* Extra code. */
- int32_t si_errno; /* Errno. */
- } pr_info; /* Info associated with signal. */
- int16_t pr_cursig; /* Current signal. */
- uint64_t pr_sigpend; /* Set of pending signals. */
- uint64_t pr_sighold; /* Set of held signals. */
- int32_t pr_pid;
- int32_t pr_ppid;
- int32_t pr_pgrp;
- int32_t pr_sid;
- struct x86_64_timeval
- {
- int64_t tv_sec;
- int32_t tv_usec;
- } pr_utime; /* User time. */
- struct x86_64_timeval pr_stime; /* System time. */
- struct x86_64_timeval pr_cutime; /* Cumulative user time. */
- struct x86_64_timeval pr_cstime; /* Cumulative system time. */
- uint64_t pr_reg[27]; /* GP registers. */
- int32_t pr_fpvalid; /* True if math copro being used. */
+#define GR(at, n, dwreg) \
+ { .offset = at * 8, .regno = dwreg, .count = n, .bits = 64 }
+#define SR(at, n, dwreg) \
+ { .offset = at * 8, .regno = dwreg, .count = n, .bits = 16, .pad = 6 }
+
+ GR (0, 1, 15), /* %r15 */
+ GR (1, 1, 14), /* %r14 */
+ GR (2, 1, 13), /* %r13 */
+ GR (3, 1, 12), /* %r12 */
+ GR (4, 1, 6), /* %rbp */
+ GR (5, 1, 3), /* %rbx */
+ GR (6, 1, 11), /* %r11 */
+ GR (7, 1, 10), /* %r10 */
+ GR (8, 1, 9), /* %r9 */
+ GR (9, 1, 8), /* %r8 */
+ GR (10,1, 0), /* %rax */
+ GR (11,1, 2), /* %rcx */
+ GR (12,1, 1), /* %rdx */
+ GR (13,2, 4), /* %rsi-%rdi */
+ /* 15,1, orig_rax */
+ GR (16,1, 16), /* %rip */
+ SR (17,1, 51), /* %cs */
+ GR (18,1, 49), /* %rFLAGS */
+ GR (19,1, 7), /* %rsp */
+ SR (20,1, 52), /* %ss */
+ GR (21,2, 58), /* %fs.base-%gs.base */
+ SR (23,1, 53), /* %ds */
+ SR (24,1, 50), /* %es */
+ SR (25,2, 54), /* %fs-%gs */
+
+#undef GR
+#undef SR
};
-
-
-struct elf_prpsinfo
+#define PRSTATUS_REGS_SIZE (27 * 8)
+
+#define ULONG uint64_t
+#define PID_T int32_t
+#define UID_T uint32_t
+#define GID_T uint32_t
+#define ALIGN_ULONG 8
+#define ALIGN_PID_T 4
+#define ALIGN_UID_T 4
+#define ALIGN_GID_T 4
+#define TYPE_ULONG ELF_T_XWORD
+#define TYPE_PID_T ELF_T_SWORD
+#define TYPE_UID_T ELF_T_SWORD
+#define TYPE_GID_T ELF_T_SWORD
+
+#define PRSTATUS_REGSET_ITEMS \
+ { \
+ .name = "orig_rax", .type = ELF_T_SXWORD, .format = 'd', \
+ .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + (8 * 15), \
+ .group = "register" \
+ }
+
+static const Ebl_Register_Location fpregset_regs[] =
{
- char pr_state; /* Numeric process state. */
- char pr_sname; /* Char for pr_state. */
- char pr_zomb; /* Zombie. */
- char pr_nice; /* Nice val. */
- uint64_t pr_flag; /* Flags. */
- uint32_t pr_uid;
- uint32_t pr_gid;
- int32_t pr_pid;
- int32_t pr_ppid;
- int32_t pr_pgrp;
- int32_t pr_sid;
- /* Lots missing */
- char pr_fname[16]; /* Filename of executable. */
- char pr_psargs[80]; /* Initial part of arg list. */
+ { .offset = 0, .regno = 65, .count = 2, .bits = 16 }, /* fcw-fsw */
+ { .offset = 24, .regno = 64, .count = 1, .bits = 32 }, /* mxcsr */
+ { .offset = 32, .regno = 33, .count = 8, .bits = 80, .pad = 6 }, /* stN */
+ { .offset = 32 + 128, .regno = 17, .count = 16, .bits = 128 }, /* xmm */
};
+#define FPREGSET_SIZE 512
-
-bool
-x86_64_core_note (name, type, descsz, desc)
- const char *name __attribute__ ((unused));
- uint32_t type;
- uint32_t descsz;
- const char *desc;
-{
- bool result = false;
-
- switch (type)
- {
- case NT_PRSTATUS:
- if (descsz < sizeof (struct elf_prstatus))
- /* Not enough data. */
- break;
-
- struct elf_prstatus *stat = (struct elf_prstatus *) desc;
-
- printf (" SIGINFO: signo: %" PRId32 ", code = %" PRId32
- ", errno = %" PRId32 "\n"
- " signal: %" PRId16 ", pending: %#08" PRIx64 ", holding: %#08"
- PRIx64 "\n"
- " pid: %" PRId32 ", ppid = %" PRId32 ", pgrp = %" PRId32
- ", sid = %" PRId32 "\n"
- " utime: %6" PRId64 ".%06" PRId32
- "s, stime: %6" PRId64 ".%06" PRId32 "s\n"
- " cutime: %6" PRId64 ".%06" PRId32
- "s, cstime: %6" PRId64 ".%06" PRId32 "s\n"
- " rax: %016" PRIx64 " rbx: %016" PRIx64 "\n"
- " rcx: %016" PRIx64 " rdx: %016" PRIx64 "\n"
- " rsi: %016" PRIx64 " rdi: %016" PRIx64 "\n"
- " rbp: %016" PRIx64 " rsp: %016" PRIx64 "\n"
- " r8: %016" PRIx64 " r9: %016" PRIx64 "\n"
- " r10: %016" PRIx64 " r11: %016" PRIx64 "\n"
- " r12: %016" PRIx64 " r13: %016" PRIx64 "\n"
- " r14: %016" PRIx64 " r15: %016" PRIx64 "\n"
- " rip: %016" PRIx64 " eflags: %08" PRIx64 "\n"
- " original rax: %016" PRIx64 "\n"
- " cs: %04" PRIx64 " ds: %04" PRIx64 " es: %04" PRIx64
- " ss: %04" PRIx64 "\n"
- " fs: %04" PRIx64 " fs_base: %016" PRIx64
- " gs: %04" PRIx64 " gs_base: %016" PRIx64 "\n\n",
- stat->pr_info. si_signo,
- stat->pr_info. si_code,
- stat->pr_info. si_errno,
- stat->pr_cursig,
- stat->pr_sigpend, stat->pr_sighold,
- stat->pr_pid, stat->pr_ppid, stat->pr_pgrp, stat->pr_sid,
- stat->pr_utime.tv_sec, stat->pr_utime.tv_usec,
- stat->pr_stime.tv_sec, stat->pr_stime.tv_usec,
- stat->pr_cutime.tv_sec, stat->pr_cutime.tv_usec,
- stat->pr_cstime.tv_sec, stat->pr_cstime.tv_usec,
- stat->pr_reg[10], stat->pr_reg[5], stat->pr_reg[11],
- stat->pr_reg[12], stat->pr_reg[13], stat->pr_reg[14],
- stat->pr_reg[4], stat->pr_reg[10], stat->pr_reg[9],
- stat->pr_reg[7], stat->pr_reg[6], stat->pr_reg[5],
- stat->pr_reg[3], stat->pr_reg[2], stat->pr_reg[1],
- stat->pr_reg[0], stat->pr_reg[16], stat->pr_reg[18],
- stat->pr_reg[15], stat->pr_reg[17], stat->pr_reg[23],
- stat->pr_reg[24], stat->pr_reg[20],
- stat->pr_reg[25], stat->pr_reg[21],
- stat->pr_reg[26], stat->pr_reg[22]);
-
- /* We handled this entry. */
- result = true;
- break;
-
- case NT_PRPSINFO:
- if (descsz < sizeof (struct elf_prpsinfo))
- /* Not enough data. */
- break;
-
- struct elf_prpsinfo *info = (struct elf_prpsinfo *) desc;
-
- printf (" state: %c (%hhd), zombie: %hhd, nice: %hhd\n"
- " flags: %08" PRIx64 " uid: %" PRIu32 " gid: %" PRIu32 "\n"
- " pid: %" PRId32 " ppid: %" PRId32 " pgrp: %" PRId32
- " sid: %" PRId32 "\n"
- " fname: %.16s\n"
- " args: %.80s\n\n",
- info->pr_sname, info->pr_state, info->pr_zomb, info->pr_nice,
- info->pr_flag, info->pr_uid, info->pr_gid,
- info->pr_pid, info->pr_ppid, info->pr_pgrp, info->pr_sid,
- info->pr_fname, info->pr_psargs);
-
- /* We handled this entry. */
- result = true;
- break;
-
- default:
- break;
- }
-
- return result;
-}
+#include "linux-core-note.c"
/* Initialization of x86-64 specific backend library.
- Copyright (C) 2002, 2005, 2006 Red Hat, Inc.
+ Copyright (C) 2002, 2005, 2006, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
/* This defines the common reloc hooks based on x86_64_reloc.def. */
#include "common-reloc.c"
-
-
const char *
x86_64_init (elf, machine, eh, ehlen)
Elf *elf __attribute__ ((unused));
HOOK (eh, core_note);
HOOK (eh, return_value_location);
HOOK (eh, register_info);
+ HOOK (eh, auxv_info);
return MODVERSION;
}
return stpcpy (&name[1], "s.base") + 1 - name;
case 49:
+ *setname = "integer";
return stpcpy (name, "rflags") + 1 - name;
case 62:
return stpcpy (name, "tr") + 1 - name;
+2007-08-22 Roland McGrath <roland@redhat.com>
+
+ * libebl.h (Ebl_Core_Item): New member `group'.
+
+2007-08-19 Roland McGrath <roland@redhat.com>
+
+ * ebl-hooks.h: Add new hook auxv_info.
+ * eblopenbackend.c (default_auxv_info): New function.
+ (fill_defaults): Initialize auxv_info hook.
+ * eblauxvinfo.c : New file.
+ * Makefile.am (gen_SOURCES): Add it.
+ * libebl.h: Declare ebl_auxv_info.
+
+ * eblcorenote.c: Rewritten with new signature.
+ * Makefile.am (gen_SOURCES): Add it.
+ * libebl.h (Ebl_Register_Location, Ebl_Core_Item): New types.
+ (ebl_core_note_info): Completely revamp signature.
+ * ebl-hooks.h: Update decl.
+ * eblopenbackend.c (default_core_note): Update signature.
+
2007-07-09 Roland McGrath <roland@redhat.com>
* eblobjnotetypename.c (ebl_object_note_type_name): Handle
eblelfclass.c eblelfdata.c eblelfmachine.c \
ebl_check_special_symbol.c eblbsspltp.c eblretval.c \
eblreginfo.c eblnonerelocp.c eblrelativerelocp.c \
- eblsysvhashentrysize.c
+ eblsysvhashentrysize.c eblauxvinfo.c
libebl_a_SOURCES = $(gen_SOURCES)
/* Name of a note entry type for object files. */
const char *EBLHOOK(object_note_type_name) (uint32_t, char *, size_t);
-/* Handle core note. */
-bool EBLHOOK(core_note) (const char *, uint32_t, uint32_t, const char *);
+/* Describe core note format. */
+int EBLHOOK(core_note) (GElf_Word, GElf_Word, GElf_Word *, size_t *,
+ const Ebl_Register_Location **,
+ size_t *, const Ebl_Core_Item **);
/* Handle object file note. */
bool EBLHOOK(object_note) (const char *, uint32_t, uint32_t, const char *);
+/* Describe auxv element type. */
+int EBLHOOK(auxv_info) (GElf_Xword, const char **, const char **);
+
/* Check section name for being that of a debug informatino section. */
bool EBLHOOK(debugscn_p) (const char *);
--- /dev/null
+/* Describe known auxv types.
+ Copyright (C) 2007 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+
+ Red Hat elfutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by the
+ Free Software Foundation; version 2 of the License.
+
+ Red Hat elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ In addition, as a special exception, Red Hat, Inc. gives You the
+ additional right to link the code of Red Hat elfutils with code licensed
+ under any Open Source Initiative certified open source license
+ (http://www.opensource.org/licenses/index.php) which requires the
+ distribution of source code with any binary distribution and to
+ distribute linked combinations of the two. Non-GPL Code permitted under
+ this exception must only link to the code of Red Hat elfutils through
+ those well defined interfaces identified in the file named EXCEPTION
+ found in the source code files (the "Approved Interfaces"). The files
+ of Non-GPL Code may instantiate templates or use macros or inline
+ functions from the Approved Interfaces without causing the resulting
+ work to be covered by the GNU General Public License. Only Red Hat,
+ Inc. may make changes or additions to the list of Approved Interfaces.
+ Red Hat's grant of this exception is conditioned upon your not adding
+ any new exceptions. If you wish to add a new Approved Interface or
+ exception, please contact Red Hat. You must obey the GNU General Public
+ License in all respects for all of the Red Hat elfutils code and other
+ code used in conjunction with Red Hat elfutils except the Non-GPL Code
+ covered by this exception. If you modify this file, you may extend this
+ exception to your version of the file, but you are not obligated to do
+ so. If you do not wish to provide this exception without modification,
+ you must delete this exception statement from your version and license
+ this file solely under the GPL without exception.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <byteswap.h>
+#include <endian.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <libeblP.h>
+
+#define AUXV_TYPES \
+ TYPE (NULL, "") \
+ TYPE (IGNORE, "") \
+ TYPE (EXECFD, "d") \
+ TYPE (PHDR, "p") \
+ TYPE (PHENT, "u") \
+ TYPE (PHNUM, "u") \
+ TYPE (PAGESZ, "u") \
+ TYPE (BASE, "p") \
+ TYPE (FLAGS, "x") \
+ TYPE (ENTRY, "p") \
+ TYPE (NOTELF, "") \
+ TYPE (UID, "u") \
+ TYPE (EUID, "u") \
+ TYPE (GID, "u") \
+ TYPE (EGID, "u") \
+ TYPE (CLKTCK, "u") \
+ TYPE (PLATFORM, "s") \
+ TYPE (HWCAP, "x") \
+ TYPE (FPUCW, "x") \
+ TYPE (DCACHEBSIZE, "d") \
+ TYPE (ICACHEBSIZE, "d") \
+ TYPE (UCACHEBSIZE, "d") \
+ TYPE (IGNOREPPC, "") \
+ TYPE (SECURE, "u") \
+ TYPE (SYSINFO, "p") \
+ TYPE (SYSINFO_EHDR, "p") \
+ TYPE (L1I_CACHESHAPE, "d") \
+ TYPE (L1D_CACHESHAPE, "d") \
+ TYPE (L2_CACHESHAPE, "d") \
+ TYPE (L3_CACHESHAPE, "d")
+
+static const struct
+{
+ const char *name, *format;
+} auxv_types[] =
+ {
+#define TYPE(name, fmt) [AT_##name] = { #name, fmt },
+ AUXV_TYPES
+#undef TYPE
+ };
+#define nauxv_types (sizeof auxv_types / sizeof auxv_types[0])
+
+int
+ebl_auxv_info (ebl, a_type, name, format)
+ Ebl *ebl;
+ GElf_Xword a_type;
+ const char **name;
+ const char **format;
+{
+ int result = ebl->auxv_info (a_type, name, format);
+ if (result == 0 && a_type < nauxv_types)
+ {
+ /* The machine specific function did not know this type. */
+ *name = auxv_types[a_type].name;
+ *format = auxv_types[a_type].format;
+ result = 1;
+ }
+ return result;
+}
-/* Print contents of core note.
- Copyright (C) 2002, 2004, 2005, 2007 Red Hat, Inc.
+/* Describe known core note formats.
+ Copyright (C) 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
- Written by Ulrich Drepper <drepper@redhat.com>, 2002.
Red Hat elfutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by the
#include <libeblP.h>
-void
-ebl_core_note (ebl, name, type, descsz, desc)
+int
+ebl_core_note (ebl, n_type, descsz,
+ regs_offset, nregloc, reglocs, nitems, items)
Ebl *ebl;
- const char *name;
- uint32_t type;
- uint32_t descsz;
- const char *desc;
+ GElf_Word n_type;
+ GElf_Word descsz;
+ GElf_Word *regs_offset;
+ size_t *nregloc;
+ const Ebl_Register_Location **reglocs;
+ size_t *nitems;
+ const Ebl_Core_Item **items;
{
- GElf_Ehdr ehdr_mem;
- GElf_Ehdr *ehdr = gelf_getehdr (ebl->elf, &ehdr_mem);
- assert (ehdr != NULL);
- int class = ehdr->e_ident[EI_CLASS];
- int endian = ehdr->e_ident[EI_DATA];
-
- if (! ebl->core_note (name, type, descsz, desc))
- /* The machine specific function did not know this type. */
- switch (type)
- {
- case NT_PLATFORM:
- printf (gettext (" Platform: %.*s\n"), (int) descsz, desc);
- break;
-
- case NT_AUXV:
- ;
- size_t elsize = (class == ELFCLASS32
- ? sizeof (Elf32_auxv_t) : sizeof (Elf64_auxv_t));
-
- for (size_t cnt = 0; (cnt + 1) * elsize <= descsz; ++cnt)
- {
- uintmax_t atype;
- uintmax_t val;
-
- if (class == ELFCLASS32)
- {
- Elf32_auxv_t *auxv = &((Elf32_auxv_t *) desc)[cnt];
-
- if ((endian == ELFDATA2LSB && __BYTE_ORDER == __LITTLE_ENDIAN)
- || (endian == ELFDATA2MSB && __BYTE_ORDER == __BIG_ENDIAN))
- {
- atype = auxv->a_type;
- val = auxv->a_un.a_val;
- }
- else
- {
- atype = bswap_32 (auxv->a_type);
- val = bswap_32 (auxv->a_un.a_val);
- }
- }
- else
- {
- Elf64_auxv_t *auxv = &((Elf64_auxv_t *) desc)[cnt];
-
- if ((endian == ELFDATA2LSB && __BYTE_ORDER == __LITTLE_ENDIAN)
- || (endian == ELFDATA2MSB && __BYTE_ORDER == __BIG_ENDIAN))
- {
- atype = auxv->a_type;
- val = auxv->a_un.a_val;
- }
- else
- {
- atype = bswap_64 (auxv->a_type);
- val = bswap_64 (auxv->a_un.a_val);
- }
- }
-
- /* XXX Do we need the auxiliary vector info anywhere
- else? If yes, move code into a separate function. */
- const char *at;
-
- switch (atype)
+ int result = ebl->core_note (n_type, descsz, regs_offset, nregloc, reglocs,
+ nitems, items);
+ if (result == 0)
+ {
+ /* The machine specific function did not know this type. */
+
+ *regs_offset = 0;
+ *nregloc = 0;
+ *reglocs = NULL;
+ switch (n_type)
+ {
+#define ITEMS(type, table) \
+ case type: \
+ *items = table; \
+ *nitems = sizeof table / sizeof table[0]; \
+ result = 1; \
+ break
+
+ static const Ebl_Core_Item platform[] =
+ {
{
-#define NEW_AT(name) case AT_##name: at = #name; break
- NEW_AT (NULL);
- NEW_AT (IGNORE);
- NEW_AT (EXECFD);
- NEW_AT (PHDR);
- NEW_AT (PHENT);
- NEW_AT (PHNUM);
- NEW_AT (PAGESZ);
- NEW_AT (BASE);
- NEW_AT (FLAGS);
- NEW_AT (ENTRY);
- NEW_AT (NOTELF);
- NEW_AT (UID);
- NEW_AT (EUID);
- NEW_AT (GID);
- NEW_AT (EGID);
- NEW_AT (CLKTCK);
- NEW_AT (PLATFORM);
- NEW_AT (HWCAP);
- NEW_AT (FPUCW);
- NEW_AT (DCACHEBSIZE);
- NEW_AT (ICACHEBSIZE);
- NEW_AT (UCACHEBSIZE);
- NEW_AT (IGNOREPPC);
- NEW_AT (SECURE);
- NEW_AT (SYSINFO);
- NEW_AT (SYSINFO_EHDR);
- NEW_AT (L1I_CACHESHAPE);
- NEW_AT (L1D_CACHESHAPE);
- NEW_AT (L2_CACHESHAPE);
- NEW_AT (L3_CACHESHAPE);
-
- default:;
- static char buf[30];
- sprintf (buf, "%ju (AT_?""?""?)", atype);
- at = buf;
- break;
- }
-
- switch (atype)
- {
- /* Decimal. */
- case AT_EXECFD:
- case AT_PHENT:
- case AT_PHNUM:
- case AT_PAGESZ:
- case AT_UID:
- case AT_EUID:
- case AT_GID:
- case AT_EGID:
- case AT_CLKTCK:
- case AT_FPUCW:
- case AT_DCACHEBSIZE:
- case AT_ICACHEBSIZE:
- case AT_UCACHEBSIZE:
- case AT_SECURE:
- case AT_L1I_CACHESHAPE:
- case AT_L1D_CACHESHAPE:
- case AT_L2_CACHESHAPE:
- case AT_L3_CACHESHAPE:
- printf (" %s: %jd\n", at, val);
- break;
-
- /* Normally zero. */
- case AT_NULL:
- case AT_IGNORE:
- case AT_IGNOREPPC:
- case AT_NOTELF:
- default:
- if (val == 0)
- {
- printf (" %s\n", at);
- break;
- }
- /* Fall through. */
-
- /* Hex. */
- case AT_PHDR:
- case AT_BASE:
- case AT_FLAGS: /* XXX Print flags? */
- case AT_ENTRY:
- case AT_PLATFORM: /* XXX Get string? */
- case AT_HWCAP: /* XXX Print flags? */
- case AT_SYSINFO:
- case AT_SYSINFO_EHDR:
- printf (" %s: %#jx\n", at, val);
- break;
+ .name = "Platform",
+ .type = ELF_T_BYTE, .count = 0, .format = 's'
}
+ };
+ ITEMS (NT_PLATFORM, platform);
- if (atype == AT_NULL)
- /* Reached the end. */
- break;
- }
- break;
+#undef ITEMS
+ }
+ }
- default:
- /* Unknown type. */
- break;
- }
+ return result;
}
size_t len);
static const char *default_object_note_type_name (uint32_t, char *buf,
size_t len);
-static bool default_core_note (const char *name, uint32_t type,
- uint32_t descsz, const char *desc);
+static int default_core_note (GElf_Word n_type, GElf_Word descsz,
+ GElf_Word *regs_offset, size_t *nregloc,
+ const Ebl_Register_Location **reglocs,
+ size_t *nitems, const Ebl_Core_Item **);
+static int default_auxv_info (GElf_Xword a_type,
+ const char **name, const char **format);
static bool default_object_note (const char *name, uint32_t type,
uint32_t descsz, const char *desc);
static bool default_debugscn_p (const char *name);
result->core_note_type_name = default_core_note_type_name;
result->object_note_type_name = default_object_note_type_name;
result->core_note = default_core_note;
+ result->auxv_info = default_auxv_info;
result->object_note = default_object_note;
result->debugscn_p = default_debugscn_p;
result->copy_reloc_p = default_copy_reloc_p;
return NULL;
}
+static int
+default_auxv_info (GElf_Xword a_type __attribute__ ((unused)),
+ const char **name __attribute__ ((unused)),
+ const char **format __attribute__ ((unused)))
+{
+ return 0;
+}
+
+static int
+default_core_note (GElf_Word n_type __attribute__ ((unused)),
+ GElf_Word descsz __attribute__ ((unused)),
+ GElf_Word *ro __attribute__ ((unused)),
+ size_t *nregloc __attribute__ ((unused)),
+ const Ebl_Register_Location **reglocs
+ __attribute__ ((unused)),
+ size_t *nitems __attribute__ ((unused)),
+ const Ebl_Core_Item **items __attribute__ ((unused)))
+{
+ return 0;
+}
+
static const char *
default_object_note_type_name (uint32_t ignore __attribute__ ((unused)),
char *buf __attribute__ ((unused)),
return NULL;
}
-static bool
-default_core_note (const char *name __attribute__ ((unused)),
- uint32_t type __attribute__ ((unused)),
- uint32_t descsz __attribute__ ((unused)),
- const char *desc __attribute__ ((unused)))
-{
- return NULL;
-}
-
static bool
default_object_note (const char *name __attribute__ ((unused)),
uint32_t type __attribute__ ((unused)),
extern const char *ebl_object_note_type_name (Ebl *ebl, uint32_t type,
char *buf, size_t len);
-/* Print information about core note if available. */
-extern void ebl_core_note (Ebl *ebl, const char *name, uint32_t type,
- uint32_t descsz, const char *desc);
-
/* Print information about object note if available. */
extern void ebl_object_note (Ebl *ebl, const char *name, uint32_t type,
uint32_t descsz, const char *desc);
/* Get offset in wide char string table for string associated with SE. */
extern size_t ebl_gstrtaboffset (struct Ebl_GStrent *se);
+
+/* Register map info. */
+typedef struct
+{
+ Dwarf_Half offset; /* Byte offset in register data block. */
+ Dwarf_Half regno; /* DWARF register number. */
+ uint8_t bits; /* Bits of data for one register. */
+ uint8_t pad; /* Bytes of padding after register's data. */
+ Dwarf_Half count; /* Consecutive register numbers here. */
+} Ebl_Register_Location;
+
+/* Non-register data items in core notes. */
+typedef struct
+{
+ const char *name; /* Printable identifier. */
+ const char *group; /* Identifier for category of related items. */
+ Dwarf_Half offset; /* Byte offset in note data. */
+ Dwarf_Half count;
+ Elf_Type type;
+ char format;
+ bool thread_identifier;
+} Ebl_Core_Item;
+
+/* Describe the format of a core file note with type field matching N_TYPE
+ and descriptor size matching DESCSZ. */
+extern int ebl_core_note (Ebl *ebl, GElf_Word n_type, GElf_Word descsz,
+ GElf_Word *regs_offset, size_t *nregloc,
+ const Ebl_Register_Location **reglocs,
+ size_t *nitems, const Ebl_Core_Item **items)
+ __nonnull_attribute__ (1, 4, 5, 6, 7, 8);
+
+/* Describe the auxv type number. */
+extern int ebl_auxv_info (Ebl *ebl, GElf_Xword a_type,
+ const char **name, const char **format)
+ __nonnull_attribute__ (1, 3, 4);
+
+
#ifdef __cplusplus
}
#endif
+2007-08-19 Roland McGrath <roland@redhat.com>
+
+ * gelf_update_auxv.c: New file.
+ * gelf_getauxv.c: New file.
+ * Makefile.am (libelf_a_SOURCES): Add them.
+ * gelf.h: Declare gelf_getauxv, gelf_update_auxv.
+ * libelf.map (ELFUTILS_1.3): New set, inherits fom ELFUTILS_1.2.
+ Export gelf_getauxv, gelf_update_auxv.
+
+ * libelf.h (Elf_Type): Add ELF_T_AUXV.
+ * abstract.h: Add auxv_t entries.
+ * exttypes.h: Likewise.
+ * gelf_xlate.h: Likewise.
+ * gelf_xlate.c (__elf_xfctstom): Add ELF_T_AUXV entries.
+ * gelf_fsize.c (__libelf_type_sizes): Likewise.
+
2007-08-12 Roland McGrath <roland@redhat.com>
* elf32_updatefile.c (compare_sections): Sort secondarily on sh_size,
gelf_getdyn.c gelf_update_dyn.c \
gelf_getmove.c gelf_update_move.c \
gelf_getsyminfo.c gelf_update_syminfo.c \
+ gelf_getauxv.c gelf_update_auxv.c \
gelf_xlatetof.c gelf_xlatetom.c \
nlist.c \
gelf_getsymshndx.c gelf_update_symshndx.c \
/* Abstract description of component ELF types.
- Copyright (C) 1998, 1999, 2000, 2002, 2004 Red Hat, Inc.
+ Copyright (C) 1998, 1999, 2000, 2002, 2004, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
Lib (32, Ext)
#define Lib64(Ext) \
Lib (64, Ext)
+
+#define auxv_t32(Ext) \
+START (32, auxv_t, Ext##auxv_t) \
+ TYPE_NAME (ElfW2(32, Ext##Word), a_type) \
+ TYPE_EXTRA (union {) \
+ TYPE_EXTRA (ElfW2(32, Ext##Word) a_val;) \
+ TYPE_XLATE (Elf32_cvt_Addr1 (&tdest->a_un.a_val, &tsrc->a_un.a_val);) \
+ TYPE_EXTRA (} a_un;) \
+END (32, Ext##auxv_t)
+#define auxv_t64(Ext) \
+START (64, auxv_t, Ext##auxv_t) \
+ TYPE_NAME (ElfW2(64, Ext##Xword), a_type) \
+ TYPE_EXTRA (union {) \
+ TYPE_EXTRA (ElfW2(64, Ext##Xword) a_val;) \
+ TYPE_XLATE (Elf64_cvt_Addr1 (&tdest->a_un.a_val, &tsrc->a_un.a_val);) \
+ TYPE_EXTRA (} a_un;) \
+END (64, Ext##auxv_t)
/* External ELF types.
- Copyright (C) 1998, 1999, 2000, 2002 Red Hat, Inc.
+ Copyright (C) 1998, 1999, 2000, 2002, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
Vernaux32 (Ext_);
Syminfo32 (Ext_);
Move32 (Ext_);
+auxv_t32 (Ext_);
Ehdr64 (Ext_);
Phdr64 (Ext_);
Vernaux64 (Ext_);
Syminfo64 (Ext_);
Move64 (Ext_);
+auxv_t64 (Ext_);
#undef START
#undef END
/* This file defines generic ELF types, structures, and macros.
- Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005 Red Hat, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
GElf_Verdaux *__src);
+/* Get auxv entry at the given index. */
+extern GElf_auxv_t *gelf_getauxv (Elf_Data *__data, int __ndx,
+ GElf_auxv_t *__dst);
+
+/* Update auxv entry at the given index. */
+extern int gelf_update_auxv (Elf_Data *__data, int __ndx, GElf_auxv_t *__src);
+
+
/* Retrieve uninterpreted chunk of the file contents. */
extern char *gelf_rawchunk (Elf *__elf, GElf_Off __offset, GElf_Word __size);
/* Return the size of an object file type.
- Copyright (C) 1998, 1999, 2000, 2002 Red Hat, Inc.
+ Copyright (C) 1998, 1999, 2000, 2002, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
[ELF_T_VNAUX] = sizeof (ElfW2(LIBELFBITS, Ext_Vernaux)), \
[ELF_T_NHDR] = sizeof (ElfW2(LIBELFBITS, Ext_Nhdr)), \
[ELF_T_SYMINFO] = sizeof (ElfW2(LIBELFBITS, Ext_Syminfo)), \
- [ELF_T_MOVE] = sizeof (ElfW2(LIBELFBITS, Ext_Move))
+ [ELF_T_MOVE] = sizeof (ElfW2(LIBELFBITS, Ext_Move)), \
+ [ELF_T_AUXV] = sizeof (ElfW2(LIBELFBITS, Ext_auxv_t))
TYPE_SIZES (32)
},
[ELFCLASS64 - 1] = {
--- /dev/null
+/* Get information from auxiliary vector at the given index.
+ Copyright (C) 2007 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+
+ Red Hat elfutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by the
+ Free Software Foundation; version 2 of the License.
+
+ Red Hat elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ In addition, as a special exception, Red Hat, Inc. gives You the
+ additional right to link the code of Red Hat elfutils with code licensed
+ under any Open Source Initiative certified open source license
+ (http://www.opensource.org/licenses/index.php) which requires the
+ distribution of source code with any binary distribution and to
+ distribute linked combinations of the two. Non-GPL Code permitted under
+ this exception must only link to the code of Red Hat elfutils through
+ those well defined interfaces identified in the file named EXCEPTION
+ found in the source code files (the "Approved Interfaces"). The files
+ of Non-GPL Code may instantiate templates or use macros or inline
+ functions from the Approved Interfaces without causing the resulting
+ work to be covered by the GNU General Public License. Only Red Hat,
+ Inc. may make changes or additions to the list of Approved Interfaces.
+ Red Hat's grant of this exception is conditioned upon your not adding
+ any new exceptions. If you wish to add a new Approved Interface or
+ exception, please contact Red Hat. You must obey the GNU General Public
+ License in all respects for all of the Red Hat elfutils code and other
+ code used in conjunction with Red Hat elfutils except the Non-GPL Code
+ covered by this exception. If you modify this file, you may extend this
+ exception to your version of the file, but you are not obligated to do
+ so. If you do not wish to provide this exception without modification,
+ you must delete this exception statement from your version and license
+ this file solely under the GPL without exception.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_auxv_t *
+gelf_getauxv (data, ndx, dst)
+ Elf_Data *data;
+ int ndx;
+ GElf_auxv_t *dst;
+{
+ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+ GElf_auxv_t *result = NULL;
+ Elf *elf;
+
+ if (data_scn == NULL)
+ return NULL;
+
+ if (unlikely (data_scn->d.d_type != ELF_T_AUXV))
+ {
+ __libelf_seterrno (ELF_E_INVALID_HANDLE);
+ return NULL;
+ }
+
+ elf = data_scn->s->elf;
+
+ rwlock_rdlock (elf->lock);
+
+ /* This is the one place where we have to take advantage of the fact
+ that an `Elf_Data' pointer is also a pointer to `Elf_Data_Scn'.
+ The interface is broken so that it requires this hack. */
+ if (elf->class == ELFCLASS32)
+ {
+ Elf32_auxv_t *src;
+
+ /* Here it gets a bit more complicated. The format of the vector
+ entries has to be converted. The user better have provided a
+ buffer where we can store the information. While copying the data
+ we convert the format. */
+ if (unlikely ((ndx + 1) * sizeof (Elf32_auxv_t) > data_scn->d.d_size))
+ {
+ __libelf_seterrno (ELF_E_INVALID_INDEX);
+ goto out;
+ }
+
+ src = &((Elf32_auxv_t *) data_scn->d.d_buf)[ndx];
+
+ /* This might look like a simple copy operation but it's
+ not. There are zero- and sign-extensions going on. */
+ dst->a_type = src->a_type;
+ dst->a_un.a_val = src->a_un.a_val;
+ }
+ else
+ {
+ /* If this is a 64 bit object it's easy. */
+ assert (sizeof (GElf_auxv_t) == sizeof (Elf64_auxv_t));
+
+ /* The data is already in the correct form. Just make sure the
+ index is OK. */
+ if (unlikely ((ndx + 1) * sizeof (GElf_auxv_t) > data_scn->d.d_size))
+ {
+ __libelf_seterrno (ELF_E_INVALID_INDEX);
+ goto out;
+ }
+
+ *dst = ((GElf_auxv_t *) data_scn->d.d_buf)[ndx];
+ }
+
+ result = dst;
+
+ out:
+ rwlock_unlock (elf->lock);
+
+ return result;
+}
--- /dev/null
+/* Update information in dynamic table at the given index.
+ Copyright (C) 2007 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+
+ Red Hat elfutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by the
+ Free Software Foundation; version 2 of the License.
+
+ Red Hat elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ In addition, as a special exception, Red Hat, Inc. gives You the
+ additional right to link the code of Red Hat elfutils with code licensed
+ under any Open Source Initiative certified open source license
+ (http://www.opensource.org/licenses/index.php) which requires the
+ distribution of source code with any binary distribution and to
+ distribute linked combinations of the two. Non-GPL Code permitted under
+ this exception must only link to the code of Red Hat elfutils through
+ those well defined interfaces identified in the file named EXCEPTION
+ found in the source code files (the "Approved Interfaces"). The files
+ of Non-GPL Code may instantiate templates or use macros or inline
+ functions from the Approved Interfaces without causing the resulting
+ work to be covered by the GNU General Public License. Only Red Hat,
+ Inc. may make changes or additions to the list of Approved Interfaces.
+ Red Hat's grant of this exception is conditioned upon your not adding
+ any new exceptions. If you wish to add a new Approved Interface or
+ exception, please contact Red Hat. You must obey the GNU General Public
+ License in all respects for all of the Red Hat elfutils code and other
+ code used in conjunction with Red Hat elfutils except the Non-GPL Code
+ covered by this exception. If you modify this file, you may extend this
+ exception to your version of the file, but you are not obligated to do
+ so. If you do not wish to provide this exception without modification,
+ you must delete this exception statement from your version and license
+ this file solely under the GPL without exception.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_auxv (data, ndx, src)
+ Elf_Data *data;
+ int ndx;
+ GElf_auxv_t *src;
+{
+ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+ Elf_Scn *scn;
+ int result = 0;
+
+ if (data == NULL)
+ return 0;
+
+ if (unlikely (ndx < 0))
+ {
+ __libelf_seterrno (ELF_E_INVALID_INDEX);
+ return 0;
+ }
+
+ if (unlikely (data_scn->d.d_type != ELF_T_AUXV))
+ {
+ /* The type of the data better should match. */
+ __libelf_seterrno (ELF_E_DATA_MISMATCH);
+ return 0;
+ }
+
+ scn = data_scn->s;
+ rwlock_wrlock (scn->elf->lock);
+
+ if (scn->elf->class == ELFCLASS32)
+ {
+ Elf32_auxv_t *auxv;
+
+ /* There is the possibility that the values in the input are
+ too large. */
+ if (unlikely (src->a_type > 0xffffffffll)
+ || unlikely (src->a_un.a_val > 0xffffffffull))
+ {
+ __libelf_seterrno (ELF_E_INVALID_DATA);
+ goto out;
+ }
+
+ /* Check whether we have to resize the data buffer. */
+ if (unlikely ((ndx + 1) * sizeof (Elf32_auxv_t) > data_scn->d.d_size))
+ {
+ __libelf_seterrno (ELF_E_INVALID_INDEX);
+ goto out;
+ }
+
+ auxv = &((Elf32_auxv_t *) data_scn->d.d_buf)[ndx];
+
+ auxv->a_type = src->a_type;
+ auxv->a_un.a_val = src->a_un.a_val;
+ }
+ else
+ {
+ /* Check whether we have to resize the data buffer. */
+ if (unlikely ((ndx + 1) * sizeof (Elf64_auxv_t) > data_scn->d.d_size))
+ {
+ __libelf_seterrno (ELF_E_INVALID_INDEX);
+ goto out;
+ }
+
+ ((Elf64_auxv_t *) data_scn->d.d_buf)[ndx] = *src;
+ }
+
+ result = 1;
+
+ /* Mark the section as modified. */
+ scn->flags |= ELF_F_DIRTY;
+
+ out:
+ rwlock_unlock (scn->elf->lock);
+
+ return result;
+}
/* Transformation functions for ELF data types.
- Copyright (C) 1998, 1999, 2000, 2002, 2004, 2005, 2006 Red Hat, Inc.
+ Copyright (C) 1998,1999,2000,2002,2004,2005,2006,2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
[ELF_T_NHDR] = ElfW2(Bits, cvt_Nhdr), \
[ELF_T_SYMINFO] = ElfW2(Bits, cvt_Syminfo), \
[ELF_T_MOVE] = ElfW2(Bits, cvt_Move), \
- [ELF_T_LIB] = ElfW2(Bits, cvt_Lib)
+ [ELF_T_LIB] = ElfW2(Bits, cvt_Lib), \
+ [ELF_T_AUXV] = ElfW2(Bits, cvt_auxv_t)
define_xfcts (32),
[ELF_T_GNUHASH] = Elf32_cvt_Word
},
/* Helper file for type conversion function generation.
- Copyright (C) 1998, 1999, 2000, 2002, 2004 Red Hat, Inc.
+ Copyright (C) 1998, 1999, 2000, 2002, 2004, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
TYPE (Syminfo, LIBELFBITS)
TYPE (Move, LIBELFBITS)
TYPE (Lib, LIBELFBITS)
+TYPE (auxv_t, LIBELFBITS)
/* Prepare for the next round. */
/* Interface for libelf.
- Copyright (C) 1998, 1999, 2000, 2002, 2004, 2005, 2006 Red Hat, Inc.
+ Copyright (C) 1998, 1999, 2000, 2002, 2004, 2005, 2006, 2007 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
ELF_T_MOVE, /* Elf32_Move, Elf64_Move, ... */
ELF_T_LIB, /* Elf32_Lib, Elf64_Lib, ... */
ELF_T_GNUHASH, /* GNU-style hash section. */
+ ELF_T_AUXV, /* Elf32_auxv_t, Elf64_auxv_t, ... */
/* Keep this the last entry. */
ELF_T_NUM
} Elf_Type;
global:
elf_gnu_hash;
} ELFUTILS_1.1.1;
+
+ELFUTILS_1.3 {
+ global:
+ gelf_getauxv;
+ gelf_update_auxv;
+};
+2007-08-23 Roland McGrath <roland@redhat.com>
+
+ * readelf.c (printf_with_wrap): Function removed.
+ (REGISTER_WRAP_COLUMN): New macro.
+ (handle_core_register): Use print_core_item instead.
+ (struct register_info): New type.
+ (compare_registers, compare_register_sets): New functions.
+ (register_bitpos, compare_sets_by_info): New functions.
+ (handle_core_registers): Use those to segregate and sort registers
+ for display.
+
+ * readelf.c (ITEM_WRAP_COLUMN): New macro.
+ (print_core_item): New function.
+ (handle_core_item): Use it instead of printf_with_wrap.
+ (compare_core_items, compare_core_item_groups): New functions.
+ (handle_core_items): Use them. Sort by group and force line breaks
+ between groups.
+
+ * readelf.c (handle_core_registers, handle_core_items): New functions,
+ broken out of ...
+ (handle_core_note): ... here. Call them.
+
+2007-08-22 Roland McGrath <roland@redhat.com>
+
+ * unstrip.c (new_shstrtab): New function, broken out of ...
+ (copy_elided_sections): ... here.
+
+2007-08-20 Roland McGrath <roland@redhat.com>
+
+ Avoid local function trampolines in nm binary.
+ * nm.c (sort_by_address): Move to a static function instead of local
+ inside show_symbols.
+ (sort_by_name_strtab): New static variable.
+ (sort_by_name): Use it. Move to a static function instead of local
+ inside show_symbols.
+ (show_symbols): Set sort_by_name_strtab.
+
+2007-08-19 Roland McGrath <roland@redhat.com>
+
+ * readelf.c (handle_auxv_note): New function.
+ (handle_notes): Call it.
+
+ * readelf.c (printf_with_wrap, convert): New functions.
+ (handle_core_item, (handle_core_register): New functions.
+ (handle_notes): Call those with details from ebl_core_note.
+
2007-08-12 Roland McGrath <roland@redhat.com>
* elflint.c (check_note): Accept type 0 with name "Linux".
/* Maximum size of memory we allocate on the stack. */
#define MAX_STACK_ALLOC 65536
-static void
-show_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn,
- GElf_Shdr *shdr, const char *prefix, const char *fname,
- const char *fullname)
+static int
+sort_by_address (const void *p1, const void *p2)
{
- int sort_by_name (const void *p1, const void *p2)
- {
- GElf_SymX *s1 = (GElf_SymX *) p1;
- GElf_SymX *s2 = (GElf_SymX *) p2;
- int result;
+ GElf_SymX *s1 = (GElf_SymX *) p1;
+ GElf_SymX *s2 = (GElf_SymX *) p2;
- result = strcmp (elf_strptr (ebl->elf, shdr->sh_link, s1->sym.st_name),
- elf_strptr (ebl->elf, shdr->sh_link, s2->sym.st_name));
+ int result = (s1->sym.st_value < s2->sym.st_value
+ ? -1 : (s1->sym.st_value == s2->sym.st_value ? 0 : 1));
- return reverse_sort ? -result : result;
- }
+ return reverse_sort ? -result : result;
+}
- int sort_by_address (const void *p1, const void *p2)
- {
- GElf_SymX *s1 = (GElf_SymX *) p1;
- GElf_SymX *s2 = (GElf_SymX *) p2;
+static Elf_Data *sort_by_name_strtab;
+
+static int
+sort_by_name (const void *p1, const void *p2)
+{
+ GElf_SymX *s1 = (GElf_SymX *) p1;
+ GElf_SymX *s2 = (GElf_SymX *) p2;
- int result = (s1->sym.st_value < s2->sym.st_value
- ? -1 : (s1->sym.st_value == s2->sym.st_value ? 0 : 1));
+ const char *n1 = sort_by_name_strtab->d_buf + s1->sym.st_name;
+ const char *n2 = sort_by_name_strtab->d_buf + s2->sym.st_name;
- return reverse_sort ? -result : result;
- }
+ int result = strcmp (n1, n2);
+
+ return reverse_sort ? -result : result;
+}
+static void
+show_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn,
+ GElf_Shdr *shdr, const char *prefix, const char *fname,
+ const char *fullname)
+{
/* Get the section header string table index. */
size_t shstrndx;
if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
/* Sort the entries according to the users wishes. */
if (sort == sort_name)
- qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_name);
+ {
+ sort_by_name_strtab = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link),
+ NULL);
+ qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_name);
+ }
else if (sort == sort_numeric)
qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_address);
#include <libdw.h>
#include <libintl.h>
#include <locale.h>
+#include <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
}
+#define ITEM_INDENT 4
+#define ITEM_WRAP_COLUMN 150
+#define REGISTER_WRAP_COLUMN 75
+
+/* Print "NAME: FORMAT", wrapping when FORMAT_MAX chars of FORMAT would
+ make the line exceed ITEM_WRAP_COLUMN. Unpadded numbers look better
+ for the core items. But we do not want the line breaks to depend on
+ the particular values. */
+static unsigned int
+__attribute__ ((format (printf, 7, 8)))
+print_core_item (unsigned int colno, char sep, unsigned int wrap,
+ size_t name_width, const char *name,
+ size_t format_max, const char *format, ...)
+{
+ size_t len = strlen (name);
+ if (name_width < len)
+ name_width = len;
+
+ size_t n = name_width + sizeof ": " - 1 + format_max;
+
+ if (colno == 0)
+ {
+ printf ("%*s", ITEM_INDENT, "");
+ colno = ITEM_INDENT + n;
+ }
+ else if (colno + 2 + n < wrap)
+ {
+ printf ("%c ", sep);
+ colno += 2 + n;
+ }
+ else
+ {
+ printf ("\n%*s", ITEM_INDENT, "");
+ colno = ITEM_INDENT + n;
+ }
+
+ printf ("%s: %*s", name, (int) (name_width - len), "");
+
+ va_list ap;
+ va_start (ap, format);
+ vprintf (format, ap);
+ va_end (ap);
+
+ return colno;
+}
+
+static const void *
+convert (Elf *core, Elf_Type type, uint_fast16_t count,
+ void *value, const void *data)
+{
+ Elf_Data valuedata =
+ {
+ .d_type = type,
+ .d_buf = value,
+ .d_size = gelf_fsize (core, type, count, EV_CURRENT),
+ .d_version = EV_CURRENT,
+ };
+ Elf_Data indata =
+ {
+ .d_type = type,
+ .d_buf = (void *) data,
+ .d_size = valuedata.d_size,
+ .d_version = EV_CURRENT,
+ };
+
+ Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
+ ? elf32_xlatetom : elf64_xlatetom)
+ (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
+ if (d == NULL)
+ error (EXIT_FAILURE, 0,
+ gettext ("cannot convert core note data: %s"), elf_errmsg (-1));
+
+ return data + indata.d_size;
+}
+
+typedef uint8_t GElf_Byte;
+
+static unsigned int
+handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
+ unsigned int colno)
+{
+ uint_fast16_t count = item->count ?: 1;
+
+#define TYPES \
+ DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8, 4); \
+ DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16, 6); \
+ DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32, 11); \
+ DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32, 11); \
+ DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64, 20); \
+ DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64, 20)
+
+#define DO_TYPE(NAME, Name, hex, dec, max) GElf_##Name Name[count]
+ union { TYPES; } value;
+#undef DO_TYPE
+
+ desc = convert (core, item->type, count, &value, desc + item->offset);
+
+ switch (item->format)
+ {
+ case 'd':
+ assert (count == 1);
+ switch (item->type)
+ {
+#define DO_TYPE(NAME, Name, hex, dec, max) \
+ case ELF_T_##NAME: \
+ colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, \
+ 0, item->name, max, dec, value.Name[0]); \
+ break
+ TYPES;
+#undef DO_TYPE
+ default:
+ abort ();
+ }
+ break;
+
+ case 'x':
+ assert (count == 1);
+ switch (item->type)
+ {
+#define DO_TYPE(NAME, Name, hex, dec, max) \
+ case ELF_T_##NAME: \
+ colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, \
+ 0, item->name, max, hex, value.Name[0]); \
+ break
+ TYPES;
+#undef DO_TYPE
+ default:
+ abort ();
+ }
+ break;
+
+ case 'b':
+ assert (count == 1);
+ Dwarf_Word bits = 0;
+ Dwarf_Word bit = 0;
+ switch (item->type)
+ {
+#define DO_TYPE(NAME, Name, hex, dec, max) \
+ case ELF_T_##NAME: \
+ bits = value.Name[0]; \
+ bit = (Dwarf_Word) 1 << ((sizeof value.Name[0] * 8) - 1); \
+ break
+ TYPES;
+#undef DO_TYPE
+ default:
+ abort ();
+ }
+ char printed[sizeof (Dwarf_Word) * 8 + 1];
+ int i = 0;
+ while (bit != 0)
+ {
+ printed[i++] = (bits & bit) ? '1' : '0';
+ bit >>= 1;
+ }
+ colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
+ sizeof printed - 1, "%.*s", i, printed);
+ break;
+
+ case 'T':
+ assert (count == 2);
+ Dwarf_Word sec;
+ Dwarf_Word usec;
+ size_t maxfmt = 7;
+ switch (item->type)
+ {
+#define DO_TYPE(NAME, Name, hex, dec, max) \
+ case ELF_T_##NAME: \
+ sec = value.Name[0]; \
+ usec = value.Name[1]; \
+ maxfmt += max; \
+ break
+ TYPES;
+#undef DO_TYPE
+ default:
+ abort ();
+ }
+ colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
+ maxfmt, "%" PRIu64 ".%.6" PRIu64, sec, usec);
+ break;
+
+ case 'c':
+ assert (count == 1);
+ colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
+ 1, "%c", value.Byte[0]);
+ break;
+
+ case 's':
+ colno = print_core_item (colno, ',', ITEM_WRAP_COLUMN, 0, item->name,
+ count, "%.*s", (int) count, value.Byte);
+ break;
+
+ default:
+ error (0, 0, "XXX not handling format '%c' for %s",
+ item->format, item->name);
+ break;
+ }
+
+#undef TYPES
+
+ return colno;
+}
+
+
+/* Sort items by group, and by layout offset within each group. */
+static int
+compare_core_items (const void *a, const void *b)
+{
+ const Ebl_Core_Item *const *p1 = a;
+ const Ebl_Core_Item *const *p2 = b;
+ const Ebl_Core_Item *item1 = *p1;
+ const Ebl_Core_Item *item2 = *p2;
+
+ return ((item1->group == item2->group ? 0
+ : strcmp (item1->group, item2->group))
+ ?: (int) item1->offset - (int) item2->offset);
+}
+
+/* Sort item groups by layout offset of the first item in the group. */
+static int
+compare_core_item_groups (const void *a, const void *b)
+{
+ const Ebl_Core_Item *const *const *p1 = a;
+ const Ebl_Core_Item *const *const *p2 = b;
+ const Ebl_Core_Item *const *group1 = *p1;
+ const Ebl_Core_Item *const *group2 = *p2;
+ const Ebl_Core_Item *item1 = *group1;
+ const Ebl_Core_Item *item2 = *group2;
+
+ return (int) item1->offset - (int) item2->offset;
+}
+
+static unsigned int
+handle_core_items (Elf *core, const void *desc,
+ const Ebl_Core_Item *items, size_t nitems)
+{
+ if (nitems == 0)
+ return 0;
+
+ /* Sort to collect the groups together. */
+ const Ebl_Core_Item *sorted_items[nitems];
+ for (size_t i = 0; i < nitems; ++i)
+ sorted_items[i] = &items[i];
+ qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
+
+ /* Collect the unique groups and sort them. */
+ const Ebl_Core_Item **groups[nitems];
+ groups[0] = &sorted_items[0];
+ size_t ngroups = 1;
+ for (size_t i = 1; i < nitems; ++i)
+ if (sorted_items[i]->group != sorted_items[i - 1]->group
+ && strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
+ groups[ngroups++] = &sorted_items[i];
+ qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
+
+ /* Write out all the groups. */
+ unsigned int colno = 0;
+ for (size_t i = 0; i < ngroups; ++i)
+ {
+ for (const Ebl_Core_Item **item = groups[i];
+ (item < &sorted_items[nitems]
+ && ((*item)->group == groups[i][0]->group
+ || !strcmp ((*item)->group, groups[i][0]->group)));
+ ++item)
+ colno = handle_core_item (core, *item, desc, colno);
+
+ /* Force a line break at the end of the group. */
+ colno = ITEM_WRAP_COLUMN;
+ }
+
+ return colno;
+}
+
+static unsigned int
+handle_bit_registers (const Ebl_Register_Location *regloc, const void *desc,
+ unsigned int colno)
+{
+ desc += regloc->offset;
+
+ abort (); /* XXX */
+ return colno;
+}
+
+
+static unsigned int
+handle_core_register (Ebl *ebl, Elf *core, int maxregname,
+ const Ebl_Register_Location *regloc, const void *desc,
+ unsigned int colno)
+{
+ if (regloc->bits % 8 != 0)
+ return handle_bit_registers (regloc, desc, colno);
+
+ desc += regloc->offset;
+
+ for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
+ {
+ const char *pfx;
+ const char *set;
+ char name[16];
+ int bits;
+ int type;
+ ssize_t n = ebl_register_info (ebl, reg, name, sizeof name,
+ &pfx, &set, &bits, &type);
+ if (n <= 0)
+ error (EXIT_FAILURE, 0,
+ gettext ("unable to handle register number %d"),
+ regloc->regno);
+
+#define TYPES \
+ BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8, 4); \
+ BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16, 6); \
+ BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32, 11); \
+ BITS (64, XWORD, "%20" PRId64, " 0x%.16" PRIx64, 20)
+
+#define BITS(bits, xtype, sfmt, ufmt, max) \
+ uint##bits##_t b##bits; int##bits##_t b##bits##s
+ union { TYPES; uint64_t b128[2]; } value;
+#undef BITS
+
+ switch (type)
+ {
+ case DW_ATE_unsigned:
+ case DW_ATE_signed:
+ case DW_ATE_address:
+ switch (bits)
+ {
+#define BITS(bits, xtype, sfmt, ufmt, max) \
+ case bits: \
+ desc = convert (core, ELF_T_##xtype, 1, &value, desc); \
+ if (type == DW_ATE_signed) \
+ colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, \
+ maxregname, name, \
+ max, sfmt, value.b##bits##s); \
+ else \
+ colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN, \
+ maxregname, name, \
+ max, ufmt, value.b##bits); \
+ break
+
+ TYPES;
+
+ case 128:
+ assert (type == DW_ATE_unsigned);
+ desc = convert (core, ELF_T_XWORD, 2, &value, desc);
+ int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
+ colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
+ maxregname, name,
+ 34, "0x%.16" PRIx64 "%.16" PRIx64,
+ value.b128[!be], value.b128[be]);
+ break;
+
+ default:
+ abort ();
+#undef BITS
+ }
+ break;
+
+ default:
+ /* Print each byte in hex, the whole thing in native byte order. */
+ assert (bits % 8 == 0);
+ const uint8_t *bytes = desc;
+ desc += bits / 8;
+ char hex[bits / 4 + 1];
+ hex[bits / 4] = '\0';
+ int incr = 1;
+ if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
+ {
+ bytes += bits / 8 - 1;
+ incr = -1;
+ }
+ size_t idx = 0;
+ for (char *h = hex; bits > 0; bits -= 8, idx += incr)
+ {
+ *h++ = "0123456789abcdef"[bytes[idx] >> 4];
+ *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
+ }
+ colno = print_core_item (colno, ' ', REGISTER_WRAP_COLUMN,
+ maxregname, name,
+ 2 + sizeof hex - 1, "0x%s", hex);
+ break;
+ }
+ desc += regloc->pad;
+
+#undef TYPES
+ }
+
+ return colno;
+}
+
+
+struct register_info
+{
+ const Ebl_Register_Location *regloc;
+ const char *set;
+ char name[16];
+ Dwarf_Half regno;
+ uint8_t bits;
+ uint8_t type;
+};
+
+static int
+register_bitpos (const struct register_info *r)
+{
+ return (r->regloc->offset * 8
+ + ((r->regno - r->regloc->regno)
+ * (r->regloc->bits + r->regloc->pad * 8)));
+}
+
+static int
+compare_sets_by_info (const struct register_info *r1,
+ const struct register_info *r2)
+{
+ return ((int) r2->bits - (int) r1->bits
+ ?: register_bitpos (r1) - register_bitpos (r2));
+}
+
+/* Sort registers by set, and by size and layout offset within each set. */
+static int
+compare_registers (const void *a, const void *b)
+{
+ const struct register_info *r1 = a;
+ const struct register_info *r2 = b;
+
+ /* Unused elements sort last. */
+ if (r1->regloc == NULL)
+ return r2->regloc == NULL ? 0 : 1;
+ if (r2->regloc == NULL)
+ return -1;
+
+ return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
+ ?: compare_sets_by_info (r1, r2));
+}
+
+/* Sort register sets by layout offset of the first register in the set. */
+static int
+compare_register_sets (const void *a, const void *b)
+{
+ const struct register_info *const *p1 = a;
+ const struct register_info *const *p2 = b;
+ return compare_sets_by_info (*p1, *p2);
+}
+
+static unsigned int
+handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
+ const Ebl_Register_Location *reglocs, size_t nregloc)
+{
+ if (nregloc == 0)
+ return 0;
+
+ ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
+ if (maxnreg <= 0)
+ error (EXIT_FAILURE, 0,
+ gettext ("cannot register info: %s"), elf_errmsg (-1));
+
+ struct register_info regs[maxnreg];
+ memset (regs, 0, sizeof regs);
+
+ /* Sort to collect the sets together. */
+ int maxreg = 0;
+ for (size_t i = 0; i < nregloc; ++i)
+ for (int reg = reglocs[i].regno;
+ reg < reglocs[i].regno + reglocs[i].count;
+ ++reg)
+ {
+ assert (reg < maxnreg);
+ if (reg > maxreg)
+ maxreg = reg;
+ struct register_info *info = ®s[reg];
+
+ const char *pfx;
+ int bits;
+ int type;
+ ssize_t n = ebl_register_info (ebl, reg, info->name, sizeof info->name,
+ &pfx, &info->set, &bits, &type);
+ if (n <= 0)
+ error (EXIT_FAILURE, 0,
+ gettext ("cannot register info: %s"), elf_errmsg (-1));
+
+ info->regloc = ®locs[i];
+ info->regno = reg;
+ info->bits = bits;
+ info->type = type;
+ }
+ qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
+
+ /* Collect the unique sets and sort them. */
+ inline bool same_set (const struct register_info *a,
+ const struct register_info *b)
+ {
+ return (a < ®s[maxnreg] && a->regloc != NULL
+ && b < ®s[maxnreg] && b->regloc != NULL
+ && a->bits == b->bits
+ && (a->set == b->set || !strcmp (a->set, b->set)));
+ }
+ struct register_info *sets[maxreg + 1];
+ sets[0] = ®s[0];
+ size_t nsets = 1;
+ for (int i = 1; i <= maxreg; ++i)
+ if (regs[i].regloc != NULL && !same_set (®s[i], ®s[i - 1]))
+ sets[nsets++] = ®s[i];
+ qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
+
+ /* Write out all the sets. */
+ unsigned int colno = 0;
+ for (size_t i = 0; i < nsets; ++i)
+ {
+ /* Find the longest name of a register in this set. */
+ size_t maxname = 0;
+ const struct register_info *end;
+ for (end = sets[i]; same_set (sets[i], end); ++end)
+ {
+ size_t len = strlen (end->name);
+ if (len > maxname)
+ maxname = len;
+ }
+
+ for (const struct register_info *reg = sets[i];
+ reg < end;
+ reg += reg->regloc->count ?: 1)
+ colno = handle_core_register (ebl, core, maxname,
+ reg->regloc, desc, colno);
+
+ /* Force a line break at the end of the group. */
+ colno = REGISTER_WRAP_COLUMN;
+ }
+
+ return colno;
+}
+
+static void
+handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, const void *desc)
+{
+ const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
+ for (size_t i = 0; i < nauxv; ++i)
+ {
+ const GElf_auxv_t *av = (const GElf_auxv_t *) desc + i;
+
+ const char *name;
+ const char *fmt;
+ if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
+ {
+ /* Unknown type. */
+ if (av->a_un.a_val == 0)
+ printf (" %" PRIu64 "\n", av->a_type);
+ else
+ printf (" %" PRIu64 ": %#" PRIx64 "\n",
+ av->a_type, av->a_un.a_val);
+ }
+ else
+ switch (fmt[0])
+ {
+ case '\0': /* Normally zero. */
+ if (av->a_un.a_val == 0)
+ {
+ printf (" %s\n", name);
+ break;
+ }
+ /* Fall through */
+ case 'x': /* hex */
+ case 'p': /* address */
+ case 's': /* address of string */
+ printf (" %s: %#" PRIx64 "\n", name, av->a_un.a_val);
+ break;
+ case 'u':
+ printf (" %s: %" PRIu64 "\n", name, av->a_un.a_val);
+ break;
+ case 'd':
+ printf (" %s: %" PRId64 "\n", name, av->a_un.a_val);
+ break;
+
+ case 'b':
+ printf (" %s: %#" PRIx64 " ", name, av->a_un.a_val);
+ GElf_Xword bit = 1;
+ const char *pfx = "<";
+ for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
+ {
+ if (av->a_un.a_val & bit)
+ {
+ printf ("%s%s", pfx, p);
+ pfx = " ";
+ }
+ bit <<= 1;
+ }
+ printf (">\n");
+ break;
+
+ default:
+ abort ();
+ }
+ }
+}
+
+static void
+handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr, const void *desc)
+{
+ GElf_Word regs_offset;
+ size_t nregloc;
+ const Ebl_Register_Location *reglocs;
+ size_t nitems;
+ const Ebl_Core_Item *items;
+
+ if (! ebl_core_note (ebl, nhdr->n_type, nhdr->n_descsz,
+ ®s_offset, &nregloc, ®locs, &nitems, &items))
+ return;
+
+ unsigned int colno = handle_core_items (ebl->elf, desc, items, nitems);
+ if (colno != 0)
+ putchar_unlocked ('\n');
+
+ colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
+ reglocs, nregloc);
+ if (colno != 0)
+ putchar_unlocked ('\n');
+}
+
+
static void
handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
{
size_t idx = 0;
while (idx < phdr->p_filesz)
{
- /* XXX Handle 64-bit note section entries correctly. */
- struct
- {
- uint32_t namesz;
- uint32_t descsz;
- uint32_t type;
- char name[0];
- } *noteentry = (__typeof (noteentry)) (notemem + idx);
+ const GElf_Nhdr *nhdr = (const GElf_Nhdr *) (notemem + idx);
+ const char *name = (const char *) (nhdr + 1);
+ const void *desc = &name[ALIGNED_LEN (nhdr->n_namesz)];
if (idx + 12 > phdr->p_filesz
- || (idx + 12 + ALIGNED_LEN (noteentry->namesz)
- + ALIGNED_LEN (noteentry->descsz) > phdr->p_filesz))
+ || (idx + 12 + ALIGNED_LEN (nhdr->n_namesz)
+ + ALIGNED_LEN (nhdr->n_descsz) > phdr->p_filesz))
/* This entry isn't completely contained in the note
section. Ignore it. */
break;
char buf[100];
char buf2[100];
printf (gettext (" %-13.*s %9" PRId32 " %s\n"),
- (int) noteentry->namesz, noteentry->name,
- noteentry->descsz,
+ (int) nhdr->n_namesz, name,
+ nhdr->n_descsz,
ehdr->e_type == ET_CORE
- ? ebl_core_note_type_name (ebl, noteentry->type,
+ ? ebl_core_note_type_name (ebl, nhdr->n_type,
buf, sizeof (buf))
- : ebl_object_note_type_name (ebl, noteentry->type,
+ : ebl_object_note_type_name (ebl, nhdr->n_type,
buf2, sizeof (buf2)));
/* Filter out invalid entries. */
- if (memchr (noteentry->name, '\0', noteentry->namesz) != NULL
+ if (memchr (name, '\0', nhdr->n_namesz) != NULL
/* XXX For now help broken Linux kernels. */
|| 1)
{
if (ehdr->e_type == ET_CORE)
- ebl_core_note (ebl, noteentry->name, noteentry->type,
- noteentry->descsz,
- ¬eentry->name[ALIGNED_LEN (noteentry->namesz)]);
+ {
+ if (nhdr->n_type == NT_AUXV)
+ handle_auxv_note (ebl, ebl->elf, nhdr->n_descsz, desc);
+ else
+ handle_core_note (ebl, nhdr, desc);
+ }
else
- ebl_object_note (ebl, noteentry->name, noteentry->type,
- noteentry->descsz,
- ¬eentry->name[ALIGNED_LEN (noteentry->namesz)]);
+ ebl_object_note (ebl, name, nhdr->n_type,
+ nhdr->n_descsz, desc);
}
/* Move to the next entry. */
- idx += (12 + ALIGNED_LEN (noteentry->namesz)
- + ALIGNED_LEN (noteentry->descsz));
+ idx += (12 + ALIGNED_LEN (nhdr->n_namesz)
+ + ALIGNED_LEN (nhdr->n_descsz));
}
gelf_freechunk (ebl->elf, notemem);
return split_bss;
}
+/* Create new .shstrtab contents, subroutine of copy_elided_sections.
+ This can't be open coded there and still use variable-length auto arrays,
+ since the end of our block would free other VLAs too. */
+static Elf_Data *
+new_shstrtab (Elf *unstripped, size_t unstripped_shnum,
+ Elf_Data *shstrtab, size_t unstripped_shstrndx,
+ struct section *sections, size_t stripped_shnum,
+ struct Ebl_Strtab *strtab)
+{
+ if (strtab == NULL)
+ return NULL;
+
+ struct Ebl_Strent *unstripped_strent[unstripped_shnum - 1];
+ memset (unstripped_strent, 0, sizeof unstripped_strent);
+ for (struct section *sec = sections;
+ sec < §ions[stripped_shnum - 1];
+ ++sec)
+ if (sec->outscn != NULL)
+ {
+ if (sec->strent == NULL)
+ {
+ sec->strent = ebl_strtabadd (strtab, sec->name, 0);
+ ELF_CHECK (sec->strent != NULL,
+ _("cannot add section name to string table: %s"));
+ }
+ unstripped_strent[elf_ndxscn (sec->outscn) - 1] = sec->strent;
+ }
+
+ /* Add names of sections we aren't touching. */
+ for (size_t i = 0; i < unstripped_shnum - 1; ++i)
+ if (unstripped_strent[i] == NULL)
+ {
+ Elf_Scn *scn = elf_getscn (unstripped, i + 1);
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ const char *name = get_section_name (i + 1, shdr, shstrtab);
+ unstripped_strent[i] = ebl_strtabadd (strtab, name, 0);
+ ELF_CHECK (unstripped_strent[i] != NULL,
+ _("cannot add section name to string table: %s"));
+ }
+ else
+ unstripped_strent[i] = NULL;
+
+ /* Now finalize the string table so we can get offsets. */
+ Elf_Data *strtab_data = elf_getdata (elf_getscn (unstripped,
+ unstripped_shstrndx), NULL);
+ ELF_CHECK (elf_flagdata (strtab_data, ELF_C_SET, ELF_F_DIRTY),
+ _("cannot update section header string table data: %s"));
+ ebl_strtabfinalize (strtab, strtab_data);
+
+ /* Update the sh_name fields of sections we aren't modifying later. */
+ for (size_t i = 0; i < unstripped_shnum - 1; ++i)
+ if (unstripped_strent[i] != NULL)
+ {
+ Elf_Scn *scn = elf_getscn (unstripped, i + 1);
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+ shdr->sh_name = ebl_strtaboffset (unstripped_strent[i]);
+ if (i + 1 == unstripped_shstrndx)
+ shdr->sh_size = strtab_data->d_size;
+ ELF_CHECK (gelf_update_shdr (scn, shdr),
+ _("cannot update section header: %s"));
+ }
+
+ return strtab_data;
+}
+
/* Fill in any SHT_NOBITS sections in UNSTRIPPED by
copying their contents and sh_type from STRIPPED. */
static void
ndx_section[secndx - 1] = elf_ndxscn (sec->outscn);
}
- Elf_Data *strtab_data = NULL;
- if (strtab != NULL)
- {
- /* We added some sections, so we need a new shstrtab. */
-
- struct Ebl_Strent *unstripped_strent[unstripped_shnum - 1];
- memset (unstripped_strent, 0, sizeof unstripped_strent);
- for (struct section *sec = sections;
- sec < §ions[stripped_shnum - 1];
- ++sec)
- if (sec->outscn != NULL)
- {
- if (sec->strent == NULL)
- {
- sec->strent = ebl_strtabadd (strtab, sec->name, 0);
- ELF_CHECK (sec->strent != NULL,
- _("cannot add section name to string table: %s"));
- }
- unstripped_strent[elf_ndxscn (sec->outscn) - 1] = sec->strent;
- }
-
- /* Add names of sections we aren't touching. */
- for (size_t i = 0; i < unstripped_shnum - 1; ++i)
- if (unstripped_strent[i] == NULL)
- {
- scn = elf_getscn (unstripped, i + 1);
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- const char *name = get_section_name (i + 1, shdr, shstrtab);
- unstripped_strent[i] = ebl_strtabadd (strtab, name, 0);
- ELF_CHECK (unstripped_strent[i] != NULL,
- _("cannot add section name to string table: %s"));
- }
- else
- unstripped_strent[i] = NULL;
-
- /* Now finalize the string table so we can get offsets. */
- strtab_data = elf_getdata (elf_getscn (unstripped, unstripped_shstrndx),
- NULL);
- ELF_CHECK (elf_flagdata (strtab_data, ELF_C_SET, ELF_F_DIRTY),
- _("cannot update section header string table data: %s"));
- ebl_strtabfinalize (strtab, strtab_data);
-
- /* Update the sh_name fields of sections we aren't modifying later. */
- for (size_t i = 0; i < unstripped_shnum - 1; ++i)
- if (unstripped_strent[i] != NULL)
- {
- scn = elf_getscn (unstripped, i + 1);
- GElf_Shdr shdr_mem;
- GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- shdr->sh_name = ebl_strtaboffset (unstripped_strent[i]);
- if (i + 1 == unstripped_shstrndx)
- shdr->sh_size = strtab_data->d_size;
- ELF_CHECK (gelf_update_shdr (scn, shdr),
- _("cannot update section header: %s"));
- }
- }
+ /* We added some sections, so we need a new shstrtab. */
+ Elf_Data *strtab_data = new_shstrtab (unstripped, unstripped_shnum,
+ shstrtab, unstripped_shstrndx,
+ sections, stripped_shnum,
+ strtab);
/* Get the updated section count. */
ELF_CHECK (elf_getshnum (unstripped, &unstripped_shnum) == 0,
+2007-08-23 Roland McGrath <roland@redhat.com>
+
+ * run-allregs.sh: Update expected x86-64 output for %rflags.
+
2007-08-12 Roland McGrath <roland@redhat.com>
* run-strip-test7.sh: New file.
14: %r14 (r14), signed 64 bits
15: %r15 (r15), signed 64 bits
16: %rip (rip), address 64 bits
+ 49: %rflags (rflags), unsigned 64 bits
MMX registers:
41: %mm0 (mm0), unsigned 64 bits
42: %mm1 (mm1), unsigned 64 bits
31: %xmm14 (xmm14), unsigned 128 bits
32: %xmm15 (xmm15), unsigned 128 bits
control registers:
- 49: %rflags (rflags), unsigned 64 bits
62: %tr (tr), unsigned 64 bits
63: %ldtr (ldtr), unsigned 64 bits
64: %mxcsr (mxcsr), unsigned 64 bits