blob: a76d6322b0b3d30b583df1230a2dc933b51056a3 [file] [log] [blame]
Alexandre Julliardf0b23541993-09-29 12:21:49 +00001/*
2 * File hash.c - generate hash tables for Wine debugger symbols
3 *
4 * Copyright (C) 1993, Eric Youngdale.
5 */
6
7
Marcus Meissnerb0d52b01999-02-28 19:59:00 +00008#include "config.h"
Alexandre Julliardf0b23541993-09-29 12:21:49 +00009#include <stdlib.h>
10#include <stdio.h>
11#include <string.h>
Alexandre Julliardc6c09441997-01-12 18:32:19 +000012#include <limits.h>
Alexandre Julliardf0b23541993-09-29 12:21:49 +000013#include <sys/types.h>
Alexandre Julliard808cb041995-08-17 17:11:36 +000014#include "debugger.h"
Alexandre Julliardf0b23541993-09-29 12:21:49 +000015
Alexandre Julliardc6c09441997-01-12 18:32:19 +000016#define NR_NAME_HASH 16384
Alexandre Julliard01d63461997-01-20 19:43:45 +000017#ifndef PATH_MAX
18#define PATH_MAX _MAX_PATH
19#endif
Alexandre Julliardc6c09441997-01-12 18:32:19 +000020
Ulrich Weigandb3ec4b91999-11-13 20:58:45 +000021#ifdef __i386__
Alexandre Julliardc6c09441997-01-12 18:32:19 +000022static char * reg_name[] =
23{
24 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
25};
26
Ove Kaaveneee1ddc1998-12-07 12:09:55 +000027static unsigned reg_ofs[] =
28{
29 FIELD_OFFSET(CONTEXT, Eax), FIELD_OFFSET(CONTEXT, Ecx),
30 FIELD_OFFSET(CONTEXT, Edx), FIELD_OFFSET(CONTEXT, Ebx),
31 FIELD_OFFSET(CONTEXT, Esp), FIELD_OFFSET(CONTEXT, Ebp),
32 FIELD_OFFSET(CONTEXT, Esi), FIELD_OFFSET(CONTEXT, Edi)
33};
Ulrich Weigandb3ec4b91999-11-13 20:58:45 +000034#else
35static char * reg_name[] = { NULL }; /* FIXME */
36static unsigned reg_ofs[] = { 0 };
37#endif
Ove Kaaveneee1ddc1998-12-07 12:09:55 +000038
Alexandre Julliardc6c09441997-01-12 18:32:19 +000039
40struct name_hash
41{
42 struct name_hash * next; /* Used to look up within name hash */
43 char * name;
44 char * sourcefile;
45
46 int n_locals;
47 int locals_alloc;
48 WineLocals * local_vars;
49
50 int n_lines;
51 int lines_alloc;
52 WineLineNo * linetab;
53
Eric Pouechd33bcb62000-03-15 19:57:20 +000054 DBG_VALUE value;
Alexandre Julliardc6c09441997-01-12 18:32:19 +000055 unsigned short flags;
56 unsigned short breakpoint_offset;
57 unsigned int symbol_size;
58};
59
60
Eric Pouechd33bcb62000-03-15 19:57:20 +000061static BOOL DEBUG_GetStackSymbolValue( const char * name, DBG_VALUE *value );
Alexandre Julliardc6c09441997-01-12 18:32:19 +000062static int sortlist_valid = FALSE;
63
64static int sorttab_nsym;
65static struct name_hash ** addr_sorttab = NULL;
Alexandre Julliardf0b23541993-09-29 12:21:49 +000066
Alexandre Julliardd90840e1996-06-11 16:02:08 +000067static struct name_hash * name_hash_table[NR_NAME_HASH];
Alexandre Julliardf0b23541993-09-29 12:21:49 +000068
Alexandre Julliard808cb041995-08-17 17:11:36 +000069static unsigned int name_hash( const char * name )
Alexandre Julliard2787be81995-05-22 18:23:01 +000070{
Alexandre Julliard808cb041995-08-17 17:11:36 +000071 unsigned int hash = 0;
Alexandre Julliardc6c09441997-01-12 18:32:19 +000072 unsigned int tmp;
Alexandre Julliard808cb041995-08-17 17:11:36 +000073 const char * p;
Alexandre Julliardf0b23541993-09-29 12:21:49 +000074
Alexandre Julliard808cb041995-08-17 17:11:36 +000075 p = name;
Alexandre Julliardf0b23541993-09-29 12:21:49 +000076
Alexandre Julliardc6c09441997-01-12 18:32:19 +000077 while (*p)
78 {
79 hash = (hash << 4) + *p++;
80
81 if( (tmp = (hash & 0xf0000000)) )
82 {
83 hash ^= tmp >> 24;
84 }
85 hash &= ~tmp;
86 }
Alexandre Julliard808cb041995-08-17 17:11:36 +000087 return hash % NR_NAME_HASH;
Alexandre Julliardf0b23541993-09-29 12:21:49 +000088}
89
Alexandre Julliardc6c09441997-01-12 18:32:19 +000090int
91DEBUG_cmp_sym(const void * p1, const void * p2)
92{
93 struct name_hash ** name1 = (struct name_hash **) p1;
94 struct name_hash ** name2 = (struct name_hash **) p2;
95
96 if( ((*name1)->flags & SYM_INVALID) != 0 )
97 {
98 return -1;
99 }
100
101 if( ((*name2)->flags & SYM_INVALID) != 0 )
102 {
103 return 1;
104 }
105
Eric Pouechd33bcb62000-03-15 19:57:20 +0000106 if( (*name1)->value.addr.seg > (*name2)->value.addr.seg )
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000107 {
108 return 1;
109 }
110
Eric Pouechd33bcb62000-03-15 19:57:20 +0000111 if( (*name1)->value.addr.seg < (*name2)->value.addr.seg )
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000112 {
113 return -1;
114 }
115
Eric Pouechd33bcb62000-03-15 19:57:20 +0000116 if( (*name1)->value.addr.off > (*name2)->value.addr.off )
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000117 {
118 return 1;
119 }
120
Eric Pouechd33bcb62000-03-15 19:57:20 +0000121 if( (*name1)->value.addr.off < (*name2)->value.addr.off )
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000122 {
123 return -1;
124 }
125
126 return 0;
127}
128
129/***********************************************************************
130 * DEBUG_ResortSymbols
131 *
132 * Rebuild sorted list of symbols.
133 */
134static
135void
Eric Pouechd33bcb62000-03-15 19:57:20 +0000136DEBUG_ResortSymbols(void)
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000137{
138 struct name_hash *nh;
139 int nsym = 0;
140 int i;
141
142 for(i=0; i<NR_NAME_HASH; i++)
143 {
144 for (nh = name_hash_table[i]; nh; nh = nh->next)
145 {
Eric Pouech9bd9b821999-08-21 12:53:49 +0000146 if( (nh->flags & SYM_INVALID) == 0 )
147 nsym++;
148 else
Eric Poueche5efa0c2000-04-13 19:31:58 +0000149 DEBUG_Printf( DBG_CHN_MESG, "Symbol %s is invalid\n", nh->name );
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000150 }
151 }
152
153 sorttab_nsym = nsym;
154 if( nsym == 0 )
155 {
156 return;
157 }
158
Ove Kaavendda17c61999-04-25 12:24:42 +0000159 addr_sorttab = (struct name_hash **) DBG_realloc(addr_sorttab,
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000160 nsym * sizeof(struct name_hash *));
161
162 nsym = 0;
163 for(i=0; i<NR_NAME_HASH; i++)
164 {
165 for (nh = name_hash_table[i]; nh; nh = nh->next)
166 {
Eric Pouech9bd9b821999-08-21 12:53:49 +0000167 if( (nh->flags & SYM_INVALID) == 0 )
168 addr_sorttab[nsym++] = nh;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000169 }
170 }
171
172 qsort(addr_sorttab, nsym,
173 sizeof(struct name_hash *), DEBUG_cmp_sym);
174 sortlist_valid = TRUE;
175
176}
Alexandre Julliard808cb041995-08-17 17:11:36 +0000177
178/***********************************************************************
179 * DEBUG_AddSymbol
180 *
181 * Add a symbol to the table.
182 */
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000183struct name_hash *
Eric Pouech52c75342001-05-03 18:32:47 +0000184DEBUG_AddSymbol( const char * name, const DBG_VALUE *value,
185 const char * source, int flags)
Alexandre Julliard2787be81995-05-22 18:23:01 +0000186{
Alexandre Julliard808cb041995-08-17 17:11:36 +0000187 struct name_hash * new;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000188 struct name_hash *nh;
189 static char prev_source[PATH_MAX] = {'\0', };
190 static char * prev_duped_source = NULL;
Alexandre Julliard808cb041995-08-17 17:11:36 +0000191 int hash;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000192
Eric Pouechd33bcb62000-03-15 19:57:20 +0000193 assert(value->cookie == DV_TARGET || value->cookie == DV_HOST);
194
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000195 hash = name_hash(name);
196 for (nh = name_hash_table[hash]; nh; nh = nh->next)
197 {
198 if( ((nh->flags & SYM_INVALID) != 0) && strcmp(name, nh->name) == 0 )
199 {
Eric Poueche5efa0c2000-04-13 19:31:58 +0000200#if 0
201 DEBUG_Printf(DBG_CHN_MESG, "Changing address for symbol %s (%08lx:%08lx => %08lx:%08lx)\n",
202 name, nh->value.addr.seg, nh->value.addr.off, value->addr.seg, value->addr.off);
203#endif
Eric Pouechd33bcb62000-03-15 19:57:20 +0000204 nh->value.addr = value->addr;
Eric Pouechd33bcb62000-03-15 19:57:20 +0000205 if( nh->value.type == NULL && value->type != NULL )
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000206 {
Eric Pouechd33bcb62000-03-15 19:57:20 +0000207 nh->value.type = value->type;
208 nh->value.cookie = value->cookie;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000209 }
Eric Pouech9bd9b821999-08-21 12:53:49 +0000210 /* it may happen that the same symbol is defined in several compilation
211 * units, but the linker decides to merge it into a single instance.
212 * in that case, we don't clear the invalid flag for all the compilation
213 * units (N_GSYM), and wait to get the symbol from the symtab
214 */
215 if ((flags & SYM_INVALID) == 0)
216 nh->flags &= ~SYM_INVALID;
Eric Pouechd33bcb62000-03-15 19:57:20 +0000217
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000218 return nh;
219 }
Eric Pouechd33bcb62000-03-15 19:57:20 +0000220 if (nh->value.addr.seg == value->addr.seg &&
221 nh->value.addr.off == value->addr.off &&
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000222 strcmp(name, nh->name) == 0 )
223 {
224 return nh;
225 }
226 }
227
Eric Poueche5efa0c2000-04-13 19:31:58 +0000228#if 0
229 DEBUG_Printf(DBG_CHN_TRACE, "adding symbol (%s) from file '%s' at 0x%04lx:%08lx\n",
230 name, source, value->addr.seg, value->addr.off);
231#endif
232
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000233 /*
234 * First see if we already have an entry for this symbol. If so
235 * return it, so we don't end up with duplicates.
236 */
237
Ove Kaavendda17c61999-04-25 12:24:42 +0000238 new = (struct name_hash *) DBG_alloc(sizeof(struct name_hash));
Eric Pouechd33bcb62000-03-15 19:57:20 +0000239 new->value = *value;
Ove Kaavendda17c61999-04-25 12:24:42 +0000240 new->name = DBG_strdup(name);
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000241
242 if( source != NULL )
243 {
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000244 /*
245 * This is an enhancement to reduce memory consumption. The idea
246 * is that we duplicate a given string only once. This is a big
247 * win if there are lots of symbols defined in a given source file.
248 */
249 if( strcmp(source, prev_source) == 0 )
250 {
251 new->sourcefile = prev_duped_source;
252 }
253 else
254 {
255 strcpy(prev_source, source);
Ove Kaavendda17c61999-04-25 12:24:42 +0000256 prev_duped_source = new->sourcefile = DBG_strdup(source);
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000257 }
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000258 }
259 else
260 {
261 new->sourcefile = NULL;
262 }
263
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000264 new->n_lines = 0;
265 new->lines_alloc = 0;
266 new->linetab = NULL;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000267
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000268 new->n_locals = 0;
269 new->locals_alloc = 0;
270 new->local_vars = NULL;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000271
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000272 new->flags = flags;
273 new->next = NULL;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000274
Alexandre Julliard808cb041995-08-17 17:11:36 +0000275 /* Now insert into the hash table */
276 new->next = name_hash_table[hash];
277 name_hash_table[hash] = new;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000278
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000279 /*
280 * Check some heuristics based upon the file name to see whether
281 * we want to step through this guy or not. These are machine generated
282 * assembly files that are used to translate between the MS way of
283 * calling things and the GCC way of calling things. In general we
284 * always want to step through.
285 */
Eric Pouech52c75342001-05-03 18:32:47 +0000286 if ( source != NULL ) {
287 int len = strlen(source);
288
289 if (len > 2 && source[len-2] == '.' && source[len-1] == 's') {
290 char* c = strrchr(source - 2, '/');
291 if (c != NULL) {
292 if (strcmp(c + 1, "asmrelay.s") == 0)
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000293 new->flags |= SYM_TRAMPOLINE;
Eric Pouech52c75342001-05-03 18:32:47 +0000294 }
295 }
296 }
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000297
298 sortlist_valid = FALSE;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000299 return new;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000300}
301
Alexandre Julliarda3960291999-02-26 11:11:13 +0000302BOOL DEBUG_Normalize(struct name_hash * nh )
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000303{
304
305 /*
306 * We aren't adding any more locals or linenumbers to this function.
307 * Free any spare memory that we might have allocated.
308 */
309 if( nh == NULL )
310 {
311 return TRUE;
312 }
313
314 if( nh->n_locals != nh->locals_alloc )
315 {
316 nh->locals_alloc = nh->n_locals;
Ove Kaavendda17c61999-04-25 12:24:42 +0000317 nh->local_vars = DBG_realloc(nh->local_vars,
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000318 nh->locals_alloc * sizeof(WineLocals));
319 }
320
321 if( nh->n_lines != nh->lines_alloc )
322 {
323 nh->lines_alloc = nh->n_lines;
Ove Kaavendda17c61999-04-25 12:24:42 +0000324 nh->linetab = DBG_realloc(nh->linetab,
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000325 nh->lines_alloc * sizeof(WineLineNo));
326 }
327
328 return TRUE;
329}
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000330
Alexandre Julliard808cb041995-08-17 17:11:36 +0000331/***********************************************************************
332 * DEBUG_GetSymbolValue
333 *
334 * Get the address of a named symbol.
335 */
Eric Pouech52c75342001-05-03 18:32:47 +0000336static int DEBUG_GSV_Helper(const char* name, const int lineno,
337 DBG_VALUE* value, int num, int bp_flag)
Alexandre Julliard2787be81995-05-22 18:23:01 +0000338{
Eric Pouech52c75342001-05-03 18:32:47 +0000339 struct name_hash* nh;
340 int i = 0;
341 DBG_ADDR addr;
Alexandre Julliardf0b23541993-09-29 12:21:49 +0000342
Eric Pouech52c75342001-05-03 18:32:47 +0000343 for (nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
344 {
345 if ((nh->flags & SYM_INVALID) != 0) continue;
346 if (!strcmp(nh->name, name) && DEBUG_GetLineNumberAddr( nh, lineno, &addr, bp_flag ))
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000347 {
Eric Pouech52c75342001-05-03 18:32:47 +0000348 if (i >= num) return num + 1;
349 value[i].addr = addr;
350 value[i].type = nh->value.type;
351 value[i].cookie = nh->value.cookie;
352 i++;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000353 }
Eric Pouech52c75342001-05-03 18:32:47 +0000354 }
355 return i;
356}
Alexandre Julliard2787be81995-05-22 18:23:01 +0000357
Eric Pouech52c75342001-05-03 18:32:47 +0000358BOOL DEBUG_GetSymbolValue( const char * name, const int lineno,
359 DBG_VALUE *rtn, int bp_flag )
360{
361#define NUMDBGV 10
362 /* FIXME: NUMDBGV should be made variable */
363 DBG_VALUE value[NUMDBGV];
364 DBG_VALUE vtmp;
365 int num, i;
366
367 num = DEBUG_GSV_Helper(name, lineno, value, NUMDBGV, bp_flag);
368 if (!num && (name[0] != '_'))
369 {
370 char buffer[256];
Eric Poueche9392062000-11-15 22:16:26 +0000371
Eric Pouech52c75342001-05-03 18:32:47 +0000372 assert(strlen(name) < sizeof(buffer) - 2); /* one for '_', one for '\0' */
373 buffer[0] = '_';
374 strcpy(buffer + 1, name);
375 num = DEBUG_GSV_Helper(buffer, lineno, value, NUMDBGV, bp_flag);
376 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000377
Eric Pouech52c75342001-05-03 18:32:47 +0000378 /* now get the local symbols if any */
379 if (DEBUG_GetStackSymbolValue(name, &vtmp) && num < NUMDBGV)
380 {
381 value[num] = vtmp;
382 num++;
383 }
384
385 if (num == 0) {
386 return FALSE;
387 } else if (!DEBUG_interactiveP || num == 1) {
388 i = 0;
389 } else {
390 char* ptr;
391 if (num == NUMDBGV+1) {
392 DEBUG_Printf(DBG_CHN_MESG, "Too many addresses for symbol '%s', limiting the first %d\n", name, NUMDBGV);
393 num = NUMDBGV;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000394 }
Eric Pouech52c75342001-05-03 18:32:47 +0000395 DEBUG_Printf(DBG_CHN_MESG, "Many symbols with name '%s', choose the one you want (<cr> to abort):\n", name);
396 for (i = 0; i < num; i++) {
397 DEBUG_Printf(DBG_CHN_MESG, "[%d]: ", i + 1);
398 DEBUG_PrintAddress( &value[i].addr, DEBUG_GetSelectorType(value[i].addr.seg), TRUE);
399 DEBUG_Printf(DBG_CHN_MESG, "\n");
400 }
401 do {
402 ptr = readline("=> ");
403 if (!*ptr) return FALSE;
404 i = atoi(ptr);
James Juran4ee31d52001-05-19 17:34:17 +0000405 if (i < 1 || i > num)
406 DEBUG_Printf(DBG_CHN_MESG, "Invalid choice %d\n", i);
407 } while (i < 1 || i > num);
408
409 /* The array is 0-based, but the choices are 1..n, so we have to subtract one before returning. */
410 i--;
Eric Pouech52c75342001-05-03 18:32:47 +0000411 }
412 *rtn = value[i];
413 return TRUE;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000414}
415
416/***********************************************************************
417 * DEBUG_GetLineNumberAddr
418 *
419 * Get the address of a named symbol.
420 */
Eric Poueche9392062000-11-15 22:16:26 +0000421BOOL DEBUG_GetLineNumberAddr( const struct name_hash * nh, const int lineno,
Eric Pouechd33bcb62000-03-15 19:57:20 +0000422 DBG_ADDR *addr, int bp_flag )
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000423{
424 int i;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000425
426 if( lineno == -1 )
427 {
Eric Pouechd33bcb62000-03-15 19:57:20 +0000428 *addr = nh->value.addr;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000429 if( bp_flag )
430 {
431 addr->off += nh->breakpoint_offset;
432 }
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000433 }
434 else
435 {
436 /*
437 * Search for the specific line number. If we don't find it,
438 * then return FALSE.
439 */
440 if( nh->linetab == NULL )
441 {
442 return FALSE;
443 }
444
445 for(i=0; i < nh->n_lines; i++ )
446 {
447 if( nh->linetab[i].line_number == lineno )
448 {
449 *addr = nh->linetab[i].pc_offset;
450 return TRUE;
451 }
452 }
453
454 /*
455 * This specific line number not found.
456 */
457 return FALSE;
458 }
459
Alexandre Julliard808cb041995-08-17 17:11:36 +0000460 return TRUE;
461}
Alexandre Julliard2787be81995-05-22 18:23:01 +0000462
Alexandre Julliard808cb041995-08-17 17:11:36 +0000463
464/***********************************************************************
465 * DEBUG_SetSymbolValue
466 *
467 * Set the address of a named symbol.
468 */
Eric Pouechd33bcb62000-03-15 19:57:20 +0000469BOOL DEBUG_SetSymbolValue( const char * name, const DBG_VALUE *value )
Alexandre Julliard808cb041995-08-17 17:11:36 +0000470{
471 char buffer[256];
472 struct name_hash *nh;
473
Eric Pouechd33bcb62000-03-15 19:57:20 +0000474 assert(value->cookie == DV_TARGET || value->cookie == DV_HOST);
475
Alexandre Julliard808cb041995-08-17 17:11:36 +0000476 for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
477 if (!strcmp(nh->name, name)) break;
478
479 if (!nh && (name[0] != '_'))
Alexandre Julliard2787be81995-05-22 18:23:01 +0000480 {
Alexandre Julliard808cb041995-08-17 17:11:36 +0000481 buffer[0] = '_';
482 strcpy(buffer+1, name);
483 for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
484 if (!strcmp(nh->name, buffer)) break;
485 }
486
487 if (!nh) return FALSE;
Eric Pouechd33bcb62000-03-15 19:57:20 +0000488 nh->value = *value;
489 nh->flags &= ~SYM_INVALID;
Ulrich Weigand1cbf27a2000-06-04 01:33:21 +0000490
491#ifdef __i386__
Eric Pouechd33bcb62000-03-15 19:57:20 +0000492 DEBUG_FixAddress( &nh->value.addr, DEBUG_context.SegDs );
Ulrich Weigand1cbf27a2000-06-04 01:33:21 +0000493#endif
494
Alexandre Julliard808cb041995-08-17 17:11:36 +0000495 return TRUE;
496}
497
498
499/***********************************************************************
500 * DEBUG_FindNearestSymbol
501 *
502 * Find the symbol nearest to a given address.
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000503 * If ebp is specified as non-zero, it means we should dump the argument
504 * list into the string we return as well.
Alexandre Julliard808cb041995-08-17 17:11:36 +0000505 */
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000506const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag,
507 struct name_hash ** rtn,
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000508 unsigned int ebp,
509 struct list_id * source)
Alexandre Julliard808cb041995-08-17 17:11:36 +0000510{
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000511 static char name_buffer[MAX_PATH + 256];
512 static char arglist[1024];
513 static char argtmp[256];
Alexandre Julliard808cb041995-08-17 17:11:36 +0000514 struct name_hash * nearest = NULL;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000515 int mid, high, low;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000516 unsigned int * ptr;
517 int lineno;
518 char * lineinfo, *sourcefile;
Alexandre Julliard808cb041995-08-17 17:11:36 +0000519 int i;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000520 char linebuff[16];
Eric Pouech527eea92000-03-08 16:44:54 +0000521 unsigned val;
Eric Pouech52c75342001-05-03 18:32:47 +0000522 DBG_MODULE* module;
523 char modbuf[256];
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000524
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000525 if( rtn != NULL )
526 {
527 *rtn = NULL;
528 }
Alexandre Julliard808cb041995-08-17 17:11:36 +0000529
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000530 if( source != NULL )
531 {
532 source->sourcefile = NULL;
533 source->line = -1;
534 }
535
536 if( sortlist_valid == FALSE )
537 {
538 DEBUG_ResortSymbols();
539 }
540
541 if( sortlist_valid == FALSE )
542 {
543 return NULL;
544 }
545
546 /*
547 * FIXME - use the binary search that we added to
548 * the function DEBUG_CheckLinenoStatus. Better yet, we should
549 * probably keep some notion of the current function so we don't
550 * have to search every time.
551 */
552 /*
553 * Binary search to find closest symbol.
554 */
555 low = 0;
556 high = sorttab_nsym;
Eric Pouechd33bcb62000-03-15 19:57:20 +0000557 if( addr_sorttab[0]->value.addr.seg > addr->seg
558 || ( addr_sorttab[0]->value.addr.seg == addr->seg
559 && addr_sorttab[0]->value.addr.off > addr->off) )
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000560 {
561 nearest = NULL;
562 }
Eric Pouechd33bcb62000-03-15 19:57:20 +0000563 else if( addr_sorttab[high - 1]->value.addr.seg < addr->seg
564 || ( addr_sorttab[high - 1]->value.addr.seg == addr->seg
565 && addr_sorttab[high - 1]->value.addr.off < addr->off) )
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000566 {
567 nearest = addr_sorttab[high - 1];
568 }
569 else
570 {
571 while(1==1)
572 {
573 mid = (high + low)/2;
574 if( mid == low )
575 {
576 /*
577 * See if there are any other entries that might also
578 * have the same address, and would also have a line
579 * number table.
580 */
581 if( mid > 0 && addr_sorttab[mid]->linetab == NULL )
582 {
Eric Pouechd33bcb62000-03-15 19:57:20 +0000583 if( (addr_sorttab[mid - 1]->value.addr.seg ==
584 addr_sorttab[mid]->value.addr.seg)
585 && (addr_sorttab[mid - 1]->value.addr.off ==
586 addr_sorttab[mid]->value.addr.off)
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000587 && (addr_sorttab[mid - 1]->linetab != NULL) )
588 {
589 mid--;
590 }
591 }
592
593 if( (mid < sorttab_nsym - 1)
594 && (addr_sorttab[mid]->linetab == NULL) )
595 {
Eric Pouechd33bcb62000-03-15 19:57:20 +0000596 if( (addr_sorttab[mid + 1]->value.addr.seg ==
597 addr_sorttab[mid]->value.addr.seg)
598 && (addr_sorttab[mid + 1]->value.addr.off ==
599 addr_sorttab[mid]->value.addr.off)
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000600 && (addr_sorttab[mid + 1]->linetab != NULL) )
601 {
602 mid++;
603 }
604 }
605 nearest = addr_sorttab[mid];
606#if 0
Eric Poueche5efa0c2000-04-13 19:31:58 +0000607 DEBUG_Printf(DBG_CHN_MESG, "Found %x:%x when looking for %x:%x %x %s\n",
608 addr_sorttab[mid ]->value.addr.seg,
609 addr_sorttab[mid ]->value.addr.off,
610 addr->seg, addr->off,
611 addr_sorttab[mid ]->linetab,
612 addr_sorttab[mid ]->name);
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000613#endif
614 break;
615 }
Eric Pouechd33bcb62000-03-15 19:57:20 +0000616 if( (addr_sorttab[mid]->value.addr.seg < addr->seg)
617 || ( addr_sorttab[mid]->value.addr.seg == addr->seg
618 && addr_sorttab[mid]->value.addr.off <= addr->off) )
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000619 {
620 low = mid;
621 }
622 else
623 {
624 high = mid;
625 }
626 }
627 }
628
Alexandre Julliard808cb041995-08-17 17:11:36 +0000629 if (!nearest) return NULL;
630
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000631 if( rtn != NULL )
632 {
633 *rtn = nearest;
634 }
635
636 /*
637 * Fill in the relevant bits to the structure so that we can
638 * locate the source and line for this bit of code.
639 */
640 if( source != NULL )
641 {
642 source->sourcefile = nearest->sourcefile;
643 if( nearest->linetab == NULL )
644 {
645 source->line = -1;
646 }
647 else
648 {
649 source->line = nearest->linetab[0].line_number;
650 }
651 }
652
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000653 lineinfo = "";
654 lineno = -1;
655
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000656 /*
657 * Prepare to display the argument list. If ebp is specified, it is
658 * the framepointer for the function in question. If not specified,
659 * we don't want the arglist.
660 */
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000661 memset(arglist, '\0', sizeof(arglist));
662 if( ebp != 0 )
663 {
664 for(i=0; i < nearest->n_locals; i++ )
665 {
666 /*
667 * If this is a register (offset == 0) or a local
668 * variable, we don't want to know about it.
669 */
670 if( nearest->local_vars[i].offset <= 0 )
671 {
672 continue;
673 }
674
675 ptr = (unsigned int *) (ebp + nearest->local_vars[i].offset);
676 if( arglist[0] == '\0' )
677 {
678 arglist[0] = '(';
679 }
680 else
681 {
682 strcat(arglist, ", ");
683 }
Eric Pouech527eea92000-03-08 16:44:54 +0000684 DEBUG_READ_MEM_VERBOSE(ptr, &val, sizeof(val));
685 sprintf(argtmp, "%s=0x%x", nearest->local_vars[i].name, val);
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000686
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000687 strcat(arglist, argtmp);
688 }
689 if( arglist[0] == '(' )
690 {
691 strcat(arglist, ")");
692 }
693 }
694
Eric Pouech52c75342001-05-03 18:32:47 +0000695 module = DEBUG_FindModuleByAddr((void*)DEBUG_ToLinear(addr), DMT_UNKNOWN);
696 if (module) {
697 char* ptr = strrchr(module->module_name, '/');
698
699 if (!ptr++) ptr = module->module_name;
700 sprintf( modbuf, " in %s", ptr);
701 }
702 else
703 modbuf[0] = '\0';
704
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000705 if( (nearest->sourcefile != NULL) && (flag == TRUE)
Eric Pouechd33bcb62000-03-15 19:57:20 +0000706 && (addr->off - nearest->value.addr.off < 0x100000) )
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000707 {
708
709 /*
710 * Try and find the nearest line number to the current offset.
711 */
712 if( nearest->linetab != NULL )
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000713 {
714 low = 0;
715 high = nearest->n_lines;
716 while ((high - low) > 1)
717 {
718 mid = (high + low) / 2;
719 if (addr->off < nearest->linetab[mid].pc_offset.off)
720 high = mid;
721 else
722 low = mid;
723 }
724 lineno = nearest->linetab[low].line_number;
725 }
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000726
727 if( lineno != -1 )
728 {
729 sprintf(linebuff, ":%d", lineno);
730 lineinfo = linebuff;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000731 if( source != NULL )
732 {
733 source->line = lineno;
734 }
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000735 }
736
737 /* Remove the path from the file name */
738 sourcefile = strrchr( nearest->sourcefile, '/' );
739 if (!sourcefile) sourcefile = nearest->sourcefile;
740 else sourcefile++;
Eric Pouech52c75342001-05-03 18:32:47 +0000741
Eric Pouechd33bcb62000-03-15 19:57:20 +0000742 if (addr->off == nearest->value.addr.off)
Eric Pouech52c75342001-05-03 18:32:47 +0000743 sprintf( name_buffer, "%s%s [%s%s]%s", nearest->name,
744 arglist, sourcefile, lineinfo, modbuf);
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000745 else
Eric Pouech52c75342001-05-03 18:32:47 +0000746 sprintf( name_buffer, "%s+0x%lx%s [%s%s]%s", nearest->name,
Eric Pouechd33bcb62000-03-15 19:57:20 +0000747 addr->off - nearest->value.addr.off,
Eric Pouech52c75342001-05-03 18:32:47 +0000748 arglist, sourcefile, lineinfo, modbuf );
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000749 }
Alexandre Julliard808cb041995-08-17 17:11:36 +0000750 else
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000751 {
Eric Pouechd33bcb62000-03-15 19:57:20 +0000752 if (addr->off == nearest->value.addr.off)
Eric Pouech52c75342001-05-03 18:32:47 +0000753 sprintf( name_buffer, "%s%s%s", nearest->name, arglist, modbuf);
Alexandre Julliard491502b1997-11-01 19:08:16 +0000754 else {
Eric Pouechd33bcb62000-03-15 19:57:20 +0000755 if (addr->seg && (nearest->value.addr.seg!=addr->seg))
Alexandre Julliard491502b1997-11-01 19:08:16 +0000756 return NULL;
757 else
Eric Pouech52c75342001-05-03 18:32:47 +0000758 sprintf( name_buffer, "%s+0x%lx%s%s", nearest->name,
759 addr->off - nearest->value.addr.off, arglist, modbuf);
Alexandre Julliard491502b1997-11-01 19:08:16 +0000760 }
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000761 }
Alexandre Julliard808cb041995-08-17 17:11:36 +0000762 return name_buffer;
763}
764
765
766/***********************************************************************
767 * DEBUG_ReadSymbolTable
768 *
769 * Read a symbol file into the hash table.
770 */
Eric Pouech52c75342001-05-03 18:32:47 +0000771void DEBUG_ReadSymbolTable( const char* filename )
Alexandre Julliard808cb041995-08-17 17:11:36 +0000772{
773 FILE * symbolfile;
Eric Pouechd33bcb62000-03-15 19:57:20 +0000774 DBG_VALUE value;
Alexandre Julliard808cb041995-08-17 17:11:36 +0000775 char type;
776 char * cpnt;
777 char buffer[256];
778 char name[256];
779
780 if (!(symbolfile = fopen(filename, "r")))
781 {
Eric Poueche5efa0c2000-04-13 19:31:58 +0000782 DEBUG_Printf( DBG_CHN_WARN, "Unable to open symbol table %s\n", filename );
Alexandre Julliard808cb041995-08-17 17:11:36 +0000783 return;
784 }
785
Eric Poueche5efa0c2000-04-13 19:31:58 +0000786 DEBUG_Printf( DBG_CHN_MESG, "Reading symbols from file %s\n", filename );
Alexandre Julliard808cb041995-08-17 17:11:36 +0000787
Eric Pouechd33bcb62000-03-15 19:57:20 +0000788 value.type = NULL;
789 value.addr.seg = 0;
790 value.addr.off = 0;
791 value.cookie = DV_TARGET;
792
Alexandre Julliard808cb041995-08-17 17:11:36 +0000793 while (1)
794 {
795 fgets( buffer, sizeof(buffer), symbolfile );
796 if (feof(symbolfile)) break;
797
798 /* Strip any text after a # sign (i.e. comments) */
799 cpnt = buffer;
800 while (*cpnt)
801 if(*cpnt++ == '#') { *cpnt = 0; break; }
802
803 /* Quietly ignore any lines that have just whitespace */
804 cpnt = buffer;
805 while(*cpnt)
806 {
807 if(*cpnt != ' ' && *cpnt != '\t') break;
808 cpnt++;
809 }
810 if (!(*cpnt) || *cpnt == '\n') continue;
811
Eric Poueche5efa0c2000-04-13 19:31:58 +0000812 if (sscanf(buffer, "%lx %c %s", &value.addr.off, &type, name) == 3)
813 DEBUG_AddSymbol( name, &value, NULL, SYM_WINE );
Alexandre Julliard808cb041995-08-17 17:11:36 +0000814 }
815 fclose(symbolfile);
816}
817
818
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000819void
820DEBUG_AddLineNumber( struct name_hash * func, int line_num,
821 unsigned long offset )
822{
823 if( func == NULL )
824 {
825 return;
826 }
827
828 if( func->n_lines + 1 >= func->lines_alloc )
829 {
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000830 func->lines_alloc += 64;
Ove Kaavendda17c61999-04-25 12:24:42 +0000831 func->linetab = DBG_realloc(func->linetab,
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000832 func->lines_alloc * sizeof(WineLineNo));
833 }
834
835 func->linetab[func->n_lines].line_number = line_num;
Eric Pouechd33bcb62000-03-15 19:57:20 +0000836 func->linetab[func->n_lines].pc_offset.seg = func->value.addr.seg;
837 func->linetab[func->n_lines].pc_offset.off = func->value.addr.off + offset;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000838 func->n_lines++;
839}
840
841
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000842struct wine_locals *
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000843DEBUG_AddLocal( struct name_hash * func, int regno,
844 int offset,
845 int pc_start,
846 int pc_end,
847 char * name)
848{
849 if( func == NULL )
850 {
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000851 return NULL;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000852 }
853
854 if( func->n_locals + 1 >= func->locals_alloc )
855 {
856 func->locals_alloc += 32;
Ove Kaavendda17c61999-04-25 12:24:42 +0000857 func->local_vars = DBG_realloc(func->local_vars,
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000858 func->locals_alloc * sizeof(WineLocals));
859 }
860
861 func->local_vars[func->n_locals].regno = regno;
862 func->local_vars[func->n_locals].offset = offset;
863 func->local_vars[func->n_locals].pc_start = pc_start;
864 func->local_vars[func->n_locals].pc_end = pc_end;
Ove Kaavendda17c61999-04-25 12:24:42 +0000865 func->local_vars[func->n_locals].name = DBG_strdup(name);
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000866 func->local_vars[func->n_locals].type = NULL;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000867 func->n_locals++;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000868
869 return &func->local_vars[func->n_locals - 1];
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +0000870}
871
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000872void
Eric Pouechd33bcb62000-03-15 19:57:20 +0000873DEBUG_DumpHashInfo(void)
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000874{
875 int i;
876 int depth;
877 struct name_hash *nh;
878
879 /*
880 * Utility function to dump stats about the hash table.
881 */
882 for(i=0; i<NR_NAME_HASH; i++)
883 {
884 depth = 0;
885 for (nh = name_hash_table[i]; nh; nh = nh->next)
886 {
887 depth++;
888 }
Eric Poueche5efa0c2000-04-13 19:31:58 +0000889 DEBUG_Printf(DBG_CHN_MESG, "Bucket %d: %d\n", i, depth);
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000890 }
891}
892
893/***********************************************************************
894 * DEBUG_CheckLinenoStatus
895 *
896 * Find the symbol nearest to a given address.
897 * If ebp is specified as non-zero, it means we should dump the argument
898 * list into the string we return as well.
899 */
900int DEBUG_CheckLinenoStatus( const DBG_ADDR *addr)
901{
902 struct name_hash * nearest = NULL;
903 int mid, high, low;
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000904
905 if( sortlist_valid == FALSE )
906 {
907 DEBUG_ResortSymbols();
908 }
909
910 /*
911 * Binary search to find closest symbol.
912 */
913 low = 0;
914 high = sorttab_nsym;
Eric Pouechd33bcb62000-03-15 19:57:20 +0000915 if( addr_sorttab[0]->value.addr.seg > addr->seg
916 || ( addr_sorttab[0]->value.addr.seg == addr->seg
917 && addr_sorttab[0]->value.addr.off > addr->off) )
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000918 {
919 nearest = NULL;
920 }
Eric Pouechd33bcb62000-03-15 19:57:20 +0000921 else if( addr_sorttab[high - 1]->value.addr.seg < addr->seg
922 || ( addr_sorttab[high - 1]->value.addr.seg == addr->seg
923 && addr_sorttab[high - 1]->value.addr.off < addr->off) )
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000924 {
925 nearest = addr_sorttab[high - 1];
926 }
927 else
928 {
929 while(1==1)
930 {
931 mid = (high + low)/2;
932 if( mid == low )
933 {
934 /*
935 * See if there are any other entries that might also
936 * have the same address, and would also have a line
937 * number table.
938 */
939 if( mid > 0 && addr_sorttab[mid]->linetab == NULL )
940 {
Eric Pouechd33bcb62000-03-15 19:57:20 +0000941 if( (addr_sorttab[mid - 1]->value.addr.seg ==
942 addr_sorttab[mid]->value.addr.seg)
943 && (addr_sorttab[mid - 1]->value.addr.off ==
944 addr_sorttab[mid]->value.addr.off)
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000945 && (addr_sorttab[mid - 1]->linetab != NULL) )
946 {
947 mid--;
948 }
949 }
950
951 if( (mid < sorttab_nsym - 1)
952 && (addr_sorttab[mid]->linetab == NULL) )
953 {
Eric Pouechd33bcb62000-03-15 19:57:20 +0000954 if( (addr_sorttab[mid + 1]->value.addr.seg ==
955 addr_sorttab[mid]->value.addr.seg)
956 && (addr_sorttab[mid + 1]->value.addr.off ==
957 addr_sorttab[mid]->value.addr.off)
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000958 && (addr_sorttab[mid + 1]->linetab != NULL) )
959 {
960 mid++;
961 }
962 }
963 nearest = addr_sorttab[mid];
964#if 0
Eric Poueche5efa0c2000-04-13 19:31:58 +0000965 DEBUG_Printf(DBG_CHN_MESG, "Found %x:%x when looking for %x:%x %x %s\n",
966 addr_sorttab[mid ]->value.addr.seg,
967 addr_sorttab[mid ]->value.addr.off,
968 addr->seg, addr->off,
969 addr_sorttab[mid ]->linetab,
970 addr_sorttab[mid ]->name);
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000971#endif
972 break;
973 }
Eric Pouechd33bcb62000-03-15 19:57:20 +0000974 if( (addr_sorttab[mid]->value.addr.seg < addr->seg)
975 || ( addr_sorttab[mid]->value.addr.seg == addr->seg
976 && addr_sorttab[mid]->value.addr.off <= addr->off) )
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000977 {
978 low = mid;
979 }
980 else
981 {
982 high = mid;
983 }
984 }
985 }
986
987 if (!nearest) return FUNC_HAS_NO_LINES;
988
989 if( nearest->flags & SYM_STEP_THROUGH )
990 {
991 /*
992 * This will cause us to keep single stepping until
993 * we get to the other side somewhere.
994 */
995 return NOT_ON_LINENUMBER;
996 }
997
998 if( (nearest->flags & SYM_TRAMPOLINE) )
999 {
1000 /*
1001 * This will cause us to keep single stepping until
1002 * we get to the other side somewhere.
1003 */
1004 return FUNC_IS_TRAMPOLINE;
1005 }
1006
1007 if( nearest->linetab == NULL )
1008 {
1009 return FUNC_HAS_NO_LINES;
1010 }
1011
1012
1013 /*
1014 * We never want to stop on the first instruction of a function
1015 * even if it has it's own linenumber. Let the thing keep running
1016 * until it gets past the function prologue. We only do this if there
1017 * is more than one line number for the function, of course.
1018 */
Eric Pouechd33bcb62000-03-15 19:57:20 +00001019 if( nearest->value.addr.off == addr->off && nearest->n_lines > 1 )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001020 {
1021 return NOT_ON_LINENUMBER;
1022 }
1023
1024 if( (nearest->sourcefile != NULL)
Eric Pouechd33bcb62000-03-15 19:57:20 +00001025 && (addr->off - nearest->value.addr.off < 0x100000) )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001026 {
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00001027 low = 0;
1028 high = nearest->n_lines;
1029 while ((high - low) > 1)
1030 {
1031 mid = (high + low) / 2;
1032 if (addr->off < nearest->linetab[mid].pc_offset.off) high = mid;
1033 else low = mid;
1034 }
1035 if (addr->off == nearest->linetab[low].pc_offset.off)
1036 return AT_LINENUMBER;
1037 else
1038 return NOT_ON_LINENUMBER;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001039 }
1040
1041 return FUNC_HAS_NO_LINES;
1042}
1043
1044/***********************************************************************
1045 * DEBUG_GetFuncInfo
1046 *
1047 * Find the symbol nearest to a given address.
1048 * Returns sourcefile name and line number in a format that the listing
1049 * handler can deal with.
1050 */
1051void
1052DEBUG_GetFuncInfo( struct list_id * ret, const char * filename,
1053 const char * name)
1054{
1055 char buffer[256];
1056 char * pnt;
1057 struct name_hash *nh;
1058
1059 for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
1060 {
1061 if( filename != NULL )
1062 {
1063
1064 if( nh->sourcefile == NULL )
1065 {
1066 continue;
1067 }
1068
1069 pnt = strrchr(nh->sourcefile, '/');
1070 if( strcmp(nh->sourcefile, filename) != 0
1071 && (pnt == NULL || strcmp(pnt + 1, filename) != 0) )
1072 {
1073 continue;
1074 }
1075 }
1076 if (!strcmp(nh->name, name)) break;
1077 }
1078
1079 if (!nh && (name[0] != '_'))
1080 {
1081 buffer[0] = '_';
1082 strcpy(buffer+1, name);
1083 for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
1084 {
1085 if( filename != NULL )
1086 {
1087 if( nh->sourcefile == NULL )
1088 {
1089 continue;
1090 }
1091
1092 pnt = strrchr(nh->sourcefile, '/');
1093 if( strcmp(nh->sourcefile, filename) != 0
1094 && (pnt == NULL || strcmp(pnt + 1, filename) != 0) )
1095 {
1096 continue;
1097 }
1098 }
1099 if (!strcmp(nh->name, buffer)) break;
1100 }
1101 }
1102
1103 if( !nh )
1104 {
1105 if( filename != NULL )
1106 {
Eric Poueche5efa0c2000-04-13 19:31:58 +00001107 DEBUG_Printf(DBG_CHN_MESG, "No such function %s in %s\n", name, filename);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001108 }
1109 else
1110 {
Eric Poueche5efa0c2000-04-13 19:31:58 +00001111 DEBUG_Printf(DBG_CHN_MESG, "No such function %s\n", name);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001112 }
1113 ret->sourcefile = NULL;
1114 ret->line = -1;
1115 return;
1116 }
1117
1118 ret->sourcefile = nh->sourcefile;
1119
1120 /*
1121 * Search for the specific line number. If we don't find it,
1122 * then return FALSE.
1123 */
1124 if( nh->linetab == NULL )
1125 {
1126 ret->line = -1;
1127 }
1128 else
1129 {
1130 ret->line = nh->linetab[0].line_number;
1131 }
1132}
1133
1134/***********************************************************************
1135 * DEBUG_GetStackSymbolValue
1136 *
1137 * Get the address of a named symbol from the current stack frame.
1138 */
1139static
Eric Pouechd33bcb62000-03-15 19:57:20 +00001140BOOL DEBUG_GetStackSymbolValue( const char * name, DBG_VALUE *value )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001141{
1142 struct name_hash * curr_func;
1143 unsigned int ebp;
1144 unsigned int eip;
1145 int i;
1146
1147 if( DEBUG_GetCurrentFrame(&curr_func, &eip, &ebp) == FALSE )
1148 {
1149 return FALSE;
1150 }
1151
1152 for(i=0; i < curr_func->n_locals; i++ )
1153 {
1154 /*
1155 * Test the range of validity of the local variable. This
1156 * comes up with RBRAC/LBRAC stabs in particular.
1157 */
1158 if( (curr_func->local_vars[i].pc_start != 0)
Eric Pouechd33bcb62000-03-15 19:57:20 +00001159 && ((eip - curr_func->value.addr.off)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001160 < curr_func->local_vars[i].pc_start) )
1161 {
1162 continue;
1163 }
1164
1165 if( (curr_func->local_vars[i].pc_end != 0)
Eric Pouechd33bcb62000-03-15 19:57:20 +00001166 && ((eip - curr_func->value.addr.off)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001167 > curr_func->local_vars[i].pc_end) )
1168 {
1169 continue;
1170 }
1171
1172 if( strcmp(name, curr_func->local_vars[i].name) == 0 )
1173 {
1174 /*
1175 * OK, we found it. Now figure out what to do with this.
1176 */
1177 if( curr_func->local_vars[i].regno != 0 )
1178 {
1179 /*
Ove Kaaveneee1ddc1998-12-07 12:09:55 +00001180 * Register variable. Point to DEBUG_context field.
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001181 */
Eric Pouech04c16b82000-04-30 12:21:15 +00001182 assert(curr_func->local_vars[i].regno - 1 < sizeof(reg_ofs)/sizeof(reg_ofs[0]));
Eric Pouechd33bcb62000-03-15 19:57:20 +00001183 value->addr.off = ((DWORD)&DEBUG_context) +
1184 reg_ofs[curr_func->local_vars[i].regno - 1];
1185 value->cookie = DV_HOST;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001186 }
Eric Pouechd33bcb62000-03-15 19:57:20 +00001187 else
1188 {
1189 value->addr.off = ebp + curr_func->local_vars[i].offset;
1190 value->cookie = DV_TARGET;
1191 }
1192 value->addr.seg = 0;
1193 value->type = curr_func->local_vars[i].type;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001194
1195 return TRUE;
1196 }
1197 }
Eric Pouechd33bcb62000-03-15 19:57:20 +00001198
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001199 return FALSE;
1200}
1201
1202int
Eric Pouechd33bcb62000-03-15 19:57:20 +00001203DEBUG_InfoLocals(void)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001204{
1205 struct name_hash * curr_func;
1206 unsigned int ebp;
1207 unsigned int eip;
1208 int i;
1209 unsigned int * ptr;
Eric Pouech527eea92000-03-08 16:44:54 +00001210 unsigned int val;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001211
1212 if( DEBUG_GetCurrentFrame(&curr_func, &eip, &ebp) == FALSE )
1213 {
1214 return FALSE;
1215 }
1216
Eric Pouech38f2be42001-08-15 17:40:31 +00001217 DEBUG_Printf(DBG_CHN_MESG, "%s:\n", curr_func->name);
1218
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001219 for(i=0; i < curr_func->n_locals; i++ )
1220 {
1221 /*
1222 * Test the range of validity of the local variable. This
1223 * comes up with RBRAC/LBRAC stabs in particular.
1224 */
1225 if( (curr_func->local_vars[i].pc_start != 0)
Eric Pouechd33bcb62000-03-15 19:57:20 +00001226 && ((eip - curr_func->value.addr.off)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001227 < curr_func->local_vars[i].pc_start) )
1228 {
1229 continue;
1230 }
1231
1232 if( (curr_func->local_vars[i].pc_end != 0)
Eric Pouechd33bcb62000-03-15 19:57:20 +00001233 && ((eip - curr_func->value.addr.off)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001234 > curr_func->local_vars[i].pc_end) )
1235 {
1236 continue;
1237 }
1238
Eric Pouech38f2be42001-08-15 17:40:31 +00001239 DEBUG_PrintTypeCast(curr_func->local_vars[i].type);
1240
Eric Pouechd33bcb62000-03-15 19:57:20 +00001241 if( curr_func->local_vars[i].regno != 0 )
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001242 {
Eric Pouechd33bcb62000-03-15 19:57:20 +00001243 ptr = (unsigned int *)(((DWORD)&DEBUG_context)
1244 + reg_ofs[curr_func->local_vars[i].regno - 1]);
Eric Pouech38f2be42001-08-15 17:40:31 +00001245 DEBUG_Printf(DBG_CHN_MESG, " %s (optimized into register $%s) == 0x%8.8x\n",
1246 curr_func->local_vars[i].name,
Eric Poueche5efa0c2000-04-13 19:31:58 +00001247 reg_name[curr_func->local_vars[i].regno - 1],
1248 *ptr);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001249 }
1250 else
1251 {
Eric Pouech527eea92000-03-08 16:44:54 +00001252 DEBUG_READ_MEM_VERBOSE((void*)(ebp + curr_func->local_vars[i].offset),
1253 &val, sizeof(val));
Eric Pouech38f2be42001-08-15 17:40:31 +00001254 DEBUG_Printf(DBG_CHN_MESG, " %s == 0x%8.8x\n",
1255 curr_func->local_vars[i].name, val);
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001256 }
1257 }
1258
Eric Pouech527eea92000-03-08 16:44:54 +00001259 return TRUE;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001260}
1261
1262int
1263DEBUG_SetSymbolSize(struct name_hash * sym, unsigned int len)
1264{
1265 sym->symbol_size = len;
1266
1267 return TRUE;
1268}
1269
1270int
1271DEBUG_SetSymbolBPOff(struct name_hash * sym, unsigned int off)
1272{
1273 sym->breakpoint_offset = off;
1274
1275 return TRUE;
1276}
1277
1278int
1279DEBUG_GetSymbolAddr(struct name_hash * sym, DBG_ADDR * addr)
1280{
1281
Eric Pouechd33bcb62000-03-15 19:57:20 +00001282 *addr = sym->value.addr;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001283
1284 return TRUE;
1285}
1286
1287int DEBUG_SetLocalSymbolType(struct wine_locals * sym, struct datatype * type)
1288{
1289 sym->type = type;
1290
1291 return TRUE;
1292}