Rizin
unix-like reverse engineering framework and cli tools
pe_clr.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2008-2019 nibble <nibble.ds@gmail.com>
2 // SPDX-FileCopyrightText: 2008-2019 pancake <pancake@nopcode.org>
3 // SPDX-FileCopyrightText: 2008-2019 inisider <inisider@gmail.com>
4 // SPDX-License-Identifier: LGPL-3.0-only
5 
6 #include "pe.h"
7 
9  if (!bin || !bin->clr || !bin->clr->methoddefs) {
10  return NULL;
11  }
12  RzList /* RzBinSymbol */ *methods = rz_list_newf((RzListFree)rz_bin_symbol_free);
13  if (!methods) {
14  return NULL;
15  }
16 
17  // Namespace and classes
18 
19  // Each typedef contains a methodlist field which indexes into
20  // the MethodDef table and marks the start of methods
21  // belonging to that type
22 
23  // In order to determine the end of the methods of that type,
24  // we mark the start of the next run with `type_methods_end`
25  RzListIter *type_it = rz_list_iterator(bin->clr->typedefs);
26 
27  char *type_name = NULL;
28  char *type_namespace = NULL;
29 
30  ut32 type_methods_start = rz_pvector_len(bin->clr->methoddefs) + 1;
31  ut32 type_methods_end = type_methods_start;
32 
33  if (type_it) {
34  Pe_image_metadata_typedef *typedef_ = type_it->data;
35  type_name = rz_buf_get_string(bin->clr->strings, typedef_->name);
36  type_namespace = rz_buf_get_string(bin->clr->strings, typedef_->namespace);
37 
38  type_methods_start = ((Pe_image_metadata_typedef *)type_it->data)->methodlist;
39  type_methods_end = rz_pvector_len(bin->clr->methoddefs) + 1;
40 
41  type_it = type_it->n;
42  if (type_it) {
43  type_methods_end = ((Pe_image_metadata_typedef *)type_it->data)->methodlist;
44  }
45  }
46 
47  int i = 1;
48  void **it;
49  rz_pvector_foreach (bin->clr->methoddefs, it) {
50  Pe_image_metadata_methoddef *methoddef = *it;
51 
52  if ((type_name || type_namespace) && i >= type_methods_start && i >= type_methods_end) {
53  // Update class and namespace
54  free(type_name);
55  free(type_namespace);
56 
57  Pe_image_metadata_typedef *typedef_ = type_it->data;
58  type_name = rz_buf_get_string(bin->clr->strings, typedef_->name);
59  type_namespace = rz_buf_get_string(bin->clr->strings, typedef_->namespace);
60 
61  // Update next end
62  type_it = type_it->n;
63  if (type_it) {
64  type_methods_end = ((Pe_image_metadata_typedef *)type_it->data)->methodlist;
65  } else {
66  type_methods_end = rz_pvector_len(bin->clr->methoddefs) + 1;
67  }
68  }
69 
70  RzBinSymbol *sym;
71  if (!(sym = RZ_NEW0(RzBinSymbol))) {
72  break;
73  }
74  char *name = rz_buf_get_string(bin->clr->strings, methoddef->name);
75  sym->name = rz_str_newf("%s%s%s::%s",
76  type_namespace ? type_namespace : "",
77  type_namespace && type_namespace[0] != '\x00' ? "::" : "", // separator
78  type_name ? type_name : "",
79  name ? name : "");
80  free(name);
81 
83  sym->vaddr = PE_(bin_pe_rva_to_va)(bin, methoddef->rva);
84  sym->paddr = PE_(bin_pe_rva_to_paddr)(bin, methoddef->rva);
85 
86  if (!(methoddef->implflags & 0x01) && methoddef->rva) { // not native
87  if (bin_pe_dotnet_read_method_header(bin->clr, bin->b, sym) < 0) {
88  free(sym);
89  break;
90  }
91  }
92 
93  rz_list_append(methods, sym);
94  i++;
95  }
96 
97  // Cleanup class / namespace strings
98  free(type_name);
99  free(type_namespace);
100 
101  return methods;
102 }
103 
105  if (!bin || !bin->clr || !methoddef) {
106  return UT64_MAX;
107  }
108 
109  RzBinSymbol sym;
110  sym.vaddr = PE_(bin_pe_rva_to_va)(bin, methoddef->rva);
111  sym.paddr = PE_(bin_pe_rva_to_paddr)(bin, methoddef->rva);
112 
113  if (!(methoddef->implflags & 0x01) && methoddef->rva) { // not native
114  if (bin_pe_dotnet_read_method_header(bin->clr, bin->b, &sym) < 0) {
115  return UT64_MAX;
116  }
117  }
118 
119  return sym.vaddr;
120 }
121 
123  PE_(image_data_directory) *clr_dir = &bin->data_directory[PE_IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
124  PE_DWord image_clr_hdr_paddr = PE_(bin_pe_rva_to_paddr)(bin, clr_dir->VirtualAddress);
125 
127  if (!clr) {
128  return -1;
129  }
130 
131  if (bin_pe_dotnet_init_clr(clr, bin->b, image_clr_hdr_paddr)) {
132  return -1;
133  }
134 
135  if (clr->header) {
136  PE_DWord metadata_directory = PE_(bin_pe_rva_to_paddr)(bin, clr->header->MetaDataDirectoryAddress);
137  bin_pe_dotnet_init_metadata(clr, bin->big_endian, bin->b, metadata_directory);
138  }
139 
140  bin->clr = clr;
141  return 0;
142 }
lzma_index ** i
Definition: index.h:629
RZ_API void rz_bin_symbol_free(RzBinSymbol *sym)
Definition: bin.c:175
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
int bin_pe_dotnet_read_method_header(Pe_image_clr *clr, RzBuffer *b, RzBinSymbol *sym)
Definition: dotnet.c:745
int bin_pe_dotnet_init_clr(Pe_image_clr *clr, RzBuffer *b, ut64 image_clr_hdr_paddr)
Definition: dotnet.c:932
int bin_pe_dotnet_init_metadata(Pe_image_clr *clr, bool big_endian, RzBuffer *b, ut64 metadata_directory)
Definition: dotnet.c:783
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API RZ_BORROW RzListIter * rz_list_iterator(const RzList *list)
returns the first RzList iterator int the list
Definition: list.c:51
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
PE_DWord PE_() bin_pe_rva_to_paddr(RzBinPEObj *bin, PE_DWord rva)
Definition: pe.c:15
PE_DWord PE_() bin_pe_rva_to_va(RzBinPEObj *bin, PE_DWord rva)
Definition: pe.c:28
#define RzBinPEObj
Definition: pe.h:126
ut64 PE_() rz_bin_pe_get_clr_methoddef_offset(RzBinPEObj *bin, Pe_image_metadata_methoddef *methoddef)
Definition: pe_clr.c:104
RZ_OWN RzList *PE_() rz_bin_pe_get_clr_symbols(RzBinPEObj *bin)
Definition: pe_clr.c:8
int PE_() bin_pe_init_clr(RzBinPEObj *bin)
Definition: pe_clr.c:122
#define PE_(name)
Definition: pe_specs.h:23
#define PE_IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
Definition: pe_specs.h:158
#define PE_DWord
Definition: pe_specs.h:27
#define RZ_BIN_TYPE_FUNC_STR
Definition: rz_bin.h:119
RZ_API RZ_OWN char * rz_buf_get_string(RZ_NONNULL RzBuffer *b, ut64 addr)
Get a string from the buffer.
Definition: buf.c:628
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define UT64_MAX
Definition: rz_types_base.h:86
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
ut32 MetaDataDirectoryAddress
Definition: dotnet.h:15
Pe_image_clr_header * header
Definition: dotnet.h:151
Definition: malloc.c:26
Definition: z80asm.h:102
const char * type
Definition: rz_bin.h:682
char * name
Definition: rz_bin.h:675
struct rz_list_iter_t * n
Definition: rz_list.h:15
void * data
Definition: rz_list.h:14
ut64(WINAPI *w32_GetEnabledXStateFeatures)()