Added some TRACEs to the ddraw code.
[wine/gsoc_dplay.git] / programs / winedbg / hash.c
blobdc6f3b937a403f0159d191d2cd945948fad7b487
1 /*
2 * File hash.c - generate hash tables for Wine debugger symbols
4 * Copyright (C) 1993, Eric Youngdale.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <limits.h>
27 #include <sys/types.h>
28 #include "debugger.h"
30 #define NR_NAME_HASH 16384
31 #ifndef PATH_MAX
32 #define PATH_MAX MAX_PATH
33 #endif
35 #ifdef __i386__
36 static char * reg_name[] =
38 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
41 static unsigned reg_ofs[] =
43 FIELD_OFFSET(CONTEXT, Eax), FIELD_OFFSET(CONTEXT, Ecx),
44 FIELD_OFFSET(CONTEXT, Edx), FIELD_OFFSET(CONTEXT, Ebx),
45 FIELD_OFFSET(CONTEXT, Esp), FIELD_OFFSET(CONTEXT, Ebp),
46 FIELD_OFFSET(CONTEXT, Esi), FIELD_OFFSET(CONTEXT, Edi)
48 #else
49 static char * reg_name[] = { NULL }; /* FIXME */
50 static unsigned reg_ofs[] = { 0 };
51 #endif
54 struct name_hash
56 struct name_hash * next; /* Used to look up within name hash */
57 char * name;
58 char * sourcefile;
60 int n_locals;
61 int locals_alloc;
62 WineLocals * local_vars;
64 int n_lines;
65 int lines_alloc;
66 WineLineNo * linetab;
68 DBG_VALUE value;
69 unsigned short flags;
70 unsigned short breakpoint_offset;
71 unsigned int symbol_size;
75 static BOOL DEBUG_GetStackSymbolValue( const char * name, DBG_VALUE *value );
76 static int sortlist_valid = FALSE;
78 static int sorttab_nsym;
79 static struct name_hash ** addr_sorttab = NULL;
81 static struct name_hash * name_hash_table[NR_NAME_HASH];
83 static unsigned int name_hash( const char * name )
85 unsigned int hash = 0;
86 unsigned int tmp;
87 const char * p;
89 p = name;
91 while (*p)
93 hash = (hash << 4) + *p++;
95 if( (tmp = (hash & 0xf0000000)) )
97 hash ^= tmp >> 24;
99 hash &= ~tmp;
101 return hash % NR_NAME_HASH;
105 DEBUG_cmp_sym(const void * p1, const void * p2)
107 struct name_hash ** name1 = (struct name_hash **) p1;
108 struct name_hash ** name2 = (struct name_hash **) p2;
110 if( ((*name1)->flags & SYM_INVALID) != 0 )
112 return -1;
115 if( ((*name2)->flags & SYM_INVALID) != 0 )
117 return 1;
120 if( (*name1)->value.addr.seg > (*name2)->value.addr.seg )
122 return 1;
125 if( (*name1)->value.addr.seg < (*name2)->value.addr.seg )
127 return -1;
130 if( (*name1)->value.addr.off > (*name2)->value.addr.off )
132 return 1;
135 if( (*name1)->value.addr.off < (*name2)->value.addr.off )
137 return -1;
140 return 0;
143 /***********************************************************************
144 * DEBUG_ResortSymbols
146 * Rebuild sorted list of symbols.
148 static
149 void
150 DEBUG_ResortSymbols(void)
152 struct name_hash *nh;
153 int nsym = 0;
154 int i;
156 for(i=0; i<NR_NAME_HASH; i++)
158 for (nh = name_hash_table[i]; nh; nh = nh->next)
160 if( (nh->flags & SYM_INVALID) == 0 )
161 nsym++;
162 else
163 DEBUG_Printf( DBG_CHN_MESG, "Symbol %s is invalid\n", nh->name );
167 sorttab_nsym = nsym;
168 if( nsym == 0 )
170 return;
173 addr_sorttab = (struct name_hash **) DBG_realloc(addr_sorttab,
174 nsym * sizeof(struct name_hash *));
176 nsym = 0;
177 for(i=0; i<NR_NAME_HASH; i++)
179 for (nh = name_hash_table[i]; nh; nh = nh->next)
181 if( (nh->flags & SYM_INVALID) == 0 )
182 addr_sorttab[nsym++] = nh;
186 qsort(addr_sorttab, nsym,
187 sizeof(struct name_hash *), DEBUG_cmp_sym);
188 sortlist_valid = TRUE;
192 /***********************************************************************
193 * DEBUG_AddSymbol
195 * Add a symbol to the table.
197 struct name_hash *
198 DEBUG_AddSymbol( const char * name, const DBG_VALUE *value,
199 const char * source, int flags)
201 struct name_hash * new;
202 struct name_hash *nh;
203 static char prev_source[PATH_MAX] = {'\0', };
204 static char * prev_duped_source = NULL;
205 int hash;
207 assert(value->cookie == DV_TARGET || value->cookie == DV_HOST);
209 hash = name_hash(name);
210 for (nh = name_hash_table[hash]; nh; nh = nh->next)
212 if( ((nh->flags & SYM_INVALID) != 0) && strcmp(name, nh->name) == 0 )
214 #if 0
215 DEBUG_Printf(DBG_CHN_MESG, "Changing address for symbol %s (%08lx:%08lx => %08lx:%08lx)\n",
216 name, nh->value.addr.seg, nh->value.addr.off, value->addr.seg, value->addr.off);
217 #endif
218 nh->value.addr = value->addr;
219 if( nh->value.type == NULL && value->type != NULL )
221 nh->value.type = value->type;
222 nh->value.cookie = value->cookie;
224 /* it may happen that the same symbol is defined in several compilation
225 * units, but the linker decides to merge it into a single instance.
226 * in that case, we don't clear the invalid flag for all the compilation
227 * units (N_GSYM), and wait to get the symbol from the symtab
229 if ((flags & SYM_INVALID) == 0)
230 nh->flags &= ~SYM_INVALID;
232 return nh;
234 if (nh->value.addr.seg == value->addr.seg &&
235 nh->value.addr.off == value->addr.off &&
236 strcmp(name, nh->name) == 0 )
238 return nh;
242 #if 0
243 DEBUG_Printf(DBG_CHN_TRACE, "adding symbol (%s) from file '%s' at 0x%04lx:%08lx\n",
244 name, source, value->addr.seg, value->addr.off);
245 #endif
248 * First see if we already have an entry for this symbol. If so
249 * return it, so we don't end up with duplicates.
252 new = (struct name_hash *) DBG_alloc(sizeof(struct name_hash));
253 new->value = *value;
254 new->name = DBG_strdup(name);
256 if( source != NULL )
259 * This is an enhancement to reduce memory consumption. The idea
260 * is that we duplicate a given string only once. This is a big
261 * win if there are lots of symbols defined in a given source file.
263 if( strcmp(source, prev_source) == 0 )
265 new->sourcefile = prev_duped_source;
267 else
269 strcpy(prev_source, source);
270 prev_duped_source = new->sourcefile = DBG_strdup(source);
273 else
275 new->sourcefile = NULL;
278 new->n_lines = 0;
279 new->lines_alloc = 0;
280 new->linetab = NULL;
282 new->n_locals = 0;
283 new->locals_alloc = 0;
284 new->local_vars = NULL;
286 new->flags = flags;
287 new->next = NULL;
289 /* Now insert into the hash table */
290 new->next = name_hash_table[hash];
291 name_hash_table[hash] = new;
294 * Check some heuristics based upon the file name to see whether
295 * we want to step through this guy or not. These are machine generated
296 * assembly files that are used to translate between the MS way of
297 * calling things and the GCC way of calling things. In general we
298 * always want to step through.
300 if ( source != NULL ) {
301 int len = strlen(source);
303 if (len > 2 && source[len-2] == '.' && source[len-1] == 's') {
304 char* c = strrchr(source - 2, '/');
305 if (c != NULL) {
306 if (strcmp(c + 1, "asmrelay.s") == 0)
307 new->flags |= SYM_TRAMPOLINE;
312 sortlist_valid = FALSE;
313 return new;
316 BOOL DEBUG_Normalize(struct name_hash * nh )
320 * We aren't adding any more locals or linenumbers to this function.
321 * Free any spare memory that we might have allocated.
323 if( nh == NULL )
325 return TRUE;
328 if( nh->n_locals != nh->locals_alloc )
330 nh->locals_alloc = nh->n_locals;
331 nh->local_vars = DBG_realloc(nh->local_vars,
332 nh->locals_alloc * sizeof(WineLocals));
335 if( nh->n_lines != nh->lines_alloc )
337 nh->lines_alloc = nh->n_lines;
338 nh->linetab = DBG_realloc(nh->linetab,
339 nh->lines_alloc * sizeof(WineLineNo));
342 return TRUE;
345 /***********************************************************************
346 * DEBUG_GetSymbolValue
348 * Get the address of a named symbol.
349 * Return values:
350 * gsv_found: if the symbol is found
351 * gsv_unknown: if the symbol isn't found
352 * gsv_aborted: some error occured (likely, many symbols of same name exist,
353 * and user didn't pick one of them)
355 static int DEBUG_GSV_Helper(const char* name, const int lineno,
356 DBG_VALUE* value, int num, int bp_flag)
358 struct name_hash* nh;
359 int i = 0;
360 DBG_ADDR addr;
362 for (nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
364 if ((nh->flags & SYM_INVALID) != 0) continue;
365 if (!strcmp(nh->name, name) && DEBUG_GetLineNumberAddr( nh, lineno, &addr, bp_flag ))
367 if (i >= num) return num + 1;
368 value[i].addr = addr;
369 value[i].type = nh->value.type;
370 value[i].cookie = nh->value.cookie;
371 i++;
374 return i;
377 enum get_sym_val DEBUG_GetSymbolValue( const char * name,
378 const int lineno,
379 DBG_VALUE *rtn, int bp_flag )
381 #define NUMDBGV 10
382 /* FIXME: NUMDBGV should be made variable */
383 DBG_VALUE value[NUMDBGV];
384 DBG_VALUE vtmp;
385 int num, i, local = -1;
387 num = DEBUG_GSV_Helper(name, lineno, value, NUMDBGV, bp_flag);
388 if (!num && (name[0] != '_'))
390 char buffer[512];
392 assert(strlen(name) < sizeof(buffer) - 2); /* one for '_', one for '\0' */
393 buffer[0] = '_';
394 strcpy(buffer + 1, name);
395 num = DEBUG_GSV_Helper(buffer, lineno, value, NUMDBGV, bp_flag);
398 /* now get the local symbols if any */
399 if (DEBUG_GetStackSymbolValue(name, &vtmp) && num < NUMDBGV)
401 value[num] = vtmp;
402 local = num;
403 num++;
406 if (num == 0) {
407 return gsv_unknown;
408 } else if (!DEBUG_InteractiveP || num == 1) {
409 i = 0;
410 } else {
411 char buffer[256];
413 if (num == NUMDBGV+1) {
414 DEBUG_Printf(DBG_CHN_MESG, "Too many addresses for symbol '%s', limiting the first %d\n", name, NUMDBGV);
415 num = NUMDBGV;
417 DEBUG_Printf(DBG_CHN_MESG, "Many symbols with name '%s', choose the one you want (<cr> to abort):\n", name);
418 for (i = 0; i < num; i++) {
419 DEBUG_Printf(DBG_CHN_MESG, "[%d]: ", i + 1);
420 if (i == local) {
421 struct name_hash*func;
422 unsigned int ebp;
423 unsigned int eip;
425 if (DEBUG_GetCurrentFrame(&func, &eip, &ebp))
426 DEBUG_Printf(DBG_CHN_MESG, "local variable of %s in %s\n", func->name, func->sourcefile);
427 else
428 DEBUG_Printf(DBG_CHN_MESG, "local variable\n");
429 } else {
430 DEBUG_PrintAddress( &value[i].addr, DEBUG_GetSelectorType(value[i].addr.seg), TRUE);
431 DEBUG_Printf(DBG_CHN_MESG, "\n");
434 do {
435 i = 0;
436 if (DEBUG_ReadLine("=> ", buffer, sizeof(buffer)))
438 if (buffer[0] == '\0') return gsv_aborted;
439 i = atoi(buffer);
440 if (i < 1 || i > num)
441 DEBUG_Printf(DBG_CHN_MESG, "Invalid choice %d\n", i);
443 } while (i < 1 || i > num);
445 /* The array is 0-based, but the choices are 1..n, so we have to subtract one before returning. */
446 i--;
448 *rtn = value[i];
449 return gsv_found;
452 /***********************************************************************
453 * DEBUG_GetLineNumberAddr
455 * Get the address of a named symbol.
457 BOOL DEBUG_GetLineNumberAddr( const struct name_hash * nh, const int lineno,
458 DBG_ADDR *addr, int bp_flag )
460 int i;
462 if( lineno == -1 )
464 *addr = nh->value.addr;
465 if( bp_flag )
467 addr->off += nh->breakpoint_offset;
470 else
473 * Search for the specific line number. If we don't find it,
474 * then return FALSE.
476 if( nh->linetab == NULL )
478 return FALSE;
481 for(i=0; i < nh->n_lines; i++ )
483 if( nh->linetab[i].line_number == lineno )
485 *addr = nh->linetab[i].pc_offset;
486 return TRUE;
491 * This specific line number not found.
493 return FALSE;
496 return TRUE;
500 /***********************************************************************
501 * DEBUG_SetSymbolValue
503 * Set the address of a named symbol.
505 BOOL DEBUG_SetSymbolValue( const char * name, const DBG_VALUE *value )
507 char buffer[256];
508 struct name_hash *nh;
510 assert(value->cookie == DV_TARGET || value->cookie == DV_HOST);
512 for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
513 if (!strcmp(nh->name, name)) break;
515 if (!nh && (name[0] != '_'))
517 buffer[0] = '_';
518 strcpy(buffer+1, name);
519 for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
520 if (!strcmp(nh->name, buffer)) break;
523 if (!nh) return FALSE;
524 nh->value = *value;
525 nh->flags &= ~SYM_INVALID;
527 #ifdef __i386__
528 DEBUG_FixAddress( &nh->value.addr, DEBUG_context.SegDs );
529 #endif
531 return TRUE;
535 /***********************************************************************
536 * DEBUG_FindNearestSymbol
538 * Find the symbol nearest to a given address.
539 * If ebp is specified as non-zero, it means we should dump the argument
540 * list into the string we return as well.
542 const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag,
543 struct name_hash ** rtn,
544 unsigned int ebp,
545 struct list_id * source)
547 static char name_buffer[MAX_PATH + 256];
548 static char arglist[1024];
549 static char argtmp[256];
550 struct name_hash * nearest = NULL;
551 int mid, high, low;
552 unsigned int * ptr;
553 int lineno;
554 char * lineinfo, *sourcefile;
555 int i;
556 char linebuff[16];
557 unsigned val;
558 DBG_MODULE* module;
559 char modbuf[256];
561 if( rtn != NULL )
563 *rtn = NULL;
566 if( source != NULL )
568 source->sourcefile = NULL;
569 source->line = -1;
572 if( sortlist_valid == FALSE )
574 DEBUG_ResortSymbols();
577 if( sortlist_valid == FALSE )
579 return NULL;
583 * FIXME - use the binary search that we added to
584 * the function DEBUG_CheckLinenoStatus. Better yet, we should
585 * probably keep some notion of the current function so we don't
586 * have to search every time.
589 * Binary search to find closest symbol.
591 low = 0;
592 high = sorttab_nsym;
593 if( addr_sorttab[0]->value.addr.seg > addr->seg
594 || ( addr_sorttab[0]->value.addr.seg == addr->seg
595 && addr_sorttab[0]->value.addr.off > addr->off) )
597 nearest = NULL;
599 else if( addr_sorttab[high - 1]->value.addr.seg < addr->seg
600 || ( addr_sorttab[high - 1]->value.addr.seg == addr->seg
601 && addr_sorttab[high - 1]->value.addr.off < addr->off) )
603 nearest = addr_sorttab[high - 1];
605 else
607 while(1==1)
609 mid = (high + low)/2;
610 if( mid == low )
613 * See if there are any other entries that might also
614 * have the same address, and would also have a line
615 * number table.
617 if( mid > 0 && addr_sorttab[mid]->linetab == NULL )
619 if( (addr_sorttab[mid - 1]->value.addr.seg ==
620 addr_sorttab[mid]->value.addr.seg)
621 && (addr_sorttab[mid - 1]->value.addr.off ==
622 addr_sorttab[mid]->value.addr.off)
623 && (addr_sorttab[mid - 1]->linetab != NULL) )
625 mid--;
629 if( (mid < sorttab_nsym - 1)
630 && (addr_sorttab[mid]->linetab == NULL) )
632 if( (addr_sorttab[mid + 1]->value.addr.seg ==
633 addr_sorttab[mid]->value.addr.seg)
634 && (addr_sorttab[mid + 1]->value.addr.off ==
635 addr_sorttab[mid]->value.addr.off)
636 && (addr_sorttab[mid + 1]->linetab != NULL) )
638 mid++;
641 nearest = addr_sorttab[mid];
642 #if 0
643 DEBUG_Printf(DBG_CHN_MESG, "Found %x:%x when looking for %x:%x %x %s\n",
644 addr_sorttab[mid ]->value.addr.seg,
645 addr_sorttab[mid ]->value.addr.off,
646 addr->seg, addr->off,
647 addr_sorttab[mid ]->linetab,
648 addr_sorttab[mid ]->name);
649 #endif
650 break;
652 if( (addr_sorttab[mid]->value.addr.seg < addr->seg)
653 || ( addr_sorttab[mid]->value.addr.seg == addr->seg
654 && addr_sorttab[mid]->value.addr.off <= addr->off) )
656 low = mid;
658 else
660 high = mid;
665 if (!nearest) return NULL;
667 if( rtn != NULL )
669 *rtn = nearest;
673 * Fill in the relevant bits to the structure so that we can
674 * locate the source and line for this bit of code.
676 if( source != NULL )
678 source->sourcefile = nearest->sourcefile;
679 if( nearest->linetab == NULL )
681 source->line = -1;
683 else
685 source->line = nearest->linetab[0].line_number;
689 lineinfo = "";
690 lineno = -1;
693 * Prepare to display the argument list. If ebp is specified, it is
694 * the framepointer for the function in question. If not specified,
695 * we don't want the arglist.
697 memset(arglist, '\0', sizeof(arglist));
698 if( ebp != 0 )
700 for(i=0; i < nearest->n_locals; i++ )
703 * If this is a register (offset == 0) or a local
704 * variable, we don't want to know about it.
706 if( nearest->local_vars[i].offset <= 0 )
708 continue;
711 ptr = (unsigned int *) (ebp + nearest->local_vars[i].offset);
712 if( arglist[0] == '\0' )
714 arglist[0] = '(';
716 else
718 strcat(arglist, ", ");
720 DEBUG_READ_MEM_VERBOSE(ptr, &val, sizeof(val));
721 sprintf(argtmp, "%s=0x%x", nearest->local_vars[i].name, val);
723 strcat(arglist, argtmp);
725 if( arglist[0] == '(' )
727 strcat(arglist, ")");
731 module = DEBUG_FindModuleByAddr((void*)DEBUG_ToLinear(addr), DMT_UNKNOWN);
732 if (module) {
733 char* ptr = strrchr(module->module_name, '/');
735 if (!ptr++) ptr = module->module_name;
736 sprintf( modbuf, " in %s", ptr);
738 else
739 modbuf[0] = '\0';
741 if( (nearest->sourcefile != NULL) && (flag == TRUE)
742 && (addr->off - nearest->value.addr.off < 0x100000) )
746 * Try and find the nearest line number to the current offset.
748 if( nearest->linetab != NULL )
750 low = 0;
751 high = nearest->n_lines;
752 while ((high - low) > 1)
754 mid = (high + low) / 2;
755 if (addr->off < nearest->linetab[mid].pc_offset.off)
756 high = mid;
757 else
758 low = mid;
760 lineno = nearest->linetab[low].line_number;
763 if( lineno != -1 )
765 sprintf(linebuff, ":%d", lineno);
766 lineinfo = linebuff;
767 if( source != NULL )
769 source->line = lineno;
773 /* Remove the path from the file name */
774 sourcefile = strrchr( nearest->sourcefile, '/' );
775 if (!sourcefile) sourcefile = nearest->sourcefile;
776 else sourcefile++;
778 if (addr->off == nearest->value.addr.off)
779 sprintf( name_buffer, "%s%s [%s%s]%s", nearest->name,
780 arglist, sourcefile, lineinfo, modbuf);
781 else
782 sprintf( name_buffer, "%s+0x%lx%s [%s%s]%s", nearest->name,
783 addr->off - nearest->value.addr.off,
784 arglist, sourcefile, lineinfo, modbuf );
786 else
788 if (addr->off == nearest->value.addr.off)
789 sprintf( name_buffer, "%s%s%s", nearest->name, arglist, modbuf);
790 else {
791 if (addr->seg && (nearest->value.addr.seg!=addr->seg))
792 return NULL;
793 else
794 sprintf( name_buffer, "%s+0x%lx%s%s", nearest->name,
795 addr->off - nearest->value.addr.off, arglist, modbuf);
798 return name_buffer;
802 /***********************************************************************
803 * DEBUG_ReadSymbolTable
805 * Read a symbol file into the hash table.
807 void DEBUG_ReadSymbolTable( const char* filename, unsigned long offset )
809 FILE * symbolfile;
810 DBG_VALUE value;
811 char type;
812 char * cpnt;
813 char buffer[256];
814 char name[256];
816 if (!(symbolfile = fopen(filename, "r")))
818 DEBUG_Printf( DBG_CHN_WARN, "Unable to open symbol table %s\n", filename );
819 return;
822 DEBUG_Printf( DBG_CHN_MESG, "Reading symbols from file %s\n", filename );
824 value.type = NULL;
825 value.addr.seg = 0;
826 value.addr.off = 0;
827 value.cookie = DV_TARGET;
829 while (1)
831 fgets( buffer, sizeof(buffer), symbolfile );
832 if (feof(symbolfile)) break;
834 /* Strip any text after a # sign (i.e. comments) */
835 cpnt = buffer;
836 while (*cpnt)
837 if(*cpnt++ == '#') { *cpnt = 0; break; }
839 /* Quietly ignore any lines that have just whitespace */
840 cpnt = buffer;
841 while(*cpnt)
843 if(*cpnt != ' ' && *cpnt != '\t') break;
844 cpnt++;
846 if (!(*cpnt) || *cpnt == '\n') continue;
848 if (sscanf(buffer, "%lx %c %s", &value.addr.off, &type, name) == 3)
850 if (value.addr.off + offset < value.addr.off)
851 DEBUG_Printf( DBG_CHN_WARN, "Address wrap around\n");
852 value.addr.off += offset;
853 DEBUG_AddSymbol( name, &value, NULL, SYM_WINE );
856 fclose(symbolfile);
860 void
861 DEBUG_AddLineNumber( struct name_hash * func, int line_num,
862 unsigned long offset )
864 if( func == NULL )
866 return;
869 if( func->n_lines + 1 >= func->lines_alloc )
871 func->lines_alloc += 64;
872 func->linetab = DBG_realloc(func->linetab,
873 func->lines_alloc * sizeof(WineLineNo));
876 func->linetab[func->n_lines].line_number = line_num;
877 func->linetab[func->n_lines].pc_offset.seg = func->value.addr.seg;
878 func->linetab[func->n_lines].pc_offset.off = func->value.addr.off + offset;
879 func->n_lines++;
883 struct wine_locals *
884 DEBUG_AddLocal( struct name_hash * func, int regno,
885 int offset,
886 int pc_start,
887 int pc_end,
888 char * name)
890 if( func == NULL )
892 return NULL;
895 if( func->n_locals + 1 >= func->locals_alloc )
897 func->locals_alloc += 32;
898 func->local_vars = DBG_realloc(func->local_vars,
899 func->locals_alloc * sizeof(WineLocals));
902 func->local_vars[func->n_locals].regno = regno;
903 func->local_vars[func->n_locals].offset = offset;
904 func->local_vars[func->n_locals].pc_start = pc_start;
905 func->local_vars[func->n_locals].pc_end = pc_end;
906 func->local_vars[func->n_locals].name = DBG_strdup(name);
907 func->local_vars[func->n_locals].type = NULL;
908 func->n_locals++;
910 return &func->local_vars[func->n_locals - 1];
913 void
914 DEBUG_DumpHashInfo(void)
916 int i;
917 int depth;
918 struct name_hash *nh;
921 * Utility function to dump stats about the hash table.
923 for(i=0; i<NR_NAME_HASH; i++)
925 depth = 0;
926 for (nh = name_hash_table[i]; nh; nh = nh->next)
928 depth++;
930 DEBUG_Printf(DBG_CHN_MESG, "Bucket %d: %d\n", i, depth);
934 /***********************************************************************
935 * DEBUG_CheckLinenoStatus
937 * Find the symbol nearest to a given address.
938 * If ebp is specified as non-zero, it means we should dump the argument
939 * list into the string we return as well.
941 int DEBUG_CheckLinenoStatus( const DBG_ADDR *addr)
943 struct name_hash * nearest = NULL;
944 int mid, high, low;
946 if( sortlist_valid == FALSE )
948 DEBUG_ResortSymbols();
952 * Binary search to find closest symbol.
954 low = 0;
955 high = sorttab_nsym;
956 if( addr_sorttab[0]->value.addr.seg > addr->seg
957 || ( addr_sorttab[0]->value.addr.seg == addr->seg
958 && addr_sorttab[0]->value.addr.off > addr->off) )
960 nearest = NULL;
962 else if( addr_sorttab[high - 1]->value.addr.seg < addr->seg
963 || ( addr_sorttab[high - 1]->value.addr.seg == addr->seg
964 && addr_sorttab[high - 1]->value.addr.off < addr->off) )
966 nearest = addr_sorttab[high - 1];
968 else
970 while(1==1)
972 mid = (high + low)/2;
973 if( mid == low )
976 * See if there are any other entries that might also
977 * have the same address, and would also have a line
978 * number table.
980 if( mid > 0 && addr_sorttab[mid]->linetab == NULL )
982 if( (addr_sorttab[mid - 1]->value.addr.seg ==
983 addr_sorttab[mid]->value.addr.seg)
984 && (addr_sorttab[mid - 1]->value.addr.off ==
985 addr_sorttab[mid]->value.addr.off)
986 && (addr_sorttab[mid - 1]->linetab != NULL) )
988 mid--;
992 if( (mid < sorttab_nsym - 1)
993 && (addr_sorttab[mid]->linetab == NULL) )
995 if( (addr_sorttab[mid + 1]->value.addr.seg ==
996 addr_sorttab[mid]->value.addr.seg)
997 && (addr_sorttab[mid + 1]->value.addr.off ==
998 addr_sorttab[mid]->value.addr.off)
999 && (addr_sorttab[mid + 1]->linetab != NULL) )
1001 mid++;
1004 nearest = addr_sorttab[mid];
1005 #if 0
1006 DEBUG_Printf(DBG_CHN_MESG, "Found %x:%x when looking for %x:%x %x %s\n",
1007 addr_sorttab[mid ]->value.addr.seg,
1008 addr_sorttab[mid ]->value.addr.off,
1009 addr->seg, addr->off,
1010 addr_sorttab[mid ]->linetab,
1011 addr_sorttab[mid ]->name);
1012 #endif
1013 break;
1015 if( (addr_sorttab[mid]->value.addr.seg < addr->seg)
1016 || ( addr_sorttab[mid]->value.addr.seg == addr->seg
1017 && addr_sorttab[mid]->value.addr.off <= addr->off) )
1019 low = mid;
1021 else
1023 high = mid;
1028 if (!nearest) return FUNC_HAS_NO_LINES;
1030 if( nearest->flags & SYM_STEP_THROUGH )
1033 * This will cause us to keep single stepping until
1034 * we get to the other side somewhere.
1036 return NOT_ON_LINENUMBER;
1039 if( (nearest->flags & SYM_TRAMPOLINE) )
1042 * This will cause us to keep single stepping until
1043 * we get to the other side somewhere.
1045 return FUNC_IS_TRAMPOLINE;
1048 if( nearest->linetab == NULL )
1050 return FUNC_HAS_NO_LINES;
1055 * We never want to stop on the first instruction of a function
1056 * even if it has it's own linenumber. Let the thing keep running
1057 * until it gets past the function prologue. We only do this if there
1058 * is more than one line number for the function, of course.
1060 if( nearest->value.addr.off == addr->off && nearest->n_lines > 1 )
1062 return NOT_ON_LINENUMBER;
1065 if( (nearest->sourcefile != NULL)
1066 && (addr->off - nearest->value.addr.off < 0x100000) )
1068 low = 0;
1069 high = nearest->n_lines;
1070 while ((high - low) > 1)
1072 mid = (high + low) / 2;
1073 if (addr->off < nearest->linetab[mid].pc_offset.off) high = mid;
1074 else low = mid;
1076 if (addr->off == nearest->linetab[low].pc_offset.off)
1077 return AT_LINENUMBER;
1078 else
1079 return NOT_ON_LINENUMBER;
1082 return FUNC_HAS_NO_LINES;
1085 /***********************************************************************
1086 * DEBUG_GetFuncInfo
1088 * Find the symbol nearest to a given address.
1089 * Returns sourcefile name and line number in a format that the listing
1090 * handler can deal with.
1092 void
1093 DEBUG_GetFuncInfo( struct list_id * ret, const char * filename,
1094 const char * name)
1096 char buffer[256];
1097 char * pnt;
1098 struct name_hash *nh;
1100 for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
1102 if( filename != NULL )
1105 if( nh->sourcefile == NULL )
1107 continue;
1110 pnt = strrchr(nh->sourcefile, '/');
1111 if( strcmp(nh->sourcefile, filename) != 0
1112 && (pnt == NULL || strcmp(pnt + 1, filename) != 0) )
1114 continue;
1117 if (!strcmp(nh->name, name)) break;
1120 if (!nh && (name[0] != '_'))
1122 buffer[0] = '_';
1123 strcpy(buffer+1, name);
1124 for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
1126 if( filename != NULL )
1128 if( nh->sourcefile == NULL )
1130 continue;
1133 pnt = strrchr(nh->sourcefile, '/');
1134 if( strcmp(nh->sourcefile, filename) != 0
1135 && (pnt == NULL || strcmp(pnt + 1, filename) != 0) )
1137 continue;
1140 if (!strcmp(nh->name, buffer)) break;
1144 if( !nh )
1146 if( filename != NULL )
1148 DEBUG_Printf(DBG_CHN_MESG, "No such function %s in %s\n", name, filename);
1150 else
1152 DEBUG_Printf(DBG_CHN_MESG, "No such function %s\n", name);
1154 ret->sourcefile = NULL;
1155 ret->line = -1;
1156 return;
1159 ret->sourcefile = nh->sourcefile;
1162 * Search for the specific line number. If we don't find it,
1163 * then return FALSE.
1165 if( nh->linetab == NULL )
1167 ret->line = -1;
1169 else
1171 ret->line = nh->linetab[0].line_number;
1175 /***********************************************************************
1176 * DEBUG_GetStackSymbolValue
1178 * Get the address of a named symbol from the current stack frame.
1180 static
1181 BOOL DEBUG_GetStackSymbolValue( const char * name, DBG_VALUE *value )
1183 struct name_hash * curr_func;
1184 unsigned int ebp;
1185 unsigned int eip;
1186 int i;
1188 if( DEBUG_GetCurrentFrame(&curr_func, &eip, &ebp) == FALSE )
1190 return FALSE;
1193 for(i=0; i < curr_func->n_locals; i++ )
1196 * Test the range of validity of the local variable. This
1197 * comes up with RBRAC/LBRAC stabs in particular.
1199 if( (curr_func->local_vars[i].pc_start != 0)
1200 && ((eip - curr_func->value.addr.off)
1201 < curr_func->local_vars[i].pc_start) )
1203 continue;
1206 if( (curr_func->local_vars[i].pc_end != 0)
1207 && ((eip - curr_func->value.addr.off)
1208 > curr_func->local_vars[i].pc_end) )
1210 continue;
1213 if( strcmp(name, curr_func->local_vars[i].name) == 0 )
1216 * OK, we found it. Now figure out what to do with this.
1218 if( curr_func->local_vars[i].regno != 0 )
1221 * Register variable. Point to DEBUG_context field.
1223 assert(curr_func->local_vars[i].regno - 1 < sizeof(reg_ofs)/sizeof(reg_ofs[0]));
1224 value->addr.off = ((DWORD)&DEBUG_context) +
1225 reg_ofs[curr_func->local_vars[i].regno - 1];
1226 value->cookie = DV_HOST;
1228 else
1230 value->addr.off = ebp + curr_func->local_vars[i].offset;
1231 value->cookie = DV_TARGET;
1233 value->addr.seg = 0;
1234 value->type = curr_func->local_vars[i].type;
1236 return TRUE;
1240 return FALSE;
1244 DEBUG_InfoLocals(void)
1246 struct name_hash * curr_func;
1247 unsigned int ebp;
1248 unsigned int eip;
1249 int i;
1250 unsigned int * ptr;
1251 unsigned int val;
1253 if( DEBUG_GetCurrentFrame(&curr_func, &eip, &ebp) == FALSE )
1255 return FALSE;
1258 DEBUG_Printf(DBG_CHN_MESG, "%s:\n", curr_func->name);
1260 for(i=0; i < curr_func->n_locals; i++ )
1263 * Test the range of validity of the local variable. This
1264 * comes up with RBRAC/LBRAC stabs in particular.
1266 if( (curr_func->local_vars[i].pc_start != 0)
1267 && ((eip - curr_func->value.addr.off)
1268 < curr_func->local_vars[i].pc_start) )
1270 continue;
1273 if( (curr_func->local_vars[i].pc_end != 0)
1274 && ((eip - curr_func->value.addr.off)
1275 > curr_func->local_vars[i].pc_end) )
1277 continue;
1280 DEBUG_PrintTypeCast(curr_func->local_vars[i].type);
1282 if( curr_func->local_vars[i].regno != 0 )
1284 ptr = (unsigned int *)(((DWORD)&DEBUG_context)
1285 + reg_ofs[curr_func->local_vars[i].regno - 1]);
1286 DEBUG_Printf(DBG_CHN_MESG, " %s (optimized into register $%s) == 0x%8.8x\n",
1287 curr_func->local_vars[i].name,
1288 reg_name[curr_func->local_vars[i].regno - 1],
1289 *ptr);
1291 else
1293 DEBUG_READ_MEM_VERBOSE((void*)(ebp + curr_func->local_vars[i].offset),
1294 &val, sizeof(val));
1295 DEBUG_Printf(DBG_CHN_MESG, " %s == 0x%8.8x\n",
1296 curr_func->local_vars[i].name, val);
1300 return TRUE;
1304 DEBUG_SetSymbolSize(struct name_hash * sym, unsigned int len)
1306 sym->symbol_size = len;
1308 return TRUE;
1312 DEBUG_SetSymbolBPOff(struct name_hash * sym, unsigned int off)
1314 sym->breakpoint_offset = off;
1316 return TRUE;
1320 DEBUG_GetSymbolAddr(struct name_hash * sym, DBG_ADDR * addr)
1323 *addr = sym->value.addr;
1325 return TRUE;
1328 int DEBUG_SetLocalSymbolType(struct wine_locals * sym, struct datatype * type)
1330 sym->type = type;
1332 return TRUE;