未验证 提交 a2bde143 编写于 作者: O openharmony_ci 提交者: Gitee

!419 RM.006.增强动态库符号管理

Merge pull request !419 from dhy308/branch_rm006
# 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.
import("../../../test_template.gni")
import("test_src_functionalext_symver.gni")
foreach(s, functionalext_symver_list) {
test_unittest(s) {
target_dir = "functionalext/symver"
}
}
group("functionalext_symver_test") {
testonly = true
deps = [ ":dso_shared" ]
foreach(s, functionalext_symver_list) {
deps += [ ":${s}" ]
}
}
group("dso_shared") {
testonly = true
deps = [
":dso_easy_symver",
":dso_hard_symver",
":dso_no_symver",
":dso_symver",
]
}
test_sharedlib("dso_easy_symver") {
version_script = "dso_easy_symver.map"
}
test_sharedlib("dso_hard_symver") {
version_script = "dso_hard_symver.map"
}
test_sharedlib("dso_no_symver") {
}
test_sharedlib("dso_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_easy_symver.h"
#include "dso_hard_symver.h"
#include "dso_no_symver.h"
#include "dso_symver.h"
/**
* @tc.name : dlsym_no_symver_0100
* @tc.desc : invoke a symbol programmatically
* @tc.level : Level 0
*/
void dlsym_no_symver_0100(void)
{
symver_log("start");
void *handle = dlopen(dso_no_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlsym(handle, dso_no_symver_symbol);
const char *error = dlerror();
if (error != NULL) {
symver_error("%s", error);
return;
}
const char *result = func();
symver_streq(result, dso_no_symver_symbol);
dlclose(handle);
symver_log("end");
}
/**
* @tc.name : dlsym_no_symver_0200
* @tc.desc : invoke an invalid symbol programmatically
* @tc.level : Level 2
*/
void dlsym_no_symver_0200(void)
{
symver_log("start");
void *handle = dlopen(dso_no_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlsym(handle, dso_symbol_invalid);
const char *error = dlerror();
if (error == NULL) {
symver_error();
return;
}
symver_log("error = %s", error);
dlclose(handle);
symver_log("end");
}
/**
* @tc.name : dlsym_easy_symver_0100
* @tc.desc : invoke a symbol directly after specifying a non-default version
* @tc.level : Level 0
*/
void dlsym_easy_symver_0100(void)
{
symver_log("start");
__asm__(".symver dso_easy_symver, dso_easy_symver@OLD");
const char *result = dso_easy_symver();
symver_streq(result, dso_easy_symver_symbol_old);
symver_log("end");
}
/**
* @tc.name : dlsym_easy_symver_0200
* @tc.desc : invoke a symbol with versions programmatically
* @tc.level : Level 1
*/
void dlsym_easy_symver_0200(void)
{
symver_log("start");
void *handle = dlopen(dso_easy_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlsym(handle, dso_easy_symver_symbol);
const char *error = dlerror();
if (error != NULL) {
symver_error("%s", error);
return;
}
const char *result = func();
symver_streq(result, dso_easy_symver_symbol_stable);
dlclose(handle);
symver_log("end");
}
/**
* @tc.name : dlsym_easy_symver_0300
* @tc.desc : invoke an invalid symbol programmatically
* @tc.level : Level 2
*/
void dlsym_easy_symver_0300(void)
{
symver_log("start");
void *handle = dlopen(dso_easy_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlsym(handle, dso_symbol_invalid);
const char *error = dlerror();
if (error == NULL) {
symver_error();
return;
}
symver_log("error = %s", error);
dlclose(handle);
symver_log("end");
}
/**
* @tc.name : dlsym_hard_symver_0100
* @tc.desc : invoke a symbol directly after specifying a non-default version
* @tc.level : Level 0
*/
void dlsym_hard_symver_0100(void)
{
symver_log("start");
__asm__(".symver dso_hard_symver_ld, dso_hard_symver_ld@OLD");
const char *result = dso_hard_symver_ld();
symver_streq(result, dso_hard_symver_ld_symbol_old);
symver_log("end");
}
/**
* @tc.name : dlsym_hard_symver_0200
* @tc.desc : invoke a symbol with versions programmatically
* @tc.level : Level 1
*/
void dlsym_hard_symver_0200(void)
{
symver_log("start");
void *handle = dlopen(dso_hard_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlsym(handle, dso_hard_symver_if_symbol);
const char *error = dlerror();
if (error != NULL) {
symver_error("%s", error);
return;
}
const char *result = func();
symver_streq(result, dso_hard_symver_if_symbol_stable);
dlclose(handle);
symver_log("end");
}
/**
* @tc.name : dlsym_hard_symver_0300
* @tc.desc : invoke an invalid symbol programmatically
* @tc.level : Level 2
*/
void dlsym_hard_symver_0300(void)
{
symver_log("start");
void *handle = dlopen(dso_hard_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlsym(handle, dso_symbol_invalid);
const char *error = dlerror();
if (error == NULL) {
symver_error();
return;
}
symver_log("error = %s", error);
dlclose(handle);
symver_log("end");
}
int main(int argc, char *argv[])
{
symver_log("start");
dlsym_no_symver_0100();
dlsym_no_symver_0200();
dlsym_easy_symver_0100();
dlsym_easy_symver_0200();
dlsym_easy_symver_0300();
dlsym_hard_symver_0100();
dlsym_hard_symver_0200();
dlsym_hard_symver_0300();
symver_log("t_status = %d", t_status);
symver_log("end");
return t_status;
}
/*
* 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 : dlvsym_no_symver_0100
* @tc.desc : invoke a symbol with an invalid version
* @tc.level : Level 2
*/
void dlvsym_no_symver_0100(void)
{
symver_log("start");
void *handle = dlopen(dso_no_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlvsym(handle, dso_no_symver_symbol, dso_version_invalid);
const char *error = dlerror();
if (error == NULL) {
symver_error();
return;
}
symver_log("error = %s", error);
dlclose(handle);
symver_log("end");
}
/**
* @tc.name : dlvsym_no_symver_0200
* @tc.desc : invoke an invalid symbol with an invalid version
* @tc.level : Level 2
*/
void dlvsym_no_symver_0200(void)
{
symver_log("start");
void *handle = dlopen(dso_no_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlvsym(handle, dso_symbol_invalid, dso_version_invalid);
const char *error = dlerror();
if (error == NULL) {
symver_error();
return;
}
symver_log("error = %s", error);
dlclose(handle);
symver_log("end");
}
/**
* @tc.name : dlvsym_easy_symver_0100
* @tc.desc : invoke a symbol with the default version
* @tc.level : Level 0
*/
void dlvsym_easy_symver_0100(void)
{
symver_log("start");
void *handle = dlopen(dso_easy_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlvsym(handle, dso_easy_symver_symbol, dso_easy_symver_version_stable);
const char *error = dlerror();
if (error != NULL) {
symver_error("%s", error);
return;
}
const char *result = func();
symver_streq(result, dso_easy_symver_symbol_stable);
dlclose(handle);
symver_log("end");
}
/**
* @tc.name : dlvsym_easy_symver_0200
* @tc.desc : invoke a symbol with a non-default version
* @tc.level : Level 1
*/
void dlvsym_easy_symver_0200(void)
{
symver_log("start");
void *handle = dlopen(dso_easy_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlvsym(handle, dso_easy_symver_symbol, dso_easy_symver_version_old);
const char *error = dlerror();
if (error != NULL) {
symver_error("%s", error);
return;
}
const char *result = func();
symver_streq(result, dso_easy_symver_symbol_old);
dlclose(handle);
symver_log("end");
}
/**
* @tc.name : dlvsym_easy_symver_0300
* @tc.desc : invoke an invalid symbol with an invalid version
* @tc.level : Level 2
*/
void dlvsym_easy_symver_0300(void)
{
symver_log("start");
void *handle = dlopen(dso_easy_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlvsym(handle, dso_symbol_invalid, dso_version_invalid);
const char *error = dlerror();
if (error == NULL) {
symver_error();
return;
}
symver_log("error = %s", error);
dlclose(handle);
symver_log("end");
}
/**
* @tc.name : dlvsym_easy_symver_0400
* @tc.desc : invoke a symbol with an invalid version
* @tc.level : Level 2
*/
void dlvsym_easy_symver_0400(void)
{
symver_log("start");
void *handle = dlopen(dso_easy_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlvsym(handle, dso_easy_symver_symbol, dso_version_invalid);
const char *error = dlerror();
if (error == NULL) {
symver_error();
return;
}
symver_log("error = %s", error);
dlclose(handle);
symver_log("end");
}
/**
* @tc.name : dlvsym_hard_symver_0100
* @tc.desc : invoke a symbol with the default version
* @tc.level : Level 0
*/
void dlvsym_hard_symver_0100(void)
{
symver_log("start");
void *handle = dlopen(dso_hard_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlvsym(handle, dso_hard_symver_if_symbol, dso_hard_symver_version_stable);
const char *error = dlerror();
if (error != NULL) {
symver_error("%s", error);
return;
}
const char *result = func();
symver_streq(result, dso_hard_symver_if_symbol_stable);
dlclose(handle);
symver_log("end");
}
/**
* @tc.name : dlvsym_hard_symver_0200
* @tc.desc : invoke a symbol with a non-default version
* @tc.level : Level 1
*/
void dlvsym_hard_symver_0200(void)
{
symver_log("start");
void *handle = dlopen(dso_hard_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlvsym(handle, dso_hard_symver_if_symbol, dso_hard_symver_version_old);
const char *error = dlerror();
if (error != NULL) {
symver_error("%s", error);
return;
}
const char *result = func();
symver_streq(result, dso_hard_symver_if_symbol_old);
dlclose(handle);
symver_log("end");
}
/**
* @tc.name : dlvsym_hard_symver_0300
* @tc.desc : invoke an invalid symbol with an invalid version
* @tc.level : Level 2
*/
void dlvsym_hard_symver_0300(void)
{
symver_log("start");
void *handle = dlopen(dso_hard_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlvsym(handle, dso_symbol_invalid, dso_version_invalid);
const char *error = dlerror();
if (error == NULL) {
symver_error();
return;
}
symver_log("error = %s", error);
dlclose(handle);
symver_log("end");
}
/**
* @tc.name : dlvsym_hard_symver_0400
* @tc.desc : invoke a symbol with an invalid version
* @tc.level : Level 2
*/
void dlvsym_hard_symver_0400(void)
{
symver_log("start");
void *handle = dlopen(dso_hard_symver_name, RTLD_LAZY);
if (!handle) {
symver_error("%s", dlerror());
return;
}
// Clear any existing error
dlerror();
functype func = (functype)dlvsym(handle, dso_hard_symver_if_symbol, dso_version_invalid);
const char *error = dlerror();
if (error == NULL) {
symver_error();
return;
}
symver_log("error = %s", error);
dlclose(handle);
symver_log("end");
}
int main(int argc, char *argv[])
{
symver_log("start");
dlvsym_no_symver_0100();
dlvsym_no_symver_0200();
dlvsym_easy_symver_0100();
dlvsym_easy_symver_0200();
dlvsym_easy_symver_0300();
dlvsym_easy_symver_0400();
dlvsym_hard_symver_0100();
dlvsym_hard_symver_0200();
dlvsym_hard_symver_0300();
dlvsym_hard_symver_0400();
symver_log("t_status = %d", t_status);
symver_log("end");
return t_status;
}
/*
* 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_easy_symver.h"
__asm__(".symver dso_easy_symver_old, dso_easy_symver@OLD");
__asm__(".symver dso_easy_symver_stable, dso_easy_symver@@STABLE");
__asm__(".symver dso_easy_symver_dev, dso_easy_symver@DEV");
char *dso_easy_symver_old(void)
{
return (char *)__FUNCTION__;
}
char *dso_easy_symver_stable(void)
{
return (char *)__FUNCTION__;
}
char *dso_easy_symver_dev(void)
{
return (char *)__FUNCTION__;
}
/*
* 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.
*/
#ifdef __cplusplus
extern "C" {
#endif
char *dso_easy_symver(void);
#ifdef __cplusplus
}
#endif
# 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.
OLD {
global: dso_easy_symver_old;
local: *;
};
STABLE {
global: dso_easy_symver_stable;
local: *;
};
DEV {
global: dso_easy_symver_dev;
local: *;
};
/*
* 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_hard_symver.h"
__asm__(".symver dso_hard_symver_if_old, dso_hard_symver_if@OLD");
__asm__(".symver dso_hard_symver_if_stable, dso_hard_symver_if@@STABLE");
__asm__(".symver dso_hard_symver_if_dev, dso_hard_symver_if@DEV");
__asm__(".symver dso_hard_symver_ld_old, dso_hard_symver_ld@OLD");
__asm__(".symver dso_hard_symver_ld_stable, dso_hard_symver_ld@@STABLE");
__asm__(".symver dso_hard_symver_ld_dev, dso_hard_symver_ld@DEV");
char *dso_hard_symver_if_old(void)
{
return (char *)__FUNCTION__;
}
char *dso_hard_symver_if_stable(void)
{
return (char *)__FUNCTION__;
}
char *dso_hard_symver_if_dev(void)
{
return (char *)__FUNCTION__;
}
char *dso_hard_symver_ld_old(void)
{
return (char *)__FUNCTION__;
}
char *dso_hard_symver_ld_stable(void)
{
return (char *)__FUNCTION__;
}
char *dso_hard_symver_ld_dev(void)
{
return (char *)__FUNCTION__;
}
/*
* 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.
*/
#ifdef __cplusplus
extern "C" {
#endif
char *dso_hard_symver_if(void);
char *dso_hard_symver_ld(void);
#ifdef __cplusplus
}
#endif
# 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.
OLD {
global: dso_hard_symver_if_old; dso_hard_symver_ld_old;
local: *;
};
STABLE {
global: dso_hard_symver_if_stable; dso_hard_symver_ld_stable;
local: *;
};
DEV {
global: dso_hard_symver_if_dev; dso_hard_symver_ld_dev;
local: *;
};
/*
* 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"
char *dso_no_symver(void)
{
return (char *)__FUNCTION__;
}
/*
* 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.
*/
#ifdef __cplusplus
extern "C" {
#endif
char *dso_no_symver(void);
#ifdef __cplusplus
}
#endif
/*
* 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.
*/
const char *dso_symbol_invalid = "dso_symbol_invalid";
const char *dso_version_invalid = "dso_version_invalid";
const char *dso_no_symver_name = "libdso_no_symver.so";
const char *dso_no_symver_symbol = "dso_no_symver";
const char *dso_easy_symver_name = "libdso_easy_symver.so";
const char *dso_easy_symver_symbol = "dso_easy_symver";
const char *dso_easy_symver_symbol_old = "dso_easy_symver_old";
const char *dso_easy_symver_symbol_stable = "dso_easy_symver_stable";
const char *dso_easy_symver_symbol_dev = "dso_easy_symver_dev";
const char *dso_easy_symver_version_old = "OLD";
const char *dso_easy_symver_version_stable = "STABLE";
const char *dso_easy_symver_version_dev = "DEV";
const char *dso_hard_symver_name = "libdso_hard_symver.so";
const char *dso_hard_symver_if_symbol = "dso_hard_symver_if";
const char *dso_hard_symver_if_symbol_old = "dso_hard_symver_if_old";
const char *dso_hard_symver_if_symbol_stable = "dso_hard_symver_if_stable";
const char *dso_hard_symver_if_symbol_dev = "dso_hard_symver_if_dev";
const char *dso_hard_symver_ld_symbol = "dso_hard_symver_ld";
const char *dso_hard_symver_ld_symbol_old = "dso_hard_symver_ld_old";
const char *dso_hard_symver_ld_symbol_stable = "dso_hard_symver_ld_stable";
const char *dso_hard_symver_ld_symbol_dev = "dso_hard_symver_ld_dev";
const char *dso_hard_symver_version_old = "OLD";
const char *dso_hard_symver_version_stable = "STABLE";
const char *dso_hard_symver_version_dev = "DEV";
/*
* 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 <stdio.h>
#include <string.h>
#include "test.h"
extern const char *dso_symbol_invalid;
extern const char *dso_version_invalid;
extern const char *dso_no_symver_name;
extern const char *dso_no_symver_symbol;
extern const char *dso_easy_symver_name;
extern const char *dso_easy_symver_symbol;
extern const char *dso_easy_symver_symbol_old;
extern const char *dso_easy_symver_symbol_stable;
extern const char *dso_easy_symver_symbol_dev;
extern const char *dso_easy_symver_version_old;
extern const char *dso_easy_symver_version_stable;
extern const char *dso_easy_symver_version_dev;
extern const char *dso_hard_symver_name;
extern const char *dso_hard_symver_if_symbol;
extern const char *dso_hard_symver_if_symbol_old;
extern const char *dso_hard_symver_if_symbol_stable;
extern const char *dso_hard_symver_if_symbol_dev;
extern const char *dso_hard_symver_ld_symbol;
extern const char *dso_hard_symver_ld_symbol_old;
extern const char *dso_hard_symver_ld_symbol_stable;
extern const char *dso_hard_symver_ld_symbol_dev;
extern const char *dso_hard_symver_version_old;
extern const char *dso_hard_symver_version_stable;
extern const char *dso_hard_symver_version_dev;
typedef char *(*functype)(void);
#define SYMVER_DEBUG
#ifdef SYMVER_DEBUG
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
#define symver_log(fmt, ...) \
do { \
printf("[%s:%4d][%s]" fmt "\n", __FILENAME__, __LINE__, __FUNCTION__, ##__VA_ARGS__); \
} while (0)
#else // SYMVER_DEBUG
#define symver_log(fmt, ...)
#endif // SYMVER_DEBUG
#define symver_error(fmt, ...) \
do { \
t_error("%s failed: " fmt "\n", __FUNCTION__, ##__VA_ARGS__); \
} while (0)
#define symver_streq(s1, s2) \
do { \
if (strcmp(s1, s2)) { \
t_error("%s failed: s1 = %s, s2 = %s\n", __FUNCTION__, s1, s2); \
} \
} while (0)
/*
* 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_easy_symver.h"
#include "dso_hard_symver.h"
#include "dso_no_symver.h"
#include "dso_symver.h"
/**
* @tc.name : dynlink_0100
* @tc.desc : invoke a symbol without versions directly
* @tc.level : Level 0
*/
void dynlink_0100(void)
{
symver_log("start");
const char *result = dso_no_symver();
symver_streq(result, dso_no_symver_symbol);
symver_log("end");
}
/**
* @tc.name : dynlink_0200
* @tc.desc : invoke a symbol with versions directly
* @tc.level : Level 1
*/
void dynlink_0200(void)
{
symver_log("start");
const char *result = dso_easy_symver();
symver_streq(result, dso_easy_symver_symbol_stable);
symver_log("end");
}
/**
* @tc.name : dynlink_0300
* @tc.desc : invoke a symbol with versions directly
* @tc.level : Level 1
*/
void dynlink_0300(void)
{
symver_log("start");
const char *result = dso_hard_symver_ld();
symver_streq(result, dso_hard_symver_ld_symbol_stable);
symver_log("end");
}
int main(int argc, char *argv[])
{
symver_log("start");
dynlink_0100();
dynlink_0200();
dynlink_0300();
symver_log("t_status = %d", t_status);
symver_log("end");
return t_status;
}
/*
* 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_easy_symver.h"
#include "dso_hard_symver.h"
#include "dso_no_symver.h"
#include "dso_symver.h"
/**
* @tc.name : dynlink_default_0100
* @tc.desc : invoke a symbol directly after specifying the default version
* @tc.level : Level 0
*/
void dynlink_default_0100(void)
{
symver_log("start");
__asm__(".symver dso_easy_symver, dso_easy_symver@STABLE");
const char *result = dso_easy_symver();
symver_streq(result, dso_easy_symver_symbol_stable);
symver_log("end");
}
/**
* @tc.name : dynlink_default_0200
* @tc.desc : invoke a symbol directly after specifying the default version
* @tc.level : Level 1
*/
void dynlink_default_0200(void)
{
symver_log("start");
__asm__(".symver dso_hard_symver_ld, dso_hard_symver_ld@STABLE");
const char *result = dso_hard_symver_ld();
symver_streq(result, dso_hard_symver_ld_symbol_stable);
symver_log("end");
}
int main(int argc, char *argv[])
{
symver_log("start");
dynlink_default_0100();
dynlink_default_0200();
symver_log("t_status = %d", t_status);
symver_log("end");
return t_status;
}
# 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.
functionalext_symver_list = [
"dlsym",
"dlvsym",
"dynlink_default",
"dynlink",
]
......@@ -22,4 +22,5 @@ functionalext_list = [
"info:functionalext_info_test",
"ldso_randomization:functionalext_ldso_randomization_test",
"relro:functionalext_relro_test",
"symver:functionalext_symver_test",
]
......@@ -136,6 +136,19 @@ template("test_unittest") {
include_dirs += [ "//${test_dir}/src/functionalext/common" ]
}
if (target_dir == "functionalext/symver") {
if (target_name == "dlsym" || target_name == "dlvsym" ||
target_name == "dynlink" || target_name == "dynlink_default") {
ldflags += [ "-Wl,-rpath=src/functional" ]
libs += [
"//${root_out_dir}/${test_lib_dir}/libdso_easy_symver.so",
"//${root_out_dir}/${test_lib_dir}/libdso_hard_symver.so",
"//${root_out_dir}/${test_lib_dir}/libdso_no_symver.so",
"//${root_out_dir}/${test_lib_dir}/libdso_symver.so",
]
}
}
if (target_dir == "musl") {
cflags_c += [ "-w" ]
......@@ -243,6 +256,11 @@ template("test_sharedlib") {
"-nostdlib",
]
if (defined(invoker.version_script)) {
_version_script = rebase_path(invoker.version_script, root_build_dir)
ldflags += [ "-Wl,--version-script=${_version_script}" ]
}
libs = [ "//${out_test_dir}/src/common/libtest.a" ]
output_name = "${target_name}"
......
......@@ -7,6 +7,7 @@ if (musl_arch == "arm") {
"src/fenv/arm/fenv.c",
"src/ldso/arm/dlsym.s",
"src/ldso/arm/dlsym_time64.S",
"src/ldso/arm/dlvsym.s",
"src/ldso/arm/find_exidx.c",
"src/ldso/arm/tlsdesc.S",
"src/math/arm/fabs.c",
......@@ -99,6 +100,7 @@ if (musl_arch == "arm") {
musl_src_arch_file = [
"src/fenv/aarch64/fenv.s",
"src/ldso/aarch64/dlsym.s",
"src/ldso/aarch64/dlvsym.s",
"src/ldso/aarch64/tlsdesc.s",
"src/math/aarch64/ceil.c",
"src/math/aarch64/ceilf.c",
......@@ -2085,6 +2087,10 @@ musl_src_porting_file = [
"src/time/strptime.c",
"src/time/time_impl.h",
"src/thread/pthread_getname_np.c",
"src/ldso/aarch64/dlvsym.s",
"src/ldso/arm/dlvsym.s",
"src/ldso/riscv64/dlvsym.s",
"src/ldso/x86_64/dlvsym.s",
]
musl_inc_hook_files = [
......
......@@ -29,6 +29,7 @@ int dlclose(void *);
char *dlerror(void);
void *dlopen(const char *, int);
void *dlsym(void *__restrict, const char *__restrict);
void *dlvsym(void *__restrict, const char *__restrict, const char *__restrict);
/* namespace apis */
#define NS_NAME_MAX 255
......
......@@ -81,6 +81,12 @@ struct td_index {
struct td_index *next;
};
struct verinfo {
const char *s;
const char *v;
Verneed *verneed;
};
struct dso {
#if DL_FDPIC
struct fdpic_loadmap *loadmap;
......@@ -102,6 +108,8 @@ struct dso {
Elf_Symndx *hashtab;
uint32_t *ghashtab;
int16_t *versym;
Verdef *verdef;
Verneed *verneed;
char *strings;
struct dso *syms_next, *lazy_next;
size_t *lazy, lazy_cnt;
......@@ -453,6 +461,95 @@ 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)
{
int matched = 0;
Verneed *verneed = verinfo->verneed;
vsym &= 0x7fff;
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;
}
vernaux = (Vernaux *)((char *)vernaux + vernaux->vna_next);
}
if (verneed->vn_next == 0) {
break;
}
verneed = (Verneed *)((char *)verneed + verneed->vn_next);
}
return matched;
}
static int check_verinfo(Verdef *def, int16_t *versym, uint32_t index, struct verinfo *verinfo, char *strings)
{
/* if the versym and verinfo is null , then not need version. */
if (!versym) {
if (strlen(verinfo->v) == 0) {
return 1;
} else {
return 0;
}
}
int 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);
}
/* if the version length is zero and vsym not less than zero, then library hava default version symbol. */
if (strlen(verinfo->v) == 0) {
if (vsym >= 0) {
return 1;
} else {
return 0;
}
}
/* find the version of symbol. */
vsym &= 0x7fff;
for (;;) {
if (!(def->vd_flags & VER_FLG_BASE) && (def->vd_ndx & 0x7fff) == vsym) {
break;
}
if (def->vd_next == 0) {
return 0;
}
def = (Verdef *)((char *)def + def->vd_next);
}
Verdaux *aux = (Verdaux *)((char *)def + def->vd_aux);
return !strcmp(verinfo->v, strings + aux->vda_name);
}
static uint32_t sysv_hash(const char *s0)
{
const unsigned char *s = (void *)s0;
......@@ -473,21 +570,27 @@ static uint32_t gnu_hash(const char *s0)
return h;
}
static Sym *sysv_lookup(const char *s, uint32_t h, struct dso *dso)
static Sym *sysv_lookup(struct verinfo *verinfo, uint32_t h, struct dso *dso)
{
size_t i;
Sym *syms = dso->syms;
Elf_Symndx *hashtab = dso->hashtab;
char *strings = dso->strings;
for (i=hashtab[2+h%hashtab[0]]; i; i=hashtab[2+hashtab[0]+i]) {
if ((!dso->versym || dso->versym[i] >= 0)
&& (!strcmp(s, strings+syms[i].st_name)))
if ((!dso->versym || (dso->versym[i] & 0x7fff) >= 0)
&& (!strcmp(verinfo->s, strings+syms[i].st_name))) {
if (!check_verinfo(dso->verdef, dso->versym, i, verinfo, dso->strings)) {
continue;
}
return syms+i;
}
}
return 0;
}
static Sym *gnu_lookup(uint32_t h1, uint32_t *hashtab, struct dso *dso, const char *s)
static Sym *gnu_lookup(uint32_t h1, uint32_t *hashtab, struct dso *dso, struct verinfo *verinfo)
{
uint32_t nbuckets = hashtab[0];
uint32_t *buckets = hashtab + 4 + hashtab[2]*(sizeof(size_t)/4);
......@@ -499,17 +602,24 @@ static Sym *gnu_lookup(uint32_t h1, uint32_t *hashtab, struct dso *dso, const ch
for (h1 |= 1; ; i++) {
uint32_t h2 = *hashval++;
if ((h1 == (h2|1)) && (!dso->versym || dso->versym[i] >= 0)
&& !strcmp(s, dso->strings + dso->syms[i].st_name))
if ((h1 == (h2|1)) && (!dso->versym || (dso->versym[i] & 0x7fff) >= 0)
&& !strcmp(verinfo->s, dso->strings + dso->syms[i].st_name)) {
if (!check_verinfo(dso->verdef, dso->versym, i, verinfo, dso->strings)) {
continue;
}
return dso->syms+i;
}
if (h2 & 1) break;
}
return 0;
}
static Sym *gnu_lookup_filtered(uint32_t h1, uint32_t *hashtab, struct dso *dso, const char *s, uint32_t fofs, size_t fmask)
static Sym *gnu_lookup_filtered(uint32_t h1, uint32_t *hashtab, struct dso *dso, struct verinfo *verinfo, uint32_t fofs, size_t fmask)
{
const size_t *bloomwords = (const void *)(hashtab+4);
size_t f = bloomwords[fofs & (hashtab[2]-1)];
if (!(f & fmask)) return 0;
......@@ -517,7 +627,7 @@ static Sym *gnu_lookup_filtered(uint32_t h1, uint32_t *hashtab, struct dso *dso,
f >>= (h1 >> hashtab[3]) % (8 * sizeof f);
if (!(f & 1)) return 0;
return gnu_lookup(h1, hashtab, dso, s);
return gnu_lookup(h1, hashtab, dso, verinfo);
}
#define OK_TYPES (1<<STT_NOTYPE | 1<<STT_OBJECT | 1<<STT_FUNC | 1<<STT_COMMON | 1<<STT_TLS)
......@@ -530,19 +640,19 @@ static Sym *gnu_lookup_filtered(uint32_t h1, uint32_t *hashtab, struct dso *dso,
#if defined(__GNUC__)
__attribute__((always_inline))
#endif
static inline struct symdef find_sym2(struct dso *dso, const char *s, int need_def, int use_deps)
static inline struct symdef find_sym2(struct dso *dso, struct verinfo *verinfo, int need_def, int use_deps)
{
uint32_t h = 0, gh = gnu_hash(s), gho = gh / (8*sizeof(size_t)), *ght;
uint32_t h = 0, gh = gnu_hash(verinfo->s), gho = gh / (8*sizeof(size_t)), *ght;
size_t ghm = 1ul << gh % (8*sizeof(size_t));
struct symdef def = {0};
struct dso **deps = use_deps ? dso->deps : 0;
for (; dso; dso=use_deps ? *deps++ : dso->syms_next) {
Sym *sym;
if ((ght = dso->ghashtab)) {
sym = gnu_lookup_filtered(gh, ght, dso, s, gho, ghm);
sym = gnu_lookup_filtered(gh, ght, dso, verinfo, gho, ghm);
} else {
if (!h) h = sysv_hash(s);
sym = sysv_lookup(s, h, dso);
if (!h) h = sysv_hash(verinfo->s);
sym = sysv_lookup(verinfo, h, dso);
}
if (!sym) continue;
if (!sym->st_shndx)
......@@ -563,7 +673,8 @@ static inline struct symdef find_sym2(struct dso *dso, const char *s, int need_d
static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
{
return find_sym2(dso, s, need_def, 0);
struct verinfo verinfo = { .s = s, .v = "", .verneed = dso->verneed };
return find_sym2(dso, &verinfo, need_def, 0);
}
static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride)
......@@ -1163,6 +1274,10 @@ static void decode_dyn(struct dso *p)
p->ghashtab = laddr(p, *dyn);
if (search_vec(p->dynv, dyn, DT_VERSYM))
p->versym = laddr(p, *dyn);
if (search_vec(p->dynv, dyn, DT_VERDEF))
p->verdef = laddr(p, *dyn);
if (search_vec(p->dynv, dyn, DT_VERNEED))
p->verneed = laddr(p, *dyn);
}
static size_t count_syms(struct dso *p)
......@@ -2816,7 +2931,7 @@ static void *addr2dso(size_t a)
return 0;
}
static void *do_dlsym(struct dso *p, const char *s, void *ra)
static void *do_dlsym(struct dso *p, const char *s, const char *v, void *ra)
{
int use_deps = 0;
if (p == head || p == RTLD_DEFAULT) {
......@@ -2829,9 +2944,10 @@ static void *do_dlsym(struct dso *p, const char *s, void *ra)
return 0;
} else
use_deps = 1;
struct symdef def = find_sym2(p, s, 0, use_deps);
struct verinfo verinfo = { .s = s, .v = v, .verneed = NULL };
struct symdef def = find_sym2(p, &verinfo, 0, use_deps);
if (!def.sym) {
error("Symbol not found: %s", s);
error("Symbol not found: %s, version: %s", s, strlen(v) > 0 ? v : "null");
return 0;
}
if ((def.sym->st_info&0xf) == STT_TLS)
......@@ -3040,12 +3156,34 @@ hidden void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra
pthread_rwlock_unlock(&lock);
return 0;
}
res = do_dlsym(dso, s, ra);
res = do_dlsym(dso, s, "", ra);
} else {
res = do_dlsym(p, s, "", ra);
}
#else
res = do_dlsym(p, s, "", ra);
#endif
pthread_rwlock_unlock(&lock);
return res;
}
hidden void *__dlvsym(void *restrict p, const char *restrict s, const char *restrict v, void *restrict ra)
{
void *res;
pthread_rwlock_rdlock(&lock);
#ifdef HANDLE_RANDOMIZATION
if ((p != RTLD_DEFAULT) && (p != RTLD_NEXT)) {
struct dso *dso = find_dso_by_handle(p);
if (dso == NULL) {
pthread_rwlock_unlock(&lock);
return 0;
}
res = do_dlsym(dso, s, v, ra);
} else {
res = do_dlsym(p, s, ra);
res = do_dlsym(p, s, v, ra);
}
#else
res = do_dlsym(p, s, ra);
res = do_dlsym(p, s, v, ra);
#endif
pthread_rwlock_unlock(&lock);
return res;
......
......@@ -11,6 +11,10 @@
typedef Elf32_Ehdr Ehdr;
typedef Elf32_Phdr Phdr;
typedef Elf32_Sym Sym;
typedef Elf32_Verdaux Verdaux;
typedef Elf32_Verdef Verdef;
typedef Elf32_Vernaux Vernaux;
typedef Elf32_Verneed Verneed;
#define R_TYPE(x) ((x)&255)
#define R_SYM(x) ((x)>>8)
#define R_INFO ELF32_R_INFO
......@@ -18,6 +22,10 @@ typedef Elf32_Sym Sym;
typedef Elf64_Ehdr Ehdr;
typedef Elf64_Phdr Phdr;
typedef Elf64_Sym Sym;
typedef Elf64_Verdaux Verdaux;
typedef Elf64_Verdef Verdef;
typedef Elf64_Vernaux Vernaux;
typedef Elf64_Verneed Verneed;
#define R_TYPE(x) ((x)&0x7fffffff)
#define R_SYM(x) ((x)>>32)
#define R_INFO ELF64_R_INFO
......@@ -98,6 +106,7 @@ struct fdpic_dummy_loadmap {
typedef void (*stage2_func)(unsigned char *, size_t *);
hidden void *__dlsym(void *restrict, const char *restrict, void *restrict);
hidden void *__dlvsym(void *restrict, const char *restrict, const char *restrict, void *restrict);
hidden int __dlclose(void *p);
hidden void __dl_seterr(const char *, ...);
......
/*
* 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.
*/
.global dlvsym
.hidden __dlvsym
.type dlvsym,%function
dlvsym:
mov x3,x30
b __dlvsym
/*
* 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.
*/
.syntax unified
.text
.global dlvsym
.hidden __dlvsym
.type dlvsym,%function
dlvsym:
mov r3,lr
b __dlvsym
/*
* 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.
*/
.global dlvsym
.hidden __dlvsym
.type dlvsym, %function
dlvsym:
mv a3, ra
tail __dlvsym
/*
* 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.
*/
.text
.global dlvsym
.hidden __dlvsym
.type dlvsym,@function
dlvsym:
mov (%rsp),%rcx
jmp __dlvsym
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册