The implementation of mmioWrite is now called instead of the stub.
[wine/multimedia.git] / debugger / hash.c
blob19f2a77cf0a9c1ff96e5d96ac69d97e212c82516
1 /*
2 * File hash.c - generate hash tables for Wine debugger symbols
4 * Copyright (C) 1993, Eric Youngdale.
5 */
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <limits.h>
12 #include <sys/types.h>
13 #include <neexe.h>
14 #include "module.h"
15 #include "process.h"
16 #include "selectors.h"
17 #include "debugger.h"
18 #include "toolhelp.h"
19 #include "xmalloc.h"
21 #define NR_NAME_HASH 16384
22 #ifndef PATH_MAX
23 #define PATH_MAX _MAX_PATH
24 #endif
26 static char * reg_name[] =
28 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
32 struct name_hash
34 struct name_hash * next; /* Used to look up within name hash */
35 char * name;
36 char * sourcefile;
38 int n_locals;
39 int locals_alloc;
40 WineLocals * local_vars;
42 int n_lines;
43 int lines_alloc;
44 WineLineNo * linetab;
46 DBG_ADDR addr;
47 unsigned short flags;
48 unsigned short breakpoint_offset;
49 unsigned int symbol_size;
53 static BOOL32 DEBUG_GetStackSymbolValue( const char * name, DBG_ADDR *addr );
54 static int sortlist_valid = FALSE;
56 static int sorttab_nsym;
57 static struct name_hash ** addr_sorttab = NULL;
59 static struct name_hash * name_hash_table[NR_NAME_HASH];
61 static unsigned int name_hash( const char * name )
63 unsigned int hash = 0;
64 unsigned int tmp;
65 const char * p;
67 p = name;
69 while (*p)
71 hash = (hash << 4) + *p++;
73 if( (tmp = (hash & 0xf0000000)) )
75 hash ^= tmp >> 24;
77 hash &= ~tmp;
79 return hash % NR_NAME_HASH;
82 int
83 DEBUG_cmp_sym(const void * p1, const void * p2)
85 struct name_hash ** name1 = (struct name_hash **) p1;
86 struct name_hash ** name2 = (struct name_hash **) p2;
88 if( ((*name1)->flags & SYM_INVALID) != 0 )
90 return -1;
93 if( ((*name2)->flags & SYM_INVALID) != 0 )
95 return 1;
98 if( (*name1)->addr.seg > (*name2)->addr.seg )
100 return 1;
103 if( (*name1)->addr.seg < (*name2)->addr.seg )
105 return -1;
108 if( (*name1)->addr.off > (*name2)->addr.off )
110 return 1;
113 if( (*name1)->addr.off < (*name2)->addr.off )
115 return -1;
118 return 0;
121 /***********************************************************************
122 * DEBUG_ResortSymbols
124 * Rebuild sorted list of symbols.
126 static
127 void
128 DEBUG_ResortSymbols()
130 struct name_hash *nh;
131 int nsym = 0;
132 int i;
134 for(i=0; i<NR_NAME_HASH; i++)
136 for (nh = name_hash_table[i]; nh; nh = nh->next)
138 nsym++;
142 sorttab_nsym = nsym;
143 if( nsym == 0 )
145 return;
148 addr_sorttab = (struct name_hash **) xrealloc(addr_sorttab,
149 nsym * sizeof(struct name_hash *));
151 nsym = 0;
152 for(i=0; i<NR_NAME_HASH; i++)
154 for (nh = name_hash_table[i]; nh; nh = nh->next)
156 addr_sorttab[nsym++] = nh;
160 qsort(addr_sorttab, nsym,
161 sizeof(struct name_hash *), DEBUG_cmp_sym);
162 sortlist_valid = TRUE;
166 /***********************************************************************
167 * DEBUG_AddSymbol
169 * Add a symbol to the table.
171 struct name_hash *
172 DEBUG_AddSymbol( const char * name, const DBG_ADDR *addr, const char * source,
173 int flags)
175 struct name_hash * new;
176 struct name_hash *nh;
177 static char prev_source[PATH_MAX] = {'\0', };
178 static char * prev_duped_source = NULL;
179 char * c;
180 int hash;
182 hash = name_hash(name);
183 for (nh = name_hash_table[hash]; nh; nh = nh->next)
185 if( ((nh->flags & SYM_INVALID) != 0) && strcmp(name, nh->name) == 0 )
187 nh->addr.off = addr->off;
188 nh->addr.seg = addr->seg;
189 if( nh->addr.type == NULL && addr->type != NULL )
191 nh->addr.type = addr->type;
193 nh->flags &= ~SYM_INVALID;
194 return nh;
196 if (nh->addr.seg == addr->seg &&
197 nh->addr.off == addr->off &&
198 strcmp(name, nh->name) == 0 )
200 return nh;
205 * First see if we already have an entry for this symbol. If so
206 * return it, so we don't end up with duplicates.
209 new = (struct name_hash *) xmalloc(sizeof(struct name_hash));
210 new->addr = *addr;
211 new->name = xstrdup(name);
213 if( source != NULL )
216 * This is an enhancement to reduce memory consumption. The idea
217 * is that we duplicate a given string only once. This is a big
218 * win if there are lots of symbols defined in a given source file.
220 if( strcmp(source, prev_source) == 0 )
222 new->sourcefile = prev_duped_source;
224 else
226 strcpy(prev_source, source);
227 prev_duped_source = new->sourcefile = xstrdup(source);
230 else
232 new->sourcefile = NULL;
235 new->n_lines = 0;
236 new->lines_alloc = 0;
237 new->linetab = NULL;
239 new->n_locals = 0;
240 new->locals_alloc = 0;
241 new->local_vars = NULL;
243 new->flags = flags;
244 new->next = NULL;
246 /* Now insert into the hash table */
247 new->next = name_hash_table[hash];
248 name_hash_table[hash] = new;
251 * Check some heuristics based upon the file name to see whether
252 * we want to step through this guy or not. These are machine generated
253 * assembly files that are used to translate between the MS way of
254 * calling things and the GCC way of calling things. In general we
255 * always want to step through.
257 if( source != NULL )
259 c = strrchr(source, '.');
260 if( c != NULL && strcmp(c, ".s") == 0 )
262 c = strrchr(source, '/');
263 if( c != NULL )
265 c++;
266 if( (strcmp(c, "callfrom16.s") == 0)
267 || (strcmp(c, "callto16.s") == 0)
268 || (strcmp(c, "call32.s") == 0) )
270 new->flags |= SYM_TRAMPOLINE;
276 sortlist_valid = FALSE;
277 return new;
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.
287 if( nh == NULL )
289 return TRUE;
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));
306 return TRUE;
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 )
317 char buffer[256];
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 )
324 continue;
327 if (!strcmp(nh->name, name)) break;
330 if (!nh && (name[0] != '_'))
332 buffer[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 )
338 continue;
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.
350 if (!nh)
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 )
366 int i;
368 if( lineno == -1 )
370 *addr = nh->addr;
371 if( bp_flag )
373 addr->off += nh->breakpoint_offset;
376 else
379 * Search for the specific line number. If we don't find it,
380 * then return FALSE.
382 if( nh->linetab == NULL )
384 return FALSE;
387 for(i=0; i < nh->n_lines; i++ )
389 if( nh->linetab[i].line_number == lineno )
391 *addr = nh->linetab[i].pc_offset;
392 return TRUE;
397 * This specific line number not found.
399 return FALSE;
402 return TRUE;
406 /***********************************************************************
407 * DEBUG_SetSymbolValue
409 * Set the address of a named symbol.
411 BOOL32 DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr )
413 char buffer[256];
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] != '_'))
421 buffer[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;
428 nh->addr = *addr;
429 nh->flags &= SYM_INVALID;
430 DBG_FIX_ADDR_SEG( &nh->addr, DS_reg(&DEBUG_context) );
431 return TRUE;
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,
444 unsigned int ebp,
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;
451 int mid, high, low;
452 unsigned int * ptr;
453 int lineno;
454 char * lineinfo, *sourcefile;
455 int i;
456 char linebuff[16];
458 if( rtn != NULL )
460 *rtn = NULL;
463 if( source != NULL )
465 source->sourcefile = NULL;
466 source->line = -1;
469 if( sortlist_valid == FALSE )
471 DEBUG_ResortSymbols();
474 if( sortlist_valid == FALSE )
476 return NULL;
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.
488 low = 0;
489 high = sorttab_nsym;
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) )
494 nearest = NULL;
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];
502 else
504 while(1==1)
506 mid = (high + low)/2;
507 if( mid == low )
510 * See if there are any other entries that might also
511 * have the same address, and would also have a line
512 * number table.
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) )
522 mid--;
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) )
535 mid++;
538 nearest = addr_sorttab[mid];
539 #if 0
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);
546 #endif
547 break;
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) )
553 low = mid;
555 else
557 high = mid;
562 if (!nearest) return NULL;
564 if( rtn != NULL )
566 *rtn = nearest;
570 * Fill in the relevant bits to the structure so that we can
571 * locate the source and line for this bit of code.
573 if( source != NULL )
575 source->sourcefile = nearest->sourcefile;
576 if( nearest->linetab == NULL )
578 source->line = -1;
580 else
582 source->line = nearest->linetab[0].line_number;
586 lineinfo = "";
587 lineno = -1;
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));
595 if( ebp != 0 )
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 )
605 continue;
608 ptr = (unsigned int *) (ebp + nearest->local_vars[i].offset);
609 if( arglist[0] == '\0' )
611 arglist[0] = '(';
613 else
615 strcat(arglist, ", ");
618 sprintf(argtmp, "%s=0x%x", nearest->local_vars[i].name,
619 *ptr);
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 )
637 low = 0;
638 high = nearest->n_lines;
639 while ((high - low) > 1)
641 mid = (high + low) / 2;
642 if (addr->off < nearest->linetab[mid].pc_offset.off)
643 high = mid;
644 else
645 low = mid;
647 lineno = nearest->linetab[low].line_number;
650 if( lineno != -1 )
652 sprintf(linebuff, ":%d", lineno);
653 lineinfo = linebuff;
654 if( source != NULL )
656 source->line = lineno;
660 /* Remove the path from the file name */
661 sourcefile = strrchr( nearest->sourcefile, '/' );
662 if (!sourcefile) sourcefile = nearest->sourcefile;
663 else sourcefile++;
665 if (addr->off == nearest->addr.off)
666 sprintf( name_buffer, "%s%s [%s%s]", nearest->name,
667 arglist, sourcefile, lineinfo);
668 else
669 sprintf( name_buffer, "%s+0x%lx%s [%s%s]", nearest->name,
670 addr->off - nearest->addr.off,
671 arglist, sourcefile, lineinfo );
673 else
675 if (addr->off == nearest->addr.off)
676 sprintf( name_buffer, "%s%s", nearest->name, arglist);
677 else {
678 if (addr->seg && (nearest->addr.seg!=addr->seg))
679 return NULL;
680 else
681 sprintf( name_buffer, "%s+0x%lx%s", nearest->name,
682 addr->off - nearest->addr.off, arglist);
685 return name_buffer;
689 /***********************************************************************
690 * DEBUG_ReadSymbolTable
692 * Read a symbol file into the hash table.
694 void DEBUG_ReadSymbolTable( const char * filename )
696 FILE * symbolfile;
697 DBG_ADDR addr = { 0, 0 };
698 int nargs;
699 char type;
700 char * cpnt;
701 char buffer[256];
702 char name[256];
704 if (!(symbolfile = fopen(filename, "r")))
706 fprintf( stderr, "Unable to open symbol table %s\n", filename );
707 return;
710 fprintf( stderr, "Reading symbols from file %s\n", filename );
712 while (1)
714 fgets( buffer, sizeof(buffer), symbolfile );
715 if (feof(symbolfile)) break;
717 /* Strip any text after a # sign (i.e. comments) */
718 cpnt = buffer;
719 while (*cpnt)
720 if(*cpnt++ == '#') { *cpnt = 0; break; }
722 /* Quietly ignore any lines that have just whitespace */
723 cpnt = buffer;
724 while(*cpnt)
726 if(*cpnt != ' ' && *cpnt != '\t') break;
727 cpnt++;
729 if (!(*cpnt) || *cpnt == '\n') continue;
731 nargs = sscanf(buffer, "%lx %c %s", &addr.off, &type, name);
732 DEBUG_AddSymbol( name, &addr, NULL, SYM_WINE );
734 fclose(symbolfile);
738 /***********************************************************************
739 * DEBUG_LoadEntryPoints16
741 * Load the entry points of a Win16 module into the hash table.
743 static void DEBUG_LoadEntryPoints16( HMODULE16 hModule, NE_MODULE *pModule,
744 const char *name )
746 DBG_ADDR addr;
747 char buffer[256];
748 FARPROC16 address;
750 /* First search the resident names */
752 unsigned char *cpnt = (unsigned char *)pModule + pModule->name_table;
753 while (*cpnt)
755 cpnt += *cpnt + 1 + sizeof(WORD);
756 sprintf( buffer, "%s.%.*s", name, *cpnt, cpnt + 1 );
757 if ((address = NE_GetEntryPoint(hModule, *(WORD *)(cpnt + *cpnt + 1))))
759 addr.seg = HIWORD(address);
760 addr.off = LOWORD(address);
761 addr.type = NULL;
762 DEBUG_AddSymbol( buffer, &addr, NULL, SYM_WIN32 | SYM_FUNC );
766 /* Now search the non-resident names table */
768 if (!pModule->nrname_handle) return; /* No non-resident table */
769 cpnt = (char *)GlobalLock16( pModule->nrname_handle );
770 while (*cpnt)
772 cpnt += *cpnt + 1 + sizeof(WORD);
773 sprintf( buffer, "%s.%.*s", name, *cpnt, cpnt + 1 );
774 if ((address = NE_GetEntryPoint(hModule, *(WORD *)(cpnt + *cpnt + 1))))
776 addr.seg = HIWORD(address);
777 addr.off = LOWORD(address);
778 addr.type = NULL;
779 DEBUG_AddSymbol( buffer, &addr, NULL, SYM_WIN32 | SYM_FUNC );
785 /***********************************************************************
786 * DEBUG_LoadEntryPoints32
788 * Load the entry points of a Win32 module into the hash table.
790 static void DEBUG_LoadEntryPoints32( HMODULE32 hModule, const char *name )
792 #define RVA(x) (hModule+(DWORD)(x))
794 DBG_ADDR addr;
795 char buffer[256];
796 int i, j;
797 IMAGE_SECTION_HEADER *pe_seg;
798 IMAGE_EXPORT_DIRECTORY *exports;
799 IMAGE_DATA_DIRECTORY *dir;
800 WORD *ordinals;
801 void **functions;
802 const char **names;
804 addr.seg = 0;
805 addr.type = NULL;
807 /* Add start of DLL */
809 addr.off = hModule;
810 DEBUG_AddSymbol( name, &addr, NULL, SYM_WIN32 | SYM_FUNC );
812 /* Add entry point */
814 sprintf( buffer, "%s.EntryPoint", name );
815 addr.off = (DWORD)RVA_PTR( hModule, OptionalHeader.AddressOfEntryPoint );
816 DEBUG_AddSymbol( buffer, &addr, NULL, SYM_WIN32 | SYM_FUNC );
818 /* Add start of sections */
820 pe_seg = PE_SECTIONS(hModule);
821 for (i = 0; i < PE_HEADER(hModule)->FileHeader.NumberOfSections; i++)
823 sprintf( buffer, "%s.%s", name, pe_seg->Name );
824 addr.off = RVA(pe_seg->VirtualAddress );
825 DEBUG_AddSymbol( buffer, &addr, NULL, SYM_WIN32 | SYM_FUNC );
826 pe_seg++;
829 /* Add exported functions */
831 dir = &PE_HEADER(hModule)->OptionalHeader.
832 DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
833 if (!dir->Size) return;
834 exports = (IMAGE_EXPORT_DIRECTORY *)RVA( dir->VirtualAddress );
835 ordinals = (WORD *)RVA( exports->AddressOfNameOrdinals );
836 names = (const char **)RVA( exports->AddressOfNames );
837 functions = (void **)RVA( exports->AddressOfFunctions );
839 for (i = 0; i < exports->NumberOfNames; i++)
841 if (!names[i]) continue;
842 sprintf( buffer, "%s.%s", name, (char *)RVA(names[i]) );
843 addr.off = RVA( functions[ordinals[i]] );
844 DEBUG_AddSymbol( buffer, &addr, NULL, SYM_WIN32 | SYM_FUNC );
847 for (i = 0; i < exports->NumberOfFunctions; i++)
849 if (!functions[i]) continue;
850 /* Check if we already added it with a name */
851 for (j = 0; j < exports->NumberOfNames; j++)
852 if ((ordinals[j] == i) && names[j]) break;
853 if (j < exports->NumberOfNames) continue;
854 sprintf( buffer, "%s.%ld", name, i + exports->Base );
855 addr.off = (DWORD)RVA( functions[i] );
856 DEBUG_AddSymbol( buffer, &addr, NULL, SYM_WIN32 | SYM_FUNC );
859 dir = &PE_HEADER(hModule)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
860 if (dir->Size)
861 DEBUG_RegisterDebugInfo(hModule, name, dir->VirtualAddress, dir->Size);
862 #undef RVA
866 /***********************************************************************
867 * DEBUG_LoadEntryPoints
869 * Load the entry points of all the modules into the hash table.
871 void DEBUG_LoadEntryPoints(void)
873 MODULEENTRY entry;
874 NE_MODULE *pModule;
875 BOOL32 ok;
876 WINE_MODREF *wm;
877 int rowcount = 3;
879 fprintf( stderr, " " );
880 for (ok = ModuleFirst(&entry); ok; ok = ModuleNext(&entry))
882 if (!(pModule = NE_GetPtr( entry.hModule ))) continue;
883 if (!(pModule->flags & NE_FFLAGS_WIN32)) /* NE module */
885 if ((rowcount + strlen(entry.szModule)) > 76)
887 fprintf( stderr,"\n ");
888 rowcount = 3;
890 fprintf( stderr, " %s", entry.szModule );
891 rowcount += strlen(entry.szModule) + 1;
893 DEBUG_LoadEntryPoints16( entry.hModule, pModule, entry.szModule );
896 for (wm=PROCESS_Current()->modref_list;wm;wm=wm->next)
898 if ((rowcount + strlen(wm->modname)) > 76)
900 fprintf( stderr,"\n ");
901 rowcount = 3;
903 fprintf( stderr, " %s", wm->modname );
904 rowcount += strlen(wm->modname) + 1;
905 DEBUG_LoadEntryPoints32( wm->module, wm->modname );
907 fprintf( stderr, "\n" );
911 void
912 DEBUG_AddLineNumber( struct name_hash * func, int line_num,
913 unsigned long offset )
915 if( func == NULL )
917 return;
920 if( func->n_lines + 1 >= func->lines_alloc )
922 func->lines_alloc += 64;
923 func->linetab = xrealloc(func->linetab,
924 func->lines_alloc * sizeof(WineLineNo));
927 func->linetab[func->n_lines].line_number = line_num;
928 func->linetab[func->n_lines].pc_offset.seg = func->addr.seg;
929 func->linetab[func->n_lines].pc_offset.off = func->addr.off + offset;
930 func->linetab[func->n_lines].pc_offset.type = NULL;
931 func->n_lines++;
935 struct wine_locals *
936 DEBUG_AddLocal( struct name_hash * func, int regno,
937 int offset,
938 int pc_start,
939 int pc_end,
940 char * name)
942 if( func == NULL )
944 return NULL;
947 if( func->n_locals + 1 >= func->locals_alloc )
949 func->locals_alloc += 32;
950 func->local_vars = xrealloc(func->local_vars,
951 func->locals_alloc * sizeof(WineLocals));
954 func->local_vars[func->n_locals].regno = regno;
955 func->local_vars[func->n_locals].offset = offset;
956 func->local_vars[func->n_locals].pc_start = pc_start;
957 func->local_vars[func->n_locals].pc_end = pc_end;
958 func->local_vars[func->n_locals].name = xstrdup(name);
959 func->local_vars[func->n_locals].type = NULL;
960 func->n_locals++;
962 return &func->local_vars[func->n_locals - 1];
965 void
966 DEBUG_DumpHashInfo()
968 int i;
969 int depth;
970 struct name_hash *nh;
973 * Utility function to dump stats about the hash table.
975 for(i=0; i<NR_NAME_HASH; i++)
977 depth = 0;
978 for (nh = name_hash_table[i]; nh; nh = nh->next)
980 depth++;
982 fprintf(stderr, "Bucket %d: %d\n", i, depth);
986 /***********************************************************************
987 * DEBUG_CheckLinenoStatus
989 * Find the symbol nearest to a given address.
990 * If ebp is specified as non-zero, it means we should dump the argument
991 * list into the string we return as well.
993 int DEBUG_CheckLinenoStatus( const DBG_ADDR *addr)
995 struct name_hash * nearest = NULL;
996 int mid, high, low;
998 if( sortlist_valid == FALSE )
1000 DEBUG_ResortSymbols();
1004 * Binary search to find closest symbol.
1006 low = 0;
1007 high = sorttab_nsym;
1008 if( addr_sorttab[0]->addr.seg > addr->seg
1009 || ( addr_sorttab[0]->addr.seg == addr->seg
1010 && addr_sorttab[0]->addr.off > addr->off) )
1012 nearest = NULL;
1014 else if( addr_sorttab[high - 1]->addr.seg < addr->seg
1015 || ( addr_sorttab[high - 1]->addr.seg == addr->seg
1016 && addr_sorttab[high - 1]->addr.off < addr->off) )
1018 nearest = addr_sorttab[high - 1];
1020 else
1022 while(1==1)
1024 mid = (high + low)/2;
1025 if( mid == low )
1028 * See if there are any other entries that might also
1029 * have the same address, and would also have a line
1030 * number table.
1032 if( mid > 0 && addr_sorttab[mid]->linetab == NULL )
1034 if( (addr_sorttab[mid - 1]->addr.seg ==
1035 addr_sorttab[mid]->addr.seg)
1036 && (addr_sorttab[mid - 1]->addr.off ==
1037 addr_sorttab[mid]->addr.off)
1038 && (addr_sorttab[mid - 1]->linetab != NULL) )
1040 mid--;
1044 if( (mid < sorttab_nsym - 1)
1045 && (addr_sorttab[mid]->linetab == NULL) )
1047 if( (addr_sorttab[mid + 1]->addr.seg ==
1048 addr_sorttab[mid]->addr.seg)
1049 && (addr_sorttab[mid + 1]->addr.off ==
1050 addr_sorttab[mid]->addr.off)
1051 && (addr_sorttab[mid + 1]->linetab != NULL) )
1053 mid++;
1056 nearest = addr_sorttab[mid];
1057 #if 0
1058 fprintf(stderr, "Found %x:%x when looking for %x:%x %x %s\n",
1059 addr_sorttab[mid ]->addr.seg,
1060 addr_sorttab[mid ]->addr.off,
1061 addr->seg, addr->off,
1062 addr_sorttab[mid ]->linetab,
1063 addr_sorttab[mid ]->name);
1064 #endif
1065 break;
1067 if( (addr_sorttab[mid]->addr.seg < addr->seg)
1068 || ( addr_sorttab[mid]->addr.seg == addr->seg
1069 && addr_sorttab[mid]->addr.off <= addr->off) )
1071 low = mid;
1073 else
1075 high = mid;
1080 if (!nearest) return FUNC_HAS_NO_LINES;
1082 if( nearest->flags & SYM_STEP_THROUGH )
1085 * This will cause us to keep single stepping until
1086 * we get to the other side somewhere.
1088 return NOT_ON_LINENUMBER;
1091 if( (nearest->flags & SYM_TRAMPOLINE) )
1094 * This will cause us to keep single stepping until
1095 * we get to the other side somewhere.
1097 return FUNC_IS_TRAMPOLINE;
1100 if( nearest->linetab == NULL )
1102 return FUNC_HAS_NO_LINES;
1107 * We never want to stop on the first instruction of a function
1108 * even if it has it's own linenumber. Let the thing keep running
1109 * until it gets past the function prologue. We only do this if there
1110 * is more than one line number for the function, of course.
1112 if( nearest->addr.off == addr->off && nearest->n_lines > 1 )
1114 return NOT_ON_LINENUMBER;
1117 if( (nearest->sourcefile != NULL)
1118 && (addr->off - nearest->addr.off < 0x100000) )
1120 low = 0;
1121 high = nearest->n_lines;
1122 while ((high - low) > 1)
1124 mid = (high + low) / 2;
1125 if (addr->off < nearest->linetab[mid].pc_offset.off) high = mid;
1126 else low = mid;
1128 if (addr->off == nearest->linetab[low].pc_offset.off)
1129 return AT_LINENUMBER;
1130 else
1131 return NOT_ON_LINENUMBER;
1134 return FUNC_HAS_NO_LINES;
1137 /***********************************************************************
1138 * DEBUG_GetFuncInfo
1140 * Find the symbol nearest to a given address.
1141 * Returns sourcefile name and line number in a format that the listing
1142 * handler can deal with.
1144 void
1145 DEBUG_GetFuncInfo( struct list_id * ret, const char * filename,
1146 const char * name)
1148 char buffer[256];
1149 char * pnt;
1150 struct name_hash *nh;
1152 for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
1154 if( filename != NULL )
1157 if( nh->sourcefile == NULL )
1159 continue;
1162 pnt = strrchr(nh->sourcefile, '/');
1163 if( strcmp(nh->sourcefile, filename) != 0
1164 && (pnt == NULL || strcmp(pnt + 1, filename) != 0) )
1166 continue;
1169 if (!strcmp(nh->name, name)) break;
1172 if (!nh && (name[0] != '_'))
1174 buffer[0] = '_';
1175 strcpy(buffer+1, name);
1176 for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
1178 if( filename != NULL )
1180 if( nh->sourcefile == NULL )
1182 continue;
1185 pnt = strrchr(nh->sourcefile, '/');
1186 if( strcmp(nh->sourcefile, filename) != 0
1187 && (pnt == NULL || strcmp(pnt + 1, filename) != 0) )
1189 continue;
1192 if (!strcmp(nh->name, buffer)) break;
1196 if( !nh )
1198 if( filename != NULL )
1200 fprintf(stderr, "No such function %s in %s\n", name, filename);
1202 else
1204 fprintf(stderr, "No such function %s\n", name);
1206 ret->sourcefile = NULL;
1207 ret->line = -1;
1208 return;
1211 ret->sourcefile = nh->sourcefile;
1214 * Search for the specific line number. If we don't find it,
1215 * then return FALSE.
1217 if( nh->linetab == NULL )
1219 ret->line = -1;
1221 else
1223 ret->line = nh->linetab[0].line_number;
1227 /***********************************************************************
1228 * DEBUG_GetStackSymbolValue
1230 * Get the address of a named symbol from the current stack frame.
1232 static
1233 BOOL32 DEBUG_GetStackSymbolValue( const char * name, DBG_ADDR *addr )
1235 struct name_hash * curr_func;
1236 unsigned int ebp;
1237 unsigned int eip;
1238 int i;
1240 if( DEBUG_GetCurrentFrame(&curr_func, &eip, &ebp) == FALSE )
1242 return FALSE;
1245 for(i=0; i < curr_func->n_locals; i++ )
1248 * Test the range of validity of the local variable. This
1249 * comes up with RBRAC/LBRAC stabs in particular.
1251 if( (curr_func->local_vars[i].pc_start != 0)
1252 && ((eip - curr_func->addr.off)
1253 < curr_func->local_vars[i].pc_start) )
1255 continue;
1258 if( (curr_func->local_vars[i].pc_end != 0)
1259 && ((eip - curr_func->addr.off)
1260 > curr_func->local_vars[i].pc_end) )
1262 continue;
1265 if( strcmp(name, curr_func->local_vars[i].name) == 0 )
1268 * OK, we found it. Now figure out what to do with this.
1270 if( curr_func->local_vars[i].regno != 0 )
1273 * Register variable. We don't know how to treat
1274 * this yet.
1276 return FALSE;
1279 addr->seg = 0;
1280 addr->off = ebp + curr_func->local_vars[i].offset;
1281 addr->type = curr_func->local_vars[i].type;
1283 return TRUE;
1286 return FALSE;
1290 DEBUG_InfoLocals()
1292 struct name_hash * curr_func;
1293 unsigned int ebp;
1294 unsigned int eip;
1295 int i;
1296 unsigned int * ptr;
1297 int rtn = FALSE;
1299 if( DEBUG_GetCurrentFrame(&curr_func, &eip, &ebp) == FALSE )
1301 return FALSE;
1304 for(i=0; i < curr_func->n_locals; i++ )
1307 * Test the range of validity of the local variable. This
1308 * comes up with RBRAC/LBRAC stabs in particular.
1310 if( (curr_func->local_vars[i].pc_start != 0)
1311 && ((eip - curr_func->addr.off)
1312 < curr_func->local_vars[i].pc_start) )
1314 continue;
1317 if( (curr_func->local_vars[i].pc_end != 0)
1318 && ((eip - curr_func->addr.off)
1319 > curr_func->local_vars[i].pc_end) )
1321 continue;
1324 if( curr_func->local_vars[i].offset == 0 )
1326 fprintf(stderr, "%s:%s optimized into register $%s \n",
1327 curr_func->name, curr_func->local_vars[i].name,
1328 reg_name[curr_func->local_vars[i].regno]);
1330 else
1332 ptr = (unsigned int *) (ebp + curr_func->local_vars[i].offset);
1333 fprintf(stderr, "%s:%s == 0x%8.8x\n",
1334 curr_func->name, curr_func->local_vars[i].name,
1335 *ptr);
1339 rtn = TRUE;
1341 return (rtn);
1345 DEBUG_SetSymbolSize(struct name_hash * sym, unsigned int len)
1347 sym->symbol_size = len;
1349 return TRUE;
1353 DEBUG_SetSymbolBPOff(struct name_hash * sym, unsigned int off)
1355 sym->breakpoint_offset = off;
1357 return TRUE;
1361 DEBUG_GetSymbolAddr(struct name_hash * sym, DBG_ADDR * addr)
1364 *addr = sym->addr;
1366 return TRUE;
1369 int DEBUG_SetLocalSymbolType(struct wine_locals * sym, struct datatype * type)
1371 sym->type = type;
1373 return TRUE;