blob: ec5ede4aefc5247a974b352d32200f1081eb22ce [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "crazy_linker_proc_maps.h"
#include <gtest/gtest.h>
#include <limits.h>
#include "crazy_linker_system_mock.h"
namespace crazy {
namespace {
const char kProcMaps0[] =
"4000b000-4000c000 r--p 00000000 00:00 0\n"
"4005c000-40081000 r-xp 00000000 b3:01 141 /system/bin/mksh\n"
"40082000-40083000 r--p 00025000 b3:01 141 /system/bin/mksh\n"
"40083000-40084000 rw-p 00026000 b3:01 141 /system/bin/mksh\n"
"40084000-40088000 rw-p 00000000 00:00 0\n"
"40088000-40090000 r--s 00000000 00:0b 1704 /dev/__properties__\n"
"400eb000-400ec000 r--p 00000000 00:00 0\n"
"40141000-40150000 r-xp 00000000 b3:01 126 /system/bin/linker\n"
"40150000-40151000 r--p 0000e000 b3:01 126 /system/bin/linker\n"
"40151000-40152000 rw-p 0000f000 b3:01 126 /system/bin/linker\n"
"40152000-40153000 rw-p 00000000 00:00 0\n"
"40231000-40277000 r-xp 00001000 b3:01 638 /system/lib/libc.so\n"
"40277000-40279000 r--p 00046000 b3:01 638 /system/lib/libc.so\n"
"40279000-4027b000 rw-p 00048000 b3:01 638 /system/lib/libc.so\n"
"4027b000-40289000 rw-p 00000000 00:00 0\n"
"41e6b000-41e72000 rw-p 00000000 00:00 0 [heap]\n"
"be91b000-be93c000 rw-p 00000000 00:00 0 [stack]\n"
"ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]\n";
class ScopedTestEnv {
public:
ScopedTestEnv() : sys_() {
sys_.AddRegularFile("/proc/self/maps", kProcMaps0, sizeof(kProcMaps0) - 1);
}
~ScopedTestEnv() {}
private:
SystemMock sys_;
};
} // namespace
TEST(ProcMaps, FindElfBinaryForAddress) {
ScopedTestEnv env;
char path[512];
uintptr_t load_address;
EXPECT_TRUE(FindElfBinaryForAddress(
reinterpret_cast<void*>(0x400694c2), &load_address, path, sizeof(path)));
EXPECT_EQ(0x4005c000, load_address);
EXPECT_STREQ("/system/bin/mksh", path);
}
TEST(ProcMaps, FindElfBinaryForAddressWithBadAddress) {
ScopedTestEnv env;
char path[512];
uintptr_t load_address;
EXPECT_FALSE(FindElfBinaryForAddress(
reinterpret_cast<void*>(0x50000000), &load_address, path, sizeof(path)));
}
TEST(ProcMaps, FindLoadAddressForFile) {
ScopedTestEnv env;
static const struct {
bool success;
uintptr_t address;
uintptr_t offset;
const char* name;
} kData[] = {{true, 0x4005c000, 0, "mksh"},
{true, 0x40141000, 0, "/system/bin/linker"},
{false, 0, 0, "[heap]"},
{false, 0, 0, "bin/mksh"},
{true, 0x4005c000, 0, "/system/bin/mksh"},
{true, 0x40231000, 0x1000000, "libc.so"}, };
for (auto const& data : kData) {
uintptr_t address, offset;
bool success = FindLoadAddressForFile(data.name, &address, &offset);
EXPECT_EQ(data.success, success) << "Checking " << data.name;
if (success) {
EXPECT_EQ(data.address, address) << "Checking " << data.name;
EXPECT_EQ(data.offset, offset) << "Checking " << data.name;
}
}
}
TEST(ProcMaps, Entries) {
ScopedTestEnv env;
// "4000b000-4000c000 r--p 00000000 00:00 0\n"
// "4005c000-40081000 r-xp 00000000 b3:01 141 /system/bin/mksh\n"
// "40082000-40083000 r--p 00025000 b3:01 141 /system/bin/mksh\n"
// "40083000-40084000 rw-p 00026000 b3:01 141 /system/bin/mksh\n"
// "40084000-40088000 rw-p 00000000 00:00 0\n"
// "40088000-40090000 r--s 00000000 00:0b 1704
// /dev/__properties__\n"
// "400eb000-400ec000 r--p 00000000 00:00 0\n"
// "40141000-40150000 r-xp 00000000 b3:01 126 /system/bin/linker\n"
// "40150000-40151000 r--p 0000e000 b3:01 126 /system/bin/linker\n"
// "40151000-40152000 rw-p 0000f000 b3:01 126 /system/bin/linker\n"
// "40152000-40153000 rw-p 00000000 00:00 0\n"
// "40231000-40277000 r-xp 00001000 b3:01 638
// /system/lib/libc.so\n"
// "40277000-40279000 r--p 00046000 b3:01 638
// /system/lib/libc.so\n"
// "40279000-4027b000 rw-p 00048000 b3:01 638
// /system/lib/libc.so\n"
// "4027b000-40289000 rw-p 00000000 00:00 0\n"
// "41e6b000-41e72000 rw-p 00000000 00:00 0 [heap]\n"
// "be91b000-be93c000 rw-p 00000000 00:00 0 [stack]\n"
// "ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]\n"
static const struct {
size_t vma_start;
size_t vma_end;
int prot_flags;
size_t load_offset;
const char* path;
} kData[] = {
{0x4000b000, 0x4000c000, PROT_READ, 0, NULL},
{0x4005c000, 0x40081000, PROT_READ | PROT_EXEC, 0, "/system/bin/mksh"},
{0x40082000, 0x40083000, PROT_READ,
0x25000 * PAGE_SIZE, "/system/bin/mksh"},
{0x40083000, 0x40084000, PROT_READ | PROT_WRITE,
0x26000 * PAGE_SIZE, "/system/bin/mksh"},
{0x40084000, 0x40088000, PROT_READ | PROT_WRITE, 0, NULL},
{0x40088000, 0x40090000, PROT_READ, 0, "/dev/__properties__"},
{0x400eb000, 0x400ec000, PROT_READ, 0, NULL},
{0x40141000, 0x40150000, PROT_READ | PROT_EXEC,
0, "/system/bin/linker"},
{0x40150000, 0x40151000, PROT_READ,
0xe000 * PAGE_SIZE, "/system/bin/linker"},
{0x40151000, 0x40152000, PROT_READ | PROT_WRITE,
0xf000 * PAGE_SIZE, "/system/bin/linker"},
{0x40152000, 0x40153000, PROT_READ | PROT_WRITE, 0, NULL},
{0x40231000, 0x40277000, PROT_READ | PROT_EXEC,
0x1000 * PAGE_SIZE, "/system/lib/libc.so"},
{0x40277000, 0x40279000, PROT_READ,
0x46000 * PAGE_SIZE, "/system/lib/libc.so"},
{0x40279000, 0x4027b000, PROT_READ | PROT_WRITE,
0x48000 * PAGE_SIZE, "/system/lib/libc.so"},
{0x4027b000, 0x40289000, PROT_READ | PROT_WRITE, 0, NULL},
{0x41e6b000, 0x41e72000, PROT_READ | PROT_WRITE, 0, "[heap]"},
{0xbe91b000, 0xbe93c000, PROT_READ | PROT_WRITE, 0, "[stack]"},
{0xffff0000, 0xffff1000, PROT_READ | PROT_EXEC, 0, "[vectors]"}, };
ProcMaps self_maps;
ProcMaps::Entry entry;
const Vector<ProcMaps::Entry>& entries = self_maps.entries();
size_t count = 0;
for (const auto& data : kData) {
std::string text = "Checking entry #";
text += std::to_string(++count);
text += " ";
text += std::to_string(data.vma_start);
text += "-";
text += std::to_string(data.vma_end);
EXPECT_LT(count - 1U, entries.GetCount()) << text;
const ProcMaps::Entry& entry = entries[count - 1];
EXPECT_EQ(data.vma_start, entry.vma_start) << text;
EXPECT_EQ(data.vma_end, entry.vma_end) << text;
EXPECT_EQ(data.prot_flags, entry.prot_flags) << text;
EXPECT_EQ(data.load_offset, entry.load_offset) << text;
if (!data.path) {
EXPECT_FALSE(entry.path) << text;
} else {
EXPECT_EQ(std::string(data.path), std::string(entry.path, entry.path_len))
<< text;
}
}
EXPECT_EQ(count, entries.GetCount());
}
} // namespace crazy