Generate valid XML even for very long fn names - always ensure tags

have matching closing tags.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6502
This commit is contained in:
Julian Seward 2007-01-10 15:42:15 +00:00
parent 0e343fea86
commit afb082acc7

View File

@ -744,38 +744,73 @@ Bool VG_(lookup_symbol_SLOW)(UChar* sopatt, UChar* name, Addr* pEnt, Addr* pToc)
}
/* Print into buf info on code address, function name and filename */
/* VG_(describe_IP): print into buf info on code address, function
name and filename. */
/* Copy str into buf starting at n, but not going past buf[n_buf-1]
and always ensuring that buf is zero-terminated. */
static Int putStr ( Int n, Int n_buf, Char* buf, Char* str )
{
vg_assert(n_buf > 0);
vg_assert(n >= 0 && n < n_buf);
for (; n < n_buf-1 && *str != 0; n++,str++)
buf[n] = *str;
vg_assert(n >= 0 && n < n_buf);
buf[n] = '\0';
return n;
}
static Int putStrEsc ( Int n, Int n_buf, Char* buf, Char* str )
/* Same as putStr, but escaping chars for XML output, and
also not adding more than count chars to n_buf. */
static Int putStrEsc ( Int n, Int n_buf, Int count, Char* buf, Char* str )
{
Char alt[2];
vg_assert(n_buf > 0);
vg_assert(count >= 0 && count < n_buf);
vg_assert(n >= 0 && n < n_buf);
for (; *str != 0; str++) {
vg_assert(count >= 0);
if (count <= 0)
goto done;
switch (*str) {
case '&': n = putStr( n, n_buf, buf, "&amp;"); break;
case '<': n = putStr( n, n_buf, buf, "&lt;"); break;
case '>': n = putStr( n, n_buf, buf, "&gt;"); break;
default: alt[0] = *str;
alt[1] = 0;
n = putStr( n, n_buf, buf, alt );
break;
case '&':
if (count < 5) goto done;
n = putStr( n, n_buf, buf, "&amp;");
count -= 5;
break;
case '<':
if (count < 4) goto done;
n = putStr( n, n_buf, buf, "&lt;");
count -= 4;
break;
case '>':
if (count < 4) goto done;
n = putStr( n, n_buf, buf, "&gt;");
count -= 4;
break;
default:
if (count < 1) goto done;
alt[0] = *str;
alt[1] = 0;
n = putStr( n, n_buf, buf, alt );
count -= 1;
break;
}
}
done:
vg_assert(count >= 0); /* should not go -ve in loop */
vg_assert(n >= 0 && n < n_buf);
return n;
}
Char* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
{
# define APPEND(_str) \
n = putStr(n, n_buf, buf, _str);
# define APPEND_ESC(_str) \
n = putStrEsc(n, n_buf, buf, _str);
n = putStr(n, n_buf, buf, _str)
# define APPEND_ESC(_count,_str) \
n = putStrEsc(n, n_buf, (_count), buf, (_str))
# define BUF_LEN 4096
UInt lineno;
@ -802,7 +837,12 @@ Char* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
HChar* maybe_newline = human_readable ? "\n " : "";
HChar* maybe_newline2 = human_readable ? "\n " : "";
/* Print in XML format, dumping in as much info as we know. */
/* Print in XML format, dumping in as much info as we know.
Ensure all tags are balanced even if the individual strings
are too long. Allocate 1/10 of BUF_LEN to the object name,
6/10s to the function name, 1/10 to the directory name and
1/10 to the file name, leaving 1/10 for all the fixed-length
stuff. */
APPEND("<frame>");
VG_(sprintf)(ibuf,"<ip>0x%llx</ip>", (ULong)eip);
APPEND(maybe_newline);
@ -810,25 +850,25 @@ Char* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf)
if (know_objname) {
APPEND(maybe_newline);
APPEND("<obj>");
APPEND_ESC(buf_obj);
APPEND_ESC(1*BUF_LEN/10, buf_obj);
APPEND("</obj>");
}
if (know_fnname) {
APPEND(maybe_newline);
APPEND("<fn>");
APPEND_ESC(buf_fn);
APPEND_ESC(6*BUF_LEN/10, buf_fn);
APPEND("</fn>");
}
if (know_srcloc) {
if (know_dirinfo) {
APPEND(maybe_newline);
APPEND("<dir>");
APPEND(buf_dirname);
APPEND_ESC(1*BUF_LEN/10, buf_dirname);
APPEND("</dir>");
}
APPEND(maybe_newline);
APPEND("<file>");
APPEND_ESC(buf_srcloc);
APPEND_ESC(1*BUF_LEN/10, buf_srcloc);
APPEND("</file>");
APPEND(maybe_newline);
APPEND("<line>");