--- crash-4.0-4.6/memory.c 2007-09-25 11:04:38.000000000 -0400 +++ crash-4.0-4.7/memory.c 2007-09-13 14:49:22.000000000 -0400 @@ -9948,6 +9948,8 @@ ulong vaddr, orig_flags; physaddr_t paddr; ulong offset; + ulong task; + struct task_context *tc; switch (mi->memtype) { @@ -9982,7 +9984,7 @@ if ((mi->memtype == KVADDR) && IS_VMALLOC_ADDR(mi->spec_addr)) { if (kvtop(NULL, mi->spec_addr, &paddr, 0)) { mi->flags = orig_flags; - dump_vmlist(mi); + dump_vmlist(mi); fprintf(fp, "\n"); mi->spec_addr = paddr; mi->memtype = PHYSADDR; @@ -10046,8 +10048,22 @@ fprintf(fp, "\n"); } + /* + * Check whether it's a current task or stack address. + */ + if ((mi->memtype == KVADDR) && (task = vaddr_in_task_struct(vaddr)) && + (tc = task_to_context(task))) { + show_context(tc); + fprintf(fp, "\n"); + } else if ((mi->memtype == KVADDR) && (task = stkptr_to_task(vaddr)) && + (tc = task_to_context(task))) { + show_context(tc); + fprintf(fp, "\n"); + } + mem_map: mi->flags = orig_flags; + pc->curcmd_flags &= ~HEADER_PRINTED; dump_mem_map(mi); if (!mi->retval) --- crash-4.0-4.6/help.c 2007-09-25 11:04:38.000000000 -0400 +++ crash-4.0-4.7/help.c 2007-09-24 14:11:05.000000000 -0400 @@ -1529,13 +1529,20 @@ " ", " Below is an example shared object file consisting of just one command, ", " called \"echo\", which simply echoes back all arguments passed to it.", -" Note the comments contained within it for further details. To build it,", -" cut and paste the following output into a file, and call it, for example,", -" \"echo.c\". Then compile like so:", +" Note the comments contained within it for further details. Cut and paste", +" the following output into a file, and call it, for example, \"echo.c\".", +" Then compiled in either of two manners. Either manually like so:", +" ", +" gcc -nostartfiles -shared -rdynamic -o echo.so echo.c -fPIC -D $(TARGET_CFLAGS)", +" ", +" where must be one of the MACHINE_TYPE #define's in defs.h,", +" and where $(TARGET_CFLAGS) is the same as it is declared in the top-level", +" Makefile after a build is completed. Or alternatively, the \"echo.c\" file", +" can be copied into the \"extensions\" subdirectory, and compiled automatically", +" like so:", " ", -" gcc -nostartfiles -shared -rdynamic -o echo.so echo.c -fPIC -D", +" make extensions", " ", -" where must be one of the MACHINE_TYPE #define's in defs.h.", " The echo.so file may be dynamically linked into %s during runtime, or", " during initialization by putting \"extend echo.so\" into a .%src file", " located in the current directory, or in the user's $HOME directory.", @@ -3881,9 +3888,12 @@ " address when used without any flag, the address can be a kernel virtual,", " or physical address; a search is made through the symbol table,", " the kmalloc() slab subsystem, the free list, the page_hash_table,", -" the vmalloc() vmlist subsystem, and the mem_map array. If found", -" in any of those areas, the information will be dumped in the", -" same manner as if the flags were used.", +" the vmalloc() vmlist subsystem, the current set of task_structs", +" and kernel stacks, and the mem_map array. If found in any of", +" those areas, the information will be dumped in the same manner as", +" if the location-specific flags were used; if contained within a", +" curent task_struct or kernel stack, that task's context will be", +" displayed.", " address when used with -s or -S, searches the kmalloc() slab subsystem", " for the slab containing of this virtual address, showing whether", " it is in use or free.", --- crash-4.0-4.6/task.c 2007-09-25 11:04:38.000000000 -0400 +++ crash-4.0-4.7/task.c 2007-09-13 14:45:24.000000000 -0400 @@ -3467,6 +3467,25 @@ /* + * Return the task if the vaddr is part of a task's task_struct. + */ +ulong +vaddr_in_task_struct(ulong vaddr) +{ + int i; + struct task_context *tc; + + tc = FIRST_CONTEXT(); + for (i = 0; i < RUNNING_TASKS(); i++, tc++) { + if ((vaddr >= tc->task) && + (vaddr < (tc->task + SIZE(task_struct)))) + return tc->task; + } + + return NO_TASK; +} + +/* * Verify whether any task is running a command. */ int --- crash-4.0-4.6/x86.c 2007-09-25 11:04:38.000000000 -0400 +++ crash-4.0-4.7/x86.c 2007-09-06 08:34:46.000000000 -0400 @@ -4141,9 +4141,9 @@ if (CRASHDEBUG(7)) { up = (ulong *)xkd->page; - for (i = 0; i < 256; i++) { + for (j = 0; j < 256; j++) { fprintf(fp, "%08lx: %08lx %08lx %08lx %08lx\n", - (ulong)((i * 4) * sizeof(ulong)), + (ulong)((j * 4) * sizeof(ulong)), *up, *(up+1), *(up+2), *(up+3)); up += 4; } --- crash-4.0-4.6/x86_64.c 2007-09-25 11:04:38.000000000 -0400 +++ crash-4.0-4.7/x86_64.c 2007-09-19 10:55:39.000000000 -0400 @@ -3427,6 +3427,14 @@ i < (bt->stacktop - bt->stackbase)/sizeof(ulong); i++, up++) { sym = closest_symbol(*up); if (XEN_CORE_DUMPFILE()) { + if (STREQ(sym, "crash_kexec")) { + sp = x86_64_function_called_by((*up)-5); + if (sp && STREQ(sp->name, "machine_kexec")) { + *rip = *up; + *rsp = bt->stackbase + ((char *)(up) - bt->stackbuf); + return; + } + } if (STREQ(sym, "xen_machine_kexec")) { *rip = *up; *rsp = bt->stackbase + ((char *)(up) - bt->stackbuf); @@ -3439,6 +3447,14 @@ STREQ(sym, "crash_kexec") || STREQ(sym, "machine_kexec") || STREQ(sym, "try_crashdump")) { + if (STREQ(sym, "crash_kexec")) { + sp = x86_64_function_called_by((*up)-5); + if (sp && STREQ(sp->name, "machine_kexec")) { + *rip = *up; + *rsp = bt->stackbase + ((char *)(up) - bt->stackbuf); + return; + } + } /* * Use second instance of crash_kexec if it exists. */ --- crash-4.0-4.6/extensions.c 2007-09-25 11:04:38.000000000 -0400 +++ crash-4.0-4.7/extensions.c 2007-09-24 15:46:12.000000000 -0400 @@ -354,4 +354,23 @@ pc->curext->flags |= REGISTERED; /* Mark of approval */ } +/* + * Hooks for sial. + */ +unsigned long +get_curtask(void) +{ + return CURRENT_TASK(); +} + +char * +crash_global_cmd(void) +{ + return pc->curcmd; +} +struct command_table_entry * +crash_cmd_table(void) +{ + return pc->cmd_table; +} --- crash-4.0-4.6/symbols.c 2007-09-25 11:04:38.000000000 -0400 +++ crash-4.0-4.7/symbols.c 2007-09-19 16:41:05.000000000 -0400 @@ -7716,19 +7716,33 @@ add_symbol_file(struct load_module *lm) { struct gnu_request request, *req; - char buf[BUFSIZE]; + char buf[BUFSIZE]; + int i, len; + char *secname; + + for (i = len = 0; i < lm->mod_sections; i++) + { + secname = lm->mod_section_data[i].name; + if ((lm->mod_section_data[i].flags & SEC_FOUND) && + !STREQ(secname, ".text")) { + sprintf(buf, " -s %s 0x%lx", secname, + lm->mod_section_data[i].offset + lm->mod_base); + len += strlen(buf); + } + } req = &request; BZERO(req, sizeof(struct gnu_request)); req->command = GNU_ADD_SYMBOL_FILE; req->addr = (ulong)lm; - req->buf = buf; + req->buf = GETBUF(len+BUFSIZE); if (!CRASHDEBUG(1)) req->fp = pc->nullfp; st->flags |= ADD_SYMBOL_FILE; - gdb_interface(req); + gdb_interface(req); st->flags &= ~ADD_SYMBOL_FILE; + FREEBUF(req->buf); sprintf(buf, "set complaints 0"); gdb_pass_through(buf, NULL, 0); --- crash-4.0-4.6/lkcd_common.c 2007-09-25 11:04:38.000000000 -0400 +++ crash-4.0-4.7/lkcd_common.c 2007-09-19 14:09:10.000000000 -0400 @@ -64,7 +64,7 @@ for (i = 0; i < lkcd->fix_addr_num; i++) { if ( (addr >=lkcd->fix_addr[i].task) && - (addr <= lkcd->fix_addr[i].task + STACKSIZE())){ + (addr < lkcd->fix_addr[i].task + STACKSIZE())){ offset = addr - lkcd->fix_addr[i].task; addr = lkcd->fix_addr[i].saddr + offset; --- crash-4.0-4.6/xendump.c 2007-09-25 11:04:38.000000000 -0400 +++ crash-4.0-4.7/xendump.c 2007-09-17 15:12:50.000000000 -0400 @@ -1272,6 +1272,7 @@ int i, b, idx, done; ulong tmp[MAX_BATCH_SIZE]; off_t offset; + size_t size; uint nr_pages; if (xd->flags & XC_CORE_ELF) @@ -1289,9 +1290,8 @@ for (b = 0, idx = -1, done = FALSE; !done && (b < nr_pages); b += MAX_BATCH_SIZE) { - - if (read(xd->xfd, tmp, sizeof(ulong) * MAX_BATCH_SIZE) != - (MAX_BATCH_SIZE * sizeof(ulong))) { + size = sizeof(ulong) * MIN(MAX_BATCH_SIZE, nr_pages - b); + if (read(xd->xfd, tmp, size) != size) { error(INFO, "cannot read index page %d\n", b); return NULL; } @@ -1354,7 +1354,6 @@ struct xen_dumpcore_p2m p2m_batch[MAX_BATCH_SIZE]; offset = xd->xc_core.header.xch_index_offset; - size = sizeof(struct xen_dumpcore_p2m) * MAX_BATCH_SIZE; nr_pages = xd->xc_core.header.xch_nr_pages; if (lseek(xd->xfd, offset, SEEK_SET) == -1) @@ -1362,7 +1361,8 @@ for (b = 0, idx = -1, done = FALSE; !done && (b < nr_pages); b += MAX_BATCH_SIZE) { - + size = sizeof(struct xen_dumpcore_p2m) * + MIN(MAX_BATCH_SIZE, nr_pages - b); if (read(xd->xfd, &p2m_batch[0], size) != size) { error(INFO, "cannot read index page %d\n", b); return NULL; @@ -1422,6 +1422,7 @@ int i, b; ulong tmp[MAX_BATCH_SIZE]; uint nr_pages; + size_t size; if (xd->flags & XC_CORE_ELF) return xc_core_elf_mfn_to_page_index(mfn); @@ -1437,9 +1438,8 @@ nr_pages *= 2; for (b = 0; b < nr_pages; b += MAX_BATCH_SIZE) { - - if (read(xd->xfd, tmp, sizeof(ulong) * MAX_BATCH_SIZE) != - (MAX_BATCH_SIZE * sizeof(ulong))) { + size = sizeof(ulong) * MIN(MAX_BATCH_SIZE, nr_pages - b); + if (read(xd->xfd, tmp, size) != size) { error(INFO, "cannot read index page %d\n", b); return MFN_NOT_FOUND; } @@ -1475,14 +1475,14 @@ struct xen_dumpcore_p2m p2m_batch[MAX_BATCH_SIZE]; offset = xd->xc_core.header.xch_index_offset; - size = sizeof(struct xen_dumpcore_p2m) * MAX_BATCH_SIZE; nr_pages = xd->xc_core.header.xch_nr_pages; if (lseek(xd->xfd, offset, SEEK_SET) == -1) error(FATAL, "cannot lseek to page index\n"); for (b = 0; b < nr_pages; b += MAX_BATCH_SIZE) { - + size = sizeof(struct xen_dumpcore_p2m) * + MIN(MAX_BATCH_SIZE, nr_pages - b); if (read(xd->xfd, &p2m_batch[0], size) != size) { error(INFO, "cannot read index page %d\n", b); return MFN_NOT_FOUND; @@ -1518,6 +1518,7 @@ uint nr_pages; ulong tmp[MAX_BATCH_SIZE]; ulonglong tmp64[MAX_BATCH_SIZE]; + size_t size; if (lseek(xd->xfd, (off_t)xd->xc_core.header.xch_index_offset, SEEK_SET) == -1) { @@ -1563,8 +1564,9 @@ nr_pages = xd->xc_core.header.xch_nr_pages; for (b = 0; b < nr_pages; b += MAX_BATCH_SIZE) { - if (read(xd->xfd, tmp, sizeof(ulong) * MAX_BATCH_SIZE) != - (MAX_BATCH_SIZE * sizeof(ulong))) { + size = sizeof(ulong) * + MIN(MAX_BATCH_SIZE, nr_pages - b); + if (read(xd->xfd, tmp, size) != size) { error(INFO, "cannot read index page %d\n", b); return FALSE; } @@ -1595,8 +1597,9 @@ nr_pages = xd->xc_core.header.xch_nr_pages; for (b = 0; b < nr_pages; b += MAX_BATCH_SIZE) { - if (read(xd->xfd, tmp64, sizeof(ulonglong) * MAX_BATCH_SIZE) != - (MAX_BATCH_SIZE * sizeof(ulonglong))) { + size = sizeof(ulonglong) * + MIN(MAX_BATCH_SIZE, nr_pages - b); + if (read(xd->xfd, tmp64, size) != size) { error(INFO, "cannot read index page %d\n", b); return FALSE; } @@ -1715,7 +1718,6 @@ struct xen_dumpcore_p2m p2m_batch[MAX_BATCH_SIZE]; offset = xd->xc_core.header.xch_index_offset; - size = sizeof(struct xen_dumpcore_p2m) * MAX_BATCH_SIZE; nr_pages = xd->xc_core.header.xch_nr_pages; /* @@ -1744,7 +1746,8 @@ error(FATAL, "cannot lseek to page index\n"); for (b = start_index; b < nr_pages; b += MAX_BATCH_SIZE) { - + size = sizeof(struct xen_dumpcore_p2m) * + MIN(MAX_BATCH_SIZE, nr_pages - b); if (read(xd->xfd, &p2m_batch[0], size) != size) { error(INFO, "cannot read index page %d\n", b); return PFN_NOT_FOUND; @@ -1844,7 +1847,6 @@ uint64_t pfn_batch[MAX_BATCH_SIZE]; offset = xd->xc_core.header.xch_index_offset; - size = sizeof(uint64_t) * MAX_BATCH_SIZE; nr_pages = xd->xc_core.header.xch_nr_pages; /* @@ -1873,7 +1875,7 @@ error(FATAL, "cannot lseek to page index\n"); for (b = start_index; b < nr_pages; b += MAX_BATCH_SIZE) { - + size = sizeof(uint64_t) * MIN(MAX_BATCH_SIZE, nr_pages - b); if (read(xd->xfd, &pfn_batch[0], size) != size) { error(INFO, "cannot read index page %d\n", b); return PFN_NOT_FOUND; @@ -2023,7 +2025,7 @@ case EM_X86_64: if ((elf64->e_ident[EI_DATA] == ELFDATA2LSB) && - machine_type("X86_64")) + (machine_type("X86_64") || machine_type("X86"))) break; else goto bailout; --- crash-4.0-4.6/defs.h 2007-09-25 11:04:38.000000000 -0400 +++ crash-4.0-4.7/defs.h 2007-09-24 16:08:49.000000000 -0400 @@ -3438,6 +3438,7 @@ ulong task_mm(ulong, int); ulong task_tgid(ulong); ulonglong task_last_run(ulong); +ulong vaddr_in_task_struct(ulong); int comm_exists(char *); struct task_context *task_to_context(ulong); struct task_context *pid_to_context(ulong); @@ -3483,6 +3484,10 @@ void dump_extension_table(int); void load_extension(char *); void unload_extension(char *); +/* Hooks for sial */ +unsigned long get_curtask(void); +char *crash_global_cmd(void); +struct command_table_entry *crash_cmd_table(void); /* * kernel.c --- crash-4.0-4.6/Makefile 2007-09-25 11:40:26.000000000 -0400 +++ crash-4.0-4.7/Makefile 2007-09-25 11:40:26.000000000 -0400 @@ -103,8 +103,38 @@ # directory. EXTENSIONS=extensions -EXTENSION_SOURCE_FILES=${EXTENSIONS}/Makefile ${EXTENSIONS}/echo.c ${EXTENSIONS}/dminfo.c -EXTENSION_OBJECT_FILES=echo.so dminfo.so +EXTENSION_SOURCE_FILES=${EXTENSIONS}/Makefile ${EXTENSIONS}/echo.c ${EXTENSIONS}/dminfo.c \ + ${EXTENSIONS}/libsial/Makefile \ + ${EXTENSIONS}/libsial/mkbaseop.c \ + ${EXTENSIONS}/libsial/README \ + ${EXTENSIONS}/libsial/README.sial \ + ${EXTENSIONS}/libsial/sial_alloc.c \ + ${EXTENSIONS}/libsial/sial_api.c \ + ${EXTENSIONS}/libsial/sial_api.h \ + ${EXTENSIONS}/libsial/sial_builtin.c \ + ${EXTENSIONS}/libsial/sial_case.c \ + ${EXTENSIONS}/libsial/sial_define.c \ + ${EXTENSIONS}/libsial/sial_func.c \ + ${EXTENSIONS}/libsial/sial.h \ + ${EXTENSIONS}/libsial/sial_input.c \ + ${EXTENSIONS}/libsial/sial.l \ + ${EXTENSIONS}/libsial/sial-lsed \ + ${EXTENSIONS}/libsial/sial_member.c \ + ${EXTENSIONS}/libsial/sial_node.c \ + ${EXTENSIONS}/libsial/sial_num.c \ + ${EXTENSIONS}/libsial/sial_op.c \ + ${EXTENSIONS}/libsial/sialpp.l \ + ${EXTENSIONS}/libsial/sialpp-lsed \ + ${EXTENSIONS}/libsial/sialpp.y \ + ${EXTENSIONS}/libsial/sial_print.c \ + ${EXTENSIONS}/libsial/sial_stat.c \ + ${EXTENSIONS}/libsial/sial_str.c \ + ${EXTENSIONS}/libsial/sial_type.c \ + ${EXTENSIONS}/libsial/sial_util.c \ + ${EXTENSIONS}/libsial/sial_var.c \ + ${EXTENSIONS}/libsial/sial.y \ + ${EXTENSIONS}/sial.c \ + ${EXTENSIONS}/sial.mk DAEMON_OBJECT_FILES=remote_daemon.o va_server.o va_server_v1.o \ lkcd_common.o lkcd_v1.o lkcd_v2_v3.o lkcd_v5.o lkcd_v7.o lkcd_v8.o \ @@ -251,6 +281,7 @@ clean: rm -f ${OBJECT_FILES} ${DAEMON_OBJECT_FILES} ${PROGRAM} ${PROGRAM}lib.a ${GDB_OFILES} + @(cd extensions; make --no-print-directory -i clean) make_build_data: force cc -c ${CFLAGS} build_data.c ${WARNING_OPTIONS} ${WARNING_ERROR} @@ -543,5 +574,4 @@ @make --no-print-directory do_extensions do_extensions: - @(cd extensions; make -i OBJECTS="$(EXTENSION_OBJECT_FILES)" \ - TARGET=$(TARGET) TARGET_CFLAGS=$(TARGET_CFLAGS)) + @(cd extensions; make -i TARGET=$(TARGET) TARGET_CFLAGS=$(TARGET_CFLAGS)) --- crash-4.0-4.6/extensions/Makefile 2007-09-25 11:04:38.000000000 -0400 +++ crash-4.0-4.7/extensions/Makefile 2007-09-21 14:43:03.000000000 -0400 @@ -1,8 +1,8 @@ # # Makefile for building crash shared object extensions # -# Copyright (C) 2005 David Anderson -# Copyright (C) 2005 Red Hat, Inc. All rights reserved. +# Copyright (C) 2005, 2007 David Anderson +# Copyright (C) 2005, 2007 Red Hat, Inc. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -17,27 +17,31 @@ # To build the extension shared objects in this directory, run # "make extensions" from the top-level directory. # -# To add a new extension object: -# -# - add the new source file to the EXTENSION_SOURCE_FILES list -# in the top-level Makefile -# - add the object file name to the EXTENSION_OBJECT_FILES list -# in the top-level Makefile -# - create a compile stanza below, typically using "echo.so" as -# a base template. +# To add a new extension object, simply copy your module's .c file +# to this directory, and it will be built automatically using +# the "standard" compile line. If that compile line does not +# suffice, create a .mk file with the same prefix as the .c file, +# and that makefile will be invoked. # -all: link_defs $(OBJECTS) +CONTRIB_SO := $(patsubst %.c,%.so,$(wildcard *.c)) + +all: link_defs $(CONTRIB_SO) link_defs: @if [ ! -f defs.h ]; then \ ln -s ../defs.h; fi -echo.so: ../defs.h echo.c - gcc -nostartfiles -shared -rdynamic -o echo.so echo.c -fPIC \ - -D$(TARGET) $(TARGET_CFLAGS) +$(CONTRIB_SO): %.so: %.c + @if [ -f $*.mk ]; then \ + make -f $*.mk; \ + else \ + echo "gcc -nostartfiles -shared -rdynamic -o $@ $*.c -fPIC -D$(TARGET) $(TARGET_CFLAGS)"; \ + gcc -nostartfiles -shared -rdynamic -o $@ $*.c -fPIC -D$(TARGET) $(TARGET_CFLAGS); \ + fi -dminfo.so: ../defs.h dminfo.c - gcc -nostartfiles -shared -rdynamic -o dminfo.so dminfo.c -fPIC \ - -D$(TARGET) $(TARGET_CFLAGS) - +clean: + rm -f $(CONTRIB_SO) + @for MAKEFILE in `grep -sl "^clean:" *.mk`; \ + do make --no-print-directory -f $$MAKEFILE clean; \ + done --- crash-4.0-4.6/extensions/libsial/Makefile 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/Makefile 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,91 @@ +# +# Copyright 2001 Silicon Graphics, Inc. All rights reserved. +# +# +# Makefile for LIBSIAL +# + +# Must be berkeley yacc. Bison will not cut it +YACC = bison + +LDIRT = lex.sial.c lex.sialpp.c sial.tab.c sial.tab.h sialpp.tab.c \ + sialpp.tab.h y.output mkbaseop baseops.c y.tab.c y.tab.h \ + libsial.so* *.output + +LIBDIR = /usr/lib +TARGETS = libsial.a + +CFLAGS += -O3 -fPIC + +CFILES = sial_util.c sial_node.c sial_var.c sial_func.c sial_str.c \ + sial_op.c sial_num.c sial_stat.c sial_builtin.c sial_type.c \ + sial_case.c sial_api.c sial_member.c sial_alloc.c sial_define.c \ + sial_input.c sial_print.c + +OFILES = $(CFILES:.c=.o) sialpp.tab.o sial.tab.o lex.sial.o lex.sialpp.o \ + baseops.o + +HFILES = sial.h sial_api.h + +LSOURCES = sial-lsed sialpp-lsed sial.l sialpp.l sial.y sialpp.y mkbaseop.c + +all: default + +showfiles: + @echo $(RELDIR)/$(CFILES) $(RELDIR)/$(HFILES) $(RELDIR)/$(LSOURCES) + +exports: all + install $(TARGETS) $(ROOT)$(LIBDIR) + +headers: + install -m 644 $(HFILES) $(ROOT)/usr/include + +install: headers exports + (cd scripts ; $(MAKE) install ) + +baseops.o: mkbaseop.c + $(CC) $(CFLAGS) -o mkbaseop mkbaseop.c + ./mkbaseop > baseops.c + $(CC) $(CFLAGS) -c baseops.c + +mkbaseop.c sial_member.o sial_op.o sial_stat.o sial_type.o y.tab.o : sial.tab.h + +lex.sial.o: lex.sial.c sial.tab.c sial.h + $(CC) $(CFLAGS) -c lex.sial.c + +lex.sial.c: sial.l + flex -L -Psial -t sial.l > lex.sial.c + +sial.tab.c: sial.tab.h + +sialpp.tab.o: sialpp.tab.c + $(CC) $(CFLAGS) -c sialpp.tab.c + +sial.tab.o: sial.tab.c + $(CC) $(CFLAGS) -c sial.tab.c + +sial.tab.h : sial.y + $(YACC) -psial -v -t -d sial.y + +lex.sialpp.o: lex.sialpp.c sialpp.tab.c sial.h + $(CC) $(CFLAGS) -c lex.sialpp.c + +lex.sialpp.c: sialpp.l + flex -Psialpp -t sialpp.l > lex.sialpp.c + +sialpp.tab.c: sialpp.tab.h sial.tab.h + +sialpp.tab.h : sialpp.y sial.tab.h + $(YACC) -psialpp -v -t -d sialpp.y + +default: $(TARGETS) + +$(CFILES): $(HFILES) sial.tab.h + +$(TARGETS): $(OFILES) + $(AR) ccurl $(TARGETS) $(OFILES) + +clean: + -/bin/rm -f *.o $(TARGETS) $(LDIRT) + +clobber: clean --- crash-4.0-4.6/extensions/libsial/mkbaseop.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/mkbaseop.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,169 @@ +/* + * Copyright 2000 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include "sial.h" +#include "sial.tab.h" +/* + This utility generates a operator function table for the base type. + Each combinaison of operand type and operation needs a dedicated + function. We use a table defined here in to generate an indirect table + that if indexed (from within sial_op.c) using : + + value_t * (func)(value_t *v1, value_t *v2) = table[type1][type2][op]; +*/ +static struct opss { + char *str; + char *acro; + int code; +} opstbl[] = { + { "+", "ADD", ADD }, + { "-", "SUB", SUB }, + { "/", "DIV", DIV }, + { "*", "MUL", MUL }, + { "^", "XOR", XOR }, + { "%", "MOD", MOD }, + { "|", "OR", OR }, + { "&", "AND", AND }, + { "<<", "SHL", SHL }, + { ">>", "SHR", SHR }, + { "==", "EQ", EQ }, /* most be first bool */ + { ">", "GT", GT }, + { "<", "LT", LT }, + { ">=", "GE", GE }, + { "<=", "LE", LE }, + { "!=", "NE", NE }, +}; + +static char *typtbl[] = { "sc", "uc", "ss", "us", "sl", "ul", "sll", "ull" }; + +#define NOPS (sizeof(opstbl)/sizeof(opstbl[0])) +#define NTYPS (sizeof(typtbl)/sizeof(typtbl[0])) + +int +main() +{ +int i,j,k; + + printf("\ +#include \"sial.h\"\n\ +#include \"sial.tab.h\"\n\ +/**************************************************************\n\ + This file is generated by a program.\n\ + Check out and modify libsial/mkbaseop.c instead !\n\ +***************************************************************/\n"); + + + /* create all the functions for all combinaison */ + for(i=0;iv.%s = v1->v.%s %s v2->v.%s;\n" +" ret->type.type=%s->type.type;\n" +" ret->type.idx=%s->type.idx;\n" +" ret->type.size=%s->type.size;\n" +"}\n", + opstbl[k].acro, + typtbl[i], + typtbl[j], + j>=i?typtbl[j]:typtbl[i], + typtbl[i], + opstbl[k].str, + typtbl[j], + j>=i?"v2":"v1", + j>=i?"v2":"v1", + j>=i?"v2":"v1"); + + } else { + + printf("" +"static void \n" +"op_%s_%s_%s(value_t *v1,value_t *v2,value_t *ret)\n" +"{\n" +" ret->v.%s = ( v1->v.%s %s v2->v.%s );\n" +" ret->type.type=V_BASE;\n" +" ret->type.idx=B_UL;\n" +" ret->type.size=4;\n" +"}\n", + opstbl[k].acro, + typtbl[i], + typtbl[j], + "ul", + typtbl[i], + opstbl[k].str, + typtbl[j]); + } + + } + + } + + } + + /* create the array from within which the runtime functions + will indexed to get a function pointer */ + + printf("void (*opfuncs[%d][%d][%d])()={\n", NTYPS, NTYPS, NOPS); + + for(i=0;itype.idx][v2->type.idx][i])(v1,v2,ret);\n\ +}\n", NOPS, NOPS); + exit(0); +} --- crash-4.0-4.6/extensions/libsial/README 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/README 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,1024 @@ + + SIAL : Simple Image Access Language + =================================== + + Sial is a C interpreter that permits easy access to the symbol +and type information stored in a executable image like a coredump or live +memory interfaces (e.g. /dev/kmem, /dev/mem). It support a FULL C +syntax and the same variable and function scope and type. Symbols and +type information in the image become standard variables and types in +the sial scripts's context. + + This README focuses on the differences between sial and a C compiler +so, for C syntax information, please refer to a C reference manual. I +also explain the mechanisms of the API that allow sial to be inserted +into any debugging tool that deals with objects and can furnish symbol +and type information to sial through the API. The more specific lcrash +sial implementation is described and a howto on creating commands is +also given here. + +Preprocessor commands +--------------------- + + All preprocessor commands I knew of are supported. #define, + #undef, #ifdef, #if, #ifndef, #else, #elif, #endif and #include. + + This one is ignored: #ident #pragma + + Sial has a builtin secondary parser for preprocessor expression + evaluation. + +Symbols +------- + + The symbols from the system image and their associated value + are available from within sial. Since, most of the time, no + type information is associated with the symbols, a reference to + a symbol return the actual address of the symbol within the + system image. So you might say that sial adds a level of + reference for symbol information. Let's say there is a (int) + symbol called "nproc" that contains the number of processes + currently running on the system. To get the value of nproc from + sial one would have to write something like this: + + void + showprocs() + { + int i; + int np; + + np=*(int*)nproc; + + for(i=0;ip_next) + + do something... + } + } + +Variable Initialization +-------------------- + + Variable assignment at the time of declaration is supported. + Also, the function __init() will be executed, if it is defined, + right after the macro file as been compiled. + + Using an uinitialized variable will generate a run time error. + +Variable types +-------------- + + All types made available from the API can be used. + These are the types already defined in the executable image. + + Floating point types are not supported at this time. I have no + plan to support it. + + Declaration of arrays is not supported. To access a array from + the image, use a pointer. + + Unions and structures type declarations are supported and can be + used to create additional types that become available within + the same macro file. + + Typedef are supported. + + Function pointers are not supported (use 'string' type instead, + see "Operators" below) + + Sial defines a 'string' types to handle ansi C strings within + the interpreter. This string type also support some of the + operator (+, ==, =, !=, etc... see below) + +Variable Scope +-------------- + + All symbols available in the system image become global + variable in the sial context. + + Variable declared within sial can be given one of 3 different + scopes like in normal C. + + GLOBAL: A variable that is declared outside a + function that is not marked as static. this variable if + available to all macros that have been load into the + interpreter. + + Ex: file1: + + int global; int func() { } + + file2: + + func2() + { + int i; + + i=global; + } + + NB: since sial currently validates variable existence only at + run time there is no need to declare a 'global' as an 'extern' + variable. At run time, if none of the currently loaded macros + define a global variable called 'global' then 'i=global' will + fail with a 'unknown variable' error. + + FILE: A Variable that is declared outside any + functions that is tagged with the static keyword. This + variables is available to all functions defined in the + same macro file. + + Ex: + + file1: + + static int maxproc=100; + sraruc int array; + + __init() + { + int i; + + for(i=0;i<10;i++) array[i]=-1; + + } + + void func1() + { + int i; + + for(i=0;i, <=, >=. + + examples: + + s = "hello" + "World"; + + if("hello" == "world" ) { ... } + + The 'in' operator is supported on dynamic arrays. + + if(i in array) { ... } + str=i in array ? "yes" : "no"; + + Function callbacks + ------------------ + + Function calls through function pointers is not possible + currently. Instead, use a 'string' type to achieve the same + result. When sial is about to perform a call, it will look at + the type of the variable used to name the function. If the type + is 'string' it will use the value that string and call that + function instead. + + func0(int i, int j) + { + printf("i=%d j=%d\n", i,j); + } + func1(string func) + { + func(1,2); + } + main() + { + func1("func0"); + } + + In the above example, func1() ends up calling func0() not + func. This can be used as a callback mechanism, specially + useful for creating generating function that call s linked list + of objects and calls a variable function for each object. Like + a function that walks tasks or procs. + + The sizeof() operator is evaluated at execution time. So you + can supply a type, a variable, or any valid expression and the + appropriate size will be returned. The expression *will* be + executed, so be careful. + +Statements +---------- + + All C statements except 'goto' are supported. + + The 'for(i in array)' is supported on dynamic arrays. + +Dynamic arrays +------------------------------- + + When indexing through a non pointer variable you end up + creating a dynamic array. + + Example: + + int func() + { + char *cp, c; + int array, i; + + cp=(char *)symbol; + c=cp[10]; + + array[0]="one string"; + array[12]="second string"; + + for(i in array) { + + printf("array[%d]=%s\n", i, array[i]); + } + + } + + In the 'c=cp[10]' statement, sial goes to the system image to + get one 'char' at the address symbol+10. + + In the second case, 'array' is not a pointer, it's a 'int'. So + sial threats all indexing through it as dynamic. + + Additionally, sial supports multi levels of dynamic index, + which makes possible to create random trees of indexed values: + + int func() + { + int array, i, j; + + array[10]="array10"; + array[10][3]="array10,3"; + array[20]="array20"; + array[20][99]="array20,99"; + + for(i in array) { + + printf("array[%d]=%s\n", i, array[i]); + + for(j in array[i]) { + + printf("array[%d][%d]=%s\n", i, j, array[i][j]); + + } + + } + } + + I think it is a good thing to have, since system image access + and analysis require frequent lists search. So for example, + with dynamic arrays, one can walk the proc list taking note of + the proc*, then walking a user thread list taking note of the + thread* and gathering some metrics for each of these threads. + In order to get to these metrics at some later point in the + execution, something like this could be used: + + func() + { + proc *p; + + for(p in procs) { + + thread *t; + + for(t in procs[p]) { + + int rss, size; + + /* we use index 0 for rss and 1 for size */ + printf("proc %p, thread %p, rss:size = %d:%d\n" + , p, t, procs[p][t][0], procs[p][t][1]); + } + } + } + + Arrays are always passed by reference. On creation the + reference count is set to one. So this array will exist + untill the variable it's assigned to dies. + + Arrays can be created by dso's. See the DSo section below for more + information and examples of this. + + +Sial API +-------- + + Sial can be integrated into any tool that needs to access + symbol and type information from some object. Currently it is + integrated in lcrash and icrash (tools that access Linux and + Irix kernel images respectively), but it should be possible to + use it, for example, in dbx or gdb. The API gives a simple + interface through which the host application sends symbol and + type (including member) information and gives access to the + image itself so that sial can read random blocks of data from + the image. + + >> sial_builtin(bt *bt) + + Install some set of builtin function. See below + (builtin api). + + + >> sial_chkfname(char *fname, int silent); + + Will check for the exsistance of a function in sial. + Typically used to check xtra entry points before the + application registers a new command (see sial_setcallback). + + >> sial_open(): + + The first function that should be called is sial_open(). + sial_open() will return a value of 1 if everything is ok or 0 + in case of some problem. This call initializes internal date + for the sial package. + + >> sial_setapi(apiops* ops, int nbytes): + + This function will setup the callbacks that sial will use + to get information from the application. + + See 'callback interface' below. + + >> sial_load(char *name); + + To have sial load and compile a macro or a set of macro + use sial_load(). Parameter name gives the name of the + file to compile. If name points to a directory instead, + then all the files in this directory will be load. So + an application would call sial_load() when it first + starts up specifying some well known files or + directories to load. For example $HOME/.xxx and + /etc/xxx would be loaded, ~/.xxx containing user + defined macros, and /etc/xxx containing system macros. + + >> sial_unload(char *funcname) + + To unload the a macro file use this function. + "funcname" is the name of any global function in the + file you want to unload. + + >> void sial_setcallback(void (*scb)(char *)); + + To be called prior to any load calls. + After each loads, sial will call this function + back with the name of each functions compiled. + Typicly, the application will then perform checks + and potencially install a new command for this + function. + + ex: + void + reg_callback(char *name) + { + char fname[MAX_SYMNAMELEN+sizeof("_usage")+1]; + _command_t cmds[2]; + + snprintf(fname, sizeof(fname), "%s_help", name); + if(!sial_chkfname(fname, 0)) return; + snprintf(fname, sizeof(fname), "%s_usage", name); + if(!sial_chkfname(fname, 0)) return; + + cmds[0].cmd=strdup(name); + cmds[0].real_cmd=0; + cmds[0].cmdfunc=run_callback; + cmds[0].cmdparse=parse_callback; + cmds[0].cmdusage=usage_callback; + cmds[0].cmdhelp=help_callback; + cmds[1].cmd=0; + unregister_cmd(cmds[0].cmd); + (void)register_cmds(cmds); + } + + >> sial_setipath(char *path) + + When sial processes a #include directive it will use + the specified path as a search path. + The usual PATH format is supported ex: + "/etc/include:/usr/include". + + >> sial_setmpath(char *path) + + When sial_load() is called with a relative path name or + just the name of a file, it will use a search PATH to + locate it. The path parameter to sial_set,path() sets + this path. The usual PATH format is supported ex: + "/etc/xxx:/usr/lib/xxx". + + >> sial_setofile(FILE *ofile) + + All output of sial commands will be send to file ofile. + + >> sial_cmd(char *cmd, char **argv, int nargs) + + This is the way to execute a sial command that as been + loaded. 'cmd' is the name of function to call. 'argv' + are the argument to this function. 'nargs' is the + number of argument in array 'argv'. + + Sial_cmd() will process argv and make the corresponding + values available to the function by creating global + variables that the function can test and use. + + >> sial_showallhelp() + + This command will send a complete list of the commands + long with the usage and help for each one of them. This + function should be called when the user request + something like 'help all'. + + >> sial_showhelp(char *func) + + This will display the help information for a particular + function loaded in sial. + +The callback interface +---------------------- + + Everytime sial needs some piece of information, it will call + the application back for it. THe sial_apiset() function is used + to install this callback interface into sial. Here is the list + of callback functions: + + typedef unsigned long long ull; + + Sial_apiset() passes this structure to sial: + + typedef struct { + + int (*getmem)(ull, void *, int); + int (*putmem)(ull, void *, int); + int (*member)(char *, ull, type * , member *); + int (*getctype)(int ctype, char * , type*); + char* (*getrtype)(ull, type *); + int (*alignment)(ull); + int (*getval)(char *, ull *); + enum_t* (*getenum)(char *name); + def_t* (*getdefs)(); + uint8_t (*get_uint8)(void*); + uint16_t (*get_uint16)(void*); + uint32_t (*get_uint32)(void*); + uint64_t (*get_uint64)(void*); + } apiops; + + + The apiops* struct defines the following member and function pointers: + + -getmem(ull addr, void *buffer, int nbytes) + + Read nbytes from image at virtual address addr (32 or + 64 bit) to buffer. + + -putmem(ull addr, void *buffer, int nbytes) + + Write nbytes from buffer to image at virtual address + addr (32 or 64 bit). + + -member(char *name, ull pidx, type *tm, member *m); + + Get information on a structure member called name. + Pidx is a unique type index for the parent structure. + The getctype() function should fill in this index in + it's type*. The dwarf model uses unique indexes (die + offsets) that can be used here. 'tm' will hold + information on the type of the member. 'm' will hold + information on the member specific stuff (bit sizes, + bit offset etc.). + + Use the sial_member_...() functions to setup m. + Use the sial_type_...() functions to setup t. + + -getctype(int ctype, char *name, type *tout) + + Get type information for a complex type. Ctype + specifies that name is a type of type struct/union or + enum. tout contain the returned type information. + + -getrtype(ull idx, type *t) + + Gets the type string linked to a typedef. For example, + the gettdeftype() would return + "unsigned long long". This enables sial to drill down a + typedef (a typedef can be build from a typedef + itself) in order to perform proper type validation for + assignment or function parameters or return values. + + -getval(char *sname, ull *value) + + Returns the value of symbol "sname" from the image. The + value is returned in 'value'. On any image this is + address of the symbol within the image itself, not the + value of the symbol itself. See explanation of this + above. + + -getenum(char *name); + + Return a list of enum values. + Sial will make these available as symbol for the duration + of the compile. + + -getdefs() + + Return a list of #defines to be active througout the + sial session. + + -get_uint8/16/32/64() + + Return converted unsigned integers. As parameters are passed pointers + to unsigned int values in dump representation. The return values are + the corresponding unsigned int values in the representation of the + host architecture, where sial is running. + +The builtin API +--------------- + + Sometime it is necessary to create a C function that will + handle some piece of the work, that a macro cannot do. Sial's + builtin function are implemented this way. Generic function + like 'printf' or 'getstr' can get some parameter input from the + macros and do something (printf) or they get some information, + map it to a sial value and return it to a macro (getstr). + + + Sial can load new functiosn from DSOs. If the extension of + a file name is ".so" then sial opens it and gets a list + of function specs from it. Unload of that file will + uninstall these functions. + + The API between the dso and sial is quite simple at this time. + It has not been exercised as must as it would need to, so it + might get more flexible and thus complex in the future. + + Here are two examples of simple extensions. + + This is an example of a simple extension. An equivalent + os the "hello world" C program, but this one gets 2 parameters + , one int and one string and returns the received int. + + #include "sial_api.h" + + value * + helloworld(value *vi, value *vs) + { + int i=sial_getval(vi); + char *s=(char*)sial_getval(vs); + + sial_msg("Hello to the world![%d] s=[%s]\n", i, s); + return sial_makebtype(1); + } + + BT_SPEC_TABLE = { + { "int hello(int i, string s)", helloworld}, + { 0, 0} + }; + + static char *buf; + + BT_INIDSO_FUNC() + { + sial_msg("Hello world being initialized\n"); + buf=sial_alloc(1000); + return 1; + } + + BT_ENDDSO_FUNC() + { + sial_msg("Hello world being shutdown\n"); + sial_free(buf); + } + + The BT_SPEC_TABLE is scanned. It's a simple table + with 2 entries per functions and terminated with + a NULL prototype. + + The DSO initializer function is called. + If it returns 0 then installtion is terminates. + If it returns 1 we proceed forward. + + The prototype is compiled and a syntax error + will send the error message to the application + output file (stdout usually). + + When the prototype as compiled with no errors + the function is installed and ready to be used from + sial macros. + + Type checking is performed by sial at + execution time on both, the function parameters + andthe function return. + + DSO's can also receive, create and manipulate dynamic arrays. + Here is an example of this: + + #include "sial_api.h" + + #ifdef ARRAY_STATIC + static value *v; + #endif + + value * + mkarray(value* vi) + { + int i=sial_getval(vi); + #ifndef ARRAY_STATIC + value *v=sial_makebtype(0); + #endif + + sial_msg("Received value [%d]\n", i); + /* build an array indexed w/ int w/ 2 string values */ + sial_addvalarray(v, sial_makebtype(0) + , sial_makestr("Value of index 0")); + sial_addvalarray(v, sial_makebtype(2) + , sial_makestr("Value of index 2")); + #if ARRAY_STATIC + /* + For a static array use : + Then the array will persist until you Free it. + */ + sial_refarray(v, 1); + #endif + return v; + } + + value * + showstrarray(value* va) + { + value *v1=sial_strindex(va, "foo"); + value *v2=sial_strindex(va, "goo"); + + printf("array[1]=%d\n", sial_getval(v1)); + printf("array[2]=%d\n", sial_getval(v2)); + sial_addvalarray(va, sial_makestr("gaa"), sial_makebtype(3)); + sial_addvalarray(va, sial_makestr("doo"), sial_makebtype(4)); + sial_freeval(v1); + sial_freeval(v2); + return sial_makebtype(0); + } + + value * + showintarray(value* va) + { + value *v1=sial_intindex(va, 1); + value *v2=sial_intindex(va, 2); + + printf("array[1]=%d\n", sial_getval(v1)); + printf("array[2]=%d\n", sial_getval(v2)); + sial_freeval(v1); + sial_freeval(v2); + return sial_makebtype(0); + } + + BT_SPEC_TABLE = { + { "int mkarray(int i)", mkarray}, + { "void showintarray(int i)",showintarray}, + { "void showstrarray(int i)",showstrarray}, + { 0, 0} + }; + + static char *buf; + + BT_INIDSO_FUNC() + { + sial_msg("mkarray initialized\n"); + #ifdef ARRAY_STATIC + /* we will need a static value to attach the + array too */ + v=sial_makebtype(0); + #endif + return 1; + } + + BT_ENDDSO_FUNC() + { + sial_msg("mkarray being shutdown\n"); + #ifdef ARRAY_STATIC + sial_freeval(v); + /* freing the value decrements the reference + count by one. So, if none of the calling + macros copied the value to a static + sial variable, it will free the array */ + #endif + } + +Macro Construction +------------------ + + When sial as been integrated into an application and a basic + set of builtin command as been created, it is time to start + creating the macro themselves. Some basic rules and conventions + apply to macro construction that make the coding and + documenting steps of macro definition easy. + + I will use the function foo as an example. Function foo is + defined in file /usr/tmp/sial/foo. Function foo is a user + callable function, meaning that it can be executed by the + sial_cmd() function. The command input section of the + application can thus call sial_cmd("foo", char *argv, int + nargs) to execute the foo macro. + + ------------ file foo ------------- + + foo_opt(){ return "ab:c"; } + + foo_usage(){ return "[-a] [-b barg] [-c] addr [addr [addr...]]"; } + + foo_help(){ return "This is an example function"; } + + static int + doproc(proc_t *p) + { + printf("p=0x%p\n", p); + } + + int foo() + { + int all, i; + string barg; + + if(exists(aflag)) all=1; + else all=0; + + if(exists("bflag")) bval=barg; + + for(i in argv) { + + proc_t *p; + + p=(proc_t*)atoi(argv[i], 16); + + doproc(p); + + } + } + + ------------ end of file foo -------------- + + The application calls sial_load() to load foo. Sial calls + back the application with the names of all fucntions declared + in that file. The aplication can then register commands for + the user to type according to this list of functions. + In this case 'foo'. + + The application then uses sial_cmd() to run a specific + command 'foo'. + + Before executing the command, sial checks if a foo_opt() + function exists and if so, calls it. This function returns the + proper getopt() argument specification string. If this function + does not exists then all arguments are passed down to the foo() + function directly. + + If the arguments supplied by the user do not follow the proper + syntax then the function foo_usage() will be called, if it + exists. If the foo_usage() function does not exists, a generic + error message is generated by sial. + + If the command 'help foo' is issued, the application should be + calling sial_exefunc("help_foo", 0) whish will return a VALUE_S + for the help for foo. Or whatever foo_help() returns. + + Each option, their associated value and addition arguments are + made available to the foo funtion by creating the following + global variables before the actual call. + + Each option, if specified, will trigger the existence of flag + variable. In the foo() case, this means that variables aflag, + bflag and cflag can possibly exist. The function + exists("variable name") can then be used to test for this + option presence. + + If an option has an associated value (getopt's ':' is specified + on the string foo_opt() returns) this value is made available + as a string type variable called Xarg, where X is the option + letter. In the case of foo() variable 'string barg' would exist + if the -b option was supplied by the user. + + The rest of the arguments supplied by the user are made + available in an array of 'string' called argv. argv[0] is + set to the name of the function 'foo' and argc is a global + that defines how many argv their are. + +Builtin functions +================= + + Here is a description of the current set of builtin functions. + + unsigned long long + atoi(string value [, int base]) + + Convert a string value to a long long. Base is the base + that should be used to process the string e.g. 8, 10 or + 16. If not specified, then the standard numeric format + will be scnanned for ex: + + 0x[0-9a-fA-F]+ : hexadecimal + 0[0-7]+ : octal + [1-9]+[0-9]* : decimal + + This function is used when converting command line + arguments to pointers. + + Example: + + void + mycommand() + { + int i; + + for(i=1;i> mycommand 0xa80000004ab14578 + + int exists(string name) + + Checks for the existance of a variable. Returns 1 if + the variables does exist and 0 otherwise. This function + is mostly used to test if some options were specified + on when the macro was executed from command line. + + It can also be used to test for image variable. + + example: + + void + mycommand() + { + if(exists("aflag")) { + + // user has specified -a option + } + } + + void exit() + + Terminate macro excution now. + + int getchar() + + Get a single character from tty. + + string gets() + + Get a line of input from tty. + + string getstr(void *) + + Gets a null terminated string from the image at the + address specified. Sial will read a series of 16 byte + values from the image untill it find the \0 character. + Up to 4000 bytes will be read this way. + + string getnstr(void *, int n) + + Gets n characters from the image at the specified + address and returns the corresponding string. + + string itoa(unsigned long long) + + Convert a unsigned long long to a decimal string. + + void printf(char *fmt, ...); + + Send a formatted message to the screen or output file. + For proper allignment of output on 32 and 64 bit systems + one can use the %> sequence along with the %p format. + + On a 32 bit system %p will print a 8 character hexadecimal + value and on a 64 bit system it will print a 16 character + value. So, to get proper alignment on both type of systems + use the %> format which will print nothing on a 64 bit system + but will print 8 times the following character on a 32 bit + system. + + example: + + struct proc *p; + + printf("Proc %> uid pid\n"); + printf("0x%p %8d %8d\n" + , p, p->p_uid,p_p_pid); + + int sial_depend(string file) + + Loads a macro or directory of macros called + 'file'. Contrary to sial_load() it will not + give any error messages. Returns 1 on success + 0 otherwise. + + int sial_load(string file) + + Loads and compiles a sial macro file. + returns 1 if successful or 0 otherwise. + + void sial_unload(string file) + + Unload's a sial macro file + + string sprintf(string format, ...) + + Creates a string from the result of a sprintf. + Example: + + void + mycommand() + { + + string msg; + + msg=sprintf("i=%d\n", i); + } + The result will be truncated to maxbytes if it would be + longer. + + int strlen(string s) + + Return the length of string s. + + string substr(string s, int start, int len) + + Creates a string from the substring starting a charcater + 'start' of 's' for 'len' characters. + example: + + s=substr("this is the original", 6, 2); + + So 's' will become "is". + + + -------------------------------------------------------- + +Questions/Comments +Luc Chouinard, lucchouina@yahoo.com --- crash-4.0-4.6/extensions/libsial/README.sial 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/README.sial 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,97 @@ + + This file (README.sial) gives some information specific to the crash(1) + integration of sial. + + Please refer to the README file generic libsial informations. + + An example script can be found as ../scripts/sial.c + + PATHS and ENVIRONMENT + ===================== + + The default location to look for macros and include files are + /usr/share/sial/.sial and ~/..sial + + The default 'root' for #include location are thus: + + /usr/share/sial/crash/include and ~/.sial/include. + + There are two environment variables that control these locations. + + SIAL_IPATH : path to use for include files. + ex: setenv SIAL_IPATH /usr/include:$(ROOT)/usr/include:~/.lcrash/include + + SIAL_MPATH : path to use for finding macro files. + ex: setenv SIAL_MPATH /usr/tmp/macs:~/.sial + + #define's + ===================== + + The current independent #define's are: + + Name Value/format + ==== ===== + linux 1 + __linux 1 + __linux__ 1 + unix 1 + __unix 1 + __unix 1 + LINUX_RELEASE 0x%08x + LINUX_2_2_16 (LINUX_RELEASE==0x020210) + LINUX_2_2_17 (LINUX_RELEASE==0x020211) + LINUX_2_4_0 (LINUX_RELEASE==0x020400) + LINUX_2_2_X (((LINUX_RELEASE) & 0xffff00) == 0x020200) + LINUX_2_4_X (((LINUX_RELEASE) & 0xffff00) == 0x020400) + + For i386 images/cores only. + + Name Value + ==== ==== + i386 1 + __i386 1 + __i386__ 1 + + For ia64 images/cores only. + + Name Value + ==== ===== + ia64 1 + __ia64 1 + __ia64__ 1 + __LP64__ 1 + _LONGLONG 1 + __LONG_MAX__ 9223372036854775807L + + If you feel there should be more standard defined pushed + there, let me know. + + + Loading/Unloading + ===================== + + crash defines two new commands for loading and unloading sial + macros called "sload" and "sunload", respectively. + + Using "sload" should be enough, since sial automaticly "sunload's" + the previous copy after successfully compiling the new one. + + DSO's must be unload'ed before you can reload them. + + Editing + ===================== + + To facilitate macro editing, crash makes a "edit" command available. + edit will get you directly in the macro file that + defines function "funcname" at the line where "funcname" starts. + + edit -f /somedir/somefile, will start editing a new/old file. + + edit -l will get you position on the "l"ast compile or runtime error. + + Macro integration into the crash framework + ============================================= + + Refer to the README file on writing a user level command. + Also look at the 'sial.c' example in the scripts directory + --- crash-4.0-4.6/extensions/libsial/sial_alloc.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_alloc.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,414 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ + +#define MEMDEBUG 1 +/* +*/ +#include "sial.h" +#include +#include +#include +#include +#include +#include +#include + +#if linux +#define __return_address (void*)0 +# if __LP64__ +# define NKPC 16 +# else +# define NKPC 4 +# endif +#else +# if (_MIPS_SZLONG == 64) +# define NKPC 16 +# else +# define NKPC 4 +# endif +#endif +#define PAGESIZE (NKPC*1024) + + +/* + Jump defines +*/ +#define MAXJMPS (S_MAXDEEP*3) +int njmps=0; + +typedef struct blklist { + + struct blklist *next; /* root based doubly chained */ + struct blklist *prev; + int size; /* size of the allocation */ + int istmp; /* was flaged as temp ? */ + int level; /* coresponding level */ + void *caller; /* __return_address of caller */ + void *freer; /* __return_address of freer */ + +} blist; + +#define SIZEBL (((sizeof(blist)+8)/8)*8) +static blist temp={ &temp, &temp, 0, 0, 0, 0, 0 }; + +value_t* +sial_findsym(value_t *vadr) +{ + char *addr=sial_getptr(vadr, char); + char *p = API_FINDSYM(addr); + + if(p) { + return sial_setstrval(sial_newval(), p); + } else { + return sial_setstrval(sial_newval(),""); + } +} + +value_t* +sial_showaddr(value_t *vadr) +{ +void *addr=sial_getptr(vadr, void); +blist *bl; +int n=0; + + for(bl=temp.next; bl != &temp; bl=bl->next) { + + if(bl->caller==addr) { + + if(!(n%8)) sial_msg("\n"); + sial_msg("0x%08x ", ((char *)bl) + SIZEBL); + n++; + } + } + return sial_makebtype(0); +} + +static int memdebug=0; + +/* these two functions must *not* receive any values */ +value_t* sial_memdebugon() { memdebug=1; return sial_makebtype(0); } +value_t* sial_memdebugoff() { memdebug=0; return sial_makebtype(0); } +int sial_ismemdebug() { return memdebug; } + +value_t* +sial_showtemp() +{ +blist *bl; +int i, totsiz, totbl; +static int ncallers=0; +static void *callers[1000]; +static int count[1000]; +static int sizes[1000]; +static int dir=0; + + if(!dir) { + + memset(callers, 0, sizeof(void*)*1000); + memset(count, 0, sizeof(int)*1000); + memset(sizes, 0, sizeof(int)*1000); + ncallers=0; + } + + if(dir==1) dir=0; + else dir=1; + + for(bl=temp.next; bl != &temp; bl=bl->next) { + + int i; + + for(i=0;icaller) { + if(dir) { count[i]++; sizes[i]+=bl->size; } + else { count[i]--; sizes[i]-=bl->size; } + break; + } + + if(i==ncallers) { + callers[ncallers]=bl->caller; + count[ncallers]=1; + sizes[ncallers]=bl->size; + ncallers++; + } + + } + totbl=totsiz=0; + for(i=0;isize=size; + bl->level=njmps; + bl->prev=bl->next=bl; + bl->istmp=0; + TAG(m+SIZEBL); + return m+SIZEBL; +} + +void +sial_maketemp(void *p) +{ +blist *bl; + + if(!p) return; + + bl=(blist*)(((char*)p)-SIZEBL); + bl->prev=&temp; + bl->next=temp.next; + bl->istmp=1; + temp.next->prev=bl; + temp.next=bl; +} + +void * +sial_calloc(int size) +{ +char *p=sial_alloc(size); + + TAG(p); + memset(p, 0, size); + return p; +} + +static void +sial_free_bl(blist *bl, void *ra) +{ + bl->freer=ra; + bl->prev->next=bl->next; + bl->next->prev=bl->prev; + +#ifdef MEMDEBUG + + if(memdebug) { + + /* help out dbx/gdb when they're watching the allocated area + by writing over it */ + { + int i, ni=bl->size/sizeof(void*); + char *p=(char*)bl; + unsigned long up; + + for(i=0;inext; + sial_free_bl(bl, __return_address); + bl=next; + } +} + +int +sial_istemp(void *p) +{ + return ((blist*)(((char*)p)-SIZEBL))->istmp; +} + +char * +sial_strdup(char *s) +{ +char *ns=sial_alloc(strlen(s)+1); + + strcpy(ns, s); + TAG(ns); + return ns; +} + +void * +sial_dupblock(void *p) +{ +void *p2; +int size=((blist*)(((char*)p)-SIZEBL))->size-SIZEBL; + + if(!p) return 0; + + p2=sial_alloc(size); + memcpy(p2, p, size); + return p2; +} + +/* cheap realloc. we drop the original + This function is only used ones in configmon(1) code */ +void * +sial_realloc(void *p, int size) +{ +int cursize=((blist*)(((char*)p)-SIZEBL))->size-SIZEBL; +void *p2; + + p2=sial_calloc(size); + memcpy(p2, p, cursize 1) { + + jmp_buf *env; + + while(njmps && jmps[--njmps].type!=type); + if(jmps[njmps].val) *(jmps[njmps].val)=val; + env=jmps[njmps].env; + + /* reset the variable level too... */ + sial_setsvlev(jmps[njmps].svlev); + + longjmp(*env, 1); + /* NOT REACHED */ + + } else sial_parseback(); /* we use the same code for initializing + static and automatic variables. In the case of statiuc variables + is the initizer expression throws an error then there's no J_EXIT + jump context and njmps is null. It's treated as a parsing error */ +} + +void +sial_popjmp(int type) +{ + if(!njmps) { + + sial_error("Pop underflow!"); + } + njmps--; + if(jmps[njmps].type != type) { + + sial_error("Wrong pop! %d vs %d", jmps[njmps].type, type); + } + sial_setsvlev(jmps[njmps].svlev); +} + --- crash-4.0-4.6/extensions/libsial/sial_api.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_api.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,1510 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include "sial.h" +#include "sial.tab.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* here we do some caching of the information. This can have a speedup effect + since it limits the number of accesses we do the dwarf (or whatever type) db that + drives the type and symbols information + */ + +static stinfo_t slist={"root"}; + +/* running key to new structures */ +static ull nextidx=0, abitype=ABI_MIPS; +#define LOCALTYPESBASE 0x80000000 +static ull sial_nextidx(void) { return LOCALTYPESBASE+nextidx++; } + +/* this set of function is used to cleanup tdefs after their use. + Trailing tdefs can be combersome. Trailing struct/union/enum get new idx + each time and are not a trouble */ +static stinfo_t*tag=0; +void +sial_tagst(void) +{ + tag=slist.next; +} + +void +sial_flushtdefs(void) +{ +stinfo_t*st=slist.next; +stinfo_t*last=&slist; + + while(st != tag) { + + stinfo_t*next=st->next; + + if(st->ctype.type==V_TYPEDEF && st->idx & LOCALTYPESBASE) { + + sial_free(st->name); + sial_free(st); + last->next=next; + + } else last=st; + + st=next; + + } + tag=0; +} + +static stinfo_t* +sial_getst(char *name, int type) +{ +stinfo_t*tst; + + for(tst=slist.next; tst; tst=tst->next) { + + if(tst->ctype.type == type && tst->name && ! strcmp(tst->name, name)) { + + return tst; + } + } + return 0; +} + +#if 0 +Not used yet. +static void +sial_rmst(stinfo_t*rst) +{ +stinfo_t*st=slist.next; +stinfo_t*last=&slist; + + while(st) { + + if(st==rst) { + + last->next=st->next; + sial_free(st->name); + sial_free(st); + + return; + + } + + last=st; + st=st->next; + } +} +#endif + +stinfo_t* +sial_getstbyindex(ull idx, int type) +{ +stinfo_t*tst; + + for(tst=slist.next; tst; tst=tst->next) { + + if(tst->ctype.type == type && tst->idx == idx) { + + return tst; + } + } + return 0; +} + +static void +sial_addst(stinfo_t*st) +{ +stinfo_t*tst; + + tst=slist.next; + slist.next=st; + st->next=tst; +} + +typedef struct neg_s { + struct neg_s *next; + char *name; +} neg_t; + +static neg_t *nlist=0; + +static void +sial_addneg(int ctype, char *name) +{ +neg_t *neg; + + if(ctype != V_TYPEDEF) return; + neg=sial_alloc(sizeof *neg); + neg->name=sial_strdup(name); + neg->next=nlist; + nlist=neg; +} + +int +sial_isneg(char *name) +{ +neg_t *neg; + + for(neg=nlist; neg; neg=neg->next) + if(!strcmp(neg->name, name)) return 1; + return 0; +} + +/* + This function is called by sial_vardecl() when the typedef storage class + as been specified. In which case we need to create new typedefs not variables. +*/ +void +sial_tdef_decl(dvar_t*dv, type_t*t) +{ + while(dv) { + + dvar_t*next; + + stinfo_t*st=sial_calloc(sizeof(stinfo_t)); + + if(dv->nbits) sial_error("No bits fields for typedefs"); + if(dv->idx) { + + /* we change a 'typedef type var[n];' into a 'typedef type_t*var;' */ + sial_freeidx(dv->idx); + dv->idx=0; + dv->ref++; + } +#if 0 +At this time we do not give any error messages or warnings. +If a type is redefined within a single file that will means +problem for the user put this is not a full blown C compiler. + + { + type_t*t=sial_newtype(); + + if(API_GETCTYPE(V_TYPEDEF, dv->name, t)) { + + sial_warning("Typedef %s already defined in image, redefinition ignored", + dv->name); + } + sial_freetype(t); + } +#endif + t->typattr &= ~sial_istdef(t->typattr); + sial_duptype(&st->rtype, t); + sial_pushref(&st->rtype, dv->ref); + st->name=dv->name; + dv->name=0; + st->idx=sial_nextidx(); + st->ctype.type=V_TYPEDEF; + + sial_addst(st); + + next=dv->next; + dv->next=0; + sial_freedvar(dv); + dv=next; + } +} + +int +sial_ispartial(type_t*t) +{ +stinfo_t*st=sial_getstbyindex(t->idx, t->type); + + if(!st) { + + sial_error("Oops sial_ispartial"); + } + return !st->all; +} + +char * +sial_gettdefname(ull idx) +{ +stinfo_t*tst=sial_getstbyindex(idx, V_TYPEDEF); + + if(tst) return tst->name; + else return 0; +} + +static int init=0; +static void +sial_chkinit(void) +{ + if(!init) { + + sial_error("Sial Package not initialized"); + + } +} + +void +sial_getmem(ull kp, void *p, int n) +{ + sial_chkinit(); + if(!API_GETMEM(kp, p, n)) { + + sial_error("Error on read from 0x%llx for %d", kp, n); + + } +} + +void +sial_putmem(ull kp, char *p, int n) +{ + sial_chkinit(); + if(!API_PUTMEM(kp, p,n)) { + + sial_error("Error on write at 0x%llx for %d", kp, n); + + } +} + +void +sial_partialctype(int type, char *name) +{ +stinfo_t*st; + + /* check first if we have a partial of that type + already in progress (after a forward declaration) */ + if((st=sial_getst(name, type))) { + + /* if it's complete we need to start a new one */ + if(!st->all) return; + + } + st=sial_calloc(sizeof(stinfo_t)); + st->name=sial_strdup(name); + st->ctype.type=type; + st->all=0; + st->ctype.idx=st->idx=sial_nextidx(); + sial_addst(st); +} + +void +sial_startctype_named(int type, char *name) +{ +stinfo_t*st; + + /* if no partial yet start one */ + if(!(st=sial_getst(name, type)) || st->all) + sial_partialctype(type, name); +} + +void +sial_startctype(int type, node_t*namen) +{ + sial_startctype_named(type, NODE_NAME(namen)); +} + +int +sial_samectypename(int type, ull idx1, ull idx2) +{ +stinfo_t*st1, *st2; + + if((st1=sial_getstbyindex(idx1, type)) && + (st2=sial_getstbyindex(idx2, type))) { + + // check names + if(!strcmp(st1->name, st2->name)) return 1; + + // check all members and sizes in order + // unamed ctypes can end up here too... + if(st1->stm) { + stmember_t *m1=st1->stm, *m2=st2->stm; + while(m1 && m2) { + if(strcmp(m1->m.name, m2->m.name)) break; + if(m1->m.offset != m2->m.offset ) break; + if(m1->m.size != m2->m.size ) break; + m1=m1->next; + m2=m2->next; + } + if(!m1 && !m2) return 1; + } + else if(st1->enums) { + + enum_t *e1=st1->enums, *e2=st2->enums; + while(e1 && e2) { + if(strcmp(e1->name, e2->name)) break; + if(e1->value != e2->value ) break; + e1=e1->next; + e2=e2->next; + } + if(!e1 && !e2) return 1; + } + + } + return 0; +} + +#define VOIDIDX 0xbabebabell +type_t* +sial_getvoidstruct(int ctype) +{ +type_t*bt=sial_newtype(); + + bt->type=ctype; + bt->idx=VOIDIDX; + bt->size=0; + bt->ref=0; + return bt; +} + +void sial_fillst(stinfo_t *st); + +/* Just in case this is an unnamed structure member then we need + to add it to the slist ourselves using the index. sial_getctype() would + not found it. +*/ +static void +sial_memstinfo(stmember_t *stm, char *pname) +{ +int type=stm->type.ref?stm->type.rtype:stm->type.type; + + if(is_ctype(type)) { + + if(!sial_getstbyindex(stm->type.idx, type)) { + + stinfo_t*st=sial_calloc(sizeof(stinfo_t)); + + sial_duptype(&st->ctype, &stm->type); + st->ctype.type=type; + // dereference level is attached (wrongly) to type... + // zap it + st->ctype.ref=0; + st->idx=st->ctype.idx; + st->name=sial_strdup(pname); + sial_addst(st); + } + } +} + +void +sial_fillst(stinfo_t *st) +{ +char *mname=0; +ull idx=st->ctype.idx, lidx=0; +stmember_t *stm=sial_calloc(sizeof(stmember_t)), **last=&st->stm; +char *pname; + + /* bail out if this is local type */ + if(idx & LOCALTYPESBASE) return; + + if(st->stm) sial_error("Oops sial_fillst!"); + + while((pname=API_MEMBER(mname, idx, &stm->type, &stm->m, &lidx))) { + + sial_memstinfo(stm, pname); + stm->next=0; + *last=stm; + last=&stm->next; + mname=""; + stm=sial_calloc(sizeof(stmember_t)); + if(pname[0]) sial_free(pname); + } + st->all=1; + sial_free(stm); +} + +type_t* +sial_getctype(int ctype, char *name, int silent) +{ +stinfo_t *st; +type_t *t=sial_newtype(); + + sial_chkinit(); + if(!(st=sial_getst(name, ctype))) { + + if(silent && sial_isneg(name)) return 0; + +//sial_msg("Sial_getctype '%s' type %d\n", name, ctype); + + st=sial_calloc(sizeof(stinfo_t)); + if(!API_GETCTYPE(ctype, name, &st->ctype)) { + + sial_free(st); + sial_freetype(t); + // add any tdef to the neg list + sial_addneg(ctype, name); + if(silent) return 0; + /* we fill a partial structure for this one + assuming it will be defined later. This is to permit cross + referencing of structures, self referencing of structure, and + undefined structure (opaque structures) irix: see types.c : + __pasid_opaque + */ + sial_partialctype(ctype, name); + return sial_getctype(ctype, name, silent); + } + st->name=sial_alloc(strlen(name)+1); + strcpy(st->name, name); + st->stm=0; + st->idx=st->ctype.idx; + st->all=1; + sial_addst(st); + /* + if this is a typedef then drill down to the real type + and make sure it is in the cache. That's what we return + + Bug cure: this would fail: + + struct sv { + int i; + }; + struct foo { + sv_t ms_sv; + }; + + Because the rtype index returned by API_GETRTYPE() is the die offset + in the image. If We already have redefine the real type locally the + call to sial_getctype() will not have a matching index later when we + don't find the index in the type cache. + + So we track the real index with ridx. This also ensures that + redefining a struct locally and using a typetef from the image will actualy + end up pointing to the local struct and not the image struct. + */ + if(ctype == V_TYPEDEF) { + + char *tname; + int itype; + + tname=API_GETRTYPE(st->idx, t); + + if(t->type==V_REF) itype=t->rtype; + else itype=t->type; + + /* if it's a named struct, enum or union then make sure we have it in the cache */ + if(is_ctype(itype) && tname && tname[0] && + (strcmp(tname,"struct ") != 0 + && strcmp(tname,"union ") != 0 + && strcmp(tname,"enum ") != 0)) { + + sial_freetype(t); + t=sial_getctype(itype, tname, silent); + + /* in IRIX we have a typedef struct __pasid_opaque* aspasid_t; + w/ no struct __pasid_opaque defined. The aspasid_t ends + up being used as a "named" void *. So we force a void * here */ + /* XXX: This should at least generate a warning */ + if(!t) { + sial_warning("voidstruct created (%s)\n", tname); + t=sial_getvoidstruct(itype); + } + } else if (is_ctype(itype) || itype == V_ENUM) { + + /* for unnamed structs, unions and enums create an entry */ + stinfo_t*st=sial_calloc(sizeof(stinfo_t)); + + sial_duptype(&st->ctype, t); + st->idx=t->idx; + st->name=sial_strdup(""); + sial_fillst(st); + sial_addst(st); + } + sial_duptype(&st->rtype, t); + + } else if(is_ctype(ctype)) { + + /* get all member info now ! */ + sial_fillst(st); + } + } + if(ctype == V_ENUM || (ctype == V_TYPEDEF && st->rtype.type == V_ENUM)) { + st->enums=API_GETENUM(name); + sial_pushenums(st->enums); + } + if(ctype==V_TYPEDEF) sial_duptype(t, &st->rtype); + else sial_duptype(t, &st->ctype); + + return t; +} + +type_t* +sial_newctype(int ctype, node_t*n) +{ +type_t*t; +char *name; + + t=sial_getctype(ctype, name=NODE_NAME(n), 0); + NODE_FREE(n); + sial_free(name); + return t; +} + +/* + We don't use the type to point back to get the typedef name. + The type is now the real type not the type for the typedef. + So we keep a running sting of the last name variable name + the parser found and use that. + 5/23/00 +*/ +node_t* +sial_tdeftovar(type_t*td) +{ +char *sial_lastvar(void); +char *name=sial_lastvar(); + + sial_free(td); + return sial_newvnode(name); +} + +/* + Check to see if a cached member info is available +*/ +static stmember_t* +sial_getm(char *name, type_t*tp, stinfo_t**sti) +{ +ull idx=tp->idx; +stinfo_t*st; +stmember_t*stm; + + for(st=slist.next; st; st=st->next) { + + if(st->idx == idx) { + + *sti=st; + + if(!st->stm) sial_fillst(st); + + for(stm=st->stm; stm; stm=stm->next) { + + + if(!strcmp(stm->m.name, name)) { + + return stm; + + } + } + } + } + return 0; +} + +value_t * +sial_ismember(value_t*vp, value_t*vm) +{ +char *name=sial_getptr(vm, char); +int ret=0; +stinfo_t*st; + + if(sial_getm(name, &vp->type, &st)) ret=1; + + return sial_defbtype(sial_newval(), ret); +} + +/* XXX this entire stuff could very well be machine specific ... */ +static int +sial_getalign(type_t*t) +{ + /* this is a custome type deal w/ it */ + if(t->type == V_BASE) { + + int n; + + /* Intel 386 ABI says that double values align on 4 bytes */ + if(abitype==ABI_INTEL_X86) n=((t->size>4)?4:t->size); + else n=t->size; + return n*8; + } + if(t->type == V_REF) { + /* + * This is an array but if there are additional references + * (>1) it is an array of pointers. In that case the pointer + * alignment has to be used. + */ + if(t->idxlst && t->ref == 1) { + int ret; + + sial_popref(t, 1); + ret=sial_getalign(t); + sial_pushref(t, 1); + return ret; + } + return sial_defbsize()*8; + } + /* alignment of a struct/union is on the largest of it's member or + largest allignment of sub structures */ + if(is_ctype(t->type)) { + + stinfo_t*st; + stmember_t*sm; + int maxallign=0; + + /* if this is a image type then let the api tell us */ + if(!(t->idx & LOCALTYPESBASE)) { + + return API_ALIGNMENT(t->idx)*8; + + } + + if(!(st=sial_getstbyindex(t->idx, t->type))) { + + sial_error("Oops sial_getalign"); + } + + for(sm=st->stm; sm; sm=sm->next) { + + int a=sial_getalign(&sm->type); + + if(a > maxallign) maxallign=a; + + } + + return maxallign; + + } + /* other types shoudl not be part of a ctype declaration ... */ + sial_error("Oops sial_getalign2!"); + return 0; +} + +static stinfo_t* +sial_chkctype(int ctype, char *name) +{ +stinfo_t*sti; + + if(name) { + + /* we should already have a partial structure on the stack */ + sti=sial_getst(name, ctype); + +#if 0 +At this time I choose not to give any warning. +Structure redefinition is a normal part of include files... + + /* We give a warning message for redefined types */ + { + type_t*t=sial_newtype(); + + if(API_GETCTYPE(ctype, name, t)) { + + sial_warning("%s %s redefinition", sial_ctypename(ctype), name); + } + sial_freetype(t); + } +#endif + + if(sti->all) { + + sial_error("Oops sial_ctype_decl"); + } + + sial_free(name); + + } else { + + sti=sial_alloc(sizeof(stinfo_t)); + sti->name=0; + sti->idx=sial_nextidx(); + sial_addst(sti); + } + return sti; +} + +/* + This function is used to create new enum types. + The syntax for enum is: + enum ident { + ident [= int], + [ident [= int] ] ... + }; + So we check for an assign value and is it exists then + we reset the counter to it. + This is the way the mips compiler does it. Which migt be + the right way or not, although I fail to see why it's done + that way. + + So enum foo { + a, + b, + c=0, + d + }; + + Wil yield values : + + a=0 + b=1 + c=0 + c=1 +*/ +enum_t* +sial_add_enum(enum_t*ep, char *name, int val) +{ +enum_t *epi, *nep=sial_alloc(sizeof(enum_t)); + + nep->name=name; + nep->value=val; + nep->next=0; + if(!ep) return nep; + epi=ep; + while(ep->next) ep=ep->next; + ep->next=nep; + return epi; +} + +type_t* +sial_enum_decl(int ctype, node_t*n, dvar_t*dvl) +{ +dvar_t*dv=dvl, *next; +int counter=0; +stinfo_t*sti; +enum_t *ep=0; +char *name=n?NODE_NAME(n):0; +type_t *t; + + if(n) sial_startctype(ctype, n); + sti=sial_chkctype(ctype, name); + + while(dv) { + + int val; + + /* evaluate an assignment ? */ + if(dv->init) { + + value_t *v=sial_exenode(dv->init); + + if(!v) { + + sial_rerror(&dv->pos, "Syntax error in enum expression"); + + } else if(v->type.type != V_BASE) { + + sial_rerror(&dv->pos, "Integer expression needed"); + } + + val=sial_getval(v); + counter=val+1; + sial_freeval(v); + + } else { + + val=counter++; + } + + ep=sial_add_enum(ep, dv->name, val); + + next=dv->next; + dv->next=0; + dv->name=0; + sial_freedvar(dv); + dv=next; + } + sti->enums=ep; + + /* now we push the values in the defines */ + sial_pushenums(sti->enums); + + /* we return a simple basetype_t*/ + /* after stahing the idx in rtype */ + t=sial_newbtype(INT); + t->rtype=sti->idx; + t->typattr |= sial_isenum(-1); + + return t; + +} + +/* + The next functions are used to produce a new type + and make it available throught the local cache. + This enables custom type definitions on top of the + ctypes defined in the object symbol tables. + + There is one function per suported architechture. + +*/ +/* macro for alignment to a log2 boundary */ +#define Alignto(v, a) (((v) + (a) -1) & ~((a)-1)) +/* + The algorith complies with the SysV mips ABI +*/ +type_t* +sial_ctype_decl(int ctype, node_t*n, var_t*list) +{ +type_t*t; +stinfo_t*sti; +stmember_t **mpp; +var_t*v; +int bits_left, bit_alignment; +int maxbytes, alignment, nextbit; +char *name=n?NODE_NAME(n):0; + + if(list->next==list) { + + sial_error("Empty struct/union/enum declaration"); + } + + t=sial_newbtype(0); + sti=sial_chkctype(ctype, name); + t->type=sti->ctype.type=ctype; + t->idx=sti->ctype.idx=sti->idx; + sti->stm=0; + mpp=&sti->stm; + +#if LDEBUG +printf("\n%s %s\n", ctype==V_STRUCT?"Structure":"Union", name ? name : ""); +#endif + + /* these are the running position in the structure/union */ + nextbit=0; /* next bit open for business */ + alignment=0; /* keeps track of the structure alignment + Mips ABI says align to bigest alignment of + all members of the struct/union. Also + unamed bit fields do not participate here. */ + maxbytes=0; /* tracking of the maximum member size for union */ + + for(v=list->next; v!=list; v=v->next) { + + stmember_t*stm=sial_calloc(sizeof(stmember_t)); + dvar_t*dv=v->dv; + int nbits; + + stm->m.name=sial_strdup(v->name); + sial_duptype(&stm->type, &v->v->type); + + /* if this member is a bit filed simply use that */ + if(dv->bitfield) { + + nbits=dv->nbits; + + /* aligment is the size of the declared base type size */ + bit_alignment=v->v->type.size*8; + + if(nbits > bit_alignment) { + + sial_error("Too many bits for specified type"); + } + + /* For unamed bit field align to smallest entity */ + /* except for 0 bit bit fields */ + if(!dv->name[0] && nbits) { + + bit_alignment=((nbits+7)/8)*8; + + } + + /* We compute the number of bits left in this entity */ + bits_left = bit_alignment - (nextbit%bit_alignment); + + /* 0 bits means, jump to next alignement unit anyway + if not already on such a boundary */ + if(!nbits && (bits_left != bit_alignment)) nbits=bits_left; + + /* Not enough space ? */ + if(nbits > bits_left) { + + /* jump to next start of entity */ + nextbit += bits_left; + + } + + /* update member information */ + stm->m.offset=(nextbit/bit_alignment)*v->v->type.size; + stm->m.fbit=nextbit % bit_alignment; + stm->m.nbits=nbits; + stm->m.size=v->v->type.size; +#if LDEBUG + printf(" [%s] Bit member offset=%d, fbit=%d, nbits=%d\n", stm->m.name, stm->m.offset, stm->m.fbit, stm->m.nbits); +#endif + /* an unamed bit field does not participate in the alignment value */ + if(!dv->name[0]) { + + bit_alignment=0; + + /* reset size so that it does not have affect in sial_getalign() */ + stm->type.size=1; + } + + } else { + + int nidx=1; + + if(dv->idx) { + + int i; + + /* flag it */ + stm->type.idxlst=sial_calloc(sizeof(int)*(dv->idx->nidx+1)); + + /* multiply all the [n][m][o]'s */ + for(i=0;iidx->nidx;i++) { + + value_t *vidx; + ull idxv; + + vidx=sial_exenode(dv->idx->idxs[i]); + if(!vidx) { + + sial_error("Error while evaluating array size"); + } + if(vidx->type.type != V_BASE) { + + sial_freeval(vidx); + sial_error("Invalid index type"); + + } + + idxv=sial_getval(vidx); + sial_freeval(vidx); + + stm->type.idxlst[i]=idxv; + + nidx *= idxv; + } + + + } + + /* the number of bits on which this item aligns itself */ + bit_alignment=sial_getalign(&stm->type); + + /* jump to this boundary */ + nextbit = Alignto(nextbit,bit_alignment); + + + if(stm->type.ref - (dv->idx?1:0)) { + + nbits=nidx*sial_defbsize()*8; + + } else { + + nbits=nidx*stm->type.size*8; + } + + if(abitype==ABI_INTEL_X86) { + + int pos=nextbit/8; + + pos = (pos & 0xfffffffc) + 3 - (pos & 0x2); + stm->m.offset=pos; + + } else { + + stm->m.offset=nextbit/8; + } + stm->m.nbits=0; + stm->m.size=nbits/8; +#if LDEBUG +printf(" [%s] Mmember offset=%d, size=%d size1=%d nidx=%d\n", stm->m.name, stm->m.offset, stm->m.size, stm->type.size, nidx); +#endif + + } + + if(ctype==V_STRUCT) nextbit+=nbits; + /* Union members overlap */ + else nextbit=0; + + /* keep track of the maximum alignment */ + if(bit_alignment>alignment) alignment=bit_alignment; + + /* keep track of maximum size for unions */ + if(stm->m.size > maxbytes) maxbytes=stm->m.size; + + stm->next=0; + *mpp=stm; + mpp=&stm->next; + } + + /* pad the final structure according to it's most stricly aligned member */ + if(nextbit) nextbit = Alignto(nextbit, alignment); + else nextbit=Alignto(maxbytes*8, alignment); /* --> it's the case for a union */ + + t->size=sti->ctype.size=nextbit/8; + +#if LDEBUG +printf("Final size = %d\n", t->size); +#endif + + sti->all=1; + sial_addfunc_ctype(sti->idx); + return t; +} + +/* + member access and caching. + If the member name is empty then the caller wants us + to populate the entire engregate. The apimember() should + support a getfirst() (member name == "") and getnext() + (member name != "") for this perpose. + */ +stmember_t* +sial_member(char *mname, type_t*tp) +{ +stinfo_t *sti; +stmember_t *stm; + + if(!is_ctype(tp->type) && ! (tp->type==V_REF && is_ctype(tp->rtype))) { + + sial_error("Expression for member '%s' is not a struct/union", mname); + + + } + + if(tp->idx == VOIDIDX) { + + sial_error("Reference to member (%s) from unknown structure type", mname); + } + + if(!(stm=sial_getm(mname, tp, &sti))) { + + sial_error("Unknown member name [%s]", mname); + } + return stm; +} + +int +sial_open() +{ + sial_setofile(stdout); + /* push an empty level for parsing allocation */ + sial_pushjmp(0, 0, 0); + sial_setapiglobs(); + init=1; + sial_setbuiltins(); + return 1; +} + +/* here is a set of api function that do nothing */ +static int apigetmem(ull iaddr, void *p, int nbytes) { return 1; } +static int apiputmem(ull iaddr, void *p, int nbytes) { return 1; } +static char* apimember(char *mname, ull pidx, type_t*tm, member_t *m, ull *lidx) { return 0; } +static int apigetctype(int ctype, char *name, type_t*tout) { return 0; } +static char * apigetrtype(ull idx, type_t*t) { return ""; } +static int apialignment(ull idx) { return 0; } +static int apigetval(char *name, ull *val) { return 0; } +static enum_t* apigetenum(char *name) { return 0; } +static def_t *apigetdefs(void) { return 0; } +static char* apifindsym(char *p) { return 0; } + +static apiops nullops= { + apigetmem, apiputmem, apimember, apigetctype, apigetrtype, apialignment, + apigetval, apigetenum, apigetdefs, 0, 0, 0, 0, apifindsym +}; + +apiops *sial_ops=&nullops;; + +void +sial_apiset(apiops *o, int abi, int nbpw, int sign) +{ +def_t *dt; + + sial_ops=o?o:&nullops; + sial_setdefbtype(nbpw, sign); + /* get the pre defines and push them. */ + dt=API_GETDEFS(); + while(dt) { + + sial_newmac(dt->name, dt->val, 0, 0, 1); + dt=dt->next; + } + /* add the sial define */ + sial_newmac(sial_strdup("sial"), sial_strdup("1"), 0, 0, 1); +} + +/* + Get and set path function. + ipath is include file search path. + mpath is macro search path +*/ +static char *mpath=""; +static char *ipath=""; +void sial_setmpath(char *p) { mpath=p; } +void sial_setipath(char *p) { ipath=p; } +char *sial_getmpath(void) { return mpath; } +char *sial_getipath(void) { return ipath; } + +static char *curp=0; +char *sial_curp(char *p) { char *op=curp; p?(curp=p):(op=curp); return op; } + +static char* +sial_cattry(char *first, char *second) +{ +struct stat stats; +char *buf=sial_alloc(strlen(first)+strlen(second)+2); + + strcpy(buf, first); + strcat(buf, "/"); + strcat(buf, second); + if(!stat(buf, &stats)) return buf; + sial_free(buf); + return 0; +} + +char * +sial_filepath(char *fname, char *path) +{ + struct stat buf; + /* valid file path, return immediatly */ + if(stat(fname,&buf) == 0) { + /* must return a free'able name */ + char *name=sial_strdup(fname); + TAG(name); + return name; + + } else if(fname[0]=='~') { + + if(strlen(fname)>1) { + + char *rname, *start; + struct passwd *pwd; + + if(fname[1]=='/') { + + /* current user name */ + pwd=getpwuid(getuid()); + + if(!pwd) { + sial_msg("Who are you : uid=%d \n?", getuid()); + return 0; + } + + start=fname+1; + + } else { + + char *p, s; + + for(p=fname+1;*p;p++) if(*p=='/') break; + s=*p; + *p='\0'; + + /* other user */ + pwd=getpwnam(fname+1); + if(!pwd) { + + sial_msg("Who is this : %s ?\n", fname+1); + return 0; + } + if(s) *p=s; + start=p; + } + rname=sial_alloc(strlen(start+1)+strlen(pwd->pw_dir)+2); + strcpy(rname, pwd->pw_dir); + strcat(rname, start); + return rname; + } + + } else { + + char *p=sial_strdup(path); + char *tok, *curp; + + /* we check if the file is found relatively to the current + position. I.e. the position of the running script */ + if((curp=sial_curp(0)) && (curp=sial_cattry(curp, fname))) { + + sial_free(p); + return curp; + } + + tok=strtok(p, ":"); + while(tok) { + + if((curp=sial_cattry(tok, fname))) { + + sial_free(p); + return curp; + } + tok=strtok(NULL, ":"); + + } + sial_free(p); + } + return 0; +} + +char* +sial_filempath(char *fname) +{ + return sial_filepath(fname, mpath); +} + +char * +sial_fileipath(char *fname) +{ + return sial_filepath(fname, ipath); +} + +/* load a file or a set of file */ +int +sial_loadunload(int load, char *name, int silent) +{ +DIR *dirp; +int ret=1; +char *fname=sial_filempath(name); + + if(!fname) { + + if(!silent) sial_msg("File not found : %s\n", name); + return 0; + } + + if((dirp=opendir(fname))) { + + struct dirent *dp; + char *buf; + + while ((dp = readdir(dirp)) != NULL) { + + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + continue; + + buf=sial_alloc(strlen(fname)+dp->d_reclen+2); + sprintf(buf, "%s/%s", fname, dp->d_name); + if(load) { + ret &= sial_newfile(buf, silent); + }else{ + sial_deletefile(buf); + } + sial_free(buf); + } + closedir(dirp); + } + else { + + if(load) { + ret=sial_newfile(fname, silent); + }else{ + sial_deletefile(fname); + } + } + sial_free(fname); + return ret; +} + +/* + Load conditionaly. + If it's already load, return. +*/ +ull +sial_depend(char *name) +{ +char *fname=sial_filempath(name); +int ret=1 ; +void *fp; + + if(!fname) ret=0; + else if(!(fp=sial_findfile(fname,0)) || sial_isnew(fp)) { + + ret=sial_loadunload(1, name, 1); + sial_free(fname); + } + return ret; +} + +value_t * +sial_bdepend(value_t *vname) +{ + return sial_makebtype(sial_depend(sial_getptr(vname, char))); +} + +ull +sial_load(char *fname) +{ + return sial_loadunload(1, fname, 0); +} + +value_t* +sial_bload(value_t *vfname) +{ +char *fname=sial_getptr(vfname, char); +value_t *v; + + v=sial_makebtype(sial_load(fname)); + return v; +} + +ull +sial_unload(char *fname) +{ + return sial_loadunload(0, fname, 0); +} + +value_t* +sial_bunload(value_t *vfname) +{ +char *fname=sial_getptr(vfname, char); + + return sial_defbtype(sial_newval(), sial_unload(fname)); +} + +void +sial_loadall() +{ +char *path=sial_strdup(sial_getmpath()); +char *p, *pn; + + p=pn=path; + while(*pn) { + + if(*pn == ':') { + + *pn++='\0'; + sial_loadunload(1, p, 1); + p=pn; + + } else pn++; + } + if(p!=pn) sial_loadunload(1, p, 1); + /* sial_free(path); */ +} + +static void +add_flag(var_t*flags, int c) +{ +char s[20]; +var_t *v; + + sprintf(s, "%cflag", c); + v=sial_newvar(s); + sial_defbtype(v->v, (ull)0); + v->ini=1; + sial_enqueue(flags, v); +} + +int +sial_cmd(char *fname, char **argv, int argc) +{ +value_t *idx, *val; + + sial_chkinit(); + + if(sial_chkfname(fname, 0)) { + + var_t*flags, *args, *narg; + char *opts, *newn=sial_alloc(strlen(fname)+sizeof("_usage")+1); + int c, i; + extern char *optarg; + extern int optind; + int dou; + char *f=sial_strdup("Xflag"); + + flags=(var_t*)sial_newvlist(); + + /* build a complete list of option variables */ + for(c='a';c<='z';c++) add_flag(flags, c); + for(c='A';c<='Z';c++) add_flag(flags, c); + + /* check if there is a getopt string associated with this command */ + /* there needs to be a fname_opt() and a fname_usage() function */ + sprintf(newn, "%s_opt", fname); + + if(sial_chkfname(newn, 0)) opts=(char*)(unsigned long)sial_exefunc(newn, 0); + else opts=""; + + sprintf(newn, "%s_usage", fname); + dou=sial_chkfname(newn, 0); + + /* build a set of variable from the given list of arguments */ + /* each options generate a conrresponding flag ex: -X sets Xflag to one + end the corresponding argument of a ":" option is in ex. Xarg + each additional arguments is keaped in the array args[] */ + + if(opts[0]) { + +#ifdef linux + optind=0; +#else + getoptreset(); +#endif + while ((c = getopt(argc, argv, opts)) != -1) { + + var_t*flag, *opt; + char *a=sial_strdup("Xarg");; + + if(c==':') { + + sial_warning("Missing argument(s)"); + if(dou) sial_exefunc(newn, 0); + sial_free(a); + goto out; + + } else if(c=='?') { + + if(dou) { + + char *u=(char*)(unsigned long)sial_exefunc(newn, 0); + + if(u) sial_msg("usage: %s %s\n", fname, u); + } + sial_free(a); + goto out; + } + + + /* set the Xflag variable to 1 */ + f[0]=c; + flag=sial_inlist(f, flags); + sial_defbtype(flag->v, (ull)1); + flag->ini=1; + + /* create the Xarg variable */ + if(optarg && optarg[0]) { + + char *p=sial_alloc(strlen(optarg)+1); + + a[0]=c; + strcpy(p, optarg); + opt=(var_t*)sial_newvar(a); + sial_setstrval(opt->v, p); + opt->ini=1; + sial_enqueue(flags, opt); + } + sial_free(a); + } + sial_free(f); + } + else optind=1; + + /* put every other args into the argv[] array_t*/ + args=(var_t*)sial_newvar("argv"); + args->ini=1; + + /* create a argv[0] with the name of the command */ + { + + val=sial_makestr(fname); + idx=sial_makebtype(0); + + /* create the value's value */ + sial_addarrelem(&args->v->arr, idx, val); + sial_freeval(idx); + } + + for ( i=1; optind < argc; optind++, i++) { + + val=sial_makestr(argv[optind]); + idx=sial_makebtype(i); + + /* create the value's value */ + sial_addarrelem(&args->v->arr, idx, val); + sial_freeval(idx); + } + + narg=(var_t*)sial_newvar("argc"); + sial_defbtype(narg->v, i); + narg->ini=1; + + sial_enqueue(flags, narg); + + /* add the args variable to the flags queue */ + sial_enqueue(flags, args); + + /* now execute */ + sial_runcmd(fname, flags); + +out: + /* free all arguments variables Xflag Xarg and argv[] */ + sial_freesvs(flags); + + sial_free(newn); + return 0; + } + return 1; +} + --- crash-4.0-4.6/extensions/libsial/sial_api.h 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_api.h 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,251 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ + +/* minor and major version number */ +#define S_MAJOR 3 +#define S_MINOR 0 + +#define MAX_SYMNAMELEN 100 +#define MAXIDX 20 + +/* abi values */ +#define ABI_MIPS 1 +#define ABI_INTEL_X86 2 +#define ABI_INTEL_IA 3 + +/* types of variables */ +#define V_BASE 1 +#define V_STRING 2 +#define V_REF 3 +#define V_ENUM 4 +#define V_UNION 5 +#define V_STRUCT 6 +#define V_TYPEDEF 7 +#define V_ARRAY 8 + +#define ENUM_S struct enum_s +#define DEF_S struct def_s +#define MEMBER_S struct member_s +#define TYPE_S struct type_s +#define VALUE_S struct value_s +#define ARRAY_S struct array_s +#define NODE_S struct node_s +#define IDX_S struct idx_s +#define VAR_S struct var_s + +ENUM_S; +DEF_S; +MEMBER_S; +TYPE_S; +VALUE_S; +ARRAY_S; +NODE_S; +IDX_S; +VAR_S; + +#if linux +#include +typedef uint64_t ull; +typedef uint32_t ul; +#else +typedef unsigned long long ull; +typedef unsigned long ul; +#endif + +/* THe API function calls numbers */ +typedef struct { + + int (*getmem)(ull, void *, int); /* write to system image */ + int (*putmem)(ull, void *, int); /* read from system image */ + char* (*member)(char *, ull, TYPE_S * /* get type and positional information ... */ + , MEMBER_S *, ull *lidx); /* ... about the member of a structure */ + int (*getctype)(int ctype, char * /* get struct/union type information */ + , TYPE_S*); + char* (*getrtype)(ull, TYPE_S *); /* get complex type information */ + int (*alignment)(ull); /* get alignment value for a type */ + int (*getval)(char *, ull *); /* get the value of a system variable */ + ENUM_S* (*getenum)(char *name); /* get the list of symbols for an enum type */ + DEF_S* (*getdefs)(void); /* get the list of compiler pre-defined macros */ + uint8_t (*get_uint8)(void*); + uint16_t (*get_uint16)(void*); + uint32_t (*get_uint32)(void*); + uint64_t (*get_uint64)(void*); + char* (*findsym)(char*); +} apiops; + +/* + Builtin API defines.... +*/ +/* call this function to install a new builtin + + proto is the function prototype ex: + struct proc* mybuiltin(int flag, char *str); + + "mybuiltin" will be the sial name for the function. + "fp" is the pointer to the builtin function code. + +*/ +typedef VALUE_S* bf_t(VALUE_S*, ...); +typedef struct btspec { + char *proto; + bf_t *fp; +} btspec_t; + +/* dso entry points */ +#define BT_SPEC_TABLE btspec_t bttlb[] +#define BT_SPEC_SYM "bttlb" +#define BT_INIDSO_FUNC int btinit +#define BT_INIDSO_SYM "btinit" +#define BT_ENDDSO_FUNC void btend +#define BT_ENDDSO_SYM "btend" + +/* maximum number of parameters that can be passed to a builtin */ +#define BT_MAXARGS 20 + +extern apiops *sial_ops; +#define API_GETMEM(i, p, n) ((sial_ops->getmem)((i), (p), (n))) +#define API_PUTMEM(i, p, n) ((sial_ops->putmem)((i), (p), (n))) +#define API_MEMBER(n, i, tm, m, l) ((sial_ops->member)((n), (i), (tm), (m), (l))) +#define API_GETCTYPE(i, n, t) ((sial_ops->getctype)((i), (n), (t))) +#define API_GETRTYPE(i, t) ((sial_ops->getrtype)((i), (t))) +#define API_ALIGNMENT(i) ((sial_ops->alignment)((i))) +#define API_GETVAL(n, v) ((sial_ops->getval)((n), (v))) +#define API_GETENUM(n) ((sial_ops->getenum)(n)) +#define API_GETDEFS() ((sial_ops->getdefs)()) +#define API_GET_UINT8(ptr) ((sial_ops->get_uint8)(ptr)) +#define API_GET_UINT16(ptr) ((sial_ops->get_uint16)(ptr)) +#define API_GET_UINT32(ptr) ((sial_ops->get_uint32)(ptr)) +#define API_GET_UINT64(ptr) ((sial_ops->get_uint64)(ptr)) +#define API_FINDSYM(p) ((sial_ops->findsym)(p)) + +#if linux +# if __LP64__ +# define sial_getptr(v, t) ((t*)sial_getval(v)) +# else +# define sial_getptr(v, t) ((t*)(ul)sial_getval(v)) +# endif +#else +# if (_MIPS_SZLONG == 64) +# define sial_getptr(v, t) ((t*)sial_getval(v)) +# else +# define sial_getptr(v, t) ((t*)(ul)sial_getval(v)) +# endif +#endif + +/* startup function */ +int sial_open(void); /* initialize a session with sial */ +void sial_apiset(apiops *, int, int, int);/* define the API for a connection */ +void sial_setofile(void *); /* sial should output messages to this file */ +void *sial_getofile(void); /* where is sial currently outputing */ +void sial_setmpath(char *p); /* set the search path for sial scripts */ +void sial_setipath(char *p); /* set the search path for sial include files */ +VAR_S *sial_builtin(char *proto, bf_t);/* install a builtin function */ +int sial_cmd(char *name, char **argv, int argc); /* execute a command w/ args */ + +/* load/unload of script files and directories */ +ull sial_load(char *); /* load/parse a file */ +ull sial_unload(char *); /* load/parse a file */ +void sial_loadall(void); /* load all files found in set path */ + +/* variables associated functions */ +VAR_S *sial_newvar(char *); /* create a new static/auto variable */ +void *sial_add_globals(VAR_S*); /* add a set of variable to the globals context */ +VAR_S *sial_newvlist(void); /* create a root for a list of variables */ + +int sial_tryexe(char *, char**, int);/* try to execute a function */ +int sial_parsetype(char*, TYPE_S *, int);/* parse a typedef line */ +ull sial_exefunc(char *, VALUE_S **);/* to execute a function defined in sial */ + +/* help related function */ +void sial_showallhelp(void); /* display help info for all commands */ +int sial_showhelp(char *); /* display help info for a single command */ + +/* allocation related function */ +void *sial_alloc(int); /* allocate some memory */ +void *sial_calloc(int); /* allocate some 0 filed memory */ +void sial_free(void*); /* free it */ +char *sial_strdup(char*); /* equivalent of strdup() returns sial_free'able char */ +void *sial_dupblock(void *p); /* duplicate the contain of a block of allocated memory */ +void *sial_realloc(void *p, int size); /* reallocate a block */ +void sial_maketemp(void *p); /* put a block on the temp list */ +void sial_freetemp(void); /* free the temp list */ +VALUE_S *sial_makebtype(ull); /* create a default base type value (int) */ + +/* handle values */ +VALUE_S *sial_newval(void); /* get a new placeholder for a value */ +void sial_freeval(VALUE_S *); /* free a value* and associated structs */ +VALUE_S *sial_makestr(char *); /* create a string value */ +ull sial_getval(VALUE_S*); /* transform a random value to a ull */ +VALUE_S *sial_cloneval(VALUE_S *); /* make a clone of a value */ + +/* array related */ +/* add a new array element to a value */ +void sial_addvalarray(VALUE_S*v, VALUE_S*idx, VALUE_S*val); +/* return the value associated with a int index */ +VALUE_S *sial_intindex(VALUE_S *, int); +/* return the value associated with a 'string' index */ +VALUE_S *sial_strindex(VALUE_S *, char *); +/* set the value of an array element */ +void sial_setarrbval(ARRAY_S*, int); +/* get the array element coresponding to index */ +ARRAY_S *sial_getarrval(ARRAY_S**, VALUE_S*); +/* get the initiale array for a variable */ +ARRAY_S *sial_addarrelem(ARRAY_S**, VALUE_S*, VALUE_S*); + +/* type manipulation */ +int sial_is_struct(int); +int sial_is_enum(int); +int sial_is_union(int); +int sial_is_typedef(int); +int sial_type_gettype(TYPE_S*t); +int sial_chkfname(char *fname, void *vfd); +int sial_loadunload(int load, char *name, int silent); + +void sial_type_settype(TYPE_S*t, int type); +void sial_setcallback(void (*scb)(char *, int)); +void sial_vilast(void); +void sial_vi(char *fname, int file); +void sial_type_setsize(TYPE_S*t, int size); +int sial_type_getsize(TYPE_S*t); +void sial_type_setidx(TYPE_S*t, ull idx); +ull sial_type_getidx(TYPE_S*t); +void sial_type_setidxlst(TYPE_S*t, int *idxlst); +void sial_type_setref(TYPE_S*t, int ref, int type); +void sial_type_setfct(TYPE_S*t, int val); +void sial_type_mkunion(TYPE_S*t); +void sial_type_mkenum(TYPE_S*t); +void sial_type_mkstruct(TYPE_S*t); +void sial_type_mktypedef(TYPE_S*t); +TYPE_S*sial_newtype(void); +void sial_freetype(TYPE_S*t); +TYPE_S*sial_getctype(int ctype_t, char *name, int silent); +void sial_type_free(TYPE_S* t); +void sial_pushref(TYPE_S*t, int ref); +void sial_duptype(TYPE_S*to, TYPE_S*from); +int sial_defbsize(void); +TYPE_S*sial_newbtype(int token); + +/* struct member functions */ +void sial_member_soffset(MEMBER_S*m, int offset); +void sial_member_ssize(MEMBER_S*m, int size); +void sial_member_sfbit(MEMBER_S*m, int fbit); +void sial_member_snbits(MEMBER_S*m, int nbits); +void sial_member_sname(MEMBER_S*m, char *name); + +/* enums */ +ENUM_S* sial_add_enum(ENUM_S* e, char* name, int val); +/* defines */ +DEF_S* sial_add_def(DEF_S* d, char *name, char *val); + +/* error handling */ +/* display error w/ file/line coordinates */ +/* does not return */ +void sial_error(char *, ...); +/* display warning w/ file/line coordinates */ +void sial_warning(char *, ...); +/* display a message and continue */ +void sial_msg(char *, ...); + +/* parsers debug flags */ +extern int sialdebug, sialppdebug; --- crash-4.0-4.6/extensions/libsial/sial_builtin.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_builtin.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,434 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include +#include +#include +#include +#include +#include "sial.h" + +/* information necessary for a builtin function */ +typedef struct builtin { + + var_t*v; /* resulting variable declaration after parsing */ + bf_t *fp; /* pointer to actual function */ + char *proto; /* associated prototype_t*/ + struct builtin *next; /* to chain them */ + +} builtin; + +#define BT_EINVAL 1 /* Something is wrong and it's not ... */ +value_t* +sial_exit(int v) +{ + /* Were we compiling ? */ + sial_parseback(); + + /* we were running... exit () */ + sial_dojmp(J_EXIT, &v); + + /* NOT REACHED */ + return 0; +} + +value_t* +sial_bexit(value_t *vv) +{ +int v=sial_getval(vv); + + /* we're not going back to the he caller so free + the input value_t */ + sial_freeval(vv); + sial_exit(v); + /* NOT REACHED */ + return 0; +} + +#define MAXBYTES 4000 +#define INCREMENT 16 +value_t * +sial_getstr(value_t *vmadr) +{ +ull madr=sial_getval(vmadr); +char *buf=sial_alloc(MAXBYTES+1); +char *p=buf; +value_t *v; + + /* sial as already verified that this is a V_REF */ + /* since this is reading from a unkown size pool + we have to do an exponential reduction on the number of bytes + read ... */ + buf[0]=0; + while(1) { + + int i; + + if(!API_GETMEM(madr, p, INCREMENT)) break; + + /* have we found the '\0' yet ? */ + for(i=0;i= MAXBYTES) { + buf[MAXBYTES]='\0'; + break; + } + + } + v=sial_setstrval(sial_newval(), buf); + sial_free(buf); + return v; +} + +value_t * +sial_substr(value_t *vp, value_t *vi, value_t *vj) +{ +char *p=sial_getptr(vp, char); +ul i=sial_getval(vi); +int l=strlen(p); +int j=(vj?sial_getval(vj):(l-i+1)); +char *s; +value_t *v; + + if((i+j-1)>l || !i) { + + sial_error("Valid positions are [1..%d]\n", l); + + } + + s=sial_alloc(j+1); + strncpy(s, p+i-1, j); + s[j]='\0'; + v=sial_setstrval(sial_newval(), s); + sial_free(s); + return v; +} + +value_t * +sial_getnstr(value_t* vmadr, value_t* vl) +{ +ull madr=sial_getval(vmadr); +ul l=sial_getval(vl); +char *buf=sial_alloc(l+1); +value_t *v; + + if(!API_GETMEM(madr, buf, l)) buf[0]='\0'; + else buf[l]='\0'; + v=sial_setstrval(sial_newval(), buf); + sial_free(buf); + return v; +} + +value_t * +sial_atoi(value_t *vs, value_t* vbase) +{ +char *s=sial_getptr(vs, char); +int base=vbase ? sial_getval(vbase) : 0; + + strtoull(s, 0, (int) base); + return sial_defbtypesize(sial_newval(), strtoull(s, 0, base), B_ULL); +} + +value_t * +sial_itoa(value_t* vi) +{ +ull i=sial_getval(vi); +char p[40]; + + sprintf(p, "%llu", (unsigned long long)i); + return sial_setstrval(sial_newval(), p); +} + +value_t * +sial_strlen(value_t *vs) +{ +char *s=sial_getptr(vs, char); +ull l; + if(!s) l=0; + else l=strlen(s); + + return sial_defbtype(sial_newval(), l); +} + +value_t * +sial_getchar(void) +{ +char c; +struct termio tio, stio; +int in=fileno(stdin); + + if(ioctl(in, TCGETA, &tio)) c=255; + else { + stio=tio; + tio.c_lflag &= ~(ICANON | ECHO); + tio.c_iflag &= ~(ICRNL | INLCR); + tio.c_cc[VMIN] = 1; + tio.c_cc[VTIME] = 0; + ioctl(in, TCSETA, &tio); + c=getc(stdin); + ioctl(in, TCSETA, &stio); + } + return sial_defbtype(sial_newval(), (ull)c); +} + +value_t * +sial_gets(void) +{ +char p[1024]; + + if(!fgets(p, sizeof(p)-1, stdin)) p[0]='\0'; + else p[strlen(p)-1]='\0'; + return sial_setstrval(sial_newval(), p); +} + +static builtin *bfuncs=0; + +/* + Check for the existance of a bt function +*/ +void * +sial_chkbuiltin(char *name) +{ +builtin *bf; + + for(bf=bfuncs; bf; bf=bf->next) { + + if(!strcmp(name, bf->v->name)) { + + return bf; + } + } + return 0; +} + +/* + Remove a builtin. + This is done when we 'unload' a *.so file. +*/ +void +sial_rmbuiltin(var_t*v) +{ +builtin *bf; +builtin *last=0; + + for(bf=bfuncs; bf; bf=bf->next) { + + if(!strcmp(v->name, bf->v->name)) { + + if(!last) bfuncs=bf->next; + else { + + last->next=bf->next; + } + sial_free(bf->proto); + sial_free(bf); + } + last=bf; + } +} + +/* + Install a new builtin function. +*/ +var_t* +sial_builtin(char *proto, bf_t* fp) +{ +var_t*v; + + /* parse the prototype_t*/ + if((v=sial_parsexpr(proto))) { + + builtin *bt; + int nargs=0; + + /* check name */ + if(!v->name || !v->name[0]) { + + sial_freevar(v); + sial_msg("Syntax error: no function name specified [%s]\n", proto); + return 0; + } + + /* check for function with same name */ + if(sial_chkfname(v->name, 0)) { + + sial_freevar(v); + sial_msg("Function already defined [%s]\n", proto); + return 0; + } + + if(v->dv->fargs) { + + var_t*vn=v->dv->fargs->next; + + while(vn!=v->dv->fargs) { + + nargs++; + vn=vn->next; + } + } + /* check number of args */ + if(nargs > BT_MAXARGS) { + + sial_freevar(v); + sial_msg("Too many parameters to function (max=%d) [%s]\n", BT_MAXARGS, proto); + return 0; + } + + + bt=sial_alloc(sizeof(builtin)); + bt->proto=sial_strdup(proto); + bt->fp=fp; + bt->v=v; + bt->next=0; + + /* install it */ + if(!bfuncs) bfuncs=bt; + else { + builtin *btp; + + for(btp=bfuncs; ; btp=btp->next) if(!btp->next) break; + btp->next=bt; + } + return v; + } + + sial_msg("Builtin [%s] not loaded.", proto); + + return 0; +} + +#define bcast(f) ((bf_t*)f) + +static btspec_t sialbfuncs[] = { + { "unsigned long long atoi(string, ...)",bcast(sial_atoi)}, + { "int exists(string)", bcast(sial_exists)}, + { "void exit(int)", bcast(sial_bexit)}, + { "int getchar()", bcast(sial_getchar)}, + { "string gets()", bcast(sial_gets)}, + { "string getstr(char *)", bcast(sial_getstr)}, + { "string getnstr(char *, int)", bcast(sial_getnstr)}, + { "string itoa(int)", bcast(sial_itoa)}, + { "void printf(string, ...)", bcast(sial_printf)}, + { "void showtemp()", bcast(sial_showtemp)}, + { "void showaddr(char *)", bcast(sial_showaddr)}, + { "void memdebugon()", bcast(sial_memdebugon)}, + { "void memdebugoff()", bcast(sial_memdebugoff)}, + { "int sial_load(string)", bcast(sial_bload)}, + { "int sial_unload(string)", bcast(sial_bunload)}, + { "int depend(string)", bcast(sial_bdepend)}, + { "int strlen(string)", bcast(sial_strlen)}, + { "string sprintf(string, ...)", bcast(sial_sprintf)}, + { "string substr(string, int, ...)", bcast(sial_substr)}, + { "void prarr(string name, int i)", bcast(sial_prarr)}, + { "int member(void*, string name)", bcast(sial_ismember)}, + { "string findsym(string)", bcast(sial_findsym)}, +}; + + +/* + Install the sial builtins. +*/ +void +sial_setbuiltins() +{ +int i; + + for(i=0;iv->dv->fargs) { + + var_t*vv=bf->v->dv->fargs->next; + + while(vv != bf->v->dv->fargs) { + + if(vv->name && !strcmp(vv->name, S_VARARG)) { + while(nargsv); + sial_chkandconvert(lvals[nargs], vals[nargs]); + } + nargs++; + vv=vv->next; + } + } + + /* check parameters number */ + if(iv->dv->pos, "Too few parameters to '%s'", bf->proto); + + } else if(i>nargs){ + + sial_rerror(&bf->v->dv->pos, "Too many parameters to '%s'", bf->proto); + + } + + if(vals) { + /* the actual call */ + v=(bf->fp) ( + lvals[0], lvals[1], + lvals[2], lvals[3], + lvals[4], lvals[5], + lvals[6], lvals[7], + lvals[8], lvals[9], + lvals[10], lvals[11], + lvals[12], lvals[13], + lvals[14], lvals[15], + lvals[16], lvals[17], + lvals[18], lvals[19] + ); + } else { + + v=(bf->fp) ((value_t*)0); + } + + while(i) { + + --i; + sial_freeval(vals[i]); + sial_freeval(lvals[i]); + } + + /* make a copy of the return value_t info */ + vr=sial_cloneval(bf->v->v); + sial_chkandconvert(vr, v); + sial_freeval(v); + + return vr; + } + + sial_error("Oops. sial_exebfunc()"); + return 0; +} --- crash-4.0-4.6/extensions/libsial/sial_case.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_case.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,125 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +/* + Set of functions to handle the case construct. +*/ +#include "sial.h" + +void +sial_freecaseval(caseval_t*cv) +{ + sial_free(cv); +} + +node_t* +sial_caseval(int isdef, node_t*val) +{ +caseval_t*cv=sial_alloc(sizeof(caseval_t)); +node_t*n=sial_newnode(); +value_t *v; + + cv->isdef=isdef; + if(val) { + + v=NODE_EXE(val); + cv->val=unival(v); + sial_freeval(v); + NODE_FREE(val); + + } else cv->val=0; + + sial_setpos(&cv->pos); + + cv->next=0; + n->data=cv; + return n; +} + +node_t* +sial_addcaseval(node_t*n, node_t*n2) +{ +caseval_t*cv=(caseval_t*)n->data; +caseval_t*ncv=(caseval_t*)n2->data; + + sial_free(n); + ncv->next=cv; + return n2; +} + +void +sial_freecase(void *vcl) +{ +caselist_t*cl=(caselist_t*)vcl; + + NODE_FREE(cl->stmt); + sial_free(cl); +} + +node_t* +sial_newcase(node_t*nc, node_t* n) +{ +caseval_t*cv=(caseval_t*)nc->data; +caselist_t*cl=sial_alloc(sizeof(caselist_t)); +node_t*nn=sial_newnode(); + + + nn->data=cl; + nn->free=(ffct_t)sial_freecase; + + cl->vals=cv; + sial_free(nc); + + cl->stmt=n; + cl->next=0; + + sial_setpos(&cl->pos); + + return nn; +} + +node_t* +sial_addcase(node_t*n, node_t*n2) +{ +caselist_t*lcl; +caselist_t*ncl=(caselist_t*)n2->data; +caselist_t*cl=(caselist_t*)n->data; + + for(lcl=cl; lcl->next; lcl=lcl->next); + + /* we need to add case in the order they are listed */ + lcl->next=ncl; + sial_free(n2); + ncl->next=0; + + sial_setpos(&ncl->pos); + + return n; +} + +int +sial_docase(ull val, caselist_t*cl) +{ +caselist_t*defclp=0, *clp; + + + for(clp=cl;clp;clp=clp->next) { + + caseval_t*cvp; + + for(cvp=clp->vals; cvp; cvp=cvp->next) { + + if(cvp->val==val) goto out; + else if(cvp->isdef) defclp=clp; + } + } +out: + if(clp || (clp=defclp)) { + + for(;clp;clp=clp->next) { + + if(clp->stmt) NODE_EXE(clp->stmt); + } + } + return 1; +} --- crash-4.0-4.6/extensions/libsial/sial_define.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_define.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,518 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include +#include +#include "sial.h" +/* + This set of functions handle #define for simple constant or macros. + We read from the current parser input strem untill end of line. + + The big thing is that we need to do some parsing to get the deinf names + and parameters. Also at the time of the macro instanciation, we need to parse + the parameters again. That leads to a more complex package... +*/ + +#define MAXP 20 +typedef struct mac_s { + + char *name; /* this macro name */ + int np; /* number of parameters */ + int issub; /* subs have to be threated differently */ + char **p; /* parameters names */ + char *buf; /* text for the macro itself */ + struct mac_s *next; /* next on the list */ + srcpos_t pos; + +} mac_t; + +typedef struct { + mac_t *m; + char **subs; +} smac_t; + +static mac_t* macs=0; + +/* we have to add a space at the end of the value + Again, this is to prevent a EOF on the parsing stream */ +def_t* +sial_add_def(def_t*d, char*name, char*val) +{ +def_t*nd=sial_alloc(sizeof(def_t)); +char *buf=sial_alloc(strlen(val)+2); + + strcpy(buf, val); + strcat(buf, " "); + sial_free(val); + nd->name=name; + nd->val=buf; + nd->next=d; + return nd; +} + +/* search for a macro is the current list */ +mac_t * +sial_getmac(char *name, int takeof) +{ +mac_t *m; +mac_t *prev=0; +mac_t *sial_getcurmac(void); + + if(takeof || !(m=sial_getcurmac())) m=macs; + + for(; m; m=m->next) { + + if( !strcmp(m->name, name) ) { + + if(takeof) { + + if(!prev) macs=m->next; + else prev->next=m->next; + + } + return m; + } + prev=m; + } + return 0; +} + +node_t* +sial_macexists(node_t*var) +{ +char *name=NODE_NAME(var); +int val; + + if(sial_getmac(name, 0)) val=1; + else val=0; + return sial_makenum(B_UL, val); +} +static void +sial_freemac(mac_t*m) +{ +int i; + + for(i=0;inp;i++) sial_free(m->p[i]); + if(m->np) sial_free(m->p); + sial_free(m); +} + +/* + These are called at 2 different points. + One call at the very begining. One call for each file. +*/ +void* sial_curmac(void) { return macs; } + +void +sial_flushmacs(void *vtag) +{ +mac_t *m, *next; +mac_t *tag=(mac_t *)vtag; + + for(m=macs; m!=tag; m=next) { + + next=m->next; + sial_freemac(m); + } + macs=m; +} + +/* this function is called to register a new macro. + The text associated w/ the macro is still on the parser stream. + Untill eol. +*/ +void +sial_newmac(char *mname, char *buf, int np, char **p, int silent) +{ +char *p2; +mac_t *m; + + { + char *p=buf+strlen(buf)-1; + + /* eliminate trailing blanks */ + while(*p && (*p==' ' || *p=='\t')) p--; + *(p+1)='\0'; + + /* eliminate leading blanks */ + p=buf; + while(*p && (*p==' ' || *p=='\t')) p++; + + /* copy and append a space. This is to prevent unloading of the + macro before the sial_chkvarmac() call as been performed */ + p2=sial_alloc(strlen(p)+2); + strcpy(p2, p); + sial_free(buf); + p2[strlen(p2)+1]='\0'; + p2[strlen(p2)]=' '; + buf=p2; + } + + if((m=sial_getmac(mname, 1)) && strcmp(m->buf, buf)) { + + /* when processing the compile options, be silent. */ + if(!silent) { + + sial_warning("Macro redefinition '%s' with different value_t\n" + "value_t=[%s]\n" + "Previous value_t at %s:%d=[%s]\n" + , mname, buf, m->pos.file, m->pos.line, m->buf); + } + + } + m=(mac_t*)sial_alloc(sizeof(mac_t)); + m->name=sial_strdup(mname); + m->np=np; + m->p=p; + m->buf=buf; + m->next=macs; + m->issub=0; + sial_setpos(&m->pos); + macs=m; +} + +/* this function is called by the enum declaration function and + when a enum type is extracted from the image to push a set + of define's onto the stack, that correspond to each identifier + in the enum. +*/ +void +sial_pushenums(enum_t *et) +{ + while(et) { + + char *buf=sial_alloc(40); + + sprintf(buf, "%d", et->value); + sial_newmac(et->name, buf, 0, 0, 0); + et=et->next; + } +} + +static void +sial_skipcomment(void) +{ +int c; + + while((c=sial_input())) { + + if(c=='*') { + + int c2; + + if((c2=sial_input())=='/') return; + sial_unput(c2); + } + } +} + +static void +sial_skipstr(void) +{ +int c; + + while((c=sial_input())) { + + if(c=='\\') sial_input(); + else if(c=='"') return; + } +} + + +/* skip over strings and comment to a specific chracter */ +static void +sial_skipto(int x) +{ +int c; + + while((c=sial_input())) { + + if(c==x) return; + + switch(c) { + + case '\\': + sial_input(); + break; + + case '"': + sial_skipstr(); + break; + + case '/': { + + int c2; + + if((c2=sial_input())=='*') { + + sial_skipcomment(); + + } else sial_unput(c2); + } + break; + + case '(': + + sial_skipto(')'); + break; + + case ')': + sial_error("Missing parameters to macro"); + break; + } + + } + + sial_error("Expected '%c'", x); +} + + +/* + This function gets called when the buffer for a macro as been fully + parsed. We need to take the associated parameter substitution macros + of of the stack and deallocate associated data. +*/ +static void +sial_popmac(void *vsm) +{ +smac_t *sm=(smac_t *)vsm; +int i; + + for(i=0;im->np;i++) { + + mac_t *m=sial_getmac(sm->m->p[i], 1); + + if(!m) sial_error("Oops macro pop!"); + sial_free(m->buf); + sial_free(m->name); + sial_free(m); + } + sial_free(sm->subs); + sial_free(sm); +} + +/* + + need to get the actual parameters from the parser stream. + This can be simple variable or complex multiple line expressions + with strings and commants imbedded in them... + +*/ +static int +sial_pushmac(mac_t *m) +{ +int i; +char **subs=sial_alloc(sizeof(char*)*m->np); +smac_t *sm; +int siallex(void); + + /* the next token should be a '(' */ + if(siallex() != '(') { + + sial_error("Expected '(' after '%s'", m->name); + + } + + /* get the parameters */ + for(i=0;inp;i++) { + + char *p=sial_cursorp(); + int nc; + + if(inp-1) sial_skipto(','); + else sial_skipto(')'); + + nc=sial_cursorp()-p-1; + subs[i]=sial_alloc(nc+2); + strncpy(subs[i], p, nc); + subs[i][nc]=' '; + subs[i][nc+1]='\0'; + } + + /* take care of the macro() case. ex: IS_R10000()i.e. no parms */ + if(!m->np) + sial_skipto(')'); + + sm=sial_alloc(sizeof(smac_t)); + + sm->m=m; + sm->subs=subs; + + /* we push the associated buffer on the stream */ + sial_pushbuf(m->buf, 0, sial_popmac, sm, 0); + + /* we push the subs onto the macro stack */ + for(i=0;inp;i++) { + + mac_t *pm=sial_alloc(sizeof(mac_t)); + + pm->name=sial_alloc(strlen(m->p[i])+1); + strcpy(pm->name, m->p[i]); + pm->np=0; + pm->p=0; + pm->buf=subs[i]; + pm->next=macs; + pm->issub=1; + macs=pm; + } + return 1; + +} + + +/* + This one is called from the lexer to check if a 'var' is to be substituted for + a macro +*/ +int +sial_chkmacvar(char *mname) +{ +mac_t *m; + + if((m=sial_getmac(mname, 0))) { + + + /* simple constant ? */ + if(!m->p) { + + sial_pushbuf(m->buf, 0, 0, 0, m->issub ? m->next : 0); + + } else { + return sial_pushmac(m); + } + return 1; + + } + return 0; + +} + +/* + Skip an unsupported preprocessor directive. +*/ +void +sial_skip_directive(void) +{ + sial_free(sial_getline()); +} + +void +sial_undefine(void) +{ +int c; +int i=0; +char mname[MAX_SYMNAMELEN+1]; +mac_t *m; + + /* skip all white spaces */ + while((c=sial_input()) == ' ' || c == '\t') if(c=='\n' || !c) { + + sial_error("Macro name expected"); + } + + mname[i++]=c; + + /* get the constant or macro name */ + while((c=sial_input()) != ' ' && c != '\t') { + + if(c=='\n' || !c) break; + if(i==MAX_SYMNAMELEN) break; + mname[i++]=c; + } + mname[i]='\0'; + if((m=sial_getmac(mname, 1))) sial_freemac(m); +} + +/* + This one is called from the lexer after #define as been detected +*/ +void +sial_define(void) +{ +int c; +int i=0; +char mname[MAX_SYMNAMELEN+1]; + + /* skip all white spaces */ + while((c=sial_input()) == ' ' || c == '\t') if(c=='\n' || !c) goto serror; + + mname[i++]=c; + + /* get the constant or macro name */ + while((c=sial_input()) != ' ' && c != '\t' && c != '(') { + + if(c=='\n' || !c) break; + + if(i==MAX_SYMNAMELEN) break; + + mname[i++]=c; + } + mname[i]='\0'; + + /* does this macro have paraneters */ + /* If so, '(' will be right after name of macro. No spaces. */ + if(c=='(') { + + int np, nc, done; + char **pnames; + char curname[MAX_SYMNAMELEN+1]; + + np=nc=done=0; + pnames=(char **)sial_alloc(sizeof(char*)*MAXP); + + while(!done) { + + c=sial_input(); + + switch(c) { + case '\n': case 0: + goto serror; + + /* continuation */ + case '\\': + if(sial_input()!='\n') goto serror; + break; + + case ',': + if(!nc) goto serror; +last: + curname[nc]='\0'; + pnames[np]=sial_alloc(strlen(curname)+1); + strcpy(pnames[np], curname); + nc=0; + np++; + break; + + case ')': + done=1; + if(nc) goto last; + break; + + case ' ': + case '\t': + break; + + default: + curname[nc++]=c; + break; + } + } + sial_newmac(mname, sial_getline(), np, pnames, 0); + return; + + } else if(c == '\n') { + + /* if nothing speciied then set to "1" */ + sial_newmac(mname, sial_strdup("1"), 0, 0, 0); + + } else { + + sial_newmac(mname, sial_getline(), 0, 0, 0); + } + + return; + +serror: + + sial_error("Syntax error on macro definition"); +} --- crash-4.0-4.6/extensions/libsial/sial_func.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_func.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,1191 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sial.h" + +/* + The next few functions manege the files and associated functions. +*/ +struct fdata; + +typedef struct fctype_t { + int idx; + struct fctype_t*next; + +} fctype_t; + +typedef struct func { + + char *name; /* name of the function */ + var_t*varlist; /* parameters information */ + var_t*rvar; /* return value_t information */ + node_t*body; /* execution node for body */ + int local; /* load i.e. static ? */ + srcpos_t pos; /* source position of function declaration */ + struct fdata *file; /* back pointer to corresponding file */ + struct func *next; /* linked list */ + +} func; + +typedef struct fdata { + + char *fname; /* name of the file */ + int isdso; /* is this from a loadable module ? + `globs' becomes the handle */ + time_t time; /* load time */ + var_t*fsvs; /* associated list of static variables */ + var_t*fgvs; /* associated list of global variables */ + void *globs; /* handle for these globals */ + func *funcs; /* chained list of functions */ + fctype_t *ctypes; /* ctypes declared by this function */ + struct fdata *next; /* chained list of files */ + +} fdata; + +static fdata *fall=0; +void sialparse(void); +static func * sial_getfbyname(char *name, fdata *thisfd); +value_t * sial_execmcfunc(func *f, value_t **vp); + +ull +sial_getval(value_t*v) +{ +ull ret=0; + + if(!v) return 0; + + /* need to cast properly here */ + if(v->type.type==V_BASE || v->type.type==V_REF) { + + if(v->type.type==V_REF || !sial_issigned(v->type.typattr)) { + + switch(TYPE_SIZE(&v->type)) { + case 1: ret= (ull) v->v.uc; break; + case 2: ret= (ull) v->v.us; break; + case 4: ret= (ull) v->v.ul; break; + case 8: ret= (ull) v->v.ull; break; + default: sial_error("Oops getval base"); + } + + } else { + + switch(TYPE_SIZE(&v->type)) { + case 1: ret= (ull) v->v.sc; break; + case 2: ret= (ull) v->v.ss; break; + case 4: ret= (ull) v->v.sl; break; + case 8: ret= (ull) v->v.sll; break; + default: sial_error("Oops getval base"); + } + } + } + /* in the case of a struct/union we pass a pointer to it */ + else ret = (unsigned long)v->v.data; + return ret; +} + +static int +sial_dohelp(char *fname) +{ +char buf[MAX_SYMNAMELEN+1]; +char *hstr; + + sprintf(buf, "%s_help", fname); + + if(sial_chkfname(buf, 0)) { + + char buf2[MAX_SYMNAMELEN+1]; + char *ustr; + + sprintf(buf2, "%s_usage", fname); + ustr=(char*)(unsigned long)sial_exefunc(buf2, 0); + sial_msg("COMMAND: %s %s\n\n", fname , ustr?ustr:""); + hstr=(char*)(unsigned long)sial_exefunc(buf, 0); + sial_format(1, hstr); + sial_format(0, "\n"); + sial_msg("\n"); + return 1; + } + return 0; +} + +void +sial_showallhelp() +{ +fdata *filep; + + for(filep=fall; filep; filep=filep->next) { + + func *funcp; + + for(funcp=filep->funcs;funcp;funcp=funcp->next) { + + (void)sial_dohelp(funcp->name); + + } + } +} + +int +sial_showhelp(char *fname) +{ + return sial_dohelp(fname); +} + +void* +sial_getcurfile() { return fall; } + +int +sial_isnew(void *p) +{ +fdata *fd=(fdata *)p; +struct stat stats; + + if(!stat(fd->fname, &stats)) { + + if(stats.st_mtime > fd->time) { + + return 1; + } + } + return 0; +} + +void * +sial_findfile(char *name, int unlink) +{ +fdata *fd; +fdata *last=0; + + for(fd=fall; fd; last=fd, fd=fd->next) { + + if(!strcmp(fd->fname, name)) { + + /* remove from the list ?*/ + if(unlink) { + + if(!last) fall=fd->next; + else last->next=fd->next; + + } + return fd; + } + + } + return 0; +} + +void +sial_freefunc(func *fn) +{ + sial_free(fn->name); + NODE_FREE(fn->body); + if(fn->varlist) sial_freesvs(fn->varlist); + sial_freevar(fn->rvar); + sial_free(fn); +} + +static void +sial_unloadso(fdata *fd) +{ +typedef int (*fp_t)(void); +fp_t fp; +func *f; + + if((fp=(fp_t)dlsym(fd->globs, BT_ENDDSO_SYM))) { + + fp(); + } + for(f=fd->funcs; f; ) { + + func *n=f->next; + sial_rmbuiltin(f->varlist); + sial_freevar(f->varlist); + sial_free(f); + f=n; + } + + dlclose(fd->globs); + + if(fall==fd) fall=fd->next; + else { + + fdata *last=fall; + + while(last->next) { + + if(last->next==fd) { + + last->next=fd->next; + break; + } + last=last->next; + } + } + + /* free the associated static and global variables */ + if(fd->fsvs) sial_freesvs(fd->fsvs); + if(fd->fgvs) sial_freesvs(fd->fgvs); + sial_free(fd->fname); + sial_free(fd); +} + +static void (*cb)(char *, int)=0; +void sial_setcallback(void (*scb)(char *, int)) +{ cb=scb; } +static void +sial_docallback( fdata *fd, int load) +{ +func *f; + + if(!cb) return; + + for(f=fd->funcs; f; f=f->next) { + + cb(f->name, load); + } +} + +void +sial_freefile(fdata *fd) +{ + if(fd) { + + func *fct, *nxt; + fctype_t *ct, *nct; + + if(fd->isdso) { + + sial_unloadso(fd); + return; + } + + /* free the associated static and global variables */ + if(fd->fsvs) sial_freesvs(fd->fsvs); + if(fd->fgvs) sial_freesvs(fd->fgvs); + + /* free all function nodes */ + // let debugger know ... + sial_docallback(fd, 0); + for(fct=fd->funcs; fct; fct=nxt) { + + nxt=fct->next; + sial_freefunc(fct); + } + + for(ct=fd->ctypes; ct; ct=nct) { + + nct=ct->next; + sial_free(ct); + } + sial_free(fd->fname); + if(fd->globs) sial_rm_globals(fd->globs); + sial_free(fd); + } + else sial_warning("Oops freefile!"); +} + +int +sial_deletefile(char *name) +{ +fdata *fd=sial_findfile(name, 0); + + if(fd) { + + sial_freefile(fd); + (void)sial_findfile(name, 1); + return 1; + + } + return 0; +} + +static int parsing=0; +static jmp_buf parjmp; + +void +sial_parseback(void) +{ + if(parsing) { + + parsing=0; + longjmp(parjmp, 1); + } +} + +/* link in a new set of static file variables */ +int +sial_file_decl(var_t*svs) +{ + sial_validate_vars(svs); + + if(!fall->fsvs) + fall->fsvs=(void*)sial_newvlist(); + + if(!fall->fgvs) + fall->fgvs=(void*)sial_newvlist(); + + (void)sial_addnewsvs(fall->fgvs, fall->fsvs, svs); + + return 1; +} + +typedef struct sigaction sact; +static int sigs[]={SIGSEGV, SIGILL, SIGTRAP, SIGINT, SIGPIPE}; +#define S_NSIG (sizeof(sigs)/sizeof(sigs[0])) + +void +sial_except_handler(int sig) +{ +static int i=0; + if(sig != SIGPIPE && sig != SIGINT) sial_error("Exception caught!"); + sial_dojmp(J_EXIT, &i); +} + +void * +sial_setexcept() +{ +int i; +sact *osa=sial_alloc(S_NSIG*sizeof(sact)); +#if linux +sact na; + + memset(&na, 0, sizeof(na)); + na.sa_handler=sial_except_handler; + na.sa_flags=SA_NODEFER; + +#else +sact na={ SA_NODEFER+SA_SIGINFO, sial_except_handler, 0, 0 }; +#endif + + + for(i=0;ifname="__expr__"; + fd->next=fall; + fall=fd; + + sial_pushbuf(exp2, "stdin", 0, 0, 0); + parsing=1; + if(!setjmp(parjmp)) { + + sial_rsteofoneol(); + sial_settakeproto(1); + sialparse(); + sial_settakeproto(0); + + /* remove longjump for parsing */ + parsing=0; + + if(!fall->fgvs) { + + sial_error("Invalid function declaration."); + + } + + ret=fall->fgvs->next; + + } else { + + sial_popallin(); + ret=0; + + } + sial_free(exp2); + /* only free the top of the fgvs list to keep 'ret' */ + if(fall->fgvs) sial_freevar(fall->fgvs); + if(fall->fsvs) sial_freesvs(fall->fsvs); + fall=fd->next; + sial_free(fd); + return ret; +} + +/* + Load a dso file. + We are looking for the btinit() and btshutdown() functions. + + btinit() will should initialized the package and call sial_builtin() + to install the sial functions. + + btshutdown(), if it exists, will be called when an unload of the + file is requested. The dso should deallocate memory etc... at that + time. +*/ +static int +sial_loadso(char *fname, int silent) +{ +void *h; + + if((h=dlopen(fname, RTLD_LAZY))) { + + typedef int (*fp_t)(void); + fp_t fp; + + if((fp=(fp_t)dlsym(h, BT_INIDSO_SYM))) { + + btspec_t *sp; + + if(fp()) { + + if((sp=(btspec_t *)dlsym(h, BT_SPEC_SYM))) { + + int i; + fdata *fd=sial_calloc(sizeof(fdata)); + func **ff=&fd->funcs; + + fd->fname=fname; + fd->isdso=1; + fd->globs=h; + + for(i=0;sp[i].proto;i++) { + + var_t*v; + + if((v=sial_builtin(sp[i].proto, sp[i].fp))) { + + func *f=sial_alloc(sizeof(func)); + + f->varlist=v; + f->next=*ff; + *ff=f; + } + } + fd->next=fall; + fall=fd; + return 1; + + } else if(!silent) { + + sial_msg("Missing '%s' table in dso [%s]", BT_SPEC_SYM, fname); + + } + + } else if(!silent) { + + sial_msg("Could not initialize dso [%s]", fname); + + } + + } else if(!silent) { + + sial_msg("Missing '%s' function in dso [%s]", BT_INIDSO_SYM, fname); + } + dlclose(h); + } + else if(!silent) sial_msg(dlerror()); + sial_free(fname); + return 0; +} + +void +sial_addfunc_ctype(int idx) +{ +fctype_t *fct=sial_alloc(sizeof(fctype_t)); + + fct->idx=idx; + fct->next=fall->ctypes; + fall->ctypes=fct; +} + +int +sial_newfile(char *name, int silent) +{ +fdata *fd; +fdata *oldf; +char *fname=sial_strdup(name); +void *mtag; + + /* check if this is a dso type file */ + if(!strcmp(fname+strlen(fname)-3, ".so")) { + + if(sial_findfile(name,0)) { + + if(!silent) + sial_msg("Warning: dso must be unloaded before reload\n"); + return 0; + } + return sial_loadso(fname, silent); + + } + + fd=sial_calloc(sizeof(fdata)); + oldf=sial_findfile(name,1); + + /* push this file onto the parser stack */ + if(!sial_pushfile(fname)) { + + sial_free(fname); + if(!silent && errno != EISDIR) sial_msg("File %s : %s\n", name, strerror(errno)); + return 0; + } + + /* we also need to remove the globals for this file + before starting the parsing */ + if(oldf && oldf->globs) { + + sial_rm_globals(oldf->globs); + oldf->globs=0; + + } + + needvar=instruct=0; + + fd->fname=fname; + + /* put it on the list */ + fd->next=fall; + fall=fd; + + /* we tag the current ctype list so we know later what to clean up */ + sial_tagst(); + + /* we also tag the macro stack so we can erase out defines and + keep the compiler and api ones. */ + mtag=sial_curmac(); + + parsing=1; + if(!setjmp(parjmp)) { + + func *fct; + int ret=1; + + /* parse it */ + sial_rsteofoneol(); + + sialparse(); + + /* remove longjump for parsing */ + parsing=0; + + /* before adding the globals we need to push all the static + variables for this file since the initialization expressions + might use them (e.g. sizeof('a static var')). Eh, as long as + we keep the interpreter handling a superset of the 'standard' C + I don't have a problem with it. Do you ? */ + + { + int lev; + + lev=sial_addsvs(S_STAT, fd->fsvs); + + /* ok to add the resulting globals now */ + fall->globs=sial_add_globals(fall->fgvs); + + sial_setsvlev(lev); + } + + /* ok to free olf version */ + if(oldf) sial_freefile(oldf); + + sial_flushtdefs(); + sial_flushmacs(mtag); + + /* we proceed with the callback */ + sial_docallback(fd, 1); + + fd->time=time(0); + + /* compilation was ok , check for a __init() function to execute */ + if((fct=sial_getfbyname("__init", fd))) { + + int *exval; + jmp_buf exitjmp; + sact *sa; + + sa=sial_setexcept(); + + if(!setjmp(exitjmp)) { + + sial_pushjmp(J_EXIT, &exitjmp, &exval); + sial_freeval(sial_execmcfunc(fct, 0)); + sial_rmexcept(sa); + sial_popjmp(J_EXIT); + + } + else { + + sial_rmexcept(sa); + ret=0; + } + + } + return ret; + } + else { + + /* remove all streams from the stack */ + sial_popallin(); + + /* error, free this partial one and reinstall old one */ + if(oldf) { + /* we zap the top pointer (it's fd) */ + oldf->next=fall->next; + fall=oldf; + oldf->globs=sial_add_globals(oldf->fgvs); + } + else { + + fall=fall->next; + } + + /* and free fd */ + sial_freefile(fd); + } + sial_flushtdefs(); + sial_flushmacs(mtag); + return 0; +} + +/* scan the current list of functions for the one named name */ +static func * +sial_getfbyname(char *name, fdata *thisfd) +{ +fdata *fd; + + /* check localy first */ + if(thisfd) { + + for(fd=fall; fd; fd=fd->next) { + + func *f; + + if(fd->isdso) continue; + + /* skip non-local function */ + if(thisfd != fd) continue; + + for(f=fd->funcs; f; f=f->next) { + + if(!strcmp(f->name, name)) return f; + } + } + } + + /* check global function */ + for(fd=fall; fd; fd=fd->next) { + + func *f; + + if(fd->isdso) continue; + + for(f=fd->funcs; f; f=f->next) { + + /* skip static functions not local */ + if(f->local) continue; + + if(!strcmp(f->name, name)) return f; + } + } + return 0; +} + +/* external boolean to check if a function exists */ +int sial_funcexists(char *name) +{ + return !(!(sial_getfbyname(name, 0))); +} + +/* + This combined set of functions enables the aplication to + get alist of currently defined commands that have a help. +*/ +static fdata *nxtfdata=0; +static func *nxtfunc; +void +sial_rstscan(void) +{ + nxtfdata=0; +} +char * +sial_getnxtfct(void) +{ + if(!nxtfdata) { + + if(!fall) return 0; + nxtfdata=fall; + nxtfunc=nxtfdata->funcs;; + } + + while(nxtfdata) { + + if(!nxtfdata->isdso) for(; nxtfunc; nxtfunc=nxtfunc->next) { + + int l=strlen(nxtfunc->name); + + if(l > 5) { + + if(!strcmp(nxtfunc->name+l-5, "_help")) { + + char buf[MAX_SYMNAMELEN+1]; + func *ret; + + strncpy(buf, nxtfunc->name, l-5); + buf[l-5]='\0'; + + /* make sure we do have the function */ + if((ret=sial_getfbyname(buf, 0))) { + + nxtfunc=nxtfunc->next; + return ret->name; + } + } + } + } + nxtfdata=nxtfdata->next; + if(nxtfdata) nxtfunc=nxtfdata->funcs; + } + sial_rstscan(); + return 0; +} + +/* + This is the entry point for the error handling +*/ +void +sial_exevi(char *fname, int line) +{ +char buf[200]; +char *ed=getenv("EDITOR"); + + if(!ed) ed="vi"; + snprintf(buf, sizeof(buf), "%s +%d %s", ed, line, fname); + system(buf); + sial_load(fname); +} + +/* + This funciton is called to start a vi session on a function + (file=0) or a file (file=1); +*/ +void +sial_vi(char *fname, int file) +{ +int line, freeit=0; +char *filename; + + if(file) { + + filename=sial_filempath(fname); + + if(!filename) { + + sial_msg("File not found : %s\n", fname); + return; + + } + + line=1; + freeit=1; + + + } else { + + func *f=sial_getfbyname(fname, 0); + + if(!f) { + + sial_msg("Function not found : %s\n", fname); + return; + + } else { + + filename=f->pos.file; + line=f->pos.line; + + } + } + + sial_exevi(filename, line); + + if(freeit) sial_free(filename); + +} + +char * +sial_getfile(char *fname) +{ +func *f; + + if((f=sial_getfbyname(fname, 0))) return f->file->fname; + return 0; +} + +static void +sial_insertfunc(func *f) +{ + f->next=fall->funcs; + fall->funcs=f; +} + +value_t * +sial_execmcfunc(func *f, value_t **vp) +{ +value_t *retval; +jmp_buf env; +var_t*parm=0; +int i=0; +char *ocurp, *curp; + + /* set the current path */ + { + char *p; + + curp=sial_strdup(f->file->fname); + if((p=strrchr(curp, '/'))) *p='\0'; + ocurp=sial_curp(curp); + } + + + if(!(setjmp(env))) { + + /* push a return level */ + sial_pushjmp(J_RETURN, &env, &retval); + + /* Now it's ok to add any static vars for this file */ + sial_addsvs(S_FILE, f->file->fsvs); + + /* we need to create brand new variables with + the name of the declared arguments */ + if(f->varlist) { + + for(i=0, parm=f->varlist->next; + vp && (parm != f->varlist) && vp[i]; + parm=parm->next, i++) { + + var_t*var=sial_newvar(parm->name); + + var->v=sial_cloneval(parm->v); + sial_chkandconvert(var->v, vp[i]); + sial_add_auto(var); + sial_freeval(vp[i]); + + } + } + if(vp && vp[i]) { + + sial_warning("Too many parameters to function call"); + + } else if(parm != f->varlist) { + + sial_warning("Not enough parameters for function call"); + } + + /* we execute the buddy of the function */ + retval=NODE_EXE(f->body); + + sial_freeval(retval); + + retval=0; + + sial_popjmp(J_RETURN); + } + + /* make sure non void function do return something */ + if(!retval) { + + if(!sial_isvoid(f->rvar->v->type.typattr)) + + sial_rwarning(&f->pos, "Non void function should return a value."); + + } else { + + /* type checking here ... */ + } + + sial_curp(ocurp); + sial_free(curp); + + return retval; +} + +/* this is the externalized function that the API users call to execute + a function */ +ull +sial_exefunc(char *fname, value_t **vp) +{ +func *f; +ull ret; + + if(!sial_chkfname(fname, 0)) + sial_warning("Unknown function called: %s\n", fname); + + /* builtin vs cmc ...*/ + if((f=sial_getfbyname(fname, 0))) ret=sial_getval(sial_execmcfunc(f, vp)); + else ret=sial_getval(sial_exebfunc(fname, vp)); + /* sial_freeval(v); */ + return ret; +} + +value_t * +sial_exefunc_common(char *fname, node_t*parms, fdata *fd) +{ +int i; +node_t*args; +value_t *vp[BT_MAXARGS+1]; +func *f; + + /* We most execute before pushing the S_FILE vars so the the + local variable for the caller can still be accessed */ + for(i=0,args=parms; args; args=args->next) { + + if(i==BT_MAXARGS) { + + sial_error("Max number of parameters exceeded [%d]", BT_MAXARGS); + } + vp[i++]=NODE_EXE(args); + + } + + /* null out the rest */ + for(;i<=BT_MAXARGS;i++) vp[i]=0; + + /* builtin vs cmc ...*/ + if((f=sial_getfbyname(fname, fd))) return sial_execmcfunc(f, vp); + else return sial_exebfunc(fname, vp); +} + + +/* this function is called by the sial_exeop() through a CALL op. */ +value_t * +sial_docall(node_t*name, node_t*parms, void *arg) +{ +fdata *fd = arg; +char *sname=sial_vartofunc(name); +value_t *v=0; + + if(sial_chkfname(sname, fd)) { + + v=sial_exefunc_common(sname, parms, fd); + + } + else sial_rerror(&name->pos, "Unknown function being called:[%s]", sname, fd); + /* sial_vartofunc() allocates the name */ + /* we don't free this item if mem debug has been set */ + if(!sial_ismemdebug()) sial_free(sname); + return v; + +} + +int +sial_newfunc(var_t*fvar, node_t* body) +{ +var_t*v=fvar->next; + + if(v == fvar) { + + sial_freevar(v); + NODE_FREE(body); + sial_error("Syntax error in function declaration"); + + }else{ + + func *fn, *fi ; + + sial_freevar(fvar); + + /* we do the func insertion first so that if we have a problem + we can jump our of the parser using the sial_parback() function + which will deallocate the stuff */ + + fn=sial_alloc(sizeof(func)); + if(sial_isstatic(v->v->type.typattr)) fn->local=1; + fn->rvar=v; + fn->varlist=v->dv->fargs; + + /* check for func(void) */ + if(fn->varlist && fn->varlist->next != fn->varlist) { + + var_t*v=fn->varlist->next; + + if(v->v->type.type != V_REF && sial_isvoid(v->v->type.typattr)) { + + /* cut the chain here */ + if(v->next != fn->varlist) { + + sial_error("function parameter cannot have 'void' type"); + } + sial_freesvs(fn->varlist); + fn->varlist=0; + } + } + + v->dv->fargs=0; + fn->name=sial_strdup(v->name); + fn->local=sial_isstatic(v->v->type.typattr)?1:0; + fn->body=body; + fn->file=fall; + + /* the position of the function is the position of the var_t*/ + memcpy(&fn->pos, &v->dv->pos, sizeof(srcpos_t)); + + /* emit a warning for variables in the main statement group that + shadow ont of the parameters */ + if(fn->varlist) { + + var_t*v; + + for(v=fn->varlist->next; v!=fn->varlist; v=v->next) { + + var_t*vs; + + if((vs=sial_inlist(v->name, sial_getsgrp_avs(body))) || + (vs=sial_inlist(v->name, sial_getsgrp_svs(body)))) { + + sial_rwarning(&vs->dv->pos, "variable '%s' shadow's a function parameter" + , v->name); + + } + } + } + + if((fi=sial_getfbyname(fn->name, fall))) { + + /* check for local conflicts */ + if(fi->file == fn->file) { + + sial_insertfunc(fn); + sial_rerror(&fn->pos, "Function '%s' redefinition, first defined in file '%s' line %d" + , fn->name, fi->pos.file, fi->pos.line); + + /* check for global conflicts */ + } else if(!fn->local) { + + sial_insertfunc(fn); + sial_rerror(&fn->pos, "Function '%s' already defined in file %s, line %d" + , fn->name, fi->pos.file, fi->pos.line); + + } /* else... it's a static that shadows a global somewhere else. So it's ok */ + + } + + /* Searching is all done, so insert it */ + sial_insertfunc(fn); + + /* check out the storage class. Only 'static' is supported */ + if(!sial_isjuststatic(v->v->type.typattr)) { + + sial_error("Only 'static' storage class is valid for a function"); + } + } + return 1; +} + +/* check for the existance of a function in the list */ +int +sial_chkfname(char *fname, void *vfd) +{ +fdata *fd=(fdata *)vfd; + + /* check script functions */ + if(!sial_getfbyname(fname, fd)) { + + /* check builtin list */ + if(sial_chkbuiltin(fname)) return 1; + return 0; + + } + return 1; +} + +/* + + Thsi is the interface function with the command interpreter. + It needs to be able to execute a function giving a name and + passing some random parameters to it. + + A return of 0 means "no such function". +*/ +int +sial_runcmd(char *fname, var_t*args) +{ + if(sial_chkfname(fname, 0)) { + + value_t *val; + int *exval; + jmp_buf exitjmp; + void *vp; + ull ret; + sact *sa; + + /* make sure arguments are available in the global vars */ + vp=sial_add_globals(args); + + /* we set the exception handler too... */ + sa=sial_setexcept(); + + if(!setjmp(exitjmp)) { + + sial_pushjmp(J_EXIT, &exitjmp, &exval); + + /* we need to create a var with that name */ + val=sial_exefunc_common(fname, 0, 0); + + sial_popjmp(J_EXIT); + + if(val) { + + ret=unival(val); + sial_freeval(val); + } + else ret=0; + } + else { + + ret=*exval; + } + + /* remove exception handlers and restore previous handlers */ + sial_rmexcept(sa); + + /* remove args from global vars */ + sial_rm_globals(vp); + return ret; + } + return 0; +} + --- crash-4.0-4.6/extensions/libsial/sial.h 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial.h 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,457 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include "sial_api.h" +typedef unsigned long long caddr; + +#define SRCPOS_S struct srcpos_s +#define DVAR_S struct dvar_s +#define CASELIST_S struct caselist_s +#define CASEVAL_S struct caseval_s +#define STMEMBER_S struct stmember_s +#define STINFO_S struct stinfo_s + +SRCPOS_S; +DVAR_S; +CASELIST_S; +CASEVAL_S; +STMEMBER_S; +STINFO_S; + + +/************* source position tracking ************/ +typedef SRCPOS_S { + char *file; + int line; + int col; +} srcpos_t; + +/* member information */ +typedef MEMBER_S { + + char *name; + int offset; /* offset from top of structure */ + int size; /* size in bytes of the member or of the bit array */ + int fbit; /* fist bit (-1) is not a bit field */ + int nbits; /* number of bits for this member */ + int value; /* for a enum member, the corresponding value_t */ + +} member_t; + +/* list to hold enum constant information */ +typedef ENUM_S { + + struct enum_s *next; + char *name; + int value; + +} enum_t; + +/* list of macro symbols and there corresponding value_ts */ +typedef DEF_S { + struct def_s * next; + char *name; + char *val; + +} def_t; + +/* type_t information past back and forth */ +typedef TYPE_S { + int type; /* type_t of type_t */ + ull idx; /* index to basetype_t or ctype_t */ + int size; /* size of this item */ + /* ... next fields are use internally */ + int typattr; /* base type_t qualifiers */ + int ref; /* level of reference */ + int fct; /* 1 if function pointer */ + int *idxlst; /* points to list of indexes if array */ + ull rtype; /* type_t a reference refers too */ +} type_t; + +/* scope/storage of variables */ +#define S_FILE 1 /* persistant file scope */ +#define S_STAT 2 /* persistant statement scope */ +#define S_AUTO 3 /* stack (default) */ +#define S_GLOB 4 /* add to the global variables */ + +typedef union vu_s { + unsigned char uc; + signed char sc; + unsigned short us; + signed short ss; + unsigned int ul; + signed int sl; + unsigned long long ull; + signed long long sll; + void *data; +} vu_t; + +/************* value_t **************/ +typedef VALUE_S { + type_t type; + int set; /* is this is a Lvalue_t then set is 1 */ + VALUE_S *setval;/* value_t to set back to */ + void (*setfct)(struct value_s*, struct value_s*); + /* the function that will set the value */ + ARRAY_S *arr; /* array associated with value */ + vu_t v; + ull mem; +} value_t; + +/************** array linked lists *****************/ +typedef ARRAY_S { + + ARRAY_S *next; /* to support a linked list of array elements */ + ARRAY_S *prev; + int ref; /* reference count on this array */ + VALUE_S *idx; /* arrays can be indexed using any type of variables */ + VALUE_S *val; /* arrays element values */ + +} array_t; + +/************* node_t *************/ +typedef NODE_S { + VALUE_S* (*exe)(void*); /* execute it */ + void (*free)(void*); /* free it up */ + char* (*name)(void*); /* get a name */ + void *data; /* opaque data */ + NODE_S* next; + SRCPOS_S pos; +} node_t; + +typedef IDX_S { + + int nidx; + NODE_S *idxs[MAXIDX]; + +} idx_t; + +/*************** variable list ****************/ +typedef VAR_S { + + char *name; + VAR_S *next; + VAR_S *prev; + VALUE_S *v; + int ini; + DVAR_S *dv; + +} var_t; + +/* V_BASE subtype */ +#define B_SC 0 /* signed char */ +#define B_UC 1 /* unsignec char */ +#define B_SS 2 /* signed short */ +#define B_US 3 /* unsigned short */ +#define B_SL 4 /* signed long */ +#define B_UL 5 /* unsigned long */ +#define B_SLL 6 /* signed long long */ +#define B_ULL 7 /* unsigned long long */ + +#define is_ctype(t) ((t)==V_UNION || (t)==V_STRUCT) +#define VAL_TYPE(v) (v->type.type) +#define TYPE_SIZE(t) ((t)->type==V_REF?sial_defbsize():(t)->size) + +/* type_ts of jumps */ +#define J_CONTINUE 1 +#define J_BREAK 2 +#define J_RETURN 3 +#define J_EXIT 4 + +#define sial_setval(v, v2) if((v)->set) ((v)->setfct)((v)->setval, (v2)) + +/************* case *************/ +typedef CASEVAL_S { + + int isdef; + ull val; + CASEVAL_S *next; + SRCPOS_S pos; + +} caseval_t; + +typedef CASELIST_S { + + CASEVAL_S *vals; + NODE_S *stmt; + CASELIST_S *next; + SRCPOS_S pos; + +} caselist_t; + +/*************** struct member info ****************/ +typedef STMEMBER_S { + + TYPE_S type; /* corresponding type_t */ + MEMBER_S m; /* member information */ + + STMEMBER_S *next; + +} stmember_t; + +typedef DVAR_S { + + char *name; + int refcount; + int ref; + int fct; + int bitfield; + int nbits; + IDX_S *idx; + NODE_S *init; + VAR_S *fargs; + SRCPOS_S pos; + DVAR_S *next; + +} dvar_t; + +typedef STINFO_S { + char *name; /* structure name */ + ull idx; /* key for search */ + int all; /* local : partial or complete declaration ? */ + TYPE_S ctype; /* associated type */ + TYPE_S rtype; /* real type_t when typedef */ + STMEMBER_S *stm; /* linked list of members */ + ENUM_S *enums; /* enums names and values */ + STINFO_S *next; /* next struct on the list */ + +} stinfo_t; + +stinfo_t *sial_getstbyindex(ull idx, int type_t); + +typedef value_t* (*xfct_t)(void *); +typedef char* (*nfct_t)(void *); +typedef void (*ffct_t)(void *); +typedef void (*setfct_t)(value_t*, value_t*); + +#ifdef DEBUG +#define NODE_EXE(n) (printf("(%s):[%d]\n",__FILE__, __LINE__), (n)->exe((n)->data)) */ +#else +#define NODE_EXE(n) ((n)->exe((n)->data)) +#endif +#define NODE_NAME(n) ((n)->name?((n)->name((n)->data)):0) +#define NODE_FREE(n) (sial_freenode(n)) + +#if 0 +#define TAG(p) sial_caller(p, __return_address) +#else +#define TAG(p) ; +#endif + +node_t *sial_sibling(node_t*, node_t*); +node_t *sial_newnode(void); +node_t *sial_newvnode(char *); +node_t *sial_newstr(void); +node_t *sial_newnum(char *); +node_t *sial_newop(int op, int nagrs, ...); +node_t *sial_newptrto(int, node_t*); +node_t *sial_newmult(node_t*, node_t*, int); +node_t *sial_newstat(int op, int nargs, ...); +node_t *sial_stat_decl(node_t*, var_t*); +node_t *sial_addstat(node_t*, node_t*); +node_t *sial_type_cast(type_t*, node_t*); +node_t *sial_newmem(int, node_t*, node_t*); +node_t *sial_newcall(node_t*, node_t*); +node_t *sial_newindex(node_t*, node_t*); +node_t *sial_newadrof(node_t*); +node_t *sial_newcase(node_t*, node_t*); +node_t *sial_addcase(node_t*, node_t*); +node_t *sial_caseval(int, node_t*); +node_t *sial_addcaseval(node_t*, node_t*); +node_t *sial_sizeof(void *p, int type_t); +node_t *sial_tdeftovar(type_t *td); +node_t *sial_getppnode(void); +node_t *sial_allocstr(char *buf); +node_t *sial_makenum(int type_t, ull val); +node_t *sial_macexists(node_t *var_t); +node_t *sial_newptype(var_t *v); +node_t *sial_newpval(node_t *vn, int fmt); +node_t *sial_strconcat(node_t *, node_t *); +node_t *sial_typecast(type_t*type, node_t*expr); + +dvar_t *sial_newdvar(node_t *v); +dvar_t *sial_linkdvar(dvar_t *dvl, dvar_t *dv); +dvar_t *sial_dvarini(dvar_t *dv, node_t *init); +dvar_t *sial_dvaridx(dvar_t *dv, node_t *n); +dvar_t *sial_dvarfld(dvar_t *dv, node_t *n); +dvar_t *sial_dvarptr(int ref, dvar_t *dv); +dvar_t *sial_dvarfct(dvar_t *dv, var_t *fargs); + +void sial_pushjmp(int type_t, void *env, void *val); +void sial_popjmp(int type_t); +void *sial_getcurfile(void); +void sial_walkarray(node_t *varnode_t, node_t *arrnode_t, void(*cb)(void *), void *data); +void get_bit_value(ull val, int nbits, int boff, int size, value_t *v); +void sial_enqueue(var_t *vl, var_t *v); +void sial_freenode(node_t *n); +void sial_validate_vars(var_t *svs); +void sial_freesvs(var_t *svs); +void *sial_setexcept(void); +void sial_tdef_decl(dvar_t *dv, type_t *t); +void sial_refarray(value_t *v, int inc); +void *sial_curmac(void); +void sial_setfct(value_t *v1, value_t *v2); +void sial_exevi(char *fname, int line); +void sial_unput(char); +void sial_dupval(value_t *v, value_t *vs); +void sial_parseback(void); +void sial_curpos(srcpos_t *p, srcpos_t *s); +void sial_rmexcept(void *osa); +void sial_chksign(type_t*t); +void sial_chksize(type_t*t); +void sial_setpos(srcpos_t *p); +void sial_rerror(srcpos_t *p, char *fmt, ...); +void sial_rwarning(srcpos_t *p, char *fmt, ...); +void sial_chkandconvert(value_t *vto, value_t *vfrm); +void sial_warning(char *fmt, ...); +void sial_format(int tabs, char *str); +void sial_freevar(var_t*v); +void sial_rmbuiltin(var_t*v); +void sial_rm_globals(void *vg); +void sial_addnewsvs(var_t*avl, var_t*svl, var_t*nvl); +void sial_dojmp(int type, void *val); +void sial_pushbuf(char *buf, char *fname, void(*f)(void*), void *d, void *m); +void sial_rsteofoneol(void); +void sial_settakeproto(int v); +void sial_popallin(void); +void sial_tagst(void); +void sial_flushtdefs(void); +void sial_setsvlev(int newlev); +void sial_flushmacs(void *tag); +void sial_add_auto(var_t*nv); +void *sial_chkbuiltin(char *name); +void sial_freedata(value_t *v); +void sial_dupdata(value_t *v, value_t *vs); +void sial_setarray(array_t**arpp); +void sial_rawinput(int on); +void sial_setini(node_t*n); +void sial_valindex(value_t *var, value_t *idx, value_t *ret); +void sial_free_siblings(node_t*ni); +void sial_mkvsigned(value_t*v); +void sial_transval(int s1, int s2, value_t *v, int issigned); +void sial_popref(type_t*t, int ref); +void sial_getmem(ull kp, void *p, int n); +void sial_baseop(int op, value_t *v1, value_t *v2, value_t *result); +void sial_setinsizeof(int v); +void sial_freeidx(idx_t *idx); +void sial_freedvar(dvar_t*dv); +void sial_pushenums(enum_t *et); +void sial_addfunc_ctype(int idx); +void sial_setapiglobs(void); +void sial_setbuiltins(void); +void sial_setdefbtype(int size, int sign); +void get_bit_value(ull val, int nbits, int boff, int size, value_t *v); +void *sial_findfile(char *name, int unlink); +void sial_newmac(char *mname, char *buf, int np, char **p, int silent); +void *sial_getcurfile(void); +void *sial_getcurfile(void); +void sial_startctype(int type, node_t*namen); +void sial_addtolist(var_t*vl, var_t*v); +void sial_arch_swapvals(void* vp, void *sp); +void sial_fillst(stinfo_t *st); +void sial_exememlocal(value_t *vp, stmember_t* stm, value_t *v); +void sial_do_deref(int n, value_t *v, value_t *ref); + +stmember_t*sial_member(char *mname, type_t*tp); + +ull set_bit_value_t(ull dvalue_t, ull value_t, int nbits, int boff); +ull unival(value_t *); +ul sial_bool(value_t *); + +value_t *sial_docall(node_t *, node_t *, void *); +value_t *sial_docast(void); +value_t *sial_newval(void); +value_t *sial_exebfunc(char *, value_t **); +value_t *sial_exevar(void *); +value_t *sial_exenode(node_t *); +value_t *sial_setstrval(value_t *, char *); +value_t *sial_defbtype(value_t *, ull); +value_t *sial_defbtypesize(value_t *, ull, int); +value_t *sial_sprintf(value_t *, ...); +value_t *sial_printf(value_t *, ...); +value_t *sial_exists(value_t *vname); +value_t *sial_exit(int v); +value_t *sial_bload(value_t *name); +value_t *sial_bdepend(value_t *name); +value_t *sial_bunload(value_t *vfname); +value_t *sial_showtemp(void); +value_t *sial_showaddr(value_t *vadr); +value_t *sial_findsym(value_t *vadr); +value_t *sial_memdebugon(void); +value_t *sial_memdebugoff(void); +value_t *sial_ismember(value_t*vp, value_t*vm); + +value_t *sial_prarr(value_t*name, value_t*root); +value_t *sial_getstr(value_t*vm); + +var_t *sial_vardecl(dvar_t *dv, type_t *t); +var_t *sial_inlist(char *name, var_t *vl); +var_t *sial_dupvlist(var_t *vl); +var_t *sial_getcurgvar(void); +var_t *sial_getvarbyname(char *name, int silent, int local); +var_t *sial_getsgrp_avs(node_t *n); +var_t *sial_getsgrp_svs(node_t *n); +var_t *sial_parsexpr(char *); + +int sial_file_decl(var_t *svs); +int sial_newfunc(var_t *fvar, node_t* body); +int sial_line(int inc); +int sial_samectypename(int type_t, ull idx1, ull idx2); +int sial_issigned(int attr); +int sial_isstatic(int atr); +int sial_isjuststatic(int attr); +int sial_isconst(int atr); +int sial_issigned(int atr); +int sial_istdef(int atr); +int sial_isxtern(int atr); +int sial_isvoid(int atr); +int sial_isstor(int atr); +int sial_ispartial(type_t*t); +int sial_input(void); +int sial_addsvs(int type, var_t*sv); +int sial_pushfile(char *name); +int sial_chkfname(char *fname, void *fd); +int sial_lookuparray(node_t*vnode, node_t*arrnode); +int sial_runcmd(char *fname, var_t*args); +int sial_getseq(int c); +int sial_newfile(char *name, int silent); +int sial_deletefile(char *name); +int sial_getsvlev(void); +int sial_idxtoattr(int idx); +int sial_docase(ull val, caselist_t*cl); +int siallex(void); +int sialpplex(void); +int sial_ismemdebug(void); +int sial_isenum(int atr); +int sial_funcexists(char *name); +int sial_isnew(void* p); + +char *sial_vartofunc(node_t *name); +char *sial_gettdefname(ull idx); +char *sial_ctypename(int type_t); +char *sial_filempath(char *fname); +char *sial_fileipath(char *fname); +char *sial_getline(void); +char *sial_cursorp(void); +char *sial_getbtypename(int typattr); +char *sial_filename(void); +char *sial_curp(char *); + +type_t *sial_newcast(var_t *v); +type_t *sial_newctype(int ctype_t, node_t *n); +type_t *sial_addbtype(type_t *t, int newtok); +type_t *sial_ctype_decl(int ctype_t, node_t *n, var_t *list); +type_t *sial_enum_decl(int ctype_t, node_t *n, dvar_t *dvl); +type_t *sial_addstorage(type_t *t1, type_t *t2); +type_t *sial_getvoidstruct(int ctype); + +extern int lineno, needvar, instruct, nomacs; + +#define NULLNODE ((node_t*)0) + +/* configuration variables */ +#define S_MAXSTRLEN 1024 /* lengh of a STRING variable value_t */ +#define S_MAXDEEP 500 /* maximum stacking of calls */ +#define S_MAXFILES 200 /* maximum number of macro files */ + +#define S_VARARG "__VARARG" /* name of the special var for ... */ --- crash-4.0-4.6/extensions/libsial/sial_input.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_input.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,802 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sial.h" + +char *sialpp_create_buffer(void *, int); +void sialpp_switch_to_buffer(void *); +void sialpp_delete_buffer(void *); + +typedef void fdone(void *data); +extern void* sial_create_buffer(FILE *, int); +typedef struct inbuf_s { + srcpos_t pos; /* current filename,line,col */ + int cursor; /* position of next input() character */ + int len; /* length of the buffer */ + char *buf; /* buffer */ + void *data; /* opaque data for callback */ + void *mac; /* for nested defines substitutions */ + fdone *donefunc; /* function to call when done with buffer */ + int space; + int eofonpop; /* terminate parsing at end of buffer ? */ +#if linux + void* yybuf; +#endif + +} inbuf_t; + +void sial_switch_to_buffer(void *); +void sial_delete_buffer(void *); +#define MAXIN 20 +static inbuf_t inlist[MAXIN]; +static inbuf_t *in=0; +static int nin=0; +static int eol=0, virgin=1; +#if linux +static int inpp=0; +#endif + +extern void *sial_getmac(char *, int); + +/* this function is called by the macro macro functions to set + and test the current buffer level in order to take care of + imbedded macros w/ the same parameter names. + see sial_getmac(). +*/ +void *sial_getcurmac(void) +{ + return in ? in->mac : 0 ; +} + +static void +sial_pusherror(void) +{ + sial_error("Too many level of input stream"); +} + +/* + Push a buffer onto the parser input stream. +*/ +void +sial_pushbuf(char *buf, char *fname, void (*vf)(void *), void *d, void *m) +{ +fdone *f=(fdone*)vf; + + if(nin==MAXIN) sial_pusherror(); + + /* if we are pushing a macro then use upper level coordinates */ + if(fname) { + + inlist[nin].pos.line=1; + inlist[nin].pos.col=1; + inlist[nin].pos.file=fname; + + } else sial_setpos(&inlist[nin].pos); + + /* set it */ + if(nin) { + + sial_curpos(&inlist[nin].pos, &inlist[nin-1].pos); + + } else { + + sial_curpos(&inlist[nin].pos, 0); + + } + + inlist[nin].buf=buf; + inlist[nin].donefunc=f; + inlist[nin].space=0; + inlist[nin].data=d; + inlist[nin].mac=m; + inlist[nin].cursor=0; + inlist[nin].len=strlen(buf); + inlist[nin].eofonpop=0; +#if linux + if(inpp) { + inlist[nin].yybuf=sialpp_create_buffer(0, inlist[nin].len); + sialpp_switch_to_buffer(inlist[nin].yybuf); + }else{ + inlist[nin].yybuf=sial_create_buffer(0, inlist[nin].len); + sial_switch_to_buffer(inlist[nin].yybuf); + } +#endif + in=&inlist[nin]; + nin++; +} + +/* read the rest of the "#include" line from the parser input stream + open the corresponding file, push it's contain on the parser input + stream. +*/ +int +sial_pushfile(char *name) +{ +struct stat s; +char *fname; + + if(nin==MAXIN) sial_pusherror(); + + fname=sial_fileipath(name); + + if(fname) { + + if(!stat(fname, &s)) { + + char *buf=sial_alloc(s.st_size+1); + int fd; + + if((fd=open(fname, O_RDONLY))==-1) { + + sial_msg("%s: %s", fname, strerror(errno)); + + } + else { + + if(read(fd, buf, s.st_size) != s.st_size) { + + if(errno != EISDIR) + sial_msg("%s: read error : %s", fname, strerror(errno)); + + } + else { + + + buf[s.st_size]='\0'; + sial_pushbuf(buf, fname, sial_free, buf, 0); + close(fd); + return 1; + + } + close(fd); + } + + sial_free(buf); + + } + sial_free(fname); + } + return 0; + +} + +/* + Done with the current buffer. + Go back to previous on the stack. +*/ +static int +sial_popin(void) +{ + + if(eol || !nin) { + + if(!nin) in=0; + return 1; + + } else { + + nin--; + + /* call back */ + if(inlist[nin].donefunc) { + + inlist[nin].donefunc(inlist[nin].data); + } + if(inlist[nin].eofonpop) { + + eol=1; +#if linux + inpp=0; +#endif + } + if(!nin) in=0; + else { + + in=&inlist[nin-1]; + if(!eol) { +#if linux + if(inpp) { + sialpp_switch_to_buffer(inlist[nin-1].yybuf); + sialpp_delete_buffer(inlist[nin].yybuf); + } else { + sial_switch_to_buffer(inlist[nin-1].yybuf); + sial_delete_buffer(inlist[nin].yybuf); + } +#endif + } + sial_curpos(&in->pos, 0); + } + return 0; + } +} + +/* + With linux we need to use the wrap function + so that the flex buffer stuff is keaped in the game. +*/ +int +sialwrap(void) +{ + return sial_popin(); +} + +int +sialppwrap(void) +{ + if(eol) return 1; + return sial_popin(); +} + +void +sial_popallin(void) +{ + while(nin) { + eol=0; + sial_popin(); + } +} + +#define BLK_IFDEF 1 +#define BLK_IFNDEF 2 +#define BLK_IF 3 +#define BLK_ELIF 4 +#define BLK_ELSE 5 + +typedef struct ifblk { + int type; /* type of block */ + int exprpos; /* curpor to start of corresponding expression */ + int bstart; /* curpor position at start of block */ + int dirlen; /* length of the directive name */ + int bend; /* cursor position at end of block */ + struct ifblk *next; +} ifblk_t; + +static int +sial_isif(int pos) +{ + if( + (in->len-pos>6 && !strncmp(in->buf+pos, "ifndef", 6)) + || (in->len-pos>5 && !strncmp(in->buf+pos, "ifdef", 5)) + || (in->len-pos>2 && !strncmp(in->buf+pos, "if", 2)) + + ) return 1; + + return 0; +} + +/* + Get directly to next block, skipping nested blocks. +*/ +static int +sial_nxtblk(int pos, int lev) +{ +int virgin=0; + + while(1) { + + if(pos==in->len) { + + sial_error("Block without endif"); + } + + if(virgin && in->buf[pos]=='#') { + + pos++; + + /* nested if ? */ + if(in->buf[pos]=='i' && sial_isif(pos)) { + + while(1) { + pos=sial_nxtblk(pos, lev+1); + if(in->len-pos>5 && !strncmp(in->buf+pos, "endif", 5)) break; + } + + } else if(in->buf[pos]=='e') return pos; + + } else if(in->buf[pos]=='\n') { + + virgin=1; + + } else if(in->buf[pos] != ' ' && in->buf[pos] != '\t') { + + virgin=0; + } + pos++; + } +} + +static ifblk_t * +sial_getblklst(void) +{ +ifblk_t *lst, *last; +int doneelse=0, pos; + + lst=sial_alloc(sizeof(ifblk_t)); + + lst->bstart=in->cursor-1; + if(!strncmp(in->buf+in->cursor, "ifdef", 5)) { + + lst->type=BLK_IFDEF; + lst->exprpos=lst->bstart+6; + lst->dirlen=6; + + } else if(!strncmp(in->buf+in->cursor, "ifndef", 6)){ + + lst->type=BLK_IFNDEF; + lst->exprpos=lst->bstart+7; + lst->dirlen=7; + + } else { + + lst->type=BLK_IF; + lst->exprpos=lst->bstart+3; + lst->dirlen=3; + } + + last=lst; + pos=in->cursor; + + while(1) { + + ifblk_t *new=sial_alloc(sizeof(ifblk_t)); + + pos=sial_nxtblk(pos, 0); + + last->bend=pos-2; + new->bstart=pos-1; + if(!strncmp(in->buf+pos, "elif", 4)) { + + if(doneelse) { + + sial_error("Additional block found after #else directive"); + } + new->type=BLK_ELIF; + new->exprpos=new->bstart+5; + new->dirlen=5; + + } else if(!strncmp(in->buf+pos, "else", 4)) { + + if(doneelse) { + + sial_error("#else already done"); + } + new->type=BLK_ELSE; + new->exprpos=new->bstart+5; + new->dirlen=5; + doneelse=1; + + } else if(!strncmp(in->buf+pos, "endif", 5)) { + + sial_free(new); + last->next=0; + break; + } + last->next=new; + last=new; + } + return lst; +} + +/* + Zap a complete block. + We put spaces everywhere but over the newline. + Hey, it works. It's good enough for me. +*/ +static void +sial_zapblk(ifblk_t *blk) +{ +int i; + + for(i=blk->bstart;ibend;i++) { + + if(in->buf[i]!='\n') in->buf[i]=' '; + } +} + +int sial_eol(char c) { return (!c || c=='\n') ? 1 : 0; } + +/* + This function is called by sial_input() when a #if[def] is found. + We gather all blocks of the if/then/else into a list. + Parsing and execution of the expression is done only when needed. +*/ +void sial_rsteofoneol(void) +{ + eol=0; + virgin=1; +#if linux + inpp=0; +#endif +} + +void +sial_zapif(void) +{ +ifblk_t *lst=sial_getblklst(); +ifblk_t *last=lst; +int b=0; + + /* we scan the entire list untill a condition is true or we + reach #else or we reach the end */ + while(lst) { + + switch(lst->type) { + + case BLK_IFDEF: + case BLK_IFNDEF: + { + char mname[MAX_SYMNAMELEN+1], c; + int i=0, j=lst->bstart+lst->dirlen; + int v; + + /* get the macro name and see if it exists */ + /* skip all white spaces */ + while((c=in->buf[j]) == ' ' || c == '\t') if(c=='\n' || !c) { + + sial_error("Macro name not found!"); + + } else j++; + + /* get the constant or macro name */ + while((c=in->buf[j]) != ' ' && c != '\t' && c != '(') { + + if(c=='\n' || !c) break; + + if(i==MAX_SYMNAMELEN) break; + + mname[i++]=c; + j++; + } + mname[i]='\0'; + lst->dirlen += (j-lst->bstart-lst->dirlen); + if(sial_getmac(mname,0)) v=1; + else v=0; + b=lst->type==BLK_IFDEF?v:!v; + + } + break; + + case BLK_IF: case BLK_ELIF: + { + node_t*n; + void sialpprestart(int); + void sialppparse(void); + char *expr=sial_getline(); + int len=lst->dirlen; + +#if linux + sialpprestart(0); + inpp=1; +#endif + lst->dirlen += (in->cursor-lst->exprpos-1); + sial_pushbuf(expr, 0, sial_free, expr, 0); + in->eofonpop=1; + in->cursor += len; + sialppparse(); + + sial_rsteofoneol(); + eol=0; + + /* get the resulting node_t*/ + n=sial_getppnode(); + + /* execute it */ + { + + int *exval; + jmp_buf exitjmp; + void *sa; + value_t *v; + + sa=sial_setexcept(); + + if(!setjmp(exitjmp)) { + + sial_pushjmp(J_EXIT, &exitjmp, &exval); + v=NODE_EXE(n); + sial_rmexcept(sa); + sial_popjmp(J_EXIT); + b=sial_bool(v); + sial_freeval(v); + + } else { + + sial_rmexcept(sa); + sial_parseback(); + } + } + } + break; + + case BLK_ELSE: + { + + b=1; + + } + break; + } + + last=lst; + if(b) break; + + /* count new lines */ + { + while(in->cursor < lst->bend+1) { + + if(sial_eol(in->buf[in->cursor])) + sial_line(1); + in->cursor++; + } + + } + lst=lst->next; + } + + if(lst) { + + /* remove the # directive itself */ + memset(in->buf+lst->bstart, ' ', lst->dirlen); + + /* zap all remaining blocks */ + while((lst=lst->next)) { sial_zapblk(lst); last=lst; } + } + + /* most remove the #endif */ + memset(in->buf+last->bend+1, ' ', 6); +} + +static int rawinput=0; +void sial_rawinput(int on) { rawinput=on; } + +/* + Get the next character from the input stream tack. +*/ +int +sial_input(void) +{ +register char c; + +redo: + + if(!in || eol) { + + return 0; + } + + if(in->cursor==in->len) { + +#if linux + return (-1); +#else + sial_popin(); + goto redo; +#endif + } + + c=in->buf[in->cursor++]; + if(!rawinput) { + if(c=='\\') { + + if(in->cursor==in->len) return c; + else if(in->buf[in->cursor]=='\n') { + + sial_line(1); + in->cursor++; + goto redo; + } + + } else if(c=='/') { + + if(in->cursor==in->len) return c; + else if(in->buf[in->cursor]=='/') { + + /* C++ stype comment. Eat it. */ + in->cursor++; + while(in->cursorlen) { + + c=in->buf[in->cursor++]; + if(c=='\n') { + /* leave the newline in there */ + in->cursor--; + break; + } + } + goto redo; + + }else if(in->buf[in->cursor]=='*') { + + /* C style comment, eat it */ + in->cursor++; + while(in->cursorlen) { + + c=in->buf[in->cursor++]; + if(c=='*' && (in->cursorlen)) { + + if(in->buf[in->cursor]=='/') { + + in->cursor++; + break; + + } + + } else if(c=='/' && (in->cursorlen)) { + + if(in->buf[in->cursor]=='*') { + + sial_warning("Nested comment"); + + } + + } + if(c=='\n') sial_line(1); + } + goto redo; + } + + }else if(virgin && c=='#') { + + char *p=in->buf+in->cursor; + char *end=in->buf+in->len; + int c=0; + + /* skip white spaces '# define ... ' */ + while(p<(end-4) && (*p==' ' || *p=='\t')) { p++; c++; } + + /* this must be a preprocessor command */ + /* we trigger on the if, ifdef only. #define, #undef, #include are + handled by the lexer */ + + if(!strncmp(p, "if", 2)) { + + in->cursor += c; + sial_zapif(); + /* zapif sets the cursor correctly */ + goto redo; + } + } + } + + if(c=='\n') { + + virgin=1; + sial_line(1); + + }else if(c != ' ' && c != '\t') { + + virgin=0; + + } + else if(!rawinput){ + + register char c2=c; + + /* return one white space for a group of them */ + while((in->cursor < in->len) + && in->buf[in->cursor]==c2) in->cursor++; + + } + + return c; +} + +char * +sial_cursorp() +{ + if(!in) return 0; + return in->buf+in->cursor; +} + +void +sial_unput(char c) +{ + + if(!c) return; + if(!nin) return; + if(!in->cursor) { + + sial_error("Fatal unput error"); + + } + in->buf[--in->cursor]=c; + if(c=='\n') { + + sial_line(-1); + } +} + +/* + Get a single line from the parser stream. +*/ +char * +sial_getline() +{ +char *buf2=0; + + /* use the current input stream for that */ + if(in) { + + /* save the cursor */ + int n=0, c; + char *buf=sial_alloc(in->len-in->cursor+1); + + while(!sial_eol(c=sial_input())) + buf[n++]=c; + buf[n]='\0'; + buf2=sial_alloc(n+2); + strcpy(buf2,buf); + buf2[n]=' '; + buf2[n+1]='\0'; + sial_free(buf); + /* leave the newline there */ + sial_unput(c); + } + return buf2; +} + + +/* read a complete line from the input stream */ +void +sial_include(void) +{ +char name[MAX_SYMNAMELEN+1]; +int n=0; +int c; +int found=0; + + while((c=sial_input())) { + + if(c=='"') { + + if(!found) found++; + else break; + continue; + } + + if(c=='<') { + + found++; + continue; + + } + if(c=='>') break; + if(sial_eol(c)) { + + sial_error("Unexpected EOL on #include"); + } + if(found) { + + if(n==MAX_SYMNAMELEN) { + + sial_error("Filename too long"); + } + name[n++]=c; + + } + } + name[n]='\0'; + + /* flush the rest of the line */ + while((c=sial_input())) { + + if(sial_eol(c)) break; + } + sial_unput(c); + if(sial_fileipath(name)) { + + sial_pushfile(name); + + } else { + + sial_error("Include file not found: %s", name); + } +} --- crash-4.0-4.6/extensions/libsial/sial.l 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial.l 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,193 @@ +%{ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +%} + +%{ +#include + +#ifdef linux +#define YY_INPUT(buf,result,max_size) \ +{ \ + int c = sial_input(); \ + result = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \ +} +#endif + +#define yylval siallval +#include "sial.h" +#define YY_NO_UNPUT +#include "sial.tab.h" + +#define retok(t) return(t) +int needvar=0, instruct=0; +static char *lastvar=0; +char *sial_lastvar(void) { return lastvar; } +extern void sial_skip_directive(void); +extern void sial_define(void); +extern void sial_include(void); +extern void sial_undefine(void); +extern char sial_newchar(void); +extern int sial_chkmacvar(char *); +%} + +ABC [a-zA-Z_] +ABCN [a-zA-Z0-9_] +N [0-9] +X [0-9a-fA-F] +W [ \t\n] +P #[ \t]* + +%% + +{W} { ; } + +"..." { retok(VARARGS); } +"&&" { retok(BAND); } +"||" { retok(BOR); } +"<" { retok(LT); } +"<=" { retok(LE); } +"==" { retok(EQ); } +">=" { retok(GE); } +">" { retok(GT); } +"!=" { retok(NE); } + +"&=" { retok(ANDME); } +"|" { retok(OR); } +"|=" { retok(ORME); } +"!" { retok(NOT); } +"^" { retok(XOR); } +"&" { retok(AND); } +"^=" { retok(XORME); } +">>" { retok(SHR); } +"<<=" { retok(SHLME); } +">>=" { retok(SHRME); } +"<<" { retok(SHL); } +"++" { retok(INCR); } +"+" { retok(ADD); } +"--" { retok(DECR); } +"-" { retok(SUB); } +"+=" { retok(ADDME); } +"-=" { retok(SUBME); } +"*=" { retok(MULME); } +"/=" { retok(DIVME); } +"/" { retok(DIV); } +"%=" { retok(MODME); } +"%" { retok(MOD); } +"=" { retok(ASSIGN); } +"->" { retok(INDIRECT); } +"." { retok(DIRECT); } +"{" { needvar=0; retok('{'); } + +\*+ { + yylval.i=strlen(yytext); + return PTR; + } + +(("0x"+){X}+[lL]*|{N}+[lL]*) { yylval.n = sial_newnum(yytext); retok(NUMBER); } + +{P}ident { sial_skip_directive(); } +{P}pragma { sial_skip_directive(); } +{P}define { + /* preprocessor command */ + /* either a simple constant or a macro */ + sial_define(); + } +{P}include { + + /* file inclusion */ + sial_include(); + } +{P}undef { + sial_undefine(); + } +while { retok(WHILE); } +for { retok(FOR); } +do { retok(DO); } +if { retok(IF); } +else { retok(ELSE); } +break { retok(BREAK); } +continue { retok(CONTINUE); } +in { retok(IN); } +return { retok(RETURN); } + +__char__ { retok(yylval.i=CHAR); } +__short__ { retok(yylval.i=SHORT); } +__int__ { retok(yylval.i=INT); } +__float__ { retok(yylval.i=FLOAT); } +__double__ { retok(yylval.i=DOUBLE); } +__register__ { retok(yylval.i=REGISTER); } +__volatile__ { retok(yylval.i=VOLATILE); } +__void__ { retok(yylval.i=VOID); } +__unsigned__ { retok(yylval.i=UNSIGNED); } +__signed__ { retok(yylval.i=SIGNED); } +__long__ { retok(yylval.i=LONG); } +__const__ { retok(yylval.i=CONST); } +__static__ { retok(yylval.i=STATIC); } +__extern__ { retok(yylval.i=EXTERN); } + +char { retok(yylval.i=CHAR); } +short { retok(yylval.i=SHORT); } +int { retok(yylval.i=INT); } +float { retok(yylval.i=FLOAT); } +double { retok(yylval.i=DOUBLE); } +register { retok(yylval.i=REGISTER); } +volatile { retok(yylval.i=VOLATILE); } +void { retok(yylval.i=VOID); } +unsigned { retok(yylval.i=UNSIGNED); } +signed { retok(yylval.i=SIGNED); } +long { retok(yylval.i=LONG); } +const { retok(yylval.i=CONST); } +static { retok(yylval.i=STATIC); } +extern { retok(yylval.i=EXTERN); } + +string { retok(yylval.i=STRTYPE); } +__inline { ; } +switch { retok(SWITCH); } +case { retok(CASE); } +default { retok(DEFAULT); } +enum { retok(yylval.i=ENUM); } +union { retok(yylval.i=UNION);} +struct { retok(yylval.i=STRUCT); } +typedef { retok(yylval.i=TDEF); } +sizeof { retok(SIZEOF); } +print { retok(PRINT); } +printo { retok(PRINTO); } +printd { retok(PRINTD); } +printx { retok(PRINTX); } +take_array { retok(TAKE_ARR); } + + +{ABC}{ABCN}* { + if((!needvar) && (yylval.t=sial_getctype(V_TYPEDEF, yytext, 1))) + { + /* hack to remember last tdef name */ + if(lastvar) sial_free(lastvar); + lastvar=sial_alloc(strlen(yytext)+1); + strcpy(lastvar, yytext); + needvar++; + retok(TYPEDEF); + } + needvar=0; + if(strlen(yytext) > MAX_SYMNAMELEN) { + + sial_error("Symbol name too long"); + } + if(!sial_chkmacvar(yytext)) { + yylval.n = sial_newvnode(yytext); + retok(VAR); + } + } + +\" { yylval.n = sial_newstr(); retok(STRING); } +\'.\' { yylval.n = sial_makenum(B_SC, yytext[1]); retok(NUMBER); } +\'\\.\' { yylval.n = sial_makenum(B_SC, sial_getseq(yytext[2])); retok(NUMBER); } + +. { retok(yylval.i = yytext[0]); } + +%% +#undef input +#undef unput +#define input() sial_input() +#define unput(c) sial_unput(c) --- crash-4.0-4.6/extensions/libsial/sial-lsed 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial-lsed 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,32 @@ +s/yyback/sialback/g +s/yybgin/sialbgin/g +s/yycrank/sialcrank/g +s/yyerror/sialerror/g +s/yyestate/sialestate/g +s/yyextra/sialextra/g +s/yyfnd/sialfnd/g +s/yyin/sialin/g +s/yyinput/sialinput/g +s/yyleng/sialleng/g +s/yylex/siallex/g +s/yylineno/siallineno/g +s/yylook/siallook/g +s/yylsp/siallsp/g +s/yylstate/siallstate/g +s/yylval/siallval/g +s/yymatch/sialmatch/g +s/yymorfg/sialmorfg/g +s/yyolsp/sialolsp/g +s/yyout/sialout/g +s/yyoutput/sialoutput/g +s/yyprevious/sialprevious/g +s/yysbuf/sialsbuf/g +s/yysptr/sialsptr/g +s/yysvec/sialsvec/g +s/yytchar/sialtchar/g +s/yytext/sialtext/g +s/yytop/sialtop/g +s/yyunput/sialunput/g +s/yyvstop/sialvstop/g +s/yywrap/sialwrap/g +s/yydebug/sialdebug/g --- crash-4.0-4.6/extensions/libsial/sial_member.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_member.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,321 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include +#include "sial.h" +#include "sial.tab.h" + +/* these function are used to access and set members in structs */ + +/* define a member access */ +typedef struct mem { + char *name; /* member name */ + int dir; /* direct/indirect access */ + node_t*expr; /* expression node_t*/ + stmember_t*stm; /* associated member information */ + char *local; /* local memory or ... */ + ull mem; /* ... system memory access */ + srcpos_t p; +} mem; + +void * +sial_adrval(value_t *v) +{ + switch(v->type.size) { + + case 1: return &v->v.uc; + case 2: return &v->v.us; + case 4: return &v->v.ul; + case 8: return &v->v.ull; + } + sial_error("Oops sial_adrval"); + return 0; +} + +/* some API secondary entry points */ +void sial_member_soffset(member_t*m, int offset) { m->offset=offset; } +void sial_member_ssize(member_t*m, int size) { m->size=size; } +void sial_member_sfbit(member_t*m, int fbit) { m->fbit=fbit; } +void sial_member_snbits(member_t*m, int nbits) { m->nbits=nbits; } +void sial_member_sname(member_t*m, char *name) { m->name=sial_strdup(name); } + + +void +sial_setmem(mem *m, value_t *v) +{ +stmember_t*stm=m->stm; + + /* check type compatibility. Ctypes should point to the same stinfo...*/ + if(stm->type.type != v->type.type + /* pointer most point to the same type of object */ + || (v->type.type==V_REF && v->type.rtype != stm->type.rtype) + /* ctypes should point to the same stinfo */ + || (is_ctype(v->type.type) && v->type.idx != stm->type.idx)) { + + sial_error("Incompatible types for assignment"); + + } + + if(stm->m.nbits) { + + ull dvalue_t=0; + + if(v->type.type!=V_BASE) { + + sial_error("Invalid assignment to bit field"); + + } + + /* do the bit gymnastic */ + /* we need to create a ull that contain the current + bit of teh destination */ + if(m->local) { + + memmove(m->local+stm->m.offset, ((char*)(&dvalue_t))+8-stm->m.size, stm->m.size); + dvalue_t=set_bit_value_t(dvalue_t, v->v.ull, stm->m.nbits, stm->m.fbit); + memmove(((char*)(&dvalue_t))+8-stm->m.size, m->local+stm->m.offset, stm->m.size); + + } + + if(m->mem) { + + API_GETMEM(m->mem+stm->m.offset, ((char*)(&dvalue_t))+8-stm->m.size, stm->m.size); + dvalue_t=set_bit_value_t(dvalue_t, v->v.ull, stm->m.nbits, stm->m.fbit); + API_PUTMEM(m->mem+stm->m.offset, ((char*)(&dvalue_t))+8-stm->m.size, stm->m.size); + + } + + + } else { + + /* move the data */ + if(is_ctype(v->type.type)) { + + if(m->local) { + + memmove(m->local+stm->m.offset, v->v.data, stm->m.size); + + } + if(m->mem) { + + API_PUTMEM(m->mem+stm->m.offset, v->v.data, stm->m.size); + } + + } else { + + sial_transval(v->type.size, stm->m.size, v, sial_issigned(v->type.typattr)); + + if(m->local) { + + memmove(m->local+stm->m.offset, sial_adrval(v), stm->m.size); + + } + + if(m->mem) { + + API_PUTMEM(m->mem+stm->m.offset, sial_adrval(v), stm->m.size); + } + } + } +} + +#define vdata(p, t) ((t*)(p->v.data)) + +void +sial_exememlocal(value_t *vp, stmember_t* stm, value_t *v) +{ + /* expression should be a ctype_t*/ + if(!is_ctype(vp->type.type)) { + + sial_error("Invalid type for '.' expression"); + } + /* get that value_t from the application memory */ + if(is_ctype(stm->type.type) && !stm->type.idxlst) { + + void *data=sial_alloc(stm->m.size); + + memmove(data, vdata(vp, char)+stm->m.offset, stm->m.size); + if(vp->mem) v->mem=vp->mem+stm->m.offset; + v->v.data=data; + + } + /* bit field gymnastic */ + else if(stm->m.nbits) { + + ull value=0; + + memmove(vdata(vp, char)+stm->m.offset, ((char*)&value)+(sizeof(value)-stm->m.size), stm->m.size); + get_bit_value(value, stm->m.nbits, stm->m.fbit, stm->m.size, v); + + } + /* check if this is an array, if so then create a reference to it */ + else if(stm->type.idxlst) { + + ull mempos=vp->mem+stm->m.offset; + if(sial_defbsize()==8) v->v.ull=mempos; + else v->v.ul=mempos; + v->mem=mempos; + + } else { + + switch(TYPE_SIZE(&stm->type)) { + case 1: + memmove(&v->v.uc, vdata(vp, char)+stm->m.offset, 1); + break; + case 2: + memmove(&v->v.us, vdata(vp, char)+stm->m.offset, 2); + break; + case 4: + memmove(&v->v.ul, vdata(vp, char)+stm->m.offset, 4); + break; + case 8: + memmove(&v->v.ull, vdata(vp, char)+stm->m.offset, 8); + break; + default: + sial_error("Oops exemem2[%d]", TYPE_SIZE(&stm->type)); + break; + } + if(vp->mem) v->mem=vp->mem+stm->m.offset; + } +} + +value_t * +sial_exemem(mem *m) +{ +value_t *v=sial_newval(); +value_t *vp=NODE_EXE(m->expr); +stmember_t*stm; +srcpos_t p; + + sial_curpos(&m->p, &p); + + if(vp->type.type == V_REF) { + + if(vp->type.ref > 1) { + + sial_error("Too many levels of indirection for access to [%s]", m->name); + + } + } + + /* get the member information and attach it */ + stm=m->stm=(stmember_t*)sial_member(m->name, &vp->type); + if(!stm) { + + sial_freeval(v); + sial_freeval(vp); + sial_error("Invalid member name specified : %s", m->name); + + } + + /* get a copy of the type of thise member and put it in v */ + sial_duptype(&v->type, &stm->type); + + /* indirect i.e. (struct*)->member *most* be relative to the + system image. This is a restriction of this language */ + if(m->dir==INDIRECT) { + + ull mempos; + + if(vp->type.type != V_REF || !is_ctype(vp->type.rtype)) { + + sial_error("Invalid type for '->' expression"); + } + + m->local=0; + m->mem=sial_defbsize()==8?vp->v.ull:vp->v.ul; + mempos=m->mem+stm->m.offset; + + /* get that value_t from the system image */ + if(is_ctype(v->type.type) && !stm->type.idxlst) { + + v->v.data=sial_alloc(stm->m.size); + API_GETMEM(mempos, v->v.data, stm->m.size); + v->mem=mempos; + + } + /* bit field gymnastic */ + else if(stm->m.nbits) { + + ull value=0; + + API_GETMEM(m->mem+stm->m.offset, &value, stm->m.size); + get_bit_value(value, stm->m.nbits, stm->m.fbit, stm->m.size, v); + /* no mempos for bit fields ... */ + + } + /* check if this is an array, if so then create a reference to it */ + else if(stm->type.idxlst) { + + if(sial_defbsize()==8) v->v.ull=mempos; + else v->v.ul=mempos; + v->mem=mempos; + + } else { + + v->mem=mempos; + + switch(TYPE_SIZE(&stm->type)) { + case 1: + API_GETMEM(mempos, &v->v.uc, 1); + break; + case 2: + API_GETMEM(mempos, &v->v.us, 2); + break; + case 4: + API_GETMEM(mempos, &v->v.ul, 4); + break; + case 8: + API_GETMEM(mempos, &v->v.ull, 8); + break; + default: + sial_error("Oops exemem[%d]", TYPE_SIZE(&stm->type)); + break; + } + + } + } + /* direct i.e. (struct).member *most* be in referance to a local + structure. */ + else { + + m->mem=vp->mem; + m->local=vp->v.data; + + /* extract the value from a local copy */ + sial_exememlocal(vp, stm, v); + } + sial_curpos(&p, 0); + sial_freeval(vp); + v->setfct=(setfct_t)sial_setmem; + v->setval=(value_t*)m; + v->set=1; + return v; +} + +void +sial_freemem(mem *m) +{ + NODE_FREE(m->expr); + sial_free(m->name); + sial_free(m); +} + +node_t* +sial_newmem(int dir, node_t*expr, node_t*name) +{ +char *nstr=NODE_NAME(name); +node_t*n=sial_newnode(); +mem *m=sial_alloc(sizeof(mem)); + + /* dicard nam node_t*/ + NODE_FREE(name); + m->name=nstr; + m->dir=dir; + m->expr=expr; + sial_setpos(&m->p); + n->data=m; + n->exe=(xfct_t)sial_exemem; + n->free=(ffct_t)sial_freemem; + return n; +} --- crash-4.0-4.6/extensions/libsial/sial_node.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_node.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,69 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +/* + These function are use to allocate a new node. + It's a layer between the type specific functions and the parser. +*/ +#include "sial.h" +#include + +/* + Allocate a new node structure +*/ +node_t* +sial_newnode() +{ +node_t*n; + + n = (node_t*) sial_calloc(sizeof(node_t)); + TAG(n); + return n; +} + +void +sial_free_siblings(node_t*ni) +{ + while(ni) { + + node_t*next=ni->next; + + NODE_FREE(ni); + + ni=next; + } +} + +/* + This function is called du ring compile time + to exevaluate constant expression, like sizeof() and + array sizes and enum constant. +*/ +value_t * +sial_exenode(node_t*n) +{ +value_t *v; +int *exval; +jmp_buf exitjmp; +void *sa; +srcpos_t p; + + sial_curpos(&n->pos, &p); + sa=sial_setexcept(); + + if(!setjmp(exitjmp)) { + + sial_pushjmp(J_EXIT, &exitjmp, &exval); + v=NODE_EXE(n); + sial_rmexcept(sa); + sial_popjmp(J_EXIT); + + } else { + + sial_rmexcept(sa); + return 0; + + } + sial_curpos(&p, 0); + return v; +} --- crash-4.0-4.6/extensions/libsial/sial_num.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_num.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,233 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include +#include +#include "sial.h" + +typedef struct { + int type; + ull val; +} num; + +/* + Numeric constants. +*/ + +static value_t* +sial_exenum(num *n) +{ +value_t *v=sial_newval(); + + v->type.type=V_BASE; + v->type.idx=n->type; + if(n->type==B_SLL) { + +ll: + v->v.sll=n->val; + v->type.size=8; + + }else if(n->type==B_SC) { + + v->v.sc=n->val; + v->type.size=1; + + } else { + + if(sial_defbsize()==4) { + + v->v.sl=n->val; + v->type.size=4; + + } else { + + v->type.idx=B_SLL; + goto ll; + } + } + v->type.typattr=sial_idxtoattr(v->type.idx); + v->set=0; + return v; +} + +void +sial_freenumnode(num *n) +{ + sial_free(n); +} + +node_t* +sial_makenum(int type, ull val) +{ +node_t*n=sial_newnode(); +num *nu=sial_alloc(sizeof(num)); + + TAG(nu); + + nu->type=type; + nu->val=val; + n->exe=(xfct_t)sial_exenum; + n->free=(ffct_t)sial_freenumnode; + n->data=nu; + + sial_setpos(&n->pos); + return n; +} + +/* + Execution of the sizeof() operator. + This sould be done at compile time, but I have not setup + a 'type only' execution path for the nodes. + Runtime is good enough to cover mos cases. +*/ +#define SN_TYPE 1 +#define SN_EXPR 2 + +typedef struct { + int type; + void *p; + srcpos_t pos; +} snode_t; + +static value_t * +sial_exesnode(snode_t*sn) +{ +srcpos_t pos; +type_t*t; +value_t *v=sial_newval(); +value_t *v2=0; +int size; + + sial_curpos(&sn->pos, &pos); + if(sn->type == SN_TYPE) { + + t=(type_t*)(sn->p); + + } else { + + sial_setinsizeof(1); + v2=NODE_EXE((node_t*)(sn->p)); + t=&v2->type; + sial_setinsizeof(0); + } + + switch(t->type) { + + case V_REF: + + if(t->idxlst) { + + int i; + for(size=t->size,i=0;t->idxlst[i];i++) size *= t->idxlst[i]; + + } else size=sial_defbsize(); + + break; + case V_STRUCT: case V_UNION: + + if(sial_ispartial(t)) { + + sial_error("Invalid type specified"); + } + size=t->size; + + break; + case V_BASE: case V_STRING: + size=t->size; + break; + + default: size=0; + } + + sial_defbtype(v, (ull)size); + + sial_curpos(&pos, 0); + + if(v2) sial_freeval(v2); + + return v; + +} + +static void +sial_freesnode(snode_t*sn) +{ + if(sn->type == SN_TYPE) sial_free(sn->p); + else NODE_FREE(sn->p); + sial_free(sn); +} + +node_t* +sial_sizeof(void *p, int type) +{ +node_t*n=sial_newnode(); +snode_t*sn=sial_alloc(sizeof(snode_t)); + + n->exe=(xfct_t)sial_exesnode; + n->free=(ffct_t)sial_freesnode; + n->data=sn; + sn->type=type; + sn->p=p; + sial_setpos(&sn->pos); + return n; +} + +node_t* +sial_newnum(char *buf) +{ +int type; +unsigned long long val; + + type=B_SL; + + /* get the value_t of this constant. Could be hex, octal or dec. */ + if(buf[0]=='0') { + + if(buf[1]=='x') { + + if(!sscanf(buf, "%llx", &val)) goto error; + + } else { + + if(!sscanf(buf,"%llo", &val)) goto error; + } + + } else { + + if(!sscanf(buf,"%lld", &val)) goto error; + + } + + if(val & 0xffffffff00000000ll) type=B_SLL; + + /* threat the long and long long atributes */ + { + int l=strlen(buf); + + if(l>1) { + + if(buf[l-1]=='l' || buf[l-1]=='L') { + + if(l>2) { + + if(sial_defbsize()==8 || buf[l-2]=='l' || buf[l-2]=='L') { + + type=B_SLL; + + } + else type=B_SL; + + } + + } + } + } + { + node_t*n=sial_makenum(type, val); + TAG(n->data); + return n; + } +error: + sial_error("Oops! NUMBER"); + return 0; +} --- crash-4.0-4.6/extensions/libsial/sial_op.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_op.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,881 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include "sial.h" +#include "sial.tab.h" +#include +#include + +#define MAXPARMS 10 + +typedef struct { + + int op; /* operator */ + int np; /* number of operands */ + node_t*parms[MAXPARMS]; /* operands */ + + srcpos_t pos; + +} oper; + +#define P1 (o->parms[0]) +#define P2 (o->parms[1]) +#define P3 (o->parms[2]) +#define P4 (o->parms[3]) + +#define V1 (v1?v1:(v1=NODE_EXE(P1))) +#define V2 (v2?v2:(v2=NODE_EXE(P2))) +#define V3 (v3?v3:(v3=NODE_EXE(P3))) +#define V4 (v4?v4:(v4=NODE_EXE(P4))) + +#define L1 (unival(v1?v1:V1)) +#define L2 (unival(v2?v2:V2)) +#define L3 (unival(v3?v3:V3)) +#define L4 (unival(v4?v4:V4)) + +#define S1 ((v1?v1:V1)->v.data) +#define S2 ((v2?v2:V2)->v.data) +#define S3 ((v3?v3:V3)->v.data) +#define S4 ((v4?v4:V4)->v.data) + +void sial_do_deref(int n, value_t *v, value_t *ref); +ul +sial_bool(value_t *v) +{ + switch(v->type.type) { + + case V_BASE: + switch(v->type.size) { + case 1: return !(!(v->v.uc)); + case 2: return !(!(v->v.us)); + case 4: return !(!(v->v.ul)); + case 8: return !(!(v->v.ull)); + default: sial_error("Oops sial_bool()[%d]", v->type.size); break; + } + case V_STRING : return !(!(*((char*)(v->v.data)))); + case V_REF: return sial_defbsize()==8?(!(!(v->v.ull))):(!(!(v->v.ul))); + default : + + sial_error("Invalid operand for boolean expression"); + return 0; + } +} + +static int cops[]={BAND,BOR,NOT,LT,LE,EQ,GE,GT,NE,CEXPR}; +#define NCOPS (sizeof(cops)/sizeof(cops[0])) + +static int +is_cond(int op) +{ +int i; + + for(i=0;itype)) { + + case 1: v1->v.uc=rl; break; + case 2: v1->v.us=rl; break; + case 4: v1->v.ul=rl; break; + case 8: v1->v.ull=rl; break; + + } + /* the result of an assignment cannot be a lvalue_t */ + v1->set=0; +} + +#define anyop(t) (V1->type.type==t || (o->np>1 && V2->type.type==t)) + +typedef struct { + node_t*index; + node_t*var; + srcpos_t pos; +} index_t ; + +static value_t * +sial_exeindex(index_t *i) +{ +value_t *var; +value_t *vi=NODE_EXE(i->index); +value_t *v; +srcpos_t p; + + sial_curpos(&i->pos, &p); + + /* we need to make believe it's been initiazed */ + sial_setini(i->var); + var=NODE_EXE(i->var); + + /* check the type of the variable */ + /* if it's a pointer then index through the image */ + if(var->type.type==V_REF) { + + int size; + int n=sial_getval(vi); + value_t *ref; + + /* if this is an array and we're not at the rightmost index */ + if(var->type.idxlst && var->type.idxlst[1]) { + + int i, size=var->type.size; + + v=sial_cloneval(var); + + v->type.idxlst[0]=0; + for(i=1; var->type.idxlst[i]; i++) { + + size *= var->type.idxlst[i]; + v->type.idxlst[i]=var->type.idxlst[i+1]; + } + + if(sial_defbsize()==4) { + + v->v.ul+=size*n; + v->mem=v->v.ul; + + } else { + + v->v.ull+=size*n; + v->mem=v->v.ull; + } + + + } else { + + v=sial_newval(); + ref=sial_cloneval(var); + + if(var->type.ref==1) size=var->type.size; + else size=sial_defbsize(); + + if(sial_defbsize()==4) { + + ref->v.ul+=size*n; + ref->mem=ref->v.ul; + + } else { + + ref->v.ull+=size*n; + ref->mem=ref->v.ull; + } + sial_do_deref(1, v, ref); + sial_freeval(ref); + } + + } else { + + v=sial_newval(); + + /* use dynamic indexing aka awk indexing */ + sial_valindex(var, vi, v); + } + + /* discard expression results */ + sial_freeval(var); + sial_freeval(vi); + sial_curpos(&p, 0); + + return v; +} + +void +sial_freeindex(index_t *i) +{ + NODE_FREE(i->index); + NODE_FREE(i->var); + sial_free(i); +} + +node_t* +sial_newindex(node_t*var, node_t*idx) +{ +index_t *i=sial_alloc(sizeof(index_t )); +node_t*n=sial_newnode(); + + i->index=idx; + i->var=var; + n->exe=(xfct_t)sial_exeindex; + n->free=(ffct_t)sial_freeindex; + n->data=i; + sial_setpos(&i->pos); + return n; +} + +typedef struct { + node_t*fname; + node_t*parms; + srcpos_t pos; + void *file; +} call; + +static value_t * +sial_execall(call *c) +{ +value_t *rv; +srcpos_t p; + + sial_curpos(&c->pos, &p); + rv=sial_docall(c->fname, c->parms, c->file); + sial_curpos(&p, 0); + return rv; +} + +void +sial_freecall(call *c) +{ + NODE_FREE(c->fname); + sial_free_siblings(c->parms); + sial_free(c); +} + +node_t* +sial_newcall(node_t* fname, node_t* parms) +{ +node_t*n=sial_newnode(); +call *c=sial_alloc(sizeof(call)); + + c->fname=fname; + c->file=sial_getcurfile(); + c->parms=parms; + n->exe=(xfct_t)sial_execall; + n->free=(ffct_t)sial_freecall; + n->data=c; + sial_setpos(&c->pos); + return n; +} + +typedef struct { + node_t*expr; + srcpos_t pos; +} adrof; + +static value_t * +sial_exeadrof(adrof *a) +{ +value_t *rv, *v=NODE_EXE(a->expr); + +#if 0 + /* we can only do this op on something that came from system image + Must not allow creation of references to local variable */ + if(!v->mem) { + + sial_freeval(v); + sial_rerror(&a->pos, "Invalid operand to '&' operator"); + + } +#endif + /* create the reference */ + rv=sial_newval(); + sial_duptype(&rv->type, &v->type); + sial_pushref(&rv->type, 1); + + /* remmember position in image */ + if(sial_defbsize()==8) rv->v.ull=v->mem; + else rv->v.ul=v->mem; + rv->mem=0; + + sial_freeval(v); + + return rv; +} + +void +sial_freeadrof(adrof *a) +{ + NODE_FREE(a->expr); + sial_free(a); +} + +node_t* +sial_newadrof(node_t* expr) +{ +node_t*n=sial_newnode(); +adrof *a=sial_alloc(sizeof(adrof)); + + a->expr=expr; + n->exe=(xfct_t)sial_exeadrof; + n->free=(ffct_t)sial_freeadrof; + n->data=a; + sial_setpos(&a->pos); + return n; +} + +static int +sial_reftobase(value_t *v) +{ +int idx= v->type.idx; + + if(v->type.type==V_REF) { + + if(sial_defbsize()==4) + v->type.idx=B_UL; + else + v->type.idx=B_ULL; + } + return idx; +} + +static value_t* +sial_docomp(int op, value_t *v1, value_t *v2) +{ + + /* if one parameter is string then both must be */ + if(v1->type.type == V_STRING || v2->type.type == V_STRING) { + + if(v1->type.type != V_STRING || v2->type.type != V_STRING) { + + sial_error("Invalid condition arguments"); + } + else { + + switch(op) { + + case EQ: { /* expr == expr */ + + return sial_makebtype(!strcmp(v1->v.data, v2->v.data)); + + } + case GT: case GE: { /* expr > expr */ + + return sial_makebtype(strcmp(v1->v.data, v2->v.data) > 0); + + } + case LE: case LT: { /* expr <= expr */ + + return sial_makebtype(strcmp(v1->v.data, v2->v.data) < 0); + + } + case NE: { /* expr != expr */ + + return sial_makebtype(strcmp(v1->v.data, v2->v.data)); + + } + default: { + + sial_error("Oops conditional unknown 1"); + + } + } + } + + } + else { + + int idx1, idx2; + value_t *v=sial_newval(); + + /* make sure pointers are forced to proper basetype + before calling sial_baseop()*/ + idx1=sial_reftobase(v1); + idx2=sial_reftobase(v2); + + + switch(op) { + + case EQ: + case GT: + case GE: + case LE: + case LT: + case NE: + sial_baseop(op, v1, v2, v); + break; + default: { + + sial_error("Oops conditional unknown 2"); + + } + } + v1->type.idx=idx1; + v2->type.idx=idx2; + return v; + } + return 0; +} + +static value_t * +sial_exeop(oper *o) +{ +value_t *v=0, *v1=0, *v2=0, *v3=0, *v4=0; +int top; +srcpos_t p; + + sial_curpos(&o->pos, &p); + + /* if ME (op on myself) operator, translate to normal operator + we will re-assign onto self when done */ + + top=getop(o->op); + + if(top == ASSIGN) { + + goto doop; + + } else if(top == IN) { + + /* the val in array[] test is valid for anything but struct/union */ + v=sial_makebtype((ull)sial_lookuparray(P1,P2)); + + } + else if(is_cond(top)) { + + /* the operands are eithr BASE (integer) or REF (pointer) */ + /* all conditional operators accept a mixture of pointers and integer */ + /* set the return as a basetype even if bool */ + + switch(top) { + + case CEXPR: { /* conditional expression expr ? : stmt : stmt */ + + if(sial_bool(V1)) { + + v=sial_cloneval(V2); + + } else { + + v=sial_cloneval(V3); + + } + + } + break; + case BOR: { /* a || b */ + + v=sial_makebtype((ull)(sial_bool(V1) || sial_bool(V2))); + + } + break; + case BAND: { /* a && b */ + + v=sial_makebtype((ull)(sial_bool(V1) && sial_bool(V2))); + + } + break; + case NOT: { /* ! expr */ + + v=sial_makebtype((ull)(! sial_bool(V1))); + + } + break; + default: { + + v=sial_docomp(top, V1, V2); + + } + } + + } else if(anyop(V_STRING)) { + + if(top == ADD) + { + char *buf; + + if(V1->type.type != V_STRING || V2->type.type != V_STRING) { + + sial_rerror(&P1->pos, "String concatenation needs two strings!"); + + } + buf=sial_alloc(strlen(S1)+strlen(S2)+1); + strcpy(buf, S1); + strcat(buf, S2); + v=sial_makestr(buf); + sial_free(buf); + } + else { + + sial_rerror(&P1->pos, "Invalid string operator"); + + } + } + /* arithmetic operator */ + else if(anyop(V_REF)) { + + int size; + value_t *vt; + + /* make sure we have the base type second */ + if(V1->type.type != V_REF) { vt=V1; v1=V2; v2=vt; } + + + if(V1->type.type == V_BASE) { +inval: + sial_error("Invalid operand on pointer operation"); + } + + /* get the size of whas we reference */ + size=V1->type.size; + + switch(top) { + case ADD: { /* expr + expr */ + /* adding two pointers ? */ + if(V2->type.type == V_REF) goto inval; + sial_transfer(v=sial_newval(), V1, L1 + L2*size); + } + break; + case SUB: { /* expr - expr */ + + /* different results if mixed types. + if both are pointers then result is a V_BASE */ + if(V2->type.type == V_REF) + v=sial_makebtype(L1 - L2); + + else sial_transfer(v=sial_newval(), V1, L1 - L2*size); + } + break; + case PREDECR: { /* pre is easy */ + sial_transfer(v=sial_newval(), V1, L1-size); + sial_setval(V1, v); + } + break; + case PREINCR: { + sial_transfer(v=sial_newval(), V1, L1+size); + sial_setval(V1, v); + } + break; + case POSTINCR: { + sial_transfer(v=sial_newval(), V1, L1+size); + sial_setval(V1, v); + sial_transfer(v, V1, L1); + } + break; + case POSTDECR: { + sial_transfer(v=sial_newval(), V1, L1-size); + sial_setval(V1, v); + sial_transfer(v, V1, L1); + } + break; + default: + sial_error("Invalid operation on pointer [%d]",top); + } + } + else { + + /* both operands are V_BASE */ + switch(top) { + + /* for mod and div, we check for divide by zero */ + case MOD: case DIV: + if(!L2) { + sial_rerror(&P1->pos, "Mod by zero"); + } + case ADD: case SUB: case MUL: case XOR: + case OR: case AND: case SHL: case SHR: + { + sial_baseop(top, V1, V2, v=sial_newval()); + } + break; + case UMINUS: { + + value_t *v0=sial_newval(); + sial_defbtype(v0, (ull)0); + /* keep original type of v1 */ + v=sial_newval(); + sial_duptype(&v0->type, &V1->type); + sial_duptype(&v->type, &V1->type); + sial_baseop(SUB, v0, V1, v); + sial_freeval(v0); + /* must make result signed */ + sial_mkvsigned(v); + } + break; + case FLIP: { + + value_t *v0=sial_newval(); + sial_defbtype(v0, (ull)0xffffffffffffffffll); + /* keep original type of v1 */ + sial_duptype(&v0->type, &V1->type); + sial_baseop(XOR, v0, V1, v=sial_newval()); + sial_freeval(v0); + } + break; + case PREDECR: { /* pre is easy */ + sial_transfer(v=sial_newval(), V1, L1-1); + sial_setval(V1, v); + } + break; + case PREINCR: { + V1; + sial_transfer(v=sial_newval(), V1, L1+1); + sial_setval(V1, v); + } + break; + case POSTINCR: { + sial_transfer(v=sial_newval(), V1, L1+1); + sial_setval(V1, v); + sial_transfer(v, V1, L1); + } + break; + case POSTDECR: { + sial_transfer(v=sial_newval(), V1, L1-1); + sial_setval(V1, v); + sial_transfer(v, V1, L1); + } + break; + default: sial_rerror(&P1->pos, "Oops ops ! [%d]", top); + } + } +doop: + /* need to assign the value_t back to P1 */ + if(top != o->op || top==ASSIGN) { + + /* in the case the Lvalue_t is a variable , bypass execution and set ini */ + if(P1->exe == sial_exevar) { + + char *name=NODE_NAME(P1); + var_t*va=sial_getvarbyname(name, 0, 0); + value_t *vp; + + sial_free(name); + + if(top != o->op) vp=v; + else vp=V2; + + sial_chkandconvert(va->v, vp); + + sial_freeval(v); + v=sial_cloneval(va->v); + va->ini=1; + + } else { + + if(!(V1->set)) { + + sial_rerror(&P1->pos, "Not Lvalue_t on assignment"); + + } + else { + + /* if it's a Me-op then v is already set */ + if(top != o->op) { sial_setval(V1, v); } + else { + + sial_setval(V1, V2); + v=sial_cloneval(V2); + } + } + } + /* the result of a assignment if not an Lvalue_t */ + v->set=0; + } + sial_freeval(v1); + sial_freeval(v2); + sial_freeval(v3); + sial_freeval(v4); + sial_setpos(&p); + return v; +} + +void +sial_freeop(oper *o) +{ +int i; + + for(i=0;inp;i++) NODE_FREE(o->parms[i]); + sial_free(o); +} + +node_t* +sial_newop(int op, int nargs, ...) +{ +va_list ap; +node_t*n=sial_newnode(); +oper *o=sial_alloc(sizeof(oper)); +int i; + + o->op=op; + o->np=nargs; + + sial_setpos(&o->pos); + + va_start(ap, nargs); + + for(i=0 ; iparms[i]=va_arg(ap, node_t*))) break;; + } + + n->exe=(xfct_t)sial_exeop; + n->free=(ffct_t)sial_freeop; + n->data=o; + + va_end(ap); + return n; +} + +/* mult is a special case since the parse always return a PTR token + for the '*' signed. The PTR token value_t is the number of '* found. +*/ +node_t* +sial_newmult(node_t*n1, node_t*n2, int n) +{ + if(n>1) { + + sial_error("Syntax error"); + } + return sial_newop(MUL, 2, n1, n2); +} +/* + This function is called when we want to set a value_t in live memory + using a pointer to it. +*/ +static void +sial_setderef(value_t *v1, value_t *v2) +{ + void *sial_adrval(value_t *); + sial_transval(v2->type.size, v1->type.size, v2, sial_issigned(v2->type.typattr)); + API_PUTMEM(v1->mem, sial_adrval(v2), v2->type.size); +} + +/* + Do a de-referencing from a pointer (ref) and put the result in v. +*/ +typedef struct { + int lev; + node_t*n; +} ptrto; + +void +sial_do_deref(int n, value_t *v, value_t *ref) +{ +ull madr, new_madr; + + if(n > ref->type.ref) { + + sial_error("Too many levels of dereference"); + + }else { + + + if(sial_defbsize()==4) madr=(ull)ref->v.ul; + else madr=ref->v.ull; + + /* copy the target type to the returned value_t's type_t*/ + sial_duptype(&v->type, &ref->type); + + /* do a number of deferences according to PTR value_t */ + while(n--) { + + sial_popref(&v->type, 1); + + if(!v->type.ref) { + + /* make sure the pointer is pointing into the vmcore */ + if(is_ctype(v->type.type)) { + + v->v.data=sial_alloc(v->type.size); + sial_getmem(madr, v->v.data, v->type.size); + + } else { + + /* get the data from the system image */ + switch(TYPE_SIZE(&v->type)) { + + case 1: sial_getmem(madr, &v->v.uc, 1); + break; + case 2: sial_getmem(madr, &v->v.us, 2); + break; + case 4: sial_getmem(madr, &v->v.ul, 4); + break; + case 8: sial_getmem(madr, &v->v.ull, 8); + break; + + } + } + } + else { + + /* get the pointer at this address */ + if(sial_defbsize()==4) { + + sial_getmem(madr, &v->v.ul, 4); + new_madr=v->v.ul; + + } else { + + sial_getmem(madr, &v->v.ull, 8); + new_madr=v->v.ull; + } + } + + /* remember this address. For the '&' operator */ + v->mem=madr; + madr=new_madr; + } + } + + /* we can always assign to a reference */ + v->set=1; + v->setval=v; + v->setfct=sial_setderef; +} + +static value_t * +sial_exepto(ptrto *pto) +{ +value_t *v=sial_newval(); +int n=pto->lev; +value_t *ref=NODE_EXE(pto->n); + + sial_do_deref(n, v, ref); + sial_freeval(ref); + return v; +} + +static void +sial_freepto(ptrto *pto) +{ + NODE_FREE(pto->n); + sial_free(pto); +} + + +/* same thing for the ptrto operator */ +node_t* +sial_newptrto(int lev, node_t*n) +{ +ptrto *pto=sial_alloc(sizeof(ptrto)); +node_t*nn=sial_newnode(); + + pto->lev=lev; + pto->n=n; + nn->exe=(xfct_t)sial_exepto; + nn->free=(ffct_t)sial_freepto; + nn->data=pto; + return nn; +} --- crash-4.0-4.6/extensions/libsial/sialpp.l 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sialpp.l 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,85 @@ +%{ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ + +#define YY_NO_UNPUT +%} + +%{ +#include + +#ifdef linux +#define YY_INPUT(buf,result,max_size) \ +{ \ + int c = sial_input(); \ + result = (c == EOF) ? YY_NULL : (buf[0] = c, 1); \ +} +#endif + +#include "sial.h" +#include "sialpp.tab.h" +#if linux +#define yylval sialpplval +#endif + +#define retok(t) return(t) +int nomacs=0; +extern int sial_chkmacvar(char *); +extern node_t *sial_newchar(void); +%} + +ABC [a-zA-Z_] +ABCN [a-zA-Z0-9_] +N [0-9] +X [0-9a-fA-F] + +%% + +[ \t\n]+ { ; } + +"defined" { retok(P_DEFINED); } +"&&" { retok(P_BAND); } +"||" { retok(P_BOR); } +"<" { retok(P_LT); } +"<=" { retok(P_LE); } +"==" { retok(P_EQ); } +">=" { retok(P_GE); } +">" { retok(P_GT); } +"!=" { retok(P_NE); } +"|" { retok(P_OR); } +"!" { retok(P_NOT); } +"^" { retok(P_XOR); } +">>" { retok(P_SHR); } +"<<" { retok(P_SHL); } +"+" { retok(P_ADD); } +"-" { retok(P_SUB); } +"/" { retok(P_DIV); } +"%" { retok(P_MOD); } +"*" { retok(P_MUL); } + +(("0x"+){X}+[lL]*|{N}+[lL]*) { yylval.n = sial_newnum(yytext); retok(P_NUMBER); } + +{ABC}{ABCN}* { + if(strlen(yytext) > MAX_SYMNAMELEN) { + + sial_error("Symbol name too long"); + } + if(nomacs || !sial_chkmacvar(yytext)) { + + yylval.n = sial_newvnode(yytext); + retok(P_VAR); + } + } + +\'.\' { yylval.n = sial_makenum(B_SC, yytext[1]); retok(P_NUMBER); } +\'\\.\' { yylval.n = sial_makenum(B_SC, sial_getseq(yytext[2])); retok(P_NUMBER); } + + +. { retok(yylval.i = yytext[0]); } + +%% +#undef input +#undef unput +#define input() sial_input() +#define unput(c) sial_unput(c) --- crash-4.0-4.6/extensions/libsial/sialpp-lsed 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sialpp-lsed 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,32 @@ +s/yyback/sialppback/g +s/yybgin/sialppbgin/g +s/yycrank/sialppcrank/g +s/yyerror/sialpperror/g +s/yyestate/sialppestate/g +s/yyextra/sialppextra/g +s/yyfnd/sialppfnd/g +s/yyin/sialppin/g +s/yyinput/sialppinput/g +s/yyleng/sialppleng/g +s/yylex/sialpplex/g +s/yylineno/sialpplineno/g +s/yylook/sialpplook/g +s/yylsp/sialpplsp/g +s/yylstate/sialpplstate/g +s/yylval/sialpplval/g +s/yymatch/sialppmatch/g +s/yymorfg/sialppmorfg/g +s/yyolsp/sialppolsp/g +s/yyout/sialppout/g +s/yyoutput/sialppoutput/g +s/yyprevious/sialppprevious/g +s/yysbuf/sialppsbuf/g +s/yysptr/sialppsptr/g +s/yysvec/sialppsvec/g +s/yytchar/sialpptchar/g +s/yytext/sialpptext/g +s/yytop/sialpptop/g +s/yyunput/sialppunput/g +s/yyvstop/sialppvstop/g +s/yywrap/sialppwrap/g +s/yydebug/sialdebug/g --- crash-4.0-4.6/extensions/libsial/sialpp.y 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sialpp.y 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,88 @@ +%{ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +/* + This is the grammar for the preprocessor expression evaluation. +*/ +#include "sial.h" +#include "sial.tab.h" +#include +#include +#include +static node_t *last_term; +%} + +%union { + node_t *n; + int i; +} + +%token P_VAR P_NUMBER +%token P_DEFINED + +%type term + +%right '?' +%left P_BOR +%left P_BAND +%left P_OR +%left P_XOR +%left P_AND +%left P_EQ P_NE +%left P_GE P_GT P_LE P_LT +%left P_SHL P_SHR +%left P_ADD P_SUB +%left P_MUL P_DIV P_MOD +%right P_UMINUS P_FLIP P_NOT + +%% + +term: + + term '?' term ':' term %prec '?' + { $$ = sial_newop(CEXPR, 3, $1, $3, $5); last_term = $$; } + | term P_BOR term { $$ = sial_newop(BOR, 2, $1, $3); last_term = $$; } + | term P_BAND term { $$ = sial_newop(BAND, 2, $1, $3); last_term = $$; } + | P_NOT term { $$ = sial_newop(NOT, 1, $2); last_term = $$; } + | term P_EQ term { $$ = sial_newop(EQ, 2, $1, $3); last_term = $$; } + | term P_GE term { $$ = sial_newop(GE, 2, $1, $3); last_term = $$; } + | term P_GT term { $$ = sial_newop(GT, 2, $1, $3); last_term = $$; } + | term P_LE term { $$ = sial_newop(LE, 2, $1, $3); last_term = $$; } + | term P_LT term { $$ = sial_newop(LT, 2, $1, $3); last_term = $$; } + | term P_NE term { $$ = sial_newop(NE, 2, $1, $3); last_term = $$; } + | '(' term ')' { $$ = $2; last_term == $$; } + | term P_OR term { $$ = sial_newop(OR, 2, $1, $3); last_term = $$; } + | term P_XOR term { $$ = sial_newop(XOR, 2, $1, $3); last_term = $$; } + | term P_SHR term { $$ = sial_newop(SHR, 2, $1, $3); last_term = $$; } + | term P_SHL term { $$ = sial_newop(SHL, 2, $1, $3); last_term = $$; } + | term P_DIV term { $$ = sial_newop(DIV, 2, $1, $3); last_term = $$; } + | term P_MOD term { $$ = sial_newop(MOD, 2, $1, $3); last_term = $$; } + | term P_SUB term { $$ = sial_newop(SUB, 2, $1, $3); last_term = $$; } + | term P_ADD term { $$ = sial_newop(ADD, 2, $1, $3); last_term = $$; } + | term P_MUL term { $$ = sial_newop(MUL, 2, $1, $3); last_term = $$; } + | term '&' term %prec P_AND { $$ = sial_newop(AND, 2, $1, $3); last_term = $$; } + | P_SUB term %prec P_UMINUS { $$ = sial_newop(UMINUS, 1, $2); last_term = $$; } + | '~' term %prec P_FLIP { $$ = sial_newop(FLIP, 1, $2); last_term = $$; } + | '+' term %prec P_UMINUS { $$ = $2; last_term = $$; } + | P_DEFINED '(' {nomacs++;} P_VAR ')' + { nomacs=0; $$ = sial_macexists($4); last_term = $$; } + | P_NUMBER { last_term = $$; } + | P_VAR { $$ = sial_makenum(B_UL, 0); last_term = $$; } + ; + +%% + +node_t * +sial_getppnode() +{ + return last_term; +} + +int +sialpperror(char *s) +{ + sial_error(s); + return 1; +} + --- crash-4.0-4.6/extensions/libsial/sial_print.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_print.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,398 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include +#include +#include +#include "sial.h" +/* + This set of function are used to print value_ts. +*/ + +/* utility that returns a string of '*' for a reference */ +static +char *sial_getref(int lev) +{ +static char *ptrs="*******"; + + return ptrs+strlen(ptrs)-lev; +} + +static char * +sial_getidx(type_t *t, char*buf, int len) +{ +int pos=0; + + buf[0]='\0'; + if(t->idxlst) { + + int i; + + for(i=0; t->idxlst[i] && pos < len; i++) { + + pos += snprintf(buf+pos, len-pos, "[%d]", t->idxlst[i]); + } + } + return buf; +} + +#define INDENT 4 /* print indent at beginning of new line */ +#define SPACER 16 /* space for type string */ +#define NAMESPACE 16 /* space used for member/var names */ +#define NBUNDLE 4 /* when printing arrays print this much before \n */ + +static void +sial_indent(int level, int indent) +{ + if(!indent) return; + sial_msg("%*s", level*INDENT, ""); +} + +static void sial_ptype2(type_t*t, value_t*v, int level, int indent, char *name, int ref, int justv); + +/* + Print a struct/union type or value +*/ +static void +sial_print_ctype(type_t *t, value_t *v, int level, int indent, char *name, int ref, int justv) +{ +stinfo_t *st=sial_getstbyindex(t->idx, t->type); +stmember_t *m; +char buf[100]; + + if(!st) sial_error("Oops sial_print_ctype!"); + + if(!st->all) { + + sial_fillst(st); + if(!st->all) sial_error("Reference to a incomplete type"); + } + + sial_indent(level, indent); + + if(!justv) { + snprintf(buf, sizeof(buf)-1, "%s %s", sial_ctypename(t->type), st->name?st->name:""); + sial_msg("%-*s ", SPACER, buf); + + /* is this is a pointer, bail out */ + } + if(ref) return; + + if(v && !justv) sial_msg(" = "); + + sial_msg("{\n"); + + for(m=st->stm; m; m=m->next) { + + value_t *vm=0; + + sial_indent(level+1, 1); + if(v) { + vm=sial_newval(); + sial_duptype(&vm->type, &m->type); + sial_exememlocal(v, m, vm); + sial_ptype2(&vm->type, vm, level+1, 0, m->m.name, 0, 0); + + } else sial_ptype2(&m->type, vm, level+1, 0, m->m.name, 0, 0); + sial_msg(";\n"); + if(vm) sial_freeval(vm); + } + + sial_indent(level, 1); + sial_msg("}"); + if(name) sial_msg(" %s", name); + +} + +static void +sial_prbval(value_t *v) +{ + if(sial_issigned(v->type.typattr)) sial_msg("%8lld", sial_getval(v)); + else sial_msg("%8llu", sial_getval(v)); +} + +static int +sial_prtstr(value_t *v, int justv) +{ +value_t *vs; +char *s, *p; + + if(sial_defbsize()==8) v->v.ull=v->mem; + else v->v.ul=v->mem; + vs=sial_getstr(v); + s=sial_getptr(vs, char); + for(p=s; *p; p++) if(!isprint(*p)) return 0; + if(p==s) { sial_freeval(vs); return 0; } + if(!justv) sial_msg("= "); + sial_msg("\"%s\"", s); + sial_freeval(vs); + return 1; +} + +static void +sial_prtarray(type_t*t, ull mem, int level, int idx) +{ +int i; +int j, size=1; + + for(j=idx+1; t->idxlst[j]; j++) size *= t->idxlst[j]; + size *= t->type==V_REF ? sial_defbsize() : t->size; + + /* start printing */ + sial_msg("{"); + sial_msg("\n"); + sial_indent(level+1, 1); + + for(i=0; iidxlst[idx]; i++, mem += size) { + + if(t->idxlst[idx+1]) { + + sial_msg("[%d] = ", i); + sial_prtarray(t, mem, level+1, idx+1); + + } else { + + /* time to deref and print final type */ + value_t *v=sial_newval(), *vr=sial_newval(); + int *pi=t->idxlst; + + t->idxlst=0; + + sial_duptype(&vr->type, t); + sial_pushref(&vr->type, 1); + if(sial_defbsize()==8) vr->v.ull=mem; + else vr->v.ul=(ul)mem; + sial_do_deref(1, v, vr); + if(is_ctype(v->type.type) || !(i%NBUNDLE)) sial_msg("[%2d] ", i); + sial_ptype2(&v->type, v, level+1, 0, 0, 0, 1); + sial_msg(", "); + /* anything else then struct/unions, print in buddles */ + if(!is_ctype(v->type.type) && !((i+1)%NBUNDLE)) { + + sial_msg("\n"); + sial_indent(level+1, 1); + } + sial_freeval(v); + sial_freeval(vr); + t->idxlst=pi; + } + } + sial_msg("\n"); + sial_indent(level, 1); + sial_msg("}"); +} + +/* + Print a type. + Typical output of the 'whatis' command. +*/ +static +void sial_ptype2(type_t*t, value_t*v, int level, int indent, char *name, int ref, int justv) +{ +int type=t->type; + + sial_indent(level, indent); + switch(type) { + + case V_STRUCT: case V_UNION: + + /* make sure we have all the member info */ + sial_print_ctype(t, v, level, 0, name, ref, justv); + break; + + + case V_TYPEDEF: + /* no typedef should get here */ + sial_warning("Typedef in print!"); + break; + + case V_ENUM: + /* no enum should get here */ + sial_warning("ENUM in print!"); + break; + + case V_REF: + { + int refi=t->ref, ref=refi; + + /* decrement ref if this was declared as a array */ + if(t->idxlst) ref--; + + /* print the referenced type */ + sial_popref(t, t->ref); + sial_ptype2(t, 0, level, 0, 0, 1, justv); + sial_pushref(t, refi); + + if(!justv) { + + char buf[100], buf2[100]; + int pos=0, len=sizeof(buf); + + buf[0]='\0'; + if(t->fct) buf[pos++]='('; + if(pos < len) + pos += snprintf(buf+pos, len-pos, "%s%s", sial_getref(ref), name?name:""); + if(pos < len) + pos += snprintf(buf+pos, len-pos, "%s", sial_getidx(t, buf2, sizeof(buf2))); + if(pos < len && t->fct) + pos += snprintf(buf+pos, len-pos, "%s", ")()"); + + sial_msg("%*s ", NAMESPACE, buf); + } + + /* arrays are ref with boundaries... */ + if(t->idxlst && v) { + + if(t->idxlst[1] || t->rtype!=V_BASE || t->size!=1 || !sial_prtstr(v, justv)) + { + if(!justv) sial_msg("= "); + sial_popref(t, 1); + sial_prtarray(t, v->mem, level, 0); + sial_pushref(t, 1); + } + + } else if(v) { + + if(!justv) sial_msg("= "); + if(!sial_getval(v)) sial_msg("(nil)"); + else { + if(sial_defbsize()==8) sial_msg("0x%016llx", sial_getval(v)); + else sial_msg("0x%08x", sial_getval(v)); + } + if(t->ref==1 && t->rtype==V_BASE && t->size==1) { + + (void)sial_prtstr(v, justv); + } + } + } + break; + + case V_BASE: + { + if(sial_isenum(t->typattr)) { + + stinfo_t *st=sial_getstbyindex(t->rtype, V_ENUM); + if(!justv) { + char buf[200]; + snprintf(buf, sizeof(buf), "enum %s", st->name?st->name:""); + sial_msg("%-*s ", SPACER, buf); + sial_msg("%*s ", NAMESPACE, (name&&v)?name:""); + } + if(v) { + + enum_t *e=st->enums; + + sial_msg("= "); + sial_prbval(v); + while(e) { + + if(e->value==sial_getval(v)) { + sial_msg(" [%s]", e->name); + break; + } + e=e->next; + } + if(!e) sial_msg(" [???]"); + + }else{ + + enum_t *e=st->enums; + int count=0; + + sial_msg(" {"); + while(e) { + + if(!(count%4)) { + sial_msg("\n"); + sial_indent(level+1, 1); + } + count ++; + sial_msg("%s = %d, ", e->name, e->value); + e=e->next; + + } + sial_msg("\n"); + sial_indent(level, 1); + sial_msg("%-*s ", SPACER, "}"); + if(ref) return; + sial_msg("%*s ", NAMESPACE, name?name:""); + } + + } else { + + if(!justv) { + sial_msg("%-*s " , SPACER , sial_getbtypename(t->typattr)); + if(ref) return; + sial_msg("%s%*s ", sial_getref(t->ref), NAMESPACE, name?name:""); + } + if(v) { + + if(!justv) sial_msg("= "); + sial_prbval(v); + } + } + } + break; + case V_STRING: + if(!justv) { + sial_msg("%-*s " , SPACER , "string"); + sial_msg("%*s ", NAMESPACE, name?name:""); + } + if(v) { + + if(!justv) sial_msg("= "); + sial_msg("\"%s\"", v->v.data); + } + break; + } + if(indent) sial_msg("\n"); +} + +static value_t* +sial_ptype(value_t*v) +{ + sial_ptype2(&v->type, 0, 0, 1, 0, 0, 0); + sial_msg("\n"); + return 0; +} + +node_t* +sial_newptype(var_t*v) +{ +node_t*n=sial_newnode(); + + n->data=v->next->v; + v->next->v=0; /* save value against freeing */ + sial_freevar(v->next); + sial_freevar(v); + n->exe=(xfct_t)sial_ptype; + n->free=(ffct_t)sial_freeval; + n->name=0; + sial_setpos(&n->pos); + return n; +} + +static value_t * +sial_pval(node_t*n) +{ +value_t *v=NODE_EXE(n); +char *name=NODE_NAME(n); + + sial_ptype2(&v->type, v, 0, 1, name, 0, 0); + sial_free(name); + sial_freeval(v); + return 0; +} + +node_t* +sial_newpval(node_t*vn, int fmt) +{ +node_t*n=sial_newnode(); + + n->data=vn; + n->exe=(xfct_t)sial_pval; + n->free=(ffct_t)sial_freenode; + n->name=0; + sial_setpos(&n->pos); + return n; +} --- crash-4.0-4.6/extensions/libsial/sial_stat.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_stat.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,435 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include "sial.h" +#include "sial.tab.h" +#include +#include + +#define MAXPARMS 10 + +typedef struct stat { + + int stype; + int np; + struct stat *next; + srcpos_t pos; + node_t*n; + node_t*parms[MAXPARMS]; + var_t*svs; /* if statement block then these are the auto and static + wars for it */ + var_t*avs; + +} stat; + +#define SETVS value_t *v1=0,*v2=0,*v3=0,*v4=0 +#define FV1 sial_freeval(v1),v1=0 +#define FV2 sial_freeval(v2),v2=0 +#define FV3 sial_freeval(v3),v3=0 +#define FV4 sial_freeval(v4),v4=0 +#define UNSETVS FV1,FV2,FV3,FV4 + +#define P1 (s->parms[0]) +#define P2 (s->parms[1]) +#define P3 (s->parms[2]) +#define P4 (s->parms[3]) + +#define V1 (v1?v1:(v1=NODE_EXE(P1))) +#define V2 (v2?v2:(v2=NODE_EXE(P2))) +#define V3 (v3?v3:(v3=NODE_EXE(P3))) +#define V4 (v4?v4:(v4=NODE_EXE(P4))) + +#define L1 (unival(V1)) +#define L2 (unival(V2)) +#define L3 (unival(V3)) +#define L4 (unival(V4)) + +#define S1 (V1->v.data) +#define S2 (V2->v.data) +#define S3 (V3->v.data) +#define S4 (V4->v.data) + +/* this is used to execute staement lists e.g. i=1,j=3; */ +static value_t* +sial_exeplist(node_t*n) +{ +value_t *val=0; + + if(n) { + + do { + + if(val) sial_freeval(val), val=0; + val=NODE_EXE(n); + n=n->next; + + } while(n); + } + return val; +} + +static int +sial_dofor(stat *s) +{ +jmp_buf brkenv; +jmp_buf cntenv; +SETVS; + + if(!setjmp(brkenv)) { + + sial_pushjmp(J_BREAK, &brkenv, 0); + + v1=sial_exeplist(P1); + FV1; + + while(!P2 || sial_bool(V2)) { + + FV2; + + if(!setjmp(cntenv)) { + + sial_pushjmp(J_CONTINUE, &cntenv, 0); + V4; + FV4; + sial_popjmp(J_CONTINUE); + + } + + UNSETVS; /* make sure we re-execute everything each time */ + v3=sial_exeplist(P3); + FV3; + } + sial_popjmp(J_BREAK); + + } + UNSETVS; + return 1; +} + +static int +sial_dowhile(stat *s) +{ +jmp_buf brkenv; +jmp_buf cntenv; +SETVS; + + if(!setjmp(brkenv)) { + + sial_pushjmp(J_BREAK, &brkenv, 0); + + while(sial_bool(V1)) { + + FV1; + + if(!setjmp(cntenv)) { + + sial_pushjmp(J_CONTINUE, &cntenv, 0); + V2; + FV2; + sial_popjmp(J_CONTINUE); + + } + + UNSETVS; /* make sure we re-execute everything each time */ + } + FV1; + sial_popjmp(J_BREAK); + + } + + return 1; +} + +static int +sial_dodo(stat *s) +{ +jmp_buf brkenv; +jmp_buf cntenv; +SETVS; + + if(!setjmp(brkenv)) { + + sial_pushjmp(J_BREAK, &brkenv, 0); + + do { + + FV2; + if(!setjmp(cntenv)) { + + sial_pushjmp(J_CONTINUE, &cntenv, 0); + V1; + FV1; + sial_popjmp(J_CONTINUE); + + } + + UNSETVS; /* make sure we re-execute everything each time */ + + } while (sial_bool(V2)); + FV2; + + sial_popjmp(J_BREAK); + + } + + UNSETVS; + return 1; +} + +static int +sial_doif(stat *s) +{ +SETVS; +ul b; + + b=sial_bool(V1); + FV1; + + if(s->np==3) { + + if (b) + V2; + else + V3; + + } else { + + if (b) + V2; + + } + + UNSETVS; + return 1; +} + +static int +sial_doswitch(stat *s) +{ +jmp_buf brkenv; +ull cval; +SETVS; + + if(!setjmp(brkenv)) { + + sial_pushjmp(J_BREAK, &brkenv, 0); + cval=unival(V1); + FV1; + sial_docase(cval, P2->data); + sial_popjmp(J_BREAK); + + } + + UNSETVS; + return 1; +} + +static void +sial_exein(stat *s) +{ +jmp_buf cntenv; +SETVS; + + if(!setjmp(cntenv)) { + + sial_pushjmp(J_CONTINUE, &cntenv, 0); + V3; + sial_popjmp(J_CONTINUE); + + } + UNSETVS; +} + +static int +sial_doin(stat *s) +{ +jmp_buf brkenv; + if(!setjmp(brkenv)) { + + sial_pushjmp(J_BREAK, &brkenv, 0); + sial_walkarray(P1, P2, (void (*)(void *))sial_exein, s); + sial_popjmp(J_BREAK); + } + return 1; +} + +/* this is where all of the flow control takes place */ + +static value_t* +sial_exestat(stat *s) +{ +srcpos_t p; +value_t *val=0; + + do { + + /* dump the val while looping */ + if(val) sial_freeval(val); + val=0; + + sial_curpos(&s->pos, &p); + + + switch(s->stype) { + + case FOR : sial_dofor(s); break; + case WHILE: sial_dowhile(s); break; + case IN: sial_doin(s); break; + case IF: sial_doif(s); break; + case DO: sial_dodo(s); break; + case SWITCH: sial_doswitch(s); break; + case DOBLK: + { + int lev; + + /* add any static variables to the current context */ + lev=sial_addsvs(S_STAT, s->svs); + sial_addsvs(S_AUTO, sial_dupvlist(s->avs)); + + /* with the block statics inserted exeute the inside stmts */ + if(s->next) val=sial_exestat(s->next); + + /* remove any static variables to the current context */ + if(s->svs) sial_setsvlev(lev); + + sial_curpos(&p, 0); + + return val; + } + + case BREAK: sial_dojmp(J_BREAK, 0); break; + case CONTINUE: sial_dojmp(J_CONTINUE, 0); break; + case RETURN: { + + + if(s->parms[0]) { + + val=(s->parms[0]->exe)(s->parms[0]->data); + } + else val=sial_newval(); + + sial_curpos(&p, 0); + sial_dojmp(J_RETURN, val); + } + break; + case PATTERN: + + val=sial_exeplist(s->parms[0]); + + } + + sial_curpos(&p, 0); + + } while((s=s->next)); + + /* we most return a type val no mather what it is */ + /* that's just the way it is...Somethings will never change...*/ + if(!val) val=sial_newval(); + + return val; +} + +void +sial_freestat(stat *s) +{ +int i; + + if(s->next) sial_freenode(s->next->n); + + for(i=0;inp && s->parms[i];i++) { + + NODE_FREE(s->parms[i]); + + } + sial_free(s); +} + +void +sial_freestat_static(stat *s) +{ + + if(s->next) sial_freenode(s->next->n); + + /* free associated static var list */ + sial_freesvs(s->svs); + sial_freesvs(s->avs); + sial_free(s); +} + +var_t*sial_getsgrp_avs(node_t*n) { return ((stat *)n->data)->avs; } +var_t*sial_getsgrp_svs(node_t*n) { return ((stat *)n->data)->svs; } + +/* add a set of static variable to a statement */ +node_t* +sial_stat_decl(node_t*n, var_t*svs) +{ +node_t*nn; +stat *s; + + sial_validate_vars(svs); + + nn=sial_newnode(); + s=sial_alloc(sizeof(stat)); + + /* add statics and autos to this statement */ + s->svs=sial_newvlist(); + s->avs=sial_newvlist(); + sial_addnewsvs(s->avs, s->svs, svs); + + if(n) s->next=(stat*)(n->data); + else s->next=0; + s->stype=DOBLK; + s->n=nn; + nn->exe=(xfct_t)sial_exestat; + nn->free=(ffct_t)sial_freestat_static; + nn->data=s; + sial_setpos(&s->pos); + + return nn; +} + +node_t* +sial_newstat(int type, int nargs, ...) +{ +va_list ap; +node_t*n=sial_newnode(); +stat *s=sial_alloc(sizeof(stat)); +int i; + + s->stype=type; + + va_start(ap, nargs); + + for(i=0;iparms[i]=va_arg(ap, node_t*); + } + + s->np=i; + s->n=n; + s->next=0; + n->exe=(xfct_t)sial_exestat; + n->free=(ffct_t)sial_freestat; + n->data=s; + + sial_setpos(&s->pos); + + va_end(ap); + return n; +} + +node_t* +sial_addstat(node_t*list, node_t*s) +{ + if(!s && list) return list; + if(s && !list) return s; + else { + stat *sp=(stat*)(list->data); + + while(sp->next) sp=sp->next; + sp->next=(stat*)(s->data); + return list; + + } +} + --- crash-4.0-4.6/extensions/libsial/sial_str.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_str.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,185 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include +#include +#include "sial.h" + +/* + Create a new string node from a string. +*/ + +value_t * +sial_setstrval(value_t *val, char *buf) +{ +char *newbuf=sial_strdup(buf); + + val->v.data=(void*)newbuf; + val->type.type=V_STRING; + val->type.size=strlen(buf)+1; + val->set=0; + return val; +} + +value_t * +sial_makestr(char *s) +{ + return sial_setstrval(sial_newval(), s); +} + +static value_t* +sial_exestr(char *buf) +{ +value_t *v=sial_newval(); + + sial_setstrval(v, buf); + return v; +} + +void +sial_freestrnode(char *buf) +{ + sial_free(buf); +} + +node_t* +sial_allocstr(char *buf) +{ +node_t*n=sial_newnode(); + + n->exe=(xfct_t)sial_exestr; + n->free=(ffct_t)sial_freestrnode; + n->data=buf; + sial_setpos(&n->pos); + + return n; +} + +node_t* +sial_strconcat(node_t*n1, node_t*n2) +{ +char *newbuf=sial_alloc(strlen(n1->data)+strlen(n2->data)+1); + + strcpy(newbuf, n1->data); + strcat(newbuf, n2->data); + sial_free(n1->data); + n1->data=newbuf; + sial_freenode(n2); + return n1; +} + +static int +is_valid(int c, int base) +{ + switch(base) + { + case 16: return (c>='0' && c<='9') || (toupper(c) >= 'A' && toupper(c) <= 'F'); + case 10: return (c>='0' && c<='9'); + case 8: return (c>='0' && c<='7'); + } + return 0; +} + +/* extract a number value_t from the input stream */ +static int sial_getnum(int base) +{ +int val=0; + while(1) + { + char c=sial_input(), C; + + C=toupper(c); + if(is_valid(C, base)) { + + val=val*base; + val+=(C>='A')?10+('F'-C):'9'-C; + } + else + { + sial_unput(c); + break; + } + } + return val; +} + +int +sial_getseq(int c) +{ +int i; +static struct { + int code; + int value; +} seqs[] = { + { 'n', '\n' }, + { 't', '\t' }, + { 'f', '\f' }, + { 'r', '\r' }, + { 'n', '\n' }, + { 'v', '\v' }, + { '\\', '\007' }, +}; + for(i=0;i +#include +/* + This file contains functions that deals with type and type + casting operators. +*/ +#define B_SIZE_MASK 0x0007f0 +#define B_SIGN_MASK 0x00f000 +#define B_STOR_MASK 0x1f0000 +#define B_CHAR 0x000010 +#define B_SHORT 0x000020 +#define B_INT 0x000040 +#define B_LONG 0x000080 +#define B_LONGLONG 0x000100 +#define B_FLOAT 0x000200 +#define B_CONST 0x000400 +#define B_SIGNED 0x001000 +#define B_UNSIGNED 0x002000 +#define B_STATIC 0x010000 +#define B_REGISTER 0x020000 +#define B_VOLATILE 0x040000 +#define B_TYPEDEF 0x080000 +#define B_EXTERN 0x100000 +#define B_VOID 0x800000 +#define B_USPEC 0x000001 /* user specified sign */ +#define B_ENUM 0x000002 /* btype is from a enum */ + +#define is_size(i) ((i)&B_SIZE_MASK) +#define is_sign(i) ((i)&B_SIGN_MASK) +#define is_stor(i) ((i)&B_STOR_MASK) +#define issigned(v) (v->type.typattr & B_SIGNED) +#define vsize(v) (is_size(v->type.typattr)) + +static struct { + int btype; + int key; + char *name; +} blut[] = { + { B_VOID, VOID , "void"}, + { B_TYPEDEF, TDEF , "tdef"}, + { B_EXTERN, EXTERN , "extern"}, + { B_STATIC, STATIC , "static"}, + { B_VOLATILE, VOLATILE , "volatile"}, + { B_CONST, CONST , "const"}, + { B_REGISTER, REGISTER , "register"}, + { B_UNSIGNED, UNSIGNED , "unsigned"}, + { B_SIGNED, SIGNED , "signed"}, + { B_CHAR, CHAR, "char" }, + { B_SHORT, SHORT , "short"}, + { B_INT, INT , "int"}, + { B_LONG, LONG , "long"}, + { B_LONGLONG, DOUBLE , "long long"}, + { B_FLOAT, FLOAT , "float"}, +}; + +type_t * +sial_newtype() +{ + return sial_calloc(sizeof(type_t)); +} + +void +sial_freetype(type_t* t) +{ + if(t->idxlst) sial_free(t->idxlst); + sial_free(t); +} + +/* this function is called by the parser to merge the + storage information (being hold in a basetype) into the real type_t*/ +type_t* +sial_addstorage(type_t*t1, type_t*t2) +{ + t1->typattr |= is_stor(t2->typattr); + sial_freetype(t2); + return t1; +} + +char * +sial_ctypename(int type) +{ + switch(type) { + + case V_TYPEDEF: return "typedef"; + case V_STRUCT: return "struct"; + case V_UNION: return "union"; + case V_ENUM: return "enum"; + default: return "???"; + } +} + +int sial_isstatic(int atr) { return atr & B_STATIC; } +int sial_isenum(int atr) { return atr & B_ENUM; } +int sial_isconst(int atr) { return atr & B_CONST; } +int sial_issigned(int atr) { return atr & B_SIGNED; } +int sial_istdef(int atr) { return atr & B_TYPEDEF; } +int sial_isxtern(int atr) { return atr & B_EXTERN; } +int sial_isvoid(int atr) { return atr & B_VOID; } +int sial_isstor(int atr) { return is_stor(atr); } +int sial_is_struct(int ctype) { return ctype==V_STRUCT; } +int sial_is_enum(int ctype) { return ctype==V_ENUM; } +int sial_is_union(int ctype) { return ctype==V_UNION; } +int sial_is_typedef(int ctype) { return ctype==V_TYPEDEF; } + +/* type seting */ +int sial_type_gettype(type_t*t) { return t->type; } +void sial_type_settype(type_t*t, int type) { t->type=type; } +void sial_type_setsize(type_t*t, int size) { t->size=size; } +int sial_type_getsize(type_t*t) { return t->size; } +void sial_type_setidx(type_t*t, ull idx) { t->idx=idx; } +ull sial_type_getidx(type_t*t) { return t->idx; } +void sial_type_setidxlst(type_t*t, int* idxlst) { t->idxlst=idxlst; } +void sial_type_setref(type_t*t, int ref, int type) { t->ref=ref; t->rtype=type; } +void sial_type_setfct(type_t*t, int val) { t->fct=val; } +void sial_type_mkunion(type_t*t) { t->type=V_UNION; } +void sial_type_mkenum(type_t*t) { t->type=V_ENUM; } +void sial_type_mkstruct(type_t*t) { t->type=V_STRUCT; } +void sial_type_mktypedef(type_t*t) { t->type=V_TYPEDEF; } + +static int defbtype=B_LONG|B_SIGNED; +static int defbidx=B_SL; +static int defbsize=4; +static int defbsign=B_SIGNED; +int sial_defbsize() { return defbsize; } + +char * +sial_getbtypename(int typattr) +{ +int i; +char *name=sial_alloc(200); + + name[0]='\0'; + for(i=0;itype.type==V_REF) { + + return TYPE_SIZE(&v->type)==4 ? (ull)(v->v.ul) : v->v.ull; + + } else switch(v->type.idx) { + + case B_SC: return (ull)(v->v.sc); + case B_UC: return (ull)(v->v.uc); + case B_SS: return (ull)(v->v.ss); + case B_US: return (ull)(v->v.us); + case B_SL: return (ull)(v->v.sl); + case B_UL: return (ull)(v->v.ul); + case B_SLL: return (ull)(v->v.sll); + case B_ULL: return (ull)(v->v.ull); + default: sial_error("Oops univ()[%d]", TYPE_SIZE(&v->type)); break; + } + return 0; +} + +void +sial_duptype(type_t*t, type_t*ts) +{ + memmove(t, ts, sizeof(type_t)); + if(ts->idxlst) { + + t->idxlst=sial_calloc(sizeof(int)*(MAXIDX+1)); + memmove(t->idxlst, ts->idxlst, sizeof(int)*(MAXIDX+1)); + } +} + +#define asarray(v) (v->arr!=v->arr->next) + +/* + Duplicate a value_t. + On duplication we do verification of the value_ts involved. + this is to make it possible to pass array to subfunctions + and to override specific value_ts that also have arrays attached + to them. +*/ +void +sial_dupval(value_t *v, value_t *vs) +{ +int isvoid=(v->type.typattr & B_VOID); + + /* if both have an attached array ... fail */ + if(asarray(v) && asarray(vs)) { + + sial_error("Can't override array"); + + } + /* when we are attaching a new array to the destination value_t + we need to add the destination reference count to the source */ + if(asarray(v)) { + + array_t*a=v->arr; + + /* preserve the array accross the freedata and memmove */ + v->arr=0; + sial_freedata(v); + + /* copy the new value_t over it */ + memmove(v, vs, sizeof(value_t)); + + /* and restore the array_t*/ + v->arr=a; + + } else { + + sial_refarray(vs, 1); + sial_freedata(v); + memmove(v, vs, sizeof(value_t)); + } + + sial_duptype(&v->type, &vs->type); + sial_dupdata(v, vs); + + /* conserve the void atribute across asignements */ + v->type.typattr |= isvoid; +} + +/* + clone a value_t. +*/ +value_t * +sial_cloneval(value_t *v) +{ +value_t *nv=sial_alloc(sizeof(value_t)); + + memmove(nv, v, sizeof(value_t)); + sial_refarray(v, 1); + sial_dupdata(nv, v); + return nv; +} + +static signed long long +twoscomp(ull val, int nbits) +{ + return val | (0xffffffffffffffffll << nbits); + // XXX return (val-1)^0xffffffffll; +} + +/* + Get a bit field value_t from system image or live memory. + We do all operations with a ull untill the end. + Then we check for the basetype size and sign and convert + apropriatly. +*/ +void +get_bit_value(ull val, int nbits, int boff, int size, value_t *v) +{ + ull mask; + int dosign=0; + int vnbits=size*8; + + + val = API_GET_UINT64(&val); + + /* first get the value_t */ + if (nbits >= 32) { + int upper_bits = nbits - 32; + mask = ((1 << upper_bits) - 1); + mask = (mask << 32) | 0xffffffff; + } + else { + mask = ((1 << nbits) - 1); + } + val = val >> boff; + val &= mask; + + if(issigned(v)) { + + /* get the sign bit */ + if(val >> (nbits-1)) dosign=1; + + } + switch(vsize(v)) { + + case B_CHAR: { + if(dosign) { + v->v.sc=(signed char)twoscomp(val, nbits); + } + else { + v->v.uc=val; + } + } + break; + case B_SHORT: { + if(dosign) { + v->v.ss=(signed short)twoscomp(val, nbits); + } + else { + v->v.us=val; + } + } + break; + case B_LONG: + + if(sial_defbsize()==8) goto ll; + + case B_INT: { + if(dosign) { + v->v.sl=(signed long)twoscomp(val, nbits); + } + else { + v->v.ul=val; + } + } + break; + case B_LONGLONG: { +ll: + if(dosign) { + v->v.sll=(signed long long)twoscomp(val, nbits); + } + else { + v->v.ull=val; + } + } + break; + default: + sial_error("Oops get_bit_value_t..."); + break; + } + +} +/* + Set a bit field value_t. dvalue_t is the destination value_t as read + from either the system image of live memory. + */ +ull +set_bit_value_t(ull dvalue, ull value, int nbits, int boff) +{ + ull mask; + + if (nbits >= 32) { + int upper_bits = nbits - 32; + mask = ((1 << upper_bits) - 1); + mask = (mask << 32) | 0xffffffff; + } + else { + mask = ((1 << nbits) - 1); + } + /* strip out the current value_t */ + dvalue &= ~(mask << boff); + + /* put in the new one */ + dvalue |= (value << boff); + return dvalue; +} + +/* this function is called when we have determined the systems + default int size (64 bit vs 32 bits) */ +void +sial_setdefbtype(int size, int sign) +{ +int idx=B_INT; + + switch(size) { + + case 1: defbtype=B_CHAR; idx=B_UC; break; + case 2: defbtype=B_SHORT;idx=B_US; break; + case 4: defbtype=B_INT; idx=B_UL; break; + case 8: defbtype=B_LONGLONG; idx=B_ULL; break; + + } + if(sign) defbsign = B_SIGNED; + else defbsign = B_UNSIGNED; + defbtype |= defbsign; + defbsize=size; + defbidx=idx; +} + +static int +getbtype(int token) +{ +int i; + + for(i=0;itype.type=V_BASE; + v->setfct=sial_setfct; + v->type.idx=idx; + v->mem=0; + switch(idx) { + + case B_UC: case B_SC: + v->type.size=1; + v->v.uc=i; + break; + case B_US: case B_SS: + v->type.size=2; + v->v.us=i; + break; + case B_UL: case B_SL: + v->type.size=4; + v->v.ul=i; + break; + case B_ULL: case B_SLL: + v->type.size=8; + v->v.ull=i; + break; + default: sial_error("Oops defbtypesize!"); break; + } + return v; +} + +value_t * +sial_defbtype(value_t *v, ull i) +{ + v->type.typattr=defbtype; + return sial_defbtypesize(v, i, defbidx); +} + +value_t * +sial_makebtype(ull i) +{ +value_t *v=sial_calloc(sizeof(value_t)); + + sial_defbtype(v, i); + sial_setarray(&v->arr); + TAG(v); + return v; +} + +value_t * +sial_newval() +{ +value_t *v=sial_makebtype(0); + + return v; +} + +/* take the current basetypes and generate a uniq index */ +static void +settypidx(type_t*t) +{ +int v1, v2, v3, size; + + if(t->typattr & B_CHAR) { + size=1; + v1=B_SC; v2=B_UC; + v3=(defbsign==B_SIGNED?B_SC:B_UC); + } else if(t->typattr & B_SHORT) { + size=2; + v1=B_SS; v2=B_US; v3=B_SS; + } else if(t->typattr & B_LONG) { + if(sial_defbsize()==4) { + size=4; + v1=B_SL; v2=B_UL; v3=B_SL; + } else goto ll; + } else if(t->typattr & B_INT) { +go: + size=4; + v1=B_SL; v2=B_UL; v3=B_SL; + } else if(t->typattr & B_LONGLONG) { +ll: + size=8; + v1=B_SLL; v2=B_ULL; v3=B_SLL; + } + else goto go; + + if(t->typattr & B_SIGNED) t->idx=v1; + else if(t->typattr & B_UNSIGNED) t->idx=v2; + else t->idx=v3; + t->size=size; +} + +/* take the current basetypes and generate a uniq index */ +int +sial_idxtoattr(int idx) +{ +int i; +static struct { + + int idx; + int attr; + +} atoidx[] = { + + {B_SC, B_SIGNED | B_CHAR}, + {B_UC, B_UNSIGNED| B_CHAR}, + {B_SS, B_SIGNED | B_SHORT}, + {B_US, B_UNSIGNED| B_SHORT}, + {B_SL, B_SIGNED | B_LONG}, + {B_UL, B_UNSIGNED| B_LONG}, + {B_SLL, B_SIGNED | B_LONGLONG}, + {B_ULL, B_UNSIGNED| B_LONGLONG}, +}; + + for(i=0; i < sizeof(atoidx)/sizeof(atoidx[0]); i++) { + + if(atoidx[i].idx==idx) return atoidx[i].attr; + } + sial_error("Oops sial_idxtoattr!"); + return 0; +} + +void +sial_mkvsigned(value_t*v) +{ + v->type.typattr &= ~B_SIGN_MASK; + v->type.typattr |= B_SIGNED; + settypidx(&v->type); +} + +/* if there's no sign set the default */ +void +sial_chksign(type_t*t) +{ + if(sial_isvoid(t->typattr)) return; + if(!is_sign(t->typattr)) { + + /* char is compile time dependant */ + if(t->idx==B_SC || t->idx==B_UC) t->typattr |= defbsign; + /* all other sizes are signed by default */ + else t->typattr |= B_SIGNED; + } + settypidx(t); +} + +/* if ther's no size specification, make it an INT */ +void +sial_chksize(type_t*t) +{ + if(!sial_isvoid(t->typattr) && !is_size(t->typattr)) sial_addbtype(t, INT); +} + +/* create a new base type element */ +type_t* +sial_newbtype(int token) +{ +int btype; +type_t*t=sial_newtype(); + + if(!token) btype=defbtype; + else { + + btype=getbtype(token); + if(is_sign(btype)) btype |= B_USPEC; + } + t->type=V_BASE; + t->typattr=btype; + settypidx(t); + TAG(t); + return t; +} + +/* set the default sign on a type if user did'nt specify one and not int */ +#define set_base_sign(a) if(!(base & (B_USPEC|B_INT))) base = (base ^ is_sign(base)) | a + +/* + char short int long longlong +char XXX XXX XXX XXX XXX +short XXX XXX OOO XXX XXX +int XXX OOO XXX OOO OOO +long XXX XXX OOO OOO XXX +longlong XXX XXX OOO XXX XXX + + the parser let's you specify any of the B_ type. It's here that we + have to check things out + +*/ +type_t* +sial_addbtype(type_t*t, int newtok) +{ +int btype=getbtype(newtok); +int base=t->typattr; + + /* size specification. Check for 'long long' any other + combinaison of size is invalid as is 'long long long' */ + if(is_size(btype)) { + + int ibase=base; + + switch(btype) { + + case B_LONG: { + + + if(!(base & (B_CHAR|B_SHORT))) { + + set_base_sign(B_UNSIGNED); + + if(base & B_LONG || sial_defbsize()==8) { + + ibase &= ~B_LONGLONG; + base |= B_LONGLONG; + base &= ~B_LONG; + + } else { + + base |= B_LONG; + } + } + break; + } + case B_INT: { + + /* + * This is a bit of a hack to circumvent the + * problem that "long int" or "long long int" + * is a valid statement in C. + */ + if(!(base & (B_INT|B_CHAR|B_LONG|B_LONGLONG))) { + + set_base_sign(B_SIGNED); + base |= B_INT; + } + if (base & (B_LONG|B_LONGLONG)) + ibase = 0; + break; + } + case B_SHORT: { + + if(!(base & (B_SHORT|B_CHAR|B_LONG|B_LONGLONG))) { + + base |= B_SHORT; + set_base_sign(B_UNSIGNED); + } + + } + case B_CHAR: { + + if(!(base & (B_CHAR|B_SHORT|B_INT|B_LONG|B_LONGLONG))) { + + base |= B_CHAR; + set_base_sign(defbsign); + } + + } + } + + if(ibase == base) { + + sial_warning("Invalid combinaison of sizes"); + + } + + } else if(is_sign(btype)) { + + if(base & B_USPEC) { + + if(is_sign(btype) == is_sign(base)) + + sial_warning("duplicate type specifier"); + + else + + sial_error("invalid combination of type specifiers"); + } + /* always keep last found signed specification */ + base ^= is_sign(base); + base |= btype; + base |= B_USPEC; + + } else if(is_stor(btype)) { + + if(is_stor(base)) { + + sial_warning("Suplemental storage class ignore"); + + } + else base |= btype; + } + t->typattr=base; + settypidx(t); + return t; +} + +/* this function gets called back from the API when the user need to parse + a type declaration. Like when a typedef dwarf returns a type string */ + +void +sial_pushref(type_t*t, int ref) +{ + if(t->type==V_REF) { + + t->ref += ref; + + } else { + + t->ref=ref; + + if(ref) { + + t->rtype=t->type; + t->type=V_REF; + } + } +} +void +sial_popref(type_t*t, int ref) +{ + + if(!t->ref) return; + + t->ref-=ref; + + if(!t->ref) { + + t->type=t->rtype; + } +} + +typedef struct { + int battr; + char *str; +} bstr; +static bstr btypstr[] = { + {CHAR, "char"}, + {SHORT, "short"}, + {INT, "int"}, + {LONG, "long"}, + {DOUBLE, "double"}, + {SIGNED, "signed"}, + {UNSIGNED, "unsigned"}, + {STATIC, "static"}, + {REGISTER, "register"}, + {VOLATILE, "volatile"}, + {VOID, "void"}, +}; +int +sial_parsetype(char *str, type_t*t, int ref) +{ +char *p; +char *tok, *pend; +int ctype=0, i, first, found; +type_t*bt=0; + + /* if it's a simple unamed ctype return 0 */ + if(!strcmp(str, "struct")) { t->type=V_STRUCT; return 0; } + if(!strcmp(str, "enum")) { t->type=V_ENUM; return 0; } + if(!strcmp(str, "union")) { t->type=V_UNION; return 0; } + + p=sial_strdup(str); + + /* get he level of reference */ + for(pend=p+strlen(p)-1; pend>=p; pend--) { + + if(*pend==' ' || *pend == '\t') continue; + if(*pend == '*' ) ref ++; + else break; + + } + *++pend='\0'; + +again: + tok=strtok(p," "); + if(!strcmp(tok, "struct")) { + + ctype=V_STRUCT; + + } else if(!strcmp(tok, "union")) { + + ctype=V_UNION; + + } else if(!strcmp(tok, "enum")) { + sial_free(p); + p=(char*)sial_alloc(strlen("unsigned int") + 1); + /* force enum type into unigned int type for now */ + strcpy(p, "unsigned int"); + goto again; + + } + if(ctype) { + + char *name=strtok(NULL, " \t"); + bt=sial_getctype(ctype, name, 1); + + /* we accept unknow struct reference if it's a ref to it */ + /* the user will probably cast it to something else anyway... */ + if(!bt) { + + if(ref) { + + bt=(type_t*)sial_getvoidstruct(ctype); + + } else { + + sial_error("Unknown Struct/Union/Enum %s", name); + + } + } + + sial_duptype(t, bt); + sial_freetype(bt); + sial_pushref(t, ref); + sial_free(p); + return 1; + } + + /* this must be a basetype_t*/ + first=1; + do { + found=0; + for(i=0;inext->v->type); + sial_freesvs(v); + return type; +} + +typedef struct cast { + + type_t*t; + node_t*n; + srcpos_t pos; + +} cast; + +/* make sure we do the proper casting */ +void +sial_transval(int s1, int s2, value_t *v, int issigned) +{ +vu_t u; + + if(s1==s2) return; + + if(issigned) { + + switch(s1) { + case 1: + switch(s2) { + case 2: + u.us=v->v.sc; + break; + case 4: + u.ul=v->v.sc; + break; + case 8: + u.ull=v->v.sc; + break; + } + break; + case 2: + switch(s2) { + case 1: + u.uc=v->v.ss; + break; + case 4: + u.ul=v->v.ss; + break; + case 8: + u.ull=v->v.ss; + break; + } + break; + case 4: + switch(s2) { + case 2: + u.us=v->v.sl; + break; + case 1: + u.uc=v->v.sl; + break; + case 8: + u.ull=v->v.sl; + break; + } + break; + case 8: + switch(s2) { + case 2: + u.us=v->v.sll; + break; + case 4: + u.ul=v->v.sll; + break; + case 1: + u.uc=v->v.sll; + break; + } + break; + } + + } else { + + switch(s1) { + case 1: + switch(s2) { + case 2: + u.us=v->v.uc; + break; + case 4: + u.ul=v->v.uc; + break; + case 8: + u.ull=v->v.uc; + break; + } + break; + case 2: + switch(s2) { + case 1: + u.uc=v->v.us; + break; + case 4: + u.ul=v->v.us; + break; + case 8: + u.ull=v->v.us; + break; + } + break; + case 4: + switch(s2) { + case 2: + u.us=v->v.ul; + break; + case 1: + u.uc=v->v.ul; + break; + case 8: + u.ull=v->v.ul; + break; + } + break; + case 8: + switch(s2) { + case 2: + u.us=v->v.ull; + break; + case 4: + u.ul=v->v.ull; + break; + case 1: + u.uc=v->v.ull; + break; + } + break; + } + } + memmove(&v->v, &u, sizeof(u)); + if(v->type.type!=V_REF) v->type.size=s2; +} + +value_t * +sial_execast(cast *c) +{ +/* we execute the expression node_t*/ +value_t *v=NODE_EXE(c->n); + + /* ... and validate the type cast */ + if(v->type.type != V_REF && v->type.type != V_BASE) { + + sial_rerror(&c->pos, "Invalid typecast"); + + } + else { + + int vsize=TYPE_SIZE(&v->type); + int issigned=sial_issigned(v->type.typattr); + + /* Now, just copy the cast type over the current type_t*/ + sial_duptype(&v->type, c->t); + + /* Take into account the size of the two objects */ + sial_transval(vsize, TYPE_SIZE(c->t), v, issigned); + } + return v; +} + +void +sial_freecast(cast *c) +{ + NODE_FREE(c->n); + sial_freetype(c->t); + sial_free(c); +} + +node_t* +sial_typecast(type_t*type, node_t*expr) +{ + if(type->type==V_STRING) { + + sial_error("Cannot cast to a 'string'"); + return 0; + + } else { + + node_t*n=sial_newnode(); + cast *c=sial_alloc(sizeof(cast)); + + c->t=type; + c->n=expr; + n->exe=(xfct_t)sial_execast; + n->free=(ffct_t)sial_freecast; + n->data=c; + sial_setpos(&c->pos); + return n; + } +} + +/* + Validate type conversions on function calls and assignments. +*/ +void +sial_chkandconvert(value_t *vto, value_t *vfrm) +{ +type_t*tto=&vto->type; +type_t*tfrm=&vfrm->type; + + if(tto->type == tfrm->type) { + + if(tto->type == V_BASE) { + + int attr=tto->typattr; + int idx=tto->idx; + + sial_transval(tfrm->size, tto->size, vfrm, sial_issigned(vfrm->type.typattr)); + sial_dupval(vto, vfrm); + tto->typattr=attr; + tto->idx=idx; + return; + + } else if(tto->type == V_REF) { + + if(sial_isvoid(tto->typattr) || sial_isvoid(tfrm->typattr)) goto dupit; + + if(tto->ref == tfrm->ref && tto->rtype == tfrm->rtype) { + + if(is_ctype(tto->rtype)) { + + if(tto->idx == tfrm->idx || sial_samectypename(tto->rtype, tto->idx, tfrm->idx)) + goto dupit; + + } else if(tto->size == tfrm->size) { + + int attr=tto->typattr; + sial_dupval(vto, vfrm); + tto->typattr=attr; + return; + } + } + } + /* Allow assignments between enums of the same type */ + else if(is_ctype(tto->type) || tto->type == V_ENUM) { + + /* same structure type_t*/ + if(tto->idx == tfrm->idx || sial_samectypename(tto->type, tto->idx, tfrm->idx)) + goto dupit; + } + else if(tto->type == V_STRING) goto dupit; + + } + else if((tto->type == V_ENUM && tfrm->type == V_BASE) || + (tto->type == V_BASE && tfrm->type == V_ENUM)) { + /* convert type from or to enum */ + int attr=tto->typattr; + int idx=tto->idx; + + sial_transval(tfrm->size, tto->size, vfrm, sial_issigned(vfrm->type.typattr)); + sial_dupval(vto, vfrm); + tto->typattr=attr; + tto->idx=idx; + return; + } + // support NULL assignment to pointer + else if(tto->type == V_REF && tfrm->type == V_BASE && !sial_getval(vfrm)) return; + sial_error("Invalid type conversion"); + +dupit: + sial_dupval(vto, vfrm); +} + --- crash-4.0-4.6/extensions/libsial/sial_util.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_util.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,831 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include "sial.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static FILE *ofile=0; +static int cols=25; +static char *bold_on, *bold_off; + + +static void +sial_getwinsize(void) +{ +struct winsize w; + + if (ioctl (fileno(ofile), TIOCGWINSZ, &w) == 0) + { + cols=w.ws_col; + } + else /* use ENV */ + { + char *ewidth; + if ((ewidth = getenv ("COLUMNS"))) + cols = atoi (ewidth); + /* use what's in terminfo */ + if (cols <= 0) + cols = tigetnum ("co"); + } + if(cols <= 10) cols=10; + if(cols > 80) cols=80; +} + +void +sial_setofile(void * f) +{ +int out; +int ret; +char *term; + + ofile=(FILE *)f; + + bold_on=""; + bold_off=""; + cols=80; + + out=fileno(ofile); + if(isatty(out)) + { + + if(!(term = getenv ("TERM"))) term="dumb"; + if(setupterm(term, out, &ret)!=ERR) + { + bold_on=tigetstr("bold"); + if(!bold_on) bold_on=""; + bold_off=tigetstr("sgr0"); + if(!bold_off) bold_off=""; + } + sial_getwinsize(); + } +} + +void * +sial_getofile(void) +{ + return ofile; +} + +/* + Output a line of text to the screen with line wrap + and escape sequence. +*/ +#define ESC '<' +#define ESC2 '>' + +static int +sial_tabs(int tabs, char *t, int lf) +{ +int i; + + if(lf) fprintf(ofile, "\n"); + for(i=0;i cols) { + + char *p3=p+(cols-n-1); + + char c=*p3; + char c2=*(p3+1); + + *p3='-'; + *(p3+1)='\0'; + + fprintf(ofile, "%s", p); + *p3=c; + *(p3+1)=c2; + n=sial_tabs(tabs, t, 0); + + } else if(n + (p2-p) >= cols) { + + n=sial_tabs(tabs, t, 1); + + } else { + + fprintf(ofile, " "); + n++; + } + + } else if(*p=='\n') { + + n=sial_tabs(tabs, t, 1); + + } else { + + fprintf(ofile, "%c", *p); + n++; + } + } + +} + +void +sial_msg(char *fmt, ...) +{ +va_list ap; + va_start(ap, fmt); + vfprintf(ofile, fmt, ap); + va_end(ap); +} + +void +sial_freenode(node_t *n) +{ + n->free(n->data); + sial_free(n); +} + +int lineno=1, lastline=1; +int col=1; +static char *filename=0; +static char *lastfile=0; + +void +sial_setlastfile(char *fname, int line) +{ + if(!fname) return; + if(lastfile) sial_free(lastfile); + lastfile=sial_strdup(fname); + lastline=line; +} + +void +sial_rstpos(void) +{ + lineno=1; + col=1; + /* do not free filename */ + filename=0; +} + +void +sial_setpos(srcpos_t *p) +{ + p->line=lineno; + p->col=col; + p->file=filename; +} + +/* set the current position */ +void +sial_curpos(srcpos_t *p, srcpos_t *s) +{ + if(s) { + s->line=lineno; + s->col=col; + s->file=filename; + } + lineno=p->line; + col=p->col; + filename=p->file; +} + +int +sial_line(int inc){ return lineno+=inc; } + +int +sial_col(int inc) { return col+=inc; } + +char * +sial_filename(void) { return filename; } + +/* + This function scans a printf() fmt string and transaletes the %p + to %08x or %016x depending on the pointer size of the object image. + We also substiture %> for 8 spaces if the pointer size is 4 bytes, this + permits easy allignment of output on either 32 or 64 bit images. + + ex: + + Proc %> pid ppid + %p %3d %3d + + In this case the %> alligns the pid with it's corresponding value_t + in the next line of output. + + We also process the '?' format which will be set to match the + corresponding value_t type. + + Also, format versus argument type validation is performed. + +*/ + +/* + Printf formats have the form : + %3$-*3$.*4$lld + %20x + %08x + %-08.8f +*/ +/* these are the buildin blocks for a regex matching formats */ +#define F_POSP "([0-9]+\\$)*" +#define F_FLGS "([-'+ #0]*)" +#define F_WARG "(\\*([0-9]+\\$)*){0,1}" +#define F_WIDTH "([0-9]*)" +#define F_PREC "((\\.(\\*([0-9]+\\$)*)*([0-9]*))*)" +#define F_SIZE "([hlL]*)" +#define F_FMT "([diouxXfeEgGcCsSpn?>]{1})" +#define FMTREG F_POSP""F_FLGS""F_WARG""F_WIDTH""F_PREC""F_SIZE""F_FMT +#define M_POSP 1 +#define M_FLAGS 2 +#define M_WIDTHARG 3 +#define M_WIDTDIGITS 4 +#define M_WIDTH 5 +#define M_PRECARG 8 +#define M_PRECDIGITS 9 +#define M_PREC 10 +#define M_SIZE 11 +#define M_FMT 12 +#define NMATCH 16 +static int addit[]={M_FLAGS,M_WIDTHARG,M_WIDTH,M_PRECARG,M_PREC,M_SIZE}; + +#define ptrto(idx) (matches[idx].rm_so==matches[idx].rm_eo?0:(pi+matches[idx].rm_so)) +#define matchlen(idx) (matches[(idx)].rm_eo-matches[(idx)].rm_so) + +void sial_error(char *fmt, ...); + +static int +chkforint(char *p, value_t **vals, int *curarg) +{ +int pos=-1; + + if(!p) return -1; + + /* a single star ? */ + if(isdigit(p[1])) { + + if(sscanf(p+1, "%d", &pos)!=1) { + + return pos; + } + pos--; + + } else { + + pos=*curarg; + *curarg=(*curarg)+1; + + } + + if(pos < BT_MAXARGS && vals[pos] && vals[pos]->type.type == V_BASE) return pos; + sial_error("Expected 'integer' type for arg%d", pos+1); + return -1; +} + +#define pushval(val, s, sig) ( \ + sig ? \ + ( \ + (s==8) ? \ + (val)->v.sll \ + : ( \ + (s==4) ? \ + (val)->v.sl \ + : ( \ + (s==2) ? \ + (val)->v.ss \ + :( \ + (s==1) ? \ + (val)->v.sc \ + :( \ + sial_error("Oops pushval"),1 \ + ) \ + ) \ + ) \ + ) \ + ) : ( \ + (s==8) ? \ + (val)->v.ull \ + : ( \ + (s==4) ? \ + (val)->v.ul \ + : ( \ + (s==2) ? \ + (val)->v.us \ + :( \ + (s==1) ? \ + (val)->v.uc \ + :( \ + sial_error("Oops pushval"),1 \ + ) \ + ) \ + ) \ + ) \ + ) \ + ) + + +static char * +add_fmt(int len, char *s, char *onefmt, int ppos, int wpos, int posarg, value_t **vals) +{ +int size=(vals[posarg]->type.type == V_REF ? sial_defbsize(): vals[posarg]->type.size); +int sign=(vals[posarg]->type.type == V_REF ? 0 : sial_issigned(vals[posarg]->type.typattr)); + + if(vals[posarg]->type.type == V_STRING) { + + if(wpos>=0 && ppos<0) + s+=snprintf(s, len, onefmt + , (int)sial_getval(vals[wpos]) + , vals[posarg]->v.data); + else if(wpos<0 && ppos>=0) + s+=snprintf(s, len, onefmt + , (int)sial_getval(vals[ppos]) + , vals[posarg]->v.data); + else if(wpos>=0 && ppos>=0) + s+=snprintf(s, len, onefmt + , (int)sial_getval(vals[wpos]) + , (int)sial_getval(vals[ppos]) + , vals[posarg]->v.data); + else s+=snprintf(s, len, onefmt + , vals[posarg]->v.data); + + } else { +#if defined(__s390x__) || defined(__s390__) + if(wpos>=0 && ppos<0) + s+=snprintf(s, len, onefmt + , (int)sial_getval(vals[wpos]) + , (unsigned long)pushval(vals[posarg], size, sign)); + else if(wpos<0 && ppos>=0) + s+=snprintf(s, len, onefmt + , (int)sial_getval(vals[ppos]) + , (unsigned long)pushval(vals[posarg], size, sign)); + else if(wpos>=0 && ppos>=0) + s+=snprintf(s, len, onefmt + , (int)sial_getval(vals[wpos]) + , (int)sial_getval(vals[ppos]) + , (unsigned long) pushval(vals[posarg], size, sign)); + else s+=snprintf(s, len, onefmt + , (unsigned long) pushval(vals[posarg], size, sign)); +#else + if(wpos>=0 && ppos<0) + s+=snprintf(s, len, onefmt + , (int)sial_getval(vals[wpos]) + , pushval(vals[posarg], size, sign)); + else if(wpos<0 && ppos>=0) + s+=snprintf(s, len, onefmt + , (int)sial_getval(vals[ppos]) + , pushval(vals[posarg], size, sign)); + else if(wpos>=0 && ppos>=0) + s+=snprintf(s, len, onefmt + , (int)sial_getval(vals[wpos]) + , (int)sial_getval(vals[ppos]) + , pushval(vals[posarg], size, sign)); + else s+=snprintf(s, len, onefmt + , pushval(vals[posarg], size, sign)); +#endif + } + return s; +} + +static char * +sial_ptr(char *fmt, value_t **vals) +{ + /* We need to ensure that we dont overflow our string buffer. Although its unlikely we will overflow it with + just numbers, strings will easliy overflow. So, lets check for strings and see how long they are. + */ +int len=0; +char *nfmt=NULL,*ni=NULL; +char *onefmt=NULL, *onei=NULL; +char *p=fmt; +char last=' '; +int curarg=0; +#define NBYTES (len-(nfmt-ni)) + +int i = 0; + + while(vals[i] != NULL) { + if(vals[i]->type.type == V_STRING) + len+=vals[i]->type.size; + i++; + } + /* We add a fudge factor of 100, which should cover all the number arguments */ + len+=strlen(fmt) + 100; + nfmt=sial_alloc(len); + ni=nfmt; + onefmt=sial_alloc(len); + onei=onefmt; + + + + while(*p) { + + if(*p=='%') { + + static regex_t preg; + static int done=0; + regmatch_t matches[NMATCH]; + + if(!done) { + + regcomp(&preg, FMTREG, REG_EXTENDED); + done=1; + } + + /* build a new format translation */ + onefmt=onei; + *onefmt++=*p++; + + /* if the returned pointer is (char*)-1 or NULL then something is wrong */ + if(!regexec(&preg, p, NMATCH, matches, 0)) { + + int i, n=matches[0].rm_eo-1; + int posarg, wpos, ppos; + char *pi=p; /* save p for ptrto() macro */ + + /* check that the width and precision field args point + to a int value_t. If they were used */ + wpos=chkforint(ptrto(M_WIDTHARG), vals, &curarg); + ppos=chkforint(ptrto(M_PRECARG), vals, &curarg); + + /* argument position was specfified ? */ + if(ptrto(M_POSP)) { + + /* we work from 0-n, printf works from 1-n */ + if(sscanf(ptrto(M_POSP), "%d", &posarg)==1) posarg--; + + if(posarg >= BT_MAXARGS || !vals[posarg]) { + sial_error("Invalid arg position specified [%d]", posarg+1); + } + + } else posarg=curarg++; + + /* jump over the format spec in the original */ + p+=n; +#if 0 +for(i=0;i=0 ){ + + *onefmt++='*'; + + } else goto def; + + break; + case M_PRECARG: + + if(ppos >=0 ){ + + *onefmt++='.'; + *onefmt++='*'; + + } else goto def; + + break; + case M_PREC: + if(ptrto(addit[i])) *onefmt++='.'; + goto def; + default: +def: + if(ptrto(addit[i])) { + strcpy(onefmt, ptrto(addit[i])); + onefmt+=matchlen(addit[i]); + } + } + } + + if(*p=='p') { + +ref: + /* if user overrides anything don't do nothing */ + if(ptrto(M_FLAGS)||ptrto(M_WIDTH)||ptrto(M_WIDTHARG)||ptrto(M_PREC)||ptrto(M_PRECARG)||ptrto(M_SIZE)) { + *onefmt++='p'; + + } else { + if(sial_defbsize()==8) { + + strcpy(onefmt, "016llx"); + onefmt+=6; + + } else { + + strcpy(onefmt, "08x"); + onefmt+=3; + } + } + *onefmt='\0'; + p++; + nfmt=add_fmt(NBYTES, nfmt, onei, ppos, wpos, posarg, vals); + + } else if(*p=='>') { + + nfmt--; + if(sial_defbsize()==8) { + + int i; + + for(i=0;i<8;i++) *nfmt++=last; + } + p++; + curarg--; + + } else if(*p=='?') { + + /* put the proper format for the user */ + if(!vals[posarg]) { + + sial_error("Expected additional argument %d\n", posarg+1); + + } else switch(vals[posarg]->type.type) { + + case V_BASE: case V_ENUM: + { + if(!ptrto(M_SIZE)) { + + if(vals[posarg]->type.size==8) { + + *onefmt++='l'; + *onefmt++='l'; + } + } + if(sial_issigned(vals[posarg]->type.typattr)) { + + *onefmt++='d'; + + }else{ + + *onefmt++='u'; + } + } + break; + case V_REF: + { + *p='p'; + goto ref; + } + case V_STRING: + { + *onefmt++='s'; + } + break; + } + p++; + *onefmt='\0'; + nfmt=add_fmt(NBYTES, nfmt, onei, ppos, wpos, posarg, vals); + + } else { + + /* check that format and value_t agree */ + /* can't do a lot more then check for strings vs anything_else */ + + if(!vals[posarg]) { + + sial_error("Expected additional argument %d\n", posarg+1); + + + } else if(*p=='s') { + + if(vals[posarg]->type.type != V_STRING) { + + sial_error("Expected type 'string' as arg%d", posarg+1); + } + + } else if(vals[posarg]->type.type == V_STRING) { + + sial_error("Incompatible type 'string' in arg%d", posarg+1); + + } + *onefmt++=*p++; + *onefmt='\0'; + nfmt=add_fmt(NBYTES, nfmt, onei, ppos, wpos, posarg, vals); + } + + } else { + + sial_warning("Malformed format specifier!"); + + } + + } else { + + last=*p; + if(nfmt-ni > len) sial_error("format tranlation overflow!"); + *nfmt++=*p++; + + } + } + sial_free(onei); + *nfmt='\0'; + return ni; +} + +value_t* sial_printf(value_t *vfmt, ...) +{ +char *fmt = sial_getptr(vfmt, char); +va_list ap; +value_t *vals[BT_MAXARGS]; +int i; + + va_start(ap, vfmt); + for(i=0;ifile, p->line); + va_start(ap, fmt); + fprintf(ofile, "%s : line %d : Error: ", p->file, p->line); + vfprintf(ofile, fmt, ap); + fprintf(ofile, "\n"); + va_end(ap); + sial_exit(1); +} + +void +sial_warning(char *fmt, ...) +{ +va_list ap; + + sial_setlastfile(filename, sial_line(0)); + va_start(ap, fmt); + fprintf(ofile, "%s : line %d : Warning: ", filename, lineno); + vfprintf(ofile, fmt, ap); + fprintf(ofile, "\n"); + va_end(ap); +} + +void +sial_rwarning(srcpos_t *p, char *fmt, ...) +{ +va_list ap; + + sial_setlastfile(p->file, p->line); + va_start(ap, fmt); + fprintf(ofile, "%s : line %d : Warning: ", p->file, p->line); + vfprintf(ofile, fmt, ap); + fprintf(ofile, "\n"); + va_end(ap); +} + +void +sial_vilast() +{ + if(lastfile) { + + sial_exevi(lastfile, lastline); + + } else { + + sial_msg("No last error record available"); + } +} + +void +sial_getcomment(void) +{ + while(1) { + + unsigned char c; + + while((c=sial_input())!='*' && c!=255) + + if(c==255) goto bad; + + if((c=sial_input())=='/') return; + else if(c==255) { +bad: + sial_error("Unterminated comment!"); + } + } +} + +/* on assignment this function is called to set the new value */ +void +sial_setfct(value_t *v1, value_t *v2) +{ + /* duplicate type and data, safeguarding array info */ + sial_dupval(v1, v2); + + /* value_t v1 is still setable */ + v1->set=1; + v1->setval=v1; +} + +node_t * +sial_sibling(node_t *n, node_t *m) +{ +node_t *p; + + if(m) { + + for(p=n;p->next;p=p->next); + p->next=m; + m->next=0; + } + return n; +} + --- crash-4.0-4.6/extensions/libsial/sial_var.c 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial_var.c 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,1321 @@ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include +#include +#include +#include "sial.h" + +/* + Get an existing variable from the current set. +*/ + +/* variable lists for the different scopes */ +typedef struct { + int type; + var_t*svs; +} svlist; + +typedef struct glo { + struct glo *next; + var_t*vv; +} glo; + +/* + Free indexes specifications. +*/ +void +sial_freeidx(idx_t *idx) +{ +int i; + + for(i=0;inidx;i++) { + + if(idx->idxs[i]) NODE_FREE(idx->idxs[i]); + } + sial_free(idx); +} + +/* + Free a variable declaration structure. +*/ +void +sial_freedvar(dvar_t*dv) +{ + if(!dv) return; + if(--dv->refcount) return; + if(dv->name) sial_free(dv->name); + if(dv->idx) sial_freeidx(dv->idx); + if(dv->init) NODE_FREE(dv->init); + if(dv->fargs) sial_freesvs(dv->fargs); + sial_free(dv); +} + +void +sial_setarray(array_t**arpp) +{ +array_t*arp=*arpp; + + if(!arp) { + + arp=sial_calloc(sizeof(array_t)); + TAG(arp); + arp->next=arp->prev=arp; + arp->ref=1; + *arpp=arp; + } +} + +/* + this is the main variable declaration function. + We support the global scope attribute that make the declared + variable accessible to all function from all scripts. + + By default the scope of a variable either the statement block + where it was declared (or first used): + { + int var; + ... + } + Then it's scope is the block itself. + + Or the file, if it was declared outside of a function. + + Storage is by default 'automatic' and can be made permanent + by using the 'static' keywork in the declaration. + 'Volatile' and 'register' storage classes are supported but + have no effect. +*/ +var_t* +sial_vardecl(dvar_t*dv, type_t*t) +{ +var_t*vlist=sial_newvlist(); +var_t*var; + + /* type *and* dv can have ref counts. First comes from typedef parsing + second comes from the declaration itself */ + dv->ref += t->ref; + + /* add one level of ref for arrays */ + if(dv->idx) dv->ref++; + + /* reset ref level for tests below */ + sial_popref(t, t->ref); + + TAG(vlist); + + if(!t->type) { + + int sto=sial_isstor(t->typattr); + + sial_freetype(t); + t=sial_newbtype(0); + t->typattr |= sto; + } + else if(t->type==V_BASE && !dv->ref) { + + sial_chksign(t); + sial_chksize(t); + } + + /* is this a new typedef declaration ? */ + /* typedef is considered just like any other storage class */ + if(sial_istdef(t->typattr)) { + + sial_tdef_decl(dv, t); + return 0; + } + + while(dv) { + + /* disalow var names that match against already defined vars */ + if(dv->name[0]) { + type_t *t=sial_getctype(V_TYPEDEF, dv->name, 1); + if(t) { + + sial_freetype(t); + sial_error("Variable '%s' already defined as typedef.\n"); + } + } + + /* + some sanity checks here that apply to both var and struct + declarations + */ + if(is_ctype(t->type) && !dv->ref) { + + if(dv->name[0]) { + + if(!instruct) { + + if(!sial_isxtern(t->typattr)) { + + sial_freesvs(vlist); + sial_error("struct/union instances not supported, please use pointers"); + } + + } else if(sial_ispartial(t)) { + + sial_freesvs(vlist); + sial_error("Reference to incomplete type"); + } + } + } + if(dv->nbits) { + + if(t->type != V_BASE) { + + sial_freesvs(vlist); + sial_error("Bit fields can only be of integer type"); + + } + if(dv->idx) { + + sial_freesvs(vlist); + sial_error("An array of bits ? Come on..."); + } + } + + var=sial_newvar(dv->name); + + t->fct=dv->fct; + sial_duptype(&var->v->type, t); + sial_pushref(&var->v->type, dv->ref); + + var->dv=dv; + + TAG(var); + + if(t->type == V_STRING) { + + sial_setstrval(var->v, ""); + + } + + sial_setpos(&dv->pos); + + sial_enqueue(vlist, var); + + dv=dv->next; + } + sial_free(t); + TAG(vlist); + return vlist; +} + +dvar_t* +sial_newdvar(node_t*v) +{ +dvar_t*dv; + + dv=sial_alloc(sizeof(dvar_t)); + memset(dv, 0, sizeof(dvar_t)); + if(v) { + dv->name=NODE_NAME(v); + NODE_FREE(v); + + } else { + + dv->name=sial_alloc(1); + dv->name[0]='\0'; + } + dv->refcount=1; + sial_setpos(&dv->pos); + return dv; +} + +dvar_t* +sial_dvarini(dvar_t*dv, node_t*init) +{ + dv->init=init; + return dv; +} + +dvar_t* +sial_dvarptr(int ref, dvar_t*dv) +{ + dv->ref+=ref; + return dv; +} + +dvar_t* +sial_dvaridx(dvar_t*dv, node_t*n) +{ + if(!dv->idx) { + + dv->idx=sial_alloc(sizeof(idx_t)); + dv->idx->nidx=0; + } + dv->idx->idxs[dv->idx->nidx++]=n; + return dv; +} + +dvar_t* +sial_dvarfld(dvar_t*dv, node_t*n) +{ + + if(n) { + + value_t *va=sial_exenode(n); + + /* get the value_t for the bits */ + if(!va) dv->nbits=0; + else { + dv->nbits=unival(va); + sial_freeval(va); + } + NODE_FREE(n); + + } else dv->nbits=0; + + dv->bitfield=1; + return dv; +} + +dvar_t* +sial_dvarfct(dvar_t*dv, var_t*fargs) +{ + dv->fct=1; + dv->fargs=fargs; + return dv; +} + +dvar_t* +sial_linkdvar(dvar_t*dvl, dvar_t*dv) +{ +dvar_t*v; + + /* need to keep declaration order for variable initialization */ + if(dv) { + + for(v=dvl; v->next; v=v->next); + dv->next=0; + v->next=dv; + } + return dvl; +} + +idx_t * +sial_newidx(node_t*n) +{ +idx_t *idx; + + if(!instruct) { + + sial_error("Array supported only in struct/union declarations"); + } + idx=sial_alloc(sizeof(idx_t)); + idx->nidx=1; + idx->idxs[0]=n; + return idx; +} + +idx_t * +sial_addidx(idx_t *idx, node_t*n) +{ + if(idx->nidx==MAXIDX) { + + sial_error("Maximum number of dimension is %d", MAXIDX); + } + idx->idxs[idx->nidx++]=n; + return idx; +} + +static svlist svs[S_MAXDEEP]; +static glo *globs=0; +int svlev=0; + +void +sial_refarray(value_t *v, int inc) +{ +array_t*ap, *na; + + if(!v->arr) return; + v->arr->ref+=inc; + if(v->arr->ref == 0) { + + /* free all array element. */ + for(ap=v->arr->next; ap!=v->arr; ap=na) { + + na=ap->next; + sial_freeval(ap->idx); + sial_freeval(ap->val); + sial_free(ap); + } + sial_free(v->arr); + v->arr=0; + + } else { + + /* do the same to all sub arrays */ + for(ap=v->arr->next; ap!=v->arr; ap=na) { + + na=ap->next; + sial_refarray(ap->val, inc); + } + } + +} + +void +sial_freedata(value_t *v) +{ + + if(is_ctype(v->type.type) || v->type.type == V_STRING) { + + if(v->v.data) sial_free(v->v.data); + v->v.data=0; + + } + sial_refarray(v, -1); +} + +void +sial_dupdata(value_t *v, value_t *vs) +{ + + if(is_ctype(vs->type.type) || vs->type.type == V_STRING) { + + v->v.data=sial_alloc(vs->type.size); + memmove(v->v.data, vs->v.data, vs->type.size); + } +} + +void +sial_freeval(value_t *v) +{ + if(!v) return; + sial_freedata(v); + sial_free(v); +} + + +void +sial_freevar(var_t*v) +{ + + if(v->name) sial_free(v->name); + sial_freeval(v->v); + sial_freedvar(v->dv); + sial_free(v); +} + +void +sial_enqueue(var_t*vl, var_t*v) +{ + v->prev=vl->prev; + v->next=vl; + vl->prev->next=v; + vl->prev=v; +} + +void +sial_dequeue(var_t*v) +{ + v->prev->next=v->next; + v->next->prev=v->prev; + v->next=v->prev=v; +} + +/* + This function is called to validate variable declaration. + No array decalration for variables (this can only be checked in + sial_stat_decl() and sial_file_decl() usingthe idx field ofthe var struct. + Same comment for nbits. Only in struct declarations. +*/ +void +sial_validate_vars(var_t*svs) +{ +var_t*v, *next; + + if(!svs) return; + + for(v=svs->next; v!=svs; v=next) { + + next=v->next; + + /* just remove extern variables */ + if(sial_isxtern(v->v->type.typattr)) { + + sial_dequeue(v); + sial_freevar(v); + + } else { + + if(v->dv->idx) { + + sial_freesvs(svs); + sial_error("Array instanciations not supported."); + + } + if(v->dv->nbits) { + + sial_freesvs(svs); + sial_error("Syntax error. Bit field unexpected."); + } + } + } +} + +var_t* +sial_inlist(char *name, var_t*vl) +{ +var_t*vp; + + if(vl) { + + for(vp=vl->next; vp!=vl; vp=vp->next) { + + if(!strcmp(name, vp->name)) { + + return vp; + + } + + } + } + return 0; +} + +static var_t*apiglobs; + +void +sial_setapiglobs(void) +{ + apiglobs=sial_newvlist(); + sial_add_globals(apiglobs); +} + +static var_t* +sial_inglobs(char *name) +{ +var_t*vp; +glo *g; + + for(g=globs; g; g=g->next) { + + if((vp=sial_inlist(name, g->vv))) return vp; + } + return 0; +} + + +void +sial_chkglobsforvardups(var_t*vl) +{ +var_t*v; + + if(!vl) return; + + for(v=vl->next; v != vl; v=v->next) { + + var_t*vg; + + if(v->name[0] && (vg=sial_inglobs(v->name))) { + + /* if this is a prototype declaration then skip it */ + if(v->dv && v->dv->fct) continue; + + sial_rerror(&v->dv->pos, "Duplicate declaration of variable '%s', defined at %s:%d" + , v->name, vg->dv->pos.file, vg->dv->pos.line); + } + } +} + +/* + This function scans a list of variable and looks for those that have not been initialized yet. + Globals, statics and autos all get initialized through here. +*/ +static void +sial_inivars(var_t*sv) +{ +var_t*v; + + if(!sv) return; + + for(v=sv->next; v!=sv; v=v->next) { + + /* check if we need to initialize it */ + if(!v->ini && v->dv && v->dv->init) { + + value_t *val; + srcpos_t pos; + + sial_curpos(&v->dv->pos, &pos); + + if((val=sial_exenode(v->dv->init))) { + + sial_chkandconvert(v->v, val); + sial_freeval(val); + v->ini=1; + + } else { + + sial_rwarning(&v->dv->pos, "Error initializing '%s'", v->name); + } + sial_curpos(&pos, 0); + } + } +} + +/* return the last set of globals */ +var_t* +sial_getcurgvar() +{ + if(!globs) return 0; + return globs->vv; +} + +void * +sial_add_globals(var_t*vv) +{ +glo *ng=sial_alloc(sizeof(glo)); + + sial_inivars(vv); + ng->vv=vv; + ng->next=globs; + sial_chkglobsforvardups(vv); + globs=ng; + return ng; +} + +void +sial_rm_globals(void *vg) +{ +glo *g=(glo*)vg; + + if(globs) { + + if(globs==g) globs=g->next; + else { + + glo *gp; + + for(gp=globs; gp; gp=gp->next) { + + if(gp->next==g) { + + gp->next=g->next; + + } + + } + } + sial_free(g); + } +} + + + +/* + This is where we implement the variable scoping. +*/ +var_t* +sial_getvarbyname(char *name, int silent, int local) +{ +var_t*vp; +int i, aidx=0; +ull apiv; + + for(i=svlev-1; i>=0; i--) { + + if((vp=sial_inlist(name, svs[i].svs))) { + + return vp; + } + if(svs[i].type==S_AUTO && !aidx) aidx=i; + + /* when we get to the function we're finished */ + if(svs[i].type==S_FILE) break; + } + + /* have'nt found any variable named like this one */ + /* first check the globals */ + if(!(vp=sial_inglobs(name))) { + + int off=0; + + /* check the API for a corresponding symbol */ + /* Jump over possible leading "IMG_" prefix */ + if(!strncmp(name, "IMG_", 4)) off=4; + if(!local && API_GETVAL(name+off, &apiv)) { + + vp=sial_newvar(name); + vp->ini=1; + + sial_defbtype(vp->v, apiv); + vp->v->mem=apiv; + + /* put this on the global list */ + sial_enqueue(apiglobs, vp); + } + else { + + if(silent) return 0; + sial_error("Unknown variable [%s]", name); + } + } + return vp; +} + +value_t * +sial_exists(value_t *vname) +{ +char *name=sial_getptr(vname, char); + + return sial_defbtype(sial_newval(), (sial_getvarbyname(name, 1, 0) || sial_funcexists(name))); +} + +/* get a new empty vlist */ +var_t* +sial_newvlist() +{ +var_t*p=sial_newvar(""); + TAG(p); + TAG(p->name); + TAG(p->array); + return p; +} + +/* this is called when we duplicate a list of automatic variables */ +var_t* +sial_dupvlist(var_t*vl) +{ +var_t*nv=(var_t*)sial_newvlist(); /* new root */ +var_t*vp; + + for(vp=vl->next; vp !=vl; vp=vp->next) { + + var_t*v=sial_newvar(vp->name); /* new var_t*/ + + v->dv=vp->dv; + v->dv->refcount++; + v->ini=vp->ini; + sial_dupval(v->v, vp->v); + + /* we start with a new array for automatic variable */ + sial_refarray(v->v, -1); + v->v->arr=0; + sial_setarray(&v->v->arr); + + /* can't check ctypes for initialisation */ + if(is_ctype(v->v->type.type)) v->ini=1; + sial_enqueue(nv, v); + + } + return nv; +} + +void +sial_addtolist(var_t*vl, var_t*v) +{ + if(!v->name[0] || !sial_inlist(v->name, vl)) { + + sial_enqueue(vl, v); + + } else { + + /* if this is a prototype declaration then skip it */ + if(v->dv && v->dv->fct) return; + + sial_error("Duplicate declaration of variable %s", v->name); + } +} + +static void +sial_chkforvardups(var_t*vl) +{ +var_t*v; + + if(!vl) return; + + for(v=vl->next; v!=vl; v=v->next) { + + var_t*v2=v->next; + + for(v2=v->next; v2!=vl; v2=v2->next) { + + if(v2->name[0] && !strcmp(v->name, v2->name)) { + + sial_rerror(&v2->dv->pos, "Duplicate declaration of variable '%s'", v->name); + + } + } + } +} + +static int takeproto=0; +void sial_settakeproto(int v) { takeproto=v; } + + +/* + This function scans a new list of declared variables + searching for static variables. +*/ +void +sial_addnewsvs(var_t*avl, var_t*svl, var_t*nvl) +{ +var_t*v; + + if(nvl) { + + for(v=nvl->next; v!=nvl; ) { + + var_t*next; + + /* save next before sial_enqueue() trashes it ... */ + next=v->next; + + /* if this is a external variable or prototype function declaration + skip it */ + if((!takeproto && v->dv->fct && !v->dv->ref) || sial_isxtern(v->v->type.typattr)) { + + v=next; + continue; + } + + if(sial_isstatic(v->v->type.typattr)) { + + sial_addtolist(svl, v); + + } else { + + sial_addtolist(avl, v); + } + /* with each new variables check for duplicate declarations */ + sial_chkforvardups(avl); + sial_chkforvardups(svl); + + v=next; + } + /* discard nvl's root */ + sial_freevar(nvl); + } +} + +int +sial_addsvs(int type, var_t*sv) +{ +int curlev=svlev; + + if(svlev==S_MAXDEEP) { + + sial_error("Svars stack overflow"); + + } else { + + svs[svlev].type=type; + svs[svlev].svs=sv; + svlev++; + + /* perform automatic initializations */ + sial_inivars(sv); + + /* if S_FILE then we are entering a function so start a newset of + stack variables */ + if(type == S_FILE ) { + + (void)sial_addsvs(S_AUTO, (var_t*)sial_newvlist()); + + } + } + return curlev; +} + +void +sial_add_statics(var_t*var) +{ +int i; + + for(i=svlev-1;i>=0;i--) { + + if(svs[i].type==S_FILE ) { + + if(svs[i].svs) + sial_enqueue(svs[i].svs, var); + else + svs[i].svs=var; + return; + + } + } + sial_rwarning(&var->dv->pos, "No static context for var %s.", var->name); +} + +void sial_freesvs(var_t*v) +{ +var_t*vp; + + for(vp=v->next; vp != v; ) { + + var_t*vn=vp->next; + + sial_freevar(vp); + + vp=vn; + } + sial_freevar(v); +} + +int +sial_getsvlev() { return svlev; } + +/* reset the current level of execution and free up any automatic + variables. */ +void +sial_setsvlev(int newlev) +{ +int lev; + + for(lev=svlev-1; lev>=newlev; lev--) { + + if(svs[lev].type==S_AUTO) { + + sial_freesvs(svs[lev].svs); + + } + + } + svlev=newlev; +} + +/* + called by the 'var in array' bool expression. +*/ +int +sial_lookuparray(node_t*vnode, node_t*arrnode) +{ +value_t *varr=NODE_EXE(arrnode); +array_t*ap, *apr=varr->arr; +value_t *val; +int b=0; + + val=NODE_EXE(vnode); + + if(apr) { + + for(ap=apr->next; ap != apr; ap=ap->next) { + + if(VAL_TYPE(ap->idx) == VAL_TYPE(val)) { + + switch(VAL_TYPE(val)) { + case V_STRING: b=(!strcmp(ap->idx->v.data, val->v.data)); break; + case V_BASE: b=(unival(ap->idx)==unival(val)); break; + case V_REF: + if(sial_defbsize()==4) + b=(ap->idx->v.ul==val->v.ul); + else + b=(ap->idx->v.ull==val->v.ull); + break; + default: + sial_rerror(&vnode->pos, "Invalid indexing type %d", VAL_TYPE(val)); + } + if(b) break; + } + + } + } + sial_freeval(val); + sial_freeval(varr); + return b; +} + +/* + The actual for(i in array) core... +*/ +void +sial_walkarray(node_t*varnode, node_t*arrnode, void (*cb)(void *), void *data) +{ +value_t *v; +value_t *av; +array_t*ap, *apr; + + sial_setini(varnode); + v=NODE_EXE(varnode); + + av=NODE_EXE(arrnode); + + if(av->arr) { + + for(apr=av->arr, ap=apr->next; ap != apr; ap=ap->next) { + + /* we set the value_t of the variable */ + sial_setval(v,ap->idx); + + (cb)(data); + + } + } + sial_freeval(v); + sial_freeval(av); +} + +/* scan the current array for a specific index and return value_t + XXX should use some hashing tables here for speed and scalability */ +array_t* +sial_getarrval(array_t**app, value_t *idx) +{ +array_t*ap, *apr; + + /* sial_setarray(app); AAA comment out */ + apr=*app; + + for(ap=apr->next; ap != apr; ap=ap->next) { + + if(ap->idx->type.type == idx->type.type) { + + int b=0; + + switch(idx->type.type) { + case V_STRING: b=(!strcmp(ap->idx->v.data, idx->v.data)); + break; + case V_BASE: b=(unival(ap->idx)==unival(idx)); + break; + case V_REF: + if(sial_defbsize()==4) + b=(ap->idx->v.ul==idx->v.ul); + else + b=(ap->idx->v.ull==idx->v.ull); + break; + default: + sial_error("Invalid index type %d", idx->type.type); + } + + if(b) { + + return ap; + + } + } + } + + /* we have not found this index, create one */ + ap=(array_t*)sial_calloc(sizeof(array_t)); + ap->idx=sial_makebtype(0); + sial_dupval(ap->idx, idx); + + /* just give it a int value_t of 0 for now */ + ap->val=sial_makebtype(0); + + /* we must set the same refenrence number as the + upper level array_t*/ + ap->val->arr->ref=apr->ref; + + /* link it in */ + ap->prev=apr->prev; + ap->next=apr; + apr->prev->next=ap; + apr->prev=ap; + ap->ref=0; + return ap; +} + +value_t * +sial_intindex(value_t *a, int idx) +{ +value_t *v=sial_makebtype(idx); +array_t*ap=sial_getarrval(&a->arr, v); + + sial_dupval(v, ap->val); + return v; +} + +value_t * +sial_strindex(value_t *a, char *idx) +{ +value_t *v=sial_makestr(idx); +array_t*ap=sial_getarrval(&a->arr, v); + + sial_dupval(v, ap->val); + return v; +} + + +void +sial_setarrbval(array_t*a, int val) +{ + sial_defbtype(a->val, (ull)val); +} + +array_t* +sial_addarrelem(array_t**arr, value_t *idx, value_t *val) +{ +array_t*na; + + na=sial_getarrval(arr, idx); + + /* copy new val over */ + sial_freeval(na->val); + na->val=val; + + return na; +} + +/* insert a variable at the end of the list */ +static void +sial_varinsert(var_t*v) +{ +int i; + + for(i=svlev-1;i>=0;i--) { + + if(svs[i].type==S_AUTO) { + + sial_enqueue(svs[i].svs, v); + break; + } + } +} + +/* Dupicate and add a set of variables. Used to setup a function execution. + The new veriables are the actual parameters of the function so we mark them + As being initialized. +*/ +void +sial_add_auto(var_t*nv) +{ + nv->ini=1; + sial_varinsert(nv); +} + +void +sial_valindex(value_t *var, value_t *idx, value_t *ret) +{ + if(is_ctype(idx->type.type)) { + + sial_error("Invalid indexing type"); + + } else { + + array_t*a; + + a=sial_getarrval(&var->arr, idx); + + /* this is the first level of indexing through a variable */ + sial_dupval(ret, a->val); + ret->set=1; + ret->setval=a->val; + } +} + +void +sial_addvalarray(value_t*v, value_t*idx, value_t*val) +{ + sial_addarrelem(&v->arr, idx, val); + sial_freeval(idx); +} + +static void +prtval(value_t*v) +{ +value_t*fmt=sial_makestr("%?"); + + sial_printf(fmt, v, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); + sial_freeval(fmt); +} + +static void +prlevel(char *name, value_t*root, int level) +{ +ARRAY_S *arr; + + for(arr=root->arr->next; arr != root->arr; arr=arr->next) { + + printf("%*s%s[", level*3, "", name); + prtval(arr->idx); + printf("]="); + prtval(arr->val); + printf("\n"); + prlevel(name, arr->val, level+1); + } +} + +/* sial_prarr builtin */ +value_t* +sial_prarr(value_t*vname, value_t*root) +{ +char *name=sial_getptr(vname, char); + printf("%s=", name); + prtval(root); + printf("\n"); + prlevel(name, root, 1); + return sial_makebtype(0); +} + +var_t* +sial_newvar(char *name) +{ +var_t*v=sial_calloc(sizeof(var_t)); +char *myname=sial_alloc(strlen(name)+1); + + TAG(myname); + strcpy(myname,name); + v->name=myname; + v->v=sial_makebtype(0); + v->v->setval=v->v; + v->next=v->prev=v; + return v; +} + + +typedef struct { + node_t*n; + char name[1]; +} vnode_t ; + +static int insizeof=0; +void sial_setinsizeof(int v) { insizeof=v;} + +value_t * +sial_exevar(void *arg) +{ +vnode_t *vn = arg; +value_t *nv; +var_t*curv; +srcpos_t pos; + + sial_curpos(&vn->n->pos, &pos); + + if(!(curv=sial_getvarbyname(vn->name, 0, 0))) { + + sial_error("Oops! Var ref1.[%s]", vn->name); + + } + if(!curv->ini && !insizeof) { + + sial_error("Variable [%s] used before being initialized", curv->name); + + } + + nv=sial_newval(); + sial_dupval(nv,curv->v); + nv->set=1; + nv->setval=curv->v; + nv->setfct=sial_setfct; + + sial_curpos(&pos, 0); + + return nv; +} + +/* make sure a variable is flaged as being inited */ +void +sial_setini(node_t*n) +{ + if((void*)n->exe == (void*)sial_exevar) { + + var_t*v=sial_getvarbyname(((vnode_t*)(n->data))->name, 0, 0); + v->ini=1; + } +} + + +/* get the name of a function through a variable */ +char * +sial_vartofunc(node_t*name) +{ +char *vname=NODE_NAME(name); +value_t *val; + + /* if the nore is a general expression, then vname is 0 */ + if(!vname) { + + val=sial_exenode(name); + + } else { + + var_t*v; + + v=sial_getvarbyname(vname, 1, 1); + if(!v) return vname; + val=v->v; + } + + switch(val->type.type) + { + case V_STRING: + { + char *p=sial_alloc(val->type.size+1); + /* return the value_t of that string variable */ + strcpy(p, val->v.data); + sial_free(vname); + return p; + } + default: + /* return the name of the variable itself */ + sial_error("Invalid type for function pointer, expected 'string'."); + return vname; + } +} + +char * +sial_namevar(vnode_t*vn) +{ +char *p; + + p=sial_strdup(vn->name); + TAG(p); + return p; +} + +static void +sial_freevnode(vnode_t*vn) +{ + sial_free(vn); +} + +/* + create or return existing variable node. +*/ +node_t* +sial_newvnode(char *name) +{ +node_t*n=sial_newnode(); +vnode_t*vn=sial_alloc(sizeof(vnode_t)+strlen(name)+1); + + TAG(vn); + + strcpy(vn->name, name); + n->exe=(xfct_t)sial_exevar; + n->free=(ffct_t)sial_freevnode; + n->name=(nfct_t)sial_namevar; + n->data=vn; + vn->n=n; + + sial_setpos(&n->pos); + + return n; +} + +#define TO (*to) +#define FRM (*frm) + +void +sial_cparrelems(array_t**to, array_t**frm) +{ +array_t*ap; + + if(FRM) { + + sial_setarray(to); + for(ap=FRM->next; ap!=FRM; ap=ap->next) { + + array_t*na=sial_calloc(sizeof(array_t)); + + /* copy value_ts */ + sial_dupval(na->idx, ap->idx); + sial_dupval(na->val, ap->val); + + /* link it in */ + na->prev=TO->prev; + na->next=TO; + TO->prev->next=na; + TO->prev=na; + na->ref=1; + + /* copy that branch */ + sial_cparrelems(&na->val->arr, &ap->val->arr); + } + } +} + --- crash-4.0-4.6/extensions/libsial/sial.y 2007-09-25 11:24:51.000000000 -0400 +++ crash-4.0-4.7/extensions/libsial/sial.y 2007-09-24 12:07:19.000000000 -0400 @@ -0,0 +1,438 @@ +%{ +/* + * Copyright 2001 Silicon Graphics, Inc. All rights reserved. + */ +#include "sial.h" +#include +#include +#include +#include +// to help resolve type name versus var name ambiguity... +#define VARON needvar=1; +#define VAROFF needvar=0; +static int sial_toctype(int); +int sialerror(char *); +%} + +%union { + node_t *n; + char *s; + int i; + type_t *t; + dvar_t *d; + var_t *v; +} + +%token STATIC DOBLK WHILE RETURN TDEF EXTERN VARARGS +%token CHAR SHORT FLOAT DOUBLE VOID INT UNSIGNED LONG SIGNED VOLATILE REGISTER STRTYPE CONST +%token BREAK CONTINUE DO FOR FUNC +%token IF PATTERN BASETYPE +%token STRUCT ENUM UNION +%token SWITCH CASE DEFAULT +%token ELSE CEXPR +%token VAR NUMBER STRING +%token TYPEDEF +%token '(' ')' ',' ';' '{' '}' + +%type termlist term opt_term opt_termlist +%type stmt stmtlist expstmt stmtgroup +%type var opt_var c_string +%type for if while switch case caselist caseconstlist caseconst + +%type dvar dvarlist dvarini + +%type one_var_decl var_decl_list var_decl farglist decl_list + +%type type ctype rctype btype_list tdef typecast +%type storage_list string type_decl +%type ctype_decl +%type btype storage ctype_tok print + +%right ASSIGN ADDME SUBME MULME DIVME MODME ANDME XORME +%right ORME SHLME SHRME +%right '?' +%left IN +%left BOR +%left BAND +%left OR +%left XOR +%left AND +%left EQ NE +%left GE GT LE LT +%left SHL SHR +%left ADD SUB +%left MUL DIV MOD +%left PRINT PRINTO PRINTD PRINTX TAKE_ARR +%right ADROF PTRTO PTR UMINUS SIZEOF TYPECAST POSTINCR PREINCR POSTDECR PREDECR INCR DECR FLIP NOT +%left ARRAY CALL INDIRECT DIRECT + +%% + +file: + /* empty */ + | fileobj + | file fileobj + ; + +fileobj: + function + | var_decl ';' { sial_file_decl($1); } + | ctype_decl ';' { ; } + ; + +function: + one_var_decl stmtgroup + { sial_newfunc($1, $2); } + ; + + +for: + FOR '(' opt_termlist ';' opt_term ';' opt_termlist ')' expstmt + { $$ = sial_newstat(FOR, 4, $3, $5, $7, $9); } + | FOR '(' var IN term ')' expstmt + { $$ = sial_newstat(IN, 3, $3, $5, $7); } + ; + +if: + IF '(' {VARON} term {VAROFF} ')' { $$ = $4; } + ; + +switch : + SWITCH '(' {VARON} term {VAROFF} ')' '{' caselist '}' + + { $$ = sial_newstat(SWITCH, 2, $4, $8); } + ; + +caselist: + case + | caselist case { $$ = sial_addcase($1, $2); } + ; + +case : + caseconstlist stmtlist { $$ = sial_newcase($1, $2); } + ; + +caseconst: + CASE term ':' { $$ = sial_caseval(0, $2); } + | DEFAULT ':' { $$ = sial_caseval(1, 0); } + ; + +caseconstlist: + caseconst + | caseconstlist caseconst { $$ = sial_addcaseval($1, $2); } + ; + +opt_term: + /* empty */ { $$ = 0; } + | term + ; + +termlist: + term + | termlist ',' term { $$ = sial_sibling($1, $3); } + ; + +opt_termlist: + /* empty */ { $$ = 0; } + | termlist + ; + +stmt: + termlist ';' { $$ = sial_newstat(PATTERN, 1, $1); } + | while expstmt { $$ = sial_newstat(WHILE, 2, $1, $2); } + | switch + | for + | if expstmt ELSE expstmt { $$ = sial_newstat(IF, 3, $1, $2, $4); } + | if expstmt { $$ = sial_newstat(IF, 2, $1, $2); } + | DO expstmt WHILE '(' term ')' ';' + { $$ = sial_newstat(DO, 2, $2, $5); } + | RETURN term ';' { $$ = sial_newstat(RETURN, 1, $2); } + | RETURN ';' { $$ = sial_newstat(RETURN, 1, NULLNODE); } + | BREAK ';' { $$ = sial_newstat(BREAK, 0); } + | CONTINUE ';' { $$ = sial_newstat(CONTINUE, 0); } + | ';' { $$ = 0; } + ; + +stmtlist: + /* empty */ { $$ = 0; } + | stmt + | stmtgroup + | stmtlist stmt { $$ = sial_addstat($1, $2); } + | stmtlist stmtgroup { $$ = sial_addstat($1, $2); } + ; + +stmtgroup: + '{' decl_list stmtlist '}' { $$ = sial_stat_decl($3, $2); } + | '{' stmtlist '}' { $$ = sial_stat_decl($2, 0); } + ; + +expstmt: + stmt + | stmtgroup + ; + +term: + + term '?' term ':' term %prec '?' + { $$ = sial_newop(CEXPR, 3, $1, $3, $5); } + | term BOR term { $$ = sial_newop(BOR, 2, $1, $3); } + | term BAND term { $$ = sial_newop(BAND, 2, $1, $3); } + | NOT term { $$ = sial_newop(NOT, 1, $2); } + | term ASSIGN term { $$ = sial_newop(ASSIGN, 2, $1, $3); } + | term EQ term { $$ = sial_newop(EQ, 2, $1, $3); } + | term GE term { $$ = sial_newop(GE, 2, $1, $3); } + | term GT term { $$ = sial_newop(GT, 2, $1, $3); } + | term LE term { $$ = sial_newop(LE, 2, $1, $3); } + | term LT term { $$ = sial_newop(LT, 2, $1, $3); } + | term IN term { $$ = sial_newop(IN, 2, $1, $3); } + | term NE term { $$ = sial_newop(NE, 2, $1, $3); } + | '(' term ')' { $$ = $2; } + | term ANDME term { $$ = sial_newop(ANDME, 2, $1, $3); } + | PTR term %prec PTRTO { $$ = sial_newptrto($1, $2); } + | AND term %prec ADROF { $$ = sial_newadrof($2); } + | term OR term { $$ = sial_newop(OR, 2, $1, $3); } + | term ORME term { $$ = sial_newop(ORME, 2, $1, $3); } + | term XOR term { $$ = sial_newop(XOR, 2, $1, $3); } + | term XORME term { $$ = sial_newop(XORME, 2, $1, $3); } + | term SHR term { $$ = sial_newop(SHR, 2, $1, $3); } + | term SHRME term { $$ = sial_newop(SHRME, 2, $1, $3); } + | term SHL term { $$ = sial_newop(SHL, 2, $1, $3); } + | term SHLME term { $$ = sial_newop(SHLME, 2, $1, $3); } + | term ADDME term { $$ = sial_newop(ADDME, 2, $1, $3); } + | term SUBME term { $$ = sial_newop(SUBME, 2, $1, $3); } + | term MULME term { $$ = sial_newop(MULME, 2, $1, $3); } + | term DIV term { $$ = sial_newop(DIV, 2, $1, $3); } + | term DIVME term { $$ = sial_newop(DIVME, 2, $1, $3); } + | term MODME term { $$ = sial_newop(MODME, 2, $1, $3); } + | term MOD term { $$ = sial_newop(MOD, 2, $1, $3); } + | term SUB term { $$ = sial_newop(SUB, 2, $1, $3); } + | term ADD term { $$ = sial_newop(ADD, 2, $1, $3); } + | term PTR term %prec MUL { $$ = sial_newmult($1, $3, $2); } + | term AND term { $$ = sial_newop(AND, 2, $1, $3); } + | SUB term %prec UMINUS { $$ = sial_newop(UMINUS, 1, $2); } + | '~' term %prec FLIP { $$ = sial_newop(FLIP, 1, $2); } + | '+' term %prec UMINUS { $$ = $2; } + | term '(' ')' %prec CALL { $$ = sial_newcall($1, NULLNODE); } + | term '(' termlist ')' %prec CALL { $$ = sial_newcall($1, $3); } + | DECR term { $$ = sial_newop(PREDECR, 1, $2); } + | INCR term { $$ = sial_newop(PREINCR, 1, $2); } + | term DECR { $$ = sial_newop(POSTDECR, 1, $1); } + | term INCR { $$ = sial_newop(POSTINCR, 1, $1); } + | term INDIRECT var { $$ = sial_newmem(INDIRECT, $1, $3); } + | term DIRECT var { $$ = sial_newmem(DIRECT, $1, $3); } + | term INDIRECT tdef { $$ = sial_newmem(INDIRECT, $1, sial_tdeftovar($3)); } + | term DIRECT tdef { $$ = sial_newmem(DIRECT, $1, sial_tdeftovar($3)); } + | term '[' term ']' %prec ARRAY + { $$ = sial_newindex($1, $3); } + | NUMBER + | c_string + | typecast term %prec TYPECAST { $$ = sial_typecast($1, $2); } + | SIZEOF '(' var_decl ')' + { $$ = sial_sizeof(sial_newcast($3), 1); } + | SIZEOF term { $$ = sial_sizeof($2, 2); } + | print '(' var_decl ')' %prec SIZEOF + { $$ = sial_newptype($3); } + | print term %prec SIZEOF { $$ = sial_newpval($2, $1); } + | TAKE_ARR '(' term ',' term ')' { $$ = $3; /* sial_newtakearr($3, $5); */ } + | var + ; + +print: + PRINT + | PRINTX + | PRINTO + | PRINTD + ; + +typecast: + '(' var_decl ')' { $$ = sial_newcast($2); } + ; + +var_decl_list: + var_decl ';' + | var_decl_list var_decl ';' { sial_addnewsvs($1, $1, $2); $$=$1; } + ; + +decl_list: + ctype_decl ';' { $$ = 0; } + | var_decl ';' { $$ = $1; } + | decl_list var_decl ';' { $$=$1; if($1 && $2) sial_addnewsvs($1, $1, $2); } + | decl_list ctype_decl ';' { $$ = $1; } + ; + + +var_decl: + type_decl dvarlist { needvar=0; $$ = sial_vardecl($2, $1); } + | type_decl tdef { needvar=0; $$ = sial_vardecl(sial_newdvar(sial_tdeftovar($2)), $1); } + ; + +one_var_decl: + type_decl dvar { needvar=0; $$ = sial_vardecl($2, $1); } + ; + +type_decl: + type { $$=$1; needvar++; } + | storage_list { $$=$1; needvar++; } + | type storage_list { $$=sial_addstorage($1, $2); needvar++; } + | storage_list type { $$=sial_addstorage($2, $1); needvar++; } + | type_decl PTR { $$=$1; sial_pushref($1, $2);; needvar++; } + | type_decl storage_list { $$=sial_addstorage($1, $2); needvar++; } + ; + +type: + ctype + | tdef + | btype_list + | string + | ctype_decl + ; + +ctype_decl: + ctype_tok var '{' {sial_startctype(sial_toctype($1),$2);instruct++;} var_decl_list '}' + { instruct--; $$ = sial_ctype_decl(sial_toctype($1), $2, $5); } + | ctype_tok tdef '{' {sial_startctype(sial_toctype($1),sial_tdeftovar($2));instruct++;} var_decl_list '}' + { instruct--; $$ = sial_ctype_decl(sial_toctype($1), sial_tdeftovar($2), $5); } + | ctype_tok var '{' dvarlist '}' + { $$ = sial_enum_decl(sial_toctype($1), $2, $4); } + | ctype_tok tdef '{' dvarlist '}' + { $$ = sial_enum_decl(sial_toctype($1), sial_tdeftovar($2), $4); } + ; + +ctype: + rctype { $$ = $1; } + | ctype_tok '{' {instruct++;} var_decl_list '}' + { instruct--; $$ = sial_ctype_decl(sial_toctype($1), 0, $4); } + | ctype_tok '{' dvarlist '}' + { $$ = sial_enum_decl(sial_toctype($1), 0, $3); } + ; + +farglist: + /* empty */ { $$ = 0; } + | one_var_decl { $$ = $1; } + | farglist ',' one_var_decl { + if(!$1) sial_error("Syntax error"); + if($3) sial_addnewsvs($1, $1, $3); $$=$1; + } + | farglist ',' VARARGS { + if(!$1) sial_error("Syntax error"); + sial_addtolist($1, sial_newvar(S_VARARG)); $$=$1; + } + ; + + +string: + STRTYPE { + type_t *t; + t=sial_newtype(); + t->type=V_STRING; + t->typattr=0; + $$ = t; + } + ; + +rctype: + ctype_tok var { $$ = sial_newctype(sial_toctype($1), $2); } + | ctype_tok tdef { $$ = sial_newctype(sial_toctype($1), sial_tdeftovar($2)); } + ; + +ctype_tok: + STRUCT + | ENUM + | UNION + ; + +btype_list: + btype { $$ = sial_newbtype($1); } + | btype_list btype { $$ = sial_addbtype($1, $2); } + ; + +c_string: + STRING { $$ = $1; } + | c_string STRING { $$ = sial_strconcat($1, $2); } + ; + +btype: + LONG + | CHAR + | INT + | SHORT + | UNSIGNED + | SIGNED + | DOUBLE + | FLOAT + | VOID + ; + +storage_list: + storage { $$ = sial_newbtype($1); } + | storage_list storage { sial_error("Only one storage class can be speficied"); } + ; + +storage: + STATIC + | VOLATILE + | REGISTER + | TDEF + | EXTERN + | CONST + ; + +dvarlist: + dvarini { $$ = $1; } + | dvarlist ',' dvarini { $$ = sial_linkdvar($1, $3); } + ; + +dvarini: + dvar { $$ = $1; } + | dvar ASSIGN term { $$ = sial_dvarini($1, $3); } + ; + +dvar: + opt_var { $$ = sial_newdvar($1); needvar=0; } + | tdef { $$ = sial_newdvar(sial_tdeftovar($1)); needvar=0; } + | ':' term { $$ = sial_dvarfld(sial_newdvar(0), $2); } + | dvar ':' term { $$ = sial_dvarfld($1, $3); } + | dvar '[' opt_term ']' { $$ = sial_dvaridx($1, $3); } + | PTR dvar { $$ = sial_dvarptr($1, $2); } + | dvar '(' ')' { $$ = sial_dvarfct($1, 0); } + | dvar '(' farglist ')' { $$ = sial_dvarfct($1, $3); } + | '(' dvar ')' { $$ = $2; } + ; + +opt_var: + /* empty */ { $$ = 0; } + | var { $$ = $1; } + ; + +var: + VAR { $$ = $1; } + ; + +tdef: + TYPEDEF { $$ = $1; } + ; + +while: + WHILE '(' {VARON} term {VAROFF} ')' { $$ = $4; } + ; + +%% + +static int +sial_toctype(int tok) +{ + switch(tok) { + case STRUCT: return V_STRUCT; + case ENUM: return V_ENUM; + case UNION: return V_UNION; + default: sial_error("Oops sial_toctype!"); return 0; + } +} + +/* + This file gets included into the yacc specs. + So the "sial.h" is already included +*/ + +int sialerror(char *p) { sial_error(p); return 0; } + --- crash-4.0-4.6/extensions/sial.c 2007-09-25 11:23:56.000000000 -0400 +++ crash-4.0-4.7/extensions/sial.c 2007-09-24 15:53:32.000000000 -0400 @@ -0,0 +1,887 @@ +/* + * $Id: sial.c,v 1.1 2007/09/24 19:53:32 anderson Exp $ + * + * This file is part of lcrash, an analysis tool for Linux memory dumps. + * + * Created by Silicon Graphics, Inc. + * Contributions by IBM, and others + * + * Copyright (C) 1999 - 2005 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001, 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. See the file COPYING for more + * information. + */ + +#include "gdb-6.1/gdb/defs.h" +#include "target.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "gdbcore.h" +#include "frame.h" +#include "value.h" +#include "symfile.h" +#include "objfiles.h" +#include "gdbcmd.h" +#include "call-cmds.h" +#include "gdb_regex.h" +#include "expression.h" +#include "language.h" +#include "demangle.h" +#include "inferior.h" +#include "linespec.h" +#include "source.h" +#include "filenames.h" /* for FILENAME_CMP */ +#include "objc-lang.h" + +#include "hashtab.h" + +#include "gdb_obstack.h" +#include "block.h" +#include "dictionary.h" + +#include +#include +#include "gdb_string.h" +#include "gdb_stat.h" +#include +#include "cp-abi.h" + +#include +#include +#include +#include + +///////////////////////////////////////////////////////////////////////// +// some stuff from crash's defs.h, file which cannot be included here. +// Hate to do this but this is a quick port. +// If anyone cares to work on the include and defs structure to make +// this work cleanly... +// +/* + * Global data (global_data.c) + */ +extern char *args[]; +extern int argcnt; +extern int argerrs; +#define SYNOPSIS (0x1) +#define COMPLETE_HELP (0x2) +#define PIPE_TO_LESS (0x4) +#define KVADDR (0x1) +#define QUIET (0x4) + +typedef void (*cmd_func_t)(void); + +struct command_table_entry { /* one for each command in menu */ + char *name; + cmd_func_t func; + char **help_data; + ulong flags; +}; +extern FILE *fp; +extern char *crash_global_cmd(); + +// +///////////////////////////////////////////////////////////////////////// +/* + This is the glue between the sial interpreter and crash. +*/ + +static int +apigetmem(ull iaddr, void *p, int nbytes) +{ + return readmem(iaddr, KVADDR, p, nbytes, NULL, QUIET); +} + +// Since crash is target dependant (build for the +static uint8_t apigetuint8(void* ptr) +{ +uint8_t val; + if(!readmem((unsigned long)ptr, KVADDR, (char*)&val, sizeof val, NULL, QUIET)) return (uint8_t)-1; + return val; +} + +static uint16_t apigetuint16(void* ptr) +{ +uint16_t val; + if(!readmem((unsigned long)ptr, KVADDR, (char*)&val, sizeof val, NULL, QUIET)) return (uint16_t)-1; + return val; +} + +static uint32_t apigetuint32(void* ptr) +{ +uint32_t val; + if(!readmem((unsigned long)ptr, KVADDR, (char*)&val, sizeof val, NULL, QUIET)) return (uint32_t)-1; + return val; +} + +static uint64_t apigetuint64(void* ptr) +{ +uint64_t val; + if(!readmem((unsigned long)ptr, KVADDR, (char*)&val, sizeof val, NULL, QUIET)) return (uint64_t)-1; + return val; +} + +static int +apiputmem(ull iaddr, void *p, int nbytes) +{ + return 1; +} + +/* extract a complex type (struct, union and enum) */ +static int +apigetctype(int ctype, char *name, TYPE_S *tout) +{ + struct symbol *sym; + struct type *type; + static int a=0; + + sym = lookup_symbol(name, 0, STRUCT_DOMAIN, 0, (struct symtab **) NULL); + if(!sym) + sym = lookup_symbol(name, 0, VAR_DOMAIN, 0, (struct symtab **) NULL); + + if (sym) { + type=sym->type; + switch(TYPE_CODE(type)) { + case TYPE_CODE_TYPEDEF: if(sial_is_typedef(ctype)) goto match; break; + case TYPE_CODE_ENUM: if(sial_is_enum(ctype)) goto match; break; + case TYPE_CODE_STRUCT: if(sial_is_struct(ctype)) goto match; break; + case TYPE_CODE_UNION: if(sial_is_union(ctype)) goto match; break; + } + } + return 0; + +match: + + /* populate */ + sial_type_settype(tout, ctype); + sial_type_setsize(tout, TYPE_LENGTH(type)); + sial_type_setidx(tout, (ull)(unsigned long)type); + sial_pushref(tout, 0); + return 1; +} + +/* set idx value to actual array indexes from specified size */ +static void +sial_setupidx(TYPE_S*t, int ref, int nidx, int *idxlst) +{ + /* put the idxlst in index size format */ + if(nidx) { + + int i; + + for(i=0;itype; + } + } + + switch(TYPE_CODE(type)) { + + /* typedef inserts a level of reference to the 1'dactual type */ + case TYPE_CODE_PTR: + + ref++; + type=TYPE_TARGET_TYPE(type); + /* this could be a void*, in which case the drill down stops here */ + if(!type) { + + /* make it a char* */ + sial_parsetype("char", t, ref); + return 0; + + } + break; + + /* handle pointer to functions */ + case TYPE_CODE_FUNC: + + fctflg=1; + type=TYPE_TARGET_TYPE(type); + break; + + /* Is this an array ? if so then just skip this type info and + we only need information on the elements themselves */ + case TYPE_CODE_ARRAY: + if(!idxlst) idxlst=sial_calloc(sizeof(int)*(MAXIDX+1)); + if(nidx >= MAXIDX) sial_error("Too many indexes! max=%d\n", MAXIDX); + if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) + { + idxlst[nidx++]=TYPE_LENGTH (type) / TYPE_LENGTH (check_typedef(TYPE_TARGET_TYPE (type))); + } + type=TYPE_TARGET_TYPE(type); + break; + + /* typedef points to a typedef itself */ + case TYPE_CODE_TYPEDEF: + type=TYPE_TARGET_TYPE(type); + break; + + case TYPE_CODE_INT: + + sial_parsetype(tstr=TYPE_NAME(type), t, 0); + type=0; + break; + + case TYPE_CODE_UNION: + sial_type_mkunion(t); + goto label; + + case TYPE_CODE_ENUM: + sial_type_mkenum(t); + goto label; + + case TYPE_CODE_STRUCT: + { + sial_type_mkstruct(t); + +label: + sial_type_setsize(t, TYPE_LENGTH(type)); + sial_type_setidx(t, (ull)(unsigned long)type); + tstr=TYPE_TAG_NAME(type); + type=0; + } + break; + + /* we don;t have all the info about it */ + case TYPE_CODE_VOID: + sial_parsetype("int", t, 0); + type=0; + break; + + + default: + sial_error("Oops drilldowntype"); + break; + } + + + } + sial_setupidx(t, ref, nidx, idxlst); + if(fctflg) sial_type_setfct(t, 1); + sial_pushref(t, ref+(nidx?1:0)); + if(tstr) return sial_strdup(tstr); + return sial_strdup(""); +} + +static char * +apigetrtype(ull idx, TYPE_S *t) +{ + return drilldowntype((struct type*)(unsigned long)(idx), t); +} + +/* + Return the name of a symbol at an address (if any) +*/ +static char* +apifindsym(char *p) +{ + return NULL; +} + + +/* + Get the type, size and position information for a member of a structure. +*/ +static char* +apimember(char *mname, ull tnum, TYPE_S *tm, MEMBER_S *m, ull *lnum) +{ +struct type *type=(struct type*)(unsigned long)tnum; +int midx; +#define LASTNUM (*lnum) + + /* if we're being asked the next member in a getfirst/getnext sequence */ + if(mname && !mname[0] && LASTNUM) { + + midx = LASTNUM; + + } else { + + if (TYPE_CODE(type) == TYPE_CODE_TYPEDEF) { + return 0; + } + if ((TYPE_CODE(type) != TYPE_CODE_STRUCT) && (TYPE_CODE(type) != TYPE_CODE_UNION)) { + return 0; + } + midx=0; + } + while(midx < TYPE_NFIELDS(type)) { + + if (!mname || !mname[0] || !strcmp(mname, TYPE_FIELD_NAME(type, midx))) { + + check_typedef(TYPE_FIELD_TYPE(type, midx)); + sial_member_soffset(m, TYPE_FIELD_BITPOS(type, midx)/8); + sial_member_ssize(m, TYPE_FIELD_TYPE(type, midx)->length); + sial_member_snbits(m, TYPE_FIELD_BITSIZE(type, midx)); + sial_member_sfbit(m, TYPE_FIELD_BITSIZE(type, midx)); + sial_member_sname(m, TYPE_FIELD_NAME(type, midx)); + LASTNUM=midx+1; + return drilldowntype(TYPE_FIELD_TYPE(type, midx), tm); + } + midx++; + } + return 0; +} + +/* + This function gets the proper allignment value for a type. +*/ +static int +apialignment(ull idx) +{ +struct type *type=(struct type *)(unsigned long)idx; + + while(1) + { + switch(TYPE_CODE(type)) { + + case TYPE_CODE_ARRAY: case TYPE_CODE_TYPEDEF: + type=TYPE_TARGET_TYPE(type); + break; + + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + { + int max=0, cur; + int midx=0; + + while(midx < TYPE_NFIELDS(type)) { + cur=apialignment((ull)(unsigned long)TYPE_FIELD_TYPE(type, midx)); + if(cur > max) max=cur; + midx++; + } + return max; + } + + + case TYPE_CODE_PTR: + case TYPE_CODE_ENUM: + case TYPE_CODE_INT: + + return TYPE_LENGTH (type); + + default: + + sial_error("Oops apialignment"); + } + } +} + +/* get the value of a symbol */ +static int +apigetval(char *name, ull *val) +{ + if (symbol_exists(name)) { + *val=symbol_value(name); + return 1; + } + return 0; +} + +/* + Get the list of enum symbols. +*/ +ENUM_S* +apigetenum(char *name) +{ + struct symbol *sym; + + sym = lookup_symbol(name, 0, STRUCT_DOMAIN, 0, (struct symtab **) NULL); + if (sym && TYPE_CODE(sym->type)==TYPE_CODE_ENUM) { + ENUM_S *et=0; + struct type *type=sym->type; + int n=0; + while(n < TYPE_NFIELDS (type)) { + et=sial_add_enum(et, sial_strdup(TYPE_FIELD_NAME(type, n)), TYPE_FIELD_BITPOS(type, n)); + n++; + } + return et; + } + return 0; +} + +/* + Return the list of preprocessor defines. + For Irix we have to get the die for a startup.c file. + Of dwarf type DW_TAG_compile_unit. + the DW_AT_producer will contain the compile line. + + We then need to parse that line to get all the -Dname[=value] +*/ +DEF_S * +apigetdefs(void) +{ +DEF_S *dt=0; +int i; +struct linuxdefs_s { + + char *name; + char *value; + +} linuxdefs[] = { + + {"linux", "1"}, + {"__linux", "1"}, + {"__linux__", "1"}, + {"unix", "1"}, + {"__unix", "1"}, + {"__unix__", "1"}, + // helper macros + {"LINUX_2_2_16", "(LINUX_RELEASE==0x020210)"}, + {"LINUX_2_2_17", "(LINUX_RELEASE==0x020211)"}, + {"LINUX_2_4_0", "(LINUX_RELEASE==0x020400)"}, + {"LINUX_2_2_X", "(((LINUX_RELEASE) & 0xffff00) == 0x020200)"}, + {"LINUX_2_4_X", "(((LINUX_RELEASE) & 0xffff00) == 0x020400)"}, + {"LINUX_2_6_X", "(((LINUX_RELEASE) & 0xffff00) == 0x020600)"}, +#ifdef i386 + {"i386", "1"}, + {"__i386", "1"}, + {"__i386__", "1"}, +#endif +#ifdef s390 + {"s390", "1"}, + {"__s390", "1"}, + {"__s390__", "1"}, +#endif +#ifdef s390x + {"s390x", "1"}, + {"__s390x", "1"}, + {"__s390x__", "1"}, +#endif +#ifdef ia64 + {"ia64", "1"}, + {"__ia64", "1"}, + {"__ia64__", "1"}, + {"__LP64__", "1"}, + {"_LONGLONG", "1"}, + {"__LONG_MAX__", "9223372036854775807L"}, +#endif + }; + +#if 0 +How to extract basic set of -D flags from the kernel image + + prod=sial_strdup(kl_getproducer()); + for(p=prod; *p; p++) { + + if(*p=='-' && *(p+1)=='D') { + + char *def=p+2; + + while(*p && *p != '=' && *p != ' ') p++; + + if(!*p || *p == ' ') { + + *p='\0'; + dt=sial_add_def(dt, sial_strdup(def), sial_strdup("1")); + + } else { + + char *val=p+1; + + *p++='\0'; + while(*p && *p != ' ') p++; + *p='\0'; + + dt=sial_add_def(dt, sial_strdup(def), sial_strdup(val)); + } + } + } +#endif + /* insert constant defines from list above */ + for(i=0;i\n" + , S_MAJOR, S_MINOR); +} + +static void +run_callback(void) +{ +extern char *crash_global_cmd(); + sial_cmd(crash_global_cmd(), args, argcnt); +} + + +void +edit_cmd(void) +{ +int c, file=0; + while ((c = getopt(argcnt, args, "lf")) != EOF) { + switch(c) + { + case 'l': + sial_vilast(); + break; + case 'f': + file++; + break; + default: + argerrs++; + break; + } + } + + if (argerrs) + cmd_usage(crash_global_cmd(), SYNOPSIS); + + else if(args[optind]) { + while(args[optind]) { + sial_vi(args[optind++], file); + } + } + else cmd_usage(crash_global_cmd(), SYNOPSIS); +} + +char *edit_help[]={ + "edit", + "Start a $EDITOR session of a sial function or file", + "<-f fileName>|", + "This command can be use during a tight development cycle", + "where frequent editing->run->editing sequences are executed.", + "To edit a known sial macro file use the -f option. To edit the file", + "at the location of a known function's declaration omit the -f option.", + "", + "EXAMPLES:", + " %s> edit -f ps", + " %s> edit ps", + " %s> edit ps_opt", + NULL +}; + + +// these control debug mode when parsing (pre-processor and compile) +int sialdebug=0, sialppdebug=0; + +void +load_cmd(void) +{ + if(argcnt< 2) cmd_usage(crash_global_cmd(), SYNOPSIS); + else { + sial_setofile(fp); + sial_loadunload(1, args[1], 0); + } +} + +char *load_help[]={ + "load", + "Load a sial file", + "|", + " Load a file or a directory. In the case of a directory", + " all files in that directory will be loaded.", + NULL + +}; + +void +unload_cmd(void) +{ + if(argcnt < 2) cmd_usage(crash_global_cmd(), SYNOPSIS); + else sial_loadunload(0, args[1], 0); +} + +char *unload_help[]={ + "unload", + "Unload a sial file", + "|", + " Unload a file or a directory. In the case of a directory", + " all files in that directory will be unloaded.", + NULL +}; + +#define NCMDS 100 +static struct command_table_entry command_table[NCMDS] = { + + {"edit", edit_cmd, edit_help}, + {"load", load_cmd, load_help}, + {"unload", unload_cmd, unload_help}, + {(char *)0 } +}; + +static void +add_sial_cmd(char *name, void (*cmd)(void), char **help, int flags) +{ +struct command_table_entry *cp; +struct command_table_entry *crash_cmd_table(); + + // check for a clash with native commands + for (cp = crash_cmd_table(); cp->name; cp++) { + if (!strcmp(cp->name, name)) { + sial_msg("Sial command name '%s' conflicts with native crash command.\n", name); + return; + } + } + + // make sure we have enough space for the new command + if(!command_table[NCMDS-2].name) { + for (cp = command_table; cp->name; cp++); + cp->name=sial_strdup(name); + cp->func=cmd; + cp->help_data=help; + cp->flags=flags; + } +} + +static void +rm_sial_cmd(char *name) +{ +struct command_table_entry *cp, *end; + + for (cp = command_table; cp->name; cp++) { + if (!strcmp(cp->name, name)) { + sial_free(cp->name); + memmove(cp, cp+1, sizeof *cp *(NCMDS-(cp-command_table)-1)); + break; + } + } +} + +/* + This function is called for every new function + generated by a load command. This enables us to + register new commands. + + We check here is the functions: + + fname_help() + fname_opt() + and + fname_usage() + + exist, and if so then we have a new command. + Then we associated (register) a function with + the standard sial callbacks. +*/ +void +reg_callback(char *name, int load) +{ +char fname[MAX_SYMNAMELEN+sizeof("_usage")+1]; +char *help_str, *opt_str; +char **help=malloc(sizeof *help * 5); + + if(!help) return; + snprintf(fname, sizeof(fname), "%s_help", name); + if(sial_chkfname(fname, 0)) { + help_str=sial_strdup((char*)(unsigned long)sial_exefunc(fname, 0)); + snprintf(fname, sizeof(fname), "%s_usage", name); + if(sial_chkfname(fname, 0)) { + if(load) { + opt_str=sial_strdup((char*)(unsigned long)sial_exefunc(fname, 0)); + help[0]=sial_strdup(name); + help[1]=""; + help[2]=sial_strdup(opt_str); + help[3]=sial_strdup(help_str); + help[4]=0; + add_sial_cmd(name, run_callback, help, 0); + return; + } + else rm_sial_cmd(name); + } + sial_free(help_str); + } + free(help); + return; +} + +/* + * The _fini() function is called if the shared object is unloaded. + * If desired, perform any cleanups here. + */ +void _fini() +{ + // need to unload any files we have loaded + +} + +VALUE_S *curtask(VALUE_S *v, ...) +{ +unsigned long get_curtask(); + return sial_makebtype((ull)get_curtask()); +} + +_init() /* Register the command set. */ +{ +#define LCDIR "/usr/share/sial/crash" +#define LCIDIR "include" +#define LCUDIR ".sial" + + + if(sial_open() >= 0) { + + char *path, *ipath; + char *homepath=0; + char *home=getenv("HOME"); + + /* set api, default size, and default sign for types */ +#ifdef i386 +#define SIAL_ABI ABI_INTEL_X86 +#else +#ifdef ia64 +#define SIAL_ABI ABI_INTEL_IA +#else +#ifdef __x86_64__ +#define SIAL_ABI ABI_INTEL_IA +#else +#error sial: Unkown ABI +#endif +#endif +#endif + sial_apiset(&icops, SIAL_ABI, sizeof(long), 0); + + sial_version(); + + /* set the macro search path */ + if(!(path=getenv("SIAL_MPATH"))) { + + if(home) { + + path=sial_alloc(strlen(home)+sizeof(LCUDIR)+sizeof(LCDIR)+4); + homepath=sial_alloc(strlen(home)+sizeof(LCUDIR)+2); + + /* build a path for call to sial_load() */ + strcpy(homepath, home); + strcat(homepath, "/"); + strcat(homepath, LCUDIR); + + /* built the official path */ + strcpy(path, LCDIR); + strcat(path, ":"); + strcat(path, home); + strcat(path, "/"); + strcat(path, LCUDIR); + } + else path=LCDIR; + } + sial_setmpath(path); + + fprintf(fp, "\tLoading sial commands from %s .... ", + path); + + /* include path */ + if(!(ipath=getenv("SIAL_IPATH"))) { + + if(home) { + + ipath=sial_alloc(strlen(home)+sizeof(LCDIR)+sizeof(LCUDIR)+(sizeof(LCIDIR)*2)+(sizeof("/usr/include")+2)+6); + + /* built the official path */ + strcpy(ipath, LCDIR); + strcat(ipath, "/"LCIDIR":"); + strcat(ipath, home); + strcat(ipath, "/"); + strcat(ipath, LCUDIR); + strcat(ipath, "/"LCIDIR); + strcat(ipath, ":/usr/include"); + } + else ipath=LCDIR"/"LCIDIR; + } + sial_setipath(ipath); + + /* set the new function callback */ + sial_setcallback(reg_callback); + + /* load the default macros */ + sial_loadall(); + + /* load some sial specific commands */ + register_extension(command_table); + + /* some builtins */ + sial_builtin("int curtask()", curtask); + + fprintf(fp, "Done.\n"); + } + return 1; +} --- crash-4.0-4.6/extensions/sial.mk 2007-09-25 11:23:56.000000000 -0400 +++ crash-4.0-4.7/extensions/sial.mk 2007-09-24 12:08:26.000000000 -0400 @@ -0,0 +1,11 @@ +# +all: sial.so + +lib-sial: + cd libsial && make + +sial.so: ../defs.h sial.c lib-sial + gcc -g -I.. -Ilibsial -I../gdb-6.1/bfd -I../gdb-6.1/include -I../gdb-6.1/gdb -I../gdb-6.1/gdb/config -nostartfiles -shared -rdynamic -o sial.so sial.c -fPIC -D$(TARGET) -Llibsial -lsial + +clean: + cd libsial && make clean