rizin/librz/arch/swift_rtti.c
Giovanni b5fee3471c
Move RzAnalysis as private and force usage of C API (#6123)
* Hide RzAnalysis structure to force the usage of the C APIs.

* Fix rop code & test

* Fix linter

* Fix rz_analysis_free to return void
2026-04-06 16:07:53 +00:00

114 lines
No EOL
3.6 KiB
C

// SPDX-FileCopyrightText: 2025 tushar3q34 <tushar3q34@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#include "analysis_private.h"
static void add_metaclass_info(HtUP *swift_metaclass_info, RzList /*<RzBinClassField *>*/ *fields, char *class_name) {
RzListIter *iter;
RzBinClassField *field;
rz_list_foreach (fields, iter, field) {
if (!field) {
continue;
}
if (strstr(field->name, "type metadata for ")) {
ht_up_insert(swift_metaclass_info, field->vaddr + 0x100000000, class_name);
}
}
}
static void add_class_base(RzAnalysis *analysis, char *class_name, char *super_class_name) {
RzAnalysisBaseClass base = { .class_name = super_class_name, .offset = 0 };
rz_analysis_class_base_set(analysis, class_name, &base);
}
static void rz_add_swift_base_classes(RzAnalysis *analysis, RzBinClass *bin_class, HtUP *swift_metaclass_info) {
RzList *fields = bin_class->fields;
RzListIter *iter;
RzBinClassField *field;
ut64 vaddr = UT64_MAX;
rz_list_foreach (fields, iter, field) {
if (!field) {
continue;
}
if (strstr(field->name, "type metadata for ")) {
vaddr = field->vaddr + 0x100000000;
break;
}
}
if (vaddr == UT64_MAX) {
return;
}
vaddr += 0x8;
// check hexa value ar vaddr + 0x8
// it should be address to type metadata of superclass
ut64 super_vaddr = 0;
ut8 buffer[sizeof(ut64)] = { 0 };
if (analysis->iob.read_at(analysis->iob.io, vaddr, (ut8 *)&buffer, sizeof(super_vaddr))) {
super_vaddr = rz_read_ble64(buffer, analysis->big_endian);
}
bool found = false;
char *super_class_name = ht_up_find(swift_metaclass_info, super_vaddr, &found);
if (found) {
// If found, we can use the superclass name
add_class_base(analysis, bin_class->name, super_class_name);
}
}
static void identify_constructor_destructor(RzAnalysis *analysis) {
RzPVector *vect = rz_analysis_class_get_all(analysis, false);
void **iter;
rz_pvector_foreach (vect, iter) {
SdbKv *kv = *iter;
const char *class_name = sdbkv_key(kv);
RzVector *methods = rz_analysis_class_method_get_all(analysis, class_name);
RzAnalysisMethod *method;
rz_vector_foreach (methods, method) {
if (!method || !method->name) {
continue;
}
if (strstr(method->name, "_init") != NULL && strstr(method->name, "_allocating_init") == NULL) {
method->method_type = RZ_ANALYSIS_CLASS_METHOD_CONSTRUCTOR;
rz_analysis_class_method_set(analysis, class_name, method);
} else if (strstr(method->name, "_deinit") != NULL && strstr(method->name, "_deallocating_deinit") == NULL) {
method->method_type = RZ_ANALYSIS_CLASS_METHOD_DESTRUCTOR;
rz_analysis_class_method_set(analysis, class_name, method);
}
}
}
rz_pvector_free(vect);
}
/**
* \brief Process Swift RTTI information.
* This function processes Swift RTTI information from the given RzBinObject.
* It extracts class, metaclass and method information, and adds it to the analysis.
* \param analysis The RzAnalysis context to use for processing.
*/
RZ_API void rz_analysis_rtti_swift(RzAnalysis *analysis) {
HtUP *swift_metaclass_info = ht_up_new(NULL, free);
RzBinObject *bin_obj = rz_bin_cur_object(analysis->binb.bin);
const RzPVector *classes = rz_bin_object_get_classes(bin_obj);
if (!classes) {
return;
}
void **iter_class;
RzBinClass *class;
rz_pvector_foreach (classes, iter_class) {
class = *iter_class;
if (!class) {
continue;
}
RzList *fields = class->fields;
if (fields) {
add_metaclass_info(swift_metaclass_info, fields, class->name);
}
}
rz_pvector_foreach (classes, iter_class) {
class = *iter_class;
rz_add_swift_base_classes(analysis, class, swift_metaclass_info);
}
identify_constructor_destructor(analysis);
}