2016-02-06 06:00:48 +00:00
|
|
|
package proc
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// AsmInstruction represents one assembly instruction.
|
2016-02-06 06:00:48 +00:00
|
|
|
type AsmInstruction struct {
|
|
|
|
Loc Location
|
|
|
|
DestLoc *Location
|
|
|
|
Bytes []byte
|
|
|
|
Breakpoint bool
|
|
|
|
AtPC bool
|
2018-08-31 18:08:18 +00:00
|
|
|
Inst *archInst
|
2016-02-06 06:00:48 +00:00
|
|
|
}
|
|
|
|
|
2018-08-31 18:08:18 +00:00
|
|
|
// AssemblyFlavour is the assembly syntax to display.
|
2016-02-06 06:00:48 +00:00
|
|
|
type AssemblyFlavour int
|
|
|
|
|
|
|
|
const (
|
2018-08-31 18:08:18 +00:00
|
|
|
// GNUFlavour will display GNU assembly syntax.
|
2016-02-06 06:00:48 +00:00
|
|
|
GNUFlavour = AssemblyFlavour(iota)
|
2018-08-31 18:08:18 +00:00
|
|
|
// IntelFlavour will display Intel assembly syntax.
|
2016-02-06 06:00:48 +00:00
|
|
|
IntelFlavour
|
2018-08-31 18:08:18 +00:00
|
|
|
// GoFlavour will display Go assembly syntax.
|
2017-10-26 11:37:19 +00:00
|
|
|
GoFlavour
|
2016-02-06 06:00:48 +00:00
|
|
|
)
|
|
|
|
|
2019-08-08 18:54:56 +00:00
|
|
|
// Disassemble disassembles target memory between startAddr and endAddr, marking
|
2017-02-15 13:41:03 +00:00
|
|
|
// the current instruction being executed in goroutine g.
|
2019-08-08 18:54:56 +00:00
|
|
|
// If currentGoroutine is set and thread is stopped at a CALL instruction Disassemble
|
|
|
|
// will evaluate the argument of the CALL instruction using the thread's registers.
|
|
|
|
// Be aware that the Bytes field of each returned instruction is a slice of a larger array of size startAddr - endAddr.
|
|
|
|
func Disassemble(mem MemoryReadWriter, regs Registers, breakpoints *BreakpointMap, bi *BinaryInfo, startAddr, endAddr uint64) ([]AsmInstruction, error) {
|
|
|
|
return disassemble(mem, regs, breakpoints, bi, startAddr, endAddr, false)
|
2017-04-13 23:19:57 +00:00
|
|
|
}
|
|
|
|
|
2019-08-08 18:54:56 +00:00
|
|
|
func disassemble(memrw MemoryReadWriter, regs Registers, breakpoints *BreakpointMap, bi *BinaryInfo, startAddr, endAddr uint64, singleInstr bool) ([]AsmInstruction, error) {
|
2019-10-25 13:22:33 +00:00
|
|
|
minInstructionLength := bi.Arch.MinInstructionLength()
|
2019-08-08 18:54:56 +00:00
|
|
|
mem := make([]byte, int(endAddr-startAddr))
|
|
|
|
_, err := memrw.ReadMemory(mem, uintptr(startAddr))
|
2016-02-06 06:00:48 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-10-25 13:22:33 +00:00
|
|
|
r := make([]AsmInstruction, 0, len(mem)/int(maxInstructionLength))
|
2019-08-08 18:54:56 +00:00
|
|
|
pc := startAddr
|
2016-02-06 06:00:48 +00:00
|
|
|
|
|
|
|
var curpc uint64
|
2017-04-13 23:19:57 +00:00
|
|
|
if regs != nil {
|
|
|
|
curpc = regs.PC()
|
2016-02-06 06:00:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for len(mem) > 0 {
|
2017-09-24 13:00:55 +00:00
|
|
|
bp, atbp := breakpoints.M[pc]
|
2016-02-06 06:00:48 +00:00
|
|
|
if atbp {
|
|
|
|
for i := range bp.OriginalData {
|
|
|
|
mem[i] = bp.OriginalData[i]
|
|
|
|
}
|
|
|
|
}
|
2017-04-13 23:19:57 +00:00
|
|
|
file, line, fn := bi.PCToLine(pc)
|
2016-02-06 06:00:48 +00:00
|
|
|
loc := Location{PC: pc, File: file, Line: line, Fn: fn}
|
|
|
|
inst, err := asmDecode(mem, pc)
|
|
|
|
if err == nil {
|
2017-04-13 23:19:57 +00:00
|
|
|
atpc := (regs != nil) && (curpc == pc)
|
2019-10-25 13:22:33 +00:00
|
|
|
destloc := resolveCallArg(inst, pc, atpc, regs, memrw, bi)
|
|
|
|
r = append(r, AsmInstruction{Loc: loc, DestLoc: destloc, Bytes: mem[:inst.Size()], Breakpoint: atbp, AtPC: atpc, Inst: inst})
|
2016-02-06 06:00:48 +00:00
|
|
|
|
|
|
|
pc += uint64(inst.Size())
|
|
|
|
mem = mem[inst.Size():]
|
|
|
|
} else {
|
2019-10-25 13:22:33 +00:00
|
|
|
r = append(r, AsmInstruction{Loc: loc, Bytes: mem[:minInstructionLength], Breakpoint: atbp, Inst: nil})
|
|
|
|
pc += uint64(minInstructionLength)
|
|
|
|
mem = mem[minInstructionLength:]
|
2016-02-06 06:00:48 +00:00
|
|
|
}
|
2017-11-06 17:34:59 +00:00
|
|
|
if singleInstr {
|
|
|
|
break
|
|
|
|
}
|
2016-02-06 06:00:48 +00:00
|
|
|
}
|
|
|
|
return r, nil
|
|
|
|
}
|