Changeset 15280


Ignore:
Timestamp:
05/13/20 06:04:44 (6 months ago)
Author:
Mark Evenson
Message:

Make javap the default for CL:DISASSEMBLE

Fix system interface for choosing disassemblers. Use
SYS:CHOOSE-DISASSEMBLER to interogate and/or change the active
disassembler for CL:DISASSEMBLER from the available assemblers
enumerated in SYS:*DISASSEMBLERS*. Test the ABCL-INTROSPECT for
loading available disassemblers as part of CI.

Additional disassemblers are collected in the ABCL-INTROSPECT contrib
as top-level ASDF systems. Currently available disassemblers include
OBJECTWEB, JAVAP, JAD, PROCYON, FERNFLOWER, and CFR.

Update OBJECTWEB to ASM framework 8.0.1

Encapsulate the loading and use of javap and jad command line
disassemblers as ASDF systems.

Rename all packages as ABCL-INTROSPECT/mumble/mumble.

Normalize ASDF formatting with dangling ":components" keyword. N.b. I
don't like this convention, as stylistically keyword arguments should
not occur in a line without their parameter, but otherwise ASDF
systems creep into too much screen.

Incomplete initial implementation for PROCYON.

Fix test semantics. Normalize test system ASDF name to
the singular form.

Document the CL:DISASSEMBLER interface in the manual and system
README.

Move the JAD dissassembler into a contrib. This contrib should
introspect the current archicture, download the necessary version of
JAD, and use that but it doesn't yet quite work. Among other
problems, it seems that the PATHNAME-URL implementation used for
downloading has problems on openjdk8 being returned a 403 Forbidden
from the remote server for some unexplained reason, whereas openjdk11
works.

