Merge branch 'GP-5619_emteere_VariousSpeedImprovements_VERSION2'

This commit is contained in:
ghidra1 2025-05-08 16:18:38 -04:00
commit 0bf8f03a1e
79 changed files with 2290 additions and 1275 deletions

View file

@ -534,7 +534,7 @@ public abstract class AbstractTraceRmiLaunchOffer implements TraceRmiLaunchOffer
Map<String, TerminalSession> sessions, Map<String, ValStr<?>> args,
SocketAddress address) throws Exception;
static class NoStaticMappingException extends Exception {
public static class NoStaticMappingException extends Exception {
public NoStaticMappingException(String message) {
super(message);
}

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.
@ -91,7 +91,7 @@ public class LaunchAction extends MultiActionDockingAction {
.popupMenuIcon(offer.getIcon())
.helpLocation(offer.getHelpLocation())
.enabledWhen(ctx -> true)
.onAction(ctx -> plugin.relaunch(offer))
.onAction(ctx -> plugin.relaunch(ctx, offer))
.build());
}
return actions;
@ -148,7 +148,7 @@ public class LaunchAction extends MultiActionDockingAction {
Swing.runLater(() -> button.showPopup());
return;
}
plugin.relaunch(offer);
plugin.relaunch(context, offer);
}
@Override

View file

@ -78,6 +78,6 @@ public class PowerShellScriptTraceRmiLaunchOffer extends AbstractScriptTraceRmiL
protected void prepareSubprocess(List<String> commandLine, Map<String, String> env,
Map<String, ValStr<?>> args, SocketAddress address) {
super.prepareSubprocess(commandLine, env, args, address);
commandLine.add(0, "powershell");
commandLine.addAll(0, List.of("powershell", "-File"));
}
}

View file

@ -342,7 +342,8 @@ public abstract class ScriptAttributesParser {
public record ScriptAttributes(String title, String description, List<String> menuPath,
String menuGroup, String menuOrder, Icon icon, HelpLocation helpLocation,
Map<String, LaunchParameter<?>> parameters, Map<String, TtyCondition> extraTtys,
int timeoutMillis, LaunchParameter<?> imageOpt) {}
int timeoutMillis, LaunchParameter<?> imageOpt) {
}
/**
* Convert an arguments map into a command line and environment variables

View file

@ -15,6 +15,7 @@
*/
package ghidra.app.plugin.core.debug.gui.tracermi.launcher;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.util.*;
@ -25,6 +26,7 @@ import org.jdom.Element;
import org.jdom.JDOMException;
import db.Transaction;
import docking.ActionContext;
import docking.action.DockingActionIf;
import docking.action.builder.ActionBuilder;
import ghidra.app.events.ProgramActivatedPluginEvent;
@ -348,6 +350,16 @@ public class TraceRmiLauncherServicePlugin extends Plugin
executeTask(new ReLaunchTask(offer));
}
protected void relaunch(ActionContext ctx, TraceRmiLaunchOffer offer) {
int mods = ctx == null ? 0 : ctx.getEventClickModifiers();
if ((mods & ActionEvent.SHIFT_MASK) != 0) {
configureAndLaunch(offer);
}
else {
relaunch(offer);
}
}
protected void configureAndLaunch(TraceRmiLaunchOffer offer) {
executeTask(new ConfigureAndLaunchTask(offer));
}
@ -478,7 +490,8 @@ public class TraceRmiLauncherServicePlugin extends Plugin
toolLaunchConfigs.putSaveState(name, state);
}
protected record ConfigLast(String configName, long last, Program program) {}
protected record ConfigLast(String configName, long last, Program program) {
}
protected ConfigLast checkSavedConfig(Program program, ProgramUserData userData,
String propName) {

View file

@ -64,13 +64,16 @@ public abstract class AbstractTraceRmiConnection implements TraceRmiConnection {
if (!traceManager.getOpenTraces().contains(trace)) {
traceManager.openTrace(trace);
traceManager.activate(finalCoords, ActivationCause.SYNC_MODEL);
return;
}
else {
Trace currentTrace = traceManager.getCurrentTrace();
if (currentTrace == null || ownsTrace(currentTrace)) {
traceManager.activate(finalCoords, ActivationCause.SYNC_MODEL);
}
Trace currentTrace = traceManager.getCurrentTrace();
if (currentTrace == null || ownsTrace(currentTrace)) {
traceManager.activate(finalCoords, ActivationCause.SYNC_MODEL);
return;
}
// LATER: See if all this ownership checking is really necessary.
// For now, just always activate anyway
traceManager.activate(finalCoords, ActivationCause.SYNC_MODEL);
});
}
}

View file

@ -17,7 +17,7 @@ classifiers = [
"Operating System :: OS Independent",
]
dependencies = [
"protobuf >= 3, < 4",
"protobuf >= 3.20.0",
]
[project.urls]

View file

@ -1,15 +1,15 @@
## ###
# 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.
# 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.
##

View file

