mirror of
https://github.com/hengyoush/kyanos.git
synced 2025-12-20 01:03:46 +08:00
fix: add check for AttrDataMemberLoc when val is []uint8 (#273)
This commit is contained in:
109
agent/uprobe/dwarf_reader/buf.go
Normal file
109
agent/uprobe/dwarf_reader/buf.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package dwarfreader
|
||||||
|
|
||||||
|
import (
|
||||||
|
"debug/dwarf"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Data buffer being decoded.
|
||||||
|
type buf struct {
|
||||||
|
dwarf *dwarf.Data
|
||||||
|
format dataFormat
|
||||||
|
name string
|
||||||
|
off dwarf.Offset
|
||||||
|
data []byte
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data format, other than byte order. This affects the handling of
|
||||||
|
// certain field formats.
|
||||||
|
type dataFormat interface {
|
||||||
|
// DWARF version number. Zero means unknown.
|
||||||
|
version() int
|
||||||
|
|
||||||
|
// 64-bit DWARF format?
|
||||||
|
dwarf64() (dwarf64 bool, isKnown bool)
|
||||||
|
|
||||||
|
// Size of an address, in bytes. Zero means unknown.
|
||||||
|
addrsize() int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some parts of DWARF have no data format, e.g., abbrevs.
|
||||||
|
type UnknownFormat struct{}
|
||||||
|
|
||||||
|
func (u UnknownFormat) version() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u UnknownFormat) dwarf64() (bool, bool) {
|
||||||
|
return false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u UnknownFormat) addrsize() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeBuf(d *dwarf.Data, format dataFormat, name string, off dwarf.Offset, data []byte) buf {
|
||||||
|
return buf{d, format, name, off, data, nil}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *buf) Uint8() uint8 {
|
||||||
|
if len(b.data) < 1 {
|
||||||
|
b.error("underflow")
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
val := b.data[0]
|
||||||
|
b.data = b.data[1:]
|
||||||
|
b.off++
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read a varint, which is 7 bits per byte, little endian.
|
||||||
|
// the 0x80 bit means read another byte.
|
||||||
|
func (b *buf) Varint() (c uint64, bits uint) {
|
||||||
|
for i := 0; i < len(b.data); i++ {
|
||||||
|
byte := b.data[i]
|
||||||
|
c |= uint64(byte&0x7F) << bits
|
||||||
|
bits += 7
|
||||||
|
if byte&0x80 == 0 {
|
||||||
|
b.off += dwarf.Offset(i + 1)
|
||||||
|
b.data = b.data[i+1:]
|
||||||
|
return c, bits
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unsigned int is just a varint.
|
||||||
|
func (b *buf) Uint() uint64 {
|
||||||
|
x, _ := b.Varint()
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signed int is a sign-extended varint.
|
||||||
|
func (b *buf) Int() int64 {
|
||||||
|
ux, bits := b.Varint()
|
||||||
|
x := int64(ux)
|
||||||
|
if x&(1<<(bits-1)) != 0 {
|
||||||
|
x |= -1 << bits
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssertEmpty checks that everything has been read from b.
|
||||||
|
func (b *buf) AssertEmpty() {
|
||||||
|
if len(b.data) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(b.data) > 5 {
|
||||||
|
b.error(fmt.Sprintf("unexpected extra data: %x...", b.data[0:5]))
|
||||||
|
}
|
||||||
|
b.error(fmt.Sprintf("unexpected extra data: %x", b.data))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *buf) error(s string) {
|
||||||
|
if b.Err == nil {
|
||||||
|
b.data = nil
|
||||||
|
b.Err = dwarf.DecodeError{Name: b.name, Offset: b.off, Err: s}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -190,18 +190,45 @@ func GetStructMemberInfo(structName string, tag dwarf.Tag, memberName string, me
|
|||||||
}
|
}
|
||||||
return &memberInfo, nil
|
return &memberInfo, nil
|
||||||
}
|
}
|
||||||
return nil, errors.New(fmt.Sprintf("Could not find member %s in struct %s.", memberName, structName))
|
return nil, fmt.Errorf("could not find member %s in struct %s", memberName, structName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMemberOffset(die *dwarf.Entry) (int64, error) {
|
func GetMemberOffset(die *dwarf.Entry) (int64, error) {
|
||||||
|
const DW_OP_plus_uconst = 0x23
|
||||||
|
const DW_OP_consts = 0x11
|
||||||
|
const DW_OP_plus = 0x22
|
||||||
|
|
||||||
if die.Tag != dwarf.TagMember {
|
if die.Tag != dwarf.TagMember {
|
||||||
panic("not a member")
|
panic("not a member")
|
||||||
}
|
}
|
||||||
attr := die.AttrField(dwarf.AttrDataMemberLoc)
|
attr := die.AttrField(dwarf.AttrDataMemberLoc)
|
||||||
if attr == nil {
|
if attr == nil {
|
||||||
return 0, errors.New(fmt.Sprintf("can't find DW_AT_data_member_location"))
|
return 0, fmt.Errorf("can't find DW_AT_data_member_location")
|
||||||
}
|
}
|
||||||
return attr.Val.(int64), nil
|
var offset int64
|
||||||
|
switch val := attr.Val.(type) {
|
||||||
|
case int64:
|
||||||
|
return attr.Val.(int64), nil
|
||||||
|
case []byte:
|
||||||
|
if len(val) == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
b := MakeBuf(nil, UnknownFormat{}, "location", 0, val)
|
||||||
|
op := b.Uint8()
|
||||||
|
switch op {
|
||||||
|
case DW_OP_plus_uconst: // DW_OP_plus_uconst, Handle opcode sequence [DW_OP_plus_uconst <uleb128>]
|
||||||
|
offset = int64(b.Uint())
|
||||||
|
case DW_OP_consts: // DW_OP_consts, Handle opcode sequence [DW_OP_consts <sleb128> DW_OP_plus]
|
||||||
|
offset = b.Int()
|
||||||
|
op = b.Uint8()
|
||||||
|
if op != DW_OP_plus {
|
||||||
|
return -1, fmt.Errorf("unexpected opcode 0x%x exptect: 0x%x", op, DW_OP_plus)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return -1, fmt.Errorf("unknown opcode: %x", op)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return offset, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetNumPrimitives(die *dwarf.Entry, reader *dwarf.Reader) (int, error) {
|
func GetNumPrimitives(die *dwarf.Entry, reader *dwarf.Reader) (int, error) {
|
||||||
|
|||||||
@@ -62,7 +62,14 @@ func LoadGoTlsUprobe() error {
|
|||||||
goTlsObjs = objs
|
goTlsObjs = objs
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func AttachGoTlsProbes(pid int) ([]link.Link, error) {
|
func AttachGoTlsProbes(pid int) (_links []link.Link, e error) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
common.UprobeLog.Errorf("Recovered in AttachGoTlsProbes: %v", r)
|
||||||
|
_links = nil
|
||||||
|
e = fmt.Errorf("attachBpfProgs panic: %v", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
if goTlsObjs == nil {
|
if goTlsObjs == nil {
|
||||||
return nil, errors.New("GoTlsObjs not loaded")
|
return nil, errors.New("GoTlsObjs not loaded")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ func (bf *BPF) AttachProgs(options *ac.AgentOptions) error {
|
|||||||
}
|
}
|
||||||
bpf.PullProcessExecEvents(options.Ctx, &execEventChannels)
|
bpf.PullProcessExecEvents(options.Ctx, &execEventChannels)
|
||||||
|
|
||||||
attachOpenSslUprobes(links, options, options.Kv, bf.Objs)
|
attachUprobes(links, options, options.Kv, bf.Objs)
|
||||||
options.LoadPorgressChannel <- "🍕 Attached ssl eBPF programs."
|
options.LoadPorgressChannel <- "🍕 Attached ssl eBPF programs."
|
||||||
}
|
}
|
||||||
attachSchedProgs(links)
|
attachSchedProgs(links)
|
||||||
@@ -683,7 +683,7 @@ func attachBpfProgs(ifName string, kernelVersion *compatible.KernelVersion, opti
|
|||||||
return linkList, nil
|
return linkList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func attachOpenSslUprobes(links *list.List, options *ac.AgentOptions, kernelVersion *compatible.KernelVersion, objs any) {
|
func attachUprobes(links *list.List, options *ac.AgentOptions, kernelVersion *compatible.KernelVersion, objs any) {
|
||||||
pids, err := common.GetAllPids()
|
pids, err := common.GetAllPids()
|
||||||
loadGoTlsErr := uprobe.LoadGoTlsUprobe()
|
loadGoTlsErr := uprobe.LoadGoTlsUprobe()
|
||||||
if loadGoTlsErr != nil {
|
if loadGoTlsErr != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user