diff --git a/core/src/main/java/org/teavm/backend/wasm/dwarf/DwarfConstants.java b/core/src/main/java/org/teavm/backend/wasm/dwarf/DwarfConstants.java index cf15571ba..0716711f1 100644 --- a/core/src/main/java/org/teavm/backend/wasm/dwarf/DwarfConstants.java +++ b/core/src/main/java/org/teavm/backend/wasm/dwarf/DwarfConstants.java @@ -21,6 +21,7 @@ public final class DwarfConstants { public static final int DW_UT_COMPILE = 0x01; public static final int DW_TAG_COMPILE_UNIT = 0x11; + public static final int DW_TAG_SUBPROGRAM = 0x2E; public static final int DW_AT_NAME = 0x03; public static final int DW_AT_STMT_LIST = 0x10; diff --git a/core/src/main/java/org/teavm/backend/wasm/dwarf/blob/BlobReader.java b/core/src/main/java/org/teavm/backend/wasm/dwarf/blob/BlobReader.java index 6d4eaaff4..96bb14554 100644 --- a/core/src/main/java/org/teavm/backend/wasm/dwarf/blob/BlobReader.java +++ b/core/src/main/java/org/teavm/backend/wasm/dwarf/blob/BlobReader.java @@ -48,7 +48,7 @@ public class BlobReader { var offsetInChunk = this.offsetInChunk; while (ptr < to) { var chunk = blob.chunkAt(currentChunk); - var limit = Math.min(ptr + chunk.length, to); + var limit = Math.min(ptr + chunk.length - offsetInChunk, to); var bytesToWrite = limit - ptr; consumer.accept(chunk, offsetInChunk, offsetInChunk + bytesToWrite); offsetInChunk += bytesToWrite; diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/DwarfGenerator.java b/core/src/main/java/org/teavm/backend/wasm/generate/DwarfGenerator.java index 295f7e145..60144bd54 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/DwarfGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/DwarfGenerator.java @@ -30,7 +30,7 @@ import org.teavm.backend.wasm.model.WasmCustomSection; public class DwarfGenerator { private DwarfInfoWriter infoWriter = new DwarfInfoWriter(); private DwarfPlaceholder endOfSection; - private DwarfStrings strings = new DwarfStrings(); + public final DwarfStrings strings = new DwarfStrings(); private DwarfStrings lineStrings = new DwarfStrings(); private DwarfLinesGenerator lines = new DwarfLinesGenerator(lineStrings); private Marker highPcMarker; @@ -89,8 +89,10 @@ public class DwarfGenerator { } public void setCodeSize(int codeSize) { + var backup = infoWriter.marker(); highPcMarker.rewind(); infoWriter.writeInt(codeSize); + backup.rewind(); } public Collection createSections() { @@ -119,4 +121,8 @@ public class DwarfGenerator { public void lineNumber(int address, String fileName, int lineNumber) { lines.lineNumber(address, fileName, lineNumber); } + + public DwarfInfoWriter getInfoWriter() { + return infoWriter; + } } diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/DwarfStrings.java b/core/src/main/java/org/teavm/backend/wasm/generate/DwarfStrings.java index 3abf78320..de477bb8a 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/DwarfStrings.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/DwarfStrings.java @@ -20,11 +20,11 @@ import com.carrotsearch.hppc.ObjectIntMap; import java.nio.charset.StandardCharsets; import org.teavm.backend.wasm.dwarf.blob.Blob; -class DwarfStrings { +public class DwarfStrings { final Blob blob = new Blob(); private ObjectIntMap offsets = new ObjectIntHashMap<>(); - int stringRef(String s) { + public int stringRef(String s) { int ptr = offsets.getOrDefault(s, -1); if (ptr < 0) { ptr = blob.size(); diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderer.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderer.java index 020e44267..ac1e33d2d 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderer.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderer.java @@ -15,6 +15,7 @@ */ package org.teavm.backend.wasm.render; +import static org.teavm.backend.wasm.dwarf.DwarfConstants.DW_TAG_SUBPROGRAM; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -23,6 +24,9 @@ import java.util.List; import java.util.Map; import java.util.function.Supplier; import java.util.stream.Collectors; +import org.teavm.backend.wasm.dwarf.DwarfAbbreviation; +import org.teavm.backend.wasm.dwarf.DwarfConstants; +import org.teavm.backend.wasm.dwarf.DwarfInfoWriter; import org.teavm.backend.wasm.generate.DwarfGenerator; import org.teavm.backend.wasm.model.WasmCustomSection; import org.teavm.backend.wasm.model.WasmFunction; @@ -55,6 +59,8 @@ public class WasmBinaryRenderer { private Map functionIndexes = new HashMap<>(); private boolean obfuscated; private DwarfGenerator dwarfGenerator; + private DwarfInfoWriter infoWriter; + private DwarfAbbreviation methodAbbrev; public WasmBinaryRenderer(WasmBinaryWriter output, WasmBinaryVersion version, boolean obfuscated, DwarfGenerator dwarfGenerator) { @@ -62,6 +68,7 @@ public class WasmBinaryRenderer { this.version = version; this.obfuscated = obfuscated; this.dwarfGenerator = dwarfGenerator; + infoWriter = dwarfGenerator != null ? dwarfGenerator.getInfoWriter() : null; } public void render(WasmModule module) { @@ -317,9 +324,28 @@ public class WasmBinaryRenderer { } code.writeByte(0x0B); + if (dwarfGenerator != null && function.getName() != null) { + infoWriter.tag(getMethodAbbrev()); + infoWriter.writeInt(dwarfGenerator.strings.stringRef(function.getName())); + infoWriter.writeInt(offset); + infoWriter.writeInt(offset + code.getPosition()); + infoWriter.emptyTag(); + } + return code.getData(); } + private DwarfAbbreviation getMethodAbbrev() { + if (methodAbbrev == null) { + methodAbbrev = infoWriter.abbreviation(DW_TAG_SUBPROGRAM, true, data -> { + data.writeLEB(DwarfConstants.DW_AT_NAME).writeLEB(DwarfConstants.DW_FORM_STRP); + data.writeLEB(DwarfConstants.DW_AT_LOW_PC).writeLEB(DwarfConstants.DW_FORM_ADDR); + data.writeLEB(DwarfConstants.DW_AT_HIGH_PC).writeLEB(DwarfConstants.DW_FORM_ADDR); + }); + } + return methodAbbrev; + } + private void renderInitializer(WasmBinaryWriter output, int value) { output.writeByte(0x41); output.writeLEB(value);