@ -13,7 +13,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
##
from typing import get_args, get_origin
try:
from . import trace_rmi_pb2 as bufs
except Exception as e:
from .setuputils import prompt_and_mitigate_dependencies
prompt_and_mitigate_dependencies("Debug/Debugger-rmi-trace")
from collections import deque
from concurrent.futures import Executor, Future
from contextlib import contextmanager
@ -26,12 +32,12 @@ import traceback
from typing import (Annotated, Any, Callable, Collection, Dict, Generator,
Generic, Iterable, List, MutableSequence, Optional,
Sequence, Tuple, TypeVar, Union)
from typing import get_args, get_origin
from google.protobuf.internal.containers import (
RepeatedCompositeFieldContainer as RCFC)
from . import sch
from . import trace_rmi_pb2 as bufs
from .util import send_delimited, recv_delimited
@ -188,7 +194,6 @@ class TraceObject:
else:
return '<Future>'
def insert(self, span: Optional[Lifespan] = None,
resolution: str = 'adjust') -> Union[
Lifespan, RemoteResult[Any, Lifespan]]:
@ -654,7 +659,7 @@ class MethodRegistry(object):
return ''
@classmethod
def _make_param(cls, s:inspect.Signature, p: inspect.Parameter) -> RemoteParameter:
def _make_param(cls, s: inspect.Signature, p: inspect.Parameter) -> RemoteParameter:
schema = cls._to_schema(s, p.annotation)
required = p.default is p.empty
return RemoteParameter(

View file

@ -0,0 +1,124 @@
## ###
# 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.
##
"""
This file holds utilities required by Python-based connectors. At the
moment, that includes all connectors except the ones targeting Java
applications. While uncommon, it is possible that dependencies turn up
missing on a remote target, and so the gmodutils.py file will not be
present. However, by the time such dependencies turn up missing,
whether remote or local, the PYTHONPATH should already include this
module, and so we place the setup logic here.
"""
import os
from typing import List, Sequence
home = os.getenv('GHIDRA_HOME')
def ghidra_module_src(name: str) -> str:
installed = f'{home}/Ghidra/{name}/pypkg'
if os.path.isdir(installed):
return installed
dev1 = f'{home}/Ghidra/{name}/src/main/py'
if os.path.isdir(dev1):
return dev1
dev2 = f'{home}/ghidra/Ghidra/{name}/src/main/py'
if os.path.isdir(dev2):
return dev2
raise Exception(f"""
Cannot find Python source for {name}.
If this is a remote system, we shouldn't even be here. Chances are,
the Python dependencies required by ghidra on the remote system were
removed or replaced with incompatible versions. If this is a local
system, your installation or development repo may be corrupt.
""")
def get_module_dependencies(name: str) -> List[str]:
src = ghidra_module_src(name)
# Can't rely on tomllib until Python 3.11 is minimum requirement.
# And, I'm in a place where I presume deps are missing, so do this garbage
# of a parse job.
with open(f"{src}/pyproject.toml") as project:
seen_deps = False
result: List[str] = []
for l in project.readlines():
l = l.strip()
if l == "dependencies = [":
seen_deps = True
elif seen_deps and l == ']':
return [r for r in result if not 'ghidra' in r]
elif seen_deps:
if l.endswith(','): # Last one may not have ,
l = l[:-1].strip()
result.append(l[1:-1]) # Remove 's or "s
raise Exception("Could not parse pyproject.toml")
def prompt_mitigation(msg: str, prompt: str) -> bool:
print("""
--------------------------------------------------------------------------------
!!! INCORRECT OR INCOMPLETE SETUP !!!
--------------------------------------------------------------------------------
""")
print(msg)
print("")
print("Select KEEP if you're seeing this in an error dialog.")
print(f"{prompt} [Y/n] ", end="")
answer = input()
return answer == 'y' or answer == 'Y' or answer == ''
def mitigate_by_pip_install(*args: str) -> None:
import sys
import runpy
sys.argv = [
'pip', 'install', '--force-reinstall', *args
]
os.environ['PIP_BREAK_SYSTEM_PACKAGES'] = '1'
runpy.run_module("pip", run_name="__main__")
def prompt_and_mitigate_dependencies(name: str) -> None:
deps = get_module_dependencies(name)
deps_str = ' '.join(f"'{d}'" for d in deps)
answer = prompt_mitigation("""
It appears dependencies are missing or have the wrong version. This can happen
if you forgot to install the required packages. This can also happen if you
installed the packages to a different Python environment than is being used
right now.
This script is about to offer automatic resolution. If you'd like to resolve
this manually, answer no to the next question and then see Ghidra's help by
pressing F1 in the dialog of launch parameters.
WARNING: Answering yes to the next question will invoke pip to try to install
missing or incorrectly-versioned dependencies. It may attempt to find packages
from your configured PyPI mirror. If you have not configured one, it will
connect to the official one.
WARNING: We invoke pip with the --break-system-packages flag, because some
debuggers that embed Python (gdb, lldb) may not support virtual environments,
and so the packages must be installed to your user environment.
NOTE: Automatic resolution may cause this session to terminate. When it has
finished, close this terminal, and try launching again.
""", f"Would you like to install {deps_str}?")
if answer:
mitigate_by_pip_install('-f', '../../pypkg/dist', *deps)