mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
GP-1633/GP-2308 Added ProgramArchitecture to datatype managers.
Refactored ProjectDataTypeManager to extend StandaloneDataTypeManager. Added actions to datatype tree to allow setting archive architecture. Added use of storage translators when switching architectures. Allow FunctionDefinition to accept arbitrary calling convention names and many other misc changes.
This commit is contained in:
parent
75a185aa9e
commit
a4776892bd
248 changed files with 6282 additions and 2935 deletions
|
@ -24,7 +24,9 @@ import db.DBHandle;
|
|||
import ghidra.framework.model.DomainFile;
|
||||
import ghidra.program.database.data.ProgramBasedDataTypeManagerDB;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressFactory;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.trace.database.DBTrace;
|
||||
import ghidra.trace.database.DBTraceManager;
|
||||
import ghidra.trace.model.data.TraceBasedDataTypeManager;
|
||||
|
@ -38,15 +40,36 @@ import ghidra.util.task.TaskMonitor;
|
|||
public class DBTraceDataTypeManager extends ProgramBasedDataTypeManagerDB
|
||||
implements TraceBasedDataTypeManager, DBTraceManager {
|
||||
|
||||
protected final ReadWriteLock lock;
|
||||
protected final ReadWriteLock lock; // TODO: This lock object is not used
|
||||
protected final DBTrace trace;
|
||||
|
||||
private static final String INSTANCE_TABLE_PREFIX = null; // placeholder only
|
||||
|
||||
public DBTraceDataTypeManager(DBHandle dbh, DBOpenMode openMode, ReadWriteLock lock,
|
||||
TaskMonitor monitor, DBTrace trace)
|
||||
throws CancelledException, VersionException, IOException {
|
||||
super(dbh, null, openMode.toInteger(), trace, trace.getLock(), monitor);
|
||||
super(dbh, null, openMode.toInteger(), INSTANCE_TABLE_PREFIX, trace, trace.getLock(),
|
||||
monitor);
|
||||
this.lock = lock; // TODO: nothing uses this local lock - not sure what its purpose is
|
||||
this.trace = trace;
|
||||
|
||||
setProgramArchitecture(new ProgramArchitecture() {
|
||||
|
||||
@Override
|
||||
public Language getLanguage() {
|
||||
return trace.getBaseLanguage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompilerSpec getCompilerSpec() {
|
||||
return trace.getBaseCompilerSpec();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddressFactory getAddressFactory() {
|
||||
return trace.getBaseAddressFactory();
|
||||
}
|
||||
}, null, false, monitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -233,12 +256,4 @@ public class DBTraceDataTypeManager extends ProgramBasedDataTypeManagerDB
|
|||
*/
|
||||
return ArchiveType.PROGRAM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataOrganization getDataOrganization() {
|
||||
if (dataOrganization == null) {
|
||||
dataOrganization = trace.getBaseCompilerSpec().getDataOrganization();
|
||||
}
|
||||
return dataOrganization;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
*/
|
||||
package ghidra.trace.database.program;
|
||||
|
||||
import static ghidra.lifecycle.Unfinished.TODO;
|
||||
import static ghidra.lifecycle.Unfinished.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import generic.NestedIterator;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
|
@ -64,7 +64,7 @@ public class DBTraceProgramViewFunctionManager implements FunctionManager {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<String> getCallingConventionNames() {
|
||||
public Collection<String> getCallingConventionNames() {
|
||||
return functions.getCallingConventionNames();
|
||||
}
|
||||
|
||||
|
@ -78,11 +78,6 @@ public class DBTraceProgramViewFunctionManager implements FunctionManager {
|
|||
return functions.getCallingConvention(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrototypeModel[] getCallingConventions() {
|
||||
return functions.getCallingConventions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TraceFunctionSymbol createFunction(String name, Address entryPoint, AddressSetView body,
|
||||
SourceType source) throws InvalidInputException, OverlappingFunctionException {
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
|
|||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import db.DBRecord;
|
||||
import ghidra.program.database.data.DataTypeManagerDB;
|
||||
import ghidra.program.database.function.OverlappingFunctionException;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.*;
|
||||
|
@ -33,6 +34,7 @@ import ghidra.program.model.symbol.*;
|
|||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.AddressDBFieldCodec;
|
||||
import ghidra.trace.database.address.DBTraceOverlaySpaceAdapter.DecodesAddresses;
|
||||
import ghidra.trace.database.bookmark.DBTraceBookmarkType;
|
||||
import ghidra.trace.database.data.DBTraceDataTypeManager;
|
||||
import ghidra.trace.database.listing.DBTraceCommentAdapter;
|
||||
import ghidra.trace.database.listing.DBTraceData;
|
||||
import ghidra.trace.database.program.DBTraceProgramView;
|
||||
|
@ -122,7 +124,7 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
|
|||
@DBAnnotatedField(column = FIXUP_COLUMN_NAME)
|
||||
protected String callFixup;
|
||||
@DBAnnotatedField(column = CALLING_CONVENTION_COLUMN_NAME)
|
||||
protected byte callingConventionID = DBTraceSymbolManager.DEFAULT_CALLING_CONVENTION_ID;
|
||||
protected byte callingConventionID = DataTypeManagerDB.UNKNOWN_CALLING_CONVENTION_ID;
|
||||
// TODO: Pack into flags if more bits needed
|
||||
@DBAnnotatedField(column = SIGNATURE_SOURCE_COLUMN_NAME)
|
||||
protected SourceType signatureSource = SourceType.ANALYSIS; // Assumed default, 0-ordinal
|
||||
|
@ -484,7 +486,8 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
|
|||
}
|
||||
|
||||
protected boolean hasExplicitCallingConvention() {
|
||||
return callingConventionID != -1 && callingConventionID != -2;
|
||||
return callingConventionID != DataTypeManagerDB.DEFAULT_CALLING_CONVENTION_ID &&
|
||||
callingConventionID != DataTypeManagerDB.UNKNOWN_CALLING_CONVENTION_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1734,16 +1737,14 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
|
|||
if (cs == null) {
|
||||
return null;
|
||||
}
|
||||
if (DBTraceSymbolManager.UNKNOWN_CALLING_CONVENTION_ID == callingConventionID) {
|
||||
DBTraceDataTypeManager dtm = manager.dataTypeManager;
|
||||
if (callingConventionID == DataTypeManagerDB.UNKNOWN_CALLING_CONVENTION_ID) {
|
||||
return null;
|
||||
}
|
||||
if (DBTraceSymbolManager.DEFAULT_CALLING_CONVENTION_ID == callingConventionID) {
|
||||
if (callingConventionID == DataTypeManagerDB.DEFAULT_CALLING_CONVENTION_ID) {
|
||||
return cs.getDefaultCallingConvention();
|
||||
}
|
||||
String ccName = manager.callingConventionMap.getKey(callingConventionID);
|
||||
if (ccName == null) {
|
||||
return null;
|
||||
}
|
||||
String ccName = dtm.getCallingConventionName(callingConventionID);
|
||||
return cs.getCallingConvention(ccName);
|
||||
}
|
||||
}
|
||||
|
@ -1751,28 +1752,8 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
|
|||
@Override
|
||||
public String getCallingConventionName() {
|
||||
try (LockHold hold = LockHold.lock(manager.lock.readLock())) {
|
||||
if (DBTraceSymbolManager.UNKNOWN_CALLING_CONVENTION_ID == callingConventionID) {
|
||||
return null;
|
||||
}
|
||||
if (DBTraceSymbolManager.DEFAULT_CALLING_CONVENTION_ID == callingConventionID) {
|
||||
return DBTraceSymbolManager.DEFAULT_CALLING_CONVENTION_NAME;
|
||||
}
|
||||
return manager.callingConventionMap.getKey(callingConventionID);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultCallingConventionName() {
|
||||
try (LockHold hold = LockHold.lock(manager.lock.readLock())) {
|
||||
PrototypeModel cc = manager.functions.getDefaultCallingConvention();
|
||||
if (cc == null) {
|
||||
return DBTraceSymbolManager.DEFAULT_CALLING_CONVENTION_NAME;
|
||||
}
|
||||
String ccName = cc.getName();
|
||||
if (ccName == null) { // Really?
|
||||
return DBTraceSymbolManager.DEFAULT_CALLING_CONVENTION_NAME;
|
||||
}
|
||||
return ccName;
|
||||
DBTraceDataTypeManager dtm = manager.dataTypeManager;
|
||||
return dtm.getCallingConventionName(callingConventionID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1783,12 +1764,16 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
|
|||
thunked.setCallingConvention(name);
|
||||
return;
|
||||
}
|
||||
if (Objects.equals(getCallingConventionName(), name)) {
|
||||
return;
|
||||
|
||||
DBTraceDataTypeManager dtm = manager.dataTypeManager;
|
||||
byte id = dtm.getCallingConventionID(name, true);
|
||||
if (id == callingConventionID) {
|
||||
return; // no change
|
||||
}
|
||||
|
||||
doLoadVariables();
|
||||
|
||||
this.callingConventionID = manager.findOrRecordCallingConvention(name);
|
||||
callingConventionID = id;
|
||||
update(CALLING_CONVENTION_COLUMN);
|
||||
|
||||
boolean hasCustomStorage = hasCustomVariableStorage();
|
||||
|
@ -1813,11 +1798,14 @@ public class DBTraceFunctionSymbol extends DBTraceNamespaceSymbol
|
|||
new TraceChangeRecord<>(TraceFunctionChangeType.CHANGED, getSpace(), this));
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
manager.dbError(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void createClassStructIfNeeded() {
|
||||
PrototypeModel cc = getCallingConvention();
|
||||
if (cc == null || cc.getGenericCallingConvention() != GenericCallingConvention.thiscall) {
|
||||
if (cc == null || !CompilerSpec.CALLING_CONVENTION_thiscall.equals(cc.getName())) {
|
||||
return;
|
||||
}
|
||||
Namespace parentNS = getParentNamespace();
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
*/
|
||||
package ghidra.trace.database.symbol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import ghidra.program.database.function.OverlappingFunctionException;
|
||||
import ghidra.program.database.symbol.OverlappingNamespaceException;
|
||||
|
@ -165,54 +164,19 @@ public class DBTraceFunctionSymbolView
|
|||
}
|
||||
}
|
||||
|
||||
public static List<String> getCallingConventionNames(CompilerSpec cs) {
|
||||
PrototypeModel[] namedCCs = cs.getCallingConventions();
|
||||
List<String> names = new ArrayList<>(2 + namedCCs.length);
|
||||
names.add(Function.UNKNOWN_CALLING_CONVENTION_STRING);
|
||||
names.add(Function.DEFAULT_CALLING_CONVENTION_STRING);
|
||||
for (PrototypeModel model : namedCCs) {
|
||||
names.add(model.getName());
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getCallingConventionNames() {
|
||||
// TODO: Allow for user-selected compiler spec(s)
|
||||
return getCallingConventionNames(manager.trace.getBaseCompilerSpec());
|
||||
public Collection<String> getCallingConventionNames() {
|
||||
return manager.dataTypeManager.getDefinedCallingConventionNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrototypeModel getDefaultCallingConvention() {
|
||||
CompilerSpec cs = manager.trace.getBaseCompilerSpec();
|
||||
if (cs == null) {
|
||||
return null;
|
||||
}
|
||||
return cs.getDefaultCallingConvention();
|
||||
return manager.dataTypeManager.getDefaultCallingConvention();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrototypeModel getCallingConvention(String name) {
|
||||
CompilerSpec cs = manager.trace.getBaseCompilerSpec();
|
||||
if (cs == null) {
|
||||
return null;
|
||||
}
|
||||
if (Function.UNKNOWN_CALLING_CONVENTION_STRING.equals(name)) {
|
||||
return null;
|
||||
}
|
||||
if (Function.DEFAULT_CALLING_CONVENTION_STRING.equals(name)) {
|
||||
return cs.getDefaultCallingConvention();
|
||||
}
|
||||
return cs.getCallingConvention(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrototypeModel[] getCallingConventions() {
|
||||
CompilerSpec cs = manager.trace.getBaseCompilerSpec();
|
||||
if (cs == null) {
|
||||
return EMPTY_MODEL_LIST;
|
||||
}
|
||||
return cs.getCallingConventions();
|
||||
return manager.dataTypeManager.getCallingConvention(name);
|
||||
}
|
||||
|
||||
// TODO: Move this into a FunctionUtilities class?
|
||||
|
|
|
@ -20,9 +20,6 @@ import java.lang.reflect.Field;
|
|||
import java.util.*;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
|
||||
import org.apache.commons.collections4.BidiMap;
|
||||
import org.apache.commons.collections4.bidimap.DualHashBidiMap;
|
||||
|
||||
import db.*;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.DataType;
|
||||
|
@ -60,11 +57,6 @@ import ghidra.util.task.TaskMonitor;
|
|||
* TODO: See if CALL-type references produce dynamic labels or functions.
|
||||
*/
|
||||
public class DBTraceSymbolManager implements TraceSymbolManager, DBTraceManager {
|
||||
protected static final byte DEFAULT_CALLING_CONVENTION_ID = -1;
|
||||
protected static final byte UNKNOWN_CALLING_CONVENTION_ID = -2;
|
||||
|
||||
protected static final String DEFAULT_CALLING_CONVENTION_NAME = "default";
|
||||
protected static final String UNKNOWN_CALLING_CONVENTION_NAME = "unknown";
|
||||
|
||||
private static final long TYPE_MASK = 0xFF;
|
||||
private static final int TYPE_SHIFT = 64 - 8;
|
||||
|
@ -101,32 +93,6 @@ public class DBTraceSymbolManager implements TraceSymbolManager, DBTraceManager
|
|||
}
|
||||
}
|
||||
|
||||
@DBAnnotatedObjectInfo(version = 0)
|
||||
public static class DBTraceCallingConventionEntry extends DBAnnotatedObject {
|
||||
static final String TABLE_NAME = "CallingConventions";
|
||||
|
||||
static final String NAME_COLUMN_NAME = "Name";
|
||||
|
||||
@DBAnnotatedColumn(NAME_COLUMN_NAME)
|
||||
static DBObjectColumn NAME_COLUMN;
|
||||
|
||||
@DBAnnotatedField(column = NAME_COLUMN_NAME)
|
||||
String name;
|
||||
|
||||
public DBTraceCallingConventionEntry(DBCachedObjectStore<?> store, DBRecord record) {
|
||||
super(store, record);
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
update(NAME_COLUMN);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@DBAnnotatedObjectInfo(version = 0)
|
||||
public static class DBTraceFunctionTag extends DBAnnotatedObject implements FunctionTag {
|
||||
|
||||
|
@ -435,9 +401,6 @@ public class DBTraceSymbolManager implements TraceSymbolManager, DBTraceManager
|
|||
|
||||
protected final DBTraceAddressSnapRangePropertyMap<Long, DBTraceSymbolIDEntry> idMap;
|
||||
|
||||
protected final DBCachedObjectStore<DBTraceCallingConventionEntry> callingConventionStore;
|
||||
protected final BidiMap<String, Byte> callingConventionMap = new DualHashBidiMap<>();
|
||||
|
||||
protected final DBCachedObjectStore<DBTraceFunctionTag> tagStore;
|
||||
protected final DBCachedObjectIndex<String, DBTraceFunctionTag> tagsByName;
|
||||
|
||||
|
@ -494,11 +457,6 @@ public class DBTraceSymbolManager implements TraceSymbolManager, DBTraceManager
|
|||
baseLanguage, trace, threadManager, DBTraceSymbolIDEntry.class,
|
||||
DBTraceSymbolIDEntry::new);
|
||||
|
||||
callingConventionStore =
|
||||
factory.getOrCreateCachedStore(DBTraceCallingConventionEntry.TABLE_NAME,
|
||||
DBTraceCallingConventionEntry.class, DBTraceCallingConventionEntry::new, true);
|
||||
loadCallingConventions();
|
||||
|
||||
tagStore = factory.getOrCreateCachedStore(DBTraceFunctionTag.TABLE_NAME,
|
||||
DBTraceFunctionTag.class, (s, r) -> new DBTraceFunctionTag(this, s, r), true);
|
||||
tagsByName = tagStore.getIndex(String.class, DBTraceFunctionTag.NAME_COLUMN);
|
||||
|
@ -570,9 +528,7 @@ public class DBTraceSymbolManager implements TraceSymbolManager, DBTraceManager
|
|||
if (ptrSize != dataTypeManager.getDataOrganization().getPointerSize()) {
|
||||
return dataTypeManager.getPointer(formal, ptrSize);
|
||||
}
|
||||
else {
|
||||
return dataTypeManager.getPointer(formal);
|
||||
}
|
||||
return dataTypeManager.getPointer(formal);
|
||||
}
|
||||
|
||||
protected <T extends AbstractDBTraceSymbolSingleTypeView<?>> T putInMap(T view) {
|
||||
|
@ -608,25 +564,6 @@ public class DBTraceSymbolManager implements TraceSymbolManager, DBTraceManager
|
|||
return (symbolID >> KEY_SHIFT) & KEY_MASK;
|
||||
}
|
||||
|
||||
protected void loadCallingConventions() {
|
||||
// NOTE: Should already own write lock
|
||||
for (DBTraceCallingConventionEntry ent : callingConventionStore.asMap().values()) {
|
||||
// NOTE: No need to check. Only called on new or invalidate.
|
||||
callingConventionMap.put(ent.name, (byte) ent.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
protected byte doRecordCallingConvention(String name) {
|
||||
DBTraceCallingConventionEntry ent = callingConventionStore.create();
|
||||
ent.setName(name);
|
||||
return (byte) ent.getKey();
|
||||
}
|
||||
|
||||
protected byte findOrRecordCallingConvention(String name) {
|
||||
// NOTE: Must already have write lock
|
||||
return callingConventionMap.computeIfAbsent(name, this::doRecordCallingConvention);
|
||||
}
|
||||
|
||||
protected int findOrRecordVariableStorage(VariableStorage storage) {
|
||||
DBTraceVariableStorageEntry entry = storageByStorage.getOne(storage);
|
||||
if (entry == null) {
|
||||
|
@ -645,9 +582,6 @@ public class DBTraceSymbolManager implements TraceSymbolManager, DBTraceManager
|
|||
public void invalidateCache(boolean all) {
|
||||
try (LockHold hold = LockHold.lock(lock.writeLock())) {
|
||||
idMap.invalidateCache(all);
|
||||
callingConventionStore.invalidateCache();
|
||||
callingConventionMap.clear();
|
||||
loadCallingConventions();
|
||||
|
||||
for (AbstractDBTraceSymbolSingleTypeView<?> view : symbolViews.values()) {
|
||||
view.invalidateCache();
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package ghidra.trace.model.symbol;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
|
||||
import ghidra.program.database.function.OverlappingFunctionException;
|
||||
import ghidra.program.model.address.Address;
|
||||
|
@ -37,11 +37,30 @@ public interface TraceFunctionSymbolView extends TraceSymbolWithLocationView<Tra
|
|||
return add(Lifespan.nowOn(snap), entryPoint, body, name, thunked, parent, source);
|
||||
}
|
||||
|
||||
PrototypeModel[] getCallingConventions();
|
||||
|
||||
List<String> getCallingConventionNames();
|
||||
/**
|
||||
* Get the ordered unmodifiable set of defined calling convention names. The reserved names
|
||||
* "unknown" and "default" are not included. The returned collection may not include all names
|
||||
* referenced by various functions and function-definitions. This set is limited to
|
||||
* those defined by the associated compiler specification.
|
||||
*
|
||||
* @return the set of defined calling convention names.
|
||||
*/
|
||||
Collection<String> getCallingConventionNames();
|
||||
|
||||
/**
|
||||
* Get the default calling convention's prototype model.
|
||||
*
|
||||
* @return the default calling convention prototype model.
|
||||
*/
|
||||
PrototypeModel getDefaultCallingConvention();
|
||||
|
||||
/**
|
||||
* Get the prototype model of the calling convention with the specified name from the
|
||||
* associated compiler specification. If {@link Function#DEFAULT_CALLING_CONVENTION_STRING}
|
||||
* is specified {@link #getDefaultCallingConvention()} will be returned.
|
||||
*
|
||||
* @param name the calling convention name
|
||||
* @return the named function calling convention prototype model or null if not defined.
|
||||
*/
|
||||
PrototypeModel getCallingConvention(String name);
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@ import static ghidra.lifecycle.Unfinished.*;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
|
@ -423,25 +423,12 @@ public class DBTraceProgramViewFunctionManagerTest extends AbstractGhidraHeadles
|
|||
assertEquals(defaultModel, protoModel);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCallingConventions() throws Exception {
|
||||
PrototypeModel[] protoModels = functionManager.getCallingConventions();
|
||||
assertTrue(protoModels.length >= 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCallingConventionNames() throws Exception {
|
||||
|
||||
List<String> names = functionManager.getCallingConventionNames();
|
||||
Collection<String> names = functionManager.getCallingConventionNames();
|
||||
assertTrue(names.size() >= 1);
|
||||
|
||||
for (String name : names) {
|
||||
if (Function.UNKNOWN_CALLING_CONVENTION_STRING.equals(name)) {
|
||||
assertNull(functionManager.getCallingConvention(name));
|
||||
}
|
||||
else {
|
||||
assertNotNull(functionManager.getCallingConvention(name));
|
||||
}
|
||||
assertNotNull(functionManager.getCallingConvention(name));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue