--- old/usr/src/tools/ctf/dump/Makefile.com Mon Apr 7 11:31:05 2008 +++ new/usr/src/tools/ctf/dump/Makefile.com Mon Apr 7 11:31:04 2008 @@ -28,8 +28,9 @@ .KEEP_STATE: .SUFFIXES: -PROG = ctfdump -SRCS = dump.c utils.c symbol.c +PROG = ctfdump ctftoh +DUMPSRCS = dump.c utils.c symbol.c +TOHSRCS = ctftoh.c include ../../Makefile.ctf @@ -36,22 +37,33 @@ OWNER = root GROUP = bin -LDLIBS += -lelf -lz +C99MODE= -xc99=%all +C99LMODE= -Xc99=%all -OBJS = $(SRCS:%.c=%.o) -LINTFILES = $(SRCS:%.c=%.ln) +LDLIBS += -lctf -lelf -lz +DUMPOBJS = $(DUMPSRCS:%.c=%.o) +TOHOBJS = $(TOHSRCS:%.c=%.o) list.o memory.o +LINTFILES = $(DUMPSRCS:%.c=%.ln) +LINTFILES += $(TOHSRCS:%.c=%.ln) + .NO_PARALLEL: -.PARALLEL: $(OBJS) $(LINTFILES) +.PARALLEL: $(DUMPOBJS) $(TOHOBJS) $(LINTFILES) all: $(PROG) -$(PROG): $(OBJS) - $(LINK.c) $(OBJS) -o $@ $(LDLIBS) +ctfdump: $(DUMPOBJS) + $(LINK.c) $(DUMPOBJS) -o $@ $(LDLIBS) $(POST_PROCESS) +ctftoh: $(TOHOBJS) + $(LINK.c) $(TOHOBJS) -o $@ $(LDLIBS) + $(POST_PROCESS) + %.o: ../%.c $(COMPILE.c) $< +%.o: ../common/%.c + $(COMPILE.c) $< $(ROOTONBLDMACHPROG): $(PROG) @@ -58,7 +70,7 @@ install: $(ROOTONBLDMACHPROG) clean: - $(RM) $(OBJS) $(LINTFILES) + $(RM) $(DUMPOBJS) $(TOHOBJS) $(LINTFILES) %.ln: ../%.c $(LINT.c) -c $< --- /dev/null Mon Apr 7 11:31:05 2008 +++ new/usr/src/tools/ctf/dump/ctftoh.c Mon Apr 7 11:31:05 2008 @@ -0,0 +1,422 @@ +/* + * 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 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include +#include +#include +#include + +#include +#include "list.h" + +typedef struct ctf_item { + ctf_id_t t_id; + char t_name[1024 /* FIXME */]; + int t_type; + int t_marked; +} ctf_item_t; + +typedef struct type_cb { + ctf_file_t *tc_ctf; + int tc_close; +} type_cb_t; + +static list_t *types; +static list_t *functions; + +static int show_offsets; +static int show_functions; +static int show_types; + +static int print_type(void *, void *); +static int insert_type(ctf_id_t, void *); + +static int +find_item_cb(void *item, void *template) +{ + return (((ctf_item_t *)item)->t_id != ((ctf_item_t *)template)->t_id); +} + +static ctf_item_t * +find_item(list_t *list, ctf_id_t id) +{ + ctf_item_t template; + template.t_id = id; + return (list_find(list, &template, find_item_cb)); +} + +static int +item_cmp(void *a, void *b) +{ + ctf_item_t *ia = a; + ctf_item_t *ib = b; + int ret = strcmp(ia->t_name, ib->t_name); + + if (ia->t_type == CTF_K_TYPEDEF && ib->t_type != CTF_K_TYPEDEF) + return (-1); + if (ib->t_type == CTF_K_TYPEDEF && ia->t_type != CTF_K_TYPEDEF) + return (1); + + if (ret != 0) + return (ret); + if (ia->t_id < ib->t_id) + return (-1); + return (1); +} + +/*ARGSUSED*/ +static int +visit_type(const char *name, ctf_id_t id, ulong_t off, int depth, void *arg) +{ + return (insert_type(id, arg)); +} + +static int +insert_type(ctf_id_t id, void *arg) +{ + ctf_file_t *ctf = arg; + ctf_item_t *item; + int err; + + if (ctf_type_kind(ctf, id) == CTF_K_FUNCTION) + return (0); + + if (find_item(types, id) != NULL) + return (0); + + if ((item = malloc(sizeof (*item))) == NULL) { + fprintf(stderr, "couldn't mamloc!\n"); + return (-1); + } + /* FIXME free */ + + item->t_id = id; + item->t_marked = 0; + item->t_type = ctf_type_kind(ctf, id); + + if (ctf_type_name(ctf, id, item->t_name, 1024) == NULL) { + fprintf(stderr, "couldnot name\n"); + free(item); + return (-1); + } + + slist_add(&types, item, item_cmp); + + err = ctf_type_visit(ctf, id, visit_type, ctf); + + if (err) { + fprintf(stderr, "visiting failed: %s\n", + ctf_errmsg(ctf_errno(ctf))); + } + + return (err); +} + +static int +print_enum_member(const char *name, int number, void *arg) +{ + ctf_file_t *ctf = arg; + + printf("\t"); + printf("%s = 0x%x,\n", name, number); + /* FIXME: commas */ + return (0); +} + +static void +print_enum(ctf_file_t *ctf, ctf_id_t id, int close) +{ + char name[1024]; + + ctf_type_name(ctf, id, name, 1024); + printf("%s", name); + if (name[strlen(name) - 1] != ' ') + printf(" "); + printf("{\n"); + ctf_enum_iter(ctf, id, print_enum_member, ctf); + printf("}"); + if (close) + printf(";\n"); +} + +static int +print_member(const char *name, ctf_id_t id, ulong_t off, void *arg) +{ + ctf_file_t *ctf = arg; + ctf_item_t *item = NULL; + type_cb_t cb = { .tc_ctf = ctf, .tc_close = 0 }; + char type[1024]; + + ctf_type_name(ctf, id, type, 1024); + + item = find_item(types, id); + + printf("\t"); + + /* FIXME: needs to be global offset */ + if (show_offsets) + printf(" /* 0x%x */ ", off); + + /* + * FIXME: indenting, also sort topologically so we don't have to + * be special like this. How do we decide whether a struct + * should be inline or not (e.g. union 'u' or anon should almost always + * be inline). + * + * Also indenting. + */ + if (item != NULL && !item->t_marked && + (item->t_type == CTF_K_STRUCT || item->t_type == CTF_K_UNION || + item->t_type == CTF_K_ENUM)) { + print_type(item, &cb); + printf("%s;\n", name); + } else { + printf("%s %s;\n", type, name); + } + return (0); +} + +static void +print_sou(ctf_file_t *ctf, ctf_id_t id, int close) +{ + char name[1024]; + + ctf_type_name(ctf, id, name, 1024); + printf("%s", name); + if (name[strlen(name) - 1] != ' ') + printf(" "); + + printf("{\n"); + + ctf_member_iter(ctf, id, print_member, ctf); + + printf("}"); + if (show_offsets) + printf(" /* 0x%x */ ", ctf_type_size(ctf, id)); + + if (close) + printf(";\n"); +} + +static void +print_typedef(ctf_file_t *ctf, ctf_id_t id) +{ + ctf_id_t ref = ctf_type_reference(ctf, id); + ctf_item_t *refitem; + char name[1024]; + char refname[1024]; + + ctf_type_name(ctf, id, name, 1024); + + refitem = find_item(types, ref); + + printf("typedef "); + + switch (ctf_type_kind(ctf, ref)) { + case CTF_K_STRUCT: + case CTF_K_UNION: + print_sou(ctf, ref, 0); + printf(" %s;\n", name); + if (refitem != NULL) + refitem->t_marked = 1; + break; + case CTF_K_ENUM: + print_enum(ctf, ref, 0); + printf(" %s;\n", name); + if (refitem != NULL) + refitem->t_marked = 1; + break; + default: + ctf_type_name(ctf, ref, refname, 1024); + printf("%s %s;\n", refname, name); + break; + } +} + +static int +print_type(void *type, void *arg) +{ + ctf_item_t *item = type; + type_cb_t *cb = arg; + ctf_file_t *ctf = cb->tc_ctf; + int close = cb->tc_close; + + if (item->t_marked) + return (0); + + if (item->t_name[0] != '\0') { + switch (item->t_type) { + case CTF_K_UNKNOWN: + case CTF_K_FUNCTION: + break; + case CTF_K_INTEGER: + break; + case CTF_K_FLOAT: + break; + case CTF_K_POINTER: + break; + case CTF_K_ARRAY: + break; + case CTF_K_STRUCT: + case CTF_K_UNION: + print_sou(ctf, item->t_id, close); + break; + case CTF_K_ENUM: + print_enum(ctf, item->t_id, close); + break; + case CTF_K_FORWARD: + break; + case CTF_K_TYPEDEF: + print_typedef(ctf, item->t_id); + break; + case CTF_K_VOLATILE: + break; + case CTF_K_CONST: + break; + case CTF_K_RESTRICT: + break; + default: + break; + } + } + + if (close) + printf("\n"); + + item->t_marked = 1; + + return (0); +} + +static void +print_types(ctf_file_t *ctf) +{ + type_cb_t cb = { .tc_ctf = ctf, .tc_close = 1 }; + ctf_item_t *item; + + /* FIXME: error reporting */ + + if (ctf_type_iter(ctf, insert_type, ctf)) + exit(1); + + if (list_iter(types, print_type, &cb)) + exit(1); +} + +static void +usage(void) +{ + fprintf(stderr, "Usage: ctftoh [-fot] [-p parent] file [file...]\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + char *parent = NULL; + int i; + int c; + + while ((c = getopt(argc, argv, "fop:t")) != (int)EOF) { + switch (c) { + case 'f': + show_functions = 1; + break; + case 'o': + show_offsets = 1; + break; + case 'p': + parent = optarg; + case 't': + show_types = 1; + break; + default: + usage(); + break; + } + } + + /* + * Default to showing everything. + */ + if (!show_functions && !show_types) { + show_functions = 1; + show_types = 1; + } + + if (optind == argc) + usage(); + + for (i = optind; i < argc; i++) { + const char *filename = argv[i]; + ctf_file_t *ctf; + int err; + + ctf = ctf_open(filename, &err); + + if (ctf == NULL) { + fprintf(stderr, "Couldn't open CTF for %s: %s\n", + filename, strerror(err)); + exit(1); + } + + if (parent != NULL) { + ctf_file_t *pctf = ctf_open(parent, &err); + + if (ctf == NULL) { + fprintf(stderr, + "Couldn't open CTF for %s: %s\n", + filename, strerror(err)); + exit(1); + } + + if (ctf_import(ctf, pctf)) { + fprintf(stderr, + "Failed to import %s: %s\n", + parent, ctf_errmsg(ctf_errno(ctf))); + exit(1); + } + } + + + if (show_types) { + printf("/* %s: types */\n\n", filename); + print_types(ctf); + } + + if (show_functions) { + printf("/* %s: functions */\n\n", filename); + /* print_functions(ctf); */ + } + + printf("\n\n"); + + ctf_close(ctf); + } + + return (0); +}