jexcept.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "platform.h"
  14. #include <algorithm>
  15. #include "jexcept.hpp"
  16. #include <assert.h>
  17. #include <stdio.h>
  18. #include <stdarg.h>
  19. #include <errno.h>
  20. #include "jptree.hpp"
  21. #ifdef _WIN32
  22. #include "psapi.h"
  23. #include <eh.h>
  24. #elif defined (__linux__) || defined(__FreeBSD__) || defined(__APPLE__)
  25. #include <sys/wait.h>
  26. #include <sys/types.h>
  27. #include <stddef.h>
  28. #include <errno.h>
  29. #ifdef __linux__
  30. #include <execinfo.h> // comment out if not present
  31. #endif
  32. #ifdef __APPLE__
  33. #ifndef _XOPEN_SOURCE
  34. #define _XOPEN_SOURCE
  35. #endif
  36. #include <ucontext.h>
  37. #endif
  38. #endif
  39. //#define NOSEH
  40. #define NO_LINUX_SEH
  41. #define EXTENDED_EXCEPTION_TRACE
  42. #ifdef EXTENDED_EXCEPTION_TRACE
  43. #include "jmisc.hpp"
  44. #define LINUX_SIGNAL_EXCEPTION
  45. #endif
  46. class jlib_thrown_decl StringException: public CInterface, public IException
  47. {
  48. public:
  49. IMPLEMENT_IINTERFACE;
  50. StringException(int code, const char *str, MessageAudience aud = MSGAUD_user) : errcode(code), msg(str), audience(aud) {};
  51. int errorCode() const { return errcode; }
  52. StringBuffer & errorMessage(StringBuffer &str) const { str.append(msg); return str;}
  53. MessageAudience errorAudience() const { return audience; }
  54. protected:
  55. int errcode;
  56. StringAttr msg;
  57. MessageAudience audience;
  58. };
  59. IException *makeStringExceptionVA(int code, const char *format, va_list args)
  60. {
  61. StringBuffer eStr;
  62. eStr.limited_valist_appendf(1024, format, args);
  63. return new StringException(code, eStr.str());
  64. }
  65. IException *makeStringExceptionV(int code,const char *format, ...)
  66. {
  67. va_list args;
  68. va_start(args, format);
  69. IException *ret = makeStringExceptionVA(code, format, args);
  70. va_end(args);
  71. return ret;
  72. }
  73. IException jlib_decl *makeStringException(int code,const char *why)
  74. {
  75. return new StringException(code,why);
  76. }
  77. IException *makeStringExceptionVA(MessageAudience aud, int code, const char *format, va_list args)
  78. {
  79. StringBuffer eStr;
  80. eStr.limited_valist_appendf(1024, format, args);
  81. return new StringException(code, eStr.str(), aud);
  82. }
  83. IException *makeStringExceptionV(MessageAudience aud, int code, const char *format, ...)
  84. {
  85. va_list args;
  86. va_start(args, format);
  87. IException *ret = makeStringExceptionVA(aud, code, format, args);
  88. va_end(args);
  89. return ret;
  90. }
  91. IException jlib_decl *makeStringException(MessageAudience aud,int code,const char *why)
  92. {
  93. return new StringException(code,why,aud);
  94. }
  95. void jlib_decl throwStringExceptionV(int code,const char *format, ...)
  96. {
  97. va_list args;
  98. va_start(args, format);
  99. IException *ret = makeStringExceptionVA(code, format, args);
  100. va_end(args);
  101. throw ret;
  102. }
  103. class jlib_thrown_decl OsException: public CInterface, public IOSException
  104. {
  105. public:
  106. IMPLEMENT_IINTERFACE;
  107. OsException(int code) : errcode(code) {};
  108. OsException(int code, const char *_msg) : msg(_msg), errcode(code) {};
  109. ~OsException() {}
  110. int errorCode() const { return errcode; }
  111. StringBuffer & errorMessage(StringBuffer &str) const
  112. {
  113. if (msg)
  114. str.append(msg).append(", ");
  115. formatSystemError(str, errcode);
  116. return str;
  117. }
  118. MessageAudience errorAudience() const { return MSGAUD_user; }
  119. protected:
  120. StringAttr msg;
  121. int errcode;
  122. };
  123. IOSException *makeOsException(int code)
  124. {
  125. return new OsException(code);
  126. }
  127. IOSException *makeOsException(int code, const char *msg)
  128. {
  129. return new OsException(code, msg);
  130. }
  131. IOSException *makeOsExceptionV(int code, const char *msg, ...)
  132. {
  133. StringBuffer eStr;
  134. va_list args;
  135. va_start(args, msg);
  136. eStr.limited_valist_appendf(1024, msg, args);
  137. va_end(args);
  138. return new OsException(code, eStr.str());
  139. }
  140. class jlib_thrown_decl ErrnoException: public CInterface, public IErrnoException
  141. {
  142. public:
  143. IMPLEMENT_IINTERFACE;
  144. ErrnoException(int errn) : audience(MSGAUD_user) { errcode = errn==-1?errno:errn; }
  145. ErrnoException(int errn, const char *_msg, MessageAudience aud = MSGAUD_user) : msg(_msg), audience(aud) { errcode = errn==-1?errno:errn; }
  146. ~ErrnoException() { }
  147. int errorCode() const { return errcode; }
  148. StringBuffer & errorMessage(StringBuffer &str) const
  149. {
  150. if (msg)
  151. str.append(msg).append(", ");
  152. if (errcode==DISK_FULL_EXCEPTION_CODE)
  153. str.append("Disk full");
  154. else
  155. str.append(strerror(errcode));
  156. return str;
  157. }
  158. MessageAudience errorAudience() const { return audience; }
  159. protected:
  160. StringAttr msg;
  161. int errcode;
  162. MessageAudience audience;
  163. };
  164. IErrnoException *makeErrnoException(int errn, const char *msg)
  165. {
  166. return new ErrnoException(errn, msg);
  167. }
  168. IErrnoException *makeErrnoException(const char *msg)
  169. {
  170. return new ErrnoException(-1, msg);
  171. }
  172. IErrnoException *makeErrnoExceptionV(int errn, const char *msg, ...)
  173. {
  174. StringBuffer eStr;
  175. va_list args;
  176. va_start(args, msg);
  177. eStr.limited_valist_appendf(1024, msg, args);
  178. va_end(args);
  179. return new ErrnoException(errn, eStr.str());
  180. }
  181. IErrnoException *makeErrnoExceptionV(const char *msg, ...)
  182. {
  183. StringBuffer eStr;
  184. va_list args;
  185. va_start(args, msg);
  186. eStr.limited_valist_appendf(1024, msg, args);
  187. va_end(args);
  188. return new ErrnoException(-1, eStr.str());
  189. }
  190. IErrnoException *makeErrnoException(MessageAudience aud, int errn, const char *msg)
  191. {
  192. return new ErrnoException(errn, msg, aud);
  193. }
  194. IErrnoException *makeErrnoExceptionV(MessageAudience aud, int errn, const char *msg, ...)
  195. {
  196. StringBuffer eStr;
  197. va_list args;
  198. va_start(args, msg);
  199. eStr.limited_valist_appendf(1024, msg, args);
  200. va_end(args);
  201. return new ErrnoException(errn, eStr.str(), aud);
  202. }
  203. IErrnoException *makeErrnoExceptionV(MessageAudience aud, const char *msg, ...)
  204. {
  205. StringBuffer eStr;
  206. va_list args;
  207. va_start(args, msg);
  208. eStr.limited_valist_appendf(1024, msg, args);
  209. va_end(args);
  210. return new ErrnoException(-1, eStr.str(), aud);
  211. }
  212. const char* serializeMessageAudience(MessageAudience ma)
  213. {
  214. const char* ret;
  215. switch(ma)
  216. {
  217. case MSGAUD_unknown: ret = "unknown"; break;
  218. case MSGAUD_operator: ret = "operator"; break;
  219. case MSGAUD_user: ret = "user"; break;
  220. case MSGAUD_monitor: ret = "monitor"; break;
  221. case MSGAUD_performance: ret = "performance"; break;
  222. case MSGAUD_internal: ret = "internal"; break;
  223. case MSGAUD_programmer: ret = "programmer"; break;
  224. case MSGAUD_legacy: ret = "legacy"; break;
  225. case MSGAUD_all: ret = "all"; break;
  226. default: ret = "unknown"; break;
  227. }
  228. return ret;
  229. }
  230. MessageAudience deserializeMessageAudience(const char* text)
  231. {
  232. MessageAudience ma = MSGAUD_unknown;
  233. if (text && *text)
  234. {
  235. if (!strcmp(text, "operator"))
  236. ma = MSGAUD_operator;
  237. else if (!strcmp(text, "user"))
  238. ma = MSGAUD_user;
  239. else if (!strcmp(text, "monitor"))
  240. ma = MSGAUD_monitor;
  241. else if (!strcmp(text, "performance"))
  242. ma = MSGAUD_performance;
  243. else if (!strcmp(text, "internal"))
  244. ma = MSGAUD_internal;
  245. else if (!strcmp(text, "programmer"))
  246. ma = MSGAUD_programmer;
  247. else if (!strcmp(text, "legacy"))
  248. ma = MSGAUD_legacy;
  249. else if (!strcmp(text, "all"))
  250. ma = MSGAUD_all;
  251. }
  252. return ma;
  253. }
  254. class jlib_thrown_decl CMultiException : public CInterface,
  255. implements IMultiException
  256. {
  257. public:
  258. IMPLEMENT_IINTERFACE
  259. CMultiException(const char* source=NULL)
  260. {
  261. if (source)
  262. source_.append(source);
  263. }
  264. //convenience methods for handling this as an array
  265. virtual aindex_t ordinality() const
  266. {
  267. synchronized block(m_mutex);
  268. return array_.ordinality();
  269. }
  270. virtual IException& item(aindex_t pos) const
  271. {
  272. synchronized block(m_mutex);
  273. return array_.item(pos);
  274. }
  275. virtual const char* source() const
  276. {
  277. synchronized block(m_mutex);
  278. return source_.str();
  279. }
  280. //for complete control...caller is responsible for thread safety!
  281. virtual IArrayOf<IException>& getArray() { return array_; }
  282. //add another exception
  283. virtual void append(IException& e)
  284. {
  285. synchronized block(m_mutex);
  286. array_.append(e);
  287. }
  288. virtual void append(IMultiException& me)
  289. {
  290. synchronized block(m_mutex);
  291. IArrayOf<IException>& exceptions = me.getArray();
  292. const char* source = me.source();
  293. ForEachItemIn(i, exceptions)
  294. {
  295. IException& e = exceptions.item(i);
  296. if (source && *source)
  297. {
  298. StringBuffer msg;
  299. msg.appendf("[%s] ",source);
  300. e.errorMessage(msg);
  301. array_.append(*makeStringExceptionV(e.errorAudience(), e.errorCode(), "%s", msg.str()));
  302. }
  303. else
  304. array_.append(*LINK(&e));
  305. }
  306. }
  307. StringBuffer& serialize(StringBuffer& buffer, unsigned indent = 0, bool simplified=false, bool root=true) const
  308. {
  309. synchronized block(m_mutex);
  310. if (root)
  311. buffer.append("<Exceptions>");
  312. if (!simplified)
  313. {
  314. if (indent) buffer.append("\n\t");
  315. buffer.appendf("<Source>%s</Source>", source_.str());
  316. }
  317. ForEachItemIn(i, array_)
  318. {
  319. IException& exception = array_.item(i);
  320. if (indent) buffer.append("\n\t");
  321. buffer.append("<Exception>");
  322. //tag order is important for some soap clients (i.e. Java Axis)
  323. if (indent) buffer.append("\n\t\t");
  324. buffer.appendf("<Code>%d</Code>", exception.errorCode());
  325. if (indent) buffer.append("\n\t\t");
  326. buffer.appendf("<Audience>%s</Audience>", serializeMessageAudience( exception.errorAudience() ));
  327. if (simplified)
  328. {
  329. if (indent) buffer.append("\n\t\t");
  330. StringBuffer msg;
  331. buffer.appendf("<Source>%s</Source>", source_.str());
  332. }
  333. if (indent) buffer.append("\n\t\t");
  334. StringBuffer msg;
  335. StringBuffer encoded;
  336. encodeXML(exception.errorMessage(msg).str(), encoded);
  337. buffer.appendf("<Message>%s</Message>", encoded.str());
  338. if (indent) buffer.append("\n\t");
  339. buffer.append("</Exception>");
  340. }
  341. if (root)
  342. buffer.append("</Exceptions>");
  343. return buffer;
  344. }
  345. virtual void deserialize(const char* xml)
  346. {
  347. synchronized block(m_mutex);
  348. StringBuffer wrapper;
  349. if (strncmp(xml, "<Exceptions>", 12))
  350. xml = wrapper.appendf("<Exceptions>%s</Exceptions>", xml).str();
  351. Owned<IPropertyTree> pTree = createPTreeFromXMLString(xml);
  352. if (!pTree)
  353. throw makeStringException(-1, "Failed to deserialize IMultiException!");
  354. Owned<IPropertyTreeIterator> i = pTree->getElements("Exception");
  355. if (pTree->hasProp("Source"))
  356. source_.clear().append( pTree->queryProp("Source"));
  357. else
  358. {
  359. if (i->first())
  360. {
  361. IPropertyTree* pNode = &i->query();
  362. source_.clear().append( pNode->queryProp("Source"));
  363. }
  364. }
  365. array_.kill();
  366. ForEach(*i)
  367. {
  368. IPropertyTree* pNode = &i->query();
  369. IException* pException =
  370. makeStringException(
  371. deserializeMessageAudience(pNode->queryProp("Audience")),
  372. pNode->getPropInt("Code", -1),
  373. pNode->queryProp("Message"));
  374. array_.append(*pException);
  375. }
  376. }
  377. //the following methods override those in IIException
  378. //
  379. virtual int errorCode() const
  380. {
  381. synchronized block(m_mutex);
  382. return ordinality() == 1 ? item(0).errorCode() : -1;
  383. }
  384. virtual StringBuffer& errorMessage(StringBuffer &msg) const
  385. {
  386. synchronized block(m_mutex);
  387. ForEachItemIn(i, array_)
  388. {
  389. IException& e = item(i);
  390. StringBuffer buf;
  391. msg.appendf("[%3d: %s] ", e.errorCode(), e.errorMessage(buf).str());
  392. }
  393. return msg;
  394. }
  395. virtual MessageAudience errorAudience() const
  396. {
  397. synchronized block(m_mutex);
  398. return ordinality() == 1 ? item(0).errorAudience() : MSGAUD_unknown;
  399. }
  400. private:
  401. CMultiException( const CMultiException& );
  402. IArrayOf<IException> array_;
  403. StringBuffer source_;
  404. mutable Mutex m_mutex;
  405. };
  406. IMultiException *makeMultiException(const char* source/*=NULL*/)
  407. {
  408. return new CMultiException(source);
  409. }
  410. void pexception(const char *msg,IException *e)
  411. { // like perror except for exceptions
  412. StringBuffer s;
  413. fprintf(stderr,"%s : %s\n",msg,e?e->errorMessage(s).toCharArray():"NULL Exception!");
  414. }
  415. void userBreakpoint()
  416. {
  417. #ifdef _WIN32
  418. try
  419. {
  420. DebugBreak();
  421. }
  422. catch (...)
  423. {
  424. //if not debugging don't give an unhandled exception.
  425. }
  426. #endif
  427. }
  428. void raiseAssertException(const char *assertion, const char *file, unsigned line)
  429. {
  430. printStackReport();
  431. StringBuffer s;
  432. s.append("assert(");
  433. s.append(assertion);
  434. s.append(") failed - file: ");
  435. s.append(file);
  436. s.append(", line ");
  437. s.append(line);
  438. ERRLOG("%s",s.str()); // make sure doesn't get lost!
  439. queryLogMsgManager()->flushQueue(10*1000);
  440. #ifdef _DEBUG
  441. // cause a breakpoint in the debugger if we are debugging.
  442. //userBreakpoint();
  443. #endif
  444. #if 0
  445. #ifndef USING_MPATROL
  446. #ifdef _WIN32
  447. // disable memory leak dump since it is meaningless in this case
  448. int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
  449. tmpFlag &= ~_CRTDBG_LEAK_CHECK_DF;
  450. _CrtSetDbgFlag( tmpFlag );
  451. #endif
  452. #endif
  453. #endif
  454. throw makeStringException(3000, s.toCharArray()); // 3000: internal error
  455. }
  456. void raiseAssertCore(const char *assertion, const char *file, unsigned line)
  457. {
  458. printStackReport();
  459. StringBuffer s;
  460. s.append("assert(");
  461. s.append(assertion);
  462. s.append(") failed - file: ");
  463. s.append(file);
  464. s.append(", line ");
  465. s.append(line);
  466. ERRLOG("%s",s.str()); // make sure doesn't get lost!
  467. queryLogMsgManager()->flushQueue(10*1000);
  468. #ifdef _WIN32
  469. userBreakpoint();
  470. ExitProcess(255);
  471. #else
  472. raise(SIGABRT);
  473. _exit(255);
  474. #endif
  475. }
  476. static int SEHnested = 0;
  477. static IExceptionHandler *SEHHandler = NULL;
  478. static bool SEHtermOnSystemDLLs = false;
  479. static bool SEHtermAlways = false;
  480. #ifdef _WIN32
  481. static void *SEHrestore;
  482. #ifdef EXTENDED_EXCEPTION_TRACE
  483. static LPTSTR GetExceptionString( DWORD dwCode )
  484. {
  485. #define EXCEPTION( x ) case EXCEPTION_##x: return #x;
  486. switch ( dwCode )
  487. {
  488. EXCEPTION( ACCESS_VIOLATION )
  489. EXCEPTION( DATATYPE_MISALIGNMENT )
  490. EXCEPTION( BREAKPOINT )
  491. EXCEPTION( SINGLE_STEP )
  492. EXCEPTION( ARRAY_BOUNDS_EXCEEDED )
  493. EXCEPTION( FLT_DENORMAL_OPERAND )
  494. EXCEPTION( FLT_DIVIDE_BY_ZERO )
  495. EXCEPTION( FLT_INEXACT_RESULT )
  496. EXCEPTION( FLT_INVALID_OPERATION )
  497. EXCEPTION( FLT_OVERFLOW )
  498. EXCEPTION( FLT_STACK_CHECK )
  499. EXCEPTION( FLT_UNDERFLOW )
  500. EXCEPTION( INT_DIVIDE_BY_ZERO )
  501. EXCEPTION( INT_OVERFLOW )
  502. EXCEPTION( PRIV_INSTRUCTION )
  503. EXCEPTION( IN_PAGE_ERROR )
  504. EXCEPTION( ILLEGAL_INSTRUCTION )
  505. EXCEPTION( NONCONTINUABLE_EXCEPTION )
  506. EXCEPTION( STACK_OVERFLOW )
  507. EXCEPTION( INVALID_DISPOSITION )
  508. EXCEPTION( GUARD_PAGE )
  509. EXCEPTION( INVALID_HANDLE )
  510. }
  511. static CHAR szBuffer[512] = { 0 };
  512. FormatMessage( FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
  513. GetModuleHandle( "NTDLL.DLL" ),
  514. dwCode, 0, szBuffer, sizeof( szBuffer ), 0 );
  515. return szBuffer;
  516. }
  517. static BOOL GetLogicalAddress( PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD& offset )
  518. {
  519. szModule[0] = 0;
  520. section = 0;
  521. offset = 0;
  522. if ((unsigned)addr<0x10000)
  523. return FALSE;
  524. MEMORY_BASIC_INFORMATION mbi;
  525. if ( !VirtualQuery( addr, &mbi, sizeof(mbi) ) )
  526. return FALSE;
  527. DWORD hMod = (DWORD)mbi.AllocationBase;
  528. if ( !GetModuleFileName( (HMODULE)hMod, szModule, len ) )
  529. return FALSE;
  530. PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
  531. PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + pDosHdr->e_lfanew);
  532. PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION( pNtHdr );
  533. DWORD rva = (DWORD)addr - hMod;
  534. for (unsigned i = 0; i < pNtHdr->FileHeader.NumberOfSections; i++, pSection++ )
  535. {
  536. DWORD sectionStart = pSection->VirtualAddress;
  537. DWORD sectionEnd = sectionStart
  538. + std::max(pSection->SizeOfRawData, pSection->Misc.VirtualSize);
  539. if ( (rva >= sectionStart) && (rva <= sectionEnd) )
  540. {
  541. section = i+1;
  542. offset = rva - sectionStart;
  543. return TRUE;
  544. }
  545. }
  546. return FALSE;
  547. }
  548. #if defined(_WIN32)
  549. #ifdef __cplusplus
  550. extern "C" {
  551. typedef BOOL (CALLBACK* LPENUMPROCESSMODULES)(HANDLE,HMODULE *,DWORD,LPDWORD);
  552. typedef BOOL (CALLBACK* LPGETMODULEINFORMATION)(HANDLE,HMODULE,LPMODULEINFO,DWORD);
  553. }
  554. #endif
  555. #endif
  556. static void ModuleWalk()
  557. {
  558. HMODULE hmSystem = LoadLibrary("psapi.dll");
  559. if (!hmSystem)
  560. return;
  561. LPENUMPROCESSMODULES enumProcessModules = (LPENUMPROCESSMODULES)GetProcAddress(hmSystem,"EnumProcessModules");
  562. if (!enumProcessModules)
  563. return;
  564. LPGETMODULEINFORMATION getModuleInformation = (LPGETMODULEINFORMATION)GetProcAddress(hmSystem,"GetModuleInformation");
  565. if (!getModuleInformation)
  566. return;
  567. DWORD processID = GetCurrentProcessId();
  568. PrintLog( "Process ID: %u", processID );
  569. // Get a list of all the modules in this process.
  570. HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
  571. PROCESS_VM_READ,
  572. FALSE, processID );
  573. if (NULL == hProcess)
  574. return;
  575. HMODULE hMods[1024];
  576. DWORD cbNeeded;
  577. if (enumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
  578. for (unsigned i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ ) {
  579. char szModName[MAX_PATH];
  580. szModName[0] = 0;
  581. // Get the full path to the module's file.
  582. MODULEINFO modinfo;
  583. memset(&modinfo,0,sizeof(modinfo));
  584. getModuleInformation(hProcess, hMods[i], &modinfo, sizeof(modinfo));
  585. GetModuleFileName( hMods[i], szModName, sizeof(szModName));
  586. PrintLog("%8X %8X %8X %s",(unsigned)modinfo.lpBaseOfDll,(unsigned)modinfo.SizeOfImage,(unsigned)modinfo.EntryPoint,szModName);
  587. }
  588. }
  589. CloseHandle( hProcess );
  590. FreeLibrary(hmSystem);
  591. }
  592. static void StackWalk( size_t pc, size_t bp )
  593. {
  594. PrintLog( "Call stack:" );
  595. PrintLog( "Address Frame Logical addr Module" );
  596. size_t * pFrame;
  597. size_t * pPrevFrame=NULL;
  598. pFrame = (size_t*)bp;
  599. do
  600. {
  601. TCHAR szModule[MAX_PATH] = "";
  602. DWORD section = 0, offset = 0;
  603. if (pc>0x10000)
  604. GetLogicalAddress((PVOID)pc, szModule,sizeof(szModule),section,offset );
  605. else
  606. strcpy(szModule,"NULL");
  607. PrintLog( "%08X %08X %04X:%08X %s",
  608. pc, pFrame, section, offset, szModule );
  609. if ( (size_t)pFrame & 0x80000003 )
  610. break;
  611. if ( (size_t)pFrame <= (size_t)pPrevFrame )
  612. break;
  613. if ( IsBadWritePtr(pFrame, sizeof(PVOID)*2) )
  614. break;
  615. pc = pFrame[1];
  616. if ( IsBadCodePtr((FARPROC) pc) )
  617. break;
  618. pPrevFrame = pFrame;
  619. pFrame = (size_t *)pFrame[0];
  620. } while ( 1 );
  621. }
  622. static void doPrintStackReport( size_t ip, size_t _bp, size_t sp )
  623. {
  624. if (_bp==0) {
  625. #ifdef _ARCH_X86_
  626. __asm {
  627. mov eax,ebp
  628. mov _bp,eax
  629. }
  630. #else
  631. PrintLog("inline assembler is only supported for x86_32; StackReport incomplete bp tend to not be used");
  632. #endif
  633. }
  634. for (unsigned i=0;i<8;i++) {
  635. StringBuffer s;
  636. #ifdef __64BIT__
  637. s.appendf("Stack[%016X]:",sp);
  638. #else
  639. s.appendf("Stack[%08X]:",sp);
  640. #endif
  641. for (unsigned j=0;j<8;j++) {
  642. if ( IsBadReadPtr((const void *)sp, sizeof(unsigned)) )
  643. break;
  644. size_t v = *(size_t *)sp;
  645. sp += sizeof(unsigned);
  646. #ifdef __64BIT__
  647. s.appendf(" %016X",v);
  648. #else
  649. s.appendf(" %08X",v);
  650. #endif
  651. }
  652. PrintLog( "%s",s.str());
  653. }
  654. StackWalk( ip , _bp);
  655. ModuleWalk();
  656. StringBuffer threadlist;
  657. PrintLog( "ThreadList:\n%s",getThreadList(threadlist).str());
  658. }
  659. static void PrintExceptionReport( PEXCEPTION_POINTERS pExceptionInfo)
  660. {
  661. PrintLog("=====================================================");
  662. PrintMemoryStatusLog();
  663. PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
  664. PrintLog( "Exception code: %08X %s",
  665. pExceptionRecord->ExceptionCode,
  666. GetExceptionString(pExceptionRecord->ExceptionCode) );
  667. PrintLog( "Fault address: %08X", pExceptionRecord->ExceptionAddress);
  668. TCHAR szFaultingModule[MAX_PATH];
  669. DWORD section, offset;
  670. GetLogicalAddress( pExceptionRecord->ExceptionAddress,
  671. szFaultingModule,
  672. sizeof( szFaultingModule ),
  673. section, offset );
  674. PrintLog("Fault module: %02X:%08X %s", section, offset, szFaultingModule);
  675. PCONTEXT pCtx = pExceptionInfo->ContextRecord;
  676. PrintLog( "\nRegisters:" );
  677. #ifdef _ARCH_X86_64_
  678. PrintLog("RAX:%016" I64F "X RBX:%016" I64F "X RCX:%016" I64F "X RDX:%016" I64F "X RSI:%016" I64F "X RDI:%016" I64F "X",
  679. pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx, pCtx->Rsi, pCtx->Rdi );
  680. PrintLog( "CS:RIP:%04X:%016" I64F "X", pCtx->SegCs, pCtx->Rip );
  681. PrintLog( "SS:PSP:%04X:%016" I64F "X PBP:%016" I64F "X",
  682. pCtx->SegSs, pCtx->Rsp, pCtx->Rbp );
  683. #elif defined(_ARCH_X86_)
  684. PrintLog("EAX:%08X EBX:%08X ECX:%08X EDX:%08X ESI:%08X EDI:%08X",
  685. pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx, pCtx->Esi, pCtx->Edi );
  686. PrintLog( "CS:EIP:%04X:%08X", pCtx->SegCs, pCtx->Eip );
  687. PrintLog( "SS:ESP:%04X:%08X EBP:%08X",
  688. pCtx->SegSs, pCtx->Esp, pCtx->Ebp );
  689. #else
  690. // ARMFIX: Implement register bank dump for ARM on _WIN32.
  691. PrintLog("Register bank not implemented for your platform");
  692. #endif
  693. PrintLog( "DS:%04X ES:%04X FS:%04X GS:%04X",
  694. pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs );
  695. PrintLog( "Flags:%08X", pCtx->EFlags );
  696. #ifdef _ARCH_X86_64_
  697. doPrintStackReport(pCtx->Rip, pCtx->Rbp,pCtx->Rsp);
  698. #elif defined(_ARCH_X86_)
  699. doPrintStackReport(pCtx->Eip, pCtx->Ebp,pCtx->Esp);
  700. #else
  701. // ARMFIX: Implement stack dump for ARM on _WIN32.
  702. PrintLog("Stack report not implemented for your platform");
  703. #endif
  704. if (SEHtermOnSystemDLLs || SEHtermAlways) {
  705. char *s = szFaultingModule;
  706. while (*s) {
  707. char *sep = strchr(s,'\\');
  708. if (!sep) {
  709. sep = strchr(s,'.');
  710. if (sep)
  711. *sep = 0;
  712. break;
  713. }
  714. s = sep+1;
  715. }
  716. if (SEHtermAlways || (stricmp(s,"ntdll")==0)||(stricmp(s,"kernel32")==0)||(stricmp(s,"msvcrt")==0)||(stricmp(s,"msvcrtd")==0)) {
  717. TerminateProcess(GetCurrentProcess(), 1);
  718. }
  719. }
  720. }
  721. class jlib_thrown_decl CSEHException: public CInterface, public ISEH_Exception
  722. {
  723. public:
  724. IMPLEMENT_IINTERFACE;
  725. CSEHException(unsigned int u, _EXCEPTION_POINTERS* pExp) : errcode((int)u)
  726. {
  727. #ifdef EXTENDED_EXCEPTION_TRACE
  728. PrintExceptionReport(pExp);
  729. #endif
  730. #ifdef ALLREGS
  731. char s[256]; // not too good on stack faults!
  732. sprintf(s,"SEH Exception(%x)\n"
  733. "EAX=%08X EBX=%08X ECX=%08X EDX=%08X ESI=%08X\n"
  734. "EDI=%08X EBP=%08X ESP=%08X EIP=%08X FLG=%08X\n"
  735. "CS=%04X DS=%04X SS=%04X ES=%04X FS=%04X GS=%04X",
  736. u,
  737. pExp->ContextRecord->Eax, pExp->ContextRecord->Ebx,
  738. pExp->ContextRecord->Ecx, pExp->ContextRecord->Edx,
  739. pExp->ContextRecord->Esi, pExp->ContextRecord->Edi,
  740. pExp->ContextRecord->Ebp, pExp->ContextRecord->Esp,
  741. pExp->ContextRecord->Eip, pExp->ContextRecord->EFlags,
  742. pExp->ContextRecord->SegCs, pExp->ContextRecord->SegDs,
  743. pExp->ContextRecord->SegSs, pExp->ContextRecord->SegEs,
  744. pExp->ContextRecord->SegFs, pExp->ContextRecord->SegGs);
  745. #else
  746. char s[80];
  747. #ifdef _ARCH_X86_64_
  748. sprintf(s,"SEH Exception(%08X) at %04X:%016" I64F "X\n",u,pExp->ContextRecord->SegCs,pExp->ContextRecord->Rip);
  749. #elif defined(_ARCH_X86_)
  750. sprintf(s,"SEH Exception(%08X) at %04X:%08X\n",u,pExp->ContextRecord->SegCs,pExp->ContextRecord->Eip);
  751. #else
  752. // ARMFIX: Implement exception dump for ARM on _WIN32.
  753. sprintf(s,"SEH Exception");
  754. #endif
  755. #endif
  756. msg.set(s);
  757. };
  758. int errorCode() const { return errcode; }
  759. StringBuffer & errorMessage(StringBuffer &str) const { str.append(msg); return str;}
  760. MessageAudience errorAudience() const { return MSGAUD_user; }
  761. static void Translate(unsigned int u, _EXCEPTION_POINTERS* pExp)
  762. {
  763. #ifdef _DEBUG
  764. if (u == 0x80000003) return; // int 3 breakpoints
  765. static CriticalSection crit;
  766. {
  767. CriticalBlock b(crit);
  768. PrintExceptionReport(pExp);
  769. }
  770. #endif
  771. ISEH_Exception *e = new CSEHException(u,pExp);
  772. if (SEHHandler && SEHHandler->fireException(e)) return;
  773. throw(e);
  774. }
  775. protected:
  776. int errcode;
  777. StringAttr msg;
  778. };
  779. #endif
  780. #else
  781. #ifdef LINUX_SIGNAL_EXCEPTION
  782. static IException *sigsegv_exc;
  783. static int excsignal;
  784. class jlib_thrown_decl CSEHException: public CInterface, public ISEH_Exception
  785. {
  786. public:
  787. IMPLEMENT_IINTERFACE;
  788. CSEHException(int signum, const char *s)
  789. {
  790. errcode = signum;
  791. msg.set(s);
  792. };
  793. int errorCode() const { return errcode; }
  794. StringBuffer & errorMessage(StringBuffer &str) const { str.append(msg); return str;}
  795. MessageAudience errorAudience() const { return MSGAUD_user; }
  796. protected:
  797. int errcode;
  798. StringAttr msg;
  799. };
  800. static void throwSigSegV()
  801. {
  802. int childpid = fork();
  803. if (childpid <= 0) { // the child
  804. // generate a coredump on different process
  805. signal(excsignal, SIG_DFL);
  806. raise(excsignal);
  807. return;
  808. }
  809. PROGLOG("Dumping core using child process %d",childpid);
  810. waitpid(childpid, NULL, 0);
  811. if (SEHHandler && SEHHandler->fireException(sigsegv_exc))
  812. return;
  813. throw sigsegv_exc;
  814. }
  815. void excsighandler(int signum, siginfo_t *info, void *extra)
  816. {
  817. static byte nested=0;
  818. if (nested++)
  819. return;
  820. #ifdef NO_LINUX_SEH
  821. signal(SIGSEGV, SIG_DFL);
  822. signal(SIGBUS, SIG_DFL);
  823. signal(SIGILL, SIG_DFL);
  824. signal(SIGFPE, SIG_DFL);
  825. #endif
  826. StringBuffer s;
  827. #ifdef _ARCH_X86_64_
  828. #define I64X "%016" I64F "X"
  829. ucontext_t *uc = (ucontext_t *)extra;
  830. #ifdef __APPLE__
  831. __int64 ip = uc->uc_mcontext->__ss.__rip;
  832. __int64 sp = uc->uc_mcontext->__ss.__rsp;
  833. #else
  834. __int64 ip = uc->uc_mcontext.gregs[REG_RIP];
  835. __int64 sp = uc->uc_mcontext.gregs[REG_RSP];
  836. #endif
  837. excsignal = signum;
  838. s.appendf("SIG: %s(%d), accessing "I64X", IP="I64X, strsignal(signum),signum, (__int64)info->si_addr, ip);
  839. PROGLOG("================================================");
  840. PROGLOG("Signal: %d %s",signum,strsignal(signum));
  841. PROGLOG("Fault IP: "I64X"", ip);
  842. PROGLOG("Accessing: "I64X"", (unsigned __int64) info->si_addr);
  843. PROGLOG("Registers:" );
  844. PROGLOG("EAX:"I64X" EBX:"I64X" ECX:"I64X" EDX:"I64X" ESI:"I64X" EDI:"I64X"",
  845. #ifdef __APPLE__
  846. (unsigned __int64) uc->uc_mcontext->__ss.__rax, (unsigned __int64)uc->uc_mcontext->__ss.__rbx,
  847. (unsigned __int64) uc->uc_mcontext->__ss.__rcx, (unsigned __int64)uc->uc_mcontext->__ss.__rdx,
  848. (unsigned __int64) uc->uc_mcontext->__ss.__rsi, (unsigned __int64)uc->uc_mcontext->__ss.__rdi);
  849. PROGLOG( "CS:EIP:%04X:"I64X"", ((unsigned) uc->uc_mcontext->__ss.__cs)&0xffff, ip );
  850. PROGLOG( " ESP:"I64X" EBP:"I64X"", sp, (unsigned __int64) uc->uc_mcontext->__ss.__rbp );
  851. #else
  852. (unsigned __int64) uc->uc_mcontext.gregs[REG_RAX], (unsigned __int64)uc->uc_mcontext.gregs[REG_RBX],
  853. (unsigned __int64) uc->uc_mcontext.gregs[REG_RCX], (unsigned __int64) uc->uc_mcontext.gregs[REG_RDX],
  854. (unsigned __int64) uc->uc_mcontext.gregs[REG_RSI], (unsigned __int64) uc->uc_mcontext.gregs[REG_RDI] );
  855. PROGLOG( "CS:EIP:%04X:"I64X"", ((unsigned) uc->uc_mcontext.gregs[REG_CSGSFS])&0xffff, ip );
  856. PROGLOG( " ESP:"I64X" EBP:"I64X"", sp, (unsigned __int64) uc->uc_mcontext.gregs[REG_RBP] );
  857. #endif
  858. for (unsigned i=0;i<8;i++) {
  859. StringBuffer s;
  860. s.appendf("Stack["I64X"]:",sp);
  861. for (unsigned j=0;j<8;j++) {
  862. __int64 v = *(size_t *)sp;
  863. sp += sizeof(unsigned);
  864. s.appendf(" "I64X"",v);
  865. }
  866. PROGLOG( "%s",s.str());
  867. }
  868. #elif defined (__linux__) && defined (_ARCH_X86_)
  869. ucontext_t *uc = (ucontext_t *)extra;
  870. unsigned ip = uc->uc_mcontext.gregs[REG_EIP];
  871. unsigned sp = uc->uc_mcontext.gregs[REG_ESP];
  872. excsignal = signum;
  873. s.appendf("SIG: %s(%d), accessing %p, IP=%x", strsignal(signum),signum, info->si_addr, ip);
  874. PROGLOG("================================================");
  875. PROGLOG("Signal: %d %s",signum,strsignal(signum));
  876. PROGLOG("Fault IP: %08X", ip);
  877. PROGLOG("Accessing: %08X", info->si_addr);
  878. PROGLOG("Registers:" );
  879. PROGLOG("EAX:%08X EBX:%08X ECX:%08X EDX:%08X ESI:%08X EDI:%08X",
  880. uc->uc_mcontext.gregs[REG_EAX], uc->uc_mcontext.gregs[REG_EBX],
  881. uc->uc_mcontext.gregs[REG_ECX], uc->uc_mcontext.gregs[REG_EDX],
  882. uc->uc_mcontext.gregs[REG_ESI], uc->uc_mcontext.gregs[REG_EDI] );
  883. PROGLOG( "CS:EIP:%04X:%08X", uc->uc_mcontext.gregs[REG_CS], ip );
  884. PROGLOG( "SS:ESP:%04X:%08X EBP:%08X",
  885. uc->uc_mcontext.gregs[REG_SS], sp, uc->uc_mcontext.gregs[REG_EBP] );
  886. for (unsigned i=0;i<8;i++) {
  887. StringBuffer s;
  888. s.appendf("Stack[%08X]:",sp);
  889. for (unsigned j=0;j<8;j++) {
  890. size_t v = *(size_t *)sp;
  891. sp += sizeof(unsigned);
  892. s.appendf(" %08X",v);
  893. }
  894. PROGLOG( "%s",s.str());
  895. }
  896. PROGLOG("Frame:");
  897. unsigned* bp = (unsigned*) (uc->uc_mcontext.gregs[REG_EBP]);
  898. for (unsigned n=0; n<64; n++) {
  899. unsigned * nextbp = (unsigned *) *bp++;
  900. unsigned fip = *bp;
  901. if ((fip < 0x08000000) || (fip > 0x7fffffff) || (nextbp < bp))
  902. break;
  903. PROGLOG("%2d %08X %08X",n+1,fip,(unsigned) bp);
  904. bp = nextbp;
  905. }
  906. #elif defined (__linux__) && defined (__ARM_ARCH_7A__)
  907. #pragma message "Implement signal dump for ARMv7-A."
  908. ucontext_t *uc = (ucontext_t *) extra;
  909. PROGLOG("================================================");
  910. PROGLOG("Signal: %d %s",signum,strsignal(signum));
  911. PROGLOG("Registers:" );
  912. PROGLOG("r0 :%08lX r1 :%08lX r2 :%08lX r3 :%08lX r4 :%08lX r5 :%08lX",
  913. uc->uc_mcontext.arm_r0, uc->uc_mcontext.arm_r1, uc->uc_mcontext.arm_r2,
  914. uc->uc_mcontext.arm_r3, uc->uc_mcontext.arm_r4, uc->uc_mcontext.arm_r5);
  915. PROGLOG("r6 :%08lX r7 :%08lX r8 :%08lX r9 :%08lX r10:%08lX fp :%08lX",
  916. uc->uc_mcontext.arm_r6, uc->uc_mcontext.arm_r7, uc->uc_mcontext.arm_r8,
  917. uc->uc_mcontext.arm_r9, uc->uc_mcontext.arm_r10, uc->uc_mcontext.arm_fp);
  918. PROGLOG("ip :%08lX sp :%08lX lr :%08lX pc :%08lX",
  919. uc->uc_mcontext.arm_ip, uc->uc_mcontext.arm_sp, uc->uc_mcontext.arm_lr,
  920. uc->uc_mcontext.arm_pc);
  921. PROGLOG("CPSR:%08lX\n", uc->uc_mcontext.arm_cpsr);
  922. struct flags
  923. {
  924. unsigned int Mode:4; // bit 0 - 3
  925. unsigned int M:1; // bit 4
  926. unsigned int T:1; // bit 5
  927. unsigned int F:1; // bit 6
  928. unsigned int I:1; // bit 7
  929. unsigned int A:1; // bit 8
  930. unsigned int E:1; // bit 9
  931. unsigned int IT1:6; // bit 10 - 15
  932. unsigned int GE:4; // bit 16 - 19
  933. unsigned int DNM:4; // bit 20 - 23
  934. unsigned int J:1; // bit 24
  935. unsigned int IT2:2; // bit 25 - 26
  936. unsigned int Q:1; // bit 27
  937. unsigned int V:1; // bit 28
  938. unsigned int C:1; // bit 29
  939. unsigned int Z:1; // bit 30
  940. unsigned int N:1; // bit 31
  941. } *flags_p;
  942. const char *ArmCpuModes[] = {
  943. // M M[3:0]
  944. "User", // 1 0000
  945. "FIQ", // 1 0001
  946. "IRQ", // 1 0010
  947. "Supervisor", // 1 0011
  948. "N/A", // 1 0100
  949. "N/A", // 1 0101
  950. "Monitor", // 1 0110
  951. "Abort", // 1 0111
  952. "N/A", // 1 1000
  953. "N/A", // 1 1001
  954. "Hyp" // 1 1010
  955. "Undefined", // 1 1011
  956. "N/A", // 1 1100
  957. "N/A", // 1 1101
  958. "N/A", // 1 1110
  959. "System" // 1 1111
  960. };
  961. flags_p = (struct flags *)&uc->uc_mcontext.arm_cpsr;
  962. PROGLOG("Flags N:%d Z:%d C:%d V:%d Q:%d IT:0x%X J:%d GE:0x%X E:%d A:%d I:%d F:%d T:%d M:0x%X [%s]"
  963. , flags_p->N, flags_p->Z, flags_p->C, flags_p->V, flags_p->Q
  964. , (flags_p->IT2 << 6 | flags_p->IT1)
  965. , flags_p->J, flags_p->GE
  966. , flags_p->E, flags_p->A, flags_p->I, flags_p->F, flags_p->T, (flags_p->M << 4 | flags_p->Mode)
  967. , ArmCpuModes[flags_p->Mode]
  968. );
  969. PROGLOG("Fault address: %08lX", uc->uc_mcontext.fault_address);
  970. PROGLOG("Trap no : %08lX", uc->uc_mcontext.trap_no);
  971. PROGLOG("Error code : %08lX", uc->uc_mcontext.error_code);
  972. PROGLOG("Old mask : %08lX", uc->uc_mcontext.oldmask);
  973. unsigned sp = uc->uc_mcontext.arm_sp;
  974. for (unsigned i=0;i<8;i++)
  975. {
  976. StringBuffer s;
  977. s.appendf("Stack[%08X]:",sp);
  978. for (unsigned j=0;j<8;j++)
  979. {
  980. size_t v = *(size_t *)sp;
  981. sp += sizeof(unsigned);
  982. s.appendf(" %08X",v);
  983. }
  984. }
  985. PROGLOG( "%s",s.str());
  986. #elif defined (__linux__) && defined (__arm__)
  987. #pragma message "Unknown ARM architecture!"
  988. PROGLOG("================================================");
  989. PROGLOG("Signal: %d %s",signum,strsignal(signum));
  990. PROGLOG("More information unavailable on your platform");
  991. #else
  992. // Placeholder for any new HW-SW platform
  993. #endif
  994. #ifdef _EXECINFO_H
  995. printStackReport();
  996. #endif
  997. StringBuffer threadlist;
  998. PROGLOG( "ThreadList:\n%s",getThreadList(threadlist).str());
  999. queryLogMsgManager()->flushQueue(10*1000);
  1000. #ifndef NO_LINUX_SEH
  1001. void (* _P)() = throwSigSegV;
  1002. uc->uc_mcontext.gregs[REG_ESP]-=4;
  1003. uc->uc_mcontext.gregs[REG_EIP] = (unsigned)_P;
  1004. unsigned *spp = (unsigned *)sp;
  1005. *spp = ip;
  1006. sigsegv_exc = new CSEHException(signum,s.str());
  1007. #else
  1008. if (SEHHandler && SEHHandler->fireException(new CSEHException(signum,s.str())))
  1009. return;
  1010. #endif
  1011. nested--;
  1012. }
  1013. #endif
  1014. #endif
  1015. void jlib_decl setTerminateOnSEHInSystemDLLs(bool set)
  1016. {
  1017. SEHtermOnSystemDLLs = set;
  1018. }
  1019. void jlib_decl setTerminateOnSEH(bool set)
  1020. {
  1021. SEHtermAlways = set;
  1022. }
  1023. void *EnableSEHtranslation()
  1024. {
  1025. #ifdef NOSEH
  1026. return NULL;
  1027. #else
  1028. #ifdef _WIN32
  1029. return _set_se_translator( CSEHException::Translate );
  1030. #else
  1031. UNIMPLEMENTED;
  1032. #endif
  1033. #endif
  1034. }
  1035. void jlib_decl *setSEHtoExceptionHandler(IExceptionHandler *handler)
  1036. {
  1037. #ifdef NOSEH
  1038. return NULL;
  1039. #endif
  1040. void *ret = SEHHandler;
  1041. SEHHandler = handler;
  1042. return ret;
  1043. }
  1044. void jlib_decl enableSEHtoExceptionMapping()
  1045. {
  1046. #ifdef NOSEH
  1047. return;
  1048. #endif
  1049. if (SEHnested++)
  1050. return; // already done
  1051. #ifdef _WIN32
  1052. enableThreadSEH();
  1053. SEHrestore = EnableSEHtranslation();
  1054. #else
  1055. struct sigaction act;
  1056. sigset_t blockset;
  1057. sigemptyset(&blockset);
  1058. act.sa_mask = blockset;
  1059. act.sa_flags = SA_SIGINFO;
  1060. act.sa_sigaction = &excsighandler;
  1061. sigaction(SIGSEGV, &act, NULL);
  1062. sigaction(SIGILL, &act, NULL);
  1063. sigaction(SIGBUS, &act, NULL);
  1064. sigaction(SIGFPE, &act, NULL);
  1065. #endif
  1066. }
  1067. void jlib_decl disableSEHtoExceptionMapping()
  1068. {
  1069. #ifdef NOSEH
  1070. return;
  1071. #endif
  1072. if (--SEHnested)
  1073. return;
  1074. #ifdef _WIN32
  1075. if (SEHrestore) {
  1076. void *restore = SEHrestore;
  1077. SEHrestore = NULL;
  1078. _set_se_translator( (_se_translator_function)restore );
  1079. }
  1080. #else
  1081. signal(SIGSEGV, SIG_DFL);
  1082. signal(SIGBUS, SIG_DFL);
  1083. signal(SIGILL, SIG_DFL);
  1084. signal(SIGFPE, SIG_DFL);
  1085. #endif
  1086. }
  1087. StringBuffer & formatSystemError(StringBuffer & out, unsigned errcode)
  1088. {
  1089. #ifdef _WIN32
  1090. const char * lpMessageBuffer=NULL;
  1091. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  1092. NULL,
  1093. errcode,
  1094. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default
  1095. (LPTSTR) &lpMessageBuffer,
  1096. 0,
  1097. NULL );
  1098. if (lpMessageBuffer) {
  1099. out.append(lpMessageBuffer);
  1100. LocalFree( (void *)lpMessageBuffer );
  1101. }
  1102. else {
  1103. out.append(errcode);
  1104. }
  1105. #else
  1106. int saverr = errno;
  1107. errno = 0;
  1108. const char *errstr = strerror(errcode);
  1109. if (errno==0) {
  1110. out.append(errstr);
  1111. }
  1112. else {
  1113. out.append(errcode);
  1114. }
  1115. errno = saverr;
  1116. #endif
  1117. return out;
  1118. }
  1119. IException * deserializeException(MemoryBuffer & in)
  1120. {
  1121. byte nulle;
  1122. in.read(nulle);
  1123. if (nulle) return NULL;
  1124. int code;
  1125. StringAttr text;
  1126. in.read(code);
  1127. in.read(text);
  1128. return makeStringExceptionV(code, "%s", text.get());
  1129. }
  1130. void jlib_decl serializeException(IException * e, MemoryBuffer & out)
  1131. {
  1132. if (!e)
  1133. out.append((byte)1);
  1134. else
  1135. {
  1136. out.append((byte)0);
  1137. StringBuffer text;
  1138. out.append(e->errorCode());
  1139. out.append(e->errorMessage(text).str());
  1140. }
  1141. }
  1142. void printStackReport()
  1143. {
  1144. #ifdef _WIN32
  1145. unsigned onstack=1234;
  1146. doPrintStackReport(0, 0,(unsigned)&onstack);
  1147. #elif defined(__linux__)
  1148. DBGLOG("Backtrace:");
  1149. void *btarray[100];
  1150. unsigned btn = backtrace (btarray, 100);
  1151. char **strings = backtrace_symbols (btarray, btn);
  1152. for (unsigned i=0; i<btn; i++)
  1153. DBGLOG(" %s", strings[i]);
  1154. free (strings);
  1155. #endif
  1156. queryLogMsgManager()->flushQueue(10*1000);
  1157. }