refactor(cmd): re-enter child modes via environment instead of hidden flags
Assisted-by: GLM 5.3 Flash
This commit is contained in:
+24
-9
@@ -24,15 +24,30 @@ function in a traced subprocess (ptrace), then provides a REPL for
|
|||||||
single-stepping, breakpoints, register and memory inspection.
|
single-stepping, breakpoints, register and memory inspection.
|
||||||
|
|
||||||
REPL commands:
|
REPL commands:
|
||||||
break <label|addr> set a breakpoint at a label or absolute address
|
break <label|addr> [if <reg> <op> <val>]
|
||||||
step [n] single-step n instructions (default 1)
|
set a breakpoint, optionally conditional on a
|
||||||
continue run until next breakpoint or exit
|
register comparison (reg-reg or reg-immediate)
|
||||||
regs print general-purpose registers
|
delete <label|addr> remove a breakpoint
|
||||||
|
info break list all breakpoints
|
||||||
|
step [n], s single-step n instructions (default 1)
|
||||||
|
next, n step over a CALL
|
||||||
|
finish, fin run until the function returns
|
||||||
|
continue, c run until a breakpoint, watchpoint or exit
|
||||||
|
disas [n], u disassemble n instructions at PC
|
||||||
|
regs print general-purpose and vector registers
|
||||||
|
where show source line and nearest label at PC
|
||||||
|
stack show stack near RSP (return address + ABI0 args)
|
||||||
|
bt, backtrace backtrace (current frame + return address)
|
||||||
x [addr] [len] hex-dump memory (default: current PC, 64 bytes)
|
x [addr] [len] hex-dump memory (default: current PC, 64 bytes)
|
||||||
labels list function labels and offsets
|
w <addr> <val...> write bytes to memory
|
||||||
quit kill the debuggee and exit
|
set <reg> <value> set a register
|
||||||
|
watch <addr> [r|w] [size]
|
||||||
|
set a hardware watchpoint (write by default)
|
||||||
|
unwatch [<slot>] clear one watchpoint, or all without an argument
|
||||||
|
labels, l list function labels and offsets
|
||||||
|
help, h, ? show command help
|
||||||
|
quit, q kill the debuggee and exit
|
||||||
`)
|
`)
|
||||||
target := fs.Bool("target", false, "") // hidden: debuggee subprocess mode
|
|
||||||
funcName := fs.String("func", "", "function to debug")
|
funcName := fs.String("func", "", "function to debug")
|
||||||
argsFile := fs.String("args", "", "file containing the ABI0 argument block")
|
argsFile := fs.String("args", "", "file containing the ABI0 argument block")
|
||||||
bufSpec := fs.String("buf", "", "buffer specification: name:size:pattern[,name:size:pattern...] where pattern is zero, ones, seq, or hex")
|
bufSpec := fs.String("buf", "", "buffer specification: name:size:pattern[,name:size:pattern...] where pattern is zero, ones, seq, or hex")
|
||||||
@@ -42,10 +57,10 @@ REPL commands:
|
|||||||
fs.Parse(args)
|
fs.Parse(args)
|
||||||
|
|
||||||
// --- Debuggee mode (internal, spawned by the debugger) ---
|
// --- Debuggee mode (internal, spawned by the debugger) ---
|
||||||
if *target {
|
if os.Getenv("GASM_DEBUG_TARGET") != "" {
|
||||||
tmpDir := os.Getenv("GASM_DEBUG_TMP")
|
tmpDir := os.Getenv("GASM_DEBUG_TMP")
|
||||||
if tmpDir == "" || fs.NArg() < 1 || *funcName == "" || *argsFile == "" {
|
if tmpDir == "" || fs.NArg() < 1 || *funcName == "" || *argsFile == "" {
|
||||||
fmt.Fprintln(os.Stderr, "gasm debug --target: internal mode")
|
fmt.Fprintln(os.Stderr, "gasm debug: internal debuggee mode")
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
if err := debug.RunTarget(fs.Arg(0), *funcName, *argsFile, tmpDir); err != nil {
|
if err := debug.RunTarget(fs.Arg(0), *funcName, *argsFile, tmpDir); err != nil {
|
||||||
|
|||||||
+20
-15
@@ -1054,8 +1054,6 @@ decoders) that crash on random input but should succeed on valid data.
|
|||||||
groundTruth := set.Bool("ground-truth", false, "compare machine code byte-for-byte against go tool asm")
|
groundTruth := set.Bool("ground-truth", false, "compare machine code byte-for-byte against go tool asm")
|
||||||
fuzz := set.Bool("fuzz", false, "differential fuzz: JIT both gasm and go-tool-asm versions, compare outputs")
|
fuzz := set.Bool("fuzz", false, "differential fuzz: JIT both gasm and go-tool-asm versions, compare outputs")
|
||||||
fuzzN := set.Int("n", 1000, "number of fuzz iterations per function")
|
fuzzN := set.Int("n", 1000, "number of fuzz iterations per function")
|
||||||
fuzzOne := set.String("fuzz-one", "", "") // hidden: fuzz a single function (subprocess mode)
|
|
||||||
sweepOne := set.String("sweep-one", "", "") // hidden: smoke/abi a single function (subprocess mode)
|
|
||||||
call := set.String("call", "", "call a single function with -buf instead of the sweeps")
|
call := set.String("call", "", "call a single function with -buf instead of the sweeps")
|
||||||
bufSpec := set.String("buf", "", "buffer spec for -call: name:size:pattern[,name:size:pattern] (zero, ones, seq, or hex)")
|
bufSpec := set.String("buf", "", "buffer spec for -call: name:size:pattern[,name:size:pattern] (zero, ones, seq, or hex)")
|
||||||
scalarSpec := set.String("args", "", "scalar args for -call: name=value[,name=value] (decimal or 0x hex)")
|
scalarSpec := set.String("args", "", "scalar args for -call: name=value[,name=value] (decimal or 0x hex)")
|
||||||
@@ -1100,8 +1098,11 @@ decoders) that crash on random input but should succeed on valid data.
|
|||||||
return cmdVerifyCall(k, path, *call, *bufSpec, *scalarSpec, *repeat)
|
return cmdVerifyCall(k, path, *call, *bufSpec, *scalarSpec, *repeat)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subprocess mode: fuzz a single function and exit.
|
// Subprocess mode: fuzz a single function and exit. The parent selects
|
||||||
if *fuzzOne != "" {
|
// the function through the environment, so no internal flag leaks into
|
||||||
|
// the -h output.
|
||||||
|
fuzzOne := os.Getenv("GASM_VERIFY_FUZZ_ONE")
|
||||||
|
if fuzzOne != "" {
|
||||||
gt, err := verify.GroundTruth(path)
|
gt, err := verify.GroundTruth(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "gasm verify: %v\n", err)
|
fmt.Fprintf(os.Stderr, "gasm verify: %v\n", err)
|
||||||
@@ -1113,17 +1114,17 @@ decoders) that crash on random input but should succeed on valid data.
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
sigs := verify.ExtractSignatures(src)
|
sigs := verify.ExtractSignatures(src)
|
||||||
sig, ok := sigs[*fuzzOne]
|
sig, ok := sigs[fuzzOne]
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Printf("%s: no signature\n", *fuzzOne)
|
fmt.Printf("%s: no signature\n", fuzzOne)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
goCode, ok := gt[*fuzzOne]
|
goCode, ok := gt[fuzzOne]
|
||||||
if !ok {
|
if !ok {
|
||||||
fmt.Printf("%s: not in go tool asm\n", *fuzzOne)
|
fmt.Printf("%s: not in go tool asm\n", fuzzOne)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
res := k.FuzzFunc(*fuzzOne, sig, goCode, *fuzzN, 42)
|
res := k.FuzzFunc(fuzzOne, sig, goCode, *fuzzN, 42)
|
||||||
fmt.Printf("%s\n", res)
|
fmt.Printf("%s\n", res)
|
||||||
if !res.OK() {
|
if !res.OK() {
|
||||||
return 1
|
return 1
|
||||||
@@ -1134,13 +1135,15 @@ decoders) that crash on random input but should succeed on valid data.
|
|||||||
// Subprocess mode: run the smoke/abi checks for a single function and
|
// Subprocess mode: run the smoke/abi checks for a single function and
|
||||||
// exit with the accumulated status. The parent interprets a clean exit
|
// exit with the accumulated status. The parent interprets a clean exit
|
||||||
// as success, a non-zero exit as failure and death-by-signal as a crash.
|
// as success, a non-zero exit as failure and death-by-signal as a crash.
|
||||||
if *sweepOne != "" {
|
// Like the fuzz mode, the parent selects the function through the
|
||||||
fl, err := k.Func(*sweepOne)
|
// environment instead of an internal flag.
|
||||||
|
if sweepOne := os.Getenv("GASM_VERIFY_SWEEP_ONE"); sweepOne != "" {
|
||||||
|
fl, err := k.Func(sweepOne)
|
||||||
if err != nil || !fl.NoSplit {
|
if err != nil || !fl.NoSplit {
|
||||||
fmt.Fprintf(os.Stderr, "gasm verify: %s: %v\n", *sweepOne, err)
|
fmt.Fprintf(os.Stderr, "gasm verify: %s: %v\n", sweepOne, err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
msgs, failed := runSweepChecks(k, path, *sweepOne, fl, *smoke, *abi, *abiN)
|
msgs, failed := runSweepChecks(k, path, sweepOne, fl, *smoke, *abi, *abiN)
|
||||||
for _, m := range msgs {
|
for _, m := range msgs {
|
||||||
fmt.Println(m)
|
fmt.Println(m)
|
||||||
}
|
}
|
||||||
@@ -1324,7 +1327,8 @@ func fuzzInSubprocess(path, funcName string, n int) string {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Sprintf("%s: cannot find self: %v", funcName, err)
|
return fmt.Sprintf("%s: cannot find self: %v", funcName, err)
|
||||||
}
|
}
|
||||||
cmd := exec.Command(self, "verify", "--fuzz-one="+funcName, "-n", strconv.Itoa(n), path)
|
cmd := exec.Command(self, "verify", "-n", strconv.Itoa(n), path)
|
||||||
|
cmd.Env = append(os.Environ(), "GASM_VERIFY_FUZZ_ONE="+funcName)
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Check if the child was killed by a signal.
|
// Check if the child was killed by a signal.
|
||||||
@@ -1363,7 +1367,7 @@ func sweepInSubprocess(path, funcName string, smoke, abi bool, abiN int) (string
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Sprintf(" smoke/abi: FAIL — cannot find self: %v", err), true
|
return fmt.Sprintf(" smoke/abi: FAIL — cannot find self: %v", err), true
|
||||||
}
|
}
|
||||||
args := []string{"verify", "--sweep-one=" + funcName}
|
args := []string{"verify"}
|
||||||
if smoke {
|
if smoke {
|
||||||
args = append(args, "-smoke")
|
args = append(args, "-smoke")
|
||||||
}
|
}
|
||||||
@@ -1372,6 +1376,7 @@ func sweepInSubprocess(path, funcName string, smoke, abi bool, abiN int) (string
|
|||||||
}
|
}
|
||||||
args = append(args, path)
|
args = append(args, path)
|
||||||
cmd := exec.Command(self, args...)
|
cmd := exec.Command(self, args...)
|
||||||
|
cmd.Env = append(os.Environ(), "GASM_VERIFY_SWEEP_ONE="+funcName)
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ func LaunchWithBuffers(gasmBin, asmPath, funcName string, args []byte, bufSpec s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command(self, "debug", "--target", "--func", funcName, "--args", argsFile, asmPath)
|
cmd := exec.Command(self, "debug", "--func", funcName, "--args", argsFile, asmPath)
|
||||||
cmd.Env = append(os.Environ(), "GASM_DEBUG_TMP="+tmpDir)
|
cmd.Env = append(os.Environ(), "GASM_DEBUG_TARGET=1", "GASM_DEBUG_TMP="+tmpDir)
|
||||||
cmd.Stdout = nil
|
cmd.Stdout = nil
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||||
|
|||||||
Reference in New Issue
Block a user