135421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
235421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/*---------------------------------------------------------------*/
3752f90673ebbb6b2f55fc5e46606dea371313713sewardj/*--- begin                                       main_util.c ---*/
435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/*---------------------------------------------------------------*/
535421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
6f8ed9d874a7b8651654591c68c6d431c758d787csewardj/*
7752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This file is part of Valgrind, a dynamic binary instrumentation
8752f90673ebbb6b2f55fc5e46606dea371313713sewardj   framework.
9f8ed9d874a7b8651654591c68c6d431c758d787csewardj
10ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes   Copyright (C) 2004-2017 OpenWorks LLP
11752f90673ebbb6b2f55fc5e46606dea371313713sewardj      info@open-works.net
127bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
13752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This program is free software; you can redistribute it and/or
14752f90673ebbb6b2f55fc5e46606dea371313713sewardj   modify it under the terms of the GNU General Public License as
15752f90673ebbb6b2f55fc5e46606dea371313713sewardj   published by the Free Software Foundation; either version 2 of the
16752f90673ebbb6b2f55fc5e46606dea371313713sewardj   License, or (at your option) any later version.
177bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
18752f90673ebbb6b2f55fc5e46606dea371313713sewardj   This program is distributed in the hope that it will be useful, but
19752f90673ebbb6b2f55fc5e46606dea371313713sewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
20752f90673ebbb6b2f55fc5e46606dea371313713sewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21752f90673ebbb6b2f55fc5e46606dea371313713sewardj   General Public License for more details.
22752f90673ebbb6b2f55fc5e46606dea371313713sewardj
23752f90673ebbb6b2f55fc5e46606dea371313713sewardj   You should have received a copy of the GNU General Public License
24752f90673ebbb6b2f55fc5e46606dea371313713sewardj   along with this program; if not, write to the Free Software
25752f90673ebbb6b2f55fc5e46606dea371313713sewardj   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
267bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj   02110-1301, USA.
277bd6ffe203f3aa9e7b25f7eae40a9b9cf48710cfsewardj
28752f90673ebbb6b2f55fc5e46606dea371313713sewardj   The GNU General Public License is contained in the file COPYING.
29f8ed9d874a7b8651654591c68c6d431c758d787csewardj
30f8ed9d874a7b8651654591c68c6d431c758d787csewardj   Neither the names of the U.S. Department of Energy nor the
31f8ed9d874a7b8651654591c68c6d431c758d787csewardj   University of California nor the names of its contributors may be
32f8ed9d874a7b8651654591c68c6d431c758d787csewardj   used to endorse or promote products derived from this software
33f8ed9d874a7b8651654591c68c6d431c758d787csewardj   without prior written permission.
34f8ed9d874a7b8651654591c68c6d431c758d787csewardj*/
35f8ed9d874a7b8651654591c68c6d431c758d787csewardj
36887a11a609f3e61d2ae8fe4e67f176207715da7esewardj#include "libvex_basictypes.h"
3741f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj#include "libvex.h"
3841f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj
39cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "main_globals.h"
40cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj#include "main_util.h"
4135421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
4235421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
4335421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/*---------------------------------------------------------*/
4435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/*--- Storage                                           ---*/
4535421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/*---------------------------------------------------------*/
4635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
47ce605f986c5b7e54322c44d722a4e71f6b37a365sewardj/* Try to keep this as low as possible -- in particular, less than the
48ce605f986c5b7e54322c44d722a4e71f6b37a365sewardj   size of the smallest L2 cache we might encounter.  At 50000, my VIA
49ce605f986c5b7e54322c44d722a4e71f6b37a365sewardj   Nehemiah 1 GHz (a weedy machine) can satisfy 27 million calls/
50ce605f986c5b7e54322c44d722a4e71f6b37a365sewardj   second to LibVEX_Alloc(16) -- that is, allocate memory at over 400
51ce605f986c5b7e54322c44d722a4e71f6b37a365sewardj   MByte/sec.  Once the size increases enough to fall out of the cache
52ce605f986c5b7e54322c44d722a4e71f6b37a365sewardj   into memory, the rate falls by about a factor of 3.
53ce605f986c5b7e54322c44d722a4e71f6b37a365sewardj*/
54d749c7a34da29d8a475d7ff4c4eeb333b9c9d263florian
55e165a8ac12b8eb79c6a414258d0c21faa76ce459sewardj#define N_TEMPORARY_BYTES 5000000
56443cd9d34617dd7608e5dd4b4b0b4674d4f433e7sewardj
57d749c7a34da29d8a475d7ff4c4eeb333b9c9d263florianstatic HChar  temporary[N_TEMPORARY_BYTES] __attribute__((aligned(REQ_ALIGN)));
582d6b14aa64df2ff85f8da143516779d5d43574cbsewardjstatic HChar* temporary_first = &temporary[0];
592d6b14aa64df2ff85f8da143516779d5d43574cbsewardjstatic HChar* temporary_curr  = &temporary[0];
602d6b14aa64df2ff85f8da143516779d5d43574cbsewardjstatic HChar* temporary_last  = &temporary[N_TEMPORARY_BYTES-1];
61443cd9d34617dd7608e5dd4b4b0b4674d4f433e7sewardj
622d6b14aa64df2ff85f8da143516779d5d43574cbsewardjstatic ULong  temporary_bytes_allocd_TOT = 0;
63443cd9d34617dd7608e5dd4b4b0b4674d4f433e7sewardj
64e29a31da9dcd4665c612a3d07cccf2c9a83f7ff5sewardj#define N_PERMANENT_BYTES 10000
6535421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
66d749c7a34da29d8a475d7ff4c4eeb333b9c9d263florianstatic HChar  permanent[N_PERMANENT_BYTES] __attribute__((aligned(REQ_ALIGN)));
672d6b14aa64df2ff85f8da143516779d5d43574cbsewardjstatic HChar* permanent_first = &permanent[0];
682d6b14aa64df2ff85f8da143516779d5d43574cbsewardjstatic HChar* permanent_curr  = &permanent[0];
69e29a31da9dcd4665c612a3d07cccf2c9a83f7ff5sewardjstatic HChar* permanent_last  = &permanent[N_PERMANENT_BYTES-1];
7035421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
71d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florianHChar* private_LibVEX_alloc_first = &temporary[0];
72d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florianHChar* private_LibVEX_alloc_curr  = &temporary[0];
73d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florianHChar* private_LibVEX_alloc_last  = &temporary[N_TEMPORARY_BYTES-1];
74bde340633ae5d586ad1e46b7d8989353f3870f10florian
75bde340633ae5d586ad1e46b7d8989353f3870f10florian
762d6b14aa64df2ff85f8da143516779d5d43574cbsewardjstatic VexAllocMode mode = VexAllocModeTEMP;
77443cd9d34617dd7608e5dd4b4b0b4674d4f433e7sewardj
782d6b14aa64df2ff85f8da143516779d5d43574cbsewardjvoid vexAllocSanityCheck ( void )
792d6b14aa64df2ff85f8da143516779d5d43574cbsewardj{
802d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(temporary_first == &temporary[0]);
812d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(temporary_last  == &temporary[N_TEMPORARY_BYTES-1]);
822d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(permanent_first == &permanent[0]);
83e29a31da9dcd4665c612a3d07cccf2c9a83f7ff5sewardj   vassert(permanent_last  == &permanent[N_PERMANENT_BYTES-1]);
842d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(temporary_first <= temporary_curr);
852d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(temporary_curr  <= temporary_last);
862d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(permanent_first <= permanent_curr);
872d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(permanent_curr  <= permanent_last);
882d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(private_LibVEX_alloc_first <= private_LibVEX_alloc_curr);
892d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(private_LibVEX_alloc_curr  <= private_LibVEX_alloc_last);
902d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   if (mode == VexAllocModeTEMP){
912d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      vassert(private_LibVEX_alloc_first == temporary_first);
922d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      vassert(private_LibVEX_alloc_last  == temporary_last);
932d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   }
942d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   else
952d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   if (mode == VexAllocModePERM) {
962d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      vassert(private_LibVEX_alloc_first == permanent_first);
972d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      vassert(private_LibVEX_alloc_last  == permanent_last);
982d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   }
992d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   else
1002d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      vassert(0);
1012d6b14aa64df2ff85f8da143516779d5d43574cbsewardj
1022d6b14aa64df2ff85f8da143516779d5d43574cbsewardj#  define IS_WORD_ALIGNED(p)   (0 == (((HWord)p) & (sizeof(HWord)-1)))
1032d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(sizeof(HWord) == 4 || sizeof(HWord) == 8);
1042d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(IS_WORD_ALIGNED(temporary_first));
1052d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(IS_WORD_ALIGNED(temporary_curr));
1062d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(IS_WORD_ALIGNED(temporary_last+1));
1072d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(IS_WORD_ALIGNED(permanent_first));
1082d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(IS_WORD_ALIGNED(permanent_curr));
1092d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(IS_WORD_ALIGNED(permanent_last+1));
1102d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_first));
1112d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_curr));
1122d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vassert(IS_WORD_ALIGNED(private_LibVEX_alloc_last+1));
1132d6b14aa64df2ff85f8da143516779d5d43574cbsewardj#  undef IS_WORD_ALIGNED
1142d6b14aa64df2ff85f8da143516779d5d43574cbsewardj}
115ce605f986c5b7e54322c44d722a4e71f6b37a365sewardj
116443cd9d34617dd7608e5dd4b4b0b4674d4f433e7sewardj/* The current allocation mode. */
117ce605f986c5b7e54322c44d722a4e71f6b37a365sewardj
118d887b8634b2c2685f528bd968459c628e8f86a34sewardjvoid vexSetAllocMode ( VexAllocMode m )
119443cd9d34617dd7608e5dd4b4b0b4674d4f433e7sewardj{
1202d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vexAllocSanityCheck();
1212d6b14aa64df2ff85f8da143516779d5d43574cbsewardj
1222d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   /* Save away the current allocation point .. */
1232d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   if (mode == VexAllocModeTEMP){
1242d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      temporary_curr = private_LibVEX_alloc_curr;
1252d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   }
1262d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   else
1272d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   if (mode == VexAllocModePERM) {
1282d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      permanent_curr = private_LibVEX_alloc_curr;
1292d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   }
1302d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   else
1312d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      vassert(0);
1322d6b14aa64df2ff85f8da143516779d5d43574cbsewardj
1332d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   /* Did that screw anything up? */
1342d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vexAllocSanityCheck();
1352d6b14aa64df2ff85f8da143516779d5d43574cbsewardj
1362d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   if (m == VexAllocModeTEMP){
1372d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      private_LibVEX_alloc_first = temporary_first;
1382d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      private_LibVEX_alloc_curr  = temporary_curr;
1392d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      private_LibVEX_alloc_last  = temporary_last;
1402d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   }
1412d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   else
1422d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   if (m == VexAllocModePERM) {
1432d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      private_LibVEX_alloc_first = permanent_first;
1442d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      private_LibVEX_alloc_curr  = permanent_curr;
1452d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      private_LibVEX_alloc_last  = permanent_last;
1462d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   }
1472d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   else
1482d6b14aa64df2ff85f8da143516779d5d43574cbsewardj      vassert(0);
1492d6b14aa64df2ff85f8da143516779d5d43574cbsewardj
150443cd9d34617dd7608e5dd4b4b0b4674d4f433e7sewardj   mode = m;
151443cd9d34617dd7608e5dd4b4b0b4674d4f433e7sewardj}
152443cd9d34617dd7608e5dd4b4b0b4674d4f433e7sewardj
153d887b8634b2c2685f528bd968459c628e8f86a34sewardjVexAllocMode vexGetAllocMode ( void )
154443cd9d34617dd7608e5dd4b4b0b4674d4f433e7sewardj{
155443cd9d34617dd7608e5dd4b4b0b4674d4f433e7sewardj   return mode;
156443cd9d34617dd7608e5dd4b4b0b4674d4f433e7sewardj}
157ce605f986c5b7e54322c44d722a4e71f6b37a365sewardj
1582d6b14aa64df2ff85f8da143516779d5d43574cbsewardj__attribute__((noreturn))
159d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florianvoid private_LibVEX_alloc_OOM(void)
16035421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj{
16155085f8680acc89d727e321f3b34cae1a8c4093aflorian   const HChar* pool = "???";
1622d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   if (private_LibVEX_alloc_first == &temporary[0]) pool = "TEMP";
1632d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   if (private_LibVEX_alloc_first == &permanent[0]) pool = "PERM";
1642d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vex_printf("VEX temporary storage exhausted.\n");
16566afb9fb536ec22d535d27063424f7e9672d75a0sewardj   vex_printf("Pool = %s,  start %p curr %p end %p (size %lld)\n",
1662d6b14aa64df2ff85f8da143516779d5d43574cbsewardj              pool,
1672d6b14aa64df2ff85f8da143516779d5d43574cbsewardj              private_LibVEX_alloc_first,
1682d6b14aa64df2ff85f8da143516779d5d43574cbsewardj              private_LibVEX_alloc_curr,
1692d6b14aa64df2ff85f8da143516779d5d43574cbsewardj              private_LibVEX_alloc_last,
170e29a31da9dcd4665c612a3d07cccf2c9a83f7ff5sewardj              (Long)(private_LibVEX_alloc_last + 1 - private_LibVEX_alloc_first));
1712d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vpanic("VEX temporary storage exhausted.\n"
1722d6b14aa64df2ff85f8da143516779d5d43574cbsewardj          "Increase N_{TEMPORARY,PERMANENT}_BYTES and recompile.");
17335421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj}
17435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
1752d6b14aa64df2ff85f8da143516779d5d43574cbsewardjvoid vexSetAllocModeTEMP_and_clear ( void )
17635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj{
1777df596b1e36840e2d74c90aa55589934add61ccfsewardj   /* vassert(vex_initdone); */ /* causes infinite assert loops */
1782d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   temporary_bytes_allocd_TOT
17966afb9fb536ec22d535d27063424f7e9672d75a0sewardj      += (ULong)(private_LibVEX_alloc_curr - private_LibVEX_alloc_first);
1802d6b14aa64df2ff85f8da143516779d5d43574cbsewardj
1812d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   mode = VexAllocModeTEMP;
1822d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   temporary_curr            = &temporary[0];
1832d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   private_LibVEX_alloc_curr = &temporary[0];
1848688a7278ae7a5dd1f777cc027824981f14b9ce3sewardj
1858688a7278ae7a5dd1f777cc027824981f14b9ce3sewardj   /* Set to (1) and change the fill byte to 0x00 or 0xFF to test for
1868688a7278ae7a5dd1f777cc027824981f14b9ce3sewardj      any potential bugs due to using uninitialised memory in the main
1878688a7278ae7a5dd1f777cc027824981f14b9ce3sewardj      VEX storage area. */
1888688a7278ae7a5dd1f777cc027824981f14b9ce3sewardj   if (0) {
1898688a7278ae7a5dd1f777cc027824981f14b9ce3sewardj      Int i;
1908688a7278ae7a5dd1f777cc027824981f14b9ce3sewardj      for (i = 0; i < N_TEMPORARY_BYTES; i++)
1918688a7278ae7a5dd1f777cc027824981f14b9ce3sewardj         temporary[i] = 0x00;
1928688a7278ae7a5dd1f777cc027824981f14b9ce3sewardj   }
1938688a7278ae7a5dd1f777cc027824981f14b9ce3sewardj
1942d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vexAllocSanityCheck();
19535421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj}
19635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
19735421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
198d887b8634b2c2685f528bd968459c628e8f86a34sewardj/* Exported to library client. */
199d887b8634b2c2685f528bd968459c628e8f86a34sewardj
200d887b8634b2c2685f528bd968459c628e8f86a34sewardjvoid LibVEX_ShowAllocStats ( void )
201d887b8634b2c2685f528bd968459c628e8f86a34sewardj{
2022d6b14aa64df2ff85f8da143516779d5d43574cbsewardj   vex_printf("vex storage: T total %lld bytes allocated\n",
2032d6b14aa64df2ff85f8da143516779d5d43574cbsewardj              (Long)temporary_bytes_allocd_TOT );
204e29a31da9dcd4665c612a3d07cccf2c9a83f7ff5sewardj   vex_printf("vex storage: P total %lld bytes allocated\n",
205e29a31da9dcd4665c612a3d07cccf2c9a83f7ff5sewardj              (Long)(permanent_curr - permanent_first) );
206d887b8634b2c2685f528bd968459c628e8f86a34sewardj}
207d887b8634b2c2685f528bd968459c628e8f86a34sewardj
208d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florianvoid *LibVEX_Alloc ( SizeT nbytes )
209d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian{
210d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian   return LibVEX_Alloc_inline(nbytes);
211d8e3ecaede8eccf5bc7be2a55d99a188a07b0a34florian}
21235421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
21335421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/*---------------------------------------------------------*/
21435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/*--- Bombing out                                       ---*/
21535421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/*---------------------------------------------------------*/
21635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
21735421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj__attribute__ ((noreturn))
2185827784e6bb74e2a032b66ec310776c24fd88729sewardjvoid vex_assert_fail ( const HChar* expr,
2195827784e6bb74e2a032b66ec310776c24fd88729sewardj                       const HChar* file, Int line, const HChar* fn )
22035421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj{
22135421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   vex_printf( "\nvex: %s:%d (%s): Assertion `%s' failed.\n",
22235421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj               file, line, fn, expr );
22335421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   (*vex_failure_exit)();
22435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj}
22535421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
226eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian/* To be used in assert-like (i.e. should never ever happen) situations */
22735421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj__attribute__ ((noreturn))
22876714fdcf200b71609ab5b79aaef11c37c7b8912florianvoid vpanic ( const HChar* str )
22935421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj{
23035421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   vex_printf("\nvex: the `impossible' happened:\n   %s\n", str);
23135421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   (*vex_failure_exit)();
23235421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj}
23335421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
23435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
23535421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/*---------------------------------------------------------*/
23635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/*--- vex_printf                                        ---*/
23735421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/*---------------------------------------------------------*/
23835421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
23935421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/* This should be the only <...> include in the entire VEX library.
24035421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   New code for vex_util.c should go above this point. */
24135421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj#include <stdarg.h>
24235421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
24304fc6b1eab791c7387b81b9fd820f4ae6aaf90a2florianSizeT vex_strlen ( const HChar* str )
24435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj{
24504fc6b1eab791c7387b81b9fd820f4ae6aaf90a2florian   SizeT i = 0;
24635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   while (str[i] != 0) i++;
24735421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   return i;
24835421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj}
24935421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
2505827784e6bb74e2a032b66ec310776c24fd88729sewardjBool vex_streq ( const HChar* s1, const HChar* s2 )
25136ca51378f8851635df814230fa23f2c409b9eddsewardj{
25236ca51378f8851635df814230fa23f2c409b9eddsewardj   while (True) {
25336ca51378f8851635df814230fa23f2c409b9eddsewardj      if (*s1 == 0 && *s2 == 0)
25436ca51378f8851635df814230fa23f2c409b9eddsewardj         return True;
25536ca51378f8851635df814230fa23f2c409b9eddsewardj      if (*s1 != *s2)
25636ca51378f8851635df814230fa23f2c409b9eddsewardj         return False;
25736ca51378f8851635df814230fa23f2c409b9eddsewardj      s1++;
25836ca51378f8851635df814230fa23f2c409b9eddsewardj      s2++;
25936ca51378f8851635df814230fa23f2c409b9eddsewardj   }
26036ca51378f8851635df814230fa23f2c409b9eddsewardj}
26135421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
26204fc6b1eab791c7387b81b9fd820f4ae6aaf90a2florianvoid vex_bzero ( void* sV, SizeT n )
263c9069f2908814843e9a4da00da9c8905440195a6sewardj{
26404fc6b1eab791c7387b81b9fd820f4ae6aaf90a2florian   SizeT i;
265c9069f2908814843e9a4da00da9c8905440195a6sewardj   UChar* s = (UChar*)sV;
266c9069f2908814843e9a4da00da9c8905440195a6sewardj   /* No laughing, please.  Just don't call this too often.  Thank you
267c9069f2908814843e9a4da00da9c8905440195a6sewardj      for your attention. */
268c9069f2908814843e9a4da00da9c8905440195a6sewardj   for (i = 0; i < n; i++) s[i] = 0;
269c9069f2908814843e9a4da00da9c8905440195a6sewardj}
270c9069f2908814843e9a4da00da9c8905440195a6sewardj
27135421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
272da46fdd3b076e02b0171b2371685bad99869dc66sewardj/* Convert N0 into ascii in BUF, which is assumed to be big enough (at
273da46fdd3b076e02b0171b2371685bad99869dc66sewardj   least 67 bytes long).  Observe BASE, SYNED and HEXCAPS. */
274da46fdd3b076e02b0171b2371685bad99869dc66sewardjstatic
275da46fdd3b076e02b0171b2371685bad99869dc66sewardjvoid convert_int ( /*OUT*/HChar* buf, Long n0,
276da46fdd3b076e02b0171b2371685bad99869dc66sewardj                   Int base, Bool syned, Bool hexcaps )
277da46fdd3b076e02b0171b2371685bad99869dc66sewardj{
278da46fdd3b076e02b0171b2371685bad99869dc66sewardj   ULong u0;
279da46fdd3b076e02b0171b2371685bad99869dc66sewardj   HChar c;
280da46fdd3b076e02b0171b2371685bad99869dc66sewardj   Bool minus = False;
281da46fdd3b076e02b0171b2371685bad99869dc66sewardj   Int i, j, bufi = 0;
282da46fdd3b076e02b0171b2371685bad99869dc66sewardj   buf[bufi] = 0;
283da46fdd3b076e02b0171b2371685bad99869dc66sewardj
284da46fdd3b076e02b0171b2371685bad99869dc66sewardj   if (syned) {
285da46fdd3b076e02b0171b2371685bad99869dc66sewardj      if (n0 < 0) {
286da46fdd3b076e02b0171b2371685bad99869dc66sewardj         minus = True;
287da46fdd3b076e02b0171b2371685bad99869dc66sewardj         u0 = (ULong)(-n0);
288da46fdd3b076e02b0171b2371685bad99869dc66sewardj      } else {
289da46fdd3b076e02b0171b2371685bad99869dc66sewardj         u0 = (ULong)(n0);
290da46fdd3b076e02b0171b2371685bad99869dc66sewardj      }
291da46fdd3b076e02b0171b2371685bad99869dc66sewardj   } else {
292da46fdd3b076e02b0171b2371685bad99869dc66sewardj      u0 = (ULong)n0;
29335421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   }
29435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
295da46fdd3b076e02b0171b2371685bad99869dc66sewardj   while (1) {
296c7cd2142ff0172bd3702d0607426a8014d8842e5sewardj     buf[bufi++] = toHChar('0' + toUInt(u0 % base));
297da46fdd3b076e02b0171b2371685bad99869dc66sewardj     u0 /= base;
298da46fdd3b076e02b0171b2371685bad99869dc66sewardj     if (u0 == 0) break;
29935421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   }
300da46fdd3b076e02b0171b2371685bad99869dc66sewardj   if (minus)
301da46fdd3b076e02b0171b2371685bad99869dc66sewardj      buf[bufi++] = '-';
302da46fdd3b076e02b0171b2371685bad99869dc66sewardj
303da46fdd3b076e02b0171b2371685bad99869dc66sewardj   buf[bufi] = 0;
304da46fdd3b076e02b0171b2371685bad99869dc66sewardj   for (i = 0; i < bufi; i++)
305da46fdd3b076e02b0171b2371685bad99869dc66sewardj      if (buf[i] > '9')
306c7cd2142ff0172bd3702d0607426a8014d8842e5sewardj         buf[i] = toHChar(buf[i] + (hexcaps ? 'A' : 'a') - '9' - 1);
307da46fdd3b076e02b0171b2371685bad99869dc66sewardj
308da46fdd3b076e02b0171b2371685bad99869dc66sewardj   i = 0;
309da46fdd3b076e02b0171b2371685bad99869dc66sewardj   j = bufi-1;
310da46fdd3b076e02b0171b2371685bad99869dc66sewardj   while (i <= j) {
311da46fdd3b076e02b0171b2371685bad99869dc66sewardj      c = buf[i];
312da46fdd3b076e02b0171b2371685bad99869dc66sewardj      buf[i] = buf[j];
313da46fdd3b076e02b0171b2371685bad99869dc66sewardj      buf[j] = c;
314da46fdd3b076e02b0171b2371685bad99869dc66sewardj      i++;
315da46fdd3b076e02b0171b2371685bad99869dc66sewardj      j--;
31635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   }
31735421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj}
31835421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
31935421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
320da46fdd3b076e02b0171b2371685bad99869dc66sewardj/* A half-arsed and buggy, but good-enough, implementation of
321da46fdd3b076e02b0171b2371685bad99869dc66sewardj   printf. */
322da46fdd3b076e02b0171b2371685bad99869dc66sewardjstatic
323da46fdd3b076e02b0171b2371685bad99869dc66sewardjUInt vprintf_wrk ( void(*sink)(HChar),
32476714fdcf200b71609ab5b79aaef11c37c7b8912florian                   const HChar* format,
325da46fdd3b076e02b0171b2371685bad99869dc66sewardj                   va_list ap )
326da46fdd3b076e02b0171b2371685bad99869dc66sewardj{
327da46fdd3b076e02b0171b2371685bad99869dc66sewardj#  define PUT(_ch)  \
328da46fdd3b076e02b0171b2371685bad99869dc66sewardj      do { sink(_ch); nout++; } \
329da46fdd3b076e02b0171b2371685bad99869dc66sewardj      while (0)
33035421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
331da46fdd3b076e02b0171b2371685bad99869dc66sewardj#  define PAD(_n) \
332da46fdd3b076e02b0171b2371685bad99869dc66sewardj      do { Int _qq = (_n); for (; _qq > 0; _qq--) PUT(padchar); } \
333da46fdd3b076e02b0171b2371685bad99869dc66sewardj      while (0)
33435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
335da46fdd3b076e02b0171b2371685bad99869dc66sewardj#  define PUTSTR(_str) \
33655085f8680acc89d727e321f3b34cae1a8c4093aflorian      do { const HChar* _qq = _str; for (; *_qq; _qq++) PUT(*_qq); } \
337da46fdd3b076e02b0171b2371685bad99869dc66sewardj      while (0)
33835421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
33976714fdcf200b71609ab5b79aaef11c37c7b8912florian   const HChar* saved_format;
340c66ba6536adc89a69ed9caaf3c16d575b729e73cflorian   Bool   longlong, ljustify, is_sizet;
341da46fdd3b076e02b0171b2371685bad99869dc66sewardj   HChar  padchar;
34204fc6b1eab791c7387b81b9fd820f4ae6aaf90a2florian   Int    fwidth, nout, len1, len3;
34304fc6b1eab791c7387b81b9fd820f4ae6aaf90a2florian   SizeT  len2;
344da46fdd3b076e02b0171b2371685bad99869dc66sewardj   HChar  intbuf[100];  /* big enough for a 64-bit # in base 2 */
34535421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
346da46fdd3b076e02b0171b2371685bad99869dc66sewardj   nout = 0;
347da46fdd3b076e02b0171b2371685bad99869dc66sewardj   while (1) {
34835421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
349da46fdd3b076e02b0171b2371685bad99869dc66sewardj      if (!format)
35035421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj         break;
351da46fdd3b076e02b0171b2371685bad99869dc66sewardj      if (*format == 0)
352da46fdd3b076e02b0171b2371685bad99869dc66sewardj         break;
353da46fdd3b076e02b0171b2371685bad99869dc66sewardj
354da46fdd3b076e02b0171b2371685bad99869dc66sewardj      if (*format != '%') {
355da46fdd3b076e02b0171b2371685bad99869dc66sewardj         PUT(*format);
356da46fdd3b076e02b0171b2371685bad99869dc66sewardj         format++;
35735421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj         continue;
35835421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj      }
359da46fdd3b076e02b0171b2371685bad99869dc66sewardj
360da46fdd3b076e02b0171b2371685bad99869dc66sewardj      saved_format = format;
361c66ba6536adc89a69ed9caaf3c16d575b729e73cflorian      longlong = is_sizet = False;
362da46fdd3b076e02b0171b2371685bad99869dc66sewardj      ljustify = False;
363da46fdd3b076e02b0171b2371685bad99869dc66sewardj      padchar = ' ';
364da46fdd3b076e02b0171b2371685bad99869dc66sewardj      fwidth = 0;
365da46fdd3b076e02b0171b2371685bad99869dc66sewardj      format++;
366da46fdd3b076e02b0171b2371685bad99869dc66sewardj
367da46fdd3b076e02b0171b2371685bad99869dc66sewardj      if (*format == '-') {
368da46fdd3b076e02b0171b2371685bad99869dc66sewardj         format++;
369da46fdd3b076e02b0171b2371685bad99869dc66sewardj         ljustify = True;
37035421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj      }
371da46fdd3b076e02b0171b2371685bad99869dc66sewardj      if (*format == '0') {
372da46fdd3b076e02b0171b2371685bad99869dc66sewardj         format++;
373da46fdd3b076e02b0171b2371685bad99869dc66sewardj         padchar = '0';
37435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj      }
375473dc16b5a24914e11dbf884af25cd388a26eb11florian      if (*format == '*') {
376473dc16b5a24914e11dbf884af25cd388a26eb11florian         fwidth = va_arg(ap, Int);
37704fc6b1eab791c7387b81b9fd820f4ae6aaf90a2florian         vassert(fwidth >= 0);
378da46fdd3b076e02b0171b2371685bad99869dc66sewardj         format++;
379473dc16b5a24914e11dbf884af25cd388a26eb11florian      } else {
380473dc16b5a24914e11dbf884af25cd388a26eb11florian         while (*format >= '0' && *format <= '9') {
381473dc16b5a24914e11dbf884af25cd388a26eb11florian            fwidth = fwidth * 10 + (*format - '0');
382473dc16b5a24914e11dbf884af25cd388a26eb11florian            format++;
383473dc16b5a24914e11dbf884af25cd388a26eb11florian         }
38435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj      }
385da46fdd3b076e02b0171b2371685bad99869dc66sewardj      if (*format == 'l') {
386da46fdd3b076e02b0171b2371685bad99869dc66sewardj         format++;
387da46fdd3b076e02b0171b2371685bad99869dc66sewardj         if (*format == 'l') {
388da46fdd3b076e02b0171b2371685bad99869dc66sewardj            format++;
389c66ba6536adc89a69ed9caaf3c16d575b729e73cflorian            longlong = True;
390da46fdd3b076e02b0171b2371685bad99869dc66sewardj         }
391c66ba6536adc89a69ed9caaf3c16d575b729e73cflorian      } else if (*format == 'z') {
392c66ba6536adc89a69ed9caaf3c16d575b729e73cflorian         format++;
393c66ba6536adc89a69ed9caaf3c16d575b729e73cflorian         is_sizet = True;
39435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj      }
39535421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
396da46fdd3b076e02b0171b2371685bad99869dc66sewardj      switch (*format) {
397da46fdd3b076e02b0171b2371685bad99869dc66sewardj         case 's': {
39855085f8680acc89d727e321f3b34cae1a8c4093aflorian            const HChar* str = va_arg(ap, HChar*);
399da46fdd3b076e02b0171b2371685bad99869dc66sewardj            if (str == NULL)
400da46fdd3b076e02b0171b2371685bad99869dc66sewardj               str = "(null)";
401da46fdd3b076e02b0171b2371685bad99869dc66sewardj            len1 = len3 = 0;
402da46fdd3b076e02b0171b2371685bad99869dc66sewardj            len2 = vex_strlen(str);
4037d730cfce15157aa78b822aeb66a7fab13b12aa3cerion            if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
4047d730cfce15157aa78b822aeb66a7fab13b12aa3cerion                                 len3 = ljustify ? fwidth-len2 : 0; }
405da46fdd3b076e02b0171b2371685bad99869dc66sewardj            PAD(len1); PUTSTR(str); PAD(len3);
40635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj            break;
407da46fdd3b076e02b0171b2371685bad99869dc66sewardj         }
408da46fdd3b076e02b0171b2371685bad99869dc66sewardj         case 'c': {
409da46fdd3b076e02b0171b2371685bad99869dc66sewardj            HChar c = (HChar)va_arg(ap, int);
410da46fdd3b076e02b0171b2371685bad99869dc66sewardj            HChar str[2];
411da46fdd3b076e02b0171b2371685bad99869dc66sewardj            str[0] = c;
412da46fdd3b076e02b0171b2371685bad99869dc66sewardj            str[1] = 0;
413da46fdd3b076e02b0171b2371685bad99869dc66sewardj            len1 = len3 = 0;
414da46fdd3b076e02b0171b2371685bad99869dc66sewardj            len2 = vex_strlen(str);
4157d730cfce15157aa78b822aeb66a7fab13b12aa3cerion            if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
4167d730cfce15157aa78b822aeb66a7fab13b12aa3cerion                                 len3 = ljustify ? fwidth-len2 : 0; }
417da46fdd3b076e02b0171b2371685bad99869dc66sewardj            PAD(len1); PUTSTR(str); PAD(len3);
41835421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj            break;
419da46fdd3b076e02b0171b2371685bad99869dc66sewardj         }
420da46fdd3b076e02b0171b2371685bad99869dc66sewardj         case 'd': {
421da46fdd3b076e02b0171b2371685bad99869dc66sewardj            Long l;
422c66ba6536adc89a69ed9caaf3c16d575b729e73cflorian            vassert(is_sizet == False); // %zd is obscure; we don't allow it
423da46fdd3b076e02b0171b2371685bad99869dc66sewardj            if (longlong) {
424da46fdd3b076e02b0171b2371685bad99869dc66sewardj               l = va_arg(ap, Long);
425da46fdd3b076e02b0171b2371685bad99869dc66sewardj            } else {
426da46fdd3b076e02b0171b2371685bad99869dc66sewardj               l = (Long)va_arg(ap, Int);
427da46fdd3b076e02b0171b2371685bad99869dc66sewardj            }
428da46fdd3b076e02b0171b2371685bad99869dc66sewardj            convert_int(intbuf, l, 10/*base*/, True/*signed*/,
429da46fdd3b076e02b0171b2371685bad99869dc66sewardj                                False/*irrelevant*/);
430da46fdd3b076e02b0171b2371685bad99869dc66sewardj            len1 = len3 = 0;
431da46fdd3b076e02b0171b2371685bad99869dc66sewardj            len2 = vex_strlen(intbuf);
4327d730cfce15157aa78b822aeb66a7fab13b12aa3cerion            if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
4337d730cfce15157aa78b822aeb66a7fab13b12aa3cerion                                 len3 = ljustify ? fwidth-len2 : 0; }
434da46fdd3b076e02b0171b2371685bad99869dc66sewardj            PAD(len1); PUTSTR(intbuf); PAD(len3);
43535421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj            break;
436b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
437da46fdd3b076e02b0171b2371685bad99869dc66sewardj         case 'u':
438da46fdd3b076e02b0171b2371685bad99869dc66sewardj         case 'x':
439da46fdd3b076e02b0171b2371685bad99869dc66sewardj         case 'X': {
440da46fdd3b076e02b0171b2371685bad99869dc66sewardj            Int   base = *format == 'u' ? 10 : 16;
441da46fdd3b076e02b0171b2371685bad99869dc66sewardj            Bool  hexcaps = True; /* *format == 'X'; */
442da46fdd3b076e02b0171b2371685bad99869dc66sewardj            ULong l;
443c66ba6536adc89a69ed9caaf3c16d575b729e73cflorian            if (is_sizet) {
444c66ba6536adc89a69ed9caaf3c16d575b729e73cflorian               l = (ULong)va_arg(ap, SizeT);
445c66ba6536adc89a69ed9caaf3c16d575b729e73cflorian            } else if (longlong) {
446da46fdd3b076e02b0171b2371685bad99869dc66sewardj               l = va_arg(ap, ULong);
447da46fdd3b076e02b0171b2371685bad99869dc66sewardj            } else {
448da46fdd3b076e02b0171b2371685bad99869dc66sewardj               l = (ULong)va_arg(ap, UInt);
449b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            }
450da46fdd3b076e02b0171b2371685bad99869dc66sewardj            convert_int(intbuf, l, base, False/*unsigned*/, hexcaps);
451da46fdd3b076e02b0171b2371685bad99869dc66sewardj            len1 = len3 = 0;
452da46fdd3b076e02b0171b2371685bad99869dc66sewardj            len2 = vex_strlen(intbuf);
4537d730cfce15157aa78b822aeb66a7fab13b12aa3cerion            if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
4547d730cfce15157aa78b822aeb66a7fab13b12aa3cerion                                 len3 = ljustify ? fwidth-len2 : 0; }
455da46fdd3b076e02b0171b2371685bad99869dc66sewardj            PAD(len1); PUTSTR(intbuf); PAD(len3);
456da46fdd3b076e02b0171b2371685bad99869dc66sewardj            break;
457da46fdd3b076e02b0171b2371685bad99869dc66sewardj         }
458da46fdd3b076e02b0171b2371685bad99869dc66sewardj         case 'p':
459da46fdd3b076e02b0171b2371685bad99869dc66sewardj         case 'P': {
460c7cd2142ff0172bd3702d0607426a8014d8842e5sewardj            Bool hexcaps = toBool(*format == 'P');
46193a09742b0de3d61718882c2d999f64be402564dflorian            ULong l = (Addr)va_arg(ap, void*);
462da46fdd3b076e02b0171b2371685bad99869dc66sewardj            convert_int(intbuf, l, 16/*base*/, False/*unsigned*/, hexcaps);
463da46fdd3b076e02b0171b2371685bad99869dc66sewardj            len1 = len3 = 0;
464da46fdd3b076e02b0171b2371685bad99869dc66sewardj            len2 = vex_strlen(intbuf)+2;
4657d730cfce15157aa78b822aeb66a7fab13b12aa3cerion            if (fwidth > len2) { len1 = ljustify ? 0 : fwidth-len2;
4667d730cfce15157aa78b822aeb66a7fab13b12aa3cerion                                 len3 = ljustify ? fwidth-len2 : 0; }
467da46fdd3b076e02b0171b2371685bad99869dc66sewardj            PAD(len1); PUT('0'); PUT('x'); PUTSTR(intbuf); PAD(len3);
468b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion            break;
469b85e8bba97fdae7d892f7bfd12e4601307e4721dcerion         }
470eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         case '%': {
471eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            PUT('%');
472eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj            break;
473eb17e49565dd7867a56c8ba6e45fdca01a576bb3sewardj         }
47435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj         default:
475da46fdd3b076e02b0171b2371685bad99869dc66sewardj            /* no idea what it is.  Print the format literally and
476da46fdd3b076e02b0171b2371685bad99869dc66sewardj               move on. */
477da46fdd3b076e02b0171b2371685bad99869dc66sewardj            while (saved_format <= format) {
478da46fdd3b076e02b0171b2371685bad99869dc66sewardj               PUT(*saved_format);
479da46fdd3b076e02b0171b2371685bad99869dc66sewardj               saved_format++;
480da46fdd3b076e02b0171b2371685bad99869dc66sewardj            }
48135421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj            break;
48235421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj      }
483da46fdd3b076e02b0171b2371685bad99869dc66sewardj
484da46fdd3b076e02b0171b2371685bad99869dc66sewardj      format++;
485da46fdd3b076e02b0171b2371685bad99869dc66sewardj
48635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   }
487da46fdd3b076e02b0171b2371685bad99869dc66sewardj
488da46fdd3b076e02b0171b2371685bad99869dc66sewardj   return nout;
489da46fdd3b076e02b0171b2371685bad99869dc66sewardj
490da46fdd3b076e02b0171b2371685bad99869dc66sewardj#  undef PUT
491da46fdd3b076e02b0171b2371685bad99869dc66sewardj#  undef PAD
492da46fdd3b076e02b0171b2371685bad99869dc66sewardj#  undef PUTSTR
49335421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj}
49435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
49535421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
49635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/* A general replacement for printf().  Note that only low-level
49735421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   debugging info should be sent via here.  The official route is to
49835421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   to use vg_message().  This interface is deprecated.
49935421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj*/
5005827784e6bb74e2a032b66ec310776c24fd88729sewardjstatic HChar myprintf_buf[1000];
5015827784e6bb74e2a032b66ec310776c24fd88729sewardjstatic Int   n_myprintf_buf;
50235421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
5035827784e6bb74e2a032b66ec310776c24fd88729sewardjstatic void add_to_myprintf_buf ( HChar c )
50435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj{
505c7cd2142ff0172bd3702d0607426a8014d8842e5sewardj   Bool emit = toBool(c == '\n' || n_myprintf_buf >= 1000-10 /*paranoia*/);
506da46fdd3b076e02b0171b2371685bad99869dc66sewardj   myprintf_buf[n_myprintf_buf++] = c;
507da46fdd3b076e02b0171b2371685bad99869dc66sewardj   myprintf_buf[n_myprintf_buf] = 0;
508da46fdd3b076e02b0171b2371685bad99869dc66sewardj   if (emit) {
50935421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj      (*vex_log_bytes)( myprintf_buf, vex_strlen(myprintf_buf) );
51035421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj      n_myprintf_buf = 0;
511da46fdd3b076e02b0171b2371685bad99869dc66sewardj      myprintf_buf[n_myprintf_buf] = 0;
51235421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   }
51335421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj}
51435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
515eebdb2b9c85a2b925e4725657a2db9805f3fcde0florianstatic UInt vex_vprintf ( const HChar* format, va_list vargs )
51635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj{
51735421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   UInt ret;
51835421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
51935421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   n_myprintf_buf = 0;
52035421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   myprintf_buf[n_myprintf_buf] = 0;
52135421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   ret = vprintf_wrk ( add_to_myprintf_buf, format, vargs );
52235421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
52335421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   if (n_myprintf_buf > 0) {
52435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj      (*vex_log_bytes)( myprintf_buf, n_myprintf_buf );
52535421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   }
52635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
527eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian   return ret;
528eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian}
529eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian
530eebdb2b9c85a2b925e4725657a2db9805f3fcde0florianUInt vex_printf ( const HChar* format, ... )
531eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian{
532eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian   UInt ret;
533eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian   va_list vargs;
534eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian   va_start(vargs, format);
535eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian   ret = vex_vprintf(format, vargs);
53635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   va_end(vargs);
53735421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
53835421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj   return ret;
53935421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj}
54035421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
541eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian/* Use this function to communicate to users that a (legitimate) situation
542eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian   occured that we cannot handle (yet). */
543eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian__attribute__ ((noreturn))
544eebdb2b9c85a2b925e4725657a2db9805f3fcde0florianvoid vfatal ( const HChar* format, ... )
545eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian{
546eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian   va_list vargs;
547eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian   va_start(vargs, format);
548eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian   vex_vprintf( format, vargs );
549eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian   va_end(vargs);
550eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian   vex_printf("Cannot continue. Good-bye\n\n");
551eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian
552eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian   (*vex_failure_exit)();
553eebdb2b9c85a2b925e4725657a2db9805f3fcde0florian}
55435421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj
55541f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj/* A general replacement for sprintf(). */
55641f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj
5575827784e6bb74e2a032b66ec310776c24fd88729sewardjstatic HChar *vg_sprintf_ptr;
55841f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj
5595827784e6bb74e2a032b66ec310776c24fd88729sewardjstatic void add_to_vg_sprintf_buf ( HChar c )
56041f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj{
56141f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj   *vg_sprintf_ptr++ = c;
56241f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj}
56341f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj
56476714fdcf200b71609ab5b79aaef11c37c7b8912florianUInt vex_sprintf ( HChar* buf, const HChar *format, ... )
56541f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj{
56641f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj   Int ret;
56741f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj   va_list vargs;
56841f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj
56941f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj   vg_sprintf_ptr = buf;
57041f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj
57141f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj   va_start(vargs,format);
57241f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj
57341f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj   ret = vprintf_wrk ( add_to_vg_sprintf_buf, format, vargs );
57441f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj   add_to_vg_sprintf_buf(0);
57541f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj
57641f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj   va_end(vargs);
57741f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj
57841f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj   vassert(vex_strlen(buf) == ret);
57941f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj   return ret;
58041f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj}
58141f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj
58241f43bcdee3e150a74a2e8c8e3b5bc5f5fda3215sewardj
58348729060949c3c8e2cfdd9aae20df000dac279c0sewardj/*---------------------------------------------------------*/
58448729060949c3c8e2cfdd9aae20df000dac279c0sewardj/*--- Misaligned memory access support                  ---*/
58548729060949c3c8e2cfdd9aae20df000dac279c0sewardj/*---------------------------------------------------------*/
58648729060949c3c8e2cfdd9aae20df000dac279c0sewardj
58748729060949c3c8e2cfdd9aae20df000dac279c0sewardjUInt read_misaligned_UInt_LE ( void* addr )
58848729060949c3c8e2cfdd9aae20df000dac279c0sewardj{
58948729060949c3c8e2cfdd9aae20df000dac279c0sewardj   UChar* p = (UChar*)addr;
59048729060949c3c8e2cfdd9aae20df000dac279c0sewardj   UInt   w = 0;
59148729060949c3c8e2cfdd9aae20df000dac279c0sewardj   w = (w << 8) | p[3];
59248729060949c3c8e2cfdd9aae20df000dac279c0sewardj   w = (w << 8) | p[2];
59348729060949c3c8e2cfdd9aae20df000dac279c0sewardj   w = (w << 8) | p[1];
59448729060949c3c8e2cfdd9aae20df000dac279c0sewardj   w = (w << 8) | p[0];
59548729060949c3c8e2cfdd9aae20df000dac279c0sewardj   return w;
59648729060949c3c8e2cfdd9aae20df000dac279c0sewardj}
59748729060949c3c8e2cfdd9aae20df000dac279c0sewardj
59848729060949c3c8e2cfdd9aae20df000dac279c0sewardjULong read_misaligned_ULong_LE ( void* addr )
59948729060949c3c8e2cfdd9aae20df000dac279c0sewardj{
60048729060949c3c8e2cfdd9aae20df000dac279c0sewardj   UChar* p = (UChar*)addr;
60148729060949c3c8e2cfdd9aae20df000dac279c0sewardj   ULong  w = 0;
60248729060949c3c8e2cfdd9aae20df000dac279c0sewardj   w = (w << 8) | p[7];
60348729060949c3c8e2cfdd9aae20df000dac279c0sewardj   w = (w << 8) | p[6];
60448729060949c3c8e2cfdd9aae20df000dac279c0sewardj   w = (w << 8) | p[5];
60548729060949c3c8e2cfdd9aae20df000dac279c0sewardj   w = (w << 8) | p[4];
60648729060949c3c8e2cfdd9aae20df000dac279c0sewardj   w = (w << 8) | p[3];
60748729060949c3c8e2cfdd9aae20df000dac279c0sewardj   w = (w << 8) | p[2];
60848729060949c3c8e2cfdd9aae20df000dac279c0sewardj   w = (w << 8) | p[1];
60948729060949c3c8e2cfdd9aae20df000dac279c0sewardj   w = (w << 8) | p[0];
61048729060949c3c8e2cfdd9aae20df000dac279c0sewardj   return w;
61148729060949c3c8e2cfdd9aae20df000dac279c0sewardj}
61248729060949c3c8e2cfdd9aae20df000dac279c0sewardj
61348729060949c3c8e2cfdd9aae20df000dac279c0sewardjvoid write_misaligned_UInt_LE ( void* addr, UInt w )
61448729060949c3c8e2cfdd9aae20df000dac279c0sewardj{
61548729060949c3c8e2cfdd9aae20df000dac279c0sewardj   UChar* p = (UChar*)addr;
61648729060949c3c8e2cfdd9aae20df000dac279c0sewardj   p[0] = (w & 0xFF); w >>= 8;
61748729060949c3c8e2cfdd9aae20df000dac279c0sewardj   p[1] = (w & 0xFF); w >>= 8;
61848729060949c3c8e2cfdd9aae20df000dac279c0sewardj   p[2] = (w & 0xFF); w >>= 8;
61948729060949c3c8e2cfdd9aae20df000dac279c0sewardj   p[3] = (w & 0xFF); w >>= 8;
62048729060949c3c8e2cfdd9aae20df000dac279c0sewardj}
62148729060949c3c8e2cfdd9aae20df000dac279c0sewardj
62248729060949c3c8e2cfdd9aae20df000dac279c0sewardjvoid write_misaligned_ULong_LE ( void* addr, ULong w )
62348729060949c3c8e2cfdd9aae20df000dac279c0sewardj{
62448729060949c3c8e2cfdd9aae20df000dac279c0sewardj   UChar* p = (UChar*)addr;
62548729060949c3c8e2cfdd9aae20df000dac279c0sewardj   p[0] = (w & 0xFF); w >>= 8;
62648729060949c3c8e2cfdd9aae20df000dac279c0sewardj   p[1] = (w & 0xFF); w >>= 8;
62748729060949c3c8e2cfdd9aae20df000dac279c0sewardj   p[2] = (w & 0xFF); w >>= 8;
62848729060949c3c8e2cfdd9aae20df000dac279c0sewardj   p[3] = (w & 0xFF); w >>= 8;
62948729060949c3c8e2cfdd9aae20df000dac279c0sewardj   p[4] = (w & 0xFF); w >>= 8;
63048729060949c3c8e2cfdd9aae20df000dac279c0sewardj   p[5] = (w & 0xFF); w >>= 8;
63148729060949c3c8e2cfdd9aae20df000dac279c0sewardj   p[6] = (w & 0xFF); w >>= 8;
63248729060949c3c8e2cfdd9aae20df000dac279c0sewardj   p[7] = (w & 0xFF); w >>= 8;
63348729060949c3c8e2cfdd9aae20df000dac279c0sewardj}
63448729060949c3c8e2cfdd9aae20df000dac279c0sewardj
63548729060949c3c8e2cfdd9aae20df000dac279c0sewardj
63635421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/*---------------------------------------------------------------*/
637cef7d3e3df4796e35b4521158d9dc058f034aa87sewardj/*--- end                                         main_util.c ---*/
63835421a3cfd43bc829d27ee15bd34bbc7cb690805sewardj/*---------------------------------------------------------------*/
639