From: Julian Seward Date: Fri, 13 Jul 2012 11:24:05 +0000 (+0000) Subject: Allow multiple rw and rx mappings in the ELF debuginfo reader. X-Git-Tag: svn/VALGRIND_3_8_0~133 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=989f74ff0de4f0ca02bc865121e51d8e78e1e136;p=thirdparty%2Fvalgrind.git Allow multiple rw and rx mappings in the ELF debuginfo reader. Fixes #296318 (patch on comment 8). (Jiří Hruška, jirka@fud.cz) git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12735 --- diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c index 99389c296d..7b484a7503 100644 --- a/coregrind/m_debuginfo/debuginfo.c +++ b/coregrind/m_debuginfo/debuginfo.c @@ -178,6 +178,9 @@ DebugInfo* alloc_DebugInfo( const UChar* filename ) di = ML_(dinfo_zalloc)("di.debuginfo.aDI.1", sizeof(DebugInfo)); di->handle = handle_counter++; di->fsm.filename = ML_(dinfo_strdup)("di.debuginfo.aDI.2", filename); + di->fsm.maps = VG_(newXA)( + ML_(dinfo_zalloc), "di.debuginfo.aDI.3", + ML_(dinfo_free), sizeof(struct _DebugInfoMapping)); /* Everything else -- pointers, sizes, arrays -- is zeroed by ML_(dinfo_zalloc). Now set up the debugging-output flags. */ @@ -204,6 +207,7 @@ static void free_DebugInfo ( DebugInfo* di ) GExpr* gexpr; vg_assert(di != NULL); + if (di->fsm.maps) VG_(deleteXA)(di->fsm.maps); if (di->fsm.filename) ML_(dinfo_free)(di->fsm.filename); if (di->soname) ML_(dinfo_free)(di->soname); if (di->loctab) ML_(dinfo_free)(di->loctab); @@ -385,32 +389,20 @@ static Bool ranges_overlap (Addr s1, SizeT len1, Addr s2, SizeT len2 ) } -/* Do the basic rx_ and rw_ mappings of the two DebugInfos overlap in - any way? */ +/* Do the basic mappings of the two DebugInfos overlap in any way? */ static Bool do_DebugInfos_overlap ( DebugInfo* di1, DebugInfo* di2 ) { + Word i, j; vg_assert(di1); vg_assert(di2); - - if (di1->fsm.have_rx_map && di2->fsm.have_rx_map - && ranges_overlap(di1->fsm.rx_map_avma, di1->fsm.rx_map_size, - di2->fsm.rx_map_avma, di2->fsm.rx_map_size)) - return True; - - if (di1->fsm.have_rx_map && di2->fsm.have_rw_map - && ranges_overlap(di1->fsm.rx_map_avma, di1->fsm.rx_map_size, - di2->fsm.rw_map_avma, di2->fsm.rw_map_size)) - return True; - - if (di1->fsm.have_rw_map && di2->fsm.have_rx_map - && ranges_overlap(di1->fsm.rw_map_avma, di1->fsm.rw_map_size, - di2->fsm.rx_map_avma, di2->fsm.rx_map_size)) - return True; - - if (di1->fsm.have_rw_map && di2->fsm.have_rw_map - && ranges_overlap(di1->fsm.rw_map_avma, di1->fsm.rw_map_size, - di2->fsm.rw_map_avma, di2->fsm.rw_map_size)) - return True; + for (i = 0; i < VG_(sizeXA)(di1->fsm.maps); i++) { + struct _DebugInfoMapping* map1 = VG_(indexXA)(di1->fsm.maps, i); + for (j = 0; j < VG_(sizeXA)(di2->fsm.maps); j++) { + struct _DebugInfoMapping* map2 = VG_(indexXA)(di2->fsm.maps, j); + if (ranges_overlap(map1->avma, map1->size, map2->avma, map2->size)) + return True; + } + } return False; } @@ -441,8 +433,7 @@ static void discard_marked_DebugInfos ( void ) /* Discard any elements of debugInfo_list which overlap with diRef. - Clearly diRef must have its rx_ and rw_ mapping information set to - something sane. */ + Clearly diRef must have its mapping information set to something sane. */ static void discard_DebugInfos_which_overlap_with ( DebugInfo* diRef ) { DebugInfo* di; @@ -490,41 +481,67 @@ static DebugInfo* find_or_create_DebugInfo_for ( UChar* filename ) static void check_CFSI_related_invariants ( DebugInfo* di ) { DebugInfo* di2 = NULL; + Bool has_nonempty_rx = False; + Bool cfsi_fits = False; + Word i, j; vg_assert(di); /* This fn isn't called until after debuginfo for this object has been successfully read. And that shouldn't happen until we have both a r-x and rw- mapping for the object. Hence: */ vg_assert(di->fsm.have_rx_map); vg_assert(di->fsm.have_rw_map); - /* degenerate case: r-x section is empty */ - if (di->fsm.rx_map_size == 0) { - vg_assert(di->cfsi == NULL); - return; - } - /* normal case: r-x section is nonempty */ - /* invariant (0) */ - vg_assert(di->fsm.rx_map_size > 0); - /* invariant (1) */ - for (di2 = debugInfo_list; di2; di2 = di2->next) { - if (di2 == di) + for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { + struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); + /* We are interested in r-x mappings only */ + if (!map->rx) continue; - if (di2->fsm.rx_map_size == 0) + + /* degenerate case: r-x section is empty */ + if (map->size == 0) continue; - vg_assert( - di->fsm.rx_map_avma + di->fsm.rx_map_size <= di2->fsm.rx_map_avma - || di2->fsm.rx_map_avma + di2->fsm.rx_map_size <= di->fsm.rx_map_avma - ); + has_nonempty_rx = True; + + /* normal case: r-x section is nonempty */ + /* invariant (0) */ + vg_assert(map->size > 0); + + /* invariant (1) */ + for (di2 = debugInfo_list; di2; di2 = di2->next) { + if (di2 == di) + continue; + for (j = 0; j < VG_(sizeXA)(di2->fsm.maps); j++) { + struct _DebugInfoMapping* map2 = VG_(indexXA)(di2->fsm.maps, j); + if (!map2->rx || map2->size == 0) + continue; + vg_assert(!ranges_overlap(map->avma, map->size, + map2->avma, map2->size)); + } + } + di2 = NULL; + + /* invariant (2) */ + if (di->cfsi) { + vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */ + /* Assume the csfi fits completely into one individual mapping + for now. This might need to be improved/reworked later. */ + if (di->cfsi_minavma >= map->avma && + di->cfsi_maxavma < map->avma + map->size) + cfsi_fits = True; + } } - di2 = NULL; - /* invariant (2) */ - if (di->cfsi) { - vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */ - vg_assert(di->cfsi_minavma >= di->fsm.rx_map_avma); - vg_assert(di->cfsi_maxavma < di->fsm.rx_map_avma + di->fsm.rx_map_size); + + /* degenerate case: all r-x sections are empty */ + if (!has_nonempty_rx) { + vg_assert(di->cfsi == NULL); + return; } + + /* invariant (2) - cont. */ + if (di->cfsi) + vg_assert(cfsi_fits); + /* invariants (3) and (4) */ if (di->cfsi) { - Word i; vg_assert(di->cfsi_used > 0); vg_assert(di->cfsi_size > 0); for (i = 0; i < di->cfsi_used; i++) { @@ -601,9 +618,9 @@ static ULong di_notify_ACHIEVE_ACCEPT_STATE ( struct _DebugInfo* di ) TRACE_SYMTAB("\n"); /* We're going to read symbols and debug info for the avma - ranges [rx_map_avma, +rx_map_size) and [rw_map_avma, - +rw_map_size). First get rid of any other DebugInfos which - overlap either of those ranges (to avoid total confusion). */ + ranges specified in the _DebugInfoFsm mapping array. First + get rid of any other DebugInfos which overlap any of those + ranges (to avoid total confusion). */ discard_DebugInfos_which_overlap_with( di ); /* .. and acquire new info. */ @@ -874,41 +891,20 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd ) di = find_or_create_DebugInfo_for( filename ); vg_assert(di); - if (is_rx_map) { - /* We have a text-like mapping. Note the details. */ - if (!di->fsm.have_rx_map) { - di->fsm.have_rx_map = True; - di->fsm.rx_map_avma = a; - di->fsm.rx_map_size = seg->end + 1 - seg->start; - di->fsm.rx_map_foff = seg->offset; - } else { - /* FIXME: complain about a second text-like mapping */ - } - } - - if (is_rw_map) { - /* We have a data-like mapping. Note the details. */ - if (!di->fsm.have_rw_map) { - di->fsm.have_rw_map = True; - di->fsm.rw_map_avma = a; - di->fsm.rw_map_size = seg->end + 1 - seg->start; - di->fsm.rw_map_foff = seg->offset; - } else { - /* FIXME: complain about a second data-like mapping */ - } - } - - if (is_ro_map) { - /* We have a r-- mapping. Note the details (OSX 10.7, 32-bit only) */ - if (!di->fsm.have_ro_map) { - di->fsm.have_ro_map = True; - di->fsm.ro_map_avma = a; - di->fsm.ro_map_size = seg->end + 1 - seg->start; - di->fsm.ro_map_foff = seg->offset; - } else { - /* FIXME: complain about a second r-- mapping */ - } - } + /* Note the details about the mapping. */ + struct _DebugInfoMapping map; + map.avma = a; + map.size = seg->end + 1 - seg->start; + map.foff = seg->offset; + map.rx = is_rx_map; + map.rw = is_rw_map; + map.ro = is_ro_map; + VG_(addToXA)(di->fsm.maps, &map); + + /* Update flags about what kind of mappings we've already seen. */ + di->fsm.have_rx_map |= is_rx_map; + di->fsm.have_rw_map |= is_rw_map; + di->fsm.have_ro_map |= is_ro_map; /* So, finally, are we in an accept state? */ if (di->fsm.have_rx_map && di->fsm.have_rw_map && !di->have_dinfo) { @@ -977,6 +973,8 @@ void VG_(di_notify_vm_protect)( Addr a, SizeT len, UInt prot ) is found, conclude we're in an accept state and read debuginfo accordingly. */ DebugInfo* di; + struct _DebugInfoMapping *map = NULL; + Word i; for (di = debugInfo_list; di; di = di->next) { vg_assert(di->fsm.filename); if (di->have_dinfo) @@ -987,36 +985,45 @@ void VG_(di_notify_vm_protect)( Addr a, SizeT len, UInt prot ) continue; /* rx- mapping already exists */ if (!di->fsm.have_rw_map) continue; /* need to have a rw- mapping */ - if (di->fsm.ro_map_avma != a || di->fsm.ro_map_size != len) - continue; /* this isn't an upgrade of the r-- mapping */ + /* Try to find a mapping matching the memory area. */ + for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { + map = (struct _DebugInfoMapping*)VG_(indexXA)(di->fsm.maps, i); + if (map->ro && map->avma == a && map->size == len) + break; + map = NULL; + } + if (!map) + continue; /* this isn't an upgrade of an r-- mapping */ /* looks like we're in luck! */ break; } if (di == NULL) return; /* didn't find anything */ - /* Do the upgrade. Copy the RO map info into the RX map info and - pretend we never saw the RO map at all. */ - vg_assert(di->fsm.have_rw_map); + /* Do the upgrade. Simply update the flags of the mapping + and pretend we never saw the RO map at all. */ vg_assert(di->fsm.have_ro_map); - vg_assert(!di->fsm.have_rx_map); - + map->rx = True; + map->ro = False; di->fsm.have_rx_map = True; - di->fsm.rx_map_avma = di->fsm.ro_map_avma; - di->fsm.rx_map_size = di->fsm.ro_map_size; - di->fsm.rx_map_foff = di->fsm.ro_map_foff; - di->fsm.have_ro_map = False; - di->fsm.ro_map_avma = 0; - di->fsm.ro_map_size = 0; - di->fsm.ro_map_foff = 0; + /* See if there are any more ro mappings */ + for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { + map = (struct _DebugInfoMapping*)VG_(indexXA)(di->fsm.maps, i); + if (map->ro) { + di->fsm.have_ro_map = True; + break; + } + } - /* And since we're now in an accept state, read debuginfo. Finally. */ - ULong di_handle __attribute__((unused)) - = di_notify_ACHIEVE_ACCEPT_STATE( di ); - /* di_handle is ignored. That's not a problem per se -- it just - means nobody will ever be able to refer to this debuginfo by - handle since nobody will know what the handle value is. */ + /* Check if we're now in an accept state and read debuginfo. Finally. */ + if (di->fsm.have_rx_map && di->fsm.have_rw_map && !di->have_dinfo) { + ULong di_handle __attribute__((unused)) + = di_notify_ACHIEVE_ACCEPT_STATE( di ); + /* di_handle is ignored. That's not a problem per se -- it just + means nobody will ever be able to refer to this debuginfo by + handle since nobody will know what the handle value is. */ + } } @@ -1273,6 +1280,31 @@ void VG_(di_discard_ALL_debuginfo)( void ) } +struct _DebugInfoMapping* ML_(find_rx_mapping) ( struct _DebugInfo* di, + Addr lo, Addr hi ) +{ + Word i; + vg_assert(lo <= hi); + + /* Optimization: Try to use the last matched rx mapping first */ + if ( di->last_rx_map + && lo >= di->last_rx_map->avma + && hi < di->last_rx_map->avma + di->last_rx_map->size) + return di->last_rx_map; + + for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { + struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); + if ( map->rx && map->size > 0 + && lo >= map->avma && hi < map->avma + map->size) { + di->last_rx_map = map; + return map; + } + } + + return NULL; +} + + /*------------------------------------------------------------*/ /*--- Use of symbol table & location info to create ---*/ /*--- plausible-looking stack dumps. ---*/ @@ -1300,9 +1332,7 @@ static void search_all_symtabs ( Addr ptr, /*OUT*/DebugInfo** pdi, See Comment_Regarding_Text_Range_Checks in storage.c for details. */ inRange = di->fsm.have_rx_map - && di->fsm.rx_map_size > 0 - && di->fsm.rx_map_avma <= ptr - && ptr < di->fsm.rx_map_avma + di->fsm.rx_map_size; + && (ML_(find_rx_mapping)(di, ptr, ptr) != NULL); } else { inRange = (di->data_present && di->data_size > 0 diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h index 193b154bc2..b541b1512a 100644 --- a/coregrind/m_debuginfo/priv_storage.h +++ b/coregrind/m_debuginfo/priv_storage.h @@ -421,13 +421,9 @@ ML_(cmp_for_DiAddrRange_range) ( const void* keyV, const void* elemV ); true. The initial state is one in which we have no observations, so have_rx_map and have_rw_map are both false. - This is all rather ad-hoc; for example it has no way to record more - than one rw or rx mapping for a given object, not because such - events have never been observed, but because we've never needed to - note more than the first one of any such in order when to decide to - read debug info. It may be that in future we need to track more - state in order to make the decision, so this struct would then get - expanded. + This all started as a rather ad-hoc solution, but was further + expanded to handle weird object layouts, e.g. more than one rw + or rx mapping for one binary. The normal sequence of events is one of @@ -444,28 +440,22 @@ ML_(cmp_for_DiAddrRange_range) ( const void* keyV, const void* elemV ); where the upgrade is done by a call to vm_protect. Hence we need to also track this possibility. */ -struct _DebugInfoFSM + +struct _DebugInfoMapping { - /* --- all targets --- */ - UChar* filename; /* in mallocville (VG_AR_DINFO) */ + Addr avma; /* these fields record the file offset, length */ + SizeT size; /* and map address of each mapping */ + OffT foff; + Bool rx, rw, ro; /* memory access flags for this mapping */ +}; +struct _DebugInfoFSM +{ + UChar* filename; /* in mallocville (VG_AR_DINFO) */ + XArray* maps; /* XArray of _DebugInfoMapping structs */ 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; - - /* --- OSX 10.7, 32-bit only --- */ Bool have_ro_map; /* did we see a r-- mapping yet for the file? */ - - Addr ro_map_avma; /* file offset, length, avma for said mapping */ - SizeT ro_map_size; - OffT ro_map_foff; }; @@ -545,17 +535,17 @@ struct _DebugInfo { Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS: we require that - either (rx_map_size == 0 && cfsi == NULL) (the degenerate case) + either (size of all rx maps == 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. + (0) size of at least one rx mapping > 0 + (1) no two DebugInfos with some rx mapping of size > 0 + have overlapping rx mappings + (2) [cfsi_minavma,cfsi_maxavma] does not extend beyond + [avma,+size) of one rx mapping; 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). + [avma,+size) of that rx mapping. (4) all DiCfSI in the cfsi array are non-overlapping The cumulative effect of these restrictions is to ensure that @@ -808,6 +798,11 @@ struct _DebugInfo { /* An array of guarded DWARF3 expressions. */ XArray* admin_gexprs; + + /* Cached last rx mapping matched and returned by ML_(find_rx_mapping). + This helps performance a lot during ML_(addLineInfo) etc., which can + easily be invoked hundreds of thousands of times. */ + struct _DebugInfoMapping* last_rx_map; }; /* --------------------- functions --------------------- */ @@ -876,6 +871,11 @@ extern Word ML_(search_one_cfitab) ( struct _DebugInfo* di, Addr ptr ); if not found. Binary search. */ extern Word ML_(search_one_fpotab) ( struct _DebugInfo* di, Addr ptr ); +/* Helper function for the most often needed searching for an rx mapping + containing the specified address range. */ +extern struct _DebugInfoMapping* ML_(find_rx_mapping) ( struct _DebugInfo* di, + Addr lo, Addr hi ); + /* ------ Misc ------ */ /* Show a non-fatal debug info reading error. Use vg_panic if diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c index 40f5eea6ff..c0578dcc0b 100644 --- a/coregrind/m_debuginfo/readelf.c +++ b/coregrind/m_debuginfo/readelf.c @@ -554,9 +554,8 @@ Bool get_elf_symbol_info ( background. */ Bool in_rx; vg_assert(di->fsm.have_rx_map); - in_rx = (!(*sym_avma_out + *sym_size_out <= di->fsm.rx_map_avma - || *sym_avma_out >= di->fsm.rx_map_avma - + di->fsm.rx_map_size)); + in_rx = (ML_(find_rx_mapping)(di, *sym_avma_out, + *sym_avma_out + *sym_size_out) != NULL); if (in_text) vg_assert(in_rx); if (!in_rx) { @@ -1266,12 +1265,6 @@ Word file_offset_from_svma ( /*OUT*/Bool* ok, supplied DebugInfo. */ -/* Temporarily holds information copied out of PT_LOAD entries - in ML_(read_elf_debug_info. */ -typedef - struct { Addr svma_base; Addr svma_limit; PtrdiffT bias; } - RangeAndBias; - Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) { /* This function is long and complex. That, and the presence of @@ -1283,7 +1276,7 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) /* TOPLEVEL */ Bool res, ok; SysRes fd, sres; - Word i; + Word i, j; Bool dynbss_present = False; Bool sdynbss_present = False; @@ -1312,19 +1305,19 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) UChar* shdr_strtab_img = NULL; /* SVMAs covered by rx and rw segments and corresponding biases. - We keep separate lists of rx and rw areas. Each can have up to - N_RX_RW_AREAS entries. Normally each object would provide just - one rx and one rw area, but Mike Hommey's elfhack creates - objects with two rx PT_LOAD entries, hence the generality. */ - const Int N_RX_RW_AREAS = 2; - - RangeAndBias rx[N_RX_RW_AREAS]; - RangeAndBias rw[N_RX_RW_AREAS]; - Word n_rx = 0; /* 0 .. N_RX_RW_AREAS */ - Word n_rw = 0; /* 0 .. N_RX_RW_AREAS */ - /* Pointless paranoia: */ - VG_(memset)( rx, 0, sizeof(rx) ); - VG_(memset)( rw, 0, sizeof(rw) ); + Normally each object would provide just one rx and one rw area, + but various ELF mangling tools create objects with multiple + such entries, hence the generality. */ + typedef + struct { + Addr svma_base; + Addr svma_limit; + PtrdiffT bias; + Bool exec; + } + RangeAndBias; + + XArray* /* of RangeAndBias */ svma_ranges = NULL; /* Build ID */ Char* buildid = NULL; @@ -1332,8 +1325,6 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) vg_assert(di); vg_assert(di->fsm.have_rx_map == True); vg_assert(di->fsm.have_rw_map == True); - vg_assert(di->fsm.rx_map_size > 0); - vg_assert(di->fsm.rw_map_size > 0); vg_assert(di->have_dinfo == False); vg_assert(di->fsm.filename); vg_assert(!di->symtab); @@ -1343,19 +1334,35 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) vg_assert(!di->strchunks); vg_assert(!di->soname); - /* If these don't hold true, it means that m_syswrap/m_aspacemgr - managed to do a mapping where the start isn't page aligned. - Which sounds pretty bogus to me. */ - vg_assert(VG_IS_PAGE_ALIGNED(di->fsm.rx_map_avma)); - vg_assert(VG_IS_PAGE_ALIGNED(di->fsm.rw_map_avma)); + { + Bool has_nonempty_rx = False; + Bool has_nonempty_rw = False; + for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { + struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); + if (map->rx) { + if (map->size > 0) + has_nonempty_rx = True; + } else if (map->rw) { + if (map->size > 0) + has_nonempty_rw = True; + } else + continue; + + /* If this doesn't hold true, it means that m_syswrap/m_aspacemgr + managed to do a mapping where the start isn't page aligned. + Which sounds pretty bogus to me. */ + vg_assert(VG_IS_PAGE_ALIGNED(map->avma)); + } + vg_assert(has_nonempty_rx); + vg_assert(has_nonempty_rw); + } /* ---------------------------------------------------------- At this point, there is very little information in the DebugInfo. We only know that something that looks like an ELF - file has been mapped rx-ishly as recorded with the di->*rx_map* - fields and has also been mapped rw-ishly as recorded with the - di->*rw_map* fields. First we examine the file's ELF Program - Header, and, by comparing that against the di->*r{w,x}_map* + file has been mapped rx-ishly and rw-ishly as recorded in the + di->fsm.maps array items. First we examine the file's ELF + Program Header, and, by comparing that against the di->fsm.maps info, try to figure out the AVMAs for the sections we care about, that should have been mapped: text, data, sdata, bss, got, plt, and toc. @@ -1365,8 +1372,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) oimage = (Addr)NULL; if (VG_(clo_verbosity) > 1 || VG_(clo_trace_redir)) - VG_(message)(Vg_DebugMsg, "Reading syms from %s (%#lx)\n", - di->fsm.filename, di->fsm.rx_map_avma ); + VG_(message)(Vg_DebugMsg, "Reading syms from %s\n", + di->fsm.filename ); /* mmap the object image aboard, so that we can read symbols and line number info out of it. It will be munmapped immediately @@ -1441,10 +1448,18 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) phdr_img, phdr_nent, phdr_ent_szB); TRACE_SYMTAB("shdr: img %p nent %ld ent_szB %ld\n", shdr_img, shdr_nent, shdr_ent_szB); - TRACE_SYMTAB("rx_map: avma %#lx size %lu foff %lu\n", - di->fsm.rx_map_avma, di->fsm.rx_map_size, di->fsm.rx_map_foff); - TRACE_SYMTAB("rw_map: avma %#lx size %lu foff %lu\n", - di->fsm.rw_map_avma, di->fsm.rw_map_size, di->fsm.rw_map_foff); + for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { + struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); + if (map->rx) + TRACE_SYMTAB("rx_map: avma %#lx size %lu foff %lu\n", + map->avma, map->size, map->foff); + } + for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { + struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); + if (map->rw) + TRACE_SYMTAB("rw_map: avma %#lx size %lu foff %lu\n", + map->avma, map->size, map->foff); + } if (phdr_nent == 0 || !contained_within( @@ -1478,10 +1493,12 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) TRACE_SYMTAB("shdr: string table at %p\n", shdr_strtab_img ); + svma_ranges = VG_(newXA)(ML_(dinfo_zalloc), "di.relfdi.1", + ML_(dinfo_free), sizeof(RangeAndBias)); + /* TOPLEVEL */ /* Look through the program header table, and: - - copy information from suitable PT_LOAD entries into rx[] or - rw[] + - copy information from suitable PT_LOAD entries into svma_ranges - find (or fake up) the .soname for this object. */ TRACE_SYMTAB("\n"); @@ -1496,10 +1513,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) /* Make sure the PT_LOADable entries are in order and non-overlapping. This in turn means the address ranges - slurped into rx[] and rw[] are in order and + slurped into svma_ranges are in order and non-overlapping. */ - vg_assert(n_rx >= 0 && n_rx <= N_RX_RW_AREAS); - vg_assert(n_rw >= 0 && n_rw <= N_RX_RW_AREAS); if (phdr->p_type == PT_LOAD) { TRACE_SYMTAB("PT_LOAD[%ld]: p_vaddr %#lx (prev %#lx)\n", @@ -1516,42 +1531,41 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) goto out; } prev_svma = phdr->p_vaddr; - if (phdr->p_offset >= di->fsm.rx_map_foff - && phdr->p_offset < di->fsm.rx_map_foff + di->fsm.rx_map_size - && phdr->p_offset + phdr->p_filesz - <= di->fsm.rx_map_foff + di->fsm.rx_map_size - && (phdr->p_flags & (PF_R | PF_W | PF_X)) == (PF_R | PF_X)) { - if (n_rx == N_RX_RW_AREAS) { - ML_(symerr)(di, True, - "N_RX_RW_AREAS is too low; " - "increase and recompile."); - goto out; + if (phdr->p_memsz > 0) { + Bool loaded = False; + for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) { + struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j); + if ( (map->rx || map->rw) + && phdr->p_offset >= map->foff + && phdr->p_offset < map->foff + map->size + && phdr->p_offset + phdr->p_filesz <= map->foff + + map->size) { + RangeAndBias item; + item.svma_base = phdr->p_vaddr; + item.svma_limit = phdr->p_vaddr + phdr->p_memsz; + item.bias = map->avma - map->foff + + phdr->p_offset - phdr->p_vaddr; + if ( map->rw + && (phdr->p_flags & (PF_R | PF_W)) == (PF_R | PF_W)) { + item.exec = False; + VG_(addToXA)(svma_ranges, &item); + TRACE_SYMTAB("PT_LOAD[%ld]: acquired as rw\n", i); + loaded = True; + } + if ( map->rx + && (phdr->p_flags & (PF_R | PF_X)) == (PF_R | PF_X)) { + item.exec = True; + VG_(addToXA)(svma_ranges, &item); + TRACE_SYMTAB("PT_LOAD[%ld]: acquired as rx\n", i); + loaded = True; + } + } } - rx[n_rx].svma_base = phdr->p_vaddr; - rx[n_rx].svma_limit = phdr->p_vaddr + phdr->p_memsz; - rx[n_rx].bias = di->fsm.rx_map_avma - di->fsm.rx_map_foff - + phdr->p_offset - phdr->p_vaddr; - n_rx++; - TRACE_SYMTAB("PT_LOAD[%ld]: acquired as rx\n", i); - } - else - if (phdr->p_offset >= di->fsm.rw_map_foff - && phdr->p_offset < di->fsm.rw_map_foff + di->fsm.rw_map_size - && phdr->p_offset + phdr->p_filesz - <= di->fsm.rw_map_foff + di->fsm.rw_map_size - && (phdr->p_flags & (PF_R | PF_W | PF_X)) == (PF_R | PF_W)) { - if (n_rw == N_RX_RW_AREAS) { - ML_(symerr)(di, True, - "N_RX_RW_AREAS is too low; " - "increase and recompile."); + if (!loaded) { + ML_(symerr)(di, False, + "ELF section outside all mapped regions"); goto out; } - rw[n_rw].svma_base = phdr->p_vaddr; - rw[n_rw].svma_limit = phdr->p_vaddr + phdr->p_memsz; - rw[n_rw].bias = di->fsm.rw_map_avma - di->fsm.rw_map_foff - + phdr->p_offset - phdr->p_vaddr; - n_rw++; - TRACE_SYMTAB("PT_LOAD[%ld]: acquired as rw\n", i); } } @@ -1564,7 +1578,6 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) + phdr->p_offset); Word stroff = -1; UChar* strtab = NULL; - Word j; for (j = 0; dyn_img[j].d_tag != DT_NULL; j++) { switch (dyn_img[j].d_tag) { case DT_SONAME: { @@ -1608,33 +1621,36 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) di->soname = ML_(dinfo_strdup)("di.redi.2", "NONE"); } - vg_assert(n_rx >= 0 && n_rx <= N_RX_RW_AREAS); - vg_assert(n_rw >= 0 && n_rw <= N_RX_RW_AREAS); - for (i = 0; i < n_rx; i++) { - vg_assert(rx[i].svma_limit != 0); - } - for (i = 0; i < n_rw; i++) { - vg_assert(rw[i].svma_limit != 0); - } + vg_assert(VG_(sizeXA)(svma_ranges) != 0); /* Now read the section table. */ TRACE_SYMTAB("\n"); TRACE_SYMTAB("------ Examining the section headers ------\n"); - TRACE_SYMTAB("rx: at %#lx are mapped foffsets %ld .. %ld\n", - di->fsm.rx_map_avma, - di->fsm.rx_map_foff, - di->fsm.rx_map_foff + di->fsm.rx_map_size - 1 ); - for (i = 0; i < n_rx; i++) { - TRACE_SYMTAB("rx[%ld]: contains svmas %#lx .. %#lx with bias %#lx\n", - i, rx[i].svma_base, rx[i].svma_limit - 1, rx[i].bias ); + for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { + struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); + if (map->rx) + TRACE_SYMTAB("rx: at %#lx are mapped foffsets %ld .. %ld\n", + map->avma, map->foff, map->foff + map->size - 1 ); } - TRACE_SYMTAB("rw: at %#lx are mapped foffsets %ld .. %ld\n", - di->fsm.rw_map_avma, - di->fsm.rw_map_foff, - di->fsm.rw_map_foff + di->fsm.rw_map_size - 1 ); - for (i = 0; i < n_rw; i++) { - TRACE_SYMTAB("rw[%ld]: contains svmas %#lx .. %#lx with bias %#lx\n", - i, rw[i].svma_base, rw[i].svma_limit - 1, rw[i].bias ); + TRACE_SYMTAB("rx: contains these svma regions:\n"); + for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) { + RangeAndBias* reg = VG_(indexXA)(svma_ranges, i); + if (reg->exec) + TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n", + reg->svma_base, reg->svma_limit - 1, reg->bias ); + } + for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { + struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); + if (map->rw) + TRACE_SYMTAB("rw: at %#lx are mapped foffsets %ld .. %ld\n", + map->avma, map->foff, map->foff + map->size - 1 ); + } + TRACE_SYMTAB("rw: contains these svma regions:\n"); + for (i = 0; i < VG_(sizeXA)(svma_ranges); i++) { + RangeAndBias* reg = VG_(indexXA)(svma_ranges, i); + if (!reg->exec) + TRACE_SYMTAB(" svmas %#lx .. %#lx with bias %#lx\n", + reg->svma_base, reg->svma_limit - 1, reg->bias ); } /* TOPLEVEL */ @@ -1653,19 +1669,17 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) leave the relevant pointer at NULL. */ RangeAndBias* inrx = NULL; RangeAndBias* inrw = NULL; - { Word j; - for (j = 0; j < n_rx; j++) { - if (svma >= rx[j].svma_base && svma < rx[j].svma_limit) { - inrx = &rx[j]; - break; - } - } - for (j = 0; j < n_rw; j++) { - if (svma >= rw[j].svma_base && svma < rw[j].svma_limit) { - inrw = &rw[j]; - break; - } - } + for (j = 0; j < VG_(sizeXA)(svma_ranges); j++) { + RangeAndBias* rng = VG_(indexXA)(svma_ranges, j); + if (svma >= rng->svma_base && svma < rng->svma_limit) { + if (!inrx && rng->exec) { + inrx = rng; + } else if (!inrw && !rng->exec) { + inrw = rng; + } + if (inrx && inrw) + break; + } } TRACE_SYMTAB(" [sec %2ld] %s %s al%2u foff %6ld .. %6ld " @@ -2268,10 +2282,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) UChar* shdr_strtab_dimg = NULL; /* SVMAs covered by rx and rw segments and corresponding bias. */ - /* Addr rx_dsvma_base = 0; */ /* UNUSED */ Addr rx_dsvma_limit = 0; PtrdiffT rx_dbias = 0; - /* Addr rw_dsvma_base = 0; */ /* UNUSED */ Addr rw_dsvma_limit = 0; PtrdiffT rw_dbias = 0; @@ -2324,28 +2336,24 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) = INDEX_BIS( (void*)(dimage + ehdr_dimg->e_phoff), i, phdr_ent_szB ); if (phdr->p_type == PT_LOAD) { - if (rx_dsvma_limit == 0 - && phdr->p_offset >= di->fsm.rx_map_foff - && phdr->p_offset - < di->fsm.rx_map_foff + di->fsm.rx_map_size - && phdr->p_offset + phdr->p_filesz - <= di->fsm.rx_map_foff + di->fsm.rx_map_size) { - /* rx_dsvma_base = phdr->p_vaddr; */ /* UNUSED */ - rx_dsvma_limit = phdr->p_vaddr + phdr->p_memsz; - rx_dbias = di->fsm.rx_map_avma - di->fsm.rx_map_foff - + phdr->p_offset - phdr->p_vaddr; - } - else - if (rw_dsvma_limit == 0 - && phdr->p_offset >= di->fsm.rw_map_foff - && phdr->p_offset - < di->fsm.rw_map_foff + di->fsm.rw_map_size - && phdr->p_offset + phdr->p_filesz - <= di->fsm.rw_map_foff + di->fsm.rw_map_size) { - /* rw_dsvma_base = phdr->p_vaddr; */ /* UNUSED */ - rw_dsvma_limit = phdr->p_vaddr + phdr->p_memsz; - rw_dbias = di->fsm.rw_map_avma - di->fsm.rw_map_foff - + phdr->p_offset - phdr->p_vaddr; + for (j = 0; j < VG_(sizeXA)(di->fsm.maps); j++) { + struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, j); + if ( phdr->p_offset >= map->foff + && phdr->p_offset < map->foff + map->size + && phdr->p_offset + phdr->p_filesz < map->foff + + map->size) { + if (map->rx && rx_dsvma_limit == 0) { + rx_dsvma_limit = phdr->p_vaddr + phdr->p_memsz; + rx_dbias = map->avma - map->foff + phdr->p_offset + - phdr->p_vaddr; + } + if (map->rw && rw_dsvma_limit == 0) { + rw_dsvma_limit = phdr->p_vaddr + phdr->p_memsz; + rw_dbias = map->avma - map->foff + phdr->p_offset + - phdr->p_vaddr; + } + break; + } } } } @@ -2562,7 +2570,6 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) exp-sgcheck.) */ if (0 && (VG_(needs).var_info || VG_(clo_read_var_info))) { UWord nVars = 0; - Word j; if (di->varinfo) { for (j = 0; j < VG_(sizeXA)(di->varinfo); j++) { OSet* /* of DiAddrRange */ scope @@ -2596,6 +2603,10 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di ) } m_res = VG_(am_munmap_valgrind) ( oimage, n_oimage ); vg_assert(!sr_isError(m_res)); + + if (svma_ranges) + VG_(deleteXA)(svma_ranges); + return res; } /* out: */ diff --git a/coregrind/m_debuginfo/readmacho.c b/coregrind/m_debuginfo/readmacho.c index e41b58d90b..91d06d832e 100644 --- a/coregrind/m_debuginfo/readmacho.c +++ b/coregrind/m_debuginfo/readmacho.c @@ -676,19 +676,35 @@ Bool ML_(read_macho_debug_info)( struct _DebugInfo* di ) ImageInfo ii; /* main file */ ImageInfo iid; /* auxiliary .dSYM file */ Bool ok; + Word i; + struct _DebugInfoMapping* rx_map = NULL; + struct _DebugInfoMapping* rw_map = NULL; /* mmap the object file to look for di->soname and di->text_bias and uuid and nlist and STABS */ - if (VG_(clo_verbosity) > 1) - VG_(message)(Vg_DebugMsg, - "%s (%#lx)\n", di->fsm.filename, di->fsm.rx_map_avma ); - /* This should be ensured by our caller (that we're in the accept state). */ vg_assert(di->fsm.have_rx_map); vg_assert(di->fsm.have_rw_map); + for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { + struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); + if (map->rx && !rx_map) + rx_map = map; + if (map->rw && !rw_map) + rw_map = map; + if (rx_map && rw_map) + break; + } + vg_assert(rx_map); + vg_assert(rw_map); + + if (VG_(clo_verbosity) > 1) + VG_(message)(Vg_DebugMsg, + "%s (rx at %#lx, rw at %#lx)\n", di->fsm.filename, + rx_map->avma, rw_map->avma ); + VG_(memset)(&ii, 0, sizeof(ii)); VG_(memset)(&iid, 0, sizeof(iid)); VG_(memset)(&uuid, 0, sizeof(uuid)); @@ -779,7 +795,7 @@ Bool ML_(read_macho_debug_info)( struct _DebugInfo* di ) && seg->fileoff == 0 && seg->filesize != 0) { di->text_present = True; di->text_svma = (Addr)seg->vmaddr; - di->text_avma = di->fsm.rx_map_avma; + di->text_avma = rx_map->avma; di->text_size = seg->vmsize; di->text_bias = di->text_avma - di->text_svma; /* Make the _debug_ values be the same as the @@ -796,7 +812,7 @@ Bool ML_(read_macho_debug_info)( struct _DebugInfo* di ) /* && DDD:seg->fileoff == 0 */ && seg->filesize != 0) { di->data_present = True; di->data_svma = (Addr)seg->vmaddr; - di->data_avma = di->fsm.rw_map_avma; + di->data_avma = rw_map->avma; di->data_size = seg->vmsize; di->data_bias = di->data_avma - di->data_svma; di->data_debug_svma = di->data_svma; @@ -829,7 +845,7 @@ Bool ML_(read_macho_debug_info)( struct _DebugInfo* di ) struct NLIST *syms; UChar *strs; XArray* /* DiSym */ candSyms = NULL; - Word i, nCandSyms; + Word nCandSyms; if (ii.macho_img_szB < symcmd->stroff + symcmd->strsize || ii.macho_img_szB < symcmd->symoff + symcmd->nsyms diff --git a/coregrind/m_debuginfo/readpdb.c b/coregrind/m_debuginfo/readpdb.c index e9fa7f5275..3461bcc796 100644 --- a/coregrind/m_debuginfo/readpdb.c +++ b/coregrind/m_debuginfo/readpdb.c @@ -86,8 +86,8 @@ doesn't make much sense. Here, we use text_bias as empirically producing the most ranges that fall inside the text segments for a multi-dll program. Of course, it could still be nonsense :-) */ -#define BIAS_FOR_SYMBOLS (di->fsm.rx_map_avma) -#define BIAS_FOR_LINETAB (di->fsm.rx_map_avma) +#define BIAS_FOR_SYMBOLS (di->text_avma) +#define BIAS_FOR_LINETAB (di->text_avma) #define BIAS_FOR_LINETAB2 (di->text_bias) #define BIAS_FOR_FPO (di->text_bias) /* Using di->text_bias for the FPOs causes 981 in range and 1 out of @@ -2259,8 +2259,6 @@ Bool ML_(read_pdb_debug_info)( + OFFSET_OF(IMAGE_NT_HEADERS, OptionalHeader) + ntheaders_avma->FileHeader.SizeOfOptionalHeader; - di->fsm.rx_map_avma = (Addr)obj_avma; - /* Iterate over PE(?) headers. Try to establish the text_bias, that's all we really care about. */ for ( i = 0; @@ -2283,6 +2281,12 @@ Bool ML_(read_pdb_debug_info)( VG_(message)(Vg_DebugMsg, " ::: mapped_avma is %#lx\n", mapped_avma); + struct _DebugInfoMapping map; + map.avma = mapped_avma; + map.size = pe_sechdr_avma->Misc.VirtualSize; + map.foff = pe_sechdr_avma->PointerToRawData; + map.ro = False; + if (pe_sechdr_avma->Characteristics & IMAGE_SCN_CNT_CODE) { /* Ignore uninitialised code sections - if you have incremental linking enabled in Visual Studio then you will @@ -2290,60 +2294,44 @@ Bool ML_(read_pdb_debug_info)( the real text section and valgrind will compute the wrong avma value and hence the wrong bias. */ if (!(pe_sechdr_avma->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)) { + map.rx = True; + map.rw = False; + VG_(addToXA)(di->fsm.maps, &map); di->fsm.have_rx_map = True; - if (di->fsm.rx_map_avma == 0) { - di->fsm.rx_map_avma = mapped_avma; - } - if (di->fsm.rx_map_size==0) { - di->fsm.rx_map_foff = pe_sechdr_avma->PointerToRawData; - } + di->text_present = True; - if (di->text_avma==0) { + if (di->text_avma == 0) { + di->text_svma = pe_sechdr_avma->VirtualAddress; di->text_avma = mapped_avma; + di->text_size = pe_sechdr_avma->Misc.VirtualSize; + } else { + di->text_size = mapped_end_avma - di->text_avma; } - di->text_size += pe_sechdr_avma->Misc.VirtualSize; - di->fsm.rx_map_size += pe_sechdr_avma->Misc.VirtualSize; } } else if (pe_sechdr_avma->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) { + map.rx = False; + map.rw = True; + VG_(addToXA)(di->fsm.maps, &map); di->fsm.have_rw_map = True; - if (di->fsm.rw_map_avma == 0) { - di->fsm.rw_map_avma = mapped_avma; - } - if (di->fsm.rw_map_size==0) { - di->fsm.rw_map_foff = pe_sechdr_avma->PointerToRawData; - } + di->data_present = True; - if (di->data_avma==0) { + if (di->data_avma == 0) { di->data_avma = mapped_avma; + di->data_size = pe_sechdr_avma->Misc.VirtualSize; + } else { + di->data_size = mapped_end_avma - di->data_avma; } - di->fsm.rw_map_size += pe_sechdr_avma->Misc.VirtualSize; - di->data_size += pe_sechdr_avma->Misc.VirtualSize; } else if (pe_sechdr_avma->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) { di->bss_present = True; - di->bss_avma = mapped_avma; - di->bss_size = pe_sechdr_avma->Misc.VirtualSize; - } - - mapped_avma = VG_PGROUNDDN(mapped_avma); - mapped_end_avma = VG_PGROUNDUP(mapped_end_avma); - - /* Urr. These tests are bogus; ->fsm.rx_map_avma is not necessarily - the start of the text section. */ - if ((1 /*VG_(needs).data_syms*/ - || (pe_sechdr_avma->Characteristics & IMAGE_SCN_CNT_CODE)) - && mapped_avma >= di->fsm.rx_map_avma - && mapped_avma <= (di->fsm.rx_map_avma+di->text_size) - && mapped_end_avma > (di->fsm.rx_map_avma+di->text_size)) { - UInt newsz = mapped_end_avma - di->fsm.rx_map_avma; - if (newsz > di->text_size) { - /* extending the mapping is always needed for PE files - under WINE */ - di->text_size = newsz; - di->fsm.rx_map_size = newsz; + if (di->bss_avma == 0) { + di->bss_avma = mapped_avma; + di->bss_size = pe_sechdr_avma->Misc.VirtualSize; + } else { + di->bss_size = mapped_end_avma - di->bss_avma; } } } @@ -2364,14 +2352,20 @@ Bool ML_(read_pdb_debug_info)( } if (VG_(clo_verbosity) > 1) { - VG_(message)(Vg_DebugMsg, - "rx_map: avma %#lx size %7lu foff %llu\n", - di->fsm.rx_map_avma, di->fsm.rx_map_size, - (Off64T)di->fsm.rx_map_foff); - VG_(message)(Vg_DebugMsg, - "rw_map: avma %#lx size %7lu foff %llu\n", - di->fsm.rw_map_avma, di->fsm.rw_map_size, - (Off64T)di->fsm.rw_map_foff); + for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { + struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); + if (map->rx) + VG_(message)(Vg_DebugMsg, + "rx_map: avma %#lx size %7lu foff %llu\n", + map->avma, map->size, (Off64T)map->foff); + } + for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) { + struct _DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i); + if (map->rw) + VG_(message)(Vg_DebugMsg, + "rw_map: avma %#lx size %7lu foff %llu\n", + map->avma, map->size, (Off64T)map->foff); + } VG_(message)(Vg_DebugMsg, " text: avma %#lx svma %#lx size %7lu bias %#lx\n", diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c index 6773c6acf3..a4223b56eb 100644 --- a/coregrind/m_debuginfo/storage.c +++ b/coregrind/m_debuginfo/storage.c @@ -385,8 +385,7 @@ void ML_(addLineInfo) ( struct _DebugInfo* di, See "Comment_Regarding_Text_Range_Checks" elsewhere in this file for background and rationale. */ vg_assert(di->fsm.have_rx_map && di->fsm.have_rw_map); - if (next-1 < di->fsm.rx_map_avma - || this >= di->fsm.rx_map_avma + di->fsm.rx_map_size ) { + if (ML_(find_rx_mapping)(di, this, next - 1) == NULL) { if (0) VG_(message)(Vg_DebugMsg, "warning: ignoring line info entry falling " @@ -436,6 +435,8 @@ void ML_(addDiCfSI) ( struct _DebugInfo* di, DiCfSI* cfsi_orig ) UInt new_sz, i; DiCfSI* new_tab; SSizeT delta; + struct _DebugInfoMapping* map; + struct _DebugInfoMapping* map2; /* copy the original, so we can mess with it */ DiCfSI cfsi = *cfsi_orig; @@ -456,27 +457,30 @@ void ML_(addDiCfSI) ( struct _DebugInfo* di, DiCfSI* cfsi_orig ) vg_assert(cfsi.len < 5000000); vg_assert(di->fsm.have_rx_map && di->fsm.have_rw_map); - /* If we have an empty r-x mapping (is that possible?) then the - DiCfSI can't possibly fall inside it. In which case skip. */ - if (di->fsm.rx_map_size == 0) - return; - - /* Rule out ones which are completely outside the r-x mapped area. + /* Find mapping where at least one end of the CFSI falls into. */ + map = ML_(find_rx_mapping)(di, cfsi.base, cfsi.base); + map2 = ML_(find_rx_mapping)(di, cfsi.base + cfsi.len - 1, + cfsi.base + cfsi.len - 1); + if (map == NULL) + map = map2; + else if (map2 == NULL) + map2 = map; + + /* Rule out ones which are completely outside the r-x mapped area + (or which span across different areas). See "Comment_Regarding_Text_Range_Checks" elsewhere in this file for background and rationale. */ - if (cfsi.base + cfsi.len - 1 < di->fsm.rx_map_avma - || cfsi.base >= di->fsm.rx_map_avma + di->fsm.rx_map_size) { + if (map == NULL || map != map2) { static Int complaints = 10; if (VG_(clo_trace_cfi) || complaints > 0) { complaints--; if (VG_(clo_verbosity) > 1) { VG_(message)( Vg_DebugMsg, - "warning: DiCfSI %#lx .. %#lx outside segment %#lx .. %#lx\n", + "warning: DiCfSI %#lx .. %#lx outside mapped rw segments (%s)\n", cfsi.base, cfsi.base + cfsi.len - 1, - di->text_avma, - di->text_avma + di->text_size - 1 + di->soname ); } if (VG_(clo_trace_cfi)) @@ -493,27 +497,27 @@ void ML_(addDiCfSI) ( struct _DebugInfo* di, DiCfSI* cfsi_orig ) will fail. See "Comment_on_IMPORTANT_CFSI_REPRESENTATIONAL_INVARIANTS" in priv_storage.h for background. */ - if (cfsi.base < di->fsm.rx_map_avma) { + if (cfsi.base < map->avma) { /* Lower end is outside the mapped area. Hence upper end must be inside it. */ if (0) VG_(printf)("XXX truncate lower\n"); - vg_assert(cfsi.base + cfsi.len - 1 >= di->fsm.rx_map_avma); - delta = (SSizeT)(di->fsm.rx_map_avma - cfsi.base); + vg_assert(cfsi.base + cfsi.len - 1 >= map->avma); + delta = (SSizeT)(map->avma - cfsi.base); vg_assert(delta > 0); vg_assert(delta < (SSizeT)cfsi.len); cfsi.base += delta; cfsi.len -= delta; } else - if (cfsi.base + cfsi.len - 1 > di->fsm.rx_map_avma - + di->fsm.rx_map_size - 1) { + if (cfsi.base + cfsi.len - 1 > map->avma + map->size - 1) { /* Upper end is outside the mapped area. Hence lower end must be inside it. */ if (0) VG_(printf)("XXX truncate upper\n"); - vg_assert(cfsi.base <= di->fsm.rx_map_avma + di->fsm.rx_map_size - 1); + vg_assert(cfsi.base <= map->avma + map->size - 1); delta = (SSizeT)( (cfsi.base + cfsi.len - 1) - - (di->fsm.rx_map_avma + di->fsm.rx_map_size - 1) ); - vg_assert(delta > 0); vg_assert(delta < (SSizeT)cfsi.len); + - (map->avma + map->size - 1) ); + vg_assert(delta > 0); + vg_assert(delta < (SSizeT)cfsi.len); cfsi.len -= delta; } @@ -526,9 +530,9 @@ void ML_(addDiCfSI) ( struct _DebugInfo* di, DiCfSI* cfsi_orig ) vg_assert(cfsi.len > 0); /* Similar logic applies for the next two assertions. */ - vg_assert(cfsi.base >= di->fsm.rx_map_avma); + vg_assert(cfsi.base >= map->avma); vg_assert(cfsi.base + cfsi.len - 1 - <= di->fsm.rx_map_avma + di->fsm.rx_map_size - 1); + <= map->avma + map->size - 1); if (di->cfsi_used == di->cfsi_size) { new_sz = 2 * di->cfsi_size; @@ -918,16 +922,12 @@ void ML_(addVar)( struct _DebugInfo* di, and it is re-checked at the start of ML_(read_elf_debug_info). */ vg_assert(di->fsm.have_rx_map && di->fsm.have_rw_map); - if (level > 0 - && (aMax < di->fsm.rx_map_avma - || aMin >= di->fsm.rx_map_avma + di->fsm.rx_map_size)) { + if (level > 0 && ML_(find_rx_mapping)(di, aMin, aMax) == NULL) { if (VG_(clo_verbosity) >= 0) { VG_(message)(Vg_DebugMsg, "warning: addVar: in range %#lx .. %#lx outside " - "segment %#lx .. %#lx (%s)\n", - aMin, aMax, - di->text_avma, di->text_avma + di->text_size -1, - name + "all rx mapped areas (%s)\n", + aMin, aMax, name ); } return; @@ -1858,7 +1858,7 @@ Word ML_(search_one_cfitab) ( struct _DebugInfo* di, Addr ptr ) Word ML_(search_one_fpotab) ( struct _DebugInfo* di, Addr ptr ) { - Addr const addr = ptr - di->fsm.rx_map_avma; + Addr const addr = ptr - di->text_avma; Addr a_mid_lo, a_mid_hi; Word mid, size, lo = 0,