feat(debug): add named buffer allocation with pattern filling
This commit is contained in:
@@ -33,9 +33,17 @@ type Session struct {
|
||||
// JIT code, calls PTRACE_TRACEME and raises SIGSTOP; Launch waits for
|
||||
// that initial stop and returns a ready Session.
|
||||
func Launch(gasmBin, asmPath, funcName string, args []byte) (*Session, error) {
|
||||
sess, _, err := LaunchWithBuffers(gasmBin, asmPath, funcName, args, "")
|
||||
return sess, err
|
||||
}
|
||||
|
||||
// LaunchWithBuffers is like Launch but also allocates buffers in the debuggee
|
||||
// based on the buffer specification. Returns the Session and the buffer
|
||||
// addresses (in the order they appear in the spec).
|
||||
func LaunchWithBuffers(gasmBin, asmPath, funcName string, args []byte, bufSpec string) (*Session, []uint64, error) {
|
||||
self, err := os.Executable()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("debug: cannot find gasm binary: %w", err)
|
||||
return nil, nil, fmt.Errorf("debug: cannot find gasm binary: %w", err)
|
||||
}
|
||||
if gasmBin != "" {
|
||||
self = gasmBin
|
||||
@@ -44,12 +52,20 @@ func Launch(gasmBin, asmPath, funcName string, args []byte) (*Session, error) {
|
||||
// Write the arg block to a temp file (the child reads it).
|
||||
tmpDir, err := os.MkdirTemp("", "gasm-debug-*")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("debug: tempdir: %w", err)
|
||||
return nil, nil, fmt.Errorf("debug: tempdir: %w", err)
|
||||
}
|
||||
argsFile := filepath.Join(tmpDir, "args.bin")
|
||||
if err := os.WriteFile(argsFile, args, 0o644); err != nil {
|
||||
os.RemoveAll(tmpDir)
|
||||
return nil, fmt.Errorf("debug: write args: %w", err)
|
||||
return nil, nil, fmt.Errorf("debug: write args: %w", err)
|
||||
}
|
||||
|
||||
// Write the buffer spec if present.
|
||||
if bufSpec != "" {
|
||||
if err := os.WriteFile(filepath.Join(tmpDir, "bufspec"), []byte(bufSpec), 0o644); err != nil {
|
||||
os.RemoveAll(tmpDir)
|
||||
return nil, nil, fmt.Errorf("debug: write bufspec: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
cmd := exec.Command(self, "debug", "--target", "--func", funcName, "--args", argsFile, asmPath)
|
||||
@@ -60,7 +76,7 @@ func Launch(gasmBin, asmPath, funcName string, args []byte) (*Session, error) {
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
os.RemoveAll(tmpDir)
|
||||
return nil, fmt.Errorf("debug: start debuggee: %w", err)
|
||||
return nil, nil, fmt.Errorf("debug: start debuggee: %w", err)
|
||||
}
|
||||
|
||||
s := &Session{pid: cmd.Process.Pid, cmd: cmd}
|
||||
@@ -79,8 +95,28 @@ func Launch(gasmBin, asmPath, funcName string, args []byte) (*Session, error) {
|
||||
if _, err := syscall.Wait4(s.pid, &ws, syscall.WUNTRACED, nil); err != nil {
|
||||
cmd.Process.Kill()
|
||||
os.RemoveAll(tmpDir)
|
||||
return nil, fmt.Errorf("debug: wait for debuggee: %w", err)
|
||||
return nil, nil, fmt.Errorf("debug: wait for stop: %w", err)
|
||||
}
|
||||
|
||||
// Wait for the debuggee to reach the function entry point.
|
||||
entryFile := filepath.Join(tmpDir, "entry")
|
||||
for i := 0; i < 500; i++ {
|
||||
if _, err := os.Stat(entryFile); err == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
}
|
||||
|
||||
// Continue the debuggee to the entry point.
|
||||
if err := s.Continue(); err != nil {
|
||||
return nil, nil, fmt.Errorf("debug: continue to entry: %w", err)
|
||||
}
|
||||
|
||||
// Wait for the entry stop.
|
||||
if _, err := syscall.Wait4(s.pid, &ws, syscall.WUNTRACED, nil); err != nil {
|
||||
return nil, nil, fmt.Errorf("debug: wait for entry: %w", err)
|
||||
}
|
||||
|
||||
s.stopped = true
|
||||
|
||||
// Read the code base from /proc/pid/maps (find the RWX mapping).
|
||||
@@ -93,7 +129,21 @@ func Launch(gasmBin, asmPath, funcName string, args []byte) (*Session, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return s, nil
|
||||
// Read buffer addresses if buffers were allocated.
|
||||
var bufAddrs []uint64
|
||||
if bufSpec != "" {
|
||||
addrFile := filepath.Join(tmpDir, "bufaddrs")
|
||||
if data, err := os.ReadFile(addrFile); err == nil {
|
||||
for _, line := range strings.Split(strings.TrimSpace(string(data)), "\n") {
|
||||
var addr uint64
|
||||
if _, err := fmt.Sscanf(line, "%d", &addr); err == nil {
|
||||
bufAddrs = append(bufAddrs, addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return s, bufAddrs, nil
|
||||
}
|
||||
|
||||
// wait waits for the debuggee to stop and returns the wait status.
|
||||
|
||||
Reference in New Issue
Block a user