Skip to content

Json#7

Open
edmcman wants to merge 5 commits into
mainfrom
json
Open

Json#7
edmcman wants to merge 5 commits into
mainfrom
json

Conversation

@edmcman

@edmcman edmcman commented Dec 19, 2025

Copy link
Copy Markdown
Owner

No description provided.

Copilot AI review requested due to automatic review settings December 19, 2025 21:44
@edmcman edmcman self-assigned this Dec 19, 2025

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds JSON output format support to the Ghidra C++ exporter, providing an alternative to the existing C and header file outputs. The implementation follows the project's functional programming style and minimal code change philosophy by refactoring existing code into reusable helper functions.

Key Changes:

  • Adds JSON export functionality that captures function bodies, signatures, and header content in a structured format
  • Refactors type and equate writing into string-capturing functions for reuse across output formats
  • Creates comprehensive test suite with validation of JSON structure, content, and consistency with traditional outputs

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/run_tests.sh Adds "json" test suite option to test runner, integrated alongside existing test suites
tests/json_output_tests.bats New comprehensive test suite validating JSON syntax, structure, section headers, and consistency with standalone header files
export.bash Updates output validation to check for JSON files alongside C/H files, improving error handling for multiple output types
cpp_exporter_headless.py Core implementation: adds JSON output via write_json_output, refactors type/equate writing into capture_*_as_string functions, adds build_header_content and build_c_content helpers for code reuse
.github/instructions/runtests.instructions.md Adds guidance to run test suites after making changes to ensure quality

[[ $(get_file_size "$json_file") -gt 0 ]]

# 2. Valid JSON syntax check
run -0 jq empty "$json_file"

Copilot AI Dec 19, 2025

Copy link

Choose a reason for hiding this comment

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

The tests depend on jq being installed but don't check for its availability. Consider adding a check in the setup function to skip tests if jq is not available, similar to how the test_helper.bash checks for GHIDRA_INSTALL_DIR. This would prevent test failures on systems where jq is not installed.

Copilot uses AI. Check for mistakes.
Comment thread cpp_exporter_headless.py
Comment on lines +1043 to +1054
if create_json:
# Build content using helper functions
header_content = build_header_content(h_types_sb, h_equates_sb, h_func_decls_sb, h_globals_sb)

# Write JSON output
json_path = os.path.join(out_dir, base_fname + ".json")
write_json_output(json_path, current_program.getName(), header_content, results_list)

# Traditional C/header file output (independent of JSON)
if h_pw:
if h_func_decls_sb:
h_pw.write("".join(h_func_decls_sb))
if h_globals_sb:
h_pw.write("".join(h_globals_sb))
header_content = build_header_content(h_types_sb, h_equates_sb, h_func_decls_sb, h_globals_sb)
h_pw.write(header_content)

Copilot AI Dec 19, 2025

Copy link

Choose a reason for hiding this comment

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

When both JSON output and header file are requested simultaneously, build_header_content is called twice (lines 1045 and 1053) with the same arguments, which is inefficient. Consider building the header content once and reusing it for both outputs when both create_json and h_pw are true.

Copilot uses AI. Check for mistakes.
Comment thread cpp_exporter_headless.py
Comment on lines +874 to +880
# Write to C file if it exists and no header file (C file gets types directly)
if c_pw and not h_pw:
mon.setMessage("Writing data types and equates to C file...")
for line in h_equates_sb:
c_pw.write(line)
for line in h_types_sb:
c_pw.write(line)

Copilot AI Dec 19, 2025

Copy link

Choose a reason for hiding this comment

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

The condition on line 875 writes types and equates to the C file only when there's no header file, but it doesn't account for JSON-only mode. When JSON is requested without C or header files (create_json=True, c_pw=None, h_pw=None), the types are captured but not written anywhere except to JSON, which is correct. However, the comment on line 874 could be misleading since it says "Write to C file if it exists and no header file" but doesn't mention that this also correctly skips writing when doing JSON-only export. Consider clarifying the comment to make the intent clearer.

Copilot uses AI. Check for mistakes.
Comment thread cpp_exporter_headless.py
Comment on lines +1145 to +1166
"""
functions_dict = {}
for result in decompile_results:
addr = result.function_obj.getEntryPoint().toString()
functions_dict[addr] = {
"name": result.function_obj.getName(),
"signature": result.header_code,
"body": result.body_code
}

output_data = {
"program_name": program_name,
"header": header_content,
"functions": functions_dict
}

with open(output_path, 'w') as f:
json.dump(output_data, f, indent=2)

log_message("INFO", "JSON export written to: {}".format(output_path))


Copilot AI Dec 19, 2025

Copy link

Choose a reason for hiding this comment

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

The write_json_output function doesn't handle potential exceptions that could occur during file writing or JSON serialization. If the file cannot be written (e.g., due to permissions issues) or if there's an issue with JSON serialization, the exception will propagate up. Consider adding a try-except block to provide a more informative error message and return a boolean success indicator, similar to how the main export function handles errors.

Suggested change
"""
functions_dict = {}
for result in decompile_results:
addr = result.function_obj.getEntryPoint().toString()
functions_dict[addr] = {
"name": result.function_obj.getName(),
"signature": result.header_code,
"body": result.body_code
}
output_data = {
"program_name": program_name,
"header": header_content,
"functions": functions_dict
}
with open(output_path, 'w') as f:
json.dump(output_data, f, indent=2)
log_message("INFO", "JSON export written to: {}".format(output_path))
Returns:
True if the JSON file was written successfully, False otherwise.
"""
try:
functions_dict = {}
for result in decompile_results:
addr = result.function_obj.getEntryPoint().toString()
functions_dict[addr] = {
"name": result.function_obj.getName(),
"signature": result.header_code,
"body": result.body_code
}
output_data = {
"program_name": program_name,
"header": header_content,
"functions": functions_dict
}
with open(output_path, 'w') as f:
json.dump(output_data, f, indent=2)
log_message("INFO", "JSON export written to: {}".format(output_path))
return True
except Exception as e:
log_message(
"ERROR",
"Failed to write JSON export to {}: {}"
.format(output_path, e)
)
# Include stack trace for easier debugging in headless runs
log_message("DEBUG", traceback.format_exc())
return False

Copilot uses AI. Check for mistakes.
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.

2 participants