Rizin
unix-like reverse engineering framework and cli tools
rtti_msvc.c File Reference
#include "rz_analysis.h"

Go to the source code of this file.

Classes

struct  rtti_complete_object_locator_t
 
struct  rtti_class_hierarchy_descriptor_t
 
struct  rtti_base_class_descriptor_t
 
struct  rtti_type_descriptor_t
 
struct  recovery_base_descriptor_t
 
struct  recovery_complete_object_locator_t
 
struct  recovery_type_descriptor_t
 
struct  rtti_msvc_analysis_context_t
 

Macros

#define NAME_BUF_SIZE   64
 
#define BASE_CLASSES_MAX   32
 

Typedefs

typedef struct rtti_complete_object_locator_t rtti_complete_object_locator
 
typedef struct rtti_class_hierarchy_descriptor_t rtti_class_hierarchy_descriptor
 
typedef struct rtti_base_class_descriptor_t rtti_base_class_descriptor
 
typedef struct rtti_type_descriptor_t rtti_type_descriptor
 
typedef struct recovery_type_descriptor_t RecoveryTypeDescriptor
 
typedef struct recovery_base_descriptor_t RecoveryBaseDescriptor
 
typedef struct recovery_complete_object_locator_t RecoveryCompleteObjectLocator
 
typedef struct rtti_msvc_analysis_context_t RRTTIMSVCAnalContext
 

Functions

static void rtti_type_descriptor_fini (rtti_type_descriptor *td)
 
static ut64 rtti_msvc_addr (RVTableContext *context, ut64 col_addr, ut64 col_base, ut32 addr)
 
static bool rtti_msvc_read_complete_object_locator (RVTableContext *context, ut64 addr, rtti_complete_object_locator *col)
 
static bool rtti_msvc_read_class_hierarchy_descriptor (RVTableContext *context, ut64 addr, rtti_class_hierarchy_descriptor *chd)
 
static ut64 rtti_msvc_base_class_descriptor_size (RVTableContext *context)
 
static bool rtti_msvc_read_base_class_descriptor (RVTableContext *context, ut64 addr, rtti_base_class_descriptor *bcd)
 
static RzListrtti_msvc_read_base_class_array (RVTableContext *context, ut32 num_base_classes, ut64 base, ut32 offset)
 
static bool rtti_msvc_read_type_descriptor (RVTableContext *context, ut64 addr, rtti_type_descriptor *td)
 
static void rtti_msvc_print_complete_object_locator (rtti_complete_object_locator *col, ut64 addr, const char *prefix)
 
static void rtti_msvc_print_complete_object_locator_json (PJ *pj, rtti_complete_object_locator *col)
 
static void rtti_msvc_print_type_descriptor (rtti_type_descriptor *td, ut64 addr, const char *prefix)
 
static void rtti_msvc_print_type_descriptor_json (PJ *pj, rtti_type_descriptor *td)
 
static void rtti_msvc_print_class_hierarchy_descriptor (rtti_class_hierarchy_descriptor *chd, ut64 addr, const char *prefix)
 
static void rtti_msvc_print_class_hierarchy_descriptor_json (PJ *pj, rtti_class_hierarchy_descriptor *chd)
 
static void rtti_msvc_print_base_class_descriptor (rtti_base_class_descriptor *bcd, const char *prefix)
 
static void rtti_msvc_print_base_class_descriptor_json (PJ *pj, rtti_base_class_descriptor *bcd)
 
RZ_API char * rz_analysis_rtti_msvc_demangle_class_name (RVTableContext *context, const char *name)
 
RZ_API void rz_analysis_rtti_msvc_print_complete_object_locator (RVTableContext *context, ut64 addr, int mode)
 
RZ_API void rz_analysis_rtti_msvc_print_type_descriptor (RVTableContext *context, ut64 addr, int mode)
 
RZ_API void rz_analysis_rtti_msvc_print_class_hierarchy_descriptor (RVTableContext *context, ut64 addr, int mode)
 
RZ_API void rz_analysis_rtti_msvc_print_base_class_descriptor (RVTableContext *context, ut64 addr, int mode)
 
static bool rtti_msvc_print_complete_object_locator_recurse (RVTableContext *context, ut64 atAddress, RzOutputMode mode, bool strict)
 
RZ_API bool rz_analysis_rtti_msvc_print_at_vtable (RVTableContext *context, ut64 addr, RzOutputMode mode, bool strict)
 
RecoveryCompleteObjectLocatorrecovery_complete_object_locator_new ()
 
void recovery_complete_object_locator_free (RecoveryCompleteObjectLocator *col)
 
RecoveryTypeDescriptorrecovery_type_descriptor_new ()
 
void recovery_type_descriptor_free (RecoveryTypeDescriptor *td)
 
RecoveryTypeDescriptorrecovery_analysis_type_descriptor (RRTTIMSVCAnalContext *context, ut64 addr, RecoveryCompleteObjectLocator *col)
 
RecoveryCompleteObjectLocatorrecovery_analysis_complete_object_locator (RRTTIMSVCAnalContext *context, ut64 addr, RVTableInfo *vtable)
 
static char * unique_class_name (RzAnalysis *analysis, const char *original_name)
 
static void recovery_apply_vtable (RVTableContext *context, const char *class_name, RVTableInfo *vtable_info)
 
static const char * recovery_apply_complete_object_locator (RRTTIMSVCAnalContext *context, RecoveryCompleteObjectLocator *col)
 
static const char * recovery_apply_type_descriptor (RRTTIMSVCAnalContext *context, RecoveryTypeDescriptor *td)
 
static void recovery_apply_bases (RRTTIMSVCAnalContext *context, const char *class_name, RzVector *base_descs)
 
void str_value_free (HtUPKv *kv)
 
RZ_API void rz_analysis_rtti_msvc_recover_all (RVTableContext *vt_context, RzList *vtables)
 

Macro Definition Documentation

◆ BASE_CLASSES_MAX

#define BASE_CLASSES_MAX   32

Definition at line 9 of file rtti_msvc.c.

◆ NAME_BUF_SIZE

#define NAME_BUF_SIZE   64

Definition at line 8 of file rtti_msvc.c.

Typedef Documentation

◆ RecoveryBaseDescriptor

◆ RecoveryCompleteObjectLocator

◆ RecoveryTypeDescriptor

Definition at line 617 of file rtti_msvc.c.

◆ RRTTIMSVCAnalContext

◆ rtti_base_class_descriptor

◆ rtti_class_hierarchy_descriptor

◆ rtti_complete_object_locator

◆ rtti_type_descriptor

Function Documentation

◆ recovery_analysis_complete_object_locator()

RecoveryCompleteObjectLocator* recovery_analysis_complete_object_locator ( RRTTIMSVCAnalContext context,
ut64  addr,
RVTableInfo *  vtable 
)

Definition at line 698 of file rtti_msvc.c.

