From ce8907d6d838077794467cfeeca903824dc1fe64 Mon Sep 17 00:00:00 2001 From: Andrei Lascu Date: Tue, 17 Sep 2024 14:59:33 +0100 Subject: [PATCH] Introduce a symbols API Rework how we store and search symbols for relocation, abstracting away most of the detail, in order to be able to use various underlying data types. As relocation seems to take most of the runtime based on initial observations, this is a first step in order to compare against various backend data types, rather than using an ad-hoc implementation. --- include/compartment.h | 29 +---- include/symbols.h | 74 +++++++++++ src/CMakeLists.txt | 4 +- src/compartment.c | 289 +++++++++++++++++++++--------------------- src/symbols_comp.c | 72 +++++++++++ src/symbols_lib.c | 78 ++++++++++++ 6 files changed, 376 insertions(+), 170 deletions(-) create mode 100644 include/symbols.h create mode 100644 src/symbols_comp.c create mode 100644 src/symbols_lib.c diff --git a/include/compartment.h b/include/compartment.h index 8a70438..1a2827d 100644 --- a/include/compartment.h +++ b/include/compartment.h @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -18,6 +17,8 @@ #include #include +#include "symbols.h" + #include "cheriintrin.h" // Morello `gcc` defines `ptraddr_t` in `stddef.h`, while `clang` does so in @@ -94,28 +95,6 @@ struct LibRelaMapping uint16_t rela_sym_shndx; // section index of underlying symbol }; -/* Struct representing a symbol entry of a dependency library - */ -struct LibDependencySymbol -{ - char *sym_name; - void *sym_offset; - unsigned short sym_type; - unsigned short sym_bind; - uint16_t sym_shndx; -}; - -/* Struct representing the result of searching for a library symbol in a - * compartment; for simplicity, we store the respective library index within - * the compartment, and symbol index within the library's symbols - */ -struct LibSymSearchResult -{ - unsigned short lib_idx; - unsigned short sym_idx; - bool found; -}; - /** * Struct representing a library dependency for one of our given compartments */ @@ -131,8 +110,7 @@ struct LibDependency struct SegmentMap *lib_segs; // Symbols within this library - size_t lib_syms_count; - struct LibDependencySymbol *lib_syms; + lib_symbol_list *lib_syms; // Library dependencies for this library unsigned short lib_dep_count; @@ -224,6 +202,7 @@ struct Compartment void *tls_lookup_func; size_t total_tls_size; struct TLSDesc *libs_tls_sects; + comp_symbol_list *comp_syms; // Hardware info - maybe move size_t page_size; diff --git a/include/symbols.h b/include/symbols.h new file mode 100644 index 0000000..76cb532 --- /dev/null +++ b/include/symbols.h @@ -0,0 +1,74 @@ +#ifndef _CHERICOMP_SYMBOLS_H +#define _CHERICOMP_SYMBOLS_H + +#include +#include +#include +#include +#include + +struct simple_lds_list +{ + struct LibDependencySymbol **data; + size_t data_count; +}; + +struct simple_cs_list +{ + struct CompSymbol **data; + size_t data_count; +}; + +typedef struct simple_lds_list lib_symbol_list; +typedef struct LibDependencySymbol lib_symbol; + +typedef struct simple_cs_list comp_symbol_list; +typedef struct CompSymbol comp_symbol; + +/* Struct representing a symbol entry of a dependency library + */ +struct LibDependencySymbol +{ + char *sym_name; + void *sym_offset; + unsigned short sym_type; + unsigned short sym_bind; + uint16_t sym_shndx; +}; + +/* Struct representing a wrapper around a LibDependencySymbol, in order to + * facilitate compartment-level searching + */ +struct CompSymbol +{ + struct LibDependencySymbol *sym_ref; + size_t sym_lib_idx; +}; + +comp_symbol_list * +comp_syms_init(); +void +comp_syms_clean(comp_symbol_list *); +void +comp_syms_clean_deep(comp_symbol_list *); +void +comp_syms_insert(comp_symbol *, comp_symbol_list *); +comp_symbol * +comp_syms_search(const char *, const comp_symbol_list *); +comp_symbol_list * +comp_syms_find_all(const char *, const comp_symbol_list *); + +lib_symbol_list * +lib_syms_init(); +void +lib_syms_clean(lib_symbol_list *); +void +lib_syms_clean_deep(lib_symbol_list *); +void +lib_syms_insert(lib_symbol *, lib_symbol_list *); +lib_symbol * +lib_syms_search(const char *, const lib_symbol_list *); +lib_symbol_list * +lib_syms_find_all(const char *, const lib_symbol_list *); + +#endif // _CHERICOMP_SYMBOLS_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bbd58e3..19156e2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,10 @@ # Compartment management library add_library(chcomp STATIC - manager.c compartment.c intercept.c + manager.c + symbols_comp.c + symbols_lib.c transition.S ) target_include_directories(chcomp PRIVATE ${INCLUDE_DIR} ${TOML_INCLUDE_DIR}) diff --git a/src/compartment.c b/src/compartment.c index 45bbd4e..be882ff 100644 --- a/src/compartment.c +++ b/src/compartment.c @@ -23,17 +23,19 @@ parse_lib_rela(Elf64_Shdr *, Elf64_Ehdr *, int, struct LibDependency *); static void parse_lib_dynamic_deps(Elf64_Shdr *, Elf64_Ehdr *, int, struct LibDependency *); static void +update_comp_syms(struct Compartment *, const lib_symbol_list *, const size_t); +static void map_comp_entry_points(struct Compartment *); static void resolve_rela_syms(struct Compartment *); -static struct LibSymSearchResult -find_lib_dep_sym_in_comp(const char *, struct Compartment *, const size_t, - const unsigned short, bool); -static struct LibSymSearchResult -find_lib_dep_sym_in_lib( - const char *, struct Compartment *, const size_t, const unsigned short); +static bool +check_lib_dep_sym(lib_symbol *, const unsigned short); +static void * +eval_sym_offset(struct Compartment *, const comp_symbol *); +static void * +eval_lib_sym_offset(struct Compartment *, const size_t, const lib_symbol *); static void * -extract_sym_offset(struct Compartment *, struct LibSymSearchResult); +eval_sym_tls_offset(struct Compartment *, const comp_symbol *); static ssize_t do_pread(int, void *, size_t, off_t); @@ -87,6 +89,7 @@ comp_init() new_comp->libs_count = 0; new_comp->libs = NULL; new_comp->libs_tls_sects = NULL; + new_comp->comp_syms = comp_syms_init(); new_comp->page_size = sysconf(_SC_PAGESIZE); @@ -119,16 +122,11 @@ comp_from_elf(char *filename, struct CompConfig *cc) // Get `tls_lookup_func` if we parsed `comp_utils.so` if (!strcmp(parsed_lib->lib_name, comp_utils_soname)) { - for (size_t i = 0; i < parsed_lib->lib_syms_count; ++i) - { - if (!strcmp(parsed_lib->lib_syms[i].sym_name, tls_rtld_dropin)) - { - new_comp->tls_lookup_func - = (char *) parsed_lib->lib_syms[i].sym_offset - + (intptr_t) parsed_lib->lib_mem_base; - break; - } - } + new_comp->tls_lookup_func + = (char *) (lib_syms_search( + tls_rtld_dropin, parsed_lib->lib_syms) + ->sym_offset) + + (intptr_t) parsed_lib->lib_mem_base; assert(new_comp->tls_lookup_func); } @@ -375,11 +373,7 @@ comp_clean(struct Compartment *to_clean) free(curr_lib_dep->lib_segs); // Clean library symbol data - for (j = 0; j < curr_lib_dep->lib_syms_count; ++j) - { - free(curr_lib_dep->lib_syms[j].sym_name); - } - free(curr_lib_dep->lib_syms); + lib_syms_clean_deep(curr_lib_dep->lib_syms); // Clear library dependency names for (j = 0; j < curr_lib_dep->lib_dep_count; ++j) @@ -416,6 +410,7 @@ comp_clean(struct Compartment *to_clean) free(to_clean->cc->entry_points); free(to_clean->cc); free(to_clean->libs); + comp_syms_clean_deep(to_clean->comp_syms); if (to_clean->libs_tls_sects) { free(to_clean->libs_tls_sects); @@ -479,7 +474,6 @@ parse_lib_file(char *lib_name, struct Compartment *new_comp) new_lib->lib_segs_size = 0; new_lib->lib_segs = NULL; - new_lib->lib_syms_count = 0; new_lib->lib_syms = NULL; new_lib->lib_dep_count = 0; @@ -571,6 +565,7 @@ parse_lib_file(char *lib_name, struct Compartment *new_comp) new_comp->libs = realloc( new_comp->libs, new_comp->libs_count * sizeof(struct LibDependency *)); new_comp->libs[new_comp->libs_count - 1] = new_lib; + update_comp_syms(new_comp, new_lib->lib_syms, new_comp->libs_count - 1); free(shstrtab); @@ -651,13 +646,13 @@ parse_lib_symtb(Elf64_Shdr *symtb_shdr, Elf64_Ehdr *lib_ehdr, int lib_fd, char *str_tb = malloc(link_shdr.sh_size); do_pread(lib_fd, str_tb, link_shdr.sh_size, link_shdr.sh_offset); - lib_dep->lib_syms_count = symtb_shdr->sh_size / sizeof(Elf64_Sym); + size_t lib_syms_count = symtb_shdr->sh_size / sizeof(Elf64_Sym); size_t actual_syms = 0; - struct LibDependencySymbol *ld_syms - = malloc(lib_dep->lib_syms_count * sizeof(struct LibDependencySymbol)); Elf64_Sym curr_sym; - for (size_t j = 0; j < lib_dep->lib_syms_count; ++j) + lib_symbol_list *ld_syms = lib_syms_init(); + lib_symbol *to_insert; + for (size_t j = 0; j < lib_syms_count; ++j) { curr_sym = sym_tb[j]; // TODO currently ignore symbols of unspecified type @@ -666,18 +661,16 @@ parse_lib_symtb(Elf64_Shdr *symtb_shdr, Elf64_Ehdr *lib_ehdr, int lib_fd, continue; } - ld_syms[actual_syms].sym_offset = (void *) curr_sym.st_value; + to_insert = malloc(sizeof(lib_symbol)); + to_insert->sym_offset = (void *) curr_sym.st_value; char *sym_name = &str_tb[curr_sym.st_name]; - ld_syms[actual_syms].sym_name = malloc(strlen(sym_name) + 1); - strcpy(ld_syms[actual_syms].sym_name, sym_name); - ld_syms[actual_syms].sym_type = ELF64_ST_TYPE(curr_sym.st_info); - ld_syms[actual_syms].sym_bind = ELF64_ST_BIND(curr_sym.st_info); - ld_syms[actual_syms].sym_shndx = curr_sym.st_shndx; - actual_syms += 1; + to_insert->sym_name = malloc(strlen(sym_name) + 1); + strcpy(to_insert->sym_name, sym_name); + to_insert->sym_type = ELF64_ST_TYPE(curr_sym.st_info); + to_insert->sym_bind = ELF64_ST_BIND(curr_sym.st_info); + to_insert->sym_shndx = curr_sym.st_shndx; + lib_syms_insert(to_insert, ld_syms); } - ld_syms - = realloc(ld_syms, actual_syms * sizeof(struct LibDependencySymbol)); - lib_dep->lib_syms_count = actual_syms; lib_dep->lib_syms = ld_syms; free(sym_tb); @@ -895,6 +888,25 @@ parse_lib_dynamic_deps(Elf64_Shdr *dynamic_shdr, Elf64_Ehdr *lib_ehdr, free(dyn_entries); } +static void +update_comp_syms(struct Compartment *comp, const lib_symbol_list *lib_dep_syms, + const size_t lib_idx) +{ + comp_symbol *new_cs; + for (size_t i = 0; i < lib_dep_syms->data_count; ++i) + { + // We do not want to record non-local symbols + if (lib_dep_syms->data[i]->sym_shndx == 0) + { + continue; + } + new_cs = malloc(sizeof(comp_symbol)); + new_cs->sym_ref = lib_dep_syms->data[i]; + new_cs->sym_lib_idx = lib_idx; + comp_syms_insert(new_cs, comp->comp_syms); + } +} + static void map_comp_entry_points(struct Compartment *new_comp) { @@ -902,15 +914,25 @@ map_comp_entry_points(struct Compartment *new_comp) { // TODO are entry points always in the main loaded library? // TODO is the main loaded library always the 0th indexed one? + const size_t lib_idx = 0; const char *ep_name = new_comp->cc->entry_points[i].name; - struct LibSymSearchResult found_sym - = find_lib_dep_sym_in_comp(ep_name, new_comp, 0, STT_FUNC, true); - if (!found_sym.found) + lib_symbol_list *candidates + = lib_syms_find_all(ep_name, new_comp->libs[lib_idx]->lib_syms); + size_t j = 0; + for (; j < candidates->data_count; ++j) + { + if (check_lib_dep_sym(candidates->data[j], STT_FUNC)) + { + break; + } + } + if (j == candidates->data_count) { errx(1, "Did not find entry point %s!\n", ep_name); } new_comp->cc->entry_points[i].comp_addr - = extract_sym_offset(new_comp, found_sym); + = eval_lib_sym_offset(new_comp, lib_idx, candidates->data[j]); + free(candidates); } } @@ -920,7 +942,8 @@ resolve_rela_syms(struct Compartment *new_comp) // Find all symbols for eager relocation mapping size_t prev_tls_secs_size = 0; struct LibRelaMapping *curr_rela_map; - struct LibSymSearchResult found_sym; + comp_symbol_list *candidate_syms; + comp_symbol *chosen_sym; for (size_t i = 0; i < new_comp->libs_count; ++i) { for (size_t j = 0; j < new_comp->libs[i]->rela_maps_count; ++j) @@ -958,59 +981,84 @@ resolve_rela_syms(struct Compartment *new_comp) continue; } - // Prioritise looking for weak symbols in libraries outside the - // source library, even if they are defined - if (curr_rela_map->rela_sym_bind == STB_WEAK) + candidate_syms = comp_syms_find_all( + curr_rela_map->rela_name, new_comp->comp_syms); + + if (candidate_syms->data_count == 0) { - found_sym = find_lib_dep_sym_in_comp(curr_rela_map->rela_name, - new_comp, i, curr_rela_map->rela_sym_type, false); - if (!found_sym.found) + if (curr_rela_map->rela_sym_bind == STB_WEAK) { - found_sym - = find_lib_dep_sym_in_comp(curr_rela_map->rela_name, - new_comp, i, curr_rela_map->rela_sym_type, true); + // TODO Hack to suppress weak `libc` relocations + const char *lib_to_suppress = "libc.so"; + if (strlen(new_comp->libs[i]->lib_name) + > strlen(lib_to_suppress) + && strncmp(new_comp->libs[i]->lib_name, lib_to_suppress, + strlen(lib_to_suppress))) + { + warnx("Did not find WEAK symbol %s of type %hu (idx " + "%zu in library %s (idx %zu)) - execution " + "*might* fault.", + curr_rela_map->rela_name, + curr_rela_map->rela_sym_type, j, + new_comp->libs[i]->lib_name, i); + } + continue; } + + errx(1, + "Did not find symbol %s of type %hu (idx %zu in " + "library %s " + "(idx %zu))!", + curr_rela_map->rela_name, curr_rela_map->rela_sym_type, j, + new_comp->libs[i]->lib_name, i); } - else - { - found_sym = find_lib_dep_sym_in_comp(curr_rela_map->rela_name, - new_comp, i, curr_rela_map->rela_sym_type, - curr_rela_map->rela_sym_shndx != 0); - } + // TODO caching - if (!found_sym.found) + // Prioritise looking for weak symbols in libraries outside the + // source library, even if they are defined + if (curr_rela_map->rela_sym_bind == STB_WEAK) { - if (curr_rela_map->rela_sym_bind == STB_WEAK) + int fallback_sym_id = -1; + size_t k = 0; + for (; k < candidate_syms->data_count; ++k) { - warnx("Did not find WEAK symbol %s of type %hu (idx %zu in " - "library %s (idx %zu)) - execution *might* fault.", - curr_rela_map->rela_name, curr_rela_map->rela_sym_type, - j, new_comp->libs[i]->lib_name, i); - continue; + if (!check_lib_dep_sym(candidate_syms->data[k]->sym_ref, + curr_rela_map->rela_sym_type)) + { + continue; + } + if (candidate_syms->data[k]->sym_lib_idx != i) + { + chosen_sym = candidate_syms->data[k]; + break; + } + else + { + fallback_sym_id = k; + } } - else + if (k == candidate_syms->data_count) { - errx(1, - "Did not find symbol %s of type %hu (idx %zu in " - "library %s " - "(idx %zu))!", - curr_rela_map->rela_name, curr_rela_map->rela_sym_type, - j, new_comp->libs[i]->lib_name, i); + assert(fallback_sym_id != -1); + chosen_sym = candidate_syms->data[fallback_sym_id]; } } + else + { + // TODO is there a better choice? + chosen_sym = candidate_syms->data[0]; + } + comp_syms_clean(candidate_syms); if (curr_rela_map->rela_sym_type == STT_TLS) { curr_rela_map->target_func_address - = (char *) new_comp->libs[found_sym.lib_idx] - ->lib_syms[found_sym.sym_idx] - .sym_offset - + new_comp->libs[found_sym.lib_idx]->tls_offset; + = eval_sym_tls_offset(new_comp, chosen_sym); } else { curr_rela_map->target_func_address - = extract_sym_offset(new_comp, found_sym); + = eval_sym_offset(new_comp, chosen_sym); } } prev_tls_secs_size += new_comp->libs[i]->tls_sec_size; @@ -1033,84 +1081,37 @@ do_pread(int fd, void *buf, size_t count, off_t offset) } static void * -extract_sym_offset(struct Compartment *comp, struct LibSymSearchResult res) +eval_sym_offset(struct Compartment *comp, const comp_symbol *sym) { - return (char *) comp->libs[res.lib_idx]->lib_mem_base - + (intptr_t) comp->libs[res.lib_idx]->lib_syms[res.sym_idx].sym_offset; + return (char *) comp->libs[sym->sym_lib_idx]->lib_mem_base + + (intptr_t) sym->sym_ref->sym_offset; } -static struct LibSymSearchResult -find_lib_dep_sym_in_comp(const char *to_find, - struct Compartment *comp_to_search, const size_t source_lib_idx, - const unsigned short sym_type, bool in_lib) +static void * +eval_lib_sym_offset( + struct Compartment *comp, const size_t lib_idx, const lib_symbol *sym) { - struct LibSymSearchResult res = { -1, -1, false }; - if (in_lib) - { - res = find_lib_dep_sym_in_lib( - to_find, comp_to_search, source_lib_idx, sym_type); - } - else - { - for (size_t i = 0; i < comp_to_search->libs_count; ++i) - { - if (i == source_lib_idx) - { - continue; - } - res = find_lib_dep_sym_in_lib(to_find, comp_to_search, i, sym_type); - if (res.found) - { - break; - } - } - } - return res; + return (char *) comp->libs[lib_idx]->lib_mem_base + + (intptr_t) sym->sym_offset; } -static struct LibSymSearchResult -find_lib_dep_sym_in_lib(const char *to_find, struct Compartment *comp_to_search, - const size_t lib_idx, const unsigned short sym_type) +static void * +eval_sym_tls_offset(struct Compartment *comp, const comp_symbol *sym) { - const size_t syms_count = comp_to_search->libs[lib_idx]->lib_syms_count; - const struct LibDependencySymbol *syms - = comp_to_search->libs[lib_idx]->lib_syms; - struct LibSymSearchResult res = { -1, -1, false }; - for (size_t i = 0; i < syms_count; ++i) - { - struct LibDependencySymbol curr_sym = syms[i]; - - // Ignore no-named symbols - if (!curr_sym.sym_name) - { - continue; - } + return (char *) sym->sym_ref->sym_offset + + comp->libs[sym->sym_lib_idx]->tls_offset; +} - // We build up the conditions needed to find a valid symbol to be - // relocated against in `cond` - // +static bool +check_lib_dep_sym(lib_symbol *sym, const unsigned short sym_type) +{ + return // Ignore `LOCAL` bind symbols - they cannot be relocated against - bool cond = curr_sym.sym_bind != STB_LOCAL; - + sym->sym_bind != STB_LOCAL && // Check symbol is indeed local, not another external reference - cond = cond && curr_sym.sym_shndx != 0; - - // Check symbol name matches - cond = cond && !strcmp(to_find, curr_sym.sym_name); - + sym->sym_shndx != 0 && // Check symbol type matches - cond = cond && curr_sym.sym_type == sym_type; - - // If all conditions pass, we found a valid symbol to relocate against - if (cond) - { - res = (struct LibSymSearchResult) { - .lib_idx = lib_idx, .sym_idx = i, .found = true - }; - break; - } - } - return res; + sym->sym_type == sym_type; } static char * @@ -1280,7 +1281,7 @@ print_lib_dep(struct LibDependency *lib_dep) print_lib_dep_seg(&lib_dep->lib_segs[i]); } - printf("- lib_syms_count : %lu\n", lib_dep->lib_syms_count); + // TODO lib_syms printf("- lib_dep_count : %hu\n", lib_dep->lib_dep_count); printf("- lib_dep_names :\n"); diff --git a/src/symbols_comp.c b/src/symbols_comp.c new file mode 100644 index 0000000..d5e7fc4 --- /dev/null +++ b/src/symbols_comp.c @@ -0,0 +1,72 @@ +#include "symbols.h" + +/******************************************************************************* + * Main functions + ******************************************************************************/ + +comp_symbol_list * +comp_syms_init() +{ + comp_symbol_list *new_list = malloc(sizeof(comp_symbol_list)); + new_list->data_count = 0; + new_list->data = NULL; + return new_list; +} + +void +comp_syms_clean(comp_symbol_list *list) +{ + free(list->data); + free(list); +} + +void +comp_syms_clean_deep(comp_symbol_list *list) +{ + for (size_t i = 0; i < list->data_count; ++i) + { + free(list->data[i]); + } + comp_syms_clean(list); +} + +void +comp_syms_insert(comp_symbol *to_insert, comp_symbol_list *list) +{ + size_t curr_count = list->data_count; + list->data = realloc(list->data, (curr_count + 1) * sizeof(comp_symbol *)); + if (list->data == NULL) + { + err(1, "Error inserting symbol %s in comp_list!", + to_insert->sym_ref->sym_name); + } + list->data[curr_count] = to_insert; + list->data_count += 1; +} + +comp_symbol * +comp_syms_search(const char *to_find, const comp_symbol_list *list) +{ + for (size_t i = 0; i < list->data_count; ++i) + { + if (!strcmp(list->data[i]->sym_ref->sym_name, to_find)) + { + return list->data[i]; + } + } + errx(1, "Did not find symbol %s!\n", to_find); +} + +comp_symbol_list * +comp_syms_find_all(const char *to_find, const comp_symbol_list *list) +{ + comp_symbol_list *res = comp_syms_init(); + for (size_t i = 0; i < list->data_count; ++i) + { + if (!strcmp(list->data[i]->sym_ref->sym_name, to_find)) + { + comp_syms_insert(list->data[i], res); + } + } + return res; +} diff --git a/src/symbols_lib.c b/src/symbols_lib.c new file mode 100644 index 0000000..2c48272 --- /dev/null +++ b/src/symbols_lib.c @@ -0,0 +1,78 @@ +#include "symbols.h" + +static void +lib_syms_clean_one_entry(lib_symbol *sym) +{ + free(sym->sym_name); + free(sym); +} + +/******************************************************************************* + * Main functions + ******************************************************************************/ + +lib_symbol_list * +lib_syms_init() +{ + lib_symbol_list *new_list = malloc(sizeof(lib_symbol_list)); + new_list->data_count = 0; + new_list->data = NULL; + return new_list; +} + +void +lib_syms_clean(lib_symbol_list *list) +{ + free(list->data); + free(list); +} + +void +lib_syms_clean_deep(lib_symbol_list *list) +{ + for (size_t i = 0; i < list->data_count; ++i) + { + lib_syms_clean_one_entry(list->data[i]); + } + lib_syms_clean(list); +} + +void +lib_syms_insert(lib_symbol *to_insert, lib_symbol_list *list) +{ + size_t curr_count = list->data_count; + list->data = realloc(list->data, (curr_count + 1) * sizeof(lib_symbol *)); + if (list->data == NULL) + { + err(1, "Error inserting symbol %s in lib_list!", to_insert->sym_name); + } + list->data[curr_count] = to_insert; + list->data_count += 1; +} + +lib_symbol * +lib_syms_search(const char *to_find, const lib_symbol_list *list) +{ + for (size_t i = 0; i < list->data_count; ++i) + { + if (!strcmp(list->data[i]->sym_name, to_find)) + { + return list->data[i]; + } + } + errx(1, "Did not find symbol %s!\n", to_find); +} + +lib_symbol_list * +lib_syms_find_all(const char *to_find, const lib_symbol_list *list) +{ + lib_symbol_list *res = lib_syms_init(); + for (size_t i = 0; i < list->data_count; ++i) + { + if (!strcmp(list->data[i]->sym_name, to_find)) + { + lib_syms_insert(list->data[i], res); + } + } + return res; +}