2 * File hash.c - generate hash tables for Wine debugger symbols
4 * Copyright (C) 1993, Eric Youngdale.
12 #include <sys/types.h>
15 #include "selectors.h"
20 #define NR_NAME_HASH 16384
22 #define PATH_MAX _MAX_PATH
25 static char * reg_name[] =
27 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
33 struct name_hash * next; /* Used to look up within name hash */
39 WineLocals * local_vars;
47 unsigned short breakpoint_offset;
48 unsigned int symbol_size;
52 static BOOL32 DEBUG_GetStackSymbolValue( const char * name, DBG_ADDR *addr );
53 static int sortlist_valid = FALSE;
55 static int sorttab_nsym;
56 static struct name_hash ** addr_sorttab = NULL;
58 static struct name_hash * name_hash_table[NR_NAME_HASH];
60 static unsigned int name_hash( const char * name )
62 unsigned int hash = 0;
70 hash = (hash << 4) + *p++;
72 if( (tmp = (hash & 0xf0000000)) )
78 return hash % NR_NAME_HASH;
82 DEBUG_cmp_sym(const void * p1, const void * p2)
84 struct name_hash ** name1 = (struct name_hash **) p1;
85 struct name_hash ** name2 = (struct name_hash **) p2;
87 if( ((*name1)->flags & SYM_INVALID) != 0 )
92 if( ((*name2)->flags & SYM_INVALID) != 0 )
97 if( (*name1)->addr.seg > (*name2)->addr.seg )
102 if( (*name1)->addr.seg < (*name2)->addr.seg )
107 if( (*name1)->addr.off > (*name2)->addr.off )
112 if( (*name1)->addr.off < (*name2)->addr.off )
120 /***********************************************************************
121 * DEBUG_ResortSymbols
123 * Rebuild sorted list of symbols.
127 DEBUG_ResortSymbols()
129 struct name_hash *nh;
133 for(i=0; i<NR_NAME_HASH; i++)
135 for (nh = name_hash_table[i]; nh; nh = nh->next)
147 addr_sorttab = (struct name_hash **) xrealloc(addr_sorttab,
148 nsym * sizeof(struct name_hash *));
151 for(i=0; i<NR_NAME_HASH; i++)
153 for (nh = name_hash_table[i]; nh; nh = nh->next)
155 addr_sorttab[nsym++] = nh;
159 qsort(addr_sorttab, nsym,
160 sizeof(struct name_hash *), DEBUG_cmp_sym);
161 sortlist_valid = TRUE;
165 /***********************************************************************
168 * Add a symbol to the table.
171 DEBUG_AddSymbol( const char * name, const DBG_ADDR *addr, const char * source,
174 struct name_hash * new;
175 struct name_hash *nh;
176 static char prev_source[PATH_MAX] = {'\0', };
177 static char * prev_duped_source = NULL;
181 hash = name_hash(name);
182 for (nh = name_hash_table[hash]; nh; nh = nh->next)
184 if( ((nh->flags & SYM_INVALID) != 0) && strcmp(name, nh->name) == 0 )
186 nh->addr.off = addr->off;
187 nh->addr.seg = addr->seg;
188 if( nh->addr.type == NULL && addr->type != NULL )
190 nh->addr.type = addr->type;
192 nh->flags &= ~SYM_INVALID;
195 if (nh->addr.seg == addr->seg &&
196 nh->addr.off == addr->off &&
197 strcmp(name, nh->name) == 0 )
204 * First see if we already have an entry for this symbol. If so
205 * return it, so we don't end up with duplicates.
208 new = (struct name_hash *) xmalloc(sizeof(struct name_hash));
210 new->name = xstrdup(name);
215 * This is an enhancement to reduce memory consumption. The idea
216 * is that we duplicate a given string only once. This is a big
217 * win if there are lots of symbols defined in a given source file.
219 if( strcmp(source, prev_source) == 0 )
221 new->sourcefile = prev_duped_source;
225 strcpy(prev_source, source);
226 prev_duped_source = new->sourcefile = xstrdup(source);
231 new->sourcefile = NULL;
235 new->lines_alloc = 0;
239 new->locals_alloc = 0;
240 new->local_vars = NULL;
245 /* Now insert into the hash table */
246 new->next = name_hash_table[hash];
247 name_hash_table[hash] = new;
250 * Check some heuristics based upon the file name to see whether
251 * we want to step through this guy or not. These are machine generated
252 * assembly files that are used to translate between the MS way of
253 * calling things and the GCC way of calling things. In general we
254 * always want to step through.
258 c = strrchr(source, '.');
259 if( c != NULL && strcmp(c, ".s") == 0 )
261 c = strrchr(source, '/');
265 if( (strcmp(c, "callfrom16.s") == 0)
266 || (strcmp(c, "callto16.s") == 0)
267 || (strcmp(c, "callfrom32.s") == 0)
268 || (strcmp(c, "callto32.s") == 0) )
270 new->flags |= SYM_TRAMPOLINE;
276 sortlist_valid = FALSE;
280 BOOL32 DEBUG_Normalize(struct name_hash * nh )
284 * We aren't adding any more locals or linenumbers to this function.
285 * Free any spare memory that we might have allocated.
292 if( nh->n_locals != nh->locals_alloc )
294 nh->locals_alloc = nh->n_locals;
295 nh->local_vars = xrealloc(nh->local_vars,
296 nh->locals_alloc * sizeof(WineLocals));
299 if( nh->n_lines != nh->lines_alloc )
301 nh->lines_alloc = nh->n_lines;
302 nh->linetab = xrealloc(nh->linetab,
303 nh->lines_alloc * sizeof(WineLineNo));
309 /***********************************************************************
310 * DEBUG_GetSymbolValue
312 * Get the address of a named symbol.
314 BOOL32 DEBUG_GetSymbolValue( const char * name, const int lineno,
315 DBG_ADDR *addr, int bp_flag )
318 struct name_hash *nh;
320 for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
322 if( (nh->flags & SYM_INVALID) != 0 )
327 if (!strcmp(nh->name, name)) break;
330 if (!nh && (name[0] != '_'))
333 strcpy(buffer+1, name);
334 for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
336 if( (nh->flags & SYM_INVALID) != 0 )
340 if (!strcmp(nh->name, buffer)) break;
345 * If we don't have anything here, then try and see if this
346 * is a local symbol to the current stack frame. No matter
347 * what, we have nothing more to do, so we let that function
348 * decide what we ultimately return.
352 return DEBUG_GetStackSymbolValue(name, addr);
355 return DEBUG_GetLineNumberAddr( nh, lineno, addr, bp_flag );
358 /***********************************************************************
359 * DEBUG_GetLineNumberAddr
361 * Get the address of a named symbol.
363 BOOL32 DEBUG_GetLineNumberAddr( struct name_hash * nh, const int lineno,
364 DBG_ADDR *addr, int bp_flag )
373 addr->off += nh->breakpoint_offset;
379 * Search for the specific line number. If we don't find it,
382 if( nh->linetab == NULL )
387 for(i=0; i < nh->n_lines; i++ )
389 if( nh->linetab[i].line_number == lineno )
391 *addr = nh->linetab[i].pc_offset;
397 * This specific line number not found.
406 /***********************************************************************
407 * DEBUG_SetSymbolValue
409 * Set the address of a named symbol.
411 BOOL32 DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr )
414 struct name_hash *nh;
416 for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
417 if (!strcmp(nh->name, name)) break;
419 if (!nh && (name[0] != '_'))
422 strcpy(buffer+1, name);
423 for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
424 if (!strcmp(nh->name, buffer)) break;
427 if (!nh) return FALSE;
429 nh->flags &= SYM_INVALID;
430 DBG_FIX_ADDR_SEG( &nh->addr, DS_reg(&DEBUG_context) );
435 /***********************************************************************
436 * DEBUG_FindNearestSymbol
438 * Find the symbol nearest to a given address.
439 * If ebp is specified as non-zero, it means we should dump the argument
440 * list into the string we return as well.
442 const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag,
443 struct name_hash ** rtn,
445 struct list_id * source)
447 static char name_buffer[MAX_PATH + 256];
448 static char arglist[1024];
449 static char argtmp[256];
450 struct name_hash * nearest = NULL;
454 char * lineinfo, *sourcefile;
465 source->sourcefile = NULL;
469 if( sortlist_valid == FALSE )
471 DEBUG_ResortSymbols();
474 if( sortlist_valid == FALSE )
480 * FIXME - use the binary search that we added to
481 * the function DEBUG_CheckLinenoStatus. Better yet, we should
482 * probably keep some notion of the current function so we don't
483 * have to search every time.
486 * Binary search to find closest symbol.
490 if( addr_sorttab[0]->addr.seg > addr->seg
491 || ( addr_sorttab[0]->addr.seg == addr->seg
492 && addr_sorttab[0]->addr.off > addr->off) )
496 else if( addr_sorttab[high - 1]->addr.seg < addr->seg
497 || ( addr_sorttab[high - 1]->addr.seg == addr->seg
498 && addr_sorttab[high - 1]->addr.off < addr->off) )
500 nearest = addr_sorttab[high - 1];
506 mid = (high + low)/2;
510 * See if there are any other entries that might also
511 * have the same address, and would also have a line
514 if( mid > 0 && addr_sorttab[mid]->linetab == NULL )
516 if( (addr_sorttab[mid - 1]->addr.seg ==
517 addr_sorttab[mid]->addr.seg)
518 && (addr_sorttab[mid - 1]->addr.off ==
519 addr_sorttab[mid]->addr.off)
520 && (addr_sorttab[mid - 1]->linetab != NULL) )
526 if( (mid < sorttab_nsym - 1)
527 && (addr_sorttab[mid]->linetab == NULL) )
529 if( (addr_sorttab[mid + 1]->addr.seg ==
530 addr_sorttab[mid]->addr.seg)
531 && (addr_sorttab[mid + 1]->addr.off ==
532 addr_sorttab[mid]->addr.off)
533 && (addr_sorttab[mid + 1]->linetab != NULL) )
538 nearest = addr_sorttab[mid];
540 fprintf(stderr, "Found %x:%x when looking for %x:%x %x %s\n",
541 addr_sorttab[mid ]->addr.seg,
542 addr_sorttab[mid ]->addr.off,
543 addr->seg, addr->off,
544 addr_sorttab[mid ]->linetab,
545 addr_sorttab[mid ]->name);
549 if( (addr_sorttab[mid]->addr.seg < addr->seg)
550 || ( addr_sorttab[mid]->addr.seg == addr->seg
551 && addr_sorttab[mid]->addr.off <= addr->off) )
562 if (!nearest) return NULL;
570 * Fill in the relevant bits to the structure so that we can
571 * locate the source and line for this bit of code.
575 source->sourcefile = nearest->sourcefile;
576 if( nearest->linetab == NULL )
582 source->line = nearest->linetab[0].line_number;
590 * Prepare to display the argument list. If ebp is specified, it is
591 * the framepointer for the function in question. If not specified,
592 * we don't want the arglist.
594 memset(arglist, '\0', sizeof(arglist));
597 for(i=0; i < nearest->n_locals; i++ )
600 * If this is a register (offset == 0) or a local
601 * variable, we don't want to know about it.
603 if( nearest->local_vars[i].offset <= 0 )
608 ptr = (unsigned int *) (ebp + nearest->local_vars[i].offset);
609 if( arglist[0] == '\0' )
615 strcat(arglist, ", ");
618 sprintf(argtmp, "%s=0x%x", nearest->local_vars[i].name,
620 strcat(arglist, argtmp);
622 if( arglist[0] == '(' )
624 strcat(arglist, ")");
628 if( (nearest->sourcefile != NULL) && (flag == TRUE)
629 && (addr->off - nearest->addr.off < 0x100000) )
633 * Try and find the nearest line number to the current offset.
635 if( nearest->linetab != NULL )
638 * FIXME - this is an inefficient linear search. A binary
639 * search would be better if this gets to be a performance
642 for(i=0; i < nearest->n_lines; i++)
644 if( addr->off < nearest->linetab[i].pc_offset.off )
648 lineno = nearest->linetab[i].line_number;
654 sprintf(linebuff, ":%d", lineno);
658 source->line = lineno;
662 /* Remove the path from the file name */
663 sourcefile = strrchr( nearest->sourcefile, '/' );
664 if (!sourcefile) sourcefile = nearest->sourcefile;
667 if (addr->off == nearest->addr.off)
668 sprintf( name_buffer, "%s%s [%s%s]", nearest->name,
669 arglist, sourcefile, lineinfo);
671 sprintf( name_buffer, "%s+0x%lx%s [%s%s]", nearest->name,
672 addr->off - nearest->addr.off,
673 arglist, sourcefile, lineinfo );
677 if (addr->off == nearest->addr.off)
678 sprintf( name_buffer, "%s%s", nearest->name, arglist);
680 sprintf( name_buffer, "%s+0x%lx%s", nearest->name,
681 addr->off - nearest->addr.off, arglist);
687 /***********************************************************************
688 * DEBUG_ReadSymbolTable
690 * Read a symbol file into the hash table.
692 void DEBUG_ReadSymbolTable( const char * filename )
695 DBG_ADDR addr = { 0, 0 };
702 if (!(symbolfile = fopen(filename, "r")))
704 fprintf( stderr, "Unable to open symbol table %s\n", filename );
708 fprintf( stderr, "Reading symbols from file %s\n", filename );
712 fgets( buffer, sizeof(buffer), symbolfile );
713 if (feof(symbolfile)) break;
715 /* Strip any text after a # sign (i.e. comments) */
718 if(*cpnt++ == '#') { *cpnt = 0; break; }
720 /* Quietly ignore any lines that have just whitespace */
724 if(*cpnt != ' ' && *cpnt != '\t') break;
727 if (!(*cpnt) || *cpnt == '\n') continue;
729 nargs = sscanf(buffer, "%lx %c %s", &addr.off, &type, name);
730 DEBUG_AddSymbol( name, &addr, NULL, SYM_WINE );
736 /***********************************************************************
737 * DEBUG_LoadEntryPoints
739 * Load the entry points of all the modules into the hash table.
741 void DEBUG_LoadEntryPoints(void)
747 unsigned char *cpnt, *name;
751 for (ok = ModuleFirst(&entry); ok; ok = ModuleNext(&entry))
753 if (!(pModule = MODULE_GetPtr( entry.hModule ))) continue;
754 if (pModule->flags & NE_FFLAGS_WIN32) continue;
756 name = (unsigned char *)pModule + pModule->name_table;
758 fprintf( stderr, "Loading symbols from Win16 module %.*s...\n",
761 /* First search the resident names */
763 cpnt = (unsigned char *)pModule + pModule->name_table;
766 cpnt += *cpnt + 1 + sizeof(WORD);
767 sprintf( buffer, "%.*s_%.*s", *name, name + 1, *cpnt, cpnt + 1 );
768 if ((address = MODULE_GetEntryPoint( entry.hModule,
769 *(WORD *)(cpnt + *cpnt + 1) )))
771 addr.seg = HIWORD(address);
772 addr.off = LOWORD(address);
774 DEBUG_AddSymbol( buffer, &addr, NULL, SYM_WIN32 | SYM_FUNC );
778 /* Now search the non-resident names table */
780 if (!pModule->nrname_handle) continue; /* No non-resident table */
781 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
784 cpnt += *cpnt + 1 + sizeof(WORD);
785 sprintf( buffer, "%.*s_%.*s", *name, name + 1, *cpnt, cpnt + 1 );
786 if ((address = MODULE_GetEntryPoint( entry.hModule,
787 *(WORD *)(cpnt + *cpnt + 1) )))
789 addr.seg = HIWORD(address);
790 addr.off = LOWORD(address);
792 DEBUG_AddSymbol( buffer, &addr, NULL, SYM_WIN32);
799 DEBUG_AddLineNumber( struct name_hash * func, int line_num,
800 unsigned long offset )
807 if( func->n_lines + 1 >= func->lines_alloc )
809 func->lines_alloc += 64;
810 func->linetab = xrealloc(func->linetab,
811 func->lines_alloc * sizeof(WineLineNo));
814 func->linetab[func->n_lines].line_number = line_num;
815 func->linetab[func->n_lines].pc_offset.seg = func->addr.seg;
816 func->linetab[func->n_lines].pc_offset.off = func->addr.off + offset;
817 func->linetab[func->n_lines].pc_offset.type = NULL;
823 DEBUG_AddLocal( struct name_hash * func, int regno,
834 if( func->n_locals + 1 >= func->locals_alloc )
836 func->locals_alloc += 32;
837 func->local_vars = xrealloc(func->local_vars,
838 func->locals_alloc * sizeof(WineLocals));
841 func->local_vars[func->n_locals].regno = regno;
842 func->local_vars[func->n_locals].offset = offset;
843 func->local_vars[func->n_locals].pc_start = pc_start;
844 func->local_vars[func->n_locals].pc_end = pc_end;
845 func->local_vars[func->n_locals].name = xstrdup(name);
846 func->local_vars[func->n_locals].type = NULL;
849 return &func->local_vars[func->n_locals - 1];
857 struct name_hash *nh;
860 * Utility function to dump stats about the hash table.
862 for(i=0; i<NR_NAME_HASH; i++)
865 for (nh = name_hash_table[i]; nh; nh = nh->next)
869 fprintf(stderr, "Bucket %d: %d\n", i, depth);
873 /***********************************************************************
874 * DEBUG_CheckLinenoStatus
876 * Find the symbol nearest to a given address.
877 * If ebp is specified as non-zero, it means we should dump the argument
878 * list into the string we return as well.
880 int DEBUG_CheckLinenoStatus( const DBG_ADDR *addr)
882 struct name_hash * nearest = NULL;
886 if( sortlist_valid == FALSE )
888 DEBUG_ResortSymbols();
892 * Binary search to find closest symbol.
896 if( addr_sorttab[0]->addr.seg > addr->seg
897 || ( addr_sorttab[0]->addr.seg == addr->seg
898 && addr_sorttab[0]->addr.off > addr->off) )
902 else if( addr_sorttab[high - 1]->addr.seg < addr->seg
903 || ( addr_sorttab[high - 1]->addr.seg == addr->seg
904 && addr_sorttab[high - 1]->addr.off < addr->off) )
906 nearest = addr_sorttab[high - 1];
912 mid = (high + low)/2;
916 * See if there are any other entries that might also
917 * have the same address, and would also have a line
920 if( mid > 0 && addr_sorttab[mid]->linetab == NULL )
922 if( (addr_sorttab[mid - 1]->addr.seg ==
923 addr_sorttab[mid]->addr.seg)
924 && (addr_sorttab[mid - 1]->addr.off ==
925 addr_sorttab[mid]->addr.off)
926 && (addr_sorttab[mid - 1]->linetab != NULL) )
932 if( (mid < sorttab_nsym - 1)
933 && (addr_sorttab[mid]->linetab == NULL) )
935 if( (addr_sorttab[mid + 1]->addr.seg ==
936 addr_sorttab[mid]->addr.seg)
937 && (addr_sorttab[mid + 1]->addr.off ==
938 addr_sorttab[mid]->addr.off)
939 && (addr_sorttab[mid + 1]->linetab != NULL) )
944 nearest = addr_sorttab[mid];
946 fprintf(stderr, "Found %x:%x when looking for %x:%x %x %s\n",
947 addr_sorttab[mid ]->addr.seg,
948 addr_sorttab[mid ]->addr.off,
949 addr->seg, addr->off,
950 addr_sorttab[mid ]->linetab,
951 addr_sorttab[mid ]->name);
955 if( (addr_sorttab[mid]->addr.seg < addr->seg)
956 || ( addr_sorttab[mid]->addr.seg == addr->seg
957 && addr_sorttab[mid]->addr.off <= addr->off) )
968 if (!nearest) return FUNC_HAS_NO_LINES;
970 if( nearest->flags & SYM_STEP_THROUGH )
973 * This will cause us to keep single stepping until
974 * we get to the other side somewhere.
976 return NOT_ON_LINENUMBER;
979 if( (nearest->flags & SYM_TRAMPOLINE) )
982 * This will cause us to keep single stepping until
983 * we get to the other side somewhere.
985 return FUNC_IS_TRAMPOLINE;
988 if( nearest->linetab == NULL )
990 return FUNC_HAS_NO_LINES;
995 * We never want to stop on the first instruction of a function
996 * even if it has it's own linenumber. Let the thing keep running
997 * until it gets past the function prologue. We only do this if there
998 * is more than one line number for the function, of course.
1000 if( nearest->addr.off == addr->off && nearest->n_lines > 1 )
1002 return NOT_ON_LINENUMBER;
1005 if( (nearest->sourcefile != NULL)
1006 && (addr->off - nearest->addr.off < 0x100000) )
1009 * FIXME - this is an inefficient linear search. A binary
1010 * search would be better if this gets to be a performance
1013 for(i=0; i < nearest->n_lines; i++)
1015 if( addr->off == nearest->linetab[i].pc_offset.off )
1017 return AT_LINENUMBER;
1019 if( addr->off < nearest->linetab[i].pc_offset.off )
1025 return NOT_ON_LINENUMBER;
1028 return FUNC_HAS_NO_LINES;
1031 /***********************************************************************
1034 * Find the symbol nearest to a given address.
1035 * Returns sourcefile name and line number in a format that the listing
1036 * handler can deal with.
1039 DEBUG_GetFuncInfo( struct list_id * ret, const char * filename,
1044 struct name_hash *nh;
1046 for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
1048 if( filename != NULL )
1051 if( nh->sourcefile == NULL )
1056 pnt = strrchr(nh->sourcefile, '/');
1057 if( strcmp(nh->sourcefile, filename) != 0
1058 && (pnt == NULL || strcmp(pnt + 1, filename) != 0) )
1063 if (!strcmp(nh->name, name)) break;
1066 if (!nh && (name[0] != '_'))
1069 strcpy(buffer+1, name);
1070 for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
1072 if( filename != NULL )
1074 if( nh->sourcefile == NULL )
1079 pnt = strrchr(nh->sourcefile, '/');
1080 if( strcmp(nh->sourcefile, filename) != 0
1081 && (pnt == NULL || strcmp(pnt + 1, filename) != 0) )
1086 if (!strcmp(nh->name, buffer)) break;
1092 if( filename != NULL )
1094 fprintf(stderr, "No such function %s in %s\n", name, filename);
1098 fprintf(stderr, "No such function %s\n", name);
1100 ret->sourcefile = NULL;
1105 ret->sourcefile = nh->sourcefile;
1108 * Search for the specific line number. If we don't find it,
1109 * then return FALSE.
1111 if( nh->linetab == NULL )
1117 ret->line = nh->linetab[0].line_number;
1121 /***********************************************************************
1122 * DEBUG_GetStackSymbolValue
1124 * Get the address of a named symbol from the current stack frame.
1127 BOOL32 DEBUG_GetStackSymbolValue( const char * name, DBG_ADDR *addr )
1129 struct name_hash * curr_func;
1134 if( DEBUG_GetCurrentFrame(&curr_func, &eip, &ebp) == FALSE )
1139 for(i=0; i < curr_func->n_locals; i++ )
1142 * Test the range of validity of the local variable. This
1143 * comes up with RBRAC/LBRAC stabs in particular.
1145 if( (curr_func->local_vars[i].pc_start != 0)
1146 && ((eip - curr_func->addr.off)
1147 < curr_func->local_vars[i].pc_start) )
1152 if( (curr_func->local_vars[i].pc_end != 0)
1153 && ((eip - curr_func->addr.off)
1154 > curr_func->local_vars[i].pc_end) )
1159 if( strcmp(name, curr_func->local_vars[i].name) == 0 )
1162 * OK, we found it. Now figure out what to do with this.
1164 if( curr_func->local_vars[i].regno != 0 )
1167 * Register variable. We don't know how to treat
1174 addr->off = ebp + curr_func->local_vars[i].offset;
1175 addr->type = curr_func->local_vars[i].type;
1186 struct name_hash * curr_func;
1193 if( DEBUG_GetCurrentFrame(&curr_func, &eip, &ebp) == FALSE )
1198 for(i=0; i < curr_func->n_locals; i++ )
1201 * Test the range of validity of the local variable. This
1202 * comes up with RBRAC/LBRAC stabs in particular.
1204 if( (curr_func->local_vars[i].pc_start != 0)
1205 && ((eip - curr_func->addr.off)
1206 < curr_func->local_vars[i].pc_start) )
1211 if( (curr_func->local_vars[i].pc_end != 0)
1212 && ((eip - curr_func->addr.off)
1213 > curr_func->local_vars[i].pc_end) )
1218 if( curr_func->local_vars[i].offset == 0 )
1220 fprintf(stderr, "%s:%s optimized into register $%s \n",
1221 curr_func->name, curr_func->local_vars[i].name,
1222 reg_name[curr_func->local_vars[i].regno]);
1226 ptr = (unsigned int *) (ebp + curr_func->local_vars[i].offset);
1227 fprintf(stderr, "%s:%s == 0x%8.8x\n",
1228 curr_func->name, curr_func->local_vars[i].name,
1239 DEBUG_SetSymbolSize(struct name_hash * sym, unsigned int len)
1241 sym->symbol_size = len;
1247 DEBUG_SetSymbolBPOff(struct name_hash * sym, unsigned int off)
1249 sym->breakpoint_offset = off;
1255 DEBUG_GetSymbolAddr(struct name_hash * sym, DBG_ADDR * addr)
1263 int DEBUG_SetLocalSymbolType(struct wine_locals * sym, struct datatype * type)