mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 09:25:31 +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;
|
||||
|
||||
boolean printEnabled = true;
|
||||
|
||||
public Dwarf(String file) throws IOException {
|
||||
Elf exe = new Elf(file);
|
||||
init(exe);
|
||||
|
@ -340,15 +342,18 @@ public class Dwarf {
|
|||
header.abbreviationOffset = read_4_bytes(data, offset + 6);
|
||||
header.addressSize = data[offset + 10];
|
||||
|
||||
System.out.println("Compilation Unit @ " + Long.toHexString(offset)); //$NON-NLS-1$
|
||||
System.out.println(header);
|
||||
if (printEnabled) {
|
||||
System.out.println("Compilation Unit @ " + Long.toHexString(offset)); //$NON-NLS-1$
|
||||
System.out.println(header);
|
||||
}
|
||||
|
||||
// read the abbrev section.
|
||||
InputStream in = new ByteArrayInputStream(data, offset + 11, length);
|
||||
Map abbrevs = parseDebugAbbreviation(header);
|
||||
parseDebugInfoEntry(requestor, in, abbrevs, header);
|
||||
|
||||
System.out.println();
|
||||
if (printEnabled)
|
||||
System.out.println();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -562,10 +567,13 @@ public class Dwarf {
|
|||
void processDebugInfoEntry(IDebugEntryRequestor requestor, AbbreviationEntry entry, List list) {
|
||||
int len = list.size();
|
||||
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++) {
|
||||
AttributeValue av = (AttributeValue) list.get(i);
|
||||
System.out.println(av);
|
||||
if (printEnabled)
|
||||
System.out.println(av);
|
||||
// We are only interrested in certain tags.
|
||||
switch (tag) {
|
||||
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.IAddress;
|
||||
import org.eclipse.cdt.core.IAddressFactory;
|
||||
import org.eclipse.cdt.core.ISymbolReader;
|
||||
import org.eclipse.cdt.utils.Addr32;
|
||||
import org.eclipse.cdt.utils.Addr32Factory;
|
||||
import org.eclipse.cdt.utils.Addr64;
|
||||
import org.eclipse.cdt.utils.Addr64Factory;
|
||||
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
|
||||
public class Elf {
|
||||
|
@ -1141,4 +1146,22 @@ public class Elf {
|
|||
}
|
||||
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.IBinaryParser;
|
||||
import org.eclipse.cdt.core.ISymbolReader;
|
||||
import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
|
||||
import org.eclipse.cdt.core.IBinaryParser.ISymbol;
|
||||
import org.eclipse.cdt.utils.AR;
|
||||
|
@ -183,6 +184,12 @@ public class ElfBinaryObject extends BinaryObjectAdapter {
|
|||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
if (adapter.equals(ISymbolReader.class)) {
|
||||
Elf elf = (Elf)getAdapter(Elf.class);
|
||||
if (elf != null) {
|
||||
return elf.getSymbolReader();
|
||||
}
|
||||
}
|
||||
return super.getAdapter(adapter);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue