Skip to content

Conversation

@cQQkie-dev
Copy link

@cQQkie-dev cQQkie-dev commented Oct 29, 2025

Summary

Auto-detect Ghidra's protobuf version from the installation directory to prevent runtime version mismatch errors.

Problem

BinExport previously hardcoded protobuf 4.31.0 and bundled it in the extension ZIP. This caused runtime errors when used with Ghidra releases that ship different protobuf versions:

  • Ghidra 11.4.2 release ships protobuf 3.21.8
  • Ghidra source builds (recent) use protobuf 4.31.0

When the extension bundled 4.31.0 ran on Ghidra 11.4.2, it caused, e.g. following error:

...
java.lang.VerifyError: Bad return type
internalGetFieldAccessorTable() returns GeneratedMessageV3$FieldAccessorTable
but method signature expects GeneratedMessage$FieldAccessorTable
...

This happened because bundled protobuf 4.x (which uses GeneratedMessageV3) replaced Ghidra's runtime protobuf 3.x classes (which use GeneratedMessage), creating binary-incompatible class hierarchies.

Solution

Auto-detect protobuf version from GHIDRA_INSTALL_DIR:

  • Source builds: Read ghidra.protobuf.java.version from gradle.properties
  • Release builds: Scan for protobuf-java-*.jar in known locations (Ghidra/Debug/ProposedUtils/lib, Ghidra/Framework)
  • Fallback: Default to 3.21.8 (Ghidra 11.4.2 stable release)
  • Manual override: Support -PghidraProtobufVersion=x.y.z for edge cases

Changed from implementation to compileOnly dependency. This prevents bundling protobuf in the extension .zip, but is provided by Ghidra itself it at runtime.

Changes

Modified: java/build.gradle

  • Added detectGhidraProtobufVersion() function

  • Removed configurations { extraLibs } and bundling logic

  • Changed dependency: implementationcompileOnly

  • Added runtimeClasspath exclusion as safety net

  • Preserved Eclipse IDE configuration and license headers

Testing

Environment:

  • OS: Ubuntu 22.04

  • Java: OpenJDK 21

  • Ghidra: 11.4.2 release (protobuf 3.21.8)

Build verification:

$ gradle buildExtension | grep protobuf
Detected protobuf version from Ghidra release: 3.21.8

$ unzip -l dist/*.zip | grep protobuf
(no output - protobuf not bundled)

Runtime testing:

  • Right-click → Export (project workspace) => Success
  • Script Manager (BinExport.java with IDA options) => Success
  • correctly exports .BinExport files (optionally with additional IDA Pro Compatibility

Validation:

  • All exported .BinExport files validated as valid BinExport2 protobuf format
  • BinDiff CLI processing successful: 96.95% similarity on test binaries (e.g. too similiar hello world files)
  • No VerifyError, IllegalAccessError, or protobuf-related errors
  • Extension loads and runs without issues

Note:
Manual override example:
gradle -PghidraProtobufVersion=4.31.0 buildExtension

The extension now adapts to the installed Ghidra version automatically, eliminating the need for manual build.gradle edits when switching between Ghidra versions.

	- Detect version from GHIDRA_INSTALL_DIR instead of hardcoding
	- Check gradle.properties for source builds
	- Scan for protobuf jars in release builds
	- Fallback to 3.21.8 if detection fails
	- Changed to compileOnly dependency to prevent bundling
	- Fixes VerifyError with mismatched protobuf versions
extraLibs
// Detect protobuf version from Ghidra installation
// Allow manual override via -PghidraProtobufVersion=x.y.z
def detectGhidraProtobufVersion() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow. This is pretty involved for "just linking protobuf" :)

}
dependencies {
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.9.5'
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.9.4'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any particular reason we're downgrading this one?

Copy link
Author

@cQQkie-dev cQQkie-dev Oct 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No particular reason, except for a typo ^^.
I just build and tested with a revision to "0.9.5" and it works just as well.
If you want I just add another commit on top reverting to "0.9.5"

@cblichmann
Copy link
Member

Thank you! I was tearing my hair out the last time I looked at this. But the explanation makes perfect sense.
Should we also ugprade upstream's protobuf version?

I'll try and merge this soon-ish, but I'm travelling.

@cQQkie-dev
Copy link
Author

Thank you! I was tearing my hair out the last time I looked at this. But the explanation makes perfect sense. Should we also ugprade upstream's protobuf version?

I'll try and merge this soon-ish, but I'm travelling.

I'm not sure what the best course of action is here for now. Just my two cents:

  • Ghidra 11.4.2 release from August : protobuf 3.21.8 => I'm assuming (unfounded assumption) that most people probably use the ready made release of the recent version for now
  • Ghidra main branch: protobuf 4.31.0 => seems like they will probably be migrating to this version for the next release
  • Next Ghidra release (likely): will include 4.31.0

So I guess that it's safe to keep 3.21.8 as default for now and then upgrade to 4.31.0 when the next ghidra release drops.

Thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants