/* * File display.c - display handling for Wine internal debugger. * * Copyright (C) 1997, Eric Youngdale. * Copyright (C) 2003, Michal Miroslaw * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "debugger.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(winedbg); /* needs to be power of 2, search for MARK to see why :) */ #define DISPTAB_DELTA 8 struct display { struct expr* exp; int count; char format; char enabled; char func_buffer[sizeof(SYMBOL_INFO) + 256]; SYMBOL_INFO* func; }; static struct display *displaypoints = NULL; static unsigned int maxdisplays = 0, ndisplays = 0; static inline BOOL cmp_symbol(const SYMBOL_INFO* si1, const SYMBOL_INFO* si2) { if (si1->NameLen != si2->NameLen) return FALSE; return !memcmp(si1, si2, sizeof(SYMBOL_INFO) + si1->NameLen); } int display_add(struct expr *exp, int count, char format, int in_frame) { int i; for (i = 0; i < ndisplays; i++) if (displaypoints[i].exp == NULL) break; if (i == maxdisplays) { /* no space left - expand */ maxdisplays += DISPTAB_DELTA; displaypoints = dbg_heap_realloc(displaypoints, maxdisplays * sizeof(*displaypoints)); } if (i == ndisplays) ndisplays++; displaypoints[i].exp = expr_clone(exp); displaypoints[i].count = count; displaypoints[i].format = format; displaypoints[i].enabled = TRUE; if (in_frame) { displaypoints[i].func = (SYMBOL_INFO*)displaypoints[i].func_buffer; displaypoints[i].func->SizeOfStruct = sizeof(SYMBOL_INFO); displaypoints[i].func->MaxNameLen = sizeof(displaypoints[i].func_buffer) - sizeof(*displaypoints[i].func); if (!stack_get_frame(displaypoints[i].func, NULL)) { expr_free(displaypoints[i].exp); displaypoints[i].exp = NULL; return FALSE; } } else displaypoints[i].func = NULL; return TRUE; } int display_info(void) { int i; char buffer[sizeof(SYMBOL_INFO) + 256]; SYMBOL_INFO* func; const char* info; func = (SYMBOL_INFO*)buffer; func->SizeOfStruct = sizeof(SYMBOL_INFO); func->MaxNameLen = sizeof(buffer) - sizeof(*func); if (!stack_get_frame(func, NULL)) return FALSE; for (i = 0; i < ndisplays; i++) { if (displaypoints[i].exp == NULL) continue; if (displaypoints[i].enabled) { if (displaypoints[i].func && !cmp_symbol(displaypoints[i].func, func)) info = " (out of scope)"; else info = ""; } else info = " (disabled)"; dbg_printf("%d in %s%s: ", i + 1, func ? displaypoints[i].func->Name : "", info); expr_print(displaypoints[i].exp); dbg_printf("\n"); } return TRUE; } static void print_one_display(int i) { struct dbg_lvalue lvalue; if (displaypoints[i].enabled) { lvalue = expr_eval(displaypoints[i].exp); if (lvalue.typeid == dbg_itype_none) { dbg_printf("Unable to evaluate expression "); expr_print(displaypoints[i].exp); dbg_printf("\nDisabling display %d ...\n", i + 1); displaypoints[i].enabled = FALSE; return; } } dbg_printf("%d: ", i + 1); expr_print(displaypoints[i].exp); dbg_printf(" = "); if (!displaypoints[i].enabled) dbg_printf("(disabled)\n"); else if (displaypoints[i].format == 'i') memory_examine(&lvalue, displaypoints[i].count, displaypoints[i].format); else print_value(&lvalue, displaypoints[i].format, 0); } int display_print(void) { int i; char buffer[sizeof(SYMBOL_INFO) + 256]; SYMBOL_INFO* func; func = (SYMBOL_INFO*)buffer; func->SizeOfStruct = sizeof(SYMBOL_INFO); func->MaxNameLen = sizeof(buffer) - sizeof(*func); if (!stack_get_frame(func, NULL)) return FALSE; for (i = 0; i < ndisplays; i++) { if (displaypoints[i].exp == NULL || !displaypoints[i].enabled) continue; if (displaypoints[i].func && !cmp_symbol(displaypoints[i].func, func)) continue; print_one_display(i); } return TRUE; } int display_delete(int displaynum) { int i; if (displaynum > ndisplays || displaynum == 0 || displaynum < -1 || displaypoints[displaynum - 1].exp == NULL) { dbg_printf("Invalid display number\n"); return TRUE; } if (displaynum == -1) { for (i = 0; i < ndisplays; i++) { if (displaypoints[i].exp != NULL) { expr_free(displaypoints[i].exp); displaypoints[i].exp = NULL; } } maxdisplays = DISPTAB_DELTA; displaypoints = dbg_heap_realloc(displaypoints, (maxdisplays = DISPTAB_DELTA) * sizeof(*displaypoints)); ndisplays = 0; } else if (displaypoints[--displaynum].exp != NULL) { expr_free(displaypoints[displaynum].exp); displaypoints[displaynum].exp = NULL; while (displaynum == ndisplays - 1 && displaypoints[displaynum].exp == NULL) { --ndisplays; --displaynum; } if (maxdisplays - ndisplays >= 2 * DISPTAB_DELTA) { /* MARK */ maxdisplays = (ndisplays + DISPTAB_DELTA - 1) & ~(DISPTAB_DELTA - 1); displaypoints = dbg_heap_realloc(displaypoints, maxdisplays * sizeof(*displaypoints)); } } return TRUE; } int display_enable(int displaynum, int enable) { char buffer[sizeof(SYMBOL_INFO) + 256]; SYMBOL_INFO* func; func = (SYMBOL_INFO*)buffer; func->SizeOfStruct = sizeof(SYMBOL_INFO); func->MaxNameLen = sizeof(buffer) - sizeof(*func); if (!stack_get_frame(func, NULL)) return FALSE; --displaynum; if (displaynum >= ndisplays || displaynum < 0 || displaypoints[displaynum].exp == NULL) { dbg_printf("Invalid display number\n"); return TRUE; } displaypoints[displaynum].enabled = enable; if (!displaypoints[displaynum].func || cmp_symbol(displaypoints[displaynum].func, func)) { print_one_display(displaynum); } return TRUE; }