Initial support for disassembling
authorJan Vrany <jan.vrany@fit.cvut.cz>
Thu, 10 Dec 2015 08:47:42 +0000
changeset 1 aa002d0c231b
parent 0 e4a716697bef
child 2 88445baa732f
Initial support for disassembling
udis86sx/Make.proto
udis86sx/Make.spec
udis86sx/UDIS86.st
udis86sx/UDIS86Instruction.st
udis86sx/abbrev.stc
udis86sx/bc.mak
udis86sx/jv_dragonfly_udis86sx.st
udis86sx/libInit.cc
--- a/udis86sx/Make.proto	Tue Dec 08 08:55:42 2015 +0000
+++ b/udis86sx/Make.proto	Thu Dec 10 08:47:42 2015 +0000
@@ -34,7 +34,7 @@
 # add the path(es) here:,
 # ********** OPTIONAL: MODIFY the next lines ***
 # LOCALINCLUDES=-Ifoo -Ibar
-LOCALINCLUDES= -I$(INCLUDE_TOP)/stx/libbasic
+LOCALINCLUDES=-Iudis86 -I$(INCLUDE_TOP)/stx/libbasic
 
 
 # if you need any additional defines for embedded C code,
@@ -128,6 +128,8 @@
 
 
 # BEGINMAKEDEPEND --- do not remove this line; make depend needs it
+$(OUTDIR)UDIS86.$(O) UDIS86.$(H): UDIS86.st $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
+$(OUTDIR)UDIS86Instruction.$(O) UDIS86Instruction.$(H): UDIS86Instruction.st $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(STCHDR)
 $(OUTDIR)jv_dragonfly_udis86sx.$(O) jv_dragonfly_udis86sx.$(H): jv_dragonfly_udis86sx.st $(INCLUDE_TOP)/stx/libbasic/LibraryDefinition.$(H) $(INCLUDE_TOP)/stx/libbasic/Object.$(H) $(INCLUDE_TOP)/stx/libbasic/ProjectDefinition.$(H) $(STCHDR)
 
 # ENDMAKEDEPEND --- do not remove this line
--- a/udis86sx/Make.spec	Tue Dec 08 08:55:42 2015 +0000
+++ b/udis86sx/Make.spec	Thu Dec 10 08:47:42 2015 +0000
@@ -51,12 +51,16 @@
 STCWARNINGS=-warnNonStandard
 
 COMMON_CLASSES= \
+	UDIS86 \
+	UDIS86Instruction \
 	jv_dragonfly_udis86sx \
 
 
 
 
 COMMON_OBJS= \
