Blame backends/linux-core-note.c

Packit 032894
/* Common core note type descriptions for Linux.
Packit 032894
   Copyright (C) 2007-2010 Red Hat, Inc.
Packit 032894
   Copyright (C) H.J. Lu <hjl.tools@gmail.com>, 2015.
Packit 032894
   This file is part of elfutils.
Packit 032894
Packit 032894
   This file is free software; you can redistribute it and/or modify
Packit 032894
   it under the terms of either
Packit 032894
Packit 032894
     * the GNU Lesser General Public License as published by the Free
Packit 032894
       Software Foundation; either version 3 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or
Packit 032894
Packit 032894
     * the GNU General Public License as published by the Free
Packit 032894
       Software Foundation; either version 2 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or both in parallel, as here.
Packit 032894
Packit 032894
   elfutils is distributed in the hope that it will be useful, but
Packit 032894
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 032894
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 032894
   General Public License for more details.
Packit 032894
Packit 032894
   You should have received copies of the GNU General Public License and
Packit 032894
   the GNU Lesser General Public License along with this program.  If
Packit 032894
   not, see <http://www.gnu.org/licenses/>.  */
Packit 032894
Packit 032894
#include <string.h>
Packit 032894
Packit 032894
/* The including CPU_corenote.c file provides prstatus_regs and
Packit 032894
   defines macros ULONG, [PUG]ID_T, and ALIGN_*, TYPE_*.
Packit 032894
Packit 032894
   Here we describe the common layout used in <linux/elfcore.h>.  */
Packit 032894
Packit 032894
#define	CHAR			int8_t
Packit 032894
#define	ALIGN_CHAR		1
Packit 032894
#define	TYPE_CHAR		ELF_T_BYTE
Packit 032894
#define	SHORT			uint16_t
Packit 032894
#define ALIGN_SHORT		2
Packit 032894
#define TYPE_SHORT		ELF_T_HALF
Packit 032894
#define	INT			int32_t
Packit 032894
#ifndef ALIGN_INT
Packit 032894
# define ALIGN_INT		4
Packit 032894
#endif
Packit 032894
#define TYPE_INT		ELF_T_SWORD
Packit 032894
#ifndef PR_REG
Packit 032894
# define PR_REG			ULONG
Packit 032894
#endif
Packit 032894
#ifndef ALIGN_PR_REG
Packit 032894
# define ALIGN_PR_REG		ALIGN_ULONG
Packit 032894
#endif
Packit 032894
#ifndef PRPSINFO_UID_T
Packit 032894
# define PRPSINFO_UID_T		UID_T
Packit 032894
# define ALIGN_PRPSINFO_UID_T	ALIGN_UID_T
Packit 032894
# define TYPE_PRPSINFO_UID_T	TYPE_UID_T
Packit 032894
#endif
Packit 032894
#ifndef PRPSINFO_GID_T
Packit 032894
# define PRPSINFO_GID_T		GID_T
Packit 032894
# define ALIGN_PRPSINFO_GID_T	ALIGN_GID_T
Packit 032894
# define TYPE_PRPSINFO_GID_T	TYPE_GID_T
Packit 032894
#endif
Packit 032894
Packit 032894
#define FIELD(type, name) type name __attribute__ ((aligned (ALIGN_##type)))
Packit 032894
Packit 032894
struct EBLHOOK(siginfo)
Packit 032894
{
Packit 032894
  FIELD (INT, si_signo);
Packit 032894
  FIELD (INT, si_code);
Packit 032894
  FIELD (INT, si_errno);
Packit 032894
};
Packit 032894
Packit 032894
struct EBLHOOK(timeval)
Packit 032894
{
Packit 032894
  FIELD (ULONG, tv_sec);
Packit 032894
  FIELD (ULONG, tv_usec);
Packit 032894
};
Packit 032894
Packit 032894
/* On sparc64, tv_usec (suseconds_t) is actually 32 bits with 32 bits padding.
Packit 032894
   The 'T'|0x80 value for .format indicates this as a special kludge.  */