698  {
699  RecoveryCompleteObjectLocator *col = ht_up_find(context->addr_col, addr, NULL);
700  if (col) {
701  return col;
702  }
703 
705  if (!col) {
706  return NULL;
707  }
708  rz_pvector_push(&context->complete_object_locators, col);
709  ht_up_insert(context->addr_col, addr, col);
710  col->addr = addr;
711  col->valid = rtti_msvc_read_complete_object_locator(context->vt_context, addr, &col->col);
712  if (!col->valid) {
713  return col;
714  }
715  col->vtable = vtable;
716 
717  ut64 td_addr = rtti_msvc_addr(context->vt_context, col->addr, col->col.object_base, col->col.type_descriptor_addr);
718  col->td = recovery_analysis_type_descriptor(context, td_addr, col);
719  if (!col->td->valid) {
720  col->valid = false;
721  return col;
722  }
723  col->td->col = col;
724 
725  ut64 chd_addr = rtti_msvc_addr(context->vt_context, col->addr, col->col.object_base, col->col.class_descriptor_addr);
726  col->valid &= rtti_msvc_read_class_hierarchy_descriptor(context->vt_context, chd_addr, &col->chd);
727  if (!col->valid) {
728  return col;
729  }
730 
731  ut64 base = col->chd.base_class_array_addr;
732  ut32 baseClassArrayOffset = 0;
733  if (context->vt_context->word_size == 8) {
734  base = col->addr - col->col.object_base;
735  baseClassArrayOffset = col->chd.base_class_array_addr;
736  }
737 
738  col->bcd = rtti_msvc_read_base_class_array(context->vt_context, col->chd.num_base_classes, base, baseClassArrayOffset);
739  if (!col->bcd) {
740  col->valid = false;
741  return col;
742  }
743 
744  rz_vector_reserve(&col->base_td, (size_t)col->bcd->length);
745  RzListIter *bcdIter;
747  rz_list_foreach (col->bcd, bcdIter, bcd) {
748  ut64 base_td_addr = rtti_msvc_addr(context->vt_context, col->addr, col->col.object_base, bcd->type_descriptor_addr);
750  if (td == col->td) {
751  continue;
752  }
753  if (!td->valid) {
754  RZ_LOG_DEBUG("Type descriptor of base is invalid.\n");
755  continue;
756  }
757  RecoveryBaseDescriptor *base_desc = rz_vector_push(&col->base_td, NULL);
758  base_desc->bcd = bcd;
759  base_desc->td = td;
760  }
761 
762  return col;
763 }
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
static RzList * rtti_msvc_read_base_class_array(RVTableContext *context, ut32 num_base_classes, ut64 base, ut32 offset)
Definition: rtti_msvc.c:156
static bool rtti_msvc_read_class_hierarchy_descriptor(RVTableContext *context, ut64 addr, rtti_class_hierarchy_descriptor *chd)
Definition: rtti_msvc.c:95
RecoveryTypeDescriptor * recovery_analysis_type_descriptor(RRTTIMSVCAnalContext *context, ut64 addr, RecoveryCompleteObjectLocator *col)
Definition: rtti_msvc.c:765
RecoveryCompleteObjectLocator * recovery_complete_object_locator_new()
Definition: rtti_msvc.c:639
static ut64 rtti_msvc_addr(RVTableContext *context, ut64 col_addr, ut64 col_base, ut32 addr)
Definition: rtti_msvc.c:49
static bool rtti_msvc_read_complete_object_locator(RVTableContext *context, ut64 addr, rtti_complete_object_locator *col)
Definition: rtti_msvc.c:56
#define RZ_LOG_DEBUG(fmtstr,...)
Definition: rz_log.h:49
RZ_API void * rz_vector_reserve(RzVector *vec, size_t capacity)
Definition: vector.c:214
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
rtti_base_class_descriptor * bcd
Definition: rtti_msvc.c:624
RecoveryTypeDescriptor * td
Definition: rtti_msvc.c:625
RecoveryTypeDescriptor * td
Definition: rtti_msvc.c:633
rtti_class_hierarchy_descriptor chd
Definition: rtti_msvc.c:634
rtti_complete_object_locator col
Definition: rtti_msvc.c:632
RecoveryCompleteObjectLocator * col
Definition: rtti_msvc.c:661
ut32 length
Definition: rz_list.h:22
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58

References recovery_complete_object_locator_t::addr, addr, rtti_class_hierarchy_descriptor_t::base_class_array_addr, recovery_complete_object_locator_t::base_td, recovery_base_descriptor_t::bcd, recovery_complete_object_locator_t::bcd, recovery_complete_object_locator_t::chd, rtti_complete_object_locator_t::class_descriptor_addr, recovery_complete_object_locator_t::col, recovery_type_descriptor_t::col, rz_list_t::length, NULL, rtti_class_hierarchy_descriptor_t::num_base_classes, rtti_complete_object_locator_t::object_base, recovery_analysis_type_descriptor(), recovery_complete_object_locator_new(), rtti_msvc_addr(), rtti_msvc_read_base_class_array(), rtti_msvc_read_class_hierarchy_descriptor(), rtti_msvc_read_complete_object_locator(), RZ_LOG_DEBUG, rz_pvector_push(), rz_vector_push(), rz_vector_reserve(), recovery_base_descriptor_t::td, recovery_complete_object_locator_t::td, rtti_complete_object_locator_t::type_descriptor_addr, rtti_base_class_descriptor_t::type_descriptor_addr, ut64(), recovery_complete_object_locator_t::valid, recovery_type_descriptor_t::valid, and recovery_complete_object_locator_t::vtable.

Referenced by rz_analysis_rtti_msvc_recover_all().

◆ recovery_analysis_type_descriptor()

RecoveryTypeDescriptor * recovery_analysis_type_descriptor ( RRTTIMSVCAnalContext context,
ut64  addr,
RecoveryCompleteObjectLocator col 
)

Definition at line 765 of file rtti_msvc.c.

765  {
766  RecoveryTypeDescriptor *td = ht_up_find(context->addr_td, addr, NULL);
767  if (td) {
768  if (col != NULL) {
769  td->col = col;
770  }
771  return td;
772  }
773 
775  if (!td) {
776  return NULL;
777  }
778  rz_pvector_push(&context->type_descriptors, td);
779  ht_up_insert(context->addr_td, addr, td);
780  td->addr = addr;
781  td->valid = rtti_msvc_read_type_descriptor(context->vt_context, addr, &td->td);
782  if (!td->valid) {
783  return td;
784  }
785 
786  td->col = col;
787 
788  return td;
789 }
RecoveryTypeDescriptor * recovery_type_descriptor_new()
Definition: rtti_msvc.c:664
static bool rtti_msvc_read_type_descriptor(RVTableContext *context, ut64 addr, rtti_type_descriptor *td)
Definition: rtti_msvc.c:226
rtti_type_descriptor td
Definition: rtti_msvc.c:660

References recovery_type_descriptor_t::addr, addr, recovery_type_descriptor_t::col, NULL, recovery_type_descriptor_new(), rtti_msvc_read_type_descriptor(), rz_pvector_push(), recovery_type_descriptor_t::td, and recovery_type_descriptor_t::valid.

Referenced by recovery_analysis_complete_object_locator().

◆ recovery_apply_bases()

static void recovery_apply_bases ( RRTTIMSVCAnalContext context,
const char *  class_name,
RzVector base_descs 
)
static

Definition at line 855 of file rtti_msvc.c.

855  {
856  RecoveryBaseDescriptor *base_desc;
857  rz_vector_foreach(base_descs, base_desc) {
858  RecoveryTypeDescriptor *base_td = base_desc->td;
859  if (!base_td->valid) {
860  RZ_LOG_WARN("Base td is invalid!\n");
861  continue;
862  }
863 
864  const char *base_class_name;
865  if (!base_td->col) {
866  RZ_LOG_DEBUG("Base td %s has no col. Falling back to recovery from td only.\n", base_td->td.name);
867  base_class_name = recovery_apply_type_descriptor(context, base_td);
868  } else {
869  base_class_name = recovery_apply_complete_object_locator(context, base_td->col);
870  }
871 
872  if (!base_class_name) {
873  RZ_LOG_DEBUG("Failed to convert !base td->col or td to a class\n");
874  continue;
875  }
876 
877  RzAnalysisBaseClass base;
878  base.id = NULL;
879  base.offset = (ut64)base_desc->bcd->where.mdisp;
880  base.class_name = strdup(base_class_name);
881  rz_analysis_class_base_set(context->vt_context->analysis, class_name, &base);
883  }
884 }
RZ_API RzAnalysisClassErr rz_analysis_class_base_set(RzAnalysis *analysis, const char *class_name, RzAnalysisBaseClass *base)
Definition: class.c:983
RZ_API void rz_analysis_class_base_fini(RzAnalysisBaseClass *base)
Definition: class.c:880
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
static const char * recovery_apply_complete_object_locator(RRTTIMSVCAnalContext *context, RecoveryCompleteObjectLocator *col)
Definition: rtti_msvc.c:886
static const char * recovery_apply_type_descriptor(RRTTIMSVCAnalContext *context, RecoveryTypeDescriptor *td)
Definition: rtti_msvc.c:928
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define rz_vector_foreach(vec, it)
Definition: rz_vector.h:169
struct rtti_base_class_descriptor_t::@22 where

References recovery_base_descriptor_t::bcd, recovery_type_descriptor_t::col, rtti_base_class_descriptor_t::mdisp, rtti_type_descriptor_t::name, NULL, recovery_apply_complete_object_locator(), recovery_apply_type_descriptor(), rz_analysis_class_base_fini(), rz_analysis_class_base_set(), RZ_LOG_DEBUG, RZ_LOG_WARN, rz_vector_foreach, strdup(), recovery_base_descriptor_t::td, recovery_type_descriptor_t::td, ut64(), recovery_type_descriptor_t::valid, and rtti_base_class_descriptor_t::where.

Referenced by recovery_apply_complete_object_locator(), and recovery_apply_type_descriptor().

◆ recovery_apply_complete_object_locator()

static const char * recovery_apply_complete_object_locator ( RRTTIMSVCAnalContext context,
RecoveryCompleteObjectLocator col 
)
static

Definition at line 886 of file rtti_msvc.c.

