diff options
Diffstat (limited to 'coregrind/m_debuginfo/.svn/text-base/priv_storage.h.svn-base')
-rw-r--r-- | coregrind/m_debuginfo/.svn/text-base/priv_storage.h.svn-base | 684 |
1 files changed, 684 insertions, 0 deletions
diff --git a/coregrind/m_debuginfo/.svn/text-base/priv_storage.h.svn-base b/coregrind/m_debuginfo/.svn/text-base/priv_storage.h.svn-base new file mode 100644 index 0000000..50abe79 --- /dev/null +++ b/coregrind/m_debuginfo/.svn/text-base/priv_storage.h.svn-base @@ -0,0 +1,684 @@ + +/*--------------------------------------------------------------------*/ +/*--- 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 */ + UInt size; /* size in bytes */ + Bool isText; + } + 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); + +/* 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 ); + +/* ------ 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 ---*/ +/*--------------------------------------------------------------------*/ |