ÖÁÓÚlinuxÏÂgccÊÇÔõÑù×öµÄ£¬ÍøÉϳä³âן÷ÖÖÎĵµ£¬ºÜ¶àµ«Ò²±È½ÏÔÓ£¬ÎÒÕâ¶ù¾Í¼òµ¥°ÑÎÒÕ⼸Ìì¿´µ½µÄ£¬Ïëµ½µÄ£¬Àí½âÁ˵쬲»Àí½âµÄ£¬×ö¸ö¼òµ¥µÄ×ܽᣬ»¶ÓÖ¸Õý¡£
Òì³£Å׳öºó£¬·¢ÉúÁËʲôÊÂÇ飿
¸ù¾Ýc++µÄ±ê×¼£¬Òì³£Å׳öºóÈç¹ûÔÚµ±Ç°º¯ÊýÄÚûÓб»²¶×½(catch), Ëü¾Í񻄯ן¯ÊýµÄµ÷ÓÃÁ´¼ÌÐøÍùÉÏÅ×£¬Ö±µ½×ßÍêÕû¸öµ÷ÓÃÁ´£¬»òÕßÖ±µ½ÔÚij¸öº¯ÊýÖÐÕÒµ½ÏàÓ¦µÄcatch¡£Èç¹û×ßÍêµ÷ÓÃÁ´¶¼Ã»ÓÐÕÒµ½ÏàÓ¦µÄcatch, ÄÇôstd::terminate()¾Í»á±»µ÷Óã¬Õâ¸öº¯ÊýĬÈÏÊǰѳÌÐòabort, ¶øÈç¹û×îºóÕÒµ½ÁËÏàÓ¦µÄcatch£¬¾Í»á½øÈë¸Ãcatch¿é£¬Ö´ÐÐÏàÓ¦µÄ²Ù×÷¡£
Õâ¸öcatch´úÂëÓÐÒ»¸öרÃŵÄÃû×Ö½Ð×÷£ºlanding pad¡£
³ÌÐòÔÚÖ´ÐÐlanding padÀïµÄ´úÂëǰ£¬Òª½øÐÐÒ»¸ö½Ð×÷stack unwindµÄ¹ý³Ì£¬¸Ã¹ý³ÌÒª×öµÄÊÂÇé¾ÍÊÇ´ÓÅ׳öÒì³£µÄº¯Êý¿ªÊ¼£¬ÇåÀíµ÷ÓÃÕ»ÉϵÄÒѾ´´½¨Á˵ľֲ¿±äÁ¿²¢Í˳ö¸Ãº¯Êý£¬Õâ¸öÇåÀí¹ý³ÌÒÔº¯Êýµ÷ÓÃèåΪµ¥Î»£¬Ö±µ½ÏàÓ¦µÄcatchËùÔڵĺ¯ÊýΪֹ¡£
¸´ÖÆ´úÂë
void func1()
{
cs a; // stack unwindʱ±»Îö¹¹¡£
throw 3;
}
void func2()
{
cs b;
func1();
}
void func3()
{
cs c;
try
{
func2();
}
catch (int)
{
//½øÈëÕâÀï֮ǰ£¬ func1, func2ÒѾ±»unwind.
}
}
¸´ÖÆ´úÂë
¿ÉÒÔ¿´³ö£¬unwindµÄ¹ý³Ì¿ÉÒÔ¼òµ¥¿´³ÉÊǺ¯Êýµ÷ÓõÄÄæ¹ý³Ì£¬Õâ¸ö¹ý³ÌÓÉÒ»¸öרÃŵÄstack unwind¿âÀ´½øÐУ¬ÔÚintelƽ̨ÉÏ£¬Õâ¸ö¿âÊôÓÚItanium ABI½Ó¿ÚÖеÄÒ»²¿·Ö£¬ËüÓë¾ßÌåµÄÓïÑÔÎ޹أ¬ÓÉϵͳÌṩʵÏÖ£¬ÈκÎÉϲãÓïÑÔ¶¼¿ÉÒÔÔÚÕâ¸ö½Ó¿ÚµÄ»ù´¡ÉÏʵÏÖ¸÷×ÔµÄÒì³£´¦Àí£¬GCC¾Í»ùÓÚÕâ¸ö½Ó¿ÚÀ´ÊµÏÖËüÀ´ÊµÏÖc++µÄÒì³£´¦Àí¡£
Itanium C++ ABI
Itanium ABI¶¨ÒåÁËһϵÁк¯Êý¼°ÏàÓ¦µÄ½á¹¹À´½¨Á¢Õû¸öÒì³£´¦ÀíµÄÁ÷³Ì¼°¿ò¼Ü£¬Ö÷ÒªµÄº¯Êý°üÀ¨ÒÔÏ£º
¸´ÖÆ´úÂë
_Unwind_RaiseException,
_Unwind_Resume,
_Unwind_DeleteException,
_Unwind_GetGR,
_Unwind_SetGR,
_Unwind_GetIP,
_Unwind_SetIP,
_Unwind_GetRegionStart,
_Unwind_GetLanguageSpecificData,
_Unwind_ForcedUnwind
¸´ÖÆ´úÂë
ÆäÖÐ_Unwind_RaiseExceptionº¯Êý¾ÍÊÇÓÃÓÚ½øÐÐstack unwindµÄ, ËüÔÚÓû§Ö´ÐÐthrowʱ±»µ÷Óã¬È»ºó´Óµ±Ç°º¯Êý¿ªÊ¼£¬¶Ôµ÷ÓÃÕ»ÉÏÿ¸öº¯Êýèå¶¼µ÷ÓÃÒ»¸ö½Ð×÷personality routineµÄº¯Êý£¨__gxx_personality_v0)£¬¸Ãº¯ÊýÓÉÉϲãµÄÓïÑÔ¶¨Ò弰ʵÏÖ£¬_Unwind_RaiseException»áÔÚÄÚ²¿°Ñµ±Ç°º¯ÊýÕ»µÄµ÷ÓÃÏÖ³¡Öؽ¨£¬È»ºó´«¸øpersonality routine, personality routineÔòÖ÷Òª¸ºÔð×öÁ½¼þÊÂÇ飺
1£©¼ì²éµ±Ç°º¯ÊýÊÇ·ñº¬ÓÐÏàÓ¦catch¿ÉÒÔ´¦ÀíÉÏÃæÅ׳öµÄÒì³£¡£
2£©Çåµôµ÷ÓÃÕ»Éϵľֲ¿±äÁ¿¡£
ÐèҪעÒâµÄÊÇ£¬ÕâÁ½¼þÊÂÇéÊÇ·Ö¿ªÀ´×öµÄ£¬Ê×ÏÈ´ÓÅ×Òì³£µÄµØ·½¿ªÊ¼£¬Ò»Ö¡Ò»Ö¡ÏòÉϼì²é£¬Ö±µ½ÕÒµ½º¬ÓÐÏàÓ¦catchµÄº¯Êý£¨»ò·¢ÏÖµ½Á˾¡Í·Ôòterminate£©£¬Èç¹ûÕÒµ½£¬ÔòÔٴλص½Òì³£Å׳öËùÔڵĺ¯Êý£¬Ò»Ö¡Ò»Ö¡µØÇåÀíµ÷ÓÃÕ»µÄ±äÁ¿£¬»»¶øÑÔÖ®£¬_Unwind_RaiseException±éÀúÁËÁ½´Îº¯Êýµ÷ÓÃÕ»£¬ÕâÁ½¸ö½×¶Î¿ÉÒÔ´ó¸ÅÓÃÈçÏÂα´úÂë±íʾ£º
¸´ÖÆ´úÂë
_Unwind_RaiseException(exception)
{
bool found = false;
while (1)
{
// ½¨Á¢Éϸöº¯ÊýµÄÉÏÏÂÎÄ
context = build_context();
found = personality_routine(exception, context, SEARCH);
if (found or reach the end) break;
}
while (found)
{
context = build_context();
personality_routine(exception, context, UNWIND);
if (reach_catch_function) break;
}
}
¸´ÖÆ´úÂë
ABIÖеĺ¯ÊýʹÓõ½ÁËÁ½¸ö×Ô¶¨ÒåµÄ½á¹¹Ì壬ÓÃÓÚ´«µÝһЩÄÚ²¿µÄÐÅÏ¢¡£
¸´ÖÆ´úÂë
struct _Unwind_Context;
struct _Unwind_Exception {
uint64 exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
uint64 private_1;
uint64 private_2;
};
¸´ÖÆ´úÂë
¸ù¾Ý½Ó¿ÚµÄ½éÉÜ£¬_Unwind_ContextÊÇÒ»¸ö¶Ôµ÷ÓÃÕß͸Ã÷µÄ½á¹¹£¬ÓÃÓÚ±íʾ³ÌÐòÔËÐеÄÉÏÏÂÎÄ£¬Ö÷Òª¾ÍÊÇһЩ¼Ä´æÆ÷µÄÖµ£¬º¯Êý·µ»ØµØÖ·µÈ£¬ËüÓɽӿÚʵÏÖÕßÀ´¶¨Òå¼°´´½¨£¬µ«ÎÒûÔÚ½Ó¿ÚÖÐÕÒµ½ËüµÄ¶¨Ò壬ֻÔÚgccµÄ
Ô´ÂëÀïÕÒµ½ÁËÒ»·ÝËüµÄ¶¨Òå¡£
¸´ÖÆ´úÂë
struct _Unwind_Context
{
void *reg[DWARF_FRAME_REGISTERS+1];
void *cfa;
void *ra;
void *lsda;
struct dwarf_eh_bases bases;
_Unwind_Word args_size;
};
¸´ÖÆ´úÂë
ÖÁÓÚ_Unwind_Exception£¬¹ËÃû˼Ò壬ËüÔÚunwind¿âÄÚÓÃÓÚ±íʾһ¸öÒì³£¡£
C++ ABI.
»ùÓÚÇ°Ãæ½éÉܵÄItanium ABI£¬±àÒëÆ÷²ãÃæÒ²¶¨ÒåһϵÁÐABIÀ´ÓëÖ®½»»¥¡£
µ±ÎÒÃÇÔÚ´ú