Merge remote-tracking branch 'origin/patch'

This commit is contained in:
Ryan Kurtz 2022-04-05 16:31:51 -04:00
commit f0cb8d4ac1
13 changed files with 304 additions and 22 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Before After
Before After

View file

@ -197,6 +197,7 @@ public class DebuggerLocationLabel extends JLabel {
}
public void updateLabel() {
setText(computeLocationString());
String label = computeLocationString();
setText(label);
}
}

View file

@ -285,6 +285,13 @@ public class DebuggerMemoryBytesProvider extends ProgramByteViewerComponentProvi
locationLabel.updateLabel();
}
@Override
public boolean goTo(Program gotoProgram, ProgramLocation location) {
boolean result = super.goTo(gotoProgram, location);
locationLabel.goToAddress(location == null ? null : location.getAddress());
return result;
}
protected DebuggerCoordinates adjustCoordinates(DebuggerCoordinates coordinates) {
if (followsCurrentThread) {
return coordinates;

View file

@ -29,6 +29,7 @@ import docking.DialogComponentProvider;
import docking.widgets.model.GAddressRangeField;
import docking.widgets.model.GLifespanField;
import ghidra.app.services.DebuggerStaticMappingService;
import ghidra.framework.model.DomainFile;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
import ghidra.program.util.ProgramLocation;
@ -357,7 +358,15 @@ public class DebuggerAddMappingDialog extends DialogComponentProvider {
public void setProgram(Program program) {
this.program = program;
if (program != null) {
labelProg.setText(program.getName());
String name;
DomainFile df = program.getDomainFile();
if (df != null) {
name = df.getName();
}
else {
name = program.getName();
}
labelProg.setText(name);
fieldProgRange.setAddressFactory(program.getAddressFactory());
}
else {

View file

@ -0,0 +1,243 @@
/* ###
* 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.app.plugin.core.debug.gui.modules;
import java.awt.BorderLayout;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.Function;
import javax.swing.*;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import docking.DialogComponentProvider;
import docking.widgets.table.*;
import docking.widgets.table.ColumnSortState.SortDirection;
import docking.widgets.table.DefaultEnumeratedColumnTableModel.EnumeratedTableColumn;
import ghidra.app.services.DebuggerStaticMappingService;
import ghidra.framework.model.DomainFile;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.address.Address;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.util.ProgramLocation;
import ghidra.trace.model.modules.TraceSection;
import ghidra.util.table.GhidraTableFilterPanel;
public class DebuggerBlockChooserDialog extends DialogComponentProvider {
static class MemoryBlockRow {
private final Program program;
private final MemoryBlock block;
private double score;
public MemoryBlockRow(Program program, MemoryBlock block) {
this.program = program;
this.block = block;
}
public Program getProgram() {
return program;
}
public MemoryBlock getBlock() {
return block;
}
public String getProgramName() {
DomainFile df = program.getDomainFile();
if (df != null) {
return df.getName();
}
return program.getName();
}
public String getBlockName() {
return block.getName();
}
public Address getMinAddress() {
return block.getStart();
}
public Address getMaxAddress() {
return block.getEnd();
}
public long getLength() {
return block.getSize();
}
public double getScore() {
return score;
}
public double score(TraceSection section, DebuggerStaticMappingService service) {
if (section == null) {
return score = 0;
}
return score = service.proposeSectionMap(section, program, block).computeScore();
}
public ProgramLocation getProgramLocation() {
return new ProgramLocation(program, block.getStart());
}
}
enum MemoryBlockTableColumns
implements EnumeratedTableColumn<MemoryBlockTableColumns, MemoryBlockRow> {
SCORE("Score", Double.class, MemoryBlockRow::getScore, SortDirection.DESCENDING),
PROGRAM("Program", String.class, MemoryBlockRow::getProgramName, SortDirection.ASCENDING),
BLOCK("Block", String.class, MemoryBlockRow::getBlockName, SortDirection.ASCENDING),
START("Start Address", Address.class, MemoryBlockRow::getMinAddress, SortDirection.ASCENDING),
END("End Address", Address.class, MemoryBlockRow::getMaxAddress, SortDirection.ASCENDING),
LENGTH("Length", Long.class, MemoryBlockRow::getLength, SortDirection.ASCENDING);
<T> MemoryBlockTableColumns(String header, Class<T> cls, Function<MemoryBlockRow, T> getter,
SortDirection dir) {
this.header = header;
this.cls = cls;
this.getter = getter;
this.dir = dir;
}
private final String header;
private final Function<MemoryBlockRow, ?> getter;
private final Class<?> cls;
private final SortDirection dir;
@Override
public String getHeader() {
return header;
}
@Override
public Class<?> getValueClass() {
return cls;
}
@Override
public Object getValueOf(MemoryBlockRow row) {
return getter.apply(row);
}
@Override
public SortDirection defaultSortDirection() {
return dir;
}
}
final EnumeratedColumnTableModel<MemoryBlockRow> tableModel =
new DefaultEnumeratedColumnTableModel<>("Blocks", MemoryBlockTableColumns.class);
GTable table;
GhidraTableFilterPanel<MemoryBlockRow> filterPanel;
private Entry<Program, MemoryBlock> chosen;
protected DebuggerBlockChooserDialog() {
super("Memory Blocks", true, true, true, false);
populateComponents();
}
protected void populateComponents() {
JPanel panel = new JPanel(new BorderLayout());
table = new GTable(tableModel);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
panel.add(new JScrollPane(table));
filterPanel = new GhidraTableFilterPanel<>(table, tableModel);
panel.add(filterPanel, BorderLayout.SOUTH);
addWorkPanel(panel);
addOKButton();
addCancelButton();
table.getSelectionModel().addListSelectionListener(evt -> {
okButton.setEnabled(filterPanel.getSelectedItems().size() == 1);
// Prevent empty selection
});
// TODO: Adjust column widths?
TableColumnModel columnModel = table.getColumnModel();
TableColumn startCol = columnModel.getColumn(MemoryBlockTableColumns.START.ordinal());
startCol.setCellRenderer(CustomToStringCellRenderer.MONO_OBJECT);
TableColumn endCol = columnModel.getColumn(MemoryBlockTableColumns.END.ordinal());
endCol.setCellRenderer(CustomToStringCellRenderer.MONO_OBJECT);
TableColumn lenCol = columnModel.getColumn(MemoryBlockTableColumns.LENGTH.ordinal());
lenCol.setCellRenderer(CustomToStringCellRenderer.MONO_ULONG_HEX);
}
public Map.Entry<Program, MemoryBlock> chooseBlock(PluginTool tool, TraceSection section,
Collection<Program> programs) {
setBlocksFromPrograms(programs);
computeScores(section, tool.getService(DebuggerStaticMappingService.class));
selectHighestScoringBlock();
tool.showDialog(this);
return getChosen();
}
protected void computeScores(TraceSection section, DebuggerStaticMappingService service) {
for (MemoryBlockRow rec : tableModel.getModelData()) {
rec.score(section, service);
}
}
protected void setBlocksFromPrograms(Collection<Program> programs) {
this.tableModel.clear();
List<MemoryBlockRow> rows = new ArrayList<>();
for (Program program : programs) {
for (MemoryBlock block : program.getMemory().getBlocks()) {
rows.add(new MemoryBlockRow(program, block));
}
}
this.tableModel.addAll(rows);
}
protected void selectHighestScoringBlock() {
MemoryBlockRow best = null;
for (MemoryBlockRow rec : tableModel.getModelData()) {
if (best == null || rec.getScore() > best.getScore()) {
best = rec;
}
}
if (best != null) {
filterPanel.setSelectedItem(best);
}
}
@Override
protected void okCallback() {
MemoryBlockRow sel = filterPanel.getSelectedItem();
this.chosen = sel == null ? null : Map.entry(sel.program, sel.block);
close();
}
@Override
protected void cancelCallback() {
this.chosen = null;
close();
}
public Entry<Program, MemoryBlock> getChosen() {
return chosen;
}
}

View file

@ -44,7 +44,9 @@ public class DebuggerModuleMapProposalDialog
MODULE_NAME("Module", String.class, e -> e.getModule().getName()),
DYNAMIC_BASE("Dynamic Base", Address.class, e -> e.getModule().getBase()),
CHOOSE("Choose", String.class, e -> "Choose Program", (e, v) -> nop()),
PROGRAM_NAME("Program", String.class, e -> e.getToProgram().getName()),
PROGRAM_NAME("Program", String.class, e -> (e.getToProgram().getDomainFile() == null
? e.getToProgram().getName()
: e.getToProgram().getDomainFile().getName())),
STATIC_BASE("Static Base", Address.class, e -> e.getToProgram().getImageBase()),
SIZE("Size", Long.class, e -> e.getModuleRange().getLength());

View file

@ -1148,7 +1148,19 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
public void setProgram(Program program) {
currentProgram = program;
String name = (program == null ? "..." : program.getName());
String name;
if (program != null) {
DomainFile df = program.getDomainFile();
if (df != null) {
name = df.getName();
}
else {
name = program.getName();
}
}
else {
name = "...";
}
actionMapModuleTo.getPopupMenuData().setMenuItemName(MapModuleToAction.NAME_PREFIX + name);
actionMapSectionsTo.getPopupMenuData()
.setMenuItemName(MapSectionsToAction.NAME_PREFIX + name);
@ -1174,7 +1186,13 @@ public class DebuggerModulesProvider extends ComponentProviderAdapter {
if (block == null) {
return "...";
}
return location.getProgram().getName() + ":" + block.getName();
Program program = location.getProgram();
String name = program.getName();
DomainFile df = program.getDomainFile();
if (df != null) {
name = df.getName();
}
return name + ":" + block.getName();
}
public void setLocation(ProgramLocation location) {

View file

@ -33,11 +33,6 @@ public class DbgDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
super(program, tool, factory);
}
@Override
public String getMenuParentTitle() {
return "Debug " + program.getName();
}
@Override
protected List<String> getLauncherPath() {
return PathUtils.parse("");

View file

@ -34,11 +34,6 @@ public class GdbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
super(program, tool, factory);
}
@Override
public String getMenuParentTitle() {
return "Debug " + program.getName();
}
@Override
protected List<String> getLauncherPath() {
return PathUtils.parse("Inferiors[1]");

View file

@ -33,11 +33,6 @@ public class LldbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOp
super(program, tool, factory);
}
@Override
public String getMenuParentTitle() {
return "Debug " + program.getName();
}
@Override
protected List<String> getLauncherPath() {
return PathUtils.parse("");

View file

@ -256,7 +256,13 @@ public class TraceObjectManager {
recorder.createSnapshot(traceThread + " started", traceThread, null);
try (UndoableTransaction tid =
UndoableTransaction.start(recorder.getTrace(), "Adjust thread creation", true)) {
traceThread.setCreationSnap(recorder.getSnap());
long existing = traceThread.getCreationSnap();
if (existing == Long.MIN_VALUE) {
traceThread.setCreationSnap(recorder.getSnap());
}
else {
traceThread.setDestructionSnap(Long.MAX_VALUE);
}
}
catch (DuplicateNameException e) {
throw new AssertionError(e); // Should be shrinking

View file

@ -34,6 +34,7 @@ import ghidra.dbg.target.TargetMethod.ParameterDescription;
import ghidra.dbg.target.TargetObject;
import ghidra.dbg.target.schema.TargetObjectSchema;
import ghidra.dbg.util.PathUtils;
import ghidra.framework.model.DomainFile;
import ghidra.framework.options.SaveState;
import ghidra.framework.plugintool.AutoConfigState.ConfigStateField;
import ghidra.framework.plugintool.PluginTool;
@ -56,6 +57,16 @@ public abstract class AbstractDebuggerProgramLaunchOffer implements DebuggerProg
this.factory = factory;
}
@Override
public String getMenuParentTitle() {
String name = program.getName();
DomainFile df = program.getDomainFile();
if (df != null) {
name = df.getName();
}
return "Debug " + name;
}
protected List<String> getLauncherPath() {
return PathUtils.parse("");
}

View file

@ -44,7 +44,7 @@ import ghidra.app.plugin.core.debug.DebuggerCoordinates;
import ghidra.app.plugin.core.debug.gui.AbstractGhidraHeadedDebuggerGUITest;
import ghidra.app.plugin.core.debug.gui.DebuggerResources;
import ghidra.app.plugin.core.debug.gui.DebuggerResources.AbstractFollowsCurrentThreadAction;
import ghidra.app.plugin.core.debug.gui.action.*;
import ghidra.app.plugin.core.debug.gui.action.DebuggerGoToDialog;
import ghidra.app.plugin.core.debug.gui.listing.DebuggerListingPlugin;
import ghidra.app.services.TraceRecorder;
import ghidra.async.SwingExecutorService;