Remove dangling links in secondary namespaces
linker didn't remove link to the soinfo from shared
namespaces on soinfo_unload, because it didn't keep
record of all namespaces the library is added to.
This change adds test for this and also fixes the
problem by introducing list of secondary namespaces
to soinfo, which is used to remove soinfo in
soinfo::remove_all_links().
Bug: http://b/28115950
Change-Id: Ifbf6e54f92fa6e88f86b6a8dd6dc22d4553afd22
(cherry picked from commit aca299ac4721809d6fc61e25c505bb59acd23fbc)
diff --git a/linker/linker.h b/linker/linker.h
index a27374c..a776525 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -114,6 +114,16 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(SoinfoListAllocator);
};
+class NamespaceListAllocator {
+ public:
+ static LinkedListEntry<android_namespace_t>* alloc();
+ static void free(LinkedListEntry<android_namespace_t>* entry);
+
+ private:
+ // unconstructable
+ DISALLOW_IMPLICIT_CONSTRUCTORS(NamespaceListAllocator);
+};
+
class SymbolName {
public:
explicit SymbolName(const char* name)
@@ -166,6 +176,7 @@
struct soinfo {
public:
typedef LinkedList<soinfo, SoinfoListAllocator> soinfo_list_t;
+ typedef LinkedList<android_namespace_t, NamespaceListAllocator> android_namespace_list_t;
#if defined(__work_around_b_24465209__)
private:
char old_name_[SOINFO_NAME_LEN];
@@ -340,7 +351,8 @@
void set_dt_runpath(const char *);
const std::vector<std::string>& get_dt_runpath() const;
- android_namespace_t* get_namespace();
+ android_namespace_t* get_primary_namespace();
+ void add_secondary_namespace(android_namespace_t* secondary_ns);
void set_mapped_by_caller(bool reserved_map);
bool is_mapped_by_caller() const;
@@ -412,7 +424,8 @@
// version >= 3
std::vector<std::string> dt_runpath_;
- android_namespace_t* namespace_;
+ android_namespace_t* primary_namespace_;
+ android_namespace_list_t secondary_namespaces_;
uintptr_t handle_;
friend soinfo* get_libdl_info();