shithub: sl

Download patch

ref: 5090b2fec4c35cfc5b41fcb32e8efc33a078567f
parent: 9c0e261a35c05718aa9c890f7164c441c868ceb4
author: spew <spew@cbza.org>
date: Tue Mar 18 20:34:18 EDT 2025

lsd: add filepc, extend bpset/bpdel with file:line

--- a/src/plan9/lsd.c
+++ b/src/plan9/lsd.c
@@ -393,6 +393,30 @@
 	return str_from_cstr(buf);
 }
 
+BUILTIN("lsd-file2pc", lsd_file2pc)
+{
+	static char buf[1024];
+	uvlong addr;
+	int len, line;
+
+	argcount(nargs, 2);
+	if(sl_unlikely(!sl_isstr(args[0])))
+		type_error("str", args[0]);
+	if(sl_unlikely(!isfixnum(args[1])))
+		type_error("num", args[1]);
+
+	len = cv_len(ptr(args[0]));
+	if(len+1 > sizeof(buf))
+		lerrorf(sl_errio, "path too long");
+	memmove(buf, cvalue_data(args[0]), len);
+	buf[len] = '\0';
+	line = numval(args[1]);
+	addr = file2pc(buf, line);
+	if(addr == ~0)
+		lerrorf(sl_errio, "could not find address of %s:%d", buf, line);
+	return size_wrap(addr);
+}
+
 BUILTIN("lsd-ctrace", lsd_ctrace)
 {
 	sl_v *a;
--- a/src/plan9/lsd.lsp
+++ b/src/plan9/lsd.lsp
@@ -28,6 +28,7 @@
   (princ "process " pid " exited\n")
   (set! pids (cdr pids))
   (set! pid (if pids (car pids) -1))
+  (set! bptbl (table))
   (detach))
 
 (def (readnote)
@@ -86,11 +87,11 @@
                  (unless (eq? (status) 'Stopped)
                          (begin (princ "Waiting... " status "\n")
                                 (stop)))
-                 (cond ((sym? loc) (unless (has? (global-text globals) loc)
-                                           (error "symbol " loc " not found"))
-                                   (symbol-addr (get (global-text globals) loc)))
+                 (cond ((sym? loc) (symbol-addr (get (global-text globals) loc)))
                        ((num? loc) (u64 loc))
-                       (else (error "symbol or number"))))))
+                       ((symbol? loc) (symbol-addr loc))
+                       ((str? loc) (filepc loc))
+                       (else (error "sym|num|symbol|file:line"))))))
   (set! bpset (λ (loc)
                 (let ((addr (bp_init loc)))
                   (when (has? bptbl addr)
@@ -107,26 +108,34 @@
 (doc-for (bpset loc)
   "Set a breakpoint.
 
-   The location can either be a symbol, in which case
-   the address will be retrieved from the global text symbols
-   of the process, or an integer which is the address at which
-   to place the break.
+   The location can be one of the following:
+   1. A sym, in which case the address will be retrieved from
+      the global text symbols of the process,
+   2. A num which is the address at which to place the break.
+   3. An LSD symbol in which the case the symbol's address is used.
+   4. A string of the form \"file:line\" which specifies a line in a
+      file of source code.
 
    Examples:
      `(bpset 'strcpy)` ; breakpoint on strcpy function.
-     `(bpset (readreg PC))` ; breakpoint on current instruction.")
+     `(bpset (readreg PC))` ; breakpoint on current instruction.
+     `(bpset \"/sys/src/cmd/cat.c:26\")` ; breakpoint on line 26.")
 
 (doc-for (bpdel loc)
   "Delete a breakpoint.
 
-   The location can either be a symbol, in which case
-   the address will be retrieved from the global text symbols
-   of the process, or an integer which is the address at which
-   to remove the break.
+   The location can be one of the following:
+   1. A sym, in which case the address will be retrieved from
+      the global text symbols of the process,
+   2. A num which is the address at which to place the break.
+   3. An LSD symbol in which the case the symbol's address is used.
+   4. A string of the form \"file:line\" which specifies a line in a
+      file of source code.
 
    Examples:
      `(bpdel 'strcpy)` ; remove breakpoint on strcpy function.
-     `(bpdel (readreg PC))` ; remove breakpoint on current instruction.")
+     `(bpdel (readreg PC))` ; remove breakpoint on current instruction.
+     `(bpdel \"/sys/src/cmd/cat.c:26\")` ; remove breakpoint on line 26.")
 
 (def (detach)
   (when regsf (io-close regsf))
@@ -234,11 +243,7 @@
 
 (def (src (addr (readreg PC)))
   "Returns a string of the filename and line number corresponding
-   to the instruction address.
-
-   Examples:
-     `(src)`
-     `(src (asm 10))` ; read 10 instructions forward first."
+   to the instruction address."
   (lsd-fileline addr))
 
 (def (Bsrc (addr (readreg PC)))
@@ -257,6 +262,14 @@
                    "\n" s))
     (io-close plumbf)))
 
+(def (filepc f (line NIL))
+  (if line
+      (lsd-file2pc f line)
+      (let ((s (str-split f ":")))
+        (when (/= (length s) 2) (error "invalid file"))
+        (let ((line (str->num (cadr s))))
+          (unless line (error "bad line number"))
+          (lsd-file2pc (car s) line)))))
 
 (def (at-exit s)
   (when proc-stdin (io-close proc-stdin))
@@ -263,6 +276,13 @@
   (detach)
   (lsd-cleanup)
   (for-each (λ (p) (princ "echo kill > /proc/" p "/ctl\n")) pids))
+
+(def (sym-find s)
+  (let* ((find (λ (tbl k) (and (has? tbl k) (get tbl k)))))
+    (or (find (global-text globals) s)
+        (find (global-data globals) s))))
+
+(def (sym-addr s) (symbol-addr (find-sym s)))
 
 (add-exit-hook at-exit)