Add RTLD_NODELETE flag support
Bug: https://code.google.com/p/android/issues/detail?id=64069
Change-Id: Ie5f90482feae86391172be4b32d6cb7d76f446fb
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 4f42c82..d86379e 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -976,6 +976,11 @@
}
static void soinfo_unload(soinfo* si) {
+ if (!si->can_unload()) {
+ TRACE("not unloading '%s' - the binary is flagged with NODELETE", si->name);
+ return;
+ }
+
if (si->ref_count == 1) {
TRACE("unloading '%s'", si->name);
si->CallDestructors();
@@ -1034,7 +1039,7 @@
}
soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo) {
- if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NOLOAD)) != 0) {
+ if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NODELETE|RTLD_NOLOAD)) != 0) {
DL_ERR("invalid flags to dlopen: %x", flags);
return nullptr;
}
@@ -1794,6 +1799,9 @@
return strtab + index;
}
+bool soinfo::can_unload() const {
+ return (rtld_flags & (RTLD_NODELETE | RTLD_GLOBAL)) == 0;
+}
/* Force any of the closed stdin, stdout and stderr to be associated with
/dev/null. */
static int nullify_closed_stdio() {
@@ -2062,9 +2070,13 @@
if ((d->d_un.d_val & DF_1_GLOBAL) != 0) {
rtld_flags |= RTLD_GLOBAL;
}
+
+ if ((d->d_un.d_val & DF_1_NODELETE) != 0) {
+ rtld_flags |= RTLD_NODELETE;
+ }
// TODO: Implement other flags
- if ((d->d_un.d_val & ~(DF_1_NOW | DF_1_GLOBAL)) != 0) {
+ if ((d->d_un.d_val & ~(DF_1_NOW | DF_1_GLOBAL | DF_1_NODELETE)) != 0) {
DL_WARN("Unsupported flags DT_FLAGS_1=%p", reinterpret_cast<void*>(d->d_un.d_val));
}
break;