| |
| /*--------------------------------------------------------------------*/ |
| /*--- Format-neutral storage of and querying of info acquired from ---*/ |
| /*--- ELF/XCOFF stabs/dwarf1/dwarf2 debug info. ---*/ |
| /*--- priv_storage.h ---*/ |
| /*--------------------------------------------------------------------*/ |
| |
| /* |
| This file is part of Valgrind, a dynamic binary instrumentation |
| framework. |
| |
| Copyright (C) 2000-2009 Julian Seward |
| jseward@acm.org |
| |
| 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 2 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, write to the Free Software |
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 02111-1307, USA. |
| |
| The GNU General Public License is contained in the file COPYING. |
| */ |
| /* |
| Stabs reader greatly improved by Nick Nethercote, Apr 02. |
| This module was also extensively hacked on by Jeremy Fitzhardinge |
| and Tom Hughes. |
| */ |
| /* See comment at top of debuginfo.c for explanation of |
| the _svma / _avma / _image / _bias naming scheme. |
| */ |
| /* Note this is not freestanding; needs pub_core_xarray.h and |
| priv_tytypes.h to be included before it. */ |
| |
| #ifndef __PRIV_STORAGE_H |
| #define __PRIV_STORAGE_H |
| |
| /* --------------------- SYMBOLS --------------------- */ |
| |
| /* A structure to hold an ELF/XCOFF symbol (very crudely). */ |
| typedef |
| struct { |
| Addr addr; /* lowest address of entity */ |
| Addr tocptr; /* ppc64-linux only: value that R2 should have */ |
| UChar *name; /* name */ |
| // XXX: this could be shrunk (on 32-bit platforms) by using 31 bits for |
| // the size and 1 bit for the isText. If you do this, make sure that |
| // all assignments to isText use 0 or 1 (or True or False), and that a |
| // positive number larger than 1 is never used to represent True. |
| UInt size; /* size in bytes */ |
| Bool isText; |
| Bool isIFunc; /* symbol is an indirect function? */ |
| } |
| DiSym; |
| |
| /* --------------------- SRCLOCS --------------------- */ |
| |
| /* Line count at which overflow happens, due to line numbers being |
| stored as shorts in `struct nlist' in a.out.h. */ |
| #define LINENO_OVERFLOW (1 << (sizeof(short) * 8)) |
| |
| #define LINENO_BITS 20 |
| #define LOC_SIZE_BITS (32 - LINENO_BITS) |
| #define MAX_LINENO ((1 << LINENO_BITS) - 1) |
| |
| /* Unlikely to have any lines with instruction ranges > 4096 bytes */ |
| #define MAX_LOC_SIZE ((1 << LOC_SIZE_BITS) - 1) |
| |
| /* Number used to detect line number overflows; if one line is |
| 60000-odd smaller than the previous, it was probably an overflow. |
| */ |
| #define OVERFLOW_DIFFERENCE (LINENO_OVERFLOW - 5000) |
| |
| /* A structure to hold addr-to-source info for a single line. There |
| can be a lot of these, hence the dense packing. */ |
| typedef |
| struct { |
| /* Word 1 */ |
| Addr addr; /* lowest address for this line */ |
| /* Word 2 */ |
| UShort size:LOC_SIZE_BITS; /* # bytes; we catch overflows of this */ |
| UInt lineno:LINENO_BITS; /* source line number, or zero */ |
| /* Word 3 */ |
| UChar* filename; /* source filename */ |
| /* Word 4 */ |
| UChar* dirname; /* source directory name */ |
| } |
| DiLoc; |
| |
| /* --------------------- CF INFO --------------------- */ |
| |
| /* A structure to summarise DWARF2/3 CFA info for the code address |
| range [base .. base+len-1]. In short, if you know (sp,fp,ip) at |
| some point and ip is in the range [base .. base+len-1], it tells |
| you how to calculate (sp,fp) for the caller of the current frame |
| and also ra, the return address of the current frame. |
| |
| First off, calculate CFA, the Canonical Frame Address, thusly: |
| |
| cfa = case cfa_how of |
| CFIC_SPREL -> sp + cfa_off |
| CFIC_FPREL -> fp + cfa_off |
| CFIR_EXPR -> expr whose index is in cfa_off |
| |
| Once that is done, the previous frame's sp/fp values and this |
| frame's ra value can be calculated like this: |
| |
| old_sp/fp/ra |
| = case sp/fp/ra_how of |
| CFIR_UNKNOWN -> we don't know, sorry |
| CFIR_SAME -> same as it was before (sp/fp only) |
| CFIR_CFAREL -> cfa + sp/fp/ra_off |
| CFIR_MEMCFAREL -> *( cfa + sp/fp/ra_off ) |
| CFIR_EXPR -> expr whose index is in sp/fp/ra_off |
| */ |
| |
| #define CFIC_SPREL ((UChar)1) |
| #define CFIC_FPREL ((UChar)2) |
| #define CFIC_EXPR ((UChar)3) |
| |
| #define CFIR_UNKNOWN ((UChar)4) |
| #define CFIR_SAME ((UChar)5) |
| #define CFIR_CFAREL ((UChar)6) |
| #define CFIR_MEMCFAREL ((UChar)7) |
| #define CFIR_EXPR ((UChar)8) |
| |
| typedef |
| struct { |
| Addr base; |
| UInt len; |
| UChar cfa_how; /* a CFIC_ value */ |
| UChar ra_how; /* a CFIR_ value */ |
| UChar sp_how; /* a CFIR_ value */ |
| UChar fp_how; /* a CFIR_ value */ |
| Int cfa_off; |
| Int ra_off; |
| Int sp_off; |
| Int fp_off; |
| } |
| DiCfSI; |
| |
| |
| typedef |
| enum { |
| Cop_Add=0x321, |
| Cop_Sub, |
| Cop_And, |
| Cop_Mul |
| } |
| CfiOp; |
| |
| typedef |
| enum { |
| Creg_SP=0x213, |
| Creg_FP, |
| Creg_IP |
| } |
| CfiReg; |
| |
| typedef |
| enum { |
| Cex_Undef=0x123, |
| Cex_Deref, |
| Cex_Const, |
| Cex_Binop, |
| Cex_CfiReg, |
| Cex_DwReg |
| } |
| CfiExprTag; |
| |
| typedef |
| struct { |
| CfiExprTag tag; |
| union { |
| struct { |
| } Undef; |
| struct { |
| Int ixAddr; |
| } Deref; |
| struct { |
| UWord con; |
| } Const; |
| struct { |
| CfiOp op; |
| Int ixL; |
| Int ixR; |
| } Binop; |
| struct { |
| CfiReg reg; |
| } CfiReg; |
| struct { |
| Int reg; |
| } DwReg; |
| } |
| Cex; |
| } |
| CfiExpr; |
| |
| extern Int ML_(CfiExpr_Undef) ( XArray* dst ); |
| extern Int ML_(CfiExpr_Deref) ( XArray* dst, Int ixAddr ); |
| extern Int ML_(CfiExpr_Const) ( XArray* dst, UWord con ); |
| extern Int ML_(CfiExpr_Binop) ( XArray* dst, CfiOp op, Int ixL, Int ixR ); |
| extern Int ML_(CfiExpr_CfiReg)( XArray* dst, CfiReg reg ); |
| extern Int ML_(CfiExpr_DwReg) ( XArray* dst, Int reg ); |
| |
| extern void ML_(ppCfiExpr)( XArray* src, Int ix ); |
| |
| /* ---------------- FPO INFO (Windows PE) -------------- */ |
| |
| /* for apps using Wine: MSVC++ PDB FramePointerOmitted: somewhat like |
| a primitive CFI */ |
| typedef |
| struct _FPO_DATA { /* 16 bytes */ |
| UInt ulOffStart; /* offset of 1st byte of function code */ |
| UInt cbProcSize; /* # bytes in function */ |
| UInt cdwLocals; /* # bytes/4 in locals */ |
| UShort cdwParams; /* # bytes/4 in params */ |
| UChar cbProlog; /* # bytes in prolog */ |
| UChar cbRegs :3; /* # regs saved */ |
| UChar fHasSEH:1; /* Structured Exception Handling */ |
| UChar fUseBP :1; /* EBP has been used */ |
| UChar reserved:1; |
| UChar cbFrame:2; /* frame type */ |
| } |
| FPO_DATA; |
| |
| #define PDB_FRAME_FPO 0 |
| #define PDB_FRAME_TRAP 1 |
| #define PDB_FRAME_TSS 2 |
| |
| /* --------------------- VARIABLES --------------------- */ |
| |
| typedef |
| struct { |
| Addr aMin; |
| Addr aMax; |
| XArray* /* of DiVariable */ vars; |
| } |
| DiAddrRange; |
| |
| typedef |
| struct { |
| UChar* name; /* in DebugInfo.strchunks */ |
| UWord typeR; /* a cuOff */ |
| GExpr* gexpr; /* on DebugInfo.gexprs list */ |
| GExpr* fbGX; /* SHARED. */ |
| UChar* fileName; /* where declared; may be NULL. in |
| DebugInfo.strchunks */ |
| Int lineNo; /* where declared; may be zero. */ |
| } |
| DiVariable; |
| |
| Word |
| ML_(cmp_for_DiAddrRange_range) ( const void* keyV, const void* elemV ); |
| |
| /* --------------------- DEBUGINFO --------------------- */ |
| |
| /* This is the top-level data type. It's a structure which contains |
| information pertaining to one mapped ELF object. This type is |
| exported only abstractly - in pub_tool_debuginfo.h. */ |
| |
| #define SEGINFO_STRCHUNKSIZE (64*1024) |
| |
| struct _DebugInfo { |
| |
| /* Admin stuff */ |
| |
| struct _DebugInfo* next; /* list of DebugInfos */ |
| Bool mark; /* marked for deletion? */ |
| |
| /* An abstract handle, which can be used by entities outside of |
| m_debuginfo to (in an abstract datatype sense) refer to this |
| struct _DebugInfo. A .handle of zero is invalid; valid handles |
| are 1 and above. The same handle is never issued twice (in any |
| given run of Valgrind), so a handle becomes invalid when the |
| associated struct _DebugInfo is discarded, and remains invalid |
| forever thereafter. The .handle field is set as soon as this |
| structure is allocated. */ |
| ULong handle; |
| |
| /* Used for debugging only - indicate what stuff to dump whilst |
| reading stuff into the seginfo. Are computed as early in the |
| lifetime of the DebugInfo as possible -- at the point when it is |
| created. Use these when deciding what to spew out; do not use |
| the global VG_(clo_blah) flags. */ |
| |
| Bool trace_symtab; /* symbols, our style */ |
| Bool trace_cfi; /* dwarf frame unwind, our style */ |
| Bool ddump_syms; /* mimic /usr/bin/readelf --syms */ |
| Bool ddump_line; /* mimic /usr/bin/readelf --debug-dump=line */ |
| Bool ddump_frames; /* mimic /usr/bin/readelf --debug-dump=frames */ |
| |
| /* Fields that must be filled in before we can start reading |
| anything from the ELF file. These fields are filled in by |
| VG_(di_notify_mmap) and its immediate helpers. */ |
| |
| UChar* filename; /* in mallocville (VG_AR_DINFO) */ |
| UChar* memname; /* also in VG_AR_DINFO. AIX5 only: .a member name */ |
| |
| Bool have_rx_map; /* did we see a r?x mapping yet for the file? */ |
| Bool have_rw_map; /* did we see a rw? mapping yet for the file? */ |
| |
| Addr rx_map_avma; /* these fields record the file offset, length */ |
| SizeT rx_map_size; /* and map address of the r?x mapping we believe */ |
| OffT rx_map_foff; /* is the .text segment mapping */ |
| |
| Addr rw_map_avma; /* ditto, for the rw? mapping we believe is the */ |
| SizeT rw_map_size; /* .data segment mapping */ |
| OffT rw_map_foff; |
| |
| /* Once both a rw? and r?x mapping for .filename have been |
| observed, we can go on to read the symbol tables and debug info. |
| .have_dinfo flags when that has happened. */ |
| /* If have_dinfo is False, then all fields except "*rx_map*" and |
| "*rw_map*" are invalid and should not be consulted. */ |
| Bool have_dinfo; /* initially False */ |
| |
| /* All the rest of the fields in this structure are filled in once |
| we have committed to reading the symbols and debug info (that |
| is, at the point where .have_dinfo is set to True). */ |
| |
| /* The file's soname. FIXME: ensure this is always allocated in |
| VG_AR_DINFO. */ |
| UChar* soname; |
| |
| /* Description of some important mapped segments. The presence or |
| absence of the mapping is denoted by the _present field, since |
| in some obscure circumstances (to do with data/sdata/bss) it is |
| possible for the mapping to be present but have zero size. |
| Certainly text_ is mandatory on all platforms; not sure about |
| the rest though. |
| |
| -------------------------------------------------------- |
| |
| Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS: we require that |
| |
| either (rx_map_size == 0 && cfsi == NULL) (the degenerate case) |
| |
| or the normal case, which is the AND of the following: |
| (0) rx_map_size > 0 |
| (1) no two DebugInfos with rx_map_size > 0 |
| have overlapping [rx_map_avma,+rx_map_size) |
| (2) [cfsi_minavma,cfsi_maxavma] does not extend |
| beyond [rx_map_avma,+rx_map_size); that is, the former is a |
| subrange or equal to the latter. |
| (3) all DiCfSI in the cfsi array all have ranges that fall within |
| [rx_map_avma,+rx_map_size). |
| (4) all DiCfSI in the cfsi array are non-overlapping |
| |
| The cumulative effect of these restrictions is to ensure that |
| all the DiCfSI records in the entire system are non overlapping. |
| Hence any address falls into either exactly one DiCfSI record, |
| or none. Hence it is safe to cache the results of searches for |
| DiCfSI records. This is the whole point of these restrictions. |
| The caching of DiCfSI searches is done in VG_(use_CF_info). The |
| cache is flushed after any change to debugInfo_list. DiCfSI |
| searches are cached because they are central to stack unwinding |
| on amd64-linux. |
| |
| Where are these invariants imposed and checked? |
| |
| They are checked after a successful read of debuginfo into |
| a DebugInfo*, in check_CFSI_related_invariants. |
| |
| (1) is not really imposed anywhere. We simply assume that the |
| kernel will not map the text segments from two different objects |
| into the same space. Sounds reasonable. |
| |
| (2) follows from (4) and (3). It is ensured by canonicaliseCFI. |
| (3) is ensured by ML_(addDiCfSI). |
| (4) is ensured by canonicaliseCFI. |
| |
| -------------------------------------------------------- |
| |
| Comment_on_DEBUG_SVMA_and_DEBUG_BIAS_fields: |
| |
| The _debug_{svma,bias} fields were added as part of a fix to |
| #185816. The problem encompassed in that bug report was that it |
| wasn't correct to use apply the bias values deduced for a |
| primary object to its associated debuginfo object, because the |
| debuginfo object (or the primary) could have been prelinked to a |
| different SVMA. Hence debuginfo and primary objects need to |
| have their own biases. |
| |
| ------ JRS: (referring to r9329): ------ |
| Let me see if I understand the workings correctly. Initially |
| the _debug_ values are set to the same values as the "normal" |
| ones, as there's a bunch of bits of code like this (in |
| readelf.c) |
| |
| di->text_svma = svma; |
| ... |
| di->text_bias = rx_bias; |
| di->text_debug_svma = svma; |
| di->text_debug_bias = rx_bias; |
| |
| If a debuginfo object subsequently shows up then the |
| _debug_svma/bias are set for the debuginfo object. Result is |
| that if there's no debuginfo object then the values are the same |
| as the primary-object values, and if there is a debuginfo object |
| then they will (or at least may) be different. |
| |
| Then when we need to actually bias something, we'll have to |
| decide whether to use the primary bias or the debuginfo bias. |
| And the strategy is to use the primary bias for ELF symbols but |
| the debuginfo bias for anything pulled out of Dwarf. |
| |
| ------ THH: ------ |
| Correct - the debug_svma and bias values apply to any address |
| read from the debug data regardless of where that debug data is |
| stored and the other values are used for addresses from other |
| places (primarily the symbol table). |
| |
| ------ JRS: ------ |
| Ok; so this was my only area of concern. Are there any |
| corner-case scenarios where this wouldn't be right? It sounds |
| like we're assuming the ELF symbols come from the primary object |
| and, if there is a debug object, then all the Dwarf comes from |
| there. But what if (eg) both symbols and Dwarf come from the |
| debug object? Is that even possible or allowable? |
| |
| ------ THH: ------ |
| You may have a point... |
| |
| The current logic is to try and take any one set of data from |
| either the base object or the debug object. There are four sets |
| of data we consider: |
| |
| - Symbol Table |
| - Stabs |
| - DWARF1 |
| - DWARF2 |
| |
| If we see the primary section for a given set in the base object |
| then we ignore all sections relating to that set in the debug |
| object. |
| |
| Now in principle if we saw a secondary section (like debug_line |
| say) in the base object, but not the main section (debug_info in |
| this case) then we would take debug_info from the debug object |
| but would use the debug_line from the base object unless we saw |
| a replacement copy in the debug object. That's probably unlikely |
| however. |
| |
| A bigger issue might be, as you say, the symbol table as we will |
| pick that up from the debug object if it isn't in the base. The |
| dynamic symbol table will always have to be in the base object |
| though so we will have to be careful when processing symbols to |
| know which table we are reading in that case. |
| |
| What we probably need to do is tell read_elf_symtab which object |
| the symbols it is being asked to read came from. |
| |
| (A followup patch to deal with this was committed in r9469). |
| */ |
| /* .text */ |
| Bool text_present; |
| Addr text_avma; |
| Addr text_svma; |
| SizeT text_size; |
| PtrdiffT text_bias; |
| Addr text_debug_svma; |
| PtrdiffT text_debug_bias; |
| /* .data */ |
| Bool data_present; |
| Addr data_svma; |
| Addr data_avma; |
| SizeT data_size; |
| PtrdiffT data_bias; |
| Addr data_debug_svma; |
| PtrdiffT data_debug_bias; |
| /* .sdata */ |
| Bool sdata_present; |
| Addr sdata_svma; |
| Addr sdata_avma; |
| SizeT sdata_size; |
| PtrdiffT sdata_bias; |
| Addr sdata_debug_svma; |
| PtrdiffT sdata_debug_bias; |
| /* .rodata */ |
| Bool rodata_present; |
| Addr rodata_svma; |
| Addr rodata_avma; |
| SizeT rodata_size; |
| PtrdiffT rodata_bias; |
| Addr rodata_debug_svma; |
| PtrdiffT rodata_debug_bias; |
| /* .bss */ |
| Bool bss_present; |
| Addr bss_svma; |
| Addr bss_avma; |
| SizeT bss_size; |
| PtrdiffT bss_bias; |
| Addr bss_debug_svma; |
| PtrdiffT bss_debug_bias; |
| /* .sbss */ |
| Bool sbss_present; |
| Addr sbss_svma; |
| Addr sbss_avma; |
| SizeT sbss_size; |
| PtrdiffT sbss_bias; |
| Addr sbss_debug_svma; |
| PtrdiffT sbss_debug_bias; |
| /* .plt */ |
| Bool plt_present; |
| Addr plt_avma; |
| SizeT plt_size; |
| /* .got */ |
| Bool got_present; |
| Addr got_avma; |
| SizeT got_size; |
| /* .got.plt */ |
| Bool gotplt_present; |
| Addr gotplt_avma; |
| SizeT gotplt_size; |
| /* .opd -- needed on ppc64-linux for finding symbols */ |
| Bool opd_present; |
| Addr opd_avma; |
| SizeT opd_size; |
| /* .ehframe -- needed on amd64-linux for stack unwinding */ |
| Bool ehframe_present; |
| Addr ehframe_avma; |
| SizeT ehframe_size; |
| |
| /* Sorted tables of stuff we snarfed from the file. This is the |
| eventual product of reading the debug info. All this stuff |
| lives in VG_AR_DINFO. */ |
| |
| /* An expandable array of symbols. */ |
| DiSym* symtab; |
| UWord symtab_used; |
| UWord symtab_size; |
| /* An expandable array of locations. */ |
| DiLoc* loctab; |
| UWord loctab_used; |
| UWord loctab_size; |
| /* An expandable array of CFI summary info records. Also includes |
| summary address bounds, showing the min and max address covered |
| by any of the records, as an aid to fast searching. And, if the |
| records require any expression nodes, they are stored in |
| cfsi_exprs. */ |
| DiCfSI* cfsi; |
| UWord cfsi_used; |
| UWord cfsi_size; |
| Addr cfsi_minavma; |
| Addr cfsi_maxavma; |
| XArray* cfsi_exprs; /* XArray of CfiExpr */ |
| |
| /* Optimized code under Wine x86: MSVC++ PDB FramePointerOmitted |
| data. Non-expandable array, hence .size == .used. */ |
| FPO_DATA* fpo; |
| UWord fpo_size; |
| Addr fpo_minavma; |
| Addr fpo_maxavma; |
| |
| /* Expandable arrays of characters -- the string table. Pointers |
| into this are stable (the arrays are not reallocated). */ |
| struct strchunk { |
| UInt strtab_used; |
| struct strchunk* next; |
| UChar strtab[SEGINFO_STRCHUNKSIZE]; |
| } *strchunks; |
| |
| /* Variable scope information, as harvested from Dwarf3 files. |
| |
| In short it's an |
| |
| array of (array of PC address ranges and variables) |
| |
| The outer array indexes over scopes, with Entry 0 containing |
| information on variables which exist for any value of the program |
| counter (PC) -- that is, the outermost scope. Entries 1, 2, 3, |
| etc contain information on increasinly deeply nested variables. |
| |
| Each inner array is an array of (an address range, and a set |
| of variables that are in scope over that address range). |
| |
| The address ranges may not overlap. |
| |
| Since Entry 0 in the outer array holds information on variables |
| that exist for any value of the PC (that is, global vars), it |
| follows that Entry 0's inner array can only have one address |
| range pair, one that covers the entire address space. |
| */ |
| XArray* /* of OSet of DiAddrRange */varinfo; |
| |
| /* These are arrays of the relevant typed objects, held here |
| partially for the purposes of visiting each object exactly once |
| when we need to delete them. */ |
| |
| /* An array of TyEnts. These are needed to make sense of any types |
| in the .varinfo. Also, when deleting this DebugInfo, we must |
| first traverse this array and throw away malloc'd stuff hanging |
| off it -- by calling ML_(TyEnt__make_EMPTY) on each entry. */ |
| XArray* /* of TyEnt */ admin_tyents; |
| |
| /* An array of guarded DWARF3 expressions. */ |
| XArray* admin_gexprs; |
| }; |
| |
| /* --------------------- functions --------------------- */ |
| |
| /* ------ Adding ------ */ |
| |
| /* Add a symbol to si's symbol table. */ |
| extern void ML_(addSym) ( struct _DebugInfo* di, DiSym* sym ); |
| |
| /* Add a line-number record to a DebugInfo. */ |
| extern |
| void ML_(addLineInfo) ( struct _DebugInfo* di, |
| UChar* filename, |
| UChar* dirname, /* NULL is allowable */ |
| Addr this, Addr next, Int lineno, Int entry); |
| |
| /* Shrink completed tables to save memory. */ |
| extern |
| void ML_(shrinkSym) ( struct _DebugInfo *di ); |
| extern |
| void ML_(shrinkLineInfo) ( struct _DebugInfo *di ); |
| |
| /* Add a CFI summary record. The supplied DiCfSI is copied. */ |
| extern void ML_(addDiCfSI) ( struct _DebugInfo* di, DiCfSI* cfsi ); |
| |
| /* Add a string to the string table of a DebugInfo. If len==-1, |
| ML_(addStr) will itself measure the length of the string. */ |
| extern UChar* ML_(addStr) ( struct _DebugInfo* di, UChar* str, Int len ); |
| |
| extern void ML_(addVar)( struct _DebugInfo* di, |
| Int level, |
| Addr aMin, |
| Addr aMax, |
| UChar* name, |
| UWord typeR, /* a cuOff */ |
| GExpr* gexpr, |
| GExpr* fbGX, /* SHARED. */ |
| UChar* fileName, /* where decl'd - may be NULL */ |
| Int lineNo, /* where decl'd - may be zero */ |
| Bool show ); |
| |
| /* Canonicalise the tables held by 'di', in preparation for use. Call |
| this after finishing adding entries to these tables. */ |
| extern void ML_(canonicaliseTables) ( struct _DebugInfo* di ); |
| |
| /* Canonicalise the call-frame-info table held by 'di', in preparation |
| for use. This is called by ML_(canonicaliseTables) but can also be |
| called on it's own to sort just this table. */ |
| extern void ML_(canonicaliseCFI) ( struct _DebugInfo* di ); |
| |
| /* ------ Searching ------ */ |
| |
| /* Find a symbol-table index containing the specified pointer, or -1 |
| if not found. Binary search. */ |
| extern Word ML_(search_one_symtab) ( struct _DebugInfo* di, Addr ptr, |
| Bool match_anywhere_in_sym, |
| Bool findText ); |
| |
| /* Find a location-table index containing the specified pointer, or -1 |
| if not found. Binary search. */ |
| extern Word ML_(search_one_loctab) ( struct _DebugInfo* di, Addr ptr ); |
| |
| /* Find a CFI-table index containing the specified pointer, or -1 if |
| not found. Binary search. */ |
| extern Word ML_(search_one_cfitab) ( struct _DebugInfo* di, Addr ptr ); |
| |
| /* Find a FPO-table index containing the specified pointer, or -1 |
| if not found. Binary search. */ |
| extern Word ML_(search_one_fpotab) ( struct _DebugInfo* di, Addr ptr ); |
| |
| /* ------ Misc ------ */ |
| |
| /* Show a non-fatal debug info reading error. Use vg_panic if |
| terminal. 'serious' errors are always shown, not 'serious' ones |
| are shown only at verbosity level 2 and above. */ |
| extern |
| void ML_(symerr) ( struct _DebugInfo* di, Bool serious, HChar* msg ); |
| |
| /* Print a symbol. */ |
| extern void ML_(ppSym) ( Int idx, DiSym* sym ); |
| |
| /* Print a call-frame-info summary. */ |
| extern void ML_(ppDiCfSI) ( XArray* /* of CfiExpr */ exprs, DiCfSI* si ); |
| |
| |
| #define TRACE_SYMTAB(format, args...) \ |
| if (di->trace_symtab) { VG_(printf)(format, ## args); } |
| |
| |
| #endif /* ndef __PRIV_STORAGE_H */ |
| |
| /*--------------------------------------------------------------------*/ |
| /*--- end ---*/ |
| /*--------------------------------------------------------------------*/ |