win_shared.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "win_local.h"
  23. #include <lmerr.h>
  24. #include <lmcons.h>
  25. #include <lmwksta.h>
  26. #include <errno.h>
  27. #include <fcntl.h>
  28. #include <direct.h>
  29. #include <io.h>
  30. #include <conio.h>
  31. #ifndef ID_DEDICATED
  32. #include <comdef.h>
  33. #include <comutil.h>
  34. #include <Wbemidl.h>
  35. #pragma comment (lib, "wbemuuid.lib")
  36. #endif
  37. #include "win_nanoafx.h"
  38. /*
  39. ================
  40. Sys_Milliseconds
  41. ================
  42. */
  43. int Sys_Milliseconds( void ) {
  44. int sys_curtime;
  45. static int sys_timeBase;
  46. static bool initialized = false;
  47. if ( !initialized ) {
  48. sys_timeBase = timeGetTime();
  49. initialized = true;
  50. }
  51. sys_curtime = timeGetTime() - sys_timeBase;
  52. return sys_curtime;
  53. }
  54. /*
  55. ================
  56. Sys_GetSystemRam
  57. returns amount of physical memory in MB
  58. ================
  59. */
  60. int Sys_GetSystemRam( void ) {
  61. MEMORYSTATUSEX statex;
  62. statex.dwLength = sizeof ( statex );
  63. GlobalMemoryStatusEx (&statex);
  64. int physRam = statex.ullTotalPhys / ( 1024 * 1024 );
  65. // HACK: For some reason, ullTotalPhys is sometimes off by a meg or two, so we round up to the nearest 16 megs
  66. physRam = ( physRam + 8 ) & ~15;
  67. return physRam;
  68. }
  69. /*
  70. ================
  71. Sys_GetDriveFreeSpace
  72. returns in megabytes
  73. ================
  74. */
  75. int Sys_GetDriveFreeSpace( const char *path ) {
  76. DWORDLONG lpFreeBytesAvailable;
  77. DWORDLONG lpTotalNumberOfBytes;
  78. DWORDLONG lpTotalNumberOfFreeBytes;
  79. int ret = 26;
  80. //FIXME: see why this is failing on some machines
  81. if ( ::GetDiskFreeSpaceEx( path, (PULARGE_INTEGER)&lpFreeBytesAvailable, (PULARGE_INTEGER)&lpTotalNumberOfBytes, (PULARGE_INTEGER)&lpTotalNumberOfFreeBytes ) ) {
  82. ret = ( double )( lpFreeBytesAvailable ) / ( 1024.0 * 1024.0 );
  83. }
  84. return ret;
  85. }
  86. /*
  87. ================
  88. Sys_GetVideoRam
  89. returns in megabytes
  90. ================
  91. */
  92. int Sys_GetVideoRam( void ) {
  93. #ifdef ID_DEDICATED
  94. return 0;
  95. #else
  96. unsigned int retSize = 64;
  97. CComPtr<IWbemLocator> spLoc = NULL;
  98. HRESULT hr = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_SERVER, IID_IWbemLocator, ( LPVOID * ) &spLoc );
  99. if ( hr != S_OK || spLoc == NULL ) {
  100. return retSize;
  101. }
  102. CComBSTR bstrNamespace( _T( "\\\\.\\root\\CIMV2" ) );
  103. CComPtr<IWbemServices> spServices;
  104. // Connect to CIM
  105. hr = spLoc->ConnectServer( bstrNamespace, NULL, NULL, 0, NULL, 0, 0, &spServices );
  106. if ( hr != WBEM_S_NO_ERROR ) {
  107. return retSize;
  108. }
  109. // Switch the security level to IMPERSONATE so that provider will grant access to system-level objects.
  110. hr = CoSetProxyBlanket( spServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
  111. if ( hr != S_OK ) {
  112. return retSize;
  113. }
  114. // Get the vid controller
  115. CComPtr<IEnumWbemClassObject> spEnumInst = NULL;
  116. hr = spServices->CreateInstanceEnum( CComBSTR( "Win32_VideoController" ), WBEM_FLAG_SHALLOW, NULL, &spEnumInst );
  117. if ( hr != WBEM_S_NO_ERROR || spEnumInst == NULL ) {
  118. return retSize;
  119. }
  120. ULONG uNumOfInstances = 0;
  121. CComPtr<IWbemClassObject> spInstance = NULL;
  122. hr = spEnumInst->Next( 10000, 1, &spInstance, &uNumOfInstances );
  123. if ( hr == S_OK && spInstance ) {
  124. // Get properties from the object
  125. CComVariant varSize;
  126. hr = spInstance->Get( CComBSTR( _T( "AdapterRAM" ) ), 0, &varSize, 0, 0 );
  127. if ( hr == S_OK ) {
  128. retSize = varSize.intVal / ( 1024 * 1024 );
  129. if ( retSize == 0 ) {
  130. retSize = 64;
  131. }
  132. }
  133. }
  134. return retSize;
  135. #endif
  136. }
  137. /*
  138. ================
  139. Sys_GetCurrentMemoryStatus
  140. returns OS mem info
  141. all values are in kB except the memoryload
  142. ================
  143. */
  144. void Sys_GetCurrentMemoryStatus( sysMemoryStats_t &stats ) {
  145. MEMORYSTATUSEX statex;
  146. unsigned __int64 work;
  147. memset( &statex, sizeof( statex ), 0 );
  148. statex.dwLength = sizeof( statex );
  149. GlobalMemoryStatusEx( &statex );
  150. memset( &stats, 0, sizeof( stats ) );
  151. stats.memoryLoad = statex.dwMemoryLoad;
  152. work = statex.ullTotalPhys >> 20;
  153. stats.totalPhysical = *(int*)&work;
  154. work = statex.ullAvailPhys >> 20;
  155. stats.availPhysical = *(int*)&work;
  156. work = statex.ullAvailPageFile >> 20;
  157. stats.availPageFile = *(int*)&work;
  158. work = statex.ullTotalPageFile >> 20;
  159. stats.totalPageFile = *(int*)&work;
  160. work = statex.ullTotalVirtual >> 20;
  161. stats.totalVirtual = *(int*)&work;
  162. work = statex.ullAvailVirtual >> 20;
  163. stats.availVirtual = *(int*)&work;
  164. work = statex.ullAvailExtendedVirtual >> 20;
  165. stats.availExtendedVirtual = *(int*)&work;
  166. }
  167. /*
  168. ================
  169. Sys_LockMemory
  170. ================
  171. */
  172. bool Sys_LockMemory( void *ptr, int bytes ) {
  173. return ( VirtualLock( ptr, (SIZE_T)bytes ) != FALSE );
  174. }
  175. /*
  176. ================
  177. Sys_UnlockMemory
  178. ================
  179. */
  180. bool Sys_UnlockMemory( void *ptr, int bytes ) {
  181. return ( VirtualUnlock( ptr, (SIZE_T)bytes ) != FALSE );
  182. }
  183. /*
  184. ================
  185. Sys_SetPhysicalWorkMemory
  186. ================
  187. */
  188. void Sys_SetPhysicalWorkMemory( int minBytes, int maxBytes ) {
  189. ::SetProcessWorkingSetSize( GetCurrentProcess(), minBytes, maxBytes );
  190. }
  191. /*
  192. ================
  193. Sys_GetCurrentUser
  194. ================
  195. */
  196. char *Sys_GetCurrentUser( void ) {
  197. static char s_userName[1024];
  198. unsigned long size = sizeof( s_userName );
  199. if ( !GetUserName( s_userName, &size ) ) {
  200. strcpy( s_userName, "player" );
  201. }
  202. if ( !s_userName[0] ) {
  203. strcpy( s_userName, "player" );
  204. }
  205. return s_userName;
  206. }
  207. /*
  208. ===============================================================================
  209. Call stack
  210. ===============================================================================
  211. */
  212. #define PROLOGUE_SIGNATURE 0x00EC8B55
  213. #include <dbghelp.h>
  214. const int UNDECORATE_FLAGS = UNDNAME_NO_MS_KEYWORDS |
  215. UNDNAME_NO_ACCESS_SPECIFIERS |
  216. UNDNAME_NO_FUNCTION_RETURNS |
  217. UNDNAME_NO_ALLOCATION_MODEL |
  218. UNDNAME_NO_ALLOCATION_LANGUAGE |
  219. UNDNAME_NO_MEMBER_TYPE;
  220. #if defined(_DEBUG) && 1
  221. typedef struct symbol_s {
  222. int address;
  223. char * name;
  224. struct symbol_s * next;
  225. } symbol_t;
  226. typedef struct module_s {
  227. int address;
  228. char * name;
  229. symbol_t * symbols;
  230. struct module_s * next;
  231. } module_t;
  232. module_t *modules;
  233. /*
  234. ==================
  235. SkipRestOfLine
  236. ==================
  237. */
  238. void SkipRestOfLine( const char **ptr ) {
  239. while( (**ptr) != '\0' && (**ptr) != '\n' && (**ptr) != '\r' ) {
  240. (*ptr)++;
  241. }
  242. while( (**ptr) == '\n' || (**ptr) == '\r' ) {
  243. (*ptr)++;
  244. }
  245. }
  246. /*
  247. ==================
  248. SkipWhiteSpace
  249. ==================
  250. */
  251. void SkipWhiteSpace( const char **ptr ) {
  252. while( (**ptr) == ' ' ) {
  253. (*ptr)++;
  254. }
  255. }
  256. /*
  257. ==================
  258. ParseHexNumber
  259. ==================
  260. */
  261. int ParseHexNumber( const char **ptr ) {
  262. int n = 0;
  263. while( (**ptr) >= '0' && (**ptr) <= '9' || (**ptr) >= 'a' && (**ptr) <= 'f' ) {
  264. n <<= 4;
  265. if ( **ptr >= '0' && **ptr <= '9' ) {
  266. n |= ( (**ptr) - '0' );
  267. } else {
  268. n |= 10 + ( (**ptr) - 'a' );
  269. }
  270. (*ptr)++;
  271. }
  272. return n;
  273. }
  274. /*
  275. ==================
  276. Sym_Init
  277. ==================
  278. */
  279. void Sym_Init( long addr ) {
  280. TCHAR moduleName[MAX_STRING_CHARS];
  281. MEMORY_BASIC_INFORMATION mbi;
  282. VirtualQuery( (void*)addr, &mbi, sizeof(mbi) );
  283. GetModuleFileName( (HMODULE)mbi.AllocationBase, moduleName, sizeof( moduleName ) );
  284. char *ext = moduleName + strlen( moduleName );
  285. while( ext > moduleName && *ext != '.' ) {
  286. ext--;
  287. }
  288. if ( ext == moduleName ) {
  289. strcat( moduleName, ".map" );
  290. } else {
  291. strcpy( ext, ".map" );
  292. }
  293. module_t *module = (module_t *) malloc( sizeof( module_t ) );
  294. module->name = (char *) malloc( strlen( moduleName ) + 1 );
  295. strcpy( module->name, moduleName );
  296. module->address = (int)mbi.AllocationBase;
  297. module->symbols = NULL;
  298. module->next = modules;
  299. modules = module;
  300. FILE *fp = fopen( moduleName, "rb" );
  301. if ( fp == NULL ) {
  302. return;
  303. }
  304. int pos = ftell( fp );
  305. fseek( fp, 0, SEEK_END );
  306. int length = ftell( fp );
  307. fseek( fp, pos, SEEK_SET );
  308. char *text = (char *) malloc( length+1 );
  309. fread( text, 1, length, fp );
  310. text[length] = '\0';
  311. fclose( fp );
  312. const char *ptr = text;
  313. // skip up to " Address" on a new line
  314. while( *ptr != '\0' ) {
  315. SkipWhiteSpace( &ptr );
  316. if ( idStr::Cmpn( ptr, "Address", 7 ) == 0 ) {
  317. SkipRestOfLine( &ptr );
  318. break;
  319. }
  320. SkipRestOfLine( &ptr );
  321. }
  322. int symbolAddress;
  323. int symbolLength;
  324. char symbolName[MAX_STRING_CHARS];
  325. symbol_t *symbol;
  326. // parse symbols
  327. while( *ptr != '\0' ) {
  328. SkipWhiteSpace( &ptr );
  329. ParseHexNumber( &ptr );
  330. if ( *ptr == ':' ) {
  331. ptr++;
  332. } else {
  333. break;
  334. }
  335. ParseHexNumber( &ptr );
  336. SkipWhiteSpace( &ptr );
  337. // parse symbol name
  338. symbolLength = 0;
  339. while( *ptr != '\0' && *ptr != ' ' ) {
  340. symbolName[symbolLength++] = *ptr++;
  341. if ( symbolLength >= sizeof( symbolName ) - 1 ) {
  342. break;
  343. }
  344. }
  345. symbolName[symbolLength++] = '\0';
  346. SkipWhiteSpace( &ptr );
  347. // parse symbol address
  348. symbolAddress = ParseHexNumber( &ptr );
  349. SkipRestOfLine( &ptr );
  350. symbol = (symbol_t *) malloc( sizeof( symbol_t ) );
  351. symbol->name = (char *) malloc( symbolLength );
  352. strcpy( symbol->name, symbolName );
  353. symbol->address = symbolAddress;
  354. symbol->next = module->symbols;
  355. module->symbols = symbol;
  356. }
  357. free( text );
  358. }
  359. /*
  360. ==================
  361. Sym_Shutdown
  362. ==================
  363. */
  364. void Sym_Shutdown( void ) {
  365. module_t *m;
  366. symbol_t *s;
  367. for ( m = modules; m != NULL; m = modules ) {
  368. modules = m->next;
  369. for ( s = m->symbols; s != NULL; s = m->symbols ) {
  370. m->symbols = s->next;
  371. free( s->name );
  372. free( s );
  373. }
  374. free( m->name );
  375. free( m );
  376. }
  377. modules = NULL;
  378. }
  379. /*
  380. ==================
  381. Sym_GetFuncInfo
  382. ==================
  383. */
  384. void Sym_GetFuncInfo( long addr, idStr &module, idStr &funcName ) {
  385. MEMORY_BASIC_INFORMATION mbi;
  386. module_t *m;
  387. symbol_t *s;
  388. VirtualQuery( (void*)addr, &mbi, sizeof(mbi) );
  389. for ( m = modules; m != NULL; m = m->next ) {
  390. if ( m->address == (int) mbi.AllocationBase ) {
  391. break;
  392. }
  393. }
  394. if ( !m ) {
  395. Sym_Init( addr );
  396. m = modules;
  397. }
  398. for ( s = m->symbols; s != NULL; s = s->next ) {
  399. if ( s->address == addr ) {
  400. char undName[MAX_STRING_CHARS];
  401. if ( UnDecorateSymbolName( s->name, undName, sizeof(undName), UNDECORATE_FLAGS ) ) {
  402. funcName = undName;
  403. } else {
  404. funcName = s->name;
  405. }
  406. for ( int i = 0; i < funcName.Length(); i++ ) {
  407. if ( funcName[i] == '(' ) {
  408. funcName.CapLength( i );
  409. break;
  410. }
  411. }
  412. module = m->name;
  413. return;
  414. }
  415. }
  416. sprintf( funcName, "0x%08x", addr );
  417. module = "";
  418. }
  419. #elif defined(_DEBUG)
  420. DWORD lastAllocationBase = -1;
  421. HANDLE processHandle;
  422. idStr lastModule;
  423. /*
  424. ==================
  425. Sym_Init
  426. ==================
  427. */
  428. void Sym_Init( long addr ) {
  429. TCHAR moduleName[MAX_STRING_CHARS];
  430. TCHAR modShortNameBuf[MAX_STRING_CHARS];
  431. MEMORY_BASIC_INFORMATION mbi;
  432. if ( lastAllocationBase != -1 ) {
  433. Sym_Shutdown();
  434. }
  435. VirtualQuery( (void*)addr, &mbi, sizeof(mbi) );
  436. GetModuleFileName( (HMODULE)mbi.AllocationBase, moduleName, sizeof( moduleName ) );
  437. _splitpath( moduleName, NULL, NULL, modShortNameBuf, NULL );
  438. lastModule = modShortNameBuf;
  439. processHandle = GetCurrentProcess();
  440. if ( !SymInitialize( processHandle, NULL, FALSE ) ) {
  441. return;
  442. }
  443. if ( !SymLoadModule( processHandle, NULL, moduleName, NULL, (DWORD)mbi.AllocationBase, 0 ) ) {
  444. SymCleanup( processHandle );
  445. return;
  446. }
  447. SymSetOptions( SymGetOptions() & ~SYMOPT_UNDNAME );
  448. lastAllocationBase = (DWORD) mbi.AllocationBase;
  449. }
  450. /*
  451. ==================
  452. Sym_Shutdown
  453. ==================
  454. */
  455. void Sym_Shutdown( void ) {
  456. SymUnloadModule( GetCurrentProcess(), lastAllocationBase );
  457. SymCleanup( GetCurrentProcess() );
  458. lastAllocationBase = -1;
  459. }
  460. /*
  461. ==================
  462. Sym_GetFuncInfo
  463. ==================
  464. */
  465. void Sym_GetFuncInfo( long addr, idStr &module, idStr &funcName ) {
  466. MEMORY_BASIC_INFORMATION mbi;
  467. VirtualQuery( (void*)addr, &mbi, sizeof(mbi) );
  468. if ( (DWORD) mbi.AllocationBase != lastAllocationBase ) {
  469. Sym_Init( addr );
  470. }
  471. BYTE symbolBuffer[ sizeof(IMAGEHLP_SYMBOL) + MAX_STRING_CHARS ];
  472. PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)&symbolBuffer[0];
  473. pSymbol->SizeOfStruct = sizeof(symbolBuffer);
  474. pSymbol->MaxNameLength = 1023;
  475. pSymbol->Address = 0;
  476. pSymbol->Flags = 0;
  477. pSymbol->Size =0;
  478. DWORD symDisplacement = 0;
  479. if ( SymGetSymFromAddr( processHandle, addr, &symDisplacement, pSymbol ) ) {
  480. // clean up name, throwing away decorations that don't affect uniqueness
  481. char undName[MAX_STRING_CHARS];
  482. if ( UnDecorateSymbolName( pSymbol->Name, undName, sizeof(undName), UNDECORATE_FLAGS ) ) {
  483. funcName = undName;
  484. } else {
  485. funcName = pSymbol->Name;
  486. }
  487. module = lastModule;
  488. }
  489. else {
  490. LPVOID lpMsgBuf;
  491. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  492. NULL,
  493. GetLastError(),
  494. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  495. (LPTSTR) &lpMsgBuf,
  496. 0,
  497. NULL
  498. );
  499. LocalFree( lpMsgBuf );
  500. // Couldn't retrieve symbol (no debug info?, can't load dbghelp.dll?)
  501. sprintf( funcName, "0x%08x", addr );
  502. module = "";
  503. }
  504. }
  505. #else
  506. /*
  507. ==================
  508. Sym_Init
  509. ==================
  510. */
  511. void Sym_Init( long addr ) {
  512. }
  513. /*
  514. ==================
  515. Sym_Shutdown
  516. ==================
  517. */
  518. void Sym_Shutdown( void ) {
  519. }
  520. /*
  521. ==================
  522. Sym_GetFuncInfo
  523. ==================
  524. */
  525. void Sym_GetFuncInfo( long addr, idStr &module, idStr &funcName ) {
  526. module = "";
  527. sprintf( funcName, "0x%08x", addr );
  528. }
  529. #endif
  530. /*
  531. ==================
  532. GetFuncAddr
  533. ==================
  534. */
  535. address_t GetFuncAddr( address_t midPtPtr ) {
  536. long temp;
  537. do {
  538. temp = (long)(*(long*)midPtPtr);
  539. if ( (temp&0x00FFFFFF) == PROLOGUE_SIGNATURE ) {
  540. break;
  541. }
  542. midPtPtr--;
  543. } while(true);
  544. return midPtPtr;
  545. }
  546. /*
  547. ==================
  548. GetCallerAddr
  549. ==================
  550. */
  551. address_t GetCallerAddr( long _ebp ) {
  552. long midPtPtr;
  553. long res = 0;
  554. __asm {
  555. mov eax, _ebp
  556. mov ecx, [eax] // check for end of stack frames list
  557. test ecx, ecx // check for zero stack frame
  558. jz label
  559. mov eax, [eax+4] // get the ret address
  560. test eax, eax // check for zero return address
  561. jz label
  562. mov midPtPtr, eax
  563. }
  564. res = GetFuncAddr( midPtPtr );
  565. label:
  566. return res;
  567. }
  568. /*
  569. ==================
  570. Sys_GetCallStack
  571. use /Oy option
  572. ==================
  573. */
  574. void Sys_GetCallStack( address_t *callStack, const int callStackSize ) {
  575. #if 1 //def _DEBUG
  576. int i;
  577. long m_ebp;
  578. __asm {
  579. mov eax, ebp
  580. mov m_ebp, eax
  581. }
  582. // skip last two functions
  583. m_ebp = *((long*)m_ebp);
  584. m_ebp = *((long*)m_ebp);
  585. // list functions
  586. for ( i = 0; i < callStackSize; i++ ) {
  587. callStack[i] = GetCallerAddr( m_ebp );
  588. if ( callStack[i] == 0 ) {
  589. break;
  590. }
  591. m_ebp = *((long*)m_ebp);
  592. }
  593. #else
  594. int i = 0;
  595. #endif
  596. while( i < callStackSize ) {
  597. callStack[i++] = 0;
  598. }
  599. }
  600. /*
  601. ==================
  602. Sys_GetCallStackStr
  603. ==================
  604. */
  605. const char *Sys_GetCallStackStr( const address_t *callStack, const int callStackSize ) {
  606. static char string[MAX_STRING_CHARS*2];
  607. int index, i;
  608. idStr module, funcName;
  609. index = 0;
  610. for ( i = callStackSize-1; i >= 0; i-- ) {
  611. Sym_GetFuncInfo( callStack[i], module, funcName );
  612. index += sprintf( string+index, " -> %s", funcName.c_str() );
  613. }
  614. return string;
  615. }
  616. /*
  617. ==================
  618. Sys_GetCallStackCurStr
  619. ==================
  620. */
  621. const char *Sys_GetCallStackCurStr( int depth ) {
  622. address_t *callStack;
  623. callStack = (address_t *) _alloca( depth * sizeof( address_t ) );
  624. Sys_GetCallStack( callStack, depth );
  625. return Sys_GetCallStackStr( callStack, depth );
  626. }
  627. /*
  628. ==================
  629. Sys_GetCallStackCurAddressStr
  630. ==================
  631. */
  632. const char *Sys_GetCallStackCurAddressStr( int depth ) {
  633. static char string[MAX_STRING_CHARS*2];
  634. address_t *callStack;
  635. int index, i;
  636. callStack = (address_t *) _alloca( depth * sizeof( address_t ) );
  637. Sys_GetCallStack( callStack, depth );
  638. index = 0;
  639. for ( i = depth-1; i >= 0; i-- ) {
  640. index += sprintf( string+index, " -> 0x%08x", callStack[i] );
  641. }
  642. return string;
  643. }
  644. /*
  645. ==================
  646. Sys_ShutdownSymbols
  647. ==================
  648. */
  649. void Sys_ShutdownSymbols( void ) {
  650. Sym_Shutdown();
  651. }