From 31ed1dad8e2e882f8cf547736475eeb9a4701db3 Mon Sep 17 00:00:00 2001 From: John Dallaway Date: Mon, 3 Jul 2023 15:07:16 +0100 Subject: [PATCH] Support DWARF v5 content form data --- .../.settings/.api_filters | 12 ++ .../eclipse/cdt/utils/debug/dwarf/Dwarf.java | 2 +- .../cdt/utils/debug/dwarf/DwarfConstants.java | 12 +- .../cdt/utils/debug/dwarf/DwarfReader.java | 183 ++++++++++++++---- 4 files changed, 167 insertions(+), 42 deletions(-) diff --git a/core/org.eclipse.cdt.core/.settings/.api_filters b/core/org.eclipse.cdt.core/.settings/.api_filters index 51035270037..e75372b8f80 100644 --- a/core/org.eclipse.cdt.core/.settings/.api_filters +++ b/core/org.eclipse.cdt.core/.settings/.api_filters @@ -13,5 +13,17 @@ + + + + + + + + + + + + diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java index fca32d3f41c..118d3c43dc2 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/Dwarf.java @@ -65,7 +65,7 @@ public class Dwarf implements AutoCloseable { final static String[] DWARF_SCNNAMES = { DWARF_DEBUG_INFO, DWARF_DEBUG_ABBREV, DWARF_DEBUG_ARANGES, DWARF_DEBUG_LINE, DWARF_DEBUG_FRAME, DWARF_EH_FRAME, DWARF_DEBUG_LOC, DWARF_DEBUG_PUBNAMES, DWARF_DEBUG_STR, DWARF_DEBUG_FUNCNAMES, DWARF_DEBUG_TYPENAMES, DWARF_DEBUG_VARNAMES, DWARF_DEBUG_WEAKNAMES, - DWARF_DEBUG_MACINFO }; + DWARF_DEBUG_MACINFO, DWARF_DEBUG_LINE_STR }; final static String[] DWARF_ALT_SCNNAMES = { DWARF_DEBUG_INFO, DWARF_DEBUG_TYPES, DWARF_DEBUG_MACRO, DWARF_DEBUG_STR, }; diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfConstants.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfConstants.java index e1c62cf9a13..29d9965dd90 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfConstants.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfConstants.java @@ -11,7 +11,7 @@ * Contributors: * QNX Software Systems - Initial API and implementation * John Dallaway - Add DW_FORM_line_strp (#198) - * John Dallaway - Add DW_FORM_implicit_const (#443) + * John Dallaway - Add DW_FORM_implicit_const and DW_LNCT codes (#443) *******************************************************************************/ package org.eclipse.cdt.utils.debug.dwarf; @@ -241,6 +241,16 @@ public class DwarfConstants { */ public final static int DW_FORM_GNU_strp_alt = 0x1f21; + /* DWARF v5 content types */ + /** + * @since 8.3 + */ + public final static int DW_LNCT_path = 0x01; /* Null-terminated path name string */ + /** + * @since 8.3 + */ + public final static int DW_LNCT_directory_index = 0x02; /* Index to directories entry */ + /* DWARF location operation encodings. */ public final static int DW_OP_addr = 0x03; /* Constant address. */ public final static int DW_OP_deref = 0x06; diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfReader.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfReader.java index 7eb90327d5e..04602d1cdfa 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfReader.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/debug/dwarf/DwarfReader.java @@ -13,6 +13,7 @@ * Ling Wang (Nokia) bug 201000 * Serge Beauchamp (Freescale Semiconductor) - Bug 421070 * Red Hat Inc. - add debuginfo and macro section support + * John Dallaway - support DWARF v5 content form data (#443) *******************************************************************************/ package org.eclipse.cdt.utils.debug.dwarf; @@ -62,6 +63,11 @@ public class DwarfReader extends Dwarf implements ISymbolReader, ICompileOptions private final ArrayList m_parsedLineTableOffsets = new ArrayList<>(); private long m_parsedLineTableSize = 0; + private class ContentForm { + long lnct; // content type code DW_LNCT_* + long form; // content form code DW_FORM_* + } + public DwarfReader(String file) throws IOException { super(file); } @@ -285,6 +291,137 @@ private static String printHexBinary(byte[] byteArray) { return sb.toString(); } + private String getPathInLineStr(long offset) { + final ByteBuffer data = dwarfSections.get(DWARF_DEBUG_LINE_STR); + if (null != data) { + data.position((int) offset); + return readString(data); + } + return ""; //$NON-NLS-1$ + } + + private long readOffset(ByteBuffer data, byte offsetSize) throws IOException { + switch (offsetSize) { + case 8: + return read_8_bytes(data); + case 4: + return read_4_bytes(data); + case 2: + return read_2_bytes(data); + default: + return -1L; // unsupported + } + } + + private ContentForm readContentForm(ByteBuffer in) throws IOException { + ContentForm contentForm = new ContentForm(); + contentForm.lnct = read_unsigned_leb128(in); // DW_LNCT_* + contentForm.form = read_unsigned_leb128(in); // DW_FORM_* + return contentForm; + } + + /* read source file data (DWARF v4 and earlier) */ + private void addSourceFilesDwarf(String cuCompDir, ByteBuffer data) throws IOException { + List dirList = new ArrayList<>(); + + // add the compilation directory of the CU as the first directory + dirList.add(cuCompDir); + + // read directories + while (true) { + String str = readString(data); + if (str.isEmpty()) { // if no more directories + break; + } + // if the directory is relative, append it to the CU directory + IPath dir = new Path(str); + if (!dir.isAbsolute()) { + dir = new Path(cuCompDir).append(str); + } + dirList.add(dir.toString()); + } + + // read file names + while (true) { + String fileName = readString(data); + if (fileName.isEmpty()) { // if no more file entries + break; + } + + // read directory index + long leb128 = read_unsigned_leb128(data); + + addSourceFile(dirList.get((int) leb128), fileName); + + // skip modification time + leb128 = read_unsigned_leb128(data); + + // skip file size in bytes + leb128 = read_unsigned_leb128(data); + } + } + + /* read source file data (DWARF v5 and later) */ + private void addSourceFilesDwarf5(String cuCompDir, ByteBuffer data, byte offsetSize) throws IOException { + // read directory content forms + byte dcf_count[] = new byte[1]; + data.get(dcf_count); + List directoryContentForms = new ArrayList<>(); + for (int fmt = 0; fmt < dcf_count[0]; fmt++) { + ContentForm def = readContentForm(data); + directoryContentForms.add(def); + } + + // read directories + long directories_count = read_unsigned_leb128(data); + List directories = new ArrayList<>((int) directories_count); + for (int directory_index = 0; directory_index < directories_count; directory_index++) { + for (ContentForm contentForm : directoryContentForms) { + if ((DwarfConstants.DW_FORM_line_strp == contentForm.form) + && (DwarfConstants.DW_LNCT_path == contentForm.lnct)) { + long offset = readOffset(data, offsetSize); + String path = getPathInLineStr(offset); + IPath dir = new Path(path); + if (!dir.isAbsolute()) { + dir = new Path(cuCompDir).append(path); + } + directories.add(dir.toString()); + } // TODO: support other DW_LNCT_path forms + } + } + + // read file name content forms + byte[] fncf_count = new byte[1]; + data.get(fncf_count); + List fileNameContentForms = new ArrayList<>(); + for (int fmt = 0; fmt < fncf_count[0]; fmt++) { + ContentForm fnef = readContentForm(data); + fileNameContentForms.add(fnef); + } + + // read file names + long file_names_count = read_unsigned_leb128(data); + for (int file_index = 0; file_index < file_names_count; file_index++) { + String filename = null; + String directory = null; + for (ContentForm contentForm : fileNameContentForms) { + if ((DwarfConstants.DW_FORM_line_strp == contentForm.form) + && (DwarfConstants.DW_LNCT_path == contentForm.lnct)) { + long offset = readOffset(data, offsetSize); + filename = getPathInLineStr(offset); + } // TODO: support other DW_LNCT_path forms + if ((DwarfConstants.DW_FORM_udata == contentForm.form) + && (DwarfConstants.DW_LNCT_directory_index == contentForm.lnct)) { + long directory_index = read_unsigned_leb128(data); + directory = directories.get((int) directory_index); + } // TODO: support other DW_LNCT_directory_index forms + } + if ((null != directory) && (null != filename)) { + addSourceFile(directory, filename); + } + } + } + /* * Parse line table data of a compilation unit to get names of all source files * that contribute to the compilation unit. @@ -319,11 +456,13 @@ void parseSourceInCULineInfo(String cuCompDir, // compilation directory of the C Integer cuOffset = Integer.valueOf(cuStmtList); boolean dwarf64Bit = false; + byte offsetSize = 0; if (!m_parsedLineTableOffsets.contains(cuOffset)) { m_parsedLineTableOffsets.add(cuOffset); // Note the length does not including the "length" field(s) itself. InitialLengthValue length = readInitialLengthField(data); + offsetSize = length.offsetSize; dwarf64Bit = length.offsetSize == 8; m_parsedLineTableSize += length.length + (dwarf64Bit ? 12 : 4); } else { @@ -346,46 +485,10 @@ void parseSourceInCULineInfo(String cuCompDir, // compilation directory of the C int opcode_base = data.get(); data.position(data.position() + opcode_base - 1); - // Read in directories. - // - ArrayList dirList = new ArrayList<>(); - - // Put the compilation directory of the CU as the first dir - dirList.add(cuCompDir); - - String str, fileName; - - while (true) { - str = readString(data); - if (str.length() == 0) - break; - // If the directory is relative, append it to the CU dir - IPath dir = new Path(str); - if (!dir.isAbsolute()) - dir = new Path(cuCompDir).append(str); - dirList.add(dir.toString()); - } - - // Read file names - // - long leb128; - while (true) { - fileName = readString(data); - if (fileName.length() == 0) // no more file entry - break; - - // dir index - leb128 = read_unsigned_leb128(data); - - addSourceFile(dirList.get((int) leb128), fileName); - - // Skip the followings - // - // modification time - leb128 = read_unsigned_leb128(data); - - // file size in bytes - leb128 = read_unsigned_leb128(data); + if (version >= 5) { + addSourceFilesDwarf5(cuCompDir, data, offsetSize); + } else { + addSourceFilesDwarf(cuCompDir, data); } } catch (IOException e) { CCorePlugin.log("Failed to parse part of dwarf header", e); //$NON-NLS-1$