debug.cc revision 11793
16691Stjones1@inf.ed.ac.uk/* 26691Stjones1@inf.ed.ac.uk * Copyright (c) 2003-2005 The Regents of The University of Michigan 36691Stjones1@inf.ed.ac.uk * All rights reserved. 46691Stjones1@inf.ed.ac.uk * 56691Stjones1@inf.ed.ac.uk * Redistribution and use in source and binary forms, with or without 66691Stjones1@inf.ed.ac.uk * modification, are permitted provided that the following conditions are 76691Stjones1@inf.ed.ac.uk * met: redistributions of source code must retain the above copyright 86691Stjones1@inf.ed.ac.uk * notice, this list of conditions and the following disclaimer; 96691Stjones1@inf.ed.ac.uk * redistributions in binary form must reproduce the above copyright 106691Stjones1@inf.ed.ac.uk * notice, this list of conditions and the following disclaimer in the 116691Stjones1@inf.ed.ac.uk * documentation and/or other materials provided with the distribution; 126691Stjones1@inf.ed.ac.uk * neither the name of the copyright holders nor the names of its 136691Stjones1@inf.ed.ac.uk * contributors may be used to endorse or promote products derived from 146691Stjones1@inf.ed.ac.uk * this software without specific prior written permission. 156691Stjones1@inf.ed.ac.uk * 166691Stjones1@inf.ed.ac.uk * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176691Stjones1@inf.ed.ac.uk * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186691Stjones1@inf.ed.ac.uk * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196691Stjones1@inf.ed.ac.uk * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206691Stjones1@inf.ed.ac.uk * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216691Stjones1@inf.ed.ac.uk * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226691Stjones1@inf.ed.ac.uk * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236691Stjones1@inf.ed.ac.uk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246691Stjones1@inf.ed.ac.uk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256691Stjones1@inf.ed.ac.uk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266691Stjones1@inf.ed.ac.uk * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276691Stjones1@inf.ed.ac.uk * 286691Stjones1@inf.ed.ac.uk * Authors: Nathan Binkert 296691Stjones1@inf.ed.ac.uk */ 306691Stjones1@inf.ed.ac.uk 316691Stjones1@inf.ed.ac.uk#include "base/debug.hh" 326691Stjones1@inf.ed.ac.uk 336691Stjones1@inf.ed.ac.uk#include <sys/types.h> 346691Stjones1@inf.ed.ac.uk#include <unistd.h> 356691Stjones1@inf.ed.ac.uk 366691Stjones1@inf.ed.ac.uk#include <algorithm> 376691Stjones1@inf.ed.ac.uk#include <csignal> 386691Stjones1@inf.ed.ac.uk 396691Stjones1@inf.ed.ac.uk#include "base/cprintf.hh" 406691Stjones1@inf.ed.ac.uk#include "base/misc.hh" 416691Stjones1@inf.ed.ac.uk 426691Stjones1@inf.ed.ac.ukusing namespace std; 436691Stjones1@inf.ed.ac.uk 446691Stjones1@inf.ed.ac.uknamespace Debug { 456691Stjones1@inf.ed.ac.uk 466691Stjones1@inf.ed.ac.uk// 476691Stjones1@inf.ed.ac.uk// This function will cause the process to signal itself with a 486691Stjones1@inf.ed.ac.uk// SIGTRAP which is ignored if not in gdb, but will cause the debugger 496691Stjones1@inf.ed.ac.uk// to break if in gdb. 506691Stjones1@inf.ed.ac.uk// 516691Stjones1@inf.ed.ac.ukvoid 526691Stjones1@inf.ed.ac.ukbreakpoint() 536691Stjones1@inf.ed.ac.uk{ 546691Stjones1@inf.ed.ac.uk#ifndef NDEBUG 556691Stjones1@inf.ed.ac.uk kill(getpid(), SIGTRAP); 566691Stjones1@inf.ed.ac.uk#else 576691Stjones1@inf.ed.ac.uk cprintf("Debug::breakpoint suppressed, compiled with NDEBUG\n"); 586691Stjones1@inf.ed.ac.uk#endif 596691Stjones1@inf.ed.ac.uk} 606691Stjones1@inf.ed.ac.uk 616691Stjones1@inf.ed.ac.uk// 626691Stjones1@inf.ed.ac.uk// Flags for debugging purposes. Primarily for trace.hh 636691Stjones1@inf.ed.ac.uk// 646691Stjones1@inf.ed.ac.ukint allFlagsVersion = 0; 656691Stjones1@inf.ed.ac.ukFlagsMap & 666691Stjones1@inf.ed.ac.ukallFlags() 676691Stjones1@inf.ed.ac.uk{ 686691Stjones1@inf.ed.ac.uk static FlagsMap flags; 696691Stjones1@inf.ed.ac.uk return flags; 706691Stjones1@inf.ed.ac.uk} 716691Stjones1@inf.ed.ac.uk 726691Stjones1@inf.ed.ac.ukbool SimpleFlag::_active = false; 736691Stjones1@inf.ed.ac.uk 746691Stjones1@inf.ed.ac.ukFlag * 756691Stjones1@inf.ed.ac.ukfindFlag(const std::string &name) 766691Stjones1@inf.ed.ac.uk{ 776691Stjones1@inf.ed.ac.uk FlagsMap::iterator i = allFlags().find(name); 786691Stjones1@inf.ed.ac.uk if (i == allFlags().end()) 796691Stjones1@inf.ed.ac.uk return NULL; 806691Stjones1@inf.ed.ac.uk return i->second; 816691Stjones1@inf.ed.ac.uk} 826691Stjones1@inf.ed.ac.uk 836691Stjones1@inf.ed.ac.ukFlag::Flag(const char *name, const char *desc) 846691Stjones1@inf.ed.ac.uk : _name(name), _desc(desc) 856691Stjones1@inf.ed.ac.uk{ 866691Stjones1@inf.ed.ac.uk pair<FlagsMap::iterator, bool> result = 876691Stjones1@inf.ed.ac.uk allFlags().insert(make_pair(name, this)); 886691Stjones1@inf.ed.ac.uk 896691Stjones1@inf.ed.ac.uk if (!result.second) 906691Stjones1@inf.ed.ac.uk panic("Flag %s already defined!", name); 916691Stjones1@inf.ed.ac.uk 926691Stjones1@inf.ed.ac.uk ++allFlagsVersion; 936691Stjones1@inf.ed.ac.uk} 946691Stjones1@inf.ed.ac.uk 956691Stjones1@inf.ed.ac.ukFlag::~Flag() 966691Stjones1@inf.ed.ac.uk{ 976691Stjones1@inf.ed.ac.uk // should find and remove flag. 986691Stjones1@inf.ed.ac.uk} 996691Stjones1@inf.ed.ac.uk 1006691Stjones1@inf.ed.ac.ukvoid 1016691Stjones1@inf.ed.ac.ukSimpleFlag::enableAll() 1026691Stjones1@inf.ed.ac.uk{ 1036691Stjones1@inf.ed.ac.uk _active = true; 1046691Stjones1@inf.ed.ac.uk for (auto& i : allFlags()) 1056691Stjones1@inf.ed.ac.uk i.second->sync(); 1066691Stjones1@inf.ed.ac.uk} 1076691Stjones1@inf.ed.ac.uk 1086691Stjones1@inf.ed.ac.ukvoid 1096691Stjones1@inf.ed.ac.ukSimpleFlag::disableAll() 1106691Stjones1@inf.ed.ac.uk{ 1116691Stjones1@inf.ed.ac.uk _active = false; 1126691Stjones1@inf.ed.ac.uk for (auto& i : allFlags()) 1136691Stjones1@inf.ed.ac.uk i.second->sync(); 1146691Stjones1@inf.ed.ac.uk} 1156691Stjones1@inf.ed.ac.uk 1166691Stjones1@inf.ed.ac.ukvoid 1176691Stjones1@inf.ed.ac.ukCompoundFlag::enable() 1186691Stjones1@inf.ed.ac.uk{ 1196691Stjones1@inf.ed.ac.uk for (auto& k : _kids) 1206691Stjones1@inf.ed.ac.uk k->enable(); 1216691Stjones1@inf.ed.ac.uk} 1226691Stjones1@inf.ed.ac.uk 1236691Stjones1@inf.ed.ac.ukvoid 1246691Stjones1@inf.ed.ac.ukCompoundFlag::disable() 1256691Stjones1@inf.ed.ac.uk{ 1266691Stjones1@inf.ed.ac.uk for (auto& k : _kids) 1276691Stjones1@inf.ed.ac.uk k->disable(); 1286691Stjones1@inf.ed.ac.uk} 1296691Stjones1@inf.ed.ac.uk 1306691Stjones1@inf.ed.ac.ukstruct AllFlags : public Flag 1316691Stjones1@inf.ed.ac.uk{ 1326691Stjones1@inf.ed.ac.uk AllFlags() 1336691Stjones1@inf.ed.ac.uk : Flag("All", "All Flags") 1346691Stjones1@inf.ed.ac.uk {} 1356691Stjones1@inf.ed.ac.uk 1366691Stjones1@inf.ed.ac.uk void 1376691Stjones1@inf.ed.ac.uk enable() 1386691Stjones1@inf.ed.ac.uk { 1396691Stjones1@inf.ed.ac.uk FlagsMap::iterator i = allFlags().begin(); 1406691Stjones1@inf.ed.ac.uk FlagsMap::iterator end = allFlags().end(); 1416691Stjones1@inf.ed.ac.uk for (; i != end; ++i) 1426691Stjones1@inf.ed.ac.uk if (i->second != this) 1436691Stjones1@inf.ed.ac.uk i->second->enable(); 1446691Stjones1@inf.ed.ac.uk } 1456691Stjones1@inf.ed.ac.uk 1466691Stjones1@inf.ed.ac.uk void 1476691Stjones1@inf.ed.ac.uk disable() 1486691Stjones1@inf.ed.ac.uk { 1496691Stjones1@inf.ed.ac.uk FlagsMap::iterator i = allFlags().begin(); 1506691Stjones1@inf.ed.ac.uk FlagsMap::iterator end = allFlags().end(); 1516691Stjones1@inf.ed.ac.uk for (; i != end; ++i) 1526691Stjones1@inf.ed.ac.uk if (i->second != this) 1536691Stjones1@inf.ed.ac.uk i->second->disable(); 1546691Stjones1@inf.ed.ac.uk } 1556691Stjones1@inf.ed.ac.uk}; 1566691Stjones1@inf.ed.ac.uk 1576691Stjones1@inf.ed.ac.ukAllFlags theAllFlags; 1586691Stjones1@inf.ed.ac.ukFlag *const All = &theAllFlags; 159 160bool 161changeFlag(const char *s, bool value) 162{ 163 Flag *f = findFlag(s); 164 if (!f) 165 return false; 166 167 if (value) 168 f->enable(); 169 else 170 f->disable(); 171 172 return true; 173} 174 175} // namespace Debug 176 177// add a set of functions that can easily be invoked from gdb 178void 179setDebugFlag(const char *string) 180{ 181 Debug::changeFlag(string, true); 182} 183 184void 185clearDebugFlag(const char *string) 186{ 187 Debug::changeFlag(string, false); 188} 189 190void 191dumpDebugFlags() 192{ 193 using namespace Debug; 194 FlagsMap::iterator i = allFlags().begin(); 195 FlagsMap::iterator end = allFlags().end(); 196 for (; i != end; ++i) { 197 SimpleFlag *f = dynamic_cast<SimpleFlag *>(i->second); 198 if (f && f->status()) 199 cprintf("%s\n", f->name()); 200 } 201} 202