GP-3209: Refactor opinions and catch missing factory names

This commit is contained in:
Dan 2023-04-21 16:31:54 -04:00
parent 9dcc504965
commit 28725b358f
6 changed files with 155 additions and 154 deletions

View file

@ -108,12 +108,16 @@ public class GdbModelTargetThread
return stack;
}
private static Long intToLong(Integer i) {
return i == null ? null : i.longValue();
}
private CompletableFuture<Void> updateInfo() {
return thread.getInfo().thenAccept(res -> {
this.info = res;
changeAttributes(List.of(), Map.of( //
SHORT_DISPLAY_ATTRIBUTE_NAME, shortDisplay = computeShortDisplay(), //
TID_ATTRIBUTE_NAME, info.getTid(), //
TID_ATTRIBUTE_NAME, intToLong(info.getTid()), //
DISPLAY_ATTRIBUTE_NAME, display = computeDisplay() //
), "Initialized");
});

View file

@ -15,16 +15,23 @@
*/
package ghidra.app.plugin.core.debug.platform.dbgeng;
import java.util.*;
import java.util.Collection;
import java.util.List;
import ghidra.app.plugin.core.debug.service.model.launch.*;
import ghidra.app.services.DebuggerModelService;
import ghidra.dbg.DebuggerModelFactory;
import ghidra.dbg.util.PathUtils;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;
public class DbgDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpinion {
public class DbgDebuggerProgramLaunchOpinion extends AbstractDebuggerProgramLaunchOpinion {
protected static final List<Class<? extends DebuggerProgramLaunchOffer>> OFFER_CLASSES =
List.of(
InVmDbgengDebuggerProgramLaunchOffer.class,
GadpDbgengDebuggerProgramLaunchOffer.class,
InVmDbgmodelDebuggerProgramLaunchOffer.class,
GadpDbgmodelDebuggerProgramLaunchOffer.class);
protected static abstract class AbstractDbgDebuggerProgramLaunchOffer
extends AbstractDebuggerProgramLaunchOffer {
@ -39,10 +46,9 @@ public class DbgDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
}
}
protected class InVmDbgengDebuggerProgramLaunchOffer
@FactoryClass("agent.dbgeng.DbgEngInJvmDebuggerModelFactory")
protected static class InVmDbgengDebuggerProgramLaunchOffer
extends AbstractDbgDebuggerProgramLaunchOffer {
private static final String FACTORY_CLS_NAME =
"agent.dbgeng.DbgEngInJvmDebuggerModelFactory";
public InVmDbgengDebuggerProgramLaunchOffer(Program program, PluginTool tool,
DebuggerModelFactory factory) {
@ -60,10 +66,9 @@ public class DbgDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
}
}
protected class GadpDbgengDebuggerProgramLaunchOffer
@FactoryClass("agent.dbgeng.gadp.DbgEngGadpDebuggerModelFactory")
protected static class GadpDbgengDebuggerProgramLaunchOffer
extends AbstractDbgDebuggerProgramLaunchOffer {
private static final String FACTORY_CLS_NAME =
"agent.dbgeng.gadp.DbgEngLocalDebuggerModelFactory";
public GadpDbgengDebuggerProgramLaunchOffer(Program program, PluginTool tool,
DebuggerModelFactory factory) {
@ -81,10 +86,9 @@ public class DbgDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
}
}
protected class InVmDbgmodelDebuggerProgramLaunchOffer
@FactoryClass("agent.dbgmodel.DbgModelInJvmDebuggerModelFactory")
protected static class InVmDbgmodelDebuggerProgramLaunchOffer
extends AbstractDbgDebuggerProgramLaunchOffer {
private static final String FACTORY_CLS_NAME =
"agent.dbgmodel.DbgModelInJvmDebuggerModelFactory";
public InVmDbgmodelDebuggerProgramLaunchOffer(Program program, PluginTool tool,
DebuggerModelFactory factory) {
@ -102,10 +106,9 @@ public class DbgDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
}
}
protected class GadpDbgmodelDebuggerProgramLaunchOffer
@FactoryClass("agent.dbgmodel.gadp.DbgModelGadpDebuggerModelFactory")
protected static class GadpDbgmodelDebuggerProgramLaunchOffer
extends AbstractDbgDebuggerProgramLaunchOffer {
private static final String FACTORY_CLS_NAME =
"agent.dbgmodel.gadp.DbgModelLocalDebuggerModelFactory";
public GadpDbgmodelDebuggerProgramLaunchOffer(Program program, PluginTool tool,
DebuggerModelFactory factory) {
@ -124,31 +127,7 @@ public class DbgDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
}
@Override
public Collection<DebuggerProgramLaunchOffer> getOffers(Program program, PluginTool tool,
DebuggerModelService service) {
String exe = program.getExecutablePath();
if (exe == null || "".equals(exe.trim())) {
return List.of();
}
List<DebuggerProgramLaunchOffer> offers = new ArrayList<>();
for (DebuggerModelFactory factory : service.getModelFactories()) {
if (!factory.isCompatible(program)) {
continue;
}
String clsName = factory.getClass().getName();
if (clsName.equals(InVmDbgengDebuggerProgramLaunchOffer.FACTORY_CLS_NAME)) {
offers.add(new InVmDbgengDebuggerProgramLaunchOffer(program, tool, factory));
}
else if (clsName.equals(GadpDbgengDebuggerProgramLaunchOffer.FACTORY_CLS_NAME)) {
offers.add(new GadpDbgengDebuggerProgramLaunchOffer(program, tool, factory));
}
else if (clsName.equals(InVmDbgmodelDebuggerProgramLaunchOffer.FACTORY_CLS_NAME)) {
offers.add(new InVmDbgmodelDebuggerProgramLaunchOffer(program, tool, factory));
}
else if (clsName.equals(GadpDbgmodelDebuggerProgramLaunchOffer.FACTORY_CLS_NAME)) {
offers.add(new GadpDbgmodelDebuggerProgramLaunchOffer(program, tool, factory));
}
}
return offers;
protected Collection<Class<? extends DebuggerProgramLaunchOffer>> getOfferClasses() {
return OFFER_CLASSES;
}
}

View file

@ -15,16 +15,21 @@
*/
package ghidra.app.plugin.core.debug.platform.frida;
import java.util.*;
import java.util.Collection;
import java.util.List;
import ghidra.app.plugin.core.debug.service.model.launch.*;
import ghidra.app.services.DebuggerModelService;
import ghidra.dbg.DebuggerModelFactory;
import ghidra.dbg.util.PathUtils;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;
public class FridaDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpinion {
public class FridaDebuggerProgramLaunchOpinion extends AbstractDebuggerProgramLaunchOpinion {
protected static final List<Class<? extends DebuggerProgramLaunchOffer>> OFFER_CLASSES =
List.of(
InVmFridaDebuggerProgramLaunchOffer.class,
GadpFridaDebuggerProgramLaunchOffer.class);
protected static abstract class AbstractFridaDebuggerProgramLaunchOffer
extends AbstractDebuggerProgramLaunchOffer {
@ -45,9 +50,9 @@ public class FridaDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchO
}
protected class InVmFridaDebuggerProgramLaunchOffer
@FactoryClass("agent.frida.FridaInJvmDebuggerModelFactory")
protected static class InVmFridaDebuggerProgramLaunchOffer
extends AbstractFridaDebuggerProgramLaunchOffer {
private static final String FACTORY_CLS_NAME = "agent.frida.FridaInJvmDebuggerModelFactory";
public InVmFridaDebuggerProgramLaunchOffer(Program program, PluginTool tool,
DebuggerModelFactory factory) {
@ -65,10 +70,9 @@ public class FridaDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchO
}
}
protected class GadpFridaDebuggerProgramLaunchOffer
@FactoryClass("agent.frida.gadp.FridaGadpDebuggerModelFactory")
protected static class GadpFridaDebuggerProgramLaunchOffer
extends AbstractFridaDebuggerProgramLaunchOffer {
private static final String FACTORY_CLS_NAME =
"agent.frida.gadp.FridaLocalDebuggerModelFactory";
public GadpFridaDebuggerProgramLaunchOffer(Program program, PluginTool tool,
DebuggerModelFactory factory) {
@ -87,25 +91,7 @@ public class FridaDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchO
}
@Override
public Collection<DebuggerProgramLaunchOffer> getOffers(Program program, PluginTool tool,
DebuggerModelService service) {
String exe = program.getExecutablePath();
if (exe == null || "".equals(exe.trim())) {
return List.of();
}
List<DebuggerProgramLaunchOffer> offers = new ArrayList<>();
for (DebuggerModelFactory factory : service.getModelFactories()) {
if (!factory.isCompatible(program)) {
continue;
}
String clsName = factory.getClass().getName();
if (clsName.equals(InVmFridaDebuggerProgramLaunchOffer.FACTORY_CLS_NAME)) {
offers.add(new InVmFridaDebuggerProgramLaunchOffer(program, tool, factory));
}
else if (clsName.equals(GadpFridaDebuggerProgramLaunchOffer.FACTORY_CLS_NAME)) {
offers.add(new GadpFridaDebuggerProgramLaunchOffer(program, tool, factory));
}
}
return offers;
protected Collection<Class<? extends DebuggerProgramLaunchOffer>> getOfferClasses() {
return OFFER_CLASSES;
}
}

View file

@ -18,14 +18,19 @@ package ghidra.app.plugin.core.debug.platform.gdb;
import java.util.*;
import ghidra.app.plugin.core.debug.service.model.launch.*;
import ghidra.app.services.DebuggerModelService;
import ghidra.dbg.DebuggerModelFactory;
import ghidra.dbg.util.ConfigurableFactory.Property;
import ghidra.dbg.util.PathUtils;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;
public class GdbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpinion {
public class GdbDebuggerProgramLaunchOpinion extends AbstractDebuggerProgramLaunchOpinion {
protected static final List<Class<? extends DebuggerProgramLaunchOffer>> OFFER_CLASSES =
List.of(
InVmGdbDebuggerProgramLaunchOffer.class,
GadpGdbDebuggerProgramLaunchOffer.class,
SshGdbDebuggerProgramLaunchOffer.class);
protected static abstract class AbstractGdbDebuggerProgramLaunchOffer
extends AbstractDebuggerProgramLaunchOffer {
@ -41,9 +46,9 @@ public class GdbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
}
protected class InVmGdbDebuggerProgramLaunchOffer
@FactoryClass("agent.gdb.GdbInJvmDebuggerModelFactory")
protected static class InVmGdbDebuggerProgramLaunchOffer
extends AbstractGdbDebuggerProgramLaunchOffer {
private static final String FACTORY_CLS_NAME = "agent.gdb.GdbInJvmDebuggerModelFactory";
public InVmGdbDebuggerProgramLaunchOffer(Program program, PluginTool tool,
DebuggerModelFactory factory) {
@ -61,31 +66,9 @@ public class GdbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
}
}
protected class InVmGdbConPtyDebuggerProgramLaunchOffer
@FactoryClass("agent.gdb.gadp.GdbGadpDebuggerModelFactory")
protected static class GadpGdbDebuggerProgramLaunchOffer
extends AbstractGdbDebuggerProgramLaunchOffer {
private static final String FACTORY_CLS_NAME =
"agent.gdb.GdbInJvmConPtyDebuggerModelFactory";
public InVmGdbConPtyDebuggerProgramLaunchOffer(Program program, PluginTool tool,
DebuggerModelFactory factory) {
super(program, tool, factory);
}
@Override
public String getConfigName() {
return "IN-VM GDB (Windows)";
}
@Override
public String getMenuTitle() {
return "in GDB locally IN-VM (Windows)";
}
}
protected class GadpGdbDebuggerProgramLaunchOffer
extends AbstractGdbDebuggerProgramLaunchOffer {
private static final String FACTORY_CLS_NAME =
"agent.gdb.gadp.GdbLocalDebuggerModelFactory";
public GadpGdbDebuggerProgramLaunchOffer(Program program, PluginTool tool,
DebuggerModelFactory factory) {
@ -103,8 +86,9 @@ public class GdbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
}
}
protected class SshGdbDebuggerProgramLaunchOffer extends AbstractGdbDebuggerProgramLaunchOffer {
private static final String FACTORY_CLS_NAME = "agent.gdb.GdbOverSshDebuggerModelFactory";
@FactoryClass("agent.gdb.GdbOverSshDebuggerModelFactory")
protected static class SshGdbDebuggerProgramLaunchOffer
extends AbstractGdbDebuggerProgramLaunchOffer {
public SshGdbDebuggerProgramLaunchOffer(Program program, PluginTool tool,
DebuggerModelFactory factory) {
@ -131,31 +115,7 @@ public class GdbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpi
}
@Override
public Collection<DebuggerProgramLaunchOffer> getOffers(Program program, PluginTool tool,
DebuggerModelService service) {
String exe = program.getExecutablePath();
if (exe == null || "".equals(exe.trim())) {
return List.of();
}
List<DebuggerProgramLaunchOffer> offers = new ArrayList<>();
for (DebuggerModelFactory factory : service.getModelFactories()) {
if (!factory.isCompatible(program)) {
continue;
}
String clsName = factory.getClass().getName();
if (clsName.equals(InVmGdbDebuggerProgramLaunchOffer.FACTORY_CLS_NAME)) {
offers.add(new InVmGdbDebuggerProgramLaunchOffer(program, tool, factory));
}
else if (clsName.equals(GadpGdbDebuggerProgramLaunchOffer.FACTORY_CLS_NAME)) {
offers.add(new GadpGdbDebuggerProgramLaunchOffer(program, tool, factory));
}
else if (clsName.equals(SshGdbDebuggerProgramLaunchOffer.FACTORY_CLS_NAME)) {
offers.add(new SshGdbDebuggerProgramLaunchOffer(program, tool, factory));
}
else if (clsName.equals(InVmGdbConPtyDebuggerProgramLaunchOffer.FACTORY_CLS_NAME)) {
offers.add(new InVmGdbConPtyDebuggerProgramLaunchOffer(program, tool, factory));
}
}
return offers;
protected Collection<Class<? extends DebuggerProgramLaunchOffer>> getOfferClasses() {
return OFFER_CLASSES;
}
}

View file

@ -15,16 +15,21 @@
*/
package ghidra.app.plugin.core.debug.platform.lldb;
import java.util.*;
import java.util.Collection;
import java.util.List;
import ghidra.app.plugin.core.debug.service.model.launch.*;
import ghidra.app.services.DebuggerModelService;
import ghidra.dbg.DebuggerModelFactory;
import ghidra.dbg.util.PathUtils;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;
public class LldbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpinion {
public class LldbDebuggerProgramLaunchOpinion extends AbstractDebuggerProgramLaunchOpinion {
protected static final List<Class<? extends DebuggerProgramLaunchOffer>> OFFER_CLASSES =
List.of(
InVmLldbDebuggerProgramLaunchOffer.class,
GadpLldbDebuggerProgramLaunchOffer.class);
protected static abstract class AbstractLldbDebuggerProgramLaunchOffer
extends AbstractDebuggerProgramLaunchOffer {
@ -40,9 +45,9 @@ public class LldbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOp
}
protected class InVmLldbDebuggerProgramLaunchOffer
@FactoryClass("agent.lldb.LldbInJvmDebuggerModelFactory")
protected static class InVmLldbDebuggerProgramLaunchOffer
extends AbstractLldbDebuggerProgramLaunchOffer {
private static final String FACTORY_CLS_NAME = "agent.lldb.LldbInJvmDebuggerModelFactory";
public InVmLldbDebuggerProgramLaunchOffer(Program program, PluginTool tool,
DebuggerModelFactory factory) {
@ -60,10 +65,9 @@ public class LldbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOp
}
}
protected class GadpLldbDebuggerProgramLaunchOffer
@FactoryClass("agent.lldb.gadp.LldbGadpDebuggerModelFactory")
protected static class GadpLldbDebuggerProgramLaunchOffer
extends AbstractLldbDebuggerProgramLaunchOffer {
private static final String FACTORY_CLS_NAME =
"agent.lldb.gadp.LldbLocalDebuggerModelFactory";
public GadpLldbDebuggerProgramLaunchOffer(Program program, PluginTool tool,
DebuggerModelFactory factory) {
@ -82,25 +86,7 @@ public class LldbDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOp
}
@Override
public Collection<DebuggerProgramLaunchOffer> getOffers(Program program, PluginTool tool,
DebuggerModelService service) {
String exe = program.getExecutablePath();
if (exe == null || "".equals(exe.trim())) {
return List.of();
}
List<DebuggerProgramLaunchOffer> offers = new ArrayList<>();
for (DebuggerModelFactory factory : service.getModelFactories()) {
if (!factory.isCompatible(program)) {
continue;
}
String clsName = factory.getClass().getName();
if (clsName.equals(InVmLldbDebuggerProgramLaunchOffer.FACTORY_CLS_NAME)) {
offers.add(new InVmLldbDebuggerProgramLaunchOffer(program, tool, factory));
}
else if (clsName.equals(GadpLldbDebuggerProgramLaunchOffer.FACTORY_CLS_NAME)) {
offers.add(new GadpLldbDebuggerProgramLaunchOffer(program, tool, factory));
}
}
return offers;
protected Collection<Class<? extends DebuggerProgramLaunchOffer>> getOfferClasses() {
return OFFER_CLASSES;
}
}

View file

@ -0,0 +1,86 @@
/* ###
* 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.service.model.launch;
import java.lang.annotation.*;
import java.lang.invoke.*;
import java.lang.invoke.MethodHandles.Lookup;
import java.util.*;
import ghidra.app.services.DebuggerModelService;
import ghidra.dbg.DebuggerModelFactory;
import ghidra.framework.plugintool.PluginTool;
import ghidra.program.model.listing.Program;
import ghidra.util.Msg;
public abstract class AbstractDebuggerProgramLaunchOpinion implements DebuggerProgramLaunchOpinion {
protected static final Lookup LOOKUP = MethodHandles.lookup();
protected static final MethodType CON_SIG = MethodType.methodType(void.class, Program.class,
PluginTool.class, DebuggerModelFactory.class);
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
protected @interface FactoryClass {
String value();
}
protected static DebuggerModelFactory getFactory(
Class<? extends DebuggerProgramLaunchOffer> offerClass, DebuggerModelService service) {
FactoryClass annotation = offerClass.getAnnotation(FactoryClass.class);
if (annotation == null) {
Msg.error(AbstractDebuggerProgramLaunchOpinion.class,
"Missing @" + FactoryClass.class.getSimpleName() + " annotation on " + offerClass);
return null;
}
Optional<DebuggerModelFactory> found = service.getModelFactories()
.stream()
.filter(f -> f.getClass().getName().equals(annotation.value()))
.findAny();
if (found.isEmpty()) {
Msg.error(AbstractDebuggerProgramLaunchOpinion.class,
"No factory with name " + annotation.value() + " required by " + offerClass);
return null;
}
return found.get();
}
protected abstract Collection<Class<? extends DebuggerProgramLaunchOffer>> getOfferClasses();
@Override
public Collection<DebuggerProgramLaunchOffer> getOffers(Program program, PluginTool tool,
DebuggerModelService service) {
String exe = program.getExecutablePath();
if (exe == null || exe.isBlank()) {
return List.of();
}
List<DebuggerProgramLaunchOffer> offers = new ArrayList<>();
for (Class<? extends DebuggerProgramLaunchOffer> cls : getOfferClasses()) {
DebuggerModelFactory factory = getFactory(cls, service);
if (factory == null || !factory.isCompatible(program)) {
continue;
}
try {
MethodHandle constructor = LOOKUP.findConstructor(cls, CON_SIG);
offers.add((DebuggerProgramLaunchOffer) constructor.invoke(program, tool, factory));
}
catch (Throwable e) {
throw new AssertionError(e);
}
}
return offers;
}
}