Add realpath for soinfo
This change adds realpath to soinfo and
extends limit on filenames from 128 to PATH_MAX.
It also removes soinfo::name field, linker uses
dt_soname instead.
Bug: http://b/19818481
Bug: https://code.google.com/p/android/issues/detail?id=80336
Change-Id: I9cff4cb5bda3ee2bc74e1bbded9594ea7fbe2a08
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index a63c070..1d62428 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -26,9 +26,12 @@
#include <string>
+#include "utils.h"
+
#define ASSERT_SUBSTR(needle, haystack) \
ASSERT_PRED_FORMAT2(::testing::IsSubstring, needle, haystack)
+
static bool g_called = false;
extern "C" void DlSymTestFunction() {
g_called = true;
@@ -699,7 +702,7 @@
ASSERT_EQ(0, dlclose(self));
}
-TEST(dlfcn, dladdr) {
+TEST(dlfcn, dladdr_executable) {
dlerror(); // Clear any pending errors.
void* self = dlopen(NULL, RTLD_NOW);
ASSERT_TRUE(self != NULL);
@@ -720,13 +723,11 @@
rc = readlink("/proc/self/exe", executable_path, sizeof(executable_path));
ASSERT_NE(rc, -1);
executable_path[rc] = '\0';
- std::string executable_name(basename(executable_path));
// The filename should be that of this executable.
- // Note that we don't know whether or not we have the full path, so we want an "ends_with" test.
- std::string dli_fname(info.dli_fname);
- dli_fname = basename(&dli_fname[0]);
- ASSERT_EQ(dli_fname, executable_name);
+ char dli_realpath[PATH_MAX];
+ ASSERT_TRUE(realpath(info.dli_fname, dli_realpath) != nullptr);
+ ASSERT_STREQ(executable_path, dli_realpath);
// The symbol name should be the symbol we looked up.
ASSERT_STREQ(info.dli_sname, "DlSymTestFunction");
@@ -734,22 +735,16 @@
// The address should be the exact address of the symbol.
ASSERT_EQ(info.dli_saddr, sym);
- // Look in /proc/pid/maps to find out what address we were loaded at.
- // TODO: factor /proc/pid/maps parsing out into a class and reuse all over bionic.
- void* base_address = NULL;
- char line[BUFSIZ];
- FILE* fp = fopen("/proc/self/maps", "r");
- ASSERT_TRUE(fp != NULL);
- while (fgets(line, sizeof(line), fp) != NULL) {
- uintptr_t start = strtoul(line, 0, 16);
- line[strlen(line) - 1] = '\0'; // Chomp the '\n'.
- char* path = strchr(line, '/');
- if (path != NULL && strcmp(executable_path, path) == 0) {
- base_address = reinterpret_cast<void*>(start);
+ std::vector<map_record> maps;
+ ASSERT_TRUE(Maps::parse_maps(&maps));
+
+ void* base_address = nullptr;
+ for (const map_record& rec : maps) {
+ if (executable_path == rec.pathname) {
+ base_address = reinterpret_cast<void*>(rec.addr_start);
break;
}
}
- fclose(fp);
// The base address should be the address we were loaded at.
ASSERT_EQ(info.dli_fbase, base_address);
@@ -757,6 +752,28 @@
ASSERT_EQ(0, dlclose(self));
}
+#if defined(__LP64__)
+#define BIONIC_PATH_TO_LIBC "/system/lib64/libc.so"
+#else
+#define BIONIC_PATH_TO_LIBC "/system/lib/libc.so"
+#endif
+
+TEST(dlfcn, dladdr_libc) {
+#if defined(__BIONIC__)
+ Dl_info info;
+ void* addr = reinterpret_cast<void*>(puts); // well-known libc function
+ ASSERT_TRUE(dladdr(addr, &info) != 0);
+
+ ASSERT_STREQ(BIONIC_PATH_TO_LIBC, info.dli_fname);
+ // TODO: add check for dfi_fbase
+ ASSERT_STREQ("puts", info.dli_sname);
+ ASSERT_EQ(addr, info.dli_saddr);
+#else
+ GTEST_LOG_(INFO) << "This test does nothing for glibc. Glibc returns path from ldconfig "
+ "for libc.so, which is symlink itself (not a realpath).\n";
+#endif
+}
+
TEST(dlfcn, dladdr_invalid) {
Dl_info info;