// Copyright 2014 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "snapshot/mac/process_reader_mac.h"

#include <AvailabilityMacros.h>
#include <errno.h>
#include <OpenCL/opencl.h>
#include <mach-o/dyld.h>
#include <mach-o/dyld_images.h>
#include <mach/mach.h>
#include <string.h>
#include <sys/stat.h>

#include <map>
#include <utility>

#include "base/logging.h"
#include "base/mac/mach_logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "gtest/gtest.h"
#include "snapshot/mac/mach_o_image_reader.h"
#include "snapshot/mac/mach_o_image_segment_reader.h"
#include "test/errors.h"
#include "test/mac/dyld.h"
#include "test/mac/mach_errors.h"
#include "test/mac/mach_multiprocess.h"
#include "util/file/file_io.h"
#include "util/mac/mac_util.h"
#include "util/mach/mach_extensions.h"
#include "util/misc/from_pointer_cast.h"
#include "util/synchronization/semaphore.h"

namespace crashpad {
namespace test {
namespace {

constexpr char kDyldPath[] = "/usr/lib/dyld";

TEST(ProcessReaderMac, SelfBasic) {
  ProcessReaderMac process_reader;
  ASSERT_TRUE(process_reader.Initialize(mach_task_self()));

#if !defined(ARCH_CPU_64_BITS)
  EXPECT_FALSE(process_reader.Is64Bit());
#else
  EXPECT_TRUE(process_reader.Is64Bit());
#endif

  EXPECT_EQ(process_reader.ProcessID(), getpid());
  EXPECT_EQ(process_reader.ParentProcessID(), getppid());

  static constexpr char kTestMemory[] = "Some test memory";
  char buffer[base::size(kTestMemory)];
  ASSERT_TRUE(process_reader.Memory()->Read(
      FromPointerCast<mach_vm_address_t>(kTestMemory),
      sizeof(kTestMemory),
      &buffer));
  EXPECT_STREQ(kTestMemory, buffer);
}

constexpr char kTestMemory[] = "Read me from another process";

class ProcessReaderChild final : public MachMultiprocess {
 public:
  ProcessReaderChild() : MachMultiprocess() {}

  ~ProcessReaderChild() {}

 private:
  void MachMultiprocessParent() override {
    ProcessReaderMac process_reader;
    ASSERT_TRUE(process_reader.Initialize(ChildTask()));

#if !defined(ARCH_CPU_64_BITS)
    EXPECT_FALSE(process_reader.Is64Bit());
#else
    EXPECT_TRUE(process_reader.Is64Bit());
#endif

    EXPECT_EQ(process_reader.ParentProcessID(), getpid());
    EXPECT_EQ(process_reader.ProcessID(), ChildPID());

    FileHandle read_handle = ReadPipeHandle();

    mach_vm_address_t address;
    CheckedReadFileExactly(read_handle, &address, sizeof(address));

    std::string read_string;
    ASSERT_TRUE(process_reader.Memory()->ReadCString(address, &read_string));
    EXPECT_EQ(read_string, kTestMemory);
  }

  void MachMultiprocessChild() override {
    FileHandle write_handle = WritePipeHandle();

    mach_vm_address_t address = FromPointerCast<mach_vm_address_t>(kTestMemory);
    CheckedWriteFile(write_handle, &address, sizeof(address));

    // Wait for the parent to signal that it’s OK to exit by closing its end of
    // the pipe.
    CheckedReadFileAtEOF(ReadPipeHandle());
  }

