mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-01-06 20:53:55 -05:00
Merge tag 'Ghidra_12.0_build' into stable
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -54,7 +54,6 @@ Release
|
||||
*.aps
|
||||
*.vcproj.*
|
||||
*.vcxproj.*
|
||||
# dump files
|
||||
*.mdmp
|
||||
.vs/
|
||||
.editorconfig/
|
||||
@@ -77,10 +76,8 @@ Release
|
||||
*/*/*/*/test-bin
|
||||
|
||||
# Ignore Intellij metadata
|
||||
**/*.iml
|
||||
**/.idea
|
||||
*.iml
|
||||
.idea
|
||||
.idea/
|
||||
|
||||
# Ignore logs and core dumps
|
||||
*.log
|
||||
|
||||
156
CONTRIBUTING.md
156
CONTRIBUTING.md
@@ -29,98 +29,106 @@ Patches should be submitted in the form of Pull Requests to the Ghidra
|
||||
[repository] on GitHub. But first, consider the following tips to ensure a
|
||||
smooth process when submitting a patch:
|
||||
|
||||
- Ensure that the patch compiles and does not break any build-time tests.
|
||||
- Be understanding, patient, and friendly; developers may need time to review
|
||||
your submissions before they can take action or respond. This does not mean
|
||||
your contribution is not valued. If your contribution has not received a
|
||||
response in a reasonable time, consider commenting with a polite inquiry for
|
||||
an update.
|
||||
- Limit your patches to the smallest reasonable change to achieve your intended
|
||||
goal. For example, do not make unnecessary indentation changes; but don't go
|
||||
out of your way to make the patch so minimal that it isn't easy to read,
|
||||
either. Consider the reviewer's perspective.
|
||||
- Unless previously authorized by the Ghidra team, repackaging, renaming, and
|
||||
other refactoring should not be part of any pull request. These types of
|
||||
changes are difficult to review, pollute the git history making it harder
|
||||
to do git forensics on regressions, and will likely conflict with other
|
||||
changes that the Ghidra team is making internally.
|
||||
- Avoid "find and replace" changes in your pull request. While it may be
|
||||
tempting to globally replace calls to deprecated methods or change the style
|
||||
of the code to fit your personal preference, these types of seemingly trivial
|
||||
changes have likely not already been performed by the Ghidra team for good
|
||||
reason.
|
||||
- Focus your patches on bug fixes that were discovered through real-world
|
||||
usage and testing, and on improvements that clearly satisfy a need in
|
||||
Ghidra's functionality. Before you begin implementing, consider first
|
||||
opening a dialogue with the Ghidra team to ensure that your efforts will
|
||||
align with the goals of the project. This will significantly improve the odds
|
||||
that your patch gets accepted.
|
||||
- Unless it addresses a critical security update, avoid pull requests that update
|
||||
jars or other 3rd party libraries. It is preferred that these changes are made
|
||||
internally by the team. If you have a need for an updated library, please
|
||||
submit an issue with your request instead of a pull request.
|
||||
- Before submission, please squash your commits to using a message that starts
|
||||
with the issue number and a description of the changes.
|
||||
- Isolate multiple patches from each other. If you wish to make several
|
||||
independent patches, do so in separate, smaller pull requests that can be
|
||||
reviewed more easily.
|
||||
- Be prepared to answer questions from reviewers. They may have further
|
||||
questions before accepting your patch, and may even propose changes. Please
|
||||
accept this feedback constructively, and not as a rejection of your proposed
|
||||
change.
|
||||
- Ensure that the patch compiles and runs in at least our development environment, and ideally our
|
||||
full build too. Even the most trivial change done in the GitHub editor has a chance to cause
|
||||
problems in the full development environment for unexpected reasons.
|
||||
- If using "AI" to assist in development, please apply extra scrutity to its suggestions, in terms
|
||||
of both correctness and adherence to our [legal](#legal) requirements.
|
||||
- Be understanding, patient, and friendly; developers may need time to review your submissions
|
||||
before they can take action or respond. This does not mean your contribution is not valued. If
|
||||
your contribution has not received a response in a reasonable time, consider commenting with a
|
||||
polite inquiry for an update.
|
||||
- Limit your patches to the smallest reasonable change to achieve your intended goal. For example,
|
||||
do not make unnecessary indentation changes; but don't go out of your way to make the patch so
|
||||
minimal that it isn't easy to read, either. Consider the reviewer's perspective.
|
||||
- Unless previously authorized by the Ghidra team, repackaging, renaming, and other refactoring
|
||||
should not be part of any pull request. These types of changes are difficult to review, pollute
|
||||
the git history making it harder to do git forensics on regressions, and will likely conflict with
|
||||
other changes that the Ghidra team is making internally.
|
||||
- Avoid "find and replace" changes in your pull request. While it may be tempting to globally
|
||||
replace calls to deprecated methods or change the style of the code to fit your personal
|
||||
preference, these types of seemingly trivial changes have likely not already been performed by the
|
||||
Ghidra team for good reason.
|
||||
- Focus your patches on bug fixes that were discovered through real-world usage and testing, and on
|
||||
improvements that clearly satisfy a need in Ghidra's functionality. Before you begin
|
||||
implementing, consider first opening a dialogue with the Ghidra team to ensure that your efforts
|
||||
will align with the goals of the project. This will significantly improve the odds that your
|
||||
patch gets accepted.
|
||||
- Unless it addresses a critical security update, avoid pull requests that update jars or other 3rd
|
||||
party libraries. It is preferred that these changes are made internally by the team. If you have
|
||||
a need for an updated library, please submit an issue with your request instead of a pull request.
|
||||
- Before submission, please squash your commits to using a message that starts with the issue number
|
||||
and a description of the changes.
|
||||
- Isolate multiple patches from each other. If you wish to make several independent patches, do so
|
||||
in separate, smaller pull requests that can be reviewed more easily.
|
||||
- Avoid submitting self-generated binary files as part of your pull request. Despite your best
|
||||
intentions, our policy forbids accepting them because we cannot effectively review and validate
|
||||
their content.
|
||||
- Be prepared to answer questions from reviewers. They may have further questions before accepting
|
||||
your patch, and may even propose changes. Please accept this feedback constructively, and not as a
|
||||
rejection of your proposed change.
|
||||
|
||||
## Review
|
||||
|
||||
- We welcome code reviews from anyone. A committer is required to formally
|
||||
accept and merge the changes.
|
||||
- Reviewers will be looking for things like threading issues, performance
|
||||
implications, API design, duplication of existing functionality, readability
|
||||
and code style, avoidance of bloat (scope-creep), etc.
|
||||
- We welcome code reviews from anyone. A committer is required to formally accept and merge the
|
||||
changes.
|
||||
- Reviewers will be looking for things like threading issues, performance implications, API design,
|
||||
duplication of existing functionality, readability and code style, avoidance of bloat
|
||||
(scope-creep), etc.
|
||||
- Reviewers will likely ask questions to better understand your change.
|
||||
- Reviewers will make comments about changes to your patch:
|
||||
- MUST means that the change is required
|
||||
- SHOULD means that the change is suggested, further discussion on the
|
||||
subject may be required
|
||||
- SHOULD means that the change is suggested, further discussion on the subject may be required
|
||||
- COULD means that the change is optional
|
||||
|
||||
## Getting Started
|
||||
|
||||
Once available, please see the [developer's guide][devguide] for instructions to set up a suitable development environment.
|
||||
Once available, please see the [developer's guide][devguide] for instructions to set up a suitable
|
||||
development environment.
|
||||
|
||||
## Timeline and Managing Expectations
|
||||
|
||||
As we continue to engage contributors and learn best practices for running a successful open source project, our processes
|
||||
and guidance will likely evolve. We will try to communicate expectations as we are able and to always be responsive. We
|
||||
hope that the community will share their suggestions for improving this engagement. Based on the level of initial interest
|
||||
we receive and the availability of resources to evaluate contributions, we anticipate the following:
|
||||
As we continue to engage contributors and learn best practices for running a successful open source
|
||||
project, our processes and guidance will likely evolve. We will try to communicate expectations as
|
||||
we are able to and be responsive. We hope that the community will share their suggestions for
|
||||
improving this engagement. Based on the level of initial interest we receive and the availability
|
||||
of resources to evaluate contributions, we anticipate the following:
|
||||
|
||||
- We will initially prioritize pull requests that include small bug fixes and code that addresses potential vulnerabilities
|
||||
as well as pull requests that include improvements for processor language specifications because these require a
|
||||
reasonable amount of effort to evaluate and will help us exercise and revise our process for accepting contributions. In
|
||||
other words, we are going to start small in order to work out the kinks first.
|
||||
- We are committed to maintaining the integrity and security of our code base. In addition to the careful review the
|
||||
maintainers will give to code contributions to make sure they do not introduce new bugs or vulnerabilities, we will be
|
||||
trying to identify best practices to incorporate with our open source project so that contributors can have more control
|
||||
over whether their contributions are accepted. These might include things like style guides and requirements for tests and
|
||||
documentation to accompany some code contributions. As a result, it may take a long time for some contributions to be
|
||||
accepted. This does not mean we are ignoring them.
|
||||
- We are committed to integrating this GitHub project with our team's regular development work flow so that the open source
|
||||
project remains dynamic and relevant. This may affect our responsiveness and ability to accept pull requests
|
||||
quickly. This does not mean we are ignoring them.
|
||||
- Not all innovative ideas need to be accepted as pull requests into this GitHub project to be valuable to the community.
|
||||
There may be times when we recommend that you just share your code for some enhancement to Ghidra from your own
|
||||
repository. As we identify and recognize extensions that are of general interest to the reverse engineering community, we
|
||||
may seek to incorporate them with our baseline.
|
||||
- We will initially prioritize pull requests that include small bug fixes and code that addresses
|
||||
potential vulnerabilities as well as pull requests that include improvements for processor
|
||||
language specifications because these require a reasonable amount of effort to evaluate and will
|
||||
help us exercise and revise our process for accepting contributions. In other words, we are going
|
||||
to start small in order to work out the kinks first.
|
||||
- We are committed to maintaining the integrity and security of our code base. In addition to the
|
||||
careful review the maintainers will give to code contributions to make sure they do not introduce
|
||||
new bugs or vulnerabilities, we will be trying to identify best practices to incorporate with our
|
||||
open source project so that contributors can have more control over whether their contributions
|
||||
are accepted. These might include things like style guides and requirements for tests and
|
||||
documentation to accompany some code contributions. As a result, it may take a long time for some
|
||||
contributions to be accepted. This does not mean we are ignoring them.
|
||||
- We are committed to integrating this GitHub project with our team's regular development work flow
|
||||
so that the open source project remains dynamic and relevant. This may affect our responsiveness
|
||||
and ability to accept pull requests quickly. This does not mean we are ignoring them.
|
||||
- Not all innovative ideas need to be accepted as pull requests into this GitHub project to be
|
||||
valuable to the community. There may be times when we recommend that you just share your code for
|
||||
some enhancement to Ghidra from your own repository. As we identify and recognize extensions that
|
||||
are of general interest to the reverse engineering community, we may seek to incorporate them with
|
||||
our baseline.
|
||||
|
||||
## Legal
|
||||
|
||||
Consistent with Section D.6. of the GitHub Terms of Service as of 2019, and Section 5. of the Apache License, Version 2.0, the project maintainer for this project accepts contributions using the inbound=outbound model.
|
||||
When you submit a pull request to this repository (inbound), you are agreeing to license your contribution under the same terms as specified in [LICENSE] (outbound).
|
||||
Consistent with Section D.6. of the GitHub Terms of Service as of 2019, and Section 5. of the Apache
|
||||
License, Version 2.0, the project maintainer for this project accepts contributions using the
|
||||
inbound=outbound model. When you submit a pull request to this repository (inbound), you are
|
||||
agreeing to license your contribution under the same terms as specified in [LICENSE] (outbound).
|
||||
|
||||
This is an open source project.
|
||||
Contributions you make to this public U.S. Government ("USG") repository are completely voluntary.
|
||||
When you submit an issue, bug report, question, enhancement, pull request, etc., you are offering your contribution without expectation of payment, you expressly waive any future pay claims against the USG related to your contribution, and you acknowledge that this does not create an obligation on the part of the USG of any kind.
|
||||
Furthermore, your contributing to this project does not create an employer-employee relationship between the United States ("U.S.") Government and the contributor.
|
||||
This is an open source project. Contributions you make to this public U.S. Government ("USG")
|
||||
repository are completely voluntary. When you submit an issue, bug report, question, enhancement,
|
||||
pull request, etc., you are offering your contribution without expectation of payment, you expressly
|
||||
waive any future pay claims against the USG related to your contribution, and you acknowledge that
|
||||
this does not create an obligation on the part of the USG of any kind. Furthermore, your
|
||||
contributing to this project does not create an employer-employee relationship between the United
|
||||
States ("U.S.") Government and the contributor.
|
||||
|
||||
[issues]: https://github.com/NationalSecurityAgency/ghidra/issues
|
||||
[repository]: https://github.com/NationalSecurityAgency/ghidra/
|
||||
|
||||
@@ -41,6 +41,12 @@ will be stored at `$HOME/.gradle/`.
|
||||
gradle prepdev
|
||||
```
|
||||
|
||||
Clean up repository build files. In rare circumstances this may be necessary after a `git pull` to
|
||||
fix unexplainable compilation errors.
|
||||
```
|
||||
gradle clean
|
||||
```
|
||||
|
||||
Generate nested Eclipse project files which can then be imported into Eclipse as "existing
|
||||
projects".
|
||||
```
|
||||
|
||||
@@ -24,6 +24,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getShort(byte[])
|
||||
*/
|
||||
@Override
|
||||
public final short getShort(byte[] b) {
|
||||
return getShort(b, 0);
|
||||
}
|
||||
@@ -31,6 +32,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getShort(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public short getShort(byte[] b, int offset) {
|
||||
return (short) (((b[offset] & 0xff) << 8) | (b[offset + 1] & 0xff));
|
||||
}
|
||||
@@ -38,6 +40,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getInt(byte[])
|
||||
*/
|
||||
@Override
|
||||
public final int getInt(byte[] b) {
|
||||
return getInt(b, 0);
|
||||
}
|
||||
@@ -45,6 +48,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getInt(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public int getInt(byte[] b, int offset) {
|
||||
int v = b[offset];
|
||||
for (int i = 1; i < 4; i++) {
|
||||
@@ -56,6 +60,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getLong(byte[])
|
||||
*/
|
||||
@Override
|
||||
public final long getLong(byte[] b) {
|
||||
return getLong(b, 0);
|
||||
}
|
||||
@@ -63,6 +68,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getLong(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public long getLong(byte[] b, int offset) {
|
||||
long v = b[offset];
|
||||
for (int i = 1; i < 8; i++) {
|
||||
@@ -74,6 +80,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter.util.DataConverter#getValue(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(byte[] b, int size) {
|
||||
return getValue(b, 0, size);
|
||||
}
|
||||
@@ -81,6 +88,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter.util.DataConverter#getValue(byte[], int, int)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(byte[] b, int offset, int size) {
|
||||
if (size > 8) {
|
||||
throw new IndexOutOfBoundsException("size exceeds sizeof long: " + size);
|
||||
@@ -95,6 +103,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getBytes(short, byte[])
|
||||
*/
|
||||
@Override
|
||||
public final void getBytes(short value, byte[] b) {
|
||||
getBytes(value, b, 0);
|
||||
}
|
||||
@@ -102,6 +111,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getBytes(short, byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public void getBytes(short value, byte[] b, int offset) {
|
||||
b[offset] = (byte) (value >> 8);
|
||||
b[offset + 1] = (byte) (value & 0xff);
|
||||
@@ -110,6 +120,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getBytes(int, byte[])
|
||||
*/
|
||||
@Override
|
||||
public final void getBytes(int value, byte[] b) {
|
||||
getBytes(value, b, 0);
|
||||
}
|
||||
@@ -117,6 +128,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getBytes(int, byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public void getBytes(int value, byte[] b, int offset) {
|
||||
b[offset + 3] = (byte) (value);
|
||||
for (int i = 2; i >= 0; i--) {
|
||||
@@ -128,6 +140,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getBytes(long, byte[])
|
||||
*/
|
||||
@Override
|
||||
public final void getBytes(long value, byte[] b) {
|
||||
getBytes(value, 8, b, 0);
|
||||
}
|
||||
@@ -135,6 +148,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getBytes(long, byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public void getBytes(long value, byte[] b, int offset) {
|
||||
getBytes(value, 8, b, offset);
|
||||
}
|
||||
@@ -142,6 +156,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter.util.DataConverter#getBytes(long, int, byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public void getBytes(long value, int size, byte[] b, int offset) {
|
||||
for (int i = size - 1; i >= 0; i--) {
|
||||
b[offset + i] = (byte) value;
|
||||
@@ -152,6 +167,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter.util.DataConverter#putInt(byte[], int, int)
|
||||
*/
|
||||
@Override
|
||||
public final void putInt(byte[] b, int offset, int value) {
|
||||
getBytes(value, b, offset);
|
||||
}
|
||||
@@ -159,6 +175,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter.util.DataConverter#putInt(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public final void putInt(byte[] b, int value) {
|
||||
getBytes(value, b);
|
||||
}
|
||||
@@ -166,6 +183,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter.util.DataConverter#putLong(byte[], int, long)
|
||||
*/
|
||||
@Override
|
||||
public final void putLong(byte[] b, int offset, long value) {
|
||||
getBytes(value, b, offset);
|
||||
}
|
||||
@@ -173,6 +191,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter.util.DataConverter#putLong(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public final void putLong(byte[] b, long value) {
|
||||
getBytes(value, b);
|
||||
}
|
||||
@@ -180,6 +199,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter.util.DataConverter#putShort(byte[], int, short)
|
||||
*/
|
||||
@Override
|
||||
public final void putShort(byte[] b, int offset, short value) {
|
||||
getBytes(value, b, offset);
|
||||
}
|
||||
@@ -187,6 +207,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter.util.DataConverter#putShort(byte[], short)
|
||||
*/
|
||||
@Override
|
||||
public final void putShort(byte[] b, short value) {
|
||||
getBytes(value, b);
|
||||
}
|
||||
@@ -194,6 +215,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter.util.DataConverter#getBytes(int)
|
||||
*/
|
||||
@Override
|
||||
public byte[] getBytes(int value) {
|
||||
byte[] bytes = new byte[4];
|
||||
getBytes(value, bytes);
|
||||
@@ -203,6 +225,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter.util.DataConverter#getBytes(long)
|
||||
*/
|
||||
@Override
|
||||
public byte[] getBytes(long value) {
|
||||
byte[] bytes = new byte[8];
|
||||
getBytes(value, bytes);
|
||||
@@ -212,6 +235,7 @@ public class GDataConverterBE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter.util.DataConverter#getBytes(short)
|
||||
*/
|
||||
@Override
|
||||
public byte[] getBytes(short value) {
|
||||
byte[] bytes = new byte[2];
|
||||
getBytes(value, bytes);
|
||||
|
||||
@@ -23,6 +23,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getShort(byte[])
|
||||
*/
|
||||
@Override
|
||||
public final short getShort(byte[] b) {
|
||||
return getShort(b, 0);
|
||||
}
|
||||
@@ -30,6 +31,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getShort(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public short getShort(byte[] b, int offset) {
|
||||
return (short) (((b[offset + 1] & 0xff) << 8) | (b[offset] & 0xff));
|
||||
}
|
||||
@@ -37,6 +39,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getInt(byte[])
|
||||
*/
|
||||
@Override
|
||||
public final int getInt(byte[] b) {
|
||||
return getInt(b, 0);
|
||||
}
|
||||
@@ -44,6 +47,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getInt(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public int getInt(byte[] b, int offset) {
|
||||
int v = b[offset + 3];
|
||||
for (int i = 2; i >= 0; i--) {
|
||||
@@ -55,6 +59,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getLong(byte[])
|
||||
*/
|
||||
@Override
|
||||
public final long getLong(byte[] b) {
|
||||
return getLong(b, 0);
|
||||
}
|
||||
@@ -62,6 +67,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getLong(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public long getLong(byte[] b, int offset) {
|
||||
long v = b[offset + 7];
|
||||
for (int i = 6; i >= 0; i--) {
|
||||
@@ -73,6 +79,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see ghidra.util.GDataConverter#getValue(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(byte[] b, int size) {
|
||||
return getValue(b, 0, size);
|
||||
}
|
||||
@@ -80,6 +87,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see ghidra.util.GDataConverter#getValue(byte[], int, int)
|
||||
*/
|
||||
@Override
|
||||
public long getValue(byte[] b, int offset, int size) {
|
||||
if (size > 8) {
|
||||
throw new IndexOutOfBoundsException("size exceeds sizeof long: " + size);
|
||||
@@ -94,6 +102,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getBytes(short, byte[])
|
||||
*/
|
||||
@Override
|
||||
public final void getBytes(short value, byte[] b) {
|
||||
getBytes(value, b, 0);
|
||||
}
|
||||
@@ -101,6 +110,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getBytes(short, byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public void getBytes(short value, byte[] b, int offset) {
|
||||
b[offset + 1] = (byte) (value >> 8);
|
||||
b[offset] = (byte) (value & 0xff);
|
||||
@@ -109,6 +119,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getBytes(int, byte[])
|
||||
*/
|
||||
@Override
|
||||
public final void getBytes(int value, byte[] b) {
|
||||
getBytes(value, b, 0);
|
||||
}
|
||||
@@ -116,6 +127,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getBytes(int, byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public void getBytes(int value, byte[] b, int offset) {
|
||||
b[offset] = (byte) (value);
|
||||
for (int i = 1; i < 4; i++) {
|
||||
@@ -127,6 +139,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getBytes(long, byte[])
|
||||
*/
|
||||
@Override
|
||||
public final void getBytes(long value, byte[] b) {
|
||||
getBytes(value, 8, b, 0);
|
||||
}
|
||||
@@ -134,6 +147,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see GDataConverter#getBytes(long, byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public void getBytes(long value, byte[] b, int offset) {
|
||||
getBytes(value, 8, b, offset);
|
||||
}
|
||||
@@ -141,6 +155,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see ghidra.util.GDataConverter#getBytes(long, int, byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public void getBytes(long value, int size, byte[] b, int offset) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
b[offset + i] = (byte) value;
|
||||
@@ -151,6 +166,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see ghidra.util.GDataConverter#putInt(byte[], int, int)
|
||||
*/
|
||||
@Override
|
||||
public final void putInt(byte[] b, int offset, int value) {
|
||||
getBytes(value, b, offset);
|
||||
}
|
||||
@@ -158,6 +174,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see ghidra.util.GDataConverter#putInt(byte[], int)
|
||||
*/
|
||||
@Override
|
||||
public final void putInt(byte[] b, int value) {
|
||||
getBytes(value, b);
|
||||
}
|
||||
@@ -165,6 +182,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see ghidra.util.GDataConverter#putLong(byte[], int, long)
|
||||
*/
|
||||
@Override
|
||||
public final void putLong(byte[] b, int offset, long value) {
|
||||
getBytes(value, b, offset);
|
||||
}
|
||||
@@ -172,6 +190,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see ghidra.util.GDataConverter#putLong(byte[], long)
|
||||
*/
|
||||
@Override
|
||||
public final void putLong(byte[] b, long value) {
|
||||
getBytes(value, b);
|
||||
}
|
||||
@@ -179,6 +198,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see ghidra.util.GDataConverter#putShort(byte[], int, short)
|
||||
*/
|
||||
@Override
|
||||
public final void putShort(byte[] b, int offset, short value) {
|
||||
getBytes(value, b, offset);
|
||||
}
|
||||
@@ -186,6 +206,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see ghidra.util.GDataConverter#putShort(byte[], short)
|
||||
*/
|
||||
@Override
|
||||
public final void putShort(byte[] b, short value) {
|
||||
getBytes(value, b);
|
||||
}
|
||||
@@ -193,6 +214,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see ghidra.util.GDataConverter#getBytes(int)
|
||||
*/
|
||||
@Override
|
||||
public byte[] getBytes(int value) {
|
||||
byte[] bytes = new byte[4];
|
||||
getBytes(value, bytes);
|
||||
@@ -202,6 +224,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see ghidra.util.GDataConverter#getBytes(long)
|
||||
*/
|
||||
@Override
|
||||
public byte[] getBytes(long value) {
|
||||
byte[] bytes = new byte[8];
|
||||
getBytes(value, bytes);
|
||||
@@ -211,6 +234,7 @@ public class GDataConverterLE implements GDataConverter {
|
||||
/**
|
||||
* @see ghidra.util.GDataConverter#getBytes(short)
|
||||
*/
|
||||
@Override
|
||||
public byte[] getBytes(short value) {
|
||||
byte[] bytes = new byte[2];
|
||||
getBytes(value, bytes);
|
||||
|
||||
@@ -9,71 +9,118 @@
|
||||
* and SDKs are installed.
|
||||
****************************************************************************/
|
||||
|
||||
if (!hasProperty("VISUAL_STUDIO_INSTALL_DIR")) {
|
||||
configureVisualStudio()
|
||||
if (!hasProperty("VISUAL_STUDIO_INSTALL_DIR") && isCurrentWindows()) {
|
||||
|
||||
// Initialize variables
|
||||
rootProject.ext.VISUAL_STUDIO_INSTALL_DIR = ""
|
||||
rootProject.ext.VISUAL_STUDIO_TOOLS_VERSION_DEFAULT = ""
|
||||
rootProject.ext.VISUAL_STUDIO_SDK_DIR_DEFAULT = ""
|
||||
rootProject.ext.VISUAL_STUDIO_SDK_VERSION_DEFAULT = ""
|
||||
rootProject.ext.VISUAL_STUDIO_SDK_VERSION_OVERRIDE = ""
|
||||
rootProject.ext.VISUAL_STUDIO_VCVARS_CMD = ""
|
||||
|
||||
// Use vswhere.exe to search for latest Visual Studio installation
|
||||
println "Searching for latest Visual Studio and required components..."
|
||||
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 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 * -prerelease -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -format json -utf8".execute()
|
||||
def vswhereOutput = vswhereProcess.text.trim()
|
||||
def vswhereExit = vswhereProcess.exitValue()
|
||||
if (vswhereExit != 0) {
|
||||
if (vswhereExit == 87) { // ERROR_INVALID_PARAMATER
|
||||
println " -> Visual Studio vswhere.exe was passed an unsupported argument!"
|
||||
}
|
||||
else {
|
||||
println " -> Visual Studio vswhere.exe returned an error code (${vswhereExit})!"
|
||||
}
|
||||
println " -> Please confirm ${vswherePath} is version 2.5 or later."
|
||||
println " -> Please check README.md or GettingStarted.md to verify you are using a supported version of Visual Studio."
|
||||
return
|
||||
}
|
||||
def vswhereJson = new groovy.json.JsonSlurper().parseText(vswhereOutput);
|
||||
|
||||
// Our minimum supported version of vswhere does not support the -sort arg, so we must
|
||||
// manually sort. The -sort arg was introduced in vswhere 2.6.7.
|
||||
sortVisualStudioVersions(vswhereJson)
|
||||
|
||||
def usePrerelease = project.hasProperty("vswherePrerelease")
|
||||
def i = -1
|
||||
println " -> Searching for Visual Studio installations..."
|
||||
vswhereJson.eachWithIndex { item, index ->
|
||||
def isPrerelease = item.get("isPrerelease")
|
||||
if (i == -1 && (usePrerelease || !isPrerelease)) {
|
||||
i = index
|
||||
}
|
||||
println " ${index + 1}: ${item.displayName}" +
|
||||
(i == index ? " (selected)" : "") +
|
||||
(isPrerelease && !usePrerelease ? " (enable with -PvswherePrerelease)" : "")
|
||||
println " - Installation Version: ${item.installationVersion}" +
|
||||
(item.containsKey("unsupportedVersion") ? " (failed to sort)" : "")
|
||||
println " - Installation Date: ${item.installDate}"
|
||||
println " - Installation Path: ${item.installationPath}"
|
||||
if (isPrerelease) {
|
||||
println " - Prerelease"
|
||||
}
|
||||
}
|
||||
if (i == -1) {
|
||||
println " -> Visual Studio not found!"
|
||||
return
|
||||
}
|
||||
|
||||
def vsInstallDir = vswhereJson[i].installationPath
|
||||
println " -> Installation Directory: ${vsInstallDir}"
|
||||
|
||||
// Use vcvarsall.bat to determine the latest Visual Studio's default SDK and tool versions
|
||||
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 sdkDir = "${vcvarsEnvCmd} !WindowsSdkDir!".execute().text.trim()
|
||||
println " -> SDK Directory (default): ${sdkDir}"
|
||||
def sdkVersion = "${vcvarsEnvCmd} !WindowsSDKVersion!".execute().text.trim().replace('\\', '')
|
||||
println " -> SDK Version (default): ${sdkVersion}"
|
||||
|
||||
// Check Gradle properties for override values
|
||||
def windowsTargetPlatformVersion = findProperty("WindowsTargetPlatformVersion")
|
||||
println " -> SDK Version (override): " + (windowsTargetPlatformVersion ?: "N/A")
|
||||
|
||||
// Save Visual Studio information so other projects can access it
|
||||
rootProject.ext.VISUAL_STUDIO_INSTALL_DIR = vsInstallDir
|
||||
rootProject.ext.VISUAL_STUDIO_SDK_DIR_DEFAULT = sdkDir
|
||||
rootProject.ext.VISUAL_STUDIO_SDK_VERSION_DEFAULT = sdkVersion
|
||||
rootProject.ext.VISUAL_STUDIO_SDK_VERSION_OVERRIDE = windowsTargetPlatformVersion
|
||||
rootProject.ext.VISUAL_STUDIO_VCVARS_CMD = vcvarsCmd
|
||||
}
|
||||
|
||||
def configureVisualStudio() {
|
||||
|
||||
if (isCurrentWindows()) {
|
||||
|
||||
// Initialize variables
|
||||
rootProject.ext.VISUAL_STUDIO_INSTALL_DIR = ""
|
||||
rootProject.ext.VISUAL_STUDIO_TOOLS_VERSION_DEFAULT = ""
|
||||
rootProject.ext.VISUAL_STUDIO_SDK_DIR_DEFAULT = ""
|
||||
rootProject.ext.VISUAL_STUDIO_SDK_VERSION_DEFAULT = ""
|
||||
rootProject.ext.VISUAL_STUDIO_SDK_VERSION_OVERRIDE = ""
|
||||
rootProject.ext.VISUAL_STUDIO_VCVARS_CMD = ""
|
||||
|
||||
// Use vswhere.exe to search for latest Visual Studio installation
|
||||
println "Searching for latest Visual Studio and required components..."
|
||||
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 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 vswhereOutput = vswhereProcess.text.trim()
|
||||
def vswhereExit = vswhereProcess.exitValue()
|
||||
if (vswhereExit != 0) {
|
||||
if (vswhereExit == 87) { // ERROR_INVALID_PARAMATER
|
||||
println " -> Visual Studio vswhere.exe was passed an unsupported argument!"
|
||||
}
|
||||
else {
|
||||
println " -> Visual Studio vswhere.exe returned an error code (${vswhereExit})!"
|
||||
}
|
||||
println " -> Please confirm ${vswherePath} is version 2.5 or later."
|
||||
println " -> Please check README.md or GettingStarted.md to verify you are using a supported version of Visual Studio."
|
||||
return
|
||||
}
|
||||
def vswhereJson = new groovy.json.JsonSlurper().parseText(vswhereOutput);
|
||||
if (vswhereJson.isEmpty()) {
|
||||
println " -> Visual Studio not found!"
|
||||
return
|
||||
}
|
||||
def vsInstallDir = vswhereJson[0].installationPath
|
||||
println " -> Installation Directory: ${vsInstallDir}"
|
||||
def sortVisualStudioVersions(vswhereJson) {
|
||||
|
||||
// Use vcvarsall.bat to determine the latest Visual Studio's default SDK and tool versions
|
||||
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 sdkDir = "${vcvarsEnvCmd} !WindowsSdkDir!".execute().text.trim()
|
||||
println " -> SDK Directory (default): ${sdkDir}"
|
||||
def sdkVersion = "${vcvarsEnvCmd} !WindowsSDKVersion!".execute().text.trim().replace('\\', '')
|
||||
println " -> SDK Version (default): ${sdkVersion}"
|
||||
|
||||
// Check Gradle properties for override values
|
||||
def windowsTargetPlatformVersion = findProperty("WindowsTargetPlatformVersion")
|
||||
println " -> SDK Version (override): " + (windowsTargetPlatformVersion ?: "N/A")
|
||||
|
||||
// Save Visual Studio information so other projects can access it
|
||||
rootProject.ext.VISUAL_STUDIO_INSTALL_DIR = vsInstallDir
|
||||
rootProject.ext.VISUAL_STUDIO_SDK_DIR_DEFAULT = sdkDir
|
||||
rootProject.ext.VISUAL_STUDIO_SDK_VERSION_DEFAULT = sdkVersion
|
||||
rootProject.ext.VISUAL_STUDIO_SDK_VERSION_OVERRIDE = windowsTargetPlatformVersion
|
||||
rootProject.ext.VISUAL_STUDIO_VCVARS_CMD = vcvarsCmd
|
||||
// Try to parse each version using Gradle's own version parser, marking the entries that failed
|
||||
// (none should fail)
|
||||
def validVersions = true
|
||||
vswhereJson.each {
|
||||
try {
|
||||
GradleVersion.version(it.installationVersion)
|
||||
}
|
||||
catch (Exception e) {
|
||||
it.put("unsupportedVersion", "true")
|
||||
validVersions = false
|
||||
}
|
||||
}
|
||||
|
||||
// Establish a consistent ordering by first sorting by instance ID
|
||||
vswhereJson.sort { a, b -> b.instanceId <=> a.instanceId }
|
||||
|
||||
// Primary sort by installation version. If all the version numbers were parseable with the
|
||||
// GradleVersion class, use that class to achieve the correct ordering. Otherwise, fall back to
|
||||
// lexicographic order.
|
||||
if (validVersions) {
|
||||
vswhereJson.sort { a, b -> GradleVersion.version(b.installationVersion) <=> GradleVersion.version(a.installationVersion) } // primary sort
|
||||
}
|
||||
else {
|
||||
vswhereJson.sort { a, b -> b.installationVersion <=> a.installationVersion } // primary sort
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,172 @@
|
||||
# Ghidra 12.0 Change History (December 2025)
|
||||
|
||||
### New Features
|
||||
* _Data Types_. Added `RGB16` and `RGB32` Color primitive datatypes which have been implemented as unsigned integer types and will render a color patch for Data within the Listing. These default, respectively, to `RGB_565` and `ARGB_8888` encodings but can adopt a different RGB Encoding through the use of a Typedef and a default Setting. (GP-4310, Issue #6191)
|
||||
* _Decompiler_. Implemented low-pcode-based abstract interpretation via the Università Ca’ Foscari's Library for Static Analysis (LiSA). (GP-5566)
|
||||
* _Emulator_. Added an experimental Z3 Symbolic emulator with a summarization GUI. This feature is distributed as an installable extension. (GP-5727)
|
||||
* _FileSystems_. Add support for zstd compression in GFileSystem via user-provided zstd or 7-Zip command line tools. (GP-5842)
|
||||
* _Graphing_. Added a Function Graph tab to the Function Comparison widget. This allows users to see two functions side-by-side in Function Graph views, such as when viewing BSim functions. (GP-3648, Issue #1154)
|
||||
* _Graphing_. Created a new prototype __Data Graph__ graphing feature with nodes that display data structures and values and edges that link one data structure to another via a pointer reference. (GP-5481)
|
||||
* _GUI_. Updated the Xrefs Table to allow the user to delete references to the current location. (GP-2140, Issue #4317)
|
||||
* _GUI_. Added a shared project repository connection status indicator to the root node of the project data tree. A popup menu action was also added to the root node allowing the connection to be established when in a disconnected state. (GP-5333)
|
||||
* _GUI_. Added ability to toggle the displaying of function variables (parameters and locals) that are normally displayed just below the function signature. The variables display can be turned on/off globally or individually per function. (GP-5886, Issue #8385)
|
||||
* _Importer_. Created an importer for the Decompiler debug format which is produced by the Decompiler. (GP-3947)
|
||||
* _Importer_. Added an option to mirror the local filesystem when importing programs and their libraries. Programs and libraries that exist on the local filesystem as symbolic links will have both their corresponding link file and resolved program file mirrored in the project. (GP-5343, Issue #7430)
|
||||
* _Importer_. Added a new loader for HP-UX PA-RISC __System Object Module__ (SOM) binaries. (GP-5942)
|
||||
* _Processors_. Added support for the NDS32 Processor. (GP-6007, Issue #1778)
|
||||
* _Project_. Added expanded support for project link-files with the introduction of internal project folder and file links. The links behave similar to Linux symbolic links and allow a single folder or file to be referenced by alternative project paths. The GUI Project Tree and related project file chooser have also been improved with the ability to expand folder-links like folders (subject to filter restrictions at the API level). The main Project Tree will continue to rely on project views for following external folder-links. Some of the project tree's recursive traversal actions do not follow folder-links (e.g., Expand All). NOTE: Although Ghidra permits files and folders to have the same name, this should be avoided when utilizing link-files or Ghidra URLs due to the path ambiguity it can cause. This change also introduces a new file storage format which can create issues within a project if opened with an older version of Ghidra. While this version remains compatible with older Ghidra Server versions, adding link files to a repository will require a Ghidra Server upgrade to the latest version. (GP-3551)
|
||||
|
||||
### Improvements
|
||||
* _Accessibility_. Fixed tooltips in the Symbol Tree to not read HTML markup to screen readers. (GP-5741, Issue #8228)
|
||||
* _Analysis_. Added `ENDBR64` and `ENDBR32` to function start patterns for x86 gcc. (GP-5287)
|
||||
* _Analysis_. Added support for Golang 1.24 and 1.25. Changed method of bootstrapping Go type info to use json Go snapshot files instead of gdt files. (GP-5470)
|
||||
* _Analysis_. Fixed PowerPC 64-bit thunk patterns using prepatterns analyzer pattern files. (GP-6120)
|
||||
* _API_. Corrected ELF ppc64 import issues related to use of 32-bit-addressing language variants. Improved handling of ELFv1 vs. ELFv2 binary markup. Eliminated EXTERNAL `.pltgot.` symbols. (GP-3091, Issue #570)
|
||||
* _API_. Updated various `SourceType` checks which should avoid use of equality checks in favor of priority checks when covering a range of sources. (GP-6008)
|
||||
* _Basic Infrastructure_. The `support/launch.properties` now supports expansion of `${var}`-style environment variables. (GP-6022)
|
||||
* _BSim_. Added `getmetadata` subcommand to `bsim` command-line utility. (GP-5748, Issue #8176)
|
||||
* _BSim_. Updated BSim Elasticsearch extension support to version 8.19.7. (GP-6146, Issue #8611)
|
||||
* _Calling Conventions_. Added a compiler specification for Apple platforms on ARM64. (GP-3139, Issue #2723, #8032)
|
||||
* _Calling Conventions_. Corrected handling of parameters for the AVR8 calling convention. Expanded abilities of Decompiler model rules for expressing calling conventions in XML cspec files. (GP-4356)
|
||||
* _Calling Conventions_. Added `max_primitives` filter to homogeneous aggregate type in cspec files. (GP-5367)
|
||||
* _Calling Conventions_. Added callfixups to x86 gcc compiler spec for pc_thunk functions using the `DI` register. (GP-5958, Issue #8416)
|
||||
* _CodeBrowser_. Replaced __Dynamic Update__ checkbox in __Instruction Info__ window with a toolbar toggle action. (GP-5650)
|
||||
* _CodeCompare_. Added actions to transfer variable and callee function names and datatypes from the dual Decompiler function comparison window. (GP-4007)
|
||||
* _Data_. Improved the Listing's __Create Structure__ action, giving the ability to choose the data type category. (GP-5327, Issue #6713)
|
||||
* _Data Types_. Added utility methods to the `DataTypeQueryService` for clients to have more flexibility in how they retrieve data types. (GP-5694, Issue #8157)
|
||||
* _Debugger:Agents_. Upgraded to `protobuf-java 4.31.0` and `protobuf 6.31.0` for Python. (GP-5456)
|
||||
* _Debugger:Agents_. Improved debug-connection failure-detection when the back-end terminates early. (GP-5700)
|
||||
* _Debugger:Emulator_. Added Help for `PcodeStepperPlugin`. (GP-5772)
|
||||
* _Debugger:Emulator_. Fixed an issue with emulation when the program has block/sections with brackets in the name. (GP-5897, Issue #8398)
|
||||
* _Debugger:LLDB_. Fixed variable name typos in the `lldbsetuputils.ps1` script. (GP-5973, Issue #8498)
|
||||
* _Debugger:Trace_. Removed legacy mode from the Trace database. (GP-5194)
|
||||
* _Debugger:Watches_. Added a __Comment__ column to the __Watch__ window. (GP-5795, Issue #8302)
|
||||
* _Decompiler_. The Decompiler now propagates constants through conditional branches in more situations. (GP-5950, Issue #8455)
|
||||
* _Demangler_. Modified Microsoft Demangler to process virtual call modifiers and based pointers for 16-bit programs. (GP-5776)
|
||||
* _Disassembly_. Added quick toggle action (`Ctrl-Shift-1`) for __PCode__ field in the Listing display. (GP-5930)
|
||||
* _Documentation_. Fixed missing javadocs for Debugger-related APIs. (GP-5891)
|
||||
* _DWARF_. The DWARF analyzer now records all source files, including source files without source map information. (GP-5773)
|
||||
* _DWARF_. Added code for parsing DWARF `.debug_macro` sections and example script, `DWARFMacroScript`. (GP-5792)
|
||||
* _DWARF_. Add support for specifying the charset of DWARF debug strings. (GP-5871, Issue #8346)
|
||||
* _DWARF_. The DWARF analyzer can now create enums from macro information recorded in DWARF debug data (DWARF v5 only). (GP-5984)
|
||||
* _ELF_. Added partial support for AARCH64 ELF loading of object modules with GOT allocation capability. Added support for the following relocation types which rely on this revised relocation handler capability: `R_AARCH64_ADR_GOT_PAGE`, `R_AARCH64_P32_ADR_GOT_PAGE`, `R_AARCH64_P32_LD32_GOT_LO12_NC`, and `R_AARCH64_LD64_GOT_LO12_NC`. (GP-5815, Issue #8253)
|
||||
* _Emulator_. Refactored the p-code emulator to use composition instead of inheritance for UI integration. This should simplify development of extended emulators and permit easier integration of those emulators with the UI. (GP-5879)
|
||||
* _Emulator:JIT_. Added support for multi-precision integers (varnodes of size 9 or greater) to the JIT-accelerated p-code emulator. (GP-5214)
|
||||
* _Exporter_. Updated the IDA Pro exporter to work with IDA Pro 9.x. (GP-5873, Issue #7392)
|
||||
* _FID_. Updated the FID plugin to delay loading of FID DB resources. This will improve the tool load time when there are many FID DB objects in use. (GP-6073, Issue #8593)
|
||||
* _Graphing_. Update the Program Graph __Compact Hierarchical__ layout to have less space between nodes. (GP-4741)
|
||||
* _GUI_. Added ability to remember last user ID specified for server login prompts such as the Ghidra Server authentication prompt. (GP-5579, Issue #7454)
|
||||
* _GUI_. Added ability to reorder program tabs via drag-n-drop. (GP-5646, Issue #8099)
|
||||
* _GUI_. Updated the Data Type Manager to increase performance in deleting data types. (GP-5654, Issue #8104)
|
||||
* _GUI_. Updated the Structure Editor's __Find Uses of__ action to work on fields with no name or data type. (GP-5711, Issue #8171)
|
||||
* _GUI_. Added modes to the drop-down text fields to control how matches are found. Choices will now typically include __Starts With__ and __Contains__ modes. (GP-5720, Issue #4725, #8203)
|
||||
* _GUI_. Update the Data Type Manager's __Collapse__ toolbar action to stop any post-filter state-restoring. (GP-5761, Issue #8244)
|
||||
* _GUI_. Updated dialogs wth combo boxes to have consistent behavior when pressing the `Enter` key. (GP-5769, Issue #8280)
|
||||
* _GUI_. Updated the Ghidra File Chooser to not lock the UI for folders that contain many files. (GP-5807, Issue #4725, #8284)
|
||||
* _GUI_. Reduced some excessive Symbol Tree updates seen while performing auto-analysis. (GP-5826)
|
||||
* _GUI_. Fixed bug in Memory Search where some GUI options were not initialized correctly to the last-used options. (GP-5883)
|
||||
* _GUI_. Updated the __Next Instruction__ action to jump to the function entry point when the action is invoked from the function signature. (GP-5885, Issue #8385)
|
||||
* _GUI_. Added full data type path to Decompiler and Listing hovers. (GP-5913)
|
||||
* _GUI_. Created new theme value for the Decompiler's middle-mouse highlight color so that the Listing and Decompiler colors may change independently. (GP-5947)
|
||||
* _GUI_. Added convenience methods to `TableColumnDescriptor` to create simple columns using only a name, column type, and a function to map from the row object to the column object. (GP-5963, Issue #7346)
|
||||
* _GUI_. Added key-binding navigation support to the File Chooser. (GP-5964, Issue #6310, #7129, #7130)
|
||||
* _GUI_. Updated the Tool Options' Key Binding view to have a simpler screen. (GP-5967, Issue #7024)
|
||||
* _GUI_. Updated key-binding support to allow for usage of the right `Alt` key independently from the left `Alt` key. (GP-5978, Issue #8205)
|
||||
* _GUI_. Added accelerator mnemonics to the Memory Search dialog to help reduce manual navigation issues. (GP-5979, Issue #8264)
|
||||
* _Headless_. The user can now specify headless loader options independently of what loader is being used. The headless importer will ignore loader options that are unsupported by the active loader. (GP-5545)
|
||||
* _Help_. Added Processor, Language, and Compiler specification file names to __About Program__ dialog. (GP-5716, Issue #8163)
|
||||
* _Importer:COFF_. Added support for importing big-endian COFF binaries. (GP-5645, Issue #1398, #8042)
|
||||
* _Importer:PE_. The PeLoader no longer fails to import if a Data Directory does not parse successfully. (GP-4881, Issue #6864)
|
||||
* _Languages_. Corrected handling of small integer parameters and structured data-type parameters for the PowerPC 64-bit default calling convention. (GP-4029)
|
||||
* _Languages_. Added support for mixed integer/floating-point parameters and structured data-type parameters for MIPS calling conventions. (GP-4030)
|
||||
* _MachineLearning_. Updated __RandomForestFunctionFinderPlugin__ with improved model training performance, the ability to apply a model to a program selection, and the addition of disassembly to the similar-starts table. (GP-4400)
|
||||
* _PDB_. Modified handling of PDB thunks so that for when Ghidra does not consider the function to be a thunk, which would normally cause the thunk to get the same signature as the thunked function, the Demangler is enabled to set the proper function signature and name. This affects C++-related functions, for example, such as vtordisps and adjustors. (GP-5713)
|
||||
* _Processors_. Added initial implementation of ARM Neon `VLD`/`VSTn` instructions. (GP-5853)
|
||||
* _Processors_. Added support for MIPS16e2 instructions. (GP-5902, Issue #8406)
|
||||
* _Processors_. Refactored RISCV context and moved CSR registers into a CSR memory space to support custom instructions and RISCV variants. Also added sample RISCV variant Andestar. (GP-5975)
|
||||
* _Processors_. Corrected AArch64 `fmadd` operand semantics ordering. (GP-6121, Issue #8454, #8625)
|
||||
* _ProgramDB_. Improved performance of Symbol Table and its storage of `ExternalLocation` data. (GP-5498)
|
||||
* _Scripting_. Condensed the script categories into a better-organized subset of categories. (GP-3952)
|
||||
* _Scripting_. Python scripts that do not declare a `@runtime` metadata comment now default to PyGhidra instead of Jython. Jython scripts will need to include the "`# @runtime Jython`" script header in order to continue running within the Jython environment. (GP-5415, Issue #7856)
|
||||
* _Scripting_. Released PyGhidra 3.0.0. (GP-5637, Issue #6914, #6915)
|
||||
* _Scripting_. Made a few speed improvements to the RecoverClassesFromRTTIScript. (GP-5831, Issue #8199)
|
||||
* _Scripting_. Added new script methods to allow script writers to color the console output: `print(String, Color)` and `println(String, Color)`. (GP-5970, Issue #2849)
|
||||
* _Scripting_. Fixed an issue in the `RecoverClassesFromRTTIScript` where pure virtual functions were not handled correctly in GCC programs. (GP-5993)
|
||||
* _Sleigh_. Temporary (`unique`) variables can be accessed within a Sleigh language piece-wise using a direct varnode offset and length rather than masking which had inherent size limitations. (GP-5581)
|
||||
|
||||
### Bugs
|
||||
* _Analysis_. Fixed an issue where __Apply Data Archives__ analyzer replaced functions that had the same `SourceType` priority. (GP-5661)
|
||||
* _Analysis_. Fixed the Non-Returning Functions analyzer to consider external functions. Also added check for the function called right before an `INT3` as possibly being non-returning. (GP-5763)
|
||||
* _Analysis_. Fixed handling of `segment()` op in stack analysis when segment op is unknown stack segment SS. (GP-6078, Issue #8584)
|
||||
* _Assembler_. Added help anchor for Assembler's exhaust-or-zero-fill toggle. (GP-4478)
|
||||
* _Assembler_. Removed debug messaging from the assembler, speeding it up significantly. (GP-5800, Issue #8308, #8309)
|
||||
* _Calling Conventions_. Corrected handling of long integer parameters and structured data-type parameters for the RISCV 32-bit and 64-bit default calling conventions. (GP-5211)
|
||||
* _Debugger_. Fixed issues related to register editing with lldb. (GP-6084, Issue #8598)
|
||||
* _Debugger_. Fixed issue where register panel used stale register objects when switching between similar assembly languages. (GP-6105)
|
||||
* _Decompiler_. Fixed _"Overlapping input varnodes"_ exceptions in the Decompiler caused by the use of the XMM0 register as a function input. (GP-5863)
|
||||
* _Decompiler_. Allowed the __Rename Global__ action in the Decompiler to create a primary symbol if it didn't exist. (GP-5866, Issue #4864, #8121)
|
||||
* _Decompiler_. Eliminated the unsound `SBORROW(0,x) => 0` simplification rule from Decompiler analysis. (GP-5934, Issue #8396, #8400)
|
||||
* _Decompiler_. Fixed a bug that prevented overlapping functions from being correctly decompiled. (GP-5983)
|
||||
* _Decompiler_. Fixed a bug in the Decompiler's __Force Union__ action that caused _"Could not recover p-code op"_ exceptions. (GP-5989, Issue #7466)
|
||||
* _DWARF_. Improved DWARF location expression evaluation, which has bearing on a number of areas including the placement of local variables. (GP-4069, Issue #2322, #5311, #5982, #6974)
|
||||
* _DWARF_. Fixed issue with importing 64-bit DWARF when subsections of the DWARF line info were marked as 32-bit. (GP-5931)
|
||||
* _FID_. Added a temporary fix to identify the `security_check_cookie()` function in VS2022 binaries. If the function is not identified, the return type is incorrectly recovered by the Decompiler. (GP-5998, Issue #2743)
|
||||
* _Function_. Fixed thunk detection and thunk address calculation for thunks with an internal call/branch to the next instruction in order to load the current PC into an LR register. (GP-6072)
|
||||
* _GUI_. Updated the Plate Comment field to render annotations' display text instead of raw annotation text. (GP-3756)
|
||||
* _GUI_. Fixed potential deadlock in Ghidra tables that use the __Code Unit__ table column. (GP-5724, Issue #8208)
|
||||
* _GUI_. Fixed bug that caused an incorrect tab to be selected when closing docked component provider tabs via the __x__ button. (GP-5821, Issue #8303)
|
||||
* _GUI_. Fixed the Decompiler's __Edit Data Type__ action to correctly scroll the structure field being edited. (GP-6045, Issue #8522)
|
||||
* _Languages_. Fixed issue with importing 32-bit RUST binaries for x86 Windows- and Unix-based systems. (GP-4711, Issue #6042)
|
||||
* _Navigation_. Changed __Next Function__ / __Previous Function__ actions to skip functions that are not in memory. This prevents the actions from becoming _stuck_ until the user manually moves to an new address past the non-memory function. (GP-5712)
|
||||
* _PDB_. Fixed an issue where the function arguments list record was a NOTYPE, which caused the analyzer to terminate. (GP-6010)
|
||||
* _Processors_. Fixed ARM `vmvn` instruction semantics. (GP-4650, Issue #6544)
|
||||
* _Processors_. Fixed SuperH4 `FSCA` instruction destination operand and FPU-register ABI-ordering for little-endian. (GP-5759, Issue #8192)
|
||||
* _Processors_. Corrected 80251 `ANL` instruction variant disassembling as `ADD`. (GP-5903, Issue #8393)
|
||||
* _Processors_. Fixed 80251 `ANL Areg,Data` source-mode disassembly bug. (GP-5904, Issue #8394)
|
||||
* _Processors_. Added support for the eBPF `CALLX` instruction. (GP-5909, Issue #7972)
|
||||
* _Processors_. Corrected PowerPC branch conditional instruction semantics. (GP-6049, Issue #8424)
|
||||
* _Processors_. Fixed disassembly of various Xtensa big-endian instructions. (GP-6050, Issue #8537, #8544)
|
||||
* _Processors_. Fixed pcode for SuperH `bclr` instruction. (GP-6065, Issue #8579)
|
||||
* _Processors_. Fixed several issues including ARM `cpy` instruction setting the PC, incorrect function start pattern, and spurious references when saving the PC at function entry. (GP-6079)
|
||||
* _Project_. Corrected issues related to failed attempts at removal of multiple folders from project tree via a selection. (GP-5907)
|
||||
* _Project_. Improved project tree change listener to handle link status updates when such links reference non-visited regions of the project tree. (GP-5908)
|
||||
* _Scripting_. Fixed the `GhidraScript.writer` member variable to properly get used in the various `GhidraScript.print*()` methods. (GP-5737)
|
||||
* _Scripting_. Updated vxWorks symbol-table-finding script to better filter out runs of pointers when trying to locate the table. Also, deleted old scripts and fixed demangling and labeling issues. (GP-5969, Issue #8024)
|
||||
* _Scripting_. Jython scripts invoked via `runScript()` now have their local variables properly reset to a fresh state. (GP-5981)
|
||||
* _Scripting_. Fixed a bug that prevented OSGi scripting bundles from running with newer versions of Java. (GP-6014)
|
||||
* _Scripting_. Fixed a bug that prevented PyGhidra from redirecting output from `print()` and `sys.stdout.write()` to the Ghidra GUI scripting console. (GP-6021, Issue #8524)
|
||||
* _Scripting_. Fixed a bug in the the PyGhidra headless analyzer that resulted in the wrong exception being thrown when a script tries to import a module that isn't found. (GP-6132, Issue #8610)
|
||||
* _Symbol Tree_. Updated the Symbol Tree to respond to external program path changes. (GP-5793)
|
||||
* _Symbol Tree_. Fixed a bug where opening a folder in the Symbol Tree caused navigation to occur in the Listing. (GP-5914)
|
||||
|
||||
### Notable API Changes
|
||||
* _API_. (GP-5600) The `AutoImporter` class has been deprecated. Use the new `ProgramLoader.Builder` class instead. The returned `Loaded` class should now be managed with a _try-with-resources_ pattern. If a `DomainObject` is extracted from a `Loaded` object, it must be released independly of closing the `Loaded` object.
|
||||
* _Assembler_. (GP-5800) Deleted `DbgTimer`.
|
||||
* _Data Types_. (GP-5694) Deprecated `DataTypeQueryService.getDataType()`. This method has been replaced by `promptForDataType()`.
|
||||
* _Debugger:Agents_. (GP-5700) Launcher scripts `GHIDRA_HOME` now points to `<ghidra-install>/Ghidra`. `MODULE_HOME` now points to containing module root. Can request `MODULE_Xxx_HOME` pointing to module `Xxx` root by placing `@depends Xxx` in header.
|
||||
* _Debugger:Trace_. (GP-5194) Objects mode is now the normal mode for Trace databases. The legacy mode has been removed. As a result, the root object must be created early, since other managers require it. Merged methods from `TraceObjectX` interfaces into `TraceX` (only those derived from `TraceObjectInterface`). To avoid confusion, renamed `TraceMethod` (in Java TraceRmi Client) to `TraceRmiMethod`. Renamed `TraceBreakpoint` to `TraceBreakpointLocation`. Added `TraceBreakpointSpecification`, `TraceBreakpointCommon`. Deleted `TraceAddressSpace` in favor of `AddressSpace`. Added `DebuggerCoordinates.isRegisterSpace()`. Space-based managers, e.g., `TraceMemoryManager`, no longer have special tables for register spaces. They all use the overlay-named-after-register-container convention. Added `TraceBaseCodeUnitsView.get(platform,snap,register,forward)`. Memory region management is moved from `TraceMemoryOperations` to `TraceMemoryManager`. Removed experimental and incomplete `TraceProgramView.getViewRegisters()` method and related. Removed `thread` parameter from `TraceLabelSymbolView.add/create`. Added variant of `TraceLabelSymbolView.add/create` that takes `platform(optional),thread,register` (and similar with getters in `TraceSymbolWithLocationView`). Added methods to `DefaultSchemaContext` and related builders to more easily build a context derived from an existing one. Added `TraceObjectManager.requireRootSchema()`. Added `TraceRegisterUtils.getRegisterContainer`, `getRegisterAddressSpace`, `getThread`, and `getFrameLevel`.
|
||||
* _Debugger:Trace_. (GP-5926) Added `TraceReference.getToRange`. Added `TraceReferenceOperations.addMemoryReference(...AddressRange toRange...)`. Added `TraceReferenceOperations.getReference(...AddressRange toRange...)`. Added `TraceReferenceOperations.getReferencesToRange(...order)`.
|
||||
* _Debugger:Watches_. (GP-5795) Added `WatchRow.get/setComment`.
|
||||
* _Emulator_. (GP-5727) Added `SymZ3PcodeEmulator` and related.
|
||||
* _Emulator_. (GP-5864) Added `EmulatorUtilities`.
|
||||
* _Emulator_. (GP-5879) <B>Primary changes</B>: Added `PcodeEmulationCallbacks`, `PcodeStateCallbacks`, `ComposedPcodeEmulationCallbacks`. Added `Writer` and `TraceWriter`. Added `PieceHandler` and implementations for `byte[]`, `TaintVec`, and `SymValueZ3`. Added `TraceEmulationIntegration`. Added `DebuggerEmulationIntegration`. Deleted `TracePcodeMachine`, `DebuggerPcodeMachine` and all implementations. `PcodeMachine` is used with a `Writer`/callbacks instead. Deleted `TracePcodeExecutorStatePiece` and all implementations. `PcodeExecutorStatePiece` is used with callbacks instead. Deleted `AbstractDebuggerPcodeEmulatorFactory`. `EmulatorFactory` is used instead. Deleted `TraceEmulatorPartsFactory`, `DebuggerEmulatorPartsFactory` and all implementations. `EmulatorPartsFactory` is used instead. Changed constructor of `AbstractPcodeMachine` to require callbacks. Changed constructor of `AbstractLongOffsetPcodeExecutorStatePiece` and derivatives to require callbacks. Changed signature of `PcodeExecutorStatePiece.fork` to require callbacks. Changed signature of `EmulatorFactory.create` to accept a `Writer`. Changed signatures of several methods in `EmulatorPartsFactory` to accept callbacks.
|
||||
<BR><B>Secondary changes</B>: Added `PcodeTraceAccess.deriveForWrite(snap)`. Added `PcodeTracePropertyAccess.getEntry/put`. The `put` method is also modified to clear if `value` is null. Added `PcodeArithmetic.getDomain`. Added `PcodeExecutorStatePiece.streamPieces`. Added `AbstractPcodeExecutorState`. Added `PcodeExecutorStatePiece.get/setVarInternal`. Added `PcodeExecutorStatePiece.getNextEntryInternal`. Renamed `DebuggerPcodeEmulatorFactory` to `EmulatorFactory`. Changed signature of `PcodeDebuggerMemoryAccess.readFromStaticImages`. Several changes to `AbstractLongOffsetPcodeExecutorStatePiece` and its derivatives. See stock implementations for updates. In particular, removed all notion of "backing" including the type parameter `B`.
|
||||
* _Emulator:JIT_. (GP-5214) Added `PcodeUseropDefinition.getOutputType()`. `AnnotatedPcodeUseropLibrary` allows `@PcodUserop` methods to take `int[]` parameters, including for the `@OpOutput` parameter.
|
||||
* _FileSystems_. (GP-5825) Removed GFilesystem `LocalFileSystemSub` class.
|
||||
* _FileSystems_. (GP-5842) Removed `throws IOException` from `ByteProvider.length()` method.
|
||||
* _Graphing_. (GP-3648) The `CodeComparisonPanel` extension point has been renamed to `CodeComparisonViewer`. Any clients subclassing `CodeComparisonPanel` will need to rename their parent class reference and also rename their extension to end with `CodeComparisonView` instead of `CodeComparisonPanel`.
|
||||
* _GUI_. (GP-5769) Removed the `GhidraComboBox.setEnterKeyForwarding(boolean)` method. Any clients calling this method with a value of `true` may simply delete the call to maintain the previous behavior, Any clients calling this with a value of `false` will need to change how the combo box responds to `Enter` key presses in a way that preserves effect of not passing the `Enter` key press up to the parent container.
|
||||
* _GUI_. (GP-5963) Added convenience methods to `TableColumnDescriptor` to create simple columns using only a name, column type, and a function to map from the row object to the column object.
|
||||
* _Importer_. (GP-3947) Added `XmlElement.isStart(String string)`, which checks that the element is a starting element and also that its name matches the passed string.
|
||||
* _Importer_. (GP-5343) The `Loader.load()` and `Loader.loadInto()` interface definitions have been simplified to take in a new `ImporterSettings` record. The `Loader.getDefaultOptions()` definition has also been changed to accept a new `mirrorFsLayout` parameter. These changes trickle down the loader class hierarchy, so all 3rd party loaders will need to be updated to work with Ghidra 12.0.
|
||||
* _ProgramDB_. (GP-5498) Revised `ExternalManager` interface including removal of previously deprecated methods which have new method names. The `getExternalLocations` now returns a `Set` of locations instead of a `List`.
|
||||
* _ProgramDB_. (GP-5990) Eliminated the various forms of the `Listing.getCompositeData` method and associated map table from the Program database. These methods were never used within Ghidra and were found to be the source of unnecessary overhead.For infrequent needs, a defined-data iterator can be used to identify locations where composites exist. In addition, the following related Program and Trace events were eliminated: `ProgramEvent.COMPOSITE_ADDED`, `ProgramEvent.COMPOSITE_REMOVED`
|
||||
`ChangeManager.DOCR_COMPOSITE_ADDED`,
|
||||
`ChangeManager.DOCR_COMPOSITE_REMOVED`,`ProgramEvent.COMPOSITE_ADDED`, `ProgramEvent.COMPOSITE_ADDED`.
|
||||
* _Project_. (GP-3551) Made significant changes to `ProjectDataUtils` in support of folder and file links. This utility's static methods should be used in place of directly instantiating `DomainFileIterator` or `DomainFolderIterator`. Significant changes have been made to `ProjectData` storage and interface to accommodate expanded link-file support. The `getFile` and `getFolder` methods have been overloaded with an optional filter to control treatment of such link-files where the pre-existing method forms will ignore external links. Extensive changes have also been made to the Project Data Tree component which now has the ability to render and follow folder and file links. Since a folder link exists as a `DomainFile`, and all link-files rely on unique content-types, additional logic is needed to follow such links. `LinkFileInfo` can be obtained from a `DomainFile` although the use of `ProjectData` and `ProjectDataUtils` will simplify the use of link-files.
|
||||
* _Scripting_. (GP-5737) Added a `GhidraScript.set()` method that takes a new `ScriptControls` object which provides more control over how scripts write to stdout and stderr.
|
||||
* _Scripting_. (GP-5961) Deprecated `pyghidra.open_program` and `pyghidra.run_script`.
|
||||
|
||||
# Ghidra 11.4.3 Change History (December 2025)
|
||||
|
||||
### Improvements
|
||||
|
||||
@@ -5,7 +5,7 @@ to analyze compiled code on a variety of platforms including Windows, MacOS, and
|
||||
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
|
||||
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.
|
||||
|
||||
@@ -15,17 +15,17 @@ applied Ghidra SRE capabilities to a variety of problems that involve analyzing
|
||||
generating deep insights for NSA analysts who seek a better understanding of potential
|
||||
vulnerabilities in networks and systems.
|
||||
|
||||
# What's New in Ghidra 11.4
|
||||
# What's New in Ghidra 12.0
|
||||
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.4 is fully backward compatible with project data from previous releases. However, programs
|
||||
and data type archives which are created or modified in 11.4 will not be usable by an earlier Ghidra
|
||||
Ghidra 12.0 is fully backward compatible with project data from previous releases. However, programs
|
||||
and data type archives which are created or modified in 12.0 will not be usable by an earlier Ghidra
|
||||
version.
|
||||
|
||||
**IMPORTANT:** Ghidra 11.4 requires at minimum JDK 21 to run.
|
||||
**IMPORTANT:** Ghidra 12.0 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.13 supported) installed on your system.
|
||||
@@ -35,18 +35,23 @@ for `CVE-2024-31083` in X.org software in April 2024 introduced a regression, wh
|
||||
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
|
||||
**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 *Getting Started* document 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.
|
||||
See the *Getting Started* document 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:** Ghidra Server: The Ghidra 12.0 server is compatible with Ghidra 11.3.2 and later Ghidra
|
||||
clients, although the presence of any newer link-files within a repository may not be handled properly
|
||||
by client versions prior to 12.0 which lack support for the new storage format. Ghidra 12.0 clients
|
||||
that introduce new link-files into a project will not be able to add such files into version
|
||||
control if connected to older Ghidra Server versions.
|
||||
|
||||
**NOTE:** Ghidra Server: 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 unless they need to work with link-files within a shared repository.
|
||||
|
||||
**NOTE:** 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
|
||||
@@ -59,79 +64,110 @@ process that will provide better results than prior Ghidra versions. You might
|
||||
fresh import of any program you will continue to reverse engineer to see if the latest Ghidra
|
||||
provides better results.
|
||||
|
||||
## Project Data Link Files
|
||||
Support for link-files within a Ghidra Project has been significantly expanded with this release and
|
||||
with it a new file storage type has been introduced which can create some incompatibilities if
|
||||
projects and repositories containing such files are used by older version of Ghidra or the Ghidra
|
||||
Server.
|
||||
|
||||
## Search
|
||||
Previously, only external folder and file links were supported through the use of a Ghidra URL. With
|
||||
12.0 the ability to establish internal folder and file links has been introduced. A new storage
|
||||
format was adopted for link-files which avoids the use of a database and relies only on a
|
||||
light-weight property file only. Internal project links also allow for either absolute or relative
|
||||
links. Due to Ghidra allowing a folder and file to have the same pathname, some ambiguities can
|
||||
result for Ghidra URL usage. It is highly recommended that the use of conflicting folder and file
|
||||
pathnames be avoided.
|
||||
|
||||
A new "Search and Replace" feature allows searching for string patterns in a wide variety
|
||||
of Ghidra elements and replacing that text with a different text sequence. Using this feature, many different
|
||||
Ghidra elements can be renamed all at once including labels, functions, name-spaces, parameters, data-types,
|
||||
field names, and enum values. This feature also supports regular expressions (including capture groups).
|
||||
After initiating a search and replace, a results table is displayed with a list of items that match the
|
||||
search. From this table, the replace actions can be applied in bulk or individually, one item at a time
|
||||
as they are reviewed.
|
||||
The use of internally linked folders and files allows batch import processing to more accurately
|
||||
reflect the native file-system and its use of symbolic links which allow for the same content to
|
||||
be referenced by multiple paths. Allowing this within a Ghidra project can avoid the potential for
|
||||
importing content multiple times with the different paths and simply import once with additional
|
||||
link-files which reference it. How best to leverage links very much depends on the end-user's
|
||||
needs and project file management preferences. Special care must be taken when defining or
|
||||
traversing link-files to avoid external and circular references.
|
||||
|
||||
## Taint Engine Support
|
||||
Additional Ghidra API methods have been provided or refined on the following classes to leverage
|
||||
link-files: `DomainFolder`, `DomainFile`, `LinkFile`, `LinkHandler`, `DomainFileFilter`,
|
||||
`DomainFileIterator`, etc.
|
||||
|
||||
Extended support for using taint engines, particularly CTADL (https://github.com/sandialabs/ctadl)
|
||||
and AngryGhidra (https://github.com/Nalen98/AngryGhidra), from the decompiler. Allows users to mark
|
||||
pcode varnodes as sources and sinks, displaying paths from sources to sinks as both address selections
|
||||
in the disassembly and token selections in the decompiler.
|
||||
## Importer Filesystem Mirroring
|
||||
An option has been added to mirror the local filesystem when importing programs and their libraries.
|
||||
Programs and libraries that exist on the local filesystem as symbolic links will have both their
|
||||
corresponding link file and resolved program file mirrored in the project. Filesystem mirroring
|
||||
can also be used in headless mode with the new `-mirror` command line option.
|
||||
|
||||
## Dockerized Ghidra
|
||||
## PyGhidra
|
||||
PyGhidra 3.0.0 (compatible with Ghidra 12.0 and later) introduces many new Python-specific API
|
||||
methods with the goal of making the most common Ghidra tasks quick and easy, such as opening a
|
||||
project, getting a program, and running a GhidraScript. Legacy API functions such as
|
||||
`pyghidra.open_program()` and `pyghidra_run_script()` have been deprecated in favor of the new
|
||||
methods, which are outlined at https://pypi.org/project/pyghidra.
|
||||
|
||||
A new capability to build a docker image that demonstrates Ghidra's various entrypoint executions for `headless`,
|
||||
`ghidra-server`, `bsim-server`, `bsim`, `pyghidra`, and `gui` within the docker container has been included. The Docker
|
||||
image can be used as is, or can be tailored to your workflow needs. Configuration such as the base
|
||||
image (linux distro), additional packages, and more is possible using Docker.
|
||||
The default Python scripting engine has been changed in Ghidra 12.0 from Jython to PyGhidra.
|
||||
Existing Jython scripts will need to include the `# @runtime Jython` script header in order to
|
||||
continue running within the Jython environment.
|
||||
|
||||
See the `docker/README.md` for information about building a docker image for Ghidra and running within the Ghidra container.
|
||||
## Z3 Concolic Emulation and Symbolic Summary
|
||||
We've added an experimental Z3-based symbolic emulator, which runs as an "auxiliary" domain to the
|
||||
concrete emulator, effectively constructing what is commonly called a "concolic" emulator. The
|
||||
symbolic emulator creates Z3 expressions and branching constraints, but it only follows the path
|
||||
determined by concrete emulation. This is most easily accessed by installing the "SymbolicSummaryZ3"
|
||||
extension (**File -> Install Extensions**) and then enabling the `Z3SummaryPlugin` in the
|
||||
Debugger or Emulator tool, which includes a GUI for viewing and sorting through the results. The Z3
|
||||
emulator requires z3-4.13.0, available from https://github.com/Z3Prover/z3. Other versions may work,
|
||||
but our current test configuration uses 4.13.0. Depending on the release and your platform, the
|
||||
required libraries may be missing or incompatible. If this is the case, you will need to download
|
||||
Z3, or build it from source with Java bindings, and install the libraries into
|
||||
`Ghidra/Extensions/SymbolicSummaryZ3/os/<platform>/`.
|
||||
|
||||
## Emulation API
|
||||
The `PcodeEmulator` and related API has undergone substantial changes in preparation for integrating
|
||||
our JIT-accelerated emulator into the GUI. Please see the **Notable API Changes** section of our
|
||||
[Change History](ChangeHistory.md). The goal is to facilitate integration by composition; whereas,
|
||||
it had previously required inheritance, which is now considered poor design. Essentially, we've
|
||||
introduced a set of callbacks that integrators can use to detect when certain things have happened
|
||||
in emulation, as well as offer some control of machine-state behavior; e.g., to facilitate lazily
|
||||
loading from a snapshot.
|
||||
|
||||
## Binary Formats
|
||||
Extensions that currently integrate via inheritance can continue to do so, but will still need to
|
||||
apply some minimal changes to satisfy interface and constructor changes. The developers of such
|
||||
extensions ought to consider porting their integrations to the compositional/callback-based
|
||||
mechanism. A careful assessment may be required depending on the nature of the extension. Extensions
|
||||
that merely integrate with emulation should consider the compositional/callback-based mechanism.
|
||||
Extensions that incorporate new domains (e.g. Z3) or novel behaviors (e.g. JIT) should continue
|
||||
using inheritance.
|
||||
|
||||
+ New loaders for the a.out and OMF-51 binary file formats.
|
||||
+ Support for Mach-O "re-exports".
|
||||
+ New ability to load Mach-O binaries directly from a Universal Binary without needing to open the File System Browser.
|
||||
+ DWARF will now load external debug files during analysis as is done for PDB files.
|
||||
## Data Graph
|
||||
Added a new data graph showing data relationships defined by references from one in memory defined data item
|
||||
to another. The data graph can be displayed by clicking on a data item in the listing and
|
||||
invoking the data graph action (**ctrl-g** or from the popup menu **data -> display data graph**). This action
|
||||
will create a new data graph displaying the selected data item and its contents. From
|
||||
that node, the graph can be expanded by following from or to references to that data item.
|
||||
|
||||
## Debugger
|
||||
## Hide Function Variables
|
||||
Added the ability to toggle the display of function variables (parameters and locals) within
|
||||
the Code Browser Listing just below the function signature. The Variables display can be turned
|
||||
on/off globally via the popup menu toggle action (**Function -> Show/Hide All Variables**) or for
|
||||
individual functions via an adjacent expand/collapse(+/-) icon.
|
||||
|
||||
There have been numerous improvements, extensions for new targets, better launching and configuration, and bug fixes to the debugger.
|
||||
|
||||
## Analysis Speed
|
||||
|
||||
Constant and Stack analysis time has been greatly decreased through algorithm improvements and better threading. There has been additional
|
||||
work to loosen locking of the program database where possible. By locking only when necessary, multiple threads can better analyze the program
|
||||
and interaction with the GUI during analysis should be more responsive.
|
||||
|
||||
## Golang
|
||||
|
||||
Golang binary analysis analysis has been improved.
|
||||
+ Analysis has been improved to model closures, interface methods, and generic functions more accurately.
|
||||
+ Function signatures for core golang library functions are automatically applied.
|
||||
+ Decompilation results are improved by filtering some verbose golang garbage collection function logic.
|
||||
+ Addressed finding the Golang bootstrap information in stripped PE binaries.
|
||||
|
||||
## BSim
|
||||
|
||||
PostgreSQL for BSim has been updated to version 15.13 and the JDBC driver to 42.7.6. This resolves issues with building PostgreSQL
|
||||
server on newer releases of Linux and compiler toolchains which compile with -std=c23 option by default. In addition,
|
||||
building of PostgreSQL for linux_arm_64 and mac_arm_64 based platforms is supported.
|
||||
|
||||
+ BSim is now installed in the default Codebrowser tool.
|
||||
+ Function names now update in BSim search results overview if the name is changed elsewhere in Ghidra.
|
||||
## GhidraGo URL
|
||||
Did you know Ghidra supports embedding URL links in web pages? After setting up GhidraGo in
|
||||
your preferred web browser and adding the GhidraGo plugin into Ghidra, clicking on a Ghidra URL link
|
||||
will start Ghidra, open the program either locally or in a multi-user project, and then navigate
|
||||
to the specified address in the specified program. A Ghidra remote URL looks something like
|
||||
(**ghidra://myrepo.org:13100/perf/9305e1d039/busybox_aarch64_fc0bdbc**). You can provide
|
||||
just the project path or include a path all the way to an address/symbol in a program within the
|
||||
project. See the Ghidra Help under GhidraGo for setup and more information.
|
||||
|
||||
## Processors
|
||||
|
||||
+ Enhanced support for the x86 AVX-512 processor extension with additional instruction support - including the BF16, FP16 and VNNI extensions.
|
||||
+ Implemented many AARCH64 Neon instruction semantics to improve decompilation.
|
||||
+ Upgraded pcodetest framework scripts to python3 and improved command-line options.
|
||||
|
||||
## Other Improvements
|
||||
+ Many calling conventions for various processors/compilers have been improved using the more flexible decompiler rules
|
||||
when the data types for parameters and return values are known.
|
||||
+ Upgraded many 3rd party dependencies to address potential bugs and CVE's, including jars for Bouncy Castle,
|
||||
Apache Commons Compress, Apache Commons Lang3, Apache Commons IO, protobuf, and JUnit.
|
||||
The NDS32, and RISCV variant AndeStar v5 processors have been added. In addition the RISCV processor
|
||||
has been re-factored to better handle RISCV custom extensions and the csreg register definitions have been
|
||||
moved into a separate memory space. The benefit of having an actual memory space for special function
|
||||
registers is they can be seen, named, references created to them, data types applied at the location,
|
||||
as well as default values supplied for a given binary sample. We plan to do the same for other processors
|
||||
such as the PowerPC. There have also been numerous extensions and fixes added to the
|
||||
AArch64, 8051, LoongArch, SuperH, Arm, Xtensa, x86, 68k, and many other processors. Thanks for all
|
||||
the community contributions!
|
||||
|
||||
## Additional Bug Fixes and Enhancements
|
||||
Numerous other new features, improvements, and bug fixes are fully listed in the
|
||||
|
||||
@@ -28,63 +28,56 @@ dependencies {
|
||||
api project(':Debugger-rmi-trace')
|
||||
}
|
||||
|
||||
ext.tlb = file("build/os/win_x86_64/dbgmodel.tlb")
|
||||
def tlb = file("build/os/win_x86_64/dbgmodel.tlb")
|
||||
def depsFile = file("${DEPS_DIR}/Debugger-agent-dbgeng/dbgmodel.tlb")
|
||||
def binRepoFile = file("${BIN_REPO}/${getGhidraRelativePath(project)}/os/win_x86_64/dbgmodel.tlb")
|
||||
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
||||
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 depsFile = file("${DEPS_DIR}/Debugger-agent-dbgeng/dbgmodel.tlb")
|
||||
def binRepoFile = file("${BIN_REPO}/${getGhidraRelativePath(project)}/os/win_x86_64/dbgmodel.tlb")
|
||||
tasks.assemblePyPackage {
|
||||
def prebuiltTlb = depsFile.exists() ? depsFile : (binRepoFile.exists() ? binRepoFile : null)
|
||||
assert prebuiltTlb != null : "Failed to locate prebuilt TLB file"
|
||||
|
||||
if (prebuiltTlb) {
|
||||
tasks.assemblePyPackage {
|
||||
from(prebuiltTlb) {
|
||||
into("src/ghidradbg/dbgmodel/tlb")
|
||||
}
|
||||
from(prebuiltTlb) {
|
||||
into("src/ghidradbg/dbgmodel/tlb")
|
||||
}
|
||||
}
|
||||
|
||||
task buildTlb(type: Exec) {
|
||||
|
||||
def tmpBatch = file("build/buildTlb.bat")
|
||||
def idl = file("src/main/py/src/ghidradbg/dbgmodel/DbgModel.idl")
|
||||
|
||||
inputs.file(idl)
|
||||
outputs.file(tlb)
|
||||
|
||||
doFirst {
|
||||
assert isCurrentX86_64() && isCurrentWindows() : "Can only build TLB on Windows x86"
|
||||
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
|
||||
}
|
||||
}
|
||||
else {
|
||||
println "****WARNING:**** dbgmodel.tlb omitted from ghidradbg python package"
|
||||
|
||||
doLast {
|
||||
assert file(tlb).exists() : "Failed to build dbgmodel.tlb"
|
||||
}
|
||||
|
||||
commandLine "cmd", "/c", tmpBatch
|
||||
}
|
||||
|
||||
task prebuildTlb(type: Copy) {
|
||||
|
||||
dependsOn buildTlb
|
||||
|
||||
from tlb
|
||||
into binRepoFile.parentFile
|
||||
|
||||
doFirst {
|
||||
assert file(BIN_REPO).exists() : "Bin repo doesn't exist"
|
||||
file(binRepoFile).parentFile.mkdirs()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
::@menu-group dbgeng
|
||||
::@icon icon.debugger
|
||||
::@help dbgeng#win_kernel
|
||||
::@depends Debugger-rmi-trace
|
||||
::@enum Connection:str Remote Local EXDI
|
||||
::@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
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
::@menu-group dbgeng
|
||||
::@icon icon.debugger
|
||||
::@help dbgeng#attach
|
||||
::@depends Debugger-rmi-trace
|
||||
::@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"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
::@menu-group dbgeng
|
||||
::@icon icon.debugger
|
||||
::@help dbgeng#ext
|
||||
::@depends Debugger-rmi-trace
|
||||
::@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"
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
::@menu-group dbgeng
|
||||
::@icon icon.debugger
|
||||
::@help dbgeng#ttd
|
||||
::@depends Debugger-rmi-trace
|
||||
::@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_TRACE:file="" "Trace (.run)" "The target trace image"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
::@menu-group dbgeng
|
||||
::@icon icon.debugger
|
||||
::@help dbgeng#local
|
||||
::@depends Debugger-rmi-trace
|
||||
::@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"
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
::@menu-group dbgeng
|
||||
::@icon icon.debugger
|
||||
::@help dbgeng#remote
|
||||
::@depends Debugger-rmi-trace
|
||||
::@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_CONNECT_STRING:str="" "Connection" "Connection-string arguments (a la .server)"
|
||||
::@env WINDBG_DIR:dir="" "Path to dbgeng.dll directory" "Path containing dbgeng and associated DLLS (if not Windows Kits)."
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
::@menu-group dbgeng
|
||||
::@icon icon.debugger
|
||||
::@help dbgeng#svrcx
|
||||
::@depends Debugger-rmi-trace
|
||||
::@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"
|
||||
|
||||
@@ -19,10 +19,11 @@ import sys
|
||||
|
||||
|
||||
def append_paths():
|
||||
sys.path.append("../../../Debugger-rmi-trace/data/support")
|
||||
sys.path.append(
|
||||
f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support")
|
||||
from gmodutils import ghidra_module_pypath
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng"))
|
||||
sys.path.append(ghidra_module_pypath("Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath())
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -19,10 +19,11 @@ import sys
|
||||
|
||||
|
||||
def append_paths():
|
||||
sys.path.append("../../../Debugger-rmi-trace/data/support")
|
||||
sys.path.append(
|
||||
f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support")
|
||||
from gmodutils import ghidra_module_pypath
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng"))
|
||||
sys.path.append(ghidra_module_pypath("Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath())
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -19,10 +19,11 @@ import sys
|
||||
|
||||
|
||||
def append_paths():
|
||||
sys.path.append("../../../Debugger-rmi-trace/data/support")
|
||||
sys.path.append(
|
||||
f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support")
|
||||
from gmodutils import ghidra_module_pypath
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng"))
|
||||
sys.path.append(ghidra_module_pypath("Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath())
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -19,10 +19,11 @@ import sys
|
||||
|
||||
|
||||
def append_paths():
|
||||
sys.path.append("../../../Debugger-rmi-trace/data/support")
|
||||
sys.path.append(
|
||||
f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support")
|
||||
from gmodutils import ghidra_module_pypath
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng"))
|
||||
sys.path.append(ghidra_module_pypath("Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath())
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -19,10 +19,11 @@ import sys
|
||||
|
||||
|
||||
def append_paths():
|
||||
sys.path.append("../../../Debugger-rmi-trace/data/support")
|
||||
sys.path.append(
|
||||
f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support")
|
||||
from gmodutils import ghidra_module_pypath
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng"))
|
||||
sys.path.append(ghidra_module_pypath("Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath())
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -19,10 +19,11 @@ import sys
|
||||
|
||||
|
||||
def append_paths():
|
||||
sys.path.append("../../../Debugger-rmi-trace/data/support")
|
||||
sys.path.append(
|
||||
f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support")
|
||||
from gmodutils import ghidra_module_pypath
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng"))
|
||||
sys.path.append(ghidra_module_pypath("Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath())
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -21,10 +21,11 @@ import sys
|
||||
|
||||
|
||||
def append_paths():
|
||||
sys.path.append("../../../Debugger-rmi-trace/data/support")
|
||||
sys.path.append(
|
||||
f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support")
|
||||
from gmodutils import ghidra_module_pypath
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng"))
|
||||
sys.path.append(ghidra_module_pypath("Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath())
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -19,10 +19,11 @@ import sys
|
||||
|
||||
|
||||
def append_paths():
|
||||
sys.path.append("../../../Debugger-rmi-trace/data/support")
|
||||
sys.path.append(
|
||||
f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support")
|
||||
from gmodutils import ghidra_module_pypath
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath("Debug/Debugger-agent-dbgeng"))
|
||||
sys.path.append(ghidra_module_pypath("Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath())
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -260,18 +260,38 @@ exdi:CLSID={29f9906e-9dbe-4d4b-b0fb-6acf7fb6d014},Kd=Guess,DataBreaks=Exdi
|
||||
|
||||
<H2><A name="ttd"></A>TTD (Time-Travel Debugging)</H2>
|
||||
|
||||
<P>This is a nascent extension to our launcher for the Windows Debugger. The launcher itself
|
||||
functions, but lacks full integration. In particular, Ghidra's concept of time is not mapped
|
||||
directly to the TTD concept of time. TTD uses a major/minor scheme for ordering events, where
|
||||
the major index changes when TTD must record a change in state. Events, including thread
|
||||
creation/termination, module loads/unloads, syscalls, and other asynchronous changes, merit new
|
||||
major indices. When you step forward or backward in a trace, the dbgeng API will increment and
|
||||
decrement correspondingly. Ghidra, on the other hand, will only increment.</P>
|
||||
<P>This is an extension to our launcher for the Windows Debugger to support TTD. WinDbg TTD
|
||||
uses <CODE>event:ticks</CODE> to denote its times. This corresponds well to Ghidra's
|
||||
<CODE>snapshot:steps</CODE> syntax, when we let snapshot be an event and ticks count the number
|
||||
of instruction steps. Upon expanding the "Events" node in the Model tree, we create a snapshot
|
||||
for every TTD event, including thread create/terminate, module load/unload, syscall, and other
|
||||
asynchronous changes. Then, when Ghidra navigates to a schedule of the form
|
||||
<CODE>snapshot:steps</CODE>, we command WinDbg to navigate to the corresponding
|
||||
<CODE>event:ticks</CODE> instead of using Ghidra's emulator. Conversely, time navigation from
|
||||
the WinDbg CLI will correspondingly navigate Ghidra. Thus, the two are synchronized in time. We
|
||||
also add <EM>reverse</EM> variants of the <B>Go</B> and <B>Step</B> control commands.</P>
|
||||
|
||||
<H3>Options</H3>
|
||||
|
||||
<P>This launcher has basically the same options as the WinDbg launcher, except that arguments
|
||||
are not included and the DLL path must contain <TT>TTDReplay.dll</TT> and the scripts that
|
||||
implement TTD. These are most easily obtained by installing WinDbg Preview or later.</P>
|
||||
|
||||
<H3>Setup</H3>
|
||||
|
||||
<P>Depending on how you acquire WinDbg TTD, you may need to copy the installation to a
|
||||
directory Ghidra is allowed to access. It's best not to try cherry-picking files. Just
|
||||
copy/unpack the entire WinDbg installation. Point the launch dialog to the directory containing
|
||||
<TT>dbgeng.dll</TT> as usual.</P>
|
||||
|
||||
<P><B>NOTE:</B> It's possible, especially if you have anti-virus software installed, that
|
||||
<TT>dbghelp.dll</TT> is forcefully loaded into the Python process before our connector package
|
||||
tries to load <TT>dbgeng.dll</TT>. This can cause <TT>dbghelp.dll</TT> to be loaded from
|
||||
<TT>System32</TT>, but <TT>dbgeng.dll</TT> to be loaded from the WinDbg installation, often
|
||||
leading to DLL compatibility problems. This usually manifests in module load and/or Python
|
||||
import errors. The only real way to be sure is to use a system utility and inspect the DLLs
|
||||
loaded by the <TT>python.exe</TT> process. You may be able to work around the issue by copying
|
||||
<TT>dbghelp.dll</TT> (and any other affected WinDbg DLLs) from the WinDbg installation into
|
||||
your Python installation, e.g., <TT>C:\Python313\dbghelp.dll</TT>.</P>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
@@ -4,20 +4,20 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "ghidradbg"
|
||||
version = "11.4"
|
||||
version = "11.5"
|
||||
authors = [
|
||||
{ name="Ghidra Development Team" },
|
||||
]
|
||||
description = "Ghidra's Plugin for dbgeng"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.7"
|
||||
requires-python = ">=3.9"
|
||||
classifiers = [
|
||||
"Programming Language :: Python :: 3",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Operating System :: OS Independent",
|
||||
]
|
||||
dependencies = [
|
||||
"ghidratrace==11.4",
|
||||
"ghidratrace==11.5",
|
||||
"pybag>=2.2.12"
|
||||
]
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ try:
|
||||
import pybag
|
||||
except Exception as e:
|
||||
from ghidratrace.setuputils import prompt_and_mitigate_dependencies
|
||||
prompt_and_mitigate_dependencies("Debug/Debugger-agent-dbgeng")
|
||||
prompt_and_mitigate_dependencies("<SELF>")
|
||||
|
||||
# NOTE: libraries must precede EVERYTHING, esp pybag and DbgMod
|
||||
from . import libraries, util, commands, methods, hooks
|
||||
|
||||
@@ -26,7 +26,7 @@ from ghidratrace.client import (MethodRegistry, ParamDesc, Address,
|
||||
from pybag import pydbg # type: ignore
|
||||
from pybag.dbgeng import core as DbgEng, exception # type: ignore
|
||||
|
||||
from . import util, commands
|
||||
from . import arch, util, commands
|
||||
|
||||
|
||||
REGISTRY = MethodRegistry(ThreadPoolExecutor(
|
||||
@@ -828,7 +828,7 @@ def read_mem(process: Process, range: AddressRange) -> None:
|
||||
display_result=False)
|
||||
if result['count'] == 0:
|
||||
commands.putmem_state(
|
||||
offset_start, offset_start + range.length() - 1, 'error')
|
||||
offset_start, range.length() - 1, 'error')
|
||||
|
||||
|
||||
@REGISTRY.method()
|
||||
@@ -836,7 +836,7 @@ def read_mem(process: Process, range: AddressRange) -> None:
|
||||
def write_mem(process: Process, address: Address, data: bytes) -> None:
|
||||
"""Write memory."""
|
||||
nproc = find_proc_by_obj(process)
|
||||
offset = process.trace.extra.required_mm().map_back(nproc, address)
|
||||
offset = process.trace.extra.require_mm().map_back(nproc, address)
|
||||
dbg().write(offset, data)
|
||||
|
||||
|
||||
@@ -845,9 +845,14 @@ def write_mem(process: Process, address: Address, data: bytes) -> None:
|
||||
def write_reg(frame: StackFrame, name: str, value: bytes) -> None:
|
||||
"""Write a register."""
|
||||
f = find_frame_by_obj(frame)
|
||||
util.select_frame(f.FrameNumber)
|
||||
nproc = pydbg.selected_process()
|
||||
dbg().reg._set_register(name, value)
|
||||
current = util.selected_frame()
|
||||
if f.FrameNumber != current:
|
||||
raise Exception("Mismatch on frame")
|
||||
nproc = util.selected_process()
|
||||
trace: Trace[commands.Extra] = frame.trace
|
||||
rv = trace.extra.require_rm().map_value_back(nproc, name, value)
|
||||
rval = int.from_bytes(rv.value, signed=False)
|
||||
dbg().reg._set_register(name, rval)
|
||||
|
||||
|
||||
@REGISTRY.method(display='Refresh Events (custom)', condition=util.dbg.IS_TRACE)
|
||||
|
||||
@@ -309,6 +309,9 @@
|
||||
</schema>
|
||||
<schema name="RegisterBank" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||
<attribute name="_order" schema="INT" hidden="yes" />
|
||||
<attribute schema="VOID" />
|
||||
<attribute schema="Register" />
|
||||
</schema>
|
||||
<schema name="Register">
|
||||
<interface name="Register" />
|
||||
</schema>
|
||||
</context>
|
||||
@@ -270,7 +270,10 @@
|
||||
</schema>
|
||||
<schema name="RegisterBank" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||
<attribute name="_order" schema="INT" hidden="yes" />
|
||||
<attribute schema="VOID" />
|
||||
<attribute schema="Register" />
|
||||
</schema>
|
||||
<schema name="Register">
|
||||
<interface name="Register" />
|
||||
</schema>
|
||||
|
||||
<schema name="ExdiProcessContainer" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#@menu-group drgn
|
||||
#@icon icon.debugger
|
||||
#@help drgn#core
|
||||
#@depends Debugger-rmi-trace
|
||||
#@env OPT_TARGET_IMG:file!="" "Core dump" "The target core dump"
|
||||
|
||||
export OPT_TARGET_KIND="coredump"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#@menu-group drgn
|
||||
#@icon icon.debugger
|
||||
#@help drgn#linux_kernel
|
||||
#@depends Debugger-rmi-trace
|
||||
|
||||
export OPT_TARGET_KIND="kernel"
|
||||
sudo -E drgn ../support/local-drgn.py
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#@menu-group drgn
|
||||
#@icon icon.debugger
|
||||
#@help drgn#attach
|
||||
#@depends Debugger-rmi-trace
|
||||
#@env OPT_TARGET_PID:int=44068 "PID" "The target's process id"
|
||||
|
||||
export OPT_TARGET_KIND="user"
|
||||
|
||||
@@ -22,25 +22,18 @@ import sys
|
||||
|
||||
import drgn.cli
|
||||
|
||||
home = os.getenv('GHIDRA_HOME')
|
||||
|
||||
if os.path.isdir(f'{home}/ghidra/.git'):
|
||||
def append_paths():
|
||||
sys.path.append(
|
||||
f'{home}/ghidra/Ghidra/Debug/Debugger-agent-drgn/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-drgn/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-drgn/pypkg/src')
|
||||
sys.path.append(f'{home}/Ghidra/Debug/Debugger-rmi-trace/pypkg/src')
|
||||
f"{os.getenv('MODULE_Debugger_rmi_trace_HOME')}/data/support")
|
||||
from gmodutils import ghidra_module_pypath
|
||||
sys.path.append(ghidra_module_pypath("Debugger-rmi-trace"))
|
||||
sys.path.append(ghidra_module_pypath())
|
||||
|
||||
|
||||
def main():
|
||||
append_paths()
|
||||
|
||||
from ghidradrgn import commands as cmd
|
||||
cmd.ghidra_trace_connect(address=os.getenv('GHIDRA_TRACE_RMI_ADDR'))
|
||||
cmd.ghidra_trace_create(start_trace=True)
|
||||
@@ -49,9 +42,7 @@ def main():
|
||||
cmd.ghidra_trace_txcommit()
|
||||
cmd.ghidra_trace_activate()
|
||||
drgn.cli.run_interactive(cmd.prog)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
||||
|
||||
@@ -4,20 +4,20 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "ghidradrgn"
|
||||
version = "11.4"
|
||||
version = "11.5"
|
||||
authors = [
|
||||
{ name="Ghidra Development Team" },
|
||||
]
|
||||
description = "Ghidra's Plugin for drgn"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.7"
|
||||
requires-python = ">=3.9"
|
||||
classifiers = [
|
||||
"Programming Language :: Python :: 3",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Operating System :: OS Independent",
|
||||
]
|
||||
dependencies = [
|
||||
"ghidratrace==11.4",
|
||||
"ghidratrace==11.5",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#@menu-group gdb
|
||||
#@icon icon.debugger
|
||||
#@help gdb#local
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum StartCmd:str run start starti
|
||||
#@enum Endian:str auto big little
|
||||
#@arg :file "Image" "The target binary executable image"
|
||||
@@ -36,8 +37,8 @@
|
||||
|
||||
. ..\support\gdbsetuputils.ps1
|
||||
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace"
|
||||
$pypathGdb = Ghidra-Module-PyPath "Debug/Debugger-agent-gdb"
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace"
|
||||
$pypathGdb = Ghidra-Module-PyPath
|
||||
$Env:PYTHONPATH = "$pypathGdb;$pypathTrace;$Env:PYTHONPATH"
|
||||
|
||||
$arglist = Compute-Gdb-Usermode-Args `
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#@menu-group gdb
|
||||
#@icon icon.debugger
|
||||
#@help gdb#local
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum StartCmd:str run start starti
|
||||
#@enum Endian:str auto big little
|
||||
#@arg :file "Image" "The target binary executable image, empty for no target"
|
||||
@@ -39,8 +40,8 @@
|
||||
|
||||
. ../support/gdbsetuputils.sh
|
||||
|
||||
pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace")
|
||||
pypathGdb=$(ghidra-module-pypath "Debug/Debugger-agent-gdb")
|
||||
pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace")
|
||||
pypathGdb=$(ghidra-module-pypath)
|
||||
export PYTHONPATH=$pypathGdb:$pypathTrace:$PYTHONPATH
|
||||
|
||||
target_image="$1"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#@menu-group gdb
|
||||
#@icon icon.debugger
|
||||
#@help gdb#rr
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum StartCmd:str run start starti
|
||||
#@enum Endian:str auto big little
|
||||
#@arg :file "Trace Dir" "The target trace directory (e.g. .local/share/rr/trace)"
|
||||
@@ -36,8 +37,8 @@
|
||||
|
||||
. ../support/gdbsetuputils.sh
|
||||
|
||||
pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace")
|
||||
pypathGdb=$(ghidra-module-pypath "Debug/Debugger-agent-gdb")
|
||||
pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace")
|
||||
pypathGdb=$(ghidra-module-pypath)
|
||||
export PYTHONPATH=$pypathGdb:$pypathTrace:$PYTHONPATH
|
||||
|
||||
target_trace="$1"
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#@menu-group gdb
|
||||
#@icon icon.debugger
|
||||
#@help gdb#qemu
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum Endian:str auto big little
|
||||
#@arg :file! "Image" "The target binary executable image"
|
||||
#@args "Arguments" "Command-line arguments to pass to the target"
|
||||
@@ -42,8 +43,8 @@
|
||||
|
||||
. ../support/gdbsetuputils.sh
|
||||
|
||||
pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace")
|
||||
pypathGdb=$(ghidra-module-pypath "Debug/Debugger-agent-gdb")
|
||||
pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace")
|
||||
pypathGdb=$(ghidra-module-pypath)
|
||||
export PYTHONPATH=$pypathGdb:$pypathTrace:$PYTHONPATH
|
||||
|
||||
target_image="$1"
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#@menu-group gdb
|
||||
#@icon icon.debugger
|
||||
#@help gdb#qemu
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum Endian:str auto big little
|
||||
#@env OPT_TARGET_IMG:file!="" "Image" "The target binary executable image"
|
||||
#@env GHIDRA_LANG_EXTTOOL_qemu_system:file="" "QEMU command" "The path to qemu-system for the target architecture."
|
||||
@@ -38,8 +39,8 @@
|
||||
|
||||
. ..\support\gdbsetuputils.ps1
|
||||
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace"
|
||||
$pypathGdb = Ghidra-Module-PyPath "Debug/Debugger-agent-gdb"
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace"
|
||||
$pypathGdb = Ghidra-Module-PyPath
|
||||
$Env:PYTHONPATH = "$pypathGdb;$pypathTrace;$Env:PYTHONPATH"
|
||||
|
||||
$qemuargs = @("`"$Env:GHIDRA_LANG_EXTTOOL_qemu_system`"")
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#@menu-group gdb
|
||||
#@icon icon.debugger
|
||||
#@help gdb#qemu
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum Endian:str auto big little
|
||||
#@arg :file! "Image" "The target binary executable image"
|
||||
#@env GHIDRA_LANG_EXTTOOL_qemu_system:file="" "QEMU command" "The path to qemu-system for the target architecture."
|
||||
@@ -41,8 +42,8 @@
|
||||
|
||||
. ../support/gdbsetuputils.sh
|
||||
|
||||
pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace")
|
||||
pypathGdb=$(ghidra-module-pypath "Debug/Debugger-agent-gdb")
|
||||
pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace")
|
||||
pypathGdb=$(ghidra-module-pypath)
|
||||
export PYTHONPATH=$pypathGdb:$pypathTrace:$PYTHONPATH
|
||||
|
||||
target_image="$1"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#@menu-group gdb
|
||||
#@icon icon.debugger
|
||||
#@help gdb#remote
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum TargetType:str remote extended-remote
|
||||
#@enum Endian:str auto big little
|
||||
#@arg :file "Image" "The target binary executable image (a copy on the local system)"
|
||||
@@ -37,8 +38,8 @@
|
||||
|
||||
. ..\support\gdbsetuputils.ps1
|
||||
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace"
|
||||
$pypathGdb = Ghidra-Module-PyPath "Debug/Debugger-agent-gdb"
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace"
|
||||
$pypathGdb = Ghidra-Module-PyPath
|
||||
$Env:PYTHONPATH = "$pypathGdb;$pypathTrace;$Env:PYTHONPATH"
|
||||
|
||||
$arglist = Compute-Gdb-Remote-Args `
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#@menu-group gdb
|
||||
#@icon icon.debugger
|
||||
#@help gdb#remote
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum TargetType:str remote extended-remote
|
||||
#@enum Endian:str auto big little
|
||||
#@arg :file "Image" "The target binary executable image (a copy on the local system)"
|
||||
@@ -38,8 +39,8 @@
|
||||
|
||||
. ../support/gdbsetuputils.sh
|
||||
|
||||
pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace")
|
||||
pypathGdb=$(ghidra-module-pypath "Debug/Debugger-agent-gdb")
|
||||
pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace")
|
||||
pypathGdb=$(ghidra-module-pypath)
|
||||
export PYTHONPATH=$pypathGdb:$pypathTrace:$PYTHONPATH
|
||||
|
||||
target_image="$1"
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
##
|
||||
#@timeout 60000
|
||||
#@title gdb via ssh
|
||||
#@image-opt arg:1
|
||||
#@desc <html><body width="300px">
|
||||
@@ -26,6 +25,7 @@
|
||||
#@menu-group gdb
|
||||
#@icon icon.debugger
|
||||
#@help gdb#ssh
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum StartCmd:str run start starti
|
||||
#@enum Endian:str auto big little
|
||||
#@arg :str "Image" "The target binary executable image on the remote system"
|
||||
@@ -76,7 +76,7 @@ finished, try launching again.
|
||||
|
||||
if ($answer) {
|
||||
Write-Host "Copying Wheels to $Env:OPT_HOST"
|
||||
Mitigate-Scp-PyModules "Debug/Debugger-rmi-trace" "Debug/Debugger-agent-gdb"
|
||||
Mitigate-Scp-PyModules "Debugger-rmi-trace" "<SELF>"
|
||||
|
||||
Write-Host "Installing Wheels into GDB's embedded Python"
|
||||
$arglist = Compute-Gdb-PipInstall-Args "'-f'" "os.environ['HOME']" "'ghidragdb>=$version'"
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
##
|
||||
#@timeout 60000
|
||||
#@title gdb via ssh
|
||||
#@image-opt arg:1
|
||||
#@desc <html><body width="300px">
|
||||
@@ -27,6 +26,7 @@
|
||||
#@menu-group gdb
|
||||
#@icon icon.debugger
|
||||
#@help gdb#ssh
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum StartCmd:str run start starti
|
||||
#@enum Endian:str auto big little
|
||||
#@arg :str "Image" "The target binary executable image on the remote system"
|
||||
@@ -93,7 +93,7 @@ finished, try launching again.
|
||||
" "Would you like to install 'ghidragdb>=$version'?"; then
|
||||
|
||||
echo "Copying Wheels to $OPT_HOST"
|
||||
mitigate-scp-pymodules "Debug/Debugger-rmi-trace" "Debug/Debugger-agent-gdb"
|
||||
mitigate-scp-pymodules "Debugger-rmi-trace" "<SELF>"
|
||||
|
||||
echo "Installing Wheels into GDB's embedded Python"
|
||||
do-installation
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
##
|
||||
#@timeout 60000
|
||||
#@title gdb + gdbserver via ssh
|
||||
#@image-opt arg:1
|
||||
#@desc <html><body width="300px">
|
||||
@@ -26,6 +25,7 @@
|
||||
#@menu-group gdb
|
||||
#@icon icon.debugger
|
||||
#@help gdb#gdbserver_ssh
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum Endian:str auto big little
|
||||
#@arg :str! "Image" "The target binary executable image on the remote system"
|
||||
#@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||
@@ -40,8 +40,8 @@
|
||||
|
||||
. ..\support\gdbsetuputils.ps1
|
||||
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace"
|
||||
$pypathGdb = Ghidra-Module-PyPath "Debug/Debugger-agent-gdb"
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace"
|
||||
$pypathGdb = Ghidra-Module-PyPath
|
||||
$Env:PYTHONPATH = "$pypathGdb;$pypathTrace;$Env:PYTHONPATH"
|
||||
|
||||
$arglist = Compute-Gdb-Remote-Args `
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
##
|
||||
#@timeout 60000
|
||||
#@title gdb + gdbserver via ssh
|
||||
#@image-opt arg:1
|
||||
#@desc <html><body width="300px">
|
||||
@@ -27,6 +26,7 @@
|
||||
#@menu-group gdb
|
||||
#@icon icon.debugger
|
||||
#@help gdb#gdbserver_ssh
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum Endian:str auto big little
|
||||
#@arg :str! "Image" "The target binary executable image on the remote system"
|
||||
#@args "Arguments" "Command-line arguments to pass to the target"
|
||||
@@ -41,8 +41,8 @@
|
||||
|
||||
. ../support/gdbsetuputils.sh
|
||||
|
||||
pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace")
|
||||
pypathGdb=$(ghidra-module-pypath "Debug/Debugger-agent-gdb")
|
||||
pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace")
|
||||
pypathGdb=$(ghidra-module-pypath)
|
||||
export PYTHONPATH=$pypathGdb:$pypathTrace:$PYTHONPATH
|
||||
|
||||
target_image="$1"
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#@menu-group gdb
|
||||
#@icon icon.debugger
|
||||
#@help gdb#wine
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum Endian:str auto big little
|
||||
#@arg :file! "Image" "The target binary executable image"
|
||||
#@args "Arguments" "Command-line arguments to pass to the target"
|
||||
@@ -39,8 +40,8 @@
|
||||
|
||||
. ../support/gdbsetuputils.sh
|
||||
|
||||
pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace")
|
||||
pypathGdb=$(ghidra-module-pypath "Debug/Debugger-agent-gdb")
|
||||
pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace")
|
||||
pypathGdb=$(ghidra-module-pypath)
|
||||
export PYTHONPATH=$pypathGdb:$pypathTrace:$PYTHONPATH
|
||||
|
||||
target_image="$1"
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
##
|
||||
. ..\..\..\Debugger-rmi-trace\data\support\setuputils.ps1
|
||||
. $Env:MODULE_Debugger_rmi_trace_HOME\data\support\setuputils.ps1
|
||||
|
||||
function Add-Gdb-Init-Args {
|
||||
param([ref]$ArgList)
|
||||
@@ -62,7 +62,7 @@ function Add-Gdb-Tail-Args {
|
||||
param([ref]$ArgList)
|
||||
|
||||
$ArgList.Value+=("-ex", "`"set confirm on`"")
|
||||
$ArgList.Value+=("-ex", "`"set pagination on`"")
|
||||
# $ArgList.Value+=("-ex", "`"set pagination on`"")
|
||||
}
|
||||
|
||||
function Compute-Gdb-Usermode-Args {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
##
|
||||
. ../../../Debugger-rmi-trace/data/support/setuputils.sh
|
||||
. $MODULE_Debugger_rmi_trace_HOME/data/support/setuputils.sh
|
||||
|
||||
add-gdb-init-args() {
|
||||
args+=(-q)
|
||||
@@ -64,7 +64,7 @@ add-gdb-start-if-image() {
|
||||
|
||||
add-gdb-tail-args() {
|
||||
args+=(-ex "set confirm on")
|
||||
args+=(-ex "set pagination on")
|
||||
# args+=(-ex "set pagination on")
|
||||
}
|
||||
|
||||
compute-gdb-usermode-args() {
|
||||
|
||||
@@ -4,20 +4,20 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "ghidragdb"
|
||||
version = "11.4"
|
||||
version = "11.5"
|
||||
authors = [
|
||||
{ name="Ghidra Development Team" },
|
||||
]
|
||||
description = "Ghidra's Plugin for gdb"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.7"
|
||||
requires-python = ">=3.9"
|
||||
classifiers = [
|
||||
"Programming Language :: Python :: 3",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Operating System :: OS Independent",
|
||||
]
|
||||
dependencies = [
|
||||
"ghidratrace==11.4",
|
||||
"ghidratrace==11.5",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
|
||||
@@ -225,6 +225,9 @@
|
||||
<schema name="RegisterValueContainer" attributeResync="NEVER">
|
||||
<interface name="RegisterContainer" />
|
||||
<attribute name="_order" schema="INT" hidden="yes" />
|
||||
<attribute schema="VOID" />
|
||||
<attribute schema="Register" />
|
||||
</schema>
|
||||
<schema name="Register">
|
||||
<interface name="Register" />
|
||||
</schema>
|
||||
</context>
|
||||
@@ -25,6 +25,7 @@
|
||||
#@menu-group lldb
|
||||
#@icon icon.debugger
|
||||
#@help lldb#android
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum StartCmd:str "process launch" "process launch --stop-at-entry"
|
||||
#@arg :file "Image" "The target binary executable image"
|
||||
#@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||
@@ -36,8 +37,8 @@
|
||||
|
||||
. ..\support\lldbsetuputils.ps1
|
||||
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace"
|
||||
$pypathLldb = Ghidra-Module-PyPath "Debug/Debugger-agent-lldb"
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace"
|
||||
$pypathLldb = Ghidra-Module-PyPath
|
||||
$Env:PYTHONPATH = "$pypathLldb;$pypathTrace;$Env:PYTHONPATH"
|
||||
|
||||
$arglist = Compute-Lldb-Platform-Args `
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#@menu-group lldb
|
||||
#@icon icon.debugger
|
||||
#@help lldb#android
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum StartCmd:str "process launch" "process launch --stop-at-entry"
|
||||
#@arg :file "Image" "The target binary executable image"
|
||||
#@args "Arguments" "Command-line arguments to pass to the target"
|
||||
@@ -37,8 +38,8 @@
|
||||
|
||||
. ../support/lldbsetuputils.sh
|
||||
|
||||
pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace")
|
||||
pypathLldb=$(ghidra-module-pypath "Debug/Debugger-agent-lldb")
|
||||
pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace")
|
||||
pypathLldb=$(ghidra-module-pypath)
|
||||
export PYTHONPATH=$pypathLldb:$pypathTrace:$PYTHONPATH
|
||||
|
||||
target_image="$1"
|
||||
|
||||
@@ -24,14 +24,15 @@
|
||||
#@menu-group lldb
|
||||
#@icon icon.debugger
|
||||
#@help lldb#macos_kernel
|
||||
#@depends Debugger-rmi-trace
|
||||
#@env OPT_HOST:str="localhost" "Host" "The hostname of the target"
|
||||
#@env OPT_ARCH:str="" "Architecture" "Target architecture override"
|
||||
#@env OPT_LLDB_PATH:file="lldb" "lldb command" "The path to lldb on the local system. Omit the full path to resolve using the system PATH."
|
||||
|
||||
. ..\support\lldbsetuputils.ps1
|
||||
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace"
|
||||
$pypathLldb = Ghidra-Module-PyPath "Debug/Debugger-agent-lldb"
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace"
|
||||
$pypathLldb = Ghidra-Module-PyPath
|
||||
$Env:PYTHONPATH = "$pypathLldb;$pypathTrace;$Env:PYTHONPATH"
|
||||
|
||||
$arglist = Compute-Lldb-Remote-Args `
|
||||
|
||||
@@ -25,14 +25,15 @@
|
||||
#@menu-group lldb
|
||||
#@icon icon.debugger
|
||||
#@help lldb#macos_kernel
|
||||
#@depends Debugger-rmi-trace
|
||||
#@env OPT_HOST:str="localhost" "Host" "The hostname of the target"
|
||||
#@env OPT_ARCH:str="" "Architecture" "Target architecture override"
|
||||
#@env OPT_LLDB_PATH:file="lldb" "lldb command" "The path to lldb on the local system. Omit the full path to resolve using the system PATH."
|
||||
|
||||
. ../support/lldbsetuputils.sh
|
||||
|
||||
pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace")
|
||||
pypathLldb=$(ghidra-module-pypath "Debug/Debugger-agent-lldb")
|
||||
pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace")
|
||||
pypathLldb=$(ghidra-module-pypath)
|
||||
export PYTHONPATH=$pypathLldb:$pypathTrace:$PYTHONPATH
|
||||
|
||||
function launch-lldb() {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#@menu-group lldb
|
||||
#@icon icon.debugger
|
||||
#@help lldb#local
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum StartCmd:str "process launch" "process launch --stop-at-entry"
|
||||
#@arg :file "Image" "The target binary executable image"
|
||||
#@env OPT_TARGET_ARGS:str="" "Arguments" "Command-line arguments to pass to the target"
|
||||
@@ -33,8 +34,8 @@
|
||||
|
||||
. ..\support\lldbsetuputils.ps1
|
||||
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace"
|
||||
$pypathLldb = Ghidra-Module-PyPath "Debug/Debugger-agent-lldb"
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace"
|
||||
$pypathLldb = Ghidra-Module-PyPath
|
||||
$Env:PYTHONPATH = "$pypathLldb;$pypathTrace;$Env:PYTHONPATH"
|
||||
|
||||
$arglist = Compute-Lldb-Usermode-Args `
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#@menu-group lldb
|
||||
#@icon icon.debugger
|
||||
#@help lldb#local
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum StartCmd:str "process launch" "process launch --stop-at-entry"
|
||||
#@arg :file "Image" "The target binary executable image"
|
||||
#@args "Arguments" "Command-line arguments to pass to the target"
|
||||
@@ -36,8 +37,8 @@
|
||||
|
||||
. ../support/lldbsetuputils.sh
|
||||
|
||||
pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace")
|
||||
pypathLldb=$(ghidra-module-pypath "Debug/Debugger-agent-lldb")
|
||||
pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace")
|
||||
pypathLldb=$(ghidra-module-pypath)
|
||||
export PYTHONPATH=$pypathLldb:$pypathTrace:$PYTHONPATH
|
||||
|
||||
target_image="$1"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#@menu-group lldb
|
||||
#@icon icon.debugger
|
||||
#@help lldb#remote
|
||||
#@depends Debugger-rmi-trace
|
||||
#@arg :file "Image" "The target binary executable image (a copy on the local system)"
|
||||
#@env OPT_HOST:str="localhost" "Host" "The hostname of the target"
|
||||
#@env OPT_PORT:str="9999" "Port" "The host's listening port"
|
||||
@@ -33,8 +34,8 @@
|
||||
|
||||
. ..\support\lldbsetuputils.ps1
|
||||
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debug/Debugger-rmi-trace"
|
||||
$pypathLldb = Ghidra-Module-PyPath "Debug/Debugger-agent-lldb"
|
||||
$pypathTrace = Ghidra-Module-PyPath "Debugger-rmi-trace"
|
||||
$pypathLldb = Ghidra-Module-PyPath
|
||||
$Env:PYTHONPATH = "$pypathLldb;$pypathTrace;$Env:PYTHONPATH"
|
||||
|
||||
$arglist = Compute-Lldb-Remote-Args `
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#@menu-group lldb
|
||||
#@icon icon.debugger
|
||||
#@help lldb#remote
|
||||
#@depends Debugger-rmi-trace
|
||||
#@arg :file "Image" "The target binary executable image (a copy on the local system)"
|
||||
#@env OPT_HOST:str="localhost" "Host" "The hostname of the target"
|
||||
#@env OPT_PORT:str="9999" "Port" "The host's listening port"
|
||||
@@ -34,8 +35,8 @@
|
||||
|
||||
. ../support/lldbsetuputils.sh
|
||||
|
||||
pypathTrace=$(ghidra-module-pypath "Debug/Debugger-rmi-trace")
|
||||
pypathLldb=$(ghidra-module-pypath "Debug/Debugger-agent-lldb")
|
||||
pypathTrace=$(ghidra-module-pypath "Debugger-rmi-trace")
|
||||
pypathLldb=$(ghidra-module-pypath)
|
||||
export PYTHONPATH=$pypathLldb:$pypathTrace:$PYTHONPATH
|
||||
|
||||
target_image="$1"
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
##
|
||||
#@timeout 60000
|
||||
#@title lldb via ssh
|
||||
#@image-opt arg:1
|
||||
#@desc <html><body width="300px">
|
||||
@@ -26,6 +25,7 @@
|
||||
#@menu-group lldb
|
||||
#@icon icon.debugger
|
||||
#@help lldb#ssh
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum StartCmd:str "process launch" "process launch --stop-at-entry"
|
||||
#@enum Endian:str auto big little
|
||||
#@arg :str "Image" "The target binary executable image on the remote system"
|
||||
@@ -75,7 +75,7 @@ finished, try launching again.
|
||||
|
||||
if ($answer) {
|
||||
Write-Host "Copying Wheels to $Env:OPT_HOST"
|
||||
Mitigate-Scp-PyModules "Debug/Debugger-rmi-trace" "Debug/Debugger-agent-lldb"
|
||||
Mitigate-Scp-PyModules "Debugger-rmi-trace" "<SELF>"
|
||||
|
||||
Write-Host "Installing Wheels into LLDB's embedded Python"
|
||||
$arglist = Compute-Lldb-PipInstall-Args "'-f'" "os.environ['HOME']" "'ghidralldb>=$version'"
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
##
|
||||
#@timeout 60000
|
||||
#@title lldb via ssh
|
||||
#@image-opt arg:1
|
||||
#@desc <html><body width="300px">
|
||||
@@ -27,6 +26,7 @@
|
||||
#@menu-group lldb
|
||||
#@icon icon.debugger
|
||||
#@help lldb#ssh
|
||||
#@depends Debugger-rmi-trace
|
||||
#@enum StartCmd:str "process launch" "process launch --stop-at-entry"
|
||||
#@enum Endian:str auto big little
|
||||
#@arg :str "Image" "The target binary executable image on the remote system"
|
||||
@@ -92,7 +92,7 @@ finished, try launching again.
|
||||
" "Would you like to install 'ghidralldb>=$version'?"; then
|
||||
|
||||
echo "Copying Wheels to $OPT_HOST"
|
||||
mitigate-scp-pymodules "Debug/Debugger-rmi-trace" "Debug/Debugger-agent-lldb"
|
||||
mitigate-scp-pymodules "Debugger-rmi-trace" "<SELF>"
|
||||
|
||||
echo "Installing Wheels into LLDB's embedded Python"
|
||||
do-installation
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
##
|
||||
. ..\..\..\Debugger-rmi-trace\data\support\setuputils.ps1
|
||||
. $Env:MODULE_Debugger_rmi_trace_HOME\data\support\setuputils.ps1
|
||||
|
||||
function Add-Lldb-Init-Args {
|
||||
param([ref]$ArgList)
|
||||
@@ -81,11 +81,11 @@ function Compute-Lldb-Usermode-Args {
|
||||
function Compute-Lldb-Platform-Args {
|
||||
param($TargetImage, $TargetType, $TargetUrl, $RmiAddress)
|
||||
|
||||
$argslist = @("`"$Env:OPT_LLDB_PATH`"")
|
||||
$arglist = @("`"$Env:OPT_LLDB_PATH`"")
|
||||
Add-Lldb-Init-Args -ArgList ([ref]$arglist)
|
||||
$argslist+=("-o", "`"platform select '$TargetType'`"")
|
||||
$argslist+=("-o", "`"platform connect '$TargetUrl'`"")
|
||||
Add-Lldb-Image-And-Args -ArgList ([ref]$arglistt) -TargetImage $TargetImage -TargetArgs $Env:OPT_TARGET_ARGS
|
||||
$arglist+=("-o", "`"platform select '$TargetType'`"")
|
||||
$arglist+=("-o", "`"platform connect '$TargetUrl'`"")
|
||||
Add-Lldb-Image-And-Args -ArgList ([ref]$arglist) -TargetImage $TargetImage -TargetArgs $Env:OPT_TARGET_ARGS
|
||||
Add-Lldb-Connect-And-Sync -ArgList ([ref]$arglist) -Address $RmiAddress
|
||||
Add-Lldb-Start-If-Image -ArgList ([ref]$arglist) -TargetImage $TargetImage
|
||||
Add-Lldb-Tail-Args -ArgList ([ref]$arglist)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
##
|
||||
. ../../../Debugger-rmi-trace/data/support/setuputils.sh
|
||||
. $MODULE_Debugger_rmi_trace_HOME/data/support/setuputils.sh
|
||||
|
||||
add-lldb-init-args() {
|
||||
args+=(-o "version")
|
||||
|
||||
@@ -4,20 +4,20 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "ghidralldb"
|
||||
version = "11.4"
|
||||
version = "11.5"
|
||||
authors = [
|
||||
{ name="Ghidra Development Team" },
|
||||
]
|
||||
description = "Ghidra's Plugin for lldb"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.7"
|
||||
requires-python = ">=3.9"
|
||||
classifiers = [
|
||||
"Programming Language :: Python :: 3",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Operating System :: OS Independent",
|
||||
]
|
||||
dependencies = [
|
||||
"ghidratrace==11.4",
|
||||
"ghidratrace==11.5",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
|
||||
@@ -308,6 +308,8 @@ class DefaultRegisterMapper(object):
|
||||
|
||||
def map_value_back(self, proc: lldb.SBProcess, name: str,
|
||||
value: bytes) -> RegVal:
|
||||
if self.byte_order == 'little':
|
||||
value = bytes(reversed(value))
|
||||
return RegVal(self.map_name_back(proc, name), value)
|
||||
|
||||
|
||||
|
||||
@@ -106,6 +106,10 @@ def find_proc_by_modules_obj(object: TraceObject) -> lldb.SBProcess:
|
||||
return find_proc_by_pattern(object, MODULES_PATTERN, "a ModuleContainer")
|
||||
|
||||
|
||||
def find_proc_by_frame(object: TraceObject) -> lldb.SBProcess:
|
||||
return find_proc_by_pattern(object, FRAME_PATTERN, "a StaclFrame")
|
||||
|
||||
|
||||
def find_thread_by_num(proc: lldb.SBThread, tnum: int) -> lldb.SBThread:
|
||||
for t in proc.threads:
|
||||
if t.GetThreadID() == tnum:
|
||||
@@ -731,11 +735,22 @@ def write_mem(process: Process, address: Address, data: bytes) -> None:
|
||||
@REGISTRY.method()
|
||||
def write_reg(frame: StackFrame, name: str, value: bytes) -> None:
|
||||
"""Write a register."""
|
||||
proc = find_proc_by_frame(frame)
|
||||
util.get_debugger().SetSelectedTarget(proc.target)
|
||||
f = find_frame_by_obj(frame)
|
||||
f.select()
|
||||
proc = lldb.selected_process()
|
||||
mname, mval = frame.trace.extra.require_rm().map_value_back(proc, name, value)
|
||||
size = int(lldb.parse_and_eval(f'sizeof(${mname})'))
|
||||
arr = '{' + ','.join(str(b) for b in mval) + '}'
|
||||
exec_convert_errors(
|
||||
f'expr ((unsigned char[{size}])${mname}) = {arr};')
|
||||
exec_convert_errors(f'frame select {f.idx}')
|
||||
rv = frame.trace.extra.require_rm().map_value_back(proc, name, value)
|
||||
reg = f.registers[0].GetChildMemberWithName(name)
|
||||
error = lldb.SBError()
|
||||
data = lldb.SBData()
|
||||
tgt = util.get_target()
|
||||
for b in rv.value:
|
||||
bv = tgt.EvaluateExpression(f"(char){b}")
|
||||
if bv.error.fail:
|
||||
raise Exception(bv.error.description)
|
||||
if not data.Append(bv.GetData()):
|
||||
raise Exception(f"Could not build data for register value {rv.value}")
|
||||
if not reg.SetData(data, error):
|
||||
raise Exception(error.description)
|
||||
with commands.open_tracked_tx(f'Write Register {name}'):
|
||||
exec_convert_errors('ghidra trace putreg')
|
||||
|
||||
@@ -260,6 +260,9 @@
|
||||
</schema>
|
||||
<schema name="RegisterBank" canonical="yes" elementResync="ONCE" attributeResync="NEVER">
|
||||
<attribute name="_order" schema="INT" hidden="yes" />
|
||||
<attribute schema="VOID" />
|
||||
<attribute schema="Register" />
|
||||
</schema>
|
||||
<schema name="Register">
|
||||
<interface name="Register" />
|
||||
</schema>
|
||||
</context>
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -18,6 +18,7 @@ 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/distributableGhidraModule.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javadoc.gradle"
|
||||
|
||||
apply plugin: 'eclipse'
|
||||
eclipse.project.name = 'Debug Debugger-api'
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -19,9 +19,10 @@ import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import ghidra.debug.api.emulation.DebuggerPcodeEmulatorFactory;
|
||||
import ghidra.debug.api.emulation.DebuggerPcodeMachine;
|
||||
import ghidra.debug.api.emulation.EmulatorFactory;
|
||||
import ghidra.framework.plugintool.ServiceInfo;
|
||||
import ghidra.pcode.emu.PcodeMachine;
|
||||
import ghidra.pcode.exec.trace.TraceEmulationIntegration.Writer;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.trace.model.Trace;
|
||||
@@ -55,17 +56,25 @@ public interface DebuggerEmulationService {
|
||||
|
||||
/**
|
||||
* The result of letting the emulator "run free"
|
||||
*
|
||||
* @param schedule the schedule that was emulated
|
||||
* @param snapshot the snapshot where the final state was written down
|
||||
* @param error if an error occurred, the error, or null
|
||||
*/
|
||||
record RecordEmulationResult(TraceSchedule schedule, long snapshot, Throwable error)
|
||||
implements EmulationResult {
|
||||
}
|
||||
implements EmulationResult {}
|
||||
|
||||
/**
|
||||
* An emulator managed by this service
|
||||
*
|
||||
* @param trace the trace the emulator is bound to
|
||||
* @param emulator the emulator itself
|
||||
* @param writer the callbacks with delayed writes for trace/UI integration
|
||||
* @param version the cache version. See {@link #isValid()}.
|
||||
*/
|
||||
record CachedEmulator(Trace trace, DebuggerPcodeMachine<?> emulator, long version) {
|
||||
public CachedEmulator(Trace trace, DebuggerPcodeMachine<?> emulator) {
|
||||
this(trace, emulator, trace.getEmulatorCacheVersion());
|
||||
record CachedEmulator(Trace trace, PcodeMachine<?> emulator, Writer writer, long version) {
|
||||
public CachedEmulator(Trace trace, PcodeMachine<?> emulator, Writer writer) {
|
||||
this(trace, emulator, writer, trace.getEmulatorCacheVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +98,7 @@ public interface DebuggerEmulationService {
|
||||
* @return the emulator
|
||||
*/
|
||||
@Override
|
||||
public DebuggerPcodeMachine<?> emulator() {
|
||||
public PcodeMachine<?> emulator() {
|
||||
return emulator;
|
||||
}
|
||||
|
||||
@@ -112,14 +121,16 @@ public interface DebuggerEmulationService {
|
||||
*
|
||||
* @param emu the emulator
|
||||
*/
|
||||
void running(CachedEmulator emu);
|
||||
default void running(CachedEmulator emu) {
|
||||
}
|
||||
|
||||
/**
|
||||
* An emulator has stopped
|
||||
*
|
||||
* @param emu the emulator
|
||||
*/
|
||||
void stopped(CachedEmulator emu);
|
||||
default void stopped(CachedEmulator emu) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,7 +138,7 @@ public interface DebuggerEmulationService {
|
||||
*
|
||||
* @return the collection of factories
|
||||
*/
|
||||
Collection<DebuggerPcodeEmulatorFactory> getEmulatorFactories();
|
||||
Collection<EmulatorFactory> getEmulatorFactories();
|
||||
|
||||
/**
|
||||
* Set the current emulator factory
|
||||
@@ -140,19 +151,18 @@ public interface DebuggerEmulationService {
|
||||
* <p>
|
||||
* TODO: Should there be some opinion service for choosing default configs? Seems overly
|
||||
* complicated for what it offers. For now, we won't save anything, we'll default to the
|
||||
* (built-in) {@link BytesDebuggerPcodeEmulatorFactory}, and we won't have configuration
|
||||
* options.
|
||||
* (built-in) concrete emulator, and we won't have configuration options.
|
||||
*
|
||||
* @param factory the chosen factory
|
||||
*/
|
||||
void setEmulatorFactory(DebuggerPcodeEmulatorFactory factory);
|
||||
void setEmulatorFactory(EmulatorFactory factory);
|
||||
|
||||
/**
|
||||
* Get the current emulator factory
|
||||
*
|
||||
* @return the factory
|
||||
*/
|
||||
DebuggerPcodeEmulatorFactory getEmulatorFactory();
|
||||
EmulatorFactory getEmulatorFactory();
|
||||
|
||||
/**
|
||||
* Load the given program into a trace suitable for emulation in the UI, starting at the given
|
||||
@@ -228,6 +238,7 @@ public interface DebuggerEmulationService {
|
||||
* @param monitor a monitor cancellation
|
||||
* @param scheduler a thread scheduler for the emulator
|
||||
* @return the result of emulation
|
||||
* @throws CancelledException if the user cancels the task
|
||||
*/
|
||||
EmulationResult run(TracePlatform platform, TraceSchedule from, TaskMonitor monitor,
|
||||
Scheduler scheduler) throws CancelledException;
|
||||
@@ -268,8 +279,8 @@ public interface DebuggerEmulationService {
|
||||
* Get the cached emulator for the given trace and time
|
||||
*
|
||||
* <p>
|
||||
* To guarantee the emulator is present, call {@link #backgroundEmulate(Trace, TraceSchedule)}
|
||||
* first.
|
||||
* To guarantee the emulator is present, call
|
||||
* {@link #backgroundEmulate(TracePlatform, TraceSchedule)} first.
|
||||
* <p>
|
||||
* <b>WARNING:</b> This emulator belongs to this service. Stepping it, or otherwise manipulating
|
||||
* it without the service's knowledge can lead to unintended consequences.
|
||||
@@ -281,7 +292,7 @@ public interface DebuggerEmulationService {
|
||||
* @param time the time coordinates, including initial snap, steps, and p-code steps
|
||||
* @return the copied p-code frame
|
||||
*/
|
||||
DebuggerPcodeMachine<?> getCachedEmulator(Trace trace, TraceSchedule time);
|
||||
PcodeMachine<?> getCachedEmulator(Trace trace, TraceSchedule time);
|
||||
|
||||
/**
|
||||
* Get the emulators which are current executing
|
||||
@@ -290,6 +301,11 @@ public interface DebuggerEmulationService {
|
||||
*/
|
||||
Collection<CachedEmulator> getBusyEmulators();
|
||||
|
||||
/**
|
||||
* Invalidate the trace's cache of emulated states.
|
||||
*/
|
||||
void invalidateCache();
|
||||
|
||||
/**
|
||||
* Add a listener for emulator state changes
|
||||
*
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -21,16 +21,16 @@ import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import ghidra.debug.api.breakpoint.LogicalBreakpoint;
|
||||
import ghidra.debug.api.breakpoint.LogicalBreakpointsChangeListener;
|
||||
import ghidra.debug.api.breakpoint.LogicalBreakpoint.State;
|
||||
import ghidra.debug.api.breakpoint.LogicalBreakpointsChangeListener;
|
||||
import ghidra.framework.plugintool.ServiceInfo;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.CodeUnitLocation;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
|
||||
@ServiceInfo(
|
||||
@@ -99,10 +99,10 @@ public interface DebuggerLogicalBreakpointService {
|
||||
* If the given trace breakpoint is not part of any logical breakpoint, e.g., because the trace
|
||||
* is not opened in the tool or events are still being processed, then null is returned.
|
||||
*
|
||||
* @param bpt the trace breakpoint
|
||||
* @param loc the trace breakpoint location
|
||||
* @return the logical breakpoint, or null
|
||||
*/
|
||||
LogicalBreakpoint getBreakpoint(TraceBreakpoint bpt);
|
||||
LogicalBreakpoint getBreakpoint(TraceBreakpointLocation loc);
|
||||
|
||||
/**
|
||||
* Get the collected logical breakpoints (at present) at the given location.
|
||||
@@ -297,10 +297,10 @@ public interface DebuggerLogicalBreakpointService {
|
||||
*
|
||||
* <p>
|
||||
* If the given location refers to a static image, this behaves as in
|
||||
* {@link #placeBreakpointAt(Program, Address, TraceBreakpointKind)}. If it refers to a trace
|
||||
* view, this behaves as in {@link #placeBreakpointAt(Trace, Address, TraceBreakpointKind)},
|
||||
* ignoring the view's current snapshot in favor of the present. The name is only saved for a
|
||||
* program breakpoint.
|
||||
* {@link #placeBreakpointAt(Program, Address, long, Collection, String)}. If it refers to a
|
||||
* trace view, this behaves as in *
|
||||
* {@link #placeBreakpointAt(Trace, Address, long, Collection, String)}, ignoring the view's
|
||||
* current snapshot in favor of the present. The name is only saved for a program breakpoint.
|
||||
*
|
||||
* @param loc the location
|
||||
* @param length size of the breakpoint, may be ignored by debugger
|
||||
@@ -348,7 +348,7 @@ public interface DebuggerLogicalBreakpointService {
|
||||
/**
|
||||
* Disable a collection of logical breakpoints on target, if applicable
|
||||
*
|
||||
* @see #enableAll(Collection)
|
||||
* @see #enableAll(Collection, Trace)
|
||||
* @param col the collection
|
||||
* @param trace a trace, if the command should be limited to the given trace
|
||||
* @return a future which completes when all associated specifications have been disabled
|
||||
@@ -358,7 +358,7 @@ public interface DebuggerLogicalBreakpointService {
|
||||
/**
|
||||
* Delete, if possible, a collection of logical breakpoints on target, if applicable
|
||||
*
|
||||
* @see #enableAll(Collection)
|
||||
* @see #enableAll(Collection, Trace)
|
||||
* @param col the collection
|
||||
* @param trace a trace, if the command should be limited to the given trace
|
||||
* @return a future which completes when all associated specifications have been deleted
|
||||
@@ -371,7 +371,7 @@ public interface DebuggerLogicalBreakpointService {
|
||||
* @param col the trace breakpoints
|
||||
* @return a future which completes when the command has been processed
|
||||
*/
|
||||
CompletableFuture<Void> enableLocs(Collection<TraceBreakpoint> col);
|
||||
CompletableFuture<Void> enableLocs(Collection<TraceBreakpointLocation> col);
|
||||
|
||||
/**
|
||||
* Disable the given locations
|
||||
@@ -379,7 +379,7 @@ public interface DebuggerLogicalBreakpointService {
|
||||
* @param col the trace breakpoints
|
||||
* @return a future which completes when the command has been processed
|
||||
*/
|
||||
CompletableFuture<Void> disableLocs(Collection<TraceBreakpoint> col);
|
||||
CompletableFuture<Void> disableLocs(Collection<TraceBreakpointLocation> col);
|
||||
|
||||
/**
|
||||
* Delete the given locations
|
||||
@@ -387,7 +387,7 @@ public interface DebuggerLogicalBreakpointService {
|
||||
* @param col the trace breakpoints
|
||||
* @return a future which completes when the command has been processed
|
||||
*/
|
||||
CompletableFuture<Void> deleteLocs(Collection<TraceBreakpoint> col);
|
||||
CompletableFuture<Void> deleteLocs(Collection<TraceBreakpointLocation> col);
|
||||
|
||||
/**
|
||||
* Generate an informational message when toggling the breakpoints
|
||||
@@ -397,7 +397,8 @@ public interface DebuggerLogicalBreakpointService {
|
||||
* is for toggling breakpoints. If the breakpoint set is empty, this should return null, since
|
||||
* the usual behavior in that case is to prompt to place a new breakpoint.
|
||||
*
|
||||
* @see #generateStatusEnable(Collection, Trace))
|
||||
* @see #generateStatusEnable(Collection, Trace)
|
||||
* @param bs the set of logical breakpoints
|
||||
* @param loc a representative location
|
||||
* @return the status message, or null
|
||||
*/
|
||||
@@ -407,12 +408,12 @@ public interface DebuggerLogicalBreakpointService {
|
||||
* Generate an informational message when toggling the breakpoints at the given location
|
||||
*
|
||||
* <p>
|
||||
* This works in the same manner as {@link #generateStatusEnable(Collection, Trace))}, except it
|
||||
* This works in the same manner as {@link #generateStatusEnable(Collection, Trace)}, except it
|
||||
* is for toggling breakpoints at a given location. If there are no breakpoints at the location,
|
||||
* this should return null, since the usual behavior in that case is to prompt to place a new
|
||||
* breakpoint.
|
||||
*
|
||||
* @see #generateStatusEnable(Collection)
|
||||
* @see #generateStatusEnable(Collection, Trace)
|
||||
* @param loc the location
|
||||
* @return the status message, or null
|
||||
*/
|
||||
|
||||
@@ -38,8 +38,8 @@ public interface DebuggerPlatformService {
|
||||
* <p>
|
||||
* If the trace's current mapper is applicable to the object, it will be returned. Otherwise,
|
||||
* the service will query the opinions for a new mapper, as in
|
||||
* {@link #getNewMapper(TraceObject)} and set it as the current mapper before returning. If a
|
||||
* new mapper is set, the trace is also initialized for that mapper.
|
||||
* {@link #getNewMapper(Trace, TraceObject, long)} and set it as the current mapper before
|
||||
* returning. If a new mapper is set, the trace is also initialized for that mapper.
|
||||
*
|
||||
* @param trace the trace
|
||||
* @param object the object for which a mapper is desired
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -18,11 +18,11 @@ package ghidra.debug.api.action;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
|
||||
/**
|
||||
* The actual tracking logic for a location tracking spec
|
||||
@@ -73,8 +73,8 @@ public interface LocationTracker {
|
||||
* @param coordinates the provider's current coordinates
|
||||
* @return true if re-computation and "goto" is warranted
|
||||
*/
|
||||
boolean affectedByBytesChange(TraceAddressSpace space,
|
||||
TraceAddressSnapRange range, DebuggerCoordinates coordinates);
|
||||
boolean affectedByBytesChange(AddressSpace space, TraceAddressSnapRange range,
|
||||
DebuggerCoordinates coordinates);
|
||||
|
||||
/**
|
||||
* Check if the address should be recomputed given the indicated stack change
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -20,9 +20,8 @@ import javax.swing.Icon;
|
||||
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
|
||||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.framework.plugintool.AutoConfigState.ConfigFieldCodec;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.trace.model.TraceAddressSnapRange;
|
||||
import ghidra.trace.model.memory.TraceMemorySpace;
|
||||
import ghidra.trace.util.TraceAddressSpace;
|
||||
|
||||
/**
|
||||
* A specification for automatic navigation of the dynamic listing
|
||||
@@ -67,21 +66,13 @@ public interface LocationTrackingSpec {
|
||||
* @param current the current coordinates
|
||||
* @return true if the change affects the tracked address for the given coordinates
|
||||
*/
|
||||
static boolean changeIsCurrent(TraceAddressSpace space, TraceAddressSnapRange range,
|
||||
static boolean changeIsCurrent(AddressSpace space, TraceAddressSnapRange range,
|
||||
DebuggerCoordinates current) {
|
||||
if (space == null) {
|
||||
return false;
|
||||
}
|
||||
if (!space.getAddressSpace().isMemorySpace()) {
|
||||
if (current.getThread() == null) {
|
||||
return false;
|
||||
}
|
||||
TraceMemorySpace memSpace = current.getTrace()
|
||||
.getMemoryManager()
|
||||
.getMemoryRegisterSpace(current.getThread(), current.getFrame(), false);
|
||||
if (memSpace == null || memSpace.getAddressSpace() != space.getAddressSpace()) {
|
||||
return false;
|
||||
}
|
||||
if (!space.isMemorySpace() && !current.isRegisterSpace(space)) {
|
||||
return false;
|
||||
}
|
||||
if (!range.getLifespan().contains(current.getSnap())) {
|
||||
return false;
|
||||
|
||||
@@ -28,8 +28,8 @@ import ghidra.program.model.listing.Bookmark;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
import resources.MultiIcon;
|
||||
|
||||
/**
|
||||
@@ -471,6 +471,8 @@ public interface LogicalBreakpoint {
|
||||
*/
|
||||
INCONSISTENT_MIXED(Mode.MIXED, Consistency.INCONSISTENT, NAME_MARKER_INCON_MIX, ICON_MARKER_INCON_MIX);
|
||||
|
||||
public static final List<State> VALUES = List.of(values());
|
||||
|
||||
public final Mode mode;
|
||||
public final Consistency consistency;
|
||||
public final String display;
|
||||
@@ -540,7 +542,7 @@ public interface LogicalBreakpoint {
|
||||
Mode mode = this.mode.sameAddress(that.mode);
|
||||
Consistency consistency = this.consistency.sameAddress(that.consistency);
|
||||
return fromFields(mode, consistency);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* For logical breakpoints which appear at the same address, compose their state
|
||||
@@ -658,7 +660,7 @@ public interface LogicalBreakpoint {
|
||||
* Get the sleigh injection when emulating this breakpoint
|
||||
*
|
||||
* @return the sleigh injection
|
||||
* @see TraceBreakpoint#getEmuSleigh()
|
||||
* @see TraceBreakpointLocation#getEmuSleigh(long)
|
||||
*/
|
||||
String getEmuSleigh();
|
||||
|
||||
@@ -666,7 +668,7 @@ public interface LogicalBreakpoint {
|
||||
* Set the sleigh injection when emulating this breakpoint
|
||||
*
|
||||
* @param sleigh the sleigh injection
|
||||
* @see TraceBreakpoint#setEmuSleigh(String)
|
||||
* @see TraceBreakpointLocation#setEmuSleigh(long,String)
|
||||
*/
|
||||
void setEmuSleigh(String sleigh);
|
||||
|
||||
@@ -699,7 +701,7 @@ public interface LogicalBreakpoint {
|
||||
*
|
||||
* @return the set of trace breakpoints
|
||||
*/
|
||||
Set<TraceBreakpoint> getTraceBreakpoints();
|
||||
Set<TraceBreakpointLocation> getTraceBreakpoints();
|
||||
|
||||
/**
|
||||
* Get all trace breakpoints for the given trace which map to this logical breakpoint.
|
||||
@@ -707,15 +709,15 @@ public interface LogicalBreakpoint {
|
||||
* @param trace the trace
|
||||
* @return the set of trace breakpoints
|
||||
*/
|
||||
Set<TraceBreakpoint> getTraceBreakpoints(Trace trace);
|
||||
Set<TraceBreakpointLocation> getTraceBreakpoints(Trace trace);
|
||||
|
||||
/**
|
||||
* Get the traces for which this logical breakpoint has an address.
|
||||
*
|
||||
* <p>
|
||||
* Note, this does not necessarily indicate that a {@link TraceBreakpoint} is present for each
|
||||
* trace, but rather that for each returned trace, the logical breakpoint can be mapped to an
|
||||
* address in that trace. See {@link #getParticipatingTraces()}.
|
||||
* Note, this does not necessarily indicate that a {@link TraceBreakpointLocation} is present
|
||||
* for each trace, but rather that for each returned trace, the logical breakpoint can be mapped
|
||||
* to an address in that trace. See {@link #getParticipatingTraces()}.
|
||||
*
|
||||
* @return a copy of the set of traces
|
||||
*/
|
||||
@@ -725,8 +727,8 @@ public interface LogicalBreakpoint {
|
||||
* Get the traces for which this logical breakpoint has a trace breakpoint.
|
||||
*
|
||||
* <p>
|
||||
* Note, unlike {@link #getMappedTraces()}, this does indicate that a {@link TraceBreakpoint} is
|
||||
* present for each trace.
|
||||
* Note, unlike {@link #getMappedTraces()}, this does indicate that a
|
||||
* {@link TraceBreakpointLocation} is present for each trace.
|
||||
*
|
||||
* @return the set of traces
|
||||
*/
|
||||
@@ -779,7 +781,7 @@ public interface LogicalBreakpoint {
|
||||
* @param loc the location
|
||||
* @return the state
|
||||
*/
|
||||
State computeStateForLocation(TraceBreakpoint loc);
|
||||
State computeStateForLocation(TraceBreakpointLocation loc);
|
||||
|
||||
/**
|
||||
* Compute the state for all involved traces and program.
|
||||
|
||||
@@ -17,7 +17,7 @@ package ghidra.debug.api.breakpoint;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointLocation;
|
||||
|
||||
public interface LogicalBreakpointsChangeListener {
|
||||
default void breakpointAdded(LogicalBreakpoint added) {
|
||||
@@ -47,12 +47,12 @@ public interface LogicalBreakpointsChangeListener {
|
||||
}
|
||||
}
|
||||
|
||||
default void locationAdded(TraceBreakpoint added) {
|
||||
default void locationAdded(TraceBreakpointLocation added) {
|
||||
}
|
||||
|
||||
default void locationUpdated(TraceBreakpoint updated) {
|
||||
default void locationUpdated(TraceBreakpointLocation updated) {
|
||||
}
|
||||
|
||||
default void locationRemoved(TraceBreakpoint removed) {
|
||||
default void locationRemoved(TraceBreakpointLocation removed) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -15,19 +15,14 @@
|
||||
*/
|
||||
package ghidra.debug.api.emulation;
|
||||
|
||||
import ghidra.debug.api.target.Target;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.pcode.emu.PcodeMachine;
|
||||
import ghidra.pcode.exec.trace.TraceEmulationIntegration.Writer;
|
||||
import ghidra.util.classfinder.ExtensionPoint;
|
||||
|
||||
/**
|
||||
* A factory for configuring and creating a Debugger-integrated emulator
|
||||
*
|
||||
* <p>
|
||||
* See {@link BytesDebuggerPcodeEmulatorFactory} for the default implementation. See the Taint
|
||||
* Analyzer for the archetype of alternative implementations.
|
||||
*/
|
||||
public interface DebuggerPcodeEmulatorFactory extends ExtensionPoint {
|
||||
public interface EmulatorFactory extends ExtensionPoint {
|
||||
// TODO: Config options, use ModelFactory as a model
|
||||
|
||||
/**
|
||||
@@ -37,23 +32,12 @@ public interface DebuggerPcodeEmulatorFactory extends ExtensionPoint {
|
||||
*/
|
||||
String getTitle();
|
||||
|
||||
/**
|
||||
* Create the emulator
|
||||
*
|
||||
* @param tool the tool creating the emulator
|
||||
* @param platform the user's current trace platform from which the emulator should load state
|
||||
* @param snap the user's current snap from which the emulator should load state
|
||||
* @param target if applicable, the live target
|
||||
* @return the emulator
|
||||
*/
|
||||
DebuggerPcodeMachine<?> create(PluginTool tool, TracePlatform platform, long snap,
|
||||
Target target);
|
||||
|
||||
/**
|
||||
* Create the emulator
|
||||
*
|
||||
* @param access the trace-and-debugger access shim
|
||||
* @return the emulator
|
||||
* @param writer the Debugger's emulation callbacks for UI integration
|
||||
* @return the emulator with callbacks installed
|
||||
*/
|
||||
DebuggerPcodeMachine<?> create(PcodeDebuggerAccess access);
|
||||
PcodeMachine<?> create(PcodeDebuggerAccess access, Writer writer);
|
||||
}
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -26,8 +26,7 @@ import ghidra.trace.model.thread.TraceThread;
|
||||
* In addition to the trace "coordinates" encapsulated by {@link PcodeTraceAccess}, this
|
||||
* encapsulates the tool controlling a session and the session's target. This permits p-code
|
||||
* executor/emulator states to access target data and to access session data, e.g., data from mapped
|
||||
* static images. It supports the same method chain pattern as {@link PcodeTraceAccess}, but
|
||||
* starting with {@link DefaultPcodeDebuggerAccess}.
|
||||
* static images. It supports the same method chain pattern as {@link PcodeTraceAccess}.
|
||||
*/
|
||||
public interface PcodeDebuggerAccess extends PcodeTraceAccess {
|
||||
@Override
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -17,7 +17,7 @@ package ghidra.debug.api.emulation;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import ghidra.generic.util.datastruct.SemisparseByteArray;
|
||||
import ghidra.pcode.exec.PcodeExecutorStatePiece;
|
||||
import ghidra.pcode.exec.trace.data.PcodeTraceMemoryAccess;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSetView;
|
||||
@@ -53,11 +53,12 @@ public interface PcodeDebuggerMemoryAccess
|
||||
* image was relocated with fixups, reads at those fixups which fall through to static images
|
||||
* will be incorrect, and may lead to undefined behavior in the emulated program.
|
||||
*
|
||||
* @param bytes the destination byte store
|
||||
* @param piece the destination state piece
|
||||
* @param unknown the address set to read
|
||||
* @return true if any bytes were read, false if there was no effect
|
||||
* @return the parts of {@code unknown} that <em>still haven't</em> been read
|
||||
*/
|
||||
boolean readFromStaticImages(SemisparseByteArray bytes, AddressSetView unknown);
|
||||
AddressSetView readFromStaticImages(PcodeExecutorStatePiece<byte[], byte[]> piece,
|
||||
AddressSetView unknown);
|
||||
|
||||
/**
|
||||
* Instruct the associated recorder to write target memory
|
||||
|
||||
@@ -29,8 +29,7 @@ import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.TraceExecutionState;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpoint;
|
||||
import ghidra.trace.model.breakpoint.TraceBreakpointKind;
|
||||
import ghidra.trace.model.breakpoint.*;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.memory.TraceMemoryState;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
@@ -520,8 +519,10 @@ public interface Target {
|
||||
* be recorded into the trace <em>before</em> this method returns. If the request is
|
||||
* unsuccessful, this method throw an exception.
|
||||
*
|
||||
* @param address the starting address
|
||||
* @param data the bytes to write
|
||||
* @param platform the platform whose language defines the registers
|
||||
* @param thread the thread whose register to write
|
||||
* @param frame the frame level, usually 0.
|
||||
* @param value the register and value to write
|
||||
*/
|
||||
void writeRegister(TracePlatform platform, TraceThread thread, int frame, RegisterValue value);
|
||||
|
||||
@@ -549,7 +550,7 @@ public interface Target {
|
||||
* @param thread if a register, the thread whose registers to examine
|
||||
* @param frame the frame level, usually 0.
|
||||
* @param address the address of the variable
|
||||
* @param size the size of the variable. Ignored for memory
|
||||
* @param length the size of the variable. Ignored for memory
|
||||
* @return true if the variable can be mapped to the target
|
||||
*/
|
||||
boolean isVariableExists(TracePlatform platform, TraceThread thread, int frame, Address address,
|
||||
@@ -559,8 +560,7 @@ public interface Target {
|
||||
* @see #writeVariable(TracePlatform, TraceThread, int, Address, byte[])
|
||||
*/
|
||||
CompletableFuture<Void> writeVariableAsync(TracePlatform platform, TraceThread thread,
|
||||
int frame,
|
||||
Address address, byte[] data);
|
||||
int frame, Address address, byte[] data);
|
||||
|
||||
/**
|
||||
* Write a variable (memory or register) of the given thread or the process
|
||||
@@ -572,7 +572,7 @@ public interface Target {
|
||||
* {@link #writeMemory(Address, byte[])}.
|
||||
*
|
||||
* @param thread the thread. Ignored (may be null) if address is in memory
|
||||
* @param frameLevel the frame, usually 0. Ignored if address is in memory
|
||||
* @param frame the frame, usually 0. Ignored if address is in memory
|
||||
* @param address the starting address
|
||||
* @param data the value to write
|
||||
*/
|
||||
@@ -617,12 +617,12 @@ public interface Target {
|
||||
* @param breakpoint the breakpoint
|
||||
* @return true if valid
|
||||
*/
|
||||
boolean isBreakpointValid(TraceBreakpoint breakpoint);
|
||||
boolean isBreakpointValid(TraceBreakpointLocation breakpoint);
|
||||
|
||||
/**
|
||||
* @see #deleteBreakpoint(TraceBreakpoint)
|
||||
* @see #deleteBreakpoint(TraceBreakpointCommon)
|
||||
*/
|
||||
CompletableFuture<Void> deleteBreakpointAsync(TraceBreakpoint breakpoint);
|
||||
CompletableFuture<Void> deleteBreakpointAsync(TraceBreakpointCommon breakpoint);
|
||||
|
||||
/**
|
||||
* Delete the given breakpoint from the target
|
||||
@@ -633,12 +633,13 @@ public interface Target {
|
||||
*
|
||||
* @param breakpoint the breakpoint to delete
|
||||
*/
|
||||
void deleteBreakpoint(TraceBreakpoint breakpoint);
|
||||
void deleteBreakpoint(TraceBreakpointCommon breakpoint);
|
||||
|
||||
/**
|
||||
* @see #toggleBreakpoint(TraceBreakpoint, boolean)
|
||||
* @see #toggleBreakpoint(TraceBreakpointLocation, boolean)
|
||||
*/
|
||||
CompletableFuture<Void> toggleBreakpointAsync(TraceBreakpoint breakpoint, boolean enabled);
|
||||
CompletableFuture<Void> toggleBreakpointAsync(TraceBreakpointCommon breakpoint,
|
||||
boolean enabled);
|
||||
|
||||
/**
|
||||
* Toggle the given breakpoint on the target
|
||||
@@ -651,7 +652,7 @@ public interface Target {
|
||||
* @param breakpoint the breakpoint to toggle
|
||||
* @param enabled true to enable, false to disable
|
||||
*/
|
||||
void toggleBreakpoint(TraceBreakpoint breakpoint, boolean enabled);
|
||||
void toggleBreakpoint(TraceBreakpointCommon breakpoint, boolean enabled);
|
||||
|
||||
/**
|
||||
* @see #forceTerminate()
|
||||
@@ -665,7 +666,8 @@ public interface Target {
|
||||
* This will first attempt to kill the target gracefully. In addition, and whether or not the
|
||||
* target is successfully terminated, the target will be dissociated from its trace, and the
|
||||
* target will be invalidated. To attempt only a graceful termination, check
|
||||
* {@link #collectActions(ActionName, ActionContext)} with {@link ActionName#KILL}.
|
||||
* {@link #collectActions(ActionName, ActionContext, ObjectArgumentPolicy)} with
|
||||
* {@link ActionName#KILL}.
|
||||
*/
|
||||
void forceTerminate();
|
||||
|
||||
|
||||
@@ -27,15 +27,17 @@ import ghidra.framework.model.*;
|
||||
import ghidra.framework.options.SaveState;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.framework.store.LockException;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.trace.database.DBTraceContentHandler;
|
||||
import ghidra.trace.model.Lifespan;
|
||||
import ghidra.trace.model.Trace;
|
||||
import ghidra.trace.model.guest.TracePlatform;
|
||||
import ghidra.trace.model.program.TraceProgramView;
|
||||
import ghidra.trace.model.stack.*;
|
||||
import ghidra.trace.model.stack.TraceStack;
|
||||
import ghidra.trace.model.stack.TraceStackFrame;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.thread.TraceObjectThread;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.TraceSnapshot;
|
||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||
@@ -47,7 +49,6 @@ public class DebuggerCoordinates {
|
||||
|
||||
/**
|
||||
* Coordinates that indicate no trace is active in the Debugger UI.
|
||||
*
|
||||
* <p>
|
||||
* Typically, that only happens when no trace is open. Telling the trace manager to activate
|
||||
* {@code NOWHERE} will cause it to instead activate the most recently active trace, which may
|
||||
@@ -315,36 +316,34 @@ public class DebuggerCoordinates {
|
||||
return thread(trace.getThreadManager().getThread(thread.getKey()));
|
||||
}
|
||||
|
||||
private static KeyPath resolvePath(TraceThread thread, Integer frameLevel,
|
||||
TraceSchedule time) {
|
||||
if (thread instanceof TraceObjectThread tot) {
|
||||
TraceObject objThread = tot.getObject();
|
||||
if (frameLevel == null) {
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
TraceStack stack;
|
||||
long snap = time.getSnap();
|
||||
try {
|
||||
stack = thread.getTrace().getStackManager().getStack(thread, snap, false);
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
// Schema does not specify a stack
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
if (stack == null) {
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
TraceStackFrame frame = stack.getFrame(snap, frameLevel, false);
|
||||
if (frame == null) {
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
return ((TraceObjectStackFrame) frame).getObject().getCanonicalPath();
|
||||
private static KeyPath resolvePath(TraceThread thread, Integer frameLevel, TraceSchedule time) {
|
||||
if (thread == null) {
|
||||
return KeyPath.of();
|
||||
}
|
||||
return null;
|
||||
TraceObject objThread = thread.getObject();
|
||||
if (frameLevel == null) {
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
TraceStack stack;
|
||||
long snap = time.getSnap();
|
||||
try {
|
||||
stack = thread.getTrace().getStackManager().getStack(thread, snap, false);
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
// Schema does not specify a stack
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
if (stack == null) {
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
TraceStackFrame frame = stack.getFrame(snap, frameLevel, false);
|
||||
if (frame == null) {
|
||||
return objThread.getCanonicalPath();
|
||||
}
|
||||
return frame.getObject().getCanonicalPath();
|
||||
}
|
||||
|
||||
private static KeyPath choose(KeyPath curPath,
|
||||
KeyPath newPath) {
|
||||
private static KeyPath choose(KeyPath curPath, KeyPath newPath) {
|
||||
if (curPath == null) {
|
||||
return newPath;
|
||||
}
|
||||
@@ -525,9 +524,7 @@ public class DebuggerCoordinates {
|
||||
if (object == null) {
|
||||
return null;
|
||||
}
|
||||
return object.queryCanonicalAncestorsInterface(TraceObjectThread.class)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
return object.queryCanonicalAncestorsInterface(TraceThread.class).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
private static Integer resolveFrame(Trace trace, KeyPath path) {
|
||||
@@ -535,10 +532,9 @@ public class DebuggerCoordinates {
|
||||
if (object == null) {
|
||||
return null;
|
||||
}
|
||||
TraceObjectStackFrame frame =
|
||||
object.queryCanonicalAncestorsInterface(TraceObjectStackFrame.class)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
TraceStackFrame frame = object.queryCanonicalAncestorsInterface(TraceStackFrame.class)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
return frame == null ? null : frame.getLevel();
|
||||
}
|
||||
|
||||
@@ -613,6 +609,10 @@ public class DebuggerCoordinates {
|
||||
return platform;
|
||||
}
|
||||
|
||||
public Language getLanguage() {
|
||||
return platform == null ? null : platform.getLanguage();
|
||||
}
|
||||
|
||||
public Target getTarget() {
|
||||
return target;
|
||||
}
|
||||
@@ -669,6 +669,11 @@ public class DebuggerCoordinates {
|
||||
return registerContainer = object.findRegisterContainer(getFrame());
|
||||
}
|
||||
|
||||
public boolean isRegisterSpace(AddressSpace space) {
|
||||
TraceObject container = getRegisterContainer();
|
||||
return container != null && container.getCanonicalPath().toString().equals(space.getName());
|
||||
}
|
||||
|
||||
public synchronized long getViewSnap() {
|
||||
if (viewSnap != null) {
|
||||
return viewSnap;
|
||||
|
||||
@@ -117,7 +117,7 @@ public interface RemoteMethod {
|
||||
* Check the type of an argument.
|
||||
*
|
||||
* <p>
|
||||
* This is a hack, because {@link TraceObjectSchema} expects {@link TargetObject}, or a
|
||||
* This is a hack, because {@link TraceObjectSchema} expects {@link TraceObject}, or a
|
||||
* primitive. We instead need {@link TraceObject}. I'd add the method to the schema, except that
|
||||
* trace stuff is not in its dependencies.
|
||||
*
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -34,6 +34,7 @@ public interface TraceRmiAcceptor {
|
||||
*
|
||||
* @return the connection, if successful
|
||||
* @throws IOException if there was an error
|
||||
* @throws CancelledException if {@link #cancel()} is called, usually from the user canceling
|
||||
*/
|
||||
TraceRmiConnection accept() throws IOException, CancelledException;
|
||||
|
||||
@@ -64,8 +65,8 @@ public interface TraceRmiAcceptor {
|
||||
*
|
||||
* <p>
|
||||
* If a different thread has called {@link #accept()}, it will fail. In this case, both
|
||||
* {@linkplain TraceRmiServiceListener#acceptCancelled(TraceRmiAcceptor)} and
|
||||
* {@linkplain TraceRmiServiceListener#acceptFailed(Exception)} may be invoked.
|
||||
* {@link TraceRmiServiceListener#acceptCancelled(TraceRmiAcceptor)} and
|
||||
* {@link TraceRmiServiceListener#acceptFailed(TraceRmiAcceptor, Exception)} may be invoked.
|
||||
*/
|
||||
void cancel();
|
||||
}
|
||||
|
||||
@@ -86,8 +86,9 @@ public interface TraceRmiServiceListener {
|
||||
*
|
||||
* <p>
|
||||
* The acceptor remains valid until one of three events occurs:
|
||||
* {@linkplain} #connected(TraceRmiConnection, ConnectMode, TraceRmiAcceptor)},
|
||||
* {@linkplain} #acceptCancelled(TraceRmiAcceptor)}, or {@linkplain} #acceptFailed(Exception)}.
|
||||
* {@link #connected(TraceRmiConnection, ConnectMode, TraceRmiAcceptor)},
|
||||
* {@link #acceptCancelled(TraceRmiAcceptor)}, or
|
||||
* {@link #acceptFailed(TraceRmiAcceptor, Exception)}.
|
||||
*
|
||||
* @param acceptor the acceptor waiting
|
||||
*/
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -230,4 +230,18 @@ public interface WatchRow {
|
||||
* @return true if the value changed, false otherwise.
|
||||
*/
|
||||
boolean isChanged();
|
||||
|
||||
/**
|
||||
* Get the user-defined comment for this row
|
||||
*
|
||||
* @return the comment
|
||||
*/
|
||||
String getComment();
|
||||
|
||||
/**
|
||||
* Set the user-defined comment for this row
|
||||
*
|
||||
* @param comment the comment
|
||||
*/
|
||||
void setComment(String comment);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@ import ghidra.trace.model.program.TraceProgramView;
|
||||
import ghidra.trace.model.target.TraceObject;
|
||||
import ghidra.trace.model.target.TraceObjectValue;
|
||||
import ghidra.trace.model.target.path.KeyPath;
|
||||
import ghidra.trace.model.thread.TraceObjectThread;
|
||||
import ghidra.trace.model.thread.TraceThread;
|
||||
import ghidra.trace.model.time.schedule.TraceSchedule;
|
||||
import ghidra.util.MathUtilities;
|
||||
@@ -1452,11 +1451,7 @@ public interface FlatDebuggerAPI {
|
||||
}
|
||||
|
||||
default ActionContext createContext(TraceThread thread) {
|
||||
if (thread instanceof TraceObjectThread objThread) {
|
||||
return createContext(objThread.getObject());
|
||||
}
|
||||
return new DebuggerSingleObjectPathActionContext(
|
||||
KeyPath.parse(thread.getPath()));
|
||||
return createContext(thread.getObject());
|
||||
}
|
||||
|
||||
default ActionContext createContext(Trace trace) {
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -98,6 +98,7 @@ public abstract class AbstractIsfWriter implements Closeable {
|
||||
gson.toJson(object, writer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (writer != null) {
|
||||
writer.flush();
|
||||
|
||||
@@ -86,8 +86,9 @@ public class JavaTraceRmiLaunchOffer extends AbstractScriptTraceRmiLaunchOffer {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void launchBackEnd(TaskMonitor monitor, Map<String, TerminalSession> sessions,
|
||||
Map<String, ValStr<?>> args, SocketAddress address) throws Exception {
|
||||
protected TraceRmiBackEnd launchBackEnd(TaskMonitor monitor,
|
||||
Map<String, TerminalSession> sessions, Map<String, ValStr<?>> args,
|
||||
SocketAddress address) throws Exception {
|
||||
List<String> commandLine = new ArrayList<>();
|
||||
Map<String, String> env = new HashMap<>(System.getenv());
|
||||
prepareSubprocess(commandLine, env, args, address);
|
||||
@@ -101,18 +102,28 @@ public class JavaTraceRmiLaunchOffer extends AbstractScriptTraceRmiLaunchOffer {
|
||||
sessions.put(ns.name(), ns);
|
||||
}
|
||||
|
||||
TraceRmiBackEnd result = new TraceRmiBackEnd();
|
||||
if (hasKeyReally(env, "OPT_JSHELL_PATH")) {
|
||||
String classPath = computeClassPath(env);
|
||||
commandLine.add(0, "--startup");
|
||||
commandLine.add(0, "--class-path=" + classPath);
|
||||
commandLine.add(0, env.get("OPT_JSHELL_PATH"));
|
||||
sessions.put("Shell",
|
||||
runInTerminal(commandLine, env, script.getParentFile(), sessions.values()));
|
||||
PtyTerminalSession session =
|
||||
runInTerminal(commandLine, env, script.getParentFile(), sessions.values());
|
||||
sessions.put("Shell", session);
|
||||
session.terminal().addTerminalListener(result);
|
||||
}
|
||||
else {
|
||||
JdiClientThread thread = new JdiClientThread(env);
|
||||
JdiClientThread thread = new JdiClientThread(env) {
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
result.terminated(0);
|
||||
}
|
||||
};
|
||||
thread.start();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String computeClassPath(Map<String, String> env) {
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.Map;
|
||||
import com.sun.jdi.*;
|
||||
|
||||
import ghidra.app.plugin.core.debug.client.tracermi.*;
|
||||
import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceMethod;
|
||||
import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceRmiMethod;
|
||||
import ghidra.dbg.jdi.manager.impl.DebugStatus;
|
||||
import ghidra.dbg.jdi.manager.impl.JdiManagerImpl;
|
||||
import ghidra.program.model.address.*;
|
||||
@@ -144,7 +144,7 @@ public class JdiConnector {
|
||||
}
|
||||
|
||||
public void registerRemoteMethod(JdiMethods methods, java.lang.reflect.Method m, String name) {
|
||||
TraceMethod annot = m.getAnnotation(TraceMethod.class);
|
||||
TraceRmiMethod annot = m.getAnnotation(TraceRmiMethod.class);
|
||||
if (annot == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@ import com.sun.jdi.*;
|
||||
import com.sun.jdi.request.*;
|
||||
|
||||
import ghidra.app.plugin.core.debug.client.tracermi.*;
|
||||
import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceMethod;
|
||||
import ghidra.app.plugin.core.debug.client.tracermi.RmiMethodRegistry.TraceRmiMethod;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
import ghidra.rmi.trace.TraceRmi.MemoryState;
|
||||
import ghidra.trace.model.target.iface.TraceObjectMethod.Param;
|
||||
import ghidra.trace.model.target.iface.TraceMethod.Param;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
public class JdiMethods implements RmiMethods {
|
||||
@@ -45,14 +45,14 @@ public class JdiMethods implements RmiMethods {
|
||||
public void registerMethods() {
|
||||
Class<?> cls = this.getClass();
|
||||
for (java.lang.reflect.Method m : cls.getMethods()) {
|
||||
TraceMethod annot = m.getAnnotation(TraceMethod.class);
|
||||
TraceRmiMethod annot = m.getAnnotation(TraceRmiMethod.class);
|
||||
if (annot != null) {
|
||||
connector.registerRemoteMethod(this, m, m.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh VM")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh VM")
|
||||
public void refresh_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVM")) {
|
||||
String path = obj.getPath();
|
||||
@@ -61,7 +61,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh process")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh process")
|
||||
public void refresh_process(
|
||||
@Param(schema = "ProcessRef", name = "process") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshProcess")) {
|
||||
@@ -71,7 +71,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh thread groups")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh thread groups")
|
||||
public void refresh_thread_groups(
|
||||
@Param(
|
||||
schema = "ThreadGroupReferenceContainer",
|
||||
@@ -89,7 +89,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh thread group")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh thread group")
|
||||
public void refresh_thread_group_proxy(
|
||||
@Param(schema = "ThreadGroupReferenceProxy", name = "proxy") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreadGroup")) {
|
||||
@@ -105,7 +105,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh thread group")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh thread group")
|
||||
public void refresh_thread_group(
|
||||
@Param(schema = "ThreadGroupReference", name = "group") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreadGroup")) {
|
||||
@@ -115,7 +115,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh threads")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh threads")
|
||||
public void refresh_threads(
|
||||
@Param(schema = "ThreadContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreads")) {
|
||||
@@ -126,7 +126,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh threads")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh threads")
|
||||
public void refresh_threadrefs(
|
||||
@Param(schema = "ThreadReferenceContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThreads")) {
|
||||
@@ -147,7 +147,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh thread")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh thread")
|
||||
public void refresh_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshThread")) {
|
||||
String path = obj.getPath();
|
||||
@@ -156,14 +156,14 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh stack")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh stack")
|
||||
public void refresh_stack(@Param(schema = "Stack", name = "stack") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshStack")) {
|
||||
cmds.ghidraTracePutFrames();
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh registers")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh registers")
|
||||
public void refresh_registers(
|
||||
@Param(schema = "RegisterContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshRegisters")) {
|
||||
@@ -171,7 +171,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh modules")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh modules")
|
||||
public void refresh_modules(
|
||||
@Param(schema = "ModuleReferenceContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshModules")) {
|
||||
@@ -179,7 +179,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh module")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh module")
|
||||
public void refresh_module(
|
||||
@Param(schema = "ModuleReference", name = "module") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshModule")) {
|
||||
@@ -189,7 +189,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh monitor info")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh monitor info")
|
||||
public void refresh_monitors(
|
||||
@Param(schema = "MonitorInfoContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMonitorInfo")) {
|
||||
@@ -203,7 +203,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh monitor info")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh monitor info")
|
||||
public void refresh_monitor_info(
|
||||
@Param(schema = "MonitorInfo", name = "monitor_info") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMonitorInfo")) {
|
||||
@@ -213,13 +213,13 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh fields")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh fields")
|
||||
public void refresh_canonical_fields(
|
||||
@Param(schema = "CanonicalFieldContainer", name = "container") RmiTraceObject obj) {
|
||||
refresh_fields(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh fields")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh fields")
|
||||
public void refresh_fields(
|
||||
@Param(schema = "FieldContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshFields")) {
|
||||
@@ -235,7 +235,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh objects")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh objects")
|
||||
public void refresh_objects(
|
||||
@Param(schema = "ObjectReferenceContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshObjects")) {
|
||||
@@ -261,7 +261,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh object")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh object")
|
||||
public void refresh_object_proxy(
|
||||
@Param(schema = "ObjectReferenceProxy", name = "proxy") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshObject")) {
|
||||
@@ -283,7 +283,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh object")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh object")
|
||||
public void refresh_object(
|
||||
@Param(schema = "ObjectReference", name = "object") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshInstance")) {
|
||||
@@ -293,13 +293,13 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh methods")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh methods")
|
||||
public void refresh_canonical_methods(
|
||||
@Param(schema = "CanonicalMethodContainer", name = "container") RmiTraceObject obj) {
|
||||
refresh_methods(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh methods")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh methods")
|
||||
public void refresh_methods(
|
||||
@Param(schema = "MethodContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMethods")) {
|
||||
@@ -310,7 +310,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh method")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh method")
|
||||
public void refresh_method(@Param(schema = "Method", name = "method") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshMethod")) {
|
||||
String path = obj.getPath();
|
||||
@@ -319,7 +319,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh arguments")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh arguments")
|
||||
public void refresh_arguments(
|
||||
@Param(schema = "ArgumentContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshArguments")) {
|
||||
@@ -330,7 +330,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Load class")
|
||||
@TraceRmiMethod(display = "Load class")
|
||||
public boolean find_canonical_class(
|
||||
@Param(
|
||||
schema = "CanonicalReferenceTypeContainer",
|
||||
@@ -344,7 +344,7 @@ public class JdiMethods implements RmiMethods {
|
||||
return find_class(obj, targetClass);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Load class")
|
||||
@TraceRmiMethod(display = "Load class")
|
||||
public boolean find_class(
|
||||
@Param(
|
||||
schema = "ReferenceTypeContainer",
|
||||
@@ -370,12 +370,12 @@ public class JdiMethods implements RmiMethods {
|
||||
* NB. Did not assign action="refresh" because this method is expensive. Assigning that action
|
||||
* name will cause the UI to do it upon expanding the node, which we <em>do not</em> want.
|
||||
*/
|
||||
@TraceMethod(display = "Refresh memory")
|
||||
@TraceRmiMethod(display = "Refresh memory")
|
||||
public void refresh_memory(@Param(schema = "Memory", name = "memory") RmiTraceObject obj) {
|
||||
refresh_reference_types(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Refresh reference types")
|
||||
@TraceRmiMethod(display = "Refresh reference types")
|
||||
public void refresh_canonical_reference_types(
|
||||
@Param(
|
||||
schema = "CanonicalReferenceTypeContainer",
|
||||
@@ -387,7 +387,7 @@ public class JdiMethods implements RmiMethods {
|
||||
* NB. Did not assign action="refresh" because this method is expensive. Assigning that action
|
||||
* name will cause the UI to do it upon expanding the node, which we <em>do not</em> want.
|
||||
*/
|
||||
@TraceMethod(display = "Refresh reference types")
|
||||
@TraceRmiMethod(display = "Refresh reference types")
|
||||
public void refresh_reference_types(
|
||||
@Param(schema = "ReferenceTypeContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceTypes")) {
|
||||
@@ -430,7 +430,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh reference type")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh reference type")
|
||||
public void refresh_reference_type_proxy(
|
||||
@Param(schema = "ReferenceTypeProxy", name = "proxy") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) {
|
||||
@@ -452,13 +452,13 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh reference type")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh reference type")
|
||||
public void refresh_canonical_reference_type(
|
||||
@Param(schema = "CanonicalReferenceType", name = "container") RmiTraceObject obj) {
|
||||
refresh_reference_type(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh reference type")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh reference type")
|
||||
public void refresh_reference_type(
|
||||
@Param(schema = "ReferenceType", name = "reference_type") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) {
|
||||
@@ -468,7 +468,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Load reference type")
|
||||
@TraceRmiMethod(display = "Load reference type")
|
||||
public void load_reftype(
|
||||
@Param(schema = "ReferenceType", name = "reference_type") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshReferenceType")) {
|
||||
@@ -480,13 +480,13 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh variables")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh variables")
|
||||
public void refresh_canonical_variables(
|
||||
@Param(schema = "CanonicalVariableContainer", name = "container") RmiTraceObject obj) {
|
||||
refresh_variables(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh variables")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh variables")
|
||||
public void refresh_variables(
|
||||
@Param(schema = "VariableContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVariables")) {
|
||||
@@ -513,7 +513,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh variable")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh variable")
|
||||
public void refresh_variable(
|
||||
@Param(schema = "Variable", name = "variable") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshVariable")) {
|
||||
@@ -525,7 +525,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh locations")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh locations")
|
||||
public void refresh_locations(
|
||||
@Param(schema = "LocationContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocations")) {
|
||||
@@ -543,7 +543,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh location")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh location")
|
||||
public void refresh_location(
|
||||
@Param(schema = "Location", name = "location") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocation")) {
|
||||
@@ -553,7 +553,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh breakpoints")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh breakpoints")
|
||||
public void refresh_breakpoints(
|
||||
@Param(schema = "BreakpointContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshBreakpoints")) {
|
||||
@@ -561,7 +561,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh events")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh events")
|
||||
public void refresh_events(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshEvents")) {
|
||||
@@ -569,7 +569,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh values")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh values")
|
||||
public void refresh_values(
|
||||
@Param(schema = "ValueContainer", name = "container") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshValues")) {
|
||||
@@ -582,7 +582,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "refresh", display = "Refresh value")
|
||||
@TraceRmiMethod(action = "refresh", display = "Refresh value")
|
||||
public void refresh_value(@Param(schema = "Value", name = "value") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("RefreshLocation")) {
|
||||
String path = obj.getPath();
|
||||
@@ -591,7 +591,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Set value")
|
||||
@TraceRmiMethod(display = "Set value")
|
||||
public void set_value_lvar(
|
||||
@Param(
|
||||
schema = "Variable",
|
||||
@@ -609,7 +609,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Set value")
|
||||
@TraceRmiMethod(display = "Set value")
|
||||
public void set_value_field(
|
||||
@Param(
|
||||
schema = "Field",
|
||||
@@ -627,7 +627,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "activate", display = "Activate")
|
||||
@TraceRmiMethod(action = "activate", display = "Activate")
|
||||
public void activate(@Param(schema = "OBJECT", name = "object") RmiTraceObject obj) {
|
||||
try (RmiTransaction tx = cmds.state.trace.openTx("Activate")) {
|
||||
String path = obj.getPath();
|
||||
@@ -635,7 +635,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "kill", display = "Terminate")
|
||||
@TraceRmiMethod(action = "kill", display = "Terminate")
|
||||
public void kill(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath());
|
||||
vm.exit(143);
|
||||
@@ -647,28 +647,28 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "resume", display = "Resume")
|
||||
@TraceRmiMethod(action = "resume", display = "Resume")
|
||||
public void resume_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath());
|
||||
vm.resume();
|
||||
connector.getHooks().setState(vm);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "resume", display = "Resume")
|
||||
@TraceRmiMethod(action = "resume", display = "Resume")
|
||||
public void resume_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
|
||||
thread.resume();
|
||||
connector.getHooks().setState(thread.virtualMachine());
|
||||
}
|
||||
|
||||
@TraceMethod(action = "interrupt", display = "Suspend")
|
||||
@TraceRmiMethod(action = "interrupt", display = "Suspend")
|
||||
public void suspend_vm(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
VirtualMachine vm = (VirtualMachine) getObjectFromPath(obj.getPath());
|
||||
vm.suspend();
|
||||
connector.getHooks().setState(vm);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "interrupt", display = "Suspend")
|
||||
@TraceRmiMethod(action = "interrupt", display = "Suspend")
|
||||
public void suspend_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
|
||||
thread.suspend();
|
||||
@@ -679,7 +679,7 @@ public class JdiMethods implements RmiMethods {
|
||||
* NB: For the VirtualMachine, the step methods add requests for break-on-step for all threads.
|
||||
* These requests will remain pending until the VM is resumed.
|
||||
*/
|
||||
@TraceMethod(action = "step_into", display = "Step into")
|
||||
@TraceRmiMethod(action = "step_into", display = "Step into")
|
||||
public void step_vm_into(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
List<ThreadReference> threads = getThreadsFromValue(obj);
|
||||
@@ -697,7 +697,7 @@ public class JdiMethods implements RmiMethods {
|
||||
vm.resume();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "step_over", display = "Step over")
|
||||
@TraceRmiMethod(action = "step_over", display = "Step over")
|
||||
public void step_vm_over(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
List<ThreadReference> threads = getThreadsFromValue(obj);
|
||||
@@ -715,7 +715,7 @@ public class JdiMethods implements RmiMethods {
|
||||
vm.resume();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "step_out", display = "Step out")
|
||||
@TraceRmiMethod(action = "step_out", display = "Step out")
|
||||
public void step_vm_out(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
List<ThreadReference> threads = getThreadsFromValue(obj);
|
||||
@@ -733,7 +733,7 @@ public class JdiMethods implements RmiMethods {
|
||||
vm.resume();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "step_into", display = "Step into")
|
||||
@TraceRmiMethod(action = "step_into", display = "Step into")
|
||||
public void step_into(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
|
||||
@@ -744,7 +744,7 @@ public class JdiMethods implements RmiMethods {
|
||||
vm.resume();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "step_over", display = "Step over")
|
||||
@TraceRmiMethod(action = "step_over", display = "Step over")
|
||||
public void step_over(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
|
||||
@@ -755,7 +755,7 @@ public class JdiMethods implements RmiMethods {
|
||||
vm.resume();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "step_out", display = "Step out")
|
||||
@TraceRmiMethod(action = "step_out", display = "Step out")
|
||||
public void step_out(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
ThreadReference thread = (ThreadReference) getObjectFromPath(obj.getPath());
|
||||
@@ -766,7 +766,7 @@ public class JdiMethods implements RmiMethods {
|
||||
vm.resume();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Thread Interrupt")
|
||||
@TraceRmiMethod(display = "Thread Interrupt")
|
||||
public void thread_interrupt(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
Object object = getObjectFromPath(obj.getPath());
|
||||
if (object instanceof ThreadReference thread) {
|
||||
@@ -775,7 +775,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "step_ext", display = "Pop stack")
|
||||
@TraceRmiMethod(action = "step_ext", display = "Pop stack")
|
||||
public void pop_stack(@Param(schema = "StackFrame", name = "frame") RmiTraceObject obj) {
|
||||
StackFrame frame = (StackFrame) getObjectFromPath(obj.getPath());
|
||||
ThreadReference thread = frame.thread();
|
||||
@@ -787,7 +787,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on execute")
|
||||
@TraceRmiMethod(display = "Break on execute")
|
||||
public void break_location(@Param(schema = "Location", name = "location") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
Object ctxt = getObjectFromPath(obj.getPath());
|
||||
@@ -799,7 +799,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on access")
|
||||
@TraceRmiMethod(display = "Break on access")
|
||||
public void break_access(@Param(schema = "Field", name = "field") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
Object ctxt = getObjectFromPath(obj.getPath());
|
||||
@@ -811,7 +811,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on modify")
|
||||
@TraceRmiMethod(display = "Break on modify")
|
||||
public void break_modify(@Param(schema = "Field", name = "field") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
Object ctxt = getObjectFromPath(obj.getPath());
|
||||
@@ -823,7 +823,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on exception")
|
||||
@TraceRmiMethod(display = "Break on exception")
|
||||
public void break_exception(
|
||||
@Param(
|
||||
schema = "ReferenceType",
|
||||
@@ -861,13 +861,13 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on thread start")
|
||||
@TraceRmiMethod(display = "Break on thread start")
|
||||
public void break_started_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_started(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on thread start")
|
||||
@TraceRmiMethod(display = "Break on thread start")
|
||||
public void break_started_thread(
|
||||
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_started(obj);
|
||||
@@ -886,18 +886,18 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on thread exit")
|
||||
@TraceRmiMethod(display = "Break on thread exit")
|
||||
public void break_death_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_death(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on thread exit")
|
||||
@TraceRmiMethod(display = "Break on thread exit")
|
||||
public void break_death_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_death(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on VM death")
|
||||
@TraceRmiMethod(display = "Break on VM death")
|
||||
public void break_vm_death(@Param(schema = "VirtualMachine", name = "vm") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
VMDeathRequest brkReq = vm.eventRequestManager()
|
||||
@@ -927,25 +927,25 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method enter")
|
||||
@TraceRmiMethod(display = "Break on method enter")
|
||||
public void break_enter_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_enter(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method enter")
|
||||
@TraceRmiMethod(display = "Break on method enter")
|
||||
public void break_enter_reftype(
|
||||
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
|
||||
break_enter(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method enter")
|
||||
@TraceRmiMethod(display = "Break on method enter")
|
||||
public void break_enter_instance(
|
||||
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
|
||||
break_enter(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method enter")
|
||||
@TraceRmiMethod(display = "Break on method enter")
|
||||
public void break_enter_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_enter(obj);
|
||||
}
|
||||
@@ -971,25 +971,25 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method exit")
|
||||
@TraceRmiMethod(display = "Break on method exit")
|
||||
public void break_exit_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_exit(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method exit")
|
||||
@TraceRmiMethod(display = "Break on method exit")
|
||||
public void break_exit_reftype(
|
||||
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
|
||||
break_exit(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method exit")
|
||||
@TraceRmiMethod(display = "Break on method exit")
|
||||
public void break_exit_instance(
|
||||
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
|
||||
break_exit(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on method exit")
|
||||
@TraceRmiMethod(display = "Break on method exit")
|
||||
public void break_exit_thread(@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_exit(obj);
|
||||
}
|
||||
@@ -1007,13 +1007,13 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on class load")
|
||||
@TraceRmiMethod(display = "Break on class load")
|
||||
public void break_load_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_load(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on class load")
|
||||
@TraceRmiMethod(display = "Break on class load")
|
||||
public void break_load_reftype(
|
||||
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
|
||||
break_load(obj);
|
||||
@@ -1027,7 +1027,7 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on class unload")
|
||||
@TraceRmiMethod(display = "Break on class unload")
|
||||
public void break_unload_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_unload(obj);
|
||||
@@ -1054,25 +1054,25 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contended enter")
|
||||
@TraceRmiMethod(display = "Break on monitor contended enter")
|
||||
public void break_mon_enter_contention_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_mon_enter_contention(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contended enter")
|
||||
@TraceRmiMethod(display = "Break on monitor contended enter")
|
||||
public void break_mon_enter_contention_reftype(
|
||||
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
|
||||
break_mon_enter_contention(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contended enter")
|
||||
@TraceRmiMethod(display = "Break on monitor contended enter")
|
||||
public void break_mon_enter_contention_instance(
|
||||
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
|
||||
break_mon_enter_contention(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contended enter")
|
||||
@TraceRmiMethod(display = "Break on monitor contended enter")
|
||||
public void break_mon_enter_contention_thread(
|
||||
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_mon_enter_contention(obj);
|
||||
@@ -1099,25 +1099,25 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contented entered")
|
||||
@TraceRmiMethod(display = "Break on monitor contented entered")
|
||||
public void break_mon_entered_contention_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_mon_entered_contention(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contented entered")
|
||||
@TraceRmiMethod(display = "Break on monitor contented entered")
|
||||
public void break_mon_entered_contention_reftype(
|
||||
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
|
||||
break_mon_entered_contention(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contented entered")
|
||||
@TraceRmiMethod(display = "Break on monitor contented entered")
|
||||
public void break_mon_entered_contention_instance(
|
||||
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
|
||||
break_mon_entered_contention(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor contented entered")
|
||||
@TraceRmiMethod(display = "Break on monitor contented entered")
|
||||
public void break_mon_entered_contention_thread(
|
||||
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_mon_entered_contention(obj);
|
||||
@@ -1144,25 +1144,25 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor wait")
|
||||
@TraceRmiMethod(display = "Break on monitor wait")
|
||||
public void break_mon_wait_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_mon_wait(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor wait")
|
||||
@TraceRmiMethod(display = "Break on monitor wait")
|
||||
public void break_mon_wait_reftype(
|
||||
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
|
||||
break_mon_wait(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor wait")
|
||||
@TraceRmiMethod(display = "Break on monitor wait")
|
||||
public void break_mon_wait_instance(
|
||||
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
|
||||
break_mon_wait(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor wait")
|
||||
@TraceRmiMethod(display = "Break on monitor wait")
|
||||
public void break_mon_wait_thread(
|
||||
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_mon_wait(obj);
|
||||
@@ -1189,31 +1189,31 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor waited")
|
||||
@TraceRmiMethod(display = "Break on monitor waited")
|
||||
public void break_mon_waited_container(
|
||||
@Param(schema = "EventContainer", name = "container") RmiTraceObject obj) {
|
||||
break_mon_waited(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor waited")
|
||||
@TraceRmiMethod(display = "Break on monitor waited")
|
||||
public void break_mon_waited_reftype(
|
||||
@Param(schema = "ReferenceType", name = "class") RmiTraceObject obj) {
|
||||
break_mon_waited(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor waited")
|
||||
@TraceRmiMethod(display = "Break on monitor waited")
|
||||
public void break_mon_waited_instance(
|
||||
@Param(schema = "ObjectReference", name = "instance") RmiTraceObject obj) {
|
||||
break_mon_waited(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Break on monitor waited")
|
||||
@TraceRmiMethod(display = "Break on monitor waited")
|
||||
public void break_mon_waited_thread(
|
||||
@Param(schema = "Thread", name = "thread") RmiTraceObject obj) {
|
||||
break_mon_waited(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Add count filter")
|
||||
@TraceRmiMethod(display = "Add count filter")
|
||||
public void add_count_filter(
|
||||
@Param(
|
||||
schema = "Event",
|
||||
@@ -1234,7 +1234,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Set class filter")
|
||||
@TraceRmiMethod(display = "Set class filter")
|
||||
public void set_class_filter(
|
||||
@Param(
|
||||
schema = "Event",
|
||||
@@ -1349,7 +1349,7 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Set source filter")
|
||||
@TraceRmiMethod(display = "Set source filter")
|
||||
public void set_source_filter(
|
||||
@Param(
|
||||
schema = "Event",
|
||||
@@ -1370,7 +1370,7 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Set platform filter")
|
||||
@TraceRmiMethod(display = "Set platform filter")
|
||||
public void set_platform_filter(@Param(schema = "Event", name = "event") RmiTraceObject obj) {
|
||||
Object ctxt = getObjectFromPath(obj.getPath());
|
||||
if (ctxt instanceof ThreadStartRequest req) {
|
||||
@@ -1388,7 +1388,7 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "toggle", display = "Toggle breakpoint")
|
||||
@TraceRmiMethod(action = "toggle", display = "Toggle breakpoint")
|
||||
public void toggle_breakpoint(
|
||||
@Param(schema = "BreakpointSpec", name = "breakpoint") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
@@ -1409,7 +1409,7 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putBreakpoints();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "delete", display = "Delete breakpoint")
|
||||
@TraceRmiMethod(action = "delete", display = "Delete breakpoint")
|
||||
public void delete_breakpoint(
|
||||
@Param(schema = "BreakpointSpec", name = "breakpoint") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
@@ -1420,7 +1420,7 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putBreakpoints();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "toggle", display = "Toggle event")
|
||||
@TraceRmiMethod(action = "toggle", display = "Toggle event")
|
||||
public void toggle_event(@Param(schema = "Event", name = "event") RmiTraceObject obj) {
|
||||
Object ctxt = getObjectFromPath(obj.getPath());
|
||||
if (ctxt instanceof EventRequest req) {
|
||||
@@ -1434,7 +1434,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "delete", display = "Delete Event")
|
||||
@TraceRmiMethod(action = "delete", display = "Delete Event")
|
||||
public void delete_event(@Param(schema = "Event", name = "event") RmiTraceObject obj) {
|
||||
VirtualMachine vm = connector.getJdi().getCurrentVM();
|
||||
Object ctxt = getObjectFromPath(obj.getPath());
|
||||
@@ -1444,13 +1444,13 @@ public class JdiMethods implements RmiMethods {
|
||||
cmds.putEvents();
|
||||
}
|
||||
|
||||
@TraceMethod(action = "toggle", display = "Toggle scope")
|
||||
@TraceRmiMethod(action = "toggle", display = "Toggle scope")
|
||||
public void toggle_scope_canonical_methods(
|
||||
@Param(schema = "CanonicalMethodContainer", name = "container") RmiTraceObject obj) {
|
||||
toggle_scope_methods(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "toggle", display = "Toggle scope")
|
||||
@TraceRmiMethod(action = "toggle", display = "Toggle scope")
|
||||
public void toggle_scope_methods(
|
||||
@Param(schema = "MethodContainer", name = "container") RmiTraceObject obj) {
|
||||
String ppath = cmds.getParentPath(obj.getPath());
|
||||
@@ -1459,13 +1459,13 @@ public class JdiMethods implements RmiMethods {
|
||||
refresh_methods(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "toggle", display = "Toggle scope")
|
||||
@TraceRmiMethod(action = "toggle", display = "Toggle scope")
|
||||
public void toggle_scope_canonical_fields(
|
||||
@Param(schema = "CanonicalFieldContainer", name = "container") RmiTraceObject obj) {
|
||||
toggle_scope_fields(obj);
|
||||
}
|
||||
|
||||
@TraceMethod(action = "toggle", display = "Toggle scope")
|
||||
@TraceRmiMethod(action = "toggle", display = "Toggle scope")
|
||||
public void toggle_scope_fields(
|
||||
@Param(schema = "FieldContainer", name = "container") RmiTraceObject obj) {
|
||||
String ppath = cmds.getParentPath(obj.getPath());
|
||||
@@ -1479,7 +1479,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(action = "read_mem", display = "Read Memory")
|
||||
@TraceRmiMethod(action = "read_mem", display = "Read Memory")
|
||||
public long read_mem(
|
||||
@Param(
|
||||
schema = "VirtualMachine",
|
||||
@@ -1503,7 +1503,7 @@ public class JdiMethods implements RmiMethods {
|
||||
return range.getLength();
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Invoke method (no args)")
|
||||
@TraceRmiMethod(display = "Invoke method (no args)")
|
||||
public void execute_on_instance(
|
||||
@Param(
|
||||
schema = "ObjectReference",
|
||||
@@ -1531,7 +1531,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Invoke static method (no args)")
|
||||
@TraceRmiMethod(display = "Invoke static method (no args)")
|
||||
public void execute_on_class(
|
||||
@Param(
|
||||
schema = "ReferenceType",
|
||||
@@ -1565,7 +1565,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Invoke method (no args)")
|
||||
@TraceRmiMethod(display = "Invoke method (no args)")
|
||||
public void execute_method(
|
||||
@Param(
|
||||
schema = "Method",
|
||||
@@ -1596,7 +1596,7 @@ public class JdiMethods implements RmiMethods {
|
||||
}
|
||||
}
|
||||
|
||||
@TraceMethod(display = "Invoke static method (no args)")
|
||||
@TraceRmiMethod(display = "Invoke static method (no args)")
|
||||
public void execute_static_method(
|
||||
@Param(
|
||||
schema = "Method",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
MODULE FILE LICENSE: pypkg/dist/protobuf-3.20.3-py2.py3-none-any.whl BSD-3-GOOGLE
|
||||
MODULE FILE LICENSE: pypkg/dist/protobuf-6.31.0-py3-none-any.whl BSD-3-GOOGLE
|
||||
MODULE FILE LICENSE: pypkg/dist/psutil-5.9.8.tar.gz BSD-3-PSUTIL
|
||||
MODULE FILE LICENSE: pypkg/dist/setuptools-68.0.0-py3-none-any.whl MIT
|
||||
MODULE FILE LICENSE: pypkg/dist/wheel-0.37.1-py2.py3-none-any.whl MIT
|
||||
|
||||
@@ -19,6 +19,7 @@ apply from: "${rootProject.projectDir}/gradle/helpProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/jacocoProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javaTestProject.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/distributableGhidraModule.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/javadoc.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/hasProtobuf.gradle"
|
||||
apply from: "${rootProject.projectDir}/gradle/hasPythonPackage.gradle"
|
||||
|
||||
@@ -72,7 +73,7 @@ tasks.assemblePyPackage {
|
||||
}
|
||||
}
|
||||
|
||||
distributePyDep("protobuf-3.20.3-py2.py3-none-any.whl")
|
||||
distributePyDep("protobuf-6.31.0-py3-none-any.whl")
|
||||
distributePyDep("psutil-5.9.8.tar.gz")
|
||||
distributePyDep("setuptools-68.0.0-py3-none-any.whl")
|
||||
distributePyDep("wheel-0.37.1-py2.py3-none-any.whl")
|
||||
|
||||
@@ -30,14 +30,9 @@
|
||||
#@env OPT_LANG:str="DATA:LE:64:default" "Ghidra Language" "The Ghidra LanguageID for the trace"
|
||||
#@env OPT_COMP:str="pointer64" "Ghidra Compiler" "The Ghidra CompilerSpecID for the trace"
|
||||
|
||||
if [ -d ${GHIDRA_HOME}/ghidra/.git ]
|
||||
then
|
||||
export PYTHONPATH=$GHIDRA_HOME/ghidra/Ghidra/Debug/Debugger-rmi-trace/build/pypkg/src:$PYTHONPATH
|
||||
elif [ -d ${GHIDRA_HOME}/.git ]
|
||||
then
|
||||
export PYTHONPATH=$GHIDRA_HOME/Ghidra/Debug/Debugger-rmi-trace/build/pypkg/src:$PYTHONPATH
|
||||
else
|
||||
export PYTHONPATH=$GHIDRA_HOME/Ghidra/Debug/Debugger-rmi-trace/pypkg/src:$PYTHONPATH
|
||||
fi
|
||||
. ../support/setuputils.sh
|
||||
|
||||
pypathTrace=$(ghidra-module-pypath)
|
||||
export PYTHONPATH=$pypathTrace:$PYTHONPATH
|
||||
|
||||
"$OPT_PYTHON_EXE" -i ../support/raw-python3.py
|
||||
|
||||
@@ -28,19 +28,17 @@ This file CANNOT be assumed to be available on a remote target. For
|
||||
that, consider ghidratrace.setuputils.
|
||||
"""
|
||||
import os
|
||||
|
||||
home = os.getenv('GHIDRA_HOME')
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def ghidra_module_pypath(name: str) -> str:
|
||||
installed = f'{home}/Ghidra/{name}/pypkg/src'
|
||||
def ghidra_module_pypath(name: Optional[str]=None) -> str:
|
||||
mod_home_name = 'MODULE_HOME' if name is None else f'MODULE_{name.replace("-","_")}_HOME'
|
||||
mod_home = os.getenv(mod_home_name)
|
||||
installed = f'{mod_home}/pypkg/src'
|
||||
if os.path.isdir(installed):
|
||||
return installed
|
||||
dev1 = f'{home}/Ghidra/{name}/build/pypkg/src'
|
||||
if os.path.isdir(dev1):
|
||||
return dev1
|
||||
dev2 = f'{home}/ghidra/Ghidra/{name}/build/pypkg/src'
|
||||
if os.path.isdir(dev2):
|
||||
return dev2
|
||||
dev = f'{mod_home}/build/pypkg/src'
|
||||
if os.path.isdir(dev):
|
||||
return dev
|
||||
raise Exception(
|
||||
f"Cannot find Python source for {name}. Try gradle assemblePyPackage?")
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
## ###
|
||||
# IP: GHIDRA
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# IP: GHIDRA
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
##
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
import os
|
||||
@@ -33,4 +33,4 @@ client = Client(
|
||||
print(f"Connected to {client.description} at {host}:{port}")
|
||||
|
||||
trace = client.create_trace("noname", os.getenv(
|
||||
"OPT_LANG"), os.getenv("OPT_COMP"))
|
||||
"OPT_LANG"), os.getenv("OPT_COMP"), extra=None)
|
||||
|
||||
@@ -14,13 +14,9 @@
|
||||
# limitations under the License.
|
||||
##
|
||||
function Find-App-Properties {
|
||||
[IO.FileInfo] $simple = "$Env:GHIDRA_HOME\Ghidra\applications.properties"
|
||||
if ($simple.Exists) {
|
||||
return $simple
|
||||
}
|
||||
[IO.FileInfo] $dev2 = "$Env:GHIDRA_HOME\ghidra\Ghidra\application.properties"
|
||||
if ($dev2.Exists) {
|
||||
return $dev2
|
||||
[IO.FileInfo] $props = "$Env:GHIDRA_HOME\application.properties"
|
||||
if ($props.Exists) {
|
||||
return $props
|
||||
}
|
||||
throw "Cannot find application.properties"
|
||||
}
|
||||
@@ -32,33 +28,39 @@ function Get-Ghidra-Version {
|
||||
}
|
||||
|
||||
function Ghidra-Module-PyPath {
|
||||
[IO.DirectoryInfo] $installed = "$Env:GHIDRA_HOME\Ghidra\$($args[0])\pypkg\src"
|
||||
if ($args.Count -eq 0 -or $args[0] -eq "<SELF>") {
|
||||
$modhomename = 'MODULE_HOME'
|
||||
} else {
|
||||
$modhomename = "MODULE_$($args[0])_HOME" -replace '-', '_'
|
||||
}
|
||||
$modhomeitem = Get-ChildItem Env:$modhomename
|
||||
$modhome = $modhomeitem.Value
|
||||
[IO.DirectoryInfo] $installed = "$modhome\pypkg\src"
|
||||
if ($installed.Exists) {
|
||||
return "$installed"
|
||||
}
|
||||
[IO.DirectoryInfo] $dev1 = "$Env:GHIDRA_HOME\Ghidra\$($args[0])\build\pypkg\src"
|
||||
if ($dev1.Exists) {
|
||||
return "$dev1"
|
||||
}
|
||||
[IO.DirectoryInfo] $dev2 = "$Env:GHIDRA_HOME\ghidra\Ghidra\$($args[0])\build\pypkg\src"
|
||||
if ($dev2.Exists) {
|
||||
return "$dev2"
|
||||
[IO.DirectoryInfo] $dev = "$modhome\build\pypkg\src"
|
||||
if ($dev.Exists) {
|
||||
return "$dev"
|
||||
}
|
||||
throw "Cannot find Python source for $($args[0]). Try gradle assemblePyPackage?"
|
||||
}
|
||||
|
||||
function Ghidra-Module-PyDist {
|
||||
[IO.DirectoryInfo] $installed = "$Env:GHIDRA_HOME\Ghidra\$($args[0])\pypkg\dist"
|
||||
if ($args.Count -eq 0 -or $args[0] -eq "<SELF>") {
|
||||
$modhomename = 'MODULE_HOME'
|
||||
} else {
|
||||
$modhomename = "MODULE_$($args[0])_HOME" -replace '-', '_'
|
||||
}
|
||||
$modhomeitem = Get-ChildItem Env:$modhomename
|
||||
$modhome = $modhomeitem.Value
|
||||
[IO.DirectoryInfo] $installed = "$modhome\pypkg\dist"
|
||||
if ($installed.Exists) {
|
||||
return "$installed"
|
||||
}
|
||||
[IO.DirectoryInfo] $dev1 = "$Env:GHIDRA_HOME\Ghidra\$($args[0])\build\pypkg\dist"
|
||||
if ($dev1.Exists) {
|
||||
return "$dev1"
|
||||
}
|
||||
[IO.DirectoryInfo] $dev2 = "$Env:GHIDRA_HOME\ghidra\Ghidra\$($args[0])\build\pypkg\dist"
|
||||
if ($dev2.Exists) {
|
||||
return "$dev2"
|
||||
[IO.DirectoryInfo] $dev = "$modhome\build\pypkg\dist"
|
||||
if ($dev.Exists) {
|
||||
return "$dev"
|
||||
}
|
||||
throw "Cannot find Python package for $($args[0]). Try gradle buildPyPackage?"
|
||||
}
|
||||
|
||||
@@ -14,14 +14,9 @@
|
||||
# limitations under the License.
|
||||
##
|
||||
find-app-properties() {
|
||||
local simple="$GHIDRA_HOME/Ghidra/application.properties"
|
||||
if [ -f "$simple" ]; then
|
||||
echo $simple
|
||||
return 0
|
||||
fi
|
||||
local dev2="$GHIDRA_HOME/ghidra/Ghidra/application.properties"
|
||||
if [ -f "$dev2" ]; then
|
||||
echo $dev2
|
||||
local props="$GHIDRA_HOME/application.properties"
|
||||
if [ -f "$props" ]; then
|
||||
echo $props
|
||||
return 0
|
||||
fi
|
||||
echo >&2 "Cannot find application.properties"
|
||||
@@ -45,19 +40,21 @@ get-ghidra-version() {
|
||||
}
|
||||
|
||||
ghidra-module-pypath() {
|
||||
installed="$GHIDRA_HOME/Ghidra/$1/pypkg/src"
|
||||
local modhomename
|
||||
if [ -z "$1" ] || [ "$1" == "<SELF>" ]; then
|
||||
modhomename='MODULE_HOME'
|
||||
else
|
||||
modhomename="MODULE_${1//-/_}_HOME"
|
||||
fi
|
||||
local modhome="${!modhomename}"
|
||||
local installed="$modhome/pypkg/src"
|
||||
if [ -d "$installed" ]; then
|
||||
echo $installed
|
||||
return 0
|
||||
fi
|
||||
dev1="$GHIDRA_HOME/Ghidra/$1/build/pypkg/src"
|
||||
if [ -d "$dev1" ]; then
|
||||
echo $dev1
|
||||
return 0
|
||||
fi
|
||||
dev2="$GHIDRA_HOME/ghidra/Ghidra/$1/build/pypkg/src"
|
||||
if [ -d "$dev2" ]; then
|
||||
echo $dev2
|
||||
local dev="$modhome/build/pypkg/src"
|
||||
if [ -d "$dev" ]; then
|
||||
echo $dev
|
||||
return 0
|
||||
fi
|
||||
echo >&2 "Cannot find Python source for $1. Try gradle assemblePyPackage?"
|
||||
@@ -65,19 +62,21 @@ ghidra-module-pypath() {
|
||||
}
|
||||
|
||||
ghidra-module-pydist() {
|
||||
installed="$GHIDRA_HOME/Ghidra/$1/pypkg/dist"
|
||||
local modhomename
|
||||
if [ -z "$1" ] || [ "$1" == "<SELF>" ]; then
|
||||
modhomename='MODULE_HOME'
|
||||
else
|
||||
modhomename="MODULE_${1//-/_}_HOME"
|
||||
fi
|
||||
local modhome="${!modhomename}"
|
||||
local installed="$modhome/pypkg/dist"
|
||||
if [ -d "$installed" ]; then
|
||||
echo $installed
|
||||
return 0
|
||||
fi
|
||||
dev1="$GHIDRA_HOME/Ghidra/$1/build/pypkg/dist"
|
||||
if [ -d "$dev1" ]; then
|
||||
echo $dev1
|
||||
return 0
|
||||
fi
|
||||
dev2="$GHIDRA_HOME/ghidra/Ghidra/$1/build/pypkg/dist"
|
||||
if [ -d "$dev2" ]; then
|
||||
echo $dev2
|
||||
local dev="$modhome/build/pypkg/dist"
|
||||
if [ -d "$dev" ]; then
|
||||
echo $dev
|
||||
return 0
|
||||
fi
|
||||
echo >&2 "Cannot find Python package for $1. Try gradle buildPyPackage?"
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package ghidra.app.plugin.core.debug.client.tracermi;
|
||||
|
||||
import com.sun.jdi.VirtualMachine;
|
||||
|
||||
import ghidra.program.model.address.Address;
|
||||
|
||||
public interface MemoryMapper {
|
||||
|
||||
@@ -26,7 +26,7 @@ public class RmiMethodRegistry {
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public static @interface TraceMethod {
|
||||
public static @interface TraceRmiMethod {
|
||||
String action() default "";
|
||||
|
||||
String display() default "";
|
||||
|
||||
@@ -18,7 +18,7 @@ package ghidra.app.plugin.core.debug.client.tracermi;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
|
||||
import ghidra.trace.model.target.iface.TraceObjectMethod.ParameterDescription;
|
||||
import ghidra.trace.model.target.iface.TraceMethod.ParameterDescription;
|
||||
import ghidra.trace.model.target.schema.*;
|
||||
import ghidra.trace.model.target.schema.TraceObjectSchema.SchemaName;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user