acbdd6a8761bf6bf67086f9e4440da59780c3ef0
[platform/upstream/binutils.git] / gdb / psymtab.c
1 /* Partial symbol tables.
2    
3    Copyright (C) 2009-2013 Free Software Foundation, Inc.
4
5    This file is part of GDB.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21 #include "symtab.h"
22 #include "psympriv.h"
23 #include "objfiles.h"
24 #include "gdb_assert.h"
25 #include "block.h"
26 #include "filenames.h"
27 #include "source.h"
28 #include "addrmap.h"
29 #include "gdbtypes.h"
30 #include "bcache.h"
31 #include "ui-out.h"
32 #include "command.h"
33 #include "readline/readline.h"
34 #include "gdb_regex.h"
35 #include "dictionary.h"
36 #include "language.h"
37 #include "cp-support.h"
38 #include "gdbcmd.h"
39
40 #ifndef DEV_TTY
41 #define DEV_TTY "/dev/tty"
42 #endif
43
44 struct psymbol_bcache
45 {
46   struct bcache *bcache;
47 };
48
49 static struct partial_symbol *match_partial_symbol (struct objfile *,
50                                                     struct partial_symtab *,
51                                                     int,
52                                                     const char *, domain_enum,
53                                                     symbol_compare_ftype *,
54                                                     symbol_compare_ftype *);
55
56 static struct partial_symbol *lookup_partial_symbol (struct objfile *,
57                                                      struct partial_symtab *,
58                                                      const char *, int,
59                                                      domain_enum);
60
61 static char *psymtab_to_fullname (struct partial_symtab *ps);
62
63 static struct partial_symbol *find_pc_sect_psymbol (struct objfile *,
64                                                     struct partial_symtab *,
65                                                     CORE_ADDR,
66                                                     struct obj_section *);
67
68 static void fixup_psymbol_section (struct partial_symbol *psym,
69                                    struct objfile *objfile);
70
71 static struct symtab *psymtab_to_symtab (struct objfile *objfile,
72                                          struct partial_symtab *pst);
73
74 /* Ensure that the partial symbols for OBJFILE have been loaded.  This
75    function always returns its argument, as a convenience.  */
76
77 struct objfile *
78 require_partial_symbols (struct objfile *objfile, int verbose)
79 {
80   if ((objfile->flags & OBJF_PSYMTABS_READ) == 0)
81     {
82       objfile->flags |= OBJF_PSYMTABS_READ;
83
84       if (objfile->sf->sym_read_psymbols)
85         {
86           if (verbose)
87             {
88               printf_unfiltered (_("Reading symbols from %s..."),
89                                  objfile->name);
90               gdb_flush (gdb_stdout);
91             }
92           (*objfile->sf->sym_read_psymbols) (objfile);
93           if (verbose)
94             {
95               if (!objfile_has_symbols (objfile))
96                 {
97                   wrap_here ("");
98                   printf_unfiltered (_("(no debugging symbols found)..."));
99                   wrap_here ("");
100                 }
101
102               printf_unfiltered (_("done.\n"));
103             }
104         }
105     }
106
107   return objfile;
108 }
109
110 /* Traverse all psymtabs in one objfile, requiring that the psymtabs
111    be read in.  */
112
113 #define ALL_OBJFILE_PSYMTABS_REQUIRED(objfile, p)               \
114     for ((p) = require_partial_symbols (objfile, 1)->psymtabs;  \
115          (p) != NULL;                                           \
116          (p) = (p)->next)
117
118 /* We want to make sure this file always requires psymtabs.  */
119
120 #undef ALL_OBJFILE_PSYMTABS
121
122 /* Traverse all psymtabs in all objfiles.  */
123
124 #define ALL_PSYMTABS(objfile, p) \
125   ALL_OBJFILES (objfile)         \
126     ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, p)
127
128 /* Helper function for partial_map_symtabs_matching_filename that
129    expands the symtabs and calls the iterator.  */
130
131 static int
132 partial_map_expand_apply (struct objfile *objfile,
133                           const char *name,
134                           const char *full_path,
135                           const char *real_path,
136                           struct partial_symtab *pst,
137                           int (*callback) (struct symtab *, void *),
138                           void *data)
139 {
140   struct symtab *last_made = objfile->symtabs;
141
142   /* Shared psymtabs should never be seen here.  Instead they should
143      be handled properly by the caller.  */
144   gdb_assert (pst->user == NULL);
145
146   /* Don't visit already-expanded psymtabs.  */
147   if (pst->readin)
148     return 0;
149
150   /* This may expand more than one symtab, and we want to iterate over
151      all of them.  */
152   psymtab_to_symtab (objfile, pst);
153
154   return iterate_over_some_symtabs (name, full_path, real_path, callback, data,
155                                     objfile->symtabs, last_made);
156 }
157
158 /* Implementation of the map_symtabs_matching_filename method.  */
159
160 static int
161 partial_map_symtabs_matching_filename (struct objfile *objfile,
162                                        const char *name,
163                                        const char *full_path,
164                                        const char *real_path,
165                                        int (*callback) (struct symtab *,
166                                                         void *),
167                                        void *data)
168 {
169   struct partial_symtab *pst;
170   const char *name_basename = lbasename (name);
171   int is_abs = IS_ABSOLUTE_PATH (name);
172
173   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst)
174   {
175     /* We can skip shared psymtabs here, because any file name will be
176        attached to the unshared psymtab.  */
177     if (pst->user != NULL)
178       continue;
179
180     /* Anonymous psymtabs don't have a file name.  */
181     if (pst->anonymous)
182       continue;
183
184     if (FILENAME_CMP (name, pst->filename) == 0
185         || (!is_abs && compare_filenames_for_search (pst->filename, name)))
186       {
187         if (partial_map_expand_apply (objfile, name, full_path, real_path,
188                                       pst, callback, data))
189           return 1;
190       }
191
192     /* Before we invoke realpath, which can get expensive when many
193        files are involved, do a quick comparison of the basenames.  */
194     if (! basenames_may_differ
195         && FILENAME_CMP (name_basename, lbasename (pst->filename)) != 0)
196       continue;
197
198     /* If the user gave us an absolute path, try to find the file in
199        this symtab and use its absolute path.  */
200     if (full_path != NULL)
201       {
202         psymtab_to_fullname (pst);
203         if (pst->fullname != NULL
204             && (FILENAME_CMP (full_path, pst->fullname) == 0
205                 || (!is_abs && compare_filenames_for_search (pst->fullname,
206                                                              name))))
207           {
208             if (partial_map_expand_apply (objfile, name, full_path, real_path,
209                                           pst, callback, data))
210               return 1;
211           }
212       }
213
214     if (real_path != NULL)
215       {
216         char *rp = NULL;
217         psymtab_to_fullname (pst);
218         if (pst->fullname != NULL)
219           {
220             rp = gdb_realpath (pst->fullname);
221             make_cleanup (xfree, rp);
222           }
223         if (rp != NULL
224             && (FILENAME_CMP (real_path, rp) == 0
225                 || (!is_abs && compare_filenames_for_search (real_path, name))))
226           {
227             if (partial_map_expand_apply (objfile, name, full_path, real_path,
228                                           pst, callback, data))
229               return 1;
230           }
231       }
232   }
233
234   return 0;
235 }
236
237 /* Find which partial symtab contains PC and SECTION starting at psymtab PST.
238    We may find a different psymtab than PST.  See FIND_PC_SECT_PSYMTAB.  */
239
240 static struct partial_symtab *
241 find_pc_sect_psymtab_closer (struct objfile *objfile,
242                              CORE_ADDR pc, struct obj_section *section,
243                              struct partial_symtab *pst,
244                              struct minimal_symbol *msymbol)
245 {
246   struct partial_symtab *tpst;
247   struct partial_symtab *best_pst = pst;
248   CORE_ADDR best_addr = pst->textlow;
249
250   gdb_assert (!pst->psymtabs_addrmap_supported);
251
252   /* An objfile that has its functions reordered might have
253      many partial symbol tables containing the PC, but
254      we want the partial symbol table that contains the
255      function containing the PC.  */
256   if (!(objfile->flags & OBJF_REORDERED) &&
257       section == 0)     /* Can't validate section this way.  */
258     return pst;
259
260   if (msymbol == NULL)
261     return (pst);
262
263   /* The code range of partial symtabs sometimes overlap, so, in
264      the loop below, we need to check all partial symtabs and
265      find the one that fits better for the given PC address.  We
266      select the partial symtab that contains a symbol whose
267      address is closest to the PC address.  By closest we mean
268      that find_pc_sect_symbol returns the symbol with address
269      that is closest and still less than the given PC.  */
270   for (tpst = pst; tpst != NULL; tpst = tpst->next)
271     {
272       if (pc >= tpst->textlow && pc < tpst->texthigh)
273         {
274           struct partial_symbol *p;
275           CORE_ADDR this_addr;
276
277           /* NOTE: This assumes that every psymbol has a
278              corresponding msymbol, which is not necessarily
279              true; the debug info might be much richer than the
280              object's symbol table.  */
281           p = find_pc_sect_psymbol (objfile, tpst, pc, section);
282           if (p != NULL
283               && SYMBOL_VALUE_ADDRESS (p)
284               == SYMBOL_VALUE_ADDRESS (msymbol))
285             return tpst;
286
287           /* Also accept the textlow value of a psymtab as a
288              "symbol", to provide some support for partial
289              symbol tables with line information but no debug
290              symbols (e.g. those produced by an assembler).  */
291           if (p != NULL)
292             this_addr = SYMBOL_VALUE_ADDRESS (p);
293           else
294             this_addr = tpst->textlow;
295
296           /* Check whether it is closer than our current
297              BEST_ADDR.  Since this symbol address is
298              necessarily lower or equal to PC, the symbol closer
299              to PC is the symbol which address is the highest.
300              This way we return the psymtab which contains such
301              best match symbol.  This can help in cases where the
302              symbol information/debuginfo is not complete, like
303              for instance on IRIX6 with gcc, where no debug info
304              is emitted for statics.  (See also the nodebug.exp
305              testcase.)  */
306           if (this_addr > best_addr)
307             {
308               best_addr = this_addr;
309               best_pst = tpst;
310             }
311         }
312     }
313   return best_pst;
314 }
315
316 /* Find which partial symtab contains PC and SECTION.  Return 0 if
317    none.  We return the psymtab that contains a symbol whose address
318    exactly matches PC, or, if we cannot find an exact match, the
319    psymtab that contains a symbol whose address is closest to PC.  */
320 static struct partial_symtab *
321 find_pc_sect_psymtab (struct objfile *objfile, CORE_ADDR pc,
322                       struct obj_section *section,
323                       struct minimal_symbol *msymbol)
324 {
325   struct partial_symtab *pst;
326
327   /* Try just the PSYMTABS_ADDRMAP mapping first as it has better granularity
328      than the later used TEXTLOW/TEXTHIGH one.  */
329
330   if (objfile->psymtabs_addrmap != NULL)
331     {
332       pst = addrmap_find (objfile->psymtabs_addrmap, pc);
333       if (pst != NULL)
334         {
335           /* FIXME: addrmaps currently do not handle overlayed sections,
336              so fall back to the non-addrmap case if we're debugging
337              overlays and the addrmap returned the wrong section.  */
338           if (overlay_debugging && msymbol && section)
339             {
340               struct partial_symbol *p;
341
342               /* NOTE: This assumes that every psymbol has a
343                  corresponding msymbol, which is not necessarily
344                  true; the debug info might be much richer than the
345                  object's symbol table.  */
346               p = find_pc_sect_psymbol (objfile, pst, pc, section);
347               if (!p
348                   || SYMBOL_VALUE_ADDRESS (p)
349                   != SYMBOL_VALUE_ADDRESS (msymbol))
350                 goto next;
351             }
352
353           /* We do not try to call FIND_PC_SECT_PSYMTAB_CLOSER as
354              PSYMTABS_ADDRMAP we used has already the best 1-byte
355              granularity and FIND_PC_SECT_PSYMTAB_CLOSER may mislead us into
356              a worse chosen section due to the TEXTLOW/TEXTHIGH ranges
357              overlap.  */
358
359           return pst;
360         }
361     }
362
363  next:
364
365   /* Existing PSYMTABS_ADDRMAP mapping is present even for PARTIAL_SYMTABs
366      which still have no corresponding full SYMTABs read.  But it is not
367      present for non-DWARF2 debug infos not supporting PSYMTABS_ADDRMAP in GDB
368      so far.  */
369
370   /* Check even OBJFILE with non-zero PSYMTABS_ADDRMAP as only several of
371      its CUs may be missing in PSYMTABS_ADDRMAP as they may be varying
372      debug info type in single OBJFILE.  */
373
374   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst)
375     if (!pst->psymtabs_addrmap_supported
376         && pc >= pst->textlow && pc < pst->texthigh)
377       {
378         struct partial_symtab *best_pst;
379
380         best_pst = find_pc_sect_psymtab_closer (objfile, pc, section, pst,
381                                                 msymbol);
382         if (best_pst != NULL)
383           return best_pst;
384       }
385
386   return NULL;
387 }
388
389 static struct symtab *
390 find_pc_sect_symtab_from_partial (struct objfile *objfile,
391                                   struct minimal_symbol *msymbol,
392                                   CORE_ADDR pc, struct obj_section *section,
393                                   int warn_if_readin)
394 {
395   struct partial_symtab *ps = find_pc_sect_psymtab (objfile, pc, section,
396                                                     msymbol);
397   if (ps)
398     {
399       if (warn_if_readin && ps->readin)
400         /* Might want to error() here (in case symtab is corrupt and
401            will cause a core dump), but maybe we can successfully
402            continue, so let's not.  */
403         warning (_("\
404 (Internal error: pc %s in read in psymtab, but not in symtab.)\n"),
405                  paddress (get_objfile_arch (objfile), pc));
406       psymtab_to_symtab (objfile, ps);
407       return ps->symtab;
408     }
409   return NULL;
410 }
411
412 /* Find which partial symbol within a psymtab matches PC and SECTION.
413    Return 0 if none.  */
414
415 static struct partial_symbol *
416 find_pc_sect_psymbol (struct objfile *objfile,
417                       struct partial_symtab *psymtab, CORE_ADDR pc,
418                       struct obj_section *section)
419 {
420   struct partial_symbol *best = NULL, *p, **pp;
421   CORE_ADDR best_pc;
422
423   gdb_assert (psymtab != NULL);
424
425   /* Cope with programs that start at address 0.  */
426   best_pc = (psymtab->textlow != 0) ? psymtab->textlow - 1 : 0;
427
428   /* Search the global symbols as well as the static symbols, so that
429      find_pc_partial_function doesn't use a minimal symbol and thus
430      cache a bad endaddr.  */
431   for (pp = objfile->global_psymbols.list + psymtab->globals_offset;
432     (pp - (objfile->global_psymbols.list + psymtab->globals_offset)
433      < psymtab->n_global_syms);
434        pp++)
435     {
436       p = *pp;
437       if (SYMBOL_DOMAIN (p) == VAR_DOMAIN
438           && SYMBOL_CLASS (p) == LOC_BLOCK
439           && pc >= SYMBOL_VALUE_ADDRESS (p)
440           && (SYMBOL_VALUE_ADDRESS (p) > best_pc
441               || (psymtab->textlow == 0
442                   && best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0)))
443         {
444           if (section)          /* Match on a specific section.  */
445             {
446               fixup_psymbol_section (p, objfile);
447               if (!matching_obj_sections (SYMBOL_OBJ_SECTION (p), section))
448                 continue;
449             }
450           best_pc = SYMBOL_VALUE_ADDRESS (p);
451           best = p;
452         }
453     }
454
455   for (pp = objfile->static_psymbols.list + psymtab->statics_offset;
456     (pp - (objfile->static_psymbols.list + psymtab->statics_offset)
457      < psymtab->n_static_syms);
458        pp++)
459     {
460       p = *pp;
461       if (SYMBOL_DOMAIN (p) == VAR_DOMAIN
462           && SYMBOL_CLASS (p) == LOC_BLOCK
463           && pc >= SYMBOL_VALUE_ADDRESS (p)
464           && (SYMBOL_VALUE_ADDRESS (p) > best_pc
465               || (psymtab->textlow == 0
466                   && best_pc == 0 && SYMBOL_VALUE_ADDRESS (p) == 0)))
467         {
468           if (section)          /* Match on a specific section.  */
469             {
470               fixup_psymbol_section (p, objfile);
471               if (!matching_obj_sections (SYMBOL_OBJ_SECTION (p), section))
472                 continue;
473             }
474           best_pc = SYMBOL_VALUE_ADDRESS (p);
475           best = p;
476         }
477     }
478
479   return best;
480 }
481
482 static void
483 fixup_psymbol_section (struct partial_symbol *psym, struct objfile *objfile)
484 {
485   CORE_ADDR addr;
486
487   if (psym == NULL || SYMBOL_OBJ_SECTION (psym) != NULL)
488     return;
489
490   gdb_assert (objfile);
491
492   switch (SYMBOL_CLASS (psym))
493     {
494     case LOC_STATIC:
495     case LOC_LABEL:
496     case LOC_BLOCK:
497       addr = SYMBOL_VALUE_ADDRESS (psym);
498       break;
499     default:
500       /* Nothing else will be listed in the minsyms -- no use looking
501          it up.  */
502       return;
503     }
504
505   fixup_section (&psym->ginfo, addr, objfile);
506 }
507
508 static struct symtab *
509 lookup_symbol_aux_psymtabs (struct objfile *objfile,
510                             int block_index, const char *name,
511                             const domain_enum domain)
512 {
513   struct partial_symtab *ps;
514   const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0);
515   struct symtab *stab_best = NULL;
516
517   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
518   {
519     if (!ps->readin && lookup_partial_symbol (objfile, ps, name,
520                                               psymtab_index, domain))
521       {
522         struct symbol *sym = NULL;
523         struct symtab *stab = psymtab_to_symtab (objfile, ps);
524
525         /* Some caution must be observed with overloaded functions
526            and methods, since the psymtab will not contain any overload
527            information (but NAME might contain it).  */
528         if (stab->primary)
529           {
530             struct blockvector *bv = BLOCKVECTOR (stab);
531             struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
532
533             sym = lookup_block_symbol (block, name, domain);
534           }
535
536         if (sym && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0)
537           {
538             if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
539               return stab;
540
541             stab_best = stab;
542           }
543
544         /* Keep looking through other psymtabs.  */
545       }
546   }
547
548   return stab_best;
549 }
550
551 /* Look in PST for a symbol in DOMAIN whose name matches NAME.  Search
552    the global block of PST if GLOBAL, and otherwise the static block.
553    MATCH is the comparison operation that returns true iff MATCH (s,
554    NAME), where s is a SYMBOL_SEARCH_NAME.  If ORDERED_COMPARE is
555    non-null, the symbols in the block are assumed to be ordered
556    according to it (allowing binary search).  It must be compatible
557    with MATCH.  Returns the symbol, if found, and otherwise NULL.  */
558
559 static struct partial_symbol *
560 match_partial_symbol (struct objfile *objfile,
561                       struct partial_symtab *pst, int global,
562                       const char *name, domain_enum domain,
563                       symbol_compare_ftype *match,
564                       symbol_compare_ftype *ordered_compare)
565 {
566   struct partial_symbol **start, **psym;
567   struct partial_symbol **top, **real_top, **bottom, **center;
568   int length = (global ? pst->n_global_syms : pst->n_static_syms);
569   int do_linear_search = 1;
570
571   if (length == 0)
572       return NULL;
573   start = (global ?
574            objfile->global_psymbols.list + pst->globals_offset :
575            objfile->static_psymbols.list + pst->statics_offset);
576
577   if (global && ordered_compare)  /* Can use a binary search.  */
578     {
579       do_linear_search = 0;
580
581       /* Binary search.  This search is guaranteed to end with center
582          pointing at the earliest partial symbol whose name might be
583          correct.  At that point *all* partial symbols with an
584          appropriate name will be checked against the correct
585          domain.  */
586
587       bottom = start;
588       top = start + length - 1;
589       real_top = top;
590       while (top > bottom)
591         {
592           center = bottom + (top - bottom) / 2;
593           gdb_assert (center < top);
594           if (!do_linear_search
595               && (SYMBOL_LANGUAGE (*center) == language_java))
596             do_linear_search = 1;
597           if (ordered_compare (SYMBOL_SEARCH_NAME (*center), name) >= 0)
598             top = center;
599           else
600             bottom = center + 1;
601         }
602       gdb_assert (top == bottom);
603
604       while (top <= real_top
605              && match (SYMBOL_SEARCH_NAME (*top), name) == 0)
606         {
607           if (symbol_matches_domain (SYMBOL_LANGUAGE (*top),
608                                      SYMBOL_DOMAIN (*top), domain))
609             return *top;
610           top++;
611         }
612     }
613
614   /* Can't use a binary search or else we found during the binary search that
615      we should also do a linear search.  */
616
617   if (do_linear_search)
618     {
619       for (psym = start; psym < start + length; psym++)
620         {
621           if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym),
622                                      SYMBOL_DOMAIN (*psym), domain)
623               && match (SYMBOL_SEARCH_NAME (*psym), name) == 0)
624             return *psym;
625         }
626     }
627
628   return NULL;
629 }
630
631 /* Returns the name used to search psymtabs.  Unlike symtabs, psymtabs do
632    not contain any method/function instance information (since this would
633    force reading type information while reading psymtabs).  Therefore,
634    if NAME contains overload information, it must be stripped before searching
635    psymtabs.
636
637    The caller is responsible for freeing the return result.  */
638
639 static char *
640 psymtab_search_name (const char *name)
641 {
642   switch (current_language->la_language)
643     {
644     case language_cplus:
645     case language_java:
646       {
647        if (strchr (name, '('))
648          {
649            char *ret = cp_remove_params (name);
650
651            if (ret)
652              return ret;
653          }
654       }
655       break;
656
657     default:
658       break;
659     }
660
661   return xstrdup (name);
662 }
663
664 /* Look, in partial_symtab PST, for symbol whose natural name is NAME.
665    Check the global symbols if GLOBAL, the static symbols if not.  */
666
667 static struct partial_symbol *
668 lookup_partial_symbol (struct objfile *objfile,
669                        struct partial_symtab *pst, const char *name,
670                        int global, domain_enum domain)
671 {
672   struct partial_symbol **start, **psym;
673   struct partial_symbol **top, **real_top, **bottom, **center;
674   int length = (global ? pst->n_global_syms : pst->n_static_syms);
675   int do_linear_search = 1;
676   char *search_name;
677   struct cleanup *cleanup;
678
679   if (length == 0)
680     {
681       return (NULL);
682     }
683
684   search_name = psymtab_search_name (name);
685   cleanup = make_cleanup (xfree, search_name);
686   start = (global ?
687            objfile->global_psymbols.list + pst->globals_offset :
688            objfile->static_psymbols.list + pst->statics_offset);
689
690   if (global)                   /* This means we can use a binary search.  */
691     {
692       do_linear_search = 0;
693
694       /* Binary search.  This search is guaranteed to end with center
695          pointing at the earliest partial symbol whose name might be
696          correct.  At that point *all* partial symbols with an
697          appropriate name will be checked against the correct
698          domain.  */
699
700       bottom = start;
701       top = start + length - 1;
702       real_top = top;
703       while (top > bottom)
704         {
705           center = bottom + (top - bottom) / 2;
706           if (!(center < top))
707             internal_error (__FILE__, __LINE__,
708                             _("failed internal consistency check"));
709           if (!do_linear_search
710               && SYMBOL_LANGUAGE (*center) == language_java)
711             {
712               do_linear_search = 1;
713             }
714           if (strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*center),
715                                  search_name) >= 0)
716             {
717               top = center;
718             }
719           else
720             {
721               bottom = center + 1;
722             }
723         }
724       if (!(top == bottom))
725         internal_error (__FILE__, __LINE__,
726                         _("failed internal consistency check"));
727
728       /* For `case_sensitivity == case_sensitive_off' strcmp_iw_ordered will
729          search more exactly than what matches SYMBOL_MATCHES_SEARCH_NAME.  */
730       while (top >= start && SYMBOL_MATCHES_SEARCH_NAME (*top, search_name))
731         top--;
732
733       /* Fixup to have a symbol which matches SYMBOL_MATCHES_SEARCH_NAME.  */
734       top++;
735
736       while (top <= real_top && SYMBOL_MATCHES_SEARCH_NAME (*top, search_name))
737         {
738           if (symbol_matches_domain (SYMBOL_LANGUAGE (*top),
739                                      SYMBOL_DOMAIN (*top), domain))
740             {
741               do_cleanups (cleanup);
742               return (*top);
743             }
744           top++;
745         }
746     }
747
748   /* Can't use a binary search or else we found during the binary search that
749      we should also do a linear search.  */
750
751   if (do_linear_search)
752     {
753       for (psym = start; psym < start + length; psym++)
754         {
755           if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym),
756                                      SYMBOL_DOMAIN (*psym), domain)
757               && SYMBOL_MATCHES_SEARCH_NAME (*psym, search_name))
758             {
759               do_cleanups (cleanup);
760               return (*psym);
761             }
762         }
763     }
764
765   do_cleanups (cleanup);
766   return (NULL);
767 }
768
769 /* Get the symbol table that corresponds to a partial_symtab.
770    This is fast after the first time you do it.  */
771
772 static struct symtab *
773 psymtab_to_symtab (struct objfile *objfile, struct partial_symtab *pst)
774 {
775   /* If it is a shared psymtab, find an unshared psymtab that includes
776      it.  Any such psymtab will do.  */
777   while (pst->user != NULL)
778     pst = pst->user;
779
780   /* If it's been looked up before, return it.  */
781   if (pst->symtab)
782     return pst->symtab;
783
784   /* If it has not yet been read in, read it.  */
785   if (!pst->readin)
786     {
787       struct cleanup *back_to = increment_reading_symtab ();
788
789       (*pst->read_symtab) (objfile, pst);
790       do_cleanups (back_to);
791     }
792
793   return pst->symtab;
794 }
795
796 static void
797 relocate_psymtabs (struct objfile *objfile,
798                    struct section_offsets *new_offsets,
799                    struct section_offsets *delta)
800 {
801   struct partial_symbol **psym;
802   struct partial_symtab *p;
803
804   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, p)
805     {
806       p->textlow += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
807       p->texthigh += ANOFFSET (delta, SECT_OFF_TEXT (objfile));
808     }
809
810   for (psym = objfile->global_psymbols.list;
811        psym < objfile->global_psymbols.next;
812        psym++)
813     {
814       fixup_psymbol_section (*psym, objfile);
815       if (SYMBOL_SECTION (*psym) >= 0)
816         SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
817                                                   SYMBOL_SECTION (*psym));
818     }
819   for (psym = objfile->static_psymbols.list;
820        psym < objfile->static_psymbols.next;
821        psym++)
822     {
823       fixup_psymbol_section (*psym, objfile);
824       if (SYMBOL_SECTION (*psym) >= 0)
825         SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta,
826                                                   SYMBOL_SECTION (*psym));
827     }
828 }
829
830 static struct symtab *
831 find_last_source_symtab_from_partial (struct objfile *ofp)
832 {
833   struct partial_symtab *ps;
834   struct partial_symtab *cs_pst = 0;
835
836   ALL_OBJFILE_PSYMTABS_REQUIRED (ofp, ps)
837     {
838       const char *name = ps->filename;
839       int len = strlen (name);
840
841       if (!(len > 2 && (strcmp (&name[len - 2], ".h") == 0
842                         || strcmp (name, "<<C++-namespaces>>") == 0)))
843         cs_pst = ps;
844     }
845
846   if (cs_pst)
847     {
848       if (cs_pst->readin)
849         {
850           internal_error (__FILE__, __LINE__,
851                           _("select_source_symtab: "
852                           "readin pst found and no symtabs."));
853         }
854       else
855         return psymtab_to_symtab (ofp, cs_pst);
856     }
857   return NULL;
858 }
859
860 static void
861 forget_cached_source_info_partial (struct objfile *objfile)
862 {
863   struct partial_symtab *pst;
864
865   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst)
866     {
867       if (pst->fullname != NULL)
868         {
869           xfree (pst->fullname);
870           pst->fullname = NULL;
871         }
872     }
873 }
874
875 static void
876 print_partial_symbols (struct gdbarch *gdbarch,
877                        struct partial_symbol **p, int count, char *what,
878                        struct ui_file *outfile)
879 {
880   fprintf_filtered (outfile, "  %s partial symbols:\n", what);
881   while (count-- > 0)
882     {
883       QUIT;
884       fprintf_filtered (outfile, "    `%s'", SYMBOL_LINKAGE_NAME (*p));
885       if (SYMBOL_DEMANGLED_NAME (*p) != NULL)
886         {
887           fprintf_filtered (outfile, "  `%s'", SYMBOL_DEMANGLED_NAME (*p));
888         }
889       fputs_filtered (", ", outfile);
890       switch (SYMBOL_DOMAIN (*p))
891         {
892         case UNDEF_DOMAIN:
893           fputs_filtered ("undefined domain, ", outfile);
894           break;
895         case VAR_DOMAIN:
896           /* This is the usual thing -- don't print it.  */
897           break;
898         case STRUCT_DOMAIN:
899           fputs_filtered ("struct domain, ", outfile);
900           break;
901         case LABEL_DOMAIN:
902           fputs_filtered ("label domain, ", outfile);
903           break;
904         default:
905           fputs_filtered ("<invalid domain>, ", outfile);
906           break;
907         }
908       switch (SYMBOL_CLASS (*p))
909         {
910         case LOC_UNDEF:
911           fputs_filtered ("undefined", outfile);
912           break;
913         case LOC_CONST:
914           fputs_filtered ("constant int", outfile);
915           break;
916         case LOC_STATIC:
917           fputs_filtered ("static", outfile);
918           break;
919         case LOC_REGISTER:
920           fputs_filtered ("register", outfile);
921           break;
922         case LOC_ARG:
923           fputs_filtered ("pass by value", outfile);
924           break;
925         case LOC_REF_ARG:
926           fputs_filtered ("pass by reference", outfile);
927           break;
928         case LOC_REGPARM_ADDR:
929           fputs_filtered ("register address parameter", outfile);
930           break;
931         case LOC_LOCAL:
932           fputs_filtered ("stack parameter", outfile);
933           break;
934         case LOC_TYPEDEF:
935           fputs_filtered ("type", outfile);
936           break;
937         case LOC_LABEL:
938           fputs_filtered ("label", outfile);
939           break;
940         case LOC_BLOCK:
941           fputs_filtered ("function", outfile);
942           break;
943         case LOC_CONST_BYTES:
944           fputs_filtered ("constant bytes", outfile);
945           break;
946         case LOC_UNRESOLVED:
947           fputs_filtered ("unresolved", outfile);
948           break;
949         case LOC_OPTIMIZED_OUT:
950           fputs_filtered ("optimized out", outfile);
951           break;
952         case LOC_COMPUTED:
953           fputs_filtered ("computed at runtime", outfile);
954           break;
955         default:
956           fputs_filtered ("<invalid location>", outfile);
957           break;
958         }
959       fputs_filtered (", ", outfile);
960       fputs_filtered (paddress (gdbarch, SYMBOL_VALUE_ADDRESS (*p)), outfile);
961       fprintf_filtered (outfile, "\n");
962       p++;
963     }
964 }
965
966 static void
967 dump_psymtab (struct objfile *objfile, struct partial_symtab *psymtab,
968               struct ui_file *outfile)
969 {
970   struct gdbarch *gdbarch = get_objfile_arch (objfile);
971   int i;
972
973   if (psymtab->anonymous)
974     {
975       fprintf_filtered (outfile, "\nAnonymous partial symtab (%s) ",
976                         psymtab->filename);
977     }
978   else
979     {
980       fprintf_filtered (outfile, "\nPartial symtab for source file %s ",
981                         psymtab->filename);
982     }
983   fprintf_filtered (outfile, "(object ");
984   gdb_print_host_address (psymtab, outfile);
985   fprintf_filtered (outfile, ")\n\n");
986   fprintf_unfiltered (outfile, "  Read from object file %s (",
987                       objfile->name);
988   gdb_print_host_address (objfile, outfile);
989   fprintf_unfiltered (outfile, ")\n");
990
991   if (psymtab->readin)
992     {
993       fprintf_filtered (outfile,
994                         "  Full symtab was read (at ");
995       gdb_print_host_address (psymtab->symtab, outfile);
996       fprintf_filtered (outfile, " by function at ");
997       gdb_print_host_address (psymtab->read_symtab, outfile);
998       fprintf_filtered (outfile, ")\n");
999     }
1000
1001   fprintf_filtered (outfile, "  Relocate symbols by ");
1002   for (i = 0; i < objfile->num_sections; ++i)
1003     {
1004       if (i != 0)
1005         fprintf_filtered (outfile, ", ");
1006       wrap_here ("    ");
1007       fputs_filtered (paddress (gdbarch,
1008                                 ANOFFSET (psymtab->section_offsets, i)),
1009                       outfile);
1010     }
1011   fprintf_filtered (outfile, "\n");
1012
1013   fprintf_filtered (outfile, "  Symbols cover text addresses ");
1014   fputs_filtered (paddress (gdbarch, psymtab->textlow), outfile);
1015   fprintf_filtered (outfile, "-");
1016   fputs_filtered (paddress (gdbarch, psymtab->texthigh), outfile);
1017   fprintf_filtered (outfile, "\n");
1018   fprintf_filtered (outfile, "  Address map supported - %s.\n",
1019                     psymtab->psymtabs_addrmap_supported ? "yes" : "no");
1020   fprintf_filtered (outfile, "  Depends on %d other partial symtabs.\n",
1021                     psymtab->number_of_dependencies);
1022   for (i = 0; i < psymtab->number_of_dependencies; i++)
1023     {
1024       fprintf_filtered (outfile, "    %d ", i);
1025       gdb_print_host_address (psymtab->dependencies[i], outfile);
1026       fprintf_filtered (outfile, " %s\n",
1027                         psymtab->dependencies[i]->filename);
1028     }
1029   if (psymtab->user != NULL)
1030     {
1031       fprintf_filtered (outfile, "  Shared partial symtab with user ");
1032       gdb_print_host_address (psymtab->user, outfile);
1033       fprintf_filtered (outfile, "\n");
1034     }
1035   if (psymtab->n_global_syms > 0)
1036     {
1037       print_partial_symbols (gdbarch,
1038                              objfile->global_psymbols.list
1039                              + psymtab->globals_offset,
1040                              psymtab->n_global_syms, "Global", outfile);
1041     }
1042   if (psymtab->n_static_syms > 0)
1043     {
1044       print_partial_symbols (gdbarch,
1045                              objfile->static_psymbols.list
1046                              + psymtab->statics_offset,
1047                              psymtab->n_static_syms, "Static", outfile);
1048     }
1049   fprintf_filtered (outfile, "\n");
1050 }
1051
1052 static void
1053 print_psymtab_stats_for_objfile (struct objfile *objfile)
1054 {
1055   int i;
1056   struct partial_symtab *ps;
1057
1058   i = 0;
1059   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
1060     {
1061       if (ps->readin == 0)
1062         i++;
1063     }
1064   printf_filtered (_("  Number of psym tables (not yet expanded): %d\n"), i);
1065 }
1066
1067 static void
1068 dump_psymtabs_for_objfile (struct objfile *objfile)
1069 {
1070   struct partial_symtab *psymtab;
1071
1072   if (objfile->psymtabs)
1073     {
1074       printf_filtered ("Psymtabs:\n");
1075       for (psymtab = objfile->psymtabs;
1076            psymtab != NULL;
1077            psymtab = psymtab->next)
1078         {
1079           printf_filtered ("%s at ",
1080                            psymtab->filename);
1081           gdb_print_host_address (psymtab, gdb_stdout);
1082           printf_filtered (", ");
1083           wrap_here ("  ");
1084         }
1085       printf_filtered ("\n\n");
1086     }
1087 }
1088
1089 /* Look through the partial symtabs for all symbols which begin
1090    by matching FUNC_NAME.  Make sure we read that symbol table in.  */
1091
1092 static void
1093 read_symtabs_for_function (struct objfile *objfile, const char *func_name)
1094 {
1095   struct partial_symtab *ps;
1096
1097   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
1098   {
1099     if (ps->readin)
1100       continue;
1101
1102     if ((lookup_partial_symbol (objfile, ps, func_name, 1, VAR_DOMAIN)
1103          != NULL)
1104         || (lookup_partial_symbol (objfile, ps, func_name, 0, VAR_DOMAIN)
1105             != NULL))
1106       psymtab_to_symtab (objfile, ps);
1107   }
1108 }
1109
1110 static void
1111 expand_partial_symbol_tables (struct objfile *objfile)
1112 {
1113   struct partial_symtab *psymtab;
1114
1115   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, psymtab)
1116     {
1117       psymtab_to_symtab (objfile, psymtab);
1118     }
1119 }
1120
1121 static void
1122 read_psymtabs_with_filename (struct objfile *objfile, const char *filename)
1123 {
1124   struct partial_symtab *p;
1125
1126   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, p)
1127     {
1128       /* Anonymous psymtabs don't have a name of a source file.  */
1129       if (p->anonymous)
1130         continue;
1131
1132       if (filename_cmp (filename, p->filename) == 0)
1133         psymtab_to_symtab (objfile, p);
1134     }
1135 }
1136
1137 static void
1138 map_symbol_filenames_psymtab (struct objfile *objfile,
1139                               symbol_filename_ftype *fun, void *data,
1140                               int need_fullname)
1141 {
1142   struct partial_symtab *ps;
1143
1144   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
1145     {
1146       const char *fullname;
1147
1148       if (ps->readin)
1149         continue;
1150
1151       /* We can skip shared psymtabs here, because any file name will be
1152          attached to the unshared psymtab.  */
1153       if (ps->user != NULL)
1154         continue;
1155
1156       /* Anonymous psymtabs don't have a file name.  */
1157       if (ps->anonymous)
1158         continue;
1159
1160       QUIT;
1161       if (need_fullname)
1162         fullname = psymtab_to_fullname (ps);
1163       else
1164         fullname = NULL;
1165       (*fun) (ps->filename, fullname, data);
1166     }
1167 }
1168
1169 /* Finds the fullname that a partial_symtab represents.
1170
1171    If this functions finds the fullname, it will save it in ps->fullname
1172    and it will also return the value.
1173
1174    If this function fails to find the file that this partial_symtab represents,
1175    NULL will be returned and ps->fullname will be set to NULL.  */
1176
1177 static char *
1178 psymtab_to_fullname (struct partial_symtab *ps)
1179 {
1180   int r;
1181
1182   if (!ps)
1183     return NULL;
1184   if (ps->anonymous)
1185     return NULL;
1186
1187   /* Use cached copy if we have it.
1188      We rely on forget_cached_source_info being called appropriately
1189      to handle cases like the file being moved.  */
1190   if (ps->fullname)
1191     return ps->fullname;
1192
1193   r = find_and_open_source (ps->filename, ps->dirname, &ps->fullname);
1194
1195   if (r >= 0)
1196     {
1197       close (r);
1198       return ps->fullname;
1199     }
1200
1201   return NULL;
1202 }
1203
1204 static const char *
1205 find_symbol_file_from_partial (struct objfile *objfile, const char *name)
1206 {
1207   struct partial_symtab *pst;
1208
1209   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst)
1210     {
1211       if (lookup_partial_symbol (objfile, pst, name, 1, VAR_DOMAIN))
1212         return pst->filename;
1213     }
1214   return NULL;
1215 }
1216
1217 /*  For all symbols, s, in BLOCK that are in NAMESPACE and match NAME
1218     according to the function MATCH, call CALLBACK(BLOCK, s, DATA).
1219     BLOCK is assumed to come from OBJFILE.  Returns 1 iff CALLBACK
1220     ever returns non-zero, and otherwise returns 0.  */
1221
1222 static int
1223 map_block (const char *name, domain_enum namespace, struct objfile *objfile,
1224            struct block *block,
1225            int (*callback) (struct block *, struct symbol *, void *),
1226            void *data, symbol_compare_ftype *match)
1227 {
1228   struct block_iterator iter;
1229   struct symbol *sym;
1230
1231   for (sym = block_iter_match_first (block, name, match, &iter);
1232        sym != NULL; sym = block_iter_match_next (name, match, &iter))
1233     {
1234       if (symbol_matches_domain (SYMBOL_LANGUAGE (sym), 
1235                                  SYMBOL_DOMAIN (sym), namespace))
1236         {
1237           if (callback (block, sym, data))
1238             return 1;
1239         }
1240     }
1241
1242   return 0;
1243 }
1244
1245 /*  Psymtab version of map_matching_symbols.  See its definition in
1246     the definition of quick_symbol_functions in symfile.h.  */
1247
1248 static void
1249 map_matching_symbols_psymtab (const char *name, domain_enum namespace,
1250                               struct objfile *objfile, int global,
1251                               int (*callback) (struct block *,
1252                                                struct symbol *, void *),
1253                               void *data,
1254                               symbol_compare_ftype *match,
1255                               symbol_compare_ftype *ordered_compare)
1256 {
1257   const int block_kind = global ? GLOBAL_BLOCK : STATIC_BLOCK;
1258   struct partial_symtab *ps;
1259
1260   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
1261     {
1262       QUIT;
1263       if (ps->readin
1264           || match_partial_symbol (objfile, ps, global, name, namespace, match,
1265                                    ordered_compare))
1266         {
1267           struct symtab *s = psymtab_to_symtab (objfile, ps);
1268           struct block *block;
1269
1270           if (s == NULL || !s->primary)
1271             continue;
1272           block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), block_kind);
1273           if (map_block (name, namespace, objfile, block,
1274                          callback, data, match))
1275             return;
1276           if (callback (block, NULL, data))
1277             return;
1278         }
1279     }
1280 }           
1281
1282 /* A helper for expand_symtabs_matching_via_partial that handles
1283    searching included psymtabs.  This returns 1 if a symbol is found,
1284    and zero otherwise.  It also updates the 'searched_flag' on the
1285    various psymtabs that it searches.  */
1286
1287 static int
1288 recursively_search_psymtabs (struct partial_symtab *ps,
1289                              struct objfile *objfile,
1290                              enum search_domain kind,
1291                              int (*name_matcher) (const char *, void *),
1292                              void *data)
1293 {
1294   struct partial_symbol **psym;
1295   struct partial_symbol **bound, **gbound, **sbound;
1296   int keep_going = 1;
1297   int result = PST_SEARCHED_AND_NOT_FOUND;
1298   int i;
1299
1300   if (ps->searched_flag != PST_NOT_SEARCHED)
1301     return ps->searched_flag == PST_SEARCHED_AND_FOUND;
1302
1303   /* Recurse into shared psymtabs first, because they may have already
1304      been searched, and this could save some time.  */
1305   for (i = 0; i < ps->number_of_dependencies; ++i)
1306     {
1307       int r;
1308
1309       /* Skip non-shared dependencies, these are handled elsewhere.  */
1310       if (ps->dependencies[i]->user == NULL)
1311         continue;
1312
1313       r = recursively_search_psymtabs (ps->dependencies[i],
1314                                        objfile, kind, name_matcher, data);
1315       if (r != 0)
1316         {
1317           ps->searched_flag = PST_SEARCHED_AND_FOUND;
1318           return 1;
1319         }
1320     }
1321
1322   gbound = (objfile->global_psymbols.list
1323             + ps->globals_offset + ps->n_global_syms);
1324   sbound = (objfile->static_psymbols.list
1325             + ps->statics_offset + ps->n_static_syms);
1326   bound = gbound;
1327
1328   /* Go through all of the symbols stored in a partial
1329      symtab in one loop.  */
1330   psym = objfile->global_psymbols.list + ps->globals_offset;
1331   while (keep_going)
1332     {
1333       if (psym >= bound)
1334         {
1335           if (bound == gbound && ps->n_static_syms != 0)
1336             {
1337               psym = objfile->static_psymbols.list + ps->statics_offset;
1338               bound = sbound;
1339             }
1340           else
1341             keep_going = 0;
1342           continue;
1343         }
1344       else
1345         {
1346           QUIT;
1347
1348           if ((kind == ALL_DOMAIN
1349                || (kind == VARIABLES_DOMAIN
1350                    && SYMBOL_CLASS (*psym) != LOC_TYPEDEF
1351                    && SYMBOL_CLASS (*psym) != LOC_BLOCK)
1352                || (kind == FUNCTIONS_DOMAIN
1353                    && SYMBOL_CLASS (*psym) == LOC_BLOCK)
1354                || (kind == TYPES_DOMAIN
1355                    && SYMBOL_CLASS (*psym) == LOC_TYPEDEF))
1356               && (*name_matcher) (SYMBOL_SEARCH_NAME (*psym), data))
1357             {
1358               /* Found a match, so notify our caller.  */
1359               result = PST_SEARCHED_AND_FOUND;
1360               keep_going = 0;
1361             }
1362         }
1363       psym++;
1364     }
1365
1366   ps->searched_flag = result;
1367   return result == PST_SEARCHED_AND_FOUND;
1368 }
1369
1370 static void
1371 expand_symtabs_matching_via_partial
1372   (struct objfile *objfile,
1373    int (*file_matcher) (const char *, void *),
1374    int (*name_matcher) (const char *, void *),
1375    enum search_domain kind,
1376    void *data)
1377 {
1378   struct partial_symtab *ps;
1379
1380   /* Clear the search flags.  */
1381   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
1382     {
1383       ps->searched_flag = PST_NOT_SEARCHED;
1384     }
1385
1386   ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, ps)
1387     {
1388       if (ps->readin)
1389         continue;
1390
1391       /* We skip shared psymtabs because file-matching doesn't apply
1392          to them; but we search them later in the loop.  */
1393       if (ps->user != NULL)
1394         continue;
1395
1396       if (file_matcher)
1397         {
1398           if (ps->anonymous)
1399             continue;
1400           if (! (*file_matcher) (ps->filename, data))
1401             continue;
1402         }
1403
1404       if (recursively_search_psymtabs (ps, objfile, kind, name_matcher, data))
1405         psymtab_to_symtab (objfile, ps);
1406     }
1407 }
1408
1409 static int
1410 objfile_has_psyms (struct objfile *objfile)
1411 {
1412   return objfile->psymtabs != NULL;
1413 }
1414
1415 const struct quick_symbol_functions psym_functions =
1416 {
1417   objfile_has_psyms,
1418   find_last_source_symtab_from_partial,
1419   forget_cached_source_info_partial,
1420   partial_map_symtabs_matching_filename,
1421   lookup_symbol_aux_psymtabs,
1422   print_psymtab_stats_for_objfile,
1423   dump_psymtabs_for_objfile,
1424   relocate_psymtabs,
1425   read_symtabs_for_function,
1426   expand_partial_symbol_tables,
1427   read_psymtabs_with_filename,
1428   find_symbol_file_from_partial,
1429   map_matching_symbols_psymtab,
1430   expand_symtabs_matching_via_partial,
1431   find_pc_sect_symtab_from_partial,
1432   map_symbol_filenames_psymtab
1433 };
1434
1435 \f
1436
1437 /* This compares two partial symbols by names, using strcmp_iw_ordered
1438    for the comparison.  */
1439
1440 static int
1441 compare_psymbols (const void *s1p, const void *s2p)
1442 {
1443   struct partial_symbol *const *s1 = s1p;
1444   struct partial_symbol *const *s2 = s2p;
1445
1446   return strcmp_iw_ordered (SYMBOL_SEARCH_NAME (*s1),
1447                             SYMBOL_SEARCH_NAME (*s2));
1448 }
1449
1450 void
1451 sort_pst_symbols (struct objfile *objfile, struct partial_symtab *pst)
1452 {
1453   /* Sort the global list; don't sort the static list.  */
1454
1455   qsort (objfile->global_psymbols.list + pst->globals_offset,
1456          pst->n_global_syms, sizeof (struct partial_symbol *),
1457          compare_psymbols);
1458 }
1459
1460 /* Allocate and partially fill a partial symtab.  It will be
1461    completely filled at the end of the symbol list.
1462
1463    FILENAME is the name of the symbol-file we are reading from.  */
1464
1465 struct partial_symtab *
1466 start_psymtab_common (struct objfile *objfile,
1467                       struct section_offsets *section_offsets,
1468                       const char *filename,
1469                       CORE_ADDR textlow, struct partial_symbol **global_syms,
1470                       struct partial_symbol **static_syms)
1471 {
1472   struct partial_symtab *psymtab;
1473
1474   psymtab = allocate_psymtab (filename, objfile);
1475   psymtab->section_offsets = section_offsets;
1476   psymtab->textlow = textlow;
1477   psymtab->texthigh = psymtab->textlow;         /* default */
1478   psymtab->globals_offset = global_syms - objfile->global_psymbols.list;
1479   psymtab->statics_offset = static_syms - objfile->static_psymbols.list;
1480   return (psymtab);
1481 }
1482
1483 /* Calculate a hash code for the given partial symbol.  The hash is
1484    calculated using the symbol's value, language, domain, class
1485    and name.  These are the values which are set by
1486    add_psymbol_to_bcache.  */
1487
1488 static unsigned long
1489 psymbol_hash (const void *addr, int length)
1490 {
1491   unsigned long h = 0;
1492   struct partial_symbol *psymbol = (struct partial_symbol *) addr;
1493   unsigned int lang = psymbol->ginfo.language;
1494   unsigned int domain = PSYMBOL_DOMAIN (psymbol);
1495   unsigned int class = PSYMBOL_CLASS (psymbol);
1496
1497   h = hash_continue (&psymbol->ginfo.value, sizeof (psymbol->ginfo.value), h);
1498   h = hash_continue (&lang, sizeof (unsigned int), h);
1499   h = hash_continue (&domain, sizeof (unsigned int), h);
1500   h = hash_continue (&class, sizeof (unsigned int), h);
1501   h = hash_continue (psymbol->ginfo.name, strlen (psymbol->ginfo.name), h);
1502
1503   return h;
1504 }
1505
1506 /* Returns true if the symbol at addr1 equals the symbol at addr2.
1507    For the comparison this function uses a symbols value,
1508    language, domain, class and name.  */
1509
1510 static int
1511 psymbol_compare (const void *addr1, const void *addr2, int length)
1512 {
1513   struct partial_symbol *sym1 = (struct partial_symbol *) addr1;
1514   struct partial_symbol *sym2 = (struct partial_symbol *) addr2;
1515
1516   return (memcmp (&sym1->ginfo.value, &sym1->ginfo.value,
1517                   sizeof (sym1->ginfo.value)) == 0
1518           && sym1->ginfo.language == sym2->ginfo.language
1519           && PSYMBOL_DOMAIN (sym1) == PSYMBOL_DOMAIN (sym2)
1520           && PSYMBOL_CLASS (sym1) == PSYMBOL_CLASS (sym2)
1521           && sym1->ginfo.name == sym2->ginfo.name);
1522 }
1523
1524 /* Initialize a partial symbol bcache.  */
1525
1526 struct psymbol_bcache *
1527 psymbol_bcache_init (void)
1528 {
1529   struct psymbol_bcache *bcache = XCALLOC (1, struct psymbol_bcache);
1530   bcache->bcache = bcache_xmalloc (psymbol_hash, psymbol_compare);
1531   return bcache;
1532 }
1533
1534 /* Free a partial symbol bcache.  */
1535 void
1536 psymbol_bcache_free (struct psymbol_bcache *bcache)
1537 {
1538   if (bcache == NULL)
1539     return;
1540
1541   bcache_xfree (bcache->bcache);
1542   xfree (bcache);
1543 }
1544
1545 /* Return the internal bcache of the psymbol_bcache BCACHE.  */
1546
1547 struct bcache *
1548 psymbol_bcache_get_bcache (struct psymbol_bcache *bcache)
1549 {
1550   return bcache->bcache;
1551 }
1552
1553 /* Find a copy of the SYM in BCACHE.  If BCACHE has never seen this
1554    symbol before, add a copy to BCACHE.  In either case, return a pointer
1555    to BCACHE's copy of the symbol.  If optional ADDED is not NULL, return
1556    1 in case of new entry or 0 if returning an old entry.  */
1557
1558 static const struct partial_symbol *
1559 psymbol_bcache_full (struct partial_symbol *sym,
1560                      struct psymbol_bcache *bcache,
1561                      int *added)
1562 {
1563   return bcache_full (sym,
1564                       sizeof (struct partial_symbol),
1565                       bcache->bcache,
1566                       added);
1567 }
1568
1569 /* Helper function, initialises partial symbol structure and stashes 
1570    it into objfile's bcache.  Note that our caching mechanism will
1571    use all fields of struct partial_symbol to determine hash value of the
1572    structure.  In other words, having two symbols with the same name but
1573    different domain (or address) is possible and correct.  */
1574
1575 static const struct partial_symbol *
1576 add_psymbol_to_bcache (const char *name, int namelength, int copy_name,
1577                        domain_enum domain,
1578                        enum address_class class,
1579                        long val,        /* Value as a long */
1580                        CORE_ADDR coreaddr,      /* Value as a CORE_ADDR */
1581                        enum language language, struct objfile *objfile,
1582                        int *added)
1583 {
1584   struct partial_symbol psymbol;
1585
1586   /* We must ensure that the entire 'value' field has been zeroed
1587      before assigning to it, because an assignment may not write the
1588      entire field.  */
1589   memset (&psymbol.ginfo.value, 0, sizeof (psymbol.ginfo.value));
1590
1591   /* val and coreaddr are mutually exclusive, one of them *will* be zero.  */
1592   if (val != 0)
1593     {
1594       SYMBOL_VALUE (&psymbol) = val;
1595     }
1596   else
1597     {
1598       SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr;
1599     }
1600   SYMBOL_SECTION (&psymbol) = 0;
1601   SYMBOL_OBJ_SECTION (&psymbol) = NULL;
1602   SYMBOL_SET_LANGUAGE (&psymbol, language);
1603   PSYMBOL_DOMAIN (&psymbol) = domain;
1604   PSYMBOL_CLASS (&psymbol) = class;
1605
1606   SYMBOL_SET_NAMES (&psymbol, name, namelength, copy_name, objfile);
1607
1608   /* Stash the partial symbol away in the cache.  */
1609   return psymbol_bcache_full (&psymbol,
1610                               objfile->psymbol_cache,
1611                               added);
1612 }
1613
1614 /* Increase the space allocated for LISTP, which is probably
1615    global_psymbols or static_psymbols.  This space will eventually
1616    be freed in free_objfile().  */
1617
1618 static void
1619 extend_psymbol_list (struct psymbol_allocation_list *listp,
1620                      struct objfile *objfile)
1621 {
1622   int new_size;
1623
1624   if (listp->size == 0)
1625     {
1626       new_size = 255;
1627       listp->list = (struct partial_symbol **)
1628         xmalloc (new_size * sizeof (struct partial_symbol *));
1629     }
1630   else
1631     {
1632       new_size = listp->size * 2;
1633       listp->list = (struct partial_symbol **)
1634         xrealloc ((char *) listp->list,
1635                   new_size * sizeof (struct partial_symbol *));
1636     }
1637   /* Next assumes we only went one over.  Should be good if
1638      program works correctly.  */
1639   listp->next = listp->list + listp->size;
1640   listp->size = new_size;
1641 }
1642
1643 /* Helper function, adds partial symbol to the given partial symbol
1644    list.  */
1645
1646 static void
1647 append_psymbol_to_list (struct psymbol_allocation_list *list,
1648                         const struct partial_symbol *psym,
1649                         struct objfile *objfile)
1650 {
1651   if (list->next >= list->list + list->size)
1652     extend_psymbol_list (list, objfile);
1653   *list->next++ = (struct partial_symbol *) psym;
1654   OBJSTAT (objfile, n_psyms++);
1655 }
1656
1657 /* Add a symbol with a long value to a psymtab.
1658    Since one arg is a struct, we pass in a ptr and deref it (sigh).
1659    Return the partial symbol that has been added.  */
1660
1661 void
1662 add_psymbol_to_list (const char *name, int namelength, int copy_name,
1663                      domain_enum domain,
1664                      enum address_class class,
1665                      struct psymbol_allocation_list *list, 
1666                      long val,  /* Value as a long */
1667                      CORE_ADDR coreaddr,        /* Value as a CORE_ADDR */
1668                      enum language language, struct objfile *objfile)
1669 {
1670   const struct partial_symbol *psym;
1671
1672   int added;
1673
1674   /* Stash the partial symbol away in the cache.  */
1675   psym = add_psymbol_to_bcache (name, namelength, copy_name, domain, class,
1676                                 val, coreaddr, language, objfile, &added);
1677
1678   /* Do not duplicate global partial symbols.  */
1679   if (list == &objfile->global_psymbols
1680       && !added)
1681     return;
1682
1683   /* Save pointer to partial symbol in psymtab, growing symtab if needed.  */
1684   append_psymbol_to_list (list, psym, objfile);
1685 }
1686
1687 /* Initialize storage for partial symbols.  */
1688
1689 void
1690 init_psymbol_list (struct objfile *objfile, int total_symbols)
1691 {
1692   /* Free any previously allocated psymbol lists.  */
1693
1694   if (objfile->global_psymbols.list)
1695     {
1696       xfree (objfile->global_psymbols.list);
1697     }
1698   if (objfile->static_psymbols.list)
1699     {
1700       xfree (objfile->static_psymbols.list);
1701     }
1702
1703   /* Current best guess is that approximately a twentieth
1704      of the total symbols (in a debugging file) are global or static
1705      oriented symbols.  */
1706
1707   objfile->global_psymbols.size = total_symbols / 10;
1708   objfile->static_psymbols.size = total_symbols / 10;
1709
1710   if (objfile->global_psymbols.size > 0)
1711     {
1712       objfile->global_psymbols.next =
1713         objfile->global_psymbols.list = (struct partial_symbol **)
1714         xmalloc ((objfile->global_psymbols.size
1715                   * sizeof (struct partial_symbol *)));
1716     }
1717   if (objfile->static_psymbols.size > 0)
1718     {
1719       objfile->static_psymbols.next =
1720         objfile->static_psymbols.list = (struct partial_symbol **)
1721         xmalloc ((objfile->static_psymbols.size
1722                   * sizeof (struct partial_symbol *)));
1723     }
1724 }
1725
1726 struct partial_symtab *
1727 allocate_psymtab (const char *filename, struct objfile *objfile)
1728 {
1729   struct partial_symtab *psymtab;
1730
1731   if (objfile->free_psymtabs)
1732     {
1733       psymtab = objfile->free_psymtabs;
1734       objfile->free_psymtabs = psymtab->next;
1735     }
1736   else
1737     psymtab = (struct partial_symtab *)
1738       obstack_alloc (&objfile->objfile_obstack,
1739                      sizeof (struct partial_symtab));
1740
1741   memset (psymtab, 0, sizeof (struct partial_symtab));
1742   psymtab->filename = obsavestring (filename, strlen (filename),
1743                                     &objfile->objfile_obstack);
1744   psymtab->symtab = NULL;
1745
1746   /* Prepend it to the psymtab list for the objfile it belongs to.
1747      Psymtabs are searched in most recent inserted -> least recent
1748      inserted order.  */
1749
1750   psymtab->next = objfile->psymtabs;
1751   objfile->psymtabs = psymtab;
1752
1753   if (symtab_create_debug)
1754     {
1755       /* Be a bit clever with debugging messages, and don't print objfile
1756          every time, only when it changes.  */
1757       static char *last_objfile_name = NULL;
1758
1759       if (last_objfile_name == NULL
1760           || strcmp (last_objfile_name, objfile->name) != 0)
1761         {
1762           xfree (last_objfile_name);
1763           last_objfile_name = xstrdup (objfile->name);
1764           fprintf_unfiltered (gdb_stdlog,
1765                               "Creating one or more psymtabs for objfile %s ...\n",
1766                               last_objfile_name);
1767         }
1768       fprintf_unfiltered (gdb_stdlog,
1769                           "Created psymtab %s for module %s.\n",
1770                           host_address_to_string (psymtab), filename);
1771     }
1772
1773   return (psymtab);
1774 }
1775
1776 void
1777 discard_psymtab (struct objfile *objfile, struct partial_symtab *pst)
1778 {
1779   struct partial_symtab **prev_pst;
1780
1781   /* From dbxread.c:
1782      Empty psymtabs happen as a result of header files which don't
1783      have any symbols in them.  There can be a lot of them.  But this
1784      check is wrong, in that a psymtab with N_SLINE entries but
1785      nothing else is not empty, but we don't realize that.  Fixing
1786      that without slowing things down might be tricky.  */
1787
1788   /* First, snip it out of the psymtab chain.  */
1789
1790   prev_pst = &(objfile->psymtabs);
1791   while ((*prev_pst) != pst)
1792     prev_pst = &((*prev_pst)->next);
1793   (*prev_pst) = pst->next;
1794
1795   /* Next, put it on a free list for recycling.  */
1796
1797   pst->next = objfile->free_psymtabs;
1798   objfile->free_psymtabs = pst;
1799 }
1800
1801 \f
1802
1803 static void
1804 maintenance_print_psymbols (char *args, int from_tty)
1805 {
1806   char **argv;
1807   struct ui_file *outfile;
1808   struct cleanup *cleanups;
1809   char *symname = NULL;
1810   char *filename = DEV_TTY;
1811   struct objfile *objfile;
1812   struct partial_symtab *ps;
1813
1814   dont_repeat ();
1815
1816   if (args == NULL)
1817     {
1818       error (_("\
1819 print-psymbols takes an output file name and optional symbol file name"));
1820     }
1821   argv = gdb_buildargv (args);
1822   cleanups = make_cleanup_freeargv (argv);
1823
1824   if (argv[0] != NULL)
1825     {
1826       filename = argv[0];
1827       /* If a second arg is supplied, it is a source file name to match on.  */
1828       if (argv[1] != NULL)
1829         {
1830           symname = argv[1];
1831         }
1832     }
1833
1834   filename = tilde_expand (filename);
1835   make_cleanup (xfree, filename);
1836
1837   outfile = gdb_fopen (filename, FOPEN_WT);
1838   if (outfile == 0)
1839     perror_with_name (filename);
1840   make_cleanup_ui_file_delete (outfile);
1841
1842   ALL_PSYMTABS (objfile, ps)
1843     {
1844       QUIT;
1845       if (symname == NULL || filename_cmp (symname, ps->filename) == 0)
1846         dump_psymtab (objfile, ps, outfile);
1847     }
1848   do_cleanups (cleanups);
1849 }
1850
1851 /* List all the partial symbol tables whose names match REGEXP (optional).  */
1852 static void
1853 maintenance_info_psymtabs (char *regexp, int from_tty)
1854 {
1855   struct program_space *pspace;
1856   struct objfile *objfile;
1857
1858   if (regexp)
1859     re_comp (regexp);
1860
1861   ALL_PSPACES (pspace)
1862     ALL_PSPACE_OBJFILES (pspace, objfile)
1863     {
1864       struct gdbarch *gdbarch = get_objfile_arch (objfile);
1865       struct partial_symtab *psymtab;
1866
1867       /* We don't want to print anything for this objfile until we
1868          actually find a symtab whose name matches.  */
1869       int printed_objfile_start = 0;
1870
1871       ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, psymtab)
1872         {
1873           QUIT;
1874
1875           if (! regexp
1876               || re_exec (psymtab->filename))
1877             {
1878               if (! printed_objfile_start)
1879                 {
1880                   printf_filtered ("{ objfile %s ", objfile->name);
1881                   wrap_here ("  ");
1882                   printf_filtered ("((struct objfile *) %s)\n", 
1883                                    host_address_to_string (objfile));
1884                   printed_objfile_start = 1;
1885                 }
1886
1887               printf_filtered ("  { psymtab %s ", psymtab->filename);
1888               wrap_here ("    ");
1889               printf_filtered ("((struct partial_symtab *) %s)\n", 
1890                                host_address_to_string (psymtab));
1891
1892               printf_filtered ("    readin %s\n",
1893                                psymtab->readin ? "yes" : "no");
1894               printf_filtered ("    fullname %s\n",
1895                                psymtab->fullname
1896                                ? psymtab->fullname : "(null)");
1897               printf_filtered ("    text addresses ");
1898               fputs_filtered (paddress (gdbarch, psymtab->textlow),
1899                               gdb_stdout);
1900               printf_filtered (" -- ");
1901               fputs_filtered (paddress (gdbarch, psymtab->texthigh),
1902                               gdb_stdout);
1903               printf_filtered ("\n");
1904               printf_filtered ("    psymtabs_addrmap_supported %s\n",
1905                                (psymtab->psymtabs_addrmap_supported
1906                                 ? "yes" : "no"));
1907               printf_filtered ("    globals ");
1908               if (psymtab->n_global_syms)
1909                 {
1910                   printf_filtered ("(* (struct partial_symbol **) %s @ %d)\n",
1911                                    host_address_to_string (objfile->global_psymbols.list
1912                                     + psymtab->globals_offset),
1913                                    psymtab->n_global_syms);
1914                 }
1915               else
1916                 printf_filtered ("(none)\n");
1917               printf_filtered ("    statics ");
1918               if (psymtab->n_static_syms)
1919                 {
1920                   printf_filtered ("(* (struct partial_symbol **) %s @ %d)\n",
1921                                    host_address_to_string (objfile->static_psymbols.list
1922                                     + psymtab->statics_offset),
1923                                    psymtab->n_static_syms);
1924                 }
1925               else
1926                 printf_filtered ("(none)\n");
1927               printf_filtered ("    dependencies ");
1928               if (psymtab->number_of_dependencies)
1929                 {
1930                   int i;
1931
1932                   printf_filtered ("{\n");
1933                   for (i = 0; i < psymtab->number_of_dependencies; i++)
1934                     {
1935                       struct partial_symtab *dep = psymtab->dependencies[i];
1936
1937                       /* Note the string concatenation there --- no comma.  */
1938                       printf_filtered ("      psymtab %s "
1939                                        "((struct partial_symtab *) %s)\n",
1940                                        dep->filename, 
1941                                        host_address_to_string (dep));
1942                     }
1943                   printf_filtered ("    }\n");
1944                 }
1945               else
1946                 printf_filtered ("(none)\n");
1947               printf_filtered ("  }\n");
1948             }
1949         }
1950
1951       if (printed_objfile_start)
1952         printf_filtered ("}\n");
1953     }
1954 }
1955
1956 /* Check consistency of psymtabs and symtabs.  */
1957
1958 static void
1959 maintenance_check_symtabs (char *ignore, int from_tty)
1960 {
1961   struct symbol *sym;
1962   struct partial_symbol **psym;
1963   struct symtab *s = NULL;
1964   struct partial_symtab *ps;
1965   struct blockvector *bv;
1966   struct objfile *objfile;
1967   struct block *b;
1968   int length;
1969
1970   ALL_PSYMTABS (objfile, ps)
1971   {
1972     struct gdbarch *gdbarch = get_objfile_arch (objfile);
1973
1974     s = psymtab_to_symtab (objfile, ps);
1975     if (s == NULL)
1976       continue;
1977     bv = BLOCKVECTOR (s);
1978     b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
1979     psym = objfile->static_psymbols.list + ps->statics_offset;
1980     length = ps->n_static_syms;
1981     while (length--)
1982       {
1983         sym = lookup_block_symbol (b, SYMBOL_LINKAGE_NAME (*psym),
1984                                    SYMBOL_DOMAIN (*psym));
1985         if (!sym)
1986           {
1987             printf_filtered ("Static symbol `");
1988             puts_filtered (SYMBOL_LINKAGE_NAME (*psym));
1989             printf_filtered ("' only found in ");
1990             puts_filtered (ps->filename);
1991             printf_filtered (" psymtab\n");
1992           }
1993         psym++;
1994       }
1995     b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
1996     psym = objfile->global_psymbols.list + ps->globals_offset;
1997     length = ps->n_global_syms;
1998     while (length--)
1999       {
2000         sym = lookup_block_symbol (b, SYMBOL_LINKAGE_NAME (*psym),
2001                                    SYMBOL_DOMAIN (*psym));
2002         if (!sym)
2003           {
2004             printf_filtered ("Global symbol `");
2005             puts_filtered (SYMBOL_LINKAGE_NAME (*psym));
2006             printf_filtered ("' only found in ");
2007             puts_filtered (ps->filename);
2008             printf_filtered (" psymtab\n");
2009           }
2010         psym++;
2011       }
2012     if (ps->texthigh < ps->textlow)
2013       {
2014         printf_filtered ("Psymtab ");
2015         puts_filtered (ps->filename);
2016         printf_filtered (" covers bad range ");
2017         fputs_filtered (paddress (gdbarch, ps->textlow), gdb_stdout);
2018         printf_filtered (" - ");
2019         fputs_filtered (paddress (gdbarch, ps->texthigh), gdb_stdout);
2020         printf_filtered ("\n");
2021         continue;
2022       }
2023     if (ps->texthigh == 0)
2024       continue;
2025     if (ps->textlow < BLOCK_START (b) || ps->texthigh > BLOCK_END (b))
2026       {
2027         printf_filtered ("Psymtab ");
2028         puts_filtered (ps->filename);
2029         printf_filtered (" covers ");
2030         fputs_filtered (paddress (gdbarch, ps->textlow), gdb_stdout);
2031         printf_filtered (" - ");
2032         fputs_filtered (paddress (gdbarch, ps->texthigh), gdb_stdout);
2033         printf_filtered (" but symtab covers only ");
2034         fputs_filtered (paddress (gdbarch, BLOCK_START (b)), gdb_stdout);
2035         printf_filtered (" - ");
2036         fputs_filtered (paddress (gdbarch, BLOCK_END (b)), gdb_stdout);
2037         printf_filtered ("\n");
2038       }
2039   }
2040 }
2041
2042 \f
2043
2044 void
2045 expand_partial_symbol_names (int (*fun) (const char *, void *),
2046                              void *data)
2047 {
2048   struct objfile *objfile;
2049
2050   ALL_OBJFILES (objfile)
2051   {
2052     if (objfile->sf)
2053       objfile->sf->qf->expand_symtabs_matching (objfile, NULL, fun,
2054                                                 ALL_DOMAIN, data);
2055   }
2056 }
2057
2058 void
2059 map_partial_symbol_filenames (symbol_filename_ftype *fun, void *data,
2060                               int need_fullname)
2061 {
2062   struct objfile *objfile;
2063
2064   ALL_OBJFILES (objfile)
2065   {
2066     if (objfile->sf)
2067       objfile->sf->qf->map_symbol_filenames (objfile, fun, data,
2068                                              need_fullname);
2069   }
2070 }
2071
2072 extern initialize_file_ftype _initialize_psymtab;
2073
2074 void
2075 _initialize_psymtab (void)
2076 {
2077   add_cmd ("psymbols", class_maintenance, maintenance_print_psymbols, _("\
2078 Print dump of current partial symbol definitions.\n\
2079 Entries in the partial symbol table are dumped to file OUTFILE.\n\
2080 If a SOURCE file is specified, dump only that file's partial symbols."),
2081            &maintenanceprintlist);
2082
2083   add_cmd ("psymtabs", class_maintenance, maintenance_info_psymtabs, _("\
2084 List the partial symbol tables for all object files.\n\
2085 This does not include information about individual partial symbols,\n\
2086 just the symbol table structures themselves."),
2087            &maintenanceinfolist);
2088
2089   add_cmd ("check-symtabs", class_maintenance, maintenance_check_symtabs,
2090            _("Check consistency of psymtabs and symtabs."),
2091            &maintenancelist);
2092 }