Skip to content

Commit

Permalink
Add ffmasm-disassebler
Browse files Browse the repository at this point in the history
  • Loading branch information
YaSuenag committed Jan 13, 2025
1 parent 9b06c4c commit 81f74fc
Show file tree
Hide file tree
Showing 6 changed files with 420 additions and 0 deletions.
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,44 @@ NOTE: [Linker.Option.critical()](https://docs.oracle.com/en/java/javase/22/docs/
int ret = (int)method.invoke(100); // "ret" should be 100
```

# Debugging

[ffmasm-disassembler](tools/disas) can disassemble the code in `MemorySegment` like generated by ffmasm, and dump assembly code to stdout.

You can download ffmasm-dissassembler Maven package from GitHub packages: https://github.com/YaSuenag/ffmasm/packages/2370043

See [examples/disas](examples/disas) for details.

## Requirements

ffmasm-disassembler requires [hsdis](https://github.com/openjdk/jdk/tree/master/src/utils/hsdis).

## Generate hsdis

To generate hsdis for Linux, you can use [hsdis-builder](https://github.com/YaSuenag/hsdis-builder).

## Deploy hsdis

It should be deployed one of following directory (it is documented as source comment in disassembler.cpp in HotSpot):

1. `$JAVA_HOME/lib/<vm>/libhsdis-<arch>.so`
2. `$JAVA_HOME/lib/<vm>/hsdis-<arch>.so`
3. `$JAVA_HOME/lib/hsdis-<arch>.so`
4. `hsdis-<arch>.so` (using `LD_LIBRARY_PATH`)

If you don't want to deploy hsdis into your JDK, you can specify `hsdis` system property like `-Dhsdis=/path/to/hsdis-amd64.so`

## Examples

```
import com.yasuenag.ffmasmtools.disas.Disassembler;
: <snip>
MemorySegment rdtsc = createRDTSC(); // Generate machine code with ffmasm
Disassembler.dumpToStdout(rdtsc); // Dump assembly code of `rdtsc` to stdout
```

# Play with JNI

You can bind native method to `MemorySegment` of ffmasm code dynamically.
Expand Down
97 changes: 97 additions & 0 deletions examples/disas/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>

<!--
Copyright (C) 2025, Yasumasa Suenaga
This file is part of ffmasm.
ffmasm is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ffmasm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public Licensealong with ffmasm. If not, see <http://www.gnu.org/licenses/>.
-->

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.yasuenag</groupId>
<artifactId>ffmasm-disas-example</artifactId>
<version>0.1.0</version>
<packaging>jar</packaging>

<name>ffmasm-disas-example</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mainClass>com.yasuenag.ffmasm.examples.disas.Main</mainClass>
<imageName>${project.artifactId}-${project.version}</imageName>
<maven.compiler.source>22</maven.compiler.source>
<maven.compiler.target>22</maven.compiler.target>
</properties>

<repositories>
<repository>
<id>github</id>
<url>https://maven.pkg.github.com/YaSuenag/ffmasm</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>com.yasuenag</groupId>
<artifactId>ffmasm</artifactId>
<version>0.5.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.yasuenag</groupId>
<artifactId>ffmasm-disassembler</artifactId>
<version>0.1.0</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<compilerArgs>
<arg>-Xlint:all</arg>
</compilerArgs>
<debug>true</debug>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<archive>
<manifest>
<mainClass>${mainClass}</mainClass>
</manifest>
<manifestEntries>
<Enable-Native-Access>ALL-UNNAMED</Enable-Native-Access>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<mainClass>${mainClass}</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2025 Yasumasa Suenaga
*
* This file is part of ffmasm.
*
* ffmasm is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ffmasm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with ffmasm. If not, see <http://www.gnu.org/licenses/>.
*/
package com.yasuenag.ffmasm.examples.disas;

import java.lang.foreign.*;
import java.util.*;

import com.yasuenag.ffmasm.*;
import com.yasuenag.ffmasm.amd64.*;

import com.yasuenag.ffmasmtools.disas.Disassembler;


public class Main{

public static MemorySegment createRDTSC() throws Exception{
var seg = new CodeSegment();
return AMD64AsmBuilder.create(AMD64AsmBuilder.class, seg)
/* push %rbp */ .push(Register.RBP)
/* mov %rsp, %rbp */ .movMR(Register.RSP, Register.RBP, OptionalInt.empty())
/* rdtsc */ .rdtsc()
/* shl $32, %rdx */ .shl(Register.RDX, (byte)32, OptionalInt.empty())
/* or %rdx, %rax */ .orMR(Register.RDX, Register.RAX, OptionalInt.empty())
/* leave */ .leave()
/* ret */ .ret()
.getMemorySegment();
}

public static void main(String[] args) throws Exception{
var rdtsc = createRDTSC();
Disassembler.dumpToStdout(rdtsc);
}

}
80 changes: 80 additions & 0 deletions tools/disas/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>

<!--
Copyright (C) 2025, Yasumasa Suenaga
This file is part of ffmasm.
ffmasm is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ffmasm is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with ffmasm. If not, see <http://www.gnu.org/licenses/>.
-->

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.yasuenag</groupId>
<artifactId>ffmasm-disassembler</artifactId>
<version>0.1.0</version>
<packaging>jar</packaging>

<name>ffmasm-disassembler</name>

<scm>
<connection>scm:git:git://github.com/YaSuenag/ffmasm.git</connection>
<developerConnection>scm:git:ssh://github.com:YaSuenag/ffmasm.git</developerConnection>
<url>https://github.com/YaSuenag/ffmasm</url>
</scm>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>22</maven.compiler.source>
<maven.compiler.target>22</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>com.yasuenag</groupId>
<artifactId>ffmasm</artifactId>
<version>0.5.0-SNAPSHOT</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<compilerArgs>
<arg>-Xlint:all</arg>
</compilerArgs>
<debug>true</debug>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.4.1</version>
</plugin>
</plugins>
</build>

<distributionManagement>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/YaSuenag/ffmasm</url>
</repository>
</distributionManagement>
</project>
Loading

0 comments on commit 81f74fc

Please sign in to comment.