  DISALLOW_COPY_AND_ASSIGN(ProcessReaderChild);
};

TEST(ProcessReaderMac, ChildBasic) {
  ProcessReaderChild process_reader_child;
  process_reader_child.Run();
}

// Returns a thread ID given a pthread_t. This wraps pthread_threadid_np() but
// that function has a cumbersome interface because it returns a success value.
// This function CHECKs success and returns the thread ID directly.
uint64_t PthreadToThreadID(pthread_t pthread) {
  uint64_t thread_id;
  errno = pthread_threadid_np(pthread, &thread_id);
  PCHECK(errno == 0) << "pthread_threadid_np";
  return thread_id;
}

TEST(ProcessReaderMac, SelfOneThread) {
  ProcessReaderMac process_reader;
  ASSERT_TRUE(process_reader.Initialize(mach_task_self()));

  const std::vector<ProcessReaderMac::Thread>& threads =
      process_reader.Threads();

  // If other tests ran in this process previously, threads may have been
  // created and may still be running. This check must look for at least one
  // thread, not exactly one thread.
  ASSERT_GE(threads.size(), 1u);

  EXPECT_EQ(threads[0].id, PthreadToThreadID(pthread_self()));

  thread_t thread_self = MachThreadSelf();
  EXPECT_EQ(threads[0].port, thread_self);

  EXPECT_EQ(threads[0].suspend_count, 0);
}

class TestThreadPool {
 public:
  struct ThreadExpectation {
    mach_vm_address_t stack_address;
    int suspend_count;
  };

  TestThreadPool() : thread_infos_() {}

  // Resumes suspended threads, signals each thread’s exit semaphore asking it
  // to exit, and joins each thread, blocking until they have all exited.
  ~TestThreadPool() {
    for (const auto& thread_info : thread_infos_) {
      thread_t thread_port = pthread_mach_thread_np(thread_info->pthread);
      while (thread_info->suspend_count > 0) {
        kern_return_t kr = thread_resume(thread_port);
        EXPECT_EQ(kr, KERN_SUCCESS) << MachErrorMessage(kr, "thread_resume");
        --thread_info->suspend_count;
      }
    }

    for (const auto& thread_info : thread_infos_) {
      thread_info->exit_semaphore.Signal();
    }

    for (const auto& thread_info : thread_infos_) {
      int rv = pthread_join(thread_info->pthread, nullptr);
      CHECK_EQ(0, rv);
    }
  }

  // Starts |thread_count| threads and waits on each thread’s ready semaphore,
  // so that when this function returns, all threads have been started and have
  // all run to the point that they’ve signalled that they are ready.
  void StartThreads(size_t thread_count) {
    ASSERT_TRUE(thread_infos_.empty());

    for (size_t thread_index = 0; thread_index < thread_count; ++thread_index) {
      thread_infos_.push_back(std::make_unique<ThreadInfo>());
      ThreadInfo* thread_info = thread_infos_.back().get();

      int rv = pthread_create(
          &thread_info->pthread, nullptr, ThreadMain, thread_info);
      ASSERT_EQ(rv, 0);
    }

    for (const auto& thread_info : thread_infos_) {
      thread_info->ready_semaphore.Wait();
    }

    // If present, suspend the thread at indices 1 through 3 the same number of
    // times as their index. This tests reporting of suspend counts.
    for (size_t thread_index = 1;
         thread_index < thread_infos_.size() && thread_index < 4;
         ++thread_index) {
      thread_t thread_port =
          pthread_mach_thread_np(thread_infos_[thread_index]->pthread);
      for (size_t suspend_count = 0; suspend_count < thread_index;
           ++suspend_count) {
        kern_return_t kr = thread_suspend(thread_port);
        EXPECT_EQ(kr, KERN_SUCCESS) << MachErrorMessage(kr, "thread_suspend");
        if (kr == KERN_SUCCESS) {
          ++thread_infos_[thread_index]->suspend_count;
        }
      }
    }
  }

  uint64_t GetThreadInfo(size_t thread_index, ThreadExpectation* expectation) {
    CHECK_LT(thread_index, thread_infos_.size());

    const auto& thread_info = thread_infos_[thread_index];
    expectation->stack_address = thread_info->stack_address;
    expectation->suspend_count = thread_info->suspend_count;

    return PthreadToThreadID(thread_info->pthread);
  }

 private:
  struct ThreadInfo {
    ThreadInfo()
        : pthread(nullptr),
          stack_address(0),
          ready_semaphore(0),
          exit_semaphore(0),
          suspend_count(0) {}

    ~ThreadInfo() {}

    // The thread’s ID, set at the time the thread is created.
    pthread_t pthread;

