|
From: Jeremy F. <je...@go...> - 2005-01-15 02:08:25
|
CVS commit by fitzhardinge:
A couple of cleanups to vg_procselfmaps and its users:
- VG_(parse_procselfmaps) now reads the file for itself, rather than relying on
the caller to call VG_(read_procselfmaps) first. VG_(read_procselfmaps) is no
longer publically visible.
- read_procselfmaps uses a dynamic buffer, to cope with any sized /proc/self/maps.
Modern programs with many mappings can make this file very large.
M +8 -13 core.h 1.63
M +16 -30 vg_main.c 1.235
M +27 -20 vg_memory.c 1.84
M +59 -45 vg_procselfmaps.c 1.18
--- valgrind/coregrind/core.h #1.62:1.63
@@ -114,7 +114,4 @@ typedef struct _ThreadState ThreadState;
#define M_VG_MSGBUF 10000
-/* Size of a big enough table used to read /proc/self/map entries. */
-#define M_PROCMAP_BUF 200000
-
/* Max length of pathname to a .so/executable file. */
#define M_VG_LIBNAMESTR 100
@@ -1074,14 +1071,8 @@ extern UInt VG_(get_n_errs_found) (
------------------------------------------------------------------ */
-/* Reads /proc/self/maps into a static buffer which can be parsed by
- VG_(parse_procselfmaps)(). */
-extern void VG_(read_procselfmaps) ( void );
-
-/* Parses /proc/self/maps, calling `record_mapping' for each entry. If
- `read_from_file' is True, /proc/self/maps is read directly, otherwise
- it's read from the buffer filled by VG_(read_procselfmaps_contents)(). */
+/* Parses /proc/self/maps, calling `record_mapping' for each entry. */
extern
void VG_(parse_procselfmaps) (
- void (*record_mapping)( Addr addr, SizeT len, Char rr, Char ww, Char xx,
+ void (*record_mapping)( Addr addr, SizeT len, UInt prot,
UInt dev, UInt ino, ULong foff,
const UChar *filename ) );
@@ -1184,6 +1175,4 @@ extern void VG_(align_BaB)( UInt );
extern Int VG_(alloc_BaB_1_set)( Addr ); // Allocate & init baseBlock slot
-extern Bool VG_(sanity_check_memory)(void);
-
/* ---------------------------------------------------------------------
Exports of vg_memory.c
@@ -1255,4 +1244,10 @@ extern REGPARM(1)
void VG_(unknown_SP_update) ( Addr new_SP );
+/* Check vg_memory structures for sanity */
+extern Bool VG_(sanity_check_memory)(void);
+
+/* Return string for prot */
+extern const Char *VG_(prot_str)(UInt prot);
+
/* ---------------------------------------------------------------------
Exports of vg_syscalls.c
--- valgrind/coregrind/vg_main.c #1.234:1.235
@@ -2310,11 +2310,8 @@ Int VG_(helper_offset)(Addr a)
/*====================================================================*/
-static void build_valgrind_map_callback
- ( Addr start, SizeT size, Char rr, Char ww, Char xx,
- UInt dev, UInt ino, ULong foffset, const UChar* filename )
+static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
+ UInt dev, UInt ino, ULong foffset,
+ const UChar* filename )
{
- UInt prot = 0;
- UInt flags = SF_MMAP|SF_NOSYMS;
-
/* Only record valgrind mappings for now, without loading any
symbols. This is so we know where the free space is before we
@@ -2322,9 +2319,10 @@ static void build_valgrind_map_callback
which is the problem here). */
if (start >= VG_(client_end) && (start+size-1) <= VG_(valgrind_last)) {
- flags |= SF_VALGRIND;
- if (rr == 'r') prot |= VKI_PROT_READ;
- if (ww == 'w') prot |= VKI_PROT_WRITE;
- if (xx == 'x') prot |= VKI_PROT_EXEC;
- VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
+ if (0)
+ VG_(printf)("init1: %p-%p prot %s\n",
+ start, start+size, VG_(prot_str)(prot));
+ VG_(map_file_segment)(start, size, prot,
+ SF_MMAP|SF_NOSYMS|SF_VALGRIND,
+ dev, ino, foffset, filename);
}
}
@@ -2343,9 +2341,8 @@ Addr sp_at_startup___global_arg = 0;
will load their symtabs)>
*/
-static void build_segment_map_callback
- ( Addr start, SizeT size, Char rr, Char ww, Char xx,
- UInt dev, UInt ino, ULong foffset, const UChar* filename )
+static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
+ UInt dev, UInt ino, ULong foffset,
+ const UChar* filename )
{
- UInt prot = 0;
UInt flags;
Bool is_stack_segment;
@@ -2356,10 +2353,6 @@ static void build_segment_map_callback
if (0)
- VG_(printf)("init: %p-%p prot %c%c%c stack=%d\n",
- start, start+size, rr, ww, xx, is_stack_segment);
-
- if (rr == 'r') prot |= VKI_PROT_READ;
- if (ww == 'w') prot |= VKI_PROT_WRITE;
- if (xx == 'x') prot |= VKI_PROT_EXEC;
+ VG_(printf)("init2: %p-%p prot %s stack=%d\n",
+ start, start+size, VG_(prot_str)(prot), is_stack_segment);
if (is_stack_segment)
@@ -2394,5 +2387,6 @@ static void build_segment_map_callback
if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
- VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
+ VG_TRACK( new_mem_startup, start, size,
+ !!(prot & VKI_PROT_READ), !!(prot & VKI_PROT_WRITE), !!(prot & VKI_PROT_EXEC));
/* If this is the stack segment mark all below %esp as noaccess. */
@@ -2684,12 +2678,5 @@ int main(int argc, char **argv, char **e
//--------------------------------------------------------------
- // Read /proc/self/maps into a buffer
- // p: all memory layout, environment setup [so memory maps are right]
- //--------------------------------------------------------------
- VG_(read_procselfmaps)();
-
- //--------------------------------------------------------------
// Build segment map (Valgrind segments only)
- // p: read proc/self/maps
// p: sk_pre_clo_init() [to setup new_mem_startup tracker]
//--------------------------------------------------------------
@@ -2728,5 +2715,4 @@ int main(int argc, char **argv, char **e
//--------------------------------------------------------------
sp_at_startup___global_arg = sp_at_startup;
- VG_(read_procselfmaps)();
VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
sp_at_startup___global_arg = 0;
--- valgrind/coregrind/vg_memory.c #1.83:1.84
@@ -909,9 +909,29 @@ void *VG_(shadow_alloc)(UInt size)
/*--------------------------------------------------------------------*/
+const Char *VG_(prot_str)(UInt prot)
+{
+ static const Char *str[] = {
+ "---",
+ "r--",
+ "-w-",
+ "rw-",
+ "--x",
+ "r-x",
+ "-wx",
+ "rwx",
+ };
+
+ vg_assert(VKI_PROT_READ == 1);
+ vg_assert(VKI_PROT_WRITE == 2);
+ vg_assert(VKI_PROT_EXEC == 4);
+
+ return str[prot & 7];
+}
+
static Segment *next_segment;
static Bool segment_maps_ok;
static Addr prevmapstart, prevmapend;
-static void check_segment_maps(Addr addr, SizeT len, Char rr, Char ww, Char xx,
+static void check_segment_maps(Addr addr, SizeT len, UInt prot,
UInt dev, UInt ino, ULong foff, const UChar *filename)
{
@@ -919,5 +939,4 @@ static void check_segment_maps(Addr addr
Addr end = addr+len;
Segment *seg, *next, *prev;
- UInt prot;
if (addr >= VG_(valgrind_last))
@@ -932,9 +951,4 @@ static void check_segment_maps(Addr addr
prevmapend = end;
- prot = 0;
- prot |= rr == 'r' ? VKI_PROT_READ : 0;
- prot |= ww == 'w' ? VKI_PROT_WRITE: 0;
- prot |= xx == 'x' ? VKI_PROT_EXEC : 0;
-
if (next_segment == NULL)
seg = VG_(first_segment)();
@@ -989,11 +1003,9 @@ static void check_segment_maps(Addr addr
if (0)
- VG_(printf)("seg: %p-%p (%c%c%c) %4x mapping %p-%p %x (%c%c%c) %s%s %s\n",
+ VG_(printf)("seg: %p-%p (%s) %4x mapping %p-%p %s %s%s %s\n",
seg->addr, segend,
- seg->prot & VKI_PROT_READ ? 'r' : '-',
- seg->prot & VKI_PROT_WRITE? 'w' : '-',
- seg->prot & VKI_PROT_EXEC ? 'x' : '-',
+ VG_(prot_str)(seg->prot),
seg->flags,
- addr, end, prot, rr, ww, xx,
+ addr, end, VG_(prot_str)(prot),
(addr == seg->addr && segend == end) ? "" : " !!!",
(seg->prot & prot) != seg->prot ? " ???" : "",
@@ -1010,11 +1022,9 @@ static void check_segment_maps(Addr addr
if ((seg->prot & prot) != seg->prot) {
- VG_(printf)("INV 4 FAILED: seg %p-%p permissions %c%c%c not subset of mapping %p-%p permissions %c%c%c\n",
+ VG_(printf)("INV 4 FAILED: seg %p-%p permissions %s not subset of mapping %p-%p permissions %s\n",
seg->addr, segend,
- seg->prot & VKI_PROT_READ ? 'r' : '-',
- seg->prot & VKI_PROT_WRITE? 'w' : '-',
- seg->prot & VKI_PROT_EXEC ? 'x' : '-',
+ VG_(prot_str)(seg->prot),
addr, end,
- rr, ww, xx);
+ VG_(prot_str)(prot));
segment_maps_ok = False;
}
@@ -1104,7 +1114,4 @@ Bool VG_(sanity_check_memory)(void)
}
- /* Now compare with /proc/self/maps */
- VG_(read_procselfmaps)();
-
next_segment = NULL;
segment_maps_ok = True;
--- valgrind/coregrind/vg_procselfmaps.c #1.17:1.18
@@ -33,12 +33,4 @@
#include "core.h"
-
-/* static ... to keep it out of the stack frame. */
-static Char procmap_buf[M_PROCMAP_BUF];
-
-/* Records length of /proc/self/maps read into procmap_buf. */
-static Int buf_n_tot;
-
-
/* Helper fns. */
@@ -57,5 +49,5 @@ static Int decdigit ( Char c )
}
-static Int readchar ( Char* buf, Char* ch )
+static Int readchar ( const Char* buf, Char* ch )
{
if (*buf == 0) return 0;
@@ -64,5 +56,5 @@ static Int readchar ( Char* buf, Char* c
}
-static Int readhex ( Char* buf, UWord* val )
+static Int readhex ( const Char* buf, UWord* val )
{
Int n = 0;
@@ -75,5 +67,5 @@ static Int readhex ( Char* buf, UWord* v
}
-static Int readdec ( Char* buf, UInt* val )
+static Int readdec ( const Char* buf, UInt* val )
{
Int n = 0;
@@ -87,8 +79,13 @@ static Int readdec ( Char* buf, UInt* va
-/* Read /proc/self/maps, store the contents in a static buffer. If there's
- a syntax error or other failure, just abort. */
-void VG_(read_procselfmaps)(void)
+/* Read /proc/self/maps, store the contents in a buffer. If there's a
+ syntax error or other failure, just abort. The buffer size is
+ increased dynamically to fit whatever sized contents we need to
+ read. It can get pretty big in some programs. */
+static const Char *read_procselfmaps(Int *maps_size)
{
+ static Char *buffer;
+ static Int bufsize = 1024;
+ Int bufused = 0;
Int n_chunk, fd;
@@ -99,22 +96,34 @@ void VG_(read_procselfmaps)(void)
VG_(exit)(1);
}
- buf_n_tot = 0;
+
+ bufused = 0;
+ if (buffer == NULL)
+ buffer = VG_(arena_malloc)(VG_AR_CORE, bufsize);
+
do {
- Int want = M_PROCMAP_BUF - buf_n_tot;
- n_chunk = VG_(read) ( fd, &procmap_buf[buf_n_tot],
- want > 4000 ? 4000 : want );
- buf_n_tot += n_chunk;
- } while ( n_chunk > 0 && buf_n_tot < M_PROCMAP_BUF );
- VG_(close)(fd);
- if (buf_n_tot >= M_PROCMAP_BUF-5) {
- VG_(message)(Vg_UserMsg, "FATAL: M_PROCMAP_BUF is too small; "
- "increase it and recompile");
- VG_(exit)(1);
+ Int want = bufsize - bufused;
+ n_chunk = VG_(read) ( fd, &buffer[bufused], want );
+
+ if (n_chunk < 0) {
+ VG_(message)(Vg_UserMsg, "FATAL: read error on /proc/self/maps");
+ VG_(exit)(99);
}
- if (buf_n_tot == 0) {
+
+ bufused += n_chunk;
+
+ if (bufused == bufsize) {
+ bufsize *= 2;
+ buffer = VG_(arena_realloc)(VG_AR_CORE, buffer, VG_MIN_MALLOC_SZB, bufsize);
+ }
+ } while ( n_chunk > 0 );
+ VG_(close)(fd);
+ if (bufused == 0) {
VG_(message)(Vg_UserMsg, "FATAL: I/O error on /proc/self/maps" );
VG_(exit)(1);
}
- procmap_buf[buf_n_tot] = 0;
+ buffer[bufused] = '\0';
+
+ *maps_size = bufused;
+ return buffer;
}
@@ -124,7 +133,6 @@ void VG_(read_procselfmaps)(void)
start address in memory
length
- r permissions char; either - or r
- w permissions char; either - or w
- x permissions char; either - or x
+ page protections (using the VKI_PROT_* flags)
+ mapped file device and inode
offset in file, or zero if no file
filename, zero terminated, or NULL if no file
@@ -132,16 +140,13 @@ void VG_(read_procselfmaps)(void)
So the sig of the called fn might be
- void (*record_mapping)( Addr start, SizeT size,
- Char r, Char w, Char x,
+ void (*record_mapping)( Addr start, SizeT size, UInt prot,
+ UInt dev, UInt info,
ULong foffset, UChar* filename )
Note that the supplied filename is transiently stored; record_mapping
should make a copy if it wants to keep it.
-
- Nb: it is important that this function does not alter the contents of
- procmap_buf!
*/
void VG_(parse_procselfmaps) (
- void (*record_mapping)( Addr addr, SizeT len, Char rr, Char ww, Char xx,
+ void (*record_mapping)( Addr addr, SizeT len, UInt prot,
UInt dev, UInt ino, ULong foff, const UChar* filename )
)
@@ -153,4 +158,9 @@ void VG_(parse_procselfmaps) (
UInt ino;
UWord foffset, maj, min;
+ const Char *procmap_buf;
+ Int buf_n_tot;
+ UInt prot;
+
+ procmap_buf = read_procselfmaps(&buf_n_tot);
sk_assert( '\0' != procmap_buf[0] && 0 != buf_n_tot);
@@ -223,5 +233,5 @@ void VG_(parse_procselfmaps) (
/* Try and find the name of the file mapped to this segment, if
it exists. */
- while (procmap_buf[i] != '\n' && i < M_PROCMAP_BUF-1) i++;
+ while (procmap_buf[i] != '\n' && i < buf_n_tot-1) i++;
i_eol = i;
i--;
@@ -231,21 +241,25 @@ void VG_(parse_procselfmaps) (
/* Minor hack: put a '\0' at the filename end for the call to
`record_mapping', then restore the old char with `tmp'. */
- filename = &procmap_buf[i];
- tmp = filename[i_eol - i];
+ filename = VG_(arena_malloc)(VG_AR_CORE, i_eol-i);
+ VG_(memcpy)(filename, &procmap_buf[i], i_eol-i);
filename[i_eol - i] = '\0';
} else {
- tmp = '\0';
+ tmp = 0;
filename = NULL;
foffset = 0;
}
+ prot = 0;
+ if (rr == 'r') prot |= VKI_PROT_READ;
+ if (ww == 'w') prot |= VKI_PROT_WRITE;
+ if (xx == 'x') prot |= VKI_PROT_EXEC;
+
if (start < VG_(valgrind_last))
(*record_mapping) ( start, endPlusOne-start,
- rr, ww, xx, maj * 256 + min, ino,
+ prot, maj * 256 + min, ino,
foffset, filename );
- if ('\0' != tmp) {
- filename[i_eol - i] = tmp;
- }
+ if (filename != NULL)
+ VG_(arena_free)(VG_AR_CORE, filename);
i = i_eol + 1;
|