1
0
mirror of https://github.com/beego/bee.git synced 2025-07-01 17:20:17 +00:00

Updated vendor

This commit is contained in:
Ruben Cid
2019-04-15 16:43:01 +02:00
parent 33dd897647
commit da91d50ab8
134 changed files with 4988 additions and 2530 deletions

View File

@ -0,0 +1,39 @@
package linutil
import (
"bytes"
"encoding/binary"
)
const (
_AT_NULL_AMD64 = 0
_AT_ENTRY_AMD64 = 9
)
// EntryPointFromAuxv searches the elf auxiliary vector for the entry point
// address.
// For a description of the auxiliary vector (auxv) format see:
// System V Application Binary Interface, AMD64 Architecture Processor
// Supplement, section 3.4.3
func EntryPointFromAuxvAMD64(auxv []byte) uint64 {
rd := bytes.NewBuffer(auxv)
for {
var tag, val uint64
err := binary.Read(rd, binary.LittleEndian, &tag)
if err != nil {
return 0
}
err = binary.Read(rd, binary.LittleEndian, &val)
if err != nil {
return 0
}
switch tag {
case _AT_NULL_AMD64:
return 0
case _AT_ENTRY_AMD64:
return val
}
}
}

View File

@ -0,0 +1,4 @@
// This package contains functions and data structures used by both the
// linux implementation of the native backend and the core backend to deal
// with structures used by the linux kernel.
package linutil

View File

@ -0,0 +1,172 @@
package linutil
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"github.com/go-delve/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
)
// dynamicSearchDebug searches for the DT_DEBUG entry in the .dynamic section
func dynamicSearchDebug(p proc.Process) (uint64, error) {
bi := p.BinInfo()
mem := p.CurrentThread()
dynbuf := make([]byte, bi.ElfDynamicSection.Size)
_, err := mem.ReadMemory(dynbuf, uintptr(bi.ElfDynamicSection.Addr))
if err != nil {
return 0, err
}
rd := bytes.NewReader(dynbuf)
for {
var tag, val uint64
if err := binary.Read(rd, binary.LittleEndian, &tag); err != nil {
return 0, err
}
if err := binary.Read(rd, binary.LittleEndian, &val); err != nil {
return 0, err
}
switch tag {
case _DT_NULL:
return 0, nil
case _DT_DEBUG:
return val, nil
}
}
}
// hard-coded 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.
const (
_R_DEBUG_MAP_OFFSET = 8
_LINK_MAP_ADDR_OFFSET = 0 // offset of link_map.l_addr field (base address shared object is loaded at)
_LINK_MAP_NAME_OFFSET = 8 // offset of link_map.l_name field (absolute file name object was found in)
_LINK_MAP_LD = 16 // offset of link_map.l_ld field (dynamic section of the shared object)
_LINK_MAP_NEXT = 24 // offset of link_map.l_next field
_LINK_MAP_PREV = 32 // offset of link_map.l_prev field
)
func readPtr(p proc.Process, addr uint64) (uint64, error) {
ptrbuf := make([]byte, p.BinInfo().Arch.PtrSize())
_, err := p.CurrentThread().ReadMemory(ptrbuf, uintptr(addr))
if err != nil {
return 0, err
}
return binary.LittleEndian.Uint64(ptrbuf), nil
}
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.CurrentThread()
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, uintptr(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
}
r_map, err := readPtr(p, debugAddr+_R_DEBUG_MAP_OFFSET)
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
}

View File