886  {
887  if (!col->valid) {
888  return NULL;
889  }
890 
891  if (!col->td) {
892  RZ_LOG_DEBUG("No recovery type descriptor for recovery object locator at 0x%" PFMT64x "\n", col->addr);
893  return NULL;
894  }
895 
896  RzAnalysis *analysis = context->vt_context->analysis;
897 
898  const char *existing = ht_up_find(context->col_td_classes, col->addr, NULL);
899  if (existing != NULL) {
900  return existing;
901  }
902 
903  char *name = rz_analysis_rtti_msvc_demangle_class_name(context->vt_context, col->td->td.name);
904  if (!name) {
905  RZ_LOG_DEBUG("Failed to demangle a class name: \"%s\"\n", col->td->td.name);
906  name = strdup(col->td->td.name);
907  if (!name) {
908  return NULL;
909  }
910  }
911 
912  char *tmp = name;
913  name = unique_class_name(analysis, name);
914  free(tmp);
915  if (!name) {
916  return NULL;
917  }
918 
919  rz_analysis_class_create(analysis, name);
920  ht_up_insert(context->col_td_classes, col->addr, name);
921 
922  recovery_apply_vtable(context->vt_context, name, col->vtable);
924 
925  return name;
926 }
RZ_API RzAnalysisClassErr rz_analysis_class_create(RzAnalysis *analysis, const char *name)
Definition: class.c:79
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
const char * name
Definition: op.c:541
RZ_API char * rz_analysis_rtti_msvc_demangle_class_name(RVTableContext *context, const char *name)
Definition: rtti_msvc.c:393
static void recovery_apply_bases(RRTTIMSVCAnalContext *context, const char *class_name, RzVector *base_descs)
Definition: rtti_msvc.c:855
static void recovery_apply_vtable(RVTableContext *context, const char *class_name, RVTableInfo *vtable_info)
Definition: rtti_msvc.c:810
static char * unique_class_name(RzAnalysis *analysis, const char *original_name)
Definition: rtti_msvc.c:791
#define PFMT64x
Definition: rz_types.h:393
Definition: z80asm.h:102

References recovery_complete_object_locator_t::addr, recovery_complete_object_locator_t::base_td, free(), name, rtti_type_descriptor_t::name, NULL, PFMT64x, recovery_apply_bases(), recovery_apply_vtable(), rz_analysis_class_create(), rz_analysis_rtti_msvc_demangle_class_name(), RZ_LOG_DEBUG, strdup(), recovery_complete_object_locator_t::td, recovery_type_descriptor_t::td, autogen_x86imm::tmp, unique_class_name(), recovery_complete_object_locator_t::valid, and recovery_complete_object_locator_t::vtable.

Referenced by recovery_apply_bases(), and rz_analysis_rtti_msvc_recover_all().

◆ recovery_apply_type_descriptor()

static const char * recovery_apply_type_descriptor ( RRTTIMSVCAnalContext context,
RecoveryTypeDescriptor td 
)
static

Definition at line 928 of file rtti_msvc.c.

928  {
929  if (!td->valid) {
930  return NULL;
931  }
932 
933  RzAnalysis *analysis = context->vt_context->analysis;
934 
935  const char *existing = ht_up_find(context->col_td_classes, td->addr, NULL);
936  if (existing != NULL) {
937  return existing;
938  }
939 
941  if (!name) {
942  RZ_LOG_DEBUG("Failed to demangle a class name: \"%s\"\n", td->td.name);
943  name = strdup(td->td.name);
944  if (!name) {
945  return NULL;
946  }
947  }
948 
949  rz_analysis_class_create(analysis, name);
950  ht_up_insert(context->col_td_classes, td->addr, name);
951 
952  if (!td->col || !td->col->valid) {
953  return name;
954  }
955 
956  recovery_apply_vtable(context->vt_context, name, td->col->vtable);
958 
959  return name;
960 }

References recovery_type_descriptor_t::addr, recovery_complete_object_locator_t::base_td, recovery_type_descriptor_t::col, name, rtti_type_descriptor_t::name, NULL, recovery_apply_bases(), recovery_apply_vtable(), rz_analysis_class_create(), rz_analysis_rtti_msvc_demangle_class_name(), RZ_LOG_DEBUG, strdup(), recovery_type_descriptor_t::td, recovery_complete_object_locator_t::valid, recovery_type_descriptor_t::valid, and recovery_complete_object_locator_t::vtable.

Referenced by recovery_apply_bases(), and rz_analysis_rtti_msvc_recover_all().

◆ recovery_apply_vtable()

static void recovery_apply_vtable ( RVTableContext *  context,
const char *  class_name,
RVTableInfo *  vtable_info 
)
static

Definition at line 810 of file rtti_msvc.c.

810  {
811  if (!vtable_info) {
812  return;
813  }
814 
816 
817  RzAnalysisVTable vtable;
818  vtable.size = size;
819  vtable.id = NULL;
820  vtable.offset = 0;
821  vtable.addr = vtable_info->saddr;
822  rz_analysis_class_vtable_set(context->analysis, class_name, &vtable);
824 
825  RVTableMethodInfo *vmeth;
826  rz_vector_foreach(&vtable_info->methods, vmeth) {
827  RzAnalysisMethod meth;
828  if (!rz_analysis_class_method_exists_by_addr(context->analysis, class_name, vmeth->addr)) {
829  meth.addr = vmeth->addr;
830  meth.vtable_offset = vmeth->vtable_offset;
831  RzAnalysisFunction *fcn = rz_analysis_get_function_at(context->analysis, vmeth->addr);
832  meth.name = fcn ? rz_str_new(fcn->name) : rz_str_newf("virtual_%" PFMT64d, meth.vtable_offset);
833  // Temporarily set as attr name
834  meth.real_name = fcn ? rz_str_new(fcn->name) : rz_str_newf("virtual_%" PFMT64d, meth.vtable_offset);
835  meth.method_type = RZ_ANALYSIS_CLASS_METHOD_VIRTUAL;
836  } else {
837  RzAnalysisMethod exist_meth;
838  if (rz_analysis_class_method_get_by_addr(context->analysis, class_name, vmeth->addr, &exist_meth) == RZ_ANALYSIS_CLASS_ERR_SUCCESS) {
839  meth.addr = vmeth->addr;
840  meth.name = rz_str_new(exist_meth.name);
841  meth.real_name = rz_str_new(exist_meth.real_name);
842  meth.vtable_offset = vmeth->vtable_offset;
843  meth.method_type = RZ_ANALYSIS_CLASS_METHOD_VIRTUAL;
844  rz_analysis_class_method_fini(&exist_meth);
845  }
846  }
847  rz_analysis_class_method_set(context->analysis, class_name, &meth);
849  }
850 }
RZ_API RzAnalysisFunction * rz_analysis_get_function_at(RzAnalysis *analysis, ut64 addr)
Definition: function.c:184
RZ_API bool rz_analysis_class_method_exists_by_addr(RzAnalysis *analysis, const char *class_name, ut64 addr)
Definition: class.c:643
RZ_API void rz_analysis_class_vtable_fini(RzAnalysisVTable *vtable)
Definition: class.c:1069
RZ_API RzAnalysisClassErr rz_analysis_class_vtable_set(RzAnalysis *analysis, const char *class_name, RzAnalysisVTable *vtable)
Definition: class.c:1153
RZ_API RzAnalysisClassErr rz_analysis_class_method_set(RzAnalysis *analysis, const char *class_name, RzAnalysisMethod *meth)
Definition: class.c:770
RZ_API void rz_analysis_class_method_fini(RzAnalysisMethod *meth)
Definition: class.c:606
RZ_API RzAnalysisClassErr rz_analysis_class_method_get_by_addr(RzAnalysis *analysis, const char *class_name, ut64 addr, RzAnalysisMethod *method)
Definition: class.c:659
voidpf void uLong size
Definition: ioapi.h:138
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_str_new(const char *str)
Definition: str.c:865
#define PFMT64d
Definition: rz_types.h:394
RZ_API ut64 rz_analysis_vtable_info_get_size(RVTableContext *context, RVTableInfo *vtable)
Definition: vtable.c:37

References rz_analysis_function_t::name, NULL, PFMT64d, rz_analysis_class_method_exists_by_addr(), rz_analysis_class_method_fini(), rz_analysis_class_method_get_by_addr(), rz_analysis_class_method_set(), rz_analysis_class_vtable_fini(), rz_analysis_class_vtable_set(), rz_analysis_get_function_at(), rz_analysis_vtable_info_get_size(), rz_str_new(), rz_str_newf(), rz_vector_foreach, and ut64().

Referenced by recovery_apply_complete_object_locator(), and recovery_apply_type_descriptor().

◆ recovery_complete_object_locator_free()

void recovery_complete_object_locator_free ( RecoveryCompleteObjectLocator col)

Definition at line 648 of file rtti_msvc.c.

