display.c 7.74 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
 * 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
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 26
#include "debugger.h"

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

30 31 32 33 34 35 36 37
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
38 39
};

40 41 42
static struct display *displaypoints = NULL;
static unsigned int maxdisplays = 0, ndisplays = 0;

43
static inline BOOL cmp_symbol(const SYMBOL_INFO* si1, const SYMBOL_INFO* si2)
44
{
45 46 47 48 49 50
    /* 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!!
     */
51
    return !memcmp(si1, si2, FIELD_OFFSET(SYMBOL_INFO, Name)) &&
52
        !memcmp(si1->Name, si2->Name, si1->NameLen);
53 54
}

55
int display_add(struct expr *exp, int count, char format)
56
{
57
    unsigned i;
Mike McCormack's avatar
Mike McCormack committed
58
    BOOL local_binding = FALSE;
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73

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

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

    return TRUE;
95
}
Alexandre Julliard's avatar
Alexandre Julliard committed
96

97
int display_info(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
98
{
99
    unsigned            i;
100 101 102 103 104
    char                buffer[sizeof(SYMBOL_INFO) + 256];
    SYMBOL_INFO*        func;
    const char*         info;

    func = (SYMBOL_INFO*)buffer;
105
    memset(func, 0, sizeof(SYMBOL_INFO));
106 107
    func->SizeOfStruct = sizeof(SYMBOL_INFO);
    func->MaxNameLen = sizeof(buffer) - sizeof(*func);
108
    if (!stack_get_current_symbol(func)) return FALSE;
109 110 111 112 113

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

114 115 116
        dbg_printf("%d: ", i + 1);
        expr_print(displaypoints[i].exp);

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

133
static void print_one_display(int i)
Alexandre Julliard's avatar
Alexandre Julliard committed
134
{
135 136 137 138 139
    struct dbg_lvalue   lvalue;

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

162
int display_print(void)
163
{
164
    unsigned            i;
165 166 167 168
    char                buffer[sizeof(SYMBOL_INFO) + 256];
    SYMBOL_INFO*        func;

    func = (SYMBOL_INFO*)buffer;
169
    memset(func, 0, sizeof(SYMBOL_INFO));
170 171
    func->SizeOfStruct = sizeof(SYMBOL_INFO);
    func->MaxNameLen = sizeof(buffer) - sizeof(*func);
172
    if (!stack_get_current_symbol(func)) return FALSE;
173 174 175 176 177 178 179 180 181 182 183

    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
184 185
}

186
int display_delete(int displaynum)
Alexandre Julliard's avatar
Alexandre Julliard committed
187
{
188 189 190 191 192 193 194 195 196
    if (displaynum > ndisplays || displaynum == 0 || displaynum < -1 ||
        displaypoints[displaynum - 1].exp == NULL)
    {
        dbg_printf("Invalid display number\n");
        return TRUE;
    }

    if (displaynum == -1)
    {
197 198
        unsigned i;

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
        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
230 231
}

232
int display_enable(int displaynum, int enable)
Alexandre Julliard's avatar
Alexandre Julliard committed
233
{
234 235 236 237
    char                buffer[sizeof(SYMBOL_INFO) + 256];
    SYMBOL_INFO*        func;

    func = (SYMBOL_INFO*)buffer;
238
    memset(func, 0, sizeof(SYMBOL_INFO));
239 240
    func->SizeOfStruct = sizeof(SYMBOL_INFO);
    func->MaxNameLen = sizeof(buffer) - sizeof(*func);
241
    if (!stack_get_current_symbol(func)) return FALSE;
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258

    --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
259
}