display.c 7.86 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4
/*
 * File display.c - display handling for Wine internal debugger.
 *
 * Copyright (C) 1997, Eric Youngdale.
5
 * Copyright (C) 2003, Michal Miroslaw
Alexandre Julliard's avatar
Alexandre Julliard committed
6
 *
7 8 9 10 11 12 13 14 15 16 17 18 19
 * 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
Alexandre Julliard's avatar
Alexandre Julliard committed
20 21 22 23
 */

#include <stdlib.h>
#include <string.h>
24

Alexandre Julliard's avatar
Alexandre Julliard committed
25
#include "debugger.h"
26
#include "wine/debug.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
27

28
WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
Alexandre Julliard's avatar
Alexandre Julliard committed
29

30 31
/* needs to be power of 2, search for MARK to see why :) */
#define DISPTAB_DELTA 8
Alexandre Julliard's avatar
Alexandre Julliard committed
32

33 34 35 36 37 38 39 40
struct display
{
    struct expr*        exp;
    int                 count;
    char                format;
    char                enabled;
    char                func_buffer[sizeof(SYMBOL_INFO) + 256];
    SYMBOL_INFO*        func;
Alexandre Julliard's avatar
Alexandre Julliard committed
41 42
};

43 44 45
static struct display *displaypoints = NULL;
static unsigned int maxdisplays = 0, ndisplays = 0;

46 47
#define OFFSET_OF(_f,_s)        ((unsigned)(&(((_s*)NULL)->_f)))

48
static inline BOOL cmp_symbol(const SYMBOL_INFO* si1, const SYMBOL_INFO* si2)
49
{
50 51 52 53 54 55 56 57
    /* FIXME: !memcmp(si1, si2, sizeof(SYMBOL_INFO) + si1->NameLen)
     * is wrong because sizeof(SYMBOL_INFO) can be aligned on 4-byte boundary
     * Note: we also need to zero out the structures before calling 
     * stack_get_frame, so that un-touched fields by stack_get_frame
     * get the same value!!
     */
    return !memcmp(si1, si2, OFFSET_OF(Name, SYMBOL_INFO)) &&
        !memcmp(si1->Name, si2->Name, si1->NameLen);
58 59
}

60
int display_add(struct expr *exp, int count, char format)
61
{
62
    int         i;
Mike McCormack's avatar
Mike McCormack committed
63
    BOOL local_binding = FALSE;
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78

    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++;

79
    displaypoints[i].exp           = expr_clone(exp, &local_binding);
80 81 82
    displaypoints[i].count         = count;
    displaypoints[i].format        = format;
    displaypoints[i].enabled       = TRUE;
83
    if (local_binding)
84 85
    {
        displaypoints[i].func = (SYMBOL_INFO*)displaypoints[i].func_buffer;
86
        memset(displaypoints[i].func, 0, sizeof(SYMBOL_INFO));
87 88 89
        displaypoints[i].func->SizeOfStruct = sizeof(SYMBOL_INFO);
        displaypoints[i].func->MaxNameLen = sizeof(displaypoints[i].func_buffer) -
            sizeof(*displaypoints[i].func);
90
        if (!stack_get_current_symbol(displaypoints[i].func))
91 92 93 94 95 96 97 98 99
        {
            expr_free(displaypoints[i].exp);
            displaypoints[i].exp = NULL;
            return FALSE;
        }
    }
    else displaypoints[i].func = NULL;

    return TRUE;
100
}
Alexandre Julliard's avatar
Alexandre Julliard committed
101

102
int display_info(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
103
{
104 105 106 107 108 109
    int                 i;
    char                buffer[sizeof(SYMBOL_INFO) + 256];
    SYMBOL_INFO*        func;
    const char*         info;

    func = (SYMBOL_INFO*)buffer;
110
    memset(func, 0, sizeof(SYMBOL_INFO));
111 112
    func->SizeOfStruct = sizeof(SYMBOL_INFO);
    func->MaxNameLen = sizeof(buffer) - sizeof(*func);
113
    if (!stack_get_current_symbol(func)) return FALSE;
114 115 116 117 118

    for (i = 0; i < ndisplays; i++)
    {
        if (displaypoints[i].exp == NULL) continue;

119 120 121
        dbg_printf("%d: ", i + 1);
        expr_print(displaypoints[i].exp);

122 123 124 125 126 127 128 129 130
        if (displaypoints[i].enabled)
        {
            if (displaypoints[i].func && !cmp_symbol(displaypoints[i].func, func))
                info = " (out of scope)";
            else
                info = "";
        }
        else
            info = " (disabled)";
131 132 133
        if (displaypoints[i].func)
            dbg_printf(" in %s", displaypoints[i].func->Name);
        dbg_printf("%s\n", info);
134 135
    }
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
136 137
}

138
static void print_one_display(int i)
Alexandre Julliard's avatar
Alexandre Julliard committed
139
{
140 141 142 143 144
    struct dbg_lvalue   lvalue;

    if (displaypoints[i].enabled) 
    {
        lvalue = expr_eval(displaypoints[i].exp);
145
        if (lvalue.type.id == dbg_itype_none)
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
        {
            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
161
	if (displaypoints[i].format == 'i')
162
            memory_examine(&lvalue, displaypoints[i].count, displaypoints[i].format);
163
	else
164
            print_value(&lvalue, displaypoints[i].format, 0);
165 166
}

167
int display_print(void)
168
{
169 170 171 172 173
    int                 i;
    char                buffer[sizeof(SYMBOL_INFO) + 256];
    SYMBOL_INFO*        func;

    func = (SYMBOL_INFO*)buffer;
174
    memset(func, 0, sizeof(SYMBOL_INFO));
175 176
    func->SizeOfStruct = sizeof(SYMBOL_INFO);
    func->MaxNameLen = sizeof(buffer) - sizeof(*func);
177
    if (!stack_get_current_symbol(func)) return FALSE;
178 179 180 181 182 183 184 185 186 187 188

    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;
Alexandre Julliard's avatar
Alexandre Julliard committed
189 190
}

191
int display_delete(int displaynum)
Alexandre Julliard's avatar
Alexandre Julliard committed
192
{
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
    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;
Alexandre Julliard's avatar
Alexandre Julliard committed
235 236
}

237
int display_enable(int displaynum, int enable)
Alexandre Julliard's avatar
Alexandre Julliard committed
238
{
239 240 241 242
    char                buffer[sizeof(SYMBOL_INFO) + 256];
    SYMBOL_INFO*        func;

    func = (SYMBOL_INFO*)buffer;
243
    memset(func, 0, sizeof(SYMBOL_INFO));
244 245
    func->SizeOfStruct = sizeof(SYMBOL_INFO);
    func->MaxNameLen = sizeof(buffer) - sizeof(*func);
246
    if (!stack_get_current_symbol(func)) return FALSE;
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263

    --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;
Alexandre Julliard's avatar
Alexandre Julliard committed
264
}