GAS-CFI.TXT

Programs and patches

CFI support for GNU assembler

Historical notes and examples for hand-written DWARF2 unwind information.

Last updated · 7 April 2006

Modern ABIs don't require frame pointers to be used in functions. However missing FPs bring difficulties when doing a backtrace. One solution is to provide Dwarf-2 CFI data for each such function. This can be easily done for example by GCC in it's output, but isn't that easy to write by hand for pure assembler functions.

With the help of these .cfi_* directives one can add appropriate unwind info into his asm source without too much trouble.

Directives implemented so far:

.cfi_startproc
Use at the beginning of each function. It initializes some internal data structures and emits initial CFI instructions.
.cfi_endproc
Opens .eh_frame, generates appropriate binary structures (CIE, FDE) and sets up relocation records.
.cfi_def_cfa reg,imm
Set a rule for computing CFA to: take content of register reg and add imm to it.
.cfi_def_cfa_register reg
Change rule for CFA to use reg. Offset remains the same.
.cfi_def_cfa_offset imm
Change rule for CFA to use offset imm. Register remains the same.
.cfi_adjust_cfa_offset imm
Like the previous one but imm is a relative value that will be added to current offset instead of an absolute value as in .cfi_def_cfa_offset.
.cfi_offset reg,imm
Generate a rule saying that register reg is saved at offset imm from CFA.

Related links:

Example file
Read example.s below · Download raw example.s
Dwarf-2 standard
dwarf-2.0.0.pdf

example.s source


#; Demonstration of using GAS CFI directives.
#; Michal Ludvig <michal@logix.cz>
#; /devel/gas-cfi

#; $ as -o test.o gas-cfi-test.s && gcc -nostdlib -o test test.o

        .text

#; func_locvars
#; - function with a space on the stack 
#;   allocated for local variables

        .type   func_locvars,@function
func_locvars:
        .cfi_startproc

        #; alocate space for local vars
        sub     $0x1234,%rsp
        .cfi_adjust_cfa_offset  0x1234

        #; dummy body
        movl    $1,%eax

        #; release space of local vars and return
        add     $0x1234,%rsp
        .cfi_adjust_cfa_offset  -0x1234
        ret
        .cfi_endproc

#; func_prologue
#; - functions that begins with standard
#;   prologue: "pushq %rbp; movq %rsp,%rbp"

        .type   func_prologue,@function
func_prologue:
        .cfi_startproc

        #; prologue, CFI is valid after 
        #; each instruction.
        pushq   %rbp
        .cfi_def_cfa_offset     16
        .cfi_offset             rbp,-16
        movq    %rsp, %rbp
        .cfi_def_cfa_register   rbp

        #; function body
        call    func_locvars
        addl    $3, %eax

        #; epilogue with a valid CFI
        #; (we're better than gcc :-)
        leaveq
        .cfi_def_cfa            rsp,8
        ret
        .cfi_endproc

#; func_otherreg
#; - function that moves frame pointer to 
#;   another register (r12) and then allocates 
#;   a space for local variables

        .type   func_otherreg,@function
func_otherreg:
        .cfi_startproc

        #; save frame pointer to r12
        movq    %rsp,%r12
        .cfi_def_cfa_register   r12

        #; alocate space for local vars
        #;  (no .cfi_{def,adjust}_cfa_offset here,
        #;   because CFA is computed from r12!)
        sub     $100,%rsp

        #; function body
        call    func_prologue
        addl    $2, %eax

        #; restore frame pointer from r12
        movq    %r12,%rsp
        .cfi_def_cfa_register   rsp
        ret
        .cfi_endproc

#; main
#; - typical function
        .type   main,@function
main:
        .cfi_startproc

        #; only function body that doesn't
        #; touch the stack at all.
        call    func_otherreg

        #; return
        ret
        .cfi_endproc

#; _start
#; - standard entry point

        .type   _start,@function
        .globl  _start
_start:
        .cfi_startproc
        call    main
        movq    %rax,%rdi
        movq    $0x3c,%rax
        syscall
        hlt
        .cfi_endproc

Download raw example.s ↓

CFI support for GNU assemblerUTF-8 · LOGIX.CZ

Find in Logix

Search page titles and descriptions. Esc closes.

A few handy keys

A little Borland, a little early desktop, a corner of the web to call home.

Pick a directory from the menu or tree. Use Find when you know what you’re after.

Tab / Shift+Tab
Move between controls
↑ / ↓ in menus
Choose an entry
← / → in menus
Switch directories
/
Find a page
Esc
Close menu or dialog
F1
Open this help

Prefer a different atmosphere? View has blue, grey, and green palettes.

No commands to learn. Just follow your curiosity.