648  {
649  if (!col) {
650  return;
651  }
652  rz_list_free(col->bcd);
653  rz_vector_clear(&col->base_td);
654  free(col);
655 }
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
RZ_API void rz_vector_clear(RzVector *vec)
Definition: vector.c:68

References recovery_complete_object_locator_t::base_td, recovery_complete_object_locator_t::bcd, free(), rz_list_free(), and rz_vector_clear().

Referenced by rz_analysis_rtti_msvc_recover_all().

◆ recovery_complete_object_locator_new()

RecoveryCompleteObjectLocator* recovery_complete_object_locator_new ( )

Definition at line 639 of file rtti_msvc.c.

639  {
641  if (!col) {
642  return NULL;
643  }
645  return col;
646 }
#define RZ_NEW0(x)
Definition: rz_types.h:284
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:33

References recovery_complete_object_locator_t::base_td, NULL, RZ_NEW0, and rz_vector_init().

Referenced by recovery_analysis_complete_object_locator().

◆ recovery_type_descriptor_free()

void recovery_type_descriptor_free ( RecoveryTypeDescriptor td)

Definition at line 678 of file rtti_msvc.c.

678  {
679  if (!td) {
680  return;
681  }
683  free(td);
684 }
static void rtti_type_descriptor_fini(rtti_type_descriptor *td)
Definition: rtti_msvc.c:44

References free(), rtti_type_descriptor_fini(), and recovery_type_descriptor_t::td.

Referenced by rz_analysis_rtti_msvc_recover_all().

◆ recovery_type_descriptor_new()

RecoveryTypeDescriptor* recovery_type_descriptor_new ( )

Definition at line 664 of file rtti_msvc.c.

664  {
666  if (!td) {
667  return NULL;
668  }
669 
670  td->addr = 0;
671  td->valid = false;
672  memset(&td->td, 0, sizeof(td->td));
673  td->col = NULL;
674  // td->vtable = NULL;
675  return td;
676 }
return memset(p, 0, total)
#define RZ_NEW(x)
Definition: rz_types.h:285

References recovery_type_descriptor_t::addr, recovery_type_descriptor_t::col, memset(), NULL, RZ_NEW, recovery_type_descriptor_t::td, and recovery_type_descriptor_t::valid.

Referenced by recovery_analysis_type_descriptor().

◆ rtti_msvc_addr()

static ut64 rtti_msvc_addr ( RVTableContext *  context,
ut64  col_addr,
ut64  col_base,
ut32  addr 
)
inlinestatic

Definition at line 49 of file rtti_msvc.c.

49  {
50  if (context->word_size != 8) {
51  return addr;
52  }
53  return addr + (col_addr - col_base);
54 }

References addr.

Referenced by recovery_analysis_complete_object_locator(), and rtti_msvc_print_complete_object_locator_recurse().

◆ rtti_msvc_base_class_descriptor_size()

static ut64 rtti_msvc_base_class_descriptor_size ( RVTableContext *  context)
static

Definition at line 125 of file rtti_msvc.c.

125  {
126  return context->word_size + 5 * sizeof(ut32);
127 }

Referenced by rtti_msvc_read_base_class_descriptor().

◆ rtti_msvc_print_base_class_descriptor()

static void rtti_msvc_print_base_class_descriptor ( rtti_base_class_descriptor bcd,
const char *  prefix 
)
static

Definition at line 352 of file rtti_msvc.c.

352  {
353  rz_cons_printf("%sBase Class Descriptor:\n"
354  "%s\ttypeDescriptorAddr: 0x%08" PFMT32x "\n"
355  "%s\tnumContainedBases: %#x\n"
356  "%s\twhere:\n"
357  "%s\t\tmdisp: %d\n"
358  "%s\t\tpdisp: %d\n"
359  "%s\t\tvdisp: %d\n"
360  "%s\tattributes: %#x\n\n",
361  prefix,
364  prefix,
365  prefix, bcd->where.mdisp,
366  prefix, bcd->where.pdisp,
367  prefix, bcd->where.vdisp,
368  prefix, bcd->attributes);
369 }
#define PFMT32x
RZ_API int rz_cons_printf(const char *format,...)
Definition: cons.c:1202
unsigned short prefix[65536]
Definition: gun.c:163

References rtti_base_class_descriptor_t::attributes, rtti_base_class_descriptor_t::mdisp, rtti_base_class_descriptor_t::num_contained_bases, rtti_base_class_descriptor_t::pdisp, PFMT32x, prefix, rz_cons_printf(), rtti_base_class_descriptor_t::type_descriptor_addr, rtti_base_class_descriptor_t::vdisp, and rtti_base_class_descriptor_t::where.

Referenced by rtti_msvc_print_complete_object_locator_recurse(), and rz_analysis_rtti_msvc_print_base_class_descriptor().

◆ rtti_msvc_print_base_class_descriptor_json()

static void rtti_msvc_print_base_class_descriptor_json ( PJ pj,
rtti_base_class_descriptor bcd 
)
static

Definition at line 371 of file rtti_msvc.c.

371  {
372  pj_o(pj);
373  pj_kn(pj, "type_desc_addr", bcd->type_descriptor_addr);
374  pj_kn(pj, "num_contained_bases", bcd->num_contained_bases);
375  pj_ko(pj, "where");
376  pj_ki(pj, "mdisp", bcd->where.mdisp);
377  pj_ki(pj, "pdisp", bcd->where.pdisp);
378  pj_ki(pj, "vdisp", bcd->where.vdisp);
379  pj_end(pj);
380  pj_kn(pj, "attributes", bcd->attributes);
381  pj_end(pj);
382 }
RZ_API PJ * pj_ko(PJ *j, const char *k)
Definition: pj.c:156
RZ_API PJ * pj_ki(PJ *j, const char *k, int d)
Definition: pj.c:149
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_kn(PJ *j, const char *k, ut64 n)
Definition: pj.c:121

References rtti_base_class_descriptor_t::attributes, rtti_base_class_descriptor_t::mdisp, rtti_base_class_descriptor_t::num_contained_bases, rtti_base_class_descriptor_t::pdisp, pj_end(), pj_ki(), pj_kn(), pj_ko(), pj_o(), rtti_base_class_descriptor_t::type_descriptor_addr, rtti_base_class_descriptor_t::vdisp, and rtti_base_class_descriptor_t::where.

Referenced by rtti_msvc_print_complete_object_locator_recurse(), and rz_analysis_rtti_msvc_print_base_class_descriptor().

◆ rtti_msvc_print_class_hierarchy_descriptor()

static void rtti_msvc_print_class_hierarchy_descriptor ( rtti_class_hierarchy_descriptor chd,
ut64  addr,
const char *  prefix 
)
static

Definition at line 330 of file rtti_msvc.c.