Packit 032894
#if SUSECONDS_HALF
Packit 032894
# define TIMEVAL_FIELD(name)	FIELD (time, ULONG, name, 'T'|0x80, .count = 2)
Packit 032894
#else
Packit 032894
# define TIMEVAL_FIELD(name)	FIELD (time, ULONG, name, 'T', .count = 2)
Packit 032894
#endif
Packit 032894
Packit 032894
Packit 032894
struct EBLHOOK(prstatus)
Packit 032894
{
Packit 032894
  struct EBLHOOK(siginfo) pr_info;
Packit 032894
  FIELD (SHORT, pr_cursig);
Packit 032894
  FIELD (ULONG, pr_sigpend);
Packit 032894
  FIELD (ULONG, pr_sighold);
Packit 032894
  FIELD (PID_T, pr_pid);
Packit 032894
  FIELD (PID_T, pr_ppid);
Packit 032894
  FIELD (PID_T, pr_pgrp);
Packit 032894
  FIELD (PID_T, pr_sid);
Packit 032894
  struct EBLHOOK(timeval) pr_utime;
Packit 032894
  struct EBLHOOK(timeval) pr_stime;
Packit 032894
  struct EBLHOOK(timeval) pr_cutime;
Packit 032894
  struct EBLHOOK(timeval) pr_cstime;
Packit 032894
  struct
Packit 032894
  {
Packit 032894
    FIELD (PR_REG, pr_reg[PRSTATUS_REGS_SIZE / sizeof (PR_REG)]);
Packit 032894
  }
Packit 032894
#ifdef ALIGN_PR_REG
Packit 032894
    __attribute__ ((aligned (ALIGN_PR_REG)))
Packit 032894
#endif
Packit 032894
    ;
Packit 032894
  FIELD (INT, pr_fpvalid);
Packit 032894
}
Packit 032894
#ifdef ALIGN_PRSTATUS
Packit 032894
  attribute_packed __attribute__ ((aligned (ALIGN_PRSTATUS)))
