return r_codemeta_print_internal (code, line_offsets, anal, false);
}
-// TODO rename R_API char *r_codemeta_print_offsets(RCodeMeta *code, RVector *line_offsets, bool d) {
+// TODO rename R_API char *r_codemeta_print_offsets(RCodeMeta *code, RVecCodeMetaOffset *line_offsets, bool d) {
R_API char *r_codemeta_print(RCodeMeta *code, RVecCodeMetaOffset *line_offsets) {
R_LOG_DEBUG ("RCodeMetaPrint is deprecated: use RCodeMetaPrint2 instead");
return r_codemeta_print_internal (code, line_offsets, NULL, false);
RVecRecoveryBaseDescriptor base_td;
} RecoveryCompleteObjectLocator;
+static void recovery_complete_object_locator_free(RecoveryCompleteObjectLocator *col);
+static void recovery_type_descriptor_free(RecoveryTypeDescriptor *td);
+
+static void rtti_msvc_vtable_info_fini(RVTableInfo **info) {
+ r_anal_vtable_info_free (*info);
+}
+
+static void rtti_msvc_col_fini(RecoveryCompleteObjectLocator **col) {
+ recovery_complete_object_locator_free (*col);
+}
+
+static void rtti_msvc_td_fini(RecoveryTypeDescriptor **td) {
+ recovery_type_descriptor_free (*td);
+}
+
+R_VEC_TYPE_WITH_FINI (RVecVTableInfo, RVTableInfo *, rtti_msvc_vtable_info_fini);
+R_VEC_TYPE_WITH_FINI (RVecRecoveryCompleteObjectLocator, RecoveryCompleteObjectLocator *, rtti_msvc_col_fini);
+R_VEC_TYPE_WITH_FINI (RVecRecoveryTypeDescriptor, RecoveryTypeDescriptor *, rtti_msvc_td_fini);
+
typedef struct rtti_msvc_anal_context_t {
RVTableContext *vt_context;
- RPVector vtables; // <RVTableInfo>
- RPVector complete_object_locators; // <RecoveryCompleteObjectLocator>
+ RVecVTableInfo vtables; // <RVTableInfo>
+ RVecRecoveryCompleteObjectLocator complete_object_locators; // <RecoveryCompleteObjectLocator>
HtUP *addr_col; // <ut64, RecoveryCompleteObjectLocator *>
- RPVector type_descriptors; // <RecoveryTypeDescriptor>
+ RVecRecoveryTypeDescriptor type_descriptors; // <RecoveryTypeDescriptor>
HtUP *addr_td; // <ut64, RecoveryTypeDescriptor *>
HtUP *col_td_classes; // <ut64, char *> contains already recovered classes for col (or td) addresses
} RRTTIMSVCAnalContext;
}
static void recovery_complete_object_locator_free(RecoveryCompleteObjectLocator *col) {
- if (!col) {
- return;
- }
r_list_free (col->bcd);
RVecRecoveryBaseDescriptor_fini (&col->base_td);
free (col);
}
static void recovery_type_descriptor_free(RecoveryTypeDescriptor *td) {
- if (!td) {
- return;
- }
rtti_type_descriptor_fini (&td->td);
free (td);
}
if (!col) {
return NULL;
}
- r_pvector_push (&context->complete_object_locators, col);
+ RVecRecoveryCompleteObjectLocator_push_back (&context->complete_object_locators, &col);
ht_up_insert (context->addr_col, addr, col);
col->addr = addr;
col->valid = rtti_msvc_read_complete_object_locator (context->vt_context, addr, &col->col);
if (!td) {
return NULL;
}
- r_pvector_push (&context->type_descriptors, td);
+ RVecRecoveryTypeDescriptor_push_back (&context->type_descriptors, &td);
ht_up_insert (context->addr_td, addr, td);
td->addr = addr;
td->valid = rtti_msvc_read_type_descriptor (context->vt_context, addr, &td->td);
R_API void r_anal_rtti_msvc_recover_all(RVTableContext *vt_context, RList *vtables) {
RRTTIMSVCAnalContext context;
context.vt_context = vt_context;
- r_pvector_init (&context.vtables, (RPVectorFree)r_anal_vtable_info_free);
+ RVecVTableInfo_init (&context.vtables);
- r_pvector_init (&context.complete_object_locators, (RPVectorFree) recovery_complete_object_locator_free);
+ RVecRecoveryCompleteObjectLocator_init (&context.complete_object_locators);
context.addr_col = ht_up_new0 ();
- r_pvector_init (&context.type_descriptors, (RPVectorFree) recovery_type_descriptor_free);
+ RVecRecoveryTypeDescriptor_init (&context.type_descriptors);
context.addr_td = ht_up_new0 ();
context.col_td_classes = ht_up_new (NULL, (HtUPKvFreeFunc)str_value_free, (HtUPCalcSizeV)strlen);
recovery_anal_complete_object_locator (&context, colAddr, table);
}
- void **it;
#if USE_TD_RECOVERY
- r_pvector_foreach (&context.type_descriptors, it) {
- RecoveryTypeDescriptor *td = *it;
+ RecoveryTypeDescriptor **td_it;
+ R_VEC_FOREACH (&context.type_descriptors, td_it) {
+ RecoveryTypeDescriptor *td = *td_it;
if (!td->valid) {
continue;
}
recovery_apply_type_descriptor (&context, td);
}
#else
- r_pvector_foreach (&context.complete_object_locators, it) {
- RecoveryCompleteObjectLocator *col = *it;
+ RecoveryCompleteObjectLocator **col_it;
+ R_VEC_FOREACH (&context.complete_object_locators, col_it) {
+ RecoveryCompleteObjectLocator *col = *col_it;
if (!col->valid) {
continue;
}
recovery_apply_complete_object_locator (&context, col);
}
#endif
- r_pvector_clear (&context.vtables);
- r_pvector_clear (&context.complete_object_locators);
+ RVecVTableInfo_clear (&context.vtables);
+ RVecRecoveryCompleteObjectLocator_clear (&context.complete_object_locators);
ht_up_free (context.addr_col);
- r_pvector_clear (&context.type_descriptors);
+ RVecRecoveryTypeDescriptor_clear (&context.type_descriptors);
ht_up_free (context.addr_td);
ht_up_free (context.col_td_classes);
}
return false;
}
- r_pvector_push (&mo->libs_cache, r_str_ndup (lib, R_BIN_MACH0_STRING_LENGTH));
+ char *name = r_str_ndup (lib, R_BIN_MACH0_STRING_LENGTH);
+ RVecMach0Lib_push_back (&mo->libs_cache, &name);
return true;
}
mo->os = 0;
mo->has_crypto = false;
mo->segments_vec = NULL;
- r_pvector_init (&mo->libs_cache, (RPVectorFree) free);
+ RVecMach0Lib_init (&mo->libs_cache);
if (mo->hdr.sizeofcmds > mo->size) {
R_LOG_WARN ("chopping hdr.sizeofcmds because it's larger than the file size");
}
mo->baddr = MACH0_(get_baddr)(mo);
mo->libs_loaded = true;
- r_pvector_shrink (&mo->libs_cache);
+ RVecMach0Lib_shrink_to_fit (&mo->libs_cache);
return true;
}
free (mo->toc);
free (mo->modtab);
if (mo->libs_loaded) {
- r_pvector_fini (&mo->libs_cache);
+ RVecMach0Lib_fini (&mo->libs_cache);
}
free (mo->func_start);
free (mo->signature);
#if R2_590
#else
if (mo->imports_loaded) {
- r_pvector_fini (&mo->imports_cache);
+ RVecMach0Import_fini (&mo->imports_cache);
}
#endif
if (mo->sections_loaded) {
}
}
-const RPVector *MACH0_(load_imports)(RBinFile *bf, struct MACH0_(obj_t) *bin) {
+const RVecMach0Import *MACH0_(load_imports)(RBinFile *bf, struct MACH0_(obj_t) *bin) {
R_RETURN_VAL_IF_FAIL (bin, NULL);
if (bin->imports_loaded) {
return &bin->imports_cache;
}
bin->imports_loaded = true;
- r_pvector_init (&bin->imports_cache, (RPVectorFree) r_bin_import_free);
+ RVecMach0Import_init (&bin->imports_cache);
ut32 nundefsym = bin->dysymtab.nundefsym;
if (nundefsym < 1 || nundefsym > 0xfffff) {
return NULL;
}
- r_pvector_reserve (&bin->imports_cache, nundefsym);
+ RVecMach0Import_reserve (&bin->imports_cache, nundefsym);
if (!bin->sects || !bin->symtab || !bin->symstr || !bin->indirectsyms) {
return NULL;
}
import->ordinal = i;
- r_pvector_push (&bin->imports_cache, import);
+ RVecMach0Import_push_back (&bin->imports_cache, &import);
num_imports++;
check_for_special_import_names (bin, import);
free (imp_name);
return NULL;
}
- void **it;
- r_pvector_foreach (&bin->imports_cache, it) {
- RBinImport *import = (RBinImport*) *it;
+ RBinImport **it;
+ R_VEC_FOREACH (&bin->imports_cache, it) {
+ RBinImport *import = *it;
if (import->ordinal < bin->imports_by_ord_size) {
bin->imports_by_ord[import->ordinal] = import;
}
return size > 0 && size <= UT16_MAX;
}
+static void mach0_reloc_ref_fini (struct reloc_t **reloc) {
+ free (*reloc);
+}
+
+R_VEC_TYPE_WITH_FINI (RVecRelocRef, struct reloc_t *, mach0_reloc_ref_fini);
+
+static RVecRelocRef *reloc_ref_vec_new_with_len (ut64 length) {
+ RVecRelocRef *vec = RVecRelocRef_new ();
+ if (!vec) {
+ return NULL;
+ }
+ if (!RVecRelocRef_reserve (vec, length)) {
+ RVecRelocRef_free (vec);
+ return NULL;
+ }
+ struct reloc_t *empty = NULL;
+ while (RVecRelocRef_length (vec) < length) {
+ RVecRelocRef_push_back (vec, &empty);
+ }
+ return vec;
+}
+
static bool _load_relocations(struct MACH0_(obj_t) *mo) {
- RPVector *threaded_binds = NULL;
+ RVecRelocRef *threaded_binds = NULL;
ut8 *opcodes = NULL;
size_t wordsize = get_word_size (mo);
if (mo->dyld_info) {
break;
}
if (threaded_binds) {
- r_pvector_free (threaded_binds);
+ RVecRelocRef_free (threaded_binds);
}
- threaded_binds = r_pvector_new_with_len ((RPVectorFree) &free, table_size);
+ threaded_binds = reloc_ref_vec_new_with_len (table_size);
if (threaded_binds) {
sym_ord = 0;
}
case BIND_SUBOPCODE_THREADED_APPLY:
if (threaded_binds) {
int cur_seg_idx = (seg_idx != -1)? seg_idx: 0;
- size_t n_threaded_binds = r_pvector_length (threaded_binds);
+ ut64 n_threaded_binds = RVecRelocRef_length (threaded_binds);
while (addr < segment_end_addr) {
ut8 tmp[8];
ut64 paddr = addr - mo->segs[cur_seg_idx].vmaddr + mo->segs[cur_seg_idx].fileoff;
R_LOG_DEBUG ("Malformed bind chain");
break;
}
- struct reloc_t *ref = r_pvector_at (threaded_binds, ordinal);
+ struct reloc_t **ref_slot = RVecRelocRef_at (threaded_binds, ordinal);
+ struct reloc_t *ref = ref_slot ? *ref_slot : NULL;
if (!ref) {
R_LOG_DEBUG ("Inconsistent bind opcodes");
break;
if (seg_idx >= mo->nsegs) {
R_LOG_ERROR ("BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB has no segment %d", seg_idx);
free (opcodes);
- r_pvector_free (threaded_binds);
+ RVecRelocRef_free (threaded_binds);
return false; // early exit to avoid future mayhem
}
addr = mo->segs[seg_idx].vmaddr + read_uleb128 (&p, end);
r_str_ncpy (reloc->name, sym_name, 256);\
}\
if (threaded_binds) {\
- r_pvector_set (threaded_binds, sym_ord, reloc);\
+ struct reloc_t **slot = RVecRelocRef_at (threaded_binds, sym_ord);\
+ if (slot) {\
+ *slot = reloc;\
+ }\
} else {\
r_skiplist_insert (mo->relocs_cache, reloc);\
}\
default:
R_LOG_DEBUG ("unknown bind opcode 0x%02x in dyld_info", *p);
R_FREE (opcodes);
- r_pvector_free (threaded_binds);
+ RVecRelocRef_free (threaded_binds);
return false;
}
}
opcodes_offset += partition_size;
}
R_FREE (opcodes);
- r_pvector_free (threaded_binds);
+ RVecRelocRef_free (threaded_binds);
threaded_binds = NULL;
}
}
beach:
R_FREE (opcodes);
- r_pvector_free (threaded_binds);
+ RVecRelocRef_free (threaded_binds);
return true;
}
char lib_flagname[128];
for (i = 0; i < mo->nlibs; i++) {
snprintf (lib_flagname, sizeof (lib_flagname), "libs.%d.name", i);
- sdb_set (mo->kv, lib_flagname, r_pvector_at (&mo->libs_cache, i), 0);
+ char **lib = RVecMach0Lib_at (&mo->libs_cache, i);
+ sdb_set (mo->kv, lib_flagname, lib? *lib: NULL, 0);
}
}
-const RPVector *MACH0_(load_libs)(struct MACH0_(obj_t) *mo) {
+const RVecMach0Lib *MACH0_(load_libs)(struct MACH0_(obj_t) *mo) {
R_RETURN_VAL_IF_FAIL (mo, NULL);
if (!mo->nlibs) {
return NULL;
#include <r_bin.h>
#include <r_types.h>
-#include <r_vector.h>
+#include <r_vec.h>
#include "mach0_specs.h"
#ifndef _INCLUDE_R_BIN_MACH0_H_
RBinFile *bf;
};
-static inline void r_bin_section_fini(RBinSection *bs) {
- if (bs) {
- free (bs->name);
- free (bs->format);
- }
+static inline void r_bin_section_fini (RBinSection *bs) {
+ free (bs->name);
+ free (bs->format);
}
R_VEC_TYPE_WITH_FINI(RVecSegment, RBinSection, r_bin_section_fini);
+static inline void mach0_lib_fini (char **lib) {
+ free (*lib);
+}
+
+static inline void mach0_import_fini (RBinImport **import) {
+ r_bin_import_free (*import);
+}
+
+R_VEC_TYPE_WITH_FINI (RVecMach0Lib, char *, mach0_lib_fini);
+R_VEC_TYPE_WITH_FINI (RVecMach0Import, RBinImport *, mach0_import_fini);
+
struct MACH0_(obj_t) {
struct MACH0_(mach_header) hdr;
struct MACH0_(segment_command) *segs;
struct arm_thread_state64 arm_64;
} thread_state;
bool libs_loaded;
- RPVector libs_cache;
+ RVecMach0Lib libs_cache;
int nlibs;
ut64 size;
ut64 baddr;
bool sections_loaded;
RVecSection sections_cache;
bool imports_loaded;
- RPVector imports_cache;
+ RVecMach0Import imports_cache;
bool relocs_loaded;
RSkipList *relocs_cache;
RList *reloc_fixups;
RVecSegment *MACH0_(get_segments_vec)(RBinFile *bf, struct MACH0_(obj_t) *mo);
const bool MACH0_(load_symbols)(struct MACH0_(obj_t) *mo);
void MACH0_(pull_symbols)(struct MACH0_(obj_t) *mo, RBinSymbolCallback cb, void *user);
-const RPVector *MACH0_(load_imports)(RBinFile* bf, struct MACH0_(obj_t) *bin);
+const RVecMach0Import *MACH0_(load_imports)(RBinFile* bf, struct MACH0_(obj_t) *bin);
const RSkipList *MACH0_(load_relocs)(struct MACH0_(obj_t) *bin);
struct addr_t *MACH0_(get_entrypoint)(struct MACH0_(obj_t) *bin);
-const RPVector *MACH0_(load_libs)(struct MACH0_(obj_t) *bin);
+const RVecMach0Lib *MACH0_(load_libs)(struct MACH0_(obj_t) *bin);
ut64 MACH0_(get_baddr)(struct MACH0_(obj_t) *bin);
char *MACH0_(get_class)(struct MACH0_(obj_t) *bin);
int MACH0_(get_bits)(struct MACH0_(obj_t) *bin);
typedef size_t (*ConsumeFcn) (const ut8 *p, const ut8 *bound, ut32 *out_value);
typedef void *(*ParseEntryFcn) (RBinWasmObj *bin, ut64 bound, ut32 index);
+typedef void (*WasmEntryFree) (void *entry);
// RBuffer consume functions
static ut32 consume_r(RBuffer *b, ut64 bound, size_t *n_out, ConsumeFcn consume_fcn) {
}
}
+static void free_vec_entries(RVecWasmPtr *vec, WasmEntryFree free_entry);
+
static inline void free_all_imports(RBinWasmObj *bin) {
int i;
for (i = 0; i < R_ARRAY_SIZE (bin->g_imports_arr); i++) {
- r_pvector_free (bin->g_imports_arr[i]);
+ free_vec_entries (bin->g_imports_arr[i], (WasmEntryFree)free_import_entry);
}
memset (bin->g_imports_arr, 0, sizeof (bin->g_imports_arr));
}
}
}
+static void free_vec_entries(RVecWasmPtr *vec, WasmEntryFree free_entry) {
+ if (vec) {
+ void **it;
+ R_VEC_FOREACH (vec, it) {
+ free_entry (*it);
+ }
+ }
+ RVecWasmPtr_free (vec);
+}
+
static void wasm_sec_free(RBinWasmSection *sec) {
if (sec) {
free (sec->name);
}
// Parsing
-static inline RPVector *parse_vec(RBinWasmObj *bin, ut64 bound, ParseEntryFcn parse_entry, RPVectorFree free_entry) {
+static inline RVecWasmPtr *parse_vec(RBinWasmObj *bin, ut64 bound, ParseEntryFcn parse_entry, WasmEntryFree free_entry) {
RBuffer *buf = bin->buf;
ut32 count;
return NULL;
}
- RPVector *vec = r_pvector_new (free_entry);
- if (vec) {
- if (!r_pvector_reserve (vec, count)) {
- return NULL;
- }
- ut32 i;
- for (i = 0; i < count; i++) {
- ut64 start = r_buf_tell (buf);
- void *e = parse_entry (bin, bound, i);
- if (!e || !r_pvector_push (vec, e)) {
- R_LOG_ERROR ("Failed to parse entry %u/%u of vec at 0x%" PFMT64x, i, count, start);
- free_entry (e);
- break;
- }
+ RVecWasmPtr *vec = RVecWasmPtr_new ();
+ if (!vec) {
+ return NULL;
+ }
+ if (!RVecWasmPtr_reserve (vec, count)) {
+ RVecWasmPtr_free (vec);
+ return NULL;
+ }
+ ut32 i;
+ for (i = 0; i < count; i++) {
+ ut64 start = r_buf_tell (buf);
+ void *e = parse_entry (bin, bound, i);
+ if (!e) {
+ R_LOG_ERROR ("Failed to parse entry %u/%u of vec at 0x%" PFMT64x, i, count, start);
+ free_entry (e);
+ break;
}
+ RVecWasmPtr_push_back (vec, &e);
}
return vec;
}
int i;
for (i = 0; i < R_ARRAY_SIZE (bin->g_imports_arr); i++) {
- bin->g_imports_arr[i] = r_pvector_new ((RPVectorFree)free_import_entry);
+ bin->g_imports_arr[i] = RVecWasmPtr_new ();
if (!bin->g_imports_arr[i]) {
return false;
}
// over estimate size, shrink later
for (i = 0; i < R_ARRAY_SIZE (bin->g_imports_arr); i++) {
- if (!r_pvector_reserve (bin->g_imports_arr[i], count)) {
+ if (!RVecWasmPtr_reserve (bin->g_imports_arr[i], count)) {
R_LOG_ERROR ("Unable to allocate %d in import array", count);
return false;
}
ut64 start = r_buf_tell (buf);
RBinWasmImportEntry *imp = parse_import_entry (bin, bound, i);
if (imp && imp->kind < R_ARRAY_SIZE (bin->g_imports_arr)) {
- r_pvector_push (bin->g_imports_arr[imp->kind], imp);
+ RVecWasmPtr_push_back (bin->g_imports_arr[imp->kind], (void **)&imp);
} else {
R_LOG_ERROR ("Failed to parse import entry %u/%u of vec at 0x%" PFMT64x, i, count, start);
free_import_entry (imp);
ut32 seen = 0;
for (i = 0; i < R_ARRAY_SIZE (bin->g_imports_arr); i++) {
- r_pvector_shrink (bin->g_imports_arr[i]);
- seen += r_pvector_length (bin->g_imports_arr[i]);
+ RVecWasmPtr_shrink_to_fit (bin->g_imports_arr[i]);
+ seen += RVecWasmPtr_length (bin->g_imports_arr[i]);
}
return seen == count? true: false;
}
if (bin) {
r_buf_free (bin->buf);
r_list_free (bin->g_sections);
- r_pvector_free (bin->g_types);
+ free_vec_entries (bin->g_types, (WasmEntryFree)free_type_entry);
free_all_imports (bin);
- r_pvector_free (bin->g_funcs);
- r_pvector_free (bin->g_tables);
- r_pvector_free (bin->g_memories);
- r_pvector_free (bin->g_globals);
- r_pvector_free (bin->g_exports);
- r_pvector_free (bin->g_elements);
- r_pvector_free (bin->g_codes);
- r_pvector_free (bin->g_datas);
+ free_vec_entries (bin->g_funcs, free);
+ free_vec_entries (bin->g_tables, free);
+ free_vec_entries (bin->g_memories, free);
+ free_vec_entries (bin->g_globals, free);
+ free_vec_entries (bin->g_exports, (WasmEntryFree)free_export_entry);
+ free_vec_entries (bin->g_elements, free);
+ free_vec_entries (bin->g_codes, (WasmEntryFree)free_code_entry);
+ free_vec_entries (bin->g_datas, free);
free_custom_names (bin->names);
free (bin);
}
return bin->entrypoint;
}
ut32 start = r_bin_wasm_get_start (bin);
- RPVector *code = r_bin_wasm_get_codes (bin);
+ RVecWasmPtr *code = r_bin_wasm_get_codes (bin);
// FIX: entrypoint can be also an import
if (code && start != UT32_MAX) {
- RBinWasmCodeEntry *func = r_pvector_at (code, start);
+ void **slot = RVecWasmPtr_at (code, start);
+ RBinWasmCodeEntry *func = slot? *slot: NULL;
return func? func->code: 0;
}
return 0;
}
-static int _export_sorter(const void *_a, const void *_b) {
- const RBinWasmExportEntry *a = _a;
- const RBinWasmExportEntry *b = _b;
+static int _export_sorter(void *const *_a, void *const *_b) {
+ const RBinWasmExportEntry *a = *_a;
+ const RBinWasmExportEntry *b = *_b;
st64 diff = (st64)a->kind - b->kind;
if (!diff) {
diff = (st64)a->index - b->index;
return diff > 0? 1: -1;
}
-static RPVector *parse_sub_section_vec(RBinWasmObj *bin, RBinWasmSection *sec) {
- RPVectorComparator sorter = NULL;
- RPVector **cache = NULL;
- RPVectorFree pfree = (RPVectorFree)free;
+static RVecWasmPtr *parse_sub_section_vec(RBinWasmObj *bin, RBinWasmSection *sec) {
+ RVecWasmPtrCompare sorter = NULL;
+ RVecWasmPtr **cache = NULL;
+ WasmEntryFree pfree = (WasmEntryFree)free;
ParseEntryFcn parser;
switch (sec->id) {
case R_BIN_WASM_SECTION_TYPE:
parser = (ParseEntryFcn)parse_type_entry;
- pfree = (RPVectorFree)free_type_entry;
+ pfree = (WasmEntryFree)free_type_entry;
cache = &bin->g_types;
break;
case R_BIN_WASM_SECTION_FUNCTION:
break;
case R_BIN_WASM_SECTION_EXPORT:
parser = (ParseEntryFcn)parse_export_entry;
- pfree = (RPVectorFree)free_export_entry;
+ pfree = (WasmEntryFree)free_export_entry;
cache = &bin->g_exports;
- sorter = (RPVectorComparator)_export_sorter;
+ sorter = _export_sorter;
break;
case R_BIN_WASM_SECTION_ELEMENT:
parser = (ParseEntryFcn)parse_element_entry;
break;
case R_BIN_WASM_SECTION_CODE:
parser = (ParseEntryFcn)parse_code_entry;
- pfree = (RPVectorFree)free_code_entry;
+ pfree = (WasmEntryFree)free_code_entry;
cache = &bin->g_codes;
break;
case R_BIN_WASM_SECTION_DATA:
*cache = parse_vec (bin, bound, parser, pfree);
if (sorter) {
- r_pvector_sort (*cache, sorter);
+ RVecWasmPtr_sort (*cache, sorter);
}
return *cache;
}
// warns if there are two sections of this type
-static inline RPVector *parse_unique_subsec_vec_by_id(RBinWasmObj *bin, ut8 id) {
+static inline RVecWasmPtr *parse_unique_subsec_vec_by_id(RBinWasmObj *bin, ut8 id) {
RBinWasmSection *sec = section_first_with_id (bin->g_sections, id);
if (sec) {
return parse_sub_section_vec (bin, sec);
return false;
}
-RPVector *r_bin_wasm_get_types(RBinWasmObj *bin) {
+RVecWasmPtr *r_bin_wasm_get_types(RBinWasmObj *bin) {
R_RETURN_VAL_IF_FAIL (bin && bin->g_sections, NULL);
return bin->g_types? bin->g_types: parse_unique_subsec_vec_by_id (bin, R_BIN_WASM_SECTION_TYPE);
}
-RPVector *r_bin_wasm_get_imports_kind(RBinWasmObj *bin, ut32 kind) {
+RVecWasmPtr *r_bin_wasm_get_imports_kind(RBinWasmObj *bin, ut32 kind) {
R_RETURN_VAL_IF_FAIL (bin && bin->g_sections && kind < R_ARRAY_SIZE (bin->g_imports_arr), NULL);
- RPVector **vec = &bin->g_imports_arr[kind];
+ RVecWasmPtr **vec = &bin->g_imports_arr[kind];
if (!*vec) {
parse_import_sec (bin);
}
return *vec;
}
-RPVector *r_bin_wasm_get_functions(RBinWasmObj *bin) {
+RVecWasmPtr *r_bin_wasm_get_functions(RBinWasmObj *bin) {
R_RETURN_VAL_IF_FAIL (bin && bin->g_sections, NULL);
return bin->g_funcs? bin->g_funcs: parse_unique_subsec_vec_by_id (bin, R_BIN_WASM_SECTION_FUNCTION);
}
-RPVector *r_bin_wasm_get_tables(RBinWasmObj *bin) {
+RVecWasmPtr *r_bin_wasm_get_tables(RBinWasmObj *bin) {
R_RETURN_VAL_IF_FAIL (bin && bin->g_sections, NULL);
return bin->g_tables? bin->g_tables: parse_unique_subsec_vec_by_id (bin, R_BIN_WASM_SECTION_TABLE);
}
-RPVector *r_bin_wasm_get_memories(RBinWasmObj *bin) {
+RVecWasmPtr *r_bin_wasm_get_memories(RBinWasmObj *bin) {
R_RETURN_VAL_IF_FAIL (bin && bin->g_sections, NULL);
return bin->g_memories? bin->g_memories: parse_unique_subsec_vec_by_id (bin, R_BIN_WASM_SECTION_MEMORY);
}
-RPVector *r_bin_wasm_get_globals(RBinWasmObj *bin) {
+RVecWasmPtr *r_bin_wasm_get_globals(RBinWasmObj *bin) {
R_RETURN_VAL_IF_FAIL (bin && bin->g_sections, NULL);
return bin->g_globals? bin->g_globals: parse_unique_subsec_vec_by_id (bin, R_BIN_WASM_SECTION_GLOBAL);
}
-RPVector *r_bin_wasm_get_exports(RBinWasmObj *bin) {
+RVecWasmPtr *r_bin_wasm_get_exports(RBinWasmObj *bin) {
R_RETURN_VAL_IF_FAIL (bin && bin->g_sections, NULL);
return bin->g_exports? bin->g_exports: parse_unique_subsec_vec_by_id (bin, R_BIN_WASM_SECTION_EXPORT);
}
-RPVector *r_bin_wasm_get_elements(RBinWasmObj *bin) {
+RVecWasmPtr *r_bin_wasm_get_elements(RBinWasmObj *bin) {
R_RETURN_VAL_IF_FAIL (bin && bin->g_sections, NULL);
return bin->g_elements? bin->g_elements: parse_unique_subsec_vec_by_id (bin, R_BIN_WASM_SECTION_ELEMENT);
}
-RPVector *r_bin_wasm_get_codes(RBinWasmObj *bin) {
+RVecWasmPtr *r_bin_wasm_get_codes(RBinWasmObj *bin) {
R_RETURN_VAL_IF_FAIL (bin && bin->g_sections, NULL);
return bin->g_codes? bin->g_codes: parse_unique_subsec_vec_by_id (bin, R_BIN_WASM_SECTION_CODE);
}
-RPVector *r_bin_wasm_get_datas(RBinWasmObj *bin) {
+RVecWasmPtr *r_bin_wasm_get_datas(RBinWasmObj *bin) {
R_RETURN_VAL_IF_FAIL (bin && bin->g_sections, NULL);
return bin->g_datas? bin->g_datas: parse_unique_subsec_vec_by_id (bin, R_BIN_WASM_SECTION_DATA);
}
#include <r_util.h>
#include <r_lib.h>
#include <r_bin.h>
-#include <r_vector.h>
+#include <r_vec.h>
#ifndef _INCLUDE_WASM_H_
#define _INCLUDE_WASM_H_
ut32 data; // offset
} RBinWasmDataEntry;
+R_VEC_TYPE (RVecWasmPtr, void *);
+
typedef struct r_bin_wasm_custom_module {
ut64 file_offset;
char *name;
// cache purposes
RList *g_sections;
- RPVector *g_types;
- RPVector *g_imports_arr[4];
- RPVector *g_funcs;
- RPVector *g_tables;
- RPVector *g_memories;
- RPVector *g_globals;
- RPVector *g_exports;
- RPVector *g_elements;
- RPVector *g_codes;
- RPVector *g_datas;
+ RVecWasmPtr *g_types;
+ RVecWasmPtr *g_imports_arr[4];
+ RVecWasmPtr *g_funcs;
+ RVecWasmPtr *g_tables;
+ RVecWasmPtr *g_memories;
+ RVecWasmPtr *g_globals;
+ RVecWasmPtr *g_exports;
+ RVecWasmPtr *g_elements;
+ RVecWasmPtr *g_codes;
+ RVecWasmPtr *g_datas;
ut32 g_start;
// custom sections
RBinWasmObj *r_bin_wasm_init(RBinFile *bf, RBuffer *buf);
void r_bin_wasm_destroy(RBinFile *bf);
RList *r_bin_wasm_get_sections(RBinWasmObj *bin);
-RPVector *r_bin_wasm_get_types(RBinWasmObj *bin);
-RPVector *r_bin_wasm_get_imports_kind(RBinWasmObj *bin, ut32 kind);
-RPVector *r_bin_wasm_get_functions(RBinWasmObj *bin);
-RPVector *r_bin_wasm_get_tables(RBinWasmObj *bin);
-RPVector *r_bin_wasm_get_memories(RBinWasmObj *bin);
-RPVector *r_bin_wasm_get_globals(RBinWasmObj *bin);
-RPVector *r_bin_wasm_get_exports(RBinWasmObj *bin);
-RPVector *r_bin_wasm_get_elements(RBinWasmObj *bin);
-RPVector *r_bin_wasm_get_codes(RBinWasmObj *bin);
-RPVector *r_bin_wasm_get_datas(RBinWasmObj *bin);
+RVecWasmPtr *r_bin_wasm_get_types(RBinWasmObj *bin);
+RVecWasmPtr *r_bin_wasm_get_imports_kind(RBinWasmObj *bin, ut32 kind);
+RVecWasmPtr *r_bin_wasm_get_functions(RBinWasmObj *bin);
+RVecWasmPtr *r_bin_wasm_get_tables(RBinWasmObj *bin);
+RVecWasmPtr *r_bin_wasm_get_memories(RBinWasmObj *bin);
+RVecWasmPtr *r_bin_wasm_get_globals(RBinWasmObj *bin);
+RVecWasmPtr *r_bin_wasm_get_exports(RBinWasmObj *bin);
+RVecWasmPtr *r_bin_wasm_get_elements(RBinWasmObj *bin);
+RVecWasmPtr *r_bin_wasm_get_codes(RBinWasmObj *bin);
+RVecWasmPtr *r_bin_wasm_get_datas(RBinWasmObj *bin);
RBinWasmCustomNames *r_bin_wasm_get_custom_names(RBinWasmObj *bin);
ut32 r_bin_wasm_get_entrypoint(RBinWasmObj *bin);
const char *r_bin_wasm_get_function_name(RBinWasmObj *bin, ut32 idx);
#include "objc/mach0_classes.h"
#include <sdb/ht_uu.h>
+R_VEC_TYPE (RVecExtReloc, struct reloc_t *);
+
typedef struct {
ut8 *buf;
int count;
static RList *imports(RBinFile *bf) {
RBinObject *obj = bf? bf->bo: NULL;
- const RPVector *imports = MACH0_(load_imports) (bf, obj->bin_obj);
+ const RVecMach0Import *imports = MACH0_(load_imports) (bf, obj->bin_obj);
if (!imports) {
return NULL;
}
RList *list = r_list_newf ((RListFree) r_bin_import_free);
- void **it;
- r_pvector_foreach (imports, it) {
+ RBinImport **it;
+ R_VEC_FOREACH (imports, it) {
// need to clone here, in bobj.c the list free function is forced to `r_bin_import_free`
// otherwise, a list with no free function could be returned here..
RBinImport *import = r_bin_import_clone (*it);
return NULL;
}
- const RPVector *libs = MACH0_(load_libs) (obj->bin_obj);
- if (!libs) {
- return NULL;
- }
+const RVecMach0Lib *libs = MACH0_(load_libs) (obj->bin_obj);
+if (!libs) {
+ return NULL;
+}
- RList *result = r_list_new ();
- void **it;
- r_pvector_foreach (libs, it) {
- r_list_append (result, *it);
- }
- return result;
+RList *result = r_list_new ();
+char **it;
+R_VEC_FOREACH (libs, it) {
+ r_list_append (result, *it);
+}
+return result;
}
static RBinInfo *info(RBinFile *bf) {
if (!all_relocs) {
return NULL;
}
- RPVector ext_relocs;
- r_pvector_init (&ext_relocs, NULL);
+ RVecExtReloc ext_relocs;
+ RVecExtReloc_init (&ext_relocs);
RSkipListNode *it;
struct reloc_t *reloc;
r_skiplist_foreach (all_relocs, it, reloc) {
if (!reloc->external) {
continue;
}
- r_pvector_push (&ext_relocs, reloc);
+ RVecExtReloc_push_back (&ext_relocs, &reloc);
}
#if 1
// XXX for some reason we are patching this twice as relocs and fixups
}
}
#endif
- ut64 num_ext_relocs = r_pvector_length (&ext_relocs);
+ ut64 num_ext_relocs = RVecExtReloc_length (&ext_relocs);
if (!num_ext_relocs) {
goto beach;
}
goto beach;
}
ut64 vaddr = n_vaddr;
- void **ext_reloc_iter;
- r_pvector_foreach (&ext_relocs, ext_reloc_iter) {
+ struct reloc_t **ext_reloc_iter;
+ R_VEC_FOREACH (&ext_relocs, ext_reloc_iter) {
reloc = *ext_reloc_iter;
bool found = false;
ut64 sym_addr = ht_uu_find (relocs_by_sym, reloc->ord, &found);
goto beach;
}
ht_uu_free (relocs_by_sym);
- r_pvector_fini (&ext_relocs);
+ RVecExtReloc_fini (&ext_relocs);
// XXX r_io_desc_free (gotr2desc);
return ret;
beach:
- r_pvector_fini (&ext_relocs);
+ RVecExtReloc_fini (&ext_relocs);
r_io_desc_free (gotr2desc);
r_list_free (ret);
ht_uu_free (relocs_by_sym);
}
} else if (part->format == R_BIN_MDT_PART_ELF && part->obj.elf) {
// Get relocs from nested ELF
- const RVector *elf_relocs = Elf_(load_relocs) (part->obj.elf);
+ const RVecRBinElfReloc *elf_relocs = Elf_(load_relocs) (part->obj.elf);
if (elf_relocs) {
RBinElfReloc *erel;
- r_vector_foreach (elf_relocs, erel) {
+ R_VEC_FOREACH (elf_relocs, erel) {
RBinReloc *rel = R_NEW0 (RBinReloc);
if (!rel) {
continue;
.data = &r_bin_plugin_mdt,
.version = R2_VERSION
};
-#endif
\ No newline at end of file
+#endif
#include <r_util.h>
#include <r_lib.h>
#include <r_bin.h>
-#include <r_vector.h>
+#include <r_vec.h>
#include "../format/p9/p9bin.h"
#undef P9_ALIGN
char *name;
} Sym;
+static void sym_fini (Sym *sym);
+
+R_VEC_TYPE_WITH_FINI (RVecSym, Sym, sym_fini);
+R_VEC_TYPE (RVecP9Name, char *);
+
static st64 sym_read(RBinFile *bf, Sym *sym, const ut64 offset) {
st64 size = 0;
const RBinPlan9Obj *o = (RBinPlan9Obj *)bf->bo->bin_obj;
return size;
}
-static void sym_fini(void *sym, R_UNUSED void *user) {
- Sym *s = (Sym *)sym;
- if (s && s->name) {
- R_FREE (s->name);
- }
+static void sym_fini (Sym *sym) {
+ R_FREE (sym->name);
}
static int apply_history(RBinFile *bf, ut64 pc, ut64 line, Sym *base, Sym **ret) {
static RList *symbols(RBinFile *bf) {
RList *ret = NULL;
- RVector *history = NULL; // <Sym>
- HtUP *histories = NULL; // <ut64, RVector<Sym> *>
- RPVector *names = NULL; // <char *>
+ RVecSym *history = NULL; // <Sym>
+ HtUP *histories = NULL; // <ut64, RVecSym *>
+ RVecP9Name *names = NULL; // <char *>
const RBinPlan9Obj *o = (RBinPlan9Obj *)bf->bo->bin_obj;
ut64 i;
Sym sym = {0};
goto error;
}
- if (!(names = r_pvector_new (NULL))) {
+ if (!(names = RVecP9Name_new ())) {
goto error;
}
R_LOG_ERROR ("Prevented huge memory allocation");
break;
}
- if (r_pvector_length (names) < sym.value) {
- if (!r_pvector_reserve (names, sym.value)) {
+ if (RVecP9Name_length (names) < sym.value) {
+ char *empty = NULL;
+ if (!RVecP9Name_reserve (names, sym.value)) {
goto error;
}
// reserve zeros so this is safe
- names->v.len = sym.value;
+ while (RVecP9Name_length (names) < sym.value) {
+ RVecP9Name_push_back (names, &empty);
+ }
}
- r_pvector_set (names, sym.value - 1, sym.name);
+ char **name_slot = RVecP9Name_at (names, sym.value - 1);
+ if (!name_slot) {
+ goto error;
+ }
+ *name_slot = sym.name;
continue;
}
break;
}
- const char *name = r_pvector_at (names, index - 1);
+ char *name = NULL;
+ char **name_slot = RVecP9Name_at (names, index - 1);
+ if (name_slot) {
+ name = *name_slot;
+ }
r_strbuf_appendf (sb, "%s", name);
// lead / is NOT assumed
if (i != 0) {
}
if (!history) {
- history = r_vector_new (sizeof (Sym), sym_fini, NULL);
+ history = RVecSym_new ();
}
Sym history_sym = {sym.value, 'z', name};
- r_vector_push (history, &history_sym);
+ RVecSym_push_back (history, &history_sym);
continue;
}
}
// fallthrough
default:
- sym_fini (&sym, NULL);
+ sym_fini (&sym);
continue;
}
offset = 0;
while (offset < o->header.pcsz) {
- RVector *h = ht_up_find (histories, pc + o->pcq, NULL);
+ RVecSym *h = ht_up_find (histories, pc + o->pcq, NULL);
if (h) {
history = h;
}
pc += o->pcq;
- if (history && prev != line && r_vector_length (history) > 1) {
- apply_history (bf, pc, line, r_vector_at (history, 0), NULL);
+ if (history && prev != line && RVecSym_length (history) > 1) {
+ apply_history (bf, pc, line, RVecSym_at (history, 0), NULL);
}
}
ht_up_free (histories);
- r_pvector_free (names);
+ RVecP9Name_free (names);
return ret;
error:
- sym_fini (&sym, NULL);
+ sym_fini (&sym);
r_list_free (ret);
- r_pvector_free (names);
+ RVecP9Name_free (names);
ht_up_free (histories);
return NULL;
}
#include "wasm/wasm.h"
#include "../format/wasm/wasm.h"
-static inline void *vector_at(RPVector *vec, ut64 n) {
+static inline void *vector_at(RVecWasmPtr *vec, ut64 n) {
// If the file is corrupted, the section may not have as many entries as it should
- if (n < r_pvector_length (vec)) {
- return r_pvector_at (vec, n);
+ if (vec && n < RVecWasmPtr_length (vec)) {
+ void **slot = RVecWasmPtr_at (vec, n);
+ return slot? *slot: NULL;
}
return NULL;
}
+static int vec_bsearch(RVecWasmPtr *vec, const void *needle, int (*cmp)(const void *elem, const void *needle)) {
+ if (!vec || !cmp) {
+ return -1;
+ }
+ st64 low = 0;
+ st64 high = (st64)RVecWasmPtr_length (vec) - 1;
+ while (low <= high) {
+ st64 mid = low + ((high - low) >> 1);
+ void **slot = RVecWasmPtr_at (vec, mid);
+ void *elem = slot? *slot: NULL;
+ int res = cmp (elem, needle);
+ if (!res) {
+ return (int)mid;
+ }
+ if (res < 0) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ }
+ }
+ return -1;
+}
+
static bool check(RBinFile *bf, RBuffer *rbuf) {
ut8 buf[4] = {0};
return rbuf && r_buf_read_at (rbuf, 0, buf, 4) == 4 && !memcmp (buf, R_BIN_WASM_MAGIC_BYTES, 4);
return diff > 0? 1: -1;
}
-static inline RBinWasmExportEntry *find_export(RPVector *exports, ut8 kind, ut32 index) {
+static inline RBinWasmExportEntry *find_export(RVecWasmPtr *exports, ut8 kind, ut32 index) {
if (!exports) {
return NULL;
}
struct search_fields sf = { .kind = kind, .index = index };
- int n = r_pvector_bsearch (exports, (void *)&sf, _export_finder);
+ int n = vec_bsearch (exports, (void *)&sf, _export_finder);
return n >= 0? vector_at (exports, n): NULL;
}
// TODO
ut64 addr = (ut64)r_bin_wasm_get_entrypoint (bin);
if (!addr) {
- RPVector *codes = r_bin_wasm_get_codes (bin);
+ RVecWasmPtr *codes = r_bin_wasm_get_codes (bin);
if (codes) {
RBinWasmCodeEntry *func = vector_at (codes, 0);
if (func) {
}
static inline ut32 first_ord_not_import(RBinWasmObj *bin, ut32 kind) {
- RPVector *imps = r_bin_wasm_get_imports_kind (bin, kind);
- return imps? r_pvector_length (imps): 0;
+ RVecWasmPtr *imps = r_bin_wasm_get_imports_kind (bin, kind);
+ return imps? RVecWasmPtr_length (imps): 0;
}
static const char *import_typename(ut32 kind) {
void **p;
ut32 ordinal = 0;
const char *type = import_typename (kind);
- RPVector *imports = r_bin_wasm_get_imports_kind (bin, kind);
+ RVecWasmPtr *imports = r_bin_wasm_get_imports_kind (bin, kind);
if (imports && type) {
- r_pvector_foreach (imports, p) {
+ R_VEC_FOREACH (imports, p) {
RBinWasmImportEntry *imp = *p;
RBinSymbol *sym = R_NEW0 (RBinSymbol);
if (!sym) {
}
static inline char *name_from_export(RBinWasmObj *bin, int type, int ord) {
- RPVector *exports = r_bin_wasm_get_exports (bin);
+ RVecWasmPtr *exports = r_bin_wasm_get_exports (bin);
RBinWasmExportEntry *exp = find_export (exports, type, ord);
return exp? strdup (exp->field_str): NULL;
}
}
static inline bool symbols_add_code(RBinWasmObj *bin, RList *list) {
- RPVector *codes = r_bin_wasm_get_codes (bin);
+ RVecWasmPtr *codes = r_bin_wasm_get_codes (bin);
if (!codes) {
return false;
}
ut32 ordinal = first_ord_not_import (bin, R_BIN_WASM_EXTERNALKIND_Function);
void **p;
- r_pvector_foreach (codes, p) {
+ R_VEC_FOREACH (codes, p) {
RBinWasmCodeEntry *func = *p;
RBinSymbol *sym = R_NEW0 (RBinSymbol);
if (!sym) {
}
static inline bool symbols_add_globals(RBinWasmObj *bin, RList *list) {
- RPVector *globals = r_bin_wasm_get_globals (bin);
+ RVecWasmPtr *globals = r_bin_wasm_get_globals (bin);
if (!globals) {
return true;
}
ut32 ordinal = first_ord_not_import (bin, R_BIN_WASM_EXTERNALKIND_Global);
void **p;
- r_pvector_foreach (globals, p) {
+ R_VEC_FOREACH (globals, p) {
// not real confident in any of this
RBinWasmGlobalEntry *gl = *p;
RBinSymbol *sym = R_NEW0 (RBinSymbol);
ut32 kind;
for (kind = 0; kind <= R_BIN_WASM_EXTERNALKIND_Global; kind++) {
const char *type = import_typename (kind);
- RPVector *imports = r_bin_wasm_get_imports_kind (bin, kind);
+ RVecWasmPtr *imports = r_bin_wasm_get_imports_kind (bin, kind);
if (!type || !imports) {
continue;
}
int i = 0;
void **p;
- r_pvector_foreach (imports, p) {
+ R_VEC_FOREACH (imports, p) {
RBinWasmImportEntry *import = *p;
RBinImport *ptr = R_NEW0 (RBinImport);
if (!ptr) {
static ut64 get_fcn_offset_from_id(RBinFile *bf, int ordinal) {
RBinWasmObj *bin = bf->bo->bin_obj;
ut32 min = first_ord_not_import (bin, R_BIN_WASM_EXTERNALKIND_Function);
- RPVector *codes = r_bin_wasm_get_codes (bin);
+ RVecWasmPtr *codes = r_bin_wasm_get_codes (bin);
if (min <= ordinal && codes) {
ordinal -= min;
RBinWasmCodeEntry *func = vector_at (codes, ordinal);
static ut64 get_fcn_offset_from_addr(RBinFile *bf, int addr, bool start) {
RBinWasmObj *bin = R_UNWRAP3 (bf, bo, bin_obj);
if (bin) {
- RPVector *codes = r_bin_wasm_get_codes (bin);
+ RVecWasmPtr *codes = r_bin_wasm_get_codes (bin);
if (codes) {
- int n = r_pvector_bsearch (codes, (void *)&addr, _code_frm_addr);
+ int n = vec_bsearch (codes, (void *)&addr, _code_frm_addr);
RBinWasmCodeEntry *code = vector_at (codes, n);
if (code) {
if (start) {
#include <r_codemeta.h>
#include <r_anal/hint.h>
#include <r_vec.h>
-#include <r_vector.h>
#include <r_util/r_intervaltree.h>
#include <sdb/set.h>
ut8 *fingerprint; // TODO: make is fuzzy and smarter
size_t fingerprint_size;
RAnalDiff *diff;
- RList *bbs; // TODO: should be RPVector
+ RList *bbs; // TODO: should be RVec
RAnalFcnMeta meta;
RList *imports; // maybe bound to class?
struct r_anal_t *anal; // this function is associated with this instance
};
typedef struct {
- // TODO: use RVector
+ // TODO: use RVec
RList *items;
} RTableRow;
* C++ and std::vec::Vec in Rust. Unlike in those languages, C does not have
* templates and instead relies on macros to generate 1 concrete implementation per type.
*
- * Note that compared to the older r_vector and r_pvector types in R2, there is
- * only a single type that exists for both usecases.
+ * Note that compared to the older vector types in R2, there is only a single
+ * type that exists for both use cases.
*
* The way to use this code is as follows:
* 1. Use the R_VEC_TYPE or R_VEC_TYPE_WITH_FINI macro to generate the vector
AlignTrailingComments: false
AlignOperands: false
Cpp11BracedListStyle: false
-ForEachMacros: ['r_list_foreach', 'ls_foreach', 'fcn_tree_foreach_intersect', 'r_skiplist_foreach', 'graph_foreach_anode', 'r_list_foreach_safe', 'r_pvector_foreach', 'r_rbtree_foreach', 'r_interval_tree_foreach']
+ForEachMacros: ['r_list_foreach', 'ls_foreach', 'fcn_tree_foreach_intersect', 'r_skiplist_foreach', 'graph_foreach_anode', 'r_list_foreach_safe', 'R_VEC_FOREACH', 'R_VEC_FOREACH_I', 'R_VEC_FOREACH_PREV', 'r_rbtree_foreach', 'r_interval_tree_foreach']
SortIncludes: false
"""