From 65bd3eb36781a68caae52fde23419e3f5eb2a84f Mon Sep 17 00:00:00 2001 From: Tom Hughes Date: Tue, 4 Oct 2005 15:59:54 +0000 Subject: [PATCH] Create a new SkShmC segment type for shared memory segments so that we can ensure they are never merged with adjacent segments. This makes sure that we can find the right piece of memory to release when the shmdt system call occurs. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4854 --- coregrind/m_aspacemgr/aspacemgr.c | 48 ++++++++++++++++++++++++--- coregrind/m_syswrap/syswrap-generic.c | 9 +++-- coregrind/pub_core_aspacemgr.h | 6 ++++ include/pub_tool_aspacemgr.h | 7 ++++ 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/coregrind/m_aspacemgr/aspacemgr.c b/coregrind/m_aspacemgr/aspacemgr.c index a95d73f0b9..611fd1e4b6 100644 --- a/coregrind/m_aspacemgr/aspacemgr.c +++ b/coregrind/m_aspacemgr/aspacemgr.c @@ -441,6 +441,7 @@ static HChar* show_SegKind ( SegKind sk ) case SkAnonV: return "ANON"; case SkFileC: return "file"; case SkFileV: return "FILE"; + case SkShmC: return "shm "; case SkResvn: return "RSVN"; default: return "????"; } @@ -523,7 +524,7 @@ static void show_nsegment ( Int logLevel, Int segNo, NSegment* seg ) ); break; - case SkAnonC: case SkAnonV: + case SkAnonC: case SkAnonV: case SkShmC: VG_(debugLog)( logLevel, "aspacem", "%3d: %s %010llx-%010llx %s %c%c%c%c%c\n", @@ -688,7 +689,7 @@ static Bool sane_NSegment ( NSegment* s ) && !s->hasR && !s->hasW && !s->hasX && !s->hasT && !s->isCH; - case SkAnonC: case SkAnonV: + case SkAnonC: case SkAnonV: case SkShmC: return s->smode == SmFixed && s->dev == 0 && s->ino == 0 && s->offset == 0 && s->fnIdx == -1 @@ -754,6 +755,9 @@ static Bool maybe_merge_nsegments ( NSegment* s1, NSegment* s2 ) } break; + case SkShmC: + return False; + default: break; @@ -890,7 +894,8 @@ static void sync_check_mapping_callback ( Addr addr, SizeT len, UInt prot, same = nsegments[i].kind == SkAnonC || nsegments[i].kind == SkAnonV || nsegments[i].kind == SkFileC - || nsegments[i].kind == SkFileV; + || nsegments[i].kind == SkFileV + || nsegments[i].kind == SkShmC; seg_prot = 0; if (nsegments[i].hasR) seg_prot |= VKI_PROT_READ; @@ -1106,7 +1111,7 @@ NSegment* VG_(am_next_nsegment) ( NSegment* here, Bool fwds ) return NULL; } switch (nsegments[i].kind) { - case SkFileC: case SkFileV: + case SkFileC: case SkFileV: case SkShmC: case SkAnonC: case SkAnonV: case SkResvn: return &nsegments[i]; default: @@ -1169,6 +1174,7 @@ Bool is_valid_for_client( Addr start, SizeT len, UInt prot, Bool freeOk ) for (i = iLo; i <= iHi; i++) { if ( (nsegments[i].kind == SkFileC || nsegments[i].kind == SkAnonC + || nsegments[i].kind == SkShmC || (nsegments[i].kind == SkFree && freeOk) || (nsegments[i].kind == SkResvn && freeOk)) && (needR ? nsegments[i].hasR : True) @@ -1638,6 +1644,7 @@ Addr VG_(am_get_advisory) ( MapRequest* req, if (nsegments[i].kind == SkFree || nsegments[i].kind == SkFileC || nsegments[i].kind == SkAnonC + || nsegments[i].kind == SkShmC || nsegments[i].kind == SkResvn) { /* ok */ } else { @@ -1830,6 +1837,37 @@ VG_(am_notify_client_mmap)( Addr a, SizeT len, UInt prot, UInt flags, return needDiscard; } +/* Notifies aspacem that the client completed a shmat successfully. + The segment array is updated accordingly. If the returned Bool is + True, the caller should immediately discard translations from the + specified address range. */ + +Bool +VG_(am_notify_client_shmat)( Addr a, SizeT len, UInt prot ) +{ + NSegment seg; + Bool needDiscard; + + aspacem_assert(len > 0); + aspacem_assert(VG_IS_PAGE_ALIGNED(a)); + aspacem_assert(VG_IS_PAGE_ALIGNED(len)); + + /* Discard is needed if any of the just-trashed range had T. */ + needDiscard = any_Ts_in_range( a, len ); + + init_nsegment( &seg ); + seg.kind = SkShmC; + seg.start = a; + seg.end = a + len - 1; + seg.offset = 0; + seg.hasR = toBool(prot & VKI_PROT_READ); + seg.hasW = toBool(prot & VKI_PROT_WRITE); + seg.hasX = toBool(prot & VKI_PROT_EXEC); + add_segment( &seg ); + AM_SANITY_CHECK; + return needDiscard; +} + /* Notifies aspacem that an mprotect was completed successfully. The segment array is updated accordingly. Note, as with VG_(am_notify_munmap), it is not the job of this function to reject @@ -1866,7 +1904,7 @@ Bool VG_(am_notify_mprotect)( Addr start, SizeT len, UInt prot ) for (i = iLo; i <= iHi; i++) { /* Apply the permissions to all relevant segments. */ switch (nsegments[i].kind) { - case SkAnonC: case SkAnonV: case SkFileC: case SkFileV: + case SkAnonC: case SkAnonV: case SkFileC: case SkFileV: case SkShmC: nsegments[i].hasR = newR; nsegments[i].hasW = newW; nsegments[i].hasX = newX; diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c index 1d03b0c444..4d467fccb6 100644 --- a/coregrind/m_syswrap/syswrap-generic.c +++ b/coregrind/m_syswrap/syswrap-generic.c @@ -1600,8 +1600,7 @@ ML_(generic_POST_sys_shmat) ( ThreadId tid, cope with the discrepancy, aspacem's sync checker omits the dev/ino correspondence check in cases where V does not know the dev/ino. */ - d = VG_(am_notify_client_mmap)( res, VG_PGROUNDUP(segmentSize), - prot, VKI_MAP_ANONYMOUS, 0,0); + d = VG_(am_notify_client_shmat)( res, VG_PGROUNDUP(segmentSize), prot ); /* we don't distinguish whether it's read-only or * read-write -- it doesn't matter really. */ @@ -1630,7 +1629,11 @@ ML_(generic_POST_sys_shmdt) ( ThreadId tid, UWord res, UWord arg0 ) if (s != NULL) { Addr s_start = s->start; SizeT s_len = s->end+1 - s->start; - Bool d = VG_(am_notify_munmap)(s_start, s_len); + Bool d; + + vg_assert(s->kind == SkShmC && s->start == arg0); + + d = VG_(am_notify_munmap)(s_start, s_len); s = NULL; /* s is now invalid */ VG_TRACK( die_mem_munmap, s_start, s_len ); if (d) diff --git a/coregrind/pub_core_aspacemgr.h b/coregrind/pub_core_aspacemgr.h index 6bf343ec41..88b9127bd6 100644 --- a/coregrind/pub_core_aspacemgr.h +++ b/coregrind/pub_core_aspacemgr.h @@ -155,6 +155,12 @@ extern Addr VG_(am_get_advisory_client_simple) extern Bool VG_(am_notify_client_mmap) ( Addr a, SizeT len, UInt prot, UInt flags, Int fd, Off64T offset ); +/* Notifies aspacem that the client completed a shmat successfully. + The segment array is updated accordingly. If the returned Bool is + True, the caller should immediately discard translations from the + specified address range. */ +extern Bool VG_(am_notify_client_shmat)( Addr a, SizeT len, UInt prot ); + /* Notifies aspacem that an mprotect was completed successfully. The segment array is updated accordingly. Note, as with VG_(am_notify_munmap), it is not the job of this function to reject diff --git a/include/pub_tool_aspacemgr.h b/include/pub_tool_aspacemgr.h index 51240bb3d7..160a5aa1d3 100644 --- a/include/pub_tool_aspacemgr.h +++ b/include/pub_tool_aspacemgr.h @@ -43,6 +43,7 @@ typedef SkAnonV, // anonymous mapping belonging to valgrind SkFileC, // file mapping belonging to the client SkFileV, // file mapping belonging to valgrind + SkShmC, // shared memory segment belonging to the client SkResvn // reservation } SegKind; @@ -73,6 +74,12 @@ typedef // there is an associated file // segment may have permissions + kind == SkShmC: + // smode==SmFixed + // there's no associated file: + dev==ino==foff = 0, fnidx == -1 + // segment may have permissions + kind == SkResvn // the segment may be resized if required // there's no associated file: -- 2.47.3