diff --git a/proctl/arch.go b/proctl/arch.go new file mode 100644 index 00000000..62cdcba9 --- /dev/null +++ b/proctl/arch.go @@ -0,0 +1,33 @@ +package proctl + +type Arch interface { + PtrSize() int + BreakpointInstruction() []byte + BreakpointSize() int +} + +type AMD64 struct { + ptrSize int + breakInstruction []byte + breakInstructionLen int +} + +func AMD64Arch() *AMD64 { + return &AMD64{ + ptrSize: 8, + breakInstruction: []byte{0xCC}, + breakInstructionLen: 1, + } +} + +func (a *AMD64) PtrSize() int { + return a.ptrSize +} + +func (a *AMD64) BreakpointInstruction() []byte { + return a.breakInstruction +} + +func (a *AMD64) BreakpointSize() int { + return a.breakInstructionLen +} diff --git a/proctl/breakpoints.go b/proctl/breakpoints.go index b3ede353..deb6a9fc 100644 --- a/proctl/breakpoints.go +++ b/proctl/breakpoints.go @@ -129,11 +129,11 @@ func (dbp *DebuggedProcess) setBreakpoint(tid int, addr uint64, temp bool) (*Bre } // Fall back to software breakpoint. 0xCC is INT 3 trap interrupt. thread := dbp.Threads[tid] - originalData := make([]byte, 1) + originalData := make([]byte, dbp.arch.BreakpointSize()) if _, err := readMemory(thread, uintptr(addr), originalData); err != nil { return nil, err } - if _, err := writeMemory(thread, uintptr(addr), []byte{0xCC}); err != nil { + if _, err := writeMemory(thread, uintptr(addr), dbp.arch.BreakpointInstruction()); err != nil { return nil, err } dbp.BreakPoints[addr] = dbp.newBreakpoint(fn.Name, f, l, addr, originalData, temp) diff --git a/proctl/proctl.go b/proctl/proctl.go index 656f180e..e53b15db 100644 --- a/proctl/proctl.go +++ b/proctl/proctl.go @@ -7,6 +7,7 @@ import ( "fmt" "os" "path/filepath" + "runtime" "strconv" "strings" "sync" @@ -35,6 +36,7 @@ type DebuggedProcess struct { firstStart bool singleStepping bool os *OSProcessDetails + arch Arch ast *source.Searcher breakpointIDCounter int tempBreakpointIDCounter int @@ -401,11 +403,11 @@ func (dbp *DebuggedProcess) GoroutinesInfo() ([]*G, error) { if err != nil { return nil, err } - faddr, err := dbp.CurrentThread.readMemory(uintptr(allgentryaddr), ptrsize) + faddr, err := dbp.CurrentThread.readMemory(uintptr(allgentryaddr), dbp.arch.PtrSize()) allgptr := binary.LittleEndian.Uint64(faddr) for i := uint64(0); i < allglen; i++ { - g, err := parseG(dbp.CurrentThread, allgptr+(i*uint64(ptrsize)), reader) + g, err := parseG(dbp.CurrentThread, allgptr+(i*uint64(dbp.arch.PtrSize())), reader) if err != nil { return nil, err } @@ -510,6 +512,11 @@ func initializeDebugProcess(dbp *DebuggedProcess, path string, attach bool) (*De return nil, err } + switch runtime.GOARCH { + case "amd64": + dbp.arch = AMD64Arch() + } + return dbp, nil } diff --git a/proctl/threads.go b/proctl/threads.go index 69a4e269..d8f326b2 100644 --- a/proctl/threads.go +++ b/proctl/threads.go @@ -251,7 +251,7 @@ func (thread *ThreadContext) curG() (*G, error) { return err } reader := thread.Process.dwarf.Reader() - g, err = parseG(thread, regs.SP()+uint64(ptrsize), reader) + g, err = parseG(thread, regs.SP()+uint64(thread.Process.arch.PtrSize()), reader) return err }) return g, err diff --git a/proctl/variables.go b/proctl/variables.go index bf107fe8..43e7f487 100644 --- a/proctl/variables.go +++ b/proctl/variables.go @@ -15,8 +15,6 @@ import ( ) const ( - ptrsize uintptr = unsafe.Sizeof(int(1)) // Size of a pointer. - maxVariableRecurse = 1 // How far to recurse when evaluating nested types. maxArrayValues = 64 // Max value for reading large arrays. @@ -79,7 +77,7 @@ func (thread *ThreadContext) AllM() ([]*M, error) { if err != nil { return nil, err } - mptr, err := thread.readMemory(uintptr(allmaddr), ptrsize) + mptr, err := thread.readMemory(uintptr(allmaddr), thread.Process.arch.PtrSize()) if err != nil { return nil, err } @@ -116,7 +114,7 @@ func (thread *ThreadContext) AllM() ([]*M, error) { if err != nil { return nil, err } - curgBytes, err := thread.readMemory(uintptr(curgAddr), ptrsize) + curgBytes, err := thread.readMemory(uintptr(curgAddr), thread.Process.arch.PtrSize()) if err != nil { return nil, fmt.Errorf("could not read curg %#v %s", curgAddr, err) } @@ -127,7 +125,7 @@ func (thread *ThreadContext) AllM() ([]*M, error) { if err != nil { return nil, err } - procidBytes, err := thread.readMemory(uintptr(procidAddr), ptrsize) + procidBytes, err := thread.readMemory(uintptr(procidAddr), thread.Process.arch.PtrSize()) if err != nil { return nil, fmt.Errorf("could not read procid %#v %s", procidAddr, err) } @@ -165,7 +163,7 @@ func (thread *ThreadContext) AllM() ([]*M, error) { if err != nil { return nil, err } - mptr, err = thread.readMemory(uintptr(alllinkAddr), ptrsize) + mptr, err = thread.readMemory(uintptr(alllinkAddr), thread.Process.arch.PtrSize()) if err != nil { return nil, fmt.Errorf("could not read alllink %#v %s", alllinkAddr, err) } @@ -245,7 +243,7 @@ func (ng NoGError) Error() string { } func parseG(thread *ThreadContext, addr uint64, reader *dwarf.Reader) (*G, error) { - gaddrbytes, err := thread.readMemory(uintptr(addr), ptrsize) + gaddrbytes, err := thread.readMemory(uintptr(addr), thread.Process.arch.PtrSize()) if err != nil { return nil, fmt.Errorf("error derefing *G %s", err) } @@ -260,7 +258,7 @@ func parseG(thread *ThreadContext, addr uint64, reader *dwarf.Reader) (*G, error if err != nil { return nil, err } - goidbytes, err := thread.readMemory(uintptr(goidaddr), ptrsize) + goidbytes, err := thread.readMemory(uintptr(goidaddr), thread.Process.arch.PtrSize()) if err != nil { return nil, fmt.Errorf("error reading goid %s", err) } @@ -269,7 +267,7 @@ func parseG(thread *ThreadContext, addr uint64, reader *dwarf.Reader) (*G, error if err != nil { return nil, err } - gopcbytes, err := thread.readMemory(uintptr(gopcaddr), ptrsize) + gopcbytes, err := thread.readMemory(uintptr(gopcaddr), thread.Process.arch.PtrSize()) if err != nil { return nil, fmt.Errorf("error reading gopc %s", err) } @@ -288,13 +286,13 @@ func parseG(thread *ThreadContext, addr uint64, reader *dwarf.Reader) (*G, error return nil, err } - spbytes, err := thread.readMemory(uintptr(schedaddr), ptrsize) + spbytes, err := thread.readMemory(uintptr(schedaddr), thread.Process.arch.PtrSize()) if err != nil { return nil, fmt.Errorf("error reading goroutine SP %s", err) } gosp := binary.LittleEndian.Uint64(spbytes) - pcbytes, err := thread.readMemory(uintptr(schedaddr+uint64(ptrsize)), ptrsize) + pcbytes, err := thread.readMemory(uintptr(schedaddr+uint64(thread.Process.arch.PtrSize())), thread.Process.arch.PtrSize()) if err != nil { return nil, fmt.Errorf("error reading goroutine PC %s", err) } @@ -632,7 +630,7 @@ func (thread *ThreadContext) extractVariableDataAddress(entry *dwarf.Entry, read ptraddress := uintptr(address) - ptr, err := thread.readMemory(ptraddress, ptrsize) + ptr, err := thread.readMemory(ptraddress, thread.Process.arch.PtrSize()) if err != nil { return 0, err } @@ -672,7 +670,7 @@ func (thread *ThreadContext) extractValueInternal(instructions []byte, addr int6 ptraddress := uintptr(addr) switch t := typ.(type) { case *dwarf.PtrType: - ptr, err := thread.readMemory(ptraddress, ptrsize) + ptr, err := thread.readMemory(ptraddress, thread.Process.arch.PtrSize()) if err != nil { return "", err } @@ -747,14 +745,14 @@ func (thread *ThreadContext) readString(addr uintptr) (string, error) { // http://research.swtch.com/godata // read len - val, err := thread.readMemory(addr+ptrsize, ptrsize) + val, err := thread.readMemory(addr+uintptr(thread.Process.arch.PtrSize()), thread.Process.arch.PtrSize()) if err != nil { return "", err } - strlen := uintptr(binary.LittleEndian.Uint64(val)) + strlen := int(binary.LittleEndian.Uint64(val)) // read addr - val, err = thread.readMemory(addr, ptrsize) + val, err = thread.readMemory(addr, thread.Process.arch.PtrSize()) if err != nil { return "", err } @@ -775,7 +773,7 @@ func (thread *ThreadContext) readSlice(addr uintptr, t *dwarf.StructType) (strin for _, f := range t.Field { switch f.Name { case "array": - val, err := thread.readMemory(addr+uintptr(f.ByteOffset), ptrsize) + val, err := thread.readMemory(addr+uintptr(f.ByteOffset), thread.Process.arch.PtrSize()) if err != nil { return "", err } @@ -809,7 +807,7 @@ func (thread *ThreadContext) readSlice(addr uintptr, t *dwarf.StructType) (strin stride := arrayType.Size() if _, ok := arrayType.(*dwarf.PtrType); ok { - stride = int64(ptrsize) + stride = int64(thread.Process.arch.PtrSize()) } vals, err := thread.readArrayValues(arrayAddr, sliceLen, stride, arrayType) if err != nil { @@ -853,7 +851,7 @@ func (thread *ThreadContext) readArrayValues(addr uintptr, count int64, stride i func (thread *ThreadContext) readInt(addr uintptr, size int64) (string, error) { var n int64 - val, err := thread.readMemory(addr, uintptr(size)) + val, err := thread.readMemory(addr, int(size)) if err != nil { return "", err } @@ -875,7 +873,7 @@ func (thread *ThreadContext) readInt(addr uintptr, size int64) (string, error) { func (thread *ThreadContext) readUint(addr uintptr, size int64) (string, error) { var n uint64 - val, err := thread.readMemory(addr, uintptr(size)) + val, err := thread.readMemory(addr, int(size)) if err != nil { return "", err } @@ -895,7 +893,7 @@ func (thread *ThreadContext) readUint(addr uintptr, size int64) (string, error) } func (thread *ThreadContext) readFloat(addr uintptr, size int64) (string, error) { - val, err := thread.readMemory(addr, uintptr(size)) + val, err := thread.readMemory(addr, int(size)) if err != nil { return "", err } @@ -916,7 +914,7 @@ func (thread *ThreadContext) readFloat(addr uintptr, size int64) (string, error) } func (thread *ThreadContext) readBool(addr uintptr) (string, error) { - val, err := thread.readMemory(addr, uintptr(1)) + val, err := thread.readMemory(addr, 1) if err != nil { return "", err } @@ -929,7 +927,7 @@ func (thread *ThreadContext) readBool(addr uintptr) (string, error) { } func (thread *ThreadContext) readFunctionPtr(addr uintptr) (string, error) { - val, err := thread.readMemory(addr, ptrsize) + val, err := thread.readMemory(addr, thread.Process.arch.PtrSize()) if err != nil { return "", err } @@ -940,7 +938,7 @@ func (thread *ThreadContext) readFunctionPtr(addr uintptr) (string, error) { return "nil", nil } - val, err = thread.readMemory(addr, ptrsize) + val, err = thread.readMemory(addr, thread.Process.arch.PtrSize()) if err != nil { return "", err } @@ -961,7 +959,7 @@ func (thread *ThreadContext) readFunctionPtr(addr uintptr) (string, error) { return n, nil } -func (thread *ThreadContext) readMemory(addr uintptr, size uintptr) ([]byte, error) { +func (thread *ThreadContext) readMemory(addr uintptr, size int) ([]byte, error) { if size == 0 { return nil, nil } @@ -1008,9 +1006,3 @@ func (thread *ThreadContext) variablesByTag(tag dwarf.Tag) ([]*Variable, error) return vars, nil } - -// Sets the length of a slice. -func setSliceLength(ptr unsafe.Pointer, l int) { - lptr := (*int)(unsafe.Pointer(uintptr(ptr) + ptrsize)) - *lptr = l -}