mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 09:49:23 +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
|
||||
.settings/
|
||||
.prefs
|
||||
.pydevproject
|
||||
|
||||
# Ignore XTEXT generated dirs/files
|
||||
*/*/*/*/xtend-gen
|
||||
|
@ -81,12 +82,12 @@ Release
|
|||
*.iml
|
||||
.idea
|
||||
|
||||
# Ignore gradle wrapper files
|
||||
gradle/wrapper
|
||||
gradlew
|
||||
gradlew.*
|
||||
|
||||
# Ignore logs and core dumps
|
||||
*.log
|
||||
core.*
|
||||
!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
|
||||
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
|
||||
will be stored at `$HOME/.gradle/`.
|
||||
```
|
||||
$ gradle prepdev
|
||||
gradle prepdev
|
||||
```
|
||||
|
||||
Generate nested Eclipse project files which can then be imported into Eclipse as "existing
|
||||
projects".
|
||||
```
|
||||
$ gradle cleanEclipse eclipse
|
||||
gradle cleanEclipse eclipse
|
||||
```
|
||||
|
||||
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.
|
||||
```
|
||||
$ gradle sleighCompile
|
||||
gradle sleighCompile
|
||||
```
|
||||
|
||||
Build Javadoc:
|
||||
```
|
||||
$ gradle createJavadocs
|
||||
gradle createJavadocs
|
||||
```
|
||||
|
||||
Build Ghidra to `build/dist`. This will be a distribution intended only to run on the platform on
|
||||
which it was built.
|
||||
Build Python3 packages for the Debugger:
|
||||
```
|
||||
$ 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
|
||||
|
@ -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
|
||||
prevent specific tasks from running:
|
||||
```
|
||||
$ gradle buildGhidra -x ip
|
||||
gradle buildGhidra -x ip
|
||||
```
|
||||
|
||||
## 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
|
||||
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`
|
||||
3. Move ghidra directory to different 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:
|
||||
|
||||
```
|
||||
$ gradle eclipse -PeclipsePDE
|
||||
gradle eclipse -PeclipsePDE
|
||||
```
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
## Running tests
|
||||
To run unit tests, do:
|
||||
```
|
||||
$ gradle unitTestReport
|
||||
gradle unitTestReport
|
||||
```
|
||||
|
||||
For more complex integration tests, do:
|
||||
```
|
||||
$ gradle integrationTest
|
||||
gradle integrationTest
|
||||
```
|
||||
|
||||
For running both unit and integration tests and to generate a report do:
|
||||
```
|
||||
$ gradle combinedTestReport
|
||||
gradle combinedTestReport
|
||||
```
|
||||
|
||||
## Setup build in CI
|
||||
|
||||
For running tests in headless mode on Linux, in a CI environment, or in Docker, first do:
|
||||
```
|
||||
$ Xvfb :99 -nolisten tcp &
|
||||
$ export DISPLAY=:99
|
||||
Xvfb :99 -nolisten tcp &
|
||||
export DISPLAY=:99
|
||||
```
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
In addition to Ghidra's normal dependencies, you may want the following:
|
||||
|
||||
* WinDbg for Windows x64
|
||||
* GDB 8.0 or later for Linux amd64/x86_64
|
||||
* LLDB 13.0 for macOS
|
||||
* GDB 13 or later for Linux
|
||||
* LLDB 10 or later for macOS
|
||||
|
||||
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
|
||||
description and status.
|
||||
|
||||
* ProposedUtils - a collection of utilities proposed to be moved to other respective projects
|
||||
* AnnotationValidator - an experimental annotation processor for database access objects
|
||||
* ProposedUtils - a collection of utilities proposed to be moved to other respective projects.
|
||||
* AnnotationValidator - an experimental annotation processor for database access objects.
|
||||
* 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
|
||||
and completable-future conveniences).
|
||||
* 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-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-dbgmodel - an experimental connector for WinDbg Preview (with TTD, via
|
||||
dbgmodel.dll) on Windows x64.
|
||||
* Debugger-agent-dbgmodel-traceloader - an experimental "importer" for WinDbg trace files.
|
||||
* Debugger-agent-gdb - the connector for GDB (8.0 or later recommended) on UNIX.
|
||||
* Debugger-swig-lldb - the Java language bindings for LLDB's SBDebugger, also proposed upstream.
|
||||
* Debugger-agent-lldb - the connector for LLDB (13.0 required) on macOS, UNIX, and Windows.
|
||||
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. This is deprecated.
|
||||
* 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. This is deprecated. We now use the Python3 language bindings for LLDB.
|
||||
* 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
|
||||
Protocol.
|
||||
* Debugger-jpda - an in-development connector for Java and Dalvik debugging via JDI (i.e., JDWP).
|
||||
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). This is deprecated and not yet replaced.
|
||||
|
||||
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
|
||||
Ghidra project and shared via a server, if desired. Trace "recording" is a de facto requirement for
|
||||
displaying information in Ghidra's UI. However, only the machine state actually observed by the user
|
||||
(or perhaps a script) is recorded. For most use cases, the Trace is small and ephemeral, serving
|
||||
only to mediate between the UI components and the target's model. It supports many of the same
|
||||
markup (e.g., disassembly, data types) as Programs, in addition to tracking active threads, loaded
|
||||
modues, breakpoints, etc.
|
||||
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.
|
||||
Trace "recording" is a de facto requirement for displaying information in Ghidra's UI.
|
||||
The back-end connector has full discretion over what is recorded by using Trace RMI.
|
||||
Typically, only the machine state actually observed by the user (or perhaps a script) is recorded.
|
||||
For most use cases, the Trace is small and ephemeral, serving only to mediate between the UI components and the target's model.
|
||||
It supports many of the same markup (e.g., disassembly, data types) as Programs, in addition to tracking active threads, loaded modues, breakpoints, etc.
|
||||
|
||||
Every model (or "adapter" or "connector" or "agent") implements the API specified in
|
||||
Framework-Debugging. 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. This allows us to contain crashes, preventing data loss. To
|
||||
accommodate this requirement -- given that debugging native applications is almost certainly going
|
||||
to require access to native APIs -- we've developed the Ghidra Asynchronous Debugging Protocol. This
|
||||
protocol is tightly coupled to Framework-Debugging, essentially exposing its methods via RMI. The
|
||||
protocol is built using Google's Protobuf library, providing a potential path for agent
|
||||
implementations in alternative languages. GADP provides both a server and a client implementation.
|
||||
The server can accept any model which adheres to the specification and expose it via TCP; the client
|
||||
does the converse. When a model is instantiated in this way, it is called an "agent," because it is
|
||||
executing in its own JVM. The other connectors, which do not use native APIs, may reside in Ghidra's
|
||||
JVM and typically implement alternative wire protocols, e.g., JDWP. In both cases, the
|
||||
implementations inherit from the same interfaces.
|
||||
Every back end (or "adapter" or "connector" or "agent") employs the Trace RMI client to populate a trace database.
|
||||
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.
|
||||
This allows us to contain crashes, preventing data loss.
|
||||
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.
|
||||
This also allows us to better bridge the language gap between Java and Python, which is supported by most native debuggers.
|
||||
This protocol is loosely coupled to Framework-TraceModeling, essentially exposing its methods via RMI, as well as some methods for controlling the UI.
|
||||
The protocol is built using Google's Protobuf library, providing a potential path for back-end implementations in alternative languages.
|
||||
We provide the Trace RMI server as a Ghidra component implemented in Java and the Trace RMI client as a Python3 package.
|
||||
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.
|
||||
It then connects to Ghidra via Trace RMI to populate the trace database with information gleaned from that API.
|
||||
It should provide a set of diagnostic commands to control and monitor that connection.
|
||||
It should also use the native API to detect session and target changes so that Ghidra's UI consistently reflects the debugging session.
|
||||
|
||||
The Debugger services maintain a collection of active connections and inspect each model for
|
||||
potential targets. When a target is found, the service inspects the target environment and attempts
|
||||
to find a suitable opinion. Such an opinion, if found, instructs Ghidra how to map the objects,
|
||||
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.
|
||||
The old system relied on a "recorder" to discover targets and map them to traces in the proper Ghidra language.
|
||||
That responsibility is now delegated to the back end.
|
||||
Typically, it examines the target's architecture and immediately creates a trace upon connection.
|
||||
|
||||
### Developing a new connector
|
||||
|
||||
So Ghidra does not yet support your favorite debugger?
|
||||
It is tempting, exciting, but also daunting to develop your own connector.
|
||||
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. Of course, in time you might also search the internet to see
|
||||
if others are developing one. There are quite a few caveats and gotchas, the most notable being that
|
||||
this interface is still in quite a bit of flux. When things go wrong, it could be because of,
|
||||
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.
|
||||
We believe the new system is much less daunting than the previous.
|
||||
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.
|
||||
Of course, in time you might also search the internet to see if others are developing one.
|
||||
There are quite a few caveats and gotchas, the most notable being that this interface is still in some flux.
|
||||
When things go wrong, it could be because of, without limitation:
|
||||
|
||||
You'll also need to provide launcher(s) so that Ghidra knows how to configure and start your
|
||||
connector. Please provide launchers for your model in both configurations: as a connector in
|
||||
Ghidra's JVM, and as a GADP agent. If your model requires native API access, you should only permit
|
||||
launching it as a GADP agent, unless you give ample warning in the launcher's description. Look at
|
||||
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
|
||||
with and without GADP. Testing with GADP tends to reveal those implementation errors, but also
|
||||
obscures the source of client method calls behind network messages. We've also codified (or
|
||||
attempted to codify) these requirements in a suite of abstract test cases. See the `ghidra.dbg.test`
|
||||
package of Framework-Debugging, and again, look at existing implementations.
|
||||
1. A bug on your part
|
||||
2. A bug on our part
|
||||
3. A design flaw in the interfaces
|
||||
4. A bug in the debugger/API you're adapting
|
||||
|
||||
We are still (yes, still) in the process of writing up this documentation.
|
||||
In the meantime, we recommend using the GDB and dbgeng agents as examples.
|
||||
Be sure to look at the Python code `src/main/py`!
|
||||
The deprecated Java code `src/main/java` is still included as we transition.
|
||||
|
||||
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
|
||||
|
||||
If an existing connector exists for a suitable debugger on the desired platform, then adding it may
|
||||
be very simple. For example, both the x86 and ARM platforms are supported by GDB, so even though
|
||||
we're currently focused on x86 support, we've provided the opinions needed for Ghidra to debug ARM
|
||||
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.
|
||||
If a connector already exists for a suitable debugger on the desired platform, then adding it may be very simple.
|
||||
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.
|
||||
These mappings are conventionally kept in each connector's `arch.py` file.
|
||||
|
||||
In general, to write a new opinion, you need to know: 1) What the platform is called (including
|
||||
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
|
||||
mapping of target register names to those in Ghidra's processor language. In most cases (3) and (4)
|
||||
are already implemented by default mappers, so you can use those same mappers in your opinion. Once
|
||||
you have the opinion written, you can try debugging and recording a target. If Ghidra finds your
|
||||
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 general, to update `arch.py`, you need to know:
|
||||
|
||||
1. What the platform is called (including 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 mapping of target register names to those in Ghidra's processor language
|
||||
|
||||
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
|
||||
|
||||
The most obvious integration path for 3rd-party emulators is to write a "connector." However, p-code
|
||||
emulation is now an integral feature of the Ghidra UI, and it has a fairly accessible API. Namely,
|
||||
for interpolation between machines states recorded in a trace, and extrapolation into future machine
|
||||
states. 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.
|
||||
The most obvious integration path for 3rd-party emulators is to write a "connector."
|
||||
However, p-code emulation is an integral feature of the Ghidra UI, and it has a fairly accessible API.
|
||||
Namely, for interpolation between machines states recorded in a trace, and extrapolation into future machine states.
|
||||
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.
|
||||
We also provide out-of-the-box QEMU integration via GDB.
|
||||
|
||||
### Contributing
|
||||
|
||||
Whether submitting help tickets and pull requests, please tag those related to the debugger with
|
||||
"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.
|
||||
When submitting help tickets and pull requests, please tag those related to the debugger with "Debugger" so that we can triage them more quickly.
|
||||
|
||||
|
||||
[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: Public Domain
|
||||
Module.manifest||Public Domain||||END|
|
||||
README.md||GHIDRA||||END|
|
||||
data/lib/csframework.jar||LGPL 2.1||||END|
|
||||
data/lib/hfsexplorer-0_21-src.zip||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'
|
||||
|
||||
|
||||
def v33_1 = "demangler_gnu_v2_33_1"
|
||||
def v41 = "demangler_gnu_v2_41"
|
||||
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"
|
||||
|
||||
/**
|
||||
|
@ -41,19 +41,18 @@ task zipBuildableSource(type:Zip) {
|
|||
archiveExtension = 'zip'
|
||||
|
||||
//
|
||||
// Version 2.33.1
|
||||
// Version 2.41
|
||||
//
|
||||
from (project.projectDir.toString() + "/" + srcVersion33_1 + "c") {
|
||||
into "/" + srcVersion33_1
|
||||
from (project.projectDir.toString() + "/" + srcVersion41 + "c") {
|
||||
into "/" + srcVersion41
|
||||
}
|
||||
from (project.projectDir.toString() + "/" + srcVersion33_1 + "/headers") {
|
||||
into "/" + srcVersion33_1
|
||||
from (project.projectDir.toString() + "/" + srcVersion41 + "/headers") {
|
||||
into "/" + srcVersion41
|
||||
}
|
||||
from (project.projectDir.toString() + "/" + srcVersion33_1 + "/build") {
|
||||
into "/" + srcVersion33_1
|
||||
from (project.projectDir.toString() + "/" + srcVersion41 + "/build") {
|
||||
into "/" + srcVersion41
|
||||
}
|
||||
from (project.projectDir.toString() + "/" + srcVersion33_1 + "/README.txt")
|
||||
|
||||
from (project.projectDir.toString() + "/" + srcVersion41 + "/README.txt")
|
||||
|
||||
//
|
||||
// Version 2.24
|
||||
|
@ -72,23 +71,25 @@ task zipBuildableSource(type:Zip) {
|
|||
|
||||
model {
|
||||
|
||||
//
|
||||
// Version 2.33.1
|
||||
//
|
||||
components {
|
||||
demangler_gnu_v2_33_1(NativeExecutableSpec) {
|
||||
//
|
||||
// Version 2.41
|
||||
//
|
||||
demangler_gnu_v2_41(NativeExecutableSpec) {
|
||||
targetPlatform "win_x86_64"
|
||||
targetPlatform "linux_x86_64"
|
||||
targetPlatform "linux_arm_64"
|
||||
targetPlatform "mac_x86_64"
|
||||
targetPlatform "mac_arm_64"
|
||||
targetPlatform "freebsd_x86_64"
|
||||
targetPlatform "freebsd_arm_64"
|
||||
sources {
|
||||
c {
|
||||
source {
|
||||
srcDir srcVersion33_1 + "/c"
|
||||
srcDir srcVersion41 + "/c"
|
||||
}
|
||||
exportedHeaders {
|
||||
srcDir srcVersion33_1 + "/headers"
|
||||
srcDir srcVersion41 + "/headers"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,6 +104,8 @@ model {
|
|||
targetPlatform "linux_arm_64"
|
||||
targetPlatform "mac_x86_64"
|
||||
targetPlatform "mac_arm_64"
|
||||
targetPlatform "freebsd_x86_64"
|
||||
targetPlatform "freebsd_arm_64"
|
||||
sources {
|
||||
c {
|
||||
source {
|
||||
|
@ -127,7 +130,7 @@ model {
|
|||
|
||||
def version = b.getApplication().getName()
|
||||
|
||||
if (version.equals(v33_1)) {
|
||||
if (version.equals(v41)) {
|
||||
if (toolChain in Gcc) {
|
||||
//cCompiler.args "-DCP_DEMANGLE_DEBUG"
|
||||
cCompiler.args "-DHAVE_STDLIB_H"
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
##MODULE IP: LGPL 3.0
|
||||
##MODULE IP: Public Domain
|
||||
Module.manifest||Public Domain||||END|
|
||||
README.md||GHIDRA||||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;
|
||||
|
||||
/* 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.
|
||||
A few special names such as '___elabs' add a few chars (at most 7), but
|
||||
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
|
||||
* 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
|
||||
(Mostly) portable public-domain implementation -- D A Gwyn
|
||||
|
@ -162,7 +162,7 @@ static header *last_alloca_header = NULL; /* -> last alloca header. */
|
|||
|
||||
/* @undocumented C_alloca */
|
||||
|
||||
PTR
|
||||
void *
|
||||
C_alloca (size_t size)
|
||||
{
|
||||
auto char probe; /* Probes stack depth: */
|
||||
|
@ -185,7 +185,7 @@ C_alloca (size_t size)
|
|||
{
|
||||
register header *np = hp->h.next;
|
||||
|
||||
free ((PTR) hp); /* Collect garbage. */
|
||||
free ((void *) hp); /* Collect garbage. */
|
||||
|
||||
hp = np; /* -> next header. */
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ C_alloca (size_t size)
|
|||
|
||||
/* 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
|
||||
*/
|
||||
/* 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
|
||||
|
||||
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})
|
||||
|
||||
Write each member of ARGV, handling all necessary quoting, to the file
|
||||
named by FILE, separated by whitespace. Return 0 on success, non-zero
|
||||
if an error occurred while writing to FILE.
|
||||
associated with FILE, separated by whitespace. Return 0 on success,
|
||||
non-zero if an error occurred while writing to FILE.
|
||||
|
||||
@end deftypefn
|
||||
|
||||
|
@ -303,8 +303,6 @@ if an error occurred while writing to FILE.
|
|||
int
|
||||
writeargv (char * const *argv, FILE *f)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
if (f == NULL)
|
||||
return 1;
|
||||
|
||||
|
@ -318,29 +316,26 @@ writeargv (char * const *argv, FILE *f)
|
|||
|
||||
if (ISSPACE(c) || c == '\\' || c == '\'' || c == '"')
|
||||
if (EOF == fputc ('\\', f))
|
||||
{
|
||||
status = 1;
|
||||
goto done;
|
||||
}
|
||||
return 1;
|
||||
|
||||
if (EOF == fputc (c, f))
|
||||
{
|
||||
status = 1;
|
||||
goto done;
|
||||
}
|
||||
return 1;
|
||||
|
||||
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))
|
||||
{
|
||||
status = 1;
|
||||
goto done;
|
||||
}
|
||||
return 1;
|
||||
|
||||
argv++;
|
||||
}
|
||||
|
||||
done:
|
||||
return status;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -438,7 +433,10 @@ expandargv (int *argcp, char ***argvp)
|
|||
due to CR/LF->CR translation when reading text files.
|
||||
That does not in-and-of itself indicate failure. */
|
||||
&& ferror (f))
|
||||
{
|
||||
free (buffer);
|
||||
goto error;
|
||||
}
|
||||
/* Add a NUL terminator. */
|
||||
buffer[len] = '\0';
|
||||
/* 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
|
||||
*/
|
||||
/* 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)
|
||||
Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
|
||||
Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
|
||||
|
@ -56,7 +56,6 @@ void * realloc ();
|
|||
#define CURRENT_DEMANGLING_STYLE options
|
||||
|
||||
#include "libiberty.h"
|
||||
#include "rust-demangle.h"
|
||||
|
||||
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)
|
||||
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. */
|
||||
if (GNU_V3_DEMANGLING || RUST_DEMANGLING || AUTO_DEMANGLING)
|
||||
if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
|
||||
{
|
||||
ret = cplus_demangle_v3 (mangled, options);
|
||||
if (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)
|
||||
if (ret || GNU_V3_DEMANGLING)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -208,27 +200,6 @@ cplus_demangle (const char *mangled, int options)
|
|||
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. */
|
||||
|
||||
char *
|
||||
|
@ -248,7 +219,7 @@ ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
|
|||
goto unknown;
|
||||
|
||||
/* 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.
|
||||
A few special names such as '___elabs' add a few chars (at most 7), but
|
||||
they occur only once. */
|
|
@ -2,7 +2,7 @@
|
|||
* IP: GPL 3
|
||||
*/
|
||||
/* 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)
|
||||
Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid 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
|
||||
02110-1301, USA.
|
||||
|
||||
|
||||
CHANGE NOTICE:
|
||||
This file was changed on July 22nd, 2020.
|
||||
This file was changed on October 31st, 2023.
|
||||
|
||||
*/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
// #include "sysdep.h" // Changed 10/31/23
|
||||
// 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 "demangle.h"
|
||||
#include "getopt.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 strip_underscore = 0; // TARGET_PREPENDS_UNDERSCORE; // Changed Jan 22, 2020
|
||||
static const char *program_name; // Changed Jan 22, 2020
|
||||
static int strip_underscore = 0; // TARGET_PREPENDS_UNDERSCORE; // Changed 10/31/23
|
||||
|
||||
// declared in bucomm.c
|
||||
static const char *program_name; // Changed 10/31/23
|
||||
|
||||
|
||||
static const struct option long_options[] =
|
||||
{
|
||||
|
@ -108,10 +119,12 @@ Usage: %s [options] [mangled names]\n", program_name);
|
|||
fprintf (stream, "\
|
||||
Options are:\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, "\
|
||||
[-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, "\
|
||||
[-p|--no-params] Do not display function arguments\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 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)
|
||||
fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
|
||||
*/
|
||||
|
||||
*/
|
||||
exit (status);
|
||||
}
|
||||
|
||||
|
@ -158,8 +171,8 @@ main (int argc, char **argv)
|
|||
enum demangling_styles style = auto_demangling;
|
||||
|
||||
program_name = argv[0];
|
||||
// xmalloc_set_program_name (program_name); // Changed Jan 22, 2020
|
||||
// bfd_set_error_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 10/31/23
|
||||
|
||||
expandargv (&argc, &argv);
|
||||
|
||||
|
@ -191,7 +204,8 @@ main (int argc, char **argv)
|
|||
flags &= ~ DMGL_VERBOSE;
|
||||
break;
|
||||
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;
|
||||
case '_':
|
||||
strip_underscore = 1;
|
||||
|
@ -230,13 +244,14 @@ main (int argc, char **argv)
|
|||
case rust_demangling:
|
||||
valid_symbols = standard_symbol_characters ();
|
||||
break;
|
||||
default: {
|
||||
default:
|
||||
/* Folks should explicitly indicate the appropriate alphabet for
|
||||
each demangling. Providing a default would allow the
|
||||
question to go unconsidered. */
|
||||
fprintf (stderr, "Internal error: no symbol alphabet for current style\n"); // Changed Jan 22, 2020
|
||||
exit (1); // Changed Jan 22, 2020
|
||||
}
|
||||
// fatal ("Internal error: no symbol alphabet for current style"); // Changed 10/31/23
|
||||
fprintf (stderr, "Internal error: no symbol alphabet for current style\n"); // Changed 10/31/23
|
||||
exit (1); // Changed 10/31/23
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
/* 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).
|
||||
|
||||
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)
|
||||
dest->s[i + length] = dest->s[i];
|
||||
/* Splice in the new stuff. */
|
||||
strncpy (dest->s + pos, src, length);
|
||||
memcpy (dest->s + pos, src, length);
|
||||
/* Compute the new length. */
|
||||
dest->length += length;
|
||||
return 1;
|
|
@ -1,5 +1,5 @@
|
|||
/* ###
|
||||
* IP: GPL 3
|
||||
* IP: GPL 3 Linking Permitted
|
||||
* NOTE: See binutils/include/COPYING3
|
||||
*/
|
||||
/* Getopt for GNU.
|
||||
|
@ -7,7 +7,7 @@
|
|||
"Keep this file name-space clean" means, talk to drepper@gnu.org
|
||||
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
|
||||
Library (glibc).
|
|
@ -1,9 +1,9 @@
|
|||
/* ###
|
||||
* IP: GPL 3
|
||||
* IP: GPL 3 Linking Permitted
|
||||
* NOTE: See binutils/include/COPYING3
|
||||
*/
|
||||
/* 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
|
||||
Library (glibc).
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
|
||||
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
|
||||
|
||||
*/
|
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
|
||||
* NOTE: See binutils/include/COPYING
|
||||
* NOTE: See binutils/libiberty/COPYING.LIB
|
||||
*/
|
||||
/* <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>.
|
||||
|
||||
This file is part of the libiberty library.
|
|
@ -3,7 +3,7 @@
|
|||
* NOTE: See binutils/libiberty/COPYING.LIB
|
||||
*/
|
||||
/* 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.
|
||||
Libiberty is free software; you can redistribute it and/or
|
|
@ -2,8 +2,8 @@
|
|||
* IP: LGPL 2.1
|
||||
* NOTE: See binutils/include/COPYING
|
||||
*/
|
||||
/* ANSI and traditional C compatability macros
|
||||
Copyright (C) 1991-2019 Free Software Foundation, Inc.
|
||||
/* Compiler compatibility macros
|
||||
Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
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
|
||||
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* ANSI and traditional C compatibility macros
|
||||
|
||||
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
|
||||
/* For ease of writing code which uses GCC extensions but needs to be
|
||||
portable to other compilers, we provide the GCC_VERSION macro that
|
||||
simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various
|
||||
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__)
|
||||
#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
|
||||
it too, but it's not in C89. */
|
||||
#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 */
|
||||
#else
|
||||
# if GCC_VERSION >= 2007
|
||||
|
@ -93,22 +68,6 @@ So instead we use the macro below and test it against specific values. */
|
|||
# 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
|
||||
macros freely, and know that they will come into play for the
|
||||
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
|
||||
|
||||
/* 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
|
||||
about GCC extensions. This feature didn't work properly before
|
||||
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
|
||||
#endif
|
||||
|
||||
#if __cpp_constexpr >= 200704
|
||||
#if defined(__cplusplus) && __cpp_constexpr >= 200704
|
||||
#define CONSTEXPR constexpr
|
||||
#else
|
||||
#define CONSTEXPR
|
||||
#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.
|
||||
When building with C++11 and above, the methods are explicitly
|
||||
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. */
|
||||
|
||||
#if __cplusplus >= 201103
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103
|
||||
#define DISABLE_COPY_AND_ASSIGN(TYPE) \
|
||||
TYPE (const TYPE&) = delete; \
|
||||
void operator= (const TYPE &) = delete
|
|
@ -1,9 +1,9 @@
|
|||
/* ###
|
||||
* IP: GPL 3 Linking Permitted
|
||||
* NOTE: See binutils/libiberty/COPYING.LIB; Used GPL 3 from this file's header
|
||||
* IP: LGPL 2.1
|
||||
* NOTE: See binutils/include/COPYING
|
||||
*/
|
||||
/* 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>.
|
||||
|
||||
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
|
||||
operator, but not when in an expression. */
|
||||
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
|
||||
the current 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[];
|
||||
#endif
|
||||
|
||||
#define D_BUILTIN_TYPE_COUNT (34)
|
||||
#define D_BUILTIN_TYPE_COUNT (36)
|
||||
|
||||
CP_STATIC_IF_GLIBCPP_V3
|
||||
const struct demangle_builtin_type_info
|
|
@ -3,7 +3,7 @@
|
|||
* NOTE: See binutils/include/COPYING
|
||||
*/
|
||||
/* 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
|
||||
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 *
|
||||
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
|
||||
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 *
|
||||
rust_demangle (const char *mangled, int options);
|
||||
|
||||
|
@ -425,6 +412,9 @@ enum demangle_component_type
|
|||
number which involves neither modifying the mangled string nor
|
||||
allocating a new copy of the literal in memory. */
|
||||
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
|
||||
resource. */
|
||||
DEMANGLE_COMPONENT_JAVA_RESOURCE,
|
||||
|
@ -463,7 +453,25 @@ enum demangle_component_type
|
|||
/* A cloned function. */
|
||||
DEMANGLE_COMPONENT_CLONE,
|
||||
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. */
|
||||
|
@ -485,6 +493,7 @@ struct demangle_component
|
|||
Initialize to zero. Private to d_print_comp.
|
||||
All other fields are final after initialization. */
|
||||
int d_printing;
|
||||
int d_counting;
|
||||
|
||||
union
|
||||
{
|
||||
|
@ -549,6 +558,15 @@ struct demangle_component
|
|||
const struct demangle_builtin_type_info *type;
|
||||
} 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. */
|
||||
struct
|
||||
{
|
|
@ -3,7 +3,7 @@
|
|||
* NOTE: See binutils/include/COPYING3
|
||||
*/
|
||||
/* 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).
|
||||
|
||||
This file is part of GCC.
|
|
@ -3,7 +3,7 @@
|
|||
* NOTE: See binutils/include/COPYING3
|
||||
*/
|
||||
/* 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.
|
||||
Bugs can be reported to bug-glibc@gnu.org.
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
/* 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
|
||||
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 *);
|
||||
|
||||
/* 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
|
||||
the last argument of this function, to terminate the list of
|
||||
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,
|
||||
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,
|
||||
realloc type functions are not suitable for attribute malloc since
|
||||
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
|
||||
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. */
|
||||
|
||||
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. */
|
||||
|
||||
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. */
|
||||
|
||||
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. */
|
||||
extern double physmem_total (void);
|
||||
|
@ -641,6 +645,13 @@ extern int pexecute (const char *, char * const *, const char *,
|
|||
|
||||
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
|
||||
/* Like sprintf but provides a pointer to malloc'd storage, which must
|
||||
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;
|
||||
|
||||
#if !HAVE_DECL_VASPRINTF
|
||||
#if defined(HAVE_DECL_VASPRINTF) && !HAVE_DECL_VASPRINTF
|
||||
/* Like vsprintf but provides a pointer to malloc'd storage, which
|
||||
must be freed by the caller. */
|
||||
|
||||
|
@ -706,11 +717,6 @@ extern unsigned long long int strtoull (const char *nptr,
|
|||
char **endptr, int base);
|
||||
#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 */
|
||||
extern void setproctitle (const char *name, ...);
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
/* <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>.
|
||||
|
||||
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
|
||||
// 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"
|
||||
|
||||
// Find the GPL dir
|
||||
def gplDir = null;
|
||||
if (file("../utils.gradle").exists()) {
|
||||
gplDir = file("..").getCanonicalPath()
|
||||
ext.ghidraInstallDir = file("../..").getCanonicalPath()
|
||||
ext.binutilsLocation = file("${ghidraInstallDir}/../ghidra.bin/GPL/${name}").getCanonicalPath()
|
||||
}
|
||||
else {
|
||||
// Module lives disconnected from the GPL directory, which it will need to build.
|
||||
// Find a Ghidra installation directory and use its GPL directory.
|
||||
ext.binutilsLocation = projectDir
|
||||
if (file("../../Extensions").exists() && file("../../../GPL/utils.gradle").exists()) {
|
||||
// Module is installed within a Ghidra installation (i.e, ghidra/Ghidra/Extensions)
|
||||
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.binutilsResource = new File("${projectDir}/${binutils}.tar.bz2")
|
||||
ext.binutilsResource = new File("${binutilsLocation}/${binutils}.tar.bz2")
|
||||
|
||||
def binutilsUnpackDir = file("${project.buildDir}/${binutils}/")
|
||||
|
||||
|
@ -37,8 +37,8 @@ model {
|
|||
all {
|
||||
def binutilsArtifactsDir = file("build/binutils/${targetPlatform.name}")
|
||||
if ((toolChain in Gcc) || (toolChain in Clang)) {
|
||||
cCompiler.args "-I${binutilsArtifactsDir}/include", "-I${binutilsArtifactsDir}/bfd"
|
||||
linker.args "-L${binutilsArtifactsDir}/lib", "-lopcodes", "-lbfd", "-liberty", "-lz", "-ldl"
|
||||
cCompiler.args "-I${binutilsArtifactsDir}/include", "-I${binutilsArtifactsDir}/bfd", "-I${binutilsArtifactsDir}/libsframe"
|
||||
linker.args "-L${binutilsArtifactsDir}/lib", "-lopcodes", "-lbfd", "-lsframe", "-liberty", "-lz", "-ldl"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,9 +151,10 @@ supportedPlatforms.each { platform ->
|
|||
include "**/*.h"
|
||||
}
|
||||
into("/lib") {
|
||||
from "${configDir}/bfd/libbfd.a"
|
||||
from "${configDir}/bfd/.libs/libbfd.a"
|
||||
from "${configDir}/libiberty/libiberty.a"
|
||||
from "${configDir}/opcodes/libopcodes.a"
|
||||
from "${configDir}/libsframe/.libs/libsframe.a"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
##MODULE IP: Public Domain
|
||||
.gitignore||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/big.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 i;
|
||||
size_t n;
|
||||
int n;
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
|
@ -57,6 +56,18 @@ int objdump_sprintf (SFILE *f, const char *format, ...)
|
|||
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,
|
||||
disassemble_info* info,
|
||||
|
@ -67,7 +78,7 @@ void configureDisassembleInfo(bfd* abfd,
|
|||
|
||||
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->mach = mach;
|
||||
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) {
|
||||
// specify installDir because Gradle doesn't find VS Build Tools.
|
||||
// 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_arm_64", os: "linux", arch: "arm64"],
|
||||
[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.*/:
|
||||
os = "mac"
|
||||
break
|
||||
case ~/FreeBSD.*/:
|
||||
os = "freebsd"
|
||||
break
|
||||
default:
|
||||
throw new GradleException("Unrecognized platform operating system: $os")
|
||||
}
|
||||
|
@ -112,6 +117,20 @@ ext.isCurrentMac = {
|
|||
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.
|
||||
*********************************************************************************/
|
||||
|
|
|
@ -27,12 +27,14 @@ def configureVisualStudio() {
|
|||
|
||||
// Use vswhere.exe to search for latest Visual Studio installation
|
||||
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()) {
|
||||
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
|
||||
}
|
||||
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 vswhereExit = vswhereProcess.exitValue()
|
||||
if (vswhereExit != 0) {
|
||||
|
@ -58,8 +60,6 @@ def configureVisualStudio() {
|
|||
def vcvarsPath = "${vsInstallDir}\\VC\\Auxiliary\\Build\\vcvarsall.bat"
|
||||
def vcvarsCmd = "\"${vcvarsPath}\" x86_amd64"
|
||||
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()
|
||||
println " -> SDK Directory (default): ${sdkDir}"
|
||||
def sdkVersion = "${vcvarsEnvCmd} !WindowsSDKVersion!".execute().text.trim().replace('\\', '')
|
||||
|
@ -71,7 +71,6 @@ def configureVisualStudio() {
|
|||
|
||||
// Save Visual Studio information so other projects can access it
|
||||
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_VERSION_DEFAULT = sdkVersion
|
||||
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/jacocoProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/helpProject.gradle"
|
||||
apply plugin: 'eclipse'
|
||||
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
|
||||
Module.manifest||GHIDRA||||END|
|
||||
README.md||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/WhatsNew.html||GHIDRA||||END|
|
||||
src/global/docs/WhatsNew.md||GHIDRA||||END|
|
||||
src/main/resources/UserAgreement.html||GHIDRA||||END|
|
||||
src/main/resources/defaultTools/CodeBrowser.tool||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://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://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>
|
||||
<HEAD>
|
||||
<TITLE>Ghidra User Agreement</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<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
|
||||
Module.manifest||GHIDRA||||END|
|
||||
README.md||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.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 {
|
||||
protected final ValidationContext ctx;
|
||||
|
||||
/**
|
||||
* Construct a new {@code AbstractDBAnnotationValidator} with the specified validation context.
|
||||
*
|
||||
* @param ctx the validation context
|
||||
*/
|
||||
public AbstractDBAnnotationValidator(ValidationContext 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,
|
||||
TypeElement type) {
|
||||
if (type.getKind() != ElementKind.CLASS) {
|
||||
|
|
|
@ -19,6 +19,10 @@ import java.util.Set;
|
|||
|
||||
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 {
|
||||
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 second the second
|
||||
|
|
|
@ -22,14 +22,43 @@ import javax.tools.Diagnostic.Kind;
|
|||
|
||||
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 {
|
||||
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) {
|
||||
super(ctx);
|
||||
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() {
|
||||
if (!ctx.hasType(column, ctx.DB_OBJECT_COLUMN_ELEM)) {
|
||||
ctx.messager.printMessage(Kind.ERROR,
|
||||
|
|
|
@ -23,6 +23,14 @@ import javax.tools.Diagnostic.Kind;
|
|||
|
||||
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 {
|
||||
final VariableElement field;
|
||||
final Map<TypeMirror, TypeElement> javaToDBTypeMap;
|
||||
|
@ -39,6 +47,13 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
|||
|
||||
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) {
|
||||
super(ctx);
|
||||
this.field = field;
|
||||
|
@ -59,6 +74,13 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
|||
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,
|
||||
String codecName) {
|
||||
PrimitiveType primitive = ctx.typeUtils.getPrimitiveType(kind);
|
||||
|
@ -68,12 +90,26 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
|||
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) {
|
||||
TypeMirror type = ctx.elementUtils.getTypeElement(cls.getCanonicalName()).asType();
|
||||
TypeElement codec = ctx.elementUtils.getTypeElement(codecName);
|
||||
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,
|
||||
String codecName) {
|
||||
PrimitiveType primitive = ctx.typeUtils.getPrimitiveType(kind);
|
||||
|
@ -82,6 +118,19 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
|||
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() {
|
||||
Set<Modifier> mods = field.getModifiers();
|
||||
if (mods.contains(Modifier.FINAL)) {
|
||||
|
@ -101,6 +150,12 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
|||
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) {
|
||||
if (ctx.isEnumType(javaType)) {
|
||||
return ENUM_CODEC_ELEM;
|
||||
|
@ -108,6 +163,12 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
|||
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() {
|
||||
DBAnnotatedField annotation = field.getAnnotation(DBAnnotatedField.class);
|
||||
TypeElement codecElem;
|
||||
|
@ -123,6 +184,12 @@ public class DBAnnotatedFieldValidator extends AbstractDBAnnotationValidator {
|
|||
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) {
|
||||
|
||||
TypeElement codecType = getCodecTypeElement();
|
||||
|
|
|
@ -29,8 +29,10 @@ import ghidra.util.database.annot.*;
|
|||
/**
|
||||
* 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,
|
||||
* it will.
|
||||
* <p>
|
||||
* 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
|
||||
public class DBAnnotatedObjectProcessor extends AbstractProcessor {
|
||||
|
@ -39,6 +41,11 @@ public class DBAnnotatedObjectProcessor extends AbstractProcessor {
|
|||
|
||||
private ValidationContext ctx;
|
||||
|
||||
/**
|
||||
* Initialize the processor with the given preprocessing environment.
|
||||
*
|
||||
* @param env the processing environment
|
||||
*/
|
||||
@Override
|
||||
public synchronized void init(ProcessingEnvironment env) {
|
||||
//System.err.println("HERE4");
|
||||
|
@ -46,6 +53,14 @@ public class DBAnnotatedObjectProcessor extends AbstractProcessor {
|
|||
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
|
||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||
Map<TypeElement, DBAnnotatedObjectValidator> types = new LinkedHashMap<>();
|
||||
|
@ -76,21 +91,40 @@ public class DBAnnotatedObjectProcessor extends AbstractProcessor {
|
|||
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
|
||||
public Iterable<? extends Completion> getCompletions(Element element,
|
||||
AnnotationMirror annotation, ExecutableElement member, String userText) {
|
||||
// TODO Auto-generated method stub
|
||||
return super.getCompletions(element, annotation, member, userText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the latest supported source version.
|
||||
*
|
||||
* @return the latest supported source version
|
||||
*/
|
||||
@Override
|
||||
public SourceVersion getSupportedSourceVersion() {
|
||||
return SourceVersion.latestSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the set of supported annotation types.
|
||||
*
|
||||
* @return the set of supported annotation types
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getSupportedAnnotationTypes() {
|
||||
return SUPPORTED_ANNOTATIONS.stream().map(Class::getCanonicalName).collect(
|
||||
Collectors.toSet());
|
||||
return SUPPORTED_ANNOTATIONS.stream()
|
||||
.map(Class::getCanonicalName)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,31 +20,62 @@ import java.util.*;
|
|||
import javax.lang.model.element.*;
|
||||
import javax.tools.Diagnostic.Kind;
|
||||
|
||||
import ghidra.util.database.DBAnnotatedObject;
|
||||
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 {
|
||||
private final ValidationContext ctx;
|
||||
private final TypeElement type;
|
||||
private final Map<String, DBAnnotatedFieldValidator> fieldsByName = 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) {
|
||||
this.ctx = ctx;
|
||||
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) {
|
||||
DBAnnotatedField annotation = field.getAnnotation(DBAnnotatedField.class);
|
||||
assert annotation != null;
|
||||
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) {
|
||||
DBAnnotatedColumn annotation = column.getAnnotation(DBAnnotatedColumn.class);
|
||||
assert annotation != null;
|
||||
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() {
|
||||
DBAnnotatedObjectInfo annotation = type.getAnnotation(DBAnnotatedObjectInfo.class);
|
||||
if (annotation != null && type.getKind() != ElementKind.CLASS) {
|
||||
|
@ -81,18 +112,27 @@ public class DBAnnotatedObjectValidator {
|
|||
checkMissing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate all fields annotated with {@link DBAnnotatedField}.
|
||||
*/
|
||||
protected void validateFields() {
|
||||
for (DBAnnotatedFieldValidator fv : fieldsByName.values()) {
|
||||
fv.validate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate all columns annotated with {@link DBAnnotatedColumn}.
|
||||
*/
|
||||
protected void validateColumns() {
|
||||
for (DBAnnotatedColumnValidator cv : columnsByName.values()) {
|
||||
cv.validate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for missing corresponding annotations between fields and columns.
|
||||
*/
|
||||
protected void checkMissing() {
|
||||
Set<String> names = new LinkedHashSet<>();
|
||||
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) {
|
||||
AccessSpec fieldSpec = AccessSpec.get(field.getModifiers());
|
||||
AccessSpec columnSpec = AccessSpec.get(column.getModifiers());
|
||||
|
|
|
@ -38,6 +38,11 @@ public class ValidationContext {
|
|||
final TypeElement DEFAULT_CODEC_ELEM;
|
||||
final TypeElement ENUM_ELEM;
|
||||
|
||||
/**
|
||||
* Construct a Validation Context with the specified processing environment/
|
||||
*
|
||||
* @param env the processing environment
|
||||
*/
|
||||
public ValidationContext(ProcessingEnvironment env) {
|
||||
typeUtils = env.getTypeUtils();
|
||||
elementUtils = env.getElementUtils();
|
||||
|
@ -54,14 +59,35 @@ public class ValidationContext {
|
|||
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) {
|
||||
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) {
|
||||
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) {
|
||||
TypeMirror fieldType = field.asType();
|
||||
try {
|
||||
|
@ -86,9 +112,16 @@ public class ValidationContext {
|
|||
}
|
||||
|
||||
return typeUtils.isAssignable(fieldType, type);
|
||||
// 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) {
|
||||
// TODO: This only works for typevar at top level...
|
||||
// TODO: Need to figure out how to check for capture and check
|
||||
|
@ -105,6 +138,12 @@ public class ValidationContext {
|
|||
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) {
|
||||
if (t.getKind() != TypeKind.DECLARED) {
|
||||
return false;
|
||||
|
@ -113,6 +152,13 @@ public class ValidationContext {
|
|||
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) {
|
||||
Set<DeclaredType> next;
|
||||
while (!types.isEmpty()) {
|
||||
|
@ -132,14 +178,35 @@ public class ValidationContext {
|
|||
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) {
|
||||
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) {
|
||||
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) {
|
||||
List<? extends TypeParameterElement> typeParameters = superElem.getTypeParameters();
|
||||
List<? extends TypeMirror> typeArguments = superType.getTypeArguments();
|
||||
|
@ -151,14 +218,34 @@ public class ValidationContext {
|
|||
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) {
|
||||
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) {
|
||||
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) {
|
||||
FormatVisitor vis = new FormatVisitor();
|
||||
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> {
|
||||
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
|
||||
public Void visit(TypeMirror t, Void p) {
|
||||
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
|
||||
public Void visitPrimitive(PrimitiveType t, Void p) {
|
||||
buf.append(t.toString());
|
||||
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
|
||||
public Void visitNull(NullType t, Void p) {
|
||||
buf.append(t.toString());
|
||||
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
|
||||
public Void visitArray(ArrayType t, Void p) {
|
||||
visit(t.getComponentType());
|
||||
|
@ -226,6 +345,13 @@ class FormatVisitor implements TypeVisitor<Void, Void> {
|
|||
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
|
||||
public Void visitDeclared(DeclaredType t, Void p) {
|
||||
buf.append(t.asElement().toString());
|
||||
|
@ -242,12 +368,26 @@ class FormatVisitor implements TypeVisitor<Void, Void> {
|
|||
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
|
||||
public Void visitError(ErrorType t, Void p) {
|
||||
buf.append(t.toString());
|
||||
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
|
||||
public Void visitTypeVariable(TypeVariable t, Void p) {
|
||||
buf.append(t.toString());
|
||||
|
@ -264,6 +404,13 @@ class FormatVisitor implements TypeVisitor<Void, Void> {
|
|||
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
|
||||
public Void visitWildcard(WildcardType t, Void p) {
|
||||
buf.append("?");
|
||||
|
@ -280,24 +427,52 @@ class FormatVisitor implements TypeVisitor<Void, Void> {
|
|||
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
|
||||
public Void visitExecutable(ExecutableType t, Void p) {
|
||||
buf.append(t.toString());
|
||||
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
|
||||
public Void visitNoType(NoType t, Void p) {
|
||||
buf.append(t.toString());
|
||||
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
|
||||
public Void visitUnknown(TypeMirror t, Void p) {
|
||||
buf.append(t.toString());
|
||||
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
|
||||
public Void visitUnion(UnionType t, Void p) {
|
||||
Iterator<? extends TypeMirror> it = t.getAlternatives().iterator();
|
||||
|
@ -311,6 +486,13 @@ class FormatVisitor implements TypeVisitor<Void, Void> {
|
|||
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
|
||||
public Void visitIntersection(IntersectionType t, Void p) {
|
||||
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/nativeProject.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle"
|
||||
|
||||
apply from: "$rootProject.projectDir/gradle/hasPythonPackage.gradle"
|
||||
apply from: "$rootProject.projectDir/gradle/debugger/hasNodepJar.gradle"
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
eclipse.project.name = 'Debug Debugger-agent-dbgeng'
|
||||
|
||||
dependencies {
|
||||
api project(":Framework-AsyncComm")
|
||||
api project(":Framework-Debugging")
|
||||
api project(":Debugger-gadp")
|
||||
ext.tlb = file("build/os/win_x86_64/dbgmodel.tlb")
|
||||
|
||||
//testImplementation project(":Base")
|
||||
testImplementation project(path: ':Framework-AsyncComm', configuration: 'testArtifacts')
|
||||
testImplementation project(path: ':Framework-Debugging', configuration: 'testArtifacts')
|
||||
testImplementation project(path: ":Debugger-gadp", configuration: 'testArtifacts')
|
||||
if ("win_x86_64".equals(getCurrentPlatformName())) {
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.nodepJar {
|
||||
manifest {
|
||||
attributes['Main-Class'] = 'agent.dbgeng.gadp.DbgEngGadpServer'
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
jvmArgs('-Xrs') // TODO: Is this needed, or left over from trial-and-error
|
||||
if ("win_x86_64".equals(getCurrentPlatformName())) {
|
||||
dependsOn(":Framework-Debugging:testSpecimenWin_x86_64")
|
||||
}
|
||||
}
|
||||
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
|
||||
##MODULE IP: Apache License 2.0
|
||||
##MODULE IP: MIT
|
||||
Module.manifest||GHIDRA||||END|
|
||||
src/javaprovider/def/javaprovider.def||GHIDRA||||END|
|
||||
src/javaprovider/rc/javaprovider.rc||GHIDRA||||END|
|
||||
README.md||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