1éš
2éš
ãã³ãããã®äžã®C ++äŸå€ïŒé©åãªã©ã³ãã£ã³ã°ããããèŠã€ãã
ããã¯ç§ãã¡ã®é·ãæŽå²ã®äžã§15çªç®ã®ç« ã§ãã äŸå€ãã©ã®ããã«æ©èœãããã«ã€ããŠã¯ãã§ã«å€ãã®ããšãåŠã³ãŸããããŸãããã£ãããããã¯ã®å Žæã決å®ããå°éã®ãªãã¬ã¯ã·ã§ã³ïŒäŸå€ã«é¢ããã©ã³ãã£ã³ã°ãããïŒãåããç¬èªã®æ©èœãèšè¿°ããŸããã åã®ç« ã§ã¯ãäŸå€ãåŠçã§ããå人çšé¢æ°ãäœæããŸããããåžžã«æåã®ã©ã³ãã£ã³ã°ãããïŒã€ãŸããæåã®catchãããã¯ïŒã®ã¿ã眮ãæããŸãã ããã€ãã®ãã£ãããããã¯ãããé¢æ°ã§é©åãªã©ã³ãã£ã³ã°ããããéžæããæ©èœãè¿œå ããŠãå人ã®æ©èœãæ¹åããŸãããã
TDDïŒãã¹ãé§åéçºïŒmodã«ç¶ããŠãæåã«ABIã®ãã¹ããäœæã§ããŸãã ããã°ã©ã throw.cppãæ¹åããããã€ãã®try / catchãããã¯ãäœæããŸãã
#include <stdio.h> #include "throw.h" struct Fake_Exception {}; void raise() { throw Exception(); } void try_but_dont_catch() { try { printf("Running a try which will never throw.\n"); } catch(Fake_Exception&) { printf("Exception caught... with the wrong catch!\n"); } try { raise(); } catch(Fake_Exception&) { printf("Caught a Fake_Exception!\n"); } printf("try_but_dont_catch handled the exception\n"); } void catchit() { try { try_but_dont_catch(); } catch(Fake_Exception&) { printf("Caught a Fake_Exception!\n"); } catch(Exception&) { printf("Caught an Exception!\n"); } printf("catchit handled the exception\n"); } extern "C" { void seppuku() { catchit(); } }
ãã¹ãããåã«ããã®ãã¹ãã®ç«ã¡äžãäžã«äœãèµ·ãããèããŠã¿ãŠãã ããã try_but_dont_catché¢æ°ã«æ³šç®ããŠãã ãããæåã®try / catchãããã¯ã¯äŸå€ãã¹ããŒããã2çªç®ã®ãããã¯ã¯ãã£ããããã«ã¹ããŒããŸãã ABIãå°ãéãéããæåã®catchãããã¯ã¯2çªç®ã®ãããã¯ã®äŸå€ãåŠçããŸãã ããããæåã®ãã£ãããåŠçãããåŸã¯ã©ããªããŸããïŒ å®è¡ã¯ãæåã®catch / tryãçµäºããå Žæããç¶è¡ãããåã³äŸå€ãã¹ããŒãã2çªç®ã®try / catchãããã¯ã®çŽåã«ãªããŸããããã«ãããæåã®ãã³ãã©ãŒã¯åã³åŠçããŸãã ç¡éã«ãŒãïŒ ããŠãåã³ïŒæ¬åœã®ïŒéåžžã«è€éã«ãªããŸããïŒ
LSDAããŒãã«ã®éå§/é·ããã£ãŒã«ãã®ç¥èã䜿çšããŠãçéžããããæ£ããéžæããŸãã ãããè¡ãã«ã¯ãäŸå€ãã¹ããŒããããšãã«IPãäœã§ãã£ãããç¥ãå¿ èŠãããããã§ã«ç¥ã£ãŠããUnwindé¢æ°_Unwind_GetIPã§ãããææ¡ã§ããŸãã _Unwind_GetIPãè¿ãå 容ãç解ããããã«ãäŸãèŠãŠã¿ãŸãããã
void f1() {} void f2() { throw 1; } void f3() {} void foo() { L1: try{ f1(); } catch(...) {} L2: try{ f2(); } catch(...) {} L3: try{ f3(); } catch(...) {} }
ãã®å Žåãf2ã®catchãããã¯ã§ããŒãœãã«é¢æ°ãåŒã³åºãããã¹ã¿ãã¯ã¯æ¬¡ã®ããã«ãªããŸãã
+------------------------------+ | IP: f2 stack frame: f2 | +------------------------------+ | IP: L3 stack frame: foo | +------------------------------+
IPã¯L3ã«èšå®ãããŸãããL2ã§äŸå€ãã¹ããŒãããããšã«æ³šæããŠãã ããã ããã¯ãIPãå®è¡ãããã¹ã次ã®åœä»€ã瀺ãããã§ãã ããã¯ãäŸå€ãã¹ããŒãããIPãååŸããå Žåã¯1ãæžç®ããå¿ èŠãããããšãæå³ããŸããããããªããšã_Unwind_GetIPã®çµæãã©ã³ãã£ã³ã°ãããã®å€åŽã«ãªãå¯èœæ§ããããŸãã ããŒãœãã«æ©èœã«æ»ããŸãïŒ
_Unwind_Reason_Code __gxx_personality_v0 ( int version, _Unwind_Action actions, uint64_t exceptionClass, _Unwind_Exception* unwind_exception, _Unwind_Context* context) { if (actions & _UA_SEARCH_PHASE) { printf("Personality function, lookup phase\n"); return _URC_HANDLER_FOUND; } else if (actions & _UA_CLEANUP_PHASE) { printf("Personality function, cleanup\n"); // -- IP // , uintptr_t throw_ip = _Unwind_GetIP(context) - 1; // LSDA LSDA_ptr lsda = (uint8_t*)_Unwind_GetLanguageSpecificData(context); // LSDA LSDA_Header header(&lsda); // LSDA CS LSDA_CS_Header cs_header(&lsda); // LSDA CS const LSDA_ptr lsda_cs_table_end = lsda + cs_header.length; // CS while (lsda < lsda_cs_table_end) { LSDA_CS cs(&lsda); // LP, , if (not cs.lp) continue; uintptr_t func_start = _Unwind_GetRegionStart(context); // IP lp // LP , // IP uintptr_t try_start = func_start + cs.start; uintptr_t try_end = func_start + cs.start + cs.len; // : LP try if (throw_ip < try_start) continue; if (throw_ip > try_end) continue; // landing pad ; int r0 = __builtin_eh_return_data_regno(0); int r1 = __builtin_eh_return_data_regno(1); _Unwind_SetGR(context, r0, (uintptr_t)(unwind_exception)); // , ; // _Unwind_SetGR(context, r1, (uintptr_t)(1)); _Unwind_SetIP(context, func_start + cs.lp); break; } return _URC_INSTALL_CONTEXT; } else { printf("Personality function, error\n"); return _URC_FATAL_PHASE1_ERROR; } } }
ãã€ãã®ããã«ãçŸåšã®ãµã³ãã«ã³ãŒãã¯ãã¡ãã§ãã
ããäžåºŠå®è¡ããŠãåºæ¥äžããïŒ ç¡éã«ãŒãã¯ãããããŸããïŒ ç°¡åãªå€æŽã«ãããé©åãªã©ã³ãã£ã³ã°ããããéžæã§ããŸããã 次ã«ãæåã®ä»£ããã«æ£ããã¹ã¿ãã¯ãã¬ãŒã ãéžæããããã«å人æ©èœãæããŸãã
ãã³ãããã®äžã®C ++äŸå€ïŒã©ã³ãã£ã³ã°ãããã§é©åãªãã£ãããããã¯ãèŠã€ãã
è€æ°ã®ã©ã³ãã£ã³ã°ããããåããæ©èœãåŠçã§ããå人çšæ©èœãæ¢ã«äœæããŸããã ããã§ãã©ã®ç¹å®ã®ãããã¯ãç¹å®ã®äŸå€ãåŠçã§ããããèšãæãããšãã©ã®ãããã¯ããã£ããããŠç§ãã¡ãåŒã³åºãããèªèããããšããŸãã
ãã¡ãããã©ã®ãããã¯ãäŸå€ãåŠçã§ããããå€æããã®ã¯ç°¡åãªããšã§ã¯ãããŸããã ããããããªãã¯æ¬åœã«äœãä»ã®ãã®ãæåŸ ããŠããŸãããïŒ çŸåšã®äž»ãªåé¡ã¯æ¬¡ã®ãšããã§ãã
- æåãšã¡ã€ã³ïŒãã®catch-blockã§åãå ¥ããããã¿ã€ãã®äŸå€ãã©ãã§ã©ã®ããã«èŠã€ããããšãã§ããŸãã
- ãã£ããã¿ã€ããèŠã€ããããšãã§ãããšããŠããã©ã®ããã«ãã£ãããåŠçã§ããŸããïŒ...ïŒïŒ
- è€æ°ã®ãã£ãããããã¯ãããã©ã³ãã£ã³ã°ãããã®å Žåãå¯èœãªãã¹ãŠã®ãã£ããã¿ã€ããã©ã®ããã«èŠã€ããããšãã§ããŸããïŒ
- äŸãèŠãŠã¿ãŸãããïŒ
struct Base {}; struct Child : public Base {}; void foo() { throw Child; } void bar() { try { foo(); } catch(const Base&){ ... } }
çŸåšã®ã©ã³ãã£ã³ã°ããããçŸåšã®äŸå€ãåãå ¥ããããšãã§ãããã©ããã ãã§ãªãããã®ãã¹ãŠã®èŠªããã§ãã¯ããå¿ èŠããããŸãã
ã¿ã¹ã¯ãããå°ãç°¡åã«ããŠã¿ãŸãããããã£ãããããã¯ã1ã€ãããªãã©ã³ãã£ã³ã°ãããã䜿çšããŸãããŸããç¶æ¿ã¯ãããŸããã ããããã©ã®ããã«ããŠåãå ¥ãããããããã¿ã€ããèŠã€ããã®ã§ããããïŒ
äžè¬ã«ãããã¯.gcc_except_tableéšåã«ãããŸããããŸã åæããŠããŸããïŒã¢ã¯ã·ã§ã³ããŒãã«ã throw.cppã§éã¢ã»ã³ãã«ãããtry but dont catchãé¢æ°ã®åŒã³åºããµã€ãããŒãã«ã®ããåŸã«ãããã®ã確èªããŸãã
LLSDACSE1: .byte 0x1 .byte 0 .align 4 .long _ZTI14Fake_Exception .LLSDATT1:
å€ãã®æ å ±ãããããã«ã¯èŠããŸããããäŸå€ã®ååãæã€äœããžã®ææãªãã€ã³ã¿ãŒããããŸãã _ZTI14Fake_Exceptionã®å®çŸ©ãèŠãŠã¿ãŸãããã
_ZTI14Fake_Exception: .long _ZTVN10__cxxabiv117__class_type_infoE+8 .long _ZTS14Fake_Exception .weak _ZTS9Exception .section .rodata._ZTS9Exception,"aG",@progbits,_ZTS9Exception,comdat .type _ZTS9Exception, @object .size _ZTS9Exception, 11
éåžžã«èå³æ·±ããã®ãèŠã€ãããŸããïŒ èªèã§ããŸããïŒ ããã¯std :: Fake_Exceptionæ§é äœã®type_infoã§ãïŒ
ããã§ãäŸå€ã«å¯Ÿããäžçš®ã®ãªãã¬ã¯ã·ã§ã³ãžã®ãã€ã³ã¿ãŒãååŸããæ¹æ³ãããããšãããããŸããã ããã°ã©ã ã§ãããèŠã€ããããšãã§ããŸããïŒ ããã«èŠãŠã¿ãŸãããã
å éšã®C ++äŸå€ïŒäŸå€ã¿ã€ãã®ãªãã¬ã¯ã·ã§ã³ãšèªã¿åã.gcc_except_table
ããã§ãããŒã«ã«ããŒã¿ã¹ãã¢.gcc_except_tableãèªã¿åãããšã§ãäŸå€ã«é¢ããå€ãã®æ å ±ãååŸã§ããå ŽæãããããŸããã æ£ããã©ã³ãã£ã³ã°ãããã決å®ããããã«å人æ©èœã«å®è£ ããå¿ èŠããããã®ã
ABIã®å®è£ ãæŸæ£ãã.gcc_except_tableã®ã¢ã»ã³ãã©ãŒèª¿æ»ã«çªå ¥ããŠãåŠçå¯èœãªäŸå€ã®çš®é¡ãèŠã€ããæ¹æ³ãç解ããŸããã ããŒãã«ã®äžéšã«ãå¿ èŠãªæ å ±ãå«ãã¿ã€ãã®ãªã¹ããå«ãŸããŠããããšãããããŸããã ã¯ãªãŒã³ã¢ãããã§ãŒãºã§ãã®æ å ±ãèªã¿åããŸãããæåã«ãLSDAããããŒã®å®çŸ©ãæãåºããŠã¿ãŸãããã
struct LSDA_Header { uint8_t start_encoding; uint8_t type_encoding; // uint8_t type_table_offset; };
æåŸã®ãã£ãŒã«ãã¯ãç§ãã¡ã«ãšã£ãŠæ°ãããã®ã§ããããã¯ãã¿ã€ãããŒãã«ã®ãªãã»ããã瀺ããŸãã ååŒã³åºãã®å®çŸ©ãæãåºããŠãã ããã
struct LSDA_CS { // uint8_t start; // , uint8_t len; // Landing pad uint8_t lp; // action table + 1 (0 " ") uint8_t action; };
æåŸã®ãã£ãŒã«ããã¢ã¯ã·ã§ã³ããèŠãŠãã ããã ããã¯ãã¢ã¯ã·ã§ã³ããŒãã«ã®ãªãã»ããã§ãã ããã¯ãç¹å®ã®CSïŒåŒã³åºããµã€ãïŒã®ã¢ã¯ã·ã§ã³ãèŠã€ããããšãã§ããããšãæå³ããŸãã ããªãã¯ã¯ããã£ãããããã¯ãããã©ã³ãã£ã³ã°ãããã®å Žåãã¢ã¯ã·ã§ã³ã«ã¿ã€ãããŒãã«ãžã®ãªãã»ãããå«ãŸããŠããããšã§ãããªãã»ããã䜿çšããŠãããããŒããååŸã§ããã¿ã€ãããŒãã«ãååŸã§ããããã«ãªããŸããã 話ããããŠãã³ãŒããããèŠãŠãã ããïŒ
// LSDA LSDA_ptr lsda = (uint8_t*)_Unwind_GetLanguageSpecificData(context); // LSDA LSDA_Header header(&lsda); const LSDA_ptr types_table_start = lsda + header.type_table_offset; // LSDA CS LSDA_CS_Header cs_header(&lsda); // LSDA CS const LSDA_ptr lsda_cs_table_end = lsda + cs_header.length; // action tables const LSDA_ptr action_tbl_start = lsda_cs_table_end; // call site LSDA_CS cs(&lsda); // cs.action -- offset + 1; cs.action == 0 // const size_t action_offset = cs.action - 1; const LSDA_ptr action = action_tbl_start + action_offset; // landing pad catch the action table // index int type_index = action[0]; // types_table_start , // type_index. ptr // std::type_info, catch- const void* catch_type_info = types_table_start[ -1 * type_index ]; const std::type_info *catch_ti = (const std::type_info *) catch_type_info; // , - Fake_Exception printf("%s\n", catch_ti->name());
ãã®ã³ãŒãã¯ãtype_infoæ§é ãååŸããåã®éæ¥çãªã¢ãã¬ã¹æå®ãé£ç¶ããŠããããè€éã«èŠããŸãããå®éã«ã¯è€éãªåŠçã¯è¡ãããéã¢ã»ã³ãã«æã«èŠã€ãã£ã.gcc_except_tableãèªã¿åããŸãã
äŸå€ã¿ã€ãã®å°åºã¯ãæ£ããæ¹åãžã®å€§ããªäžæ©ã§ãã ãŸããç§ãã¡ã®å人çãªæ©èœãå°ãéãªã£ãŠããŸãã ã»ãšãã©ã®LSDAã®èªã¿åãã®åé¡ã¯ã«ãŒãããã®äžã«é ããŠããå¯èœæ§ããããŸããããã¯ããŸãé«äŸ¡ã§ã¯ãªãã¯ãã§ãïŒã€ãŸããå¥ã®æ©èœã«é 眮ããïŒã
ããã«ãåŠçãããäŸå€ã®ã¿ã€ããšã¹ããŒãããã¿ã€ããæ¯èŒããæ¹æ³ãåŠç¿ããŸãã
å éšã®C ++äŸå€ïŒé©åãªã¹ã¿ãã¯ãã¬ãŒã ã®ååŸ
ããŒãœãã«é¢æ°ã®ææ°ããŒãžã§ã³ã¯ããã®äŸå€ãåŠçã§ãããã©ããã«é¢ããæ å ±ã®æ ŒçŽå Žæãç¥ã£ãŠããŸãïŒãã ãã1ã€ã®try / catchãããã¯ã®1ã€ã®catchãããã¯ã§ã®ã¿æ©èœããç¶æ¿ããããŸããïŒãæåã«ãäŸå€ãåŠçå¯èœãªã¿ã€ãã®ãã®ã§ãããã©ããã確èªããŸãã
ãã¡ãããæåã«äŸå€ã®ã¿ã€ããèŠã€ããå¿ èŠããããŸãã ãããè¡ãã«ã¯ã __ cxa_throwãåŒã³åºããããšãã«èšé²ããå¿ èŠããããŸãã
void __cxa_throw(void* thrown_exception, std::type_info *tinfo, void (*dest)(void*)) { __cxa_exception *header = ((__cxa_exception *) thrown_exception - 1); // , _Unwind_ // header->exceptionType = tinfo; _Unwind_RaiseException(&header->unwindHeader); }
ãããŠãããŒãœãã«é¢æ°ã§äŸå€ã®åãèªã¿åããåã®äžèŽãåçŽã«æ¯èŒã§ããŸãïŒäŸå€ã®ååã¯C ++è¡ãªã®ã§ãåçŽãªã==ãã§ååã§ãïŒã
// const void* catch_type_info = lsda.types_table_start[ -1 * type_index ]; const std::type_info *catch_ti = (const std::type_info *) catch_type_info; // __cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1; std::type_info *org_ex_type = exception_header-&gt;exceptionType; printf("%s thrown, catch handles %s\n", org_ex_type->name(), catch_ti->name()); // : // if (org_ex_type->name() != catch_ti->name()) continue;
gitã®ææ°ã®å€æŽãèŠãŠãã ããã
ããŒãããã¡ããåé¡ã¯ãããŸãããèªåã§èŠã€ããããŸããïŒ äŸå€ã2ã€ã®æ®µéã§ã¹ããŒãããæåã®æ®µéã§äŸå€ãåŠçãããå Žåã2床ç®ã«ã¯å床åŠçããããªããšã¯èšããŸããã _Unwindããã®ã±ãŒã¹ãåŠçããŸãããããã¥ã¡ã³ãããªããããæªå®çŸ©ã®åäœãçºçããå¯èœæ§ãé«ãããããã¹ãŠãé£ç¶ããŠåŠçããã ãã§ã¯ååã§ã¯ãããŸããã
ã©ã®ã©ã³ãã£ã³ã°ããããäŸå€ãåŠçã§ããããèŠã€ããããã«å人çãªæ©èœãæããŠããéããã©ã®äŸå€ãåŠçã§ãããã«ã€ããŠUnwindã«åãã€ããŸããã代ããã«ãABI 9ã§ãã¹ãŠãåŠçãããšèšããŸããçå®ã¯ããããŸãããåŠçãããã©ããã ããã¯åãªãä¿®æ£ã§ãã次ã®ãããªããšãã§ããŸãã
_Unwind_Reason_Code __gxx_personality_v0 (...) { printf("Personality function, searching for handler\n"); // ... foreach (call site entry in lsda) { if (call site entry.not_good()) continue; // landing pad ; // , _Unwind_, if (actions & _UA_SEARCH_PHASE) return _URC_HANDLER_FOUND; // , _UA_CLEANUP_PHASE /* */ return _URC_INSTALL_CONTEXT; } return _URC_CONTINUE_UNWIND; }
ããŒãœãã«æ©èœãèµ·åãããšãäœãåŸãããŸããïŒ ç§ïŒ 誰ãçãã§ãããã èœäžæ©èœãèŠããŠããŸããïŒ äŸå€ããã£ãããããã®ã¯æ¬¡ã®ãšããã§ãã
void catchit() { try { try_but_dont_catch(); } catch(Fake_Exception&) { printf("Caught a Fake_Exception!\n"); } catch(Exception&) { printf("Caught an Exception!\n"); } printf("catchit handled the exception\n"); }
æ®å¿µãªãããç§ãã¡ã®å人çãªæ©èœã¯ãã©ã³ãã£ã³ã°ããããåŠçã§ããæåã®ã¿ã€ãã®ãšã©ãŒã®ã¿ããã§ãã¯ããŸãã Fake_Exception catchãããã¯ãåé€ããŠåè©Šè¡ãããšããã¹ãŠãæ£ããæ©èœããŸãã ç§ãã¡ã®å人çãªæ©èœã¯ãåäžã®catchãããã¯ãæã€try-catchãããã¯ã«ãã£ãŠæäŸãããæ£ãããã¬ãŒã å ã®æ£ããcatchãããã¯ãéžæã§ããŸãã
次ã®ç« ã§ã¯ãåã³æ¹åããŸãïŒ
ãã³ãããã®äžã®C ++äŸå€ïŒã©ã³ãã£ã³ã°ãããããé©åãªãã£ãããéžæãã
C ++ã®äŸå€ã«é¢ãã第19ç« ïŒLSDAãèªã¿åããé©åãªã©ã³ãã£ã³ã°ããããé©åãªã¹ã¿ãã¯ãã¬ãŒã ãéžæããŠäŸå€ãåŠçã§ããå人çšé¢æ°ãäœæããŸããããæ£ããcatchãã©ã³ããèŠã€ããããšã¯äŸç¶ãšããŠå°é£ã§ãã äœæ¥çšå人æ©èœã®æçµããŒãžã§ã³ã§ã¯ãã¢ã¯ã·ã§ã³ããŒãã«.gcc_except_tableå šäœã§äŸå€ã®ã¿ã€ãã確èªããå¿ èŠããããŸãã
ã¢ã¯ã·ã§ã³ããŒãã«ãèŠããŠããŸããïŒ ããäžåºŠèŠãŠã¿ãŸãããããã ããããã€ãã®catchãããã¯ããããŸãã
# Call site table .LLSDACSB2: # Call site 1 .uleb128 ip_range_start .uleb128 ip_range_len .uleb128 landing_pad_ip .uleb128 (action_offset+1) => 0x3 # Rest of call site table # Action table start .LLSDACSE2: # Action 1 .byte 0x2 .byte 0 # Action 2 .byte 0x1 .byte 0x7d .align 4 .long _ZTI9Exception .long _ZTI14Fake_Exception .LLSDATT2: # Types table start
ãã®äŸã®ã©ã³ãã£ã³ã°ãããã§ãµããŒããããŠãããã¹ãŠã®äŸå€ïŒcatchité¢æ°ã®ãã®LSDAïŒãèªã¿åãå Žåã¯ã次ã®ããã«ããå¿ èŠããããŸãã
- åŒã³åºãããŒãã«ããã¢ã¯ã·ã§ã³ã®ãªãã»ãããååŸããŸãïŒå¿ããªãã§ãã ããããªãã»ãã+ 1ãèªã¿åãã0ã¯ã¢ã¯ã·ã§ã³ãªããæå³ããŸãïŒ
- ãªãã»ããã§ã¢ã¯ã·ã§ã³2ã«ç§»åããã¿ã€ã1ã®ã€ã³ããã¯ã¹ãååŸããŸããã¿ã€ãããŒãã«ã«ã¯éã®é åºã§ã€ã³ããã¯ã¹ãä»ããããŸãïŒã€ãŸããæ«å°Ÿãžã®ãã€ã³ã¿ãããã-1 *ã€ã³ããã¯ã¹ã䜿çšããŠã¢ã¯ã»ã¹ããå¿ èŠããããŸãïŒ
- types_table [-1]ã«ç§»åããŠãFake_Exceptionã®type_infoãååŸããŸã
- Fake_Exceptionã¯ã¹ããŒãããäŸå€ã§ã¯ãªãã次ã®ã¢ã¯ã·ã§ã³ïŒã¢ã¯ã·ã§ã³ïŒïŒ0x7dïŒãžã®ãªãã»ãããååŸããŸã
- uleb128ã§0x7dãèªã¿åããš-3ãè¿ãããŸããããã¯ããªãã»ãããèªã¿åã£ãŠããäœçœ®ãã3ã¹ãããæ»ããŸã
- ã€ã³ããã¯ã¹2ã®èªã¿åãã¿ã€ã
- type_infoãååŸããŠäŸå€ãã¹ããŒããŸãããä»åã¯äŸå€ãã¹ããŒããŸããããã«ãããã©ã³ãã£ã³ã°ããããèšå®ã§ããŸãã
åã³å€ãã®éæ¥çãªã¢ãã¬ã¹æå®ãããéããè€éã«èŠããŸããããªããžããªã§æçµçãªã³ãŒããèŠãããšãã§ããŸã ã åããŒãã«ãèªã¿åã£ãŠå¿ èŠãªcatchãããã¯ã決å®ã§ããå人é¢æ°ã®åœ¢ã§ããŒãã¹ããããŸãïŒåãnullã®å Žåããããã¯ã¯ãã¹ãŠã®äŸå€ãé£ç¶ããŠåŠçã§ããŸãïŒã é¢çœãå¯äœçšããããŸããC++ããã°ã©ã ããã¹ããŒããããšã©ãŒã®ã¿ãåŠçã§ããŸãã
æåŸã«ãäŸå€ãã¹ããŒãããæ¹æ³ãã¹ã¿ãã¯ã解ãããæ¹æ³ãå人æ©èœãæ£ããã¹ã¿ãã¯ãã¬ãŒã ãéžæããæ¹æ³ãããã³ã©ã³ãã£ã³ã°ãããå ã®ãããã¯ãéžæããæ¹æ³ã¯ããã£ãŠããŸããããã¹ãã©ã¯ã¿ãéå§ãããšããåé¡ããŸã ãããŸãã ããã§ã¯ãRAIIãµããŒããæäŸããããšã«ãããå人ã®æ©èœãå€æŽããŸãã
å éšã®C ++äŸå€ïŒããã¢ãŒã·ã§ã³ã§ã®ãã¹ãã©ã¯ã¿ãŒã®å®è¡
ããABIããŒãžã§ã³11㯠ãäŸå€åŠçã®åºæ¬æ©èœã®ã»ãšãã©ãã¹ãŠã«å¯Ÿå¿ããŠããŸããããã¹ãã©ã¯ã¿ãå®è¡ããããšã¯ã§ããŸããã å®å šãªã³ãŒããæžãããå Žåãããã¯éåžžã«éèŠãªéšåã§ãã å¿ èŠãªãã¹ãã©ã¯ã¿ã.gcc_except_tableã«æ ŒçŽãããŠããããšãããã£ãŠãããããã¢ã»ã³ãã©ã³ãŒããããå°ãèŠãå¿ èŠããããŸãã
# Call site table .LLSDACSB2: # Call site 1 .uleb128 ip_range_start .uleb128 ip_range_len .uleb128 landing_pad_ip .uleb128 (action_offset+1) => 0x3 # Rest of call site table # Action table start .LLSDACSE2: # Action 1 .byte 0 .byte 0 # Action 2 .byte 0x1 .byte 0x7d .align 4 .long _ZTI14Fake_Exception .LLSDATT2: # Types table start
éåžžã®ã©ã³ãã£ã³ã°ãããã§ã¯ãã¢ã¯ã·ã§ã³ã®ã€ã³ããã¯ã¹ã®ã¿ã€ãã0ãã倧ããå Žåãã¿ã€ãããŒãã«ã«ã€ã³ããã¯ã¹ãååŸããããã䜿çšããŠå¿ èŠãªcatchãããã¯ãèŠã€ããããšãã§ããŸãã ãã以å€ã®å Žåãã€ã³ããã¯ã¹ã0ã®ãšããã¯ãªãŒã³ã¢ããã³ãŒããå®è¡ããå¿ èŠããããŸãã ã©ã³ãã£ã³ã°ããããäŸå€ãåŠçã§ããªãå Žåã§ããããã¢ãŒã·ã§ã³äžã«ã¯ãªãŒã³ã¢ãããå®è¡ã§ããŸãã ãã¡ãããã¯ãªãŒã³ã¢ãããå®äºããåŸãã©ã³ãã£ã³ã°ãããã¯_Unwind_ResumeãåŒã³åºããŠããã¢ãŒã·ã§ã³ããã»ã¹ãç¶è¡ããå¿ èŠããããŸãã
æ°ããææ°ããŒãžã§ã³ã®ã³ãŒããgithubãªããžããªã«ã¢ããããŒãããŸããããæªããã¥ãŒã¹ããããŸãïŒuleb128 == charãšèšã£ããšãã®äžæ£è¡çºãèŠããŠããŸããïŒ ãã¹ãã©ã¯ã¿çšã®ã³ãŒãã®è¿œå ãéå§ãããšã.gcc_except_tableã®ãªãã»ããã倧ãããªãïŒã倧ããããšã¯127ãè¶ ããããšãæå³ããŸãïŒãããªãã¯ãæ©èœããªããªããŸããã
次ã®ããŒãžã§ã³ã§ã¯ãLSDAãªãŒããŒãæžãæããŠãuleb128ã³ãŒããæ£ããåŠçããå¿ èŠããããŸãã
ããã«ãããããããç§ãã¡ã¯ç®æšãéæããŸããïŒ åœŒãã¯ãlibcxxabiã©ã€ãã©ãªã®å©ããªãã«äŸå€ãæ£ããåŠçã§ããããABIãäœæããŸããïŒ
ãã¡ããããã®èšèªã®ãã€ãã£ãã§ã¯ãªãäŸå€ãåŠçããããã³ã³ãã€ã©ãšãªã³ã«ãŒéã®äºææ§ããµããŒãããããããªã©ããŸã ããããšããããŸãã ãã¶ãåŸã§...
å éšã®C ++äŸå€ïŒçµæ
äœã¬ãã«ã®äŸå€åŠçã«é¢ãã20ã®ç« ãèªãã åŸãåšåº«ã確èªããŸãããïŒ äŸå€ãã©ã®ããã«ã¹ããŒãããã©ã®ããã«ãã£ããããããã«ã€ããŠãç§ãã¡ã¯äœãåŠã³ãŸãããïŒ
ãããããã®èšäºã®æ倧ã®éšåã§ãã.gcc_except_tableã®èªã¿åãã«é¢ããæããã詳现ã¯å¥ãšããŠãçµè«ãåºãããšãã§ããŸãã
- C ++ã³ã³ãã€ã©ã¯ãå®éã«ã¯äŸå€åŠçã«é¢é£ããäœæ¥ãã»ãšãã©è¡ããŸãããã»ãšãã©ã®éæ³ã¯libstdc ++ã§çºçããŸã
- ã³ã³ãã€ã©ãè¡ãããã€ãã®ããšã次ã«ç€ºããŸãã
- CFIã¹ã¿ãã¯ããã¢ãŒã·ã§ã³æ å ±ãäœæããŸã
- ã©ã³ãã£ã³ã°ãããã«é¢ããæ å ±ãå«ã.gcc_except_tableãšåŒã°ãããã®ãäœæããŸãïŒtry / catchãããã¯ïŒã åå°ã®äžéšã
- throwãèšè¿°ãããšãã³ã³ãã€ã©ãŒã¯ãããlibstdc ++ã®2ã3ã®åŒã³åºãã«å€æããäŸå€ãå²ãåœãŠãŠããããã¢ãŒã·ã§ã³ãéå§ããŸã
- ã©ã³ã¿ã€ã ã§äŸå€ãã¹ããŒããããšã__ cxa_throwã¯ã¹ã¿ãã¯ããã¢ãŒã·ã§ã³ãlibstdcã©ã€ãã©ãªã«å§ä»»ããŸã
- ã¹ã¿ãã¯ããã¢ãŒã·ã§ã³ã®ããã»ã¹ã§ã¯ãlibstdc ++ãšããç¹å¥ãªé¢æ°ïŒããŒãœããªãã£é¢æ°ãããŒãœããªãã£ã«ãŒãã³ãšåŒã°ããïŒãåŒã³åºãããã¹ã¿ãã¯å ã®åé¢æ°ãäŸå€ãåŠçã§ãããã©ããã確èªããŸãã
- äžèŽããcatchãããã¯ãèŠã€ãããªãå Žåãstd :: terminateãåŒã³åºãããŸãã
- èŠã€ãã£ãå Žåãã¹ã¿ãã¯ã®ææ Œã¯ã¹ã¿ãã¯ã®å é ããåã³éå§ãããŸãã
- 2åç®ã®ãã¹ã§ã¯ãã¯ãªãŒãã³ã°ãå®è¡ãããŸã
- ããŒãœãã«é¢æ°ã¯ãçŸåšã®ã¡ãœããã®.gcc_except_tableããã§ãã¯ããŸãã ã¯ãªãŒãã³ã°ã¢ã¯ã·ã§ã³ïŒããŒãã«ïŒãããå ŽåãããŒãœãã«é¢æ°ã¯çŸåšã®ã¹ã¿ãã¯ãã¬ãŒã ã«ããžã£ã³ããããŠãã®ã¡ââãœããã®ã¯ãªãŒãã³ã°ãéå§ããŸã
- ã¢ã³ã¯ã€ã³ããŒã¯ããã®äŸå€ãåŠçã§ããã¹ã¿ãã¯ãã¬ãŒã ïŒé¢æ°ãèæ ®ïŒã«ééãããšããã«ãé©åãªcatchãããã¯ã«ãžã£ã³ãããŸã
- catchãããã¯ãå®è¡ããããšãäŸå€ã«ãã£ãŠå æãããŠããã¡ã¢ãªãã¯ãªã¢ãããŸãã
äŸå€ã®åŠçæ¹æ³ã詳现ã«æ€èšããçµæãäŸå€ã«å¯ŸããŠå®å šãªã³ãŒããèšè¿°ããããšãéåžžã«é£ããçç±ã説æã§ããããã«ãªããŸããã
äžèŠãããšãäŸå€ã¯çŽ æŽãããç°¡åã«èŠãããããããŸããããå°ãæ·±ãæãäžãããšãå€ãã®å°é£ã«ééãããšãããã°ã©ã ã¯æåéãããèªäœãæãäžãå§ããŸãïŒãªãã¬ã¯ã·ã§ã³ïŒãããã¯C ++ã¢ããªã±ãŒã·ã§ã³ã§ã¯äžè¬çã§ã¯ãããŸããã
äŸå€ãã¹ããŒããããšãã«é«ã¬ãã«èšèªã«ã€ããŠè©±ããŠããå Žåã§ããéåžžã®ã³ãŒãå®è¡ã®ç解ã«é Œãããšã¯ã§ããŸãããéåžžãifããã³switchã¹ããŒãã¡ã³ãã®åœ¢åŒã§å°ããªåå²ã䜿çšããŠçŽç·çã«å®è¡ãããŸããäŸå€ãé€ããŠããã¹ãŠãç°ãªããŸããã³ãŒãã¯ç解ã§ããªãé åºã§å®è¡ãéå§ããã¹ã¿ãã¯ãæ¡åŒµããé¢æ°ã®å®è¡ãäžæããéåžžã®èŠåã«åŸãããšãåæ¢ããŸããæ瀺ãã€ã³ã¿ãŒã¯åã©ã³ãã£ã³ã°ãããã§å€åããã¹ã¿ãã¯ã¯ç§ãã¡ã®å¶åŸ¡ãªãã§ã¹ãã³ããŸããäžè¬ã«ãå€ãã®éæ³ããã³ãããã®äžã§çºçããŸãã
çµå±ãäŸå€ã¯ããã°ã©ã ã®èªç¶ãªå®è¡ã«å¯Ÿããç解ãæãªãããè€éã§ããããã¯ããããã䜿çšããããšãå³å¯ã«çŠæ¢ãããŠããããšãæå³ããã®ã§ã¯ãªãããããã䜿çšãããšãã¯åžžã«æ³šæããå¿ èŠããããšã ãèšã£ãŠããŸãïŒ