Pgcore.c revision 64e4e50ab4bc3670a29e5691e3dd935c94f0a5d7
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright (c) 2014, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
#define _STRUCTURED_PROC 1
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <procfs.h>
#include <priv.h>
#include <sys/sysmacros.h>
#include <sys/systeminfo.h>
#include <sys/old_procfs.h>
#include "Pcontrol.h"
#include "P32ton.h"
typedef enum {
} shstrtype_t;
static const char *shstrtab_data[] = {
"",
".SUNW_ctf",
".symtab",
".dynsym",
".strtab",
".dynstr",
".shstrtab"
};
typedef struct shstrtab {
int sst_cur;
} shstrtab_t;
typedef struct {
struct ps_prochandle *P;
int pgc_fd;
void *pgc_chunk;
} pgcore_t;
typedef struct {
int fd_fd;
} fditer_t;
static int
{
int err;
if (err < 0)
return (err);
/*
* We will take a page from ZFS's book here and use the otherwise
* unused EBADE to mean a short write. Typically this will actually
* result from ENOSPC or EDQUOT, but we can't be sure.
*/
return (-1);
}
return (0);
}
static void
{
s->sst_cur = 1;
}
static int
{
int ret;
return (ret);
return (ret);
}
static size_t
shstrtab_size(const shstrtab_t *s)
{
return (s->sst_cur);
}
int
{
int fd;
int err;
int saved_errno;
return (-1);
saved_errno = errno;
errno = saved_errno;
return (err);
}
}
/*
* Since we don't want to use the old-school procfs interfaces, we use the
* new-style data structures we already have to construct the old-style
* data structures. We include these data structures in core files for
* backward compatability.
*/
static void
{
/*
* Note that PR_PTRACE (0x0040) from <sys/old_procfs.h> is never set;
*/
}
static void
{
psp->pr_aslwpid = 0;
}
#ifdef _LP64
static void
{
/*
* Note that PR_PTRACE (0x0040) from <sys/old_procfs.h> is never set;
*/
}
static void
{
psp->pr_aslwpid = 0;
}
#endif /* _LP64 */
static int
{
/*
* Note headers are the same regardless of the data model of the
* ELF file; we arbitrarily use Elf64_Nhdr here.
*/
struct {
char name[8];
} n;
bzero(&n, sizeof (n));
return (-1);
*offp += sizeof (n);
return (-1);
return (0);
}
static int
{
struct ps_prochandle *P = pgc->P;
/*
* Legacy core files don't contain information about zombie LWPs.
* We use Plwp_iter_all() so that we get the lwpsinfo_t structure
* more cheaply.
*/
return (0);
return (0);
return (1);
#ifdef _LP64
} else {
return (1);
return (1);
#endif /* _LP64 */
}
#ifdef sparc
{
return (1);
}
#endif /* sparc */
return (0);
}
static int
{
struct ps_prochandle *P = pgc->P;
/*
* If lsp is NULL this indicates that this is a zombie LWP in
* which case we dump only the lwpsinfo_t structure and none of
* the other ancillary LWP state data.
*/
return (1);
return (0);
return (1);
#ifdef _LP64
} else {
return (1);
return (0);
return (1);
#endif /* _LP64 */
}
#ifdef sparc
{
return (1);
}
return (1);
}
}
#ifdef __sparcv9
return (1);
}
}
#endif /* __sparcv9 */
#endif /* sparc */
return (0);
return (0);
return (1);
#ifdef _LP64
} else {
return (1);
#endif /* _LP64 */
}
return (0);
}
static int
{
return (1);
return (0);
}
static uint_t
{
struct ps_prochandle *P = pgc->P;
return (0);
int hit_symtab = 0;
Pbuild_file_symtab(P, fptr);
nshdrs++;
if (fptr->file_ctf_dyn) {
} else {
hit_symtab = 1;
}
nshdrs += 2;
}
nshdrs += 2;
}
}
}
static int
{
return (-1);
#ifdef _LP64
} else {
return (-1);
#endif /* _LP64 */
}
return (0);
}
static int
{
return (0);
return (-1);
return (-1);
return (-1);
return (-1);
return (0);
}
static int
{
struct ps_prochandle *P = pgc->P;
return (0);
int hit_symtab = 0;
Pbuild_file_symtab(P, fptr);
/*
* Write the symtab out first so we can correctly
* set the sh_link field in the CTF section header.
* symindex will be 0 if there is no corresponding
* symbol table section.
*/
if (fptr->file_ctf_dyn) {
dynsym = 1;
} else {
dynsym = 0;
hit_symtab = 1;
}
return (-1);
index += 2;
}
/*
* Write the CTF data that we've read out of the
* file itself into the core file.
*/
return (-1);
return (-1);
index++;
}
return (-1);
index += 2;
}
}
return (0);
}
/*ARGSUSED*/
static int
{
struct ps_prochandle *P = pgc->P;
#ifdef _LP64
#else
#endif
size_t n;
goto exclude;
goto exclude;
goto exclude;
} else {
goto exclude;
}
goto exclude;
goto exclude;
} else {
goto exclude;
}
goto exclude;
goto exclude;
goto exclude;
} else {
goto exclude;
}
n = 0;
/*
* If we can't read out part of the victim's address
* space for some reason ignore that failure and try to
* emit a partial core file without that mapping's data.
* As in the kernel, we mark these failures with the
* PF_SUNW_FAILURE flag and store the errno where the
* mapping would have been.
*/
goto exclude;
}
n += csz;
}
return (1);
#ifdef _LP64
} else {
return (1);
#endif /* _LP64 */
}
return (0);
}
int
{
int i, ndx;
if (shstrtab_size(s) == 1)
return (0);
/*
* Preemptively stick the name of the shstrtab in the string table.
*/
size = shstrtab_size(s);
/*
* Dump all the strings that we used being sure we include the
* terminating null character.
*/
for (i = 0; i < STR_NUM; i++) {
const char *str = shstrtab_data[i];
return (1);
}
}
return (1);
#ifdef _LP64
} else {
return (1);
#endif /* _LP64 */
}
return (0);
}
/*
* Don't explicity stop the process; that's up to the consumer.
*/
int
{
char zonename[ZONENAME_MAX];
int platlen = -1;
if (ftruncate64(fd, 0) != 0)
return (-1);
if (content == CC_CONTENT_INVALID) {
return (-1);
}
/*
* Cache the mappings and other useful data.
*/
(void) Prd_agent(P);
(void) Ppsinfo(P);
pgc.P = P;
return (-1);
/*
* There are two PT_NOTE program headers for ancillary data, and
* one for each mapping.
*/
Preadauxvec(P);
zonename[0] = '\0';
/*
* The core file contents may required zero section headers, but if we
* overflow the 16 bits allotted to the program header count in the ELF
* header, we'll need that program header at index zero.
*/
nshdrs = 1;
/*
* Set up the ELF header.
*/
#if defined(__sparc)
#else
#error "unknown machine type"
#endif
else
if (nshdrs > 0) {
if (nshdrs >= SHN_LORESERVE)
else
else
}
goto err;
#ifdef _LP64
} else {
#if defined(__sparc)
#else
#error "unknown machine type"
#endif
else
if (nshdrs > 0) {
if (nshdrs >= SHN_LORESERVE)
else
else
}
goto err;
#endif /* _LP64 */
}
/*
* Write the zero indexed section if it exists.
*/
goto err;
/*
* Construct the old-style note header and section.
*/
mkprpsinfo(P, &prpsinfo);
&doff) != 0) {
goto err;
}
goto err;
}
#ifdef _LP64
} else {
int i;
mkprpsinfo32(P, &pi32);
&doff) != 0) {
goto err;
}
goto err;
for (i = 0; i < P->nauxv; i++) {
}
goto err;
}
#endif /* _LP64 */
}
goto err;
goto err;
goto err;
#ifdef _LP64
} else {
goto err;
#endif /* _LP64 */
}
/*
* Construct the new-style note header and section.
*/
&doff) != 0) {
goto err;
}
&doff) != 0) {
goto err;
}
goto err;
}
#ifdef _LP64
} else {
int i;
&doff) != 0) {
goto err;
}
&doff) != 0) {
goto err;
}
goto err;
for (i = 0; i < P->nauxv; i++) {
}
goto err;
}
#endif /* _LP64 */
}
goto err;
{
goto err;
if (cred.pr_ngroups > 0)
goto err;
goto err;
}
}
{
const priv_impl_info_t *pinfo;
goto err;
goto err;
}
goto err;
goto err;
}
&doff) != 0)
goto err;
{
goto err;
}
/* CSTYLED */
{
int nldt;
/*
* Only dump out non-zero sized LDT notes.
*/
goto err;
goto err;
}
}
}
#endif /* __i386 || __amd64 */
goto err;
goto err;
#ifdef _LP64
} else {
goto err;
#endif /* _LP64 */
}
/*
* Construct the headers for each mapping and write out its data
* if the content parameter indicates that it should be present
* in the core file.
*/
goto err;
if (dump_sections(&pgc) != 0)
goto err;
if (write_shstrtab(P, &pgc) != 0)
goto err;
return (0);
err:
/*
* Wipe out anything we may have written if there was an error.
*/
(void) ftruncate64(fd, 0);
return (-1);
}
static const char *content_str[] = {
"stack", /* CC_CONTENT_STACK */
"heap", /* CC_CONTENT_HEAP */
"shfile", /* CC_CONTENT_SHFILE */
"shanon", /* CC_CONTENT_SHANON */
"text", /* CC_CONTENT_TEXT */
"data", /* CC_CONTENT_DATA */
"rodata", /* CC_CONTENT_RODATA */
"anon", /* CC_CONTENT_ANON */
"shm", /* CC_CONTENT_SHM */
"ism", /* CC_CONTENT_ISM */
"dism", /* CC_CONTENT_DISM */
"ctf", /* CC_CONTENT_CTF */
"symtab", /* CC_CONTENT_SYMTAB */
};
int
{
int add = 1;
for (;;) {
continue;
mask = 0;
} else {
int i = 0;
i++;
if (i >= ncontent_str)
return (-1);
}
}
if (add)
else
switch (*cur) {
case '\0':
return (0);
case '+':
add = 1;
break;
case '-':
add = 0;
break;
default:
return (-1);
}
}
}
static int
{
int i;
for (i = 0; x != 0; i++)
x &= x - 1;
return (i);
}
int
{
int first;
if (content == 0)
if (content & ~CC_CONTENT_ALL)
first = 0;
if (n > size)
n = size;
buf += n;
size -= n;
first = 0;
if (n > size)
n = size;
buf += n;
size -= n;
} else {
first = 1;
}
while (mask != 0) {
if (!first) {
if (size > 1) {
buf++;
size--;
}
tot++;
}
if (n > size)
n = size;
buf += n;
size -= n;
first = 0;
}
return ((int)tot);
}