Skip to content

Instantly share code, notes, and snippets.

@benolee
Last active April 13, 2023 23:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benolee/ff515f4cfcf7e5c70ef634db35146779 to your computer and use it in GitHub Desktop.
Save benolee/ff515f4cfcf7e5c70ef634db35146779 to your computer and use it in GitHub Desktop.

why can't I run a dex file in a statically linked linux x64 native elf dalvik vm?

I want to run a dex file in a simple dalvik vm runtime for x86_64…but how?

trying out a simple dvm. there are a few old projects that I couldn't get to work. I will probably try this out at some point: https://github.com/jserv/simple-dvm

dvm

  1. java hello world ugh
$ cat Hello.java
package com.gordea.dvm;
public class Hello {
  public static void main(String[] args) {
    System.out.println("hello world!!!!");
  }
}
  1. compile java to class file. dalvik is super picky about supporting only java 7 class file so make it use java 7 target.
$ javac -source 1.7 -target 1.7 -d . src/com/gordea/dvm/Hello.java  # dalvik doesn't support newer class file versions

$  javap -c com/gordea/dvm/Hello.class
Compiled from "Hello.java"
public class com.gordea.dvm.Hello {
  public com.gordea.dvm.Hello();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #3                  // String hello world!!!!
       5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}

class to dex

02 dex file format.png

02 dex file format.png

dex file header and format structs

typedef struct _DexHeader {
    u1 magic[8]; /* includes version number */
    u1 checksum[4]; /* adler32 checksum */
    u1 signature[20]; /* SHA-1 hash */
    u4 fileSize; /* length of entire file */
    u4 headerSize; /* offset to start of next section */
    u4 endianTag;
    u4 linkSize;
    u4 linkOff;
    u4 mapOff;
    u4 stringIdsSize;
    u4 stringIdsOff;
    u4 typeIdsSize;
    u4 typeIdsOff;
    u4 protoIdsSize;
    u4 protoIdsOff;
    u4 fieldIdsSize;
    u4 fieldIdsOff;
    u4 methodIdsSize;
    u4 methodIdsOff;
    u4 classDefsSize;
    u4 classDefsOff;
    u4 dataSize;
    u4 dataOff;
} DexHeader;

typedef struct DexFileFormat {
    DexHeader header;
    string_ids       *string_ids;
    string_data_item *string_data_item;
    type_id_item     *type_id_item;
    proto_id_item    *proto_id_item;
    type_list        *proto_type_list;
    field_id_item    *field_id_item;
    method_id_item   *method_id_item;
    class_def_item   *class_def_item;
    class_data_item  *class_data_item;
    map_list         map_list;
    type_list        type_list;
    u1               *data;
} DexFileFormat;
  1. compile class file to dex using android sdk
$ dx --dex --output=classes.dex com/gordea/dvm/Hello.class

$ dexdump classes.dex
dexdump classes.dex
Processing 'classes.dex'...
Opened 'classes.dex', DEX version '035'
Class #0            -
  Class descriptor  : 'Lcom/gordea/dvm/Hello;'
  Access flags      : 0x0001 (PUBLIC)
  Superclass        : 'Ljava/lang/Object;'
  Interfaces        -
  Static fields     -
  Instance fields   -
  Direct methods    -
    #0              : (in Lcom/gordea/dvm/Hello;)
      name          : '<init>'
      type          : '()V'
      access        : 0x10001 (PUBLIC CONSTRUCTOR)
      code          -
      registers     : 1
      ins           : 1
      outs          : 1
      insns size    : 4 16-bit code units
      catches       : (none)
      positions     :
        0x0000 line=22
      locals        :
        0x0000 - 0x0004 reg=0 this Lcom/gordea/dvm/Hello;
    #1              : (in Lcom/gordea/dvm/Hello;)
      name          : 'main'
      type          : '([Ljava/lang/String;)V'
      access        : 0x0009 (PUBLIC STATIC)
      code          -
      registers     : 3
      ins           : 1
      outs          : 2
      insns size    : 8 16-bit code units
      catches       : (none)
      positions     :
        0x0000 line=25
        0x0007 line=26
      locals        :
        0x0000 - 0x0008 reg=2 (null) [Ljava/lang/String;
  Virtual methods   -
  source_file_idx   : 1 (Hello.java)
  1. run dex in simple dalvik vm
$ ./dvm classes.dex
parse map_list offset = 025c
map_list size = 13
parse string ids offset = 0070
parse type ids offset = 00a8
parse proto ids offset = 00c4
 proto_typ_list[1] offset 0x55ecacdfd588  proto_typ_list[2] offset 0x55ecacdfd590 exit parse_proto_ids
parse feild ids offset = 00e8
parse method ids offset = 00f0
parse class defs offset = 0110
Magic Number = 0x64 0x65 0x78 0x0a 0x30 0x33 0x35 0x00 ( dex\n035 )
Checksum      = a4 64 65 d6
HAO
FileSize      =  764 (0x02fc)
headerSize    =  112 (0x0070)
endianTag     = 305419896 (0x12345678)
linkSize      =    0 (0x0000)
mapOff        =  604 (0x025c)
stringIdsSize =   14 (0x000e)
stringIdsOff  =  112 (0x0070)
typeIdsSize   =    7 (0x0007)
typeIdsOff    =  168 (0x00a8)
protoIdsSize  =    3 (0x0003)
protoIdsOff   =  196 (0x00c4)
fieldIdsSize  =    1 (0x0001)
fieldIdsOff   =  232 (0x00e8)
methodIdsSize =    4 (0x0004)
methodIdsOff  =  240 (0x00f0)
classDefsSize =    1 (0x0001)
classDefsOff  =  272 (0x0110)
dataSize      =  460 (0x01cc)
dataOff       =  304 (0x0130)
-------------------------------------
hello world!!!!
-------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment