Merge branch 'GP-2308_1633_ghidra1_FunctionDefinitionCallingConventions'

(Closes #4537, Closes #4898, Closes #3723, Closes #3267)
This commit is contained in:
ghidra1
2023-04-20 14:36:23 -04:00
273 changed files with 8249 additions and 3415 deletions
@@ -264,9 +264,9 @@ class SymPcodeExecutor extends PcodeExecutor<Sym> {
// TODO: Does the decompiler communicate the inferred calling convention?
try {
PrototypeModel convention = program.getCompilerSpec().findBestCallingConvention(params);
sig.setGenericCallingConvention(convention.getGenericCallingConvention());
sig.setCallingConvention(convention.getName());
}
catch (SleighException e) {
catch (SleighException | InvalidInputException e) {
// Whatever, just leave sig at "unknown"
}
return sig;
@@ -352,7 +352,7 @@ class SymPcodeExecutor extends PcodeExecutor<Sym> {
throw new PcodeExecutionException("Cannot get stack change for indirect call: " + op);
}
PrototypeModel convention =
program.getCompilerSpec().matchConvention(sig.getGenericCallingConvention());
program.getCompilerSpec().matchConvention(sig.getCallingConventionName());
if (convention == null) {
warnings.add(new UnspecifiedConventionStackUnwindWarning(null));
convention = program.getCompilerSpec().getDefaultCallingConvention();
@@ -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));
}
}
+3 -2
View File
@@ -30,8 +30,9 @@ data/parserprofiles/MacOSX_10.9.prf||GHIDRA||||END|
data/parserprofiles/MacOSX_Cocoa.prf||GHIDRA||||END|
data/parserprofiles/VisualStudio12_32.prf||GHIDRA||||END|
data/parserprofiles/VisualStudio12_64.prf||GHIDRA||||END|
data/parserprofiles/VisualStudio9.prf||GHIDRA||reviewed||END|
data/parserprofiles/clib.prf||GHIDRA||reviewed||END|
data/parserprofiles/VisualStudio22_64.prf||GHIDRA||||END|
data/parserprofiles/VisualStudio9.prf||GHIDRA||||END|
data/parserprofiles/clib.prf||GHIDRA||||END|
data/parserprofiles/generic_clib_32.prf||GHIDRA||||END|
data/parserprofiles/generic_clib_64.prf||GHIDRA||||END|
data/parserprofiles/linux_32.prf||GHIDRA||||END|
@@ -207,7 +207,6 @@ zlib.h
-DTARGET_API_MAC_OSX
-DTARGET_COCOA
-DHANDLE="unsigned long"
-D_WCHAR_T
-D_Complex
-Drestrict
-D__restrict
@@ -323,7 +323,6 @@ zlib.h
-D_MAC_
-DTARGET_API_MAC_OSX
-DHANDLE="unsigned long"
-D_WCHAR_T
-D_Complex
-Drestrict
-D__restrict
@@ -28,7 +28,6 @@ Cocoa\Cocoa.h
-D_MAC_
-DTARGET_API_MAC_OSX=1
-DHANDLE="unsigned long"
-D_WCHAR_T
-D_Complex
-Drestrict
-D__restrict
@@ -172,12 +172,8 @@ wpcapi.h
wscapi.h
wsdapi.h
wspiapi.h
rpcproxy.h
-I/VC/VS12/src
-I/VC/VS12/include
-I/VC/SDK/v7.1A/Include
-D_M_IX86=300
-D_MSC_VER=1200
-D_INTEGRAL_MAX_BITS=32
@@ -191,7 +187,6 @@ rpcproxy.h
-DSTRSAFE_LIB
-DSTRSAFE_LIB_IMPL
-DLPSKBINFO=LPARAM
-D_WCHAR_T_DEFINED
-DCONST=const
-D_CRT_SECURE_NO_WARNINGS
-D_CRT_NONSTDC_NO_DEPRECATE
@@ -205,3 +200,14 @@ rpcproxy.h
-D_ThrowInfo=ThrowInfo
-v0
-D__inner_checkReturn=""
/data/HeaderFiles/VC/VS12/src
/data/HeaderFiles/VC/VS12/include
/data/HeaderFiles/VC/SDK/v7.1A/Include
x86:LE:32:default
windows
@@ -172,12 +172,8 @@ wpcapi.h
wscapi.h
wsdapi.h
wspiapi.h
rpcproxy.h
-I/VC/VS12/src
-I/VC/VS12/include
-I/VC/SDK/v7.1A/Include
-D_M_IX86=300
-D_MSC_VER=1200
-D_INTEGRAL_MAX_BITS=64
@@ -193,7 +189,6 @@ rpcproxy.h
-DSTRSAFE_LIB
-DSTRSAFE_LIB_IMPL
-DLPSKBINFO=LPARAM
-D_WCHAR_T_DEFINED
-DCONST=const
-D_CRT_SECURE_NO_WARNINGS
-D_CRT_NONSTDC_NO_DEPRECATE
@@ -208,3 +203,11 @@ rpcproxy.h
-D__unaligned=""
-v0
-D__inner_checkReturn=""
/data/HeaderFiles/VC/VS12/include
/data/HeaderFiles/VC/VS12/src
/data/HeaderFiles/VC/SDK/v7.1A/Include
@@ -0,0 +1,341 @@
# Core necessary files
winapifamily.h
winpackagefamily.h
sdkddkver.h
sal.h
no_sal2.h
corecrt.h
wtypes.h
winnt.h
winternl.h
#ntdef.h
# Common headers
dos.h
errno.h
malloc.h
signal.h
stdalign.h
stddef.h
stdio.h
stdlib.h
assert.h
crtdbg.h
ctype.h
conio.h
direct.h
fcntl.h
float.h
fpieee.h
inttypes.h
io.h
locale.h
complex.h
math.h
mbctype.h
mbstring.h
memory.h
minmax.h
new.h
process.h
search.h
share.h
winbase.h
winuser.h
Windows.h
# Security and identity (https://docs.microsoft.com/en-us/windows/win32/api/_security/)
accctrl.h
aclapi.h
aclui.h
advapi32.h
adtgen.h
authz.h
azroles.h
bcrypt.h
casetup.h
ccgplugins.h
celib.h
ntlsa.h
sspi.h
ntsecapi.h
ntsecpkg.h
schannel.h
certadm.h
certbcli.h
certcli.h
certenroll.h
certexit.h
certif.h
certmod.h
certpol.h
certpoleng.h
certsrv.h
certview.h
credssp.h
cryptdlg.h
cryptuiapi.h
cryptxml.h
diagnosticdataquery.h
diagnosticdataquerytypes.h
dpapi.h
dssec.h
iads.h
identitycommon.h
identityprovider.h
identitystore.h
keycredmgr.h
lmaccess.h
lsalookup.h
mmcobj.h
mscat.h
mssip.h
namedpipeapi.h
ncrypt.h
ncryptprotect.h
npapi.h
processthreadsapi.h
sas.h
scesvc.h
sddl.h
securityappcontainer.h
securitybaseapi.h
slpublic.h
subauth.h
tokenbinding.h
tpmvscmgr.h
wincred.h
wincrypt.h
winnetwk.h
winreg.h
winsafer.h
winscard.h
winsvc.h
wintrust.h
winwlx.h
xenroll.h
# Windows sockets
af_irda.h
in6addr.h
mstcpip.h
ws2def.h
winsock.h
winsock2.h
nsemail.h
nspapi.h
socketapi.h
# Nothing includes this; is it necessary?
#sporder.h
transportsettingcommon.h
ws2atm.h
ws2spi.h
mswsock.h
ws2tcpip.h
wsipv6ok.h
wsnwlink.h
wsrm.h
mswsockdef.h
# Remote Procedure Call (RPC)
midles.h
midlbase.h
rpc.h
rpcndr.h
rpcasync.h
rpcdcep.h
rpcnsi.h
rpcproxy.h
rpcssl.h
# COM
accctrl.h
callobj.h
combaseapi.h
comcat.h
ctxtcall.h
dmerror.h
docobj.h
eventsys.h
guiddef.h
iaccess.h
hstring.h
imessagedispatcher.h
messagedispatcherapi.h
objbase.h
objidlbase.h
objidl.h
ocidl.h
ole.h
ole2.h
oledlg.h
oleidl.h
roapi.h
rpcdce.h
servprov.h
shobjidl.h
txlogpub.h
unknwnbase.h
unknwn.h
urlmon.h
vbinterf.h
winddi.h
winerror.h
wtypesbase.h
# COM+
comadmin.h
mtxdm.h
# More
inspectable.h
# Windows Internet
proofofpossessioncookieinfo.h
wininet.h
winineti.h
# Windows HTTP Services
winhttp.h
# Compression
compressapi.h
# TraceLogging
#traceloggingactivity.h
#traceloggingprovider.h
# Windows Error Reporting
errorrep.h
werapi.h
# Windows and MEssages
olectl.h
windef.h
windowsx.h
# Shell
appmgmt.h
appnotify.h
cpl.h
credentialprovider.h
dimm.h
imagetranscode.h
inputpanelconfiguration.h
intsafe.h
intshcut.h
mobsync.h
objectarray.h
pathcch.h
profinfo.h
propkeydef.h
scrnsave.h
shappmgr.h
shdeprecated.h
shidfact.h
shimgdata.h
shlwapi.h
shtypes.h
storageprovider.h
syncmgr.h
thumbcache.h
thumbnailstreamcache.h
tlogstg.h
userenv.h
# Windows Controls
commctrl.h
commoncontrols.h
dpa_dsa.h
prsht.h
richedit.h
richole.h
shlobj_core.h
shlobj.h
#textserv.h // C++
tom.h
uxtheme.h
# Menus and other resources
resourceindexer.h
strsafe.h
verrsrc.h
winver.h
# Windows Accessibility Features
oleacc.h
uiautomationcore.h
uiautomationclient.h
uiautomationcoreapi.h
# Internationalization
datetimeapi.h
elscore.h
gb18030.h
imepad.h
imm.h
immdev.h
msime.h
msimeapi.h
muiload.h
spellcheck.h
spellcheckprovider.h
stringapiset.h
usp10.h
winnls.h
# HTTP Server API
#http.h // included by something else
# IP Helper
ifdef.h
inaddr.h
ip2string.h
ipexport.h
iphlpapi.h
icmpapi.h
iprtrmib.h
iptypes.h
netioapi.h
nldef.h
tcpestats.h
ws2ipdef.h
# Network Management
atacct.h
lmalert.h
lmapibuf.h
lmat.h
lmaudit.h
lmconfig.h
lmerrlog.h
lmjoin.h
lmmsg.h
lmremutl.h
lmserver.h
lmsvc.h
lmuse.h
lmwksta.h
-D_MSC_VER=1924
-D_INTEGRAL_MAX_BITS=64
-DWINVER=0x0a00
-D_WIN32_WINNT=0x0a00
-D_AMD64_
-D_M_AMD64
-D_M_X64
-D_WIN64
-D_WIN32
-D_USE_ATTRIBUTES_FOR_SAL
-D_CRTBLD
-D_OPENMP_NOFORCE_MANIFEST
-DSTRSAFE_LIB
-DSTRSAFE_LIB_IMPL
-DLPSKBINFO=LPARAM
-DCONST=const
-D_CRT_SECURE_NO_WARNINGS
-D_CRT_NONSTDC_NO_DEPRECATE
-D_CRT_NONSTDC_NO_WARNINGS
-D_CRT_OBSOLETE_NO_DEPRECATE
-D_ALLOW_KEYWORD_MACROS
-D_ASSERT_OK
-DSTRSAFE_NO_DEPRECATE
-D__possibly_notnullterminated
"-Dtype_info=\"void *\"",
-D_ThrowInfo=ThrowInfo
-D__unaligned=
-v0
-D__inner_checkReturn=
-DWINAPI_PARTITION_APP=1
-DWINAPI_PARTITION_SYSTEM=1
-DWINAPI_PARTITION_GAMES=1
-DSECURITY_WIN32
/data/HeaderFiles/VC/VS22/Community/VC/Tools/MSVC/14.29.30133/include
/data/HeaderFiles/VC/VS22/10.0.19041.0/shared
/data/HeaderFiles/VC/VS22/10.0.19041.0/ucrt
/data/HeaderFiles/VC/VS22/10.0.19041.0/um
/data/HeaderFiles/VC/VS22/10.0.19041.0/winrt
x86:LE:64:default
windows
@@ -58,13 +58,10 @@ yvals.h
CommDlg.h
WinUser.h
WinNls.h
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\crt\src\internal.h
internal.h
strsafe.h
penwin.h
-IC:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\Include
-IC:\Program Files (x86)\Microsoft SDKs\Windows\v5.0\Include
-IC:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\crt\src
-D_M_IX86=500
-D_MSC_VER=9090
-D_MSC_EXTENSIONS
@@ -85,5 +82,11 @@ penwin.h
-DSTRSAFE_LIB_IMPL
-DLPSKBINFO=LPARAM
-D_PHNDLR=void *
-D_WCHAR_T_DEFINED
-DCONST=const
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\Include
C:\Program Files (x86)\Microsoft SDKs\Windows\v5.0\Include
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\crt\src
x86:LE:64:default
@@ -78,13 +78,17 @@ wchar.h
wctype.h
wordexp.h
-IU:\linux_include\include
-IU:\linux_include\include\sys
-IU:\linux_include\i386-redhat-linux\4.1.2\include
-D_X86_
-D__STDC__
-D__WORDSIZE=32
-D__builtin_va_list=void *
-D__DO_NOT_DEFINE_COMPILE
-D_Complex
-D_WCHAR_T
U:\linux_include\include
U:\linux_include\include\sys
U:\linux_include\i386-redhat-linux\4.1.2\include
x86:LE:32:default
gcc
@@ -219,11 +219,6 @@ arpa/nameser_compat.h
arpa/telnet.h
arpa/tftp.h
-I/linux/include
-I/linux/include/sys
-I/linux/gcc/include
-I/linux/x86_64-redhat-linux5E/include
-I/linux/x86_64-redhat-linux5E/include/sys
-D_X86_
-D__STDC__
-D_GNU_SOURCE
@@ -231,10 +226,19 @@ arpa/tftp.h
-D__builtin_va_list=void *
-D__DO_NOT_DEFINE_COMPILE
-D_Complex
-D_WCHAR_T
-D__NO_STRING_INLINES
-D__NO_LONG_DOUBLE_MATH
-D__signed__
-D__extension__=""
-D__GLIBC_HAVE_LONG_LONG=1
-Daligned_u64=uint64_t
/data/HeaderFiles/linux/include
/data/HeaderFiles/linux/include/sys
/data/HeaderFiles/linux/gcc/include
/data/HeaderFiles/linux/x86_64-redhat-linux5E/include
/data/HeaderFiles/linux/x86_64-redhat-linux5E/include/sys
x86:LE:32:default
gcc
@@ -219,11 +219,6 @@ arpa/nameser_compat.h
arpa/telnet.h
arpa/tftp.h
-I/linux/include
-I/linux/include/sys
-I/linux/gcc/include
-I/linux/x86_64-redhat-linux5E/include
-I/linux/x86_64-redhat-linux5E/include/sys
-D_X86_
-D__STDC__
-D_GNU_SOURCE
@@ -231,10 +226,19 @@ arpa/tftp.h
-D__builtin_va_list=void *
-D__DO_NOT_DEFINE_COMPILE
-D_Complex
-D_WCHAR_T
-D__NO_STRING_INLINES
-D__signed__
-D__extension__=""
-D__GLIBC_HAVE_LONG_LONG=1
-D__need_sigset_t
-Daligned_u64=uint64_t
/data/HeaderFiles/linux/include
/data/HeaderFiles/linux/include/sys
/data/HeaderFiles/linux/gcc/include
/data/HeaderFiles/linux/x86_64-redhat-linux5E/include
/data/HeaderFiles/linux/x86_64-redhat-linux5E/include/sys
x86:LE:64:default
gcc
@@ -515,11 +515,6 @@ mechglue.h
auth_gss.h
auth_gssapi.h
-I/linux/include
-I/linux/include/sys
-I/linux/gcc/include
-I/linux/x86_64-redhat-linux5E/include
-I/linux/x86_64-redhat-linux5E/include/sys
-D_X86_
-D__STDC__
-D_POSIX_C_SOURCE
@@ -528,10 +523,19 @@ auth_gssapi.h
-D__builtin_va_list=void *
-D__DO_NOT_DEFINE_COMPILE
-D_Complex
-D_WCHAR_T
-D__NO_STRING_INLINES
-D__NO_LONG_DOUBLE_MATH
-D__signed__
-D__extension__=""
-D__GLIBC_HAVE_LONG_LONG=1
-Daligned_u64=uint64_t
/data/HeaderFiles/linux/include
/data/HeaderFiles/linux/include/sys
/data/HeaderFiles/linux/gcc/include
/data/HeaderFiles/linux/x86_64-redhat-linux5E/include
/data/HeaderFiles/linux/x86_64-redhat-linux5E/include/sys
x86:LE:32:default
gcc
@@ -515,11 +515,6 @@ mechglue.h
auth_gss.h
auth_gssapi.h
-I/linux/include
-I/linux/include/sys
-I/linux/gcc/include
-I/linux/x86_64-redhat-linux5E/include
-I/linux/x86_64-redhat-linux5E/include/sys
-D_X86_
-D__STDC__
-D_POSIX_C_SOURCE
@@ -528,9 +523,18 @@ auth_gssapi.h
-D__builtin_va_list=void *
-D__DO_NOT_DEFINE_COMPILE
-D_Complex
-D_WCHAR_T
-D__NO_STRING_INLINES
-D__signed__
-D__extension__=""
-D__GLIBC_HAVE_LONG_LONG=1
-Daligned_u64=uint64_t
/data/HeaderFiles/linux/include
/data/HeaderFiles/linux/include/sys
/data/HeaderFiles/linux/gcc/include
/data/HeaderFiles/linux/x86_64-redhat-linux5E/include
/data/HeaderFiles/linux/x86_64-redhat-linux5E/include/sys
x86:LE:64:default
gcc
@@ -222,9 +222,6 @@ wscapi.h
wsdapi.h
wspiapi.h
-I/VisualStudio/VS12/include
-I/VisualStudio/Windows/v7.0a/Include
-I/VisualStudio/VS12/src
-D_M_IX86
-D_MSC_VER=9090
-D_INTEGRAL_MAX_BITS=32
@@ -239,7 +236,6 @@ wspiapi.h
-DSTRSAFE_LIB
-DSTRSAFE_LIB_IMPL
-DLPSKBINFO=LPARAM
-D_WCHAR_T_DEFINED
-DCONST=const
-D_CRT_SECURE_NO_WARNINGS
-D_CRT_NONSTDC_NO_DEPRECATE
@@ -250,3 +246,12 @@ wspiapi.h
-D__possibly_notnullterminated
-Dtype_info="void *"
-v0
/data/HeaderFiles/VC/VS12/include
/data/HeaderFiles/VC/Windows/v7.0a/Include
/data/HeaderFiles/VC/VS12/src
x86:LE:32:default
windows
Binary file not shown.
@@ -26,6 +26,7 @@ import java.util.Iterator;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.data.*;
import ghidra.program.model.data.StandAloneDataTypeManager.ArchiveWarning;
import ghidra.util.UniversalID;
public class CompareGDTs extends GhidraScript {
@@ -54,13 +55,28 @@ public class CompareGDTs extends GhidraScript {
return;
}
}
firstArchive = openDataTypeArchive(firstFile, false);
if (firstArchive.getWarning() != ArchiveWarning.NONE) {
popup(
"An architecture language error occured while opening archive (see log for details)\n" +
firstFile.getPath());
return;
}
secondArchive = openDataTypeArchive(secondFile, false);
if (secondArchive.getWarning() != ArchiveWarning.NONE) {
popup(
"An architecture language error occured while opening archive (see log for details)\n" +
secondFile.getPath());
return;
}
matchByName = askYesNo("Match Data Types By Path Name?",
"Do you want to match data types by their path names (rather than by Universal ID)?");
checkPointers = askYesNo("Check Pointers?", "Do you want to check Pointers?");
checkArrays = askYesNo("Check Arrays?", "Do you want to check Arrays?");
firstArchive = FileDataTypeManager.openFileArchive(firstFile, false);
secondArchive = FileDataTypeManager.openFileArchive(secondFile, false);
printWriter = new PrintWriter(outputFile);
try {
compareDataTypes();
@@ -31,6 +31,7 @@ import java.io.IOException;
import ghidra.app.script.GhidraScript;
import ghidra.app.util.cparser.C.CParserUtils;
import ghidra.app.util.cparser.C.CParserUtils.CParseResults;
import ghidra.app.util.cparser.C.ParseException;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.FileDataTypeManager;
@@ -55,14 +56,16 @@ public class CreateDefaultGDTArchivesScript extends GhidraScript {
}
private void parseHeaderFilesToGDT(File outputDir, String gdtName, String languageID, String compiler, String[] filenames, String[] args)
private void parseHeaderFilesToGDT(File outputDir, String gdtName, String languageID, String compiler,
String[] filenames, String includePaths[], String[] args)
throws ParseException, ghidra.app.util.cparser.CPP.ParseException, IOException {
DataTypeManager openTypes[] = null;
parseHeaderFilesToGDT(openTypes, outputDir, gdtName, languageID, compiler, filenames, args);
parseHeaderFilesToGDT(openTypes, outputDir, gdtName, languageID, compiler, filenames, includePaths, args);
}
private void parseHeaderFilesToGDT(DataTypeManager openTypes[], File outputDir, String gdtName, String languageID, String compiler, String[] filenames, String[] args)
private void parseHeaderFilesToGDT(DataTypeManager openTypes[], File outputDir, String gdtName, String languageID, String compiler,
String[] filenames, String[] includePaths, String[] args)
throws ParseException, ghidra.app.util.cparser.CPP.ParseException, IOException {
String dataTypeFile = outputDir + File.separator + gdtName + ".gdt";
@@ -71,9 +74,9 @@ public class CreateDefaultGDTArchivesScript extends GhidraScript {
FileDataTypeManager dtMgr = FileDataTypeManager.createFileArchive(f);
String messages = CParserUtils.parseHeaderFiles(openTypes, filenames, args, dtMgr, languageID, compiler, null, monitor);
CParseResults results = CParserUtils.parseHeaderFiles(openTypes, filenames, includePaths, args, dtMgr, languageID, compiler, monitor);
Msg.info(this, messages);
Msg.info(this, results.getFormattedParseMessage(null));
dtMgr.save();
dtMgr.close();
@@ -276,14 +279,16 @@ public class CreateDefaultGDTArchivesScript extends GhidraScript {
"wscapi.h",
"wsdapi.h",
"wspiapi.h",
"rpcproxy.h",
};
String includePaths[] = {
headerFilePath+"/VC/VS12/src",
headerFilePath+"/VC/VS12/include",
headerFilePath+"/VC/SDK/v7.1A/Include",
};
String args[] = {
"-I"+headerFilePath+"/VC/VS12/src",
"-I"+headerFilePath+"/VC/VS12/include",
"-I"+headerFilePath+"/VC/SDK/v7.1A/Include",
"-D_M_IX86=300",
"-D_MSC_VER=1200",
"-D_INTEGRAL_MAX_BITS=32",
@@ -294,8 +299,6 @@ public class CreateDefaultGDTArchivesScript extends GhidraScript {
"-D_USE_ATTRIBUTES_FOR_SAL",
"-D_CRTBLD",
"-D_OPENMP_NOFORCE_MANIFEST",
"-DSTRSAFE_LIB",
"-DSTRSAFE_LIB_IMPL",
"-DLPSKBINFO=LPARAM",
"-DCONST=const",
"-D_CRT_SECURE_NO_WARNINGS",
@@ -312,7 +315,7 @@ public class CreateDefaultGDTArchivesScript extends GhidraScript {
"-D__inner_checkReturn=",
};
parseHeaderFilesToGDT(outputDirectory, "windows_vs12_32_new", "x86:LE:32:default", "windows", filenames, args);
parseHeaderFilesToGDT(outputDirectory, "windows_vs12_32_new", "x86:LE:32:default", "windows", filenames, includePaths, args);
}
@@ -494,14 +497,16 @@ public class CreateDefaultGDTArchivesScript extends GhidraScript {
"wscapi.h",
"wsdapi.h",
"wspiapi.h",
"rpcproxy.h",
};
String includePaths[] = {
headerFilePath+"/VC/VS12/src",
headerFilePath+"/VC/VS12/include",
headerFilePath+"/VC/SDK/v7.1A/Include",
};
String args[] = {
"-I"+headerFilePath+"/VC/VS12/src",
"-I"+headerFilePath+"/VC/VS12/include",
"-I"+headerFilePath+"/VC/SDK/v7.1A/Include",
"-D_MSC_VER=1200",
"-D_INTEGRAL_MAX_BITS=64",
"-DWINVER=0x0900",
@@ -513,8 +518,6 @@ public class CreateDefaultGDTArchivesScript extends GhidraScript {
"-D_USE_ATTRIBUTES_FOR_SAL",
"-D_CRTBLD",
"-D_OPENMP_NOFORCE_MANIFEST",
"-DSTRSAFE_LIB",
"-DSTRSAFE_LIB_IMPL",
"-DLPSKBINFO=LPARAM",
"-DCONST=const",
"-D_CRT_SECURE_NO_WARNINGS",
@@ -532,7 +535,7 @@ public class CreateDefaultGDTArchivesScript extends GhidraScript {
"-D__inner_checkReturn=",
};
parseHeaderFilesToGDT(outputDirectory, "windows_vs12_64_new", "x86:LE:64:default", "windows", filenames, args);
parseHeaderFilesToGDT(outputDirectory, "windows_vs12_64_new", "x86:LE:64:default", "windows", filenames, includePaths, args);
}
@@ -761,12 +764,15 @@ public class CreateDefaultGDTArchivesScript extends GhidraScript {
"arpa/tftp.h",
};
String includePaths[] = {
headerFilePath+"/linux/include",
headerFilePath+"/linux/include/sys",
headerFilePath+"/linux/gcc/include",
headerFilePath+"/linux/x86_64-redhat-linux5E/include",
headerFilePath+"/linux/x86_64-redhat-linux5E/include/sys",
};
String args[] = {
"-I"+headerFilePath+"/linux/include",
"-I"+headerFilePath+"/linux/include/sys",
"-I"+headerFilePath+"/linux/gcc/include",
"-I"+headerFilePath+"/linux/x86_64-redhat-linux5E/include",
"-I"+headerFilePath+"/linux/x86_64-redhat-linux5E/include/sys",
"-D_X86_",
"-D__STDC__",
"-D_GNU_SOURCE",
@@ -782,7 +788,7 @@ public class CreateDefaultGDTArchivesScript extends GhidraScript {
"-Daligned_u64=uint64_t",
};
parseHeaderFilesToGDT(outputDirectory, "generic_clib_64_new", "x86:LE:64:default", "gcc", filenames, args);
parseHeaderFilesToGDT(outputDirectory, "generic_clib_64_new", "x86:LE:64:default", "gcc", filenames, includePaths, args);
}
@@ -1011,12 +1017,15 @@ public class CreateDefaultGDTArchivesScript extends GhidraScript {
"arpa/tftp.h",
};
String includePaths[] = {
headerFilePath+"/linux/include",
headerFilePath+"/linux/include/sys",
headerFilePath+"/linux/gcc/include",
headerFilePath+"/linux/x86_64-redhat-linux5E/include",
headerFilePath+"/linux/x86_64-redhat-linux5E/include/sys",
};
String args[] = {
"-I"+headerFilePath+"/linux/include",
"-I"+headerFilePath+"/linux/include/sys",
"-I"+headerFilePath+"/linux/gcc/include",
"-I"+headerFilePath+"/linux/x86_64-redhat-linux5E/include",
"-I"+headerFilePath+"/linux/x86_64-redhat-linux5E/include/sys",
"-D_X86_",
"-D__STDC__",
"-D_GNU_SOURCE",
@@ -1032,6 +1041,6 @@ public class CreateDefaultGDTArchivesScript extends GhidraScript {
"-Daligned_u64=uint64_t",
};
parseHeaderFilesToGDT(outputDirectory, "generic_clib_new", "x86:LE:32:default", "gcc", filenames, args);
parseHeaderFilesToGDT(outputDirectory, "generic_clib_new", "x86:LE:32:default", "gcc", filenames, includePaths, args);
}
}
@@ -31,6 +31,7 @@ import java.io.IOException;
import ghidra.app.script.GhidraScript;
import ghidra.app.util.cparser.C.CParserUtils;
import ghidra.app.util.cparser.C.CParserUtils.CParseResults;
import ghidra.app.util.cparser.C.ParseException;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.FileDataTypeManager;
@@ -52,14 +53,16 @@ public class CreateExampleGDTArchiveScript extends GhidraScript {
parseGDT_WinVS22();
}
private void parseHeaderFilesToGDT(File outputDir, String gdtName, String languageID, String compiler, String[] filenames, String[] args)
private void parseHeaderFilesToGDT(File outputDir, String gdtName, String languageID, String compiler,
String[] filenames, String includePaths[], String[] args)
throws ParseException, ghidra.app.util.cparser.CPP.ParseException, IOException {
DataTypeManager openTypes[] = null;
parseHeaderFilesToGDT(openTypes, outputDir, gdtName, languageID, compiler, filenames, args);
parseHeaderFilesToGDT(openTypes, outputDir, gdtName, languageID, compiler, filenames, includePaths, args);
}
private void parseHeaderFilesToGDT(DataTypeManager openTypes[], File outputDir, String gdtName, String languageID, String compiler, String[] filenames, String[] args)
private void parseHeaderFilesToGDT(DataTypeManager openTypes[], File outputDir, String gdtName, String languageID, String compiler,
String[] filenames, String[] includePaths, String[] args)
throws ParseException, ghidra.app.util.cparser.CPP.ParseException, IOException {
String dataTypeFile = outputDir + File.separator + gdtName + ".gdt";
@@ -68,9 +71,9 @@ public class CreateExampleGDTArchiveScript extends GhidraScript {
FileDataTypeManager dtMgr = FileDataTypeManager.createFileArchive(f);
String messages = CParserUtils.parseHeaderFiles(openTypes, filenames, args, dtMgr, languageID, compiler, null, monitor);
CParseResults results = CParserUtils.parseHeaderFiles(openTypes, filenames, includePaths, args, dtMgr, languageID, compiler, monitor);
Msg.info(this, messages);
Msg.info(this, results.getFormattedParseMessage(null));
dtMgr.save();
dtMgr.close();
@@ -79,7 +82,7 @@ public class CreateExampleGDTArchiveScript extends GhidraScript {
/**
* Turn string into a file, delete old archive if it exists
*
* @param dataTypeFile
* @param dataTypeFile name of archive file
*
* @return file
*/
@@ -112,12 +115,15 @@ public class CreateExampleGDTArchiveScript extends GhidraScript {
"dsound.h",
};
String includeFiles[] = {
headerFilePath+"/VC/VS22/10.0.190141.0",
headerFilePath+"/VC/VS22/10.0.19041.0/um",
headerFilePath+"/VC/VS22/10.0.19041.0/shared",
headerFilePath+"/VC/VS22/10.0.19041.0/ucrt",
headerFilePath+"/VC/VS22/Community/VC/Tools/MSVC/14.30.30705/include",
};
String args[] = {
"-I"+headerFilePath+"/VC/VS22/10.0.190141.0",
"-I"+headerFilePath+"/VC/VS22/10.0.19041.0/um",
"-I"+headerFilePath+"/VC/VS22/10.0.19041.0/shared",
"-I"+headerFilePath+"/VC/VS22/10.0.19041.0/ucrt",
"-I"+headerFilePath+"/VC/VS22/Community/VC/Tools/MSVC/14.30.30705/include",
"-D_AMD64_",
"-D_M_AMD64",
"-D_M_X64",
@@ -126,7 +132,7 @@ public class CreateExampleGDTArchiveScript extends GhidraScript {
"-v0",
};
parseHeaderFilesToGDT(outputDirectory, "directX64", "x86:LE:64:default", "windows", filenames, args);
parseHeaderFilesToGDT(outputDirectory, "directX64", "x86:LE:64:default", "windows", filenames, includeFiles, args);
}
public void parseGDT_WinVS22() throws Exception {
@@ -167,7 +173,7 @@ public class CreateExampleGDTArchiveScript extends GhidraScript {
"complex.h",
"math.h",
"mbctype.h",
"mbstring.hs",
"mbstring.h",
"memory.h",
"minmax.h",
"new.h",
@@ -216,7 +222,7 @@ public class CreateExampleGDTArchiveScript extends GhidraScript {
"dssec.h",
"iads.h",
"identitycommon.h",
"identityproviders.h",
"identityprovider.h",
"identitystore.h",
"keycredmgr.h",
"lmaccess.h",
@@ -237,7 +243,7 @@ public class CreateExampleGDTArchiveScript extends GhidraScript {
"slpublic.h",
"subauth.h",
"tokenbinding.h",
"tpmsvcmgr.h",
"tpmvscmgr.h",
"wincred.h",
"wincrypt.h",
"winnetwk.h",
@@ -267,7 +273,7 @@ public class CreateExampleGDTArchiveScript extends GhidraScript {
"mswsock.h",
"ws2tcpip.h",
"wsipv6ok.h",
"wslwlink.h",
"wsnwlink.h",
"wsrm.h",
"mswsockdef.h",
@@ -375,7 +381,7 @@ public class CreateExampleGDTArchiveScript extends GhidraScript {
"thumbcache.h",
"thumbnailstreamcache.h",
"tlogstg.h",
"usereng.h",
"userenv.h",
"# Windows Controls",
"commctrl.h",
@@ -452,12 +458,15 @@ public class CreateExampleGDTArchiveScript extends GhidraScript {
"lmwksta.h"
};
String includeFiles[] = {
headerFilePath+"/VC/VS22/Community/VC/Tools/MSVC/14.29.30133/include",
headerFilePath+"/VC/VS22/10.0.19041.0/shared",
headerFilePath+"/VC/VS22/10.0.19041.0/ucrt",
headerFilePath+"/VC/VS22/10.0.19041.0/um",
headerFilePath+"/VC/VS22/10.0.19041.0/winrt",
};
String args[] = {
"-I"+headerFilePath+"/VC/VS22/Community/VC/Tools/MSVC/14.29.30133/include",
"-I"+headerFilePath+"/VC/VS22/10.0.19041.0/shared",
"-I"+headerFilePath+"/VC/VS22/10.0.19041.0/ucrt",
"-I"+headerFilePath+"/VC/VS22/10.0.19041.0/um",
"-I"+headerFilePath+"/VC/VS22/10.0.19041.0/winrt",
"-D_MSC_VER=1924",
"-D_INTEGRAL_MAX_BITS=64",
"-DWINVER=0x0a00",
@@ -473,7 +482,6 @@ public class CreateExampleGDTArchiveScript extends GhidraScript {
"-DSTRSAFE_LIB",
"-DSTRSAFE_LIB_IMPL",
"-DLPSKBINFO=LPARAM",
"-D_WCHAR_T_DEFINED",
"-DCONST=const",
"-D_CRT_SECURE_NO_WARNINGS",
"-D_CRT_NONSTDC_NO_DEPRECATE",
@@ -494,6 +502,6 @@ public class CreateExampleGDTArchiveScript extends GhidraScript {
"-DSECURITY_WIN32",
};
parseHeaderFilesToGDT(outputDirectory, "windows_vs22_64_new", "x86:LE:64:default", "windows", filenames, args);
parseHeaderFilesToGDT(outputDirectory, "windows_vs22_64_new", "x86:LE:64:default", "windows", filenames, includeFiles, args);
}
}
@@ -29,6 +29,7 @@ import ghidra.app.script.GhidraScript;
import ghidra.app.services.DataTypeManagerService;
import ghidra.framework.model.DomainFile;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.database.ProjectDataTypeManager;
import ghidra.program.database.data.*;
import ghidra.program.model.data.BuiltInDataTypeManager;
import ghidra.program.model.data.DataTypeManager;
@@ -24,43 +24,59 @@ import java.io.File;
import ghidra.app.script.GhidraScript;
import ghidra.program.model.data.Category;
import ghidra.program.model.data.FileDataTypeManager;
import ghidra.program.model.data.StandAloneDataTypeManager.ArchiveWarning;
import ghidra.util.InvalidNameException;
import ghidra.util.exception.DuplicateNameException;
public class SynchronizeGDTCategoryPaths extends GhidraScript {
private File firstFile;
private File secondFile;
private FileDataTypeManager firstArchive;
private FileDataTypeManager secondArchive;
@Override
protected void run() throws Exception {
firstFile = askFile("Select First GDT File", "Select 1st");
secondFile = askFile("Select Second GDT File", "Select 2nd");
try {
firstArchive = FileDataTypeManager.openFileArchive(firstFile, false);
secondArchive = FileDataTypeManager.openFileArchive(secondFile, true);
int transactionID = secondArchive.startTransaction("Synchronize Category Path Names");
Category firstCategory = firstArchive.getRootCategory();
Category secondCategory = secondArchive.getRootCategory();
synchronizeCategory(firstCategory, secondCategory);
secondArchive.endTransaction(transactionID, true);
}
finally {
if (firstArchive != null) {
firstArchive.close();
File firstFile = askFile("Select First GDT File", "Select 1st");
try (FileDataTypeManager firstArchive =
FileDataTypeManager.openFileArchive(firstFile, false)) {
if (hasWarning(firstArchive, firstFile)) {
return;
}
secondArchive.save();
if (secondArchive != null) {
secondArchive.close();
File secondFile = askFile("Select Second GDT File", "Select 2nd");
try (FileDataTypeManager secondArchive =
FileDataTypeManager.openFileArchive(secondFile, true)) {
if (hasWarning(secondArchive, secondFile)) {
return;
}
int transactionID =
secondArchive.startTransaction("Synchronize Category Path Names");
try {
Category firstCategory = firstArchive.getRootCategory();
Category secondCategory = secondArchive.getRootCategory();
synchronizeCategory(firstCategory, secondCategory);
}
finally {
secondArchive.endTransaction(transactionID, true);
}
}
}
}
private boolean hasWarning(FileDataTypeManager archive, File file) {
ArchiveWarning warning = archive.getWarning();
if (warning == ArchiveWarning.NONE) {
return false;
}
if (warning == ArchiveWarning.UPGRADED_LANGUAGE_VERSION) {
return !askYesNo("Archive Upgrade Confirmation",
"A language upgrade has been performed on archive " + file.getName() +
"\nIs it OK to proceed?");
}
popup(
"An architecture language error occured while opening archive (see log for details)\n" +
file.getPath());
return true;
}
private void synchronizeCategory(Category firstCategory, Category secondCategory) {
Category[] firstCategories = firstCategory.getCategories();
for (Category categoryA : firstCategories) {
@@ -123,18 +123,27 @@
<tocdef id="Ghidra Functionality"
sortgroup="e"
text="Ghidra Functionality"
target = "help/topics/Intro/GhidraFunctionality.htm">
<tocdef id="Code Browser" text="Code Browser" target="help/topics/CodeBrowserPlugin/CodeBrowser.htm" >
<tocdef id="Browser Field Formatter" sortgroup="a" text="Browser Field Formatter" target="help/topics/CodeBrowserPlugin/Browser_Field_Formatter.htm" />
<tocdef id="Markers" sortgroup="b" text="Markers" target="help/topics/CodeBrowserPlugin/CodeBrowser.htm#CBNavigationMarkers" />
<tocdef id="Cursor Text Highlight" sortgroup="c" text="Cursor Text Highlight" target="help/topics/CodeBrowserPlugin/CodeBrowser.htm#cursorTextHighlight" />
<tocdef id="Code Browser Configuration Options" sortgroup="d" text="Configuration Options" target="help/topics/CodeBrowserPlugin/CodeBrowserOptions.htm" />
sortgroup="e"
text="Ghidra Functionality"
target = "help/topics/Intro/GhidraFunctionality.htm">
<tocdef id="Code Browser" text="Code Browser" target="help/topics/CodeBrowserPlugin/CodeBrowser.htm" >
<tocdef id="Browser Field Formatter" sortgroup="a" text="Browser Field Formatter" target="help/topics/CodeBrowserPlugin/Browser_Field_Formatter.htm" />
<tocdef id="Markers" sortgroup="b" text="Markers" target="help/topics/CodeBrowserPlugin/CodeBrowser.htm#CBNavigationMarkers" />
<tocdef id="Cursor Text Highlight" sortgroup="c" text="Cursor Text Highlight" target="help/topics/CodeBrowserPlugin/CodeBrowser.htm#cursorTextHighlight" />
<tocdef id="Code Browser Configuration Options" sortgroup="d" text="Configuration Options" target="help/topics/CodeBrowserPlugin/CodeBrowserOptions.htm" />
</tocdef>
<tocdef id="Data Type Manager" sortgroup="c" text="Data Type Manager" target="help/topics/DataTypeManagerPlugin/data_type_manager_description.htm">
<tocdef id="DTM Concepts" sortgroup="a" text="Basic Concepts" target="help/topics/DataTypeManagerPlugin/data_type_manager_description.htm#Basic_Concepts" />
<tocdef id="DTM Window" sortgroup="b" text="Data Type Window" target="help/topics/DataTypeManagerPlugin/data_type_manager_window.html" />
<tocdef id="DTM Working With Archives" sortgroup="c" text="Archives" target="help/topics/DataTypeManagerPlugin/data_type_manager_description.htm#Archives" />
<tocdef id="DTM Working With Categories" sortgroup="d" text="Categories" target="help/topics/DataTypeManagerPlugin/data_type_manager_description.htm#Category" />
<tocdef id="DTM Working With Data Types" sortgroup="e" text="Data Types" target="help/topics/DataTypeManagerPlugin/data_type_manager_description.htm#Data_Types" />
<tocdef id="DTM Managing Archives" sortgroup="f" text="Managing Archives" target="help/topics/DataTypeManagerPlugin/data_type_manager_archives.html" />
<tocdef id="Structure Editor" sortgroup="d" text="Structure Editor" target="help/topics/DataTypeEditors/StructureEditor.htm" />
<tocdef id="Enum Editor" sortgroup="e" text="Enum Editor" target="help/topics/DataTypeEditors/EnumEditor.htm" />
</tocdef>
<tocdef id="Assembler" text="Assembler" target="help/topics/AssemblerPlugin/Assembler.htm"></tocdef>
<tocdef id="Entropy Overview" text="Entropy Overview" target="help/topics/OverviewPlugin/Overview.htm#EntropyOverviewBar" >
@@ -220,16 +229,6 @@
<tocdef id="Data" sortgroup="c" text="Data" target="help/topics/DataPlugin/Data.htm" >
<tocdef id="Create Data" sortgroup="a" text="Create Data" target="help/topics/DataPlugin/Data.htm" />
<tocdef id="Data Types" sortgroup="b" text="Data Types" target="help/topics/DataPlugin/Data.htm#DataTypes" />
<tocdef id="Data Type Manager" sortgroup="c" text="Data Type Manager" target="help/topics/DataTypeManagerPlugin/data_type_manager_description.htm">
<tocdef id="DTM Concepts" sortgroup="a" text="Basic Concepts" target="help/topics/DataTypeManagerPlugin/data_type_manager_description.htm#Basic_Concepts" />
<tocdef id="DTM Window" sortgroup="b" text="Data Type Window" target="help/topics/DataTypeManagerPlugin/data_type_manager_window.html" />
<tocdef id="DTM Working With Archives" sortgroup="c" text="Archives" target="help/topics/DataTypeManagerPlugin/data_type_manager_description.htm#Archives" />
<tocdef id="DTM Working With Categories" sortgroup="d" text="Categories" target="help/topics/DataTypeManagerPlugin/data_type_manager_description.htm#Category" />
<tocdef id="DTM Working With Data Types" sortgroup="e" text="Data Types" target="help/topics/DataTypeManagerPlugin/data_type_manager_description.htm#Data_Types" />
<tocdef id="DTM Managing Archives" sortgroup="f" text="Managing Archives" target="help/topics/DataTypeManagerPlugin/data_type_manager_archives.html" />
</tocdef>
<tocdef id="Structure Editor" sortgroup="d" text="Structure Editor" target="help/topics/DataTypeEditors/StructureEditor.htm" />
<tocdef id="Enum Editor" sortgroup="e" text="Enum Editor" target="help/topics/DataTypeEditors/EnumEditor.htm" />
<tocdef id="Translate Strings" sortgroup="e" text="Translate Strings" target="help/topics/TranslateStringsPlugin/TranslateStringsPlugin.htm" />
<tocdef id="Save Image" sortgroup="e" text="Save Image" target="help/topics/ResourceActionsPlugin/ResourceActions.html" />
</tocdef>
@@ -353,6 +353,14 @@
editing, since they support sharing and version control and therefore allow more than one
user to modify them at a time. Only one user at a time can have a file archive opened for
editing.</P>
<BLOCKQUOTE>
<P><IMG alt="" src="help/shared/tip.png">You can assign a specific <I>"Architecture"</I>
to a Data Type Archive while it is open for editing. This is recommended when an archive is targeting
a specific processor and compiler specification (see <A href="#Set_Archive_Architecture">Setting
Data Type Archive Architecture</A>).</P>
</BLOCKQUOTE>
</BLOCKQUOTE>
<BLOCKQUOTE>
@@ -406,6 +414,51 @@
Archive.</P>
</BLOCKQUOTE>
</BLOCKQUOTE>
<H3><A name="Set_Archive_Architecture"></A>Setting Data Type Archive Architecture</H3>
<BLOCKQUOTE>
<P>By default, data type archives are not assigned an architecture and adopt a default
<I>Data Organization</I> which determines primitive data type sizing (e.g., int, long, pointer, etc.)
as well as alignment and packing behavior. While data types copied between archives or a program
with disimilar <I>Data Organizations</I> will generally resolve correctly, unexpected results
may sometimes arise (e.g., bit-field packing within structures). In addition, this situation
frequently causes some confusion when viewing and editing data types where the <I>Data
Organization</I> differs from the intended target architecture.</P>
<P>With either a file or project data type archive open for editing, a specific architecture
may be assigned to the archive. This is done by selecting the open archive node from the
data type tree, right-click on it and select the <I><B>Set Architecture...</B></I> action.
This will popup a processor/compiler-specification selection dialog from which a selection
may be made and the <B>OK</B> button clicked. A final confirmation dialog will be displayed
before completing the change from which the <B>Set Architecture</B> or <B>Cancel</B> button
must be clicked to confirm or cancel the change. If confirmed, any architecture transition
will resolve all data types to the new data organization. Details related to custom variable
storage for Function Definitions (not yet implemented) will be preserved if possible but
may be discarded.</P>
<P>At present, the user will be forced to save any unsaved archive changes prior to completing
an architecture setting change to allow for a fallback if neccessary.</P>
</BLOCKQUOTE>
<H3><A name="Clear_Archive_Architecture"></A>Clearing Data Type Archive Architecture</H3>
<BLOCKQUOTE>
<P>With either a file or project data type archive open for editing, a currently assigned architecture
may be cleared for a selected archive. This is done by selecting the open archive node from the
data type tree, right-click on it and select the <I><B>Clear Architecture</B></I> action.
A final confirmation dialog will be displayed
before completing the change from which the <B>Clear Architecture</B> or <B>Cancel</B> button
must be clicked to confirm or cancel the change. If confirmed, the archive will revert a default
<I>Data Organization</I> and any custom variable storage for Function Definitions
(not yet implemented) will be discarded.
<P>At present, the user will be forced to save any unsaved changes prior to clearing the
architecture setting to allow for a fallback if neccessary.</P>
</BLOCKQUOTE>
<H3><A name="Close_Archive"></A>Closing a Data Type Archive</H3>
@@ -140,6 +140,7 @@ public class ApplyFunctionSignatureCmd extends BackgroundCommand {
func.updateFunction(conventionName, returnParam, params,
FunctionUpdateType.DYNAMIC_STORAGE_FORMAL_PARAMS, false, source);
func.setVarArgs(signature.hasVarArgs());
func.setNoReturn(signature.hasNoReturn());
}
catch (DuplicateNameException e) {
// should not happen unless caused by a concurrent operation
@@ -212,29 +213,21 @@ public class ApplyFunctionSignatureCmd extends BackgroundCommand {
}
private String getCallingConvention(Function function, CompilerSpec compilerSpec) {
PrototypeModel preferredModel = null;
if (signature.getGenericCallingConvention() != GenericCallingConvention.unknown) {
preferredModel = compilerSpec.matchConvention(signature.getGenericCallingConvention());
// Ignore signature's calling convention if unknown/not-defined
String callingConvention = signature.getCallingConventionName();
if (compilerSpec.getCallingConvention(callingConvention) == null) {
callingConvention = null;
}
PrototypeModel convention = function.getCallingConvention();
if (convention == null || !preserveCallingConvention) {
convention = preferredModel;
// NOTE: This has been disable since it can cause imported signature information to be
// ignored and overwritten by subsequent analysis
// if (convention == null && compilerSpec.getCallingConventions().length > 1) {
// // use default source for signature if convention is really unknown so that we
// // know dynamic storage assignment is unreliable
// source = SourceType.DEFAULT;
// }
// Continue using function's current calling convention if valid and either
// reservation was requested or signature's convention is unknown/not-defined.
PrototypeModel currentConvention = function.getCallingConvention();
if (currentConvention != null && (callingConvention == null || preserveCallingConvention)) {
callingConvention = function.getCallingConventionName();
}
// Calling convention is permitted to change
String conventionName = function.getCallingConventionName();
if (!preserveCallingConvention && convention != null) {
conventionName = convention.getName();
}
return conventionName;
return callingConvention;
}
private static void updateStackPurgeSize(Function function, Program program) {
@@ -1473,6 +1473,7 @@ public class DataTypeMergeManager implements MergeResolver {
ParameterDefinition[] sourceVars = sourceFunctionDefDt.getArguments();
ParameterDefinition[] destVars = new ParameterDefinition[sourceVars.length];
boolean sourceHasVarArgs = sourceFunctionDefDt.hasVarArgs();
boolean sourceHasNoReturn = sourceFunctionDefDt.hasNoReturn();
DataType resolvedRDT = DataType.DEFAULT;
if (sourceReturnType != null) {
@@ -1492,6 +1493,7 @@ public class DataTypeMergeManager implements MergeResolver {
}
destDt.setArguments(destVars);
destDt.setVarArgs(sourceHasVarArgs);
destDt.setNoReturn(sourceHasNoReturn);
destDt.setLastChangeTime(oldLastChangeTime);
destDt.setLastChangeTimeInSourceArchive(oldLastChangeTimeInSourceArchive);
@@ -29,6 +29,7 @@ import ghidra.docking.settings.Settings;
import ghidra.docking.settings.SettingsDefinition;
import ghidra.program.model.data.*;
import ghidra.program.model.data.Enum;
import ghidra.program.model.listing.Function;
import ghidra.program.model.listing.FunctionSignature;
import ghidra.util.StringUtilities;
import ghidra.util.UniversalID;
@@ -348,7 +349,14 @@ class DataTypePanel extends JPanel {
ParameterDefinition[] vars = fd.getArguments();
DataType returnType = fd.getReturnType();
if (fd.hasNoReturn()) {
insertString(FunctionSignature.NORETURN_DISPLAY_STRING + " ", contentAttrSet);
}
insertString(returnType.getDisplayName(), contentAttrSet);
String callingConventionName = fd.getCallingConventionName();
if (!Function.UNKNOWN_CALLING_CONVENTION_STRING.equals(callingConventionName)) {
insertString(callingConventionName + " ", contentAttrSet);
}
insertString(" " + fd.getDisplayName(), nameAttrSet);
insertString(" (", contentAttrSet);
boolean hasVarArgs = fd.hasVarArgs();
@@ -15,7 +15,13 @@
*/
package ghidra.app.plugin.core.compositeeditor;
import java.io.IOException;
import ghidra.program.model.data.*;
import ghidra.program.model.lang.ProgramArchitecture;
import ghidra.util.exception.AssertException;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
public class CompositeViewerDataTypeManager extends StandAloneDataTypeManager {
@@ -23,10 +29,10 @@ public class CompositeViewerDataTypeManager extends StandAloneDataTypeManager {
* The data type manager for original composite data type being edited.
* This is where the edited datatype will be written back to.
*/
private DataTypeManager originalDTM;
private Composite originalComposite;
private Composite viewComposite;
private int transactionID;
private final DataTypeManager originalDTM;
private final Composite originalComposite;
private final Composite viewComposite;
private final int transactionID;
/**
* Creates a data type manager that the structure editor will use
@@ -39,16 +45,42 @@ public class CompositeViewerDataTypeManager extends StandAloneDataTypeManager {
this.originalComposite = originalComposite;
transactionID = startTransaction("");
originalDTM = originalComposite.getDataTypeManager();
universalID = originalDTM.getUniversalID(); // mimic original DTM
ProgramArchitecture arch = originalDTM.getProgramArchitecture();
if (arch != null) {
try {
setProgramArchitecture(arch, null, true, TaskMonitor.DUMMY);
}
catch (CancelledException e) {
throw new AssertException(e); // unexpected
}
catch (IOException e) {
errHandler.dbError(e);
}
}
viewComposite = (Composite) super.resolve(originalComposite, null);
}
@Override
protected final boolean isArchitectureChangeAllowed() {
return false;
}
@Override
public void close() {
endTransaction(transactionID, true);
super.close();
}
/**
* Get the {@link DataTypeManager} associated with the original composite datatype being edited.
* @return original datatype manager
*/
public DataTypeManager getOriginalDataTypeManager() {
return originalDTM;
}
@Override
public ArchiveType getType() {
return originalDTM.getType();
@@ -1344,4 +1344,8 @@ abstract class CompositeViewerModel extends AbstractTableModel
return originalCompositeId;
}
@Override
public void programArchitectureChanged(DataTypeManager dataTypeManager) {
// don't care
}
}
@@ -15,19 +15,13 @@
*/
package ghidra.app.plugin.core.cparser;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;
import javax.swing.SwingUtilities;
import org.apache.commons.io.DirectoryWalker.CancelException;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.MenuData;
@@ -38,21 +32,17 @@ import ghidra.app.CorePluginPackage;
import ghidra.app.plugin.PluginCategoryNames;
import ghidra.app.plugin.ProgramPlugin;
import ghidra.app.services.DataTypeManagerService;
import ghidra.app.util.cparser.C.CParser;
import ghidra.app.util.cparser.CPP.PreProcessor;
import ghidra.app.util.cparser.C.CParserUtils;
import ghidra.app.util.cparser.C.CParserUtils.CParseResults;
import ghidra.framework.Application;
import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.PluginInfo;
import ghidra.framework.plugintool.PluginTool;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.program.database.data.ProgramDataTypeManager;
import ghidra.program.model.data.BuiltInDataTypeManager;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.FileDataTypeManager;
import ghidra.program.model.data.*;
import ghidra.program.model.listing.Program;
import ghidra.util.HTMLUtilities;
import ghidra.util.HelpLocation;
import ghidra.util.Msg;
import ghidra.util.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@@ -66,22 +56,20 @@ import ghidra.util.task.TaskMonitor;
)
//@formatter:on
public class CParserPlugin extends ProgramPlugin {
final static String PARSE_ACTION_NAME = "Import C DataTypes";
public final static String PARSE_ACTION_NAME = "Import C DataTypes";
final static String USER_PROFILES_DIR =
Application.getUserSettingsDirectory().getAbsolutePath() + File.separatorChar +
"parserprofiles";
private ParseDialog parseDialog;
private File userProfileDir;
private String parserMessages;
private String cppMessages;
private CParseResults results;
final static String DESCRIPTION =
"Parse C and C Header files, extracting data definitions and function signatures.";
private static final String PARSER_DEBUG_OUTFILE = "CParserPlugin.out";
public CParserPlugin(PluginTool plugintool) {
super(plugintool);
createActions();
@@ -155,26 +143,37 @@ public class CParserPlugin extends ProgramPlugin {
if (parseDialog == null) {
parseDialog = new ParseDialog(this);
}
else {
parseDialog.toFront();
}
parseDialog.setupForDisplay();
tool.showDialog(parseDialog);
}
/*
* Parse into a saved data type data base file
*/
protected void parse(String[] filenames, String options, String dataFilename) {
CParserTask parseTask = new CParserTask(this, filenames, options, dataFilename);
protected void parse(String[] filenames, String includePaths[], String options,
String languageIDString, String compilerSpecID, String dataFilename) {
CParserTask parseTask = new CParserTask(this, dataFilename)
.setFileNames(filenames)
.setIncludePaths(includePaths)
.setOptions(options)
.setLanguageID(languageIDString)
.setCompilerID(compilerSpecID);
this.getTool().execute(parseTask, 500);
}
/*
* Parse C-source into a data type manager
*/
protected void parse(String[] filenames, String options, DataTypeManager dtMgr,
protected void parse(String[] filenames, String includePaths[], String options,
String languageIDString, String compilerSpecID, DataTypeManager dtMgr,
TaskMonitor monitor) throws ghidra.app.util.cparser.C.ParseException,
ghidra.app.util.cparser.CPP.ParseException {
results = null;
String[] args = parseOptions(options);
DataTypeManager openDTmanagers[] = null;
@@ -184,100 +183,22 @@ public class CParserPlugin extends ProgramPlugin {
return; // parse canceled
}
cppMessages = "";
PreProcessor cpp = new PreProcessor();
cpp.setArgs(args);
PrintStream os = System.out;
String homeDir = System.getProperty("user.home");
String fName = homeDir + File.separator + "CParserPlugin.out";
try {
os = new PrintStream(new FileOutputStream(fName));
}
catch (FileNotFoundException e2) {
Msg.error(this, "Unexpected Exception: " + e2.getMessage(), e2);
}
PrintStream old = System.out;
System.setOut(os);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
cpp.setOutputStream(bos);
cpp.setMonitor(monitor);
try {
for (String filename : filenames) {
if (monitor.isCancelled()) {
break;
}
// any file beginning with a "#" is assumed to be a comment
if (filename.trim().startsWith("#")) {
continue;
}
File file = new File(filename);
if (file.isDirectory()) {
// process each header file in the directory
String[] children = file.list();
if (children == null) {
continue;
}
for (String element : children) {
File child = new File(file.getAbsolutePath() + "/" + element);
if (child.getName().endsWith(".h")) {
parseFile(child.getAbsolutePath(), monitor, cpp);
}
}
}
else {
parseFile(filename, monitor, cpp);
}
}
}
catch (RuntimeException re) {
os.close();
throw new ghidra.app.util.cparser.CPP.ParseException(re.getMessage());
}
// process all the defines and add any that are integer values into
// the Equates table
cpp.getDefinitions().populateDefineEquates(openDTmanagers, dtMgr);
System.out.println(bos.toString());
System.setOut(old);
os.close();
if (!monitor.isCancelled()) {
monitor.setMessage("Parsing C");
CParser cParser = new CParser(dtMgr, true, openDTmanagers);
cParser.setParseFileName(PARSER_DEBUG_OUTFILE);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
try {
parserMessages = "";
cParser.setParseFileName(fName);
cParser.setMonitor(monitor);
cParser.parse(bis);
}
finally {
parserMessages = cParser.getParseMessages();
}
results = CParserUtils.parseHeaderFiles(openDTmanagers, filenames, includePaths,
args, dtMgr, languageIDString, compilerSpecID, monitor);
final boolean isProgramDtMgr = (dtMgr instanceof ProgramDataTypeManager);
SwingUtilities.invokeLater(() -> {
// CParserTask will show any errors
if (!cParser.didParseSucceed()) {
if (!results.successful()) {
return;
}
if (isProgramDtMgr) {
MultiLineMessageDialog.showModalMessageDialog(parseDialog.getComponent(),
"C-Parse of Header Files Complete",
"Successfully parsed header file(s) to Program.",
getFormattedParseMessage(
"Check the Manage Data Types window for added data types."),
getFormattedParseMessage("Check the Manage Data Types window for added data types."),
MultiLineMessageDialog.INFORMATION_MESSAGE);
}
else {
@@ -286,20 +207,22 @@ public class CParserPlugin extends ProgramPlugin {
archiveName = ((FileDataTypeManager) dtMgr).getFilename();
}
MultiLineMessageDialog.showModalMessageDialog(parseDialog.getComponent(),
"C-Parse of Header Files Complete. ",
"C-Parse of Header Files Complete",
"Successfully parsed header file(s) to Archive File: " + archiveName,
getFormattedParseMessage(null), MultiLineMessageDialog.INFORMATION_MESSAGE);
getFormattedParseMessage(null),
MultiLineMessageDialog.INFORMATION_MESSAGE);
}
});
}
catch (IOException e) {
// ignore
}
}
/**
* Get open data type managers.
* User can Use Open managers, Select not to use, or Cancel
*
* @param openDTmanagers open mgrs, null if don't use
* @return array of open data type managers
*
* @throws CancelledException if user cancels
@@ -335,7 +258,7 @@ public class CParserPlugin extends ProgramPlugin {
"</ul>" + "<p><b>The new archive will become dependent on these archives<br>" +
"for any datatypes already defined in them </b>(only unique <br>" +
"data types will be added to the new archive).",
"Use Open Archives?", "Don't Use Open Archives", OptionDialog.QUESTION_MESSAGE);
"Use Open Archives", "Don't Use Open Archives", OptionDialog.QUESTION_MESSAGE);
if (result == OptionDialog.CANCEL_OPTION) {
throw new CancelledException("User Cancelled");
}
@@ -346,62 +269,40 @@ public class CParserPlugin extends ProgramPlugin {
return openDTmanagers;
}
public CParseResults getParseResults() {
return results;
}
public String getParseMessage() {
return (results != null ? results.cParseMessages() : "");
}
public String getFormattedParseMessage(String errMsg) {
protected String getFormattedParseMessage(String errMsg) {
String message = "";
if (errMsg != null) {
message += errMsg + "\n\n";
}
String msg = getParseMessage();
String msg = (results == null ? null : results.cParseMessages());
if (msg != null && msg.length() != 0) {
message += "CParser Messages:\n" + msg + "\n\n";
}
msg = getPreProcessorMessage();
msg = (results == null ? null : results.cppParseMessages());
if (msg != null && msg.length() != 0) {
message += "PreProcessor Messages:\n" + getPreProcessorMessage();
message += "PreProcessor Messages:\n" + msg;
}
return message;
}
/**
* Get any parse messages produced by parsing good, or informational
*
* @return messages from parser
*/
public String getParseMessage() {
return parserMessages;
}
public String getPreProcessorMessage() {
return cppMessages;
}
private void parseFile(String filename, TaskMonitor monitor, PreProcessor cpp)
throws ghidra.app.util.cparser.CPP.ParseException {
monitor.setMessage("PreProcessing " + filename);
try {
Msg.info(this, "parse " + filename);
cpp.parse(filename);
}
catch (Throwable e) {
Msg.error(this, "Parsing file :" + filename);
Msg.error(this, "Unexpected Exception: " + e.getMessage(), e);
throw new ghidra.app.util.cparser.CPP.ParseException(e.getMessage());
}
finally {
cppMessages += cpp.getParseMessages();
}
}
/*
* Parse into the current programs data type manager
*/
protected void parse(String[] filenames, String options) {
protected void parse(String[] filenames, String[] includePaths, String options,
String languageIDString, String compilerIDString) {
if (currentProgram == null) {
Msg.showInfo(getClass(), parseDialog.getComponent(), "No Open Program",
"A program must be open to \"Parse to Program\"");
@@ -413,8 +314,14 @@ public class CParserPlugin extends ProgramPlugin {
if (result == OptionDialog.CANCEL_OPTION) {
return;
}
CParserTask parseTask =
new CParserTask(this, filenames, options, currentProgram.getDataTypeManager());
new CParserTask(this, currentProgram.getDataTypeManager())
.setFileNames(filenames)
.setIncludePaths(includePaths)
.setOptions(options)
.setLanguageID(languageIDString)
.setCompilerID(compilerIDString);
tool.execute(parseTask);
}
@@ -20,44 +20,97 @@ import java.io.File;
import javax.swing.SwingUtilities;
import docking.widgets.dialogs.MultiLineMessageDialog;
import ghidra.program.model.data.DataTypeManager;
import ghidra.program.model.data.FileDataTypeManager;
import ghidra.program.model.data.*;
import ghidra.util.Msg;
import ghidra.util.exception.DuplicateFileException;
import ghidra.util.task.Task;
import ghidra.util.task.TaskMonitor;
/**
* This is called by the dialog box.
* Background task to parse files for cparser plugin
*
*
*/
class CParserTask extends Task {
private String[] filenames;
private String options;
private CParserPlugin plugin;
private String dataFileName;
private String[] filenames;
private String[] includePaths;
private String options;
private String languageString;
private String compilerString;
private DataTypeManager dtMgr;
CParserTask(CParserPlugin plugin, String[] filenames, String options, String dataFileName) {
/**
* Create task to parse to a dataFile
*
* @param plugin CParserPlugin that will do the work
* @param dataFileName name of the file to parse to
*/
CParserTask(CParserPlugin plugin, String dataFileName) {
super("Parsing C Files", true, false, false);
this.plugin = plugin;
this.filenames = filenames;
this.options = options;
this.dataFileName = dataFileName;
}
public CParserTask(CParserPlugin plugin, String[] filenames, String options,
DataTypeManager dataTypeManager) {
/**
* Create task to parse to a dataTypeManager
*
* @param plugin
* @param dataTypeManager
*/
public CParserTask(CParserPlugin plugin, DataTypeManager dataTypeManager) {
super("Parsing C Files", true, false, false);
this.plugin = plugin;
this.filenames = filenames;
this.options = options;
this.dtMgr = dataTypeManager;
}
/**
* Create task to parse to a ProgramDataTypeManager
*
* @param plugin
* @param dataTypeManager
*/
public CParserTask(CParserPlugin plugin, ProgramBasedDataTypeManager dataTypeManager) {
super("Parsing C Files", true, false, false);
this.plugin = plugin;
this.dtMgr = dataTypeManager;
}
public CParserTask setLanguageID(String languageID) {
this.languageString = languageID;
return this;
}
public CParserTask setCompilerID(String compilerID) {
this.compilerString = compilerID;
return this;
}
public CParserTask setIncludePaths(String includePaths[]) {
this.includePaths = includePaths.clone();
return this;
}
public CParserTask setFileNames(String names[]) {
this.filenames = names.clone();
return this;
}
public CParserTask setOptions(String options) {
this.options = options;
return this;
}
private String getFirstMessageLine(final String errMsg) {
int indexOf = errMsg.indexOf('\n');
String msg = errMsg;
@@ -77,8 +130,9 @@ class CParserTask extends Task {
fileDtMgr = dtMgr;
}
plugin.parse(filenames, options, dtMgr, monitor);
plugin.parse(filenames, includePaths, options, languageString, compilerString, dtMgr, monitor);
if (dataFileName != null) {
// TODO: does not consider existing datatypes
if (dtMgr.getDataTypeCount(true) != 0) {
try {
((FileDataTypeManager) dtMgr).save();
@@ -102,6 +156,10 @@ class CParserTask extends Task {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// no results, was canceled
if (plugin.getParseResults() == null) {
return;
}
MultiLineMessageDialog.showModalMessageDialog(
plugin.getDialog().getComponent(), "Parse Errors",
"File was not created due to parse errors: " +
File diff suppressed because it is too large Load Diff
@@ -180,6 +180,10 @@ public class DataTypesProvider extends ComponentProviderAdapter {
addLocalAction(new LockArchiveAction(plugin)); // Archive
addLocalAction(new UnlockArchiveAction(plugin)); // Archive
// Arch group
addLocalAction(new SetArchiveArchitectureAction(plugin)); // Archive
addLocalAction(new ClearArchiveArchitectureAction(plugin)); // Archive
// Repository group : version control actions
addVersionControlActions(); // Archive
@@ -0,0 +1,187 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.plugin.core.datamgr.actions;
import java.io.IOException;
import javax.swing.tree.TreePath;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.MenuData;
import docking.widgets.OptionDialog;
import docking.widgets.tree.GTree;
import docking.widgets.tree.GTreeNode;
import generic.theme.GThemeDefaults.Colors.Messages;
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
import ghidra.app.plugin.core.datamgr.DataTypesActionContext;
import ghidra.app.plugin.core.datamgr.archive.*;
import ghidra.app.plugin.core.datamgr.tree.*;
import ghidra.framework.model.DomainFile;
import ghidra.framework.store.LockException;
import ghidra.program.model.data.StandAloneDataTypeManager;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.*;
public class ClearArchiveArchitectureAction extends DockingAction {
private final DataTypeManagerPlugin plugin;
public ClearArchiveArchitectureAction(DataTypeManagerPlugin plugin) {
super("Clear Archive Architecture", plugin.getName());
this.plugin = plugin;
setPopupMenuData(new MenuData(new String[] { "Clear Architecture" }, null, "SetArch"));
setDescription(
"Clear program-architecture associated with a data type archive (existing custom storage details will be discarded)");
setEnabled(true);
}
@Override
public boolean isEnabledForContext(ActionContext context) {
if (!(context instanceof DataTypesActionContext)) {
return false;
}
Object contextObject = context.getContextObject();
GTree gtree = (GTree) contextObject;
TreePath[] selectionPaths = gtree.getSelectionPaths();
if (selectionPaths.length != 1) {
return false;
}
GTreeNode node = (GTreeNode) selectionPaths[0].getLastPathComponent();
if (!(node instanceof FileArchiveNode) && !(node instanceof ProjectArchiveNode)) {
return false;
}
ArchiveNode archiveNode = (ArchiveNode) node;
StandAloneDataTypeManager dtm =
(StandAloneDataTypeManager) archiveNode.getArchive().getDataTypeManager();
return dtm.getProgramArchitectureSummary() != null && dtm.isUpdatable();
}
@Override
public void actionPerformed(ActionContext context) {
GTree gtree = (GTree) context.getContextObject();
TreePath[] selectionPaths = gtree.getSelectionPaths();
if (selectionPaths.length != 1) {
return;
}
GTreeNode node = (GTreeNode) selectionPaths[0].getLastPathComponent();
if (!(node instanceof FileArchiveNode) && !(node instanceof ProjectArchiveNode)) {
return;
}
if (node instanceof ProjectArchiveNode) {
ProjectArchiveNode paNode = (ProjectArchiveNode) node;
ProjectArchive pa = (ProjectArchive) paNode.getArchive();
if (!pa.hasExclusiveAccess()) {
Msg.showError(this, null, "Clear Program Architecture Failed",
"Clearing program-architecture on Project Archive requires exclusive checkout.");
return;
}
}
ArchiveNode archiveNode = (ArchiveNode) node;
StandAloneDataTypeManager dtm =
(StandAloneDataTypeManager) archiveNode.getArchive().getDataTypeManager();
if (dtm.isChanged()) {
if (OptionDialog.OPTION_ONE != OptionDialog.showOptionDialogWithCancelAsDefaultButton(
null, "Save Archive Changes",
"Archive has unsaved changes which must be saved before continuing." +
"\nThis is required to allow for a reversion to the previous saved state.",
"Save")) {
return;
}
try {
archiveNode.getArchive().save();
}
catch (IOException e) {
Msg.showError(this, null, "Save Archive Failed",
"Failed to save changes for Archive: " + dtm.getName() + "\n" + e.getMessage());
return;
}
}
// TODO: Update message indicating that custom storage specification will not be
// retained/permitted (once supported)
String msg = "<html>Clear program-architecture for Archive?<BR><font color=\"" +
Messages.NORMAL + "\">" + dtm.getPath() +
"</font><BR> <BR>Archive will revert to using default data organization.";
int response = OptionDialog.showOptionDialogWithCancelAsDefaultButton(null,
"Confirm Clearing Archive Architecture", msg, "Clear Architecture",
OptionDialog.WARNING_MESSAGE);
if (response != OptionDialog.OPTION_ONE) {
return;
}
new TaskLauncher(new ClearProgramArchitectureTask(archiveNode.getArchive(), dtm));
}
private class ClearProgramArchitectureTask extends Task {
private final Archive archive;
private final StandAloneDataTypeManager dtm;
public ClearProgramArchitectureTask(Archive archive, StandAloneDataTypeManager dtm) {
super("Clearing Program-Architecture for Archive", true, false, true, false);
this.archive = archive;
this.dtm = dtm;
}
@Override
public void run(TaskMonitor monitor) throws CancelledException {
boolean success = false;
try {
dtm.clearProgramArchitecture(monitor);
success = true;
}
catch (CancelledException e) {
throw e;
}
catch (Exception e) {
Msg.showError(this, null, "Archive Update Failed",
"Failed to clear program-architecture for Archive: " + dtm.getName() + "\n" +
e.getMessage());
}
finally {
if (!success) {
if (archive instanceof FileArchive) {
try {
((FileArchive) archive).releaseWriteLock();
((FileArchive) archive).acquireWriteLock();
}
catch (LockException | IOException e) {
archive.close();
}
}
else { // if (archive instanceof ProjectArchive) {
archive.close();
DomainFile df = ((ProjectArchive) archive).getDomainFile();
plugin.openArchive(df);
}
}
}
}
}
}
@@ -37,8 +37,7 @@ public class DeleteArchiveAction extends DockingAction {
public DeleteArchiveAction(DataTypeManagerPlugin plugin) {
super("Delete Archive", plugin.getName());
// ACTIONS - auto generated
setPopupMenuData(new MenuData(new String[] { "Delete Archive" }, null, "Edit"));
setPopupMenuData(new MenuData(new String[] { "Delete Archive" }, null, "File"));
setKeyBindingData(new KeyBindingData(KeyEvent.VK_DELETE, 0));
@@ -0,0 +1,259 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ghidra.app.plugin.core.datamgr.actions;
import java.io.IOException;
import javax.swing.tree.TreePath;
import docking.ActionContext;
import docking.action.DockingAction;
import docking.action.MenuData;
import docking.widgets.OptionDialog;
import docking.widgets.tree.GTree;
import docking.widgets.tree.GTreeNode;
import generic.theme.GThemeDefaults.Colors.Messages;
import ghidra.app.plugin.core.datamgr.DataTypeManagerPlugin;
import ghidra.app.plugin.core.datamgr.DataTypesActionContext;
import ghidra.app.plugin.core.datamgr.archive.*;
import ghidra.app.plugin.core.datamgr.tree.*;
import ghidra.app.plugin.core.processors.SetLanguageDialog;
import ghidra.framework.model.DomainFile;
import ghidra.framework.store.LockException;
import ghidra.program.model.data.StandAloneDataTypeManager;
import ghidra.program.model.data.StandAloneDataTypeManager.LanguageUpdateOption;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.IncompatibleLanguageException;
import ghidra.program.util.DefaultLanguageService;
import ghidra.util.Msg;
import ghidra.util.Swing;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.*;
public class SetArchiveArchitectureAction extends DockingAction {
private final DataTypeManagerPlugin plugin;
public SetArchiveArchitectureAction(DataTypeManagerPlugin plugin) {
super("Set Archive Architecture", plugin.getName());
this.plugin = plugin;
setPopupMenuData(new MenuData(new String[] { "Set Architecture..." }, null, "SetArch"));
setDescription("Set program-architecture associated with a data type archive");
setEnabled(true);
}
private TreePath getSelectionPath(ActionContext context) {
Object contextObject = context.getContextObject();
GTree gtree = (GTree) contextObject;
TreePath[] selectionPaths = gtree.getSelectionPaths();
if (selectionPaths.length != 1) {
return null;
}
return selectionPaths[0];
}
@Override
public boolean isEnabledForContext(ActionContext context) {
if (!(context instanceof DataTypesActionContext)) {
return false;
}
TreePath selectionPath = getSelectionPath(context);
if (selectionPath == null) {
return false;
}
GTreeNode node = (GTreeNode) selectionPath.getLastPathComponent();
if (!(node instanceof FileArchiveNode) && !(node instanceof ProjectArchiveNode)) {
return false;
}
ArchiveNode archiveNode = (ArchiveNode) node;
StandAloneDataTypeManager dtm =
(StandAloneDataTypeManager) archiveNode.getArchive().getDataTypeManager();
return dtm.isUpdatable();
}
@Override
public void actionPerformed(ActionContext context) {
TreePath selectionPath = getSelectionPath(context);
if (selectionPath == null) {
return;
}
GTreeNode node = (GTreeNode) selectionPath.getLastPathComponent();
if (!(node instanceof FileArchiveNode) && !(node instanceof ProjectArchiveNode)) {
return;
}
if (node instanceof ProjectArchiveNode) {
ProjectArchiveNode paNode = (ProjectArchiveNode) node;
ProjectArchive pa = (ProjectArchive) paNode.getArchive();
if (!pa.hasExclusiveAccess()) {
Msg.showError(this, null, "Set Program Architecture Failed",
"Setting program-architecture on Project Archive requires exclusive checkout.");
return;
}
}
ArchiveNode archiveNode = (ArchiveNode) node;
StandAloneDataTypeManager dtm =
(StandAloneDataTypeManager) archiveNode.getArchive().getDataTypeManager();
if (dtm.isChanged()) {
if (OptionDialog.OPTION_ONE != OptionDialog.showOptionDialogWithCancelAsDefaultButton(
null, "Save Archive Changes",
"Archive has unsaved changes which must be saved before continuing." +
"\nThis is required to allow for a reversion to the previous saved state.",
"Save")) {
return;
}
try {
archiveNode.getArchive().save();
}
catch (IOException e) {
Msg.showError(this, null, "Save Archive Failed",
"Failed to save changes for Archive: " + dtm.getName() + "\n" + e.getMessage());
return;
}
}
SetLanguageDialog dialog = new SetLanguageDialog(plugin.getTool(),
dtm.getProgramArchitecture(),
"Select Program Architecture for Archive: " + dtm.getName());
LanguageID languageId = dialog.getLanguageDescriptionID();
CompilerSpecID compilerSpecId = dialog.getCompilerSpecDescriptionID();
if ((languageId == null) || (compilerSpecId == null)) {
return;
}
try {
Language language = DefaultLanguageService.getLanguageService().getLanguage(languageId);
StringBuilder buf = new StringBuilder();
buf.append(languageId.getIdAsString());
buf.append(" / ");
buf.append(compilerSpecId.getIdAsString());
String newProgramArchitectureSummary = buf.toString();
String programArchitectureSummary = dtm.getProgramArchitectureSummary();
String msg =
"<html>Set program-architecture for Archive?<BR><font color=\"" + Messages.NORMAL +
"\">" + dtm.getPath() + "</font><pre>";
if (programArchitectureSummary != null) {
msg +=
"\nChange Language/Compiler\n from: <font color=\"" + Messages.NORMAL +
"\">" +
programArchitectureSummary + "</font>\n to: ";
}
else {
msg += "\n\nLanguage/Compiler: ";
}
msg += "<font color=\"" + Messages.NORMAL + "\">";
msg += newProgramArchitectureSummary;
msg += "</font></pre>";
int response = OptionDialog.showOptionDialogWithCancelAsDefaultButton(null,
"Confirm Archive Architecture Change", msg, "Set Architecture",
OptionDialog.WARNING_MESSAGE);
if (response != OptionDialog.OPTION_ONE) {
return;
}
new TaskLauncher(new SetProgramArchitectureTask(archiveNode.getArchive(), dtm, language,
compilerSpecId));
}
catch (LanguageNotFoundException e) {
Msg.showError(this, null, "Archive Update Failed",
"Failed to set program-architecture for Archive: " + dtm.getName() + "\n" +
e.getMessage());
}
}
private class SetProgramArchitectureTask extends Task {
private final Archive archive;
private final StandAloneDataTypeManager dtm;
private final Language language;
private final CompilerSpecID compilerSpecId;
public SetProgramArchitectureTask(Archive archive, StandAloneDataTypeManager dtm,
Language language, CompilerSpecID compilerSpecId) {
super("Updating Program-Architecture for Archive", true, false, true, false);
this.archive = archive;
this.dtm = dtm;
this.language = language;
this.compilerSpecId = compilerSpecId;
}
@Override
public void run(TaskMonitor monitor) throws CancelledException {
boolean success = false;
try {
try {
dtm.setProgramArchitecture(language, compilerSpecId,
LanguageUpdateOption.TRANSLATE, monitor);
success = true;
}
catch (IncompatibleLanguageException e) {
int resp = OptionDialog.showOptionDialog(null, "Archive Architecture Change",
"<html>Unable to translate storage for specified architecture change.<BR><font color=\"" +
Messages.NORMAL + "\">" + dtm.getPath() +
"</font><BR><BR>Would you like to Clear custom storage information or Cancel change?",
"Clear");
if (resp == OptionDialog.CANCEL_OPTION) {
success = true; // keep archive open
return;
}
LanguageUpdateOption updateOption = LanguageUpdateOption.CLEAR;
if (resp == OptionDialog.OPTION_TWO) {
updateOption = LanguageUpdateOption.UNCHANGED;
}
dtm.setProgramArchitecture(language, compilerSpecId, updateOption, monitor);
success = true;
}
}
catch (CancelledException e) {
throw e;
}
catch (Exception e) {
Msg.showError(this, null, "Archive Update Failed",
"Failed to set program-architecture for Archive: " + dtm.getName() + "\n" +
e.getMessage());
}
finally {
if (!success) {
Swing.runNow(() -> {
/* flush event queue before closing archive */ });
if (archive instanceof FileArchive) {
try {
((FileArchive) archive).releaseWriteLock();
((FileArchive) archive).acquireWriteLock();
}
catch (LockException | IOException e) {
archive.close();
}
}
else { // if (archive instanceof ProjectArchive) {
archive.close();
DomainFile df = ((ProjectArchive) archive).getDomainFile();
plugin.openArchive(df);
}
}
}
}
}
}
@@ -96,17 +96,21 @@ public class ArchiveUtils {
return true;
}
catch (ReadOnlyException e) {
Msg.showError(log, null, "Unable to Lock File for Writing", e.getMessage());
Msg.showError(log, null, "Unable to Lock Archive for Writing", e.getMessage());
}
catch (LockException exc) {
Msg.showError(log, null, "Unable to Lock File for Writing",
Msg.showError(log, null, "Unable to Lock Archive for Writing",
"Unable to obtain lock for archive: " + archive.getName() + "\n" +
exc.getMessage());
}
catch (IOException ioe) {
Msg.showError(log, null, "Unable to Lock File for Writing",
"Problem attempting to lock archive: " + archive.getName() + "\n" +
ioe.getMessage());
Throwable cause = ioe.getCause();
if (cause == null) {
cause = ioe;
}
Msg.showError(log, null, "Unable to Lock Archive for Writing",
"Problem attempting to open archive for update: " + archive.getName() + "\n" +
cause.getMessage());
}
return false;
}
@@ -219,5 +219,10 @@ public class DataTypeIndexer {
public void sourceArchiveChanged(DataTypeManager dtm, SourceArchive dataTypeSource) {
markStale();
}
@Override
public void programArchitectureChanged(DataTypeManager dataTypeManager) {
markStale();
}
}
}
@@ -437,12 +437,13 @@ public class DataTypeManagerHandler {
return openArchive(new ResourceFile(file), acquireWriteLock, isUserAction);
}
public Archive openArchive(ResourceFile file, boolean acquireWriteLock, boolean isUserAction)
public FileArchive openArchive(ResourceFile file, boolean acquireWriteLock,
boolean isUserAction)
throws IOException, DuplicateIdException {
file = file.getCanonicalFile();
Archive archive = getArchiveForFile(file);
FileArchive archive = getArchiveForFile(file);
if (archive == null) {
archive = new FileArchive(this, file, acquireWriteLock);
Archive existingArchive =
@@ -451,11 +452,10 @@ public class DataTypeManagerHandler {
archive.close();
throw new DuplicateIdException(archive.getName(), existingArchive.getName());
}
addArchivePath(file);
addArchive(archive);
}
if (isUserAction && (archive instanceof FileArchive)) {
if (isUserAction) {
userOpenedFileArchiveNames.add(getSaveableArchive(file.getAbsolutePath()));
}
return archive;
@@ -524,7 +524,7 @@ public class DataTypeManagerHandler {
return null;
}
private Archive getArchiveForFile(ResourceFile file) {
private FileArchive getArchiveForFile(ResourceFile file) {
for (Archive archive : openArchives) {
if (archive instanceof FileArchive) {
FileArchive fileArchive = (FileArchive) archive;
@@ -1230,6 +1230,13 @@ public class DataTypeManagerHandler {
listener.sourceArchiveChanged(dataTypeManager, dataTypeSource);
}
}
@Override
public void programArchitectureChanged(DataTypeManager dataTypeManager) {
for (DataTypeManagerChangeListener listener : dataTypeManagerListeners) {
listener.programArchitectureChanged(dataTypeManager);
}
}
}
/**

Some files were not shown because too many files have changed in this diff Show More