1024598e40c84666cc311a42c256bbf880db3ac99sewardj 2024598e40c84666cc311a42c256bbf880db3ac99sewardj/* This demonstrates a stack overrun bug that exp-ptrcheck found while 3024598e40c84666cc311a42c256bbf880db3ac99sewardj running Valgrind itself (self hosting). As at 12 Sept 08 this bug 4024598e40c84666cc311a42c256bbf880db3ac99sewardj is still in Valgrind. */ 5024598e40c84666cc311a42c256bbf880db3ac99sewardj 6024598e40c84666cc311a42c256bbf880db3ac99sewardj#include <stdio.h> 7024598e40c84666cc311a42c256bbf880db3ac99sewardj#include <assert.h> 803ca90b84db7071c93455880cf0a14027655cbd9sewardj#include <stdarg.h> 9024598e40c84666cc311a42c256bbf880db3ac99sewardj 10024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef unsigned long long int ULong; 1103ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef signed long long int Long; 12024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef unsigned int UInt; 13024598e40c84666cc311a42c256bbf880db3ac99sewardjtypedef signed int Int; 1403ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef signed char Char; 1503ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef char HChar; 1603ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef unsigned long UWord; 1703ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef signed long Word; 1803ca90b84db7071c93455880cf0a14027655cbd9sewardj 1903ca90b84db7071c93455880cf0a14027655cbd9sewardj 2003ca90b84db7071c93455880cf0a14027655cbd9sewardj 2103ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef unsigned char Bool; 2203ca90b84db7071c93455880cf0a14027655cbd9sewardj#define True ((Bool)1) 2303ca90b84db7071c93455880cf0a14027655cbd9sewardj#define False ((Bool)0) 2403ca90b84db7071c93455880cf0a14027655cbd9sewardj 2503ca90b84db7071c93455880cf0a14027655cbd9sewardj#define VG_(_str) VG_##_str 2603ca90b84db7071c93455880cf0a14027655cbd9sewardj 2703ca90b84db7071c93455880cf0a14027655cbd9sewardj 2803ca90b84db7071c93455880cf0a14027655cbd9sewardj/* --------------------------------------------------------------------- 2903ca90b84db7071c93455880cf0a14027655cbd9sewardj vg_sprintf, copied from m_libcprint.c 3003ca90b84db7071c93455880cf0a14027655cbd9sewardj ------------------------------------------------------------------ */ 3103ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt 3203ca90b84db7071c93455880cf0a14027655cbd9sewardjVG_(debugLog_vprintf) ( 3303ca90b84db7071c93455880cf0a14027655cbd9sewardj void(*send)(HChar,void*), 3403ca90b84db7071c93455880cf0a14027655cbd9sewardj void* send_arg2, 3503ca90b84db7071c93455880cf0a14027655cbd9sewardj const HChar* format, 3603ca90b84db7071c93455880cf0a14027655cbd9sewardj va_list vargs 3703ca90b84db7071c93455880cf0a14027655cbd9sewardj ); 3803ca90b84db7071c93455880cf0a14027655cbd9sewardj 3903ca90b84db7071c93455880cf0a14027655cbd9sewardj/* --------------------------------------------------------------------- 4003ca90b84db7071c93455880cf0a14027655cbd9sewardj printf() and friends 4103ca90b84db7071c93455880cf0a14027655cbd9sewardj ------------------------------------------------------------------ */ 4203ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef 4303ca90b84db7071c93455880cf0a14027655cbd9sewardj struct { Int fd; Bool is_socket; } 4403ca90b84db7071c93455880cf0a14027655cbd9sewardj OutputSink; 4503ca90b84db7071c93455880cf0a14027655cbd9sewardj 4603ca90b84db7071c93455880cf0a14027655cbd9sewardj 4703ca90b84db7071c93455880cf0a14027655cbd9sewardjOutputSink VG_(log_output_sink) = { 2, False }; /* 2 = stderr */ 4803ca90b84db7071c93455880cf0a14027655cbd9sewardj 4903ca90b84db7071c93455880cf0a14027655cbd9sewardj/* Do the low-level send of a message to the logging sink. */ 5003ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic 5103ca90b84db7071c93455880cf0a14027655cbd9sewardjvoid send_bytes_to_logging_sink ( OutputSink* sink, HChar* msg, Int nbytes ) 5203ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 5303ca90b84db7071c93455880cf0a14027655cbd9sewardj fwrite(msg, 1, nbytes, stdout); 5403ca90b84db7071c93455880cf0a14027655cbd9sewardj fflush(stdout); 5503ca90b84db7071c93455880cf0a14027655cbd9sewardj} 5603ca90b84db7071c93455880cf0a14027655cbd9sewardj 5703ca90b84db7071c93455880cf0a14027655cbd9sewardj 5803ca90b84db7071c93455880cf0a14027655cbd9sewardj/* --------- printf --------- */ 5903ca90b84db7071c93455880cf0a14027655cbd9sewardj 6003ca90b84db7071c93455880cf0a14027655cbd9sewardjtypedef 6103ca90b84db7071c93455880cf0a14027655cbd9sewardj struct { 6203ca90b84db7071c93455880cf0a14027655cbd9sewardj HChar buf[512]; 6303ca90b84db7071c93455880cf0a14027655cbd9sewardj Int buf_used; 6403ca90b84db7071c93455880cf0a14027655cbd9sewardj OutputSink* sink; 6503ca90b84db7071c93455880cf0a14027655cbd9sewardj } 6603ca90b84db7071c93455880cf0a14027655cbd9sewardj printf_buf_t; 6703ca90b84db7071c93455880cf0a14027655cbd9sewardj 6803ca90b84db7071c93455880cf0a14027655cbd9sewardj// Adds a single char to the buffer. When the buffer gets sufficiently 6903ca90b84db7071c93455880cf0a14027655cbd9sewardj// full, we write its contents to the logging sink. 7003ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic void add_to__printf_buf ( HChar c, void *p ) 7103ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 7203ca90b84db7071c93455880cf0a14027655cbd9sewardj printf_buf_t *b = (printf_buf_t *)p; 7303ca90b84db7071c93455880cf0a14027655cbd9sewardj 7403ca90b84db7071c93455880cf0a14027655cbd9sewardj if (b->buf_used > sizeof(b->buf) - 2 ) { 7503ca90b84db7071c93455880cf0a14027655cbd9sewardj send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used ); 7603ca90b84db7071c93455880cf0a14027655cbd9sewardj b->buf_used = 0; 7703ca90b84db7071c93455880cf0a14027655cbd9sewardj } 7803ca90b84db7071c93455880cf0a14027655cbd9sewardj b->buf[b->buf_used++] = c; 7903ca90b84db7071c93455880cf0a14027655cbd9sewardj b->buf[b->buf_used] = 0; 8003ca90b84db7071c93455880cf0a14027655cbd9sewardj assert(b->buf_used < sizeof(b->buf)); 8103ca90b84db7071c93455880cf0a14027655cbd9sewardj} 8203ca90b84db7071c93455880cf0a14027655cbd9sewardj 8303ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline)) 8403ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic UInt vprintf_to_buf ( printf_buf_t* b, 8503ca90b84db7071c93455880cf0a14027655cbd9sewardj const HChar *format, va_list vargs ) 8603ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 8703ca90b84db7071c93455880cf0a14027655cbd9sewardj UInt ret = 0; 8803ca90b84db7071c93455880cf0a14027655cbd9sewardj if (b->sink->fd >= 0 || b->sink->fd == -2) { 8903ca90b84db7071c93455880cf0a14027655cbd9sewardj ret = VG_(debugLog_vprintf) 9003ca90b84db7071c93455880cf0a14027655cbd9sewardj ( add_to__printf_buf, b, format, vargs ); 9103ca90b84db7071c93455880cf0a14027655cbd9sewardj } 9203ca90b84db7071c93455880cf0a14027655cbd9sewardj return ret; 9303ca90b84db7071c93455880cf0a14027655cbd9sewardj} 9403ca90b84db7071c93455880cf0a14027655cbd9sewardj 9503ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline)) 9603ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic UInt vprintf_WRK ( OutputSink* sink, 9703ca90b84db7071c93455880cf0a14027655cbd9sewardj const HChar *format, va_list vargs ) 9803ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 9903ca90b84db7071c93455880cf0a14027655cbd9sewardj printf_buf_t myprintf_buf 10003ca90b84db7071c93455880cf0a14027655cbd9sewardj = { "", 0, sink }; 101d1897e1b9b34cd457daa9c95fd25cf1cbcd8702bflorian UInt ret; 102d1897e1b9b34cd457daa9c95fd25cf1cbcd8702bflorian ret = vprintf_to_buf(&myprintf_buf, format, vargs); 10303ca90b84db7071c93455880cf0a14027655cbd9sewardj // Write out any chars left in the buffer. 10403ca90b84db7071c93455880cf0a14027655cbd9sewardj if (myprintf_buf.buf_used > 0) { 10503ca90b84db7071c93455880cf0a14027655cbd9sewardj send_bytes_to_logging_sink( myprintf_buf.sink, 10603ca90b84db7071c93455880cf0a14027655cbd9sewardj myprintf_buf.buf, 10703ca90b84db7071c93455880cf0a14027655cbd9sewardj myprintf_buf.buf_used ); 10803ca90b84db7071c93455880cf0a14027655cbd9sewardj } 10903ca90b84db7071c93455880cf0a14027655cbd9sewardj return ret; 11003ca90b84db7071c93455880cf0a14027655cbd9sewardj} 11103ca90b84db7071c93455880cf0a14027655cbd9sewardj 11203ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline)) 11303ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt VG_(vprintf) ( const HChar *format, va_list vargs ) 11403ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 11503ca90b84db7071c93455880cf0a14027655cbd9sewardj return vprintf_WRK( &VG_(log_output_sink), format, vargs ); 11603ca90b84db7071c93455880cf0a14027655cbd9sewardj} 11703ca90b84db7071c93455880cf0a14027655cbd9sewardj 11803ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline)) 11903ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt VG_(printf) ( const HChar *format, ... ) 12003ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 12103ca90b84db7071c93455880cf0a14027655cbd9sewardj UInt ret; 12203ca90b84db7071c93455880cf0a14027655cbd9sewardj va_list vargs; 12303ca90b84db7071c93455880cf0a14027655cbd9sewardj va_start(vargs, format); 12403ca90b84db7071c93455880cf0a14027655cbd9sewardj ret = VG_(vprintf)(format, vargs); 12503ca90b84db7071c93455880cf0a14027655cbd9sewardj va_end(vargs); 12603ca90b84db7071c93455880cf0a14027655cbd9sewardj return ret; 12703ca90b84db7071c93455880cf0a14027655cbd9sewardj} 12803ca90b84db7071c93455880cf0a14027655cbd9sewardj 12903ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic Bool toBool ( Int x ) { 13003ca90b84db7071c93455880cf0a14027655cbd9sewardj Int r = (x == 0) ? False : True; 13103ca90b84db7071c93455880cf0a14027655cbd9sewardj return (Bool)r; 13203ca90b84db7071c93455880cf0a14027655cbd9sewardj} 13303ca90b84db7071c93455880cf0a14027655cbd9sewardj 13403ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline)) 13503ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic Int local_strlen ( const HChar* str ) 13603ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 13703ca90b84db7071c93455880cf0a14027655cbd9sewardj Int i = 0; 13803ca90b84db7071c93455880cf0a14027655cbd9sewardj while (str[i] != 0) i++; 13903ca90b84db7071c93455880cf0a14027655cbd9sewardj return i; 14003ca90b84db7071c93455880cf0a14027655cbd9sewardj} 14103ca90b84db7071c93455880cf0a14027655cbd9sewardj 14203ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline)) 14303ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic HChar local_toupper ( HChar c ) 14403ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 14503ca90b84db7071c93455880cf0a14027655cbd9sewardj if (c >= 'a' && c <= 'z') 14603ca90b84db7071c93455880cf0a14027655cbd9sewardj return c + ('A' - 'a'); 14703ca90b84db7071c93455880cf0a14027655cbd9sewardj else 14803ca90b84db7071c93455880cf0a14027655cbd9sewardj return c; 14903ca90b84db7071c93455880cf0a14027655cbd9sewardj} 15003ca90b84db7071c93455880cf0a14027655cbd9sewardj 15103ca90b84db7071c93455880cf0a14027655cbd9sewardj 15203ca90b84db7071c93455880cf0a14027655cbd9sewardj/*------------------------------------------------------------*/ 15303ca90b84db7071c93455880cf0a14027655cbd9sewardj/*--- A simple, generic, vprintf implementation. ---*/ 15403ca90b84db7071c93455880cf0a14027655cbd9sewardj/*------------------------------------------------------------*/ 15503ca90b84db7071c93455880cf0a14027655cbd9sewardj 15603ca90b84db7071c93455880cf0a14027655cbd9sewardj/* ----------------------------------------------- 15703ca90b84db7071c93455880cf0a14027655cbd9sewardj Distantly derived from: 15803ca90b84db7071c93455880cf0a14027655cbd9sewardj 15903ca90b84db7071c93455880cf0a14027655cbd9sewardj vprintf replacement for Checker. 16003ca90b84db7071c93455880cf0a14027655cbd9sewardj Copyright 1993, 1994, 1995 Tristan Gingold 16103ca90b84db7071c93455880cf0a14027655cbd9sewardj Written September 1993 Tristan Gingold 16203ca90b84db7071c93455880cf0a14027655cbd9sewardj Tristan Gingold, 8 rue Parmentier, F-91120 PALAISEAU, FRANCE 16303ca90b84db7071c93455880cf0a14027655cbd9sewardj 16403ca90b84db7071c93455880cf0a14027655cbd9sewardj (Checker itself was GPL'd.) 16503ca90b84db7071c93455880cf0a14027655cbd9sewardj ----------------------------------------------- */ 16603ca90b84db7071c93455880cf0a14027655cbd9sewardj 16703ca90b84db7071c93455880cf0a14027655cbd9sewardj/* Some flags. */ 16803ca90b84db7071c93455880cf0a14027655cbd9sewardj#define VG_MSG_SIGNED 1 /* The value is signed. */ 16903ca90b84db7071c93455880cf0a14027655cbd9sewardj#define VG_MSG_ZJUSTIFY 2 /* Must justify with '0'. */ 17003ca90b84db7071c93455880cf0a14027655cbd9sewardj#define VG_MSG_LJUSTIFY 4 /* Must justify on the left. */ 17103ca90b84db7071c93455880cf0a14027655cbd9sewardj#define VG_MSG_PAREN 8 /* Parenthesize if present (for %y) */ 17203ca90b84db7071c93455880cf0a14027655cbd9sewardj#define VG_MSG_COMMA 16 /* Add commas to numbers (for %d, %u) */ 17303ca90b84db7071c93455880cf0a14027655cbd9sewardj#define VG_MSG_ALTFORMAT 32 /* Convert the value to alternate format */ 17403ca90b84db7071c93455880cf0a14027655cbd9sewardj 17503ca90b84db7071c93455880cf0a14027655cbd9sewardj/* Copy a string into the buffer. */ 17603ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic __attribute__((noinline)) 17703ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt myvprintf_str ( void(*send)(HChar,void*), 17803ca90b84db7071c93455880cf0a14027655cbd9sewardj void* send_arg2, 17903ca90b84db7071c93455880cf0a14027655cbd9sewardj Int flags, 18003ca90b84db7071c93455880cf0a14027655cbd9sewardj Int width, 18103ca90b84db7071c93455880cf0a14027655cbd9sewardj HChar* str, 18203ca90b84db7071c93455880cf0a14027655cbd9sewardj Bool capitalise ) 18303ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 18403ca90b84db7071c93455880cf0a14027655cbd9sewardj# define MAYBE_TOUPPER(ch) (capitalise ? local_toupper(ch) : (ch)) 18503ca90b84db7071c93455880cf0a14027655cbd9sewardj UInt ret = 0; 18603ca90b84db7071c93455880cf0a14027655cbd9sewardj Int i, extra; 18703ca90b84db7071c93455880cf0a14027655cbd9sewardj Int len = local_strlen(str); 18803ca90b84db7071c93455880cf0a14027655cbd9sewardj 18903ca90b84db7071c93455880cf0a14027655cbd9sewardj if (width == 0) { 19003ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += len; 19103ca90b84db7071c93455880cf0a14027655cbd9sewardj for (i = 0; i < len; i++) 19203ca90b84db7071c93455880cf0a14027655cbd9sewardj send(MAYBE_TOUPPER(str[i]), send_arg2); 19303ca90b84db7071c93455880cf0a14027655cbd9sewardj return ret; 19403ca90b84db7071c93455880cf0a14027655cbd9sewardj } 19503ca90b84db7071c93455880cf0a14027655cbd9sewardj 19603ca90b84db7071c93455880cf0a14027655cbd9sewardj if (len > width) { 19703ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += width; 19803ca90b84db7071c93455880cf0a14027655cbd9sewardj for (i = 0; i < width; i++) 19903ca90b84db7071c93455880cf0a14027655cbd9sewardj send(MAYBE_TOUPPER(str[i]), send_arg2); 20003ca90b84db7071c93455880cf0a14027655cbd9sewardj return ret; 20103ca90b84db7071c93455880cf0a14027655cbd9sewardj } 20203ca90b84db7071c93455880cf0a14027655cbd9sewardj 20303ca90b84db7071c93455880cf0a14027655cbd9sewardj extra = width - len; 20403ca90b84db7071c93455880cf0a14027655cbd9sewardj if (flags & VG_MSG_LJUSTIFY) { 20503ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += extra; 20603ca90b84db7071c93455880cf0a14027655cbd9sewardj for (i = 0; i < extra; i++) 20703ca90b84db7071c93455880cf0a14027655cbd9sewardj send(' ', send_arg2); 20803ca90b84db7071c93455880cf0a14027655cbd9sewardj } 20903ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += len; 21003ca90b84db7071c93455880cf0a14027655cbd9sewardj for (i = 0; i < len; i++) 21103ca90b84db7071c93455880cf0a14027655cbd9sewardj send(MAYBE_TOUPPER(str[i]), send_arg2); 21203ca90b84db7071c93455880cf0a14027655cbd9sewardj if (!(flags & VG_MSG_LJUSTIFY)) { 21303ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += extra; 21403ca90b84db7071c93455880cf0a14027655cbd9sewardj for (i = 0; i < extra; i++) 21503ca90b84db7071c93455880cf0a14027655cbd9sewardj send(' ', send_arg2); 21603ca90b84db7071c93455880cf0a14027655cbd9sewardj } 21703ca90b84db7071c93455880cf0a14027655cbd9sewardj 21803ca90b84db7071c93455880cf0a14027655cbd9sewardj# undef MAYBE_TOUPPER 21903ca90b84db7071c93455880cf0a14027655cbd9sewardj return ret; 22003ca90b84db7071c93455880cf0a14027655cbd9sewardj} 22103ca90b84db7071c93455880cf0a14027655cbd9sewardj 22203ca90b84db7071c93455880cf0a14027655cbd9sewardj 22303ca90b84db7071c93455880cf0a14027655cbd9sewardj/* Copy a string into the buffer, escaping bad XML chars. */ 22403ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic 22503ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt myvprintf_str_XML_simplistic ( void(*send)(HChar,void*), 22603ca90b84db7071c93455880cf0a14027655cbd9sewardj void* send_arg2, 22703ca90b84db7071c93455880cf0a14027655cbd9sewardj HChar* str ) 22803ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 22903ca90b84db7071c93455880cf0a14027655cbd9sewardj UInt ret = 0; 23003ca90b84db7071c93455880cf0a14027655cbd9sewardj Int i; 23103ca90b84db7071c93455880cf0a14027655cbd9sewardj Int len = local_strlen(str); 23203ca90b84db7071c93455880cf0a14027655cbd9sewardj HChar* alt; 23303ca90b84db7071c93455880cf0a14027655cbd9sewardj 23403ca90b84db7071c93455880cf0a14027655cbd9sewardj for (i = 0; i < len; i++) { 23503ca90b84db7071c93455880cf0a14027655cbd9sewardj switch (str[i]) { 23603ca90b84db7071c93455880cf0a14027655cbd9sewardj case '&': alt = "&"; break; 23703ca90b84db7071c93455880cf0a14027655cbd9sewardj case '<': alt = "<"; break; 23803ca90b84db7071c93455880cf0a14027655cbd9sewardj case '>': alt = ">"; break; 23903ca90b84db7071c93455880cf0a14027655cbd9sewardj default: alt = NULL; 24003ca90b84db7071c93455880cf0a14027655cbd9sewardj } 24103ca90b84db7071c93455880cf0a14027655cbd9sewardj 24203ca90b84db7071c93455880cf0a14027655cbd9sewardj if (alt) { 24303ca90b84db7071c93455880cf0a14027655cbd9sewardj while (*alt) { 24403ca90b84db7071c93455880cf0a14027655cbd9sewardj send(*alt, send_arg2); 24503ca90b84db7071c93455880cf0a14027655cbd9sewardj ret++; 24603ca90b84db7071c93455880cf0a14027655cbd9sewardj alt++; 24703ca90b84db7071c93455880cf0a14027655cbd9sewardj } 24803ca90b84db7071c93455880cf0a14027655cbd9sewardj } else { 24903ca90b84db7071c93455880cf0a14027655cbd9sewardj send(str[i], send_arg2); 25003ca90b84db7071c93455880cf0a14027655cbd9sewardj ret++; 25103ca90b84db7071c93455880cf0a14027655cbd9sewardj } 25203ca90b84db7071c93455880cf0a14027655cbd9sewardj } 25303ca90b84db7071c93455880cf0a14027655cbd9sewardj 25403ca90b84db7071c93455880cf0a14027655cbd9sewardj return ret; 25503ca90b84db7071c93455880cf0a14027655cbd9sewardj} 25603ca90b84db7071c93455880cf0a14027655cbd9sewardj 25703ca90b84db7071c93455880cf0a14027655cbd9sewardj 25803ca90b84db7071c93455880cf0a14027655cbd9sewardj/* Write P into the buffer according to these args: 25903ca90b84db7071c93455880cf0a14027655cbd9sewardj * If SIGN is true, p is a signed. 26003ca90b84db7071c93455880cf0a14027655cbd9sewardj * BASE is the base. 26103ca90b84db7071c93455880cf0a14027655cbd9sewardj * If WITH_ZERO is true, '0' must be added. 26203ca90b84db7071c93455880cf0a14027655cbd9sewardj * WIDTH is the width of the field. 26303ca90b84db7071c93455880cf0a14027655cbd9sewardj */ 26403ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic 26503ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt myvprintf_int64 ( void(*send)(HChar,void*), 26603ca90b84db7071c93455880cf0a14027655cbd9sewardj void* send_arg2, 26703ca90b84db7071c93455880cf0a14027655cbd9sewardj Int flags, 26803ca90b84db7071c93455880cf0a14027655cbd9sewardj Int base, 26903ca90b84db7071c93455880cf0a14027655cbd9sewardj Int width, 27003ca90b84db7071c93455880cf0a14027655cbd9sewardj Bool capitalised, 27103ca90b84db7071c93455880cf0a14027655cbd9sewardj ULong p ) 27203ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 27303ca90b84db7071c93455880cf0a14027655cbd9sewardj HChar buf[40]; 27403ca90b84db7071c93455880cf0a14027655cbd9sewardj Int ind = 0; 27503ca90b84db7071c93455880cf0a14027655cbd9sewardj Int i, nc = 0; 27603ca90b84db7071c93455880cf0a14027655cbd9sewardj Bool neg = False; 27703ca90b84db7071c93455880cf0a14027655cbd9sewardj HChar* digits = capitalised ? "0123456789ABCDEF" : "0123456789abcdef"; 27803ca90b84db7071c93455880cf0a14027655cbd9sewardj UInt ret = 0; 27903ca90b84db7071c93455880cf0a14027655cbd9sewardj 28003ca90b84db7071c93455880cf0a14027655cbd9sewardj if (base < 2 || base > 16) 28103ca90b84db7071c93455880cf0a14027655cbd9sewardj return ret; 28203ca90b84db7071c93455880cf0a14027655cbd9sewardj 28303ca90b84db7071c93455880cf0a14027655cbd9sewardj if ((flags & VG_MSG_SIGNED) && (Long)p < 0) { 28403ca90b84db7071c93455880cf0a14027655cbd9sewardj p = - (Long)p; 28503ca90b84db7071c93455880cf0a14027655cbd9sewardj neg = True; 28603ca90b84db7071c93455880cf0a14027655cbd9sewardj } 28703ca90b84db7071c93455880cf0a14027655cbd9sewardj 28803ca90b84db7071c93455880cf0a14027655cbd9sewardj if (p == 0) 28903ca90b84db7071c93455880cf0a14027655cbd9sewardj buf[ind++] = '0'; 29003ca90b84db7071c93455880cf0a14027655cbd9sewardj else { 29103ca90b84db7071c93455880cf0a14027655cbd9sewardj while (p > 0) { 29203ca90b84db7071c93455880cf0a14027655cbd9sewardj if (flags & VG_MSG_COMMA && 10 == base && 29303ca90b84db7071c93455880cf0a14027655cbd9sewardj 0 == (ind-nc) % 3 && 0 != ind) 29403ca90b84db7071c93455880cf0a14027655cbd9sewardj { 29503ca90b84db7071c93455880cf0a14027655cbd9sewardj buf[ind++] = ','; 29603ca90b84db7071c93455880cf0a14027655cbd9sewardj nc++; 29703ca90b84db7071c93455880cf0a14027655cbd9sewardj } 29803ca90b84db7071c93455880cf0a14027655cbd9sewardj buf[ind++] = digits[p % base]; 29903ca90b84db7071c93455880cf0a14027655cbd9sewardj p /= base; 30003ca90b84db7071c93455880cf0a14027655cbd9sewardj } 30103ca90b84db7071c93455880cf0a14027655cbd9sewardj } 30203ca90b84db7071c93455880cf0a14027655cbd9sewardj 30303ca90b84db7071c93455880cf0a14027655cbd9sewardj if (neg) 30403ca90b84db7071c93455880cf0a14027655cbd9sewardj buf[ind++] = '-'; 30503ca90b84db7071c93455880cf0a14027655cbd9sewardj 30603ca90b84db7071c93455880cf0a14027655cbd9sewardj if (width > 0 && !(flags & VG_MSG_LJUSTIFY)) { 30703ca90b84db7071c93455880cf0a14027655cbd9sewardj for(; ind < width; ind++) { 30803ca90b84db7071c93455880cf0a14027655cbd9sewardj /* assert(ind < 39); */ 30903ca90b84db7071c93455880cf0a14027655cbd9sewardj if (ind > 39) { 31003ca90b84db7071c93455880cf0a14027655cbd9sewardj buf[39] = 0; 31103ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 31203ca90b84db7071c93455880cf0a14027655cbd9sewardj } 31303ca90b84db7071c93455880cf0a14027655cbd9sewardj buf[ind] = (flags & VG_MSG_ZJUSTIFY) ? '0': ' '; 31403ca90b84db7071c93455880cf0a14027655cbd9sewardj } 31503ca90b84db7071c93455880cf0a14027655cbd9sewardj } 31603ca90b84db7071c93455880cf0a14027655cbd9sewardj 31703ca90b84db7071c93455880cf0a14027655cbd9sewardj /* Reverse copy to buffer. */ 31803ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += ind; 31903ca90b84db7071c93455880cf0a14027655cbd9sewardj for (i = ind -1; i >= 0; i--) { 32003ca90b84db7071c93455880cf0a14027655cbd9sewardj send(buf[i], send_arg2); 32103ca90b84db7071c93455880cf0a14027655cbd9sewardj } 32203ca90b84db7071c93455880cf0a14027655cbd9sewardj if (width > 0 && (flags & VG_MSG_LJUSTIFY)) { 32303ca90b84db7071c93455880cf0a14027655cbd9sewardj for(; ind < width; ind++) { 32403ca90b84db7071c93455880cf0a14027655cbd9sewardj ret++; 32503ca90b84db7071c93455880cf0a14027655cbd9sewardj /* Never pad with zeroes on RHS -- changes the value! */ 32603ca90b84db7071c93455880cf0a14027655cbd9sewardj send(' ', send_arg2); 32703ca90b84db7071c93455880cf0a14027655cbd9sewardj } 32803ca90b84db7071c93455880cf0a14027655cbd9sewardj } 32903ca90b84db7071c93455880cf0a14027655cbd9sewardj return ret; 33003ca90b84db7071c93455880cf0a14027655cbd9sewardj} 33103ca90b84db7071c93455880cf0a14027655cbd9sewardj 33203ca90b84db7071c93455880cf0a14027655cbd9sewardj 33303ca90b84db7071c93455880cf0a14027655cbd9sewardj/* A simple vprintf(). */ 33403ca90b84db7071c93455880cf0a14027655cbd9sewardj/* EXPORTED */ 33503ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline)) 33603ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt 33703ca90b84db7071c93455880cf0a14027655cbd9sewardjVG_(debugLog_vprintf) ( 33803ca90b84db7071c93455880cf0a14027655cbd9sewardj void(*send)(HChar,void*), 33903ca90b84db7071c93455880cf0a14027655cbd9sewardj void* send_arg2, 34003ca90b84db7071c93455880cf0a14027655cbd9sewardj const HChar* format, 34103ca90b84db7071c93455880cf0a14027655cbd9sewardj va_list vargs 34203ca90b84db7071c93455880cf0a14027655cbd9sewardj) 34303ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 34403ca90b84db7071c93455880cf0a14027655cbd9sewardj UInt ret = 0; 34503ca90b84db7071c93455880cf0a14027655cbd9sewardj Int i; 34603ca90b84db7071c93455880cf0a14027655cbd9sewardj Int flags; 34703ca90b84db7071c93455880cf0a14027655cbd9sewardj Int width; 34803ca90b84db7071c93455880cf0a14027655cbd9sewardj Int n_ls = 0; 34903ca90b84db7071c93455880cf0a14027655cbd9sewardj Bool is_long, caps; 35003ca90b84db7071c93455880cf0a14027655cbd9sewardj 35103ca90b84db7071c93455880cf0a14027655cbd9sewardj /* We assume that vargs has already been initialised by the 35203ca90b84db7071c93455880cf0a14027655cbd9sewardj caller, using va_start, and that the caller will similarly 35303ca90b84db7071c93455880cf0a14027655cbd9sewardj clean up with va_end. 35403ca90b84db7071c93455880cf0a14027655cbd9sewardj */ 35503ca90b84db7071c93455880cf0a14027655cbd9sewardj 35603ca90b84db7071c93455880cf0a14027655cbd9sewardj for (i = 0; format[i] != 0; i++) { 35703ca90b84db7071c93455880cf0a14027655cbd9sewardj if (format[i] != '%') { 35803ca90b84db7071c93455880cf0a14027655cbd9sewardj send(format[i], send_arg2); 35903ca90b84db7071c93455880cf0a14027655cbd9sewardj ret++; 36003ca90b84db7071c93455880cf0a14027655cbd9sewardj continue; 36103ca90b84db7071c93455880cf0a14027655cbd9sewardj } 36203ca90b84db7071c93455880cf0a14027655cbd9sewardj i++; 36303ca90b84db7071c93455880cf0a14027655cbd9sewardj /* A '%' has been found. Ignore a trailing %. */ 36403ca90b84db7071c93455880cf0a14027655cbd9sewardj if (format[i] == 0) 36503ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 36603ca90b84db7071c93455880cf0a14027655cbd9sewardj if (format[i] == '%') { 36703ca90b84db7071c93455880cf0a14027655cbd9sewardj /* '%%' is replaced by '%'. */ 36803ca90b84db7071c93455880cf0a14027655cbd9sewardj send('%', send_arg2); 36903ca90b84db7071c93455880cf0a14027655cbd9sewardj ret++; 37003ca90b84db7071c93455880cf0a14027655cbd9sewardj continue; 37103ca90b84db7071c93455880cf0a14027655cbd9sewardj } 37203ca90b84db7071c93455880cf0a14027655cbd9sewardj flags = 0; 37303ca90b84db7071c93455880cf0a14027655cbd9sewardj n_ls = 0; 37403ca90b84db7071c93455880cf0a14027655cbd9sewardj width = 0; /* length of the field. */ 37503ca90b84db7071c93455880cf0a14027655cbd9sewardj while (1) { 37603ca90b84db7071c93455880cf0a14027655cbd9sewardj switch (format[i]) { 37703ca90b84db7071c93455880cf0a14027655cbd9sewardj case '(': 37803ca90b84db7071c93455880cf0a14027655cbd9sewardj flags |= VG_MSG_PAREN; 37903ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 38003ca90b84db7071c93455880cf0a14027655cbd9sewardj case ',': 38103ca90b84db7071c93455880cf0a14027655cbd9sewardj case '\'': 38203ca90b84db7071c93455880cf0a14027655cbd9sewardj /* If ',' or '\'' follows '%', commas will be inserted. */ 38303ca90b84db7071c93455880cf0a14027655cbd9sewardj flags |= VG_MSG_COMMA; 38403ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 38503ca90b84db7071c93455880cf0a14027655cbd9sewardj case '-': 38603ca90b84db7071c93455880cf0a14027655cbd9sewardj /* If '-' follows '%', justify on the left. */ 38703ca90b84db7071c93455880cf0a14027655cbd9sewardj flags |= VG_MSG_LJUSTIFY; 38803ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 38903ca90b84db7071c93455880cf0a14027655cbd9sewardj case '0': 39003ca90b84db7071c93455880cf0a14027655cbd9sewardj /* If '0' follows '%', pads will be inserted. */ 39103ca90b84db7071c93455880cf0a14027655cbd9sewardj flags |= VG_MSG_ZJUSTIFY; 39203ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 39303ca90b84db7071c93455880cf0a14027655cbd9sewardj case '#': 39403ca90b84db7071c93455880cf0a14027655cbd9sewardj /* If '#' follows '%', alternative format will be used. */ 39503ca90b84db7071c93455880cf0a14027655cbd9sewardj flags |= VG_MSG_ALTFORMAT; 39603ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 39703ca90b84db7071c93455880cf0a14027655cbd9sewardj default: 39803ca90b84db7071c93455880cf0a14027655cbd9sewardj goto parse_fieldwidth; 39903ca90b84db7071c93455880cf0a14027655cbd9sewardj } 40003ca90b84db7071c93455880cf0a14027655cbd9sewardj i++; 40103ca90b84db7071c93455880cf0a14027655cbd9sewardj } 40203ca90b84db7071c93455880cf0a14027655cbd9sewardj parse_fieldwidth: 40303ca90b84db7071c93455880cf0a14027655cbd9sewardj /* Compute the field length. */ 40403ca90b84db7071c93455880cf0a14027655cbd9sewardj while (format[i] >= '0' && format[i] <= '9') { 40503ca90b84db7071c93455880cf0a14027655cbd9sewardj width *= 10; 40603ca90b84db7071c93455880cf0a14027655cbd9sewardj width += format[i++] - '0'; 40703ca90b84db7071c93455880cf0a14027655cbd9sewardj } 40803ca90b84db7071c93455880cf0a14027655cbd9sewardj while (format[i] == 'l') { 40903ca90b84db7071c93455880cf0a14027655cbd9sewardj i++; 41003ca90b84db7071c93455880cf0a14027655cbd9sewardj n_ls++; 41103ca90b84db7071c93455880cf0a14027655cbd9sewardj } 41203ca90b84db7071c93455880cf0a14027655cbd9sewardj 41303ca90b84db7071c93455880cf0a14027655cbd9sewardj // %d means print a 32-bit integer. 41403ca90b84db7071c93455880cf0a14027655cbd9sewardj // %ld means print a word-size integer. 41503ca90b84db7071c93455880cf0a14027655cbd9sewardj // %lld means print a 64-bit integer. 41603ca90b84db7071c93455880cf0a14027655cbd9sewardj if (0 == n_ls) { is_long = False; } 41703ca90b84db7071c93455880cf0a14027655cbd9sewardj else if (1 == n_ls) { is_long = ( sizeof(void*) == sizeof(Long) ); } 41803ca90b84db7071c93455880cf0a14027655cbd9sewardj else { is_long = True; } 41903ca90b84db7071c93455880cf0a14027655cbd9sewardj 42003ca90b84db7071c93455880cf0a14027655cbd9sewardj switch (format[i]) { 42103ca90b84db7071c93455880cf0a14027655cbd9sewardj case 'o': /* %o */ 42203ca90b84db7071c93455880cf0a14027655cbd9sewardj if (flags & VG_MSG_ALTFORMAT) { 42303ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += 2; 42403ca90b84db7071c93455880cf0a14027655cbd9sewardj send('0',send_arg2); 42503ca90b84db7071c93455880cf0a14027655cbd9sewardj } 42603ca90b84db7071c93455880cf0a14027655cbd9sewardj if (is_long) 42703ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += myvprintf_int64(send, send_arg2, flags, 8, width, False, 42803ca90b84db7071c93455880cf0a14027655cbd9sewardj (ULong)(va_arg (vargs, ULong))); 42903ca90b84db7071c93455880cf0a14027655cbd9sewardj else 43003ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += myvprintf_int64(send, send_arg2, flags, 8, width, False, 43103ca90b84db7071c93455880cf0a14027655cbd9sewardj (ULong)(va_arg (vargs, UInt))); 43203ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 43303ca90b84db7071c93455880cf0a14027655cbd9sewardj case 'd': /* %d */ 43403ca90b84db7071c93455880cf0a14027655cbd9sewardj flags |= VG_MSG_SIGNED; 43503ca90b84db7071c93455880cf0a14027655cbd9sewardj if (is_long) 43603ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += myvprintf_int64(send, send_arg2, flags, 10, width, False, 43703ca90b84db7071c93455880cf0a14027655cbd9sewardj (ULong)(va_arg (vargs, Long))); 43803ca90b84db7071c93455880cf0a14027655cbd9sewardj else 43903ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += myvprintf_int64(send, send_arg2, flags, 10, width, False, 44003ca90b84db7071c93455880cf0a14027655cbd9sewardj (ULong)(va_arg (vargs, Int))); 44103ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 44203ca90b84db7071c93455880cf0a14027655cbd9sewardj case 'u': /* %u */ 44303ca90b84db7071c93455880cf0a14027655cbd9sewardj if (is_long) 44403ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += myvprintf_int64(send, send_arg2, flags, 10, width, False, 44503ca90b84db7071c93455880cf0a14027655cbd9sewardj (ULong)(va_arg (vargs, ULong))); 44603ca90b84db7071c93455880cf0a14027655cbd9sewardj else 44703ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += myvprintf_int64(send, send_arg2, flags, 10, width, False, 44803ca90b84db7071c93455880cf0a14027655cbd9sewardj (ULong)(va_arg (vargs, UInt))); 44903ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 450b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart case 'p': 451b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart if (format[i+1] == 'S') { 452b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart i++; 453b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart /* %pS, like %s but escaping chars for XML safety */ 454b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart /* Note: simplistic; ignores field width and flags */ 455b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart char *str = va_arg (vargs, char *); 456b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart if (str == (char*) 0) 457b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart str = "(null)"; 458b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart ret += myvprintf_str_XML_simplistic(send, send_arg2, str); 459b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart } else { 460b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart /* %p */ 461b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart ret += 2; 462b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart send('0',send_arg2); 463b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart send('x',send_arg2); 464b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart ret += myvprintf_int64(send, send_arg2, flags, 16, width, True, 465b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart (ULong)((UWord)va_arg (vargs, void *))); 466b3af9cf0b234d0d188347d92944e04ac9c8fbcd0bart } 46703ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 46803ca90b84db7071c93455880cf0a14027655cbd9sewardj case 'x': /* %x */ 46903ca90b84db7071c93455880cf0a14027655cbd9sewardj case 'X': /* %X */ 47003ca90b84db7071c93455880cf0a14027655cbd9sewardj caps = toBool(format[i] == 'X'); 47103ca90b84db7071c93455880cf0a14027655cbd9sewardj if (flags & VG_MSG_ALTFORMAT) { 47203ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += 2; 47303ca90b84db7071c93455880cf0a14027655cbd9sewardj send('0',send_arg2); 47403ca90b84db7071c93455880cf0a14027655cbd9sewardj send('x',send_arg2); 47503ca90b84db7071c93455880cf0a14027655cbd9sewardj } 47603ca90b84db7071c93455880cf0a14027655cbd9sewardj if (is_long) 47703ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps, 47803ca90b84db7071c93455880cf0a14027655cbd9sewardj (ULong)(va_arg (vargs, ULong))); 47903ca90b84db7071c93455880cf0a14027655cbd9sewardj else 48003ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += myvprintf_int64(send, send_arg2, flags, 16, width, caps, 48103ca90b84db7071c93455880cf0a14027655cbd9sewardj (ULong)(va_arg (vargs, UInt))); 48203ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 48303ca90b84db7071c93455880cf0a14027655cbd9sewardj case 'c': /* %c */ 48403ca90b84db7071c93455880cf0a14027655cbd9sewardj ret++; 48503ca90b84db7071c93455880cf0a14027655cbd9sewardj send(va_arg (vargs, int), send_arg2); 48603ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 48703ca90b84db7071c93455880cf0a14027655cbd9sewardj case 's': case 'S': { /* %s */ 48803ca90b84db7071c93455880cf0a14027655cbd9sewardj char *str = va_arg (vargs, char *); 48903ca90b84db7071c93455880cf0a14027655cbd9sewardj if (str == (char*) 0) str = "(null)"; 49003ca90b84db7071c93455880cf0a14027655cbd9sewardj ret += myvprintf_str(send, send_arg2, 49103ca90b84db7071c93455880cf0a14027655cbd9sewardj flags, width, str, format[i]=='S'); 49203ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 49303ca90b84db7071c93455880cf0a14027655cbd9sewardj } 49403ca90b84db7071c93455880cf0a14027655cbd9sewardj 49503ca90b84db7071c93455880cf0a14027655cbd9sewardj// case 'y': { /* %y - print symbol */ 49603ca90b84db7071c93455880cf0a14027655cbd9sewardj// Addr a = va_arg(vargs, Addr); 49703ca90b84db7071c93455880cf0a14027655cbd9sewardj// 49846cc04521acf2827eb33310fadc119bf2dc039e4florian// 49946cc04521acf2827eb33310fadc119bf2dc039e4florian// 50046cc04521acf2827eb33310fadc119bf2dc039e4florian// HChar *name; 50146cc04521acf2827eb33310fadc119bf2dc039e4florian// if (VG_(get_fnname_w_offset)(a, &name)) { 50246cc04521acf2827eb33310fadc119bf2dc039e4florian// HChar buf[1 + VG_strlen(name) + 1 + 1]; 50346cc04521acf2827eb33310fadc119bf2dc039e4florian// if (flags & VG_MSG_PAREN) { 50446cc04521acf2827eb33310fadc119bf2dc039e4florian// VG_(sprintf)(str, "(%s)", name): 50546cc04521acf2827eb33310fadc119bf2dc039e4florian// } else { 50646cc04521acf2827eb33310fadc119bf2dc039e4florian// VG_(sprintf)(str, "%s", name): 50703ca90b84db7071c93455880cf0a14027655cbd9sewardj// } 50846cc04521acf2827eb33310fadc119bf2dc039e4florian// ret += myvprintf_str(send, flags, width, buf, 0); 50946cc04521acf2827eb33310fadc119bf2dc039e4florian// } 51003ca90b84db7071c93455880cf0a14027655cbd9sewardj// break; 51103ca90b84db7071c93455880cf0a14027655cbd9sewardj// } 51203ca90b84db7071c93455880cf0a14027655cbd9sewardj default: 51303ca90b84db7071c93455880cf0a14027655cbd9sewardj break; 51403ca90b84db7071c93455880cf0a14027655cbd9sewardj } 51503ca90b84db7071c93455880cf0a14027655cbd9sewardj } 51603ca90b84db7071c93455880cf0a14027655cbd9sewardj return ret; 51703ca90b84db7071c93455880cf0a14027655cbd9sewardj} 51803ca90b84db7071c93455880cf0a14027655cbd9sewardj 51903ca90b84db7071c93455880cf0a14027655cbd9sewardj 52003ca90b84db7071c93455880cf0a14027655cbd9sewardjstatic void add_to__sprintf_buf ( HChar c, void *p ) 52103ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 52203ca90b84db7071c93455880cf0a14027655cbd9sewardj HChar** b = p; 52303ca90b84db7071c93455880cf0a14027655cbd9sewardj *(*b)++ = c; 52403ca90b84db7071c93455880cf0a14027655cbd9sewardj} 52503ca90b84db7071c93455880cf0a14027655cbd9sewardj 52603ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt VG_(vsprintf) ( HChar* buf, const HChar *format, va_list vargs ) 52703ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 52803ca90b84db7071c93455880cf0a14027655cbd9sewardj Int ret; 52903ca90b84db7071c93455880cf0a14027655cbd9sewardj HChar* sprintf_ptr = buf; 53003ca90b84db7071c93455880cf0a14027655cbd9sewardj 53103ca90b84db7071c93455880cf0a14027655cbd9sewardj ret = VG_(debugLog_vprintf) 53203ca90b84db7071c93455880cf0a14027655cbd9sewardj ( add_to__sprintf_buf, &sprintf_ptr, format, vargs ); 53303ca90b84db7071c93455880cf0a14027655cbd9sewardj add_to__sprintf_buf('\0', &sprintf_ptr); 53403ca90b84db7071c93455880cf0a14027655cbd9sewardj 53503ca90b84db7071c93455880cf0a14027655cbd9sewardj assert(local_strlen(buf) == ret); 53603ca90b84db7071c93455880cf0a14027655cbd9sewardj 53703ca90b84db7071c93455880cf0a14027655cbd9sewardj return ret; 53803ca90b84db7071c93455880cf0a14027655cbd9sewardj} 53903ca90b84db7071c93455880cf0a14027655cbd9sewardj 54003ca90b84db7071c93455880cf0a14027655cbd9sewardjUInt VG_(sprintf) ( HChar* buf, const HChar *format, ... ) 54103ca90b84db7071c93455880cf0a14027655cbd9sewardj{ 54203ca90b84db7071c93455880cf0a14027655cbd9sewardj UInt ret; 54303ca90b84db7071c93455880cf0a14027655cbd9sewardj va_list vargs; 54403ca90b84db7071c93455880cf0a14027655cbd9sewardj va_start(vargs,format); 54503ca90b84db7071c93455880cf0a14027655cbd9sewardj ret = VG_(vsprintf)(buf, format, vargs); 54603ca90b84db7071c93455880cf0a14027655cbd9sewardj va_end(vargs); 54703ca90b84db7071c93455880cf0a14027655cbd9sewardj return ret; 54803ca90b84db7071c93455880cf0a14027655cbd9sewardj} 54903ca90b84db7071c93455880cf0a14027655cbd9sewardj 55003ca90b84db7071c93455880cf0a14027655cbd9sewardj 551024598e40c84666cc311a42c256bbf880db3ac99sewardj 552024598e40c84666cc311a42c256bbf880db3ac99sewardj/* --------------------------------------------------------------------- 553024598e40c84666cc311a42c256bbf880db3ac99sewardj percentify() 554024598e40c84666cc311a42c256bbf880db3ac99sewardj ------------------------------------------------------------------ */ 555024598e40c84666cc311a42c256bbf880db3ac99sewardj 556024598e40c84666cc311a42c256bbf880db3ac99sewardj/* This part excerpted from coregrind/m_libcbase.c */ 557024598e40c84666cc311a42c256bbf880db3ac99sewardj 558024598e40c84666cc311a42c256bbf880db3ac99sewardj// Percentify n/m with d decimal places. Includes the '%' symbol at the end. 559024598e40c84666cc311a42c256bbf880db3ac99sewardj// Right justifies in 'buf'. 56003ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline)) 56103ca90b84db7071c93455880cf0a14027655cbd9sewardjvoid VG_percentify(ULong n, ULong m, UInt d, Int n_buf, HChar buf[]) 562024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 563024598e40c84666cc311a42c256bbf880db3ac99sewardj Int i, len, space; 564024598e40c84666cc311a42c256bbf880db3ac99sewardj ULong p1; 56503ca90b84db7071c93455880cf0a14027655cbd9sewardj HChar fmt[32]; 566024598e40c84666cc311a42c256bbf880db3ac99sewardj 567024598e40c84666cc311a42c256bbf880db3ac99sewardj if (m == 0) { 568024598e40c84666cc311a42c256bbf880db3ac99sewardj // Have to generate the format string in order to be flexible about 569024598e40c84666cc311a42c256bbf880db3ac99sewardj // the width of the field. 57003ca90b84db7071c93455880cf0a14027655cbd9sewardj VG_(sprintf)(fmt, "%%-%ds", n_buf); 571024598e40c84666cc311a42c256bbf880db3ac99sewardj // fmt is now "%<n_buf>s" where <d> is 1,2,3... 57203ca90b84db7071c93455880cf0a14027655cbd9sewardj VG_(sprintf)(buf, fmt, "--%"); 573024598e40c84666cc311a42c256bbf880db3ac99sewardj return; 574024598e40c84666cc311a42c256bbf880db3ac99sewardj } 575024598e40c84666cc311a42c256bbf880db3ac99sewardj 576024598e40c84666cc311a42c256bbf880db3ac99sewardj p1 = (100*n) / m; 577024598e40c84666cc311a42c256bbf880db3ac99sewardj 578024598e40c84666cc311a42c256bbf880db3ac99sewardj if (d == 0) { 57903ca90b84db7071c93455880cf0a14027655cbd9sewardj VG_(sprintf)(buf, "%lld%%", p1); 580024598e40c84666cc311a42c256bbf880db3ac99sewardj } else { 581024598e40c84666cc311a42c256bbf880db3ac99sewardj ULong p2; 582024598e40c84666cc311a42c256bbf880db3ac99sewardj UInt ex; 583024598e40c84666cc311a42c256bbf880db3ac99sewardj switch (d) { 584024598e40c84666cc311a42c256bbf880db3ac99sewardj case 1: ex = 10; break; 585024598e40c84666cc311a42c256bbf880db3ac99sewardj case 2: ex = 100; break; 586024598e40c84666cc311a42c256bbf880db3ac99sewardj case 3: ex = 1000; break; 587024598e40c84666cc311a42c256bbf880db3ac99sewardj default: assert(0); 588024598e40c84666cc311a42c256bbf880db3ac99sewardj /* was: VG_(tool_panic)("Currently can only handle 3 decimal places"); */ 589024598e40c84666cc311a42c256bbf880db3ac99sewardj } 590024598e40c84666cc311a42c256bbf880db3ac99sewardj p2 = ((100*n*ex) / m) % ex; 591024598e40c84666cc311a42c256bbf880db3ac99sewardj // Have to generate the format string in order to be flexible about 592024598e40c84666cc311a42c256bbf880db3ac99sewardj // the width of the post-decimal-point part. 59303ca90b84db7071c93455880cf0a14027655cbd9sewardj VG_(sprintf)(fmt, "%%lld.%%0%dlld%%%%", d); 594024598e40c84666cc311a42c256bbf880db3ac99sewardj // fmt is now "%lld.%0<d>lld%%" where <d> is 1,2,3... 59503ca90b84db7071c93455880cf0a14027655cbd9sewardj VG_(sprintf)(buf, fmt, p1, p2); 596024598e40c84666cc311a42c256bbf880db3ac99sewardj } 597024598e40c84666cc311a42c256bbf880db3ac99sewardj 59803ca90b84db7071c93455880cf0a14027655cbd9sewardj len = local_strlen(buf); 599024598e40c84666cc311a42c256bbf880db3ac99sewardj space = n_buf - len; 600024598e40c84666cc311a42c256bbf880db3ac99sewardj if (space < 0) space = 0; /* Allow for v. small field_width */ 601024598e40c84666cc311a42c256bbf880db3ac99sewardj i = len; 602024598e40c84666cc311a42c256bbf880db3ac99sewardj 603024598e40c84666cc311a42c256bbf880db3ac99sewardj /* Right justify in field */ 604024598e40c84666cc311a42c256bbf880db3ac99sewardj for ( ; i >= 0; i--) buf[i + space] = buf[i]; 605024598e40c84666cc311a42c256bbf880db3ac99sewardj for (i = 0; i < space; i++) buf[i] = ' '; 606024598e40c84666cc311a42c256bbf880db3ac99sewardj} 607024598e40c84666cc311a42c256bbf880db3ac99sewardj 608024598e40c84666cc311a42c256bbf880db3ac99sewardj 609024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/ 610024598e40c84666cc311a42c256bbf880db3ac99sewardj/*--- Stats ---*/ 611024598e40c84666cc311a42c256bbf880db3ac99sewardj/*------------------------------------------------------------*/ 612024598e40c84666cc311a42c256bbf880db3ac99sewardj 613024598e40c84666cc311a42c256bbf880db3ac99sewardj/* This part excerpted from coregrind/m_translate.c */ 614024598e40c84666cc311a42c256bbf880db3ac99sewardj 615024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic UInt n_SP_updates_fast = 0; 616024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic UInt n_SP_updates_generic_known = 0; 617024598e40c84666cc311a42c256bbf880db3ac99sewardjstatic UInt n_SP_updates_generic_unknown = 0; 618024598e40c84666cc311a42c256bbf880db3ac99sewardj 61903ca90b84db7071c93455880cf0a14027655cbd9sewardj__attribute__((noinline)) 620024598e40c84666cc311a42c256bbf880db3ac99sewardjvoid VG_print_translation_stats ( void ) 621024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 62203ca90b84db7071c93455880cf0a14027655cbd9sewardj HChar buf[6]; 623024598e40c84666cc311a42c256bbf880db3ac99sewardj UInt n_SP_updates = n_SP_updates_fast + n_SP_updates_generic_known 624024598e40c84666cc311a42c256bbf880db3ac99sewardj + n_SP_updates_generic_unknown; 625024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_percentify(n_SP_updates_fast, n_SP_updates, 1, 6, buf); 62603ca90b84db7071c93455880cf0a14027655cbd9sewardj VG_(printf)( 627024598e40c84666cc311a42c256bbf880db3ac99sewardj "translate: fast SP updates identified: %'u (%s)\n", 628024598e40c84666cc311a42c256bbf880db3ac99sewardj n_SP_updates_fast, buf ); 629024598e40c84666cc311a42c256bbf880db3ac99sewardj 630024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_percentify(n_SP_updates_generic_known, n_SP_updates, 1, 6, buf); 63103ca90b84db7071c93455880cf0a14027655cbd9sewardj VG_(printf)( 632024598e40c84666cc311a42c256bbf880db3ac99sewardj "translate: generic_known SP updates identified: %'u (%s)\n", 633024598e40c84666cc311a42c256bbf880db3ac99sewardj n_SP_updates_generic_known, buf ); 634024598e40c84666cc311a42c256bbf880db3ac99sewardj 635024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_percentify(n_SP_updates_generic_unknown, n_SP_updates, 1, 6, buf); 63603ca90b84db7071c93455880cf0a14027655cbd9sewardj VG_(printf)( 637024598e40c84666cc311a42c256bbf880db3ac99sewardj "translate: generic_unknown SP updates identified: %'u (%s)\n", 638024598e40c84666cc311a42c256bbf880db3ac99sewardj n_SP_updates_generic_unknown, buf ); 639024598e40c84666cc311a42c256bbf880db3ac99sewardj} 640024598e40c84666cc311a42c256bbf880db3ac99sewardj 641024598e40c84666cc311a42c256bbf880db3ac99sewardj 642024598e40c84666cc311a42c256bbf880db3ac99sewardj 643024598e40c84666cc311a42c256bbf880db3ac99sewardjint main ( void ) 644024598e40c84666cc311a42c256bbf880db3ac99sewardj{ 645024598e40c84666cc311a42c256bbf880db3ac99sewardj VG_print_translation_stats(); 646024598e40c84666cc311a42c256bbf880db3ac99sewardj return 0; 647024598e40c84666cc311a42c256bbf880db3ac99sewardj} 648