    // An address somewhere within the thread’s stack. The thread sets this in
    // its ThreadMain().
    mach_vm_address_t stack_address;

    // The worker thread signals ready_semaphore to indicate that it’s done
    // setting up its ThreadInfo structure. The main thread waits on this
    // semaphore before using any data that the worker thread is responsible for
    // setting.
    Semaphore ready_semaphore;

    // The worker thread waits on exit_semaphore to determine when it’s safe to
    // exit. The main thread signals exit_semaphore when it no longer needs the
    // worker thread.
    Semaphore exit_semaphore;

    // The thread’s suspend count.
    int suspend_count;
  };

  static void* ThreadMain(void* argument) {
    ThreadInfo* thread_info = static_cast<ThreadInfo*>(argument);

    thread_info->stack_address =
        FromPointerCast<mach_vm_address_t>(&thread_info);

    thread_info->ready_semaphore.Signal();
    thread_info->exit_semaphore.Wait();

    // Check this here after everything’s known to be synchronized, otherwise
    // there’s a race between the parent thread storing this thread’s pthread_t
    // in thread_info_pthread and this thread starting and attempting to access
    // it.
    CHECK_EQ(pthread_self(), thread_info->pthread);

    return nullptr;
  }

  // This is a vector of pointers because the address of a ThreadInfo object is
  // passed to each thread’s ThreadMain(), so they cannot move around in memory.
  std::vector<std::unique_ptr<ThreadInfo>> thread_infos_;

