提交 6e218489 编写于 作者: G ganlan

fix symbol version

Signed-off-by: Nganlan <tony.gan@huawei.com>
上级 d196b326
......@@ -37,6 +37,7 @@ group("dso_shared") {
":dso_hard_symver",
":dso_no_symver",
":dso_symver",
":reloc_symver_dso",
]
}
......@@ -53,3 +54,10 @@ test_sharedlib("dso_no_symver") {
test_sharedlib("dso_symver") {
}
test_sharedlib("reloc_symver_dso") {
deps = [
":dso_easy_symver",
":dso_no_symver",
]
}
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <dlfcn.h>
#include "dso_symver.h"
/**
* @tc.name : reloc_symver_0100
* @tc.desc : find versioning symbol while relocating.
* load libreloc_symver_dso.so that deps on libdso_no_symver.so and libdso_easy_symver.so.
* @tc.level : Level 1
*/
static void reloc_symver_0100(void)
{
symver_log("start");
void *so = dlopen("libreloc_symver_dso.so", RTLD_NOW);
if (so) {
dlclose(so);
} else {
symver_error("%s", dlerror());
}
symver_log("end");
}
int main(int argc, char *argv[])
{
symver_log("start");
reloc_symver_0100();
symver_log("t_status = %d", t_status);
symver_log("end");
return t_status;
}
\ No newline at end of file
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "dso_no_symver.h"
#include "dso_easy_symver.h"
void test_func()
{
(void)dso_no_symver();
(void)dso_easy_symver();
}
\ No newline at end of file
......@@ -16,4 +16,5 @@ functionalext_symver_list = [
"dlvsym",
"dynlink_default",
"dynlink",
"reloc_symver",
]
......@@ -274,6 +274,10 @@ template("test_sharedlib") {
ldflags += [ "-Wl,--version-script=${_version_script}" ]
}
if (defined(invoker.deps)) {
deps = invoker.deps
}
libs = [ "//${out_test_dir}/src/common/libtest.a" ]
output_name = "${target_name}"
......
......@@ -86,7 +86,8 @@ struct td_index {
struct verinfo {
const char *s;
const char *v;
Verneed *verneed;
bool use_vna_hash;
uint32_t vna_hash;
};
struct dso {
......@@ -464,45 +465,23 @@ static int search_vec(size_t *v, size_t *r, size_t key)
return 1;
}
static int check_verneed(Verdef *def, int vsym, struct verinfo *verinfo)
static int check_vna_hash(Verdef *def, int16_t vsym, uint32_t vna_hash)
{
int matched = 0;
Verneed *verneed = verinfo->verneed;
vsym &= 0x7fff;
Verdef *verdef = def;
for(;;) {
Vernaux *vernaux = (Vernaux *)((char *)verneed + verneed->vn_aux);
for (size_t cnt = 0; cnt < verneed->vn_cnt; cnt++) {
Verdef *verdef = def;
/* find the version of symbol for verneed. */
for(;;) {
if (vernaux->vna_hash == verdef->vd_hash) {
if ((verdef->vd_ndx & 0x7fff) == vsym) {
matched = 1;
}
break;
}
if (verdef->vd_next == 0) {
break;
}
verdef = (Verdef *)((char *)verdef + verdef->vd_next);
}
if (matched) {
break;
if ((verdef->vd_ndx & 0x7fff) == vsym) {
if (vna_hash == verdef->vd_hash) {
matched = 1;
}
vernaux = (Vernaux *)((char *)vernaux + vernaux->vna_next);
break;
}
if (verneed->vn_next == 0) {
if (verdef->vd_next == 0) {
break;
}
verneed = (Verneed *)((char *)verneed + verneed->vn_next);
verdef = (Verdef *)((char *)verdef + verdef->vd_next);
}
return matched;
......@@ -519,12 +498,13 @@ static int check_verinfo(Verdef *def, int16_t *versym, uint32_t index, struct ve
}
}
int vsym = versym[index];
int16_t vsym = versym[index];
/* if the verneed is not null , find the verneed symbol. */
Verneed *verneed = verinfo->verneed;
if (verneed) {
return check_verneed(def, vsym, verinfo);
/* find the verneed symbol. */
if (verinfo->use_vna_hash) {
if (vsym != VER_NDX_LOCAL && versym != VER_NDX_GLOBAL) {
return check_vna_hash(def, vsym, verinfo->vna_hash);
}
}
/* if the version length is zero and vsym not less than zero, then library hava default version symbol. */
......@@ -750,10 +730,52 @@ static inline struct symdef find_sym2(struct dso *dso, struct verinfo *verinfo,
static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
{
struct verinfo verinfo = { .s = s, .v = "", .verneed = dso->verneed };
struct verinfo verinfo = { .s = s, .v = "", .use_vna_hash = false };
return find_sym2(dso, &verinfo, need_def, 0, NULL);
}
static bool get_vna_hash(struct dso *dso, int sym_index, uint32_t *vna_hash)
{
if (!dso->versym || !dso->verneed) {
return false;
}
uint16_t vsym = dso->versym[sym_index];
if (vsym == VER_NDX_LOCAL || vsym == VER_NDX_GLOBAL) {
return false;
}
bool result = false;
Verneed *verneed = dso->verneed;
Vernaux *vernaux;
vsym &= 0x7fff;
for(;;) {
vernaux = (Vernaux *)((char *)verneed + verneed->vn_aux);
for (size_t cnt = 0; cnt < verneed->vn_cnt; cnt++) {
if ((vernaux->vna_other & 0x7fff) == vsym) {
result = true;
*vna_hash = vernaux->vna_hash;
break;
}
vernaux = (Vernaux *)((char *)vernaux + vernaux->vna_next);
}
if (result) {
break;
}
if (verneed->vn_next == 0) {
break;
}
verneed = (Verneed *)((char *)verneed + verneed->vn_next);
}
return result;
}
static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride)
{
unsigned char *base = dso->base;
......@@ -804,7 +826,8 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
sym = syms + sym_index;
name = strings + sym->st_name;
ctx = type==REL_COPY ? head->syms_next : head;
struct verinfo vinfo = { .s = name, .v = "", .verneed = dso->verneed };
struct verinfo vinfo = { .s = name, .v = "" };
vinfo.use_vna_hash = get_vna_hash(dso, sym_index, &vinfo.vna_hash);
def = (sym->st_info>>4) == STB_LOCAL
? (struct symdef){ .dso = dso, .sym = sym }
: find_sym2(ctx, &vinfo, type==REL_PLT, 0, dso->namespace);
......@@ -3056,7 +3079,7 @@ static void *do_dlsym(struct dso *p, const char *s, const char *v, void *ra)
ns = caller->namespace;
}
}
struct verinfo verinfo = { .s = s, .v = v, .verneed = NULL };
struct verinfo verinfo = { .s = s, .v = v, .use_vna_hash = false };
struct symdef def = find_sym2(p, &verinfo, 0, use_deps, ns);
if (!def.sym) {
error("Symbol not found: %s, version: %s", s, strlen(v) > 0 ? v : "null");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册