330  {
331  rz_cons_printf("%sClass Hierarchy Descriptor at 0x%08" PFMT64x ":\n"
332  "%s\tsignature: %#x\n"
333  "%s\tattributes: %#x\n"
334  "%s\tnumBaseClasses: %#x\n"
335  "%s\tbaseClassArrayAddr: 0x%08" PFMT32x "\n\n",
336  prefix, addr,
337  prefix, chd->signature,
338  prefix, chd->attributes,
339  prefix, chd->num_base_classes,
341 }

References addr, rtti_class_hierarchy_descriptor_t::attributes, rtti_class_hierarchy_descriptor_t::base_class_array_addr, rtti_class_hierarchy_descriptor_t::num_base_classes, PFMT32x, PFMT64x, prefix, rz_cons_printf(), and rtti_class_hierarchy_descriptor_t::signature.

Referenced by rtti_msvc_print_complete_object_locator_recurse(), and rz_analysis_rtti_msvc_print_class_hierarchy_descriptor().

◆ rtti_msvc_print_class_hierarchy_descriptor_json()

static void rtti_msvc_print_class_hierarchy_descriptor_json ( PJ pj,
rtti_class_hierarchy_descriptor chd 
)
static

◆ rtti_msvc_print_complete_object_locator()

static void rtti_msvc_print_complete_object_locator ( rtti_complete_object_locator col,
ut64  addr,
const char *  prefix 
)
static

Definition at line 283 of file rtti_msvc.c.

283  {
284  rz_cons_printf("%sComplete Object Locator at 0x%08" PFMT64x ":\n"
285  "%s\tsignature: %#x\n"
286  "%s\tvftableOffset: %#x\n"
287  "%s\tcdOffset: %#x\n"
288  "%s\ttypeDescriptorAddr: 0x%08" PFMT32x "\n"
289  "%s\tclassDescriptorAddr: 0x%08" PFMT32x "\n",
290  prefix, addr,
291  prefix, col->signature,
292  prefix, col->vtable_offset,
293  prefix, col->cd_offset,
296  rz_cons_printf("%s\tobjectBase: 0x%08" PFMT32x "\n\n",
297  prefix, col->object_base);
298 }

References addr, rtti_complete_object_locator_t::cd_offset, rtti_complete_object_locator_t::class_descriptor_addr, rtti_complete_object_locator_t::object_base, PFMT32x, PFMT64x, prefix, rz_cons_printf(), rtti_complete_object_locator_t::signature, rtti_complete_object_locator_t::type_descriptor_addr, and rtti_complete_object_locator_t::vtable_offset.

Referenced by rtti_msvc_print_complete_object_locator_recurse(), and rz_analysis_rtti_msvc_print_complete_object_locator().

◆ rtti_msvc_print_complete_object_locator_json()

static void rtti_msvc_print_complete_object_locator_json ( PJ pj,
rtti_complete_object_locator col 
)
static

◆ rtti_msvc_print_complete_object_locator_recurse()

static bool rtti_msvc_print_complete_object_locator_recurse ( RVTableContext *  context,
ut64  atAddress,
RzOutputMode  mode,
bool  strict 
)
static

Definition at line 499 of file rtti_msvc.c.

499  {
500  ut64 colRefAddr = atAddress - context->word_size;
501  ut64 colAddr;
502  if (!context->read_addr(context->analysis, colRefAddr, &colAddr)) {
503  return false;
504  }
505 
506  // complete object locator
508  if (!rtti_msvc_read_complete_object_locator(context, colAddr, &col)) {
509  if (!strict) {
510  RZ_LOG_ERROR("Failed to parse complete object locator at 0x%08" PFMT64x " (referenced from 0x%08" PFMT64x ")\n", colAddr, colRefAddr);
511  }
512  return false;
513  }
514 
515  // type descriptor
516  ut64 typeDescriptorAddr = rtti_msvc_addr(context, colAddr, col.object_base, col.type_descriptor_addr);
517  rtti_type_descriptor td = { 0 };
518  if (!rtti_msvc_read_type_descriptor(context, typeDescriptorAddr, &td)) {
519  if (!strict) {
520  RZ_LOG_ERROR("Failed to parse type descriptor at 0x%08" PFMT64x "\n", typeDescriptorAddr);
521  }
522  return false;
523  }
524 
525  // class hierarchy descriptor
526  ut64 classHierarchyDescriptorAddr = rtti_msvc_addr(context, colAddr, col.object_base, col.class_descriptor_addr);
528  if (!rtti_msvc_read_class_hierarchy_descriptor(context, classHierarchyDescriptorAddr, &chd)) {
529  if (!strict) {
530  RZ_LOG_ERROR("Failed to parse class hierarchy descriptor at 0x%08" PFMT64x "\n", classHierarchyDescriptorAddr);
531  }
533  return false;
534  }
535 
536  ut64 base = chd.base_class_array_addr;
537  ut32 baseClassArrayOffset = 0;
538  if (context->word_size == 8) {
539  base = colAddr - col.object_base;
540  baseClassArrayOffset = chd.base_class_array_addr;
541  }
542 
543  RzList *baseClassArray = rtti_msvc_read_base_class_array(context, chd.num_base_classes, base, baseClassArrayOffset);
544  if (!baseClassArray) {
545  if (!strict) {
546  RZ_LOG_ERROR("Failed to parse base class array starting at 0x%08" PFMT64x "\n", base + baseClassArrayOffset);
547  }
549  return false;
550  }
551 
552  // print
553  bool use_json = mode == RZ_OUTPUT_MODE_JSON;
554  PJ *pj = NULL;
555  if (use_json) {
556  pj = pj_new();
557  if (!pj) {
558  return false;
559  }
560  pj_o(pj);
561  pj_k(pj, "complete_object_locator");
563  pj_k(pj, "type_desc");
565  pj_k(pj, "class_hierarchy_desc");
567  pj_ka(pj, "base_classes");
568  } else {
569  rtti_msvc_print_complete_object_locator(&col, colAddr, "");
570  rtti_msvc_print_type_descriptor(&td, typeDescriptorAddr, "\t");
571  rtti_msvc_print_class_hierarchy_descriptor(&chd, classHierarchyDescriptorAddr, "\t");
572  }
573 
574  // base classes
575  RzListIter *bcdIter;
577  rz_list_foreach (baseClassArray, bcdIter, bcd) {
578  if (use_json) {
579  pj_o(pj);
580  pj_k(pj, "desc");
582  } else {
584  }
585 
586  ut64 baseTypeDescriptorAddr = rtti_msvc_addr(context, colAddr, col.object_base, bcd->type_descriptor_addr);
587  rtti_type_descriptor btd = { 0 };
588  if (rtti_msvc_read_type_descriptor(context, baseTypeDescriptorAddr, &btd)) {
589  if (use_json) {
590  pj_k(pj, "type_desc");
592  } else {
593  rtti_msvc_print_type_descriptor(&btd, baseTypeDescriptorAddr, "\t\t\t");
594  }
596  } else {
597  if (!strict) {
598  RZ_LOG_ERROR("Failed to parse type descriptor at 0x%08" PFMT64x "\n", baseTypeDescriptorAddr);
599  }
600  }
601 
602  if (use_json) {
603  pj_end(pj);
604  }
605  }
606  if (use_json) {
607  pj_end(pj);
608  pj_end(pj);
609  rz_cons_print(pj_string(pj));
610  pj_free(pj);
611  }
612 
614  return true;
615 }
const char int mode
Definition: ioapi.h:137
static void rtti_msvc_print_base_class_descriptor_json(PJ *pj, rtti_base_class_descriptor *bcd)
Definition: rtti_msvc.c:371
static void rtti_msvc_print_class_hierarchy_descriptor_json(PJ *pj, rtti_class_hierarchy_descriptor *chd)
Definition: rtti_msvc.c:343
static void rtti_msvc_print_type_descriptor_json(PJ *pj, rtti_type_descriptor *td)
Definition: rtti_msvc.c:322
static void rtti_msvc_print_complete_object_locator_json(PJ *pj, rtti_complete_object_locator *col)
Definition: rtti_msvc.c:300
static void rtti_msvc_print_base_class_descriptor(rtti_base_class_descriptor *bcd, const char *prefix)
Definition: rtti_msvc.c:352
static void rtti_msvc_print_class_hierarchy_descriptor(rtti_class_hierarchy_descriptor *chd, ut64 addr, const char *prefix)
Definition: rtti_msvc.c:330
static void rtti_msvc_print_complete_object_locator(rtti_complete_object_locator *col, ut64 addr, const char *prefix)
Definition: rtti_msvc.c:283
static void rtti_msvc_print_type_descriptor(rtti_type_descriptor *td, ut64 addr, const char *prefix)
Definition: rtti_msvc.c:311
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API PJ * pj_ka(PJ *j, const char *k)
Definition: pj.c:163
RZ_API PJ * pj_new(void)
Definition: pj.c:25
RZ_API PJ * pj_k(PJ *j, const char *k)
Definition: pj.c:104
RZ_API const char * pj_string(PJ *pj)
Definition: pj.c:57
RZ_API void pj_free(PJ *j)
Definition: pj.c:34
@ RZ_OUTPUT_MODE_JSON
Definition: rz_types.h:40
Definition: rz_pj.h:12

References rtti_class_hierarchy_descriptor_t::base_class_array_addr, rtti_complete_object_locator_t::class_descriptor_addr, NULL, rtti_class_hierarchy_descriptor_t::num_base_classes, rtti_complete_object_locator_t::object_base, PFMT64x, pj_end(), pj_free(), pj_k(), pj_ka(), pj_new(), pj_o(), pj_string(), rtti_msvc_addr(), rtti_msvc_print_base_class_descriptor(), rtti_msvc_print_base_class_descriptor_json(), rtti_msvc_print_class_hierarchy_descriptor(), rtti_msvc_print_class_hierarchy_descriptor_json(), rtti_msvc_print_complete_object_locator(), rtti_msvc_print_complete_object_locator_json(), rtti_msvc_print_type_descriptor(), rtti_msvc_print_type_descriptor_json(), rtti_msvc_read_base_class_array(), rtti_msvc_read_class_hierarchy_descriptor(), rtti_msvc_read_complete_object_locator(), rtti_msvc_read_type_descriptor(), rtti_type_descriptor_fini(), RZ_LOG_ERROR, RZ_OUTPUT_MODE_JSON, rtti_complete_object_locator_t::type_descriptor_addr, rtti_base_class_descriptor_t::type_descriptor_addr, and ut64().

◆ rtti_msvc_print_type_descriptor()

static void rtti_msvc_print_type_descriptor ( rtti_type_descriptor td,
ut64  addr,
const char *  prefix 
)
static

Definition at line 311 of file rtti_msvc.c.

311  {
312  rz_cons_printf("%sType Descriptor at 0x%08" PFMT64x ":\n"
313  "%s\tvtableAddr: 0x%08" PFMT64x "\n"
314  "%s\tspare: 0x%08" PFMT64x "\n"
315  "%s\tname: %s\n\n",
316  prefix, addr,
317  prefix, td->vtable_addr,
318  prefix, td->spare,
319  prefix, td->name);
320 }

References addr, rtti_type_descriptor_t::name, PFMT64x, prefix, rz_cons_printf(), rtti_type_descriptor_t::spare, and rtti_type_descriptor_t::vtable_addr.

Referenced by rtti_msvc_print_complete_object_locator_recurse(), and rz_analysis_rtti_msvc_print_type_descriptor().

◆ rtti_msvc_print_type_descriptor_json()

static void rtti_msvc_print_type_descriptor_json ( PJ pj,
rtti_type_descriptor td 
)
static

Definition at line 322 of file rtti_msvc.c.

322  {
323  pj_o(pj);
324  pj_kn(pj, "vtable_addr", td->vtable_addr);
325  pj_kn(pj, "spare", td->spare);
326  pj_ks(pj, "name", td->name);
327  pj_end(pj);
328 }
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170

References rtti_type_descriptor_t::name, pj_end(), pj_kn(), pj_ks(), pj_o(), rtti_type_descriptor_t::spare, and rtti_type_descriptor_t::vtable_addr.

Referenced by rtti_msvc_print_complete_object_locator_recurse(), and rz_analysis_rtti_msvc_print_type_descriptor().

◆ rtti_msvc_read_base_class_array()

static RzList* rtti_msvc_read_base_class_array ( RVTableContext *  context,
ut32  num_base_classes,
ut64  base,
ut32  offset 
)
static

Definition at line 156 of file rtti_msvc.c.

156  {
157  if (base == UT64_MAX || offset == UT32_MAX || num_base_classes == UT32_MAX) {
158  return NULL;
159  }
160 
161  RzList *ret = rz_list_newf(free);
162  if (!ret) {
163  return NULL;
164  }
165 
166  ut64 addr = base + offset;
167  ut64 stride = RZ_MIN(context->word_size, 4);
168 
169  if (num_base_classes > BASE_CLASSES_MAX) {
170  RZ_LOG_DEBUG("Length of base class array at 0x%08" PFMT64x " exceeds %d.\n", addr, BASE_CLASSES_MAX);
171  num_base_classes = BASE_CLASSES_MAX;
172  }
173 
175  while (num_base_classes > 0) {
176  if (rz_cons_is_breaked()) {
177  break;
178  }
179 
180  ut64 bcdAddr;
181  if (context->word_size <= 4) {
182  if (!context->read_addr(context->analysis, addr, &bcdAddr)) {
183  break;
184  }
185  if (bcdAddr == UT32_MAX) {
186  break;
187  }
188  } else {
189  // special offset calculation for 64bit
190  ut8 tmp[4] = { 0 };
191  if (!context->analysis->iob.read_at(context->analysis->iob.io, addr, tmp, 4)) {
192  rz_list_free(ret);
193  return NULL;
194  }
195  ut32 (*read_32)(const void *src) = context->analysis->big_endian ? rz_read_be32 : rz_read_le32;
196  ut32 bcdOffset = read_32(tmp);
197  if (bcdOffset == UT32_MAX) {
198  break;
199  }
200  bcdAddr = base + bcdOffset;
201  }
202 
204  if (!bcd) {
205  break;
206  }
207  if (!rtti_msvc_read_base_class_descriptor(context, bcdAddr, bcd)) {
208  free(bcd);
209  break;
210  }
211  rz_list_append(ret, bcd);
212  addr += stride;
213  num_base_classes--;
214  }
216 
217  if (num_base_classes > 0) {
218  // there was an error in the loop above
219  rz_list_free(ret);
220  return NULL;
221  }
222 
223  return ret;
224 }
lzma_index * src
Definition: index.h:567
RZ_API void rz_cons_break_pop(void)
Definition: cons.c:361
RZ_API void rz_cons_break_push(RzConsBreak cb, void *user)
Definition: cons.c:357
RZ_API bool rz_cons_is_breaked(void)
Definition: cons.c:373
voidpf uLong offset
Definition: ioapi.h:144
uint8_t ut8
Definition: lh5801.h:11
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
void * malloc(size_t size)
Definition: malloc.c:123
static bool rtti_msvc_read_base_class_descriptor(RVTableContext *context, ut64 addr, rtti_base_class_descriptor *bcd)
Definition: rtti_msvc.c:129
#define BASE_CLASSES_MAX
Definition: rtti_msvc.c:9
static ut32 rz_read_le32(const void *src)
Definition: rz_endian.h:239
static ut32 rz_read_be32(const void *src)
Definition: rz_endian.h:87
#define RZ_MIN(x, y)
#define UT32_MAX
Definition: rz_types_base.h:99
#define UT64_MAX
Definition: rz_types_base.h:86

References addr, BASE_CLASSES_MAX, free(), malloc(), NULL, PFMT64x, rtti_msvc_read_base_class_descriptor(), rz_cons_break_pop(), rz_cons_break_push(), rz_cons_is_breaked(), rz_list_append(), rz_list_free(), rz_list_newf(), RZ_LOG_DEBUG, RZ_MIN, rz_read_be32(), rz_read_le32(), src, autogen_x86imm::tmp, UT32_MAX, ut64(), and UT64_MAX.

Referenced by recovery_analysis_complete_object_locator(), and rtti_msvc_print_complete_object_locator_recurse().

◆ rtti_msvc_read_base_class_descriptor()

static bool rtti_msvc_read_base_class_descriptor ( RVTableContext *  context,
ut64  addr,
rtti_base_class_descriptor bcd 
)
static

Definition at line 129 of file rtti_msvc.c.

129  {
130  if (addr == UT64_MAX) {
131  return false;
132  }
133 
134  ut8 buf[sizeof(ut64) + 5 * sizeof(ut32)];
136  if (bcdSize > sizeof(buf)) {
137  return false;
138  }
139 
140  if (!context->analysis->iob.read_at(context->analysis->iob.io, addr, buf, bcdSize)) {
141  return false;
142  }
143 
144  ut32 (*read_at_32)(const void *src, size_t offset) = context->analysis->big_endian ? rz_read_at_be32 : rz_read_at_le32;
145  int typeDescriptorAddrSize = RZ_MIN(context->word_size, 4);
146  bcd->type_descriptor_addr = (ut32)rz_read_ble(buf, (bool)context->analysis->big_endian, typeDescriptorAddrSize * 8);
147  size_t offset = (size_t)typeDescriptorAddrSize;
148  bcd->num_contained_bases = read_at_32(buf, offset);
149  bcd->where.mdisp = read_at_32(buf, offset + sizeof(ut32));
150  bcd->where.pdisp = read_at_32(buf, offset + 2 * sizeof(ut32));
151  bcd->where.vdisp = read_at_32(buf, offset + 3 * sizeof(ut32));
152  bcd->attributes = read_at_32(buf, offset + 4 * sizeof(ut32));
153  return true;
154 }
voidpf void * buf
Definition: ioapi.h:138
static ut64 rtti_msvc_base_class_descriptor_size(RVTableContext *context)
Definition: rtti_msvc.c:125
static ut32 rz_read_at_le32(const void *src, size_t offset)
Definition: rz_endian.h:248
static ut64 rz_read_ble(const void *src, bool big_endian, int size)
Definition: rz_endian.h:517
static ut32 rz_read_at_be32(const void *src, size_t offset)
Definition: rz_endian.h:93
static int
Definition: sfsocketcall.h:114
int size_t
Definition: sftypes.h:40

References addr, rtti_base_class_descriptor_t::attributes, int, rtti_base_class_descriptor_t::mdisp, rtti_base_class_descriptor_t::num_contained_bases, rtti_base_class_descriptor_t::pdisp, rtti_msvc_base_class_descriptor_size(), RZ_MIN, rz_read_at_be32(), rz_read_at_le32(), rz_read_ble(), src, rtti_base_class_descriptor_t::type_descriptor_addr, ut64(), UT64_MAX, rtti_base_class_descriptor_t::vdisp, and rtti_base_class_descriptor_t::where.

Referenced by rtti_msvc_read_base_class_array(), and rz_analysis_rtti_msvc_print_base_class_descriptor().

◆ rtti_msvc_read_class_hierarchy_descriptor()

static bool rtti_msvc_read_class_hierarchy_descriptor ( RVTableContext *  context,
ut64  addr,
rtti_class_hierarchy_descriptor chd 
)
static

Definition at line 95 of file rtti_msvc.c.

95  {
96  if (addr == UT64_MAX) {
97  return false;
98  }
99 
100  ut8 buf[4 * sizeof(ut32)];
101  int chdSize = 3 * sizeof(ut32) + RZ_MIN(4, context->word_size);
102  if (chdSize > sizeof(buf)) {
103  return false;
104  }
105 
106  if (!context->analysis->iob.read_at(context->analysis->iob.io, addr, buf, chdSize)) {
107  return false;
108  }
109 
110  ut32 (*read_at_32)(const void *src, size_t offset) = context->analysis->big_endian ? rz_read_at_be32 : rz_read_at_le32;
111  chd->signature = read_at_32(buf, 0);
112  chd->attributes = read_at_32(buf, 4);
113  chd->num_base_classes = read_at_32(buf, 8);
114  if (context->word_size <= 4) {
115  chd->base_class_array_addr = (ut32)rz_read_ble(buf + 12, (bool)context->analysis->big_endian, context->word_size * 8);
116  } else {
117  // 64bit is special, like in Complete Object Locator.
118  // Only the offset from the base from Complete Object Locator
119  // is contained in Class Hierarchy Descriptor
120  chd->base_class_array_addr = read_at_32(buf, 12);
121  }
122  return true;
123 }

References addr, rtti_class_hierarchy_descriptor_t::attributes, rtti_class_hierarchy_descriptor_t::base_class_array_addr, rtti_class_hierarchy_descriptor_t::num_base_classes, RZ_MIN, rz_read_at_be32(), rz_read_at_le32(), rz_read_ble(), rtti_class_hierarchy_descriptor_t::signature, src, and UT64_MAX.

Referenced by recovery_analysis_complete_object_locator(), rtti_msvc_print_complete_object_locator_recurse(), and rz_analysis_rtti_msvc_print_class_hierarchy_descriptor().

◆ rtti_msvc_read_complete_object_locator()

static bool rtti_msvc_read_complete_object_locator ( RVTableContext *  context,
ut64  addr,
rtti_complete_object_locator col 
)
static

Definition at line 56 of file rtti_msvc.c.

56  {
57  if (addr == UT64_MAX) {
58  return false;
59  }
60 
61  ut8 buf[6 * sizeof(ut32)];
62  int colSize = 5 * sizeof(ut32);
63  if (context->word_size == 8) {
64  colSize += sizeof(ut32);
65  }
66  if (colSize > sizeof(buf)) {
67  return false;
68  }
69 
70  if (!context->analysis->iob.read_at(context->analysis->iob.io, addr, buf, colSize)) {
71  return false;
72  }
73 
74  ut32 (*read_at_32)(const void *src, size_t offset) = context->analysis->big_endian ? rz_read_at_be32 : rz_read_at_le32;
75  col->signature = read_at_32(buf, 0);
76  col->vtable_offset = read_at_32(buf, 4);
77  col->cd_offset = read_at_32(buf, 8);
78 
79  int offsetSize = RZ_MIN(context->word_size, 4);
80  col->type_descriptor_addr = (ut32)rz_read_ble(buf + 12, (bool)context->analysis->big_endian, offsetSize * 8);
81  col->class_descriptor_addr = (ut32)rz_read_ble(buf + 12 + offsetSize, (bool)context->analysis->big_endian, offsetSize * 8);
82  if (context->word_size == 8) {
83  // 64bit is special:
84  // Type Descriptor and Class Hierarchy Descriptor addresses are computed
85  // by 32 bit values *(col+12) + *(col+0x14)
86  // and *(col+16) + *(col+0x14) respectively
87  col->object_base = read_at_32(buf, 20);
88  } else {
89  col->object_base = 0;
90  }
91 
92  return true;
93 }

References addr, rtti_complete_object_locator_t::cd_offset, rtti_complete_object_locator_t::class_descriptor_addr, rtti_complete_object_locator_t::object_base, RZ_MIN, rz_read_at_be32(), rz_read_at_le32(), rz_read_ble(), rtti_complete_object_locator_t::signature, src, rtti_complete_object_locator_t::type_descriptor_addr, UT64_MAX, and rtti_complete_object_locator_t::vtable_offset.

Referenced by recovery_analysis_complete_object_locator(), rtti_msvc_print_complete_object_locator_recurse(), and rz_analysis_rtti_msvc_print_complete_object_locator().

◆ rtti_msvc_read_type_descriptor()

static bool rtti_msvc_read_type_descriptor ( RVTableContext *  context,
ut64  addr,
rtti_type_descriptor td 
)
static

Definition at line 226 of file rtti_msvc.c.

226  {
227  if (addr == UT64_MAX) {
228  return false;
229  }
230 
231  if (!context->read_addr(context->analysis, addr, &td->vtable_addr)) {
232  return false;
233  }
234  if (!context->read_addr(context->analysis, addr + context->word_size, &td->spare)) {
235  return false;
236  }
237 
238  ut64 nameAddr = addr + 2 * context->word_size;
240  ut64 bufOffset = 0;
241  size_t nameLen = 0;
242  bool endFound = false;
243  bool endInvalid = false;
244  while (1) {
245  context->analysis->iob.read_at(context->analysis->iob.io, nameAddr + bufOffset, buf, sizeof(buf));
246  int i;
247  for (i = 0; i < sizeof(buf); i++) {
248  if (buf[i] == '\0') {
249  endFound = true;
250  break;
251  }
252  if (buf[i] == 0xff) {
253  endInvalid = true;
254  break;
255  }
256  nameLen++;
257  }
258  if (endFound || endInvalid) {
259  break;
260  }
261  bufOffset += sizeof(buf);
262  }
263 
264  if (endInvalid) {
265  return false;
266  }
267 
268  td->name = malloc(nameLen + 1);
269  if (!td->name) {
270  return false;
271  }
272 
273  if (bufOffset == 0) {
274  memcpy(td->name, buf, nameLen + 1);
275  } else {
276  context->analysis->iob.read_at(context->analysis->iob.io, nameAddr,
277  (ut8 *)td->name, (int)(nameLen + 1));
278  }
279 
280  return true;
281 }
lzma_index ** i
Definition: index.h:629
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
#define NAME_BUF_SIZE
Definition: rtti_msvc.c:8

References addr, i, malloc(), memcpy(), rtti_type_descriptor_t::name, NAME_BUF_SIZE, rtti_type_descriptor_t::spare, ut64(), UT64_MAX, and rtti_type_descriptor_t::vtable_addr.

Referenced by recovery_analysis_type_descriptor(), rtti_msvc_print_complete_object_locator_recurse(), and rz_analysis_rtti_msvc_print_type_descriptor().

◆ rtti_type_descriptor_fini()

static void rtti_type_descriptor_fini ( rtti_type_descriptor td)
static

◆ rz_analysis_rtti_msvc_demangle_class_name()

RZ_API char* rz_analysis_rtti_msvc_demangle_class_name ( RVTableContext *  context,
const char *  name 
)

Demangle a class name as found in MSVC RTTI type descriptors.

Examples: .?AVClassA@ => ClassA .?AVClassInInnerNamespace@InnerNamespace@OuterNamespace@ => OuterNamespace::InnerNamespace::AVClassInInnerNamespace

Definition at line 393 of file rtti_msvc.c.

393  {
394  if (!name) {
395  return NULL;
396  }
397  size_t original_len = strlen(name);
398  if (original_len < 7 || (strncmp(name, ".?AV", 4) != 0 && strncmp(name, ".?AU", 4) != 0) || strncmp(name + original_len - 2, "@@", 2) != 0) {
399  return NULL;
400  }
401  char *ret = context->analysis->binb.demangle(NULL, "msvc", name, 0, false);
402  if (ret && *ret) {
403  char *n = strchr(ret, ' ');
404  if (n && *(++n)) {
405  char *tmp = strdup(n);
406  free(ret);
407  ret = tmp;
408  } else {
409  RZ_FREE(ret);
410  }
411  } else {
412  RZ_FREE(ret);
413  }
414  return ret;
415 }
int n
Definition: mipsasm.c:19
#define RZ_FREE(x)
Definition: rz_types.h:369

References free(), n, NULL, RZ_FREE, strdup(), and autogen_x86imm::tmp.

Referenced by recovery_apply_complete_object_locator(), recovery_apply_type_descriptor(), and rz_analysis_rtti_demangle_class_name().

◆ rz_analysis_rtti_msvc_print_at_vtable()

RZ_API bool rz_analysis_rtti_msvc_print_at_vtable ( RVTableContext *  context,
ut64  addr,
RzOutputMode  mode,
bool  strict 
)

Definition at line 617 of file rtti_msvc.c.

617  {
619 }
static bool rtti_msvc_print_complete_object_locator_recurse(RVTableContext *context, ut64 atAddress, RzOutputMode mode, bool strict)
Definition: rtti_msvc.c:499

Referenced by rz_analysis_rtti_print_all(), and rz_analysis_rtti_print_at_vtable().

◆ rz_analysis_rtti_msvc_print_base_class_descriptor()

RZ_API void rz_analysis_rtti_msvc_print_base_class_descriptor ( RVTableContext *  context,
ut64  addr,
int  mode 
)

Definition at line 479 of file rtti_msvc.c.

479  {
482  RZ_LOG_ERROR("Failed to parse base class descriptor at 0x%08" PFMT64x "\n", addr);
483  return;
484  }
485 
486  if (mode == 'j') {
487  PJ *pj = pj_new();
488  if (!pj) {
489  return;
490  }
492  rz_cons_print(pj_string(pj));
493  pj_free(pj);
494  } else {
496  }
497 }

References addr, PFMT64x, pj_free(), pj_new(), pj_string(), rtti_msvc_print_base_class_descriptor(), rtti_msvc_print_base_class_descriptor_json(), rtti_msvc_read_base_class_descriptor(), and RZ_LOG_ERROR.

◆ rz_analysis_rtti_msvc_print_class_hierarchy_descriptor()

RZ_API void rz_analysis_rtti_msvc_print_class_hierarchy_descriptor ( RVTableContext *  context,
ut64  addr,
int  mode 
)

Definition at line 459 of file rtti_msvc.c.

459  {
462  RZ_LOG_ERROR("Failed to parse class hierarchy descriptor at 0x%08" PFMT64x "\n", addr);
463  return;
464  }
465 
466  if (mode == 'j') {
467  PJ *pj = pj_new();
468  if (!pj) {
469  return;
470  }
472  rz_cons_print(pj_string(pj));
473  pj_free(pj);
474  } else {
476  }
477 }