+    $(OUTDIR_SLASH)UDIS86.$(O) \
+    $(OUTDIR_SLASH)UDIS86Instruction.$(O) \
     $(OUTDIR_SLASH)jv_dragonfly_udis86sx.$(O) \
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/udis86sx/UDIS86.st	Thu Dec 10 08:47:42 2015 +0000
@@ -0,0 +1,235 @@
+"{ Package: 'jv:dragonfly/udis86sx' }"
+
+"{ NameSpace: Smalltalk }"
+
+Object subclass:#UDIS86
+	instanceVariableNames:'handle buffer'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'UDIS86'
+!
+
+!UDIS86 primitiveDefinitions!
+%{
+
+/*
+ * includes, defines, structure definitions
+ * and typedefs come here.
+ */
+
+#include <udis86.h>
+
+#define ud ((ud_t*)(&__byteArrayVal( __INST(handle) )))
+
+%}
+! !
+
+!UDIS86 class methodsFor:'documentation'!
+
+documentation
+"
+    Intel X86 disassembler for both i386 and x86_64 code.
+    Based on Vivek Thampi's udis86 C library
+
+    [author:]
+        Jan Vrany <jan.vrany@fit.cvut.cz>
+
+    [instance variables:]
+
+    [class variables:]
+
+    [see also:]
+        udis86 https://github.com/vmt/udis86
+
+"
+! !
+
+!UDIS86 class methodsFor:'instance creation'!
+
+new
+    "return an initialized instance"
+
+    ^ self basicNew initialize.
+! !
+
+!UDIS86 class methodsFor:'examples'!
+
+example1
+    | code disas insn |
+
+    code := #[ 16r81 16rc3 16r9d 16r12 16r00 16r00  "/ add    $0x129d,%ebx
+               16r68 16r40 16r94 16r04 16r08        "/ push   $0x8049440
+               16re8 16r6f 16rfe 16rff 16rff        "/  call   8048310
+            ]. 
+    disas := UDIS86 new.
+    disas buffer: code pc: 16r00FF0000.
+
+    "/ Disassemble the code, print assembly
+    "/ on Transcript
+    [ (insn := disas disassemble) notNil ] whileTrue:[
+        Transcript showCR: insn printString.
+    ]
+
+    "
+    UDIS86 example1
+    "
+
+    "Created: / 10-12-2015 / 16:54:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 11-12-2015 / 21:30:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!UDIS86 class methodsFor:'utilities'!
+
+disassemble: buffer on: stream
+    self disassemble: buffer pc: 0 on: stream
+
+    "Created: / 11-12-2015 / 10:15:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 11-12-2015 / 21:32:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+disassemble: buffer pc: pc on: stream
+    | disasm insn |
+
+    disasm := UDIS86 new.
+    disasm buffer: buffer pc: pc.
+    [ (insn := disasm disassemble) notNil ] whileTrue:[ 
+        stream nextPutLine: insn printString
+    ].
+
+    "Created: / 11-12-2015 / 21:32:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!UDIS86 methodsFor:'accessing'!
+
+buffer: aByteArrayOrExternalBytes
+    "Set the input buffer containing instructions for
+     disassembling."
+
+    | buff pc |
+
+    buff := aByteArrayOrExternalBytes asExternalBytes.
+    aByteArrayOrExternalBytes isExternalBytes ifTrue:[ 
+        pc := aByteArrayOrExternalBytes address.
+    ].
+    self buffer: buff pc: pc
+
+    "Created: / 09-12-2015 / 22:54:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 11-12-2015 / 16:10:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+buffer: aByteArray pc: anInteger
+    "Set the input buffer containing instructions for
+     disassembling."
+
+    | bufferLen pc |
+
+    buffer := aByteArray asExternalBytes.
+    bufferLen := buffer size.
+    pc := anInteger ? 0.
+%{
+    if ( __isExternalAddressLike( _INST( buffer ) ) &&
+         __isSmallInteger( bufferLen ) &&
+         __isSmallInteger( pc ) ) {
+        ud_set_input_buffer(ud, __externalAddressVal( __INST( buffer ) ), __intVal( bufferLen ) );
+        ud_set_pc(ud, __intVal( pc ) );
+        RETURN ( self );
+    }
+%}.
+    self primitiveFailed
+
+    "Created: / 11-12-2015 / 16:07:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 11-12-2015 / 21:20:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+mode: anInteger
+    "Sets the mode of disassembly. Possible values are 16, 32, and 64. 
+     By default it uses 32bit mode when running VM is 32bit, 64bit if
+     it's 64bit one"
+
+    self assert: (#(16 32 64) includes: anInteger).
+%{
+    ud_set_mode( ud, __intVal ( anInteger ) );
+%}.
+
+    "Created: / 09-12-2015 / 23:01:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+useSyntaxATT
+    "Sets AT&T syntax for assembly.
+     See http://www.imada.sdu.dk/Courses/DM18/Litteratur/IntelnATT.htm"
+%{
+    ud_set_syntax ( ud, UD_SYN_ATT );
+%}
+
+    "Created: / 10-12-2015 / 21:34:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+useSyntaxIntel
+    "Sets Intel syntax for assembly.
+     See http://www.imada.sdu.dk/Courses/DM18/Litteratur/IntelnATT.htm"
+%{
+    ud_set_syntax ( ud, UD_SYN_INTEL );
+%}
+
+    "Created: / 10-12-2015 / 21:33:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!UDIS86 methodsFor:'disassembling'!
+
+disassemble
+    "Disassembles the next instruction in the input buffer/stream.
+     Returns the number of bytes disassembled. A 0 indicates end of input."
+
+    | pc opcodeCode assembly |
+%{
+    if (! ud_disassemble ( ud ) ) { 
+        RETURN (nil);
+    }
+    opcodeCode = __MKSMALLINT( ud_insn_mnemonic ( ud ) );
+    assembly = __MKSTRING( ud_insn_asm ( ud ) );
+    pc = __MKSMALLINT( ud_insn_off ( ud ) );
+%}.
+    ^ UDIS86Instruction new
+        setAssembly: assembly;
+        setPC: pc;
+        setOpcodeCode: opcodeCode;    
+
+        yourself.
+
+    "Created: / 09-12-2015 / 22:57:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 11-12-2015 / 21:23:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!UDIS86 methodsFor:'initialization'!
+
+initialize
+    | handleSize |
+
+%{
+    handleSize = __MKSMALLINT( sizeof( ud_t ) );
+%}.
+    handle := ByteArray new: handleSize.
+%{
+    ud_init( ud );
+    ud_set_syntax ( ud, UD_SYN_INTEL );
+%}.
+    ExternalAddress pointerSize == 8 ifTrue:[ 
+        self mode: 64.
+    ] ifFalse:[ 
+        self mode: 32.
+    ].
+
+    "
+    UDIS86 new
+    "
+
+    "Modified: / 10-12-2015 / 21:26:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!UDIS86 class methodsFor:'documentation'!
+
+version_HG
+
+    ^ '$Changeset: <not expanded> $'
+! !
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/udis86sx/UDIS86Instruction.st	Thu Dec 10 08:47:42 2015 +0000
@@ -0,0 +1,55 @@
+"{ Package: 'jv:dragonfly/udis86sx' }"
+
+"{ NameSpace: Smalltalk }"
+
+Object subclass:#UDIS86Instruction
+	instanceVariableNames:'pc len assembly opcodeCode'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'UDIS86'
+!
+
+
+!UDIS86Instruction methodsFor:'accessing'!
+
+assembly
+    ^ assembly
+! !
+
+!UDIS86Instruction methodsFor:'initialization'!
+
+setAssembly: aString
+    assembly := aString.
+
+    "Created: / 10-12-2015 / 17:04:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+setOpcodeCode: anInteger
+    opcodeCode := anInteger
+
+    "Created: / 10-12-2015 / 21:12:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+setPC: anInteger
+    pc := anInteger
+
+    "Created: / 10-12-2015 / 16:55:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!UDIS86Instruction methodsFor:'printing'!
+
+printOn: aStream
+    pc printOn: aStream base: 16 size: ExternalAddress pointerSize * 2 fill: $0.
+    aStream space.
+    aStream nextPutAll: assembly
+
+    "Created: / 11-12-2015 / 21:30:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!UDIS86Instruction class methodsFor:'documentation'!
+
+version_HG
+
+    ^ '$Changeset: <not expanded> $'
+! !
+
--- a/udis86sx/abbrev.stc	Tue Dec 08 08:55:42 2015 +0000
+++ b/udis86sx/abbrev.stc	Thu Dec 10 08:47:42 2015 +0000
@@ -1,4 +1,6 @@
 # automagically generated by the project definition
 # this file is needed for stc to be able to compile modules independently.
 # it provides information about a classes filename, category and especially namespace.
+UDIS86 UDIS86 jv:dragonfly/udis86sx 'UDIS86' 0
+UDIS86Instruction UDIS86Instruction jv:dragonfly/udis86sx 'UDIS86' 0
 jv_dragonfly_udis86sx jv_dragonfly_udis86sx jv:dragonfly/udis86sx '* Projects & Packages *' 3
--- a/udis86sx/bc.mak	Tue Dec 08 08:55:42 2015 +0000
+++ b/udis86sx/bc.mak	Thu Dec 10 08:47:42 2015 +0000
@@ -35,7 +35,7 @@
 
 
 
-LOCALINCLUDES= -I$(INCLUDE_TOP)\stx\libbasic
+LOCALINCLUDES=-Iudis86 -I$(INCLUDE_TOP)\stx\libbasic
 LOCALDEFINES=
 
 STCLOCALOPT=-package=$(PACKAGE) -I. $(LOCALINCLUDES) -headerDir=. $(STCLOCALOPTIMIZATIONS) $(STCWARNINGS) $(LOCALDEFINES)  -varPrefix=$(LIBNAME)
@@ -68,6 +68,8 @@
 
 
 # BEGINMAKEDEPEND --- do not remove this line; make depend needs it
+$(OUTDIR)UDIS86.$(O) UDIS86.$(H): UDIS86.st $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
+$(OUTDIR)UDIS86Instruction.$(O) UDIS86Instruction.$(H): UDIS86Instruction.st $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(STCHDR)
 $(OUTDIR)jv_dragonfly_udis86sx.$(O) jv_dragonfly_udis86sx.$(H): jv_dragonfly_udis86sx.st $(INCLUDE_TOP)\stx\libbasic\LibraryDefinition.$(H) $(INCLUDE_TOP)\stx\libbasic\Object.$(H) $(INCLUDE_TOP)\stx\libbasic\ProjectDefinition.$(H) $(STCHDR)
 
 # ENDMAKEDEPEND --- do not remove this line
--- a/udis86sx/jv_dragonfly_udis86sx.st	Tue Dec 08 08:55:42 2015 +0000
+++ b/udis86sx/jv_dragonfly_udis86sx.st	Thu Dec 10 08:47:42 2015 +0000
@@ -85,6 +85,16 @@
     )
 ! !
 
