part #2
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) StellaOps. All rights reserved.
|
||||
// Licensed under BUSL-1.1. See LICENSE in the project root.
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StellaOps.BinaryIndex.Ghidra;
|
||||
|
||||
namespace StellaOps.BinaryIndex.Decompiler;
|
||||
|
||||
public sealed partial class GhidraDecompilerAdapter
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<DecompiledFunction> DecompileAsync(
|
||||
GhidraFunction function,
|
||||
DecompileOptions? options = null,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(function);
|
||||
|
||||
options ??= new DecompileOptions();
|
||||
|
||||
_logger.LogDebug(
|
||||
"Decompiling function {Name} at 0x{Address:X}",
|
||||
function.Name,
|
||||
function.Address);
|
||||
|
||||
var code = function.DecompiledCode;
|
||||
|
||||
if (string.IsNullOrEmpty(code))
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Function {Name} has no decompiled code, returning stub",
|
||||
function.Name);
|
||||
|
||||
return new DecompiledFunction(
|
||||
function.Name,
|
||||
BuildSignature(function),
|
||||
"/* Decompilation unavailable */",
|
||||
null,
|
||||
[],
|
||||
[],
|
||||
function.Address,
|
||||
function.Size);
|
||||
}
|
||||
|
||||
if (code.Length > options.MaxCodeLength)
|
||||
{
|
||||
code = code[..options.MaxCodeLength] + "\n/* ... truncated ... */";
|
||||
}
|
||||
|
||||
DecompiledAst? ast = null;
|
||||
try
|
||||
{
|
||||
ast = _parser.Parse(code);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to parse decompiled code for {Name}", function.Name);
|
||||
}
|
||||
|
||||
var locals = _parser.ExtractVariables(code);
|
||||
var calledFunctions = _parser.ExtractCalledFunctions(code);
|
||||
|
||||
return new DecompiledFunction(
|
||||
function.Name,
|
||||
BuildSignature(function),
|
||||
code,
|
||||
ast,
|
||||
locals,
|
||||
calledFunctions,
|
||||
function.Address,
|
||||
function.Size);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<DecompiledFunction> DecompileAtAddressAsync(
|
||||
string binaryPath,
|
||||
ulong address,
|
||||
DecompileOptions? options = null,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrEmpty(binaryPath);
|
||||
|
||||
options ??= new DecompileOptions();
|
||||
|
||||
_logger.LogDebug(
|
||||
"Decompiling function at 0x{Address:X} in {Binary}",
|
||||
address,
|
||||
Path.GetFileName(binaryPath));
|
||||
|
||||
using var stream = File.OpenRead(binaryPath);
|
||||
var analysis = await _ghidraService.AnalyzeAsync(
|
||||
stream,
|
||||
new GhidraAnalysisOptions
|
||||
{
|
||||
IncludeDecompilation = true,
|
||||
ExtractDecompilation = true
|
||||
},
|
||||
ct).ConfigureAwait(false);
|
||||
|
||||
var function = analysis.Functions.FirstOrDefault(f => f.Address == address);
|
||||
|
||||
if (function is null)
|
||||
{
|
||||
throw new InvalidOperationException($"No function found at address 0x{address:X}");
|
||||
}
|
||||
|
||||
return await DecompileAsync(function, options, ct).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user