References addr, PFMT64x, pj_free(), pj_new(), pj_string(), rtti_msvc_print_class_hierarchy_descriptor(), rtti_msvc_print_class_hierarchy_descriptor_json(), rtti_msvc_read_class_hierarchy_descriptor(), and RZ_LOG_ERROR.

◆ rz_analysis_rtti_msvc_print_complete_object_locator()

RZ_API void rz_analysis_rtti_msvc_print_complete_object_locator ( RVTableContext *  context,
ut64  addr,
int  mode 
)

Definition at line 417 of file rtti_msvc.c.

417  {
420  RZ_LOG_ERROR("Failed to parse complete object locator at 0x%08" PFMT64x "\n", addr);
421  return;
422  }
423 
424  if (mode == 'j') {
425  PJ *pj = pj_new();
426  if (!pj) {
427  return;
428  }
430  rz_cons_print(pj_string(pj));
431  pj_free(pj);
432  } else {
434  }
435 }

References addr, PFMT64x, pj_free(), pj_new(), pj_string(), rtti_msvc_print_complete_object_locator(), rtti_msvc_print_complete_object_locator_json(), rtti_msvc_read_complete_object_locator(), and RZ_LOG_ERROR.

◆ rz_analysis_rtti_msvc_print_type_descriptor()