  DISALLOW_COPY_AND_ASSIGN(TestThreadPool);
};

using ThreadMap = std::map<uint64_t, TestThreadPool::ThreadExpectation>;

// Verifies that all of the threads in |threads|, obtained from
// ProcessReaderMac, agree with the expectation in |thread_map|. If
// |tolerate_extra_threads| is true, |threads| is allowed to contain threads
// that are not listed in |thread_map|. This is useful when testing situations
// where code outside of the test’s control (such as system libraries) may start
// threads, or may have started threads prior to a test’s execution.
void ExpectSeveralThreads(ThreadMap* thread_map,
                          const std::vector<ProcessReaderMac::Thread>& threads,
                          const bool tolerate_extra_threads) {
  if (tolerate_extra_threads) {
    ASSERT_GE(threads.size(), thread_map->size());
  } else {
    ASSERT_EQ(threads.size(), thread_map->size());
  }

  for (size_t thread_index = 0; thread_index < threads.size(); ++thread_index) {
    const ProcessReaderMac::Thread& thread = threads[thread_index];
    mach_vm_address_t thread_stack_region_end =
        thread.stack_region_address + thread.stack_region_size;

    const auto& iterator = thread_map->find(thread.id);
    if (!tolerate_extra_threads) {
      // Make sure that the thread is in the expectation map.
      ASSERT_NE(iterator, thread_map->end());
    }

    if (iterator != thread_map->end()) {
      EXPECT_GE(iterator->second.stack_address, thread.stack_region_address);
      EXPECT_LT(iterator->second.stack_address, thread_stack_region_end);

      EXPECT_EQ(thread.suspend_count, iterator->second.suspend_count);

      // Remove the thread from the expectation map since it’s already been
      // found. This makes it easy to check for duplicate thread IDs, and makes
      // it easy to check that all expected threads were found.
      thread_map->erase(iterator);
    }

    // Make sure that this thread’s ID, stack region, and port don’t conflict
    // with any other thread’s. Each thread should have a unique value for its
    // ID and port, and each should have its own stack that doesn’t touch any
    // other thread’s stack.
    for (size_t other_thread_index = 0; other_thread_index < threads.size();
         ++other_thread_index) {
      if (other_thread_index == thread_index) {
        continue;
      }

      const ProcessReaderMac::Thread& other_thread =
          threads[other_thread_index];

      EXPECT_NE(other_thread.id, thread.id);
      EXPECT_NE(other_thread.port, thread.port);

      mach_vm_address_t other_thread_stack_region_end =
          other_thread.stack_region_address + other_thread.stack_region_size;
      EXPECT_FALSE(thread.stack_region_address >=
                       other_thread.stack_region_address &&
                   thread.stack_region_address < other_thread_stack_region_end);
      EXPECT_FALSE(thread_stack_region_end >
                       other_thread.stack_region_address &&
                   thread_stack_region_end <= other_thread_stack_region_end);
    }
  }

  // Make sure that each expected thread was found.
  EXPECT_TRUE(thread_map->empty());
}

TEST(ProcessReaderMac, SelfSeveralThreads) {
  // Set up the ProcessReaderMac here, before any other threads are running.
  // This tests that the threads it returns are lazily initialized as a snapshot
  // of the threads at the time of the first call to Threads(), and not at the
  // time the ProcessReader was created or initialized.
  ProcessReaderMac process_reader;
  ASSERT_TRUE(process_reader.Initialize(mach_task_self()));

  TestThreadPool thread_pool;
  constexpr size_t kChildThreads = 16;
  ASSERT_NO_FATAL_FAILURE(thread_pool.StartThreads(kChildThreads));

  // Build a map of all expected threads, keyed by each thread’s ID. The values
  // are addresses that should lie somewhere within each thread’s stack.
  ThreadMap thread_map;
  const uint64_t self_thread_id = PthreadToThreadID(pthread_self());
  TestThreadPool::ThreadExpectation expectation;
  expectation.stack_address = FromPointerCast<mach_vm_address_t>(&thread_map);
  expectation.suspend_count = 0;
  thread_map[self_thread_id] = expectation;
  for (size_t thread_index = 0; thread_index < kChildThreads; ++thread_index) {
    uint64_t thread_id = thread_pool.GetThreadInfo(thread_index, &expectation);

    // There can’t be any duplicate thread IDs.
    EXPECT_EQ(thread_map.count(thread_id), 0u);

    thread_map[thread_id] = expectation;
  }

  const std::vector<ProcessReaderMac::Thread>& threads =
      process_reader.Threads();

  // Other tests that have run previously may have resulted in the creation of
  // threads that still exist, so pass true for |tolerate_extra_threads|.
  ExpectSeveralThreads(&thread_map, threads, true);

  // When testing in-process, verify that when this thread shows up in the
  // vector, it has the expected thread port, and that this thread port only
  // shows up once.
  thread_t thread_self = MachThreadSelf();
  bool found_thread_self = false;
  for (const ProcessReaderMac::Thread& thread : threads) {
    if (thread.port == thread_self) {
      EXPECT_FALSE(found_thread_self);
      found_thread_self = true;
      EXPECT_EQ(thread.id, self_thread_id);
    }
  }
  EXPECT_TRUE(found_thread_self);
}

uint64_t GetThreadID() {
  thread_identifier_info info;
  mach_msg_type_number_t info_count = THREAD_IDENTIFIER_INFO_COUNT;
  kern_return_t kr = thread_info(MachThreadSelf(),
                                 THREAD_IDENTIFIER_INFO,
                                 reinterpret_cast<thread_info_t>(&info),
                                 &info_count);
  MACH_CHECK(kr == KERN_SUCCESS, kr) << "thread_info";

  return info.thread_id;
}

class ProcessReaderThreadedChild final : public MachMultiprocess {
 public:
  explicit ProcessReaderThreadedChild(size_t thread_count)
      : MachMultiprocess(), thread_count_(thread_count) {}

  ~ProcessReaderThreadedChild() {}

