added "debugging" support
authorRalph Ronnquist <ralph.ronnquist@gmail.com>
Mon, 28 Mar 2022 23:06:25 +0000 (10:06 +1100)
committerRalph Ronnquist <ralph.ronnquist@gmail.com>
Mon, 28 Mar 2022 23:06:25 +0000 (10:06 +1100)
asm/Makefile
asm/fas2txt.lsp [new file with mode: 0755]

index 4afe03483315228ab67879dac9f7d209691200bd..87a63e2e7e2f489e340323b94e969ec62d01722f 100644 (file)
@@ -1,6 +1,7 @@
 reaper: reaper.asm
-       fasm $^ $@
+       fasm $^ -s $@.fas $@
        chmod a+x $@
+       ./fas2txt.lsp $@.fas > $@.map
 
 clean:
        rm -f reaper
diff --git a/asm/fas2txt.lsp b/asm/fas2txt.lsp
new file mode 100755 (executable)
index 0000000..98f4c41
--- /dev/null
@@ -0,0 +1,118 @@
+#!/usr/bin/newlisp
+#
+# Print an assembly listing for ELF targets associating binary address
+# with source lines.
+
+(signal 2 exit) ; exit on Ctrl-C
+
+; Format a byte or list of bytes into a hex string
+(define (hex L)
+  (if (list? L) (string "0x" (join (map (curry format "%02x") L)))
+    ; else
+    (hex (list L))))
+
+; Helper function to "copy out" a NUL terminated string from the
+; beginning of a memblock. (only an issue with utf8-enabled newlisp)
+(define (asciiz X) (get-string (address X)))
+
+; Helper function to set and print a variable
+(define (print-assign X Y) (set X (println X " = " Y)))
+
+; Helper "macro" to set variables and print their assignments
+(define-macro (setf-print)
+  (map (fn (P) (print-assign (P 0) (eval (P 1)))) (explode (args) 2)))
+
+; Load the .fas file here; named last on the command line
+(setf FAS (read-file (main-args -1)))
+
+(setf-print
+ SIGNATURE (hex (reverse (unpack (dup "b" 4) FAS)))
+ VERSION (unpack "bb" (4 FAS))
+ HEADER-LENGTH ((unpack "u" (6 FAS)) 0)
+ INFILEP ((unpack "lu" (8 FAS)) 0)
+ OUTFILEP ((unpack "lu" (12 FAS)) 0)
+ STRINGS-TABLE-OFFSET ((unpack "lu" (16 FAS)) 0)
+ STRINGS-TABLE-LENGTH ((unpack "lu" (20 FAS)) 0)
+ SYMBOLS-TABLE-OFFSET ((unpack "lu" (24 FAS)) 0)
+ SYMBOLS-TABLE-LENGTH ((unpack "lu" (28 FAS)) 0)
+ PREPROCESSED-OFFSET ((unpack "lu" (32 FAS)) 0)
+ PREPROCESSED-LENGTH ((unpack "lu" (36 FAS)) 0)
+ ASSEMBLY-DUMP-OFFSET ((unpack "lu" (40 FAS)) 0)
+ ASSEMBLY-DUMP-LENGTH ((unpack "lu" (44 FAS)) 0)
+ SECTION-TABLE-OFFSET ((unpack "lu" (48 FAS)) 0)
+ SECTION-TABLE-LENGTH ((unpack "lu" (52 FAS)) 0)
+ SYMBOL-REFERENCES-DUMP-OFFSET ((unpack "lu" (56 FAS)) 0)
+ SYMBOL-REFERENCES-DUMP-LENGTH ((unpack "lu" (60 FAS)) 0)
+ )
+
+(setf
+ STRINGS (STRINGS-TABLE-OFFSET STRINGS-TABLE-LENGTH FAS)
+ _ (println STRINGS)
+ PREP (PREPROCESSED-OFFSET PREPROCESSED-LENGTH FAS)
+ )
+
+(setf-print
+ MAIN-FILE (asciiz (INFILEP STRINGS))
+ )
+
+; Hash tables for filename->content and macroid->firstline
+(define FILES:FILES nil)   ; for captured file content
+(define MACROS:MACROS nil) ; for captured first-appearance-line of macros
+
+; Get/cache content of file
+(define (get-file NAME)
+  (or (FILES NAME) (FILES NAME (read-file NAME))))
+
+; Check if N is the first-appearence-line in macro ID
+; (capture N for the very first appearance of ID)
+(define (macro-start ID N)
+  (if (MACROS ID) (= (MACROS ID) N) (MACROS ID N)))
+
+; The file name for prep entry index i (with 0 = main file)
+(define (source-file i)
+  (if (= i) MAIN-FILE (asciiz (i PREP))))
+
+; Extract and format the file line with line number LN that is at at
+; position i of file FILE.
+(define (get-line i FILE LN)
+  (letn ((DATA (get-file FILE))
+         (END (find "\n" DATA nil i))
+         (R (i (- END i) DATA)) )
+    (format "%s:%-5d %s" FILE LN R)))
+
+; Format a "macro" prep entry by prepending an informative line for
+; the first-appearance-line.
+(define (resolve-macro AT PL)
+  (if (macro-start (PL 2) (PL 1))
+      (string (PREP-SOURCE-LINE "--------" (PL 2)) "\n"
+              (PREP-SOURCE-LINE AT (PL 3)))
+    ; else
+    (PREP-SOURCE-LINE AT (PL 3))))
+
+; Format output for "address" AT and prep line PL (unpacked)
+(define (prep-source AT PL)
+  (if (!= (& 0x80000000 (PL 1))) (resolve-macro AT PL)
+    ; else
+    (string AT " " (get-line (PL 2) (source-file (PL 0)) (PL 1)))))
+
+; Format output for "address" AT and prep line at P (index)
+(define (PREP-SOURCE-LINE AT P)
+  (prep-source AT (unpack "lu lu lu lu" (P PREP))))
+
+; Format output for assembly line L (memblock)
+(define (ASSEMBLY-LINE L)
+  (let ((AL (unpack "lu lu lu lu lu b b b b" (or L ""))))
+    (PREP-SOURCE-LINE (hex (AL 2)) (AL 1))
+    ))
+
+; divide memblock D into memblocks of size N
+(define (frag N D)
+  (unpack (dup (string "s" N " ") (/ (length D) N)) D))
+
+#### Main action(s) start here
+
+(map println
+     (map ASSEMBLY-LINE
+          (frag 28 (ASSEMBLY-DUMP-OFFSET ASSEMBLY-DUMP-LENGTH FAS))))
+
+(exit 0)