// Reads a signed integer out of the string starting at i, stores it // in v, and returns the next index to start at. Zero-length // decimal numbers are allowed, and are returned as zero. static int readsigned(unsigned char* s, int len, int i, double* v) { int i0 = i, i2; double sgn=1, val; if(i >= len) { *v = 0; return len; } if(s[i] == '+') { i++; } else if(s[i] == '-') { i++; sgn = -1; } i2 = readdec(s, len, i, &val); if(i0 == i && i2 == i) { *v = 0; return i0; // don't successfully parse bare "+" or "-" } *v = sgn*val; return i2; }
static int tonum(unsigned char* s, int len, double* result) { int i=0, fraclen=0; double sgn=1, val, frac=0, exp=0; // Special case, "." is not a number, even though "1." and ".0" are. if(len == 1 && s[0] == '.') return 0; // Strip off the leading negative sign first, so we can correctly // parse things like -.xxx which would otherwise confuse // readsigned. if(len > 1 && s[0] == '-' && s[1] != '-') { sgn = -1; s++; len--; } // Read the integer part i = readsigned(s, len, i, &val); if(val < 0) { sgn = -1; val = -val; } // Read the fractional part, if any if(i < len && s[i] == '.') { i++; fraclen = readdec(s, len, i, &frac) - i; i += fraclen; } // Nothing so far? Then the parse failed. if(i == 0) return 0; // Read the exponent, if any if(i < len && (s[i] == 'e' || s[i] == 'E')) { int i0 = i+1; i = readsigned(s, len, i+1, &exp); if(i == i0) return 0; // Must have a number after the "e" } // compute the result *result = sgn * (val + frac * decpow(-fraclen)) * decpow(exp); // if we didn't use the whole string, return failure if(i < len) return 0; return 1; }
/* Parse /proc/self/maps. For each map entry, call record_mapping, passing it, in this order: start address in memory length 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 So the sig of the called fn might be 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, UInt prot, UInt dev, UInt ino, ULong foff, const UChar* filename ) ) { Int i, j, i_eol; Addr start, endPlusOne; UChar* filename; UChar rr, ww, xx, pp, ch, tmp; UInt ino, prot; UWord foffset, maj, min; read_procselfmaps(); tl_assert( '\0' != procmap_buf[0] && 0 != buf_n_tot); if (0) VG_(message)(Vg_DebugMsg, "raw:\n%s", procmap_buf ); /* Ok, it's safely aboard. Parse the entries. */ i = 0; while (True) { if (i >= buf_n_tot) break; /* Read (without fscanf :) the pattern %16x-%16x %c%c%c%c %16x %2x:%2x %d */ j = readhex(&procmap_buf[i], &start); if (j > 0) i += j; else goto syntaxerror; j = readchar(&procmap_buf[i], &ch); if (j == 1 && ch == '-') i += j; else goto syntaxerror; j = readhex(&procmap_buf[i], &endPlusOne); if (j > 0) i += j; else goto syntaxerror; j = readchar(&procmap_buf[i], &ch); if (j == 1 && ch == ' ') i += j; else goto syntaxerror; j = readchar(&procmap_buf[i], &rr); if (j == 1 && (rr == 'r' || rr == '-')) i += j; else goto syntaxerror; j = readchar(&procmap_buf[i], &ww); if (j == 1 && (ww == 'w' || ww == '-')) i += j; else goto syntaxerror; j = readchar(&procmap_buf[i], &xx); if (j == 1 && (xx == 'x' || xx == '-')) i += j; else goto syntaxerror; /* This field is the shared/private flag */ j = readchar(&procmap_buf[i], &pp); if (j == 1 && (pp == 'p' || pp == '-' || pp == 's')) i += j; else goto syntaxerror; j = readchar(&procmap_buf[i], &ch); if (j == 1 && ch == ' ') i += j; else goto syntaxerror; j = readhex(&procmap_buf[i], &foffset); if (j > 0) i += j; else goto syntaxerror; j = readchar(&procmap_buf[i], &ch); if (j == 1 && ch == ' ') i += j; else goto syntaxerror; j = readhex(&procmap_buf[i], &maj); if (j > 0) i += j; else goto syntaxerror; j = readchar(&procmap_buf[i], &ch); if (j == 1 && ch == ':') i += j; else goto syntaxerror; j = readhex(&procmap_buf[i], &min); if (j > 0) i += j; else goto syntaxerror; j = readchar(&procmap_buf[i], &ch); if (j == 1 && ch == ' ') i += j; else goto syntaxerror; j = readdec(&procmap_buf[i], &ino); if (j > 0) i += j; else goto syntaxerror; goto read_line_ok; syntaxerror: VG_(message)(Vg_UserMsg, "FATAL: syntax error reading /proc/self/maps"); { Int k; VG_(printf)("last 50 chars: '"); for (k = i-50; k <= i; k++) VG_(printf)("%c", procmap_buf[k]); VG_(printf)("'\n"); } VG_(exit)(1); read_line_ok: /* Try and find the name of the file mapped to this segment, if it exists. */ while (procmap_buf[i] != '\n' && i < buf_n_tot-1) i++; i_eol = i; i--; while (!VG_(isspace)(procmap_buf[i]) && i >= 0) i--; i++; if (i < i_eol-1 && procmap_buf[i] == '/') { /* 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[i_eol - i] = '\0'; } else { 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, prot, maj * 256 + min, ino, foffset, filename ); if ('\0' != tmp) { filename[i_eol - i] = tmp; } i = i_eol + 1; } }