package com.oracle.objectfile.elf.dwarf;
import com.oracle.objectfile.LayoutDecision;
import com.oracle.objectfile.debugentry.ClassEntry;
import com.oracle.objectfile.debugentry.PrimaryEntry;
import com.oracle.objectfile.debugentry.Range;
import org.graalvm.compiler.debug.DebugContext;
import java.util.LinkedList;
import static com.oracle.objectfile.elf.dwarf.DwarfDebugInfo.DW_ABBREV_CODE_compile_unit_1;
import static com.oracle.objectfile.elf.dwarf.DwarfDebugInfo.DW_ABBREV_CODE_compile_unit_2;
import static com.oracle.objectfile.elf.dwarf.DwarfDebugInfo.DW_ABBREV_CODE_subprogram;
import static com.oracle.objectfile.elf.dwarf.DwarfDebugInfo.DW_ABBREV_SECTION_NAME;
import static com.oracle.objectfile.elf.dwarf.DwarfDebugInfo.DW_FLAG_true;
import static com.oracle.objectfile.elf.dwarf.DwarfDebugInfo.DW_INFO_SECTION_NAME;
import static com.oracle.objectfile.elf.dwarf.DwarfDebugInfo.DW_LANG_Java;
import static com.oracle.objectfile.elf.dwarf.DwarfDebugInfo.DW_VERSION_2;
public class DwarfInfoSectionImpl extends DwarfSectionImpl {
private static final int = 11;
public DwarfInfoSectionImpl(DwarfDebugInfo dwarfSections) {
super(dwarfSections);
}
@Override
public String getSectionName() {
return DW_INFO_SECTION_NAME;
}
@Override
public void createContent() {
byte[] buffer = null;
int pos = 0;
for (ClassEntry classEntry : getPrimaryClasses()) {
int lengthPos = pos;
pos = writeCUHeader(buffer, pos);
assert pos == lengthPos + DW_DIE_HEADER_SIZE;
pos = writeCU(null, classEntry, false, buffer, pos);
}
for (ClassEntry classEntry : getPrimaryClasses()) {
if (classEntry.includesDeoptTarget()) {
int lengthPos = pos;
pos = writeCUHeader(buffer, pos);
assert pos == lengthPos + DW_DIE_HEADER_SIZE;
pos = writeCU(null, classEntry, true, buffer, pos);
}
}
buffer = new byte[pos];
super.setContent(buffer);
}
@Override
public void writeContent(DebugContext context) {
byte[] buffer = getContent();
int size = buffer.length;
int pos = 0;
enableLog(context, pos);
log(context, " [0x%08x] DEBUG_INFO", pos);
log(context, " [0x%08x] size = 0x%08x", pos, size);
for (ClassEntry classEntry : getPrimaryClasses()) {
classEntry.setCUIndex(pos);
int lengthPos = pos;
pos = writeCUHeader(buffer, pos);
log(context, " [0x%08x] Compilation Unit", pos, size);
assert pos == lengthPos + DW_DIE_HEADER_SIZE;
pos = writeCU(context, classEntry, false, buffer, pos);
patchLength(lengthPos, buffer, pos);
}
for (ClassEntry classEntry : getPrimaryClasses()) {
if (classEntry.includesDeoptTarget()) {
classEntry.setDeoptCUIndex(pos);
int lengthPos = pos;
pos = writeCUHeader(buffer, pos);
log(context, " [0x%08x] Compilation Unit (deopt targets)", pos, size);
assert pos == lengthPos + DW_DIE_HEADER_SIZE;
pos = writeCU(context, classEntry, true, buffer, pos);
patchLength(lengthPos, buffer, pos);
}
}
assert pos == size;
}
private int (byte[] buffer, int p) {
int pos = p;
if (buffer == null) {
pos += putInt(0, scratch, 0);
pos += putShort(DW_VERSION_2, scratch, 0);
pos += putInt(0, scratch, 0);
return pos + putByte((byte) 8, scratch, 0);
} else {
pos = putInt(0, buffer, pos);
pos = putShort(DW_VERSION_2, buffer, pos);
pos = putInt(0, buffer, pos);
return putByte((byte) 8, buffer, pos);
}
}
private static int findLo(LinkedList<PrimaryEntry> classPrimaryEntries, boolean isDeoptTargetCU) {
if (!isDeoptTargetCU) {
return classPrimaryEntries.getFirst().getPrimary().getLo();
} else {
for (PrimaryEntry primaryEntry : classPrimaryEntries) {
Range range = primaryEntry.getPrimary();
if (range.isDeoptTarget()) {
return range.getLo();
}
}
}
assert false;
return 0;
}
private static int findHi(LinkedList<PrimaryEntry> classPrimaryEntries, boolean includesDeoptTarget, boolean isDeoptTargetCU) {
if (isDeoptTargetCU || !includesDeoptTarget) {
return classPrimaryEntries.getLast().getPrimary().getHi();
} else {
int hi = 0;
for (PrimaryEntry primaryEntry : classPrimaryEntries) {
Range range = primaryEntry.getPrimary();
if (!range.isDeoptTarget()) {
hi = range.getHi();
} else {
return hi;
}
}
}
assert false;
return 0;
}
private int writeCU(DebugContext context, ClassEntry classEntry, boolean isDeoptTargetCU, byte[] buffer, int p) {
int pos = p;
LinkedList<PrimaryEntry> classPrimaryEntries = classEntry.getPrimaryEntries();
int lineIndex = classEntry.getLineIndex();
int abbrevCode = (lineIndex >= 0 ? DW_ABBREV_CODE_compile_unit_1 : DW_ABBREV_CODE_compile_unit_2);
log(context, " [0x%08x] <0> Abbrev Number %d", pos, abbrevCode);
pos = writeAbbrevCode(abbrevCode, buffer, pos);
log(context, " [0x%08x] language %s", pos, "DW_LANG_Java");
pos = writeAttrData1(DW_LANG_Java, buffer, pos);
log(context, " [0x%08x] name 0x%x (%s)", pos, debugStringIndex(classEntry.getFileName()), classEntry.getFileName());
pos = writeAttrStrp(classEntry.getFileName(), buffer, pos);
String compilationDirectory = classEntry.getCachePath();
log(context, " [0x%08x] comp_dir 0x%x (%s)", pos, debugStringIndex(compilationDirectory), compilationDirectory);
pos = writeAttrStrp(compilationDirectory, buffer, pos);
int lo = findLo(classPrimaryEntries, isDeoptTargetCU);
int hi = findHi(classPrimaryEntries, classEntry.includesDeoptTarget(), isDeoptTargetCU);
log(context, " [0x%08x] lo_pc 0x%08x", pos, lo);
pos = writeAttrAddress(lo, buffer, pos);
log(context, " [0x%08x] hi_pc 0x%08x", pos, hi);
pos = writeAttrAddress(hi, buffer, pos);
if (abbrevCode == DW_ABBREV_CODE_compile_unit_1) {
log(context, " [0x%08x] stmt_list 0x%08x", pos, lineIndex);
pos = writeAttrData4(lineIndex, buffer, pos);
}
for (PrimaryEntry primaryEntry : classPrimaryEntries) {
Range range = primaryEntry.getPrimary();
if (isDeoptTargetCU == range.isDeoptTarget()) {
pos = writePrimary(context, range, buffer, pos);
}
}
return writeAttrNull(buffer, pos);
}
private int writePrimary(DebugContext context, Range range, byte[] buffer, int p) {
int pos = p;
verboseLog(context, " [0x%08x] <1> Abbrev Number %d", pos, DW_ABBREV_CODE_subprogram);
pos = writeAbbrevCode(DW_ABBREV_CODE_subprogram, buffer, pos);
verboseLog(context, " [0x%08x] name 0x%X (%s)", pos, debugStringIndex(range.getFullMethodName()), range.getFullMethodName());
pos = writeAttrStrp(range.getFullMethodName(), buffer, pos);
verboseLog(context, " [0x%08x] lo_pc 0x%08x", pos, range.getLo());
pos = writeAttrAddress(range.getLo(), buffer, pos);
verboseLog(context, " [0x%08x] hi_pc 0x%08x", pos, range.getHi());
pos = writeAttrAddress(range.getHi(), buffer, pos);
verboseLog(context, " [0x%08x] external true", pos);
return writeFlag(DW_FLAG_true, buffer, pos);
}
private int writeAttrStrp(String value, byte[] buffer, int p) {
int pos = p;
if (buffer == null) {
return pos + putInt(0, scratch, 0);
} else {
int idx = debugStringIndex(value);
return putInt(idx, buffer, pos);
}
}
@SuppressWarnings("unused")
public int writeAttrString(String value, byte[] buffer, int p) {
int pos = p;
if (buffer == null) {
return pos + value.length() + 1;
} else {
return putAsciiStringBytes(value, buffer, pos);
}
}
private static final String TARGET_SECTION_NAME = DW_ABBREV_SECTION_NAME;
@Override
public String targetSectionName() {
return TARGET_SECTION_NAME;
}
private final LayoutDecision.Kind[] targetSectionKinds = {
LayoutDecision.Kind.CONTENT,
LayoutDecision.Kind.OFFSET
};
@Override
public LayoutDecision.Kind[] targetSectionKinds() {
return targetSectionKinds;
}
}