@ -0,0 +1,399 @@
package linutil
import (
"bytes"
"encoding/binary"
"fmt"
"golang.org/x/arch/x86/x86asm"
"github.com/go-delve/delve/pkg/proc"
)
// AMD64Registers implements the proc.Registers interface for the native/linux
// backend and core/linux backends, on AMD64.
type AMD64Registers struct {
Regs *AMD64PtraceRegs
Fpregs []proc.Register
Fpregset *AMD64Xstate
}
// AMD64PtraceRegs is the struct used by the linux kernel to return the
// general purpose registers for AMD64 CPUs.
type AMD64PtraceRegs struct {
R15 uint64
R14 uint64
R13 uint64
R12 uint64
Rbp uint64
Rbx uint64
R11 uint64
R10 uint64
R9 uint64
R8 uint64
Rax uint64
Rcx uint64
Rdx uint64
Rsi uint64
Rdi uint64
Orig_rax uint64
Rip uint64
Cs uint64
Eflags uint64
Rsp uint64
Ss uint64
Fs_base uint64
Gs_base uint64
Ds uint64
Es uint64
Fs uint64
Gs uint64
}
// Slice returns the registers as a list of (name, value) pairs.
func (r *AMD64Registers) Slice(floatingPoint bool) []proc.Register {
var regs = []struct {
k string
v uint64
}{
{"Rip", r.Regs.Rip},
{"Rsp", r.Regs.Rsp},
{"Rax", r.Regs.Rax},
{"Rbx", r.Regs.Rbx},
{"Rcx", r.Regs.Rcx},
{"Rdx", r.Regs.Rdx},
{"Rdi", r.Regs.Rdi},
{"Rsi", r.Regs.Rsi},
{"Rbp", r.Regs.Rbp},
{"R8", r.Regs.R8},
{"R9", r.Regs.R9},
{"R10", r.Regs.R10},
{"R11", r.Regs.R11},
{"R12", r.Regs.R12},
{"R13", r.Regs.R13},
{"R14", r.Regs.R14},
{"R15", r.Regs.R15},
{"Orig_rax", r.Regs.Orig_rax},
{"Cs", r.Regs.Cs},
{"Eflags", r.Regs.Eflags},
{"Ss", r.Regs.Ss},
{"Fs_base", r.Regs.Fs_base},
{"Gs_base", r.Regs.Gs_base},
{"Ds", r.Regs.Ds},
{"Es", r.Regs.Es},
{"Fs", r.Regs.Fs},
{"Gs", r.Regs.Gs},
}
out := make([]proc.Register, 0, len(regs)+len(r.Fpregs))
for _, reg := range regs {
if reg.k == "Eflags" {
out = proc.AppendEflagReg(out, reg.k, reg.v)
} else {
out = proc.AppendQwordReg(out, reg.k, reg.v)
}
}
if floatingPoint {
out = append(out, r.Fpregs...)
}
return out
}
// PC returns the value of RIP register.
func (r *AMD64Registers) PC() uint64 {
return r.Regs.Rip
}
// SP returns the value of RSP register.
func (r *AMD64Registers) SP() uint64 {
return r.Regs.Rsp
}
func (r *AMD64Registers) BP() uint64 {
return r.Regs.Rbp
}
// CX returns the value of RCX register.
func (r *AMD64Registers) CX() uint64 {
return r.Regs.Rcx
}
// TLS returns the address of the thread local storage memory segment.
func (r *AMD64Registers) TLS() uint64 {
return r.Regs.Fs_base
}
// GAddr returns the address of the G variable if it is known, 0 and false
// otherwise.
func (r *AMD64Registers) GAddr() (uint64, bool) {
return 0, false
}
// Get returns the value of the n-th register (in x86asm order).
func (r *AMD64Registers) Get(n int) (uint64, error) {
reg := x86asm.Reg(n)
const (
mask8 = 0x000f
mask16 = 0x00ff
mask32 = 0xffff
)
switch reg {
// 8-bit
case x86asm.AL:
return r.Regs.Rax & mask8, nil
case x86asm.CL:
return r.Regs.Rcx & mask8, nil
case x86asm.DL:
return r.Regs.Rdx & mask8, nil
case x86asm.BL:
return r.Regs.Rbx & mask8, nil
case x86asm.AH:
return (r.Regs.Rax >> 8) & mask8, nil
case x86asm.CH:
return (r.Regs.Rcx >> 8) & mask8, nil
case x86asm.DH:
return (r.Regs.Rdx >> 8) & mask8, nil
case x86asm.BH:
return (r.Regs.Rbx >> 8) & mask8, nil
case x86asm.SPB:
return r.Regs.Rsp & mask8, nil
case x86asm.BPB:
return r.Regs.Rbp & mask8, nil
case x86asm.SIB:
return r.Regs.Rsi & mask8, nil
case x86asm.DIB:
return r.Regs.Rdi & mask8, nil
case x86asm.R8B:
return r.Regs.R8 & mask8, nil
case x86asm.R9B:
return r.Regs.R9 & mask8, nil
case x86asm.R10B:
return r.Regs.R10 & mask8, nil
case x86asm.R11B:
return r.Regs.R11 & mask8, nil
case x86asm.R12B:
return r.Regs.R12 & mask8, nil
case x86asm.R13B:
return r.Regs.R13 & mask8, nil
case x86asm.R14B:
return r.Regs.R14 & mask8, nil
case x86asm.R15B:
return r.Regs.R15 & mask8, nil
// 16-bit
case x86asm.AX:
return r.Regs.Rax & mask16, nil
case x86asm.CX:
return r.Regs.Rcx & mask16, nil
case x86asm.DX:
return r.Regs.Rdx & mask16, nil
case x86asm.BX:
return r.Regs.Rbx & mask16, nil
case x86asm.SP:
return r.Regs.Rsp & mask16, nil
case x86asm.BP:
return r.Regs.Rbp & mask16, nil
case x86asm.SI:
return r.Regs.Rsi & mask16, nil
case x86asm.DI:
return r.Regs.Rdi & mask16, nil
case x86asm.R8W:
return r.Regs.R8 & mask16, nil
case x86asm.R9W:
return r.Regs.R9 & mask16, nil
case x86asm.R10W:
return r.Regs.R10 & mask16, nil
case x86asm.R11W:
return r.Regs.R11 & mask16, nil
case x86asm.R12W:
return r.Regs.R12 & mask16, nil
case x86asm.R13W:
return r.Regs.R13 & mask16, nil
case x86asm.R14W:
return r.Regs.R14 & mask16, nil
case x86asm.R15W:
return r.Regs.R15 & mask16, nil
// 32-bit
case x86asm.EAX:
return r.Regs.Rax & mask32, nil
case x86asm.ECX:
return r.Regs.Rcx & mask32, nil
case x86asm.EDX:
return r.Regs.Rdx & mask32, nil
case x86asm.EBX:
return r.Regs.Rbx & mask32, nil
case x86asm.ESP:
return r.Regs.Rsp & mask32, nil
case x86asm.EBP:
return r.Regs.Rbp & mask32, nil
case x86asm.ESI:
return r.Regs.Rsi & mask32, nil
case x86asm.EDI:
return r.Regs.Rdi & mask32, nil
case x86asm.R8L:
return r.Regs.R8 & mask32, nil
case x86asm.R9L:
return r.Regs.R9 & mask32, nil
case x86asm.R10L:
return r.Regs.R10 & mask32, nil
case x86asm.R11L:
return r.Regs.R11 & mask32, nil
case x86asm.R12L:
return r.Regs.R12 & mask32, nil
case x86asm.R13L:
return r.Regs.R13 & mask32, nil
case x86asm.R14L:
return r.Regs.R14 & mask32, nil
case x86asm.R15L:
return r.Regs.R15 & mask32, nil
// 64-bit
case x86asm.RAX:
return r.Regs.Rax, nil
case x86asm.RCX:
return r.Regs.Rcx, nil
case x86asm.RDX:
return r.Regs.Rdx, nil
case x86asm.RBX:
return r.Regs.Rbx, nil
case x86asm.RSP:
return r.Regs.Rsp, nil
case x86asm.RBP:
return r.Regs.Rbp, nil
case x86asm.RSI:
return r.Regs.Rsi, nil
case x86asm.RDI:
return r.Regs.Rdi, nil
case x86asm.R8:
return r.Regs.R8, nil
case x86asm.R9:
return r.Regs.R9, nil
case x86asm.R10:
return r.Regs.R10, nil
case x86asm.R11:
return r.Regs.R11, nil
case x86asm.R12:
return r.Regs.R12, nil
case x86asm.R13:
return r.Regs.R13, nil
case x86asm.R14:
return r.Regs.R14, nil
case x86asm.R15:
return r.Regs.R15, nil
}
return 0, proc.ErrUnknownRegister
}
// Copy returns a copy of these registers that is guarenteed not to change.
func (r *AMD64Registers) Copy() proc.Registers {
var rr AMD64Registers
rr.Regs = &AMD64PtraceRegs{}
rr.Fpregset = &AMD64Xstate{}
*(rr.Regs) = *(r.Regs)
if r.Fpregset != nil {
*(rr.Fpregset) = *(r.Fpregset)
}
if r.Fpregs != nil {
rr.Fpregs = make([]proc.Register, len(r.Fpregs))
copy(rr.Fpregs, r.Fpregs)
}
return &rr
}
// AMD64PtraceFpRegs tracks user_fpregs_struct in /usr/include/x86_64-linux-gnu/sys/user.h
type AMD64PtraceFpRegs struct {
Cwd uint16
Swd uint16
Ftw uint16
Fop uint16
Rip uint64
Rdp uint64
Mxcsr uint32
MxcrMask uint32
StSpace [32]uint32
XmmSpace [256]byte
Padding [24]uint32
}
// AMD64Xstate represents amd64 XSAVE area. See Section 13.1 (and
// following) of Intel® 64 and IA-32 Architectures Software Developers
// Manual, Volume 1: Basic Architecture.
type AMD64Xstate struct {
AMD64PtraceFpRegs
Xsave []byte // raw xsave area
AvxState bool // contains AVX state
YmmSpace [256]byte
}
// Decode decodes an XSAVE area to a list of name/value pairs of registers.
func (xsave *AMD64Xstate) Decode() (regs []proc.Register) {
// x87 registers
regs = proc.AppendWordReg(regs, "CW", xsave.Cwd)
regs = proc.AppendWordReg(regs, "SW", xsave.Swd)
regs = proc.AppendWordReg(regs, "TW", xsave.Ftw)
regs = proc.AppendWordReg(regs, "FOP", xsave.Fop)
regs = proc.AppendQwordReg(regs, "FIP", xsave.Rip)
regs = proc.AppendQwordReg(regs, "FDP", xsave.Rdp)
for i := 0; i < len(xsave.StSpace); i += 4 {
regs = proc.AppendX87Reg(regs, i/4, uint16(xsave.StSpace[i+2]), uint64(xsave.StSpace[i+1])<<32|uint64(xsave.StSpace[i]))
}
// SSE registers
regs = proc.AppendMxcsrReg(regs, "MXCSR", uint64(xsave.Mxcsr))
regs = proc.AppendDwordReg(regs, "MXCSR_MASK", xsave.MxcrMask)
for i := 0; i < len(xsave.XmmSpace); i += 16 {
regs = proc.AppendSSEReg(regs, fmt.Sprintf("XMM%d", i/16), xsave.XmmSpace[i:i+16])
if xsave.AvxState {
regs = proc.AppendSSEReg(regs, fmt.Sprintf("YMM%d", i/16), xsave.YmmSpace[i:i+16])
}
}
return
}
const (
_XSAVE_HEADER_START = 512
_XSAVE_HEADER_LEN = 64
_XSAVE_EXTENDED_REGION_START = 576
_XSAVE_SSE_REGION_LEN = 416
)
// LinuxX86XstateRead reads a byte array containing an XSAVE area into regset.
// If readLegacy is true regset.PtraceFpRegs will be filled with the
// contents of the legacy region of the XSAVE area.
// See Section 13.1 (and following) of Intel® 64 and IA-32 Architectures
// Software Developers Manual, Volume 1: Basic Architecture.
func AMD64XstateRead(xstateargs []byte, readLegacy bool, regset *AMD64Xstate) error {
if _XSAVE_HEADER_START+_XSAVE_HEADER_LEN >= len(xstateargs) {
return nil
}
if readLegacy {
rdr := bytes.NewReader(xstateargs[:_XSAVE_HEADER_START])
if err := binary.Read(rdr, binary.LittleEndian, &regset.AMD64PtraceFpRegs); err != nil {
return err
}
}
xsaveheader := xstateargs[_XSAVE_HEADER_START : _XSAVE_HEADER_START+_XSAVE_HEADER_LEN]
xstate_bv := binary.LittleEndian.Uint64(xsaveheader[0:8])
xcomp_bv := binary.LittleEndian.Uint64(xsaveheader[8:16])
if xcomp_bv&(1<<63) != 0 {
// compact format not supported
return nil
}
if xstate_bv&(1<<2) == 0 {
// AVX state not present
return nil
}
avxstate := xstateargs[_XSAVE_EXTENDED_REGION_START:]
regset.AvxState = true
copy(regset.YmmSpace[:], avxstate[:len(regset.YmmSpace)])
return nil
}