/* | |
* Copyright (c) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies). | |
* All rights reserved. | |
* This component and the accompanying materials are made available | |
* under the terms of the License "Eclipse Public License v1.0" | |
* which accompanies this distribution, and is available | |
* at the URL "http://www.eclipse.org/legal/epl-v10.html". | |
* | |
* Initial Contributors: | |
* Nokia Corporation - initial contribution. | |
* | |
* Contributors: | |
* | |
* Description: | |
* | |
*/ | |
package org.eclipse.cdt.debug.edc.tests; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.HashMap; | |
import java.util.LinkedHashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Random; | |
import org.eclipse.cdt.core.IAddress; | |
import org.eclipse.cdt.debug.edc.internal.HostOS; | |
import org.eclipse.cdt.debug.edc.internal.PathUtils; | |
import org.eclipse.cdt.debug.edc.internal.services.dsf.EDCSymbolReader; | |
import org.eclipse.cdt.debug.edc.internal.services.dsf.Symbols; | |
import org.eclipse.cdt.debug.edc.internal.symbols.ICompositeType; | |
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfDebugInfoProvider; | |
import org.eclipse.cdt.debug.edc.internal.symbols.dwarf.DwarfInfoReader; | |
import org.eclipse.cdt.debug.edc.symbols.ICompileUnitScope; | |
import org.eclipse.cdt.debug.edc.symbols.IDebugInfoProvider; | |
import org.eclipse.cdt.debug.edc.symbols.IEDCSymbolReader; | |
import org.eclipse.cdt.debug.edc.symbols.IFunctionScope; | |
import org.eclipse.cdt.debug.edc.symbols.IModuleScope; | |
import org.eclipse.cdt.debug.edc.symbols.IScope; | |
import org.eclipse.cdt.debug.edc.symbols.IType; | |
import org.eclipse.cdt.debug.edc.symbols.IVariable; | |
import org.eclipse.cdt.debug.edc.symbols.TypeUtils; | |
import org.eclipse.cdt.utils.Addr32; | |
import org.eclipse.core.runtime.IPath; | |
import org.junit.Before; | |
/** | |
* | |
*/ | |
public abstract class AbstractDwarfReaderTest extends BaseDwarfTestCase { | |
protected static final String[] symFilesToTest = { | |
"BlackFlagMinGW.exe", | |
"BlackFlag_gcce.sym", | |
"BlackFlag_linuxgcc.exe", | |
"BlackFlag_rvct.sym", | |
"BlackFlag_gcce_343.sym", | |
"HelloWorld_rvct_2_2.exe.sym", | |
"HelloWorld_rvct_4_0.exe.sym", | |
"QtConsole_gcce_343.sym", | |
"SimpleCpp_rvct_22.sym", | |
"SimpleCpp_rvct_40.sym", | |
"SimpleCpp_gcce_432.sym", | |
"SimpleCpp_gcc_x86.exe", | |
}; | |
/** Bag of data for testing sym files. The key is 'symFile' and other | |
* elements are used by specific tests. | |
*/ | |
protected static class TestInfo { | |
public IPath symFile; | |
IPath exeFile; | |
int numberOfSources; | |
int numberOfModuleScopeChildren; | |
int numberOfVariables; | |
Map<String, Map<String, VariableInfo>> cuVarMap | |
= new HashMap<String, Map<String,VariableInfo>>(); | |
int numberOfTypes; | |
IPath blackFlagMainFilePath; | |
int numberOfSymbols; | |
int numberOfPubFuncNames; | |
int numberOfPubFuncEntries; | |
int numberOfPubVarNames; | |
int numberOfPubVarEntries; | |
List<String> pubVars = new ArrayList<String>(); | |
List<String> pubFuncs = new ArrayList<String>(); | |
Map<String, List<ScopeInfo>> scopeInfos | |
= new LinkedHashMap<String, List<ScopeInfo>>(); | |
IAddress lowAddress; | |
IAddress highAddress; | |
Collection<SymbolInfo> symbols; | |
} | |
protected static Map<String, TestInfo> testInfos | |
= new LinkedHashMap<String, TestInfo>(); | |
static { | |
for (String sym : symFilesToTest) { | |
TestInfo info = new TestInfo(); | |
info.symFile = getFile(sym); | |
testInfos.put(sym, info); | |
} | |
} | |
protected static TestInfo lookupInfo(String sym) { | |
return testInfos.get(sym); | |
} | |
protected static void setExe(String sym, String exe) { | |
TestInfo info = lookupInfo(sym); | |
if (info != null) | |
info.exeFile = getFile(exe); | |
} | |
// not all the *.exes really exist; used to test mapping from *.exe to *.sym | |
static { | |
setExe("BlackFlagMinGW.exe", "BlackFlagMinGW.exe"); | |
setExe("BlackFlag_gcce.sym", "BlackFlag_gcce.exe"); | |
setExe("BlackFlag_linuxgcc.exe", "BlackFlag_linuxgcc.exe"); | |
setExe("BlackFlag_rvct.sym", "BlackFlag_rvct.exe"); | |
setExe("HelloWorld_rvct_2_2.exe.sym", "HelloWorld_rvct_2_2.exe"); | |
setExe("HelloWorld_rvct_4_0.exe.sym", "HelloWorld_rvct_4_0.exe"); | |
setExe("QtConsole_gcce_343.sym", "QtConsole_gcce_343.exe"); | |
} | |
protected static void setSources(String sym, int i) { | |
TestInfo info = lookupInfo(sym); | |
if (info != null) | |
info.numberOfSources = i; | |
} | |
static { | |
// TODO: this differs in Win and Lin | |
setSources("BlackFlagMinGW.exe", 121); | |
setSources("BlackFlag_gcce.sym", 108); | |
setSources("BlackFlag_linuxgcc.exe", 139); | |
setSources("BlackFlag_rvct.sym", HostOS.IS_WIN32 ? 207 : 172); | |
setSources("HelloWorld_rvct_2_2.exe.sym", HostOS.IS_WIN32 ? 323 : 320); | |
setSources("HelloWorld_rvct_4_0.exe.sym", 315); | |
setSources("QtConsole_gcce_343.sym", 434); | |
} | |
protected static void setModuleScopeChilden(String sym, int i) { | |
TestInfo info = lookupInfo(sym); | |
if (info != null) | |
info.numberOfModuleScopeChildren = i; | |
} | |
static { | |
setModuleScopeChilden("BlackFlagMinGW.exe", 29); | |
setModuleScopeChilden("BlackFlag_gcce.sym", 27); | |
setModuleScopeChilden("BlackFlag_linuxgcc.exe", 25); | |
setModuleScopeChilden("BlackFlag_rvct.sym", 693); | |
setModuleScopeChilden("HelloWorld_rvct_2_2.exe.sym", 1579); | |
setModuleScopeChilden("HelloWorld_rvct_4_0.exe.sym", 1014); | |
setModuleScopeChilden("QtConsole_gcce_343.sym", 3); | |
} | |
protected static void setStartEndAddress(String sym, IAddress startAddress, IAddress endAddress) { | |
TestInfo info = lookupInfo(sym); | |
assertNotNull(info); | |
info.lowAddress = startAddress; | |
info.highAddress = endAddress; | |
} | |
static { | |
setStartEndAddress("BlackFlagMinGW.exe", new Addr32("0x00401000"), new Addr32("0x0046d2c0")); | |
setStartEndAddress("BlackFlag_gcce.sym", new Addr32("0x00008000"), new Addr32("0x0040a028")); | |
//start address for linuxgcc indicated only by program header not by sections or symbols | |
setStartEndAddress("BlackFlag_linuxgcc.exe", new Addr32("0x08048000"), new Addr32("0x0805a01c")); | |
setStartEndAddress("BlackFlag_rvct.sym", new Addr32("0x00008000"), new Addr32("0x0040a018")); | |
setStartEndAddress("HelloWorld_rvct_2_2.exe.sym", new Addr32("0x00008000"), new Addr32("0x00400008")); | |
setStartEndAddress("HelloWorld_rvct_4_0.exe.sym", new Addr32("0x00008000"), new Addr32("0x00400070")); | |
setStartEndAddress("QtConsole_gcce_343.sym", new Addr32("0x00008000"), new Addr32("0x00400008")); | |
} | |
protected static void setVariableCount(String sym, int i) { | |
TestInfo info = lookupInfo(sym); | |
if (info != null) | |
info.numberOfVariables = i; | |
} | |
static { | |
setVariableCount("BlackFlagMinGW.exe", 52); | |
setVariableCount("BlackFlag_gcce.sym", 105); | |
setVariableCount("BlackFlag_linuxgcc.exe", 48); | |
setVariableCount("BlackFlag_rvct.sym", 61); | |
setVariableCount("HelloWorld_rvct_2_2.exe.sym", 1); | |
setVariableCount("HelloWorld_rvct_4_0.exe.sym", 1); | |
setVariableCount("QtConsole_gcce_343.sym", 2); | |
} | |
static class VariableInfo { | |
String name; | |
String typeName; | |
public VariableInfo(String name, String typeName) { | |
this.name = name; | |
this.typeName = typeName; | |
} | |
} | |
protected static void setCUVariableInfo(String sym, String cu, String var, | |
String type) { | |
TestInfo info = lookupInfo(sym); | |
if (info != null) { | |
VariableInfo vi = new VariableInfo(var, type); | |
Map<String, VariableInfo> varMap = info.cuVarMap.get(cu); | |
if (varMap == null) { | |
varMap = new HashMap<String, VariableInfo>(); | |
info.cuVarMap.put(cu, varMap); | |
} | |
varMap.put(var, vi); | |
} | |
} | |
static { | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/INC/dbg_namespaceRealms.h", "KBase", | |
"const class TLitC8"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/INC/dbg_namespaceRealms.h", "KDer1", | |
"const class TLitC8"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/INC/dbg_namespaceRealms.h", "KDer2", | |
"const class TLitC8"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/INC/dbg_namespaceRealms.h", "KDerDer", | |
"const class TLitC8"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/INC/dbg_namespaceRealms.h", "KIFace1", | |
"const class TLitC8"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/INC/dbg_namespaceRealms.h", "KIFace2", | |
"const class TLitC8"); | |
setCUVariableInfo( | |
"BlackFlag_rvct.sym", | |
"M:/sf/os/kernelhwsrv/kernel/eka/compsupp/symaehabi/callfirstprocessfn.cpp", | |
"KLitUser", "const class TLitC"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/INC/CommonFramework.h", "KTxtEPOC32EX", | |
"const class TLitC"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/INC/CommonFramework.h", "KTxtExampleCode", | |
"const class TLitC"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/INC/CommonFramework.h", "KFormatFailed", | |
"const class TLitC"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/INC/CommonFramework.h", "KTxtOK", | |
"const class TLitC"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/INC/CommonFramework.h", "KTxtPressAnyKey", | |
"const class TLitC"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/INC/CommonFramework.h", "console", | |
"class CConsoleBase *"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sgchar", "char"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sgdouble", "double"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sgfloat", "float"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sgint", "int"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sglong", "long"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sglongdouble", | |
"long double"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sgschar", "SCHAR"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sgshort", "short"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sgsint", "SINT"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sgslong", "SLONG"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sgslonglong", | |
"SLONGLONG"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sgsshort", "SSHORT"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sguchar", "UCHAR"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sguint", "UINT"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sgulong", "ULONG"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sgulonglong", | |
"ULONGLONG"); | |
setCUVariableInfo("BlackFlag_rvct.sym", | |
"/BlackFlag/SRC/dbg_simple_types.cpp", "sgushort", "USHORT"); | |
setCUVariableInfo( | |
"HelloWorld_rvct_2_2.exe.sym", | |
"/home/eswartz/source/runtime-New_configuration/ArmTest/inc/ArmTestApplication.h", | |
"KUidArmTestApp", "const class TUid"); | |
setCUVariableInfo( | |
"HelloWorld_rvct_2_2.exe.sym", | |
"/src/cedar/generic/base/e32/compsupp/symaehabi/callfirstprocessfn.cpp", | |
"KLitUser", "const class TLitC"); | |
setCUVariableInfo( | |
"HelloWorld_rvct_2_2.exe.sym", | |
"/home/eswartz/source/runtime-New_configuration/ArmTest/src/ArmTestAppUi.cpp", | |
"KFileName", "const class TLitC"); | |
setCUVariableInfo( | |
"HelloWorld_rvct_2_2.exe.sym", | |
"/home/eswartz/source/runtime-New_configuration/ArmTest/src/ArmTestAppUi.cpp", | |
"KText", "const class TLitC"); | |
setCUVariableInfo( | |
"HelloWorld_rvct_4_0.exe.sym", | |
"/home/eswartz/source/runtime-New_configuration/ArmTest/src/ArmTestApplication.cpp", | |
"KUidArmTestApp", "const struct TUid"); | |
setCUVariableInfo( | |
"HelloWorld_rvct_4_0.exe.sym", | |
"/home/eswartz/source/runtime-New_configuration/ArmTest/src/ArmTestDocument.cpp", | |
"mylit", "char[5]"); | |
setCUVariableInfo( | |
"HelloWorld_rvct_4_0.exe.sym", | |
"/home/eswartz/source/runtime-New_configuration/ArmTest/src/ArmTestAppUi.cpp", | |
"KFileName", "const struct TLitC"); | |
setCUVariableInfo( | |
"HelloWorld_rvct_4_0.exe.sym", | |
"/home/eswartz/source/runtime-New_configuration/ArmTest/src/ArmTestAppUi.cpp", | |
"KText", "const struct TLitC"); | |
setCUVariableInfo( | |
"HelloWorld_rvct_4_0.exe.sym", | |
"M:/dev2/sf/os/kernelhwsrv/kernel/eka/compsupp/symaehabi/callfirstprocessfn.cpp", | |
"KLitUser", "const struct TLitC"); | |
setCUVariableInfo("QtConsole_gcce_343.sym", | |
"/Source/GCCE3/GCCE3/main.cpp", "myGlobalInt", "int"); | |
} | |
protected static void setTypeCount(String sym, int i) { | |
TestInfo info = lookupInfo(sym); | |
if (info != null) | |
info.numberOfTypes = i; | |
} | |
static { | |
setTypeCount("BlackFlagMinGW.exe", 1378); | |
setTypeCount("BlackFlag_gcce.sym", 3419); | |
setTypeCount("BlackFlag_linuxgcc.exe", 1104); | |
setTypeCount("BlackFlag_rvct.sym", 33708); | |
setTypeCount("HelloWorld_rvct_2_2.exe.sym", 84689); | |
setTypeCount("HelloWorld_rvct_4_0.exe.sym", 31565); | |
setTypeCount("QtConsole_gcce_343.sym", 1434); | |
} | |
protected static void setMainBlackFlagFilePath(String sym, String path) { | |
TestInfo info = lookupInfo(sym); | |
if (info != null) | |
info.blackFlagMainFilePath = PathUtils.createPath(path); | |
} | |
static { | |
setMainBlackFlagFilePath("BlackFlagMinGW.exe", | |
"C:/wascana/workspace/BlackFlagWascana/src/BlackFlagWascana.cpp"); | |
setMainBlackFlagFilePath("BlackFlag_gcce.sym", | |
"/BlackFlag/SRC/main.cpp"); | |
setMainBlackFlagFilePath("BlackFlag_linuxgcc.exe", | |
"/mydisk/myprog/BlackFlag/src/BlackFlagWascana.cpp"); | |
setMainBlackFlagFilePath("BlackFlag_rvct.sym", | |
"\\BlackFlag\\SRC\\main.cpp"); | |
} | |
private static void setSymbolCount(String sym, int i) { | |
TestInfo info = lookupInfo(sym); | |
if (info != null) | |
info.numberOfSymbols = i; | |
} | |
static { | |
setSymbolCount("BlackFlagMinGW.exe", 2520); | |
setSymbolCount("BlackFlag_gcce.sym", 2941); | |
setSymbolCount("BlackFlag_linuxgcc.exe", 469); | |
setSymbolCount("BlackFlag_rvct.sym", 750); | |
setSymbolCount("HelloWorld_rvct_2_2.exe.sym", 194); | |
setSymbolCount("HelloWorld_rvct_4_0.exe.sym", 332); | |
setSymbolCount("QtConsole_gcce_343.sym", 1008); | |
} | |
protected static void setPubCount(String sym, int funcnames, | |
int funcentries, int varnames, int varentries) { | |
TestInfo info = lookupInfo(sym); | |
if (info != null) { | |
info.numberOfPubFuncNames = funcnames; | |
info.numberOfPubFuncEntries = funcentries; | |
info.numberOfPubVarNames = varnames; | |
info.numberOfPubVarEntries = varentries; | |
} | |
} | |
static { | |
setPubCount("BlackFlagMinGW.exe", 209, 241, 52, 52); | |
setPubCount("BlackFlag_gcce.sym", 217, 286, 87, 105); | |
setPubCount("BlackFlag_linuxgcc.exe", 174, 206, 48, 48); | |
setPubCount("BlackFlag_rvct.sym", 100, 101, 51, 87); | |
setPubCount("HelloWorld_rvct_2_2.exe.sym", 11, 14, 2, 4); | |
setPubCount("HelloWorld_rvct_4_0.exe.sym", 958, 978, 1, 1); | |
} | |
protected static void addPubFuncs(String sym, Object... names) { | |
TestInfo info = lookupInfo(sym); | |
if (info != null) { | |
for (Object o : names) { | |
info.pubFuncs.add(o.toString()); | |
} | |
} | |
} | |
static { | |
addPubFuncs("BlackFlagMinGW.exe", "main", "dbg_watchpoints", | |
"Base01::~Base01"); | |
addPubFuncs("BlackFlag_gcce.sym", "E32Main", "dbg_watchpoints", | |
"Base01::~Base01"); | |
addPubFuncs("BlackFlag_gcce_343.sym", "E32Main", "dbg_watchpoints", | |
"Base01::~Base01"); | |
addPubFuncs("BlackFlag_linuxgcc.exe", "main", "dbg_watchpoints", | |
"Base01::~Base01"); | |
addPubFuncs("BlackFlag_rvct.sym", "E32Main", "dbg_watchpoints", | |
"globalDestructorFunc"); | |
addPubFuncs("HelloWorld_rvct_2_2.exe.sym", "E32Main", | |
"CallThrdProcEntry", "CleanupClosePushL"); | |
addPubFuncs("HelloWorld_rvct_4_0.exe.sym", "E32Main", | |
"CallThrdProcEntry", "CleanupClosePushL"); | |
addPubFuncs("QtConsole_gcce_343.sym", "main", "__gxx_personality_v0", | |
"__gnu_unwind_frame"); | |
} | |
protected static void addPubVars(String sym, Object... names) { | |
TestInfo info = lookupInfo(sym); | |
if (info != null) { | |
for (Object o : names) { | |
info.pubVars.add(o.toString()); | |
} | |
} | |
} | |
static { | |
addPubVars("BlackFlagMinGW.exe", "vgushort", "gulong", "char_wp"); | |
addPubVars("BlackFlag_gcce.sym", "vgushort", "gulong", "g_char"); | |
addPubVars("BlackFlag_gcce_343.sym", "vgushort", "gulong", "g_char"); | |
addPubVars("BlackFlag_linuxgcc.exe", "vgushort", "gulong", "gchar"); | |
addPubVars("BlackFlag_rvct.sym", "vgushort", "gulong", "g_char"); | |
addPubVars("HelloWorld_rvct_2_2.exe.sym", "mylit"); | |
addPubVars("HelloWorld_rvct_4_0.exe.sym", "mylit"); | |
addPubVars("QtConsole_gcce_343.sym", "myGlobalInt"); | |
} | |
@Before | |
public void setup() throws Exception { | |
// each test relies on starting from scratch | |
Symbols.releaseReaderCache(); | |
} | |
protected String getTypeName(IType type) { | |
return TypeUtils.getFullTypeName(type); | |
} | |
/** | |
* Get a low-level DWARF reader for the symbol reader for testing | |
* @param symbolReader | |
* @return | |
*/ | |
protected DwarfDebugInfoProvider getDwarfDebugInfoProvider( | |
IEDCSymbolReader symbolReader) { | |
if (!(symbolReader instanceof EDCSymbolReader)) | |
return null; | |
IDebugInfoProvider debugInfoProvider | |
= ((EDCSymbolReader) symbolReader).getDebugInfoProvider(); | |
if (!(debugInfoProvider instanceof DwarfDebugInfoProvider)) | |
return null; | |
DwarfDebugInfoProvider dip | |
= (DwarfDebugInfoProvider) debugInfoProvider; | |
// do initial parse (so forward types are detected) | |
DwarfInfoReader reader = new DwarfInfoReader(dip); | |
dip.setParsedInitially(); | |
reader.parseInitial(); | |
dip.setParsedForAddresses(); | |
reader.parseForAddresses(true); | |
return dip; | |
} | |
/** | |
* @param symbolReader | |
*/ | |
protected void readFully(IEDCSymbolReader symbolReader) { | |
IModuleScope moduleScope = symbolReader.getModuleScope(); | |
moduleScope.getChildren(); | |
moduleScope.getVariablesByName(null, false); | |
moduleScope.getVariablesByName(null, true); | |
moduleScope.getFunctionsByName(null); | |
moduleScope.getFunctionByName(null); | |
} | |
/** | |
* @param symbolReader | |
*/ | |
protected void readRandomly(IEDCSymbolReader symbolReader) { | |
IModuleScope moduleScope = symbolReader.getModuleScope(); | |
IAddress low = moduleScope.getLowAddress(); | |
IAddress high = moduleScope.getHighAddress(); | |
long range = high.getValue().subtract(low.getValue()).longValue(); | |
assertTrue(range > 0); | |
Random random = new Random(0x120044ff); | |
for (int cnt = 0; cnt < 1000; cnt++) { | |
switch (random.nextInt() % 4) { | |
case 0: { | |
IAddress addr = low.add(random.nextLong() % range); | |
moduleScope.getScopeAtAddress(addr); | |
break; | |
} | |
case 1: { | |
ICompileUnitScope scope | |
= getRandomCU(symbolReader, random, true); | |
if (scope != null) { | |
long curange | |
= scope.getHighAddress() | |
.getValue() | |
.subtract(scope.getLowAddress().getValue()) | |
.longValue(); | |
IAddress addr | |
= scope.getLowAddress() | |
.add(random.nextLong() % curange); | |
scope.getFunctionAtAddress(addr); | |
} | |
break; | |
} | |
case 2: { | |
ICompileUnitScope scope | |
= getRandomCU(symbolReader, random, false); | |
if (scope != null) { | |
scope.getVariables(); | |
} | |
break; | |
} | |
case 3: { | |
ICompileUnitScope scope | |
= getRandomCU(symbolReader, random, false); | |
if (scope != null) { | |
scope.getEnumerators(); | |
} | |
break; | |
} | |
} | |
} | |
} | |
/** | |
* @param symbolReader | |
* @return | |
*/ | |
protected ICompileUnitScope getRandomCU(IEDCSymbolReader symbolReader, | |
Random random, boolean withCode) { | |
String[] srcs = symbolReader.getSourceFiles(); | |
int tries = 10; | |
Collection<ICompileUnitScope> scopes = null; | |
while (tries-- > 0) { | |
IPath src | |
= PathUtils.createPath(srcs[(random.nextInt() & 0xfffff) | |
% srcs.length]); | |
scopes = symbolReader.getModuleScope().getCompileUnitsForFile(src); | |
if (!scopes.isEmpty()) | |
break; | |
} | |
if (scopes == null) | |
return null; | |
ICompileUnitScope last = null; | |
for (ICompileUnitScope scope : scopes) { | |
if (withCode) { | |
long curange | |
= scope.getHighAddress() | |
.getValue() | |
.subtract(scope.getLowAddress().getValue()) | |
.longValue(); | |
if (curange > 0) { | |
last = scope; | |
if (random.nextBoolean()) { | |
return scope; | |
} | |
} | |
} | |
else if (random.nextInt(5) == 0) { | |
return scope; | |
} | |
} | |
return last; | |
} | |
/** | |
* @return | |
*/ | |
protected String describeScope(IScope scope) { | |
if (scope == null) | |
return ""; | |
String myscope | |
= scope.getClass().getSimpleName() + "[" | |
+ scope.getName() + "]"; | |
return describeScope(scope.getParent()) + ": " + myscope; | |
} | |
/** | |
* @param name | |
* @return | |
*/ | |
protected String stripName(String name) { | |
int idx = name.lastIndexOf(':'); | |
if (idx > 0) | |
return name.substring(idx+1); | |
else | |
return name; | |
} | |
static class ScopeInfo { | |
int address; | |
String[] names; | |
public ScopeInfo(int address, String[] names) { | |
super(); | |
this.address = address; | |
this.names = names; | |
} | |
} | |
protected static void addScopeVars(String sym, String srcFile, | |
String function, String className, int address, String... names) { | |
TestInfo info = lookupInfo(sym); | |
if (info != null) { | |
ScopeInfo scope = new ScopeInfo(address, names); | |
List<ScopeInfo> scopes; | |
String key = srcFile + "|" + function + "|" + className; | |
scopes = info.scopeInfos.get(key); | |
if (scopes == null) { | |
scopes = new ArrayList<ScopeInfo>(); | |
info.scopeInfos.put(key, scopes); | |
} | |
scopes.add(scope); | |
} | |
} | |
static { | |
/* | |
* The address information for the unit test is gathered like this: | |
* | |
* 1) Find a function of interest, usually with DW_TAG_lexical_block | |
* entries inside DW_TAG_subroutine. | |
* | |
* 2) Add a PC for the entry point (DW_AT_low_pc for that subroutine). | |
* Usually DW_TAG_formal_parameter entries are live here. Any | |
* DW_TAG_variable entries with DW_AT_scope==0 (or unspecified) are also | |
* live. | |
* | |
* 3) Find some interesting points where lexical blocks open and add the | |
* variables from there. | |
* | |
* 4) Referencing the original source code is useful too, to avoid | |
* getting confused. | |
* | |
* 5) Finally, ALSO check the DW_AT_location entries for the variables. | |
* If it references a location list (rather than a static expression), | |
* then the compiler is indicating that the variable has a narrower | |
* scope than otherwise indicated. But, that location list may specify | |
* locations *outside* the advertised lexical block scope. So those | |
* should not be considered. Note that RVCT may have bogus lexical block | |
* ranges, but the location lists are useful. GCC-E, on the other hand, | |
* has better lexical block ranges, but never uses location lists. | |
*/ | |
// RVCT has totally broken scope info; all lexical scopes go backwards, | |
// so | |
// we clamp them to the end of the function | |
// entry to function | |
addScopeVars("BlackFlag_rvct.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0xb3e0); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0xb3e4, "stackArray"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0xb3ee, "stackArray" /* , "pstackArray" */); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0xb3f0, "stackArray", "pstackArray"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0xb3f0 + 2, "stackArray", "pstackArray"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0xb3f4, "stackArray", "pstackArray", "i", "value"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0xb40a, "stackArray", "pstackArray", "pheapArray", | |
"value"); | |
// GCCE has valid scope info | |
// entry to function | |
addScopeVars("BlackFlag_gcce.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0x10854); | |
addScopeVars("BlackFlag_gcce.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0x1085a, "stackArray", "pstackArray", "value", | |
"pheapArray", "objArray", "pobj"); | |
addScopeVars("BlackFlag_gcce.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0x10876, "stackArray", "pstackArray", "value", | |
"pheapArray", "objArray", "pobj", "i"); | |
addScopeVars("BlackFlag_gcce.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0x108ac + 2, "stackArray", "pstackArray", "value", | |
"pheapArray", "objArray", "pobj"); | |
addScopeVars("BlackFlag_gcce.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0x108b8 + 4, "stackArray", "pstackArray", "value", | |
"pheapArray", "objArray", "pobj", "j"); | |
addScopeVars("BlackFlag_gcce.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0x108f2 + 2, "stackArray", "pstackArray", "value", | |
"pheapArray", "objArray", "pobj", "k"); | |
addScopeVars("BlackFlag_gcce.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0x10970 + 2, "stackArray", "pstackArray", "value", | |
"pheapArray", "objArray", "pobj", "m"); | |
// show all variables at end of function, but not variable of last for | |
// loop scope | |
addScopeVars("BlackFlag_gcce.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0x10a2a, "stackArray", "pstackArray", "value", | |
"pheapArray", "objArray", "pobj"); | |
// but not past, in case instruction stepping at end of function | |
addScopeVars("BlackFlag_gcce.sym", "dbg_pointers.cpp", "ptrToArray", | |
null, 0x10a2a + 2); | |
// entry to function | |
addScopeVars("BlackFlag_rvct.sym", "dbg_pointers.cpp", "arrayOfPtrs", | |
null, 0xb802); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_pointers.cpp", "arrayOfPtrs", | |
null, 0xb808, "parray", "pClass2", "i"); | |
// entry to function | |
addScopeVars("BlackFlag_rvct.sym", "dbg_linked_lists.cpp", "find", | |
"dlist", 0xa82a, "this", "k"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_linked_lists.cpp", "find", | |
"dlist", 0xa82e, "this", "k"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_linked_lists.cpp", "find", | |
"dlist", 0xa830, "this", "found", "k", "search_node"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_linked_lists.cpp", "find", | |
"dlist", 0xa83c, "this", "found", "k", "search_node", | |
"__result"); | |
// entry to function | |
addScopeVars("BlackFlag_rvct.sym", "dbg_linked_lists.cpp", "find", | |
"list", 0xa652, "this", "k"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_linked_lists.cpp", "find", | |
"list", 0xa656, "this", "k"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_linked_lists.cpp", "find", | |
"list", 0xa658, "this", "k", "found", "aux"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_linked_lists.cpp", "find", | |
"list", 0xa666, "this", "k", "__result", "found", "aux"); | |
// good lexical scopes here | |
// entry to function | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa07a, "this", "key"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa080, "this", "key", | |
"direction", "previous"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa082, "this", "key", | |
"direction", "previous"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa082, "this", "key", | |
"direction", "previous"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa092, "this", "key", | |
"direction", "previous", "theNode"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa098, "this", "key", | |
"__result", "direction", "previous", "theNode"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa0f2, "this", "key", | |
"direction", "previous", "theNode"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa0f8, "this", "key", | |
"direction", "previous", "theNode", "subtree"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa11e, "this", "key", | |
"direction", "previous", "theNode"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa138, "this", "key", | |
"direction", "previous", "theNode"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa164, "this", "key", | |
"direction", "previous", "theNode"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa166, "this", "key", | |
"direction", "previous", "theNode"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa16c, "this", "key", | |
"direction", "previous", "theNode", "pcurrentNode"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa1ea, "this", "key", | |
"direction", "previous", "theNode", "next", "pcurrentNode"); | |
addScopeVars("BlackFlag_rvct.sym", "dbg_binary_tree.cpp", | |
"DeleteFromTree", "binary_tree", 0xa21e, "this", "key", | |
"direction", "previous", "theNode"); | |
// enty to function | |
addScopeVars("SimpleCpp_rvct_22.sym", "Templates.h", "add", "List", | |
0x8386, "this", "item"); | |
addScopeVars("SimpleCpp_rvct_22.sym", "Templates.h", "add", "List", | |
0x8394, "this", "item"); | |
addScopeVars("SimpleCpp_rvct_22.sym", "Templates.h", "add", "List", | |
0x8398, "this", "item", "newmax"); | |
addScopeVars("SimpleCpp_rvct_22.sym", "Templates.h", "add", "List", | |
0x83a6, "this", "item", "newmax", "copy"); | |
addScopeVars("SimpleCpp_rvct_22.sym", "Templates.h", "add", "List", | |
0x83a8, "this", "item", "newmax", "copy", "i"); | |
addScopeVars("SimpleCpp_rvct_22.sym", "Templates.h", "add", "List", | |
0x83b0, "this", "item", "newmax", "copy", "i"); | |
addScopeVars("SimpleCpp_rvct_22.sym", "Templates.h", "add", "List", | |
0x83bc, "this", "item", "newmax", "copy"); | |
addScopeVars("SimpleCpp_rvct_22.sym", "Templates.h", "add", "List", | |
0x83cc); | |
// enty to function | |
addScopeVars("SimpleCpp_rvct_40.sym", "Templates.cpp", "add", "List", | |
0x835a, "this", "item", "__result$$1$$_Znaj"); | |
addScopeVars("SimpleCpp_rvct_40.sym", "Templates.cpp", "add", "List", | |
0x836c, "this", "item", "newmax", "__result$$1$$_Znaj"); | |
addScopeVars("SimpleCpp_rvct_40.sym", "Templates.cpp", "add", "List", | |
0x837a, "this", "item", "newmax", "copy", "__result$$1$$_Znaj"); | |
addScopeVars("SimpleCpp_rvct_40.sym", "Templates.cpp", "add", "List", | |
0x837c, "this", "item", "newmax", "copy", "i", | |
"__result$$1$$_Znaj"); | |
addScopeVars("SimpleCpp_rvct_40.sym", "Templates.cpp", "add", "List", | |
0x83a0, "this", "item", "__result$$1$$_Znaj"); | |
// entry to function | |
addScopeVars("SimpleCpp_gcc_x86.exe", "Templates.cpp", "add", "List", | |
0x80487a6, "this", "item"); | |
addScopeVars("SimpleCpp_gcc_x86.exe", "Templates.cpp", "add", "List", | |
0x80487c0, "this", "item", "newmax", "copy"); | |
addScopeVars("SimpleCpp_gcc_x86.exe", "Templates.cpp", "add", "List", | |
0x80487e9, "this", "item", "newmax", "copy", "i"); | |
addScopeVars("SimpleCpp_gcc_x86.exe", "Templates.cpp", "add", "List", | |
0x804881e + 1, "this", "item", "newmax", "copy"); | |
// show all locals at end of function | |
addScopeVars("SimpleCpp_gcc_x86.exe", "Templates.cpp", "add", "List", | |
0x8048854, "this", "item", "newmax", "copy"); | |
// but not past | |
addScopeVars("SimpleCpp_gcc_x86.exe", "Templates.cpp", "add", "List", | |
0x8048854 + 1, "this", "item"); | |
} | |
/** | |
* | |
*/ | |
protected static class SymbolInfo { | |
public final String name; | |
public final String address; | |
public final long size; | |
public SymbolInfo(String name, String string, long size){ | |
this.name = name; | |
this.address = string; | |
this.size = size; | |
} | |
@Override | |
public String toString(){ | |
return name + ", " + address + ", " + size; | |
} | |
} | |
/** | |
* @param sym | |
* @param symbols | |
*/ | |
protected static void addSymbols(String sym,SymbolInfo... symbols){ | |
TestInfo info = lookupInfo(sym); | |
assertNotNull(info); | |
Collection<SymbolInfo> symInfos = info.symbols; | |
if (symInfos == null){ | |
symInfos = new ArrayList<SymbolInfo>(symbols.length); | |
info.symbols = symInfos; | |
} | |
for (SymbolInfo symInfo : symbols){ | |
symInfos.add(symInfo); | |
} | |
} | |
static { | |
addSymbols("BlackFlag_linuxgcc.exe", | |
new SymbolInfo("vgfloat", "08050300", 4), | |
new SymbolInfo("_Z6arraysv", "0804a09c", 629), | |
new SymbolInfo("_ZN4list14removeFromBackEv", "0804ac10", 102), | |
new SymbolInfo("_ZTI6DerDer", "0804dff4", 12), | |
new SymbolInfo("_GLOBAL__I_gchar", "08048864", 28)); | |
addSymbols("SimpleCpp_gcc_x86.exe", | |
new SymbolInfo("dtor_idx.6637","0804a024",4), | |
new SymbolInfo("_Z41__static_initialization_and_destruction_0ii","0804853f",35), | |
new SymbolInfo("main","080485be",31), | |
new SymbolInfo("__libc_csu_fini","08048860",5), | |
new SymbolInfo("_ZN4ListIcE3addEc","08048602",174)); | |
addSymbols("QtConsole_gcce_343.sym", | |
new SymbolInfo("KErrNone","00009188",4), | |
new SymbolInfo("KDriveAttRom","0000939c",4), | |
new SymbolInfo("_Z21base_of_encoded_valuehP15_Unwind_Context","00008290",116), | |
new SymbolInfo("next_unwind_byte","00008ae8",88), | |
new SymbolInfo("KLitUser","00009638",16), | |
//Address 14 rather than 15 due to ARM thumb bit | |
new SymbolInfo("RunThread","00008014",48)); | |
} | |
/** | |
* @param scope | |
* @return | |
*/ | |
protected String getClassFor(IFunctionScope scope) { | |
for (IVariable arg : scope.getParameters()) { | |
if (arg.getName().equals("this")) { | |
ICompositeType ct | |
= (ICompositeType) TypeUtils.getBaseType(arg.getType()); | |
return ct.getName(); | |
} | |
} | |
return null; | |
} | |
} |