+!jv_dragonfly_udis86sx class methodsFor:'description - compilation'!
+
+localIncludes
+    "allow for the specification of additional include directories"
+
+    ^ '-Iudis86'
+
+    "Created: / 10-12-2015 / 16:46:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !jv_dragonfly_udis86sx class methodsFor:'description - contents'!
 
 classNamesAndAttributes
@@ -95,6 +105,8 @@
 
     ^ #(
         "<className> or (<className> attributes...) in load order"
+        UDIS86
+        UDIS86Instruction
         #'jv_dragonfly_udis86sx'
     )
 !
--- a/udis86sx/libInit.cc	Tue Dec 08 08:55:42 2015 +0000
+++ b/udis86sx/libInit.cc	Thu Dec 10 08:47:42 2015 +0000
@@ -27,6 +27,8 @@
 void _libjv_dragonfly_udis86sx_Init(pass, __pRT__, snd)
 OBJ snd; struct __vmData__ *__pRT__; {
 __BEGIN_PACKAGE2__("libjv_dragonfly_udis86sx", _libjv_dragonfly_udis86sx_Init, "jv:dragonfly/udis86sx");
+_UDIS86_Init(pass,__pRT__,snd);
+_UDIS86Instruction_Init(pass,__pRT__,snd);
 _jv_137dragonfly_137udis86sx_Init(pass,__pRT__,snd);