summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/lib/libproc/common/Pcontrol.h3
-rw-r--r--usr/src/lib/libproc/common/Pcore.c291
-rw-r--r--usr/src/lib/libproc/common/Pcore_linux.h173
3 files changed, 454 insertions, 13 deletions
diff --git a/usr/src/lib/libproc/common/Pcontrol.h b/usr/src/lib/libproc/common/Pcontrol.h
index 3e72a32804..6697d5736b 100644
--- a/usr/src/lib/libproc/common/Pcontrol.h
+++ b/usr/src/lib/libproc/common/Pcontrol.h
@@ -24,7 +24,7 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
@@ -149,6 +149,7 @@ typedef struct fd_info {
typedef struct core_info { /* information specific to core files */
char core_dmodel; /* data model for core file */
+ char core_osabi; /* ELF OS ABI */
int core_errno; /* error during initialization if != 0 */
plist_t core_lwp_head; /* head of list of lwp info */
lwp_info_t *core_lwp; /* current lwp information */
diff --git a/usr/src/lib/libproc/common/Pcore.c b/usr/src/lib/libproc/common/Pcore.c
index 596c45861a..05e5ce2e08 100644
--- a/usr/src/lib/libproc/common/Pcore.c
+++ b/usr/src/lib/libproc/common/Pcore.c
@@ -24,7 +24,7 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
- * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2014, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
@@ -49,6 +49,7 @@
#include "Pcontrol.h"
#include "P32ton.h"
#include "Putil.h"
+#include "Pcore_linux.h"
/*
* Pcore.c - Code to initialize a ps_prochandle from a core dump. We
@@ -430,6 +431,204 @@ err:
return (-1);
}
+static void
+lx_prpsinfo32_to_psinfo(lx_prpsinfo32_t *p32, psinfo_t *psinfo)
+{
+ psinfo->pr_flag = p32->pr_flag;
+ psinfo->pr_pid = p32->pr_pid;
+ psinfo->pr_ppid = p32->pr_ppid;
+ psinfo->pr_uid = p32->pr_uid;
+ psinfo->pr_gid = p32->pr_gid;
+ psinfo->pr_sid = p32->pr_sid;
+ psinfo->pr_pgid = p32->pr_pgrp;
+
+ (void) memcpy(psinfo->pr_fname, p32->pr_fname,
+ sizeof (psinfo->pr_fname));
+ (void) memcpy(psinfo->pr_psargs, p32->pr_psargs,
+ sizeof (psinfo->pr_psargs));
+}
+
+static void
+lx_prpsinfo64_to_psinfo(lx_prpsinfo64_t *p64, psinfo_t *psinfo)
+{
+ psinfo->pr_flag = p64->pr_flag;
+ psinfo->pr_pid = p64->pr_pid;
+ psinfo->pr_ppid = p64->pr_ppid;
+ psinfo->pr_uid = p64->pr_uid;
+ psinfo->pr_gid = p64->pr_gid;
+ psinfo->pr_sid = p64->pr_sid;
+ psinfo->pr_pgid = p64->pr_pgrp;
+ psinfo->pr_pgid = p64->pr_pgrp;
+
+ (void) memcpy(psinfo->pr_fname, p64->pr_fname,
+ sizeof (psinfo->pr_fname));
+ (void) memcpy(psinfo->pr_psargs, p64->pr_psargs,
+ sizeof (psinfo->pr_psargs));
+}
+
+static int
+note_linux_psinfo(struct ps_prochandle *P, size_t nbytes)
+{
+ core_info_t *core = P->data;
+ lx_prpsinfo32_t p32;
+ lx_prpsinfo64_t p64;
+
+ if (core->core_dmodel == PR_MODEL_ILP32) {
+ if (nbytes < sizeof (p32) ||
+ read(P->asfd, &p32, sizeof (p32)) != sizeof (p32))
+ goto err;
+
+ lx_prpsinfo32_to_psinfo(&p32, &P->psinfo);
+ } else {
+ if (nbytes < sizeof (p64) ||
+ read(P->asfd, &p64, sizeof (p64)) != sizeof (p64))
+ goto err;
+
+ lx_prpsinfo64_to_psinfo(&p64, &P->psinfo);
+ }
+
+
+ P->status.pr_pid = P->psinfo.pr_pid;
+ P->status.pr_ppid = P->psinfo.pr_ppid;
+ P->status.pr_pgid = P->psinfo.pr_pgid;
+ P->status.pr_sid = P->psinfo.pr_sid;
+
+ P->psinfo.pr_nlwp = 0;
+ P->status.pr_nlwp = 0;
+
+ return (0);
+err:
+ dprintf("Pgrab_core: failed to read NT_PSINFO\n");
+ return (-1);
+}
+
+static void
+lx_prstatus64_to_lwp(lx_prstatus64_t *prs64, lwp_info_t *lwp)
+{
+ LTIME_TO_TIMESPEC(lwp->lwp_status.pr_utime, prs64->pr_utime);
+ LTIME_TO_TIMESPEC(lwp->lwp_status.pr_stime, prs64->pr_stime);
+
+ lwp->lwp_status.pr_reg[REG_R15] = prs64->pr_reg.lxr_r15;
+ lwp->lwp_status.pr_reg[REG_R14] = prs64->pr_reg.lxr_r14;
+ lwp->lwp_status.pr_reg[REG_R13] = prs64->pr_reg.lxr_r13;
+ lwp->lwp_status.pr_reg[REG_R12] = prs64->pr_reg.lxr_r12;
+ lwp->lwp_status.pr_reg[REG_R11] = prs64->pr_reg.lxr_r11;
+ lwp->lwp_status.pr_reg[REG_R10] = prs64->pr_reg.lxr_r10;
+ lwp->lwp_status.pr_reg[REG_R9] = prs64->pr_reg.lxr_r9;
+ lwp->lwp_status.pr_reg[REG_R8] = prs64->pr_reg.lxr_r8;
+
+ lwp->lwp_status.pr_reg[REG_RDI] = prs64->pr_reg.lxr_rdi;
+ lwp->lwp_status.pr_reg[REG_RSI] = prs64->pr_reg.lxr_rsi;
+ lwp->lwp_status.pr_reg[REG_RBP] = prs64->pr_reg.lxr_rbp;
+ lwp->lwp_status.pr_reg[REG_RBX] = prs64->pr_reg.lxr_rbx;
+ lwp->lwp_status.pr_reg[REG_RDX] = prs64->pr_reg.lxr_rdx;
+ lwp->lwp_status.pr_reg[REG_RCX] = prs64->pr_reg.lxr_rcx;
+ lwp->lwp_status.pr_reg[REG_RAX] = prs64->pr_reg.lxr_rax;
+
+ lwp->lwp_status.pr_reg[REG_RIP] = prs64->pr_reg.lxr_rip;
+ lwp->lwp_status.pr_reg[REG_CS] = prs64->pr_reg.lxr_cs;
+ lwp->lwp_status.pr_reg[REG_RSP] = prs64->pr_reg.lxr_rsp;
+ lwp->lwp_status.pr_reg[REG_FS] = prs64->pr_reg.lxr_fs;
+ lwp->lwp_status.pr_reg[REG_SS] = prs64->pr_reg.lxr_ss;
+ lwp->lwp_status.pr_reg[REG_GS] = prs64->pr_reg.lxr_gs;
+ lwp->lwp_status.pr_reg[REG_ES] = prs64->pr_reg.lxr_es;
+ lwp->lwp_status.pr_reg[REG_DS] = prs64->pr_reg.lxr_ds;
+
+ lwp->lwp_status.pr_reg[REG_GSBASE] = prs64->pr_reg.lxr_gs_base;
+ lwp->lwp_status.pr_reg[REG_FSBASE] = prs64->pr_reg.lxr_fs_base;
+}
+
+static void
+lx_prstatus32_to_lwp(lx_prstatus32_t *prs32, lwp_info_t *lwp)
+{
+ LTIME_TO_TIMESPEC(lwp->lwp_status.pr_utime, prs32->pr_utime);
+ LTIME_TO_TIMESPEC(lwp->lwp_status.pr_stime, prs32->pr_stime);
+
+#ifdef __amd64
+ lwp->lwp_status.pr_reg[REG_GS] = prs32->pr_reg.lxr_gs;
+ lwp->lwp_status.pr_reg[REG_FS] = prs32->pr_reg.lxr_fs;
+ lwp->lwp_status.pr_reg[REG_DS] = prs32->pr_reg.lxr_ds;
+ lwp->lwp_status.pr_reg[REG_ES] = prs32->pr_reg.lxr_es;
+ lwp->lwp_status.pr_reg[REG_RDI] = prs32->pr_reg.lxr_di;
+ lwp->lwp_status.pr_reg[REG_RSI] = prs32->pr_reg.lxr_si;
+ lwp->lwp_status.pr_reg[REG_RBP] = prs32->pr_reg.lxr_bp;
+ lwp->lwp_status.pr_reg[REG_RBX] = prs32->pr_reg.lxr_bx;
+ lwp->lwp_status.pr_reg[REG_RDX] = prs32->pr_reg.lxr_dx;
+ lwp->lwp_status.pr_reg[REG_RCX] = prs32->pr_reg.lxr_cx;
+ lwp->lwp_status.pr_reg[REG_RAX] = prs32->pr_reg.lxr_ax;
+ lwp->lwp_status.pr_reg[REG_RIP] = prs32->pr_reg.lxr_ip;
+ lwp->lwp_status.pr_reg[REG_CS] = prs32->pr_reg.lxr_cs;
+ lwp->lwp_status.pr_reg[REG_RFL] = prs32->pr_reg.lxr_flags;
+ lwp->lwp_status.pr_reg[REG_RSP] = prs32->pr_reg.lxr_sp;
+ lwp->lwp_status.pr_reg[REG_SS] = prs32->pr_reg.lxr_ss;
+#else /* __amd64 */
+ lwp->lwp_status.pr_reg[EBX] = prs32->pr_reg.lxr_bx;
+ lwp->lwp_status.pr_reg[ECX] = prs32->pr_reg.lxr_cx;
+ lwp->lwp_status.pr_reg[EDX] = prs32->pr_reg.lxr_dx;
+ lwp->lwp_status.pr_reg[ESI] = prs32->pr_reg.lxr_si;
+ lwp->lwp_status.pr_reg[EDI] = prs32->pr_reg.lxr_di;
+ lwp->lwp_status.pr_reg[EBP] = prs32->pr_reg.lxr_bp;
+ lwp->lwp_status.pr_reg[EAX] = prs32->pr_reg.lxr_ax;
+ lwp->lwp_status.pr_reg[EIP] = prs32->pr_reg.lxr_ip;
+ lwp->lwp_status.pr_reg[UESP] = prs32->pr_reg.lxr_sp;
+
+ lwp->lwp_status.pr_reg[DS] = prs32->pr_reg.lxr_ds;
+ lwp->lwp_status.pr_reg[ES] = prs32->pr_reg.lxr_es;
+ lwp->lwp_status.pr_reg[FS] = prs32->pr_reg.lxr_fs;
+ lwp->lwp_status.pr_reg[GS] = prs32->pr_reg.lxr_gs;
+ lwp->lwp_status.pr_reg[CS] = prs32->pr_reg.lxr_cs;
+ lwp->lwp_status.pr_reg[SS] = prs32->pr_reg.lxr_ss;
+
+ lwp->lwp_status.pr_reg[EFL] = prs32->pr_reg.lxr_flags;
+#endif /* !__amd64 */
+}
+
+static int
+note_linux_prstatus(struct ps_prochandle *P, size_t nbytes)
+{
+ core_info_t *core = P->data;
+
+ lx_prstatus64_t prs64;
+ lx_prstatus32_t prs32;
+ lwp_info_t *lwp;
+ lwpid_t tid;
+
+ dprintf("looking for model %d, %ld/%ld\n", core->core_dmodel,
+ (ulong_t)nbytes, (ulong_t)sizeof (prs32));
+ if (core->core_dmodel == PR_MODEL_ILP32) {
+ if (nbytes < sizeof (prs32) ||
+ read(P->asfd, &prs32, sizeof (prs32)) != nbytes)
+ goto err;
+ tid = prs32.pr_pid;
+ } else {
+ if (nbytes < sizeof (prs64) ||
+ read(P->asfd, &prs64, sizeof (prs64)) != nbytes)
+ goto err;
+ tid = prs64.pr_pid;
+ }
+
+ if ((lwp = lwpid2info(P, tid)) == NULL) {
+ dprintf("Pgrab_core: failed to add lwpid2info "
+ "linux_prstatus\n");
+ return (-1);
+ }
+
+ P->psinfo.pr_nlwp++;
+ P->status.pr_nlwp++;
+
+ lwp->lwp_status.pr_lwpid = tid;
+
+ if (core->core_dmodel == PR_MODEL_ILP32)
+ lx_prstatus32_to_lwp(&prs32, lwp);
+ else
+ lx_prstatus64_to_lwp(&prs64, lwp);
+
+ return (0);
+err:
+ dprintf("Pgrab_core: failed to read NT_PRSTATUS\n");
+ return (-1);
+}
+
static int
note_psinfo(struct ps_prochandle *P, size_t nbytes)
{
@@ -915,7 +1114,8 @@ err:
static int
note_notsup(struct ps_prochandle *P, size_t nbytes)
{
- dprintf("skipping unsupported note type\n");
+ dprintf("skipping unsupported note type of size %ld bytes\n",
+ (ulong_t)nbytes);
return (0);
}
@@ -925,9 +1125,9 @@ note_notsup(struct ps_prochandle *P, size_t nbytes)
*/
static int (*nhdlrs[])(struct ps_prochandle *, size_t) = {
note_notsup, /* 0 unassigned */
- note_notsup, /* 1 NT_PRSTATUS (old) */
+ note_linux_prstatus, /* 1 NT_PRSTATUS (old) */
note_notsup, /* 2 NT_PRFPREG (old) */
- note_notsup, /* 3 NT_PRPSINFO (old) */
+ note_linux_psinfo, /* 3 NT_PRPSINFO (old) */
#ifdef __sparc
note_xreg, /* 4 NT_PRXREG */
#else
@@ -1040,7 +1240,7 @@ core_add_mapping(struct ps_prochandle *P, GElf_Phdr *php)
core_info_t *core = P->data;
prmap_t pmap;
- dprintf("mapping base %llx filesz %llu memsz %llu offset %llu\n",
+ dprintf("mapping base %llx filesz %llx memsz %llx offset %llx\n",
(u_longlong_t)php->p_vaddr, (u_longlong_t)php->p_filesz,
(u_longlong_t)php->p_memsz, (u_longlong_t)php->p_offset);
@@ -2105,6 +2305,7 @@ Pfgrab_core(int core_fd, const char *aout_path, int *perr)
*perr = G_FORMAT;
goto err;
}
+ core_info->core_osabi = core.e_hdr.e_ident[EI_OSABI];
/*
* Because the core file may be a large file, we can't use libelf to
@@ -2151,6 +2352,9 @@ Pfgrab_core(int core_fd, const char *aout_path, int *perr)
goto err;
}
break;
+ default:
+ dprintf("Pgrab_core: unknown phdr %d\n", phdr.p_type);
+ break;
}
php = (char *)php + core.e_hdr.e_phentsize;
@@ -2164,7 +2368,8 @@ Pfgrab_core(int core_fd, const char *aout_path, int *perr)
* If we couldn't find anything of type PT_NOTE, or only one PT_NOTE
* was present, abort. The core file is either corrupt or too old.
*/
- if (notes == 0 || notes == 1) {
+ if (notes == 0 || (notes == 1 && core_info->core_osabi ==
+ ELFOSABI_SOLARIS)) {
*perr = G_NOTE;
goto err;
}
@@ -2194,7 +2399,7 @@ Pfgrab_core(int core_fd, const char *aout_path, int *perr)
*/
for (nleft = note_phdr.p_filesz; nleft > 0; ) {
Elf64_Nhdr nhdr;
- off64_t off, namesz;
+ off64_t off, namesz, descsz;
/*
* Although <sys/elf.h> defines both Elf32_Nhdr and Elf64_Nhdr
@@ -2217,6 +2422,7 @@ Pfgrab_core(int core_fd, const char *aout_path, int *perr)
* the name field and the padding to 4-byte alignment.
*/
namesz = P2ROUNDUP((off64_t)nhdr.n_namesz, (off64_t)4);
+
if (lseek64(P->asfd, namesz, SEEK_CUR) == (off64_t)-1) {
dprintf("failed to seek past name and padding\n");
*perr = G_STRANGE;
@@ -2233,17 +2439,20 @@ Pfgrab_core(int core_fd, const char *aout_path, int *perr)
*/
if (nhdr.n_type < sizeof (nhdlrs) / sizeof (nhdlrs[0])) {
if (nhdlrs[nhdr.n_type](P, nhdr.n_descsz) < 0) {
+ dprintf("handler for type %d returned < 0",
+ nhdr.n_type);
*perr = G_NOTE;
goto err;
}
- } else
+ } else {
(void) note_notsup(P, nhdr.n_descsz);
+ }
/*
* Seek past the current note data to the next Elf_Nhdr
*/
- if (lseek64(P->asfd, off + nhdr.n_descsz,
- SEEK_SET) == (off64_t)-1) {
+ descsz = P2ROUNDUP((off64_t)nhdr.n_descsz, (off64_t)4);
+ if (lseek64(P->asfd, off + descsz, SEEK_SET) == (off64_t)-1) {
dprintf("Pgrab_core: failed to seek to next nhdr\n");
*perr = G_STRANGE;
goto err;
@@ -2253,7 +2462,63 @@ Pfgrab_core(int core_fd, const char *aout_path, int *perr)
* Subtract the size of the header and its data from what
* we have left to process.
*/
- nleft -= sizeof (nhdr) + namesz + nhdr.n_descsz;
+ nleft -= sizeof (nhdr) + namesz + descsz;
+ }
+
+ if (core_info->core_osabi == ELFOSABI_NONE) {
+ size_t tcount, pid;
+ lwp_info_t *lwp;
+
+ P->status.pr_dmodel = core_info->core_dmodel;
+
+ lwp = list_next(&core_info->core_lwp_head);
+
+ pid = P->status.pr_pid;
+
+ for (tcount = 0; tcount < core_info->core_nlwp;
+ tcount++, lwp = list_next(lwp)) {
+ dprintf("Linux thread with id %d\n", lwp->lwp_id);
+
+ /*
+ * In the case we don't have a valid psinfo (i.e. pid is
+ * 0, probably because of gdb creating the core) assume
+ * lowest pid count is the first thread (what if the
+ * next thread wraps the pid around?)
+ */
+ if (P->status.pr_pid == 0 &&
+ ((pid == 0 && lwp->lwp_id > 0) ||
+ (lwp->lwp_id < pid))) {
+ pid = lwp->lwp_id;
+ }
+ }
+
+ if (P->status.pr_pid != pid) {
+ dprintf("No valid pid, setting to %ld\n", (ulong_t)pid);
+ P->status.pr_pid = pid;
+ P->psinfo.pr_pid = pid;
+ }
+
+ /*
+ * Consumers like mdb expect the first thread to actually have
+ * an id of 1, on linux that is actually the pid. Find the the
+ * thread with our process id, and set the id to 1
+ */
+ if ((lwp = lwpid2info(P, pid)) == NULL) {
+ dprintf("Couldn't find first thread\n");
+ *perr = G_STRANGE;
+ goto err;
+ }
+
+ dprintf("setting representative thread: %d\n", lwp->lwp_id);
+
+ lwp->lwp_id = 1;
+ lwp->lwp_status.pr_lwpid = 1;
+
+ /* set representative thread */
+ (void) memcpy(&P->status.pr_lwp, &lwp->lwp_status,
+ sizeof (P->status.pr_lwp));
+
+ lwp = list_next(&core_info->core_lwp_head);
}
if (nleft != 0) {
@@ -2375,7 +2640,9 @@ Pfgrab_core(int core_fd, const char *aout_path, int *perr)
* If we're a statically linked executable, then just locate the
* executable's text and data and name them after the executable.
*/
- if (base_addr == (uintptr_t)-1L) {
+ if (base_addr == (uintptr_t)-1L ||
+ core_info->core_osabi == ELFOSABI_NONE) {
+ dprintf("looking for text and data: %s\n", execname);
map_info_t *tmp, *dmp;
file_info_t *fp;
rd_loadobj_t rl;
diff --git a/usr/src/lib/libproc/common/Pcore_linux.h b/usr/src/lib/libproc/common/Pcore_linux.h
new file mode 100644
index 0000000000..f23934f27f
--- /dev/null
+++ b/usr/src/lib/libproc/common/Pcore_linux.h
@@ -0,0 +1,173 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2014, Joyent, Inc.
+ */
+
+#ifndef _PCORE_LINUX_H
+#define _PCORE_LINUX_H
+
+/*
+ * Note that these structures can end up in both a 32-bit and 64-bit libproc.
+ * Therefore, one should generally avoid using types whose size change between
+ * ILP32 and LP64 and instead use the correct fixed width type. eg. long should
+ * be int32_t and int64_t as appropriate to whether it's a 32-bit or 64-bit
+ * structure.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Process Information */
+typedef struct lx_prpsinfo32 {
+ uint8_t pr_state; /* Numeric process state */
+ int8_t pr_sname; /* Char for pr_state */
+ uint8_t pr_zomb; /* Zombie */
+ int8_t pr_nice; /* Nice value */
+ uint32_t pr_flag; /* Flags */
+ uint16_t pr_uid; /* User ID */
+ uint16_t pr_gid; /* Group ID */
+ int32_t pr_pid; /* Process ID */
+ int32_t pr_ppid; /* Parent's process ID */
+ int32_t pr_pgrp; /* Group ID */
+ int32_t pr_sid; /* Session ID */
+ char pr_fname[16]; /* Filename of executable */
+ char pr_psargs[80]; /* Initial part of arg list */
+} lx_prpsinfo32_t;
+
+typedef struct lx_prpsinfo64 {
+ uint8_t pr_state; /* Numeric process state */
+ int8_t pr_sname; /* Char for pr_state */
+ uint8_t pr_zomb; /* Zombie */
+ int8_t pr_nice; /* Nice value */
+ uint64_t pr_flag; /* Flags */
+ uint32_t pr_uid; /* User ID */
+ uint32_t pr_gid; /* Group ID */
+ int32_t pr_pid; /* Process ID */
+ int32_t pr_ppid; /* Parent's process ID */
+ int32_t pr_pgrp; /* Group ID */
+ int32_t pr_sid; /* Session ID */
+ char pr_fname[16]; /* Filename of executable */
+ char pr_psargs[80]; /* Initial part of arg list */
+} lx_prpsinfo64_t;
+
+typedef struct lx_amd64_regs {
+ uint64_t lxr_r15;
+ uint64_t lxr_r14;
+ uint64_t lxr_r13;
+ uint64_t lxr_r12;
+ uint64_t lxr_rbp;
+ uint64_t lxr_rbx;
+ uint64_t lxr_r11;
+ uint64_t lxr_r10;
+ uint64_t lxr_r9;
+ uint64_t lxr_r8;
+ uint64_t lxr_rax;
+ uint64_t lxr_rcx;
+ uint64_t lxr_rdx;
+ uint64_t lxr_rsi;
+ uint64_t lxr_rdi;
+ uint64_t lxr_orig_rax;
+ uint64_t lxr_rip;
+ uint64_t lxr_cs;
+ uint64_t lxr_eflags;
+ uint64_t lxr_rsp;
+ uint64_t lxr_ss;
+ uint64_t lxr_fs_base;
+ uint64_t lxr_gs_base;
+ uint64_t lxr_ds;
+ uint64_t lxr_es;
+ uint64_t lxr_fs;
+ uint64_t lxr_gs;
+} lx_amd64_regs_t;
+
+typedef struct lx_ia32_regs {
+ uint32_t lxr_bx;
+ uint32_t lxr_cx;
+ uint32_t lxr_dx;
+ uint32_t lxr_si;
+ uint32_t lxr_di;
+ uint32_t lxr_bp;
+ uint32_t lxr_ax;
+ uint32_t lxr_ds;
+ uint32_t lxr_es;
+ uint32_t lxr_fs;
+ uint32_t lxr_gs;
+ uint32_t lxr_orig_ax;
+ uint32_t lxr_ip;
+ uint32_t lxr_cs;
+ uint32_t lxr_flags;
+ uint32_t lxr_sp;
+ uint32_t lxr_ss;
+} lx_ia32_regs_t;
+
+typedef struct lx_elf_siginfo {
+ int32_t si_signo; /* Signal number */
+ int32_t si_code; /* Extra code */
+ int32_t si_errno; /* Errno */
+} lx_elf_siginfo_t;
+
+typedef struct lx_elf_timeval32 {
+ int32_t tv_sec; /* Seconds */
+ int32_t tv_usec; /* Microseconds */
+} lx_elf_timeval32_t;
+
+typedef struct lx_elf_timeval64 {
+ int64_t tv_sec; /* Seconds */
+ int64_t tv_usec; /* Microseconds */
+} lx_elf_timeval64_t;
+
+/* Thread Information */
+typedef struct lx_prstatus32 {
+ lx_elf_siginfo_t pr_info; /* Singal Info */
+ uint16_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; /* Process ID */
+ int32_t pr_ppid; /* Parent's process ID */
+ int32_t pr_pgrp; /* Group ID */
+ int32_t pr_sid; /* Session ID */
+ lx_elf_timeval32_t pr_utime; /* User time */
+ lx_elf_timeval32_t pr_stime; /* System time */
+ lx_elf_timeval32_t pr_cutime; /* Cumulative user time */
+ lx_elf_timeval32_t pr_cstime; /* Cumulative system time */
+ lx_ia32_regs_t pr_reg; /* CPU registers */
+ uint32_t pr_fpvalid; /* True if we have fp state */
+} lx_prstatus32_t;
+
+typedef struct lx_prstatus64 {
+ lx_elf_siginfo_t pr_info; /* Singal Info */
+ uint16_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; /* Process ID */
+ int32_t pr_ppid; /* Parent's process ID */
+ int32_t pr_pgrp; /* Group ID */
+ int32_t pr_sid; /* Session ID */
+ lx_elf_timeval64_t pr_utime; /* User time */
+ lx_elf_timeval64_t pr_stime; /* System time */
+ lx_elf_timeval64_t pr_cutime; /* Cumulative user time */
+ lx_elf_timeval64_t pr_cstime; /* Cumulative system time */
+ lx_amd64_regs_t pr_reg; /* CPU registers */
+ uint32_t pr_fpvalid; /* True if we have fp state */
+} lx_prstatus64_t;
+
+#define LTIME_TO_TIMESPEC(dst, src) \
+ (dst).tv_sec = (src).tv_sec; \
+ (dst).tv_nsec = (src).tv_usec * 1000;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PCORE_LINUX_H */