GP-5877: Fix Patch Instruction action in some Harvard architectures.

This commit is contained in:
Dan 2025-07-28 15:48:40 +00:00
parent 6f339247ef
commit 39c0a83c0c
6 changed files with 114 additions and 7 deletions

View file

@ -4,9 +4,9 @@
* 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.
@ -21,7 +21,8 @@ import ghidra.app.util.PseudoInstruction;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.*;
import ghidra.program.model.mem.*;
import ghidra.program.model.mem.DumbMemBufferImpl;
import ghidra.program.model.mem.MemBuffer;
import ghidra.program.model.util.CodeUnitInsertionException;
import ghidra.program.util.ProgramContextImpl;
import ghidra.util.Msg;
@ -85,8 +86,7 @@ public class ReDisassembler {
protected class ReDisState {
protected final TaskMonitor monitor;
protected final MemBuffer progMemBuffer =
new DumbMemBufferImpl(program.getMemory(), program.getMemory().getMinAddress());
protected final Map<AddressSpace, MemBuffer> progMemBuffers = new HashMap<>();
protected final ProgramContext tempContext = new ProgramContextImpl(language);
protected final AddressSet visited = new AddressSet();
protected final Deque<Flow> queue = new LinkedList<>();
@ -121,8 +121,9 @@ public class ReDisassembler {
}
protected MemBuffer createBuffer(Address at) {
return new WrappedMemBuffer(progMemBuffer, 20,
(int) at.subtract(progMemBuffer.getAddress()));
return progMemBuffers.computeIfAbsent(at.getAddressSpace(), space -> {
return new DumbMemBufferImpl(program.getMemory(), space.getMinAddress());
});
}
/**

View file

@ -19,6 +19,7 @@ data/languages/toy64-long8.cspec||GHIDRA||||END|
data/languages/toy64.cspec||GHIDRA||||END|
data/languages/toy64_be.slaspec||GHIDRA||||END|
data/languages/toy64_be_harvard.slaspec||GHIDRA||||END|
data/languages/toy64_be_harvard_rev.slaspec||GHIDRA||||END|
data/languages/toy64_le.slaspec||GHIDRA||||END|
data/languages/toyInstructions.sinc||GHIDRA||||END|
data/languages/toyPosStack.cspec||GHIDRA||||END|

View file

@ -79,6 +79,17 @@
<description>Toy (test) processor 64-bit big-endian Harvard</description>
<compiler name="default" spec="toy64.cspec" id="default"/>
</language>
<language processor="Toy"
endian="big"
size="64"
variant="harvard_rev"
version="1.0"
slafile="toy64_be_harvard_rev.sla"
processorspec="toy_harvard.pspec"
id="Toy:BE:64:harvard_rev">
<description>Toy (test) processor 64-bit big-endian Harvard</description>
<compiler name="default" spec="toy64.cspec" id="default"/>
</language>
<language processor="Toy"
endian="little"
size="64"

View file

@ -8,8 +8,10 @@
@define ALIGN "1"
@endif
@ifndef ALREADY_ENDIAN_ALIGN
define endian=$(ENDIAN);
define alignment=$(ALIGN);
@endif
define space ram type=ram_space size=$(SIZE) wordsize=$(WORDSIZE) default;

View file

@ -0,0 +1,16 @@
@define ENDIAN "big"
@define SIZE "8"
@define WORDSIZE "1"
@define ALIGN "1"
@define INSTR_PHASE "" # not used by basic toy language
@define DATA_SPACE "data"
@define ALREADY_ENDIAN_ALIGN
define endian=$(ENDIAN);
define alignment=$(ALIGN);
define space data type=ram_space size=$(SIZE) wordsize=$(WORDSIZE);
@include "toy.sinc"
@include "toyInstructions.sinc"

View file

@ -0,0 +1,76 @@
/* ###
* 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.program.disassemble;
import org.junit.*;
import org.junit.rules.TestName;
import db.Transaction;
import ghidra.app.plugin.assembler.Assembler;
import ghidra.app.plugin.assembler.Assemblers;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.LanguageID;
import ghidra.program.model.listing.Program;
import ghidra.program.util.DefaultLanguageService;
import ghidra.test.AbstractGhidraHeadlessIntegrationTest;
import ghidra.util.task.ConsoleTaskMonitor;
import ghidra.util.task.TaskMonitor;
public class ReDisassemblerTest extends AbstractGhidraHeadlessIntegrationTest {
Language toy;
final TaskMonitor monitor = new ConsoleTaskMonitor();
Program program;
@Rule
public TestName name = new TestName();
@Before
public void setup() throws Exception {
toy = DefaultLanguageService.getLanguageService()
.getLanguage(new LanguageID("Toy:BE:64:harvard_rev"));
}
@After
public void tearDown() throws Exception {
if (program != null) {
program.release(this);
}
}
@Test
public void testWhereDefaultSpaceIsDeclaredSecond() throws Exception {
program = createDefaultProgram(name.getMethodName(), "Toy:BE:64:harvard_rev", this);
try (Transaction tx = program.openTransaction("Init")) {
Address start =
program.getAddressFactory().getDefaultAddressSpace().getAddress(0x00400000);
Address data =
program.getAddressFactory().getAddressSpace("data").getAddress(0x00100000);
program.getMemory()
.createInitializedBlock(".data", data, 0x1000, (byte) 0, monitor, false);
program.getMemory()
.createInitializedBlock(".text", start, 0x1000, (byte) 0, monitor, false);
Assembler asm = Assemblers.getAssembler(program);
asm.assemble(start,
"imm r0, #0x23");
ReDisassembler rd = new ReDisassembler(program);
rd.disasemble(start, monitor);
}
}
}