diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/ContextCache.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/ContextCache.java index d437e8e40f..639898eccb 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/ContextCache.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/ContextCache.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,19 +15,19 @@ */ package ghidra.app.plugin.processors.sleigh; -import ghidra.program.model.address.Address; -import ghidra.program.model.lang.*; - import java.math.BigInteger; import java.util.Arrays; +import generic.stl.Pair; +import ghidra.program.model.address.Address; +import ghidra.program.model.lang.*; + public class ContextCache { private int context_size = 0; private Register contextBaseRegister = null; - private BigInteger lastContextValue; - private int[] lastContextWords; - + Pair lastValue = null; + public ContextCache() { } @@ -57,12 +56,15 @@ public class ContextCache { } } - private synchronized int[] getWords(BigInteger value) { - if (value.equals(lastContextValue)) { - return lastContextWords; - } + private int[] getWords(BigInteger value) { + Pair lastValueTmp = lastValue; + if (lastValueTmp != null && value.equals(lastValueTmp.first)) { + return lastValueTmp.second; + } + int[] words = new int[context_size]; + byte[] bytes = value.toByteArray(); int byteIndexDiff = context_size * 4 - bytes.length; for (int i = 0; i < context_size; i++) { @@ -73,8 +75,10 @@ public class ContextCache { } words[i] = word; } - lastContextValue = value; - lastContextWords = words; + + lastValueTmp = new Pair(value, words); + lastValue = lastValueTmp; + return words; } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java index 9c68b72f09..c577072f3c 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/plugin/processors/sleigh/SleighLanguage.java @@ -20,6 +20,7 @@ import static ghidra.pcode.utils.SlaFormat.*; import java.io.*; import java.math.BigInteger; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -88,7 +89,7 @@ public class SleighLanguage implements Language { /** * Cached instruction prototypes */ - private LinkedHashMap instructProtoMap; + private ConcurrentHashMap instructProtoMap; private DecisionNode root = null; /** * table of AddressSpaces @@ -148,7 +149,7 @@ public class SleighLanguage implements Language { buildVolatileSymbolAddresses(); xrefRegisters(); - instructProtoMap = new LinkedHashMap<>(); + instructProtoMap = new ConcurrentHashMap<>(); initParallelHelper(); } @@ -374,20 +375,15 @@ public class SleighLanguage implements Language { new SleighInstructionPrototype(this, buf, context, contextcache, inDelaySlot, null); Integer hashcode = newProto.hashCode(); - if (!instructProtoMap.containsKey(hashcode)) { - newProto.cacheInfo(buf, context, true); - } - - synchronized (instructProtoMap) { - res = instructProtoMap.get(hashcode); - if (res == null) { // We have a prototype we have never seen - // before, build it fully - instructProtoMap.put(hashcode, newProto); - res = newProto; - } - if (inDelaySlot && res.hasDelaySlots()) { - throw new NestedDelaySlotException(); - } + // get existing proto and use it + // if doesn't exist in map, cache info and store new proto + res = instructProtoMap.computeIfAbsent(hashcode, h -> { + newProto.cacheInfo(buf, context, true); + return newProto; + }); + + if (inDelaySlot && res.hasDelaySlots()) { + throw new NestedDelaySlotException(); } } catch (MemoryAccessException e) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunction.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunction.java index ea569a49c6..ce492b49ad 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunction.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/HighFunction.java @@ -50,6 +50,7 @@ public class HighFunction extends PcodeSyntaxTree { private GlobalSymbolMap globalSymbols; private List jumpTables; private List protoOverrides; + private Address entryPoint; /** * @param function function associated with the higher level function abstraction. @@ -64,6 +65,7 @@ public class HighFunction extends PcodeSyntaxTree { this.language = language; this.compilerSpec = compilerSpec; AddressSpace stackSpace = function.getProgram().getAddressFactory().getStackSpace(); + entryPoint = function.getEntryPoint(); localSymbols = new LocalSymbolMap(this, stackSpace); globalSymbols = new GlobalSymbolMap(this); proto = new FunctionPrototype(localSymbols, function); @@ -87,7 +89,7 @@ public class HighFunction extends PcodeSyntaxTree { if (func instanceof FunctionDB) { return func.getSymbol().getID(); } - return func.getProgram().getSymbolTable().getDynamicSymbolID(func.getEntryPoint()); + return func.getProgram().getSymbolTable().getDynamicSymbolID(entryPoint); } /** @@ -255,7 +257,7 @@ public class HighFunction extends PcodeSyntaxTree { } if (subel == ELEM_ADDR.id()) { Address addr = AddressXML.decode(decoder); - if (!func.getEntryPoint().equals(addr)) { + if (!entryPoint.equals(addr)) { throw new DecoderException("Mismatched address in function tag"); } } @@ -300,7 +302,7 @@ public class HighFunction extends PcodeSyntaxTree { private void decodeJumpTableList(Decoder decoder) throws DecoderException { int el = decoder.openElement(ELEM_JUMPTABLELIST); while (decoder.peekElement() != 0) { - JumpTable table = new JumpTable(func.getEntryPoint().getAddressSpace()); + JumpTable table = new JumpTable(entryPoint.getAddressSpace()); table.decode(decoder); if (!table.isEmpty()) { if (jumpTables == null) { @@ -318,10 +320,10 @@ public class HighFunction extends PcodeSyntaxTree { pcaddr = rep.getPCAddress(); if (pcaddr == Address.NO_ADDRESS) { try { - pcaddr = func.getEntryPoint().add(-1); + pcaddr = entryPoint.add(-1); } catch (AddressOutOfBoundsException e) { - pcaddr = func.getEntryPoint(); + pcaddr = entryPoint; } } } @@ -446,7 +448,7 @@ public class HighFunction extends PcodeSyntaxTree { encoder.writeBool(ATTRIB_NORETURN, true); } if (entryPoint == null) { - AddressXML.encode(encoder, func.getEntryPoint()); + AddressXML.encode(encoder, this.entryPoint); } else { AddressXML.encode(encoder, entryPoint); // Address is forced on XML