mirror of
				https://github.com/go-delve/delve.git
				synced 2025-11-01 03:42:59 +08:00 
			
		
		
		
	Further isolate Linux specific code
This commit is contained in:
		| @ -7,12 +7,25 @@ import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"sync" | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/derekparker/delve/dwarf/frame" | ||||
| 	"github.com/derekparker/delve/vendor/dwarf" | ||||
| ) | ||||
|  | ||||
| // Struct representing a debugged process. Holds onto pid, register values, | ||||
| // process struct and process state. | ||||
| type DebuggedProcess struct { | ||||
| 	Pid           int | ||||
| 	Process       *os.Process | ||||
| 	Dwarf         *dwarf.Data | ||||
| 	GoSymTable    *gosym.Table | ||||
| 	FrameEntries  *frame.FrameDescriptionEntries | ||||
| 	BreakPoints   map[uint64]*BreakPoint | ||||
| 	Threads       map[int]*ThreadContext | ||||
| 	CurrentThread *ThreadContext | ||||
| } | ||||
|  | ||||
| // Represents a single breakpoint. Stores information on the break | ||||
| // point including the byte of data that originally was stored at that | ||||
| // address. | ||||
| @ -179,31 +192,6 @@ func (dbp *DebuggedProcess) PrintThreadInfo() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Finds the executable from /proc/<pid>/exe and then | ||||
| // uses that to parse the following information: | ||||
| // * Dwarf .debug_frame section | ||||
| // * Dwarf .debug_line section | ||||
| // * Go symbol table. | ||||
| func (dbp *DebuggedProcess) LoadInformation() error { | ||||
| 	var ( | ||||
| 		wg  sync.WaitGroup | ||||
| 		err error | ||||
| 	) | ||||
|  | ||||
| 	err = dbp.findExecutable() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	wg.Add(2) | ||||
| 	go dbp.parseDebugFrame(&wg) | ||||
| 	go dbp.obtainGoSymbols(&wg) | ||||
|  | ||||
| 	wg.Wait() | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Steps through process. | ||||
| func (dbp *DebuggedProcess) Step() (err error) { | ||||
| 	var ( | ||||
| @ -310,53 +298,6 @@ func (dbp *DebuggedProcess) EvalSymbol(name string) (*Variable, error) { | ||||
| 	return dbp.CurrentThread.EvalSymbol(name) | ||||
| } | ||||
|  | ||||
| func (dbp *DebuggedProcess) parseDebugFrame(wg *sync.WaitGroup) { | ||||
| 	defer wg.Done() | ||||
|  | ||||
| 	debugFrame, err := dbp.Executable.Section(".debug_frame").Data() | ||||
| 	if err != nil { | ||||
| 		fmt.Println("could not get .debug_frame section", err) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
|  | ||||
| 	dbp.FrameEntries = frame.Parse(debugFrame) | ||||
| } | ||||
|  | ||||
| func (dbp *DebuggedProcess) obtainGoSymbols(wg *sync.WaitGroup) { | ||||
| 	defer wg.Done() | ||||
|  | ||||
| 	var ( | ||||
| 		symdat  []byte | ||||
| 		pclndat []byte | ||||
| 		err     error | ||||
| 	) | ||||
|  | ||||
| 	if sec := dbp.Executable.Section(".gosymtab"); sec != nil { | ||||
| 		symdat, err = sec.Data() | ||||
| 		if err != nil { | ||||
| 			fmt.Println("could not get .gosymtab section", err) | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if sec := dbp.Executable.Section(".gopclntab"); sec != nil { | ||||
| 		pclndat, err = sec.Data() | ||||
| 		if err != nil { | ||||
| 			fmt.Println("could not get .gopclntab section", err) | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	pcln := gosym.NewLineTable(pclndat, dbp.Executable.Section(".text").Addr) | ||||
| 	tab, err := gosym.NewTable(symdat, pcln) | ||||
| 	if err != nil { | ||||
| 		fmt.Println("could not get initialize line table", err) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
|  | ||||
| 	dbp.GoSymTable = tab | ||||
| } | ||||
|  | ||||
| type ProcessExitedError struct { | ||||
| 	pid int | ||||
| } | ||||
|  | ||||
| @ -4,25 +4,13 @@ import ( | ||||
| 	"debug/gosym" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"sync" | ||||
| 	"syscall" | ||||
|  | ||||
| 	"github.com/derekparker/delve/dwarf/frame" | ||||
| 	"github.com/derekparker/delve/vendor/elf" | ||||
| ) | ||||
|  | ||||
| // Struct representing a debugged process. Holds onto pid, register values, | ||||
| // process struct and process state. | ||||
| type DebuggedProcess struct { | ||||
| 	Pid           int | ||||
| 	Process       *os.Process | ||||
| 	Executable    *elf.File | ||||
| 	GoSymTable    *gosym.Table | ||||
| 	FrameEntries  *frame.FrameDescriptionEntries | ||||
| 	BreakPoints   map[uint64]*BreakPoint | ||||
| 	Threads       map[int]*ThreadContext | ||||
| 	CurrentThread *ThreadContext | ||||
| } | ||||
|  | ||||
| func (dbp *DebuggedProcess) addThread(tid int) (*ThreadContext, error) { | ||||
| 	err := syscall.PtraceSetOptions(tid, syscall.PTRACE_O_TRACECLONE) | ||||
| 	if err == syscall.ESRCH { | ||||
| @ -60,20 +48,97 @@ func parseProcessStatus(pid int) (*ProcessStatus, error) { | ||||
| 	return &ps, nil | ||||
| } | ||||
|  | ||||
| func (dbp *DebuggedProcess) findExecutable() error { | ||||
| // Finds the executable from /proc/<pid>/exe and then | ||||
| // uses that to parse the following information: | ||||
| // * Dwarf .debug_frame section | ||||
| // * Dwarf .debug_line section | ||||
| // * Go symbol table. | ||||
| func (dbp *DebuggedProcess) LoadInformation() error { | ||||
| 	var ( | ||||
| 		wg  sync.WaitGroup | ||||
| 		exe *elf.File | ||||
| 		err error | ||||
| 	) | ||||
|  | ||||
| 	exe, err = dbp.findExecutable() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	wg.Add(2) | ||||
| 	go dbp.parseDebugFrame(exe, &wg) | ||||
| 	go dbp.obtainGoSymbols(exe, &wg) | ||||
|  | ||||
| 	wg.Wait() | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (dbp *DebuggedProcess) findExecutable() (*elf.File, error) { | ||||
| 	procpath := fmt.Sprintf("/proc/%d/exe", dbp.Pid) | ||||
|  | ||||
| 	f, err := os.OpenFile(procpath, 0, os.ModePerm) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	elffile, err := elf.NewFile(f) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	dbp.Executable = elffile | ||||
| 	data, err := elffile.DWARF() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	dbp.Dwarf = data | ||||
|  | ||||
| 	return nil | ||||
| 	return elffile, nil | ||||
| } | ||||
|  | ||||
| func (dbp *DebuggedProcess) parseDebugFrame(exe *elf.File, wg *sync.WaitGroup) { | ||||
| 	defer wg.Done() | ||||
|  | ||||
| 	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) | ||||
| } | ||||
|  | ||||
| func (dbp *DebuggedProcess) obtainGoSymbols(exe *elf.File, wg *sync.WaitGroup) { | ||||
| 	defer wg.Done() | ||||
|  | ||||
| 	var ( | ||||
| 		symdat  []byte | ||||
| 		pclndat []byte | ||||
| 		err     error | ||||
| 	) | ||||
|  | ||||
| 	if sec := exe.Section(".gosymtab"); sec != nil { | ||||
| 		symdat, err = sec.Data() | ||||
| 		if err != nil { | ||||
| 			fmt.Println("could not get .gosymtab section", err) | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if sec := exe.Section(".gopclntab"); sec != nil { | ||||
| 		pclndat, err = sec.Data() | ||||
| 		if err != nil { | ||||
| 			fmt.Println("could not get .gopclntab section", err) | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	pcln := gosym.NewLineTable(pclndat, exe.Section(".text").Addr) | ||||
| 	tab, err := gosym.NewTable(symdat, pcln) | ||||
| 	if err != nil { | ||||
| 		fmt.Println("could not get initialize line table", err) | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
|  | ||||
| 	dbp.GoSymTable = tab | ||||
| } | ||||
|  | ||||
| @ -29,11 +29,7 @@ type M struct { | ||||
| // Parses and returns select info on the internal M | ||||
| // data structures used by the Go scheduler. | ||||
| func (thread *ThreadContext) AllM() ([]*M, error) { | ||||
| 	data, err := thread.Process.Executable.DWARF() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	reader := data.Reader() | ||||
| 	reader := thread.Process.Dwarf.Reader() | ||||
|  | ||||
| 	allmaddr, err := parseAllMPtr(thread.Process, reader) | ||||
| 	if err != nil { | ||||
| @ -186,11 +182,7 @@ func parseAllMPtr(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) { | ||||
| } | ||||
|  | ||||
| func (dbp *DebuggedProcess) PrintGoroutinesInfo() error { | ||||
| 	data, err := dbp.Executable.DWARF() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	reader := data.Reader() | ||||
| 	reader := dbp.Dwarf.Reader() | ||||
|  | ||||
| 	allglen, err := allglenval(dbp, reader) | ||||
| 	if err != nil { | ||||
| @ -309,10 +301,7 @@ func offsetFor(dbp *DebuggedProcess, name string, reader *dwarf.Reader, parentin | ||||
|  | ||||
| // Returns the value of the named symbol. | ||||
| func (thread *ThreadContext) EvalSymbol(name string) (*Variable, error) { | ||||
| 	data, err := thread.Process.Executable.DWARF() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	data := thread.Process.Dwarf | ||||
|  | ||||
| 	pc, err := thread.CurrentPC() | ||||
| 	if err != nil { | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Derek Parker
					Derek Parker