Packit 032894
#endif
Packit 032894
;
Packit 032894
Packit 032894
#define	FNAMESZ	16
Packit 032894
#define	PRARGSZ	80
Packit 032894
Packit 032894
struct EBLHOOK(prpsinfo)
Packit 032894
{
Packit 032894
  FIELD (CHAR, pr_state);
Packit 032894
  FIELD (CHAR, pr_sname);
Packit 032894
  FIELD (CHAR, pr_zomb);
Packit 032894
  FIELD (CHAR, pr_nice);
Packit 032894
  FIELD (ULONG, pr_flag);
Packit 032894
  FIELD (PRPSINFO_UID_T, pr_uid);
Packit 032894
  FIELD (PRPSINFO_GID_T, pr_gid);
Packit 032894
  FIELD (PID_T, pr_pid);
Packit 032894
  FIELD (PID_T, pr_ppid);
Packit 032894
  FIELD (PID_T, pr_pgrp);
Packit 032894
  FIELD (PID_T, pr_sid);
Packit 032894
  FIELD (CHAR, pr_fname[FNAMESZ]);
Packit 032894
  FIELD (CHAR, pr_psargs[PRARGSZ]);
Packit 032894
};
Packit 032894
Packit 032894
#undef	FIELD
Packit 032894
Packit 032894
#define FIELD(igroup, itype, item, fmt, ...)			\
Packit 032894
    {								\
Packit 032894
      .name = #item,						\
Packit 032894
      .group = #igroup,					\
Packit 032894
      .offset = offsetof (struct EBLHOOK(prstatus), pr_##item),	\
Packit 032894
      .type = TYPE_##itype,					\
Packit 032894
      .format = fmt,						\
Packit 032894
      __VA_ARGS__						\
Packit 032894
    }
Packit 032894
Packit 032894
static const Ebl_Core_Item prstatus_items[] =
Packit 032894
  {
Packit 032894
    FIELD (signal, INT, info.si_signo, 'd'),
Packit 032894
    FIELD (signal, INT, info.si_code, 'd'),
Packit 032894
    FIELD (signal, INT, info.si_errno, 'd'),
Packit 032894
    FIELD (signal, SHORT, cursig, 'd'),
Packit 032894
Packit 032894
    /* Use different group name for a newline delimiter.  */
Packit 032894
    FIELD (signal2, ULONG, sigpend, 'B'),
Packit 032894
    FIELD (signal3, ULONG, sighold, 'B'),
Packit 032894
    FIELD (identity, PID_T, pid, 'd', .thread_identifier = true),
Packit 032894
    FIELD (identity, PID_T, ppid, 'd'),
Packit 032894
    FIELD (identity, PID_T, pgrp, 'd'),
Packit 032894
    FIELD (identity, PID_T, sid, 'd'),
Packit 032894
    TIMEVAL_FIELD (utime),
Packit 032894
    TIMEVAL_FIELD (stime),
Packit 032894
    TIMEVAL_FIELD (cutime),
Packit 032894
    TIMEVAL_FIELD (cstime),
Packit 032894
#ifdef PRSTATUS_REGSET_ITEMS
Packit 032894
    PRSTATUS_REGSET_ITEMS,
Packit 032894
#endif
Packit 032894
    FIELD (register, INT, fpvalid, 'd'),
Packit 032894
  };
Packit 032894
Packit 032894
#undef	FIELD
Packit 032894
Packit 032894
#define FIELD(igroup, itype, item, fmt, ...)			\
Packit 032894
    {								\
Packit 032894
      .name = #item,						\
Packit 032894
      .group = #igroup,					\
Packit 032894
      .offset = offsetof (struct EBLHOOK(prpsinfo), pr_##item),	\
Packit 032894
      .type = TYPE_##itype,					\
Packit 032894
      .format = fmt,						\
Packit 032894
      __VA_ARGS__						\
Packit 032894
    }
Packit 032894
Packit 032894
static const Ebl_Core_Item prpsinfo_items[] =
Packit 032894
  {
Packit 032894
    FIELD (state, CHAR, state, 'd'),
Packit 032894
    FIELD (state, CHAR, sname, 'c'),
Packit 032894
    FIELD (state, CHAR, zomb, 'd'),
Packit 032894
    FIELD (state, CHAR, nice, 'd'),
Packit 032894
    FIELD (state, ULONG, flag, 'x'),
Packit 032894
    FIELD (identity, PRPSINFO_UID_T, uid, 'd'),
Packit 032894
    FIELD (identity, PRPSINFO_GID_T, gid, 'd'),
Packit 032894
    FIELD (identity, PID_T, pid, 'd'),
Packit 032894
    FIELD (identity, PID_T, ppid, 'd'),
Packit 032894
    FIELD (identity, PID_T, pgrp, 'd'),
Packit 032894
    FIELD (identity, PID_T, sid, 'd'),
Packit 032894
    FIELD (command, CHAR, fname, 's', .count = FNAMESZ),
Packit 032894
    FIELD (command, CHAR, psargs, 's', .count = PRARGSZ),
Packit 032894
  };
Packit 032894
Packit 032894
static const Ebl_Core_Item vmcoreinfo_items[] =
Packit 032894
  {
Packit 032894
    {
Packit 032894
      .type = ELF_T_BYTE, .format = '\n'
Packit 032894
    }
Packit 032894
  };
Packit 032894
Packit 032894
#undef	FIELD
Packit 032894
Packit 032894
int
Packit 032894
EBLHOOK(core_note) (const GElf_Nhdr *nhdr, const char *name,
Packit 032894
		    GElf_Word *regs_offset, size_t *nregloc,
Packit 032894
		    const Ebl_Register_Location **reglocs,
Packit 032894
		    size_t *nitems, const Ebl_Core_Item **items)
Packit 032894
{
Packit 032894
  switch (nhdr->n_namesz)
Packit 032894
    {
Packit 032894
    case sizeof "CORE" - 1:	/* Buggy old Linux kernels.  */
Packit 032894
      if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
Packit 032894
	break;
Packit 032894
      return 0;
Packit 032894
Packit 032894
    case sizeof "CORE":
Packit 032894
      if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
Packit 032894
	break;
Packit 032894
      /* Buggy old Linux kernels didn't terminate "LINUX".  */
Packit 032894
      FALLTHROUGH;
Packit 032894
Packit 032894
    case sizeof "LINUX":
Packit 032894
      if (memcmp (name, "LINUX", nhdr->n_namesz) == 0)
Packit 032894
	break;
Packit 032894
      return 0;
Packit 032894
Packit 032894
    case sizeof "VMCOREINFO":
Packit 032894
      if (nhdr->n_type != 0
Packit 032894
	  || memcmp (name, "VMCOREINFO", sizeof "VMCOREINFO") != 0)
Packit 032894
	return 0;
Packit 032894
      *regs_offset = 0;
Packit 032894
      *nregloc = 0;
Packit 032894
      *nitems = 1;
Packit 032894
      *items = vmcoreinfo_items;
Packit 032894
      return 1;
Packit 032894
Packit 032894
    default:
Packit 032894
      return 0;
Packit 032894
    }
Packit 032894
Packit 032894
  switch (nhdr->n_type)
Packit 032894
    {
Packit 032894
    case NT_PRSTATUS:
Packit 032894
      if (nhdr->n_descsz != sizeof (struct EBLHOOK(prstatus)))
Packit 032894
	return 0;
Packit 032894
      *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg);
Packit 032894
      *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0];
Packit 032894
      *reglocs = prstatus_regs;
Packit 032894
      *nitems = sizeof prstatus_items / sizeof prstatus_items[0];
Packit 032894
      *items = prstatus_items;
Packit 032894
      return 1;
Packit 032894
Packit 032894
    case NT_PRPSINFO:
Packit 032894
      if (nhdr->n_descsz != sizeof (struct EBLHOOK(prpsinfo)))
Packit 032894
	return 0;
Packit 032894
      *regs_offset = 0;
Packit 032894
      *nregloc = 0;
Packit 032894
      *reglocs = NULL;
Packit 032894
      *nitems = sizeof prpsinfo_items / sizeof prpsinfo_items[0];
Packit 032894
      *items = prpsinfo_items;
Packit 032894
      return 1;
Packit 032894
Packit 032894
#define EXTRA_REGSET(type, size, table)					      \
Packit 032894
    case type:								      \
Packit 032894
      if (nhdr->n_descsz != size)					      \
Packit 032894
	return 0;							      \
Packit 032894
      *regs_offset = 0;							      \
Packit 032894
      *nregloc = sizeof table / sizeof table[0];			      \
Packit 032894
      *reglocs = table;							      \
Packit 032894
      *nitems = 0;							      \
Packit 032894
      *items = NULL;							      \
Packit 032894
      return 1;
Packit 032894
Packit 032894
#define EXTRA_REGSET_ITEMS(type, size, table, extra_items)		      \
Packit 032894
    case type:								      \
Packit 032894
      if (nhdr->n_descsz != size)					      \
Packit 032894
	return 0;							      \
Packit 032894
      *regs_offset = 0;							      \
Packit 032894
      *nregloc = sizeof table / sizeof table[0];			      \
Packit 032894
      *reglocs = table;							      \
Packit 032894
      *nitems = sizeof extra_items / sizeof extra_items[0];		      \
Packit 032894
      *items = extra_items;						      \
Packit 032894
      return 1;
Packit 032894
Packit 032894
#define EXTRA_ITEMS(type, size, extra_items)				      \
Packit 032894
    case type:								      \
Packit 032894
      if (nhdr->n_descsz != size)					      \
Packit 032894
	return 0;							      \
Packit 032894
      *regs_offset = 0;							      \
Packit 032894
      *nregloc = 0;							      \
Packit 032894
      *reglocs = NULL;							      \
Packit 032894
      *nitems = sizeof extra_items / sizeof extra_items[0];		      \
Packit 032894
      *items = extra_items;						      \
Packit 032894
      return 1;
Packit 032894
Packit 032894
#ifdef FPREGSET_SIZE
Packit 032894
    EXTRA_REGSET (NT_FPREGSET, FPREGSET_SIZE, fpregset_regs)
Packit 032894
#endif
Packit 032894
Packit 032894
#ifdef EXTRA_NOTES
Packit 032894
    EXTRA_NOTES
Packit 032894
#endif
Packit 032894
    }
Packit 032894
Packit 032894
  return 0;
Packit 032894
}