 private:
  void MachMultiprocessParent() override {
    ProcessReaderMac process_reader;
    ASSERT_TRUE(process_reader.Initialize(ChildTask()));

    FileHandle read_handle = ReadPipeHandle();

    // Build a map of all expected threads, keyed by each thread’s ID, and with
    // addresses that should lie somewhere within each thread’s stack as values.
    // These IDs and addresses all come from the child process via the pipe.
    ThreadMap thread_map;
    for (size_t thread_index = 0; thread_index < thread_count_ + 1;
         ++thread_index) {
      uint64_t thread_id;
      CheckedReadFileExactly(read_handle, &thread_id, sizeof(thread_id));

      TestThreadPool::ThreadExpectation expectation;
      CheckedReadFileExactly(read_handle,
                             &expectation.stack_address,
                             sizeof(expectation.stack_address));
      CheckedReadFileExactly(read_handle,
                             &expectation.suspend_count,
                             sizeof(expectation.suspend_count));

      // There can’t be any duplicate thread IDs.
      EXPECT_EQ(thread_map.count(thread_id), 0u);

      thread_map[thread_id] = expectation;
    }

    const std::vector<ProcessReaderMac::Thread>& threads =
        process_reader.Threads();

    // The child shouldn’t have any threads other than its main thread and the
    // ones it created in its pool, so pass false for |tolerate_extra_threads|.
    ExpectSeveralThreads(&thread_map, threads, false);
  }

  void MachMultiprocessChild() override {
    TestThreadPool thread_pool;
    ASSERT_NO_FATAL_FAILURE(thread_pool.StartThreads(thread_count_));

    FileHandle write_handle = WritePipeHandle();

    // This thread isn’t part of the thread pool, but the parent will be able
    // to inspect it. Write an entry for it.
    uint64_t thread_id = GetThreadID();

    CheckedWriteFile(write_handle, &thread_id, sizeof(thread_id));

    TestThreadPool::ThreadExpectation expectation;
    expectation.stack_address = FromPointerCast<mach_vm_address_t>(&thread_id);
    expectation.suspend_count = 0;

    CheckedWriteFile(write_handle,
                     &expectation.stack_address,
                     sizeof(expectation.stack_address));
    CheckedWriteFile(write_handle,
                     &expectation.suspend_count,
                     sizeof(expectation.suspend_count));

    // Write an entry for everything in the thread pool.
    for (size_t thread_index = 0; thread_index < thread_count_;
         ++thread_index) {
      uint64_t thread_id =
          thread_pool.GetThreadInfo(thread_index, &expectation);

      CheckedWriteFile(write_handle, &thread_id, sizeof(thread_id));
      CheckedWriteFile(write_handle,
                       &expectation.stack_address,
                       sizeof(expectation.stack_address));
      CheckedWriteFile(write_handle,
                       &expectation.suspend_count,
                       sizeof(expectation.suspend_count));
    }

    // Wait for the parent to signal that it’s OK to exit by closing its end of
    // the pipe.
    CheckedReadFileAtEOF(ReadPipeHandle());
  }

  size_t thread_count_;

  DISALLOW_COPY_AND_ASSIGN(ProcessReaderThreadedChild);
};

TEST(ProcessReaderMac, ChildOneThread) {
  // The main thread plus zero child threads equals one thread.
  constexpr size_t kChildThreads = 0;
  ProcessReaderThreadedChild process_reader_threaded_child(kChildThreads);
  process_reader_threaded_child.Run();
}

TEST(ProcessReaderMac, ChildSeveralThreads) {
  constexpr size_t kChildThreads = 64;
  ProcessReaderThreadedChild process_reader_threaded_child(kChildThreads);
  process_reader_threaded_child.Run();
}

// cl_kernels images (OpenCL kernels) are weird. They’re not ld output and don’t
// exist as files on disk. On OS X 10.10 and 10.11, their Mach-O structure isn’t
// perfect. They show up loaded into many executables, so these quirks should be
// tolerated.
//
// Create an object of this class to ensure that at least one cl_kernels image
// is present in a process, to be able to test that all of the process-reading
// machinery tolerates them. On systems where cl_kernels modules have known
// quirks, the image that an object of this class produces will also have those
// quirks.
//
// https://openradar.appspot.com/20239912
class ScopedOpenCLNoOpKernel {
 public:
  ScopedOpenCLNoOpKernel()
      : context_(nullptr), program_(nullptr), kernel_(nullptr) {}

