// addresses. The vector is dynamically allocated and should be freed
// by the caller when done. REQUIRES m_mallocfree to be running.
// Writes the number of addresses required into *n_acquired.
-Addr* VG_(get_segment_starts) ( /*OUT*/Int* n_acquired )
+// Only those segments are considered whose kind matches any of the kinds
+// given in KIND_MASK.
+Addr* VG_(get_segment_starts) ( UInt kind_mask, /*OUT*/Int* n_acquired )
{
Addr* starts;
Int n_starts, r = 0;
n_starts = 1;
while (True) {
starts = VG_(malloc)( "main.gss.1", n_starts * sizeof(Addr) );
- r = VG_(am_get_segment_starts)( starts, n_starts );
+ r = VG_(am_get_segment_starts)( kind_mask, starts, n_starts );
if (r >= 0)
break;
VG_(free)(starts);
return (i < 0) ? NULL : segnames + i;
}
-/* Collect up the start addresses of all non-free, non-resvn segments.
+/* Collect up the start addresses of segments whose kind matches one of
+ the kinds specified in kind_mask.
The interface is a bit strange in order to avoid potential
segment-creation races caused by dynamic allocation of the result
buffer *starts.
Correct use of this function may mean calling it multiple times in
order to establish a suitably-sized buffer. */
-Int VG_(am_get_segment_starts)( Addr* starts, Int nStarts )
+Int VG_(am_get_segment_starts)( UInt kind_mask, Addr* starts, Int nStarts )
{
Int i, j, nSegs;
nSegs = 0;
for (i = 0; i < nsegments_used; i++) {
- if (nsegments[i].kind == SkFree || nsegments[i].kind == SkResvn)
- continue;
- nSegs++;
+ if ((nsegments[i].kind & kind_mask) != 0)
+ nSegs++;
}
if (nSegs > nStarts) {
j = 0;
for (i = 0; i < nsegments_used; i++) {
- if (nsegments[i].kind == SkFree || nsegments[i].kind == SkResvn)
- continue;
- starts[j] = nsegments[i].start;
- j++;
+ if ((nsegments[i].kind & kind_mask) != 0)
+ starts[j++] = nsegments[i].start;
}
aspacem_assert(j == nSegs); /* this should not fail */
return; /* can't create file */
}
- /* Get the segments */
- seg_starts = VG_(get_segment_starts)(&n_seg_starts);
+ /* Get the client segments */
+ seg_starts = VG_(get_segment_starts)(SkFileC | SkAnonC | SkShmC,
+ &n_seg_starts);
/* First, count how many memory segments to dump */
num_phdrs = 1; /* start with notes */
Int n_seg_starts;
Addr_n_ULong anu;
- seg_starts = VG_(get_segment_starts)( &n_seg_starts );
+ seg_starts = VG_(get_segment_starts)( SkFileC | SkFileV, &n_seg_starts );
vg_assert(seg_starts && n_seg_starts >= 0);
/* show them all to the debug info reader. allow_SkFileV has to
# elif defined(VGO_darwin)
{ Addr* seg_starts;
Int n_seg_starts;
- seg_starts = VG_(get_segment_starts)( &n_seg_starts );
+ seg_starts = VG_(get_segment_starts)( SkFileC, &n_seg_starts );
vg_assert(seg_starts && n_seg_starts >= 0);
/* show them all to the debug info reader.
vg_assert(VG_(running_tid) == VG_INVALID_THREADID);
VG_(running_tid) = tid_main;
- seg_starts = VG_(get_segment_starts)( &n_seg_starts );
+ seg_starts = VG_(get_segment_starts)( SkFileC | SkAnonC | SkShmC,
+ &n_seg_starts );
vg_assert(seg_starts && n_seg_starts >= 0);
- /* show interesting ones to the tool */
+ /* Show client segments to the tool */
for (i = 0; i < n_seg_starts; i++) {
Word j, n;
NSegment const* seg
= VG_(am_find_nsegment)( seg_starts[i] );
vg_assert(seg);
- if (seg->kind == SkFileC || seg->kind == SkAnonC) {
- /* This next assertion is tricky. If it is placed
- immediately before this 'if', it very occasionally fails.
- Why? Because previous iterations of the loop may have
- caused tools (via the new_mem_startup calls) to do
- dynamic memory allocation, and that may affect the mapped
- segments; in particular it may cause segment merging to
- happen. Hence we cannot assume that seg_starts[i], which
- reflects the state of the world before we started this
- loop, is the same as seg->start, as the latter reflects
- the state of the world (viz, mappings) at this particular
- iteration of the loop.
-
- Why does moving it inside the 'if' make it safe? Because
- any dynamic memory allocation done by the tools will
- affect only the state of Valgrind-owned segments, not of
- Client-owned segments. And the 'if' guards against that
- -- we only get in here for Client-owned segments.
-
- In other words: the loop may change the state of
- Valgrind-owned segments as it proceeds. But it should
- not cause the Client-owned segments to change. */
- vg_assert(seg->start == seg_starts[i]);
+ vg_assert(seg->kind == SkFileC || seg->kind == SkAnonC ||
+ seg->kind == SkShmC);
+ vg_assert(seg->start == seg_starts[i]);
+ {
VG_(debugLog)(2, "main",
"tell tool about %010lx-%010lx %c%c%c\n",
seg->start, seg->end,
// addresses. The vector is dynamically allocated and should be freed
// by the caller when done. REQUIRES m_mallocfree to be running.
// Writes the number of addresses required into *n_acquired.
-extern Addr* VG_(get_segment_starts) ( /*OUT*/Int* n_acquired );
+// Only those segments are considered whose kind matches any of the kinds
+// given in KIND_MASK.
+extern Addr* VG_(get_segment_starts)( UInt kind_mask, /*OUT*/Int* n_acquired );
#endif // __PUB_TOOL_ASPACEHL_H
//--------------------------------------------------------------
// Definition of address-space segments
-/* Describes segment kinds. */
+/* Describes segment kinds. Enumerators are one-hot encoded so they
+ can be or'ed together. */
typedef
enum {
- SkFree, // unmapped space
- SkAnonC, // anonymous mapping belonging to the client
- 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
+ SkFree = 0x01, // unmapped space
+ SkAnonC = 0x02, // anonymous mapping belonging to the client
+ SkAnonV = 0x04, // anonymous mapping belonging to valgrind
+ SkFileC = 0x08, // file mapping belonging to the client
+ SkFileV = 0x10, // file mapping belonging to valgrind
+ SkShmC = 0x20, // shared memory segment belonging to the client
+ SkResvn = 0x40 // reservation
}
SegKind;
NSegment;
-/* Collect up the start addresses of all non-free, non-resvn segments.
+/* Collect up the start addresses of segments whose kind matches one of
+ the kinds specified in kind_mask.
The interface is a bit strange in order to avoid potential
segment-creation races caused by dynamic allocation of the result
buffer *starts.
Correct use of this function may mean calling it multiple times in
order to establish a suitably-sized buffer. */
-extern Int VG_(am_get_segment_starts)( Addr* starts, Int nStarts );
+extern Int VG_(am_get_segment_starts)( UInt kind_mask, Addr* starts,
+ Int nStarts );
/* Finds the segment containing 'a'. Only returns file/anon/resvn
segments. This returns a 'NSegment const *' - a pointer to
{
Int i;
Int n_seg_starts;
- Addr* seg_starts = VG_(get_segment_starts)( &n_seg_starts );
+ Addr* seg_starts = VG_(get_segment_starts)( SkFileC | SkAnonC | SkShmC,
+ &n_seg_starts );
tl_assert(seg_starts && n_seg_starts > 0);
SizeT seg_size;
NSegment const* seg = VG_(am_find_nsegment)( seg_starts[i] );
tl_assert(seg);
+ tl_assert(seg->kind == SkFileC || seg->kind == SkAnonC ||
+ seg->kind == SkShmC);
- if (seg->kind != SkFileC && seg->kind != SkAnonC) continue;
if (!(seg->hasR && seg->hasW)) continue;
if (seg->isCH) continue;