RZ_API void rz_analysis_rtti_msvc_print_type_descriptor ( RVTableContext *  context,
ut64  addr,
int  mode 
)

Definition at line 437 of file rtti_msvc.c.

437  {
438  rtti_type_descriptor td = { 0 };
440  RZ_LOG_ERROR("Failed to parse type descriptor at 0x%08" PFMT64x "\n", addr);
441  return;
442  }
443 
444  if (mode == 'j') {
445  PJ *pj = pj_new();
446  if (!pj) {
447  return;
448  }
450  rz_cons_print(pj_string(pj));
451  pj_free(pj);
452  } else {
454  }
455 
457 }

References addr, PFMT64x, pj_free(), pj_new(), pj_string(), rtti_msvc_print_type_descriptor(), rtti_msvc_print_type_descriptor_json(), rtti_msvc_read_type_descriptor(), rtti_type_descriptor_fini(), and RZ_LOG_ERROR.

◆ rz_analysis_rtti_msvc_recover_all()

RZ_API void rz_analysis_rtti_msvc_recover_all ( RVTableContext *  vt_context,
RzList vtables 
)

Definition at line 966 of file rtti_msvc.c.

966  {
968  context.vt_context = vt_context;
970 
972  context.addr_col = ht_up_new0();
974  context.addr_td = ht_up_new0();
975 
976  context.col_td_classes = ht_up_new(NULL, (HtUPKvFreeFunc)str_value_free, (HtUPCalcSizeV)strlen);
977 
978  RzListIter *vtableIter;
979  RVTableInfo *table;
980  rz_list_foreach (vtables, vtableIter, table) {
981  ut64 colRefAddr = table->saddr - vt_context->word_size;
982  ut64 colAddr;
983  if (!vt_context->read_addr(vt_context->analysis, colRefAddr, &colAddr)) {
984  continue;
985  }
987  }
988 
989  void **it;
990 #if USE_TD_RECOVERY
991  rz_pvector_foreach (&context.type_descriptors, it) {
992  RecoveryTypeDescriptor *td = *it;
993  if (!td->valid) {
994  continue;
995  }
997  }
998 #else
999  rz_pvector_foreach (&context.complete_object_locators, it) {
1000  RecoveryCompleteObjectLocator *col = *it;
1001  if (!col->valid) {
1002  continue;
1003  }
1005  }
1006 #endif
1007 
1008  rz_pvector_clear(&context.vtables);
1009  rz_pvector_clear(&context.complete_object_locators);
1010  ht_up_free(context.addr_col);
1011  rz_pvector_clear(&context.type_descriptors);
1012  ht_up_free(context.addr_td);
1013  ht_up_free(context.col_td_classes);
1014 }
void recovery_complete_object_locator_free(RecoveryCompleteObjectLocator *col)
Definition: rtti_msvc.c:648
void str_value_free(HtUPKv *kv)
Definition: rtti_msvc.c:962
RecoveryCompleteObjectLocator * recovery_analysis_complete_object_locator(RRTTIMSVCAnalContext *context, ut64 addr, RVTableInfo *vtable)
Definition: rtti_msvc.c:698
void recovery_type_descriptor_free(RecoveryTypeDescriptor *td)
Definition: rtti_msvc.c:678
RZ_API void rz_pvector_init(RzPVector *vec, RzPVectorFree free)
Definition: vector.c:298
void(* RzPVectorFree)(void *e)
Definition: rz_vector.h:43
RZ_API void rz_pvector_clear(RzPVector *vec)
Definition: vector.c:326
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
RZ_API void rz_analysis_vtable_info_free(RVTableInfo *vtable)
Definition: vtable.c:29