  ~ScopedOpenCLNoOpKernel() {
    if (kernel_) {
      cl_int rv = clReleaseKernel(kernel_);
      EXPECT_EQ(rv, CL_SUCCESS) << "clReleaseKernel";
    }

    if (program_) {
      cl_int rv = clReleaseProgram(program_);
      EXPECT_EQ(rv, CL_SUCCESS) << "clReleaseProgram";
    }

    if (context_) {
      cl_int rv = clReleaseContext(context_);
      EXPECT_EQ(rv, CL_SUCCESS) << "clReleaseContext";
    }
  }

  void SetUp() {
    cl_platform_id platform_id;
    cl_int rv = clGetPlatformIDs(1, &platform_id, nullptr);
    ASSERT_EQ(rv, CL_SUCCESS) << "clGetPlatformIDs";

#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10 && \
    MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10
// cl_device_id is really available in OpenCL.framework back to 10.5, but in
// the 10.10 SDK and later, OpenCL.framework includes <OpenGL/CGLDevice.h>,
// which has its own cl_device_id that was introduced in 10.10. That
// triggers erroneous availability warnings.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
#define DISABLED_WUNGUARDED_AVAILABILITY
#endif  // SDK >= 10.10 && DT < 10.10
    // Use CL_DEVICE_TYPE_CPU to ensure that the kernel would execute on the
    // CPU. This is the only device type that a cl_kernels image will be created
    // for.
    cl_device_id device_id;
#if defined(DISABLED_WUNGUARDED_AVAILABILITY)
#pragma clang diagnostic pop
#undef DISABLED_WUNGUARDED_AVAILABILITY
#endif  // DISABLED_WUNGUARDED_AVAILABILITY
    rv =
        clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_CPU, 1, &device_id, nullptr);
    ASSERT_EQ(rv, CL_SUCCESS) << "clGetDeviceIDs";

    context_ = clCreateContext(nullptr, 1, &device_id, nullptr, nullptr, &rv);
    ASSERT_EQ(rv, CL_SUCCESS) << "clCreateContext";

    // The goal of the program in |sources| is to produce a cl_kernels image
    // that doesn’t strictly conform to Mach-O expectations. On OS X 10.10,
    // cl_kernels modules show up with an __LD,__compact_unwind section, showing
    // up in the __TEXT segment. MachOImageSegmentReader would normally reject
    // modules for this problem, but a special exception is made when this
    // occurs in cl_kernels images. This portion of the test is aimed at making
    // sure that this exception works correctly.
    //
    // A true no-op program doesn’t actually produce unwind data, so there would
    // be no errant __LD,__compact_unwind section on 10.10, and the test
    // wouldn’t be complete. This simple no-op, which calls a built-in function,
    // does produce unwind data provided optimization is disabled.
    // "-cl-opt-disable" is given to clBuildProgram() below.
    const char* sources[] = {
        "__kernel void NoOp(void) {barrier(CLK_LOCAL_MEM_FENCE);}",
    };
    const size_t source_lengths[] = {
        strlen(sources[0]),
    };
    static_assert(base::size(sources) == base::size(source_lengths),
                  "arrays must be parallel");

    program_ = clCreateProgramWithSource(
        context_, base::size(sources), sources, source_lengths, &rv);
    ASSERT_EQ(rv, CL_SUCCESS) << "clCreateProgramWithSource";

    rv = clBuildProgram(
        program_, 1, &device_id, "-cl-opt-disable", nullptr, nullptr);
    ASSERT_EQ(rv, CL_SUCCESS) << "clBuildProgram";

    kernel_ = clCreateKernel(program_, "NoOp", &rv);
    ASSERT_EQ(rv, CL_SUCCESS) << "clCreateKernel";
  }

 private:
  cl_context context_;
  cl_program program_;
  cl_kernel kernel_;

