decompile-bytecode.scm 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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 decompile-bytecode)
  18. #:use-module (system vm instruction)
  19. #:use-module (system base pmatch)
  20. #:use-module (srfi srfi-4)
  21. #:use-module (rnrs bytevectors)
  22. #:use-module (language assembly)
  23. #:use-module ((system vm objcode) #:select (byte-order))
  24. #:export (decompile-bytecode))
  25. (define (decompile-bytecode x env opts)
  26. (let ((i 0) (size (u8vector-length x)))
  27. (define (pop)
  28. (let ((b (cond ((< i size) (u8vector-ref x i))
  29. ((= i size) #f)
  30. (else (error "tried to decode too many bytes")))))
  31. (if b (set! i (1+ i)))
  32. b))
  33. (let ((ret (decode-load-program pop)))
  34. (if (= i size)
  35. (values ret env)
  36. (error "bad bytecode: only decoded ~a out of ~a bytes" i size)))))
  37. (define (br-instruction? x)
  38. (memq x '(br br-if br-if-not br-if-eq br-if-not-eq br-if-null br-if-not-null)))
  39. (define (br-nargs-instruction? x)
  40. (memq x '(br-if-nargs-ne br-if-nargs-lt br-if-nargs-gt)))
  41. (define (bytes->s24 a b c)
  42. (let ((x (+ (ash a 16) (ash b 8) c)))
  43. (if (zero? (logand (ash 1 23) x))
  44. x
  45. (- x (ash 1 24)))))
  46. ;; FIXME: this is a little-endian disassembly!!!
  47. (define (decode-load-program pop)
  48. (let* ((a (pop)) (b (pop)) (c (pop)) (d (pop))
  49. (e (pop)) (f (pop)) (g (pop)) (h (pop))
  50. (len (+ a (ash b 8) (ash c 16) (ash d 24)))
  51. (metalen (+ e (ash f 8) (ash g 16) (ash h 24)))
  52. (labels '())
  53. (i 0))
  54. (define (ensure-label rel1 rel2 rel3)
  55. (let ((where (+ i (bytes->s24 rel1 rel2 rel3))))
  56. (or (assv-ref labels where)
  57. (begin
  58. (let ((l (gensym ":L")))
  59. (set! labels (acons where l labels))
  60. l)))))
  61. (define (sub-pop) ;; ...records. ha. ha.
  62. (let ((b (cond ((< i len) (pop))
  63. ((= i len) #f)
  64. (else (error "tried to decode too many bytes")))))
  65. (if b (set! i (1+ i)))
  66. b))
  67. (let lp ((out '()))
  68. (cond ((> i len)
  69. (error "error decoding program -- read too many bytes" out))
  70. ((= i len)
  71. `(load-program ,(map (lambda (x) (cons (cdr x) (car x)))
  72. (reverse labels))
  73. ,len
  74. ,(if (zero? metalen) #f (decode-load-program pop))
  75. ,@(reverse! out)))
  76. (else
  77. (let ((exp (decode-bytecode sub-pop)))
  78. (pmatch exp
  79. ((,br ,rel1 ,rel2 ,rel3) (guard (br-instruction? br))
  80. (lp (cons `(,br ,(ensure-label rel1 rel2 rel3)) out)))
  81. ((,br ,hi ,lo ,rel1 ,rel2 ,rel3) (guard (br-nargs-instruction? br))
  82. (lp (cons `(,br ,hi ,lo ,(ensure-label rel1 rel2 rel3)) out)))
  83. ((mv-call ,n ,rel1 ,rel2 ,rel3)
  84. (lp (cons `(mv-call ,n ,(ensure-label rel1 rel2 rel3)) out)))
  85. ((prompt ,n0 ,rel1 ,rel2 ,rel3)
  86. (lp (cons `(prompt ,n0 ,(ensure-label rel1 rel2 rel3)) out)))
  87. (else
  88. (lp (cons exp out))))))))))
  89. (define (decode-bytecode pop)
  90. (and=> (pop)
  91. (lambda (opcode)
  92. (let ((inst (opcode->instruction opcode)))
  93. (cond
  94. ((eq? inst 'load-program)
  95. (decode-load-program pop))
  96. ((< (instruction-length inst) 0)
  97. ;; the negative length indicates a variable length
  98. ;; instruction
  99. (let* ((make-sequence
  100. (if (or (memq inst '(load-array load-wide-string)))
  101. make-bytevector
  102. make-string))
  103. (sequence-set!
  104. (if (or (memq inst '(load-array load-wide-string)))
  105. bytevector-u8-set!
  106. (lambda (str pos value)
  107. (string-set! str pos (integer->char value)))))
  108. (len (let* ((a (pop)) (b (pop)) (c (pop)))
  109. (+ (ash a 16) (ash b 8) c)))
  110. (seq (make-sequence len)))
  111. (let lp ((i 0))
  112. (if (= i len)
  113. `(,inst ,(if (eq? inst 'load-wide-string)
  114. (utf32->string seq (native-endianness))
  115. seq))
  116. (begin
  117. (sequence-set! seq i (pop))
  118. (lp (1+ i)))))))
  119. (else
  120. ;; fixed length
  121. (let lp ((n (instruction-length inst)) (out (list inst)))
  122. (if (zero? n)
  123. (reverse! out)
  124. (lp (1- n) (cons (pop) out))))))))))