1. 在 Android4.1 中,执行到 hardware.c 中的 load 方法时
static int load(const char *id,
const char *path,
const struct hw_module_t **pHmi)
{
int status;
void *handle;
struct hw_module_t *hmi;
/*
* load the symbols resolving undefined symbols before
* dlopen returns. Since RTLD_GLOBAL is not or'd in with
* RTLD_NOW the external symbols will not be global
*/
handle = dlopen(path, RTLD_NOW);
if (handle == NULL) {
char const *err_str = dlerror();
ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
status = -EINVAL;
goto done;
}
/* Get the address of the struct hal_module_info. */
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
hmi = (struct hw_module_t *)dlsym(handle, sym);
if (hmi == NULL) {
ALOGE("load: couldn't find symbol %s", sym);
status = -EINVAL;
goto done;
}
/* Check that the id matches */
if (strcmp(id, hmi->id) != 0) {
ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);
status = -EINVAL;
goto done;
}
hmi->dso = handle;
/* success */
status = 0;
done:
if (status != 0) {
hmi = NULL;
if (handle != NULL) {
dlclose(handle);
handle = NULL;
}
} else {
ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
id, path, *pHmi, handle);
}
*pHmi = hmi;
return status;
}
其中有这样一句话 hmi->dso = handle;// 这句话导致 了 crash
Android4.1 中修改了 bionic/linker 中的内容,添加了对 RELRO的支持。他将 const 变量 的内存地址映射为只读的,如果通过const变量的指针对const变量进行修改,那么就会出现段错误。
hmi 表示 的是 具体HAL模块中定义的 模块变量 HAL_MODULE_INFO_SYM,以 power 模块为例子
struct power_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = POWER_MODULE_API_VERSION_0_2,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = POWER_HARDWARE_MODULE_ID,
.name = "Default Power HAL",
.author = "The Android Open Source Project",
.methods = &power_module_methods,
},
.init = power_init,
.setInteractive = power_set_interactive,
.powerHint = power_hint,
};
那么 如果 HAL_MODULE_INFO_SYM 定义为 const,
const struct power_module HAL_MODULE_INFO_SYM = {
....
}
那么libhardware 在调用 power 模块的动态链接库的时候就会出现 段错误,解决的方案就是 将 HAL_MODULE_INFO_SYM 声明为 非 const 类型的。
2.出现这个问题的原因在于 Android4.1 在 bionic/linker 中添加了对 relro 的支持,在bionic/linker 中查看 log
commit 9ec0f03a0d0b17bbb94ac0b9fef6add28a133c3a
Author: Nick Kralevich <nnk@google.com>
Date: Tue Feb 28 10:40:00 2012 -0800
Add relro support
Add support for PT_GNU_RELRO. This allows the static linker to
indicate that certain regions of memory should be marked as
"read-only" after dynamic linking is complete.
See:
* http://www.akkadia.org/drepper/nonselsec.pdf (section 6)
* http://tk-blog.blogspot.com/2009/02/relro-not-so-well-known-memory.html
Note that this change has no effect on Android right now, because
we don't compile our code with relro enabled.
Change-Id: I6541f8775367e8558b4388f7d105b1ae6e8f046b
static int load(const char *id,
const char *path,
const struct hw_module_t **pHmi)
{
int status;
void *handle;
struct hw_module_t *hmi;
/*
* load the symbols resolving undefined symbols before
* dlopen returns. Since RTLD_GLOBAL is not or'd in with
* RTLD_NOW the external symbols will not be global
*/
handle = dlopen(path, RTLD_NOW);
if (handle == NULL) {
char const *err_str = dlerror();
ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
status = -EINVAL;
goto done;
}
/* Get the address of the struct hal_module_info. */
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
hmi = (struct hw_module_t *)dlsym(handle, sym);
if (hmi == NULL) {
ALOGE("load: couldn't find symbol %s", sym);
status = -EINVAL;
goto done;
}
/* Check that the id matches */
if (strcmp(id, hmi->id) != 0) {
ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);
status = -EINVAL;
goto done;
}
hmi->dso = handle;
/* success */
status = 0;
done:
if (status != 0) {
hmi = NULL;
if (handle != NULL) {
dlclose(handle);
handle = NULL;
}
} else {
ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
id, path, *pHmi, handle);
}
*pHmi = hmi;
return status;
}
其中有这样一句话 hmi->dso = handle;// 这句话导致 了 crash
Android4.1 中修改了 bionic/linker 中的内容,添加了对 RELRO的支持。他将 const 变量 的内存地址映射为只读的,如果通过const变量的指针对const变量进行修改,那么就会出现段错误。
hmi 表示 的是 具体HAL模块中定义的 模块变量 HAL_MODULE_INFO_SYM,以 power 模块为例子
struct power_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = POWER_MODULE_API_VERSION_0_2,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = POWER_HARDWARE_MODULE_ID,
.name = "Default Power HAL",
.author = "The Android Open Source Project",
.methods = &power_module_methods,
},
.init = power_init,
.setInteractive = power_set_interactive,
.powerHint = power_hint,
};
那么 如果 HAL_MODULE_INFO_SYM 定义为 const,
const struct power_module HAL_MODULE_INFO_SYM = {
....
}
那么libhardware 在调用 power 模块的动态链接库的时候就会出现 段错误,解决的方案就是 将 HAL_MODULE_INFO_SYM 声明为 非 const 类型的。
2.出现这个问题的原因在于 Android4.1 在 bionic/linker 中添加了对 relro 的支持,在bionic/linker 中查看 log
commit 9ec0f03a0d0b17bbb94ac0b9fef6add28a133c3a
Author: Nick Kralevich <nnk@google.com>
Date: Tue Feb 28 10:40:00 2012 -0800
Add relro support
Add support for PT_GNU_RELRO. This allows the static linker to
indicate that certain regions of memory should be marked as
"read-only" after dynamic linking is complete.
See:
* http://www.akkadia.org/drepper/nonselsec.pdf (section 6)
* http://tk-blog.blogspot.com/2009/02/relro-not-so-well-known-memory.html
Note that this change has no effect on Android right now, because
we don't compile our code with relro enabled.
Change-Id: I6541f8775367e8558b4388f7d105b1ae6e8f046b