mdb_fmt.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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Format String Decoder
*
* This file provides the core engine for converting strings of format
* characters into formatted output. The various format dcmds invoke the
* mdb_fmt_print() function below with a target, address space identifier,
* address, count, and format character, and it reads the required data from
* the target and prints the formatted output to stdout. Since nearly two
* thirds of the format characters can be expressed as simple printf format
* strings, we implement the engine using the lookup table below. Each entry
* provides either a pointer to a printf format string or a pointer to a
* function to perform special processing. For the printf case, the
* corresponding data size in bytes is also supplied. The printf processing
* code handles 1, 2, 4, and 8-byte reads into an unsigned integer container
* of the given size, and then simply calls mdb_iob_printf with the integer
* and format string. This handles all printf cases, except when unsigned
* promotion of an integer type in the varargs list does not perform the
* conversion we require to get the proper result. With the current set of
* format characters, this case only occurs twice: we need a 4-byte float
* to get promoted to 8-byte double for the 'f' format so it can be
* correctly formatted by %f, and we need a 1-byte int8_t to get promoted
* with sign extension to a 4-byte int32_t for the 'v' format so it can be
* correctly formatted by %d. We provide explicit functions to handle these
* cases, as well as to handle special format characters such as 'i', etc.
* We also provide a cmd_formats() dcmd function below which prints a table
* of the output formats and their sizes. Format characters that provide
* custom functions provide their help description string explicitly. All
* the printf formats have their help strings generated automatically by
* our printf "unparser" mdb_iob_format2str().
*/
#include <mdb/mdb_types.h>
#include <mdb/mdb_target.h>
#include <mdb/mdb_string.h>
#include <mdb/mdb_modapi.h>
#define FUNCP(p) ((void *)(p)) /* Cast to f_ptr type */
/*
* There are several 'special' characters that are handled outside of
* mdb_fmt_print(). These are characters that write (vwWZ) and characters that
* match (lLM). We include them here so that ::formats can display an
* appropriate message, but they are handled specially by write_arglist() and
* match_arglist() in mdb_cmds.c.
*/
typedef struct mdb_fmt_desc {
int f_type; /* Type of format (see above) */
void *f_ptr; /* Data pointer (see above) */
const char *f_help; /* Additional help string */
static const char help_plus[] = "increment dot by the count";
static const char help_minus[] = "decrement dot by the count";
static const char help_escchr[] = "character using C character notation";
static const char help_swapint[] = "swap bytes and shorts";
static const char help_dotinstr[] = "address and disassembled instruction";
static const char help_instr[] = "disassembled instruction";
static const char help_escstr[] = "string using C string notation";
static const char help_time32[] = "decoded time32_t";
static const char help_carat[] = "decrement dot by increment * count";
static const char help_dot[] = "dot as symbol+offset";
#ifndef _KMDB
static const char help_f[] = "float";
#endif
static const char help_swapshort[] = "swap bytes";
static const char help_nl[] = "newline";
static const char help_ws[] = "whitespace";
static const char help_rawstr[] = "raw string";
static const char help_tab[] = "horizontal tab";
static const char help_sdbyte[] = "decimal signed int";
static const char help_time64[] = "decoded time64_t";
static const char help_binary[] = "binary unsigned long long";
static const char help_hex64[] = "hexadecimal long long";
static const char help_match32[] = "int";
static const char help_match64[] = "long long";
static const char help_match16[] = "short";
static const char help_uintptr[] = "hexadecimal uintptr_t";
/*ARGSUSED*/
static mdb_tgt_addr_t
{
char buf[24];
while (cnt-- != 0)
} else {
while (cnt-- != 0)
}
return (addr);
}
#ifndef _KMDB
static mdb_tgt_addr_t
{
float f;
/*
* We need to handle float as a special case because we need it to be
* promoted to a double by virtue of appearing as a parameter, and all
* our generic format handling below is based on integer types.
*/
while (cnt-- != 0) {
warn("failed to read data from target");
break;
}
addr += sizeof (f);
}
return (addr);
}
#endif
/*ARGSUSED*/
static mdb_tgt_addr_t
{
}
/*ARGSUSED*/
static mdb_tgt_addr_t
{
}
/*ARGSUSED*/
static mdb_tgt_addr_t
{
}
/*ARGSUSED*/
static mdb_tgt_addr_t
{
while (cnt-- != 0)
return (addr);
}
/*ARGSUSED*/
static mdb_tgt_addr_t
{
return (addr);
}
/*ARGSUSED*/
static mdb_tgt_addr_t
{
return (addr);
}
static mdb_tgt_addr_t
{
do {
if (nbytes > 0) {
} else if (nbytes < 0) {
warn("failed to read data from target");
goto out;
}
if (cnt != 0)
}
out:
return (addr);
}
static mdb_tgt_addr_t
{
char *s;
do {
if (nbytes > 0) {
strfree(s);
} else if (nbytes < 0) {
warn("failed to read data from target");
goto out;
}
if (cnt != 0)
}
out:
return (addr);
}
static mdb_tgt_addr_t
{
char *buf, *s;
convert = &strchr2adb;
else
convert = &strchr2esc;
strfree(s);
}
return (addr);
}
static mdb_tgt_addr_t
{
ushort_t x;
while (cnt-- != 0) {
x = (x << 8) | (x >> 8);
addr += sizeof (x);
} else {
warn("failed to read data from target");
break;
}
}
return (addr);
}
static mdb_tgt_addr_t
{
uint_t x;
while (cnt-- != 0) {
x = ((x << 24) | ((x << 8) & 0xff0000) |
((x >> 8) & 0xff00) | ((x >> 24) & 0xff));
addr += sizeof (x);
} else {
warn("failed to read data from target");
break;
}
}
return (addr);
}
static mdb_tgt_addr_t
{
uint32_t x;
while (cnt-- != 0) {
addr += sizeof (x);
} else {
warn("failed to read data from target");
break;
}
}
return (addr);
}
static mdb_tgt_addr_t
{
uint64_t x;
while (cnt-- != 0) {
addr += sizeof (x);
} else {
warn("failed to read data from target");
break;
}
}
return (addr);
}
static mdb_tgt_addr_t
{
int8_t x;
while (cnt-- != 0) {
addr += sizeof (x);
} else {
warn("failed to read data from target");
break;
}
}
return (addr);
}
static mdb_tgt_addr_t
{
while (cnt-- != 0) {
return (addr); /* If we didn't move, we failed */
}
return (addr);
}
static mdb_tgt_addr_t
{
uint32_t i;
warn("failed to read data from target");
break; /* Fail if we can't read instruction */
}
break; /* Fail if we didn't advance */
}
return (addr);
}
static mdb_tgt_addr_t
{
uint64_t x;
while (cnt-- != 0) {
addr += sizeof (x);
} else {
warn("failed to read data from target");
break;
}
}
return (addr);
}
static mdb_tgt_addr_t
{
uint64_t x;
while (cnt-- != 0) {
addr += sizeof (x);
} else {
warn("failed to read data from target");
break;
}
}
return (addr);
}
static const mdb_fmt_desc_t fmttab[] = {
#ifdef _KMDB
#else
#endif
#ifdef _LP64
#else
#endif
#ifdef _KMDB
#else
#endif
};
{
void *buf;
union {
} u;
return (addr);
}
case FMT_FUNC:
break;
case FMT_PRINTF:
case 1:
break;
case 2:
break;
case 4:
break;
case 8:
break;
default:
}
while (cnt-- != 0) {
warn("failed to read data from target");
return (addr);
}
case 1:
break;
case 2:
break;
case 4:
break;
case 8:
break;
}
}
break;
default:
}
return (addr);
}
/*ARGSUSED*/
int
{
int i;
const char *write;
return (DCMD_USAGE);
continue;
else
case SZ_NONE:
mdb_printf("\n");
break;
case 0:
mdb_printf(" (variable size)\n");
break;
case 1:
mdb_printf(" (1 byte)\n");
break;
default:
}
}
return (DCMD_OK);
}