Release 970305
[wine] / debugger / hash.c
1 /*
2  * File hash.c - generate hash tables for Wine debugger symbols
3  *
4  * Copyright (C) 1993, Eric Youngdale.
5  */
6
7
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 "selectors.h"
16 #include "debugger.h"
17 #include "toolhelp.h"
18 #include "xmalloc.h"
19
20 #define NR_NAME_HASH 16384
21 #ifndef PATH_MAX
22 #define PATH_MAX _MAX_PATH
23 #endif
24
25 static char * reg_name[] =
26 {
27   "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
28 };
29
30
31 struct name_hash
32 {
33     struct name_hash * next;            /* Used to look up within name hash */
34     char *             name;
35     char *             sourcefile;
36
37     int                n_locals;
38     int                locals_alloc;
39     WineLocals       * local_vars;
40   
41     int                n_lines;
42     int                lines_alloc;
43     WineLineNo       * linetab;
44
45     DBG_ADDR           addr;
46     unsigned short     flags;
47     unsigned short     breakpoint_offset;
48     unsigned int       symbol_size;
49 };
50
51
52 static BOOL32 DEBUG_GetStackSymbolValue( const char * name, DBG_ADDR *addr );
53 static int sortlist_valid = FALSE;
54
55 static int sorttab_nsym;
56 static struct name_hash ** addr_sorttab = NULL;
57
58 static struct name_hash * name_hash_table[NR_NAME_HASH];
59
60 static unsigned int name_hash( const char * name )
61 {
62     unsigned int hash = 0;
63     unsigned int tmp;
64     const char * p;
65
66     p = name;
67
68     while (*p) 
69       {
70         hash = (hash << 4) + *p++;
71
72         if( (tmp = (hash & 0xf0000000)) )
73           {
74             hash ^= tmp >> 24;
75           }
76         hash &= ~tmp;
77       }
78     return hash % NR_NAME_HASH;
79 }
80
81 int
82 DEBUG_cmp_sym(const void * p1, const void * p2)
83 {
84   struct name_hash ** name1 = (struct name_hash **) p1;
85   struct name_hash ** name2 = (struct name_hash **) p2;
86
87   if( ((*name1)->flags & SYM_INVALID) != 0 )
88     {
89       return -1;
90     }
91
92   if( ((*name2)->flags & SYM_INVALID) != 0 )
93     {
94       return 1;
95     }
96
97   if( (*name1)->addr.seg > (*name2)->addr.seg )
98     {
99       return 1;
100     }
101
102   if( (*name1)->addr.seg < (*name2)->addr.seg )
103     {
104       return -1;
105     }
106
107   if( (*name1)->addr.off > (*name2)->addr.off )
108     {
109       return 1;
110     }
111
112   if( (*name1)->addr.off < (*name2)->addr.off )
113     {
114       return -1;
115     }
116
117   return 0;
118 }
119
120 /***********************************************************************
121  *           DEBUG_ResortSymbols
122  *
123  * Rebuild sorted list of symbols.
124  */
125 static
126 void
127 DEBUG_ResortSymbols()
128 {
129     struct name_hash *nh;
130     int         nsym = 0;
131     int         i;
132
133     for(i=0; i<NR_NAME_HASH; i++)
134     {
135         for (nh = name_hash_table[i]; nh; nh = nh->next)
136           {
137             nsym++;
138           }
139     }
140
141     sorttab_nsym = nsym;
142     if( nsym == 0 )
143       {
144         return;
145       }
146
147     addr_sorttab = (struct name_hash **) xrealloc(addr_sorttab, 
148                                          nsym * sizeof(struct name_hash *));
149
150     nsym = 0;
151     for(i=0; i<NR_NAME_HASH; i++)
152     {
153         for (nh = name_hash_table[i]; nh; nh = nh->next)
154           {
155             addr_sorttab[nsym++] = nh;
156           }
157     }
158
159     qsort(addr_sorttab, nsym,
160           sizeof(struct name_hash *), DEBUG_cmp_sym);
161     sortlist_valid = TRUE;
162
163 }
164
165 /***********************************************************************
166  *           DEBUG_AddSymbol
167  *
168  * Add a symbol to the table.
169  */
170 struct name_hash *
171 DEBUG_AddSymbol( const char * name, const DBG_ADDR *addr, const char * source,
172                  int flags)
173 {
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;
178     char * c;
179     int hash;
180
181     hash = name_hash(name);
182     for (nh = name_hash_table[hash]; nh; nh = nh->next)
183     {
184         if( ((nh->flags & SYM_INVALID) != 0) && strcmp(name, nh->name) == 0 )
185         {
186             nh->addr.off = addr->off;
187             nh->addr.seg = addr->seg;
188             if( nh->addr.type == NULL && addr->type != NULL )
189             {
190                 nh->addr.type = addr->type;
191             }
192             nh->flags &= ~SYM_INVALID;
193             return nh;
194         }
195         if (nh->addr.seg == addr->seg &&
196             nh->addr.off == addr->off &&
197             strcmp(name, nh->name) == 0 )
198         {
199             return nh;
200         }
201     }
202
203     /*
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.
206      */
207     
208     new = (struct name_hash *) xmalloc(sizeof(struct name_hash));
209     new->addr = *addr;
210     new->name = xstrdup(name);
211
212     if( source != NULL )
213       {
214         /*
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.
218          */
219         if( strcmp(source, prev_source) == 0 )
220           {
221             new->sourcefile = prev_duped_source;
222           }
223         else
224           {
225             strcpy(prev_source, source);
226             prev_duped_source = new->sourcefile = xstrdup(source);
227           }
228       }
229     else
230       {
231         new->sourcefile = NULL;
232       }
233
234     new->n_lines        = 0;
235     new->lines_alloc    = 0;
236     new->linetab        = NULL;
237
238     new->n_locals       = 0;
239     new->locals_alloc   = 0;
240     new->local_vars     = NULL;
241
242     new->flags          = flags;
243     new->next           = NULL;
244
245     /* Now insert into the hash table */
246     new->next = name_hash_table[hash];
247     name_hash_table[hash] = new;
248
249     /*
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.
255      */
256     if( source != NULL )
257       {
258         c = strrchr(source, '.');
259         if( c != NULL && strcmp(c, ".s") == 0 )
260           {
261             c = strrchr(source, '/');
262             if( c != NULL )
263               {
264                 c++;
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) )
269                   {
270                     new->flags |= SYM_TRAMPOLINE;
271                   }
272               }
273           }
274       }
275
276     sortlist_valid = FALSE;
277     return new;
278 }
279
280 BOOL32 DEBUG_Normalize(struct name_hash * nh )
281 {
282
283   /*
284    * We aren't adding any more locals or linenumbers to this function.
285    * Free any spare memory that we might have allocated.
286    */
287   if( nh == NULL )
288     {
289       return TRUE;
290     }
291
292   if( nh->n_locals != nh->locals_alloc )
293     {
294       nh->locals_alloc = nh->n_locals;
295       nh->local_vars = xrealloc(nh->local_vars,
296                                   nh->locals_alloc * sizeof(WineLocals));
297     }
298
299   if( nh->n_lines != nh->lines_alloc )
300     {
301       nh->lines_alloc = nh->n_lines;
302       nh->linetab = xrealloc(nh->linetab,
303                               nh->lines_alloc * sizeof(WineLineNo));
304     }
305
306   return TRUE;
307 }
308
309 /***********************************************************************
310  *           DEBUG_GetSymbolValue
311  *
312  * Get the address of a named symbol.
313  */
314 BOOL32 DEBUG_GetSymbolValue( const char * name, const int lineno, 
315                              DBG_ADDR *addr, int bp_flag )
316 {
317     char buffer[256];
318     struct name_hash *nh;
319
320     for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
321       {
322         if( (nh->flags & SYM_INVALID) != 0 )
323           {
324             continue;
325           }
326
327         if (!strcmp(nh->name, name)) break;
328       }
329
330     if (!nh && (name[0] != '_'))
331     {
332         buffer[0] = '_';
333         strcpy(buffer+1, name);
334         for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
335           {
336             if( (nh->flags & SYM_INVALID) != 0 )
337               {
338                 continue;
339               }
340             if (!strcmp(nh->name, buffer)) break;
341           }
342     }
343
344     /*
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.
349      */
350     if (!nh) 
351       {
352         return DEBUG_GetStackSymbolValue(name, addr);
353       }
354
355     return DEBUG_GetLineNumberAddr( nh, lineno, addr, bp_flag );
356 }
357
358 /***********************************************************************
359  *           DEBUG_GetLineNumberAddr
360  *
361  * Get the address of a named symbol.
362  */
363 BOOL32 DEBUG_GetLineNumberAddr( struct name_hash * nh, const int lineno, 
364                                 DBG_ADDR *addr, int bp_flag )
365 {
366     int i;
367
368     if( lineno == -1 )
369       {
370         *addr = nh->addr;
371         if( bp_flag )
372           {
373             addr->off += nh->breakpoint_offset;
374           }
375       }
376     else
377       {
378         /*
379          * Search for the specific line number.  If we don't find it,
380          * then return FALSE.
381          */
382         if( nh->linetab == NULL )
383           {
384             return FALSE;
385           }
386
387         for(i=0; i < nh->n_lines; i++ )
388           {
389             if( nh->linetab[i].line_number == lineno )
390               {
391                 *addr = nh->linetab[i].pc_offset;
392                 return TRUE;
393               }
394           }
395
396         /*
397          * This specific line number not found.
398          */
399         return FALSE;
400       }
401
402     return TRUE;
403 }
404
405
406 /***********************************************************************
407  *           DEBUG_SetSymbolValue
408  *
409  * Set the address of a named symbol.
410  */
411 BOOL32 DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr )
412 {
413     char buffer[256];
414     struct name_hash *nh;
415
416     for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
417         if (!strcmp(nh->name, name)) break;
418
419     if (!nh && (name[0] != '_'))
420     {
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;
425     }
426
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;
432 }
433
434
435 /***********************************************************************
436  *           DEBUG_FindNearestSymbol
437  *
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.
441  */
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)
446 {
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];
457
458     if( rtn != NULL )
459       {
460         *rtn = NULL;
461       }
462
463     if( source != NULL )
464       {
465         source->sourcefile = NULL;
466         source->line = -1;
467       }
468
469     if( sortlist_valid == FALSE )
470       {
471         DEBUG_ResortSymbols();
472       }
473
474     if( sortlist_valid == FALSE )
475       {
476         return NULL;
477       }
478
479     /*
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.
484      */
485     /*
486      * Binary search to find closest symbol.
487      */
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) )
493       {
494         nearest = NULL;
495       }
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) )
499       {
500         nearest = addr_sorttab[high - 1];
501       }
502     else
503       {
504         while(1==1)
505           {
506             mid = (high + low)/2;
507             if( mid == low )
508               {
509                 /* 
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.  
513                  */
514                 if( mid > 0 && addr_sorttab[mid]->linetab == NULL )
515                   {
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) )
521                       {
522                         mid--;
523                       }
524                   }
525
526                 if(    (mid < sorttab_nsym - 1)
527                     && (addr_sorttab[mid]->linetab == NULL) )
528                   {
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) )
534                       {
535                         mid++;
536                       }
537                   }
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;
548               }
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) )
552               {
553                 low = mid;
554               }
555             else
556               {
557                 high = mid;
558               }
559           }
560       }
561
562     if (!nearest) return NULL;
563
564     if( rtn != NULL )
565       {
566         *rtn = nearest;
567       }
568
569     /*
570      * Fill in the relevant bits to the structure so that we can
571      * locate the source and line for this bit of code.
572      */
573     if( source != NULL )
574       {
575         source->sourcefile = nearest->sourcefile;
576         if( nearest->linetab == NULL )
577           {
578             source->line = -1;
579           }
580         else
581           {
582             source->line = nearest->linetab[0].line_number;
583           }
584       }
585
586     lineinfo = "";
587     lineno = -1;
588
589     /*
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.
593      */
594     memset(arglist, '\0', sizeof(arglist));
595     if( ebp != 0 )
596       {
597         for(i=0; i < nearest->n_locals; i++ )
598           {
599             /*
600              * If this is a register (offset == 0) or a local
601              * variable, we don't want to know about it.
602              */
603             if( nearest->local_vars[i].offset <= 0 )
604               {
605                 continue;
606               }
607
608             ptr = (unsigned int *) (ebp + nearest->local_vars[i].offset);
609             if( arglist[0] == '\0' )
610               {
611                 arglist[0] = '(';
612               }
613             else
614               {
615                 strcat(arglist, ", ");
616               }
617
618             sprintf(argtmp, "%s=0x%x", nearest->local_vars[i].name,
619                     *ptr);
620             strcat(arglist, argtmp);
621           }
622         if( arglist[0] == '(' )
623           {
624             strcat(arglist, ")");
625           }
626       }
627
628     if( (nearest->sourcefile != NULL) && (flag == TRUE)
629         && (addr->off - nearest->addr.off < 0x100000) )
630       {
631
632         /*
633          * Try and find the nearest line number to the current offset.
634          */
635         if( nearest->linetab != NULL )
636           {
637             /*
638              * FIXME - this is an inefficient linear search.  A binary
639              * search would be better if this gets to be a performance
640              * bottleneck.
641              */
642             for(i=0; i < nearest->n_lines; i++)
643               {
644                 if( addr->off < nearest->linetab[i].pc_offset.off )
645                 {
646                   break;
647                 }
648                 lineno = nearest->linetab[i].line_number;
649               }
650           }
651
652         if( lineno != -1 )
653           {
654             sprintf(linebuff, ":%d", lineno);
655             lineinfo = linebuff;
656             if( source != NULL )
657               {
658                 source->line = lineno;
659               }
660           }
661
662         /* Remove the path from the file name */
663         sourcefile = strrchr( nearest->sourcefile, '/' );
664         if (!sourcefile) sourcefile = nearest->sourcefile;
665         else sourcefile++;
666
667         if (addr->off == nearest->addr.off)
668           sprintf( name_buffer, "%s%s [%s%s]", nearest->name, 
669                    arglist, sourcefile, lineinfo);
670         else
671           sprintf( name_buffer, "%s+0x%lx%s [%s%s]", nearest->name,
672                    addr->off - nearest->addr.off, 
673                    arglist, sourcefile, lineinfo );
674       }
675     else
676       {
677         if (addr->off == nearest->addr.off)
678           sprintf( name_buffer, "%s%s", nearest->name, arglist);
679         else
680           sprintf( name_buffer, "%s+0x%lx%s", nearest->name,
681                    addr->off - nearest->addr.off, arglist);
682       }
683     return name_buffer;
684 }
685
686
687 /***********************************************************************
688  *           DEBUG_ReadSymbolTable
689  *
690  * Read a symbol file into the hash table.
691  */
692 void DEBUG_ReadSymbolTable( const char * filename )
693 {
694     FILE * symbolfile;
695     DBG_ADDR addr = { 0, 0 };
696     int nargs;
697     char type;
698     char * cpnt;
699     char buffer[256];
700     char name[256];
701
702     if (!(symbolfile = fopen(filename, "r")))
703     {
704         fprintf( stderr, "Unable to open symbol table %s\n", filename );
705         return;
706     }
707
708     fprintf( stderr, "Reading symbols from file %s\n", filename );
709
710     while (1)
711     {
712         fgets( buffer, sizeof(buffer), symbolfile );
713         if (feof(symbolfile)) break;
714                 
715         /* Strip any text after a # sign (i.e. comments) */
716         cpnt = buffer;
717         while (*cpnt)
718             if(*cpnt++ == '#') { *cpnt = 0; break; }
719                 
720         /* Quietly ignore any lines that have just whitespace */
721         cpnt = buffer;
722         while(*cpnt)
723         {
724             if(*cpnt != ' ' && *cpnt != '\t') break;
725             cpnt++;
726         }
727         if (!(*cpnt) || *cpnt == '\n') continue;
728                 
729         nargs = sscanf(buffer, "%lx %c %s", &addr.off, &type, name);
730         DEBUG_AddSymbol( name, &addr, NULL, SYM_WINE );
731     }
732     fclose(symbolfile);
733 }
734
735
736 /***********************************************************************
737  *           DEBUG_LoadEntryPoints
738  *
739  * Load the entry points of all the modules into the hash table.
740  */
741 void DEBUG_LoadEntryPoints(void)
742 {
743     MODULEENTRY entry;
744     NE_MODULE *pModule;
745     DBG_ADDR addr;
746     char buffer[256];
747     unsigned char *cpnt, *name;
748     FARPROC16 address;
749     BOOL32 ok;
750
751     for (ok = ModuleFirst(&entry); ok; ok = ModuleNext(&entry))
752     {
753         if (!(pModule = MODULE_GetPtr( entry.hModule ))) continue;
754         if (pModule->flags & NE_FFLAGS_WIN32) continue;
755
756         name = (unsigned char *)pModule + pModule->name_table;
757
758         fprintf( stderr, "Loading symbols from Win16 module %.*s...\n",
759                  *name, name + 1 );
760
761         /* First search the resident names */
762
763         cpnt = (unsigned char *)pModule + pModule->name_table;
764         while (*cpnt)
765         {
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) )))
770             {
771                 addr.seg = HIWORD(address);
772                 addr.off = LOWORD(address);
773                 addr.type = NULL;
774                 DEBUG_AddSymbol( buffer, &addr, NULL, SYM_WIN32 | SYM_FUNC );
775             }
776         }
777
778         /* Now search the non-resident names table */
779
780         if (!pModule->nrname_handle) continue;  /* No non-resident table */
781         cpnt = (char *)GlobalLock16( pModule->nrname_handle );
782         while (*cpnt)
783         {
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) )))
788             {
789                 addr.seg = HIWORD(address);
790                 addr.off = LOWORD(address);
791                 addr.type = NULL;
792                 DEBUG_AddSymbol( buffer, &addr, NULL, SYM_WIN32);
793             }
794         }
795     }
796 }
797
798 void
799 DEBUG_AddLineNumber( struct name_hash * func, int line_num, 
800                      unsigned long offset )
801 {
802   if( func == NULL )
803     {
804       return;
805     }
806
807   if( func->n_lines + 1 >= func->lines_alloc )
808     {
809       func->lines_alloc += 64;
810       func->linetab = xrealloc(func->linetab,
811                               func->lines_alloc * sizeof(WineLineNo));
812     }
813
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;
818   func->n_lines++;
819 }
820
821
822 struct wine_locals *
823 DEBUG_AddLocal( struct name_hash * func, int regno, 
824                 int offset,
825                 int pc_start,
826                 int pc_end,
827                 char * name)
828 {
829   if( func == NULL )
830     {
831       return NULL;
832     }
833
834   if( func->n_locals + 1 >= func->locals_alloc )
835     {
836       func->locals_alloc += 32;
837       func->local_vars = xrealloc(func->local_vars,
838                               func->locals_alloc * sizeof(WineLocals));
839     }
840
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;
847   func->n_locals++;
848
849   return &func->local_vars[func->n_locals - 1];
850 }
851
852 void
853 DEBUG_DumpHashInfo()
854 {
855   int i;
856   int depth;
857   struct name_hash *nh;
858
859   /*
860    * Utility function to dump stats about the hash table.
861    */
862     for(i=0; i<NR_NAME_HASH; i++)
863     {
864       depth = 0;
865       for (nh = name_hash_table[i]; nh; nh = nh->next)
866         {
867           depth++;
868         }
869       fprintf(stderr, "Bucket %d: %d\n", i, depth);
870     }
871 }
872
873 /***********************************************************************
874  *           DEBUG_CheckLinenoStatus
875  *
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.
879  */
880 int DEBUG_CheckLinenoStatus( const DBG_ADDR *addr)
881 {
882     struct name_hash * nearest = NULL;
883     int mid, high, low;
884     int i;
885
886     if( sortlist_valid == FALSE )
887       {
888         DEBUG_ResortSymbols();
889       }
890
891     /*
892      * Binary search to find closest symbol.
893      */
894     low = 0;
895     high = sorttab_nsym;
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) )
899       {
900         nearest = NULL;
901       }
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) )
905       {
906         nearest = addr_sorttab[high - 1];
907       }
908     else
909       {
910         while(1==1)
911           {
912             mid = (high + low)/2;
913             if( mid == low )
914               {
915                 /* 
916                  * See if there are any other entries that might also
917                  * have the same address, and would also have a line
918                  * number table.  
919                  */
920                 if( mid > 0 && addr_sorttab[mid]->linetab == NULL )
921                   {
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) )
927                       {
928                         mid--;
929                       }
930                   }
931
932                 if(    (mid < sorttab_nsym - 1)
933                     && (addr_sorttab[mid]->linetab == NULL) )
934                   {
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) )
940                       {
941                         mid++;
942                       }
943                   }
944                 nearest = addr_sorttab[mid];
945 #if 0
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);
952 #endif
953                 break;
954               }
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) )
958               {
959                 low = mid;
960               }
961             else
962               {
963                 high = mid;
964               }
965           }
966       }
967
968     if (!nearest) return FUNC_HAS_NO_LINES;
969
970     if( nearest->flags & SYM_STEP_THROUGH )
971       {
972         /*
973          * This will cause us to keep single stepping until
974          * we get to the other side somewhere.
975          */
976         return NOT_ON_LINENUMBER;
977       }
978
979     if( (nearest->flags & SYM_TRAMPOLINE) )
980       {
981         /*
982          * This will cause us to keep single stepping until
983          * we get to the other side somewhere.
984          */
985         return FUNC_IS_TRAMPOLINE;
986       }
987
988     if( nearest->linetab == NULL )
989       {
990         return FUNC_HAS_NO_LINES;
991       }
992
993
994     /*
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.
999      */
1000     if( nearest->addr.off == addr->off && nearest->n_lines > 1 )
1001       {
1002         return NOT_ON_LINENUMBER;
1003       }
1004
1005     if( (nearest->sourcefile != NULL)
1006         && (addr->off - nearest->addr.off < 0x100000) )
1007       {
1008         /*
1009          * FIXME - this is an inefficient linear search.  A binary
1010          * search would be better if this gets to be a performance
1011          * bottleneck.
1012          */
1013         for(i=0; i < nearest->n_lines; i++)
1014           {
1015             if( addr->off == nearest->linetab[i].pc_offset.off )
1016               {
1017                 return AT_LINENUMBER;
1018               }
1019             if( addr->off < nearest->linetab[i].pc_offset.off )
1020               {
1021                 break;
1022               }
1023           }
1024
1025         return NOT_ON_LINENUMBER;
1026       }
1027
1028     return FUNC_HAS_NO_LINES;
1029 }
1030
1031 /***********************************************************************
1032  *           DEBUG_GetFuncInfo
1033  *
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.
1037  */
1038 void
1039 DEBUG_GetFuncInfo( struct list_id * ret, const char * filename, 
1040                    const char * name)
1041 {
1042     char buffer[256];
1043     char * pnt;
1044     struct name_hash *nh;
1045
1046     for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
1047       {
1048         if( filename != NULL )
1049           {
1050
1051             if( nh->sourcefile == NULL )
1052               {
1053                 continue;
1054               }
1055
1056             pnt = strrchr(nh->sourcefile, '/');
1057             if( strcmp(nh->sourcefile, filename) != 0
1058                 && (pnt == NULL || strcmp(pnt + 1, filename) != 0) )
1059               {
1060                 continue;
1061               }
1062           }
1063         if (!strcmp(nh->name, name)) break;
1064       }
1065
1066     if (!nh && (name[0] != '_'))
1067     {
1068         buffer[0] = '_';
1069         strcpy(buffer+1, name);
1070         for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
1071           {
1072             if( filename != NULL )
1073               {
1074                 if( nh->sourcefile == NULL )
1075                   {
1076                     continue;
1077                   }
1078
1079                 pnt = strrchr(nh->sourcefile, '/');
1080                 if( strcmp(nh->sourcefile, filename) != 0
1081                     && (pnt == NULL || strcmp(pnt + 1, filename) != 0) )
1082                   {
1083                     continue;
1084                   }
1085               }
1086             if (!strcmp(nh->name, buffer)) break;
1087           }
1088     }
1089
1090     if( !nh )
1091       {
1092         if( filename != NULL )
1093           {
1094             fprintf(stderr, "No such function %s in %s\n", name, filename);
1095           }
1096         else
1097           {
1098             fprintf(stderr, "No such function %s\n", name);
1099           }
1100         ret->sourcefile = NULL;
1101         ret->line = -1;
1102         return;
1103       }
1104
1105     ret->sourcefile = nh->sourcefile;
1106
1107     /*
1108      * Search for the specific line number.  If we don't find it,
1109      * then return FALSE.
1110      */
1111     if( nh->linetab == NULL )
1112       {
1113         ret->line = -1;
1114       }
1115     else
1116       {
1117         ret->line = nh->linetab[0].line_number;
1118       }
1119 }
1120
1121 /***********************************************************************
1122  *           DEBUG_GetStackSymbolValue
1123  *
1124  * Get the address of a named symbol from the current stack frame.
1125  */
1126 static
1127 BOOL32 DEBUG_GetStackSymbolValue( const char * name, DBG_ADDR *addr )
1128 {
1129   struct name_hash * curr_func;
1130   unsigned int       ebp;
1131   unsigned int       eip;
1132   int                i;
1133
1134   if( DEBUG_GetCurrentFrame(&curr_func, &eip, &ebp) == FALSE )
1135     {
1136       return FALSE;
1137     }
1138
1139   for(i=0; i < curr_func->n_locals; i++ )
1140     {
1141       /*
1142        * Test the range of validity of the local variable.  This
1143        * comes up with RBRAC/LBRAC stabs in particular.
1144        */
1145       if(    (curr_func->local_vars[i].pc_start != 0)
1146           && ((eip - curr_func->addr.off) 
1147               < curr_func->local_vars[i].pc_start) )
1148         {
1149           continue;
1150         }
1151
1152       if(    (curr_func->local_vars[i].pc_end != 0)
1153           && ((eip - curr_func->addr.off) 
1154               > curr_func->local_vars[i].pc_end) )
1155         {
1156           continue;
1157         }
1158
1159       if( strcmp(name, curr_func->local_vars[i].name) == 0 )
1160         {
1161           /*
1162            * OK, we found it.  Now figure out what to do with this.
1163            */
1164           if( curr_func->local_vars[i].regno != 0 )
1165             {
1166               /*
1167                * Register variable.  We don't know how to treat
1168                * this yet.
1169                */
1170               return FALSE;
1171             }
1172
1173           addr->seg = 0;
1174           addr->off = ebp + curr_func->local_vars[i].offset;
1175           addr->type = curr_func->local_vars[i].type;
1176
1177           return TRUE;
1178         }
1179     }
1180   return FALSE;
1181 }
1182
1183 int
1184 DEBUG_InfoLocals()
1185 {
1186   struct name_hash  * curr_func;
1187   unsigned int        ebp;
1188   unsigned int        eip;
1189   int                 i;
1190   unsigned int      * ptr;
1191   int                 rtn = FALSE;
1192
1193   if( DEBUG_GetCurrentFrame(&curr_func, &eip, &ebp) == FALSE )
1194     {
1195       return FALSE;
1196     }
1197
1198   for(i=0; i < curr_func->n_locals; i++ )
1199     {
1200       /*
1201        * Test the range of validity of the local variable.  This
1202        * comes up with RBRAC/LBRAC stabs in particular.
1203        */
1204       if(    (curr_func->local_vars[i].pc_start != 0)
1205           && ((eip - curr_func->addr.off) 
1206               < curr_func->local_vars[i].pc_start) )
1207         {
1208           continue;
1209         }
1210
1211       if(    (curr_func->local_vars[i].pc_end != 0)
1212           && ((eip - curr_func->addr.off) 
1213               > curr_func->local_vars[i].pc_end) )
1214         {
1215           continue;
1216         }
1217       
1218       if( curr_func->local_vars[i].offset == 0 )
1219         {
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]);
1223         }
1224       else
1225         {
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,
1229                   *ptr);
1230         }
1231     }
1232
1233   rtn = TRUE;
1234
1235   return (rtn);
1236 }
1237
1238 int
1239 DEBUG_SetSymbolSize(struct name_hash * sym, unsigned int len)
1240 {
1241   sym->symbol_size = len;
1242
1243   return TRUE;
1244 }
1245
1246 int
1247 DEBUG_SetSymbolBPOff(struct name_hash * sym, unsigned int off)
1248 {
1249   sym->breakpoint_offset = off;
1250
1251   return TRUE;
1252 }
1253
1254 int
1255 DEBUG_GetSymbolAddr(struct name_hash * sym, DBG_ADDR * addr)
1256 {
1257
1258   *addr = sym->addr;
1259
1260   return TRUE;
1261 }
1262
1263 int DEBUG_SetLocalSymbolType(struct wine_locals * sym, struct datatype * type)
1264 {
1265   sym->type = type;
1266
1267   return TRUE;
1268 }