Skip to content

Commit

Permalink
test debug/gosym
Browse files Browse the repository at this point in the history
  • Loading branch information
wlingze committed Apr 3, 2024
1 parent 0f69ac9 commit 1216376
Showing 1 changed file with 121 additions and 0 deletions.
121 changes: 121 additions & 0 deletions tests/gosym_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package main

import (
"bytes"
"debug/buildinfo"
"debug/elf"
"debug/gosym"
"encoding/binary"
"strings"
"testing"
)

func getPclntab(file *elf.File) *elf.Section {

sectionLabel := ".gopclntab"
section := file.Section(sectionLabel)
if section != nil {
return section
}
// binary may be built with -pie
sectionLabel = ".data.rel.ro.gopclntab"
section = file.Section(sectionLabel)
if section != nil {
return section
}
sectionLabel = ".data.rel.ro"
section = file.Section(sectionLabel)
if section != nil {
return section
}
return nil
}

// From go/src/debug/gosym/pclntab.go
const (
go12magic = 0xfffffffb
go116magic = 0xfffffffa
go118magic = 0xfffffff0
go120magic = 0xfffffff1
)

// Select the magic number based on the Go version
func magicNumber(goVersion string) []byte {
bs := make([]byte, 4)
var magic uint32
if strings.Compare(goVersion, "go1.20") >= 0 {
magic = go120magic
} else if strings.Compare(goVersion, "go1.18") >= 0 {
magic = go118magic
} else if strings.Compare(goVersion, "go1.16") >= 0 {
magic = go116magic
} else {
magic = go12magic
}
binary.LittleEndian.PutUint32(bs, magic)
return bs
}

const FuncitonName = "crypto/tls.(*Conn).Read"

// readelf -sW ./testdata/docker_aarch64/docker | grep $FUNCTION
// 6649: 0000000000635cb0 928 FUNC LOCAL DEFAULT 6 crypto/tls.(*Conn).Read

// in ida:
// .text:0000000000635CB0
// .text:0000000000635CB0
// .text:0000000000635CB0 ; retval_635CB0 __golang crypto_tls__ptr_Conn_Read(crypto_tls_Conn_0 *c, _slice_uint8 b)
// .text:0000000000635CB0 crypto_tls._ptr_Conn.Read ; CODE XREF: crypto_tls._ptr_Conn.Read+390↓j
// .text:0000000000635CB0

const FunctionAddress = 0x0000000000635cb0

func TestDockerSymbolFromPclntab(t *testing.T) {
path := "./docker_binary/arm64"

// Read the build information of the Go application
buildInfo, err := buildinfo.ReadFile(path)
if err != nil {
t.Fatal("get biuldinfo error:", err)
}

file, err := elf.Open(path)
if err != nil {
t.Fatal("elf open error:", err)
}

section := getPclntab(file)
if section == nil {
t.Fatalf("con't get pclntab")
}

tableData, err := section.Data()
if err != nil {
t.Fatalf("found section but could not read pclntab from %s ", path)
}
// Find .gopclntab by magic number even if there is no section label
magic := magicNumber(buildInfo.GoVersion)
pclntabIndex := bytes.Index(tableData, magic)
if pclntabIndex < 0 {
t.Fatalf("could not find magic number in %s ", path)
}
tableData = tableData[pclntabIndex:]

addr := file.Section(".text").Addr
lineTable := gosym.NewLineTable(tableData, addr)
symTable, err := gosym.NewTable([]byte{}, lineTable)
if err != nil {
t.Fatalf("gosym.NewTable error: ", err)
}
// when this symTab builded, this function address is error,
// this functino index = 6626,
// you can set condition breakpoint in `/usr/lib/go/src/debug/gosym/pclntab.go:308` with `i==6626`, this code build this functino.
f := symTable.LookupFunc(FuncitonName)
if f == nil {
t.Fatalf("con't looup symbol %s", FuncitonName)
}
if f.Value != FunctionAddress {
t.Fatalf("error symbol address: got[0x%08x] vs want[0x%08x]", f.Value, FunctionAddress)
}

}

0 comments on commit 1216376

Please sign in to comment.