  DISALLOW_COPY_AND_ASSIGN(ScopedOpenCLNoOpKernel);
};

// Although Mac OS X 10.6 has OpenCL and can compile and execute OpenCL code,
// OpenCL kernels that run on the CPU do not result in cl_kernels images
// appearing on that OS version.
bool ExpectCLKernels() {
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7
  return true;
#else
  return MacOSXMinorVersion() >= 7;
#endif
}

TEST(ProcessReaderMac, SelfModules) {
  ScopedOpenCLNoOpKernel ensure_cl_kernels;
  ASSERT_NO_FATAL_FAILURE(ensure_cl_kernels.SetUp());

  ProcessReaderMac process_reader;
  ASSERT_TRUE(process_reader.Initialize(mach_task_self()));

  uint32_t dyld_image_count = _dyld_image_count();
  const std::vector<ProcessReaderMac::Module>& modules =
      process_reader.Modules();

  // There needs to be at least an entry for the main executable, for a dylib,
  // and for dyld.
  ASSERT_GE(modules.size(), 3u);

  // dyld_image_count doesn’t include an entry for dyld itself, but |modules|
  // does.
  ASSERT_EQ(modules.size(), dyld_image_count + 1);

  bool found_cl_kernels = false;
  for (uint32_t index = 0; index < dyld_image_count; ++index) {
    SCOPED_TRACE(base::StringPrintf(
        "index %u, name %s", index, modules[index].name.c_str()));

    const char* dyld_image_name = _dyld_get_image_name(index);
    EXPECT_EQ(modules[index].name, dyld_image_name);
    ASSERT_TRUE(modules[index].reader);
    EXPECT_EQ(
        modules[index].reader->Address(),
        FromPointerCast<mach_vm_address_t>(_dyld_get_image_header(index)));

    bool expect_timestamp;
    if (index == 0) {
      // dyld didn’t load the main executable, so it couldn’t record its
      // timestamp, and it is reported as 0.
      EXPECT_EQ(modules[index].timestamp, 0);
    } else if (IsMalformedCLKernelsModule(modules[index].reader->FileType(),
                                          modules[index].name,
                                          &expect_timestamp)) {
      // cl_kernels doesn’t exist as a file, but may still have a timestamp.
      if (!expect_timestamp) {
        EXPECT_EQ(modules[index].timestamp, 0);
      } else {
        EXPECT_NE(modules[index].timestamp, 0);
      }
      found_cl_kernels = true;
    } else {
      // Hope that the module didn’t change on disk.
      struct stat stat_buf;
      int rv = stat(dyld_image_name, &stat_buf);
      EXPECT_EQ(rv, 0) << ErrnoMessage("stat");
      if (rv == 0) {
        EXPECT_EQ(modules[index].timestamp, stat_buf.st_mtime);
      }
    }
  }

  EXPECT_EQ(found_cl_kernels, ExpectCLKernels());

  size_t index = modules.size() - 1;
  EXPECT_EQ(modules[index].name, kDyldPath);

  // dyld didn’t load itself either, so it couldn’t record its timestamp, and it
  // is also reported as 0.
  EXPECT_EQ(modules[index].timestamp, 0);

  const dyld_all_image_infos* dyld_image_infos = DyldGetAllImageInfos();
  if (dyld_image_infos->version >= 2) {
    ASSERT_TRUE(modules[index].reader);
    EXPECT_EQ(modules[index].reader->Address(),
              FromPointerCast<mach_vm_address_t>(
                  dyld_image_infos->dyldImageLoadAddress));
  }
}

class ProcessReaderModulesChild final : public MachMultiprocess {
 public:
  ProcessReaderModulesChild() : MachMultiprocess() {}

  ~ProcessReaderModulesChild() {}

