mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-10 12:19:23 +08:00
Merge remote-tracking branch 'origin/patch' into Ghidra_12.1
This commit is contained in:
@@ -1,3 +1,33 @@
|
||||
# Ghidra 12.0.4 Change History (March 2026)
|
||||
|
||||
### Improvements
|
||||
* _Analysis_. Updated the RTTI Analyzer to better handle the case where class names cannot be demangled correctly. Previously, class members would end up in global namespace. Now, a class namespace with the mangled name will be created so that items in that class can be correctly grouped together. (GP-6431, Issue #8944)
|
||||
* _GUI_. Fixed a potential zip path traversal vulnerability when importing Ghidra theme zip files. (GP-6455)
|
||||
* _Scripting_. Improved RTTI Windows script vbtable discovery to recognize some invalid tables. (GP-6446, Issue #8944)
|
||||
|
||||
### Bugs
|
||||
* _Analysis_. Fixed an issue with constants from one function finding their way into another function that is jumped to, and mid-constant propagation the jump is turned into a call. (GP-6442)
|
||||
* _Analysis_. Corrected analysis problem which failed to properly link thunk functions in the EXTERNAL memory block to existing External library symbols instead of creating new external functions in the unknown external library. (GP-6465)
|
||||
* _Bookmarks_. Corrected potential Bookmark exception which can occur if bookmarks were ever deleted: <I>Missing bookmark table<I>. (GP-6517)
|
||||
* _Debugger_. Fixed a deadlock when saving Traces from the __Close Project__ dialog. (GP-6392)
|
||||
* _Debugger:Memory_. Fixed a bug in the Memory viewer when looking at multiple address spaces. (GP-6449, Issue #8982)
|
||||
* _Disassembly_. Refactored `PsuedoDisassembler` to use the normal high level Disassembler instead of calling `Language.parse()`. (GP-6496)
|
||||
* _Exporter_. Enable cancellation for SARIF exports (GP-6469)
|
||||
* _Listing_. Fixed Listing display to show single string operands. (GP-6095)
|
||||
* _Processors_. Fixed the semantics of the AARCH64 `ldpsw` instruction. (GP-5590, Issue #6469, #8008)
|
||||
* _Processors_. Fixed issue with PIC-18 instructions double-incrementing/decrementing. (GP-6004, Issue #3342, #8501)
|
||||
* _Processors_. Corrected Xtensa slapsec token field naming. (GP-6080)
|
||||
* _Processors_. Corrected semantics for the CR16 `tbit` instruction. (GP-6181, Issue #8716)
|
||||
* _Processors_. Corrected mnemonic and semantics for eBPF atomic compare-and-exchange instructions. (GP-6182, Issue #8721)
|
||||
* _Processors_. Added missing definition for PowerPC Altivec `vadduws` instruction that was mistakenly commented out. (GP-6268, Issue #8821)
|
||||
* _Processors_. Added support for AARCH64 Common Short Sequence Compression (CSSC) instructions. (GP-6448, Issue #8973, #8979)
|
||||
* _Processors_. Fixed semantics of AARCH64 `ldar` instruction. (GP-6473, Issue #6467, #8014)
|
||||
* _Processors_. Corrected disassembly for MIPS instruction `sdbbp16`. (GP-6489)
|
||||
* _Processors_. Added MIPS32 `save` and `restore` instructions, and refactored coprocessor register read/write. (GP-6501)
|
||||
|
||||
### Notable API Changes
|
||||
* _GUI_. (GP-6480) The resultsLimit and minLength parameters of the AddressRangeTableModel constructor have been removed.
|
||||
|
||||
# Ghidra 12.0.3 Change History (February 2026)
|
||||
|
||||
### New Features
|
||||
|
||||
@@ -450,7 +450,7 @@ public class SymbolicPropogator {
|
||||
this.destination = destination;
|
||||
this.pcodeIndex = pcodeIndex;
|
||||
this.continueAfterHittingFlow = continueAfterHittingFlow;
|
||||
vContext.pushMemState();
|
||||
vContext.pushMemState(pcodeIndex != 0);
|
||||
}
|
||||
|
||||
public boolean isContinueAfterHittingFlow() {
|
||||
|
||||
@@ -36,6 +36,7 @@ import ghidra.program.model.scalar.Scalar;
|
||||
import ghidra.program.model.symbol.Reference;
|
||||
import ghidra.program.model.symbol.ReferenceIterator;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.datastruct.FixedSizeHashMap;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
|
||||
@@ -76,8 +77,16 @@ public class VarnodeContext implements ProcessorContext {
|
||||
// temp values for individual instruction computation before being merged into
|
||||
// the end flow state for an instruction
|
||||
private HashMap<Address, Varnode> tempVals = new HashMap<>();
|
||||
protected HashMap<Address, Varnode> tempUniqueVals = new HashMap<>();
|
||||
protected HashMap<Address, Varnode> tempUniqueVals;
|
||||
protected boolean keepTempUniqueValues = false;
|
||||
|
||||
// During tracing of paths, unique values need to be stored if the language has crossbuilds.
|
||||
// MaxCrossBuilds is the general number of uniques with values that should be stored in the cache.
|
||||
// The maxUniqueBytes is the number of actual entries (bytes) in the cache to keep. This is based
|
||||
// on the size of a pointer, which is in general the size of a register. This is not intended
|
||||
// to support general computation of values, and is more geared to 32/64 bit contstants and pointers.
|
||||
private static final int MaxCrossBuilds = 200; // maximum instructions worth of uniques
|
||||
private int maxUniqueBytes = 0; // number of bytes worth of uniques to keep
|
||||
|
||||
// Values that must be cleared from final instruction flow state
|
||||
protected HashSet<Varnode> clearVals = new HashSet<>();
|
||||
@@ -158,7 +167,10 @@ public class VarnodeContext implements ProcessorContext {
|
||||
|
||||
memoryVals.push(new HashMap<Address, Varnode>());
|
||||
regVals.push((new HashMap<Address, Varnode>()));
|
||||
uniqueVals.push(new HashMap<Address, Varnode>());
|
||||
|
||||
maxUniqueBytes = MaxCrossBuilds * program.getDefaultPointerSize();
|
||||
tempUniqueVals = new HashMap<Address,Varnode>();
|
||||
uniqueVals.push(new FixedSizeHashMap<Address, Varnode>(maxUniqueBytes));
|
||||
|
||||
setupValidSymbolicStackNames(program);
|
||||
|
||||
@@ -169,6 +181,9 @@ public class VarnodeContext implements ProcessorContext {
|
||||
if (language instanceof SleighLanguage) {
|
||||
// Must preserve temp values if named pcode sections exist (i.e., cross-builds are used)
|
||||
keepTempUniqueValues = ((SleighLanguage) language).numSections() != 0;
|
||||
if (keepTempUniqueValues) {
|
||||
tempUniqueVals = new FixedSizeHashMap<Address, Varnode>(maxUniqueBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,9 +434,13 @@ public class VarnodeContext implements ProcessorContext {
|
||||
Varnode rvnode = null;
|
||||
if (varnode.isUnique()) {
|
||||
rvnode = getMemoryValue(tempUniqueVals,varnode,signed);
|
||||
if (rvnode == null && keepTempUniqueValues) {
|
||||
rvnode = getMemoryValue(uniqueVals,0,varnode,signed);
|
||||
}
|
||||
// TODO: if doing full cross build tracking, need to
|
||||
// look back at uniqueVals stack. For now,
|
||||
// since any cross builds are flushed on branches
|
||||
// just use tempUniqueVals
|
||||
// if (rvnode == null && keepTempUniqueValues) {
|
||||
// rvnode = getMemoryValue(uniqueVals,0,varnode,signed);
|
||||
//}
|
||||
}
|
||||
else {
|
||||
rvnode = getMemoryValue(tempVals, varnode, signed);
|
||||
@@ -1029,9 +1048,13 @@ public class VarnodeContext implements ProcessorContext {
|
||||
// merge tempvals to top of regVals
|
||||
regVals.peek().putAll(tempVals);
|
||||
|
||||
if (keepTempUniqueValues) {
|
||||
uniqueVals.peek().putAll(tempUniqueVals);
|
||||
}
|
||||
// TODO: if doing full cross build tracking, need to
|
||||
// save tmpuniques into uniqueVals. For now,
|
||||
// since any cross builds are flushed on branches
|
||||
// just use tempUniqueVals
|
||||
//if (keepTempUniqueValues) {
|
||||
// uniqueVals.peek().putAll(tempUniqueVals);
|
||||
//}
|
||||
|
||||
if (clearContext) {
|
||||
if (!keepTempUniqueValues) {
|
||||
@@ -1971,18 +1994,33 @@ public class VarnodeContext implements ProcessorContext {
|
||||
|
||||
/**
|
||||
* Save the current memory state
|
||||
* @param saveTempUniques - if internal branching, must save the tempUniques as well
|
||||
* Note: currently unique values do not survive in the sleigh parser for crossbuild
|
||||
* lookback if any branch is taken. In the future crossbuilds may be path based.
|
||||
* This will need to be re-worked and the unique value state treated as other path
|
||||
* tracing and stored in uniqueVals.
|
||||
*/
|
||||
public void pushMemState() {
|
||||
public void pushMemState(boolean saveTempUniques) {
|
||||
Stack<HashMap<Address, Varnode>> newRegValsTrace =
|
||||
(Stack<HashMap<Address, Varnode>>) regVals.clone();
|
||||
regTraces.push(newRegValsTrace);
|
||||
regVals.push(new HashMap<Address, Varnode>());
|
||||
|
||||
// TODO: only save if need to
|
||||
Stack<HashMap<Address, Varnode>> newUniqueValsTrace =
|
||||
(Stack<HashMap<Address, Varnode>>) uniqueVals.clone();
|
||||
uniqueTraces.push(newUniqueValsTrace);
|
||||
uniqueVals.push(new HashMap<Address, Varnode>());
|
||||
FixedSizeHashMap<Address, Varnode> uniqueValsState = new FixedSizeHashMap<Address, Varnode>(maxUniqueBytes);
|
||||
// if pushing state for internal branching, must save unique state for restored path
|
||||
// For now, only put temp unique values if internally branching.
|
||||
// Note: saved tempUniqueVals are stored at the top of the trace stack, this is different than
|
||||
// than other trace stacks, as those trace stacks, the top of the stack is the current
|
||||
// state and the older stack entries are existing old states before a branch occurred.
|
||||
if (saveTempUniques) {
|
||||
newUniqueValsTrace.push((HashMap<Address, Varnode>) tempUniqueVals.clone());
|
||||
} else {
|
||||
newUniqueValsTrace.push(new FixedSizeHashMap<>(maxUniqueBytes));
|
||||
}
|
||||
uniqueVals.push(uniqueValsState);
|
||||
|
||||
Stack<HashMap<Address, Varnode>> newMemValsTrace =
|
||||
(Stack<HashMap<Address, Varnode>>) memoryVals.clone();
|
||||
@@ -1999,9 +2037,14 @@ public class VarnodeContext implements ProcessorContext {
|
||||
public void popMemState() {
|
||||
regVals = regTraces.pop();
|
||||
memoryVals = memTraces.pop();
|
||||
|
||||
// TODO: only save if need to
|
||||
|
||||
// restore old temp values if any was saved
|
||||
tempUniqueVals = uniqueTraces.peek().peek();
|
||||
uniqueVals = uniqueTraces.pop();
|
||||
if (tempUniqueVals == null) {
|
||||
// if no tempUnique values stored for this path
|
||||
tempUniqueVals = new FixedSizeHashMap<>(maxUniqueBytes);
|
||||
}
|
||||
|
||||
lastSet = lastSetSaves.pop();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user