
翻蚳è
ãã
é«ã¬ãã«ã®èšèªã¯äžçã§åã¡åã£ãŠãããruby-python-jséçºè
ã®äžçã§ã¯ãããããããããã§äœ¿çšãã䟡å€ããªãããšããã ãã§ãã ããšãã°ãäŸå€ã¯äœéã§ãããå€ãã®åé·ã³ãŒããçæããããã§ãã ããã«å¿ããŠã€ã¶ãããšäœé³ãåãåã£ããšããããããŠãããã©ã®ã³ãŒããçæãããããå°ãã䟡å€ããããŸããã ãããŠçå®ã¯-圌ãã¯ã©ã®ããã«æ©èœããã®ã§ããïŒ ããŠã-Sãã©ã°ãä»ããŠg ++ã§ã³ã³ãã€ã«ããäœãèµ·ãã£ãã®ãèŠãŠã¿ãŸãããã 衚é¢çã«çè§£ããããšã¯é£ãããããŸãããã誀解ããããšããäºå®ã¯ç§ãç ãããŸããã§ããã 幞ããªããšã«ã宿ããèšäºãèŠã€ãããŸããã
Habréã«ã¯ãC ++ã§äŸå€ãã©ã®ããã«æ©èœãããã説æãã
詳现ã§
éåžžã« ïŒåæã«è¯ãïŒã®èšäºãããã€ããããŸãã ããããæ¬åœã«æ·±ããã®ã¯ãªãã®ã§ãé©åãªææãããããããã®ã®ã£ãããåããããšã«ããŸããã gccã®äŸã§C ++ã®äŸå€ãã©ã®ããã«æ©èœããããèª°ãæ°ã«ããŸããïŒ
2éš3éšPS翻蚳ã«é¢ããããã€ãã®èšèïŒ
- 翻蚳ã¯ããã¹ãã«éåžžã«è¿ãã§ãããæã
段èœå
šäœã倿Žããããšãèš±å¯ããŸãã
- ã©ã³ãã£ã³ã°ããããé»è©±ãµã€ããªã©ãããã€ãã®çšèªã®ç¿»è𳿹æ³ãèããŠããŸããã§ãã
- ä»äºã¯æã£ããããã¯ããã«å€ããæçµçã«ã¯ç¿»èš³ãã©ãã«ããã®ããå
ã®å Žæã¯ã©ããã§æ··ä¹±ããããã«ãªããŸããããã¹ãŠãä¿®æ£ããŸãã
- ãã®å Žåãã³ãŒãã¯èšäºã®äžå¯æ¬ ãªéšåã§ãããããã¹ãã€ã©ãŒã®äžã«ã¯äœãé ããŸããã
- ãã€ãã®ããã«ãã¹ãã«ãå¥èªç¹ã軜埮ãªééã-PMã å®éã®ãšã©ãŒãäžæ£ç¢ºãããã³çç¥ã¯ã³ã¡ã³ãã«èšèŒãããŠããŸãã
å
éšã®C ++äŸå€
äŸå€ã®åŠçãé£ããããšã¯èª°ããç¥ã£ãŠããŸãã äŸå€ã®ãã©ã€ããµã€ã¯ã«ãã®åã¬ã€ã€ãŒã«ã¯ãããã«ã¯å€ãã®çç±ããããŸãã匷åãªäŸå€ã»ãŒãã³ãŒãã䜿çšããŠã³ãŒããèšè¿°ããããšã¯é£ãããäºæããªãå ŽæããäŸå€ãã¹ããŒãããå¯èœæ§ããããŸããããŒãã®äžã«å€§éã®ããŒãã¥ãŒæã®éæ³ããããããããã¯å±éºã§ãããšã©ãŒã誀ã£ãŠã¹ããŒãããšã
std::terminate
ãžã®åŒã³åºãã
std::terminate
ããªãããã§ãã ãããŠãããããã¹ãŠã«ãããããããããã°ã©ã ã§äŸå€ã䜿çšãããã©ããã«ã€ããŠã®æŠãã¯ãŸã é²è¡äžã§ãã ããã¯ãããããããããã©ã®ããã«æ©èœãããã«ã€ããŠã®æµ
ãçè§£ã«ãããã®ã§ãã
ãŸããèªåèªèº«ã«åããããå¿
èŠããããŸããããã¯ã©ã®ããã«æ©èœããŸããïŒ ããã¯ã
C ++ã®å
éšã§äŸå€ãã©ã®ããã«å®è£
ããããã«ã€ããŠæžããé·ãã·ãªãŒãºã®æåã®èšäº
ã§ãïŒx86ã®äžã®gccãã©ãããã©ãŒã ã§ãä»ã®ãã©ãããã©ãŒã ã«ãé©çšã§ããã¯ãã§ãïŒã ãããã®èšäºã§ã¯ããšã©ãŒãã¹ããŒããã³ãã£ããããããã»ã¹ã«ã€ããŠè©³ãã説æããŸããããã£ãã¡ãªäººã®ããã«ã gcc / x86ã§ã®äŸå€ã®ã¹ããŒ
ã«é¢ãããã¹ãŠã®èšäºã®ç°¡åãªèª¬æã以äžã«ç€ºããŸã ã
- throwã¹ããŒãã¡ã³ããäœæãããšãã³ã³ãã€ã©ãŒã¯ããã
libstdc++
颿°ã®2ã3ã®åŒã³åºãã«å€æããŸããããã«ãããäŸå€ãã¹ããŒããã libstdc
ã©ã€ãã©ãªãŒåŒã³åºãã§ã¹ã¿ãã¯ãå·»ãæ»ãé«éããã»ã¹ãéå§ãããŸãã
- åcatchãããã¯ã«ã€ããŠãã³ã³ãã€ã©ã¯ã¡ãœããæ¬äœã®åŸã«ç¹å¥ãªæ
å ±ã远å ããã¡ãœããããã£ããã§ããäŸå€ã®ããŒãã«ãããã³ã¯ãªãŒã³ã¢ããããŒãã«ã远å ããŸãïŒä»¥äžã®ã¯ãªãŒã³ã¢ããããŒãã«ãåç
§ïŒã
- ã¹ã¿ãã¯ãã¢ã³ã¯ã€ã³ãããããã»ã¹ã§ã¯ã
libstdc++
ãšåŒã°ããç¹å¥ãªé¢æ°ïŒãããŒãœããªãã£ã«ãŒãã³ããšåŒã°ããïŒãåŒã³åºãããã¹ã¿ãã¯äžã®å颿°ããã£ããã§ãããšã©ãŒããã§ãã¯ããŸãã
- ãã®ãšã©ãŒããã£ãããã人ãããªãå Žåã
std::terminate
åŒã³åºãããŸãã
- ããã§ã誰ããèŠã€ãã£ãå Žåãããã¢ãŒã·ã§ã³ã¯ã¹ã¿ãã¯ã®äžçªäžããåéãããŸãã
- ã¹ã¿ãã¯ãç¹°ãè¿ãééãããšããããŒãœãã«æ©èœããéå§ãããåã¡ãœããã®ãªãœãŒã¹ãã¯ãªã¢ãããŸãã
- ã«ãŒãã³ã¯ãçŸåšã®ã¡ãœããã®ã¯ãªãŒã³ã¢ããããŒãã«ããã§ãã¯ããŸãã ã¯ãªã¢ãããã®ãããå Žåãã«ãŒãã³ã¯ã¹ã¿ãã¯ã®çŸåšã®ãã¬ãŒã ã«ããžã£ã³ããããçŸåšã®ã¹ã³ãŒãã«ããåãªããžã§ã¯ãã®ãã¹ãã©ã¯ã¿ãåŒã³åºãã¯ãªã¢ã³ãŒããèµ·åããŸãã
- ããã¢ãŒã·ã§ã³ãäŸå€ãåŠçã§ããã¹ã¿ãã¯ã®ãã©ã°ã¡ã³ãã«ééãããšãäŸå€åŠçãããã¯ã«ãžã£ã³ãããŸãã
- äŸå€ã®åŠçãçµäºãããšãã¯ãªãŒã³ã¢ãã颿°ãåŒã³åºãããäŸå€ãå æããŠããã¡ã¢ãªãè§£æŸãããŸãã
*ããã¯ç§ãã¡ã«ãšã£ãŠ1ã€ã®å€§ããªèšäºã§ãããæçã«åå²ãããŸãããã®ããããäžé£ã®èšäºãã®ä»¥éã¯ãæ··ä¹±ãé¿ããããã«åã«ãèšäºãã«çœ®ãæããããŸãã
ä»ã§ãè€éã«èŠããŸãããéå§ããããŠããŸãããäŸå€ãåŠçããã®ã«å¿
èŠãªé£ãããçãäžæ£ç¢ºã«èšè¿°ããã ãã§ãã
libstdlibc++
ã§çºçãããã¹ãŠã®è©³çްã調ã¹ãããã«ã次ã®ããŒãã§ã¯
libstdlibc++
ç¬èªã®ããããŒãžã§ã³ãå®è£
ããããšããå§ã
libstdlibc++
ã ãã¹ãŠã§ã¯ãªãããšã©ãŒåŠçãåããéšåã®ã¿ã å®éã«ã¯ããã®éšåã®ãã¹ãŠã§ãããã¹ããŒ/ãã£ãããããã¯ãå®è£
ããããã«å¿
èŠãªæå°å€ã§ã¯ãããŸããã ãŸããå°ããªã¢ã»ã³ãã©ãå¿
èŠã«ãªããŸãããã»ãã®å°ãã ãã§ãã ããããæ®å¿µãªããå€ãã®å¿èãå¿
èŠã§ãã
奜å¥å¿ã匷ãå Žåã¯ã
ããããéå§ã§ã
ãŸã ã ããã¯ã次ã®ããŒãã§å®è£
ãããã®ã®å®å
šãªä»æ§ã§ãã æ¬¡åã¯ãç¬èªã®ABIïŒã¢ããªã±ãŒã·ã§ã³ãã€ããªã€ã³ã¿ãŒãã§ãŒã¹ïŒã䜿çšããŠç°¡åã«éå§ã§ããããã«ããã®èšäºãããããããã·ã³ãã«ã«ããããšæããŸãã
泚ïŒå
責äºé
ïŒïŒäŸå€ãã¹ããŒããããšãã«ã©ã®ãããªããŒãã¥ãŒæã®éæ³ãèµ·ãããã¯æ±ºããŠããããŸããã ãã®èšäºã§ã¯ãç§å¯ãå
¬éãããã®ä»çµã¿ã調ã¹ãŠã¿ãŸãã ããã€ãã®ããããªããšã埮åŠãªç¹ã¯çŸå®ãšã¯äžèŽããŸããã ã©ããã«åé¡ãããå Žåã¯ãç¥ãããã ããã
ãæ³šæ 翻蚳è
ïŒããã¯ç¿»èš³ã«ãåœãŠã¯ãŸããŸãã
å
éšã®C ++äŸå€ïŒå°ããªABI
äŸå€ããªãéåžžã«è€éã§ãã©ã®ããã«æ©èœããã®ããçè§£ããããšãããšã倧éã®ããã¥ã¢ã«ãããã¥ã¡ã³ãã«drããããèªåã§äŸå€ããã£ããããããšããããšãã§ããŸãã å®éããã®ãããã¯ã«é¢ãã質ã®é«ãæ
å ±ã®äžè¶³ã«é©ããïŒç¿»èš³è
ã®ã¡ã¢-ãšããã§ãç§ãïŒïŒèŠã€ããããšãã§ãããã®ã¯ãã¹ãŠã詳现ãããããåçŽããããã®ããããã§ãã ãã¡ããã仿§ïŒæãææžåããããã®ïŒ
C ++ã®ABIã ãã§ãªãã
CFI ã
DWARFããã³libstdcããããŸãïŒããããŸãããå
éšã§äœãèµ·ãã£ãŠããã®ããæ¬åœã«çè§£ãããå Žåãææžãåå¥ã«èªãã ãã§ã¯ååã§ã¯ãããŸããã
æãããªããšããå§ããŸãããïŒè»èŒªã®åçºæïŒ çŽç²ãªCã«ã¯äŸå€ããªãããšãç¥ã£ãŠããã®ã§ãC ++ããã°ã©ã ãçŽç²ãªCãªã³ã«ãŒãšãªã³ã¯ããŠãäœãèµ·ãããèŠãŠã¿ãŸãããïŒ ç§ã¯ãã®ãããªåçŽãªãã®ããå§ããŸããïŒ
#include "throw.h" extern "C" { void seppuku() { throw Exception(); } }
extern
å¿ããªãã§ãã ããããããªããšãG ++ãå°ããªé¢æ°ãåãåã£ãŠãçŽç²ãªCã§ããã°ã©ã ã«ãªã³ã¯ã§ããªããªããŸãããã¡ãããC ++ãšCã®äžçãæ¥ç¶ã§ããããã«ããªã³ã¯çšã®ããããŒãã¡ã€ã«ãå¿
èŠã§ãã
struct Exception {}; #ifdef __cplusplus extern "C" { #endif void seppuku(); #ifdef __cplusplus } #endif
ãããŠéåžžã«ã·ã³ãã«ãªã¡ã€ã³ïŒ
#include "throw.h" int main() { seppuku(); return 0; }
ãã®ãã©ã³ã¯ã³ãŒããã³ã³ãã€ã«ããŠãªã³ã¯ããããšãããšã©ããªããŸããïŒ
> g++ -c -o throw.o -O0 -ggdb throw.cpp > gcc -c -o main.o -O0 -ggdb main.c
泚ïŒãã®ãããžã§ã¯ãã®ãã¹ãŠã®ãœãŒã¹ã³ãŒãã¯
ãgitãªããžããªããããŠã³ããŒãã§ã
ãŸã ã
ãããŸã§ã®ãšããããšãŠãè¯ãã g ++ãšgccã¯ã©ã¡ãããå°ããªäžçã§æºè¶³ããŠããŸãã ããããäžç·ã«ãªã³ã¯ããããšãããšããã«ã«ãªã¹ãå§ãŸããŸãïŒ
> gcc main.o throw.o -o app throw.o: In function `foo()': throw.cpp:4: undefined reference to `__cxa_allocate_exception' throw.cpp:4: undefined reference to `__cxa_throw' throw.o:(.rodata._ZTI9Exception[typeinfo for Exception]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info' collect2: ld returned 1 exit status
ãããŠãã¡ãããgccã¯C ++宣èšã®æ¬ èœã«ã€ããŠäžæºãèšã£ãŠããŸãã ãããã¯éåžžã«å
·äœçãªC ++宣èšã§ãã ãšã©ãŒã®æåŸã®è¡ãèŠãŠãã ããïŒ
cxxabiv1
vtable
cxxabiv1
ãŸãã
libstdc++
ã§å®£èšããã
cxxabi
ãC ++ã®ABIãåç
§ããŸãã ããã§ã宣èšãããC ++ ABIã€ã³ã¿ãŒãã§ã€ã¹ãæã€æšæºC ++ã©ã€ãã©ãªã䜿çšããŠãšã©ãŒåŠçãå®è¡ãããããšãããããŸããã
C ++ ABIã¯ã1ã€ã®ããã°ã©ã ã§ãªããžã§ã¯ãããªã³ã¯ã§ããæšæºã®ãã€ããªåœ¢åŒãçºè¡šããŸãã ç°ãªãABIã䜿çšãã2ã€ã®ç°ãªãã³ã³ãã€ã©ã§.oãã¡ã€ã«ãã³ã³ãã€ã«ããå Žåããããã1ã€ã®ã¢ããªã±ãŒã·ã§ã³ã«çµåããããšã¯ã§ããŸããã ABIã¯ãä»ã®ããŸããŸãªæšæºãããšãã°ãã¹ã¿ãã¯ãã¢ã³ã¯ã€ã³ãããããäŸå€ãã¹ããŒãããããããã®ã€ã³ã¿ãŒãã§ã€ã¹ã宣èšã§ããŸãã ãã®å ŽåãABIã¯ãC ++ãšã¹ã¿ãã¯ããã¢ãŒã·ã§ã³ãæäŸããã¢ããªã±ãŒã·ã§ã³å
ã®ä»ã®ã©ã€ãã©ãªãšã®éã®ã€ã³ã¿ãŒãã§ã€ã¹ïŒå¿
ããããã€ããªåœ¢åŒã§ã¯ãªããåãªãã€ã³ã¿ãŒãã§ã€ã¹ïŒãå®çŸ©ããŸãã èšãæãããšãABIã¯ãã¢ããªã±ãŒã·ã§ã³ãC ++以å€ã®ã©ã€ãã©ãªãšéä¿¡ã§ããããšã«ãããC ++åºæã®ããšãå®çŸ©ããŸããããã«ãããC ++ã§ãã£ãããããä»ã®èšèªããäŸå€ãã¹ããŒã§ããããã«ãªããŸãã
ãããã®å Žåã§ãããªã³ã«ãšã©ãŒã¯éå§ç¹ã§ããã
cxxabi
ã®äŸå€ã®åäœã®åæã«ãããæåã®å±€
cxxabi
ãå®è£
ããå¿
èŠãããã€ã³ã¿ãŒãã§ã€ã¹ã¯
cxxabi
ã§ãã æ¬¡ã®ç« ã§ã¯ã
C ++ ABIãšããŠæ£ç¢ºã«å®çŸ©ãããç¬èªã®ããABIããå§ããŸãã
ãã³ãããã®äžã®C ++äŸå€ïŒABIãããã·ã¥ããŠãªã³ã«ãŒãåã°ããŸã
äŸå€ãçè§£ããéçšã§ããã¹ãŠã®ééæãã
libstdc++
ã§å®è£
ãããŠããããã®å®çŸ©ã¯C ++ ABIã§æäŸãããŠããããšãçºèŠããŸããã ãªã³ã«ã®ãšã©ãŒã調ã¹ãŠããšã©ãŒåŠçã®ããã«ãC ++ ABIã«å©ããæ±ããã¹ãã ãšæšæž¬ããŸããã çŽç²ãªCããã°ã©ã ã«ãªã³ã¯ãããC ++ã¹ãããã£ã³ã°ãšã©ãŒããã°ã©ã ãäœæããã³ã³ãã€ã©ãŒãäŸå€ãçŽæ¥ã¹ããŒããããã€ãã®libstd ++颿°ãåŒã³åºããã®ã«ã¹ããŒåœä»€ãäœããã®åœ¢ã§å€æããããšãããããŸããã
ããã§ããäŸå€ãã©ã®ããã«æ©èœããããæ£ç¢ºã«çè§£ãããã®ã§ããšã©ãŒãæããã¡ã«ããºã ãæäŸããç¬èªã®ããABIãå®è£
ããŠã¿ãŸãããã ãããè¡ãã«ã¯ã
RTFMã®ã¿ãå¿
èŠã§ããã
LLVMã®å®å
šãªã€ã³ã¿ãŒãã§ã€ã¹ã¯
ãã¡ãã«ãããŸãã æ¬ èœããŠããæ©èœãæ£ç¢ºã«æãåºããŠãã ããã
> gcc main.o throw.o -o app throw.o: In function `foo()': throw.cpp:4: undefined reference to `__cxa_allocate_exception' throw.cpp:4: undefined reference to `__cxa_throw' throw.o:(.rodata._ZTI9Exception[typeinfo for Exception]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info' collect2: ld returned 1 exit status
__cxa_allocate_exception
ååã¯èªçµŠèªè¶³ã ãšæããŸãã
__cxa_allocate_exceptionã¯ã
size_t
ãåããäŸå€ãã¹ããŒããéãäŸå€ãä¿æããã®ã«ååãªã¡ã¢ãªãå²ãåœãŠãŸãã ããã¯èŠãç®ãããè€éã§ãïŒãšã©ãŒãåŠçããããšãã¹ã¿ãã¯ã«éæ³ããããŸããã¹ã¿ãã¯äžã®å²ãåœãŠïŒç¿»èš³è
ã®ã³ã¡ã³ã-ãã®èšèã¯èš±ããŠãã ãããã§ãæã
䜿çšããŸãïŒã¯æªãèãã§ãã ããŒãïŒããŒãïŒã«ã¡ã¢ãªãå²ãåœãŠãããšããäžè¬ã«æªãèãã§ããäŸå€ãçºçããã¡ã¢ãªãã©ãã«å²ãåœãŠãŠãã¡ã¢ãªãäžè¶³ããããšãç¥ãããã®ã§ããããã ã¡ã¢ãªå
ã®éçã¹ãã¬ãŒãžããã¹ã¬ããã»ãŒãã«ããå¿
èŠãããéããæªãèãã§ãïŒããããªããšãäŸå€ãã¹ããŒãã2ã€ã®ç«¶åããã¹ã¬ãããçœå®³ã«ã€ãªãããŸãïŒã ãããã®åé¡ãèãããšãã¹ããªãŒã ã®ããŒã«ã«ã¹ãã¬ãŒãžïŒããŒãïŒã®ã¡ã¢ãªå²ãåœãŠãæãæå©ã«èŠããŸãããå¿
èŠã«å¿ããŠãã¡ã¢ãªãäžè¶³ããŠããå Žåã¯ç·æ¥ã¹ãã¬ãŒãžïŒããããéçïŒã«ã¢ã¯ã»ã¹ããŸãã ãã¡ãããæããã詳现ã«ã€ããŠã¯å¿é
ããªãã®ã§ãå¿
èŠã«å¿ããŠéçãããã¡ã䜿çšããã ãã§ãã
__cxa_throw
ãã®æ©èœã¯ã転éã®ãã¹ãŠã®éæ³ãå®è¡ããŸãïŒ ABIã«ãããšãäŸå€ã
çºçããã
ã__ cxa_throwãåŒã³åºãå¿
èŠããããŸãã ãã®é¢æ°ã¯ãã¹ã¿ãã¯ããã¢ãŒã·ã§ã³ãåŒã³åºããŸãã éèŠãªå¹æïŒ
__cxa_throwã¯æ»ããæå³ããããšã¯ãããŸããã ãŸããé©åãªcatchãããã¯ã«å¶åŸ¡ãæž¡ããŠãäŸå€ãåŠçããããããã©ã«ãã§
std::terminate
åŒã³åºããŸãããäœãè¿ããŸããã
__cxxabiv1::__class_type_info
vtable
__cxxabiv1::__class_type_info
å¥åŠãª...
__class_type_infoã¯æããã«ããã€ãã®RTTIïŒã©ã³ã¿ã€ã åæ
å ±ãã©ã³ã¿ã€ã åèå¥ãåçããŒã¿åèå¥ïŒã§ãããã©ãã§ããïŒ ãããŸã§ã®ãšãããããã«çããããšã¯ç°¡åã§ã¯ãããŸããããŸããããABIã«ãšã£ãŠã¯ããã»ã©éèŠã§ã¯ãããŸããã äŸå€ãã¹ããŒããããã»ã¹ã®åæã®åŸã«æç€ºãããã¢ããªã±ãŒã·ã§ã³ãã®ãã®éšåãæ®ããŸããããããã§ããããå®è¡æã®ABIå®çŸ©ã®ãšã³ããªãã€ã³ãã§ããããããã2ã€ã®ã¿ã€ãã¯åããã©ããããšãã質åã«çããŸãã ããã¯ãç¹å®ã®catchãããã¯ããã®ãšã©ãŒãåŠçã§ãããã©ããã倿ããããã«åŒã³åºããã颿°ã§ãã ããã§äž»ãªããšã«çŠç¹ãåœãŠãŸãïŒãªã³ã«ãŒã®ã¢ãã¬ã¹ãšããŠæå®ããå¿
èŠããããŸãïŒã€ãŸãããããå®çŸ©ããã ãã§ã¯ååã§ã¯ãªããéå§ããå¿
èŠããããŸãïŒãvtableãå¿
èŠã§ãïŒã¯ããã¯ããä»®æ³ã¡ãœãããå¿
èŠã§ãïŒã
ãããã®é¢æ°ã§ã¯å€ãã®äœæ¥ãçºçããŸãããåçŽãªäŸå€ã¹ããŒã©ãŒãå®è£
ããŠã¿ãŸããããäŸå€ãã¹ããŒããããšãã«ããã°ã©ã ãçµäºããïŒexitãåŒã³åºãïŒãã®ã§ãã ã¢ããªã±ãŒã·ã§ã³ã¯ã»ãŒå®æããŠããŸãããäžéšã®ABI颿°ãæ¬ èœããŠãããããmycppabi.cppãäœæããŸãããã
ABI仿§ã
èªãã§ ã
__ cxa_allocate_exceptionããã³
__cxa_throwã®çœ²åã説æã§ããŸãã
#include <unistd.h> #include <stdio.h> #include <stdlib.h> namespace __cxxabiv1 { struct __class_type_info { virtual void foo() {} } ti; } #define EXCEPTION_BUFF_SIZE 255 char exception_buff[EXCEPTION_BUFF_SIZE]; extern "C" { void* __cxa_allocate_exception(size_t thrown_size) { printf("alloc ex %i\n", thrown_size); if (thrown_size > EXCEPTION_BUFF_SIZE) printf("Exception too big"); return &exception_buff; } void __cxa_free_exception(void *thrown_exception); #include <unwind.h> void __cxa_throw( void* thrown_exception, struct type_info *tinfo, void (*dest)(void*)) { printf("throw\n");
æãåºãããŠãã ããïŒ
githubãªããžããªã§ãœãŒã¹ãèŠã€ããããšãã§ã
ãŸã ã
ããã§mycppabi.cppãã³ã³ãã€ã«ããä»ã®2ã€ã®.oãã¡ã€ã«ã«ãªã³ã¯ãããšããalloc ex 1 \ n throwããåºåããŠçµäºããäœæ¥ãã€ããªãåŸãããŸãã éåžžã«ç°¡åã§ãããåæã«é©ãã¹ãããšã§ããlibc++ãåŒã³åºããã«äŸå€ã管çããŸããC++ ABIã®ïŒéåžžã«å°ããªïŒéšåãèšè¿°ããŸããã
ç¬èªã®ããABIãäœæãããšãã«åŸãç¥æµã®ãã1ã€ã®éèŠãªéšåïŒ
throw
ããŒã¯ãŒãã¯ãlibstdc ++ããã®2ã€ã®é¢æ°åŒã³åºãã«ã³ã³ãã€ã«ãããŸãã ããŒãã¥ãŒæã®éæ³ã¯ãããŸãããããã¯åçŽãªå€æã§ãã ããããã¹ãããããã«é¢æ°ãéã¢ã»ã³ãã«ããããšãã§ããŸãã
g++ -S throw.cpp
å®è¡ããŸã
seppuku: .LFB3: [...] call __cxa_allocate_exception movl $0, 8(%esp) movl $_ZTI9Exception, 4(%esp) movl %eax, (%esp) call __cxa_throw [...]
ããã«éæ³ïŒ
throw
ãããã2ã€ã®åŒã³åºãã«å€æããããšãã³ã³ãã€ã©ãŒã¯äŸå€ãã©ã®ããã«åŠçããããããç¥ããŸããã
libstdc++
__cxa_throw
ãšãã®ãã¬ã³ããå®çŸ©
__cxa_throw
ãšã
libstdc++
å®è¡æã«åçã«ãªã³ã¯ãããã¢ããªã±ãŒã·ã§ã³ãæåã«èµ·åãããšãã«äŸå€åŠçã¡ãœãããéžæã§ããŸãã
ç§ãã¡ã¯ãã§ã«é²æ©ãèŠãŠããŸãããããã§ãç§ãã¡ã¯é·ãåŠã³ã®éãæ©ãŸãªããã°ãªããŸããã çŸåšãABIã¯äŸå€ã®ã¿ãã¹ããŒã§ããŸãã ãšã©ãŒããã£ããããããã«æ¡åŒµã§ããŸããïŒ ããŠã次ã®ç« ã§ãããè¡ãæ¹æ³ãèŠãŠã¿ãŸãããïŒ
å
éšã®C ++äŸå€ïŒã¹ããŒãããã®ããã£ãããã
ãã®èšäºã§ã¯ãã³ã³ãã€ã©ãŒãšãªã³ã«ãŒã®ãšã©ãŒã芳å¯ããããšã«ãããäŸå€ã®ã¹ããŒã«é¢ããç§å¯ã®ããŒã«ããããã«éããŸãããããšã©ãŒã®ãã£ããã«ã€ããŠã¯äœãçè§£ããŠããŸããã ãã§ã«ããã£ãããšãèŠçŽããŸãã
- throw-announcementã¯ãã³ã³ãã€ã©ã«ãã£ãŠ__cxa_allocate_exceptionãš__cxa_throwã® 2ã€ã®åŒã³åºãã§ãããŒããã£ã¹ããããŸãã
- __cxa_allocate_exceptionããã³__cxa_throwã¯
libstdc++
ã§ãã©ã€ãã libstdc++
ã - __cxa_allocate_exceptionã¯ãæ°ããäŸå€ã«ã¡ã¢ãªãå²ãåœãŠãŸãã
- __cxa_throwã¯ã _Unwindã§
libstdc
ååšããäžé£ã®é¢æ°ã«å¯ŸããŠäŸå€ãæºåããã³ã¹ããŒã ãã¹ã¿ãã¯ã®å®éã®æ¡åŒµãå®è¡ããŸãïŒ ABIã¯ãããã®é¢æ°ã®ã€ã³ã¿ãŒãã§ãŒã¹ãå®çŸ©ããŸãïŒã
ãããŸã§ã¯éåžžã«åçŽã§ããããäŸå€ããã£ããããã®ã¯å°ãè€éã§ããç¹ã«ãå°ãã®ãªãã¬ã¯ã·ã§ã³ãå¿
èŠãªããã§ãïŒããã°ã©ã ãç¬èªã®ã³ãŒããåæã§ããããã«ããããïŒã å€ãã¡ãœããã䜿çšããŠãã³ãŒãã«catchãããã¯ã远å ããã³ã³ãã€ã«ããŠäœãèµ·ãããèŠãŠã¿ãŸãããã
#include #include <stdio.h> // struct Fake_Exception {}; void raise() { throw Exception(); } // , , catch- void try_but_dont_catch() { try { raise(); } catch(Fake_Exception&) { printf(); } printf(); } // , void catchit() { try { try_but_dont_catch(); } catch(Exception&) { printf(); } catch(Fake_Exception&) { printf(); } printf(); } extern { void seppuku() { catchit(); } }
以åãšåæ§ã«ãCãšC ++ã®äžçãæ¥ç¶ããseppuku颿°ããããŸãããä»åã¯ã¹ã¿ãã¯ãããé¢çœãããããã«ããã€ãã®é¢æ°åŒã³åºãã远å ãããããã¯ã®try / catchãã©ã³ãã远å ãããããlibstdc ++ã®åŠçæ¹æ³ãåæã§ããŸããããã
ãŸããABI颿°ã®æ¬ èœã«é¢ãããªã³ã«ãŒãšã©ãŒãçºçããŸãã
> g++ -c -o throw.o -O0 -ggdb throw.cpp > gcc main.o throw.o mycppabi.o -O0 -ggdb -o app throw.o: In function `try_but_dont_catch()': throw.cpp:12: undefined reference to `__cxa_begin_catch' throw.cpp:12: undefined reference to `__cxa_end_catch' throw.o: In function `catchit()': throw.cpp:20: undefined reference to `__cxa_begin_catch' throw.cpp:20: undefined reference to `__cxa_end_catch' throw.o:(.eh_frame+0x47): undefined reference to `__gxx_personality_v0' collect2: ld returned 1 exit status
ç¹°ãè¿ããŸãããè峿·±ããã®ããããããããŸãã
__cxa_begin_catchããã³
__cxa_end_catchã®åŒã³åºããäºæããŠããŸããããããããäœã§ãããã¯ãŸã ããããŸãããã
throw / __ cxa_allocate / throwãšåçã§ãããšæ³å®ã§ããŸãã
__gxx_personality_v0ã¯æ°ãããã®ã§ãããæ¬¡ã®ããŒãã®ã¡ã€ã³ããŒãã«ãªããŸãã
å人çãªæ©èœã¯äœãããŸããïŒ ïŒç¿»èš³è
ãšäžç·ã«-ããè¯ãååãæãã€ããŸããã§ãããã¢ã€ãã¢ãããã°ã³ã¡ã³ãæ¬ã§æããŠãã ããïŒã å°å
¥éšã§åœŒå¥³ã«ã€ããŠã¯ãã§ã«è¿°ã¹ãŸããããæ¬¡åã¯åœŒå¥³ã«ã€ããŠããã«è©³ããèŠãŠ
ãããŸãããŸãã2äººã®æ°ããå人
__cxa_begin_catchãš
__cxa_end_catch ã«ã€ããŠã
èŠãŠãããŸãã
å
éšã® C ++äŸå€ïŒ __cxa_begin_catchããã³__cxa_end_catchã®éæ³
äŸå€ãã©ã®ããã«ã¹ããŒããããã調ã¹ãåŸãã©ã®ããã«ãã£ããããããã調ã¹ãããã®éãèŠã€ããŸãã åã®ç« ã§ã¯ããµã³ãã«ã¢ããªã±ãŒã·ã§ã³ã«try-catch-blockã远å ããŠã³ã³ãã€ã©ãŒã®åäœã確èªããŸããããŸããã¹ããŒãããã¯ã远å ãããšã©ããªãããååèŠããšããšåãããã«ãªã³ã«ãŒãšã©ãŒãçºçããŸããã ãªã³ã«ãèšè¿°ããå
å®¹ã¯æ¬¡ã®ãšããã§ãã
> g++ -c -o throw.o -O0 -ggdb throw.cpp > gcc main.o throw.o mycppabi.o -O0 -ggdb -o app throw.o: In function `try_but_dont_catch()': throw.cpp:12: undefined reference to `__cxa_begin_catch' throw.cpp:12: undefined reference to `__cxa_end_catch' throw.o: In function `catchit()': throw.cpp:20: undefined reference to `__cxa_begin_catch' throw.cpp:20: undefined reference to `__cxa_end_catch' throw.o:(.eh_frame+0x47): undefined reference to `__gxx_personality_v0' collect2: ld returned 1 exit status
ç§ã®gitãªããžããªã§ã³ãŒããååŸã§ããããšãæãåºãããŠãã ããã
çè«äžïŒãã¡ãããçè«äžïŒãcatchãããã¯ã¯libstdc ++ãã
__cxa_begin_catch / end_catchã®ãã¢ã«å€æãããŸããã
å人çšé¢æ°ãšåŒã°ããæ°ãããã®ã«ã倿ãã
ãŸãã ãããã«ã€ããŠã¯ãŸã äœãããããŸããã
__cxa_begin_catchãš
__cxa_end_catchã«ã€ããŠã®çè«ããã¹ãããŠã¿ãŸãããã -Sãã©ã°ãæå®ããŠthrow.cppãã³ã³ãã€ã«ããã¢ã»ã³ãã©ã³ãŒããåæããŸãã è峿·±ãããšããããããããŸããæãå¿
èŠãªãã®ã«ã«ããããŸãã
_Z5raisev: call __cxa_allocate_exception call __cxa_throw
ãã¹ãŠãé 調ã«é²ãã§ããŸãïŒraiseïŒïŒã«åãå®çŸ©ããããäŸå€ãã¹ããŒããã ãã§ãïŒ
_Z18try_but_dont_catchv: .cfi_startproc .cfi_personality 0,__gxx_personality_v0 .cfi_lsda 0,.LLSDA1
try_but_dont_catchïŒïŒã®å®çŸ©ã¯ãã³ã³ãã€ã©ãŒã«ãã£ãŠåãåãããŸãã ããã¯æ°ãããã®ã§ã
ã__gxx_personality_v0ãžã®ãªã³ã¯ãš
LSDAãšåŒã°ããä»ã®äœãã ããã¯å°ããªå®çŸ©ã®ããã«æããŸãããå®éã«ã¯éåžžã«éèŠã§ãã
- ãªã³ã«ã¯ãããCFIïŒåŒã³åºããã¬ãŒã æ
å ±ïŒä»æ§ã«äœ¿çšããŸãã CFIã¯åŒã³åºããã¬ãŒã æ
å ±ãä¿åããŸãã ããã«ãã®å®å
šãªä»æ§ããããŸãã äž»ã«ã¹ã¿ãã¯ã®ã¹ãã³ã«äœ¿çšãããŸãã
- LDSA ïŒèšèªåºæã®ããŒã¿é åïŒã¯ããã®é¢æ°ã§åŠçã§ããäŸå€ãç¥ãããã«åäººé¢æ°ã䜿çšããåèšèªã®ç¹å¥ãªé åã§ãã
次ã®ç« ã§CFIãšLSDAã«ã€ããŠèª¬æããŸããããããã«ã€ããŠã¯å¿ããªãã§ãã ãããæ¬¡ã«é²ã¿ãŸãããã
[...] call _Z5raisev jmp .L8
å¥ã®èŠçŽ äž»çŸ©ïŒ
raise
ãåŒã³åºããŠããL8ã«ãžã£ã³ãããã ãã§ãã L8ã¯é¢æ°ããæ£åžžã«æ»ããŸãã
raise
æ£ããå®è¡ãããªãå Žåãå®è¡ã¯ïŒã©ããããããããŸã ããããŸããïŒïŒæ¬¡ã®åœä»€ããç¶è¡ããã®ã§ã¯ãªããäŸå€ãã³ãã©ãŒïŒABIã®çšèªã§ã¯
landing pads
ãšåŒã°ããŸãïŒã«é²ãå¿
èŠããããŸãã
cmpl $1, %edx je .L5 .LEHB1: call _Unwind_Resume .LEHE1: .L5: call __cxa_begin_catch call __cxa_end_catch
äžèŠããã®äœåã¯å°ãè€éã§ãããå®éã«ã¯ãã¹ãŠãã·ã³ãã«ã§ãã
ããã§æå€§ã®éæ³ãçºçããŸãïŒæåã«ãã®äŸå€ãåŠçã§ãããã©ããã確èªããããã§ãªãå Žåã¯ãåŒã³åºã_Unwind_Resume
ãå¯èœã§ããã°åŒã³åºã__cxa_begin_catch
ãŠ__cxa_end_catch
ããã®åŸã颿°ãæ£åžžã«ç¶è¡ããå¿
èŠããããããL8ãå®è¡ãããŸãïŒãã£ãããããã¯ã®ããäžã«L8 ïŒïŒ .L8: leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc
ãã ã®éåžžã®é¢æ°ãæ»ããŸã... CFIã®ãŽããå
¥ã£ãŠããŸããããã¯ãã¹ãŠãšã©ãŒåŠçã®ããã§ããã__ cxa_begin / end_catchãã©ã®ããã«æ©èœãããã¯ãŸã ããããŸããããã®ãã¢ãã©ã³ãã£ã³ã°ããããåŒã³åºããã®ã圢æããæ¹æ³ã«ã€ããŠã®ã¢ã€ãã¢ãæã£ãŠããŸã-äŸå€ãã³ãã©ãŒãé
眮ãããŠãã颿°å
ã®å Žæã§ãããŸã äžæãªã®ã¯ãã©ã³ãã£ã³ã°ãããã®æ€çŽ¢æ¹æ³ã§ããUnwindã¯ãäœããã®æ¹æ³ã§ã¹ã¿ãã¯äžã®ãã¹ãŠã®åŒã³åºããééããå¿
èŠããããŸãããã§ãã¯ïŒåŒã³åºãïŒæ£ç¢ºãã®ããã«ã¹ã¿ãã¯ãã¬ãŒã ïŒã«ã¯ããã®äŸå€ãåŠçã§ããã©ã³ãã£ã³ã°ãããä»ãã®æå¹ãªãããã¯ããããå®è¡ãç¶è¡ããŸããããã¯éèŠãªææã§ããããã®ä»çµã¿ã«ã€ããŠã¯æ¬¡ã®ç« ã§èª¬æããŸããå
éšã®C ++äŸå€ïŒgcc_except_tableããã³å人çšé¢æ°
åã«ãthrowã¯__cxa_allocate_exception / throwã«å€æãããcatchãããã¯ã¯__cxa_begin / end_catchã«å€æãããããšãšãã©ã³ãã£ã³ã°ãããïŒãšã©ãŒãã³ãã©ãŒã®ãšã³ããªãã€ã³ãïŒãæ€çŽ¢ããããã®CFIïŒåŒã³åºããã¬ãŒã æ
å ±ïŒãšåŒã°ãããã®ãèŠã€ãããŸããããããŸã§ã®ãšããããããªãã®ã¯ã_Unwindããããã®ã©ã³ãã£ã³ã°ãããã®å Žæãã©ã®ããã«èŠã€ãããã§ããã¹ã¿ãã¯å
ã®äžé£ã®é¢æ°ãéããŠäŸå€ãã¹ããŒããããšããã¹ãŠã®CFIã«ãããã¹ã¿ãã¯æ¡åŒµããã°ã©ã ãçŸåšå®è¡äžã®é¢æ°ãèŠã€ããããšãã§ããŸãããŸãã颿°ã®ã©ã®ã©ã³ãã£ã³ã°ãããã§ãã®äŸå€ãåŠçã§ãããã調ã¹ãå¿
èŠããããŸãïŒãããŠãè€æ°ã®try / catchãããã¯ãæã€é¢æ°ïŒïŒããã®ã©ã³ãã£ã³ã°ãããã®å Žæã確èªããã«ã¯ãgcc_except_tableãšåŒã°ãããã®ã䜿çšããŸãããã®ããŒãã«ã¯ã颿°ã®çµäºåŸã«ïŒCFIã¬ããŒãžã§ïŒèŠã€ããããšãã§ããŸãã .LFE1: .globl __gxx_personality_v0 .section .gcc_except_table,"a",@progbits [...] .LLSDACSE1: .long _ZTI14Fake_Exception
ãã®ã»ã¯ã·ã§ã³.gcc_except_table-ã©ã³ãã£ã³ã°ããããæ€åºããããã®ãã¹ãŠã®æ
å ±ãæ ŒçŽãããŸããããã«ã€ããŠã¯ãåŸã§å人æ©èœãåæãããšãã«èª¬æããŸããä»ã®ãšãããLSDAã®æå³-å人æ©èœãæ©èœã®ã©ã³ãã£ã³ã°ãããããã§ãã¯ããèšèªåºæã®ããŒã¿ãæã€ãŸãŒã³ïŒã¹ã¿ãã¯æ¡åŒµã®éçšã§ãã¹ãã©ã¯ã¿ãèµ·åããããã«ã䜿çšãããŸãïŒã ããèšããŸããèŠçŽãããšãå°ãªããšã1ã€ã®catchãããã¯ãããå颿°ã«ã€ããŠãã³ã³ãã€ã©ãŒã¯ãããcxa_begin_catch / cxa_end_catchã®åŒã³åºãã«å€æãã__ cxa_throwã«ãã£ãŠåŒã³åºãããåäººé¢æ°ãgcc_except_tableãèªã¿åããŸãã¹ã¿ãã¯å
ã®åã¡ãœããã«å¯ŸããŠãLSDAãšåŒã°ãããã®ãæ€çŽ¢ããŸããæ¬¡ã«ãããŒãœãã«é¢æ°ã¯ãLSDAã«ãã®äŸå€ãåŠçãããããã¯ããããã©ãããããã³äœããã®çš®é¡ã®ã¯ãªã¢ã³ãŒãïŒå¿
èŠã«å¿ããŠãã¹ãã©ã¯ã¿ãŒãå®è¡ããïŒããããã©ããã確èªããŸãããŸããè峿·±ãçµè«ãåºãããšãã§ããŸãïŒnothrowïŒãŸãã¯ç©ºã®throwã¹ããŒãã¡ã³ãïŒã䜿çšããå Žåãã³ã³ãã€ã©ã¯gcc_except_tableãçç¥ã§ããŸãã¡ãœããã®ãããã©ãŒãã³ã¹ã«å€§ããªåœ±é¿ãäžããªãgccã§ã®ãã®äŸå€ã®å®è£
æ¹æ³ã¯ãå®éã«ã¯ã³ãŒãã®ãµã€ãºã«å€§ãã圱é¿ããŸãããã£ãããããã¯ã«ã€ã㊠nothrowæå®åã宣èšããããšãã«äŸå€ãã¹ããŒãããå ŽåãLSDAã¯çæããããããŒãœãã«é¢æ°ã¯äœããã¹ãããç¥ããŸãããããŒãœãã«é¢æ°ãäœããã¹ããåãããªãå Žåãããã©ã«ãã®ãšã©ãŒãã³ãã©ãåŒã³åºããŸããããã¯ãã»ãšãã©ã®å Žåãnothrowã¡ãœãããããšã©ãŒãã¹ããŒãããšãstd :: terminateã§çµäºããããšãæå³ããŸããå人çãªæ©èœãäœããããã«ã€ããŠã®ã¢ã€ãã¢ãã§ããã®ã§ããããå®è£
ã§ããŸããïŒããŠãèŠãŠã¿ãŸãããïŒç¶ç¶