#include "snapshot/elf/elf_image_reader.h"
#include <dlfcn.h>
#include <link.h>
#include <unistd.h>
#include "build/build_config.h"
#include "gtest/gtest.h"
#include "test/multiprocess_exec.h"
#include "test/process_type.h"
#include "test/scoped_module_handle.h"
#include "test/test_paths.h"
#include "util/file/file_io.h"
#include "util/misc/address_types.h"
#include "util/misc/elf_note_types.h"
#include "util/misc/from_pointer_cast.h"
#include "util/process/process_memory_native.h"
#if BUILDFLAG(IS_FUCHSIA)
#include <lib/zx/process.h>
#include "base/fuchsia/fuchsia_logging.h"
#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
#include "test/linux/fake_ptrace_connection.h"
#include "util/linux/auxiliary_vector.h"
#include "util/linux/memory_map.h"
#else
#error Port.
#endif
extern "C" {
__attribute__((visibility("default"))) void ElfImageReaderTestExportedSymbol() { … }
}
namespace crashpad {
namespace test {
namespace {
#if BUILDFLAG(IS_FUCHSIA)
void LocateExecutable(const ProcessType& process,
ProcessMemory* memory,
VMAddress* elf_address) {
uintptr_t debug_address;
zx_status_t status = process->get_property(
ZX_PROP_PROCESS_DEBUG_ADDR, &debug_address, sizeof(debug_address));
ASSERT_EQ(status, ZX_OK)
<< "zx_object_get_property: ZX_PROP_PROCESS_DEBUG_ADDR";
EXPECT_NE(debug_address, 0u);
constexpr auto k_r_debug_map_offset = offsetof(r_debug, r_map);
uintptr_t map;
ASSERT_TRUE(
memory->Read(debug_address + k_r_debug_map_offset, sizeof(map), &map))
<< "read link_map";
constexpr auto k_link_map_addr_offset = offsetof(link_map, l_addr);
uintptr_t base;
ASSERT_TRUE(memory->Read(map + k_link_map_addr_offset, sizeof(base), &base))
<< "read base";
*elf_address = base;
}
#elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
void LocateExecutable(PtraceConnection* connection,
ProcessMemory* memory,
VMAddress* elf_address) { … }
#endif
void ExpectSymbol(ElfImageReader* reader,
const std::string& symbol_name,
VMAddress expected_symbol_address) { … }
void ReadThisExecutableInTarget(ProcessType process,
VMAddress exported_symbol_address) { … }
void ReadLibcInTarget(ProcessType process,
VMAddress elf_address,
VMAddress getpid_address) { … }
TEST(ElfImageReader, DISABLED_MainExecutableSelf) { … }
CRASHPAD_CHILD_TEST_MAIN(ReadExecutableChild) { … }
class ReadExecutableChildTest : public MultiprocessExec { … };
TEST(ElfImageReader, MainExecutableChild) { … }
TEST(ElfImageReader, OneModuleSelf) { … }
CRASHPAD_CHILD_TEST_MAIN(ReadLibcChild) { … }
class ReadLibcChildTest : public MultiprocessExec { … };
TEST(ElfImageReader, OneModuleChild) { … }
#if BUILDFLAG(IS_FUCHSIA)
TEST(ElfImageReader, DtHashAndDtGnuHashMatch) {
base::FilePath module_path =
TestPaths::BuildArtifact(FILE_PATH_LITERAL("snapshot"),
FILE_PATH_LITERAL("both_dt_hash_styles"),
TestPaths::FileType::kLoadableModule);
module_path = module_path.BaseName();
ScopedModuleHandle module(
dlopen(module_path.value().c_str(), RTLD_LAZY | RTLD_LOCAL));
ASSERT_TRUE(module.valid()) << "dlopen " << module_path.value() << ": "
<< dlerror();
#if defined(ARCH_CPU_64_BITS)
constexpr bool am_64_bit = true;
#else
constexpr bool am_64_bit = false;
#endif
ProcessMemoryNative memory;
ASSERT_TRUE(memory.Initialize(GetSelfProcess()));
ProcessMemoryRange range;
ASSERT_TRUE(range.Initialize(&memory, am_64_bit));
struct link_map* lm = reinterpret_cast<struct link_map*>(module.get());
ElfImageReader reader;
ASSERT_TRUE(reader.Initialize(range, lm->l_addr));
VMSize from_dt_hash;
ASSERT_TRUE(reader.GetNumberOfSymbolEntriesFromDtHash(&from_dt_hash));
VMSize from_dt_gnu_hash;
ASSERT_TRUE(reader.GetNumberOfSymbolEntriesFromDtGnuHash(&from_dt_gnu_hash));
EXPECT_EQ(from_dt_hash, from_dt_gnu_hash);
}
#endif
}
}
}