Home | History | Annotate | Download | only in src
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "crazy_linker_proc_maps.h"
      6 
      7 #include <limits.h>
      8 #include <minitest/minitest.h>
      9 #include "crazy_linker_system_mock.h"
     10 
     11 namespace crazy {
     12 
     13 namespace {
     14 
     15 const char kProcMaps0[] =
     16     "4000b000-4000c000 r--p 00000000 00:00 0\n"
     17     "4005c000-40081000 r-xp 00000000 b3:01 141        /system/bin/mksh\n"
     18     "40082000-40083000 r--p 00025000 b3:01 141        /system/bin/mksh\n"
     19     "40083000-40084000 rw-p 00026000 b3:01 141        /system/bin/mksh\n"
     20     "40084000-40088000 rw-p 00000000 00:00 0\n"
     21     "40088000-40090000 r--s 00000000 00:0b 1704       /dev/__properties__\n"
     22     "400eb000-400ec000 r--p 00000000 00:00 0\n"
     23     "40141000-40150000 r-xp 00000000 b3:01 126        /system/bin/linker\n"
     24     "40150000-40151000 r--p 0000e000 b3:01 126        /system/bin/linker\n"
     25     "40151000-40152000 rw-p 0000f000 b3:01 126        /system/bin/linker\n"
     26     "40152000-40153000 rw-p 00000000 00:00 0\n"
     27     "40231000-40277000 r-xp 00001000 b3:01 638        /system/lib/libc.so\n"
     28     "40277000-40279000 r--p 00046000 b3:01 638        /system/lib/libc.so\n"
     29     "40279000-4027b000 rw-p 00048000 b3:01 638        /system/lib/libc.so\n"
     30     "4027b000-40289000 rw-p 00000000 00:00 0\n"
     31     "41e6b000-41e72000 rw-p 00000000 00:00 0          [heap]\n"
     32     "be91b000-be93c000 rw-p 00000000 00:00 0          [stack]\n"
     33     "ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]\n";
     34 
     35 class ScopedTestEnv {
     36  public:
     37   ScopedTestEnv() : sys_() {
     38     sys_.AddRegularFile("/proc/self/maps", kProcMaps0, sizeof(kProcMaps0) - 1);
     39   }
     40 
     41   ~ScopedTestEnv() {}
     42 
     43  private:
     44   SystemMock sys_;
     45 };
     46 
     47 }  // namespace
     48 
     49 TEST(ProcMaps, FindElfBinaryForAddress) {
     50   ScopedTestEnv env;
     51   char path[512];
     52   uintptr_t load_address;
     53 
     54   EXPECT_TRUE(FindElfBinaryForAddress(
     55       reinterpret_cast<void*>(0x400694c2), &load_address, path, sizeof(path)));
     56   EXPECT_EQ(0x4005c000, load_address);
     57   EXPECT_STREQ("/system/bin/mksh", path);
     58 }
     59 
     60 TEST(ProcMaps, FindElfBinaryForAddressWithBadAddress) {
     61   ScopedTestEnv env;
     62   char path[512];
     63   uintptr_t load_address;
     64 
     65   EXPECT_FALSE(FindElfBinaryForAddress(
     66       reinterpret_cast<void*>(0x50000000), &load_address, path, sizeof(path)));
     67 }
     68 
     69 TEST(ProcMaps, FindProtectionFlagsForAddress) {
     70   ScopedTestEnv env;
     71   static const struct {
     72     uintptr_t address;
     73     bool success;
     74     int prot;
     75   } kData[] = {{0x4000afff, false, 0},
     76                {0x4000b000, true, PROT_READ},
     77                {0x4000bfff, true, PROT_READ},
     78                {0x4000c000, false, 0},
     79                {0x4005bfff, false, 0},
     80                {0x4005c000, true, PROT_READ | PROT_EXEC},
     81                {0x40067832, true, PROT_READ | PROT_EXEC},
     82                {0x40082000, true, PROT_READ},
     83                {0x40083000, true, PROT_READ | PROT_WRITE},
     84                {0x40084000, true, PROT_READ | PROT_WRITE}, };
     85 
     86   int prot;
     87   for (size_t n = 0; n < ARRAY_LEN(kData); ++n) {
     88     void* address = reinterpret_cast<void*>(kData[n].address);
     89     TEST_TEXT << minitest::Format("Checking address %p", address);
     90     EXPECT_EQ(kData[n].success, FindProtectionFlagsForAddress(address, &prot));
     91     if (kData[n].success) {
     92       TEST_TEXT << minitest::Format("Checking address %p", address);
     93       EXPECT_EQ(kData[n].prot, prot);
     94     }
     95   }
     96 }
     97 
     98 TEST(ProcMaps, FindLoadAddressForFile) {
     99   ScopedTestEnv env;
    100   static const struct {
    101     bool success;
    102     uintptr_t address;
    103     uintptr_t offset;
    104     const char* name;
    105   } kData[] = {{true, 0x4005c000, 0, "mksh"},
    106                {true, 0x40141000, 0, "/system/bin/linker"},
    107                {false, 0, 0, "[heap]"},
    108                {false, 0, 0, "bin/mksh"},
    109                {true, 0x4005c000, 0, "/system/bin/mksh"},
    110                {true, 0x40231000, 0x1000000, "libc.so"}, };
    111   for (size_t n = 0; n < ARRAY_LEN(kData); ++n) {
    112     uintptr_t address, offset;
    113     TEST_TEXT << "Checking " << kData[n].name;
    114     bool success = FindLoadAddressForFile(kData[n].name, &address, &offset);
    115     EXPECT_EQ(kData[n].success, success);
    116     if (success) {
    117       TEST_TEXT << "Checking " << kData[n].name;
    118       EXPECT_EQ(kData[n].address, address);
    119 
    120       TEST_TEXT << "Checking " << kData[n].name;
    121       EXPECT_EQ(kData[n].offset, offset);
    122     }
    123   }
    124 }
    125 
    126 TEST(ProcMaps, GetNextEntry) {
    127   ScopedTestEnv env;
    128   //     "4000b000-4000c000 r--p 00000000 00:00 0\n"
    129   //     "4005c000-40081000 r-xp 00000000 b3:01 141        /system/bin/mksh\n"
    130   //     "40082000-40083000 r--p 00025000 b3:01 141        /system/bin/mksh\n"
    131   //     "40083000-40084000 rw-p 00026000 b3:01 141        /system/bin/mksh\n"
    132   //     "40084000-40088000 rw-p 00000000 00:00 0\n"
    133   //     "40088000-40090000 r--s 00000000 00:0b 1704
    134   // /dev/__properties__\n"
    135   //     "400eb000-400ec000 r--p 00000000 00:00 0\n"
    136   //     "40141000-40150000 r-xp 00000000 b3:01 126        /system/bin/linker\n"
    137   //     "40150000-40151000 r--p 0000e000 b3:01 126        /system/bin/linker\n"
    138   //     "40151000-40152000 rw-p 0000f000 b3:01 126        /system/bin/linker\n"
    139   //     "40152000-40153000 rw-p 00000000 00:00 0\n"
    140   //     "40231000-40277000 r-xp 00001000 b3:01 638
    141   // /system/lib/libc.so\n"
    142   //     "40277000-40279000 r--p 00046000 b3:01 638
    143   // /system/lib/libc.so\n"
    144   //     "40279000-4027b000 rw-p 00048000 b3:01 638
    145   // /system/lib/libc.so\n"
    146   //     "4027b000-40289000 rw-p 00000000 00:00 0\n"
    147   //     "41e6b000-41e72000 rw-p 00000000 00:00 0          [heap]\n"
    148   //     "be91b000-be93c000 rw-p 00000000 00:00 0          [stack]\n"
    149   //     "ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]\n"
    150   static const struct {
    151     size_t vma_start;
    152     size_t vma_end;
    153     int prot_flags;
    154     size_t load_offset;
    155     const char* path;
    156   } kData[] = {
    157         {0x4000b000, 0x4000c000, PROT_READ, 0, NULL},
    158         {0x4005c000, 0x40081000, PROT_READ | PROT_EXEC, 0, "/system/bin/mksh"},
    159         {0x40082000,          0x40083000,        PROT_READ,
    160          0x25000 * PAGE_SIZE, "/system/bin/mksh"},
    161         {0x40083000,          0x40084000,        PROT_READ | PROT_WRITE,
    162          0x26000 * PAGE_SIZE, "/system/bin/mksh"},
    163         {0x40084000, 0x40088000, PROT_READ | PROT_WRITE, 0, NULL},
    164         {0x40088000, 0x40090000, PROT_READ, 0, "/dev/__properties__"},
    165         {0x400eb000, 0x400ec000, PROT_READ, 0, NULL},
    166         {0x40141000, 0x40150000,          PROT_READ | PROT_EXEC,
    167          0,          "/system/bin/linker"},
    168         {0x40150000,         0x40151000,          PROT_READ,
    169          0xe000 * PAGE_SIZE, "/system/bin/linker"},
    170         {0x40151000,         0x40152000,          PROT_READ | PROT_WRITE,
    171          0xf000 * PAGE_SIZE, "/system/bin/linker"},
    172         {0x40152000, 0x40153000, PROT_READ | PROT_WRITE, 0, NULL},
    173         {0x40231000,         0x40277000,           PROT_READ | PROT_EXEC,
    174          0x1000 * PAGE_SIZE, "/system/lib/libc.so"},
    175         {0x40277000,          0x40279000,           PROT_READ,
    176          0x46000 * PAGE_SIZE, "/system/lib/libc.so"},
    177         {0x40279000,          0x4027b000,           PROT_READ | PROT_WRITE,
    178          0x48000 * PAGE_SIZE, "/system/lib/libc.so"},
    179         {0x4027b000, 0x40289000, PROT_READ | PROT_WRITE, 0, NULL},
    180         {0x41e6b000, 0x41e72000, PROT_READ | PROT_WRITE, 0, "[heap]"},
    181         {0xbe91b000, 0xbe93c000, PROT_READ | PROT_WRITE, 0, "[stack]"},
    182         {0xffff0000, 0xffff1000, PROT_READ | PROT_EXEC, 0, "[vectors]"}, };
    183 
    184   ProcMaps self_maps;
    185   ProcMaps::Entry entry;
    186 
    187   for (size_t n = 0; n < ARRAY_LEN(kData); ++n) {
    188     minitest::internal::String text =
    189         minitest::Format("Checking entry #%d %p-%p",
    190                          n + 1,
    191                          kData[n].vma_start,
    192                          kData[n].vma_end);
    193     TEST_TEXT << text;
    194     EXPECT_TRUE(self_maps.GetNextEntry(&entry));
    195     TEST_TEXT << text;
    196     EXPECT_EQ(kData[n].vma_start, entry.vma_start);
    197     TEST_TEXT << text;
    198     EXPECT_EQ(kData[n].vma_end, entry.vma_end);
    199     TEST_TEXT << text;
    200     EXPECT_EQ(kData[n].prot_flags, entry.prot_flags);
    201     TEST_TEXT << text;
    202     EXPECT_EQ(kData[n].load_offset, entry.load_offset);
    203 
    204     if (!kData[n].path) {
    205       TEST_TEXT << text;
    206       EXPECT_FALSE(entry.path);
    207     } else {
    208       EXPECT_MEMEQ(
    209           kData[n].path, strlen(kData[n].path), entry.path, entry.path_len);
    210     }
    211   }
    212   EXPECT_FALSE(self_maps.GetNextEntry(&entry));
    213 }
    214 
    215 }  // namespace crazy
    216