Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

690 lines
22 KiB

  1. //========= Copyright (c), Valve LLC, All rights reserved. ============
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #include "stdafx.h"
  8. #include "gcsystemaccess.h"
  9. #include "gcjob.h"
  10. #include "gcsdk/gcreportprinter.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. namespace GCSDK
  14. {
  15. static GCConVar gcaccess_enable( "gcaccess_enable", "1", "Kill switch that disables all gcaccess tracking and systems" );
  16. DECLARE_GC_EMIT_GROUP( g_EGAccess, access );
  17. //-----------------------------------------------------------------------------------------------------------------------------------------
  18. GCAccessSystem_t GenerateUniqueGCAccessID()
  19. {
  20. static GCAccessSystem_t s_nID = 0;
  21. return s_nID++;
  22. }
  23. //-----------------------------------------------------------------------------------------------------------------------------------------
  24. // CGCAccessSystem
  25. //-----------------------------------------------------------------------------------------------------------------------------------------
  26. //a GCAccess system that has been registered
  27. class CGCAccessSystem
  28. {
  29. public:
  30. //the name of the system for display
  31. CUtlString m_sName;
  32. //the unique ID for this system
  33. GCAccessSystem_t m_nID;
  34. //which actions should be enabled or disabled for this system in particular
  35. uint32 m_nActions;
  36. uint32 m_nSuppressActions;
  37. struct AccessStats_t
  38. {
  39. AccessStats_t();
  40. void Add( const AccessStats_t& rhs );
  41. //how many raw accesses have we had?
  42. uint32 m_nNumValid;
  43. //how many failed because the context didn't have rights?
  44. uint32 m_nNumFail;
  45. //how many failed because the associated ID wasn't valid?
  46. uint32 m_nNumFailID;
  47. };
  48. struct TrackedJob_t
  49. {
  50. CUtlString m_sContext;
  51. AccessStats_t m_Stats;
  52. };
  53. //which jobs have violated this system access rights
  54. CUtlHashMapLarge< uintp, TrackedJob_t > m_Jobs;
  55. };
  56. //-----------------------------------------------------------------------------------------------------------------------------------------
  57. // CGCAccessContext
  58. //-----------------------------------------------------------------------------------------------------------------------------------------
  59. CGCAccessContext::CGCAccessContext() :
  60. m_nActions( 0 ),
  61. m_nSuppressActions( 0 )
  62. {
  63. }
  64. void CGCAccessContext::Init( const char* pszName, uint32 nActions, uint32 nSuppressActions )
  65. {
  66. m_sName = pszName;
  67. m_nActions = nActions;
  68. m_nSuppressActions = nSuppressActions;
  69. }
  70. void CGCAccessContext::AddSystem( GCAccessSystem_t nSystem )
  71. {
  72. m_nSystems.InsertIfNotFound( nSystem );
  73. }
  74. bool CGCAccessContext::HasSystem( GCAccessSystem_t system ) const
  75. {
  76. return ( m_nSystems.Find( system ) != m_nSystems.InvalidIndex() );
  77. }
  78. bool CGCAccessContext::IsSubsetOf( const CGCAccessContext& context ) const
  79. {
  80. FOR_EACH_VEC( m_nSystems, nCurrSystem )
  81. {
  82. if( !context.HasSystem( m_nSystems[ nCurrSystem ] ) )
  83. return false;
  84. }
  85. return true;
  86. }
  87. void CGCAccessContext::AddSystemsFrom( const CGCAccessContext& context )
  88. {
  89. FOR_EACH_VEC( context.m_nSystems, nCurrSystem )
  90. {
  91. AddSystem( context.m_nSystems[ nCurrSystem ] );
  92. }
  93. }
  94. void CGCAccessContext::SetAction( EGCAccessAction eAction, bool bSet )
  95. {
  96. if( bSet )
  97. m_nActions |= eAction;
  98. else
  99. m_nActions &= ~( uint32 )eAction;
  100. }
  101. void CGCAccessContext::SetSuppressAction( EGCAccessAction eAction, bool bSet )
  102. {
  103. if( bSet )
  104. m_nSuppressActions |= eAction;
  105. else
  106. m_nSuppressActions &= ~( uint32 )eAction;
  107. }
  108. //-----------------------------------------------------------------------------------------------------------------------------------------
  109. // CGCAccess
  110. //-----------------------------------------------------------------------------------------------------------------------------------------
  111. static CGCAccess g_GCAccess;
  112. CGCAccess& GGCAccess()
  113. {
  114. return g_GCAccess;
  115. }
  116. CGCAccessSystem::AccessStats_t::AccessStats_t()
  117. : m_nNumFail( 0 )
  118. , m_nNumFailID( 0 )
  119. , m_nNumValid( 0 )
  120. {}
  121. void CGCAccessSystem::AccessStats_t::Add( const AccessStats_t& rhs )
  122. {
  123. m_nNumFail += rhs.m_nNumFail;
  124. m_nNumFailID += rhs.m_nNumFailID;
  125. m_nNumValid += rhs.m_nNumValid;
  126. }
  127. CGCAccess::CGCAccess() :
  128. m_nActions( GCAccessAction_TrackSuccess | GCAccessAction_TrackFail| GCAccessAction_ReturnFail ),
  129. m_nSuppressActions( 0 )
  130. {
  131. m_GlobalContext.Init( "Global" );
  132. }
  133. void CGCAccess::RegisterSystem( const char* pszName, GCAccessSystem_t nID, uint32 nActions, uint32 nSupressActions )
  134. {
  135. //make sure that we don't have a conflict
  136. int nIndex = m_Systems.Find( nID );
  137. if( nIndex != m_Systems.InvalidIndex() )
  138. {
  139. // !FIXME!
  140. // DOTAMERGE AssertMsg varargs
  141. AssertMsg3( false, "Multiple systems conflciting in Register System: ID %d, original: %s, new %s", nID, m_Systems[ nIndex ]->m_sName.String(), pszName );
  142. return;
  143. }
  144. CGCAccessSystem* pSystem = new CGCAccessSystem;
  145. pSystem->m_sName = pszName;
  146. pSystem->m_nID = nID;
  147. pSystem->m_nActions = nActions;
  148. pSystem->m_nSuppressActions = nSupressActions;
  149. m_Systems.Insert( nID, pSystem );
  150. }
  151. bool CGCAccess::ValidateAccess( GCAccessSystem_t nSystem )
  152. {
  153. //global kill switch
  154. if( !gcaccess_enable.GetBool() )
  155. return true;
  156. return InternalValidateAccess( nSystem, CSteamID(), CSteamID() );
  157. }
  158. bool CGCAccess::ValidateSteamIDAccess( GCAccessSystem_t nSystem, CSteamID steamID )
  159. {
  160. //global kill switch
  161. if( !gcaccess_enable.GetBool() )
  162. return true;
  163. CSteamID expectedID = ( g_pJobCur ) ? g_pJobCur->SOVALIDATE_GetSteamID() : steamID;
  164. return InternalValidateAccess( nSystem, steamID, expectedID );
  165. }
  166. bool CGCAccess::InternalValidateAccess( GCAccessSystem_t nSystem, CSteamID steamID, CSteamID expectedID )
  167. {
  168. //see if tracking for this system is disabled. This list is almost always empty, so just use a linear search for now.
  169. FOR_EACH_VEC( m_SuppressAccess, nAction )
  170. {
  171. if( m_SuppressAccess[ nAction ].m_nSystem == nSystem )
  172. return true;
  173. }
  174. //assume the global context
  175. const CGCAccessContext* pContext = &m_GlobalContext;
  176. const char* pszJobName = "[global]";
  177. //if we have a job, use it's context
  178. if( g_pJobCur )
  179. {
  180. const CGCJob* pJob = static_cast< const CGCJob* >( g_pJobCur );
  181. pszJobName = pJob->GetName();
  182. if( pJob->GetContext() )
  183. pContext = pJob->GetContext();
  184. }
  185. //is this a valid system to access
  186. bool bValidSteamID = ( steamID == expectedID );
  187. bool bValidSystem = pContext->HasSystem( nSystem );
  188. bool bValidAccess = ( bValidSystem && bValidSteamID );
  189. //determine the actions we want to do for tracking
  190. uint32 nActions = pContext->GetActions() | m_nActions;
  191. uint32 nSuppressActions = pContext->GetSuppressActions() | m_nSuppressActions;
  192. //look up the system that we are accessing
  193. CGCAccessSystem* pSystem = NULL;
  194. int nSystemIndex = m_Systems.Find( nSystem );
  195. if( nSystemIndex == m_Systems.InvalidIndex() )
  196. {
  197. // !FIXME! DOTAMERGE
  198. // AssertMsg varargs
  199. AssertMsg1( false, "Error: Tracking a system that has not been registered. Make sure to register system %u", nSystem );
  200. }
  201. else
  202. {
  203. //make sure that we have a stat entry for this job
  204. pSystem = m_Systems[ nSystemIndex ];
  205. nActions |= pSystem->m_nActions;
  206. nSuppressActions |= pSystem->m_nSuppressActions;
  207. }
  208. //remove any suppressed actions
  209. nActions &= ~nSuppressActions;
  210. //see if we need to track this access
  211. bool bTrackSuccess = ( nActions & GCAccessAction_TrackSuccess ) && bValidAccess;
  212. bool bTrackFail = ( nActions & GCAccessAction_TrackFail ) && !bValidAccess;
  213. if( ( bTrackSuccess || bTrackFail ) && pSystem )
  214. {
  215. //make sure that we have a stat entry for this job
  216. int nJobIndex = pSystem->m_Jobs.Find( ( uintp )pszJobName );
  217. if( nJobIndex == pSystem->m_Jobs.InvalidIndex() )
  218. {
  219. nJobIndex = pSystem->m_Jobs.Insert( ( uintp )pszJobName );
  220. pSystem->m_Jobs[ nJobIndex ].m_sContext = pContext->GetName();
  221. }
  222. //update our stats based upon what was valid and what wasn't
  223. CGCAccessSystem::AccessStats_t& stats = pSystem->m_Jobs[ nJobIndex ].m_Stats;
  224. if( bTrackSuccess )
  225. stats.m_nNumValid++;
  226. if( bTrackFail )
  227. {
  228. if( !bValidSteamID )
  229. stats.m_nNumFailID++;
  230. if( !bValidSystem )
  231. stats.m_nNumFail++;
  232. }
  233. }
  234. //see if this is a single access we want to try and track
  235. FOR_EACH_VEC( m_SingleAsserts, nCurrAssert )
  236. {
  237. SingleAssert_t* pAssert = m_SingleAsserts[ nCurrAssert ];
  238. if( nSystem == pAssert->m_System )
  239. {
  240. if( V_stricmp( ( pAssert->m_bContext ) ? pContext->GetName() : pszJobName, pAssert->m_sContextOrJob ) == 0 )
  241. {
  242. //log this assert
  243. {
  244. // !FIXME! DOTAMERGE
  245. //CGCInterface::CDisableAssertRateLimit disableAssertLimit;
  246. // !FIXME! DOTAMERGE
  247. // AssertMsg varargs
  248. AssertMsg3( false, "GCSystemAccess Caught %s (context %s) calling into %s", pszJobName, pContext->GetName(), pSystem ? pSystem->m_sName.String() : "unknown" );
  249. }
  250. //and clear it
  251. delete pAssert;
  252. m_SingleAsserts.FastRemove( nCurrAssert );
  253. }
  254. }
  255. }
  256. //at this point, if it is a valid access, just bail
  257. if( bValidAccess )
  258. return true;
  259. //otherwise, handle the failure case
  260. if( nActions & ( GCAccessAction_Msg | GCAccessAction_Assert ) )
  261. {
  262. int nSystemIndex = m_Systems.Find( nSystem );
  263. const char* pszSystem = ( nSystemIndex != m_Systems.InvalidIndex() ) ? m_Systems[ nSystemIndex ]->m_sName.String() : "<unregistered>";
  264. //display a message based upon if it was a system or ID violation
  265. CFmtStr1024 szMsg;
  266. if( !bValidSystem )
  267. {
  268. szMsg.sprintf( "Job %s Accessed invalid system %s (%u) while in context %s\n", pszJobName, pszSystem, nSystem, pContext->GetName() );
  269. }
  270. else
  271. {
  272. szMsg.sprintf( "Job %s Accessed invalid steam ID %s but expected %s in system %s (%u) while in context %s\n", pszJobName, steamID.RenderLink(), expectedID.RenderLink(), pszSystem, nSystem, pContext->GetName() );
  273. }
  274. if( nActions & GCAccessAction_Msg )
  275. EG_MSG( g_EGAccess, "%s", szMsg.String() );
  276. if( nActions & GCAccessAction_Assert )
  277. {
  278. // !FIXME! DOTAMERGE
  279. // AssertMsg varargs
  280. AssertMsg1( false, "%s", szMsg.String() );
  281. }
  282. }
  283. return !( nActions & GCAccessAction_ReturnFail );
  284. }
  285. void CGCAccess::SuppressAccess( GCAccessSystem_t nSystem, bool bEnable )
  286. {
  287. //see if it is an existing item already suppressed that we need to modify the ref count of
  288. FOR_EACH_VEC( m_SuppressAccess, nAccess )
  289. {
  290. if( m_SuppressAccess[ nAccess ].m_nSystem == nSystem )
  291. {
  292. if( bEnable )
  293. {
  294. //to enable, we want to decrease the disable count, or remove if we are fully re-enabled
  295. if( m_SuppressAccess[ nAccess ].m_nCount <= 1 )
  296. m_SuppressAccess.FastRemove( nAccess );
  297. else
  298. m_SuppressAccess[ nAccess ].m_nCount--;
  299. }
  300. else
  301. {
  302. m_SuppressAccess[ nAccess ].m_nCount++;
  303. }
  304. return;
  305. }
  306. }
  307. //only add it to the list if we are disabling
  308. if( !bEnable )
  309. {
  310. SuppressAccess_t access;
  311. access.m_nSystem = nSystem;
  312. access.m_nCount = 1;
  313. m_SuppressAccess.AddToTail( access );
  314. }
  315. }
  316. void CGCAccess::ClearSystemStats()
  317. {
  318. FOR_EACH_MAP_FAST( m_Systems, nSystem )
  319. {
  320. m_Systems[ nSystem ]->m_Jobs.Purge();
  321. }
  322. }
  323. bool CGCAccess::CatchSingleAssert( const char* pszSystem, bool bContext, const char* pszContextOrJob )
  324. {
  325. //find the system we are referencing so we don't add invalid breakpoints if we can avoid it
  326. GCAccessSystem_t nSystemID = ( GCAccessSystem_t )-1;
  327. FOR_EACH_MAP_FAST( m_Systems, nSystem )
  328. {
  329. if( V_stricmp( m_Systems[ nSystem ]->m_sName, pszSystem ) == 0 )
  330. {
  331. nSystemID = m_Systems.Key( nSystem );
  332. break;
  333. }
  334. }
  335. if( nSystemID == ( GCAccessSystem_t )-1 )
  336. return false;
  337. SingleAssert_t* pAssert = new SingleAssert_t;
  338. pAssert->m_System = nSystemID;
  339. pAssert->m_bContext = bContext;
  340. pAssert->m_sContextOrJob = pszContextOrJob;
  341. m_SingleAsserts.AddToTail( pAssert );
  342. return true;
  343. }
  344. void CGCAccess::ClearSingleAsserts()
  345. {
  346. m_SingleAsserts.PurgeAndDeleteElements();
  347. }
  348. //given a display type and a stats object, determines if it meets the criteria
  349. static bool ShouldDisplayStats( CGCAccess::EDisplay eDisplay, const CGCAccessSystem::AccessStats_t& stats )
  350. {
  351. if( eDisplay == CGCAccess::eDisplay_Referenced )
  352. return ( stats.m_nNumFail + stats.m_nNumFailID + stats.m_nNumValid ) > 0;
  353. if( eDisplay == CGCAccess::eDisplay_Violations )
  354. return ( stats.m_nNumFail + stats.m_nNumFailID ) > 0;
  355. if( eDisplay == CGCAccess::eDisplay_IDViolations )
  356. return stats.m_nNumFailID > 0;
  357. //unknown, so just assume all
  358. return true;
  359. }
  360. void CGCAccess::ReportJobs( const char* pszContext, EDisplay eDisplay ) const
  361. {
  362. //collect all of the job stats into a single summary table
  363. CUtlHashMapLarge< uintp, CGCAccessSystem::TrackedJob_t > jobs;
  364. FOR_EACH_MAP_FAST( m_Systems, nSystem )
  365. {
  366. const CGCAccessSystem* pSystem = m_Systems[ nSystem ];
  367. FOR_EACH_MAP_FAST( pSystem->m_Jobs, nJob )
  368. {
  369. const CGCAccessSystem::TrackedJob_t& job = pSystem->m_Jobs[ nJob ];
  370. //skip any contexts we don't care about
  371. if( pszContext && ( V_stricmp( pszContext, job.m_sContext ) != 0 ) )
  372. continue;
  373. if( !ShouldDisplayStats( eDisplay, job.m_Stats ) )
  374. continue;
  375. int nIndex = jobs.Find( pSystem->m_Jobs.Key( nJob ) );
  376. if( nIndex == jobs.InvalidIndex() )
  377. {
  378. nIndex = jobs.Insert( pSystem->m_Jobs.Key( nJob ) );
  379. jobs[ nIndex ].m_sContext = job.m_sContext;
  380. }
  381. jobs[ nIndex ].m_Stats.Add( job.m_Stats );
  382. }
  383. }
  384. CGCReportPrinter rp;
  385. rp.AddStringColumn( "Job" );
  386. rp.AddStringColumn( "Context" );
  387. rp.AddIntColumn( "Valid", CGCReportPrinter::eSummary_Total );
  388. rp.AddIntColumn( "Invalid", CGCReportPrinter::eSummary_Total );
  389. rp.AddIntColumn( "InvalidID", CGCReportPrinter::eSummary_Total );
  390. FOR_EACH_MAP_FAST( jobs, nJob )
  391. {
  392. rp.StrValue( ( const char* )jobs.Key( nJob ), CFmtStr( "gcaccess_dump_job \"%s\" %d", ( const char* )jobs.Key( nJob ), eDisplay ).String() );
  393. rp.StrValue( jobs[ nJob ].m_sContext, CFmtStr( "gcaccess_dump_context \"%s\" %d", jobs[ nJob ].m_sContext.String(), eDisplay ).String() );
  394. rp.IntValue( jobs[ nJob ].m_Stats.m_nNumValid );
  395. rp.IntValue( jobs[ nJob ].m_Stats.m_nNumFail );
  396. rp.IntValue( jobs[ nJob ].m_Stats.m_nNumFailID );
  397. rp.CommitRow();
  398. }
  399. rp.SortReport( "Job", false );
  400. rp.PrintReport( SPEW_CONSOLE );
  401. }
  402. void CGCAccess::ReportSystems( const char* pszContext, EDisplay eDisplay ) const
  403. {
  404. CGCReportPrinter rp;
  405. rp.AddStringColumn( "System" );
  406. rp.AddIntColumn( "ID", CGCReportPrinter::eSummary_None );
  407. rp.AddIntColumn( "Jobs", CGCReportPrinter::eSummary_None );
  408. rp.AddIntColumn( "Valid", CGCReportPrinter::eSummary_Total );
  409. rp.AddIntColumn( "Invalid", CGCReportPrinter::eSummary_Total );
  410. rp.AddIntColumn( "InvalidID", CGCReportPrinter::eSummary_Total );
  411. FOR_EACH_MAP_FAST( m_Systems, nSystem )
  412. {
  413. const CGCAccessSystem* pSystem = m_Systems[ nSystem ];
  414. CGCAccessSystem::AccessStats_t stats;
  415. FOR_EACH_MAP_FAST( pSystem->m_Jobs, nJob )
  416. {
  417. const CGCAccessSystem::TrackedJob_t& job = pSystem->m_Jobs[ nJob ];
  418. //skip any contexts we don't care about
  419. if( pszContext && ( V_stricmp( pszContext, job.m_sContext ) != 0 ) )
  420. continue;
  421. stats.Add( job.m_Stats );
  422. }
  423. if( !ShouldDisplayStats( eDisplay, stats ) )
  424. continue;
  425. rp.StrValue( pSystem->m_sName, CFmtStr( "gcaccess_dump_system \"%s\" %d", pSystem->m_sName.String(), eDisplay ).String() );
  426. rp.IntValue( pSystem->m_nID );
  427. rp.IntValue( pSystem->m_Jobs.Count() );
  428. rp.IntValue( stats.m_nNumValid );
  429. rp.IntValue( stats.m_nNumFail );
  430. rp.IntValue( stats.m_nNumFailID );
  431. rp.CommitRow();
  432. }
  433. rp.SortReport( "System", false );
  434. rp.PrintReport( SPEW_CONSOLE );
  435. }
  436. void CGCAccess::FullReport( const char* pszSystemFilter, const char* pszContextFilter, const char* pszJobFilter, EDisplay eDisplay ) const
  437. {
  438. CGCReportPrinter rp;
  439. rp.AddStringColumn( "Job" );
  440. rp.AddStringColumn( "Context" );
  441. rp.AddStringColumn( "System" );
  442. rp.AddIntColumn( "Valid", CGCReportPrinter::eSummary_Total );
  443. rp.AddIntColumn( "Invalid", CGCReportPrinter::eSummary_Total );
  444. rp.AddIntColumn( "InvalidID", CGCReportPrinter::eSummary_Total );
  445. FOR_EACH_MAP_FAST( m_Systems, nSystem )
  446. {
  447. const CGCAccessSystem* pSystem = m_Systems[ nSystem ];
  448. if( pszSystemFilter && V_stricmp( pszSystemFilter, pSystem->m_sName ) )
  449. continue;
  450. FOR_EACH_MAP_FAST( pSystem->m_Jobs, nJob )
  451. {
  452. const CGCAccessSystem::AccessStats_t& stats = pSystem->m_Jobs[ nJob ].m_Stats;
  453. const char* pszJob = ( const char* )pSystem->m_Jobs.Key( nJob );
  454. const char* pszContext = ( const char* )pSystem->m_Jobs[ nJob ].m_sContext;
  455. if( !ShouldDisplayStats( eDisplay, stats ) )
  456. continue;
  457. if( pszJobFilter && V_stricmp( pszJobFilter, pszJob ) )
  458. continue;
  459. if( pszContextFilter && V_stricmp( pszContextFilter, pszContext ) )
  460. continue;
  461. rp.StrValue( pszJob, CFmtStr( "gcaccess_dump_job \"%s\" %d", pszJob, eDisplay ).String() );
  462. rp.StrValue( pszContext, CFmtStr( "gcaccess_dump_context \"%s\" %d", pszContext, eDisplay ).String() );
  463. rp.StrValue( pSystem->m_sName, CFmtStr( "gcaccess_dump_system \"%s\" %d", pSystem->m_sName.String(), eDisplay ).String() );
  464. rp.IntValue( stats.m_nNumValid );
  465. rp.IntValue( stats.m_nNumFail );
  466. rp.IntValue( stats.m_nNumFailID );
  467. rp.CommitRow();
  468. }
  469. }
  470. rp.SortReport( "Context", false );
  471. rp.PrintReport( SPEW_CONSOLE );
  472. }
  473. void CGCAccess::DependencyReport( const char* pszSystem, EDisplay eDisplay ) const
  474. {
  475. //first off, we need to find the system we are scanning for dependencies on
  476. const CGCAccessSystem* pMatchSystem = NULL;
  477. FOR_EACH_MAP_FAST( m_Systems, nSystem )
  478. {
  479. const CGCAccessSystem* pSystem = m_Systems[ nSystem ];
  480. if( V_stricmp( pszSystem, pSystem->m_sName ) == 0 )
  481. {
  482. pMatchSystem = pSystem;
  483. break;
  484. }
  485. }
  486. if( !pMatchSystem )
  487. {
  488. EG_MSG( SPEW_CONSOLE, "Unable to find system %s for dependency report\n", pszSystem );
  489. return;
  490. }
  491. //now generate our report
  492. CGCReportPrinter rp;
  493. rp.AddStringColumn( "Job" );
  494. rp.AddStringColumn( "Context" );
  495. rp.AddStringColumn( "System" );
  496. rp.AddIntColumn( "Valid", CGCReportPrinter::eSummary_Total );
  497. rp.AddIntColumn( "Invalid", CGCReportPrinter::eSummary_Total );
  498. rp.AddIntColumn( "InvalidID", CGCReportPrinter::eSummary_Total );
  499. FOR_EACH_MAP_FAST( m_Systems, nSystem )
  500. {
  501. const CGCAccessSystem* pSystem = m_Systems[ nSystem ];
  502. //skip ourself
  503. if( pSystem == pMatchSystem )
  504. continue;
  505. FOR_EACH_MAP_FAST( pSystem->m_Jobs, nJob )
  506. {
  507. const CGCAccessSystem::AccessStats_t& stats = pSystem->m_Jobs[ nJob ].m_Stats;
  508. const char* pszJob = ( const char* )pSystem->m_Jobs.Key( nJob );
  509. const char* pszContext = ( const char* )pSystem->m_Jobs[ nJob ].m_sContext;
  510. //skip any job that isn't using our match system
  511. if( !pMatchSystem->m_Jobs.HasElement( ( uintp )pszJob ) )
  512. continue;
  513. if( !ShouldDisplayStats( eDisplay, stats ) )
  514. continue;
  515. rp.StrValue( pszJob, CFmtStr( "gcaccess_dump_job \"%s\" %d", pszJob, eDisplay ).String() );
  516. rp.StrValue( pszContext, CFmtStr( "gcaccess_dump_context \"%s\" %d", pszContext, eDisplay ).String() );
  517. rp.StrValue( pSystem->m_sName, CFmtStr( "gcaccess_dump_system \"%s\" %d", pSystem->m_sName.String(), eDisplay ).String() );
  518. rp.IntValue( stats.m_nNumValid );
  519. rp.IntValue( stats.m_nNumFail );
  520. rp.IntValue( stats.m_nNumFailID );
  521. rp.CommitRow();
  522. }
  523. }
  524. rp.SortReport( "System", false );
  525. rp.PrintReport( SPEW_CONSOLE );
  526. }
  527. GC_CON_COMMAND_PARAMS( gcaccess_dump_job, 1, "<Job Name> Dumps all of the accesses associated with the specified job" )
  528. {
  529. CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 3 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 2 ] ) : CGCAccess::eDisplay_Referenced;
  530. GGCAccess().FullReport( NULL, NULL, args[ 1 ], eDisplay );
  531. }
  532. GC_CON_COMMAND_PARAMS( gcaccess_dump_context, 1, "<Job Name> Dumps all of the accesses associated with the specified context" )
  533. {
  534. CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 3 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 2 ] ) : CGCAccess::eDisplay_Referenced;
  535. GGCAccess().FullReport( NULL, args[ 1 ], NULL, eDisplay );
  536. }
  537. GC_CON_COMMAND_PARAMS( gcaccess_dump_system, 1, "<Job Name> Dumps all of the accesses associated with the specified system" )
  538. {
  539. CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 3 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 2 ] ) : CGCAccess::eDisplay_Referenced;
  540. GGCAccess().FullReport( args[ 1 ], NULL, NULL, eDisplay );
  541. }
  542. GC_CON_COMMAND_PARAMS( gcaccess_dump_context_jobs, 1, "<Context Name> Dumps all of the accesses associated with the specified context" )
  543. {
  544. CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 3 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 2 ] ) : CGCAccess::eDisplay_Referenced;
  545. GGCAccess().ReportJobs( args[ 1 ], eDisplay );
  546. }
  547. GC_CON_COMMAND_PARAMS( gcaccess_dump_context_systems, 1, "<Context Name> Dumps all of the accesses associated with the specified context" )
  548. {
  549. CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 3 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 2 ] ) : CGCAccess::eDisplay_Referenced;
  550. GGCAccess().ReportSystems( args[ 1 ], eDisplay );
  551. }
  552. GC_CON_COMMAND_PARAMS( gcaccess_dump_system_dependencies, 1, "<System Name> This will dump out for all jobs that reference the specified system, what other systems they reference" )
  553. {
  554. CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 3 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 2 ] ) : CGCAccess::eDisplay_Referenced;
  555. GGCAccess().DependencyReport( args[ 1 ], eDisplay );
  556. }
  557. GC_CON_COMMAND( gcaccess_dump_jobs, "Dumps all the jobs that have been tracked with the gcaccess system as well as count of violations" )
  558. {
  559. CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 2 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 1 ] ) : CGCAccess::eDisplay_Referenced;
  560. GGCAccess().ReportJobs( NULL, eDisplay);
  561. }
  562. GC_CON_COMMAND( gcaccess_dump_systems, "Dumps all the systems that have been tracked with the gcaccess system as well as count of violations" )
  563. {
  564. CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 2 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 1 ] ) : CGCAccess::eDisplay_Referenced;
  565. GGCAccess().ReportSystems( NULL, eDisplay );
  566. }
  567. GC_CON_COMMAND( gcaccess_dump_full, "Dumps all the information tracked by the gcaccess" )
  568. {
  569. CGCAccess::EDisplay eDisplay = ( args.ArgC() >= 2 ) ? ( CGCAccess::EDisplay )V_atoi( args[ 1 ] ) : CGCAccess::eDisplay_Referenced;
  570. GGCAccess().FullReport( NULL, NULL, NULL, eDisplay );
  571. }
  572. GC_CON_COMMAND_PARAMS( gcaccess_catch_context, 2, "<system> <context> - Catches and generates an assert when the specified context calls into the provided system. This will only generate a single assert" )
  573. {
  574. if( !GGCAccess().CatchSingleAssert( args[ 1 ], true, args[ 2 ] ) )
  575. EG_MSG( SPEW_CONSOLE, "Unable to register catch, likely \'%s\' is not a valid system.", args[ 1 ] );
  576. }
  577. GC_CON_COMMAND_PARAMS( gcaccess_catch_job, 2, "<system> <job> - Catches and generates an assert when the specified job calls into the provided system. This will only generate a single assert" )
  578. {
  579. if( !GGCAccess().CatchSingleAssert( args[ 1 ], false, args[ 2 ] ) )
  580. EG_MSG( SPEW_CONSOLE, "Unable to register catch, likely \'%s\' is not a valid system.", args[ 1 ] );
  581. }
  582. GC_CON_COMMAND( gcaccess_catch_clear, "Clears all previously specified catches" )
  583. {
  584. GGCAccess().ClearSingleAsserts();
  585. }
  586. } //namespace GCSDK