parse jumps as labels when decompiling bytecode->assembly
[bpt/guile.git] / module / language / assembly / disassemble.scm
CommitLineData
d7236899
AW
1;;; Guile VM code converters
2
3;; Copyright (C) 2001 Free Software Foundation, Inc.
4
5;; This program is free software; you can redistribute it and/or modify
6;; it under the terms of the GNU General Public License as published by
7;; the Free Software Foundation; either version 2, or (at your option)
8;; any later version.
9;;
10;; This program is distributed in the hope that it will be useful,
11;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13;; GNU General Public License for more details.
14;;
15;; You should have received a copy of the GNU General Public License
16;; along with this program; see the file COPYING. If not, write to
17;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18;; Boston, MA 02111-1307, USA.
19
20;;; Code:
21
22(define-module (language assembly disassemble)
23 #:use-module (ice-9 format)
24 #:use-module (system vm instruction)
25 #:use-module (system vm program)
26 #:use-module (system base pmatch)
27 #:use-module (language assembly)
28 #:use-module (system base compile)
29 #:export (disassemble))
30
31(define (disassemble x)
32 (format #t "Disassembly of ~A:\n\n" x)
33 (call-with-values
34 (lambda () (decompile x #:from 'value #:to 'assembly))
35 disassemble-load-program))
36
37(define (disassemble-load-program asm env)
38 (pmatch asm
1f1ec13b 39 ((load-program ,nargs ,nrest ,nlocs ,nexts ,labels ,len ,meta . ,code)
d7236899
AW
40 (let ((objs (and env (assq-ref env 'objects)))
41 (meta (and env (assq-ref env 'meta)))
42 (exts (and env (assq-ref env 'exts)))
43 (blocs (and env (assq-ref env 'blocs)))
44 (bexts (and env (assq-ref env 'bexts)))
45 (srcs (and env (assq-ref env 'sources))))
46 (let lp ((pos 0) (code code) (programs '()))
47 (cond
48 ((null? code)
49 (newline)
50 (for-each
51 (lambda (sym+asm)
52 (format #t "Embedded program ~A:\n\n" (car sym+asm))
53 (disassemble-load-program (cdr sym+asm) '()))
54 (reverse! programs)))
55 (else
56 (let* ((asm (car code))
57 (len (byte-length asm))
58 (end (+ pos len)))
59 (pmatch asm
60 ((load-program . _)
61 (let ((sym (gensym "")))
62 (print-info pos `(load-program ,sym) #f #f)
63 (lp (+ pos (byte-length asm)) (cdr code)
64 (acons sym asm programs))))
65 (else
66 (print-info pos asm
67 (code-annotation end asm objs nargs blocs bexts)
68 (and=> (and srcs (assq end srcs)) source->string))
69 (lp (+ pos (byte-length asm)) (cdr code) programs)))))))
70
71 (if (pair? exts)
72 (disassemble-externals exts))
73 (if meta
74 (disassemble-meta meta))
75
76 ;; Disassemble other bytecode in it
77 ;; FIXME: something about the module.
78 (if objs
79 (for-each
80 (lambda (x)
81 (if (program? x)
82 (begin (display "----------------------------------------\n")
83 (disassemble x))))
84 (cddr (vector->list objs))))))
85 (else
86 (error "bad load-program form" asm))))
87
88(define (disassemble-objects objs)
89 (display "Objects:\n\n")
90 (let ((len (vector-length objs)))
91 (do ((n 0 (1+ n)))
92 ((= n len) (newline))
93 (print-info n (vector-ref objs n) #f #f))))
94
95(define (disassemble-externals exts)
96 (display "Externals:\n\n")
97 (let ((len (length exts)))
98 (do ((n 0 (1+ n))
99 (l exts (cdr l)))
100 ((null? l) (newline))
101 (print-info n (car l) #f #f))))
102
103(define-macro (unless test . body)
104 `(if (not ,test) (begin ,@body)))
105
106(define *uninteresting-props* '(name))
107
108(define (disassemble-meta meta)
109 (let ((sources (cadr meta))
110 (props (filter (lambda (x)
111 (not (memq (car x) *uninteresting-props*)))
112 (cddr meta))))
113 (unless (null? props)
114 (display "Properties:\n\n")
115 (for-each (lambda (x) (print-info #f x #f #f)) props)
116 (newline))))
117
118(define (source->string src)
119 (format #f "~a:~a:~a" (or (source:file src) "(unknown file)")
120 (source:line src) (source:column src)))
121
122(define (make-int16 byte1 byte2)
123 (+ (* byte1 256) byte2))
124
125(define (code-annotation end-addr code objs nargs blocs bexts)
126 (let* ((code (assembly-unpack code))
127 (inst (car code))
128 (args (cdr code)))
129 (case inst
130 ((list vector)
131 (list "~a element~:p" (apply make-int16 args)))
132 ((br br-if br-if-eq br-if-not br-if-not-eq br-if-not-null br-if-null)
133 (list "-> ~A" (+ end-addr (apply make-int16 args))))
134 ((object-ref)
135 (and objs (list "~s" (vector-ref objs (car args)))))
136 ((local-ref local-set)
137 (and blocs
594d9d4c
AW
138 (let lp ((bindings (list-ref blocs (car args))))
139 (and (pair? bindings)
140 (let ((b (car bindings)))
141 (if (and (< (binding:start (car bindings)) end-addr)
142 (>= (binding:end (car bindings)) end-addr))
143 (list "`~a'~@[ (arg)~]"
144 (binding:name b) (< (binding:index b) nargs))
145 (lp (cdr bindings))))))))
d7236899
AW
146 ((external-ref external-set)
147 (and bexts
148 (if (< (car args) (length bexts))
149 (let ((b (list-ref bexts (car args))))
150 (list "`~a'~@[ (arg)~]"
151 (binding:name b) (< (binding:index b) nargs)))
152 (list "(closure variable)"))))
153 ((toplevel-ref toplevel-set)
154 (and objs
155 (let ((v (vector-ref objs (car args))))
156 (if (and (variable? v) (variable-bound? v))
157 (list "~s" (variable-ref v))
158 (list "`~s'" v)))))
159 ((mv-call)
160 (list "MV -> ~A" (+ end-addr (apply make-int16 (cdr args)))))
161 (else
162 (and=> (assembly->object code)
163 (lambda (obj) (list "~s" obj)))))))
164
165;; i am format's daddy.
166(define (print-info addr info extra src)
167 (format #t "~4@S ~32S~@[;; ~1{~@?~}~]~@[~61t at ~a~]\n" addr info extra src))
168
169(define (simplify x)
170 (cond ((string? x)
171 (cond ((string-index x #\newline) =>
172 (lambda (i) (set! x (substring x 0 i)))))
173 (cond ((> (string-length x) 16)
174 (set! x (string-append (substring x 0 13) "..."))))))
175 x)
176