GCC C++ Exception Handling Implementation

后端 未结 2 1001
隐瞒了意图╮
隐瞒了意图╮ 2021-02-06 02:13

I would like to know how GCC implements exception handling for C++ programs. I couldn\'t find an easy-to-understand and self-explanatory article on the Web (although there are m

相关标签:
2条回答
  • 2021-02-06 02:40

    The Itanium ABI (which both gcc, clang and a number of others follow) specify that exception handling should follow the Zero-Cost strategy.

    The idea of the Zero-Cost strategy is to push all exception handling in side-tables that are not kept on the main program execution path (and thus not trashing the instruction cache). These tables are indexed by the program point.

    Furthermore, DWARF information (which is debug information really) is used to unwind the stack. This functionality is usually provided as a library such as libunwind for example, the source code is chokeful of assembly (and thus very platform specific).

    Advantages:

    • 0-cost for entering try/catch block (as fast as if there was none)
    • 0-cost for having a throw statement in a function (as long as it is not taken)

    Disadvantage:

    • Slow in case of exception (10x slower than an if strategy) because the side tables are usually not in cache and then there are expensive computations to run to know which catch clause actually matches (based on RTTI)

    It is a very popular strategy implement on both 32 bits and 64 bits platform for all major compilers... except MSVC 32 bits (if I remember correctly).

    0 讨论(0)
  • 2021-02-06 02:59

    .eh_frame layout is described briefly in the LSB documentation. Ian Lance Taylor (author of the gold linker) also made some blog posts on .eh_frame and .gcc_except_table layout.

    For a more reference-like description, check my Recon 2012 slides (start at 37 or so).

    EDIT: here's the commented structures from your sample. First, the .eh_table (some parts omitted for clarity):

    .Lframe1:                     # start of CFI 1
        .long   .LECIE1-.LSCIE1   # length of CIE 1 data
    .LSCIE1:                      # start of CIE 1 data
        .long   0                 # CIE id
        .byte   0x1               # Version
        .string "zPL"             # augmentation string:
                                  # z: has augmentation data
                                  # P: has personality routine pointer
                                  # L: has LSDA pointer
        .uleb128 0x1              # code alignment factor
        .sleb128 -4               # data alignment factor
        .byte   0x8               # return address register no.
        .uleb128 0x6              # augmentation data length (z)
        .byte   0                 # personality routine pointer encoding (P): DW_EH_PE_ptr|DW_EH_PE_absptr
        .long   __gxx_personality_v0 # personality routine pointer (P)
        .byte   0                 # LSDA pointer encoding: DW_EH_PE_ptr|DW_EH_PE_absptr
        .byte   0xc               # Initial CFI Instructions
        [...]
        .align 4
    .LECIE1:                      # end of CIE 1
        [...]
    
    .LSFDE3:                      # start of FDE 3
        .long   .LEFDE3-.LASFDE3  # length of FDE 3
    .LASFDE3:                     # start of FDE 3 data
        .long   .LASFDE3-.Lframe1 # Distance to parent CIE from here
        .long   .LFB1             # initial location                
        .long   .LFE1-.LFB1       # range length                    
        .uleb128 0x4              # Augmentation data length (z)    
        .long   .LLSDA1           # LSDA pointer (L)                
        .byte   0x4               # CFI instructions                
        .long   .LCFI2-.LFB1
        [...]
        .align 4
    .LEFDE3:                      # end of FDE 3
    

    Next, the LSDA (language-specific data area) referenced by FDE 3:

    .LLSDA1:                           # LSDA 1
        .byte   0xff                   # LPStart encoding: DW_EH_PE_omit
        .byte   0                      # TType encoding: DW_EH_PE_ptr|DW_EH_PE_absptr
        .uleb128 .LLSDATT1-.LLSDATTD1  # TType offset
    .LLSDATTD1:                        # LSDA 1 action table
        .byte   0x1                    # call site encoding: DW_EH_PE_uleb128|DW_EH_PE_absptr
        .uleb128 .LLSDACSE1-.LLSDACSB1 # call site table length
    .LLSDACSB1:                        # LSDA 1 call site entries
        .uleb128 .LEHB0-.LFB1          # call site 0 start
        .uleb128 .LEHE0-.LEHB0         # call site 0 length
        .uleb128 .L8-.LFB1             # call site 0 landing pad
        .uleb128 0x1                   # call site 0 action (1=action 1)
        .uleb128 .LEHB1-.LFB1          # call site 1 start
        .uleb128 .LEHE1-.LEHB1         # call site 1 length
        .uleb128 0                     # call site 1 landing pad
        .uleb128 0                     # call site 1 action (0=no action)
    .LLSDACSE1:                        # LSDA 1 action table entries
        .byte   0x1                    # action 1 filter (1=T1 typeinfo)
        .byte   0                      # displacement to next action (0=end of chain)
        .align 4
        .long   _ZTIi                  # T1 typeinfo ("typeinfo for int")
    .LLSDATT1:                         # LSDA 1 TTBase
    
    0 讨论(0)
提交回复
热议问题