mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-27 15:32:10 +08:00
9f896f2581
The real Chromium base/bit_cast.h is in the base namespace. mini_chromium's version was just changed to be in the base namespace as well. Roll to the latest mini_chromium and scope all calls to bit_cast. Bug: chromium:1506769 Change-Id: I7b25ee512f67694ef6ed3d0250e4f6a6db151eb3 Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/5116880 Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Avi Drissman <avi@chromium.org>
227 lines
6.5 KiB
C++
227 lines
6.5 KiB
C++
// Copyright 2017 The Crashpad Authors
|
|
//
|
|
// 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 "util/linux/auxiliary_vector.h"
|
|
|
|
#include <linux/auxvec.h>
|
|
#include <sys/utsname.h>
|
|
#include <unistd.h>
|
|
|
|
#include <limits>
|
|
|
|
#include "base/bit_cast.h"
|
|
#include "build/build_config.h"
|
|
#include "gtest/gtest.h"
|
|
#include "test/errors.h"
|
|
#include "test/linux/fake_ptrace_connection.h"
|
|
#include "test/main_arguments.h"
|
|
#include "test/multiprocess.h"
|
|
#include "util/linux/address_types.h"
|
|
#include "util/linux/memory_map.h"
|
|
#include "util/misc/from_pointer_cast.h"
|
|
#include "util/numeric/int128.h"
|
|
#include "util/process/process_memory_linux.h"
|
|
|
|
#if !BUILDFLAG(IS_ANDROID)
|
|
// TODO(jperaza): This symbol isn't defined when building in chromium for
|
|
// Android. There may be another symbol to use.
|
|
extern "C" {
|
|
#if defined(ARCH_CPU_MIPS_FAMILY)
|
|
#define START_SYMBOL __start
|
|
#else
|
|
#define START_SYMBOL _start
|
|
#endif
|
|
extern void START_SYMBOL();
|
|
} // extern "C"
|
|
#endif
|
|
|
|
namespace crashpad {
|
|
namespace test {
|
|
namespace {
|
|
|
|
void TestAgainstCloneOrSelf(pid_t pid) {
|
|
FakePtraceConnection connection;
|
|
ASSERT_TRUE(connection.Initialize(pid));
|
|
|
|
AuxiliaryVector aux;
|
|
ASSERT_TRUE(aux.Initialize(&connection));
|
|
|
|
MemoryMap mappings;
|
|
ASSERT_TRUE(mappings.Initialize(&connection));
|
|
|
|
LinuxVMAddress phdrs;
|
|
ASSERT_TRUE(aux.GetValue(AT_PHDR, &phdrs));
|
|
EXPECT_TRUE(mappings.FindMapping(phdrs));
|
|
|
|
int pagesize;
|
|
ASSERT_TRUE(aux.GetValue(AT_PAGESZ, &pagesize));
|
|
EXPECT_EQ(pagesize, getpagesize());
|
|
|
|
LinuxVMAddress interp_base;
|
|
ASSERT_TRUE(aux.GetValue(AT_BASE, &interp_base));
|
|
EXPECT_TRUE(mappings.FindMapping(interp_base));
|
|
|
|
#if !BUILDFLAG(IS_ANDROID)
|
|
LinuxVMAddress entry_addr;
|
|
ASSERT_TRUE(aux.GetValue(AT_ENTRY, &entry_addr));
|
|
EXPECT_EQ(entry_addr, FromPointerCast<LinuxVMAddress>(START_SYMBOL));
|
|
#endif
|
|
|
|
uid_t uid;
|
|
ASSERT_TRUE(aux.GetValue(AT_UID, &uid));
|
|
EXPECT_EQ(uid, getuid());
|
|
|
|
uid_t euid;
|
|
ASSERT_TRUE(aux.GetValue(AT_EUID, &euid));
|
|
EXPECT_EQ(euid, geteuid());
|
|
|
|
gid_t gid;
|
|
ASSERT_TRUE(aux.GetValue(AT_GID, &gid));
|
|
EXPECT_EQ(gid, getgid());
|
|
|
|
gid_t egid;
|
|
ASSERT_TRUE(aux.GetValue(AT_EGID, &egid));
|
|
EXPECT_EQ(egid, getegid());
|
|
|
|
ProcessMemoryLinux memory(&connection);
|
|
|
|
// AT_PLATFORM is null for RISC-V:
|
|
// https://elixir.bootlin.com/linux/v6.4-rc4/C/ident/ELF_PLATFORM
|
|
#if !defined(ARCH_CPU_RISCV64)
|
|
LinuxVMAddress platform_addr;
|
|
ASSERT_TRUE(aux.GetValue(AT_PLATFORM, &platform_addr));
|
|
std::string platform;
|
|
ASSERT_TRUE(memory.ReadCStringSizeLimited(platform_addr, 10, &platform));
|
|
#endif // ARCH_CPU_RISCV64
|
|
|
|
#if defined(ARCH_CPU_X86)
|
|
EXPECT_STREQ(platform.c_str(), "i686");
|
|
#elif defined(ARCH_CPU_X86_64)
|
|
EXPECT_STREQ(platform.c_str(), "x86_64");
|
|
#elif defined(ARCH_CPU_ARMEL)
|
|
// Machine name and platform are set in Linux:/arch/arm/kernel/setup.c
|
|
// Machine typically looks like "armv7l".
|
|
// Platform typically looks like "v7l".
|
|
utsname sys_names;
|
|
ASSERT_EQ(uname(&sys_names), 0);
|
|
std::string machine_name(sys_names.machine);
|
|
EXPECT_NE(machine_name.find(platform), std::string::npos);
|
|
#elif defined(ARCH_CPU_ARM64)
|
|
EXPECT_STREQ(platform.c_str(), "aarch64");
|
|
#endif // ARCH_CPU_X86
|
|
|
|
#if defined(AT_SYSINFO_EHDR)
|
|
LinuxVMAddress vdso_addr;
|
|
if (aux.GetValue(AT_SYSINFO_EHDR, &vdso_addr)) {
|
|
EXPECT_TRUE(mappings.FindMapping(vdso_addr));
|
|
}
|
|
#endif // AT_SYSINFO_EHDR
|
|
|
|
#if defined(AT_EXECFN)
|
|
LinuxVMAddress filename_addr;
|
|
ASSERT_TRUE(aux.GetValue(AT_EXECFN, &filename_addr));
|
|
std::string filename;
|
|
ASSERT_TRUE(memory.ReadCStringSizeLimited(filename_addr, 4096, &filename));
|
|
EXPECT_TRUE(filename.find(GetMainArguments()[0]) != std::string::npos);
|
|
#endif // AT_EXECFN
|
|
|
|
int ignore;
|
|
EXPECT_FALSE(aux.GetValue(AT_NULL, &ignore));
|
|
|
|
char too_small;
|
|
EXPECT_FALSE(aux.GetValue(AT_PAGESZ, &too_small));
|
|
|
|
uint128_struct big_dest;
|
|
memset(&big_dest, 0xf, sizeof(big_dest));
|
|
ASSERT_TRUE(aux.GetValue(AT_PHDR, &big_dest));
|
|
EXPECT_EQ(big_dest.lo, phdrs);
|
|
}
|
|
|
|
TEST(AuxiliaryVector, ReadSelf) {
|
|
TestAgainstCloneOrSelf(getpid());
|
|
}
|
|
|
|
class ReadChildTest : public Multiprocess {
|
|
public:
|
|
ReadChildTest() : Multiprocess() {}
|
|
|
|
ReadChildTest(const ReadChildTest&) = delete;
|
|
ReadChildTest& operator=(const ReadChildTest&) = delete;
|
|
|
|
~ReadChildTest() {}
|
|
|
|
private:
|
|
void MultiprocessParent() override { TestAgainstCloneOrSelf(ChildPID()); }
|
|
|
|
void MultiprocessChild() override { CheckedReadFileAtEOF(ReadPipeHandle()); }
|
|
};
|
|
|
|
TEST(AuxiliaryVector, ReadChild) {
|
|
ReadChildTest test;
|
|
test.Run();
|
|
}
|
|
|
|
class AuxVecTester : public AuxiliaryVector {
|
|
public:
|
|
AuxVecTester() : AuxiliaryVector() {}
|
|
void Insert(uint64_t type, uint64_t value) { values_[type] = value; }
|
|
};
|
|
|
|
TEST(AuxiliaryVector, SignedBit) {
|
|
FakePtraceConnection connection;
|
|
ASSERT_TRUE(connection.Initialize(getpid()));
|
|
|
|
AuxVecTester aux;
|
|
ASSERT_TRUE(&connection);
|
|
constexpr uint64_t type = 0x0000000012345678;
|
|
|
|
constexpr int32_t neg1_32 = -1;
|
|
aux.Insert(type, base::bit_cast<uint32_t>(neg1_32));
|
|
int32_t outval32s;
|
|
ASSERT_TRUE(aux.GetValue(type, &outval32s));
|
|
EXPECT_EQ(outval32s, neg1_32);
|
|
|
|
constexpr int32_t int32_max = std::numeric_limits<int32_t>::max();
|
|
aux.Insert(type, base::bit_cast<uint32_t>(int32_max));
|
|
ASSERT_TRUE(aux.GetValue(type, &outval32s));
|
|
EXPECT_EQ(outval32s, int32_max);
|
|
|
|
constexpr uint32_t uint32_max = std::numeric_limits<uint32_t>::max();
|
|
aux.Insert(type, uint32_max);
|
|
uint32_t outval32u;
|
|
ASSERT_TRUE(aux.GetValue(type, &outval32u));
|
|
EXPECT_EQ(outval32u, uint32_max);
|
|
|
|
constexpr int64_t neg1_64 = -1;
|
|
aux.Insert(type, base::bit_cast<uint64_t>(neg1_64));
|
|
int64_t outval64s;
|
|
ASSERT_TRUE(aux.GetValue(type, &outval64s));
|
|
EXPECT_EQ(outval64s, neg1_64);
|
|
|
|
constexpr int64_t int64_max = std::numeric_limits<int64_t>::max();
|
|
aux.Insert(type, base::bit_cast<uint64_t>(int64_max));
|
|
ASSERT_TRUE(aux.GetValue(type, &outval64s));
|
|
EXPECT_EQ(outval64s, int64_max);
|
|
|
|
constexpr uint64_t uint64_max = std::numeric_limits<uint64_t>::max();
|
|
aux.Insert(type, uint64_max);
|
|
uint64_t outval64u;
|
|
ASSERT_TRUE(aux.GetValue(type, &outval64u));
|
|
EXPECT_EQ(outval64u, uint64_max);
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace test
|
|
} // namespace crashpad
|