feat(analysis): add type information to xref and label entries
This commit is contained in:
parent
dcb4cf6a3c
commit
b26631c5aa
@ -4,6 +4,7 @@ static main() {
|
||||
auto ea, func_end, curr_inst, func_name, disasm, file;
|
||||
auto last_inst, xref, ref, label_name;
|
||||
auto entry_ea, entry_name;
|
||||
auto xref_type, type_str;
|
||||
|
||||
Message("Aguardando fim da analise...\n");
|
||||
Wait();
|
||||
@ -31,12 +32,20 @@ static main() {
|
||||
fprintf(file, " \"function\": \"%s\",\n", func_name);
|
||||
fprintf(file, " \"address\": \"0x%08X\",\n", ea);
|
||||
|
||||
// --- XREFS TO (Simplificado e direto para o IDA 5) ---
|
||||
// --- XREFS TO (com tipo: CALL ou JUMP) ---
|
||||
fprintf(file, " \"xrefs\": \"");
|
||||
xref = RfirstB(ea);
|
||||
while (xref != BADADDR) {
|
||||
if (GetFunctionName(xref) != "") {
|
||||
fprintf(file, "%s ", GetFunctionName(xref));
|
||||
xref_type = XrefType();
|
||||
if (xref_type == fl_CN || xref_type == fl_CF) {
|
||||
type_str = "CALL";
|
||||
} else if (xref_type == fl_JN || xref_type == fl_JF) {
|
||||
type_str = "JUMP";
|
||||
} else {
|
||||
type_str = "UNKNOWN";
|
||||
}
|
||||
fprintf(file, "%s:%s ", GetFunctionName(xref), type_str);
|
||||
}
|
||||
xref = RnextB(ea, xref);
|
||||
}
|
||||
@ -63,7 +72,7 @@ static main() {
|
||||
}
|
||||
fprintf(file, "\",\n");
|
||||
|
||||
// --- LABELS (code references from instructions) ---
|
||||
// --- LABELS (code references with type) ---
|
||||
fprintf(file, " \"labels\": \"");
|
||||
curr_inst = ea;
|
||||
last_inst = 0;
|
||||
@ -78,7 +87,15 @@ static main() {
|
||||
while (ref != BADADDR) {
|
||||
label_name = Name(ref);
|
||||
if (label_name != "") {
|
||||
fprintf(file, "%s:0x%08X ", label_name, ref);
|
||||
xref_type = XrefType();
|
||||
if (xref_type == fl_CN || xref_type == fl_CF) {
|
||||
type_str = "CALL";
|
||||
} else if (xref_type == fl_JN || xref_type == fl_JF) {
|
||||
type_str = "JUMP";
|
||||
} else {
|
||||
type_str = "UNKNOWN";
|
||||
}
|
||||
fprintf(file, "%s:0x%08X:%s ", label_name, ref, type_str);
|
||||
}
|
||||
ref = Rnext(curr_inst, ref);
|
||||
}
|
||||
|
||||
@ -279,7 +279,10 @@ public class ChatContextBuilder {
|
||||
|
||||
sb.append("Callers: ");
|
||||
sb.append(
|
||||
String.join(", ", callers.stream().limit(5).map(x -> x.getCaller().getName()).toList()));
|
||||
callers.stream()
|
||||
.limit(5)
|
||||
.map(x -> x.getCaller().getName() + " [" + x.getType() + "]")
|
||||
.collect(java.util.stream.Collectors.joining(", ")));
|
||||
sb.append("\n");
|
||||
}
|
||||
|
||||
@ -290,7 +293,10 @@ public class ChatContextBuilder {
|
||||
|
||||
sb.append("Callees: ");
|
||||
sb.append(
|
||||
String.join(", ", callees.stream().limit(10).map(x -> x.getCallee().getName()).toList()));
|
||||
callees.stream()
|
||||
.limit(10)
|
||||
.map(x -> x.getCallee().getName() + " [" + x.getType() + "]")
|
||||
.collect(java.util.stream.Collectors.joining(", ")));
|
||||
sb.append("\n");
|
||||
}
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@ package ai.decompile.analysis.model.dto;
|
||||
|
||||
import ai.decompile.analysis.model.entity.StaticLabel;
|
||||
|
||||
public record LabelResponse(String name, String address) {
|
||||
public record LabelResponse(String name, String address, String type) {
|
||||
public static LabelResponse from(StaticLabel l) {
|
||||
return new LabelResponse(l.getName(), l.getAddress());
|
||||
return new LabelResponse(l.getName(), l.getAddress(), l.getType());
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,4 +25,8 @@ public class StaticLabel {
|
||||
|
||||
@Column(nullable = false, length = 20)
|
||||
private String address;
|
||||
|
||||
@Column(nullable = false, length = 10)
|
||||
@Builder.Default
|
||||
private String type = "CALL";
|
||||
}
|
||||
|
||||
@ -132,6 +132,7 @@ public class AnalysisService {
|
||||
.function(func)
|
||||
.name(label.name())
|
||||
.address(label.address())
|
||||
.type(label.type())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
@ -145,13 +146,13 @@ public class AnalysisService {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var calleeName : funcResult.xrefNames()) {
|
||||
var calleeId = nameToId.get(calleeName);
|
||||
for (var xrefEntry : funcResult.xrefs()) {
|
||||
var calleeId = nameToId.get(xrefEntry.name());
|
||||
if (calleeId == null) {
|
||||
log.debug(
|
||||
"Skipping xref from '{}' to unknown function '{}' (likely external/lib)",
|
||||
funcResult.name(),
|
||||
calleeName);
|
||||
xrefEntry.name());
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -159,7 +160,7 @@ public class AnalysisService {
|
||||
StaticXref.builder()
|
||||
.caller(functionRepository.getReferenceById(callerId))
|
||||
.callee(functionRepository.getReferenceById(calleeId))
|
||||
.type("CALL")
|
||||
.type(xrefEntry.type())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,5 +8,5 @@ public record FunctionResult(
|
||||
String assembly,
|
||||
String decompiledCode,
|
||||
String signature,
|
||||
List<String> xrefNames,
|
||||
List<XrefEntry> xrefs,
|
||||
List<LabelEntry> labels) {}
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
package ai.decompile.engine.model;
|
||||
|
||||
public record LabelEntry(String name, String address) {}
|
||||
public record LabelEntry(String name, String address, String type) {}
|
||||
|
||||
3
src/main/java/ai/decompile/engine/model/XrefEntry.java
Normal file
3
src/main/java/ai/decompile/engine/model/XrefEntry.java
Normal file
@ -0,0 +1,3 @@
|
||||
package ai.decompile.engine.model;
|
||||
|
||||
public record XrefEntry(String name, String type) {}
|
||||
@ -6,6 +6,7 @@ import ai.decompile.engine.model.AnalysisResult;
|
||||
import ai.decompile.engine.model.EngineType;
|
||||
import ai.decompile.engine.model.FunctionResult;
|
||||
import ai.decompile.engine.model.LabelEntry;
|
||||
import ai.decompile.engine.model.XrefEntry;
|
||||
import com.github.dockerjava.api.model.Bind;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -185,10 +186,9 @@ public class Ida5EngineService implements EngineService {
|
||||
continue;
|
||||
}
|
||||
|
||||
var xrefNames =
|
||||
xrefsRaw.isBlank() ? List.<String>of() : Arrays.asList(xrefsRaw.trim().split("\\s+"));
|
||||
var xrefs = parseXrefs(xrefsRaw.trim());
|
||||
var labels = parseLabels(labelsRaw.trim());
|
||||
functions.add(new FunctionResult(name, address, assembly, null, null, xrefNames, labels));
|
||||
functions.add(new FunctionResult(name, address, assembly, null, null, xrefs, labels));
|
||||
}
|
||||
|
||||
if (functions.isEmpty()) {
|
||||
@ -210,6 +210,23 @@ public class Ida5EngineService implements EngineService {
|
||||
return idx < 0 ? null : text.substring(idx + delim.length());
|
||||
}
|
||||
|
||||
private static List<XrefEntry> parseXrefs(String raw) {
|
||||
if (Objects.isNull(raw) || raw.isBlank()) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
return Arrays.stream(raw.trim().split("\\s+")).map(Ida5EngineService::parseXrefEntry).toList();
|
||||
}
|
||||
|
||||
private static XrefEntry parseXrefEntry(String token) {
|
||||
var colon = token.lastIndexOf(':');
|
||||
if (colon < 0) {
|
||||
return new XrefEntry(token, "CALL");
|
||||
}
|
||||
|
||||
return new XrefEntry(token.substring(0, colon), token.substring(colon + 1));
|
||||
}
|
||||
|
||||
private static List<LabelEntry> parseLabels(String raw) {
|
||||
if (raw == null || raw.isBlank()) {
|
||||
return List.of();
|
||||
@ -221,10 +238,19 @@ public class Ida5EngineService implements EngineService {
|
||||
}
|
||||
|
||||
private static LabelEntry parseLabelEntry(String token) {
|
||||
int colon = token.lastIndexOf(':');
|
||||
if (colon < 0) {
|
||||
return new LabelEntry(token, "");
|
||||
var lastColon = token.lastIndexOf(':');
|
||||
if (lastColon < 0) {
|
||||
return new LabelEntry(token, "", "CALL");
|
||||
}
|
||||
return new LabelEntry(token.substring(0, colon), token.substring(colon + 1));
|
||||
|
||||
var type = token.substring(lastColon + 1);
|
||||
var nameAddr = token.substring(0, lastColon);
|
||||
var addrColon = nameAddr.lastIndexOf(':');
|
||||
if (addrColon < 0) {
|
||||
return new LabelEntry(nameAddr, "", type);
|
||||
}
|
||||
|
||||
return new LabelEntry(
|
||||
nameAddr.substring(0, addrColon), nameAddr.substring(addrColon + 1), type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1 @@
|
||||
ALTER TABLE static_label ADD COLUMN IF NOT EXISTS type VARCHAR(10) NOT NULL DEFAULT 'CALL';
|
||||
@ -114,6 +114,7 @@ CREATE TABLE IF NOT EXISTS static_label
|
||||
id UUID PRIMARY KEY,
|
||||
function_id UUID NOT NULL REFERENCES static_function (id) ON DELETE CASCADE,
|
||||
name VARCHAR(500) NOT NULL,
|
||||
address VARCHAR(20) NOT NULL
|
||||
address VARCHAR(20) NOT NULL,
|
||||
type VARCHAR(10) NOT NULL DEFAULT 'CALL'
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_static_label_function_id ON static_label (function_id);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user