 private:
  void MachMultiprocessParent() override {
    ProcessReaderMac process_reader;
    ASSERT_TRUE(process_reader.Initialize(ChildTask()));

    const std::vector<ProcessReaderMac::Module>& modules =
        process_reader.Modules();

    // There needs to be at least an entry for the main executable, for a dylib,
    // and for dyld.
    ASSERT_GE(modules.size(), 3u);

    FileHandle read_handle = ReadPipeHandle();

    uint32_t expect_modules;
    CheckedReadFileExactly(
        read_handle, &expect_modules, sizeof(expect_modules));

    ASSERT_EQ(modules.size(), expect_modules);

    bool found_cl_kernels = false;
    for (size_t index = 0; index < modules.size(); ++index) {
      SCOPED_TRACE(base::StringPrintf(
          "index %zu, name %s", index, modules[index].name.c_str()));

      uint32_t expect_name_length;
      CheckedReadFileExactly(
          read_handle, &expect_name_length, sizeof(expect_name_length));

      // The NUL terminator is not read.
      std::string expect_name(expect_name_length, '\0');
      CheckedReadFileExactly(read_handle, &expect_name[0], expect_name_length);
      EXPECT_EQ(modules[index].name, expect_name);

      mach_vm_address_t expect_address;
      CheckedReadFileExactly(
          read_handle, &expect_address, sizeof(expect_address));
      ASSERT_TRUE(modules[index].reader);
      EXPECT_EQ(modules[index].reader->Address(), expect_address);

      bool expect_timestamp;
      if (index == 0 || index == modules.size() - 1) {
        // dyld didn’t load the main executable or itself, so it couldn’t record
        // these timestamps, and they are reported as 0.
        EXPECT_EQ(modules[index].timestamp, 0);
      } else if (IsMalformedCLKernelsModule(modules[index].reader->FileType(),
                                            modules[index].name,
                                            &expect_timestamp)) {
        // cl_kernels doesn’t exist as a file, but may still have a timestamp.
        if (!expect_timestamp) {
          EXPECT_EQ(modules[index].timestamp, 0);
        } else {
          EXPECT_NE(modules[index].timestamp, 0);
        }
        found_cl_kernels = true;
      } else {
        // Hope that the module didn’t change on disk.
        struct stat stat_buf;
        int rv = stat(expect_name.c_str(), &stat_buf);
        EXPECT_EQ(rv, 0) << ErrnoMessage("stat");
        if (rv == 0) {
          EXPECT_EQ(modules[index].timestamp, stat_buf.st_mtime);
        }
      }
    }

    EXPECT_EQ(found_cl_kernels, ExpectCLKernels());
  }

  void MachMultiprocessChild() override {
    FileHandle write_handle = WritePipeHandle();

    uint32_t dyld_image_count = _dyld_image_count();
    const dyld_all_image_infos* dyld_image_infos = DyldGetAllImageInfos();

    uint32_t write_image_count = dyld_image_count;
    if (dyld_image_infos->version >= 2) {
      // dyld_image_count doesn’t include an entry for dyld itself, but one will
      // be written.
      ++write_image_count;
    }

    CheckedWriteFile(
        write_handle, &write_image_count, sizeof(write_image_count));

    for (size_t index = 0; index < write_image_count; ++index) {
      const char* dyld_image_name;
      mach_vm_address_t dyld_image_address;

      if (index < dyld_image_count) {
        dyld_image_name = _dyld_get_image_name(index);
        dyld_image_address =
            FromPointerCast<mach_vm_address_t>(_dyld_get_image_header(index));
      } else {
        dyld_image_name = kDyldPath;
        dyld_image_address = FromPointerCast<mach_vm_address_t>(
            dyld_image_infos->dyldImageLoadAddress);
      }

      uint32_t dyld_image_name_length = strlen(dyld_image_name);
      CheckedWriteFile(write_handle,
                       &dyld_image_name_length,
                       sizeof(dyld_image_name_length));

      // The NUL terminator is not written.
      CheckedWriteFile(write_handle, dyld_image_name, dyld_image_name_length);

      CheckedWriteFile(
          write_handle, &dyld_image_address, sizeof(dyld_image_address));
    }

    // Wait for the parent to signal that it’s OK to exit by closing its end of
    // the pipe.
    CheckedReadFileAtEOF(ReadPipeHandle());
  }

  DISALLOW_COPY_AND_ASSIGN(ProcessReaderModulesChild);
};

TEST(ProcessReaderMac, ChildModules) {
  ScopedOpenCLNoOpKernel ensure_cl_kernels;
  ASSERT_NO_FATAL_FAILURE(ensure_cl_kernels.SetUp());

  ProcessReaderModulesChild process_reader_modules_child;
  process_reader_modules_child.Run();
}

}  // namespace
}  // namespace test
}  // namespace crashpad
