disassemble.scm 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. ;;; Guile VM code converters
  2. ;; Copyright (C) 2001, 2009, 2010 Free Software Foundation, Inc.
  3. ;;;; This library is free software; you can redistribute it and/or
  4. ;;;; modify it under the terms of the GNU Lesser General Public
  5. ;;;; License as published by the Free Software Foundation; either
  6. ;;;; version 3 of the License, or (at your option) any later version.
  7. ;;;;
  8. ;;;; This library is distributed in the hope that it will be useful,
  9. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. ;;;; Lesser General Public License for more details.
  12. ;;;;
  13. ;;;; You should have received a copy of the GNU Lesser General Public
  14. ;;;; License along with this library; if not, write to the Free Software
  15. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  16. ;;; Code:
  17. (define-module (language assembly disassemble)
  18. #:use-module (ice-9 format)
  19. #:use-module (srfi srfi-1)
  20. #:use-module (system vm instruction)
  21. #:use-module (system vm program)
  22. #:use-module (system base pmatch)
  23. #:use-module (language assembly)
  24. #:use-module (system base compile)
  25. #:export (disassemble))
  26. (define (disassemble x)
  27. (format #t "Disassembly of ~A:\n\n" x)
  28. (call-with-values
  29. (lambda () (decompile x #:from 'value #:to 'assembly))
  30. disassemble-load-program))
  31. (define (disassemble-load-program asm env)
  32. (pmatch asm
  33. ((load-program ,labels ,len ,meta . ,code)
  34. (let ((objs (and env (assq-ref env 'objects)))
  35. (free-vars (and env (assq-ref env 'free-vars)))
  36. (meta (and env (assq-ref env 'meta)))
  37. (blocs (and env (assq-ref env 'blocs)))
  38. (srcs (and env (assq-ref env 'sources))))
  39. (let lp ((pos 0) (code code) (programs '()))
  40. (cond
  41. ((null? code)
  42. (newline)
  43. (for-each
  44. (lambda (sym+asm)
  45. (format #t "Embedded program ~A:\n\n" (car sym+asm))
  46. (disassemble-load-program (cdr sym+asm) '()))
  47. (reverse! programs)))
  48. (else
  49. (let* ((asm (car code))
  50. (len (byte-length asm))
  51. (end (+ pos len)))
  52. (pmatch asm
  53. ((load-program . _)
  54. (let ((sym (gensym "")))
  55. (print-info pos `(load-program ,sym) #f #f)
  56. (lp (+ pos (byte-length asm)) (cdr code)
  57. (acons sym asm programs))))
  58. ((nop)
  59. (lp (+ pos (byte-length asm)) (cdr code) programs))
  60. (else
  61. (print-info pos asm
  62. ;; FIXME: code-annotation for whether it's
  63. ;; an arg or not, currently passing nargs=-1
  64. (code-annotation end asm objs -1 blocs
  65. labels)
  66. (and=> (and srcs (assq end srcs)) source->string))
  67. (lp (+ pos (byte-length asm)) (cdr code) programs)))))))
  68. (if (pair? free-vars)
  69. (disassemble-free-vars free-vars))
  70. (if meta
  71. (disassemble-meta meta))
  72. ;; Disassemble other bytecode in it
  73. ;; FIXME: something about the module.
  74. (if objs
  75. (for-each
  76. (lambda (x)
  77. (if (program? x)
  78. (begin (display "----------------------------------------\n")
  79. (disassemble x))))
  80. (cdr (vector->list objs))))))
  81. (else
  82. (error "bad load-program form" asm))))
  83. (define (disassemble-free-vars free-vars)
  84. (display "Free variables:\n\n")
  85. (fold (lambda (free-var i)
  86. (print-info i free-var #f #f)
  87. (+ 1 i))
  88. 0
  89. free-vars))
  90. (define-macro (unless test . body)
  91. `(if (not ,test) (begin ,@body)))
  92. (define *uninteresting-props* '(name))
  93. (define (disassemble-meta meta)
  94. (let ((props (filter (lambda (x)
  95. (not (memq (car x) *uninteresting-props*)))
  96. (cdddr meta))))
  97. (unless (null? props)
  98. (display "Properties:\n\n")
  99. (for-each (lambda (x) (print-info #f x #f #f)) props)
  100. (newline))))
  101. (define (source->string src)
  102. (format #f "~a:~a:~a" (or (source:file src) "(unknown file)")
  103. (source:line-for-user src) (source:column src)))
  104. (define (make-int16 byte1 byte2)
  105. (+ (* byte1 256) byte2))
  106. (define (code-annotation end-addr code objs nargs blocs labels)
  107. (let* ((code (assembly-unpack code))
  108. (inst (car code))
  109. (args (cdr code)))
  110. (case inst
  111. ((list vector)
  112. (list "~a element~:p" (apply make-int16 args)))
  113. ((br br-if br-if-eq br-if-not br-if-not-eq br-if-not-null br-if-null)
  114. (list "-> ~A" (assq-ref labels (car args))))
  115. ((br-if-nargs-ne br-if-nargs-lt br-if-nargs-gt)
  116. (list "-> ~A" (assq-ref labels (caddr args))))
  117. ((object-ref)
  118. (and objs (list "~s" (vector-ref objs (car args)))))
  119. ((local-ref local-boxed-ref local-set local-boxed-set)
  120. (and blocs
  121. (let lp ((bindings (list-ref blocs (car args))))
  122. (and (pair? bindings)
  123. (let ((b (car bindings)))
  124. (if (and (< (binding:start (car bindings)) end-addr)
  125. (>= (binding:end (car bindings)) end-addr))
  126. (list "`~a'~@[ (arg)~]"
  127. (binding:name b) (< (binding:index b) nargs))
  128. (lp (cdr bindings))))))))
  129. ((free-ref free-boxed-ref free-boxed-set)
  130. ;; FIXME: we can do better than this
  131. (list "(closure variable)"))
  132. ((toplevel-ref toplevel-set)
  133. (and objs
  134. (let ((v (vector-ref objs (car args))))
  135. (if (and (variable? v) (variable-bound? v))
  136. (list "~s" (variable-ref v))
  137. (list "`~s'" v)))))
  138. ((mv-call)
  139. (list "MV -> ~A" (assq-ref labels (cadr args))))
  140. ((prompt)
  141. ;; the H is for handler
  142. (list "H -> ~A" (assq-ref labels (cadr args))))
  143. (else
  144. (and=> (assembly->object code)
  145. (lambda (obj) (list "~s" obj)))))))
  146. ;; i am format's daddy.
  147. (define (print-info addr info extra src)
  148. (format #t "~4@S ~32S~@[;; ~1{~@?~}~]~@[~61t at ~a~]\n" addr info extra src))