mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Merge branch 'NationalSecurityAgency:master' into armv8-splimit
This commit is contained in:
commit
68171d3302
10853 changed files with 691087 additions and 483887 deletions
11
.gitignore
vendored
11
.gitignore
vendored
|
@ -68,6 +68,7 @@ Release
|
||||||
.classpath
|
.classpath
|
||||||
.settings/
|
.settings/
|
||||||
.prefs
|
.prefs
|
||||||
|
.pydevproject
|
||||||
|
|
||||||
# Ignore XTEXT generated dirs/files
|
# Ignore XTEXT generated dirs/files
|
||||||
*/*/*/*/xtend-gen
|
*/*/*/*/xtend-gen
|
||||||
|
@ -81,12 +82,12 @@ Release
|
||||||
*.iml
|
*.iml
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
# Ignore gradle wrapper files
|
|
||||||
gradle/wrapper
|
|
||||||
gradlew
|
|
||||||
gradlew.*
|
|
||||||
|
|
||||||
# Ignore logs and core dumps
|
# Ignore logs and core dumps
|
||||||
*.log
|
*.log
|
||||||
core.*
|
core.*
|
||||||
!core.png
|
!core.png
|
||||||
|
!core.py
|
||||||
|
|
||||||
|
# python files
|
||||||
|
*.egg-info
|
||||||
|
__pycache__
|
||||||
|
|
248
DevGuide.md
248
DevGuide.md
|
@ -32,40 +32,51 @@ authors' names directly in the source code, so it is discouraged.
|
||||||
Download non-Maven Central dependencies. This creates a `dependencies` directory in the repository
|
Download non-Maven Central dependencies. This creates a `dependencies` directory in the repository
|
||||||
root.
|
root.
|
||||||
```
|
```
|
||||||
$ gradle -I gradle/support/fetchDependencies.gradle init
|
gradle -I gradle/support/fetchDependencies.gradle
|
||||||
```
|
```
|
||||||
|
|
||||||
Download Maven Central dependencies and setup the repository for development. By default, these
|
Download Maven Central dependencies and setup the repository for development. By default, these
|
||||||
will be stored at `$HOME/.gradle/`.
|
will be stored at `$HOME/.gradle/`.
|
||||||
```
|
```
|
||||||
$ gradle prepdev
|
gradle prepdev
|
||||||
```
|
```
|
||||||
|
|
||||||
Generate nested Eclipse project files which can then be imported into Eclipse as "existing
|
Generate nested Eclipse project files which can then be imported into Eclipse as "existing
|
||||||
projects".
|
projects".
|
||||||
```
|
```
|
||||||
$ gradle cleanEclipse eclipse
|
gradle cleanEclipse eclipse
|
||||||
```
|
```
|
||||||
|
|
||||||
Build native components for your current platform. Requires native tool chains to be present.
|
Build native components for your current platform. Requires native tool chains to be present.
|
||||||
```
|
```
|
||||||
$ gradle buildNatives
|
gradle buildNatives
|
||||||
```
|
```
|
||||||
|
|
||||||
Manually compile sleigh files. Ghidra will also do this at runtime when necessary.
|
Manually compile sleigh files. Ghidra will also do this at runtime when necessary.
|
||||||
```
|
```
|
||||||
$ gradle sleighCompile
|
gradle sleighCompile
|
||||||
```
|
```
|
||||||
|
|
||||||
Build Javadoc:
|
Build Javadoc:
|
||||||
```
|
```
|
||||||
$ gradle createJavadocs
|
gradle createJavadocs
|
||||||
```
|
```
|
||||||
|
|
||||||
Build Ghidra to `build/dist`. This will be a distribution intended only to run on the platform on
|
Build Python3 packages for the Debugger:
|
||||||
which it was built.
|
|
||||||
```
|
```
|
||||||
$ gradle buildGhidra
|
gradle buildPyPackage
|
||||||
|
```
|
||||||
|
|
||||||
|
Build Ghidra to `build/dist` in an uncompressed form. This will be a distribution intended only to
|
||||||
|
run on the platform on which it was built.
|
||||||
|
```
|
||||||
|
gradle assembleAll
|
||||||
|
```
|
||||||
|
|
||||||
|
Build Ghidra to `build/dist` in a compressed form. This will be a distribution intended only to run
|
||||||
|
on the platform on which it was built.
|
||||||
|
```
|
||||||
|
gradle buildGhidra
|
||||||
```
|
```
|
||||||
|
|
||||||
**Tip:** You may want to skip certain Gradle tasks to speed up your build, or to deal with
|
**Tip:** You may want to skip certain Gradle tasks to speed up your build, or to deal with
|
||||||
|
@ -73,7 +84,7 @@ a problem later. For example, perhaps you added some new source files and the b
|
||||||
because of unresolved IP header issues. You can use the Gradle `-x <task>` command line argument to
|
because of unresolved IP header issues. You can use the Gradle `-x <task>` command line argument to
|
||||||
prevent specific tasks from running:
|
prevent specific tasks from running:
|
||||||
```
|
```
|
||||||
$ gradle buildGhidra -x ip
|
gradle buildGhidra -x ip
|
||||||
```
|
```
|
||||||
|
|
||||||
## Known Issues
|
## Known Issues
|
||||||
|
@ -86,7 +97,7 @@ Sometimes you may want to move the Ghidra repository to an offline network and d
|
||||||
These are the recommended steps to ensure that you not only move the source repository, but all
|
These are the recommended steps to ensure that you not only move the source repository, but all
|
||||||
downloaded dependencies as well:
|
downloaded dependencies as well:
|
||||||
|
|
||||||
1. `gradle -I gradle/support/fetchDependencies.gradle init`
|
1. `gradle -I gradle/support/fetchDependencies.gradle`
|
||||||
2. `gradle -g dependencies/gradle prepdev`
|
2. `gradle -g dependencies/gradle prepdev`
|
||||||
3. Move ghidra directory to different system
|
3. Move ghidra directory to different system
|
||||||
4. `gradle -g dependencies/gradle buildGhidra` (on offline system)
|
4. `gradle -g dependencies/gradle buildGhidra` (on offline system)
|
||||||
|
@ -103,7 +114,7 @@ It is also included in the _Eclipse IDE for RCP and RAP Developers_. To generate
|
||||||
Eclipse projects, execute:
|
Eclipse projects, execute:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ gradle eclipse -PeclipsePDE
|
gradle eclipse -PeclipsePDE
|
||||||
```
|
```
|
||||||
|
|
||||||
Import the newly generated GhidraDev projects into an Eclipse that supports this type of project.
|
Import the newly generated GhidraDev projects into an Eclipse that supports this type of project.
|
||||||
|
@ -111,31 +122,31 @@ Import the newly generated GhidraDev projects into an Eclipse that supports this
|
||||||
__Note:__ If you are getting compilation errors related to PyDev and CDT, go into Eclipse's
|
__Note:__ If you are getting compilation errors related to PyDev and CDT, go into Eclipse's
|
||||||
preferences, and under _Target Platform_, activate _/Eclipse GhidraDevPlugin/GhidraDev.target_.
|
preferences, and under _Target Platform_, activate _/Eclipse GhidraDevPlugin/GhidraDev.target_.
|
||||||
|
|
||||||
See [GhidraDevPlugin/build_README.txt](GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/build_README.txt)
|
See [Building GhidraDev](GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/README.md#building)
|
||||||
for instructions on how to build the GhidraDev plugin.
|
for instructions on how to build the GhidraDev plugin.
|
||||||
|
|
||||||
## Running tests
|
## Running tests
|
||||||
To run unit tests, do:
|
To run unit tests, do:
|
||||||
```
|
```
|
||||||
$ gradle unitTestReport
|
gradle unitTestReport
|
||||||
```
|
```
|
||||||
|
|
||||||
For more complex integration tests, do:
|
For more complex integration tests, do:
|
||||||
```
|
```
|
||||||
$ gradle integrationTest
|
gradle integrationTest
|
||||||
```
|
```
|
||||||
|
|
||||||
For running both unit and integration tests and to generate a report do:
|
For running both unit and integration tests and to generate a report do:
|
||||||
```
|
```
|
||||||
$ gradle combinedTestReport
|
gradle combinedTestReport
|
||||||
```
|
```
|
||||||
|
|
||||||
## Setup build in CI
|
## Setup build in CI
|
||||||
|
|
||||||
For running tests in headless mode on Linux, in a CI environment, or in Docker, first do:
|
For running tests in headless mode on Linux, in a CI environment, or in Docker, first do:
|
||||||
```
|
```
|
||||||
$ Xvfb :99 -nolisten tcp &
|
Xvfb :99 -nolisten tcp &
|
||||||
$ export DISPLAY=:99
|
export DISPLAY=:99
|
||||||
```
|
```
|
||||||
This is required to make AWT happy.
|
This is required to make AWT happy.
|
||||||
|
|
||||||
|
@ -176,13 +187,18 @@ If you'd like some details of our fine tuning, take a look at [building_fid.txt]
|
||||||
|
|
||||||
## Debugger Development
|
## Debugger Development
|
||||||
|
|
||||||
|
We have recently changed the Debugger's back-end architecture.
|
||||||
|
We no longer user JNA to access native Debugger APIs.
|
||||||
|
We only use it for pseudo-terminal access.
|
||||||
|
Instead, we use Python3 and a protobuf-based TCP connection for back-end integration.
|
||||||
|
|
||||||
### Additional Dependencies
|
### Additional Dependencies
|
||||||
|
|
||||||
In addition to Ghidra's normal dependencies, you may want the following:
|
In addition to Ghidra's normal dependencies, you may want the following:
|
||||||
|
|
||||||
* WinDbg for Windows x64
|
* WinDbg for Windows x64
|
||||||
* GDB 8.0 or later for Linux amd64/x86_64
|
* GDB 13 or later for Linux
|
||||||
* LLDB 13.0 for macOS
|
* LLDB 10 or later for macOS
|
||||||
|
|
||||||
The others (e.g., JNA) are handled by Gradle via Maven Central.
|
The others (e.g., JNA) are handled by Gradle via Maven Central.
|
||||||
|
|
||||||
|
@ -193,121 +209,137 @@ These all currently reside in the `Ghidra/Debug` directory, but will likely be r
|
||||||
`Framework` and `Feature` directories later. Each project is listed "bottom up" with a brief
|
`Framework` and `Feature` directories later. Each project is listed "bottom up" with a brief
|
||||||
description and status.
|
description and status.
|
||||||
|
|
||||||
* ProposedUtils - a collection of utilities proposed to be moved to other respective projects
|
* ProposedUtils - a collection of utilities proposed to be moved to other respective projects.
|
||||||
* AnnotationValidator - an experimental annotation processor for database access objects
|
* AnnotationValidator - an experimental annotation processor for database access objects.
|
||||||
* Framework-TraceModeling - a database schema and set of interfaces for storing machine state over
|
* Framework-TraceModeling - a database schema and set of interfaces for storing machine state over
|
||||||
time
|
time.
|
||||||
* Framework-AsyncComm - a collection of utilities for asynchronous communication (packet formats
|
* Framework-AsyncComm - a collection of utilities for asynchronous communication (packet formats
|
||||||
and completable-future conveniences).
|
and completable-future conveniences).
|
||||||
* Framework-Debugging - specifies interfaces for debugger models and provides implementation
|
* Framework-Debugging - specifies interfaces for debugger models and provides implementation
|
||||||
conveniences.
|
conveniences. This is mostly deprecated.
|
||||||
* Debugger - the collection of Ghidra plugins and services comprising the Debugger UI.
|
* Debugger - the collection of Ghidra plugins and services comprising the Debugger UI.
|
||||||
|
* Debugger-rmi-trace - the wire protocol, client, services, and UI components for Trace RMI, the new back-end architecture.
|
||||||
* Debugger-agent-dbgeng - the connector for WinDbg (via dbgeng.dll) on Windows x64.
|
* Debugger-agent-dbgeng - the connector for WinDbg (via dbgeng.dll) on Windows x64.
|
||||||
* Debugger-agent-dbgmodel - an experimental connector for WinDbg Preview (with TTD, via
|
* Debugger-agent-dbgmodel - an experimental connector for WinDbg Preview (with TTD, via
|
||||||
dbgmodel.dll) on Windows x64.
|
dbgmodel.dll) on Windows x64. This is deprecated, as most of these features are implemented in Debugger-agent-dbgeng for the new architecture.
|
||||||
* Debugger-agent-dbgmodel-traceloader - an experimental "importer" for WinDbg trace files.
|
* Debugger-agent-dbgmodel-traceloader - an experimental "importer" for WinDbg trace files. This is deprecated.
|
||||||
* Debugger-agent-gdb - the connector for GDB (8.0 or later recommended) on UNIX.
|
* Debugger-agent-gdb - the connector for GDB (13 or later recommended) on UNIX.
|
||||||
* Debugger-swig-lldb - the Java language bindings for LLDB's SBDebugger, also proposed upstream.
|
* Debugger-swig-lldb - the Java language bindings for LLDB's SBDebugger, also proposed upstream. This is deprecated. We now use the Python3 language bindings for LLDB.
|
||||||
* Debugger-agent-lldb - the connector for LLDB (13.0 required) on macOS, UNIX, and Windows.
|
* Debugger-agent-lldb - the connector for LLDB (10 or later recommended) on macOS, UNIX, and Windows.
|
||||||
* Debugger-gadp - the connector for our custom wire protocol the Ghidra Asynchronous Debugging
|
* Debugger-gadp - the connector for our custom wire protocol the Ghidra Asynchronous Debugging
|
||||||
Protocol.
|
Protocol. This is deprecated. It's replaced by Debugger-rmi-trace.
|
||||||
* Debugger-jpda - an in-development connector for Java and Dalvik debugging via JDI (i.e., JDWP).
|
* Debugger-jpda - an in-development connector for Java and Dalvik debugging via JDI (i.e., JDWP). This is deprecated and not yet replaced.
|
||||||
|
|
||||||
The Trace Modeling schema records machine state and markup over time.
|
The Trace Modeling schema records machine state and markup over time.
|
||||||
It rests on the same database framework as Programs, allowing trace recordings to be stored in a
|
It rests on the same database framework as Programs, allowing trace recordings to be stored in a Ghidra project and shared via a server, if desired.
|
||||||
Ghidra project and shared via a server, if desired. Trace "recording" is a de facto requirement for
|
Trace "recording" is a de facto requirement for displaying information in Ghidra's UI.
|
||||||
displaying information in Ghidra's UI. However, only the machine state actually observed by the user
|
The back-end connector has full discretion over what is recorded by using Trace RMI.
|
||||||
(or perhaps a script) is recorded. For most use cases, the Trace is small and ephemeral, serving
|
Typically, only the machine state actually observed by the user (or perhaps a script) is recorded.
|
||||||
only to mediate between the UI components and the target's model. It supports many of the same
|
For most use cases, the Trace is small and ephemeral, serving only to mediate between the UI components and the target's model.
|
||||||
markup (e.g., disassembly, data types) as Programs, in addition to tracking active threads, loaded
|
It supports many of the same markup (e.g., disassembly, data types) as Programs, in addition to tracking active threads, loaded modues, breakpoints, etc.
|
||||||
modues, breakpoints, etc.
|
|
||||||
|
|
||||||
Every model (or "adapter" or "connector" or "agent") implements the API specified in
|
Every back end (or "adapter" or "connector" or "agent") employs the Trace RMI client to populate a trace database.
|
||||||
Framework-Debugging. As a general rule in Ghidra, no component is allowed to access a native API and
|
As a general rule in Ghidra, no component is allowed to access a native API and reside in the same JVM as the Ghidra UI.
|
||||||
reside in the same JVM as the Ghidra UI. This allows us to contain crashes, preventing data loss. To
|
This allows us to contain crashes, preventing data loss.
|
||||||
accommodate this requirement -- given that debugging native applications is almost certainly going
|
To accommodate this requirement — given that debugging native applications is almost certainly going to require access to native APIs — we've developed the Trace RMI protocol.
|
||||||
to require access to native APIs -- we've developed the Ghidra Asynchronous Debugging Protocol. This
|
This also allows us to better bridge the language gap between Java and Python, which is supported by most native debuggers.
|
||||||
protocol is tightly coupled to Framework-Debugging, essentially exposing its methods via RMI. The
|
This protocol is loosely coupled to Framework-TraceModeling, essentially exposing its methods via RMI, as well as some methods for controlling the UI.
|
||||||
protocol is built using Google's Protobuf library, providing a potential path for agent
|
The protocol is built using Google's Protobuf library, providing a potential path for back-end implementations in alternative languages.
|
||||||
implementations in alternative languages. GADP provides both a server and a client implementation.
|
We provide the Trace RMI server as a Ghidra component implemented in Java and the Trace RMI client as a Python3 package.
|
||||||
The server can accept any model which adheres to the specification and expose it via TCP; the client
|
A back-end implementation may be a stand-alone executable or script that accesses the native debugger's API, or a script or plugin for the native debugger.
|
||||||
does the converse. When a model is instantiated in this way, it is called an "agent," because it is
|
It then connects to Ghidra via Trace RMI to populate the trace database with information gleaned from that API.
|
||||||
executing in its own JVM. The other connectors, which do not use native APIs, may reside in Ghidra's
|
It should provide a set of diagnostic commands to control and monitor that connection.
|
||||||
JVM and typically implement alternative wire protocols, e.g., JDWP. In both cases, the
|
It should also use the native API to detect session and target changes so that Ghidra's UI consistently reflects the debugging session.
|
||||||
implementations inherit from the same interfaces.
|
|
||||||
|
|
||||||
The Debugger services maintain a collection of active connections and inspect each model for
|
The old system relied on a "recorder" to discover targets and map them to traces in the proper Ghidra language.
|
||||||
potential targets. When a target is found, the service inspects the target environment and attempts
|
That responsibility is now delegated to the back end.
|
||||||
to find a suitable opinion. Such an opinion, if found, instructs Ghidra how to map the objects,
|
Typically, it examines the target's architecture and immediately creates a trace upon connection.
|
||||||
addresses, registers, etc. from the target namespace into Ghidra's. The target is then handed to a
|
|
||||||
Trace Recorder which begins collecting information needed to populate the UI, e.g., the program
|
|
||||||
counter, stack pointer, and the bytes of memory they refer to.
|
|
||||||
|
|
||||||
### Developing a new connector
|
### Developing a new connector
|
||||||
|
|
||||||
So Ghidra does not yet support your favorite debugger?
|
So Ghidra does not yet support your favorite debugger?
|
||||||
It is tempting, exciting, but also daunting to develop your own connector.
|
We believe the new system is much less daunting than the previous.
|
||||||
Please finish reading this guide, and look carefully at the ones we have so far, and perhaps ask to
|
Still, please finish reading this guide, and look carefully at the ones we have so far, and perhaps ask to see if we are already developing one.
|
||||||
see if we are already developing one. Of course, in time you might also search the internet to see
|
Of course, in time you might also search the internet to see if others are developing one.
|
||||||
if others are developing one. There are quite a few caveats and gotchas, the most notable being that
|
There are quite a few caveats and gotchas, the most notable being that this interface is still in some flux.
|
||||||
this interface is still in quite a bit of flux. When things go wrong, it could be because of,
|
When things go wrong, it could be because of, without limitation:
|
||||||
without limitation: 1) a bug on your part, 2) a bug on our part, 3) a design flaw in the interfaces,
|
|
||||||
or 4) a bug in the debugger/API you're adapting. We are still in the process of writing up this
|
|
||||||
documentation. In the meantime, we recommend using the GDB and dbgeng.dll agents as examples.
|
|
||||||
|
|
||||||
You'll also need to provide launcher(s) so that Ghidra knows how to configure and start your
|
1. A bug on your part
|
||||||
connector. Please provide launchers for your model in both configurations: as a connector in
|
2. A bug on our part
|
||||||
Ghidra's JVM, and as a GADP agent. If your model requires native API access, you should only permit
|
3. A design flaw in the interfaces
|
||||||
launching it as a GADP agent, unless you give ample warning in the launcher's description. Look at
|
4. A bug in the debugger/API you're adapting
|
||||||
the existing launchers for examples. There are many model implementation requirements that cannot be
|
|
||||||
expressed in Java interfaces. Failing to adhere to those requirements may cause different behaviors
|
We are still (yes, still) in the process of writing up this documentation.
|
||||||
with and without GADP. Testing with GADP tends to reveal those implementation errors, but also
|
In the meantime, we recommend using the GDB and dbgeng agents as examples.
|
||||||
obscures the source of client method calls behind network messages. We've also codified (or
|
Be sure to look at the Python code `src/main/py`!
|
||||||
attempted to codify) these requirements in a suite of abstract test cases. See the `ghidra.dbg.test`
|
The deprecated Java code `src/main/java` is still included as we transition.
|
||||||
package of Framework-Debugging, and again, look at existing implementations.
|
|
||||||
|
You'll also need to provide launcher(s) so that Ghidra knows how to configure and start your connector.
|
||||||
|
These are just shell scripts.
|
||||||
|
We use bash scripts on Linux and macOS, and we use batch files on Windows.
|
||||||
|
Try to include as many common use cases as makes sense for the debugger.
|
||||||
|
This provides the most flexibility to users and examples to power users who might create derivative launchers.
|
||||||
|
Look at the existing launchers for examples.
|
||||||
|
|
||||||
|
For testing, please follow the examples for GDB.
|
||||||
|
We no longer provide abstract classes that prescribe requirements.
|
||||||
|
Instead, we just provide GDB as an example.
|
||||||
|
Usually, we split our tests into three categories:
|
||||||
|
|
||||||
|
* Commands
|
||||||
|
* Methods
|
||||||
|
* Hooks
|
||||||
|
|
||||||
|
The Commands tests check that the user CLI commands, conventionally implemented in `commands.py`, work correctly.
|
||||||
|
In general, do the minimum connection setup, execute the command, and check that it produces the expected output and causes the expected effects.
|
||||||
|
|
||||||
|
The Methods tests check that the remote methods, conventionally implemented in `methods.py`, work correctly.
|
||||||
|
Many methods are just wrappers around CLI commands, some provided by the native debugger and some provided by `commands.py`.
|
||||||
|
These work similarly to the commands test, except that they invoke methods instead of executing commands.
|
||||||
|
Again, check the return value (rarely applicable) and that it causes the expected effects.
|
||||||
|
|
||||||
|
The Hooks tests check that the back end is able to listen for session and target changes, e.g., knowing when the target stops.
|
||||||
|
*The test should not "cheat" by executing commands or invoking methods that should instead be triggered by the listener.*
|
||||||
|
It should execute the minimal commands to setup the test, then trigger an event.
|
||||||
|
It should then check that the event in turn triggered the expected effects, e.g., updating PC upon the target stopping.
|
||||||
|
|
||||||
|
Whenever you make a change to the Python code, you'll need to re-assemble the package's source.
|
||||||
|
|
||||||
|
```
|
||||||
|
gradle assemblePyPackage
|
||||||
|
```
|
||||||
|
|
||||||
|
This is required in case your package includes generated source, as is the case for Debugger-rmi-trace.
|
||||||
|
If you want to create a new Ghidra module for your connector (recommended) use an existing one's `build.gradle` as a template.
|
||||||
|
A key part is applying the `hasPythonPackage.gradle` script.
|
||||||
|
|
||||||
### Adding a new platform
|
### Adding a new platform
|
||||||
|
|
||||||
If an existing connector exists for a suitable debugger on the desired platform, then adding it may
|
If a connector already exists for a suitable debugger on the desired platform, then adding it may be very simple.
|
||||||
be very simple. For example, both the x86 and ARM platforms are supported by GDB, so even though
|
For example, many platforms are supported by GDB, so even though we're currently focused on x86-64 (and to some extent arm64) support, we've provided the mappings for many.
|
||||||
we're currently focused on x86 support, we've provided the opinions needed for Ghidra to debug ARM
|
These mappings are conventionally kept in each connector's `arch.py` file.
|
||||||
platforms (and several others) via GDB. These opinions are kept in the "Debugger" project, not their
|
|
||||||
respective "agent" projects. We imagine there are a number of platforms that could be supported
|
|
||||||
almost out of the box, except that we haven't written the necessary opinions, yet. Take a look at
|
|
||||||
the existing ones for examples.
|
|
||||||
|
|
||||||
In general, to write a new opinion, you need to know: 1) What the platform is called (including
|
In general, to update `arch.py`, you need to know:
|
||||||
variant names) by the debugger, 2) What the processor language is called by Ghidra, 3) If
|
|
||||||
applicable, the mapping of target address spaces into Ghidra's address spaces, 4) If applicable, the
|
1. What the platform is called (including variant names) by the debugger
|
||||||
mapping of target register names to those in Ghidra's processor language. In most cases (3) and (4)
|
2. What the processor language is called by Ghidra
|
||||||
are already implemented by default mappers, so you can use those same mappers in your opinion. Once
|
3. If applicable, the mapping of target address spaces into Ghidra's address spaces
|
||||||
you have the opinion written, you can try debugging and recording a target. If Ghidra finds your
|
4. If applicable, the mapping of target register names to those in Ghidra's processor language
|
||||||
opinion applicable to that target, it will attempt to record, and then you can work out the kinds
|
|
||||||
from there. Again, we have a bit of documentation to do regarding common pitfalls.
|
In most cases (3) and (4) are already implemented by the included mappers.
|
||||||
|
Naturally, you'll want to test the special cases, preferably in automated tests.
|
||||||
|
|
||||||
### Emulation
|
### Emulation
|
||||||
|
|
||||||
The most obvious integration path for 3rd-party emulators is to write a "connector." However, p-code
|
The most obvious integration path for 3rd-party emulators is to write a "connector."
|
||||||
emulation is now an integral feature of the Ghidra UI, and it has a fairly accessible API. Namely,
|
However, p-code emulation is an integral feature of the Ghidra UI, and it has a fairly accessible API.
|
||||||
for interpolation between machines states recorded in a trace, and extrapolation into future machine
|
Namely, for interpolation between machines states recorded in a trace, and extrapolation into future machine states.
|
||||||
states. Integration of such emulators may still be useful to you, but we recommend trying the p-code
|
Integration of such emulators may still be useful to you, but we recommend trying the p-code emulator to see if it suits your needs for emulation in Ghidra before pursuing integration of another emulator.
|
||||||
emulator to see if it suits your needs for emulation in Ghidra before pursuing integration of
|
We also provide out-of-the-box QEMU integration via GDB.
|
||||||
another emulator.
|
|
||||||
|
|
||||||
### Contributing
|
### Contributing
|
||||||
|
|
||||||
Whether submitting help tickets and pull requests, please tag those related to the debugger with
|
When submitting help tickets and pull requests, please tag those related to the debugger with "Debugger" so that we can triage them more quickly.
|
||||||
"Debugger" so that we can triage them more quickly.
|
|
||||||
|
|
||||||
To set up your environment, in addition to the usual Gradle tasks, process the Protobuf
|
|
||||||
specification for GADP:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ gradle generateProto
|
|
||||||
```
|
|
||||||
|
|
||||||
If you already have an environment set up in Eclipse, please re-run `gradle prepDev eclipse` and
|
|
||||||
import the new projects.
|
|
||||||
|
|
||||||
|
|
||||||
[java]: https://dev.java
|
[java]: https://dev.java
|
||||||
|
|
1
GPL/DMG/README.md
Normal file
1
GPL/DMG/README.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# DMG
|
|
@ -3,6 +3,7 @@
|
||||||
##MODULE IP: LGPL 2.1
|
##MODULE IP: LGPL 2.1
|
||||||
##MODULE IP: Public Domain
|
##MODULE IP: Public Domain
|
||||||
Module.manifest||Public Domain||||END|
|
Module.manifest||Public Domain||||END|
|
||||||
|
README.md||GHIDRA||||END|
|
||||||
data/lib/csframework.jar||LGPL 2.1||||END|
|
data/lib/csframework.jar||LGPL 2.1||||END|
|
||||||
data/lib/hfsexplorer-0_21-src.zip||GPL 3||||END|
|
data/lib/hfsexplorer-0_21-src.zip||GPL 3||||END|
|
||||||
data/lib/hfsx.jar||GPL 3||||END|
|
data/lib/hfsx.jar||GPL 3||||END|
|
||||||
|
|
1
GPL/DemanglerGnu/README.md
Normal file
1
GPL/DemanglerGnu/README.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# DemanglerGnu
|
|
@ -17,9 +17,9 @@ apply plugin: 'eclipse'
|
||||||
eclipse.project.name = 'GPL DemanglerGnu'
|
eclipse.project.name = 'GPL DemanglerGnu'
|
||||||
|
|
||||||
|
|
||||||
def v33_1 = "demangler_gnu_v2_33_1"
|
def v41 = "demangler_gnu_v2_41"
|
||||||
def v24 = "demangler_gnu_v2_24"
|
def v24 = "demangler_gnu_v2_24"
|
||||||
def srcVersion33_1 = "src/demangler_gnu_v2_33_1"
|
def srcVersion41 = "src/demangler_gnu_v2_41"
|
||||||
def srcVersion24 = "src/demangler_gnu_v2_24"
|
def srcVersion24 = "src/demangler_gnu_v2_24"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,19 +41,18 @@ task zipBuildableSource(type:Zip) {
|
||||||
archiveExtension = 'zip'
|
archiveExtension = 'zip'
|
||||||
|
|
||||||
//
|
//
|
||||||
// Version 2.33.1
|
// Version 2.41
|
||||||
//
|
//
|
||||||
from (project.projectDir.toString() + "/" + srcVersion33_1 + "c") {
|
from (project.projectDir.toString() + "/" + srcVersion41 + "c") {
|
||||||
into "/" + srcVersion33_1
|
into "/" + srcVersion41
|
||||||
}
|
}
|
||||||
from (project.projectDir.toString() + "/" + srcVersion33_1 + "/headers") {
|
from (project.projectDir.toString() + "/" + srcVersion41 + "/headers") {
|
||||||
into "/" + srcVersion33_1
|
into "/" + srcVersion41
|
||||||
}
|
}
|
||||||
from (project.projectDir.toString() + "/" + srcVersion33_1 + "/build") {
|
from (project.projectDir.toString() + "/" + srcVersion41 + "/build") {
|
||||||
into "/" + srcVersion33_1
|
into "/" + srcVersion41
|
||||||
}
|
}
|
||||||
from (project.projectDir.toString() + "/" + srcVersion33_1 + "/README.txt")
|
from (project.projectDir.toString() + "/" + srcVersion41 + "/README.txt")
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Version 2.24
|
// Version 2.24
|
||||||
|
@ -72,23 +71,25 @@ task zipBuildableSource(type:Zip) {
|
||||||
|
|
||||||
model {
|
model {
|
||||||
|
|
||||||
//
|
|
||||||
// Version 2.33.1
|
|
||||||
//
|
|
||||||
components {
|
components {
|
||||||
demangler_gnu_v2_33_1(NativeExecutableSpec) {
|
//
|
||||||
|
// Version 2.41
|
||||||
|
//
|
||||||
|
demangler_gnu_v2_41(NativeExecutableSpec) {
|
||||||
targetPlatform "win_x86_64"
|
targetPlatform "win_x86_64"
|
||||||
targetPlatform "linux_x86_64"
|
targetPlatform "linux_x86_64"
|
||||||
targetPlatform "linux_arm_64"
|
targetPlatform "linux_arm_64"
|
||||||
targetPlatform "mac_x86_64"
|
targetPlatform "mac_x86_64"
|
||||||
targetPlatform "mac_arm_64"
|
targetPlatform "mac_arm_64"
|
||||||
|
targetPlatform "freebsd_x86_64"
|
||||||
|
targetPlatform "freebsd_arm_64"
|
||||||
sources {
|
sources {
|
||||||
c {
|
c {
|
||||||
source {
|
source {
|
||||||
srcDir srcVersion33_1 + "/c"
|
srcDir srcVersion41 + "/c"
|
||||||
}
|
}
|
||||||
exportedHeaders {
|
exportedHeaders {
|
||||||
srcDir srcVersion33_1 + "/headers"
|
srcDir srcVersion41 + "/headers"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,6 +104,8 @@ model {
|
||||||
targetPlatform "linux_arm_64"
|
targetPlatform "linux_arm_64"
|
||||||
targetPlatform "mac_x86_64"
|
targetPlatform "mac_x86_64"
|
||||||
targetPlatform "mac_arm_64"
|
targetPlatform "mac_arm_64"
|
||||||
|
targetPlatform "freebsd_x86_64"
|
||||||
|
targetPlatform "freebsd_arm_64"
|
||||||
sources {
|
sources {
|
||||||
c {
|
c {
|
||||||
source {
|
source {
|
||||||
|
@ -127,7 +130,7 @@ model {
|
||||||
|
|
||||||
def version = b.getApplication().getName()
|
def version = b.getApplication().getName()
|
||||||
|
|
||||||
if (version.equals(v33_1)) {
|
if (version.equals(v41)) {
|
||||||
if (toolChain in Gcc) {
|
if (toolChain in Gcc) {
|
||||||
//cCompiler.args "-DCP_DEMANGLE_DEBUG"
|
//cCompiler.args "-DCP_DEMANGLE_DEBUG"
|
||||||
cCompiler.args "-DHAVE_STDLIB_H"
|
cCompiler.args "-DHAVE_STDLIB_H"
|
||||||
|
|
|
@ -5,5 +5,5 @@
|
||||||
##MODULE IP: LGPL 3.0
|
##MODULE IP: LGPL 3.0
|
||||||
##MODULE IP: Public Domain
|
##MODULE IP: Public Domain
|
||||||
Module.manifest||Public Domain||||END|
|
Module.manifest||Public Domain||||END|
|
||||||
|
README.md||GHIDRA||||END|
|
||||||
src/demangler_gnu_v2_24/README.txt||Public Domain||||END|
|
src/demangler_gnu_v2_24/README.txt||Public Domain||||END|
|
||||||
src/demangler_gnu_v2_33_1/README.txt||Public Domain||||END|
|
|
||||||
|
|
|
@ -903,7 +903,7 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
|
||||||
goto unknown;
|
goto unknown;
|
||||||
|
|
||||||
/* Most of the demangling will trivially remove chars. Operator names
|
/* Most of the demangling will trivially remove chars. Operator names
|
||||||
may add one char but because they are always preceeded by '__' which is
|
may add one char but because they are always preceded by '__' which is
|
||||||
replaced by '.', they eventually never expand the size.
|
replaced by '.', they eventually never expand the size.
|
||||||
A few special names such as '___elabs' add a few chars (at most 7), but
|
A few special names such as '___elabs' add a few chars (at most 7), but
|
||||||
they occur only once. */
|
they occur only once. */
|
||||||
|
|
|
@ -1,81 +0,0 @@
|
||||||
PURPOSE
|
|
||||||
|
|
||||||
This is a readme file to note the changes made to the binutils-2.33.1 source
|
|
||||||
code in to build its GNU demangler. The files in this directory are used to create a demangling
|
|
||||||
utility during the full build process.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
COPIED SOURCE CODE / BUILDING RESTRICTIONS
|
|
||||||
|
|
||||||
Most of the files used to build the Ghidra GNU demangler are copied from binutils and have
|
|
||||||
not been changed. Further, the files in this directory are a small subset of the files used to
|
|
||||||
build the binutils suite. By copying specific files we are able to use Make and Visual Studio
|
|
||||||
to build a stand alone demangler without having to perform the more complicated build needed
|
|
||||||
to build binutils. Specifically, we do not have to run the configure utility that is
|
|
||||||
provided by binutils. This is critical, as we are using Visual Studio to build on Windows,
|
|
||||||
which does not have the configure utility support. If we ever wished to build the entire
|
|
||||||
binutils suite on Windows, then we would most likely need to use a GNU environment made for
|
|
||||||
Windows, such as MinGW.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CHANGES TO BINUTILS SOURCE
|
|
||||||
|
|
||||||
cp-demangle.c
|
|
||||||
|
|
||||||
This file contains a small, one-line change to flush to the standard output stream. Without
|
|
||||||
this change, the program, when called repeatedly from Java would hang as it attempts to read
|
|
||||||
characters that are buffered on the native side.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
UPDATING
|
|
||||||
|
|
||||||
If we ever wish to update to a newer version of binutils, then we will need to re-copy the files
|
|
||||||
in this directory. That is, unless at least one of the following changes happens:
|
|
||||||
|
|
||||||
1) building a stand alone c++filt is simple enough that we can do it on each platform, or
|
|
||||||
2) we decide to build the entire binutils suite and use the full c++filt binary.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SOURCE FILES
|
|
||||||
|
|
||||||
binutils/libiberty/alloca.c
|
|
||||||
binutils/libiberty/argv.c
|
|
||||||
binutils/libiberty/cp-demangle.c
|
|
||||||
binutils/libiberty/cplus-dem.c
|
|
||||||
binutils/libiberty/d-demangle.c
|
|
||||||
binutils/libiberty/dyn-string.c
|
|
||||||
binutils/libiberty/getopt.c
|
|
||||||
binutils/libiberty/getopt1.c
|
|
||||||
binutils/libiberty/rust-demangle.c
|
|
||||||
binutils/libiberty/safe-ctype.c
|
|
||||||
binutils/libiberty/xexit.c
|
|
||||||
binutils/libiberty/xstrdup.c
|
|
||||||
binutils/include/ansidecl.h
|
|
||||||
binutils/libiberty/cp-demangle.h
|
|
||||||
binutils/include/demangle.h
|
|
||||||
binutils/include/dyn-string.h
|
|
||||||
binutils/include/getopt.h
|
|
||||||
binutils/include/libiberty.h
|
|
||||||
binutils/libiberty/rust-demangle.h
|
|
||||||
binutils/include/safe-ctype.h
|
|
||||||
|
|
||||||
|
|
||||||
This file is created to add minor missing dependencies.
|
|
||||||
|
|
||||||
missing.c
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LICENSE
|
|
||||||
|
|
||||||
The files listed above are licensed by using the file header or the COPYING or COPYING.LIB file
|
|
||||||
listed in the original source directory of binutils.
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,353 +0,0 @@
|
||||||
/* ###
|
|
||||||
* IP: LGPL 2.1
|
|
||||||
* NOTE: See binutils/libiberty/COPYING.LIB
|
|
||||||
*/
|
|
||||||
/* Demangler for the Rust programming language
|
|
||||||
Copyright (C) 2016-2019 Free Software Foundation, Inc.
|
|
||||||
Written by David Tolnay (dtolnay@gmail.com).
|
|
||||||
|
|
||||||
This file is part of the libiberty library.
|
|
||||||
Libiberty is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Library General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
In addition to the permissions in the GNU Library General Public
|
|
||||||
License, the Free Software Foundation gives you unlimited permission
|
|
||||||
to link the compiled version of this file into combinations with other
|
|
||||||
programs, and to distribute those combinations without any restriction
|
|
||||||
coming from the use of this file. (The Library Public License
|
|
||||||
restrictions do apply in other respects; for example, they cover
|
|
||||||
modification of the file, and distribution when not linked into a
|
|
||||||
combined executable.)
|
|
||||||
|
|
||||||
Libiberty is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Library General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
|
||||||
License along with libiberty; see the file COPYING.LIB.
|
|
||||||
If not, see <http://www.gnu.org/licenses/>. */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "safe-ctype.h"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_STRING_H
|
|
||||||
#include <string.h>
|
|
||||||
#else
|
|
||||||
extern size_t strlen(const char *s);
|
|
||||||
extern int strncmp(const char *s1, const char *s2, size_t n);
|
|
||||||
extern void *memset(void *s, int c, size_t n);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <demangle.h>
|
|
||||||
#include "libiberty.h"
|
|
||||||
#include "rust-demangle.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* Mangled Rust symbols look like this:
|
|
||||||
_$LT$std..sys..fd..FileDesc$u20$as$u20$core..ops..Drop$GT$::drop::hc68340e1baa4987a
|
|
||||||
|
|
||||||
The original symbol is:
|
|
||||||
<std::sys::fd::FileDesc as core::ops::Drop>::drop
|
|
||||||
|
|
||||||
The last component of the path is a 64-bit hash in lowercase hex,
|
|
||||||
prefixed with "h". Rust does not have a global namespace between
|
|
||||||
crates, an illusion which Rust maintains by using the hash to
|
|
||||||
distinguish things that would otherwise have the same symbol.
|
|
||||||
|
|
||||||
Any path component not starting with a XID_Start character is
|
|
||||||
prefixed with "_".
|
|
||||||
|
|
||||||
The following escape sequences are used:
|
|
||||||
|
|
||||||
"," => $C$
|
|
||||||
"@" => $SP$
|
|
||||||
"*" => $BP$
|
|
||||||
"&" => $RF$
|
|
||||||
"<" => $LT$
|
|
||||||
">" => $GT$
|
|
||||||
"(" => $LP$
|
|
||||||
")" => $RP$
|
|
||||||
" " => $u20$
|
|
||||||
"\"" => $u22$
|
|
||||||
"'" => $u27$
|
|
||||||
"+" => $u2b$
|
|
||||||
";" => $u3b$
|
|
||||||
"[" => $u5b$
|
|
||||||
"]" => $u5d$
|
|
||||||
"{" => $u7b$
|
|
||||||
"}" => $u7d$
|
|
||||||
"~" => $u7e$
|
|
||||||
|
|
||||||
A double ".." means "::" and a single "." means "-".
|
|
||||||
|
|
||||||
The only characters allowed in the mangled symbol are a-zA-Z0-9 and _.:$ */
|
|
||||||
|
|
||||||
static const char *hash_prefix = "::h";
|
|
||||||
static const size_t hash_prefix_len = 3;
|
|
||||||
static const size_t hash_len = 16;
|
|
||||||
|
|
||||||
static int is_prefixed_hash (const char *start);
|
|
||||||
static int looks_like_rust (const char *sym, size_t len);
|
|
||||||
static int unescape (const char **in, char **out, const char *seq, char value);
|
|
||||||
|
|
||||||
/* INPUT: sym: symbol that has been through C++ (gnu v3) demangling
|
|
||||||
|
|
||||||
This function looks for the following indicators:
|
|
||||||
|
|
||||||
1. The hash must consist of "h" followed by 16 lowercase hex digits.
|
|
||||||
|
|
||||||
2. As a sanity check, the hash must use between 5 and 15 of the 16
|
|
||||||
possible hex digits. This is true of 99.9998% of hashes so once
|
|
||||||
in your life you may see a false negative. The point is to
|
|
||||||
notice path components that could be Rust hashes but are
|
|
||||||
probably not, like "haaaaaaaaaaaaaaaa". In this case a false
|
|
||||||
positive (non-Rust symbol has an important path component
|
|
||||||
removed because it looks like a Rust hash) is worse than a false
|
|
||||||
negative (the rare Rust symbol is not demangled) so this sets
|
|
||||||
the balance in favor of false negatives.
|
|
||||||
|
|
||||||
3. There must be no characters other than a-zA-Z0-9 and _.:$
|
|
||||||
|
|
||||||
4. There must be no unrecognized $-sign sequences.
|
|
||||||
|
|
||||||
5. There must be no sequence of three or more dots in a row ("..."). */
|
|
||||||
|
|
||||||
int
|
|
||||||
rust_is_mangled (const char *sym)
|
|
||||||
{
|
|
||||||
size_t len, len_without_hash;
|
|
||||||
|
|
||||||
if (!sym)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
len = strlen (sym);
|
|
||||||
if (len <= hash_prefix_len + hash_len)
|
|
||||||
/* Not long enough to contain "::h" + hash + something else */
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
len_without_hash = len - (hash_prefix_len + hash_len);
|
|
||||||
if (!is_prefixed_hash (sym + len_without_hash))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return looks_like_rust (sym, len_without_hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A hash is the prefix "::h" followed by 16 lowercase hex digits. The
|
|
||||||
hex digits must comprise between 5 and 15 (inclusive) distinct
|
|
||||||
digits. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
is_prefixed_hash (const char *str)
|
|
||||||
{
|
|
||||||
const char *end;
|
|
||||||
char seen[16];
|
|
||||||
size_t i;
|
|
||||||
int count;
|
|
||||||
|
|
||||||
if (strncmp (str, hash_prefix, hash_prefix_len))
|
|
||||||
return 0;
|
|
||||||
str += hash_prefix_len;
|
|
||||||
|
|
||||||
memset (seen, 0, sizeof(seen));
|
|
||||||
for (end = str + hash_len; str < end; str++)
|
|
||||||
if (*str >= '0' && *str <= '9')
|
|
||||||
seen[*str - '0'] = 1;
|
|
||||||
else if (*str >= 'a' && *str <= 'f')
|
|
||||||
seen[*str - 'a' + 10] = 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Count how many distinct digits seen */
|
|
||||||
count = 0;
|
|
||||||
for (i = 0; i < 16; i++)
|
|
||||||
if (seen[i])
|
|
||||||
count++;
|
|
||||||
|
|
||||||
return count >= 5 && count <= 15;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
looks_like_rust (const char *str, size_t len)
|
|
||||||
{
|
|
||||||
const char *end = str + len;
|
|
||||||
|
|
||||||
while (str < end)
|
|
||||||
switch (*str)
|
|
||||||
{
|
|
||||||
case '$':
|
|
||||||
if (!strncmp (str, "$C$", 3))
|
|
||||||
str += 3;
|
|
||||||
else if (!strncmp (str, "$SP$", 4)
|
|
||||||
|| !strncmp (str, "$BP$", 4)
|
|
||||||
|| !strncmp (str, "$RF$", 4)
|
|
||||||
|| !strncmp (str, "$LT$", 4)
|
|
||||||
|| !strncmp (str, "$GT$", 4)
|
|
||||||
|| !strncmp (str, "$LP$", 4)
|
|
||||||
|| !strncmp (str, "$RP$", 4))
|
|
||||||
str += 4;
|
|
||||||
else if (!strncmp (str, "$u20$", 5)
|
|
||||||
|| !strncmp (str, "$u22$", 5)
|
|
||||||
|| !strncmp (str, "$u27$", 5)
|
|
||||||
|| !strncmp (str, "$u2b$", 5)
|
|
||||||
|| !strncmp (str, "$u3b$", 5)
|
|
||||||
|| !strncmp (str, "$u5b$", 5)
|
|
||||||
|| !strncmp (str, "$u5d$", 5)
|
|
||||||
|| !strncmp (str, "$u7b$", 5)
|
|
||||||
|| !strncmp (str, "$u7d$", 5)
|
|
||||||
|| !strncmp (str, "$u7e$", 5))
|
|
||||||
str += 5;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
case '.':
|
|
||||||
/* Do not allow three or more consecutive dots */
|
|
||||||
if (!strncmp (str, "...", 3))
|
|
||||||
return 0;
|
|
||||||
/* Fall through */
|
|
||||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
|
||||||
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
|
|
||||||
case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
|
|
||||||
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
|
||||||
case 'y': case 'z':
|
|
||||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
|
||||||
case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
|
|
||||||
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
|
|
||||||
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
|
|
||||||
case 'Y': case 'Z':
|
|
||||||
case '0': case '1': case '2': case '3': case '4': case '5':
|
|
||||||
case '6': case '7': case '8': case '9':
|
|
||||||
case '_':
|
|
||||||
case ':':
|
|
||||||
str++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
INPUT: sym: symbol for which rust_is_mangled(sym) returned 1.
|
|
||||||
|
|
||||||
The input is demangled in-place because the mangled name is always
|
|
||||||
longer than the demangled one. */
|
|
||||||
|
|
||||||
void
|
|
||||||
rust_demangle_sym (char *sym)
|
|
||||||
{
|
|
||||||
const char *in;
|
|
||||||
char *out;
|
|
||||||
const char *end;
|
|
||||||
|
|
||||||
if (!sym)
|
|
||||||
return;
|
|
||||||
|
|
||||||
in = sym;
|
|
||||||
out = sym;
|
|
||||||
end = sym + strlen (sym) - (hash_prefix_len + hash_len);
|
|
||||||
|
|
||||||
while (in < end)
|
|
||||||
switch (*in)
|
|
||||||
{
|
|
||||||
case '$':
|
|
||||||
if (!(unescape (&in, &out, "$C$", ',')
|
|
||||||
|| unescape (&in, &out, "$SP$", '@')
|
|
||||||
|| unescape (&in, &out, "$BP$", '*')
|
|
||||||
|| unescape (&in, &out, "$RF$", '&')
|
|
||||||
|| unescape (&in, &out, "$LT$", '<')
|
|
||||||
|| unescape (&in, &out, "$GT$", '>')
|
|
||||||
|| unescape (&in, &out, "$LP$", '(')
|
|
||||||
|| unescape (&in, &out, "$RP$", ')')
|
|
||||||
|| unescape (&in, &out, "$u20$", ' ')
|
|
||||||
|| unescape (&in, &out, "$u22$", '\"')
|
|
||||||
|| unescape (&in, &out, "$u27$", '\'')
|
|
||||||
|| unescape (&in, &out, "$u2b$", '+')
|
|
||||||
|| unescape (&in, &out, "$u3b$", ';')
|
|
||||||
|| unescape (&in, &out, "$u5b$", '[')
|
|
||||||
|| unescape (&in, &out, "$u5d$", ']')
|
|
||||||
|| unescape (&in, &out, "$u7b$", '{')
|
|
||||||
|| unescape (&in, &out, "$u7d$", '}')
|
|
||||||
|| unescape (&in, &out, "$u7e$", '~'))) {
|
|
||||||
/* unexpected escape sequence, not looks_like_rust. */
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '_':
|
|
||||||
/* If this is the start of a path component and the next
|
|
||||||
character is an escape sequence, ignore the underscore. The
|
|
||||||
mangler inserts an underscore to make sure the path
|
|
||||||
component begins with a XID_Start character. */
|
|
||||||
if ((in == sym || in[-1] == ':') && in[1] == '$')
|
|
||||||
in++;
|
|
||||||
else
|
|
||||||
*out++ = *in++;
|
|
||||||
break;
|
|
||||||
case '.':
|
|
||||||
if (in[1] == '.')
|
|
||||||
{
|
|
||||||
/* ".." becomes "::" */
|
|
||||||
*out++ = ':';
|
|
||||||
*out++ = ':';
|
|
||||||
in += 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* "." becomes "-" */
|
|
||||||
*out++ = '-';
|
|
||||||
in++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
|
||||||
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
|
|
||||||
case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
|
|
||||||
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
|
|
||||||
case 'y': case 'z':
|
|
||||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
|
||||||
case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
|
|
||||||
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
|
|
||||||
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
|
|
||||||
case 'Y': case 'Z':
|
|
||||||
case '0': case '1': case '2': case '3': case '4': case '5':
|
|
||||||
case '6': case '7': case '8': case '9':
|
|
||||||
case ':':
|
|
||||||
*out++ = *in++;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* unexpected character in symbol, not looks_like_rust. */
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
*out++ = '?'; /* This is pretty lame, but it's hard to do better. */
|
|
||||||
done:
|
|
||||||
*out = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
unescape (const char **in, char **out, const char *seq, char value)
|
|
||||||
{
|
|
||||||
size_t len = strlen (seq);
|
|
||||||
|
|
||||||
if (strncmp (*in, seq, len))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
**out = value;
|
|
||||||
|
|
||||||
*in += len;
|
|
||||||
*out += 1;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
/* ###
|
|
||||||
* IP: LGPL 2.1
|
|
||||||
* NOTE: See binutils/libiberty/COPYING.LIB
|
|
||||||
*/
|
|
||||||
/* Internal demangler interface for the Rust programming language.
|
|
||||||
Copyright (C) 2016-2019 Free Software Foundation, Inc.
|
|
||||||
Written by David Tolnay (dtolnay@gmail.com).
|
|
||||||
|
|
||||||
This file is part of the libiberty library.
|
|
||||||
Libiberty is free software; you can redistribute it and/or
|
|
||||||
modify it under the terms of the GNU Library General Public
|
|
||||||
License as published by the Free Software Foundation; either
|
|
||||||
version 2 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
In addition to the permissions in the GNU Library General Public
|
|
||||||
License, the Free Software Foundation gives you unlimited permission
|
|
||||||
to link the compiled version of this file into combinations with other
|
|
||||||
programs, and to distribute those combinations without any restriction
|
|
||||||
coming from the use of this file. (The Library Public License
|
|
||||||
restrictions do apply in other respects; for example, they cover
|
|
||||||
modification of the file, and distribution when not linked into a
|
|
||||||
combined executable.)
|
|
||||||
|
|
||||||
Libiberty is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
Library General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Library General Public
|
|
||||||
License along with libiberty; see the file COPYING.LIB.
|
|
||||||
If not, see <http://www.gnu.org/licenses/>. */
|
|
||||||
|
|
||||||
/* This file provides some definitions shared by cplus-dem.c and
|
|
||||||
rust-demangle.c. It should not be included by any other files. */
|
|
||||||
|
|
||||||
/* Returns non-zero iff MANGLED is a rust mangled symbol. MANGLED must
|
|
||||||
already have been demangled through cplus_demangle_v3. If this function
|
|
||||||
returns non-zero then MANGLED can be demangled (in-place) using
|
|
||||||
RUST_DEMANGLE_SYM. */
|
|
||||||
extern int
|
|
||||||
rust_is_mangled (const char *mangled);
|
|
||||||
|
|
||||||
/* Demangles SYM (in-place) if RUST_IS_MANGLED returned non-zero for SYM.
|
|
||||||
If RUST_IS_MANGLED returned zero for SYM then RUST_DEMANGLE_SYM might
|
|
||||||
replace characters that cannot be demangled with '?' and might truncate
|
|
||||||
SYM. After calling RUST_DEMANGLE_SYM SYM might be shorter, but never
|
|
||||||
larger. */
|
|
||||||
extern void
|
|
||||||
rust_demangle_sym (char *sym);
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: LGPL 2.1
|
* IP: LGPL 2.1
|
||||||
* NOTE: license is not in file, but in the directory from whence it came: binutils-2.24/libiberty/COPYING.LIB
|
* NOTE: See binutils/libiberty/COPYING.LIB
|
||||||
*/
|
*/
|
||||||
/* alloca.c -- allocate automatically reclaimed memory
|
/* alloca.c -- allocate automatically reclaimed memory
|
||||||
(Mostly) portable public-domain implementation -- D A Gwyn
|
(Mostly) portable public-domain implementation -- D A Gwyn
|
||||||
|
@ -162,7 +162,7 @@ static header *last_alloca_header = NULL; /* -> last alloca header. */
|
||||||
|
|
||||||
/* @undocumented C_alloca */
|
/* @undocumented C_alloca */
|
||||||
|
|
||||||
PTR
|
void *
|
||||||
C_alloca (size_t size)
|
C_alloca (size_t size)
|
||||||
{
|
{
|
||||||
auto char probe; /* Probes stack depth: */
|
auto char probe; /* Probes stack depth: */
|
||||||
|
@ -185,7 +185,7 @@ C_alloca (size_t size)
|
||||||
{
|
{
|
||||||
register header *np = hp->h.next;
|
register header *np = hp->h.next;
|
||||||
|
|
||||||
free ((PTR) hp); /* Collect garbage. */
|
free ((void *) hp); /* Collect garbage. */
|
||||||
|
|
||||||
hp = np; /* -> next header. */
|
hp = np; /* -> next header. */
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,7 @@ C_alloca (size_t size)
|
||||||
|
|
||||||
/* User storage begins just after header. */
|
/* User storage begins just after header. */
|
||||||
|
|
||||||
return (PTR) ((char *) new_storage + sizeof (header));
|
return (void *) ((char *) new_storage + sizeof (header));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* NOTE: See binutils/libiberty/COPYING.LIB
|
* NOTE: See binutils/libiberty/COPYING.LIB
|
||||||
*/
|
*/
|
||||||
/* Create and destroy argument vectors (argv's)
|
/* Create and destroy argument vectors (argv's)
|
||||||
Copyright (C) 1992-2019 Free Software Foundation, Inc.
|
Copyright (C) 1992-2023 Free Software Foundation, Inc.
|
||||||
Written by Fred Fish @ Cygnus Support
|
Written by Fred Fish @ Cygnus Support
|
||||||
|
|
||||||
This file is part of the libiberty library.
|
This file is part of the libiberty library.
|
||||||
|
@ -293,8 +293,8 @@ char **buildargv (const char *input)
|
||||||
@deftypefn Extension int writeargv (char * const *@var{argv}, FILE *@var{file})
|
@deftypefn Extension int writeargv (char * const *@var{argv}, FILE *@var{file})
|
||||||
|
|
||||||
Write each member of ARGV, handling all necessary quoting, to the file
|
Write each member of ARGV, handling all necessary quoting, to the file
|
||||||
named by FILE, separated by whitespace. Return 0 on success, non-zero
|
associated with FILE, separated by whitespace. Return 0 on success,
|
||||||
if an error occurred while writing to FILE.
|
non-zero if an error occurred while writing to FILE.
|
||||||
|
|
||||||
@end deftypefn
|
@end deftypefn
|
||||||
|
|
||||||
|
@ -303,8 +303,6 @@ if an error occurred while writing to FILE.
|
||||||
int
|
int
|
||||||
writeargv (char * const *argv, FILE *f)
|
writeargv (char * const *argv, FILE *f)
|
||||||
{
|
{
|
||||||
int status = 0;
|
|
||||||
|
|
||||||
if (f == NULL)
|
if (f == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -318,29 +316,26 @@ writeargv (char * const *argv, FILE *f)
|
||||||
|
|
||||||
if (ISSPACE(c) || c == '\\' || c == '\'' || c == '"')
|
if (ISSPACE(c) || c == '\\' || c == '\'' || c == '"')
|
||||||
if (EOF == fputc ('\\', f))
|
if (EOF == fputc ('\\', f))
|
||||||
{
|
return 1;
|
||||||
status = 1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EOF == fputc (c, f))
|
if (EOF == fputc (c, f))
|
||||||
{
|
return 1;
|
||||||
status = 1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
arg++;
|
arg++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Write out a pair of quotes for an empty argument. */
|
||||||
|
if (arg == *argv)
|
||||||
|
if (EOF == fputs ("\"\"", f))
|
||||||
|
return 1;
|
||||||
|
|
||||||
if (EOF == fputc ('\n', f))
|
if (EOF == fputc ('\n', f))
|
||||||
{
|
return 1;
|
||||||
status = 1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
argv++;
|
argv++;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
return 0;
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -438,7 +433,10 @@ expandargv (int *argcp, char ***argvp)
|
||||||
due to CR/LF->CR translation when reading text files.
|
due to CR/LF->CR translation when reading text files.
|
||||||
That does not in-and-of itself indicate failure. */
|
That does not in-and-of itself indicate failure. */
|
||||||
&& ferror (f))
|
&& ferror (f))
|
||||||
|
{
|
||||||
|
free (buffer);
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
/* Add a NUL terminator. */
|
/* Add a NUL terminator. */
|
||||||
buffer[len] = '\0';
|
buffer[len] = '\0';
|
||||||
/* If the file is empty or contains only whitespace, buildargv would
|
/* If the file is empty or contains only whitespace, buildargv would
|
File diff suppressed because it is too large
Load diff
|
@ -3,7 +3,7 @@
|
||||||
* NOTE: See binutils/libiberty/COPYING.LIB
|
* NOTE: See binutils/libiberty/COPYING.LIB
|
||||||
*/
|
*/
|
||||||
/* Demangler for GNU C++
|
/* Demangler for GNU C++
|
||||||
Copyright (C) 1989-2019 Free Software Foundation, Inc.
|
Copyright (C) 1989-2023 Free Software Foundation, Inc.
|
||||||
Written by James Clark (jjc@jclark.uucp)
|
Written by James Clark (jjc@jclark.uucp)
|
||||||
Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
|
Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
|
||||||
Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
|
Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
|
||||||
|
@ -56,7 +56,6 @@ void * realloc ();
|
||||||
#define CURRENT_DEMANGLING_STYLE options
|
#define CURRENT_DEMANGLING_STYLE options
|
||||||
|
|
||||||
#include "libiberty.h"
|
#include "libiberty.h"
|
||||||
#include "rust-demangle.h"
|
|
||||||
|
|
||||||
enum demangling_styles current_demangling_style = auto_demangling;
|
enum demangling_styles current_demangling_style = auto_demangling;
|
||||||
|
|
||||||
|
@ -164,27 +163,20 @@ cplus_demangle (const char *mangled, int options)
|
||||||
if ((options & DMGL_STYLE_MASK) == 0)
|
if ((options & DMGL_STYLE_MASK) == 0)
|
||||||
options |= (int) current_demangling_style & DMGL_STYLE_MASK;
|
options |= (int) current_demangling_style & DMGL_STYLE_MASK;
|
||||||
|
|
||||||
|
/* The Rust demangling is implemented elsewhere.
|
||||||
|
Legacy Rust symbols overlap with GNU_V3, so try Rust first. */
|
||||||
|
if (RUST_DEMANGLING || AUTO_DEMANGLING)
|
||||||
|
{
|
||||||
|
ret = rust_demangle (mangled, options);
|
||||||
|
if (ret || RUST_DEMANGLING)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* The V3 ABI demangling is implemented elsewhere. */
|
/* The V3 ABI demangling is implemented elsewhere. */
|
||||||
if (GNU_V3_DEMANGLING || RUST_DEMANGLING || AUTO_DEMANGLING)
|
if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
|
||||||
{
|
{
|
||||||
ret = cplus_demangle_v3 (mangled, options);
|
ret = cplus_demangle_v3 (mangled, options);
|
||||||
if (GNU_V3_DEMANGLING)
|
if (ret || GNU_V3_DEMANGLING)
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
/* Rust symbols are GNU_V3 mangled plus some extra subtitutions.
|
|
||||||
The subtitutions are always smaller, so do in place changes. */
|
|
||||||
if (rust_is_mangled (ret))
|
|
||||||
rust_demangle_sym (ret);
|
|
||||||
else if (RUST_DEMANGLING)
|
|
||||||
{
|
|
||||||
free (ret);
|
|
||||||
ret = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret || RUST_DEMANGLING)
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,27 +200,6 @@ cplus_demangle (const char *mangled, int options)
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
|
||||||
rust_demangle (const char *mangled, int options)
|
|
||||||
{
|
|
||||||
/* Rust symbols are GNU_V3 mangled plus some extra subtitutions. */
|
|
||||||
char *ret = cplus_demangle_v3 (mangled, options);
|
|
||||||
|
|
||||||
/* The Rust subtitutions are always smaller, so do in place changes. */
|
|
||||||
if (ret != NULL)
|
|
||||||
{
|
|
||||||
if (rust_is_mangled (ret))
|
|
||||||
rust_demangle_sym (ret);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
free (ret);
|
|
||||||
ret = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */
|
/* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */
|
||||||
|
|
||||||
char *
|
char *
|
||||||
|
@ -248,7 +219,7 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
|
||||||
goto unknown;
|
goto unknown;
|
||||||
|
|
||||||
/* Most of the demangling will trivially remove chars. Operator names
|
/* Most of the demangling will trivially remove chars. Operator names
|
||||||
may add one char but because they are always preceeded by '__' which is
|
may add one char but because they are always preceded by '__' which is
|
||||||
replaced by '.', they eventually never expand the size.
|
replaced by '.', they eventually never expand the size.
|
||||||
A few special names such as '___elabs' add a few chars (at most 7), but
|
A few special names such as '___elabs' add a few chars (at most 7), but
|
||||||
they occur only once. */
|
they occur only once. */
|
|
@ -2,7 +2,7 @@
|
||||||
* IP: GPL 3
|
* IP: GPL 3
|
||||||
*/
|
*/
|
||||||
/* Demangler for GNU C++ - main program
|
/* Demangler for GNU C++ - main program
|
||||||
Copyright (C) 1989-2019 Free Software Foundation, Inc.
|
Copyright (C) 1989-2023 Free Software Foundation, Inc.
|
||||||
Written by James Clark (jjc@jclark.uucp)
|
Written by James Clark (jjc@jclark.uucp)
|
||||||
Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
|
Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
|
||||||
Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
|
Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
|
||||||
|
@ -24,22 +24,33 @@
|
||||||
Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
|
Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
|
||||||
02110-1301, USA.
|
02110-1301, USA.
|
||||||
|
|
||||||
|
|
||||||
CHANGE NOTICE:
|
CHANGE NOTICE:
|
||||||
This file was changed on July 22nd, 2020.
|
This file was changed on October 31st, 2023.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
// #include "sysdep.h" // Changed 10/31/23
|
||||||
#include <string.h>
|
// error reporting front end
|
||||||
|
// #include "bfd.h" // Changed 10/31/23
|
||||||
|
|
||||||
|
#include <stdlib.h> // Changed 10/31/23
|
||||||
|
#include <string.h> // Changed 10/31/23
|
||||||
|
|
||||||
#include "libiberty.h"
|
#include "libiberty.h"
|
||||||
#include "demangle.h"
|
#include "demangle.h"
|
||||||
#include "getopt.h"
|
#include "getopt.h"
|
||||||
#include "safe-ctype.h"
|
#include "safe-ctype.h"
|
||||||
|
|
||||||
|
// bfd code
|
||||||
|
// #include "bucomm.h" // Changed 10/31/23
|
||||||
|
|
||||||
static int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE;
|
static int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE;
|
||||||
static int strip_underscore = 0; // TARGET_PREPENDS_UNDERSCORE; // Changed Jan 22, 2020
|
static int strip_underscore = 0; // TARGET_PREPENDS_UNDERSCORE; // Changed 10/31/23
|
||||||
static const char *program_name; // Changed Jan 22, 2020
|
|
||||||
|
// declared in bucomm.c
|
||||||
|
static const char *program_name; // Changed 10/31/23
|
||||||
|
|
||||||
|
|
||||||
static const struct option long_options[] =
|
static const struct option long_options[] =
|
||||||
{
|
{
|
||||||
|
@ -108,10 +119,12 @@ Usage: %s [options] [mangled names]\n", program_name);
|
||||||
fprintf (stream, "\
|
fprintf (stream, "\
|
||||||
Options are:\n\
|
Options are:\n\
|
||||||
[-_|--strip-underscore] Ignore first leading underscore%s\n",
|
[-_|--strip-underscore] Ignore first leading underscore%s\n",
|
||||||
strip_underscore ? " (default)" : ""); // Changed Jan 22, 2020
|
// TARGET_PREPENDS_UNDERSCORE ? " (default)" : ""); // Changed 10/31/23
|
||||||
|
strip_underscore ? " (default)" : ""); // Changed 10/31/23
|
||||||
fprintf (stream, "\
|
fprintf (stream, "\
|
||||||
[-n|--no-strip-underscore] Do not ignore a leading underscore%s\n",
|
[-n|--no-strip-underscore] Do not ignore a leading underscore%s\n",
|
||||||
strip_underscore ? "" : " (default)"); // Changed Jan 22, 2020
|
// TARGET_PREPENDS_UNDERSCORE ? "" : " (default)"); // Changed 10/31/23
|
||||||
|
strip_underscore ? "" : " (default)"); // Changed 10/31/23
|
||||||
fprintf (stream, "\
|
fprintf (stream, "\
|
||||||
[-p|--no-params] Do not display function arguments\n\
|
[-p|--no-params] Do not display function arguments\n\
|
||||||
[-i|--no-verbose] Do not show implementation details (if any)\n\
|
[-i|--no-verbose] Do not show implementation details (if any)\n\
|
||||||
|
@ -130,11 +143,11 @@ Demangled names are displayed to stdout.\n\
|
||||||
If a name cannot be demangled it is just echoed to stdout.\n\
|
If a name cannot be demangled it is just echoed to stdout.\n\
|
||||||
If no names are provided on the command line, stdin is read.\n");
|
If no names are provided on the command line, stdin is read.\n");
|
||||||
|
|
||||||
/* Changed Jan 22, 2020
|
/* Changed 10/31/23
|
||||||
|
// defined in version.h
|
||||||
if (REPORT_BUGS_TO[0] && status == 0)
|
if (REPORT_BUGS_TO[0] && status == 0)
|
||||||
fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
|
fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exit (status);
|
exit (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,8 +171,8 @@ main (int argc, char **argv)
|
||||||
enum demangling_styles style = auto_demangling;
|
enum demangling_styles style = auto_demangling;
|
||||||
|
|
||||||
program_name = argv[0];
|
program_name = argv[0];
|
||||||
// xmalloc_set_program_name (program_name); // Changed Jan 22, 2020
|
// xmalloc_set_program_name (program_name); // Changed 10/31/23
|
||||||
// bfd_set_error_program_name (program_name); // Changed Jan 22, 2020
|
// bfd_set_error_program_name (program_name); // Changed 10/31/23
|
||||||
|
|
||||||
expandargv (&argc, &argv);
|
expandargv (&argc, &argv);
|
||||||
|
|
||||||
|
@ -191,7 +204,8 @@ main (int argc, char **argv)
|
||||||
flags &= ~ DMGL_VERBOSE;
|
flags &= ~ DMGL_VERBOSE;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
printf ("(GNU Binutils) c++filt 2.33.1\n"); // Changed Jan 22, 2020
|
// print_version ("c++filt"); // Changed 10/31/23
|
||||||
|
printf ("c++filt 2.41\n"); // Changed 10/31/23
|
||||||
return 0;
|
return 0;
|
||||||
case '_':
|
case '_':
|
||||||
strip_underscore = 1;
|
strip_underscore = 1;
|
||||||
|
@ -230,13 +244,14 @@ main (int argc, char **argv)
|
||||||
case rust_demangling:
|
case rust_demangling:
|
||||||
valid_symbols = standard_symbol_characters ();
|
valid_symbols = standard_symbol_characters ();
|
||||||
break;
|
break;
|
||||||
default: {
|
default:
|
||||||
/* Folks should explicitly indicate the appropriate alphabet for
|
/* Folks should explicitly indicate the appropriate alphabet for
|
||||||
each demangling. Providing a default would allow the
|
each demangling. Providing a default would allow the
|
||||||
question to go unconsidered. */
|
question to go unconsidered. */
|
||||||
fprintf (stderr, "Internal error: no symbol alphabet for current style\n"); // Changed Jan 22, 2020
|
// fatal ("Internal error: no symbol alphabet for current style"); // Changed 10/31/23
|
||||||
exit (1); // Changed Jan 22, 2020
|
fprintf (stderr, "Internal error: no symbol alphabet for current style\n"); // Changed 10/31/23
|
||||||
}
|
exit (1); // Changed 10/31/23
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
1986
GPL/DemanglerGnu/src/demangler_gnu_v2_41/c/d-demangle.c
Normal file
1986
GPL/DemanglerGnu/src/demangler_gnu_v2_41/c/d-demangle.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -3,7 +3,7 @@
|
||||||
* NOTE: See binutils/include/COPYING3
|
* NOTE: See binutils/include/COPYING3
|
||||||
*/
|
*/
|
||||||
/* An abstract string datatype.
|
/* An abstract string datatype.
|
||||||
Copyright (C) 1998-2019 Free Software Foundation, Inc.
|
Copyright (C) 1998-2023 Free Software Foundation, Inc.
|
||||||
Contributed by Mark Mitchell (mark@markmitchell.com).
|
Contributed by Mark Mitchell (mark@markmitchell.com).
|
||||||
|
|
||||||
This file is part of GNU CC.
|
This file is part of GNU CC.
|
||||||
|
@ -281,7 +281,7 @@ dyn_string_insert_cstr (dyn_string_t dest, int pos, const char *src)
|
||||||
for (i = dest->length; i >= pos; --i)
|
for (i = dest->length; i >= pos; --i)
|
||||||
dest->s[i + length] = dest->s[i];
|
dest->s[i + length] = dest->s[i];
|
||||||
/* Splice in the new stuff. */
|
/* Splice in the new stuff. */
|
||||||
strncpy (dest->s + pos, src, length);
|
memcpy (dest->s + pos, src, length);
|
||||||
/* Compute the new length. */
|
/* Compute the new length. */
|
||||||
dest->length += length;
|
dest->length += length;
|
||||||
return 1;
|
return 1;
|
|
@ -1,5 +1,5 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GPL 3
|
* IP: GPL 3 Linking Permitted
|
||||||
* NOTE: See binutils/include/COPYING3
|
* NOTE: See binutils/include/COPYING3
|
||||||
*/
|
*/
|
||||||
/* Getopt for GNU.
|
/* Getopt for GNU.
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
"Keep this file name-space clean" means, talk to drepper@gnu.org
|
"Keep this file name-space clean" means, talk to drepper@gnu.org
|
||||||
before changing it!
|
before changing it!
|
||||||
|
|
||||||
Copyright (C) 1987-2019 Free Software Foundation, Inc.
|
Copyright (C) 1987-2023 Free Software Foundation, Inc.
|
||||||
|
|
||||||
NOTE: This source is derived from an old version taken from the GNU C
|
NOTE: This source is derived from an old version taken from the GNU C
|
||||||
Library (glibc).
|
Library (glibc).
|
|
@ -1,9 +1,9 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GPL 3
|
* IP: GPL 3 Linking Permitted
|
||||||
* NOTE: See binutils/include/COPYING3
|
* NOTE: See binutils/include/COPYING3
|
||||||
*/
|
*/
|
||||||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||||
Copyright (C) 1987-2019 Free Software Foundation, Inc.
|
Copyright (C) 1987-2023 Free Software Foundation, Inc.
|
||||||
|
|
||||||
NOTE: This source is derived from an old version taken from the GNU C
|
NOTE: This source is derived from an old version taken from the GNU C
|
||||||
Library (glibc).
|
Library (glibc).
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
|
|
||||||
CHANGE NOTICE:
|
CHANGE NOTICE:
|
||||||
This file was created on January 22nd, 2020:
|
This file was created on October 31st, 2023:
|
||||||
-This code was copied and modified from a previous version of libiberty
|
-This code was copied and modified from a previous version of libiberty
|
||||||
|
|
||||||
*/
|
*/
|
1608
GPL/DemanglerGnu/src/demangler_gnu_v2_41/c/rust-demangle.c
Normal file
1608
GPL/DemanglerGnu/src/demangler_gnu_v2_41/c/rust-demangle.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,10 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: LGPL 2.1
|
* IP: LGPL 2.1
|
||||||
* NOTE: See binutils/include/COPYING
|
* NOTE: See binutils/libiberty/COPYING.LIB
|
||||||
*/
|
*/
|
||||||
/* <ctype.h> replacement macros.
|
/* <ctype.h> replacement macros.
|
||||||
|
|
||||||
Copyright (C) 2000-2019 Free Software Foundation, Inc.
|
Copyright (C) 2000-2023 Free Software Foundation, Inc.
|
||||||
Contributed by Zack Weinberg <zackw@stanford.edu>.
|
Contributed by Zack Weinberg <zackw@stanford.edu>.
|
||||||
|
|
||||||
This file is part of the libiberty library.
|
This file is part of the libiberty library.
|
|
@ -3,7 +3,7 @@
|
||||||
* NOTE: See binutils/libiberty/COPYING.LIB
|
* NOTE: See binutils/libiberty/COPYING.LIB
|
||||||
*/
|
*/
|
||||||
/* xexit.c -- Run any exit handlers, then exit.
|
/* xexit.c -- Run any exit handlers, then exit.
|
||||||
Copyright (C) 1994-2019 Free Software Foundation, Inc.
|
Copyright (C) 1994-2023 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is part of the libiberty library.
|
This file is part of the libiberty library.
|
||||||
Libiberty is free software; you can redistribute it and/or
|
Libiberty is free software; you can redistribute it and/or
|
|
@ -2,8 +2,8 @@
|
||||||
* IP: LGPL 2.1
|
* IP: LGPL 2.1
|
||||||
* NOTE: See binutils/include/COPYING
|
* NOTE: See binutils/include/COPYING
|
||||||
*/
|
*/
|
||||||
/* ANSI and traditional C compatability macros
|
/* Compiler compatibility macros
|
||||||
Copyright (C) 1991-2019 Free Software Foundation, Inc.
|
Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -20,18 +20,7 @@ You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
|
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||||
|
|
||||||
/* ANSI and traditional C compatibility macros
|
/* For ease of writing code which uses GCC extensions but needs to be
|
||||||
|
|
||||||
ANSI C is assumed if __STDC__ is #defined.
|
|
||||||
|
|
||||||
Macro ANSI C definition Traditional C definition
|
|
||||||
----- ---- - ---------- ----------- - ----------
|
|
||||||
PTR `void *' `char *'
|
|
||||||
const not defined `'
|
|
||||||
volatile not defined `'
|
|
||||||
signed not defined `'
|
|
||||||
|
|
||||||
For ease of writing code which uses GCC extensions but needs to be
|
|
||||||
portable to other compilers, we provide the GCC_VERSION macro that
|
portable to other compilers, we provide the GCC_VERSION macro that
|
||||||
simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various
|
simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various
|
||||||
wrappers around __attribute__. Also, __extension__ will be #defined
|
wrappers around __attribute__. Also, __extension__ will be #defined
|
||||||
|
@ -66,24 +55,10 @@ So instead we use the macro below and test it against specific values. */
|
||||||
#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
|
#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
|
||||||
#endif /* GCC_VERSION */
|
#endif /* GCC_VERSION */
|
||||||
|
|
||||||
#if defined (__STDC__) || defined(__cplusplus) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32)
|
|
||||||
/* All known AIX compilers implement these things (but don't always
|
|
||||||
define __STDC__). The RISC/OS MIPS compiler defines these things
|
|
||||||
in SVR4 mode, but does not define __STDC__. */
|
|
||||||
/* eraxxon@alumni.rice.edu: The Compaq C++ compiler, unlike many other
|
|
||||||
C++ compilers, does not define __STDC__, though it acts as if this
|
|
||||||
was so. (Verified versions: 5.7, 6.2, 6.3, 6.5) */
|
|
||||||
|
|
||||||
#define PTR void *
|
|
||||||
|
|
||||||
#undef const
|
|
||||||
#undef volatile
|
|
||||||
#undef signed
|
|
||||||
|
|
||||||
/* inline requires special treatment; it's in C99, and GCC >=2.7 supports
|
/* inline requires special treatment; it's in C99, and GCC >=2.7 supports
|
||||||
it too, but it's not in C89. */
|
it too, but it's not in C89. */
|
||||||
#undef inline
|
#undef inline
|
||||||
#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) || (defined(__SUNPRO_C) && defined(__C99FEATURES__))
|
#if (!defined(__cplusplus) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) || (defined(__SUNPRO_C) && defined(__C99FEATURES__))
|
||||||
/* it's a keyword */
|
/* it's a keyword */
|
||||||
#else
|
#else
|
||||||
# if GCC_VERSION >= 2007
|
# if GCC_VERSION >= 2007
|
||||||
|
@ -93,22 +68,6 @@ So instead we use the macro below and test it against specific values. */
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else /* Not ANSI C. */
|
|
||||||
|
|
||||||
#define PTR char *
|
|
||||||
|
|
||||||
/* some systems define these in header files for non-ansi mode */
|
|
||||||
#undef const
|
|
||||||
#undef volatile
|
|
||||||
#undef signed
|
|
||||||
#undef inline
|
|
||||||
#define const
|
|
||||||
#define volatile
|
|
||||||
#define signed
|
|
||||||
#define inline
|
|
||||||
|
|
||||||
#endif /* ANSI C. */
|
|
||||||
|
|
||||||
/* Define macros for some gcc attributes. This permits us to use the
|
/* Define macros for some gcc attributes. This permits us to use the
|
||||||
macros freely, and know that they will come into play for the
|
macros freely, and know that they will come into play for the
|
||||||
version of gcc in which they are supported. */
|
version of gcc in which they are supported. */
|
||||||
|
@ -296,6 +255,40 @@ So instead we use the macro below and test it against specific values. */
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Attribute `alloc_size' was valid as of gcc 4.3. */
|
||||||
|
#ifndef ATTRIBUTE_RESULT_SIZE_1
|
||||||
|
# if (GCC_VERSION >= 4003)
|
||||||
|
# define ATTRIBUTE_RESULT_SIZE_1 __attribute__ ((alloc_size (1)))
|
||||||
|
# else
|
||||||
|
# define ATTRIBUTE_RESULT_SIZE_1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ATTRIBUTE_RESULT_SIZE_2
|
||||||
|
# if (GCC_VERSION >= 4003)
|
||||||
|
# define ATTRIBUTE_RESULT_SIZE_2 __attribute__ ((alloc_size (2)))
|
||||||
|
# else
|
||||||
|
# define ATTRIBUTE_RESULT_SIZE_2
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ATTRIBUTE_RESULT_SIZE_1_2
|
||||||
|
# if (GCC_VERSION >= 4003)
|
||||||
|
# define ATTRIBUTE_RESULT_SIZE_1_2 __attribute__ ((alloc_size (1, 2)))
|
||||||
|
# else
|
||||||
|
# define ATTRIBUTE_RESULT_SIZE_1_2
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Attribute `warn_unused_result' was valid as of gcc 3.3. */
|
||||||
|
#ifndef ATTRIBUTE_WARN_UNUSED_RESULT
|
||||||
|
# if GCC_VERSION >= 3003
|
||||||
|
# define ATTRIBUTE_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
|
||||||
|
# else
|
||||||
|
# define ATTRIBUTE_WARN_UNUSED_RESULT
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* We use __extension__ in some places to suppress -pedantic warnings
|
/* We use __extension__ in some places to suppress -pedantic warnings
|
||||||
about GCC extensions. This feature didn't work properly before
|
about GCC extensions. This feature didn't work properly before
|
||||||
gcc 2.8. */
|
gcc 2.8. */
|
||||||
|
@ -326,53 +319,12 @@ So instead we use the macro below and test it against specific values. */
|
||||||
#define ENUM_BITFIELD(TYPE) unsigned int
|
#define ENUM_BITFIELD(TYPE) unsigned int
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __cpp_constexpr >= 200704
|
#if defined(__cplusplus) && __cpp_constexpr >= 200704
|
||||||
#define CONSTEXPR constexpr
|
#define CONSTEXPR constexpr
|
||||||
#else
|
#else
|
||||||
#define CONSTEXPR
|
#define CONSTEXPR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* C++11 adds the ability to add "override" after an implementation of a
|
|
||||||
virtual function in a subclass, to:
|
|
||||||
(A) document that this is an override of a virtual function
|
|
||||||
(B) allow the compiler to issue a warning if it isn't (e.g. a mismatch
|
|
||||||
of the type signature).
|
|
||||||
|
|
||||||
Similarly, it allows us to add a "final" to indicate that no subclass
|
|
||||||
may subsequently override the vfunc.
|
|
||||||
|
|
||||||
Provide OVERRIDE and FINAL as macros, allowing us to get these benefits
|
|
||||||
when compiling with C++11 support, but without requiring C++11.
|
|
||||||
|
|
||||||
For gcc, use "-std=c++11" to enable C++11 support; gcc 6 onwards enables
|
|
||||||
this by default (actually GNU++14). */
|
|
||||||
|
|
||||||
#if defined __cplusplus
|
|
||||||
# if __cplusplus >= 201103
|
|
||||||
/* C++11 claims to be available: use it. Final/override were only
|
|
||||||
implemented in 4.7, though. */
|
|
||||||
# if GCC_VERSION < 4007
|
|
||||||
# define OVERRIDE
|
|
||||||
# define FINAL
|
|
||||||
# else
|
|
||||||
# define OVERRIDE override
|
|
||||||
# define FINAL final
|
|
||||||
# endif
|
|
||||||
# elif GCC_VERSION >= 4007
|
|
||||||
/* G++ 4.7 supports __final in C++98. */
|
|
||||||
# define OVERRIDE
|
|
||||||
# define FINAL __final
|
|
||||||
# else
|
|
||||||
/* No C++11 support; leave the macros empty. */
|
|
||||||
# define OVERRIDE
|
|
||||||
# define FINAL
|
|
||||||
# endif
|
|
||||||
#else
|
|
||||||
/* No C++11 support; leave the macros empty. */
|
|
||||||
# define OVERRIDE
|
|
||||||
# define FINAL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* A macro to disable the copy constructor and assignment operator.
|
/* A macro to disable the copy constructor and assignment operator.
|
||||||
When building with C++11 and above, the methods are explicitly
|
When building with C++11 and above, the methods are explicitly
|
||||||
deleted, causing a compile-time error if something tries to copy.
|
deleted, causing a compile-time error if something tries to copy.
|
||||||
|
@ -389,7 +341,7 @@ So instead we use the macro below and test it against specific values. */
|
||||||
|
|
||||||
so that most attempts at copy are caught at compile-time. */
|
so that most attempts at copy are caught at compile-time. */
|
||||||
|
|
||||||
#if __cplusplus >= 201103
|
#if defined(__cplusplus) && __cplusplus >= 201103
|
||||||
#define DISABLE_COPY_AND_ASSIGN(TYPE) \
|
#define DISABLE_COPY_AND_ASSIGN(TYPE) \
|
||||||
TYPE (const TYPE&) = delete; \
|
TYPE (const TYPE&) = delete; \
|
||||||
void operator= (const TYPE &) = delete
|
void operator= (const TYPE &) = delete
|
|
@ -1,9 +1,9 @@
|
||||||
/* ###
|
/* ###
|
||||||
* IP: GPL 3 Linking Permitted
|
* IP: LGPL 2.1
|
||||||
* NOTE: See binutils/libiberty/COPYING.LIB; Used GPL 3 from this file's header
|
* NOTE: See binutils/include/COPYING
|
||||||
*/
|
*/
|
||||||
/* Internal demangler interface for g++ V3 ABI.
|
/* Internal demangler interface for g++ V3 ABI.
|
||||||
Copyright (C) 2003-2019 Free Software Foundation, Inc.
|
Copyright (C) 2003-2023 Free Software Foundation, Inc.
|
||||||
Written by Ian Lance Taylor <ian@wasabisystems.com>.
|
Written by Ian Lance Taylor <ian@wasabisystems.com>.
|
||||||
|
|
||||||
This file is part of the libiberty library, which is part of GCC.
|
This file is part of the libiberty library, which is part of GCC.
|
||||||
|
@ -126,6 +126,10 @@ struct d_info
|
||||||
/* Non-zero if we are parsing the type operand of a conversion
|
/* Non-zero if we are parsing the type operand of a conversion
|
||||||
operator, but not when in an expression. */
|
operator, but not when in an expression. */
|
||||||
int is_conversion;
|
int is_conversion;
|
||||||
|
/* 1: using new unresolved-name grammar.
|
||||||
|
-1: using new unresolved-name grammar and saw an unresolved-name.
|
||||||
|
0: using old unresolved-name grammar. */
|
||||||
|
int unresolved_name_state;
|
||||||
/* If DMGL_NO_RECURSE_LIMIT is not active then this is set to
|
/* If DMGL_NO_RECURSE_LIMIT is not active then this is set to
|
||||||
the current recursion level. */
|
the current recursion level. */
|
||||||
unsigned int recursion_level;
|
unsigned int recursion_level;
|
||||||
|
@ -180,7 +184,7 @@ d_advance (struct d_info *di, int i)
|
||||||
extern const struct demangle_operator_info cplus_demangle_operators[];
|
extern const struct demangle_operator_info cplus_demangle_operators[];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define D_BUILTIN_TYPE_COUNT (34)
|
#define D_BUILTIN_TYPE_COUNT (36)
|
||||||
|
|
||||||
CP_STATIC_IF_GLIBCPP_V3
|
CP_STATIC_IF_GLIBCPP_V3
|
||||||
const struct demangle_builtin_type_info
|
const struct demangle_builtin_type_info
|
|
@ -3,7 +3,7 @@
|
||||||
* NOTE: See binutils/include/COPYING
|
* NOTE: See binutils/include/COPYING
|
||||||
*/
|
*/
|
||||||
/* Defs for interface to demanglers.
|
/* Defs for interface to demanglers.
|
||||||
Copyright (C) 1992-2019 Free Software Foundation, Inc.
|
Copyright (C) 1992-2023 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public License
|
modify it under the terms of the GNU Library General Public License
|
||||||
|
@ -163,24 +163,11 @@ ada_demangle (const char *mangled, int options);
|
||||||
extern char *
|
extern char *
|
||||||
dlang_demangle (const char *mangled, int options);
|
dlang_demangle (const char *mangled, int options);
|
||||||
|
|
||||||
/* Returns non-zero iff MANGLED is a rust mangled symbol. MANGLED must
|
|
||||||
already have been demangled through cplus_demangle_v3. If this function
|
|
||||||
returns non-zero then MANGLED can be demangled (in-place) using
|
|
||||||
RUST_DEMANGLE_SYM. */
|
|
||||||
extern int
|
extern int
|
||||||
rust_is_mangled (const char *mangled);
|
rust_demangle_callback (const char *mangled, int options,
|
||||||
|
demangle_callbackref callback, void *opaque);
|
||||||
|
|
||||||
/* Demangles SYM (in-place) if RUST_IS_MANGLED returned non-zero for SYM.
|
|
||||||
If RUST_IS_MANGLED returned zero for SYM then RUST_DEMANGLE_SYM might
|
|
||||||
replace characters that cannot be demangled with '?' and might truncate
|
|
||||||
SYM. After calling RUST_DEMANGLE_SYM SYM might be shorter, but never
|
|
||||||
larger. */
|
|
||||||
extern void
|
|
||||||
rust_demangle_sym (char *sym);
|
|
||||||
|
|
||||||
/* Demangles MANGLED if it was GNU_V3 and then RUST mangled, otherwise
|
|
||||||
returns NULL. Uses CPLUS_DEMANGLE_V3, RUST_IS_MANGLED and
|
|
||||||
RUST_DEMANGLE_SYM. Returns a new string that is owned by the caller. */
|
|
||||||
extern char *
|
extern char *
|
||||||
rust_demangle (const char *mangled, int options);
|
rust_demangle (const char *mangled, int options);
|
||||||
|
|
||||||
|
@ -425,6 +412,9 @@ enum demangle_component_type
|
||||||
number which involves neither modifying the mangled string nor
|
number which involves neither modifying the mangled string nor
|
||||||
allocating a new copy of the literal in memory. */
|
allocating a new copy of the literal in memory. */
|
||||||
DEMANGLE_COMPONENT_LITERAL_NEG,
|
DEMANGLE_COMPONENT_LITERAL_NEG,
|
||||||
|
/* A vendor's builtin expression. The left subtree holds the
|
||||||
|
expression's name, and the right subtree is a argument list. */
|
||||||
|
DEMANGLE_COMPONENT_VENDOR_EXPR,
|
||||||
/* A libgcj compiled resource. The left subtree is the name of the
|
/* A libgcj compiled resource. The left subtree is the name of the
|
||||||
resource. */
|
resource. */
|
||||||
DEMANGLE_COMPONENT_JAVA_RESOURCE,
|
DEMANGLE_COMPONENT_JAVA_RESOURCE,
|
||||||
|
@ -463,7 +453,25 @@ enum demangle_component_type
|
||||||
/* A cloned function. */
|
/* A cloned function. */
|
||||||
DEMANGLE_COMPONENT_CLONE,
|
DEMANGLE_COMPONENT_CLONE,
|
||||||
DEMANGLE_COMPONENT_NOEXCEPT,
|
DEMANGLE_COMPONENT_NOEXCEPT,
|
||||||
DEMANGLE_COMPONENT_THROW_SPEC
|
DEMANGLE_COMPONENT_THROW_SPEC,
|
||||||
|
|
||||||
|
DEMANGLE_COMPONENT_STRUCTURED_BINDING,
|
||||||
|
|
||||||
|
DEMANGLE_COMPONENT_MODULE_NAME,
|
||||||
|
DEMANGLE_COMPONENT_MODULE_PARTITION,
|
||||||
|
DEMANGLE_COMPONENT_MODULE_ENTITY,
|
||||||
|
DEMANGLE_COMPONENT_MODULE_INIT,
|
||||||
|
|
||||||
|
DEMANGLE_COMPONENT_TEMPLATE_HEAD,
|
||||||
|
DEMANGLE_COMPONENT_TEMPLATE_TYPE_PARM,
|
||||||
|
DEMANGLE_COMPONENT_TEMPLATE_NON_TYPE_PARM,
|
||||||
|
DEMANGLE_COMPONENT_TEMPLATE_TEMPLATE_PARM,
|
||||||
|
DEMANGLE_COMPONENT_TEMPLATE_PACK_PARM,
|
||||||
|
|
||||||
|
/* A builtin type with argument. This holds the builtin type
|
||||||
|
information. */
|
||||||
|
DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Types which are only used internally. */
|
/* Types which are only used internally. */
|
||||||
|
@ -485,6 +493,7 @@ struct demangle_component
|
||||||
Initialize to zero. Private to d_print_comp.
|
Initialize to zero. Private to d_print_comp.
|
||||||
All other fields are final after initialization. */
|
All other fields are final after initialization. */
|
||||||
int d_printing;
|
int d_printing;
|
||||||
|
int d_counting;
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
@ -549,6 +558,15 @@ struct demangle_component
|
||||||
const struct demangle_builtin_type_info *type;
|
const struct demangle_builtin_type_info *type;
|
||||||
} s_builtin;
|
} s_builtin;
|
||||||
|
|
||||||
|
/* For DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE. */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/* Builtin type. */
|
||||||
|
const struct demangle_builtin_type_info *type;
|
||||||
|
short arg;
|
||||||
|
char suffix;
|
||||||
|
} s_extended_builtin;
|
||||||
|
|
||||||
/* For DEMANGLE_COMPONENT_SUB_STD. */
|
/* For DEMANGLE_COMPONENT_SUB_STD. */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
|
@ -3,7 +3,7 @@
|
||||||
* NOTE: See binutils/include/COPYING3
|
* NOTE: See binutils/include/COPYING3
|
||||||
*/
|
*/
|
||||||
/* An abstract string datatype.
|
/* An abstract string datatype.
|
||||||
Copyright (C) 1998-2019 Free Software Foundation, Inc.
|
Copyright (C) 1998-2023 Free Software Foundation, Inc.
|
||||||
Contributed by Mark Mitchell (mark@markmitchell.com).
|
Contributed by Mark Mitchell (mark@markmitchell.com).
|
||||||
|
|
||||||
This file is part of GCC.
|
This file is part of GCC.
|
|
@ -3,7 +3,7 @@
|
||||||
* NOTE: See binutils/include/COPYING3
|
* NOTE: See binutils/include/COPYING3
|
||||||
*/
|
*/
|
||||||
/* Declarations for getopt.
|
/* Declarations for getopt.
|
||||||
Copyright (C) 1989-2019 Free Software Foundation, Inc.
|
Copyright (C) 1989-2023 Free Software Foundation, Inc.
|
||||||
|
|
||||||
NOTE: The canonical source of this file is maintained with the GNU C Library.
|
NOTE: The canonical source of this file is maintained with the GNU C Library.
|
||||||
Bugs can be reported to bug-glibc@gnu.org.
|
Bugs can be reported to bug-glibc@gnu.org.
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
/* Function declarations for libiberty.
|
/* Function declarations for libiberty.
|
||||||
|
|
||||||
Copyright (C) 1997-2019 Free Software Foundation, Inc.
|
Copyright (C) 1997-2023 Free Software Foundation, Inc.
|
||||||
|
|
||||||
Note - certain prototypes declared in this header file are for
|
Note - certain prototypes declared in this header file are for
|
||||||
functions whoes implementation copyright does not belong to the
|
functions whoes implementation copyright does not belong to the
|
||||||
|
@ -141,6 +141,10 @@ extern const char *unix_lbasename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRI
|
||||||
|
|
||||||
extern char *lrealpath (const char *);
|
extern char *lrealpath (const char *);
|
||||||
|
|
||||||
|
/* Return true when FD file descriptor exists. */
|
||||||
|
|
||||||
|
extern int is_valid_fd (int fd);
|
||||||
|
|
||||||
/* Concatenate an arbitrary number of strings. You must pass NULL as
|
/* Concatenate an arbitrary number of strings. You must pass NULL as
|
||||||
the last argument of this function, to terminate the list of
|
the last argument of this function, to terminate the list of
|
||||||
strings. Allocates memory using xmalloc. */
|
strings. Allocates memory using xmalloc. */
|
||||||
|
@ -314,30 +318,30 @@ extern void xmalloc_failed (size_t) ATTRIBUTE_NORETURN;
|
||||||
message to stderr (using the name set by xmalloc_set_program_name,
|
message to stderr (using the name set by xmalloc_set_program_name,
|
||||||
if any) and then call xexit. */
|
if any) and then call xexit. */
|
||||||
|
|
||||||
extern void *xmalloc (size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
|
extern void *xmalloc (size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_RESULT_SIZE_1 ATTRIBUTE_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
/* Reallocate memory without fail. This works like xmalloc. Note,
|
/* Reallocate memory without fail. This works like xmalloc. Note,
|
||||||
realloc type functions are not suitable for attribute malloc since
|
realloc type functions are not suitable for attribute malloc since
|
||||||
they may return the same address across multiple calls. */
|
they may return the same address across multiple calls. */
|
||||||
|
|
||||||
extern void *xrealloc (void *, size_t) ATTRIBUTE_RETURNS_NONNULL;
|
extern void *xrealloc (void *, size_t) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_RESULT_SIZE_2 ATTRIBUTE_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
/* Allocate memory without fail and set it to zero. This works like
|
/* Allocate memory without fail and set it to zero. This works like
|
||||||
xmalloc. */
|
xmalloc. */
|
||||||
|
|
||||||
extern void *xcalloc (size_t, size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
|
extern void *xcalloc (size_t, size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_RESULT_SIZE_1_2 ATTRIBUTE_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
/* Copy a string into a memory buffer without fail. */
|
/* Copy a string into a memory buffer without fail. */
|
||||||
|
|
||||||
extern char *xstrdup (const char *) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
|
extern char *xstrdup (const char *) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
/* Copy at most N characters from string into a buffer without fail. */
|
/* Copy at most N characters from string into a buffer without fail. */
|
||||||
|
|
||||||
extern char *xstrndup (const char *, size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
|
extern char *xstrndup (const char *, size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
/* Copy an existing memory buffer to a new memory buffer without fail. */
|
/* Copy an existing memory buffer to a new memory buffer without fail. */
|
||||||
|
|
||||||
extern void *xmemdup (const void *, size_t, size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
|
extern void *xmemdup (const void *, size_t, size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
/* Physical memory routines. Return values are in BYTES. */
|
/* Physical memory routines. Return values are in BYTES. */
|
||||||
extern double physmem_total (void);
|
extern double physmem_total (void);
|
||||||
|
@ -641,6 +645,13 @@ extern int pexecute (const char *, char * const *, const char *,
|
||||||
|
|
||||||
extern int pwait (int, int *, int);
|
extern int pwait (int, int *, int);
|
||||||
|
|
||||||
|
/* Like bsearch, but takes and passes on an argument like qsort_r. */
|
||||||
|
|
||||||
|
extern void *bsearch_r (const void *, const void *,
|
||||||
|
size_t, size_t,
|
||||||
|
int (*)(const void *, const void *, void *),
|
||||||
|
void *);
|
||||||
|
|
||||||
#if defined(HAVE_DECL_ASPRINTF) && !HAVE_DECL_ASPRINTF
|
#if defined(HAVE_DECL_ASPRINTF) && !HAVE_DECL_ASPRINTF
|
||||||
/* Like sprintf but provides a pointer to malloc'd storage, which must
|
/* Like sprintf but provides a pointer to malloc'd storage, which must
|
||||||
be freed by the caller. */
|
be freed by the caller. */
|
||||||
|
@ -653,7 +664,7 @@ extern int asprintf (char **, const char *, ...) ATTRIBUTE_PRINTF_2;
|
||||||
|
|
||||||
extern char *xasprintf (const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_PRINTF_1;
|
extern char *xasprintf (const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_PRINTF_1;
|
||||||
|
|
||||||
#if !HAVE_DECL_VASPRINTF
|
#if defined(HAVE_DECL_VASPRINTF) && !HAVE_DECL_VASPRINTF
|
||||||
/* Like vsprintf but provides a pointer to malloc'd storage, which
|
/* Like vsprintf but provides a pointer to malloc'd storage, which
|
||||||
must be freed by the caller. */
|
must be freed by the caller. */
|
||||||
|
|
||||||
|
@ -706,11 +717,6 @@ extern unsigned long long int strtoull (const char *nptr,
|
||||||
char **endptr, int base);
|
char **endptr, int base);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_DECL_STRVERSCMP) && !HAVE_DECL_STRVERSCMP
|
|
||||||
/* Compare version strings. */
|
|
||||||
extern int strverscmp (const char *, const char *);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Set the title of a process */
|
/* Set the title of a process */
|
||||||
extern void setproctitle (const char *name, ...);
|
extern void setproctitle (const char *name, ...);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
/* <ctype.h> replacement macros.
|
/* <ctype.h> replacement macros.
|
||||||
|
|
||||||
Copyright (C) 2000-2019 Free Software Foundation, Inc.
|
Copyright (C) 2000-2023 Free Software Foundation, Inc.
|
||||||
Contributed by Zack Weinberg <zackw@stanford.edu>.
|
Contributed by Zack Weinberg <zackw@stanford.edu>.
|
||||||
|
|
||||||
This file is part of the libiberty library.
|
This file is part of the libiberty library.
|
27
GPL/GnuDisassembler/README.md
Normal file
27
GPL/GnuDisassembler/README.md
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# GnuDisassembler
|
||||||
|
|
||||||
|
The GnuDisassembler extension module must be built using gradle prior to its use within Ghidra.
|
||||||
|
|
||||||
|
This module provides the ability to leverage the binutils disassembler capabilities
|
||||||
|
for various processors as a means of verifying Sleigh disassembler output syntax.
|
||||||
|
|
||||||
|
To build this extension for Linux or macOS:
|
||||||
|
|
||||||
|
1. If building for an installation of Ghidra, copy the appropriate source distribution of binutils
|
||||||
|
into this module's root directory. If building within a git clone of the full Ghidra source, copy
|
||||||
|
binutils source distribution file into the `ghidra.bin/GPL/GnuDisassembler` directory.
|
||||||
|
|
||||||
|
The supported version and archive format is identified within the build.gradle file. If a
|
||||||
|
different binutils distribution is used the build.gradle and/or buildGdis.gradle may require
|
||||||
|
modification.
|
||||||
|
|
||||||
|
The build requires the following packages to be installed:
|
||||||
|
* flex
|
||||||
|
* bison
|
||||||
|
* texinfo
|
||||||
|
* zlib1g-dev
|
||||||
|
|
||||||
|
2. Run gradle from the module's root directory (see top of `build.gradle` file for specific
|
||||||
|
instructions).
|
||||||
|
|
||||||
|
This resulting gdis executable will be located in `build/os/<platform>`.
|
|
@ -1,26 +0,0 @@
|
||||||
The GnuDisassembler extension module must be built using gradle prior to its' use within Ghidra.
|
|
||||||
|
|
||||||
This module provides the ability to leverage the binutils disassembler capabilities
|
|
||||||
for various processors as a means of verifying Sleigh disassembler output syntax.
|
|
||||||
|
|
||||||
To build this extension for Linux or Mac OS X:
|
|
||||||
|
|
||||||
1. If building for an installation of Ghidra, copy the appropriate source distribution of
|
|
||||||
binutils into this module's root directory. If building within a git clone of the full
|
|
||||||
Ghidra source, copy binutils source distribution file into the ghidra.bin/GPL/GnuDisassembler
|
|
||||||
directory.
|
|
||||||
|
|
||||||
The supported version and archive format is identified within the build.gradle file.
|
|
||||||
If a different binutils distribution is used the build.gradle and/or buildGdis.gradle
|
|
||||||
may require modification.
|
|
||||||
|
|
||||||
The build requires the following packages to be installed:
|
|
||||||
* flex
|
|
||||||
* bison
|
|
||||||
* texinfo
|
|
||||||
* zlib1g-dev
|
|
||||||
|
|
||||||
2. Run gradle from the module's root directory (see top of build.gradle file for
|
|
||||||
specific instructions).
|
|
||||||
|
|
||||||
This resulting gdis executable will be located in build/os/<platform>.
|
|
|
@ -28,20 +28,23 @@
|
||||||
// directory once the extension has been installed/unpacked by Ghidra. The binutils referenced
|
// directory once the extension has been installed/unpacked by Ghidra. The binutils referenced
|
||||||
// by the script below may be downloaded from the following URL:
|
// by the script below may be downloaded from the following URL:
|
||||||
//
|
//
|
||||||
// https://ftp.gnu.org/pub/gnu/binutils/binutils-2.36.tar.bz2
|
// https://ftp.gnu.org/pub/gnu/binutils/binutils-2.41.tar.bz2
|
||||||
//
|
//
|
||||||
|
|
||||||
ext.binutils = "binutils-2.36"
|
ext.binutils = "binutils-2.41"
|
||||||
ext.binutilsDistro = "${binutils}.tar.bz2"
|
ext.binutilsDistro = "${binutils}.tar.bz2"
|
||||||
|
|
||||||
// Find the GPL dir
|
// Find the GPL dir
|
||||||
def gplDir = null;
|
def gplDir = null;
|
||||||
if (file("../utils.gradle").exists()) {
|
if (file("../utils.gradle").exists()) {
|
||||||
gplDir = file("..").getCanonicalPath()
|
gplDir = file("..").getCanonicalPath()
|
||||||
|
ext.ghidraInstallDir = file("../..").getCanonicalPath()
|
||||||
|
ext.binutilsLocation = file("${ghidraInstallDir}/../ghidra.bin/GPL/${name}").getCanonicalPath()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Module lives disconnected from the GPL directory, which it will need to build.
|
// Module lives disconnected from the GPL directory, which it will need to build.
|
||||||
// Find a Ghidra installation directory and use its GPL directory.
|
// Find a Ghidra installation directory and use its GPL directory.
|
||||||
|
ext.binutilsLocation = projectDir
|
||||||
if (file("../../Extensions").exists() && file("../../../GPL/utils.gradle").exists()) {
|
if (file("../../Extensions").exists() && file("../../../GPL/utils.gradle").exists()) {
|
||||||
// Module is installed within a Ghidra installation (i.e, ghidra/Ghidra/Extensions)
|
// Module is installed within a Ghidra installation (i.e, ghidra/Ghidra/Extensions)
|
||||||
gplDir = file("../../../GPL").getCanonicalPath()
|
gplDir = file("../../../GPL").getCanonicalPath()
|
||||||
|
|
|
@ -6,7 +6,7 @@ defaultTasks 'assemble'
|
||||||
|
|
||||||
ext.supportedPlatforms = ['mac_x86_64', 'mac_arm_64', 'linux_x86_64', 'linux_arm_64']
|
ext.supportedPlatforms = ['mac_x86_64', 'mac_arm_64', 'linux_x86_64', 'linux_arm_64']
|
||||||
|
|
||||||
ext.binutilsResource = new File("${projectDir}/${binutils}.tar.bz2")
|
ext.binutilsResource = new File("${binutilsLocation}/${binutils}.tar.bz2")
|
||||||
|
|
||||||
def binutilsUnpackDir = file("${project.buildDir}/${binutils}/")
|
def binutilsUnpackDir = file("${project.buildDir}/${binutils}/")
|
||||||
|
|
||||||
|
@ -37,8 +37,8 @@ model {
|
||||||
all {
|
all {
|
||||||
def binutilsArtifactsDir = file("build/binutils/${targetPlatform.name}")
|
def binutilsArtifactsDir = file("build/binutils/${targetPlatform.name}")
|
||||||
if ((toolChain in Gcc) || (toolChain in Clang)) {
|
if ((toolChain in Gcc) || (toolChain in Clang)) {
|
||||||
cCompiler.args "-I${binutilsArtifactsDir}/include", "-I${binutilsArtifactsDir}/bfd"
|
cCompiler.args "-I${binutilsArtifactsDir}/include", "-I${binutilsArtifactsDir}/bfd", "-I${binutilsArtifactsDir}/libsframe"
|
||||||
linker.args "-L${binutilsArtifactsDir}/lib", "-lopcodes", "-lbfd", "-liberty", "-lz", "-ldl"
|
linker.args "-L${binutilsArtifactsDir}/lib", "-lopcodes", "-lbfd", "-lsframe", "-liberty", "-lz", "-ldl"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,9 +151,10 @@ supportedPlatforms.each { platform ->
|
||||||
include "**/*.h"
|
include "**/*.h"
|
||||||
}
|
}
|
||||||
into("/lib") {
|
into("/lib") {
|
||||||
from "${configDir}/bfd/libbfd.a"
|
from "${configDir}/bfd/.libs/libbfd.a"
|
||||||
from "${configDir}/libiberty/libiberty.a"
|
from "${configDir}/libiberty/libiberty.a"
|
||||||
from "${configDir}/opcodes/libopcodes.a"
|
from "${configDir}/opcodes/libopcodes.a"
|
||||||
|
from "${configDir}/libsframe/.libs/libsframe.a"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
##MODULE IP: Public Domain
|
##MODULE IP: Public Domain
|
||||||
.gitignore||Public Domain||||END|
|
.gitignore||Public Domain||||END|
|
||||||
Module.manifest||Public Domain||||END|
|
Module.manifest||Public Domain||||END|
|
||||||
README.txt||Public Domain||||END|
|
README.md||GHIDRA||||END|
|
||||||
data/arm_test1.s||Public Domain||||END|
|
data/arm_test1.s||Public Domain||||END|
|
||||||
data/big.elf||Public Domain||||END|
|
data/big.elf||Public Domain||||END|
|
||||||
data/little.elf||Public Domain||||END|
|
data/little.elf||Public Domain||||END|
|
||||||
|
|
|
@ -45,8 +45,7 @@ void listSupportedArchMachTargets(void)
|
||||||
int objdump_sprintf (SFILE *f, const char *format, ...)
|
int objdump_sprintf (SFILE *f, const char *format, ...)
|
||||||
{
|
{
|
||||||
|
|
||||||
int i;
|
int n;
|
||||||
size_t n;
|
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
va_start (args, format);
|
va_start (args, format);
|
||||||
|
@ -57,6 +56,18 @@ int objdump_sprintf (SFILE *f, const char *format, ...)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compatibility fix for binutils v 2.39 change to INIT_DISASSEMLE_INFO signature */
|
||||||
|
int objdump_sprintf_styled(SFILE *f, enum disassembler_style style, const char *format, ...) {
|
||||||
|
int n;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start (args, format);
|
||||||
|
n = vsnprintf (f->buffer + f->pos, BUFF_SIZE, format, args);
|
||||||
|
strncat(disassembled_buffer, f->buffer, n);
|
||||||
|
va_end (args);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
void configureDisassembleInfo(bfd* abfd,
|
void configureDisassembleInfo(bfd* abfd,
|
||||||
disassemble_info* info,
|
disassemble_info* info,
|
||||||
|
@ -67,7 +78,7 @@ void configureDisassembleInfo(bfd* abfd,
|
||||||
|
|
||||||
memset(sfile.buffer, 0x00, BUFF_SIZE);
|
memset(sfile.buffer, 0x00, BUFF_SIZE);
|
||||||
|
|
||||||
INIT_DISASSEMBLE_INFO(*info, stdout, objdump_sprintf);
|
INIT_DISASSEMBLE_INFO(*info, stdout, objdump_sprintf, objdump_sprintf_styled);
|
||||||
info->arch = (enum bfd_architecture) arch;
|
info->arch = (enum bfd_architecture) arch;
|
||||||
info->mach = mach;
|
info->mach = mach;
|
||||||
info->flavour = bfd_get_flavour(abfd);
|
info->flavour = bfd_get_flavour(abfd);
|
||||||
|
|
|
@ -52,6 +52,16 @@ model {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (isCurrentFreeBSD()) {
|
||||||
|
gcc(Gcc) {
|
||||||
|
if (isCurrentArm_64()) {
|
||||||
|
target("freebsd_arm_64")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
target("freebsd_x86_64")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (isCurrentWindows() && VISUAL_STUDIO_INSTALL_DIR) {
|
if (isCurrentWindows() && VISUAL_STUDIO_INSTALL_DIR) {
|
||||||
// specify installDir because Gradle doesn't find VS Build Tools.
|
// specify installDir because Gradle doesn't find VS Build Tools.
|
||||||
// See https://github.com/gradle/gradle-native/issues/617#issuecomment-575735288
|
// See https://github.com/gradle/gradle-native/issues/617#issuecomment-575735288
|
||||||
|
|
|
@ -24,7 +24,9 @@ project.ext.PLATFORMS = [
|
||||||
[name: "linux_x86_64", os: "linux", arch: "x86_64"],
|
[name: "linux_x86_64", os: "linux", arch: "x86_64"],
|
||||||
[name: "linux_arm_64", os: "linux", arch: "arm64"],
|
[name: "linux_arm_64", os: "linux", arch: "arm64"],
|
||||||
[name: "mac_x86_64", os: "osx", arch: "x86_64"],
|
[name: "mac_x86_64", os: "osx", arch: "x86_64"],
|
||||||
[name: "mac_arm_64", os: "osx", arch: "arm64"]
|
[name: "mac_arm_64", os: "osx", arch: "arm64"],
|
||||||
|
[name: "freebsd_x86_64", os: "freebsd", arch: "x86_64"],
|
||||||
|
[name: "freebsd_arm_64", os: "freebsd", arch: "arm64"]
|
||||||
]
|
]
|
||||||
|
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
|
@ -51,6 +53,9 @@ ext.getCurrentPlatformName = {
|
||||||
case ~/Mac OS X.*/:
|
case ~/Mac OS X.*/:
|
||||||
os = "mac"
|
os = "mac"
|
||||||
break
|
break
|
||||||
|
case ~/FreeBSD.*/:
|
||||||
|
os = "freebsd"
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
throw new GradleException("Unrecognized platform operating system: $os")
|
throw new GradleException("Unrecognized platform operating system: $os")
|
||||||
}
|
}
|
||||||
|
@ -112,6 +117,20 @@ ext.isCurrentMac = {
|
||||||
return isMac(getCurrentPlatformName())
|
return isMac(getCurrentPlatformName())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************
|
||||||
|
* Returns true if the given platform is FreeBSD.
|
||||||
|
*********************************************************************************/
|
||||||
|
ext.isFreeBSD = { platform_name ->
|
||||||
|
return platform_name.startsWith("freebsd")
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************
|
||||||
|
* Returns true if the current platform is FreeBSD.
|
||||||
|
*********************************************************************************/
|
||||||
|
ext.isCurrentFreeBSD = {
|
||||||
|
return isFreeBSD(getCurrentPlatformName())
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
* Returns true if the given platform is Windows.
|
* Returns true if the given platform is Windows.
|
||||||
*********************************************************************************/
|
*********************************************************************************/
|
||||||
|
|
|
@ -27,12 +27,14 @@ def configureVisualStudio() {
|
||||||
|
|
||||||
// Use vswhere.exe to search for latest Visual Studio installation
|
// Use vswhere.exe to search for latest Visual Studio installation
|
||||||
println "Searching for latest Visual Studio and required components..."
|
println "Searching for latest Visual Studio and required components..."
|
||||||
def vswherePath = "C:\\Program Files (x86)\\Microsoft Visual Studio\\Installer\\vswhere.exe"
|
def programFiles = System.getenv()["ProgramFiles(x86)"] ?: "C:\\Program Files (x86)"
|
||||||
|
def vswherePath = findProperty("vswherePath") ?: "${programFiles}\\Microsoft Visual Studio\\Installer\\vswhere.exe"
|
||||||
if (!file(vswherePath).exists()) {
|
if (!file(vswherePath).exists()) {
|
||||||
println " -> Visual Studio vswhere.exe not found!"
|
println " -> Visual Studio vswhere.exe not found at \"${vswherePath}\""
|
||||||
|
println " -> To manually specify the location of vswhere.exe, add \"-PvswherePath=<vswhere path>\" to the Gradle command line arguments"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
def vswhereProcess = "${vswherePath} -products * -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -format json -utf8".execute()
|
def vswhereProcess = "\"${vswherePath}\" -products * -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -format json -utf8".execute()
|
||||||
def vswhereOutput = vswhereProcess.text.trim()
|
def vswhereOutput = vswhereProcess.text.trim()
|
||||||
def vswhereExit = vswhereProcess.exitValue()
|
def vswhereExit = vswhereProcess.exitValue()
|
||||||
if (vswhereExit != 0) {
|
if (vswhereExit != 0) {
|
||||||
|
@ -58,8 +60,6 @@ def configureVisualStudio() {
|
||||||
def vcvarsPath = "${vsInstallDir}\\VC\\Auxiliary\\Build\\vcvarsall.bat"
|
def vcvarsPath = "${vsInstallDir}\\VC\\Auxiliary\\Build\\vcvarsall.bat"
|
||||||
def vcvarsCmd = "\"${vcvarsPath}\" x86_amd64"
|
def vcvarsCmd = "\"${vcvarsPath}\" x86_amd64"
|
||||||
def vcvarsEnvCmd = "cmd /v:ON /c ${vcvarsCmd} > nul && cmd /c echo"
|
def vcvarsEnvCmd = "cmd /v:ON /c ${vcvarsCmd} > nul && cmd /c echo"
|
||||||
def toolsVersion = "${vcvarsEnvCmd} !VCToolsVersion!".execute().text.trim()
|
|
||||||
println " -> VCTools Version (default): ${toolsVersion}"
|
|
||||||
def sdkDir = "${vcvarsEnvCmd} !WindowsSdkDir!".execute().text.trim()
|
def sdkDir = "${vcvarsEnvCmd} !WindowsSdkDir!".execute().text.trim()
|
||||||
println " -> SDK Directory (default): ${sdkDir}"
|
println " -> SDK Directory (default): ${sdkDir}"
|
||||||
def sdkVersion = "${vcvarsEnvCmd} !WindowsSDKVersion!".execute().text.trim().replace('\\', '')
|
def sdkVersion = "${vcvarsEnvCmd} !WindowsSDKVersion!".execute().text.trim().replace('\\', '')
|
||||||
|
@ -71,7 +71,6 @@ def configureVisualStudio() {
|
||||||
|
|
||||||
// Save Visual Studio information so other projects can access it
|
// Save Visual Studio information so other projects can access it
|
||||||
rootProject.ext.VISUAL_STUDIO_INSTALL_DIR = vsInstallDir
|
rootProject.ext.VISUAL_STUDIO_INSTALL_DIR = vsInstallDir
|
||||||
rootProject.ext.VISUAL_STUDIO_TOOLS_VERSION_DEFAULT = toolsVersion
|
|
||||||
rootProject.ext.VISUAL_STUDIO_SDK_DIR_DEFAULT = sdkDir
|
rootProject.ext.VISUAL_STUDIO_SDK_DIR_DEFAULT = sdkDir
|
||||||
rootProject.ext.VISUAL_STUDIO_SDK_VERSION_DEFAULT = sdkVersion
|
rootProject.ext.VISUAL_STUDIO_SDK_VERSION_DEFAULT = sdkVersion
|
||||||
rootProject.ext.VISUAL_STUDIO_SDK_VERSION_OVERRIDE = windowsTargetPlatformVersion
|
rootProject.ext.VISUAL_STUDIO_SDK_VERSION_OVERRIDE = windowsTargetPlatformVersion
|
||||||
|
|
1
Ghidra/Configurations/Public_Release/README.md
Normal file
1
Ghidra/Configurations/Public_Release/README.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# Public_Release
|
|
@ -17,5 +17,12 @@ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
|
||||||
apply from: "$rootProject.projectDir/gradle/javaProject.gradle"
|
apply from: "$rootProject.projectDir/gradle/javaProject.gradle"
|
||||||
apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle"
|
apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle"
|
||||||
apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
||||||
|
apply from: "$rootProject.projectDir/gradle/helpProject.gradle"
|
||||||
apply plugin: 'eclipse'
|
apply plugin: 'eclipse'
|
||||||
eclipse.project.name = 'Z Public Release'
|
eclipse.project.name = 'Z Public Release'
|
||||||
|
|
||||||
|
rootProject.assembleDistribution {
|
||||||
|
from ("${this.projectDir}/src/main/resources/UserAgreement.html") {
|
||||||
|
into "docs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
##VERSION: 2.0
|
##VERSION: 2.0
|
||||||
Module.manifest||GHIDRA||||END|
|
Module.manifest||GHIDRA||||END|
|
||||||
|
README.md||GHIDRA||||END|
|
||||||
data/PDB_SYMBOL_SERVER_URLS.pdburl||GHIDRA||||END|
|
data/PDB_SYMBOL_SERVER_URLS.pdburl||GHIDRA||||END|
|
||||||
src/global/docs/ChangeHistory.html||GHIDRA||||END|
|
src/global/docs/ChangeHistory.md||GHIDRA||||END|
|
||||||
src/global/docs/UserAgreement.html||GHIDRA||||END|
|
src/global/docs/UserAgreement.html||GHIDRA||||END|
|
||||||
src/global/docs/WhatsNew.html||GHIDRA||||END|
|
src/global/docs/WhatsNew.md||GHIDRA||||END|
|
||||||
src/main/resources/UserAgreement.html||GHIDRA||||END|
|
src/main/resources/UserAgreement.html||GHIDRA||||END|
|
||||||
src/main/resources/defaultTools/CodeBrowser.tool||GHIDRA||||END|
|
src/main/resources/defaultTools/CodeBrowser.tool||GHIDRA||||END|
|
||||||
src/main/resources/splash.txt||GHIDRA||||END|
|
src/main/resources/splash.txt||GHIDRA||||END|
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
Internet|https://msdl.microsoft.com/download/symbols/|WARNING: Check your organization's security policy before downloading files from the internet.
|
Internet|https://msdl.microsoft.com/download/symbols/|WARNING: Check your organization's security policy before downloading files from the internet.
|
||||||
Internet|https://chromium-browser-symsrv.commondatastorage.googleapis.com|WARNING: Check your organization's security policy before downloading files from the internet.
|
Internet|https://chromium-browser-symsrv.commondatastorage.googleapis.com|WARNING: Check your organization's security policy before downloading files from the internet.
|
||||||
Internet|https://symbols.mozilla.org/|WARNING: Check your organization's security policy before downloading files from the internet.
|
Internet|https://symbols.mozilla.org/|WARNING: Check your organization's security policy before downloading files from the internet.
|
||||||
Internet|https://software.intel.com/sites/downloads/symbols/|WARNING: Check your organization's security policy before downloading files from the internet.
|
|
||||||
Internet|https://driver-symbols.nvidia.com/|WARNING: Check your organization's security policy before downloading files from the internet.
|
|
||||||
Internet|https://download.amd.com/dir/bin|WARNING: Check your organization's security policy before downloading files from the internet.
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,20 +0,0 @@
|
||||||
<HTML>
|
|
||||||
|
|
||||||
<FONT SIZE="5">
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License"); 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.
|
|
||||||
<BR>
|
|
||||||
<BR>
|
|
||||||
<B>As a software reverse engineering (SRE) framework, Ghidra is designed solely to facilitate
|
|
||||||
lawful SRE activities. You should always ensure that any SRE activities in which you engage are
|
|
||||||
permissible as computer software may be protected under governing law (e.g., copyright) or under an
|
|
||||||
applicable licensing agreement. In making Ghidra available for public use, the National Security
|
|
||||||
Agency does not condone or encourage any improper usage of Ghidra. Consistent with the Apache 2.0
|
|
||||||
license under which Ghidra has been made available, you are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing Ghidra.</B>
|
|
||||||
|
|
||||||
</FONT>
|
|
||||||
</HTML>
|
|
|
@ -1,244 +0,0 @@
|
||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
||||||
|
|
||||||
<HTML>
|
|
||||||
<HEAD>
|
|
||||||
<TITLE> Ghidra What's New</TITLE>
|
|
||||||
<STYLE type="text/css" name="text/css">
|
|
||||||
li { font-family:times new roman; font-size:14pt; font-family:times new roman; font-size:14pt; margin-bottom: 8px; }
|
|
||||||
h1 { color:#000080; font-family:times new roman; font-size:28pt; font-style:italic; font-weight:bold; text-align:center; color:#000080; font-family:times new roman; }
|
|
||||||
h2 { padding-top:10px; color:#984c4c; font-family:times new roman; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
|
|
||||||
h3 { margin-left:40px; padding-top:10px; font-family:times new roman; font-family:times new roman; font-size:14pt; font-weight:bold; }
|
|
||||||
h4 { margin-left:40px; padding-top:10px; font-family:times new roman; font-family:times new roman; font-size:14pt; font-weight:bold; }
|
|
||||||
p { margin-left:40px; font-family:times new roman; font-size:14pt; }
|
|
||||||
table, th, td { border: 1px solid black; border-collapse: collapse; font-size:10pt; }
|
|
||||||
td { font-family:times new roman; font-size:14pt; padding-left:10px; padding-right:10px; text-align:left; vertical-align:top; }
|
|
||||||
th { font-family:times new roman; font-size:14pt; font-weight:bold; padding-left:10px; padding-right:10px; text-align:left; }
|
|
||||||
code { color:black; font-family:courier new; font-size: 12pt; }
|
|
||||||
span.code { font-family:courier new font-size: 14pt; color:#000000; }
|
|
||||||
</STYLE>
|
|
||||||
</HEAD>
|
|
||||||
|
|
||||||
<BODY>
|
|
||||||
|
|
||||||
<H1>Ghidra: NSA Reverse Engineering Software</H2>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
Ghidra is a software reverse engineering (SRE) framework developed by NSA's Research Directorate.
|
|
||||||
This framework includes a suite of full-featured, high-end software analysis tools that enable
|
|
||||||
users to analyze compiled code on a variety of platforms including Windows, MacOS, and Linux.
|
|
||||||
Capabilities include disassembly, assembly, decompilation, debugging, emulation, graphing, and scripting, along with
|
|
||||||
hundreds of other features. Ghidra supports a wide variety of processor instruction sets and
|
|
||||||
executable formats and can be run in both user-interactive and automated modes. Users may also
|
|
||||||
develop their own Ghidra plug-in components and/or scripts using the exposed API. In addition there are
|
|
||||||
numerous ways to extend Ghidra such as new processors, loaders/exporters, automated analyzers,
|
|
||||||
and new visualizations.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
In support of NSA's Cybersecurity mission, Ghidra was built to solve scaling and teaming problems
|
|
||||||
on complex SRE efforts and to provide a customizable and extensible SRE research platform. NSA
|
|
||||||
has applied Ghidra SRE capabilities to a variety of problems that involve analyzing malicious
|
|
||||||
code and generating deep insights for NSA analysts who seek a better understanding of potential
|
|
||||||
vulnerabilities in networks and systems.
|
|
||||||
</P>
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<H1>What's New in Ghidra 10.2</H1>
|
|
||||||
|
|
||||||
<H2>The not-so-fine print: Please Read!</H2>
|
|
||||||
|
|
||||||
<P>Ghidra 10.2 is fully backward compatible with project data from previous releases. However, programs and data type archives
|
|
||||||
which are created or modified in 10.2 will not be useable by an earlier Ghidra version.</P>
|
|
||||||
|
|
||||||
<P>This release includes many new features and capabilities, performance improvements, quite a few bug fixes, and many pull-request
|
|
||||||
contributions. Thanks to all those who have contributed their time, thoughts, and code. The Ghidra user community
|
|
||||||
thanks you too!</P>
|
|
||||||
|
|
||||||
<P>IMPORTANT: Ghidra requires Java 17 JDK to run. A newer version of Java may be acceptable, but has not been tested. Please see the
|
|
||||||
<a href="InstallationGuide.html">Ghidra Installation Guide</a> for additional information.</P>
|
|
||||||
|
|
||||||
<P>NOTE: Please note that any programs imported with a Ghidra beta versions or code built directly from source outside of a release tag may not be compatible
|
|
||||||
and may have flaws that have been corrected. Any programs analyzed from a beta or other local master source build should be considered experimental and
|
|
||||||
re-imported and analyzed with a release version. As an example, Ghidra 10.1 beta had an import flaw affecting symbol demangling that was not correctable.
|
|
||||||
Programs imported with previous release versions should upgrade correctly through various automatic upgrade mechanisms. Any program
|
|
||||||
you will continue to reverse engineer should be imported fresh with a release version or a build you trust with the latest code fixes.</P>
|
|
||||||
|
|
||||||
<P>NOTE: Ghidra Server: The Ghidra 10.2 server is compatible with Ghidra 9.2 and later Ghidra clients. Ghidra 10.2
|
|
||||||
clients are compatible with all 10.x and 9.x servers.</P>
|
|
||||||
|
|
||||||
<P>NOTE: Platform-specific native executables can be built directly from a release distribution.
|
|
||||||
The distribution currently provides Linux 64-bit, Windows 64-bit, and MacOS x86 binaries. If you have another platform,
|
|
||||||
for example a MacOS M1 based system or a Linux variant, the support/buildNatives script can build the Decompiler,
|
|
||||||
demangler, and legacy PDB executables for your plaform. Please see "Building Ghidra Native Components" section in the
|
|
||||||
the <a href="InstallationGuide.html#Build">Ghidra Installation Guide</a> for additional information.</P>
|
|
||||||
|
|
||||||
<H2>Distribution</H2>
|
|
||||||
|
|
||||||
<P> A Software Bill of Materials (SBOM) is now included in the Ghidra release. The SBOM follows the CycloneDX standard,
|
|
||||||
and can be used with tools such as Dependency-Track to help identify risk in the software supply-chain.</P>
|
|
||||||
|
|
||||||
<H2>Debugger</H2>
|
|
||||||
|
|
||||||
<P>The Debugger improvement highlights include:</P>
|
|
||||||
<blockquote>
|
|
||||||
<ul>
|
|
||||||
<li>FlatDebuggerAPI is introduced, providing a scripting API for Java-based GhidraScripts. An example <I>DemoDebuggerScript.java</I>
|
|
||||||
is included to get started.</li>
|
|
||||||
<li>P-code Emulation is improved, including numerous fixes, a new framework for system calls in emulation scripts, and a
|
|
||||||
prototype taint analyzer.</li>
|
|
||||||
<li>Compatibility is improved, including support for GDB versions 8.0.1 through 12.1, and LLDB version 14.0.</li>
|
|
||||||
<li>Support for memory/register editing is improved in Registers, Dynamic Listing, Memory, and Watches panels.</li>
|
|
||||||
<li>A new Frida connector is introduced, including support for debugging using Frida on USB/remote devices.</li>
|
|
||||||
</ul>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<H2>Decompiler</H2>
|
|
||||||
<P>The Decompiler has a myriad of improvements in the latest-release. Many have been long-requested features or improvements.
|
|
||||||
Highlights of the changes include:</P>
|
|
||||||
<blockquote>
|
|
||||||
<ul>
|
|
||||||
<li>Support for union data-types. The Decompiler scores and displays the most likely field based on how code accesses the union. Alternately, a field access can be set manually.</li>
|
|
||||||
<li>Support for pointers with an offset relative to the start of a data type, usually a structure. Examples include windows LIST_ENTRY/CONTAINING_RECORD linked lists,
|
|
||||||
CString allocation data, and memory allocation records.</li>
|
|
||||||
<li>Support for pointers with a specified address space. Useful for targeting a specific address space such as SPI memory or
|
|
||||||
in Harvard architectures with multiple address spaces.</li>
|
|
||||||
<li>Improved reconciliation of overlapping views of data-types; for example, passing of sub members of a structure to a function.</li>
|
|
||||||
<li>Marker Margins, similar to the listing marker margins, have been added to display things like Debugger breakpoints.</li>
|
|
||||||
<li>A colored highlighting service has been added, allowing clients to create highlights in the form of background colors for syntax tokens in
|
|
||||||
the Decompiler UI through API calls.</li>
|
|
||||||
<li>Read-from and write-to access to a volatile variable now display as simple assignments, with a special token color, instead of as read- or write-volatile function calls.</li>
|
|
||||||
</ul>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<H2>Data Types</H2>
|
|
||||||
|
|
||||||
<P>With this release of Ghidra, support for Pointer Typedefs has been expanded to facilitate the use of specialized
|
|
||||||
data type settings. Improvements have also been made to ensure that such settings are preserved within data type
|
|
||||||
archives and merge situations. These settings are not supported at the instance-level and are intended to be an
|
|
||||||
attribute of the associated pointer. The Typedef provides the ability to tailor a pointer for a specific use. It
|
|
||||||
is highly recommended that all required Pointer Typedef settings be applied prior to using the data type
|
|
||||||
(e.g., for defined data, data type components, and variables) since there is currently no change propagation for such modifications.
|
|
||||||
|
|
||||||
<P>The following Pointer Typedef settings have been introduced with this release:</p>
|
|
||||||
<blockquote>
|
|
||||||
<ul>
|
|
||||||
<li> <B>Address Space</B> - allows the destination address space to be specified for a pointer. While this does not affect pointer dereferencing operations
|
|
||||||
dictated by instruction semantics, it can aid analysis and the generation of associated memory references.</li>
|
|
||||||
<li><B>Component Offset</B> - provides the ability to specify an offset relative to the associated pointer's referenced data type such that:
|
|
||||||
<blockquote>
|
|
||||||
<code><referenced-data-type-storage-address> = <pointer-offset> - <component-offset-setting></code>
|
|
||||||
</blockquote>
|
|
||||||
</li>
|
|
||||||
<li><B>Offset Mask</B> - bit-mask to be applied prior to any bit-shift (if specified) during the computation of an actual address offset</li>
|
|
||||||
|
|
||||||
<li><B>Offset Shift</B> - bit-shift to be applied after any bit-mask (if specified) during the computation of an actual address
|
|
||||||
offset (positive: left-shift, negative: right-shift)</li>
|
|
||||||
|
|
||||||
<li><B>Pointer Type</B> - facilitates special interpretation of pointers</li>
|
|
||||||
|
|
||||||
<blockquote>
|
|
||||||
<ul>
|
|
||||||
<li> <I>default</I> - normal pointer</li>
|
|
||||||
<li> <I>image-base-relative</I> - pointers whose offset should be treated as relative to the program's image base (e.g., relative virtual address (RVA))</li>
|
|
||||||
|
|
||||||
<li> <I>relative</I> - pointers whose offset is relative to the pointer's storage address</li>
|
|
||||||
|
|
||||||
<li> <I>file-offset</I> - pointers whose offset corresponds to an offset within the loaded binary file (limited to single load file)</li>
|
|
||||||
</ul>
|
|
||||||
</blockquote>
|
|
||||||
</UL>
|
|
||||||
</blockquote>
|
|
||||||
|
|
||||||
<P> NOTE: The use and consumption of Pointer Typedef settings is in its early stages and may not be utilized by various analyzers.
|
|
||||||
In addition, some settings are not relevant to some analyzers where instruction semantics will dictate pointer dereferencing.</P>
|
|
||||||
|
|
||||||
<P> At the API level, the PointerTypedef and PointerTypedefBuilder classes have been added to simplify the creation of a Pointer Typedef.
|
|
||||||
While an explicit Typedef name may be used, Pointer Typedefs also support an auto-naming mechanism (constructed with a null/empty name)
|
|
||||||
which will simply use the pointer name followed by the settings as an attribute list; example:</P>
|
|
||||||
<blockquote><blockquote>
|
|
||||||
<code>int * __((space(ram)))</code>
|
|
||||||
</blockquote></blockquote>
|
|
||||||
|
|
||||||
<P> Within the GUI, using the <B>New->Typedef on <I><pointer></I></B> action on a selected pointer within the Data Type Tree is the quickest way to create one.
|
|
||||||
Once this is done, use the <B>Settings...</B> action on the selected Pointer Typedef. The Settings dialog will be displayed allowing the various settings
|
|
||||||
to be applied to the Typedef. Settings should be made to Typedef prior to applying it since settings change propogation is very limited.</P>
|
|
||||||
|
|
||||||
<H3>C Header File Parsing</H3>
|
|
||||||
|
|
||||||
<P>C-Parser support has been added for missing C specification syntax from C11 and C23, such as tags, macros with varargs, and _NoReturn.
|
|
||||||
Numerous parsing errors have also been fixed, including for arrays of function pointers, array definitions, and placement of compiler directives.
|
|
||||||
In addition, parsing time of extremely large header files has been drastically reduced.</P>
|
|
||||||
<P>Error handling and reporting from the Pre-Processor and C-Parser have been improved.</P>
|
|
||||||
<P>Several scripts to parse header files outside of the GUI have been included, including one that specially parses AVR8 data types and memory-mapped register
|
|
||||||
definitions from header files for each AVR8 processor variant. The scripts are <I>CreateAVR8GDTArchiveScript.java</I>, <I>CreateExampleGDTArchiveScript.java</I>, <I>CreateJNIArchivesScript.java</I>,
|
|
||||||
and <I>CreateDefaultGDTArchives.java</I>.</P>
|
|
||||||
<P> Finally, data types in open archives can be used during parsing for undefined data types in a header file. At the start of parsing, use of open
|
|
||||||
archives can be chosen or ignored without closing open archives. The header files must still parse without error,
|
|
||||||
however a missing data type or unfound header file may not cause the parsing to fail if an open archive contains a missing, but needed data type definition.</P>
|
|
||||||
|
|
||||||
|
|
||||||
<H2>Mach-O Binary Import</H2>
|
|
||||||
<P>Mach-O binary analysis continues to improve. Support has been added for new file formats introduced in iOS 16 and macOS 13.
|
|
||||||
Improvements have also been made to function identification, symbol detection, and Objective-C support.</P>
|
|
||||||
|
|
||||||
<H2>Android</H2>
|
|
||||||
|
|
||||||
<P>Import and analysis of the entire existing set of Android binaries up to version 13.x is now supported, including new support for the Multi-DEX format.
|
|
||||||
The type of binaries supported include: Android Run-Time (ART), Ahead-of-Time (OAT)/ELF, Dalvik Executables (DEX), Multi-DEX, Compact DEX (CDEX),
|
|
||||||
Verified DEX (VEX), Boot Image, and Boot Loader formats. Also included are Sleigh modules for DEX files covering each major release of Android;
|
|
||||||
the optimized instructions vary across versions.</P>
|
|
||||||
|
|
||||||
<P>A new Android APK loader will load all DEX files at one time and link the <code><B>method_lookup</B></code>
|
|
||||||
sections using <B>external references</B>. The new APK loader uses the manifest file to determine the Android version.</P>
|
|
||||||
|
|
||||||
<H2>Analysis</H2>
|
|
||||||
|
|
||||||
<P>The option <B>Assume Contiguous Functions Only</B>, for the <B>Shared Return Analyzer</B>, has been turned on by default.
|
|
||||||
The <B>Shared Return Analyzer</B> turns jump instructions into a call if the jump
|
|
||||||
target is, or should be, considered a function. When turned on, the option treats a jump
|
|
||||||
over a known function entry point to be a call, even if there is only one jump to that location. The option improves thunk function
|
|
||||||
recovery as well as decompilation results by using a call to the function instead of including the called functions code within the calling function.</P>
|
|
||||||
|
|
||||||
<P>The option has been turned on by default for all processor types except ARM. ARM Thumb binaries can sometimes use <B>BL</B> instructions,
|
|
||||||
normally used as calls, as an internal jump within a large function. If this option were on by default for such a binary it would cause
|
|
||||||
additional erroneous functions to be created. The option can be used on ARM binaries, however they should be all ARM code; otherwise any Thumb code
|
|
||||||
using <B>BL</B> for far jumps must be fixed using the Fix_ARM_Call_JumpsScript and Override_ARM_Call_JumpsScript.</P>
|
|
||||||
|
|
||||||
<H2>Machine Learning</H2>
|
|
||||||
<P>An optional MachineLearning extension has been added containing the <B>Random Forest Function Finder Plugin</B>.
|
|
||||||
The plugin finds undiscovered functions within a binary using classifiers to identify potential function starts.
|
|
||||||
The plugin trains classifiers using data sets created from known functions within a binary.
|
|
||||||
These classifiers can then be used by the plugin on the original binary or other binaries to find additional functions
|
|
||||||
missed by initial analysis.</P>
|
|
||||||
<P>The extension can be installed from the <B>Ghidra Project Window</B> via <B>File->Install Extensions...</B> </P>
|
|
||||||
|
|
||||||
<H2>Processors</H2>
|
|
||||||
<P>Updated ARM32 and AARCH64 to version v9.3 to include vfp4 instructions.</P>
|
|
||||||
<P>Improvements and bug fixes have been made to many processors to include: <B>AARCH64, ARM, AVR8, AVR32, Coldfire, JVM, MIPS, MSP430, PA-Risc, PowerPC,
|
|
||||||
RISC-V, SuperH, Tricore, V850, X86, 6502, and 68K</B>.</P>
|
|
||||||
<P> Sleigh now supports <code><B>inst_next2</B></code> as well as <code><B>inst_next</B></code> to support branching around the next instruction when its length is unknown.
|
|
||||||
Many processors have conditional skip instructions which can be used on any instruction, including another skip instruction.
|
|
||||||
Some sleigh processor developers have tried to use the delayslot() directive to accomplish instruction skipping. Unfortunately, the use of the delayslot() directive
|
|
||||||
can cause nested delay slots or the potential for branches into the delay slotted instruction, both of which are not supported.</P>
|
|
||||||
|
|
||||||
<H2>User Interface Improvements</H2>
|
|
||||||
<P>The <B>Go To...</B> dialog now provides navigation to file offsets. In addition, a new File Offset field is available in the Listing. The
|
|
||||||
field must be added to the Listing using Edit Listing Fields.
|
|
||||||
These new features can greatly simplify correlating bytes in program memory with their original location within the file from which they were imported.
|
|
||||||
Example: to go to the memory location which corresponds to the first byte in the original file, enter <B><code>file(0)</code></B> in the <B>Go To...</B> dialog.</P>
|
|
||||||
|
|
||||||
<H2>Import Formats</H2>
|
|
||||||
<P>Support has been added for loading WinDbg and APPORT dump files.</P>
|
|
||||||
<P>Redesigned the Importer's library loading options to provide finer-grained control over where libraries are searched
|
|
||||||
for on disk and in the project, as well as where newly loaded libraries are saved to.</P>
|
|
||||||
|
|
||||||
<H2>Additional Bug Fixes and Enhancements</H2>
|
|
||||||
<P> Numerous other bug fixes and improvements are fully listed in the <a href="ChangeHistory.html">ChangeHistory</a> file.</P>
|
|
||||||
|
|
||||||
<BR>
|
|
||||||
<P align="center">
|
|
||||||
<B><a href="https://www.nsa.gov/ghidra"> https://www.nsa.gov/ghidra</a></B>
|
|
||||||
</P>
|
|
||||||
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
118
Ghidra/Configurations/Public_Release/src/global/docs/WhatsNew.md
Normal file
118
Ghidra/Configurations/Public_Release/src/global/docs/WhatsNew.md
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
# What's New in Ghidra 11.2
|
||||||
|
This release includes new features, enhancements, performance improvements, quite a few bug fixes,
|
||||||
|
and many pull-request contributions. Thanks to all those who have contributed their time, thoughts,
|
||||||
|
and code. The Ghidra user community thanks you too!
|
||||||
|
|
||||||
|
### The not-so-fine print: Please Read!
|
||||||
|
Ghidra 11.2 is fully backward compatible with project data from previous releases. However, programs
|
||||||
|
and data type archives which are created or modified in 11.2 will not be usable by an earlier Ghidra
|
||||||
|
version.
|
||||||
|
|
||||||
|
__IMPORTANT:__ Ghidra 11.2 requires at minimum JDK 21 to run.
|
||||||
|
|
||||||
|
__IMPORTANT:__ To use the Debugger or do a full source distribution build, you will need Python3
|
||||||
|
(3.9 to 3.12 supported) installed on your system.
|
||||||
|
|
||||||
|
__NOTE:__ There have been reports of certain features causing the XWindows server to crash. A fix
|
||||||
|
for `CVE-2024-31083` in X.org software in April 2024 introduced a regression, which has been fixed
|
||||||
|
in xwayland 23.2.6 and xorg-server 21.1.13. If you experience any crashing of Ghidra, most likely
|
||||||
|
causing a full logout, check if your xorg-server has been updated to at least the noted version.
|
||||||
|
|
||||||
|
__NOTE:__ Each build distribution will include native components (e.g., decompiler) for at least one
|
||||||
|
platform (e.g., Windows x86-64). If you have another platform that is not included in the build
|
||||||
|
distribution, you can build native components for your platform directly from the distribution.
|
||||||
|
See the `Installation Guide` for additional information. Users running with older shared libraries
|
||||||
|
and operating systems (e.g., CentOS 7.x) may also run into compatibility errors when launching
|
||||||
|
native executables such as the Decompiler and GNU Demangler which may necessitate a rebuild of
|
||||||
|
native components.
|
||||||
|
|
||||||
|
__NOTE:__ Ghidra Server: The Ghidra 11.x server is compatible with Ghidra 9.2 and later Ghidra
|
||||||
|
clients. Ghidra 11.x clients are compatible with all 10.x and 9.x servers. Although, due to
|
||||||
|
potential Java version differences, it is recommended that Ghidra Server installations older than
|
||||||
|
10.2 be upgraded. Those using 10.2 and newer should not need a server upgrade.
|
||||||
|
|
||||||
|
__NOTE:__ Any programs imported with a Ghidra beta version or code built directly from source code
|
||||||
|
outside of a release tag may not be compatible, and may have flaws that won't be corrected by using
|
||||||
|
this new release. Any programs analyzed from a beta or other local master source build should be
|
||||||
|
considered experimental and re-imported and analyzed with a release version.
|
||||||
|
|
||||||
|
Programs imported with previous release versions should upgrade correctly through various automatic
|
||||||
|
upgrade mechanisms. However, there may be improvements or bug fixes in the import and analysis
|
||||||
|
process that will provide better results than prior Ghidra versions. You might consider comparing a
|
||||||
|
fresh import of any program you will continue to reverse engineer to see if the latest Ghidra
|
||||||
|
provides better results.
|
||||||
|
|
||||||
|
## Memory Search
|
||||||
|
The __Search Memory__ feature in Ghidra has been updated substantially to provide two new features:
|
||||||
|
* The ability to perform set operations on successive searches
|
||||||
|
* The ability to (re)scan memory for changes in value
|
||||||
|
|
||||||
|
Set operations, accessible from the pull-down menu under `Search`, allow you to augment results by
|
||||||
|
performing boolean operations on an existing search. For example, you might search for the hex
|
||||||
|
pattern `DE AD` using `Search`, add `BE EF` to the pattern field, and then select `A-B` to retrieve
|
||||||
|
a list of byte sequences that begin with `DE AD` but do not include `DE AD BE EF`. Scanning for
|
||||||
|
changes is most useful in a dynamic environment, such as the Debugger. Given an existing search,
|
||||||
|
you can look for values that have changed, increased, decreased, or remained the same. Simple
|
||||||
|
examples might include looking for counters while a process is running, checking for areas of
|
||||||
|
decompressed memory, or identifying active areas of the heap.
|
||||||
|
|
||||||
|
## PDB
|
||||||
|
The `PDB Symbol Server Search Config` dialog has been changed, allowing the user to mark symbol
|
||||||
|
servers as trusted or untrusted. This is an improvement over the previous mechanism that based trust
|
||||||
|
on the symbol server's connection type.
|
||||||
|
|
||||||
|
## Debugger
|
||||||
|
__ATTENTION:__ Please either delete and re-import the default `Emulator` tool, or manually remove
|
||||||
|
the `TraceRmiPlugin` from your EmulatorTool!
|
||||||
|
|
||||||
|
There are new launchers/features for the traceRMI version of dbgeng, including extended launch
|
||||||
|
options, kernel debugging, and remote process server connections.
|
||||||
|
|
||||||
|
## Decompiler
|
||||||
|
* The Decompiler can now automatically recover strings built on the stack and initial support for
|
||||||
|
optimized heap strings has been added. Stack strings are typically found in optimized code and
|
||||||
|
obfuscated malware.
|
||||||
|
|
||||||
|
* A new Search All action has been added which displays a table containing the results found within
|
||||||
|
the current function.
|
||||||
|
|
||||||
|
## Programming Languages
|
||||||
|
Golang support for versions `1.15` and `1.16` have been added. This brings the supported Golang
|
||||||
|
versions to `1.15` through `1.22`.
|
||||||
|
|
||||||
|
## Processors
|
||||||
|
* There have been quite a few improvements to the `Sparc` processor specification, including
|
||||||
|
additional instructions, 64-bit relocation support, and better handling of call/return detection
|
||||||
|
through tracking of the `o7` link register. In addition, the calling convention for both
|
||||||
|
sparc 32 and 64 bit binaries have had an overhaul to support hidden structure return and much
|
||||||
|
improved parameter allocation of floating point and general data types.
|
||||||
|
|
||||||
|
* The `Intel M16C/60/80` sleigh processor specifications have been added. In addition, there have
|
||||||
|
been numerous fixes to the `ARM`, `RX`, `M68000`, `PIC16`, `PPC`, and `x86` processor
|
||||||
|
specifications.
|
||||||
|
|
||||||
|
## Other Improvements
|
||||||
|
* Actions have been added to compare functions directly from the Listing, Decompiler, or Functions
|
||||||
|
Table via popup menu items. If there is already a Function Comparison window showing, there are
|
||||||
|
two actions: one to add the selected function(s) to the existing comparison, and one to create a
|
||||||
|
new Function Comparison Window. This allows a workflow where users can build up a set of functions
|
||||||
|
to compare as they browse around instead of having to select them all at once.
|
||||||
|
|
||||||
|
* For Ghidra script and plugin developers who would prefer to use Visual Studio Code, a new script
|
||||||
|
`VSCodeProjectScript.java` will create a new Visual Studio Code project that is setup to do Ghidra
|
||||||
|
scripting and module development. The capabilities are similar to the Eclipse GhidraDev plugin.
|
||||||
|
|
||||||
|
* There have been major speed improvements when creating or modifying large structures within the
|
||||||
|
structure editor. In general large structure manipulation should perform fluidly no matter the
|
||||||
|
size of the structure. If the structure contains a large number of defined data, there could
|
||||||
|
still be some degradation in speed. Some fixed performance issues include: resizing a structure
|
||||||
|
smaller or larger, clicking on an item to select a row, and defining a data type either with
|
||||||
|
keyboard actions or dragging and dropping from the data type manager. In addition, the behavior
|
||||||
|
of automatically growing the size of a structure has been made consistent. Defining data on the
|
||||||
|
last element of a structure is allowed to automatically grow the structure to fit the data type.
|
||||||
|
Defining data anywhere other than the last element isn't allowed if the data type does not fit
|
||||||
|
because of defined data that would need to be cleared, or there are not enough undefined bytes.
|
||||||
|
|
||||||
|
## Additional Bug Fixes and Enhancements
|
||||||
|
Numerous other new features, improvements, and bug fixes are fully listed in the
|
||||||
|
[Change History](ChangeHistory.html) file.
|
|
@ -1,4 +1,7 @@
|
||||||
<HTML>
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<TITLE>Ghidra User Agreement</TITLE>
|
||||||
|
</HEAD>
|
||||||
|
|
||||||
<FONT SIZE="5">
|
<FONT SIZE="5">
|
||||||
|
|
||||||
|
|
1
Ghidra/Debug/AnnotationValidator/README.md
Normal file
1
Ghidra/Debug/AnnotationValidator/README.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# AnnotationValidator
|
|
@ -1,3 +1,4 @@
|
||||||
##VERSION: 2.0
|
##VERSION: 2.0
|
||||||
Module.manifest||GHIDRA||||END|
|
Module.manifest||GHIDRA||||END|
|
||||||
|
README.md||GHIDRA||||END|
|
||||||
src/main/resources/META-INF/services/javax.annotation.processing.Processor||GHIDRA||||END|
|
src/main/resources/META-INF/services/javax.annotation.processing.Processor||GHIDRA||||END|
|
||||||
|
|
|
@ -20,13 +20,33 @@ import java.lang.annotation.Annotation;
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import javax.tools.Diagnostic.Kind;
|
import javax.tools.Diagnostic.Kind;
|
||||||
|
|
||||||
|
import ghidra.util.database.DBAnnotatedObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract class for validating annotations on {@link DBAnnotatedObject}.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Performs validation checks on annotated fields and their enclosing types.
|
||||||
|
*/
|
||||||
public class AbstractDBAnnotationValidator {
|
public class AbstractDBAnnotationValidator {
|
||||||
protected final ValidationContext ctx;
|
protected final ValidationContext ctx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new {@code AbstractDBAnnotationValidator} with the specified validation context.
|
||||||
|
*
|
||||||
|
* @param ctx the validation context
|
||||||
|
*/
|
||||||
public AbstractDBAnnotationValidator(ValidationContext ctx) {
|
public AbstractDBAnnotationValidator(ValidationContext ctx) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the enclosing type of the annotated field.
|
||||||
|
*
|
||||||
|
* @param annotType the type of the annotation being validated
|
||||||
|
* @param field the field being validated
|
||||||
|
* @param type the enclosing type of the field
|
||||||
|
*/
|
||||||
protected void checkEnclosingType(Class<? extends Annotation> annotType, VariableElement field,
|
protected void checkEnclosingType(Class<? extends Annotation> annotType, VariableElement field,
|
||||||
TypeElement type) {
|
TypeElement type) {
|
||||||
if (type.getKind() != ElementKind.CLASS) {
|
if (type.getKind() != ElementKind.CLASS) {
|
||||||
|
|
|
@ -19,6 +19,10 @@ import java.util.Set;
|
||||||
|
|
||||||
import javax.lang.model.element.Modifier;
|
import javax.lang.model.element.Modifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enum to represent different levels of access specifiers (private, package-private, protected,
|
||||||
|
* public) with corresponding access levels
|
||||||
|
*/
|
||||||
public enum AccessSpec {
|
public enum AccessSpec {
|
||||||
PRIVATE(0), PACKAGE(1), PROTECTED(2), PUBLIC(3);
|
PRIVATE(0), PACKAGE(1), PROTECTED(2), PUBLIC(3);
|
||||||
|
|
||||||
|
@ -29,7 +33,7 @@ public enum AccessSpec {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the second permits the same or more access than the first
|
* Check if the second permits the same or more access than the first
|
||||||
*
|
*
|
||||||
* @param first the first
|
* @param first the first
|
||||||
* @param second the second
|
* @param second the second
|
||||||
|
|
|
@ -22,14 +22,43 @@ import javax.tools.Diagnostic.Kind;
|
||||||
|
|
||||||
import ghidra.util.database.annot.DBAnnotatedColumn;
|
import ghidra.util.database.annot.DBAnnotatedColumn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class for validating fields annotated with {@link DBAnnotatedColumn}.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* To ensure fields annotated with {@link DBAnnotatedColumn} comply with the expected criteria for
|
||||||
|
* database columns in Ghidra.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
|
||||||
public class DBAnnotatedColumnValidator extends AbstractDBAnnotationValidator {
|
public class DBAnnotatedColumnValidator extends AbstractDBAnnotationValidator {
|
||||||
final VariableElement column;
|
final VariableElement column;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new {@code DBAnnotatedColumnValidator} with the specified validation context and
|
||||||
|
* the column element.
|
||||||
|
*
|
||||||
|
* @param ctx the validation context
|
||||||
|
* @param column the field representing the column
|
||||||
|
*/
|
||||||
public DBAnnotatedColumnValidator(ValidationContext ctx, VariableElement column) {
|
public DBAnnotatedColumnValidator(ValidationContext ctx, VariableElement column) {
|
||||||
super(ctx);
|
super(ctx);
|
||||||
this.column = column;
|
this.column = column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the annotated column field.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* It performs the following checks to ensure it meets the requirements for database columns:
|
||||||
|
* <ul>
|
||||||
|
* <li>The field must be of the type specified by {@code ctx.DB_OBJECT_COLUMN_ELEM}.</li>
|
||||||
|
* <li>The field must not be declared as {@code final}.</li>
|
||||||
|
* <li>The field must be declared as {@code static}.</li>
|
||||||
|
* <li>The enclosing type of the field must meet the criteria defined in
|
||||||
|
* {@code checkEnclosingType}.</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
public void validate() {
|
public void validate() {
|
||||||
if (!ctx.hasType(column, ctx.DB_OBJECT_COLUMN_ELEM)) {
|
if (!ctx.hasType(column, ctx.DB_OBJECT_COLUMN_ELEM)) {
|
||||||
ctx.messager.printMessage(Kind.ERROR,
|
ctx.messager.printMessage(Kind.ERROR,
|
||||||
|
|
|
@ -23,6 +23,14 @@ import javax.tools.Diagnostic.Kind;
|
||||||
|
|
||||||
import ghidra.util.database.annot.DBAnnotatedField;
|
import ghidra.util.database.annot.DBAnnotatedField;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class for validating fields annotated with {@link DBAnnotatedField}
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* To ensure fields annotated with {@link DBAnnotatedField} meet the criteria required for database
|
||||||
|
* fields in Ghidra. It extends the {@code AbstractDBAnnotationValidator} to provide additional
|
||||||
|
* validation logic specific to database field annotations.
|
||||||
|
*/
|
||||||
public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
||||||
final VariableElement field;
|
final VariableElement field;
|
||||||
final Map<TypeMirror, TypeElement> javaToDBTypeMap;
|
final Map<TypeMirror, TypeElement> javaToDBTypeMap;
|
||||||
|
@ -39,6 +47,13 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
||||||
|
|
||||||
final TypeElement ENUM_CODEC_ELEM;
|
final TypeElement ENUM_CODEC_ELEM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new {@code DBAnnotatedFieldValidator} with the specified validation context and
|
||||||
|
* field element.
|
||||||
|
*
|
||||||
|
* @param ctx the validation context
|
||||||
|
* @param field the field to validate
|
||||||
|
*/
|
||||||
public DBAnnotatedFieldValidator(ValidationContext ctx, VariableElement field) {
|
public DBAnnotatedFieldValidator(ValidationContext ctx, VariableElement field) {
|
||||||
super(ctx);
|
super(ctx);
|
||||||
this.field = field;
|
this.field = field;
|
||||||
|
@ -59,6 +74,13 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
||||||
ENUM_CODEC_ELEM = ctx.elementUtils.getTypeElement(ENUM_CODEC_NAME);
|
ENUM_CODEC_ELEM = ctx.elementUtils.getTypeElement(ENUM_CODEC_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associate a primitive type and its boxed type with the specified codec type in the map.
|
||||||
|
*
|
||||||
|
* @param map the map linking java types to their corresponding codec types
|
||||||
|
* @param kind the primitive type kind
|
||||||
|
* @param codecName the fully qualified name of the codec type
|
||||||
|
*/
|
||||||
protected void putPrimitiveTypeCodec(Map<TypeMirror, TypeElement> map, TypeKind kind,
|
protected void putPrimitiveTypeCodec(Map<TypeMirror, TypeElement> map, TypeKind kind,
|
||||||
String codecName) {
|
String codecName) {
|
||||||
PrimitiveType primitive = ctx.typeUtils.getPrimitiveType(kind);
|
PrimitiveType primitive = ctx.typeUtils.getPrimitiveType(kind);
|
||||||
|
@ -68,12 +90,26 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
||||||
map.put(boxed, codec);
|
map.put(boxed, codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associate a specified class type with the specified codec type in the map.
|
||||||
|
*
|
||||||
|
* @param map the map linking Java types to their corresponding codec types
|
||||||
|
* @param cls the class type
|
||||||
|
* @param codecName the fully qualified name of the codec type
|
||||||
|
*/
|
||||||
protected void putTypeCodec(Map<TypeMirror, TypeElement> map, Class<?> cls, String codecName) {
|
protected void putTypeCodec(Map<TypeMirror, TypeElement> map, Class<?> cls, String codecName) {
|
||||||
TypeMirror type = ctx.elementUtils.getTypeElement(cls.getCanonicalName()).asType();
|
TypeMirror type = ctx.elementUtils.getTypeElement(cls.getCanonicalName()).asType();
|
||||||
TypeElement codec = ctx.elementUtils.getTypeElement(codecName);
|
TypeElement codec = ctx.elementUtils.getTypeElement(codecName);
|
||||||
map.put(type, codec);
|
map.put(type, codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associate a primitive array type with the specified codec type inthe map.
|
||||||
|
*
|
||||||
|
* @param map the map linking Java types to their corresponding codec types
|
||||||
|
* @param kind the primitive type kind
|
||||||
|
* @param codecName the fully qualified name of the codec type
|
||||||
|
*/
|
||||||
protected void putPrimitiveArrayTypeCodec(Map<TypeMirror, TypeElement> map, TypeKind kind,
|
protected void putPrimitiveArrayTypeCodec(Map<TypeMirror, TypeElement> map, TypeKind kind,
|
||||||
String codecName) {
|
String codecName) {
|
||||||
PrimitiveType primitive = ctx.typeUtils.getPrimitiveType(kind);
|
PrimitiveType primitive = ctx.typeUtils.getPrimitiveType(kind);
|
||||||
|
@ -82,6 +118,19 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
||||||
map.put(array, codec);
|
map.put(array, codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the annotated field to ensure it meets the requirements for database fields.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* It performs the following checks:
|
||||||
|
* <ul>
|
||||||
|
* <li>The field must not be declared as {@code final}.</li>
|
||||||
|
* <li>The field must not be declared as {@code static}.</li>
|
||||||
|
* <li>The enclosing type of the field must meet the criteria defined in
|
||||||
|
* {@code checkEnclosingType}.</li>
|
||||||
|
* <li>The codec types for the field must be appropriate.</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
public void validate() {
|
public void validate() {
|
||||||
Set<Modifier> mods = field.getModifiers();
|
Set<Modifier> mods = field.getModifiers();
|
||||||
if (mods.contains(Modifier.FINAL)) {
|
if (mods.contains(Modifier.FINAL)) {
|
||||||
|
@ -101,6 +150,12 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
||||||
checkCodecTypes(type);
|
checkCodecTypes(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the default codec type element for the specified Java type.
|
||||||
|
*
|
||||||
|
* @param javaType the Java type for which the default codec is needed
|
||||||
|
* @return the default codec type element, or {@code null} if no default codec is found
|
||||||
|
*/
|
||||||
protected TypeElement getDefaultCodecType(TypeMirror javaType) {
|
protected TypeElement getDefaultCodecType(TypeMirror javaType) {
|
||||||
if (ctx.isEnumType(javaType)) {
|
if (ctx.isEnumType(javaType)) {
|
||||||
return ENUM_CODEC_ELEM;
|
return ENUM_CODEC_ELEM;
|
||||||
|
@ -108,6 +163,12 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
||||||
return javaToDBTypeMap.get(javaType);
|
return javaToDBTypeMap.get(javaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the codec type element specified in the {@link DBAnnotatedField} annotation for the
|
||||||
|
* field, or the default codec type if none is specified.
|
||||||
|
*
|
||||||
|
* @return the codec type element for the field
|
||||||
|
*/
|
||||||
protected TypeElement getCodecTypeElement() {
|
protected TypeElement getCodecTypeElement() {
|
||||||
DBAnnotatedField annotation = field.getAnnotation(DBAnnotatedField.class);
|
DBAnnotatedField annotation = field.getAnnotation(DBAnnotatedField.class);
|
||||||
TypeElement codecElem;
|
TypeElement codecElem;
|
||||||
|
@ -123,6 +184,12 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
||||||
return codecElem;
|
return codecElem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the codec types associated with the field to ensure they meet the necessary
|
||||||
|
* requirements.
|
||||||
|
*
|
||||||
|
* @param objectType the type of the enclosing object
|
||||||
|
*/
|
||||||
protected void checkCodecTypes(TypeElement objectType) {
|
protected void checkCodecTypes(TypeElement objectType) {
|
||||||
|
|
||||||
TypeElement codecType = getCodecTypeElement();
|
TypeElement codecType = getCodecTypeElement();
|
||||||
|
|
|
@ -29,8 +29,10 @@ import ghidra.util.database.annot.*;
|
||||||
/**
|
/**
|
||||||
* A compile-time annotation processor for {@link DBAnnotatedObject}-related annotations.
|
* A compile-time annotation processor for {@link DBAnnotatedObject}-related annotations.
|
||||||
*
|
*
|
||||||
* Currently just performs compile-time checks. It does not generate any code, but perhaps one day,
|
* <p>
|
||||||
* it will.
|
* This processor performs compile-time validation checks on annotations related to
|
||||||
|
* {@link DBAnnotatedObject}. Currently just performs compile-time checks. It does not generate any
|
||||||
|
* code, but perhaps one day, it will.
|
||||||
*/
|
*/
|
||||||
//@AutoService(Processor.class) // TODO: Evaluate Google's auto-service as a dependency
|
//@AutoService(Processor.class) // TODO: Evaluate Google's auto-service as a dependency
|
||||||
public class DBAnnotatedObjectProcessor extends AbstractProcessor {
|
public class DBAnnotatedObjectProcessor extends AbstractProcessor {
|
||||||
|
@ -39,6 +41,11 @@ public class DBAnnotatedObjectProcessor extends AbstractProcessor {
|
||||||
|
|
||||||
private ValidationContext ctx;
|
private ValidationContext ctx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the processor with the given preprocessing environment.
|
||||||
|
*
|
||||||
|
* @param env the processing environment
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized void init(ProcessingEnvironment env) {
|
public synchronized void init(ProcessingEnvironment env) {
|
||||||
//System.err.println("HERE4");
|
//System.err.println("HERE4");
|
||||||
|
@ -46,6 +53,14 @@ public class DBAnnotatedObjectProcessor extends AbstractProcessor {
|
||||||
ctx = new ValidationContext(env);
|
ctx = new ValidationContext(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the specified annotations for the current round of processing..
|
||||||
|
*
|
||||||
|
* @param annotations the set of annotations to process
|
||||||
|
* @param roundEnv the environment for information about the current and prior round
|
||||||
|
* @return {@code true} if the annotations are claimed by this processor, {@code false}
|
||||||
|
* otherwise
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||||
Map<TypeElement, DBAnnotatedObjectValidator> types = new LinkedHashMap<>();
|
Map<TypeElement, DBAnnotatedObjectValidator> types = new LinkedHashMap<>();
|
||||||
|
@ -76,21 +91,40 @@ public class DBAnnotatedObjectProcessor extends AbstractProcessor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide completion suggestion for the specified element, annotation, and member.
|
||||||
|
*
|
||||||
|
* @param element the element being annotated
|
||||||
|
* @param annotation the annotation being processed
|
||||||
|
* @param member the annotation member being completed
|
||||||
|
* @param userText the text entered by the user
|
||||||
|
* @return an iterable of completions.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Iterable<? extends Completion> getCompletions(Element element,
|
public Iterable<? extends Completion> getCompletions(Element element,
|
||||||
AnnotationMirror annotation, ExecutableElement member, String userText) {
|
AnnotationMirror annotation, ExecutableElement member, String userText) {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return super.getCompletions(element, annotation, member, userText);
|
return super.getCompletions(element, annotation, member, userText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the latest supported source version.
|
||||||
|
*
|
||||||
|
* @return the latest supported source version
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public SourceVersion getSupportedSourceVersion() {
|
public SourceVersion getSupportedSourceVersion() {
|
||||||
return SourceVersion.latestSupported();
|
return SourceVersion.latestSupported();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the set of supported annotation types.
|
||||||
|
*
|
||||||
|
* @return the set of supported annotation types
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getSupportedAnnotationTypes() {
|
public Set<String> getSupportedAnnotationTypes() {
|
||||||
return SUPPORTED_ANNOTATIONS.stream().map(Class::getCanonicalName).collect(
|
return SUPPORTED_ANNOTATIONS.stream()
|
||||||
Collectors.toSet());
|
.map(Class::getCanonicalName)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,31 +20,62 @@ import java.util.*;
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import javax.tools.Diagnostic.Kind;
|
import javax.tools.Diagnostic.Kind;
|
||||||
|
|
||||||
|
import ghidra.util.database.DBAnnotatedObject;
|
||||||
import ghidra.util.database.annot.*;
|
import ghidra.util.database.annot.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate {@link DBAnnotatedObject}-related annotations on a given type element.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* This class ensures that annotations such as {@link DBAnnotatedField}, {@link DBAnnotatedColumn},
|
||||||
|
* and {@link DBAnnotatedObjectInfo} are applied correctly and consistently on the fields and
|
||||||
|
* columns of a class.
|
||||||
|
*/
|
||||||
public class DBAnnotatedObjectValidator {
|
public class DBAnnotatedObjectValidator {
|
||||||
private final ValidationContext ctx;
|
private final ValidationContext ctx;
|
||||||
private final TypeElement type;
|
private final TypeElement type;
|
||||||
private final Map<String, DBAnnotatedFieldValidator> fieldsByName = new LinkedHashMap<>();
|
private final Map<String, DBAnnotatedFieldValidator> fieldsByName = new LinkedHashMap<>();
|
||||||
private final Map<String, DBAnnotatedColumnValidator> columnsByName = new LinkedHashMap<>();
|
private final Map<String, DBAnnotatedColumnValidator> columnsByName = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new validator for the given type element within the specified validation context
|
||||||
|
*
|
||||||
|
* @param ctx the validation context
|
||||||
|
* @param type the type element to be validated
|
||||||
|
*/
|
||||||
public DBAnnotatedObjectValidator(ValidationContext ctx, TypeElement type) {
|
public DBAnnotatedObjectValidator(ValidationContext ctx, TypeElement type) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a field annotated with {@link DBAnnotatedField} to be validator.
|
||||||
|
*
|
||||||
|
* @param field the field element annotated with {@link DBAnnotatedField}
|
||||||
|
*/
|
||||||
public void addAnnotatedField(VariableElement field) {
|
public void addAnnotatedField(VariableElement field) {
|
||||||
DBAnnotatedField annotation = field.getAnnotation(DBAnnotatedField.class);
|
DBAnnotatedField annotation = field.getAnnotation(DBAnnotatedField.class);
|
||||||
assert annotation != null;
|
assert annotation != null;
|
||||||
fieldsByName.put(annotation.column(), new DBAnnotatedFieldValidator(ctx, field));
|
fieldsByName.put(annotation.column(), new DBAnnotatedFieldValidator(ctx, field));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a column annotated with {@link DBAnnotatedColumn} to the validator.
|
||||||
|
*
|
||||||
|
* @param column the field element annotated with {@link DBAnnotatedColumn}
|
||||||
|
*/
|
||||||
public void addAnnotatedColumn(VariableElement column) {
|
public void addAnnotatedColumn(VariableElement column) {
|
||||||
DBAnnotatedColumn annotation = column.getAnnotation(DBAnnotatedColumn.class);
|
DBAnnotatedColumn annotation = column.getAnnotation(DBAnnotatedColumn.class);
|
||||||
assert annotation != null;
|
assert annotation != null;
|
||||||
columnsByName.put(annotation.value(), new DBAnnotatedColumnValidator(ctx, column));
|
columnsByName.put(annotation.value(), new DBAnnotatedColumnValidator(ctx, column));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the annotated fields, columns, and the type element itself.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Checks for various annotation constraints and consistency rules.
|
||||||
|
*/
|
||||||
public void validate() {
|
public void validate() {
|
||||||
DBAnnotatedObjectInfo annotation = type.getAnnotation(DBAnnotatedObjectInfo.class);
|
DBAnnotatedObjectInfo annotation = type.getAnnotation(DBAnnotatedObjectInfo.class);
|
||||||
if (annotation != null && type.getKind() != ElementKind.CLASS) {
|
if (annotation != null && type.getKind() != ElementKind.CLASS) {
|
||||||
|
@ -81,18 +112,27 @@ public class DBAnnotatedObjectValidator {
|
||||||
checkMissing();
|
checkMissing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate all fields annotated with {@link DBAnnotatedField}.
|
||||||
|
*/
|
||||||
protected void validateFields() {
|
protected void validateFields() {
|
||||||
for (DBAnnotatedFieldValidator fv : fieldsByName.values()) {
|
for (DBAnnotatedFieldValidator fv : fieldsByName.values()) {
|
||||||
fv.validate();
|
fv.validate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate all columns annotated with {@link DBAnnotatedColumn}.
|
||||||
|
*/
|
||||||
protected void validateColumns() {
|
protected void validateColumns() {
|
||||||
for (DBAnnotatedColumnValidator cv : columnsByName.values()) {
|
for (DBAnnotatedColumnValidator cv : columnsByName.values()) {
|
||||||
cv.validate();
|
cv.validate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for missing corresponding annotations between fields and columns.
|
||||||
|
*/
|
||||||
protected void checkMissing() {
|
protected void checkMissing() {
|
||||||
Set<String> names = new LinkedHashSet<>();
|
Set<String> names = new LinkedHashSet<>();
|
||||||
names.addAll(fieldsByName.keySet());
|
names.addAll(fieldsByName.keySet());
|
||||||
|
@ -121,6 +161,13 @@ public class DBAnnotatedObjectValidator {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that the access specifiers of the field and column are compatible.
|
||||||
|
*
|
||||||
|
* @param field the field element
|
||||||
|
* @param column the column element
|
||||||
|
* @param name the name of the column
|
||||||
|
*/
|
||||||
protected void checkAccess(VariableElement field, VariableElement column, String name) {
|
protected void checkAccess(VariableElement field, VariableElement column, String name) {
|
||||||
AccessSpec fieldSpec = AccessSpec.get(field.getModifiers());
|
AccessSpec fieldSpec = AccessSpec.get(field.getModifiers());
|
||||||
AccessSpec columnSpec = AccessSpec.get(column.getModifiers());
|
AccessSpec columnSpec = AccessSpec.get(column.getModifiers());
|
||||||
|
|
|
@ -38,6 +38,11 @@ public class ValidationContext {
|
||||||
final TypeElement DEFAULT_CODEC_ELEM;
|
final TypeElement DEFAULT_CODEC_ELEM;
|
||||||
final TypeElement ENUM_ELEM;
|
final TypeElement ENUM_ELEM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a Validation Context with the specified processing environment/
|
||||||
|
*
|
||||||
|
* @param env the processing environment
|
||||||
|
*/
|
||||||
public ValidationContext(ProcessingEnvironment env) {
|
public ValidationContext(ProcessingEnvironment env) {
|
||||||
typeUtils = env.getTypeUtils();
|
typeUtils = env.getTypeUtils();
|
||||||
elementUtils = env.getElementUtils();
|
elementUtils = env.getElementUtils();
|
||||||
|
@ -54,14 +59,35 @@ public class ValidationContext {
|
||||||
ENUM_ELEM = elementUtils.getTypeElement(Enum.class.getCanonicalName());
|
ENUM_ELEM = elementUtils.getTypeElement(Enum.class.getCanonicalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if t1 is a subclass of t2.
|
||||||
|
*
|
||||||
|
* @param t1 the potential subclass
|
||||||
|
* @param t2 the potential superclass
|
||||||
|
* @return true if t1 is a subclass of t2, false otherwise
|
||||||
|
*/
|
||||||
public boolean isSubclass(TypeElement t1, TypeElement t2) {
|
public boolean isSubclass(TypeElement t1, TypeElement t2) {
|
||||||
return typeUtils.isSubtype(typeUtils.erasure(t1.asType()), typeUtils.erasure(t2.asType()));
|
return typeUtils.isSubtype(typeUtils.erasure(t1.asType()), typeUtils.erasure(t2.asType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the field has the specified type.
|
||||||
|
*
|
||||||
|
* @param field the field element
|
||||||
|
* @param type the type element
|
||||||
|
* @return true if the field has the specified type, false otherwise
|
||||||
|
*/
|
||||||
public boolean hasType(VariableElement field, TypeElement type) {
|
public boolean hasType(VariableElement field, TypeElement type) {
|
||||||
return hasType(field, type.asType());
|
return hasType(field, type.asType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the field has the specified type.
|
||||||
|
*
|
||||||
|
* @param field the field element
|
||||||
|
* @param type the type mirror
|
||||||
|
* @return true if the field has the specified type, false otherwise
|
||||||
|
*/
|
||||||
public boolean hasType(VariableElement field, TypeMirror type) {
|
public boolean hasType(VariableElement field, TypeMirror type) {
|
||||||
TypeMirror fieldType = field.asType();
|
TypeMirror fieldType = field.asType();
|
||||||
try {
|
try {
|
||||||
|
@ -89,6 +115,13 @@ public class ValidationContext {
|
||||||
// return typeUtils.isSameType(fieldType, type);
|
// return typeUtils.isSameType(fieldType, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if t1 is capturable by t2.
|
||||||
|
*
|
||||||
|
* @param t1 is the type to check
|
||||||
|
* @param t2 the capture target type
|
||||||
|
* @return true if t1 is capturable by t2, false otherwise
|
||||||
|
*/
|
||||||
public boolean isCapturable(TypeMirror t1, TypeMirror t2) {
|
public boolean isCapturable(TypeMirror t1, TypeMirror t2) {
|
||||||
// TODO: This only works for typevar at top level...
|
// TODO: This only works for typevar at top level...
|
||||||
// TODO: Need to figure out how to check for capture and check
|
// TODO: Need to figure out how to check for capture and check
|
||||||
|
@ -105,6 +138,12 @@ public class ValidationContext {
|
||||||
return typeUtils.isSubtype(t1, t2);
|
return typeUtils.isSubtype(t1, t2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the type is an enum type.
|
||||||
|
*
|
||||||
|
* @param t the type mirror to check
|
||||||
|
* @return true if the type is an enum type, false otherwise
|
||||||
|
*/
|
||||||
public boolean isEnumType(TypeMirror t) {
|
public boolean isEnumType(TypeMirror t) {
|
||||||
if (t.getKind() != TypeKind.DECLARED) {
|
if (t.getKind() != TypeKind.DECLARED) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -113,6 +152,13 @@ public class ValidationContext {
|
||||||
return typeUtils.isSubtype(t, enumType);
|
return typeUtils.isSubtype(t, enumType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the supertype of a set of declared types that matches the specified super type.
|
||||||
|
*
|
||||||
|
* @param types the set of declared types
|
||||||
|
* @param superType the super type element to match
|
||||||
|
* @return the matching declared type, or null if no match is found
|
||||||
|
*/
|
||||||
protected DeclaredType findSupertype(Set<DeclaredType> types, TypeElement superType) {
|
protected DeclaredType findSupertype(Set<DeclaredType> types, TypeElement superType) {
|
||||||
Set<DeclaredType> next;
|
Set<DeclaredType> next;
|
||||||
while (!types.isEmpty()) {
|
while (!types.isEmpty()) {
|
||||||
|
@ -132,14 +178,35 @@ public class ValidationContext {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the supertype of a declared type that matches the specified super type element.
|
||||||
|
*
|
||||||
|
* @param type the declared type
|
||||||
|
* @param superElem the super type element to match
|
||||||
|
* @return the matching declared type, or null if no match is found
|
||||||
|
*/
|
||||||
public DeclaredType findSupertype(DeclaredType type, TypeElement superElem) {
|
public DeclaredType findSupertype(DeclaredType type, TypeElement superElem) {
|
||||||
return findSupertype(Set.of(type), superElem);
|
return findSupertype(Set.of(type), superElem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the supertype of a type element that matches the specified super type element.
|
||||||
|
*
|
||||||
|
* @param elem the type element
|
||||||
|
* @param superElem the super type element to match
|
||||||
|
* @return the matching declared type, or null if no match is found
|
||||||
|
*/
|
||||||
public DeclaredType findSupertype(TypeElement elem, TypeElement superElem) {
|
public DeclaredType findSupertype(TypeElement elem, TypeElement superElem) {
|
||||||
return findSupertype((DeclaredType) elem.asType(), superElem);
|
return findSupertype((DeclaredType) elem.asType(), superElem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the type arguments of the super type element to a map.
|
||||||
|
*
|
||||||
|
* @param superElem the super type element
|
||||||
|
* @param superType the declared super type
|
||||||
|
* @return a map of type argument names to their corresponding type mirrors
|
||||||
|
*/
|
||||||
protected Map<String, TypeMirror> toArgsMap(TypeElement superElem, DeclaredType superType) {
|
protected Map<String, TypeMirror> toArgsMap(TypeElement superElem, DeclaredType superType) {
|
||||||
List<? extends TypeParameterElement> typeParameters = superElem.getTypeParameters();
|
List<? extends TypeParameterElement> typeParameters = superElem.getTypeParameters();
|
||||||
List<? extends TypeMirror> typeArguments = superType.getTypeArguments();
|
List<? extends TypeMirror> typeArguments = superType.getTypeArguments();
|
||||||
|
@ -151,14 +218,34 @@ public class ValidationContext {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type arguments of a declared type as a map.
|
||||||
|
*
|
||||||
|
* @param type the declared type
|
||||||
|
* @param superElem the super type element
|
||||||
|
* @return a map of type argument names to their corresponding type mirrors
|
||||||
|
*/
|
||||||
public Map<String, TypeMirror> getArguments(DeclaredType type, TypeElement superElem) {
|
public Map<String, TypeMirror> getArguments(DeclaredType type, TypeElement superElem) {
|
||||||
return toArgsMap(superElem, findSupertype(type, superElem));
|
return toArgsMap(superElem, findSupertype(type, superElem));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type arguments of a type element as a map.
|
||||||
|
*
|
||||||
|
* @param elem the type element
|
||||||
|
* @param superElem the super type element
|
||||||
|
* @return a map of type argument names to their corresponding type mirrors
|
||||||
|
*/
|
||||||
public Map<String, TypeMirror> getArguments(TypeElement elem, TypeElement superElem) {
|
public Map<String, TypeMirror> getArguments(TypeElement elem, TypeElement superElem) {
|
||||||
return toArgsMap(superElem, findSupertype(elem, superElem));
|
return toArgsMap(superElem, findSupertype(elem, superElem));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format the given type mirror as a string.
|
||||||
|
*
|
||||||
|
* @param type the type mirror to format
|
||||||
|
* @return the formatted type mirror as a string
|
||||||
|
*/
|
||||||
public String format(TypeMirror type) {
|
public String format(TypeMirror type) {
|
||||||
FormatVisitor vis = new FormatVisitor();
|
FormatVisitor vis = new FormatVisitor();
|
||||||
type.accept(vis, null);
|
type.accept(vis, null);
|
||||||
|
@ -166,9 +253,20 @@ public class ValidationContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for formatting {@link TypeMirror} instances into a readable string
|
||||||
|
*/
|
||||||
class FormatVisitor implements TypeVisitor<Void, Void> {
|
class FormatVisitor implements TypeVisitor<Void, Void> {
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit method for {@link TypeMirror}. Delegates to specific visit methods based on the type
|
||||||
|
* kind.
|
||||||
|
*
|
||||||
|
* @param t the type mirror to visit
|
||||||
|
* @param p unused parameter (can be {@code null})
|
||||||
|
* @return {@code null}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Void visit(TypeMirror t, Void p) {
|
public Void visit(TypeMirror t, Void p) {
|
||||||
switch (t.getKind()) {
|
switch (t.getKind()) {
|
||||||
|
@ -207,18 +305,39 @@ class FormatVisitor implements TypeVisitor<Void, Void> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit method for {@link PrimitiveType}.
|
||||||
|
*
|
||||||
|
* @param t the primitive type to visit
|
||||||
|
* @param p unused parameter (can be {@code null})
|
||||||
|
* @return {@code null}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Void visitPrimitive(PrimitiveType t, Void p) {
|
public Void visitPrimitive(PrimitiveType t, Void p) {
|
||||||
buf.append(t.toString());
|
buf.append(t.toString());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit method for {@link NullType}.
|
||||||
|
*
|
||||||
|
* @param t the null type to visit
|
||||||
|
* @param p unused parameter (can be {@code null})
|
||||||
|
* @return {@code null}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Void visitNull(NullType t, Void p) {
|
public Void visitNull(NullType t, Void p) {
|
||||||
buf.append(t.toString());
|
buf.append(t.toString());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit method for {@link ArrayType}.
|
||||||
|
*
|
||||||
|
* @param t the array type to visit
|
||||||
|
* @param p unused parameter (can be {@code null})
|
||||||
|
* @return {@code null}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Void visitArray(ArrayType t, Void p) {
|
public Void visitArray(ArrayType t, Void p) {
|
||||||
visit(t.getComponentType());
|
visit(t.getComponentType());
|
||||||
|
@ -226,6 +345,13 @@ class FormatVisitor implements TypeVisitor<Void, Void> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit method for {@link DeclaredType}.
|
||||||
|
*
|
||||||
|
* @param t the declared type to visit
|
||||||
|
* @param p unused parameter (can be {@code null})
|
||||||
|
* @return {@code null}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Void visitDeclared(DeclaredType t, Void p) {
|
public Void visitDeclared(DeclaredType t, Void p) {
|
||||||
buf.append(t.asElement().toString());
|
buf.append(t.asElement().toString());
|
||||||
|
@ -242,12 +368,26 @@ class FormatVisitor implements TypeVisitor<Void, Void> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit method for {@link ErrorType}.
|
||||||
|
*
|
||||||
|
* @param t the error type to visit
|
||||||
|
* @param p unused parameter (can be {@code null})
|
||||||
|
* @return {@code null}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Void visitError(ErrorType t, Void p) {
|
public Void visitError(ErrorType t, Void p) {
|
||||||
buf.append(t.toString());
|
buf.append(t.toString());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit method for {@link TypeVariable}.
|
||||||
|
*
|
||||||
|
* @param t the type variable to visit
|
||||||
|
* @param p unused parameter (can be {@code null})
|
||||||
|
* @return {@code null}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Void visitTypeVariable(TypeVariable t, Void p) {
|
public Void visitTypeVariable(TypeVariable t, Void p) {
|
||||||
buf.append(t.toString());
|
buf.append(t.toString());
|
||||||
|
@ -264,6 +404,13 @@ class FormatVisitor implements TypeVisitor<Void, Void> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit method for {@link WildcardType}.
|
||||||
|
*
|
||||||
|
* @param t the wildcard type to visit
|
||||||
|
* @param p unused parameter (can be {@code null})
|
||||||
|
* @return {@code null}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Void visitWildcard(WildcardType t, Void p) {
|
public Void visitWildcard(WildcardType t, Void p) {
|
||||||
buf.append("?");
|
buf.append("?");
|
||||||
|
@ -280,24 +427,52 @@ class FormatVisitor implements TypeVisitor<Void, Void> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit method for {@link ExecutableType}.
|
||||||
|
*
|
||||||
|
* @param t the executable type to visit
|
||||||
|
* @param p unused parameter (can be {@code null})
|
||||||
|
* @return {@code null}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Void visitExecutable(ExecutableType t, Void p) {
|
public Void visitExecutable(ExecutableType t, Void p) {
|
||||||
buf.append(t.toString());
|
buf.append(t.toString());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit method for {@link NoType}.
|
||||||
|
*
|
||||||
|
* @param t the no-type to visit
|
||||||
|
* @param p unused parameter (can be {@code null})
|
||||||
|
* @return {@code null}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Void visitNoType(NoType t, Void p) {
|
public Void visitNoType(NoType t, Void p) {
|
||||||
buf.append(t.toString());
|
buf.append(t.toString());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit method for unknown {@link TypeMirror} instances.
|
||||||
|
*
|
||||||
|
* @param t the unknown type to visit
|
||||||
|
* @param p unused parameter (can be {@code null})
|
||||||
|
* @return {@code null}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Void visitUnknown(TypeMirror t, Void p) {
|
public Void visitUnknown(TypeMirror t, Void p) {
|
||||||
buf.append(t.toString());
|
buf.append(t.toString());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit method for {@link UnionType}.
|
||||||
|
*
|
||||||
|
* @param t the union type to visit
|
||||||
|
* @param p unused parameter (can be {@code null})
|
||||||
|
* @return {@code null}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Void visitUnion(UnionType t, Void p) {
|
public Void visitUnion(UnionType t, Void p) {
|
||||||
Iterator<? extends TypeMirror> it = t.getAlternatives().iterator();
|
Iterator<? extends TypeMirror> it = t.getAlternatives().iterator();
|
||||||
|
@ -311,6 +486,13 @@ class FormatVisitor implements TypeVisitor<Void, Void> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit method for {@link IntersectionType}.
|
||||||
|
*
|
||||||
|
* @param t the intersection type to visit
|
||||||
|
* @param p unused parameter (can be {@code null})
|
||||||
|
* @return {@code null}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Void visitIntersection(IntersectionType t, Void p) {
|
public Void visitIntersection(IntersectionType t, Void p) {
|
||||||
Iterator<? extends TypeMirror> it = t.getBounds().iterator();
|
Iterator<? extends TypeMirror> it = t.getBounds().iterator();
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
MODULE FILE LICENSE: pypkg/dist/capstone-5.0.1-py3-none-win_amd64.whl BSD-3-CAPSTONE
|
||||||
|
MODULE FILE LICENSE: pypkg/dist/comtypes-1.4.1-py3-none-any.whl MIT
|
||||||
|
MODULE FILE LICENSE: pypkg/dist/Pybag-2.2.12-py3-none-any.whl MIT
|
||||||
|
MODULE FILE LICENSE: pypkg/dist/pywin32-306-cp312-cp312-win_amd64.whl Python Software Foundation License
|
||||||
|
|
1
Ghidra/Debug/Debugger-agent-dbgeng/README.md
Normal file
1
Ghidra/Debug/Debugger-agent-dbgeng/README.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# Debugger-agent-dbgeng
|
|
@ -18,32 +18,72 @@ apply from: "$rootProject.projectDir/gradle/jacocoProject.gradle"
|
||||||
apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
||||||
apply from: "$rootProject.projectDir/gradle/nativeProject.gradle"
|
apply from: "$rootProject.projectDir/gradle/nativeProject.gradle"
|
||||||
apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
|
apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
|
||||||
|
apply from: "$rootProject.projectDir/gradle/hasPythonPackage.gradle"
|
||||||
apply from: "$rootProject.projectDir/gradle/debugger/hasNodepJar.gradle"
|
apply from: "$rootProject.projectDir/gradle/debugger/hasNodepJar.gradle"
|
||||||
|
|
||||||
apply plugin: 'eclipse'
|
apply plugin: 'eclipse'
|
||||||
eclipse.project.name = 'Debug Debugger-agent-dbgeng'
|
eclipse.project.name = 'Debug Debugger-agent-dbgeng'
|
||||||
|
|
||||||
dependencies {
|
ext.tlb = file("build/os/win_x86_64/dbgmodel.tlb")
|
||||||
api project(":Framework-AsyncComm")
|
|
||||||
api project(":Framework-Debugging")
|
|
||||||
api project(":Debugger-gadp")
|
|
||||||
|
|
||||||
//testImplementation project(":Base")
|
|
||||||
testImplementation project(path: ':Framework-AsyncComm', configuration: 'testArtifacts')
|
|
||||||
testImplementation project(path: ':Framework-Debugging', configuration: 'testArtifacts')
|
|
||||||
testImplementation project(path: ":Debugger-gadp", configuration: 'testArtifacts')
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.nodepJar {
|
|
||||||
manifest {
|
|
||||||
attributes['Main-Class'] = 'agent.dbgeng.gadp.DbgEngGadpServer'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
jvmArgs('-Xrs') // TODO: Is this needed, or left over from trial-and-error
|
|
||||||
if ("win_x86_64".equals(getCurrentPlatformName())) {
|
if ("win_x86_64".equals(getCurrentPlatformName())) {
|
||||||
dependsOn(":Framework-Debugging:testSpecimenWin_x86_64")
|
|
||||||
|
String makeName = "win_x86_64DbgmodelTlbMake"
|
||||||
|
task(type: Exec, makeName) {
|
||||||
|
ext.tmpBatch = file("build/buildTlb.bat")
|
||||||
|
ext.idl = file("src/main/py/src/ghidradbg/dbgmodel/DbgModel.idl")
|
||||||
|
inputs.file(idl)
|
||||||
|
outputs.file(tlb)
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
file(tlb).parentFile.mkdirs()
|
||||||
|
def midlCmd = "midl /tlb ${tlb} ${idl}"
|
||||||
|
println "Executing: " + midlCmd
|
||||||
|
|
||||||
|
tmpBatch.withWriter { out ->
|
||||||
|
out.println "call " + VISUAL_STUDIO_VCVARS_CMD
|
||||||
|
out.println midlCmd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
doLast {
|
||||||
|
assert file(tlb).exists() : "Failed to build dbgmodel.tlb"
|
||||||
|
}
|
||||||
|
|
||||||
|
commandLine "cmd", "/c", tmpBatch
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.assemblePyPackage {
|
||||||
|
from(tasks."$makeName") {
|
||||||
|
into("src/ghidradbg/dbgmodel/tlb")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (file(tlb).exists()) {
|
||||||
|
// required for multi-platform build
|
||||||
|
tasks.assemblePyPackage {
|
||||||
|
from(tlb) {
|
||||||
|
println "Copying existing tlb build artifact: " + tlb
|
||||||
|
into("src/ghidradbg/dbgmodel/tlb")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
def prebuiltTlb = new File(rootProject.BIN_REPO + '/' + getGhidraRelativePath(project) + "/os/win_x86_64/dbgmodel.tlb")
|
||||||
|
if (prebuiltTlb.exists()) {
|
||||||
|
println "Copying prebuilt dbgmodel.tlb"
|
||||||
|
tasks.assemblePyPackage {
|
||||||
|
from(rootProject.BIN_REPO + '/' + getGhidraRelativePath(project) + "/os/win_x86_64/dbgmodel.tlb") {
|
||||||
|
into("src/ghidradbg/dbgmodel/tlb")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println "WARNING: dbgmodel.tlb omitted from ghidradbg python package"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
distributePyDep("Pybag-2.2.12-py3-none-any.whl")
|
||||||
|
distributePyDep("capstone-5.0.1-py3-none-win_amd64.whl")
|
||||||
|
distributePyDep("comtypes-1.4.1-py3-none-any.whl")
|
||||||
|
distributePyDep("pywin32-306-cp312-cp312-win_amd64.whl")
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,18 @@
|
||||||
##VERSION: 2.0
|
##VERSION: 2.0
|
||||||
##MODULE IP: Apache License 2.0
|
##MODULE IP: Apache License 2.0
|
||||||
|
##MODULE IP: MIT
|
||||||
Module.manifest||GHIDRA||||END|
|
Module.manifest||GHIDRA||||END|
|
||||||
src/javaprovider/def/javaprovider.def||GHIDRA||||END|
|
README.md||GHIDRA||||END|
|
||||||
src/javaprovider/rc/javaprovider.rc||GHIDRA||||END|
|
data/debugger-launchers/kernel-dbgeng.bat||GHIDRA||||END|
|
||||||
|
data/debugger-launchers/local-dbgeng-attach.bat||GHIDRA||||END|
|
||||||
|
data/debugger-launchers/local-dbgeng-ext.bat||GHIDRA||||END|
|
||||||
|
data/debugger-launchers/local-dbgeng.bat||GHIDRA||||END|
|
||||||
|
data/debugger-launchers/local-ttd.bat||GHIDRA||||END|
|
||||||
|
data/debugger-launchers/remote-dbgeng.bat||GHIDRA||||END|
|
||||||
|
src/main/py/LICENSE||GHIDRA||||END|
|
||||||
|
src/main/py/MANIFEST.in||GHIDRA||||END|
|
||||||
|
src/main/py/README.md||GHIDRA||||END|
|
||||||
|
src/main/py/pyproject.toml||GHIDRA||||END|
|
||||||
|
src/main/py/src/ghidradbg/dbgmodel/DbgModel.idl||GHIDRA||||END|
|
||||||
|
src/main/py/src/ghidradbg/schema.xml||GHIDRA||||END|
|
||||||
|
src/main/py/src/ghidrattd/schema.xml||GHIDRA||||END|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
::@title dbgeng-kernel
|
||||||
|
::@desc <html><body width="300px">
|
||||||
|
::@desc <h3>Kernel debugging using <tt>dbgeng</tt> (in a Python interpreter)</h3>
|
||||||
|
::@desc <p>
|
||||||
|
::@desc This will connect the kernel debugger to a remote machine using <tt>dbgeng.dll</tt>.
|
||||||
|
::@desc For setup instructions, press <b>F1</b>.
|
||||||
|
::@desc </p>
|
||||||
|
::@desc </body></html>
|
||||||
|
::@menu-group local
|
||||||
|
::@icon icon.debugger
|
||||||
|
::@help TraceRmiLauncherServicePlugin#dbgeng_kernel
|
||||||
|
::@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH."
|
||||||
|
:: Use env instead of args, because "all args except first" is terrible to implement in batch
|
||||||
|
::@env OPT_TARGET_ARGS:str="" "Arguments" "Connection-string arguments (a la .server)"
|
||||||
|
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
||||||
|
::@env WINDBG_DIR:dir="" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
||||||
|
|
||||||
|
@echo off
|
||||||
|
|
||||||
|
"%OPT_PYTHON_EXE%" -i ..\support\kernel-dbgeng.py
|
|
@ -0,0 +1,20 @@
|
||||||
|
::@title dbgeng-attach
|
||||||
|
::@desc <html><body width="300px">
|
||||||
|
::@desc <h3>Attach with <tt>dbgeng</tt> (in a Python interpreter)</h3>
|
||||||
|
::@desc <p>
|
||||||
|
::@desc This will attach to a running target on the local machine using <tt>dbgeng.dll</tt>.
|
||||||
|
::@desc For setup instructions, press <b>F1</b>.
|
||||||
|
::@desc </p>
|
||||||
|
::@desc </body></html>
|
||||||
|
::@menu-group local
|
||||||
|
::@icon icon.debugger
|
||||||
|
::@help TraceRmiLauncherServicePlugin#dbgeng_attach
|
||||||
|
::@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH."
|
||||||
|
::@env OPT_TARGET_PID:int=0 "Process id" "The target process id"
|
||||||
|
::@env OPT_ATTACH_FLAGS:int=0 "Attach flags" "Attach flags"
|
||||||
|
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
||||||
|
::@env WINDBG_DIR:dir="" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
||||||
|
|
||||||
|
@echo off
|
||||||
|
|
||||||
|
"%OPT_PYTHON_EXE%" -i ..\support\local-dbgeng-attach.py
|
|
@ -0,0 +1,27 @@
|
||||||
|
::@title dbgeng-ext
|
||||||
|
::@image-opt env:OPT_TARGET_IMG
|
||||||
|
::@desc <html><body width="300px">
|
||||||
|
::@desc <h3>Launch with <tt>dbgeng</tt> (in a Python interpreter)</h3>
|
||||||
|
::@desc <p>
|
||||||
|
::@desc This will launch the target on the local machine using <tt>dbgeng.dll</tt>.
|
||||||
|
::@desc For setup instructions, press <b>F1</b>.
|
||||||
|
::@desc </p>
|
||||||
|
::@desc </body></html>
|
||||||
|
::@menu-group local
|
||||||
|
::@icon icon.debugger
|
||||||
|
::@help TraceRmiLauncherServicePlugin#dbgeng_ext
|
||||||
|
::@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH."
|
||||||
|
:: Use env instead of args, because "all args except first" is terrible to implement in batch
|
||||||
|
::@env OPT_TARGET_IMG:file!="" "Image" "The target binary executable image"
|
||||||
|
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||||
|
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
||||||
|
::@env WINDBG_DIR:dir="" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
||||||
|
::@env OPT_TARGET_DIR:str="" "Dir" "Initial directory"
|
||||||
|
::@env OPT_TARGET_ENV:str="" "Env" "Environment variables (sep=/0)"
|
||||||
|
::@env OPT_CREATE_FLAGS:int="1" "Create flags" "Creation flags"
|
||||||
|
::@env OPT_CREATE_ENGFLAGS:int="0" "Create flags (Engine)" "Engine-specific creation flags"
|
||||||
|
::@env OPT_VERIFIER_FLAGS:int="0" "Verifier flags" "Verifier flags"
|
||||||
|
|
||||||
|
@echo off
|
||||||
|
|
||||||
|
"%OPT_PYTHON_EXE%" -i ..\support\local-dbgeng-ext.py
|
|
@ -0,0 +1,22 @@
|
||||||
|
::@title dbgeng
|
||||||
|
::@image-opt env:OPT_TARGET_IMG
|
||||||
|
::@desc <html><body width="300px">
|
||||||
|
::@desc <h3>Launch with <tt>dbgeng</tt> (in a Python interpreter)</h3>
|
||||||
|
::@desc <p>
|
||||||
|
::@desc This will launch the target on the local machine using <tt>dbgeng.dll</tt>.
|
||||||
|
::@desc For setup instructions, press <b>F1</b>.
|
||||||
|
::@desc </p>
|
||||||
|
::@desc </body></html>
|
||||||
|
::@menu-group local
|
||||||
|
::@icon icon.debugger
|
||||||
|
::@help TraceRmiLauncherServicePlugin#dbgeng
|
||||||
|
::@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH."
|
||||||
|
:: Use env instead of args, because "all args except first" is terrible to implement in batch
|
||||||
|
::@env OPT_TARGET_IMG:file!="" "Image" "The target binary executable image"
|
||||||
|
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||||
|
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
||||||
|
::@env WINDBG_DIR:dir="" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
||||||
|
|
||||||
|
@echo off
|
||||||
|
|
||||||
|
"%OPT_PYTHON_EXE%" -i ..\support\local-dbgeng.py
|
|
@ -0,0 +1,21 @@
|
||||||
|
::@title ttd
|
||||||
|
::@desc <html><body width="300px">
|
||||||
|
::@desc <h3>Launch with <tt>ttd</tt> (in a Python interpreter)</h3>
|
||||||
|
::@desc <p>
|
||||||
|
::@desc This will launch the target on the local machine for time-travel debugging.
|
||||||
|
::@desc For setup instructions, press <b>F1</b>.
|
||||||
|
::@desc </p>
|
||||||
|
::@desc </body></html>
|
||||||
|
::@menu-group local
|
||||||
|
::@icon icon.debugger
|
||||||
|
::@help TraceRmiLauncherServicePlugin#dbgeng_ttd
|
||||||
|
::@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH."
|
||||||
|
:: Use env instead of args, because "all args except first" is terrible to implement in batch
|
||||||
|
::@env OPT_TARGET_IMG:file!="" "Trace (.run)" "A trace associated with the target binary executable"
|
||||||
|
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||||
|
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
||||||
|
::@env OPT_DBGMODEL_PATH:dir="" "Path to dbgeng.dll & \\ttd" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
||||||
|
|
||||||
|
@echo off
|
||||||
|
|
||||||
|
"%OPT_PYTHON_EXE%" -i ..\support\local-ttd.py
|
|
@ -0,0 +1,23 @@
|
||||||
|
::@title dbgeng-remote
|
||||||
|
::@image-opt env:OPT_TARGET_IMG
|
||||||
|
::@desc <html><body width="300px">
|
||||||
|
::@desc <h3>Launch with <tt>dbgeng</tt> remotely (in a Python interpreter)</h3>
|
||||||
|
::@desc <p>
|
||||||
|
::@desc This will launch the target on a remote machine using <tt>dbgeng.dll</tt>.
|
||||||
|
::@desc For setup instructions, press <b>F1</b>.
|
||||||
|
::@desc </p>
|
||||||
|
::@desc </body></html>
|
||||||
|
::@menu-group local
|
||||||
|
::@icon icon.debugger
|
||||||
|
::@help TraceRmiLauncherServicePlugin#dbgeng_remote
|
||||||
|
::@env OPT_PYTHON_EXE:file!="python" "Python command" "The path to the Python 3 interpreter. Omit the full path to resolve using the system PATH."
|
||||||
|
:: Use env instead of args, because "all args except first" is terrible to implement in batch
|
||||||
|
::@env OPT_TARGET_IMG:str!="" "Image" "The target binary executable image"
|
||||||
|
::@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||||
|
::@env OPT_CONNECT_STRING:str="" "Connection" "Connection-string arguments (a la dbgsrv args)"
|
||||||
|
::@env OPT_USE_DBGMODEL:bool=true "Use dbgmodel" "Load and use dbgmodel.dll if it is available."
|
||||||
|
::@env WINDBG_DIR:dir="" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
||||||
|
|
||||||
|
@echo off
|
||||||
|
|
||||||
|
"%OPT_PYTHON_EXE%" -i ..\support\remote-dbgeng.py
|
|
@ -0,0 +1,67 @@
|
||||||
|
## ###
|
||||||
|
# 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.
|
||||||
|
##
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
home = os.getenv('GHIDRA_HOME')
|
||||||
|
|
||||||
|
if os.path.isdir(f'{home}\\ghidra\\.git'):
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\ghidra\\Ghidra\\Debug\\Debugger-agent-dbgeng\\build\\pypkg\\src')
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\ghidra\\Ghidra\\Debug\\Debugger-rmi-trace\\build\\pypkg\\src')
|
||||||
|
elif os.path.isdir(f'{home}\\.git'):
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-agent-dbgeng\\build\\pypkg\\src')
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-rmi-trace\\build\\pypkg\\src')
|
||||||
|
else:
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-agent-dbgeng\\pypkg\\src')
|
||||||
|
sys.path.append(f'{home}\\Ghidra\\Debug\\Debugger-rmi-trace\\pypkg\\src')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Delay these imports until sys.path is patched
|
||||||
|
from ghidradbg import commands as cmd
|
||||||
|
from pybag.dbgeng import core as DbgEng
|
||||||
|
from ghidradbg.hooks import on_state_changed
|
||||||
|
from ghidradbg.util import dbg
|
||||||
|
|
||||||
|
# So that the user can re-enter by typing repl()
|
||||||
|
global repl
|
||||||
|
repl = cmd.repl
|
||||||
|
|
||||||
|
cmd.ghidra_trace_connect(os.getenv('GHIDRA_TRACE_RMI_ADDR'))
|
||||||
|
args = os.getenv('OPT_TARGET_ARGS')
|
||||||
|
cmd.ghidra_trace_attach_kernel(args, start_trace=False)
|
||||||
|
|
||||||
|
# TODO: HACK
|
||||||
|
try:
|
||||||
|
dbg.wait()
|
||||||
|
except KeyboardInterrupt as ki:
|
||||||
|
dbg.interrupt()
|
||||||
|
|
||||||
|
cmd.ghidra_trace_start(os.getenv('OPT_TARGET_IMG'))
|
||||||
|
cmd.ghidra_trace_sync_enable()
|
||||||
|
|
||||||
|
on_state_changed(DbgEng.DEBUG_CES_EXECUTION_STATUS, DbgEng.DEBUG_STATUS_BREAK)
|
||||||
|
cmd.repl()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -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.
|
||||||
|
##
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
home = os.getenv('GHIDRA_HOME')
|
||||||
|
|
||||||
|
if os.path.isdir(f'{home}\\ghidra\\.git'):
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\ghidra\\Ghidra\\Debug\\Debugger-agent-dbgeng\\build\\pypkg\\src')
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\ghidra\\Ghidra\\Debug\\Debugger-rmi-trace\\build\\pypkg\\src')
|
||||||
|
elif os.path.isdir(f'{home}\\.git'):
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-agent-dbgeng\\build\\pypkg\\src')
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-rmi-trace\\build\\pypkg\\src')
|
||||||
|
else:
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-agent-dbgeng\\pypkg\\src')
|
||||||
|
sys.path.append(f'{home}\\Ghidra\\Debug\\Debugger-rmi-trace\\pypkg\\src')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Delay these imports until sys.path is patched
|
||||||
|
from ghidradbg import commands as cmd
|
||||||
|
from pybag.dbgeng import core as DbgEng
|
||||||
|
from ghidradbg.hooks import on_state_changed
|
||||||
|
from ghidradbg.util import dbg
|
||||||
|
|
||||||
|
# So that the user can re-enter by typing repl()
|
||||||
|
global repl
|
||||||
|
repl = cmd.repl
|
||||||
|
|
||||||
|
cmd.ghidra_trace_connect(os.getenv('GHIDRA_TRACE_RMI_ADDR'))
|
||||||
|
flags = os.getenv('OPT_ATTACH_FLAGS')
|
||||||
|
cmd.ghidra_trace_attach(
|
||||||
|
os.getenv('OPT_TARGET_PID'), flags, start_trace=False)
|
||||||
|
|
||||||
|
# TODO: HACK
|
||||||
|
try:
|
||||||
|
dbg.wait()
|
||||||
|
except KeyboardInterrupt as ki:
|
||||||
|
dbg.interrupt()
|
||||||
|
|
||||||
|
cmd.ghidra_trace_start(os.getenv('OPT_TARGET_IMG'))
|
||||||
|
cmd.ghidra_trace_sync_enable()
|
||||||
|
|
||||||
|
on_state_changed(DbgEng.DEBUG_CES_EXECUTION_STATUS, DbgEng.DEBUG_STATUS_BREAK)
|
||||||
|
cmd.repl()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -0,0 +1,77 @@
|
||||||
|
## ###
|
||||||
|
# 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.
|
||||||
|
##
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
home = os.getenv('GHIDRA_HOME')
|
||||||
|
|
||||||
|
if os.path.isdir(f'{home}\\ghidra\\.git'):
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\ghidra\\Ghidra\\Debug\\Debugger-agent-dbgeng\\build\\pypkg\\src')
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\ghidra\\Ghidra\\Debug\\Debugger-rmi-trace\\build\\pypkg\\src')
|
||||||
|
elif os.path.isdir(f'{home}\\.git'):
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-agent-dbgeng\\build\\pypkg\\src')
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-rmi-trace\\build\\pypkg\\src')
|
||||||
|
else:
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-agent-dbgeng\\pypkg\\src')
|
||||||
|
sys.path.append(f'{home}\\Ghidra\\Debug\\Debugger-rmi-trace\\pypkg\\src')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Delay these imports until sys.path is patched
|
||||||
|
from ghidradbg import commands as cmd
|
||||||
|
from pybag.dbgeng import core as DbgEng
|
||||||
|
from ghidradbg.hooks import on_state_changed
|
||||||
|
from ghidradbg.util import dbg
|
||||||
|
|
||||||
|
# So that the user can re-enter by typing repl()
|
||||||
|
global repl
|
||||||
|
repl = cmd.repl
|
||||||
|
|
||||||
|
cmd.ghidra_trace_connect(os.getenv('GHIDRA_TRACE_RMI_ADDR'))
|
||||||
|
args = os.getenv('OPT_TARGET_ARGS')
|
||||||
|
if args:
|
||||||
|
args = ' ' + args
|
||||||
|
cmd.ghidra_trace_create_ext(
|
||||||
|
os.getenv('OPT_TARGET_IMG') + args,
|
||||||
|
os.getenv('OPT_TARGET_DIR'),
|
||||||
|
os.getenv('OPT_TARGET_ENV'),
|
||||||
|
os.getenv('OPT_CREATE_FLAGS'),
|
||||||
|
os.getenv('OPT_CREATE_ENGFLAGS'),
|
||||||
|
os.getenv('OPT_VERIFIER_FLAGS'),
|
||||||
|
start_trace=False)
|
||||||
|
|
||||||
|
# TODO: HACK
|
||||||
|
try:
|
||||||
|
dbg.wait()
|
||||||
|
except KeyboardInterrupt as ki:
|
||||||
|
dbg.interrupt()
|
||||||
|
|
||||||
|
cmd.ghidra_trace_start(os.getenv('OPT_TARGET_IMG'))
|
||||||
|
cmd.ghidra_trace_sync_enable()
|
||||||
|
|
||||||
|
on_state_changed(DbgEng.DEBUG_CES_EXECUTION_STATUS, DbgEng.DEBUG_STATUS_BREAK)
|
||||||
|
cmd.repl()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -0,0 +1,71 @@
|
||||||
|
## ###
|
||||||
|
# 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.
|
||||||
|
##
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
home = os.getenv('GHIDRA_HOME')
|
||||||
|
|
||||||
|
if os.path.isdir(f'{home}\\ghidra\\.git'):
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\ghidra\\Ghidra\\Debug\\Debugger-agent-dbgeng\\build\\pypkg\\src')
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\ghidra\\Ghidra\\Debug\\Debugger-rmi-trace\\build\\pypkg\\src')
|
||||||
|
elif os.path.isdir(f'{home}\\.git'):
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-agent-dbgeng\\build\\pypkg\\src')
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-rmi-trace\\build\\pypkg\\src')
|
||||||
|
else:
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-agent-dbgeng\\pypkg\\src')
|
||||||
|
sys.path.append(f'{home}\\Ghidra\\Debug\\Debugger-rmi-trace\\pypkg\\src')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Delay these imports until sys.path is patched
|
||||||
|
from ghidradbg import commands as cmd
|
||||||
|
from pybag.dbgeng import core as DbgEng
|
||||||
|
from ghidradbg.hooks import on_state_changed
|
||||||
|
from ghidradbg.util import dbg
|
||||||
|
|
||||||
|
# So that the user can re-enter by typing repl()
|
||||||
|
global repl
|
||||||
|
repl = cmd.repl
|
||||||
|
|
||||||
|
cmd.ghidra_trace_connect(os.getenv('GHIDRA_TRACE_RMI_ADDR'))
|
||||||
|
args = os.getenv('OPT_TARGET_ARGS')
|
||||||
|
if args:
|
||||||
|
args = ' ' + args
|
||||||
|
cmd.ghidra_trace_create(
|
||||||
|
os.getenv('OPT_TARGET_IMG') + args, start_trace=False)
|
||||||
|
|
||||||
|
# TODO: HACK
|
||||||
|
try:
|
||||||
|
dbg.wait()
|
||||||
|
except KeyboardInterrupt as ki:
|
||||||
|
dbg.interrupt()
|
||||||
|
|
||||||
|
cmd.ghidra_trace_start(os.getenv('OPT_TARGET_IMG'))
|
||||||
|
cmd.ghidra_trace_sync_enable()
|
||||||
|
|
||||||
|
on_state_changed(DbgEng.DEBUG_CES_EXECUTION_STATUS, DbgEng.DEBUG_STATUS_BREAK)
|
||||||
|
cmd.repl()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
58
Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-ttd.py
Normal file
58
Ghidra/Debug/Debugger-agent-dbgeng/data/support/local-ttd.py
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
## ###
|
||||||
|
# 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.
|
||||||
|
##
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
home = os.getenv('GHIDRA_HOME')
|
||||||
|
|
||||||
|
if os.path.isdir(f'{home}\\ghidra\\.git'):
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\ghidra\\Ghidra\\Debug\\Debugger-agent-dbgeng\\build\\pypkg\\src')
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\ghidra\\Ghidra\\Debug\\Debugger-rmi-trace\\build\\pypkg\\src')
|
||||||
|
elif os.path.isdir(f'{home}\\.git'):
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-agent-dbgeng\\build\\pypkg\\src')
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-rmi-trace\\build\\pypkg\\src')
|
||||||
|
else:
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-agent-dbgeng\\pypkg\\src')
|
||||||
|
sys.path.append(f'{home}\\Ghidra\\Debug\\Debugger-rmi-trace\\pypkg\\src')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Delay these imports until sys.path is patched
|
||||||
|
from ghidrattd import commands as cmd
|
||||||
|
from ghidrattd import hooks
|
||||||
|
###from ghidrattd.util import dbg
|
||||||
|
|
||||||
|
cmd.ghidra_trace_connect(os.getenv('GHIDRA_TRACE_RMI_ADDR'))
|
||||||
|
args = os.getenv('OPT_TARGET_ARGS')
|
||||||
|
if args:
|
||||||
|
args = ' ' + args
|
||||||
|
cmd.ghidra_trace_create(
|
||||||
|
os.getenv('OPT_TARGET_IMG') + args, start_trace=True)
|
||||||
|
cmd.ghidra_trace_sync_enable()
|
||||||
|
hooks.on_stop()
|
||||||
|
|
||||||
|
cmd.repl()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -0,0 +1,73 @@
|
||||||
|
## ###
|
||||||
|
# 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.
|
||||||
|
##
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
home = os.getenv('GHIDRA_HOME')
|
||||||
|
|
||||||
|
if os.path.isdir(f'{home}\\ghidra\\.git'):
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\ghidra\\Ghidra\\Debug\\Debugger-agent-dbgeng\\build\\pypkg\\src')
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\ghidra\\Ghidra\\Debug\\Debugger-rmi-trace\\build\\pypkg\\src')
|
||||||
|
elif os.path.isdir(f'{home}\\.git'):
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-agent-dbgeng\\build\\pypkg\\src')
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-rmi-trace\\build\\pypkg\\src')
|
||||||
|
else:
|
||||||
|
sys.path.append(
|
||||||
|
f'{home}\\Ghidra\\Debug\\Debugger-agent-dbgeng\\pypkg\\src')
|
||||||
|
sys.path.append(f'{home}\\Ghidra\\Debug\\Debugger-rmi-trace\\pypkg\\src')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Delay these imports until sys.path is patched
|
||||||
|
from ghidradbg import commands as cmd
|
||||||
|
from pybag.dbgeng import core as DbgEng
|
||||||
|
from ghidradbg.hooks import on_state_changed
|
||||||
|
from ghidradbg.util import dbg
|
||||||
|
|
||||||
|
# So that the user can re-enter by typing repl()
|
||||||
|
global repl
|
||||||
|
repl = cmd.repl
|
||||||
|
|
||||||
|
cmd.ghidra_trace_connect(os.getenv('GHIDRA_TRACE_RMI_ADDR'))
|
||||||
|
args = os.getenv('OPT_TARGET_ARGS')
|
||||||
|
if args:
|
||||||
|
args = ' ' + args
|
||||||
|
cmd.ghidra_trace_connect_server(os.getenv('OPT_CONNECT_STRING'))
|
||||||
|
img = os.getenv('OPT_TARGET_IMG')
|
||||||
|
if img is not None and img != "":
|
||||||
|
cmd.ghidra_trace_create(img + args, start_trace=False)
|
||||||
|
|
||||||
|
# TODO: HACK
|
||||||
|
try:
|
||||||
|
dbg.wait()
|
||||||
|
except KeyboardInterrupt as ki:
|
||||||
|
dbg.interrupt()
|
||||||
|
|
||||||
|
cmd.ghidra_trace_start(os.getenv('OPT_TARGET_IMG'))
|
||||||
|
cmd.ghidra_trace_sync_enable()
|
||||||
|
|
||||||
|
on_state_changed(DbgEng.DEBUG_CES_EXECUTION_STATUS, DbgEng.DEBUG_STATUS_BREAK)
|
||||||
|
cmd.repl()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -1,224 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#define INITGUID
|
|
||||||
|
|
||||||
#include <engextcpp.hpp>
|
|
||||||
#include <jni.h>
|
|
||||||
|
|
||||||
#include "resource.h"
|
|
||||||
|
|
||||||
#define CHECK_RESULT(x, y) do { \
|
|
||||||
HRESULT hr = (x); \
|
|
||||||
if (hr != S_OK) { \
|
|
||||||
fprintf(stderr, "HRESULT of %s = %x\n", ##x, hr); \
|
|
||||||
return y; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
class EXT_CLASS : public ExtExtension {
|
|
||||||
public:
|
|
||||||
virtual HRESULT Initialize();
|
|
||||||
virtual void Uninitialize();
|
|
||||||
|
|
||||||
//virtual void OnSessionAccessible(ULONG64 Argument);
|
|
||||||
|
|
||||||
EXT_COMMAND_METHOD(java_add_cp);
|
|
||||||
EXT_COMMAND_METHOD(java_set);
|
|
||||||
EXT_COMMAND_METHOD(java_get);
|
|
||||||
EXT_COMMAND_METHOD(java_run);
|
|
||||||
|
|
||||||
void run_command(PCSTR name);
|
|
||||||
};
|
|
||||||
|
|
||||||
EXT_DECLARE_GLOBALS();
|
|
||||||
|
|
||||||
JavaVM* jvm = NULL;
|
|
||||||
JNIEnv* env = NULL;
|
|
||||||
jclass clsCommands = NULL;
|
|
||||||
|
|
||||||
char JDK_JVM_DLL_PATH[] = "\\jre\\bin\\server\\jvm.dll";
|
|
||||||
char JRE_JVM_DLL_PATH[] = "\\bin\\server\\jvm.dll";
|
|
||||||
|
|
||||||
typedef jint (_cdecl *CreateJavaVMFunc)(JavaVM**, void**, void*);
|
|
||||||
|
|
||||||
HRESULT EXT_CLASS::Initialize() {
|
|
||||||
HRESULT result = ExtExtension::Initialize();
|
|
||||||
if (result != S_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* env_java_home = getenv("JAVA_HOME");
|
|
||||||
if (env_java_home == NULL) {
|
|
||||||
fprintf(stderr, "JAVA_HOME is not set\n");
|
|
||||||
fflush(stderr);
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
char* java_home = strdup(env_java_home);
|
|
||||||
size_t home_len = strlen(java_home);
|
|
||||||
if (java_home[home_len - 1] == '\\') {
|
|
||||||
java_home[home_len - 1] = '\0';
|
|
||||||
}
|
|
||||||
size_t full_len = home_len + sizeof(JDK_JVM_DLL_PATH);
|
|
||||||
char* full_path = new char[full_len];
|
|
||||||
HMODULE jvmDll = NULL;
|
|
||||||
// Try the JRE path first;
|
|
||||||
strcpy_s(full_path, full_len, java_home);
|
|
||||||
strcat_s(full_path, full_len, JRE_JVM_DLL_PATH);
|
|
||||||
fprintf(stderr, "Trying to find jvm.dll at %s\n", full_path);
|
|
||||||
fflush(stderr);
|
|
||||||
jvmDll = LoadLibraryA(full_path);
|
|
||||||
if (jvmDll == NULL) {
|
|
||||||
// OK, then try the JDK path
|
|
||||||
strcpy_s(full_path, full_len, java_home);
|
|
||||||
strcat_s(full_path, full_len, JDK_JVM_DLL_PATH);
|
|
||||||
fprintf(stderr, "Trying to find jvm.dll at %s\n", full_path);
|
|
||||||
fflush(stderr);
|
|
||||||
jvmDll = LoadLibraryA(full_path);
|
|
||||||
}
|
|
||||||
free(full_path);
|
|
||||||
free(java_home);
|
|
||||||
if (jvmDll == NULL) {
|
|
||||||
fprintf(stderr, "Could not find the jvm.dll\n");
|
|
||||||
fflush(stderr);
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
fprintf(stderr, "Found it!\n");
|
|
||||||
fflush(stderr);
|
|
||||||
|
|
||||||
JavaVMOption options[2];
|
|
||||||
JavaVMInitArgs vm_args = { 0 };
|
|
||||||
vm_args.version = JNI_VERSION_1_8;
|
|
||||||
vm_args.nOptions = sizeof(options)/sizeof(options[0]);
|
|
||||||
vm_args.options = options;
|
|
||||||
options[0].optionString = "-Xrs";
|
|
||||||
options[1].optionString = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005";
|
|
||||||
vm_args.ignoreUnrecognized = false;
|
|
||||||
CreateJavaVMFunc create_jvm = NULL;
|
|
||||||
//create_jvm = JNI_CreateJavaVM;
|
|
||||||
create_jvm = (CreateJavaVMFunc) GetProcAddress(jvmDll, "JNI_CreateJavaVM");
|
|
||||||
jint jni_result = create_jvm(&jvm, (void**)&env, &vm_args);
|
|
||||||
|
|
||||||
if (jni_result != JNI_OK) {
|
|
||||||
jvm = NULL;
|
|
||||||
fprintf(stderr, "Could not initialize JVM: %d: ", jni_result);
|
|
||||||
switch (jni_result) {
|
|
||||||
case JNI_ERR:
|
|
||||||
fprintf(stderr, "unknown error");
|
|
||||||
break;
|
|
||||||
case JNI_EDETACHED:
|
|
||||||
fprintf(stderr, "thread detached from the VM");
|
|
||||||
break;
|
|
||||||
case JNI_EVERSION:
|
|
||||||
fprintf(stderr, "JNI version error");
|
|
||||||
break;
|
|
||||||
case JNI_ENOMEM:
|
|
||||||
fprintf(stderr, "not enough memory");
|
|
||||||
break;
|
|
||||||
case JNI_EEXIST:
|
|
||||||
fprintf(stderr, "VM already created");
|
|
||||||
break;
|
|
||||||
case JNI_EINVAL:
|
|
||||||
fprintf(stderr, "invalid arguments");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
fflush(stderr);
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HMODULE hJavaProviderModule = GetModuleHandle(TEXT("javaprovider"));
|
|
||||||
HRSRC resCommandsClassfile = FindResource(hJavaProviderModule, MAKEINTRESOURCE(IDR_CLASSFILE1), TEXT("Classfile"));
|
|
||||||
HGLOBAL gblCommandsClassfile = LoadResource(hJavaProviderModule, resCommandsClassfile);
|
|
||||||
LPVOID lpCommandsClassfile = LockResource(gblCommandsClassfile);
|
|
||||||
DWORD szCommandsClassfile = SizeofResource(hJavaProviderModule, resCommandsClassfile);
|
|
||||||
|
|
||||||
clsCommands = env->DefineClass(
|
|
||||||
"javaprovider/Commands", NULL, (jbyte*) lpCommandsClassfile, szCommandsClassfile
|
|
||||||
);
|
|
||||||
if (clsCommands == NULL) {
|
|
||||||
fprintf(stderr, "Could not define Commands class\n");
|
|
||||||
if (env->ExceptionCheck()) {
|
|
||||||
env->ExceptionDescribe();
|
|
||||||
env->ExceptionClear();
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EXT_CLASS::Uninitialize() {
|
|
||||||
if (jvm != NULL) {
|
|
||||||
jvm->DestroyJavaVM();
|
|
||||||
}
|
|
||||||
ExtExtension::Uninitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EXT_CLASS::run_command(PCSTR name) {
|
|
||||||
// TODO: Throw an exception during load, then!
|
|
||||||
if (jvm == NULL) {
|
|
||||||
Out("javaprovider extension did not load properly.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (clsCommands == NULL) {
|
|
||||||
Out("javaprovider extension did not load properly.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PCSTR args = GetRawArgStr();
|
|
||||||
|
|
||||||
jmethodID mthCommand = env->GetStaticMethodID(clsCommands, name, "(Ljava/lang/String;)V");
|
|
||||||
if (mthCommand == NULL) {
|
|
||||||
Out("INTERNAL ERROR: No such command: %s\n", name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
jstring argsStr = env->NewStringUTF(args);
|
|
||||||
if (argsStr == NULL) {
|
|
||||||
Out("Could not create Java string for arguments.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
env->CallStaticVoidMethod(clsCommands, mthCommand, argsStr);
|
|
||||||
env->DeleteLocalRef(argsStr);
|
|
||||||
if (env->ExceptionCheck()) {
|
|
||||||
Out("Exception during javaprovider command:\n");
|
|
||||||
env->ExceptionDescribe(); // TODO: Send this to output callbacks, not console.
|
|
||||||
env->ExceptionClear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EXT_COMMAND(java_add_cp, "Add an element to the class path", "{{custom}}") {
|
|
||||||
run_command("java_add_cp");
|
|
||||||
}
|
|
||||||
|
|
||||||
EXT_COMMAND(java_set, "Set a Java system property", "{{custom}}") {
|
|
||||||
run_command("java_set");
|
|
||||||
}
|
|
||||||
|
|
||||||
EXT_COMMAND(java_get, "Get a Java system property", "{{custom}}") {
|
|
||||||
run_command("java_get");
|
|
||||||
}
|
|
||||||
|
|
||||||
EXT_COMMAND(java_run, "Execute the named java class", "{{custom}}") {
|
|
||||||
run_command("java_run");
|
|
||||||
}
|
|
||||||
|
|
||||||
#define JNA extern "C" __declspec(dllexport)
|
|
||||||
|
|
||||||
JNA HRESULT createClient(PDEBUG_CLIENT* client) {
|
|
||||||
return g_ExtInstance.m_Client->CreateClient(client);
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
EXPORTS
|
|
||||||
|
|
||||||
; For ExtCpp
|
|
||||||
DebugExtensionInitialize
|
|
||||||
DebugExtensionUninitialize
|
|
||||||
DebugExtensionNotify
|
|
||||||
help
|
|
||||||
|
|
||||||
; My Commands
|
|
||||||
java_add_cp
|
|
||||||
java_set
|
|
||||||
java_get
|
|
||||||
java_run
|
|
|
@ -1,16 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
#include <Windows.h>
|
|
|
@ -1,31 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
//{{NO_DEPENDENCIES}}
|
|
||||||
// Microsoft Visual C++ generated include file.
|
|
||||||
// Used by javaprovider.rc
|
|
||||||
//
|
|
||||||
#define IDR_CLASSFILE1 101
|
|
||||||
|
|
||||||
// Next default values for new objects
|
|
||||||
//
|
|
||||||
#ifdef APSTUDIO_INVOKED
|
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
|
||||||
#define _APS_NEXT_SYMED_VALUE 101
|
|
||||||
#endif
|
|
||||||
#endif
|
|
|
@ -1,95 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
import agent.dbgeng.model.impl.DbgModelImpl;
|
|
||||||
import ghidra.dbg.DebuggerModelFactory;
|
|
||||||
import ghidra.dbg.DebuggerObjectModel;
|
|
||||||
import ghidra.dbg.util.ConfigurableFactory.FactoryDescription;
|
|
||||||
import ghidra.program.model.listing.Program;
|
|
||||||
|
|
||||||
@FactoryDescription(
|
|
||||||
brief = "MS dbgeng.dll (WinDbg)",
|
|
||||||
htmlDetails = """
|
|
||||||
Connect to the Microsoft Debug Engine.
|
|
||||||
This is the same engine that powers WinDbg.
|
|
||||||
This is best for most Windows userspace and kernel targets.
|
|
||||||
Kernel debugging is still experimental.
|
|
||||||
This will access the native API, which may put Ghidra's JVM at risk.""")
|
|
||||||
public class DbgEngInJvmDebuggerModelFactory implements DebuggerModelFactory {
|
|
||||||
|
|
||||||
protected String remote = "none"; // Require user to start server
|
|
||||||
@FactoryOption("DebugConnect options (.server)")
|
|
||||||
public final Property<String> agentRemoteOption =
|
|
||||||
Property.fromAccessors(String.class, this::getAgentRemote, this::setAgentRemote);
|
|
||||||
|
|
||||||
protected String transport = "none"; // Require user to start server
|
|
||||||
@FactoryOption("Remote process server options (untested)")
|
|
||||||
public final Property<String> agentTransportOption =
|
|
||||||
Property.fromAccessors(String.class, this::getAgentTransport, this::setAgentTransport);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CompletableFuture<? extends DebuggerObjectModel> build() {
|
|
||||||
DbgModelImpl model = new DbgModelImpl();
|
|
||||||
List<String> cmds = new ArrayList<>();
|
|
||||||
completeCommandLine(cmds);
|
|
||||||
return model.startDbgEng(cmds.toArray(new String[cmds.size()])).thenApply(__ -> model);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getPriority(Program program) {
|
|
||||||
// TODO: Might instead look for the DLL
|
|
||||||
if (!System.getProperty("os.name").toLowerCase().contains("windows")) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (program != null) {
|
|
||||||
String exe = program.getExecutablePath();
|
|
||||||
if (exe == null || exe.isBlank()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 80;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAgentTransport() {
|
|
||||||
return transport;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAgentTransport(String transport) {
|
|
||||||
this.transport = transport;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAgentRemote() {
|
|
||||||
return remote;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAgentRemote(String remote) {
|
|
||||||
this.remote = remote;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void completeCommandLine(List<String> cmd) {
|
|
||||||
if (!remote.equals("none") && !remote.equals("")) {
|
|
||||||
cmd.addAll(List.of(remote));
|
|
||||||
}
|
|
||||||
if (!transport.equals("none") && !transport.equals("")) {
|
|
||||||
cmd.addAll(List.of(transport));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
import com.sun.jna.platform.win32.WinNT.HRESULT;
|
|
||||||
import com.sun.jna.platform.win32.COM.COMException;
|
|
||||||
import com.sun.jna.platform.win32.COM.COMUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utilities for interacting with Microsoft COM objects beyond those provided by {@link COMUtils}.
|
|
||||||
*
|
|
||||||
* See the MSDN for details on the meanings of the return codes for the function or method of
|
|
||||||
* interest.
|
|
||||||
*/
|
|
||||||
public interface COMUtilsExtra {
|
|
||||||
|
|
||||||
public static HRESULT E_UNEXPECTED = new HRESULT(0x8000FFFF);
|
|
||||||
public static HRESULT E_BOUNDS = new HRESULT(0x8000000B);
|
|
||||||
public static HRESULT E_NOTIMPLEMENTED = new HRESULT(0x80004001);
|
|
||||||
public static HRESULT E_NOINTERFACE = new HRESULT(0x80004002);
|
|
||||||
public static HRESULT E_COM_EXC = new HRESULT(0x80004003);
|
|
||||||
public static HRESULT E_FAIL = new HRESULT(0x80004005);
|
|
||||||
public static HRESULT E_CANTCALLOUT_INASYNCCALL = new HRESULT(0x80010004);
|
|
||||||
public static HRESULT E_INTERNALEXCEPTION = new HRESULT(0x80040205);
|
|
||||||
public static HRESULT E_ACCESS_DENIED = new HRESULT(0x80070005);
|
|
||||||
public static HRESULT E_CANNOT_READ = new HRESULT(0x8007001E);
|
|
||||||
public static HRESULT E_INVALID_PARAM = new HRESULT(0x80070057);
|
|
||||||
public static HRESULT E_SCOPE_NOT_FOUND = new HRESULT(0x8007013E);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the given exception represents an {@code E_NOINTERFACE} result
|
|
||||||
*
|
|
||||||
* @param e the exception
|
|
||||||
* @return true if {@code E_NOINTERFACE}
|
|
||||||
*/
|
|
||||||
static boolean isE_NOINTERFACE(COMException e) {
|
|
||||||
return E_NOINTERFACE.equals(e.getHresult());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the given exception represents an {@code E_UNEXPECTED} result
|
|
||||||
*
|
|
||||||
* @param e the exception
|
|
||||||
* @return true if {@code E_UNEXPECTED}
|
|
||||||
*/
|
|
||||||
static boolean isE_UNEXPECTED(COMException e) {
|
|
||||||
return E_UNEXPECTED.equals(e.getHresult());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the given exception represents an {@code E_INTERNALEXCEPTION} result
|
|
||||||
*
|
|
||||||
* @param e the exception
|
|
||||||
* @return true if {@code E_INTERNALEXCEPTION}
|
|
||||||
*/
|
|
||||||
static boolean isE_INTERNALEXCEPTION(COMException e) {
|
|
||||||
return E_INTERNALEXCEPTION.equals(e.getHresult());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,163 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
import java.lang.ref.Cleaner;
|
|
||||||
|
|
||||||
import com.sun.jna.WString;
|
|
||||||
import com.sun.jna.platform.win32.Kernel32Util;
|
|
||||||
import com.sun.jna.platform.win32.WinDef.DWORD;
|
|
||||||
import com.sun.jna.platform.win32.WinNT.HANDLE;
|
|
||||||
import com.sun.jna.platform.win32.COM.IUnknown;
|
|
||||||
|
|
||||||
import agent.dbgeng.impl.dbgeng.client.DebugClientInternal;
|
|
||||||
import agent.dbgeng.jna.dbgeng.DbgEngNative;
|
|
||||||
import ghidra.comm.util.BitmaskSet;
|
|
||||||
import ghidra.util.Msg;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper for Microsoft's {@code dbgeng.dll} that presents a Java-friendly interface.
|
|
||||||
*
|
|
||||||
* This is the "root interface" from which all other interfaces to {@code dbgeng.dll} are generated.
|
|
||||||
* Not every method listed in the documentation, nor every method present in the header, is
|
|
||||||
* implemented. Only those that were necessary to implement the SCTL adapter. However, the class and
|
|
||||||
* interface hierarchy was designed so that adding the remaining methods should be fairly
|
|
||||||
* straightforward. This wrapper attempts to obtain the most capable COM interfaces for the debug
|
|
||||||
* client that it knows. Again, newer interfaces should be fairly straightforward to add.
|
|
||||||
*
|
|
||||||
* Methods that are "obviously" wrappers for a COM method are left undocumented, unless there is
|
|
||||||
* some nuance to how it has been wrapped. In many cases, a parameter which is an integer in the COM
|
|
||||||
* method may be presented as an {@code enum} or {@link BitmaskSet} by the wrapper. Consult the MSDN
|
|
||||||
* for the meaning of the various values and bit flags.
|
|
||||||
*
|
|
||||||
* Each wrapper interface is implemented by several COM interface wrappers: one for each known COM
|
|
||||||
* interface version. The wrapper is optimistic, in that it declares wrapper methods even for COM
|
|
||||||
* methods that are only available in later versions. The implementations limited to earlier COM
|
|
||||||
* interfaces should either emulate the operation, or throw an
|
|
||||||
* {@link UnsupportedOperationException}. Where a newer method is provided by a newer interface, a
|
|
||||||
* wrapper implementation should prefer the latest. For example, one series of interfaces introduces
|
|
||||||
* {@code *Wide} variants of existing methods. Since Java also uses a UTF-16-like string encoding
|
|
||||||
* internally, JNA permits wide strings to be passed by reference. Thus, the wide variant is always
|
|
||||||
* preferred.
|
|
||||||
*
|
|
||||||
* Pay careful attention to the threading requirements imposed by {@code dbgeng.dll} these can be
|
|
||||||
* found in the MSDN. As a general rule of thumb, if the method is reentrant (i.e., it can be called
|
|
||||||
* from any thread), it is declared in the {@code *Reentrant} variant of the wrapper interface.
|
|
||||||
* There are few of these. Unless the documentation explicitly lists the method as reentrant, do not
|
|
||||||
* declare it there. Many methods appear to execute successfully from the wrong thread, but cause
|
|
||||||
* latent issues. A practice to prevent accidental use of non-reentrant methods outside of the
|
|
||||||
* client's owning thread is to ensure that only the owning thread can see the full interface. All
|
|
||||||
* other threads should only have access to the reentrant interface.
|
|
||||||
*
|
|
||||||
* If you implement methods that introduce a new callback class, use the existing callback type
|
|
||||||
* hierarchies as a model. There are many classes to implement. Furthermore, be sure to keep a
|
|
||||||
* reference to any active callback instances within the wrapper that uses them. The JNA has no way
|
|
||||||
* of knowing whether or not the instance is still being used by the external C/C++ library. If you
|
|
||||||
* do not store a reference, the JVM will think it's garbage and free it, even though COM is still
|
|
||||||
* using it. Drop the reference only when you are certain nothing external has a reference to it.
|
|
||||||
*/
|
|
||||||
public class DbgEng {
|
|
||||||
private static final Cleaner CLEANER = Cleaner.create();
|
|
||||||
|
|
||||||
private static class ReleaseCOMObject implements Runnable {
|
|
||||||
private final IUnknown obj;
|
|
||||||
|
|
||||||
ReleaseCOMObject(IUnknown obj) {
|
|
||||||
this.obj = obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Msg.debug(this, "Releasing COM object: " + obj);
|
|
||||||
obj.Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ReleaseHANDLE implements Runnable {
|
|
||||||
private final HANDLE handle;
|
|
||||||
|
|
||||||
public ReleaseHANDLE(HANDLE handle) {
|
|
||||||
this.handle = handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Kernel32Util.closeHandle(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class OpaqueCleanable {
|
|
||||||
@SuppressWarnings("unused") // A reference to control GC
|
|
||||||
private final Object state;
|
|
||||||
@SuppressWarnings("unused") // A reference to control GC
|
|
||||||
private final Cleaner.Cleanable cleanable;
|
|
||||||
|
|
||||||
public OpaqueCleanable(Object state, Cleaner.Cleanable cleanable) {
|
|
||||||
this.state = state;
|
|
||||||
this.cleanable = cleanable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static OpaqueCleanable releaseWhenPhantom(Object owner, IUnknown obj) {
|
|
||||||
ReleaseCOMObject state = new ReleaseCOMObject(obj);
|
|
||||||
return new OpaqueCleanable(state, CLEANER.register(owner, state));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static OpaqueCleanable releaseWhenPhantom(Object owner, HANDLE handle) {
|
|
||||||
ReleaseHANDLE state = new ReleaseHANDLE(handle);
|
|
||||||
return new OpaqueCleanable(state, CLEANER.register(owner, state));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connect to a debug session.
|
|
||||||
*
|
|
||||||
* See {@code DebugConnect} or {@code DebugConnectWide} on the MSDN.
|
|
||||||
*
|
|
||||||
* @param remoteOptions the options, like those given to {@code -remote}
|
|
||||||
* @return a new client connected as specified
|
|
||||||
*/
|
|
||||||
public static DebugClient debugConnect(String remoteOptions) {
|
|
||||||
WString options = new WString(remoteOptions);
|
|
||||||
return DebugClientInternal.tryPreferredInterfaces((refiid,
|
|
||||||
ppClient) -> DbgEngNative.INSTANCE.DebugConnectWide(options, refiid, ppClient));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a debug client.
|
|
||||||
*
|
|
||||||
* Typically, this client is connected to the "local server". See {@code DebugCreate} on the
|
|
||||||
* MSDN.
|
|
||||||
*
|
|
||||||
* @return a new client
|
|
||||||
*/
|
|
||||||
public static DebugClient debugCreate() {
|
|
||||||
return DebugClientInternal.tryPreferredInterfaces(DbgEngNative.INSTANCE::DebugCreate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a debug client with the given options.
|
|
||||||
*
|
|
||||||
* See {@code DebugCreateEx} on the MSDN.
|
|
||||||
*
|
|
||||||
* @param options the options
|
|
||||||
* @return a new client
|
|
||||||
*/
|
|
||||||
public static DebugClient debugCreate(int options) {
|
|
||||||
DWORD dwOpts = new DWORD(options);
|
|
||||||
return DebugClientInternal.tryPreferredInterfaces(
|
|
||||||
(refiid, ppClient) -> DbgEngNative.INSTANCE.DebugCreateEx(refiid, dwOpts, ppClient));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper for {@code IDebugAdvanced} and its newer variants.
|
|
||||||
*/
|
|
||||||
public interface DebugAdvanced {
|
|
||||||
public static class DebugThreadBasicInformation {
|
|
||||||
public final Integer exitStatus;
|
|
||||||
public final Integer priorityClass;
|
|
||||||
public final Integer priority;
|
|
||||||
public final Long createTime;
|
|
||||||
public final Long exitTime;
|
|
||||||
public final Long kernelTime;
|
|
||||||
public final Long userTime;
|
|
||||||
public final Long startOffset;
|
|
||||||
public final Long affinity;
|
|
||||||
|
|
||||||
public DebugThreadBasicInformation(Integer exitStatus, Integer priorityClass,
|
|
||||||
Integer priority, Long createTime, Long exitTime, Long kernelTime, Long userTime,
|
|
||||||
Long startOffset, Long affinity) {
|
|
||||||
this.exitStatus = exitStatus;
|
|
||||||
this.priorityClass = priorityClass;
|
|
||||||
this.priority = priority;
|
|
||||||
this.createTime = createTime;
|
|
||||||
this.exitTime = exitTime;
|
|
||||||
this.kernelTime = kernelTime;
|
|
||||||
this.userTime = userTime;
|
|
||||||
this.startOffset = startOffset;
|
|
||||||
this.affinity = affinity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder sb = new StringBuilder("<DebugThreadBasicInformation:\n");
|
|
||||||
if (exitStatus != null) {
|
|
||||||
sb.append(" exitStatus: " + exitStatus + "\n");
|
|
||||||
}
|
|
||||||
if (priorityClass != null) {
|
|
||||||
sb.append(" priorityClass: " + priorityClass + "\n");
|
|
||||||
}
|
|
||||||
if (priority != null) {
|
|
||||||
sb.append(" priority: " + priority + "\n");
|
|
||||||
}
|
|
||||||
if (createTime != null) {
|
|
||||||
sb.append(" createTime: " + createTime + "\n");
|
|
||||||
}
|
|
||||||
if (exitTime != null) {
|
|
||||||
sb.append(" exitTime: " + exitTime + "\n");
|
|
||||||
}
|
|
||||||
if (kernelTime != null) {
|
|
||||||
sb.append(" kernelTime: " + kernelTime + "\n");
|
|
||||||
}
|
|
||||||
if (userTime != null) {
|
|
||||||
sb.append(" userTime: " + userTime + "\n");
|
|
||||||
}
|
|
||||||
if (startOffset != null) {
|
|
||||||
sb.append(" startOffset: " + startOffset + "\n");
|
|
||||||
}
|
|
||||||
if (affinity != null) {
|
|
||||||
sb.append(" affinity: " + affinity + "\n");
|
|
||||||
}
|
|
||||||
sb.append(">");
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugThreadBasicInformation getThreadBasicInformation(DebugThreadId tid);
|
|
||||||
}
|
|
|
@ -1,137 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
import agent.dbgeng.jna.dbgeng.WinNTExtra.Machine;
|
|
||||||
import ghidra.comm.util.BitmaskSet;
|
|
||||||
import ghidra.comm.util.BitmaskUniverse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper for {@code IDebugBreakpoint} and its newer variants.
|
|
||||||
*/
|
|
||||||
public interface DebugBreakpoint {
|
|
||||||
public static enum BreakType {
|
|
||||||
CODE, DATA, TIME, INLINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class BreakFullType {
|
|
||||||
public final BreakType breakType;
|
|
||||||
public final Machine procType; // TODO: Guessing the values are from WinNT
|
|
||||||
|
|
||||||
public BreakFullType(BreakType breakType, Machine procType) {
|
|
||||||
this.breakType = breakType;
|
|
||||||
this.procType = procType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum BreakFlags implements BitmaskUniverse {
|
|
||||||
GO_ONLY(1 << 0), //
|
|
||||||
DEFERRED(1 << 1), //
|
|
||||||
ENABLED(1 << 2), //
|
|
||||||
ADDER_ONLY(1 << 3), //
|
|
||||||
ONE_SHOT(1 << 4), //
|
|
||||||
;
|
|
||||||
|
|
||||||
private BreakFlags(int mask) {
|
|
||||||
this.mask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int mask;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum BreakAccess implements BitmaskUniverse {
|
|
||||||
READ(1 << 0), //
|
|
||||||
WRITE(1 << 1), //
|
|
||||||
EXECUTE(1 << 2), //
|
|
||||||
IO(1 << 3), //
|
|
||||||
;
|
|
||||||
|
|
||||||
private BreakAccess(int mask) {
|
|
||||||
this.mask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int mask;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class BreakDataParameters {
|
|
||||||
public int size;
|
|
||||||
public BitmaskSet<BreakAccess> access;
|
|
||||||
|
|
||||||
public BreakDataParameters(int size, BitmaskSet<BreakAccess> access) {
|
|
||||||
this.size = size;
|
|
||||||
this.access = access;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove();
|
|
||||||
|
|
||||||
int getId();
|
|
||||||
|
|
||||||
BreakFullType getType();
|
|
||||||
|
|
||||||
DebugClient getAdder();
|
|
||||||
|
|
||||||
BitmaskSet<BreakFlags> getFlags();
|
|
||||||
|
|
||||||
void addFlags(BitmaskSet<BreakFlags> flags);
|
|
||||||
|
|
||||||
void addFlags(BreakFlags... flags);
|
|
||||||
|
|
||||||
void removeFlags(BitmaskSet<BreakFlags> flags);
|
|
||||||
|
|
||||||
void removeFlags(BreakFlags... flags);
|
|
||||||
|
|
||||||
void setFlags(BitmaskSet<BreakFlags> flags);
|
|
||||||
|
|
||||||
void setFlags(BreakFlags... flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the location on target that triggers the breakpoint
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* If the breakpoint is deferred, this will return {@code null}. In that case, use
|
|
||||||
* {@link #getOffsetExpression()}.
|
|
||||||
*
|
|
||||||
* @return the offset, or {@code null}
|
|
||||||
*/
|
|
||||||
Long getOffset();
|
|
||||||
|
|
||||||
void setOffset(long offset);
|
|
||||||
|
|
||||||
String getOffsetExpression();
|
|
||||||
|
|
||||||
void setOffsetExpression(String expression);
|
|
||||||
|
|
||||||
BreakDataParameters getDataParameters();
|
|
||||||
|
|
||||||
void setDataParameters(BreakDataParameters params);
|
|
||||||
|
|
||||||
void setDataParameters(int size, BitmaskSet<BreakAccess> access);
|
|
||||||
|
|
||||||
void setDataParameters(int size, BreakAccess... access);
|
|
||||||
|
|
||||||
void dispose();
|
|
||||||
}
|
|
|
@ -1,434 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.sun.jna.platform.win32.WinBase;
|
|
||||||
|
|
||||||
import agent.dbgeng.dbgeng.DebugRunningProcess.Description;
|
|
||||||
import agent.dbgeng.dbgeng.DebugRunningProcess.Description.ProcessDescriptionFlags;
|
|
||||||
import ghidra.comm.util.BitmaskSet;
|
|
||||||
import ghidra.comm.util.BitmaskUniverse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper for {@code IDebugClient} and its newer variants.
|
|
||||||
*/
|
|
||||||
public interface DebugClient extends DebugClientReentrant {
|
|
||||||
public static enum ExecutionState {
|
|
||||||
RUNNING, STOPPED;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum DebugStatus {
|
|
||||||
NO_CHANGE(false, null, 13), //
|
|
||||||
GO(true, ExecutionState.RUNNING, 10), //
|
|
||||||
GO_HANDLED(true, ExecutionState.RUNNING, 9), //
|
|
||||||
GO_NOT_HANDLED(true, ExecutionState.RUNNING, 8), //
|
|
||||||
STEP_OVER(true, ExecutionState.RUNNING, 7), //
|
|
||||||
STEP_INTO(true, ExecutionState.RUNNING, 5), //
|
|
||||||
BREAK(false, ExecutionState.STOPPED, 0), //
|
|
||||||
NO_DEBUGGEE(true, null, 1), // shouldWait is true to handle process creation
|
|
||||||
STEP_BRANCH(true, ExecutionState.RUNNING, 6), //
|
|
||||||
IGNORE_EVENT(false, null, 11), //
|
|
||||||
RESTART_REQUESTED(true, null, 12), //
|
|
||||||
REVERSE_GO(true, null, 0xff), //
|
|
||||||
REVERSE_STEP_BRANCH(true, null, 0xff), //
|
|
||||||
REVERSE_STEP_OVER(true, null, 0xff), //
|
|
||||||
REVERSE_STEP_INTO(true, null, 0xff), //
|
|
||||||
OUT_OF_SYNC(false, null, 2), //
|
|
||||||
WAIT_INPUT(false, null, 3), //
|
|
||||||
TIMEOUT(false, null, 4), //
|
|
||||||
;
|
|
||||||
|
|
||||||
public static final long MASK = 0xaf;
|
|
||||||
public static final long INSIDE_WAIT = 0x100000000L;
|
|
||||||
public static final long WAIT_TIMEOUT = 0x200000000L;
|
|
||||||
|
|
||||||
DebugStatus(boolean shouldWait, ExecutionState threadState, int precedence) {
|
|
||||||
this.shouldWait = shouldWait;
|
|
||||||
this.threadState = threadState;
|
|
||||||
this.precedence = precedence;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean shouldWait;
|
|
||||||
public final ExecutionState threadState;
|
|
||||||
public final int precedence; // 0 is highest
|
|
||||||
|
|
||||||
public static DebugStatus fromArgument(long argument) {
|
|
||||||
return values()[(int) (argument & MASK)];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isInsideWait(long argument) {
|
|
||||||
return (argument & INSIDE_WAIT) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isWaitTimeout(long argument) {
|
|
||||||
return (argument & WAIT_TIMEOUT) != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum SessionStatus {
|
|
||||||
ACTIVE, //
|
|
||||||
END_SESSION_ACTIVE_TERMINATE,//
|
|
||||||
END_SESSION_ACTIVE_DETACH, //
|
|
||||||
END_SESSION_PASSIVE, //
|
|
||||||
END, //
|
|
||||||
REBOOT, //
|
|
||||||
HIBERNATE, //
|
|
||||||
FAILURE, //
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum ChangeDebuggeeState implements BitmaskUniverse {
|
|
||||||
ALL(0xffffffff), //
|
|
||||||
REGISTERS(1 << 0), //
|
|
||||||
DATA(1 << 1), //
|
|
||||||
REFRESH(1 << 2), //
|
|
||||||
;
|
|
||||||
|
|
||||||
private ChangeDebuggeeState(int mask) {
|
|
||||||
this.mask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int mask;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum ChangeEngineState implements BitmaskUniverse {
|
|
||||||
ALL(0xffffffff), //
|
|
||||||
CURRENT_THREAD(1 << 0), //
|
|
||||||
EFFECTIVE_PROCESSOR(1 << 1), //
|
|
||||||
BREAKPOINTS(1 << 2), //
|
|
||||||
CODE_LEVEL(1 << 3), //
|
|
||||||
EXECUTION_STATUS(1 << 4), //
|
|
||||||
ENGINE_OPTIONS(1 << 5), //
|
|
||||||
LOG_FILE(1 << 6), //
|
|
||||||
RADIX(1 << 7), //
|
|
||||||
EVENT_FILTERS(1 << 8), //
|
|
||||||
PROCESS_OPTIONS(1 << 9), //
|
|
||||||
EXTENSIONS(1 << 10), //
|
|
||||||
SYSTEMS(1 << 11), //
|
|
||||||
ASSEMBLY_OPTIONS(1 << 12), //
|
|
||||||
EXPRESSION_SYNTAX(1 << 13), //
|
|
||||||
TEXT_REPLACEMENTS(1 << 14), //
|
|
||||||
;
|
|
||||||
|
|
||||||
private ChangeEngineState(int mask) {
|
|
||||||
this.mask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int mask;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum ChangeSymbolState implements BitmaskUniverse {
|
|
||||||
ALL(0xffffffff), //
|
|
||||||
LOADS(1 << 0), //
|
|
||||||
UNLOADS(1 << 1), //
|
|
||||||
SCOPE(1 << 2), //
|
|
||||||
PATHS(1 << 3), //
|
|
||||||
SYMBOL_OPTIONS(1 << 4), //
|
|
||||||
TYPE_OPTIONS(1 << 5), //
|
|
||||||
;
|
|
||||||
|
|
||||||
private ChangeSymbolState(int mask) {
|
|
||||||
this.mask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int mask;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum DebugAttachFlags implements BitmaskUniverse {
|
|
||||||
DEFAULT(0), //
|
|
||||||
NONINVASIVE(1 << 0), //
|
|
||||||
EXISTING(1 << 1), //
|
|
||||||
NONINVASIVE_NO_SUSPEND(1 << 2), //
|
|
||||||
INVASIVE_NO_INITIAL_BREAK(1 << 3), //
|
|
||||||
INVASIVE_RESUME_PROCESS(1 << 4), //
|
|
||||||
NONINVASIVE_ALLOW_PARTIAL(1 << 5), //
|
|
||||||
;
|
|
||||||
|
|
||||||
DebugAttachFlags(int mask) {
|
|
||||||
this.mask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int mask;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum DebugCreateFlags implements BitmaskUniverse {
|
|
||||||
DEBUG_PROCESS(WinBase.DEBUG_PROCESS), //
|
|
||||||
DEBUG_ONLY_THIS_PROCESS(WinBase.DEBUG_ONLY_THIS_PROCESS), //
|
|
||||||
CREATE_SUSPENDED(WinBase.CREATE_SUSPENDED), //
|
|
||||||
DETACHED_PROCESS(WinBase.DETACHED_PROCESS), //
|
|
||||||
|
|
||||||
CREATE_NEW_CONSOLE(WinBase.CREATE_NEW_CONSOLE), //
|
|
||||||
//NORMAL_PRIORITY_CLASS(WinBase.NORMAL_PRIORITY_CLASS), //
|
|
||||||
//IDLE_PRIORITY_CLASS(WinBase.IDLE_PRIORITY_CLASS), //
|
|
||||||
//HIGH_PRIORITY_CLASS(WinBase.HIGH_PRIORITY_CLASS), //
|
|
||||||
|
|
||||||
//REALTIME_PRIORITY_CLASS(WinBase.REALTIME_PRIORITY_CLASS), //
|
|
||||||
CREATE_NEW_PROCESS_GROUP(WinBase.CREATE_NEW_PROCESS_GROUP), //
|
|
||||||
CREATE_UNICODE_ENVIRONMENT(WinBase.CREATE_UNICODE_ENVIRONMENT), //
|
|
||||||
CREATE_SEPARATE_WOW_VDM(WinBase.CREATE_SEPARATE_WOW_VDM), //
|
|
||||||
|
|
||||||
CREATE_SHARED_WOW_VDM(WinBase.CREATE_SHARED_WOW_VDM), //
|
|
||||||
CREATE_FORCEDOS(WinBase.CREATE_FORCEDOS), //
|
|
||||||
//BELOW_NORMAL_PRIORITY_CLASS(WinBase.BELOW_NORMAL_PRIORITY_CLASS), //
|
|
||||||
//ABOVE_NORMAL_PRIORITY_CLASS(WinBase.ABOVE_NORMAL_PRIORITY_CLASS), //
|
|
||||||
|
|
||||||
INHERIT_PARENT_AFFINITY(WinBase.INHERIT_PARENT_AFFINITY), //
|
|
||||||
//INHERIT_CALLER_PRIORITY(WinBase.INHERIT_CALLER_PRIORITY), //
|
|
||||||
CREATE_PROTECTED_PROCESS(WinBase.CREATE_PROTECTED_PROCESS), //
|
|
||||||
EXTENDED_STARTUPINFO_PRESENT(WinBase.EXTENDED_STARTUPINFO_PRESENT), //
|
|
||||||
|
|
||||||
//PROCESS_MODE_BACKGROUND_BEGIN(WinBase.PROCESS_MODE_BACKGROUND_BEGIN), //
|
|
||||||
//PROCESS_MODE_BACKGROUND_END(WinBase.PROCESS_MODE_BACKGROUND_END), //
|
|
||||||
|
|
||||||
CREATE_BREAKAWAY_FROM_JOB(WinBase.CREATE_BREAKAWAY_FROM_JOB), //
|
|
||||||
CREATE_PRESERVE_CODE_AUTHZ_LEVEL(WinBase.CREATE_PRESERVE_CODE_AUTHZ_LEVEL), //
|
|
||||||
CREATE_DEFAULT_ERROR_MODE(WinBase.CREATE_DEFAULT_ERROR_MODE), //
|
|
||||||
CREATE_NO_WINDOW(WinBase.CREATE_NO_WINDOW), //
|
|
||||||
|
|
||||||
//PROFILE_USER(WinBase.PROFILE_USER), //
|
|
||||||
//PROFILE_KERNEL(WinBase.PROFILE_KERNEL), //
|
|
||||||
//PROFILE_SERVER(WinBase.PROFILE_SERVER), //
|
|
||||||
//CREATE_IGNORE_SYSTEM_DEFAULT(WinBase.CREATE_IGNORE_SYSTEM_DEFAULT), //
|
|
||||||
DEBUG_CREATE_NO_DEBUG_HEAP(0x00000400), //
|
|
||||||
DEBUG_CREATE_THROUGH_RTL(0x00010000), //
|
|
||||||
;
|
|
||||||
|
|
||||||
DebugCreateFlags(int mask) {
|
|
||||||
this.mask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int mask;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum DebugEngCreateFlags implements BitmaskUniverse {
|
|
||||||
DEBUG_ECREATE_PROCESS_DEFAULT(0x00000000),
|
|
||||||
DEBUG_ECREATE_INHERIT_HANDLES(0x00000001),
|
|
||||||
DEBUG_ECREATE_USE_VERIFIER_FLAGS(0x00000002),
|
|
||||||
DEBUG_ECREATE_USE_IMPLICIT_COMMAND_LINE(0x00000004);
|
|
||||||
|
|
||||||
DebugEngCreateFlags(int mask) {
|
|
||||||
this.mask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int mask;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum DebugVerifierFlags implements BitmaskUniverse {
|
|
||||||
DEBUG_VERIFIER_DEFAULT(0x00000000);
|
|
||||||
|
|
||||||
DebugVerifierFlags(int mask) {
|
|
||||||
this.mask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int mask;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum DebugEndSessionFlags {
|
|
||||||
DEBUG_END_PASSIVE(0x00000000),
|
|
||||||
DEBUG_END_ACTIVE_TERMINATE(0x00000001),
|
|
||||||
DEBUG_END_ACTIVE_DETACH(0x00000002),
|
|
||||||
DEBUG_END_REENTRANT(0x00000003),
|
|
||||||
DEBUG_END_DISCONNECT(0x00000004);
|
|
||||||
|
|
||||||
DebugEndSessionFlags(int value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int value;
|
|
||||||
|
|
||||||
public long getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum DebugOutputFlags {
|
|
||||||
DEBUG_OUTPUT_NORMAL(0x1), //
|
|
||||||
DEBUG_OUTPUT_ERROR(0x2), //
|
|
||||||
DEBUG_OUTPUT_WARNING(0x4), //
|
|
||||||
DEBUG_OUTPUT_VERBOSE(0x8), //
|
|
||||||
DEBUG_OUTPUT_PROMPT(0x10), //
|
|
||||||
DEBUG_OUTPUT_PROMPT_REGISTERS(0x20), //
|
|
||||||
DEBUG_OUTPUT_EXTENSION_WARNING(0x40), //
|
|
||||||
DEBUG_OUTPUT_DEBUGGEE(0x80), //
|
|
||||||
DEBUG_OUTPUT_DEBUGGEE_PROMPT(0x100), //
|
|
||||||
DEBUG_OUTPUT_SYMBOLS(0x200);
|
|
||||||
|
|
||||||
DebugOutputFlags(int value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int value;
|
|
||||||
|
|
||||||
public long getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the advanced interface to this client.
|
|
||||||
*
|
|
||||||
* @return the advanced interface
|
|
||||||
*/
|
|
||||||
DebugAdvanced getAdvanced();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the control interface to this client
|
|
||||||
*
|
|
||||||
* @return the control interface
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
DebugControl getControl();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the data spaces interface to this client
|
|
||||||
*
|
|
||||||
* @return the data spaces interface
|
|
||||||
*/
|
|
||||||
DebugDataSpaces getDataSpaces();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the registers interface to this client
|
|
||||||
*
|
|
||||||
* @return the registers interface
|
|
||||||
*/
|
|
||||||
DebugRegisters getRegisters();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the symbols interface to this client
|
|
||||||
*
|
|
||||||
* @return the symbols interface
|
|
||||||
*/
|
|
||||||
DebugSymbols getSymbols();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the system objects interface to this client
|
|
||||||
*
|
|
||||||
* @return the system objects interface
|
|
||||||
*/
|
|
||||||
DebugSystemObjects getSystemObjects();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The the ID for the local server
|
|
||||||
*
|
|
||||||
* @return the ID
|
|
||||||
*/
|
|
||||||
DebugServerId getLocalServer();
|
|
||||||
|
|
||||||
void attachKernel(long flags, String options);
|
|
||||||
|
|
||||||
void startProcessServer(String options);
|
|
||||||
|
|
||||||
DebugServerId connectProcessServer(String options);
|
|
||||||
|
|
||||||
boolean dispatchCallbacks(int timeout);
|
|
||||||
|
|
||||||
void flushCallbacks();
|
|
||||||
|
|
||||||
default void dispatchCallbacks() {
|
|
||||||
this.dispatchCallbacks(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void exitDispatch(DebugClient client);
|
|
||||||
|
|
||||||
default void exitDispatch() {
|
|
||||||
exitDispatch(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setInputCallbacks(DebugInputCallbacks cb);
|
|
||||||
|
|
||||||
void setOutputCallbacks(DebugOutputCallbacks cb);
|
|
||||||
|
|
||||||
void setEventCallbacks(DebugEventCallbacks cb);
|
|
||||||
|
|
||||||
List<DebugRunningProcess> getRunningProcesses(DebugServerId server);
|
|
||||||
|
|
||||||
Description getProcessDescription(DebugServerId si, int systemId,
|
|
||||||
BitmaskSet<ProcessDescriptionFlags> flags);
|
|
||||||
|
|
||||||
void attachProcess(DebugServerId si, long processId, BitmaskSet<DebugAttachFlags> attachFlags);
|
|
||||||
|
|
||||||
void createProcess(DebugServerId si, String commandLine,
|
|
||||||
String initialDirectory, String environment,
|
|
||||||
BitmaskSet<DebugCreateFlags> createFlags,
|
|
||||||
BitmaskSet<DebugEngCreateFlags> engCreateFlags,
|
|
||||||
BitmaskSet<DebugVerifierFlags> verifierFlags);
|
|
||||||
|
|
||||||
void createProcessAndAttach(DebugServerId si, String commandLine,
|
|
||||||
BitmaskSet<DebugCreateFlags> createFlags, int processId,
|
|
||||||
BitmaskSet<DebugAttachFlags> attachFlags);
|
|
||||||
|
|
||||||
void startServer(String options);
|
|
||||||
|
|
||||||
// Only in IDebugClient2
|
|
||||||
|
|
||||||
void waitForProcessServerEnd(int timeout);
|
|
||||||
|
|
||||||
default void waitForProcessServerEnd() {
|
|
||||||
waitForProcessServerEnd(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void terminateCurrentProcess();
|
|
||||||
|
|
||||||
void detachCurrentProcess();
|
|
||||||
|
|
||||||
void abandonCurrentProcess();
|
|
||||||
|
|
||||||
void connectSession(int flags);
|
|
||||||
|
|
||||||
void endSession(DebugEndSessionFlags flags);
|
|
||||||
|
|
||||||
// Only in IDebugClient4+
|
|
||||||
|
|
||||||
void openDumpFileWide(String fileName);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface containing the subset of {@link DebugClient} methods which are reentrant.
|
|
||||||
*
|
|
||||||
* All other methods should be called only by the thread which created the client.
|
|
||||||
*/
|
|
||||||
public interface DebugClientReentrant {
|
|
||||||
/**
|
|
||||||
* Create a new client for the calling thread, connected to the same session as this client.
|
|
||||||
*
|
|
||||||
* @return the new client
|
|
||||||
*/
|
|
||||||
DebugClient createClient();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the reentrant control interface to the client
|
|
||||||
*
|
|
||||||
* @return the control interface
|
|
||||||
*/
|
|
||||||
DebugControlReentrant getControl();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* End a session without acquiring locks
|
|
||||||
*
|
|
||||||
* Note. This method calls {@code IDebugClient::EndSession(DEBUG_END_REENTRANT)}. Per the MSDN,
|
|
||||||
* this may leave the engine in an indeterminate state. The engine should no longer be used by
|
|
||||||
* this process. It's really only appropriate to use this method when terminating the debugger.
|
|
||||||
*/
|
|
||||||
void endSessionReentrant();
|
|
||||||
}
|
|
|
@ -1,447 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.sun.jna.platform.win32.WinBase;
|
|
||||||
import com.sun.jna.platform.win32.COM.COMException;
|
|
||||||
|
|
||||||
import agent.dbgeng.dbgeng.DebugBreakpoint.BreakType;
|
|
||||||
import agent.dbgeng.dbgeng.DebugClient.DebugStatus;
|
|
||||||
import ghidra.comm.util.BitmaskSet;
|
|
||||||
import ghidra.comm.util.BitmaskUniverse;
|
|
||||||
import ghidra.util.Msg;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper for {@code IDebugControl} and its newer variants.
|
|
||||||
*/
|
|
||||||
public interface DebugControl extends DebugControlReentrant {
|
|
||||||
public static final BitmaskSet<DebugOutputControl> SET_ALL_CLIENTS =
|
|
||||||
BitmaskSet.of(DebugOutputControl.ALL_CLIENTS);
|
|
||||||
public static final BitmaskSet<DebugExecute> SET_DEFAULT = BitmaskSet.of(DebugExecute.DEFAULT);
|
|
||||||
|
|
||||||
public static enum DebugOutputLevel implements BitmaskUniverse {
|
|
||||||
NORMAL(1 << 0), //
|
|
||||||
ERROR(1 << 1), //
|
|
||||||
WARNING(1 << 2), //
|
|
||||||
VERBOSE(1 << 3), //
|
|
||||||
PROMPT(1 << 4), //
|
|
||||||
PROMPT_REGISTERS(1 << 5), //
|
|
||||||
EXTENSION_WARNING(1 << 6), //
|
|
||||||
OUTPUT_DEBUGEE(1 << 7), //
|
|
||||||
OUTPUT_DEBUGEE_PROMPT(1 << 8), //
|
|
||||||
OUTPUT_SYMBOLS(1 << 9), //
|
|
||||||
OUTPUT_STATUS(1 << 10), //
|
|
||||||
;
|
|
||||||
|
|
||||||
private final int mask;
|
|
||||||
|
|
||||||
DebugOutputLevel(int mask) {
|
|
||||||
this.mask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum DebugOutputControl implements BitmaskUniverse {
|
|
||||||
THIS_CLIENT(0), //
|
|
||||||
ALL_CLIENTS(1), //
|
|
||||||
ALL_OTHER_CLIENTS(2), //
|
|
||||||
IGNORE(3), //
|
|
||||||
LOG_ONLY(4), //
|
|
||||||
SEND_MASK(7), //
|
|
||||||
NOT_LOGGED(1 << 3), //
|
|
||||||
OVERRIDE_MASK(1 << 4), //
|
|
||||||
DML(1 << 5), //
|
|
||||||
AMBIENT_DML(0xfffffffe), //
|
|
||||||
AMBIENT_TEXT(0xffffffff), //
|
|
||||||
AMBIENT(0xffffffff), //
|
|
||||||
;
|
|
||||||
|
|
||||||
private final int mask;
|
|
||||||
|
|
||||||
DebugOutputControl(int mask) {
|
|
||||||
this.mask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum DebugExecute implements BitmaskUniverse {
|
|
||||||
DEFAULT(0), //
|
|
||||||
ECHO(1 << 0), //
|
|
||||||
NOT_LOGGED(1 << 1), //
|
|
||||||
NO_REPEAT(1 << 2), //
|
|
||||||
;
|
|
||||||
|
|
||||||
private final int mask;
|
|
||||||
|
|
||||||
DebugExecute(int mask) {
|
|
||||||
this.mask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum DebugInterrupt {
|
|
||||||
ACTIVE, //
|
|
||||||
PASSIVE, //
|
|
||||||
EXIT, //
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum DebugFilterOrdinals {
|
|
||||||
DEBUG_FILTER_CREATE_THREAD, //
|
|
||||||
DEBUG_FILTER_EXIT_THREAD, //
|
|
||||||
DEBUG_FILTER_CREATE_PROCESS, //
|
|
||||||
DEBUG_FILTER_EXIT_PROCESS, //
|
|
||||||
DEBUG_FILTER_LOAD_MODULE, //
|
|
||||||
DEBUG_FILTER_UNLOAD_MODULE, //
|
|
||||||
DEBUG_FILTER_SYSTEM_ERROR, //
|
|
||||||
DEBUG_FILTER_INITIAL_BREAKPOINT, //
|
|
||||||
DEBUG_FILTER_INITIAL_MODULE_LOAD, //
|
|
||||||
DEBUG_FILTER_DEBUGGEE_OUTPUT, //
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum DebugFilterExecutionOption {
|
|
||||||
DEBUG_FILTER_BREAK(0, "Break"), //
|
|
||||||
DEBUG_FILTER_SECOND_CHANCE_BREAK(1, "Second-chance Break"), //
|
|
||||||
DEBUG_FILTER_OUTPUT(2, "Output-only"), //
|
|
||||||
DEBUG_FILTER_IGNORE(3, "Ignore"), //
|
|
||||||
DEBUG_FILTER_REMOVE(4, "Remove"), //
|
|
||||||
;
|
|
||||||
|
|
||||||
public static DebugFilterExecutionOption getByNumber(int val) {
|
|
||||||
for (DebugFilterExecutionOption m : DebugFilterExecutionOption.values()) {
|
|
||||||
if (m.val == val) {
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugFilterExecutionOption(int val, String description) {
|
|
||||||
this.val = val;
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final int val;
|
|
||||||
public final String description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static enum DebugFilterContinuationOption {
|
|
||||||
DEBUG_FILTER_GO_HANDLED(0, "Handled"), //
|
|
||||||
DEBUG_FILTER_GO_NOT_HANDLED(1, "Not Handled"), //
|
|
||||||
;
|
|
||||||
|
|
||||||
public static DebugFilterContinuationOption getByNumber(int val) {
|
|
||||||
for (DebugFilterContinuationOption m : DebugFilterContinuationOption.values()) {
|
|
||||||
if (m.val == val) {
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugFilterContinuationOption(int val, String description) {
|
|
||||||
this.val = val;
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final int val;
|
|
||||||
public final String description;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean getInterrupt();
|
|
||||||
|
|
||||||
int getInterruptTimeout();
|
|
||||||
|
|
||||||
void setInterruptTimeout(int seconds);
|
|
||||||
|
|
||||||
void print(BitmaskSet<DebugOutputLevel> levels, String message);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut for {@link #print(BitmaskSet, String)} that includes a newline.
|
|
||||||
*
|
|
||||||
* @param levels the log levels for the message
|
|
||||||
* @param message the message
|
|
||||||
*/
|
|
||||||
void println(BitmaskSet<DebugOutputLevel> levels, String message);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut for {@link #print(BitmaskSet, String)} that applies to a single level.
|
|
||||||
*
|
|
||||||
* @param level the log level for the message
|
|
||||||
* @param message the message
|
|
||||||
*/
|
|
||||||
default void print(DebugOutputLevel level, String message) {
|
|
||||||
print(BitmaskSet.of(level), message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut for {@link #print(BitmaskSet, String)} that includes a newline and applies to a
|
|
||||||
* single level.
|
|
||||||
*
|
|
||||||
* @param level the log level for the message
|
|
||||||
* @param message the message
|
|
||||||
*/
|
|
||||||
default void println(DebugOutputLevel level, String message) {
|
|
||||||
println(BitmaskSet.of(level), message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut for {@link #print(BitmaskSet, String)} at normal level.
|
|
||||||
*
|
|
||||||
* @param message the message
|
|
||||||
*/
|
|
||||||
default void out(String message) {
|
|
||||||
print(DebugOutputLevel.NORMAL, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut for {@link #println(BitmaskSet, String)} at normal level.
|
|
||||||
*
|
|
||||||
* @param message the message
|
|
||||||
*/
|
|
||||||
default void outln(String message) {
|
|
||||||
println(DebugOutputLevel.NORMAL, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut for {@link #print(BitmaskSet, String)} at warning level.
|
|
||||||
*
|
|
||||||
* @param message the message
|
|
||||||
*/
|
|
||||||
default void warn(String message) {
|
|
||||||
print(DebugOutputLevel.WARNING, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut for {@link #println(BitmaskSet, String)} at warning level.
|
|
||||||
*
|
|
||||||
* @param message the message
|
|
||||||
*/
|
|
||||||
default void warnln(String message) {
|
|
||||||
println(DebugOutputLevel.WARNING, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut for {@link #print(BitmaskSet, String)} at error level.
|
|
||||||
*
|
|
||||||
* @param message the message
|
|
||||||
*/
|
|
||||||
default void err(String message) {
|
|
||||||
print(DebugOutputLevel.ERROR, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut for {@link #println(BitmaskSet, String)} at error level.
|
|
||||||
*
|
|
||||||
* @param message the message
|
|
||||||
*/
|
|
||||||
default void errln(String message) {
|
|
||||||
println(DebugOutputLevel.ERROR, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut for {@link #print(BitmaskSet, String)} at verbose level.
|
|
||||||
*
|
|
||||||
* @param message the message
|
|
||||||
*/
|
|
||||||
default void verb(String message) {
|
|
||||||
print(DebugOutputLevel.VERBOSE, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut for {@link #println(BitmaskSet, String)} at verbose level.
|
|
||||||
*
|
|
||||||
* @param message the message
|
|
||||||
*/
|
|
||||||
default void verbln(String message) {
|
|
||||||
println(DebugOutputLevel.VERBOSE, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
<T extends DebugValue> T evaluate(Class<T> desiredType, String expression);
|
|
||||||
|
|
||||||
void execute(BitmaskSet<DebugOutputControl> ctl, String str, BitmaskSet<DebugExecute> flags);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut for {@link #execute(BitmaskSet, String, BitmaskSet)} outputting to all clients
|
|
||||||
* with the default execution flag.
|
|
||||||
*
|
|
||||||
* @param str the command string
|
|
||||||
*/
|
|
||||||
default void execute(String str) {
|
|
||||||
execute(SET_ALL_CLIENTS, str, SET_DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void prompt(BitmaskSet<DebugOutputControl> ctl, String message);
|
|
||||||
|
|
||||||
String getPromptText();
|
|
||||||
|
|
||||||
void returnInput(String input);
|
|
||||||
|
|
||||||
DebugStatus getExecutionStatus();
|
|
||||||
|
|
||||||
void setExecutionStatus(DebugStatus status);
|
|
||||||
|
|
||||||
int getNumberBreakpoints();
|
|
||||||
|
|
||||||
DebugBreakpoint getBreakpointByIndex(int index);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shortcut to retrieve all breakpoints for the current process.
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Uses {@link #getNumberBreakpoints()} and {@link #getBreakpointByIndex(int)} to enumerate all
|
|
||||||
* breakpoints for the current process.
|
|
||||||
*
|
|
||||||
* @return the list of retrieved breakpoints.
|
|
||||||
*/
|
|
||||||
default List<DebugBreakpoint> getBreakpoints() {
|
|
||||||
int count = getNumberBreakpoints();
|
|
||||||
List<DebugBreakpoint> result = new ArrayList<>(count);
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
try {
|
|
||||||
result.add(getBreakpointByIndex(i));
|
|
||||||
}
|
|
||||||
catch (COMException e) {
|
|
||||||
if (!COMUtilsExtra.isE_NOINTERFACE(e)) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
Msg.trace(this, "Discarding private breakpoint at index " + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a breakpoint by ID
|
|
||||||
*
|
|
||||||
* According to the MSDN, though the IDs may be global, this method should only succeed for
|
|
||||||
* breakpoints belonging to the current process.
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
DebugBreakpoint getBreakpointById(int id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a (resolved) breakpoint with the given type and desired id
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This is equivalent, in part, to the {@code bp} command.
|
|
||||||
*
|
|
||||||
* @param type the type
|
|
||||||
* @param desiredId the desired id
|
|
||||||
* @return the breakpoint, disabled at offset 0
|
|
||||||
*/
|
|
||||||
DebugBreakpoint addBreakpoint(BreakType type, int desiredId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a (resolved) breakpoint with the given type and any id
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This is equivalent, in part, to the {@code bp} command.
|
|
||||||
*
|
|
||||||
* @param type the type
|
|
||||||
* @return the breakpoint, disable at offset 0
|
|
||||||
*/
|
|
||||||
DebugBreakpoint addBreakpoint(BreakType type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an unresolved breakpoint with the given type and desired id
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This is equivalent, in part, to the {@code bu} command. See the MSDN for a comparison of
|
|
||||||
* {@code bu} and {@code bp}.
|
|
||||||
*
|
|
||||||
* @param type the type
|
|
||||||
* @param desiredId the desired id
|
|
||||||
* @return the breakpoint, disabled at offset 0
|
|
||||||
*/
|
|
||||||
DebugBreakpoint addBreakpoint2(BreakType type, int desiredId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an unresolved breakpoint with the given type and any id
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* This is equivalent, in part, to the {@code bu} command. See the MSDN for a comparison of
|
|
||||||
* {@code bu} and {@code bp}.
|
|
||||||
*
|
|
||||||
* @param desiredId the desired id
|
|
||||||
* @return the breakpoint, disabled at offset 0
|
|
||||||
*/
|
|
||||||
DebugBreakpoint addBreakpoint2(BreakType type);
|
|
||||||
|
|
||||||
void waitForEvent(int timeout);
|
|
||||||
|
|
||||||
DebugEventInformation getLastEventInformation();
|
|
||||||
|
|
||||||
DebugStackInformation getStackTrace(long frameOffset, long stackOffset, long instructionOffset);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shortcut for {@link #waitForEvent(int)} with infinite timeout.
|
|
||||||
*/
|
|
||||||
default void waitForEvent() {
|
|
||||||
waitForEvent(WinBase.INFINITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int getActualProcessorType();
|
|
||||||
|
|
||||||
int getEffectiveProcessorType();
|
|
||||||
|
|
||||||
int getExecutingProcessorType();
|
|
||||||
|
|
||||||
int getDebuggeeType();
|
|
||||||
|
|
||||||
DebugFilterInformation getNumberEventFilters();
|
|
||||||
|
|
||||||
String getEventFilterText(int index, int size);
|
|
||||||
|
|
||||||
String getEventFilterCommand(int index, int size);
|
|
||||||
|
|
||||||
void setEventFilterCommand(int index, String text);
|
|
||||||
|
|
||||||
DebugSpecificFilterInformation getSpecificFilterParameters(int start, int count);
|
|
||||||
|
|
||||||
void setSpecificFilterParameters(int start, int count, DebugSpecificFilterInformation info);
|
|
||||||
|
|
||||||
String getSpecificFilterArgument(int index, int size);
|
|
||||||
|
|
||||||
void setSpecificFilterArgument(int index, String arg);
|
|
||||||
|
|
||||||
DebugExceptionFilterInformation getExceptionFilterParameters(int start, int[] codes, int count);
|
|
||||||
|
|
||||||
void setExceptionFilterParameters(int count, DebugExceptionFilterInformation info);
|
|
||||||
|
|
||||||
String getExceptionFilterSecondCommand(int index, int size);
|
|
||||||
|
|
||||||
void setExceptionFilterSecondCommand(int index, String cmd);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
import agent.dbgeng.dbgeng.DebugControl.DebugInterrupt;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface containing the subset of {@link DebugControl} methods which are reentrant.
|
|
||||||
*
|
|
||||||
* All other methods should be called only by the thread which created the client.
|
|
||||||
*/
|
|
||||||
public interface DebugControlReentrant {
|
|
||||||
void setInterrupt(DebugInterrupt interrupt);
|
|
||||||
}
|
|
|
@ -1,290 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import com.sun.jna.platform.win32.COM.COMException;
|
|
||||||
|
|
||||||
import ghidra.comm.util.BitmaskSet;
|
|
||||||
import ghidra.comm.util.BitmaskUniverse;
|
|
||||||
import ghidra.util.Msg;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper for {@code IDebugDataSpaces} and its newer variants.
|
|
||||||
*/
|
|
||||||
public interface DebugDataSpaces {
|
|
||||||
public enum PageState {
|
|
||||||
COMMIT(0x1000), FREE(0x10000), RESERVE(0x2000);
|
|
||||||
|
|
||||||
private final int val;
|
|
||||||
|
|
||||||
private PageState(int val) {
|
|
||||||
this.val = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PageState byValue(int val) {
|
|
||||||
for (PageState state : values()) {
|
|
||||||
if (state.val == val) {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Msg.warn(PageState.class, "No such value: 0x" + Integer.toHexString(val));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum PageProtection implements BitmaskUniverse {
|
|
||||||
NOACCESS(1 << 0, false, false, false), //
|
|
||||||
READONLY(1 << 1, true, false, false), //
|
|
||||||
READWRITE(1 << 2, true, true, false), //
|
|
||||||
WRITE_COPY(1 << 3, true, true, false), // Becomes READWRITE after copy
|
|
||||||
EXECUTE(1 << 4, false, false, true), //
|
|
||||||
EXECUTE_READ(1 << 5, true, false, true), //
|
|
||||||
EXECUTE_READWRITE(1 << 6, true, true, true), //
|
|
||||||
EXECUTE_WRITECOPY(1 << 7, true, true, true), //
|
|
||||||
//
|
|
||||||
GUARD(1 << 8, false, false, false), //
|
|
||||||
NOCACHE(1 << 9, false, false, false), //
|
|
||||||
WRITECOMBINE(1 << 10, false, false, false), //
|
|
||||||
;
|
|
||||||
|
|
||||||
private PageProtection(int mask, boolean isRead, boolean isWrite, boolean isExecute) {
|
|
||||||
this.mask = mask;
|
|
||||||
this.isRead = isRead;
|
|
||||||
this.isWrite = isWrite;
|
|
||||||
this.isExecute = isExecute;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int mask;
|
|
||||||
final boolean isRead;
|
|
||||||
final boolean isWrite;
|
|
||||||
final boolean isExecute;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRead() {
|
|
||||||
return isRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isWrite() {
|
|
||||||
return isWrite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isExecute() {
|
|
||||||
return isExecute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum PageType {
|
|
||||||
NONE(0), //
|
|
||||||
IMAGE(0x1000000), //
|
|
||||||
MAPPED(0x40000), //
|
|
||||||
PRIVATE(0x20000), //
|
|
||||||
;
|
|
||||||
|
|
||||||
private final int val;
|
|
||||||
|
|
||||||
private PageType(int val) {
|
|
||||||
this.val = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PageType byValue(int val) {
|
|
||||||
for (PageType type : values()) {
|
|
||||||
if (type.val == val) {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Msg.warn(PageType.class, "No such value: 0x" + Integer.toHexString(val));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class DebugMemoryBasicInformation {
|
|
||||||
public final long baseAddress;
|
|
||||||
public final long allocationBase;
|
|
||||||
public final Set<PageProtection> allocationProtect;
|
|
||||||
public final long regionSize;
|
|
||||||
public final PageState state;
|
|
||||||
public final Set<PageProtection> protect;
|
|
||||||
public final PageType type;
|
|
||||||
|
|
||||||
public DebugMemoryBasicInformation(long baseAddress, long allocationBase,
|
|
||||||
BitmaskSet<PageProtection> allocationProtect, long regionSize, PageState state,
|
|
||||||
BitmaskSet<PageProtection> protect, PageType type) {
|
|
||||||
this.baseAddress = baseAddress;
|
|
||||||
this.allocationBase = allocationBase;
|
|
||||||
this.allocationProtect = Collections.unmodifiableSet(allocationProtect);
|
|
||||||
this.regionSize = regionSize;
|
|
||||||
this.state = state;
|
|
||||||
this.protect = Collections.unmodifiableSet(protect);
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "<DebugMemoryBasicInformation:\n" + //
|
|
||||||
" baseAddress=" + Long.toHexString(baseAddress) + "h,\n" + //
|
|
||||||
" allocationBase=" + Long.toHexString(allocationBase) + "h,\n" + //
|
|
||||||
" allocationProtect=" + allocationProtect + ",\n" + //
|
|
||||||
" regionSize=" + Long.toHexString(regionSize) + "h,\n" + //
|
|
||||||
" state=" + state + ",\n" + //
|
|
||||||
" protect=" + protect + ",\n" + //
|
|
||||||
" type=" + type + "\n" + //
|
|
||||||
">";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(baseAddress, allocationBase, allocationProtect, regionSize, state,
|
|
||||||
protect, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (!(obj instanceof DebugMemoryBasicInformation)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
DebugMemoryBasicInformation that = (DebugMemoryBasicInformation) obj;
|
|
||||||
if (this.baseAddress != that.baseAddress) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.allocationBase != that.allocationBase) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!this.allocationProtect.equals(that.allocationProtect)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.regionSize != that.regionSize) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.state != that.state) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!this.protect.equals(that.protect)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.type != that.type) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int readVirtual(long offset, ByteBuffer into, int len);
|
|
||||||
|
|
||||||
int writeVirtual(long offset, ByteBuffer from, int len);
|
|
||||||
|
|
||||||
int readVirtualUncached(long offset, ByteBuffer into, int len);
|
|
||||||
|
|
||||||
int writeVirtualUncached(long offset, ByteBuffer from, int len);
|
|
||||||
|
|
||||||
int readPhysical(long offset, ByteBuffer into, int len);
|
|
||||||
|
|
||||||
int writePhysical(long offset, ByteBuffer from, int len);
|
|
||||||
|
|
||||||
int readControl(int processor, long offset, ByteBuffer into, int len);
|
|
||||||
|
|
||||||
int writeControl(int processor, long offset, ByteBuffer from, int len);
|
|
||||||
|
|
||||||
int readBusData(int busDataType, int busNumber, int slotNumber, long offset, ByteBuffer into,
|
|
||||||
int len);
|
|
||||||
|
|
||||||
int writeBusData(int busDataType, int busNumber, int slotNumber, long offset, ByteBuffer from,
|
|
||||||
int len);
|
|
||||||
|
|
||||||
int readIo(int interfaceType, int busNumber, int addressSpace, long offset, ByteBuffer into,
|
|
||||||
int len);
|
|
||||||
|
|
||||||
int writeIo(int interfaceType, int busNumber, int addressSpace, long offset, ByteBuffer from,
|
|
||||||
int len);
|
|
||||||
|
|
||||||
long readMsr(int msr);
|
|
||||||
|
|
||||||
void writeMsr(int msr, long value);
|
|
||||||
|
|
||||||
int readDebuggerData(int offset, ByteBuffer into, int len);
|
|
||||||
|
|
||||||
DebugMemoryBasicInformation queryVirtual(long offset);
|
|
||||||
|
|
||||||
long virtualToPhysical(long offset);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A shortcut for iterating over virtual memory regions.
|
|
||||||
*
|
|
||||||
* This operates by calling {@link #queryVirtual(long)} to get each next entry, starting at an
|
|
||||||
* offset of -start-, adding the size of the returned region to determine the offset for the
|
|
||||||
* next call.
|
|
||||||
*
|
|
||||||
* @param start the starting offset
|
|
||||||
* @return an iterator over virtual memory regions after the given start
|
|
||||||
*/
|
|
||||||
default Iterable<DebugMemoryBasicInformation> iterateVirtual(long start) {
|
|
||||||
return new Iterable<DebugMemoryBasicInformation>() {
|
|
||||||
@Override
|
|
||||||
public Iterator<DebugMemoryBasicInformation> iterator() {
|
|
||||||
return new Iterator<DebugMemoryBasicInformation>() {
|
|
||||||
private long last = start;
|
|
||||||
private long offset = start;
|
|
||||||
private DebugMemoryBasicInformation next = doGetNext();
|
|
||||||
|
|
||||||
private DebugMemoryBasicInformation getNext() {
|
|
||||||
if (Long.compareUnsigned(last, offset) < 0) {
|
|
||||||
return doGetNext();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DebugMemoryBasicInformation doGetNext() {
|
|
||||||
try {
|
|
||||||
DebugMemoryBasicInformation info = queryVirtual(offset);
|
|
||||||
last = offset;
|
|
||||||
if (info != null) {
|
|
||||||
offset += info.regionSize;
|
|
||||||
}
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
catch (COMException e) {
|
|
||||||
if (!COMUtilsExtra.isE_NOINTERFACE(e)) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return next != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DebugMemoryBasicInformation next() {
|
|
||||||
DebugMemoryBasicInformation ret = next;
|
|
||||||
next = getNext();
|
|
||||||
if (ret.equals(next)) {
|
|
||||||
next = null;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,116 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
|
||||||
|
|
||||||
import agent.dbgeng.dbgeng.DebugClient.*;
|
|
||||||
import ghidra.comm.util.BitmaskSet;
|
|
||||||
import ghidra.comm.util.BitmaskUniverse;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The interface for receiving event callbacks via {@code IDebugEventCallbacks} or a newer variant.
|
|
||||||
*
|
|
||||||
* Note: The wrapper implementation will select the appropriate native interface version.
|
|
||||||
*
|
|
||||||
* Note: Even though {@link #changeDebuggeeState(BitmaskSet, long)},
|
|
||||||
* {@link #changeEngineState(BitmaskSet, long)} and {@link #changeSymbolState(BitmaskSet, long)}
|
|
||||||
* purport to return a {@link DebugStatus}, the returned value is ignored by {@code dbgeng.dll}.
|
|
||||||
*/
|
|
||||||
public interface DebugEventCallbacks {
|
|
||||||
public static enum DebugEvent implements BitmaskUniverse {
|
|
||||||
BREAKPOINT(1 << 0), //
|
|
||||||
EXCEPTION(1 << 1), //
|
|
||||||
CREATE_THREAD(1 << 2), //
|
|
||||||
EXIT_THREAD(1 << 3), //
|
|
||||||
CREATE_PROCESS(1 << 4), //
|
|
||||||
EXIT_PROCESS(1 << 5), //
|
|
||||||
LOAD_MODULE(1 << 6), //
|
|
||||||
UNLOAD_MODULE(1 << 7), //
|
|
||||||
SYSTEM_ERROR(1 << 8), //
|
|
||||||
SESSION_STATUS(1 << 9), //
|
|
||||||
CHANGE_DEBUGEE_STATE(1 << 10), //
|
|
||||||
CHANGE_ENGINE_STATE(1 << 11), //
|
|
||||||
CHANGE_SYMBOL_STATE(1 << 12), //
|
|
||||||
;
|
|
||||||
|
|
||||||
private DebugEvent(int mask) {
|
|
||||||
this.mask = mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final int mask;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getMask() {
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An annotation for marking each callback with its interest flag.
|
|
||||||
*/
|
|
||||||
@Target(ElementType.METHOD)
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
static @interface ForInterest {
|
|
||||||
/**
|
|
||||||
* The flag corresponding to the annotated callback method
|
|
||||||
*
|
|
||||||
* @return the flag
|
|
||||||
*/
|
|
||||||
DebugEvent value();
|
|
||||||
}
|
|
||||||
|
|
||||||
BitmaskSet<DebugEvent> getInterestMask();
|
|
||||||
|
|
||||||
@ForInterest(DebugEvent.BREAKPOINT)
|
|
||||||
DebugStatus breakpoint(DebugBreakpoint bp);
|
|
||||||
|
|
||||||
@ForInterest(DebugEvent.EXCEPTION)
|
|
||||||
DebugStatus exception(DebugExceptionRecord64 exception, boolean firstChance);
|
|
||||||
|
|
||||||
@ForInterest(DebugEvent.CREATE_THREAD)
|
|
||||||
DebugStatus createThread(DebugThreadInfo debugThreadInfo);
|
|
||||||
|
|
||||||
@ForInterest(DebugEvent.EXIT_THREAD)
|
|
||||||
DebugStatus exitThread(int exitCode);
|
|
||||||
|
|
||||||
@ForInterest(DebugEvent.CREATE_PROCESS)
|
|
||||||
DebugStatus createProcess(DebugProcessInfo debugProcessInfo);
|
|
||||||
|
|
||||||
@ForInterest(DebugEvent.EXIT_PROCESS)
|
|
||||||
DebugStatus exitProcess(int exitCode);
|
|
||||||
|
|
||||||
@ForInterest(DebugEvent.LOAD_MODULE)
|
|
||||||
DebugStatus loadModule(DebugModuleInfo debugModuleInfo);
|
|
||||||
|
|
||||||
@ForInterest(DebugEvent.UNLOAD_MODULE)
|
|
||||||
DebugStatus unloadModule(String imageBaseName, long baseOffset);
|
|
||||||
|
|
||||||
@ForInterest(DebugEvent.SYSTEM_ERROR)
|
|
||||||
DebugStatus systemError(int error, int level);
|
|
||||||
|
|
||||||
@ForInterest(DebugEvent.SESSION_STATUS)
|
|
||||||
DebugStatus sessionStatus(SessionStatus status);
|
|
||||||
|
|
||||||
@ForInterest(DebugEvent.CHANGE_DEBUGEE_STATE)
|
|
||||||
DebugStatus changeDebuggeeState(BitmaskSet<ChangeDebuggeeState> flags, long argument);
|
|
||||||
|
|
||||||
@ForInterest(DebugEvent.CHANGE_ENGINE_STATE)
|
|
||||||
DebugStatus changeEngineState(BitmaskSet<ChangeEngineState> flags, long argument);
|
|
||||||
|
|
||||||
@ForInterest(DebugEvent.CHANGE_SYMBOL_STATE)
|
|
||||||
DebugStatus changeSymbolState(BitmaskSet<ChangeSymbolState> flags, long argument);
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
import agent.dbgeng.jna.dbgeng.WinNTExtra;
|
|
||||||
|
|
||||||
public class DebugEventInformation {
|
|
||||||
|
|
||||||
private int type;
|
|
||||||
private DebugProcessId pid;
|
|
||||||
private DebugThreadId tid;
|
|
||||||
private DebugSessionId sid;
|
|
||||||
private int executingProcessorType = WinNTExtra.Machine.IMAGE_FILE_MACHINE_AMD64.val;
|
|
||||||
|
|
||||||
public DebugEventInformation(int type, int pid, int tid) {
|
|
||||||
this.type = type;
|
|
||||||
this.pid = new DebugProcessRecord(pid);
|
|
||||||
this.tid = new DebugThreadRecord(tid);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DebugSessionId getSessionId() {
|
|
||||||
return sid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DebugProcessId getProcessId() {
|
|
||||||
return pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DebugThreadId getThreadId() {
|
|
||||||
return tid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setThread(DebugThreadId tid) {
|
|
||||||
this.tid = tid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProcess(DebugProcessId pid) {
|
|
||||||
this.pid = pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSession(DebugSessionId sid) {
|
|
||||||
this.sid = sid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getExecutingProcessorType() {
|
|
||||||
return executingProcessorType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExecutingProcessorType(int execType) {
|
|
||||||
this.executingProcessorType = execType;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
import agent.dbgeng.jna.dbgeng.DbgEngNative.DEBUG_EXCEPTION_FILTER_PARAMETERS;
|
|
||||||
|
|
||||||
public class DebugExceptionFilterInformation {
|
|
||||||
|
|
||||||
private int nParams;
|
|
||||||
private DEBUG_EXCEPTION_FILTER_PARAMETERS[] parameters;
|
|
||||||
|
|
||||||
public DebugExceptionFilterInformation(int nParams,
|
|
||||||
DEBUG_EXCEPTION_FILTER_PARAMETERS[] parameters) {
|
|
||||||
this.nParams = nParams;
|
|
||||||
this.parameters = parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumberOfParameters() {
|
|
||||||
return nParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DEBUG_EXCEPTION_FILTER_PARAMETERS getParameter(int paramNumber) {
|
|
||||||
return parameters[paramNumber];
|
|
||||||
}
|
|
||||||
|
|
||||||
public DEBUG_EXCEPTION_FILTER_PARAMETERS[] getParameters() {
|
|
||||||
return parameters;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data copied from a {@code EXCEPTION_RECORD64} as defined in {@code winnt.h}.
|
|
||||||
*
|
|
||||||
* TODO: Some enums, flags, etc., to help interpret some of the fields.
|
|
||||||
*/
|
|
||||||
public class DebugExceptionRecord64 {
|
|
||||||
public final int code; // TODO: How to interpret
|
|
||||||
public final int flags; // TODO: How to interpret
|
|
||||||
public final long record; // TODO: How to interpret
|
|
||||||
public final long address;
|
|
||||||
public final List<Long> information;
|
|
||||||
|
|
||||||
public DebugExceptionRecord64(int code, int flags, long record, long address,
|
|
||||||
List<Long> information) {
|
|
||||||
this.code = code;
|
|
||||||
this.flags = flags;
|
|
||||||
this.record = record;
|
|
||||||
this.address = address;
|
|
||||||
this.information = Collections.unmodifiableList(information);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
public class DebugFilterInformation {
|
|
||||||
|
|
||||||
private int nEvents;
|
|
||||||
private int nSpecificExceptions;
|
|
||||||
private int nArbitraryExceptions;
|
|
||||||
|
|
||||||
public DebugFilterInformation(int nEvents, int nSpecificExceptions, int nArbitraryExceptions) {
|
|
||||||
this.nEvents = nEvents;
|
|
||||||
this.nSpecificExceptions = nSpecificExceptions;
|
|
||||||
this.nArbitraryExceptions = nArbitraryExceptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumberEvents() {
|
|
||||||
return nEvents;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumberSpecificExceptions() {
|
|
||||||
return nSpecificExceptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumberArbitraryExceptions() {
|
|
||||||
return nArbitraryExceptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The interface for receiving input callbacks via {@code IDebugInputCallbacks} or a newer variant.
|
|
||||||
*
|
|
||||||
* Note: The wrapper implementation will select the appropriate native interface version.
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface DebugInputCallbacks {
|
|
||||||
|
|
||||||
public void startInput(long bufferSize);
|
|
||||||
|
|
||||||
default void endInput() {
|
|
||||||
// Optional implementation
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle to a module (program or library image).
|
|
||||||
*/
|
|
||||||
public interface DebugModule {
|
|
||||||
public enum DebugModuleName {
|
|
||||||
IMAGE, MODULE, LOADED_IMAGE, SYMBOL_FILE, MAPPED_IMAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a name for the module.
|
|
||||||
*
|
|
||||||
* @param which identifies which name
|
|
||||||
* @return the requested name, if available
|
|
||||||
*/
|
|
||||||
String getName(DebugModuleName which);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the index assigned to this module.
|
|
||||||
*
|
|
||||||
* @return the index
|
|
||||||
*/
|
|
||||||
int getIndex();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the base address where this module is loaded, if applicable.
|
|
||||||
*
|
|
||||||
* @return the base address
|
|
||||||
*/
|
|
||||||
long getBase();
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information about a module (program or library image).
|
|
||||||
*
|
|
||||||
* The fields correspond to the parameters taken by {@code LoadModule} of
|
|
||||||
* {@code IDebugEventCallbacks}. They also appear as a subset of parameters taken by
|
|
||||||
* {@code CreateProcess} of {@code IDebugEventCallbacks}.
|
|
||||||
*/
|
|
||||||
public class DebugModuleInfo {
|
|
||||||
public final long imageFileHandle;
|
|
||||||
public final long baseOffset;
|
|
||||||
public final int moduleSize;
|
|
||||||
public final int checkSum;
|
|
||||||
public final int timeDateStamp;
|
|
||||||
private String moduleName;
|
|
||||||
private String imageName;
|
|
||||||
|
|
||||||
public DebugModuleInfo(long imageFileHandle, long baseOffset, int moduleSize, String moduleName,
|
|
||||||
String imageName, int checkSum, int timeDateStamp) {
|
|
||||||
this.imageFileHandle = imageFileHandle;
|
|
||||||
this.baseOffset = baseOffset;
|
|
||||||
this.moduleSize = moduleSize;
|
|
||||||
this.setModuleName(moduleName);
|
|
||||||
this.setImageName(imageName);
|
|
||||||
this.checkSum = checkSum;
|
|
||||||
this.timeDateStamp = timeDateStamp; // TODO: Convert to DateTime?
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return Long.toHexString(baseOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getModuleName() {
|
|
||||||
return moduleName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setModuleName(String moduleName) {
|
|
||||||
this.moduleName = moduleName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getImageName() {
|
|
||||||
return imageName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setImageName(String imageName) {
|
|
||||||
this.imageName = imageName;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
/* ###
|
|
||||||
* 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.dbgeng.dbgeng;
|
|
||||||
|
|
||||||
import agent.dbgeng.dbgeng.DebugControl.DebugOutputLevel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The interface for receiving output callbacks via {@code IDebugOutputCallbacks} or a newer
|
|
||||||
* variant.
|
|
||||||
*
|
|
||||||
* Note: The wrapper implementation will select the apprirate native interface version.
|
|
||||||
*
|
|
||||||
* TODO: Change {@link #output(int, String)} {@code mask} parameter to use {@link DebugOutputLevel}
|
|
||||||
* flags.
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface DebugOutputCallbacks {
|
|
||||||
void output(int mask, String text);
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue