Home | History | Annotate | Download | only in libdebugtest
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <jni.h>
     18 #include <gtest/gtest.h>
     19 #include <android/log.h>
     20 
     21 #include <errno.h>
     22 #include <sys/ptrace.h>
     23 #include <sys/types.h>
     24 #include <sys/uio.h>
     25 #include <sys/wait.h>
     26 #include <unistd.h>
     27 
     28 #include <functional>
     29 #include <vector>
     30 
     31 #define LOG_TAG "Cts-DebugTest"
     32 
     33 // Used by child processes only
     34 #define assert_or_exit(x)                                                                         \
     35     do {                                                                                          \
     36         if(x) break;                                                                              \
     37         __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "Assertion " #x " failed. errno(%d): %s", \
     38                 errno, strerror(errno));                                                          \
     39         _exit(1);                                                                                 \
     40     } while (0)
     41 
     42 static void parent(pid_t child) {
     43     int status;
     44     int wpid = waitpid(child, &status, 0);
     45     ASSERT_EQ(child, wpid);
     46     ASSERT_TRUE(WIFEXITED(status));
     47     ASSERT_EQ(0, WEXITSTATUS(status));
     48 }
     49 
     50 static void run_test(const std::function<void(pid_t)> &test) {
     51     pid_t pid = fork();
     52     ASSERT_NE(-1, pid) << "fork() failed with " << strerror(errno);
     53     if (pid != 0) {
     54         parent(pid);
     55     } else {
     56         // child
     57         test(getppid());
     58         _exit(0);
     59     }
     60 }
     61 
     62 static void ptraceAttach(pid_t parent) {
     63     assert_or_exit(ptrace(PTRACE_ATTACH, parent, nullptr, nullptr) == 0);
     64     int status;
     65     assert_or_exit(waitpid(parent, &status, __WALL) == parent);
     66     assert_or_exit(WIFSTOPPED(status));
     67     assert_or_exit(WSTOPSIG(status) == SIGSTOP);
     68 
     69     assert_or_exit(ptrace(PTRACE_DETACH, parent, nullptr, nullptr) == 0);
     70 }
     71 
     72 TEST(DebugTest, ptraceAttach) {
     73     run_test(ptraceAttach);
     74 }
     75 
     76 static void processVmReadv(pid_t parent, const std::vector<long *> &addresses) {
     77     long destination;
     78     iovec local = { &destination, sizeof destination };
     79 
     80     for (long *address : addresses) {
     81         // Since we are forked, the address will be valid in the remote process as well.
     82         iovec remote = { address, sizeof *address };
     83         __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "%s About to read %p\n", __func__,
     84                             address);
     85         assert_or_exit(process_vm_readv(parent, &local, 1, &remote, 1, 0) == sizeof destination);
     86 
     87         // Compare the data with the contents of our memory.
     88         assert_or_exit(destination == *address);
     89     }
     90 }
     91 
     92 static long global_variable = 0x47474747;
     93 // public static native boolean processVmReadv();
     94 TEST(DebugTest, processVmReadv) {
     95     long stack_variable = 0x42424242;
     96     // This runs the test with a selection of different kinds of addresses and
     97     // makes sure the child process (simulating a debugger) can read them.
     98     run_test([&](pid_t parent) {
     99         processVmReadv(parent, std::vector<long *>{
    100                                    &global_variable, &stack_variable,
    101                                    reinterpret_cast<long *>(&processVmReadv)});
    102     });
    103 }
    104 
    105 // public static native boolean processVmReadvNullptr();
    106 TEST(DebugTest, processVmReadvNullptr) {
    107     // Make sure reading unallocated memory behaves reasonably.
    108     run_test([](pid_t parent) {
    109         long destination;
    110         iovec local = {&destination, sizeof destination};
    111         iovec remote = {nullptr, sizeof(long)};
    112 
    113         assert_or_exit(process_vm_readv(parent, &local, 1, &remote, 1, 0) == -1);
    114         assert_or_exit(errno == EFAULT);
    115     });
    116 }
    117