References NULL, recovery_analysis_complete_object_locator(), recovery_apply_complete_object_locator(), recovery_apply_type_descriptor(), recovery_complete_object_locator_free(), recovery_type_descriptor_free(), rz_analysis_vtable_info_free(), rz_pvector_clear(), rz_pvector_foreach, rz_pvector_init(), str_value_free(), ut64(), recovery_complete_object_locator_t::valid, and recovery_type_descriptor_t::valid.

Referenced by rz_analysis_rtti_recover_all().

◆ str_value_free()

void str_value_free ( HtUPKv *  kv)

Definition at line 962 of file rtti_msvc.c.

962  {
963  free(kv->value);
964 }

References free().

Referenced by rz_analysis_rtti_msvc_recover_all().

◆ unique_class_name()

static char* unique_class_name ( RzAnalysis analysis,
const char *  original_name 
)
static

Definition at line 791 of file rtti_msvc.c.

791  {
792  if (!rz_analysis_class_exists(analysis, original_name)) {
793  return strdup(original_name);
794  }
795 
796  char *name = NULL;
797  RZ_LOG_DEBUG("Class name '%s' was already taken!\n", original_name);
798  int i = 1;
799  do {
800  free(name);
801  name = rz_str_newf("%s.%d", original_name, i++);
802  if (!name) {
803  return NULL;
804  }
805  } while (rz_analysis_class_exists(analysis, name));
806 
807  return name;
808 }
RZ_API bool rz_analysis_class_exists(RzAnalysis *analysis, const char *name)
Definition: class.c:167

References free(), i, name, NULL, rz_analysis_class_exists(), RZ_LOG_DEBUG, rz_str_newf(), and strdup().

Referenced by recovery_apply_complete_object_locator().