1 Star 1 Fork 1

mjun1833 / delve

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
dynamic.go 4.21 KB
一键复制 编辑 原始数据 按行查看 历史
majun 提交于 2023-08-24 16:44 . chore: update module name
package linutil
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
"gitee.com/mjun1833/delve/pkg/proc"
)
const (
maxNumLibraries = 1000000 // maximum number of loaded libraries, to avoid loading forever on corrupted memory
maxLibraryPathLength = 1000000 // maximum length for the path of a library, to avoid loading forever on corrupted memory
)
var ErrTooManyLibraries = errors.New("number of loaded libraries exceeds maximum")
const (
_DT_NULL = 0 // DT_NULL as defined by SysV ABI specification
_DT_DEBUG = 21 // DT_DEBUG as defined by SysV ABI specification
)
// readUintRaw reads an integer of ptrSize bytes, with the specified byte order, from reader.
func readUintRaw(reader io.Reader, order binary.ByteOrder, ptrSize int) (uint64, error) {
switch ptrSize {
case 4:
var n uint32
if err := binary.Read(reader, order, &n); err != nil {
return 0, err
}
return uint64(n), nil
case 8:
var n uint64
if err := binary.Read(reader, order, &n); err != nil {
return 0, err
}
return n, nil
}
return 0, fmt.Errorf("not supported ptr size %d", ptrSize)
}
// dynamicSearchDebug searches for the DT_DEBUG entry in the .dynamic section
func dynamicSearchDebug(p proc.Process) (uint64, error) {
bi := p.BinInfo()
mem := p.Memory()
dynbuf := make([]byte, bi.ElfDynamicSection.Size)
_, err := mem.ReadMemory(dynbuf, bi.ElfDynamicSection.Addr)
if err != nil {
return 0, err
}
rd := bytes.NewReader(dynbuf)
for {
var tag, val uint64
if tag, err = readUintRaw(rd, binary.LittleEndian, p.BinInfo().Arch.PtrSize()); err != nil {
return 0, err
}
if val, err = readUintRaw(rd, binary.LittleEndian, p.BinInfo().Arch.PtrSize()); err != nil {
return 0, err
}
switch tag {
case _DT_NULL:
return 0, nil
case _DT_DEBUG:
return val, nil
}
}
}
func readPtr(p proc.Process, addr uint64) (uint64, error) {
ptrbuf := make([]byte, p.BinInfo().Arch.PtrSize())
_, err := p.Memory().ReadMemory(ptrbuf, addr)
if err != nil {
return 0, err
}
return readUintRaw(bytes.NewReader(ptrbuf), binary.LittleEndian, p.BinInfo().Arch.PtrSize())
}
type linkMap struct {
addr uint64
name string
ld uint64
next, prev uint64
}
func readLinkMapNode(p proc.Process, r_map uint64) (*linkMap, error) {
bi := p.BinInfo()
var lm linkMap
var ptrs [5]uint64
for i := range ptrs {
var err error
ptrs[i], err = readPtr(p, r_map+uint64(bi.Arch.PtrSize()*i))
if err != nil {
return nil, err
}
}
lm.addr = ptrs[0]
var err error
lm.name, err = readCString(p, ptrs[1])
if err != nil {
return nil, err
}
lm.ld = ptrs[2]
lm.next = ptrs[3]
lm.prev = ptrs[4]
return &lm, nil
}
func readCString(p proc.Process, addr uint64) (string, error) {
if addr == 0 {
return "", nil
}
mem := p.Memory()
buf := make([]byte, 1)
r := []byte{}
for {
if len(r) > maxLibraryPathLength {
return "", fmt.Errorf("error reading libraries: string too long (%d)", len(r))
}
_, err := mem.ReadMemory(buf, addr)
if err != nil {
return "", err
}
if buf[0] == 0 {
break
}
r = append(r, buf[0])
addr++
}
return string(r), nil
}
// ElfUpdateSharedObjects reads the list of dynamic libraries loaded by the
// dynamic linker from the .dynamic section and uses it to update p.BinInfo().
// See the SysV ABI for a description of how the .dynamic section works:
// http://www.sco.com/developers/gabi/latest/contents.html
func ElfUpdateSharedObjects(p proc.Process) error {
bi := p.BinInfo()
if bi.ElfDynamicSection.Addr == 0 {
// no dynamic section, therefore nothing to do here
return nil
}
debugAddr, err := dynamicSearchDebug(p)
if err != nil {
return err
}
if debugAddr == 0 {
// no DT_DEBUG entry
return nil
}
// Offsets of the fields of the r_debug and link_map structs,
// see /usr/include/elf/link.h for a full description of those structs.
debugMapOffset := uint64(p.BinInfo().Arch.PtrSize())
r_map, err := readPtr(p, debugAddr+debugMapOffset)
if err != nil {
return err
}
libs := []string{}
for {
if r_map == 0 {
break
}
if len(libs) > maxNumLibraries {
return ErrTooManyLibraries
}
lm, err := readLinkMapNode(p, r_map)
if err != nil {
return err
}
bi.AddImage(lm.name, lm.addr)
libs = append(libs, lm.name)
r_map = lm.next
}
return nil
}
Go
1
https://gitee.com/mjun1833/delve.git
git@gitee.com:mjun1833/delve.git
mjun1833
delve
delve
v1.21.1

搜索帮助

53164aa7 5694891 3bd8fe86 5694891