mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-26 23:01:05 +08:00
Get CrashpadInfo address via a .note, rather than dynamic symtab
Embeds the address of g_crashpad_info into a .note section (which is readable by the generic code to read notes in ElfImageReader). Unfortunately because the note section is in libclient.a, it would normally be dropped at link time. To avoid that, GetCrashpadInfo() has a reference *back* to that section, which in turn forces the linker to include it, allowing the note reader to find it at runtime. Previously, it was necessary to have the embedder of "client" figure out how to cause `g_crashpad_info` to appear in the final module's dynamic symbol table. With this new approach, there's no manual configuration necessary, as it's not necessary for the symbol to be exported. This is currently only implemented in the Linux module reader (and I believe the current set of enabled tests aren't exercising it?) but it will also be done this way for the Fuchsia implementation of ModuleSnapshot. Bug: crashpad:196 Change-Id: I599db5903bc98303130d11ad850ba9ceed3b801a Reviewed-on: https://chromium-review.googlesource.com/912284 Commit-Queue: Scott Graham <scottmg@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org> Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
c406797ce6
commit
7faa2ef898
@ -47,6 +47,10 @@ static_library("client") {
|
||||
sources += [ "crashpad_client_linux.cc" ]
|
||||
}
|
||||
|
||||
if (crashpad_is_linux || crashpad_is_android || crashpad_is_fuchsia) {
|
||||
sources += [ "crashpad_info_note.S" ]
|
||||
}
|
||||
|
||||
if (crashpad_is_win) {
|
||||
sources += [
|
||||
"crash_report_database_win.cc",
|
||||
|
@ -62,6 +62,11 @@
|
||||
],
|
||||
},
|
||||
}],
|
||||
['OS=="linux" or OS=="android"', {
|
||||
'sources': [
|
||||
'crashpad_info_note.S',
|
||||
],
|
||||
}],
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
|
@ -52,12 +52,6 @@ static_assert(std::is_standard_layout<CrashpadInfo>::value,
|
||||
// because it’s POD, no code should need to run to initialize this under
|
||||
// release-mode optimization.
|
||||
|
||||
// Platforms that use ELF objects need to locate this structure via the dynamic
|
||||
// symbol table, so avoid name mangling.
|
||||
#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(OS_POSIX)
|
||||
__attribute__((
|
||||
|
||||
@ -96,12 +90,19 @@ __declspec(allocate("CPADinfo"))
|
||||
|
||||
CrashpadInfo g_crashpad_info;
|
||||
|
||||
#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA)
|
||||
} // extern "C"
|
||||
#endif
|
||||
extern "C" int* CRASHPAD_NOTE_REFERENCE;
|
||||
|
||||
// static
|
||||
CrashpadInfo* CrashpadInfo::GetCrashpadInfo() {
|
||||
#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA)
|
||||
// This otherwise-unused reference is used so that any module that
|
||||
// references GetCrashpadInfo() will also include the note in the
|
||||
// .note.crashpad.info section. That note in turn contains the address of
|
||||
// g_crashpad_info. This allows the module reader to find the CrashpadInfo
|
||||
// structure without requiring the use of the dynamic symbol table.
|
||||
static volatile int* pointer_to_note_section = CRASHPAD_NOTE_REFERENCE;
|
||||
(void)pointer_to_note_section;
|
||||
#endif
|
||||
return &g_crashpad_info;
|
||||
}
|
||||
|
||||
|
46
client/crashpad_info_note.S
Normal file
46
client/crashpad_info_note.S
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
// This note section is used on ELF platforms to give ElfImageReader a method
|
||||
// of finding the instance of CrashpadInfo g_crashpad_info without requiring
|
||||
// that symbol to be in the dynamic symbol table.
|
||||
|
||||
#include "util/misc/elf_note_types.h"
|
||||
|
||||
// namespace crashpad {
|
||||
// CrashpadInfo g_crashpad_info;
|
||||
// } // namespace crashpad
|
||||
#define CRASHPAD_INFO_SYMBOL _ZN8crashpad15g_crashpad_infoE
|
||||
|
||||
#define NOTE_ALIGN 4
|
||||
|
||||
// This section must be "a"llocated so that it appears in the final binary at
|
||||
// runtime, and "w"ritable so that the relocation to CRASHPAD_INFO_SYMBOL can
|
||||
// be performed.
|
||||
.section .note.crashpad.info,"aw",%note
|
||||
.balign NOTE_ALIGN
|
||||
.globl CRASHPAD_NOTE_REFERENCE
|
||||
.type CRASHPAD_NOTE_REFERENCE, %object
|
||||
CRASHPAD_NOTE_REFERENCE:
|
||||
.long name_end - name // namesz
|
||||
.long desc_end - desc // descsz
|
||||
.long CRASHPAD_ELF_NOTE_TYPE_CRASHPAD_INFO // type
|
||||
name:
|
||||
.asciz CRASHPAD_ELF_NOTE_NAME
|
||||
name_end:
|
||||
.balign NOTE_ALIGN
|
||||
desc:
|
||||
.quad CRASHPAD_INFO_SYMBOL
|
||||
desc_end:
|
||||
.size CRASHPAD_NOTE_REFERENCE, .-CRASHPAD_NOTE_REFERENCE
|
@ -27,6 +27,7 @@
|
||||
#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"
|
||||
|
||||
@ -163,14 +164,14 @@ void ReadThisExecutableInTarget(ProcessType process,
|
||||
ElfImageReader::NoteReader::Result::kNoMoreNotes);
|
||||
|
||||
// Find the note defined in elf_image_reader_test_note.S.
|
||||
constexpr char kCrashpadNoteName[] = "Crashpad";
|
||||
constexpr ElfImageReader::NoteReader::NoteType kCrashpadNoteType = 1;
|
||||
constexpr uint32_t kCrashpadNoteDesc = 42;
|
||||
notes = reader.NotesWithNameAndType(kCrashpadNoteName, kCrashpadNoteType, -1);
|
||||
notes = reader.NotesWithNameAndType(
|
||||
CRASHPAD_ELF_NOTE_NAME, CRASHPAD_ELF_NOTE_TYPE_SNAPSHOT_TEST, -1);
|
||||
ASSERT_EQ(notes->NextNote(¬e_name, ¬e_type, ¬e_desc),
|
||||
ElfImageReader::NoteReader::Result::kSuccess);
|
||||
EXPECT_EQ(note_name, kCrashpadNoteName);
|
||||
EXPECT_EQ(note_type, kCrashpadNoteType);
|
||||
EXPECT_EQ(note_name, CRASHPAD_ELF_NOTE_NAME);
|
||||
EXPECT_EQ(note_type,
|
||||
implicit_cast<unsigned int>(CRASHPAD_ELF_NOTE_TYPE_SNAPSHOT_TEST));
|
||||
EXPECT_EQ(note_desc.size(), sizeof(kCrashpadNoteDesc));
|
||||
EXPECT_EQ(*reinterpret_cast<decltype(kCrashpadNoteDesc)*>(¬e_desc[0]),
|
||||
kCrashpadNoteDesc);
|
||||
|
@ -12,6 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "util/misc/elf_note_types.h"
|
||||
|
||||
#define NOTE_ALIGN 4
|
||||
.section .note.crashpad.test,"a",%note
|
||||
.balign NOTE_ALIGN
|
||||
@ -19,9 +21,9 @@
|
||||
testnote:
|
||||
.long name_end - name // namesz
|
||||
.long desc_end - desc // descsz
|
||||
.long 1 // type
|
||||
.long CRASHPAD_ELF_NOTE_TYPE_SNAPSHOT_TEST // type
|
||||
name:
|
||||
.ascii "Crashpad\0"
|
||||
.asciz CRASHPAD_ELF_NOTE_NAME
|
||||
name_end:
|
||||
.balign NOTE_ALIGN
|
||||
desc:
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "snapshot/crashpad_types/image_annotation_reader.h"
|
||||
#include "util/misc/elf_note_types.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace internal {
|
||||
@ -45,17 +46,25 @@ bool ModuleSnapshotLinux::Initialize(
|
||||
elf_reader_ = process_reader_module.elf_reader;
|
||||
type_ = process_reader_module.type;
|
||||
|
||||
// The data payload is only sizeof(VMAddress) in the note, but add a bit to
|
||||
// account for the name, header, and padding.
|
||||
constexpr ssize_t kMaxNoteSize = 256;
|
||||
std::unique_ptr<ElfImageReader::NoteReader> notes =
|
||||
elf_reader_->NotesWithNameAndType(CRASHPAD_ELF_NOTE_NAME,
|
||||
CRASHPAD_ELF_NOTE_TYPE_CRASHPAD_INFO,
|
||||
kMaxNoteSize);
|
||||
std::string desc;
|
||||
VMAddress info_address;
|
||||
VMSize info_size;
|
||||
if (elf_reader_->GetDynamicSymbol(
|
||||
"g_crashpad_info", &info_address, &info_size)) {
|
||||
ProcessMemoryRange range;
|
||||
if (range.Initialize(*elf_reader_->Memory()) &&
|
||||
range.RestrictRange(info_address, info_size)) {
|
||||
auto info = std::make_unique<CrashpadInfoReader>();
|
||||
if (info->Initialize(&range, info_address)) {
|
||||
crashpad_info_ = std::move(info);
|
||||
}
|
||||
if (notes->NextNote(nullptr, nullptr, &desc) ==
|
||||
ElfImageReader::NoteReader::Result::kSuccess) {
|
||||
info_address = *reinterpret_cast<VMAddress*>(&desc[0]);
|
||||
}
|
||||
|
||||
ProcessMemoryRange range;
|
||||
if (range.Initialize(*elf_reader_->Memory())) {
|
||||
auto info = std::make_unique<CrashpadInfoReader>();
|
||||
if (info->Initialize(&range, info_address)) {
|
||||
crashpad_info_ = std::move(info);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,6 +85,7 @@ static_library("util") {
|
||||
"misc/as_underlying_type.h",
|
||||
"misc/capture_context.h",
|
||||
"misc/clock.h",
|
||||
"misc/elf_note_types.h",
|
||||
"misc/from_pointer_cast.h",
|
||||
"misc/implicit_cast.h",
|
||||
"misc/initialization_state.h",
|
||||
|
34
util/misc/elf_note_types.h
Normal file
34
util/misc/elf_note_types.h
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2018 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.
|
||||
|
||||
#ifndef CRASHPAD_UTIL_MISC_ELF_NOTE_TYPES_H_
|
||||
#define CRASHPAD_UTIL_MISC_ELF_NOTE_TYPES_H_
|
||||
|
||||
// This header defines types of ELF "notes" that are embedded sections. These
|
||||
// can be read by ElfImageReader in the snapshot library, and are created in
|
||||
// client modules. All notes used by Crashpad use the name "Crashpad" and one of
|
||||
// the types defined here. Note that this file is #included into .S files, so
|
||||
// must be relatively plain (no C++ features).
|
||||
|
||||
#define CRASHPAD_ELF_NOTE_NAME "Crashpad"
|
||||
|
||||
// Used by ElfImageReader for testing purposes.
|
||||
#define CRASHPAD_ELF_NOTE_TYPE_SNAPSHOT_TEST 1
|
||||
|
||||
// Used by the client library to stash a pointer to the CrashpadInfo structure
|
||||
// for retrieval by the module snapshot. 'OFNI' == 0x4f464e49 which appears as
|
||||
// "INFO" in readelf -x.
|
||||
#define CRASHPAD_ELF_NOTE_TYPE_CRASHPAD_INFO 0x4f464e49
|
||||
|
||||
#endif // CRASHPAD_UTIL_MISC_ELF_NOTE_TYPES_H_
|
@ -133,6 +133,7 @@
|
||||
'misc/clock_mac.cc',
|
||||
'misc/clock_posix.cc',
|
||||
'misc/clock_win.cc',
|
||||
'misc/elf_note_types.h',
|
||||
'misc/from_pointer_cast.h',
|
||||
'misc/implicit_cast.h',
|
||||
'misc/initialization_state.h',
|
||||
|
Loading…
x
Reference in New Issue
Block a user