mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-06-29 16:43:07 +00:00
Fix linux-gate handling in LinuxDumper so it gets a valid debug ID
A=ted R=nealsid at http://breakpad.appspot.com/284001 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@788 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
04023b1f6a
commit
1807e385d7
|
@ -213,6 +213,21 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
|
||||||
if (IsMappedFileOpenUnsafe(mapping))
|
if (IsMappedFileOpenUnsafe(mapping))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Special-case linux-gate because it's not a real file.
|
||||||
|
if (my_strcmp(mapping.name, kLinuxGateLibraryName) == 0) {
|
||||||
|
const uintptr_t kPageSize = getpagesize();
|
||||||
|
void* linux_gate = NULL;
|
||||||
|
if (pid_ == sys_getpid()) {
|
||||||
|
linux_gate = reinterpret_cast<void*>(mapping.start_addr);
|
||||||
|
} else {
|
||||||
|
linux_gate = allocator_.Alloc(kPageSize);
|
||||||
|
CopyFromProcess(linux_gate, pid_,
|
||||||
|
reinterpret_cast<const void*>(mapping.start_addr),
|
||||||
|
kPageSize);
|
||||||
|
}
|
||||||
|
return FileID::ElfFileIdentifierFromMappedFile(linux_gate, identifier);
|
||||||
|
}
|
||||||
|
|
||||||
char filename[NAME_MAX];
|
char filename[NAME_MAX];
|
||||||
size_t filename_len = my_strlen(mapping.name);
|
size_t filename_len = my_strlen(mapping.name);
|
||||||
assert(filename_len < NAME_MAX);
|
assert(filename_len < NAME_MAX);
|
||||||
|
|
|
@ -276,6 +276,7 @@ TEST(LinuxDumperTest, BuildProcPath) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(__ARM_EABI__)
|
#if !defined(__ARM_EABI__)
|
||||||
|
// Ensure that the linux-gate VDSO is included in the mapping list.
|
||||||
TEST(LinuxDumperTest, MappingsIncludeLinuxGate) {
|
TEST(LinuxDumperTest, MappingsIncludeLinuxGate) {
|
||||||
LinuxDumper dumper(getpid());
|
LinuxDumper dumper(getpid());
|
||||||
ASSERT_TRUE(dumper.Init());
|
ASSERT_TRUE(dumper.Init());
|
||||||
|
@ -297,6 +298,80 @@ TEST(LinuxDumperTest, MappingsIncludeLinuxGate) {
|
||||||
EXPECT_EQ(linux_gate_loc, reinterpret_cast<void*>(mapping->start_addr));
|
EXPECT_EQ(linux_gate_loc, reinterpret_cast<void*>(mapping->start_addr));
|
||||||
EXPECT_EQ(0, memcmp(linux_gate_loc, ELFMAG, SELFMAG));
|
EXPECT_EQ(0, memcmp(linux_gate_loc, ELFMAG, SELFMAG));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that the linux-gate VDSO can generate a non-zeroed File ID.
|
||||||
|
TEST(LinuxDumperTest, LinuxGateMappingID) {
|
||||||
|
LinuxDumper dumper(getpid());
|
||||||
|
ASSERT_TRUE(dumper.Init());
|
||||||
|
|
||||||
|
bool found_linux_gate = false;
|
||||||
|
const wasteful_vector<MappingInfo*> mappings = dumper.mappings();
|
||||||
|
unsigned index = 0;
|
||||||
|
for (unsigned i = 0; i < mappings.size(); ++i) {
|
||||||
|
if (!strcmp(mappings[i]->name, kLinuxGateLibraryName)) {
|
||||||
|
found_linux_gate = true;
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT_TRUE(found_linux_gate);
|
||||||
|
|
||||||
|
uint8_t identifier[sizeof(MDGUID)];
|
||||||
|
ASSERT_TRUE(dumper.ElfFileIdentifierForMapping(*mappings[index],
|
||||||
|
true,
|
||||||
|
index,
|
||||||
|
identifier));
|
||||||
|
uint8_t empty_identifier[sizeof(MDGUID)];
|
||||||
|
memset(empty_identifier, 0, sizeof(empty_identifier));
|
||||||
|
EXPECT_NE(0, memcmp(empty_identifier, identifier, sizeof(identifier)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the linux-gate VDSO can generate a non-zeroed File ID
|
||||||
|
// from a child process.
|
||||||
|
TEST(LinuxDumperTest, LinuxGateMappingIDChild) {
|
||||||
|
int fds[2];
|
||||||
|
ASSERT_NE(-1, pipe(fds));
|
||||||
|
|
||||||
|
// Fork a child so ptrace works.
|
||||||
|
const pid_t child = fork();
|
||||||
|
if (child == 0) {
|
||||||
|
close(fds[1]);
|
||||||
|
// Now wait forever for the parent.
|
||||||
|
char b;
|
||||||
|
HANDLE_EINTR(read(fds[0], &b, sizeof(b)));
|
||||||
|
close(fds[0]);
|
||||||
|
syscall(__NR_exit);
|
||||||
|
}
|
||||||
|
close(fds[0]);
|
||||||
|
|
||||||
|
LinuxDumper dumper(child);
|
||||||
|
ASSERT_TRUE(dumper.Init());
|
||||||
|
|
||||||
|
bool found_linux_gate = false;
|
||||||
|
const wasteful_vector<MappingInfo*> mappings = dumper.mappings();
|
||||||
|
unsigned index = 0;
|
||||||
|
for (unsigned i = 0; i < mappings.size(); ++i) {
|
||||||
|
if (!strcmp(mappings[i]->name, kLinuxGateLibraryName)) {
|
||||||
|
found_linux_gate = true;
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ASSERT_TRUE(found_linux_gate);
|
||||||
|
|
||||||
|
// Need to suspend the child so ptrace actually works.
|
||||||
|
ASSERT_TRUE(dumper.ThreadsSuspend());
|
||||||
|
uint8_t identifier[sizeof(MDGUID)];
|
||||||
|
ASSERT_TRUE(dumper.ElfFileIdentifierForMapping(*mappings[index],
|
||||||
|
true,
|
||||||
|
index,
|
||||||
|
identifier));
|
||||||
|
uint8_t empty_identifier[sizeof(MDGUID)];
|
||||||
|
memset(empty_identifier, 0, sizeof(empty_identifier));
|
||||||
|
EXPECT_NE(0, memcmp(empty_identifier, identifier, sizeof(identifier)));
|
||||||
|
EXPECT_TRUE(dumper.ThreadsResume());
|
||||||
|
close(fds[1]);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST(LinuxDumperTest, FileIDsMatch) {
|
TEST(LinuxDumperTest, FileIDsMatch) {
|
||||||
|
@ -311,11 +386,11 @@ TEST(LinuxDumperTest, FileIDsMatch) {
|
||||||
int fds[2];
|
int fds[2];
|
||||||
ASSERT_NE(-1, pipe(fds));
|
ASSERT_NE(-1, pipe(fds));
|
||||||
|
|
||||||
// fork a child so we can ptrace it
|
// Fork a child so ptrace works.
|
||||||
const pid_t child = fork();
|
const pid_t child = fork();
|
||||||
if (child == 0) {
|
if (child == 0) {
|
||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
// now wait forever for the parent
|
// Now wait forever for the parent.
|
||||||
char b;
|
char b;
|
||||||
HANDLE_EINTR(read(fds[0], &b, sizeof(b)));
|
HANDLE_EINTR(read(fds[0], &b, sizeof(b)));
|
||||||
close(fds[0]);
|
close(fds[0]);
|
||||||
|
|
Loading…
Reference in a new issue