зеркало из https://github.com/mozilla/gecko-dev.git
bug 1069556 - sync to Breakpad c53ed143108948eb7e2d7ee77dc8c0d92050ce7c. r=glandium, benwa
This commit contains a few things: * Update our copy of google-breakpad to upstream c53ed143108948eb7e2d7ee77dc8c0d92050ce7c * Get rid of all but one local patch, fold a few related local patches into one * Misc build fixup to sync with upstream--adding a few new moz.build files, source files * The final bits of unhooking Breakpad from the profiler: ** Revert to only building toolkit/crashreporter if MOZ_CRASHREPORTER. ** Stop building bits of Breakpad that we only needed for the profiler. ** Remove a few bits of profiler code that were used to interface with Breakpad. ** Remove toolkit/crashreporter/breakpad-logging, which was only used to suppress Breakpad logging for the in-process stackwalker. * Upstream removed their Android-compat sys/ucontext.h because the Android NDK added it, but the bionic we're using for Gonk builds is too old, so add a copy of the previous version of those files to toolkit/crashreporter/gonk-include to keep Gonk building. * Consolidate moz.build files under toolkit/crashreporter/google-breakpad/client/linux --HG-- rename : toolkit/crashreporter/google-breakpad/src/common/pathname_stripper.h => toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.h rename : toolkit/crashreporter/google-breakpad/src/common/pathname_stripper_unittest.cc => toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper_unittest.cc extra : histedit_source : 43e65f5432657f548cac5aa7936461e58454c3b6%2C7b56ccc79d9d58ebde0583d920f3593e25212621 extra : rebase_source : f6dbfb8fb2ba5b27e63b26d57c404962679c7a76 extra : commitid : DMQlXPms868 extra : source : 09fd4f3ab6e764016fe073efb226f03b5969af59 extra : intermediate-source : 16f9d3a6d2ef6a6efd088e3b8eff0a4723daef8f
This commit is contained in:
Родитель
f2d72aa588
Коммит
ea6f9a1958
|
@ -37,8 +37,11 @@ TEST_HARNESS_BINS += \
|
|||
$(NULL)
|
||||
endif
|
||||
|
||||
# The fileid utility depends on mozglue. See bug 1069556.
|
||||
ifeq ($(OS_ARCH),Darwin)
|
||||
TEST_HARNESS_BINS += fix_macosx_stack.py
|
||||
TEST_HARNESS_BINS += \
|
||||
fix_macosx_stack.py \
|
||||
$(DLL_PREFIX)mozglue$(DLL_SUFFIX)
|
||||
endif
|
||||
|
||||
ifeq ($(OS_ARCH),Linux)
|
||||
|
|
|
@ -21,9 +21,8 @@ if CONFIG['OS_ARCH'] == 'Darwin':
|
|||
if CONFIG['OS_ARCH'] == 'Linux' or CONFIG['OS_ARCH'] == 'Darwin':
|
||||
USE_LIBS += [
|
||||
'breakpad_common_s',
|
||||
'breakpad_logging',
|
||||
]
|
||||
LOCAL_INCLUDES += [
|
||||
'/toolkit/crashreporter/google-breakpad/src',
|
||||
]
|
||||
Program('fileid')
|
||||
GeckoProgram('fileid', linkage=None)
|
||||
|
|
|
@ -449,13 +449,15 @@ tail =
|
|||
|
||||
""" + "\n".join(testlines))
|
||||
|
||||
def assertTestResult(self, expected, shuffle=False, verbose=False):
|
||||
def assertTestResult(self, expected, shuffle=False, verbose=False,
|
||||
symbolsPath=None):
|
||||
"""
|
||||
Assert that self.x.runTests with manifest=self.manifest
|
||||
returns |expected|.
|
||||
"""
|
||||
self.assertEquals(expected,
|
||||
self.x.runTests(xpcshellBin,
|
||||
symbolsPath=symbolsPath,
|
||||
manifest=self.manifest,
|
||||
mozInfo=mozinfo.info,
|
||||
shuffle=shuffle,
|
||||
|
@ -525,6 +527,14 @@ tail =
|
|||
"""
|
||||
When an assertion is hit, we should produce a useful stack.
|
||||
"""
|
||||
# Passing symbolsPath will cause the stack fixer to use
|
||||
# fix_stack_using_bpsyms and exercise the fileid utility in
|
||||
# this test.
|
||||
symbolsPath = None
|
||||
candidate_path = os.path.join(build_obj.distdir, 'crashreporter-symbols')
|
||||
if os.path.isdir(candidate_path):
|
||||
symbolsPath = candidate_path
|
||||
|
||||
self.writeFile("test_assert.js", '''
|
||||
add_test(function test_asserts_immediately() {
|
||||
Components.classes["@mozilla.org/xpcom/debug;1"]
|
||||
|
@ -535,8 +545,7 @@ tail =
|
|||
''')
|
||||
|
||||
self.writeManifest(["test_assert.js"])
|
||||
|
||||
self.assertTestResult(False)
|
||||
self.assertTestResult(False, symbolsPath=symbolsPath)
|
||||
|
||||
self.assertInLog("###!!! ASSERTION")
|
||||
log_lines = self.log.getvalue().splitlines()
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
ifeq ($(OS_TARGET),Android)
|
||||
# NDK5 workarounds
|
||||
TARGET_LOCAL_INCLUDES = \
|
||||
-I$(topsrcdir)/toolkit/crashreporter/google-breakpad/src/common/android/include/ \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
check::
|
||||
$(PYTHON) $(srcdir)/tools/unit-symbolstore.py
|
|
@ -1,16 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BreakpadLogging.h"
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// An output stream that acts like /dev/null and drops all output directed to it
|
||||
// Passing 0 here causes the ostream to enter an error state, and so it silently
|
||||
// drops all output directed to it.
|
||||
std::ostream gNullStream(0);
|
||||
|
||||
} // namespace mozilla
|
|
@ -1,20 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BreakpadLogging_h
|
||||
#define BreakpadLogging_h
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// An output stream that acts like /dev/null and drops all output directed to it
|
||||
extern std::ostream gNullStream;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
// Override the breakpad info stream to disable INFO logs
|
||||
#define BPLOG_INFO_STREAM mozilla::gNullStream
|
||||
|
||||
#endif // BreakpadLogging_h
|
|
@ -1,16 +0,0 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'BreakpadLogging.cpp',
|
||||
]
|
||||
|
||||
Library('breakpad_logging')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ('Toolkit', 'Breakpad Integration')
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,526 +0,0 @@
|
|||
# HG changeset patch
|
||||
# User Ted Mielczarek <ted@mielczarek.org>
|
||||
# Date 1352220493 18000
|
||||
# Node ID c3b1109dd392c16a9fe4e85da693010966dbbf0b
|
||||
# Parent 03db269a2868503cca9e80f62ce676aabbf967fd
|
||||
Add APIs for querying Module data
|
||||
R=glandium at https://breakpad.appspot.com/511003/
|
||||
|
||||
diff --git a/src/common/module.cc b/src/common/module.cc
|
||||
--- a/src/common/module.cc
|
||||
+++ b/src/common/module.cc
|
||||
@@ -58,17 +58,17 @@
|
||||
|
||||
Module::~Module() {
|
||||
for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it)
|
||||
delete it->second;
|
||||
for (FunctionSet::iterator it = functions_.begin();
|
||||
it != functions_.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
- for (vector<StackFrameEntry *>::iterator it = stack_frame_entries_.begin();
|
||||
+ for (StackFrameEntrySet::iterator it = stack_frame_entries_.begin();
|
||||
it != stack_frame_entries_.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
for (ExternSet::iterator it = externs_.begin(); it != externs_.end(); ++it)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
void Module::SetLoadAddress(Address address) {
|
||||
@@ -88,39 +88,84 @@
|
||||
}
|
||||
|
||||
void Module::AddFunctions(vector<Function *>::iterator begin,
|
||||
vector<Function *>::iterator end) {
|
||||
for (vector<Function *>::iterator it = begin; it != end; ++it)
|
||||
AddFunction(*it);
|
||||
}
|
||||
|
||||
-void Module::AddStackFrameEntry(StackFrameEntry *stack_frame_entry) {
|
||||
- stack_frame_entries_.push_back(stack_frame_entry);
|
||||
+void Module::AddStackFrameEntry(StackFrameEntry* stack_frame_entry) {
|
||||
+ std::pair<StackFrameEntrySet::iterator,bool> ret =
|
||||
+ stack_frame_entries_.insert(stack_frame_entry);
|
||||
+ if (!ret.second) {
|
||||
+ // Free the duplicate that was not inserted because this Module
|
||||
+ // now owns it.
|
||||
+ delete stack_frame_entry;
|
||||
+ }
|
||||
}
|
||||
|
||||
void Module::AddExtern(Extern *ext) {
|
||||
std::pair<ExternSet::iterator,bool> ret = externs_.insert(ext);
|
||||
if (!ret.second) {
|
||||
// Free the duplicate that was not inserted because this Module
|
||||
// now owns it.
|
||||
delete ext;
|
||||
}
|
||||
}
|
||||
|
||||
void Module::GetFunctions(vector<Function *> *vec,
|
||||
vector<Function *>::iterator i) {
|
||||
vec->insert(i, functions_.begin(), functions_.end());
|
||||
}
|
||||
|
||||
+template<typename T>
|
||||
+bool EntryContainsAddress(T entry, Module::Address address) {
|
||||
+ return entry->address <= address && address < entry->address + entry->size;
|
||||
+}
|
||||
+
|
||||
+Module::Function* Module::FindFunctionByAddress(Address address) {
|
||||
+ Function search;
|
||||
+ search.address = address;
|
||||
+ // Ensure that name always sorts higher than the function name,
|
||||
+ // so that upper_bound always returns the function just after
|
||||
+ // the function containing this address.
|
||||
+ search.name = "\xFF";
|
||||
+ FunctionSet::iterator it = functions_.upper_bound(&search);
|
||||
+ if (it == functions_.begin())
|
||||
+ return NULL;
|
||||
+
|
||||
+ it--;
|
||||
+
|
||||
+ if (EntryContainsAddress(*it, address))
|
||||
+ return *it;
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
void Module::GetExterns(vector<Extern *> *vec,
|
||||
vector<Extern *>::iterator i) {
|
||||
vec->insert(i, externs_.begin(), externs_.end());
|
||||
}
|
||||
|
||||
+Module::Extern* Module::FindExternByAddress(Address address) {
|
||||
+ Extern search;
|
||||
+ search.address = address;
|
||||
+ ExternSet::iterator it = externs_.upper_bound(&search);
|
||||
+
|
||||
+ if (it == externs_.begin())
|
||||
+ return NULL;
|
||||
+
|
||||
+ it--;
|
||||
+ if ((*it)->address > address)
|
||||
+ return NULL;
|
||||
+
|
||||
+ return *it;
|
||||
+}
|
||||
+
|
||||
Module::File *Module::FindFile(const string &name) {
|
||||
// A tricky bit here. The key of each map entry needs to be a
|
||||
// pointer to the entry's File's name string. This means that we
|
||||
// can't do the initial lookup with any operation that would create
|
||||
// an empty entry for us if the name isn't found (like, say,
|
||||
// operator[] or insert do), because such a created entry's key will
|
||||
// be a pointer the string passed as our argument. Since the key of
|
||||
// a map's value type is const, we can't fix it up once we've
|
||||
@@ -150,18 +195,35 @@
|
||||
}
|
||||
|
||||
void Module::GetFiles(vector<File *> *vec) {
|
||||
vec->clear();
|
||||
for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it)
|
||||
vec->push_back(it->second);
|
||||
}
|
||||
|
||||
-void Module::GetStackFrameEntries(vector<StackFrameEntry *> *vec) {
|
||||
- *vec = stack_frame_entries_;
|
||||
+void Module::GetStackFrameEntries(vector<StackFrameEntry *>* vec) {
|
||||
+ vec->clear();
|
||||
+ vec->insert(vec->begin(), stack_frame_entries_.begin(),
|
||||
+ stack_frame_entries_.end());
|
||||
+}
|
||||
+
|
||||
+Module::StackFrameEntry* Module::FindStackFrameEntryByAddress(Address address) {
|
||||
+ StackFrameEntry search;
|
||||
+ search.address = address;
|
||||
+ StackFrameEntrySet::iterator it = stack_frame_entries_.upper_bound(&search);
|
||||
+
|
||||
+ if (it == stack_frame_entries_.begin())
|
||||
+ return NULL;
|
||||
+
|
||||
+ it--;
|
||||
+ if (EntryContainsAddress(*it, address))
|
||||
+ return *it;
|
||||
+
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
void Module::AssignSourceIds() {
|
||||
// First, give every source file an id of -1.
|
||||
for (FileByNameMap::iterator file_it = files_.begin();
|
||||
file_it != files_.end(); ++file_it) {
|
||||
file_it->second->source_id = -1;
|
||||
}
|
||||
@@ -256,17 +318,17 @@
|
||||
stream << "PUBLIC " << hex
|
||||
<< (ext->address - load_address_) << " 0 "
|
||||
<< ext->name << dec << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (symbol_data != NO_CFI) {
|
||||
// Write out 'STACK CFI INIT' and 'STACK CFI' records.
|
||||
- vector<StackFrameEntry *>::const_iterator frame_it;
|
||||
+ StackFrameEntrySet::const_iterator frame_it;
|
||||
for (frame_it = stack_frame_entries_.begin();
|
||||
frame_it != stack_frame_entries_.end(); ++frame_it) {
|
||||
StackFrameEntry *entry = *frame_it;
|
||||
stream << "STACK CFI INIT " << hex
|
||||
<< (entry->address - load_address_) << " "
|
||||
<< entry->size << " " << dec;
|
||||
if (!stream.good()
|
||||
|| !WriteRuleMap(entry->initial_rules, stream))
|
||||
diff --git a/src/common/module.h b/src/common/module.h
|
||||
--- a/src/common/module.h
|
||||
+++ b/src/common/module.h
|
||||
@@ -164,16 +164,23 @@
|
||||
|
||||
struct ExternCompare {
|
||||
bool operator() (const Extern *lhs,
|
||||
const Extern *rhs) const {
|
||||
return lhs->address < rhs->address;
|
||||
}
|
||||
};
|
||||
|
||||
+ struct StackFrameEntryCompare {
|
||||
+ bool operator() (const StackFrameEntry* lhs,
|
||||
+ const StackFrameEntry* rhs) const {
|
||||
+ return lhs->address < rhs->address;
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
// Create a new module with the given name, operating system,
|
||||
// architecture, and ID string.
|
||||
Module(const string &name, const string &os, const string &architecture,
|
||||
const string &id);
|
||||
~Module();
|
||||
|
||||
// Set the module's load address to LOAD_ADDRESS; addresses given
|
||||
// for functions and lines will be written to the Breakpad symbol
|
||||
@@ -223,37 +230,49 @@
|
||||
|
||||
// Insert pointers to the functions added to this module at I in
|
||||
// VEC. The pointed-to Functions are still owned by this module.
|
||||
// (Since this is effectively a copy of the function list, this is
|
||||
// mostly useful for testing; other uses should probably get a more
|
||||
// appropriate interface.)
|
||||
void GetFunctions(vector<Function *> *vec, vector<Function *>::iterator i);
|
||||
|
||||
+ // If this module has a function at ADDRESS, return a pointer to it.
|
||||
+ // Otherwise, return NULL.
|
||||
+ Function* FindFunctionByAddress(Address address);
|
||||
+
|
||||
// Insert pointers to the externs added to this module at I in
|
||||
// VEC. The pointed-to Externs are still owned by this module.
|
||||
// (Since this is effectively a copy of the extern list, this is
|
||||
// mostly useful for testing; other uses should probably get a more
|
||||
// appropriate interface.)
|
||||
void GetExterns(vector<Extern *> *vec, vector<Extern *>::iterator i);
|
||||
|
||||
+ // If this module has an extern whose base address is less than ADDRESS,
|
||||
+ // return a pointer to it. Otherwise, return NULL.
|
||||
+ Extern* FindExternByAddress(Address address);
|
||||
+
|
||||
// Clear VEC and fill it with pointers to the Files added to this
|
||||
// module, sorted by name. The pointed-to Files are still owned by
|
||||
// this module. (Since this is effectively a copy of the file list,
|
||||
// this is mostly useful for testing; other uses should probably get
|
||||
// a more appropriate interface.)
|
||||
void GetFiles(vector<File *> *vec);
|
||||
|
||||
// Clear VEC and fill it with pointers to the StackFrameEntry
|
||||
// objects that have been added to this module. (Since this is
|
||||
// effectively a copy of the stack frame entry list, this is mostly
|
||||
// useful for testing; other uses should probably get
|
||||
// a more appropriate interface.)
|
||||
void GetStackFrameEntries(vector<StackFrameEntry *> *vec);
|
||||
|
||||
+ // If this module has a StackFrameEntry whose address range covers
|
||||
+ // ADDRESS, return it. Otherwise return NULL.
|
||||
+ StackFrameEntry* FindStackFrameEntryByAddress(Address address);
|
||||
+
|
||||
// Find those files in this module that are actually referred to by
|
||||
// functions' line number data, and assign them source id numbers.
|
||||
// Set the source id numbers for all other files --- unused by the
|
||||
// source line data --- to -1. We do this before writing out the
|
||||
// symbol file, at which point we omit any unused files.
|
||||
void AssignSourceIds();
|
||||
|
||||
// Call AssignSourceIds, and write this module to STREAM in the
|
||||
@@ -299,25 +318,28 @@
|
||||
typedef map<const string *, File *, CompareStringPtrs> FileByNameMap;
|
||||
|
||||
// A set containing Function structures, sorted by address.
|
||||
typedef set<Function *, FunctionCompare> FunctionSet;
|
||||
|
||||
// A set containing Extern structures, sorted by address.
|
||||
typedef set<Extern *, ExternCompare> ExternSet;
|
||||
|
||||
+ // A set containing StackFrameEntry structures, sorted by address.
|
||||
+ typedef set<StackFrameEntry*, StackFrameEntryCompare> StackFrameEntrySet;
|
||||
+
|
||||
// The module owns all the files and functions that have been added
|
||||
// to it; destroying the module frees the Files and Functions these
|
||||
// point to.
|
||||
FileByNameMap files_; // This module's source files.
|
||||
FunctionSet functions_; // This module's functions.
|
||||
|
||||
// The module owns all the call frame info entries that have been
|
||||
// added to it.
|
||||
- vector<StackFrameEntry *> stack_frame_entries_;
|
||||
+ StackFrameEntrySet stack_frame_entries_;
|
||||
|
||||
// The module owns all the externs that have been added to it;
|
||||
// destroying the module frees the Externs these point to.
|
||||
ExternSet externs_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc
|
||||
--- a/src/common/module_unittest.cc
|
||||
+++ b/src/common/module_unittest.cc
|
||||
@@ -329,63 +329,63 @@
|
||||
entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] =
|
||||
"I think I know";
|
||||
m.AddStackFrameEntry(entry3);
|
||||
|
||||
// Check that Write writes STACK CFI records properly.
|
||||
m.Write(s, ALL_SYMBOL_DATA);
|
||||
string contents = s.str();
|
||||
EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
|
||||
- "STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n"
|
||||
- "STACK CFI INIT 8064f3af5e067e38 de2a5ee55509407"
|
||||
- " .cfa: I think that I shall never see"
|
||||
- " cannoli: a tree whose hungry mouth is prest"
|
||||
- " stromboli: a poem lovely as a tree\n"
|
||||
"STACK CFI INIT 5e8d0db0a7075c6c 1c7edb12a7aea229"
|
||||
" .cfa: Whose woods are these\n"
|
||||
"STACK CFI 36682fad3763ffff"
|
||||
" .cfa: I think I know"
|
||||
" stromboli: his house is in\n"
|
||||
"STACK CFI 47ceb0f63c269d7f"
|
||||
" calzone: the village though"
|
||||
- " cannoli: he will not see me stopping here\n",
|
||||
+ " cannoli: he will not see me stopping here\n"
|
||||
+ "STACK CFI INIT 8064f3af5e067e38 de2a5ee55509407"
|
||||
+ " .cfa: I think that I shall never see"
|
||||
+ " cannoli: a tree whose hungry mouth is prest"
|
||||
+ " stromboli: a poem lovely as a tree\n"
|
||||
+ "STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n",
|
||||
contents.c_str());
|
||||
|
||||
// Check that GetStackFrameEntries works.
|
||||
vector<Module::StackFrameEntry *> entries;
|
||||
m.GetStackFrameEntries(&entries);
|
||||
ASSERT_EQ(3U, entries.size());
|
||||
// Check first entry.
|
||||
- EXPECT_EQ(0xddb5f41285aa7757ULL, entries[0]->address);
|
||||
- EXPECT_EQ(0x1486493370dc5073ULL, entries[0]->size);
|
||||
- ASSERT_EQ(0U, entries[0]->initial_rules.size());
|
||||
- ASSERT_EQ(0U, entries[0]->rule_changes.size());
|
||||
+ EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[0]->address);
|
||||
+ EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[0]->size);
|
||||
+ Module::RuleMap entry1_initial;
|
||||
+ entry1_initial[".cfa"] = "Whose woods are these";
|
||||
+ EXPECT_THAT(entries[0]->initial_rules, ContainerEq(entry1_initial));
|
||||
+ Module::RuleChangeMap entry1_changes;
|
||||
+ entry1_changes[0x36682fad3763ffffULL][".cfa"] = "I think I know";
|
||||
+ entry1_changes[0x36682fad3763ffffULL]["stromboli"] = "his house is in";
|
||||
+ entry1_changes[0x47ceb0f63c269d7fULL]["calzone"] = "the village though";
|
||||
+ entry1_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
|
||||
+ "he will not see me stopping here";
|
||||
+ EXPECT_THAT(entries[0]->rule_changes, ContainerEq(entry1_changes));
|
||||
// Check second entry.
|
||||
EXPECT_EQ(0x8064f3af5e067e38ULL, entries[1]->address);
|
||||
EXPECT_EQ(0x0de2a5ee55509407ULL, entries[1]->size);
|
||||
ASSERT_EQ(3U, entries[1]->initial_rules.size());
|
||||
Module::RuleMap entry2_initial;
|
||||
entry2_initial[".cfa"] = "I think that I shall never see";
|
||||
entry2_initial["stromboli"] = "a poem lovely as a tree";
|
||||
entry2_initial["cannoli"] = "a tree whose hungry mouth is prest";
|
||||
EXPECT_THAT(entries[1]->initial_rules, ContainerEq(entry2_initial));
|
||||
ASSERT_EQ(0U, entries[1]->rule_changes.size());
|
||||
// Check third entry.
|
||||
- EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[2]->address);
|
||||
- EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[2]->size);
|
||||
- Module::RuleMap entry3_initial;
|
||||
- entry3_initial[".cfa"] = "Whose woods are these";
|
||||
- EXPECT_THAT(entries[2]->initial_rules, ContainerEq(entry3_initial));
|
||||
- Module::RuleChangeMap entry3_changes;
|
||||
- entry3_changes[0x36682fad3763ffffULL][".cfa"] = "I think I know";
|
||||
- entry3_changes[0x36682fad3763ffffULL]["stromboli"] = "his house is in";
|
||||
- entry3_changes[0x47ceb0f63c269d7fULL]["calzone"] = "the village though";
|
||||
- entry3_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
|
||||
- "he will not see me stopping here";
|
||||
- EXPECT_THAT(entries[2]->rule_changes, ContainerEq(entry3_changes));
|
||||
+ EXPECT_EQ(0xddb5f41285aa7757ULL, entries[2]->address);
|
||||
+ EXPECT_EQ(0x1486493370dc5073ULL, entries[2]->size);
|
||||
+ ASSERT_EQ(0U, entries[2]->initial_rules.size());
|
||||
+ ASSERT_EQ(0U, entries[2]->rule_changes.size());
|
||||
}
|
||||
|
||||
TEST(Construct, UniqueFiles) {
|
||||
Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
|
||||
Module::File *file1 = m.FindFile("foo");
|
||||
Module::File *file2 = m.FindFile(string("bar"));
|
||||
Module::File *file3 = m.FindFile(string("foo"));
|
||||
Module::File *file4 = m.FindFile("bar");
|
||||
@@ -483,8 +483,155 @@
|
||||
m.Write(s, ALL_SYMBOL_DATA);
|
||||
string contents = s.str();
|
||||
|
||||
EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
|
||||
MODULE_ID " " MODULE_NAME "\n"
|
||||
"PUBLIC ffff 0 _xyz\n",
|
||||
contents.c_str());
|
||||
}
|
||||
+
|
||||
+TEST(Lookup, Function) {
|
||||
+ Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
|
||||
+
|
||||
+ Module::Function *function1 = new(Module::Function);
|
||||
+ function1->name = "_abc1";
|
||||
+ function1->address = 0x1000;
|
||||
+ function1->size = 0x900;
|
||||
+ function1->parameter_size = 0x0;
|
||||
+
|
||||
+ Module::Function *function2 = new(Module::Function);
|
||||
+ function2->name = "_xyz2";
|
||||
+ function2->address = 0x2000;
|
||||
+ function2->size = 0x900;
|
||||
+ function2->parameter_size = 0x0;
|
||||
+
|
||||
+ Module::Function *function3 = new(Module::Function);
|
||||
+ function3->name = "_def3";
|
||||
+ function3->address = 0x3000;
|
||||
+ function3->size = 0x900;
|
||||
+ function3->parameter_size = 0x0;
|
||||
+
|
||||
+ // Put them in a vector.
|
||||
+ vector<Module::Function *> vec;
|
||||
+ vec.push_back(function1);
|
||||
+ vec.push_back(function2);
|
||||
+ vec.push_back(function3);
|
||||
+
|
||||
+ m.AddFunctions(vec.begin(), vec.end());
|
||||
+
|
||||
+ // Try looking up functions by address.
|
||||
+ Module::Function* f = m.FindFunctionByAddress(0x1000);
|
||||
+ EXPECT_EQ(function1, f);
|
||||
+ f = m.FindFunctionByAddress(0x18FF);
|
||||
+ EXPECT_EQ(function1, f);
|
||||
+
|
||||
+ f = m.FindFunctionByAddress(0x1900);
|
||||
+ EXPECT_EQ((Module::Function*)NULL, f);
|
||||
+ f = m.FindFunctionByAddress(0x1A00);
|
||||
+ EXPECT_EQ((Module::Function*)NULL, f);
|
||||
+
|
||||
+ f = m.FindFunctionByAddress(0x2000);
|
||||
+ EXPECT_EQ(function2, f);
|
||||
+ f = m.FindFunctionByAddress(0x28FF);
|
||||
+ EXPECT_EQ(function2, f);
|
||||
+
|
||||
+ f = m.FindFunctionByAddress(0x3000);
|
||||
+ EXPECT_EQ(function3, f);
|
||||
+ f = m.FindFunctionByAddress(0x38FF);
|
||||
+ EXPECT_EQ(function3, f);
|
||||
+
|
||||
+ f = m.FindFunctionByAddress(0x3900);
|
||||
+ EXPECT_EQ((Module::Function*)NULL, f);
|
||||
+ f = m.FindFunctionByAddress(0x3A00);
|
||||
+ EXPECT_EQ((Module::Function*)NULL, f);
|
||||
+}
|
||||
+
|
||||
+TEST(Lookup, Externs) {
|
||||
+ Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
|
||||
+
|
||||
+ // Two externs.
|
||||
+ Module::Extern* extern1 = new(Module::Extern);
|
||||
+ extern1->address = 0x1000;
|
||||
+ extern1->name = "_abc";
|
||||
+ Module::Extern* extern2 = new(Module::Extern);
|
||||
+ extern2->address = 0x2000;
|
||||
+ extern2->name = "_xyz";
|
||||
+
|
||||
+ m.AddExtern(extern1);
|
||||
+ m.AddExtern(extern2);
|
||||
+
|
||||
+ Module::Extern* e = m.FindExternByAddress(0xFFF);
|
||||
+ EXPECT_EQ((Module::Extern*)NULL, e);
|
||||
+
|
||||
+ e = m.FindExternByAddress(0x1000);
|
||||
+ EXPECT_EQ(extern1, e);
|
||||
+ e = m.FindExternByAddress(0x1900);
|
||||
+ EXPECT_EQ(extern1, e);
|
||||
+ e = m.FindExternByAddress(0x1FFF);
|
||||
+ EXPECT_EQ(extern1, e);
|
||||
+
|
||||
+ e = m.FindExternByAddress(0x2000);
|
||||
+ EXPECT_EQ(extern2, e);
|
||||
+ e = m.FindExternByAddress(0x2900);
|
||||
+ EXPECT_EQ(extern2, e);
|
||||
+ e = m.FindExternByAddress(0xFFFFFFFF);
|
||||
+ EXPECT_EQ(extern2, e);
|
||||
+}
|
||||
+
|
||||
+TEST(Lookup, StackFrameEntries) {
|
||||
+ Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
|
||||
+
|
||||
+ // First STACK CFI entry, with no initial rules or deltas.
|
||||
+ Module::StackFrameEntry *entry1 = new Module::StackFrameEntry();
|
||||
+ entry1->address = 0x2000;
|
||||
+ entry1->size = 0x900;
|
||||
+ m.AddStackFrameEntry(entry1);
|
||||
+
|
||||
+ // Second STACK CFI entry, with initial rules but no deltas.
|
||||
+ Module::StackFrameEntry *entry2 = new Module::StackFrameEntry();
|
||||
+ entry2->address = 0x3000;
|
||||
+ entry2->size = 0x900;
|
||||
+ entry2->initial_rules[".cfa"] = "I think that I shall never see";
|
||||
+ entry2->initial_rules["stromboli"] = "a poem lovely as a tree";
|
||||
+ entry2->initial_rules["cannoli"] = "a tree whose hungry mouth is prest";
|
||||
+ m.AddStackFrameEntry(entry2);
|
||||
+
|
||||
+ // Third STACK CFI entry, with initial rules and deltas.
|
||||
+ Module::StackFrameEntry *entry3 = new Module::StackFrameEntry();
|
||||
+ entry3->address = 0x1000;
|
||||
+ entry3->size = 0x900;
|
||||
+ entry3->initial_rules[".cfa"] = "Whose woods are these";
|
||||
+ entry3->rule_changes[0x47ceb0f63c269d7fULL]["calzone"] =
|
||||
+ "the village though";
|
||||
+ entry3->rule_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
|
||||
+ "he will not see me stopping here";
|
||||
+ entry3->rule_changes[0x36682fad3763ffffULL]["stromboli"] =
|
||||
+ "his house is in";
|
||||
+ entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] =
|
||||
+ "I think I know";
|
||||
+ m.AddStackFrameEntry(entry3);
|
||||
+
|
||||
+ Module::StackFrameEntry* s = m.FindStackFrameEntryByAddress(0x1000);
|
||||
+ EXPECT_EQ(entry3, s);
|
||||
+ s = m.FindStackFrameEntryByAddress(0x18FF);
|
||||
+ EXPECT_EQ(entry3, s);
|
||||
+
|
||||
+ s = m.FindStackFrameEntryByAddress(0x1900);
|
||||
+ EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
|
||||
+ s = m.FindStackFrameEntryByAddress(0x1A00);
|
||||
+ EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
|
||||
+
|
||||
+ s = m.FindStackFrameEntryByAddress(0x2000);
|
||||
+ EXPECT_EQ(entry1, s);
|
||||
+ s = m.FindStackFrameEntryByAddress(0x28FF);
|
||||
+ EXPECT_EQ(entry1, s);
|
||||
+
|
||||
+ s = m.FindStackFrameEntryByAddress(0x3000);
|
||||
+ EXPECT_EQ(entry2, s);
|
||||
+ s = m.FindStackFrameEntryByAddress(0x38FF);
|
||||
+ EXPECT_EQ(entry2, s);
|
||||
+
|
||||
+ s = m.FindStackFrameEntryByAddress(0x3900);
|
||||
+ EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
|
||||
+ s = m.FindStackFrameEntryByAddress(0x3A00);
|
||||
+ EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
|
||||
+}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,212 +0,0 @@
|
|||
# HG changeset patch
|
||||
# User Ted Mielczarek <ted@mielczarek.org>
|
||||
# Date 1362600444 18000
|
||||
# Node ID 0eb3c7ba8a38a269ab975eff3f95a1a5d5d937b9
|
||||
# Parent 6b68e82037b8322fb392cea369d517aeeaaee9d3
|
||||
Stop using dynamic_cast in dwarf2reader
|
||||
Patch by Julian Seward <jseward@acm.org>, R=ted
|
||||
|
||||
diff --git a/src/common/dwarf/dwarf2reader.cc b/src/common/dwarf/dwarf2reader.cc
|
||||
--- a/src/common/dwarf/dwarf2reader.cc
|
||||
+++ b/src/common/dwarf/dwarf2reader.cc
|
||||
@@ -887,68 +887,80 @@
|
||||
|
||||
// If this is a base+offset rule, change its base register to REG.
|
||||
// Otherwise, do nothing. (Ugly, but required for DW_CFA_def_cfa_register.)
|
||||
virtual void SetBaseRegister(unsigned reg) { }
|
||||
|
||||
// If this is a base+offset rule, change its offset to OFFSET. Otherwise,
|
||||
// do nothing. (Ugly, but required for DW_CFA_def_cfa_offset.)
|
||||
virtual void SetOffset(long long offset) { }
|
||||
+
|
||||
+ // A RTTI workaround, to make it possible to implement equality
|
||||
+ // comparisons on classes derived from this one.
|
||||
+ enum CFIRTag {
|
||||
+ CFIR_UNDEFINED_RULE,
|
||||
+ CFIR_SAME_VALUE_RULE,
|
||||
+ CFIR_OFFSET_RULE,
|
||||
+ CFIR_VAL_OFFSET_RULE,
|
||||
+ CFIR_REGISTER_RULE,
|
||||
+ CFIR_EXPRESSION_RULE,
|
||||
+ CFIR_VAL_EXPRESSION_RULE
|
||||
+ };
|
||||
+
|
||||
+ // Produce the tag that identifies the child class of this object.
|
||||
+ virtual CFIRTag getTag() const = 0;
|
||||
};
|
||||
|
||||
// Rule: the value the register had in the caller cannot be recovered.
|
||||
class CallFrameInfo::UndefinedRule: public CallFrameInfo::Rule {
|
||||
public:
|
||||
UndefinedRule() { }
|
||||
~UndefinedRule() { }
|
||||
+ CFIRTag getTag() const { return CFIR_UNDEFINED_RULE; }
|
||||
bool Handle(Handler *handler, uint64 address, int reg) const {
|
||||
return handler->UndefinedRule(address, reg);
|
||||
}
|
||||
bool operator==(const Rule &rhs) const {
|
||||
- // dynamic_cast is allowed by the Google C++ Style Guide, if the use has
|
||||
- // been carefully considered; cheap RTTI-like workarounds are forbidden.
|
||||
- const UndefinedRule *our_rhs = dynamic_cast<const UndefinedRule *>(&rhs);
|
||||
- return (our_rhs != NULL);
|
||||
+ if (rhs.getTag() != CFIR_UNDEFINED_RULE) return false;
|
||||
+ return true;
|
||||
}
|
||||
Rule *Copy() const { return new UndefinedRule(*this); }
|
||||
};
|
||||
|
||||
// Rule: the register's value is the same as that it had in the caller.
|
||||
class CallFrameInfo::SameValueRule: public CallFrameInfo::Rule {
|
||||
public:
|
||||
SameValueRule() { }
|
||||
~SameValueRule() { }
|
||||
+ CFIRTag getTag() const { return CFIR_SAME_VALUE_RULE; }
|
||||
bool Handle(Handler *handler, uint64 address, int reg) const {
|
||||
return handler->SameValueRule(address, reg);
|
||||
}
|
||||
bool operator==(const Rule &rhs) const {
|
||||
- // dynamic_cast is allowed by the Google C++ Style Guide, if the use has
|
||||
- // been carefully considered; cheap RTTI-like workarounds are forbidden.
|
||||
- const SameValueRule *our_rhs = dynamic_cast<const SameValueRule *>(&rhs);
|
||||
- return (our_rhs != NULL);
|
||||
+ if (rhs.getTag() != CFIR_SAME_VALUE_RULE) return false;
|
||||
+ return true;
|
||||
}
|
||||
Rule *Copy() const { return new SameValueRule(*this); }
|
||||
};
|
||||
|
||||
// Rule: the register is saved at OFFSET from BASE_REGISTER. BASE_REGISTER
|
||||
// may be CallFrameInfo::Handler::kCFARegister.
|
||||
class CallFrameInfo::OffsetRule: public CallFrameInfo::Rule {
|
||||
public:
|
||||
OffsetRule(int base_register, long offset)
|
||||
: base_register_(base_register), offset_(offset) { }
|
||||
~OffsetRule() { }
|
||||
+ CFIRTag getTag() const { return CFIR_OFFSET_RULE; }
|
||||
bool Handle(Handler *handler, uint64 address, int reg) const {
|
||||
return handler->OffsetRule(address, reg, base_register_, offset_);
|
||||
}
|
||||
bool operator==(const Rule &rhs) const {
|
||||
- // dynamic_cast is allowed by the Google C++ Style Guide, if the use has
|
||||
- // been carefully considered; cheap RTTI-like workarounds are forbidden.
|
||||
- const OffsetRule *our_rhs = dynamic_cast<const OffsetRule *>(&rhs);
|
||||
- return (our_rhs &&
|
||||
- base_register_ == our_rhs->base_register_ &&
|
||||
+ if (rhs.getTag() != CFIR_OFFSET_RULE) return false;
|
||||
+ const OffsetRule *our_rhs = static_cast<const OffsetRule *>(&rhs);
|
||||
+ return (base_register_ == our_rhs->base_register_ &&
|
||||
offset_ == our_rhs->offset_);
|
||||
}
|
||||
Rule *Copy() const { return new OffsetRule(*this); }
|
||||
// We don't actually need SetBaseRegister or SetOffset here, since they
|
||||
// are only ever applied to CFA rules, for DW_CFA_def_cfa_offset, and it
|
||||
// doesn't make sense to use OffsetRule for computing the CFA: it
|
||||
// computes the address at which a register is saved, not a value.
|
||||
private:
|
||||
@@ -959,90 +971,89 @@
|
||||
// Rule: the value the register had in the caller is the value of
|
||||
// BASE_REGISTER plus offset. BASE_REGISTER may be
|
||||
// CallFrameInfo::Handler::kCFARegister.
|
||||
class CallFrameInfo::ValOffsetRule: public CallFrameInfo::Rule {
|
||||
public:
|
||||
ValOffsetRule(int base_register, long offset)
|
||||
: base_register_(base_register), offset_(offset) { }
|
||||
~ValOffsetRule() { }
|
||||
+ CFIRTag getTag() const { return CFIR_VAL_OFFSET_RULE; }
|
||||
bool Handle(Handler *handler, uint64 address, int reg) const {
|
||||
return handler->ValOffsetRule(address, reg, base_register_, offset_);
|
||||
}
|
||||
bool operator==(const Rule &rhs) const {
|
||||
- // dynamic_cast is allowed by the Google C++ Style Guide, if the use has
|
||||
- // been carefully considered; cheap RTTI-like workarounds are forbidden.
|
||||
- const ValOffsetRule *our_rhs = dynamic_cast<const ValOffsetRule *>(&rhs);
|
||||
- return (our_rhs &&
|
||||
- base_register_ == our_rhs->base_register_ &&
|
||||
+ if (rhs.getTag() != CFIR_VAL_OFFSET_RULE) return false;
|
||||
+ const ValOffsetRule *our_rhs = static_cast<const ValOffsetRule *>(&rhs);
|
||||
+ return (base_register_ == our_rhs->base_register_ &&
|
||||
offset_ == our_rhs->offset_);
|
||||
}
|
||||
Rule *Copy() const { return new ValOffsetRule(*this); }
|
||||
void SetBaseRegister(unsigned reg) { base_register_ = reg; }
|
||||
void SetOffset(long long offset) { offset_ = offset; }
|
||||
private:
|
||||
int base_register_;
|
||||
long offset_;
|
||||
};
|
||||
|
||||
// Rule: the register has been saved in another register REGISTER_NUMBER_.
|
||||
class CallFrameInfo::RegisterRule: public CallFrameInfo::Rule {
|
||||
public:
|
||||
explicit RegisterRule(int register_number)
|
||||
: register_number_(register_number) { }
|
||||
~RegisterRule() { }
|
||||
+ CFIRTag getTag() const { return CFIR_REGISTER_RULE; }
|
||||
bool Handle(Handler *handler, uint64 address, int reg) const {
|
||||
return handler->RegisterRule(address, reg, register_number_);
|
||||
}
|
||||
bool operator==(const Rule &rhs) const {
|
||||
- // dynamic_cast is allowed by the Google C++ Style Guide, if the use has
|
||||
- // been carefully considered; cheap RTTI-like workarounds are forbidden.
|
||||
- const RegisterRule *our_rhs = dynamic_cast<const RegisterRule *>(&rhs);
|
||||
- return (our_rhs && register_number_ == our_rhs->register_number_);
|
||||
+ if (rhs.getTag() != CFIR_REGISTER_RULE) return false;
|
||||
+ const RegisterRule *our_rhs = static_cast<const RegisterRule *>(&rhs);
|
||||
+ return (register_number_ == our_rhs->register_number_);
|
||||
}
|
||||
Rule *Copy() const { return new RegisterRule(*this); }
|
||||
private:
|
||||
int register_number_;
|
||||
};
|
||||
|
||||
// Rule: EXPRESSION evaluates to the address at which the register is saved.
|
||||
class CallFrameInfo::ExpressionRule: public CallFrameInfo::Rule {
|
||||
public:
|
||||
explicit ExpressionRule(const string &expression)
|
||||
: expression_(expression) { }
|
||||
~ExpressionRule() { }
|
||||
+ CFIRTag getTag() const { return CFIR_EXPRESSION_RULE; }
|
||||
bool Handle(Handler *handler, uint64 address, int reg) const {
|
||||
return handler->ExpressionRule(address, reg, expression_);
|
||||
}
|
||||
bool operator==(const Rule &rhs) const {
|
||||
- // dynamic_cast is allowed by the Google C++ Style Guide, if the use has
|
||||
- // been carefully considered; cheap RTTI-like workarounds are forbidden.
|
||||
- const ExpressionRule *our_rhs = dynamic_cast<const ExpressionRule *>(&rhs);
|
||||
- return (our_rhs && expression_ == our_rhs->expression_);
|
||||
+ if (rhs.getTag() != CFIR_EXPRESSION_RULE) return false;
|
||||
+ const ExpressionRule *our_rhs = static_cast<const ExpressionRule *>(&rhs);
|
||||
+ return (expression_ == our_rhs->expression_);
|
||||
}
|
||||
Rule *Copy() const { return new ExpressionRule(*this); }
|
||||
private:
|
||||
string expression_;
|
||||
};
|
||||
|
||||
// Rule: EXPRESSION evaluates to the address at which the register is saved.
|
||||
class CallFrameInfo::ValExpressionRule: public CallFrameInfo::Rule {
|
||||
public:
|
||||
explicit ValExpressionRule(const string &expression)
|
||||
: expression_(expression) { }
|
||||
~ValExpressionRule() { }
|
||||
+ CFIRTag getTag() const { return CFIR_VAL_EXPRESSION_RULE; }
|
||||
bool Handle(Handler *handler, uint64 address, int reg) const {
|
||||
return handler->ValExpressionRule(address, reg, expression_);
|
||||
}
|
||||
bool operator==(const Rule &rhs) const {
|
||||
- // dynamic_cast is allowed by the Google C++ Style Guide, if the use has
|
||||
- // been carefully considered; cheap RTTI-like workarounds are forbidden.
|
||||
+ if (rhs.getTag() != CFIR_VAL_EXPRESSION_RULE) return false;
|
||||
const ValExpressionRule *our_rhs =
|
||||
- dynamic_cast<const ValExpressionRule *>(&rhs);
|
||||
- return (our_rhs && expression_ == our_rhs->expression_);
|
||||
+ static_cast<const ValExpressionRule *>(&rhs);
|
||||
+ return (expression_ == our_rhs->expression_);
|
||||
}
|
||||
Rule *Copy() const { return new ValExpressionRule(*this); }
|
||||
private:
|
||||
string expression_;
|
||||
};
|
||||
|
||||
// A map from register numbers to rules.
|
||||
class CallFrameInfo::RuleMap {
|
|
@ -1,27 +0,0 @@
|
|||
changeset: 124512:8b366545161d
|
||||
user: Julian Seward <jseward@acm.org>
|
||||
date: Sun Mar 10 23:00:23 2013 +0100
|
||||
summary: Bug 779291: Implement SPS stackwalk using the breakpad unwinder. r=bgirard,glandium
|
||||
|
||||
diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
|
||||
--- a/src/common/linux/dump_symbols.cc
|
||||
+++ b/src/common/linux/dump_symbols.cc
|
||||
@@ -621,17 +621,17 @@ bool LoadSymbols(const string& obj_file,
|
||||
bool result =
|
||||
LoadDwarfCFI<ElfClass>(obj_file, elf_header, ".eh_frame",
|
||||
eh_frame_section, true,
|
||||
got_section, text_section, big_endian, module);
|
||||
found_usable_info = found_usable_info || result;
|
||||
}
|
||||
}
|
||||
|
||||
- if (!found_debug_info_section) {
|
||||
+ if (!found_debug_info_section && symbol_data != ONLY_CFI) {
|
||||
fprintf(stderr, "%s: file contains no debugging information"
|
||||
" (no \".stab\" or \".debug_info\" sections)\n",
|
||||
obj_file.c_str());
|
||||
|
||||
// Failed, but maybe there's a .gnu_debuglink section?
|
||||
if (read_gnu_debug_link) {
|
||||
const Shdr* gnu_debuglink_section
|
||||
= FindElfSectionByName<ElfClass>(".gnu_debuglink", SHT_PROGBITS,
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,50 +0,0 @@
|
|||
# HG changeset patch
|
||||
# User Julian Seward <jseward@acm.org>
|
||||
# Date 1365953823 -7200
|
||||
# Node ID 21d2964d1337c0fce7375025610298a818ddbd0f
|
||||
# Parent ef802a6418f25841880359e6dab3e8240bfd0821
|
||||
Bug 861141 - Connect Breakpad on Android to faulty.lib's mmap interface. r=ted.
|
||||
Adds a prototype for ReadSymbolDataInternal so it can be called from
|
||||
outside breakpad.
|
||||
|
||||
diff --git src/common/linux/dump_symbols.h
|
||||
--- a/src/common/linux/dump_symbols.h
|
||||
+++ b/src/common/linux/dump_symbols.h
|
||||
@@ -36,16 +36,17 @@
|
||||
#define COMMON_LINUX_DUMP_SYMBOLS_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/symbol_data.h"
|
||||
#include "common/using_std_string.h"
|
||||
+#include "google_breakpad/common/breakpad_types.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
class Module;
|
||||
|
||||
// Find all the debugging information in OBJ_FILE, an ELF executable
|
||||
// or shared library, and write it to SYM_STREAM in the Breakpad symbol
|
||||
// file format.
|
||||
@@ -60,11 +61,19 @@ bool WriteSymbolFile(const string &obj_f
|
||||
// As above, but simply return the debugging information in MODULE
|
||||
// instead of writing it to a stream. The caller owns the resulting
|
||||
// Module object and must delete it when finished.
|
||||
bool ReadSymbolData(const string& obj_file,
|
||||
const std::vector<string>& debug_dirs,
|
||||
SymbolData symbol_data,
|
||||
Module** module);
|
||||
|
||||
+// Same as ReadSymbolData, except don't try to open the file; instead
|
||||
+// just use the in-memory data (mapped image of it) located at OBJ_FILE.
|
||||
+bool ReadSymbolDataInternal(const uint8_t* obj_file,
|
||||
+ const string& obj_filename,
|
||||
+ const std::vector<string>& debug_dirs,
|
||||
+ SymbolData symbol_data,
|
||||
+ Module** module);
|
||||
+
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_LINUX_DUMP_SYMBOLS_H__
|
|
@ -1,38 +0,0 @@
|
|||
# HG changeset patch
|
||||
# User Georg Fritzsche <georg.fritzsche@googlemail.com>
|
||||
# Date 1366630152 -7200
|
||||
# Mon Apr 22 13:29:12 2013 +0200
|
||||
# Node ID 11f7a9321b7d5d85eddc2db16e58e6870a7c4e06
|
||||
# Parent e74de3db7dd27ffda8f4772f892cfb52c5c35649
|
||||
Bug 836829 - Fix missing result check in Mac exception handler. r=ted
|
||||
|
||||
diff --git a/src/client/mac/handler/exception_handler.cc b/src/client/mac/handler/exception_handler.cc
|
||||
--- a/src/client/mac/handler/exception_handler.cc
|
||||
+++ b/src/client/mac/handler/exception_handler.cc
|
||||
@@ -276,19 +276,23 @@ bool ExceptionHandler::WriteMinidump(boo
|
||||
|
||||
use_minidump_write_mutex_ = true;
|
||||
last_minidump_write_result_ = false;
|
||||
|
||||
// Lock the mutex. Since we just created it, this will return immediately.
|
||||
if (pthread_mutex_lock(&minidump_write_mutex_) == 0) {
|
||||
// Send an empty message to the handle port so that a minidump will
|
||||
// be written
|
||||
- SendMessageToHandlerThread(write_exception_stream ?
|
||||
- kWriteDumpWithExceptionMessage :
|
||||
- kWriteDumpMessage);
|
||||
+ bool result = SendMessageToHandlerThread(write_exception_stream ?
|
||||
+ kWriteDumpWithExceptionMessage :
|
||||
+ kWriteDumpMessage);
|
||||
+ if (!result) {
|
||||
+ pthread_mutex_unlock(&minidump_write_mutex_);
|
||||
+ return false;
|
||||
+ }
|
||||
|
||||
// Wait for the minidump writer to complete its writing. It will unlock
|
||||
// the mutex when completed
|
||||
pthread_mutex_lock(&minidump_write_mutex_);
|
||||
}
|
||||
|
||||
use_minidump_write_mutex_ = false;
|
||||
UpdateNextID();
|
|
@ -1,346 +0,0 @@
|
|||
# HG changeset patch
|
||||
# User Julian Seward <jseward@acm.org>
|
||||
# Date 1372168568 -7200
|
||||
# Tue Jun 25 15:56:08 2013 +0200
|
||||
# Node ID 6d06a09b3f5624dd833bd6f905bfd88e3fdec00a
|
||||
# Parent 11f7a9321b7d5d85eddc2db16e58e6870a7c4e06
|
||||
Bug 883126 - Improve performance of EXIDX unwinding in Breakpad. r=ted
|
||||
|
||||
diff --git a/src/common/arm_ex_to_module.cc b/src/common/arm_ex_to_module.cc
|
||||
--- a/src/common/arm_ex_to_module.cc
|
||||
+++ b/src/common/arm_ex_to_module.cc
|
||||
@@ -66,141 +66,126 @@ WITH THE SOFTWARE OR THE USE OR OTHER DE
|
||||
|
||||
#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f)
|
||||
#define ARM_EXBUF_COUNT(x) ((x) & 0x0f)
|
||||
#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x))
|
||||
|
||||
using google_breakpad::ustr__pc;
|
||||
using google_breakpad::ustr__lr;
|
||||
using google_breakpad::ustr__sp;
|
||||
+using google_breakpad::ustr__ZDra;
|
||||
+using google_breakpad::ustr__ZDcfa;
|
||||
using google_breakpad::Module;
|
||||
using google_breakpad::ToUniqueString;
|
||||
using google_breakpad::UniqueString;
|
||||
|
||||
namespace arm_ex_to_module {
|
||||
|
||||
// Translate command from extab_data to command for Module.
|
||||
int ARMExToModule::TranslateCmd(const struct extab_data* edata,
|
||||
- Module::StackFrameEntry* entry, string& vsp) {
|
||||
+ Module::StackFrameEntry* entry,
|
||||
+ Module::Expr& vsp) {
|
||||
int ret = 0;
|
||||
switch (edata->cmd) {
|
||||
case ARM_EXIDX_CMD_FINISH:
|
||||
/* Copy LR to PC if there isn't currently a rule for PC in force. */
|
||||
if (entry->initial_rules.find(ustr__pc())
|
||||
== entry->initial_rules.end()) {
|
||||
if (entry->initial_rules.find(ustr__lr())
|
||||
== entry->initial_rules.end()) {
|
||||
- entry->initial_rules[ustr__pc()] = Module::Expr("lr");
|
||||
+ entry->initial_rules[ustr__pc()] = Module::Expr(ustr__lr(),
|
||||
+ 0, false); // "lr"
|
||||
} else {
|
||||
entry->initial_rules[ustr__pc()] = entry->initial_rules[ustr__lr()];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ARM_EXIDX_CMD_SUB_FROM_VSP:
|
||||
- {
|
||||
- char c[16];
|
||||
- sprintf(c, " %d -", edata->data);
|
||||
- vsp += c;
|
||||
- }
|
||||
+ vsp = vsp.add_delta(- static_cast<long>(edata->data));
|
||||
break;
|
||||
case ARM_EXIDX_CMD_ADD_TO_VSP:
|
||||
- {
|
||||
- char c[16];
|
||||
- sprintf(c, " %d +", edata->data);
|
||||
- vsp += c;
|
||||
- }
|
||||
+ vsp = vsp.add_delta(static_cast<long>(edata->data));
|
||||
break;
|
||||
case ARM_EXIDX_CMD_REG_POP:
|
||||
for (unsigned int i = 0; i < 16; i++) {
|
||||
if (edata->data & (1 << i)) {
|
||||
- entry->initial_rules[ToUniqueString(regnames[i])]
|
||||
- = Module::Expr(vsp + " ^");
|
||||
- vsp += " 4 +";
|
||||
+ entry->initial_rules[ToUniqueString(regnames[i])] = vsp.deref();
|
||||
+ vsp = vsp.add_delta(4);
|
||||
}
|
||||
}
|
||||
/* Set cfa in case the SP got popped. */
|
||||
if (edata->data & (1 << 13)) {
|
||||
- Module::Expr& vsp_expr = entry->initial_rules[ustr__sp()];
|
||||
- // It must be a postfix expression (we don't generate anything
|
||||
- // else here), so return -1 to fail out if it isn't.
|
||||
- if (!vsp_expr.isExprPostfix()) {
|
||||
- ret = -1;
|
||||
- break;
|
||||
- };
|
||||
- vsp = vsp_expr.getExprPostfix();
|
||||
+ vsp = entry->initial_rules[ustr__sp()];
|
||||
}
|
||||
break;
|
||||
case ARM_EXIDX_CMD_REG_TO_SP: {
|
||||
assert (edata->data < 16);
|
||||
const char* const regname = regnames[edata->data];
|
||||
const UniqueString* regname_us = ToUniqueString(regname);
|
||||
if (entry->initial_rules.find(regname_us) == entry->initial_rules.end()) {
|
||||
- entry->initial_rules[ustr__sp()] = Module::Expr(regname);
|
||||
+ entry->initial_rules[ustr__sp()] = Module::Expr(regname_us,
|
||||
+ 0, false); // "regname"
|
||||
} else {
|
||||
entry->initial_rules[ustr__sp()] = entry->initial_rules[regname_us];
|
||||
}
|
||||
- Module::Expr& vsp_expr = entry->initial_rules[ustr__sp()];
|
||||
- if (!vsp_expr.isExprPostfix()) {
|
||||
- ret = -1;
|
||||
- break;
|
||||
- };
|
||||
- vsp = vsp_expr.getExprPostfix();
|
||||
+ vsp = entry->initial_rules[ustr__sp()];
|
||||
break;
|
||||
}
|
||||
case ARM_EXIDX_CMD_VFP_POP:
|
||||
/* Don't recover VFP registers, but be sure to adjust the stack
|
||||
pointer. */
|
||||
for (unsigned int i = ARM_EXBUF_START(edata->data);
|
||||
i <= ARM_EXBUF_END(edata->data); i++) {
|
||||
- vsp += " 8 +";
|
||||
+ vsp = vsp.add_delta(8);
|
||||
}
|
||||
if (!(edata->data & ARM_EXIDX_VFP_FSTMD)) {
|
||||
- vsp += " 4 +";
|
||||
+ vsp = vsp.add_delta(4);
|
||||
}
|
||||
break;
|
||||
case ARM_EXIDX_CMD_WREG_POP:
|
||||
for (unsigned int i = ARM_EXBUF_START(edata->data);
|
||||
i <= ARM_EXBUF_END(edata->data); i++) {
|
||||
- vsp += " 8 +";
|
||||
+ vsp = vsp.add_delta(8);
|
||||
}
|
||||
break;
|
||||
case ARM_EXIDX_CMD_WCGR_POP:
|
||||
// Pop wCGR registers under mask {wCGR3,2,1,0}, hence "i < 4"
|
||||
for (unsigned int i = 0; i < 4; i++) {
|
||||
if (edata->data & (1 << i)) {
|
||||
- vsp += " 4 +";
|
||||
+ vsp = vsp.add_delta(4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ARM_EXIDX_CMD_REFUSED:
|
||||
case ARM_EXIDX_CMD_RESERVED:
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ARMExToModule::AddStackFrame(uintptr_t addr, size_t size) {
|
||||
stack_frame_entry_ = new Module::StackFrameEntry;
|
||||
stack_frame_entry_->address = addr;
|
||||
stack_frame_entry_->size = size;
|
||||
- stack_frame_entry_->initial_rules[ToUniqueString(kCFA)] = Module::Expr("sp");
|
||||
- vsp_ = "sp";
|
||||
+ Module::Expr sp_expr = Module::Expr(ustr__sp(), 0, false); // "sp"
|
||||
+ stack_frame_entry_->initial_rules[ustr__ZDcfa()] = sp_expr; // ".cfa"
|
||||
+ vsp_ = sp_expr;
|
||||
}
|
||||
|
||||
int ARMExToModule::ImproveStackFrame(const struct extab_data* edata) {
|
||||
return TranslateCmd(edata, stack_frame_entry_, vsp_) ;
|
||||
}
|
||||
|
||||
void ARMExToModule::DeleteStackFrame() {
|
||||
delete stack_frame_entry_;
|
||||
}
|
||||
|
||||
void ARMExToModule::SubmitStackFrame() {
|
||||
// return address always winds up in pc
|
||||
- stack_frame_entry_->initial_rules[ToUniqueString(kRA)]
|
||||
+ stack_frame_entry_->initial_rules[ustr__ZDra()] // ".ra"
|
||||
= stack_frame_entry_->initial_rules[ustr__pc()];
|
||||
// the final value of vsp is the new value of sp
|
||||
stack_frame_entry_->initial_rules[ustr__sp()] = vsp_;
|
||||
module_->AddStackFrameEntry(stack_frame_entry_);
|
||||
}
|
||||
|
||||
} // namespace arm_ex_to_module
|
||||
diff --git a/src/common/arm_ex_to_module.h b/src/common/arm_ex_to_module.h
|
||||
--- a/src/common/arm_ex_to_module.h
|
||||
+++ b/src/common/arm_ex_to_module.h
|
||||
@@ -89,19 +89,16 @@ struct extab_data {
|
||||
uint32_t data;
|
||||
};
|
||||
|
||||
enum extab_cmd_flags {
|
||||
ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
|
||||
ARM_EXIDX_VFP_FSTMD = 1 << 17, // distinguishes FSTMxxD from FSTMxxX
|
||||
};
|
||||
|
||||
-const string kRA = ".ra";
|
||||
-const string kCFA = ".cfa";
|
||||
-
|
||||
static const char* const regnames[] = {
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
"r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
|
||||
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
|
||||
"fps", "cpsr"
|
||||
};
|
||||
|
||||
// Receives information from arm_ex_reader::ExceptionTableInfo
|
||||
@@ -113,17 +110,17 @@ class ARMExToModule {
|
||||
~ARMExToModule() { }
|
||||
void AddStackFrame(uintptr_t addr, size_t size);
|
||||
int ImproveStackFrame(const struct extab_data* edata);
|
||||
void DeleteStackFrame();
|
||||
void SubmitStackFrame();
|
||||
private:
|
||||
Module* module_;
|
||||
Module::StackFrameEntry* stack_frame_entry_;
|
||||
- string vsp_;
|
||||
+ Module::Expr vsp_;
|
||||
int TranslateCmd(const struct extab_data* edata,
|
||||
Module::StackFrameEntry* entry,
|
||||
- string& vsp);
|
||||
+ Module::Expr& vsp);
|
||||
};
|
||||
|
||||
} // namespace arm_ex_to_module
|
||||
|
||||
#endif // COMMON_ARM_EX_TO_MODULE__
|
||||
diff --git a/src/common/module.h b/src/common/module.h
|
||||
--- a/src/common/module.h
|
||||
+++ b/src/common/module.h
|
||||
@@ -39,16 +39,20 @@
|
||||
#define COMMON_LINUX_MODULE_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
+#include <assert.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
#include "common/symbol_data.h"
|
||||
#include "common/using_std_string.h"
|
||||
#include "common/unique_string.h"
|
||||
#include "google_breakpad/common/breakpad_types.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
using std::set;
|
||||
@@ -161,30 +165,98 @@ class Module {
|
||||
// Construct an invalid expression
|
||||
Expr() {
|
||||
postfix_ = "";
|
||||
ident_ = NULL;
|
||||
offset_ = 0;
|
||||
how_ = kExprInvalid;
|
||||
}
|
||||
bool isExprInvalid() const { return how_ == kExprInvalid; }
|
||||
- bool isExprPostfix() const { return how_ == kExprPostfix; }
|
||||
|
||||
- // Return the postfix expression string. This is only
|
||||
- // meaningful on Exprs for which isExprPostfix returns true.
|
||||
- // In all other cases it returns an empty string.
|
||||
- string getExprPostfix() const { return postfix_; }
|
||||
+ // Return the postfix expression string, either directly,
|
||||
+ // if this is a postfix expression, or by synthesising it
|
||||
+ // for a simple expression.
|
||||
+ string getExprPostfix() const {
|
||||
+ switch (how_) {
|
||||
+ case kExprPostfix:
|
||||
+ return postfix_;
|
||||
+ case kExprSimple:
|
||||
+ case kExprSimpleMem: {
|
||||
+ char buf[40];
|
||||
+ sprintf(buf, " %ld %c%s", labs(offset_), offset_ < 0 ? '-' : '+',
|
||||
+ how_ == kExprSimple ? "" : " ^");
|
||||
+ return string(FromUniqueString(ident_)) + string(buf);
|
||||
+ }
|
||||
+ case kExprInvalid:
|
||||
+ default:
|
||||
+ assert(0 && "getExprPostfix: invalid Module::Expr type");
|
||||
+ return "Expr::genExprPostfix: kExprInvalid";
|
||||
+ }
|
||||
+ }
|
||||
|
||||
bool operator==(const Expr& other) const {
|
||||
return how_ == other.how_ &&
|
||||
ident_ == other.ident_ &&
|
||||
offset_ == other.offset_ &&
|
||||
postfix_ == other.postfix_;
|
||||
}
|
||||
|
||||
+ // Returns an Expr which evaluates to |this| + |delta|
|
||||
+ Expr add_delta(long delta) {
|
||||
+ if (delta == 0) {
|
||||
+ return *this;
|
||||
+ }
|
||||
+ // If it's a simple form expression of the form "identifier + offset",
|
||||
+ // simply add |delta| on to |offset|. In the other two possible
|
||||
+ // cases:
|
||||
+ // *(identifier + offset)
|
||||
+ // completely arbitrary postfix expression string
|
||||
+ // the only option is to "downgrade" it to a postfix expression and add
|
||||
+ // "+/- delta" at the end of the string, since the result can't be
|
||||
+ // represented in the simple form.
|
||||
+ switch (how_) {
|
||||
+ case kExprSimpleMem:
|
||||
+ case kExprPostfix: {
|
||||
+ char buf[40];
|
||||
+ sprintf(buf, " %ld %c", labs(delta), delta < 0 ? '-' : '+');
|
||||
+ return Expr(getExprPostfix() + string(buf));
|
||||
+ }
|
||||
+ case kExprSimple:
|
||||
+ return Expr(ident_, offset_ + delta, false);
|
||||
+ case kExprInvalid:
|
||||
+ default:
|
||||
+ assert(0 && "add_delta: invalid Module::Expr type");
|
||||
+ // Invalid inputs produce an invalid result
|
||||
+ return Expr();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Returns an Expr which evaluates to *|this|
|
||||
+ Expr deref() {
|
||||
+ // In the simplest case, a kExprSimple can be changed into a
|
||||
+ // kExprSimpleMem. In all other cases it has to be dumped as a
|
||||
+ // postfix string, and " ^" added at the end.
|
||||
+ switch (how_) {
|
||||
+ case kExprSimple: {
|
||||
+ Expr t = *this;
|
||||
+ t.how_ = kExprSimpleMem;
|
||||
+ return t;
|
||||
+ }
|
||||
+ case kExprSimpleMem:
|
||||
+ case kExprPostfix: {
|
||||
+ return Expr(getExprPostfix() + " ^");
|
||||
+ }
|
||||
+ case kExprInvalid:
|
||||
+ default:
|
||||
+ assert(0 && "deref: invalid Module::Expr type");
|
||||
+ // Invalid inputs produce an invalid result
|
||||
+ return Expr();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
// The identifier that gives the starting value for simple expressions.
|
||||
const UniqueString* ident_;
|
||||
// The offset to add for simple expressions.
|
||||
long offset_;
|
||||
// The Postfix expression string to evaluate for non-simple expressions.
|
||||
string postfix_;
|
||||
// The operation expressed by this expression.
|
||||
ExprHow how_;
|
|
@ -1,96 +0,0 @@
|
|||
# HG changeset patch
|
||||
# User Julian Seward <jseward@acm.org>
|
||||
# Date 1366643454 -7200
|
||||
# Mon Apr 22 17:10:54 2013 +0200
|
||||
# Node ID 3e64f12d9dab619c90bee02ed071bcda0100844e
|
||||
# Parent 6d06a09b3f5624dd833bd6f905bfd88e3fdec00a
|
||||
Bug 859745 - Install sane unwinding limit for SPS/breakpad. r=ted
|
||||
|
||||
diff --git a/src/google_breakpad/processor/stackwalker.h b/src/google_breakpad/processor/stackwalker.h
|
||||
--- a/src/google_breakpad/processor/stackwalker.h
|
||||
+++ b/src/google_breakpad/processor/stackwalker.h
|
||||
@@ -83,17 +83,20 @@ class Stackwalker {
|
||||
// argument. If no suitable concrete subclass exists, returns NULL.
|
||||
static Stackwalker* StackwalkerForCPU(
|
||||
const SystemInfo* system_info,
|
||||
MinidumpContext* context,
|
||||
MemoryRegion* memory,
|
||||
const CodeModules* modules,
|
||||
StackFrameSymbolizer* resolver_helper);
|
||||
|
||||
- static void set_max_frames(uint32_t max_frames) { max_frames_ = max_frames; }
|
||||
+ static void set_max_frames(uint32_t max_frames) {
|
||||
+ max_frames_ = max_frames;
|
||||
+ max_frames_set_ = true;
|
||||
+ }
|
||||
static uint32_t max_frames() { return max_frames_; }
|
||||
|
||||
protected:
|
||||
// system_info identifies the operating system, NULL or empty if unknown.
|
||||
// memory identifies a MemoryRegion that provides the stack memory
|
||||
// for the stack to walk. modules, if non-NULL, is a CodeModules
|
||||
// object that is used to look up which code module each stack frame is
|
||||
// associated with. frame_symbolizer is a StackFrameSymbolizer object that
|
||||
@@ -191,14 +194,19 @@ class Stackwalker {
|
||||
// the end of the stack has been reached). GetCallerFrame allocates a new
|
||||
// StackFrame (or StackFrame subclass), ownership of which is taken by
|
||||
// the caller.
|
||||
virtual StackFrame* GetCallerFrame(const CallStack* stack) = 0;
|
||||
|
||||
// The maximum number of frames Stackwalker will walk through.
|
||||
// This defaults to 1024 to prevent infinite loops.
|
||||
static uint32_t max_frames_;
|
||||
+
|
||||
+ // Keep track of whether max_frames_ has been set by the user, since
|
||||
+ // it affects whether or not an error message is printed in the case
|
||||
+ // where an unwind got stopped by the limit.
|
||||
+ static bool max_frames_set_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__
|
||||
diff --git a/src/processor/stackwalker.cc b/src/processor/stackwalker.cc
|
||||
--- a/src/processor/stackwalker.cc
|
||||
+++ b/src/processor/stackwalker.cc
|
||||
@@ -52,16 +52,17 @@
|
||||
#include "processor/stackwalker_x86.h"
|
||||
#include "processor/stackwalker_amd64.h"
|
||||
#include "processor/stackwalker_arm.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
const int Stackwalker::kRASearchWords = 30;
|
||||
uint32_t Stackwalker::max_frames_ = 1024;
|
||||
+bool Stackwalker::max_frames_set_ = false;
|
||||
|
||||
Stackwalker::Stackwalker(const SystemInfo* system_info,
|
||||
MemoryRegion* memory,
|
||||
const CodeModules* modules,
|
||||
StackFrameSymbolizer* frame_symbolizer)
|
||||
: system_info_(system_info),
|
||||
memory_(memory),
|
||||
modules_(modules),
|
||||
@@ -120,17 +121,20 @@ bool Stackwalker::Walk(CallStack* stack,
|
||||
modules_without_symbols->push_back(frame->module);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the frame to the call stack. Relinquish the ownership claim
|
||||
// over the frame, because the stack now owns it.
|
||||
stack->frames_.push_back(frame.release());
|
||||
if (stack->frames_.size() > max_frames_) {
|
||||
- BPLOG(ERROR) << "The stack is over " << max_frames_ << " frames.";
|
||||
+ // Only emit an error message in the case where the limit that we
|
||||
+ // reached is the default limit, not set by the user.
|
||||
+ if (!max_frames_set_)
|
||||
+ BPLOG(ERROR) << "The stack is over " << max_frames_ << " frames.";
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the next frame and take ownership.
|
||||
frame.reset(GetCallerFrame(stack));
|
||||
}
|
||||
|
||||
return true;
|
|
@ -1,21 +0,0 @@
|
|||
# HG changeset patch
|
||||
# User Justin Wood <Callek@gmail.com>
|
||||
# Date 1372046309 14400
|
||||
# Node ID d6fc88d46b67cd522998ab6a9320b00b6091d5ce
|
||||
# Parent aef71cf41cecf4c3d7bef313bff502c98d5883ce
|
||||
Bug 886209 - SHT_ARM_EXIDX not defined on older glibc versions. r=glandium
|
||||
(fixes SeaMonkey building on CentOS5.x)
|
||||
|
||||
diff --git src/common/linux/dump_symbols.cc
|
||||
--- a/src/common/linux/dump_symbols.cc
|
||||
+++ b/src/common/linux/dump_symbols.cc
|
||||
@@ -71,7 +71,8 @@
|
||||
#include "common/using_std_string.h"
|
||||
#include "common/logging.h"
|
||||
|
||||
-#if defined(__ANDROID__) && !defined(SHT_ARM_EXIDX)
|
||||
+#ifndef SHT_ARM_EXIDX
|
||||
+// bionic and older glibc don't define it
|
||||
# define SHT_ARM_EXIDX (SHT_LOPROC + 1)
|
||||
#endif
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
# HG changeset patch
|
||||
# User Jed Davis <jld@mozilla.com>
|
||||
|
||||
Bug 942407: Fix breakpad signal handler's test for signal origin. r=ted
|
||||
|
||||
|
||||
diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc
|
||||
index 55834e0..df958fb 100644
|
||||
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc
|
||||
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc
|
||||
@@ -334,20 +334,20 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
|
||||
if (handled) {
|
||||
signal(sig, SIG_DFL);
|
||||
} else {
|
||||
RestoreHandlersLocked();
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&handler_stack_mutex_);
|
||||
|
||||
- if (info->si_pid) {
|
||||
- // This signal was triggered by somebody sending us the signal with kill().
|
||||
- // In order to retrigger it, we have to queue a new signal by calling
|
||||
- // kill() ourselves.
|
||||
+ if (info->si_code <= 0) {
|
||||
+ // This signal was sent by another process. (Positive values of
|
||||
+ // si_code are reserved for kernel-originated signals.) In order
|
||||
+ // to retrigger it, we have to queue a new signal.
|
||||
if (tgkill(getpid(), syscall(__NR_gettid), sig) < 0) {
|
||||
// If we failed to kill ourselves (e.g. because a sandbox disallows us
|
||||
// to do so), we instead resort to terminating our process. This will
|
||||
// result in an incorrect exit code.
|
||||
_exit(1);
|
||||
}
|
||||
} else {
|
||||
// This was a synchronous signal triggered by a hard fault (e.g. SIGSEGV).
|
||||
--
|
||||
1.8.4.rc3
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
commit 443e11243cf3c88087b70602822d9e228f60d40a
|
||||
Author: Jed Davis <jld@mozilla.com>
|
||||
Date: Wed Jan 29 12:06:33 2014 -0800
|
||||
|
||||
Bug 945498: Use breakpad to report seccomp violations as crashes.
|
||||
|
||||
diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h
|
||||
index 7155419..c0039bc 100644
|
||||
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h
|
||||
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h
|
||||
@@ -219,6 +219,9 @@ class ExceptionHandler {
|
||||
|
||||
// Force signal handling for the specified signal.
|
||||
bool SimulateSignalDelivery(int sig);
|
||||
+
|
||||
+ // Report a crash signal from an SA_SIGINFO signal handler.
|
||||
+ bool HandleSignal(int sig, siginfo_t* info, void* uc);
|
||||
private:
|
||||
// Save the old signal handlers and install new ones.
|
||||
static bool InstallHandlersLocked();
|
||||
@@ -231,7 +234,6 @@ class ExceptionHandler {
|
||||
void WaitForContinueSignal();
|
||||
|
||||
static void SignalHandler(int sig, siginfo_t* info, void* uc);
|
||||
- bool HandleSignal(int sig, siginfo_t* info, void* uc);
|
||||
static int ThreadEntry(void* arg);
|
||||
bool DoDump(pid_t crashing_process, const void* context,
|
||||
size_t context_size);
|
|
@ -1,93 +0,0 @@
|
|||
commit 8885dea3716170ec7f3b213421c330f31cd5ac4b
|
||||
Author: Jed Davis <jld@mozilla.com>
|
||||
Date: Mon May 19 15:41:28 2014 -0700
|
||||
|
||||
Bug 942290: Merge ARM exidx info with DWARF if both are present.
|
||||
|
||||
diff --git a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc
|
||||
index 5d87ab4..97f99e4 100644
|
||||
--- a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc
|
||||
+++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc
|
||||
@@ -487,14 +487,16 @@ void ExceptionTableInfo::Start()
|
||||
// create CFI entries that Breakpad can use. This can also fail.
|
||||
// First, add a new stack frame entry, into which ExtabEntryDecode
|
||||
// will write the CFI entries.
|
||||
- handler_->AddStackFrame(addr, next_addr - addr);
|
||||
- int ret = ExtabEntryDecode(buf, buf_used);
|
||||
- if (ret < 0) {
|
||||
- handler_->DeleteStackFrame();
|
||||
- BPLOG(INFO) << "ExtabEntryDecode: failed with error code: " << ret;
|
||||
- continue;
|
||||
+ if (!handler_->HasStackFrame(addr, next_addr - addr)) {
|
||||
+ handler_->AddStackFrame(addr, next_addr - addr);
|
||||
+ int ret = ExtabEntryDecode(buf, buf_used);
|
||||
+ if (ret < 0) {
|
||||
+ handler_->DeleteStackFrame();
|
||||
+ BPLOG(INFO) << "ExtabEntryDecode: failed with error code: " << ret;
|
||||
+ continue;
|
||||
+ }
|
||||
+ handler_->SubmitStackFrame();
|
||||
}
|
||||
- handler_->SubmitStackFrame();
|
||||
|
||||
} /* iterating over .exidx */
|
||||
}
|
||||
diff --git a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc
|
||||
index f8535b7..b5e3b06 100644
|
||||
--- a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc
|
||||
+++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc
|
||||
@@ -162,6 +162,21 @@ int ARMExToModule::TranslateCmd(const struct extab_data* edata,
|
||||
return ret;
|
||||
}
|
||||
|
||||
+bool ARMExToModule::HasStackFrame(uintptr_t addr, size_t size) {
|
||||
+ // Invariant: the range [addr,covered) is covered by existing stack
|
||||
+ // frame entries.
|
||||
+ uintptr_t covered = addr;
|
||||
+ while (covered < addr + size) {
|
||||
+ const Module::StackFrameEntry *old_entry =
|
||||
+ module_->FindStackFrameEntryByAddress(covered);
|
||||
+ if (!old_entry) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ covered = old_entry->address + old_entry->size;
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
void ARMExToModule::AddStackFrame(uintptr_t addr, size_t size) {
|
||||
stack_frame_entry_ = new Module::StackFrameEntry;
|
||||
stack_frame_entry_->address = addr;
|
||||
diff --git a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h
|
||||
index 73c936c..9d6a879 100644
|
||||
--- a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h
|
||||
+++ b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h
|
||||
@@ -108,6 +108,7 @@ class ARMExToModule {
|
||||
ARMExToModule(Module* module)
|
||||
: module_(module) { }
|
||||
~ARMExToModule() { }
|
||||
+ bool HasStackFrame(uintptr_t addr, size_t size);
|
||||
void AddStackFrame(uintptr_t addr, size_t size);
|
||||
int ImproveStackFrame(const struct extab_data* edata);
|
||||
void DeleteStackFrame();
|
||||
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc
|
||||
index d59832c..9a54bab 100644
|
||||
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc
|
||||
+++ b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc
|
||||
@@ -695,10 +695,12 @@ bool LoadSymbols(const string& obj_file,
|
||||
FindElfSectionByName<ElfClass>(".ARM.extab", SHT_PROGBITS,
|
||||
sections, names, names_end,
|
||||
elf_header->e_shnum);
|
||||
- // Only load information from this section if there isn't a .debug_info
|
||||
- // section.
|
||||
- if (!found_debug_info_section
|
||||
- && arm_exidx_section && arm_extab_section && symbol_data != NO_CFI) {
|
||||
+ // Load information from these sections even if there is
|
||||
+ // .debug_info, because some functions (e.g., hand-written or
|
||||
+ // script-generated assembly) could have exidx entries but no DWARF.
|
||||
+ // (For functions with both, the DWARF info that has already been
|
||||
+ // parsed will take precedence.)
|
||||
+ if (arm_exidx_section && arm_extab_section && symbol_data != NO_CFI) {
|
||||
info->LoadedSection(".ARM.exidx");
|
||||
info->LoadedSection(".ARM.extab");
|
||||
bool result = LoadARMexidx<ElfClass>(elf_header,
|
|
@ -1,151 +0,0 @@
|
|||
commit 467c77076b232246970551cfba645d235381f588
|
||||
Author: Jed Davis <jld@mozilla.com>
|
||||
Date: Wed Sep 17 11:34:38 2014 -0700
|
||||
|
||||
Bug 1068410 - Remove procfs-searching workaround for credential-passing bug.
|
||||
|
||||
diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/crash_generation_server.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/crash_generation_server.cc
|
||||
index f1e16b1..420e4b2 100644
|
||||
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/crash_generation_server.cc
|
||||
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/crash_generation_server.cc
|
||||
@@ -51,116 +51,6 @@
|
||||
|
||||
static const char kCommandQuit = 'x';
|
||||
|
||||
-static bool
|
||||
-GetInodeForFileDescriptor(ino_t* inode_out, int fd)
|
||||
-{
|
||||
- assert(inode_out);
|
||||
-
|
||||
- struct stat buf;
|
||||
- if (fstat(fd, &buf) < 0)
|
||||
- return false;
|
||||
-
|
||||
- if (!S_ISSOCK(buf.st_mode))
|
||||
- return false;
|
||||
-
|
||||
- *inode_out = buf.st_ino;
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
-// expected prefix of the target of the /proc/self/fd/%d link for a socket
|
||||
-static const char kSocketLinkPrefix[] = "socket:[";
|
||||
-
|
||||
-// Parse a symlink in /proc/pid/fd/$x and return the inode number of the
|
||||
-// socket.
|
||||
-// inode_out: (output) set to the inode number on success
|
||||
-// path: e.g. /proc/1234/fd/5 (must be a UNIX domain socket descriptor)
|
||||
-static bool
|
||||
-GetInodeForProcPath(ino_t* inode_out, const char* path)
|
||||
-{
|
||||
- assert(inode_out);
|
||||
- assert(path);
|
||||
-
|
||||
- char buf[PATH_MAX];
|
||||
- if (!google_breakpad::SafeReadLink(path, buf)) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- if (0 != memcmp(kSocketLinkPrefix, buf, sizeof(kSocketLinkPrefix) - 1)) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- char* endptr;
|
||||
- const uint64_t inode_ul =
|
||||
- strtoull(buf + sizeof(kSocketLinkPrefix) - 1, &endptr, 10);
|
||||
- if (*endptr != ']')
|
||||
- return false;
|
||||
-
|
||||
- if (inode_ul == ULLONG_MAX) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- *inode_out = inode_ul;
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
-static bool
|
||||
-FindProcessHoldingSocket(pid_t* pid_out, ino_t socket_inode)
|
||||
-{
|
||||
- assert(pid_out);
|
||||
- bool already_found = false;
|
||||
-
|
||||
- DIR* proc = opendir("/proc");
|
||||
- if (!proc) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- std::vector<pid_t> pids;
|
||||
-
|
||||
- struct dirent* dent;
|
||||
- while ((dent = readdir(proc))) {
|
||||
- char* endptr;
|
||||
- const unsigned long int pid_ul = strtoul(dent->d_name, &endptr, 10);
|
||||
- if (pid_ul == ULONG_MAX || '\0' != *endptr)
|
||||
- continue;
|
||||
- pids.push_back(pid_ul);
|
||||
- }
|
||||
- closedir(proc);
|
||||
-
|
||||
- for (std::vector<pid_t>::const_iterator
|
||||
- i = pids.begin(); i != pids.end(); ++i) {
|
||||
- const pid_t current_pid = *i;
|
||||
- char buf[PATH_MAX];
|
||||
- snprintf(buf, sizeof(buf), "/proc/%d/fd", current_pid);
|
||||
- DIR* fd = opendir(buf);
|
||||
- if (!fd)
|
||||
- continue;
|
||||
-
|
||||
- while ((dent = readdir(fd))) {
|
||||
- if (snprintf(buf, sizeof(buf), "/proc/%d/fd/%s", current_pid,
|
||||
- dent->d_name) >= static_cast<int>(sizeof(buf))) {
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- ino_t fd_inode;
|
||||
- if (GetInodeForProcPath(&fd_inode, buf)
|
||||
- && fd_inode == socket_inode) {
|
||||
- if (already_found) {
|
||||
- closedir(fd);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- already_found = true;
|
||||
- *pid_out = current_pid;
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- closedir(fd);
|
||||
- }
|
||||
-
|
||||
- return already_found;
|
||||
-}
|
||||
-
|
||||
namespace google_breakpad {
|
||||
|
||||
CrashGenerationServer::CrashGenerationServer(
|
||||
@@ -367,23 +257,6 @@ CrashGenerationServer::ClientEvent(short revents)
|
||||
return true;
|
||||
}
|
||||
|
||||
- // Kernel bug workaround (broken in 2.6.30 at least):
|
||||
- // The kernel doesn't translate PIDs in SCM_CREDENTIALS across PID
|
||||
- // namespaces. Thus |crashing_pid| might be garbage from our point of view.
|
||||
- // In the future we can remove this workaround, but we have to wait a couple
|
||||
- // of years to be sure that it's worked its way out into the world.
|
||||
-
|
||||
- ino_t inode_number;
|
||||
- if (!GetInodeForFileDescriptor(&inode_number, signal_fd)) {
|
||||
- HANDLE_EINTR(close(signal_fd));
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- if (!FindProcessHoldingSocket(&crashing_pid, inode_number - 1)) {
|
||||
- HANDLE_EINTR(close(signal_fd));
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
string minidump_filename;
|
||||
if (!MakeMinidumpFilename(minidump_filename))
|
||||
return true;
|
|
@ -1,40 +0,0 @@
|
|||
commit 634161872e2dcddcea95784651a985e8ebe3e937
|
||||
Author: Jed Davis <jld@mozilla.com>
|
||||
Date: Wed Sep 17 11:35:34 2014 -0700
|
||||
|
||||
Bug 1068410 - Convert remote crash dump to use pipe instead of socketpair in the child.
|
||||
|
||||
diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/crash_generation_client.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/crash_generation_client.cc
|
||||
index 6ede779..df069e4 100644
|
||||
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/crash_generation_client.cc
|
||||
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/crash_generation_client.cc
|
||||
@@ -45,7 +45,8 @@ bool
|
||||
CrashGenerationClient::RequestDump(const void* blob, size_t blob_size)
|
||||
{
|
||||
int fds[2];
|
||||
- sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
|
||||
+ if (sys_pipe(fds) != 0)
|
||||
+ return false;
|
||||
static const unsigned kControlMsgSize = CMSG_SPACE(sizeof(int));
|
||||
|
||||
struct kernel_msghdr msg;
|
||||
diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/crash_generation_server.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/crash_generation_server.cc
|
||||
index 420e4b2..721078c 100644
|
||||
--- a/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/crash_generation_server.cc
|
||||
+++ b/toolkit/crashreporter/google-breakpad/src/client/linux/crash_generation/crash_generation_server.cc
|
||||
@@ -275,14 +275,7 @@ CrashGenerationServer::ClientEvent(short revents)
|
||||
}
|
||||
|
||||
// Send the done signal to the process: it can exit now.
|
||||
- memset(&msg, 0, sizeof(msg));
|
||||
- struct iovec done_iov;
|
||||
- done_iov.iov_base = const_cast<char*>("\x42");
|
||||
- done_iov.iov_len = 1;
|
||||
- msg.msg_iov = &done_iov;
|
||||
- msg.msg_iovlen = 1;
|
||||
-
|
||||
- HANDLE_EINTR(sendmsg(signal_fd, &msg, MSG_DONTWAIT | MSG_NOSIGNAL));
|
||||
+ // (Closing this will make the child's sys_read unblock and return 0.)
|
||||
HANDLE_EINTR(close(signal_fd));
|
||||
|
||||
return true;
|
|
@ -11,10 +11,6 @@ if CONFIG['OS_TARGET'] != 'Android':
|
|||
'crashreporter.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../google-breakpad/src',
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
UNIFIED_SOURCES += [
|
||||
'crashreporter_win.cpp',
|
||||
|
@ -42,7 +38,6 @@ elif CONFIG['OS_ARCH'] == 'Darwin':
|
|||
OS_LIBS += ['-framework Cocoa']
|
||||
USE_LIBS += [
|
||||
'breakpad_common_s',
|
||||
'breakpad_logging',
|
||||
'breakpad_mac_common_s',
|
||||
]
|
||||
elif CONFIG['OS_ARCH'] == 'SunOS':
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/toolkit/crashreporter/google-breakpad/src',
|
||||
]
|
||||
|
||||
# Suppress warnings in third-party code.
|
||||
if CONFIG['_MSC_VER']:
|
||||
CXXFLAGS += [
|
||||
|
@ -15,3 +19,8 @@ elif CONFIG['GNU_CXX']:
|
|||
]
|
||||
if CONFIG['CLANG_CXX']:
|
||||
CXXFLAGS += ['-Wno-implicit-fallthrough']
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
DEFINES['ELFSIZE'] = 32
|
||||
|
||||
DEFINES['NO_STABS_SUPPORT'] = True
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
// Copyright (c) 2012, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ELF_H
|
||||
#define GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ELF_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// The Android <elf.h> provides BSD-based definitions for the ElfXX_Nhdr
|
||||
// types
|
||||
// always source-compatible with the GLibc/kernel ones. To overcome this
|
||||
// issue without modifying a lot of code in Breakpad, use an ugly macro
|
||||
// renaming trick with #include_next
|
||||
|
||||
// Avoid conflict with BSD-based definition of ElfXX_Nhdr.
|
||||
// Unfortunately, their field member names do not use a 'n_' prefix.
|
||||
#define Elf32_Nhdr __bsd_Elf32_Nhdr
|
||||
#define Elf64_Nhdr __bsd_Elf64_Nhdr
|
||||
|
||||
// In case they are defined by the NDK version
|
||||
#define Elf32_auxv_t __bionic_Elf32_auxv_t
|
||||
#define Elf64_auxv_t __bionic_Elf64_auxv_t
|
||||
|
||||
#define Elf32_Dyn __bionic_Elf32_Dyn
|
||||
#define Elf64_Dyn __bionic_Elf64_Dyn
|
||||
|
||||
#include_next <elf.h>
|
||||
|
||||
#undef Elf32_Nhdr
|
||||
#undef Elf64_Nhdr
|
||||
|
||||
typedef struct {
|
||||
Elf32_Word n_namesz;
|
||||
Elf32_Word n_descsz;
|
||||
Elf32_Word n_type;
|
||||
} Elf32_Nhdr;
|
||||
|
||||
typedef struct {
|
||||
Elf64_Word n_namesz;
|
||||
Elf64_Word n_descsz;
|
||||
Elf64_Word n_type;
|
||||
} Elf64_Nhdr;
|
||||
|
||||
#undef Elf32_auxv_t
|
||||
#undef Elf64_auxv_t
|
||||
|
||||
typedef struct {
|
||||
uint32_t a_type;
|
||||
union {
|
||||
uint32_t a_val;
|
||||
} a_un;
|
||||
} Elf32_auxv_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t a_type;
|
||||
union {
|
||||
uint64_t a_val;
|
||||
} a_un;
|
||||
} Elf64_auxv_t;
|
||||
|
||||
#undef Elf32_Dyn
|
||||
#undef Elf64_Dyn
|
||||
|
||||
typedef struct {
|
||||
Elf32_Sword d_tag;
|
||||
union {
|
||||
Elf32_Word d_val;
|
||||
Elf32_Addr d_ptr;
|
||||
} d_un;
|
||||
} Elf32_Dyn;
|
||||
|
||||
typedef struct {
|
||||
Elf64_Sxword d_tag;
|
||||
union {
|
||||
Elf64_Xword d_val;
|
||||
Elf64_Addr d_ptr;
|
||||
} d_un;
|
||||
} Elf64_Dyn;
|
||||
|
||||
|
||||
// __WORDSIZE is GLibc-specific and used by Google Breakpad on Linux.
|
||||
// All Android platforms are 32-bit for now.
|
||||
#ifndef __WORDSIZE
|
||||
#define __WORDSIZE 32
|
||||
#endif
|
||||
|
||||
// The Android headers don't always define this constant.
|
||||
#ifndef EM_X86_64
|
||||
#define EM_X86_64 62
|
||||
#endif
|
||||
|
||||
#ifndef EM_PPC64
|
||||
#define EM_PPC64 21
|
||||
#endif
|
||||
|
||||
#ifndef EM_S390
|
||||
#define EM_S390 22
|
||||
#endif
|
||||
|
||||
#if !defined(AT_SYSINFO_EHDR)
|
||||
#define AT_SYSINFO_EHDR 33
|
||||
#endif
|
||||
|
||||
#if !defined(NT_PRSTATUS)
|
||||
#define NT_PRSTATUS 1
|
||||
#endif
|
||||
|
||||
#if !defined(NT_PRPSINFO)
|
||||
#define NT_PRPSINFO 3
|
||||
#endif
|
||||
|
||||
#if !defined(NT_AUXV)
|
||||
#define NT_AUXV 6
|
||||
#endif
|
||||
|
||||
#if !defined(NT_PRXFPREG)
|
||||
#define NT_PRXFPREG 0x46e62b7f
|
||||
#endif
|
||||
|
||||
#if !defined(NT_FPREGSET)
|
||||
#define NT_FPREGSET 2
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ELF_H
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) 2012, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_ANDROID_INCLUDE_LINK_H
|
||||
#define GOOGLE_BREAKPAD_ANDROID_INCLUDE_LINK_H
|
||||
|
||||
/* Android doesn't provide <link.h>. Provide custom version here */
|
||||
#include <elf.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#define ElfW(type) _ElfW (Elf, ELFSIZE, type)
|
||||
#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t)
|
||||
#define _ElfW_1(e,w,t) e##w##t
|
||||
|
||||
struct r_debug {
|
||||
int r_version;
|
||||
struct link_map* r_map;
|
||||
ElfW(Addr) r_brk;
|
||||
enum {
|
||||
RT_CONSISTENT,
|
||||
RT_ADD,
|
||||
RT_DELETE } r_state;
|
||||
ElfW(Addr) r_ldbase;
|
||||
};
|
||||
|
||||
struct link_map {
|
||||
ElfW(Addr) l_addr;
|
||||
char* l_name;
|
||||
ElfW(Dyn)* l_ld;
|
||||
struct link_map* l_next;
|
||||
struct link_map* l_prev;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_ANDROID_INCLUDE_LINK_H */
|
|
@ -0,0 +1,100 @@
|
|||
// Copyright (c) 2012, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_STAB_H
|
||||
#define GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_STAB_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#ifdef __BIONIC_HAVE_STAB_H
|
||||
#include <stab.h>
|
||||
#else
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#define _STAB_CODE_LIST \
|
||||
_STAB_CODE_DEF(UNDF,0x00) \
|
||||
_STAB_CODE_DEF(GSYM,0x20) \
|
||||
_STAB_CODE_DEF(FNAME,0x22) \
|
||||
_STAB_CODE_DEF(FUN,0x24) \
|
||||
_STAB_CODE_DEF(STSYM,0x26) \
|
||||
_STAB_CODE_DEF(LCSYM,0x28) \
|
||||
_STAB_CODE_DEF(MAIN,0x2a) \
|
||||
_STAB_CODE_DEF(PC,0x30) \
|
||||
_STAB_CODE_DEF(NSYMS,0x32) \
|
||||
_STAB_CODE_DEF(NOMAP,0x34) \
|
||||
_STAB_CODE_DEF(OBJ,0x38) \
|
||||
_STAB_CODE_DEF(OPT,0x3c) \
|
||||
_STAB_CODE_DEF(RSYM,0x40) \
|
||||
_STAB_CODE_DEF(M2C,0x42) \
|
||||
_STAB_CODE_DEF(SLINE,0x44) \
|
||||
_STAB_CODE_DEF(DSLINE,0x46) \
|
||||
_STAB_CODE_DEF(BSLINE,0x48) \
|
||||
_STAB_CODE_DEF(BROWS,0x48) \
|
||||
_STAB_CODE_DEF(DEFD,0x4a) \
|
||||
_STAB_CODE_DEF(EHDECL,0x50) \
|
||||
_STAB_CODE_DEF(MOD2,0x50) \
|
||||
_STAB_CODE_DEF(CATCH,0x54) \
|
||||
_STAB_CODE_DEF(SSYM,0x60) \
|
||||
_STAB_CODE_DEF(SO,0x64) \
|
||||
_STAB_CODE_DEF(LSYM,0x80) \
|
||||
_STAB_CODE_DEF(BINCL,0x82) \
|
||||
_STAB_CODE_DEF(SOL,0x84) \
|
||||
_STAB_CODE_DEF(PSYM,0xa0) \
|
||||
_STAB_CODE_DEF(EINCL,0xa2) \
|
||||
_STAB_CODE_DEF(ENTRY,0xa4) \
|
||||
_STAB_CODE_DEF(LBRAC,0xc0) \
|
||||
_STAB_CODE_DEF(EXCL,0xc2) \
|
||||
_STAB_CODE_DEF(SCOPE,0xc4) \
|
||||
_STAB_CODE_DEF(RBRAC,0xe0) \
|
||||
_STAB_CODE_DEF(BCOMM,0xe2) \
|
||||
_STAB_CODE_DEF(ECOMM,0xe4) \
|
||||
_STAB_CODE_DEF(ECOML,0xe8) \
|
||||
_STAB_CODE_DEF(NBTEXT,0xf0) \
|
||||
_STAB_CODE_DEF(NBDATA,0xf2) \
|
||||
_STAB_CODE_DEF(NBBSS,0xf4) \
|
||||
_STAB_CODE_DEF(NBSTS,0xf6) \
|
||||
_STAB_CODE_DEF(NBLCS,0xf8) \
|
||||
_STAB_CODE_DEF(LENG,0xfe)
|
||||
|
||||
enum __stab_debug_code {
|
||||
#define _STAB_CODE_DEF(x,y) N_##x = y,
|
||||
_STAB_CODE_LIST
|
||||
#undef _STAB_CODE_DEF
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __BIONIC_HAVE_STAB_H
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_STAB_H
|
|
@ -0,0 +1,113 @@
|
|||
// Copyright (c) 2012, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_SYS_PROCFS_H
|
||||
#define GOOGLE_BREAKPAD_COMMON_ANDROID_SYS_PROCFS_H
|
||||
|
||||
#ifdef __BIONIC_HAVE_SYS_PROCFS_H
|
||||
|
||||
#include_next <sys/procfs.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/user.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#ifdef __x86_64__
|
||||
typedef unsigned long long elf_greg_t;
|
||||
#else
|
||||
typedef unsigned long elf_greg_t;
|
||||
#endif
|
||||
|
||||
#ifdef __arm__
|
||||
#define ELF_NGREG (sizeof(struct user_regs) / sizeof(elf_greg_t))
|
||||
#else
|
||||
#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
|
||||
#endif
|
||||
|
||||
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
||||
|
||||
struct elf_siginfo {
|
||||
int si_signo;
|
||||
int si_code;
|
||||
int si_errno;
|
||||
};
|
||||
|
||||
struct elf_prstatus {
|
||||
struct elf_siginfo pr_info;
|
||||
short pr_cursig;
|
||||
unsigned long pr_sigpend;
|
||||
unsigned long pr_sighold;
|
||||
pid_t pr_pid;
|
||||
pid_t pr_ppid;
|
||||
pid_t pr_pgrp;
|
||||
pid_t pd_sid;
|
||||
struct timeval pr_utime;
|
||||
struct timeval pr_stime;
|
||||
struct timeval pr_cutime;
|
||||
struct timeval pr_cstime;
|
||||
elf_gregset_t pr_reg;
|
||||
int pr_fpvalid;
|
||||
};
|
||||
|
||||
#define ELF_PRARGSZ 80
|
||||
|
||||
struct elf_prpsinfo {
|
||||
char pr_state;
|
||||
char pr_sname;
|
||||
char pr_zomb;
|
||||
char pr_nice;
|
||||
unsigned long pr_flags;
|
||||
#ifdef __x86_64__
|
||||
unsigned int pr_uid;
|
||||
unsigned int pr_gid;
|
||||
#else
|
||||
unsigned short pr_uid;
|
||||
unsigned short pr_gid;
|
||||
#endif
|
||||
int pr_pid;
|
||||
int pr_ppid;
|
||||
int pr_pgrp;
|
||||
int pr_sid;
|
||||
char pr_fname[16];
|
||||
char pr_psargs[ELF_PRARGSZ];
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __BIONIC_HAVE_SYS_PROCFS_H
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_SYS_PROCFS_H
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2007, Google Inc.
|
||||
// Copyright (c) 2012, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
|
@ -26,10 +26,10 @@
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Author: Sergey Ioffe
|
||||
|
||||
#define GOOGLE_STRIP_LOG 10
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_SIGNAL_H
|
||||
#define GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_SIGNAL_H
|
||||
|
||||
// Include the actual test.
|
||||
#include "logging_striptest_main.cc"
|
||||
#include <signal.h>
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_SIGNAL_H
|
|
@ -0,0 +1,134 @@
|
|||
// Copyright (c) 2012, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_USER_H
|
||||
#define GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_USER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// These types are used with ptrace(), more specifically with
|
||||
// PTRACE_GETREGS, PTRACE_GETFPREGS and PTRACE_GETVFPREGS respectively.
|
||||
//
|
||||
// They are also defined, sometimes with different names, in <asm/user.h>
|
||||
//
|
||||
|
||||
#if defined(__arm__)
|
||||
|
||||
#define _ARM_USER_H 1 // Prevent <asm/user.h> conflicts
|
||||
|
||||
// Note: on ARM, GLibc uses user_regs instead of user_regs_struct.
|
||||
struct user_regs {
|
||||
// Note: Entries 0-15 match r0..r15
|
||||
// Entry 16 is used to store the CPSR register.
|
||||
// Entry 17 is used to store the "orig_r0" value.
|
||||
unsigned long int uregs[18];
|
||||
};
|
||||
|
||||
// Same here: user_fpregs instead of user_fpregs_struct.
|
||||
struct user_fpregs {
|
||||
struct fp_reg {
|
||||
unsigned int sign1:1;
|
||||
unsigned int unused:15;
|
||||
unsigned int sign2:1;
|
||||
unsigned int exponent:14;
|
||||
unsigned int j:1;
|
||||
unsigned int mantissa1:31;
|
||||
unsigned int mantissa0:32;
|
||||
} fpregs[8];
|
||||
unsigned int fpsr:32;
|
||||
unsigned int fpcr:32;
|
||||
unsigned char ftype[8];
|
||||
unsigned int init_flag;
|
||||
};
|
||||
|
||||
// GLibc doesn't define this one in <sys/user.h> though.
|
||||
struct user_vfpregs {
|
||||
unsigned long long fpregs[32];
|
||||
unsigned long fpscr;
|
||||
};
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
#define _I386_USER_H 1 // Prevent <asm/user.h> conflicts
|
||||
|
||||
// GLibc-compatible definitions
|
||||
struct user_regs_struct {
|
||||
long ebx, ecx, edx, esi, edi, ebp, eax;
|
||||
long xds, xes, xfs, xgs, orig_eax;
|
||||
long eip, xcs, eflags, esp, xss;
|
||||
};
|
||||
|
||||
struct user_fpregs_struct {
|
||||
long cwd, swd, twd, fip, fcs, foo, fos;
|
||||
long st_space[20];
|
||||
};
|
||||
|
||||
struct user_fpxregs_struct {
|
||||
unsigned short cwd, swd, twd, fop;
|
||||
long fip, fcs, foo, fos, mxcsr, reserved;
|
||||
long st_space[32];
|
||||
long xmm_space[32];
|
||||
long padding[56];
|
||||
};
|
||||
|
||||
struct user {
|
||||
struct user_regs_struct regs;
|
||||
int u_fpvalid;
|
||||
struct user_fpregs_struct i387;
|
||||
unsigned long u_tsize;
|
||||
unsigned long u_dsize;
|
||||
unsigned long u_ssize;
|
||||
unsigned long start_code;
|
||||
unsigned long start_stack;
|
||||
long signal;
|
||||
int reserved;
|
||||
struct user_regs_struct* u_ar0;
|
||||
struct user_fpregs_struct* u_fpstate;
|
||||
unsigned long magic;
|
||||
char u_comm [32];
|
||||
int u_debugreg [8];
|
||||
};
|
||||
|
||||
|
||||
#elif defined(__mips__)
|
||||
|
||||
// TODO: Provide some useful definitions here, once the rest of Breakpad
|
||||
// requires them.
|
||||
|
||||
#else
|
||||
# error "Unsupported Android CPU ABI"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_USER_H
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright (c) 2012, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_UCONTEXT_H
|
||||
#define GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_UCONTEXT_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef __BIONIC_HAVE_UCONTEXT_H
|
||||
# include_next <ucontext.h>
|
||||
#else
|
||||
# include <sys/ucontext.h>
|
||||
#endif // __BIONIC_UCONTEXT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// Provided by src/android/common/breakpad_getcontext.S
|
||||
int breakpad_getcontext(ucontext_t* ucp);
|
||||
|
||||
#define getcontext(x) breakpad_getcontext(x)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_UCONTEXT_H
|
|
@ -0,0 +1,81 @@
|
|||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# Ignore other VCSs.
|
||||
.svn/
|
||||
|
||||
# Ignore common compiled artifacts.
|
||||
*~
|
||||
*.o
|
||||
lib*.a
|
||||
/breakpad.pc
|
||||
/breakpad-client.pc
|
||||
/src/client/linux/linux_client_unittest_shlib
|
||||
/src/client/linux/linux_dumper_unittest_helper
|
||||
/src/processor/microdump_stackwalk
|
||||
/src/processor/minidump_dump
|
||||
/src/processor/minidump_stackwalk
|
||||
/src/tools/linux/core2md/core2md
|
||||
/src/tools/linux/dump_syms/dump_syms
|
||||
/src/tools/linux/md2core/minidump-2-core
|
||||
/src/tools/linux/symupload/minidump_upload
|
||||
/src/tools/linux/symupload/sym_upload
|
||||
|
||||
# Ignore autotools generated artifacts.
|
||||
.deps
|
||||
.dirstamp
|
||||
autom4te.cache/
|
||||
/config.cache
|
||||
config.h
|
||||
/config.log
|
||||
/config.status
|
||||
/Makefile
|
||||
stamp-h1
|
||||
|
||||
# Ignore GYP generated Visual Studio artifacts.
|
||||
*.filters
|
||||
*.sdf
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*.vcxproj
|
||||
|
||||
# Ignore GYP generated Makefiles
|
||||
src/Makefile
|
||||
*.Makefile
|
||||
*.target.mk
|
||||
|
||||
# Ignore compiled Python files.
|
||||
*.pyc
|
||||
|
||||
# Ignore directories gclient syncs.
|
||||
src/testing
|
||||
src/third_party/glog
|
||||
src/third_party/lss
|
||||
src/third_party/protobuf
|
||||
src/tools/gyp
|
|
@ -1,5 +1,4 @@
|
|||
# Copyright (c) 2010, Google Inc.
|
||||
# All rights reserved.
|
||||
# Copyright 2010 Google Inc. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
|
@ -27,18 +26,42 @@
|
|||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# We only use this file to ease the steps of generating projects after
|
||||
# syncing, if we use gclient. All dependencies are svn:externals instead.
|
||||
# If you're not using gclient, you need to run the gyp python script to
|
||||
# generate the projects.
|
||||
# This can be done by the following command (assuming current directory):
|
||||
# src\tools\gyp\gyp.bat src\client\windows\breakpad_client.gyp
|
||||
# This is used to mimic the svn:externals mechanism for gclient (both Git and
|
||||
# SVN) based checkouts of Breakpad. As such, its use is entirely optional. If
|
||||
# using a manually managed SVN checkout as opposed to a gclient managed checkout
|
||||
# you can still use the hooks mechanism for generating project files by calling
|
||||
# 'gclient runhooks' rather than 'gclient sync'.
|
||||
|
||||
deps = {
|
||||
# Logging code.
|
||||
"src/src/third_party/glog":
|
||||
"http://google-glog.googlecode.com/svn/trunk@97",
|
||||
|
||||
# Testing libraries and utilities.
|
||||
"src/src/testing": "http://googlemock.googlecode.com/svn/trunk@408",
|
||||
"src/src/testing/gtest": "http://googletest.googlecode.com/svn/trunk@615",
|
||||
|
||||
# Protobuf.
|
||||
"src/src/third_party/protobuf/protobuf":
|
||||
"http://protobuf.googlecode.com/svn/trunk@407",
|
||||
|
||||
# GYP project generator.
|
||||
"src/src/tools/gyp": "http://gyp.googlecode.com/svn/trunk@1886",
|
||||
|
||||
# Linux syscall support.
|
||||
"src/src/third_party/lss":
|
||||
"https://chromium.googlesource.com/linux-syscall-support/" +
|
||||
"@9292030109847793f7a6689adac1ddafb412fe14"
|
||||
}
|
||||
|
||||
hooks = [
|
||||
{
|
||||
# A change to a .gyp, .gypi, or to GYP itself should run the generator.
|
||||
# TODO(chrisha): Fix the GYP files so that they work without
|
||||
# --no-circular-check.
|
||||
"pattern": ".",
|
||||
"action": ["python",
|
||||
"src/src/tools/gyp/gyp",
|
||||
"src/src/tools/gyp/gyp_main.py",
|
||||
"--no-circular-check",
|
||||
"src/src/client/windows/breakpad_client.gyp"],
|
||||
},
|
||||
]
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
c53ed143108948eb7e2d7ee77dc8c0d92050ce7c
|
|
@ -1,19 +1,25 @@
|
|||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||
2006 Free Software Foundation, Inc.
|
||||
Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation,
|
||||
Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. This file is offered as-is,
|
||||
without warranty of any kind.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package.
|
||||
instructions specific to this package. Some packages provide this
|
||||
`INSTALL' file but do not implement all of the features documented
|
||||
below. The lack of an optional feature in a given package is not
|
||||
necessarily a bug. More recommendations for GNU packages can be found
|
||||
in *note Makefile Conventions: (standards)Makefile Conventions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
|
@ -42,7 +48,7 @@ may remove or edit it.
|
|||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system.
|
||||
|
@ -53,12 +59,22 @@ The simplest way to compile this package is:
|
|||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
the package, generally using the just-built uninstalled binaries.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
documentation. When installing into a prefix owned by root, it is
|
||||
recommended that the package be configured and built as a regular
|
||||
user, and only the `make install' phase executed with root
|
||||
privileges.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
5. Optionally, type `make installcheck' to repeat any self-tests, but
|
||||
this time using the binaries in their final installed location.
|
||||
This target does not install anything. Running this target as a
|
||||
regular user, particularly if the prior `make install' required
|
||||
root privileges, verifies that the installation completed
|
||||
correctly.
|
||||
|
||||
6. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
|
@ -67,12 +83,22 @@ The simplest way to compile this package is:
|
|||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
7. Often, you can also type `make uninstall' to remove the installed
|
||||
files again. In practice, not all packages have tested that
|
||||
uninstallation works correctly, even though it is required by the
|
||||
GNU Coding Standards.
|
||||
|
||||
8. Some packages, particularly those that use Automake, provide `make
|
||||
distcheck', which can by used by developers to test that all other
|
||||
targets like `make install' and `make uninstall' work correctly.
|
||||
This target is generally not run by end users.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that the
|
||||
`configure' script does not know about. Run `./configure --help' for
|
||||
details on some of the pertinent environment variables.
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. Run `./configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
|
@ -85,25 +111,41 @@ is an example:
|
|||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
source code in the directory that `configure' is in and in `..'. This
|
||||
is known as a "VPATH" build.
|
||||
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
On MacOS X 10.5 and later systems, you can create libraries and
|
||||
executables that work on multiple system types--known as "fat" or
|
||||
"universal" binaries--by specifying multiple `-arch' options to the
|
||||
compiler but only a single `-arch' option to the preprocessor. Like
|
||||
this:
|
||||
|
||||
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
|
||||
CPP="gcc -E" CXXCPP="g++ -E"
|
||||
|
||||
This is not guaranteed to produce working output in all cases, you
|
||||
may have to build one architecture at a time and combine the results
|
||||
using the `lipo' tool if you have problems.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX'.
|
||||
`configure' the option `--prefix=PREFIX', where PREFIX must be an
|
||||
absolute file name.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
|
@ -114,16 +156,47 @@ Documentation and other data files still use the regular prefix.
|
|||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
you can set and what kinds of files go in them. In general, the
|
||||
default for these options is expressed in terms of `${prefix}', so that
|
||||
specifying just `--prefix' will affect all of the other directory
|
||||
specifications that were not explicitly provided.
|
||||
|
||||
The most portable way to affect installation locations is to pass the
|
||||
correct locations to `configure'; however, many packages provide one or
|
||||
both of the following shortcuts of passing variable assignments to the
|
||||
`make install' command line to change installation locations without
|
||||
having to reconfigure or recompile.
|
||||
|
||||
The first method involves providing an override variable for each
|
||||
affected directory. For example, `make install
|
||||
prefix=/alternate/directory' will choose an alternate location for all
|
||||
directory configuration variables that were expressed in terms of
|
||||
`${prefix}'. Any directories that were specified during `configure',
|
||||
but not in terms of `${prefix}', must each be overridden at install
|
||||
time for the entire installation to be relocated. The approach of
|
||||
makefile variable overrides for each directory variable is required by
|
||||
the GNU Coding Standards, and ideally causes no recompilation.
|
||||
However, some platforms have known limitations with the semantics of
|
||||
shared libraries that end up requiring recompilation when using this
|
||||
method, particularly noticeable in packages that use GNU Libtool.
|
||||
|
||||
The second method involves providing the `DESTDIR' variable. For
|
||||
example, `make install DESTDIR=/alternate/directory' will prepend
|
||||
`/alternate/directory' before all installation names. The approach of
|
||||
`DESTDIR' overrides is not required by the GNU Coding Standards, and
|
||||
does not work on platforms that have drive letters. On the other hand,
|
||||
it does better at avoiding recompilation issues, and works well even
|
||||
when some directory options were not specified in terms of `${prefix}'
|
||||
at `configure' time.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
|
@ -135,14 +208,58 @@ find the X include and library files automatically, but if it doesn't,
|
|||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Some packages offer the ability to configure how verbose the
|
||||
execution of `make' will be. For these packages, running `./configure
|
||||
--enable-silent-rules' sets the default to minimal output, which can be
|
||||
overridden with `make V=1'; while running `./configure
|
||||
--disable-silent-rules' sets the default to verbose, which can be
|
||||
overridden with `make V=0'.
|
||||
|
||||
Particular systems
|
||||
==================
|
||||
|
||||
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
|
||||
CC is not installed, it is recommended to use the following options in
|
||||
order to use an ANSI C compiler:
|
||||
|
||||
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
|
||||
|
||||
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
|
||||
|
||||
HP-UX `make' updates targets which have the same time stamps as
|
||||
their prerequisites, which makes it generally unusable when shipped
|
||||
generated files such as `configure' are involved. Use GNU `make'
|
||||
instead.
|
||||
|
||||
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
|
||||
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
|
||||
a workaround. If GNU CC is not installed, it is therefore recommended
|
||||
to try
|
||||
|
||||
./configure CC="cc"
|
||||
|
||||
and if that doesn't work, try
|
||||
|
||||
./configure CC="cc -nodtk"
|
||||
|
||||
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
|
||||
directory contains several dysfunctional programs; working variants of
|
||||
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
|
||||
in your `PATH', put it _after_ `/usr/bin'.
|
||||
|
||||
On Haiku, software installed for all users goes in `/boot/common',
|
||||
not `/usr/local'. It is recommended to use the following options:
|
||||
|
||||
./configure --prefix=/boot/common
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out automatically,
|
||||
but needs to determine by the type of machine the package will run on.
|
||||
Usually, assuming the package is built to be run on the _same_
|
||||
architectures, `configure' can figure that out, but if it prints a
|
||||
message saying it cannot guess the machine type, give it the
|
||||
There may be some features `configure' cannot figure out
|
||||
automatically, but needs to determine by the type of machine the package
|
||||
will run on. Usually, assuming the package is built to be run on the
|
||||
_same_ architectures, `configure' can figure that out, but if it prints
|
||||
a message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
|
@ -150,7 +267,8 @@ type, such as `sun4', or a canonical name which has the form:
|
|||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
OS
|
||||
KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
|
@ -168,9 +286,9 @@ eventually be run) with `--host=TYPE'.
|
|||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share, you
|
||||
can create a site shell script called `config.site' that gives default
|
||||
values for variables like `CC', `cache_file', and `prefix'.
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
|
@ -179,7 +297,7 @@ A warning: not all `configure' scripts look for a site script.
|
|||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
|
@ -191,18 +309,27 @@ causes the specified `gcc' to be used as the C compiler (unless it is
|
|||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||
an Autoconf limitation. Until the limitation is lifted, you can use
|
||||
this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it operates.
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
Print a summary of all of the options to `configure', and exit.
|
||||
|
||||
`--help=short'
|
||||
`--help=recursive'
|
||||
Print a summary of the options unique to this package's
|
||||
`configure', and exit. The `short' variant lists options used
|
||||
only in the top level, while the `recursive' variant lists options
|
||||
also present in any nested packages.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
|
@ -229,6 +356,15 @@ an Autoconf bug. Until the bug is fixed you can use this workaround:
|
|||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`--prefix=DIR'
|
||||
Use DIR as the installation prefix. *note Installation Names::
|
||||
for more details, including other options available for fine-tuning
|
||||
the installation locations.
|
||||
|
||||
`--no-create'
|
||||
`-n'
|
||||
Run the configure checks, but stop before creating any output
|
||||
files.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
||||
|
|
|
@ -26,3 +26,25 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Copyright 2001-2004 Unicode, Inc.
|
||||
|
||||
Disclaimer
|
||||
|
||||
This source code is provided as is by Unicode, Inc. No claims are
|
||||
made as to fitness for any particular purpose. No warranties of any
|
||||
kind are expressed or implied. The recipient agrees to determine
|
||||
applicability of information provided. If this file has been
|
||||
purchased on magnetic or optical media from Unicode, Inc., the
|
||||
sole remedy for any claim will be exchange of defective media
|
||||
within 90 days of receipt.
|
||||
|
||||
Limitations on Rights to Redistribute This Code
|
||||
|
||||
Unicode, Inc. hereby grants the right to freely use the information
|
||||
supplied in this file in the creation of products supporting the
|
||||
Unicode Standard, and to make copies of this file in any form
|
||||
for internal or external distribution as long as this notice
|
||||
remains attached.
|
|
@ -64,17 +64,50 @@ endif
|
|||
# Specify include paths for ac macros
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
# License file is called LICENSE not COPYING
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
## Documentation
|
||||
docdir = $(prefix)/share/doc/$(PACKAGE)-$(VERSION)
|
||||
|
||||
dist_doc_DATA = \
|
||||
AUTHORS \
|
||||
COPYING \
|
||||
ChangeLog \
|
||||
INSTALL \
|
||||
LICENSE \
|
||||
NEWS \
|
||||
README
|
||||
README.md
|
||||
|
||||
## Headers
|
||||
if LINUX_HOST
|
||||
includeclhdir = $(includedir)/$(PACKAGE)/client/linux/handler
|
||||
includeclh_HEADERS = $(top_srcdir)/src/client/linux/handler/*.h
|
||||
|
||||
includeclmdir = $(includedir)/$(PACKAGE)/client/linux/minidump_writer
|
||||
includeclm_HEADERS = $(top_srcdir)/src/client/linux/minidump_writer/*.h
|
||||
|
||||
includeclcdir = $(includedir)/$(PACKAGE)/client/linux/crash_generation
|
||||
includeclc_HEADERS = $(top_srcdir)/src/client/linux/crash_generation/*.h
|
||||
|
||||
includelssdir = $(includedir)/$(PACKAGE)/third_party/lss
|
||||
includelss_HEADERS = $(top_srcdir)/src/third_party/lss/*.h
|
||||
|
||||
includecldir = $(includedir)/$(PACKAGE)/common/linux
|
||||
includecl_HEADERS = $(top_srcdir)/src/common/linux/*.h
|
||||
endif
|
||||
|
||||
includegbcdir = $(includedir)/$(PACKAGE)/google_breakpad/common
|
||||
includegbc_HEADERS = $(top_srcdir)/src/google_breakpad/common/*.h
|
||||
|
||||
includecdir = $(includedir)/$(PACKAGE)/common
|
||||
includec_HEADERS = $(top_srcdir)/src/common/*.h
|
||||
|
||||
includepdir = $(includedir)/$(PACKAGE)/processor
|
||||
includep_HEADERS = $(top_srcdir)/src/processor/*.h
|
||||
|
||||
## pkgconfig files
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA =
|
||||
|
||||
## Libraries
|
||||
noinst_LIBRARIES =
|
||||
|
@ -84,18 +117,23 @@ check_PROGRAMS =
|
|||
|
||||
if !DISABLE_PROCESSOR
|
||||
lib_LIBRARIES += src/libbreakpad.a
|
||||
pkgconfig_DATA += breakpad.pc
|
||||
noinst_LIBRARIES += src/third_party/libdisasm/libdisasm.a
|
||||
endif
|
||||
|
||||
if LINUX_HOST
|
||||
lib_LIBRARIES += src/client/linux/libbreakpad_client.a
|
||||
pkgconfig_DATA += breakpad-client.pc
|
||||
|
||||
src_client_linux_libbreakpad_client_a_SOURCES = \
|
||||
src/client/linux/crash_generation/crash_generation_client.cc \
|
||||
src/client/linux/crash_generation/crash_generation_server.cc \
|
||||
src/client/linux/dump_writer_common/thread_info.cc \
|
||||
src/client/linux/dump_writer_common/ucontext_reader.cc \
|
||||
src/client/linux/handler/exception_handler.cc \
|
||||
src/client/linux/handler/minidump_descriptor.cc \
|
||||
src/client/linux/log/log.cc \
|
||||
src/client/linux/microdump_writer/microdump_writer.cc \
|
||||
src/client/linux/minidump_writer/linux_dumper.cc \
|
||||
src/client/linux/minidump_writer/linux_ptrace_dumper.cc \
|
||||
src/client/linux/minidump_writer/minidump_writer.cc \
|
||||
|
@ -124,12 +162,18 @@ src_libbreakpad_a_SOURCES = \
|
|||
src/google_breakpad/processor/call_stack.h \
|
||||
src/google_breakpad/processor/code_module.h \
|
||||
src/google_breakpad/processor/code_modules.h \
|
||||
src/google_breakpad/processor/dump_context.h \
|
||||
src/google_breakpad/processor/dump_object.h \
|
||||
src/google_breakpad/processor/exploitability.h \
|
||||
src/google_breakpad/processor/fast_source_line_resolver.h \
|
||||
src/google_breakpad/processor/memory_region.h \
|
||||
src/google_breakpad/processor/microdump.h \
|
||||
src/google_breakpad/processor/microdump_processor.h \
|
||||
src/google_breakpad/processor/minidump.h \
|
||||
src/google_breakpad/processor/minidump_processor.h \
|
||||
src/google_breakpad/processor/process_result.h \
|
||||
src/google_breakpad/processor/process_state.h \
|
||||
src/google_breakpad/processor/proc_maps_linux.h \
|
||||
src/google_breakpad/processor/source_line_resolver_base.h \
|
||||
src/google_breakpad/processor/source_line_resolver_interface.h \
|
||||
src/google_breakpad/processor/stack_frame.h \
|
||||
|
@ -145,8 +189,6 @@ src_libbreakpad_a_SOURCES = \
|
|||
src/processor/basic_code_modules.h \
|
||||
src/processor/basic_source_line_resolver_types.h \
|
||||
src/processor/basic_source_line_resolver.cc \
|
||||
src/processor/binarystream.h \
|
||||
src/processor/binarystream.cc \
|
||||
src/processor/call_stack.cc \
|
||||
src/processor/cfi_frame_info.cc \
|
||||
src/processor/cfi_frame_info.h \
|
||||
|
@ -154,7 +196,11 @@ src_libbreakpad_a_SOURCES = \
|
|||
src/processor/contained_range_map.h \
|
||||
src/processor/disassembler_x86.h \
|
||||
src/processor/disassembler_x86.cc \
|
||||
src/processor/dump_context.cc \
|
||||
src/processor/dump_object.cc \
|
||||
src/processor/exploitability.cc \
|
||||
src/processor/exploitability_linux.h \
|
||||
src/processor/exploitability_linux.cc \
|
||||
src/processor/exploitability_win.h \
|
||||
src/processor/exploitability_win.cc \
|
||||
src/processor/fast_source_line_resolver_types.h \
|
||||
|
@ -164,6 +210,8 @@ src_libbreakpad_a_SOURCES = \
|
|||
src/processor/logging.cc \
|
||||
src/processor/map_serializers-inl.h \
|
||||
src/processor/map_serializers.h \
|
||||
src/processor/microdump.cc \
|
||||
src/processor/microdump_processor.cc \
|
||||
src/processor/minidump.cc \
|
||||
src/processor/minidump_processor.cc \
|
||||
src/processor/module_comparer.cc \
|
||||
|
@ -176,6 +224,7 @@ src_libbreakpad_a_SOURCES = \
|
|||
src/processor/postfix_evaluator-inl.h \
|
||||
src/processor/postfix_evaluator.h \
|
||||
src/processor/process_state.cc \
|
||||
src/processor/proc_maps_linux.cc \
|
||||
src/processor/range_map-inl.h \
|
||||
src/processor/range_map.h \
|
||||
src/processor/simple_serializer-inl.h \
|
||||
|
@ -185,14 +234,23 @@ src_libbreakpad_a_SOURCES = \
|
|||
src/processor/windows_frame_info.h \
|
||||
src/processor/source_line_resolver_base_types.h \
|
||||
src/processor/source_line_resolver_base.cc \
|
||||
src/processor/stack_frame_cpu.cc \
|
||||
src/processor/stack_frame_symbolizer.cc \
|
||||
src/processor/stackwalker.cc \
|
||||
src/processor/stackwalker_amd64.cc \
|
||||
src/processor/stackwalker_amd64.h \
|
||||
src/processor/stackwalker_arm.cc \
|
||||
src/processor/stackwalker_arm.h \
|
||||
src/processor/stackwalker_arm64.cc \
|
||||
src/processor/stackwalker_arm64.h \
|
||||
src/processor/stackwalker_address_list.cc \
|
||||
src/processor/stackwalker_address_list.h \
|
||||
src/processor/stackwalker_mips.cc \
|
||||
src/processor/stackwalker_mips.h \
|
||||
src/processor/stackwalker_ppc.cc \
|
||||
src/processor/stackwalker_ppc.h \
|
||||
src/processor/stackwalker_ppc64.cc \
|
||||
src/processor/stackwalker_ppc64.h \
|
||||
src/processor/stackwalker_sparc.cc \
|
||||
src/processor/stackwalker_sparc.h \
|
||||
src/processor/stackwalker_x86.cc \
|
||||
|
@ -207,6 +265,8 @@ src_libbreakpad_a_SOURCES = \
|
|||
src/processor/static_map.h \
|
||||
src/processor/static_range_map-inl.h \
|
||||
src/processor/static_range_map.h \
|
||||
src/processor/symbolic_constants_win.cc \
|
||||
src/processor/symbolic_constants_win.h \
|
||||
src/processor/tokenize.cc \
|
||||
src/processor/tokenize.h
|
||||
|
||||
|
@ -242,6 +302,7 @@ src_third_party_libdisasm_libdisasm_a_SOURCES = \
|
|||
|
||||
## Programs
|
||||
bin_PROGRAMS += \
|
||||
src/processor/microdump_stackwalk \
|
||||
src/processor/minidump_dump \
|
||||
src/processor/minidump_stackwalk
|
||||
endif !DISABLE_PROCESSOR
|
||||
|
@ -256,7 +317,8 @@ bin_PROGRAMS += \
|
|||
src/tools/linux/dump_syms/dump_syms \
|
||||
src/tools/linux/md2core/minidump-2-core \
|
||||
src/tools/linux/symupload/minidump_upload \
|
||||
src/tools/linux/symupload/sym_upload
|
||||
src/tools/linux/symupload/sym_upload \
|
||||
src/tools/mac/dump_syms/dump_syms
|
||||
endif
|
||||
endif LINUX_HOST
|
||||
|
||||
|
@ -266,7 +328,6 @@ if !DISABLE_PROCESSOR
|
|||
check_PROGRAMS += \
|
||||
src/common/test_assembler_unittest \
|
||||
src/processor/address_map_unittest \
|
||||
src/processor/binarystream_unittest \
|
||||
src/processor/basic_source_line_resolver_unittest \
|
||||
src/processor/cfi_frame_info_unittest \
|
||||
src/processor/contained_range_map_unittest \
|
||||
|
@ -274,6 +335,7 @@ check_PROGRAMS += \
|
|||
src/processor/exploitability_unittest \
|
||||
src/processor/fast_source_line_resolver_unittest \
|
||||
src/processor/map_serializers_unittest \
|
||||
src/processor/microdump_processor_unittest \
|
||||
src/processor/minidump_processor_unittest \
|
||||
src/processor/minidump_unittest \
|
||||
src/processor/static_address_map_unittest \
|
||||
|
@ -282,9 +344,13 @@ check_PROGRAMS += \
|
|||
src/processor/static_range_map_unittest \
|
||||
src/processor/pathname_stripper_unittest \
|
||||
src/processor/postfix_evaluator_unittest \
|
||||
src/processor/proc_maps_linux_unittest \
|
||||
src/processor/range_map_unittest \
|
||||
src/processor/stackwalker_amd64_unittest \
|
||||
src/processor/stackwalker_arm_unittest \
|
||||
src/processor/stackwalker_arm64_unittest \
|
||||
src/processor/stackwalker_address_list_unittest \
|
||||
src/processor/stackwalker_mips_unittest \
|
||||
src/processor/stackwalker_x86_unittest \
|
||||
src/processor/synth_minidump_unittest
|
||||
endif
|
||||
|
@ -299,6 +365,7 @@ check_PROGRAMS += \
|
|||
if !DISABLE_TOOLS
|
||||
check_PROGRAMS += \
|
||||
src/common/dumper_unittest \
|
||||
src/common/mac/macho_reader_unittest \
|
||||
src/tools/linux/md2core/minidump_2_core_unittest
|
||||
endif
|
||||
endif LINUX_HOST
|
||||
|
@ -312,6 +379,8 @@ endif !DISABLE_PROCESSOR
|
|||
|
||||
if !DISABLE_PROCESSOR
|
||||
check_SCRIPTS = \
|
||||
src/processor/microdump_stackwalk_test \
|
||||
src/processor/microdump_stackwalk_machine_readable_test \
|
||||
src/processor/minidump_dump_test \
|
||||
src/processor/minidump_stackwalk_test \
|
||||
src/processor/minidump_stackwalk_machine_readable_test
|
||||
|
@ -320,28 +389,40 @@ endif
|
|||
TESTS = $(check_PROGRAMS) $(check_SCRIPTS)
|
||||
|
||||
if ANDROID_HOST
|
||||
# Wrapper script to run unit test programs on a connected Android device.
|
||||
TESTS_ENVIRONMENT = $(top_srcdir)/android/test-shell.sh
|
||||
# Since Autotools 1.2, tests are run through a special "test driver" script.
|
||||
# Unfortunately, it's not possible anymore to specify an alternative shell to
|
||||
# run them on connected devices, so use a slightly modified version of the
|
||||
# driver for Android.
|
||||
LOG_DRIVER = $(top_srcdir)/android/test-driver
|
||||
else
|
||||
TESTS_ENVIRONMENT =
|
||||
# The default Autotools test driver script.
|
||||
LOG_DRIVER = $(top_srcdir)/autotools/test-driver
|
||||
endif
|
||||
|
||||
if LINUX_HOST
|
||||
src_client_linux_linux_dumper_unittest_helper_SOURCES = \
|
||||
src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
|
||||
src_client_linux_linux_dumper_unittest_helper_CXXFLAGS=$(PTHREAD_CFLAGS)
|
||||
src_client_linux_linux_dumper_unittest_helper_LDFLAGS=$(PTHREAD_CFLAGS)
|
||||
src_client_linux_linux_dumper_unittest_helper_CC=$(PTHREAD_CC)
|
||||
if ANDROID_HOST
|
||||
# On Android PTHREAD_CFLAGS is empty, and adding src/common/android/include
|
||||
# to the include path is necessary to build this program.
|
||||
src_client_linux_linux_dumper_unittest_helper_CXXFLAGS=$(AM_CXXFLAGS)
|
||||
else
|
||||
src_client_linux_linux_dumper_unittest_helper_CXXFLAGS=$(PTHREAD_CFLAGS)
|
||||
endif
|
||||
|
||||
src_client_linux_linux_client_unittest_shlib_SOURCES = \
|
||||
src/client/linux/handler/exception_handler_unittest.cc \
|
||||
src/client/linux/minidump_writer/directory_reader_unittest.cc \
|
||||
src/client/linux/minidump_writer/cpu_set_unittest.cc \
|
||||
src/client/linux/minidump_writer/line_reader_unittest.cc \
|
||||
src/client/linux/minidump_writer/linux_core_dumper.cc \
|
||||
src/client/linux/minidump_writer/linux_core_dumper_unittest.cc \
|
||||
src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc \
|
||||
src/client/linux/minidump_writer/minidump_writer_unittest.cc \
|
||||
src/client/linux/minidump_writer/minidump_writer_unittest_utils.cc \
|
||||
src/client/linux/minidump_writer/proc_cpuinfo_reader_unittest.cc \
|
||||
src/common/linux/elf_core_dump.cc \
|
||||
src/common/linux/linux_libc_support_unittest.cc \
|
||||
src/common/linux/tests/crash_generator.cc \
|
||||
|
@ -351,13 +432,20 @@ src_client_linux_linux_client_unittest_shlib_SOURCES = \
|
|||
src/testing/gtest/src/gtest_main.cc \
|
||||
src/testing/src/gmock-all.cc \
|
||||
src/processor/basic_code_modules.cc \
|
||||
src/processor/dump_context.cc \
|
||||
src/processor/dump_object.cc \
|
||||
src/processor/logging.cc \
|
||||
src/processor/minidump.cc \
|
||||
src/processor/pathname_stripper.cc
|
||||
src/processor/pathname_stripper.cc \
|
||||
src/processor/proc_maps_linux.cc
|
||||
if ANDROID_HOST
|
||||
src_client_linux_linux_client_unittest_shlib_SOURCES += \
|
||||
src/common/android/breakpad_getcontext.S
|
||||
endif
|
||||
if LINUX_HOST
|
||||
src_client_linux_linux_client_unittest_shlib_SOURCES += \
|
||||
src/client/linux/microdump_writer/microdump_writer_unittest.cc
|
||||
endif
|
||||
|
||||
src_client_linux_linux_client_unittest_shlib_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src \
|
||||
|
@ -369,10 +457,13 @@ src_client_linux_linux_client_unittest_shlib_LDFLAGS = \
|
|||
-shared \
|
||||
-Wl,-h,linux_client_unittest_shlib
|
||||
src_client_linux_linux_client_unittest_shlib_LDADD = \
|
||||
src/client/linux/crash_generation/crash_generation_client.o \
|
||||
src/client/linux/dump_writer_common/thread_info.o \
|
||||
src/client/linux/dump_writer_common/ucontext_reader.o \
|
||||
src/client/linux/handler/exception_handler.o \
|
||||
src/client/linux/handler/minidump_descriptor.o \
|
||||
src/client/linux/log/log.o \
|
||||
src/client/linux/crash_generation/crash_generation_client.o \
|
||||
src/client/linux/microdump_writer/microdump_writer.o \
|
||||
src/client/linux/minidump_writer/linux_dumper.o \
|
||||
src/client/linux/minidump_writer/linux_ptrace_dumper.o \
|
||||
src/client/linux/minidump_writer/minidump_writer.o \
|
||||
|
@ -433,6 +524,7 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \
|
|||
src/common/dwarf/bytereader.cc \
|
||||
src/common/dwarf/dwarf2diehandler.cc \
|
||||
src/common/dwarf/dwarf2reader.cc \
|
||||
src/common/linux/crc32.cc \
|
||||
src/common/linux/dump_symbols.cc \
|
||||
src/common/linux/elf_symbols_to_module.cc \
|
||||
src/common/linux/elfutils.cc \
|
||||
|
@ -456,6 +548,30 @@ src_tools_linux_symupload_sym_upload_SOURCES = \
|
|||
src/tools/linux/symupload/sym_upload.cc
|
||||
src_tools_linux_symupload_sym_upload_LDADD = -ldl
|
||||
|
||||
src_tools_mac_dump_syms_dump_syms_SOURCES = \
|
||||
src/common/dwarf_cfi_to_module.cc \
|
||||
src/common/dwarf_cu_to_module.cc \
|
||||
src/common/dwarf_line_to_module.cc \
|
||||
src/common/language.cc \
|
||||
src/common/md5.cc \
|
||||
src/common/module.cc \
|
||||
src/common/stabs_reader.cc \
|
||||
src/common/stabs_to_module.cc \
|
||||
src/common/dwarf/bytereader.cc \
|
||||
src/common/dwarf/dwarf2diehandler.cc \
|
||||
src/common/dwarf/dwarf2reader.cc \
|
||||
src/common/mac/arch_utilities.cc \
|
||||
src/common/mac/dump_syms.cc \
|
||||
src/common/mac/file_id.cc \
|
||||
src/common/mac/macho_id.cc \
|
||||
src/common/mac/macho_reader.cc \
|
||||
src/common/mac/macho_utilities.cc \
|
||||
src/common/mac/macho_walker.cc \
|
||||
src/tools/mac/dump_syms/dump_syms_tool.cc
|
||||
src_tools_mac_dump_syms_dump_syms_CXXFLAGS= \
|
||||
-I$(top_srcdir)/src/third_party/mac_headers \
|
||||
-DHAVE_MACH_O_NLIST_H
|
||||
|
||||
src_common_dumper_unittest_SOURCES = \
|
||||
src/common/byte_cursor_unittest.cc \
|
||||
src/common/dwarf_cfi_to_module.cc \
|
||||
|
@ -481,6 +597,7 @@ src_common_dumper_unittest_SOURCES = \
|
|||
src/common/dwarf/dwarf2reader.cc \
|
||||
src/common/dwarf/dwarf2reader_cfi_unittest.cc \
|
||||
src/common/dwarf/dwarf2reader_die_unittest.cc \
|
||||
src/common/linux/crc32.cc \
|
||||
src/common/linux/dump_symbols.cc \
|
||||
src/common/linux/dump_symbols_unittest.cc \
|
||||
src/common/linux/elf_core_dump.cc \
|
||||
|
@ -510,6 +627,42 @@ src_common_dumper_unittest_CPPFLAGS = \
|
|||
-I$(top_srcdir)/src/testing \
|
||||
$(PTHREAD_CFLAGS)
|
||||
src_common_dumper_unittest_LDADD = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
|
||||
src_common_mac_macho_reader_unittest_SOURCES = \
|
||||
src/common/dwarf_cfi_to_module.cc \
|
||||
src/common/dwarf_cu_to_module.cc \
|
||||
src/common/dwarf_line_to_module.cc \
|
||||
src/common/language.cc \
|
||||
src/common/md5.cc \
|
||||
src/common/module.cc \
|
||||
src/common/stabs_reader.cc \
|
||||
src/common/stabs_to_module.cc \
|
||||
src/common/test_assembler.cc \
|
||||
src/common/dwarf/bytereader.cc \
|
||||
src/common/dwarf/cfi_assembler.cc \
|
||||
src/common/dwarf/dwarf2diehandler.cc \
|
||||
src/common/dwarf/dwarf2reader.cc \
|
||||
src/common/mac/arch_utilities.cc \
|
||||
src/common/mac/file_id.cc \
|
||||
src/common/mac/macho_id.cc \
|
||||
src/common/mac/macho_reader.cc \
|
||||
src/common/mac/macho_reader_unittest.cc \
|
||||
src/common/mac/macho_utilities.cc \
|
||||
src/common/mac/macho_walker.cc \
|
||||
src/common/tests/file_utils.cc \
|
||||
src/testing/gtest/src/gtest-all.cc \
|
||||
src/testing/gtest/src/gtest_main.cc \
|
||||
src/testing/src/gmock-all.cc
|
||||
src_common_mac_macho_reader_unittest_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/testing/include \
|
||||
-I$(top_srcdir)/src/testing/gtest/include \
|
||||
-I$(top_srcdir)/src/testing/gtest \
|
||||
-I$(top_srcdir)/src/testing \
|
||||
-I$(top_srcdir)/src/third_party/mac_headers \
|
||||
-DHAVE_MACH_O_NLIST_H \
|
||||
$(PTHREAD_CFLAGS)
|
||||
src_common_mac_macho_reader_unittest_LDADD = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
endif
|
||||
|
||||
src_tools_linux_md2core_minidump_2_core_unittest_SOURCES = \
|
||||
|
@ -535,20 +688,6 @@ src_processor_address_map_unittest_LDADD = \
|
|||
src/processor/logging.o \
|
||||
src/processor/pathname_stripper.o
|
||||
|
||||
src_processor_binarystream_unittest_SOURCES = \
|
||||
src/processor/binarystream_unittest.cc \
|
||||
src/testing/gtest/src/gtest-all.cc \
|
||||
src/testing/src/gmock-all.cc
|
||||
src_processor_binarystream_unittest_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/testing/include \
|
||||
-I$(top_srcdir)/src/testing/gtest/include \
|
||||
-I$(top_srcdir)/src/testing/gtest \
|
||||
-I$(top_srcdir)/src/testing
|
||||
src_processor_binarystream_unittest_LDADD = \
|
||||
src/processor/binarystream.o \
|
||||
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
|
||||
src_processor_basic_source_line_resolver_unittest_SOURCES = \
|
||||
src/processor/basic_source_line_resolver_unittest.cc \
|
||||
src/testing/gtest/src/gtest-all.cc \
|
||||
|
@ -607,22 +746,33 @@ src_processor_exploitability_unittest_LDADD = \
|
|||
src/processor/process_state.o \
|
||||
src/processor/disassembler_x86.o \
|
||||
src/processor/exploitability.o \
|
||||
src/processor/exploitability_linux.o \
|
||||
src/processor/exploitability_win.o \
|
||||
src/processor/basic_code_modules.o \
|
||||
src/processor/basic_source_line_resolver.o \
|
||||
src/processor/call_stack.o \
|
||||
src/processor/cfi_frame_info.o \
|
||||
src/processor/dump_context.o \
|
||||
src/processor/dump_object.o \
|
||||
src/processor/logging.o \
|
||||
src/processor/minidump.o \
|
||||
src/processor/pathname_stripper.o \
|
||||
src/processor/proc_maps_linux.o \
|
||||
src/processor/simple_symbol_supplier.o \
|
||||
src/processor/source_line_resolver_base.o \
|
||||
src/processor/stack_frame_cpu.o \
|
||||
src/processor/stack_frame_symbolizer.o \
|
||||
src/processor/stackwalker.o \
|
||||
src/processor/stackwalker_address_list.o \
|
||||
src/processor/stackwalker_amd64.o \
|
||||
src/processor/stackwalker_arm.o \
|
||||
src/processor/stackwalker_arm64.o \
|
||||
src/processor/stackwalker_mips.o \
|
||||
src/processor/stackwalker_ppc.o \
|
||||
src/processor/stackwalker_ppc64.o \
|
||||
src/processor/stackwalker_sparc.o \
|
||||
src/processor/stackwalker_x86.o \
|
||||
src/processor/symbolic_constants_win.o \
|
||||
src/processor/tokenize.o \
|
||||
src/third_party/libdisasm/libdisasm.a \
|
||||
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
|
@ -680,6 +830,44 @@ src_processor_map_serializers_unittest_LDADD = \
|
|||
src/processor/pathname_stripper.o \
|
||||
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
|
||||
src_processor_microdump_processor_unittest_SOURCES = \
|
||||
src/processor/microdump_processor_unittest.cc \
|
||||
src/testing/gtest/src/gtest-all.cc \
|
||||
src/testing/src/gmock-all.cc
|
||||
src_processor_microdump_processor_unittest_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/testing/include \
|
||||
-I$(top_srcdir)/src/testing/gtest/include \
|
||||
-I$(top_srcdir)/src/testing/gtest \
|
||||
-I$(top_srcdir)/src/testing
|
||||
src_processor_microdump_processor_unittest_LDADD = \
|
||||
src/processor/basic_code_modules.o \
|
||||
src/processor/basic_source_line_resolver.o \
|
||||
src/processor/call_stack.o \
|
||||
src/processor/cfi_frame_info.o \
|
||||
src/processor/dump_context.o \
|
||||
src/processor/dump_object.o \
|
||||
src/processor/logging.o \
|
||||
src/processor/microdump.o \
|
||||
src/processor/microdump_processor.o \
|
||||
src/processor/pathname_stripper.o \
|
||||
src/processor/process_state.o \
|
||||
src/processor/simple_symbol_supplier.o \
|
||||
src/processor/source_line_resolver_base.o \
|
||||
src/processor/stack_frame_symbolizer.o \
|
||||
src/processor/stackwalker.o \
|
||||
src/processor/stackwalker_address_list.o \
|
||||
src/processor/stackwalker_amd64.o \
|
||||
src/processor/stackwalker_arm.o \
|
||||
src/processor/stackwalker_arm64.o \
|
||||
src/processor/stackwalker_mips.o \
|
||||
src/processor/stackwalker_ppc.o \
|
||||
src/processor/stackwalker_ppc64.o \
|
||||
src/processor/stackwalker_sparc.o \
|
||||
src/processor/stackwalker_x86.o \
|
||||
src/processor/tokenize.o \
|
||||
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
|
||||
src_processor_minidump_processor_unittest_SOURCES = \
|
||||
src/processor/minidump_processor_unittest.cc \
|
||||
src/testing/gtest/src/gtest-all.cc \
|
||||
|
@ -696,21 +884,31 @@ src_processor_minidump_processor_unittest_LDADD = \
|
|||
src/processor/call_stack.o \
|
||||
src/processor/cfi_frame_info.o \
|
||||
src/processor/disassembler_x86.o \
|
||||
src/processor/dump_context.o \
|
||||
src/processor/dump_object.o \
|
||||
src/processor/exploitability.o \
|
||||
src/processor/exploitability_linux.o \
|
||||
src/processor/exploitability_win.o \
|
||||
src/processor/logging.o \
|
||||
src/processor/minidump_processor.o \
|
||||
src/processor/minidump.o \
|
||||
src/processor/pathname_stripper.o \
|
||||
src/processor/process_state.o \
|
||||
src/processor/proc_maps_linux.o \
|
||||
src/processor/source_line_resolver_base.o \
|
||||
src/processor/stack_frame_cpu.o \
|
||||
src/processor/stack_frame_symbolizer.o \
|
||||
src/processor/stackwalker.o \
|
||||
src/processor/stackwalker_address_list.o \
|
||||
src/processor/stackwalker_amd64.o \
|
||||
src/processor/stackwalker_arm.o \
|
||||
src/processor/stackwalker_arm64.o \
|
||||
src/processor/stackwalker_mips.o \
|
||||
src/processor/stackwalker_ppc.o \
|
||||
src/processor/stackwalker_ppc64.o \
|
||||
src/processor/stackwalker_sparc.o \
|
||||
src/processor/stackwalker_x86.o \
|
||||
src/processor/symbolic_constants_win.o \
|
||||
src/processor/tokenize.o \
|
||||
src/third_party/libdisasm/libdisasm.a \
|
||||
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
|
@ -730,9 +928,30 @@ src_processor_minidump_unittest_CPPFLAGS = \
|
|||
-I$(top_srcdir)/src/testing
|
||||
src_processor_minidump_unittest_LDADD = \
|
||||
src/processor/basic_code_modules.o \
|
||||
src/processor/dump_context.o \
|
||||
src/processor/dump_object.o \
|
||||
src/processor/logging.o \
|
||||
src/processor/minidump.o \
|
||||
src/processor/pathname_stripper.o \
|
||||
src/processor/proc_maps_linux.o \
|
||||
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
|
||||
src_processor_proc_maps_linux_unittest_SOURCES = \
|
||||
src/processor/proc_maps_linux.cc \
|
||||
src/processor/proc_maps_linux_unittest.cc \
|
||||
src/testing/gtest/src/gtest-all.cc \
|
||||
src/testing/gtest/src/gtest_main.cc \
|
||||
src/testing/src/gmock-all.cc
|
||||
src_processor_proc_maps_linux_unittest_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/testing/include \
|
||||
-I$(top_srcdir)/src/testing/gtest/include \
|
||||
-I$(top_srcdir)/src/testing/gtest \
|
||||
-I$(top_srcdir)/src/testing
|
||||
src_processor_proc_maps_linux_unittest_LDADD = \
|
||||
src/processor/logging.o \
|
||||
src/processor/pathname_stripper.o \
|
||||
src/third_party/libdisasm/libdisasm.a \
|
||||
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
|
||||
src_processor_static_address_map_unittest_SOURCES = \
|
||||
|
@ -823,16 +1042,23 @@ src_processor_stackwalker_selftest_LDADD = \
|
|||
src/processor/call_stack.o \
|
||||
src/processor/disassembler_x86.o \
|
||||
src/processor/exploitability.o \
|
||||
src/processor/exploitability_linux.o \
|
||||
src/processor/exploitability_win.o \
|
||||
src/processor/logging.o \
|
||||
src/processor/minidump.o \
|
||||
src/processor/pathname_stripper.o \
|
||||
src/processor/proc_maps_linux.o \
|
||||
src/processor/source_line_resolver_base.o \
|
||||
src/processor/stack_frame_cpu.o \
|
||||
src/processor/stack_frame_symbolizer.o \
|
||||
src/processor/stackwalker.o \
|
||||
src/processor/stackwalker_address_list.o \
|
||||
src/processor/stackwalker_amd64.o \
|
||||
src/processor/stackwalker_arm.o \
|
||||
src/processor/stackwalker_arm64.o \
|
||||
src/processor/stackwalker_mips.o \
|
||||
src/processor/stackwalker_ppc.o \
|
||||
src/processor/stackwalker_ppc64.o \
|
||||
src/processor/stackwalker_sparc.o \
|
||||
src/processor/stackwalker_x86.o \
|
||||
src/processor/tokenize.o \
|
||||
|
@ -870,6 +1096,54 @@ src_processor_stackwalker_arm_unittest_CPPFLAGS = \
|
|||
-I$(top_srcdir)/src/testing/gtest \
|
||||
-I$(top_srcdir)/src/testing
|
||||
|
||||
src_processor_stackwalker_arm64_unittest_SOURCES = \
|
||||
src/common/test_assembler.cc \
|
||||
src/processor/stackwalker_arm64_unittest.cc \
|
||||
src/testing/gtest/src/gtest-all.cc \
|
||||
src/testing/gtest/src/gtest_main.cc \
|
||||
src/testing/src/gmock-all.cc
|
||||
src_processor_stackwalker_arm64_unittest_LDADD = \
|
||||
src/libbreakpad.a \
|
||||
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
src_processor_stackwalker_arm64_unittest_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/testing/include \
|
||||
-I$(top_srcdir)/src/testing/gtest/include \
|
||||
-I$(top_srcdir)/src/testing/gtest \
|
||||
-I$(top_srcdir)/src/testing
|
||||
|
||||
src_processor_stackwalker_address_list_unittest_SOURCES = \
|
||||
src/common/test_assembler.cc \
|
||||
src/processor/stackwalker_address_list_unittest.cc \
|
||||
src/testing/gtest/src/gtest-all.cc \
|
||||
src/testing/gtest/src/gtest_main.cc \
|
||||
src/testing/src/gmock-all.cc
|
||||
src_processor_stackwalker_address_list_unittest_LDADD = \
|
||||
src/libbreakpad.a \
|
||||
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
src_processor_stackwalker_address_list_unittest_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/testing/include \
|
||||
-I$(top_srcdir)/src/testing/gtest/include \
|
||||
-I$(top_srcdir)/src/testing/gtest \
|
||||
-I$(top_srcdir)/src/testing
|
||||
|
||||
src_processor_stackwalker_mips_unittest_SOURCES = \
|
||||
src/common/test_assembler.cc \
|
||||
src/processor/stackwalker_mips_unittest.cc \
|
||||
src/testing/gtest/src/gtest-all.cc \
|
||||
src/testing/gtest/src/gtest_main.cc \
|
||||
src/testing/src/gmock-all.cc
|
||||
src_processor_stackwalker_mips_unittest_LDADD = \
|
||||
src/libbreakpad.a \
|
||||
$(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
src_processor_stackwalker_mips_unittest_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/src/testing/include \
|
||||
-I$(top_srcdir)/src/testing/gtest/include \
|
||||
-I$(top_srcdir)/src/testing/gtest \
|
||||
-I$(top_srcdir)/src/testing
|
||||
|
||||
src_processor_stackwalker_x86_unittest_SOURCES = \
|
||||
src/common/test_assembler.cc \
|
||||
src/processor/stackwalker_x86_unittest.cc \
|
||||
|
@ -926,35 +1200,81 @@ src_processor_minidump_dump_SOURCES = \
|
|||
src/processor/minidump_dump.cc
|
||||
src_processor_minidump_dump_LDADD = \
|
||||
src/processor/basic_code_modules.o \
|
||||
src/processor/dump_context.o \
|
||||
src/processor/dump_object.o \
|
||||
src/processor/logging.o \
|
||||
src/processor/minidump.o \
|
||||
src/processor/pathname_stripper.o
|
||||
src/processor/pathname_stripper.o \
|
||||
src/processor/proc_maps_linux.o
|
||||
|
||||
src_processor_microdump_stackwalk_SOURCES = \
|
||||
src/processor/microdump_stackwalk.cc
|
||||
src_processor_microdump_stackwalk_LDADD = \
|
||||
src/processor/basic_code_modules.o \
|
||||
src/processor/basic_source_line_resolver.o \
|
||||
src/processor/call_stack.o \
|
||||
src/processor/cfi_frame_info.o \
|
||||
src/processor/disassembler_x86.o \
|
||||
src/processor/dump_context.o \
|
||||
src/processor/dump_object.o \
|
||||
src/processor/logging.o \
|
||||
src/processor/microdump.o \
|
||||
src/processor/microdump_processor.o \
|
||||
src/processor/pathname_stripper.o \
|
||||
src/processor/process_state.o \
|
||||
src/processor/simple_symbol_supplier.o \
|
||||
src/processor/source_line_resolver_base.o \
|
||||
src/processor/stack_frame_cpu.o \
|
||||
src/processor/stack_frame_symbolizer.o \
|
||||
src/processor/stackwalk_common.o \
|
||||
src/processor/stackwalker.o \
|
||||
src/processor/stackwalker_address_list.o \
|
||||
src/processor/stackwalker_amd64.o \
|
||||
src/processor/stackwalker_arm.o \
|
||||
src/processor/stackwalker_arm64.o \
|
||||
src/processor/stackwalker_mips.o \
|
||||
src/processor/stackwalker_ppc.o \
|
||||
src/processor/stackwalker_ppc64.o \
|
||||
src/processor/stackwalker_sparc.o \
|
||||
src/processor/stackwalker_x86.o \
|
||||
src/processor/tokenize.o \
|
||||
src/third_party/libdisasm/libdisasm.a
|
||||
|
||||
src_processor_minidump_stackwalk_SOURCES = \
|
||||
src/processor/minidump_stackwalk.cc
|
||||
src_processor_minidump_stackwalk_LDADD = \
|
||||
src/processor/basic_code_modules.o \
|
||||
src/processor/basic_source_line_resolver.o \
|
||||
src/processor/binarystream.o \
|
||||
src/processor/call_stack.o \
|
||||
src/processor/cfi_frame_info.o \
|
||||
src/processor/disassembler_x86.o \
|
||||
src/processor/dump_context.o \
|
||||
src/processor/dump_object.o \
|
||||
src/processor/exploitability.o \
|
||||
src/processor/exploitability_linux.o \
|
||||
src/processor/exploitability_win.o \
|
||||
src/processor/logging.o \
|
||||
src/processor/minidump.o \
|
||||
src/processor/minidump_processor.o \
|
||||
src/processor/pathname_stripper.o \
|
||||
src/processor/process_state.o \
|
||||
src/processor/proc_maps_linux.o \
|
||||
src/processor/simple_symbol_supplier.o \
|
||||
src/processor/source_line_resolver_base.o \
|
||||
src/processor/stack_frame_cpu.o \
|
||||
src/processor/stack_frame_symbolizer.o \
|
||||
src/processor/stackwalk_common.o \
|
||||
src/processor/stackwalker.o \
|
||||
src/processor/stackwalker_address_list.o \
|
||||
src/processor/stackwalker_amd64.o \
|
||||
src/processor/stackwalker_arm.o \
|
||||
src/processor/stackwalker_arm64.o \
|
||||
src/processor/stackwalker_mips.o \
|
||||
src/processor/stackwalker_ppc.o \
|
||||
src/processor/stackwalker_ppc64.o \
|
||||
src/processor/stackwalker_sparc.o \
|
||||
src/processor/stackwalker_x86.o \
|
||||
src/processor/symbolic_constants_win.o \
|
||||
src/processor/tokenize.o \
|
||||
src/third_party/libdisasm/libdisasm.a
|
||||
|
||||
|
@ -1013,6 +1333,7 @@ EXTRA_DIST = \
|
|||
src/client/windows/sender/crash_report_sender.vcproj \
|
||||
src/common/convert_UTF.c \
|
||||
src/common/convert_UTF.h \
|
||||
src/common/linux/crc32.cc \
|
||||
src/common/linux/dump_symbols.cc \
|
||||
src/common/linux/dump_symbols.h \
|
||||
src/common/linux/elf_symbols_to_module.cc \
|
||||
|
@ -1028,7 +1349,7 @@ EXTRA_DIST = \
|
|||
src/common/mac/HTTPMultipartUpload.h \
|
||||
src/common/mac/HTTPMultipartUpload.m \
|
||||
src/common/mac/dump_syms.h \
|
||||
src/common/mac/dump_syms.mm \
|
||||
src/common/mac/dump_syms.cc \
|
||||
src/common/mac/file_id.cc \
|
||||
src/common/mac/file_id.h \
|
||||
src/common/mac/macho_id.cc \
|
||||
|
@ -1080,7 +1401,7 @@ EXTRA_DIST = \
|
|||
src/tools/mac/crash_report/on_demand_symbol_supplier.h \
|
||||
src/tools/mac/crash_report/on_demand_symbol_supplier.mm \
|
||||
src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj \
|
||||
src/tools/mac/dump_syms/dump_syms_tool.m \
|
||||
src/tools/mac/dump_syms/dump_syms_tool.cc \
|
||||
src/tools/mac/symupload/minidump_upload.m \
|
||||
src/tools/mac/symupload/symupload.m \
|
||||
src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj \
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
Breakpad is a set of client and server components which implement a
|
||||
crash-reporting system.
|
||||
|
||||
|
||||
-----
|
||||
Getting started in 32-bit mode (from trunk)
|
||||
Configure: CXXFLAGS=-m32 CFLAGS=-m32 CPPFLAGS=-m32 ./configure
|
||||
Build: make
|
||||
Test: make check
|
||||
Install: make install
|
||||
|
||||
If you need to reconfigure your build be sure to run "make distclean" first.
|
||||
|
||||
|
||||
-----
|
||||
To request change review:
|
||||
0. Get access to a read-write copy of source.
|
||||
Owners at http://code.google.com/p/google-breakpad/ are able to grant
|
||||
this access.
|
||||
|
||||
1. Check out a read-write copy of source using instructions at
|
||||
http://code.google.com/p/google-breakpad/source/checkout
|
||||
|
||||
2. Make changes. Build and test your changes.
|
||||
For core code like processor use methods above.
|
||||
For linux/mac/windows, there are test targets in each project file.
|
||||
|
||||
3. Download http://codereview.appspot.com/static/upload.py
|
||||
|
||||
4. Run upload.py from the 'src' directory:
|
||||
upload.py --server=breakpad.appspot.com
|
||||
|
||||
You will be prompted for credential and a description.
|
||||
|
||||
5. At http://breakpad.appspot.com you'll find your issue listed; click on it,
|
||||
and select Publish+Mail, and enter in the code reviewer and CC
|
||||
google-breakpad-dev@googlegroups.com
|
||||
|
||||
6. When applying code review feedback, specify the '-i' option when running
|
||||
upload.py again and pass the issue number so it updates the existing issue,
|
||||
rather than creating a new one.
|
||||
Be sure to rerun upload.py from the same directory as you did for previous
|
||||
uploads to allow for proper diff calculations.
|
|
@ -5,8 +5,8 @@ This document explains how to use the Google Breakpad client library
|
|||
on Android, and later generate valid stack traces from the minidumps
|
||||
it generates.
|
||||
|
||||
This release supports ARM and x86 based Android systems. MIPS is not
|
||||
currently supported by Breakpad.
|
||||
This release supports ARM, x86 and MIPS based Android systems.
|
||||
This release requires NDK release r10c or higher.
|
||||
|
||||
I. Building the client library:
|
||||
===============================
|
||||
|
@ -37,8 +37,8 @@ NOTE: The client library requires a C++ STL implementation,
|
|||
It has been tested succesfully with both STLport and GNU libstdc++
|
||||
|
||||
|
||||
II.1. Building with a standalone Android toolchain:
|
||||
---------------------------------------------------
|
||||
I.2. Building with a standalone Android toolchain:
|
||||
--------------------------------------------------
|
||||
|
||||
All you need to do is configure your build with the right 'host'
|
||||
value, and disable the processor and tools, as in:
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
# Breakpad
|
||||
|
||||
Breakpad is a set of client and server components which implement a
|
||||
crash-reporting system.
|
||||
|
||||
## Getting started in 32-bit mode (from trunk)
|
||||
|
||||
```sh
|
||||
# Configure
|
||||
CXXFLAGS=-m32 CFLAGS=-m32 CPPFLAGS=-m32 ./configure
|
||||
# Build
|
||||
make
|
||||
# Test
|
||||
make check
|
||||
# Install
|
||||
make install
|
||||
```
|
||||
|
||||
If you need to reconfigure your build be sure to run `make distclean` first.
|
||||
|
||||
## To request change review:
|
||||
|
||||
1. Get a copy of depot_tools repo.
|
||||
http://dev.chromium.org/developers/how-tos/install-depot-tools
|
||||
|
||||
2. Create a new directory for checking out the source code.
|
||||
mkdir breakpad && cd breakpad
|
||||
|
||||
3. Run the `fetch` tool from depot_tools to download all the source repos.
|
||||
`fetch breakpad`
|
||||
|
||||
4. Make changes. Build and test your changes.
|
||||
For core code like processor use methods above.
|
||||
For linux/mac/windows, there are test targets in each project file.
|
||||
|
||||
5. Commit your changes to your local repo and upload them to the server.
|
||||
http://dev.chromium.org/developers/contributing-code
|
||||
e.g. `git commit ... && git cl upload ...`
|
||||
You will be prompted for credential and a description.
|
||||
|
||||
6. At https://codereview.chromium.org/ you'll find your issue listed; click on
|
||||
it, and select Publish+Mail, and enter in the code reviewer and CC
|
||||
google-breakpad-dev@googlegroups.com
|
||||
|
||||
## Documentation
|
||||
|
||||
Visit https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/
|
|
@ -1,12 +0,0 @@
|
|||
Path: /tmp/google-breakpad-read-only
|
||||
Working Copy Root Path: /tmp/google-breakpad-read-only
|
||||
URL: http://google-breakpad.googlecode.com/svn/trunk
|
||||
Repository Root: http://google-breakpad.googlecode.com/svn
|
||||
Repository UUID: 4c0a9323-5329-0410-9bdc-e9ce6186880e
|
||||
Revision: 1143
|
||||
Node Kind: directory
|
||||
Schedule: normal
|
||||
Last Changed Author: ted.mielczarek@gmail.com
|
||||
Last Changed Rev: 1143
|
||||
Last Changed Date: 2013-04-04 18:24:52 +0200 (Thu, 04 Apr 2013)
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -45,11 +45,6 @@
|
|||
# to select one in your Application.mk
|
||||
#
|
||||
|
||||
# Sanity check. We can only build for ARM for now.
|
||||
ifneq (,$(filter-out armeabi armeabi-v7a x86,$(TARGET_ARCH_ABI)))
|
||||
$(error Sorry, Google Breakpad only works on Android ARM and x86 for now!)
|
||||
endif
|
||||
|
||||
# The top Google Breakpad directory.
|
||||
# We assume this Android.mk to be under 'android/google_breakpad'
|
||||
|
||||
|
@ -85,7 +80,8 @@ LOCAL_SRC_FILES := \
|
|||
src/client/minidump_file_writer.cc \
|
||||
src/common/android/breakpad_getcontext.S \
|
||||
src/common/convert_UTF.c \
|
||||
src/common/md5.cc src/common/string_conversion.cc \
|
||||
src/common/md5.cc \
|
||||
src/common/string_conversion.cc \
|
||||
src/common/linux/elfutils.cc \
|
||||
src/common/linux/file_id.cc \
|
||||
src/common/linux/guid_creator.cc \
|
||||
|
|
|
@ -326,6 +326,9 @@ case $ARCH in
|
|||
x86)
|
||||
GNU_CONFIG=i686-linux-android
|
||||
;;
|
||||
mips)
|
||||
GNU_CONFIG=mipsel-linux-android
|
||||
;;
|
||||
*)
|
||||
GNU_CONFIG="$ARCH-linux-android"
|
||||
;;
|
||||
|
|
|
@ -28,4 +28,4 @@
|
|||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
APP_STL := stlport_static
|
||||
APP_ABI := armeabi armeabi-v7a
|
||||
APP_ABI := all
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
#! /bin/sh
|
||||
# test-driver - basic testsuite driver script.
|
||||
|
||||
# Slightly modified for Android, see ANDROID comment below.
|
||||
|
||||
scriptversion=2012-06-27.10; # UTC
|
||||
|
||||
# Copyright (C) 2011-2013 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
# Make unconditional expansion of undefined variables an error. This
|
||||
# helps a lot in preventing typo-related bugs.
|
||||
set -u
|
||||
|
||||
usage_error ()
|
||||
{
|
||||
echo "$0: $*" >&2
|
||||
print_usage >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
print_usage ()
|
||||
{
|
||||
cat <<END
|
||||
Usage:
|
||||
test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
|
||||
[--expect-failure={yes|no}] [--color-tests={yes|no}]
|
||||
[--enable-hard-errors={yes|no}] [--] TEST-SCRIPT
|
||||
The '--test-name', '--log-file' and '--trs-file' options are mandatory.
|
||||
END
|
||||
}
|
||||
|
||||
# TODO: better error handling in option parsing (in particular, ensure
|
||||
# TODO: $log_file, $trs_file and $test_name are defined).
|
||||
test_name= # Used for reporting.
|
||||
log_file= # Where to save the output of the test script.
|
||||
trs_file= # Where to save the metadata of the test run.
|
||||
expect_failure=no
|
||||
color_tests=no
|
||||
enable_hard_errors=yes
|
||||
while test $# -gt 0; do
|
||||
case $1 in
|
||||
--help) print_usage; exit $?;;
|
||||
--version) echo "test-driver $scriptversion"; exit $?;;
|
||||
--test-name) test_name=$2; shift;;
|
||||
--log-file) log_file=$2; shift;;
|
||||
--trs-file) trs_file=$2; shift;;
|
||||
--color-tests) color_tests=$2; shift;;
|
||||
--expect-failure) expect_failure=$2; shift;;
|
||||
--enable-hard-errors) enable_hard_errors=$2; shift;;
|
||||
--) shift; break;;
|
||||
-*) usage_error "invalid option: '$1'";;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test $color_tests = yes; then
|
||||
# Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
|
||||
red='[0;31m' # Red.
|
||||
grn='[0;32m' # Green.
|
||||
lgn='[1;32m' # Light green.
|
||||
blu='[1;34m' # Blue.
|
||||
mgn='[0;35m' # Magenta.
|
||||
std='[m' # No color.
|
||||
else
|
||||
red= grn= lgn= blu= mgn= std=
|
||||
fi
|
||||
|
||||
do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
|
||||
trap "st=129; $do_exit" 1
|
||||
trap "st=130; $do_exit" 2
|
||||
trap "st=141; $do_exit" 13
|
||||
trap "st=143; $do_exit" 15
|
||||
|
||||
# Test script is run here.
|
||||
# ANDROID: old line was: "$@" > $log_file 2>&1
|
||||
progdir=$(dirname "$0")
|
||||
"$progdir/test-shell.sh" "$@" > $log_file 2>&1
|
||||
estatus=$?
|
||||
if test $enable_hard_errors = no && test $estatus -eq 99; then
|
||||
estatus=1
|
||||
fi
|
||||
|
||||
case $estatus:$expect_failure in
|
||||
0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
|
||||
0:*) col=$grn res=PASS recheck=no gcopy=no;;
|
||||
77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
|
||||
99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
|
||||
*:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
|
||||
*:*) col=$red res=FAIL recheck=yes gcopy=yes;;
|
||||
esac
|
||||
|
||||
# Report outcome to console.
|
||||
echo "${col}${res}${std}: $test_name"
|
||||
|
||||
# Register the test result, and other relevant metadata.
|
||||
echo ":test-result: $res" > $trs_file
|
||||
echo ":global-test-result: $res" >> $trs_file
|
||||
echo ":recheck: $recheck" >> $trs_file
|
||||
echo ":copy-in-global-log: $gcopy" >> $trs_file
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
|
@ -52,8 +52,9 @@ if [ ! -f "$TEST_PROGRAM" ]; then
|
|||
fi
|
||||
|
||||
# Create test directory on the device
|
||||
TEST_DIR=/data/local/tmp/test-google-breakpad
|
||||
adb_shell mkdir "$TEST_DIR" || panic "Can't create test directory on device"
|
||||
TEST_DIR=/data/local/tmp/test-google-breakpad-$$
|
||||
adb_shell mkdir "$TEST_DIR" ||
|
||||
panic "Can't create test directory on device: $TEST_DIR"
|
||||
|
||||
# Ensure that it is always removed when the script exits.
|
||||
clean_test_dir () {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2012-03-05.13; # UTC
|
||||
scriptversion=2012-10-14.11; # UTC
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009, 2010, 2012 Free
|
||||
# Software Foundation, Inc.
|
||||
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
|
@ -113,6 +112,11 @@ func_cl_dashl ()
|
|||
lib=$dir/$lib.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/lib$lib.a"; then
|
||||
found=yes
|
||||
lib=$dir/lib$lib.a
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS=$save_IFS
|
||||
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
# 2011, 2012 Free Software Foundation, Inc.
|
||||
# Copyright 1992-2015 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2012-06-17'
|
||||
timestamp='2015-03-04'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
|
@ -22,19 +20,17 @@ timestamp='2012-06-17'
|
|||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
|
||||
# Originally written by Per Bothner. Please send patches (context
|
||||
# diff format) to <config-patches@gnu.org> and include a ChangeLog
|
||||
# entry.
|
||||
# the same distribution terms that you use for the rest of that
|
||||
# program. This Exception is an additional permission under section 7
|
||||
# of the GNU General Public License, version 3 ("GPLv3").
|
||||
#
|
||||
# This script attempts to guess a canonical system name similar to
|
||||
# config.sub. If it succeeds, it prints the system name on stdout, and
|
||||
# exits with 0. Otherwise, it exits with 1.
|
||||
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
|
||||
#
|
||||
# You can get the latest version of this script from:
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
||||
#
|
||||
# Please send patches to <config-patches@gnu.org>.
|
||||
|
||||
|
||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||
|
||||
|
@ -54,9 +50,7 @@ version="\
|
|||
GNU config.guess ($timestamp)
|
||||
|
||||
Originally written by Per Bothner.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
|
||||
Free Software Foundation, Inc.
|
||||
Copyright 1992-2015 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
|
@ -138,6 +132,27 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
|
|||
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
|
||||
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
|
||||
|
||||
case "${UNAME_SYSTEM}" in
|
||||
Linux|GNU|GNU/*)
|
||||
# If the system lacks a compiler, then just pick glibc.
|
||||
# We could probably try harder.
|
||||
LIBC=gnu
|
||||
|
||||
eval $set_cc_for_build
|
||||
cat <<-EOF > $dummy.c
|
||||
#include <features.h>
|
||||
#if defined(__UCLIBC__)
|
||||
LIBC=uclibc
|
||||
#elif defined(__dietlibc__)
|
||||
LIBC=dietlibc
|
||||
#else
|
||||
LIBC=gnu
|
||||
#endif
|
||||
EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
|
||||
;;
|
||||
esac
|
||||
|
||||
# Note: order is significant - the case branches are not exclusive.
|
||||
|
||||
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
|
@ -153,20 +168,27 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||
# Note: NetBSD doesn't particularly care about the vendor
|
||||
# portion of the name. We always set it to "unknown".
|
||||
sysctl="sysctl -n hw.machine_arch"
|
||||
UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
|
||||
/usr/sbin/$sysctl 2>/dev/null || echo unknown)`
|
||||
UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
|
||||
/sbin/$sysctl 2>/dev/null || \
|
||||
/usr/sbin/$sysctl 2>/dev/null || \
|
||||
echo unknown)`
|
||||
case "${UNAME_MACHINE_ARCH}" in
|
||||
armeb) machine=armeb-unknown ;;
|
||||
arm*) machine=arm-unknown ;;
|
||||
sh3el) machine=shl-unknown ;;
|
||||
sh3eb) machine=sh-unknown ;;
|
||||
sh5el) machine=sh5le-unknown ;;
|
||||
earmv*)
|
||||
arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
|
||||
endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
|
||||
machine=${arch}${endian}-unknown
|
||||
;;
|
||||
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
|
||||
esac
|
||||
# The Operating System including object format, if it has switched
|
||||
# to ELF recently, or will in the future.
|
||||
case "${UNAME_MACHINE_ARCH}" in
|
||||
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
|
||||
arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)
|
||||
eval $set_cc_for_build
|
||||
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep -q __ELF__
|
||||
|
@ -182,6 +204,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||
os=netbsd
|
||||
;;
|
||||
esac
|
||||
# Determine ABI tags.
|
||||
case "${UNAME_MACHINE_ARCH}" in
|
||||
earm*)
|
||||
expr='s/^earmv[0-9]/-eabi/;s/eb$//'
|
||||
abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
|
||||
;;
|
||||
esac
|
||||
# The OS release
|
||||
# Debian GNU/NetBSD machines have a different userland, and
|
||||
# thus, need a distinct triplet. However, they do not need
|
||||
|
@ -198,7 +227,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
|
||||
# contains redundant information, the shorter form:
|
||||
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
|
||||
echo "${machine}-${os}${release}"
|
||||
echo "${machine}-${os}${release}${abi}"
|
||||
exit ;;
|
||||
*:Bitrig:*:*)
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
|
||||
|
@ -306,7 +335,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
|
||||
echo arm-acorn-riscix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
arm:riscos:*:*|arm:RISCOS:*:*)
|
||||
arm*:riscos:*:*|arm*:RISCOS:*:*)
|
||||
echo arm-unknown-riscos
|
||||
exit ;;
|
||||
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
|
||||
|
@ -564,8 +593,9 @@ EOF
|
|||
else
|
||||
IBM_ARCH=powerpc
|
||||
fi
|
||||
if [ -x /usr/bin/oslevel ] ; then
|
||||
IBM_REV=`/usr/bin/oslevel`
|
||||
if [ -x /usr/bin/lslpp ] ; then
|
||||
IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
|
||||
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
|
||||
else
|
||||
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
|
||||
fi
|
||||
|
@ -805,10 +835,13 @@ EOF
|
|||
i*:CYGWIN*:*)
|
||||
echo ${UNAME_MACHINE}-pc-cygwin
|
||||
exit ;;
|
||||
*:MINGW64*:*)
|
||||
echo ${UNAME_MACHINE}-pc-mingw64
|
||||
exit ;;
|
||||
*:MINGW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-mingw32
|
||||
exit ;;
|
||||
i*:MSYS*:*)
|
||||
*:MSYS*:*)
|
||||
echo ${UNAME_MACHINE}-pc-msys
|
||||
exit ;;
|
||||
i*:windows32*:*)
|
||||
|
@ -856,21 +889,21 @@ EOF
|
|||
exit ;;
|
||||
*:GNU:*:*)
|
||||
# the GNU system
|
||||
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
|
||||
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
|
||||
exit ;;
|
||||
*:GNU/*:*:*)
|
||||
# other systems with GNU libc and userland
|
||||
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
|
||||
exit ;;
|
||||
i*86:Minix:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-minix
|
||||
exit ;;
|
||||
aarch64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
aarch64_be:Linux:*:*)
|
||||
UNAME_MACHINE=aarch64_be
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
alpha:Linux:*:*)
|
||||
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
|
||||
|
@ -883,59 +916,57 @@ EOF
|
|||
EV68*) UNAME_MACHINE=alphaev68 ;;
|
||||
esac
|
||||
objdump --private-headers /bin/sh | grep -q ld.so.1
|
||||
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
|
||||
if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
arc:Linux:*:* | arceb:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
arm*:Linux:*:*)
|
||||
eval $set_cc_for_build
|
||||
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep -q __ARM_EABI__
|
||||
then
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
else
|
||||
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep -q __ARM_PCS_VFP
|
||||
then
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnueabi
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
|
||||
else
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
|
||||
fi
|
||||
fi
|
||||
exit ;;
|
||||
avr32*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
cris:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-axis-linux-gnu
|
||||
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
|
||||
exit ;;
|
||||
crisv32:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-axis-linux-gnu
|
||||
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
|
||||
exit ;;
|
||||
e2k:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
frv:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
hexagon:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
i*86:Linux:*:*)
|
||||
LIBC=gnu
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#ifdef __dietlibc__
|
||||
LIBC=dietlibc
|
||||
#endif
|
||||
EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
|
||||
echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
|
||||
echo ${UNAME_MACHINE}-pc-linux-${LIBC}
|
||||
exit ;;
|
||||
ia64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
m32r*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
m68*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
mips:Linux:*:* | mips64:Linux:*:*)
|
||||
eval $set_cc_for_build
|
||||
|
@ -954,54 +985,63 @@ EOF
|
|||
#endif
|
||||
EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
|
||||
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
|
||||
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
|
||||
;;
|
||||
or32:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
openrisc*:Linux:*:*)
|
||||
echo or1k-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
or32:Linux:*:* | or1k*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
padre:Linux:*:*)
|
||||
echo sparc-unknown-linux-gnu
|
||||
echo sparc-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
parisc64:Linux:*:* | hppa64:Linux:*:*)
|
||||
echo hppa64-unknown-linux-gnu
|
||||
echo hppa64-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
parisc:Linux:*:* | hppa:Linux:*:*)
|
||||
# Look for CPU level
|
||||
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
|
||||
PA7*) echo hppa1.1-unknown-linux-gnu ;;
|
||||
PA8*) echo hppa2.0-unknown-linux-gnu ;;
|
||||
*) echo hppa-unknown-linux-gnu ;;
|
||||
PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
|
||||
PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
|
||||
*) echo hppa-unknown-linux-${LIBC} ;;
|
||||
esac
|
||||
exit ;;
|
||||
ppc64:Linux:*:*)
|
||||
echo powerpc64-unknown-linux-gnu
|
||||
echo powerpc64-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
ppc:Linux:*:*)
|
||||
echo powerpc-unknown-linux-gnu
|
||||
echo powerpc-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
ppc64le:Linux:*:*)
|
||||
echo powerpc64le-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
ppcle:Linux:*:*)
|
||||
echo powerpcle-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
s390:Linux:*:* | s390x:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-ibm-linux
|
||||
echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
|
||||
exit ;;
|
||||
sh64*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
sh*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
sparc:Linux:*:* | sparc64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
tile*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
vax:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-dec-linux-gnu
|
||||
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
|
||||
exit ;;
|
||||
x86_64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
xtensa*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
i*86:DYNIX/ptx:4*:*)
|
||||
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
|
||||
|
@ -1205,6 +1245,9 @@ EOF
|
|||
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
|
||||
echo i586-pc-haiku
|
||||
exit ;;
|
||||
x86_64:Haiku:*:*)
|
||||
echo x86_64-unknown-haiku
|
||||
exit ;;
|
||||
SX-4:SUPER-UX:*:*)
|
||||
echo sx4-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
|
@ -1231,19 +1274,31 @@ EOF
|
|||
exit ;;
|
||||
*:Darwin:*:*)
|
||||
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
|
||||
case $UNAME_PROCESSOR in
|
||||
i386)
|
||||
eval $set_cc_for_build
|
||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
||||
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
UNAME_PROCESSOR="x86_64"
|
||||
fi
|
||||
fi ;;
|
||||
unknown) UNAME_PROCESSOR=powerpc ;;
|
||||
esac
|
||||
eval $set_cc_for_build
|
||||
if test "$UNAME_PROCESSOR" = unknown ; then
|
||||
UNAME_PROCESSOR=powerpc
|
||||
fi
|
||||
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
|
||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
||||
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
case $UNAME_PROCESSOR in
|
||||
i386) UNAME_PROCESSOR=x86_64 ;;
|
||||
powerpc) UNAME_PROCESSOR=powerpc64 ;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
elif test "$UNAME_PROCESSOR" = i386 ; then
|
||||
# Avoid executing cc on OS X 10.9, as it ships with a stub
|
||||
# that puts up a graphical alert prompting to install
|
||||
# developer tools. Any system running Mac OS X 10.7 or
|
||||
# later (Darwin 11 and later) is required to have a 64-bit
|
||||
# processor. This is not true of the ARM version of Darwin
|
||||
# that Apple uses in portable devices.
|
||||
UNAME_PROCESSOR=x86_64
|
||||
fi
|
||||
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:procnto*:*:* | *:QNX:[0123456789]*:*)
|
||||
|
@ -1334,157 +1389,6 @@ EOF
|
|||
exit ;;
|
||||
esac
|
||||
|
||||
#echo '(No uname command or uname output not recognized.)' 1>&2
|
||||
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
|
||||
|
||||
eval $set_cc_for_build
|
||||
cat >$dummy.c <<EOF
|
||||
#ifdef _SEQUENT_
|
||||
# include <sys/types.h>
|
||||
# include <sys/utsname.h>
|
||||
#endif
|
||||
main ()
|
||||
{
|
||||
#if defined (sony)
|
||||
#if defined (MIPSEB)
|
||||
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
|
||||
I don't know.... */
|
||||
printf ("mips-sony-bsd\n"); exit (0);
|
||||
#else
|
||||
#include <sys/param.h>
|
||||
printf ("m68k-sony-newsos%s\n",
|
||||
#ifdef NEWSOS4
|
||||
"4"
|
||||
#else
|
||||
""
|
||||
#endif
|
||||
); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (__arm) && defined (__acorn) && defined (__unix)
|
||||
printf ("arm-acorn-riscix\n"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (hp300) && !defined (hpux)
|
||||
printf ("m68k-hp-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (NeXT)
|
||||
#if !defined (__ARCHITECTURE__)
|
||||
#define __ARCHITECTURE__ "m68k"
|
||||
#endif
|
||||
int version;
|
||||
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
|
||||
if (version < 4)
|
||||
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
|
||||
else
|
||||
printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
|
||||
exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (MULTIMAX) || defined (n16)
|
||||
#if defined (UMAXV)
|
||||
printf ("ns32k-encore-sysv\n"); exit (0);
|
||||
#else
|
||||
#if defined (CMU)
|
||||
printf ("ns32k-encore-mach\n"); exit (0);
|
||||
#else
|
||||
printf ("ns32k-encore-bsd\n"); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (__386BSD__)
|
||||
printf ("i386-pc-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
#if defined (sequent)
|
||||
#if defined (i386)
|
||||
printf ("i386-sequent-dynix\n"); exit (0);
|
||||
#endif
|
||||
#if defined (ns32000)
|
||||
printf ("ns32k-sequent-dynix\n"); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (_SEQUENT_)
|
||||
struct utsname un;
|
||||
|
||||
uname(&un);
|
||||
|
||||
if (strncmp(un.version, "V2", 2) == 0) {
|
||||
printf ("i386-sequent-ptx2\n"); exit (0);
|
||||
}
|
||||
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
|
||||
printf ("i386-sequent-ptx1\n"); exit (0);
|
||||
}
|
||||
printf ("i386-sequent-ptx\n"); exit (0);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (vax)
|
||||
# if !defined (ultrix)
|
||||
# include <sys/param.h>
|
||||
# if defined (BSD)
|
||||
# if BSD == 43
|
||||
printf ("vax-dec-bsd4.3\n"); exit (0);
|
||||
# else
|
||||
# if BSD == 199006
|
||||
printf ("vax-dec-bsd4.3reno\n"); exit (0);
|
||||
# else
|
||||
printf ("vax-dec-bsd\n"); exit (0);
|
||||
# endif
|
||||
# endif
|
||||
# else
|
||||
printf ("vax-dec-bsd\n"); exit (0);
|
||||
# endif
|
||||
# else
|
||||
printf ("vax-dec-ultrix\n"); exit (0);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined (alliant) && defined (i860)
|
||||
printf ("i860-alliant-bsd\n"); exit (0);
|
||||
#endif
|
||||
|
||||
exit (1);
|
||||
}
|
||||
EOF
|
||||
|
||||
$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
|
||||
{ echo "$SYSTEM_NAME"; exit; }
|
||||
|
||||
# Apollos put the system type in the environment.
|
||||
|
||||
test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
|
||||
|
||||
# Convex versions that predate uname can use getsysinfo(1)
|
||||
|
||||
if [ -x /usr/convex/getsysinfo ]
|
||||
then
|
||||
case `getsysinfo -f cpu_type` in
|
||||
c1*)
|
||||
echo c1-convex-bsd
|
||||
exit ;;
|
||||
c2*)
|
||||
if getsysinfo -f scalar_acc
|
||||
then echo c32-convex-bsd
|
||||
else echo c2-convex-bsd
|
||||
fi
|
||||
exit ;;
|
||||
c34*)
|
||||
echo c34-convex-bsd
|
||||
exit ;;
|
||||
c38*)
|
||||
echo c38-convex-bsd
|
||||
exit ;;
|
||||
c4*)
|
||||
echo c4-convex-bsd
|
||||
exit ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
cat >&2 <<EOF
|
||||
$0: unable to guess system type
|
||||
|
||||
|
|
|
@ -1,24 +1,18 @@
|
|||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
# 2011, 2012 Free Software Foundation, Inc.
|
||||
# Copyright 1992-2015 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2012-06-17'
|
||||
timestamp='2015-03-08'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
# can handle that machine. It does not imply ALL GNU software can.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
@ -26,11 +20,12 @@ timestamp='2012-06-17'
|
|||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
# the same distribution terms that you use for the rest of that
|
||||
# program. This Exception is an additional permission under section 7
|
||||
# of the GNU General Public License, version 3 ("GPLv3").
|
||||
|
||||
|
||||
# Please send patches to <config-patches@gnu.org>. Submit a context
|
||||
# diff and a properly formatted GNU ChangeLog entry.
|
||||
# Please send patches to <config-patches@gnu.org>.
|
||||
#
|
||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||
# Supply the specified configuration type as an argument.
|
||||
|
@ -73,9 +68,7 @@ Report bugs and patches to <config-patches@gnu.org>."
|
|||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
|
||||
Free Software Foundation, Inc.
|
||||
Copyright 1992-2015 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
|
@ -123,8 +116,8 @@ esac
|
|||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
|
||||
linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
||||
knetbsd*-gnu* | netbsd*-gnu* | \
|
||||
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
||||
knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
|
||||
kopensolaris*-gnu* | \
|
||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
|
@ -156,7 +149,7 @@ case $os in
|
|||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||
-apple | -axis | -knuth | -cray | -microblaze)
|
||||
-apple | -axis | -knuth | -cray | -microblaze*)
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
|
@ -259,21 +252,24 @@ case $basic_machine in
|
|||
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||
| am33_2.0 \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
|
||||
| be32 | be64 \
|
||||
| arc | arceb \
|
||||
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
|
||||
| avr | avr32 \
|
||||
| be32 | be64 \
|
||||
| bfin \
|
||||
| c4x | clipper \
|
||||
| c4x | c8051 | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| epiphany \
|
||||
| fido | fr30 | frv \
|
||||
| e2k | epiphany \
|
||||
| fido | fr30 | frv | ft32 \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| hexagon \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| k1om \
|
||||
| le32 | le64 \
|
||||
| lm32 \
|
||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||
| maxq | mb | microblaze | mcore | mep | metag \
|
||||
| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
| mips64 | mips64el \
|
||||
|
@ -287,23 +283,26 @@ case $basic_machine in
|
|||
| mips64vr5900 | mips64vr5900el \
|
||||
| mipsisa32 | mipsisa32el \
|
||||
| mipsisa32r2 | mipsisa32r2el \
|
||||
| mipsisa32r6 | mipsisa32r6el \
|
||||
| mipsisa64 | mipsisa64el \
|
||||
| mipsisa64r2 | mipsisa64r2el \
|
||||
| mipsisa64r6 | mipsisa64r6el \
|
||||
| mipsisa64sb1 | mipsisa64sb1el \
|
||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipsr5900 | mipsr5900el \
|
||||
| mipstx39 | mipstx39el \
|
||||
| mn10200 | mn10300 \
|
||||
| moxie \
|
||||
| mt \
|
||||
| msp430 \
|
||||
| nds32 | nds32le | nds32be \
|
||||
| nios | nios2 \
|
||||
| nios | nios2 | nios2eb | nios2el \
|
||||
| ns16k | ns32k \
|
||||
| open8 \
|
||||
| or32 \
|
||||
| open8 | or1k | or1knd | or32 \
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle \
|
||||
| pyramid \
|
||||
| riscv32 | riscv64 \
|
||||
| rl78 | rx \
|
||||
| score \
|
||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
|
@ -314,6 +313,7 @@ case $basic_machine in
|
|||
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
|
||||
| ubicom32 \
|
||||
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
|
||||
| visium \
|
||||
| we32k \
|
||||
| x86 | xc16x | xstormy16 | xtensa \
|
||||
| z8k | z80)
|
||||
|
@ -328,7 +328,10 @@ case $basic_machine in
|
|||
c6x)
|
||||
basic_machine=tic6x-unknown
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
|
||||
leon|leon[3-9])
|
||||
basic_machine=sparc-$basic_machine
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
;;
|
||||
|
@ -370,26 +373,28 @@ case $basic_machine in
|
|||
| aarch64-* | aarch64_be-* \
|
||||
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
|
||||
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* | avr32-* \
|
||||
| be32-* | be64-* \
|
||||
| bfin-* | bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* \
|
||||
| clipper-* | craynv-* | cydra-* \
|
||||
| c8051-* | clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| e2k-* | elxsi-* \
|
||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| hexagon-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| k1om-* \
|
||||
| le32-* | le64-* \
|
||||
| lm32-* \
|
||||
| m32c-* | m32r-* | m32rle-* \
|
||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
|
||||
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
|
||||
| microblaze-* | microblazeel-* \
|
||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||
| mips16-* \
|
||||
| mips64-* | mips64el-* \
|
||||
|
@ -403,18 +408,22 @@ case $basic_machine in
|
|||
| mips64vr5900-* | mips64vr5900el-* \
|
||||
| mipsisa32-* | mipsisa32el-* \
|
||||
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||
| mipsisa32r6-* | mipsisa32r6el-* \
|
||||
| mipsisa64-* | mipsisa64el-* \
|
||||
| mipsisa64r2-* | mipsisa64r2el-* \
|
||||
| mipsisa64r6-* | mipsisa64r6el-* \
|
||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||
| mipsr5900-* | mipsr5900el-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
| mmix-* \
|
||||
| mt-* \
|
||||
| msp430-* \
|
||||
| nds32-* | nds32le-* | nds32be-* \
|
||||
| nios-* | nios2-* \
|
||||
| nios-* | nios2-* | nios2eb-* | nios2el-* \
|
||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||
| open8-* \
|
||||
| or1k*-* \
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
||||
|
@ -432,6 +441,7 @@ case $basic_machine in
|
|||
| ubicom32-* \
|
||||
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
|
||||
| vax-* \
|
||||
| visium-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* \
|
||||
| xstormy16-* | xtensa*-* \
|
||||
|
@ -508,6 +518,9 @@ case $basic_machine in
|
|||
basic_machine=i386-pc
|
||||
os=-aros
|
||||
;;
|
||||
asmjs)
|
||||
basic_machine=asmjs-unknown
|
||||
;;
|
||||
aux)
|
||||
basic_machine=m68k-apple
|
||||
os=-aux
|
||||
|
@ -769,6 +782,9 @@ case $basic_machine in
|
|||
basic_machine=m68k-isi
|
||||
os=-sysv
|
||||
;;
|
||||
leon-*|leon[3-9]-*)
|
||||
basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
|
||||
;;
|
||||
m68knommu)
|
||||
basic_machine=m68k-unknown
|
||||
os=-linux
|
||||
|
@ -788,11 +804,15 @@ case $basic_machine in
|
|||
basic_machine=ns32k-utek
|
||||
os=-sysv
|
||||
;;
|
||||
microblaze)
|
||||
microblaze*)
|
||||
basic_machine=microblaze-xilinx
|
||||
;;
|
||||
mingw64)
|
||||
basic_machine=x86_64-pc
|
||||
os=-mingw64
|
||||
;;
|
||||
mingw32)
|
||||
basic_machine=i386-pc
|
||||
basic_machine=i686-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
mingw32ce)
|
||||
|
@ -820,6 +840,10 @@ case $basic_machine in
|
|||
basic_machine=powerpc-unknown
|
||||
os=-morphos
|
||||
;;
|
||||
moxiebox)
|
||||
basic_machine=moxie-unknown
|
||||
os=-moxiebox
|
||||
;;
|
||||
msdos)
|
||||
basic_machine=i386-pc
|
||||
os=-msdos
|
||||
|
@ -828,7 +852,7 @@ case $basic_machine in
|
|||
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
|
||||
;;
|
||||
msys)
|
||||
basic_machine=i386-pc
|
||||
basic_machine=i686-pc
|
||||
os=-msys
|
||||
;;
|
||||
mvs)
|
||||
|
@ -1019,7 +1043,11 @@ case $basic_machine in
|
|||
basic_machine=i586-unknown
|
||||
os=-pw32
|
||||
;;
|
||||
rdos)
|
||||
rdos | rdos64)
|
||||
basic_machine=x86_64-pc
|
||||
os=-rdos
|
||||
;;
|
||||
rdos32)
|
||||
basic_machine=i386-pc
|
||||
os=-rdos
|
||||
;;
|
||||
|
@ -1346,9 +1374,9 @@ case $os in
|
|||
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
|
||||
| -sym* | -kopensolaris* \
|
||||
| -sym* | -kopensolaris* | -plan9* \
|
||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||
| -aos* | -aros* \
|
||||
| -aos* | -aros* | -cloudabi* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||
|
@ -1359,16 +1387,16 @@ case $os in
|
|||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* | -cegcc* \
|
||||
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -linux-android* \
|
||||
| -linux-newlib* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
|
||||
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
|
@ -1492,9 +1520,6 @@ case $os in
|
|||
-aros*)
|
||||
os=-aros
|
||||
;;
|
||||
-kaos*)
|
||||
os=-kaos
|
||||
;;
|
||||
-zvmoe)
|
||||
os=-zvmoe
|
||||
;;
|
||||
|
@ -1543,6 +1568,9 @@ case $basic_machine in
|
|||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
c8051-*)
|
||||
os=-elf
|
||||
;;
|
||||
hexagon-*)
|
||||
os=-elf
|
||||
;;
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2006-10-15.18
|
||||
scriptversion=2013-05-30.07; # UTC
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006 Free Software
|
||||
# Foundation, Inc.
|
||||
# Copyright (C) 1999-2013 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -17,9 +16,7 @@ scriptversion=2006-10-15.18
|
|||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
|
@ -30,9 +27,9 @@ scriptversion=2006-10-15.18
|
|||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
@ -42,11 +39,11 @@ as side-effects.
|
|||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by `PROGRAMS ARGS'.
|
||||
object Object file output by `PROGRAMS ARGS'.
|
||||
source Source file read by 'PROGRAMS ARGS'.
|
||||
object Object file output by 'PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputing dependencies.
|
||||
tmpdepfile Temporary file to use when outputting dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
|
@ -59,6 +56,66 @@ EOF
|
|||
;;
|
||||
esac
|
||||
|
||||
# Get the directory component of the given path, and save it in the
|
||||
# global variables '$dir'. Note that this directory component will
|
||||
# be either empty or ending with a '/' character. This is deliberate.
|
||||
set_dir_from ()
|
||||
{
|
||||
case $1 in
|
||||
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
|
||||
*) dir=;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get the suffix-stripped basename of the given path, and save it the
|
||||
# global variable '$base'.
|
||||
set_base_from ()
|
||||
{
|
||||
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
|
||||
}
|
||||
|
||||
# If no dependency file was actually created by the compiler invocation,
|
||||
# we still have to create a dummy depfile, to avoid errors with the
|
||||
# Makefile "include basename.Plo" scheme.
|
||||
make_dummy_depfile ()
|
||||
{
|
||||
echo "#dummy" > "$depfile"
|
||||
}
|
||||
|
||||
# Factor out some common post-processing of the generated depfile.
|
||||
# Requires the auxiliary global variable '$tmpdepfile' to be set.
|
||||
aix_post_process_depfile ()
|
||||
{
|
||||
# If the compiler actually managed to produce a dependency file,
|
||||
# post-process it.
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form 'foo.o: dependency.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# $object: dependency.h
|
||||
# and one to simply output
|
||||
# dependency.h:
|
||||
# which is needed to avoid the deleted-header problem.
|
||||
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
|
||||
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
|
||||
} > "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
}
|
||||
|
||||
# A tabulation character.
|
||||
tab=' '
|
||||
# A newline character.
|
||||
nl='
|
||||
'
|
||||
# Character ranges might be problematic outside the C locale.
|
||||
# These definitions help.
|
||||
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
lower=abcdefghijklmnopqrstuvwxyz
|
||||
digits=0123456789
|
||||
alpha=${upper}${lower}
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
|
@ -71,6 +128,9 @@ tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
|||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Avoid interferences from the environment.
|
||||
gccflag= dashmflag=
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
|
@ -82,9 +142,32 @@ if test "$depmode" = hp; then
|
|||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
if test "$depmode" = msvc7msys; then
|
||||
# This is just like msvc7 but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvc7
|
||||
fi
|
||||
|
||||
if test "$depmode" = xlc; then
|
||||
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
|
||||
gccflag=-qmakedep=gcc,-MF
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
|
@ -107,8 +190,7 @@ gcc3)
|
|||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
|
@ -116,13 +198,17 @@ gcc3)
|
|||
;;
|
||||
|
||||
gcc)
|
||||
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
|
||||
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
|
||||
## (see the conditional assignment to $gccflag above).
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say).
|
||||
## -MM, not -M (despite what the docs say). Also, it might not be
|
||||
## supported by the other compilers which use the 'gcc' depmode.
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
|
@ -130,31 +216,31 @@ gcc)
|
|||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
|
||||
## The second -e expression handles DOS-style file names with drive letters.
|
||||
# The second -e expression handles DOS-style file names with drive
|
||||
# letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the `deleted header file' problem.
|
||||
## This next piece of magic avoids the "deleted header file" problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" |
|
||||
## Some versions of gcc put a space before the `:'. On the theory
|
||||
## Some versions of gcc put a space before the ':'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well.
|
||||
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||
## to the object. Take care to not repeat it in the output.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
|
@ -172,8 +258,7 @@ sgi)
|
|||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
|
@ -181,99 +266,156 @@ sgi)
|
|||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like `#:fec' to the end of the
|
||||
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
|
||||
tr '
|
||||
' ' ' >> $depfile
|
||||
echo >> $depfile
|
||||
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
|
||||
| tr "$nl" ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> $depfile
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
xlc)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts `$object:' at the
|
||||
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'`
|
||||
tmpdepfile="$stripped.u"
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
|
||||
if test -f "$tmpdepfile"; then :
|
||||
else
|
||||
stripped=`echo "$stripped" | sed 's,^.*/,,'`
|
||||
tmpdepfile="$stripped.u"
|
||||
fi
|
||||
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile"
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
if test -f "$tmpdepfile"; then
|
||||
outname="$stripped.o"
|
||||
# Each line is of the form `foo.o: dependent.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
# The sourcefile does not contain any dependencies, so just
|
||||
# store a dummy comment line, to avoid errors with the Makefile
|
||||
# "include basename.Plo" scheme.
|
||||
echo "#dummy" > "$depfile"
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
tcc)
|
||||
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
|
||||
# FIXME: That version still under development at the moment of writing.
|
||||
# Make that this statement remains true also for stable, released
|
||||
# versions.
|
||||
# It will wrap lines (doesn't matter whether long or short) with a
|
||||
# trailing '\', as in:
|
||||
#
|
||||
# foo.o : \
|
||||
# foo.c \
|
||||
# foo.h \
|
||||
#
|
||||
# It will put a trailing '\' even on the last line, and will use leading
|
||||
# spaces rather than leading tabs (at least since its commit 0394caf7
|
||||
# "Emit spaces for -MD").
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
|
||||
# We have to change lines of the first kind to '$object: \'.
|
||||
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
|
||||
# And for each line of the second kind, we have to emit a 'dep.h:'
|
||||
# dummy dependency, to avoid the deleted-header problem.
|
||||
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
icc)
|
||||
# Intel's C compiler understands `-MD -MF file'. However on
|
||||
# icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
|
||||
# ICC 7.0 will fill foo.d with something like
|
||||
# foo.o: sub/foo.c
|
||||
# foo.o: sub/foo.h
|
||||
# which is wrong. We want:
|
||||
# sub/foo.o: sub/foo.c
|
||||
# sub/foo.o: sub/foo.h
|
||||
# sub/foo.c:
|
||||
# sub/foo.h:
|
||||
# ICC 7.1 will output
|
||||
## The order of this option in the case statement is important, since the
|
||||
## shell code in configure will try each of these formats in the order
|
||||
## listed in this file. A plain '-MD' option would be understood by many
|
||||
## compilers, so we must ensure this comes after the gcc and icc options.
|
||||
pgcc)
|
||||
# Portland's C compiler understands '-MD'.
|
||||
# Will always output deps to 'file.d' where file is the root name of the
|
||||
# source file under compilation, even if file resides in a subdirectory.
|
||||
# The object file name does not affect the name of the '.d' file.
|
||||
# pgcc 10.2 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using \ :
|
||||
# and will wrap long lines using '\' :
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
set_dir_from "$object"
|
||||
# Use the source, not the object, to determine the base name, since
|
||||
# that's sadly what pgcc will do too.
|
||||
set_base_from "$source"
|
||||
tmpdepfile=$base.d
|
||||
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
# For projects that build the same source file twice into different object
|
||||
# files, the pgcc approach of using the *source* file root name can cause
|
||||
# problems in parallel builds. Use a locking strategy to avoid stomping on
|
||||
# the same $tmpdepfile.
|
||||
lockdir=$base.d-lock
|
||||
trap "
|
||||
echo '$0: caught signal, cleaning up...' >&2
|
||||
rmdir '$lockdir'
|
||||
exit 1
|
||||
" 1 2 13 15
|
||||
numtries=100
|
||||
i=$numtries
|
||||
while test $i -gt 0; do
|
||||
# mkdir is a portable test-and-set.
|
||||
if mkdir "$lockdir" 2>/dev/null; then
|
||||
# This process acquired the lock.
|
||||
"$@" -MD
|
||||
stat=$?
|
||||
# Release the lock.
|
||||
rmdir "$lockdir"
|
||||
break
|
||||
else
|
||||
# If the lock is being held by a different process, wait
|
||||
# until the winning process is done or we timeout.
|
||||
while test -d "$lockdir" && test $i -gt 0; do
|
||||
sleep 1
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
fi
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
trap - 1 2 13 15
|
||||
if test $i -le 0; then
|
||||
echo "$0: failed to acquire lock after $numtries attempts" >&2
|
||||
echo "$0: check lockdir '$lockdir'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
|
@ -285,8 +427,8 @@ icc)
|
|||
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
|
||||
sed -e 's/$/ :/' >> "$depfile"
|
||||
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
|
@ -297,9 +439,8 @@ hp2)
|
|||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
|
@ -310,8 +451,7 @@ hp2)
|
|||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
@ -321,72 +461,107 @@ hp2)
|
|||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add `dependent.h:' lines.
|
||||
sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile"
|
||||
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add 'dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in `foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
|
||||
test "x$dir" = "x$object" && dir=
|
||||
base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in 'foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# With Tru64 cc, shared objects can also be used to make a
|
||||
# static library. This mechanism is used in libtool 1.4 series to
|
||||
# handle both shared and static libraries in a single compilation.
|
||||
# With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
|
||||
#
|
||||
# With libtool 1.5 this exception was removed, and libtool now
|
||||
# generates 2 separate objects for the 2 libraries. These two
|
||||
# compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4
|
||||
tmpdepfile2=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5
|
||||
tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.o.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
tmpdepfile4=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
if test "$libtool" = yes; then
|
||||
# Libtool generates 2 separate objects for the 2 libraries. These
|
||||
# two compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
|
||||
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -eq 0; then :
|
||||
else
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
exit $stat
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
|
||||
# That's a tab and a space in the [].
|
||||
sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
echo "#dummy" > "$depfile"
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
# Same post-processing that is required for AIX mode.
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
msvc7)
|
||||
if test "$libtool" = yes; then
|
||||
showIncludes=-Wc,-showIncludes
|
||||
else
|
||||
showIncludes=-showIncludes
|
||||
fi
|
||||
"$@" $showIncludes > "$tmpdepfile"
|
||||
stat=$?
|
||||
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The first sed program below extracts the file names and escapes
|
||||
# backslashes for cygpath. The second sed program outputs the file
|
||||
# name when reading, but also accumulates all include files in the
|
||||
# hold buffer in order to output them again at the end. This only
|
||||
# works with sed implementations that can handle large buffers.
|
||||
sed < "$tmpdepfile" -n '
|
||||
/^Note: including file: *\(.*\)/ {
|
||||
s//\1/
|
||||
s/\\/\\\\/g
|
||||
p
|
||||
}' | $cygpath_u | sort -u | sed -n '
|
||||
s/ /\\ /g
|
||||
s/\(.*\)/'"$tab"'\1 \\/p
|
||||
s/.\(.*\) \\/\1:/
|
||||
H
|
||||
$ {
|
||||
s/.*/'"$tab"'/
|
||||
G
|
||||
p
|
||||
}' >> "$depfile"
|
||||
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7msys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
|
@ -399,13 +574,13 @@ dashmstdout)
|
|||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test $1 != '--mode=compile'; do
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove `-o $object'.
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
|
@ -425,18 +600,18 @@ dashmstdout)
|
|||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for `:'
|
||||
# Require at least two characters before searching for ':'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
|
||||
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile"
|
||||
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
tr ' ' '
|
||||
' < "$tmpdepfile" | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this sed invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
|
@ -450,41 +625,51 @@ makedepend)
|
|||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test $1 != '--mode=compile'; do
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no
|
||||
for arg in "$@"; do
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix="`echo $object | sed 's/^.*\././'`"
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
sed '1,2d' "$tmpdepfile" | tr ' ' '
|
||||
' | \
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
|
||||
# makedepend may prepend the VPATH from the source file name to the object.
|
||||
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process the last invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed '1,2d' "$tmpdepfile" \
|
||||
| tr ' ' "$nl" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
|
@ -495,13 +680,13 @@ cpp)
|
|||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test $1 != '--mode=compile'; do
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove `-o $object'.
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
|
@ -520,10 +705,10 @@ cpp)
|
|||
esac
|
||||
done
|
||||
|
||||
"$@" -E |
|
||||
sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
|
||||
sed '$ s: \\$::' > "$tmpdepfile"
|
||||
"$@" -E \
|
||||
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
| sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
|
@ -533,35 +718,56 @@ cpp)
|
|||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o,
|
||||
# because we must use -o when running libtool.
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile"
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile"
|
||||
echo " " >> "$depfile"
|
||||
. "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||
echo "$tab" >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
@ -580,5 +786,6 @@ exit 0
|
|||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2006-10-14.15
|
||||
scriptversion=2011-11-20.07; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
|
@ -35,7 +35,7 @@ scriptversion=2006-10-14.15
|
|||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# 'make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
|
@ -48,7 +48,7 @@ IFS=" "" $nl"
|
|||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
doit=${DOITPROG-}
|
||||
if test -z "$doit"; then
|
||||
doit_exec=exec
|
||||
else
|
||||
|
@ -58,34 +58,49 @@ fi
|
|||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_glob='?'
|
||||
initialize_posix_glob='
|
||||
test "$posix_glob" != "?" || {
|
||||
if (set -f) 2>/dev/null; then
|
||||
posix_glob=
|
||||
else
|
||||
posix_glob=:
|
||||
fi
|
||||
}
|
||||
'
|
||||
|
||||
posix_glob=
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
chgrpcmd=
|
||||
stripcmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dstarg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
no_target_directory=
|
||||
|
||||
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
@ -95,65 +110,59 @@ In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
|||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
-c (ignored)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve the last data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) shift
|
||||
continue;;
|
||||
-c) ;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
shift
|
||||
shift
|
||||
case $mode in
|
||||
*' '* | *' '* | *'
|
||||
'* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
continue;;
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
shift;;
|
||||
|
||||
-s) stripcmd=$stripprog
|
||||
shift
|
||||
continue;;
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t) dstarg=$2
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
-t) dst_arg=$2
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-T) no_target_directory=true
|
||||
shift
|
||||
continue;;
|
||||
-T) no_target_directory=true;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
|
@ -165,21 +174,26 @@ while test $# -ne 0; do
|
|||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dstarg"; then
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dstarg"; then
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dstarg"
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dstarg=$arg
|
||||
dst_arg=$arg
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
|
@ -188,13 +202,17 @@ if test $# -eq 0; then
|
|||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call `install-sh -d' without argument.
|
||||
# It's OK to call 'install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
do_exit='(exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
|
@ -222,9 +240,9 @@ fi
|
|||
|
||||
for src
|
||||
do
|
||||
# Protect names starting with `-'.
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $src in
|
||||
-*) src=./$src ;;
|
||||
-* | [=\(\)!]) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
|
@ -242,22 +260,17 @@ do
|
|||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dstarg"; then
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dst=$dstarg
|
||||
# Protect names starting with `-'.
|
||||
case $dst in
|
||||
-*) dst=./$dst ;;
|
||||
esac
|
||||
dst=$dst_arg
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test -n "$no_target_directory"; then
|
||||
echo "$0: $dstarg: Is a directory" >&2
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
|
@ -341,7 +354,7 @@ do
|
|||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writeable bit of parent directory when it shouldn't.
|
||||
# other-writable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
|
@ -378,33 +391,26 @@ do
|
|||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix=/ ;;
|
||||
-*) prefix=./ ;;
|
||||
*) prefix= ;;
|
||||
/*) prefix='/';;
|
||||
[-=\(\)!]*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
case $posix_glob in
|
||||
'')
|
||||
if (set -f) 2>/dev/null; then
|
||||
posix_glob=true
|
||||
else
|
||||
posix_glob=false
|
||||
fi ;;
|
||||
esac
|
||||
eval "$initialize_posix_glob"
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
$posix_glob && set -f
|
||||
$posix_glob set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
$posix_glob && set +f
|
||||
$posix_glob set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test -z "$d" && continue
|
||||
test X"$d" = X && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
|
@ -459,41 +465,54 @@ do
|
|||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
|
||||
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
|
||||
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
|
||||
&& { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
{ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \
|
||||
|| {
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
if test -f "$dst"; then
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null \
|
||||
|| { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \
|
||||
&& { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\
|
||||
|| {
|
||||
echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
else
|
||||
:
|
||||
fi
|
||||
} &&
|
||||
eval "$initialize_posix_glob" &&
|
||||
$posix_glob set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
$posix_glob set +f &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
} || exit 1
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
|
@ -503,5 +522,6 @@ done
|
|||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
#! /bin/sh
|
||||
# Common stub for a few missing GNU programs while installing.
|
||||
# Common wrapper for a few potentially missing GNU programs.
|
||||
|
||||
scriptversion=2006-05-10.23
|
||||
scriptversion=2013-10-28.13; # UTC
|
||||
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006
|
||||
# Free Software Foundation, Inc.
|
||||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
|
||||
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,9 +17,7 @@ scriptversion=2006-05-10.23
|
|||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
|
@ -28,66 +25,40 @@ scriptversion=2006-05-10.23
|
|||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
echo 1>&2 "Try '$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run=:
|
||||
sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
|
||||
sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
|
||||
|
||||
# In the cases where this matters, `missing' is being run in the
|
||||
# srcdir already.
|
||||
if test -f configure.ac; then
|
||||
configure_ac=configure.ac
|
||||
else
|
||||
configure_ac=configure.in
|
||||
fi
|
||||
|
||||
msg="missing on your system"
|
||||
|
||||
case $1 in
|
||||
--run)
|
||||
# Try to run requested program, and just exit if it succeeds.
|
||||
run=
|
||||
shift
|
||||
"$@" && exit 0
|
||||
# Exit code 63 means version mismatch. This often happens
|
||||
# when the user try to use an ancient version of a tool on
|
||||
# a file that requires a minimum version. In this case we
|
||||
# we should proceed has if the program had been absent, or
|
||||
# if --run hadn't been passed.
|
||||
if test $? = 63; then
|
||||
run=:
|
||||
msg="probably too old"
|
||||
fi
|
||||
;;
|
||||
|
||||
--is-lightweight)
|
||||
# Used by our autoconf macros to check whether the available missing
|
||||
# script is modern enough.
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--run)
|
||||
# Back-compat with the calling convention used by older automake.
|
||||
shift
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
|
||||
error status if there is no known handling for PROGRAM.
|
||||
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
|
||||
to PROGRAM being missing or too old.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
--run try to run the given command, and emulate it if it fails
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal touch file \`aclocal.m4'
|
||||
autoconf touch file \`configure'
|
||||
autoheader touch file \`config.h.in'
|
||||
autom4te touch the output file, or create a stub one
|
||||
automake touch all \`Makefile.in' files
|
||||
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
flex create \`lex.yy.c', if possible, from existing .c
|
||||
help2man touch the output file
|
||||
lex create \`lex.yy.c', if possible, from existing .c
|
||||
makeinfo touch the output file
|
||||
tar try tar, gnutar, gtar, then tar without non-portable flags
|
||||
yacc create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
aclocal autoconf autoheader autom4te automake makeinfo
|
||||
bison yacc flex lex help2man
|
||||
|
||||
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
|
||||
'g' are ignored when checking the name.
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
exit $?
|
||||
|
@ -99,269 +70,146 @@ Send bug reports to <bug-automake@gnu.org>."
|
|||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: Unknown \`$1' option"
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
echo 1>&2 "$0: unknown '$1' option"
|
||||
echo 1>&2 "Try '$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# Now exit if we have it, but it failed. Also exit now if we
|
||||
# don't have it and --version was passed (most likely to detect
|
||||
# the program).
|
||||
case $1 in
|
||||
lex|yacc)
|
||||
# Not GNU programs, they don't have --version.
|
||||
# Run the given program, remember its exit status.
|
||||
"$@"; st=$?
|
||||
|
||||
# If it succeeded, we are done.
|
||||
test $st -eq 0 && exit 0
|
||||
|
||||
# Also exit now if we it failed (or wasn't found), and '--version' was
|
||||
# passed; such an option is passed most likely to detect whether the
|
||||
# program is present and works.
|
||||
case $2 in --version|--help) exit $st;; esac
|
||||
|
||||
# Exit code 63 means version mismatch. This often happens when the user
|
||||
# tries to use an ancient version of a tool on a file that requires a
|
||||
# minimum version.
|
||||
if test $st -eq 63; then
|
||||
msg="probably too old"
|
||||
elif test $st -eq 127; then
|
||||
# Program was missing.
|
||||
msg="missing on your system"
|
||||
else
|
||||
# Program was found and executed, but failed. Give up.
|
||||
exit $st
|
||||
fi
|
||||
|
||||
perl_URL=http://www.perl.org/
|
||||
flex_URL=http://flex.sourceforge.net/
|
||||
gnu_software_URL=http://www.gnu.org/software
|
||||
|
||||
program_details ()
|
||||
{
|
||||
case $1 in
|
||||
aclocal|automake)
|
||||
echo "The '$1' program is part of the GNU Automake package:"
|
||||
echo "<$gnu_software_URL/automake>"
|
||||
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
|
||||
echo "<$gnu_software_URL/autoconf>"
|
||||
echo "<$gnu_software_URL/m4/>"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
autoconf|autom4te|autoheader)
|
||||
echo "The '$1' program is part of the GNU Autoconf package:"
|
||||
echo "<$gnu_software_URL/autoconf/>"
|
||||
echo "It also requires GNU m4 and Perl in order to run:"
|
||||
echo "<$gnu_software_URL/m4/>"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
give_advice ()
|
||||
{
|
||||
# Normalize program name to check for.
|
||||
normalized_program=`echo "$1" | sed '
|
||||
s/^gnu-//; t
|
||||
s/^gnu//; t
|
||||
s/^g//; t'`
|
||||
|
||||
printf '%s\n' "'$1' is $msg."
|
||||
|
||||
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
|
||||
case $normalized_program in
|
||||
autoconf*)
|
||||
echo "You should only need it if you modified 'configure.ac',"
|
||||
echo "or m4 files included by it."
|
||||
program_details 'autoconf'
|
||||
;;
|
||||
autoheader*)
|
||||
echo "You should only need it if you modified 'acconfig.h' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'autoheader'
|
||||
;;
|
||||
automake*)
|
||||
echo "You should only need it if you modified 'Makefile.am' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'automake'
|
||||
;;
|
||||
aclocal*)
|
||||
echo "You should only need it if you modified 'acinclude.m4' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'aclocal'
|
||||
;;
|
||||
autom4te*)
|
||||
echo "You might have modified some maintainer files that require"
|
||||
echo "the 'autom4te' program to be rebuilt."
|
||||
program_details 'autom4te'
|
||||
;;
|
||||
bison*|yacc*)
|
||||
echo "You should only need it if you modified a '.y' file."
|
||||
echo "You may want to install the GNU Bison package:"
|
||||
echo "<$gnu_software_URL/bison/>"
|
||||
;;
|
||||
lex*|flex*)
|
||||
echo "You should only need it if you modified a '.l' file."
|
||||
echo "You may want to install the Fast Lexical Analyzer package:"
|
||||
echo "<$flex_URL>"
|
||||
;;
|
||||
help2man*)
|
||||
echo "You should only need it if you modified a dependency" \
|
||||
"of a man page."
|
||||
echo "You may want to install the GNU Help2man package:"
|
||||
echo "<$gnu_software_URL/help2man/>"
|
||||
;;
|
||||
makeinfo*)
|
||||
echo "You should only need it if you modified a '.texi' file, or"
|
||||
echo "any other file indirectly affecting the aspect of the manual."
|
||||
echo "You might want to install the Texinfo package:"
|
||||
echo "<$gnu_software_URL/texinfo/>"
|
||||
echo "The spurious makeinfo call might also be the consequence of"
|
||||
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
|
||||
echo "want to install GNU make:"
|
||||
echo "<$gnu_software_URL/make/>"
|
||||
;;
|
||||
*)
|
||||
echo "You might have modified some files without having the proper"
|
||||
echo "tools for further handling them. Check the 'README' file, it"
|
||||
echo "often tells you about the needed prerequisites for installing"
|
||||
echo "this package. You may also peek at any GNU archive site, in"
|
||||
echo "case some other package contains this missing '$1' program."
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
tar)
|
||||
if test -n "$run"; then
|
||||
echo 1>&2 "ERROR: \`tar' requires --run"
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
give_advice "$1" | sed -e '1s/^/WARNING: /' \
|
||||
-e '2,$s/^/ /' >&2
|
||||
|
||||
*)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
|
||||
# Could not run --version or --help. This is probably someone
|
||||
# running `$TOOL --version' or `$TOOL --help' to check whether
|
||||
# $TOOL exists and not knowing $TOOL uses missing.
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# If it does not exist, or fails to run (possibly an outdated version),
|
||||
# try to emulate it.
|
||||
case $1 in
|
||||
aclocal*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
|
||||
to install the \`Automake' and \`Perl' packages. Grab them from
|
||||
any GNU archive site."
|
||||
touch aclocal.m4
|
||||
;;
|
||||
|
||||
autoconf)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`${configure_ac}'. You might want to install the
|
||||
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
|
||||
archive site."
|
||||
touch configure
|
||||
;;
|
||||
|
||||
autoheader)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`acconfig.h' or \`${configure_ac}'. You might want
|
||||
to install the \`Autoconf' and \`GNU m4' packages. Grab them
|
||||
from any GNU archive site."
|
||||
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
|
||||
test -z "$files" && files="config.h"
|
||||
touch_files=
|
||||
for f in $files; do
|
||||
case $f in
|
||||
*:*) touch_files="$touch_files "`echo "$f" |
|
||||
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
|
||||
*) touch_files="$touch_files $f.in";;
|
||||
esac
|
||||
done
|
||||
touch $touch_files
|
||||
;;
|
||||
|
||||
automake*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
|
||||
You might want to install the \`Automake' and \`Perl' packages.
|
||||
Grab them from any GNU archive site."
|
||||
find . -type f -name Makefile.am -print |
|
||||
sed 's/\.am$/.in/' |
|
||||
while read f; do touch "$f"; done
|
||||
;;
|
||||
|
||||
autom4te)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, but is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them.
|
||||
You can get \`$1' as part of \`Autoconf' from any GNU
|
||||
archive site."
|
||||
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo "#! /bin/sh"
|
||||
echo "# Created by GNU Automake missing as a replacement of"
|
||||
echo "# $ $@"
|
||||
echo "exit 0"
|
||||
chmod +x $file
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
bison|yacc)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' $msg. You should only need it if
|
||||
you modified a \`.y' file. You may need the \`Bison' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Bison' from any GNU archive site."
|
||||
rm -f y.tab.c y.tab.h
|
||||
if test $# -ne 1; then
|
||||
eval LASTARG="\${$#}"
|
||||
case $LASTARG in
|
||||
*.y)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" y.tab.c
|
||||
fi
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" y.tab.h
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if test ! -f y.tab.h; then
|
||||
echo >y.tab.h
|
||||
fi
|
||||
if test ! -f y.tab.c; then
|
||||
echo 'main() { return 0; }' >y.tab.c
|
||||
fi
|
||||
;;
|
||||
|
||||
lex|flex)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.l' file. You may need the \`Flex' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Flex' from any GNU archive site."
|
||||
rm -f lex.yy.c
|
||||
if test $# -ne 1; then
|
||||
eval LASTARG="\${$#}"
|
||||
case $LASTARG in
|
||||
*.l)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
||||
if test -f "$SRCFILE"; then
|
||||
cp "$SRCFILE" lex.yy.c
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if test ! -f lex.yy.c; then
|
||||
echo 'main() { return 0; }' >lex.yy.c
|
||||
fi
|
||||
;;
|
||||
|
||||
help2man)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a dependency of a manual page. You may need the
|
||||
\`Help2man' package in order for those modifications to take
|
||||
effect. You can get \`Help2man' from any GNU archive site."
|
||||
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo ".ab help2man is required to generate this page"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
makeinfo)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is $msg. You should only need it if
|
||||
you modified a \`.texi' or \`.texinfo' file, or any other file
|
||||
indirectly affecting the aspect of the manual. The spurious
|
||||
call might also be the consequence of using a buggy \`make' (AIX,
|
||||
DU, IRIX). You might want to install the \`Texinfo' package or
|
||||
the \`GNU make' package. Grab either from any GNU archive site."
|
||||
# The file to touch is that specified with -o ...
|
||||
file=`echo "$*" | sed -n "$sed_output"`
|
||||
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
|
||||
if test -z "$file"; then
|
||||
# ... or it is the one specified with @setfilename ...
|
||||
infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
||||
file=`sed -n '
|
||||
/^@setfilename/{
|
||||
s/.* \([^ ]*\) *$/\1/
|
||||
p
|
||||
q
|
||||
}' $infile`
|
||||
# ... or it is derived from the source name (dir/f.texi becomes f.info)
|
||||
test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
|
||||
fi
|
||||
# If the file does not exist, the user really needs makeinfo;
|
||||
# let's fail without touching anything.
|
||||
test -f $file || exit 1
|
||||
touch $file
|
||||
;;
|
||||
|
||||
tar)
|
||||
shift
|
||||
|
||||
# We have already tried tar in the generic part.
|
||||
# Look for gnutar/gtar before invocation to avoid ugly error
|
||||
# messages.
|
||||
if (gnutar --version > /dev/null 2>&1); then
|
||||
gnutar "$@" && exit 0
|
||||
fi
|
||||
if (gtar --version > /dev/null 2>&1); then
|
||||
gtar "$@" && exit 0
|
||||
fi
|
||||
firstarg="$1"
|
||||
if shift; then
|
||||
case $firstarg in
|
||||
*o*)
|
||||
firstarg=`echo "$firstarg" | sed s/o//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
case $firstarg in
|
||||
*h*)
|
||||
firstarg=`echo "$firstarg" | sed s/h//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: I can't seem to be able to run \`tar' with the given arguments.
|
||||
You may want to install GNU tar or Free paxutils, or check the
|
||||
command line arguments."
|
||||
exit 1
|
||||
;;
|
||||
|
||||
*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, and is $msg.
|
||||
You might have modified some files without having the
|
||||
proper tools for further handling them. Check the \`README' file,
|
||||
it often tells you about the needed prerequisites for installing
|
||||
this package. You may also peek at any GNU archive site, in case
|
||||
some other package would contain this missing \`$1' program."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
# Propagate the correct exit status (expected to be 127 for a program
|
||||
# not found, 63 for a program that failed due to version mismatch).
|
||||
exit $st
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
#! /bin/sh
|
||||
# test-driver - basic testsuite driver script.
|
||||
|
||||
scriptversion=2013-07-13.22; # UTC
|
||||
|
||||
# Copyright (C) 2011-2013 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
# Make unconditional expansion of undefined variables an error. This
|
||||
# helps a lot in preventing typo-related bugs.
|
||||
set -u
|
||||
|
||||
usage_error ()
|
||||
{
|
||||
echo "$0: $*" >&2
|
||||
print_usage >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
print_usage ()
|
||||
{
|
||||
cat <<END
|
||||
Usage:
|
||||
test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
|
||||
[--expect-failure={yes|no}] [--color-tests={yes|no}]
|
||||
[--enable-hard-errors={yes|no}] [--]
|
||||
TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
|
||||
The '--test-name', '--log-file' and '--trs-file' options are mandatory.
|
||||
END
|
||||
}
|
||||
|
||||
test_name= # Used for reporting.
|
||||
log_file= # Where to save the output of the test script.
|
||||
trs_file= # Where to save the metadata of the test run.
|
||||
expect_failure=no
|
||||
color_tests=no
|
||||
enable_hard_errors=yes
|
||||
while test $# -gt 0; do
|
||||
case $1 in
|
||||
--help) print_usage; exit $?;;
|
||||
--version) echo "test-driver $scriptversion"; exit $?;;
|
||||
--test-name) test_name=$2; shift;;
|
||||
--log-file) log_file=$2; shift;;
|
||||
--trs-file) trs_file=$2; shift;;
|
||||
--color-tests) color_tests=$2; shift;;
|
||||
--expect-failure) expect_failure=$2; shift;;
|
||||
--enable-hard-errors) enable_hard_errors=$2; shift;;
|
||||
--) shift; break;;
|
||||
-*) usage_error "invalid option: '$1'";;
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
missing_opts=
|
||||
test x"$test_name" = x && missing_opts="$missing_opts --test-name"
|
||||
test x"$log_file" = x && missing_opts="$missing_opts --log-file"
|
||||
test x"$trs_file" = x && missing_opts="$missing_opts --trs-file"
|
||||
if test x"$missing_opts" != x; then
|
||||
usage_error "the following mandatory options are missing:$missing_opts"
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
usage_error "missing argument"
|
||||
fi
|
||||
|
||||
if test $color_tests = yes; then
|
||||
# Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
|
||||
red='[0;31m' # Red.
|
||||
grn='[0;32m' # Green.
|
||||
lgn='[1;32m' # Light green.
|
||||
blu='[1;34m' # Blue.
|
||||
mgn='[0;35m' # Magenta.
|
||||
std='[m' # No color.
|
||||
else
|
||||
red= grn= lgn= blu= mgn= std=
|
||||
fi
|
||||
|
||||
do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
|
||||
trap "st=129; $do_exit" 1
|
||||
trap "st=130; $do_exit" 2
|
||||
trap "st=141; $do_exit" 13
|
||||
trap "st=143; $do_exit" 15
|
||||
|
||||
# Test script is run here.
|
||||
"$@" >$log_file 2>&1
|
||||
estatus=$?
|
||||
if test $enable_hard_errors = no && test $estatus -eq 99; then
|
||||
estatus=1
|
||||
fi
|
||||
|
||||
case $estatus:$expect_failure in
|
||||
0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
|
||||
0:*) col=$grn res=PASS recheck=no gcopy=no;;
|
||||
77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
|
||||
99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
|
||||
*:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
|
||||
*:*) col=$red res=FAIL recheck=yes gcopy=yes;;
|
||||
esac
|
||||
|
||||
# Report outcome to console.
|
||||
echo "${col}${res}${std}: $test_name"
|
||||
|
||||
# Register the test result, and other relevant metadata.
|
||||
echo ":test-result: $res" > $trs_file
|
||||
echo ":global-test-result: $res" >> $trs_file
|
||||
echo ":recheck: $recheck" >> $trs_file
|
||||
echo ":copy-in-global-log: $gcopy" >> $trs_file
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
|
@ -0,0 +1,10 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@/@PACKAGE_NAME@
|
||||
|
||||
Name: google-breakpad-client
|
||||
Description: An open-source multi-platform crash reporting system
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs: -L${libdir} -lbreakpad_client @PTHREAD_LIBS@
|
||||
Cflags: -I${includedir} @PTHREAD_CFLAGS@
|
|
@ -0,0 +1,10 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@/@PACKAGE_NAME@
|
||||
|
||||
Name: google-breakpad
|
||||
Description: An open-source multi-platform crash reporting system
|
||||
Version: @PACKAGE_VERSION@
|
||||
Libs: -L${libdir} -lbreakpad @PTHREAD_LIBS@
|
||||
Cflags: -I${includedir} @PTHREAD_CFLAGS@
|
|
@ -1,5 +1,5 @@
|
|||
# This file is used by gcl to get repository specific information.
|
||||
CODE_REVIEW_SERVER: breakpad.appspot.com
|
||||
CODE_REVIEW_SERVER: codereview.chromium.org
|
||||
CC_LIST: google-breakpad-dev@googlegroups.com
|
||||
TRY_ON_UPLOAD: False
|
||||
VIEW_VC: http://code.google.com/p/google-breakpad/source/detail?r=
|
||||
VIEW_VC: https://chromium.googlesource.com/breakpad/breakpad/+/
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -32,13 +32,14 @@ AC_PREREQ(2.57)
|
|||
|
||||
AC_INIT(breakpad, 0.1, google-breakpad-dev@googlegroups.com)
|
||||
dnl Sanity check: the argument is just a file that should exist.
|
||||
AC_CONFIG_SRCDIR(README)
|
||||
AC_CONFIG_SRCDIR(README.md)
|
||||
AC_CONFIG_AUX_DIR(autotools)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
AM_INIT_AUTOMAKE(subdir-objects tar-ustar 1.11.1)
|
||||
AM_CONFIG_HEADER(src/config.h)
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
AM_PROG_AS
|
||||
AC_PROG_CC
|
||||
|
@ -48,7 +49,28 @@ AC_PROG_CXX
|
|||
AC_PROG_RANLIB
|
||||
AM_CONDITIONAL(GCC, test "$GCC" = yes) # let the Makefile know if we're gcc
|
||||
|
||||
dnl This must come before all the feature tests below.
|
||||
AC_ARG_ENABLE(m32,
|
||||
AS_HELP_STRING([--enable-m32],
|
||||
[Compile/build with -m32]
|
||||
[(default is no)]),
|
||||
[case "${enableval}" in
|
||||
yes)
|
||||
CFLAGS="${CFLAGS} -m32"
|
||||
CXXFLAGS="${CXXFLAGS} -m32"
|
||||
usem32=true
|
||||
;;
|
||||
no)
|
||||
usem32=false
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR(bad value ${enableval} for --enable-m32)
|
||||
;;
|
||||
esac],
|
||||
[usem32=false])
|
||||
|
||||
AC_HEADER_STDC
|
||||
AC_SYS_LARGEFILE
|
||||
m4_include(m4/ax_pthread.m4)
|
||||
AX_PTHREAD
|
||||
AC_CHECK_HEADERS([a.out.h])
|
||||
|
@ -69,25 +91,6 @@ case $host in
|
|||
esac
|
||||
AM_CONDITIONAL(ANDROID_HOST, test x$ANDROID_HOST = xtrue)
|
||||
|
||||
AC_ARG_ENABLE(m32,
|
||||
AS_HELP_STRING([--enable-m32],
|
||||
[Compile/build with -m32]
|
||||
[(default is no)]),
|
||||
[case "${enableval}" in
|
||||
yes)
|
||||
CFLAGS="${CFLAGS} -m32"
|
||||
CXXFLAGS="${CXXFLAGS} -m32"
|
||||
usem32=true
|
||||
;;
|
||||
no)
|
||||
usem32=false
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR(bad value ${enableval} for --enable-m32)
|
||||
;;
|
||||
esac],
|
||||
[usem32=false])
|
||||
|
||||
AC_ARG_ENABLE(processor,
|
||||
AS_HELP_STRING([--disable-processor],
|
||||
[Don't build processor library]
|
||||
|
@ -147,5 +150,10 @@ AC_ARG_ENABLE(selftest,
|
|||
[selftest=false])
|
||||
AM_CONDITIONAL(SELFTEST, test x$selftest = xtrue)
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_CONFIG_FILES(m4_flatten([
|
||||
breakpad.pc
|
||||
breakpad-client.pc
|
||||
Makefile
|
||||
]))
|
||||
|
||||
AC_OUTPUT
|
||||
|
|
|
@ -33,4 +33,25 @@
|
|||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "testing/include/gmock/gmock.h"
|
||||
|
||||
// If AddressSanitizer is used, NULL pointer dereferences generate SIGILL
|
||||
// (illegal instruction) instead of SIGSEGV (segmentation fault). Also,
|
||||
// the number of memory regions differs, so there is no point in running
|
||||
// this test if AddressSanitizer is used.
|
||||
//
|
||||
// Ideally we'd use this attribute to disable ASAN on a per-func basis,
|
||||
// but this doesn't seem to actually work, and it's changed names over
|
||||
// time. So just stick with disabling the actual tests.
|
||||
// http://crbug.com/304575
|
||||
//#define NO_ASAN __attribute__((no_sanitize_address))
|
||||
#if defined(__clang__) && defined(__has_feature)
|
||||
// Have to keep this check sep from above as newer gcc will barf on it.
|
||||
# if __has_feature(address_sanitizer)
|
||||
# define ADDRESS_SANITIZER
|
||||
# endif
|
||||
#elif defined(__GNUC__) && defined(__SANITIZE_ADDRESS__)
|
||||
# define ADDRESS_SANITIZER
|
||||
#else
|
||||
# undef ADDRESS_SANITIZER
|
||||
#endif
|
||||
|
||||
#endif // BREAKPAD_GOOGLETEST_INCLUDES_H__
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'All',
|
||||
'type': 'none',
|
||||
'dependencies': [
|
||||
'../common/common.gyp:*',
|
||||
'../processor/processor.gyp:*',
|
||||
'../tools/tools.gyp:*',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
# Copyright (c) 2010, Google Inc.
|
||||
# All rights reserved.
|
||||
# Copyright 2010 Google Inc. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
|
@ -32,34 +31,13 @@
|
|||
# since gyp_chromium is automatically forcing its inclusion.
|
||||
{
|
||||
'variables': {
|
||||
# .gyp files or targets should set chromium_code to 1 if they build
|
||||
# Chromium-specific code, as opposed to external code. This variable is
|
||||
# used to control such things as the set of warnings to enable, and
|
||||
# whether warnings are treated as errors.
|
||||
'chromium_code%': 0,
|
||||
|
||||
# Variables expected to be overriden on the GYP command line (-D) or by
|
||||
# ~/.gyp/include.gypi.
|
||||
|
||||
# Putting a variables dict inside another variables dict looks kind of
|
||||
# weird. This is done so that "branding" and "buildtype" are defined as
|
||||
# variables within the outer variables dict here. This is necessary
|
||||
# to get these variables defined for the conditions within this variables
|
||||
# dict that operate on these variables.
|
||||
# weird. This is necessary to get these variables defined for the conditions
|
||||
# within this variables dict that operate on these variables.
|
||||
'variables': {
|
||||
# Override branding to select the desired branding flavor.
|
||||
'branding%': 'Chromium',
|
||||
|
||||
# Override buildtype to select the desired build flavor.
|
||||
# Dev - everyday build for development/testing
|
||||
# Official - release build (generally implies additional processing)
|
||||
# TODO(mmoss) Once 'buildtype' is fully supported (e.g. Windows gyp
|
||||
# conversion is done), some of the things which are now controlled by
|
||||
# 'branding', such as symbol generation, will need to be refactored based
|
||||
# on 'buildtype' (i.e. we don't care about saving symbols for non-Official
|
||||
# builds).
|
||||
'buildtype%': 'Dev',
|
||||
|
||||
'variables': {
|
||||
# Compute the architecture that we're building on.
|
||||
'conditions': [
|
||||
|
@ -73,49 +51,19 @@
|
|||
'host_arch%': 'ia32',
|
||||
}],
|
||||
],
|
||||
|
||||
# Whether we're building a ChromeOS build. We set the initial
|
||||
# value at this level of nesting so it's available for the
|
||||
# toolkit_views test below.
|
||||
'chromeos%': '0',
|
||||
},
|
||||
|
||||
# Set default value of toolkit_views on for Windows and Chrome OS.
|
||||
# We set it at this level of nesting so the value is available for
|
||||
# other conditionals below.
|
||||
'conditions': [
|
||||
['OS=="win" or chromeos==1', {
|
||||
'toolkit_views%': 1,
|
||||
}, {
|
||||
'toolkit_views%': 0,
|
||||
}],
|
||||
],
|
||||
|
||||
'host_arch%': '<(host_arch)',
|
||||
|
||||
# Default architecture we're building for is the architecture we're
|
||||
# building on.
|
||||
'target_arch%': '<(host_arch)',
|
||||
|
||||
# We do want to build Chromium with Breakpad support in certain
|
||||
# situations. I.e. for Chrome bot.
|
||||
'linux_chromium_breakpad%': 0,
|
||||
# And if we want to dump symbols.
|
||||
'linux_chromium_dump_symbols%': 0,
|
||||
# Also see linux_strip_binary below.
|
||||
|
||||
# Copy conditionally-set chromeos variable out one scope.
|
||||
'chromeos%': '<(chromeos)',
|
||||
|
||||
# This variable tells WebCore.gyp and JavaScriptCore.gyp whether they are
|
||||
# are built under a chromium full build (1) or a webkit.org chromium
|
||||
# build (0).
|
||||
'inside_chromium_build%': 1,
|
||||
|
||||
# Set to 1 to enable fast builds. It disables debug info for fastest
|
||||
# compilation.
|
||||
'fastbuild%': 0,
|
||||
|
||||
# Set to 1 compile with -fPIC cflag on linux. This is a must for shared
|
||||
# libraries on linux x86-64 and arm.
|
||||
'linux_fpic%': 0,
|
||||
|
@ -123,10 +71,10 @@
|
|||
# Python version.
|
||||
'python_ver%': '2.5',
|
||||
|
||||
# Set ARM-v7 compilation flags
|
||||
'armv7%': 0,
|
||||
# Determine ARM compilation flags.
|
||||
'arm_version%': 7,
|
||||
|
||||
# Set Neon compilation flags (only meaningful if armv7==1).
|
||||
# Set Neon compilation flags (only meaningful if arm_version==7).
|
||||
'arm_neon%': 1,
|
||||
|
||||
# The system root for cross-compiles. Default: none.
|
||||
|
@ -136,19 +84,12 @@
|
|||
'disable_sse2%': 0,
|
||||
},
|
||||
|
||||
# Define branding and buildtype on the basis of their settings within the
|
||||
# variables sub-dict above, unless overridden.
|
||||
'branding%': '<(branding)',
|
||||
'buildtype%': '<(buildtype)',
|
||||
'target_arch%': '<(target_arch)',
|
||||
'host_arch%': '<(host_arch)',
|
||||
'toolkit_views%': '<(toolkit_views)',
|
||||
'chromeos%': '<(chromeos)',
|
||||
'inside_chromium_build%': '<(inside_chromium_build)',
|
||||
'fastbuild%': '<(fastbuild)',
|
||||
'linux_fpic%': '<(linux_fpic)',
|
||||
'python_ver%': '<(python_ver)',
|
||||
'armv7%': '<(armv7)',
|
||||
'arm_version%': '<(arm_version)',
|
||||
'arm_neon%': '<(arm_neon)',
|
||||
'sysroot%': '<(sysroot)',
|
||||
'disable_sse2%': '<(disable_sse2)',
|
||||
|
@ -245,7 +186,7 @@
|
|||
'linux_use_seccomp_sandbox%': 0,
|
||||
|
||||
# Set to select the Title Case versions of strings in GRD files.
|
||||
'use_titlecase_in_grd_files%': 0,
|
||||
'use_titlecase_in_grd%': 0,
|
||||
|
||||
# Used to disable Native Client at compile time, for platforms where it
|
||||
# isn't supported
|
||||
|
@ -254,7 +195,7 @@
|
|||
# Set Thumb compilation flags.
|
||||
'arm_thumb%': 0,
|
||||
|
||||
# Set ARM fpu compilation flags (only meaningful if armv7==1 and
|
||||
# Set ARM fpu compilation flags (only meaningful if arm_version==7 and
|
||||
# arm_neon==0).
|
||||
'arm_fpu%': 'vfpv3',
|
||||
|
||||
|
@ -262,62 +203,6 @@
|
|||
'enable_new_npdevice_api%': 0,
|
||||
|
||||
'conditions': [
|
||||
['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
|
||||
# This will set gcc_version to XY if you are running gcc X.Y.*.
|
||||
# This is used to tweak build flags for gcc 4.4.
|
||||
'gcc_version%': '<!(python <(DEPTH)/build/compiler_version.py)',
|
||||
# Figure out the python architecture to decide if we build pyauto.
|
||||
'python_arch%': '<!(<(DEPTH)/build/linux/python_arch.sh <(sysroot)/usr/lib/libpython<(python_ver).so.1.0)',
|
||||
'conditions': [
|
||||
['branding=="Chrome" or linux_chromium_breakpad==1', {
|
||||
'linux_breakpad%': 1,
|
||||
}, {
|
||||
'linux_breakpad%': 0,
|
||||
}],
|
||||
# All Chrome builds have breakpad symbols, but only process the
|
||||
# symbols from official builds.
|
||||
# TODO(mmoss) dump_syms segfaults on x64. Enable once dump_syms and
|
||||
# crash server handle 64-bit symbols.
|
||||
['linux_chromium_dump_symbols==1 or '
|
||||
'(branding=="Chrome" and buildtype=="Official" and '
|
||||
'target_arch=="ia32")', {
|
||||
'linux_dump_symbols%': 1,
|
||||
}, {
|
||||
'linux_dump_symbols%': 0,
|
||||
}],
|
||||
['toolkit_views==0', {
|
||||
# GTK wants Title Case strings
|
||||
'use_titlecase_in_grd_files%': 1,
|
||||
}],
|
||||
],
|
||||
}], # OS=="linux" or OS=="freebsd" or OS=="openbsd"
|
||||
['OS=="mac"', {
|
||||
# Mac wants Title Case strings
|
||||
'use_titlecase_in_grd_files%': 1,
|
||||
'conditions': [
|
||||
# mac_product_name is set to the name of the .app bundle as it should
|
||||
# appear on disk. This duplicates data from
|
||||
# chrome/app/theme/chromium/BRANDING and
|
||||
# chrome/app/theme/google_chrome/BRANDING, but is necessary to get
|
||||
# these names into the build system.
|
||||
['branding=="Chrome"', {
|
||||
'mac_product_name%': 'Google Chrome',
|
||||
}, { # else: branding!="Chrome"
|
||||
'mac_product_name%': 'Chromium',
|
||||
}],
|
||||
|
||||
# Feature variables for enabling Mac Breakpad and Keystone auto-update
|
||||
# support. Both features are on by default in official builds with
|
||||
# Chrome branding.
|
||||
['branding=="Chrome" and buildtype=="Official"', {
|
||||
'mac_breakpad%': 1,
|
||||
'mac_keystone%': 1,
|
||||
}, { # else: branding!="Chrome" or buildtype!="Official"
|
||||
'mac_breakpad%': 0,
|
||||
'mac_keystone%': 0,
|
||||
}],
|
||||
],
|
||||
}], # OS=="mac"
|
||||
# Whether to use multiple cores to compile with visual studio. This is
|
||||
# optional because it sometimes causes corruption on VS 2005.
|
||||
# It is on by default on VS 2008 and off on VS 2005.
|
||||
|
@ -341,24 +226,6 @@
|
|||
'NACL_WIN64',
|
||||
],
|
||||
}],
|
||||
# Compute based on OS and target architecture whether the GPU
|
||||
# plugin / process is supported.
|
||||
[ 'OS=="win" or (OS=="linux" and target_arch!="arm") or OS=="mac"', {
|
||||
# Enable a variable used elsewhere throughout the GYP files to determine
|
||||
# whether to compile in the sources for the GPU plugin / process.
|
||||
'enable_gpu%': 1,
|
||||
}, { # GPU plugin not supported
|
||||
'enable_gpu%': 0,
|
||||
}],
|
||||
# Compute based on OS, target architecture and device whether GLES
|
||||
# is supported
|
||||
[ 'OS=="linux" and target_arch=="arm" and chromeos==1', {
|
||||
# Enable a variable used elsewhere throughout the GYP files to determine
|
||||
# whether to compile in the sources for the GLES support.
|
||||
'enable_gles%': 1,
|
||||
}, { # GLES not supported
|
||||
'enable_gles%': 0,
|
||||
}],
|
||||
],
|
||||
|
||||
# NOTE: When these end up in the Mac bundle, we need to replace '-' for '_'
|
||||
|
@ -373,18 +240,10 @@
|
|||
],
|
||||
},
|
||||
'target_defaults': {
|
||||
'includes': [
|
||||
'filename_rules.gypi',
|
||||
],
|
||||
'variables': {
|
||||
# The condition that operates on chromium_code is in a target_conditions
|
||||
# section, and will not have access to the default fallback value of
|
||||
# chromium_code at the top of this file, or to the chromium_code
|
||||
# variable placed at the root variables scope of .gyp files, because
|
||||
# those variables are not set at target scope. As a workaround,
|
||||
# if chromium_code is not set at target scope, define it in target scope
|
||||
# to contain whatever value it has during early variable expansion.
|
||||
# That's enough to make it available during target conditional
|
||||
# processing.
|
||||
'chromium_code%': '<(chromium_code)',
|
||||
|
||||
# See http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Optimize-Options.html
|
||||
'mac_release_optimization%': '3', # Use -O3 unless overridden
|
||||
'mac_debug_optimization%': '0', # Use -O0 unless overridden
|
||||
|
@ -400,34 +259,6 @@
|
|||
'release_valgrind_build%': 0,
|
||||
},
|
||||
'conditions': [
|
||||
['branding=="Chrome"', {
|
||||
'defines': ['GOOGLE_CHROME_BUILD'],
|
||||
}, { # else: branding!="Chrome"
|
||||
'defines': ['CHROMIUM_BUILD'],
|
||||
}],
|
||||
['toolkit_views==1', {
|
||||
'defines': ['TOOLKIT_VIEWS=1'],
|
||||
}],
|
||||
['chromeos==1', {
|
||||
'defines': ['OS_CHROMEOS=1'],
|
||||
}],
|
||||
['fastbuild!=0', {
|
||||
'conditions': [
|
||||
# Finally, for Windows, we simply turn on profiling.
|
||||
['OS=="win"', {
|
||||
'msvs_settings': {
|
||||
'VCLinkerTool': {
|
||||
'GenerateDebugInformation': 'false',
|
||||
},
|
||||
'VCCLCompilerTool': {
|
||||
'DebugInformationFormat': '0',
|
||||
}
|
||||
}
|
||||
}, { # else: OS != "win"
|
||||
'cflags': [ '-g1' ],
|
||||
}],
|
||||
], # conditions for fastbuild.
|
||||
}], # fastbuild!=0
|
||||
['selinux==1', {
|
||||
'defines': ['CHROMIUM_SELINUX=1'],
|
||||
}],
|
||||
|
@ -438,16 +269,6 @@
|
|||
}],
|
||||
],
|
||||
}],
|
||||
['enable_gpu==1', {
|
||||
'defines': [
|
||||
'ENABLE_GPU=1',
|
||||
],
|
||||
}],
|
||||
['enable_gles==1', {
|
||||
'defines': [
|
||||
'ENABLE_GLES=1',
|
||||
],
|
||||
}],
|
||||
['coverage!=0', {
|
||||
'conditions': [
|
||||
['OS=="mac"', {
|
||||
|
@ -489,82 +310,34 @@
|
|||
}], # coverage!=0
|
||||
], # conditions for 'target_defaults'
|
||||
'target_conditions': [
|
||||
['chromium_code==0', {
|
||||
'conditions': [
|
||||
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
|
||||
'cflags!': [
|
||||
'-Wall',
|
||||
'-Wextra',
|
||||
'-Werror',
|
||||
],
|
||||
}],
|
||||
[ 'OS=="win"', {
|
||||
'defines': [
|
||||
'_CRT_SECURE_NO_DEPRECATE',
|
||||
'_CRT_NONSTDC_NO_WARNINGS',
|
||||
'_CRT_NONSTDC_NO_DEPRECATE',
|
||||
],
|
||||
'msvs_disabled_warnings': [4800],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'WarnAsError': 'false',
|
||||
'Detect64BitPortabilityProblems': 'false',
|
||||
},
|
||||
},
|
||||
}],
|
||||
[ 'OS=="mac"', {
|
||||
'xcode_settings': {
|
||||
'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO',
|
||||
'WARNING_CFLAGS!': ['-Wall'],
|
||||
},
|
||||
}],
|
||||
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
|
||||
'cflags!': [
|
||||
'-Wall',
|
||||
'-Wextra',
|
||||
'-Werror',
|
||||
],
|
||||
}, {
|
||||
# In Chromium code, we define __STDC_FORMAT_MACROS in order to get the
|
||||
# C99 macros on Mac and Linux.
|
||||
}],
|
||||
[ 'OS=="win"', {
|
||||
'defines': [
|
||||
'__STDC_FORMAT_MACROS',
|
||||
],
|
||||
'conditions': [
|
||||
['OS!="win"', {
|
||||
'sources/': [ ['exclude', '_win(_unittest)?\\.cc$'],
|
||||
['exclude', '/win/'],
|
||||
['exclude', '/win_[^/]*\\.cc$'] ],
|
||||
}],
|
||||
['OS!="mac"', {
|
||||
'sources/': [ ['exclude', '_(cocoa|mac)(_unittest)?\\.cc$'],
|
||||
['exclude', '/(cocoa|mac)/'],
|
||||
['exclude', '\.mm?$' ] ],
|
||||
}],
|
||||
['OS!="linux" and OS!="freebsd" and OS!="openbsd"', {
|
||||
'sources/': [
|
||||
['exclude', '_(chromeos|gtk|x|x11|xdg)(_unittest)?\\.cc$'],
|
||||
['exclude', '/gtk/'],
|
||||
['exclude', '/(gtk|x11)_[^/]*\\.cc$'],
|
||||
],
|
||||
}],
|
||||
['OS!="linux"', {
|
||||
'sources/': [
|
||||
['exclude', '_linux(_unittest)?\\.cc$'],
|
||||
['exclude', '/linux/'],
|
||||
],
|
||||
}],
|
||||
# We use "POSIX" to refer to all non-Windows operating systems.
|
||||
['OS=="win"', {
|
||||
'sources/': [ ['exclude', '_posix\\.cc$'] ],
|
||||
}],
|
||||
# Though Skia is conceptually shared by Linux and Windows,
|
||||
# the only _skia files in our tree are Linux-specific.
|
||||
['OS!="linux" and OS!="freebsd" and OS!="openbsd"', {
|
||||
'sources/': [ ['exclude', '_skia\\.cc$'] ],
|
||||
}],
|
||||
['chromeos!=1', {
|
||||
'sources/': [ ['exclude', '_chromeos\\.cc$'] ]
|
||||
}],
|
||||
['toolkit_views==0', {
|
||||
'sources/': [ ['exclude', '_views\\.cc$'] ]
|
||||
}],
|
||||
'_CRT_SECURE_NO_DEPRECATE',
|
||||
'_CRT_NONSTDC_NO_WARNINGS',
|
||||
'_CRT_NONSTDC_NO_DEPRECATE',
|
||||
# This is required for ATL to use XP-safe versions of its functions.
|
||||
'_USING_V110_SDK71_',
|
||||
],
|
||||
'msvs_disabled_warnings': [4800],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'WarnAsError': 'true',
|
||||
'Detect64BitPortabilityProblems': 'false',
|
||||
},
|
||||
},
|
||||
}],
|
||||
[ 'OS=="mac"', {
|
||||
'xcode_settings': {
|
||||
'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO',
|
||||
'WARNING_CFLAGS!': ['-Wall'],
|
||||
},
|
||||
}],
|
||||
], # target_conditions for 'target_defaults'
|
||||
'default_configuration': 'Debug',
|
||||
|
@ -590,6 +363,7 @@
|
|||
'abstract': 1,
|
||||
'msvs_settings': {
|
||||
'VCLinkerTool': {
|
||||
'MinimumRequiredVersion': '5.01', # XP.
|
||||
'TargetMachine': '1',
|
||||
},
|
||||
},
|
||||
|
@ -715,7 +489,30 @@
|
|||
'inherit_from': ['Common_Base', 'x86_Base', 'Release_Base'],
|
||||
'conditions': [
|
||||
['msvs_use_common_release', {
|
||||
'includes': ['release.gypi'],
|
||||
'defines': ['OFFICIAL_BUILD'],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'Optimization': '3',
|
||||
'StringPooling': 'true',
|
||||
'OmitFramePointers': 'true',
|
||||
'InlineFunctionExpansion': '2',
|
||||
'EnableIntrinsicFunctions': 'true',
|
||||
'FavorSizeOrSpeed': '2',
|
||||
'OmitFramePointers': 'true',
|
||||
'EnableFiberSafeOptimizations': 'true',
|
||||
'WholeProgramOptimization': 'true',
|
||||
},
|
||||
'VCLibrarianTool': {
|
||||
'AdditionalOptions': ['/ltcg', '/expectedoutputsize:120000000'],
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
'LinkIncremental': '1',
|
||||
'OptimizeReferences': '2',
|
||||
'EnableCOMDATFolding': '2',
|
||||
'OptimizeForWindows98': '1',
|
||||
'LinkTimeCodeGeneration': '1',
|
||||
},
|
||||
},
|
||||
}],
|
||||
]
|
||||
},
|
||||
|
@ -773,7 +570,7 @@
|
|||
'-fvisibility=hidden',
|
||||
],
|
||||
'cflags_cc': [
|
||||
'-fno-rtti',
|
||||
'-frtti',
|
||||
'-fno-threadsafe-statics',
|
||||
# Make inline functions have hidden visiblity by default.
|
||||
# Surprisingly, not covered by -fvisibility=hidden.
|
||||
|
@ -821,12 +618,6 @@
|
|||
'$_LIBDIRFLAGS', '$LDMODULEFLAGS', '$SOURCES',
|
||||
'-Wl,--start-group', '$_LIBFLAGS', '-Wl,--end-group']],
|
||||
'IMPLICIT_COMMAND_DEPENDENCIES': 0,
|
||||
# -rpath is only used when building with shared libraries.
|
||||
'conditions': [
|
||||
[ 'component=="shared_library"', {
|
||||
'RPATH': '$LIB_DIR',
|
||||
}],
|
||||
],
|
||||
},
|
||||
'scons_import_variables': [
|
||||
'AS',
|
||||
|
@ -932,22 +723,13 @@
|
|||
# compiler optimized the code, since the value is always kept
|
||||
# in its specified precision.
|
||||
'conditions': [
|
||||
['branding=="Chromium" and disable_sse2==0', {
|
||||
['disable_sse2==0', {
|
||||
'cflags': [
|
||||
'-march=pentium4',
|
||||
'-msse2',
|
||||
'-mfpmath=sse',
|
||||
],
|
||||
}],
|
||||
# ChromeOS targets Pinetrail, which is sse3, but most of the
|
||||
# benefit comes from sse2 so this setting allows ChromeOS
|
||||
# to build on other CPUs. In the future -march=atom would help
|
||||
# but requires a newer compiler.
|
||||
['chromeos==1 and disable_sse2==0', {
|
||||
'cflags': [
|
||||
'-msse2',
|
||||
],
|
||||
}],
|
||||
],
|
||||
# -mmmx allows mmintrin.h to be used for mmx intrinsics.
|
||||
# video playback is mmx and sse2 optimized.
|
||||
|
@ -980,7 +762,7 @@
|
|||
'-Wa,-mimplicit-it=thumb',
|
||||
]
|
||||
}],
|
||||
['armv7==1', {
|
||||
['arm_version==7', {
|
||||
'cflags': [
|
||||
'-march=armv7-a',
|
||||
'-mtune=cortex-a8',
|
||||
|
@ -1019,24 +801,6 @@
|
|||
'-fno-strict-aliasing',
|
||||
],
|
||||
}],
|
||||
['linux_breakpad==1', {
|
||||
'cflags': [ '-gstabs' ],
|
||||
'defines': ['USE_LINUX_BREAKPAD'],
|
||||
}],
|
||||
['linux_use_seccomp_sandbox==1 and buildtype!="Official"', {
|
||||
'defines': ['USE_SECCOMP_SANDBOX'],
|
||||
}],
|
||||
['library=="shared_library"', {
|
||||
# When building with shared libraries, remove the visiblity-hiding
|
||||
# flag.
|
||||
'cflags!': [ '-fvisibility=hidden' ],
|
||||
'conditions': [
|
||||
['target_arch=="x64" or target_arch=="arm"', {
|
||||
# Shared libraries need -fPIC on x86-64 and arm
|
||||
'cflags': ['-fPIC']
|
||||
}]
|
||||
],
|
||||
}],
|
||||
['linux_use_heapchecker==1', {
|
||||
'variables': {'linux_use_tcmalloc%': 1},
|
||||
}],
|
||||
|
@ -1078,7 +842,7 @@
|
|||
'GCC_DYNAMIC_NO_PIC': 'NO', # No -mdynamic-no-pic
|
||||
# (Equivalent to -fPIC)
|
||||
'GCC_ENABLE_CPP_EXCEPTIONS': 'NO', # -fno-exceptions
|
||||
'GCC_ENABLE_CPP_RTTI': 'NO', # -fno-rtti
|
||||
'GCC_ENABLE_CPP_RTTI': 'YES', # -frtti
|
||||
'GCC_ENABLE_PASCAL_STRINGS': 'NO', # No -mpascal-strings
|
||||
# GCC_INLINES_ARE_PRIVATE_EXTERN maps to -fvisibility-inlines-hidden
|
||||
'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES',
|
||||
|
@ -1106,51 +870,6 @@
|
|||
['_mac_bundle', {
|
||||
'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-ObjC']},
|
||||
}],
|
||||
['_type=="executable" or _type=="shared_library"', {
|
||||
'target_conditions': [
|
||||
['mac_real_dsym == 1', {
|
||||
# To get a real .dSYM bundle produced by dsymutil, set the
|
||||
# debug information format to dwarf-with-dsym. Since
|
||||
# strip_from_xcode will not be used, set Xcode to do the
|
||||
# stripping as well.
|
||||
'configurations': {
|
||||
'Release_Base': {
|
||||
'xcode_settings': {
|
||||
'DEBUG_INFORMATION_FORMAT': 'dwarf-with-dsym',
|
||||
'DEPLOYMENT_POSTPROCESSING': 'YES',
|
||||
'STRIP_INSTALLED_PRODUCT': 'YES',
|
||||
'target_conditions': [
|
||||
['_type=="shared_library"', {
|
||||
# The Xcode default is to strip debugging symbols
|
||||
# only (-S). Local symbols should be stripped as
|
||||
# well, which will be handled by -x. Xcode will
|
||||
# continue to insert -S when stripping even when
|
||||
# additional flags are added with STRIPFLAGS.
|
||||
'STRIPFLAGS': '-x',
|
||||
}], # _type=="shared_library"
|
||||
], # target_conditions
|
||||
}, # xcode_settings
|
||||
}, # configuration "Release"
|
||||
}, # configurations
|
||||
}, { # mac_real_dsym != 1
|
||||
# To get a fast fake .dSYM bundle, use a post-build step to
|
||||
# produce the .dSYM and strip the executable. strip_from_xcode
|
||||
# only operates in the Release configuration.
|
||||
'postbuilds': [
|
||||
{
|
||||
'variables': {
|
||||
# Define strip_from_xcode in a variable ending in _path
|
||||
# so that gyp understands it's a path and performs proper
|
||||
# relativization during dict merging.
|
||||
'strip_from_xcode_path': 'mac/strip_from_xcode',
|
||||
},
|
||||
'postbuild_name': 'Strip If Needed',
|
||||
'action': ['<(strip_from_xcode_path)'],
|
||||
},
|
||||
], # postbuilds
|
||||
}], # mac_real_dsym
|
||||
], # target_conditions
|
||||
}], # _type=="executable" or _type=="shared_library"
|
||||
], # target_conditions
|
||||
}, # target_defaults
|
||||
}], # OS=="mac"
|
||||
|
@ -1174,7 +893,9 @@
|
|||
'$(VSInstallDir)/VC/atlmfc/include',
|
||||
],
|
||||
'msvs_cygwin_dirs': ['<(DEPTH)/third_party/cygwin'],
|
||||
'msvs_disabled_warnings': [4396, 4503, 4819],
|
||||
'msvs_disabled_warnings': [
|
||||
4100, 4127, 4396, 4503, 4512, 4819, 4995, 4702
|
||||
],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'MinimalRebuild': 'false',
|
||||
|
@ -1182,7 +903,7 @@
|
|||
'BufferSecurityCheck': 'true',
|
||||
'EnableFunctionLevelLinking': 'true',
|
||||
'RuntimeTypeInfo': 'false',
|
||||
'WarningLevel': '3',
|
||||
'WarningLevel': '4',
|
||||
'WarnAsError': 'true',
|
||||
'DebugInformationFormat': '3',
|
||||
'conditions': [
|
||||
|
@ -1322,9 +1043,3 @@
|
|||
'SYMROOT': '<(DEPTH)/xcodebuild',
|
||||
},
|
||||
}
|
||||
|
||||
# Local Variables:
|
||||
# tab-width:2
|
||||
# indent-tabs-mode:nil
|
||||
# End:
|
||||
# vim: set expandtab tabstop=2 shiftwidth=2:
|
|
@ -0,0 +1,57 @@
|
|||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
{
|
||||
'target_conditions': [
|
||||
['OS!="win"', {
|
||||
'sources/': [
|
||||
['exclude', '(^|/)windows/'],
|
||||
],
|
||||
}],
|
||||
['OS!="linux"', {
|
||||
'sources/': [
|
||||
['exclude', '(^|/)linux/'],
|
||||
],
|
||||
}],
|
||||
['OS!="mac"', {
|
||||
'sources/': [
|
||||
['exclude', '(^|/)mac/'],
|
||||
],
|
||||
}],
|
||||
['OS!="android"', {
|
||||
'sources/': [
|
||||
['exclude', '(^|/)android/'],
|
||||
],
|
||||
}],
|
||||
['OS!="solaris"', {
|
||||
'sources/': [
|
||||
['exclude', '(^|/)solaris/'],
|
||||
],
|
||||
}],
|
||||
],
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
breakpad_root = os.path.abspath(os.path.join(script_dir, os.pardir))
|
||||
|
||||
sys.path.insert(0, os.path.join(breakpad_root, 'tools', 'gyp', 'pylib'))
|
||||
import gyp
|
||||
|
||||
def run_gyp(args):
|
||||
rc = gyp.main(args)
|
||||
if rc != 0:
|
||||
print 'Error running GYP'
|
||||
sys.exit(rc)
|
||||
|
||||
|
||||
def main():
|
||||
args = sys.argv[1:]
|
||||
args.append(os.path.join(script_dir, 'all.gyp'))
|
||||
|
||||
args.append('-I')
|
||||
args.append(os.path.join(breakpad_root, 'build', 'common.gypi'))
|
||||
|
||||
args.extend(['-D', 'gyp_output_dir=out'])
|
||||
|
||||
# Set the GYP DEPTH variable to the root of the project.
|
||||
args.append('--depth=' + os.path.relpath(breakpad_root))
|
||||
|
||||
print 'Updating projects from gyp files...'
|
||||
sys.stdout.flush()
|
||||
|
||||
run_gyp(args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
|
@ -0,0 +1,90 @@
|
|||
# Copyright 2014 Google Inc. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'gtest',
|
||||
'type': 'static_library',
|
||||
'sources': [
|
||||
'../testing/gtest/src/gtest-all.cc',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../testing/gtest',
|
||||
'../testing/gtest/include',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'../testing/gtest/include',
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
'target_name': 'gtest_main',
|
||||
'type': 'static_library',
|
||||
'dependencies': [
|
||||
'gtest',
|
||||
],
|
||||
'sources': [
|
||||
'gtest/src/gtest_main.cc',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'gmock',
|
||||
'type': 'static_library',
|
||||
'dependencies': [
|
||||
'gtest',
|
||||
],
|
||||
'sources': [
|
||||
'../testing/src/gmock-all.cc',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../testing',
|
||||
'../testing/include',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'../testing/include',
|
||||
],
|
||||
},
|
||||
'export_dependent_settings': [
|
||||
'gtest',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'gmock_main',
|
||||
'type': 'static_library',
|
||||
'dependencies': [
|
||||
'gmock',
|
||||
],
|
||||
'sources': [
|
||||
'../testing/src/gmock_main.cc',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
|
@ -62,6 +62,7 @@
|
|||
#define BREAKPAD_EMAIL "BreakpadEmail"
|
||||
#define BREAKPAD_SERVER_TYPE "BreakpadServerType"
|
||||
#define BREAKPAD_SERVER_PARAMETER_DICT "BreakpadServerParameters"
|
||||
#define BREAKPAD_IN_PROCESS "BreakpadInProcess"
|
||||
|
||||
// The keys below are NOT user supplied, and are used internally.
|
||||
#define BREAKPAD_PROCESS_START_TIME "BreakpadProcStartTime"
|
||||
|
|
|
@ -196,12 +196,39 @@ void BreakpadRemoveUploadParameter(BreakpadRef ref, NSString *key);
|
|||
|
||||
// Method to handle uploading data to the server
|
||||
|
||||
// Returns if there is some report to send to the server.
|
||||
bool BreakpadHasCrashReportToUpload(BreakpadRef ref);
|
||||
// Returns the number of crash reports waiting to send to the server.
|
||||
int BreakpadGetCrashReportCount(BreakpadRef ref);
|
||||
|
||||
// Returns the next upload configuration. The report file is deleted.
|
||||
NSDictionary *BreakpadGetNextReportConfiguration(BreakpadRef ref);
|
||||
|
||||
// Upload next report to the server.
|
||||
void BreakpadUploadNextReport(BreakpadRef ref);
|
||||
|
||||
// Upload next report to the server.
|
||||
// |server_parameters| is additional server parameters to send.
|
||||
void BreakpadUploadNextReportWithParameters(BreakpadRef ref,
|
||||
NSDictionary *server_parameters);
|
||||
|
||||
// Upload a report to the server.
|
||||
// |server_parameters| is additional server parameters to send.
|
||||
// |configuration| is the configuration of the breakpad report to send.
|
||||
void BreakpadUploadReportWithParametersAndConfiguration(
|
||||
BreakpadRef ref,
|
||||
NSDictionary *server_parameters,
|
||||
NSDictionary *configuration);
|
||||
|
||||
// Handles the network response of a breakpad upload. This function is needed if
|
||||
// the actual upload is done by the Breakpad client.
|
||||
// |configuration| is the configuration of the upload. It must contain the same
|
||||
// fields as the configuration passed to
|
||||
// BreakpadUploadReportWithParametersAndConfiguration.
|
||||
// |data| and |error| contain the network response.
|
||||
void BreakpadHandleNetworkResponse(BreakpadRef ref,
|
||||
NSDictionary *configuration,
|
||||
NSData *data,
|
||||
NSError *error);
|
||||
|
||||
// Upload a file to the server. |data| is the content of the file to sent.
|
||||
// |server_parameters| is additional server parameters to send.
|
||||
void BreakpadUploadData(BreakpadRef ref, NSData *data, NSString *name,
|
||||
|
|
|
@ -27,33 +27,25 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
#if VERBOSE
|
||||
static bool gDebugLog = true;
|
||||
#else
|
||||
static bool gDebugLog = false;
|
||||
#endif
|
||||
|
||||
#define DEBUGLOG if (gDebugLog) fprintf
|
||||
#define IGNORE_DEBUGGER "BREAKPAD_IGNORE_DEBUGGER"
|
||||
|
||||
#import "client/ios/Breakpad.h"
|
||||
|
||||
#include <assert.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#import "client/ios/handler/ios_exception_minidump_generator.h"
|
||||
#import "client/mac/crash_generation/ConfigFile.h"
|
||||
#import "client/mac/handler/exception_handler.h"
|
||||
#import "client/mac/handler/minidump_generator.h"
|
||||
#import "client/mac/sender/uploader.h"
|
||||
#import "common/mac/SimpleStringDictionary.h"
|
||||
#import "client/ios/handler/ios_exception_minidump_generator.h"
|
||||
#import "client/mac/handler/protected_memory_allocator.h"
|
||||
#import "common/simple_string_dictionary.h"
|
||||
|
||||
#ifndef __EXCEPTIONS
|
||||
#if !defined(__EXCEPTIONS) || (__clang__ && !__has_feature(cxx_exceptions))
|
||||
// This file uses C++ try/catch (but shouldn't). Duplicate the macros from
|
||||
// <c++/4.2.1/exception_defines.h> allowing this file to work properly with
|
||||
// exceptions disabled even when other C++ libraries are used. #undef the try
|
||||
|
@ -67,9 +59,7 @@
|
|||
|
||||
using google_breakpad::ConfigFile;
|
||||
using google_breakpad::EnsureDirectoryPathExists;
|
||||
using google_breakpad::KeyValueEntry;
|
||||
using google_breakpad::SimpleStringDictionary;
|
||||
using google_breakpad::SimpleStringDictionaryIterator;
|
||||
|
||||
//=============================================================================
|
||||
// We want any memory allocations which are used by breakpad during the
|
||||
|
@ -102,36 +92,32 @@ pthread_mutex_t gDictionaryMutex;
|
|||
// ProtectedMemoryLocker will unprotect this block after taking the lock.
|
||||
// Its destructor will first re-protect the memory then release the lock.
|
||||
class ProtectedMemoryLocker {
|
||||
public:
|
||||
// allocator may be NULL, in which case no Protect() or Unprotect() calls
|
||||
// will be made, but a lock will still be taken
|
||||
public:
|
||||
ProtectedMemoryLocker(pthread_mutex_t *mutex,
|
||||
ProtectedMemoryAllocator *allocator)
|
||||
: mutex_(mutex), allocator_(allocator) {
|
||||
: mutex_(mutex),
|
||||
allocator_(allocator) {
|
||||
// Lock the mutex
|
||||
assert(pthread_mutex_lock(mutex_) == 0);
|
||||
__attribute__((unused)) int rv = pthread_mutex_lock(mutex_);
|
||||
assert(rv == 0);
|
||||
|
||||
// Unprotect the memory
|
||||
if (allocator_ ) {
|
||||
allocator_->Unprotect();
|
||||
}
|
||||
allocator_->Unprotect();
|
||||
}
|
||||
|
||||
~ProtectedMemoryLocker() {
|
||||
// First protect the memory
|
||||
if (allocator_) {
|
||||
allocator_->Protect();
|
||||
}
|
||||
allocator_->Protect();
|
||||
|
||||
// Then unlock the mutex
|
||||
assert(pthread_mutex_unlock(mutex_) == 0);
|
||||
__attribute__((unused)) int rv = pthread_mutex_unlock(mutex_);
|
||||
assert(rv == 0);
|
||||
};
|
||||
|
||||
private:
|
||||
// Keep anybody from ever creating one of these things not on the stack.
|
||||
ProtectedMemoryLocker() { }
|
||||
private:
|
||||
ProtectedMemoryLocker();
|
||||
ProtectedMemoryLocker(const ProtectedMemoryLocker&);
|
||||
ProtectedMemoryLocker & operator=(ProtectedMemoryLocker&);
|
||||
ProtectedMemoryLocker& operator=(const ProtectedMemoryLocker&);
|
||||
|
||||
pthread_mutex_t *mutex_;
|
||||
ProtectedMemoryAllocator *allocator_;
|
||||
|
@ -164,10 +150,17 @@ class Breakpad {
|
|||
void SetKeyValue(NSString *key, NSString *value);
|
||||
NSString *KeyValue(NSString *key);
|
||||
void RemoveKeyValue(NSString *key);
|
||||
NSArray *CrashReportsToUpload();
|
||||
NSString *NextCrashReportToUpload();
|
||||
void UploadNextReport();
|
||||
NSDictionary *NextCrashReportConfiguration();
|
||||
void UploadNextReport(NSDictionary *server_parameters);
|
||||
void UploadReportWithConfiguration(NSDictionary *configuration,
|
||||
NSDictionary *server_parameters);
|
||||
void UploadData(NSData *data, NSString *name,
|
||||
NSDictionary *server_parameters);
|
||||
void HandleNetworkResponse(NSDictionary *configuration,
|
||||
NSData *data,
|
||||
NSError *error);
|
||||
NSDictionary *GenerateReport(NSDictionary *server_parameters);
|
||||
|
||||
private:
|
||||
|
@ -271,6 +264,7 @@ void Breakpad::UncaughtExceptionHandler(NSException *exception) {
|
|||
if (current_breakpad_) {
|
||||
current_breakpad_->HandleUncaughtException(exception);
|
||||
}
|
||||
BreakpadRelease(current_breakpad_);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -290,7 +284,6 @@ bool Breakpad::Initialize(NSDictionary *parameters) {
|
|||
|
||||
// Check for debugger
|
||||
if (IsDebuggerActive()) {
|
||||
DEBUGLOG(stderr, "Debugger is active: Not installing handler\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -329,8 +322,11 @@ bool Breakpad::ExtractParameters(NSDictionary *parameters) {
|
|||
NSString *urlStr = [parameters objectForKey:@BREAKPAD_URL];
|
||||
NSString *vendor =
|
||||
[parameters objectForKey:@BREAKPAD_VENDOR];
|
||||
NSString *dumpSubdirectory =
|
||||
[parameters objectForKey:@BREAKPAD_DUMP_DIRECTORY];
|
||||
// We check both parameters and the environment variable here.
|
||||
char *envVarDumpSubdirectory = getenv(BREAKPAD_DUMP_DIRECTORY);
|
||||
NSString *dumpSubdirectory = envVarDumpSubdirectory ?
|
||||
[NSString stringWithUTF8String:envVarDumpSubdirectory] :
|
||||
[parameters objectForKey:@BREAKPAD_DUMP_DIRECTORY];
|
||||
|
||||
NSDictionary *serverParameters =
|
||||
[parameters objectForKey:@BREAKPAD_SERVER_PARAMETER_DICT];
|
||||
|
@ -345,7 +341,7 @@ bool Breakpad::ExtractParameters(NSDictionary *parameters) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!version)
|
||||
if (!version.length) // Default nil or empty string to CFBundleVersion
|
||||
version = [parameters objectForKey:@"CFBundleVersion"];
|
||||
|
||||
if (!vendor) {
|
||||
|
@ -366,17 +362,14 @@ bool Breakpad::ExtractParameters(NSDictionary *parameters) {
|
|||
|
||||
// The product, version, and URL are required values.
|
||||
if (![product length]) {
|
||||
DEBUGLOG(stderr, "Missing required product key.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (![version length]) {
|
||||
DEBUGLOG(stderr, "Missing required version key.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (![urlStr length]) {
|
||||
DEBUGLOG(stderr, "Missing required URL key.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -439,7 +432,7 @@ void Breakpad::RemoveKeyValue(NSString *key) {
|
|||
}
|
||||
|
||||
//=============================================================================
|
||||
NSString *Breakpad::NextCrashReportToUpload() {
|
||||
NSArray *Breakpad::CrashReportsToUpload() {
|
||||
NSString *directory = KeyValue(@BREAKPAD_DUMP_DIRECTORY);
|
||||
if (!directory)
|
||||
return nil;
|
||||
|
@ -447,20 +440,53 @@ NSString *Breakpad::NextCrashReportToUpload() {
|
|||
contentsOfDirectoryAtPath:directory error:nil];
|
||||
NSArray *configs = [dirContents filteredArrayUsingPredicate:[NSPredicate
|
||||
predicateWithFormat:@"self BEGINSWITH 'Config-'"]];
|
||||
NSString *config = [configs lastObject];
|
||||
return configs;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
NSString *Breakpad::NextCrashReportToUpload() {
|
||||
NSString *directory = KeyValue(@BREAKPAD_DUMP_DIRECTORY);
|
||||
if (!directory)
|
||||
return nil;
|
||||
NSString *config = [CrashReportsToUpload() lastObject];
|
||||
if (!config)
|
||||
return nil;
|
||||
return [NSString stringWithFormat:@"%@/%@", directory, config];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
void Breakpad::UploadNextReport() {
|
||||
NSString *configFile = NextCrashReportToUpload();
|
||||
if (configFile) {
|
||||
Uploader *uploader = [[[Uploader alloc]
|
||||
initWithConfigFile:[configFile UTF8String]] autorelease];
|
||||
if (uploader)
|
||||
[uploader report];
|
||||
NSDictionary *Breakpad::NextCrashReportConfiguration() {
|
||||
return [Uploader readConfigurationDataFromFile:NextCrashReportToUpload()];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
void Breakpad::HandleNetworkResponse(NSDictionary *configuration,
|
||||
NSData *data,
|
||||
NSError *error) {
|
||||
Uploader *uploader = [[[Uploader alloc]
|
||||
initWithConfig:configuration] autorelease];
|
||||
[uploader handleNetworkResponse:data withError:error];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
void Breakpad::UploadReportWithConfiguration(NSDictionary *configuration,
|
||||
NSDictionary *server_parameters) {
|
||||
Uploader *uploader = [[[Uploader alloc]
|
||||
initWithConfig:configuration] autorelease];
|
||||
if (!uploader)
|
||||
return;
|
||||
for (NSString *key in server_parameters) {
|
||||
[uploader addServerParameter:[server_parameters objectForKey:key]
|
||||
forKey:key];
|
||||
}
|
||||
[uploader report];
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
void Breakpad::UploadNextReport(NSDictionary *server_parameters) {
|
||||
NSDictionary *configuration = NextCrashReportConfiguration();
|
||||
if (configuration) {
|
||||
return UploadReportWithConfiguration(configuration, server_parameters);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -469,10 +495,10 @@ void Breakpad::UploadData(NSData *data, NSString *name,
|
|||
NSDictionary *server_parameters) {
|
||||
NSMutableDictionary *config = [NSMutableDictionary dictionary];
|
||||
|
||||
SimpleStringDictionaryIterator it(*config_params_);
|
||||
while (const KeyValueEntry *next = it.Next()) {
|
||||
[config setValue:[NSString stringWithUTF8String:next->GetValue()]
|
||||
forKey:[NSString stringWithUTF8String:next->GetKey()]];
|
||||
SimpleStringDictionary::Iterator it(*config_params_);
|
||||
while (const SimpleStringDictionary::Entry *next = it.Next()) {
|
||||
[config setValue:[NSString stringWithUTF8String:next->value]
|
||||
forKey:[NSString stringWithUTF8String:next->key]];
|
||||
}
|
||||
|
||||
Uploader *uploader =
|
||||
|
@ -509,8 +535,7 @@ NSDictionary *Breakpad::GenerateReport(NSDictionary *server_parameters) {
|
|||
|
||||
// Handle results.
|
||||
NSMutableDictionary *result = [NSMutableDictionary dictionary];
|
||||
NSString *dumpFullPath = [dumpDirAsNSString stringByAppendingPathComponent:
|
||||
[NSString stringWithUTF8String:dumpFilename.c_str()]];
|
||||
NSString *dumpFullPath = [NSString stringWithUTF8String:dumpFilename.c_str()];
|
||||
[result setValue:dumpFullPath
|
||||
forKey:@BREAKPAD_OUTPUT_DUMP_FILE];
|
||||
[result setValue:[NSString stringWithUTF8String:config_file.GetFilePath()]
|
||||
|
@ -521,8 +546,6 @@ NSDictionary *Breakpad::GenerateReport(NSDictionary *server_parameters) {
|
|||
//=============================================================================
|
||||
bool Breakpad::HandleMinidump(const char *dump_dir,
|
||||
const char *minidump_id) {
|
||||
DEBUGLOG(stderr, "Breakpad: a minidump has been created.\n");
|
||||
|
||||
config_file_.WriteFile(dump_dir,
|
||||
config_params_,
|
||||
dump_dir,
|
||||
|
@ -778,31 +801,84 @@ void BreakpadRemoveKeyValue(BreakpadRef ref, NSString *key) {
|
|||
}
|
||||
|
||||
//=============================================================================
|
||||
bool BreakpadHasCrashReportToUpload(BreakpadRef ref) {
|
||||
int BreakpadGetCrashReportCount(BreakpadRef ref) {
|
||||
try {
|
||||
// Not called at exception time
|
||||
Breakpad *breakpad = (Breakpad *)ref;
|
||||
|
||||
if (breakpad) {
|
||||
return breakpad->NextCrashReportToUpload() != 0;
|
||||
return static_cast<int>([breakpad->CrashReportsToUpload() count]);
|
||||
}
|
||||
} catch(...) { // don't let exceptions leave this C API
|
||||
fprintf(stderr, "BreakpadHasCrashReportToUpload() : error\n");
|
||||
fprintf(stderr, "BreakpadGetCrashReportCount() : error\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
void BreakpadUploadNextReport(BreakpadRef ref) {
|
||||
BreakpadUploadNextReportWithParameters(ref, nil);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
NSDictionary *BreakpadGetNextReportConfiguration(BreakpadRef ref) {
|
||||
try {
|
||||
Breakpad *breakpad = (Breakpad *)ref;
|
||||
if (breakpad)
|
||||
return breakpad->NextCrashReportConfiguration();
|
||||
} catch(...) { // don't let exceptions leave this C API
|
||||
fprintf(stderr, "BreakpadGetNextReportConfiguration() : error\n");
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
void BreakpadUploadReportWithParametersAndConfiguration(
|
||||
BreakpadRef ref,
|
||||
NSDictionary *server_parameters,
|
||||
NSDictionary *configuration) {
|
||||
try {
|
||||
Breakpad *breakpad = (Breakpad *)ref;
|
||||
if (!breakpad || !configuration)
|
||||
return;
|
||||
breakpad->UploadReportWithConfiguration(configuration, server_parameters);
|
||||
} catch(...) { // don't let exceptions leave this C API
|
||||
fprintf(stderr,
|
||||
"BreakpadUploadReportWithParametersAndConfiguration() : error\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
void BreakpadUploadNextReportWithParameters(BreakpadRef ref,
|
||||
NSDictionary *server_parameters) {
|
||||
try {
|
||||
Breakpad *breakpad = (Breakpad *)ref;
|
||||
if (!breakpad)
|
||||
return;
|
||||
NSDictionary *configuration = breakpad->NextCrashReportConfiguration();
|
||||
if (!configuration)
|
||||
return;
|
||||
return BreakpadUploadReportWithParametersAndConfiguration(ref,
|
||||
server_parameters,
|
||||
configuration);
|
||||
} catch(...) { // don't let exceptions leave this C API
|
||||
fprintf(stderr, "BreakpadUploadNextReportWithParameters() : error\n");
|
||||
}
|
||||
}
|
||||
|
||||
void BreakpadHandleNetworkResponse(BreakpadRef ref,
|
||||
NSDictionary *configuration,
|
||||
NSData *data,
|
||||
NSError *error) {
|
||||
try {
|
||||
// Not called at exception time
|
||||
Breakpad *breakpad = (Breakpad *)ref;
|
||||
if (breakpad && configuration)
|
||||
breakpad->HandleNetworkResponse(configuration,data, error);
|
||||
|
||||
if (breakpad) {
|
||||
breakpad->UploadNextReport();
|
||||
}
|
||||
} catch(...) { // don't let exceptions leave this C API
|
||||
fprintf(stderr, "BreakpadUploadNextReport() : error\n");
|
||||
fprintf(stderr, "BreakpadHandleNetworkResponse() : error\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
14569321182CE29F0029C465 /* ucontext_compat.h in Headers */ = {isa = PBXBuildFile; fileRef = 14569320182CE29F0029C465 /* ucontext_compat.h */; };
|
||||
14569323182CE2C10029C465 /* mach_vm_compat.h in Headers */ = {isa = PBXBuildFile; fileRef = 14569322182CE2C10029C465 /* mach_vm_compat.h */; };
|
||||
16BFA67014E195E9009704F8 /* ios_exception_minidump_generator.h in Headers */ = {isa = PBXBuildFile; fileRef = 16BFA66E14E195E9009704F8 /* ios_exception_minidump_generator.h */; };
|
||||
16BFA67214E1965A009704F8 /* ios_exception_minidump_generator.mm in Sources */ = {isa = PBXBuildFile; fileRef = 16BFA67114E1965A009704F8 /* ios_exception_minidump_generator.mm */; };
|
||||
16C7CCCB147D4A4300776EAD /* BreakpadDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 16C7C968147D4A4200776EAD /* BreakpadDefines.h */; };
|
||||
|
@ -29,15 +31,12 @@
|
|||
16C7CE18147D4A4300776EAD /* minidump_file_writer-inl.h in Headers */ = {isa = PBXBuildFile; fileRef = 16C7CC04147D4A4300776EAD /* minidump_file_writer-inl.h */; };
|
||||
16C7CE19147D4A4300776EAD /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = 16C7CC05147D4A4300776EAD /* minidump_file_writer.cc */; };
|
||||
16C7CE1A147D4A4300776EAD /* minidump_file_writer.h in Headers */ = {isa = PBXBuildFile; fileRef = 16C7CC06147D4A4300776EAD /* minidump_file_writer.h */; };
|
||||
16C7CE1B147D4A4300776EAD /* minidump_file_writer_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 16C7CC07147D4A4300776EAD /* minidump_file_writer_unittest.cc */; };
|
||||
16C7CE40147D4A4300776EAD /* convert_UTF.c in Sources */ = {isa = PBXBuildFile; fileRef = 16C7CC4A147D4A4300776EAD /* convert_UTF.c */; };
|
||||
16C7CE41147D4A4300776EAD /* convert_UTF.h in Headers */ = {isa = PBXBuildFile; fileRef = 16C7CC4B147D4A4300776EAD /* convert_UTF.h */; };
|
||||
16C7CE78147D4A4300776EAD /* GTMLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 16C7CC88147D4A4300776EAD /* GTMLogger.h */; };
|
||||
16C7CE79147D4A4300776EAD /* GTMLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 16C7CC89147D4A4300776EAD /* GTMLogger.m */; };
|
||||
16C7CE7A147D4A4300776EAD /* HTTPMultipartUpload.h in Headers */ = {isa = PBXBuildFile; fileRef = 16C7CC8A147D4A4300776EAD /* HTTPMultipartUpload.h */; };
|
||||
16C7CE7B147D4A4300776EAD /* HTTPMultipartUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = 16C7CC8B147D4A4300776EAD /* HTTPMultipartUpload.m */; };
|
||||
16C7CE7E147D4A4300776EAD /* SimpleStringDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 16C7CC8E147D4A4300776EAD /* SimpleStringDictionary.h */; };
|
||||
16C7CE7F147D4A4300776EAD /* SimpleStringDictionary.mm in Sources */ = {isa = PBXBuildFile; fileRef = 16C7CC8F147D4A4300776EAD /* SimpleStringDictionary.mm */; };
|
||||
16C7CE83147D4A4300776EAD /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 16C7CC93147D4A4300776EAD /* file_id.cc */; };
|
||||
16C7CE84147D4A4300776EAD /* file_id.h in Headers */ = {isa = PBXBuildFile; fileRef = 16C7CC94147D4A4300776EAD /* file_id.h */; };
|
||||
16C7CE85147D4A4300776EAD /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 16C7CC95147D4A4300776EAD /* macho_id.cc */; };
|
||||
|
@ -54,11 +53,15 @@
|
|||
16C7CEA8147D4A4300776EAD /* string_conversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 16C7CCBA147D4A4300776EAD /* string_conversion.h */; };
|
||||
16C92FAD150DF8330053D7BA /* BreakpadController.h in Headers */ = {isa = PBXBuildFile; fileRef = 16C92FAB150DF8330053D7BA /* BreakpadController.h */; };
|
||||
16C92FAE150DF8330053D7BA /* BreakpadController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 16C92FAC150DF8330053D7BA /* BreakpadController.mm */; };
|
||||
1EEEB60F1720821900F7E689 /* simple_string_dictionary.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1EEEB60C1720821900F7E689 /* simple_string_dictionary.cc */; };
|
||||
1EEEB6101720821900F7E689 /* simple_string_dictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EEEB60D1720821900F7E689 /* simple_string_dictionary.h */; };
|
||||
AA747D9F0F9514B9006C5449 /* Breakpad_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = AA747D9E0F9514B9006C5449 /* Breakpad_Prefix.pch */; };
|
||||
AACBBE4A0F95108600F1A2B1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AACBBE490F95108600F1A2B1 /* Foundation.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
14569320182CE29F0029C465 /* ucontext_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ucontext_compat.h; sourceTree = "<group>"; };
|
||||
14569322182CE2C10029C465 /* mach_vm_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mach_vm_compat.h; sourceTree = "<group>"; };
|
||||
16BFA66E14E195E9009704F8 /* ios_exception_minidump_generator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ios_exception_minidump_generator.h; sourceTree = "<group>"; };
|
||||
16BFA67114E1965A009704F8 /* ios_exception_minidump_generator.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ios_exception_minidump_generator.mm; sourceTree = "<group>"; };
|
||||
16C7C968147D4A4200776EAD /* BreakpadDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BreakpadDefines.h; sourceTree = "<group>"; };
|
||||
|
@ -88,8 +91,6 @@
|
|||
16C7CC89147D4A4300776EAD /* GTMLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTMLogger.m; sourceTree = "<group>"; };
|
||||
16C7CC8A147D4A4300776EAD /* HTTPMultipartUpload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTTPMultipartUpload.h; sourceTree = "<group>"; };
|
||||
16C7CC8B147D4A4300776EAD /* HTTPMultipartUpload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTTPMultipartUpload.m; sourceTree = "<group>"; };
|
||||
16C7CC8E147D4A4300776EAD /* SimpleStringDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleStringDictionary.h; sourceTree = "<group>"; };
|
||||
16C7CC8F147D4A4300776EAD /* SimpleStringDictionary.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SimpleStringDictionary.mm; sourceTree = "<group>"; };
|
||||
16C7CC93147D4A4300776EAD /* file_id.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file_id.cc; sourceTree = "<group>"; };
|
||||
16C7CC94147D4A4300776EAD /* file_id.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file_id.h; sourceTree = "<group>"; };
|
||||
16C7CC95147D4A4300776EAD /* macho_id.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = macho_id.cc; sourceTree = "<group>"; };
|
||||
|
@ -106,6 +107,8 @@
|
|||
16C7CCBA147D4A4300776EAD /* string_conversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string_conversion.h; sourceTree = "<group>"; };
|
||||
16C92FAB150DF8330053D7BA /* BreakpadController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BreakpadController.h; sourceTree = "<group>"; };
|
||||
16C92FAC150DF8330053D7BA /* BreakpadController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BreakpadController.mm; sourceTree = "<group>"; };
|
||||
1EEEB60C1720821900F7E689 /* simple_string_dictionary.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = simple_string_dictionary.cc; sourceTree = "<group>"; };
|
||||
1EEEB60D1720821900F7E689 /* simple_string_dictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simple_string_dictionary.h; sourceTree = "<group>"; };
|
||||
AA747D9E0F9514B9006C5449 /* Breakpad_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Breakpad_Prefix.pch; sourceTree = SOURCE_ROOT; };
|
||||
AACBBE490F95108600F1A2B1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
D2AAC07E0554694100DB518D /* libBreakpad.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libBreakpad.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
@ -239,10 +242,12 @@
|
|||
16C7CBB0147D4A4300776EAD /* dynamic_images.h */,
|
||||
16C7CBB1147D4A4300776EAD /* exception_handler.cc */,
|
||||
16C7CBB2147D4A4300776EAD /* exception_handler.h */,
|
||||
14569322182CE2C10029C465 /* mach_vm_compat.h */,
|
||||
16C7CBB4147D4A4300776EAD /* minidump_generator.cc */,
|
||||
16C7CBB5147D4A4300776EAD /* minidump_generator.h */,
|
||||
16C7CBBC147D4A4300776EAD /* protected_memory_allocator.cc */,
|
||||
16C7CBBD147D4A4300776EAD /* protected_memory_allocator.h */,
|
||||
14569320182CE29F0029C465 /* ucontext_compat.h */,
|
||||
);
|
||||
path = handler;
|
||||
sourceTree = "<group>";
|
||||
|
@ -259,6 +264,8 @@
|
|||
16C7CC47147D4A4300776EAD /* common */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1EEEB60C1720821900F7E689 /* simple_string_dictionary.cc */,
|
||||
1EEEB60D1720821900F7E689 /* simple_string_dictionary.h */,
|
||||
16C7CC4A147D4A4300776EAD /* convert_UTF.c */,
|
||||
16C7CC4B147D4A4300776EAD /* convert_UTF.h */,
|
||||
16C7CC82147D4A4300776EAD /* mac */,
|
||||
|
@ -278,8 +285,6 @@
|
|||
16C7CC89147D4A4300776EAD /* GTMLogger.m */,
|
||||
16C7CC8A147D4A4300776EAD /* HTTPMultipartUpload.h */,
|
||||
16C7CC8B147D4A4300776EAD /* HTTPMultipartUpload.m */,
|
||||
16C7CC8E147D4A4300776EAD /* SimpleStringDictionary.h */,
|
||||
16C7CC8F147D4A4300776EAD /* SimpleStringDictionary.mm */,
|
||||
16C7CC93147D4A4300776EAD /* file_id.cc */,
|
||||
16C7CC94147D4A4300776EAD /* file_id.h */,
|
||||
16C7CC95147D4A4300776EAD /* macho_id.cc */,
|
||||
|
@ -313,6 +318,7 @@
|
|||
16C7CCCB147D4A4300776EAD /* BreakpadDefines.h in Headers */,
|
||||
16C7CCCC147D4A4300776EAD /* Breakpad.h in Headers */,
|
||||
16C7CDE8147D4A4300776EAD /* ConfigFile.h in Headers */,
|
||||
14569321182CE29F0029C465 /* ucontext_compat.h in Headers */,
|
||||
16C7CDF6147D4A4300776EAD /* breakpad_nlist_64.h in Headers */,
|
||||
16C7CDF8147D4A4300776EAD /* dynamic_images.h in Headers */,
|
||||
16C7CDFA147D4A4300776EAD /* exception_handler.h in Headers */,
|
||||
|
@ -324,7 +330,6 @@
|
|||
16C7CE41147D4A4300776EAD /* convert_UTF.h in Headers */,
|
||||
16C7CE78147D4A4300776EAD /* GTMLogger.h in Headers */,
|
||||
16C7CE7A147D4A4300776EAD /* HTTPMultipartUpload.h in Headers */,
|
||||
16C7CE7E147D4A4300776EAD /* SimpleStringDictionary.h in Headers */,
|
||||
16C7CE84147D4A4300776EAD /* file_id.h in Headers */,
|
||||
16C7CE86147D4A4300776EAD /* macho_id.h in Headers */,
|
||||
16C7CE8B147D4A4300776EAD /* macho_utilities.h in Headers */,
|
||||
|
@ -334,6 +339,8 @@
|
|||
16C7CEA8147D4A4300776EAD /* string_conversion.h in Headers */,
|
||||
16BFA67014E195E9009704F8 /* ios_exception_minidump_generator.h in Headers */,
|
||||
16C92FAD150DF8330053D7BA /* BreakpadController.h in Headers */,
|
||||
1EEEB6101720821900F7E689 /* simple_string_dictionary.h in Headers */,
|
||||
14569323182CE2C10029C465 /* mach_vm_compat.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -362,6 +369,9 @@
|
|||
/* Begin PBXProject section */
|
||||
0867D690FE84028FC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0510;
|
||||
};
|
||||
buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "Breakpad" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
|
@ -407,11 +417,9 @@
|
|||
16C7CDFE147D4A4300776EAD /* protected_memory_allocator.cc in Sources */,
|
||||
16C7CE09147D4A4300776EAD /* uploader.mm in Sources */,
|
||||
16C7CE19147D4A4300776EAD /* minidump_file_writer.cc in Sources */,
|
||||
16C7CE1B147D4A4300776EAD /* minidump_file_writer_unittest.cc in Sources */,
|
||||
16C7CE40147D4A4300776EAD /* convert_UTF.c in Sources */,
|
||||
16C7CE79147D4A4300776EAD /* GTMLogger.m in Sources */,
|
||||
16C7CE7B147D4A4300776EAD /* HTTPMultipartUpload.m in Sources */,
|
||||
16C7CE7F147D4A4300776EAD /* SimpleStringDictionary.mm in Sources */,
|
||||
16C7CE83147D4A4300776EAD /* file_id.cc in Sources */,
|
||||
16C7CE85147D4A4300776EAD /* macho_id.cc in Sources */,
|
||||
16C7CE8A147D4A4300776EAD /* macho_utilities.cc in Sources */,
|
||||
|
@ -421,6 +429,7 @@
|
|||
16C7CEA7147D4A4300776EAD /* string_conversion.cc in Sources */,
|
||||
16BFA67214E1965A009704F8 /* ios_exception_minidump_generator.mm in Sources */,
|
||||
16C92FAE150DF8330053D7BA /* BreakpadController.mm in Sources */,
|
||||
1EEEB60F1720821900F7E689 /* simple_string_dictionary.cc in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -431,7 +440,6 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DSTROOT = /tmp/Breakpad.dst;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
|
@ -463,7 +471,6 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
DSTROOT = /tmp/Breakpad.dst;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -491,7 +498,7 @@
|
|||
1DEB922308733DC00010E9CD /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
|
||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
|
@ -509,15 +516,18 @@
|
|||
../../client/apple/Framework,
|
||||
../../common/mac,
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
SDKROOT = iphoneos;
|
||||
WARNING_CFLAGS = "-Wundef";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
1DEB922408733DC00010E9CD /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
|
||||
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
|
@ -534,8 +544,10 @@
|
|||
../../client/apple/Framework,
|
||||
../../common/mac,
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 5.0;
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
SDKROOT = iphoneos;
|
||||
WARNING_CFLAGS = "-Wundef";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
@ -62,6 +62,10 @@
|
|||
// The interval to wait between two uploads. Value is 0 if no upload must be
|
||||
// done.
|
||||
int uploadIntervalInSeconds_;
|
||||
|
||||
// The dictionary that contains additional server parameters to send when
|
||||
// uploading crash reports.
|
||||
NSDictionary* uploadTimeParameters_;
|
||||
}
|
||||
|
||||
// Singleton.
|
||||
|
@ -71,6 +75,10 @@
|
|||
// new one. Merge is done by replacing the old values by the new values.
|
||||
- (void)updateConfiguration:(NSDictionary*)configuration;
|
||||
|
||||
// Reset the controller configuration to its initial value, which is the
|
||||
// infoDictionary of the bundle of the application.
|
||||
- (void)resetConfiguration;
|
||||
|
||||
// Configure the URL to upload the report to. This must be called at least once
|
||||
// if the URL is not in the bundle information.
|
||||
- (void)setUploadingURL:(NSString*)url;
|
||||
|
@ -80,8 +88,11 @@
|
|||
// will prevent uploads.
|
||||
- (void)setUploadInterval:(int)intervalInSeconds;
|
||||
|
||||
// Specify a parameter that will be uploaded to the crash server. See
|
||||
// |BreakpadAddUploadParameter|.
|
||||
// Set additional server parameters to send when uploading crash reports.
|
||||
- (void)setParametersToAddAtUploadTime:(NSDictionary*)uploadTimeParameters;
|
||||
|
||||
// Specify an upload parameter that will be added to the crash report when a
|
||||
// crash report is generated. See |BreakpadAddUploadParameter|.
|
||||
- (void)addUploadParameter:(NSString*)value forKey:(NSString*)key;
|
||||
|
||||
// Remove a previously-added parameter from the upload parameter set. See
|
||||
|
@ -108,6 +119,23 @@
|
|||
// Check if there is currently a crash report to upload.
|
||||
- (void)hasReportToUpload:(void(^)(BOOL))callback;
|
||||
|
||||
// Get the number of crash reports waiting to upload.
|
||||
- (void)getCrashReportCount:(void(^)(int))callback;
|
||||
|
||||
// Get the next report to upload.
|
||||
// - If upload is disabled, callback will be called with (nil, -1).
|
||||
// - If a delay is to be waited before sending, callback will be called with
|
||||
// (nil, n), with n (> 0) being the number of seconds to wait.
|
||||
// - if no delay is needed, callback will be called with (0, configuration),
|
||||
// configuration being next report to upload, or nil if none is pending.
|
||||
- (void)getNextReportConfigurationOrSendDelay:
|
||||
(void(^)(NSDictionary*, int))callback;
|
||||
|
||||
// Sends synchronously the report specified by |configuration|. This method is
|
||||
// NOT thread safe and must be called from the breakpad thread.
|
||||
- (void)threadUnsafeSendReportWithConfiguration:(NSDictionary*)configuration
|
||||
withBreakpadRef:(BreakpadRef)ref;
|
||||
|
||||
@end
|
||||
|
||||
#endif // CLIENT_IOS_HANDLER_IOS_BREAKPAD_CONTROLLER_H_
|
||||
|
|
|
@ -108,12 +108,9 @@ NSString* GetPlatform() {
|
|||
self = [super init];
|
||||
if (self) {
|
||||
queue_ = dispatch_queue_create("com.google.BreakpadQueue", NULL);
|
||||
configuration_ = [[[NSBundle mainBundle] infoDictionary] mutableCopy];
|
||||
enableUploads_ = NO;
|
||||
started_ = NO;
|
||||
NSString* uploadInterval =
|
||||
[configuration_ valueForKey:@BREAKPAD_REPORT_INTERVAL];
|
||||
[self setUploadInterval:[uploadInterval intValue]];
|
||||
[self resetConfiguration];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -123,6 +120,7 @@ NSString* GetPlatform() {
|
|||
assert(!breakpadRef_);
|
||||
dispatch_release(queue_);
|
||||
[configuration_ release];
|
||||
[uploadTimeParameters_ release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
@ -157,6 +155,18 @@ NSString* GetPlatform() {
|
|||
});
|
||||
}
|
||||
|
||||
// This method must be called from the breakpad queue.
|
||||
- (void)threadUnsafeSendReportWithConfiguration:(NSDictionary*)configuration
|
||||
withBreakpadRef:(BreakpadRef)ref {
|
||||
NSAssert(started_, @"The controller must be started before "
|
||||
"threadUnsafeSendReportWithConfiguration is called");
|
||||
if (breakpadRef_) {
|
||||
BreakpadUploadReportWithParametersAndConfiguration(breakpadRef_,
|
||||
uploadTimeParameters_,
|
||||
configuration);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setUploadingEnabled:(BOOL)enabled {
|
||||
NSAssert(started_,
|
||||
@"The controller must be started before setUploadingEnabled is called");
|
||||
|
@ -187,6 +197,17 @@ NSString* GetPlatform() {
|
|||
[self setUploadInterval:[uploadInterval intValue]];
|
||||
}
|
||||
|
||||
- (void)resetConfiguration {
|
||||
NSAssert(!started_,
|
||||
@"The controller must not be started when resetConfiguration is called");
|
||||
[configuration_ autorelease];
|
||||
configuration_ = [[[NSBundle mainBundle] infoDictionary] mutableCopy];
|
||||
NSString* uploadInterval =
|
||||
[configuration_ valueForKey:@BREAKPAD_REPORT_INTERVAL];
|
||||
[self setUploadInterval:[uploadInterval intValue]];
|
||||
[self setParametersToAddAtUploadTime:nil];
|
||||
}
|
||||
|
||||
- (void)setUploadingURL:(NSString*)url {
|
||||
NSAssert(!started_,
|
||||
@"The controller must not be started when setUploadingURL is called");
|
||||
|
@ -202,6 +223,13 @@ NSString* GetPlatform() {
|
|||
uploadIntervalInSeconds_ = 0;
|
||||
}
|
||||
|
||||
- (void)setParametersToAddAtUploadTime:(NSDictionary*)uploadTimeParameters {
|
||||
NSAssert(!started_, @"The controller must not be started when "
|
||||
"setParametersToAddAtUploadTime is called");
|
||||
[uploadTimeParameters_ autorelease];
|
||||
uploadTimeParameters_ = [uploadTimeParameters copy];
|
||||
}
|
||||
|
||||
- (void)addUploadParameter:(NSString*)value forKey:(NSString*)key {
|
||||
NSAssert(started_,
|
||||
@"The controller must be started before addUploadParameter is called");
|
||||
|
@ -232,7 +260,34 @@ NSString* GetPlatform() {
|
|||
NSAssert(started_, @"The controller must be started before "
|
||||
"hasReportToUpload is called");
|
||||
dispatch_async(queue_, ^{
|
||||
callback(breakpadRef_ && BreakpadHasCrashReportToUpload(breakpadRef_));
|
||||
callback(breakpadRef_ && (BreakpadGetCrashReportCount(breakpadRef_) > 0));
|
||||
});
|
||||
}
|
||||
|
||||
- (void)getCrashReportCount:(void(^)(int))callback {
|
||||
NSAssert(started_, @"The controller must be started before "
|
||||
"getCrashReportCount is called");
|
||||
dispatch_async(queue_, ^{
|
||||
callback(breakpadRef_ ? BreakpadGetCrashReportCount(breakpadRef_) : 0);
|
||||
});
|
||||
}
|
||||
|
||||
- (void)getNextReportConfigurationOrSendDelay:
|
||||
(void(^)(NSDictionary*, int))callback {
|
||||
NSAssert(started_, @"The controller must be started before "
|
||||
"getNextReportConfigurationOrSendDelay is called");
|
||||
dispatch_async(queue_, ^{
|
||||
if (!breakpadRef_) {
|
||||
callback(nil, -1);
|
||||
return;
|
||||
}
|
||||
int delay = [self sendDelay];
|
||||
if (delay != 0) {
|
||||
callback(nil, delay);
|
||||
return;
|
||||
}
|
||||
[self reportWillBeSent];
|
||||
callback(BreakpadGetNextReportConfiguration(breakpadRef_), 0);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -264,7 +319,7 @@ NSString* GetPlatform() {
|
|||
|
||||
- (void)sendStoredCrashReports {
|
||||
dispatch_async(queue_, ^{
|
||||
if (!BreakpadHasCrashReportToUpload(breakpadRef_))
|
||||
if (BreakpadGetCrashReportCount(breakpadRef_) == 0)
|
||||
return;
|
||||
|
||||
int timeToWait = [self sendDelay];
|
||||
|
@ -276,18 +331,23 @@ NSString* GetPlatform() {
|
|||
// A report can be sent now.
|
||||
if (timeToWait == 0) {
|
||||
[self reportWillBeSent];
|
||||
BreakpadUploadNextReport(breakpadRef_);
|
||||
BreakpadUploadNextReportWithParameters(breakpadRef_,
|
||||
uploadTimeParameters_);
|
||||
|
||||
// If more reports must be sent, make sure this method is called again.
|
||||
if (BreakpadHasCrashReportToUpload(breakpadRef_))
|
||||
if (BreakpadGetCrashReportCount(breakpadRef_) > 0)
|
||||
timeToWait = uploadIntervalInSeconds_;
|
||||
}
|
||||
|
||||
// A report must be sent later.
|
||||
if (timeToWait > 0)
|
||||
[self performSelector:@selector(sendStoredCrashReports)
|
||||
withObject:nil
|
||||
afterDelay:timeToWait];
|
||||
if (timeToWait > 0) {
|
||||
// performSelector: doesn't work on queue_
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self performSelector:@selector(sendStoredCrashReports)
|
||||
withObject:nil
|
||||
afterDelay:timeToWait];
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -51,10 +51,20 @@ class IosExceptionMinidumpGenerator : public MinidumpGenerator {
|
|||
private:
|
||||
|
||||
// Get the crashing program counter from the exception.
|
||||
uint32_t GetPCFromException();
|
||||
uintptr_t GetPCFromException();
|
||||
|
||||
// Get the crashing link register from the exception.
|
||||
uintptr_t GetLRFromException();
|
||||
|
||||
// Write a virtual thread context for the crashing site.
|
||||
bool WriteCrashingContext(MDLocationDescriptor *register_location);
|
||||
// Per-CPU implementations of the above method.
|
||||
#ifdef HAS_ARM_SUPPORT
|
||||
bool WriteCrashingContextARM(MDLocationDescriptor *register_location);
|
||||
#endif
|
||||
#ifdef HAS_ARM64_SUPPORT
|
||||
bool WriteCrashingContextARM64(MDLocationDescriptor *register_location);
|
||||
#endif
|
||||
|
||||
NSArray *return_addresses_;
|
||||
};
|
||||
|
|
|
@ -29,22 +29,30 @@
|
|||
|
||||
#include "client/ios/handler/ios_exception_minidump_generator.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "google_breakpad/common/minidump_cpu_arm.h"
|
||||
#include "google_breakpad/common/minidump_cpu_arm64.h"
|
||||
#include "google_breakpad/common/minidump_exception_mac.h"
|
||||
#include "client/minidump_file_writer-inl.h"
|
||||
#include "common/scoped_ptr.h"
|
||||
|
||||
#if defined(HAS_ARM_SUPPORT) && defined(HAS_ARM64_SUPPORT)
|
||||
#error "This file should be compiled for only one architecture at a time"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32_t kExpectedFinalFp = 4;
|
||||
const uint32_t kExpectedFinalSp = 0;
|
||||
const int kExceptionType = EXC_SOFTWARE;
|
||||
const int kExceptionCode = MD_EXCEPTION_CODE_MAC_NS_EXCEPTION;
|
||||
|
||||
#ifdef HAS_ARM_SUPPORT
|
||||
// Append the given 4 bytes value to the sp position of the stack represented
|
||||
#if defined(HAS_ARM_SUPPORT) || defined(HAS_ARM64_SUPPORT)
|
||||
const uintptr_t kExpectedFinalFp = sizeof(uintptr_t);
|
||||
const uintptr_t kExpectedFinalSp = 0;
|
||||
|
||||
// Append the given value to the sp position of the stack represented
|
||||
// by memory.
|
||||
void AppendToMemory(uint8_t *memory, uint32_t sp, uint32_t data) {
|
||||
assert(sizeof(data) == 4);
|
||||
void AppendToMemory(uint8_t *memory, uintptr_t sp, uintptr_t data) {
|
||||
memcpy(memory + sp, &data, sizeof(data));
|
||||
}
|
||||
#endif
|
||||
|
@ -70,6 +78,18 @@ IosExceptionMinidumpGenerator::~IosExceptionMinidumpGenerator() {
|
|||
bool IosExceptionMinidumpGenerator::WriteCrashingContext(
|
||||
MDLocationDescriptor *register_location) {
|
||||
#ifdef HAS_ARM_SUPPORT
|
||||
return WriteCrashingContextARM(register_location);
|
||||
#elif defined(HAS_ARM64_SUPPORT)
|
||||
return WriteCrashingContextARM64(register_location);
|
||||
#else
|
||||
assert(false);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAS_ARM_SUPPORT
|
||||
bool IosExceptionMinidumpGenerator::WriteCrashingContextARM(
|
||||
MDLocationDescriptor *register_location) {
|
||||
TypedMDRVA<MDRawContextARM> context(&writer_);
|
||||
if (!context.Allocate())
|
||||
return false;
|
||||
|
@ -77,25 +97,43 @@ bool IosExceptionMinidumpGenerator::WriteCrashingContext(
|
|||
MDRawContextARM *context_ptr = context.get();
|
||||
memset(context_ptr, 0, sizeof(MDRawContextARM));
|
||||
context_ptr->context_flags = MD_CONTEXT_ARM_FULL;
|
||||
context_ptr->iregs[7] = kExpectedFinalFp; // FP
|
||||
context_ptr->iregs[13] = kExpectedFinalSp; // SP
|
||||
uint32_t pc = GetPCFromException();
|
||||
context_ptr->iregs[14] = pc; // LR
|
||||
context_ptr->iregs[15] = pc; // PC
|
||||
context_ptr->iregs[MD_CONTEXT_ARM_REG_IOS_FP] = kExpectedFinalFp; // FP
|
||||
context_ptr->iregs[MD_CONTEXT_ARM_REG_SP] = kExpectedFinalSp; // SP
|
||||
context_ptr->iregs[MD_CONTEXT_ARM_REG_LR] = GetLRFromException(); // LR
|
||||
context_ptr->iregs[MD_CONTEXT_ARM_REG_PC] = GetPCFromException(); // PC
|
||||
return true;
|
||||
#else
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_ARM64_SUPPORT
|
||||
bool IosExceptionMinidumpGenerator::WriteCrashingContextARM64(
|
||||
MDLocationDescriptor *register_location) {
|
||||
TypedMDRVA<MDRawContextARM64> context(&writer_);
|
||||
if (!context.Allocate())
|
||||
return false;
|
||||
*register_location = context.location();
|
||||
MDRawContextARM64 *context_ptr = context.get();
|
||||
memset(context_ptr, 0, sizeof(*context_ptr));
|
||||
context_ptr->context_flags = MD_CONTEXT_ARM64_FULL;
|
||||
context_ptr->iregs[MD_CONTEXT_ARM64_REG_FP] = kExpectedFinalFp; // FP
|
||||
context_ptr->iregs[MD_CONTEXT_ARM64_REG_SP] = kExpectedFinalSp; // SP
|
||||
context_ptr->iregs[MD_CONTEXT_ARM64_REG_LR] = GetLRFromException(); // LR
|
||||
context_ptr->iregs[MD_CONTEXT_ARM64_REG_PC] = GetPCFromException(); // PC
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
uintptr_t IosExceptionMinidumpGenerator::GetPCFromException() {
|
||||
return [[return_addresses_ objectAtIndex:0] unsignedIntegerValue];
|
||||
}
|
||||
|
||||
uint32_t IosExceptionMinidumpGenerator::GetPCFromException() {
|
||||
return [[return_addresses_ objectAtIndex:0] unsignedIntegerValue];
|
||||
uintptr_t IosExceptionMinidumpGenerator::GetLRFromException() {
|
||||
return [[return_addresses_ objectAtIndex:1] unsignedIntegerValue];
|
||||
}
|
||||
|
||||
bool IosExceptionMinidumpGenerator::WriteExceptionStream(
|
||||
MDRawDirectory *exception_stream) {
|
||||
#ifdef HAS_ARM_SUPPORT
|
||||
#if defined(HAS_ARM_SUPPORT) || defined(HAS_ARM64_SUPPORT)
|
||||
TypedMDRVA<MDRawExceptionStream> exception(&writer_);
|
||||
|
||||
if (!exception.Allocate())
|
||||
|
@ -123,34 +161,38 @@ bool IosExceptionMinidumpGenerator::WriteExceptionStream(
|
|||
|
||||
bool IosExceptionMinidumpGenerator::WriteThreadStream(mach_port_t thread_id,
|
||||
MDRawThread *thread) {
|
||||
#ifdef HAS_ARM_SUPPORT
|
||||
#if defined(HAS_ARM_SUPPORT) || defined(HAS_ARM64_SUPPORT)
|
||||
if (pthread_mach_thread_np(pthread_self()) != thread_id)
|
||||
return MinidumpGenerator::WriteThreadStream(thread_id, thread);
|
||||
|
||||
size_t frame_count = [return_addresses_ count];
|
||||
UntypedMDRVA memory(&writer_);
|
||||
size_t size = 8 * (frame_count - 1) + 4;
|
||||
if (!memory.Allocate(size))
|
||||
if (frame_count == 0)
|
||||
return false;
|
||||
scoped_array<uint8_t> stack_memory(new uint8_t[size]);
|
||||
uint32_t sp = size - 4;
|
||||
uint32_t fp = 0;
|
||||
uint32_t lr = [[return_addresses_ lastObject] unsignedIntegerValue];
|
||||
for (int current_frame = frame_count - 2;
|
||||
current_frame >= 0;
|
||||
UntypedMDRVA memory(&writer_);
|
||||
size_t pointer_size = sizeof(uintptr_t);
|
||||
size_t frame_record_size = 2 * pointer_size;
|
||||
size_t stack_size = frame_record_size * (frame_count - 1) + pointer_size;
|
||||
if (!memory.Allocate(stack_size))
|
||||
return false;
|
||||
scoped_array<uint8_t> stack_memory(new uint8_t[stack_size]);
|
||||
uintptr_t sp = stack_size - pointer_size;
|
||||
uintptr_t fp = 0;
|
||||
uintptr_t lr = 0;
|
||||
for (size_t current_frame = frame_count - 1;
|
||||
current_frame > 0;
|
||||
--current_frame) {
|
||||
AppendToMemory(stack_memory.get(), sp, fp);
|
||||
sp -= 4;
|
||||
fp = sp;
|
||||
AppendToMemory(stack_memory.get(), sp, lr);
|
||||
sp -= 4;
|
||||
sp -= pointer_size;
|
||||
AppendToMemory(stack_memory.get(), sp, fp);
|
||||
fp = sp;
|
||||
sp -= pointer_size;
|
||||
lr = [[return_addresses_ objectAtIndex:current_frame] unsignedIntegerValue];
|
||||
}
|
||||
if (!memory.Copy(stack_memory.get(), size))
|
||||
if (!memory.Copy(stack_memory.get(), stack_size))
|
||||
return false;
|
||||
assert(sp == kExpectedFinalSp);
|
||||
assert(fp == kExpectedFinalFp);
|
||||
assert(lr == GetPCFromException());
|
||||
assert(lr == GetLRFromException());
|
||||
thread->stack.start_of_memory_range = sp;
|
||||
thread->stack.memory = memory.location();
|
||||
memory_blocks_.push_back(thread->stack);
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
ifeq (Android,$(OS_TARGET))
|
||||
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||
TARGET_LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/crashreporter/gonk-include/
|
||||
else
|
||||
TARGET_LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/crashreporter/google-breakpad/src/common/android/include/
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef MOZ_THUMB2 #{
|
||||
# The syscall number is passed through r7 in the linux ARM ABI, but r7
|
||||
# is also the THUMB frame pointer. (Unfortunate, but ah well.) gcc
|
||||
# complains if we store to r7, not unreasonably, but complains
|
||||
# inconsistently. The generic syscall template pushes/stores to/pops
|
||||
# r7 with no complaint from gcc, but the sys_clone() function marks r7
|
||||
# as a clobbered register yet gcc error's. The generated assembly for
|
||||
# sys_clone() looks OK, so we chalk this up to a gcc/gas quirk and
|
||||
# work around it by telling gcc that the THUMB frame pointer is a
|
||||
# vanilla callee-save register.
|
||||
OS_CXXFLAGS += -fomit-frame-pointer
|
||||
MOZ_FRAMEPTR_FLAGS := -fomit-frame-pointer
|
||||
endif #}
|
|
@ -27,67 +27,79 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "client/linux/crash_generation/crash_generation_client.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "client/linux/crash_generation/crash_generation_client.h"
|
||||
#include "common/linux/eintr_wrapper.h"
|
||||
#include "common/linux/ignore_ret.h"
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
bool
|
||||
CrashGenerationClient::RequestDump(const void* blob, size_t blob_size)
|
||||
{
|
||||
int fds[2];
|
||||
if (sys_pipe(fds) != 0)
|
||||
return false;
|
||||
static const unsigned kControlMsgSize = CMSG_SPACE(sizeof(int));
|
||||
namespace {
|
||||
|
||||
struct kernel_msghdr msg;
|
||||
my_memset(&msg, 0, sizeof(struct kernel_msghdr));
|
||||
struct kernel_iovec iov[1];
|
||||
iov[0].iov_base = const_cast<void*>(blob);
|
||||
iov[0].iov_len = blob_size;
|
||||
class CrashGenerationClientImpl : public CrashGenerationClient {
|
||||
public:
|
||||
explicit CrashGenerationClientImpl(int server_fd) : server_fd_(server_fd) {}
|
||||
virtual ~CrashGenerationClientImpl() {}
|
||||
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
|
||||
char cmsg[kControlMsgSize];
|
||||
my_memset(cmsg, 0, kControlMsgSize);
|
||||
msg.msg_control = cmsg;
|
||||
msg.msg_controllen = sizeof(cmsg);
|
||||
virtual bool RequestDump(const void* blob, size_t blob_size) {
|
||||
int fds[2];
|
||||
if (sys_pipe(fds) < 0)
|
||||
return false;
|
||||
static const unsigned kControlMsgSize = CMSG_SPACE(sizeof(int));
|
||||
|
||||
struct cmsghdr* hdr = CMSG_FIRSTHDR(&msg);
|
||||
hdr->cmsg_level = SOL_SOCKET;
|
||||
hdr->cmsg_type = SCM_RIGHTS;
|
||||
hdr->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
int* p = reinterpret_cast<int*>(CMSG_DATA(hdr));
|
||||
*p = fds[1];
|
||||
struct kernel_iovec iov;
|
||||
iov.iov_base = const_cast<void*>(blob);
|
||||
iov.iov_len = blob_size;
|
||||
|
||||
ssize_t ret = HANDLE_EINTR(sys_sendmsg(server_fd_, &msg, 0));
|
||||
sys_close(fds[1]);
|
||||
if (ret <= 0)
|
||||
return false;
|
||||
struct kernel_msghdr msg = { 0 };
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
char cmsg[kControlMsgSize] = "";
|
||||
msg.msg_control = cmsg;
|
||||
msg.msg_controllen = sizeof(cmsg);
|
||||
|
||||
// wait for an ACK from the server
|
||||
char b;
|
||||
IGNORE_RET(HANDLE_EINTR(sys_read(fds[0], &b, 1)));
|
||||
struct cmsghdr* hdr = CMSG_FIRSTHDR(&msg);
|
||||
hdr->cmsg_level = SOL_SOCKET;
|
||||
hdr->cmsg_type = SCM_RIGHTS;
|
||||
hdr->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
int* p = reinterpret_cast<int*>(CMSG_DATA(hdr));
|
||||
*p = fds[1];
|
||||
|
||||
return true;
|
||||
}
|
||||
ssize_t ret = HANDLE_EINTR(sys_sendmsg(server_fd_, &msg, 0));
|
||||
sys_close(fds[1]);
|
||||
if (ret < 0) {
|
||||
sys_close(fds[0]);
|
||||
return false;
|
||||
}
|
||||
|
||||
//static
|
||||
CrashGenerationClient*
|
||||
CrashGenerationClient::TryCreate(int server_fd)
|
||||
{
|
||||
if (0 > server_fd)
|
||||
// Wait for an ACK from the server.
|
||||
char b;
|
||||
IGNORE_RET(HANDLE_EINTR(sys_read(fds[0], &b, 1)));
|
||||
sys_close(fds[0]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
int server_fd_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CrashGenerationClientImpl);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
CrashGenerationClient* CrashGenerationClient::TryCreate(int server_fd) {
|
||||
if (server_fd < 0)
|
||||
return NULL;
|
||||
return new CrashGenerationClient(server_fd);
|
||||
return new CrashGenerationClientImpl(server_fd);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace google_breakpad
|
||||
|
|
|
@ -30,40 +30,36 @@
|
|||
#ifndef CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
|
||||
#define CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
|
||||
|
||||
#include "common/basictypes.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// CrashGenerationClient is an interface for implementing out-of-process crash
|
||||
// dumping. The default implementation, accessed via the TryCreate() factory,
|
||||
// works in conjunction with the CrashGenerationServer to generate a minidump
|
||||
// via a remote process.
|
||||
class CrashGenerationClient {
|
||||
public:
|
||||
~CrashGenerationClient()
|
||||
{
|
||||
}
|
||||
public:
|
||||
CrashGenerationClient() {}
|
||||
virtual ~CrashGenerationClient() {}
|
||||
|
||||
// Request the crash server to generate a dump. |blob| is a hack,
|
||||
// see exception_handler.h and minidump_writer.h
|
||||
//
|
||||
// Return true if the dump was successful; false otherwise.
|
||||
bool RequestDump(const void* blob, size_t blob_size);
|
||||
// Request the crash server to generate a dump. |blob| is an opaque
|
||||
// CrashContext pointer from exception_handler.h.
|
||||
// Returns true if the dump was successful; false otherwise.
|
||||
virtual bool RequestDump(const void* blob, size_t blob_size) = 0;
|
||||
|
||||
// Return a new CrashGenerationClient if |server_fd| is valid and
|
||||
// Returns a new CrashGenerationClient if |server_fd| is valid and
|
||||
// connects to a CrashGenerationServer. Otherwise, return NULL.
|
||||
// The returned CrashGenerationClient* is owned by the caller of
|
||||
// this function.
|
||||
static CrashGenerationClient* TryCreate(int server_fd);
|
||||
|
||||
private:
|
||||
CrashGenerationClient(int server_fd) : server_fd_(server_fd)
|
||||
{
|
||||
}
|
||||
|
||||
int server_fd_;
|
||||
|
||||
// prevent copy construction and assignment
|
||||
CrashGenerationClient(const CrashGenerationClient&);
|
||||
CrashGenerationClient& operator=(const CrashGenerationClient&);
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CrashGenerationClient);
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
|
||||
#endif // CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
|
||||
|
|
|
@ -239,7 +239,7 @@ CrashGenerationServer::ClientEvent(short revents)
|
|||
// A nasty process could try and send us too many descriptors and
|
||||
// force a leak.
|
||||
for (unsigned i = 0; i < num_fds; ++i)
|
||||
HANDLE_EINTR(close(reinterpret_cast<int*>(CMSG_DATA(hdr))[i]));
|
||||
close(reinterpret_cast<int*>(CMSG_DATA(hdr))[i]);
|
||||
return true;
|
||||
} else {
|
||||
signal_fd = reinterpret_cast<int*>(CMSG_DATA(hdr))[0];
|
||||
|
@ -253,7 +253,7 @@ CrashGenerationServer::ClientEvent(short revents)
|
|||
|
||||
if (crashing_pid == -1 || signal_fd == -1) {
|
||||
if (signal_fd)
|
||||
HANDLE_EINTR(close(signal_fd));
|
||||
close(signal_fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -264,7 +264,7 @@ CrashGenerationServer::ClientEvent(short revents)
|
|||
if (!google_breakpad::WriteMinidump(minidump_filename.c_str(),
|
||||
crashing_pid, crash_context,
|
||||
kCrashContextSize)) {
|
||||
HANDLE_EINTR(close(signal_fd));
|
||||
close(signal_fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -276,7 +276,7 @@ CrashGenerationServer::ClientEvent(short revents)
|
|||
|
||||
// Send the done signal to the process: it can exit now.
|
||||
// (Closing this will make the child's sys_read unblock and return 0.)
|
||||
HANDLE_EINTR(close(signal_fd));
|
||||
close(signal_fd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'crash_generation_client.cc',
|
||||
'crash_generation_server.cc',
|
||||
]
|
||||
|
||||
# We allow warnings for third-party code that can be updated from upstream.
|
||||
ALLOW_COMPILER_WARNINGS = True
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/toolkit/crashreporter/google-breakpad/src',
|
||||
]
|
||||
|
||||
if CONFIG['OS_TARGET'] == 'Android':
|
||||
LOCAL_INCLUDES += [
|
||||
'/toolkit/crashreporter/google-breakpad/src/common/android/include',
|
||||
]
|
||||
|
||||
include('/toolkit/crashreporter/crashreporter.mozbuild')
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2000 - 2007, Google Inc.
|
||||
// Copyright (c) 2014, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
|
@ -26,35 +26,36 @@
|
|||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Routines to extract the current stack trace. These functions are
|
||||
// thread-safe.
|
||||
|
||||
#ifndef BASE_STACKTRACE_H_
|
||||
#define BASE_STACKTRACE_H_
|
||||
#ifndef CLIENT_LINUX_DUMP_WRITER_COMMON_MAPPING_INFO_H_
|
||||
#define CLIENT_LINUX_DUMP_WRITER_COMMON_MAPPING_INFO_H_
|
||||
|
||||
#include "config.h"
|
||||
#include <limits.h>
|
||||
#include <list>
|
||||
#include <stdint.h>
|
||||
|
||||
_START_GOOGLE_NAMESPACE_
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
// This is similar to the GetStackFrames routine, except that it returns
|
||||
// the stack trace only, and not the stack frame sizes as well.
|
||||
// Example:
|
||||
// main() { foo(); }
|
||||
// foo() { bar(); }
|
||||
// bar() {
|
||||
// void* result[10];
|
||||
// int depth = GetStackFrames(result, 10, 1);
|
||||
// }
|
||||
//
|
||||
// This produces:
|
||||
// result[0] foo
|
||||
// result[1] main
|
||||
// .... ...
|
||||
//
|
||||
// "result" must not be NULL.
|
||||
extern int GetStackTrace(void** result, int max_depth, int skip_count);
|
||||
namespace google_breakpad {
|
||||
|
||||
_END_GOOGLE_NAMESPACE_
|
||||
// One of these is produced for each mapping in the process (i.e. line in
|
||||
// /proc/$x/maps).
|
||||
struct MappingInfo {
|
||||
uintptr_t start_addr;
|
||||
size_t size;
|
||||
size_t offset; // offset into the backed file.
|
||||
bool exec; // true if the mapping has the execute bit set.
|
||||
char name[NAME_MAX];
|
||||
};
|
||||
|
||||
#endif // BASE_STACKTRACE_H_
|
||||
struct MappingEntry {
|
||||
MappingInfo first;
|
||||
uint8_t second[sizeof(MDGUID)];
|
||||
};
|
||||
|
||||
// A list of <MappingInfo, GUID>
|
||||
typedef std::list<MappingEntry> MappingList;
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_DUMP_WRITER_COMMON_MAPPING_INFO_H_
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright (c) 2014, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CLIENT_LINUX_DUMP_WRITER_COMMON_RAW_CONTEXT_CPU_H
|
||||
#define CLIENT_LINUX_DUMP_WRITER_COMMON_RAW_CONTEXT_CPU_H
|
||||
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
#if defined(__i386__)
|
||||
typedef MDRawContextX86 RawContextCPU;
|
||||
#elif defined(__x86_64)
|
||||
typedef MDRawContextAMD64 RawContextCPU;
|
||||
#elif defined(__ARM_EABI__)
|
||||
typedef MDRawContextARM RawContextCPU;
|
||||
#elif defined(__aarch64__)
|
||||
typedef MDRawContextARM64 RawContextCPU;
|
||||
#elif defined(__mips__)
|
||||
typedef MDRawContextMIPS RawContextCPU;
|
||||
#else
|
||||
#error "This code has not been ported to your platform yet."
|
||||
#endif
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_DUMP_WRITER_COMMON_RAW_CONTEXT_CPU_H
|
|
@ -0,0 +1,299 @@
|
|||
// Copyright (c) 2014, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "client/linux/dump_writer_common/thread_info.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(__i386__)
|
||||
// Write a uint16_t to memory
|
||||
// out: memory location to write to
|
||||
// v: value to write.
|
||||
void U16(void* out, uint16_t v) {
|
||||
my_memcpy(out, &v, sizeof(v));
|
||||
}
|
||||
|
||||
// Write a uint32_t to memory
|
||||
// out: memory location to write to
|
||||
// v: value to write.
|
||||
void U32(void* out, uint32_t v) {
|
||||
my_memcpy(out, &v, sizeof(v));
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
#if defined(__i386__)
|
||||
|
||||
uintptr_t ThreadInfo::GetInstructionPointer() const {
|
||||
return regs.eip;
|
||||
}
|
||||
|
||||
void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
|
||||
out->context_flags = MD_CONTEXT_X86_ALL;
|
||||
|
||||
out->dr0 = dregs[0];
|
||||
out->dr1 = dregs[1];
|
||||
out->dr2 = dregs[2];
|
||||
out->dr3 = dregs[3];
|
||||
// 4 and 5 deliberatly omitted because they aren't included in the minidump
|
||||
// format.
|
||||
out->dr6 = dregs[6];
|
||||
out->dr7 = dregs[7];
|
||||
|
||||
out->gs = regs.xgs;
|
||||
out->fs = regs.xfs;
|
||||
out->es = regs.xes;
|
||||
out->ds = regs.xds;
|
||||
|
||||
out->edi = regs.edi;
|
||||
out->esi = regs.esi;
|
||||
out->ebx = regs.ebx;
|
||||
out->edx = regs.edx;
|
||||
out->ecx = regs.ecx;
|
||||
out->eax = regs.eax;
|
||||
|
||||
out->ebp = regs.ebp;
|
||||
out->eip = regs.eip;
|
||||
out->cs = regs.xcs;
|
||||
out->eflags = regs.eflags;
|
||||
out->esp = regs.esp;
|
||||
out->ss = regs.xss;
|
||||
|
||||
out->float_save.control_word = fpregs.cwd;
|
||||
out->float_save.status_word = fpregs.swd;
|
||||
out->float_save.tag_word = fpregs.twd;
|
||||
out->float_save.error_offset = fpregs.fip;
|
||||
out->float_save.error_selector = fpregs.fcs;
|
||||
out->float_save.data_offset = fpregs.foo;
|
||||
out->float_save.data_selector = fpregs.fos;
|
||||
|
||||
// 8 registers * 10 bytes per register.
|
||||
my_memcpy(out->float_save.register_area, fpregs.st_space, 10 * 8);
|
||||
|
||||
// This matches the Intel fpsave format.
|
||||
U16(out->extended_registers + 0, fpregs.cwd);
|
||||
U16(out->extended_registers + 2, fpregs.swd);
|
||||
U16(out->extended_registers + 4, fpregs.twd);
|
||||
U16(out->extended_registers + 6, fpxregs.fop);
|
||||
U32(out->extended_registers + 8, fpxregs.fip);
|
||||
U16(out->extended_registers + 12, fpxregs.fcs);
|
||||
U32(out->extended_registers + 16, fpregs.foo);
|
||||
U16(out->extended_registers + 20, fpregs.fos);
|
||||
U32(out->extended_registers + 24, fpxregs.mxcsr);
|
||||
|
||||
my_memcpy(out->extended_registers + 32, &fpxregs.st_space, 128);
|
||||
my_memcpy(out->extended_registers + 160, &fpxregs.xmm_space, 128);
|
||||
}
|
||||
|
||||
#elif defined(__x86_64)
|
||||
|
||||
uintptr_t ThreadInfo::GetInstructionPointer() const {
|
||||
return regs.rip;
|
||||
}
|
||||
|
||||
void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
|
||||
out->context_flags = MD_CONTEXT_AMD64_FULL |
|
||||
MD_CONTEXT_AMD64_SEGMENTS;
|
||||
|
||||
out->cs = regs.cs;
|
||||
|
||||
out->ds = regs.ds;
|
||||
out->es = regs.es;
|
||||
out->fs = regs.fs;
|
||||
out->gs = regs.gs;
|
||||
|
||||
out->ss = regs.ss;
|
||||
out->eflags = regs.eflags;
|
||||
|
||||
out->dr0 = dregs[0];
|
||||
out->dr1 = dregs[1];
|
||||
out->dr2 = dregs[2];
|
||||
out->dr3 = dregs[3];
|
||||
// 4 and 5 deliberatly omitted because they aren't included in the minidump
|
||||
// format.
|
||||
out->dr6 = dregs[6];
|
||||
out->dr7 = dregs[7];
|
||||
|
||||
out->rax = regs.rax;
|
||||
out->rcx = regs.rcx;
|
||||
out->rdx = regs.rdx;
|
||||
out->rbx = regs.rbx;
|
||||
|
||||
out->rsp = regs.rsp;
|
||||
|
||||
out->rbp = regs.rbp;
|
||||
out->rsi = regs.rsi;
|
||||
out->rdi = regs.rdi;
|
||||
out->r8 = regs.r8;
|
||||
out->r9 = regs.r9;
|
||||
out->r10 = regs.r10;
|
||||
out->r11 = regs.r11;
|
||||
out->r12 = regs.r12;
|
||||
out->r13 = regs.r13;
|
||||
out->r14 = regs.r14;
|
||||
out->r15 = regs.r15;
|
||||
|
||||
out->rip = regs.rip;
|
||||
|
||||
out->flt_save.control_word = fpregs.cwd;
|
||||
out->flt_save.status_word = fpregs.swd;
|
||||
out->flt_save.tag_word = fpregs.ftw;
|
||||
out->flt_save.error_opcode = fpregs.fop;
|
||||
out->flt_save.error_offset = fpregs.rip;
|
||||
out->flt_save.error_selector = 0; // We don't have this.
|
||||
out->flt_save.data_offset = fpregs.rdp;
|
||||
out->flt_save.data_selector = 0; // We don't have this.
|
||||
out->flt_save.mx_csr = fpregs.mxcsr;
|
||||
out->flt_save.mx_csr_mask = fpregs.mxcr_mask;
|
||||
|
||||
my_memcpy(&out->flt_save.float_registers, &fpregs.st_space, 8 * 16);
|
||||
my_memcpy(&out->flt_save.xmm_registers, &fpregs.xmm_space, 16 * 16);
|
||||
}
|
||||
|
||||
#elif defined(__ARM_EABI__)
|
||||
|
||||
uintptr_t ThreadInfo::GetInstructionPointer() const {
|
||||
return regs.uregs[15];
|
||||
}
|
||||
|
||||
void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
|
||||
out->context_flags = MD_CONTEXT_ARM_FULL;
|
||||
|
||||
for (int i = 0; i < MD_CONTEXT_ARM_GPR_COUNT; ++i)
|
||||
out->iregs[i] = regs.uregs[i];
|
||||
// No CPSR register in ThreadInfo(it's not accessible via ptrace)
|
||||
out->cpsr = 0;
|
||||
#if !defined(__ANDROID__)
|
||||
out->float_save.fpscr = fpregs.fpsr |
|
||||
(static_cast<uint64_t>(fpregs.fpcr) << 32);
|
||||
// TODO: sort this out, actually collect floating point registers
|
||||
my_memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
|
||||
my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
uintptr_t ThreadInfo::GetInstructionPointer() const {
|
||||
return regs.pc;
|
||||
}
|
||||
|
||||
void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
|
||||
out->context_flags = MD_CONTEXT_ARM64_FULL;
|
||||
|
||||
out->cpsr = static_cast<uint32_t>(regs.pstate);
|
||||
for (int i = 0; i < MD_CONTEXT_ARM64_REG_SP; ++i)
|
||||
out->iregs[i] = regs.regs[i];
|
||||
out->iregs[MD_CONTEXT_ARM64_REG_SP] = regs.sp;
|
||||
out->iregs[MD_CONTEXT_ARM64_REG_PC] = regs.pc;
|
||||
|
||||
out->float_save.fpsr = fpregs.fpsr;
|
||||
out->float_save.fpcr = fpregs.fpcr;
|
||||
my_memcpy(&out->float_save.regs, &fpregs.vregs,
|
||||
MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT * 16);
|
||||
}
|
||||
|
||||
#elif defined(__mips__)
|
||||
|
||||
uintptr_t ThreadInfo::GetInstructionPointer() const {
|
||||
return mcontext.pc;
|
||||
}
|
||||
|
||||
void ThreadInfo::FillCPUContext(RawContextCPU* out) const {
|
||||
out->context_flags = MD_CONTEXT_MIPS_FULL;
|
||||
|
||||
for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
|
||||
out->iregs[i] = mcontext.gregs[i];
|
||||
|
||||
out->mdhi = mcontext.mdhi;
|
||||
out->mdlo = mcontext.mdlo;
|
||||
out->dsp_control = mcontext.dsp;
|
||||
|
||||
out->hi[0] = mcontext.hi1;
|
||||
out->lo[0] = mcontext.lo1;
|
||||
out->hi[1] = mcontext.hi2;
|
||||
out->lo[1] = mcontext.lo2;
|
||||
out->hi[2] = mcontext.hi3;
|
||||
out->lo[2] = mcontext.lo3;
|
||||
|
||||
out->epc = mcontext.pc;
|
||||
out->badvaddr = 0; // Not stored in mcontext
|
||||
out->status = 0; // Not stored in mcontext
|
||||
out->cause = 0; // Not stored in mcontext
|
||||
|
||||
for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
|
||||
out->float_save.regs[i] = mcontext.fpregs.fp_r.fp_fregs[i]._fp_fregs;
|
||||
|
||||
out->float_save.fpcsr = mcontext.fpc_csr;
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
out->float_save.fir = mcontext.fpc_eir;
|
||||
#endif
|
||||
}
|
||||
#endif // __mips__
|
||||
|
||||
void ThreadInfo::GetGeneralPurposeRegisters(void** gp_regs, size_t* size) {
|
||||
assert(gp_regs || size);
|
||||
#if defined(__mips__)
|
||||
if (gp_regs)
|
||||
*gp_regs = mcontext.gregs;
|
||||
if (size)
|
||||
*size = sizeof(mcontext.gregs);
|
||||
#else
|
||||
if (gp_regs)
|
||||
*gp_regs = ®s;
|
||||
if (size)
|
||||
*size = sizeof(regs);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ThreadInfo::GetFloatingPointRegisters(void** fp_regs, size_t* size) {
|
||||
assert(fp_regs || size);
|
||||
#if defined(__mips__)
|
||||
if (fp_regs)
|
||||
*fp_regs = &mcontext.fpregs;
|
||||
if (size)
|
||||
*size = sizeof(mcontext.fpregs);
|
||||
#else
|
||||
if (fp_regs)
|
||||
*fp_regs = &fpregs;
|
||||
if (size)
|
||||
*size = sizeof(fpregs);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright (c) 2014, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CLIENT_LINUX_DUMP_WRITER_COMMON_THREAD_INFO_H_
|
||||
#define CLIENT_LINUX_DUMP_WRITER_COMMON_THREAD_INFO_H_
|
||||
|
||||
#include <sys/ucontext.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include "client/linux/dump_writer_common/raw_context_cpu.h"
|
||||
#include "common/memory.h"
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
#if defined(__i386) || defined(__x86_64)
|
||||
typedef __typeof__(((struct user*) 0)->u_debugreg[0]) debugreg_t;
|
||||
#endif
|
||||
|
||||
// We produce one of these structures for each thread in the crashed process.
|
||||
struct ThreadInfo {
|
||||
pid_t tgid; // thread group id
|
||||
pid_t ppid; // parent process
|
||||
|
||||
uintptr_t stack_pointer; // thread stack pointer
|
||||
|
||||
|
||||
#if defined(__i386) || defined(__x86_64)
|
||||
user_regs_struct regs;
|
||||
user_fpregs_struct fpregs;
|
||||
static const unsigned kNumDebugRegisters = 8;
|
||||
debugreg_t dregs[8];
|
||||
#if defined(__i386)
|
||||
user_fpxregs_struct fpxregs;
|
||||
#endif // defined(__i386)
|
||||
|
||||
#elif defined(__ARM_EABI__)
|
||||
// Mimicking how strace does this(see syscall.c, search for GETREGS)
|
||||
struct user_regs regs;
|
||||
struct user_fpregs fpregs;
|
||||
#elif defined(__aarch64__)
|
||||
// Use the structures defined in <sys/user.h>
|
||||
struct user_regs_struct regs;
|
||||
struct user_fpsimd_struct fpregs;
|
||||
#elif defined(__mips__)
|
||||
// Use the structure defined in <sys/ucontext.h>.
|
||||
mcontext_t mcontext;
|
||||
#endif
|
||||
|
||||
// Returns the instruction pointer (platform-dependent impl.).
|
||||
uintptr_t GetInstructionPointer() const;
|
||||
|
||||
// Fills a RawContextCPU using the context in the ThreadInfo object.
|
||||
void FillCPUContext(RawContextCPU* out) const;
|
||||
|
||||
// Returns the pointer and size of general purpose register area.
|
||||
void GetGeneralPurposeRegisters(void** gp_regs, size_t* size);
|
||||
|
||||
// Returns the pointer and size of float point register area.
|
||||
void GetFloatingPointRegisters(void** fp_regs, size_t* size);
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_DUMP_WRITER_COMMON_THREAD_INFO_H_
|
|
@ -0,0 +1,253 @@
|
|||
// Copyright (c) 2014, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "client/linux/dump_writer_common/ucontext_reader.h"
|
||||
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// Minidump defines register structures which are different from the raw
|
||||
// structures which we get from the kernel. These are platform specific
|
||||
// functions to juggle the ucontext and user structures into minidump format.
|
||||
|
||||
#if defined(__i386__)
|
||||
|
||||
uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) {
|
||||
return uc->uc_mcontext.gregs[REG_ESP];
|
||||
}
|
||||
|
||||
uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) {
|
||||
return uc->uc_mcontext.gregs[REG_EIP];
|
||||
}
|
||||
|
||||
void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc,
|
||||
const struct _libc_fpstate* fp) {
|
||||
const greg_t* regs = uc->uc_mcontext.gregs;
|
||||
|
||||
out->context_flags = MD_CONTEXT_X86_FULL |
|
||||
MD_CONTEXT_X86_FLOATING_POINT;
|
||||
|
||||
out->gs = regs[REG_GS];
|
||||
out->fs = regs[REG_FS];
|
||||
out->es = regs[REG_ES];
|
||||
out->ds = regs[REG_DS];
|
||||
|
||||
out->edi = regs[REG_EDI];
|
||||
out->esi = regs[REG_ESI];
|
||||
out->ebx = regs[REG_EBX];
|
||||
out->edx = regs[REG_EDX];
|
||||
out->ecx = regs[REG_ECX];
|
||||
out->eax = regs[REG_EAX];
|
||||
|
||||
out->ebp = regs[REG_EBP];
|
||||
out->eip = regs[REG_EIP];
|
||||
out->cs = regs[REG_CS];
|
||||
out->eflags = regs[REG_EFL];
|
||||
out->esp = regs[REG_UESP];
|
||||
out->ss = regs[REG_SS];
|
||||
|
||||
out->float_save.control_word = fp->cw;
|
||||
out->float_save.status_word = fp->sw;
|
||||
out->float_save.tag_word = fp->tag;
|
||||
out->float_save.error_offset = fp->ipoff;
|
||||
out->float_save.error_selector = fp->cssel;
|
||||
out->float_save.data_offset = fp->dataoff;
|
||||
out->float_save.data_selector = fp->datasel;
|
||||
|
||||
// 8 registers * 10 bytes per register.
|
||||
my_memcpy(out->float_save.register_area, fp->_st, 10 * 8);
|
||||
}
|
||||
|
||||
#elif defined(__x86_64)
|
||||
|
||||
uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) {
|
||||
return uc->uc_mcontext.gregs[REG_RSP];
|
||||
}
|
||||
|
||||
uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) {
|
||||
return uc->uc_mcontext.gregs[REG_RIP];
|
||||
}
|
||||
|
||||
void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc,
|
||||
const struct _libc_fpstate* fpregs) {
|
||||
const greg_t* regs = uc->uc_mcontext.gregs;
|
||||
|
||||
out->context_flags = MD_CONTEXT_AMD64_FULL;
|
||||
|
||||
out->cs = regs[REG_CSGSFS] & 0xffff;
|
||||
|
||||
out->fs = (regs[REG_CSGSFS] >> 32) & 0xffff;
|
||||
out->gs = (regs[REG_CSGSFS] >> 16) & 0xffff;
|
||||
|
||||
out->eflags = regs[REG_EFL];
|
||||
|
||||
out->rax = regs[REG_RAX];
|
||||
out->rcx = regs[REG_RCX];
|
||||
out->rdx = regs[REG_RDX];
|
||||
out->rbx = regs[REG_RBX];
|
||||
|
||||
out->rsp = regs[REG_RSP];
|
||||
out->rbp = regs[REG_RBP];
|
||||
out->rsi = regs[REG_RSI];
|
||||
out->rdi = regs[REG_RDI];
|
||||
out->r8 = regs[REG_R8];
|
||||
out->r9 = regs[REG_R9];
|
||||
out->r10 = regs[REG_R10];
|
||||
out->r11 = regs[REG_R11];
|
||||
out->r12 = regs[REG_R12];
|
||||
out->r13 = regs[REG_R13];
|
||||
out->r14 = regs[REG_R14];
|
||||
out->r15 = regs[REG_R15];
|
||||
|
||||
out->rip = regs[REG_RIP];
|
||||
|
||||
out->flt_save.control_word = fpregs->cwd;
|
||||
out->flt_save.status_word = fpregs->swd;
|
||||
out->flt_save.tag_word = fpregs->ftw;
|
||||
out->flt_save.error_opcode = fpregs->fop;
|
||||
out->flt_save.error_offset = fpregs->rip;
|
||||
out->flt_save.data_offset = fpregs->rdp;
|
||||
out->flt_save.error_selector = 0; // We don't have this.
|
||||
out->flt_save.data_selector = 0; // We don't have this.
|
||||
out->flt_save.mx_csr = fpregs->mxcsr;
|
||||
out->flt_save.mx_csr_mask = fpregs->mxcr_mask;
|
||||
my_memcpy(&out->flt_save.float_registers, &fpregs->_st, 8 * 16);
|
||||
my_memcpy(&out->flt_save.xmm_registers, &fpregs->_xmm, 16 * 16);
|
||||
}
|
||||
|
||||
#elif defined(__ARM_EABI__)
|
||||
|
||||
uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) {
|
||||
return uc->uc_mcontext.arm_sp;
|
||||
}
|
||||
|
||||
uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) {
|
||||
return uc->uc_mcontext.arm_pc;
|
||||
}
|
||||
|
||||
void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc) {
|
||||
out->context_flags = MD_CONTEXT_ARM_FULL;
|
||||
|
||||
out->iregs[0] = uc->uc_mcontext.arm_r0;
|
||||
out->iregs[1] = uc->uc_mcontext.arm_r1;
|
||||
out->iregs[2] = uc->uc_mcontext.arm_r2;
|
||||
out->iregs[3] = uc->uc_mcontext.arm_r3;
|
||||
out->iregs[4] = uc->uc_mcontext.arm_r4;
|
||||
out->iregs[5] = uc->uc_mcontext.arm_r5;
|
||||
out->iregs[6] = uc->uc_mcontext.arm_r6;
|
||||
out->iregs[7] = uc->uc_mcontext.arm_r7;
|
||||
out->iregs[8] = uc->uc_mcontext.arm_r8;
|
||||
out->iregs[9] = uc->uc_mcontext.arm_r9;
|
||||
out->iregs[10] = uc->uc_mcontext.arm_r10;
|
||||
|
||||
out->iregs[11] = uc->uc_mcontext.arm_fp;
|
||||
out->iregs[12] = uc->uc_mcontext.arm_ip;
|
||||
out->iregs[13] = uc->uc_mcontext.arm_sp;
|
||||
out->iregs[14] = uc->uc_mcontext.arm_lr;
|
||||
out->iregs[15] = uc->uc_mcontext.arm_pc;
|
||||
|
||||
out->cpsr = uc->uc_mcontext.arm_cpsr;
|
||||
|
||||
// TODO: fix this after fixing ExceptionHandler
|
||||
out->float_save.fpscr = 0;
|
||||
my_memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
|
||||
my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
|
||||
}
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) {
|
||||
return uc->uc_mcontext.sp;
|
||||
}
|
||||
|
||||
uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) {
|
||||
return uc->uc_mcontext.pc;
|
||||
}
|
||||
|
||||
void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc,
|
||||
const struct fpsimd_context* fpregs) {
|
||||
out->context_flags = MD_CONTEXT_ARM64_FULL;
|
||||
|
||||
out->cpsr = static_cast<uint32_t>(uc->uc_mcontext.pstate);
|
||||
for (int i = 0; i < MD_CONTEXT_ARM64_REG_SP; ++i)
|
||||
out->iregs[i] = uc->uc_mcontext.regs[i];
|
||||
out->iregs[MD_CONTEXT_ARM64_REG_SP] = uc->uc_mcontext.sp;
|
||||
out->iregs[MD_CONTEXT_ARM64_REG_PC] = uc->uc_mcontext.pc;
|
||||
|
||||
out->float_save.fpsr = fpregs->fpsr;
|
||||
out->float_save.fpcr = fpregs->fpcr;
|
||||
my_memcpy(&out->float_save.regs, &fpregs->vregs,
|
||||
MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT * 16);
|
||||
}
|
||||
|
||||
#elif defined(__mips__)
|
||||
|
||||
uintptr_t UContextReader::GetStackPointer(const struct ucontext* uc) {
|
||||
return uc->uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP];
|
||||
}
|
||||
|
||||
uintptr_t UContextReader::GetInstructionPointer(const struct ucontext* uc) {
|
||||
return uc->uc_mcontext.pc;
|
||||
}
|
||||
|
||||
void UContextReader::FillCPUContext(RawContextCPU *out, const ucontext *uc) {
|
||||
out->context_flags = MD_CONTEXT_MIPS_FULL;
|
||||
|
||||
for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
|
||||
out->iregs[i] = uc->uc_mcontext.gregs[i];
|
||||
|
||||
out->mdhi = uc->uc_mcontext.mdhi;
|
||||
out->mdlo = uc->uc_mcontext.mdlo;
|
||||
|
||||
out->hi[0] = uc->uc_mcontext.hi1;
|
||||
out->hi[1] = uc->uc_mcontext.hi2;
|
||||
out->hi[2] = uc->uc_mcontext.hi3;
|
||||
out->lo[0] = uc->uc_mcontext.lo1;
|
||||
out->lo[1] = uc->uc_mcontext.lo2;
|
||||
out->lo[2] = uc->uc_mcontext.lo3;
|
||||
out->dsp_control = uc->uc_mcontext.dsp;
|
||||
|
||||
out->epc = uc->uc_mcontext.pc;
|
||||
out->badvaddr = 0; // Not reported in signal context.
|
||||
out->status = 0; // Not reported in signal context.
|
||||
out->cause = 0; // Not reported in signal context.
|
||||
|
||||
for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
|
||||
out->float_save.regs[i] = uc->uc_mcontext.fpregs.fp_r.fp_dregs[i];
|
||||
|
||||
out->float_save.fpcsr = uc->uc_mcontext.fpc_csr;
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused.
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) 2014, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef CLIENT_LINUX_DUMP_WRITER_COMMON_UCONTEXT_READER_H
|
||||
#define CLIENT_LINUX_DUMP_WRITER_COMMON_UCONTEXT_READER_H
|
||||
|
||||
#include <sys/ucontext.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include "client/linux/dump_writer_common/raw_context_cpu.h"
|
||||
#include "common/memory.h"
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// Wraps platform-dependent implementations of accessors to ucontext structs.
|
||||
struct UContextReader {
|
||||
static uintptr_t GetStackPointer(const struct ucontext* uc);
|
||||
|
||||
static uintptr_t GetInstructionPointer(const struct ucontext* uc);
|
||||
|
||||
// Juggle a arch-specific ucontext into a minidump format
|
||||
// out: the minidump structure
|
||||
// info: the collection of register structures.
|
||||
#if defined(__i386__) || defined(__x86_64)
|
||||
static void FillCPUContext(RawContextCPU *out, const ucontext *uc,
|
||||
const struct _libc_fpstate* fp);
|
||||
#elif defined(__aarch64__)
|
||||
static void FillCPUContext(RawContextCPU *out, const ucontext *uc,
|
||||
const struct fpsimd_context* fpregs);
|
||||
#else
|
||||
static void FillCPUContext(RawContextCPU *out, const ucontext *uc);
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_DUMP_WRITER_COMMON_UCONTEXT_READER_H
|
|
@ -68,6 +68,7 @@
|
|||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/limits.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
@ -86,15 +87,19 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "common/basictypes.h"
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "common/memory.h"
|
||||
#include "client/linux/log/log.h"
|
||||
#include "client/linux/microdump_writer/microdump_writer.h"
|
||||
#include "client/linux/minidump_writer/linux_dumper.h"
|
||||
#include "client/linux/minidump_writer/minidump_writer.h"
|
||||
#include "common/linux/eintr_wrapper.h"
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include "linux/sched.h"
|
||||
#endif
|
||||
|
||||
#ifndef PR_SET_PTRACER
|
||||
#define PR_SET_PTRACER 0x59616d61
|
||||
|
@ -139,13 +144,13 @@ void InstallAlternateStackLocked() {
|
|||
// SIGSTKSZ may be too small to prevent the signal handlers from overrunning
|
||||
// the alternative stack. Ensure that the size of the alternative stack is
|
||||
// large enough.
|
||||
static const unsigned kSigStackSize = std::max(8192, SIGSTKSZ);
|
||||
static const unsigned kSigStackSize = std::max(16384, SIGSTKSZ);
|
||||
|
||||
// Only set an alternative stack if there isn't already one, or if the current
|
||||
// one is too small.
|
||||
if (sys_sigaltstack(NULL, &old_stack) == -1 || !old_stack.ss_sp ||
|
||||
old_stack.ss_size < kSigStackSize) {
|
||||
new_stack.ss_sp = malloc(kSigStackSize);
|
||||
new_stack.ss_sp = calloc(1, kSigStackSize);
|
||||
new_stack.ss_size = kSigStackSize;
|
||||
|
||||
if (sys_sigaltstack(&new_stack, NULL) == -1) {
|
||||
|
@ -183,13 +188,37 @@ void RestoreAlternateStackLocked() {
|
|||
stack_installed = false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
void InstallDefaultHandler(int sig) {
|
||||
#if defined(__ANDROID__)
|
||||
// Android L+ expose signal and sigaction symbols that override the system
|
||||
// ones. There is a bug in these functions where a request to set the handler
|
||||
// to SIG_DFL is ignored. In that case, an infinite loop is entered as the
|
||||
// signal is repeatedly sent to breakpad's signal handler.
|
||||
// To work around this, directly call the system's sigaction.
|
||||
struct kernel_sigaction sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sys_sigemptyset(&sa.sa_mask);
|
||||
sa.sa_handler_ = SIG_DFL;
|
||||
sa.sa_flags = SA_RESTART;
|
||||
sys_rt_sigaction(sig, &sa, NULL, sizeof(kernel_sigset_t));
|
||||
#else
|
||||
signal(sig, SIG_DFL);
|
||||
#endif
|
||||
}
|
||||
|
||||
// We can stack multiple exception handlers. In that case, this is the global
|
||||
// which holds the stack.
|
||||
std::vector<ExceptionHandler*>* ExceptionHandler::handler_stack_ = NULL;
|
||||
pthread_mutex_t ExceptionHandler::handler_stack_mutex_ =
|
||||
PTHREAD_MUTEX_INITIALIZER;
|
||||
// The global exception handler stack. This is needed because there may exist
|
||||
// multiple ExceptionHandler instances in a process. Each will have itself
|
||||
// registered in this stack.
|
||||
std::vector<ExceptionHandler*>* g_handler_stack_ = NULL;
|
||||
pthread_mutex_t g_handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
// sizeof(CrashContext) can be too big w.r.t the size of alternatate stack
|
||||
// for SignalHandler(). Keep the crash context as a .bss field. Exception
|
||||
// handlers are serialized by the |g_handler_stack_mutex_| and at most one at a
|
||||
// time can use |g_crash_context_|.
|
||||
ExceptionHandler::CrashContext g_crash_context_;
|
||||
|
||||
} // namespace
|
||||
|
||||
// Runs before crashing: normal context.
|
||||
ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor,
|
||||
|
@ -206,31 +235,44 @@ ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor,
|
|||
if (server_fd >= 0)
|
||||
crash_generation_client_.reset(CrashGenerationClient::TryCreate(server_fd));
|
||||
|
||||
if (!IsOutOfProcess() && !minidump_descriptor_.IsFD())
|
||||
if (!IsOutOfProcess() && !minidump_descriptor_.IsFD() &&
|
||||
!minidump_descriptor_.IsMicrodumpOnConsole())
|
||||
minidump_descriptor_.UpdatePath();
|
||||
|
||||
pthread_mutex_lock(&handler_stack_mutex_);
|
||||
if (!handler_stack_)
|
||||
handler_stack_ = new std::vector<ExceptionHandler*>;
|
||||
#if defined(__ANDROID__)
|
||||
if (minidump_descriptor_.IsMicrodumpOnConsole())
|
||||
logger::initializeCrashLogWriter();
|
||||
#endif
|
||||
|
||||
pthread_mutex_lock(&g_handler_stack_mutex_);
|
||||
|
||||
// Pre-fault the crash context struct. This is to avoid failing due to OOM
|
||||
// if handling an exception when the process ran out of virtual memory.
|
||||
memset(&g_crash_context_, 0, sizeof(g_crash_context_));
|
||||
|
||||
if (!g_handler_stack_)
|
||||
g_handler_stack_ = new std::vector<ExceptionHandler*>;
|
||||
if (install_handler) {
|
||||
InstallAlternateStackLocked();
|
||||
InstallHandlersLocked();
|
||||
}
|
||||
handler_stack_->push_back(this);
|
||||
pthread_mutex_unlock(&handler_stack_mutex_);
|
||||
g_handler_stack_->push_back(this);
|
||||
pthread_mutex_unlock(&g_handler_stack_mutex_);
|
||||
}
|
||||
|
||||
// Runs before crashing: normal context.
|
||||
ExceptionHandler::~ExceptionHandler() {
|
||||
pthread_mutex_lock(&handler_stack_mutex_);
|
||||
pthread_mutex_lock(&g_handler_stack_mutex_);
|
||||
std::vector<ExceptionHandler*>::iterator handler =
|
||||
std::find(handler_stack_->begin(), handler_stack_->end(), this);
|
||||
handler_stack_->erase(handler);
|
||||
if (handler_stack_->empty()) {
|
||||
std::find(g_handler_stack_->begin(), g_handler_stack_->end(), this);
|
||||
g_handler_stack_->erase(handler);
|
||||
if (g_handler_stack_->empty()) {
|
||||
delete g_handler_stack_;
|
||||
g_handler_stack_ = NULL;
|
||||
RestoreAlternateStackLocked();
|
||||
RestoreHandlersLocked();
|
||||
}
|
||||
pthread_mutex_unlock(&handler_stack_mutex_);
|
||||
pthread_mutex_unlock(&g_handler_stack_mutex_);
|
||||
}
|
||||
|
||||
// Runs before crashing: normal context.
|
||||
|
@ -275,7 +317,7 @@ void ExceptionHandler::RestoreHandlersLocked() {
|
|||
|
||||
for (int i = 0; i < kNumHandledSignals; ++i) {
|
||||
if (sigaction(kExceptionSignals[i], &old_handlers[i], NULL) == -1) {
|
||||
signal(kExceptionSignals[i], SIG_DFL);
|
||||
InstallDefaultHandler(kExceptionSignals[i]);
|
||||
}
|
||||
}
|
||||
handlers_installed = false;
|
||||
|
@ -290,7 +332,7 @@ void ExceptionHandler::RestoreHandlersLocked() {
|
|||
// static
|
||||
void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
|
||||
// All the exception signals are blocked at this point.
|
||||
pthread_mutex_lock(&handler_stack_mutex_);
|
||||
pthread_mutex_lock(&g_handler_stack_mutex_);
|
||||
|
||||
// Sometimes, Breakpad runs inside a process where some other buggy code
|
||||
// saves and restores signal handlers temporarily with 'signal'
|
||||
|
@ -315,15 +357,15 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
|
|||
if (sigaction(sig, &cur_handler, NULL) == -1) {
|
||||
// When resetting the handler fails, try to reset the
|
||||
// default one to avoid an infinite loop here.
|
||||
signal(sig, SIG_DFL);
|
||||
InstallDefaultHandler(sig);
|
||||
}
|
||||
pthread_mutex_unlock(&handler_stack_mutex_);
|
||||
pthread_mutex_unlock(&g_handler_stack_mutex_);
|
||||
return;
|
||||
}
|
||||
|
||||
bool handled = false;
|
||||
for (int i = handler_stack_->size() - 1; !handled && i >= 0; --i) {
|
||||
handled = (*handler_stack_)[i]->HandleSignal(sig, info, uc);
|
||||
for (int i = g_handler_stack_->size() - 1; !handled && i >= 0; --i) {
|
||||
handled = (*g_handler_stack_)[i]->HandleSignal(sig, info, uc);
|
||||
}
|
||||
|
||||
// Upon returning from this signal handler, sig will become unmasked and then
|
||||
|
@ -332,17 +374,19 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
|
|||
// previously installed handler. Then, when the signal is retriggered, it will
|
||||
// be delivered to the appropriate handler.
|
||||
if (handled) {
|
||||
signal(sig, SIG_DFL);
|
||||
InstallDefaultHandler(sig);
|
||||
} else {
|
||||
RestoreHandlersLocked();
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&handler_stack_mutex_);
|
||||
pthread_mutex_unlock(&g_handler_stack_mutex_);
|
||||
|
||||
if (info->si_code <= 0) {
|
||||
// This signal was sent by another process. (Positive values of
|
||||
// si_code are reserved for kernel-originated signals.) In order
|
||||
// to retrigger it, we have to queue a new signal.
|
||||
// info->si_code <= 0 iff SI_FROMUSER (SI_FROMKERNEL otherwise).
|
||||
if (info->si_code <= 0 || sig == SIGABRT) {
|
||||
// This signal was triggered by somebody sending us the signal with kill().
|
||||
// In order to retrigger it, we have to queue a new signal by calling
|
||||
// kill() ourselves. The special case (si_pid == 0 && sig == SIGABRT) is
|
||||
// due to the kernel sending a SIGABRT from a user request via SysRQ.
|
||||
if (tgkill(getpid(), syscall(__NR_gettid), sig) < 0) {
|
||||
// If we failed to kill ourselves (e.g. because a sandbox disallows us
|
||||
// to do so), we instead resort to terminating our process. This will
|
||||
|
@ -389,27 +433,39 @@ bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) {
|
|||
bool signal_pid_trusted = info->si_code == SI_USER ||
|
||||
info->si_code == SI_TKILL;
|
||||
if (signal_trusted || (signal_pid_trusted && info->si_pid == getpid())) {
|
||||
sys_prctl(PR_SET_DUMPABLE, 1);
|
||||
sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
|
||||
}
|
||||
CrashContext context;
|
||||
memcpy(&context.siginfo, info, sizeof(siginfo_t));
|
||||
memcpy(&context.context, uc, sizeof(struct ucontext));
|
||||
#if !defined(__ARM_EABI__)
|
||||
|
||||
// Fill in all the holes in the struct to make Valgrind happy.
|
||||
memset(&g_crash_context_, 0, sizeof(g_crash_context_));
|
||||
memcpy(&g_crash_context_.siginfo, info, sizeof(siginfo_t));
|
||||
memcpy(&g_crash_context_.context, uc, sizeof(struct ucontext));
|
||||
#if defined(__aarch64__)
|
||||
struct ucontext* uc_ptr = (struct ucontext*)uc;
|
||||
struct fpsimd_context* fp_ptr =
|
||||
(struct fpsimd_context*)&uc_ptr->uc_mcontext.__reserved;
|
||||
if (fp_ptr->head.magic == FPSIMD_MAGIC) {
|
||||
memcpy(&g_crash_context_.float_state, fp_ptr,
|
||||
sizeof(g_crash_context_.float_state));
|
||||
}
|
||||
#elif !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
// FP state is not part of user ABI on ARM Linux.
|
||||
struct ucontext *uc_ptr = (struct ucontext*)uc;
|
||||
// In case of MIPS Linux FP state is already part of struct ucontext
|
||||
// and 'float_state' is not a member of CrashContext.
|
||||
struct ucontext* uc_ptr = (struct ucontext*)uc;
|
||||
if (uc_ptr->uc_mcontext.fpregs) {
|
||||
memcpy(&context.float_state,
|
||||
uc_ptr->uc_mcontext.fpregs,
|
||||
sizeof(context.float_state));
|
||||
memcpy(&g_crash_context_.float_state, uc_ptr->uc_mcontext.fpregs,
|
||||
sizeof(g_crash_context_.float_state));
|
||||
}
|
||||
#endif
|
||||
context.tid = syscall(__NR_gettid);
|
||||
g_crash_context_.tid = syscall(__NR_gettid);
|
||||
if (crash_handler_ != NULL) {
|
||||
if (crash_handler_(&context, sizeof(context), callback_context_)) {
|
||||
if (crash_handler_(&g_crash_context_, sizeof(g_crash_context_),
|
||||
callback_context_)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return GenerateDump(&context);
|
||||
return GenerateDump(&g_crash_context_);
|
||||
}
|
||||
|
||||
// This is a public interface to HandleSignal that allows the client to
|
||||
|
@ -430,9 +486,11 @@ bool ExceptionHandler::GenerateDump(CrashContext *context) {
|
|||
if (IsOutOfProcess())
|
||||
return crash_generation_client_->RequestDump(context, sizeof(*context));
|
||||
|
||||
static const unsigned kChildStackSize = 8000;
|
||||
// Allocating too much stack isn't a problem, and better to err on the side
|
||||
// of caution than smash it into random locations.
|
||||
static const unsigned kChildStackSize = 16000;
|
||||
PageAllocator allocator;
|
||||
uint8_t* stack = (uint8_t*) allocator.Alloc(kChildStackSize);
|
||||
uint8_t* stack = reinterpret_cast<uint8_t*>(allocator.Alloc(kChildStackSize));
|
||||
if (!stack)
|
||||
return false;
|
||||
// clone() needs the top-most address. (scrub just to be safe)
|
||||
|
@ -450,28 +508,34 @@ bool ExceptionHandler::GenerateDump(CrashContext *context) {
|
|||
// kernels, but we need to know the PID of the cloned process before we
|
||||
// can do this. Create a pipe here which we can use to block the
|
||||
// cloned process after creating it, until we have explicitly enabled ptrace
|
||||
if(sys_pipe(fdes) == -1) {
|
||||
if (sys_pipe(fdes) == -1) {
|
||||
// Creating the pipe failed. We'll log an error but carry on anyway,
|
||||
// as we'll probably still get a useful crash report. All that will happen
|
||||
// is the write() and read() calls will fail with EBADF
|
||||
static const char no_pipe_msg[] = "ExceptionHandler::GenerateDump \
|
||||
sys_pipe failed:";
|
||||
static const char no_pipe_msg[] = "ExceptionHandler::GenerateDump "
|
||||
"sys_pipe failed:";
|
||||
logger::write(no_pipe_msg, sizeof(no_pipe_msg) - 1);
|
||||
logger::write(strerror(errno), strlen(strerror(errno)));
|
||||
logger::write("\n", 1);
|
||||
|
||||
// Ensure fdes[0] and fdes[1] are invalid file descriptors.
|
||||
fdes[0] = fdes[1] = -1;
|
||||
}
|
||||
|
||||
const pid_t child = sys_clone(
|
||||
ThreadEntry, stack, CLONE_FILES | CLONE_FS | CLONE_UNTRACED,
|
||||
&thread_arg, NULL, NULL, NULL);
|
||||
if (child == -1) {
|
||||
sys_close(fdes[0]);
|
||||
sys_close(fdes[1]);
|
||||
return false;
|
||||
}
|
||||
|
||||
int r, status;
|
||||
// Allow the child to ptrace us
|
||||
sys_prctl(PR_SET_PTRACER, child);
|
||||
sys_prctl(PR_SET_PTRACER, child, 0, 0, 0);
|
||||
SendContinueSignalToChild();
|
||||
do {
|
||||
r = sys_waitpid(child, &status, __WALL);
|
||||
} while (r == -1 && errno == EINTR);
|
||||
int status;
|
||||
const int r = HANDLE_EINTR(sys_waitpid(child, &status, __WALL));
|
||||
|
||||
sys_close(fdes[0]);
|
||||
sys_close(fdes[1]);
|
||||
|
@ -494,9 +558,9 @@ void ExceptionHandler::SendContinueSignalToChild() {
|
|||
static const char okToContinueMessage = 'a';
|
||||
int r;
|
||||
r = HANDLE_EINTR(sys_write(fdes[1], &okToContinueMessage, sizeof(char)));
|
||||
if(r == -1) {
|
||||
static const char msg[] = "ExceptionHandler::SendContinueSignalToChild \
|
||||
sys_write failed:";
|
||||
if (r == -1) {
|
||||
static const char msg[] = "ExceptionHandler::SendContinueSignalToChild "
|
||||
"sys_write failed:";
|
||||
logger::write(msg, sizeof(msg) - 1);
|
||||
logger::write(strerror(errno), strlen(strerror(errno)));
|
||||
logger::write("\n", 1);
|
||||
|
@ -509,9 +573,9 @@ void ExceptionHandler::WaitForContinueSignal() {
|
|||
int r;
|
||||
char receivedMessage;
|
||||
r = HANDLE_EINTR(sys_read(fdes[0], &receivedMessage, sizeof(char)));
|
||||
if(r == -1) {
|
||||
static const char msg[] = "ExceptionHandler::WaitForContinueSignal \
|
||||
sys_read failed:";
|
||||
if (r == -1) {
|
||||
static const char msg[] = "ExceptionHandler::WaitForContinueSignal "
|
||||
"sys_read failed:";
|
||||
logger::write(msg, sizeof(msg) - 1);
|
||||
logger::write(strerror(errno), strlen(strerror(errno)));
|
||||
logger::write("\n", 1);
|
||||
|
@ -522,6 +586,14 @@ void ExceptionHandler::WaitForContinueSignal() {
|
|||
// Runs on the cloned process.
|
||||
bool ExceptionHandler::DoDump(pid_t crashing_process, const void* context,
|
||||
size_t context_size) {
|
||||
if (minidump_descriptor_.IsMicrodumpOnConsole()) {
|
||||
return google_breakpad::WriteMicrodump(
|
||||
crashing_process,
|
||||
context,
|
||||
context_size,
|
||||
mapping_list_,
|
||||
*minidump_descriptor_.microdump_extra_info());
|
||||
}
|
||||
if (minidump_descriptor_.IsFD()) {
|
||||
return google_breakpad::WriteMinidump(minidump_descriptor_.fd(),
|
||||
minidump_descriptor_.size_limit(),
|
||||
|
@ -549,8 +621,16 @@ bool ExceptionHandler::WriteMinidump(const string& dump_path,
|
|||
return eh.WriteMinidump();
|
||||
}
|
||||
|
||||
// In order to making using EBP to calculate the desired value for ESP
|
||||
// a valid operation, ensure that this function is compiled with a
|
||||
// frame pointer using the following attribute. This attribute
|
||||
// is supported on GCC but not on clang.
|
||||
#if defined(__i386__) && defined(__GNUC__) && !defined(__clang__)
|
||||
__attribute__((optimize("no-omit-frame-pointer")))
|
||||
#endif
|
||||
bool ExceptionHandler::WriteMinidump() {
|
||||
if (!IsOutOfProcess() && !minidump_descriptor_.IsFD()) {
|
||||
if (!IsOutOfProcess() && !minidump_descriptor_.IsFD() &&
|
||||
!minidump_descriptor_.IsMicrodumpOnConsole()) {
|
||||
// Update the path of the minidump so that this can be called multiple times
|
||||
// and new files are created for each minidump. This is done before the
|
||||
// generation happens, as clients may want to access the MinidumpDescriptor
|
||||
|
@ -560,17 +640,40 @@ bool ExceptionHandler::WriteMinidump() {
|
|||
// Reposition the FD to its beginning and resize it to get rid of the
|
||||
// previous minidump info.
|
||||
lseek(minidump_descriptor_.fd(), 0, SEEK_SET);
|
||||
static_cast<void>(ftruncate(minidump_descriptor_.fd(), 0));
|
||||
ignore_result(ftruncate(minidump_descriptor_.fd(), 0));
|
||||
}
|
||||
|
||||
// Allow this process to be dumped.
|
||||
sys_prctl(PR_SET_DUMPABLE, 1);
|
||||
sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
|
||||
|
||||
CrashContext context;
|
||||
int getcontext_result = getcontext(&context.context);
|
||||
if (getcontext_result)
|
||||
return false;
|
||||
#if !defined(__ARM_EABI__)
|
||||
|
||||
#if defined(__i386__)
|
||||
// In CPUFillFromUContext in minidumpwriter.cc the stack pointer is retrieved
|
||||
// from REG_UESP instead of from REG_ESP. REG_UESP is the user stack pointer
|
||||
// and it only makes sense when running in kernel mode with a different stack
|
||||
// pointer. When WriteMiniDump is called during normal processing REG_UESP is
|
||||
// zero which leads to bad minidump files.
|
||||
if (!context.context.uc_mcontext.gregs[REG_UESP]) {
|
||||
// If REG_UESP is set to REG_ESP then that includes the stack space for the
|
||||
// CrashContext object in this function, which is about 128 KB. Since the
|
||||
// Linux dumper only records 32 KB of stack this would mean that nothing
|
||||
// useful would be recorded. A better option is to set REG_UESP to REG_EBP,
|
||||
// perhaps with a small negative offset in case there is any code that
|
||||
// objects to them being equal.
|
||||
context.context.uc_mcontext.gregs[REG_UESP] =
|
||||
context.context.uc_mcontext.gregs[REG_EBP] - 16;
|
||||
// The stack saving is based off of REG_ESP so it must be set to match the
|
||||
// new REG_UESP.
|
||||
context.context.uc_mcontext.gregs[REG_ESP] =
|
||||
context.context.uc_mcontext.gregs[REG_UESP];
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(__ARM_EABI__) && !defined(__aarch64__) && !defined(__mips__)
|
||||
// FPU state is not part of ARM EABI ucontext_t.
|
||||
memcpy(&context.float_state, context.context.uc_mcontext.fpregs,
|
||||
sizeof(context.float_state));
|
||||
|
@ -589,6 +692,12 @@ bool ExceptionHandler::WriteMinidump() {
|
|||
#elif defined(__arm__)
|
||||
context.siginfo.si_addr =
|
||||
reinterpret_cast<void*>(context.context.uc_mcontext.arm_pc);
|
||||
#elif defined(__aarch64__)
|
||||
context.siginfo.si_addr =
|
||||
reinterpret_cast<void*>(context.context.uc_mcontext.pc);
|
||||
#elif defined(__mips__)
|
||||
context.siginfo.si_addr =
|
||||
reinterpret_cast<void*>(context.context.uc_mcontext.pc);
|
||||
#else
|
||||
#error "This code has not been ported to your platform yet."
|
||||
#endif
|
||||
|
|
|
@ -30,15 +30,13 @@
|
|||
#ifndef CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_
|
||||
#define CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "client/linux/crash_generation/crash_generation_client.h"
|
||||
#include "client/linux/handler/minidump_descriptor.h"
|
||||
#include "client/linux/minidump_writer/minidump_writer.h"
|
||||
|
@ -129,7 +127,7 @@ class ExceptionHandler {
|
|||
ExceptionHandler(const MinidumpDescriptor& descriptor,
|
||||
FilterCallback filter,
|
||||
MinidumpCallback callback,
|
||||
void *callback_context,
|
||||
void* callback_context,
|
||||
bool install_handler,
|
||||
const int server_fd);
|
||||
~ExceptionHandler();
|
||||
|
@ -146,6 +144,10 @@ class ExceptionHandler {
|
|||
crash_handler_ = callback;
|
||||
}
|
||||
|
||||
void set_crash_generation_client(CrashGenerationClient* client) {
|
||||
crash_generation_client_.reset(client);
|
||||
}
|
||||
|
||||
// Writes a minidump immediately. This can be used to capture the execution
|
||||
// state independently of a crash.
|
||||
// Returns true on success.
|
||||
|
@ -190,15 +192,17 @@ class ExceptionHandler {
|
|||
siginfo_t siginfo;
|
||||
pid_t tid; // the crashing thread.
|
||||
struct ucontext context;
|
||||
#if !defined(__ARM_EABI__)
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
// #ifdef this out because FP state is not part of user ABI for Linux ARM.
|
||||
struct _libc_fpstate float_state;
|
||||
// In case of MIPS Linux FP state is already part of struct
|
||||
// ucontext so 'float_state' is not required.
|
||||
fpstate_t float_state;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Returns whether out-of-process dump generation is used or not.
|
||||
bool IsOutOfProcess() const {
|
||||
return crash_generation_client_.get() != NULL;
|
||||
return crash_generation_client_.get() != NULL;
|
||||
}
|
||||
|
||||
// Add information about a memory mapping. This can be used if
|
||||
|
@ -222,6 +226,7 @@ class ExceptionHandler {
|
|||
|
||||
// Report a crash signal from an SA_SIGINFO signal handler.
|
||||
bool HandleSignal(int sig, siginfo_t* info, void* uc);
|
||||
|
||||
private:
|
||||
// Save the old signal handlers and install new ones.
|
||||
static bool InstallHandlersLocked();
|
||||
|
@ -246,18 +251,16 @@ class ExceptionHandler {
|
|||
|
||||
MinidumpDescriptor minidump_descriptor_;
|
||||
|
||||
HandlerCallback crash_handler_;
|
||||
|
||||
// The global exception handler stack. This is need becuase there may exist
|
||||
// multiple ExceptionHandler instances in a process. Each will have itself
|
||||
// registered in this stack.
|
||||
static std::vector<ExceptionHandler*> *handler_stack_;
|
||||
static pthread_mutex_t handler_stack_mutex_;
|
||||
// Must be volatile. The compiler is unaware of the code which runs in
|
||||
// the signal handler which reads this variable. Without volatile the
|
||||
// compiler is free to optimise away writes to this variable which it
|
||||
// believes are never read.
|
||||
volatile HandlerCallback crash_handler_;
|
||||
|
||||
// We need to explicitly enable ptrace of parent processes on some
|
||||
// kernels, but we need to know the PID of the cloned process before we
|
||||
// can do this. We create a pipe which we can use to block the
|
||||
// cloned process after creating it, until we have explicitly enabled
|
||||
// cloned process after creating it, until we have explicitly enabled
|
||||
// ptrace. This is used to store the file descriptors for the pipe
|
||||
int fdes[2];
|
||||
|
||||
|
|
|
@ -35,6 +35,9 @@
|
|||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/wait.h>
|
||||
#if defined(__mips__)
|
||||
#include <sys/cachectl.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -55,7 +58,7 @@ using namespace google_breakpad;
|
|||
namespace {
|
||||
|
||||
// Flush the instruction cache for a given memory range.
|
||||
// Only required on ARM.
|
||||
// Only required on ARM and mips.
|
||||
void FlushInstructionCache(const char* memory, uint32_t memory_size) {
|
||||
#if defined(__arm__)
|
||||
long begin = reinterpret_cast<long>(memory);
|
||||
|
@ -72,6 +75,22 @@ void FlushInstructionCache(const char* memory, uint32_t memory_size) {
|
|||
# else
|
||||
# error "Your operating system is not supported yet"
|
||||
# endif
|
||||
#elif defined(__mips__)
|
||||
# if defined(__ANDROID__)
|
||||
// Provided by Android's <unistd.h>
|
||||
long begin = reinterpret_cast<long>(memory);
|
||||
long end = begin + static_cast<long>(memory_size);
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
cacheflush(begin, end, 0);
|
||||
#else
|
||||
syscall(__NR_cacheflush, begin, end, ICACHE);
|
||||
#endif
|
||||
# elif defined(__linux__)
|
||||
// See http://www.linux-mips.org/wiki/Cacheflush_Syscall.
|
||||
cacheflush(const_cast<char*>(memory), memory_size, ICACHE);
|
||||
# else
|
||||
# error "Your operating system is not supported yet"
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -176,6 +195,22 @@ static bool DoneCallback(const MinidumpDescriptor& descriptor,
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifndef ADDRESS_SANITIZER
|
||||
|
||||
// This is a replacement for "*reinterpret_cast<volatile int*>(NULL) = 0;"
|
||||
// It is needed because GCC is allowed to assume that the program will
|
||||
// not execute any undefined behavior (UB) operation. Further, when GCC
|
||||
// observes that UB statement is reached, it can assume that all statements
|
||||
// leading to the UB one are never executed either, and can completely
|
||||
// optimize them out. In the case of ExceptionHandlerTest::ExternalDumper,
|
||||
// GCC-4.9 optimized out the entire set up of ExceptionHandler, causing
|
||||
// test failure.
|
||||
volatile int *p_null; // external linkage, so GCC can't tell that it
|
||||
// remains NULL. Volatile just for a good measure.
|
||||
static void DoNullPointerDereference() {
|
||||
*p_null = 1;
|
||||
}
|
||||
|
||||
void ChildCrash(bool use_fd) {
|
||||
AutoTempDir temp_dir;
|
||||
int fds[2] = {0};
|
||||
|
@ -202,7 +237,7 @@ void ChildCrash(bool use_fd) {
|
|||
true, -1));
|
||||
}
|
||||
// Crash with the exception handler in scope.
|
||||
*reinterpret_cast<volatile int*>(NULL) = 0;
|
||||
DoNullPointerDereference();
|
||||
}
|
||||
}
|
||||
if (!use_fd)
|
||||
|
@ -227,6 +262,8 @@ TEST(ExceptionHandlerTest, ChildCrashWithFD) {
|
|||
ASSERT_NO_FATAL_FAILURE(ChildCrash(true));
|
||||
}
|
||||
|
||||
#endif // !ADDRESS_SANITIZER
|
||||
|
||||
static bool DoneCallbackReturnFalse(const MinidumpDescriptor& descriptor,
|
||||
void* context,
|
||||
bool succeeded) {
|
||||
|
@ -268,13 +305,15 @@ static bool InstallRaiseSIGKILL() {
|
|||
return sigaction(SIGSEGV, &sa, NULL) != -1;
|
||||
}
|
||||
|
||||
#ifndef ADDRESS_SANITIZER
|
||||
|
||||
static void CrashWithCallbacks(ExceptionHandler::FilterCallback filter,
|
||||
ExceptionHandler::MinidumpCallback done,
|
||||
string path) {
|
||||
ExceptionHandler handler(
|
||||
MinidumpDescriptor(path), filter, done, NULL, true, -1);
|
||||
// Crash with the exception handler in scope.
|
||||
*reinterpret_cast<volatile int*>(NULL) = 0;
|
||||
DoNullPointerDereference();
|
||||
}
|
||||
|
||||
TEST(ExceptionHandlerTest, RedeliveryOnFilterCallbackFalse) {
|
||||
|
@ -365,7 +404,7 @@ TEST(ExceptionHandlerTest, RedeliveryOnBadSignalHandlerFlag) {
|
|||
reinterpret_cast<void*>(SIG_ERR));
|
||||
|
||||
// Crash with the exception handler in scope.
|
||||
*reinterpret_cast<volatile int*>(NULL) = 0;
|
||||
DoNullPointerDereference();
|
||||
}
|
||||
// SIGKILL means Breakpad's signal handler didn't crash.
|
||||
ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
|
||||
|
@ -435,6 +474,18 @@ TEST(ExceptionHandlerTest, StackedHandlersUnhandledToBottom) {
|
|||
ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL));
|
||||
}
|
||||
|
||||
#endif // !ADDRESS_SANITIZER
|
||||
|
||||
const unsigned char kIllegalInstruction[] = {
|
||||
#if defined(__mips__)
|
||||
// mfc2 zero,Impl - usually illegal in userspace.
|
||||
0x48, 0x00, 0x00, 0x48
|
||||
#else
|
||||
// This crashes with SIGILL on x86/x86-64/arm.
|
||||
0xff, 0xff, 0xff, 0xff
|
||||
#endif
|
||||
};
|
||||
|
||||
// Test that memory around the instruction pointer is written
|
||||
// to the dump as a MinidumpMemoryRegion.
|
||||
TEST(ExceptionHandlerTest, InstructionPointerMemory) {
|
||||
|
@ -446,8 +497,6 @@ TEST(ExceptionHandlerTest, InstructionPointerMemory) {
|
|||
// data from the minidump afterwards.
|
||||
const uint32_t kMemorySize = 256; // bytes
|
||||
const int kOffset = kMemorySize / 2;
|
||||
// This crashes with SIGILL on x86/x86-64/arm.
|
||||
const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
const pid_t child = fork();
|
||||
if (child == 0) {
|
||||
|
@ -469,7 +518,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemory) {
|
|||
// Write some instructions that will crash. Put them in the middle
|
||||
// of the block of memory, because the minidump should contain 128
|
||||
// bytes on either side of the instruction pointer.
|
||||
memcpy(memory + kOffset, instructions, sizeof(instructions));
|
||||
memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
|
||||
FlushInstructionCache(memory, kMemorySize);
|
||||
|
||||
// Now execute the instructions, which should crash.
|
||||
|
@ -517,12 +566,13 @@ TEST(ExceptionHandlerTest, InstructionPointerMemory) {
|
|||
ASSERT_TRUE(bytes);
|
||||
|
||||
uint8_t prefix_bytes[kOffset];
|
||||
uint8_t suffix_bytes[kMemorySize - kOffset - sizeof(instructions)];
|
||||
uint8_t suffix_bytes[kMemorySize - kOffset - sizeof(kIllegalInstruction)];
|
||||
memset(prefix_bytes, 0, sizeof(prefix_bytes));
|
||||
memset(suffix_bytes, 0, sizeof(suffix_bytes));
|
||||
EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset, instructions, sizeof(instructions)) == 0);
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(instructions),
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset, kIllegalInstruction,
|
||||
sizeof(kIllegalInstruction)) == 0);
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(kIllegalInstruction),
|
||||
suffix_bytes, sizeof(suffix_bytes)) == 0);
|
||||
|
||||
unlink(minidump_path.c_str());
|
||||
|
@ -539,8 +589,6 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMinBound) {
|
|||
// data from the minidump afterwards.
|
||||
const uint32_t kMemorySize = 256; // bytes
|
||||
const int kOffset = 0;
|
||||
// This crashes with SIGILL on x86/x86-64/arm.
|
||||
const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
const pid_t child = fork();
|
||||
if (child == 0) {
|
||||
|
@ -562,7 +610,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMinBound) {
|
|||
// Write some instructions that will crash. Put them in the middle
|
||||
// of the block of memory, because the minidump should contain 128
|
||||
// bytes on either side of the instruction pointer.
|
||||
memcpy(memory + kOffset, instructions, sizeof(instructions));
|
||||
memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
|
||||
FlushInstructionCache(memory, kMemorySize);
|
||||
|
||||
// Now execute the instructions, which should crash.
|
||||
|
@ -609,10 +657,11 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMinBound) {
|
|||
const uint8_t* bytes = region->GetMemory();
|
||||
ASSERT_TRUE(bytes);
|
||||
|
||||
uint8_t suffix_bytes[kMemorySize / 2 - sizeof(instructions)];
|
||||
uint8_t suffix_bytes[kMemorySize / 2 - sizeof(kIllegalInstruction)];
|
||||
memset(suffix_bytes, 0, sizeof(suffix_bytes));
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset, instructions, sizeof(instructions)) == 0);
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(instructions),
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset, kIllegalInstruction,
|
||||
sizeof(kIllegalInstruction)) == 0);
|
||||
EXPECT_TRUE(memcmp(bytes + kOffset + sizeof(kIllegalInstruction),
|
||||
suffix_bytes, sizeof(suffix_bytes)) == 0);
|
||||
unlink(minidump_path.c_str());
|
||||
}
|
||||
|
@ -630,9 +679,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
|
|||
// if a smaller size is requested, and this test wants to
|
||||
// test the upper bound of the memory range.
|
||||
const uint32_t kMemorySize = 4096; // bytes
|
||||
// This crashes with SIGILL on x86/x86-64/arm.
|
||||
const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff };
|
||||
const int kOffset = kMemorySize - sizeof(instructions);
|
||||
const int kOffset = kMemorySize - sizeof(kIllegalInstruction);
|
||||
|
||||
const pid_t child = fork();
|
||||
if (child == 0) {
|
||||
|
@ -654,7 +701,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
|
|||
// Write some instructions that will crash. Put them in the middle
|
||||
// of the block of memory, because the minidump should contain 128
|
||||
// bytes on either side of the instruction pointer.
|
||||
memcpy(memory + kOffset, instructions, sizeof(instructions));
|
||||
memcpy(memory + kOffset, kIllegalInstruction, sizeof(kIllegalInstruction));
|
||||
FlushInstructionCache(memory, kMemorySize);
|
||||
|
||||
// Now execute the instructions, which should crash.
|
||||
|
@ -697,7 +744,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
|
|||
ASSERT_TRUE(region);
|
||||
|
||||
const size_t kPrefixSize = 128; // bytes
|
||||
EXPECT_EQ(kPrefixSize + sizeof(instructions), region->GetSize());
|
||||
EXPECT_EQ(kPrefixSize + sizeof(kIllegalInstruction), region->GetSize());
|
||||
const uint8_t* bytes = region->GetMemory();
|
||||
ASSERT_TRUE(bytes);
|
||||
|
||||
|
@ -705,15 +752,11 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
|
|||
memset(prefix_bytes, 0, sizeof(prefix_bytes));
|
||||
EXPECT_TRUE(memcmp(bytes, prefix_bytes, sizeof(prefix_bytes)) == 0);
|
||||
EXPECT_TRUE(memcmp(bytes + kPrefixSize,
|
||||
instructions, sizeof(instructions)) == 0);
|
||||
kIllegalInstruction, sizeof(kIllegalInstruction)) == 0);
|
||||
|
||||
unlink(minidump_path.c_str());
|
||||
}
|
||||
|
||||
// If AddressSanitizer is used, NULL pointer dereferences generate SIGILL
|
||||
// (illegal instruction) instead of SIGSEGV (segmentation fault). Also,
|
||||
// the number of memory regions differs, so there is no point in running
|
||||
// this test if AddressSanitizer is used.
|
||||
#ifndef ADDRESS_SANITIZER
|
||||
|
||||
// Ensure that an extra memory block doesn't get added when the instruction
|
||||
|
@ -731,8 +774,13 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryNullPointer) {
|
|||
true, -1);
|
||||
// Try calling a NULL pointer.
|
||||
typedef void (*void_function)(void);
|
||||
void_function memory_function = reinterpret_cast<void_function>(NULL);
|
||||
// Volatile markings are needed to keep Clang from generating invalid
|
||||
// opcodes. See http://crbug.com/498354 for details.
|
||||
volatile void_function memory_function =
|
||||
reinterpret_cast<void_function>(NULL);
|
||||
memory_function();
|
||||
// not reached
|
||||
exit(1);
|
||||
}
|
||||
close(fds[1]);
|
||||
|
||||
|
@ -760,7 +808,8 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryNullPointer) {
|
|||
|
||||
unlink(minidump_path.c_str());
|
||||
}
|
||||
#endif // !ADDRESS_SANITIZER
|
||||
|
||||
#endif // !ADDRESS_SANITIZER
|
||||
|
||||
// Test that anonymous memory maps can be annotated with names and IDs.
|
||||
TEST(ExceptionHandlerTest, ModuleInfo) {
|
||||
|
@ -881,6 +930,8 @@ CrashHandler(const void* crash_context, size_t crash_context_size,
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifndef ADDRESS_SANITIZER
|
||||
|
||||
TEST(ExceptionHandlerTest, ExternalDumper) {
|
||||
int fds[2];
|
||||
ASSERT_NE(socketpair(AF_UNIX, SOCK_DGRAM, 0, fds), -1);
|
||||
|
@ -894,7 +945,7 @@ TEST(ExceptionHandlerTest, ExternalDumper) {
|
|||
ExceptionHandler handler(MinidumpDescriptor("/tmp1"), NULL, NULL,
|
||||
reinterpret_cast<void*>(fds[1]), true, -1);
|
||||
handler.set_crash_handler(CrashHandler);
|
||||
*reinterpret_cast<volatile int*>(NULL) = 0;
|
||||
DoNullPointerDereference();
|
||||
}
|
||||
close(fds[1]);
|
||||
struct msghdr msg = {0};
|
||||
|
@ -913,7 +964,7 @@ TEST(ExceptionHandlerTest, ExternalDumper) {
|
|||
const ssize_t n = HANDLE_EINTR(recvmsg(fds[0], &msg, 0));
|
||||
ASSERT_EQ(static_cast<ssize_t>(kCrashContextSize), n);
|
||||
ASSERT_EQ(kControlMsgSize, msg.msg_controllen);
|
||||
ASSERT_EQ(static_cast<typeof(msg.msg_flags)>(0), msg.msg_flags);
|
||||
ASSERT_EQ(static_cast<__typeof__(msg.msg_flags)>(0), msg.msg_flags);
|
||||
ASSERT_EQ(0, close(fds[0]));
|
||||
|
||||
pid_t crashing_pid = -1;
|
||||
|
@ -953,6 +1004,8 @@ TEST(ExceptionHandlerTest, ExternalDumper) {
|
|||
unlink(templ.c_str());
|
||||
}
|
||||
|
||||
#endif // !ADDRESS_SANITIZER
|
||||
|
||||
TEST(ExceptionHandlerTest, WriteMinidumpExceptionStream) {
|
||||
AutoTempDir temp_dir;
|
||||
ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, NULL,
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// Copyright (c) 2008, Google Inc.
|
||||
// Copyright 2015 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
|
@ -14,7 +14,7 @@
|
|||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
@ -27,25 +27,22 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// ---
|
||||
// Author: Jacob Hoffman-Andrews
|
||||
#ifndef CLIENT_LINUX_HANDLER_MICRODUMP_EXTRA_INFO_H_
|
||||
#define CLIENT_LINUX_HANDLER_MICRODUMP_EXTRA_INFO_H_
|
||||
|
||||
#ifndef _GOOGLEINIT_H
|
||||
#define _GOOGLEINIT_H
|
||||
namespace google_breakpad {
|
||||
|
||||
class GoogleInitializer {
|
||||
public:
|
||||
typedef void (*void_function)(void);
|
||||
GoogleInitializer(const char* name, void_function f) {
|
||||
f();
|
||||
}
|
||||
struct MicrodumpExtraInfo {
|
||||
// Strings pointed to by this struct are not copied, and are
|
||||
// expected to remain valid for the lifetime of the process.
|
||||
const char* build_fingerprint;
|
||||
const char* product_info;
|
||||
const char* gpu_fingerprint;
|
||||
|
||||
MicrodumpExtraInfo()
|
||||
: build_fingerprint(NULL), product_info(NULL), gpu_fingerprint(NULL) {}
|
||||
};
|
||||
|
||||
#define REGISTER_MODULE_INITIALIZER(name, body) \
|
||||
namespace { \
|
||||
static void google_init_module_##name () { body; } \
|
||||
GoogleInitializer google_initializer_module_##name(#name, \
|
||||
google_init_module_##name); \
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _GOOGLEINIT_H */
|
||||
#endif // CLIENT_LINUX_HANDLER_MICRODUMP_EXTRA_INFO_H_
|
|
@ -35,11 +35,17 @@
|
|||
|
||||
namespace google_breakpad {
|
||||
|
||||
//static
|
||||
const MinidumpDescriptor::MicrodumpOnConsole
|
||||
MinidumpDescriptor::kMicrodumpOnConsole = {};
|
||||
|
||||
MinidumpDescriptor::MinidumpDescriptor(const MinidumpDescriptor& descriptor)
|
||||
: fd_(descriptor.fd_),
|
||||
: mode_(descriptor.mode_),
|
||||
fd_(descriptor.fd_),
|
||||
directory_(descriptor.directory_),
|
||||
c_path_(NULL),
|
||||
size_limit_(descriptor.size_limit_) {
|
||||
size_limit_(descriptor.size_limit_),
|
||||
microdump_extra_info_(descriptor.microdump_extra_info_) {
|
||||
// The copy constructor is not allowed to be called on a MinidumpDescriptor
|
||||
// with a valid path_, as getting its c_path_ would require the heap which
|
||||
// can cause problems in compromised environments.
|
||||
|
@ -50,6 +56,7 @@ MinidumpDescriptor& MinidumpDescriptor::operator=(
|
|||
const MinidumpDescriptor& descriptor) {
|
||||
assert(descriptor.path_.empty());
|
||||
|
||||
mode_ = descriptor.mode_;
|
||||
fd_ = descriptor.fd_;
|
||||
directory_ = descriptor.directory_;
|
||||
path_.clear();
|
||||
|
@ -59,11 +66,12 @@ MinidumpDescriptor& MinidumpDescriptor::operator=(
|
|||
UpdatePath();
|
||||
}
|
||||
size_limit_ = descriptor.size_limit_;
|
||||
microdump_extra_info_ = descriptor.microdump_extra_info_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void MinidumpDescriptor::UpdatePath() {
|
||||
assert(fd_ == -1 && !directory_.empty());
|
||||
assert(mode_ == kWriteMinidumpToFile && !directory_.empty());
|
||||
|
||||
GUID guid;
|
||||
char guid_str[kGUIDStringLength + 1];
|
||||
|
@ -72,7 +80,7 @@ void MinidumpDescriptor::UpdatePath() {
|
|||
}
|
||||
|
||||
path_.clear();
|
||||
path_ = directory_ + "/" + guid_str + ".dmp";
|
||||
path_ = directory_ + "/" + guid_str + ".dmp";
|
||||
c_path_ = path_.c_str();
|
||||
}
|
||||
|
||||
|
|
|
@ -35,20 +35,29 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "client/linux/handler/microdump_extra_info.h"
|
||||
#include "common/using_std_string.h"
|
||||
|
||||
// The MinidumpDescriptor describes how to access a minidump: it can contain
|
||||
// either a file descriptor or a path.
|
||||
// Note that when using files, it is created with the path to a directory.
|
||||
// The actual path where the minidump is generated is created by this class.
|
||||
// This class describes how a crash dump should be generated, either:
|
||||
// - Writing a full minidump to a file in a given directory (the actual path,
|
||||
// inside the directory, is determined by this class).
|
||||
// - Writing a full minidump to a given fd.
|
||||
// - Writing a reduced microdump to the console (logcat on Android).
|
||||
namespace google_breakpad {
|
||||
|
||||
class MinidumpDescriptor {
|
||||
public:
|
||||
MinidumpDescriptor() : fd_(-1), size_limit_(-1) {}
|
||||
struct MicrodumpOnConsole {};
|
||||
static const MicrodumpOnConsole kMicrodumpOnConsole;
|
||||
|
||||
MinidumpDescriptor()
|
||||
: mode_(kUninitialized),
|
||||
fd_(-1),
|
||||
size_limit_(-1) {}
|
||||
|
||||
explicit MinidumpDescriptor(const string& directory)
|
||||
: fd_(-1),
|
||||
: mode_(kWriteMinidumpToFile),
|
||||
fd_(-1),
|
||||
directory_(directory),
|
||||
c_path_(NULL),
|
||||
size_limit_(-1) {
|
||||
|
@ -56,16 +65,24 @@ class MinidumpDescriptor {
|
|||
}
|
||||
|
||||
explicit MinidumpDescriptor(int fd)
|
||||
: fd_(fd),
|
||||
: mode_(kWriteMinidumpToFd),
|
||||
fd_(fd),
|
||||
c_path_(NULL),
|
||||
size_limit_(-1) {
|
||||
assert(fd != -1);
|
||||
}
|
||||
|
||||
explicit MinidumpDescriptor(const MicrodumpOnConsole&)
|
||||
: mode_(kWriteMicrodumpToConsole),
|
||||
fd_(-1),
|
||||
size_limit_(-1) {}
|
||||
|
||||
explicit MinidumpDescriptor(const MinidumpDescriptor& descriptor);
|
||||
MinidumpDescriptor& operator=(const MinidumpDescriptor& descriptor);
|
||||
|
||||
bool IsFD() const { return fd_ != -1; }
|
||||
static MinidumpDescriptor getMicrodumpDescriptor();
|
||||
|
||||
bool IsFD() const { return mode_ == kWriteMinidumpToFd; }
|
||||
|
||||
int fd() const { return fd_; }
|
||||
|
||||
|
@ -73,6 +90,10 @@ class MinidumpDescriptor {
|
|||
|
||||
const char* path() const { return c_path_; }
|
||||
|
||||
bool IsMicrodumpOnConsole() const {
|
||||
return mode_ == kWriteMicrodumpToConsole;
|
||||
}
|
||||
|
||||
// Updates the path so it is unique.
|
||||
// Should be called from a normal context: this methods uses the heap.
|
||||
void UpdatePath();
|
||||
|
@ -80,19 +101,47 @@ class MinidumpDescriptor {
|
|||
off_t size_limit() const { return size_limit_; }
|
||||
void set_size_limit(off_t limit) { size_limit_ = limit; }
|
||||
|
||||
MicrodumpExtraInfo* microdump_extra_info() {
|
||||
assert(IsMicrodumpOnConsole());
|
||||
return µdump_extra_info_;
|
||||
};
|
||||
|
||||
private:
|
||||
enum DumpMode {
|
||||
kUninitialized = 0,
|
||||
kWriteMinidumpToFile,
|
||||
kWriteMinidumpToFd,
|
||||
kWriteMicrodumpToConsole
|
||||
};
|
||||
|
||||
// Specifies the dump mode (see DumpMode).
|
||||
DumpMode mode_;
|
||||
|
||||
// The file descriptor where the minidump is generated.
|
||||
int fd_;
|
||||
|
||||
// The directory where the minidump should be generated.
|
||||
string directory_;
|
||||
|
||||
// The full path to the generated minidump.
|
||||
string path_;
|
||||
|
||||
// The C string of |path_|. Precomputed so it can be access from a compromised
|
||||
// context.
|
||||
const char* c_path_;
|
||||
|
||||
off_t size_limit_;
|
||||
|
||||
// The extra microdump data (e.g. product name/version, build
|
||||
// fingerprint, gpu fingerprint) that should be appended to the dump
|
||||
// (microdump only). Microdumps don't have the ability of appending
|
||||
// extra metadata after the dump is generated (as opposite to
|
||||
// minidumps MIME fields), therefore the extra data must be provided
|
||||
// upfront. Any memory pointed to by members of the
|
||||
// MicrodumpExtraInfo struct must be valid for the lifetime of the
|
||||
// process (read: the caller has to guarantee that it is stored in
|
||||
// global static storage.)
|
||||
MicrodumpExtraInfo microdump_extra_info_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'../log/log.cc',
|
||||
'exception_handler.cc',
|
||||
'minidump_descriptor.cc',
|
||||
]
|
||||
|
||||
# We allow warnings for third-party code that can be updated from upstream.
|
||||
ALLOW_COMPILER_WARNINGS = True
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['OS_TARGET'] == 'Android':
|
||||
# NDK5 workarounds
|
||||
DEFINES['_STLP_CONST_CONSTRUCTOR_BUG'] = True
|
||||
DEFINES['_STLP_NO_MEMBER_TEMPLATES'] = True
|
||||
LOCAL_INCLUDES += [
|
||||
'/toolkit/crashreporter/google-breakpad/src/common/android/include',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/toolkit/crashreporter/google-breakpad/src',
|
||||
]
|
||||
|
||||
include('/toolkit/crashreporter/crashreporter.mozbuild')
|
|
@ -31,15 +31,51 @@
|
|||
|
||||
#if defined(__ANDROID__)
|
||||
#include <android/log.h>
|
||||
#include <dlfcn.h>
|
||||
#else
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
#endif
|
||||
|
||||
namespace logger {
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
namespace {
|
||||
|
||||
// __android_log_buf_write() is not exported in the NDK and is being used by
|
||||
// dynamic runtime linking. Its declaration is taken from Android's
|
||||
// system/core/include/log/log.h.
|
||||
using AndroidLogBufferWriteFunc = int (*)(int bufID, int prio, const char *tag,
|
||||
const char *text);
|
||||
const int kAndroidCrashLogId = 4; // From LOG_ID_CRASH in log.h.
|
||||
const char kAndroidLogTag[] = "google-breakpad";
|
||||
|
||||
bool g_crash_log_initialized = false;
|
||||
AndroidLogBufferWriteFunc g_android_log_buf_write = nullptr;
|
||||
|
||||
} // namespace
|
||||
|
||||
void initializeCrashLogWriter() {
|
||||
if (g_crash_log_initialized)
|
||||
return;
|
||||
g_android_log_buf_write = reinterpret_cast<AndroidLogBufferWriteFunc>(
|
||||
dlsym(RTLD_DEFAULT, "__android_log_buf_write"));
|
||||
g_crash_log_initialized = true;
|
||||
}
|
||||
|
||||
int writeToCrashLog(const char* buf) {
|
||||
// Try writing to the crash log ring buffer. If not available, fall back to
|
||||
// the standard log buffer.
|
||||
if (g_android_log_buf_write) {
|
||||
return g_android_log_buf_write(kAndroidCrashLogId, ANDROID_LOG_FATAL,
|
||||
kAndroidLogTag, buf);
|
||||
}
|
||||
return __android_log_write(ANDROID_LOG_FATAL, kAndroidLogTag, buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
int write(const char* buf, size_t nbytes) {
|
||||
#if defined(__ANDROID__)
|
||||
return __android_log_write(ANDROID_LOG_WARN, "google-breakpad", buf);
|
||||
return __android_log_write(ANDROID_LOG_WARN, kAndroidLogTag, buf);
|
||||
#else
|
||||
return sys_write(2, buf, nbytes);
|
||||
#endif
|
||||
|
|
|
@ -36,6 +36,20 @@ namespace logger {
|
|||
|
||||
int write(const char* buf, size_t nbytes);
|
||||
|
||||
// In the case of Android the log can be written to the default system log
|
||||
// (default behavior of write() above, or to the crash log (see
|
||||
// writeToCrashLog() below).
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
// The logger must be initialized in a non-compromised context.
|
||||
void initializeCrashLogWriter();
|
||||
|
||||
// Once initialized, writeToCrashLog is safe to use in a compromised context,
|
||||
// even if the initialization failed, in which case this will silently fall
|
||||
// back on write().
|
||||
int writeToCrashLog(const char* buf);
|
||||
#endif
|
||||
|
||||
} // namespace logger
|
||||
|
||||
#endif // CLIENT_LINUX_LOG_LOG_H_
|
||||
|
|
|
@ -0,0 +1,433 @@
|
|||
// Copyright (c) 2014, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// This translation unit generates microdumps into the console (logcat on
|
||||
// Android). See crbug.com/410294 for more info and design docs.
|
||||
|
||||
#include "client/linux/microdump_writer/microdump_writer.h"
|
||||
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include "client/linux/dump_writer_common/thread_info.h"
|
||||
#include "client/linux/dump_writer_common/ucontext_reader.h"
|
||||
#include "client/linux/handler/exception_handler.h"
|
||||
#include "client/linux/handler/microdump_extra_info.h"
|
||||
#include "client/linux/log/log.h"
|
||||
#include "client/linux/minidump_writer/linux_ptrace_dumper.h"
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using google_breakpad::ExceptionHandler;
|
||||
using google_breakpad::LinuxDumper;
|
||||
using google_breakpad::LinuxPtraceDumper;
|
||||
using google_breakpad::MappingInfo;
|
||||
using google_breakpad::MappingList;
|
||||
using google_breakpad::MicrodumpExtraInfo;
|
||||
using google_breakpad::RawContextCPU;
|
||||
using google_breakpad::ThreadInfo;
|
||||
using google_breakpad::UContextReader;
|
||||
|
||||
const size_t kLineBufferSize = 2048;
|
||||
|
||||
class MicrodumpWriter {
|
||||
public:
|
||||
MicrodumpWriter(const ExceptionHandler::CrashContext* context,
|
||||
const MappingList& mappings,
|
||||
const MicrodumpExtraInfo& microdump_extra_info,
|
||||
LinuxDumper* dumper)
|
||||
: ucontext_(context ? &context->context : NULL),
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
float_state_(context ? &context->float_state : NULL),
|
||||
#endif
|
||||
dumper_(dumper),
|
||||
mapping_list_(mappings),
|
||||
microdump_extra_info_(microdump_extra_info),
|
||||
log_line_(NULL) {
|
||||
log_line_ = reinterpret_cast<char*>(Alloc(kLineBufferSize));
|
||||
if (log_line_)
|
||||
log_line_[0] = '\0'; // Clear out the log line buffer.
|
||||
}
|
||||
|
||||
~MicrodumpWriter() { dumper_->ThreadsResume(); }
|
||||
|
||||
bool Init() {
|
||||
// In the exceptional case where the system was out of memory and there
|
||||
// wasn't even room to allocate the line buffer, bail out. There is nothing
|
||||
// useful we can possibly achieve without the ability to Log. At least let's
|
||||
// try to not crash.
|
||||
if (!dumper_->Init() || !log_line_)
|
||||
return false;
|
||||
return dumper_->ThreadsSuspend() && dumper_->LateInit();
|
||||
}
|
||||
|
||||
bool Dump() {
|
||||
bool success;
|
||||
LogLine("-----BEGIN BREAKPAD MICRODUMP-----");
|
||||
DumpProductInformation();
|
||||
DumpOSInformation();
|
||||
DumpGPUInformation();
|
||||
success = DumpCrashingThread();
|
||||
if (success)
|
||||
success = DumpMappings();
|
||||
LogLine("-----END BREAKPAD MICRODUMP-----");
|
||||
dumper_->ThreadsResume();
|
||||
return success;
|
||||
}
|
||||
|
||||
private:
|
||||
// Writes one line to the system log.
|
||||
void LogLine(const char* msg) {
|
||||
#if defined(__ANDROID__)
|
||||
logger::writeToCrashLog(msg);
|
||||
#else
|
||||
logger::write(msg, my_strlen(msg));
|
||||
logger::write("\n", 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Stages the given string in the current line buffer.
|
||||
void LogAppend(const char* str) {
|
||||
my_strlcat(log_line_, str, kLineBufferSize);
|
||||
}
|
||||
|
||||
// As above (required to take precedence over template specialization below).
|
||||
void LogAppend(char* str) {
|
||||
LogAppend(const_cast<const char*>(str));
|
||||
}
|
||||
|
||||
// Stages the hex repr. of the given int type in the current line buffer.
|
||||
template<typename T>
|
||||
void LogAppend(T value) {
|
||||
// Make enough room to hex encode the largest int type + NUL.
|
||||
static const char HEX[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
char hexstr[sizeof(T) * 2 + 1];
|
||||
for (int i = sizeof(T) * 2 - 1; i >= 0; --i, value >>= 4)
|
||||
hexstr[i] = HEX[static_cast<uint8_t>(value) & 0x0F];
|
||||
hexstr[sizeof(T) * 2] = '\0';
|
||||
LogAppend(hexstr);
|
||||
}
|
||||
|
||||
// Stages the buffer content hex-encoded in the current line buffer.
|
||||
void LogAppend(const void* buf, size_t length) {
|
||||
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(buf);
|
||||
for (size_t i = 0; i < length; ++i, ++ptr)
|
||||
LogAppend(*ptr);
|
||||
}
|
||||
|
||||
// Writes out the current line buffer on the system log.
|
||||
void LogCommitLine() {
|
||||
LogLine(log_line_);
|
||||
my_strlcpy(log_line_, "", kLineBufferSize);
|
||||
}
|
||||
|
||||
void DumpProductInformation() {
|
||||
LogAppend("V ");
|
||||
if (microdump_extra_info_.product_info) {
|
||||
LogAppend(microdump_extra_info_.product_info);
|
||||
} else {
|
||||
LogAppend("UNKNOWN:0.0.0.0");
|
||||
}
|
||||
LogCommitLine();
|
||||
}
|
||||
|
||||
void DumpOSInformation() {
|
||||
const uint8_t n_cpus = static_cast<uint8_t>(sysconf(_SC_NPROCESSORS_CONF));
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
const char kOSId[] = "A";
|
||||
#else
|
||||
const char kOSId[] = "L";
|
||||
#endif
|
||||
|
||||
// Dump the runtime architecture. On multiarch devices it might not match the
|
||||
// hw architecture (the one returned by uname()), for instance in the case of
|
||||
// a 32-bit app running on a aarch64 device.
|
||||
#if defined(__aarch64__)
|
||||
const char kArch[] = "arm64";
|
||||
#elif defined(__ARMEL__)
|
||||
const char kArch[] = "arm";
|
||||
#elif defined(__x86_64__)
|
||||
const char kArch[] = "x86_64";
|
||||
#elif defined(__i386__)
|
||||
const char kArch[] = "x86";
|
||||
#elif defined(__mips__)
|
||||
const char kArch[] = "mips";
|
||||
#else
|
||||
#error "This code has not been ported to your platform yet"
|
||||
#endif
|
||||
|
||||
LogAppend("O ");
|
||||
LogAppend(kOSId);
|
||||
LogAppend(" ");
|
||||
LogAppend(kArch);
|
||||
LogAppend(" ");
|
||||
LogAppend(n_cpus);
|
||||
LogAppend(" ");
|
||||
|
||||
// Dump the HW architecture (e.g., armv7l, aarch64).
|
||||
struct utsname uts;
|
||||
const bool has_uts_info = (uname(&uts) == 0);
|
||||
const char* hwArch = has_uts_info ? uts.machine : "unknown_hw_arch";
|
||||
LogAppend(hwArch);
|
||||
LogAppend(" ");
|
||||
|
||||
// If the client has attached a build fingerprint to the MinidumpDescriptor
|
||||
// use that one. Otherwise try to get some basic info from uname().
|
||||
if (microdump_extra_info_.build_fingerprint) {
|
||||
LogAppend(microdump_extra_info_.build_fingerprint);
|
||||
} else if (has_uts_info) {
|
||||
LogAppend(uts.release);
|
||||
LogAppend(" ");
|
||||
LogAppend(uts.version);
|
||||
} else {
|
||||
LogAppend("no build fingerprint available");
|
||||
}
|
||||
LogCommitLine();
|
||||
}
|
||||
|
||||
void DumpGPUInformation() {
|
||||
LogAppend("G ");
|
||||
if (microdump_extra_info_.gpu_fingerprint) {
|
||||
LogAppend(microdump_extra_info_.gpu_fingerprint);
|
||||
} else {
|
||||
LogAppend("UNKNOWN");
|
||||
}
|
||||
LogCommitLine();
|
||||
}
|
||||
|
||||
bool DumpThreadStack(uint32_t thread_id,
|
||||
uintptr_t stack_pointer,
|
||||
int max_stack_len,
|
||||
uint8_t** stack_copy) {
|
||||
*stack_copy = NULL;
|
||||
const void* stack;
|
||||
size_t stack_len;
|
||||
|
||||
if (!dumper_->GetStackInfo(&stack, &stack_len, stack_pointer)) {
|
||||
// The stack pointer might not be available. In this case we don't hard
|
||||
// fail, just produce a (almost useless) microdump w/o a stack section.
|
||||
return true;
|
||||
}
|
||||
|
||||
LogAppend("S 0 ");
|
||||
LogAppend(stack_pointer);
|
||||
LogAppend(" ");
|
||||
LogAppend(reinterpret_cast<uintptr_t>(stack));
|
||||
LogAppend(" ");
|
||||
LogAppend(stack_len);
|
||||
LogCommitLine();
|
||||
|
||||
if (max_stack_len >= 0 &&
|
||||
stack_len > static_cast<unsigned int>(max_stack_len)) {
|
||||
stack_len = max_stack_len;
|
||||
}
|
||||
|
||||
*stack_copy = reinterpret_cast<uint8_t*>(Alloc(stack_len));
|
||||
dumper_->CopyFromProcess(*stack_copy, thread_id, stack, stack_len);
|
||||
|
||||
// Dump the content of the stack, splicing it into chunks which size is
|
||||
// compatible with the max logcat line size (see LOGGER_ENTRY_MAX_PAYLOAD).
|
||||
const size_t STACK_DUMP_CHUNK_SIZE = 384;
|
||||
for (size_t stack_off = 0; stack_off < stack_len;
|
||||
stack_off += STACK_DUMP_CHUNK_SIZE) {
|
||||
LogAppend("S ");
|
||||
LogAppend(reinterpret_cast<uintptr_t>(stack) + stack_off);
|
||||
LogAppend(" ");
|
||||
LogAppend(*stack_copy + stack_off,
|
||||
std::min(STACK_DUMP_CHUNK_SIZE, stack_len - stack_off));
|
||||
LogCommitLine();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write information about the crashing thread.
|
||||
bool DumpCrashingThread() {
|
||||
const unsigned num_threads = dumper_->threads().size();
|
||||
|
||||
for (unsigned i = 0; i < num_threads; ++i) {
|
||||
MDRawThread thread;
|
||||
my_memset(&thread, 0, sizeof(thread));
|
||||
thread.thread_id = dumper_->threads()[i];
|
||||
|
||||
// Dump only the crashing thread.
|
||||
if (static_cast<pid_t>(thread.thread_id) != dumper_->crash_thread())
|
||||
continue;
|
||||
|
||||
assert(ucontext_);
|
||||
assert(!dumper_->IsPostMortem());
|
||||
|
||||
uint8_t* stack_copy;
|
||||
const uintptr_t stack_ptr = UContextReader::GetStackPointer(ucontext_);
|
||||
if (!DumpThreadStack(thread.thread_id, stack_ptr, -1, &stack_copy))
|
||||
return false;
|
||||
|
||||
RawContextCPU cpu;
|
||||
my_memset(&cpu, 0, sizeof(RawContextCPU));
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
UContextReader::FillCPUContext(&cpu, ucontext_, float_state_);
|
||||
#else
|
||||
UContextReader::FillCPUContext(&cpu, ucontext_);
|
||||
#endif
|
||||
DumpCPUState(&cpu);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DumpCPUState(RawContextCPU* cpu) {
|
||||
LogAppend("C ");
|
||||
LogAppend(cpu, sizeof(*cpu));
|
||||
LogCommitLine();
|
||||
}
|
||||
|
||||
// If there is caller-provided information about this mapping
|
||||
// in the mapping_list_ list, return true. Otherwise, return false.
|
||||
bool HaveMappingInfo(const MappingInfo& mapping) {
|
||||
for (MappingList::const_iterator iter = mapping_list_.begin();
|
||||
iter != mapping_list_.end();
|
||||
++iter) {
|
||||
// Ignore any mappings that are wholly contained within
|
||||
// mappings in the mapping_info_ list.
|
||||
if (mapping.start_addr >= iter->first.start_addr &&
|
||||
(mapping.start_addr + mapping.size) <=
|
||||
(iter->first.start_addr + iter->first.size)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Dump information about the provided |mapping|. If |identifier| is non-NULL,
|
||||
// use it instead of calculating a file ID from the mapping.
|
||||
void DumpModule(const MappingInfo& mapping,
|
||||
bool member,
|
||||
unsigned int mapping_id,
|
||||
const uint8_t* identifier) {
|
||||
MDGUID module_identifier;
|
||||
if (identifier) {
|
||||
// GUID was provided by caller.
|
||||
my_memcpy(&module_identifier, identifier, sizeof(MDGUID));
|
||||
} else {
|
||||
dumper_->ElfFileIdentifierForMapping(
|
||||
mapping,
|
||||
member,
|
||||
mapping_id,
|
||||
reinterpret_cast<uint8_t*>(&module_identifier));
|
||||
}
|
||||
|
||||
char file_name[NAME_MAX];
|
||||
char file_path[NAME_MAX];
|
||||
LinuxDumper::GetMappingEffectiveNameAndPath(
|
||||
mapping, file_path, sizeof(file_path), file_name, sizeof(file_name));
|
||||
|
||||
LogAppend("M ");
|
||||
LogAppend(static_cast<uintptr_t>(mapping.start_addr));
|
||||
LogAppend(" ");
|
||||
LogAppend(mapping.offset);
|
||||
LogAppend(" ");
|
||||
LogAppend(mapping.size);
|
||||
LogAppend(" ");
|
||||
LogAppend(module_identifier.data1);
|
||||
LogAppend(module_identifier.data2);
|
||||
LogAppend(module_identifier.data3);
|
||||
LogAppend(module_identifier.data4[0]);
|
||||
LogAppend(module_identifier.data4[1]);
|
||||
LogAppend(module_identifier.data4[2]);
|
||||
LogAppend(module_identifier.data4[3]);
|
||||
LogAppend(module_identifier.data4[4]);
|
||||
LogAppend(module_identifier.data4[5]);
|
||||
LogAppend(module_identifier.data4[6]);
|
||||
LogAppend(module_identifier.data4[7]);
|
||||
LogAppend("0 "); // Age is always 0 on Linux.
|
||||
LogAppend(file_name);
|
||||
LogCommitLine();
|
||||
}
|
||||
|
||||
// Write information about the mappings in effect.
|
||||
bool DumpMappings() {
|
||||
// First write all the mappings from the dumper
|
||||
for (unsigned i = 0; i < dumper_->mappings().size(); ++i) {
|
||||
const MappingInfo& mapping = *dumper_->mappings()[i];
|
||||
if (mapping.name[0] == 0 || // only want modules with filenames.
|
||||
!mapping.exec || // only want executable mappings.
|
||||
mapping.size < 4096 || // too small to get a signature for.
|
||||
HaveMappingInfo(mapping)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DumpModule(mapping, true, i, NULL);
|
||||
}
|
||||
// Next write all the mappings provided by the caller
|
||||
for (MappingList::const_iterator iter = mapping_list_.begin();
|
||||
iter != mapping_list_.end();
|
||||
++iter) {
|
||||
DumpModule(iter->first, false, 0, iter->second);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void* Alloc(unsigned bytes) { return dumper_->allocator()->Alloc(bytes); }
|
||||
|
||||
const struct ucontext* const ucontext_;
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
const google_breakpad::fpstate_t* const float_state_;
|
||||
#endif
|
||||
LinuxDumper* dumper_;
|
||||
const MappingList& mapping_list_;
|
||||
const MicrodumpExtraInfo microdump_extra_info_;
|
||||
char* log_line_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
bool WriteMicrodump(pid_t crashing_process,
|
||||
const void* blob,
|
||||
size_t blob_size,
|
||||
const MappingList& mappings,
|
||||
const MicrodumpExtraInfo& microdump_extra_info) {
|
||||
LinuxPtraceDumper dumper(crashing_process);
|
||||
const ExceptionHandler::CrashContext* context = NULL;
|
||||
if (blob) {
|
||||
if (blob_size != sizeof(ExceptionHandler::CrashContext))
|
||||
return false;
|
||||
context = reinterpret_cast<const ExceptionHandler::CrashContext*>(blob);
|
||||
dumper.set_crash_address(
|
||||
reinterpret_cast<uintptr_t>(context->siginfo.si_addr));
|
||||
dumper.set_crash_signal(context->siginfo.si_signo);
|
||||
dumper.set_crash_thread(context->tid);
|
||||
}
|
||||
MicrodumpWriter writer(context, mappings, microdump_extra_info, &dumper);
|
||||
if (!writer.Init())
|
||||
return false;
|
||||
return writer.Dump();
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2009, Google Inc.
|
||||
// Copyright (c) 2014, Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
|
@ -27,56 +27,39 @@
|
|||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Breakpad test application for Linux. When run, it generates one on-demand
|
||||
// minidump and then crashes, which should generate an on-crash minidump.
|
||||
// dump_syms can be used to extract symbol information for use in processing.
|
||||
#ifndef CLIENT_LINUX_MINIDUMP_WRITER_MICRODUMP_WRITER_H_
|
||||
#define CLIENT_LINUX_MINIDUMP_WRITER_MICRODUMP_WRITER_H_
|
||||
|
||||
// To build:
|
||||
// g++ -g -o linux_test_app -I ../../ -L../../client/linux linux_test_app.cc \
|
||||
// -lbreakpad
|
||||
// Add -m32 to build a 32-bit executable, or -m64 for a 64-bit one
|
||||
// (assuming your environment supports it). Replace -g with -gstabs+ to
|
||||
// generate an executable with STABS symbols (needs -m32), or -gdwarf-2 for one
|
||||
// with DWARF symbols (32- or 64-bit)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
#include "client/linux/dump_writer_common/mapping_info.h"
|
||||
|
||||
#include "client/linux/handler/exception_handler.h"
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
namespace google_breakpad {
|
||||
|
||||
namespace {
|
||||
struct MicrodumpExtraInfo;
|
||||
|
||||
// google_breakpad::MinidumpCallback to invoke after minidump generation.
|
||||
static bool callback(const char *dump_path, const char *id,
|
||||
void *context,
|
||||
bool succeeded) {
|
||||
if (succeeded) {
|
||||
printf("dump guid is %s\n", id);
|
||||
} else {
|
||||
printf("dump failed\n");
|
||||
}
|
||||
fflush(stdout);
|
||||
// Writes a microdump (a reduced dump containing only the state of the crashing
|
||||
// thread) on the console (logcat on Android). These functions do not malloc nor
|
||||
// use libc functions which may. Thus, it can be used in contexts where the
|
||||
// state of the heap may be corrupt.
|
||||
// Args:
|
||||
// crashing_process: the pid of the crashing process. This must be trusted.
|
||||
// blob: a blob of data from the crashing process. See exception_handler.h
|
||||
// blob_size: the length of |blob| in bytes.
|
||||
// mappings: a list of additional mappings provided by the application.
|
||||
// build_fingerprint: a (optional) C string which determines the OS
|
||||
// build fingerprint (e.g., aosp/occam/mako:5.1.1/LMY47W/1234:eng/dev-keys).
|
||||
// product_info: a (optional) C string which determines the product name and
|
||||
// version (e.g., WebView:42.0.2311.136).
|
||||
//
|
||||
// Returns true iff successful.
|
||||
bool WriteMicrodump(pid_t crashing_process,
|
||||
const void* blob,
|
||||
size_t blob_size,
|
||||
const MappingList& mappings,
|
||||
const MicrodumpExtraInfo& microdump_extra_info);
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
} // namespace google_breakpad
|
||||
|
||||
static void CrashFunction() {
|
||||
int *i = reinterpret_cast<int*>(0x45);
|
||||
*i = 5; // crash!
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
google_breakpad::ExceptionHandler eh(".", NULL, callback, NULL, true);
|
||||
if (!eh.WriteMinidump()) {
|
||||
printf("Failed to generate on-demand minidump\n");
|
||||
}
|
||||
CrashFunction();
|
||||
printf("did not crash?\n");
|
||||
return 0;
|
||||
}
|
||||
#endif // CLIENT_LINUX_MINIDUMP_WRITER_MICRODUMP_WRITER_H_
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче