Merge "fix the mremap signature"
diff --git a/linker/linked_list.h b/linker/linked_list.h
index 8003dbf..eb3ecd4 100644
--- a/linker/linked_list.h
+++ b/linker/linked_list.h
@@ -127,6 +127,11 @@
         } else {
           p->next = next;
         }
+
+        if (tail_ == e) {
+          tail_ = p;
+        }
+
         Allocator::free(e);
         e = next;
       } else {
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 9f0b559..31ed1ec 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1523,6 +1523,8 @@
 
   // Read the ELF header and some of the segments.
   if (!task->read(realpath.c_str(), file_stat.st_size)) {
+    soinfo_free(si);
+    task->set_soinfo(nullptr);
     return false;
   }
 
diff --git a/linker/tests/linked_list_test.cpp b/linker/tests/linked_list_test.cpp
index 09ad687..12348d9 100644
--- a/linker/tests/linked_list_test.cpp
+++ b/linker/tests/linked_list_test.cpp
@@ -133,6 +133,23 @@
   ASSERT_TRUE(list.pop_front() == nullptr);
 }
 
+TEST(linked_list, remove_if_last_then_push_back) {
+  test_list_t list;
+
+  list.push_back("a");
+  list.push_back("b");
+  list.push_back("c");
+  list.push_back("d");
+
+  list.remove_if([](const char* c) {
+    return *c == 'c' || *c == 'd';
+  });
+
+  ASSERT_EQ("ab", test_list_to_string(list));
+  list.push_back("d");
+  ASSERT_EQ("abd", test_list_to_string(list));
+}
+
 TEST(linked_list, copy_to_array) {
   test_list_t list;
   const size_t max_size = 128;
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index baf7eb5..c7d4d46 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -169,6 +169,11 @@
   ASSERT_TRUE(handle_ == nullptr);
   ASSERT_EQ("dlopen failed: \"" + lib_realpath + "\" has bad ELF magic", dlerror());
 
+  // Check if dlsym works after unsuccessful dlopen().
+  // Supply non-exiting one to make linker visit every soinfo.
+  void* sym = dlsym(RTLD_DEFAULT, "this_symbol_does_not_exist___");
+  ASSERT_TRUE(sym == nullptr);
+
   close(extinfo.library_fd);
 }