Skip to content

Instantly share code, notes, and snippets.

@apangin
Created December 15, 2021 23:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save apangin/53dfa51bb894580122ceb0814ab1a779 to your computer and use it in GitHub Desktop.
Save apangin/53dfa51bb894580122ceb0814ab1a779 to your computer and use it in GitHub Desktop.
import sun.misc.Unsafe;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
public class SymbolReader {
final ByteBuffer buf;
final long baseAddress;
final int symtab;
final int strings;
SymbolReader(String libName) throws IOException {
List<String> maps = Files.readAllLines(Paths.get("/proc/self/maps"));
String map = maps.stream().filter(s -> s.endsWith(libName)).findFirst().get();
try (FileChannel ch = FileChannel.open(Paths.get(map.substring(map.indexOf('/'))))) {
this.buf = ch.map(FileChannel.MapMode.READ_ONLY, 0, ch.size()).order(ByteOrder.nativeOrder());
}
this.baseAddress = Long.parseUnsignedLong(map.substring(0, map.indexOf('-')), 16);
this.symtab = findSection(2);
this.strings = buf.getInt(section(buf.getInt(symtab + 40)) + 24);
}
int section(int n) {
return buf.getInt(40) + (buf.getShort(58) & 0xffff) * n;
}
int findSection(int type) {
int sections = buf.getShort(60) & 0xffff;
for (int i = 0; i < sections; i++) {
int section = section(i);
if (buf.getInt(section + 4) == type) {
return section;
}
}
throw new NoSuchElementException("Section not found: " + type);
}
long findSymbol(String symbolName) {
int symbols = buf.getInt(symtab + 24);
int symbolsEnd = symbols + buf.getInt(symtab + 32);
int entrySize = buf.getInt(symtab + 56);
for (; symbols < symbolsEnd; symbols += entrySize) {
int name = buf.getInt(symbols);
long value = buf.getLong(symbols + 8);
if (name != 0 && value != 0 && strcmp(strings + name, symbolName)) {
return baseAddress + value;
}
}
throw new NoSuchElementException("Symbol not found: " + symbolName);
}
boolean strcmp(int pos, String str) {
int length = str.length();
for (int i = 0; i < length; i++) {
if (buf.get(pos++) != str.charAt(i)) {
return false;
}
}
return buf.get(pos) == 0;
}
static Unsafe getUnsafe() throws ReflectiveOperationException {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe) f.get(null);
}
static void eatAllMemory() {
ArrayList<Object> list = new ArrayList();
try {
while (true) {
list.add(new byte[1024 * 1024]);
}
} catch (OutOfMemoryError e) {
list = null;
}
}
public static void main(String[] args) throws Exception {
Unsafe unsafe = getUnsafe();
long addr = new SymbolReader("/libjvm.so")
.findSymbol("_ZZ25report_java_out_of_memoryPKcE22out_of_memory_reported");
System.out.println("OOM reported = " + unsafe.getInt(addr));
eatAllMemory();
System.out.println("OOM reported = " + unsafe.getInt(addr));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment