mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 14:12:10 +02:00
Add GNU debug-info support to DwarfReader/Dwarf
- Add support to find separate debug info file using the .gnu_debuglink section - Add support to also find the GNU alt debug info file created by the DWZ utility - Add additional DW_FORMs to support alt data - Add support to DwarfReader to find the special note section containing the build-id and then see if it can find the debug-info with that build-id Change-Id: I0e43ba8af12396cdab4e085ad0c20fdec8c1d83e Reviewed-on: https://git.eclipse.org/r/24034 Tested-by: Hudson CI Reviewed-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com> Tested-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com> Reviewed-by: Jeff Johnston <jjohnstn@redhat.com> Tested-by: Jeff Johnston <jjohnstn@redhat.com>
This commit is contained in:
parent
f5f4b5101a
commit
12a2ba4b3f
5 changed files with 866 additions and 61 deletions
|
@ -0,0 +1,30 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2013 Red Hat Inc. and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core;
|
||||
|
||||
/**
|
||||
* A class that can find compiler options for a given file name.
|
||||
*
|
||||
* @noextend This interface is not intended to be extended by clients.
|
||||
* @noimplement This interface is not intended to be implemented by clients.
|
||||
* @since 5.7
|
||||
*/
|
||||
public interface ICompileOptionsFinder {
|
||||
|
||||
/**
|
||||
* Get compiler options for a given file name.
|
||||
*
|
||||
* @param fileName - absolute source file name
|
||||
* @return a String containing the compiler options used or null.
|
||||
*
|
||||
*/
|
||||
public String getCompileOptions(String fileName);
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
package org.eclipse.cdt.utils.debug.dwarf;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -30,6 +31,8 @@ import org.eclipse.cdt.utils.debug.tools.DebugSym;
|
|||
import org.eclipse.cdt.utils.debug.tools.DebugSymsRequestor;
|
||||
import org.eclipse.cdt.utils.elf.Elf;
|
||||
import org.eclipse.cdt.utils.elf.Elf.Section;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
|
||||
public class Dwarf {
|
||||
|
||||
|
@ -48,6 +51,11 @@ public class Dwarf {
|
|||
final static String DWARF_DEBUG_VARNAMES = ".debug_varnames"; //$NON-NLS-1$
|
||||
final static String DWARF_DEBUG_WEAKNAMES = ".debug_weaknames"; //$NON-NLS-1$
|
||||
final static String DWARF_DEBUG_MACINFO = ".debug_macinfo"; //$NON-NLS-1$
|
||||
final static String DWARF_DEBUG_MACRO = ".debug_macro"; //$NON-NLS-1$
|
||||
final static String DWARF_DEBUG_TYPES = ".debug_types"; //$NON-NLS-1$
|
||||
final static String DWARF_GNU_DEBUGLINK = ".gnu_debuglink"; //$NON-NLS-1$
|
||||
final static String DWARF_GNU_DEBUGALTLINK = ".gnu_debugaltlink"; //$NON-NLS-1$
|
||||
|
||||
final static String[] DWARF_SCNNAMES =
|
||||
{
|
||||
DWARF_DEBUG_INFO,
|
||||
|
@ -65,6 +73,14 @@ public class Dwarf {
|
|||
DWARF_DEBUG_WEAKNAMES,
|
||||
DWARF_DEBUG_MACINFO };
|
||||
|
||||
final static String[] DWARF_ALT_SCNNAMES =
|
||||
{
|
||||
DWARF_DEBUG_INFO,
|
||||
DWARF_DEBUG_TYPES,
|
||||
DWARF_DEBUG_MACRO,
|
||||
DWARF_DEBUG_STR,
|
||||
};
|
||||
|
||||
class CompilationUnitHeader {
|
||||
long length;
|
||||
short version;
|
||||
|
@ -166,6 +182,7 @@ public class Dwarf {
|
|||
}
|
||||
|
||||
Map<String, ByteBuffer> dwarfSections = new HashMap<String, ByteBuffer>();
|
||||
Map<String, ByteBuffer> dwarfAltSections = new HashMap<String, ByteBuffer>();
|
||||
Map<Integer, Map<Long, AbbreviationEntry>> abbreviationMaps = new HashMap<Integer, Map<Long, AbbreviationEntry>>();
|
||||
|
||||
boolean isLE;
|
||||
|
@ -196,15 +213,86 @@ public class Dwarf {
|
|||
isLE = header.e_ident[Elf.ELFhdr.EI_DATA] == Elf.ELFhdr.ELFDATA2LSB;
|
||||
|
||||
Elf.Section[] sections = exe.getSections();
|
||||
IPath debugInfoPath = new Path(exe.getFilename());
|
||||
// Look for a .gnu_debuglink section which will have the name of the debug info file
|
||||
Elf.Section gnuDebugLink = exe.getSectionByName(DWARF_GNU_DEBUGLINK);
|
||||
if (gnuDebugLink != null) {
|
||||
ByteBuffer data = gnuDebugLink.mapSectionData();
|
||||
if (data != null) { // we have non-empty debug info link
|
||||
try {
|
||||
// name is zero-byte terminated character string
|
||||
String debugName = readString(data);
|
||||
if (debugName.length() > 0) {
|
||||
// try and open the debug info from 3 separate places in order
|
||||
File debugFile = null;
|
||||
IPath p = debugInfoPath.removeLastSegments(1);
|
||||
// 1. try and open the file in the same directory as the executable
|
||||
debugFile = p.append(debugName).toFile();
|
||||
if (!debugFile.exists()) {
|
||||
// 2. try and open the file in the .debug directory where the executable is
|
||||
debugFile = p.append(".debug").append(debugName).toFile(); //$NON-NLS-1$
|
||||
if (!debugFile.exists())
|
||||
// 3. try and open /usr/lib/debug/$(EXEPATH)/$(DEBUGINFO_NAME)
|
||||
debugFile = new Path("/usr/lib/debug").append(p).append(debugName).toFile(); //$NON-NLS-1$
|
||||
}
|
||||
if (debugFile.exists()) {
|
||||
// if the debug file exists from above, open it and get the section info from it
|
||||
Elf debugInfo = new Elf(debugFile.getCanonicalPath());
|
||||
sections = debugInfo.getSections();
|
||||
debugInfoPath = new Path(debugFile.getCanonicalPath());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
for (Section section : sections) {
|
||||
String name = section.toString();
|
||||
for (String element : DWARF_SCNNAMES) {
|
||||
if (name.equals(element)) {
|
||||
try {
|
||||
dwarfSections.put(element, section.mapSectionData());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
CCorePlugin.log(e);
|
||||
if (name.equals(DWARF_GNU_DEBUGALTLINK)) {
|
||||
ByteBuffer data = section.mapSectionData();
|
||||
try {
|
||||
// name is zero-byte terminated character string
|
||||
String altInfoName = readString(data);
|
||||
if (altInfoName.length() > 0) {
|
||||
IPath altPath = new Path(altInfoName);
|
||||
if (!altPath.isAbsolute()) {
|
||||
altPath = debugInfoPath.append(altPath);
|
||||
}
|
||||
File altFile = altPath.toFile();
|
||||
if (altFile.exists()) {
|
||||
Elf altInfo = new Elf(altFile.getCanonicalPath());
|
||||
Elf.Section[] altSections = altInfo.getSections();
|
||||
for (Section altSection : altSections) {
|
||||
String altName = altSection.toString();
|
||||
for (String element : DWARF_ALT_SCNNAMES) {
|
||||
if (altName.equals(element)) {
|
||||
try {
|
||||
dwarfAltSections.put(element, altSection.mapSectionData());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
} else {
|
||||
for (String element : DWARF_SCNNAMES) {
|
||||
if (name.equals(element)) {
|
||||
try {
|
||||
dwarfSections.put(element, section.mapSectionData());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -463,7 +551,8 @@ public class Dwarf {
|
|||
byte hasChildren = data.get();
|
||||
AbbreviationEntry entry = new AbbreviationEntry(code, tag, hasChildren);
|
||||
|
||||
//System.out.println("\tAbrev Entry: " + code + " " + Long.toHexString(entry.tag) + " " + entry.hasChildren);
|
||||
if (printEnabled)
|
||||
System.out.println("\tAbrev Entry: " + code + " " + Long.toHexString(entry.tag) + " " + entry.hasChildren); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
|
||||
// attributes
|
||||
long name = 0;
|
||||
|
@ -474,7 +563,8 @@ public class Dwarf {
|
|||
if (name != 0) {
|
||||
entry.attributes.add(new Attribute(name, form));
|
||||
}
|
||||
//System.out.println("\t\t " + Long.toHexString(name) + " " + Long.toHexString(value));
|
||||
if (printEnabled)
|
||||
System.out.println("\t\t " + Long.toHexString(name) + " " + Long.toHexString(form)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
} while (name != 0 && form != 0);
|
||||
abbrevs.put(new Long(code), entry);
|
||||
}
|
||||
|
@ -505,6 +595,8 @@ public class Dwarf {
|
|||
}
|
||||
}
|
||||
|
||||
int oldForm = 0;
|
||||
|
||||
Object readAttribute(int form, ByteBuffer in, CompilationUnitHeader header) throws IOException {
|
||||
Object obj = null;
|
||||
switch (form) {
|
||||
|
@ -621,6 +713,34 @@ public class Dwarf {
|
|||
}
|
||||
break;
|
||||
|
||||
case DwarfConstants.DW_FORM_GNU_strp_alt :
|
||||
{
|
||||
long offset;
|
||||
if (header.offsetSize == 8)
|
||||
offset = read_8_bytes(in);
|
||||
else
|
||||
offset = read_4_bytes(in) & 0xffffffffL;
|
||||
|
||||
ByteBuffer data = dwarfAltSections.get(DWARF_DEBUG_STR);
|
||||
if (data == null) {
|
||||
obj = new String();
|
||||
} else if (offset < 0 || offset > data.capacity()) {
|
||||
obj = new String();
|
||||
} else {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
data.position((int) offset);
|
||||
while (data.hasRemaining()) {
|
||||
byte c = data.get();
|
||||
if (c == 0) {
|
||||
break;
|
||||
}
|
||||
sb.append((char) c);
|
||||
}
|
||||
obj = sb.toString();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DwarfConstants.DW_FORM_ref1 :
|
||||
obj = new Byte(in.get());
|
||||
break;
|
||||
|
@ -646,6 +766,12 @@ public class Dwarf {
|
|||
int f = (int) read_unsigned_leb128(in);
|
||||
return readAttribute(f, in, header);
|
||||
}
|
||||
case DwarfConstants.DW_FORM_GNU_ref_alt :
|
||||
if (header.offsetSize == 8)
|
||||
obj = new Long(read_8_bytes(in));
|
||||
else
|
||||
obj = new Long(read_4_bytes(in) & 0xffffffffL);
|
||||
break;
|
||||
case DwarfConstants.DW_FORM_sec_offset :
|
||||
if (header.offsetSize == 8)
|
||||
obj = new Long(read_8_bytes(in));
|
||||
|
@ -667,9 +793,14 @@ public class Dwarf {
|
|||
break;
|
||||
|
||||
default :
|
||||
break;
|
||||
if (printEnabled) {
|
||||
System.out.println("Default for " + form); //$NON-NLS-1$
|
||||
System.out.println("Last form is " + oldForm); //$NON-NLS-1$
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
oldForm = form;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -775,6 +906,27 @@ public class Dwarf {
|
|||
return new Long(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a null-ended string from the given "data" stream.
|
||||
* data : IN, byte buffer
|
||||
*/
|
||||
String readString(ByteBuffer data)
|
||||
{
|
||||
String str;
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while (data.hasRemaining()) {
|
||||
byte c = data.get();
|
||||
if (c == 0) {
|
||||
break;
|
||||
}
|
||||
sb.append((char) c);
|
||||
}
|
||||
|
||||
str = sb.toString();
|
||||
return str;
|
||||
}
|
||||
|
||||
void processSubProgram(IDebugEntryRequestor requestor, List<AttributeValue> list) {
|
||||
long lowPC = 0;
|
||||
long highPC = 0;
|
||||
|
|
|
@ -65,6 +65,10 @@ public class DwarfConstants {
|
|||
public final static int DW_TAG_variant_part = 0x33;
|
||||
public final static int DW_TAG_variable = 0x34;
|
||||
public final static int DW_TAG_volatile_type = 0x35;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_TAG_partial_unit = 0x3c;
|
||||
public final static int DW_TAG_lo_user = 0x4080;
|
||||
public final static int DW_TAG_MIPS_loop = 0x4081;
|
||||
public final static int DW_TAG_format_label = 0x4101;
|
||||
|
@ -187,22 +191,42 @@ public class DwarfConstants {
|
|||
public final static int DW_FORM_ref8 = 0x14;
|
||||
public final static int DW_FORM_ref_udata = 0x15;
|
||||
public final static int DW_FORM_indirect = 0x16;
|
||||
|
||||
/**
|
||||
* @since 5.6
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_FORM_sec_offset = 0x17;
|
||||
/**
|
||||
* @since 5.6
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_FORM_exprloc = 0x18;
|
||||
/**
|
||||
* @since 5.6
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_FORM_flag_present = 0x19;
|
||||
/**
|
||||
* @since 5.6
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_FORM_ref_sig8 = 0x20;
|
||||
/* Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission. */
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_FORM_GNU_addr_index = 0x1f01;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_FORM_GNU_str_index = 0x1f02;
|
||||
/* Extensions for DWZ multifile.
|
||||
See http://www.dwarfstd.org/ShowIssue.php?issue=120604.1&type=open . */
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_FORM_GNU_ref_alt = 0x1f20;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_FORM_GNU_strp_alt = 0x1f21;
|
||||
|
||||
/* DWARF location operation encodings. */
|
||||
public final static int DW_OP_addr = 0x03; /* Constant address. */
|
||||
|
@ -459,6 +483,60 @@ public class DwarfConstants {
|
|||
public final static int DW_MACINFO_end_file = 4;
|
||||
public final static int DW_MACINFO_vendor_ext = 255;
|
||||
|
||||
/* DWARF macro type encodings. */
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_MACRO_end = 0;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_MACRO_define = 1;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_MACRO_undef = 2;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_MACRO_start_file = 3;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_MACRO_end_file = 4;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_MACRO_define_indirect = 5;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_MACRO_undef_indirect = 6;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_MACRO_transparent_include = 7;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_MACRO_define_indirect_alt = 0x08;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_MACRO_undef_indirect_alt = 0x09;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_MACRO_transparent_include_alt = 0x0a;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_MACRO_lo_user = 0xe0;
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int DW_MACRO_hi_user = 0xff;
|
||||
|
||||
/* DWARF call frame instruction encodings. */
|
||||
public final static int DW_CFA_advance_loc = 0x40;
|
||||
public final static int DW_CFA_offset = 0x80;
|
||||
|
|
|
@ -9,18 +9,26 @@
|
|||
* Nokia - initial API and implementation
|
||||
* Ling Wang (Nokia) bug 201000
|
||||
* Serge Beauchamp (Freescale Semiconductor) - Bug 421070
|
||||
* Red Hat Inc. - add debuginfo and macro section support
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.utils.debug.dwarf;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.ICompileOptionsFinder;
|
||||
import org.eclipse.cdt.core.ISymbolReader;
|
||||
import org.eclipse.cdt.utils.coff.Coff.SectionHeader;
|
||||
import org.eclipse.cdt.utils.coff.PE;
|
||||
|
@ -35,20 +43,26 @@ import org.eclipse.core.runtime.Path;
|
|||
* Light-weight parser of Dwarf2 data which is intended for getting only
|
||||
* source files that contribute to the given executable.
|
||||
*/
|
||||
public class DwarfReader extends Dwarf implements ISymbolReader {
|
||||
public class DwarfReader extends Dwarf implements ISymbolReader, ICompileOptionsFinder {
|
||||
|
||||
// These are sections that need be parsed to get the source file list.
|
||||
final static String[] DWARF_SectionsToParse =
|
||||
{
|
||||
DWARF_DEBUG_INFO,
|
||||
DWARF_DEBUG_LINE,
|
||||
DWARF_DEBUG_ABBREV,
|
||||
DWARF_DEBUG_STR // this is optional. Some compilers don't generate it.
|
||||
};
|
||||
final static String[] DWARF_SectionsToParse = {
|
||||
DWARF_DEBUG_INFO,
|
||||
DWARF_DEBUG_LINE,
|
||||
DWARF_DEBUG_ABBREV,
|
||||
DWARF_DEBUG_STR, // this is optional. Some compilers don't generate it.
|
||||
DWARF_DEBUG_MACRO, };
|
||||
|
||||
final static String[] DWARF_ALT_SectionsToParse = {
|
||||
DWARF_DEBUG_STR,
|
||||
DWARF_DEBUG_MACRO };
|
||||
|
||||
private final Collection<String> m_fileCollection = new HashSet<String>();
|
||||
private final Map<Long, String> m_stmtFileMap = new HashMap<Long, String>();
|
||||
private final Map<String, ArrayList<String>> m_compileOptionsMap = new HashMap<String, ArrayList<String>>();
|
||||
private String[] m_fileNames = null;
|
||||
private boolean m_parsed = false;
|
||||
private boolean m_macros_parsed = false;
|
||||
private final ArrayList<Integer> m_parsedLineTableOffsets = new ArrayList<Integer>();
|
||||
private long m_parsedLineTableSize = 0;
|
||||
|
||||
|
@ -74,22 +88,159 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
|
|||
Elf.ELFhdr header = exe.getELFhdr();
|
||||
isLE = header.e_ident[Elf.ELFhdr.EI_DATA] == Elf.ELFhdr.ELFDATA2LSB;
|
||||
|
||||
IPath debugInfoPath = new Path(exe.getFilename());
|
||||
Elf.Section[] sections = exe.getSections();
|
||||
|
||||
boolean have_build_id = false;
|
||||
|
||||
// Look for a special GNU build-id note which means the debug data resides in a separate
|
||||
// file with a name based on the build-id.
|
||||
for (Section section : sections) {
|
||||
if (section.sh_type == Elf.Section.SHT_NOTE) {
|
||||
ByteBuffer data = section.mapSectionData();
|
||||
try {
|
||||
// Read .note section, looking to see if it is named "GNU" and is of GNU_BUILD_ID type
|
||||
@SuppressWarnings("unused")
|
||||
int name_sz = read_4_bytes(data);
|
||||
int data_sz = read_4_bytes(data);
|
||||
int note_type = read_4_bytes(data);
|
||||
|
||||
String noteName = readString(data);
|
||||
String buildId = null;
|
||||
if (noteName.equals("GNU") && note_type == Elf.Section.NT_GNU_BUILD_ID) { //$NON-NLS-1$
|
||||
// We have the special GNU build-id note section. Skip over the name to
|
||||
// a 4-byte boundary.
|
||||
byte[] byteArray = new byte[data_sz];
|
||||
while ((data.position() & 0x3) != 0)
|
||||
data.get();
|
||||
int i = 0;
|
||||
// Read in the hex bytes from the note section's data.
|
||||
while (data.hasRemaining() && data_sz-- > 0) {
|
||||
byteArray[i++] = data.get();
|
||||
}
|
||||
// The build-id location is taken by converting the binary bytes to hex string.
|
||||
// The first byte is used as a directory specifier (e.g. 51/a4578fe2).
|
||||
String bName = DatatypeConverter.printHexBinary(byteArray).toLowerCase();
|
||||
buildId = bName.substring(0, 2) + "/" + bName.substring(2) + ".debug"; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
// The build-id file should be in the special directory /usr/lib/debug/.build-id
|
||||
IPath buildIdPath = new Path("/usr/lib/debug/.build-id").append(buildId); //$NON-NLS-1$
|
||||
File buildIdFile = buildIdPath.toFile();
|
||||
if (buildIdFile.exists()) {
|
||||
// if the debug file exists from above, open it and get the section info from it
|
||||
Elf debugInfo = new Elf(buildIdFile.getCanonicalPath());
|
||||
sections = debugInfo.getSections();
|
||||
have_build_id = true;
|
||||
debugInfoPath = new Path(buildIdFile.getCanonicalPath()).removeLastSegments(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!have_build_id) {
|
||||
// No build-id. Look for a .gnu_debuglink section which will have the name of the debug info file
|
||||
Elf.Section gnuDebugLink = exe.getSectionByName(DWARF_GNU_DEBUGLINK);
|
||||
if (gnuDebugLink != null) {
|
||||
ByteBuffer data = gnuDebugLink.mapSectionData();
|
||||
if (data != null) { // we have non-empty debug info link
|
||||
try {
|
||||
// name is zero-byte terminated character string
|
||||
String debugName = ""; //$NON-NLS-1$
|
||||
if (data.hasRemaining()) {
|
||||
int c;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while ((c = data.get()) != -1) {
|
||||
if (c == 0) {
|
||||
break;
|
||||
}
|
||||
sb.append((char) c);
|
||||
}
|
||||
debugName = sb.toString();
|
||||
}
|
||||
if (debugName.length() > 0) {
|
||||
// try and open the debug info from 3 separate places in order
|
||||
File debugFile = null;
|
||||
IPath exePath = new Path(exe.getFilename());
|
||||
IPath p = exePath.removeLastSegments(1);
|
||||
// 1. try and open the file in the same directory as the executable
|
||||
debugFile = p.append(debugName).toFile();
|
||||
if (!debugFile.exists()) {
|
||||
// 2. try and open the file in the .debug directory where the executable is
|
||||
debugFile = p.append(".debug").append(debugName).toFile(); //$NON-NLS-1$
|
||||
if (!debugFile.exists())
|
||||
// 3. try and open /usr/lib/debug/$(EXE_DIR)/$(DEBUGINFO_NAME)
|
||||
debugFile = new Path("/usr/lib/debug").append(p).append(debugName).toFile(); //$NON-NLS-1$
|
||||
}
|
||||
if (debugFile.exists()) {
|
||||
// if the debug file exists from above, open it and get the section info from it
|
||||
Elf debugInfo = new Elf(debugFile.getCanonicalPath());
|
||||
sections = debugInfo.getSections();
|
||||
debugInfoPath = new Path(debugFile.getCanonicalPath()).removeLastSegments(1);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Read in sections (and only the sections) we care about.
|
||||
//
|
||||
for (Section section : sections) {
|
||||
String name = section.toString();
|
||||
for (String element : DWARF_SectionsToParse) {
|
||||
if (name.equals(element)) {
|
||||
// catch out of memory exceptions which might happen trying to
|
||||
// load large sections (like .debug_info). not a fix for that
|
||||
// problem itself, but will at least continue to load the other
|
||||
// sections.
|
||||
try {
|
||||
dwarfSections.put(element, section.mapSectionData());
|
||||
} catch (Exception e) {
|
||||
CCorePlugin.log(e);
|
||||
if (name.equals(DWARF_GNU_DEBUGALTLINK)) {
|
||||
ByteBuffer data = section.mapSectionData();
|
||||
try {
|
||||
// name is zero-byte terminated character string
|
||||
String altInfoName = readString(data);
|
||||
if (altInfoName.length() > 0) {
|
||||
IPath altPath = new Path(altInfoName);
|
||||
if (!altPath.isAbsolute()) {
|
||||
altPath = debugInfoPath.append(altPath);
|
||||
}
|
||||
File altFile = altPath.toFile();
|
||||
if (altFile.exists()) {
|
||||
Elf altInfo = new Elf(altFile.getCanonicalPath());
|
||||
Elf.Section[] altSections = altInfo.getSections();
|
||||
for (Section altSection : altSections) {
|
||||
String altName = altSection.toString();
|
||||
for (String element : DWARF_ALT_SectionsToParse) {
|
||||
if (altName.equals(element)) {
|
||||
try {
|
||||
dwarfAltSections.put(element, altSection.mapSectionData());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (String element : DWARF_SectionsToParse) {
|
||||
if (name.equals(element)) {
|
||||
// catch out of memory exceptions which might happen trying to
|
||||
// load large sections (like .debug_info). not a fix for that
|
||||
// problem itself, but will at least continue to load the other
|
||||
// sections.
|
||||
try {
|
||||
dwarfSections.put(element, section.mapSectionData());
|
||||
} catch (Exception e) {
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -411,13 +562,19 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
|
|||
parse(null);
|
||||
}
|
||||
|
||||
private void addSourceFile(String dir, String name)
|
||||
private String addSourceFileWithStmt(String dir, String name, int stmt) {
|
||||
String fullName = addSourceFile(dir, name);
|
||||
m_stmtFileMap.put(Long.valueOf(stmt), fullName);
|
||||
return fullName;
|
||||
}
|
||||
|
||||
private String addSourceFile(String dir, String name)
|
||||
{
|
||||
if (name == null || name.length() == 0)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (name.charAt(0) == '<') // don't count the entry "<internal>" from GCCE compiler
|
||||
return;
|
||||
return null;
|
||||
|
||||
String fullName = name;
|
||||
|
||||
|
@ -433,30 +590,11 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
|
|||
fullName = pa.toOSString();
|
||||
|
||||
if (!m_fileCollection.contains(fullName))
|
||||
m_fileCollection.add(fullName);
|
||||
m_fileCollection.add(fullName);
|
||||
|
||||
return fullName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a null-ended string from the given "data" stream.
|
||||
* data : IN, byte buffer
|
||||
*/
|
||||
String readString(ByteBuffer data)
|
||||
{
|
||||
String str;
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while (data.hasRemaining()) {
|
||||
byte c = data.get();
|
||||
if (c == 0) {
|
||||
break;
|
||||
}
|
||||
sb.append((char) c);
|
||||
}
|
||||
|
||||
str = sb.toString();
|
||||
return str;
|
||||
}
|
||||
|
||||
// Override parent: only handle TAG_Compile_Unit.
|
||||
@Override
|
||||
void processDebugInfoEntry(IDebugEntryRequestor requestor, AbbreviationEntry entry, List<Dwarf.AttributeValue> list) {
|
||||
|
@ -502,7 +640,7 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
|
|||
}
|
||||
}
|
||||
|
||||
addSourceFile(cuCompDir, cuName);
|
||||
addSourceFileWithStmt(cuCompDir, cuName, stmtList);
|
||||
if (stmtList > -1) // this CU has "stmt_list" attribute
|
||||
parseSourceInCULineInfo(cuCompDir, stmtList);
|
||||
}
|
||||
|
@ -515,4 +653,406 @@ public class DwarfReader extends Dwarf implements ISymbolReader {
|
|||
return getSourceFiles();
|
||||
}
|
||||
|
||||
private class OpcodeInfo {
|
||||
private int numArgs;
|
||||
private final boolean offset_size_8;
|
||||
ArrayList<Integer> argTypes;
|
||||
|
||||
public OpcodeInfo (boolean offset_size_8) {
|
||||
this.offset_size_8 = offset_size_8;
|
||||
}
|
||||
|
||||
public void setNumArgs (int numArgs) {
|
||||
this.numArgs = numArgs;
|
||||
}
|
||||
|
||||
public void addArgType(int argType) {
|
||||
argTypes.add(Integer.valueOf(argType));
|
||||
}
|
||||
|
||||
public void readPastEntry(ByteBuffer data) {
|
||||
for (int i = 0; i < numArgs; ++i) {
|
||||
int argType = argTypes.get(i).intValue();
|
||||
switch (argType) {
|
||||
case DwarfConstants.DW_FORM_flag:
|
||||
case DwarfConstants.DW_FORM_data1:
|
||||
data.get();
|
||||
break;
|
||||
case DwarfConstants.DW_FORM_data2:
|
||||
data.getShort();
|
||||
break;
|
||||
case DwarfConstants.DW_FORM_data4:
|
||||
data.getInt();
|
||||
break;
|
||||
case DwarfConstants.DW_FORM_data8:
|
||||
data.getLong();
|
||||
break;
|
||||
case DwarfConstants.DW_FORM_sdata:
|
||||
case DwarfConstants.DW_FORM_udata:
|
||||
try {
|
||||
read_signed_leb128(data);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_FORM_block: {
|
||||
try {
|
||||
long off = read_signed_leb128(data);
|
||||
data.position((int)(data.position() + off));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_FORM_block1: {
|
||||
int off = data.get();
|
||||
data.position(data.position() + off + 1);
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_FORM_block2: {
|
||||
int off = data.getShort();
|
||||
data.position(data.position() + off + 2);
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_FORM_block4: {
|
||||
int off = data.getInt();
|
||||
data.position(data.position() + off + 4);
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_FORM_string:
|
||||
while (data.get() != 0) {
|
||||
// loop until we find 0 byte
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_FORM_strp:
|
||||
case DwarfConstants.DW_FORM_GNU_strp_alt:
|
||||
case DwarfConstants.DW_FORM_GNU_ref_alt:
|
||||
case DwarfConstants.DW_FORM_sec_offset:
|
||||
if (offset_size_8)
|
||||
data.getLong();
|
||||
else
|
||||
data.getInt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a macro to its command line form.
|
||||
private String getCommandLineMacro(String macro) {
|
||||
String commandLineMacro = "-D" + macro; //$NON-NLS-1$
|
||||
commandLineMacro = commandLineMacro.replaceFirst(" ", "="); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
return commandLineMacro;
|
||||
}
|
||||
|
||||
// Go through regular and alt macro sections and find any macros that were set on the
|
||||
// compilation command line (e.g. gcc -Dflagx=1 my.c). Built-in macros and macros that
|
||||
// are set within files (source and include) are ignored since they can and will be
|
||||
// discovered by indexing.
|
||||
private void getCommandMacrosFromMacroSection() {
|
||||
ByteBuffer data = dwarfSections.get(DWARF_DEBUG_MACRO);
|
||||
ByteBuffer str = dwarfSections.get(DWARF_DEBUG_STR);
|
||||
ByteBuffer altdata = dwarfAltSections.get(DWARF_DEBUG_MACRO);
|
||||
ByteBuffer altstr = dwarfAltSections.get(DWARF_DEBUG_STR);
|
||||
Set<String> fixupList = new HashSet<String>();
|
||||
Set<String> fixupAltList = new HashSet<String>();
|
||||
boolean DEBUG = false;
|
||||
if (data == null)
|
||||
return;
|
||||
|
||||
HashMap <Long, ArrayList<String>> t_macros = new HashMap<Long, ArrayList<String>>();
|
||||
HashMap <Long, ArrayList<String>> t_alt_macros = new HashMap<Long, ArrayList<String>>();
|
||||
|
||||
// Parse the macro section, looking for command-line macros meant for compiling files (i.e.
|
||||
// not internal macro definitions in headers or C/C++ files. Keep track of any forward
|
||||
// references to fix-up later when we have a complete list of command-line macros.
|
||||
parseMacroSection(data, str, altstr, fixupList, fixupAltList, "=FIXUP=", DEBUG, t_macros); //$NON-NLS-1$
|
||||
|
||||
// Check if there is an alternate macro section. If there is, parse the alternate section, but any references
|
||||
// found there should be considered referring to the alternate string and macro sections.
|
||||
// All forward reference fix-ups should be put on the alternate fix-up list.
|
||||
if (altdata != null) {
|
||||
if (DEBUG)
|
||||
System.out.println("Processing Alternate Macro Section"); //$NON-NLS-1$
|
||||
parseMacroSection(altdata, altstr, altstr, fixupAltList, fixupAltList, "=FIXUPALT=", DEBUG, t_alt_macros); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// Fix up all forward references from transparent includes
|
||||
fixupMacros(fixupList, "=FIXUP=", DEBUG, t_macros); //$NON-NLS-1$
|
||||
|
||||
// Fix up all forward references from transparent alt includes
|
||||
if (DEBUG)
|
||||
System.out.println("Fix up forward references in alternate macro section"); //$NON-NLS-1$
|
||||
fixupMacros(fixupAltList, "=FIXUPALT=", DEBUG, t_alt_macros); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// Fix up forward references made by transparent includes now that a complete macro list has been retrieved.
|
||||
private void fixupMacros(Set<String> fixupList, String fixupMarker, boolean DEBUG,
|
||||
HashMap<Long, ArrayList<String>> t_macros) {
|
||||
for (String name: fixupList) {
|
||||
ArrayList<String> macros = m_compileOptionsMap.get(name);
|
||||
for (int i = 0; i < macros.size(); ++i) {
|
||||
String macroLine = macros.get(i);
|
||||
if (macroLine.startsWith(fixupMarker)) {
|
||||
Long offset = Long.valueOf(macroLine.substring(7));
|
||||
if (DEBUG)
|
||||
System.out.println("Found fixup needed for offset: " + offset + " for file: " + name); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
ArrayList<String> insertMacros = t_macros.get(offset);
|
||||
if (DEBUG)
|
||||
System.out.println("insert macros are: " + insertMacros.toString()); //$NON-NLS-1$
|
||||
macros.remove(i);
|
||||
macros.addAll(i, insertMacros);
|
||||
i += insertMacros.size();
|
||||
}
|
||||
}
|
||||
m_compileOptionsMap.put(name, macros); // replace updated list
|
||||
}
|
||||
}
|
||||
|
||||
// Parse a macro section, looking for command-line macros that are used as flags to compile source files.
|
||||
// Keep track of any forward references to macros not yet defined in the file. We will later
|
||||
// fix-up these references when we have seen all command-line macros for the file.
|
||||
private void parseMacroSection(ByteBuffer data, ByteBuffer str, ByteBuffer altstr,
|
||||
Set<String> fixupList, Set<String> fixupAltList, String fixupMarker, boolean DEBUG,
|
||||
HashMap<Long, ArrayList<String>> t_macros) {
|
||||
byte op;
|
||||
while (data.hasRemaining()) {
|
||||
try {
|
||||
int original_position = data.position();
|
||||
int type = read_2_bytes(data);
|
||||
byte flags = data.get();
|
||||
boolean offset_size_8;
|
||||
long lt_offset = -1;
|
||||
String fileName = null;
|
||||
|
||||
HashMap<Integer, OpcodeInfo> opcodeInfos = null;
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println("type is " + type); //$NON-NLS-1$
|
||||
|
||||
// bottom bit 0 tells us whether we have 8 byte offsets or 4 byte offsets
|
||||
offset_size_8 = (flags & 0x1) == 1;
|
||||
if (DEBUG)
|
||||
System.out.println("offset size is " + (offset_size_8 ? 8 : 4)); //$NON-NLS-1$
|
||||
// bit 1 indicates we have an offset from the start of .debug_line section
|
||||
if ((flags & 0x2) != 0) {
|
||||
lt_offset = (offset_size_8 ? read_8_bytes(data) : read_4_bytes(data));
|
||||
fileName = m_stmtFileMap.get(Long.valueOf(lt_offset));
|
||||
if (DEBUG)
|
||||
System.out.println("debug line offset is " + lt_offset); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
// if bit 2 flag is on, then we have a macro entry table which may
|
||||
// have non-standard entry types defined which we need to know when
|
||||
// we come across macro entries later
|
||||
if ((flags & 0x4) != 0) {
|
||||
opcodeInfos = new HashMap<Integer, OpcodeInfo>();
|
||||
int num_opcodes = data.get();
|
||||
for (int i = 0; i < num_opcodes; ++i) {
|
||||
OpcodeInfo info = new OpcodeInfo(offset_size_8);
|
||||
|
||||
int opcode = data.get();
|
||||
long numArgs = read_unsigned_leb128(data);
|
||||
info.setNumArgs((int)numArgs);
|
||||
for (int j = 0; j < numArgs; ++j) {
|
||||
int argType = data.get();
|
||||
info.addArgType(argType);
|
||||
}
|
||||
opcodeInfos.put(Integer.valueOf(opcode), info);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<String> macros = new ArrayList<String>();
|
||||
|
||||
boolean done = false;
|
||||
|
||||
while (!done) {
|
||||
op = data.get();
|
||||
switch (op) {
|
||||
|
||||
case DwarfConstants.DW_MACRO_start_file: {
|
||||
long filenum;
|
||||
long lineno;
|
||||
lineno = read_signed_leb128(data);
|
||||
filenum = read_signed_leb128(data);
|
||||
// All command line macros are defined as being included before start of file
|
||||
if (filenum == 1 && lt_offset >= 0) {
|
||||
// we have a source file so add all macros defined before it with lineno 0
|
||||
m_compileOptionsMap.put(fileName, macros);
|
||||
if (DEBUG)
|
||||
System.out.println("following macros found for file " + macros.toString()); //$NON-NLS-1$
|
||||
macros = new ArrayList<String>();
|
||||
}
|
||||
if (fileName != null)
|
||||
if (DEBUG)
|
||||
System.out.println(" DW_MACRO_start_file - lineno: " + lineno + " filenum: " //$NON-NLS-1$ //$NON-NLS-2$
|
||||
+ filenum + " " + fileName); //$NON-NLS-1$
|
||||
else if (DEBUG)
|
||||
System.out.println(" DW_MACRO_start_file - lineno: " + lineno + " filenum: " //$NON-NLS-1$ //$NON-NLS-2$
|
||||
+ filenum);
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_MACRO_end_file: {
|
||||
if (DEBUG)
|
||||
System.out.println(" DW_MACRO_end_file"); //$NON-NLS-1$
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_MACRO_define: {
|
||||
long lineno;
|
||||
String string;
|
||||
lineno = read_signed_leb128(data);
|
||||
string = readString(data);
|
||||
if (lineno == 0)
|
||||
macros.add(getCommandLineMacro(string));
|
||||
if (DEBUG)
|
||||
System.out.println(" DW_MACRO_define - lineno : " + lineno + " macro : " //$NON-NLS-1$ //$NON-NLS-2$
|
||||
+ string);
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_MACRO_undef: {
|
||||
long lineno;
|
||||
String macro;
|
||||
lineno = read_signed_leb128(data);
|
||||
macro = readString(data);
|
||||
if (DEBUG)
|
||||
System.out.println(" DW_MACRO_undef - lineno : " + lineno + " macro : " //$NON-NLS-1$ //$NON-NLS-2$
|
||||
+ macro);
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_MACRO_define_indirect: {
|
||||
long lineno;
|
||||
long offset;
|
||||
lineno = read_signed_leb128(data);
|
||||
offset = (offset_size_8 ? read_8_bytes(data) : read_4_bytes(data));
|
||||
str.position((int)offset);
|
||||
String macro = readString(str);
|
||||
if (lineno == 0)
|
||||
macros.add(getCommandLineMacro(macro));
|
||||
if (DEBUG)
|
||||
System.out.println(" DW_MACRO_define_indirect - lineno : " + lineno + " macro : " //$NON-NLS-1$ //$NON-NLS-2$
|
||||
+ macro);
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_MACRO_define_indirect_alt: {
|
||||
long lineno;
|
||||
long offset;
|
||||
lineno = read_signed_leb128(data);
|
||||
offset = (offset_size_8 ? read_8_bytes(data) : read_4_bytes(data));
|
||||
altstr.position((int)offset);
|
||||
String macro = readString(altstr);
|
||||
if (lineno == 0)
|
||||
macros.add(getCommandLineMacro(macro));
|
||||
if (DEBUG)
|
||||
System.out.println(" DW_MACRO_define_indirect_alt - lineno : " + lineno + " macro : " //$NON-NLS-1$ //$NON-NLS-2$
|
||||
+ macro);
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_MACRO_undef_indirect: {
|
||||
long lineno;
|
||||
long offset;
|
||||
String macro;
|
||||
lineno = read_signed_leb128(data);
|
||||
offset = (offset_size_8 ? read_8_bytes(data) : read_4_bytes(data));
|
||||
str.position((int)offset);
|
||||
macro = readString(str);
|
||||
if (DEBUG)
|
||||
System.out.println(" DW_MACRO_undef_indirect - lineno : " + lineno + " macro : " //$NON-NLS-1$ //$NON-NLS-2$
|
||||
+ macro);
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_MACRO_undef_indirect_alt: {
|
||||
long lineno;
|
||||
long offset;
|
||||
String macro;
|
||||
lineno = read_signed_leb128(data);
|
||||
offset = (offset_size_8 ? read_8_bytes(data) : read_4_bytes(data));
|
||||
altstr.position((int)offset);
|
||||
macro = readString(altstr);
|
||||
if (DEBUG)
|
||||
System.out.println(" DW_MACRO_undef_indirect_alt - lineno : " + lineno + " macro : " //$NON-NLS-1$ //$NON-NLS-2$
|
||||
+ macro);
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_MACRO_transparent_include: {
|
||||
long offset;
|
||||
offset = (offset_size_8 ? read_8_bytes(data) : read_4_bytes(data));
|
||||
ArrayList<String> foundMacros = t_macros.get(Long.valueOf(offset));
|
||||
if (foundMacros != null)
|
||||
macros.addAll(foundMacros);
|
||||
else if (lt_offset >= 0) {
|
||||
macros.add(fixupMarker + offset); // leave a marker we can fix up later
|
||||
if (DEBUG)
|
||||
System.out.println("Adding fixup for offset: " + offset + " for file: " + fileName); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
fixupList.add(fileName);
|
||||
}
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println(" DW_MACRO_transparent_include - offset : " + offset); //$NON-NLS-1$
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_MACRO_transparent_include_alt: {
|
||||
long offset;
|
||||
offset = (offset_size_8 ? read_8_bytes(data) : read_4_bytes(data));
|
||||
if (lt_offset >= 0) {
|
||||
macros.add("=FIXUPALT=" + offset); // leave a marker we can fix up later //$NON-NLS-1$
|
||||
if (DEBUG)
|
||||
System.out.println("Adding alt fixup for offset: " + offset + " for file: " + fileName); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
fixupAltList.add(fileName);
|
||||
}
|
||||
|
||||
if (DEBUG)
|
||||
System.out.println(" DW_MACRO_transparent_include - offset : " + offset); //$NON-NLS-1$
|
||||
}
|
||||
break;
|
||||
case DwarfConstants.DW_MACRO_end: {
|
||||
if (lt_offset < 0) {
|
||||
if (DEBUG)
|
||||
System.out.println("creating transparent include macros for offset: " + original_position); //$NON-NLS-1$
|
||||
t_macros.put(Long.valueOf(original_position), macros);
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
if (opcodeInfos != null) {
|
||||
OpcodeInfo info = opcodeInfos.get(op);
|
||||
info.readPastEntry(data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set of command line flags used for a particular file name.
|
||||
*
|
||||
* @param fileName - name of file
|
||||
* @return string containing all macros used on command line to compile the file
|
||||
*
|
||||
* @since 5.7
|
||||
*/
|
||||
@Override
|
||||
public String getCompileOptions(String fileName) {
|
||||
if (!m_macros_parsed) {
|
||||
getSourceFiles();
|
||||
getCommandMacrosFromMacroSection();
|
||||
m_macros_parsed = true;
|
||||
}
|
||||
ArrayList<String>macros = m_compileOptionsMap.get(fileName);
|
||||
if (macros == null)
|
||||
return ""; //$NON-NLS-1$
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (String option: macros) {
|
||||
sb.append(option);
|
||||
sb.append(" "); //$NON-NLS-1$
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,12 +11,11 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.utils.elf;
|
||||
|
||||
import java.io.EOFException;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.ByteUtils.makeShort;
|
||||
import static org.eclipse.cdt.internal.core.ByteUtils.makeInt;
|
||||
import static org.eclipse.cdt.internal.core.ByteUtils.makeLong;
|
||||
import static org.eclipse.cdt.internal.core.ByteUtils.makeShort;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel.MapMode;
|
||||
|
@ -301,6 +300,12 @@ public class Elf {
|
|||
public final static int SHF_WRITE = 1;
|
||||
public final static int SHF_ALLOC = 2;
|
||||
public final static int SHF_EXECINTR = 4;
|
||||
|
||||
/* note_types */
|
||||
/**
|
||||
* @since 5.7
|
||||
*/
|
||||
public final static int NT_GNU_BUILD_ID = 3;
|
||||
|
||||
public long sh_name;
|
||||
public long sh_type;
|
||||
|
|
Loading…
Add table
Reference in a new issue