rizin/librz/bin/format/pe/pe_clr.c
Khairul Azhar Kasmiran 2d49628aee
Remove rz_list_iter_get_data() (#5900)
* Remove rz_list_iter_get_data()
* Use rz_list_val() instead of rz_list_iter_get_data()
2026-02-10 22:03:37 +08:00

146 lines
4.3 KiB
C

// SPDX-FileCopyrightText: 2008-2019 nibble <nibble.ds@gmail.com>
// SPDX-FileCopyrightText: 2008-2019 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2008-2019 inisider <inisider@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#include "pe.h"
RZ_OWN RzList /*<RzBinSymbol *>*/ *PE_(rz_bin_pe_get_clr_symbols)(RzBinPEObj *bin) {
if (!bin || !bin->clr || !bin->clr->methoddefs) {
return NULL;
}
RzList /*<RzBinSymbol *>*/ *methods = rz_list_newf((RzListFree)rz_bin_symbol_free);
if (!methods) {
return NULL;
}
// Namespace and classes
// Each typedef contains a methodlist field which indexes into
// the MethodDef table and marks the start of methods
// belonging to that type
// In order to determine the end of the methods of that type,
// we mark the start of the next run with `type_methods_end`
RzListIter *type_it = rz_list_iterator(bin->clr->typedefs);
char *type_name = NULL;
char *type_namespace = NULL;
ut32 type_methods_start = rz_pvector_len(bin->clr->methoddefs) + 1;
ut32 type_methods_end = type_methods_start;
if (type_it) {
Pe_image_metadata_typedef *typedef_ = rz_list_val(type_it);
type_name = rz_buf_get_string(bin->clr->strings, typedef_->name);
type_namespace = rz_buf_get_string(bin->clr->strings, typedef_->namespace);
type_methods_start = typedef_->methodlist;
type_methods_end = rz_pvector_len(bin->clr->methoddefs) + 1;
type_it = rz_list_next(type_it);
if (type_it) {
Pe_image_metadata_typedef *itypedef_ = rz_list_val(type_it);
type_methods_end = itypedef_->methodlist;
}
}
int i = 1;
void **it;
rz_pvector_foreach (bin->clr->methoddefs, it) {
Pe_image_metadata_methoddef *methoddef = *it;
if ((type_name || type_namespace) && i >= type_methods_start && i >= type_methods_end) {
rz_break_if_fail(type_it);
// Update class and namespace
free(type_name);
free(type_namespace);
Pe_image_metadata_typedef *typedef_ = rz_list_val(type_it);
type_name = rz_buf_get_string(bin->clr->strings, typedef_->name);
type_namespace = rz_buf_get_string(bin->clr->strings, typedef_->namespace);
// Update next end
type_it = rz_list_next(type_it);
if (type_it) {
Pe_image_metadata_typedef *next_typedef_ = rz_list_val(type_it);
type_methods_end = next_typedef_->methodlist;
} else {
type_methods_end = rz_pvector_len(bin->clr->methoddefs) + 1;
}
}
RzBinSymbol *sym;
if (!(sym = RZ_NEW0(RzBinSymbol))) {
break;
}
char *name = rz_buf_get_string(bin->clr->strings, methoddef->name);
sym->name = rz_str_newf("%s%s%s::%s",
type_namespace ? type_namespace : "",
type_namespace && type_namespace[0] != '\x00' ? "::" : "", // separator
type_name ? type_name : "",
name ? name : "");
free(name);
sym->type = RZ_BIN_TYPE_FUNC_STR;
sym->vaddr = PE_(bin_pe_rva_to_va)(bin, methoddef->rva);
sym->paddr = PE_(bin_pe_rva_to_paddr)(bin, methoddef->rva);
if (!(methoddef->implflags & 0x01) && methoddef->rva) { // not native
if (bin_pe_dotnet_read_method_header(bin->clr, bin->b, sym) < 0) {
free(sym);
break;
}
}
rz_list_append(methods, sym);
i++;
}
// Cleanup class / namespace strings
free(type_name);
free(type_namespace);
return methods;
}
ut64 PE_(rz_bin_pe_get_clr_methoddef_offset)(RzBinPEObj *bin, Pe_image_metadata_methoddef *methoddef) {
if (!bin || !bin->clr || !methoddef) {
return UT64_MAX;
}
RzBinSymbol sym;
sym.vaddr = PE_(bin_pe_rva_to_va)(bin, methoddef->rva);
sym.paddr = PE_(bin_pe_rva_to_paddr)(bin, methoddef->rva);
if (!(methoddef->implflags & 0x01) && methoddef->rva) { // not native
if (bin_pe_dotnet_read_method_header(bin->clr, bin->b, &sym) < 0) {
return UT64_MAX;
}
}
return sym.vaddr;
}
int PE_(bin_pe_init_clr)(RzBinPEObj *bin) {
PE_(image_data_directory) *clr_dir = &bin->data_directory[PE_IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
PE_DWord image_clr_hdr_paddr = PE_(bin_pe_rva_to_paddr)(bin, clr_dir->VirtualAddress);
Pe_image_clr *clr = RZ_NEW0(Pe_image_clr);
if (!clr) {
return -1;
}
if (bin_pe_dotnet_init_clr(clr, bin->b, image_clr_hdr_paddr)) {
return -1;
}
if (clr->header) {
PE_DWord metadata_directory = PE_(bin_pe_rva_to_paddr)(bin, clr->header->MetaDataDirectoryAddress);
bin_pe_dotnet_init_metadata(clr, bin->big_endian, bin->b, metadata_directory);
}
bin->clr = clr;
return 0;
}