diff options
Diffstat (limited to 'usr/src')
69 files changed, 4053 insertions, 4256 deletions
diff --git a/usr/src/Makefile.lint b/usr/src/Makefile.lint index 7bfc2e94e5..cbd6d1588b 100644 --- a/usr/src/Makefile.lint +++ b/usr/src/Makefile.lint @@ -101,6 +101,7 @@ COMMON_SUBDIRS = \ cmd/devmgmt \ cmd/dfs.cmds \ cmd/diff3 \ + cmd/dis \ cmd/dirname \ cmd/diskscan \ cmd/dispadmin \ @@ -302,6 +303,7 @@ COMMON_SUBDIRS = \ lib/libdhcpdu \ lib/libdhcpsvc \ lib/libdhcputil \ + lib/libdisasm \ lib/libdiskmgt \ lib/libdladm \ lib/libdlpi \ diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile index e8ec1adb3b..b72d2d2104 100644 --- a/usr/src/cmd/Makefile +++ b/usr/src/cmd/Makefile @@ -124,6 +124,7 @@ COMMON_SUBDIRS= \ diffmk \ dircmp \ dirname \ + dis \ diskmgtd \ dispadmin \ dladm \ diff --git a/usr/src/cmd/dis/Makefile b/usr/src/cmd/dis/Makefile new file mode 100644 index 0000000000..e1f2d233f1 --- /dev/null +++ b/usr/src/cmd/dis/Makefile @@ -0,0 +1,50 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + +PROG= dis +OBJS= dis_target.o dis_main.o dis_util.o dis_list.o +SRCS= $(OBJS:%.o=%.c) + +include ../Makefile.cmd + +LDLIBS += -ldisasm -luutil -lelf + +.KEEP_STATE: + +all: $(PROG) + +$(PROG): $(OBJS) + $(LINK.c) -o $@ $(OBJS) $(LDLIBS) + $(POST_PROCESS) + +install: all $(ROOTCCSBINPROG) + +clean: + $(RM) $(OBJS) $(PROG) + +lint: lint_SRCS + +include ../Makefile.targ diff --git a/usr/src/cmd/dis/dis_list.c b/usr/src/cmd/dis/dis_list.c new file mode 100644 index 0000000000..46b3ccd9db --- /dev/null +++ b/usr/src/cmd/dis/dis_list.c @@ -0,0 +1,410 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#include "dis_target.h" +#include "dis_list.h" +#include "dis_util.h" + +/* + * List support functions. + * + * Support routines for managing lists of sections and functions. We first + * process the command line arguments into lists of strings. For each target, + * we resolve these strings against the set of available sections and/or + * functions to arrive at the set of objects to disassemble. + * + * We export two types of lists, namelists and resolvelists. The first is used + * to record names given as command line options. The latter is used to + * maintain the data objects specific to a given target. + */ + +typedef struct unresolved_name { + const char *un_name; /* name of function or object */ + int un_value; /* user-supplied data */ + int un_mark; /* internal counter */ + uu_list_node_t un_node; /* uulist node */ +} unresolved_name_t; + +typedef struct resolved_name { + void *rn_data; /* section or function data */ + int rn_value; /* user-supplied data */ + uu_list_node_t rn_node; /* uulist node */ +} resolved_name_t; + +static uu_list_pool_t *unresolved_pool; +static uu_list_pool_t *resolved_pool; +static int current_mark = 0; + +static void +initialize_pools(void) +{ + unresolved_pool = uu_list_pool_create( + "unresolved_pool", sizeof (unresolved_name_t), + offsetof(unresolved_name_t, un_node), NULL, 0); + resolved_pool = uu_list_pool_create( + "resolved_pool", sizeof (resolved_name_t), + offsetof(resolved_name_t, rn_node), NULL, 0); + + if (unresolved_pool == NULL || + resolved_pool == NULL) + die("out of memory"); +} + +/* + * Returns an empty list of unresolved names. + */ +dis_namelist_t * +dis_namelist_create(void) +{ + uu_list_t *listp; + + /* + * If this is the first request to create a list, initialize the list + * pools. + */ + if (unresolved_pool == NULL) + initialize_pools(); + + if ((listp = uu_list_create(unresolved_pool, NULL, 0)) == NULL) + die("out of memory"); + + return (listp); +} + +/* + * Adds the given name to the unresolved list. 'value' is an arbitrary value + * which is preserved for this entry, even when resolved against a target. This + * allows the caller to associate similar behavior (such as the difference + * between -d, -D, and -s) without having to create multiple lists. + */ +void +dis_namelist_add(dis_namelist_t *list, const char *name, int value) +{ + unresolved_name_t *node; + + node = safe_malloc(sizeof (unresolved_name_t)); + + node->un_name = name; + node->un_value = value; + node->un_mark = 0; + + (void) uu_list_insert_before(list, NULL, node); +} + +/* + * Internal callback structure used + */ +typedef struct cb_data { + int cb_mark; + uu_list_t *cb_source; + uu_list_t *cb_resolved; +} cb_data_t; + +/* + * For each section, walk the list of unresolved names and resolve those that + * correspond to real functions. We mark functions as we see them, and re-walk + * the list a second time to warn about functions we didn't find. + * + * This is an O(n * m) algorithm, but we typically search for only a single + * function. + */ +/* ARGSUSED */ +static void +walk_sections(dis_tgt_t *tgt, dis_scn_t *scn, void *data) +{ + cb_data_t *cb = data; + unresolved_name_t *unp; + uu_list_walk_t *walk; + + if ((walk = uu_list_walk_start(cb->cb_source, UU_DEFAULT)) == NULL) + die("out of memory"); + + while ((unp = uu_list_walk_next(walk)) != NULL) { + if (strcmp(unp->un_name, dis_section_name(scn)) == 0) { + resolved_name_t *resolved; + + /* + * Mark the current node as seen + */ + unp->un_mark = cb->cb_mark; + + /* + * Add the data to the resolved list + */ + resolved = safe_malloc(sizeof (resolved_name_t)); + + resolved->rn_data = dis_section_copy(scn); + resolved->rn_value = unp->un_value; + + (void) uu_list_insert_before(cb->cb_resolved, NULL, + resolved); + } + } + + uu_list_walk_end(walk); +} + +/* + * Take a list of unresolved names and create a resolved list of sections. We + * rely on walk_sections() to do the dirty work. After resolving the sections, + * we check for any unmarked names and warn the user about missing sections. + */ +dis_scnlist_t * +dis_namelist_resolve_sections(dis_namelist_t *namelist, dis_tgt_t *tgt) +{ + uu_list_t *listp; + cb_data_t cb; + unresolved_name_t *unp; + uu_list_walk_t *walk; + + /* + * Walk all sections in the target, calling walk_sections() for each + * one. + */ + if ((listp = uu_list_create(resolved_pool, NULL, UU_DEFAULT)) == NULL) + die("out of memory"); + + cb.cb_mark = ++current_mark; + cb.cb_source = namelist; + cb.cb_resolved = listp; + + dis_tgt_section_iter(tgt, walk_sections, &cb); + + /* + * Walk all elements of the unresolved list, and report any that we + * didn't mark in the process. + */ + if ((walk = uu_list_walk_start(namelist, UU_DEFAULT)) == NULL) + die("out of memory"); + + while ((unp = uu_list_walk_next(walk)) != NULL) { + if (unp->un_mark != current_mark) + warn("failed to find section '%s' in '%s'", + unp->un_name, dis_tgt_name(tgt)); + } + + uu_list_walk_end(walk); + + return (listp); +} + +/* + * Similar to walk_sections(), but for functions. + */ +/* ARGSUSED */ +static void +walk_functions(dis_tgt_t *tgt, dis_func_t *func, void *data) +{ + cb_data_t *cb = data; + unresolved_name_t *unp; + uu_list_walk_t *walk; + + if ((walk = uu_list_walk_start(cb->cb_source, UU_DEFAULT)) == NULL) + die("out of memory"); + + while ((unp = uu_list_walk_next(walk)) != NULL) { + if (strcmp(unp->un_name, dis_function_name(func)) == 0) { + resolved_name_t *resolved; + + unp->un_mark = cb->cb_mark; + + resolved = safe_malloc(sizeof (resolved_name_t)); + + resolved->rn_data = dis_function_copy(func); + resolved->rn_value = unp->un_value; + + (void) uu_list_insert_before(cb->cb_resolved, NULL, + resolved); + } + } + + uu_list_walk_end(walk); +} + +/* + * Take a list of unresolved names and create a resolved list of functions. We + * rely on walk_functions() to do the dirty work. After resolving the + * functions, * we check for any unmarked names and warn the user about missing + * functions. + */ +dis_funclist_t * +dis_namelist_resolve_functions(dis_namelist_t *namelist, dis_tgt_t *tgt) +{ + uu_list_t *listp; + uu_list_walk_t *walk; + unresolved_name_t *unp; + cb_data_t cb; + + if ((listp = uu_list_create(resolved_pool, NULL, UU_DEFAULT)) == NULL) + die("out of memory"); + + cb.cb_mark = ++current_mark; + cb.cb_source = namelist; + cb.cb_resolved = listp; + + dis_tgt_function_iter(tgt, walk_functions, &cb); + + /* + * Walk unresolved list and report any missing functions. + */ + if ((walk = uu_list_walk_start(namelist, UU_DEFAULT)) == NULL) + die("out of memory"); + + while ((unp = uu_list_walk_next(walk)) != NULL) { + if (unp->un_mark != current_mark) + warn("failed to find function '%s' in '%s'", + unp->un_name, dis_tgt_name(tgt)); + } + + uu_list_walk_end(walk); + + return (listp); +} + +/* + * Returns true if the given list is empty. + */ +int +dis_namelist_empty(dis_namelist_t *list) +{ + return (uu_list_numnodes(list) == 0); +} + +static void +free_list(uu_list_t *list) +{ + uu_list_walk_t *walk; + void *data; + + if ((walk = uu_list_walk_start(list, UU_WALK_ROBUST)) == NULL) + die("out of memory"); + + while ((data = uu_list_walk_next(walk)) != NULL) { + uu_list_remove(list, data); + free(data); + } + + uu_list_walk_end(walk); + + uu_list_destroy(list); +} + +/* + * Destroy a list of sections. First, walk the list and free the associated + * section data. Pass the list onto to free_list() to clean up the rest of the + * list. + */ +void +dis_scnlist_destroy(dis_scnlist_t *list) +{ + uu_list_walk_t *walk; + resolved_name_t *data; + + if ((walk = uu_list_walk_start(list, UU_DEFAULT)) == NULL) + die("out of memory"); + + while ((data = uu_list_walk_next(walk)) != NULL) + dis_section_free(data->rn_data); + + uu_list_walk_end(walk); + + free_list(list); +} + +/* + * Destroy a list of functions. First, walk the list and free the associated + * function data. Pass the list onto to free_list() to clean up the rest of the + * list. + */ +void +dis_funclist_destroy(dis_funclist_t *list) +{ + uu_list_walk_t *walk; + resolved_name_t *data; + + if ((walk = uu_list_walk_start(list, UU_DEFAULT)) == NULL) + die("out of memory"); + + while ((data = uu_list_walk_next(walk)) != NULL) + dis_function_free(data->rn_data); + + uu_list_walk_end(walk); + + free_list(list); +} + +/* + * Destroy a lis tof unresolved names. + */ +void +dis_namelist_destroy(dis_namelist_t *list) +{ + free_list(list); +} + +/* + * Iterate over a resolved list of sections. + */ +void +dis_scnlist_iter(uu_list_t *list, void (*func)(dis_scn_t *, int, void *), + void *arg) +{ + uu_list_walk_t *walk; + resolved_name_t *data; + + if ((walk = uu_list_walk_start(list, UU_DEFAULT)) == NULL) + die("out of memory"); + + while ((data = uu_list_walk_next(walk)) != NULL) + func(data->rn_data, data->rn_value, arg); + + uu_list_walk_end(walk); +} + +/* + * Iterate over a resolved list of functions. + */ +void +dis_funclist_iter(uu_list_t *list, void (*func)(dis_func_t *, int, void *), + void *arg) +{ + uu_list_walk_t *walk; + resolved_name_t *data; + + if ((walk = uu_list_walk_start(list, UU_DEFAULT)) == NULL) + die("out of memory"); + + while ((data = uu_list_walk_next(walk)) != NULL) + func(data->rn_data, data->rn_value, arg); + + uu_list_walk_end(walk); +} diff --git a/usr/src/cmd/dis/dis_list.h b/usr/src/cmd/dis/dis_list.h new file mode 100644 index 0000000000..cb32809654 --- /dev/null +++ b/usr/src/cmd/dis/dis_list.h @@ -0,0 +1,61 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _DIS_LIST_H +#define _DIS_LIST_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <libuutil.h> + +/* #include "dis_target.h" */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uu_list_t dis_namelist_t; +typedef uu_list_t dis_scnlist_t; +typedef uu_list_t dis_funclist_t; + +dis_namelist_t *dis_namelist_create(void); +void dis_namelist_add(dis_namelist_t *, const char *, int); +dis_funclist_t *dis_namelist_resolve_functions(dis_namelist_t *, dis_tgt_t *); +dis_scnlist_t *dis_namelist_resolve_sections(dis_namelist_t *, dis_tgt_t *); +void dis_scnlist_iter(dis_scnlist_t *, void (*)(dis_scn_t *, int, void *), + void *); +void dis_funclist_iter(dis_funclist_t *, void (*)(dis_func_t *, int, void *), + void *); +int dis_namelist_empty(dis_namelist_t *); +void dis_scnlist_destroy(dis_scnlist_t *); +void dis_funclist_destroy(dis_funclist_t *); +void dis_namelist_destroy(dis_namelist_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _DIS_LIST_H */ diff --git a/usr/src/cmd/dis/dis_main.c b/usr/src/cmd/dis/dis_main.c new file mode 100644 index 0000000000..217109c77e --- /dev/null +++ b/usr/src/cmd/dis/dis_main.c @@ -0,0 +1,682 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <ctype.h> +#include <getopt.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/sysmacros.h> +#include <sys/elf_SPARC.h> + +#include <libdisasm.h> + +#include "dis_target.h" +#include "dis_util.h" +#include "dis_list.h" + +int g_demangle; /* Demangle C++ names */ +int g_quiet; /* Quiet mode */ +int g_numeric; /* Numeric mode */ +int g_flags; /* libdisasm language flags */ +int g_doall; /* true if no functions or sections were given */ + +dis_namelist_t *g_funclist; /* list of functions to disassemble, if any */ +dis_namelist_t *g_seclist; /* list of sections to disassemble, if any */ + +/* + * Section options for -d, -D, and -s + */ +#define DIS_DATA_RELATIVE 1 +#define DIS_DATA_ABSOLUTE 2 +#define DIS_TEXT 3 + +/* + * libdisasm callback data. Keeps track of current data (function or section) + * and offset within that data. + */ +typedef struct dis_buffer { + dis_tgt_t *db_tgt; /* current dis target */ + void *db_data; /* function or section data */ + uint64_t db_addr; /* address of function start */ + size_t db_size; /* size of data */ + uint64_t db_nextaddr; /* next address to be read */ +} dis_buffer_t; + +#define MINSYMWIDTH 22 /* Minimum width of symbol portion of line */ + +/* + * Given a symbol+offset as returned by dis_tgt_lookup(), print an appropriately + * formatted symbol, based on the offset and current setttings. + */ +void +getsymname(uint64_t addr, const char *symbol, off_t offset, char *buf, + size_t buflen) +{ + if (symbol == NULL || g_numeric) + (void) snprintf(buf, buflen, "%llx", addr); + else { + if (g_demangle) + symbol = dis_demangle(symbol); + + if (offset == 0) + (void) snprintf(buf, buflen, "%s", symbol); + else if (g_flags & DIS_OCTAL) + (void) snprintf(buf, buflen, "%s+0%o", symbol, offset); + else + (void) snprintf(buf, buflen, "%s+0x%x", symbol, offset); + } +} + +/* + * The main disassembly routine. Given a fixed-sized buffer and starting + * address, disassemble the data using the supplied target and libdisasm handle. + */ +void +dis_data(dis_tgt_t *tgt, dis_handle_t *dhp, uint64_t addr, void *data, + size_t datalen) +{ + dis_buffer_t db = { 0 }; + char buf[BUFSIZE]; + char symbuf[BUFSIZE]; + const char *symbol; + off_t symoffset; + int i; + int bytesperline; + size_t symsize; + int isfunc; + size_t symwidth = 0; + + db.db_tgt = tgt; + db.db_data = data; + db.db_addr = addr; + db.db_size = datalen; + + dis_set_data(dhp, &db); + + if ((bytesperline = dis_max_instrlen(dhp)) > 6) + bytesperline = 6; + + while (addr < db.db_addr + db.db_size) { + + if (dis_disassemble(dhp, addr, buf, BUFSIZE) != 0) { + /* + * If we encounter an invalid opcode, we just + * print "*** invalid opcode ***" at that first bad + * instruction and continue with printing the rest + * of the instruction stream as hex data, + * We then find the next valid symbol in the section, + * and disassemble from there. + */ + off_t next; + + (void) snprintf(buf, sizeof (buf), + "*** invalid opcode ***"); + + if ((next = dis_tgt_next_symbol(tgt, addr)) == 0) { + db.db_nextaddr = db.db_addr + db.db_size; + } else { + if (next > db.db_size) + db.db_nextaddr = db.db_addr + + db.db_size; + else + db.db_nextaddr = addr + next; + } + } + + /* + * Print out the line as: + * + * address: bytes text + * + * If there are more than 6 bytes in any given instruction, + * spread the bytes across two lines. We try to get symbolic + * information for the address, but if that fails we print out + * the numeric address instead. + * + * We try to keep the address portion of the text aligned at + * MINSYMWIDTH characters. If we are disassembling a function + * with a long name, this can be annoying. So we pick a width + * based on the maximum width that the current symbol can be. + * This at least produces text aligned within each function. + */ + symbol = dis_tgt_lookup(tgt, addr, &symoffset, 1, &symsize, + &isfunc); + /* Get the maximum length for this symbol */ + getsymname(addr, symbol, symsize, symbuf, sizeof (symbuf)); + symwidth = MAX(strlen(symbuf), MINSYMWIDTH); + + getsymname(addr, symbol, symoffset, symbuf, sizeof (symbuf)); + + /* + * If we've crossed a new function boundary, print out the + * function name on a blank line. + */ + if (!g_quiet && symoffset == 0 && symbol != NULL && isfunc) + (void) printf("%s()\n", symbol); + + (void) printf(" %s:%*s ", symbuf, + symwidth - strlen(symbuf), ""); + + /* print bytes */ + for (i = 0; i < MIN(bytesperline, (db.db_nextaddr - addr)); + i++) { + int byte = *((uchar_t *)data + (addr - db.db_addr) + i); + if (g_flags & DIS_OCTAL) + (void) printf("%03o ", byte); + else + (void) printf("%02x ", byte); + } + + /* trailing spaces for missing bytes */ + for (; i < bytesperline; i++) { + if (g_flags & DIS_OCTAL) + (void) printf(" "); + else + (void) printf(" "); + } + + /* contents of disassembly */ + (void) printf(" %s", buf); + + /* excess bytes that spill over onto subsequent lines */ + for (; i < db.db_nextaddr - addr; i++) { + int byte = *((uchar_t *)data + (addr - db.db_addr) + i); + if (i % bytesperline == 0) + (void) printf("\n %*s ", symwidth, ""); + if (g_flags & DIS_OCTAL) + (void) printf("%03o ", byte); + else + (void) printf("%02x ", byte); + } + + (void) printf("\n"); + + addr = db.db_nextaddr; + } +} + +/* + * libdisasm wrapper around symbol lookup. Invoke the target-specific lookup + * function, and convert the result using getsymname(). + */ +int +do_lookup(void *data, uint64_t addr, char *buf, size_t buflen, uint64_t *start, + size_t *symlen) +{ + dis_buffer_t *db = data; + const char *symbol; + off_t offset; + size_t size; + + /* + * If NULL symbol is returned, getsymname takes care of + * printing appropriate address in buf instead of symbol. + */ + symbol = dis_tgt_lookup(db->db_tgt, addr, &offset, 0, &size, NULL); + + if (buf != NULL) + getsymname(addr, symbol, offset, buf, buflen); + + if (start != NULL) + *start = addr - offset; + if (symlen != NULL) + *symlen = size; + + return (0); +} + +/* + * libdisasm wrapper around target reading. libdisasm will always read data + * in order, so update our current offset within the buffer appropriately. + * We only support reading from within the current object; libdisasm should + * never ask us to do otherwise. + */ +int +do_read(void *data, uint64_t addr, void *buf, size_t len) +{ + dis_buffer_t *db = data; + size_t offset; + + if (addr < db->db_addr || addr >= db->db_addr + db->db_size) + return (-1); + + offset = addr - db->db_addr; + len = MIN(len, db->db_size - offset); + + (void) memcpy(buf, (char *)db->db_data + offset, len); + + db->db_nextaddr = addr + len; + + return (len); +} + +/* + * Routine to dump raw data in a human-readable format. Used by the -d and -D + * options. We model our output after the xxd(1) program, which gives nicely + * formatted output, along with an ASCII translation of the result. + */ +void +dump_data(uint64_t addr, void *data, size_t datalen) +{ + uintptr_t curaddr = addr & (~0xf); + uint8_t *bytes = data; + int i; + int width; + + /* + * Determine if the address given to us fits in 32-bit range, in which + * case use a 4-byte width. + */ + if (((addr + datalen) & 0xffffffff00000000ULL) == 0ULL) + width = 8; + else + width = 16; + + while (curaddr < addr + datalen) { + /* + * Display leading address + */ + (void) printf("%0*x: ", width, curaddr); + + /* + * Print out data in two-byte chunks. If the current address + * is before the starting address or after the end of the + * section, print spaces. + */ + for (i = 0; i < 16; i++) { + if (curaddr + i < addr ||curaddr + i >= addr + datalen) + (void) printf(" "); + else + (void) printf("%02x", + bytes[curaddr + i - addr]); + + if (i & 1) + (void) printf(" "); + } + + (void) printf(" "); + + /* + * Print out the ASCII representation + */ + for (i = 0; i < 16; i++) { + if (curaddr + i < addr || + curaddr + i >= addr + datalen) { + (void) printf(" "); + } else { + uint8_t byte = bytes[curaddr + i - addr]; + if (isprint(byte)) + (void) printf("%c", byte); + else + (void) printf("."); + } + } + + (void) printf("\n"); + + curaddr += 16; + } +} + +/* + * Disassemble a section implicitly specified as part of a file. This function + * is called for all sections when no other flags are specified. We ignore any + * data sections, and print out only those sections containing text. + */ +void +dis_text_section(dis_tgt_t *tgt, dis_scn_t *scn, void *data) +{ + dis_handle_t *dhp = data; + + /* ignore data sections */ + if (!dis_section_istext(scn)) + return; + + if (!g_quiet) + (void) printf("\nsection %s\n", dis_section_name(scn)); + + dis_data(tgt, dhp, dis_section_addr(scn), dis_section_data(scn), + dis_section_size(scn)); +} + +/* + * Structure passed to dis_named_{section,function} which keeps track of both + * the target and the libdisasm handle. + */ +typedef struct callback_arg { + dis_tgt_t *ca_tgt; + dis_handle_t *ca_handle; +} callback_arg_t; + +/* + * Disassemble a section explicitly named with -s, -d, or -D. The 'type' + * argument contains the type of argument given. Pass the data onto the + * appropriate helper routine. + */ +void +dis_named_section(dis_scn_t *scn, int type, void *data) +{ + callback_arg_t *ca = data; + + if (!g_quiet) + (void) printf("\nsection %s\n", dis_section_name(scn)); + + switch (type) { + case DIS_DATA_RELATIVE: + dump_data(0, dis_section_data(scn), dis_section_size(scn)); + break; + case DIS_DATA_ABSOLUTE: + dump_data(dis_section_addr(scn), dis_section_data(scn), + dis_section_size(scn)); + break; + case DIS_TEXT: + dis_data(ca->ca_tgt, ca->ca_handle, dis_section_addr(scn), + dis_section_data(scn), dis_section_size(scn)); + break; + } +} + +/* + * Disassemble a function explicitly specified with '-F'. The 'type' argument + * is unused. + */ +/* ARGSUSED */ +void +dis_named_function(dis_func_t *func, int type, void *data) +{ + callback_arg_t *ca = data; + + dis_data(ca->ca_tgt, ca->ca_handle, dis_function_addr(func), + dis_function_data(func), dis_function_size(func)); +} + +/* + * Disassemble a complete file. First, we determine the type of the file based + * on the ELF machine type, and instantiate a version of the disassembler + * appropriate for the file. We then resolve any named sections or functions + * against the file, and iterate over the results (or all sections if no flags + * were specified). + */ +void +dis_file(const char *filename) +{ + dis_tgt_t *tgt, *current; + dis_scnlist_t *sections; + dis_funclist_t *functions; + dis_handle_t *dhp; + GElf_Ehdr ehdr; + + /* + * First, initialize the target + */ + if ((tgt = dis_tgt_create(filename)) == NULL) + return; + + if (!g_quiet) + (void) printf("disassembly for %s\n\n", filename); + + /* + * A given file may contain multiple targets (if it is an archive, for + * example). We iterate over all possible targets if this is the case. + */ + for (current = tgt; current != NULL; current = dis_tgt_next(current)) { + dis_tgt_ehdr(current, &ehdr); + + /* + * Eventually, this should probably live within libdisasm, and + * we should be able to disassemble targets from different + * architectures. For now, we only support objects as the + * native machine type. + */ + switch (ehdr.e_machine) { +#ifdef __sparc + case EM_SPARC: + if (ehdr.e_ident[EI_CLASS] != ELFCLASS32 || + ehdr.e_ident[EI_DATA] != ELFDATA2MSB) { + warn("invalid E_IDENT field for SPARC object"); + return; + } + g_flags |= DIS_SPARC_V8; + break; + + case EM_SPARC32PLUS: + if (ehdr.e_ident[EI_CLASS] != ELFCLASS32 || + ehdr.e_ident[EI_DATA] != ELFDATA2MSB) { + warn("invalid E_IDENT field for SPARC object"); + return; + } + + switch (ehdr.e_flags & EF_SPARC_32PLUS_MASK) { + case (EF_SPARC_32PLUS | EF_SPARC_SUN_US1 | + EF_SPARC_SUN_US3): + case (EF_SPARC_32PLUS | EF_SPARC_SUN_US1): + g_flags |= DIS_SPARC_V9 | DIS_SPARC_V9_SGI; + default: + g_flags |= DIS_SPARC_V9; + } + break; + + case EM_SPARCV9: + if (ehdr.e_ident[EI_CLASS] != ELFCLASS64 || + ehdr.e_ident[EI_DATA] != ELFDATA2MSB) { + warn("invalid E_IDENT field for SPARC object"); + return; + } + + g_flags |= DIS_SPARC_V9 | DIS_SPARC_V9_SGI; + break; +#endif /* __sparc */ + +#if defined(__i386) || defined(__amd64) + case EM_386: + g_flags |= DIS_X86_SIZE32; + break; + + case EM_AMD64: + g_flags |= DIS_X86_SIZE64; + break; +#endif /* __i386 || __amd64 */ + + default: + die("%s: unsupported ELF machine 0x%x", filename, + ehdr.e_machine); + } + + if (!g_quiet && dis_tgt_member(current) != NULL) + (void) printf("\narchive member %s\n", + dis_tgt_member(current)); + + /* + * Instantiate a libdisasm handle based on the file type. + */ + if ((dhp = dis_handle_create(g_flags, current, do_lookup, + do_read)) == NULL) + die("%s: failed to initialize disassembler: %s", + filename, dis_strerror(dis_errno())); + + if (g_doall) { + /* + * With no arguments, iterate over all sections and + * disassemble only those that contain text. + */ + dis_tgt_section_iter(current, dis_text_section, dhp); + } else { + callback_arg_t ca; + + ca.ca_tgt = current; + ca.ca_handle = dhp; + + /* + * If sections or functions were explicitly specified, + * resolve those names against the object, and iterate + * over just the resulting data. + */ + sections = dis_namelist_resolve_sections(g_seclist, + current); + functions = dis_namelist_resolve_functions(g_funclist, + current); + + dis_scnlist_iter(sections, dis_named_section, &ca); + dis_funclist_iter(functions, dis_named_function, &ca); + + dis_scnlist_destroy(sections); + dis_funclist_destroy(functions); + } + + dis_handle_destroy(dhp); + } + + dis_tgt_destroy(tgt); +} + +void +usage(void) +{ + (void) fprintf(stderr, "usage: dis [-CVoqn] [-d sec] \n"); + (void) fprintf(stderr, "\t[-D sec] [-F function] [-t sec] file ..\n"); + exit(2); +} + +typedef struct lib_node { + char *path; + struct lib_node *next; +} lib_node_t; + +int +main(int argc, char **argv) +{ + int optchar; + int i; + lib_node_t *libs = NULL; + + g_funclist = dis_namelist_create(); + g_seclist = dis_namelist_create(); + + while ((optchar = getopt(argc, argv, "Cd:D:F:l:Lot:Vqn")) != -1) { + switch (optchar) { + case 'C': + g_demangle = 1; + break; + case 'd': + dis_namelist_add(g_seclist, optarg, DIS_DATA_RELATIVE); + break; + case 'D': + dis_namelist_add(g_seclist, optarg, DIS_DATA_ABSOLUTE); + break; + case 'F': + dis_namelist_add(g_funclist, optarg, 0); + break; + case 'l': { + /* + * The '-l foo' option historically would attempt to + * disassemble '$LIBDIR/libfoo.a'. The $LIBDIR + * environment variable has never been supported or + * documented for our linker. However, until this + * option is formally EOLed, we have to support it. + */ + char *dir; + lib_node_t *node; + size_t len; + + if ((dir = getenv("LIBDIR")) == NULL || + dir[0] == '\0') + dir = "/usr/lib"; + node = safe_malloc(sizeof (lib_node_t)); + len = strlen(optarg) + strlen(dir) + sizeof ("/lib.a"); + node->path = safe_malloc(len); + + (void) snprintf(node->path, len, "%s/lib%s.a", dir, + optarg); + node->next = libs; + libs = node; + break; + } + case 'L': + /* + * The '-L' option historically would attempt to read + * the .debug section of the target to determine source + * line information in order to annotate the output. + * No compiler has emitted these sections in many years, + * and the option has never done what it purported to + * do. We silently consume the option for + * compatibility. + */ + break; + case 'n': + g_numeric = 1; + break; + case 'o': + g_flags |= DIS_OCTAL; + break; + case 'q': + g_quiet = 1; + break; + case 't': + dis_namelist_add(g_seclist, optarg, DIS_TEXT); + break; + case 'V': + (void) printf("Solaris disassembler version 1.0\n"); + return (0); + default: + usage(); + break; + } + } + + argc -= optind; + argv += optind; + + if (argc == 0 && libs == NULL) { + warn("no objects specified"); + usage(); + } + + if (dis_namelist_empty(g_funclist) && dis_namelist_empty(g_seclist)) + g_doall = 1; + + /* + * See comment for 'l' option, above. + */ + while (libs != NULL) { + lib_node_t *node = libs->next; + + dis_file(libs->path); + free(libs->path); + free(libs); + libs = node; + } + + for (i = 0; i < argc; i++) + dis_file(argv[i]); + + dis_namelist_destroy(g_funclist); + dis_namelist_destroy(g_seclist); + + return (g_error); +} diff --git a/usr/src/cmd/dis/dis_target.c b/usr/src/cmd/dis/dis_target.c new file mode 100644 index 0000000000..7ef0c46060 --- /dev/null +++ b/usr/src/cmd/dis/dis_target.c @@ -0,0 +1,825 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <gelf.h> +#include <libelf.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/fcntl.h> +#include <sys/stat.h> + +#include "dis_target.h" +#include "dis_util.h" + +/* + * Standard ELF disassembler target. + * + * We only support disassembly of ELF files, though this target interface could + * be extended in the future. Each basic type (target, func, section) contains + * enough information to uniquely identify the location within the file. The + * interfaces use libelf(3LIB) to do the actual processing of the file. + */ + +/* + * Symbol table entry type. We maintain our own symbol table sorted by address, + * with the symbol name already resolved against the ELF symbol table. + */ +typedef struct sym_entry { + GElf_Sym se_sym; /* value of symbol */ + char *se_name; /* name of symbol */ + int se_shndx; /* section where symbol is located */ +} sym_entry_t; + +/* + * Target data structure. This structure keeps track of the ELF file + * information, a few bits of pre-processed section index information, and + * sorted versions of the symbol table. We also keep track of the last symbol + * looked up, as the majority of lookups remain within the same symbol. + */ +struct dis_tgt { + Elf *dt_elf; /* libelf handle */ + Elf *dt_elf_root; /* main libelf handle (for archives) */ + const char *dt_filename; /* name of file */ + int dt_fd; /* underlying file descriptor */ + size_t dt_shstrndx; /* section index of .shstrtab */ + size_t dt_symidx; /* section index of symbol table */ + sym_entry_t *dt_symcache; /* last symbol looked up */ + sym_entry_t *dt_symtab; /* sorted symbol table */ + int dt_symcount; /* # of symbol table entries */ + struct dis_tgt *dt_next; /* next target (for archives) */ + Elf_Arhdr *dt_arhdr; /* archive header (for archives) */ +}; + +/* + * Function data structure. We resolve the symbol and lookup the associated ELF + * data when building this structure. The offset is calculated based on the + * section's starting address. + */ +struct dis_func { + sym_entry_t *df_sym; /* symbol table reference */ + Elf_Data *df_data; /* associated ELF data */ + size_t df_offset; /* offset within data */ +}; + +/* + * Section data structure. We store the entire section header so that we can + * determine some properties (such as whether or not it contains text) after + * building the structure. + */ +struct dis_scn { + GElf_Shdr ds_shdr; + const char *ds_name; + Elf_Data *ds_data; +}; + +/* Lifted from Psymtab.c */ +#define DATA_TYPES \ + ((1 << STT_OBJECT) | (1 << STT_FUNC) | \ + (1 << STT_COMMON) | (1 << STT_TLS)) +#define IS_DATA_TYPE(tp) (((1 << (tp)) & DATA_TYPES) != 0) + +/* + * Pick out the best symbol to used based on the sections available in the + * target. We prefer SHT_SYMTAB over SHT_DYNSYM. + */ +/* ARGSUSED */ +static void +get_symtab(dis_tgt_t *tgt, dis_scn_t *scn, void *data) +{ + int *index = data; + + *index += 1; + + /* + * Prefer SHT_SYMTAB over SHT_DYNSYM + */ + if (scn->ds_shdr.sh_type == SHT_DYNSYM && tgt->dt_symidx == 0) + tgt->dt_symidx = *index; + else if (scn->ds_shdr.sh_type == SHT_SYMTAB) + tgt->dt_symidx = *index; +} + +static int +sym_compare(const void *a, const void *b) +{ + const sym_entry_t *syma = a; + const sym_entry_t *symb = b; + const char *aname = syma->se_name; + const char *bname = symb->se_name; + + if (syma->se_sym.st_value < symb->se_sym.st_value) + return (-1); + + if (syma->se_sym.st_value > symb->se_sym.st_value) + return (1); + + /* + * Prefer functions over non-functions + */ + if (GELF_ST_TYPE(syma->se_sym.st_info) != + GELF_ST_TYPE(symb->se_sym.st_info)) { + if (GELF_ST_TYPE(syma->se_sym.st_info) == STT_FUNC) + return (-1); + if (GELF_ST_TYPE(symb->se_sym.st_info) == STT_FUNC) + return (1); + } + + /* + * For symbols with the same address and type, we sort them according to + * a hierarchy: + * + * 1. weak symbols (common name) + * 2. global symbols (external name) + * 3. local symbols + */ + if (GELF_ST_BIND(syma->se_sym.st_info) != + GELF_ST_BIND(symb->se_sym.st_info)) { + if (GELF_ST_BIND(syma->se_sym.st_info) == STB_WEAK) + return (-1); + if (GELF_ST_BIND(symb->se_sym.st_info) == STB_WEAK) + return (1); + + if (GELF_ST_BIND(syma->se_sym.st_info) == STB_GLOBAL) + return (-1); + if (GELF_ST_BIND(symb->se_sym.st_info) == STB_GLOBAL) + return (1); + } + + /* + * As a last resort, if we have multiple symbols of the same type at the + * same address, prefer the version with the fewest leading underscores. + */ + if (aname == NULL) + return (-1); + if (bname == NULL) + return (1); + + while (*aname == '_' && *bname == '_') { + aname++; + bname++; + } + + if (*bname == '_') + return (-1); + if (*aname == '_') + return (1); + + /* + * Prefer the symbol with the smaller size. + */ + if (syma->se_sym.st_size < symb->se_sym.st_size) + return (-1); + if (syma->se_sym.st_size > symb->se_sym.st_size) + return (1); + + /* + * We really do have two identical symbols for some reason. Just report + * them as equal, and to the lucky one go the spoils. + */ + return (0); +} + +/* + * Construct an optimized symbol table sorted by starting address. + */ +static void +construct_symtab(dis_tgt_t *tgt) +{ + Elf_Scn *scn; + GElf_Shdr shdr; + Elf_Data *symdata; + int i; + GElf_Word *symshndx = NULL; + int symshndx_size; + sym_entry_t *sym; + sym_entry_t *p_symtab = NULL; + int nsym = 0; /* count of symbols we're not interested in */ + + /* + * Find the symshndx section, if any + */ + for (scn = elf_nextscn(tgt->dt_elf, NULL); scn != NULL; + scn = elf_nextscn(tgt->dt_elf, scn)) { + if (gelf_getshdr(scn, &shdr) == NULL) + break; + if (shdr.sh_type == SHT_SYMTAB_SHNDX && + shdr.sh_link == tgt->dt_symidx) { + Elf_Data *data; + + if ((data = elf_getdata(scn, NULL)) != NULL) { + symshndx = (GElf_Word *)data->d_buf; + symshndx_size = data->d_size / + sizeof (GElf_Word); + break; + } + } + } + + if ((scn = elf_getscn(tgt->dt_elf, tgt->dt_symidx)) == NULL) + die("%s: failed to get section information", tgt->dt_filename); + if (gelf_getshdr(scn, &shdr) == NULL) + die("%s: failed to get section header", tgt->dt_filename); + if (shdr.sh_entsize == 0) + die("%s: symbol table has zero size", tgt->dt_filename); + + if ((symdata = elf_getdata(scn, NULL)) == NULL) + die("%s: failed to get symbol table", tgt->dt_filename); + + tgt->dt_symcount = symdata->d_size / gelf_fsize(tgt->dt_elf, ELF_T_SYM, + 1, EV_CURRENT); + + p_symtab = safe_malloc(tgt->dt_symcount * sizeof (sym_entry_t)); + + for (i = 0, sym = p_symtab; i < tgt->dt_symcount; i++) { + (void) memset(sym, sizeof (sym_entry_t), 0); + if (gelf_getsym(symdata, i, &(sym->se_sym)) == NULL) { + warn("%s: gelf_getsym returned NULL for %d", + tgt->dt_filename, i); + nsym++; + continue; + } + + /* + * We're only interested in data symbols. + */ + if (!IS_DATA_TYPE(GELF_ST_TYPE(sym->se_sym.st_info))) { + nsym++; + continue; + } + + if (sym->se_sym.st_shndx == SHN_XINDEX && symshndx != NULL) { + if (i > symshndx_size) { + warn("%s: bad SHNX_XINDEX %d", + tgt->dt_filename, i); + sym->se_shndx = -1; + } else { + sym->se_shndx = symshndx[i]; + } + } else { + sym->se_shndx = sym->se_sym.st_shndx; + } + + if ((sym->se_name = elf_strptr(tgt->dt_elf, shdr.sh_link, + (size_t)sym->se_sym.st_name)) == NULL) { + warn("%s: failed to lookup symbol %d name", + tgt->dt_filename, i); + nsym++; + continue; + } + + sym++; + } + + tgt->dt_symcount -= nsym; + tgt->dt_symtab = realloc(p_symtab, + tgt->dt_symcount * sizeof (sym_entry_t)); + + qsort(tgt->dt_symtab, tgt->dt_symcount, sizeof (sym_entry_t), + sym_compare); +} + +/* + * Create a target backed by an ELF file. + */ +dis_tgt_t * +dis_tgt_create(const char *file) +{ + dis_tgt_t *tgt, *current; + int idx; + Elf *elf; + GElf_Ehdr ehdr; + Elf_Arhdr *arhdr = NULL; + int cmd; + + if (elf_version(EV_CURRENT) == EV_NONE) + die("libelf(3ELF) out of date"); + + tgt = safe_malloc(sizeof (dis_tgt_t)); + + if ((tgt->dt_fd = open(file, O_RDONLY)) < 0) { + warn("%s: failed opening file, reason: %s", file, + strerror(errno)); + free(tgt); + return (NULL); + } + + if ((tgt->dt_elf_root = + elf_begin(tgt->dt_fd, ELF_C_READ, NULL)) == NULL) { + warn("%s: invalid or corrupt ELF file", file); + dis_tgt_destroy(tgt); + return (NULL); + } + + current = tgt; + cmd = ELF_C_READ; + while ((elf = elf_begin(tgt->dt_fd, cmd, tgt->dt_elf_root)) != NULL) { + + if (elf_kind(tgt->dt_elf_root) == ELF_K_AR && + (arhdr = elf_getarhdr(elf)) == NULL) { + warn("%s: malformed archive", file); + dis_tgt_destroy(tgt); + return (NULL); + } + + /* + * Make sure that this Elf file is sane + */ + if (gelf_getehdr(elf, &ehdr) == NULL) { + if (arhdr != NULL) { + /* + * For archives, we drive on in the face of bad + * members. The "/" and "//" members are + * special, and should be silently ignored. + */ + if (strcmp(arhdr->ar_name, "/") != 0 && + strcmp(arhdr->ar_name, "//") != 0) + warn("%s[%s]: invalid file type", + file, arhdr->ar_name); + cmd = elf_next(elf); + (void) elf_end(elf); + continue; + } + + warn("%s: invalid file type", file); + dis_tgt_destroy(tgt); + return (NULL); + } + + /* + * If we're seeing a new Elf object, then we have an + * archive. In this case, we create a new target, and chain it + * off the master target. We can later iterate over these + * targets using dis_tgt_next(). + */ + if (current->dt_elf != NULL) { + dis_tgt_t *next = safe_malloc(sizeof (dis_tgt_t)); + next->dt_elf_root = tgt->dt_elf_root; + next->dt_fd = -1; + current->dt_next = next; + current = next; + } + current->dt_elf = elf; + current->dt_arhdr = arhdr; + + if (elf_getshstrndx(elf, ¤t->dt_shstrndx) == -1) { + warn("%s: failed to get section string table for " + "file", file); + dis_tgt_destroy(tgt); + return (NULL); + } + + idx = 0; + dis_tgt_section_iter(current, get_symtab, &idx); + + if (current->dt_symidx != 0) + construct_symtab(current); + + current->dt_filename = file; + + cmd = elf_next(elf); + } + + /* + * Final sanity check. If we had an archive with no members, then bail + * out with a nice message. + */ + if (tgt->dt_elf == NULL) { + warn("%s: empty archive\n", file); + dis_tgt_destroy(tgt); + return (NULL); + } + + return (tgt); +} + +/* + * Return the filename associated with the target. + */ +const char * +dis_tgt_name(dis_tgt_t *tgt) +{ + return (tgt->dt_filename); +} + +/* + * Return the archive member name, if any. + */ +const char * +dis_tgt_member(dis_tgt_t *tgt) +{ + if (tgt->dt_arhdr) + return (tgt->dt_arhdr->ar_name); + else + return (NULL); +} + +/* + * Return the Elf_Ehdr associated with this target. Needed to determine which + * disassembler to use. + */ +void +dis_tgt_ehdr(dis_tgt_t *tgt, GElf_Ehdr *ehdr) +{ + (void) gelf_getehdr(tgt->dt_elf, ehdr); +} + +/* + * Return the next target in the list, if this is an archive. + */ +dis_tgt_t * +dis_tgt_next(dis_tgt_t *tgt) +{ + return (tgt->dt_next); +} + +/* + * Destroy a target and free up any associated memory. + */ +void +dis_tgt_destroy(dis_tgt_t *tgt) +{ + dis_tgt_t *current, *next; + + current = tgt->dt_next; + while (current != NULL) { + next = current->dt_next; + if (current->dt_elf) + (void) elf_end(current->dt_elf); + if (current->dt_symtab) + free(current->dt_symtab); + free(current); + current = next; + } + + if (tgt->dt_elf) + (void) elf_end(tgt->dt_elf); + if (tgt->dt_elf_root) + (void) elf_end(tgt->dt_elf_root); + + if (tgt->dt_symtab) + free(tgt->dt_symtab); + + free(tgt); +} + +/* + * Given an address, returns the name of the corresponding symbol, as well as + * the offset within that symbol. If no matching symbol is found, then NULL is + * returned. + * + * If 'cache_result' is specified, then we keep track of the resulting symbol. + * This cached result is consulted first on subsequent lookups in order to avoid + * unecessary lookups. This flag should be used for resolving the current PC, + * as the majority of addresses stay within the current function. + */ +const char * +dis_tgt_lookup(dis_tgt_t *tgt, uint64_t addr, off_t *offset, int cache_result, + size_t *size, int *isfunc) +{ + int lo, hi, mid; + sym_entry_t *sym, *osym, *match; + int found; + + if (tgt->dt_symcache != NULL && + addr >= tgt->dt_symcache->se_sym.st_value && + addr < tgt->dt_symcache->se_sym.st_value + + tgt->dt_symcache->se_sym.st_size) { + *offset = addr - tgt->dt_symcache->se_sym.st_value; + *size = tgt->dt_symcache->se_sym.st_size; + return (tgt->dt_symcache->se_name); + } + + lo = 0; + hi = (tgt->dt_symcount - 1); + found = 0; + match = osym = NULL; + while (lo <= hi) { + mid = (lo + hi) / 2; + + sym = &tgt->dt_symtab[mid]; + + if (addr >= sym->se_sym.st_value && + addr < sym->se_sym.st_value + sym->se_sym.st_size && + (!found || sym->se_sym.st_value > osym->se_sym.st_value)) { + osym = sym; + found = 1; + } else if (addr == sym->se_sym.st_value) { + /* + * Particularly for .plt objects, it's possible to have + * a zero sized object. We want to return this, but we + * want it to be a last resort. + */ + match = sym; + } + + if (addr < sym->se_sym.st_value) + hi = mid - 1; + else + lo = mid + 1; + } + + if (!found) { + if (match) + osym = match; + else + return (NULL); + } + + /* + * Walk backwards to find the best match. + */ + do { + sym = osym; + + if (osym == tgt->dt_symtab) + break; + + osym = osym - 1; + } while ((sym->se_sym.st_value == osym->se_sym.st_value) && + (addr >= osym->se_sym.st_value) && + (addr < osym->se_sym.st_value + osym->se_sym.st_size)); + + if (cache_result) + tgt->dt_symcache = sym; + + *offset = addr - sym->se_sym.st_value; + *size = sym->se_sym.st_size; + if (isfunc) + *isfunc = (GELF_ST_TYPE(sym->se_sym.st_info) == STT_FUNC); + + return (sym->se_name); +} + +/* + * Given an address, return the starting offset of the next symbol in the file. + * Relies on the fact that this is only used when we encounter a bad instruction + * in the input stream, so we know that the last symbol looked up will be in the + * cache. + */ +off_t +dis_tgt_next_symbol(dis_tgt_t *tgt, uint64_t addr) +{ + sym_entry_t *sym = tgt->dt_symcache; + uint64_t start; + + /* make sure the cached symbol and address are valid */ + if (sym == NULL || addr < sym->se_sym.st_value || + addr >= sym->se_sym.st_value + sym->se_sym.st_size) + return (0); + + start = sym->se_sym.st_value; + + /* find the next symbol */ + while (sym != tgt->dt_symtab + tgt->dt_symcount && + sym->se_sym.st_value == start) + sym++; + + return (sym->se_sym.st_value - addr); +} + +/* + * Iterate over all sections in the target, executing the given callback for + * each. + */ +void +dis_tgt_section_iter(dis_tgt_t *tgt, section_iter_f func, void *data) +{ + dis_scn_t sdata; + Elf_Scn *scn; + int idx; + + for (scn = elf_nextscn(tgt->dt_elf, NULL), idx = 1; scn != NULL; + scn = elf_nextscn(tgt->dt_elf, scn), idx++) { + + if (gelf_getshdr(scn, &sdata.ds_shdr) == NULL) { + warn("%s: failed to get section %d header", + tgt->dt_filename, idx); + continue; + } + + if ((sdata.ds_name = elf_strptr(tgt->dt_elf, tgt->dt_shstrndx, + sdata.ds_shdr.sh_name)) == NULL) { + warn("%s: failed to get section %d name", + tgt->dt_filename, idx); + continue; + } + + if ((sdata.ds_data = elf_getdata(scn, NULL)) == NULL) { + warn("%s: failed to get data for section '%s'", + tgt->dt_filename, sdata.ds_name); + continue; + } + + func(tgt, &sdata, data); + } +} + +/* + * Return 1 if the given section contains text, 0 otherwise. + */ +int +dis_section_istext(dis_scn_t *scn) +{ + return ((scn->ds_shdr.sh_type == SHT_PROGBITS) && + (scn->ds_shdr.sh_flags == (SHF_ALLOC | SHF_EXECINSTR))); +} + +/* + * Return a pointer to the section data. + */ +void * +dis_section_data(dis_scn_t *scn) +{ + return (scn->ds_data->d_buf); +} + +/* + * Return the size of the section data. + */ +size_t +dis_section_size(dis_scn_t *scn) +{ + return (scn->ds_data->d_size); +} + +/* + * Return the address for the given section. + */ +uint64_t +dis_section_addr(dis_scn_t *scn) +{ + return (scn->ds_shdr.sh_addr); +} + +/* + * Return the name of the current section. + */ +const char * +dis_section_name(dis_scn_t *scn) +{ + return (scn->ds_name); +} + +/* + * Create an allocated copy of the given section + */ +dis_scn_t * +dis_section_copy(dis_scn_t *scn) +{ + dis_scn_t *new; + + new = safe_malloc(sizeof (dis_scn_t)); + (void) memcpy(new, scn, sizeof (dis_scn_t)); + + return (new); +} + +/* + * Free section memory + */ +void +dis_section_free(dis_scn_t *scn) +{ + free(scn); +} + +/* + * Iterate over all functions in the target, executing the given callback for + * each one. + */ +void +dis_tgt_function_iter(dis_tgt_t *tgt, function_iter_f func, void *data) +{ + int i; + sym_entry_t *sym; + dis_func_t df; + Elf_Scn *scn; + GElf_Shdr shdr; + + for (i = 0, sym = tgt->dt_symtab; i < tgt->dt_symcount; i++, sym++) { + + /* ignore non-functions */ + if ((GELF_ST_TYPE(sym->se_sym.st_info) != STT_FUNC) || + sym->se_name == NULL || + sym->se_sym.st_size == 0 || + sym->se_shndx == -1) + continue; + + /* get the ELF data associated with this function */ + if ((scn = elf_getscn(tgt->dt_elf, sym->se_shndx)) == NULL || + gelf_getshdr(scn, &shdr) == NULL || + (df.df_data = elf_getdata(scn, NULL)) == NULL || + df.df_data->d_size == 0) { + warn("%s: failed to read section %d", + tgt->dt_filename, sym->se_shndx); + continue; + } + + /* + * Verify that the address lies within the section that we think + * it does. + */ + if (sym->se_sym.st_value < shdr.sh_addr || + (sym->se_sym.st_value + sym->se_sym.st_size) > + (shdr.sh_addr + shdr.sh_size)) { + warn("%s: bad section %d for address %p", + tgt->dt_filename, sym->se_sym.st_shndx, + sym->se_sym.st_value); + continue; + } + + df.df_sym = sym; + df.df_offset = sym->se_sym.st_value - shdr.sh_addr; + + func(tgt, &df, data); + } +} + +/* + * Return the data associated with a given function. + */ +void * +dis_function_data(dis_func_t *func) +{ + return ((char *)func->df_data->d_buf + func->df_offset); +} + +/* + * Return the size of a function. + */ +size_t +dis_function_size(dis_func_t *func) +{ + return (func->df_sym->se_sym.st_size); +} + +/* + * Return the address of a function. + */ +uint64_t +dis_function_addr(dis_func_t *func) +{ + return (func->df_sym->se_sym.st_value); +} + +/* + * Return the name of the function + */ +const char * +dis_function_name(dis_func_t *func) +{ + return (func->df_sym->se_name); +} + +/* + * Return a copy of a function. + */ +dis_func_t * +dis_function_copy(dis_func_t *func) +{ + dis_func_t *new; + + new = safe_malloc(sizeof (dis_func_t)); + (void) memcpy(new, func, sizeof (dis_func_t)); + + return (new); +} + +/* + * Free function memory + */ +void +dis_function_free(dis_func_t *func) +{ + free(func); +} diff --git a/usr/src/cmd/dis/dis_target.h b/usr/src/cmd/dis/dis_target.h new file mode 100644 index 0000000000..a38914f8a4 --- /dev/null +++ b/usr/src/cmd/dis/dis_target.h @@ -0,0 +1,91 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _DIS_TARGET_H +#define _DIS_TARGET_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#include <gelf.h> +#include <sys/types.h> + +/* + * Basic types + */ +typedef struct dis_tgt dis_tgt_t; +typedef struct dis_func dis_func_t; +typedef struct dis_scn dis_scn_t; + +/* + * Target management + */ +dis_tgt_t *dis_tgt_create(const char *); +void dis_tgt_destroy(dis_tgt_t *); +const char *dis_tgt_lookup(dis_tgt_t *, uint64_t, off_t *, int, size_t *, + int *); +const char *dis_tgt_name(dis_tgt_t *); +const char *dis_tgt_member(dis_tgt_t *); +void dis_tgt_ehdr(dis_tgt_t *, GElf_Ehdr *); +off_t dis_tgt_next_symbol(dis_tgt_t *, uint64_t); +dis_tgt_t *dis_tgt_next(dis_tgt_t *); + +/* + * Section management + */ +typedef void (*section_iter_f)(dis_tgt_t *, dis_scn_t *, void *); +void dis_tgt_section_iter(dis_tgt_t *, section_iter_f, void *); + +int dis_section_istext(dis_scn_t *); +void *dis_section_data(dis_scn_t *); +size_t dis_section_size(dis_scn_t *); +uint64_t dis_section_addr(dis_scn_t *); +const char *dis_section_name(dis_scn_t *); +dis_scn_t *dis_section_copy(dis_scn_t *); +void dis_section_free(dis_scn_t *); + +/* + * Function management + */ +typedef void (*function_iter_f)(dis_tgt_t *, dis_func_t *, void *); +void dis_tgt_function_iter(dis_tgt_t *, function_iter_f, void *); +dis_func_t *dis_tgt_function_lookup(dis_tgt_t *, const char *); + +void *dis_function_data(dis_func_t *); +size_t dis_function_size(dis_func_t *); +uint64_t dis_function_addr(dis_func_t *); +const char *dis_function_name(dis_func_t *); +dis_func_t *dis_function_copy(dis_func_t *); +void dis_function_free(dis_func_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _DIS_TARGET_H */ diff --git a/usr/src/cmd/dis/dis_util.c b/usr/src/cmd/dis/dis_util.c new file mode 100644 index 0000000000..816c41394c --- /dev/null +++ b/usr/src/cmd/dis/dis_util.c @@ -0,0 +1,147 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <dlfcn.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <demangle.h> + +#include "dis_util.h" + +int g_error; /* global process exit status, set when warn() is called */ + +/* + * Fatal error. Print out the error with a leading "dis: ", and then exit the + * program. + */ +void +die(const char *fmt, ...) +{ + va_list ap; + + (void) fprintf(stderr, "dis: fatal: "); + + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + + (void) fprintf(stderr, "\n"); + + exit(1); +} + +/* + * Non-fatal error. Print out the error with a leading "dis: ", set the global + * error flag, and return. + */ +void +warn(const char *fmt, ...) +{ + va_list ap; + + (void) fprintf(stderr, "dis: warning: "); + + va_start(ap, fmt); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + + (void) fprintf(stderr, "\n"); + + g_error = 1; +} + +/* + * Convenience wrapper around malloc() to cleanly exit if any allocation fails. + */ +void * +safe_malloc(size_t size) +{ + void *ret; + + if ((ret = calloc(1, size)) == NULL) + die("Out of memory"); + + return (ret); +} + + +/* + * Generic interface to demangle C++ names. Calls cplus_demangle to do the + * necessary translation. If the translation fails, the argument is returned + * unchanged. The memory returned is only valid until the next call to + * demangle(). + * + * We dlopen() libdemangle.so rather than linking directly against it in case it + * is not installed on the system. + */ +const char * +dis_demangle(const char *name) +{ + static char *demangled_name; + static int (*demangle_func)() = NULL; + static int size = BUFSIZE; + static int first_flag = 0; + int ret; + + /* + * If this is the first call, allocate storage + * for the buffer. + */ + if (first_flag == 0) { + void *demangle_hand; + + demangle_hand = dlopen("libdemangle.so.1", RTLD_LAZY); + if (demangle_hand != NULL) + demangle_func = (int (*)(int))dlsym( + demangle_hand, "cplus_demangle"); + + demangled_name = safe_malloc(size); + first_flag = 1; + } + + /* + * If libdemangle is not present, pass through unchanged. + */ + if (demangle_func == NULL) + return (name); + + /* + * The function returns -1 when the buffer size is not sufficient. + */ + while ((ret = (*demangle_func)(name, demangled_name, size)) == -1) { + free(demangled_name); + size = size + BUFSIZE; + demangled_name = safe_malloc(size); + } + + if (ret != 0) + return (name); + + return (demangled_name); +} diff --git a/usr/src/cmd/mdb/intel/mdb/dis.h b/usr/src/cmd/dis/dis_util.h index 69017fc98a..e3506c9cab 100644 --- a/usr/src/cmd/mdb/intel/mdb/dis.h +++ b/usr/src/cmd/dis/dis_util.h @@ -2,9 +2,8 @@ * 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. + * 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 * or http://www.opensolaris.org/os/licensing. @@ -19,45 +18,35 @@ * * CDDL HEADER END */ + /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -/* Copyright (c) 1988 AT&T */ -/* All Rights Reserved */ - - -#ifndef _DIS_H -#define _DIS_H +#ifndef _DIS_UTIL_H +#define _DIS_UTIL_H #pragma ident "%Z%%M% %I% %E% SMI" -#ifdef __cplusplus +#include <sys/types.h> + +#ifdef __cplusplus extern "C" { #endif -#include <string.h> -#include <dis_tables.h> +void die(const char *, ...); +void warn(const char *, ...); -#include <mdb/mdb_disasm_impl.h> -#include <mdb/mdb_err.h> -#include <mdb/mdb_io.h> -#include <mdb/mdb.h> +void *safe_malloc(size_t); +const char *dis_demangle(const char *); -#define NHEX 40 /* max # chars in object per line */ -#define NLINE 1024 /* max # chars in mnemonic per line */ -#define TRUE 1 -#define FALSE 0 -#define LEAD 1 -#define NOLEAD 0 -#define NOLEADSHORT 2 +int g_error; -#define DIS_IA32 0 -#define DIS_AMD64 1 +#define BUFSIZE 1024 -#ifdef __cplusplus +#ifdef __cplusplus } #endif -#endif /* _DIS_H */ +#endif /* _DIS_UTIL_H */ diff --git a/usr/src/cmd/mdb/Makefile.mdb b/usr/src/cmd/mdb/Makefile.mdb index 659ae17803..6757821ff2 100644 --- a/usr/src/cmd/mdb/Makefile.mdb +++ b/usr/src/cmd/mdb/Makefile.mdb @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -85,7 +84,7 @@ SRCS += mdb.c \ $(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG CPPFLAGS += -D_MDB -I. -I../.. -I../../../common -LDLIBS += -ltermcap -lkvm -lproc -lrtld_db -lctf -lumem \ +LDLIBS += -ltermcap -lkvm -lproc -lrtld_db -lctf -lumem -ldisasm \ $(ZLAZYLOAD) -lscf $(ZNOLAZYLOAD) LINTFLAGS += -n -errtags=yes diff --git a/usr/src/cmd/mdb/Makefile.module b/usr/src/cmd/mdb/Makefile.module index d672aef15e..f901671ab0 100644 --- a/usr/src/cmd/mdb/Makefile.module +++ b/usr/src/cmd/mdb/Makefile.module @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -66,10 +65,6 @@ TARGETS_kvm_kmdb = $(KMODFILE) TARGETS_kvm_mdb = $(MODFILE) TARGETS_kvm_both = $(TARGETS_kvm_mdb) $(TARGETS_kvm_kmdb) TARGETS_kvm = $(TARGETS_kvm_$(TARGETS_kvm_type)) -TARGETS_disasm_kmdb = $(KMODFILE) -TARGETS_disasm_mdb = $(MODFILE) -TARGETS_disasm_both = $(TARGETS_disasm_mdb) $(TARGETS_disasm_kmdb) -TARGETS_disasm = $(TARGETS_disasm_$(TARGETS_kvm_type)) TARGETS_proc = $(MODFILE) TARGETS_raw = $(MODFILE) TARGETS = $(TARGETS_$(MDBTGT)) @@ -80,10 +75,6 @@ ROOTTGTS_kvm_kmdb = $(ROOTKMOD)/$(KMODULE) ROOTTGTS_kvm_mdb = $(ROOTMOD)/$(MODULE) ROOTTGTS_kvm_both = $(ROOTTGTS_kvm_mdb) $(ROOTTGTS_kvm_kmdb) ROOTTGTS_kvm = $(ROOTTGTS_kvm_$(ROOTTGTS_kvm_type)) -ROOTTGTS_disasm_kmdb = $(ROOTKMOD)/$(KMODULE) -ROOTTGTS_disasm_mdb = $(ROOTMOD)/$(MODULE) -ROOTTGTS_disasm_both = $(ROOTTGTS_disasm_mdb) $(ROOTTGTS_disasm_kmdb) -ROOTTGTS_disasm = $(ROOTTGTS_disasm_$(TARGETS_kvm_type)) ROOTTGTS_proc = $(ROOTMOD)/$(MODULE) ROOTTGTS_raw = $(ROOTMOD)/$(MODULE) ROOTTGTS = $(ROOTTGTS_$(MDBTGT)) @@ -96,9 +87,6 @@ LINTFILES_kvm_type = $(TARGETS_kvm_type) LINTFILES_kvm_both = $(KLINTOBJS) $(LINTOBJS) LINTFILES_kvm_mdb = $(LINTOBJS) LINTFILES_kvm = $(LINTFILES_kvm_$(LINTFILES_kvm_type)) -LINTFILES_disasm_both = $(KLINTOBJS) $(LINTOBJS) -LINTFILES_disasm_mdb = $(LINTOBJS) -LINTFILES_disasm = $(LINTFILES_disasm_$(TARGETS_kvm_type)) LINTFILES_proc = $(LINTOBJS) LINTFILES_raw = $(LINTOBJS) LINTFILES = $(LINTFILES_$(MDBTGT)) @@ -177,7 +165,8 @@ $(MODFILE): dmod .WAIT $(MODOBJS) LINKTESTOBJ = $(KMDBDIR)/kmdb_modlinktest.o KMDB_LINKTEST = \ - $(LD) -zdefs -dy -r -o $@.linktest $(KMODOBJS) $(LINKTESTOBJ) && \ + $(LD) $(ZDEFS) -dy -r -o $@.linktest $(KMODOBJS) \ + $(STANDOBJS) $(LINKTESTOBJ) && \ $(RM) $@.linktest KMDB_LINKTEST_ENABLE=$(POUND_SIGN) @@ -189,7 +178,8 @@ $(KMDB_LINKTEST_ENABLE)KMDB_LINKTEST_CMD = $(KMDB_LINKTEST) KMDB_FPTEST_CMD = $(KMDB_FPTEST) $(KMODFILE): kmod .WAIT $(KMODOBJS) $(MAPFILE) - $(LD) -dy -r $(MAPFILE:%=-M%) -Nmisc/kmdbmod -o $@ $(KMODOBJS) + $(LD) -dy -r $(MAPFILE:%=-M%) -Nmisc/kmdbmod -o $@ $(KMODOBJS) \ + $(STANDOBJS) $(KMDB_LINKTEST_CMD) $(KMDB_FPTEST_CMD) $(CTFMERGE) -f -L VERSION -o $@ $(KMODOBJS) @@ -199,7 +189,7 @@ linktest: linktest_check .WAIT kmod .WAIT $(KMODOBJS) $(KMDB_LINKTEST) linktest_check: - @if [ "$(MDBTGT)" != "kvm" ] && [ "$(MDBTGT)" != "disasm" ] ; then \ + @if [ "$(MDBTGT)" != "kvm" ] ; then \ echo "ERROR: linktest is not supported non-kvm/disasm dmods" \ >&2 ; \ exit 1 ; \ diff --git a/usr/src/cmd/mdb/common/kmdb/kmdb_create.c b/usr/src/cmd/mdb/common/kmdb/kmdb_create.c index ec2765ba27..0059efe278 100644 --- a/usr/src/cmd/mdb/common/kmdb/kmdb_create.c +++ b/usr/src/cmd/mdb/common/kmdb/kmdb_create.c @@ -2,9 +2,8 @@ * 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. + * 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 * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -40,7 +39,4 @@ mdb_create_builtin_tgts(void) void mdb_create_loadable_disasms(void) { -#ifdef __sparc - (void) mdb_module_load("sparc", MDB_MOD_SILENT | MDB_MOD_DEFER); -#endif } diff --git a/usr/src/cmd/mdb/common/kmdb/kmdb_stubs.c b/usr/src/cmd/mdb/common/kmdb/kmdb_stubs.c index d536f75718..7919f8b707 100644 --- a/usr/src/cmd/mdb/common/kmdb/kmdb_stubs.c +++ b/usr/src/cmd/mdb/common/kmdb/kmdb_stubs.c @@ -2,9 +2,8 @@ * 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. + * 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 * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +33,7 @@ #include <unistd.h> #include <libproc.h> #include <sys/time.h> +#include <sys/utsname.h> #include <kmdb/kmdb_dpi.h> #include <kmdb/kmdb_promif.h> @@ -180,3 +180,12 @@ exit(int status) kmdb_dpi_reboot(); #endif } + +#if defined(__i386) && !defined(__amd64) +/*ARGSUSED*/ +int +_nuname(struct utsname *buf) +{ + return (-1); +} +#endif diff --git a/usr/src/cmd/mdb/common/kmdb/mapfile_skel b/usr/src/cmd/mdb/common/kmdb/mapfile_skel index f8f70ddd01..4934da25df 100644 --- a/usr/src/cmd/mdb/common/kmdb/mapfile_skel +++ b/usr/src/cmd/mdb/common/kmdb/mapfile_skel @@ -2,9 +2,8 @@ * 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. + * 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 * or http://www.opensolaris.org/os/licensing. @@ -21,7 +20,7 @@ */ /* BEGIN PROLOGUE */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -46,6 +45,11 @@ /* There should be only one - ours */ errno; + /* <sys/utsname.h> implictly references this on x86 */ +#if defined(__i386) && !defined(__amd64) + _nuname; +#endif + mdb_tgt_aread; mdb_dis_create; mdb_dis_destroy; diff --git a/usr/src/cmd/mdb/common/mdb/mdb_disasm.c b/usr/src/cmd/mdb/common/mdb/mdb_disasm.c index dd95cc9932..ca1517e047 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_disasm.c +++ b/usr/src/cmd/mdb/common/mdb/mdb_disasm.c @@ -2,9 +2,8 @@ * 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. + * 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 * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +33,8 @@ #include <mdb/mdb_nv.h> #include <mdb/mdb.h> +#include <libdisasm.h> + int mdb_dis_select(const char *name) { @@ -174,6 +175,304 @@ cmd_disasms(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) return (DCMD_OK); } +/* + * Generic libdisasm disassembler interfaces. + */ + +#define DISBUFSZ 64 + +/* + * Internal structure used by the read and lookup routines. + */ +typedef struct dis_buf { + mdb_tgt_t *db_tgt; + mdb_tgt_as_t db_as; + mdb_tgt_addr_t db_addr; + mdb_tgt_addr_t db_nextaddr; + uchar_t db_buf[DISBUFSZ]; + ssize_t db_bufsize; +} dis_buf_t; + +/* + * Disassembler support routine for lookup up an address. Rely on mdb's "%a" + * qualifier to convert the address to a symbol. + */ +/*ARGSUSED*/ +static int +libdisasm_lookup(void *data, uint64_t addr, char *buf, size_t buflen, + uint64_t *start, size_t *len) +{ + if (buf != NULL) { + GElf_Sym sym; + +#ifdef __sparc + uint32_t instr[3]; + uint32_t dtrace_id; + + /* + * On SPARC, DTrace FBT trampoline entries have a sethi/or pair + * that indicates the dtrace probe id; this may appear as the + * first two instructions or one instruction into the + * trampoline. + */ + if (mdb_vread(instr, sizeof (instr), (uintptr_t)addr) == + sizeof (instr)) { + if ((instr[0] & 0xfffc0000) == 0x11000000 && + (instr[1] & 0xffffe000) == 0x90122000) { + dtrace_id = (instr[0] << 10) | + (instr[1] & 0x1fff); + (void) mdb_snprintf(buf, sizeof (buf), "dt=%#x", + dtrace_id); + goto out; + } else if ((instr[1] & 0xfffc0000) == 0x11000000 && + (instr[2] & 0xffffe000) == 0x90122000) { + dtrace_id = (instr[1] << 10) | + (instr[2] & 0x1fff); + (void) mdb_snprintf(buf, sizeof (buf), "dt=%#x", + dtrace_id); + goto out; + } + } +#endif + if (mdb_lookup_by_addr((uintptr_t)addr, MDB_SYM_FUZZY, + buf, buflen, &sym) < 0) { + if (buflen > 0) + *buf = '\0'; + return (-1); + } + } + +#ifdef __sparc +out: +#endif + if (start != NULL || len != NULL) { + GElf_Sym sym; + char c; + + if (mdb_lookup_by_addr(addr, MDB_SYM_FUZZY, &c, 1, &sym) < 0) + return (-1); + + if (start != NULL) + *start = sym.st_value; + if (len != NULL) + *len = sym.st_size; + } + + return (0); +} + +/* + * Disassembler support routine for reading from the target. Rather than having + * to read one byte at a time, we read from the address space in chunks. If the + * current address doesn't lie within our buffer range, we read in the chunk + * starting from the given address. + */ +static int +libdisasm_read(void *data, uint64_t pc, void *buf, size_t buflen) +{ + dis_buf_t *db = data; + size_t offset; + size_t len; + + if (pc - db->db_addr >= db->db_bufsize) { + if ((db->db_bufsize = mdb_tgt_aread(db->db_tgt, db->db_as, + db->db_buf, sizeof (db->db_buf), pc)) == -1) + return (-1); + db->db_addr = pc; + } + + offset = pc - db->db_addr; + + len = MIN(buflen, db->db_bufsize - offset); + + memcpy(buf, (char *)db->db_buf + offset, len); + db->db_nextaddr = pc + len; + + return (len); +} + +static mdb_tgt_addr_t +libdisasm_ins2str(mdb_disasm_t *dp, mdb_tgt_t *t, mdb_tgt_as_t as, + char *buf, size_t len, mdb_tgt_addr_t pc) +{ + dis_handle_t *dhp = dp->dis_data; + dis_buf_t db = { 0 }; + + /* + * Set the libdisasm data to point to our buffer. This will be + * passed as the first argument to the lookup and read functions. + */ + db.db_tgt = t; + db.db_as = as; + + dis_set_data(dhp, &db); + + /* + * Attempt to disassemble the instruction + */ + if (dis_disassemble(dhp, pc, buf, len) != 0) + (void) mdb_snprintf(buf, len, + "***ERROR--unknown op code***"); + + /* + * Return the updated location + */ + return (db.db_nextaddr); +} + +static mdb_tgt_addr_t +libdisasm_previns(mdb_disasm_t *dp, mdb_tgt_t *t, mdb_tgt_as_t as, + mdb_tgt_addr_t pc, uint_t n) +{ + dis_handle_t *dhp = dp->dis_data; + dis_buf_t db = { 0 }; + + /* + * Set the libdisasm data to point to our buffer. This will be + * passed as the first argument to the lookup and read functions. + */ + db.db_tgt = t; + db.db_as = as; + + dis_set_data(dhp, &db); + + return (dis_previnstr(dhp, pc, n)); +} + +/*ARGSUSED*/ +static mdb_tgt_addr_t +libdisasm_nextins(mdb_disasm_t *dp, mdb_tgt_t *t, mdb_tgt_as_t as, + mdb_tgt_addr_t pc) +{ + mdb_tgt_addr_t npc; + char c; + + if ((npc = libdisasm_ins2str(dp, t, as, &c, 1, pc)) == pc) + return (pc); + + /* + * Probe the address to make sure we can read something from it - we + * want the address we return to actually contain something. + */ + if (mdb_tgt_aread(t, as, &c, 1, npc) != 1) + return (pc); + + return (npc); +} + +static void +libdisasm_destroy(mdb_disasm_t *dp) +{ + dis_handle_t *dhp = dp->dis_data; + + dis_handle_destroy(dhp); +} + +static const mdb_dis_ops_t libdisasm_ops = { + libdisasm_destroy, + libdisasm_ins2str, + libdisasm_previns, + libdisasm_nextins +}; + +/* + * Generic function for creating a libdisasm-backed disassembler. Creates an + * MDB disassembler with the given name backed by libdis with the given flags. + */ +static int +libdisasm_create(mdb_disasm_t *dp, const char *name, + const char *desc, int flags) +{ + if ((dp->dis_data = dis_handle_create(flags, NULL, libdisasm_lookup, + libdisasm_read)) == NULL) + return (-1); + + dp->dis_name = name; + dp->dis_ops = &libdisasm_ops; + dp->dis_desc = desc; + + return (0); +} + + +#if defined(__i386) || defined(__amd64) +static int +ia32_create(mdb_disasm_t *dp) +{ + return (libdisasm_create(dp, + "ia32", + "Intel 32-bit disassembler", + DIS_X86_SIZE32)); +} +#endif + +#if defined(__amd64) +static int +amd64_create(mdb_disasm_t *dp) +{ + return (libdisasm_create(dp, + "amd64", + "AMD64 and IA32e 64-bit disassembler", + DIS_X86_SIZE64)); +} +#endif + +#if defined(__sparc) +static int +sparc1_create(mdb_disasm_t *dp) +{ + return (libdisasm_create(dp, + "1", + "SPARC-v8 disassembler", + DIS_SPARC_V8)); +} + +static int +sparc2_create(mdb_disasm_t *dp) +{ + return (libdisasm_create(dp, + "2", + "SPARC-v9 disassembler", + DIS_SPARC_V9)); +} + +static int +sparc4_create(mdb_disasm_t *dp) +{ + return (libdisasm_create(dp, + "4", + "UltraSPARC1-v9 disassembler", + DIS_SPARC_V9 | DIS_SPARC_V9_SGI)); +} + +static int +sparcv8_create(mdb_disasm_t *dp) +{ + return (libdisasm_create(dp, + "v8", + "SPARC-v8 disassembler", + DIS_SPARC_V8)); +} + +static int +sparcv9_create(mdb_disasm_t *dp) +{ + return (libdisasm_create(dp, + "v9", + "SPARC-v9 disassembler", + DIS_SPARC_V9)); +} + +static int +sparcv9plus_create(mdb_disasm_t *dp) +{ + return (libdisasm_create(dp, + "v9plus", + "UltraSPARC1-v9 disassembler", + DIS_SPARC_V9 | DIS_SPARC_V9_SGI)); +} +#endif + /*ARGSUSED*/ static void defdis_destroy(mdb_disasm_t *dp) @@ -223,12 +522,19 @@ defdis_create(mdb_disasm_t *dp) } mdb_dis_ctor_f *const mdb_dis_builtins[] = { + defdis_create, #if defined(__amd64) ia32_create, amd64_create, #elif defined(__i386) ia32_create, +#elif defined(__sparc) + sparc1_create, + sparc2_create, + sparc4_create, + sparcv8_create, + sparcv9_create, + sparcv9plus_create, #endif - defdis_create, NULL }; diff --git a/usr/src/cmd/mdb/common/mdb/mdb_disasm_impl.h b/usr/src/cmd/mdb/common/mdb/mdb_disasm_impl.h index 9f68c5e165..3af2966cf5 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_disasm_impl.h +++ b/usr/src/cmd/mdb/common/mdb/mdb_disasm_impl.h @@ -2,9 +2,8 @@ * 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. + * 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 * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -63,24 +62,6 @@ struct mdb_disasm { void *dis_data; /* Private storage */ }; -#ifdef _MDB - -#if defined(__sparc) -extern mdb_dis_ctor_f sparc1_create; -extern mdb_dis_ctor_f sparc2_create; -extern mdb_dis_ctor_f sparc4_create; -extern mdb_dis_ctor_f sparcv8_create; -extern mdb_dis_ctor_f sparcv9_create; -extern mdb_dis_ctor_f sparcv9plus_create; -#else /* __i386 */ -extern mdb_dis_ctor_f ia32_create; -#if defined(__amd64) -extern mdb_dis_ctor_f amd64_create; -#endif /* __amd64 */ -#endif /* __sparc */ - -#endif /* _MDB */ - #ifdef __cplusplus } #endif diff --git a/usr/src/cmd/mdb/common/mdb/mdb_modapi.h b/usr/src/cmd/mdb/common/mdb/mdb_modapi.h index 4d9b8c8ce5..c6573f2afb 100644 --- a/usr/src/cmd/mdb/common/mdb/mdb_modapi.h +++ b/usr/src/cmd/mdb/common/mdb/mdb_modapi.h @@ -2,9 +2,8 @@ * 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. + * 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 * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -288,6 +287,7 @@ typedef void (*mdb_callback_f)(void *); extern void *mdb_callback_add(int, mdb_callback_f, void *); extern void mdb_callback_remove(void *); +extern size_t strlcat(char *, const char *, size_t); extern char *strcat(char *, const char *); extern char *strcpy(char *, const char *); extern char *strncpy(char *, const char *, size_t); diff --git a/usr/src/cmd/mdb/intel/Makefile.kmdb b/usr/src/cmd/mdb/intel/Makefile.kmdb index b1c9e3c9bd..67c6d7c92b 100644 --- a/usr/src/cmd/mdb/intel/Makefile.kmdb +++ b/usr/src/cmd/mdb/intel/Makefile.kmdb @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,10 +19,10 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" +#ident "%Z%%M% %I% %E% SMI" # PROMSRCS += \ @@ -34,9 +33,6 @@ PROMSRCS += \ prom_putchar.c KMDBSRCS += \ - bits.c \ - dis_tables.c \ - inteldis.c \ kaif.c \ kaif_activate.c \ kaif_idt.c \ @@ -60,7 +56,6 @@ KCTLSRCS += \ CTXOFFUSERS = \ kmdb_setcontext.o -OSINCDIRS += $(SRC)/common/dis/i386 CPPFLAGS += -DDIS_TEXT $(CTXOFFUSERS) $(CTXOFFUSERS:%.o=%.ln): kmdb_context_off.h @@ -86,16 +81,9 @@ MAPFILE_SOURCES = \ ../../kmdb/kmdb_dpi_isadep.h \ $(MAPFILE_SOURCES_$(MACH)) -%.o: $(SRC)/common/dis/i386/%.c - $(COMPILE.c) $< - $(CTFCONVERT_O) - %.o: ../../../../../uts/intel/promif/%.c $(COMPILE.c) $< $(CTFCONVERT_O) -%.ln: $(SRC)/common/dis/i386/%.c - $(LINT.c) -c $< - %.ln: ../../../../../uts/intel/promif/%.c $(LINT.c) -c $< diff --git a/usr/src/cmd/mdb/intel/amd64/kmdb/Makefile b/usr/src/cmd/mdb/intel/amd64/kmdb/Makefile index 2e43bd0f6e..e5094fc27b 100644 --- a/usr/src/cmd/mdb/intel/amd64/kmdb/Makefile +++ b/usr/src/cmd/mdb/intel/amd64/kmdb/Makefile @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -63,6 +62,8 @@ include ../../../../Makefile.cmd.64 include ../../Makefile.amd64 include ../../../Makefile.kmdb +STANDLIBS += $(ROOT)/usr/lib/amd64/libstanddisasm.so + INCDIRS += $(SRC)/uts/i86pc $(SRC)/common/dis/i386 CPPFLAGS += -DDIS_TEXT diff --git a/usr/src/cmd/mdb/intel/amd64/mdb/Makefile b/usr/src/cmd/mdb/intel/amd64/mdb/Makefile index 1081b4c5c9..3db1f99e85 100644 --- a/usr/src/cmd/mdb/intel/amd64/mdb/Makefile +++ b/usr/src/cmd/mdb/intel/amd64/mdb/Makefile @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,16 +19,12 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" -SRCS = \ - bits.c \ - dis_tables.c \ - inteldis.c \ - kvm_amd64dep.c \ +SRCS = kvm_amd64dep.c \ mdb_amd64util.c \ proc_amd64dep.c @@ -41,24 +36,17 @@ SRCS = \ $(COMPILE.c) $< $(CTFCONVERT_O) -%.o: $(SRC)/common/dis/i386/%.c - $(COMPILE.c) $< - $(CTFCONVERT_O) - %.ln: %.c $(LINT.c) -c $< %.ln: ../../mdb/%.c $(LINT.c) -c $< -%.ln: $(SRC)/common/dis/i386/%.c - $(LINT.c) -c $< - include ../../../../Makefile.cmd include ../../../../Makefile.cmd.64 include ../../Makefile.amd64 include ../../../Makefile.mdb -CPPFLAGS += -I../../mdb -I$(SRC)/common/dis/i386 -DDIS_TEXT +CPPFLAGS += -I../../mdb install: all $(ISAEXEC) $(ROOTPROG64) $(ROOTLINK64) diff --git a/usr/src/cmd/mdb/intel/ia32/Makefile b/usr/src/cmd/mdb/intel/ia32/Makefile index d7883caabb..4a0e384174 100644 --- a/usr/src/cmd/mdb/intel/ia32/Makefile +++ b/usr/src/cmd/mdb/intel/ia32/Makefile @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" diff --git a/usr/src/cmd/mdb/intel/ia32/kmdb/Makefile b/usr/src/cmd/mdb/intel/ia32/kmdb/Makefile index 87c8ecc639..ccd4b446c4 100644 --- a/usr/src/cmd/mdb/intel/ia32/kmdb/Makefile +++ b/usr/src/cmd/mdb/intel/ia32/kmdb/Makefile @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -54,6 +53,8 @@ include ../../../../Makefile.cmd include ../../Makefile.ia32 include ../../../Makefile.kmdb +STANDLIBS += $(ROOT)/usr/lib/libstanddisasm.so + INCDIRS += $(SRC)/uts/i86pc CPPFLAGS += -DDIS_TEXT diff --git a/usr/src/cmd/mdb/intel/ia32/mdb/Makefile b/usr/src/cmd/mdb/intel/ia32/mdb/Makefile index d283feaea6..9ca959931b 100644 --- a/usr/src/cmd/mdb/intel/ia32/mdb/Makefile +++ b/usr/src/cmd/mdb/intel/ia32/mdb/Makefile @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,15 +19,12 @@ # CDDL HEADER END # # -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" -SRCS = bits.c \ - dis_tables.c \ - inteldis.c \ - kvm_ia32dep.c \ +SRCS = kvm_ia32dep.c \ mdb_ia32util.c \ proc_ia32dep.c @@ -36,21 +32,14 @@ SRCS = bits.c \ $(COMPILE.c) $< $(CTFCONVERT_O) -%.o: $(SRC)/common/dis/i386/%.c - $(COMPILE.c) $< - $(CTFCONVERT_O) - %.ln: ../../mdb/%.c $(LINT.c) -c $< -%.ln: $(SRC)/common/dis/i386/%.c - $(LINT.c) -c $< - include ../../../../Makefile.cmd include ../../Makefile.ia32 include ../../../Makefile.mdb -CPPFLAGS += -I../../mdb -I$(SRC)/common/dis/i386 -DDIS_TEXT +CPPFLAGS += -I../../mdb install: all $(ISAEXEC) $(ROOTPROG32) $(ROOTLINK32) -$(RM) $(ROOTPROG) diff --git a/usr/src/cmd/mdb/intel/mdb/bits.c b/usr/src/cmd/mdb/intel/mdb/bits.c deleted file mode 100644 index 5abb7e4556..0000000000 --- a/usr/src/cmd/mdb/intel/mdb/bits.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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 - * or http://www.opensolaris.org/os/licensing. - * 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. - * - * Copyright (c) 1988 AT&T - * All rights reserved. - * - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "dis.h" - -/* - * Minimum instruction name field width - */ -#define INST_MINWIDTH 7 - -/* For communication to locsympr */ -const char *const *regname; -static char mneu[256]; /* array to store disassembly for return */ -static uchar_t curbyte; /* result of getbyte() */ - -static mdb_tgt_t *dis_target; -static mdb_tgt_as_t dis_as; -static mdb_tgt_addr_t dis_offset; -static ssize_t dis_size; -static uchar_t dis_buffer[64]; - -static mdb_tgt_addr_t curloc; - - -/* - * Get next byte from the instruction stream, - * set curbyte and increment curloc. - */ -/*ARGSUSED*/ -static int -getbyte(void *notused) -{ - ulong_t index = (ulong_t)(curloc - dis_offset); - - if (index >= dis_size) { - dis_size = mdb_tgt_aread(dis_target, dis_as, dis_buffer, - sizeof (dis_buffer), curloc); - - if (dis_size <= 0) { - dis_offset = 0; - dis_size = 0; - curbyte = 0; - return (-1); - } - - dis_offset = curloc; - index = 0; - } - - curbyte = dis_buffer[index]; - curloc++; - return (curbyte); -} - -static int -symlookup(uint64_t addr, char *buf, size_t len) -{ - (void) mdb_iob_snprintf(buf, len, "%a", (uintptr_t)addr); - if (strncmp(buf, "0x", 2) == 0) { - if (len > 0) - *buf = '\0'; - return (-1); - } - return (0); -} - -/* - * disassemble an instruction. Mode can be DIS_IA32 or DIS_AMD64. - */ -/*ARGSUSED*/ -static void -disasm(int mode) -{ - dis86_t x86dis; - uint_t cpu_mode = SIZE32; - -#ifdef __amd64 - if (mode == DIS_AMD64) - cpu_mode = SIZE64; -#endif - - bzero(&x86dis, sizeof (dis86_t)); - x86dis.d86_check_func = NULL; - x86dis.d86_get_byte = getbyte; - x86dis.d86_sprintf_func = - (int (*)(char *, size_t, const char *, ...))mdb_iob_snprintf; - x86dis.d86_sym_lookup = symlookup; - - if (dtrace_disx86(&x86dis, cpu_mode) != 0) { - (void) strcpy(mneu, "***ERROR--unknown op code***"); - return; - } - - dtrace_disx86_str(&x86dis, cpu_mode, curloc, mneu, sizeof (mneu)); -} - -/*ARGSUSED*/ -mdb_tgt_addr_t -ia32dis_ins2str(mdb_disasm_t *dp, mdb_tgt_t *t, mdb_tgt_as_t as, - char *buf, size_t len, mdb_tgt_addr_t pc) -{ - char *cp; - - dis_target = t; /* target pointer */ - dis_as = as; /* address space identifier */ - dis_offset = pc; /* address of current instruction */ - dis_size = 1; /* size of current instruction */ - - if (mdb_tgt_aread(t, as, &dis_buffer[0], sizeof (char), pc) == -1) { - warn("failed to read instruction at %llr", pc); - return (pc); - } - - /* - * Disassemble one instruction starting at curloc, - * increment curloc to the following location, - * and leave the ascii result in mneu[]. dp->dis_data - * holds the disassembly mode; DIS_AMD64 or DIS_IA32. - */ - curloc = pc; - disasm((uintptr_t)dp->dis_data); - - cp = mneu + strlen(mneu); - while (cp-- > mneu && *cp == ' ') - *cp = '\0'; - (void) mdb_snprintf(buf, len, "%s", mneu); - return (curloc); -} diff --git a/usr/src/cmd/mdb/intel/mdb/inteldis.c b/usr/src/cmd/mdb/intel/mdb/inteldis.c deleted file mode 100644 index 6ea67ff839..0000000000 --- a/usr/src/cmd/mdb/intel/mdb/inteldis.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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 - * or http://www.opensolaris.org/os/licensing. - * 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 "dis.h" - -extern mdb_tgt_addr_t ia32dis_ins2str(mdb_disasm_t *, mdb_tgt_t *, - mdb_tgt_as_t, char *, size_t, mdb_tgt_addr_t); - -/*ARGSUSED*/ -static void -ia32dis_destroy(mdb_disasm_t *dp) -{ - /* Nothing to do here */ -} - -static mdb_tgt_addr_t -ia32dis_previns(mdb_disasm_t *dp, mdb_tgt_t *t, mdb_tgt_as_t as, - mdb_tgt_addr_t pc, uint_t n) -{ - mdb_tgt_addr_t *hist, addr, naddr; - mdb_tgt_addr_t res = pc; - GElf_Sym sym; - int cur, nseen; - char c; - - if (mdb_lookup_by_addr(pc, MDB_SYM_FUZZY, &c, 1, &sym) < 0 || - sym.st_value == pc) - return (pc); /* we need to be in the middle of a symbol */ - - hist = mdb_zalloc(sizeof (mdb_tgt_addr_t) * n, UM_SLEEP); - - for (cur = 0, nseen = 0, addr = sym.st_value; addr < pc; addr = naddr) { - hist[cur] = addr; - cur = (cur + 1) % n; - nseen++; - - if (mdb_tgt_aread(t, as, &c, 1, addr) != 1 || - (naddr = ia32dis_ins2str(dp, t, as, &c, 1, addr)) == addr) - goto done; /* no progress or can't read - give up */ - } - - if (addr != pc) { - /* - * We scanned past %pc, but didn't find an instruction that - * started at %pc. This means that either the caller specified - * an invalid address, or we ran into something other than code - * during our scan. Virtually any combination of bytes can be - * construed as a valid Intel instruction, so any non-code bytes - * we encounter will have thrown off the scan. - */ - goto done; - } - - res = hist[(cur + n - MIN(n, nseen)) % n]; - -done: - mdb_free(hist, sizeof (mdb_tgt_addr_t) * n); - return (res); -} - -/*ARGSUSED*/ -static mdb_tgt_addr_t -ia32dis_nextins(mdb_disasm_t *dp, mdb_tgt_t *t, mdb_tgt_as_t as, - mdb_tgt_addr_t pc) -{ - mdb_tgt_addr_t npc; - char c; - - if ((npc = ia32dis_ins2str(dp, t, as, &c, 1, pc)) == pc) - return (pc); - - /* - * Probe the address to make sure we can read something from it - we - * want the address we return to actually contain something. - */ - if (mdb_tgt_aread(t, as, &c, 1, npc) != 1) - return (pc); - - return (npc); -} - -static const mdb_dis_ops_t ia32dis_ops = { - ia32dis_destroy, - ia32dis_ins2str, - ia32dis_previns, - ia32dis_nextins -}; - -int -ia32_create(mdb_disasm_t *dp) -{ - dp->dis_name = "ia32"; - dp->dis_desc = "Intel 32-bit disassembler"; - dp->dis_ops = &ia32dis_ops; - dp->dis_data = (void *)DIS_IA32; - - return (0); -} - -int -amd64_create(mdb_disasm_t *dp) -{ - dp->dis_name = "amd64"; - dp->dis_desc = "AMD64 and IA32e 64-bit disassembler"; - dp->dis_ops = &ia32dis_ops; - dp->dis_data = (void *)DIS_AMD64; - - return (0); -} diff --git a/usr/src/cmd/mdb/sparc/v7/Makefile b/usr/src/cmd/mdb/sparc/v7/Makefile index 683d7a12da..0635907080 100644 --- a/usr/src/cmd/mdb/sparc/v7/Makefile +++ b/usr/src/cmd/mdb/sparc/v7/Makefile @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -31,8 +30,6 @@ MODULES = \ $(COMMON_MODULES_PROC) \ $(COMMON_MODULES_PROC_32BIT) -$(CLOSED_BUILD)MODULES += $(CLOSED)/cmd/mdb/sparc/v7/sparcdis - SUBDIRS = mdb $(MODULES) include ../../Makefile.subdirs diff --git a/usr/src/cmd/mdb/sparc/v9/Makefile b/usr/src/cmd/mdb/sparc/v9/Makefile index ac9fc4f12e..f937a0f7b6 100644 --- a/usr/src/cmd/mdb/sparc/v9/Makefile +++ b/usr/src/cmd/mdb/sparc/v9/Makefile @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -37,8 +36,7 @@ MODULES = \ $(CLOSED_BUILD)MODULES += \ $(CLOSED_COMMON_MODULES_KVM:%=$(CLOSED)/cmd/mdb/sparc/v9/%) $(CLOSED_BUILD)MODULES += \ - $(CLOSED)/cmd/mdb/sparc/v9/isp \ - $(CLOSED)/cmd/mdb/sparc/v9/sparcdis + $(CLOSED)/cmd/mdb/sparc/v9/isp # # a "$(MODULES): kmdb" rule would seem to do the trick but, for some reason, diff --git a/usr/src/cmd/mdb/sparc/v9/kmdb/Makefile b/usr/src/cmd/mdb/sparc/v9/kmdb/Makefile index 7af39fbace..587f618343 100644 --- a/usr/src/cmd/mdb/sparc/v9/kmdb/Makefile +++ b/usr/src/cmd/mdb/sparc/v9/kmdb/Makefile @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -32,6 +31,8 @@ include ../../Makefile.sparcv9 include ../../Makefile.kmdb.64 include ../../../Makefile.kmdb +STANDLIBS += $(ROOT)/usr/lib/sparcv9/libstanddisasm.so + all: kmdb_modlinktest.o lint: FRC diff --git a/usr/src/cmd/mdb/sun4u/v9/kmdb/Makefile b/usr/src/cmd/mdb/sun4u/v9/kmdb/Makefile index c8131b33b1..b99e6181e0 100644 --- a/usr/src/cmd/mdb/sun4u/v9/kmdb/Makefile +++ b/usr/src/cmd/mdb/sun4u/v9/kmdb/Makefile @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -49,6 +48,8 @@ include ../../../sparc/Makefile.sparcv9 include ../../../sparc/Makefile.kmdb.64 include ../../../Makefile.kmdb +STANDLIBS += $(ROOT)/usr/lib/sparcv9/libstanddisasm.so + KMDB_FPTEST = \ $(FINDFP) -x kaif_resume -x kaif_trap_common $@ diff --git a/usr/src/cmd/mdb/sun4v/v9/kmdb/Makefile b/usr/src/cmd/mdb/sun4v/v9/kmdb/Makefile index 56e8c697cb..ef84fe6500 100644 --- a/usr/src/cmd/mdb/sun4v/v9/kmdb/Makefile +++ b/usr/src/cmd/mdb/sun4v/v9/kmdb/Makefile @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -49,6 +48,8 @@ include ../../../sparc/Makefile.sparcv9 include ../../../sparc/Makefile.kmdb.64 include ../../../Makefile.kmdb +STANDLIBS += $(ROOT)/usr/lib/sparcv9/libstanddisasm.so + KMDB_FPTEST = \ $(FINDFP) -x kaif_resume -x kaif_trap_common $@ diff --git a/usr/src/cmd/sgs/Makefile b/usr/src/cmd/sgs/Makefile index 59e83194fe..a6db073295 100644 --- a/usr/src/cmd/sgs/Makefile +++ b/usr/src/cmd/sgs/Makefile @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -75,8 +74,6 @@ SUBDIRS-common= libconv \ unifdef \ yacc -$(CLOSED_BUILD)SUBDIRS-common += $(CLOSED)/cmd/sgs/dis - SUBDIRS-i386= SUBDIRS-sparc= rtld.4.x diff --git a/usr/src/cmd/sgs/sgsdemangler/Makefile.com b/usr/src/cmd/sgs/sgsdemangler/Makefile.com index 3c742d9e79..e82b9f88e4 100644 --- a/usr/src/cmd/sgs/sgsdemangler/Makefile.com +++ b/usr/src/cmd/sgs/sgsdemangler/Makefile.com @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,11 +19,11 @@ # CDDL HEADER END # # -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +#ident "%Z%%M% %I% %E% SMI" +# LIBRARY = libdemangle.a @@ -35,9 +34,9 @@ CFLAGS += $(C_PICFLAGS) CFLAGS64 += $(C_PICFLAGS64) -CLEANFILES += y.tab.c y.tab.h llib-ldemangle.ln lint.out +CLEANFILES += llib-ldemangle.ln lint.out -OBJECTS= cafe_dem.o dem.o demangle.o +OBJECTS= demangle.o CFLAGS += -erroff=E_STATEMENT_NOT_REACHED CFLAGS64 += -erroff=E_STATEMENT_NOT_REACHED diff --git a/usr/src/cmd/sgs/sgsdemangler/Makefile.targ b/usr/src/cmd/sgs/sgsdemangler/Makefile.targ index 9838c5b55b..e6c1070b7d 100644 --- a/usr/src/cmd/sgs/sgsdemangler/Makefile.targ +++ b/usr/src/cmd/sgs/sgsdemangler/Makefile.targ @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,18 +19,11 @@ # CDDL HEADER END # # +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# #ident "%Z%%M% %I% %E% SMI" # -# Copyright (c) 1998,2001 by Sun Microsystems, Inc. -# All rights reserved. - -objs/cafe_dem.o: \ - ../common/cafe_dem.y ../common/cafe_dem.h ../common/dem.h - yacc ../common/cafe_dem.y - $(COMPILE.c) -I../common -c y.tab.c -o $@ - -objs/dem.o: ../common/dem.c - $(COMPILE.c) -I../common -c ../common/dem.c -o $@ objs/demangle.o: \ ../common/demangle.c diff --git a/usr/src/cmd/sgs/sgsdemangler/common/cafe_dem.h b/usr/src/cmd/sgs/sgsdemangler/common/cafe_dem.h deleted file mode 100644 index 954bde9b5f..0000000000 --- a/usr/src/cmd/sgs/sgsdemangler/common/cafe_dem.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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 - * or http://www.opensolaris.org/os/licensing. - * 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 1993 by Sun Microsystems, Inc. - * All Rights Reserved. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/***************************************************************** - - Copyright 1993 Sun Microsystems - All Rights Reserved. - - %W% %G% %U% - - Revisions - 06/10/93 - Raymond Lai Created - -******************************************************************/ - -#ifndef _CAFE_DEM_H -#define _CAFE_DEM_H - -#include "dem.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Note: NDEM_type starts with 1000 so that dbx can tell a NDEM_name - structure from a DEM (cfront) one. -*/ - -enum NDEM_type { - NDEM_other = 1000, /* default */ - NDEM_constructor, NDEM_destructor, NDEM_operator, NDEM_conversion, - NDEM_unnamed_arg, NDEM_static_constructor, NDEM_static_destructor -}; - -typedef struct NDEM_modifier { - char is_signed : 1; - char is_volatile : 1; - char is_unsigned : 1; - char is_const : 1; - char is_static : 1; -} NDEM_modifier; - -struct NDEM_class; -struct NDEM_arg; - -/* A cafe name. This can be either a (static) data member, a function member, - or a global function. -*/ - -typedef struct NDEM_name { - enum NDEM_type type; - struct NDEM_class *qual_class; - char *raw_name; - struct NDEM_arg *conv_t; /* for conversion function */ - struct NDEM_arg *f_args; /* for function */ - struct NDEM_modifier f_modifier; /* for member function */ -} NDEM_name; - -/* A class. */ - -typedef struct NDEM_class { - struct NDEM_class *qual_class; - char *raw_class_name; - struct NDEM_arg *t_args; /* for template class */ -} NDEM_class; - -/* A function pointer (as an argument). */ - -typedef struct NDEM_fptr { - struct NDEM_class *qual_class; - struct NDEM_arg *f_args; - struct NDEM_arg *return_t; - struct NDEM_arg *decls; /* function declarator list */ -} NDEM_fptr; - -/* A member data pointer (as an argument). */ - -typedef struct NDEM_mdptr { - struct NDEM_class *qual_class; - struct NDEM_arg *mem_data_t; -} NDEM_mdptr; - -/* An abbreviation record (for arguments like "NDC", "TB"). */ - -typedef struct NDEM_abbrev_rec { - int repetition_number; - int param_number; -} NDEM_abbrev_rec; - -/* A pointer, reference, or array introduces a type of its own... */ - -enum NDEM_decl_type { - NDEM_pointer = 1, NDEM_reference, NDEM_array -}; - -typedef struct NDEM_declarator { - enum NDEM_decl_type decl_type; - struct NDEM_arg *real_arg; - char *array_size; /* if an array */ -} NDEM_declarator; - -enum NDEM_arg_type { - NDEM_basic_type, NDEM_user_defined_type, NDEM_function_ptr, NDEM_decl, - NDEM_mem_data_ptr, - NDEM_abbrev_N, NDEM_abbrev_T, - NDEM_i_const, /* template integral constant argument */ - NDEM_p_const /* template pointer constant argument */ -}; - -/* A type. */ - -typedef struct NDEM_arg { - enum NDEM_arg_type arg_type; - union { - char basic_t; - struct NDEM_class *user_defined_t; - struct NDEM_fptr *function_ptr; - struct NDEM_mdptr *mem_data_ptr; - struct NDEM_abbrev_rec abbrev_rec; - struct NDEM_declarator decl; - char *pt_constant; - struct NDEM_name *temp_p_arg; - } arg_data; - struct NDEM_modifier modifier; - struct NDEM_arg *next; -} NDEM_arg; - -#ifdef DBX_SUPPORT - -extern int cafe_dem (char *, NDEM_name *, char *); -extern enum DEM_TYPE cafe_getfieldtype (NDEM_name *); -extern char *cafe_getclass (NDEM_name *, char *); -extern char *cafe_getname (NDEM_name *, char *); -extern char **cafe_getparentclass (NDEM_name *, char **); -extern char *cafe_gettemplatename (NDEM_name *); - -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/usr/src/cmd/sgs/sgsdemangler/common/cafe_dem.y b/usr/src/cmd/sgs/sgsdemangler/common/cafe_dem.y deleted file mode 100644 index cf368aece3..0000000000 --- a/usr/src/cmd/sgs/sgsdemangler/common/cafe_dem.y +++ /dev/null @@ -1,1615 +0,0 @@ -%{ -/* - * 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 - * or http://www.opensolaris.org/os/licensing. - * 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 1993-2000 by Sun Microsystems, Inc. - * All Rights Reserved - */ -/***************************************************************** - - %W% %G% %U% - - Revisions - 06/10/93 - Raymond Lai Created - -******************************************************************/ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include "cafe_dem.h" - -#define DEM_VERSION 0 -#define CHECK_OLD_PREFIX(s) (s[0] == '$') -#define CHECK_PREFIX(s) (s[0] == '_' && s[1] == '_' && \ - isdigit(s[2]) && DEM_VERSION >= s[2] - '0') - -static char ll_cur_char; -static int ll_id_size = 0; /* the default token is of size 1 */ -static char *yytext; - -#define BUFSIZE 8192 -static char name_buffer[BUFSIZE]; -static char *mem_reservoir; - -#define ALIGN_MASK 03 - -static void *allocate(size_t size) -{ - char *pos; - - while ((unsigned long)mem_reservoir & ALIGN_MASK) - ++mem_reservoir; - pos = mem_reservoir; - mem_reservoir += size; - return pos; -} - -/* Will only be called by print_template_args() and print_function_args() - to deallocate the excess memory allocated for argument array. -*/ - -static void deallocate(size_t size) -{ - mem_reservoir -= size; -} - -static char *convert_number(int n) -{ - int i, len = 0; - static char tmp[1024]; - char *s; - - if (n == 0) return NULL; - - do { - tmp[len++] = n % 10 + '0'; - } while ((n /= 10) > 0); - - s = allocate(len+1); - i = 0; - while (--len >= 0) - s[i++] = tmp[len]; - s[i] = '\0'; - - return s; -} - -static NDEM_name *result; -static NDEM_arg *conv_type; -static NDEM_modifier save_modifier, current_modifier = { 0, 0, 0, 0, 0 }; - -static void reset_current_modifier() -{ - current_modifier.is_signed = current_modifier.is_volatile = - current_modifier.is_unsigned = current_modifier.is_const = - current_modifier.is_static = 0; -} - -enum Boolean { TRUE = 1, FALSE = 0 }; - -/* Don't build function argument structures when yyparse() is called by - cafe_dem()... -*/ -static enum Boolean from_cafe_dem = FALSE; -static enum Boolean build_args = TRUE; - -/* Function arguments of embedded functions still need to be handled. For - example: - - $fDfoo7$FBfPvi44D_Dbarv == foo<&f(void*, int), 3>::bar( <IGNORE> ) - ^^^^^^^ ^^^^^^^^^^^^^^ - - The following stack is used for this purpose. When the parser is called - by cafe_dem() to parse a function, it first pushes a TRUE onto the stack. - All subsequent values pushed into the stack are FALSE. - - Note the stack doesn't need to be large. -*/ -static enum Boolean stack[10]; -static int sk_top = 0; - -#define push(f) stack[sk_top++] = f -#define pop() stack[--sk_top] - -/*________________________________________________________________________*/ - -%} - -%union { - int i_val; - char c_val; - char *s_val; - NDEM_name *n_val; - NDEM_class *class_val; - NDEM_arg *arg_val; - NDEM_fptr *fptr_val; -} - -%token IDENTIFIER NUMBER - -%type <i_val> big_number uname_size - -%type <s_val> uname_spec uname_specN op_name optimize_number - -%type <n_val> function_name global_data_name - -/* namespace_spec is used solely for qualifying class(es) for now... */ -%type <class_val> class_spec class_specN namespace_spec - -%type <arg_val> template_spec template_arg_spec t_arg_spec arg_spec - arg_type formal_arg_spec arg_abbrev type_declarator - modifier_n_declarator - -%type <fptr_val> function_arg_spec - -%% - - -mangled_name : - function_name - { result = $1; } -| global_data_name - { result = $1; } -| internal_name -| external_linkage_name -| error - { return 1; } -; - -PREFIX : - '_' '_' VERSION - { if (DEM_VERSION < ll_cur_char - '0') YYERROR; } -| '$' -; - -VERSION : - '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' -; - -UPPER_LETTER : - 'A'|'B'|'C'|'D'|'E'|'F'|'G'|'H'|'I'|'J'|'K'|'L'|'M'|'N'|'O'| - 'P'|'Q'|'R'|'S'|'T'|'U'|'V'|'W'|'X'|'Y'|'Z' -; - -LOWER_LETTER : - 'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j'|'k'|'l'|'m'|'n'|'o'| - 'p'|'q'|'r'|'s'|'t'|'u'|'v'|'w'|'x'|'y'|'z' -; - -/* Upper case letter represent the numbers 0 thru 25. Lower case are the -* numbers 26 thru 51. A prefix of '0' adds 52 to the value. e.g.: -* -* C = 2 -* c = 28 -* y = 50 -* 0y = 102 -* -* -* The key features are that: -* -numbers less than or equal to 51 are only one character -* -the end of a big_number can be found when embedded in a -* string: e.g. -* -* Dfoo = big_number 3, string "foo" -* OCB = big_number 54, string "B" -*/ - -big_number : - UPPER_LETTER - { $$ = ll_cur_char - 'A'; } -| LOWER_LETTER - { $$ = ll_cur_char - 'a' + 26; } -| '0' big_number - { $$ = 52 + $2; } -; - -/*"identifier" is defined the the ANSI committee */ - -uname : - IDENTIFIER -; - - -uname_spec : - uname_size - { ll_id_size = $1; } - uname - { - if (build_args) - { - $$ = allocate($1+1); - (void) strncpy($$, yytext, $1); - *($$+$1) = '\0'; - } - else - $$ = NULL; - } -; - -uname_size : - big_number -; - -class_specN : - namespace_spec class_spec - { - if (build_args) - { - $2->qual_class = $1; - $$ = $2; - } - else - $$ = NULL; - } -; - -class_spec : - fun_local_spec uname_spec template_spec - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_class)); - $$->raw_class_name = $2; - $$->t_args = $3; - } - else - $$ = NULL; - } -; - -uname_specN : - namespace_spec uname_spec - { - $$ = $2; - } -; - -namespace_spec : - /* nil */ - { $$ = NULL; } -| namespace_spec '1' uname_spec -| namespace_spec '5' class_specN - { - if (build_args) - { - $3->qual_class = $1; - $$ = $3; - } - else - $$ = NULL; - } -; - -template_spec : - /* nil */ - { $$ = NULL; } -| '7' template_arg_spec '_' - { $$ = $2; } -; - -template_arg_spec : - t_arg_spec -| template_arg_spec t_arg_spec - { - if (build_args) - { - NDEM_arg *tmp = $1; - while (tmp->next) tmp = tmp->next; - tmp->next = $2; - } - $$ = $1; - } -; - -t_arg_spec : - arg_spec -| '4' optimize_number - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_i_const; - $$->arg_data.pt_constant = $2; - } - else - $$ = NULL; - } -| '4' optimize_number 'n' - { - if (build_args) - { - char *s = allocate(strlen($2)+2); - s[0] = '-'; - (void) strcpy(s+1, $2); - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_i_const; - $$->arg_data.pt_constant = s; - } - else - $$ = NULL; - } -| '4' function_name '_' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_p_const; - $$->arg_data.temp_p_arg = $2; - } - else - $$ = NULL; - } -| '4' global_data_name '_' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_p_const; - $$->arg_data.temp_p_arg = $2; - } - else - $$ = NULL; - } -; - -optimize_number : - big_number - { - if (build_args) - $$ = convert_number($1); - else - $$ = NULL; - } -| '8' big_number - { ll_id_size = $2; } - uname - { - if (build_args) - { - $$ = allocate($2+1); - (void) strncpy($$, yytext, $2); - *($$+$2) = '\0'; - } - else - $$ = NULL; - } -; - -/* -* ".F" signifies a standard function -* ".f" is a member function -* ".O" is a global operator function -* ".o" is a member operator function -*/ - -function_name : - PREFIX 'F' - { - push(from_cafe_dem); - from_cafe_dem = FALSE; - } - uname_specN - { - if (pop()) - build_args = FALSE; - } - formal_arg_spec - { - $$ = allocate(sizeof(NDEM_name)); - if ($4[0] == 'O') - $$->type = NDEM_conversion; - else - $$->type = NDEM_other; - $$->raw_name = $4; - $$->f_args = $6; - } -| PREFIX 'C' - { - push(from_cafe_dem); - from_cafe_dem = FALSE; - } - uname_specN - { - if (pop()) - build_args = FALSE; - } - formal_arg_spec - { - $$ = allocate(sizeof(NDEM_name)); - $$->type = NDEM_static_constructor; - $$->raw_name = "__STATIC_CONSTRUCTOR"; - $$->f_args = $6; - } -| PREFIX 'D' - { - push(from_cafe_dem); - from_cafe_dem = FALSE; - } - uname_specN - { - if (pop()) - build_args = FALSE; - } - formal_arg_spec - { - $$ = allocate(sizeof(NDEM_name)); - $$->type = NDEM_static_destructor; - $$->raw_name = "__STATIC_DESTRUCTOR"; - $$->f_args = $6; - } -| PREFIX 'f' - { - push(from_cafe_dem); - from_cafe_dem = FALSE; - } - class_specN uname_spec - { - if (pop()) - build_args = FALSE; - } - formal_arg_spec f_modifier - { - $$ = allocate(sizeof(NDEM_name)); - $$->type = NDEM_other; - $$->qual_class = $4; - $$->raw_name = $5; - $$->f_args = $7; - $$->f_modifier = current_modifier; - reset_current_modifier(); - } -| PREFIX 'O' - { - push(from_cafe_dem); - from_cafe_dem = FALSE; - } - op_name namespace_spec - { - if (pop()) - build_args = FALSE; - } - formal_arg_spec - { - $$ = allocate(sizeof(NDEM_name)); - if ($4[0] == 'O') - { - $$->type = NDEM_conversion; - $$->conv_t = conv_type; - } - else if ($4[0] == 'C') - $$->type = NDEM_constructor; - else if ($4[0] == 'D') - $$->type = NDEM_destructor; - else - $$->type = NDEM_operator; - $$->raw_name = $4; - $$->f_args = $7; - } -| PREFIX 'o' - { - push(from_cafe_dem); - from_cafe_dem = FALSE; - } - class_specN op_name - { - if (pop()) - build_args = FALSE; - } - formal_arg_spec f_modifier - { - $$ = allocate(sizeof(NDEM_name)); - if ($5[0] == 'O') - { - $$->type = NDEM_conversion; - $$->conv_t = conv_type; - } - else if ($5[0] == 'C') - $$->type = NDEM_constructor; - else if ($5[0] == 'D') - $$->type = NDEM_destructor; - else - $$->type = NDEM_operator; - $$->qual_class = $4; - $$->raw_name = $5; - $$->f_args = $7; - $$->f_modifier = current_modifier; - reset_current_modifier(); - } -; - -f_modifier: - /* nil */ -| 'K' - { current_modifier.is_const = 1; } -| 'W' - { current_modifier.is_volatile = 1; } -| 'T' - { current_modifier.is_static = 1; } -; - -/* Note: "adv" and "add" have been changed to "gav" and "gad" to avoid -* grammar conflicts. -* -* See p. 125 of the ARM. Note that operator T() is now "op" class_specN. -*/ - -op_name : - 'm' 'l' - { $$ = "*"; } -| 'm' 'd' - { $$ = "%"; } -| 'm' 'i' - { $$ = "-"; } -| 'r' 's' - { $$ = ">>"; } -| 'n' 'e' - { $$ = "!="; } -| 'g' 't' - { $$ = ">"; } -| 'g' 'e' - { $$ = ">="; } -| 'o' 'r' - { $$ = "|"; } -| 'a' 'a' - { $$ = "&&"; } -| 'n' 't' - { $$ = "!"; } -| 'p' 'p' - { $$ = "++"; } -| 'a' 's' - { $$ = "="; } -| 'a' 'p' 'l' - { $$ = "+="; } -| 'a' 'm' 'u' - { $$ = "*="; } -| 'a' 'm' 'd' - { $$ = "%="; } -| 'a' 'r' 's' - { $$ = ">>="; } -| 'a' 'o' 'r' - { $$ = "|="; } -| 'c' 'm' - { $$ = ","; } -| 'd' 'v' - { $$ = "/"; } -| 'p' 'l' - { $$ = "+"; } -| 'l' 's' - { $$ = "<<"; } -| 'e' 'q' - { $$ = "=="; } -| 'l' 't' - { $$ = "<"; } -| 'l' 'e' - { $$ = "<="; } -| 'a' 'd' - { $$ = "&"; } -| 'e' 'r' - { $$ = "^"; } -| 'o' 'o' - { $$ = "||"; } -| 'c' 'o' - { $$ = "~"; } -| 'm' 'm' - { $$ = "--"; } -| 'r' 'f' - { $$ = "->"; } -| 'a' 'm' 'i' - { $$ = "-="; } -| 'g' 'd' 'v' -/* 'a' 'd' 'v' */ - { $$ = "/="; } -| 'a' 'l' 's' - { $$ = "<<="; } -| 'g' 'a' 'd' -/* 'a' 'a' 'd' */ - { $$ = "&="; } -| 'a' 'e' 'r' - { $$ = "^="; } -| 'r' 'm' - { $$ = "->*"; } -| 'c' 'l' - { $$ = "()"; } -| 'v' 'c' - { $$ = "[]"; } -| 'c' 't' - { $$ = "C"; } -| 'd' 't' - { $$ = "D"; } -| 'n' 'w' - { $$ = "new"; } -| 'd' 'l' - { $$ = "delete"; } -| 'o' 'p' arg_spec - { - conv_type = $3; - $$ = "O"; - } -; - -/* "$N" is for global data (they are mangled when their addresses are - passed as template arguments). -* "$d" is for static data members -*/ - -global_data_name : - PREFIX 'N' namespace_spec uname_spec - { - $$ = allocate(sizeof(NDEM_name)); - $$->type = NDEM_other; - $$->raw_name = $4; - } -| PREFIX 'd' class_specN uname_spec - { - $$ = allocate(sizeof(NDEM_name)); - $$->type = NDEM_other; - $$->qual_class = $3; - $$->raw_name = $4; - } -; - -/* -* "$P" is for compiler private data and must be file local or block local. -* "$X" is for extensions and can be global. The big_number should be used -* to serialize the extensions since collisions between different compilers -* can occur. (Note that "P" is file local and doesn't have this problem.) -* "$V" is for virtual tables. It is to be global. -*/ - -internal_name : - PREFIX 'P' private_id -| PREFIX 'X' big_number private_id -| PREFIX 'V' class_specN -; - -private_id : - /* FIXUP: This is implementation specific */ -; - -external_linkage_name : - /* defined by other languages ABI */ -; - -/* This is used to add info for function local classes. The big_number is a -* compiler dependent scope identifier and can be omitted if not needed. -*/ - -/* Note that function local classes only need to be mangled when the linker -* will see them, such as when a member function will be instantiated. -*/ - -fun_local_spec : - /* nil */ -| '2' fun_local_scope -; - -fun_local_scope : - big_number -| '8' big_number - { ll_id_size = $2; } - uname -; - -arg_spec : - modifier_n_declarator arg_type - { - if (build_args) - { - $2->modifier = current_modifier; - reset_current_modifier(); - if ($1) { - if ($2->arg_type == NDEM_function_ptr) { - $2->arg_data.function_ptr->decls = $1; - $$ = $2; - } - else { - NDEM_arg *tmp = $1; - while (tmp->arg_data.decl.real_arg) - tmp = tmp->arg_data.decl.real_arg; - tmp->arg_data.decl.real_arg = $2; - $$ = $1; - } - } - else - $$ = $2; - } - else - $$ = NULL; - } -| arg_abbrev -; - -function_arg_spec : - 'F' formal_arg_spec '_' arg_spec - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_fptr)); - $$->f_args = $2; - $$->return_t = $4; - } - else - $$ = NULL; - } -| 'M' class_specN 'F' formal_arg_spec f_modifier - { - if (build_args) - { - save_modifier = current_modifier; - reset_current_modifier(); - } - } - '_' arg_spec - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_fptr)); - $$->qual_class = $2; - $$->f_args = $4; - $$->return_t = $8; - current_modifier = save_modifier; - } - else - $$ = NULL; - } -; - -formal_arg_spec : - formal_arg_spec arg_spec - { - if (build_args) - { - NDEM_arg *tmp = $1; - while (tmp->next) tmp = tmp->next; - tmp->next = $2; - $$ = $1; - } - else - $$ = NULL; - } -| arg_spec -; - -modifier_n_declarator : - /* nil */ - { $$ = NULL; } -| modifier_n_declarator modifier -| modifier_n_declarator type_declarator - { - if (build_args) - { - if ($1) { - NDEM_arg *tmp = $1; - while (tmp->arg_data.decl.real_arg) - tmp = tmp->arg_data.decl.real_arg; - tmp->arg_data.decl.real_arg = $2; - $$ = $1; - } - else - $$ = $2; - } - else - $$ = NULL; - } -; - -modifier : - 'C' - { - if (build_args) - current_modifier.is_const = 1; - } -| 'S' - { - if (build_args) - current_modifier.is_signed = 1; - } -| 'U' - { - if (build_args) - current_modifier.is_unsigned = 1; - } -| 'V' - { - if (build_args) - current_modifier.is_volatile = 1; - } -; - -type_declarator : - 'P' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_decl; - $$->arg_data.decl.decl_type = NDEM_pointer; - $$->modifier = current_modifier; - reset_current_modifier(); - } - else - $$ = NULL; - } -| 'R' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_decl; - $$->arg_data.decl.decl_type = NDEM_reference; - $$->modifier = current_modifier; - reset_current_modifier(); - } - else - $$ = NULL; - } -| 'A' big_number - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_decl; - $$->arg_data.decl.decl_type = NDEM_array; - $$->arg_data.decl.array_size = convert_number($2); - $$->modifier = current_modifier; - reset_current_modifier(); - } - else - $$ = NULL; - } -| 'A' '8' big_number - { ll_id_size = $3; } - uname - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_decl; - $$->arg_data.decl.decl_type = NDEM_array; - $$->arg_data.decl.array_size = allocate($3+1); - (void) strncpy($$->arg_data.decl.array_size, yytext, $3); - *($$->arg_data.decl.array_size+$3) = '\0'; - $$->modifier = current_modifier; - reset_current_modifier(); - } - else - $$ = NULL; - } -; - -arg_type : - 'v' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_basic_type; - $$->arg_data.basic_t = 'v'; - } - else - $$ = NULL; - } -| 'c' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_basic_type; - $$->arg_data.basic_t = 'c'; - } - else - $$ = NULL; - } -| 's' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_basic_type; - $$->arg_data.basic_t = 's'; - } - else - $$ = NULL; - } -| 'i' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_basic_type; - $$->arg_data.basic_t = 'i'; - } - else - $$ = NULL; - } -| 'l' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_basic_type; - $$->arg_data.basic_t = 'l'; - } - else - $$ = NULL; - } -| 'f' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_basic_type; - $$->arg_data.basic_t = 'f'; - } - else - $$ = NULL; - } -| 'd' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_basic_type; - $$->arg_data.basic_t = 'd'; - } - else - $$ = NULL; - } -| 'D' -/* 'r' */ - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_basic_type; - $$->arg_data.basic_t = 'D'; - } - else - $$ = NULL; - } -| 'L' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_basic_type; - $$->arg_data.basic_t = 'L'; - } - else - $$ = NULL; - } -| 'e' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_basic_type; - $$->arg_data.basic_t = 'e'; - } - else - $$ = NULL; - } -| 'G' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_basic_type; - $$->arg_data.basic_t = 'G'; - } - else - $$ = NULL; - } -| 'w' - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_basic_type; - $$->arg_data.basic_t = 'w'; - } - else - $$ = NULL; - } -| '6' class_specN - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_user_defined_type; - $$->arg_data.user_defined_t = $2; - } - else - $$ = NULL; - } -| function_arg_spec - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_function_ptr; - $$->arg_data.function_ptr = $1; - } - else - $$ = NULL; - } -| 'M' class_specN 'D' arg_spec - { - if (build_args) - { - NDEM_mdptr *t = allocate(sizeof(NDEM_mdptr)); - t->qual_class = $2; - t->mem_data_t = $4; - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_mem_data_ptr; - $$->arg_data.mem_data_ptr = t; - } - else - $$ = NULL; - } -; - -arg_abbrev : - 'N' big_number big_number - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_abbrev_N; - $$->arg_data.abbrev_rec.repetition_number = $2; - $$->arg_data.abbrev_rec.param_number = $3; - } - else - $$ = NULL; - } -| 'T' big_number - { - if (build_args) - { - $$ = allocate(sizeof(NDEM_arg)); - $$->arg_type = NDEM_abbrev_T; - $$->arg_data.abbrev_rec.param_number = $2; - } - else - $$ = NULL; - } -; - - -/* EXAMPLES: - - *** THIS SECTION NEEDS TO BE UPDATED !! *** - - C++ constuct New Cfront - ------------ ----- -------- - - P(int); .FAPi P__fi - - class a - { - Q (double); .fAaAQd Q__1aFd - class b - { - R(...); .f5AaAbARe R__Q21a|bFe - } - S(a); .fAaAS5Aa S__1aFa - } - - namespace n - { - T(void); .F1AnATv - class c - { - U(void); .f1AnAcAUv - namespace m - { - W(void) .F1An5Ac1AmAWv - } - } - namespace p - { - X(void); .F1An1ApAXv - } - } - - - NOTES - -The dot (.), can be replaced by any character that is not valid in the -first position of the linker symbols of languages that C++ will be -linked with. - - -Numeric switches: - - - Number Rule Preceeds -------------------------------------------------------- - 0 big_number more numbers - 1 namespace_spec a namespace - 2 fun_local_spec a class local to a function - 3 template_spec a template spec - 4 fun_local_spec a scope id - 5 namespace_spec a class - 6 arg_spec a class object as an argument - -Type Letters - - - Letter Rule Type -------------------------------------------------------- - .F function_name function - .f function_name member function - .s function_name static member function - .O function_name operator - .o function_name operator member - .D global_data_name global data - .d global_data_name static member data - .P internal_name name, private to compiler - .X internal_name a compiler extension - .V internal_name virtual table - -Naming convention frequently, but not always, followed: - - (anything)_size a big_number giving size of the next item - - (anything)_spec an item, including its size, e.g.: class_spec - - (anything)_specN same as (anything)_spec but with optional - name space - -*/ - -%% - -static char *out_buffer; -static int obx = 0; /* out_buffer index */ - -static void put_characters(char *s, size_t len) -{ - size_t i; - for (i = 0; i < len; ++i) - out_buffer[obx++] = s[i]; -} - -#define put_string(s) \ -{ \ - put_characters(s, strlen(s)); \ -} - -static void print_simple_type(char t) -{ - switch(t) { - - case 'v': - put_characters("void", 4); - break; - - case 'c': - put_characters("char", 4); - break; - - case 's': - put_characters("short", 5); - break; - - case 'i': - put_characters("int", 3); - break; - - case 'l': - put_characters("long", 4); - break; - - case 'f': - put_characters("float", 5); - break; - - case 'd': - put_characters("double", 6); - break; - - case 'D': - put_characters("long double", 11); - break; - - case 'L': - put_characters("long long", 9); - break; - - case 'e': - put_characters("...", 3); - break; - - case 'w': - put_characters("wchar_t", 7); - break; - - case 'G': - put_characters("T", 1); - break; - } -} - -static void print_class(NDEM_class *, int); -static void print_function_args(NDEM_arg *); -static void print_name(NDEM_name *); - -static void print_modifier(NDEM_modifier mod) -{ - if (mod.is_const) put_characters("const ", 6); - if (mod.is_signed) put_characters("signed ", 7); - if (mod.is_unsigned) put_characters("unsigned ", 9); - if (mod.is_volatile) put_characters("volatile ", 9); -} - -/* print modifier(s) of pointers */ -static void print_p_modifier(NDEM_modifier mod) -{ - if (mod.is_const) put_characters(" const", 6); - if (mod.is_volatile) put_characters(" volatile", 9); -} - -static void print_arg(NDEM_arg *arg) -{ - if (! arg) return; - - switch(arg->arg_type) { - - case NDEM_basic_type: - print_modifier(arg->modifier); - print_simple_type(arg->arg_data.basic_t); - break; - - case NDEM_user_defined_type: - print_modifier(arg->modifier); - print_class(arg->arg_data.user_defined_t, 1); - break; - - case NDEM_function_ptr: - print_arg(arg->arg_data.function_ptr->return_t); - put_characters(" (", 2); - if (arg->arg_data.function_ptr->qual_class) - { - print_class(arg->arg_data.function_ptr->qual_class, 1); - put_characters("::", 2); - } - print_arg(arg->arg_data.function_ptr->decls); - put_characters(")", 1); - print_function_args(arg->arg_data.function_ptr->f_args); - print_p_modifier(arg->modifier); - break; - - case NDEM_mem_data_ptr: - print_arg(arg->arg_data.mem_data_ptr->mem_data_t); - put_characters(" ", 1); - print_class(arg->arg_data.mem_data_ptr->qual_class, 1); - put_characters("::", 2); - break; - - case NDEM_decl: - /* The last node in function pointer declarator list is NULL. - */ - if (arg->arg_data.decl.real_arg) - print_arg(arg->arg_data.decl.real_arg); - switch(arg->arg_data.decl.decl_type) { - - case NDEM_pointer: - put_characters("*", 1); - break; - - case NDEM_reference: - put_characters("&", 1); - break; - - case NDEM_array: - put_characters("[", 1); - if (arg->arg_data.decl.array_size) - put_string(arg->arg_data.decl.array_size) - put_characters("]", 1); - break; - } - print_p_modifier(arg->modifier); - break; - - case NDEM_i_const: - if (arg->arg_data.pt_constant) - put_string(arg->arg_data.pt_constant) - else - put_characters("0", 1); - break; - - case NDEM_p_const: - put_characters("&", 1); - print_name(arg->arg_data.temp_p_arg); - break; - - case NDEM_abbrev_N: - case NDEM_abbrev_T: - /* should never come to here! */ - default: - break; - } -} - -static void flat_args(NDEM_arg *in, NDEM_arg **arg_arr, int *n_ptr) -{ - int i, n = 0; - - while (in) - { - if (in->arg_type == NDEM_abbrev_T || in->arg_type == NDEM_abbrev_N) - { - /* first align with arg_arr index... */ - in->arg_data.abbrev_rec.param_number -= 1; - - if (in->arg_data.abbrev_rec.param_number >= n) - { - /* something's wrong. skip the argument */ - in = in->next; - break; - } - if (in->arg_type == NDEM_abbrev_T) - arg_arr[n++] = arg_arr[in->arg_data.abbrev_rec.param_number]; - else - for (i = 0; i < in->arg_data.abbrev_rec.repetition_number; i++) - arg_arr[n++] = arg_arr[in->arg_data.abbrev_rec.param_number]; - } - else - arg_arr[n++] = in; - in = in->next; - } - *n_ptr = n; -} - -#define MAX_ARG 300 -static const int arg_array_size = sizeof(NDEM_arg *) * MAX_ARG; - -static void print_template_args(NDEM_arg *arg) -{ - NDEM_arg **new_arg_list; - int no_of_args, i; - - if (! arg) - { - put_characters("<?>", 3); - return; - } - - put_characters("<", 1); - new_arg_list = allocate(arg_array_size); - flat_args(arg, new_arg_list, &no_of_args); - - /* deallocate the excess memory... - */ - deallocate(arg_array_size - sizeof(NDEM_arg *) * no_of_args); - - for(i = 0; i < no_of_args; ++i) - { - print_arg(new_arg_list[i]); - if (i < no_of_args - 1) - put_characters(", ", 2); - } - put_characters(">", 1); -} - -static void print_function_args(NDEM_arg *arg) -{ - NDEM_arg **new_arg_list; - int no_of_args, i; - - if (! arg) - { - put_characters("(?)", 3); - return; - } - - put_characters("(", 1); - new_arg_list = allocate(arg_array_size); - flat_args(arg, new_arg_list, &no_of_args); - - /* deallocate the excess memory... - */ - deallocate(arg_array_size - sizeof(NDEM_arg *) * no_of_args); - - for(i = 0; i < no_of_args; ++i) - { - print_arg(new_arg_list[i]); - if (i < no_of_args - 1) - put_characters(", ", 2); - } - put_characters(")", 1); -} - -static void print_class(NDEM_class *cl, int full_qual_name) -{ - if (! cl) return; - if (cl->qual_class && full_qual_name) - { - print_class(cl->qual_class, full_qual_name); - put_characters("::", 2); - } - put_string(cl->raw_class_name) - if (cl->t_args) - print_template_args(cl->t_args); -} - -static void print_name(NDEM_name *name) -{ - if (! name) return; - - switch (name->type) { - - case NDEM_constructor: - print_class(name->qual_class, 1); - put_characters("::", 2); - print_class(name->qual_class, 0); - print_function_args(name->f_args); - print_p_modifier(name->f_modifier); - break; - - case NDEM_destructor: - print_class(name->qual_class, 1); - put_characters("::~", 3); - print_class(name->qual_class, 0); - print_function_args(name->f_args); - print_p_modifier(name->f_modifier); - break; - - case NDEM_operator: - case NDEM_conversion: - if (name->qual_class) - { - if (name->f_modifier.is_static) - put_characters("static ", 7); - print_class(name->qual_class, 1); - put_characters("::", 2); - } - put_characters("operator ", 9); - if (name->type != NDEM_conversion) - put_string(name->raw_name) - else - print_arg(name->conv_t); - print_function_args(name->f_args); - if (name->qual_class) - print_p_modifier(name->f_modifier); - break; - - case NDEM_static_constructor: - case NDEM_static_destructor: - case NDEM_other: - if (name->qual_class) - { - if (name->f_modifier.is_static) - put_characters("static ", 7); - print_class(name->qual_class, 1); - put_characters("::", 2); - } - put_string(name->raw_name) - if (name->f_args) - { - print_function_args(name->f_args); - if (name->qual_class) - print_p_modifier(name->f_modifier); - } - break; - - case NDEM_unnamed_arg: - default: - break; - } -} - -static void print_global_name(NDEM_name *name) -{ - print_name(name); - put_characters("\0", 1); /* insert the ending '\0' */ -} - -static char *in_buffer; -static int ibx; /* in_buffer index */ -static size_t in_len = 0; /* symbol length */ - -static void startup(char *in, char *mem, size_t mem_size) -{ - if (in) { - in_buffer = in; - ibx = ll_id_size = sk_top = 0; - in_len = strlen(in); - } - mem_reservoir = mem; - (void) memset(mem_reservoir, 0, mem_size); -} - -int yylex(void) -{ - - if (ibx + (ll_id_size? ll_id_size - 1 : 0) >= in_len) - return 0; - - if (! ll_id_size) - return (ll_cur_char = in_buffer[ibx++]); - else - { - yytext = in_buffer + ibx; - ibx += ll_id_size; - ll_id_size = 0; - return IDENTIFIER; - } -} - - -int demangle(char *in, char *out) -{ - if (in == NULL || !*in || out == NULL) return -1; - - if (CHECK_PREFIX(in)) - { - startup(in, name_buffer, BUFSIZE); - if (yyparse() == 0) - { - out_buffer = out; - obx = 0; /* reset out_buffer index */ - print_global_name(result); - return 0; - } - else - { - /* definitely not a cfront name! */ - (void) strcpy(out, in); - return -1; - } - } - - /* Not a cafe symbol, try cfront demangler... */ - return cfront_demangle(in, out); -} - -static void yyerror(char *msg) -{ - (void) msg; -} - - -/* The code below is provided for tools nm, prof, and gprof. -*/ - -char *cafe_demangle(char *in, char *out) -{ - if (in == NULL || !*in || out == NULL) return in; - - if (CHECK_PREFIX(in)) - { - startup(in, name_buffer, BUFSIZE); - if (yyparse() == 0) - { - out_buffer = out; - obx = 0; - print_global_name(result); - return out; - } - } - - /* not a cafe symbol... */ - return in; -} diff --git a/usr/src/cmd/sgs/sgsdemangler/common/dem.c b/usr/src/cmd/sgs/sgsdemangler/common/dem.c deleted file mode 100644 index a087d3ba22..0000000000 --- a/usr/src/cmd/sgs/sgsdemangler/common/dem.c +++ /dev/null @@ -1,1670 +0,0 @@ -/* - * 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 - * or http://www.opensolaris.org/os/licensing. - * 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 - */ -#pragma ident "%Z%%M% %I% %E% SMI" - -/******************************************************************************* - -C++ source for the C++ Language System, Release 3.0. This product -is a new release of the original cfront developed in the computer -science research center of AT&T Bell Laboratories. - -Copyright (c) 1991 AT&T and UNIX System Laboratories, Inc. -Copyright (c) 1984, 1989, 1990 AT&T. All Rights Reserved. - -*******************************************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <string.h> -#include "cafe_dem.h" - -/************************* CUSTOMIZATION SECTION *************************/ - -#ifndef ELF_OBJ -static int clip_under = 1; /* ignore first "_" on names */ -#else -static int clip_under = 0; -#endif - -#define SP_ALIGN 0x4 /* alignment of dynamic space blocks */ - -/*#define DEM_MAIN*/ /* set if want standalone program */ - -/************************************************************************/ - -#define MAXLINE 2048 /* general buffer use */ - -#define MAXARG 400 /* max arguments in a function */ - -#define STRCMP(s, t) ((s)[0] != (t)[0] || strcmp((s), (t)) != 0) - -static char* spbase; -static char cc; -static char* base; -static int baselen; -#define gc() {cc = baselen >= 1 ? *base++ : 0, baselen--;} - -static int waserror = 0; - -#define MAXSTACK 200 -static char* stackp[MAXSTACK]; -static int stackl[MAXSTACK]; -static char stackc[MAXSTACK]; -static int sp = -1; - -#define ERROR() {waserror = 1; return NULL;} - -/************************* UTILITIES *************************/ - -/* fatal errors */ -static void fatal(char* msg, char* arg1, char* arg2) -{ - char buf[MAXLINE]; - - (void) sprintf(buf, msg, arg1, arg2); - (void) fprintf(stderr, "demangle fatal error: %s\n", buf); - - exit(1); -} - -/* get space */ -static char* gs(size_t s) -{ - char* p; - - if (s < 1) - fatal("bad argument to gs()", (char*)0, (char*)0); - - /* align space on SP_ALIGN boundary */ - - while ((unsigned long)spbase & (SP_ALIGN - 1)) - spbase++; - - p = spbase; - spbase += s; - - return p; -} - -/* copy a string */ -static char* copy(char* s) -{ - char* p; - - if (s == NULL || !*s) - fatal("bad argument to copy()", (char*)0, (char*)0); - - p = gs(strlen(s) + 1); - (void) strcpy(p, s); - return p; -} - -/************************* DEMANGLE UTILITIES *************************/ - -/* push a string to scan */ -static void push(char* s, int n) -{ - if (s == NULL || !*s || n < 1) - fatal("bad argument to push()", (char*)0, (char*)0); - if (sp + 1 >= MAXSTACK) - fatal("overflow of stack in push()", (char*)0, (char*)0); - - sp++; - stackp[sp] = base; - stackl[sp] = baselen; - stackc[sp] = cc; - base = s; - baselen = n; - gc(); -} - -static void pop() -{ - if (sp < 0) - fatal("bad argument to pop()", (char*)0, (char*)0); - - base = stackp[sp]; - baselen = stackl[sp]; - cc = stackc[sp]; - sp--; -} - -/************************* DEMANGLER *************************/ - -/* get a class name */ -static DEMARG* getarglist(); -static DEMCL* getclass() -{ - int n; - char nbuf[MAXLINE]; - int i; - int j; - int iter; - DEMCL* p; - DEMCL* clhead; - DEMCL* curr; - DEMARG* ap; - - iter = 1; - clhead = NULL; - curr = NULL; - - /* fix for ambiguity in encoding */ - - i = 0; - if (isdigit(base[0])) { - i = 1; - if (isdigit(base[1])) - i = 2; - } - if (isdigit(cc) && base[i] == 'Q' && isdigit(base[i + 1]) && - base[i + 2] == '_') { - gc(); - if (i) - gc(); - if (i == 2) - gc(); - } - - /* might be nested class */ - - if (cc == 'Q') { - gc(); - if (!isdigit(cc)) - ERROR(); - iter = cc - '0'; - if (iter < 1) - ERROR(); - gc(); - if (cc != '_') - ERROR(); - gc(); - } - - /* grab number of classes expected */ - - while (iter-- > 0) { - - /* get a class */ - - if (!isdigit(cc)) - ERROR(); - n = cc - '0'; - gc(); - if (isdigit(cc)) { - n = n * 10 + cc - '0'; - gc(); - } - if (isdigit(cc)) { - n = n * 10 + cc - '0'; - gc(); - } - if (n < 1) - ERROR(); - for (i = 0; i < n; i++) { - if (!isalnum(cc) && cc != '_') - ERROR(); - nbuf[i] = cc; - gc(); - } - nbuf[i] = 0; - p = (DEMCL*)gs(sizeof(DEMCL)); - p->rname = copy(nbuf); - p->clargs = NULL; - - /* might be a template class */ - - for (j = 0; j < i; j++) { - if (nbuf[j] == '_' && nbuf[j + 1] == '_' && - nbuf[j + 2] == 'p' && nbuf[j + 3] == 't') - break; - } - if (j == 0) - ERROR(); - if (j == i) { - p->name = copy(nbuf); - } - else { - if (nbuf[j + 4] != '_' || nbuf[j + 5] != '_') - ERROR(); - nbuf[j] = 0; - p->name = copy(nbuf); - j += 6; - if (!isdigit(nbuf[j])) - ERROR(); - n = nbuf[j] - '0'; - j++; - if (isdigit(nbuf[j])) { - n = n * 10 + nbuf[j] - '0'; - j++; - } - if (isdigit(nbuf[j])) { - n = n * 10 + nbuf[j] - '0'; - j++; - } - if (n < 2) - ERROR(); - if (nbuf[j] != '_') - ERROR(); - j++; - n--; - if (!nbuf[j]) - ERROR(); - - /* get arguments for template class */ - - push(nbuf + j, n); - if ((ap = getarglist()) == NULL || cc) - ERROR(); - pop(); - p->clargs = ap; - } - p->next = NULL; - - /* link in to list */ - - if (clhead != NULL) { - curr->next = p; - curr = p; - } - else { - clhead = p; - curr = clhead; - } - } - - return clhead; -} - -/* copy an argument */ -static DEMARG* arg_copy(DEMARG* p) -{ - DEMARG* p2; - - if (p == NULL) - fatal("bad argument to arg_copy()", (char*)0, (char*)0); - - p2 = (DEMARG*)gs(sizeof(DEMARG)); - p2->mods = p->mods; - p2->base = p->base; - p2->arr = p->arr; - p2->func = p->func; - p2->clname = p->clname; - p2->mname = p->mname; - p2->lit = p->lit; - p2->ret = p->ret; - p2->next = NULL; - - return p2; -} - -/* get an argument */ -static DEMARG* getarg(int acmax, DEMARG* arg_cache[], int* ncount) -{ - char mods[100]; - int mc; - int type; - static DEMARG* p; - DEMCL* clp; - long n; - DEMARG* farg; - DEMARG* fret; - DEMARG* getarglist(); - char litbuf[MAXLINE]; - size_t lp; - int foundx; - long arrdim[100]; - int arrp; - int i; - int wasm; - int waslm; - char buf[MAXLINE]; - char buf2[MAXLINE]; - void dem_printcl(); - DEMCL* clist[100]; - int clc; - int ic; - - /* might be stuff remaining from Nnn */ - - if (ncount != NULL && *ncount > 0) { - (*ncount)--; - return arg_copy(p); - } - - mc = 0; - type = 0; - clp = NULL; - farg = NULL; - fret = NULL; - lp = 0; - foundx = 0; - arrp = 0; - wasm = 0; - clc = 0; - - /* get type */ - - while (!type) { - switch (cc) { - - /* modifiers and declarators */ - - case 'X': - gc(); - foundx = 1; - break; - case 'U': - case 'C': - case 'V': - case 'S': - case 'P': - case 'R': - mods[mc++] = cc; - gc(); - break; - - /* fundamental types */ - - case 'v': - case 'c': - case 's': - case 'i': - case 'l': - case 'f': - case 'd': - case 'r': - case 'e': - case 'G': - type = cc; - gc(); - break; - - /* arrays */ - - case 'A': - mods[mc++] = cc; - gc(); - if (!isdigit(cc)) - ERROR(); - n = cc - '0'; - gc(); - while (isdigit(cc)) { - n = n * 10 + cc - '0'; - gc(); - } - if (cc != '_') - ERROR(); - gc(); - arrdim[arrp++] = n; - break; - - /* functions */ - - case 'F': - type = cc; - gc(); - if ((farg = getarglist()) == NULL) - ERROR(); - if (cc != '_') - ERROR(); - gc(); - if ((fret = getarg(-1, (DEMARG**)0, (int*)0)) == NULL) - ERROR(); - break; - - /* pointers to member */ - - case 'M': - mods[mc++] = cc; - wasm = 1; - gc(); - if ((clist[clc++] = getclass()) == NULL) - ERROR(); - break; - - /* repeat previous argument */ - - case 'T': - gc(); -tcase: - if (!isdigit(cc)) - ERROR(); - n = cc - '0'; - gc(); - if (n < 1) - ERROR(); - if (arg_cache == NULL || n - 1 > acmax) - ERROR(); - p = arg_copy(arg_cache[n - 1]); - return p; - - /* repeat previous argument N times */ - - case 'N': - gc(); - if (!isdigit(cc)) - ERROR(); - if (ncount == NULL) - ERROR(); - *ncount = cc - '0' - 1; - if (*ncount < 0) - ERROR(); - gc(); - goto tcase; - - /* class, struct, union, enum */ - - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': case 'Q': - if ((clp = getclass()) == NULL) - ERROR(); - type = 'C'; - break; - - default: - return NULL; - } - } - - /* template literals */ - - if (type && foundx) { - n = 0; - waslm = 0; - if (cc == 'L' && base[0] == 'M') { - gc(); - gc(); - while (cc != '_' && cc) - gc(); - if (!cc) - ERROR(); - gc(); - while (cc != '_' && cc) - gc(); - if (!cc) - ERROR(); - gc(); - n = cc - '0'; - gc(); - if (isdigit(cc)) { - n = n * 10 + cc - '0'; - gc(); - } - if (isdigit(cc)) { - n = n * 10 + cc - '0'; - gc(); - } - waslm = 1; - } - else if (cc == 'L') { - gc(); - if (!isdigit(cc)) - ERROR(); - n = cc - '0'; - gc(); - if (isdigit(cc) && base[0] == '_') { - n = n * 10 + cc - '0'; - gc(); - gc(); - } - if (cc == 'n') { - gc(); - n--; - litbuf[lp++] = '-'; - } - } - else if (cc == '0') { - n = 1; - } - else if (isdigit(cc)) { - n = cc - '0'; - gc(); - if (isdigit(cc)) { - n = n * 10 + cc - '0'; - gc(); - } - } - else { - ERROR(); - } - if (!n && waslm) { - (void) strcpy(litbuf, "0"); - lp = 1; - } - else { - ic = -1; - while (n-- > 0) { - if (!isalnum(cc) && cc != '_') - ERROR(); - litbuf[lp++] = cc; - gc(); - if (n > 0 && lp >= 2 && - litbuf[lp - 1] == '_' && litbuf[lp - 2] == '_') { - if ((clist[ic = clc++] = getclass()) == NULL) - ERROR(); - litbuf[lp - 1] = 0; - litbuf[lp - 2] = 0; - lp -= 2; - break; - } - } - litbuf[lp] = 0; - if ((wasm && waslm) || ic >= 0) { - dem_printcl(clist[ic >= 0 ? ic : 0], buf2); - (void) sprintf(buf, "%s::%s", buf2, litbuf); - (void) strcpy(litbuf, buf); - lp = strlen(litbuf); - } - } - } - - mods[mc] = 0; - litbuf[lp] = 0; - p = (DEMARG*)gs(sizeof(DEMARG)); - p->mods = mc ? copy(mods) : NULL; - p->lit = lp ? copy(litbuf) : NULL; - if (arrp > 0) { - p->arr = (long*)gs(sizeof(long) * arrp); - for (i = 0; i < arrp; i++) - p->arr[i] = arrdim[i]; - } - else { - p->arr = NULL; - } - /* LINTED */ - p->base = (char)type; - p->func = farg; - p->ret = fret; - p->clname = clp; - if (clc > 0) { - p->mname = (DEMCL**)gs(sizeof(DEMCL*) * (clc + 1)); - for (i = 0; i < clc; i++) - p->mname[i] = clist[i]; - p->mname[clc] = NULL; - } - else { - p->mname = NULL; - } - p->next = NULL; - - return p; -} - -/* get list of arguments */ -static DEMARG* getarglist() -{ - DEMARG* p; - DEMARG* head; - DEMARG* curr; - DEMARG* arg_cache[MAXARG]; - int acmax; - int ncount; - - head = NULL; - curr = NULL; - - acmax = -1; - ncount = 0; - - for (;;) { - - /* get the argument */ - - p = getarg(acmax, arg_cache, &ncount); - if (p == NULL) { - if (waserror) - return NULL; - return head; - } - - /* cache it for Tn and Nnn */ - - arg_cache[++acmax] = p; - if (curr == NULL) { - head = p; - curr = head; - } - else { - curr->next = p; - curr = p; - } - } -} - -/* entry point for demangling */ -int dem(char* s, DEM* p, char* buf) -{ - char nbuf[MAXLINE]; - int nc; - long n; - char* t; - char* t2; - char* t3; - char* ob; - int flag; - int cuflag; - char buf2[MAXLINE]; - enum DEM_TYPE dt; - - if (s == NULL || p == NULL || buf == NULL) - return -1; - - cuflag = 0; - - if (clip_under && *s == '_') - s++, cuflag = 1; - - if (!*s) - return -1; - - /* set up space and input buffer management */ - - spbase = buf; - sp = -1; - waserror = 0; - - p->fargs = NULL; - p->cl = NULL; - p->sc = 0; - p->args = NULL; - p->f = NULL; - p->vtname = NULL; - p->slev = -1; - p->type = DEM_NONE; - - /* special case local variables */ - - if (cuflag) - s--; - if (s[0] == '_' && s[1] == '_' && isdigit(s[2])) { - t = s + 2; - n = 0; - while (isdigit(*t)) { - n = n * 10 + *t - '0'; - t++; - } - if (*t) { - p->f = copy(t); - /* LINTED */ - p->slev = (short)n; - goto done2; - } - } - if (cuflag) - s++; - - /* special case sti/sti/ptbl */ - - if (s[0] == '_' && s[1] == '_' && - (!strncmp(s, "__sti__", 7) || !strncmp(s, "__std__", 7) || - !strncmp(s, "__ptbl_vec__", 12))) { - p->sc = s[4]; - t = (s[2] == 's' ? s + 7 : s + 12); - while (*t == '_') - t++; - p->f = copy(t); - if ((t2 = strstr(p->f, "_cc_")) != NULL) - nc = 3; - else if ((t2 = strstr(p->f, "_c_")) != NULL) - nc = 2; - else if ((t2 = strstr(p->f, "_C_")) != NULL) - nc = 2; - else if ((t2 = strstr(p->f, "_cxx_")) != NULL) - nc = 4; - else if ((t2 = strstr(p->f, "_h_")) != NULL) - nc = 2; - if (t2) - *(t2+nc) = 0; - cc = 0; - goto done2; - } - - /* special case type names */ - - if (cuflag) - s--; - t = s; - flag = 0; - while (t[0] && (t[0] != '_' || t == s || t[-1] != '_')) - t++; - if (t[0] == '_' && t[1] == 'p' && t[2] == 't' && - t[3] == '_' && t[4] == '_') - flag = 1; - if (t[0] == '_' && t[1] == '_' && t[2] == 'p' && t[3] == 't' && - t[4] == '_' && t[5] == '_') - flag = 1; - if (!flag) { - t = s; - if ((t[0] == '_' && t[1] == '_' && t[2] == 'Q' && - isdigit(t[3]) && t[4] == '_')) - flag = 2; - } - if (flag) { - sp = -1; - waserror = 0; - if (flag == 1) { - (void) sprintf(buf2, "%ld%s", strlen(s), s); - push(buf2, 9999); - } - else { - push(s + 2, 9999); - } - if ((p->cl = getclass()) == NULL) - return -1; - cc = 0; - goto done2; - } - if (cuflag) - s++; - - sp = -1; - push(s, 9999); - waserror = 0; - - /* get function name */ - - nc = 0; - nbuf[0] = 0; - while (isalnum(cc) || cc == '_') { - nbuf[nc++] = cc; - nbuf[nc] = 0; - if (!base[0] || - (base[0] == '_' && base[1] == '_' && base[2] != '_')) { - gc(); - break; - } - gc(); - - /* conversion operators */ - - if (!STRCMP(nbuf, "__op")) { - ob = base - 1; - if ((p->fargs = getarg(-1, (DEMARG**)0, (int*)0)) == NULL) - return -1; - while (ob < base - 1) - nbuf[nc++] = *ob++; - nbuf[nc] = 0; - break; - } - } - if (!isalpha(nbuf[0]) && nbuf[0] != '_') - return -1; - - /* pick off delimiter */ - - if (cc == '_' && base[0] == '_') { - gc(); - gc(); - if (!cc) - return -1; - } - - /* get class name */ - - if (isdigit(cc) || cc == 'Q') { - if ((p->cl = getclass()) == NULL) - return -1; - } - - /* a function template */ - - else if (cc == 'p' && !strncmp(base, "t__F", 4)) { - gc(); - gc(); - gc(); - gc(); - gc(); - if (!isdigit(cc)) - return -1; - n = cc - '0'; - gc(); - if (isdigit(cc)) { - n = n * 10 + cc - '0'; - gc(); - } - if (isdigit(cc)) { - n = n * 10 + cc - '0'; - gc(); - } - if (n < 1) - return -1; - while (n-- > 0) { - if (!isalnum(cc) && cc != '_') - return -1; - gc(); - } - if (cc != '_' || base[0] != '_') - return -1; - gc(); - gc(); - } - - if (!STRCMP(nbuf, "__vtbl")) { - if (cc == '_' && base[0] == '_' && base[1]) - p->vtname = copy(base + 1); - goto done; - } - - /* const/static member functions */ - - if ((cc == 'C' || cc == 'S') && base[0] == 'F') { - p->sc = cc; - gc(); - } - - /* get arg list for function */ - - if (cc == 'F') { - gc(); - if ((p->args = getarglist()) == NULL) - return -1; - } - -done: - if ((cc && STRCMP(nbuf, "__vtbl")) || waserror) - return -1; - - p->f = copy(nbuf); - -done2: - - /* figure out type we got */ - - dt = DEM_NONE; - if (p->sc) { - switch (p->sc) { - case 'i': - dt = DEM_STI; - break; - case 'd': - dt = DEM_STD; - break; - case 'b': - dt = DEM_PTBL; - break; - case 'C': - dt = DEM_CMFUNC; - break; - case 'S': - dt = DEM_SMFUNC; - break; - default: - fatal("bad type set for p->sc", (char*)0, (char*)0); - break; - } - } - else if (p->slev != -1) { - dt = DEM_LOCAL; - } - else if (p->args != NULL) { - if (p->fargs != NULL) { - dt = DEM_OMFUNC; - } - else if (p->cl != NULL) { - t3 = p->f; - if (t3[0] == '_' && t3[1] == '_') { - if (t3[2] == 'c' && t3[3] == 't' && !t3[4]) - dt = DEM_CTOR; - else if (t3[2] == 'd' && t3[3] == 't' && - !t3[4]) - dt = DEM_DTOR; - else - dt = DEM_MFUNC; - } - else { - dt = DEM_MFUNC; - } - } - else { - dt = DEM_FUNC; - } - } - else if (p->f == NULL && p->cl != NULL) { - if (p->cl->clargs != NULL) - dt = DEM_TTYPE; - else - dt = DEM_CTYPE; - } - else if (p->f != NULL) { - if (p->cl != NULL) { - t3 = p->f; - if (t3[0] == '_' && t3[1] == '_' && t3[2] == 'v' && - t3[3] == 't' && t3[4] == 'b' && t3[5] == 'l' && - !t3[6]) - dt = DEM_VTBL; - else - dt = DEM_MDATA; - } - else { - dt = DEM_DATA; - } - } - - if (dt == DEM_NONE) - fatal("cannot characterize type of input", (char*)0, (char*)0); - - p->type = dt; - - return 0; -} - -/************************* PRINT AN UNMANGLED NAME *************************/ - -/* format a class name */ -void dem_printcl(DEMCL* p, char* buf) -{ - int i; - char buf2[MAXLINE]; - void dem_printarglist(); - - if (p == NULL || buf == NULL) - fatal("bad argument to dem_printcl()", (char*)0, (char*)0); - - buf[0] = 0; - i = 0; - while (p != NULL) { - i++; - - /* handle nested */ - - if (i > 1) - (void) strcat(buf, "::"); - (void) strcat(buf, p->name); - - /* template class */ - - if (p->clargs != NULL) { - if (buf[strlen(buf) - 1] == '<') - (void) strcat(buf, " "); - (void) strcat(buf, "<"); - dem_printarglist(p->clargs, buf2, 0); - (void) strcat(buf, buf2); - if (buf[strlen(buf) - 1] == '>') - (void) strcat(buf, " "); - (void) strcat(buf, ">"); - } - p = p->next; - } -} - -/* format an argument list */ -void dem_printarglist(DEMARG* p, char* buf, int sv) -{ - int i; - char buf2[MAXLINE]; - void dem_printarg(); - - if (p == NULL || buf == NULL || sv < 0 || sv > 1) - fatal("bad argument to dem_printarglist()", (char*)0, (char*)0); - - /* special case single "..." argument */ - - if (p->base == 'v' && p->mods == NULL && p->next != NULL && - p->next->base == 'e' && p->next->next == NULL) { - (void) strcpy(buf, "..."); - return; - } - - /* special case single "void" argument */ - - if (p->base == 'v' && p->mods == NULL) { - (void) strcpy(buf, "void"); - return; - } - - buf[0] = 0; - i = 0; - while (p != NULL) { - i++; - if (i > 1) - (void) strcat(buf, p->base == 'e' ? " " : ","); - dem_printarg(p, buf2, sv); - (void) strcat(buf, buf2); - p = p->next; - } -} - -/* format a single argument */ -void dem_printarg(DEMARG* p, char* buf, int f) -{ - char* t; - char bufc[MAXLINE]; - char bufc2[MAXLINE]; - char farg[MAXLINE]; - char fret[MAXLINE]; - char* m; - char* mm; - char pref[MAXLINE]; - int arrindx; - long dim; - char scr[MAXLINE]; - char ptrs[MAXLINE]; - int i; - int sv; - char* s; - char* trail; - int clc; - - if (p == NULL || buf == NULL || f < 0 || f > 1) - fatal("bad argument to dem_printarg()", (char*)0, (char*)0); - - /* format the underlying type */ - - sv = !f; - - switch (p->base) { - - /* fundamental types */ - - case 'v': - t = "void"; - break; - case 'c': - t = "char"; - break; - case 's': - t = "short"; - break; - case 'i': - t = "int"; - break; - case 'l': - t = "long"; - break; - case 'f': - t = "float"; - break; - case 'd': - t = "double"; - break; - case 'r': - t = "long double"; - break; - case 'G': - t = "T"; - break; - case 'e': - t = "..."; - sv = 1; - break; - - /* functions */ - - case 'F': - dem_printarg(p->ret, fret, 0); - dem_printarglist(p->func, farg, 0); - break; - - /* class, struct, union, enum */ - - case 'C': - dem_printcl(p->clname, bufc); - t = bufc; - break; - - default: - fatal("bad base type in dem_printarg()", (char*)0, (char*)0); - break; - } - - /* handle modifiers and declarators */ - - pref[0] = 0; - m = p->mods; - if (m == NULL) - m = ""; - - /* const and unsigned */ - - mm = m; - while (*mm) { - if (mm[0] == 'C' && (mm[1] != 'P' && mm[1] != 'R' && mm[1] != 'M') && (mm[1] || p->base != 'F')) { - (void) strcat(pref, "const "); - break; - } - mm++; - } - mm = m; - while (*mm) { - if (*mm == 'U') { - (void) strcat(pref, "unsigned "); - break; - } - mm++; - } - - /* go through modifier list */ - - mm = m; - ptrs[0] = 0; - arrindx = 0; - clc = 0; - while (*mm) { - if (mm[0] == 'P') { - (void) sprintf(scr, "*%s", ptrs); - (void) strcpy(ptrs, scr); - } - else if (mm[0] == 'R') { - (void) sprintf(scr, "&%s", ptrs); - (void) strcpy(ptrs, scr); - } - else if (mm[0] == 'M') { - dem_printcl(p->mname[clc++], bufc2); - (void) sprintf(scr, "%s::*%s", bufc2, ptrs); - (void) strcpy(ptrs, scr); - } - else if (mm[0] == 'C' && mm[1] == 'P') { - (void) sprintf(scr, " *const%s%s", isalnum(ptrs[0]) || ptrs[0] == '_' ? " " : "", ptrs); - (void) strcpy(ptrs, scr); - mm++; - } - else if (mm[0] == 'C' && mm[1] == 'R') { - (void) sprintf(scr, " &const%s%s", isalnum(ptrs[0]) || ptrs[0] == '_' ? " " : "", ptrs); - (void) strcpy(ptrs, scr); - mm++; - } - else if (mm[0] == 'C' && mm[1] == 'M') { - dem_printcl(p->mname[clc++], bufc2); - (void) sprintf(scr, "%s::*const%s%s", bufc2, isalnum(ptrs[0]) || ptrs[0] == '_' ? " " : "", ptrs); - (void) strcpy(ptrs, scr); - mm++; - } - else if (mm[0] == 'A') { - dim = p->arr[arrindx++]; - s = sv ? "" : "@"; - if (!ptrs[0]) { - (void) sprintf(scr, "%s[%ld]", s, dim); - sv = 1; - } - else if (ptrs[0] == '(' || ptrs[0] == '[') { - (void) sprintf(scr, "%s[%ld]", ptrs, dim); - } - else { - (void) sprintf(scr, "(%s%s)[%ld]", ptrs, s, dim); - sv = 1; - } - (void) strcpy(ptrs, scr); - } - else if (mm[0] == 'U' || mm[0] == 'C' || mm[0] == 'S') { - /* ignore */ - } - else { - fatal("bad value in modifier list", (char*)0, (char*)0); - } - mm++; - } - - /* put it together */ - - s = sv ? "" : "@"; - if (p->base == 'F') { - i = 0; - if (ptrs[0] == ' ') - i = 1; - trail = ""; - if (p->mods != NULL && p->mods[strlen(p->mods) - 1] == 'C') - trail = " const"; - if (ptrs[i]) - (void) sprintf(buf, "%s%s (%s%s)(%s)%s", pref, fret, ptrs + i, - s, farg, trail); - else - (void) sprintf(buf, "%s%s %s(%s)%s", pref, fret, s, farg, trail); - } - else { - (void) sprintf(buf, "%s%s%s%s%s", pref, t, ptrs[0] == '(' || isalnum(ptrs[0]) || ptrs[0] == '_' ? " " : "", ptrs, s); - } - if (p->lit != NULL) { - if (isdigit(p->lit[0]) || p->lit[0] == '-') - (void) sprintf(scr, "(%s)%s", buf, p->lit); - else - (void) sprintf(scr, "&%s", p->lit); - (void) strcpy(buf, scr); - } -} - -struct Ops { - char* encode; - char* name; -}; - -static struct Ops ops[] = { - "__pp", "operator++", - "__as", "operator=", - "__vc", "operator[]", - "__nw", "operator new", - "__dl", "operator delete", - "__rf", "operator->", - "__ml", "operator*", - "__mm", "operator--", - "__oo", "operator||", - "__md", "operator%", - "__mi", "operator-", - "__rs", "operator>>", - "__ne", "operator!=", - "__gt", "operator>", - "__ge", "operator>=", - "__or", "operator|", - "__aa", "operator&&", - "__nt", "operator!", - "__apl", "operator+=", - "__amu", "operator*=", - "__amd", "operator%=", - "__ars", "operator>>=", - "__aor", "operator|=", - "__cm", "operator,", - "__dv", "operator/", - "__pl", "operator+", - "__ls", "operator<<", - "__eq", "operator==", - "__lt", "operator<", - "__le", "operator<=", - "__ad", "operator&", - "__er", "operator^", - "__co", "operator~", - "__ami", "operator-=", - "__adv", "operator/=", - "__als", "operator<<=", - "__aad", "operator&=", - "__aer", "operator^=", - "__rm", "operator->*", - "__cl", "operator()", - NULL, NULL -}; - -/* format a function name */ -void dem_printfunc(DEM* dp, char* buf) -{ - int i; - char buf2[MAXLINE]; - - if (dp == NULL || buf == NULL) - fatal("bad argument to dem_printfunc()", (char*)0, (char*)0); - - if (dp->f[0] == '_' && dp->f[1] == '_') { - - /* conversion operators */ - - if (!strncmp(dp->f, "__op", 4) && dp->fargs != NULL) { - dem_printarg(dp->fargs, buf2, 0); - (void) sprintf(buf, "operator %s", buf2); - } - - /* might be overloaded operator */ - - else { - i = 0; - while (ops[i].encode != NULL && strcmp(ops[i].encode, dp->f)) - i++; - if (ops[i].encode != NULL) - (void) strcpy(buf, ops[i].name); - else - (void) strcpy(buf, dp->f); - } - } - else { - (void) strcpy(buf, dp->f); - } -} - -/* entry point to formatting functions */ -int dem_print(DEM* p, char* buf) -{ - char buf2[MAXLINE]; - char* s; - int t; - - if (p == NULL || buf == NULL) - return -1; - - buf[0] = 0; - - /* type names */ - - if (p->f == NULL && p->cl != NULL) { - dem_printcl(p->cl, buf); - return 0; - } - - /* sti/std */ - - if (p->sc == 'i' || p->sc == 'd') { - (void) sprintf(buf, "%s:__st%c", p->f, p->sc); - return 0; - } - if (p->sc == 'b') { - (void) sprintf(buf, "%s:__ptbl_vec", p->f); - return 0; - } - - /* format class name */ - - buf2[0] = 0; - if (p->cl != NULL) { - dem_printcl(p->cl, buf2); - (void) strcat(buf, buf2); - (void) strcat(buf, "::"); - } - - /* special case constructors and destructors */ - - s = buf2 + strlen(buf2) - 1; - t = 0; - while (s >= buf2) { - if (*s == '>') - t++; - else if (*s == '<') - t--; - else if (*s == ':' && !t) - break; - s--; - } - if (!STRCMP(p->f, "__ct")) { - (void) strcat(buf, s + 1); - } - else if (!STRCMP(p->f, "__dt")) { - (void) strcat(buf, "~"); - (void) strcat(buf, s + 1); - } - else { - dem_printfunc(p, buf2); - (void) strcat(buf, buf2); - } - - /* format argument list */ - - if (p->args != NULL) { - (void) strcat(buf, "("); - dem_printarglist(p->args, buf2, 0); - (void) strcat(buf, buf2); - (void) strcat(buf, ")"); - } - - /* const member functions */ - - if (p->sc == 'C') - (void) strcat(buf, " const"); - - return 0; -} - -/* explain a type */ -char* dem_explain(enum DEM_TYPE t) -{ - switch (t) { - case DEM_STI: - return "static construction function"; - case DEM_STD: - return "static destruction function"; - case DEM_VTBL: - return "virtual table"; - case DEM_PTBL: - return "ptbl vector pointing to vtbls"; - case DEM_FUNC: - return "function"; - case DEM_MFUNC: - return "member function"; - case DEM_SMFUNC: - return "static member function"; - case DEM_CMFUNC: - return "constant member function"; - case DEM_OMFUNC: - return "conversion operator member function"; - case DEM_CTOR: - return "constructor"; - case DEM_DTOR: - return "destructor"; - case DEM_DATA: - return "data"; - case DEM_MDATA: - return "member data"; - case DEM_LOCAL: - return "local variable"; - case DEM_CTYPE: - return "class type"; - case DEM_TTYPE: - return "template type"; - default: - fatal("bad type passed to dem_explain()", (char*)0, (char*)0); - return ""; - } -} - -/* ------------------------------------------------------------------------ */ - -/* demangle in --> out */ -int cfront_demangle(char* in, char* out) -{ - char sbuf[MAXDBUF]; - DEM d; - - if (in == NULL || !*in || out == NULL) - return -1; - - if (dem(in, &d, sbuf) < 0) { - (void) strcpy(out, in); - return -1; - } - - (void) dem_print(&d, out); - - return 0; -} - -/* - The routines below are provided to enable the tools nm, - prof, and gprof to use the demangling function provided - in this file. - Entry point is DemangleAndFormat() --MK -*/ - -#include <string.h> - -static int CheckSpecialCase( char *, DEM *); -static void ProcessVtname( DEM *); -static char *FormatName( char *, char *, char *); - -static char d_buf[512]; -static char *ctor_str = "static constructor function for %s"; -static char *dtor_str = "static destructor function for %s"; -static char *ptbl_str = "pointer to the virtual table vector for %s"; -static char *vtbl_str = "virtual table for class %s"; - -extern char *cafe_demangle(char *, char *); - -char *DemangleAndFormat(char *name, char *format) -{ - char dn[MAXDBUF]; /* demangled name */ - char dn2[MAXDBUF]; /* demangled name */ - DEM dem_struct; - int dem_ret_val; - - char *cafe_out = cafe_demangle(name, dn); - if (cafe_out != name) - { - /* a cafe symbol... - */ - return FormatName(name, cafe_out, format); - } - - dem_ret_val = dem( name, &dem_struct, dn2); - - if ((dem_ret_val < 0) || !(strcmp(name, dn2))) - { /* name not demangled */ - d_buf[0] = '\0'; - } - else /* name demangled by dem() */ - { - if (CheckSpecialCase( name, &dem_struct)) - { - name = FormatName( name, d_buf, format); - } - else /* not a special case */ - { - (void) dem_print( &dem_struct, dn); - name = FormatName( name, dn, format); - } - } - - return (name); -} /* DemangleAndFormat */ - - -/* alloc memory and create name in necessary format. - Return name string -*/ -static char *FormatName(char *OldName, char *NewName, char *format) -{ - size_t length = strlen(format) + strlen(NewName) + strlen(OldName) - 3; - char *hold = OldName; - - OldName = (char *)malloc( length ); - (void) sprintf(OldName, format, NewName, hold); - return (OldName); -} - - -/* - Check for special cases: __sti__, _std__, __ptbl_vec__, __vtbl__ - use demP for the procesing - Return 1 if it is a special case, otherwise return 0. -*/ -static int CheckSpecialCase(char *name, DEM *demP) -{ - int retVal = 1; - - if (demP->sc == 'i') /* __sti__ */ - { - (void) sprintf( d_buf, ctor_str, demP->f); - } - else if (demP->sc == 'd') /* __std__ */ - { - (void) sprintf( d_buf, dtor_str, demP->f); - } - else if (demP->sc == 'b') /* __ptbl_vec__ */ - { - (void) sprintf( d_buf, ptbl_str, demP->f); - } - else if (demP->vtname != NULL) /* __vtbl__ with file name */ - { - ProcessVtname( demP); - } - else if (demP->cl != NULL) /* check for __vtbl__ without file name */ - { - if (strncmp( name, "__vtbl__", 8) == 0) - (void) sprintf( d_buf, vtbl_str, demP->cl->name); - else - retVal = 0; /* not a special case */ - } - else - { - retVal = 0; /* not a special case */ - d_buf[0] = '\0'; - } - - return (retVal); -} - - -/* process demP->vtname */ -/* called by CheckSpecialCase() */ - -static void ProcessVtname(DEM *demP) -{ - char *nameString; - char *tail; - size_t len; - int marker; - char saveChar; - - nameString = demP->vtname; - - /* check if mangled name of derived class (a heuristic) */ - /* different possibilities for string demP->vtname: */ - /* (1) 'filename_ext' class name in file */ - /* (2) '%dname' class derived from class */ - /* (3) '%dname__filename_ext' class derived from class in file */ - /* note: the filename itself could start with a digit */ - len = strlen( nameString); - if (*(nameString + len - 2) == '_') - marker = 2; - else if (*(nameString + len - 3) == '_') - marker = 3; - else - marker = 0; - if (!isdigit(*nameString)) /* case (1) */ - { - (void) sprintf( d_buf, vtbl_str, demP->cl ? demP->cl->name : "??"); - (void) strcat( d_buf, " in "); - if (marker > 0) - *(nameString + len - marker) = '.'; - (void) strcat( d_buf, nameString); - if (marker > 0) - *(nameString + len - marker) = '_'; - } - - else if ((tail = strstr( nameString, "__")) == NULL) - { /* could be case (1) or case (2) */ - /* case (1) if filename starts with a digit */ - if (marker == 0) /* case (2) */ - { - while (isdigit( *nameString)) - nameString++; - (void) sprintf( d_buf, vtbl_str, nameString); - (void) strcat( d_buf, " derived from "); - (void) strcat( d_buf, demP->cl ? demP->cl->name : "??"); - } - else /* case (1) */ - { - (void) sprintf( d_buf, vtbl_str, demP->cl ? demP->cl->name : "??"); - (void) strcat( d_buf, " in "); - if (marker > 0) - *(nameString + len - marker) = '.'; - (void) strcat( d_buf, nameString); - if (marker > 0) - *(nameString + len - marker) = '_'; - } - } - - else /* case (3) */ - { - while (isdigit( *nameString)) - nameString++; - saveChar = *(nameString + (tail - nameString)); - *(nameString + (tail - nameString)) = '\0'; - (void) sprintf( d_buf, vtbl_str, nameString); - (void) strcat( d_buf, " derived from "); - (void) strcat( d_buf, demP->cl ? demP->cl->name : "??"); - *(nameString + (tail - nameString)) = saveChar; - tail += 2; /* skip "__" */ - len = strlen( tail); - (void) strcat( d_buf, " in "); - if (marker > 0) - *(tail + len - marker) = '.'; - (void) strcat( d_buf, tail); - if (marker > 0) - *(tail + len - marker) = '_'; - } -} /* ProcessVtname */ - - diff --git a/usr/src/cmd/sgs/sgsdemangler/common/dem.h b/usr/src/cmd/sgs/sgsdemangler/common/dem.h deleted file mode 100644 index 88b726c2e6..0000000000 --- a/usr/src/cmd/sgs/sgsdemangler/common/dem.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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 - * or http://www.opensolaris.org/os/licensing. - * 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 - */ -#pragma ident "%Z%%M% %I% %E% SMI" - -/******************************************************************************* - -C++ source for the C++ Language System, Release 3.0. This product -is a new release of the original cfront developed in the computer -science research center of AT&T Bell Laboratories. - -Copyright (c) 1991 AT&T and UNIX System Laboratories, Inc. -Copyright (c) 1984, 1989, 1990 AT&T. All Rights Reserved. - -*******************************************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct DEMARG DEMARG; -typedef struct DEMCL DEMCL; -typedef struct DEM DEM; - -enum DEM_TYPE { - DEM_NONE, /* placeholder */ - DEM_STI, /* static construction function */ - DEM_STD, /* static destruction function */ - DEM_VTBL, /* virtual table */ - DEM_PTBL, /* ptbl vector */ - DEM_FUNC, /* function */ - DEM_MFUNC, /* member function */ - DEM_SMFUNC, /* static member function */ - DEM_CMFUNC, /* const member function */ - DEM_OMFUNC, /* conversion operator member function */ - DEM_CTOR, /* constructor */ - DEM_DTOR, /* destructor */ - DEM_DATA, /* data */ - DEM_MDATA, /* member data */ - DEM_LOCAL, /* local variable */ - DEM_CTYPE, /* class type */ - DEM_TTYPE, /* template class type */ - - DEM_TYPE_END /* used for cafe support... */ -}; - -struct DEMARG { - char* mods; /* modifiers and declarators (page 123 in */ - /* ARM), e.g. "CP" */ - - long* arr; /* dimension if mod[i] == 'A' else NULL */ - - DEMARG* func; /* list of arguments if base == 'F' */ - /* else NULL */ - - DEMARG* ret; /* return type if base == 'F' else NULL */ - - DEMCL* clname; /* class/enum name if base == "C" */ - - DEMCL** mname; /* class name if mod[i] == "M" */ - /* in argument list (pointers to members) */ - - DEMARG* next; /* next argument or NULL */ - - char* lit; /* literal value for PT arguments */ - /* e.g. "59" in A<59> */ - - char base; /* base type of argument, */ - /* 'C' for class/enum types */ -}; - -struct DEMCL { - char* name; /* name of class or enum without PT args */ - /* e.g. "Vector" */ - - DEMARG* clargs; /* arguments to class, NULL if not PT */ - - char* rname; /* raw class name with __pt__ if PT */ - /* e.g. "A__pt__2_i" */ - - DEMCL* next; /* next class name, NULL if not nested */ -}; - -struct DEM { - enum DEM_TYPE type; /* type of name that was demangled */ - char* f; /* function or data name; NULL if type name */ - /* see page 125 of ARM for predefined list */ - - char* vtname; /* if != NULL name of source file for vtbl */ - - DEMARG* fargs; /* arguments of function name if __opargs__ */ - /* else NULL */ - - DEMCL* cl; /* name of relevant class or enum or NULL */ - /* used also for type-name-only input */ - - DEMARG* args; /* args to function, NULL if data or type */ - - - short slev; /* scope level for local variables or -1 */ - - char sc; /* storage class type 'S' or 'C' or: */ - /* i -> __sti d --> __std */ - /* b -> __ptbl_vec */ -}; - -#define MAXDBUF 8192 - -int demangle(); -int cfront_demangle(); -void dem_printarg(); -void dem_printarglist(); -int dem_print(); -void dem_printfunc(); -int dem(); -void dem_printcl(); -char* dem_explain(); diff --git a/usr/src/cmd/sgs/sgsdemangler/common/demangle.c b/usr/src/cmd/sgs/sgsdemangler/common/demangle.c index 72c2e86d1a..718ec40497 100644 --- a/usr/src/cmd/sgs/sgsdemangler/common/demangle.c +++ b/usr/src/cmd/sgs/sgsdemangler/common/demangle.c @@ -2,9 +2,8 @@ * 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. + * 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 * or http://www.opensolaris.org/os/licensing. @@ -19,16 +18,17 @@ * * CDDL HEADER END */ + /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ + #pragma ident "%Z%%M% %I% %E% SMI" #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> -#include "dem.h" /* * C++ Demangling @@ -36,53 +36,19 @@ #define LIBDEMANGLE "libdemangle.so.1" #define DEMANGLEFUNC "cplus_demangle" -extern char *cafe_demangle(char *, char *); - -/* - * This is a backup routine which uses routine from CAFE - * project. The -3 value is returned when the demangling - * did not succeed. - * (The -1 value is intentionally not used.) - */ -/*ARGSUSED*/ -static int -sgs_cafe_demangle(char *name, char *demangled_name, int limit) -{ - char *cafe_out; - DEM dem_struct; - int dem_ret_val; - - cafe_out = cafe_demangle( - (char *)name, - (char *)demangled_name); - - if (cafe_out != name) { - return (0); - } - - dem_ret_val = dem(name, &dem_struct, demangled_name); - - if (dem_ret_val < 0) - return (-3); - - return (0); -} +#define MAXDBUF 1024 -/* - * - */ char * sgs_demangle(char *name) { static char *demangled_name; - static int (*demangle_func)() = 0; + static int (*demangle_func)() = NULL; static int first_flag = 0; static int size = MAXDBUF; int ret; /* - * If this is the first time called, - * decide which demangling function to use. + * Determine if libdemangle is available. */ if (first_flag == 0) { void *demangle_hand; @@ -92,42 +58,33 @@ sgs_demangle(char *name) demangle_func = (int (*)(int))dlsym( demangle_hand, DEMANGLEFUNC); - if (demangle_func == NULL) - demangle_func = sgs_cafe_demangle; - - /* - * Allocate the buffer - */ - demangled_name = (char *) malloc(size); - if (demangled_name == NULL) - return (name); - first_flag = 1; } /* - * If malloc() failed in the previous call, - * demangle_name is NULL. So the following codes are - * here. + * Pass through name untouched if libdemangle is not available. + */ + if (demangle_func == NULL) + return (name); + + /* + * If this is the first call (or malloc() failed previously) allocate a + * new buffer for storage. */ if (demangled_name == NULL) { size = MAXDBUF; - demangled_name = (char *) malloc(size); + demangled_name = malloc(size); if (demangled_name == NULL) return (name); } /* - * When we use the real one. - * The real function returns -1 when the buffer size - * is not sufficient. - * - * When we use the back up function, it never returns -1. + * libdemangle returns -1 when the buffer size is not sufficient. */ while ((ret = (*demangle_func)(name, demangled_name, size)) == -1) { free(demangled_name); size = size + MAXDBUF; - demangled_name = (char *) malloc(size); + demangled_name = malloc(size); if (demangled_name == NULL) return (name); } diff --git a/usr/src/common/dis/i386/dis_tables.c b/usr/src/common/dis/i386/dis_tables.c index 431591ffa9..181ca9083f 100644 --- a/usr/src/common/dis/i386/dis_tables.c +++ b/usr/src/common/dis/i386/dis_tables.c @@ -2,9 +2,8 @@ * 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. + * 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 * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -1436,7 +1435,7 @@ dtrace_check_override(dis86_t *x, int opindex) { #ifdef DIS_TEXT if (x->d86_seg_prefix) { - strlcat(x->d86_opnd[opindex].d86_prefix, + (void) strlcat(x->d86_opnd[opindex].d86_prefix, x->d86_seg_prefix, PFIXLEN); } #endif @@ -1480,39 +1479,39 @@ dtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex) #ifdef DIS_TEXT switch (wbit) { case MM_OPND: - strlcat(opnd, dis_MMREG[r_m], OPLEN); + (void) strlcat(opnd, dis_MMREG[r_m], OPLEN); break; case XMM_OPND: - strlcat(opnd, dis_XMMREG[r_m], OPLEN); + (void) strlcat(opnd, dis_XMMREG[r_m], OPLEN); break; case SEG_OPND: - strlcat(opnd, dis_SEGREG[r_m], OPLEN); + (void) strlcat(opnd, dis_SEGREG[r_m], OPLEN); break; case CONTROL_OPND: - strlcat(opnd, dis_CONTROLREG[r_m], OPLEN); + (void) strlcat(opnd, dis_CONTROLREG[r_m], OPLEN); break; case DEBUG_OPND: - strlcat(opnd, dis_DEBUGREG[r_m], OPLEN); + (void) strlcat(opnd, dis_DEBUGREG[r_m], OPLEN); break; case TEST_OPND: - strlcat(opnd, dis_TESTREG[r_m], OPLEN); + (void) strlcat(opnd, dis_TESTREG[r_m], OPLEN); break; case BYTE_OPND: if (x->d86_rex_prefix == 0) - strlcat(opnd, dis_REG8[r_m], OPLEN); + (void) strlcat(opnd, dis_REG8[r_m], OPLEN); else - strlcat(opnd, dis_REG8_REX[r_m], OPLEN); + (void) strlcat(opnd, dis_REG8_REX[r_m], OPLEN); break; case WORD_OPND: - strlcat(opnd, dis_REG16[r_m], OPLEN); + (void) strlcat(opnd, dis_REG16[r_m], OPLEN); break; case LONG_OPND: if (x->d86_opnd_size == SIZE16) - strlcat(opnd, dis_REG16[r_m], OPLEN); + (void) strlcat(opnd, dis_REG16[r_m], OPLEN); else if (x->d86_opnd_size == SIZE32) - strlcat(opnd, dis_REG32[r_m], OPLEN); + (void) strlcat(opnd, dis_REG32[r_m], OPLEN); else - strlcat(opnd, dis_REG64[r_m], OPLEN); + (void) strlcat(opnd, dis_REG64[r_m], OPLEN); break; } #endif /* DIS_TEXT */ @@ -1543,7 +1542,7 @@ dtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex) x->d86_opnd[opindex].d86_mode = MODE_NONE; else x->d86_opnd[opindex].d86_mode = MODE_OFFSET; - strlcat(opnd, dis_addr16[mode][r_m], OPLEN); + (void) strlcat(opnd, dis_addr16[mode][r_m], OPLEN); #endif return; } @@ -1593,17 +1592,17 @@ dtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex) if (have_SIB == 0) { if (x->d86_mode == SIZE32) { if (mode == 0) - strlcat(opnd, dis_addr32_mode0[r_m], + (void) strlcat(opnd, dis_addr32_mode0[r_m], OPLEN); else - strlcat(opnd, dis_addr32_mode12[r_m], + (void) strlcat(opnd, dis_addr32_mode12[r_m], OPLEN); } else { if (mode == 0) - strlcat(opnd, dis_addr64_mode0[r_m], + (void) strlcat(opnd, dis_addr64_mode0[r_m], OPLEN); else - strlcat(opnd, dis_addr64_mode12[r_m], + (void) strlcat(opnd, dis_addr64_mode12[r_m], OPLEN); } } else { @@ -1619,12 +1618,12 @@ dtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex) */ if (base == EBP_REGNO && mode == 0) { if (index != ESP_REGNO) { - strlcat(opnd, "(", OPLEN); + (void) strlcat(opnd, "(", OPLEN); need_paren = 1; } } else { - strlcat(opnd, "(", OPLEN); - strlcat(opnd, regs[base], OPLEN); + (void) strlcat(opnd, "(", OPLEN); + (void) strlcat(opnd, regs[base], OPLEN); need_paren = 1; } @@ -1632,12 +1631,12 @@ dtrace_get_operand(dis86_t *x, uint_t mode, uint_t r_m, int wbit, int opindex) * print the index (if any) */ if (index != ESP_REGNO) { - strlcat(opnd, ",", OPLEN); - strlcat(opnd, regs[index], OPLEN); - strlcat(opnd, dis_scale_factor[ss], OPLEN); + (void) strlcat(opnd, ",", OPLEN); + (void) strlcat(opnd, regs[index], OPLEN); + (void) strlcat(opnd, dis_scale_factor[ss], OPLEN); } else if (need_paren) - strlcat(opnd, ")", OPLEN); + (void) strlcat(opnd, ")", OPLEN); } #endif } @@ -1764,9 +1763,9 @@ dtrace_disx86(dis86_t *x, uint_t cpu_mode) goto error; if (opcode1 == 0 && opcode2 == 0 && - x->d86_check_func != NULL && x->d86_check_func()) { + x->d86_check_func != NULL && x->d86_check_func(x->d86_data)) { #ifdef DIS_TEXT - strncpy(x->d86_mneu, ".byte\t0", OPLEN); + (void) strncpy(x->d86_mneu, ".byte\t0", OPLEN); #endif goto done; } @@ -2036,22 +2035,22 @@ dtrace_disx86(dis86_t *x, uint_t cpu_mode) * including the prefixes. */ if (lock_prefix) - strlcat(x->d86_mneu, "lock ", OPLEN); + (void) strlcat(x->d86_mneu, "lock ", OPLEN); if (rep_prefix == 0xf2) - strlcat(x->d86_mneu, "repnz ", OPLEN); + (void) strlcat(x->d86_mneu, "repnz ", OPLEN); else if (rep_prefix == 0xf3) - strlcat(x->d86_mneu, "repz ", OPLEN); + (void) strlcat(x->d86_mneu, "repz ", OPLEN); if (cpu_mode == SIZE64 && addr_size_prefix) - strlcat(x->d86_mneu, "addr32 ", OPLEN); + (void) strlcat(x->d86_mneu, "addr32 ", OPLEN); if (dp->it_adrmode != CBW && dp->it_adrmode != CWD && dp->it_adrmode != XMMSFNC) { if (strcmp(dp->it_name, "INVALID") == 0) goto error; - strlcat(x->d86_mneu, dp->it_name, OPLEN); + (void) strlcat(x->d86_mneu, dp->it_name, OPLEN); if (dp->it_suffix) { char *types[] = {"", "w", "l", "q"}; if (opcode_bytes == 2 && opcode4 == 4) { @@ -2061,8 +2060,10 @@ dtrace_disx86(dis86_t *x, uint_t cpu_mode) break; } x->d86_mneu[i - 1] = *types[opnd_size]; - } else - strlcat(x->d86_mneu, types[opnd_size], OPLEN); + } else { + (void) strlcat(x->d86_mneu, types[opnd_size], + OPLEN); + } } } #endif @@ -2083,7 +2084,7 @@ dtrace_disx86(dis86_t *x, uint_t cpu_mode) case MOVSXZ: #ifdef DIS_TEXT if (rex_prefix == 0) - strncpy(x->d86_mneu, "movzld", OPLEN); + (void) strncpy(x->d86_mneu, "movzld", OPLEN); #endif dtrace_get_modrm(x, &mode, ®, &r_m); dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); @@ -2274,7 +2275,7 @@ mm_shift: dtrace_get_operand(x, mode, r_m, wbit, 1); #ifdef DIS_TEXT if (vbit) { - strlcat(x->d86_opnd[0].d86_opnd, "%cl", OPLEN); + (void) strlcat(x->d86_opnd[0].d86_opnd, "%cl", OPLEN); } else { x->d86_opnd[0].d86_mode = MODE_SIGNED; x->d86_opnd[0].d86_value_size = 1; @@ -2310,7 +2311,7 @@ just_mem: case SWAPGS: if (cpu_mode == SIZE64 && mode == 3 && r_m == 0) { #ifdef DIS_TEXT - strncpy(x->d86_mneu, "swapgs", OPLEN); + (void) strncpy(x->d86_mneu, "swapgs", OPLEN); #endif NOMEM; break; @@ -2520,9 +2521,9 @@ xmmprm: */ if (mode == REG_ONLY) { if (strcmp(dp->it_name, "movlps") == 0) - strncpy(x->d86_mneu, "movhlps", OPLEN); + (void) strncpy(x->d86_mneu, "movhlps", OPLEN); else if (strcmp(dp->it_name, "movhps") == 0) - strncpy(x->d86_mneu, "movlhps", OPLEN); + (void) strncpy(x->d86_mneu, "movlhps", OPLEN); } #endif if (dp->it_adrmode == XMMXIMPL) @@ -2554,7 +2555,7 @@ xmmprm: #ifdef DIS_TEXT if (mode == REG_ONLY) { if (strcmp(dp->it_name, "movhps") == 0) - strncpy(x->d86_mneu, "movlhps", OPLEN); + (void) strncpy(x->d86_mneu, "movlhps", OPLEN); else goto error; } @@ -2630,10 +2631,10 @@ xmmprm: if (pred >= (sizeof (dis_PREDSUFFIX) / sizeof (char *))) goto error; - strncpy(x->d86_mneu, "cmp", OPLEN); - strlcat(x->d86_mneu, dis_PREDSUFFIX[pred], + (void) strncpy(x->d86_mneu, "cmp", OPLEN); + (void) strlcat(x->d86_mneu, dis_PREDSUFFIX[pred], OPLEN); - strlcat(x->d86_mneu, + (void) strlcat(x->d86_mneu, dp->it_name + strlen(dp->it_name) - 2, OPLEN); x->d86_opnd[0] = x->d86_opnd[1]; @@ -2664,19 +2665,19 @@ xmmprm: dtrace_check_override(x, 0); x->d86_numopnds = 2; if (addr_size == SIZE64) { - strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)", + (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)", OPLEN); - strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)", + (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)", OPLEN); } else if (addr_size == SIZE32) { - strlcat(x->d86_opnd[0].d86_opnd, "(%esi)", + (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)", OPLEN); - strlcat(x->d86_opnd[1].d86_opnd, "(%edi)", + (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)", OPLEN); } else { - strlcat(x->d86_opnd[0].d86_opnd, "(%si)", + (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)", OPLEN); - strlcat(x->d86_opnd[1].d86_opnd, "(%di)", + (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)", OPLEN); } #endif @@ -2691,13 +2692,13 @@ xmmprm: x->d86_numopnds = 2; dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 0); if (addr_size == SIZE64) - strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)", + (void) strlcat(x->d86_opnd[1].d86_opnd, "(%rdi)", OPLEN); else if (addr_size == SIZE32) - strlcat(x->d86_opnd[1].d86_opnd, "(%edi)", + (void) strlcat(x->d86_opnd[1].d86_opnd, "(%edi)", OPLEN); else - strlcat(x->d86_opnd[1].d86_opnd, "(%di)", + (void) strlcat(x->d86_opnd[1].d86_opnd, "(%di)", OPLEN); #endif break; @@ -2709,13 +2710,13 @@ xmmprm: dtrace_check_override(x, 0); x->d86_numopnds = 2; if (addr_size == SIZE64) - strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)", + (void) strlcat(x->d86_opnd[0].d86_opnd, "(%rsi)", OPLEN); else if (addr_size == SIZE32) - strlcat(x->d86_opnd[0].d86_opnd, "(%esi)", + (void) strlcat(x->d86_opnd[0].d86_opnd, "(%esi)", OPLEN); else - strlcat(x->d86_opnd[0].d86_opnd, "(%si)", + (void) strlcat(x->d86_opnd[0].d86_opnd, "(%si)", OPLEN); dtrace_get_operand(x, REG_ONLY, EAX_REGNO, wbit, 1); #endif @@ -2733,7 +2734,7 @@ xmmprm: /* jmp/call indirect to memory or register operand */ case INM: #ifdef DIS_TEXT - strlcat(x->d86_opnd[0].d86_prefix, "*", OPLEN); + (void) strlcat(x->d86_opnd[0].d86_prefix, "*", OPLEN); #endif dtrace_rex_adjust(rex_prefix, mode, NULL, &r_m); dtrace_get_operand(x, mode, r_m, LONG_OPND, 0); @@ -2813,7 +2814,7 @@ xmmprm: x->d86_numopnds = 1; dtrace_check_override(x, 0); #ifdef DIS_TEXT - strlcat(x->d86_opnd[0].d86_opnd, "(%dx)", OPLEN); + (void) strlcat(x->d86_opnd[0].d86_opnd, "(%dx)", OPLEN); #endif NOMEM; break; @@ -2854,11 +2855,11 @@ xmmprm: case CBW: #ifdef DIS_TEXT if (opnd_size == SIZE16) - strlcat(x->d86_mneu, "cbtw", OPLEN); + (void) strlcat(x->d86_mneu, "cbtw", OPLEN); else if (opnd_size == SIZE32) - strlcat(x->d86_mneu, "cwtl", OPLEN); + (void) strlcat(x->d86_mneu, "cwtl", OPLEN); else - strlcat(x->d86_mneu, "cltq", OPLEN); + (void) strlcat(x->d86_mneu, "cltq", OPLEN); #endif wbit = LONG_OPND; NOMEM; @@ -2867,11 +2868,11 @@ xmmprm: case CWD: #ifdef DIS_TEXT if (opnd_size == SIZE16) - strlcat(x->d86_mneu, "cwtd", OPLEN); + (void) strlcat(x->d86_mneu, "cwtd", OPLEN); else if (opnd_size == SIZE32) - strlcat(x->d86_mneu, "cltd", OPLEN); + (void) strlcat(x->d86_mneu, "cltd", OPLEN); else - strlcat(x->d86_mneu, "cqtd", OPLEN); + (void) strlcat(x->d86_mneu, "cqtd", OPLEN); #endif wbit = LONG_OPND; NOMEM; @@ -2887,9 +2888,9 @@ xmmprm: /* sfence doesn't take operands */ #ifdef DIS_TEXT if (mode == REG_ONLY) { - strlcat(x->d86_mneu, "sfence", OPLEN); + (void) strlcat(x->d86_mneu, "sfence", OPLEN); } else { - strlcat(x->d86_mneu, "clflush", OPLEN); + (void) strlcat(x->d86_mneu, "clflush", OPLEN); dtrace_rex_adjust(rex_prefix, mode, ®, &r_m); dtrace_get_operand(x, mode, r_m, BYTE_OPND, 0); NOMEM; @@ -2932,7 +2933,7 @@ xmmprm: case F: #ifdef DIS_TEXT x->d86_numopnds = 1; - strlcat(x->d86_opnd[0].d86_opnd, "%st(X)", OPLEN); + (void) strlcat(x->d86_opnd[0].d86_opnd, "%st(X)", OPLEN); x->d86_opnd[0].d86_opnd[4] = r_m + '0'; #endif NOMEM; @@ -2945,8 +2946,8 @@ xmmprm: case FFC: /* case for vbit always = 0 */ #ifdef DIS_TEXT x->d86_numopnds = 2; - strlcat(x->d86_opnd[1 - vbit].d86_opnd, "%st", OPLEN); - strlcat(x->d86_opnd[vbit].d86_opnd, "%st(X)", OPLEN); + (void) strlcat(x->d86_opnd[1 - vbit].d86_opnd, "%st", OPLEN); + (void) strlcat(x->d86_opnd[vbit].d86_opnd, "%st(X)", OPLEN); x->d86_opnd[vbit].d86_opnd[4] = r_m + '0'; #endif NOMEM; @@ -3022,7 +3023,7 @@ done: error: #ifdef DIS_TEXT - strlcat(x->d86_mneu, "undef", OPLEN); + (void) strlcat(x->d86_mneu, "undef", OPLEN); #endif return (1); } @@ -3075,6 +3076,12 @@ dtrace_disx86_str(dis86_t *dis, uint_t mode, uintptr_t pc, char *buf, dis->d86_sprintf_func(buf, buflen, "%-6s ", dis->d86_mneu); + /* + * For PC-relative jumps, the pc is really the next pc after executing + * this instruction, so increment it appropriately. + */ + pc += dis->d86_len; + for (i = 0; i < dis->d86_numopnds; i++) { d86opnd_t *op = &dis->d86_opnd[i]; int64_t sv; @@ -3099,7 +3106,8 @@ dtrace_disx86_str(dis86_t *dis, uint_t mode, uintptr_t pc, char *buf, case MODE_OFFSET: if (dis->d86_seg_prefix) - strlcat(buf, dis->d86_seg_prefix, buflen); + (void) strlcat(buf, dis->d86_seg_prefix, + buflen); switch (op->d86_value_size) { case 1: @@ -3121,7 +3129,7 @@ dtrace_disx86_str(dis86_t *dis, uint_t mode, uintptr_t pc, char *buf, if (op->d86_mode == MODE_SIGNED || op->d86_mode == MODE_IMPLIED) - strlcat(buf, "$", buflen); + (void) strlcat(buf, "$", buflen); if (sv < 0 && sv > -0xffff && !isunsigned_op(dis->d86_mneu)) { @@ -3135,7 +3143,7 @@ dtrace_disx86_str(dis86_t *dis, uint_t mode, uintptr_t pc, char *buf, (dis->d86_flags & DIS_OP_OCTAL) ? "0%llo" : "0x%llx", sv & mask); } - strlcat(buf, op->d86_opnd, buflen); + (void) strlcat(buf, op->d86_opnd, buflen); break; case MODE_IPREL: @@ -3163,17 +3171,17 @@ dtrace_disx86_str(dis86_t *dis, uint_t mode, uintptr_t pc, char *buf, (dis->d86_flags & DIS_OP_OCTAL) ? "+0%llo" : "+0x%llx", sv + dis->d86_len); - strlcat(buf, "\t<", buflen); + (void) strlcat(buf, "\t<", buflen); if (dis->d86_sym_lookup == NULL || - dis->d86_sym_lookup(pc + sv, buf + strlen(buf), - buflen - strlen(buf)) != 0) + dis->d86_sym_lookup(dis->d86_data, pc + sv, + buf + strlen(buf), buflen - strlen(buf)) != 0) dis->d86_sprintf_func(buf + strlen(buf), buflen - strlen(buf), (dis->d86_flags & DIS_OP_OCTAL) ? "0%llo" : "0x%llx", pc + sv); - strlcat(buf, ">", buflen); + (void) strlcat(buf, ">", buflen); break; } diff --git a/usr/src/common/dis/i386/dis_tables.h b/usr/src/common/dis/i386/dis_tables.h index 1f579ff7e2..7ea6c25412 100644 --- a/usr/src/common/dis/i386/dis_tables.h +++ b/usr/src/common/dis/i386/dis_tables.h @@ -2,9 +2,8 @@ * 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. + * 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 * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -82,10 +81,10 @@ typedef struct dis86 { uint_t d86_addr_size; uint_t d86_got_modrm; struct d86opnd d86_opnd[3]; /* up to 3 operands */ - int (*d86_check_func)(); + int (*d86_check_func)(void *); int (*d86_get_byte)(void *); #ifdef DIS_TEXT - int (*d86_sym_lookup)(uint64_t, char *, size_t); + int (*d86_sym_lookup)(void *, uint64_t, char *, size_t); int (*d86_sprintf_func)(char *, size_t, const char *, ...); int d86_flags; uint_t d86_imm_bytes; diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index 23b01e19bc..892a841235 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -177,6 +177,7 @@ SUBDIRS += \ watchmalloc \ madv \ mpss \ + libdisasm \ libwrap \ libxcurses \ libxcurses2 \ @@ -306,6 +307,7 @@ HDRSUBDIRS= libaio \ libdhcpagent \ libdhcpsvc \ libdhcputil \ + libdisasm \ libdtrace \ libdtrace_jni \ libeti \ diff --git a/usr/src/lib/libdisasm/Makefile b/usr/src/lib/libdisasm/Makefile new file mode 100644 index 0000000000..7108f761fb --- /dev/null +++ b/usr/src/lib/libdisasm/Makefile @@ -0,0 +1,60 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + + +include ../Makefile.lib + +HDRS= libdisasm.h + +HDRDIR= common +$(INTEL_BLD)SUBDIRS= $(MACH) +$(INTEL_BLD)$(BUILD64)SUBDIRS += $(MACH64) +$(CLOSED_BLD)SUBDIRS += $(CLOSED)/lib/libdisasm + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +.KEEP_STATE: + +$(INTEL_BLD)SPECDIR= spec + +all clean clobber install: $(SPECDIR) .WAIT $(SUBDIRS) + +lint: $(SUBDIRS) + +install_h: $(ROOTHDRS) + +check: $(CHECKHDRS) + +$(SUBDIRS) spec: FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include ../Makefile.targ diff --git a/usr/src/lib/libdisasm/Makefile.com b/usr/src/lib/libdisasm/Makefile.com new file mode 100644 index 0000000000..85ab0b9361 --- /dev/null +++ b/usr/src/lib/libdisasm/Makefile.com @@ -0,0 +1,141 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + +# +# The build process for libdisasm is sightly different from that used by other +# libraries, because libdisasm must be built in two flavors - as a standalone +# for use by kmdb and as a normal library. We use $(CURTYPE) to indicate the +# current flavor being built. +# +# The SPARC library is built from the closed gate. This Makefile is shared +# between both environments, so all paths must be absolute. +# + +LIBRARY= libdisasm.a +STANDLIBRARY= libstanddisasm.so +VERS= .1 + +# By default, we build the shared library. Construction of the standalone +# is specifically requested by architecture-specific Makefiles. +TYPES= library +CURTYPE= library + +COMDIR= $(SRC)/lib/libdisasm/common +SPECDIR= $(SRC)/lib/libdisasm/spec + +# Files specific to the library version of libdisasm +OBJECTS_library = +SRC_libary = $(OBJECTS_library:%.o=$(COMDIR)/%.c) + +# +# Architecture-dependent files common to both versions of libdisasm +# +OBJECTS_common_i386 = dis_i386.o dis_tables.o +OBJECTS_common_sparc = dis_sparc.o + +SRCS_common_i386 = $(ISASRCDIR)/dis_i386.c $(SRC)/common/dis/i386/dis_tables.c +SRCS_common_sparc = $(ISASRCDIR)/dis_sparc.c + +# +# Architecture-independent files common to both version of libdisasm +# +OBJECTS_common_common = libdisasm.o +SRC_common_common = $(OBJECTS_common_common:%.o=$(COMDIR)/%.c) + + +OBJECTS= \ + $(OBJECTS_$(CURTYPE)) \ + $(OBJECTS_common_$(MACH)) \ + $(OBJECTS_common_common) + +include $(SRC)/lib/Makefile.lib + +SRCS= \ + $(SRCS_$(CURTYPE)) \ + $(SRCS_common_$(MACH)) \ + $(SRCS_common_common) + +# +# Used to verify that the standalone doesn't have any unexpected external +# dependencies. +# +LINKTEST_OBJ = objs/linktest_stand.o + +CLOBBERFILES_standalone = $(LINKTEST_OBJ) +CLOBBERFILES += $(CLOBBERFILES_$(CURTYPE)) + +LIBS_standalone = $(STANDLIBRARY) +LIBS_library = $(DYNLIB) $(LINTLIB) +LIBS = $(LIBS_$(CURTYPE)) + +MAPDIR= $(SPECDIR)/$(TRANSMACH) +SPECMAPFILE= $(MAPDIR)/mapfile + +LDLIBS += -lc + +LDFLAGS_standalone = -znoversion -Breduce -dy -r +LDFLAGS = $(LDFLAGS_$(CURTYPE)) + +ASFLAGS_standalone = -DDIS_STANDALONE +ASFLAGS_library = +ASFLAGS += -P $(ASFLAGS_$(CURTYPE)) -D_ASM + +$(LINTLIB) := SRCS = $(COMDIR)/$(LINTSRC) + +# We want the thread-specific errno in the library, but we don't want it in +# the standalone. $(DTS_ERRNO) is designed to add -D_TS_ERRNO to $(CPPFLAGS), +# in order to enable this feature. Conveniently, -D_REENTRANT does the same +# thing. As such, we null out $(DTS_ERRNO) to ensure that the standalone +# doesn't get it. +DTS_ERRNO= + +# We need to rename some standard functions so we can easily implement them +# in consumers. +STAND_RENAMED_FUNCS= \ + snprintf + +CPPFLAGS_standalone = -DDIS_STANDALONE $(STAND_RENAMED_FUNCS:%=-D%=mdb_%) \ + -I$(SRC)/cmd/mdb/common +CPPFLAGS_library = -D_REENTRANT +CPPFLAGS += -I$(COMDIR) $(CPPFLAGS_$(CURTYPE)) + +# +# For x86, we have to link to sources in usr/src/common +# +CPPFLAGS_dis_i386 = -I$(SRC)/common/dis/i386 -DDIS_TEXT +CPPFLAGS_dis_sparc = +CPPFLAGS += $(CPPFLAGS_dis_$(MACH)) + +CFLAGS_standalone = $(STAND_FLAGS_32) +CFLAGS_common = +CFLAGS += $(CFLAGS_$(CURTYPE)) $(CFLAGS_common) + +CFLAGS64_standalone = $(STAND_FLAGS_64) +CFLAGS64 += $(CCVERBOSE) $(CFLAGS64_$(CURTYPE)) $(CFLAGS64_common) + +DYNFLAGS += $(ZINTERPOSE) + +.KEEP_STATE: diff --git a/usr/src/lib/libdisasm/Makefile.targ b/usr/src/lib/libdisasm/Makefile.targ new file mode 100644 index 0000000000..c5798c1a94 --- /dev/null +++ b/usr/src/lib/libdisasm/Makefile.targ @@ -0,0 +1,100 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# +# We build each flavor in a separate make invocation to improve clarity(!) in +# Makefile.com. The subordinate makes have $(CURTYPE) set to indicate the +# flavor they're supposed to build. This causes the correct set of source +# files and compiler and linker flags to be selected. +# +# The SPARC library is built from the closed gate. This Makefile is shared +# between both environments, so all paths must be absolute. +# + +install: $(TYPES:%=install.%) + +all: $(TYPES:%=all.%) + +$(TYPES:%=all.%): + @CURTYPE=$(@:all.%=%) $(MAKE) $@.targ + +$(TYPES:%=install.%): + @CURTYPE=$(@:install.%=%) $(MAKE) $@.targ + +install.library.targ: all.library $(INSTALL_DEPS_library) +install.standalone.targ: all.standalone $(INSTALL_DEPS_standalone) + +all.library.targ: $(LIBS) +all.standalone.targ: $(STANDLIBRARY) + +lint: $(TYPES:%=lint.%) + +$(TYPES:%=lint.%): + @CURTYPE=$(@:lint.%=%) $(MAKE) lintcheck + +$(STANDLIBRARY): $(OBJS) $(LINKTEST_OBJ) + $(LD) -Breduce -zdefs $(LDFLAGS) -o $@.linktest $(OBJS) $(LINKTEST_OBJ) + rm $@.linktest + $(LD) $(LDFLAGS) -o $@ $(OBJS) + +$(DYNLIB): $(MAPFILE) + +$(MAPFILE): + @cd $(MAPDIR); $(MAKE) mapfile + +clobber: $(TYPES:%=clobber.%) + +$(TYPES:%=clobber.%): + @CURTYPE=$(@:clobber.%=%) $(MAKE) clobber.targ + +clobber.targ: clean + -$(RM) $(CLOBBERTARGFILES) + +# include library targets +include $(SRC)/lib/Makefile.targ + +$(PICS): pics +$(OBJS): objs + +objs/%.o pics/%.o: $(ISASRCDIR)/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +objs/%.o pics/%.o: $(ISASRCDIR)/%.s + $(COMPILE.s) -o $@ $< + $(POST_PROCESS_O) + +objs/%.o pics/%.o: $(COMDIR)/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +# install rule for lint library target +$(ROOTLINTDIR)/%: $(COMDIR)/% + $(INS.file) + +# install rule for x86 common source +objs/%.o pics/%.o: $(SRC)/common/dis/i386/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) diff --git a/usr/src/lib/libdisasm/amd64/Makefile b/usr/src/lib/libdisasm/amd64/Makefile new file mode 100644 index 0000000000..f53089a463 --- /dev/null +++ b/usr/src/lib/libdisasm/amd64/Makefile @@ -0,0 +1,37 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + +ISASRCDIR=../$(MACH)/ + +include ../Makefile.com +include ../../Makefile.lib.64 + +TYPES=library standalone + +INSTALL_DEPS_library = $(ROOTLINKS64) $(ROOTLINT64) $(ROOTLIBS64) +INSTALL_DEPS_standalone = $(ROOTLIBS64) + +include ../Makefile.targ diff --git a/usr/src/lib/libdisasm/common/libdisasm.c b/usr/src/lib/libdisasm/common/libdisasm.c new file mode 100644 index 0000000000..197c2c34df --- /dev/null +++ b/usr/src/lib/libdisasm/common/libdisasm.c @@ -0,0 +1,92 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <libdisasm.h> +#include <stdlib.h> +#ifdef DIS_STANDALONE +#include <mdb/mdb_modapi.h> +#endif + +static int _dis_errno; + +/* + * For the standalone library, we need to link against mdb's malloc/free. + * Otherwise, use the standard malloc/free. + */ +#ifdef DIS_STANDALONE +void * +dis_zalloc(size_t bytes) +{ + return (mdb_zalloc(bytes, UM_SLEEP)); +} + +void +dis_free(void *ptr, size_t bytes) +{ + mdb_free(ptr, bytes); +} +#else +void * +dis_zalloc(size_t bytes) +{ + return (calloc(1, bytes)); +} + +/*ARGSUSED*/ +void +dis_free(void *ptr, size_t bytes) +{ + free(ptr); +} +#endif + +int +dis_seterrno(int error) +{ + _dis_errno = error; + return (-1); +} + +int +dis_errno(void) +{ + return (_dis_errno); +} + +const char * +dis_strerror(int error) +{ + switch (error) { + case E_DIS_NOMEM: + return ("out of memory"); + case E_DIS_INVALFLAG: + return ("invalid flags for this architecture"); + default: + return ("unknown error"); + } +} diff --git a/usr/src/lib/libdisasm/common/libdisasm.h b/usr/src/lib/libdisasm/common/libdisasm.h new file mode 100644 index 0000000000..f66150a4ec --- /dev/null +++ b/usr/src/lib/libdisasm/common/libdisasm.h @@ -0,0 +1,78 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _LIBDISASM_H +#define _LIBDISASM_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct dis_handle dis_handle_t; + +#define DIS_DEFAULT 0x0 + +/* SPARC disassembler flags */ +#define DIS_SPARC_V8 0x01 +#define DIS_SPARC_V9 0x02 +#define DIS_SPARC_V9_SGI 0x04 + +/* x86 diassembler flags (mutually exclusive) */ +#define DIS_X86_SIZE16 0x08 +#define DIS_X86_SIZE32 0x10 +#define DIS_X86_SIZE64 0x20 + +/* generic disassembler flags */ +#define DIS_OCTAL 0x40 + +typedef int (*dis_lookup_f)(void *, uint64_t, char *, size_t, uint64_t *, + size_t *); +typedef int (*dis_read_f)(void *, uint64_t, void *, size_t); + +extern dis_handle_t *dis_handle_create(int, void *, dis_lookup_f, dis_read_f); +extern void dis_handle_destroy(dis_handle_t *); + +extern int dis_disassemble(dis_handle_t *, uint64_t, char *, size_t); +extern uint64_t dis_previnstr(dis_handle_t *, uint64_t, int n); +extern void dis_set_data(dis_handle_t *, void *); +extern int dis_max_instrlen(dis_handle_t *); + +/* libdisasm errors */ +#define E_DIS_NOMEM 1 /* Out of memory */ +#define E_DIS_INVALFLAG 2 /* Invalid flag for this architecture */ + +extern int dis_errno(void); +extern const char *dis_strerror(int); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBDISASM_H */ diff --git a/usr/src/lib/libdisasm/common/libdisasm_impl.h b/usr/src/lib/libdisasm/common/libdisasm_impl.h new file mode 100644 index 0000000000..c31c24fe6a --- /dev/null +++ b/usr/src/lib/libdisasm/common/libdisasm_impl.h @@ -0,0 +1,45 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _LIBDISASM_IMPL_H +#define _LIBDISASM_IMPL_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +extern int dis_seterrno(int); + +extern void *dis_zalloc(size_t); +extern void dis_free(void *, size_t); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBDISASM_IMPL_H */ diff --git a/usr/src/lib/libdisasm/common/linktest_stand.c b/usr/src/lib/libdisasm/common/linktest_stand.c new file mode 100644 index 0000000000..fd6ff8e353 --- /dev/null +++ b/usr/src/lib/libdisasm/common/linktest_stand.c @@ -0,0 +1,42 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * This file is used to verify that the standalone's external dependencies + * haven't changed in a way that'll break things that use it. + */ + +void mdb_free(void) {} +void snprintf(void) {} +void mdb_zalloc(void) {} +void strcmp(void) {} +void strlen(void) {} +void strlcat(void) {} +void strncpy(void) {} +void strncmp(void) {} +void memcpy(void) {} diff --git a/usr/src/lib/libdisasm/common/llib-ldisasm b/usr/src/lib/libdisasm/common/llib-ldisasm new file mode 100644 index 0000000000..4ca0ab20e6 --- /dev/null +++ b/usr/src/lib/libdisasm/common/llib-ldisasm @@ -0,0 +1,35 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 + */ + +/*LINTLIBRARY*/ +/*PROTOLIB1*/ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* LINTLIBRARY */ +/* PROTOLIB1 */ + +#include <libdisasm.h> diff --git a/usr/src/lib/libdisasm/i386/Makefile b/usr/src/lib/libdisasm/i386/Makefile new file mode 100644 index 0000000000..8d0d4453a2 --- /dev/null +++ b/usr/src/lib/libdisasm/i386/Makefile @@ -0,0 +1,36 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + +ISASRCDIR=. + +include ../Makefile.com + +TYPES=library standalone + +INSTALL_DEPS_library = $(ROOTLINKS) $(ROOTLINT) $(ROOTLIBS) +INSTALL_DEPS_standalone = $(ROOTLIBS) + +include ../Makefile.targ diff --git a/usr/src/lib/libdisasm/i386/dis_i386.c b/usr/src/lib/libdisasm/i386/dis_i386.c new file mode 100644 index 0000000000..e499bd9ee0 --- /dev/null +++ b/usr/src/lib/libdisasm/i386/dis_i386.c @@ -0,0 +1,225 @@ +/* + * 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 + * or http://www.opensolaris.org/os/licensing. + * 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 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <libdisasm.h> +#include <stdlib.h> +#include <stdio.h> + +#include "dis_tables.h" +#include "libdisasm_impl.h" + +struct dis_handle { + void *dh_data; + int dh_flags; + dis_lookup_f dh_lookup; + dis_read_f dh_read; + int dh_mode; + dis86_t dh_dis; + uint64_t dh_addr; + uint64_t dh_end; +}; + +/* + * Returns true if we are near the end of a function. This is a cheap hack at + * detecting NULL padding between functions. If we're within a few bytes of the + * next function, or past the start, then return true. + */ +static int +check_func(void *data) +{ + dis_handle_t *dhp = data; + uint64_t start; + size_t len; + + if (dhp->dh_lookup(dhp->dh_data, dhp->dh_addr, NULL, 0, &start, &len) + != 0) + return (0); + + if (start < dhp->dh_addr) + return (dhp->dh_addr > start + len - 0x10); + + return (1); +} + +static int +get_byte(void *data) +{ + uchar_t byte; + dis_handle_t *dhp = data; + + if (dhp->dh_read(dhp->dh_data, dhp->dh_addr, &byte, + sizeof (byte)) < sizeof (byte)) + return (-1); + + dhp->dh_addr++; + + return ((int)byte); +} + +static int +do_lookup(void *data, uint64_t addr, char *buf, size_t buflen) +{ + dis_handle_t *dhp = data; + + return (dhp->dh_lookup(dhp->dh_data, addr, buf, buflen, NULL, NULL)); +} + +dis_handle_t * +dis_handle_create(int flags, void *data, dis_lookup_f lookup_func, + dis_read_f read_func) +{ + dis_handle_t *dhp; + + /* + * Validate architecture flags + */ + if (flags & ~(DIS_X86_SIZE16 | DIS_X86_SIZE32 | DIS_X86_SIZE64 | + DIS_OCTAL)) { + (void) dis_seterrno(E_DIS_INVALFLAG); + return (NULL); + } + + /* + * Create and initialize the internal structure + */ + if ((dhp = dis_zalloc(sizeof (struct dis_handle))) == NULL) { + (void) dis_seterrno(E_DIS_NOMEM); + return (NULL); + } + + dhp->dh_lookup = lookup_func; + dhp->dh_read = read_func; + dhp->dh_flags = flags; + dhp->dh_data = data; + + /* + * Initialize x86-specific architecture structure + */ + if (flags & DIS_X86_SIZE16) + dhp->dh_mode = SIZE16; + else if (flags & DIS_X86_SIZE64) + dhp->dh_mode = SIZE64; + else + dhp->dh_mode = SIZE32; + + if (flags & DIS_OCTAL) + dhp->dh_dis.d86_flags = DIS_OP_OCTAL; + + dhp->dh_dis.d86_sprintf_func = snprintf; + dhp->dh_dis.d86_get_byte = get_byte; + dhp->dh_dis.d86_sym_lookup = do_lookup; + dhp->dh_dis.d86_check_func = check_func; + + dhp->dh_dis.d86_data = dhp; + + return (dhp); +} + +int +dis_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf, size_t buflen) +{ + dhp->dh_addr = addr; + + if (dtrace_disx86(&dhp->dh_dis, dhp->dh_mode) != 0) + return (-1); + + if (buf != NULL) + dtrace_disx86_str(&dhp->dh_dis, dhp->dh_mode, addr, buf, + buflen); + + return (0); +} + +void +dis_handle_destroy(dis_handle_t *dhp) +{ + dis_free(dhp, sizeof (dis_handle_t)); +} + +void +dis_set_data(dis_handle_t *dhp, void *data) +{ + dhp->dh_data = data; +} + +/* ARGSUSED */ +int +dis_max_instrlen(dis_handle_t *dhp) +{ + return (15); +} + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +/* + * Return the previous instruction. On x86, we have no choice except to + * disassemble everything from the start of the symbol, and stop when we have + * reached our instruction address. If we're not in the middle of a known + * symbol, then we return the same address to indicate failure. + */ +uint64_t +dis_previnstr(dis_handle_t *dhp, uint64_t pc, int n) +{ + uint64_t *hist, addr, start; + int cur, nseen; + uint64_t res = pc; + + if (dhp->dh_lookup(dhp->dh_data, pc, NULL, 0, &start, NULL) != 0 || + start == pc) + return (res); + + hist = dis_zalloc(sizeof (uint64_t) * n); + + for (cur = 0, nseen = 0, addr = start; addr < pc; addr = dhp->dh_addr) { + hist[cur] = addr; + cur = (cur + 1) % n; + nseen++; + + /* if we cannot make forward progress, give up */ + if (dis_disassemble(dhp, addr, NULL, 0) != 0) + goto done; + } + + if (addr != pc) { + /* + * We scanned past %pc, but didn't find an instruction that + * started at %pc. This means that either the caller specified + * an invalid address, or we ran into something other than code + * during our scan. Virtually any combination of bytes can be + * construed as a valid Intel instruction, so any non-code bytes + * we encounter will have thrown off the scan. + */ + goto done; + } + + res = hist[(cur + n - MIN(n, nseen)) % n]; + +done: + dis_free(hist, sizeof (uint64_t) * n); + return (res); +} diff --git a/usr/src/lib/libdisasm/spec/Makefile b/usr/src/lib/libdisasm/spec/Makefile new file mode 100644 index 0000000000..aa4090be64 --- /dev/null +++ b/usr/src/lib/libdisasm/spec/Makefile @@ -0,0 +1,27 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + +include $(SRC)/lib/Makefile.spec.arch diff --git a/usr/src/lib/libdisasm/spec/Makefile.targ b/usr/src/lib/libdisasm/spec/Makefile.targ new file mode 100644 index 0000000000..7f0c111966 --- /dev/null +++ b/usr/src/lib/libdisasm/spec/Makefile.targ @@ -0,0 +1,30 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + +LIBRARY= libdisasm.a +VERS= .1 + +OBJECTS= libdisasm.o diff --git a/usr/src/lib/libdisasm/spec/amd64/Makefile b/usr/src/lib/libdisasm/spec/amd64/Makefile new file mode 100644 index 0000000000..ccb7881373 --- /dev/null +++ b/usr/src/lib/libdisasm/spec/amd64/Makefile @@ -0,0 +1,34 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + +.KEEP_STATE: + +include ../Makefile.targ +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB64) diff --git a/usr/src/lib/libdisasm/spec/i386/Makefile b/usr/src/lib/libdisasm/spec/i386/Makefile new file mode 100644 index 0000000000..9c275ffd2d --- /dev/null +++ b/usr/src/lib/libdisasm/spec/i386/Makefile @@ -0,0 +1,33 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + +.KEEP_STATE: + +include ../Makefile.targ +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libdisasm/spec/libdisasm.spec b/usr/src/lib/libdisasm/spec/libdisasm.spec new file mode 100644 index 0000000000..d06dc0f18e --- /dev/null +++ b/usr/src/lib/libdisasm/spec/libdisasm.spec @@ -0,0 +1,57 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" + +function dis_disassemble +version SUNWprivate_1.1 +end + +function dis_errno +version SUNWprivate_1.1 +end + +function dis_handle_create +version SUNWprivate_1.1 +end + +function dis_handle_destroy +version SUNWprivate_1.1 +end + +function dis_max_instrlen +version SUNWprivate_1.1 +end + +function dis_previnstr +version SUNWprivate_1.1 +end + +function dis_set_data +version SUNWprivate_1.1 +end + +function dis_strerror +version SUNWprivate_1.1 +end diff --git a/usr/src/lib/libdisasm/spec/sparc/Makefile b/usr/src/lib/libdisasm/spec/sparc/Makefile new file mode 100644 index 0000000000..9c275ffd2d --- /dev/null +++ b/usr/src/lib/libdisasm/spec/sparc/Makefile @@ -0,0 +1,33 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + +.KEEP_STATE: + +include ../Makefile.targ +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB) diff --git a/usr/src/lib/libdisasm/spec/sparcv9/Makefile b/usr/src/lib/libdisasm/spec/sparcv9/Makefile new file mode 100644 index 0000000000..ccb7881373 --- /dev/null +++ b/usr/src/lib/libdisasm/spec/sparcv9/Makefile @@ -0,0 +1,34 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" + +.KEEP_STATE: + +include ../Makefile.targ +include $(SRC)/lib/Makefile.lib +include $(SRC)/lib/Makefile.lib.64 +include $(SRC)/lib/Makefile.spec + +install: $(ROOTABILIB64) diff --git a/usr/src/lib/libdisasm/spec/versions b/usr/src/lib/libdisasm/spec/versions new file mode 100644 index 0000000000..06da2dd348 --- /dev/null +++ b/usr/src/lib/libdisasm/spec/versions @@ -0,0 +1,43 @@ +# +# 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 +# or http://www.opensolaris.org/os/licensing. +# 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 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" + +sparc { + SUNW_1.1; + SUNWprivate_1.1; +} +sparcv9 { + SUNW_1.1; + SUNWprivate_1.1; +} +i386 { + SUNW_1.1; + SUNWprivate_1.1; +} +amd64 { + SUNW_1.1; + SUNWprivate_1.1; +} diff --git a/usr/src/pkgdefs/SUNWcsl/prototype_com b/usr/src/pkgdefs/SUNWcsl/prototype_com index 76863fbeef..1ae7b07404 100644 --- a/usr/src/pkgdefs/SUNWcsl/prototype_com +++ b/usr/src/pkgdefs/SUNWcsl/prototype_com @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -109,6 +108,8 @@ s none usr/lib/libdevinfo.so=../../lib/libdevinfo.so.1 s none usr/lib/libdevinfo.so.1=../../lib/libdevinfo.so.1 s none usr/lib/libdhcpagent.so.1=../../lib/libdhcpagent.so.1 s none usr/lib/libdhcputil.so.1=../../lib/libdhcputil.so.1 +f none usr/lib/libdisasm.so.1 755 root bin +s none usr/lib/libdisasm.so=./libdisasm.so.1 s none usr/lib/libdl.so=../../lib/libdl.so.1 s none usr/lib/libdl.so.1=../../lib/libdl.so.1 s none usr/lib/libdoor.so=../../lib/libdoor.so.1 diff --git a/usr/src/pkgdefs/SUNWcsl/prototype_i386 b/usr/src/pkgdefs/SUNWcsl/prototype_i386 index b630d4812e..c59bde1e95 100644 --- a/usr/src/pkgdefs/SUNWcsl/prototype_i386 +++ b/usr/src/pkgdefs/SUNWcsl/prototype_i386 @@ -20,7 +20,7 @@ # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -219,6 +219,8 @@ s none usr/lib/amd64/libdevid.so.1=../../../lib/amd64/libdevid.so.1 s none usr/lib/amd64/libdevid.so=../../../lib/amd64/libdevid.so.1 s none usr/lib/amd64/libdevinfo.so.1=../../../lib/amd64/libdevinfo.so.1 s none usr/lib/amd64/libdevinfo.so=../../../lib/amd64/libdevinfo.so.1 +f none usr/lib/amd64/libdisasm.so.1 755 root bin +s none usr/lib/amd64/libdisasm.so=libdisasm.so.1 s none usr/lib/amd64/libdl.so.1=../../../lib/amd64/libdl.so.1 s none usr/lib/amd64/libdl.so=../../../lib/amd64/libdl.so.1 s none usr/lib/amd64/libdoor.so.1=../../../lib/amd64/libdoor.so.1 diff --git a/usr/src/pkgdefs/SUNWcsl/prototype_sparc b/usr/src/pkgdefs/SUNWcsl/prototype_sparc index 176acf5df9..c98dc72049 100644 --- a/usr/src/pkgdefs/SUNWcsl/prototype_sparc +++ b/usr/src/pkgdefs/SUNWcsl/prototype_sparc @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -150,6 +149,8 @@ s none usr/lib/sparcv9/libctf.so.1=../../../lib/sparcv9/libctf.so.1 s none usr/lib/sparcv9/libctf.so=../../../lib/sparcv9/libctf.so.1 s none usr/lib/sparcv9/libcurses.so.1=../../../lib/sparcv9/libcurses.so.1 s none usr/lib/sparcv9/libcurses.so=../../../lib/sparcv9/libcurses.so.1 +f none usr/lib/sparcv9/libdisasm.so.1 755 root bin +s none usr/lib/sparcv9/libdisasm.so=libdisasm.so.1 f none usr/lib/sparcv9/libform.so.1 755 root bin s none usr/lib/sparcv9/libform.so=libform.so.1 s none usr/lib/sparcv9/libgen.so.1=../../../lib/sparcv9/libgen.so.1 diff --git a/usr/src/pkgdefs/SUNWmdb/prototype_sparc b/usr/src/pkgdefs/SUNWmdb/prototype_sparc index ea51863ed6..623ac1196e 100644 --- a/usr/src/pkgdefs/SUNWmdb/prototype_sparc +++ b/usr/src/pkgdefs/SUNWmdb/prototype_sparc @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -38,9 +37,6 @@ d none usr/platform/sun4u/lib/mdb/kvm 755 root sys d none usr/bin/sparcv9 755 root bin f none usr/bin/sparcv9/mdb 555 root bin l none usr/bin/sparcv9/adb=../../../usr/bin/sparcv9/mdb -f none usr/lib/mdb/disasm/sparc.so 555 root sys -d none usr/lib/mdb/disasm/sparcv9 755 root sys -f none usr/lib/mdb/disasm/sparcv9/sparc.so 555 root sys d none usr/lib/mdb/kvm/sparcv9 755 root sys f none usr/lib/mdb/kvm/sparcv9/audiosup.so 555 root sys f none usr/lib/mdb/kvm/sparcv9/cpc.so 555 root sys diff --git a/usr/src/pkgdefs/SUNWmdbr/prototype_sparc b/usr/src/pkgdefs/SUNWmdbr/prototype_sparc index bdb1b365a6..e8d71ee64f 100644 --- a/usr/src/pkgdefs/SUNWmdbr/prototype_sparc +++ b/usr/src/pkgdefs/SUNWmdbr/prototype_sparc @@ -2,9 +2,8 @@ # 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. +# 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 # or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -54,7 +53,6 @@ f none kernel/kmdb/sparcv9/random 555 root sys f none kernel/kmdb/sparcv9/sctp 555 root sys f none kernel/kmdb/sparcv9/s1394 555 root sys f none kernel/kmdb/sparcv9/sd 555 root sys -f none kernel/kmdb/sparcv9/sparc 555 root sys f none kernel/kmdb/sparcv9/specfs 555 root sys f none kernel/kmdb/sparcv9/sppp 555 root sys f none kernel/kmdb/sparcv9/ssd 555 root sys diff --git a/usr/src/pkgdefs/etc/exception_list_i386 b/usr/src/pkgdefs/etc/exception_list_i386 index 5c0e1ae3f1..32d3cc9595 100644 --- a/usr/src/pkgdefs/etc/exception_list_i386 +++ b/usr/src/pkgdefs/etc/exception_list_i386 @@ -414,6 +414,13 @@ lib/llib-lproc i386 lib/llib-lproc.ln i386 lib/amd64/llib-lproc.ln i386 # +# Private interfaces for libdisasm +# +usr/include/libdisasm.h i386 +usr/lib/llib-ldisasm i386 +usr/lib/llib-ldisasm.ln i386 +usr/lib/amd64/llib-ldisasm.ln i386 +# # This file is used for private communication between mdb, drv/kmdb, and # misc/kmdb. The interfaces described herein are not intended for customer # use, and are thus excluded from packaging. @@ -768,3 +775,10 @@ usr/include/libzfs_jni_util.h i386 # usr/include/sys/scsi/adapters/mpapi_impl.h i386 usr/include/sys/scsi/adapters/mpapi_scsi_vhci.h i386 + +# +# This library is installed in the proto area by the build of libdisasm, and is +# only used when building the KMDB disasm module. +# +usr/lib/libstanddisasm.so i386 +usr/lib/amd64/libstanddisasm.so i386 diff --git a/usr/src/pkgdefs/etc/exception_list_sparc b/usr/src/pkgdefs/etc/exception_list_sparc index 25e896ccf0..2e5b328619 100644 --- a/usr/src/pkgdefs/etc/exception_list_sparc +++ b/usr/src/pkgdefs/etc/exception_list_sparc @@ -421,6 +421,13 @@ lib/llib-lproc sparc lib/llib-lproc.ln sparc lib/sparcv9/llib-lproc.ln sparc # +# Private libdisasm interfaces +# +usr/include/libdisasm.h sparc +usr/lib/llib-ldisasm sparc +usr/lib/llib-ldisasm.ln sparc +usr/lib/sparcv9/llib-ldisasm.ln sparc +# # This file is used for private communication between mdb, drv/kmdb, and # misc/kmdb. The interfaces described herein are not intended for customer # use, and are thus excluded from packaging. @@ -829,3 +836,9 @@ usr/include/libzfs_jni_util.h sparc # usr/include/sys/scsi/adapters/mpapi_impl.h sparc usr/include/sys/scsi/adapters/mpapi_scsi_vhci.h sparc + +# +# This library is installed in the proto area by the build of libdisasm, and is +# only used when building the KMDB disasm module. +# +usr/lib/sparcv9/libstanddisasm.so sparc diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh index 0b8e815cde..257cfecc2d 100644 --- a/usr/src/tools/scripts/bfu.sh +++ b/usr/src/tools/scripts/bfu.sh @@ -4366,6 +4366,14 @@ mondo_loop() { smf_handle_new_services # + # Remove obsolete disassembler module + # + if [ $target_isa = sparc ]; then + rm -rf $usr/lib/mdb/disasm/* + rm -f $root/kernel/kmdb/sparcv9/sparc + fi + + # # Remove obsolete Sun-Fire-880 (daktari) FMA Fault Tree directory # and file. Backwards BFUs will resurrect them from the archives. # |