Merge remote-tracking branch

'origin/GP-1459_Dan_gdbAArch64VectorRegs--SQUASHED' into patch
(Closes #3541)
This commit is contained in:
Ryan Kurtz 2022-11-12 01:11:30 -05:00
commit 9188a519dc
2 changed files with 125 additions and 17 deletions

View File

@ -37,10 +37,54 @@ import ghidra.util.Msg;
*/
public class GdbReadRegistersCommand
extends AbstractGdbCommandWithThreadAndFrameId<Map<GdbRegister, BigInteger>> {
protected static final Set<String> BYTE_ARRAY_KEYS = Set.of(
"v1_int8", "v2_int8", "v4_int8", "v8_int8", "v16_int8", "v32_int8", "v64_int8", // Observed on i386:x86-64
"u8" // Observed on armv7
);
protected static BigInteger tryStructPatterns(GdbCompositeValue cv, int byteCount,
ByteOrder endianness) {
for (Map.Entry<String, GdbCValue> ent : cv.entrySet()) {
switch (ent.getKey()) {
case "v1_int8", "v2_int8", "v4_int8", "v8_int8", "v16_int8", "v32_int8", "v64_int8":
// Observed on i386:x86-64
case "u8": {
// Observed on armv7
BigInteger result = (ent.getValue() instanceof GdbArrayValue arr)
? packElements(arr, byteCount, 1, endianness)
: null;
if (result != null) {
return result;
}
}
case "b": {
// Observed on aarch64
BigInteger result = (ent.getValue() instanceof GdbCompositeValue nested)
? tryStructPatternsB(nested, byteCount, endianness)
: null;
if (result != null) {
return result;
}
}
}
}
return null;
}
protected static BigInteger tryStructPatternsB(GdbCompositeValue cv, int byteCount,
ByteOrder endianness) {
for (Map.Entry<String, GdbCValue> ent : cv.entrySet()) {
switch (ent.getKey()) {
case "u": {
// Observed on aarch64, nested in "b"
BigInteger result = (ent.getValue() instanceof GdbArrayValue arr)
? packElements(arr, byteCount, 1, endianness)
: null;
if (result != null) {
return result;
}
}
}
}
return null;
}
private final Set<GdbRegister> regs;
private final GdbThreadImpl thread;
@ -68,7 +112,7 @@ public class GdbReadRegistersCommand
return b.toString();
}
protected BigInteger packElements(GdbArrayValue av, int byteCount, int bytesPer,
public static BigInteger packElements(GdbArrayValue av, int byteCount, int bytesPer,
ByteOrder endianness) {
assert bytesPer * av.size() == byteCount;
List<BigInteger> elems = av.expectBigInts();
@ -100,8 +144,8 @@ public class GdbReadRegistersCommand
return new BigInteger(1, packed);
}
protected BigInteger parseAndFindInteger(String val, int byteCount) throws GdbParseError {
ByteOrder endianness = thread.getInferior().getEndianness();
public static BigInteger parseAndFindInteger(String val, int byteCount, ByteOrder endianness)
throws GdbParseError {
if (val.contains("lbound")) {
/**
* TODO: This might be useful information, but I've only ever seen
@ -123,15 +167,9 @@ public class GdbReadRegistersCommand
return iv.getValue();
}
}
for (Map.Entry<String, GdbCValue> ent : cv.entrySet()) {
if (BYTE_ARRAY_KEYS.contains(ent.getKey())) {
GdbCValue int8v = ent.getValue();
if (!(int8v instanceof GdbArrayValue)) {
throw new AssertionError("Expected an array of ints for " + ent);
}
GdbArrayValue int8a = (GdbArrayValue) int8v;
return packElements(int8a, byteCount, 1, endianness);
}
BigInteger result = tryStructPatterns(cv, byteCount, endianness);
if (result != null) {
return result;
}
}
if (value instanceof GdbArrayValue) {
@ -157,6 +195,7 @@ public class GdbReadRegistersCommand
regs.stream().collect(Collectors.toMap(GdbRegister::getNumber, r -> r));
List<GdbMiFieldList> valueList = done.assumeRegisterValueList();
Map<GdbRegister, BigInteger> result = new LinkedHashMap<>();
ByteOrder endianness = thread.getInferior().getEndianness();
for (GdbMiFieldList fields : valueList) {
int number = Integer.parseInt(fields.getString("number"));
String value = fields.getString("value");
@ -166,7 +205,7 @@ public class GdbReadRegistersCommand
continue;
}
try {
result.put(r, parseAndFindInteger(value, r.getSize()));
result.put(r, parseAndFindInteger(value, r.getSize(), endianness));
}
catch (GdbParseError | AssertionError e) {
Msg.warn(this,

View File

@ -0,0 +1,69 @@
/* ###
* 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 agent.gdb.manager.impl;
import static org.junit.Assert.assertEquals;
import java.math.BigInteger;
import java.nio.ByteOrder;
import org.junit.Test;
import agent.gdb.manager.impl.cmd.GdbReadRegistersCommand;
public class GdbReadRegistersCommandTest {
@Test
public void testParseAndFindInteger_Integer() throws Exception {
String value = "0x1234";
assertEquals(BigInteger.valueOf(0x1234),
GdbReadRegistersCommand.parseAndFindInteger(value, 8, ByteOrder.LITTLE_ENDIAN));
}
@Test
public void testParseAndFindInteger_CompositeWithInteger() throws Exception {
String value = "{nope = {f = 0x0}, i = 0x1234}";
assertEquals(BigInteger.valueOf(0x1234),
GdbReadRegistersCommand.parseAndFindInteger(value, 8, ByteOrder.LITTLE_ENDIAN));
}
@Test
public void testParseAndFindInteger_Array() throws Exception {
String value = "{0x34, 0x12}";
assertEquals(BigInteger.valueOf(0x1234),
GdbReadRegistersCommand.parseAndFindInteger(value, 2, ByteOrder.LITTLE_ENDIAN));
}
@Test
public void testParseAndFindInteger_PatternX64() throws Exception {
String value = "{v64_int8 = {0x34, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}";
assertEquals(BigInteger.valueOf(0x1234),
GdbReadRegistersCommand.parseAndFindInteger(value, 8, ByteOrder.LITTLE_ENDIAN));
}
@Test
public void testParseAndFindInteger_PatternARMv7() throws Exception {
String value = "{u8 = {0x34, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}";
assertEquals(BigInteger.valueOf(0x1234),
GdbReadRegistersCommand.parseAndFindInteger(value, 8, ByteOrder.LITTLE_ENDIAN));
}
@Test
public void testParseAndFindInteger_PatternAArch64() throws Exception {
String value = "{b = {u = {0x34, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}";
assertEquals(BigInteger.valueOf(0x1234),
GdbReadRegistersCommand.parseAndFindInteger(value, 8, ByteOrder.LITTLE_ENDIAN));
}
}