diff options
Diffstat (limited to 'base/third_party/symbolize')
-rw-r--r-- | base/third_party/symbolize/DEPS | 3 | ||||
-rw-r--r-- | base/third_party/symbolize/LICENSE | 28 | ||||
-rw-r--r-- | base/third_party/symbolize/README.chromium | 17 | ||||
-rw-r--r-- | base/third_party/symbolize/config.h | 7 | ||||
-rw-r--r-- | base/third_party/symbolize/demangle.cc | 1231 | ||||
-rw-r--r-- | base/third_party/symbolize/demangle.h | 84 | ||||
-rw-r--r-- | base/third_party/symbolize/glog/logging.h | 5 | ||||
-rw-r--r-- | base/third_party/symbolize/glog/raw_logging.h | 6 | ||||
-rw-r--r-- | base/third_party/symbolize/symbolize.cc | 681 | ||||
-rw-r--r-- | base/third_party/symbolize/symbolize.h | 130 | ||||
-rw-r--r-- | base/third_party/symbolize/utilities.h | 11 |
11 files changed, 0 insertions, 2203 deletions
diff --git a/base/third_party/symbolize/DEPS b/base/third_party/symbolize/DEPS deleted file mode 100644 index 73eab50..0000000 --- a/base/third_party/symbolize/DEPS +++ /dev/null @@ -1,3 +0,0 @@ -include_rules = [ - "+glog", -] diff --git a/base/third_party/symbolize/LICENSE b/base/third_party/symbolize/LICENSE deleted file mode 100644 index 433a3d1..0000000 --- a/base/third_party/symbolize/LICENSE +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2006, 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. diff --git a/base/third_party/symbolize/README.chromium b/base/third_party/symbolize/README.chromium deleted file mode 100644 index 655f787..0000000 --- a/base/third_party/symbolize/README.chromium +++ /dev/null @@ -1,17 +0,0 @@ -Name: google-glog's symbolization library -URL: http://code.google.com/p/google-glog/ - -The following files are copied AS-IS from: -http://code.google.com/p/google-glog/source/browse/#svn/trunk/src (r76) - -- demangle.cc -- demangle.h -- symbolize.cc -- symbolize.h - -The following files are minimal stubs created for use in Chromium: - -- config.h -- glog/logging.h -- glog/raw_logging.h -- utilities.h diff --git a/base/third_party/symbolize/config.h b/base/third_party/symbolize/config.h deleted file mode 100644 index 945f5a6..0000000 --- a/base/third_party/symbolize/config.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#define GOOGLE_NAMESPACE google -#define _END_GOOGLE_NAMESPACE_ } -#define _START_GOOGLE_NAMESPACE_ namespace google { diff --git a/base/third_party/symbolize/demangle.cc b/base/third_party/symbolize/demangle.cc deleted file mode 100644 index 46556bf..0000000 --- a/base/third_party/symbolize/demangle.cc +++ /dev/null @@ -1,1231 +0,0 @@ -// Copyright (c) 2006, 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. -// -// Author: Satoru Takabayashi - -#include <stdio.h> // for NULL -#include "demangle.h" - -_START_GOOGLE_NAMESPACE_ - -typedef struct { - const char *abbrev; - const char *real_name; -} AbbrevPair; - -// List of operators from Itanium C++ ABI. -static const AbbrevPair kOperatorList[] = { - { "nw", "new" }, - { "na", "new[]" }, - { "dl", "delete" }, - { "da", "delete[]" }, - { "ps", "+" }, - { "ng", "-" }, - { "ad", "&" }, - { "de", "*" }, - { "co", "~" }, - { "pl", "+" }, - { "mi", "-" }, - { "ml", "*" }, - { "dv", "/" }, - { "rm", "%" }, - { "an", "&" }, - { "or", "|" }, - { "eo", "^" }, - { "aS", "=" }, - { "pL", "+=" }, - { "mI", "-=" }, - { "mL", "*=" }, - { "dV", "/=" }, - { "rM", "%=" }, - { "aN", "&=" }, - { "oR", "|=" }, - { "eO", "^=" }, - { "ls", "<<" }, - { "rs", ">>" }, - { "lS", "<<=" }, - { "rS", ">>=" }, - { "eq", "==" }, - { "ne", "!=" }, - { "lt", "<" }, - { "gt", ">" }, - { "le", "<=" }, - { "ge", ">=" }, - { "nt", "!" }, - { "aa", "&&" }, - { "oo", "||" }, - { "pp", "++" }, - { "mm", "--" }, - { "cm", "," }, - { "pm", "->*" }, - { "pt", "->" }, - { "cl", "()" }, - { "ix", "[]" }, - { "qu", "?" }, - { "st", "sizeof" }, - { "sz", "sizeof" }, - { NULL, NULL }, -}; - -// List of builtin types from Itanium C++ ABI. -static const AbbrevPair kBuiltinTypeList[] = { - { "v", "void" }, - { "w", "wchar_t" }, - { "b", "bool" }, - { "c", "char" }, - { "a", "signed char" }, - { "h", "unsigned char" }, - { "s", "short" }, - { "t", "unsigned short" }, - { "i", "int" }, - { "j", "unsigned int" }, - { "l", "long" }, - { "m", "unsigned long" }, - { "x", "long long" }, - { "y", "unsigned long long" }, - { "n", "__int128" }, - { "o", "unsigned __int128" }, - { "f", "float" }, - { "d", "double" }, - { "e", "long double" }, - { "g", "__float128" }, - { "z", "ellipsis" }, - { NULL, NULL } -}; - -// List of substitutions Itanium C++ ABI. -static const AbbrevPair kSubstitutionList[] = { - { "St", "" }, - { "Sa", "allocator" }, - { "Sb", "basic_string" }, - // std::basic_string<char, std::char_traits<char>,std::allocator<char> > - { "Ss", "string"}, - // std::basic_istream<char, std::char_traits<char> > - { "Si", "istream" }, - // std::basic_ostream<char, std::char_traits<char> > - { "So", "ostream" }, - // std::basic_iostream<char, std::char_traits<char> > - { "Sd", "iostream" }, - { NULL, NULL } -}; - -// State needed for demangling. -typedef struct { - const char *mangled_cur; // Cursor of mangled name. - const char *mangled_end; // End of mangled name. - char *out_cur; // Cursor of output string. - const char *out_begin; // Beginning of output string. - const char *out_end; // End of output string. - const char *prev_name; // For constructors/destructors. - int prev_name_length; // For constructors/destructors. - int nest_level; // For nested names. - int number; // Remember the previous number. - bool append; // Append flag. - bool overflowed; // True if output gets overflowed. -} State; - -// We don't use strlen() in libc since it's not guaranteed to be async -// signal safe. -static size_t StrLen(const char *str) { - size_t len = 0; - while (*str != '\0') { - ++str; - ++len; - } - return len; -} - -// Returns true if "str" has "prefix" as a prefix. -static bool StrPrefix(const char *str, const char *prefix) { - size_t i = 0; - while (str[i] != '\0' && prefix[i] != '\0' && - str[i] == prefix[i]) { - ++i; - } - return prefix[i] == '\0'; // Consumed everything in "prefix". -} - -static void InitState(State *state, const char *mangled, - char *out, int out_size) { - state->mangled_cur = mangled; - state->mangled_end = mangled + StrLen(mangled); - state->out_cur = out; - state->out_begin = out; - state->out_end = out + out_size; - state->prev_name = NULL; - state->prev_name_length = -1; - state->nest_level = -1; - state->number = -1; - state->append = true; - state->overflowed = false; -} - -// Calculates the remaining length of the mangled name. -static int RemainingLength(State *state) { - return state->mangled_end - state->mangled_cur; -} - -// Returns true and advances "mangled_cur" if we find "c" at -// "mangled_cur" position. -static bool ParseChar(State *state, const char c) { - if (RemainingLength(state) >= 1 && *state->mangled_cur == c) { - ++state->mangled_cur; - return true; - } - return false; -} - -// Returns true and advances "mangled_cur" if we find "two_chars" at -// "mangled_cur" position. -static bool ParseTwoChar(State *state, const char *two_chars) { - if (RemainingLength(state) >= 2 && - state->mangled_cur[0] == two_chars[0] && - state->mangled_cur[1] == two_chars[1]) { - state->mangled_cur += 2; - return true; - } - return false; -} - -// Returns true and advances "mangled_cur" if we find any character in -// "char_class" at "mangled_cur" position. -static bool ParseCharClass(State *state, const char *char_class) { - if (state->mangled_cur == state->mangled_end) { - return false; - } - const char *p = char_class; - for (; *p != '\0'; ++p) { - if (*state->mangled_cur == *p) { - state->mangled_cur += 1; - return true; - } - } - return false; -} - -// This function is used for handling an optional non-terminal. -static bool Optional(bool status) { - return true; -} - -// This function is used for handling <non-terminal>+ syntax. -typedef bool (*ParseFunc)(State *); -static bool OneOrMore(ParseFunc parse_func, State *state) { - if (parse_func(state)) { - while (parse_func(state)) { - } - return true; - } - return false; -} - -// Append "str" at "out_cur". If there is an overflow, "overflowed" -// is set to true for later use. The output string is ensured to -// always terminate with '\0' as long as there is no overflow. -static void Append(State *state, const char * const str, const int length) { - int i; - for (i = 0; i < length; ++i) { - if (state->out_cur + 1 < state->out_end) { // +1 for '\0' - *state->out_cur = str[i]; - ++state->out_cur; - } else { - state->overflowed = true; - break; - } - } - if (!state->overflowed) { - *state->out_cur = '\0'; // Terminate it with '\0' - } -} - -// We don't use equivalents in libc to avoid locale issues. -static bool IsLower(char c) { - return c >= 'a' && c <= 'z'; -} - -static bool IsAlpha(char c) { - return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); -} - -// Append "str" with some tweaks, iff "append" state is true. -// Returns true so that it can be placed in "if" conditions. -static void MaybeAppendWithLength(State *state, const char * const str, - const int length) { - if (state->append && length > 0) { - // Append a space if the output buffer ends with '<' and "str" - // starts with '<' to avoid <<<. - if (str[0] == '<' && state->out_begin < state->out_cur && - state->out_cur[-1] == '<') { - Append(state, " ", 1); - } - // Remember the last identifier name for ctors/dtors. - if (IsAlpha(str[0]) || str[0] == '_') { - state->prev_name = state->out_cur; - state->prev_name_length = length; - } - Append(state, str, length); - } -} - -// A convenient wrapper arount MaybeAppendWithLength(). -static bool MaybeAppend(State *state, const char * const str) { - if (state->append) { - int length = StrLen(str); - MaybeAppendWithLength(state, str, length); - } - return true; -} - -// This function is used for handling nested names. -static bool EnterNestedName(State *state) { - state->nest_level = 0; - return true; -} - -// This function is used for handling nested names. -static bool LeaveNestedName(State *state, int prev_value) { - state->nest_level = prev_value; - return true; -} - -// Disable the append mode not to print function parameters, etc. -static bool DisableAppend(State *state) { - state->append = false; - return true; -} - -// Restore the append mode to the previous state. -static bool RestoreAppend(State *state, bool prev_value) { - state->append = prev_value; - return true; -} - -// Increase the nest level for nested names. -static void MaybeIncreaseNestLevel(State *state) { - if (state->nest_level > -1) { - ++state->nest_level; - } -} - -// Appends :: for nested names if necessary. -static void MaybeAppendSeparator(State *state) { - if (state->nest_level >= 1) { - MaybeAppend(state, "::"); - } -} - -// Cancel the last separator if necessary. -static void MaybeCancelLastSeparator(State *state) { - if (state->nest_level >= 1 && state->append && - state->out_begin <= state->out_cur - 2) { - state->out_cur -= 2; - *state->out_cur = '\0'; - } -} - -// Returns true if identifier pointed by "mangled_cur" is anonymous -// namespace. -static bool IdentifierIsAnonymousNamespace(State *state) { - const char anon_prefix[] = "_GLOBAL__N_"; - return (state->number > sizeof(anon_prefix) - 1 && // Should be longer. - StrPrefix(state->mangled_cur, anon_prefix)); -} - -// Forward declarations of our parsing functions. -static bool ParseMangledName(State *state); -static bool ParseEncoding(State *state); -static bool ParseName(State *state); -static bool ParseUnscopedName(State *state); -static bool ParseUnscopedTemplateName(State *state); -static bool ParseNestedName(State *state); -static bool ParsePrefix(State *state); -static bool ParseUnqualifiedName(State *state); -static bool ParseSourceName(State *state); -static bool ParseLocalSourceName(State *state); -static bool ParseNumber(State *state); -static bool ParseFloatNumber(State *state); -static bool ParseSeqId(State *state); -static bool ParseIdentifier(State *state); -static bool ParseOperatorName(State *state); -static bool ParseSpecialName(State *state); -static bool ParseCallOffset(State *state); -static bool ParseNVOffset(State *state); -static bool ParseVOffset(State *state); -static bool ParseCtorDtorName(State *state); -static bool ParseType(State *state); -static bool ParseCVQualifiers(State *state); -static bool ParseBuiltinType(State *state); -static bool ParseFunctionType(State *state); -static bool ParseBareFunctionType(State *state); -static bool ParseClassEnumType(State *state); -static bool ParseArrayType(State *state); -static bool ParsePointerToMemberType(State *state); -static bool ParseTemplateParam(State *state); -static bool ParseTemplateTemplateParam(State *state); -static bool ParseTemplateArgs(State *state); -static bool ParseTemplateArg(State *state); -static bool ParseExpression(State *state); -static bool ParseExprPrimary(State *state); -static bool ParseLocalName(State *state); -static bool ParseDiscriminator(State *state); -static bool ParseSubstitution(State *state); - -// Implementation note: the following code is a straightforward -// translation of the Itanium C++ ABI defined in BNF with a couple of -// exceptions. -// -// - Support GNU extensions not defined in the Itanium C++ ABI -// - <prefix> and <template-prefix> are combined to avoid infinite loop -// - Reorder patterns to shorten the code -// - Reorder patterns to give greedier functions precedence -// We'll mark "Less greedy than" for these cases in the code -// -// Each parsing function changes the state and returns true on -// success. Otherwise, don't change the state and returns false. To -// ensure that the state isn't changed in the latter case, we save the -// original state before we call more than one parsing functions -// consecutively with &&, and restore the state if unsuccessful. See -// ParseEncoding() as an example of this convention. We follow the -// convention throughout the code. -// -// Originally we tried to do demangling without following the full ABI -// syntax but it turned out we needed to follow the full syntax to -// parse complicated cases like nested template arguments. Note that -// implementing a full-fledged demangler isn't trivial (libiberty's -// cp-demangle.c has +4300 lines). -// -// Note that (foo) in <(foo) ...> is a modifier to be ignored. -// -// Reference: -// - Itanium C++ ABI -// <http://www.codesourcery.com/cxx-abi/abi.html#mangling> - -// <mangled-name> ::= _Z <encoding> -static bool ParseMangledName(State *state) { - if (ParseTwoChar(state, "_Z") && ParseEncoding(state)) { - // Append trailing version suffix if any. - // ex. _Z3foo@@GLIBCXX_3.4 - if (state->mangled_cur < state->mangled_end && - state->mangled_cur[0] == '@') { - MaybeAppend(state, state->mangled_cur); - state->mangled_cur = state->mangled_end; - } - return true; - } - return false; -} - -// <encoding> ::= <(function) name> <bare-function-type> -// ::= <(data) name> -// ::= <special-name> -static bool ParseEncoding(State *state) { - State copy = *state; - if (ParseName(state) && ParseBareFunctionType(state)) { - return true; - } - *state = copy; - - if (ParseName(state) || ParseSpecialName(state)) { - return true; - } - return false; -} - -// <name> ::= <nested-name> -// ::= <unscoped-template-name> <template-args> -// ::= <unscoped-name> -// ::= <local-name> -static bool ParseName(State *state) { - if (ParseNestedName(state) || ParseLocalName(state)) { - return true; - } - - State copy = *state; - if (ParseUnscopedTemplateName(state) && - ParseTemplateArgs(state)) { - return true; - } - *state = copy; - - // Less greedy than <unscoped-template-name> <template-args>. - if (ParseUnscopedName(state)) { - return true; - } - return false; -} - -// <unscoped-name> ::= <unqualified-name> -// ::= St <unqualified-name> -static bool ParseUnscopedName(State *state) { - if (ParseUnqualifiedName(state)) { - return true; - } - - State copy = *state; - if (ParseTwoChar(state, "St") && - MaybeAppend(state, "std::") && - ParseUnqualifiedName(state)) { - return true; - } - *state = copy; - return false; -} - -// <unscoped-template-name> ::= <unscoped-name> -// ::= <substitution> -static bool ParseUnscopedTemplateName(State *state) { - return ParseUnscopedName(state) || ParseSubstitution(state); -} - -// <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E -// ::= N [<CV-qualifiers>] <template-prefix> <template-args> E -static bool ParseNestedName(State *state) { - State copy = *state; - if (ParseChar(state, 'N') && - EnterNestedName(state) && - Optional(ParseCVQualifiers(state)) && - ParsePrefix(state) && - LeaveNestedName(state, copy.nest_level) && - ParseChar(state, 'E')) { - return true; - } - *state = copy; - return false; -} - -// This part is tricky. If we literally translate them to code, we'll -// end up infinite loop. Hence we merge them to avoid the case. -// -// <prefix> ::= <prefix> <unqualified-name> -// ::= <template-prefix> <template-args> -// ::= <template-param> -// ::= <substitution> -// ::= # empty -// <template-prefix> ::= <prefix> <(template) unqualified-name> -// ::= <template-param> -// ::= <substitution> -static bool ParsePrefix(State *state) { - bool has_something = false; - while (true) { - MaybeAppendSeparator(state); - if (ParseTemplateParam(state) || - ParseSubstitution(state) || - ParseUnscopedName(state)) { - has_something = true; - MaybeIncreaseNestLevel(state); - continue; - } - MaybeCancelLastSeparator(state); - if (has_something && ParseTemplateArgs(state)) { - return ParsePrefix(state); - } else { - break; - } - } - return true; -} - -// <unqualified-name> ::= <operator-name> -// ::= <ctor-dtor-name> -// ::= <source-name> -// ::= <local-source-name> -static bool ParseUnqualifiedName(State *state) { - return (ParseOperatorName(state) || - ParseCtorDtorName(state) || - ParseSourceName(state) || - ParseLocalSourceName(state)); -} - -// <source-name> ::= <positive length number> <identifier> -static bool ParseSourceName(State *state) { - State copy = *state; - if (ParseNumber(state) && ParseIdentifier(state)) { - return true; - } - *state = copy; - return false; -} - -// <local-source-name> ::= L <source-name> [<discriminator>] -// -// References: -// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775 -// http://gcc.gnu.org/viewcvs?view=rev&revision=124467 -static bool ParseLocalSourceName(State *state) { - State copy = *state; - if (ParseChar(state, 'L') && ParseSourceName(state) && - Optional(ParseDiscriminator(state))) { - return true; - } - *state = copy; - return false; -} - -// <number> ::= [n] <non-negative decimal integer> -static bool ParseNumber(State *state) { - int sign = 1; - if (ParseChar(state, 'n')) { - sign = -1; - } - const char *p = state->mangled_cur; - int number = 0; - for (;p < state->mangled_end; ++p) { - if ((*p >= '0' && *p <= '9')) { - number = number * 10 + (*p - '0'); - } else { - break; - } - } - if (p != state->mangled_cur) { // Conversion succeeded. - state->mangled_cur = p; - state->number = number * sign; - return true; - } - return false; -} - -// Floating-point literals are encoded using a fixed-length lowercase -// hexadecimal string. -static bool ParseFloatNumber(State *state) { - const char *p = state->mangled_cur; - int number = 0; - for (;p < state->mangled_end; ++p) { - if ((*p >= '0' && *p <= '9')) { - number = number * 16 + (*p - '0'); - } else if (*p >= 'a' && *p <= 'f') { - number = number * 16 + (*p - 'a' + 10); - } else { - break; - } - } - if (p != state->mangled_cur) { // Conversion succeeded. - state->mangled_cur = p; - state->number = number; - return true; - } - return false; -} - -// The <seq-id> is a sequence number in base 36, -// using digits and upper case letters -static bool ParseSeqId(State *state) { - const char *p = state->mangled_cur; - int number = 0; - for (;p < state->mangled_end; ++p) { - if ((*p >= '0' && *p <= '9')) { - number = number * 36 + (*p - '0'); - } else if (*p >= 'A' && *p <= 'Z') { - number = number * 36 + (*p - 'A' + 10); - } else { - break; - } - } - if (p != state->mangled_cur) { // Conversion succeeded. - state->mangled_cur = p; - state->number = number; - return true; - } - return false; -} - -// <identifier> ::= <unqualified source code identifier> -static bool ParseIdentifier(State *state) { - if (state->number == -1 || - RemainingLength(state) < state->number) { - return false; - } - if (IdentifierIsAnonymousNamespace(state)) { - MaybeAppend(state, "(anonymous namespace)"); - } else { - MaybeAppendWithLength(state, state->mangled_cur, state->number); - } - state->mangled_cur += state->number; - state->number = -1; // Reset the number. - return true; -} - -// <operator-name> ::= nw, and other two letters cases -// ::= cv <type> # (cast) -// ::= v <digit> <source-name> # vendor extended operator -static bool ParseOperatorName(State *state) { - if (RemainingLength(state) < 2) { - return false; - } - // First check with "cv" (cast) case. - State copy = *state; - if (ParseTwoChar(state, "cv") && - MaybeAppend(state, "operator ") && - EnterNestedName(state) && - ParseType(state) && - LeaveNestedName(state, copy.nest_level)) { - return true; - } - *state = copy; - - // Then vendor extended operators. - if (ParseChar(state, 'v') && ParseCharClass(state, "0123456789") && - ParseSourceName(state)) { - return true; - } - *state = copy; - - // Other operator names should start with a lower alphabet followed - // by a lower/upper alphabet. - if (!(IsLower(state->mangled_cur[0]) && - IsAlpha(state->mangled_cur[1]))) { - return false; - } - // We may want to perform a binary search if we really need speed. - const AbbrevPair *p; - for (p = kOperatorList; p->abbrev != NULL; ++p) { - if (state->mangled_cur[0] == p->abbrev[0] && - state->mangled_cur[1] == p->abbrev[1]) { - MaybeAppend(state, "operator"); - if (IsLower(*p->real_name)) { // new, delete, etc. - MaybeAppend(state, " "); - } - MaybeAppend(state, p->real_name); - state->mangled_cur += 2; - return true; - } - } - return false; -} - -// <special-name> ::= TV <type> -// ::= TT <type> -// ::= TI <type> -// ::= TS <type> -// ::= Tc <call-offset> <call-offset> <(base) encoding> -// ::= GV <(object) name> -// ::= T <call-offset> <(base) encoding> -// G++ extensions: -// ::= TC <type> <(offset) number> _ <(base) type> -// ::= TF <type> -// ::= TJ <type> -// ::= GR <name> -// ::= GA <encoding> -// ::= Th <call-offset> <(base) encoding> -// ::= Tv <call-offset> <(base) encoding> -// -// Note: we don't care much about them since they don't appear in -// stack traces. The are special data. -static bool ParseSpecialName(State *state) { - State copy = *state; - if (ParseChar(state, 'T') && - ParseCharClass(state, "VTIS") && - ParseType(state)) { - return true; - } - *state = copy; - - if (ParseTwoChar(state, "Tc") && ParseCallOffset(state) && - ParseCallOffset(state) && ParseEncoding(state)) { - return true; - } - *state = copy; - - if (ParseTwoChar(state, "GV") && - ParseName(state)) { - return true; - } - *state = copy; - - if (ParseChar(state, 'T') && ParseCallOffset(state) && - ParseEncoding(state)) { - return true; - } - *state = copy; - - // G++ extensions - if (ParseTwoChar(state, "TC") && ParseType(state) && - ParseNumber(state) && ParseChar(state, '_') && - DisableAppend(state) && - ParseType(state)) { - RestoreAppend(state, copy.append); - return true; - } - *state = copy; - - if (ParseChar(state, 'T') && ParseCharClass(state, "FJ") && - ParseType(state)) { - return true; - } - *state = copy; - - if (ParseTwoChar(state, "GR") && ParseName(state)) { - return true; - } - *state = copy; - - if (ParseTwoChar(state, "GA") && ParseEncoding(state)) { - return true; - } - *state = copy; - - if (ParseChar(state, 'T') && ParseCharClass(state, "hv") && - ParseCallOffset(state) && ParseEncoding(state)) { - return true; - } - *state = copy; - return false; -} - -// <call-offset> ::= h <nv-offset> _ -// ::= v <v-offset> _ -static bool ParseCallOffset(State *state) { - State copy = *state; - if (ParseChar(state, 'h') && - ParseNVOffset(state) && ParseChar(state, '_')) { - return true; - } - *state = copy; - - if (ParseChar(state, 'v') && - ParseVOffset(state) && ParseChar(state, '_')) { - return true; - } - *state = copy; - - return false; -} - -// <nv-offset> ::= <(offset) number> -static bool ParseNVOffset(State *state) { - return ParseNumber(state); -} - -// <v-offset> ::= <(offset) number> _ <(virtual offset) number> -static bool ParseVOffset(State *state) { - State copy = *state; - if (ParseNumber(state) && ParseChar(state, '_') && - ParseNumber(state)) { - return true; - } - *state = copy; - return false; -} - -// <ctor-dtor-name> ::= C1 | C2 | C3 -// ::= D0 | D1 | D2 -static bool ParseCtorDtorName(State *state) { - State copy = *state; - if (ParseChar(state, 'C') && - ParseCharClass(state, "123")) { - const char * const prev_name = state->prev_name; - const int prev_name_length = state->prev_name_length; - MaybeAppendWithLength(state, prev_name, prev_name_length); - return true; - } - *state = copy; - - if (ParseChar(state, 'D') && - ParseCharClass(state, "012")) { - const char * const prev_name = state->prev_name; - const int prev_name_length = state->prev_name_length; - MaybeAppend(state, "~"); - MaybeAppendWithLength(state, prev_name, prev_name_length); - return true; - } - *state = copy; - return false; -} - -// <type> ::= <CV-qualifiers> <type> -// ::= P <type> -// ::= R <type> -// ::= C <type> -// ::= G <type> -// ::= U <source-name> <type> -// ::= <builtin-type> -// ::= <function-type> -// ::= <class-enum-type> -// ::= <array-type> -// ::= <pointer-to-member-type> -// ::= <template-template-param> <template-args> -// ::= <template-param> -// ::= <substitution> -static bool ParseType(State *state) { - // We should check CV-qualifers, and PRGC things first. - State copy = *state; - if (ParseCVQualifiers(state) && ParseType(state)) { - return true; - } - *state = copy; - - if (ParseCharClass(state, "PRCG") && ParseType(state)) { - return true; - } - *state = copy; - - if (ParseChar(state, 'U') && ParseSourceName(state) && - ParseType(state)) { - return true; - } - *state = copy; - - if (ParseBuiltinType(state) || - ParseFunctionType(state) || - ParseClassEnumType(state) || - ParseArrayType(state) || - ParsePointerToMemberType(state) || - ParseSubstitution(state)) { - return true; - } - - if (ParseTemplateTemplateParam(state) && - ParseTemplateArgs(state)) { - return true; - } - *state = copy; - - // Less greedy than <template-template-param> <template-args>. - if (ParseTemplateParam(state)) { - return true; - } - - return false; -} - -// <CV-qualifiers> ::= [r] [V] [K] -// We don't allow empty <CV-qualifiers> to avoid infinite loop in -// ParseType(). -static bool ParseCVQualifiers(State *state) { - int num_cv_qualifiers = 0; - num_cv_qualifiers += ParseChar(state, 'r'); - num_cv_qualifiers += ParseChar(state, 'V'); - num_cv_qualifiers += ParseChar(state, 'K'); - return num_cv_qualifiers > 0; -} - -// <builtin-type> ::= v, etc. -// ::= u <source-name> -static bool ParseBuiltinType(State *state) { - const AbbrevPair *p; - for (p = kBuiltinTypeList; p->abbrev != NULL; ++p) { - if (state->mangled_cur[0] == p->abbrev[0]) { - MaybeAppend(state, p->real_name); - ++state->mangled_cur; - return true; - } - } - - State copy = *state; - if (ParseChar(state, 'u') && ParseSourceName(state)) { - return true; - } - *state = copy; - return false; -} - -// <function-type> ::= F [Y] <bare-function-type> E -static bool ParseFunctionType(State *state) { - State copy = *state; - if (ParseChar(state, 'F') && Optional(ParseChar(state, 'Y')) && - ParseBareFunctionType(state) && ParseChar(state, 'E')) { - return true; - } - *state = copy; - return false; -} - -// <bare-function-type> ::= <(signature) type>+ -static bool ParseBareFunctionType(State *state) { - State copy = *state; - DisableAppend(state); - if (OneOrMore(ParseType, state)) { - RestoreAppend(state, copy.append); - MaybeAppend(state, "()"); - return true; - } - *state = copy; - return false; -} - -// <class-enum-type> ::= <name> -static bool ParseClassEnumType(State *state) { - return ParseName(state); -} - -// <array-type> ::= A <(positive dimension) number> _ <(element) type> -// ::= A [<(dimension) expression>] _ <(element) type> -static bool ParseArrayType(State *state) { - State copy = *state; - if (ParseChar(state, 'A') && ParseNumber(state) && - ParseChar(state, '_') && ParseType(state)) { - return true; - } - *state = copy; - - if (ParseChar(state, 'A') && Optional(ParseExpression(state)) && - ParseChar(state, '_') && ParseType(state)) { - return true; - } - *state = copy; - return false; -} - -// <pointer-to-member-type> ::= M <(class) type> <(member) type> -static bool ParsePointerToMemberType(State *state) { - State copy = *state; - if (ParseChar(state, 'M') && ParseType(state) && - ParseType(state)) { - return true; - } - *state = copy; - return false; -} - -// <template-param> ::= T_ -// ::= T <parameter-2 non-negative number> _ -static bool ParseTemplateParam(State *state) { - if (ParseTwoChar(state, "T_")) { - MaybeAppend(state, "?"); // We don't support template substitutions. - return true; - } - - State copy = *state; - if (ParseChar(state, 'T') && ParseNumber(state) && - ParseChar(state, '_')) { - MaybeAppend(state, "?"); // We don't support template substitutions. - return true; - } - *state = copy; - return false; -} - - -// <template-template-param> ::= <template-param> -// ::= <substitution> -static bool ParseTemplateTemplateParam(State *state) { - return (ParseTemplateParam(state) || - ParseSubstitution(state)); -} - -// <template-args> ::= I <template-arg>+ E -static bool ParseTemplateArgs(State *state) { - State copy = *state; - DisableAppend(state); - if (ParseChar(state, 'I') && - OneOrMore(ParseTemplateArg, state) && - ParseChar(state, 'E')) { - RestoreAppend(state, copy.append); - MaybeAppend(state, "<>"); - return true; - } - *state = copy; - return false; -} - -// <template-arg> ::= <type> -// ::= <expr-primary> -// ::= X <expression> E -static bool ParseTemplateArg(State *state) { - if (ParseType(state) || - ParseExprPrimary(state)) { - return true; - } - - State copy = *state; - if (ParseChar(state, 'X') && ParseExpression(state) && - ParseChar(state, 'E')) { - return true; - } - *state = copy; - return false; -} - -// <expression> ::= <template-param> -// ::= <expr-primary> -// ::= <unary operator-name> <expression> -// ::= <binary operator-name> <expression> <expression> -// ::= <trinary operator-name> <expression> <expression> -// <expression> -// ::= st <type> -// ::= sr <type> <unqualified-name> <template-args> -// ::= sr <type> <unqualified-name> -static bool ParseExpression(State *state) { - if (ParseTemplateParam(state) || ParseExprPrimary(state)) { - return true; - } - - State copy = *state; - if (ParseOperatorName(state) && - ParseExpression(state) && - ParseExpression(state) && - ParseExpression(state)) { - return true; - } - *state = copy; - - if (ParseOperatorName(state) && - ParseExpression(state) && - ParseExpression(state)) { - return true; - } - *state = copy; - - if (ParseOperatorName(state) && - ParseExpression(state)) { - return true; - } - *state = copy; - - if (ParseTwoChar(state, "st") && ParseType(state)) { - return true; - } - *state = copy; - - if (ParseTwoChar(state, "sr") && ParseType(state) && - ParseUnqualifiedName(state) && - ParseTemplateArgs(state)) { - return true; - } - *state = copy; - - if (ParseTwoChar(state, "sr") && ParseType(state) && - ParseUnqualifiedName(state)) { - return true; - } - *state = copy; - return false; -} - -// <expr-primary> ::= L <type> <(value) number> E -// ::= L <type> <(value) float> E -// ::= L <mangled-name> E -// // A bug in g++'s C++ ABI version 2 (-fabi-version=2). -// ::= LZ <encoding> E -static bool ParseExprPrimary(State *state) { - State copy = *state; - if (ParseChar(state, 'L') && ParseType(state) && - ParseNumber(state) && - ParseChar(state, 'E')) { - return true; - } - *state = copy; - - if (ParseChar(state, 'L') && ParseType(state) && - ParseFloatNumber(state) && - ParseChar(state, 'E')) { - return true; - } - *state = copy; - - if (ParseChar(state, 'L') && ParseMangledName(state) && - ParseChar(state, 'E')) { - return true; - } - *state = copy; - - if (ParseTwoChar(state, "LZ") && ParseEncoding(state) && - ParseChar(state, 'E')) { - return true; - } - *state = copy; - - return false; -} - -// <local-name> := Z <(function) encoding> E <(entity) name> -// [<discriminator>] -// := Z <(function) encoding> E s [<discriminator>] -static bool ParseLocalName(State *state) { - State copy = *state; - if (ParseChar(state, 'Z') && ParseEncoding(state) && - ParseChar(state, 'E') && MaybeAppend(state, "::") && - ParseName(state) && Optional(ParseDiscriminator(state))) { - return true; - } - *state = copy; - - if (ParseChar(state, 'Z') && ParseEncoding(state) && - ParseTwoChar(state, "Es") && Optional(ParseDiscriminator(state))) { - return true; - } - *state = copy; - return false; -} - -// <discriminator> := _ <(non-negative) number> -static bool ParseDiscriminator(State *state) { - State copy = *state; - if (ParseChar(state, '_') && ParseNumber(state)) { - return true; - } - *state = copy; - return false; -} - -// <substitution> ::= S_ -// ::= S <seq-id> _ -// ::= St, etc. -static bool ParseSubstitution(State *state) { - if (ParseTwoChar(state, "S_")) { - MaybeAppend(state, "?"); // We don't support substitutions. - return true; - } - - State copy = *state; - if (ParseChar(state, 'S') && ParseSeqId(state) && - ParseChar(state, '_')) { - MaybeAppend(state, "?"); // We don't support substitutions. - return true; - } - *state = copy; - - // Expand abbreviations like "St" => "std". - if (ParseChar(state, 'S')) { - const AbbrevPair *p; - for (p = kSubstitutionList; p->abbrev != NULL; ++p) { - if (state->mangled_cur[0] == p->abbrev[1]) { - MaybeAppend(state, "std"); - if (p->real_name[0] != '\0') { - MaybeAppend(state, "::"); - MaybeAppend(state, p->real_name); - } - state->mangled_cur += 1; - return true; - } - } - } - *state = copy; - return false; -} - -// The demangler entry point. -bool Demangle(const char *mangled, char *out, int out_size) { - State state; - InitState(&state, mangled, out, out_size); - return (ParseMangledName(&state) && - state.overflowed == false && - RemainingLength(&state) == 0); -} - -_END_GOOGLE_NAMESPACE_ diff --git a/base/third_party/symbolize/demangle.h b/base/third_party/symbolize/demangle.h deleted file mode 100644 index 9c75915..0000000 --- a/base/third_party/symbolize/demangle.h +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2006, 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. -// -// Author: Satoru Takabayashi -// -// An async-signal-safe and thread-safe demangler for Itanium C++ ABI -// (aka G++ V3 ABI). - -// The demangler is implemented to be used in async signal handlers to -// symbolize stack traces. We cannot use libstdc++'s -// abi::__cxa_demangle() in such signal handlers since it's not async -// signal safe (it uses malloc() internally). -// -// Note that this demangler doesn't support full demangling. More -// specifically, it doesn't print types of function parameters and -// types of template arguments. It just skips them. However, it's -// still very useful to extract basic information such as class, -// function, constructor, destructor, and operator names. -// -// See the implementation note in demangle.cc if you are interested. -// -// Example: -// -// | Mangled Name | The Demangler | abi::__cxa_demangle() -// |---------------|---------------|----------------------- -// | _Z1fv | f() | f() -// | _Z1fi | f() | f(int) -// | _Z3foo3bar | foo() | foo(bar) -// | _Z1fIiEvi | f<>() | void f<int>(int) -// | _ZN1N1fE | N::f | N::f -// | _ZN3Foo3BarEv | Foo::Bar() | Foo::Bar() -// | _Zrm1XS_" | operator%() | operator%(X, X) -// | _ZN3FooC1Ev | Foo::Foo() | Foo::Foo() -// | _Z1fSs | f() | f(std::basic_string<char, -// | | | std::char_traits<char>, -// | | | std::allocator<char> >) -// -// See the unit test for more examples. -// -// Note: we might want to write demanglers for ABIs other than Itanium -// C++ ABI in the future. -// - -#ifndef BASE_DEMANGLE_H_ -#define BASE_DEMANGLE_H_ - -#include "config.h" - -_START_GOOGLE_NAMESPACE_ - -// Demangle "mangled". On success, return true and write the -// demangled symbol name to "out". Otherwise, return false. -// "out" is modified even if demangling is unsuccessful. -bool Demangle(const char *mangled, char *out, int out_size); - -_END_GOOGLE_NAMESPACE_ - -#endif // BASE_DEMANGLE_H_ diff --git a/base/third_party/symbolize/glog/logging.h b/base/third_party/symbolize/glog/logging.h deleted file mode 100644 index a42c306..0000000 --- a/base/third_party/symbolize/glog/logging.h +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Empty. diff --git a/base/third_party/symbolize/glog/raw_logging.h b/base/third_party/symbolize/glog/raw_logging.h deleted file mode 100644 index f5515c4..0000000 --- a/base/third_party/symbolize/glog/raw_logging.h +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#define WARNING 1; -#define RAW_LOG(severity, ...); // Do nothing. diff --git a/base/third_party/symbolize/symbolize.cc b/base/third_party/symbolize/symbolize.cc deleted file mode 100644 index 3465de6..0000000 --- a/base/third_party/symbolize/symbolize.cc +++ /dev/null @@ -1,681 +0,0 @@ -// Copyright (c) 2006, 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. -// -// Author: Satoru Takabayashi -// Stack-footprint reduction work done by Raksit Ashok -// -// Implementation note: -// -// We don't use heaps but only use stacks. We want to reduce the -// stack consumption so that the symbolizer can run on small stacks. -// -// Here are some numbers collected with GCC 4.1.0 on x86: -// - sizeof(Elf32_Sym) = 16 -// - sizeof(Elf32_Shdr) = 40 -// - sizeof(Elf64_Sym) = 24 -// - sizeof(Elf64_Shdr) = 64 -// -// This implementation is intended to be async-signal-safe but uses -// some functions which are not guaranteed to be so, such as memchr() -// and memmove(). We assume they are async-signal-safe. -// - -#include "utilities.h" - -#if defined(HAVE_SYMBOLIZE) - -#include <limits> - -#include "symbolize.h" -#include "demangle.h" - -_START_GOOGLE_NAMESPACE_ - -// We don't use assert() since it's not guaranteed to be -// async-signal-safe. Instead we define a minimal assertion -// macro. So far, we don't need pretty printing for __FILE__, etc. - -// A wrapper for abort() to make it callable in ? :. -static int AssertFail() { - abort(); - return 0; // Should not reach. -} - -#define SAFE_ASSERT(expr) ((expr) ? 0 : AssertFail()) - -static SymbolizeCallback g_symbolize_callback = NULL; -void InstallSymbolizeCallback(SymbolizeCallback callback) { - g_symbolize_callback = callback; -} - -// This function wraps the Demangle function to provide an interface -// where the input symbol is demangled in-place. -// To keep stack consumption low, we would like this function to not -// get inlined. -static ATTRIBUTE_NOINLINE void DemangleInplace(char *out, int out_size) { - char demangled[256]; // Big enough for sane demangled symbols. - if (Demangle(out, demangled, sizeof(demangled))) { - // Demangling succeeded. Copy to out if the space allows. - int len = strlen(demangled); - if (len + 1 <= out_size) { // +1 for '\0'. - SAFE_ASSERT(len < sizeof(demangled)); - memmove(out, demangled, len + 1); - } - } -} - -_END_GOOGLE_NAMESPACE_ - -#if defined(__ELF__) - -#include <dlfcn.h> -#include <elf.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <link.h> // For ElfW() macro. -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include "symbolize.h" -#include "config.h" -#include "glog/raw_logging.h" - -// Re-runs fn until it doesn't cause EINTR. -#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR) - -_START_GOOGLE_NAMESPACE_ - -// Read up to "count" bytes from file descriptor "fd" into the buffer -// starting at "buf" while handling short reads and EINTR. On -// success, return the number of bytes read. Otherwise, return -1. -static ssize_t ReadPersistent(const int fd, void *buf, const size_t count) { - SAFE_ASSERT(fd >= 0); - SAFE_ASSERT(count >= 0 && count <= std::numeric_limits<ssize_t>::max()); - char *buf0 = reinterpret_cast<char *>(buf); - ssize_t num_bytes = 0; - while (num_bytes < count) { - ssize_t len; - NO_INTR(len = read(fd, buf0 + num_bytes, count - num_bytes)); - if (len < 0) { // There was an error other than EINTR. - return -1; - } - if (len == 0) { // Reached EOF. - break; - } - num_bytes += len; - } - SAFE_ASSERT(num_bytes <= count); - return num_bytes; -} - -// Read up to "count" bytes from "offset" in the file pointed by file -// descriptor "fd" into the buffer starting at "buf". On success, -// return the number of bytes read. Otherwise, return -1. -static ssize_t ReadFromOffset(const int fd, void *buf, - const size_t count, const off_t offset) { - off_t off = lseek(fd, offset, SEEK_SET); - if (off == (off_t)-1) { - return -1; - } - return ReadPersistent(fd, buf, count); -} - -// Try reading exactly "count" bytes from "offset" bytes in a file -// pointed by "fd" into the buffer starting at "buf" while handling -// short reads and EINTR. On success, return true. Otherwise, return -// false. -static bool ReadFromOffsetExact(const int fd, void *buf, - const size_t count, const off_t offset) { - ssize_t len = ReadFromOffset(fd, buf, count, offset); - return len == count; -} - -// Returns elf_header.e_type if the file pointed by fd is an ELF binary. -static int FileGetElfType(const int fd) { - ElfW(Ehdr) elf_header; - if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { - return -1; - } - if (memcmp(elf_header.e_ident, ELFMAG, SELFMAG) != 0) { - return -1; - } - return elf_header.e_type; -} - -// Read the section headers in the given ELF binary, and if a section -// of the specified type is found, set the output to this section header -// and return true. Otherwise, return false. -// To keep stack consumption low, we would like this function to not get -// inlined. -static ATTRIBUTE_NOINLINE bool -GetSectionHeaderByType(const int fd, ElfW(Half) sh_num, const off_t sh_offset, - ElfW(Word) type, ElfW(Shdr) *out) { - // Read at most 16 section headers at a time to save read calls. - ElfW(Shdr) buf[16]; - for (int i = 0; i < sh_num;) { - const ssize_t num_bytes_left = (sh_num - i) * sizeof(buf[0]); - const ssize_t num_bytes_to_read = - (sizeof(buf) > num_bytes_left) ? num_bytes_left : sizeof(buf); - const ssize_t len = ReadFromOffset(fd, buf, num_bytes_to_read, - sh_offset + i * sizeof(buf[0])); - SAFE_ASSERT(len % sizeof(buf[0]) == 0); - const ssize_t num_headers_in_buf = len / sizeof(buf[0]); - SAFE_ASSERT(num_headers_in_buf <= sizeof(buf) / sizeof(buf[0])); - for (int j = 0; j < num_headers_in_buf; ++j) { - if (buf[j].sh_type == type) { - *out = buf[j]; - return true; - } - } - i += num_headers_in_buf; - } - return false; -} - -// There is no particular reason to limit section name to 63 characters, -// but there has (as yet) been no need for anything longer either. -const int kMaxSectionNameLen = 64; - -// name_len should include terminating '\0'. -bool GetSectionHeaderByName(int fd, const char *name, size_t name_len, - ElfW(Shdr) *out) { - ElfW(Ehdr) elf_header; - if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { - return false; - } - - ElfW(Shdr) shstrtab; - off_t shstrtab_offset = (elf_header.e_shoff + - elf_header.e_shentsize * elf_header.e_shstrndx); - if (!ReadFromOffsetExact(fd, &shstrtab, sizeof(shstrtab), shstrtab_offset)) { - return false; - } - - for (int i = 0; i < elf_header.e_shnum; ++i) { - off_t section_header_offset = (elf_header.e_shoff + - elf_header.e_shentsize * i); - if (!ReadFromOffsetExact(fd, out, sizeof(*out), section_header_offset)) { - return false; - } - char header_name[kMaxSectionNameLen]; - if (sizeof(header_name) < name_len) { - RAW_LOG(WARNING, "Section name '%s' is too long (%"PRIuS"); " - "section will not be found (even if present).", name, name_len); - // No point in even trying. - return false; - } - off_t name_offset = shstrtab.sh_offset + out->sh_name; - ssize_t n_read = ReadFromOffset(fd, &header_name, name_len, name_offset); - if (n_read == -1) { - return false; - } else if (n_read != name_len) { - // Short read -- name could be at end of file. - continue; - } - if (memcmp(header_name, name, name_len) == 0) { - return true; - } - } - return false; -} - -// Read a symbol table and look for the symbol containing the -// pc. Iterate over symbols in a symbol table and look for the symbol -// containing "pc". On success, return true and write the symbol name -// to out. Otherwise, return false. -// To keep stack consumption low, we would like this function to not get -// inlined. -static ATTRIBUTE_NOINLINE bool -FindSymbol(uint64_t pc, const int fd, char *out, int out_size, - uint64_t symbol_offset, const ElfW(Shdr) *strtab, - const ElfW(Shdr) *symtab) { - if (symtab == NULL) { - return false; - } - const int num_symbols = symtab->sh_size / symtab->sh_entsize; - for (int i = 0; i < num_symbols;) { - off_t offset = symtab->sh_offset + i * symtab->sh_entsize; - - // If we are reading Elf64_Sym's, we want to limit this array to - // 32 elements (to keep stack consumption low), otherwise we can - // have a 64 element Elf32_Sym array. -#if __WORDSIZE == 64 -#define NUM_SYMBOLS 32 -#else -#define NUM_SYMBOLS 64 -#endif - - // Read at most NUM_SYMBOLS symbols at once to save read() calls. - ElfW(Sym) buf[NUM_SYMBOLS]; - const ssize_t len = ReadFromOffset(fd, &buf, sizeof(buf), offset); - SAFE_ASSERT(len % sizeof(buf[0]) == 0); - const ssize_t num_symbols_in_buf = len / sizeof(buf[0]); - SAFE_ASSERT(num_symbols_in_buf <= sizeof(buf)/sizeof(buf[0])); - for (int j = 0; j < num_symbols_in_buf; ++j) { - const ElfW(Sym)& symbol = buf[j]; - uint64_t start_address = symbol.st_value; - start_address += symbol_offset; - uint64_t end_address = start_address + symbol.st_size; - if (symbol.st_value != 0 && // Skip null value symbols. - symbol.st_shndx != 0 && // Skip undefined symbols. - start_address <= pc && pc < end_address) { - ssize_t len1 = ReadFromOffset(fd, out, out_size, - strtab->sh_offset + symbol.st_name); - if (len1 <= 0 || memchr(out, '\0', out_size) == NULL) { - return false; - } - return true; // Obtained the symbol name. - } - } - i += num_symbols_in_buf; - } - return false; -} - -// Get the symbol name of "pc" from the file pointed by "fd". Process -// both regular and dynamic symbol tables if necessary. On success, -// write the symbol name to "out" and return true. Otherwise, return -// false. -static bool GetSymbolFromObjectFile(const int fd, uint64_t pc, - char *out, int out_size, - uint64_t map_start_address) { - // Read the ELF header. - ElfW(Ehdr) elf_header; - if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) { - return false; - } - - uint64_t symbol_offset = 0; - if (elf_header.e_type == ET_DYN) { // DSO needs offset adjustment. - symbol_offset = map_start_address; - } - - ElfW(Shdr) symtab, strtab; - - // Consult a regular symbol table first. - if (!GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff, - SHT_SYMTAB, &symtab)) { - return false; - } - if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff + - symtab.sh_link * sizeof(symtab))) { - return false; - } - if (FindSymbol(pc, fd, out, out_size, symbol_offset, - &strtab, &symtab)) { - return true; // Found the symbol in a regular symbol table. - } - - // If the symbol is not found, then consult a dynamic symbol table. - if (!GetSectionHeaderByType(fd, elf_header.e_shnum, elf_header.e_shoff, - SHT_DYNSYM, &symtab)) { - return false; - } - if (!ReadFromOffsetExact(fd, &strtab, sizeof(strtab), elf_header.e_shoff + - symtab.sh_link * sizeof(symtab))) { - return false; - } - if (FindSymbol(pc, fd, out, out_size, symbol_offset, - &strtab, &symtab)) { - return true; // Found the symbol in a dynamic symbol table. - } - - return false; -} - -namespace { -// Thin wrapper around a file descriptor so that the file descriptor -// gets closed for sure. -struct FileDescriptor { - const int fd_; - explicit FileDescriptor(int fd) : fd_(fd) {} - ~FileDescriptor() { - if (fd_ >= 0) { - NO_INTR(close(fd_)); - } - } - int get() { return fd_; } - - private: - explicit FileDescriptor(const FileDescriptor&); - void operator=(const FileDescriptor&); -}; - -// Helper class for reading lines from file. -// -// Note: we don't use ProcMapsIterator since the object is big (it has -// a 5k array member) and uses async-unsafe functions such as sscanf() -// and snprintf(). -class LineReader { - public: - explicit LineReader(int fd, char *buf, int buf_len) : fd_(fd), - buf_(buf), buf_len_(buf_len), bol_(buf), eol_(buf), eod_(buf) { - } - - // Read '\n'-terminated line from file. On success, modify "bol" - // and "eol", then return true. Otherwise, return false. - // - // Note: if the last line doesn't end with '\n', the line will be - // dropped. It's an intentional behavior to make the code simple. - bool ReadLine(const char **bol, const char **eol) { - if (BufferIsEmpty()) { // First time. - const ssize_t num_bytes = ReadPersistent(fd_, buf_, buf_len_); - if (num_bytes <= 0) { // EOF or error. - return false; - } - eod_ = buf_ + num_bytes; - bol_ = buf_; - } else { - bol_ = eol_ + 1; // Advance to the next line in the buffer. - SAFE_ASSERT(bol_ <= eod_); // "bol_" can point to "eod_". - if (!HasCompleteLine()) { - const int incomplete_line_length = eod_ - bol_; - // Move the trailing incomplete line to the beginning. - memmove(buf_, bol_, incomplete_line_length); - // Read text from file and append it. - char * const append_pos = buf_ + incomplete_line_length; - const int capacity_left = buf_len_ - incomplete_line_length; - const ssize_t num_bytes = ReadPersistent(fd_, append_pos, - capacity_left); - if (num_bytes <= 0) { // EOF or error. - return false; - } - eod_ = append_pos + num_bytes; - bol_ = buf_; - } - } - eol_ = FindLineFeed(); - if (eol_ == NULL) { // '\n' not found. Malformed line. - return false; - } - *eol_ = '\0'; // Replace '\n' with '\0'. - - *bol = bol_; - *eol = eol_; - return true; - } - - // Beginning of line. - const char *bol() { - return bol_; - } - - // End of line. - const char *eol() { - return eol_; - } - - private: - explicit LineReader(const LineReader&); - void operator=(const LineReader&); - - char *FindLineFeed() { - return reinterpret_cast<char *>(memchr(bol_, '\n', eod_ - bol_)); - } - - bool BufferIsEmpty() { - return buf_ == eod_; - } - - bool HasCompleteLine() { - return !BufferIsEmpty() && FindLineFeed() != NULL; - } - - const int fd_; - char * const buf_; - const int buf_len_; - char *bol_; - char *eol_; - const char *eod_; // End of data in "buf_". -}; -} // namespace - -// Place the hex number read from "start" into "*hex". The pointer to -// the first non-hex character or "end" is returned. -static char *GetHex(const char *start, const char *end, uint64_t *hex) { - *hex = 0; - const char *p; - for (p = start; p < end; ++p) { - int ch = *p; - if ((ch >= '0' && ch <= '9') || - (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) { - *hex = (*hex << 4) | (ch < 'A' ? ch - '0' : (ch & 0xF) + 9); - } else { // Encountered the first non-hex character. - break; - } - } - SAFE_ASSERT(p <= end); - return const_cast<char *>(p); -} - -// Search for the object file (from /proc/self/maps) that contains -// the specified pc. If found, open this file and return the file handle, -// and also set start_address to the start address of where this object -// file is mapped to in memory. Otherwise, return -1. -static ATTRIBUTE_NOINLINE int -OpenObjectFileContainingPcAndGetStartAddress(uint64_t pc, - uint64_t &start_address) { - int object_fd; - - // Open /proc/self/maps. - int maps_fd; - NO_INTR(maps_fd = open("/proc/self/maps", O_RDONLY)); - FileDescriptor wrapped_maps_fd(maps_fd); - if (wrapped_maps_fd.get() < 0) { - return -1; - } - - // Iterate over maps and look for the map containing the pc. Then - // look into the symbol tables inside. - char buf[1024]; // Big enough for line of sane /proc/self/maps - LineReader reader(wrapped_maps_fd.get(), buf, sizeof(buf)); - while (true) { - const char *cursor; - const char *eol; - if (!reader.ReadLine(&cursor, &eol)) { // EOF or malformed line. - return -1; - } - - // Start parsing line in /proc/self/maps. Here is an example: - // - // 08048000-0804c000 r-xp 00000000 08:01 2142121 /bin/cat - // - // We want start address (08048000), end address (0804c000), flags - // (r-xp) and file name (/bin/cat). - - // Read start address. - cursor = GetHex(cursor, eol, &start_address); - if (cursor == eol || *cursor != '-') { - return -1; // Malformed line. - } - ++cursor; // Skip '-'. - - // Read end address. - uint64_t end_address; - cursor = GetHex(cursor, eol, &end_address); - if (cursor == eol || *cursor != ' ') { - return -1; // Malformed line. - } - ++cursor; // Skip ' '. - - // Check start and end addresses. - if (!(start_address <= pc && pc < end_address)) { - continue; // We skip this map. PC isn't in this map. - } - - // Read flags. Skip flags until we encounter a space or eol. - const char * const flags_start = cursor; - while (cursor < eol && *cursor != ' ') { - ++cursor; - } - // We expect at least four letters for flags (ex. "r-xp"). - if (cursor == eol || cursor < flags_start + 4) { - return -1; // Malformed line. - } - - // Check flags. We are only interested in "r-x" maps. - if (memcmp(flags_start, "r-x", 3) != 0) { // Not a "r-x" map. - continue; // We skip this map. - } - ++cursor; // Skip ' '. - - // Skip to file name. "cursor" now points to file offset. We need to - // skip at least three spaces for file offset, dev, and inode. - int num_spaces = 0; - while (cursor < eol) { - if (*cursor == ' ') { - ++num_spaces; - } else if (num_spaces >= 3) { - // The first non-space character after skipping three spaces - // is the beginning of the file name. - break; - } - ++cursor; - } - if (cursor == eol) { - return -1; // Malformed line. - } - - // Finally, "cursor" now points to file name of our interest. - NO_INTR(object_fd = open(cursor, O_RDONLY)); - if (object_fd < 0) { - return -1; - } - return object_fd; - } -} - -// The implementation of our symbolization routine. If it -// successfully finds the symbol containing "pc" and obtains the -// symbol name, returns true and write the symbol name to "out". -// Otherwise, returns false. If Callback function is installed via -// InstallSymbolizeCallback(), the function is also called in this function, -// and "out" is used as its output. -// To keep stack consumption low, we would like this function to not -// get inlined. -static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out, - int out_size) { - uint64_t pc0 = reinterpret_cast<uintptr_t>(pc); - uint64_t start_address = 0; - - int object_fd = OpenObjectFileContainingPcAndGetStartAddress(pc0, - start_address); - if (object_fd == -1) { - return false; - } - FileDescriptor wrapped_object_fd(object_fd); - int elf_type = FileGetElfType(wrapped_object_fd.get()); - if (elf_type == -1) { - return false; - } - if (g_symbolize_callback) { - // Run the call back if it's installed. - // Note: relocation (and much of the rest of this code) will be - // wrong for prelinked shared libraries and PIE executables. - uint64 relocation = (elf_type == ET_DYN) ? start_address : 0; - int num_bytes_written = g_symbolize_callback(wrapped_object_fd.get(), - pc, out, out_size, - relocation); - if (num_bytes_written > 0) { - out += num_bytes_written; - out_size -= num_bytes_written; - } - } - if (!GetSymbolFromObjectFile(wrapped_object_fd.get(), pc0, - out, out_size, start_address)) { - return false; - } - - // Symbolization succeeded. Now we try to demangle the symbol. - DemangleInplace(out, out_size); - return true; -} - -_END_GOOGLE_NAMESPACE_ - -#elif defined(OS_MACOSX) && defined(HAVE_DLADDR) - -#include <dlfcn.h> -#include <string.h> - -_START_GOOGLE_NAMESPACE_ - -static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out, - int out_size) { - Dl_info info; - if (dladdr(pc, &info)) { - if (strlen(info.dli_sname) < out_size) { - strcpy(out, info.dli_sname); - // Symbolization succeeded. Now we try to demangle the symbol. - DemangleInplace(out, out_size); - return true; - } - } - return false; -} - -_END_GOOGLE_NAMESPACE_ - -#else -# error BUG: HAVE_SYMBOLIZE was wrongly set -#endif - -_START_GOOGLE_NAMESPACE_ - -bool Symbolize(void *pc, char *out, int out_size) { - SAFE_ASSERT(out_size >= 0); - return SymbolizeAndDemangle(pc, out, out_size); -} - -_END_GOOGLE_NAMESPACE_ - -#else /* HAVE_SYMBOLIZE */ - -#include <assert.h> - -#include "config.h" - -_START_GOOGLE_NAMESPACE_ - -// TODO: Support other environments. -bool Symbolize(void *pc, char *out, int out_size) { - assert(0); - return false; -} - -_END_GOOGLE_NAMESPACE_ - -#endif diff --git a/base/third_party/symbolize/symbolize.h b/base/third_party/symbolize/symbolize.h deleted file mode 100644 index c3e41be..0000000 --- a/base/third_party/symbolize/symbolize.h +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) 2006, 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. -// -// Author: Satoru Takabayashi -// -// This library provides Symbolize() function that symbolizes program -// counters to their corresponding symbol names on linux platforms. -// This library has a minimal implementation of an ELF symbol table -// reader (i.e. it doesn't depend on libelf, etc.). -// -// The algorithm used in Symbolize() is as follows. -// -// 1. Go through a list of maps in /proc/self/maps and find the map -// containing the program counter. -// -// 2. Open the mapped file and find a regular symbol table inside. -// Iterate over symbols in the symbol table and look for the symbol -// containing the program counter. If such a symbol is found, -// obtain the symbol name, and demangle the symbol if possible. -// If the symbol isn't found in the regular symbol table (binary is -// stripped), try the same thing with a dynamic symbol table. -// -// Note that Symbolize() is originally implemented to be used in -// FailureSignalHandler() in base/google.cc. Hence it doesn't use -// malloc() and other unsafe operations. It should be both -// thread-safe and async-signal-safe. - -#ifndef BASE_SYMBOLIZE_H_ -#define BASE_SYMBOLIZE_H_ - -#include "utilities.h" -#include "config.h" -#include "glog/logging.h" - -#ifdef HAVE_SYMBOLIZE - -#if defined(__ELF__) // defined by gcc -#if defined(__OpenBSD__) -#include <sys/exec_elf.h> -#else -#include <elf.h> -#endif -#include <link.h> // For ElfW() macro. - -// For systems where SIZEOF_VOID_P is not defined, determine it -// based on __LP64__ (defined by gcc on 64-bit systems) -#if !defined(SIZEOF_VOID_P) -# if defined(__LP64__) -# define SIZEOF_VOID_P 8 -# else -# define SIZEOF_VOID_P 4 -# endif -#endif - -// If there is no ElfW macro, let's define it by ourself. -#ifndef ElfW -# if SIZEOF_VOID_P == 4 -# define ElfW(type) Elf32_##type -# elif SIZEOF_VOID_P == 8 -# define ElfW(type) Elf64_##type -# else -# error "Unknown sizeof(void *)" -# endif -#endif - -_START_GOOGLE_NAMESPACE_ - -// Gets the section header for the given name, if it exists. Returns true on -// success. Otherwise, returns false. -bool GetSectionHeaderByName(int fd, const char *name, size_t name_len, - ElfW(Shdr) *out); - -_END_GOOGLE_NAMESPACE_ - -#endif /* __ELF__ */ - -_START_GOOGLE_NAMESPACE_ - -// Installs a callback function, which will be called right before a symbol name -// is printed. The callback is intended to be used for showing a file name and a -// line number preceding a symbol name. -// "fd" is a file descriptor of the object file containing the program -// counter "pc". The callback function should write output to "out" -// and return the size of the output written. On error, the callback -// function should return -1. -typedef int (*SymbolizeCallback)(int fd, void *pc, char *out, size_t out_size, - uint64 relocation); -void InstallSymbolizeCallback(SymbolizeCallback callback); - -_END_GOOGLE_NAMESPACE_ - -#endif - -_START_GOOGLE_NAMESPACE_ - -// Symbolizes a program counter. On success, returns true and write the -// symbol name to "out". The symbol name is demangled if possible -// (supports symbols generated by GCC 3.x or newer). Otherwise, -// returns false. -bool Symbolize(void *pc, char *out, int out_size); - -_END_GOOGLE_NAMESPACE_ - -#endif // BASE_SYMBOLIZE_H_ diff --git a/base/third_party/symbolize/utilities.h b/base/third_party/symbolize/utilities.h deleted file mode 100644 index 0bed526..0000000 --- a/base/third_party/symbolize/utilities.h +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <inttypes.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -typedef uint64_t uint64; -#define HAVE_SYMBOLIZE 1 -#define ATTRIBUTE_NOINLINE __attribute__ ((noinline)) |