From 1172fc6ca429d2765cd5662ede6fecfa12fbe3b8 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Sat, 29 Jul 2023 16:33:40 +0900 Subject: [PATCH] dyld_dlfcn_resolve_symbol: search symbols in the correct object --- libdyld/dyld.c | 85 +++++++++++++++++++++++++------------------- libdyld/dyld_dlfcn.c | 10 +++++- libdyld/dyld_impl.h | 3 ++ 3 files changed, 61 insertions(+), 37 deletions(-) diff --git a/libdyld/dyld.c b/libdyld/dyld.c index 3d993e02..9d04b6fa 100644 --- a/libdyld/dyld.c +++ b/libdyld/dyld.c @@ -856,52 +856,65 @@ symtype_str(enum symtype symtype) } int -dyld_resolve_symbol(struct dyld_object *refobj, enum symtype symtype, - const struct name *sym, uint32_t *resultp) +dyld_resolve_symbol_in_obj(struct dyld_object *refobj, struct dyld_object *obj, + enum symtype symtype, const struct name *sym, + uint32_t *resultp) { struct dyld *d = refobj->dyld; - struct dyld_object *obj; enum externtype etype; if (symtype == SYM_TYPE_FUNC) { etype = EXTERNTYPE_FUNC; } else { etype = EXTERNTYPE_GLOBAL; } - LIST_FOREACH(obj, &d->objs, q) { - const struct module *m = obj->module; - /* XXX dumb linear search */ - uint32_t i; - for (i = 0; i < m->nexports; i++) { - const struct export *ex = &m->exports[i]; - const struct exportdesc *ed = &ex->desc; - if (etype != ed->type || - compare_name(sym, &ex->name)) { + const struct module *m = obj->module; + /* XXX dumb linear search */ + uint32_t i; + for (i = 0; i < m->nexports; i++) { + const struct export *ex = &m->exports[i]; + const struct exportdesc *ed = &ex->desc; + if (etype != ed->type || compare_name(sym, &ex->name)) { + continue; + } + const struct instance *inst = obj->instance; + uint32_t addr; + if (symtype == SYM_TYPE_FUNC) { + const struct funcinst *fi = + VEC_ELEM(inst->funcs, ed->idx); + addr = dyld_register_funcinst(d, obj, fi); + } else { + struct globalinst *gi = + VEC_ELEM(inst->globals, ed->idx); + if (!is_global_type_i32_const(gi->type)) { continue; } - const struct instance *inst = obj->instance; - uint32_t addr; - if (symtype == SYM_TYPE_FUNC) { - const struct funcinst *fi = - VEC_ELEM(inst->funcs, ed->idx); - addr = dyld_register_funcinst(d, obj, fi); - } else { - struct globalinst *gi = - VEC_ELEM(inst->globals, ed->idx); - if (!is_global_type_i32_const(gi->type)) { - continue; - } - /* - * TODO: consult WASM_DYLINK_EXPORT_INFO - * subsection to check TLS. - * for TLS, use __tls_base, not __memory_base. - */ - addr = global_get_i32(gi) + obj->memory_base; - } - xlog_trace("dyld: resolved %s %.*s %.*s -> %.*s idx " - "%" PRIu32 " addr %08" PRIx32, - symtype_str(symtype), CSTR(refobj->name), - CSTR(sym), CSTR(obj->name), ed->idx, addr); - *resultp = addr; + /* + * TODO: consult WASM_DYLINK_EXPORT_INFO + * subsection to check TLS. + * for TLS, use __tls_base, not __memory_base. + */ + addr = global_get_i32(gi) + obj->memory_base; + } + xlog_trace("dyld: resolved %s %.*s %.*s -> %.*s idx " + "%" PRIu32 " addr %08" PRIx32, + symtype_str(symtype), CSTR(refobj->name), CSTR(sym), + CSTR(obj->name), ed->idx, addr); + *resultp = addr; + return 0; + } + return ENOENT; +} + +int +dyld_resolve_symbol(struct dyld_object *refobj, enum symtype symtype, + const struct name *sym, uint32_t *resultp) +{ + struct dyld *d = refobj->dyld; + struct dyld_object *obj; + LIST_FOREACH(obj, &d->objs, q) { + int ret = dyld_resolve_symbol_in_obj(refobj, obj, symtype, sym, + resultp); + if (ret == 0) { return 0; } } diff --git a/libdyld/dyld_dlfcn.c b/libdyld/dyld_dlfcn.c index a21721e4..80cd3574 100644 --- a/libdyld/dyld_dlfcn.c +++ b/libdyld/dyld_dlfcn.c @@ -177,8 +177,16 @@ dyld_dlfcn_resolve_symbol(struct exec_context *ctx, struct host_instance *hi, struct name name; name.data = vp; name.nbytes = namelen; + + /* + * Note: this implementation only searches the symbols in + * the object itself. + * Typical dlsym implementions look at symbols in dependency + * libraries as well. + */ uint32_t addr; - ret = dyld_resolve_symbol(dobj->obj, type, &name, &addr); + ret = dyld_resolve_symbol_in_obj(LIST_FIRST(&d->objs), dobj->obj, type, + &name, &addr); if (ret != 0) { xlog_trace("dyld: dyld:resolve_symbol dyld_resolve_symbol " "failed for %.*s with %d", diff --git a/libdyld/dyld_impl.h b/libdyld/dyld_impl.h index aed250de..51f02f29 100644 --- a/libdyld/dyld_impl.h +++ b/libdyld/dyld_impl.h @@ -10,6 +10,9 @@ int dyld_execute_all_init_funcs(struct dyld *d, struct dyld_object *start); int dyld_resolve_symbol(struct dyld_object *refobj, enum symtype symtype, const struct name *sym, uint32_t *resultp); +int dyld_resolve_symbol_in_obj(struct dyld_object *refobj, + struct dyld_object *obj, enum symtype symtype, + const struct name *sym, uint32_t *resultp); int dyld_search_and_load_object_from_file(struct dyld *d, const struct name *name, struct dyld_object **objp);