# HG changeset patch # User Jan Vrany # Date 1449737262 0 # Node ID aa002d0c231bc65432becad196ccaa894f1369e4 # Parent e4a716697bef84f8eca1775fe51cf7077648dca2 Initial support for disassembling diff -r e4a716697bef -r aa002d0c231b udis86sx/Make.proto --- 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 diff -r e4a716697bef -r aa002d0c231b udis86sx/Make.spec --- 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) \ diff -r e4a716697bef -r aa002d0c231b udis86sx/UDIS86.st --- /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 + +#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 + + [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 " + "Modified: / 11-12-2015 / 21:30:33 / Jan Vrany " +! ! + +!UDIS86 class methodsFor:'utilities'! + +disassemble: buffer on: stream + self disassemble: buffer pc: 0 on: stream + + "Created: / 11-12-2015 / 10:15:49 / Jan Vrany " + "Modified: / 11-12-2015 / 21:32:22 / Jan Vrany " +! + +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 " +! ! + +!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 " + "Modified: / 11-12-2015 / 16:10:57 / Jan Vrany " +! + +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 " + "Modified: / 11-12-2015 / 21:20:54 / Jan Vrany " +! + +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 " +! + +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 " +! + +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 " +! ! + +!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 " + "Modified: / 11-12-2015 / 21:23:00 / Jan Vrany " +! ! + +!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 " +! ! + +!UDIS86 class methodsFor:'documentation'! + +version_HG + + ^ '$Changeset: $' +! ! + diff -r e4a716697bef -r aa002d0c231b udis86sx/UDIS86Instruction.st --- /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 " +! + +setOpcodeCode: anInteger + opcodeCode := anInteger + + "Created: / 10-12-2015 / 21:12:58 / Jan Vrany " +! + +setPC: anInteger + pc := anInteger + + "Created: / 10-12-2015 / 16:55:40 / Jan Vrany " +! ! + +!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 " +! ! + +!UDIS86Instruction class methodsFor:'documentation'! + +version_HG + + ^ '$Changeset: $' +! ! + diff -r e4a716697bef -r aa002d0c231b udis86sx/abbrev.stc --- 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 diff -r e4a716697bef -r aa002d0c231b udis86sx/bc.mak --- 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 diff -r e4a716697bef -r aa002d0c231b udis86sx/jv_dragonfly_udis86sx.st --- 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 " +! ! + !jv_dragonfly_udis86sx class methodsFor:'description - contents'! classNamesAndAttributes @@ -95,6 +105,8 @@ ^ #( " or ( attributes...) in load order" + UDIS86 + UDIS86Instruction #'jv_dragonfly_udis86sx' ) ! diff -r e4a716697bef -r aa002d0c231b udis86sx/libInit.cc --- 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);