12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883 |
- /* Partial symbol tables.
- Copyright (C) 2009-2022 Free Software Foundation, Inc.
- This file is part of GDB.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #include "defs.h"
- #include "symtab.h"
- #include "objfiles.h"
- #include "psympriv.h"
- #include "block.h"
- #include "filenames.h"
- #include "source.h"
- #include "addrmap.h"
- #include "gdbtypes.h"
- #include "ui-out.h"
- #include "command.h"
- #include "readline/tilde.h"
- #include "gdbsupport/gdb_regex.h"
- #include "dictionary.h"
- #include "language.h"
- #include "cp-support.h"
- #include "gdbcmd.h"
- #include <algorithm>
- #include <set>
- #include "gdbsupport/buildargv.h"
- static struct partial_symbol *lookup_partial_symbol (struct objfile *,
- struct partial_symtab *,
- const lookup_name_info &,
- int,
- domain_enum);
- static const char *psymtab_to_fullname (struct partial_symtab *ps);
- static struct partial_symbol *find_pc_sect_psymbol (struct objfile *,
- struct partial_symtab *,
- CORE_ADDR,
- struct obj_section *);
- static struct compunit_symtab *psymtab_to_symtab (struct objfile *objfile,
- struct partial_symtab *pst);
- psymtab_storage::~psymtab_storage ()
- {
- partial_symtab *iter = psymtabs;
- while (iter != nullptr)
- {
- partial_symtab *next = iter->next;
- delete iter;
- iter = next;
- }
- }
- /* See psymtab.h. */
- void
- psymtab_storage::install_psymtab (partial_symtab *pst)
- {
- pst->next = psymtabs;
- psymtabs = pst;
- }
- /* Ensure that the partial symbols for OBJFILE have been loaded. This
- will print a message when symbols are loaded. This function
- returns a range adapter suitable for iterating over the psymtabs of
- OBJFILE. */
- psymtab_storage::partial_symtab_range
- psymbol_functions::require_partial_symbols (struct objfile *objfile)
- {
- objfile->require_partial_symbols (true);
- return m_partial_symtabs->range ();
- }
- /* Find which partial symtab contains PC and SECTION starting at psymtab PST.
- We may find a different psymtab than PST. See FIND_PC_SECT_PSYMTAB. */
- static struct partial_symtab *
- find_pc_sect_psymtab_closer (struct objfile *objfile,
- CORE_ADDR pc, struct obj_section *section,
- struct partial_symtab *pst,
- struct bound_minimal_symbol msymbol)
- {
- struct partial_symtab *tpst;
- struct partial_symtab *best_pst = pst;
- CORE_ADDR best_addr = pst->text_low (objfile);
- gdb_assert (!pst->psymtabs_addrmap_supported);
- /* An objfile that has its functions reordered might have
- many partial symbol tables containing the PC, but
- we want the partial symbol table that contains the
- function containing the PC. */
- if (!(objfile->flags & OBJF_REORDERED)
- && section == NULL) /* Can't validate section this way. */
- return pst;
- if (msymbol.minsym == NULL)
- return pst;
- /* The code range of partial symtabs sometimes overlap, so, in
- the loop below, we need to check all partial symtabs and
- find the one that fits better for the given PC address. We
- select the partial symtab that contains a symbol whose
- address is closest to the PC address. By closest we mean
- that find_pc_sect_symbol returns the symbol with address
- that is closest and still less than the given PC. */
- for (tpst = pst; tpst != NULL; tpst = tpst->next)
- {
- if (pc >= tpst->text_low (objfile) && pc < tpst->text_high (objfile))
- {
- struct partial_symbol *p;
- CORE_ADDR this_addr;
- /* NOTE: This assumes that every psymbol has a
- corresponding msymbol, which is not necessarily
- true; the debug info might be much richer than the
- object's symbol table. */
- p = find_pc_sect_psymbol (objfile, tpst, pc, section);
- if (p != NULL
- && (p->address (objfile) == BMSYMBOL_VALUE_ADDRESS (msymbol)))
- return tpst;
- /* Also accept the textlow value of a psymtab as a
- "symbol", to provide some support for partial
- symbol tables with line information but no debug
- symbols (e.g. those produced by an assembler). */
- if (p != NULL)
- this_addr = p->address (objfile);
- else
- this_addr = tpst->text_low (objfile);
- /* Check whether it is closer than our current
- BEST_ADDR. Since this symbol address is
- necessarily lower or equal to PC, the symbol closer
- to PC is the symbol which address is the highest.
- This way we return the psymtab which contains such
- best match symbol. This can help in cases where the
- symbol information/debuginfo is not complete, like
- for instance on IRIX6 with gcc, where no debug info
- is emitted for statics. (See also the nodebug.exp
- testcase.) */
- if (this_addr > best_addr)
- {
- best_addr = this_addr;
- best_pst = tpst;
- }
- }
- }
- return best_pst;
- }
- /* See psympriv.h. */
- struct partial_symtab *
- psymbol_functions::find_pc_sect_psymtab (struct objfile *objfile,
- CORE_ADDR pc,
- struct obj_section *section,
- struct bound_minimal_symbol msymbol)
- {
- /* Try just the PSYMTABS_ADDRMAP mapping first as it has better
- granularity than the later used TEXTLOW/TEXTHIGH one. However, we need
- to take care as the PSYMTABS_ADDRMAP can hold things other than partial
- symtabs in some cases.
- This function should only be called for objfiles that are using partial
- symtabs, not for objfiles that are using indexes (.gdb_index or
- .debug_names), however 'maintenance print psymbols' calls this function
- directly for all objfiles. If we assume that PSYMTABS_ADDRMAP contains
- partial symtabs then we will end up returning a pointer to an object
- that is not a partial_symtab, which doesn't end well. */
- if (m_partial_symtabs->psymtabs != NULL
- && m_partial_symtabs->psymtabs_addrmap != NULL)
- {
- CORE_ADDR baseaddr = objfile->text_section_offset ();
- struct partial_symtab *pst
- = ((struct partial_symtab *)
- addrmap_find (m_partial_symtabs->psymtabs_addrmap,
- pc - baseaddr));
- if (pst != NULL)
- {
- /* FIXME: addrmaps currently do not handle overlayed sections,
- so fall back to the non-addrmap case if we're debugging
- overlays and the addrmap returned the wrong section. */
- if (overlay_debugging && msymbol.minsym != NULL && section != NULL)
- {
- struct partial_symbol *p;
- /* NOTE: This assumes that every psymbol has a
- corresponding msymbol, which is not necessarily
- true; the debug info might be much richer than the
- object's symbol table. */
- p = find_pc_sect_psymbol (objfile, pst, pc, section);
- if (p == NULL
- || (p->address (objfile)
- != BMSYMBOL_VALUE_ADDRESS (msymbol)))
- goto next;
- }
- /* We do not try to call FIND_PC_SECT_PSYMTAB_CLOSER as
- PSYMTABS_ADDRMAP we used has already the best 1-byte
- granularity and FIND_PC_SECT_PSYMTAB_CLOSER may mislead us into
- a worse chosen section due to the TEXTLOW/TEXTHIGH ranges
- overlap. */
- return pst;
- }
- }
- next:
- /* Existing PSYMTABS_ADDRMAP mapping is present even for PARTIAL_SYMTABs
- which still have no corresponding full SYMTABs read. But it is not
- present for non-DWARF2 debug infos not supporting PSYMTABS_ADDRMAP in GDB
- so far. */
- /* Check even OBJFILE with non-zero PSYMTABS_ADDRMAP as only several of
- its CUs may be missing in PSYMTABS_ADDRMAP as they may be varying
- debug info type in single OBJFILE. */
- for (partial_symtab *pst : require_partial_symbols (objfile))
- if (!pst->psymtabs_addrmap_supported
- && pc >= pst->text_low (objfile) && pc < pst->text_high (objfile))
- {
- struct partial_symtab *best_pst;
- best_pst = find_pc_sect_psymtab_closer (objfile, pc, section, pst,
- msymbol);
- if (best_pst != NULL)
- return best_pst;
- }
- return NULL;
- }
- /* Psymtab version of find_pc_sect_compunit_symtab. See its definition in
- the definition of quick_symbol_functions in symfile.h. */
- struct compunit_symtab *
- psymbol_functions::find_pc_sect_compunit_symtab
- (struct objfile *objfile,
- struct bound_minimal_symbol msymbol,
- CORE_ADDR pc,
- struct obj_section *section,
- int warn_if_readin)
- {
- struct partial_symtab *ps = find_pc_sect_psymtab (objfile,
- pc, section,
- msymbol);
- if (ps != NULL)
- {
- if (warn_if_readin && ps->readin_p (objfile))
- /* Might want to error() here (in case symtab is corrupt and
- will cause a core dump), but maybe we can successfully
- continue, so let's not. */
- warning (_("\
- (Internal error: pc %s in read in psymtab, but not in symtab.)\n"),
- paddress (objfile->arch (), pc));
- psymtab_to_symtab (objfile, ps);
- return ps->get_compunit_symtab (objfile);
- }
- return NULL;
- }
- /* Find which partial symbol within a psymtab matches PC and SECTION.
- Return NULL if none. */
- static struct partial_symbol *
- find_pc_sect_psymbol (struct objfile *objfile,
- struct partial_symtab *psymtab, CORE_ADDR pc,
- struct obj_section *section)
- {
- struct partial_symbol *best = NULL;
- CORE_ADDR best_pc;
- const CORE_ADDR textlow = psymtab->text_low (objfile);
- gdb_assert (psymtab != NULL);
- /* Cope with programs that start at address 0. */
- best_pc = (textlow != 0) ? textlow - 1 : 0;
- /* Search the global symbols as well as the static symbols, so that
- find_pc_partial_function doesn't use a minimal symbol and thus
- cache a bad endaddr. */
- for (partial_symbol *p : psymtab->global_psymbols)
- {
- if (p->domain == VAR_DOMAIN
- && p->aclass == LOC_BLOCK
- && pc >= p->address (objfile)
- && (p->address (objfile) > best_pc
- || (psymtab->text_low (objfile) == 0
- && best_pc == 0 && p->address (objfile) == 0)))
- {
- if (section != NULL) /* Match on a specific section. */
- {
- if (!matching_obj_sections (p->obj_section (objfile),
- section))
- continue;
- }
- best_pc = p->address (objfile);
- best = p;
- }
- }
- for (partial_symbol *p : psymtab->static_psymbols)
- {
- if (p->domain == VAR_DOMAIN
- && p->aclass == LOC_BLOCK
- && pc >= p->address (objfile)
- && (p->address (objfile) > best_pc
- || (psymtab->text_low (objfile) == 0
- && best_pc == 0 && p->address (objfile) == 0)))
- {
- if (section != NULL) /* Match on a specific section. */
- {
- if (!matching_obj_sections (p->obj_section (objfile),
- section))
- continue;
- }
- best_pc = p->address (objfile);
- best = p;
- }
- }
- return best;
- }
- /* Psymtab version of lookup_global_symbol_language. See its definition in
- the definition of quick_symbol_functions in symfile.h. */
- enum language
- psymbol_functions::lookup_global_symbol_language (struct objfile *objfile,
- const char *name,
- domain_enum domain,
- bool *symbol_found_p)
- {
- *symbol_found_p = false;
- if (objfile->sf == NULL)
- return language_unknown;
- lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
- for (partial_symtab *ps : require_partial_symbols (objfile))
- {
- struct partial_symbol *psym;
- if (ps->readin_p (objfile))
- continue;
- psym = lookup_partial_symbol (objfile, ps, lookup_name, 1, domain);
- if (psym)
- {
- *symbol_found_p = true;
- return psym->ginfo.language ();
- }
- }
- return language_unknown;
- }
- /* Returns true if PSYM matches LOOKUP_NAME. */
- static bool
- psymbol_name_matches (partial_symbol *psym,
- const lookup_name_info &lookup_name)
- {
- const language_defn *lang = language_def (psym->ginfo.language ());
- symbol_name_matcher_ftype *name_match
- = lang->get_symbol_name_matcher (lookup_name);
- return name_match (psym->ginfo.search_name (), lookup_name, NULL);
- }
- /* Look in PST for a symbol in DOMAIN whose name matches NAME. Search
- the global block of PST if GLOBAL, and otherwise the static block.
- MATCH is the comparison operation that returns true iff MATCH (s,
- NAME), where s is a SYMBOL_SEARCH_NAME. If ORDERED_COMPARE is
- non-null, the symbols in the block are assumed to be ordered
- according to it (allowing binary search). It must be compatible
- with MATCH. Returns the symbol, if found, and otherwise NULL. */
- static struct partial_symbol *
- match_partial_symbol (struct objfile *objfile,
- struct partial_symtab *pst, int global,
- const lookup_name_info &name, domain_enum domain,
- symbol_compare_ftype *ordered_compare)
- {
- struct partial_symbol **start, **psym;
- struct partial_symbol **top, **real_top, **bottom, **center;
- int length = (global
- ? pst->global_psymbols.size ()
- : pst->static_psymbols.size ());
- int do_linear_search = 1;
- if (length == 0)
- return NULL;
- start = (global ?
- &pst->global_psymbols[0] :
- &pst->static_psymbols[0]);
- if (global && ordered_compare) /* Can use a binary search. */
- {
- do_linear_search = 0;
- /* Binary search. This search is guaranteed to end with center
- pointing at the earliest partial symbol whose name might be
- correct. At that point *all* partial symbols with an
- appropriate name will be checked against the correct
- domain. */
- bottom = start;
- top = start + length - 1;
- real_top = top;
- while (top > bottom)
- {
- center = bottom + (top - bottom) / 2;
- gdb_assert (center < top);
- enum language lang = (*center)->ginfo.language ();
- const char *lang_ln = name.language_lookup_name (lang);
- if (ordered_compare ((*center)->ginfo.search_name (),
- lang_ln) >= 0)
- top = center;
- else
- bottom = center + 1;
- }
- gdb_assert (top == bottom);
- while (top <= real_top
- && psymbol_name_matches (*top, name))
- {
- if (symbol_matches_domain ((*top)->ginfo.language (),
- (*top)->domain, domain))
- return *top;
- top++;
- }
- }
- /* Can't use a binary search or else we found during the binary search that
- we should also do a linear search. */
- if (do_linear_search)
- {
- for (psym = start; psym < start + length; psym++)
- {
- if (symbol_matches_domain ((*psym)->ginfo.language (),
- (*psym)->domain, domain)
- && psymbol_name_matches (*psym, name))
- return *psym;
- }
- }
- return NULL;
- }
- /* Look, in partial_symtab PST, for symbol whose natural name is
- LOOKUP_NAME. Check the global symbols if GLOBAL, the static
- symbols if not. */
- static struct partial_symbol *
- lookup_partial_symbol (struct objfile *objfile,
- struct partial_symtab *pst,
- const lookup_name_info &lookup_name,
- int global, domain_enum domain)
- {
- struct partial_symbol **start, **psym;
- struct partial_symbol **top, **real_top, **bottom, **center;
- int length = (global
- ? pst->global_psymbols.size ()
- : pst->static_psymbols.size ());
- int do_linear_search = 1;
- if (length == 0)
- return NULL;
- start = (global ?
- &pst->global_psymbols[0] :
- &pst->static_psymbols[0]);
- if (global) /* This means we can use a binary search. */
- {
- do_linear_search = 0;
- /* Binary search. This search is guaranteed to end with center
- pointing at the earliest partial symbol whose name might be
- correct. At that point *all* partial symbols with an
- appropriate name will be checked against the correct
- domain. */
- bottom = start;
- top = start + length - 1;
- real_top = top;
- while (top > bottom)
- {
- center = bottom + (top - bottom) / 2;
- gdb_assert (center < top);
- if (strcmp_iw_ordered ((*center)->ginfo.search_name (),
- lookup_name.c_str ()) >= 0)
- {
- top = center;
- }
- else
- {
- bottom = center + 1;
- }
- }
- gdb_assert (top == bottom);
- /* For `case_sensitivity == case_sensitive_off' strcmp_iw_ordered will
- search more exactly than what matches SYMBOL_MATCHES_SEARCH_NAME. */
- while (top >= start && symbol_matches_search_name (&(*top)->ginfo,
- lookup_name))
- top--;
- /* Fixup to have a symbol which matches SYMBOL_MATCHES_SEARCH_NAME. */
- top++;
- while (top <= real_top && symbol_matches_search_name (&(*top)->ginfo,
- lookup_name))
- {
- if (symbol_matches_domain ((*top)->ginfo.language (),
- (*top)->domain, domain))
- return *top;
- top++;
- }
- }
- /* Can't use a binary search or else we found during the binary search that
- we should also do a linear search. */
- if (do_linear_search)
- {
- for (psym = start; psym < start + length; psym++)
- {
- if (symbol_matches_domain ((*psym)->ginfo.language (),
- (*psym)->domain, domain)
- && symbol_matches_search_name (&(*psym)->ginfo, lookup_name))
- return *psym;
- }
- }
- return NULL;
- }
- /* Get the symbol table that corresponds to a partial_symtab.
- This is fast after the first time you do it.
- The result will be NULL if the primary symtab has no symbols,
- which can happen. Otherwise the result is the primary symtab
- that contains PST. */
- static struct compunit_symtab *
- psymtab_to_symtab (struct objfile *objfile, struct partial_symtab *pst)
- {
- /* If it is a shared psymtab, find an unshared psymtab that includes
- it. Any such psymtab will do. */
- while (pst->user != NULL)
- pst = pst->user;
- /* If it's been looked up before, return it. */
- if (pst->get_compunit_symtab (objfile))
- return pst->get_compunit_symtab (objfile);
- /* If it has not yet been read in, read it. */
- if (!pst->readin_p (objfile))
- {
- scoped_restore decrementer = increment_reading_symtab ();
- if (info_verbose)
- {
- gdb_printf (_("Reading in symbols for %s...\n"),
- pst->filename);
- gdb_flush (gdb_stdout);
- }
- pst->read_symtab (objfile);
- }
- return pst->get_compunit_symtab (objfile);
- }
- /* Psymtab version of find_last_source_symtab. See its definition in
- the definition of quick_symbol_functions in symfile.h. */
- struct symtab *
- psymbol_functions::find_last_source_symtab (struct objfile *ofp)
- {
- struct partial_symtab *cs_pst = NULL;
- for (partial_symtab *ps : require_partial_symbols (ofp))
- {
- const char *name = ps->filename;
- int len = strlen (name);
- if (!(len > 2 && (strcmp (&name[len - 2], ".h") == 0
- || strcmp (name, "<<C++-namespaces>>") == 0)))
- cs_pst = ps;
- }
- if (cs_pst)
- {
- if (cs_pst->readin_p (ofp))
- {
- internal_error (__FILE__, __LINE__,
- _("select_source_symtab: "
- "readin pst found and no symtabs."));
- }
- else
- {
- struct compunit_symtab *cust = psymtab_to_symtab (ofp, cs_pst);
- if (cust == NULL)
- return NULL;
- return cust->primary_filetab ();
- }
- }
- return NULL;
- }
- /* Psymtab version of forget_cached_source_info. See its definition in
- the definition of quick_symbol_functions in symfile.h. */
- void
- psymbol_functions::forget_cached_source_info (struct objfile *objfile)
- {
- for (partial_symtab *pst : require_partial_symbols (objfile))
- {
- if (pst->fullname != NULL)
- {
- xfree (pst->fullname);
- pst->fullname = NULL;
- }
- }
- }
- static void
- print_partial_symbols (struct gdbarch *gdbarch, struct objfile *objfile,
- const std::vector<partial_symbol *> &symbols,
- const char *what, struct ui_file *outfile)
- {
- gdb_printf (outfile, " %s partial symbols:\n", what);
- for (partial_symbol *p : symbols)
- {
- QUIT;
- gdb_printf (outfile, " `%s'", p->ginfo.linkage_name ());
- if (p->ginfo.demangled_name () != NULL)
- {
- gdb_printf (outfile, " `%s'",
- p->ginfo.demangled_name ());
- }
- gdb_puts (", ", outfile);
- switch (p->domain)
- {
- case UNDEF_DOMAIN:
- gdb_puts ("undefined domain, ", outfile);
- break;
- case VAR_DOMAIN:
- /* This is the usual thing -- don't print it. */
- break;
- case STRUCT_DOMAIN:
- gdb_puts ("struct domain, ", outfile);
- break;
- case MODULE_DOMAIN:
- gdb_puts ("module domain, ", outfile);
- break;
- case LABEL_DOMAIN:
- gdb_puts ("label domain, ", outfile);
- break;
- case COMMON_BLOCK_DOMAIN:
- gdb_puts ("common block domain, ", outfile);
- break;
- default:
- gdb_puts ("<invalid domain>, ", outfile);
- break;
- }
- switch (p->aclass)
- {
- case LOC_UNDEF:
- gdb_puts ("undefined", outfile);
- break;
- case LOC_CONST:
- gdb_puts ("constant int", outfile);
- break;
- case LOC_STATIC:
- gdb_puts ("static", outfile);
- break;
- case LOC_REGISTER:
- gdb_puts ("register", outfile);
- break;
- case LOC_ARG:
- gdb_puts ("pass by value", outfile);
- break;
- case LOC_REF_ARG:
- gdb_puts ("pass by reference", outfile);
- break;
- case LOC_REGPARM_ADDR:
- gdb_puts ("register address parameter", outfile);
- break;
- case LOC_LOCAL:
- gdb_puts ("stack parameter", outfile);
- break;
- case LOC_TYPEDEF:
- gdb_puts ("type", outfile);
- break;
- case LOC_LABEL:
- gdb_puts ("label", outfile);
- break;
- case LOC_BLOCK:
- gdb_puts ("function", outfile);
- break;
- case LOC_CONST_BYTES:
- gdb_puts ("constant bytes", outfile);
- break;
- case LOC_UNRESOLVED:
- gdb_puts ("unresolved", outfile);
- break;
- case LOC_OPTIMIZED_OUT:
- gdb_puts ("optimized out", outfile);
- break;
- case LOC_COMPUTED:
- gdb_puts ("computed at runtime", outfile);
- break;
- default:
- gdb_puts ("<invalid location>", outfile);
- break;
- }
- gdb_puts (", ", outfile);
- gdb_puts (paddress (gdbarch, p->unrelocated_address ()), outfile);
- gdb_printf (outfile, "\n");
- }
- }
- static void
- dump_psymtab (struct objfile *objfile, struct partial_symtab *psymtab,
- struct ui_file *outfile)
- {
- struct gdbarch *gdbarch = objfile->arch ();
- int i;
- if (psymtab->anonymous)
- {
- gdb_printf (outfile, "\nAnonymous partial symtab (%s) ",
- psymtab->filename);
- }
- else
- {
- gdb_printf (outfile, "\nPartial symtab for source file %s ",
- psymtab->filename);
- }
- gdb_printf (outfile, "(object %s)\n\n",
- host_address_to_string (psymtab));
- gdb_printf (outfile, " Read from object file %s (%s)\n",
- objfile_name (objfile),
- host_address_to_string (objfile));
- if (psymtab->readin_p (objfile))
- gdb_printf
- (outfile,
- " Full symtab was read (at %s)\n",
- host_address_to_string (psymtab->get_compunit_symtab (objfile)));
- gdb_printf (outfile, " Symbols cover text addresses ");
- gdb_puts (paddress (gdbarch, psymtab->text_low (objfile)), outfile);
- gdb_printf (outfile, "-");
- gdb_puts (paddress (gdbarch, psymtab->text_high (objfile)), outfile);
- gdb_printf (outfile, "\n");
- gdb_printf (outfile, " Address map supported - %s.\n",
- psymtab->psymtabs_addrmap_supported ? "yes" : "no");
- gdb_printf (outfile, " Depends on %d other partial symtabs.\n",
- psymtab->number_of_dependencies);
- for (i = 0; i < psymtab->number_of_dependencies; i++)
- gdb_printf (outfile, " %d %s\n", i,
- host_address_to_string (psymtab->dependencies[i]));
- if (psymtab->user != NULL)
- gdb_printf (outfile, " Shared partial symtab with user %s\n",
- host_address_to_string (psymtab->user));
- if (!psymtab->global_psymbols.empty ())
- {
- print_partial_symbols
- (gdbarch, objfile, psymtab->global_psymbols,
- "Global", outfile);
- }
- if (!psymtab->static_psymbols.empty ())
- {
- print_partial_symbols
- (gdbarch, objfile, psymtab->static_psymbols,
- "Static", outfile);
- }
- gdb_printf (outfile, "\n");
- }
- /* Count the number of partial symbols in OBJFILE. */
- int
- psymbol_functions::count_psyms ()
- {
- int count = 0;
- for (partial_symtab *pst : m_partial_symtabs->range ())
- {
- count += pst->global_psymbols.size ();
- count += pst->static_psymbols.size ();
- }
- return count;
- }
- /* Psymtab version of print_stats. See its definition in
- the definition of quick_symbol_functions in symfile.h. */
- void
- psymbol_functions::print_stats (struct objfile *objfile, bool print_bcache)
- {
- int i;
- if (!print_bcache)
- {
- int n_psyms = count_psyms ();
- if (n_psyms > 0)
- gdb_printf (_(" Number of \"partial\" symbols read: %d\n"),
- n_psyms);
- i = 0;
- for (partial_symtab *ps : require_partial_symbols (objfile))
- {
- if (!ps->readin_p (objfile))
- i++;
- }
- gdb_printf (_(" Number of psym tables (not yet expanded): %d\n"),
- i);
- gdb_printf (_(" Total memory used for psymbol cache: %d\n"),
- m_partial_symtabs->psymbol_cache.memory_used ());
- }
- else
- {
- gdb_printf (_("Psymbol byte cache statistics:\n"));
- m_partial_symtabs->psymbol_cache.print_statistics
- ("partial symbol cache");
- }
- }
- /* Psymtab version of dump. See its definition in
- the definition of quick_symbol_functions in symfile.h. */
- void
- psymbol_functions::dump (struct objfile *objfile)
- {
- struct partial_symtab *psymtab;
- if (m_partial_symtabs->psymtabs)
- {
- gdb_printf ("Psymtabs:\n");
- for (psymtab = m_partial_symtabs->psymtabs;
- psymtab != NULL;
- psymtab = psymtab->next)
- gdb_printf ("%s at %s\n",
- psymtab->filename,
- host_address_to_string (psymtab));
- gdb_printf ("\n\n");
- }
- }
- /* Psymtab version of expand_all_symtabs. See its definition in
- the definition of quick_symbol_functions in symfile.h. */
- void
- psymbol_functions::expand_all_symtabs (struct objfile *objfile)
- {
- for (partial_symtab *psymtab : require_partial_symbols (objfile))
- psymtab_to_symtab (objfile, psymtab);
- }
- /* Psymtab version of map_symbol_filenames. See its definition in
- the definition of quick_symbol_functions in symfile.h. */
- void
- psymbol_functions::map_symbol_filenames
- (struct objfile *objfile,
- gdb::function_view<symbol_filename_ftype> fun,
- bool need_fullname)
- {
- for (partial_symtab *ps : require_partial_symbols (objfile))
- {
- const char *fullname;
- if (ps->readin_p (objfile))
- continue;
- /* We can skip shared psymtabs here, because any file name will be
- attached to the unshared psymtab. */
- if (ps->user != NULL)
- continue;
- /* Anonymous psymtabs don't have a file name. */
- if (ps->anonymous)
- continue;
- QUIT;
- if (need_fullname)
- fullname = psymtab_to_fullname (ps);
- else
- fullname = NULL;
- fun (ps->filename, fullname);
- }
- }
- /* Finds the fullname that a partial_symtab represents.
- If this functions finds the fullname, it will save it in ps->fullname
- and it will also return the value.
- If this function fails to find the file that this partial_symtab represents,
- NULL will be returned and ps->fullname will be set to NULL. */
- static const char *
- psymtab_to_fullname (struct partial_symtab *ps)
- {
- gdb_assert (!ps->anonymous);
- /* Use cached copy if we have it.
- We rely on forget_cached_source_info being called appropriately
- to handle cases like the file being moved. */
- if (ps->fullname == NULL)
- {
- gdb::unique_xmalloc_ptr<char> fullname
- = find_source_or_rewrite (ps->filename, ps->dirname);
- ps->fullname = fullname.release ();
- }
- return ps->fullname;
- }
- /* Psymtab version of expand_matching_symbols. See its definition in
- the definition of quick_symbol_functions in symfile.h. */
- void
- psymbol_functions::expand_matching_symbols
- (struct objfile *objfile,
- const lookup_name_info &name, domain_enum domain,
- int global,
- symbol_compare_ftype *ordered_compare)
- {
- for (partial_symtab *ps : require_partial_symbols (objfile))
- {
- QUIT;
- if (!ps->readin_p (objfile)
- && match_partial_symbol (objfile, ps, global, name, domain,
- ordered_compare))
- psymtab_to_symtab (objfile, ps);
- }
- }
- /* A helper for psym_expand_symtabs_matching that handles searching
- included psymtabs. This returns true if a symbol is found, and
- false otherwise. It also updates the 'searched_flag' on the
- various psymtabs that it searches. */
- static bool
- recursively_search_psymtabs
- (struct partial_symtab *ps,
- struct objfile *objfile,
- block_search_flags search_flags,
- domain_enum domain,
- enum search_domain search,
- const lookup_name_info &lookup_name,
- gdb::function_view<expand_symtabs_symbol_matcher_ftype> sym_matcher)
- {
- int keep_going = 1;
- enum psymtab_search_status result = PST_SEARCHED_AND_NOT_FOUND;
- int i;
- if (ps->searched_flag != PST_NOT_SEARCHED)
- return ps->searched_flag == PST_SEARCHED_AND_FOUND;
- /* Recurse into shared psymtabs first, because they may have already
- been searched, and this could save some time. */
- for (i = 0; i < ps->number_of_dependencies; ++i)
- {
- int r;
- /* Skip non-shared dependencies, these are handled elsewhere. */
- if (ps->dependencies[i]->user == NULL)
- continue;
- r = recursively_search_psymtabs (ps->dependencies[i],
- objfile, search_flags, domain, search,
- lookup_name, sym_matcher);
- if (r != 0)
- {
- ps->searched_flag = PST_SEARCHED_AND_FOUND;
- return true;
- }
- }
- partial_symbol **gbound = (ps->global_psymbols.data ()
- + ps->global_psymbols.size ());
- partial_symbol **sbound = (ps->static_psymbols.data ()
- + ps->static_psymbols.size ());
- partial_symbol **bound = gbound;
- /* Go through all of the symbols stored in a partial
- symtab in one loop. */
- partial_symbol **psym = ps->global_psymbols.data ();
- if ((search_flags & SEARCH_GLOBAL_BLOCK) == 0)
- {
- if (ps->static_psymbols.empty ())
- keep_going = 0;
- else
- {
- psym = ps->static_psymbols.data ();
- bound = sbound;
- }
- }
- while (keep_going)
- {
- if (psym >= bound)
- {
- if (bound == gbound && !ps->static_psymbols.empty ()
- && (search_flags & SEARCH_STATIC_BLOCK) != 0)
- {
- psym = ps->static_psymbols.data ();
- bound = sbound;
- }
- else
- keep_going = 0;
- continue;
- }
- else
- {
- QUIT;
- if ((domain == UNDEF_DOMAIN
- || symbol_matches_domain ((*psym)->ginfo.language (),
- (*psym)->domain, domain))
- && (search == ALL_DOMAIN
- || (search == MODULES_DOMAIN
- && (*psym)->domain == MODULE_DOMAIN)
- || (search == VARIABLES_DOMAIN
- && (*psym)->aclass != LOC_TYPEDEF
- && (*psym)->aclass != LOC_BLOCK)
- || (search == FUNCTIONS_DOMAIN
- && (*psym)->aclass == LOC_BLOCK)
- || (search == TYPES_DOMAIN
- && (*psym)->aclass == LOC_TYPEDEF))
- && psymbol_name_matches (*psym, lookup_name)
- && (sym_matcher == NULL
- || sym_matcher ((*psym)->ginfo.search_name ())))
- {
- /* Found a match, so notify our caller. */
- result = PST_SEARCHED_AND_FOUND;
- keep_going = 0;
- }
- }
- psym++;
- }
- ps->searched_flag = result;
- return result == PST_SEARCHED_AND_FOUND;
- }
- /* Psymtab version of expand_symtabs_matching. See its definition in
- the definition of quick_symbol_functions in symfile.h. */
- bool
- psymbol_functions::expand_symtabs_matching
- (struct objfile *objfile,
- gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
- const lookup_name_info *lookup_name,
- gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
- gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
- block_search_flags search_flags,
- domain_enum domain,
- enum search_domain search)
- {
- /* Clear the search flags. */
- for (partial_symtab *ps : require_partial_symbols (objfile))
- ps->searched_flag = PST_NOT_SEARCHED;
- gdb::optional<lookup_name_info> psym_lookup_name;
- if (lookup_name != nullptr)
- psym_lookup_name = lookup_name->make_ignore_params ();
- /* This invariant is documented in quick-functions.h. */
- gdb_assert (lookup_name != nullptr || symbol_matcher == nullptr);
- for (partial_symtab *ps : m_partial_symtabs->range ())
- {
- QUIT;
- if (ps->readin_p (objfile))
- continue;
- if (file_matcher)
- {
- bool match;
- if (ps->anonymous)
- continue;
- match = file_matcher (ps->filename, false);
- if (!match)
- {
- /* Before we invoke realpath, which can get expensive when many
- files are involved, do a quick comparison of the basenames. */
- if (basenames_may_differ
- || file_matcher (lbasename (ps->filename), true))
- match = file_matcher (psymtab_to_fullname (ps), false);
- }
- if (!match)
- continue;
- }
- if (lookup_name == nullptr
- || recursively_search_psymtabs (ps, objfile, search_flags,
- domain, search,
- *psym_lookup_name,
- symbol_matcher))
- {
- compunit_symtab *cust = psymtab_to_symtab (objfile, ps);
- if (cust != nullptr && expansion_notify != nullptr)
- if (!expansion_notify (cust))
- return false;
- }
- }
- return true;
- }
- /* Psymtab version of has_symbols. See its definition in
- the definition of quick_symbol_functions in symfile.h. */
- bool
- psymbol_functions::has_symbols (struct objfile *objfile)
- {
- return m_partial_symtabs->psymtabs != NULL;
- }
- /* See quick_symbol_functions::has_unexpanded_symtabs in quick-symbol.h. */
- bool
- psymbol_functions::has_unexpanded_symtabs (struct objfile *objfile)
- {
- for (partial_symtab *psymtab : require_partial_symbols (objfile))
- {
- /* Is this already expanded? */
- if (psymtab->readin_p (objfile))
- continue;
- /* It has not yet been expanded. */
- return true;
- }
- return false;
- }
- /* Helper function for psym_find_compunit_symtab_by_address that fills
- in m_psymbol_map for a given range of psymbols. */
- void
- psymbol_functions::fill_psymbol_map
- (struct objfile *objfile,
- struct partial_symtab *psymtab,
- std::set<CORE_ADDR> *seen_addrs,
- const std::vector<partial_symbol *> &symbols)
- {
- for (partial_symbol *psym : symbols)
- {
- if (psym->aclass == LOC_STATIC)
- {
- CORE_ADDR addr = psym->address (objfile);
- if (seen_addrs->find (addr) == seen_addrs->end ())
- {
- seen_addrs->insert (addr);
- m_psymbol_map.emplace_back (addr, psymtab);
- }
- }
- }
- }
- /* See find_compunit_symtab_by_address in quick_symbol_functions, in
- symfile.h. */
- compunit_symtab *
- psymbol_functions::find_compunit_symtab_by_address (struct objfile *objfile,
- CORE_ADDR address)
- {
- if (m_psymbol_map.empty ())
- {
- std::set<CORE_ADDR> seen_addrs;
- for (partial_symtab *pst : require_partial_symbols (objfile))
- {
- fill_psymbol_map (objfile, pst,
- &seen_addrs,
- pst->global_psymbols);
- fill_psymbol_map (objfile, pst,
- &seen_addrs,
- pst->static_psymbols);
- }
- m_psymbol_map.shrink_to_fit ();
- std::sort (m_psymbol_map.begin (), m_psymbol_map.end (),
- [] (const std::pair<CORE_ADDR, partial_symtab *> &a,
- const std::pair<CORE_ADDR, partial_symtab *> &b)
- {
- return a.first < b.first;
- });
- }
- auto iter = std::lower_bound
- (m_psymbol_map.begin (), m_psymbol_map.end (), address,
- [] (const std::pair<CORE_ADDR, partial_symtab *> &a,
- CORE_ADDR b)
- {
- return a.first < b;
- });
- if (iter == m_psymbol_map.end () || iter->first != address)
- return NULL;
- return psymtab_to_symtab (objfile, iter->second);
- }
- /* Partially fill a partial symtab. It will be completely filled at
- the end of the symbol list. */
- partial_symtab::partial_symtab (const char *filename,
- psymtab_storage *partial_symtabs,
- objfile_per_bfd_storage *objfile_per_bfd,
- CORE_ADDR textlow)
- : partial_symtab (filename, partial_symtabs, objfile_per_bfd)
- {
- set_text_low (textlow);
- set_text_high (raw_text_low ()); /* default */
- }
- /* Perform "finishing up" operations of a partial symtab. */
- void
- partial_symtab::end ()
- {
- global_psymbols.shrink_to_fit ();
- static_psymbols.shrink_to_fit ();
- /* Sort the global list; don't sort the static list. */
- std::sort (global_psymbols.begin (),
- global_psymbols.end (),
- [] (partial_symbol *s1, partial_symbol *s2)
- {
- return strcmp_iw_ordered (s1->ginfo.search_name (),
- s2->ginfo.search_name ()) < 0;
- });
- }
- /* See psymtab.h. */
- unsigned long
- psymbol_bcache::hash (const void *addr, int length)
- {
- unsigned long h = 0;
- struct partial_symbol *psymbol = (struct partial_symbol *) addr;
- unsigned int lang = psymbol->ginfo.language ();
- unsigned int domain = psymbol->domain;
- unsigned int theclass = psymbol->aclass;
- h = fast_hash (&psymbol->ginfo.value, sizeof (psymbol->ginfo.value), h);
- h = fast_hash (&lang, sizeof (unsigned int), h);
- h = fast_hash (&domain, sizeof (unsigned int), h);
- h = fast_hash (&theclass, sizeof (unsigned int), h);
- /* Note that psymbol names are interned via compute_and_set_names, so
- there's no need to hash the contents of the name here. */
- h = fast_hash (&psymbol->ginfo.m_name, sizeof (psymbol->ginfo.m_name), h);
- return h;
- }
- /* See psymtab.h. */
- int
- psymbol_bcache::compare (const void *addr1, const void *addr2, int length)
- {
- struct partial_symbol *sym1 = (struct partial_symbol *) addr1;
- struct partial_symbol *sym2 = (struct partial_symbol *) addr2;
- return (memcmp (&sym1->ginfo.value, &sym2->ginfo.value,
- sizeof (sym1->ginfo.value)) == 0
- && sym1->ginfo.language () == sym2->ginfo.language ()
- && sym1->domain == sym2->domain
- && sym1->aclass == sym2->aclass
- /* Note that psymbol names are interned via
- compute_and_set_names, so there's no need to compare the
- contents of the name here. */
- && sym1->ginfo.linkage_name () == sym2->ginfo.linkage_name ());
- }
- /* See psympriv.h. */
- void
- partial_symtab::add_psymbol (const partial_symbol &psymbol,
- psymbol_placement where,
- psymtab_storage *partial_symtabs,
- struct objfile *objfile)
- {
- bool added;
- /* Stash the partial symbol away in the cache. */
- partial_symbol *psym
- = ((struct partial_symbol *)
- partial_symtabs->psymbol_cache.insert
- (&psymbol, sizeof (struct partial_symbol), &added));
- /* Do not duplicate global partial symbols. */
- if (where == psymbol_placement::GLOBAL && !added)
- return;
- /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
- std::vector<partial_symbol *> &list
- = (where == psymbol_placement::STATIC
- ? static_psymbols
- : global_psymbols);
- list.push_back (psym);
- }
- /* See psympriv.h. */
- void
- partial_symtab::add_psymbol (gdb::string_view name, bool copy_name,
- domain_enum domain,
- enum address_class theclass,
- short section,
- psymbol_placement where,
- CORE_ADDR coreaddr,
- enum language language,
- psymtab_storage *partial_symtabs,
- struct objfile *objfile)
- {
- struct partial_symbol psymbol;
- memset (&psymbol, 0, sizeof (psymbol));
- psymbol.set_unrelocated_address (coreaddr);
- psymbol.ginfo.set_section_index (section);
- psymbol.domain = domain;
- psymbol.aclass = theclass;
- psymbol.ginfo.set_language (language, partial_symtabs->obstack ());
- psymbol.ginfo.compute_and_set_names (name, copy_name, objfile->per_bfd);
- add_psymbol (psymbol, where, partial_symtabs, objfile);
- }
- /* See psympriv.h. */
- partial_symtab::partial_symtab (const char *filename_,
- psymtab_storage *partial_symtabs,
- objfile_per_bfd_storage *objfile_per_bfd)
- : searched_flag (PST_NOT_SEARCHED),
- text_low_valid (0),
- text_high_valid (0)
- {
- partial_symtabs->install_psymtab (this);
- filename = objfile_per_bfd->intern (filename_);
- if (symtab_create_debug)
- {
- /* Be a bit clever with debugging messages, and don't print objfile
- every time, only when it changes. */
- static std::string last_bfd_name;
- const char *this_bfd_name
- = bfd_get_filename (objfile_per_bfd->get_bfd ());
- if (last_bfd_name.empty () || last_bfd_name != this_bfd_name)
- {
- last_bfd_name = this_bfd_name;
- gdb_printf (gdb_stdlog,
- "Creating one or more psymtabs for %s ...\n",
- this_bfd_name);
- }
- gdb_printf (gdb_stdlog,
- "Created psymtab %s for module %s.\n",
- host_address_to_string (this), filename);
- }
- }
- /* See psympriv.h. */
- void
- partial_symtab::expand_dependencies (struct objfile *objfile)
- {
- for (int i = 0; i < number_of_dependencies; ++i)
- {
- if (!dependencies[i]->readin_p (objfile)
- && dependencies[i]->user == NULL)
- {
- /* Inform about additional files to be read in. */
- if (info_verbose)
- {
- gdb_puts (" ");
- gdb_stdout->wrap_here (0);
- gdb_puts ("and ");
- gdb_stdout->wrap_here (0);
- gdb_printf ("%s...", dependencies[i]->filename);
- gdb_flush (gdb_stdout);
- }
- dependencies[i]->expand_psymtab (objfile);
- }
- }
- }
- void
- psymtab_storage::discard_psymtab (struct partial_symtab *pst)
- {
- struct partial_symtab **prev_pst;
- /* From dbxread.c:
- Empty psymtabs happen as a result of header files which don't
- have any symbols in them. There can be a lot of them. But this
- check is wrong, in that a psymtab with N_SLINE entries but
- nothing else is not empty, but we don't realize that. Fixing
- that without slowing things down might be tricky. */
- /* First, snip it out of the psymtab chain. */
- prev_pst = &psymtabs;
- while ((*prev_pst) != pst)
- prev_pst = &((*prev_pst)->next);
- (*prev_pst) = pst->next;
- delete pst;
- }
- /* Helper function for maintenance_print_psymbols to print the addrmap
- of PSYMTAB. If PSYMTAB is NULL print the entire addrmap. */
- static void
- dump_psymtab_addrmap (struct objfile *objfile,
- psymtab_storage *partial_symtabs,
- struct partial_symtab *psymtab,
- struct ui_file *outfile)
- {
- if ((psymtab == NULL
- || psymtab->psymtabs_addrmap_supported)
- && partial_symtabs->psymtabs_addrmap != NULL)
- {
- if (psymtab == nullptr)
- gdb_printf (outfile, _("Entire address map:\n"));
- else
- gdb_printf (outfile, _("Address map:\n"));
- addrmap_dump (partial_symtabs->psymtabs_addrmap, outfile, psymtab);
- }
- }
- static void
- maintenance_print_psymbols (const char *args, int from_tty)
- {
- struct ui_file *outfile = gdb_stdout;
- char *address_arg = NULL, *source_arg = NULL, *objfile_arg = NULL;
- int i, outfile_idx, found;
- CORE_ADDR pc = 0;
- struct obj_section *section = NULL;
- dont_repeat ();
- gdb_argv argv (args);
- for (i = 0; argv != NULL && argv[i] != NULL; ++i)
- {
- if (strcmp (argv[i], "-pc") == 0)
- {
- if (argv[i + 1] == NULL)
- error (_("Missing pc value"));
- address_arg = argv[++i];
- }
- else if (strcmp (argv[i], "-source") == 0)
- {
- if (argv[i + 1] == NULL)
- error (_("Missing source file"));
- source_arg = argv[++i];
- }
- else if (strcmp (argv[i], "-objfile") == 0)
- {
- if (argv[i + 1] == NULL)
- error (_("Missing objfile name"));
- objfile_arg = argv[++i];
- }
- else if (strcmp (argv[i], "--") == 0)
- {
- /* End of options. */
- ++i;
- break;
- }
- else if (argv[i][0] == '-')
- {
- /* Future proofing: Don't allow OUTFILE to begin with "-". */
- error (_("Unknown option: %s"), argv[i]);
- }
- else
- break;
- }
- outfile_idx = i;
- if (address_arg != NULL && source_arg != NULL)
- error (_("Must specify at most one of -pc and -source"));
- stdio_file arg_outfile;
- if (argv != NULL && argv[outfile_idx] != NULL)
- {
- if (argv[outfile_idx + 1] != NULL)
- error (_("Junk at end of command"));
- gdb::unique_xmalloc_ptr<char> outfile_name
- (tilde_expand (argv[outfile_idx]));
- if (!arg_outfile.open (outfile_name.get (), FOPEN_WT))
- perror_with_name (outfile_name.get ());
- outfile = &arg_outfile;
- }
- if (address_arg != NULL)
- {
- pc = parse_and_eval_address (address_arg);
- /* If we fail to find a section, that's ok, try the lookup anyway. */
- section = find_pc_section (pc);
- }
- found = 0;
- for (objfile *objfile : current_program_space->objfiles ())
- {
- int printed_objfile_header = 0;
- int print_for_objfile = 1;
- QUIT;
- if (objfile_arg != NULL)
- print_for_objfile
- = compare_filenames_for_search (objfile_name (objfile),
- objfile_arg);
- if (!print_for_objfile)
- continue;
- for (const auto &iter : objfile->qf)
- {
- psymbol_functions *psf
- = dynamic_cast<psymbol_functions *> (iter.get ());
- if (psf == nullptr)
- continue;
- psymtab_storage *partial_symtabs
- = psf->get_partial_symtabs ().get ();
- if (address_arg != NULL)
- {
- struct bound_minimal_symbol msymbol;
- /* We don't assume each pc has a unique objfile (this is for
- debugging). */
- struct partial_symtab *ps
- = psf->find_pc_sect_psymtab (objfile, pc, section, msymbol);
- if (ps != NULL)
- {
- if (!printed_objfile_header)
- {
- outfile->printf ("\nPartial symtabs for objfile %s\n",
- objfile_name (objfile));
- printed_objfile_header = 1;
- }
- dump_psymtab (objfile, ps, outfile);
- dump_psymtab_addrmap (objfile, partial_symtabs, ps, outfile);
- found = 1;
- }
- }
- else
- {
- for (partial_symtab *ps : psf->require_partial_symbols (objfile))
- {
- int print_for_source = 0;
- QUIT;
- if (source_arg != NULL)
- {
- print_for_source
- = compare_filenames_for_search (ps->filename, source_arg);
- found = 1;
- }
- if (source_arg == NULL
- || print_for_source)
- {
- if (!printed_objfile_header)
- {
- outfile->printf ("\nPartial symtabs for objfile %s\n",
- objfile_name (objfile));
- printed_objfile_header = 1;
- }
- dump_psymtab (objfile, ps, outfile);
- dump_psymtab_addrmap (objfile, partial_symtabs, ps,
- outfile);
- }
- }
- }
- /* If we're printing all the objfile's symbols dump the full addrmap. */
- if (address_arg == NULL
- && source_arg == NULL
- && partial_symtabs->psymtabs_addrmap != NULL)
- {
- outfile->puts ("\n");
- dump_psymtab_addrmap (objfile, partial_symtabs, NULL, outfile);
- }
- }
- }
- if (!found)
- {
- if (address_arg != NULL)
- error (_("No partial symtab for address: %s"), address_arg);
- if (source_arg != NULL)
- error (_("No partial symtab for source file: %s"), source_arg);
- }
- }
- /* List all the partial symbol tables whose names match REGEXP (optional). */
- static void
- maintenance_info_psymtabs (const char *regexp, int from_tty)
- {
- if (regexp)
- re_comp (regexp);
- for (struct program_space *pspace : program_spaces)
- for (objfile *objfile : pspace->objfiles ())
- {
- struct gdbarch *gdbarch = objfile->arch ();
- /* We don't want to print anything for this objfile until we
- actually find a symtab whose name matches. */
- int printed_objfile_start = 0;
- for (const auto &iter : objfile->qf)
- {
- psymbol_functions *psf
- = dynamic_cast<psymbol_functions *> (iter.get ());
- if (psf == nullptr)
- continue;
- for (partial_symtab *psymtab : psf->require_partial_symbols (objfile))
- {
- QUIT;
- if (! regexp
- || re_exec (psymtab->filename))
- {
- if (! printed_objfile_start)
- {
- gdb_printf ("{ objfile %s ", objfile_name (objfile));
- gdb_stdout->wrap_here (2);
- gdb_printf ("((struct objfile *) %s)\n",
- host_address_to_string (objfile));
- printed_objfile_start = 1;
- }
- gdb_printf (" { psymtab %s ", psymtab->filename);
- gdb_stdout->wrap_here (4);
- gdb_printf ("((struct partial_symtab *) %s)\n",
- host_address_to_string (psymtab));
- gdb_printf (" readin %s\n",
- psymtab->readin_p (objfile) ? "yes" : "no");
- gdb_printf (" fullname %s\n",
- psymtab->fullname
- ? psymtab->fullname : "(null)");
- gdb_printf (" text addresses ");
- gdb_puts (paddress (gdbarch,
- psymtab->text_low (objfile)));
- gdb_printf (" -- ");
- gdb_puts (paddress (gdbarch,
- psymtab->text_high (objfile)));
- gdb_printf ("\n");
- gdb_printf (" psymtabs_addrmap_supported %s\n",
- (psymtab->psymtabs_addrmap_supported
- ? "yes" : "no"));
- gdb_printf (" globals ");
- if (!psymtab->global_psymbols.empty ())
- gdb_printf
- ("(* (struct partial_symbol **) %s @ %d)\n",
- host_address_to_string (psymtab->global_psymbols.data ()),
- (int) psymtab->global_psymbols.size ());
- else
- gdb_printf ("(none)\n");
- gdb_printf (" statics ");
- if (!psymtab->static_psymbols.empty ())
- gdb_printf
- ("(* (struct partial_symbol **) %s @ %d)\n",
- host_address_to_string (psymtab->static_psymbols.data ()),
- (int) psymtab->static_psymbols.size ());
- else
- gdb_printf ("(none)\n");
- if (psymtab->user)
- gdb_printf (" user %s "
- "((struct partial_symtab *) %s)\n",
- psymtab->user->filename,
- host_address_to_string (psymtab->user));
- gdb_printf (" dependencies ");
- if (psymtab->number_of_dependencies)
- {
- int i;
- gdb_printf ("{\n");
- for (i = 0; i < psymtab->number_of_dependencies; i++)
- {
- struct partial_symtab *dep = psymtab->dependencies[i];
- /* Note the string concatenation there --- no
- comma. */
- gdb_printf (" psymtab %s "
- "((struct partial_symtab *) %s)\n",
- dep->filename,
- host_address_to_string (dep));
- }
- gdb_printf (" }\n");
- }
- else
- gdb_printf ("(none)\n");
- gdb_printf (" }\n");
- }
- }
- }
- if (printed_objfile_start)
- gdb_printf ("}\n");
- }
- }
- /* Check consistency of currently expanded psymtabs vs symtabs. */
- static void
- maintenance_check_psymtabs (const char *ignore, int from_tty)
- {
- struct symbol *sym;
- struct compunit_symtab *cust = NULL;
- const struct blockvector *bv;
- const struct block *b;
- for (objfile *objfile : current_program_space->objfiles ())
- {
- for (const auto &iter : objfile->qf)
- {
- psymbol_functions *psf
- = dynamic_cast<psymbol_functions *> (iter.get ());
- if (psf == nullptr)
- continue;
- for (partial_symtab *ps : psf->require_partial_symbols (objfile))
- {
- struct gdbarch *gdbarch = objfile->arch ();
- /* We don't call psymtab_to_symtab here because that may cause symtab
- expansion. When debugging a problem it helps if checkers leave
- things unchanged. */
- cust = ps->get_compunit_symtab (objfile);
- /* First do some checks that don't require the associated symtab. */
- if (ps->text_high (objfile) < ps->text_low (objfile))
- {
- gdb_printf ("Psymtab ");
- gdb_puts (ps->filename);
- gdb_printf (" covers bad range ");
- gdb_puts (paddress (gdbarch, ps->text_low (objfile)));
- gdb_printf (" - ");
- gdb_puts (paddress (gdbarch, ps->text_high (objfile)));
- gdb_printf ("\n");
- continue;
- }
- /* Now do checks requiring the associated symtab. */
- if (cust == NULL)
- continue;
- bv = cust->blockvector ();
- b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
- for (partial_symbol *psym : ps->static_psymbols)
- {
- /* Skip symbols for inlined functions without address. These may
- or may not have a match in the full symtab. */
- if (psym->aclass == LOC_BLOCK
- && psym->ginfo.value.address == 0)
- continue;
- sym = block_lookup_symbol (b, psym->ginfo.search_name (),
- symbol_name_match_type::SEARCH_NAME,
- psym->domain);
- if (!sym)
- {
- gdb_printf ("Static symbol `");
- gdb_puts (psym->ginfo.linkage_name ());
- gdb_printf ("' only found in ");
- gdb_puts (ps->filename);
- gdb_printf (" psymtab\n");
- }
- }
- b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- for (partial_symbol *psym : ps->global_psymbols)
- {
- sym = block_lookup_symbol (b, psym->ginfo.search_name (),
- symbol_name_match_type::SEARCH_NAME,
- psym->domain);
- if (!sym)
- {
- gdb_printf ("Global symbol `");
- gdb_puts (psym->ginfo.linkage_name ());
- gdb_printf ("' only found in ");
- gdb_puts (ps->filename);
- gdb_printf (" psymtab\n");
- }
- }
- if (ps->raw_text_high () != 0
- && (ps->text_low (objfile) < BLOCK_START (b)
- || ps->text_high (objfile) > BLOCK_END (b)))
- {
- gdb_printf ("Psymtab ");
- gdb_puts (ps->filename);
- gdb_printf (" covers ");
- gdb_puts (paddress (gdbarch, ps->text_low (objfile)));
- gdb_printf (" - ");
- gdb_puts (paddress (gdbarch, ps->text_high (objfile)));
- gdb_printf (" but symtab covers only ");
- gdb_puts (paddress (gdbarch, BLOCK_START (b)));
- gdb_printf (" - ");
- gdb_puts (paddress (gdbarch, BLOCK_END (b)));
- gdb_printf ("\n");
- }
- }
- }
- }
- }
- void _initialize_psymtab ();
- void
- _initialize_psymtab ()
- {
- add_cmd ("psymbols", class_maintenance, maintenance_print_psymbols, _("\
- Print dump of current partial symbol definitions.\n\
- Usage: mt print psymbols [-objfile OBJFILE] [-pc ADDRESS] [--] [OUTFILE]\n\
- mt print psymbols [-objfile OBJFILE] [-source SOURCE] [--] [OUTFILE]\n\
- Entries in the partial symbol table are dumped to file OUTFILE,\n\
- or the terminal if OUTFILE is unspecified.\n\
- If ADDRESS is provided, dump only the file for that address.\n\
- If SOURCE is provided, dump only that file's symbols.\n\
- If OBJFILE is provided, dump only that file's minimal symbols."),
- &maintenanceprintlist);
- add_cmd ("psymtabs", class_maintenance, maintenance_info_psymtabs, _("\
- List the partial symbol tables for all object files.\n\
- This does not include information about individual partial symbols,\n\
- just the symbol table structures themselves."),
- &maintenanceinfolist);
- add_cmd ("check-psymtabs", class_maintenance, maintenance_check_psymtabs,
- _("\
- Check consistency of currently expanded psymtabs versus symtabs."),
- &maintenancelist);
- }
|