mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-09-10 12:03:16 +02:00
Added support for extracting the list of source files from ELF-DWARF.
This commit is contained in:
parent
f9320a494a
commit
65b8437bda
4 changed files with 331 additions and 5 deletions
|
@ -163,6 +163,8 @@ public class Dwarf {
|
||||||
|
|
||||||
CompileUnit currentCU;
|
CompileUnit currentCU;
|
||||||
|
|
||||||
|
boolean printEnabled = true;
|
||||||
|
|
||||||
public Dwarf(String file) throws IOException {
|
public Dwarf(String file) throws IOException {
|
||||||
Elf exe = new Elf(file);
|
Elf exe = new Elf(file);
|
||||||
init(exe);
|
init(exe);
|
||||||
|
@ -340,15 +342,18 @@ public class Dwarf {
|
||||||
header.abbreviationOffset = read_4_bytes(data, offset + 6);
|
header.abbreviationOffset = read_4_bytes(data, offset + 6);
|
||||||
header.addressSize = data[offset + 10];
|
header.addressSize = data[offset + 10];
|
||||||
|
|
||||||
System.out.println("Compilation Unit @ " + Long.toHexString(offset)); //$NON-NLS-1$
|
if (printEnabled) {
|
||||||
System.out.println(header);
|
System.out.println("Compilation Unit @ " + Long.toHexString(offset)); //$NON-NLS-1$
|
||||||
|
System.out.println(header);
|
||||||
|
}
|
||||||
|
|
||||||
// read the abbrev section.
|
// read the abbrev section.
|
||||||
InputStream in = new ByteArrayInputStream(data, offset + 11, length);
|
InputStream in = new ByteArrayInputStream(data, offset + 11, length);
|
||||||
Map abbrevs = parseDebugAbbreviation(header);
|
Map abbrevs = parseDebugAbbreviation(header);
|
||||||
parseDebugInfoEntry(requestor, in, abbrevs, header);
|
parseDebugInfoEntry(requestor, in, abbrevs, header);
|
||||||
|
|
||||||
System.out.println();
|
if (printEnabled)
|
||||||
|
System.out.println();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -562,10 +567,13 @@ public class Dwarf {
|
||||||
void processDebugInfoEntry(IDebugEntryRequestor requestor, AbbreviationEntry entry, List list) {
|
void processDebugInfoEntry(IDebugEntryRequestor requestor, AbbreviationEntry entry, List list) {
|
||||||
int len = list.size();
|
int len = list.size();
|
||||||
int tag = (int) entry.tag;
|
int tag = (int) entry.tag;
|
||||||
System.out.println("Abbrev Number " + entry.code); //$NON-NLS-1$
|
if (printEnabled)
|
||||||
|
System.out.println("Abbrev Number " + entry.code); //$NON-NLS-1$
|
||||||
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
AttributeValue av = (AttributeValue) list.get(i);
|
AttributeValue av = (AttributeValue) list.get(i);
|
||||||
System.out.println(av);
|
if (printEnabled)
|
||||||
|
System.out.println(av);
|
||||||
// We are only interrested in certain tags.
|
// We are only interrested in certain tags.
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case DwarfConstants.DW_TAG_array_type :
|
case DwarfConstants.DW_TAG_array_type :
|
||||||
|
|
|
@ -0,0 +1,288 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2006 Nokia 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:
|
||||||
|
* Nokia - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.utils.debug.dwarf;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.ISymbolReader;
|
||||||
|
import org.eclipse.cdt.utils.debug.IDebugEntryRequestor;
|
||||||
|
import org.eclipse.cdt.utils.elf.Elf;
|
||||||
|
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 {
|
||||||
|
|
||||||
|
// These are sections that must 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
|
||||||
|
};
|
||||||
|
|
||||||
|
ArrayList fileList;
|
||||||
|
String[] files = null;
|
||||||
|
boolean m_parsed = false;
|
||||||
|
private int m_leb128Size = 0;
|
||||||
|
|
||||||
|
public DwarfReader(String file) throws IOException {
|
||||||
|
super(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DwarfReader(Elf exe) throws IOException {
|
||||||
|
super(exe);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override parent.
|
||||||
|
//
|
||||||
|
public void init(Elf exe) throws IOException {
|
||||||
|
Elf.ELFhdr header = exe.getELFhdr();
|
||||||
|
isLE = header.e_ident[Elf.ELFhdr.EI_DATA] == Elf.ELFhdr.ELFDATA2LSB;
|
||||||
|
|
||||||
|
Elf.Section[] sections = exe.getSections();
|
||||||
|
|
||||||
|
// Read in sections (and only the sections) we care about.
|
||||||
|
//
|
||||||
|
for (int i = 0; i < sections.length; i++) {
|
||||||
|
String name = sections[i].toString();
|
||||||
|
for (int j = 0; j < DWARF_SectionsToParse.length; j++) {
|
||||||
|
if (name.equals(DWARF_SectionsToParse[j])) {
|
||||||
|
dwarfSections.put(DWARF_SectionsToParse[j], sections[i].loadSectionData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dwarfSections.size() < DWARF_SectionsToParse.length)
|
||||||
|
throw new IOException("No enough Dwarf data.");
|
||||||
|
|
||||||
|
// Don't print during parsing.
|
||||||
|
printEnabled = false;
|
||||||
|
|
||||||
|
m_parsed = false;
|
||||||
|
fileList = new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse line table data of a compilation unit to get names of all source files
|
||||||
|
* that contribute to the compilation unit.
|
||||||
|
*/
|
||||||
|
void parseSourceInCULineInfo(
|
||||||
|
String cuCompDir, // compilation directory of the CU
|
||||||
|
int cuStmtList) // offste of the CU in the line table section
|
||||||
|
{
|
||||||
|
byte[] data = (byte[]) dwarfSections.get(DWARF_DEBUG_LINE);
|
||||||
|
if (data != null) {
|
||||||
|
try {
|
||||||
|
int offset = cuStmtList;
|
||||||
|
|
||||||
|
/* Read line table header:
|
||||||
|
*
|
||||||
|
* total_length: 4 bytes
|
||||||
|
* version: 2
|
||||||
|
* prologue length: 4
|
||||||
|
* minimum_instruction_len: 1
|
||||||
|
* default_is_stmt: 1
|
||||||
|
* line_base: 1
|
||||||
|
* line_range: 1
|
||||||
|
* opcode_base: 1
|
||||||
|
* standard_opcode_lengths: (value of opcode_base)
|
||||||
|
*/
|
||||||
|
// Skip the following till "opcode_base"
|
||||||
|
offset = offset + 14;
|
||||||
|
int opcode_base = data[offset++];
|
||||||
|
offset += 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, offset);
|
||||||
|
if (str.length() == 0)
|
||||||
|
break;
|
||||||
|
dirList.add(str);
|
||||||
|
offset += str.length()+1;
|
||||||
|
}
|
||||||
|
offset++;
|
||||||
|
|
||||||
|
// Read file names
|
||||||
|
//
|
||||||
|
long leb128;
|
||||||
|
while (true) {
|
||||||
|
fileName = readString(data, offset);
|
||||||
|
if (fileName.length() == 0) // no more file entry
|
||||||
|
break;
|
||||||
|
offset += fileName.length()+1;
|
||||||
|
|
||||||
|
// dir index
|
||||||
|
leb128 = read_unsigned_leb128(data, offset);
|
||||||
|
offset += m_leb128Size;
|
||||||
|
|
||||||
|
addSourceFile((String)dirList.get((int)leb128), fileName);
|
||||||
|
|
||||||
|
// Skip the followings
|
||||||
|
//
|
||||||
|
// modification time
|
||||||
|
leb128 = read_unsigned_leb128(data, offset);
|
||||||
|
offset += m_leb128Size;
|
||||||
|
|
||||||
|
// file size in bytes
|
||||||
|
leb128 = read_unsigned_leb128(data, offset);
|
||||||
|
offset += m_leb128Size;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getSourceFiles() {
|
||||||
|
if (!m_parsed) {
|
||||||
|
parse(null);
|
||||||
|
m_parsed = true;
|
||||||
|
|
||||||
|
files = new String[fileList.size()];
|
||||||
|
fileList.toArray(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSourceFile(String dir, String name)
|
||||||
|
{
|
||||||
|
if (name == null)
|
||||||
|
return;
|
||||||
|
if (name.charAt(0) == '<') // don't count the entry "<internal>" from GCCE compiler
|
||||||
|
return;
|
||||||
|
|
||||||
|
String fullName = name;
|
||||||
|
|
||||||
|
Path pa = new Path(name);
|
||||||
|
if (! pa.isAbsolute() && dir.length() > 0)
|
||||||
|
fullName = dir + File.separatorChar + name;
|
||||||
|
|
||||||
|
// This convert the path to canonical path (but not necessarily absolute, which
|
||||||
|
// is different from java.io.File.getCanonicalPath()).
|
||||||
|
pa = new Path(fullName);
|
||||||
|
fullName = pa.toOSString();
|
||||||
|
|
||||||
|
if (!fileList.contains(fullName))
|
||||||
|
fileList.add(fullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a null-ended string from the given "data" stream starting at the given "offset".
|
||||||
|
* data : IN, byte stream
|
||||||
|
* offset: IN, offset in the stream
|
||||||
|
*/
|
||||||
|
String readString(byte[] data, int offset)
|
||||||
|
{
|
||||||
|
String str;
|
||||||
|
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
for (; offset < data.length; offset++) {
|
||||||
|
byte c = data[offset];
|
||||||
|
if (c == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sb.append((char) c);
|
||||||
|
}
|
||||||
|
|
||||||
|
str = sb.toString();
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
long read_unsigned_leb128(byte[] data, int offset) throws IOException {
|
||||||
|
/* unsigned */
|
||||||
|
long result = 0;
|
||||||
|
int shift = 0;
|
||||||
|
short b;
|
||||||
|
|
||||||
|
m_leb128Size = 0;
|
||||||
|
while (true) {
|
||||||
|
b = (short) data[offset];
|
||||||
|
if (b == -1)
|
||||||
|
break; //throw new IOException("no more data");
|
||||||
|
m_leb128Size++;
|
||||||
|
result |= ((long) (b & 0x7f) << shift);
|
||||||
|
if ((b & 0x80) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
shift += 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override parent: only handle TAG_Compile_Unit.
|
||||||
|
void processDebugInfoEntry(IDebugEntryRequestor requestor, AbbreviationEntry entry, List list) {
|
||||||
|
int len = list.size();
|
||||||
|
int tag = (int) entry.tag;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
switch (tag) {
|
||||||
|
case DwarfConstants.DW_TAG_compile_unit :
|
||||||
|
processCompileUnit(requestor, list);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override parent.
|
||||||
|
// Just get the file name of the CU.
|
||||||
|
// Argument "requestor" is ignored.
|
||||||
|
void processCompileUnit(IDebugEntryRequestor requestor, List list) {
|
||||||
|
|
||||||
|
String cuName, cuCompDir;
|
||||||
|
int stmtList = -1;
|
||||||
|
|
||||||
|
cuName = cuCompDir = "";
|
||||||
|
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
AttributeValue av = (AttributeValue)list.get(i);
|
||||||
|
try {
|
||||||
|
int name = (int)av.attribute.name;
|
||||||
|
switch(name) {
|
||||||
|
case DwarfConstants.DW_AT_name:
|
||||||
|
cuName = (String)av.value;
|
||||||
|
break;
|
||||||
|
case DwarfConstants.DW_AT_comp_dir:
|
||||||
|
cuCompDir = (String)av.value;
|
||||||
|
break;
|
||||||
|
case DwarfConstants.DW_AT_stmt_list:
|
||||||
|
stmtList = ((Number)av.value).intValue();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addSourceFile(cuCompDir, cuName);
|
||||||
|
if (stmtList > -1) // this CU has "stmt_list" attribute
|
||||||
|
parseSourceInCULineInfo(cuCompDir, stmtList);
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,11 +19,16 @@ import java.util.Comparator;
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
import org.eclipse.cdt.core.IAddress;
|
import org.eclipse.cdt.core.IAddress;
|
||||||
import org.eclipse.cdt.core.IAddressFactory;
|
import org.eclipse.cdt.core.IAddressFactory;
|
||||||
|
import org.eclipse.cdt.core.ISymbolReader;
|
||||||
import org.eclipse.cdt.utils.Addr32;
|
import org.eclipse.cdt.utils.Addr32;
|
||||||
import org.eclipse.cdt.utils.Addr32Factory;
|
import org.eclipse.cdt.utils.Addr32Factory;
|
||||||
import org.eclipse.cdt.utils.Addr64;
|
import org.eclipse.cdt.utils.Addr64;
|
||||||
import org.eclipse.cdt.utils.Addr64Factory;
|
import org.eclipse.cdt.utils.Addr64Factory;
|
||||||
import org.eclipse.cdt.utils.ERandomAccessFile;
|
import org.eclipse.cdt.utils.ERandomAccessFile;
|
||||||
|
import org.eclipse.cdt.utils.coff.Coff.SectionHeader;
|
||||||
|
import org.eclipse.cdt.utils.coff.PE.Attribute;
|
||||||
|
import org.eclipse.cdt.utils.debug.dwarf.DwarfReader;
|
||||||
|
import org.eclipse.cdt.utils.debug.stabs.StabsReader;
|
||||||
|
|
||||||
// test checkin
|
// test checkin
|
||||||
public class Elf {
|
public class Elf {
|
||||||
|
@ -1141,4 +1146,22 @@ public class Elf {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ISymbolReader createDwarfReader() {
|
||||||
|
DwarfReader reader = null;
|
||||||
|
// Check if Dwarf data exists
|
||||||
|
try {
|
||||||
|
reader = new DwarfReader(this);
|
||||||
|
} catch (IOException e) {
|
||||||
|
// No Dwarf data in the Elf.
|
||||||
|
}
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ISymbolReader getSymbolReader() {
|
||||||
|
ISymbolReader reader = null;
|
||||||
|
reader = createDwarfReader();
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.IAddressFactory;
|
import org.eclipse.cdt.core.IAddressFactory;
|
||||||
import org.eclipse.cdt.core.IBinaryParser;
|
import org.eclipse.cdt.core.IBinaryParser;
|
||||||
|
import org.eclipse.cdt.core.ISymbolReader;
|
||||||
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
|
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
|
||||||
import org.eclipse.cdt.core.IBinaryParser.ISymbol;
|
import org.eclipse.cdt.core.IBinaryParser.ISymbol;
|
||||||
import org.eclipse.cdt.utils.AR;
|
import org.eclipse.cdt.utils.AR;
|
||||||
|
@ -183,6 +184,12 @@ public class ElfBinaryObject extends BinaryObjectAdapter {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (adapter.equals(ISymbolReader.class)) {
|
||||||
|
Elf elf = (Elf)getAdapter(Elf.class);
|
||||||
|
if (elf != null) {
|
||||||
|
return elf.getSymbolReader();
|
||||||
|
}
|
||||||
|
}
|
||||||
return super.getAdapter(adapter);
|
return super.getAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue