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.
|
||||
|
||||
REPL commands:
|
||||
break <label|addr> set a breakpoint at a label or absolute address
|
||||
step [n] single-step n instructions (default 1)
|
||||
continue run until next breakpoint or exit
|
||||
regs print general-purpose registers
|
||||
break <label|addr> [if <reg> <op> <val>]
|
||||
set a breakpoint, optionally conditional on a
|
||||
register comparison (reg-reg or reg-immediate)
|
||||
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)
|
||||
labels list function labels and offsets
|
||||
quit kill the debuggee and exit
|
||||
w <addr> <val...> write bytes to memory
|
||||
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")
|
||||
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")
|
||||
@@ -42,10 +57,10 @@ REPL commands:
|
||||
fs.Parse(args)
|
||||
|
||||
// --- Debuggee mode (internal, spawned by the debugger) ---
|
||||
if *target {
|
||||
if os.Getenv("GASM_DEBUG_TARGET") != "" {
|
||||
tmpDir := os.Getenv("GASM_DEBUG_TMP")
|
||||
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
|
||||
}
|
||||
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")
|
||||
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")
|
||||
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")
|
||||
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)")
|
||||
@@ -1100,8 +1098,11 @@ decoders) that crash on random input but should succeed on valid data.
|
||||
return cmdVerifyCall(k, path, *call, *bufSpec, *scalarSpec, *repeat)
|
||||
}
|
||||
|
||||
// Subprocess mode: fuzz a single function and exit.
|
||||
if *fuzzOne != "" {
|
||||
// Subprocess mode: fuzz a single function and exit. The parent selects
|
||||
// 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)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
sigs := verify.ExtractSignatures(src)
|
||||
sig, ok := sigs[*fuzzOne]
|
||||
sig, ok := sigs[fuzzOne]
|
||||
if !ok {
|
||||
fmt.Printf("%s: no signature\n", *fuzzOne)
|
||||
fmt.Printf("%s: no signature\n", fuzzOne)
|
||||
return 0
|
||||
}
|
||||
goCode, ok := gt[*fuzzOne]
|
||||
goCode, ok := gt[fuzzOne]
|
||||
if !ok {
|
||||
fmt.Printf("%s: not in go tool asm\n", *fuzzOne)
|
||||
fmt.Printf("%s: not in go tool asm\n", fuzzOne)
|
||||
return 0
|
||||
}
|
||||
res := k.FuzzFunc(*fuzzOne, sig, goCode, *fuzzN, 42)
|
||||
res := k.FuzzFunc(fuzzOne, sig, goCode, *fuzzN, 42)
|
||||
fmt.Printf("%s\n", res)
|
||||
if !res.OK() {
|
||||
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
|
||||
// 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.
|
||||
if *sweepOne != "" {
|
||||
fl, err := k.Func(*sweepOne)
|
||||
// Like the fuzz mode, the parent selects the function through the
|
||||
// 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 {
|
||||
fmt.Fprintf(os.Stderr, "gasm verify: %s: %v\n", *sweepOne, err)
|
||||
fmt.Fprintf(os.Stderr, "gasm verify: %s: %v\n", sweepOne, err)
|
||||
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 {
|
||||
fmt.Println(m)
|
||||
}
|
||||
@@ -1324,7 +1327,8 @@ func fuzzInSubprocess(path, funcName string, n int) string {
|
||||
if err != nil {
|
||||
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()
|
||||
if err != nil {
|
||||
// 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 {
|
||||
return fmt.Sprintf(" smoke/abi: FAIL — cannot find self: %v", err), true
|
||||
}
|
||||
args := []string{"verify", "--sweep-one=" + funcName}
|
||||
args := []string{"verify"}
|
||||
if smoke {
|
||||
args = append(args, "-smoke")
|
||||
}
|
||||
@@ -1372,6 +1376,7 @@ func sweepInSubprocess(path, funcName string, smoke, abi bool, abiN int) (string
|
||||
}
|
||||
args = append(args, path)
|
||||
cmd := exec.Command(self, args...)
|
||||
cmd.Env = append(os.Environ(), "GASM_VERIFY_SWEEP_ONE="+funcName)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
|
||||
Reference in New Issue
Block a user