Merge "Simple tests for dladdr(3)."
This commit is contained in:
commit
8e630dacf6
1 changed files with 72 additions and 0 deletions
|
@ -17,6 +17,12 @@
|
|||
#include <gtest/gtest.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
static bool gCalled = false;
|
||||
extern "C" void DlSymTestFunction() {
|
||||
|
@ -36,3 +42,69 @@ TEST(dlopen, dlsym_in_self) {
|
|||
function();
|
||||
ASSERT_TRUE(gCalled);
|
||||
}
|
||||
|
||||
TEST(dlopen, dladdr) {
|
||||
void* self = dlopen(NULL, RTLD_NOW);
|
||||
ASSERT_TRUE(self != NULL);
|
||||
|
||||
void* sym = dlsym(self, "DlSymTestFunction");
|
||||
ASSERT_TRUE(sym != NULL);
|
||||
|
||||
// Deliberately ask dladdr for an address inside a symbol, rather than the symbol base address.
|
||||
void* addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(sym) + 2);
|
||||
|
||||
Dl_info info;
|
||||
int rc = dladdr(addr, &info);
|
||||
ASSERT_NE(rc, 0); // Zero on error, non-zero on success.
|
||||
|
||||
// Get the name of this executable.
|
||||
char executable_path[PATH_MAX];
|
||||
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);
|
||||
|
||||
// The symbol name should be the symbol we looked up.
|
||||
ASSERT_STREQ(info.dli_sname, "DlSymTestFunction");
|
||||
|
||||
// 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 path[PATH_MAX];
|
||||
snprintf(path, sizeof(path), "/proc/%d/maps", getpid());
|
||||
char line[BUFSIZ];
|
||||
FILE* fp = fopen(path, "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 (strcmp(executable_path, path) == 0) {
|
||||
base_address = reinterpret_cast<void*>(start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
// The base address should be the address we were loaded at.
|
||||
ASSERT_EQ(info.dli_fbase, base_address);
|
||||
}
|
||||
|
||||
TEST(dlopen, dladdr_invalid) {
|
||||
Dl_info info;
|
||||
|
||||
// No symbol corresponding to NULL.
|
||||
ASSERT_EQ(dladdr(NULL, &info), 0); // Zero on error, non-zero on success.
|
||||
|
||||
// No symbol corresponding to a stack address.
|
||||
ASSERT_EQ(dladdr(&info, &info), 0); // Zero on error, non-zero on success.
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue