eliben / pyelftools

Parsing ELF and DWARF in Python
Other
1.99k stars 507 forks source link

DWARF CFI not correct in golang #554

Closed XinShuichen closed 4 months ago

XinShuichen commented 4 months ago

I found that the CFI parsing is incorrect in the Go program.

With a simple go program:

package main

import (
    "os"
    "time"
)

func main() {
    function1()
}

func function1() {
    var a [64]int
    _ = a
    function2()
}

func function2() {
    var a [32]int
    _ = a
    function3()
}

func function3() {
    var a [16]int
    _ = a
    function4()
}

func function4() {
    var a [8]int
    _ = a
    function5()
}

func function5() {
    var a [4]int
    _ = a

    for {
        appendToFile("/tmp/test", "1")
        time.Sleep(1 * time.Second)
    }
}

func appendToFile(filename, content string) {
    f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    if err != nil {
        panic(err)
    }
    defer f.Close()

    if _, err := f.WriteString(content); err != nil {
        panic(err)
    }
}

Decoded CFI Example:

402500 : {'pc': 4203776, 'cfa': CFARule(reg=7, offset=8, expr=None), 16: RegisterRule(OFFSET, -8)}
402504 : {'pc': 4203780, 'cfa': CFARule(reg=7, offset=8, expr=None), 16: RegisterRule(OFFSET, -8)}
40251c : {'pc': 4203804, 'cfa': CFARule(reg=7, offset=8, expr=None), 16: RegisterRule(OFFSET, -8)}
40251c : {'pc': 4203804, 'cfa': CFARule(reg=7, offset=8, expr=None), 16: RegisterRule(OFFSET, -8)}
402520 : {'pc': 4203808, 'cfa': CFARule(reg=7, offset=8, expr=None), 16: RegisterRule(OFFSET, -8)}
402555 : {'pc': 4203861, 'cfa': CFARule(reg=7, offset=8, expr=None), 16: RegisterRule(OFFSET, -8)}

In llvm-dwarfdump output:

000002e4 00000024 00000000 FDE cie=00000000 pc=00402500...0040251d
  Format:       DWARF32
  DW_CFA_def_cfa_offset_sf: 8
  DW_CFA_advance_loc: 4
  DW_CFA_def_cfa_offset_sf: 72
  DW_CFA_advance_loc: 24
  DW_CFA_def_cfa_offset_sf: 8
  DW_CFA_advance_loc: 0
  DW_CFA_nop:
  DW_CFA_nop:
  DW_CFA_nop:
  DW_CFA_nop:
  DW_CFA_nop:
  DW_CFA_nop:
  DW_CFA_nop:

  0x402500: CFA=RSP+8: RIP=[CFA-8]
  0x402504: CFA=RSP+72: RIP=[CFA-8]
  0x40251c: CFA=RSP+8: RIP=[CFA-8]
  0x40251c: CFA=RSP+8: RIP=[CFA-8]

0000030c 0000001c 00000000 FDE cie=00000000 pc=00402520...00402556
  Format:       DWARF32
  DW_CFA_def_cfa_offset_sf: 8
  DW_CFA_advance_loc: 53
  DW_CFA_nop:
  DW_CFA_nop:
  DW_CFA_nop:
  DW_CFA_nop:
  DW_CFA_nop:

  0x402520: CFA=RSP+8: RIP=[CFA-8]
  0x402555: CFA=RSP+8: RIP=[CFA-8]

Go version is go1.20.4 linux/amd64 Kernel is 5.4.56 OS is debian 10 llvm-dwarfdump is Debian LLVM version 15.0.7

pyelftools on branch main

go_simple.zip