提交 b1640238 编写于 作者: A aarzilli 提交者: Derek Parker

dwarf/frame: detecting dwarf section endianness

上级 1bfae45b
package frame
import (
"encoding/binary"
"fmt"
"sort"
)
......@@ -25,6 +26,7 @@ type FrameDescriptionEntry struct {
CIE *CommonInformationEntry
Instructions []byte
begin, end uint64
order binary.ByteOrder
}
// Returns whether or not the given address is within the
......
package frame
import (
"encoding/binary"
"io/ioutil"
"os"
"testing"
......@@ -39,7 +40,7 @@ func BenchmarkFDEForPC(b *testing.B) {
if err != nil {
b.Fatal(err)
}
fdes := Parse(data)
fdes := Parse(data, binary.BigEndian)
for i := 0; i < b.N; i++ {
// bench worst case, exhaustive search
......
......@@ -23,7 +23,7 @@ type parseContext struct {
// Parse takes in data (a byte slice) and returns a slice of
// commonInformationEntry structures. Each commonInformationEntry
// has a slice of frameDescriptionEntry structures.
func Parse(data []byte) FrameDescriptionEntries {
func Parse(data []byte, order binary.ByteOrder) FrameDescriptionEntries {
var (
buf = bytes.NewBuffer(data)
pctx = &parseContext{buf: buf, entries: NewFrameIndex()}
......@@ -33,6 +33,10 @@ func Parse(data []byte) FrameDescriptionEntries {
fn = fn(pctx)
}
for i := range pctx.entries {
pctx.entries[i].order = order
}
return pctx.entries
}
......@@ -100,3 +104,22 @@ func parseCIE(ctx *parseContext) parsefunc {
return parselength
}
// DwarfEndian determines the endianness of the DWARF by using the version number field in the debug_info section
// Trick borrowed from "debug/dwarf".New()
func DwarfEndian(infoSec []byte) binary.ByteOrder {
if len(infoSec) < 6 {
return binary.BigEndian
}
x, y := infoSec[4], infoSec[5]
switch {
case x == 0 && y == 0:
return binary.BigEndian
case x == 0:
return binary.BigEndian
case y == 0:
return binary.LittleEndian
default:
return binary.BigEndian
}
}
package frame_test
import (
"encoding/binary"
"io/ioutil"
"os"
"testing"
......@@ -24,6 +25,6 @@ func BenchmarkParse(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
frame.Parse(data)
frame.Parse(data, binary.BigEndian)
}
}
......@@ -24,6 +24,7 @@ type DWRule struct {
type FrameContext struct {
loc uint64
order binary.ByteOrder
address uint64
cfa CurrentFrameAddress
regs map[uint64]DWRule
......@@ -138,6 +139,7 @@ func executeCIEInstructions(cie *CommonInformationEntry) *FrameContext {
// Unwind the stack to find the return address register.
func executeDwarfProgramUntilPC(fde *FrameDescriptionEntry, pc uint64) *FrameContext {
frame := executeCIEInstructions(fde.CIE)
frame.order = fde.order
frame.loc = fde.Begin()
frame.address = pc
fdeInstructions := make([]byte, len(fde.Instructions))
......@@ -237,14 +239,14 @@ func advanceloc1(frame *FrameContext) {
func advanceloc2(frame *FrameContext) {
var delta uint16
binary.Read(frame.buf, binary.BigEndian, &delta)
binary.Read(frame.buf, frame.order, &delta)
frame.loc += uint64(delta) * frame.codeAlignment
}
func advanceloc4(frame *FrameContext) {
var delta uint32
binary.Read(frame.buf, binary.BigEndian, &delta)
binary.Read(frame.buf, frame.order, &delta)
frame.loc += uint64(delta) * frame.codeAlignment
}
......@@ -280,7 +282,7 @@ func restore(frame *FrameContext) {
func setloc(frame *FrameContext) {
var loc uint64
binary.Read(frame.buf, binary.BigEndian, &loc)
binary.Read(frame.buf, frame.order, &loc)
frame.loc = loc
}
......
......@@ -193,13 +193,21 @@ func (dbp *Process) addThread(port int, attach bool) (*Thread, error) {
func (dbp *Process) parseDebugFrame(exe *macho.File, wg *sync.WaitGroup) {
defer wg.Done()
if sec := exe.Section("__debug_frame"); sec != nil {
debugFrameSec := exe.Section("__debug_frame")
debugInfoSec := exe.Section("__debug_info")
if debugFrameSec != nil && debugInfoSec != nil {
debugFrame, err := exe.Section("__debug_frame").Data()
if err != nil {
fmt.Println("could not get __debug_frame section", err)
os.Exit(1)
}
dbp.frameEntries = frame.Parse(debugFrame)
dat, err := debugInfoSec.Data()
if err != nil {
fmt.Println("could not get .debug_info section", err)
os.Exit(1)
}
dbp.frameEntries = frame.Parse(debugFrame, frame.DwarfEndian(dat))
} else {
fmt.Println("could not find __debug_frame section in binary")
os.Exit(1)
......
......@@ -179,13 +179,21 @@ func (dbp *Process) findExecutable(path string) (*elf.File, error) {
func (dbp *Process) parseDebugFrame(exe *elf.File, wg *sync.WaitGroup) {
defer wg.Done()
if sec := exe.Section(".debug_frame"); sec != nil {
debugFrameSec := exe.Section(".debug_frame")
debugInfoSec := exe.Section(".debug_info")
if debugFrameSec != nil && debugInfoSec != nil {
debugFrame, err := exe.Section(".debug_frame").Data()
if err != nil {
fmt.Println("could not get .debug_frame section", err)
os.Exit(1)
}
dbp.frameEntries = frame.Parse(debugFrame)
dat, err := debugInfoSec.Data()
if err != nil {
fmt.Println("could not get .debug_info section", err)
os.Exit(1)
}
dbp.frameEntries = frame.Parse(debugFrame, frame.DwarfEndian(dat))
} else {
fmt.Println("could not find .debug_frame section in binary")
os.Exit(1)
......
......@@ -158,16 +158,24 @@ func (dbp *Process) addThread(hThread sys.Handle, threadID int, attach bool) (*T
func (dbp *Process) parseDebugFrame(exe *pe.File, wg *sync.WaitGroup) {
defer wg.Done()
if sec := exe.Section(".debug_frame"); sec != nil {
debugFrame, err := sec.Data()
if err != nil && uint32(len(debugFrame)) < sec.Size {
debugFrameSec := exe.Section(".debug_frame")
debugInfoSec := exe.Section(".debug_info")
if debugFrameSec != nil && debugInfoSec != nil {
debugFrame, err := debugFrameSec.Data()
if err != nil && uint32(len(debugFrame)) < debugFrameSec.Size {
fmt.Println("could not get .debug_frame section", err)
os.Exit(1)
}
if 0 < sec.VirtualSize && sec.VirtualSize < sec.Size {
debugFrame = debugFrame[:sec.VirtualSize]
if 0 < debugFrameSec.VirtualSize && debugFrameSec.VirtualSize < debugFrameSec.Size {
debugFrame = debugFrame[:debugFrameSec.VirtualSize]
}
dat, err := debugInfoSec.Data()
if err != nil {
fmt.Println("could not get .debug_info section", err)
os.Exit(1)
}
dbp.frameEntries = frame.Parse(debugFrame)
dbp.frameEntries = frame.Parse(debugFrame, frame.DwarfEndian(dat))
} else {
fmt.Println("could not find .debug_frame section in binary")
os.Exit(1)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册