Location:
trunk/abcl
Files:
13 added
2 deleted
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/abcl/.travis.yml

    r15268 r15280  
    6161
    6262script:
     63  - ${ABCL_ROOT}/abcl --batch --load ${ABCL_ROOT}/ci/test-abcl-introspect.lisp
    6364  - ${ABCL_ROOT}/abcl --batch --load ${ABCL_ROOT}/ci/test-cffi.lisp
    6465  - ${ABCL_ROOT}/abcl --batch --load ${ABCL_ROOT}/ci/test-cl+ssl.lisp
  • trunk/abcl/CHANGES

    r15273 r15280  
    66<https://gitlab.common-lisp.net/abcl/abcl/>
    77<https://abcl.org/svn/trunk/abcl/>
     8
     9Enhancements
     10============
     11
     12* [] Fix and extend SYS:CHOOSE-ASSEMBLER functionality for CL:DISASSEMBLE
    813
    914
  • trunk/abcl/abcl.rdf

    r15273 r15280  
    2020  doap:language        "Common Lisp" ;
    2121  dc:created           "01-JAN-2004" ;
    22   dc:modified          "29-APR-2020" ;
     22  dc:modified          "11-MAY-2020" ;
    2323  dc:version           "abcl-1.6.2" ;
    2424  dc:release           "dev" ;
     
    163163
    164164abcl:abcl-introspect 
    165   rdfs:seeAlso <file:contrib/abcl-introspect/README.markdown> .                             
     165  rdfs:seeAlso <file:contrib/abcl-introspect/README.org> .                             
    166166
    167167abcl:abcl-contrib 
  • trunk/abcl/contrib/abcl-introspect/abcl-introspect.asd

    r15261 r15280  
    88  :components ((:file "abcl-introspect")
    99         (:file "stacktrace"))
    10   :in-order-to ((test-op (test-op abcl-introspect-tests))))
     10  :in-order-to ((test-op (test-op abcl-introspect-test))))
    1111
  • trunk/abcl/contrib/abcl-introspect/objectweb.asd

    r15013 r15280  
    11(defsystem objectweb
    2   :homepage "http://asm.ow2.org"
    3   :defsystem-depends-on (abcl-asdf)
    4   :components
    5   ((:module maven
    6             :components
    7             ((:mvn "org.ow2.asm/asm-all/5.2")))
     2  :homepage "https://asm.ow2.org"
     3  :description "Disassembly to JVM byte code via Objectweb"
     4  :version "8.0.1"
     5  :defsystem-depends-on (abcl-asdf) :components
     6  ((:module maven :components
     7            ((:mvn "org.ow2.asm/asm-util/8.0.1")))
    88   (:module source
    99            :depends-on (maven)
    10             :pathname ""
    11             :components
     10            :pathname "" :components
    1211            ((:file "objectweb")))))
    1312
  • trunk/abcl/contrib/abcl-introspect/objectweb.lisp

    r15013 r15280  
    1 (in-package :cl-user)
    2 (defpackage :abcl/build/jvm/tools/objectweb
     1(defpackage :abcl-introspect/jvm/tools/objectweb
    32  (:use :cl)
    43  (:export
    54   #:disassemble-class-bytes))
    6 (in-package :abcl/build/jvm/tools/objectweb)
     5(in-package :abcl-introspect/jvm/tools/objectweb)
    76
    87(defun disassemble-class-bytes (object)
     
    1716
    1817(eval-when (:load-toplevel :execute)
    19   (pushnew `(:objectweb . abcl/build/jvm/tools/objectweb::disassemble-class-bytes)
     18  (pushnew `(:objectweb . abcl-introspect/jvm/tools/objectweb::disassemble-class-bytes)
    2019           sys::*disassemblers*)
    2120  (format cl:*load-verbose* "~&; ~a ; Successfully added Objectweb disassembler.~%" *package*))
  • trunk/abcl/contrib/abcl-introspect/t/disassemble.lisp

    r15013 r15280  
    44                            ext:*disassembler* #\Space))))
    55  (prove:plan 1)
    6   (prove:ok (abcl-build:introspect-path-for disassembler)
    7             (format nil
    8                     "Testing invocation of ~a specified by EXT:*DISASSEMBLER*
" disassembler)))
     6  (prove:ok
     7   (abcl-build:introspect-path-for disassembler)
     8   (format nil
     9           "Testing invocation of ~a specified by EXT:*DISASSEMBLER*
" disassembler)))
    910
    10 ;;; FIXME move dependency load into ASDF definitions
    11 (asdf:load-system :objectweb)
    12 (prove:plan 2)
    13 (prove:is
    14  (sys:choose-disassembler)
    15  'ABCL/BUILD/JVM/TOOLS/OBJECTWEB::DISASSEMBLE-CLASS-BYTES)
    16 (let ((output (make-string-output-stream)))
    17   (let ((*standard-output* output))
    18     (disassemble #'cons))
    19   (let ((result (get-output-stream-string output)))
    20     (prove:ok (and result
    21                    (stringp result)
    22                    (> (length result) 0))
    23               "Invocation of Objectweb disassembler.")))
     11(let ((disassemblers '(:objectweb :javap :jad :fernflower :cfr :procyon)))
     12  (prove:plan (* 2 (length disassemblers)))
     13  (dolist (disassembler disassemblers)
     14    (prove:ok
     15     (asdf:load-system disassembler)
     16     (format nil "Loading ~a" disassembler))
     17    (prove:ok
     18     (handler-case
     19         (let ((expected (intern :disassemble-class-bytes
     20                                 (format nil "ABCL-INTROSPECT/JVM/TOOLS/~a" (symbol-name disassembler)))))
     21           (equal
     22            (sys:choose-disassembler disassembler)
     23            expected))
     24       (t (e)
     25         (progn
     26           (prove:diag (format nil "Choosing ~a failed: ~a" disassembler e))
     27           nil)))
     28     (format nil "Able to choose ~a disassembler" disassembler)))
     29 
     30  (prove:plan (length disassemblers))
     31  (dolist (disassembler disassemblers)
     32    (let ((output (make-string-output-stream)))
     33      (prove:ok
     34       (handler-case
     35           (let ((*standard-output* output))
     36             (sys:choose-disassembler disassembler)
     37             (cl:disassemble #'cons)
     38             (let ((result (get-output-stream-string output)))
     39               (not (null (and result
     40                               (stringp result)
     41                               (> (length result) 0))))))
     42         (t (e)
     43            (progn
     44              (prove:diag (format nil "Invocation failed: ~a" e))
     45              nil)))
     46       (format nil "Invocation of ~a disassembler" disassembler)))))
    2447
    2548(prove:finalize)
  • trunk/abcl/doc/manual/abcl.tex

    r15273 r15280  
    1212\date{Version 1.6.2\\
    1313\smallskip
    14 Unreleased
     14Unreleased}
    1515\author{Mark Evenson \and Erik H\"{u}lsmann \and Rudolf Schlatte \and
    1616  Alessio Stalla \and Ville Voutilainen}
     
    936936enabling the compiler to signal all warnings.
    937937
     938\subsection{Decompilation}
     939
     940\label{CL:DISASSEMBLE}
     941Since \textsc{ABCL} compiles to JVM bytecode, the
     942\code{CL:DISASSEMBLE} function provides introspection for the result
     943of that compilation.  By default the implementation attempts to find
     944and use the \code{javap} command line tool shipped as part of the Java
     945Development Kit to disassemble the results.  Code for the use of
     946additional JVM bytecode introspection tools is packaged as part of the
     947ABCL-INTROSPECT contrib.  After loading one of these tools via ASDF,
     948the \code{SYS:CHOOSE-DISASSEMBLER} function can be used to select the
     949tool used by \code{CL:DISASSEMBLE}.  See
     950\ref{abcl-introspect-disassemblers}
     951on \pageref{abcl-introspect-disassemblers} for further details.
    938952
    939953\section{Pathname}
     
    10881102
    10891103\section{Package-Local Nicknames}
    1090 \label{sec:pack-local-nickn}
     1104\label{sec:package-local-nicknames}
    10911105
    10921106ABCL allows giving packages local nicknames: they allow short and
     
    13471361      \item \code{quicklisp-abcl} Boot a local Quicklisp installation
    13481362        via the ASDF:IRI type introduced via ABCL-ASDF.
    1349 
    13501363      \item \code{jfli} A descendant of Rich Hickey's pre-Clojure work
    13511364        on the JVM.
     
    13541367        Sucks
    13551368      \item \code{abcl-introspect} Provides a framework for
    1356         introspecting runtime Java and Lisp object values.
     1369        introspecting runtime Java and Lisp object values.  Include
     1370        packaging for installing and using java decompilation tools
     1371        for use with \code{CL:DISASSEMBLE}.
    13571372      \item \code{abcl-build} Provides a toolkit for building ABCL
    13581373        from source, as well as installing the necessary tools for
     
    15351550\label{section:jfli}
    15361551
    1537 The contrib contains a pure-Java version of JFLI.
     1552The contrib contains a pure-Java version of \textsc{JFLI}, apparently
     1553a descendent of Rich Hickey's early experimentations with using Java
     1554from Common Lisp.
    15381555
    15391556\url{http://abcl.org/svn/tags/1.6.1/contrib/jfli/README}.
     
    15411558\section{abcl-introspect}
    15421559
    1543 \textsc{ABCL-INTROSPECT} offers more extensive systems for inspecting the state
    1544 of the implementation, most notably in integration with SLIME, where
    1545 the backtrace mechanism is augmented to the point that local
    1546 variables are inspectable.
     1560\textsc{ABCL-INTROSPECT} offers more extensive functionality for
     1561inspecting the state of the implementation, most notably in
     1562integration with SLIME, where the backtrace mechanism is augmented to
     1563the point that local variables are inspectable.
    15471564
    15481565A compiled function is an instance of a class - This class has
     
    15571574introspecting these constants.
    15581575
    1559 ABCL-INTROSPECT provides access to those internal values, and
     1576\textsc{ABCL-INTROSPECT} provides access to those internal values, and
    15601577uses them in at least two ways. First, to annotate locally defined
    15611578functions with the top-level function they are defined within, and
     
    15711588location of its 'owner' is instead returns.
    15721589
    1573 In order to record information about local functions, ABCL defines a
    1574 function-plist, which is for the most part unused, but is used here
    1575 with set of keys indicating where the local function was defined and
    1576 in what manner, i.e. as normal local function, as a method function,
    1577 or as an initarg function. There may be other places functions are
    1578 stashed away (defstructs come to mind) and this file should be added
    1579 to to take them into account as they are discovered.
    1580 
    1581 ABCL-INTROSPECT does not depend on jss, but provides a bit of
    1582 jss-specific functionality if jss *is* loaded.
     1590In order to record information about local functions, \textsc{ABCL}
     1591defines a function-plist, which is for the most part unused, but is
     1592used here with set of keys indicating where the local function was
     1593defined and in what manner, i.e. as normal local function, as a method
     1594function, or as an initarg function. There may be other places
     1595functions are stashed away (defstructs come to mind) and this file
     1596should be added to to take them into account as they are discovered.
     1597
     1598\textsc{ABCL-INTROSPECT} does not depend on \textsc{JSS}, but provides
     1599  a bit of jss-specific functionality if \textsc{JSS} *is* loaded.
     1600
     1601\subsection{Implementations for CL:DISASSEMBLE}
     1602\label{abcl-introspect-disassemblers}
     1603
     1604The following ASDF systems packages various external tools that may be
     1605selected by the \code{SYS:CHOOSE-DISASSEMBLER} interface:
     1606
     1607\begin{enumerate}
     1608\item \code{objectweb}
     1609\item \code{jad}
     1610\item \code{javap}
     1611\item \code{fernweb}
     1612\item \code{cfr}
     1613\item \code{procyon}
     1614\end{enumerate}
     1615
     1616To use one of these tools, first load the system via \textsc{ASDF}
     1617(and/or \textsc{Quicklisp}), then use the
     1618\code{SYS:CHOOSE-DISASSEMBLER} function to select the keyword that
     1619appears in \code{SYS:*DISASSEMBLERS*}.
     1620\begin{listing-lisp}
     1621CL-USER> (require :abcl-contrib)(asdf:load-system :objectweb)
     1622CL-USER> sys:*disassemblers*
     1623((:OBJECTWEB
     1624  . ABCL-INTROSPECT/JVM/TOOLS/OBJECTWEB:DISASSEMBLE-CLASS-BYTES)
     1625 (:SYSTEM-JAVAP . SYSTEM:DISASSEMBLE-CLASS-BYTES))
     1626CL-USER> (sys:choose-disassembler :objectweb)
     1627ABCL-INTROSPECT/JVM/TOOLS/OBJECTWEB:DISASSEMBLE-CLASS-BYTES
     1628CL-USER> (disassemble 'cons)
     1629; // class version 52.0 (52)
     1630; // access flags 0x30
     1631; final class org/armedbear/lisp/Primitives$pf_cons extends org/armedbear/lisp/Primitive  {
     1632;
     1633;   // access flags 0x1A
     1634;   private final static INNERCLASS org/armedbear/lisp/Primitives$pf_cons org/armedbear/lisp/Primitives pf_cons
     1635;
     1636;   // access flags 0x0
     1637;   <init>()V
     1638;     ALOAD 0
     1639;     GETSTATIC org/armedbear/lisp/Symbol.CONS : Lorg/armedbear/lisp/Symbol;
     1640;     LDC "object-1 object-2"
     1641;     INVOKESPECIAL org/armedbear/lisp/Primitive.<init> (Lorg/armedbear/lisp/Symbol;Ljava/lang/String;)V
     1642;     RETURN
     1643;     MAXSTACK = 3
     1644;     MAXLOCALS = 1
     1645;
     1646;   // access flags 0x1
     1647;   public execute(Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)Lorg/armedbear/lisp/LispObject;
     1648;     NEW org/armedbear/lisp/Cons
     1649;     DUP
     1650;     ALOAD 1
     1651;     ALOAD 2
     1652;     INVOKESPECIAL org/armedbear/lisp/Cons.<init> (Lorg/armedbear/lisp/LispObject;Lorg/armedbear/lisp/LispObject;)V
     1653;     ARETURN
     1654;     MAXSTACK = 4
     1655;     MAXLOCALS = 3
     1656; }
     1657NIL
     1658\end{listing-lisp}
     1659 
    15831660
    15841661\url{http://abcl.org/svn/tags/1.6.1/contrib/abcl-introspect/}.
  • trunk/abcl/src/org/armedbear/lisp/Lisp.java

    r15137 r15280  
    26992699  public static final Symbol _DISASSEMBLER_ =
    27002700    exportSpecial("*DISASSEMBLER*", PACKAGE_EXT,
    2701                   new SimpleString("jad -a -p")); // or "jad -dis -p"
     2701                  new SimpleString("javap -c -verbose")); // or "jad -dis -p"
    27022702
    27032703  // ### *speed* compiler policy
  • trunk/abcl/src/org/armedbear/lisp/disassemble.lisp

    r15013 r15280  
    4141
    4242(defvar *disassemblers*
    43   `((:jad . disassemble-class-bytes))
    44   "Methods of invoking CL:DISASSEMBLE consisting of a pushable list of (name function), where function takes a object to disassemble, returns the results as a string.
    45 
    46 The system is :jad using the venerable-but-still-works JAD.
     43  `((:system-javap . disassemble-class-bytes))
     44  "Methods of invoking CL:DISASSEMBLE consisting of a enumeration of (keyword function) pairs
     45
     46The pairs (keyword function) contain a keyword identifying this
     47particulat disassembler, and a symbol designating function takes a
     48object to disassemble.
     49
     50Use SYS:CHOOSE-DISASSEMBLER to install a given disassembler as the one
     51used by CL:DISASSEMBLE.  Additional disassemblers/decompilers are
     52packaged in the ABCL-INTROSPECT contrib.
     53
     54The intial default is :javap using the javap command line tool which
     55is part of the Java Developement Kit.
    4756")
    4857
    4958(defun choose-disassembler (&optional name)
    50   "Hook to choose invoked behavior of CL:DISASSEMBLE by using one of the methods registered in SYSTEM:*DISASSEMBLERS*.
    51 
    52 Optionally, prefer the strategy named NAME if one exists."
     59  "Report current disassembler that would be used by CL:DISASSEMBLE
     60
     61With optional keyword NAME, select the associated disassembler from
     62SYS:*DISASSEMBLERS*."
     63  (flet ((sane-disassembler-p (disassembler)
     64           (and disassembler
     65                (fboundp disassembler))))
    5366    (setf *disassembler-function*
    5467          (if name
    5568              (let ((disassembler (cdr (assoc name *disassemblers*))))
    56                 (if (and disassembler
    57                          (fboundp disassembler))
     69                (if (sane-disassembler-p disassembler)
    5870                    disassembler
    5971                    (error "Disassembler ~a doesn't appear to work." name)))
    60               (loop
    61                  :for (nil . disassembler) in *disassemblers*
    62                  :when (and disassembler
    63                             (fboundp disassembler))
    64                  :do (return disassembler)
    65                  finally (warn "Can't find suitable disassembler.")))))
     72              (if (sane-disassembler-p *disassembler-function*)
     73                  *disassembler-function*
     74                  ;; simplest strategy: choose the first working one
     75                  (loop
     76                    :for (nil . disassembler) in *disassemblers*
     77                    :when (sane-disassembler-p disassembler)
     78                      :do (return disassembler)
     79                    :finally (warn "Can't find suitable disassembler.")))))))
    6680
    6781(eval-when (:compile-toplevel :load-toplevel :execute)
Note: See TracChangeset for help on using the changeset viewer.