blob: 459ddba0c70e8d38c232ab1b1e5a422862c86522 [file] [log] [blame]
sewardj35421a32004-07-05 13:12:34 +00001
2/*---------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00003/*--- begin main_util.c ---*/
sewardj35421a32004-07-05 13:12:34 +00004/*---------------------------------------------------------------*/
5
sewardjf8ed9d82004-11-12 17:40:23 +00006/*
sewardj752f9062010-05-03 21:38:49 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjf8ed9d82004-11-12 17:40:23 +00009
sewardj89ae8472013-10-18 14:12:58 +000010 Copyright (C) 2004-2013 OpenWorks LLP
sewardj752f9062010-05-03 21:38:49 +000011 info@open-works.net
sewardjf8ed9d82004-11-12 17:40:23 +000012
sewardj752f9062010-05-03 21:38:49 +000013 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
sewardjf8ed9d82004-11-12 17:40:23 +000017
sewardj752f9062010-05-03 21:38:49 +000018 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
sewardj7bd6ffe2005-08-03 16:07:36 +000026 02110-1301, USA.
27
sewardj752f9062010-05-03 21:38:49 +000028 The GNU General Public License is contained in the file COPYING.
sewardjf8ed9d82004-11-12 17:40:23 +000029
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
sewardjf8ed9d82004-11-12 17:40:23 +000034*/
35
sewardj887a11a2004-07-05 17:26:47 +000036#include "libvex_basictypes.h"
sewardj41f43bc2004-07-08 14:23:22 +000037#include "libvex.h"
38
sewardjcef7d3e2009-07-02 12:21:59 +000039#include "main_globals.h"
40#include "main_util.h"
sewardj35421a32004-07-05 13:12:34 +000041
42
43/*---------------------------------------------------------*/
44/*--- Storage ---*/
45/*---------------------------------------------------------*/
46
sewardjce605f92004-07-05 14:39:15 +000047/* Try to keep this as low as possible -- in particular, less than the
48 size of the smallest L2 cache we might encounter. At 50000, my VIA
49 Nehemiah 1 GHz (a weedy machine) can satisfy 27 million calls/
50 second to LibVEX_Alloc(16) -- that is, allocate memory at over 400
51 MByte/sec. Once the size increases enough to fall out of the cache
52 into memory, the rate falls by about a factor of 3.
53*/
sewardje165a8a2010-09-29 21:39:12 +000054#define N_TEMPORARY_BYTES 5000000
sewardj35421a32004-07-05 13:12:34 +000055
sewardj4eeda9c2005-11-25 02:47:00 +000056static HChar temporary[N_TEMPORARY_BYTES] __attribute__((aligned(8)));
sewardj2d6b14a2005-11-23 04:25:07 +000057static HChar* temporary_first = &temporary[0];
58static HChar* temporary_curr = &temporary[0];
59static HChar* temporary_last = &temporary[N_TEMPORARY_BYTES-1];
60
61static ULong temporary_bytes_allocd_TOT = 0;
sewardj443cd9d2004-07-18 23:06:45 +000062
sewardje29a31d2007-05-05 12:26:23 +000063#define N_PERMANENT_BYTES 10000
sewardj443cd9d2004-07-18 23:06:45 +000064
sewardje29a31d2007-05-05 12:26:23 +000065static HChar permanent[N_PERMANENT_BYTES] __attribute__((aligned(8)));
sewardj2d6b14a2005-11-23 04:25:07 +000066static HChar* permanent_first = &permanent[0];
67static HChar* permanent_curr = &permanent[0];
sewardje29a31d2007-05-05 12:26:23 +000068static HChar* permanent_last = &permanent[N_PERMANENT_BYTES-1];
sewardj443cd9d2004-07-18 23:06:45 +000069
florianbde34062014-10-11 14:48:38 +000070static HChar* private_LibVEX_alloc_first = &temporary[0];
71static HChar* private_LibVEX_alloc_curr = &temporary[0];
72static HChar* private_LibVEX_alloc_last = &temporary[N_TEMPORARY_BYTES-1];
73
74
sewardjd887b862005-01-17 18:34:34 +000075static VexAllocMode mode = VexAllocModeTEMP;
sewardjce605f92004-07-05 14:39:15 +000076
sewardj2d6b14a2005-11-23 04:25:07 +000077void vexAllocSanityCheck ( void )
78{
79 vassert(temporary_first == &temporary[0]);
80 vassert(temporary_last == &temporary[N_TEMPORARY_BYTES-1]);
81 vassert(permanent_first == &permanent[0]);
sewardje29a31d2007-05-05 12:26:23 +000082 vassert(permanent_last == &permanent[N_PERMANENT_BYTES-1]);
sewardj2d6b14a2005-11-23 04:25:07 +000083 vassert(temporary_first <= temporary_curr);
84 vassert(temporary_curr <= temporary_last);
85 vassert(permanent_first <= permanent_curr);
86 vassert(permanent_curr <= permanent_last);
87 vassert(private_LibVEX_alloc_first <= private_LibVEX_alloc_curr);
88 vassert(private_LibVEX_alloc_curr <= private_LibVEX_alloc_last);
89 if (mode == VexAllocModeTEMP){
90 vassert(private_LibVEX_alloc_first == temporary_first);
91 vassert(private_LibVEX_alloc_last == temporary_last);
92 }
93 else
94 if (mode == VexAllocModePERM) {
95 vassert(private_LibVEX_alloc_first == permanent_first);
96 vassert(private_LibVEX_alloc_last == permanent_last);
97 }
98 else
99 vassert(0);
100
101# define IS_WORD_ALIGNED(p) (0 == (((HWord)p) & (sizeof(HWord)-1)))
102 vassert(sizeof(HWord) == 4 || sizeof(HWord) == 8);
103 vassert(IS_WORD_ALIGNED(temporary_first));
104 vassert(IS_WORD_ALIGNED(temporary_curr));
105 vassert(IS_WORD_ALIGNED(temporary_last+1));
106 vassert(IS_WORD_ALIGNED(permanent_first));
107 vassert(IS_WORD_ALIGNED(permanent_curr));
108 vassert(IS_WORD_ALIGNED(permanent_last+1));
109 vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_first));
110 vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_curr));
111 vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_last+1));
112# undef IS_WORD_ALIGNED
113}
114
115/* The current allocation mode. */
sewardjce605f92004-07-05 14:39:15 +0000116
sewardjd887b862005-01-17 18:34:34 +0000117void vexSetAllocMode ( VexAllocMode m )
sewardj443cd9d2004-07-18 23:06:45 +0000118{
sewardj2d6b14a2005-11-23 04:25:07 +0000119 vexAllocSanityCheck();
120
121 /* Save away the current allocation point .. */
122 if (mode == VexAllocModeTEMP){
123 temporary_curr = private_LibVEX_alloc_curr;
124 }
125 else
126 if (mode == VexAllocModePERM) {
127 permanent_curr = private_LibVEX_alloc_curr;
128 }
129 else
130 vassert(0);
131
132 /* Did that screw anything up? */
133 vexAllocSanityCheck();
134
135 if (m == VexAllocModeTEMP){
136 private_LibVEX_alloc_first = temporary_first;
137 private_LibVEX_alloc_curr = temporary_curr;
138 private_LibVEX_alloc_last = temporary_last;
139 }
140 else
141 if (m == VexAllocModePERM) {
142 private_LibVEX_alloc_first = permanent_first;
143 private_LibVEX_alloc_curr = permanent_curr;
144 private_LibVEX_alloc_last = permanent_last;
145 }
146 else
147 vassert(0);
148
sewardj443cd9d2004-07-18 23:06:45 +0000149 mode = m;
150}
151
sewardjd887b862005-01-17 18:34:34 +0000152VexAllocMode vexGetAllocMode ( void )
sewardj443cd9d2004-07-18 23:06:45 +0000153{
154 return mode;
155}
sewardjce605f92004-07-05 14:39:15 +0000156
sewardj2d6b14a2005-11-23 04:25:07 +0000157__attribute__((noreturn))
florianbde34062014-10-11 14:48:38 +0000158static void private_LibVEX_alloc_OOM(void)
sewardj35421a32004-07-05 13:12:34 +0000159{
florian55085f82012-11-21 00:36:55 +0000160 const HChar* pool = "???";
sewardj2d6b14a2005-11-23 04:25:07 +0000161 if (private_LibVEX_alloc_first == &temporary[0]) pool = "TEMP";
162 if (private_LibVEX_alloc_first == &permanent[0]) pool = "PERM";
163 vex_printf("VEX temporary storage exhausted.\n");
sewardj66afb9f2005-11-25 04:28:46 +0000164 vex_printf("Pool = %s, start %p curr %p end %p (size %lld)\n",
sewardj2d6b14a2005-11-23 04:25:07 +0000165 pool,
166 private_LibVEX_alloc_first,
167 private_LibVEX_alloc_curr,
168 private_LibVEX_alloc_last,
sewardje29a31d2007-05-05 12:26:23 +0000169 (Long)(private_LibVEX_alloc_last + 1 - private_LibVEX_alloc_first));
sewardj2d6b14a2005-11-23 04:25:07 +0000170 vpanic("VEX temporary storage exhausted.\n"
171 "Increase N_{TEMPORARY,PERMANENT}_BYTES and recompile.");
sewardj35421a32004-07-05 13:12:34 +0000172}
173
sewardj2d6b14a2005-11-23 04:25:07 +0000174void vexSetAllocModeTEMP_and_clear ( void )
sewardj35421a32004-07-05 13:12:34 +0000175{
sewardj7df596b2004-12-06 14:29:12 +0000176 /* vassert(vex_initdone); */ /* causes infinite assert loops */
sewardj2d6b14a2005-11-23 04:25:07 +0000177 temporary_bytes_allocd_TOT
sewardj66afb9f2005-11-25 04:28:46 +0000178 += (ULong)(private_LibVEX_alloc_curr - private_LibVEX_alloc_first);
sewardj2d6b14a2005-11-23 04:25:07 +0000179
180 mode = VexAllocModeTEMP;
181 temporary_curr = &temporary[0];
182 private_LibVEX_alloc_curr = &temporary[0];
sewardj8688a722009-12-03 09:50:38 +0000183
184 /* Set to (1) and change the fill byte to 0x00 or 0xFF to test for
185 any potential bugs due to using uninitialised memory in the main
186 VEX storage area. */
187 if (0) {
188 Int i;
189 for (i = 0; i < N_TEMPORARY_BYTES; i++)
190 temporary[i] = 0x00;
191 }
192
sewardj2d6b14a2005-11-23 04:25:07 +0000193 vexAllocSanityCheck();
sewardj35421a32004-07-05 13:12:34 +0000194}
195
196
sewardjd887b862005-01-17 18:34:34 +0000197/* Exported to library client. */
198
florianbde34062014-10-11 14:48:38 +0000199/* Allocate in Vex's temporary allocation area. Be careful with this.
200 You can only call it inside an instrumentation or optimisation
201 callback that you have previously specified in a call to
202 LibVEX_Translate. The storage allocated will only stay alive until
203 translation of the current basic block is complete.
204 */
205
florian04fc6b12014-12-29 20:22:26 +0000206void* LibVEX_Alloc ( SizeT nbytes )
florianbde34062014-10-11 14:48:38 +0000207{
208 struct align {
209 char c;
210 union {
211 char c;
212 short s;
213 int i;
214 long l;
215 long long ll;
216 float f;
217 double d;
218 /* long double is currently not used and would increase alignment
219 unnecessarily. */
220 /* long double ld; */
221 void *pto;
222 void (*ptf)(void);
223 } x;
224 };
225
226#if 0
227 /* Nasty debugging hack, do not use. */
228 return malloc(nbytes);
229#else
230 HChar* curr;
231 HChar* next;
florian04fc6b12014-12-29 20:22:26 +0000232 SizeT ALIGN;
florianbde34062014-10-11 14:48:38 +0000233 ALIGN = offsetof(struct align,x) - 1;
234 nbytes = (nbytes + ALIGN) & ~ALIGN;
235 curr = private_LibVEX_alloc_curr;
236 next = curr + nbytes;
237 if (next >= private_LibVEX_alloc_last)
238 private_LibVEX_alloc_OOM();
239 private_LibVEX_alloc_curr = next;
240 return curr;
241#endif
242}
243
sewardjd887b862005-01-17 18:34:34 +0000244void LibVEX_ShowAllocStats ( void )
245{
sewardj2d6b14a2005-11-23 04:25:07 +0000246 vex_printf("vex storage: T total %lld bytes allocated\n",
247 (Long)temporary_bytes_allocd_TOT );
sewardje29a31d2007-05-05 12:26:23 +0000248 vex_printf("vex storage: P total %lld bytes allocated\n",
249 (Long)(permanent_curr - permanent_first) );
sewardjd887b862005-01-17 18:34:34 +0000250}
251
sewardj35421a32004-07-05 13:12:34 +0000252
253/*---------------------------------------------------------*/
254/*--- Bombing out ---*/
255/*---------------------------------------------------------*/
256
257__attribute__ ((noreturn))
sewardj58277842005-02-07 03:11:17 +0000258void vex_assert_fail ( const HChar* expr,
259 const HChar* file, Int line, const HChar* fn )
sewardj35421a32004-07-05 13:12:34 +0000260{
261 vex_printf( "\nvex: %s:%d (%s): Assertion `%s' failed.\n",
262 file, line, fn, expr );
263 (*vex_failure_exit)();
264}
265
florianeebdb2b2014-12-10 16:08:09 +0000266/* To be used in assert-like (i.e. should never ever happen) situations */
sewardj35421a32004-07-05 13:12:34 +0000267__attribute__ ((noreturn))
florian76714fd2012-09-13 20:21:42 +0000268void vpanic ( const HChar* str )
sewardj35421a32004-07-05 13:12:34 +0000269{
270 vex_printf("\nvex: the `impossible' happened:\n %s\n", str);
271 (*vex_failure_exit)();
272}
273
274
275/*---------------------------------------------------------*/
276/*--- vex_printf ---*/
277/*---------------------------------------------------------*/
278
279/* This should be the only <...> include in the entire VEX library.
280 New code for vex_util.c should go above this point. */
281#include <stdarg.h>
282
florian04fc6b12014-12-29 20:22:26 +0000283SizeT vex_strlen ( const HChar* str )
sewardj35421a32004-07-05 13:12:34 +0000284{
florian04fc6b12014-12-29 20:22:26 +0000285 SizeT i = 0;
sewardj35421a32004-07-05 13:12:34 +0000286 while (str[i] != 0) i++;
287 return i;
288}
289
sewardj58277842005-02-07 03:11:17 +0000290Bool vex_streq ( const HChar* s1, const HChar* s2 )
sewardj36ca5132004-07-24 13:12:23 +0000291{
292 while (True) {
293 if (*s1 == 0 && *s2 == 0)
294 return True;
295 if (*s1 != *s2)
296 return False;
297 s1++;
298 s2++;
299 }
300}
sewardj35421a32004-07-05 13:12:34 +0000301
florian04fc6b12014-12-29 20:22:26 +0000302void vex_bzero ( void* sV, SizeT n )
sewardjc9069f22012-06-01 16:09:50 +0000303{
florian04fc6b12014-12-29 20:22:26 +0000304 SizeT i;
sewardjc9069f22012-06-01 16:09:50 +0000305 UChar* s = (UChar*)sV;
306 /* No laughing, please. Just don't call this too often. Thank you
307 for your attention. */
308 for (i = 0; i < n; i++) s[i] = 0;
309}
310
sewardj35421a32004-07-05 13:12:34 +0000311
sewardjda46fdd2005-08-25 21:20:18 +0000312/* Convert N0 into ascii in BUF, which is assumed to be big enough (at
313 least 67 bytes long). Observe BASE, SYNED and HEXCAPS. */
314static
315void convert_int ( /*OUT*/HChar* buf, Long n0,
316 Int base, Bool syned, Bool hexcaps )
sewardj35421a32004-07-05 13:12:34 +0000317{
sewardjda46fdd2005-08-25 21:20:18 +0000318 ULong u0;
319 HChar c;
320 Bool minus = False;
321 Int i, j, bufi = 0;
322 buf[bufi] = 0;
sewardj35421a32004-07-05 13:12:34 +0000323
sewardjda46fdd2005-08-25 21:20:18 +0000324 if (syned) {
325 if (n0 < 0) {
326 minus = True;
327 u0 = (ULong)(-n0);
328 } else {
329 u0 = (ULong)(n0);
sewardj35421a32004-07-05 13:12:34 +0000330 }
sewardjda46fdd2005-08-25 21:20:18 +0000331 } else {
332 u0 = (ULong)n0;
sewardj35421a32004-07-05 13:12:34 +0000333 }
334
sewardjda46fdd2005-08-25 21:20:18 +0000335 while (1) {
sewardjc7cd2142005-09-09 22:31:49 +0000336 buf[bufi++] = toHChar('0' + toUInt(u0 % base));
sewardjda46fdd2005-08-25 21:20:18 +0000337 u0 /= base;
338 if (u0 == 0) break;
sewardj35421a32004-07-05 13:12:34 +0000339 }
sewardjda46fdd2005-08-25 21:20:18 +0000340 if (minus)
341 buf[bufi++] = '-';
sewardj35421a32004-07-05 13:12:34 +0000342
sewardjda46fdd2005-08-25 21:20:18 +0000343 buf[bufi] = 0;
344 for (i = 0; i < bufi; i++)
345 if (buf[i] > '9')
sewardjc7cd2142005-09-09 22:31:49 +0000346 buf[i] = toHChar(buf[i] + (hexcaps ? 'A' : 'a') - '9' - 1);
sewardj35421a32004-07-05 13:12:34 +0000347
sewardjda46fdd2005-08-25 21:20:18 +0000348 i = 0;
349 j = bufi-1;
350 while (i <= j) {
351 c = buf[i];
352 buf[i] = buf[j];
353 buf[j] = c;
sewardj35421a32004-07-05 13:12:34 +0000354 i++;
sewardjda46fdd2005-08-25 21:20:18 +0000355 j--;
356 }
357}
358
359
360/* A half-arsed and buggy, but good-enough, implementation of
361 printf. */
362static
363UInt vprintf_wrk ( void(*sink)(HChar),
florian76714fd2012-09-13 20:21:42 +0000364 const HChar* format,
sewardjda46fdd2005-08-25 21:20:18 +0000365 va_list ap )
366{
367# define PUT(_ch) \
368 do { sink(_ch); nout++; } \
369 while (0)
370
371# define PAD(_n) \
372 do { Int _qq = (_n); for (; _qq > 0; _qq--) PUT(padchar); } \
373 while (0)
374
375# define PUTSTR(_str) \
florian55085f82012-11-21 00:36:55 +0000376 do { const HChar* _qq = _str; for (; *_qq; _qq++) PUT(*_qq); } \
sewardjda46fdd2005-08-25 21:20:18 +0000377 while (0)
378
florian76714fd2012-09-13 20:21:42 +0000379 const HChar* saved_format;
florianc66ba652014-12-29 19:05:37 +0000380 Bool longlong, ljustify, is_sizet;
sewardjda46fdd2005-08-25 21:20:18 +0000381 HChar padchar;
florian04fc6b12014-12-29 20:22:26 +0000382 Int fwidth, nout, len1, len3;
383 SizeT len2;
sewardjda46fdd2005-08-25 21:20:18 +0000384 HChar intbuf[100]; /* big enough for a 64-bit # in base 2 */
385
386 nout = 0;
387 while (1) {
388
389 if (!format)
sewardj35421a32004-07-05 13:12:34 +0000390 break;
sewardjda46fdd2005-08-25 21:20:18 +0000391 if (*format == 0)
392 break;
393
394 if (*format != '%') {
395 PUT(*format);
396 format++;
sewardj35421a32004-07-05 13:12:34 +0000397 continue;
398 }
sewardjda46fdd2005-08-25 21:20:18 +0000399
400 saved_format = format;
florianc66ba652014-12-29 19:05:37 +0000401 longlong = is_sizet = False;
sewardjda46fdd2005-08-25 21:20:18 +0000402 ljustify = False;
403 padchar = ' ';
404 fwidth = 0;
405 format++;
406
407 if (*format == '-') {
408 format++;
409 ljustify = True;
sewardj35421a32004-07-05 13:12:34 +0000410 }
sewardjda46fdd2005-08-25 21:20:18 +0000411 if (*format == '0') {
412 format++;
413 padchar = '0';
sewardj35421a32004-07-05 13:12:34 +0000414 }
florian473dc162012-12-16 22:44:32 +0000415 if (*format == '*') {
416 fwidth = va_arg(ap, Int);
florian04fc6b12014-12-29 20:22:26 +0000417 vassert(fwidth >= 0);
sewardjda46fdd2005-08-25 21:20:18 +0000418 format++;
florian473dc162012-12-16 22:44:32 +0000419 } else {
420 while (*format >= '0' && *format <= '9') {
421 fwidth = fwidth * 10 + (*format - '0');
422 format++;
423 }
sewardj35421a32004-07-05 13:12:34 +0000424 }
sewardjda46fdd2005-08-25 21:20:18 +0000425 if (*format == 'l') {
426 format++;
427 if (*format == 'l') {
428 format++;
florianc66ba652014-12-29 19:05:37 +0000429 longlong = True;
sewardjda46fdd2005-08-25 21:20:18 +0000430 }
florianc66ba652014-12-29 19:05:37 +0000431 } else if (*format == 'z') {
432 format++;
433 is_sizet = True;
sewardj35421a32004-07-05 13:12:34 +0000434 }
435
sewardjda46fdd2005-08-25 21:20:18 +0000436 switch (*format) {
437 case 's': {
florian55085f82012-11-21 00:36:55 +0000438 const HChar* str = va_arg(ap, HChar*);
sewardjda46fdd2005-08-25 21:20:18 +0000439 if (str == NULL)
440 str = "(null)";
441 len1 = len3 = 0;
442 len2 = vex_strlen(str);
cerion7d730cf2005-12-13 20:23:36 +0000443 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
444 len3 = ljustify ? fwidth-len2 : 0; }
sewardjda46fdd2005-08-25 21:20:18 +0000445 PAD(len1); PUTSTR(str); PAD(len3);
sewardj35421a32004-07-05 13:12:34 +0000446 break;
cerionb85e8bb2005-02-16 08:54:33 +0000447 }
sewardjda46fdd2005-08-25 21:20:18 +0000448 case 'c': {
449 HChar c = (HChar)va_arg(ap, int);
450 HChar str[2];
451 str[0] = c;
452 str[1] = 0;
453 len1 = len3 = 0;
454 len2 = vex_strlen(str);
cerion7d730cf2005-12-13 20:23:36 +0000455 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
456 len3 = ljustify ? fwidth-len2 : 0; }
sewardjda46fdd2005-08-25 21:20:18 +0000457 PAD(len1); PUTSTR(str); PAD(len3);
458 break;
459 }
460 case 'd': {
461 Long l;
florianc66ba652014-12-29 19:05:37 +0000462 vassert(is_sizet == False); // %zd is obscure; we don't allow it
sewardjda46fdd2005-08-25 21:20:18 +0000463 if (longlong) {
464 l = va_arg(ap, Long);
465 } else {
466 l = (Long)va_arg(ap, Int);
467 }
468 convert_int(intbuf, l, 10/*base*/, True/*signed*/,
469 False/*irrelevant*/);
470 len1 = len3 = 0;
471 len2 = vex_strlen(intbuf);
cerion7d730cf2005-12-13 20:23:36 +0000472 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
473 len3 = ljustify ? fwidth-len2 : 0; }
sewardjda46fdd2005-08-25 21:20:18 +0000474 PAD(len1); PUTSTR(intbuf); PAD(len3);
475 break;
476 }
477 case 'u':
478 case 'x':
479 case 'X': {
480 Int base = *format == 'u' ? 10 : 16;
481 Bool hexcaps = True; /* *format == 'X'; */
482 ULong l;
florianc66ba652014-12-29 19:05:37 +0000483 if (is_sizet) {
484 l = (ULong)va_arg(ap, SizeT);
485 } else if (longlong) {
sewardjda46fdd2005-08-25 21:20:18 +0000486 l = va_arg(ap, ULong);
487 } else {
488 l = (ULong)va_arg(ap, UInt);
489 }
490 convert_int(intbuf, l, base, False/*unsigned*/, hexcaps);
491 len1 = len3 = 0;
492 len2 = vex_strlen(intbuf);
cerion7d730cf2005-12-13 20:23:36 +0000493 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
494 len3 = ljustify ? fwidth-len2 : 0; }
sewardjda46fdd2005-08-25 21:20:18 +0000495 PAD(len1); PUTSTR(intbuf); PAD(len3);
496 break;
497 }
498 case 'p':
499 case 'P': {
sewardjc7cd2142005-09-09 22:31:49 +0000500 Bool hexcaps = toBool(*format == 'P');
sewardjda46fdd2005-08-25 21:20:18 +0000501 ULong l = Ptr_to_ULong( va_arg(ap, void*) );
502 convert_int(intbuf, l, 16/*base*/, False/*unsigned*/, hexcaps);
503 len1 = len3 = 0;
504 len2 = vex_strlen(intbuf)+2;
cerion7d730cf2005-12-13 20:23:36 +0000505 if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
506 len3 = ljustify ? fwidth-len2 : 0; }
sewardjda46fdd2005-08-25 21:20:18 +0000507 PAD(len1); PUT('0'); PUT('x'); PUTSTR(intbuf); PAD(len3);
508 break;
509 }
sewardjeb17e492007-08-25 23:07:44 +0000510 case '%': {
511 PUT('%');
512 break;
513 }
sewardjda46fdd2005-08-25 21:20:18 +0000514 default:
515 /* no idea what it is. Print the format literally and
516 move on. */
517 while (saved_format <= format) {
518 PUT(*saved_format);
519 saved_format++;
cerionb85e8bb2005-02-16 08:54:33 +0000520 }
521 break;
sewardj35421a32004-07-05 13:12:34 +0000522 }
sewardjda46fdd2005-08-25 21:20:18 +0000523
524 format++;
525
sewardj35421a32004-07-05 13:12:34 +0000526 }
sewardjda46fdd2005-08-25 21:20:18 +0000527
528 return nout;
529
530# undef PUT
531# undef PAD
532# undef PUTSTR
sewardj35421a32004-07-05 13:12:34 +0000533}
534
535
536/* A general replacement for printf(). Note that only low-level
537 debugging info should be sent via here. The official route is to
538 to use vg_message(). This interface is deprecated.
539*/
sewardj58277842005-02-07 03:11:17 +0000540static HChar myprintf_buf[1000];
541static Int n_myprintf_buf;
sewardj35421a32004-07-05 13:12:34 +0000542
sewardj58277842005-02-07 03:11:17 +0000543static void add_to_myprintf_buf ( HChar c )
sewardj35421a32004-07-05 13:12:34 +0000544{
sewardjc7cd2142005-09-09 22:31:49 +0000545 Bool emit = toBool(c == '\n' || n_myprintf_buf >= 1000-10 /*paranoia*/);
sewardj35421a32004-07-05 13:12:34 +0000546 myprintf_buf[n_myprintf_buf++] = c;
547 myprintf_buf[n_myprintf_buf] = 0;
sewardjda46fdd2005-08-25 21:20:18 +0000548 if (emit) {
549 (*vex_log_bytes)( myprintf_buf, vex_strlen(myprintf_buf) );
550 n_myprintf_buf = 0;
551 myprintf_buf[n_myprintf_buf] = 0;
552 }
sewardj35421a32004-07-05 13:12:34 +0000553}
554
florianeebdb2b2014-12-10 16:08:09 +0000555static UInt vex_vprintf ( const HChar* format, va_list vargs )
sewardj35421a32004-07-05 13:12:34 +0000556{
557 UInt ret;
sewardj35421a32004-07-05 13:12:34 +0000558
559 n_myprintf_buf = 0;
560 myprintf_buf[n_myprintf_buf] = 0;
561 ret = vprintf_wrk ( add_to_myprintf_buf, format, vargs );
562
563 if (n_myprintf_buf > 0) {
564 (*vex_log_bytes)( myprintf_buf, n_myprintf_buf );
565 }
566
florianeebdb2b2014-12-10 16:08:09 +0000567 return ret;
568}
569
570UInt vex_printf ( const HChar* format, ... )
571{
572 UInt ret;
573 va_list vargs;
574 va_start(vargs, format);
575 ret = vex_vprintf(format, vargs);
sewardj35421a32004-07-05 13:12:34 +0000576 va_end(vargs);
577
578 return ret;
579}
580
florianeebdb2b2014-12-10 16:08:09 +0000581/* Use this function to communicate to users that a (legitimate) situation
582 occured that we cannot handle (yet). */
583__attribute__ ((noreturn))
584void vfatal ( const HChar* format, ... )
585{
586 va_list vargs;
587 va_start(vargs, format);
588 vex_vprintf( format, vargs );
589 va_end(vargs);
590 vex_printf("Cannot continue. Good-bye\n\n");
591
592 (*vex_failure_exit)();
593}
sewardj35421a32004-07-05 13:12:34 +0000594
sewardj41f43bc2004-07-08 14:23:22 +0000595/* A general replacement for sprintf(). */
596
sewardj58277842005-02-07 03:11:17 +0000597static HChar *vg_sprintf_ptr;
sewardj41f43bc2004-07-08 14:23:22 +0000598
sewardj58277842005-02-07 03:11:17 +0000599static void add_to_vg_sprintf_buf ( HChar c )
sewardj41f43bc2004-07-08 14:23:22 +0000600{
601 *vg_sprintf_ptr++ = c;
602}
603
florian76714fd2012-09-13 20:21:42 +0000604UInt vex_sprintf ( HChar* buf, const HChar *format, ... )
sewardj41f43bc2004-07-08 14:23:22 +0000605{
606 Int ret;
607 va_list vargs;
608
609 vg_sprintf_ptr = buf;
610
611 va_start(vargs,format);
612
613 ret = vprintf_wrk ( add_to_vg_sprintf_buf, format, vargs );
614 add_to_vg_sprintf_buf(0);
615
616 va_end(vargs);
617
618 vassert(vex_strlen(buf) == ret);
619 return ret;
620}
621
622
sewardj35421a32004-07-05 13:12:34 +0000623/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +0000624/*--- end main_util.c ---*/
sewardj35421a32004-07-05 13:12:34 +0000625/*---------------------------------------------------------------*/