tnfxtract.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <libintl.h>
#include <unistd.h>
#include <string.h>
#include <kvm.h>
#include <fcntl.h>
#include <nlist.h>
#include <errno.h>
#define MAXFWTRY 5
typedef struct {
} BLOCK_STATUS;
static char *dumpfile; /* Dump file if extracting from crashdump */
static char *namelist; /* Symbol tbl. if extracting from crashdump */
{ "tnf_buf" },
{ "tnf_trace_file_size" },
{ NULL }
};
static uintptr_t dump_bufaddr;
static size_t tnf_bufsize;
static char *program_name;
static int input_fd;
static int output_fd;
static tnf_file_header_t *tnf_header;
/*
* usage() - gives a description of the arguments, and exits
*/
static void
{
if (msg)
"usage: %s [-d <dumpfile> -n <symbolfile> ] "
"<output-filename>\n"), argv[0]);
exit(1);
} /* end usage */
/*
* Write 'size' bytes at offset 'offset' from 'addr'
* to the output file. Bail out unceremoniously if anything goes wrong.
*/
static void
{
perror("lseek");
exit(1);
}
perror("write");
exit(1);
}
}
static void
{
/* kvm_open prints an error message */
exit(1);
}
"Symbol lookup error in %s\n"), namelist);
exit(1);
}
sizeof (dump_bufaddr)) != sizeof (dump_bufaddr) ||
sizeof (tnf_bufsize)) != sizeof (tnf_bufsize)) {
"kvm_read error in %s\n"), dumpfile);
exit(1);
}
"No trace data available in the kernel.\n"));
exit(1);
}
}
static void
{
exit(1);
}
exit(1);
}
"No trace data available in the kernel.\n"));
exit(1);
}
}
static void
read_tnf_header(char *addr)
{
"Error reading tnf header from dump file.\n"));
exit(1);
}
} else {
exit(1);
}
}
}
static int
{
int offset;
"Error reading tnf block.\n"));
exit(1);
}
} else {
return (EBUSY);
exit(1);
}
}
return (0);
}
static void
{
int offset;
int len;
/* LINTED assignment of 64-bit integer to 32-bit integer */
/* LINTED assignment of 64-bit integer to 32-bit integer */
"Error reading tnf forwarding zone.\n"));
exit(1);
}
} else {
/* LINTED pointer cast may result in improper alignment */
exit(1);
}
}
}
int
{
const char *optstr = "d:n:";
const char *outfile;
char *local_buf;
int c;
int block_num;
int fwzonesize;
int i;
int fwtries;
int block_count;
program_name = argv[0];
switch (c) {
case 'd':
break;
case 'n':
break;
case '?':
}
}
} else {
}
"-d and -n options"));
}
if (output_fd < 0) {
exit(1);
}
else
gettext("tnfxtract memory allocation failure\n"));
exit(1);
}
/* Read header, get block size, check for version mismatch */
/*LINTED pointer cast may result in improper alignment*/
/*LINTED pointer cast may result in improper alignment*/
"Buffer is not in TNF format.\n"));
exit(1);
}
gettext("Version mismatch (tnfxtract: %d; buffer: %d)\n"),
exit(1);
}
/* LINTED pointer cast may result in improper alignment */
block_base = (tnf_block_header_t *)
block_stat = (BLOCK_STATUS *)
if (block_stat == NULL) {
gettext("tnfxtract memory allocation failure\n"));
exit(1);
}
/*
* Make repeated passes until we've read every non-tag block.
*/
do {
bsp = block_stat;
block_num = 0;
blockp = block_base;
while (block_num != block_count) {
any_unread = B_TRUE;
else {
/* LINTED cast 64 to 32 bit */
}
}
++bsp;
++block_num;
/* LINTED pointer cast may result in improper alignment */
blockp = (tnf_block_header_t *)
}
} while (any_unread);
/*
* Then read tag blocks only, until we have two consecutive,
* consistent reads.
*/
do {
bsp = block_stat;
block_num = 0;
blockp = block_base;
while (block_num != block_count) {
/* LINTED cast 64bit to 32 bit */
}
++bsp;
++block_num;
/* LINTED pointer cast may result in improper alignment */
blockp = (tnf_block_header_t *)
}
} while (any_different);
/*
* Then read the forwarding pointers. If any are -1:
* sleep briefly, then make another pass.
*/
/*LINTED pointer cast may result in improper alignment*/
/* LINTED cast from 64-bit integer to 32-bit integer */
(int)(fwzonesize / sizeof (fwzone[0])));
fwtries = 0;
for (i = 0; i != fwzonesize / sizeof (fwzone[0]); ++i) {
if (fwzone[i] == -1) {
if (!retry) {
++fwtries;
}
}
}
if (!retry)
break;
sleep(2);
}
"Warning: forwarding pointers may "
"be invalid.\n"));
}
return (0);
}