mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-23 12:49:45 +00:00
Merge remote-tracking branch 'origin/GP-2089_Dan_supportGdb12--SQUASHED'
(Closes #4297)
This commit is contained in:
commit
cbeca0c544
@ -40,12 +40,22 @@ import ghidra.util.Msg;
|
||||
* The implementation of {@link GdbInferior}
|
||||
*/
|
||||
public class GdbInferiorImpl implements GdbInferior {
|
||||
protected static final Pattern MEMORY_MAPPING_LINE_PATTERN = Pattern.compile("\\s*" + //
|
||||
"0x(?<start>[0-9,A-F,a-f]+)\\s+" + //
|
||||
"0x(?<end>[0-9,A-F,a-f]+)\\s+" + //
|
||||
"0x(?<size>[0-9,A-F,a-f]+)\\s+" + //
|
||||
"0x(?<offset>[0-9,A-F,a-f]+)\\s*" + //
|
||||
"(?<file>\\S*)\\s*");
|
||||
protected static final Pattern MEMORY_MAPPING_WOUT_FLAGS_LINE_PATTERN =
|
||||
Pattern.compile("\\s*" +
|
||||
"0x(?<start>[0-9,A-F,a-f]+)\\s+" +
|
||||
"0x(?<end>[0-9,A-F,a-f]+)\\s+" +
|
||||
"0x(?<size>[0-9,A-F,a-f]+)\\s+" +
|
||||
"0x(?<offset>[0-9,A-F,a-f]+)\\s+" +
|
||||
"(?<file>\\S*)\\s*");
|
||||
|
||||
protected static final Pattern MEMORY_MAPPING_LINE_PATTERN =
|
||||
Pattern.compile("\\s*" + //
|
||||
"0x(?<start>[0-9,A-F,a-f]+)\\s+" +
|
||||
"0x(?<end>[0-9,A-F,a-f]+)\\s+" +
|
||||
"0x(?<size>[0-9,A-F,a-f]+)\\s+" +
|
||||
"0x(?<offset>[0-9,A-F,a-f]+)\\s+" +
|
||||
"(?<flags>[rwsxp\\-]+)\\s+" +
|
||||
"(?<file>\\S*)\\s*");
|
||||
|
||||
private final GdbManagerImpl manager;
|
||||
private final int id;
|
||||
@ -367,21 +377,47 @@ public class GdbInferiorImpl implements GdbInferior {
|
||||
.thenApply(this::parseMappings);
|
||||
}
|
||||
|
||||
protected GdbMemoryMapping parseMappingLine(String line) throws NumberFormatException {
|
||||
Matcher mappingMatcher = MEMORY_MAPPING_LINE_PATTERN.matcher(line);
|
||||
if (!mappingMatcher.matches()) {
|
||||
return null;
|
||||
}
|
||||
BigInteger start = new BigInteger(mappingMatcher.group("start"), 16);
|
||||
BigInteger end = new BigInteger(mappingMatcher.group("end"), 16);
|
||||
BigInteger size = new BigInteger(mappingMatcher.group("size"), 16);
|
||||
BigInteger offset = new BigInteger(mappingMatcher.group("offset"), 16);
|
||||
String flags = mappingMatcher.group("flags");
|
||||
String objfile = mappingMatcher.group("file");
|
||||
return new GdbMemoryMapping(start, end, size, offset, flags, objfile);
|
||||
}
|
||||
|
||||
protected GdbMemoryMapping parseMappingsLineWOutFlags(String line)
|
||||
throws NumberFormatException {
|
||||
Matcher mappingMatcher = MEMORY_MAPPING_WOUT_FLAGS_LINE_PATTERN.matcher(line);
|
||||
if (!mappingMatcher.matches()) {
|
||||
return null;
|
||||
}
|
||||
BigInteger start = new BigInteger(mappingMatcher.group("start"), 16);
|
||||
BigInteger end = new BigInteger(mappingMatcher.group("end"), 16);
|
||||
BigInteger size = new BigInteger(mappingMatcher.group("size"), 16);
|
||||
BigInteger offset = new BigInteger(mappingMatcher.group("offset"), 16);
|
||||
String objfile = mappingMatcher.group("file");
|
||||
return new GdbMemoryMapping(start, end, size, offset, "rwx", objfile);
|
||||
}
|
||||
|
||||
protected Map<BigInteger, GdbMemoryMapping> parseMappings(String out) {
|
||||
Set<BigInteger> startsSeen = new TreeSet<>();
|
||||
for (String line : out.split("\n")) {
|
||||
Matcher mappingMatcher = MEMORY_MAPPING_LINE_PATTERN.matcher(line);
|
||||
if (!mappingMatcher.matches()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
BigInteger start = new BigInteger(mappingMatcher.group("start"), 16);
|
||||
BigInteger end = new BigInteger(mappingMatcher.group("end"), 16);
|
||||
BigInteger size = new BigInteger(mappingMatcher.group("size"), 16);
|
||||
BigInteger offset = new BigInteger(mappingMatcher.group("offset"), 16);
|
||||
String objfile = mappingMatcher.group("file");
|
||||
startsSeen.add(start);
|
||||
mappings.put(start, new GdbMemoryMapping(start, end, size, offset, objfile));
|
||||
GdbMemoryMapping mapping = parseMappingLine(line);
|
||||
if (mapping == null) {
|
||||
mapping = parseMappingsLineWOutFlags(line);
|
||||
}
|
||||
if (mapping == null) { // still, so it matches neither pattern
|
||||
continue; // It's just a throw-away line, or the format changed again.
|
||||
}
|
||||
startsSeen.add(mapping.getStart());
|
||||
mappings.put(mapping.getStart(), mapping);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
Msg.error(this, "Could not parse mapping entry: " + line, e);
|
||||
|
@ -18,40 +18,96 @@ package agent.gdb.manager.impl;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* The abstraction for a line of output from {@code info proc mappings}
|
||||
*/
|
||||
public class GdbMemoryMapping {
|
||||
private final BigInteger start;
|
||||
private final BigInteger end;
|
||||
private final BigInteger size;
|
||||
private final BigInteger offset;
|
||||
private final String flags;
|
||||
private final String objfile;
|
||||
|
||||
/**
|
||||
* Construct a memory mapping
|
||||
*
|
||||
* @param start the start offset
|
||||
* @param end the end offset
|
||||
* @param size the size (must be end - start)
|
||||
* @param offset if backed by a file, the offset into that file
|
||||
* @param flags the flags: rwxsp for read, write, execute, shared, private. If not known, the
|
||||
* default "rwx" should be used.
|
||||
* @param objfile if backed by a file, the name of that file
|
||||
*/
|
||||
public GdbMemoryMapping(BigInteger start, BigInteger end, BigInteger size, BigInteger offset,
|
||||
String objfile) {
|
||||
String flags, String objfile) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.size = size;
|
||||
this.offset = offset;
|
||||
this.flags = flags;
|
||||
this.objfile = objfile;
|
||||
|
||||
assert Objects.equals(start.add(size), end);
|
||||
}
|
||||
|
||||
/**
|
||||
* The start offset
|
||||
*
|
||||
* @return the offset
|
||||
*/
|
||||
public BigInteger getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* The end offset
|
||||
*
|
||||
* @return the end
|
||||
*/
|
||||
public BigInteger getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
/**
|
||||
* The size
|
||||
*
|
||||
* @return the size
|
||||
*/
|
||||
public BigInteger getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* If backed by a file, the offset into that file
|
||||
*
|
||||
* @return the offset
|
||||
*/
|
||||
public BigInteger getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* The flags
|
||||
*
|
||||
* <p>
|
||||
* As of gdb-12.1, this is a four-character string, e.g., r--p, where the first three indicate
|
||||
* <b>r</b>ead, <b>w</b>rite, and e<b>x</b>ecute. Each position is either the character
|
||||
* indicating the flag is present, or a dash indicating the flag is absent. The final position
|
||||
* is either {@code s} or {@code p} to indicate shared or private.
|
||||
*
|
||||
* @return the flags
|
||||
*/
|
||||
public String getFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* If backed by a file, the name of that file
|
||||
*
|
||||
* @return the file
|
||||
*/
|
||||
public String getObjfile() {
|
||||
return objfile;
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ public class GdbModelTargetMemoryRegion
|
||||
}
|
||||
|
||||
protected AddressRangeImpl range;
|
||||
protected final String flags;
|
||||
protected final String objfile;
|
||||
protected final long offset;
|
||||
protected final String display;
|
||||
@ -76,6 +77,7 @@ public class GdbModelTargetMemoryRegion
|
||||
catch (AddressFormatException | AddressOverflowException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
this.flags = mapping.getFlags();
|
||||
changeAttributes(List.of(), Map.of( //
|
||||
MEMORY_ATTRIBUTE_NAME, memory, //
|
||||
RANGE_ATTRIBUTE_NAME, range, //
|
||||
@ -111,19 +113,20 @@ public class GdbModelTargetMemoryRegion
|
||||
|
||||
@Override
|
||||
public boolean isReadable() {
|
||||
// It can be done if debugging locally on Linux, by reading /proc/[PID]/maps
|
||||
// The sections listing will give the initial protections.
|
||||
return true; // TODO
|
||||
// This was added at or near gdb-12.1
|
||||
return flags.contains("r");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable() {
|
||||
return true; // TODO
|
||||
// This was added at or near gdb-12.1
|
||||
return flags.contains("w");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExecutable() {
|
||||
return true; // TODO
|
||||
// This was added at or near gdb-12.1
|
||||
return flags.contains("x");
|
||||
}
|
||||
|
||||
@TargetAttributeType(
|
||||
|
@ -76,16 +76,16 @@ public class GdbModelTargetProcessMemory
|
||||
if (end.longValue() < 0) {
|
||||
BigInteger split = BigInteger.valueOf(Long.MAX_VALUE);
|
||||
GdbMemoryMapping lmem = new GdbMemoryMapping(start, split,
|
||||
split.subtract(start), start.subtract(start), "defaultLow");
|
||||
split.subtract(start), start.subtract(start), "rwx", "defaultLow");
|
||||
defaultMap.put(start, lmem);
|
||||
split = split.add(BigInteger.valueOf(1));
|
||||
GdbMemoryMapping hmem = new GdbMemoryMapping(split, end,
|
||||
end.subtract(split), split.subtract(split), "defaultHigh");
|
||||
end.subtract(split), split.subtract(split), "rwx", "defaultHigh");
|
||||
defaultMap.put(split, hmem);
|
||||
}
|
||||
else {
|
||||
GdbMemoryMapping mem = new GdbMemoryMapping(start, end,
|
||||
end.subtract(start), start.subtract(start), "default");
|
||||
end.subtract(start), start.subtract(start), "rwx", "default");
|
||||
defaultMap.put(start, mem);
|
||||
}
|
||||
regions =
|
||||
@ -104,7 +104,7 @@ public class GdbModelTargetProcessMemory
|
||||
// Can't use refresh getKnownMappings is only populated by listMappings
|
||||
return doRefresh();
|
||||
}
|
||||
|
||||
|
||||
protected CompletableFuture<Void> doRefresh() {
|
||||
if (inferior.getPid() == null) {
|
||||
setElements(List.of(), "Refreshed (while no process)");
|
||||
|
@ -37,6 +37,8 @@ import ghidra.util.Msg;
|
||||
*/
|
||||
public abstract class AbstractDebuggerModelScenarioMemoryTest extends AbstractDebuggerModelTest {
|
||||
|
||||
// TODO: Something for expected flags, permissions?
|
||||
|
||||
/**
|
||||
* This specimen must perform some observable action, which can be affected by a memory write
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user