mirror of
https://github.com/DrKLO/Telegram.git
synced 2024-12-22 06:25:14 +01:00
Update to 4.6.0
This commit is contained in:
parent
9e4f5491f4
commit
4ebcbf61cd
841 changed files with 62966 additions and 47849 deletions
|
@ -9,11 +9,11 @@ configurations {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
compile 'com.google.android.gms:play-services-gcm:11.0.2'
|
||||
compile 'com.google.android.gms:play-services-maps:11.0.2'
|
||||
compile 'com.google.android.gms:play-services-vision:11.0.2'
|
||||
compile 'com.google.android.gms:play-services-wallet:11.0.2'
|
||||
compile 'com.google.android.gms:play-services-wearable:11.0.2'
|
||||
compile 'com.google.android.gms:play-services-gcm:11.0.4'
|
||||
compile 'com.google.android.gms:play-services-maps:11.0.4'
|
||||
compile 'com.google.android.gms:play-services-vision:11.0.4'
|
||||
compile 'com.google.android.gms:play-services-wallet:11.0.4'
|
||||
compile 'com.google.android.gms:play-services-wearable:11.0.4'
|
||||
compile 'com.android.support:support-core-ui:25.3.1'
|
||||
compile 'com.android.support:support-compat:25.3.1'
|
||||
compile 'com.android.support:support-core-utils:25.3.1'
|
||||
|
@ -25,8 +25,9 @@ dependencies {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion '25.0.2'
|
||||
compileSdkVersion 26
|
||||
buildToolsVersion '26.0.2'
|
||||
|
||||
|
||||
useLibrary 'org.apache.http.legacy'
|
||||
defaultConfig.applicationId = "org.telegram.messenger"
|
||||
|
@ -90,7 +91,7 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
defaultConfig.versionCode = 1043
|
||||
defaultConfig.versionCode = 1154
|
||||
|
||||
sourceSets.debug {
|
||||
manifest.srcFile 'config/debug/AndroidManifest.xml'
|
||||
|
@ -104,6 +105,8 @@ android {
|
|||
manifest.srcFile 'config/foss/AndroidManifest.xml'
|
||||
}
|
||||
|
||||
flavorDimensions "minApi"
|
||||
|
||||
productFlavors {
|
||||
x86 {
|
||||
ndk {
|
||||
|
@ -155,14 +158,21 @@ android {
|
|||
}
|
||||
|
||||
applicationVariants.all { variant ->
|
||||
def abiVersion = variant.productFlavors.get(0).versionCode
|
||||
variant.mergedFlavor.versionCode = defaultConfig.versionCode * 10 + abiVersion
|
||||
variant.outputs.all { output ->
|
||||
output.processManifest.doLast {
|
||||
def abiVersion = variant.productFlavors.get(0).versionCode
|
||||
String manifestPath = "$manifestOutputDirectory/AndroidManifest.xml"
|
||||
def manifestContent = file(manifestPath).getText()
|
||||
manifestContent = manifestContent.replace(String.format('android:versionCode="%d"', abiVersion), String.format('android:versionCode="%s"', defaultConfig.versionCode * 10 + abiVersion))
|
||||
file(manifestPath).write(manifestContent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 25
|
||||
versionName "4.2.1"
|
||||
versionName "4.6.0"
|
||||
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
|
|
|
@ -72,42 +72,6 @@ include $(PREBUILT_STATIC_LIBRARY)
|
|||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cc
|
||||
LOCAL_ARM_MODE := arm
|
||||
LOCAL_MODULE := breakpad
|
||||
LOCAL_CPPFLAGS := -Wall -std=c++11 -DANDROID -finline-functions -ffast-math -Os -fno-strict-aliasing
|
||||
|
||||
LOCAL_C_INCLUDES := \
|
||||
./jni/breakpad/common/android/include \
|
||||
./jni/breakpad
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
./breakpad/client/linux/crash_generation/crash_generation_client.cc \
|
||||
./breakpad/client/linux/dump_writer_common/ucontext_reader.cc \
|
||||
./breakpad/client/linux/dump_writer_common/thread_info.cc \
|
||||
./breakpad/client/linux/handler/exception_handler.cc \
|
||||
./breakpad/client/linux/handler/minidump_descriptor.cc \
|
||||
./breakpad/client/linux/log/log.cc \
|
||||
./breakpad/client/linux/microdump_writer/microdump_writer.cc \
|
||||
./breakpad/client/linux/minidump_writer/linux_dumper.cc \
|
||||
./breakpad/client/linux/minidump_writer/linux_ptrace_dumper.cc \
|
||||
./breakpad/client/linux/minidump_writer/minidump_writer.cc \
|
||||
./breakpad/client/minidump_file_writer.cc \
|
||||
./breakpad/common/android/breakpad_getcontext.S \
|
||||
./breakpad/common/convert_UTF.c \
|
||||
./breakpad/common/md5.cc \
|
||||
./breakpad/common/string_conversion.cc \
|
||||
./breakpad/common/linux/elfutils.cc \
|
||||
./breakpad/common/linux/file_id.cc \
|
||||
./breakpad/common/linux/guid_creator.cc \
|
||||
./breakpad/common/linux/linux_libc_support.cc \
|
||||
./breakpad/common/linux/memory_mapped_file.cc \
|
||||
./breakpad/common/linux/safe_readlink.cc
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := voip
|
||||
LOCAL_CPPFLAGS := -Wall -std=c++11 -DANDROID -finline-functions -ffast-math -Os -fno-strict-aliasing -O3 -frtti -D__STDC_LIMIT_MACROS
|
||||
LOCAL_CFLAGS := -O3 -DUSE_KISS_FFT -fexceptions -DWEBRTC_APM_DEBUG_DUMP=0 -DWEBRTC_POSIX -D__STDC_LIMIT_MACROS
|
||||
|
@ -399,7 +363,7 @@ LOCAL_CFLAGS += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA
|
|||
LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -ffast-math -D__STDC_CONSTANT_MACROS
|
||||
LOCAL_CPPFLAGS := -DBSD=1 -ffast-math -Os -funroll-loops -std=c++11
|
||||
LOCAL_LDLIBS := -ljnigraphics -llog -lz -latomic -lOpenSLES -lEGL -lGLESv2
|
||||
LOCAL_STATIC_LIBRARIES := webp sqlite tgnet breakpad avformat avcodec avutil voip
|
||||
LOCAL_STATIC_LIBRARIES := webp sqlite tgnet avformat avcodec avutil voip
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
./opus/src/opus.c \
|
||||
|
@ -600,9 +564,8 @@ LOCAL_C_INCLUDES := \
|
|||
./jni/opus/opusfile \
|
||||
./jni/libyuv/include \
|
||||
./jni/boringssl/include \
|
||||
./jni/breakpad/common/android/include \
|
||||
./jni/breakpad \
|
||||
./jni/ffmpeg/include \
|
||||
./jni/emoji \
|
||||
./jni/intro
|
||||
|
||||
LOCAL_SRC_FILES += \
|
||||
|
@ -666,6 +629,8 @@ LOCAL_SRC_FILES += \
|
|||
./SqliteWrapper.cpp \
|
||||
./TgNetWrapper.cpp \
|
||||
./NativeLoader.cpp \
|
||||
./emoji/emoji_suggestions_data.cpp \
|
||||
./emoji/emoji_suggestions.cpp \
|
||||
./libtgvoip/client/android/tg_voip_jni.cpp
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include <jni.h>
|
||||
#include <stdio.h>
|
||||
#include "breakpad/client/linux/handler/exception_handler.h"
|
||||
#include "breakpad/client/linux/handler/minidump_descriptor.h"
|
||||
|
||||
/*static google_breakpad::ExceptionHandler *exceptionHandler;
|
||||
|
||||
|
@ -19,4 +17,4 @@ extern "C" {
|
|||
exceptionHandler = new google_breakpad::ExceptionHandler(descriptor, NULL, callback, NULL, true, -1);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,50 +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.
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
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.
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright (c) 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
|
||||
// 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_CRASH_GENERATION_CLIENT_INFO_H_
|
||||
#define CLIENT_LINUX_CRASH_GENERATION_CLIENT_INFO_H_
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
class CrashGenerationServer;
|
||||
|
||||
class ClientInfo {
|
||||
public:
|
||||
ClientInfo(pid_t pid, CrashGenerationServer* crash_server)
|
||||
: crash_server_(crash_server),
|
||||
pid_(pid) {}
|
||||
|
||||
CrashGenerationServer* crash_server() const { return crash_server_; }
|
||||
pid_t pid() const { return pid_; }
|
||||
|
||||
private:
|
||||
CrashGenerationServer* crash_server_;
|
||||
pid_t pid_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // CLIENT_LINUX_CRASH_GENERATION_CLIENT_INFO_H_
|
|
@ -1,105 +0,0 @@
|
|||
// Copyright (c) 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
|
||||
// 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/crash_generation/crash_generation_client.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common/linux/eintr_wrapper.h"
|
||||
#include "common/linux/ignore_ret.h"
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
namespace {
|
||||
|
||||
class CrashGenerationClientImpl : public CrashGenerationClient {
|
||||
public:
|
||||
explicit CrashGenerationClientImpl(int server_fd) : server_fd_(server_fd) {}
|
||||
virtual ~CrashGenerationClientImpl() {}
|
||||
|
||||
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 kernel_iovec iov;
|
||||
iov.iov_base = const_cast<void*>(blob);
|
||||
iov.iov_len = blob_size;
|
||||
|
||||
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);
|
||||
|
||||
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];
|
||||
|
||||
ssize_t ret = HANDLE_EINTR(sys_sendmsg(server_fd_, &msg, 0));
|
||||
sys_close(fds[1]);
|
||||
if (ret < 0) {
|
||||
sys_close(fds[0]);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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 CrashGenerationClientImpl(server_fd);
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -1,65 +0,0 @@
|
|||
// Copyright (c) 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
|
||||
// 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_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() {}
|
||||
virtual ~CrashGenerationClient() {}
|
||||
|
||||
// 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;
|
||||
|
||||
// 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:
|
||||
DISALLOW_COPY_AND_ASSIGN(CrashGenerationClient);
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_CRASH_GENERATION_CRASH_GENERATION_CLIENT_H_
|
|
@ -1,61 +0,0 @@
|
|||
// 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_MAPPING_INFO_H_
|
||||
#define CLIENT_LINUX_DUMP_WRITER_COMMON_MAPPING_INFO_H_
|
||||
|
||||
#include <limits.h>
|
||||
#include <list>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// 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];
|
||||
};
|
||||
|
||||
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_
|
|
@ -1,53 +0,0 @@
|
|||
// 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
|
|
@ -1,299 +0,0 @@
|
|||
// 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
|
|
@ -1,91 +0,0 @@
|
|||
// 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_
|
|
@ -1,253 +0,0 @@
|
|||
// 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
|
|
@ -1,64 +0,0 @@
|
|||
// 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
|
|
@ -1,754 +0,0 @@
|
|||
// Copyright (c) 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
|
||||
// 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.
|
||||
|
||||
// The ExceptionHandler object installs signal handlers for a number of
|
||||
// signals. We rely on the signal handler running on the thread which crashed
|
||||
// in order to identify it. This is true of the synchronous signals (SEGV etc),
|
||||
// but not true of ABRT. Thus, if you send ABRT to yourself in a program which
|
||||
// uses ExceptionHandler, you need to use tgkill to direct it to the current
|
||||
// thread.
|
||||
//
|
||||
// The signal flow looks like this:
|
||||
//
|
||||
// SignalHandler (uses a global stack of ExceptionHandler objects to find
|
||||
// | one to handle the signal. If the first rejects it, try
|
||||
// | the second etc...)
|
||||
// V
|
||||
// HandleSignal ----------------------------| (clones a new process which
|
||||
// | | shares an address space with
|
||||
// (wait for cloned | the crashed process. This
|
||||
// process) | allows us to ptrace the crashed
|
||||
// | | process)
|
||||
// V V
|
||||
// (set signal handler to ThreadEntry (static function to bounce
|
||||
// SIG_DFL and rethrow, | back into the object)
|
||||
// killing the crashed |
|
||||
// process) V
|
||||
// DoDump (writes minidump)
|
||||
// |
|
||||
// V
|
||||
// sys_exit
|
||||
//
|
||||
|
||||
// This code is a little fragmented. Different functions of the ExceptionHandler
|
||||
// class run in a number of different contexts. Some of them run in a normal
|
||||
// context and are easy to code, others run in a compromised context and the
|
||||
// restrictions at the top of minidump_writer.cc apply: no libc and use the
|
||||
// alternative malloc. Each function should have comment above it detailing the
|
||||
// context which it runs in.
|
||||
|
||||
#include "client/linux/handler/exception_handler.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/limits.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/signal.h>
|
||||
#include <sys/ucontext.h>
|
||||
#include <sys/user.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#include <algorithm>
|
||||
#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
|
||||
#endif
|
||||
|
||||
// A wrapper for the tgkill syscall: send a signal to a specific thread.
|
||||
static int tgkill(pid_t tgid, pid_t tid, int sig) {
|
||||
return syscall(__NR_tgkill, tgid, tid, sig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
namespace {
|
||||
// The list of signals which we consider to be crashes. The default action for
|
||||
// all these signals must be Core (see man 7 signal) because we rethrow the
|
||||
// signal after handling it and expect that it'll be fatal.
|
||||
const int kExceptionSignals[] = {
|
||||
SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS
|
||||
};
|
||||
const int kNumHandledSignals =
|
||||
sizeof(kExceptionSignals) / sizeof(kExceptionSignals[0]);
|
||||
struct sigaction old_handlers[kNumHandledSignals];
|
||||
bool handlers_installed = false;
|
||||
|
||||
// InstallAlternateStackLocked will store the newly installed stack in new_stack
|
||||
// and (if it exists) the previously installed stack in old_stack.
|
||||
stack_t old_stack;
|
||||
stack_t new_stack;
|
||||
bool stack_installed = false;
|
||||
|
||||
// Create an alternative stack to run the signal handlers on. This is done since
|
||||
// the signal might have been caused by a stack overflow.
|
||||
// Runs before crashing: normal context.
|
||||
void InstallAlternateStackLocked() {
|
||||
if (stack_installed)
|
||||
return;
|
||||
|
||||
memset(&old_stack, 0, sizeof(old_stack));
|
||||
memset(&new_stack, 0, sizeof(new_stack));
|
||||
|
||||
// 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(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 = calloc(1, kSigStackSize);
|
||||
new_stack.ss_size = kSigStackSize;
|
||||
|
||||
if (sys_sigaltstack(&new_stack, NULL) == -1) {
|
||||
free(new_stack.ss_sp);
|
||||
return;
|
||||
}
|
||||
stack_installed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Runs before crashing: normal context.
|
||||
void RestoreAlternateStackLocked() {
|
||||
if (!stack_installed)
|
||||
return;
|
||||
|
||||
stack_t current_stack;
|
||||
if (sys_sigaltstack(NULL, ¤t_stack) == -1)
|
||||
return;
|
||||
|
||||
// Only restore the old_stack if the current alternative stack is the one
|
||||
// installed by the call to InstallAlternateStackLocked.
|
||||
if (current_stack.ss_sp == new_stack.ss_sp) {
|
||||
if (old_stack.ss_sp) {
|
||||
if (sys_sigaltstack(&old_stack, NULL) == -1)
|
||||
return;
|
||||
} else {
|
||||
stack_t disable_stack;
|
||||
disable_stack.ss_flags = SS_DISABLE;
|
||||
if (sys_sigaltstack(&disable_stack, NULL) == -1)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
free(new_stack.ss_sp);
|
||||
stack_installed = false;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
} // namespace
|
||||
|
||||
// Runs before crashing: normal context.
|
||||
ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor,
|
||||
FilterCallback filter,
|
||||
MinidumpCallback callback,
|
||||
void* callback_context,
|
||||
bool install_handler,
|
||||
const int server_fd)
|
||||
: filter_(filter),
|
||||
callback_(callback),
|
||||
callback_context_(callback_context),
|
||||
minidump_descriptor_(descriptor),
|
||||
crash_handler_(NULL) {
|
||||
if (server_fd >= 0)
|
||||
crash_generation_client_.reset(CrashGenerationClient::TryCreate(server_fd));
|
||||
|
||||
if (!IsOutOfProcess() && !minidump_descriptor_.IsFD() &&
|
||||
!minidump_descriptor_.IsMicrodumpOnConsole())
|
||||
minidump_descriptor_.UpdatePath();
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
if (minidump_descriptor_.IsMicrodumpOnConsole())
|
||||
logger::initializeCrashLogWriter();
|
||||
#endif
|
||||
|
||||
pthread_mutex_lock(&g_handler_stack_mutex_);
|
||||
if (!g_handler_stack_)
|
||||
g_handler_stack_ = new std::vector<ExceptionHandler*>;
|
||||
if (install_handler) {
|
||||
InstallAlternateStackLocked();
|
||||
InstallHandlersLocked();
|
||||
}
|
||||
g_handler_stack_->push_back(this);
|
||||
pthread_mutex_unlock(&g_handler_stack_mutex_);
|
||||
}
|
||||
|
||||
// Runs before crashing: normal context.
|
||||
ExceptionHandler::~ExceptionHandler() {
|
||||
pthread_mutex_lock(&g_handler_stack_mutex_);
|
||||
std::vector<ExceptionHandler*>::iterator handler =
|
||||
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(&g_handler_stack_mutex_);
|
||||
}
|
||||
|
||||
// Runs before crashing: normal context.
|
||||
// static
|
||||
bool ExceptionHandler::InstallHandlersLocked() {
|
||||
if (handlers_installed)
|
||||
return false;
|
||||
|
||||
// Fail if unable to store all the old handlers.
|
||||
for (int i = 0; i < kNumHandledSignals; ++i) {
|
||||
if (sigaction(kExceptionSignals[i], NULL, &old_handlers[i]) == -1)
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
// Mask all exception signals when we're handling one of them.
|
||||
for (int i = 0; i < kNumHandledSignals; ++i)
|
||||
sigaddset(&sa.sa_mask, kExceptionSignals[i]);
|
||||
|
||||
sa.sa_sigaction = SignalHandler;
|
||||
sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
|
||||
|
||||
for (int i = 0; i < kNumHandledSignals; ++i) {
|
||||
if (sigaction(kExceptionSignals[i], &sa, NULL) == -1) {
|
||||
// At this point it is impractical to back out changes, and so failure to
|
||||
// install a signal is intentionally ignored.
|
||||
}
|
||||
}
|
||||
handlers_installed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// This function runs in a compromised context: see the top of the file.
|
||||
// Runs on the crashing thread.
|
||||
// static
|
||||
void ExceptionHandler::RestoreHandlersLocked() {
|
||||
if (!handlers_installed)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < kNumHandledSignals; ++i) {
|
||||
if (sigaction(kExceptionSignals[i], &old_handlers[i], NULL) == -1) {
|
||||
InstallDefaultHandler(kExceptionSignals[i]);
|
||||
}
|
||||
}
|
||||
handlers_installed = false;
|
||||
}
|
||||
|
||||
// void ExceptionHandler::set_crash_handler(HandlerCallback callback) {
|
||||
// crash_handler_ = callback;
|
||||
// }
|
||||
|
||||
// This function runs in a compromised context: see the top of the file.
|
||||
// Runs on the crashing thread.
|
||||
// static
|
||||
void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
|
||||
// All the exception signals are blocked at this point.
|
||||
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'
|
||||
// instead of 'sigaction'. This loses the SA_SIGINFO flag associated
|
||||
// with this function. As a consequence, the values of 'info' and 'uc'
|
||||
// become totally bogus, generally inducing a crash.
|
||||
//
|
||||
// The following code tries to detect this case. When it does, it
|
||||
// resets the signal handlers with sigaction + SA_SIGINFO and returns.
|
||||
// This forces the signal to be thrown again, but this time the kernel
|
||||
// will call the function with the right arguments.
|
||||
struct sigaction cur_handler;
|
||||
if (sigaction(sig, NULL, &cur_handler) == 0 &&
|
||||
(cur_handler.sa_flags & SA_SIGINFO) == 0) {
|
||||
// Reset signal handler with the right flags.
|
||||
sigemptyset(&cur_handler.sa_mask);
|
||||
sigaddset(&cur_handler.sa_mask, sig);
|
||||
|
||||
cur_handler.sa_sigaction = SignalHandler;
|
||||
cur_handler.sa_flags = SA_ONSTACK | SA_SIGINFO;
|
||||
|
||||
if (sigaction(sig, &cur_handler, NULL) == -1) {
|
||||
// When resetting the handler fails, try to reset the
|
||||
// default one to avoid an infinite loop here.
|
||||
InstallDefaultHandler(sig);
|
||||
}
|
||||
pthread_mutex_unlock(&g_handler_stack_mutex_);
|
||||
return;
|
||||
}
|
||||
|
||||
bool handled = false;
|
||||
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
|
||||
// it will be retriggered. If one of the ExceptionHandlers handled it
|
||||
// successfully, restore the default handler. Otherwise, restore the
|
||||
// previously installed handler. Then, when the signal is retriggered, it will
|
||||
// be delivered to the appropriate handler.
|
||||
if (handled) {
|
||||
InstallDefaultHandler(sig);
|
||||
} else {
|
||||
RestoreHandlersLocked();
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&g_handler_stack_mutex_);
|
||||
|
||||
// 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
|
||||
// result in an incorrect exit code.
|
||||
_exit(1);
|
||||
}
|
||||
} else {
|
||||
// This was a synchronous signal triggered by a hard fault (e.g. SIGSEGV).
|
||||
// No need to reissue the signal. It will automatically trigger again,
|
||||
// when we return from the signal handler.
|
||||
}
|
||||
}
|
||||
|
||||
struct ThreadArgument {
|
||||
pid_t pid; // the crashing process
|
||||
const MinidumpDescriptor* minidump_descriptor;
|
||||
ExceptionHandler* handler;
|
||||
const void* context; // a CrashContext structure
|
||||
size_t context_size;
|
||||
};
|
||||
|
||||
// This is the entry function for the cloned process. We are in a compromised
|
||||
// context here: see the top of the file.
|
||||
// static
|
||||
int ExceptionHandler::ThreadEntry(void *arg) {
|
||||
const ThreadArgument *thread_arg = reinterpret_cast<ThreadArgument*>(arg);
|
||||
|
||||
// Block here until the crashing process unblocks us when
|
||||
// we're allowed to use ptrace
|
||||
thread_arg->handler->WaitForContinueSignal();
|
||||
|
||||
return thread_arg->handler->DoDump(thread_arg->pid, thread_arg->context,
|
||||
thread_arg->context_size) == false;
|
||||
}
|
||||
|
||||
// This function runs in a compromised context: see the top of the file.
|
||||
// Runs on the crashing thread.
|
||||
bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) {
|
||||
if (filter_ && !filter_(callback_context_))
|
||||
return false;
|
||||
|
||||
// Allow ourselves to be dumped if the signal is trusted.
|
||||
bool signal_trusted = info->si_code > 0;
|
||||
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, 0, 0, 0);
|
||||
}
|
||||
CrashContext context;
|
||||
// Fill in all the holes in the struct to make Valgrind happy.
|
||||
memset(&context, 0, sizeof(context));
|
||||
memcpy(&context.siginfo, info, sizeof(siginfo_t));
|
||||
memcpy(&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(&context.float_state, fp_ptr, sizeof(context.float_state));
|
||||
}
|
||||
#elif !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
// FP state is not part of user ABI on ARM Linux.
|
||||
// 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));
|
||||
}
|
||||
#endif
|
||||
context.tid = syscall(__NR_gettid);
|
||||
if (crash_handler_ != NULL) {
|
||||
if (crash_handler_(&context, sizeof(context), callback_context_)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return GenerateDump(&context);
|
||||
}
|
||||
|
||||
// This is a public interface to HandleSignal that allows the client to
|
||||
// generate a crash dump. This function may run in a compromised context.
|
||||
bool ExceptionHandler::SimulateSignalDelivery(int sig) {
|
||||
siginfo_t siginfo = {};
|
||||
// Mimic a trusted signal to allow tracing the process (see
|
||||
// ExceptionHandler::HandleSignal().
|
||||
siginfo.si_code = SI_USER;
|
||||
siginfo.si_pid = getpid();
|
||||
struct ucontext context;
|
||||
getcontext(&context);
|
||||
return HandleSignal(sig, &siginfo, &context);
|
||||
}
|
||||
|
||||
// This function may run in a compromised context: see the top of the file.
|
||||
bool ExceptionHandler::GenerateDump(CrashContext *context) {
|
||||
if (IsOutOfProcess())
|
||||
return crash_generation_client_->RequestDump(context, sizeof(*context));
|
||||
|
||||
// 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 = reinterpret_cast<uint8_t*>(allocator.Alloc(kChildStackSize));
|
||||
if (!stack)
|
||||
return false;
|
||||
// clone() needs the top-most address. (scrub just to be safe)
|
||||
stack += kChildStackSize;
|
||||
my_memset(stack - 16, 0, 16);
|
||||
|
||||
ThreadArgument thread_arg;
|
||||
thread_arg.handler = this;
|
||||
thread_arg.minidump_descriptor = &minidump_descriptor_;
|
||||
thread_arg.pid = getpid();
|
||||
thread_arg.context = context;
|
||||
thread_arg.context_size = sizeof(*context);
|
||||
|
||||
// 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. 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) {
|
||||
// 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:";
|
||||
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;
|
||||
}
|
||||
|
||||
// Allow the child to ptrace us
|
||||
sys_prctl(PR_SET_PTRACER, child, 0, 0, 0);
|
||||
SendContinueSignalToChild();
|
||||
int status;
|
||||
const int r = HANDLE_EINTR(sys_waitpid(child, &status, __WALL));
|
||||
|
||||
sys_close(fdes[0]);
|
||||
sys_close(fdes[1]);
|
||||
|
||||
if (r == -1) {
|
||||
static const char msg[] = "ExceptionHandler::GenerateDump waitpid failed:";
|
||||
logger::write(msg, sizeof(msg) - 1);
|
||||
logger::write(strerror(errno), strlen(strerror(errno)));
|
||||
logger::write("\n", 1);
|
||||
}
|
||||
|
||||
bool success = r != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0;
|
||||
if (callback_)
|
||||
success = callback_(minidump_descriptor_, callback_context_, success);
|
||||
return success;
|
||||
}
|
||||
|
||||
// This function runs in a compromised context: see the top of the file.
|
||||
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:";
|
||||
logger::write(msg, sizeof(msg) - 1);
|
||||
logger::write(strerror(errno), strlen(strerror(errno)));
|
||||
logger::write("\n", 1);
|
||||
}
|
||||
}
|
||||
|
||||
// This function runs in a compromised context: see the top of the file.
|
||||
// Runs on the cloned process.
|
||||
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:";
|
||||
logger::write(msg, sizeof(msg) - 1);
|
||||
logger::write(strerror(errno), strlen(strerror(errno)));
|
||||
logger::write("\n", 1);
|
||||
}
|
||||
}
|
||||
|
||||
// This function runs in a compromised context: see the top of the file.
|
||||
// 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_build_fingerprint(),
|
||||
minidump_descriptor_.microdump_product_info());
|
||||
}
|
||||
if (minidump_descriptor_.IsFD()) {
|
||||
return google_breakpad::WriteMinidump(minidump_descriptor_.fd(),
|
||||
minidump_descriptor_.size_limit(),
|
||||
crashing_process,
|
||||
context,
|
||||
context_size,
|
||||
mapping_list_,
|
||||
app_memory_list_);
|
||||
}
|
||||
return google_breakpad::WriteMinidump(minidump_descriptor_.path(),
|
||||
minidump_descriptor_.size_limit(),
|
||||
crashing_process,
|
||||
context,
|
||||
context_size,
|
||||
mapping_list_,
|
||||
app_memory_list_);
|
||||
}
|
||||
|
||||
// static
|
||||
bool ExceptionHandler::WriteMinidump(const string& dump_path,
|
||||
MinidumpCallback callback,
|
||||
void* callback_context) {
|
||||
MinidumpDescriptor descriptor(dump_path);
|
||||
ExceptionHandler eh(descriptor, NULL, callback, callback_context, false, -1);
|
||||
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() &&
|
||||
!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
|
||||
// after this call to find the exact path to the minidump file.
|
||||
minidump_descriptor_.UpdatePath();
|
||||
} else if (minidump_descriptor_.IsFD()) {
|
||||
// Reposition the FD to its beginning and resize it to get rid of the
|
||||
// previous minidump info.
|
||||
lseek(minidump_descriptor_.fd(), 0, SEEK_SET);
|
||||
ignore_result(ftruncate(minidump_descriptor_.fd(), 0));
|
||||
}
|
||||
|
||||
// Allow this process to be dumped.
|
||||
sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
|
||||
|
||||
CrashContext context;
|
||||
int getcontext_result = getcontext(&context.context);
|
||||
if (getcontext_result)
|
||||
return false;
|
||||
|
||||
#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));
|
||||
#endif
|
||||
context.tid = sys_gettid();
|
||||
|
||||
// Add an exception stream to the minidump for better reporting.
|
||||
memset(&context.siginfo, 0, sizeof(context.siginfo));
|
||||
context.siginfo.si_signo = MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED;
|
||||
#if defined(__i386__)
|
||||
context.siginfo.si_addr =
|
||||
reinterpret_cast<void*>(context.context.uc_mcontext.gregs[REG_EIP]);
|
||||
#elif defined(__x86_64__)
|
||||
context.siginfo.si_addr =
|
||||
reinterpret_cast<void*>(context.context.uc_mcontext.gregs[REG_RIP]);
|
||||
#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
|
||||
|
||||
return GenerateDump(&context);
|
||||
}
|
||||
|
||||
void ExceptionHandler::AddMappingInfo(const string& name,
|
||||
const uint8_t identifier[sizeof(MDGUID)],
|
||||
uintptr_t start_address,
|
||||
size_t mapping_size,
|
||||
size_t file_offset) {
|
||||
MappingInfo info;
|
||||
info.start_addr = start_address;
|
||||
info.size = mapping_size;
|
||||
info.offset = file_offset;
|
||||
strncpy(info.name, name.c_str(), sizeof(info.name) - 1);
|
||||
info.name[sizeof(info.name) - 1] = '\0';
|
||||
|
||||
MappingEntry mapping;
|
||||
mapping.first = info;
|
||||
memcpy(mapping.second, identifier, sizeof(MDGUID));
|
||||
mapping_list_.push_back(mapping);
|
||||
}
|
||||
|
||||
void ExceptionHandler::RegisterAppMemory(void* ptr, size_t length) {
|
||||
AppMemoryList::iterator iter =
|
||||
std::find(app_memory_list_.begin(), app_memory_list_.end(), ptr);
|
||||
if (iter != app_memory_list_.end()) {
|
||||
// Don't allow registering the same pointer twice.
|
||||
return;
|
||||
}
|
||||
|
||||
AppMemory app_memory;
|
||||
app_memory.ptr = ptr;
|
||||
app_memory.length = length;
|
||||
app_memory_list_.push_back(app_memory);
|
||||
}
|
||||
|
||||
void ExceptionHandler::UnregisterAppMemory(void* ptr) {
|
||||
AppMemoryList::iterator iter =
|
||||
std::find(app_memory_list_.begin(), app_memory_list_.end(), ptr);
|
||||
if (iter != app_memory_list_.end()) {
|
||||
app_memory_list_.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
bool ExceptionHandler::WriteMinidumpForChild(pid_t child,
|
||||
pid_t child_blamed_thread,
|
||||
const string& dump_path,
|
||||
MinidumpCallback callback,
|
||||
void* callback_context) {
|
||||
// This function is not run in a compromised context.
|
||||
MinidumpDescriptor descriptor(dump_path);
|
||||
descriptor.UpdatePath();
|
||||
if (!google_breakpad::WriteMinidump(descriptor.path(),
|
||||
child,
|
||||
child_blamed_thread))
|
||||
return false;
|
||||
|
||||
return callback ? callback(descriptor, callback_context, true) : true;
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -1,278 +0,0 @@
|
|||
// Copyright (c) 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
|
||||
// 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_HANDLER_EXCEPTION_HANDLER_H_
|
||||
#define CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_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"
|
||||
#include "common/scoped_ptr.h"
|
||||
#include "common/using_std_string.h"
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// ExceptionHandler
|
||||
//
|
||||
// ExceptionHandler can write a minidump file when an exception occurs,
|
||||
// or when WriteMinidump() is called explicitly by your program.
|
||||
//
|
||||
// To have the exception handler write minidumps when an uncaught exception
|
||||
// (crash) occurs, you should create an instance early in the execution
|
||||
// of your program, and keep it around for the entire time you want to
|
||||
// have crash handling active (typically, until shutdown).
|
||||
// (NOTE): There should be only be one this kind of exception handler
|
||||
// object per process.
|
||||
//
|
||||
// If you want to write minidumps without installing the exception handler,
|
||||
// you can create an ExceptionHandler with install_handler set to false,
|
||||
// then call WriteMinidump. You can also use this technique if you want to
|
||||
// use different minidump callbacks for different call sites.
|
||||
//
|
||||
// In either case, a callback function is called when a minidump is written,
|
||||
// which receives the full path or file descriptor of the minidump. The
|
||||
// caller can collect and write additional application state to that minidump,
|
||||
// and launch an external crash-reporting application.
|
||||
//
|
||||
// Caller should try to make the callbacks as crash-friendly as possible,
|
||||
// it should avoid use heap memory allocation as much as possible.
|
||||
|
||||
class ExceptionHandler {
|
||||
public:
|
||||
// A callback function to run before Breakpad performs any substantial
|
||||
// processing of an exception. A FilterCallback is called before writing
|
||||
// a minidump. |context| is the parameter supplied by the user as
|
||||
// callback_context when the handler was created.
|
||||
//
|
||||
// If a FilterCallback returns true, Breakpad will continue processing,
|
||||
// attempting to write a minidump. If a FilterCallback returns false,
|
||||
// Breakpad will immediately report the exception as unhandled without
|
||||
// writing a minidump, allowing another handler the opportunity to handle it.
|
||||
typedef bool (*FilterCallback)(void *context);
|
||||
|
||||
// A callback function to run after the minidump has been written.
|
||||
// |descriptor| contains the file descriptor or file path containing the
|
||||
// minidump. |context| is the parameter supplied by the user as
|
||||
// callback_context when the handler was created. |succeeded| indicates
|
||||
// whether a minidump file was successfully written.
|
||||
//
|
||||
// If an exception occurred and the callback returns true, Breakpad will
|
||||
// treat the exception as fully-handled, suppressing any other handlers from
|
||||
// being notified of the exception. If the callback returns false, Breakpad
|
||||
// will treat the exception as unhandled, and allow another handler to handle
|
||||
// it. If there are no other handlers, Breakpad will report the exception to
|
||||
// the system as unhandled, allowing a debugger or native crash dialog the
|
||||
// opportunity to handle the exception. Most callback implementations
|
||||
// should normally return the value of |succeeded|, or when they wish to
|
||||
// not report an exception of handled, false. Callbacks will rarely want to
|
||||
// return true directly (unless |succeeded| is true).
|
||||
typedef bool (*MinidumpCallback)(const MinidumpDescriptor& descriptor,
|
||||
void* context,
|
||||
bool succeeded);
|
||||
|
||||
// In certain cases, a user may wish to handle the generation of the minidump
|
||||
// themselves. In this case, they can install a handler callback which is
|
||||
// called when a crash has occurred. If this function returns true, no other
|
||||
// processing of occurs and the process will shortly be crashed. If this
|
||||
// returns false, the normal processing continues.
|
||||
typedef bool (*HandlerCallback)(const void* crash_context,
|
||||
size_t crash_context_size,
|
||||
void* context);
|
||||
|
||||
// Creates a new ExceptionHandler instance to handle writing minidumps.
|
||||
// Before writing a minidump, the optional |filter| callback will be called.
|
||||
// Its return value determines whether or not Breakpad should write a
|
||||
// minidump. The minidump content will be written to the file path or file
|
||||
// descriptor from |descriptor|, and the optional |callback| is called after
|
||||
// writing the dump file, as described above.
|
||||
// If install_handler is true, then a minidump will be written whenever
|
||||
// an unhandled exception occurs. If it is false, minidumps will only
|
||||
// be written when WriteMinidump is called.
|
||||
// If |server_fd| is valid, the minidump is generated out-of-process. If it
|
||||
// is -1, in-process generation will always be used.
|
||||
ExceptionHandler(const MinidumpDescriptor& descriptor,
|
||||
FilterCallback filter,
|
||||
MinidumpCallback callback,
|
||||
void* callback_context,
|
||||
bool install_handler,
|
||||
const int server_fd);
|
||||
~ExceptionHandler();
|
||||
|
||||
const MinidumpDescriptor& minidump_descriptor() const {
|
||||
return minidump_descriptor_;
|
||||
}
|
||||
|
||||
void set_minidump_descriptor(const MinidumpDescriptor& descriptor) {
|
||||
minidump_descriptor_ = descriptor;
|
||||
}
|
||||
|
||||
void set_crash_handler(HandlerCallback callback) {
|
||||
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.
|
||||
// If the ExceptionHandler has been created with a path, a new file is
|
||||
// generated for each minidump. The file path can be retrieved in the
|
||||
// MinidumpDescriptor passed to the MinidumpCallback or by accessing the
|
||||
// MinidumpDescriptor directly from the ExceptionHandler (with
|
||||
// minidump_descriptor()).
|
||||
// If the ExceptionHandler has been created with a file descriptor, the file
|
||||
// descriptor is repositioned to its beginning and the previous generated
|
||||
// minidump is overwritten.
|
||||
// Note that this method is not supposed to be called from a compromised
|
||||
// context as it uses the heap.
|
||||
bool WriteMinidump();
|
||||
|
||||
// Convenience form of WriteMinidump which does not require an
|
||||
// ExceptionHandler instance.
|
||||
static bool WriteMinidump(const string& dump_path,
|
||||
MinidumpCallback callback,
|
||||
void* callback_context);
|
||||
|
||||
// Write a minidump of |child| immediately. This can be used to
|
||||
// capture the execution state of |child| independently of a crash.
|
||||
// Pass a meaningful |child_blamed_thread| to make that thread in
|
||||
// the child process the one from which a crash signature is
|
||||
// extracted.
|
||||
//
|
||||
// WARNING: the return of this function *must* happen before
|
||||
// the code that will eventually reap |child| executes.
|
||||
// Otherwise there's a pernicious race condition in which |child|
|
||||
// exits, is reaped, another process created with its pid, then that
|
||||
// new process dumped.
|
||||
static bool WriteMinidumpForChild(pid_t child,
|
||||
pid_t child_blamed_thread,
|
||||
const string& dump_path,
|
||||
MinidumpCallback callback,
|
||||
void* callback_context);
|
||||
|
||||
// This structure is passed to minidump_writer.h:WriteMinidump via an opaque
|
||||
// blob. It shouldn't be needed in any user code.
|
||||
struct CrashContext {
|
||||
siginfo_t siginfo;
|
||||
pid_t tid; // the crashing thread.
|
||||
struct ucontext context;
|
||||
#if !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
// #ifdef this out because FP state is not part of user ABI for Linux ARM.
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Add information about a memory mapping. This can be used if
|
||||
// a custom library loader is used that maps things in a way
|
||||
// that the linux dumper can't handle by reading the maps file.
|
||||
void AddMappingInfo(const string& name,
|
||||
const uint8_t identifier[sizeof(MDGUID)],
|
||||
uintptr_t start_address,
|
||||
size_t mapping_size,
|
||||
size_t file_offset);
|
||||
|
||||
// Register a block of memory of length bytes starting at address ptr
|
||||
// to be copied to the minidump when a crash happens.
|
||||
void RegisterAppMemory(void* ptr, size_t length);
|
||||
|
||||
// Unregister a block of memory that was registered with RegisterAppMemory.
|
||||
void UnregisterAppMemory(void* ptr);
|
||||
|
||||
// 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();
|
||||
// Restore the old signal handlers.
|
||||
static void RestoreHandlersLocked();
|
||||
|
||||
void PreresolveSymbols();
|
||||
bool GenerateDump(CrashContext *context);
|
||||
void SendContinueSignalToChild();
|
||||
void WaitForContinueSignal();
|
||||
|
||||
static void SignalHandler(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);
|
||||
|
||||
const FilterCallback filter_;
|
||||
const MinidumpCallback callback_;
|
||||
void* const callback_context_;
|
||||
|
||||
scoped_ptr<CrashGenerationClient> crash_generation_client_;
|
||||
|
||||
MinidumpDescriptor minidump_descriptor_;
|
||||
|
||||
// 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
|
||||
// ptrace. This is used to store the file descriptors for the pipe
|
||||
int fdes[2];
|
||||
|
||||
// Callers can add extra info about mappings for cases where the
|
||||
// dumper code cannot extract enough information from /proc/<pid>/maps.
|
||||
MappingList mapping_list_;
|
||||
|
||||
// Callers can request additional memory regions to be included in
|
||||
// the dump.
|
||||
AppMemoryList app_memory_list_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_
|
|
@ -1,100 +0,0 @@
|
|||
// 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.
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "client/linux/handler/minidump_descriptor.h"
|
||||
|
||||
#include "common/linux/guid_creator.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
//static
|
||||
const MinidumpDescriptor::MicrodumpOnConsole
|
||||
MinidumpDescriptor::kMicrodumpOnConsole = {};
|
||||
|
||||
MinidumpDescriptor::MinidumpDescriptor(const MinidumpDescriptor& descriptor)
|
||||
: mode_(descriptor.mode_),
|
||||
fd_(descriptor.fd_),
|
||||
directory_(descriptor.directory_),
|
||||
c_path_(NULL),
|
||||
size_limit_(descriptor.size_limit_),
|
||||
microdump_build_fingerprint_(descriptor.microdump_build_fingerprint_),
|
||||
microdump_product_info_(descriptor.microdump_product_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.
|
||||
assert(descriptor.path_.empty());
|
||||
}
|
||||
|
||||
MinidumpDescriptor& MinidumpDescriptor::operator=(
|
||||
const MinidumpDescriptor& descriptor) {
|
||||
assert(descriptor.path_.empty());
|
||||
|
||||
mode_ = descriptor.mode_;
|
||||
fd_ = descriptor.fd_;
|
||||
directory_ = descriptor.directory_;
|
||||
path_.clear();
|
||||
if (c_path_) {
|
||||
// This descriptor already had a path set, so generate a new one.
|
||||
c_path_ = NULL;
|
||||
UpdatePath();
|
||||
}
|
||||
size_limit_ = descriptor.size_limit_;
|
||||
microdump_build_fingerprint_ = descriptor.microdump_build_fingerprint_;
|
||||
microdump_product_info_ = descriptor.microdump_product_info_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void MinidumpDescriptor::UpdatePath() {
|
||||
assert(mode_ == kWriteMinidumpToFile && !directory_.empty());
|
||||
|
||||
GUID guid;
|
||||
char guid_str[kGUIDStringLength + 1];
|
||||
if (!CreateGUID(&guid) || !GUIDToString(&guid, guid_str, sizeof(guid_str))) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
path_.clear();
|
||||
path_ = directory_ + "/" + guid_str + ".dmp";
|
||||
c_path_ = path_.c_str();
|
||||
}
|
||||
|
||||
void MinidumpDescriptor::SetMicrodumpBuildFingerprint(
|
||||
const char* build_fingerprint) {
|
||||
assert(mode_ == kWriteMicrodumpToConsole);
|
||||
microdump_build_fingerprint_ = build_fingerprint;
|
||||
}
|
||||
|
||||
void MinidumpDescriptor::SetMicrodumpProductInfo(const char* product_info) {
|
||||
assert(mode_ == kWriteMicrodumpToConsole);
|
||||
microdump_product_info_ = product_info;
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -1,161 +0,0 @@
|
|||
// 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 CLIENT_LINUX_HANDLER_MINIDUMP_DESCRIPTOR_H_
|
||||
#define CLIENT_LINUX_HANDLER_MINIDUMP_DESCRIPTOR_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/using_std_string.h"
|
||||
|
||||
// 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:
|
||||
struct MicrodumpOnConsole {};
|
||||
static const MicrodumpOnConsole kMicrodumpOnConsole;
|
||||
|
||||
MinidumpDescriptor() : mode_(kUninitialized),
|
||||
fd_(-1),
|
||||
size_limit_(-1),
|
||||
microdump_build_fingerprint_(NULL),
|
||||
microdump_product_info_(NULL) {}
|
||||
|
||||
explicit MinidumpDescriptor(const string& directory)
|
||||
: mode_(kWriteMinidumpToFile),
|
||||
fd_(-1),
|
||||
directory_(directory),
|
||||
c_path_(NULL),
|
||||
size_limit_(-1),
|
||||
microdump_build_fingerprint_(NULL),
|
||||
microdump_product_info_(NULL) {
|
||||
assert(!directory.empty());
|
||||
}
|
||||
|
||||
explicit MinidumpDescriptor(int fd)
|
||||
: mode_(kWriteMinidumpToFd),
|
||||
fd_(fd),
|
||||
c_path_(NULL),
|
||||
size_limit_(-1),
|
||||
microdump_build_fingerprint_(NULL),
|
||||
microdump_product_info_(NULL) {
|
||||
assert(fd != -1);
|
||||
}
|
||||
|
||||
explicit MinidumpDescriptor(const MicrodumpOnConsole&)
|
||||
: mode_(kWriteMicrodumpToConsole),
|
||||
fd_(-1),
|
||||
size_limit_(-1),
|
||||
microdump_build_fingerprint_(NULL),
|
||||
microdump_product_info_(NULL) {}
|
||||
|
||||
explicit MinidumpDescriptor(const MinidumpDescriptor& descriptor);
|
||||
MinidumpDescriptor& operator=(const MinidumpDescriptor& descriptor);
|
||||
|
||||
static MinidumpDescriptor getMicrodumpDescriptor();
|
||||
|
||||
bool IsFD() const { return mode_ == kWriteMinidumpToFd; }
|
||||
|
||||
int fd() const { return fd_; }
|
||||
|
||||
string directory() const { return directory_; }
|
||||
|
||||
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();
|
||||
|
||||
off_t size_limit() const { return size_limit_; }
|
||||
void set_size_limit(off_t limit) { size_limit_ = limit; }
|
||||
|
||||
// TODO(primiano): make this and product info (below) just part of the
|
||||
// microdump ctor once it is rolled stably into Chrome. ETA: June 2015.
|
||||
void SetMicrodumpBuildFingerprint(const char* build_fingerprint);
|
||||
const char* microdump_build_fingerprint() const {
|
||||
return microdump_build_fingerprint_;
|
||||
}
|
||||
|
||||
void SetMicrodumpProductInfo(const char* product_info);
|
||||
const char* microdump_product_info() const {
|
||||
return microdump_product_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 product name/version and build 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 product details must be provided upfront.
|
||||
// The string pointers are supposed to be valid through all the lifetime of
|
||||
// the process (read: the caller has to guarantee that they are stored in
|
||||
// global static storage).
|
||||
const char* microdump_build_fingerprint_;
|
||||
const char* microdump_product_info_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_HANDLER_MINIDUMP_DESCRIPTOR_H_
|
|
@ -1,84 +0,0 @@
|
|||
// 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.
|
||||
|
||||
#include "client/linux/log/log.h"
|
||||
|
||||
#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, kAndroidLogTag, buf);
|
||||
#else
|
||||
return sys_write(2, buf, nbytes);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace logger
|
|
@ -1,55 +0,0 @@
|
|||
// 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 CLIENT_LINUX_LOG_LOG_H_
|
||||
#define CLIENT_LINUX_LOG_LOG_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
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_
|
|
@ -1,425 +0,0 @@
|
|||
// 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/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::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 char* build_fingerprint,
|
||||
const char* product_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),
|
||||
build_fingerprint_(build_fingerprint),
|
||||
product_info_(product_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();
|
||||
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 (product_info_) {
|
||||
LogAppend(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 (build_fingerprint_) {
|
||||
LogAppend(build_fingerprint_);
|
||||
} else if (has_uts_info) {
|
||||
LogAppend(uts.release);
|
||||
LogAppend(" ");
|
||||
LogAppend(uts.version);
|
||||
} else {
|
||||
LogAppend("no build fingerprint available");
|
||||
}
|
||||
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 char* const build_fingerprint_;
|
||||
const char* const product_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 char* build_fingerprint,
|
||||
const char* product_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, build_fingerprint, product_info,
|
||||
&dumper);
|
||||
if (!writer.Init())
|
||||
return false;
|
||||
return writer.Dump();
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -1,64 +0,0 @@
|
|||
// 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_MINIDUMP_WRITER_MICRODUMP_WRITER_H_
|
||||
#define CLIENT_LINUX_MINIDUMP_WRITER_MICRODUMP_WRITER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "client/linux/dump_writer_common/mapping_info.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// 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 char* build_fingerprint,
|
||||
const char* product_info);
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_MINIDUMP_WRITER_MICRODUMP_WRITER_H_
|
|
@ -1,144 +0,0 @@
|
|||
// Copyright (c) 2013, 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_MINIDUMP_WRITER_CPU_SET_H_
|
||||
#define CLIENT_LINUX_MINIDUMP_WRITER_CPU_SET_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// Helper class used to model a set of CPUs, as read from sysfs
|
||||
// files like /sys/devices/system/cpu/present
|
||||
// See See http://www.kernel.org/doc/Documentation/cputopology.txt
|
||||
class CpuSet {
|
||||
public:
|
||||
// The maximum number of supported CPUs.
|
||||
static const size_t kMaxCpus = 1024;
|
||||
|
||||
CpuSet() {
|
||||
my_memset(mask_, 0, sizeof(mask_));
|
||||
}
|
||||
|
||||
// Parse a sysfs file to extract the corresponding CPU set.
|
||||
bool ParseSysFile(int fd) {
|
||||
char buffer[512];
|
||||
int ret = sys_read(fd, buffer, sizeof(buffer)-1);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
buffer[ret] = '\0';
|
||||
|
||||
// Expected format: comma-separated list of items, where each
|
||||
// item can be a decimal integer, or two decimal integers separated
|
||||
// by a dash.
|
||||
// E.g.:
|
||||
// 0
|
||||
// 0,1,2,3
|
||||
// 0-3
|
||||
// 1,10-23
|
||||
const char* p = buffer;
|
||||
const char* p_end = p + ret;
|
||||
while (p < p_end) {
|
||||
// Skip leading space, if any
|
||||
while (p < p_end && my_isspace(*p))
|
||||
p++;
|
||||
|
||||
// Find start and size of current item.
|
||||
const char* item = p;
|
||||
size_t item_len = static_cast<size_t>(p_end - p);
|
||||
const char* item_next =
|
||||
static_cast<const char*>(my_memchr(p, ',', item_len));
|
||||
if (item_next != NULL) {
|
||||
p = item_next + 1;
|
||||
item_len = static_cast<size_t>(item_next - item);
|
||||
} else {
|
||||
p = p_end;
|
||||
item_next = p_end;
|
||||
}
|
||||
|
||||
// Ignore trailing spaces.
|
||||
while (item_next > item && my_isspace(item_next[-1]))
|
||||
item_next--;
|
||||
|
||||
// skip empty items.
|
||||
if (item_next == item)
|
||||
continue;
|
||||
|
||||
// read first decimal value.
|
||||
uintptr_t start = 0;
|
||||
const char* next = my_read_decimal_ptr(&start, item);
|
||||
uintptr_t end = start;
|
||||
if (*next == '-')
|
||||
my_read_decimal_ptr(&end, next+1);
|
||||
|
||||
while (start <= end)
|
||||
SetBit(start++);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Intersect this CPU set with another one.
|
||||
void IntersectWith(const CpuSet& other) {
|
||||
for (size_t nn = 0; nn < kMaskWordCount; ++nn)
|
||||
mask_[nn] &= other.mask_[nn];
|
||||
}
|
||||
|
||||
// Return the number of CPUs in this set.
|
||||
int GetCount() {
|
||||
int result = 0;
|
||||
for (size_t nn = 0; nn < kMaskWordCount; ++nn) {
|
||||
result += __builtin_popcount(mask_[nn]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
void SetBit(uintptr_t index) {
|
||||
size_t nn = static_cast<size_t>(index);
|
||||
if (nn < kMaxCpus)
|
||||
mask_[nn / kMaskWordBits] |= (1U << (nn % kMaskWordBits));
|
||||
}
|
||||
|
||||
typedef uint32_t MaskWordType;
|
||||
static const size_t kMaskWordBits = 8*sizeof(MaskWordType);
|
||||
static const size_t kMaskWordCount =
|
||||
(kMaxCpus + kMaskWordBits - 1) / kMaskWordBits;
|
||||
|
||||
MaskWordType mask_[kMaskWordCount];
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_MINIDUMP_WRITER_CPU_SET_H_
|
|
@ -1,106 +0,0 @@
|
|||
// Copyright (c) 2009, 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_MINIDUMP_WRITER_DIRECTORY_READER_H_
|
||||
#define CLIENT_LINUX_MINIDUMP_WRITER_DIRECTORY_READER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// A class for enumerating a directory without using diropen/readdir or other
|
||||
// functions which may allocate memory.
|
||||
class DirectoryReader {
|
||||
public:
|
||||
DirectoryReader(int fd)
|
||||
: fd_(fd),
|
||||
buf_used_(0) {
|
||||
}
|
||||
|
||||
// Return the next entry from the directory
|
||||
// name: (output) the NUL terminated entry name
|
||||
//
|
||||
// Returns true iff successful (false on EOF).
|
||||
//
|
||||
// After calling this, one must call |PopEntry| otherwise you'll get the same
|
||||
// entry over and over.
|
||||
bool GetNextEntry(const char** name) {
|
||||
struct kernel_dirent* const dent =
|
||||
reinterpret_cast<kernel_dirent*>(buf_);
|
||||
|
||||
if (buf_used_ == 0) {
|
||||
// need to read more entries.
|
||||
const int n = sys_getdents(fd_, dent, sizeof(buf_));
|
||||
if (n < 0) {
|
||||
return false;
|
||||
} else if (n == 0) {
|
||||
hit_eof_ = true;
|
||||
} else {
|
||||
buf_used_ += n;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf_used_ == 0 && hit_eof_)
|
||||
return false;
|
||||
|
||||
assert(buf_used_ > 0);
|
||||
|
||||
*name = dent->d_name;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PopEntry() {
|
||||
if (!buf_used_)
|
||||
return;
|
||||
|
||||
const struct kernel_dirent* const dent =
|
||||
reinterpret_cast<kernel_dirent*>(buf_);
|
||||
|
||||
buf_used_ -= dent->d_reclen;
|
||||
my_memmove(buf_, buf_ + dent->d_reclen, buf_used_);
|
||||
}
|
||||
|
||||
private:
|
||||
const int fd_;
|
||||
bool hit_eof_;
|
||||
unsigned buf_used_;
|
||||
uint8_t buf_[sizeof(struct kernel_dirent) + NAME_MAX + 1];
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_MINIDUMP_WRITER_DIRECTORY_READER_H_
|
|
@ -1,131 +0,0 @@
|
|||
// Copyright (c) 2009, 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_MINIDUMP_WRITER_LINE_READER_H_
|
||||
#define CLIENT_LINUX_MINIDUMP_WRITER_LINE_READER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// A class for reading a file, line by line, without using fopen/fgets or other
|
||||
// functions which may allocate memory.
|
||||
class LineReader {
|
||||
public:
|
||||
LineReader(int fd)
|
||||
: fd_(fd),
|
||||
hit_eof_(false),
|
||||
buf_used_(0) {
|
||||
}
|
||||
|
||||
// The maximum length of a line.
|
||||
static const size_t kMaxLineLen = 512;
|
||||
|
||||
// Return the next line from the file.
|
||||
// line: (output) a pointer to the start of the line. The line is NUL
|
||||
// terminated.
|
||||
// len: (output) the length of the line (not inc the NUL byte)
|
||||
//
|
||||
// Returns true iff successful (false on EOF).
|
||||
//
|
||||
// One must call |PopLine| after this function, otherwise you'll continue to
|
||||
// get the same line over and over.
|
||||
bool GetNextLine(const char **line, unsigned *len) {
|
||||
for (;;) {
|
||||
if (buf_used_ == 0 && hit_eof_)
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < buf_used_; ++i) {
|
||||
if (buf_[i] == '\n' || buf_[i] == 0) {
|
||||
buf_[i] = 0;
|
||||
*len = i;
|
||||
*line = buf_;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf_used_ == sizeof(buf_)) {
|
||||
// we scanned the whole buffer and didn't find an end-of-line marker.
|
||||
// This line is too long to process.
|
||||
return false;
|
||||
}
|
||||
|
||||
// We didn't find any end-of-line terminators in the buffer. However, if
|
||||
// this is the last line in the file it might not have one:
|
||||
if (hit_eof_) {
|
||||
assert(buf_used_);
|
||||
// There's room for the NUL because of the buf_used_ == sizeof(buf_)
|
||||
// check above.
|
||||
buf_[buf_used_] = 0;
|
||||
*len = buf_used_;
|
||||
buf_used_ += 1; // since we appended the NUL.
|
||||
*line = buf_;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, we should pull in more data from the file
|
||||
const ssize_t n = sys_read(fd_, buf_ + buf_used_,
|
||||
sizeof(buf_) - buf_used_);
|
||||
if (n < 0) {
|
||||
return false;
|
||||
} else if (n == 0) {
|
||||
hit_eof_ = true;
|
||||
} else {
|
||||
buf_used_ += n;
|
||||
}
|
||||
|
||||
// At this point, we have either set the hit_eof_ flag, or we have more
|
||||
// data to process...
|
||||
}
|
||||
}
|
||||
|
||||
void PopLine(unsigned len) {
|
||||
// len doesn't include the NUL byte at the end.
|
||||
|
||||
assert(buf_used_ >= len + 1);
|
||||
buf_used_ -= len + 1;
|
||||
my_memmove(buf_, buf_ + len + 1, buf_used_);
|
||||
}
|
||||
|
||||
private:
|
||||
const int fd_;
|
||||
|
||||
bool hit_eof_;
|
||||
unsigned buf_used_;
|
||||
char buf_[kMaxLineLen];
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_MINIDUMP_WRITER_LINE_READER_H_
|
|
@ -1,612 +0,0 @@
|
|||
// Copyright (c) 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
|
||||
// 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.
|
||||
|
||||
// linux_dumper.cc: Implement google_breakpad::LinuxDumper.
|
||||
// See linux_dumper.h for details.
|
||||
|
||||
// This code deals with the mechanics of getting information about a crashed
|
||||
// process. Since this code may run in a compromised address space, the same
|
||||
// rules apply as detailed at the top of minidump_writer.h: no libc calls and
|
||||
// use the alternative allocator.
|
||||
|
||||
#include "client/linux/minidump_writer/linux_dumper.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <elf.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
# if __WORDSIZE == 64
|
||||
# define UINTPTR_MAX (18446744073709551615UL)
|
||||
# else
|
||||
# define UINTPTR_MAX (4294967295U)
|
||||
# endif
|
||||
|
||||
|
||||
#include "client/linux/minidump_writer/line_reader.h"
|
||||
#include "common/linux/elfutils.h"
|
||||
#include "common/linux/file_id.h"
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "common/linux/memory_mapped_file.h"
|
||||
#include "common/linux/safe_readlink.h"
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
// Android packed relocations definitions are not yet available from the
|
||||
// NDK header files, so we have to provide them manually here.
|
||||
#ifndef DT_LOOS
|
||||
#define DT_LOOS 0x6000000d
|
||||
#endif
|
||||
#ifndef DT_ANDROID_REL
|
||||
static const int DT_ANDROID_REL = DT_LOOS + 2;
|
||||
#endif
|
||||
#ifndef DT_ANDROID_RELA
|
||||
static const int DT_ANDROID_RELA = DT_LOOS + 4;
|
||||
#endif
|
||||
|
||||
#endif // __ANDROID __
|
||||
|
||||
static const char kMappedFileUnsafePrefix[] = "/dev/";
|
||||
static const char kDeletedSuffix[] = " (deleted)";
|
||||
static const char kReservedFlags[] = " ---p";
|
||||
|
||||
inline static bool IsMappedFileOpenUnsafe(
|
||||
const google_breakpad::MappingInfo& mapping) {
|
||||
// It is unsafe to attempt to open a mapped file that lives under /dev,
|
||||
// because the semantics of the open may be driver-specific so we'd risk
|
||||
// hanging the crash dumper. And a file in /dev/ almost certainly has no
|
||||
// ELF file identifier anyways.
|
||||
return my_strncmp(mapping.name,
|
||||
kMappedFileUnsafePrefix,
|
||||
sizeof(kMappedFileUnsafePrefix) - 1) == 0;
|
||||
}
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// All interesting auvx entry types are below AT_SYSINFO_EHDR
|
||||
#define AT_MAX AT_SYSINFO_EHDR
|
||||
|
||||
LinuxDumper::LinuxDumper(pid_t pid)
|
||||
: pid_(pid),
|
||||
crash_address_(0),
|
||||
crash_signal_(0),
|
||||
crash_thread_(pid),
|
||||
threads_(&allocator_, 8),
|
||||
mappings_(&allocator_),
|
||||
auxv_(&allocator_, AT_MAX + 1) {
|
||||
// The passed-in size to the constructor (above) is only a hint.
|
||||
// Must call .resize() to do actual initialization of the elements.
|
||||
auxv_.resize(AT_MAX + 1);
|
||||
}
|
||||
|
||||
LinuxDumper::~LinuxDumper() {
|
||||
}
|
||||
|
||||
bool LinuxDumper::Init() {
|
||||
return ReadAuxv() && EnumerateThreads() && EnumerateMappings();
|
||||
}
|
||||
|
||||
bool LinuxDumper::LateInit() {
|
||||
#if defined(__ANDROID__)
|
||||
LatePostprocessMappings();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping,
|
||||
bool member,
|
||||
unsigned int mapping_id,
|
||||
uint8_t identifier[sizeof(MDGUID)]) {
|
||||
assert(!member || mapping_id < mappings_.size());
|
||||
my_memset(identifier, 0, sizeof(MDGUID));
|
||||
if (IsMappedFileOpenUnsafe(mapping))
|
||||
return false;
|
||||
|
||||
// Special-case linux-gate because it's not a real file.
|
||||
if (my_strcmp(mapping.name, kLinuxGateLibraryName) == 0) {
|
||||
void* linux_gate = NULL;
|
||||
if (pid_ == sys_getpid()) {
|
||||
linux_gate = reinterpret_cast<void*>(mapping.start_addr);
|
||||
} else {
|
||||
linux_gate = allocator_.Alloc(mapping.size);
|
||||
CopyFromProcess(linux_gate, pid_,
|
||||
reinterpret_cast<const void*>(mapping.start_addr),
|
||||
mapping.size);
|
||||
}
|
||||
return FileID::ElfFileIdentifierFromMappedFile(linux_gate, identifier);
|
||||
}
|
||||
|
||||
char filename[NAME_MAX];
|
||||
size_t filename_len = my_strlen(mapping.name);
|
||||
if (filename_len >= NAME_MAX) {
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
my_memcpy(filename, mapping.name, filename_len);
|
||||
filename[filename_len] = '\0';
|
||||
bool filename_modified = HandleDeletedFileInMapping(filename);
|
||||
|
||||
MemoryMappedFile mapped_file(filename, mapping.offset);
|
||||
if (!mapped_file.data() || mapped_file.size() < SELFMAG)
|
||||
return false;
|
||||
|
||||
bool success =
|
||||
FileID::ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier);
|
||||
if (success && member && filename_modified) {
|
||||
mappings_[mapping_id]->name[filename_len -
|
||||
sizeof(kDeletedSuffix) + 1] = '\0';
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool ElfFileSoNameFromMappedFile(
|
||||
const void* elf_base, char* soname, size_t soname_size) {
|
||||
if (!IsValidElf(elf_base)) {
|
||||
// Not ELF
|
||||
return false;
|
||||
}
|
||||
|
||||
const void* segment_start;
|
||||
size_t segment_size;
|
||||
int elf_class;
|
||||
if (!FindElfSection(elf_base, ".dynamic", SHT_DYNAMIC,
|
||||
&segment_start, &segment_size, &elf_class)) {
|
||||
// No dynamic section
|
||||
return false;
|
||||
}
|
||||
|
||||
const void* dynstr_start;
|
||||
size_t dynstr_size;
|
||||
if (!FindElfSection(elf_base, ".dynstr", SHT_STRTAB,
|
||||
&dynstr_start, &dynstr_size, &elf_class)) {
|
||||
// No dynstr section
|
||||
return false;
|
||||
}
|
||||
|
||||
const ElfW(Dyn)* dynamic = static_cast<const ElfW(Dyn)*>(segment_start);
|
||||
size_t dcount = segment_size / sizeof(ElfW(Dyn));
|
||||
for (const ElfW(Dyn)* dyn = dynamic; dyn < dynamic + dcount; ++dyn) {
|
||||
if (dyn->d_tag == DT_SONAME) {
|
||||
const char* dynstr = static_cast<const char*>(dynstr_start);
|
||||
if (dyn->d_un.d_val >= dynstr_size) {
|
||||
// Beyond the end of the dynstr section
|
||||
return false;
|
||||
}
|
||||
const char* str = dynstr + dyn->d_un.d_val;
|
||||
const size_t maxsize = dynstr_size - dyn->d_un.d_val;
|
||||
my_strlcpy(soname, str, maxsize < soname_size ? maxsize : soname_size);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Did not find SONAME
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find the shared object name (SONAME) by examining the ELF information
|
||||
// for |mapping|. If the SONAME is found copy it into the passed buffer
|
||||
// |soname| and return true. The size of the buffer is |soname_size|.
|
||||
// The SONAME will be truncated if it is too long to fit in the buffer.
|
||||
bool ElfFileSoName(
|
||||
const MappingInfo& mapping, char* soname, size_t soname_size) {
|
||||
if (IsMappedFileOpenUnsafe(mapping)) {
|
||||
// Not safe
|
||||
return false;
|
||||
}
|
||||
|
||||
char filename[NAME_MAX];
|
||||
size_t filename_len = my_strlen(mapping.name);
|
||||
if (filename_len >= NAME_MAX) {
|
||||
assert(false);
|
||||
// name too long
|
||||
return false;
|
||||
}
|
||||
|
||||
my_memcpy(filename, mapping.name, filename_len);
|
||||
filename[filename_len] = '\0';
|
||||
|
||||
MemoryMappedFile mapped_file(filename, mapping.offset);
|
||||
if (!mapped_file.data() || mapped_file.size() < SELFMAG) {
|
||||
// mmap failed
|
||||
return false;
|
||||
}
|
||||
|
||||
return ElfFileSoNameFromMappedFile(mapped_file.data(), soname, soname_size);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
// static
|
||||
void LinuxDumper::GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
|
||||
char* file_path,
|
||||
size_t file_path_size,
|
||||
char* file_name,
|
||||
size_t file_name_size) {
|
||||
my_strlcpy(file_path, mapping.name, file_path_size);
|
||||
|
||||
// If an executable is mapped from a non-zero offset, this is likely because
|
||||
// the executable was loaded directly from inside an archive file (e.g., an
|
||||
// apk on Android). We try to find the name of the shared object (SONAME) by
|
||||
// looking in the file for ELF sections.
|
||||
bool mapped_from_archive = false;
|
||||
if (mapping.exec && mapping.offset != 0)
|
||||
mapped_from_archive = ElfFileSoName(mapping, file_name, file_name_size);
|
||||
|
||||
if (mapped_from_archive) {
|
||||
// Some tools (e.g., stackwalk) extract the basename from the pathname. In
|
||||
// this case, we append the file_name to the mapped archive path as follows:
|
||||
// file_name := libname.so
|
||||
// file_path := /path/to/ARCHIVE.APK/libname.so
|
||||
if (my_strlen(file_path) + 1 + my_strlen(file_name) < file_path_size) {
|
||||
my_strlcat(file_path, "/", file_path_size);
|
||||
my_strlcat(file_path, file_name, file_path_size);
|
||||
}
|
||||
} else {
|
||||
// Common case:
|
||||
// file_path := /path/to/libname.so
|
||||
// file_name := libname.so
|
||||
const char* basename = my_strrchr(file_path, '/');
|
||||
basename = basename == NULL ? file_path : (basename + 1);
|
||||
my_strlcpy(file_name, basename, file_name_size);
|
||||
}
|
||||
}
|
||||
|
||||
bool LinuxDumper::ReadAuxv() {
|
||||
char auxv_path[NAME_MAX];
|
||||
if (!BuildProcPath(auxv_path, pid_, "auxv")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd = sys_open(auxv_path, O_RDONLY, 0);
|
||||
if (fd < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
elf_aux_entry one_aux_entry;
|
||||
bool res = false;
|
||||
while (sys_read(fd,
|
||||
&one_aux_entry,
|
||||
sizeof(elf_aux_entry)) == sizeof(elf_aux_entry) &&
|
||||
one_aux_entry.a_type != AT_NULL) {
|
||||
if (one_aux_entry.a_type <= AT_MAX) {
|
||||
auxv_[one_aux_entry.a_type] = one_aux_entry.a_un.a_val;
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
sys_close(fd);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool LinuxDumper::EnumerateMappings() {
|
||||
char maps_path[NAME_MAX];
|
||||
if (!BuildProcPath(maps_path, pid_, "maps"))
|
||||
return false;
|
||||
|
||||
// linux_gate_loc is the beginning of the kernel's mapping of
|
||||
// linux-gate.so in the process. It doesn't actually show up in the
|
||||
// maps list as a filename, but it can be found using the AT_SYSINFO_EHDR
|
||||
// aux vector entry, which gives the information necessary to special
|
||||
// case its entry when creating the list of mappings.
|
||||
// See http://www.trilithium.com/johan/2005/08/linux-gate/ for more
|
||||
// information.
|
||||
const void* linux_gate_loc =
|
||||
reinterpret_cast<void *>(auxv_[AT_SYSINFO_EHDR]);
|
||||
// Although the initial executable is usually the first mapping, it's not
|
||||
// guaranteed (see http://crosbug.com/25355); therefore, try to use the
|
||||
// actual entry point to find the mapping.
|
||||
const void* entry_point_loc = reinterpret_cast<void *>(auxv_[AT_ENTRY]);
|
||||
|
||||
const int fd = sys_open(maps_path, O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
return false;
|
||||
LineReader* const line_reader = new(allocator_) LineReader(fd);
|
||||
|
||||
const char* line;
|
||||
unsigned line_len;
|
||||
while (line_reader->GetNextLine(&line, &line_len)) {
|
||||
uintptr_t start_addr, end_addr, offset;
|
||||
|
||||
const char* i1 = my_read_hex_ptr(&start_addr, line);
|
||||
if (*i1 == '-') {
|
||||
const char* i2 = my_read_hex_ptr(&end_addr, i1 + 1);
|
||||
if (*i2 == ' ') {
|
||||
bool exec = (*(i2 + 3) == 'x');
|
||||
const char* i3 = my_read_hex_ptr(&offset, i2 + 6 /* skip ' rwxp ' */);
|
||||
if (*i3 == ' ') {
|
||||
const char* name = NULL;
|
||||
// Only copy name if the name is a valid path name, or if
|
||||
// it's the VDSO image.
|
||||
if (((name = my_strchr(line, '/')) == NULL) &&
|
||||
linux_gate_loc &&
|
||||
reinterpret_cast<void*>(start_addr) == linux_gate_loc) {
|
||||
name = kLinuxGateLibraryName;
|
||||
offset = 0;
|
||||
}
|
||||
// Merge adjacent mappings with the same name into one module,
|
||||
// assuming they're a single library mapped by the dynamic linker
|
||||
if (name && !mappings_.empty()) {
|
||||
MappingInfo* module = mappings_.back();
|
||||
if ((start_addr == module->start_addr + module->size) &&
|
||||
(my_strlen(name) == my_strlen(module->name)) &&
|
||||
(my_strncmp(name, module->name, my_strlen(name)) == 0)) {
|
||||
module->size = end_addr - module->start_addr;
|
||||
line_reader->PopLine(line_len);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Also merge mappings that result from address ranges that the
|
||||
// linker reserved but which a loaded library did not use. These
|
||||
// appear as an anonymous private mapping with no access flags set
|
||||
// and which directly follow an executable mapping.
|
||||
if (!name && !mappings_.empty()) {
|
||||
MappingInfo* module = mappings_.back();
|
||||
if ((start_addr == module->start_addr + module->size) &&
|
||||
module->exec &&
|
||||
module->name[0] == '/' &&
|
||||
offset == 0 && my_strncmp(i2,
|
||||
kReservedFlags,
|
||||
sizeof(kReservedFlags) - 1) == 0) {
|
||||
module->size = end_addr - module->start_addr;
|
||||
line_reader->PopLine(line_len);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
MappingInfo* const module = new(allocator_) MappingInfo;
|
||||
my_memset(module, 0, sizeof(MappingInfo));
|
||||
module->start_addr = start_addr;
|
||||
module->size = end_addr - start_addr;
|
||||
module->offset = offset;
|
||||
module->exec = exec;
|
||||
if (name != NULL) {
|
||||
const unsigned l = my_strlen(name);
|
||||
if (l < sizeof(module->name))
|
||||
my_memcpy(module->name, name, l);
|
||||
}
|
||||
// If this is the entry-point mapping, and it's not already the
|
||||
// first one, then we need to make it be first. This is because
|
||||
// the minidump format assumes the first module is the one that
|
||||
// corresponds to the main executable (as codified in
|
||||
// processor/minidump.cc:MinidumpModuleList::GetMainModule()).
|
||||
if (entry_point_loc &&
|
||||
(entry_point_loc >=
|
||||
reinterpret_cast<void*>(module->start_addr)) &&
|
||||
(entry_point_loc <
|
||||
reinterpret_cast<void*>(module->start_addr+module->size)) &&
|
||||
!mappings_.empty()) {
|
||||
// push the module onto the front of the list.
|
||||
mappings_.resize(mappings_.size() + 1);
|
||||
for (size_t idx = mappings_.size() - 1; idx > 0; idx--)
|
||||
mappings_[idx] = mappings_[idx - 1];
|
||||
mappings_[0] = module;
|
||||
} else {
|
||||
mappings_.push_back(module);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
line_reader->PopLine(line_len);
|
||||
}
|
||||
|
||||
sys_close(fd);
|
||||
|
||||
return !mappings_.empty();
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
bool LinuxDumper::GetLoadedElfHeader(uintptr_t start_addr, ElfW(Ehdr)* ehdr) {
|
||||
CopyFromProcess(ehdr, pid_,
|
||||
reinterpret_cast<const void*>(start_addr),
|
||||
sizeof(*ehdr));
|
||||
return my_memcmp(&ehdr->e_ident, ELFMAG, SELFMAG) == 0;
|
||||
}
|
||||
|
||||
void LinuxDumper::ParseLoadedElfProgramHeaders(ElfW(Ehdr)* ehdr,
|
||||
uintptr_t start_addr,
|
||||
uintptr_t* min_vaddr_ptr,
|
||||
uintptr_t* dyn_vaddr_ptr,
|
||||
size_t* dyn_count_ptr) {
|
||||
uintptr_t phdr_addr = start_addr + ehdr->e_phoff;
|
||||
|
||||
const uintptr_t max_addr = UINTPTR_MAX;
|
||||
uintptr_t min_vaddr = max_addr;
|
||||
uintptr_t dyn_vaddr = 0;
|
||||
size_t dyn_count = 0;
|
||||
|
||||
for (size_t i = 0; i < ehdr->e_phnum; ++i) {
|
||||
ElfW(Phdr) phdr;
|
||||
CopyFromProcess(&phdr, pid_,
|
||||
reinterpret_cast<const void*>(phdr_addr),
|
||||
sizeof(phdr));
|
||||
if (phdr.p_type == PT_LOAD && phdr.p_vaddr < min_vaddr) {
|
||||
min_vaddr = phdr.p_vaddr;
|
||||
}
|
||||
if (phdr.p_type == PT_DYNAMIC) {
|
||||
dyn_vaddr = phdr.p_vaddr;
|
||||
dyn_count = phdr.p_memsz / sizeof(ElfW(Dyn));
|
||||
}
|
||||
phdr_addr += sizeof(phdr);
|
||||
}
|
||||
|
||||
*min_vaddr_ptr = min_vaddr;
|
||||
*dyn_vaddr_ptr = dyn_vaddr;
|
||||
*dyn_count_ptr = dyn_count;
|
||||
}
|
||||
|
||||
bool LinuxDumper::HasAndroidPackedRelocations(uintptr_t load_bias,
|
||||
uintptr_t dyn_vaddr,
|
||||
size_t dyn_count) {
|
||||
uintptr_t dyn_addr = load_bias + dyn_vaddr;
|
||||
for (size_t i = 0; i < dyn_count; ++i) {
|
||||
ElfW(Dyn) dyn;
|
||||
CopyFromProcess(&dyn, pid_,
|
||||
reinterpret_cast<const void*>(dyn_addr),
|
||||
sizeof(dyn));
|
||||
if (dyn.d_tag == DT_ANDROID_REL || dyn.d_tag == DT_ANDROID_RELA) {
|
||||
return true;
|
||||
}
|
||||
dyn_addr += sizeof(dyn);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uintptr_t LinuxDumper::GetEffectiveLoadBias(ElfW(Ehdr)* ehdr,
|
||||
uintptr_t start_addr) {
|
||||
uintptr_t min_vaddr = 0;
|
||||
uintptr_t dyn_vaddr = 0;
|
||||
size_t dyn_count = 0;
|
||||
ParseLoadedElfProgramHeaders(ehdr, start_addr,
|
||||
&min_vaddr, &dyn_vaddr, &dyn_count);
|
||||
// If |min_vaddr| is non-zero and we find Android packed relocation tags,
|
||||
// return the effective load bias.
|
||||
if (min_vaddr != 0) {
|
||||
const uintptr_t load_bias = start_addr - min_vaddr;
|
||||
if (HasAndroidPackedRelocations(load_bias, dyn_vaddr, dyn_count)) {
|
||||
return load_bias;
|
||||
}
|
||||
}
|
||||
// Either |min_vaddr| is zero, or it is non-zero but we did not find the
|
||||
// expected Android packed relocations tags.
|
||||
return start_addr;
|
||||
}
|
||||
|
||||
void LinuxDumper::LatePostprocessMappings() {
|
||||
for (size_t i = 0; i < mappings_.size(); ++i) {
|
||||
// Only consider exec mappings that indicate a file path was mapped, and
|
||||
// where the ELF header indicates a mapped shared library.
|
||||
MappingInfo* mapping = mappings_[i];
|
||||
if (!(mapping->exec && mapping->name[0] == '/')) {
|
||||
continue;
|
||||
}
|
||||
ElfW(Ehdr) ehdr;
|
||||
if (!GetLoadedElfHeader(mapping->start_addr, &ehdr)) {
|
||||
continue;
|
||||
}
|
||||
if (ehdr.e_type == ET_DYN) {
|
||||
// Compute the effective load bias for this mapped library, and update
|
||||
// the mapping to hold that rather than |start_addr|, at the same time
|
||||
// adjusting |size| to account for the change in |start_addr|. Where
|
||||
// the library does not contain Android packed relocations,
|
||||
// GetEffectiveLoadBias() returns |start_addr| and the mapping entry
|
||||
// is not changed.
|
||||
const uintptr_t load_bias = GetEffectiveLoadBias(&ehdr,
|
||||
mapping->start_addr);
|
||||
mapping->size += mapping->start_addr - load_bias;
|
||||
mapping->start_addr = load_bias;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __ANDROID__
|
||||
|
||||
// Get information about the stack, given the stack pointer. We don't try to
|
||||
// walk the stack since we might not have all the information needed to do
|
||||
// unwind. So we just grab, up to, 32k of stack.
|
||||
bool LinuxDumper::GetStackInfo(const void** stack, size_t* stack_len,
|
||||
uintptr_t int_stack_pointer) {
|
||||
// Move the stack pointer to the bottom of the page that it's in.
|
||||
const uintptr_t page_size = getpagesize();
|
||||
|
||||
uint8_t* const stack_pointer =
|
||||
reinterpret_cast<uint8_t*>(int_stack_pointer & ~(page_size - 1));
|
||||
|
||||
// The number of bytes of stack which we try to capture.
|
||||
static const ptrdiff_t kStackToCapture = 32 * 1024;
|
||||
|
||||
const MappingInfo* mapping = FindMapping(stack_pointer);
|
||||
if (!mapping)
|
||||
return false;
|
||||
const ptrdiff_t offset = stack_pointer -
|
||||
reinterpret_cast<uint8_t*>(mapping->start_addr);
|
||||
const ptrdiff_t distance_to_end =
|
||||
static_cast<ptrdiff_t>(mapping->size) - offset;
|
||||
*stack_len = distance_to_end > kStackToCapture ?
|
||||
kStackToCapture : distance_to_end;
|
||||
*stack = stack_pointer;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Find the mapping which the given memory address falls in.
|
||||
const MappingInfo* LinuxDumper::FindMapping(const void* address) const {
|
||||
const uintptr_t addr = (uintptr_t) address;
|
||||
|
||||
for (size_t i = 0; i < mappings_.size(); ++i) {
|
||||
const uintptr_t start = static_cast<uintptr_t>(mappings_[i]->start_addr);
|
||||
if (addr >= start && addr - start < mappings_[i]->size)
|
||||
return mappings_[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool LinuxDumper::HandleDeletedFileInMapping(char* path) const {
|
||||
static const size_t kDeletedSuffixLen = sizeof(kDeletedSuffix) - 1;
|
||||
|
||||
// Check for ' (deleted)' in |path|.
|
||||
// |path| has to be at least as long as "/x (deleted)".
|
||||
const size_t path_len = my_strlen(path);
|
||||
if (path_len < kDeletedSuffixLen + 2)
|
||||
return false;
|
||||
if (my_strncmp(path + path_len - kDeletedSuffixLen, kDeletedSuffix,
|
||||
kDeletedSuffixLen) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check |path| against the /proc/pid/exe 'symlink'.
|
||||
char exe_link[NAME_MAX];
|
||||
char new_path[NAME_MAX];
|
||||
if (!BuildProcPath(exe_link, pid_, "exe"))
|
||||
return false;
|
||||
if (!SafeReadLink(exe_link, new_path))
|
||||
return false;
|
||||
if (my_strcmp(path, new_path) != 0)
|
||||
return false;
|
||||
|
||||
// Check to see if someone actually named their executable 'foo (deleted)'.
|
||||
struct kernel_stat exe_stat;
|
||||
struct kernel_stat new_path_stat;
|
||||
if (sys_stat(exe_link, &exe_stat) == 0 &&
|
||||
sys_stat(new_path, &new_path_stat) == 0 &&
|
||||
exe_stat.st_dev == new_path_stat.st_dev &&
|
||||
exe_stat.st_ino == new_path_stat.st_ino) {
|
||||
return false;
|
||||
}
|
||||
|
||||
my_memcpy(path, exe_link, NAME_MAX);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -1,254 +0,0 @@
|
|||
// Copyright (c) 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
|
||||
// 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.
|
||||
|
||||
// linux_dumper.h: Define the google_breakpad::LinuxDumper class, which
|
||||
// is a base class for extracting information of a crashed process. It
|
||||
// was originally a complete implementation using the ptrace API, but
|
||||
// has been refactored to allow derived implementations supporting both
|
||||
// ptrace and core dump. A portion of the original implementation is now
|
||||
// in google_breakpad::LinuxPtraceDumper (see linux_ptrace_dumper.h for
|
||||
// details).
|
||||
|
||||
#ifndef CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_
|
||||
#define CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_
|
||||
|
||||
#include <elf.h>
|
||||
#if defined(__ANDROID__)
|
||||
#include <link.h>
|
||||
#endif
|
||||
#include <linux/limits.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include "client/linux/dump_writer_common/mapping_info.h"
|
||||
#include "client/linux/dump_writer_common/thread_info.h"
|
||||
#include "common/memory.h"
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// Typedef for our parsing of the auxv variables in /proc/pid/auxv.
|
||||
#if defined(__i386) || defined(__ARM_EABI__) || \
|
||||
(defined(__mips__) && _MIPS_SIM == _ABIO32)
|
||||
typedef Elf32_auxv_t elf_aux_entry;
|
||||
#elif defined(__x86_64) || defined(__aarch64__) || \
|
||||
(defined(__mips__) && _MIPS_SIM != _ABIO32)
|
||||
typedef Elf64_auxv_t elf_aux_entry;
|
||||
#endif
|
||||
|
||||
typedef __typeof__(((elf_aux_entry*) 0)->a_un.a_val) elf_aux_val_t;
|
||||
|
||||
// When we find the VDSO mapping in the process's address space, this
|
||||
// is the name we use for it when writing it to the minidump.
|
||||
// This should always be less than NAME_MAX!
|
||||
const char kLinuxGateLibraryName[] = "linux-gate.so";
|
||||
|
||||
class LinuxDumper {
|
||||
public:
|
||||
explicit LinuxDumper(pid_t pid);
|
||||
|
||||
virtual ~LinuxDumper();
|
||||
|
||||
// Parse the data for |threads| and |mappings|.
|
||||
virtual bool Init();
|
||||
|
||||
// Take any actions that could not be taken in Init(). LateInit() is
|
||||
// called after all other caller's initialization is complete, and in
|
||||
// particular after it has called ThreadsSuspend(), so that ptrace is
|
||||
// available.
|
||||
virtual bool LateInit();
|
||||
|
||||
// Return true if the dumper performs a post-mortem dump.
|
||||
virtual bool IsPostMortem() const = 0;
|
||||
|
||||
// Suspend/resume all threads in the given process.
|
||||
virtual bool ThreadsSuspend() = 0;
|
||||
virtual bool ThreadsResume() = 0;
|
||||
|
||||
// Read information about the |index|-th thread of |threads_|.
|
||||
// Returns true on success. One must have called |ThreadsSuspend| first.
|
||||
virtual bool GetThreadInfoByIndex(size_t index, ThreadInfo* info) = 0;
|
||||
|
||||
// These are only valid after a call to |Init|.
|
||||
const wasteful_vector<pid_t> &threads() { return threads_; }
|
||||
const wasteful_vector<MappingInfo*> &mappings() { return mappings_; }
|
||||
const MappingInfo* FindMapping(const void* address) const;
|
||||
const wasteful_vector<elf_aux_val_t>& auxv() { return auxv_; }
|
||||
|
||||
// Find a block of memory to take as the stack given the top of stack pointer.
|
||||
// stack: (output) the lowest address in the memory area
|
||||
// stack_len: (output) the length of the memory area
|
||||
// stack_top: the current top of the stack
|
||||
bool GetStackInfo(const void** stack, size_t* stack_len, uintptr_t stack_top);
|
||||
|
||||
PageAllocator* allocator() { return &allocator_; }
|
||||
|
||||
// Copy content of |length| bytes from a given process |child|,
|
||||
// starting from |src|, into |dest|. Returns true on success.
|
||||
virtual bool CopyFromProcess(void* dest, pid_t child, const void* src,
|
||||
size_t length) = 0;
|
||||
|
||||
// Builds a proc path for a certain pid for a node (/proc/<pid>/<node>).
|
||||
// |path| is a character array of at least NAME_MAX bytes to return the
|
||||
// result.|node| is the final node without any slashes. Returns true on
|
||||
// success.
|
||||
virtual bool BuildProcPath(char* path, pid_t pid, const char* node) const = 0;
|
||||
|
||||
// Generate a File ID from the .text section of a mapped entry.
|
||||
// If not a member, mapping_id is ignored. This method can also manipulate the
|
||||
// |mapping|.name to truncate "(deleted)" from the file name if necessary.
|
||||
bool ElfFileIdentifierForMapping(const MappingInfo& mapping,
|
||||
bool member,
|
||||
unsigned int mapping_id,
|
||||
uint8_t identifier[sizeof(MDGUID)]);
|
||||
|
||||
uintptr_t crash_address() const { return crash_address_; }
|
||||
void set_crash_address(uintptr_t crash_address) {
|
||||
crash_address_ = crash_address;
|
||||
}
|
||||
|
||||
int crash_signal() const { return crash_signal_; }
|
||||
void set_crash_signal(int crash_signal) { crash_signal_ = crash_signal; }
|
||||
|
||||
pid_t crash_thread() const { return crash_thread_; }
|
||||
void set_crash_thread(pid_t crash_thread) { crash_thread_ = crash_thread; }
|
||||
|
||||
// Extracts the effective path and file name of from |mapping|. In most cases
|
||||
// the effective name/path are just the mapping's path and basename. In some
|
||||
// other cases, however, a library can be mapped from an archive (e.g., when
|
||||
// loading .so libs from an apk on Android) and this method is able to
|
||||
// reconstruct the original file name.
|
||||
static void GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
|
||||
char* file_path,
|
||||
size_t file_path_size,
|
||||
char* file_name,
|
||||
size_t file_name_size);
|
||||
|
||||
protected:
|
||||
bool ReadAuxv();
|
||||
|
||||
virtual bool EnumerateMappings();
|
||||
|
||||
virtual bool EnumerateThreads() = 0;
|
||||
|
||||
// For the case where a running program has been deleted, it'll show up in
|
||||
// /proc/pid/maps as "/path/to/program (deleted)". If this is the case, then
|
||||
// see if '/path/to/program (deleted)' matches /proc/pid/exe and return
|
||||
// /proc/pid/exe in |path| so ELF identifier generation works correctly. This
|
||||
// also checks to see if '/path/to/program (deleted)' exists, so it does not
|
||||
// get fooled by a poorly named binary.
|
||||
// For programs that don't end with ' (deleted)', this is a no-op.
|
||||
// This assumes |path| is a buffer with length NAME_MAX.
|
||||
// Returns true if |path| is modified.
|
||||
bool HandleDeletedFileInMapping(char* path) const;
|
||||
|
||||
// ID of the crashed process.
|
||||
const pid_t pid_;
|
||||
|
||||
// Virtual address at which the process crashed.
|
||||
uintptr_t crash_address_;
|
||||
|
||||
// Signal that terminated the crashed process.
|
||||
int crash_signal_;
|
||||
|
||||
// ID of the crashed thread.
|
||||
pid_t crash_thread_;
|
||||
|
||||
mutable PageAllocator allocator_;
|
||||
|
||||
// IDs of all the threads.
|
||||
wasteful_vector<pid_t> threads_;
|
||||
|
||||
// Info from /proc/<pid>/maps.
|
||||
wasteful_vector<MappingInfo*> mappings_;
|
||||
|
||||
// Info from /proc/<pid>/auxv
|
||||
wasteful_vector<elf_aux_val_t> auxv_;
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
private:
|
||||
// Android M and later support packed ELF relocations in shared libraries.
|
||||
// Packing relocations changes the vaddr of the LOAD segments, such that
|
||||
// the effective load bias is no longer the same as the start address of
|
||||
// the memory mapping containing the executable parts of the library. The
|
||||
// packing is applied to the stripped library run on the target, but not to
|
||||
// any other library, and in particular not to the library used to generate
|
||||
// breakpad symbols. As a result, we need to adjust the |start_addr| for
|
||||
// any mapping that results from a shared library that contains Android
|
||||
// packed relocations, so that it properly represents the effective library
|
||||
// load bias. The following functions support this adjustment.
|
||||
|
||||
// Check that a given mapping at |start_addr| is for an ELF shared library.
|
||||
// If it is, place the ELF header in |ehdr| and return true.
|
||||
// The first LOAD segment in an ELF shared library has offset zero, so the
|
||||
// ELF file header is at the start of this map entry, and in already mapped
|
||||
// memory.
|
||||
bool GetLoadedElfHeader(uintptr_t start_addr, ElfW(Ehdr)* ehdr);
|
||||
|
||||
// For the ELF file mapped at |start_addr|, iterate ELF program headers to
|
||||
// find the min vaddr of all program header LOAD segments, the vaddr for
|
||||
// the DYNAMIC segment, and a count of DYNAMIC entries. Return values in
|
||||
// |min_vaddr_ptr|, |dyn_vaddr_ptr|, and |dyn_count_ptr|.
|
||||
// The program header table is also in already mapped memory.
|
||||
void ParseLoadedElfProgramHeaders(ElfW(Ehdr)* ehdr,
|
||||
uintptr_t start_addr,
|
||||
uintptr_t* min_vaddr_ptr,
|
||||
uintptr_t* dyn_vaddr_ptr,
|
||||
size_t* dyn_count_ptr);
|
||||
|
||||
// Search the DYNAMIC tags for the ELF file with the given |load_bias|, and
|
||||
// return true if the tags indicate that the file contains Android packed
|
||||
// relocations. Dynamic tags are found at |dyn_vaddr| past the |load_bias|.
|
||||
bool HasAndroidPackedRelocations(uintptr_t load_bias,
|
||||
uintptr_t dyn_vaddr,
|
||||
size_t dyn_count);
|
||||
|
||||
// If the ELF file mapped at |start_addr| contained Android packed
|
||||
// relocations, return the load bias that the system linker (or Chromium
|
||||
// crazy linker) will have used. If the file did not contain Android
|
||||
// packed relocations, returns |start_addr|, indicating that no adjustment
|
||||
// is necessary.
|
||||
// The effective load bias is |start_addr| adjusted downwards by the
|
||||
// min vaddr in the library LOAD segments.
|
||||
uintptr_t GetEffectiveLoadBias(ElfW(Ehdr)* ehdr, uintptr_t start_addr);
|
||||
|
||||
// Called from LateInit(). Iterates |mappings_| and rewrites the |start_addr|
|
||||
// field of any that represent ELF shared libraries with Android packed
|
||||
// relocations, so that |start_addr| is the load bias that the system linker
|
||||
// (or Chromium crazy linker) used. This value matches the addresses produced
|
||||
// when the non-relocation-packed library is used for breakpad symbol
|
||||
// generation.
|
||||
void LatePostprocessMappings();
|
||||
#endif // __ANDROID__
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_HANDLER_LINUX_DUMPER_H_
|
|
@ -1,355 +0,0 @@
|
|||
// 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.
|
||||
|
||||
// linux_ptrace_dumper.cc: Implement google_breakpad::LinuxPtraceDumper.
|
||||
// See linux_ptrace_dumper.h for detals.
|
||||
// This class was originally splitted from google_breakpad::LinuxDumper.
|
||||
|
||||
// This code deals with the mechanics of getting information about a crashed
|
||||
// process. Since this code may run in a compromised address space, the same
|
||||
// rules apply as detailed at the top of minidump_writer.h: no libc calls and
|
||||
// use the alternative allocator.
|
||||
|
||||
#include "client/linux/minidump_writer/linux_ptrace_dumper.h"
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#if defined(__i386)
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
|
||||
#include "client/linux/minidump_writer/directory_reader.h"
|
||||
#include "client/linux/minidump_writer/line_reader.h"
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
|
||||
// Suspends a thread by attaching to it.
|
||||
static bool SuspendThread(pid_t pid) {
|
||||
// This may fail if the thread has just died or debugged.
|
||||
errno = 0;
|
||||
if (sys_ptrace(PTRACE_ATTACH, pid, NULL, NULL) != 0 &&
|
||||
errno != 0) {
|
||||
return false;
|
||||
}
|
||||
while (sys_waitpid(pid, NULL, __WALL) < 0) {
|
||||
if (errno != EINTR) {
|
||||
sys_ptrace(PTRACE_DETACH, pid, NULL, NULL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#if defined(__i386) || defined(__x86_64)
|
||||
// On x86, the stack pointer is NULL or -1, when executing trusted code in
|
||||
// the seccomp sandbox. Not only does this cause difficulties down the line
|
||||
// when trying to dump the thread's stack, it also results in the minidumps
|
||||
// containing information about the trusted threads. This information is
|
||||
// generally completely meaningless and just pollutes the minidumps.
|
||||
// We thus test the stack pointer and exclude any threads that are part of
|
||||
// the seccomp sandbox's trusted code.
|
||||
user_regs_struct regs;
|
||||
if (sys_ptrace(PTRACE_GETREGS, pid, NULL, ®s) == -1 ||
|
||||
#if defined(__i386)
|
||||
!regs.esp
|
||||
#elif defined(__x86_64)
|
||||
!regs.rsp
|
||||
#endif
|
||||
) {
|
||||
sys_ptrace(PTRACE_DETACH, pid, NULL, NULL);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// Resumes a thread by detaching from it.
|
||||
static bool ResumeThread(pid_t pid) {
|
||||
return sys_ptrace(PTRACE_DETACH, pid, NULL, NULL) >= 0;
|
||||
}
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
LinuxPtraceDumper::LinuxPtraceDumper(pid_t pid)
|
||||
: LinuxDumper(pid),
|
||||
threads_suspended_(false) {
|
||||
}
|
||||
|
||||
bool LinuxPtraceDumper::BuildProcPath(char* path, pid_t pid,
|
||||
const char* node) const {
|
||||
if (!path || !node || pid <= 0)
|
||||
return false;
|
||||
|
||||
size_t node_len = my_strlen(node);
|
||||
if (node_len == 0)
|
||||
return false;
|
||||
|
||||
const unsigned pid_len = my_uint_len(pid);
|
||||
const size_t total_length = 6 + pid_len + 1 + node_len;
|
||||
if (total_length >= NAME_MAX)
|
||||
return false;
|
||||
|
||||
my_memcpy(path, "/proc/", 6);
|
||||
my_uitos(path + 6, pid, pid_len);
|
||||
path[6 + pid_len] = '/';
|
||||
my_memcpy(path + 6 + pid_len + 1, node, node_len);
|
||||
path[total_length] = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LinuxPtraceDumper::CopyFromProcess(void* dest, pid_t child,
|
||||
const void* src, size_t length) {
|
||||
unsigned long tmp = 55;
|
||||
size_t done = 0;
|
||||
static const size_t word_size = sizeof(tmp);
|
||||
uint8_t* const local = (uint8_t*) dest;
|
||||
uint8_t* const remote = (uint8_t*) src;
|
||||
|
||||
while (done < length) {
|
||||
const size_t l = (length - done > word_size) ? word_size : (length - done);
|
||||
if (sys_ptrace(PTRACE_PEEKDATA, child, remote + done, &tmp) == -1) {
|
||||
tmp = 0;
|
||||
}
|
||||
my_memcpy(local + done, &tmp, l);
|
||||
done += l;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read thread info from /proc/$pid/status.
|
||||
// Fill out the |tgid|, |ppid| and |pid| members of |info|. If unavailable,
|
||||
// these members are set to -1. Returns true iff all three members are
|
||||
// available.
|
||||
bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) {
|
||||
if (index >= threads_.size())
|
||||
return false;
|
||||
|
||||
pid_t tid = threads_[index];
|
||||
|
||||
assert(info != NULL);
|
||||
char status_path[NAME_MAX];
|
||||
if (!BuildProcPath(status_path, tid, "status"))
|
||||
return false;
|
||||
|
||||
const int fd = sys_open(status_path, O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
return false;
|
||||
|
||||
LineReader* const line_reader = new(allocator_) LineReader(fd);
|
||||
const char* line;
|
||||
unsigned line_len;
|
||||
|
||||
info->ppid = info->tgid = -1;
|
||||
|
||||
while (line_reader->GetNextLine(&line, &line_len)) {
|
||||
if (my_strncmp("Tgid:\t", line, 6) == 0) {
|
||||
my_strtoui(&info->tgid, line + 6);
|
||||
} else if (my_strncmp("PPid:\t", line, 6) == 0) {
|
||||
my_strtoui(&info->ppid, line + 6);
|
||||
}
|
||||
|
||||
line_reader->PopLine(line_len);
|
||||
}
|
||||
sys_close(fd);
|
||||
|
||||
if (info->ppid == -1 || info->tgid == -1)
|
||||
return false;
|
||||
|
||||
#ifdef PTRACE_GETREGSET
|
||||
struct iovec io;
|
||||
info->GetGeneralPurposeRegisters(&io.iov_base, &io.iov_len);
|
||||
if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_PRSTATUS, (void*)&io) == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
info->GetFloatingPointRegisters(&io.iov_base, &io.iov_len);
|
||||
if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_FPREGSET, (void*)&io) == -1) {
|
||||
return false;
|
||||
}
|
||||
#else // PTRACE_GETREGSET
|
||||
void* gp_addr;
|
||||
info->GetGeneralPurposeRegisters(&gp_addr, NULL);
|
||||
if (sys_ptrace(PTRACE_GETREGS, tid, NULL, gp_addr) == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !(defined(__ANDROID__) && defined(__ARM_EABI__))
|
||||
// When running an arm build on an arm64 device, attempting to get the
|
||||
// floating point registers fails. On Android, the floating point registers
|
||||
// aren't written to the cpu context anyway, so just don't get them here.
|
||||
// See http://crbug.com/508324
|
||||
void* fp_addr;
|
||||
info->GetFloatingPointRegisters(&fp_addr, NULL);
|
||||
if (sys_ptrace(PTRACE_GETFPREGS, tid, NULL, fp_addr) == -1) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif // PTRACE_GETREGSET
|
||||
|
||||
#if defined(__i386)
|
||||
#if !defined(bit_FXSAVE) // e.g. Clang
|
||||
#define bit_FXSAVE bit_FXSR
|
||||
#endif
|
||||
// Detect if the CPU supports the FXSAVE/FXRSTOR instructions
|
||||
int eax, ebx, ecx, edx;
|
||||
__cpuid(1, eax, ebx, ecx, edx);
|
||||
if (edx & bit_FXSAVE) {
|
||||
if (sys_ptrace(PTRACE_GETFPXREGS, tid, NULL, &info->fpxregs) == -1) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
memset(&info->fpxregs, 0, sizeof(info->fpxregs));
|
||||
}
|
||||
#endif // defined(__i386)
|
||||
|
||||
#if defined(__i386) || defined(__x86_64)
|
||||
for (unsigned i = 0; i < ThreadInfo::kNumDebugRegisters; ++i) {
|
||||
if (sys_ptrace(
|
||||
PTRACE_PEEKUSER, tid,
|
||||
reinterpret_cast<void*> (offsetof(struct user,
|
||||
u_debugreg[0]) + i *
|
||||
sizeof(debugreg_t)),
|
||||
&info->dregs[i]) == -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__mips__)
|
||||
sys_ptrace(PTRACE_PEEKUSER, tid,
|
||||
reinterpret_cast<void*>(DSP_BASE), &info->mcontext.hi1);
|
||||
sys_ptrace(PTRACE_PEEKUSER, tid,
|
||||
reinterpret_cast<void*>(DSP_BASE + 1), &info->mcontext.lo1);
|
||||
sys_ptrace(PTRACE_PEEKUSER, tid,
|
||||
reinterpret_cast<void*>(DSP_BASE + 2), &info->mcontext.hi2);
|
||||
sys_ptrace(PTRACE_PEEKUSER, tid,
|
||||
reinterpret_cast<void*>(DSP_BASE + 3), &info->mcontext.lo2);
|
||||
sys_ptrace(PTRACE_PEEKUSER, tid,
|
||||
reinterpret_cast<void*>(DSP_BASE + 4), &info->mcontext.hi3);
|
||||
sys_ptrace(PTRACE_PEEKUSER, tid,
|
||||
reinterpret_cast<void*>(DSP_BASE + 5), &info->mcontext.lo3);
|
||||
sys_ptrace(PTRACE_PEEKUSER, tid,
|
||||
reinterpret_cast<void*>(DSP_CONTROL), &info->mcontext.dsp);
|
||||
#endif
|
||||
|
||||
const uint8_t* stack_pointer;
|
||||
#if defined(__i386)
|
||||
my_memcpy(&stack_pointer, &info->regs.esp, sizeof(info->regs.esp));
|
||||
#elif defined(__x86_64)
|
||||
my_memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
|
||||
#elif defined(__ARM_EABI__)
|
||||
my_memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
|
||||
#elif defined(__aarch64__)
|
||||
my_memcpy(&stack_pointer, &info->regs.sp, sizeof(info->regs.sp));
|
||||
#elif defined(__mips__)
|
||||
stack_pointer =
|
||||
reinterpret_cast<uint8_t*>(info->mcontext.gregs[MD_CONTEXT_MIPS_REG_SP]);
|
||||
#else
|
||||
#error "This code hasn't been ported to your platform yet."
|
||||
#endif
|
||||
info->stack_pointer = reinterpret_cast<uintptr_t>(stack_pointer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LinuxPtraceDumper::IsPostMortem() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LinuxPtraceDumper::ThreadsSuspend() {
|
||||
if (threads_suspended_)
|
||||
return true;
|
||||
for (size_t i = 0; i < threads_.size(); ++i) {
|
||||
if (!SuspendThread(threads_[i])) {
|
||||
// If the thread either disappeared before we could attach to it, or if
|
||||
// it was part of the seccomp sandbox's trusted code, it is OK to
|
||||
// silently drop it from the minidump.
|
||||
if (i < threads_.size() - 1) {
|
||||
my_memmove(&threads_[i], &threads_[i + 1],
|
||||
(threads_.size() - i - 1) * sizeof(threads_[i]));
|
||||
}
|
||||
threads_.resize(threads_.size() - 1);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
threads_suspended_ = true;
|
||||
return threads_.size() > 0;
|
||||
}
|
||||
|
||||
bool LinuxPtraceDumper::ThreadsResume() {
|
||||
if (!threads_suspended_)
|
||||
return false;
|
||||
bool good = true;
|
||||
for (size_t i = 0; i < threads_.size(); ++i)
|
||||
good &= ResumeThread(threads_[i]);
|
||||
threads_suspended_ = false;
|
||||
return good;
|
||||
}
|
||||
|
||||
// Parse /proc/$pid/task to list all the threads of the process identified by
|
||||
// pid.
|
||||
bool LinuxPtraceDumper::EnumerateThreads() {
|
||||
char task_path[NAME_MAX];
|
||||
if (!BuildProcPath(task_path, pid_, "task"))
|
||||
return false;
|
||||
|
||||
const int fd = sys_open(task_path, O_RDONLY | O_DIRECTORY, 0);
|
||||
if (fd < 0)
|
||||
return false;
|
||||
DirectoryReader* dir_reader = new(allocator_) DirectoryReader(fd);
|
||||
|
||||
// The directory may contain duplicate entries which we filter by assuming
|
||||
// that they are consecutive.
|
||||
int last_tid = -1;
|
||||
const char* dent_name;
|
||||
while (dir_reader->GetNextEntry(&dent_name)) {
|
||||
if (my_strcmp(dent_name, ".") &&
|
||||
my_strcmp(dent_name, "..")) {
|
||||
int tid = 0;
|
||||
if (my_strtoui(&tid, dent_name) &&
|
||||
last_tid != tid) {
|
||||
last_tid = tid;
|
||||
threads_.push_back(tid);
|
||||
}
|
||||
}
|
||||
dir_reader->PopEntry();
|
||||
}
|
||||
|
||||
sys_close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -1,92 +0,0 @@
|
|||
// 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.
|
||||
|
||||
// linux_ptrace_dumper.h: Define the google_breakpad::LinuxPtraceDumper
|
||||
// class, which is derived from google_breakpad::LinuxDumper to extract
|
||||
// information from a crashed process via ptrace.
|
||||
// This class was originally splitted from google_breakpad::LinuxDumper.
|
||||
|
||||
#ifndef CLIENT_LINUX_MINIDUMP_WRITER_LINUX_PTRACE_DUMPER_H_
|
||||
#define CLIENT_LINUX_MINIDUMP_WRITER_LINUX_PTRACE_DUMPER_H_
|
||||
|
||||
#include "client/linux/minidump_writer/linux_dumper.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
class LinuxPtraceDumper : public LinuxDumper {
|
||||
public:
|
||||
// Constructs a dumper for extracting information of a given process
|
||||
// with a process ID of |pid|.
|
||||
explicit LinuxPtraceDumper(pid_t pid);
|
||||
|
||||
// Implements LinuxDumper::BuildProcPath().
|
||||
// Builds a proc path for a certain pid for a node (/proc/<pid>/<node>).
|
||||
// |path| is a character array of at least NAME_MAX bytes to return the
|
||||
// result. |node| is the final node without any slashes. Returns true on
|
||||
// success.
|
||||
virtual bool BuildProcPath(char* path, pid_t pid, const char* node) const;
|
||||
|
||||
// Implements LinuxDumper::CopyFromProcess().
|
||||
// Copies content of |length| bytes from a given process |child|,
|
||||
// starting from |src|, into |dest|. This method uses ptrace to extract
|
||||
// the content from the target process. Always returns true.
|
||||
virtual bool CopyFromProcess(void* dest, pid_t child, const void* src,
|
||||
size_t length);
|
||||
|
||||
// Implements LinuxDumper::GetThreadInfoByIndex().
|
||||
// Reads information about the |index|-th thread of |threads_|.
|
||||
// Returns true on success. One must have called |ThreadsSuspend| first.
|
||||
virtual bool GetThreadInfoByIndex(size_t index, ThreadInfo* info);
|
||||
|
||||
// Implements LinuxDumper::IsPostMortem().
|
||||
// Always returns false to indicate this dumper performs a dump of
|
||||
// a crashed process via ptrace.
|
||||
virtual bool IsPostMortem() const;
|
||||
|
||||
// Implements LinuxDumper::ThreadsSuspend().
|
||||
// Suspends all threads in the given process. Returns true on success.
|
||||
virtual bool ThreadsSuspend();
|
||||
|
||||
// Implements LinuxDumper::ThreadsResume().
|
||||
// Resumes all threads in the given process. Returns true on success.
|
||||
virtual bool ThreadsResume();
|
||||
|
||||
protected:
|
||||
// Implements LinuxDumper::EnumerateThreads().
|
||||
// Enumerates all threads of the given process into |threads_|.
|
||||
virtual bool EnumerateThreads();
|
||||
|
||||
private:
|
||||
// Set to true if all threads of the crashed process are suspended.
|
||||
bool threads_suspended_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_HANDLER_LINUX_PTRACE_DUMPER_H_
|
File diff suppressed because it is too large
Load diff
|
@ -1,124 +0,0 @@
|
|||
// Copyright (c) 2009, 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_MINIDUMP_WRITER_MINIDUMP_WRITER_H_
|
||||
#define CLIENT_LINUX_MINIDUMP_WRITER_MINIDUMP_WRITER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ucontext.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <list>
|
||||
#include <utility>
|
||||
|
||||
#include "client/linux/minidump_writer/linux_dumper.h"
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
class ExceptionHandler;
|
||||
|
||||
#if defined(__aarch64__)
|
||||
typedef struct fpsimd_context fpstate_t;
|
||||
#elif !defined(__ARM_EABI__) && !defined(__mips__)
|
||||
typedef struct _libc_fpstate fpstate_t;
|
||||
#endif
|
||||
|
||||
// These entries store a list of memory regions that the client wants included
|
||||
// in the minidump.
|
||||
struct AppMemory {
|
||||
void* ptr;
|
||||
size_t length;
|
||||
|
||||
bool operator==(const struct AppMemory& other) const {
|
||||
return ptr == other.ptr;
|
||||
}
|
||||
|
||||
bool operator==(const void* other) const {
|
||||
return ptr == other;
|
||||
}
|
||||
};
|
||||
typedef std::list<AppMemory> AppMemoryList;
|
||||
|
||||
// Writes a minidump to the filesystem. 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.
|
||||
// minidump_path: the path to the file to write to. This is opened O_EXCL and
|
||||
// fails open fails.
|
||||
// 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
|
||||
//
|
||||
// Returns true iff successful.
|
||||
bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
|
||||
const void* blob, size_t blob_size);
|
||||
// Same as above but takes an open file descriptor instead of a path.
|
||||
bool WriteMinidump(int minidump_fd, pid_t crashing_process,
|
||||
const void* blob, size_t blob_size);
|
||||
|
||||
// Alternate form of WriteMinidump() that works with processes that
|
||||
// are not expected to have crashed. If |process_blamed_thread| is
|
||||
// meaningful, it will be the one from which a crash signature is
|
||||
// extracted. It is not expected that this function will be called
|
||||
// from a compromised context, but it is safe to do so.
|
||||
bool WriteMinidump(const char* minidump_path, pid_t process,
|
||||
pid_t process_blamed_thread);
|
||||
|
||||
// These overloads also allow passing a list of known mappings and
|
||||
// a list of additional memory regions to be included in the minidump.
|
||||
bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
|
||||
const void* blob, size_t blob_size,
|
||||
const MappingList& mappings,
|
||||
const AppMemoryList& appdata);
|
||||
bool WriteMinidump(int minidump_fd, pid_t crashing_process,
|
||||
const void* blob, size_t blob_size,
|
||||
const MappingList& mappings,
|
||||
const AppMemoryList& appdata);
|
||||
|
||||
// These overloads also allow passing a file size limit for the minidump.
|
||||
bool WriteMinidump(const char* minidump_path, off_t minidump_size_limit,
|
||||
pid_t crashing_process,
|
||||
const void* blob, size_t blob_size,
|
||||
const MappingList& mappings,
|
||||
const AppMemoryList& appdata);
|
||||
bool WriteMinidump(int minidump_fd, off_t minidump_size_limit,
|
||||
pid_t crashing_process,
|
||||
const void* blob, size_t blob_size,
|
||||
const MappingList& mappings,
|
||||
const AppMemoryList& appdata);
|
||||
|
||||
bool WriteMinidump(const char* filename,
|
||||
const MappingList& mappings,
|
||||
const AppMemoryList& appdata,
|
||||
LinuxDumper* dumper);
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_MINIDUMP_WRITER_MINIDUMP_WRITER_H_
|
|
@ -1,130 +0,0 @@
|
|||
// Copyright (c) 2013, 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_MINIDUMP_WRITER_PROC_CPUINFO_READER_H_
|
||||
#define CLIENT_LINUX_MINIDUMP_WRITER_PROC_CPUINFO_READER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "client/linux/minidump_writer/line_reader.h"
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// A class for reading /proc/cpuinfo without using fopen/fgets or other
|
||||
// functions which may allocate memory.
|
||||
class ProcCpuInfoReader {
|
||||
public:
|
||||
ProcCpuInfoReader(int fd)
|
||||
: line_reader_(fd), pop_count_(-1) {
|
||||
}
|
||||
|
||||
// Return the next field name, or NULL in case of EOF.
|
||||
// field: (output) Pointer to zero-terminated field name.
|
||||
// Returns true on success, or false on EOF or error (line too long).
|
||||
bool GetNextField(const char** field) {
|
||||
for (;;) {
|
||||
const char* line;
|
||||
unsigned line_len;
|
||||
|
||||
// Try to read next line.
|
||||
if (pop_count_ >= 0) {
|
||||
line_reader_.PopLine(pop_count_);
|
||||
pop_count_ = -1;
|
||||
}
|
||||
|
||||
if (!line_reader_.GetNextLine(&line, &line_len))
|
||||
return false;
|
||||
|
||||
pop_count_ = static_cast<int>(line_len);
|
||||
|
||||
const char* line_end = line + line_len;
|
||||
|
||||
// Expected format: <field-name> <space>+ ':' <space> <value>
|
||||
// Note that:
|
||||
// - empty lines happen.
|
||||
// - <field-name> can contain spaces.
|
||||
// - some fields have an empty <value>
|
||||
char* sep = static_cast<char*>(my_memchr(line, ':', line_len));
|
||||
if (sep == NULL)
|
||||
continue;
|
||||
|
||||
// Record the value. Skip leading space after the column to get
|
||||
// its start.
|
||||
const char* val = sep+1;
|
||||
while (val < line_end && my_isspace(*val))
|
||||
val++;
|
||||
|
||||
value_ = val;
|
||||
value_len_ = static_cast<size_t>(line_end - val);
|
||||
|
||||
// Remove trailing spaces before the column to properly 0-terminate
|
||||
// the field name.
|
||||
while (sep > line && my_isspace(sep[-1]))
|
||||
sep--;
|
||||
|
||||
if (sep == line)
|
||||
continue;
|
||||
|
||||
// zero-terminate field name.
|
||||
*sep = '\0';
|
||||
|
||||
*field = line;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the field value. This must be called after a succesful
|
||||
// call to GetNextField().
|
||||
const char* GetValue() {
|
||||
assert(value_);
|
||||
return value_;
|
||||
}
|
||||
|
||||
// Same as GetValue(), but also returns the length in characters of
|
||||
// the value.
|
||||
const char* GetValueAndLen(size_t* length) {
|
||||
assert(value_);
|
||||
*length = value_len_;
|
||||
return value_;
|
||||
}
|
||||
|
||||
private:
|
||||
LineReader line_reader_;
|
||||
int pop_count_;
|
||||
const char* value_;
|
||||
size_t value_len_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_MINIDUMP_WRITER_PROC_CPUINFO_READER_H_
|
|
@ -1,97 +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.
|
||||
|
||||
// minidump_file_writer-inl.h: Minidump file writer implementation.
|
||||
//
|
||||
// See minidump_file_writer.h for documentation.
|
||||
|
||||
#ifndef CLIENT_MINIDUMP_FILE_WRITER_INL_H__
|
||||
#define CLIENT_MINIDUMP_FILE_WRITER_INL_H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "client/minidump_file_writer.h"
|
||||
#include "google_breakpad/common/minidump_size.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
template<typename MDType>
|
||||
inline bool TypedMDRVA<MDType>::Allocate() {
|
||||
allocation_state_ = SINGLE_OBJECT;
|
||||
return UntypedMDRVA::Allocate(minidump_size<MDType>::size());
|
||||
}
|
||||
|
||||
template<typename MDType>
|
||||
inline bool TypedMDRVA<MDType>::Allocate(size_t additional) {
|
||||
allocation_state_ = SINGLE_OBJECT;
|
||||
return UntypedMDRVA::Allocate(minidump_size<MDType>::size() + additional);
|
||||
}
|
||||
|
||||
template<typename MDType>
|
||||
inline bool TypedMDRVA<MDType>::AllocateArray(size_t count) {
|
||||
assert(count);
|
||||
allocation_state_ = ARRAY;
|
||||
return UntypedMDRVA::Allocate(minidump_size<MDType>::size() * count);
|
||||
}
|
||||
|
||||
template<typename MDType>
|
||||
inline bool TypedMDRVA<MDType>::AllocateObjectAndArray(size_t count,
|
||||
size_t length) {
|
||||
assert(count && length);
|
||||
allocation_state_ = SINGLE_OBJECT_WITH_ARRAY;
|
||||
return UntypedMDRVA::Allocate(minidump_size<MDType>::size() + count * length);
|
||||
}
|
||||
|
||||
template<typename MDType>
|
||||
inline bool TypedMDRVA<MDType>::CopyIndex(unsigned int index, MDType *item) {
|
||||
assert(allocation_state_ == ARRAY);
|
||||
return writer_->Copy(
|
||||
static_cast<MDRVA>(position_ + index * minidump_size<MDType>::size()),
|
||||
item, minidump_size<MDType>::size());
|
||||
}
|
||||
|
||||
template<typename MDType>
|
||||
inline bool TypedMDRVA<MDType>::CopyIndexAfterObject(unsigned int index,
|
||||
const void *src,
|
||||
size_t length) {
|
||||
assert(allocation_state_ == SINGLE_OBJECT_WITH_ARRAY);
|
||||
return writer_->Copy(
|
||||
static_cast<MDRVA>(position_ + minidump_size<MDType>::size()
|
||||
+ index * length),
|
||||
src, length);
|
||||
}
|
||||
|
||||
template<typename MDType>
|
||||
inline bool TypedMDRVA<MDType>::Flush() {
|
||||
return writer_->Copy(position_, &data_, minidump_size<MDType>::size());
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_MINIDUMP_FILE_WRITER_INL_H__
|
|
@ -1,284 +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.
|
||||
|
||||
// minidump_file_writer.cc: Minidump file writer implementation.
|
||||
//
|
||||
// See minidump_file_writer.h for documentation.
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "client/minidump_file_writer-inl.h"
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "common/string_conversion.h"
|
||||
#if defined(__linux__) && __linux__
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
#endif
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
const MDRVA MinidumpFileWriter::kInvalidMDRVA = static_cast<MDRVA>(-1);
|
||||
|
||||
MinidumpFileWriter::MinidumpFileWriter()
|
||||
: file_(-1),
|
||||
close_file_when_destroyed_(true),
|
||||
position_(0),
|
||||
size_(0) {
|
||||
}
|
||||
|
||||
MinidumpFileWriter::~MinidumpFileWriter() {
|
||||
if (close_file_when_destroyed_)
|
||||
Close();
|
||||
}
|
||||
|
||||
bool MinidumpFileWriter::Open(const char *path) {
|
||||
assert(file_ == -1);
|
||||
#if defined(__linux__) && __linux__
|
||||
file_ = sys_open(path, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
#else
|
||||
file_ = open(path, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
#endif
|
||||
|
||||
return file_ != -1;
|
||||
}
|
||||
|
||||
void MinidumpFileWriter::SetFile(const int file) {
|
||||
assert(file_ == -1);
|
||||
file_ = file;
|
||||
close_file_when_destroyed_ = false;
|
||||
}
|
||||
|
||||
bool MinidumpFileWriter::Close() {
|
||||
bool result = true;
|
||||
|
||||
if (file_ != -1) {
|
||||
if (-1 == ftruncate(file_, position_)) {
|
||||
return false;
|
||||
}
|
||||
#if defined(__linux__) && __linux__
|
||||
result = (sys_close(file_) == 0);
|
||||
#else
|
||||
result = (close(file_) == 0);
|
||||
#endif
|
||||
file_ = -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool MinidumpFileWriter::CopyStringToMDString(const wchar_t *str,
|
||||
unsigned int length,
|
||||
TypedMDRVA<MDString> *mdstring) {
|
||||
bool result = true;
|
||||
if (sizeof(wchar_t) == sizeof(uint16_t)) {
|
||||
// Shortcut if wchar_t is the same size as MDString's buffer
|
||||
result = mdstring->Copy(str, mdstring->get()->length);
|
||||
} else {
|
||||
uint16_t out[2];
|
||||
int out_idx = 0;
|
||||
|
||||
// Copy the string character by character
|
||||
while (length && result) {
|
||||
UTF32ToUTF16Char(*str, out);
|
||||
if (!out[0])
|
||||
return false;
|
||||
|
||||
// Process one character at a time
|
||||
--length;
|
||||
++str;
|
||||
|
||||
// Append the one or two UTF-16 characters. The first one will be non-
|
||||
// zero, but the second one may be zero, depending on the conversion from
|
||||
// UTF-32.
|
||||
int out_count = out[1] ? 2 : 1;
|
||||
size_t out_size = sizeof(uint16_t) * out_count;
|
||||
result = mdstring->CopyIndexAfterObject(out_idx, out, out_size);
|
||||
out_idx += out_count;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool MinidumpFileWriter::CopyStringToMDString(const char *str,
|
||||
unsigned int length,
|
||||
TypedMDRVA<MDString> *mdstring) {
|
||||
bool result = true;
|
||||
uint16_t out[2];
|
||||
int out_idx = 0;
|
||||
|
||||
// Copy the string character by character
|
||||
while (length && result) {
|
||||
int conversion_count = UTF8ToUTF16Char(str, length, out);
|
||||
if (!conversion_count)
|
||||
return false;
|
||||
|
||||
// Move the pointer along based on the nubmer of converted characters
|
||||
length -= conversion_count;
|
||||
str += conversion_count;
|
||||
|
||||
// Append the one or two UTF-16 characters
|
||||
int out_count = out[1] ? 2 : 1;
|
||||
size_t out_size = sizeof(uint16_t) * out_count;
|
||||
result = mdstring->CopyIndexAfterObject(out_idx, out, out_size);
|
||||
out_idx += out_count;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename CharType>
|
||||
bool MinidumpFileWriter::WriteStringCore(const CharType *str,
|
||||
unsigned int length,
|
||||
MDLocationDescriptor *location) {
|
||||
assert(str);
|
||||
assert(location);
|
||||
// Calculate the mdstring length by either limiting to |length| as passed in
|
||||
// or by finding the location of the NULL character.
|
||||
unsigned int mdstring_length = 0;
|
||||
if (!length)
|
||||
length = INT_MAX;
|
||||
for (; mdstring_length < length && str[mdstring_length]; ++mdstring_length)
|
||||
;
|
||||
|
||||
// Allocate the string buffer
|
||||
TypedMDRVA<MDString> mdstring(this);
|
||||
if (!mdstring.AllocateObjectAndArray(mdstring_length + 1, sizeof(uint16_t)))
|
||||
return false;
|
||||
|
||||
// Set length excluding the NULL and copy the string
|
||||
mdstring.get()->length =
|
||||
static_cast<uint32_t>(mdstring_length * sizeof(uint16_t));
|
||||
bool result = CopyStringToMDString(str, mdstring_length, &mdstring);
|
||||
|
||||
// NULL terminate
|
||||
if (result) {
|
||||
uint16_t ch = 0;
|
||||
result = mdstring.CopyIndexAfterObject(mdstring_length, &ch, sizeof(ch));
|
||||
|
||||
if (result)
|
||||
*location = mdstring.location();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool MinidumpFileWriter::WriteString(const wchar_t *str, unsigned int length,
|
||||
MDLocationDescriptor *location) {
|
||||
return WriteStringCore(str, length, location);
|
||||
}
|
||||
|
||||
bool MinidumpFileWriter::WriteString(const char *str, unsigned int length,
|
||||
MDLocationDescriptor *location) {
|
||||
return WriteStringCore(str, length, location);
|
||||
}
|
||||
|
||||
bool MinidumpFileWriter::WriteMemory(const void *src, size_t size,
|
||||
MDMemoryDescriptor *output) {
|
||||
assert(src);
|
||||
assert(output);
|
||||
UntypedMDRVA mem(this);
|
||||
|
||||
if (!mem.Allocate(size))
|
||||
return false;
|
||||
if (!mem.Copy(src, mem.size()))
|
||||
return false;
|
||||
|
||||
output->start_of_memory_range = reinterpret_cast<uint64_t>(src);
|
||||
output->memory = mem.location();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MDRVA MinidumpFileWriter::Allocate(size_t size) {
|
||||
assert(size);
|
||||
assert(file_ != -1);
|
||||
size_t aligned_size = (size + 7) & ~7; // 64-bit alignment
|
||||
|
||||
if (position_ + aligned_size > size_) {
|
||||
size_t growth = aligned_size;
|
||||
size_t minimal_growth = getpagesize();
|
||||
|
||||
// Ensure that the file grows by at least the size of a memory page
|
||||
if (growth < minimal_growth)
|
||||
growth = minimal_growth;
|
||||
|
||||
size_t new_size = size_ + growth;
|
||||
if (ftruncate(file_, new_size) != 0)
|
||||
return kInvalidMDRVA;
|
||||
|
||||
size_ = new_size;
|
||||
}
|
||||
|
||||
MDRVA current_position = position_;
|
||||
position_ += static_cast<MDRVA>(aligned_size);
|
||||
|
||||
return current_position;
|
||||
}
|
||||
|
||||
bool MinidumpFileWriter::Copy(MDRVA position, const void *src, ssize_t size) {
|
||||
assert(src);
|
||||
assert(size);
|
||||
assert(file_ != -1);
|
||||
|
||||
// Ensure that the data will fit in the allocated space
|
||||
if (static_cast<size_t>(size + position) > size_)
|
||||
return false;
|
||||
|
||||
// Seek and write the data
|
||||
#if defined(__linux__) && __linux__
|
||||
if (sys_lseek(file_, position, SEEK_SET) == static_cast<off_t>(position)) {
|
||||
if (sys_write(file_, src, size) == size) {
|
||||
#else
|
||||
if (lseek(file_, position, SEEK_SET) == static_cast<off_t>(position)) {
|
||||
if (write(file_, src, size) == size) {
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UntypedMDRVA::Allocate(size_t size) {
|
||||
assert(size_ == 0);
|
||||
size_ = size;
|
||||
position_ = writer_->Allocate(size_);
|
||||
return position_ != MinidumpFileWriter::kInvalidMDRVA;
|
||||
}
|
||||
|
||||
bool UntypedMDRVA::Copy(MDRVA pos, const void *src, size_t size) {
|
||||
assert(src);
|
||||
assert(size);
|
||||
assert(pos + size <= position_ + size_);
|
||||
return writer_->Copy(pos, src, size);
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -1,272 +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.
|
||||
|
||||
// minidump_file_writer.h: Implements file-based minidump generation. It's
|
||||
// intended to be used with the Google Breakpad open source crash handling
|
||||
// project.
|
||||
|
||||
#ifndef CLIENT_MINIDUMP_FILE_WRITER_H__
|
||||
#define CLIENT_MINIDUMP_FILE_WRITER_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
class UntypedMDRVA;
|
||||
template<typename MDType> class TypedMDRVA;
|
||||
|
||||
// The user of this class can Open() a file and add minidump streams, data, and
|
||||
// strings using the definitions in minidump_format.h. Since this class is
|
||||
// expected to be used in a situation where the current process may be
|
||||
// damaged, it will not allocate heap memory.
|
||||
// Sample usage:
|
||||
// MinidumpFileWriter writer;
|
||||
// writer.Open("/tmp/minidump.dmp");
|
||||
// TypedMDRVA<MDRawHeader> header(&writer_);
|
||||
// header.Allocate();
|
||||
// header->get()->signature = MD_HEADER_SIGNATURE;
|
||||
// :
|
||||
// writer.Close();
|
||||
//
|
||||
// An alternative is to use SetFile and provide a file descriptor:
|
||||
// MinidumpFileWriter writer;
|
||||
// writer.SetFile(minidump_fd);
|
||||
// TypedMDRVA<MDRawHeader> header(&writer_);
|
||||
// header.Allocate();
|
||||
// header->get()->signature = MD_HEADER_SIGNATURE;
|
||||
// :
|
||||
// writer.Close();
|
||||
|
||||
class MinidumpFileWriter {
|
||||
public:
|
||||
// Invalid MDRVA (Minidump Relative Virtual Address)
|
||||
// returned on failed allocation
|
||||
static const MDRVA kInvalidMDRVA;
|
||||
|
||||
MinidumpFileWriter();
|
||||
~MinidumpFileWriter();
|
||||
|
||||
// Open |path| as the destination of the minidump data. If |path| already
|
||||
// exists, then Open() will fail.
|
||||
// Return true on success, or false on failure.
|
||||
bool Open(const char *path);
|
||||
|
||||
// Sets the file descriptor |file| as the destination of the minidump data.
|
||||
// Can be used as an alternative to Open() when a file descriptor is
|
||||
// available.
|
||||
// Note that |fd| is not closed when the instance of MinidumpFileWriter is
|
||||
// destroyed.
|
||||
void SetFile(const int file);
|
||||
|
||||
// Close the current file (that was either created when Open was called, or
|
||||
// specified with SetFile).
|
||||
// Return true on success, or false on failure.
|
||||
bool Close();
|
||||
|
||||
// Copy the contents of |str| to a MDString and write it to the file.
|
||||
// |str| is expected to be either UTF-16 or UTF-32 depending on the size
|
||||
// of wchar_t.
|
||||
// Maximum |length| of characters to copy from |str|, or specify 0 to use the
|
||||
// entire NULL terminated string. Copying will stop at the first NULL.
|
||||
// |location| the allocated location
|
||||
// Return true on success, or false on failure
|
||||
bool WriteString(const wchar_t *str, unsigned int length,
|
||||
MDLocationDescriptor *location);
|
||||
|
||||
// Same as above, except with |str| as a UTF-8 string
|
||||
bool WriteString(const char *str, unsigned int length,
|
||||
MDLocationDescriptor *location);
|
||||
|
||||
// Write |size| bytes starting at |src| into the current position.
|
||||
// Return true on success and set |output| to position, or false on failure
|
||||
bool WriteMemory(const void *src, size_t size, MDMemoryDescriptor *output);
|
||||
|
||||
// Copies |size| bytes from |src| to |position|
|
||||
// Return true on success, or false on failure
|
||||
bool Copy(MDRVA position, const void *src, ssize_t size);
|
||||
|
||||
// Return the current position for writing to the minidump
|
||||
inline MDRVA position() const { return position_; }
|
||||
|
||||
private:
|
||||
friend class UntypedMDRVA;
|
||||
|
||||
// Allocates an area of |size| bytes.
|
||||
// Returns the position of the allocation, or kInvalidMDRVA if it was
|
||||
// unable to allocate the bytes.
|
||||
MDRVA Allocate(size_t size);
|
||||
|
||||
// The file descriptor for the output file.
|
||||
int file_;
|
||||
|
||||
// Whether |file_| should be closed when the instance is destroyed.
|
||||
bool close_file_when_destroyed_;
|
||||
|
||||
// Current position in buffer
|
||||
MDRVA position_;
|
||||
|
||||
// Current allocated size
|
||||
size_t size_;
|
||||
|
||||
// Copy |length| characters from |str| to |mdstring|. These are distinct
|
||||
// because the underlying MDString is a UTF-16 based string. The wchar_t
|
||||
// variant may need to create a MDString that has more characters than the
|
||||
// source |str|, whereas the UTF-8 variant may coalesce characters to form
|
||||
// a single UTF-16 character.
|
||||
bool CopyStringToMDString(const wchar_t *str, unsigned int length,
|
||||
TypedMDRVA<MDString> *mdstring);
|
||||
bool CopyStringToMDString(const char *str, unsigned int length,
|
||||
TypedMDRVA<MDString> *mdstring);
|
||||
|
||||
// The common templated code for writing a string
|
||||
template <typename CharType>
|
||||
bool WriteStringCore(const CharType *str, unsigned int length,
|
||||
MDLocationDescriptor *location);
|
||||
};
|
||||
|
||||
// Represents an untyped allocated chunk
|
||||
class UntypedMDRVA {
|
||||
public:
|
||||
explicit UntypedMDRVA(MinidumpFileWriter *writer)
|
||||
: writer_(writer),
|
||||
position_(writer->position()),
|
||||
size_(0) {}
|
||||
|
||||
// Allocates |size| bytes. Must not call more than once.
|
||||
// Return true on success, or false on failure
|
||||
bool Allocate(size_t size);
|
||||
|
||||
// Returns the current position or kInvalidMDRVA if allocation failed
|
||||
inline MDRVA position() const { return position_; }
|
||||
|
||||
// Number of bytes allocated
|
||||
inline size_t size() const { return size_; }
|
||||
|
||||
// Return size and position
|
||||
inline MDLocationDescriptor location() const {
|
||||
MDLocationDescriptor location = { static_cast<uint32_t>(size_),
|
||||
position_ };
|
||||
return location;
|
||||
}
|
||||
|
||||
// Copy |size| bytes starting at |src| into the minidump at |position|
|
||||
// Return true on success, or false on failure
|
||||
bool Copy(MDRVA position, const void *src, size_t size);
|
||||
|
||||
// Copy |size| bytes from |src| to the current position
|
||||
inline bool Copy(const void *src, size_t size) {
|
||||
return Copy(position_, src, size);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Writer we associate with
|
||||
MinidumpFileWriter *writer_;
|
||||
|
||||
// Position of the start of the data
|
||||
MDRVA position_;
|
||||
|
||||
// Allocated size
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
// Represents a Minidump object chunk. Additional memory can be allocated at
|
||||
// the end of the object as a:
|
||||
// - single allocation
|
||||
// - Array of MDType objects
|
||||
// - A MDType object followed by an array
|
||||
template<typename MDType>
|
||||
class TypedMDRVA : public UntypedMDRVA {
|
||||
public:
|
||||
// Constructs an unallocated MDRVA
|
||||
explicit TypedMDRVA(MinidumpFileWriter *writer)
|
||||
: UntypedMDRVA(writer),
|
||||
data_(),
|
||||
allocation_state_(UNALLOCATED) {}
|
||||
|
||||
inline ~TypedMDRVA() {
|
||||
// Ensure that the data_ object is written out
|
||||
if (allocation_state_ != ARRAY)
|
||||
Flush();
|
||||
}
|
||||
|
||||
// Address of object data_ of MDType. This is not declared const as the
|
||||
// typical usage will be to access the underlying |data_| object as to
|
||||
// alter its contents.
|
||||
MDType *get() { return &data_; }
|
||||
|
||||
// Allocates minidump_size<MDType>::size() bytes.
|
||||
// Must not call more than once.
|
||||
// Return true on success, or false on failure
|
||||
bool Allocate();
|
||||
|
||||
// Allocates minidump_size<MDType>::size() + |additional| bytes.
|
||||
// Must not call more than once.
|
||||
// Return true on success, or false on failure
|
||||
bool Allocate(size_t additional);
|
||||
|
||||
// Allocate an array of |count| elements of MDType.
|
||||
// Must not call more than once.
|
||||
// Return true on success, or false on failure
|
||||
bool AllocateArray(size_t count);
|
||||
|
||||
// Allocate an array of |count| elements of |size| after object of MDType
|
||||
// Must not call more than once.
|
||||
// Return true on success, or false on failure
|
||||
bool AllocateObjectAndArray(size_t count, size_t size);
|
||||
|
||||
// Copy |item| to |index|
|
||||
// Must have been allocated using AllocateArray().
|
||||
// Return true on success, or false on failure
|
||||
bool CopyIndex(unsigned int index, MDType *item);
|
||||
|
||||
// Copy |size| bytes starting at |str| to |index|
|
||||
// Must have been allocated using AllocateObjectAndArray().
|
||||
// Return true on success, or false on failure
|
||||
bool CopyIndexAfterObject(unsigned int index, const void *src, size_t size);
|
||||
|
||||
// Write data_
|
||||
bool Flush();
|
||||
|
||||
private:
|
||||
enum AllocationState {
|
||||
UNALLOCATED = 0,
|
||||
SINGLE_OBJECT,
|
||||
ARRAY,
|
||||
SINGLE_OBJECT_WITH_ARRAY
|
||||
};
|
||||
|
||||
MDType data_;
|
||||
AllocationState allocation_state_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_MINIDUMP_FILE_WRITER_H__
|
|
@ -1,489 +0,0 @@
|
|||
// 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.
|
||||
|
||||
// A minimalistic implementation of getcontext() to be used by
|
||||
// Google Breakpad on Android.
|
||||
|
||||
#include "common/android/ucontext_constants.h"
|
||||
|
||||
/* int getcontext (ucontext_t *ucp) */
|
||||
|
||||
#if defined(__arm__)
|
||||
|
||||
.text
|
||||
.global breakpad_getcontext
|
||||
.hidden breakpad_getcontext
|
||||
.type breakpad_getcontext, #function
|
||||
.align 0
|
||||
.fnstart
|
||||
breakpad_getcontext:
|
||||
|
||||
/* First, save r4-r11 */
|
||||
add r1, r0, #(MCONTEXT_GREGS_OFFSET + 4*4)
|
||||
stm r1, {r4-r11}
|
||||
|
||||
/* r12 is a scratch register, don't save it */
|
||||
|
||||
/* Save sp and lr explicitly. */
|
||||
/* - sp can't be stored with stmia in Thumb-2 */
|
||||
/* - STM instructions that store sp and pc are deprecated in ARM */
|
||||
str sp, [r0, #(MCONTEXT_GREGS_OFFSET + 13*4)]
|
||||
str lr, [r0, #(MCONTEXT_GREGS_OFFSET + 14*4)]
|
||||
|
||||
/* Save the caller's address in 'pc' */
|
||||
str lr, [r0, #(MCONTEXT_GREGS_OFFSET + 15*4)]
|
||||
|
||||
/* Save ucontext_t* pointer across next call */
|
||||
mov r4, r0
|
||||
|
||||
/* Call sigprocmask(SIG_BLOCK, NULL, &(ucontext->uc_sigmask)) */
|
||||
mov r0, #0 /* SIG_BLOCK */
|
||||
mov r1, #0 /* NULL */
|
||||
add r2, r4, #UCONTEXT_SIGMASK_OFFSET
|
||||
bl sigprocmask(PLT)
|
||||
|
||||
/* Intentionally do not save the FPU state here. This is because on
|
||||
* Linux/ARM, one should instead use ptrace(PTRACE_GETFPREGS) or
|
||||
* ptrace(PTRACE_GETVFPREGS) to get it.
|
||||
*
|
||||
* Note that a real implementation of getcontext() would need to save
|
||||
* this here to allow setcontext()/swapcontext() to work correctly.
|
||||
*/
|
||||
|
||||
/* Restore the values of r4 and lr */
|
||||
mov r0, r4
|
||||
ldr lr, [r0, #(MCONTEXT_GREGS_OFFSET + 14*4)]
|
||||
ldr r4, [r0, #(MCONTEXT_GREGS_OFFSET + 4*4)]
|
||||
|
||||
/* Return 0 */
|
||||
mov r0, #0
|
||||
bx lr
|
||||
|
||||
.fnend
|
||||
.size breakpad_getcontext, . - breakpad_getcontext
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
#define _NSIG 64
|
||||
#define __NR_rt_sigprocmask 135
|
||||
|
||||
.text
|
||||
.global breakpad_getcontext
|
||||
.hidden breakpad_getcontext
|
||||
.type breakpad_getcontext, #function
|
||||
.align 4
|
||||
.cfi_startproc
|
||||
breakpad_getcontext:
|
||||
|
||||
/* The saved context will return to the getcontext() call point
|
||||
with a return value of 0 */
|
||||
str xzr, [x0, MCONTEXT_GREGS_OFFSET + 0 * REGISTER_SIZE]
|
||||
|
||||
stp x18, x19, [x0, MCONTEXT_GREGS_OFFSET + 18 * REGISTER_SIZE]
|
||||
stp x20, x21, [x0, MCONTEXT_GREGS_OFFSET + 20 * REGISTER_SIZE]
|
||||
stp x22, x23, [x0, MCONTEXT_GREGS_OFFSET + 22 * REGISTER_SIZE]
|
||||
stp x24, x25, [x0, MCONTEXT_GREGS_OFFSET + 24 * REGISTER_SIZE]
|
||||
stp x26, x27, [x0, MCONTEXT_GREGS_OFFSET + 26 * REGISTER_SIZE]
|
||||
stp x28, x29, [x0, MCONTEXT_GREGS_OFFSET + 28 * REGISTER_SIZE]
|
||||
str x30, [x0, MCONTEXT_GREGS_OFFSET + 30 * REGISTER_SIZE]
|
||||
|
||||
/* Place LR into the saved PC, this will ensure that when
|
||||
switching to this saved context with setcontext() control
|
||||
will pass back to the caller of getcontext(), we have
|
||||
already arranged to return the appropriate return value in x0
|
||||
above. */
|
||||
str x30, [x0, MCONTEXT_PC_OFFSET]
|
||||
|
||||
/* Save the current SP */
|
||||
mov x2, sp
|
||||
str x2, [x0, MCONTEXT_SP_OFFSET]
|
||||
|
||||
/* Initialize the pstate. */
|
||||
str xzr, [x0, MCONTEXT_PSTATE_OFFSET]
|
||||
|
||||
/* Figure out where to place the first context extension
|
||||
block. */
|
||||
add x2, x0, #MCONTEXT_EXTENSION_OFFSET
|
||||
|
||||
/* Write the context extension fpsimd header. */
|
||||
mov w3, #(FPSIMD_MAGIC & 0xffff)
|
||||
movk w3, #(FPSIMD_MAGIC >> 16), lsl #16
|
||||
str w3, [x2, #FPSIMD_CONTEXT_MAGIC_OFFSET]
|
||||
mov w3, #FPSIMD_CONTEXT_SIZE
|
||||
str w3, [x2, #FPSIMD_CONTEXT_SIZE_OFFSET]
|
||||
|
||||
/* Fill in the FP SIMD context. */
|
||||
add x3, x2, #(FPSIMD_CONTEXT_VREGS_OFFSET + 8 * SIMD_REGISTER_SIZE)
|
||||
stp d8, d9, [x3], #(2 * SIMD_REGISTER_SIZE)
|
||||
stp d10, d11, [x3], #(2 * SIMD_REGISTER_SIZE)
|
||||
stp d12, d13, [x3], #(2 * SIMD_REGISTER_SIZE)
|
||||
stp d14, d15, [x3], #(2 * SIMD_REGISTER_SIZE)
|
||||
|
||||
add x3, x2, FPSIMD_CONTEXT_FPSR_OFFSET
|
||||
|
||||
mrs x4, fpsr
|
||||
str w4, [x3]
|
||||
|
||||
mrs x4, fpcr
|
||||
str w4, [x3, FPSIMD_CONTEXT_FPCR_OFFSET - FPSIMD_CONTEXT_FPSR_OFFSET]
|
||||
|
||||
/* Write the termination context extension header. */
|
||||
add x2, x2, #FPSIMD_CONTEXT_SIZE
|
||||
|
||||
str xzr, [x2, #FPSIMD_CONTEXT_MAGIC_OFFSET]
|
||||
str xzr, [x2, #FPSIMD_CONTEXT_SIZE_OFFSET]
|
||||
|
||||
/* Grab the signal mask */
|
||||
/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
|
||||
add x2, x0, #UCONTEXT_SIGMASK_OFFSET
|
||||
mov x0, #0 /* SIG_BLOCK */
|
||||
mov x1, #0 /* NULL */
|
||||
mov x3, #(_NSIG / 8)
|
||||
mov x8, #__NR_rt_sigprocmask
|
||||
svc 0
|
||||
|
||||
/* Return x0 for success */
|
||||
mov x0, 0
|
||||
ret
|
||||
|
||||
.cfi_endproc
|
||||
.size breakpad_getcontext, . - breakpad_getcontext
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
.text
|
||||
.global breakpad_getcontext
|
||||
.hidden breakpad_getcontext
|
||||
.align 4
|
||||
.type breakpad_getcontext, @function
|
||||
|
||||
breakpad_getcontext:
|
||||
|
||||
movl 4(%esp), %eax /* eax = uc */
|
||||
|
||||
/* Save register values */
|
||||
movl %ecx, MCONTEXT_ECX_OFFSET(%eax)
|
||||
movl %edx, MCONTEXT_EDX_OFFSET(%eax)
|
||||
movl %ebx, MCONTEXT_EBX_OFFSET(%eax)
|
||||
movl %edi, MCONTEXT_EDI_OFFSET(%eax)
|
||||
movl %esi, MCONTEXT_ESI_OFFSET(%eax)
|
||||
movl %ebp, MCONTEXT_EBP_OFFSET(%eax)
|
||||
|
||||
movl (%esp), %edx /* return address */
|
||||
lea 4(%esp), %ecx /* exclude return address from stack */
|
||||
mov %edx, MCONTEXT_EIP_OFFSET(%eax)
|
||||
mov %ecx, MCONTEXT_ESP_OFFSET(%eax)
|
||||
|
||||
xorl %ecx, %ecx
|
||||
movw %fs, %cx
|
||||
mov %ecx, MCONTEXT_FS_OFFSET(%eax)
|
||||
|
||||
movl $0, MCONTEXT_EAX_OFFSET(%eax)
|
||||
|
||||
/* Save floating point state to fpregstate, then update
|
||||
* the fpregs pointer to point to it */
|
||||
leal UCONTEXT_FPREGS_MEM_OFFSET(%eax), %ecx
|
||||
fnstenv (%ecx)
|
||||
fldenv (%ecx)
|
||||
mov %ecx, UCONTEXT_FPREGS_OFFSET(%eax)
|
||||
|
||||
/* Save signal mask: sigprocmask(SIGBLOCK, NULL, &uc->uc_sigmask) */
|
||||
leal UCONTEXT_SIGMASK_OFFSET(%eax), %edx
|
||||
xorl %ecx, %ecx
|
||||
push %edx /* &uc->uc_sigmask */
|
||||
push %ecx /* NULL */
|
||||
push %ecx /* SIGBLOCK == 0 on i386 */
|
||||
call sigprocmask@PLT
|
||||
addl $12, %esp
|
||||
|
||||
movl $0, %eax
|
||||
ret
|
||||
|
||||
.size breakpad_getcontext, . - breakpad_getcontext
|
||||
|
||||
#elif defined(__mips__)
|
||||
|
||||
// This implementation is inspired by implementation of getcontext in glibc.
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
#include <asm/asm.h>
|
||||
#include <asm/regdef.h>
|
||||
#include <asm/fpregdef.h>
|
||||
#else
|
||||
#include <machine/asm.h>
|
||||
#include <machine/regdef.h>
|
||||
#endif
|
||||
|
||||
// from asm/asm.h
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
#define ALSZ 7
|
||||
#define ALMASK ~7
|
||||
#define SZREG 4
|
||||
#else // _MIPS_SIM != _ABIO32
|
||||
#define ALSZ 15
|
||||
#define ALMASK ~15
|
||||
#define SZREG 8
|
||||
#endif
|
||||
|
||||
#include <asm/unistd.h> // for __NR_rt_sigprocmask
|
||||
|
||||
#define _NSIG8 128 / 8
|
||||
#define SIG_BLOCK 1
|
||||
|
||||
|
||||
.text
|
||||
LOCALS_NUM = 1 // save gp on stack
|
||||
FRAME_SIZE = ((LOCALS_NUM * SZREG) + ALSZ) & ALMASK
|
||||
|
||||
GP_FRAME_OFFSET = FRAME_SIZE - (1 * SZREG)
|
||||
MCONTEXT_REG_SIZE = 8
|
||||
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
|
||||
NESTED (breakpad_getcontext, FRAME_SIZE, ra)
|
||||
.mask 0x00000000, 0
|
||||
.fmask 0x00000000, 0
|
||||
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
.set reorder
|
||||
|
||||
move a2, sp
|
||||
#define _SP a2
|
||||
|
||||
addiu sp, -FRAME_SIZE
|
||||
.cprestore GP_FRAME_OFFSET
|
||||
|
||||
sw s0, (16 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw s1, (17 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw s2, (18 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw s3, (19 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw s4, (20 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw s5, (21 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw s6, (22 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw s7, (23 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw _SP, (29 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw fp, (30 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw ra, (31 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sw ra, MCONTEXT_PC_OFFSET(a0)
|
||||
|
||||
#ifdef __mips_hard_float
|
||||
s.d fs0, (20 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d fs1, (22 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d fs2, (24 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d fs3, (26 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d fs4, (28 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d fs5, (30 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
|
||||
cfc1 v1, fcr31
|
||||
sw v1, MCONTEXT_FPC_CSR(a0)
|
||||
#endif // __mips_hard_float
|
||||
|
||||
/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
|
||||
li a3, _NSIG8
|
||||
addu a2, a0, UCONTEXT_SIGMASK_OFFSET
|
||||
move a1, zero
|
||||
li a0, SIG_BLOCK
|
||||
li v0, __NR_rt_sigprocmask
|
||||
syscall
|
||||
|
||||
addiu sp, FRAME_SIZE
|
||||
jr ra
|
||||
|
||||
END (breakpad_getcontext)
|
||||
#else
|
||||
|
||||
#ifndef NESTED
|
||||
/*
|
||||
* NESTED - declare nested routine entry point
|
||||
*/
|
||||
#define NESTED(symbol, framesize, rpc) \
|
||||
.globl symbol; \
|
||||
.align 2; \
|
||||
.type symbol,@function; \
|
||||
.ent symbol,0; \
|
||||
symbol: .frame sp, framesize, rpc;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* END - mark end of function
|
||||
*/
|
||||
#ifndef END
|
||||
# define END(function) \
|
||||
.end function; \
|
||||
.size function,.-function
|
||||
#endif
|
||||
|
||||
/* int getcontext (ucontext_t *ucp) */
|
||||
|
||||
NESTED (breakpad_getcontext, FRAME_SIZE, ra)
|
||||
.mask 0x10000000, 0
|
||||
.fmask 0x00000000, 0
|
||||
|
||||
move a2, sp
|
||||
#define _SP a2
|
||||
move a3, gp
|
||||
#define _GP a3
|
||||
|
||||
daddiu sp, -FRAME_SIZE
|
||||
.cpsetup $25, GP_FRAME_OFFSET, breakpad_getcontext
|
||||
|
||||
/* Store a magic flag. */
|
||||
li v1, 1
|
||||
sd v1, (0 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) /* zero */
|
||||
|
||||
sd s0, (16 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s1, (17 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s2, (18 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s3, (19 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s4, (20 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s5, (21 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s6, (22 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s7, (23 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd _GP, (28 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd _SP, (29 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd s8, (30 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd ra, (31 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
|
||||
sd ra, MCONTEXT_PC_OFFSET(a0)
|
||||
|
||||
#ifdef __mips_hard_float
|
||||
s.d $f24, (24 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d $f25, (25 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d $f26, (26 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d $f27, (27 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d $f28, (28 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d $f29, (29 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d $f30, (30 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
s.d $f31, (31 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
|
||||
|
||||
cfc1 v1, $31
|
||||
sw v1, MCONTEXT_FPC_CSR(a0)
|
||||
#endif /* __mips_hard_float */
|
||||
|
||||
/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
|
||||
li a3, _NSIG8
|
||||
daddu a2, a0, UCONTEXT_SIGMASK_OFFSET
|
||||
move a1, zero
|
||||
li a0, SIG_BLOCK
|
||||
|
||||
li v0, __NR_rt_sigprocmask
|
||||
syscall
|
||||
|
||||
.cpreturn
|
||||
daddiu sp, FRAME_SIZE
|
||||
move v0, zero
|
||||
jr ra
|
||||
|
||||
END (breakpad_getcontext)
|
||||
#endif // _MIPS_SIM == _ABIO32
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
/* The x64 implementation of breakpad_getcontext was derived in part
|
||||
from the implementation of libunwind which requires the following
|
||||
notice. */
|
||||
/* libunwind - a platform-independent unwind library
|
||||
Copyright (C) 2008 Google, Inc
|
||||
Contributed by Paul Pluzhnikov <ppluzhnikov@google.com>
|
||||
Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
|
||||
|
||||
This file is part of libunwind.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
|
||||
.text
|
||||
.global breakpad_getcontext
|
||||
.hidden breakpad_getcontext
|
||||
.align 4
|
||||
.type breakpad_getcontext, @function
|
||||
|
||||
breakpad_getcontext:
|
||||
.cfi_startproc
|
||||
|
||||
/* Callee saved: RBX, RBP, R12-R15 */
|
||||
movq %r12, MCONTEXT_GREGS_R12(%rdi)
|
||||
movq %r13, MCONTEXT_GREGS_R13(%rdi)
|
||||
movq %r14, MCONTEXT_GREGS_R14(%rdi)
|
||||
movq %r15, MCONTEXT_GREGS_R15(%rdi)
|
||||
movq %rbp, MCONTEXT_GREGS_RBP(%rdi)
|
||||
movq %rbx, MCONTEXT_GREGS_RBX(%rdi)
|
||||
|
||||
/* Save argument registers (not strictly needed, but setcontext
|
||||
restores them, so don't restore garbage). */
|
||||
movq %r8, MCONTEXT_GREGS_R8(%rdi)
|
||||
movq %r9, MCONTEXT_GREGS_R9(%rdi)
|
||||
movq %rdi, MCONTEXT_GREGS_RDI(%rdi)
|
||||
movq %rsi, MCONTEXT_GREGS_RSI(%rdi)
|
||||
movq %rdx, MCONTEXT_GREGS_RDX(%rdi)
|
||||
movq %rax, MCONTEXT_GREGS_RAX(%rdi)
|
||||
movq %rcx, MCONTEXT_GREGS_RCX(%rdi)
|
||||
|
||||
/* Save fp state (not needed, except for setcontext not
|
||||
restoring garbage). */
|
||||
leaq MCONTEXT_FPREGS_MEM(%rdi),%r8
|
||||
movq %r8, MCONTEXT_FPREGS_PTR(%rdi)
|
||||
fnstenv (%r8)
|
||||
stmxcsr FPREGS_OFFSET_MXCSR(%r8)
|
||||
|
||||
leaq 8(%rsp), %rax /* exclude this call. */
|
||||
movq %rax, MCONTEXT_GREGS_RSP(%rdi)
|
||||
|
||||
movq 0(%rsp), %rax
|
||||
movq %rax, MCONTEXT_GREGS_RIP(%rdi)
|
||||
|
||||
/* Save signal mask: sigprocmask(SIGBLOCK, NULL, &uc->uc_sigmask) */
|
||||
leaq UCONTEXT_SIGMASK_OFFSET(%rdi), %rdx // arg3
|
||||
xorq %rsi, %rsi // arg2 NULL
|
||||
xorq %rdi, %rdi // arg1 SIGBLOCK == 0
|
||||
call sigprocmask@PLT
|
||||
|
||||
/* Always return 0 for success, even if sigprocmask failed. */
|
||||
xorl %eax, %eax
|
||||
ret
|
||||
.cfi_endproc
|
||||
.size breakpad_getcontext, . - breakpad_getcontext
|
||||
|
||||
#else
|
||||
#error "This file has not been ported for your CPU!"
|
||||
#endif
|
|
@ -1,168 +0,0 @@
|
|||
// 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.
|
||||
#ifndef __WORDSIZE
|
||||
#if defined(__i386__) || defined(__ARM_EABI__) || defined(__mips__)
|
||||
#define __WORDSIZE 32
|
||||
#elif defined(__x86_64__) || defined(__aarch64__)
|
||||
#define __WORDSIZE 64
|
||||
#else
|
||||
#error "Unsupported Android CPU ABI"
|
||||
#endif
|
||||
#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
|
||||
|
||||
#if !defined(SHT_MIPS_DWARF)
|
||||
#define SHT_MIPS_DWARF 0x7000001e
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ELF_H
|
|
@ -1,71 +0,0 @@
|
|||
// 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 all the data-structures required in its <link.h>.
|
||||
Provide custom version here. */
|
||||
#include_next <link.h>
|
||||
|
||||
// TODO(rmcilroy): Remove this file once the ndk is updated for other
|
||||
// architectures - crbug.com/358831
|
||||
#if !defined(__aarch64__) && !defined(__x86_64__) && \
|
||||
!(defined(__mips__) && _MIPS_SIM == _ABI64)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
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 // !defined(__aarch64__) && !defined(__x86_64__)
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_ANDROID_INCLUDE_LINK_H */
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (c) 2013, 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_SGIDEFS_H
|
||||
#define GOOGLE_BREAKPAD_ANDROID_INCLUDE_SGIDEFS_H
|
||||
|
||||
#ifdef __mips__
|
||||
|
||||
// Android doesn't contain sgidefs.h, but does have <asm/sgidefs.h> which
|
||||
// contains what we need.
|
||||
#include <asm/sgidefs.h>
|
||||
|
||||
#endif // __mips__
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_ANDROID_INCLUDE_SGIDEFS_H
|
|
@ -1,100 +0,0 @@
|
|||
// 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
|
|
@ -1,124 +0,0 @@
|
|||
// 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 <asm/ptrace.h>
|
||||
#include <sys/cdefs.h>
|
||||
#if defined (__mips__)
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <sys/user.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#if defined(__x86_64__) || defined(__aarch64__)
|
||||
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))
|
||||
#elif defined(__aarch64__)
|
||||
#define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t))
|
||||
#elif defined(__mips__)
|
||||
#define ELF_NGREG 45
|
||||
#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;
|
||||
#elif defined(__mips__)
|
||||
unsigned long pr_uid;
|
||||
unsigned long 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,35 +0,0 @@
|
|||
// 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_SIGNAL_H
|
||||
#define GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_SIGNAL_H
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_SIGNAL_H
|
|
@ -1,75 +0,0 @@
|
|||
// 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
|
||||
|
||||
// The purpose of this file is to glue the mismatching headers (Android NDK vs
|
||||
// glibc) and therefore avoid doing otherwise awkward #ifdefs in the code.
|
||||
// The following quirks are currently handled by this file:
|
||||
// - i386: Use the Android NDK but alias user_fxsr_struct > user_fpxregs_struct.
|
||||
// - aarch64: Add missing user_regs_struct and user_fpsimd_struct structs.
|
||||
// - Other platforms: Just use the Android NDK unchanged.
|
||||
|
||||
// TODO(primiano): remove these changes after Chromium has stably rolled to
|
||||
// an NDK with the appropriate fixes.
|
||||
|
||||
#include_next <sys/user.h>
|
||||
|
||||
#ifdef __i386__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
typedef struct user_fxsr_struct user_fpxregs_struct;
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
#endif // __i386__
|
||||
|
||||
#ifdef __aarch64__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
struct user_regs_struct {
|
||||
__u64 regs[31];
|
||||
__u64 sp;
|
||||
__u64 pc;
|
||||
__u64 pstate;
|
||||
};
|
||||
struct user_fpsimd_struct {
|
||||
__uint128_t vregs[32];
|
||||
__u32 fpsr;
|
||||
__u32 fpcr;
|
||||
};
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
#endif // __aarch64__
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_USER_H
|
|
@ -1,56 +0,0 @@
|
|||
// 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>
|
||||
|
||||
#ifdef __BIONIC_UCONTEXT_H
|
||||
#include <ucontext.h>
|
||||
#else
|
||||
|
||||
#include <sys/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 // __BIONIC_UCONTEXT_H
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_UCONTEXT_H
|
|
@ -1,144 +0,0 @@
|
|||
// 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.
|
||||
|
||||
// This header can be included either from a C, C++ or Assembly file.
|
||||
// Its purpose is to contain constants that must match the offsets of
|
||||
// various fields in ucontext_t.
|
||||
//
|
||||
// They should match the definitions from
|
||||
// src/common/android/include/sys/ucontext.h
|
||||
//
|
||||
// Used by src/common/android/breakpad_getcontext.S
|
||||
// Tested by src/common/android/testing/breakpad_getcontext_unittest.cc
|
||||
|
||||
#ifndef GOOGLEBREAKPAD_COMMON_ANDROID_UCONTEXT_CONSTANTS_H
|
||||
#define GOOGLEBREAKPAD_COMMON_ANDROID_UCONTEXT_CONSTANTS_H
|
||||
|
||||
#if defined(__arm__)
|
||||
|
||||
#define MCONTEXT_GREGS_OFFSET 32
|
||||
#define UCONTEXT_SIGMASK_OFFSET 104
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
#define UCONTEXT_SIGMASK_OFFSET 40
|
||||
|
||||
#define MCONTEXT_GREGS_OFFSET 184
|
||||
#define MCONTEXT_SP_OFFSET 432
|
||||
#define MCONTEXT_PC_OFFSET 440
|
||||
#define MCONTEXT_PSTATE_OFFSET 448
|
||||
#define MCONTEXT_EXTENSION_OFFSET 464
|
||||
|
||||
#define FPSIMD_MAGIC 0x46508001
|
||||
|
||||
#define FPSIMD_CONTEXT_MAGIC_OFFSET 0
|
||||
#define FPSIMD_CONTEXT_SIZE_OFFSET 4
|
||||
#define FPSIMD_CONTEXT_FPSR_OFFSET 8
|
||||
#define FPSIMD_CONTEXT_FPCR_OFFSET 12
|
||||
#define FPSIMD_CONTEXT_VREGS_OFFSET 16
|
||||
#define FPSIMD_CONTEXT_SIZE 528
|
||||
|
||||
#define REGISTER_SIZE 8
|
||||
#define SIMD_REGISTER_SIZE 16
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
#define MCONTEXT_GREGS_OFFSET 20
|
||||
#define MCONTEXT_GS_OFFSET (MCONTEXT_GREGS_OFFSET + 0*4)
|
||||
#define MCONTEXT_FS_OFFSET (MCONTEXT_GREGS_OFFSET + 1*4)
|
||||
#define MCONTEXT_ES_OFFSET (MCONTEXT_GREGS_OFFSET + 2*4)
|
||||
#define MCONTEXT_DS_OFFSET (MCONTEXT_GREGS_OFFSET + 3*4)
|
||||
#define MCONTEXT_EDI_OFFSET (MCONTEXT_GREGS_OFFSET + 4*4)
|
||||
#define MCONTEXT_ESI_OFFSET (MCONTEXT_GREGS_OFFSET + 5*4)
|
||||
#define MCONTEXT_EBP_OFFSET (MCONTEXT_GREGS_OFFSET + 6*4)
|
||||
#define MCONTEXT_ESP_OFFSET (MCONTEXT_GREGS_OFFSET + 7*4)
|
||||
#define MCONTEXT_EBX_OFFSET (MCONTEXT_GREGS_OFFSET + 8*4)
|
||||
#define MCONTEXT_EDX_OFFSET (MCONTEXT_GREGS_OFFSET + 9*4)
|
||||
#define MCONTEXT_ECX_OFFSET (MCONTEXT_GREGS_OFFSET + 10*4)
|
||||
#define MCONTEXT_EAX_OFFSET (MCONTEXT_GREGS_OFFSET + 11*4)
|
||||
#define MCONTEXT_TRAPNO_OFFSET (MCONTEXT_GREGS_OFFSET + 12*4)
|
||||
#define MCONTEXT_ERR_OFFSET (MCONTEXT_GREGS_OFFSET + 13*4)
|
||||
#define MCONTEXT_EIP_OFFSET (MCONTEXT_GREGS_OFFSET + 14*4)
|
||||
#define MCONTEXT_CS_OFFSET (MCONTEXT_GREGS_OFFSET + 15*4)
|
||||
#define MCONTEXT_EFL_OFFSET (MCONTEXT_GREGS_OFFSET + 16*4)
|
||||
#define MCONTEXT_UESP_OFFSET (MCONTEXT_GREGS_OFFSET + 17*4)
|
||||
#define MCONTEXT_SS_OFFSET (MCONTEXT_GREGS_OFFSET + 18*4)
|
||||
|
||||
#define UCONTEXT_SIGMASK_OFFSET 108
|
||||
|
||||
#define UCONTEXT_FPREGS_OFFSET 96
|
||||
#define UCONTEXT_FPREGS_MEM_OFFSET 116
|
||||
|
||||
#elif defined(__mips__)
|
||||
|
||||
#if _MIPS_SIM == _ABIO32
|
||||
#define MCONTEXT_PC_OFFSET 32
|
||||
#define MCONTEXT_GREGS_OFFSET 40
|
||||
#define MCONTEXT_FPREGS_OFFSET 296
|
||||
#define MCONTEXT_FPC_CSR 556
|
||||
#define UCONTEXT_SIGMASK_OFFSET 616
|
||||
#else
|
||||
#define MCONTEXT_GREGS_OFFSET 40
|
||||
#define MCONTEXT_FPREGS_OFFSET 296
|
||||
#define MCONTEXT_PC_OFFSET 616
|
||||
#define MCONTEXT_FPC_CSR 624
|
||||
#define UCONTEXT_SIGMASK_OFFSET 640
|
||||
#endif
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
|
||||
#define MCONTEXT_GREGS_OFFSET 40
|
||||
#define UCONTEXT_SIGMASK_OFFSET 296
|
||||
|
||||
#define MCONTEXT_GREGS_R8 40
|
||||
#define MCONTEXT_GREGS_R9 48
|
||||
#define MCONTEXT_GREGS_R10 56
|
||||
#define MCONTEXT_GREGS_R11 64
|
||||
#define MCONTEXT_GREGS_R12 72
|
||||
#define MCONTEXT_GREGS_R13 80
|
||||
#define MCONTEXT_GREGS_R14 88
|
||||
#define MCONTEXT_GREGS_R15 96
|
||||
#define MCONTEXT_GREGS_RDI 104
|
||||
#define MCONTEXT_GREGS_RSI 112
|
||||
#define MCONTEXT_GREGS_RBP 120
|
||||
#define MCONTEXT_GREGS_RBX 128
|
||||
#define MCONTEXT_GREGS_RDX 136
|
||||
#define MCONTEXT_GREGS_RAX 144
|
||||
#define MCONTEXT_GREGS_RCX 152
|
||||
#define MCONTEXT_GREGS_RSP 160
|
||||
#define MCONTEXT_GREGS_RIP 168
|
||||
#define MCONTEXT_FPREGS_PTR 224
|
||||
#define MCONTEXT_FPREGS_MEM 304
|
||||
#define FPREGS_OFFSET_MXCSR 24
|
||||
|
||||
#else
|
||||
#error "This header has not been ported for your CPU"
|
||||
#endif
|
||||
|
||||
#endif // GOOGLEBREAKPAD_COMMON_ANDROID_UCONTEXT_CONSTANTS_H
|
|
@ -1,58 +0,0 @@
|
|||
// Copyright (c) 2011 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 COMMON_BASICTYPES_H_
|
||||
#define COMMON_BASICTYPES_H_
|
||||
|
||||
// A macro to disallow the copy constructor and operator= functions
|
||||
// This should be used in the private: declarations for a class
|
||||
#ifndef DISALLOW_COPY_AND_ASSIGN
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
#endif // DISALLOW_COPY_AND_ASSIGN
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// Used to explicitly mark the return value of a function as unused. If you are
|
||||
// really sure you don't want to do anything with the return value of a function
|
||||
// that has been marked with __attribute__((warn_unused_result)), wrap it with
|
||||
// this. Example:
|
||||
//
|
||||
// scoped_ptr<MyType> my_var = ...;
|
||||
// if (TakeOwnership(my_var.get()) == SUCCESS)
|
||||
// ignore_result(my_var.release());
|
||||
//
|
||||
template<typename T>
|
||||
inline void ignore_result(const T&) {
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_BASICTYPES_H_
|
|
@ -1,265 +0,0 @@
|
|||
// -*- mode: c++ -*-
|
||||
|
||||
// Copyright (c) 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
|
||||
// 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.
|
||||
|
||||
// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
|
||||
|
||||
// byte_cursor.h: Classes for parsing values from a buffer of bytes.
|
||||
// The ByteCursor class provides a convenient interface for reading
|
||||
// fixed-size integers of arbitrary endianness, being thorough about
|
||||
// checking for buffer overruns.
|
||||
|
||||
#ifndef COMMON_BYTE_CURSOR_H_
|
||||
#define COMMON_BYTE_CURSOR_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
#include "common/using_std_string.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// A buffer holding a series of bytes.
|
||||
struct ByteBuffer {
|
||||
ByteBuffer() : start(0), end(0) { }
|
||||
ByteBuffer(const uint8_t *set_start, size_t set_size)
|
||||
: start(set_start), end(set_start + set_size) { }
|
||||
~ByteBuffer() { };
|
||||
|
||||
// Equality operators. Useful in unit tests, and when we're using
|
||||
// ByteBuffers to refer to regions of a larger buffer.
|
||||
bool operator==(const ByteBuffer &that) const {
|
||||
return start == that.start && end == that.end;
|
||||
}
|
||||
bool operator!=(const ByteBuffer &that) const {
|
||||
return start != that.start || end != that.end;
|
||||
}
|
||||
|
||||
// Not C++ style guide compliant, but this definitely belongs here.
|
||||
size_t Size() const {
|
||||
assert(start <= end);
|
||||
return end - start;
|
||||
}
|
||||
|
||||
const uint8_t *start, *end;
|
||||
};
|
||||
|
||||
// A cursor pointing into a ByteBuffer that can parse numbers of various
|
||||
// widths and representations, strings, and data blocks, advancing through
|
||||
// the buffer as it goes. All ByteCursor operations check that accesses
|
||||
// haven't gone beyond the end of the enclosing ByteBuffer.
|
||||
class ByteCursor {
|
||||
public:
|
||||
// Create a cursor reading bytes from the start of BUFFER. By default, the
|
||||
// cursor reads multi-byte values in little-endian form.
|
||||
ByteCursor(const ByteBuffer *buffer, bool big_endian = false)
|
||||
: buffer_(buffer), here_(buffer->start),
|
||||
big_endian_(big_endian), complete_(true) { }
|
||||
|
||||
// Accessor and setter for this cursor's endianness flag.
|
||||
bool big_endian() const { return big_endian_; }
|
||||
void set_big_endian(bool big_endian) { big_endian_ = big_endian; }
|
||||
|
||||
// Accessor and setter for this cursor's current position. The setter
|
||||
// returns a reference to this cursor.
|
||||
const uint8_t *here() const { return here_; }
|
||||
ByteCursor &set_here(const uint8_t *here) {
|
||||
assert(buffer_->start <= here && here <= buffer_->end);
|
||||
here_ = here;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Return the number of bytes available to read at the cursor.
|
||||
size_t Available() const { return size_t(buffer_->end - here_); }
|
||||
|
||||
// Return true if this cursor is at the end of its buffer.
|
||||
bool AtEnd() const { return Available() == 0; }
|
||||
|
||||
// When used as a boolean value this cursor converts to true if all
|
||||
// prior reads have been completed, or false if we ran off the end
|
||||
// of the buffer.
|
||||
operator bool() const { return complete_; }
|
||||
|
||||
// Read a SIZE-byte integer at this cursor, signed if IS_SIGNED is true,
|
||||
// unsigned otherwise, using the cursor's established endianness, and set
|
||||
// *RESULT to the number. If we read off the end of our buffer, clear
|
||||
// this cursor's complete_ flag, and store a dummy value in *RESULT.
|
||||
// Return a reference to this cursor.
|
||||
template<typename T>
|
||||
ByteCursor &Read(size_t size, bool is_signed, T *result) {
|
||||
if (CheckAvailable(size)) {
|
||||
T v = 0;
|
||||
if (big_endian_) {
|
||||
for (size_t i = 0; i < size; i++)
|
||||
v = (v << 8) + here_[i];
|
||||
} else {
|
||||
// This loop condition looks weird, but size_t is unsigned, so
|
||||
// decrementing i after it is zero yields the largest size_t value.
|
||||
for (size_t i = size - 1; i < size; i--)
|
||||
v = (v << 8) + here_[i];
|
||||
}
|
||||
if (is_signed && size < sizeof(T)) {
|
||||
size_t sign_bit = (T)1 << (size * 8 - 1);
|
||||
v = (v ^ sign_bit) - sign_bit;
|
||||
}
|
||||
here_ += size;
|
||||
*result = v;
|
||||
} else {
|
||||
*result = (T) 0xdeadbeef;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Read an integer, using the cursor's established endianness and
|
||||
// *RESULT's size and signedness, and set *RESULT to the number. If we
|
||||
// read off the end of our buffer, clear this cursor's complete_ flag.
|
||||
// Return a reference to this cursor.
|
||||
template<typename T>
|
||||
ByteCursor &operator>>(T &result) {
|
||||
bool T_is_signed = (T)-1 < 0;
|
||||
return Read(sizeof(T), T_is_signed, &result);
|
||||
}
|
||||
|
||||
// Copy the SIZE bytes at the cursor to BUFFER, and advance this
|
||||
// cursor to the end of them. If we read off the end of our buffer,
|
||||
// clear this cursor's complete_ flag, and set *POINTER to NULL.
|
||||
// Return a reference to this cursor.
|
||||
ByteCursor &Read(uint8_t *buffer, size_t size) {
|
||||
if (CheckAvailable(size)) {
|
||||
memcpy(buffer, here_, size);
|
||||
here_ += size;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Set STR to a copy of the '\0'-terminated string at the cursor. If the
|
||||
// byte buffer does not contain a terminating zero, clear this cursor's
|
||||
// complete_ flag, and set STR to the empty string. Return a reference to
|
||||
// this cursor.
|
||||
ByteCursor &CString(string *str) {
|
||||
const uint8_t *end
|
||||
= static_cast<const uint8_t *>(memchr(here_, '\0', Available()));
|
||||
if (end) {
|
||||
str->assign(reinterpret_cast<const char *>(here_), end - here_);
|
||||
here_ = end + 1;
|
||||
} else {
|
||||
str->clear();
|
||||
here_ = buffer_->end;
|
||||
complete_ = false;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Like CString(STR), but extract the string from a fixed-width buffer
|
||||
// LIMIT bytes long, which may or may not contain a terminating '\0'
|
||||
// byte. Specifically:
|
||||
//
|
||||
// - If there are not LIMIT bytes available at the cursor, clear the
|
||||
// cursor's complete_ flag and set STR to the empty string.
|
||||
//
|
||||
// - Otherwise, if the LIMIT bytes at the cursor contain any '\0'
|
||||
// characters, set *STR to a copy of the bytes before the first '\0',
|
||||
// and advance the cursor by LIMIT bytes.
|
||||
//
|
||||
// - Otherwise, set *STR to a copy of those LIMIT bytes, and advance the
|
||||
// cursor by LIMIT bytes.
|
||||
ByteCursor &CString(string *str, size_t limit) {
|
||||
if (CheckAvailable(limit)) {
|
||||
const uint8_t *end
|
||||
= static_cast<const uint8_t *>(memchr(here_, '\0', limit));
|
||||
if (end)
|
||||
str->assign(reinterpret_cast<const char *>(here_), end - here_);
|
||||
else
|
||||
str->assign(reinterpret_cast<const char *>(here_), limit);
|
||||
here_ += limit;
|
||||
} else {
|
||||
str->clear();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Set *POINTER to point to the SIZE bytes at the cursor, and advance
|
||||
// this cursor to the end of them. If SIZE is omitted, don't move the
|
||||
// cursor. If we read off the end of our buffer, clear this cursor's
|
||||
// complete_ flag, and set *POINTER to NULL. Return a reference to this
|
||||
// cursor.
|
||||
ByteCursor &PointTo(const uint8_t **pointer, size_t size = 0) {
|
||||
if (CheckAvailable(size)) {
|
||||
*pointer = here_;
|
||||
here_ += size;
|
||||
} else {
|
||||
*pointer = NULL;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Skip SIZE bytes at the cursor. If doing so would advance us off
|
||||
// the end of our buffer, clear this cursor's complete_ flag, and
|
||||
// set *POINTER to NULL. Return a reference to this cursor.
|
||||
ByteCursor &Skip(size_t size) {
|
||||
if (CheckAvailable(size))
|
||||
here_ += size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
// If there are at least SIZE bytes available to read from the buffer,
|
||||
// return true. Otherwise, set here_ to the end of the buffer, set
|
||||
// complete_ to false, and return false.
|
||||
bool CheckAvailable(size_t size) {
|
||||
if (Available() >= size) {
|
||||
return true;
|
||||
} else {
|
||||
here_ = buffer_->end;
|
||||
complete_ = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The buffer we're reading bytes from.
|
||||
const ByteBuffer *buffer_;
|
||||
|
||||
// The next byte within buffer_ that we'll read.
|
||||
const uint8_t *here_;
|
||||
|
||||
// True if we should read numbers in big-endian form; false if we
|
||||
// should read in little-endian form.
|
||||
bool big_endian_;
|
||||
|
||||
// True if we've been able to read all we've been asked to.
|
||||
bool complete_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_BYTE_CURSOR_H_
|
|
@ -1,554 +0,0 @@
|
|||
/*
|
||||
* Copyright © 1991-2015 Unicode, Inc. All rights reserved.
|
||||
* Distributed under the Terms of Use in
|
||||
* http://www.unicode.org/copyright.html.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of the Unicode data files and any associated documentation
|
||||
* (the "Data Files") or Unicode software and any associated documentation
|
||||
* (the "Software") to deal in the Data Files or Software
|
||||
* without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, and/or sell copies of
|
||||
* the Data Files or Software, and to permit persons to whom the Data Files
|
||||
* or Software are furnished to do so, provided that
|
||||
* (a) this copyright and permission notice appear with all copies
|
||||
* of the Data Files or Software,
|
||||
* (b) this copyright and permission notice appear in associated
|
||||
* documentation, and
|
||||
* (c) there is clear notice in each modified Data File or in the Software
|
||||
* as well as in the documentation associated with the Data File(s) or
|
||||
* Software that the data or software has been modified.
|
||||
*
|
||||
* THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
|
||||
* NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
|
||||
* DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THE DATA FILES OR SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of a copyright holder
|
||||
* shall not be used in advertising or otherwise to promote the sale,
|
||||
* use or other dealings in these Data Files or Software without prior
|
||||
* written authorization of the copyright holder.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
Conversions between UTF32, UTF-16, and UTF-8. Source code file.
|
||||
Author: Mark E. Davis, 1994.
|
||||
Rev History: Rick McGowan, fixes & updates May 2001.
|
||||
Sept 2001: fixed const & error conditions per
|
||||
mods suggested by S. Parent & A. Lillich.
|
||||
June 2002: Tim Dodd added detection and handling of incomplete
|
||||
source sequences, enhanced error detection, added casts
|
||||
to eliminate compiler warnings.
|
||||
July 2003: slight mods to back out aggressive FFFE detection.
|
||||
Jan 2004: updated switches in from-UTF8 conversions.
|
||||
Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
|
||||
|
||||
See the header file "ConvertUTF.h" for complete documentation.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#include "convert_UTF.h"
|
||||
#ifdef CVTUTF_DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
static const int halfShift = 10; /* used for shifting by 10 bits */
|
||||
|
||||
static const UTF32 halfBase = 0x0010000UL;
|
||||
static const UTF32 halfMask = 0x3FFUL;
|
||||
|
||||
#define UNI_SUR_HIGH_START (UTF32)0xD800
|
||||
#define UNI_SUR_HIGH_END (UTF32)0xDBFF
|
||||
#define UNI_SUR_LOW_START (UTF32)0xDC00
|
||||
#define UNI_SUR_LOW_END (UTF32)0xDFFF
|
||||
|
||||
#ifndef false
|
||||
#define false 0
|
||||
#endif
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF32toUTF16 (const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF32* source = *sourceStart;
|
||||
UTF16* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch;
|
||||
if (target >= targetEnd) {
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
ch = *source++;
|
||||
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
|
||||
/* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
|
||||
if (flags == strictConversion) {
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
*target++ = (UTF16)ch; /* normal case */
|
||||
}
|
||||
} else if (ch > UNI_MAX_LEGAL_UTF32) {
|
||||
if (flags == strictConversion) {
|
||||
result = sourceIllegal;
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
/* target is a character in range 0xFFFF - 0x10FFFF. */
|
||||
if (target + 1 >= targetEnd) {
|
||||
--source; /* Back up source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
ch -= halfBase;
|
||||
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
|
||||
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
|
||||
}
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF16toUTF32 (const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF16* source = *sourceStart;
|
||||
UTF32* target = *targetStart;
|
||||
UTF32 ch, ch2;
|
||||
while (source < sourceEnd) {
|
||||
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
|
||||
ch = *source++;
|
||||
/* If we have a surrogate pair, convert to UTF32 first. */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
|
||||
/* If the 16 bits following the high surrogate are in the source buffer... */
|
||||
if (source < sourceEnd) {
|
||||
ch2 = *source;
|
||||
/* If it's a low surrogate, convert to UTF32. */
|
||||
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
|
||||
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
|
||||
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
|
||||
++source;
|
||||
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
} else { /* We don't have the 16 bits following the high surrogate. */
|
||||
--source; /* return to the high surrogate */
|
||||
result = sourceExhausted;
|
||||
break;
|
||||
}
|
||||
} else if (flags == strictConversion) {
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (target >= targetEnd) {
|
||||
source = oldSource; /* Back up source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
*target++ = ch;
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
#ifdef CVTUTF_DEBUG
|
||||
if (result == sourceIllegal) {
|
||||
fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
|
||||
fflush(stderr);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Index into the table below with the first byte of a UTF-8 sequence to
|
||||
* get the number of trailing bytes that are supposed to follow it.
|
||||
* Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
|
||||
* left as-is for anyone who may want to do such conversion, which was
|
||||
* allowed in earlier algorithms.
|
||||
*/
|
||||
static const char trailingBytesForUTF8[256] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
|
||||
};
|
||||
|
||||
/*
|
||||
* Magic values subtracted from a buffer value during UTF8 conversion.
|
||||
* This table contains as many values as there might be trailing bytes
|
||||
* in a UTF-8 sequence.
|
||||
*/
|
||||
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
|
||||
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
|
||||
|
||||
/*
|
||||
* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
|
||||
* into the first byte, depending on how many bytes follow. There are
|
||||
* as many entries in this table as there are UTF-8 sequence types.
|
||||
* (I.e., one byte sequence, two byte... etc.). Remember that sequencs
|
||||
* for *legal* UTF-8 will be 4 or fewer bytes total.
|
||||
*/
|
||||
static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* The interface converts a whole buffer to avoid function-call overhead.
|
||||
* Constants have been gathered. Loops & conditionals have been removed as
|
||||
* much as possible for efficiency, in favor of drop-through switches.
|
||||
* (See "Note A" at the bottom of the file for equivalent code.)
|
||||
* If your compiler supports it, the "isLegalUTF8" call can be turned
|
||||
* into an inline function.
|
||||
*/
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF16toUTF8 (const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF16* source = *sourceStart;
|
||||
UTF8* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch;
|
||||
unsigned short bytesToWrite = 0;
|
||||
const UTF32 byteMask = 0xBF;
|
||||
const UTF32 byteMark = 0x80;
|
||||
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
|
||||
ch = *source++;
|
||||
/* If we have a surrogate pair, convert to UTF32 first. */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
|
||||
/* If the 16 bits following the high surrogate are in the source buffer... */
|
||||
if (source < sourceEnd) {
|
||||
UTF32 ch2 = *source;
|
||||
/* If it's a low surrogate, convert to UTF32. */
|
||||
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
|
||||
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
|
||||
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
|
||||
++source;
|
||||
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
} else { /* We don't have the 16 bits following the high surrogate. */
|
||||
--source; /* return to the high surrogate */
|
||||
result = sourceExhausted;
|
||||
break;
|
||||
}
|
||||
} else if (flags == strictConversion) {
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Figure out how many bytes the result will require */
|
||||
if (ch < (UTF32)0x80) { bytesToWrite = 1;
|
||||
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
|
||||
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
|
||||
} else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
|
||||
} else { bytesToWrite = 3;
|
||||
ch = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
|
||||
target += bytesToWrite;
|
||||
if (target > targetEnd) {
|
||||
source = oldSource; /* Back up source pointer! */
|
||||
target -= bytesToWrite; result = targetExhausted; break;
|
||||
}
|
||||
switch (bytesToWrite) { /* note: everything falls through. */
|
||||
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
|
||||
}
|
||||
target += bytesToWrite;
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Utility routine to tell whether a sequence of bytes is legal UTF-8.
|
||||
* This must be called with the length pre-determined by the first byte.
|
||||
* If not calling this from ConvertUTF8to*, then the length can be set by:
|
||||
* length = trailingBytesForUTF8[*source]+1;
|
||||
* and the sequence is illegal right away if there aren't that many bytes
|
||||
* available.
|
||||
* If presented with a length > 4, this returns false. The Unicode
|
||||
* definition of UTF-8 goes up to 4-byte sequences.
|
||||
*/
|
||||
|
||||
static Boolean isLegalUTF8(const UTF8 *source, int length) {
|
||||
UTF8 a;
|
||||
const UTF8 *srcptr = source+length;
|
||||
switch (length) {
|
||||
default: return false;
|
||||
/* Everything else falls through when "true"... */
|
||||
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
|
||||
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
|
||||
case 2: if ((a = (*--srcptr)) > 0xBF) return false;
|
||||
|
||||
switch (*source) {
|
||||
/* no fall-through in this inner switch */
|
||||
case 0xE0: if (a < 0xA0) return false; break;
|
||||
case 0xED: if (a > 0x9F) return false; break;
|
||||
case 0xF0: if (a < 0x90) return false; break;
|
||||
case 0xF4: if (a > 0x8F) return false; break;
|
||||
default: if (a < 0x80) return false;
|
||||
}
|
||||
|
||||
case 1: if (*source >= 0x80 && *source < 0xC2) return false;
|
||||
}
|
||||
if (*source > 0xF4) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Exported function to return whether a UTF-8 sequence is legal or not.
|
||||
* This is not used here; it's just exported.
|
||||
*/
|
||||
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
|
||||
int length = trailingBytesForUTF8[*source]+1;
|
||||
if (source+length > sourceEnd) {
|
||||
return false;
|
||||
}
|
||||
return isLegalUTF8(source, length);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF8toUTF16 (const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF8* source = *sourceStart;
|
||||
UTF16* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch = 0;
|
||||
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
|
||||
if (source + extraBytesToRead >= sourceEnd) {
|
||||
result = sourceExhausted; break;
|
||||
}
|
||||
/* Do this check whether lenient or strict */
|
||||
if (! isLegalUTF8(source, extraBytesToRead+1)) {
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* The cases all fall through. See "Note A" below.
|
||||
*/
|
||||
switch (extraBytesToRead) {
|
||||
case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
|
||||
case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
|
||||
case 3: ch += *source++; ch <<= 6;
|
||||
case 2: ch += *source++; ch <<= 6;
|
||||
case 1: ch += *source++; ch <<= 6;
|
||||
case 0: ch += *source++;
|
||||
}
|
||||
ch -= offsetsFromUTF8[extraBytesToRead];
|
||||
|
||||
if (target >= targetEnd) {
|
||||
source -= (extraBytesToRead+1); /* Back up source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
|
||||
if (flags == strictConversion) {
|
||||
source -= (extraBytesToRead+1); /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
*target++ = (UTF16)ch; /* normal case */
|
||||
}
|
||||
} else if (ch > UNI_MAX_UTF16) {
|
||||
if (flags == strictConversion) {
|
||||
result = sourceIllegal;
|
||||
source -= (extraBytesToRead+1); /* return to the start */
|
||||
break; /* Bail out; shouldn't continue */
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
/* target is a character in range 0xFFFF - 0x10FFFF. */
|
||||
if (target + 1 >= targetEnd) {
|
||||
source -= (extraBytesToRead+1); /* Back up source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
ch -= halfBase;
|
||||
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
|
||||
*target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
|
||||
}
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF32toUTF8 (const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF32* source = *sourceStart;
|
||||
UTF8* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch;
|
||||
unsigned short bytesToWrite = 0;
|
||||
const UTF32 byteMask = 0xBF;
|
||||
const UTF32 byteMark = 0x80;
|
||||
ch = *source++;
|
||||
if (flags == strictConversion ) {
|
||||
/* UTF-16 surrogate values are illegal in UTF-32 */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Figure out how many bytes the result will require. Turn any
|
||||
* illegally large UTF32 things (> Plane 17) into replacement chars.
|
||||
*/
|
||||
if (ch < (UTF32)0x80) { bytesToWrite = 1;
|
||||
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
|
||||
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
|
||||
} else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
|
||||
} else { bytesToWrite = 3;
|
||||
ch = UNI_REPLACEMENT_CHAR;
|
||||
result = sourceIllegal;
|
||||
}
|
||||
|
||||
target += bytesToWrite;
|
||||
if (target > targetEnd) {
|
||||
--source; /* Back up source pointer! */
|
||||
target -= bytesToWrite; result = targetExhausted; break;
|
||||
}
|
||||
switch (bytesToWrite) { /* note: everything falls through. */
|
||||
case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
|
||||
case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
|
||||
}
|
||||
target += bytesToWrite;
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF8toUTF32 (const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF8* source = *sourceStart;
|
||||
UTF32* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch = 0;
|
||||
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
|
||||
if (source + extraBytesToRead >= sourceEnd) {
|
||||
result = sourceExhausted; break;
|
||||
}
|
||||
/* Do this check whether lenient or strict */
|
||||
if (! isLegalUTF8(source, extraBytesToRead+1)) {
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* The cases all fall through. See "Note A" below.
|
||||
*/
|
||||
switch (extraBytesToRead) {
|
||||
case 5: ch += *source++; ch <<= 6;
|
||||
case 4: ch += *source++; ch <<= 6;
|
||||
case 3: ch += *source++; ch <<= 6;
|
||||
case 2: ch += *source++; ch <<= 6;
|
||||
case 1: ch += *source++; ch <<= 6;
|
||||
case 0: ch += *source++;
|
||||
}
|
||||
ch -= offsetsFromUTF8[extraBytesToRead];
|
||||
|
||||
if (target >= targetEnd) {
|
||||
source -= (extraBytesToRead+1); /* Back up the source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
if (ch <= UNI_MAX_LEGAL_UTF32) {
|
||||
/*
|
||||
* UTF-16 surrogate values are illegal in UTF-32, and anything
|
||||
* over Plane 17 (> 0x10FFFF) is illegal.
|
||||
*/
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
|
||||
if (flags == strictConversion) {
|
||||
source -= (extraBytesToRead+1); /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
*target++ = ch;
|
||||
}
|
||||
} else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
|
||||
result = sourceIllegal;
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
Note A.
|
||||
The fall-through switches in UTF-8 reading code save a
|
||||
temp variable, some decrements & conditionals. The switches
|
||||
are equivalent to the following loop:
|
||||
{
|
||||
int tmpBytesToRead = extraBytesToRead+1;
|
||||
do {
|
||||
ch += *source++;
|
||||
--tmpBytesToRead;
|
||||
if (tmpBytesToRead) ch <<= 6;
|
||||
} while (tmpBytesToRead > 0);
|
||||
}
|
||||
In UTF-8 writing code, the switches on "bytesToWrite" are
|
||||
similarly unrolled loops.
|
||||
|
||||
--------------------------------------------------------------------- */
|
|
@ -1,164 +0,0 @@
|
|||
/*
|
||||
* Copyright © 1991-2015 Unicode, Inc. All rights reserved.
|
||||
* Distributed under the Terms of Use in
|
||||
* http://www.unicode.org/copyright.html.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of the Unicode data files and any associated documentation
|
||||
* (the "Data Files") or Unicode software and any associated documentation
|
||||
* (the "Software") to deal in the Data Files or Software
|
||||
* without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, and/or sell copies of
|
||||
* the Data Files or Software, and to permit persons to whom the Data Files
|
||||
* or Software are furnished to do so, provided that
|
||||
* (a) this copyright and permission notice appear with all copies
|
||||
* of the Data Files or Software,
|
||||
* (b) this copyright and permission notice appear in associated
|
||||
* documentation, and
|
||||
* (c) there is clear notice in each modified Data File or in the Software
|
||||
* as well as in the documentation associated with the Data File(s) or
|
||||
* Software that the data or software has been modified.
|
||||
*
|
||||
* THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
|
||||
* NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
|
||||
* DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THE DATA FILES OR SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of a copyright holder
|
||||
* shall not be used in advertising or otherwise to promote the sale,
|
||||
* use or other dealings in these Data Files or Software without prior
|
||||
* written authorization of the copyright holder.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_CONVERT_UTF_H_
|
||||
#define COMMON_CONVERT_UTF_H_
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
Conversions between UTF32, UTF-16, and UTF-8. Header file.
|
||||
|
||||
Several funtions are included here, forming a complete set of
|
||||
conversions between the three formats. UTF-7 is not included
|
||||
here, but is handled in a separate source file.
|
||||
|
||||
Each of these routines takes pointers to input buffers and output
|
||||
buffers. The input buffers are const.
|
||||
|
||||
Each routine converts the text between *sourceStart and sourceEnd,
|
||||
putting the result into the buffer between *targetStart and
|
||||
targetEnd. Note: the end pointers are *after* the last item: e.g.
|
||||
*(sourceEnd - 1) is the last item.
|
||||
|
||||
The return result indicates whether the conversion was successful,
|
||||
and if not, whether the problem was in the source or target buffers.
|
||||
(Only the first encountered problem is indicated.)
|
||||
|
||||
After the conversion, *sourceStart and *targetStart are both
|
||||
updated to point to the end of last text successfully converted in
|
||||
the respective buffers.
|
||||
|
||||
Input parameters:
|
||||
sourceStart - pointer to a pointer to the source buffer.
|
||||
The contents of this are modified on return so that
|
||||
it points at the next thing to be converted.
|
||||
targetStart - similarly, pointer to pointer to the target buffer.
|
||||
sourceEnd, targetEnd - respectively pointers to the ends of the
|
||||
two buffers, for overflow checking only.
|
||||
|
||||
These conversion functions take a ConversionFlags argument. When this
|
||||
flag is set to strict, both irregular sequences and isolated surrogates
|
||||
will cause an error. When the flag is set to lenient, both irregular
|
||||
sequences and isolated surrogates are converted.
|
||||
|
||||
Whether the flag is strict or lenient, all illegal sequences will cause
|
||||
an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
|
||||
or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
|
||||
must check for illegal sequences.
|
||||
|
||||
When the flag is set to lenient, characters over 0x10FFFF are converted
|
||||
to the replacement character; otherwise (when the flag is set to strict)
|
||||
they constitute an error.
|
||||
|
||||
Output parameters:
|
||||
The value "sourceIllegal" is returned from some routines if the input
|
||||
sequence is malformed. When "sourceIllegal" is returned, the source
|
||||
value will point to the illegal value that caused the problem. E.g.,
|
||||
in UTF-8 when a sequence is malformed, it points to the start of the
|
||||
malformed sequence.
|
||||
|
||||
Author: Mark E. Davis, 1994.
|
||||
Rev History: Rick McGowan, fixes & updates May 2001.
|
||||
Fixes & updates, Sept 2001.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
The following 4 definitions are compiler-specific.
|
||||
The C standard does not guarantee that wchar_t has at least
|
||||
16 bits, so wchar_t is no less portable than unsigned short!
|
||||
All should be unsigned values to avoid sign extension during
|
||||
bit mask & shift operations.
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
typedef unsigned long UTF32; /* at least 32 bits */
|
||||
typedef unsigned short UTF16; /* at least 16 bits */
|
||||
typedef unsigned char UTF8; /* typically 8 bits */
|
||||
typedef unsigned char Boolean; /* 0 or 1 */
|
||||
|
||||
/* Some fundamental constants */
|
||||
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
|
||||
#define UNI_MAX_BMP (UTF32)0x0000FFFF
|
||||
#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
|
||||
#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
|
||||
#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
|
||||
|
||||
typedef enum {
|
||||
conversionOK, /* conversion successful */
|
||||
sourceExhausted, /* partial character in source, but hit end */
|
||||
targetExhausted, /* insuff. room in target for conversion */
|
||||
sourceIllegal /* source sequence is illegal/malformed */
|
||||
} ConversionResult;
|
||||
|
||||
typedef enum {
|
||||
strictConversion = 0,
|
||||
lenientConversion
|
||||
} ConversionFlags;
|
||||
|
||||
/* This is for C++ and does no harm in C */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
ConversionResult ConvertUTF8toUTF16 (const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF16toUTF8 (const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF8toUTF32 (const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF32toUTF8 (const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF16toUTF32 (const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF32toUTF16 (const UTF32** sourceStart, const UTF32* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
|
||||
|
||||
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#endif // COMMON_CONVERT_UTF_H_
|
|
@ -1,58 +0,0 @@
|
|||
// Copyright (c) 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
|
||||
// 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 COMMON_LINUX_EINTR_WRAPPER_H_
|
||||
#define COMMON_LINUX_EINTR_WRAPPER_H_
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
// This provides a wrapper around system calls which may be interrupted by a
|
||||
// signal and return EINTR. See man 7 signal.
|
||||
//
|
||||
|
||||
#define HANDLE_EINTR(x) ({ \
|
||||
__typeof__(x) eintr_wrapper_result; \
|
||||
do { \
|
||||
eintr_wrapper_result = (x); \
|
||||
} while (eintr_wrapper_result == -1 && errno == EINTR); \
|
||||
eintr_wrapper_result; \
|
||||
})
|
||||
|
||||
#define IGNORE_EINTR(x) ({ \
|
||||
__typeof__(x) eintr_wrapper_result; \
|
||||
do { \
|
||||
eintr_wrapper_result = (x); \
|
||||
if (eintr_wrapper_result == -1 && errno == EINTR) { \
|
||||
eintr_wrapper_result = 0; \
|
||||
} \
|
||||
} while (0); \
|
||||
eintr_wrapper_result; \
|
||||
})
|
||||
|
||||
#endif // COMMON_LINUX_EINTR_WRAPPER_H_
|
|
@ -1,46 +0,0 @@
|
|||
// -*- mode: C++ -*-
|
||||
|
||||
// Copyright (c) 2013, 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.
|
||||
|
||||
// Original author: Lei Zhang <thestig@google.com>
|
||||
|
||||
// elf_gnu_compat.h: #defines unique to glibc's elf.h.
|
||||
|
||||
#ifndef COMMON_LINUX_ELF_GNU_COMPAT_H_
|
||||
#define COMMON_LINUX_ELF_GNU_COMPAT_H_
|
||||
|
||||
#include <elf.h>
|
||||
|
||||
// A note type on GNU systems corresponding to the .note.gnu.build-id section.
|
||||
#ifndef NT_GNU_BUILD_ID
|
||||
#define NT_GNU_BUILD_ID 3
|
||||
#endif
|
||||
|
||||
#endif // COMMON_LINUX_ELF_GNU_COMPAT_H_
|
|
@ -1,74 +0,0 @@
|
|||
// 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 COMMON_LINUX_ELFUTILS_INL_H__
|
||||
#define COMMON_LINUX_ELFUTILS_INL_H__
|
||||
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "elfutils.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
template<typename ElfClass, typename T>
|
||||
const T* GetOffset(const typename ElfClass::Ehdr* elf_header,
|
||||
typename ElfClass::Off offset) {
|
||||
return reinterpret_cast<const T*>(reinterpret_cast<uintptr_t>(elf_header) +
|
||||
offset);
|
||||
}
|
||||
|
||||
template<typename ElfClass>
|
||||
const typename ElfClass::Shdr* FindElfSectionByName(
|
||||
const char* name,
|
||||
typename ElfClass::Word section_type,
|
||||
const typename ElfClass::Shdr* sections,
|
||||
const char* section_names,
|
||||
const char* names_end,
|
||||
int nsection) {
|
||||
assert(name != NULL);
|
||||
assert(sections != NULL);
|
||||
assert(nsection > 0);
|
||||
|
||||
int name_len = my_strlen(name);
|
||||
if (name_len == 0)
|
||||
return NULL;
|
||||
|
||||
for (int i = 0; i < nsection; ++i) {
|
||||
const char* section_name = section_names + sections[i].sh_name;
|
||||
if (sections[i].sh_type == section_type &&
|
||||
names_end - section_name >= name_len + 1 &&
|
||||
my_strcmp(name, section_name) == 0) {
|
||||
return sections + i;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_LINUX_ELFUTILS_INL_H__
|
|
@ -1,194 +0,0 @@
|
|||
// 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.
|
||||
|
||||
#include "common/linux/elfutils.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "common/linux/elfutils-inl.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename ElfClass>
|
||||
void FindElfClassSection(const char *elf_base,
|
||||
const char *section_name,
|
||||
typename ElfClass::Word section_type,
|
||||
const void **section_start,
|
||||
size_t *section_size) {
|
||||
typedef typename ElfClass::Ehdr Ehdr;
|
||||
typedef typename ElfClass::Shdr Shdr;
|
||||
|
||||
assert(elf_base);
|
||||
assert(section_start);
|
||||
assert(section_size);
|
||||
|
||||
assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0);
|
||||
|
||||
const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base);
|
||||
assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass);
|
||||
|
||||
const Shdr* sections =
|
||||
GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff);
|
||||
const Shdr* section_names = sections + elf_header->e_shstrndx;
|
||||
const char* names =
|
||||
GetOffset<ElfClass, char>(elf_header, section_names->sh_offset);
|
||||
const char *names_end = names + section_names->sh_size;
|
||||
|
||||
const Shdr* section =
|
||||
FindElfSectionByName<ElfClass>(section_name, section_type,
|
||||
sections, names, names_end,
|
||||
elf_header->e_shnum);
|
||||
|
||||
if (section != NULL && section->sh_size > 0) {
|
||||
*section_start = elf_base + section->sh_offset;
|
||||
*section_size = section->sh_size;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ElfClass>
|
||||
void FindElfClassSegment(const char *elf_base,
|
||||
typename ElfClass::Word segment_type,
|
||||
const void **segment_start,
|
||||
size_t *segment_size) {
|
||||
typedef typename ElfClass::Ehdr Ehdr;
|
||||
typedef typename ElfClass::Phdr Phdr;
|
||||
|
||||
assert(elf_base);
|
||||
assert(segment_start);
|
||||
assert(segment_size);
|
||||
|
||||
assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0);
|
||||
|
||||
const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base);
|
||||
assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass);
|
||||
|
||||
const Phdr* phdrs =
|
||||
GetOffset<ElfClass, Phdr>(elf_header, elf_header->e_phoff);
|
||||
|
||||
for (int i = 0; i < elf_header->e_phnum; ++i) {
|
||||
if (phdrs[i].p_type == segment_type) {
|
||||
*segment_start = elf_base + phdrs[i].p_offset;
|
||||
*segment_size = phdrs[i].p_filesz;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool IsValidElf(const void* elf_base) {
|
||||
return my_strncmp(reinterpret_cast<const char*>(elf_base),
|
||||
ELFMAG, SELFMAG) == 0;
|
||||
}
|
||||
|
||||
int ElfClass(const void* elf_base) {
|
||||
const ElfW(Ehdr)* elf_header =
|
||||
reinterpret_cast<const ElfW(Ehdr)*>(elf_base);
|
||||
|
||||
return elf_header->e_ident[EI_CLASS];
|
||||
}
|
||||
|
||||
bool FindElfSection(const void *elf_mapped_base,
|
||||
const char *section_name,
|
||||
uint32_t section_type,
|
||||
const void **section_start,
|
||||
size_t *section_size,
|
||||
int *elfclass) {
|
||||
assert(elf_mapped_base);
|
||||
assert(section_start);
|
||||
assert(section_size);
|
||||
|
||||
*section_start = NULL;
|
||||
*section_size = 0;
|
||||
|
||||
if (!IsValidElf(elf_mapped_base))
|
||||
return false;
|
||||
|
||||
int cls = ElfClass(elf_mapped_base);
|
||||
if (elfclass) {
|
||||
*elfclass = cls;
|
||||
}
|
||||
|
||||
const char* elf_base =
|
||||
static_cast<const char*>(elf_mapped_base);
|
||||
|
||||
if (cls == ELFCLASS32) {
|
||||
FindElfClassSection<ElfClass32>(elf_base, section_name, section_type,
|
||||
section_start, section_size);
|
||||
return *section_start != NULL;
|
||||
} else if (cls == ELFCLASS64) {
|
||||
FindElfClassSection<ElfClass64>(elf_base, section_name, section_type,
|
||||
section_start, section_size);
|
||||
return *section_start != NULL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FindElfSegment(const void *elf_mapped_base,
|
||||
uint32_t segment_type,
|
||||
const void **segment_start,
|
||||
size_t *segment_size,
|
||||
int *elfclass) {
|
||||
assert(elf_mapped_base);
|
||||
assert(segment_start);
|
||||
assert(segment_size);
|
||||
|
||||
*segment_start = NULL;
|
||||
*segment_size = 0;
|
||||
|
||||
if (!IsValidElf(elf_mapped_base))
|
||||
return false;
|
||||
|
||||
int cls = ElfClass(elf_mapped_base);
|
||||
if (elfclass) {
|
||||
*elfclass = cls;
|
||||
}
|
||||
|
||||
const char* elf_base =
|
||||
static_cast<const char*>(elf_mapped_base);
|
||||
|
||||
if (cls == ELFCLASS32) {
|
||||
FindElfClassSegment<ElfClass32>(elf_base, segment_type,
|
||||
segment_start, segment_size);
|
||||
return *segment_start != NULL;
|
||||
} else if (cls == ELFCLASS64) {
|
||||
FindElfClassSegment<ElfClass64>(elf_base, segment_type,
|
||||
segment_start, segment_size);
|
||||
return *segment_start != NULL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -1,118 +0,0 @@
|
|||
// 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.
|
||||
//
|
||||
// elfutils.h: Utilities for dealing with ELF files.
|
||||
//
|
||||
|
||||
#ifndef COMMON_LINUX_ELFUTILS_H_
|
||||
#define COMMON_LINUX_ELFUTILS_H_
|
||||
|
||||
#include <elf.h>
|
||||
#include <link.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// Traits classes so consumers can write templatized code to deal
|
||||
// with specific ELF bits.
|
||||
struct ElfClass32 {
|
||||
typedef Elf32_Addr Addr;
|
||||
typedef Elf32_Ehdr Ehdr;
|
||||
typedef Elf32_Nhdr Nhdr;
|
||||
typedef Elf32_Phdr Phdr;
|
||||
typedef Elf32_Shdr Shdr;
|
||||
typedef Elf32_Half Half;
|
||||
typedef Elf32_Off Off;
|
||||
typedef Elf32_Word Word;
|
||||
static const int kClass = ELFCLASS32;
|
||||
static const size_t kAddrSize = sizeof(Elf32_Addr);
|
||||
};
|
||||
|
||||
struct ElfClass64 {
|
||||
typedef Elf64_Addr Addr;
|
||||
typedef Elf64_Ehdr Ehdr;
|
||||
typedef Elf64_Nhdr Nhdr;
|
||||
typedef Elf64_Phdr Phdr;
|
||||
typedef Elf64_Shdr Shdr;
|
||||
typedef Elf64_Half Half;
|
||||
typedef Elf64_Off Off;
|
||||
typedef Elf64_Word Word;
|
||||
static const int kClass = ELFCLASS64;
|
||||
static const size_t kAddrSize = sizeof(Elf64_Addr);
|
||||
};
|
||||
|
||||
bool IsValidElf(const void* elf_header);
|
||||
int ElfClass(const void* elf_base);
|
||||
|
||||
// Attempt to find a section named |section_name| of type |section_type|
|
||||
// in the ELF binary data at |elf_mapped_base|. On success, returns true
|
||||
// and sets |*section_start| to point to the start of the section data,
|
||||
// and |*section_size| to the size of the section's data. If |elfclass|
|
||||
// is not NULL, set |*elfclass| to the ELF file class.
|
||||
bool FindElfSection(const void *elf_mapped_base,
|
||||
const char *section_name,
|
||||
uint32_t section_type,
|
||||
const void **section_start,
|
||||
size_t *section_size,
|
||||
int *elfclass);
|
||||
|
||||
// Internal helper method, exposed for convenience for callers
|
||||
// that already have more info.
|
||||
template<typename ElfClass>
|
||||
const typename ElfClass::Shdr*
|
||||
FindElfSectionByName(const char* name,
|
||||
typename ElfClass::Word section_type,
|
||||
const typename ElfClass::Shdr* sections,
|
||||
const char* section_names,
|
||||
const char* names_end,
|
||||
int nsection);
|
||||
|
||||
// Attempt to find the first segment of type |segment_type| in the ELF
|
||||
// binary data at |elf_mapped_base|. On success, returns true and sets
|
||||
// |*segment_start| to point to the start of the segment data, and
|
||||
// and |*segment_size| to the size of the segment's data. If |elfclass|
|
||||
// is not NULL, set |*elfclass| to the ELF file class.
|
||||
bool FindElfSegment(const void *elf_mapped_base,
|
||||
uint32_t segment_type,
|
||||
const void **segment_start,
|
||||
size_t *segment_size,
|
||||
int *elfclass);
|
||||
|
||||
// Convert an offset from an Elf header into a pointer to the mapped
|
||||
// address in the current process. Takes an extra template parameter
|
||||
// to specify the return type to avoid having to dynamic_cast the
|
||||
// result.
|
||||
template<typename ElfClass, typename T>
|
||||
const T*
|
||||
GetOffset(const typename ElfClass::Ehdr* elf_header,
|
||||
typename ElfClass::Off offset);
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_LINUX_ELFUTILS_H_
|
|
@ -1,191 +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.
|
||||
//
|
||||
// file_id.cc: Return a unique identifier for a file
|
||||
//
|
||||
// See file_id.h for documentation
|
||||
//
|
||||
|
||||
#include "common/linux/file_id.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common/linux/elf_gnu_compat.h"
|
||||
#include "common/linux/elfutils.h"
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
#include "common/linux/memory_mapped_file.h"
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
FileID::FileID(const char* path) : path_(path) {}
|
||||
|
||||
// ELF note name and desc are 32-bits word padded.
|
||||
#define NOTE_PADDING(a) ((a + 3) & ~3)
|
||||
|
||||
// These functions are also used inside the crashed process, so be safe
|
||||
// and use the syscall/libc wrappers instead of direct syscalls or libc.
|
||||
|
||||
template<typename ElfClass>
|
||||
static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length,
|
||||
uint8_t identifier[kMDGUIDSize]) {
|
||||
typedef typename ElfClass::Nhdr Nhdr;
|
||||
|
||||
const void* section_end = reinterpret_cast<const char*>(section) + length;
|
||||
const Nhdr* note_header = reinterpret_cast<const Nhdr*>(section);
|
||||
while (reinterpret_cast<const void *>(note_header) < section_end) {
|
||||
if (note_header->n_type == NT_GNU_BUILD_ID)
|
||||
break;
|
||||
note_header = reinterpret_cast<const Nhdr*>(
|
||||
reinterpret_cast<const char*>(note_header) + sizeof(Nhdr) +
|
||||
NOTE_PADDING(note_header->n_namesz) +
|
||||
NOTE_PADDING(note_header->n_descsz));
|
||||
}
|
||||
if (reinterpret_cast<const void *>(note_header) >= section_end ||
|
||||
note_header->n_descsz == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* build_id = reinterpret_cast<const char*>(note_header) +
|
||||
sizeof(Nhdr) + NOTE_PADDING(note_header->n_namesz);
|
||||
// Copy as many bits of the build ID as will fit
|
||||
// into the GUID space.
|
||||
my_memset(identifier, 0, kMDGUIDSize);
|
||||
memcpy(identifier, build_id,
|
||||
std::min(kMDGUIDSize, (size_t)note_header->n_descsz));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Attempt to locate a .note.gnu.build-id section in an ELF binary
|
||||
// and copy as many bytes of it as will fit into |identifier|.
|
||||
static bool FindElfBuildIDNote(const void *elf_mapped_base,
|
||||
uint8_t identifier[kMDGUIDSize]) {
|
||||
void* note_section;
|
||||
size_t note_size;
|
||||
int elfclass;
|
||||
if ((!FindElfSegment(elf_mapped_base, PT_NOTE,
|
||||
(const void**)¬e_section, ¬e_size, &elfclass) ||
|
||||
note_size == 0) &&
|
||||
(!FindElfSection(elf_mapped_base, ".note.gnu.build-id", SHT_NOTE,
|
||||
(const void**)¬e_section, ¬e_size, &elfclass) ||
|
||||
note_size == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (elfclass == ELFCLASS32) {
|
||||
return ElfClassBuildIDNoteIdentifier<ElfClass32>(note_section, note_size,
|
||||
identifier);
|
||||
} else if (elfclass == ELFCLASS64) {
|
||||
return ElfClassBuildIDNoteIdentifier<ElfClass64>(note_section, note_size,
|
||||
identifier);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attempt to locate the .text section of an ELF binary and generate
|
||||
// a simple hash by XORing the first page worth of bytes into |identifier|.
|
||||
static bool HashElfTextSection(const void *elf_mapped_base,
|
||||
uint8_t identifier[kMDGUIDSize]) {
|
||||
void* text_section;
|
||||
size_t text_size;
|
||||
if (!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS,
|
||||
(const void**)&text_section, &text_size, NULL) ||
|
||||
text_size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
my_memset(identifier, 0, kMDGUIDSize);
|
||||
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(text_section);
|
||||
const uint8_t* ptr_end = ptr + std::min(text_size, static_cast<size_t>(4096));
|
||||
while (ptr < ptr_end) {
|
||||
for (unsigned i = 0; i < kMDGUIDSize; i++)
|
||||
identifier[i] ^= ptr[i];
|
||||
ptr += kMDGUIDSize;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool FileID::ElfFileIdentifierFromMappedFile(const void* base,
|
||||
uint8_t identifier[kMDGUIDSize]) {
|
||||
// Look for a build id note first.
|
||||
if (FindElfBuildIDNote(base, identifier))
|
||||
return true;
|
||||
|
||||
// Fall back on hashing the first page of the text section.
|
||||
return HashElfTextSection(base, identifier);
|
||||
}
|
||||
|
||||
bool FileID::ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]) {
|
||||
MemoryMappedFile mapped_file(path_.c_str(), 0);
|
||||
if (!mapped_file.data()) // Should probably check if size >= ElfW(Ehdr)?
|
||||
return false;
|
||||
|
||||
return ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier);
|
||||
}
|
||||
|
||||
// static
|
||||
void FileID::ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize],
|
||||
char* buffer, int buffer_length) {
|
||||
uint8_t identifier_swapped[kMDGUIDSize];
|
||||
|
||||
// Endian-ness swap to match dump processor expectation.
|
||||
memcpy(identifier_swapped, identifier, kMDGUIDSize);
|
||||
uint32_t* data1 = reinterpret_cast<uint32_t*>(identifier_swapped);
|
||||
*data1 = htonl(*data1);
|
||||
uint16_t* data2 = reinterpret_cast<uint16_t*>(identifier_swapped + 4);
|
||||
*data2 = htons(*data2);
|
||||
uint16_t* data3 = reinterpret_cast<uint16_t*>(identifier_swapped + 6);
|
||||
*data3 = htons(*data3);
|
||||
|
||||
int buffer_idx = 0;
|
||||
for (unsigned int idx = 0;
|
||||
(buffer_idx < buffer_length) && (idx < kMDGUIDSize);
|
||||
++idx) {
|
||||
int hi = (identifier_swapped[idx] >> 4) & 0x0F;
|
||||
int lo = (identifier_swapped[idx]) & 0x0F;
|
||||
|
||||
if (idx == 4 || idx == 6 || idx == 8 || idx == 10)
|
||||
buffer[buffer_idx++] = '-';
|
||||
|
||||
buffer[buffer_idx++] = (hi >= 10) ? 'A' + hi - 10 : '0' + hi;
|
||||
buffer[buffer_idx++] = (lo >= 10) ? 'A' + lo - 10 : '0' + lo;
|
||||
}
|
||||
|
||||
// NULL terminate
|
||||
buffer[(buffer_idx < buffer_length) ? buffer_idx : buffer_idx - 1] = 0;
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -1,78 +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.
|
||||
//
|
||||
// file_id.h: Return a unique identifier for a file
|
||||
//
|
||||
|
||||
#ifndef COMMON_LINUX_FILE_ID_H__
|
||||
#define COMMON_LINUX_FILE_ID_H__
|
||||
|
||||
#include <limits.h>
|
||||
#include <string>
|
||||
|
||||
#include "common/linux/guid_creator.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
static const size_t kMDGUIDSize = sizeof(MDGUID);
|
||||
|
||||
class FileID {
|
||||
public:
|
||||
explicit FileID(const char* path);
|
||||
~FileID() {}
|
||||
|
||||
// Load the identifier for the elf file path specified in the constructor into
|
||||
// |identifier|. Return false if the identifier could not be created for the
|
||||
// file.
|
||||
// The current implementation will look for a .note.gnu.build-id
|
||||
// section and use that as the file id, otherwise it falls back to
|
||||
// XORing the first 4096 bytes of the .text section to generate an identifier.
|
||||
bool ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]);
|
||||
|
||||
// Load the identifier for the elf file mapped into memory at |base| into
|
||||
// |identifier|. Return false if the identifier could not be created for the
|
||||
// file.
|
||||
static bool ElfFileIdentifierFromMappedFile(const void* base,
|
||||
uint8_t identifier[kMDGUIDSize]);
|
||||
|
||||
// Convert the |identifier| data to a NULL terminated string. The string will
|
||||
// be formatted as a UUID (e.g., 22F065BB-FC9C-49F7-80FE-26A7CEBD7BCE).
|
||||
// The |buffer| should be at least 37 bytes long to receive all of the data
|
||||
// and termination. Shorter buffers will contain truncated data.
|
||||
static void ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize],
|
||||
char* buffer, int buffer_length);
|
||||
|
||||
private:
|
||||
// Storage for the path specified
|
||||
std::string path_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_LINUX_FILE_ID_H__
|
|
@ -1,104 +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.
|
||||
|
||||
#include "common/linux/guid_creator.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
//
|
||||
// GUIDGenerator
|
||||
//
|
||||
// This class is used to generate random GUID.
|
||||
// Currently use random number to generate a GUID since Linux has
|
||||
// no native GUID generator. This should be OK since we don't expect
|
||||
// crash to happen very offen.
|
||||
//
|
||||
class GUIDGenerator {
|
||||
public:
|
||||
static uint32_t BytesToUInt32(const uint8_t bytes[]) {
|
||||
return ((uint32_t) bytes[0]
|
||||
| ((uint32_t) bytes[1] << 8)
|
||||
| ((uint32_t) bytes[2] << 16)
|
||||
| ((uint32_t) bytes[3] << 24));
|
||||
}
|
||||
|
||||
static void UInt32ToBytes(uint8_t bytes[], uint32_t n) {
|
||||
bytes[0] = n & 0xff;
|
||||
bytes[1] = (n >> 8) & 0xff;
|
||||
bytes[2] = (n >> 16) & 0xff;
|
||||
bytes[3] = (n >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static bool CreateGUID(GUID *guid) {
|
||||
InitOnce();
|
||||
guid->data1 = random();
|
||||
guid->data2 = (uint16_t)(random());
|
||||
guid->data3 = (uint16_t)(random());
|
||||
UInt32ToBytes(&guid->data4[0], random());
|
||||
UInt32ToBytes(&guid->data4[4], random());
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static void InitOnce() {
|
||||
pthread_once(&once_control, &InitOnceImpl);
|
||||
}
|
||||
|
||||
static void InitOnceImpl() {
|
||||
srandom(time(NULL));
|
||||
}
|
||||
|
||||
static pthread_once_t once_control;
|
||||
};
|
||||
|
||||
pthread_once_t GUIDGenerator::once_control = PTHREAD_ONCE_INIT;
|
||||
|
||||
bool CreateGUID(GUID *guid) {
|
||||
return GUIDGenerator::CreateGUID(guid);
|
||||
}
|
||||
|
||||
// Parse guid to string.
|
||||
bool GUIDToString(const GUID *guid, char *buf, int buf_len) {
|
||||
// Should allow more space the the max length of GUID.
|
||||
assert(buf_len > kGUIDStringLength);
|
||||
int num = snprintf(buf, buf_len, kGUIDFormatString,
|
||||
guid->data1, guid->data2, guid->data3,
|
||||
GUIDGenerator::BytesToUInt32(&(guid->data4[0])),
|
||||
GUIDGenerator::BytesToUInt32(&(guid->data4[4])));
|
||||
if (num != kGUIDStringLength)
|
||||
return false;
|
||||
|
||||
buf[num] = '\0';
|
||||
return true;
|
||||
}
|
|
@ -1,48 +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.
|
||||
|
||||
#ifndef COMMON_LINUX_GUID_CREATOR_H__
|
||||
#define COMMON_LINUX_GUID_CREATOR_H__
|
||||
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
typedef MDGUID GUID;
|
||||
|
||||
// Format string for parsing GUID.
|
||||
#define kGUIDFormatString "%08x-%04x-%04x-%08x-%08x"
|
||||
// Length of GUID string. Don't count the ending '\0'.
|
||||
#define kGUIDStringLength 36
|
||||
|
||||
// Create a guid.
|
||||
bool CreateGUID(GUID *guid);
|
||||
|
||||
// Get the string from guid.
|
||||
bool GUIDToString(const GUID *guid, char *buf, int buf_len);
|
||||
|
||||
#endif
|
|
@ -1,40 +0,0 @@
|
|||
// 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 COMMON_LINUX_IGNORE_RET_H_
|
||||
#define COMMON_LINUX_IGNORE_RET_H_
|
||||
|
||||
// Some compilers are prone to warn about unused return values. In cases where
|
||||
// either a) the call cannot fail, or b) there is nothing that can be done when
|
||||
// the call fails, IGNORE_RET() can be used to mark the return code as ignored.
|
||||
// This avoids spurious compiler warnings.
|
||||
|
||||
#define IGNORE_RET(x) do { if (x); } while (0)
|
||||
|
||||
#endif // COMMON_LINUX_IGNORE_RET_H_
|
|
@ -1,237 +0,0 @@
|
|||
// 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.
|
||||
|
||||
// This source file provides replacements for libc functions that we need. If
|
||||
// we call the libc functions directly we risk crashing in the dynamic linker
|
||||
// as it tries to resolve uncached PLT entries.
|
||||
|
||||
#include "common/linux/linux_libc_support.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
size_t my_strlen(const char* s) {
|
||||
size_t len = 0;
|
||||
while (*s++) len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
int my_strcmp(const char* a, const char* b) {
|
||||
for (;;) {
|
||||
if (*a < *b)
|
||||
return -1;
|
||||
else if (*a > *b)
|
||||
return 1;
|
||||
else if (*a == 0)
|
||||
return 0;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
}
|
||||
|
||||
int my_strncmp(const char* a, const char* b, size_t len) {
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
if (*a < *b)
|
||||
return -1;
|
||||
else if (*a > *b)
|
||||
return 1;
|
||||
else if (*a == 0)
|
||||
return 0;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Parse a non-negative integer.
|
||||
// result: (output) the resulting non-negative integer
|
||||
// s: a NUL terminated string
|
||||
// Return true iff successful.
|
||||
bool my_strtoui(int* result, const char* s) {
|
||||
if (*s == 0)
|
||||
return false;
|
||||
int r = 0;
|
||||
for (;; s++) {
|
||||
if (*s == 0)
|
||||
break;
|
||||
const int old_r = r;
|
||||
r *= 10;
|
||||
if (*s < '0' || *s > '9')
|
||||
return false;
|
||||
r += *s - '0';
|
||||
if (r < old_r)
|
||||
return false;
|
||||
}
|
||||
|
||||
*result = r;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return the length of the given unsigned integer when expressed in base 10.
|
||||
unsigned my_uint_len(uintmax_t i) {
|
||||
if (!i)
|
||||
return 1;
|
||||
|
||||
int len = 0;
|
||||
while (i) {
|
||||
len++;
|
||||
i /= 10;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// Convert an unsigned integer to a string
|
||||
// output: (output) the resulting string is written here. This buffer must be
|
||||
// large enough to hold the resulting string. Call |my_uint_len| to get the
|
||||
// required length.
|
||||
// i: the unsigned integer to serialise.
|
||||
// i_len: the length of the integer in base 10 (see |my_uint_len|).
|
||||
void my_uitos(char* output, uintmax_t i, unsigned i_len) {
|
||||
for (unsigned index = i_len; index; --index, i /= 10)
|
||||
output[index - 1] = '0' + (i % 10);
|
||||
}
|
||||
|
||||
const char* my_strchr(const char* haystack, char needle) {
|
||||
while (*haystack && *haystack != needle)
|
||||
haystack++;
|
||||
if (*haystack == needle)
|
||||
return haystack;
|
||||
return (const char*) 0;
|
||||
}
|
||||
|
||||
const char* my_strrchr(const char* haystack, char needle) {
|
||||
const char* ret = NULL;
|
||||
while (*haystack) {
|
||||
if (*haystack == needle)
|
||||
ret = haystack;
|
||||
haystack++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void* my_memchr(const void* src, int needle, size_t src_len) {
|
||||
const unsigned char* p = (const unsigned char*)src;
|
||||
const unsigned char* p_end = p + src_len;
|
||||
for (; p < p_end; ++p) {
|
||||
if (*p == needle)
|
||||
return (void*)p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read a hex value
|
||||
// result: (output) the resulting value
|
||||
// s: a string
|
||||
// Returns a pointer to the first invalid charactor.
|
||||
const char* my_read_hex_ptr(uintptr_t* result, const char* s) {
|
||||
uintptr_t r = 0;
|
||||
|
||||
for (;; ++s) {
|
||||
if (*s >= '0' && *s <= '9') {
|
||||
r <<= 4;
|
||||
r += *s - '0';
|
||||
} else if (*s >= 'a' && *s <= 'f') {
|
||||
r <<= 4;
|
||||
r += (*s - 'a') + 10;
|
||||
} else if (*s >= 'A' && *s <= 'F') {
|
||||
r <<= 4;
|
||||
r += (*s - 'A') + 10;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*result = r;
|
||||
return s;
|
||||
}
|
||||
|
||||
const char* my_read_decimal_ptr(uintptr_t* result, const char* s) {
|
||||
uintptr_t r = 0;
|
||||
|
||||
for (;; ++s) {
|
||||
if (*s >= '0' && *s <= '9') {
|
||||
r *= 10;
|
||||
r += *s - '0';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*result = r;
|
||||
return s;
|
||||
}
|
||||
|
||||
void my_memset(void* ip, char c, size_t len) {
|
||||
char* p = (char *) ip;
|
||||
while (len--)
|
||||
*p++ = c;
|
||||
}
|
||||
|
||||
size_t my_strlcpy(char* s1, const char* s2, size_t len) {
|
||||
size_t pos1 = 0;
|
||||
size_t pos2 = 0;
|
||||
|
||||
while (s2[pos2] != '\0') {
|
||||
if (pos1 + 1 < len) {
|
||||
s1[pos1] = s2[pos2];
|
||||
pos1++;
|
||||
}
|
||||
pos2++;
|
||||
}
|
||||
if (len > 0)
|
||||
s1[pos1] = '\0';
|
||||
|
||||
return pos2;
|
||||
}
|
||||
|
||||
size_t my_strlcat(char* s1, const char* s2, size_t len) {
|
||||
size_t pos1 = 0;
|
||||
|
||||
while (pos1 < len && s1[pos1] != '\0')
|
||||
pos1++;
|
||||
|
||||
if (pos1 == len)
|
||||
return pos1;
|
||||
|
||||
return pos1 + my_strlcpy(s1 + pos1, s2, len - pos1);
|
||||
}
|
||||
|
||||
int my_isspace(int ch) {
|
||||
// Matches the C locale.
|
||||
const char spaces[] = " \t\f\n\r\t\v";
|
||||
for (size_t i = 0; i < sizeof(spaces); i++) {
|
||||
if (ch == spaces[i])
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
|
@ -1,96 +0,0 @@
|
|||
// Copyright (c) 2009, 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 header provides replacements for libc functions that we need. We if
|
||||
// call the libc functions directly we risk crashing in the dynamic linker as
|
||||
// it tries to resolve uncached PLT entries.
|
||||
|
||||
#ifndef CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_
|
||||
#define CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
extern size_t my_strlen(const char* s);
|
||||
|
||||
extern int my_strcmp(const char* a, const char* b);
|
||||
|
||||
extern int my_strncmp(const char* a, const char* b, size_t len);
|
||||
|
||||
// Parse a non-negative integer.
|
||||
// result: (output) the resulting non-negative integer
|
||||
// s: a NUL terminated string
|
||||
// Return true iff successful.
|
||||
extern bool my_strtoui(int* result, const char* s);
|
||||
|
||||
// Return the length of the given unsigned integer when expressed in base 10.
|
||||
extern unsigned my_uint_len(uintmax_t i);
|
||||
|
||||
// Convert an unsigned integer to a string
|
||||
// output: (output) the resulting string is written here. This buffer must be
|
||||
// large enough to hold the resulting string. Call |my_uint_len| to get the
|
||||
// required length.
|
||||
// i: the unsigned integer to serialise.
|
||||
// i_len: the length of the integer in base 10 (see |my_uint_len|).
|
||||
extern void my_uitos(char* output, uintmax_t i, unsigned i_len);
|
||||
|
||||
extern const char* my_strchr(const char* haystack, char needle);
|
||||
|
||||
extern const char* my_strrchr(const char* haystack, char needle);
|
||||
|
||||
// Read a hex value
|
||||
// result: (output) the resulting value
|
||||
// s: a string
|
||||
// Returns a pointer to the first invalid charactor.
|
||||
extern const char* my_read_hex_ptr(uintptr_t* result, const char* s);
|
||||
|
||||
extern const char* my_read_decimal_ptr(uintptr_t* result, const char* s);
|
||||
|
||||
extern void my_memset(void* ip, char c, size_t len);
|
||||
|
||||
extern void* my_memchr(const void* src, int c, size_t len);
|
||||
|
||||
// The following are considered safe to use in a compromised environment.
|
||||
// Besides, this gives the compiler an opportunity to optimize their calls.
|
||||
#define my_memcpy memcpy
|
||||
#define my_memmove memmove
|
||||
#define my_memcmp memcmp
|
||||
|
||||
extern size_t my_strlcpy(char* s1, const char* s2, size_t len);
|
||||
|
||||
extern size_t my_strlcat(char* s1, const char* s2, size_t len);
|
||||
|
||||
extern int my_isspace(int ch);
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_
|
|
@ -1,118 +0,0 @@
|
|||
// Copyright (c) 2011, 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.
|
||||
|
||||
// memory_mapped_file.cc: Implement google_breakpad::MemoryMappedFile.
|
||||
// See memory_mapped_file.h for details.
|
||||
|
||||
#include "common/linux/memory_mapped_file.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#if defined(__ANDROID__)
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/memory_range.h"
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
MemoryMappedFile::MemoryMappedFile() {}
|
||||
|
||||
MemoryMappedFile::MemoryMappedFile(const char* path, size_t offset) {
|
||||
Map(path, offset);
|
||||
}
|
||||
|
||||
MemoryMappedFile::~MemoryMappedFile() {
|
||||
Unmap();
|
||||
}
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
bool MemoryMappedFile::Map(const char* path, size_t offset) {
|
||||
Unmap();
|
||||
|
||||
int fd = sys_open(path, O_RDONLY, 0);
|
||||
if (fd == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__) || defined(__aarch64__) || \
|
||||
(defined(__mips__) && _MIPS_SIM == _ABI64)
|
||||
|
||||
struct kernel_stat st;
|
||||
if (sys_fstat(fd, &st) == -1 || st.st_size < 0) {
|
||||
#else
|
||||
struct kernel_stat64 st;
|
||||
if (sys_fstat64(fd, &st) == -1 || st.st_size < 0) {
|
||||
#endif
|
||||
sys_close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Strangely file size can be negative, but we check above that it is not.
|
||||
size_t file_len = static_cast<size_t>(st.st_size);
|
||||
// If the file does not extend beyond the offset, simply use an empty
|
||||
// MemoryRange and return true. Don't bother to call mmap()
|
||||
// even though mmap() can handle an empty file on some platforms.
|
||||
if (offset >= file_len) {
|
||||
sys_close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__) || defined(__aarch64__) || \
|
||||
(defined(__mips__) && _MIPS_SIM == _ABI64)
|
||||
void* data = sys_mmap(NULL, file_len, PROT_READ, MAP_PRIVATE, fd, offset);
|
||||
#else
|
||||
if ((offset & 4095) != 0) {
|
||||
// Not page aligned.
|
||||
sys_close(fd);
|
||||
return false;
|
||||
}
|
||||
void* data = sys_mmap2(
|
||||
NULL, file_len, PROT_READ, MAP_PRIVATE, fd, offset >> 12);
|
||||
#endif
|
||||
sys_close(fd);
|
||||
if (data == MAP_FAILED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
content_.Set(data, file_len - offset);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MemoryMappedFile::Unmap() {
|
||||
if (content_.data()) {
|
||||
sys_munmap(const_cast<uint8_t*>(content_.data()), content_.length());
|
||||
content_.Set(NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -1,87 +0,0 @@
|
|||
// Copyright (c) 2011, 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.
|
||||
|
||||
// memory_mapped_file.h: Define the google_breakpad::MemoryMappedFile
|
||||
// class, which maps a file into memory for read-only access.
|
||||
|
||||
#ifndef COMMON_LINUX_MEMORY_MAPPED_FILE_H_
|
||||
#define COMMON_LINUX_MEMORY_MAPPED_FILE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include "common/basictypes.h"
|
||||
#include "common/memory_range.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// A utility class for mapping a file into memory for read-only access of
|
||||
// the file content. Its implementation avoids calling into libc functions
|
||||
// by directly making system calls for open, close, mmap, and munmap.
|
||||
class MemoryMappedFile {
|
||||
public:
|
||||
MemoryMappedFile();
|
||||
|
||||
// Constructor that calls Map() to map a file at |path| into memory.
|
||||
// If Map() fails, the object behaves as if it is default constructed.
|
||||
MemoryMappedFile(const char* path, size_t offset);
|
||||
|
||||
~MemoryMappedFile();
|
||||
|
||||
// Maps a file at |path| into memory, which can then be accessed via
|
||||
// content() as a MemoryRange object or via data(), and returns true on
|
||||
// success. Mapping an empty file will succeed but with data() and size()
|
||||
// returning NULL and 0, respectively. An existing mapping is unmapped
|
||||
// before a new mapping is created.
|
||||
bool Map(const char* path, size_t offset);
|
||||
|
||||
// Unmaps the memory for the mapped file. It's a no-op if no file is
|
||||
// mapped.
|
||||
void Unmap();
|
||||
|
||||
// Returns a MemoryRange object that covers the memory for the mapped
|
||||
// file. The MemoryRange object is empty if no file is mapped.
|
||||
const MemoryRange& content() const { return content_; }
|
||||
|
||||
// Returns a pointer to the beginning of the memory for the mapped file.
|
||||
// or NULL if no file is mapped or the mapped file is empty.
|
||||
const void* data() const { return content_.data(); }
|
||||
|
||||
// Returns the size in bytes of the mapped file, or zero if no file
|
||||
// is mapped.
|
||||
size_t size() const { return content_.length(); }
|
||||
|
||||
private:
|
||||
// Mapped file content as a MemoryRange object.
|
||||
MemoryRange content_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MemoryMappedFile);
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_LINUX_MEMORY_MAPPED_FILE_H_
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright (c) 2011, 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.
|
||||
|
||||
// safe_readlink.cc: Implement google_breakpad::SafeReadLink.
|
||||
// See safe_readlink.h for details.
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
bool SafeReadLink(const char* path, char* buffer, size_t buffer_size) {
|
||||
// sys_readlink() does not add a NULL byte to |buffer|. In order to return
|
||||
// a NULL-terminated string in |buffer|, |buffer_size| should be at least
|
||||
// one byte longer than the expected path length. Also, sys_readlink()
|
||||
// returns the actual path length on success, which does not count the
|
||||
// NULL byte, so |result_size| should be less than |buffer_size|.
|
||||
ssize_t result_size = sys_readlink(path, buffer, buffer_size);
|
||||
if (result_size >= 0 && static_cast<size_t>(result_size) < buffer_size) {
|
||||
buffer[result_size] = '\0';
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -1,65 +0,0 @@
|
|||
// Copyright (c) 2011, 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.
|
||||
|
||||
// safe_readlink.h: Define the google_breakpad::SafeReadLink function,
|
||||
// which wraps sys_readlink and gurantees the result is NULL-terminated.
|
||||
|
||||
#ifndef COMMON_LINUX_SAFE_READLINK_H_
|
||||
#define COMMON_LINUX_SAFE_READLINK_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// This function wraps sys_readlink() and performs the same functionalty,
|
||||
// but guarantees |buffer| is NULL-terminated if sys_readlink() returns
|
||||
// no error. It takes the same arguments as sys_readlink(), but unlike
|
||||
// sys_readlink(), it returns true on success.
|
||||
//
|
||||
// |buffer_size| specifies the size of |buffer| in bytes. As this function
|
||||
// always NULL-terminates |buffer| on success, |buffer_size| should be
|
||||
// at least one byte longer than the expected path length (e.g. PATH_MAX,
|
||||
// which is typically defined as the maximum length of a path name
|
||||
// including the NULL byte).
|
||||
//
|
||||
// The implementation of this function calls sys_readlink() instead of
|
||||
// readlink(), it can thus be used in the context where calling to libc
|
||||
// functions is discouraged.
|
||||
bool SafeReadLink(const char* path, char* buffer, size_t buffer_size);
|
||||
|
||||
// Same as the three-argument version of SafeReadLink() but deduces the
|
||||
// size of |buffer| if it is a char array of known size.
|
||||
template <size_t N>
|
||||
bool SafeReadLink(const char* path, char (&buffer)[N]) {
|
||||
return SafeReadLink(path, buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_LINUX_SAFE_READLINK_H_
|
|
@ -1,251 +0,0 @@
|
|||
/*
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5Context structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "common/md5.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
#define byteReverse(buf, len) /* Nothing */
|
||||
#else
|
||||
/*
|
||||
* Note: this code is harmless on little-endian machines.
|
||||
*/
|
||||
static void byteReverse(unsigned char *buf, unsigned longs)
|
||||
{
|
||||
u32 t;
|
||||
do {
|
||||
t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
|
||||
((unsigned) buf[1] << 8 | buf[0]);
|
||||
*(u32 *) buf = t;
|
||||
buf += 4;
|
||||
} while (--longs);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void MD5Transform(u32 buf[4], u32 const in[16]);
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
void MD5Init(struct MD5Context *ctx)
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bits[0] = 0;
|
||||
ctx->bits[1] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
void MD5Update(struct MD5Context *ctx, unsigned char const *buf, size_t len)
|
||||
{
|
||||
u32 t;
|
||||
|
||||
/* Update bitcount */
|
||||
|
||||
t = ctx->bits[0];
|
||||
if ((ctx->bits[0] = t + ((u32) len << 3)) < t)
|
||||
ctx->bits[1]++; /* Carry from low to high */
|
||||
ctx->bits[1] += len >> 29;
|
||||
|
||||
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
||||
|
||||
/* Handle any leading odd-sized chunks */
|
||||
|
||||
if (t) {
|
||||
unsigned char *p = (unsigned char *) ctx->in + t;
|
||||
|
||||
t = 64 - t;
|
||||
if (len < t) {
|
||||
memcpy(p, buf, len);
|
||||
return;
|
||||
}
|
||||
memcpy(p, buf, t);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (u32 *) ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
}
|
||||
/* Process data in 64-byte chunks */
|
||||
|
||||
while (len >= 64) {
|
||||
memcpy(ctx->in, buf, 64);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (u32 *) ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
|
||||
memcpy(ctx->in, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
|
||||
{
|
||||
unsigned count;
|
||||
unsigned char *p;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
count = (ctx->bits[0] >> 3) & 0x3F;
|
||||
|
||||
/* Set the first char of padding to 0x80. This is safe since there is
|
||||
always at least one byte free */
|
||||
p = ctx->in + count;
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 64 bytes */
|
||||
count = 64 - 1 - count;
|
||||
|
||||
/* Pad out to 56 mod 64 */
|
||||
if (count < 8) {
|
||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||
memset(p, 0, count);
|
||||
byteReverse(ctx->in, 16);
|
||||
MD5Transform(ctx->buf, (u32 *) ctx->in);
|
||||
|
||||
/* Now fill the next block with 56 bytes */
|
||||
memset(ctx->in, 0, 56);
|
||||
} else {
|
||||
/* Pad block to 56 bytes */
|
||||
memset(p, 0, count - 8);
|
||||
}
|
||||
byteReverse(ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
((u32 *) ctx->in)[14] = ctx->bits[0];
|
||||
((u32 *) ctx->in)[15] = ctx->bits[1];
|
||||
|
||||
MD5Transform(ctx->buf, (u32 *) ctx->in);
|
||||
byteReverse((unsigned char *) ctx->buf, 4);
|
||||
memcpy(digest, ctx->buf, 16);
|
||||
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
static void MD5Transform(u32 buf[4], u32 const in[16])
|
||||
{
|
||||
u32 a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
// Copyright 2007 Google Inc. All Rights Reserved.
|
||||
// Author: liuli@google.com (Liu Li)
|
||||
#ifndef COMMON_MD5_H__
|
||||
#define COMMON_MD5_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
typedef uint32_t u32;
|
||||
typedef uint8_t u8;
|
||||
|
||||
struct MD5Context {
|
||||
u32 buf[4];
|
||||
u32 bits[2];
|
||||
u8 in[64];
|
||||
};
|
||||
|
||||
void MD5Init(struct MD5Context *ctx);
|
||||
|
||||
void MD5Update(struct MD5Context *ctx, unsigned char const *buf, size_t len);
|
||||
|
||||
void MD5Final(unsigned char digest[16], struct MD5Context *ctx);
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_MD5_H__
|
|
@ -1,212 +0,0 @@
|
|||
// Copyright (c) 2009, 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_MEMORY_H_
|
||||
#define GOOGLE_BREAKPAD_COMMON_MEMORY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#if defined(MEMORY_SANITIZER)
|
||||
#include <sanitizer/msan_interface.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define sys_mmap mmap
|
||||
#define sys_mmap2 mmap
|
||||
#define sys_munmap munmap
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#else
|
||||
#include "third_party/lss/linux_syscall_support.h"
|
||||
#endif
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// This is very simple allocator which fetches pages from the kernel directly.
|
||||
// Thus, it can be used even when the heap may be corrupted.
|
||||
//
|
||||
// There is no free operation. The pages are only freed when the object is
|
||||
// destroyed.
|
||||
class PageAllocator {
|
||||
public:
|
||||
PageAllocator()
|
||||
: page_size_(getpagesize()),
|
||||
last_(NULL),
|
||||
current_page_(NULL),
|
||||
page_offset_(0) {
|
||||
}
|
||||
|
||||
~PageAllocator() {
|
||||
FreeAll();
|
||||
}
|
||||
|
||||
void *Alloc(size_t bytes) {
|
||||
if (!bytes)
|
||||
return NULL;
|
||||
|
||||
if (current_page_ && page_size_ - page_offset_ >= bytes) {
|
||||
uint8_t *const ret = current_page_ + page_offset_;
|
||||
page_offset_ += bytes;
|
||||
if (page_offset_ == page_size_) {
|
||||
page_offset_ = 0;
|
||||
current_page_ = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const size_t pages =
|
||||
(bytes + sizeof(PageHeader) + page_size_ - 1) / page_size_;
|
||||
uint8_t *const ret = GetNPages(pages);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
page_offset_ =
|
||||
(page_size_ - (page_size_ * pages - (bytes + sizeof(PageHeader)))) %
|
||||
page_size_;
|
||||
current_page_ = page_offset_ ? ret + page_size_ * (pages - 1) : NULL;
|
||||
|
||||
return ret + sizeof(PageHeader);
|
||||
}
|
||||
|
||||
// Checks whether the page allocator owns the passed-in pointer.
|
||||
// This method exists for testing pursposes only.
|
||||
bool OwnsPointer(const void* p) {
|
||||
for (PageHeader* header = last_; header; header = header->next) {
|
||||
const char* current = reinterpret_cast<char*>(header);
|
||||
if ((p >= current) && (p < current + header->num_pages * page_size_))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t *GetNPages(size_t num_pages) {
|
||||
#if defined(__x86_64__) || defined(__aarch64__) || defined(__aarch64__) || \
|
||||
((defined(__mips__) && _MIPS_SIM == _ABI64))
|
||||
void *a = sys_mmap(NULL, page_size_ * num_pages, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
#else
|
||||
void *a = sys_mmap2(NULL, page_size_ * num_pages, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
#endif
|
||||
if (a == MAP_FAILED)
|
||||
return NULL;
|
||||
|
||||
#if defined(MEMORY_SANITIZER)
|
||||
// We need to indicate to MSan that memory allocated through sys_mmap is
|
||||
// initialized, since linux_syscall_support.h doesn't have MSan hooks.
|
||||
__msan_unpoison(a, page_size_ * num_pages);
|
||||
#endif
|
||||
|
||||
struct PageHeader *header = reinterpret_cast<PageHeader*>(a);
|
||||
header->next = last_;
|
||||
header->num_pages = num_pages;
|
||||
last_ = header;
|
||||
|
||||
return reinterpret_cast<uint8_t*>(a);
|
||||
}
|
||||
|
||||
void FreeAll() {
|
||||
PageHeader *next;
|
||||
|
||||
for (PageHeader *cur = last_; cur; cur = next) {
|
||||
next = cur->next;
|
||||
sys_munmap(cur, cur->num_pages * page_size_);
|
||||
}
|
||||
}
|
||||
|
||||
struct PageHeader {
|
||||
PageHeader *next; // pointer to the start of the next set of pages.
|
||||
size_t num_pages; // the number of pages in this set.
|
||||
};
|
||||
|
||||
const size_t page_size_;
|
||||
PageHeader *last_;
|
||||
uint8_t *current_page_;
|
||||
size_t page_offset_;
|
||||
};
|
||||
|
||||
// Wrapper to use with STL containers
|
||||
template <typename T>
|
||||
struct PageStdAllocator : public std::allocator<T> {
|
||||
typedef typename std::allocator<T>::pointer pointer;
|
||||
typedef typename std::allocator<T>::size_type size_type;
|
||||
|
||||
explicit PageStdAllocator(PageAllocator& allocator): allocator_(allocator) {}
|
||||
template <class Other> PageStdAllocator(const PageStdAllocator<Other>& other)
|
||||
: allocator_(other.allocator_) {}
|
||||
|
||||
inline pointer allocate(size_type n, const void* = 0) {
|
||||
return static_cast<pointer>(allocator_.Alloc(sizeof(T) * n));
|
||||
}
|
||||
|
||||
inline void deallocate(pointer, size_type) {
|
||||
// The PageAllocator doesn't free.
|
||||
}
|
||||
|
||||
template <typename U> struct rebind {
|
||||
typedef PageStdAllocator<U> other;
|
||||
};
|
||||
|
||||
private:
|
||||
// Silly workaround for the gcc from Android's ndk (gcc 4.6), which will
|
||||
// otherwise complain that `other.allocator_` is private in the constructor
|
||||
// code.
|
||||
template<typename Other> friend struct PageStdAllocator;
|
||||
|
||||
PageAllocator& allocator_;
|
||||
};
|
||||
|
||||
// A wasteful vector is a std::vector, except that it allocates memory from a
|
||||
// PageAllocator. It's wasteful because, when resizing, it always allocates a
|
||||
// whole new array since the PageAllocator doesn't support realloc.
|
||||
template<class T>
|
||||
class wasteful_vector : public std::vector<T, PageStdAllocator<T> > {
|
||||
public:
|
||||
wasteful_vector(PageAllocator* allocator, unsigned size_hint = 16)
|
||||
: std::vector<T, PageStdAllocator<T> >(PageStdAllocator<T>(*allocator)) {
|
||||
std::vector<T, PageStdAllocator<T> >::reserve(size_hint);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
inline void* operator new(size_t nbytes,
|
||||
google_breakpad::PageAllocator& allocator) {
|
||||
return allocator.Alloc(nbytes);
|
||||
}
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_MEMORY_H_
|
|
@ -1,145 +0,0 @@
|
|||
// Copyright (c) 2011, 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.
|
||||
|
||||
// memory_range.h: Define the google_breakpad::MemoryRange class, which
|
||||
// is a lightweight wrapper with a pointer and a length to encapsulate
|
||||
// a contiguous range of memory.
|
||||
|
||||
#ifndef COMMON_MEMORY_RANGE_H_
|
||||
#define COMMON_MEMORY_RANGE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "google_breakpad/common/breakpad_types.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// A lightweight wrapper with a pointer and a length to encapsulate a
|
||||
// contiguous range of memory. It provides helper methods for checked
|
||||
// access of a subrange of the memory. Its implemementation does not
|
||||
// allocate memory or call into libc functions, and is thus safer to use
|
||||
// in a crashed environment.
|
||||
class MemoryRange {
|
||||
public:
|
||||
MemoryRange() : data_(NULL), length_(0) {}
|
||||
|
||||
MemoryRange(const void* data, size_t length) {
|
||||
Set(data, length);
|
||||
}
|
||||
|
||||
// Returns true if this memory range contains no data.
|
||||
bool IsEmpty() const {
|
||||
// Set() guarantees that |length_| is zero if |data_| is NULL.
|
||||
return length_ == 0;
|
||||
}
|
||||
|
||||
// Resets to an empty range.
|
||||
void Reset() {
|
||||
data_ = NULL;
|
||||
length_ = 0;
|
||||
}
|
||||
|
||||
// Sets this memory range to point to |data| and its length to |length|.
|
||||
void Set(const void* data, size_t length) {
|
||||
data_ = reinterpret_cast<const uint8_t*>(data);
|
||||
// Always set |length_| to zero if |data_| is NULL.
|
||||
length_ = data ? length : 0;
|
||||
}
|
||||
|
||||
// Returns true if this range covers a subrange of |sub_length| bytes
|
||||
// at |sub_offset| bytes of this memory range, or false otherwise.
|
||||
bool Covers(size_t sub_offset, size_t sub_length) const {
|
||||
// The following checks verify that:
|
||||
// 1. sub_offset is within [ 0 .. length_ - 1 ]
|
||||
// 2. sub_offset + sub_length is within
|
||||
// [ sub_offset .. length_ ]
|
||||
return sub_offset < length_ &&
|
||||
sub_offset + sub_length >= sub_offset &&
|
||||
sub_offset + sub_length <= length_;
|
||||
}
|
||||
|
||||
// Returns a raw data pointer to a subrange of |sub_length| bytes at
|
||||
// |sub_offset| bytes of this memory range, or NULL if the subrange
|
||||
// is out of bounds.
|
||||
const void* GetData(size_t sub_offset, size_t sub_length) const {
|
||||
return Covers(sub_offset, sub_length) ? (data_ + sub_offset) : NULL;
|
||||
}
|
||||
|
||||
// Same as the two-argument version of GetData() but uses sizeof(DataType)
|
||||
// as the subrange length and returns an |DataType| pointer for convenience.
|
||||
template <typename DataType>
|
||||
const DataType* GetData(size_t sub_offset) const {
|
||||
return reinterpret_cast<const DataType*>(
|
||||
GetData(sub_offset, sizeof(DataType)));
|
||||
}
|
||||
|
||||
// Returns a raw pointer to the |element_index|-th element of an array
|
||||
// of elements of length |element_size| starting at |sub_offset| bytes
|
||||
// of this memory range, or NULL if the element is out of bounds.
|
||||
const void* GetArrayElement(size_t element_offset,
|
||||
size_t element_size,
|
||||
unsigned element_index) const {
|
||||
size_t sub_offset = element_offset + element_index * element_size;
|
||||
return GetData(sub_offset, element_size);
|
||||
}
|
||||
|
||||
// Same as the three-argument version of GetArrayElement() but deduces
|
||||
// the element size using sizeof(ElementType) and returns an |ElementType|
|
||||
// pointer for convenience.
|
||||
template <typename ElementType>
|
||||
const ElementType* GetArrayElement(size_t element_offset,
|
||||
unsigned element_index) const {
|
||||
return reinterpret_cast<const ElementType*>(
|
||||
GetArrayElement(element_offset, sizeof(ElementType), element_index));
|
||||
}
|
||||
|
||||
// Returns a subrange of |sub_length| bytes at |sub_offset| bytes of
|
||||
// this memory range, or an empty range if the subrange is out of bounds.
|
||||
MemoryRange Subrange(size_t sub_offset, size_t sub_length) const {
|
||||
return Covers(sub_offset, sub_length) ?
|
||||
MemoryRange(data_ + sub_offset, sub_length) : MemoryRange();
|
||||
}
|
||||
|
||||
// Returns a pointer to the beginning of this memory range.
|
||||
const uint8_t* data() const { return data_; }
|
||||
|
||||
// Returns the length, in bytes, of this memory range.
|
||||
size_t length() const { return length_; }
|
||||
|
||||
private:
|
||||
// Pointer to the beginning of this memory range.
|
||||
const uint8_t* data_;
|
||||
|
||||
// Length, in bytes, of this memory range.
|
||||
size_t length_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_MEMORY_RANGE_H_
|
|
@ -1,56 +0,0 @@
|
|||
// 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 GOOGLE_BREAKPAD_COMMON_MINIDUMP_TYPE_HELPER_H_
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_TYPE_HELPER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
template <size_t>
|
||||
struct MDTypeHelper;
|
||||
|
||||
template <>
|
||||
struct MDTypeHelper<sizeof(uint32_t)> {
|
||||
typedef MDRawDebug32 MDRawDebug;
|
||||
typedef MDRawLinkMap32 MDRawLinkMap;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MDTypeHelper<sizeof(uint64_t)> {
|
||||
typedef MDRawDebug64 MDRawDebug;
|
||||
typedef MDRawLinkMap64 MDRawLinkMap;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_MINIDUMP_TYPE_HELPER_H_
|
|
@ -1,404 +0,0 @@
|
|||
// Copyright 2013 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.
|
||||
|
||||
// Scopers help you manage ownership of a pointer, helping you easily manage the
|
||||
// a pointer within a scope, and automatically destroying the pointer at the
|
||||
// end of a scope. There are two main classes you will use, which correspond
|
||||
// to the operators new/delete and new[]/delete[].
|
||||
//
|
||||
// Example usage (scoped_ptr):
|
||||
// {
|
||||
// scoped_ptr<Foo> foo(new Foo("wee"));
|
||||
// } // foo goes out of scope, releasing the pointer with it.
|
||||
//
|
||||
// {
|
||||
// scoped_ptr<Foo> foo; // No pointer managed.
|
||||
// foo.reset(new Foo("wee")); // Now a pointer is managed.
|
||||
// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed.
|
||||
// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed.
|
||||
// foo->Method(); // Foo::Method() called.
|
||||
// foo.get()->Method(); // Foo::Method() called.
|
||||
// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer
|
||||
// // manages a pointer.
|
||||
// foo.reset(new Foo("wee4")); // foo manages a pointer again.
|
||||
// foo.reset(); // Foo("wee4") destroyed, foo no longer
|
||||
// // manages a pointer.
|
||||
// } // foo wasn't managing a pointer, so nothing was destroyed.
|
||||
//
|
||||
// Example usage (scoped_array):
|
||||
// {
|
||||
// scoped_array<Foo> foo(new Foo[100]);
|
||||
// foo.get()->Method(); // Foo::Method on the 0th element.
|
||||
// foo[10].Method(); // Foo::Method on the 10th element.
|
||||
// }
|
||||
|
||||
#ifndef COMMON_SCOPED_PTR_H_
|
||||
#define COMMON_SCOPED_PTR_H_
|
||||
|
||||
// This is an implementation designed to match the anticipated future TR2
|
||||
// implementation of the scoped_ptr class, and its closely-related brethren,
|
||||
// scoped_array, scoped_ptr_malloc.
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
|
||||
// automatically deletes the pointer it holds (if any).
|
||||
// That is, scoped_ptr<T> owns the T object that it points to.
|
||||
// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
|
||||
// Also like T*, scoped_ptr<T> is thread-compatible, and once you
|
||||
// dereference it, you get the threadsafety guarantees of T.
|
||||
//
|
||||
// The size of a scoped_ptr is small:
|
||||
// sizeof(scoped_ptr<C>) == sizeof(C*)
|
||||
template <class C>
|
||||
class scoped_ptr {
|
||||
public:
|
||||
|
||||
// The element type
|
||||
typedef C element_type;
|
||||
|
||||
// Constructor. Defaults to initializing with NULL.
|
||||
// There is no way to create an uninitialized scoped_ptr.
|
||||
// The input parameter must be allocated with new.
|
||||
explicit scoped_ptr(C* p = NULL) : ptr_(p) { }
|
||||
|
||||
// Destructor. If there is a C object, delete it.
|
||||
// We don't need to test ptr_ == NULL because C++ does that for us.
|
||||
~scoped_ptr() {
|
||||
enum { type_must_be_complete = sizeof(C) };
|
||||
delete ptr_;
|
||||
}
|
||||
|
||||
// Reset. Deletes the current owned object, if any.
|
||||
// Then takes ownership of a new object, if given.
|
||||
// this->reset(this->get()) works.
|
||||
void reset(C* p = NULL) {
|
||||
if (p != ptr_) {
|
||||
enum { type_must_be_complete = sizeof(C) };
|
||||
delete ptr_;
|
||||
ptr_ = p;
|
||||
}
|
||||
}
|
||||
|
||||
// Accessors to get the owned object.
|
||||
// operator* and operator-> will assert() if there is no current object.
|
||||
C& operator*() const {
|
||||
assert(ptr_ != NULL);
|
||||
return *ptr_;
|
||||
}
|
||||
C* operator->() const {
|
||||
assert(ptr_ != NULL);
|
||||
return ptr_;
|
||||
}
|
||||
C* get() const { return ptr_; }
|
||||
|
||||
// Comparison operators.
|
||||
// These return whether two scoped_ptr refer to the same object, not just to
|
||||
// two different but equal objects.
|
||||
bool operator==(C* p) const { return ptr_ == p; }
|
||||
bool operator!=(C* p) const { return ptr_ != p; }
|
||||
|
||||
// Swap two scoped pointers.
|
||||
void swap(scoped_ptr& p2) {
|
||||
C* tmp = ptr_;
|
||||
ptr_ = p2.ptr_;
|
||||
p2.ptr_ = tmp;
|
||||
}
|
||||
|
||||
// Release a pointer.
|
||||
// The return value is the current pointer held by this object.
|
||||
// If this object holds a NULL pointer, the return value is NULL.
|
||||
// After this operation, this object will hold a NULL pointer,
|
||||
// and will not own the object any more.
|
||||
C* release() {
|
||||
C* retVal = ptr_;
|
||||
ptr_ = NULL;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private:
|
||||
C* ptr_;
|
||||
|
||||
// Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't
|
||||
// make sense, and if C2 == C, it still doesn't make sense because you should
|
||||
// never have the same object owned by two different scoped_ptrs.
|
||||
template <class C2> bool operator==(scoped_ptr<C2> const& p2) const;
|
||||
template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const;
|
||||
|
||||
// Disallow evil constructors
|
||||
scoped_ptr(const scoped_ptr&);
|
||||
void operator=(const scoped_ptr&);
|
||||
};
|
||||
|
||||
// Free functions
|
||||
template <class C>
|
||||
void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) {
|
||||
p1.swap(p2);
|
||||
}
|
||||
|
||||
template <class C>
|
||||
bool operator==(C* p1, const scoped_ptr<C>& p2) {
|
||||
return p1 == p2.get();
|
||||
}
|
||||
|
||||
template <class C>
|
||||
bool operator!=(C* p1, const scoped_ptr<C>& p2) {
|
||||
return p1 != p2.get();
|
||||
}
|
||||
|
||||
// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
|
||||
// with new [] and the destructor deletes objects with delete [].
|
||||
//
|
||||
// As with scoped_ptr<C>, a scoped_array<C> either points to an object
|
||||
// or is NULL. A scoped_array<C> owns the object that it points to.
|
||||
// scoped_array<T> is thread-compatible, and once you index into it,
|
||||
// the returned objects have only the threadsafety guarantees of T.
|
||||
//
|
||||
// Size: sizeof(scoped_array<C>) == sizeof(C*)
|
||||
template <class C>
|
||||
class scoped_array {
|
||||
public:
|
||||
|
||||
// The element type
|
||||
typedef C element_type;
|
||||
|
||||
// Constructor. Defaults to intializing with NULL.
|
||||
// There is no way to create an uninitialized scoped_array.
|
||||
// The input parameter must be allocated with new [].
|
||||
explicit scoped_array(C* p = NULL) : array_(p) { }
|
||||
|
||||
// Destructor. If there is a C object, delete it.
|
||||
// We don't need to test ptr_ == NULL because C++ does that for us.
|
||||
~scoped_array() {
|
||||
enum { type_must_be_complete = sizeof(C) };
|
||||
delete[] array_;
|
||||
}
|
||||
|
||||
// Reset. Deletes the current owned object, if any.
|
||||
// Then takes ownership of a new object, if given.
|
||||
// this->reset(this->get()) works.
|
||||
void reset(C* p = NULL) {
|
||||
if (p != array_) {
|
||||
enum { type_must_be_complete = sizeof(C) };
|
||||
delete[] array_;
|
||||
array_ = p;
|
||||
}
|
||||
}
|
||||
|
||||
// Get one element of the current object.
|
||||
// Will assert() if there is no current object, or index i is negative.
|
||||
C& operator[](ptrdiff_t i) const {
|
||||
assert(i >= 0);
|
||||
assert(array_ != NULL);
|
||||
return array_[i];
|
||||
}
|
||||
|
||||
// Get a pointer to the zeroth element of the current object.
|
||||
// If there is no current object, return NULL.
|
||||
C* get() const {
|
||||
return array_;
|
||||
}
|
||||
|
||||
// Comparison operators.
|
||||
// These return whether two scoped_array refer to the same object, not just to
|
||||
// two different but equal objects.
|
||||
bool operator==(C* p) const { return array_ == p; }
|
||||
bool operator!=(C* p) const { return array_ != p; }
|
||||
|
||||
// Swap two scoped arrays.
|
||||
void swap(scoped_array& p2) {
|
||||
C* tmp = array_;
|
||||
array_ = p2.array_;
|
||||
p2.array_ = tmp;
|
||||
}
|
||||
|
||||
// Release an array.
|
||||
// The return value is the current pointer held by this object.
|
||||
// If this object holds a NULL pointer, the return value is NULL.
|
||||
// After this operation, this object will hold a NULL pointer,
|
||||
// and will not own the object any more.
|
||||
C* release() {
|
||||
C* retVal = array_;
|
||||
array_ = NULL;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private:
|
||||
C* array_;
|
||||
|
||||
// Forbid comparison of different scoped_array types.
|
||||
template <class C2> bool operator==(scoped_array<C2> const& p2) const;
|
||||
template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
|
||||
|
||||
// Disallow evil constructors
|
||||
scoped_array(const scoped_array&);
|
||||
void operator=(const scoped_array&);
|
||||
};
|
||||
|
||||
// Free functions
|
||||
template <class C>
|
||||
void swap(scoped_array<C>& p1, scoped_array<C>& p2) {
|
||||
p1.swap(p2);
|
||||
}
|
||||
|
||||
template <class C>
|
||||
bool operator==(C* p1, const scoped_array<C>& p2) {
|
||||
return p1 == p2.get();
|
||||
}
|
||||
|
||||
template <class C>
|
||||
bool operator!=(C* p1, const scoped_array<C>& p2) {
|
||||
return p1 != p2.get();
|
||||
}
|
||||
|
||||
// This class wraps the c library function free() in a class that can be
|
||||
// passed as a template argument to scoped_ptr_malloc below.
|
||||
class ScopedPtrMallocFree {
|
||||
public:
|
||||
inline void operator()(void* x) const {
|
||||
free(x);
|
||||
}
|
||||
};
|
||||
|
||||
// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
|
||||
// second template argument, the functor used to free the object.
|
||||
|
||||
template<class C, class FreeProc = ScopedPtrMallocFree>
|
||||
class scoped_ptr_malloc {
|
||||
public:
|
||||
|
||||
// The element type
|
||||
typedef C element_type;
|
||||
|
||||
// Constructor. Defaults to initializing with NULL.
|
||||
// There is no way to create an uninitialized scoped_ptr.
|
||||
// The input parameter must be allocated with an allocator that matches the
|
||||
// Free functor. For the default Free functor, this is malloc, calloc, or
|
||||
// realloc.
|
||||
explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {}
|
||||
|
||||
// Destructor. If there is a C object, call the Free functor.
|
||||
~scoped_ptr_malloc() {
|
||||
reset();
|
||||
}
|
||||
|
||||
// Reset. Calls the Free functor on the current owned object, if any.
|
||||
// Then takes ownership of a new object, if given.
|
||||
// this->reset(this->get()) works.
|
||||
void reset(C* p = NULL) {
|
||||
if (ptr_ != p) {
|
||||
FreeProc free_proc;
|
||||
free_proc(ptr_);
|
||||
ptr_ = p;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the current object.
|
||||
// operator* and operator-> will cause an assert() failure if there is
|
||||
// no current object.
|
||||
C& operator*() const {
|
||||
assert(ptr_ != NULL);
|
||||
return *ptr_;
|
||||
}
|
||||
|
||||
C* operator->() const {
|
||||
assert(ptr_ != NULL);
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
C* get() const {
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
// Comparison operators.
|
||||
// These return whether a scoped_ptr_malloc and a plain pointer refer
|
||||
// to the same object, not just to two different but equal objects.
|
||||
// For compatibility with the boost-derived implementation, these
|
||||
// take non-const arguments.
|
||||
bool operator==(C* p) const {
|
||||
return ptr_ == p;
|
||||
}
|
||||
|
||||
bool operator!=(C* p) const {
|
||||
return ptr_ != p;
|
||||
}
|
||||
|
||||
// Swap two scoped pointers.
|
||||
void swap(scoped_ptr_malloc & b) {
|
||||
C* tmp = b.ptr_;
|
||||
b.ptr_ = ptr_;
|
||||
ptr_ = tmp;
|
||||
}
|
||||
|
||||
// Release a pointer.
|
||||
// The return value is the current pointer held by this object.
|
||||
// If this object holds a NULL pointer, the return value is NULL.
|
||||
// After this operation, this object will hold a NULL pointer,
|
||||
// and will not own the object any more.
|
||||
C* release() {
|
||||
C* tmp = ptr_;
|
||||
ptr_ = NULL;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
C* ptr_;
|
||||
|
||||
// no reason to use these: each scoped_ptr_malloc should have its own object
|
||||
template <class C2, class GP>
|
||||
bool operator==(scoped_ptr_malloc<C2, GP> const& p) const;
|
||||
template <class C2, class GP>
|
||||
bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const;
|
||||
|
||||
// Disallow evil constructors
|
||||
scoped_ptr_malloc(const scoped_ptr_malloc&);
|
||||
void operator=(const scoped_ptr_malloc&);
|
||||
};
|
||||
|
||||
template<class C, class FP> inline
|
||||
void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) {
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template<class C, class FP> inline
|
||||
bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) {
|
||||
return p == b.get();
|
||||
}
|
||||
|
||||
template<class C, class FP> inline
|
||||
bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) {
|
||||
return p != b.get();
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_SCOPED_PTR_H_
|
|
@ -1,155 +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.
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "common/convert_UTF.h"
|
||||
#include "common/scoped_ptr.h"
|
||||
#include "common/string_conversion.h"
|
||||
#include "common/using_std_string.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
using std::vector;
|
||||
|
||||
void UTF8ToUTF16(const char *in, vector<uint16_t> *out) {
|
||||
size_t source_length = strlen(in);
|
||||
const UTF8 *source_ptr = reinterpret_cast<const UTF8 *>(in);
|
||||
const UTF8 *source_end_ptr = source_ptr + source_length;
|
||||
// Erase the contents and zero fill to the expected size
|
||||
out->clear();
|
||||
out->insert(out->begin(), source_length, 0);
|
||||
uint16_t *target_ptr = &(*out)[0];
|
||||
uint16_t *target_end_ptr = target_ptr + out->capacity() * sizeof(uint16_t);
|
||||
ConversionResult result = ConvertUTF8toUTF16(&source_ptr, source_end_ptr,
|
||||
&target_ptr, target_end_ptr,
|
||||
strictConversion);
|
||||
|
||||
// Resize to be the size of the # of converted characters + NULL
|
||||
out->resize(result == conversionOK ? target_ptr - &(*out)[0] + 1: 0);
|
||||
}
|
||||
|
||||
int UTF8ToUTF16Char(const char *in, int in_length, uint16_t out[2]) {
|
||||
const UTF8 *source_ptr = reinterpret_cast<const UTF8 *>(in);
|
||||
const UTF8 *source_end_ptr = source_ptr + sizeof(char);
|
||||
uint16_t *target_ptr = out;
|
||||
uint16_t *target_end_ptr = target_ptr + 2 * sizeof(uint16_t);
|
||||
out[0] = out[1] = 0;
|
||||
|
||||
// Process one character at a time
|
||||
while (1) {
|
||||
ConversionResult result = ConvertUTF8toUTF16(&source_ptr, source_end_ptr,
|
||||
&target_ptr, target_end_ptr,
|
||||
strictConversion);
|
||||
|
||||
if (result == conversionOK)
|
||||
return static_cast<int>(source_ptr - reinterpret_cast<const UTF8 *>(in));
|
||||
|
||||
// Add another character to the input stream and try again
|
||||
source_ptr = reinterpret_cast<const UTF8 *>(in);
|
||||
++source_end_ptr;
|
||||
|
||||
if (source_end_ptr > reinterpret_cast<const UTF8 *>(in) + in_length)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UTF32ToUTF16(const wchar_t *in, vector<uint16_t> *out) {
|
||||
size_t source_length = wcslen(in);
|
||||
const UTF32 *source_ptr = reinterpret_cast<const UTF32 *>(in);
|
||||
const UTF32 *source_end_ptr = source_ptr + source_length;
|
||||
// Erase the contents and zero fill to the expected size
|
||||
out->clear();
|
||||
out->insert(out->begin(), source_length, 0);
|
||||
uint16_t *target_ptr = &(*out)[0];
|
||||
uint16_t *target_end_ptr = target_ptr + out->capacity() * sizeof(uint16_t);
|
||||
ConversionResult result = ConvertUTF32toUTF16(&source_ptr, source_end_ptr,
|
||||
&target_ptr, target_end_ptr,
|
||||
strictConversion);
|
||||
|
||||
// Resize to be the size of the # of converted characters + NULL
|
||||
out->resize(result == conversionOK ? target_ptr - &(*out)[0] + 1: 0);
|
||||
}
|
||||
|
||||
void UTF32ToUTF16Char(wchar_t in, uint16_t out[2]) {
|
||||
const UTF32 *source_ptr = reinterpret_cast<const UTF32 *>(&in);
|
||||
const UTF32 *source_end_ptr = source_ptr + 1;
|
||||
uint16_t *target_ptr = out;
|
||||
uint16_t *target_end_ptr = target_ptr + 2 * sizeof(uint16_t);
|
||||
out[0] = out[1] = 0;
|
||||
ConversionResult result = ConvertUTF32toUTF16(&source_ptr, source_end_ptr,
|
||||
&target_ptr, target_end_ptr,
|
||||
strictConversion);
|
||||
|
||||
if (result != conversionOK) {
|
||||
out[0] = out[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint16_t Swap(uint16_t value) {
|
||||
return (value >> 8) | static_cast<uint16_t>(value << 8);
|
||||
}
|
||||
|
||||
string UTF16ToUTF8(const vector<uint16_t> &in, bool swap) {
|
||||
const UTF16 *source_ptr = &in[0];
|
||||
scoped_array<uint16_t> source_buffer;
|
||||
|
||||
// If we're to swap, we need to make a local copy and swap each byte pair
|
||||
if (swap) {
|
||||
int idx = 0;
|
||||
source_buffer.reset(new uint16_t[in.size()]);
|
||||
UTF16 *source_buffer_ptr = source_buffer.get();
|
||||
for (vector<uint16_t>::const_iterator it = in.begin();
|
||||
it != in.end(); ++it, ++idx)
|
||||
source_buffer_ptr[idx] = Swap(*it);
|
||||
|
||||
source_ptr = source_buffer.get();
|
||||
}
|
||||
|
||||
// The maximum expansion would be 4x the size of the input string.
|
||||
const UTF16 *source_end_ptr = source_ptr + in.size();
|
||||
size_t target_capacity = in.size() * 4;
|
||||
scoped_array<UTF8> target_buffer(new UTF8[target_capacity]);
|
||||
UTF8 *target_ptr = target_buffer.get();
|
||||
UTF8 *target_end_ptr = target_ptr + target_capacity;
|
||||
ConversionResult result = ConvertUTF16toUTF8(&source_ptr, source_end_ptr,
|
||||
&target_ptr, target_end_ptr,
|
||||
strictConversion);
|
||||
|
||||
if (result == conversionOK) {
|
||||
const char *targetPtr = reinterpret_cast<const char *>(target_buffer.get());
|
||||
return targetPtr;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
|
@ -1,68 +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.
|
||||
|
||||
// string_conversion.h: Conversion between different UTF-8/16/32 encodings.
|
||||
|
||||
#ifndef COMMON_STRING_CONVERSION_H__
|
||||
#define COMMON_STRING_CONVERSION_H__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/using_std_string.h"
|
||||
#include "google_breakpad/common/breakpad_types.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
using std::vector;
|
||||
|
||||
// Convert |in| to UTF-16 into |out|. Use platform byte ordering. If the
|
||||
// conversion failed, |out| will be zero length.
|
||||
void UTF8ToUTF16(const char *in, vector<uint16_t> *out);
|
||||
|
||||
// Convert at least one character (up to a maximum of |in_length|) from |in|
|
||||
// to UTF-16 into |out|. Return the number of characters consumed from |in|.
|
||||
// Any unused characters in |out| will be initialized to 0. No memory will
|
||||
// be allocated by this routine.
|
||||
int UTF8ToUTF16Char(const char *in, int in_length, uint16_t out[2]);
|
||||
|
||||
// Convert |in| to UTF-16 into |out|. Use platform byte ordering. If the
|
||||
// conversion failed, |out| will be zero length.
|
||||
void UTF32ToUTF16(const wchar_t *in, vector<uint16_t> *out);
|
||||
|
||||
// Convert |in| to UTF-16 into |out|. Any unused characters in |out| will be
|
||||
// initialized to 0. No memory will be allocated by this routine.
|
||||
void UTF32ToUTF16Char(wchar_t in, uint16_t out[2]);
|
||||
|
||||
// Convert |in| to UTF-8. If |swap| is true, swap bytes before converting.
|
||||
string UTF16ToUTF8(const vector<uint16_t> &in, bool swap);
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // COMMON_STRING_CONVERSION_H__
|
|
@ -1,42 +0,0 @@
|
|||
// -*- mode: c++ -*-
|
||||
|
||||
// Copyright (c) 2013 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 COMMON_SYMBOL_DATA_H_
|
||||
#define COMMON_SYMBOL_DATA_H_
|
||||
|
||||
// Control what data is used from the symbol file.
|
||||
enum SymbolData {
|
||||
ALL_SYMBOL_DATA,
|
||||
NO_CFI,
|
||||
ONLY_CFI
|
||||
};
|
||||
|
||||
#endif // COMMON_SYMBOL_DATA_H_
|
|
@ -1,62 +0,0 @@
|
|||
// Copyright (c) 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
|
||||
// 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 this file to use unordered_map and unordered_set. If tr1
|
||||
// or C++11 is not available, you can switch to using hash_set and
|
||||
// hash_map by defining BP_USE_HASH_SET.
|
||||
|
||||
#ifndef COMMON_UNORDERED_H_
|
||||
#define COMMON_UNORDERED_H_
|
||||
|
||||
#if defined(BP_USE_HASH_SET)
|
||||
#include <hash_map>
|
||||
#include <hash_set>
|
||||
|
||||
// For hash<string>.
|
||||
#include "util/hash/hash.h"
|
||||
|
||||
template <class T, class U, class H = __gnu_cxx::hash<T> >
|
||||
struct unordered_map : public hash_map<T, U, H> {};
|
||||
template <class T, class H = __gnu_cxx::hash<T> >
|
||||
struct unordered_set : public hash_set<T, H> {};
|
||||
|
||||
#elif defined(_LIBCPP_VERSION) // c++11
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
using std::unordered_map;
|
||||
using std::unordered_set;
|
||||
|
||||
#else // Fallback to tr1::unordered
|
||||
#include <tr1/unordered_map>
|
||||
#include <tr1/unordered_set>
|
||||
using std::tr1::unordered_map;
|
||||
using std::tr1::unordered_set;
|
||||
#endif
|
||||
|
||||
#endif // COMMON_UNORDERED_H_
|
|
@ -1,65 +0,0 @@
|
|||
// -*- mode: C++ -*-
|
||||
|
||||
// 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.
|
||||
|
||||
// Original author: Ivan Penkov
|
||||
|
||||
// using_std_string.h: Allows building this code in environments where
|
||||
// global string (::string) exists.
|
||||
//
|
||||
// The problem:
|
||||
// -------------
|
||||
// Let's say you want to build this code in an environment where a global
|
||||
// string type is defined (i.e. ::string). Now, let's suppose that ::string
|
||||
// is different that std::string and you'd like to have the option to easily
|
||||
// choose between the two string types. Ideally you'd like to control which
|
||||
// string type is chosen by simply #defining an identifier.
|
||||
//
|
||||
// The solution:
|
||||
// -------------
|
||||
// #define HAS_GLOBAL_STRING somewhere in a global header file and then
|
||||
// globally replace std::string with string. Then include this header
|
||||
// file everywhere where string is used. If you want to revert back to
|
||||
// using std::string, simply remove the #define (HAS_GLOBAL_STRING).
|
||||
|
||||
#ifndef THIRD_PARTY_BREAKPAD_SRC_COMMON_USING_STD_STRING_H_
|
||||
#define THIRD_PARTY_BREAKPAD_SRC_COMMON_USING_STD_STRING_H_
|
||||
|
||||
#ifdef HAS_GLOBAL_STRING
|
||||
typedef ::string google_breakpad_string;
|
||||
#else
|
||||
using std::string;
|
||||
typedef std::string google_breakpad_string;
|
||||
#endif
|
||||
|
||||
// Inicates that type google_breakpad_string is defined
|
||||
#define HAS_GOOGLE_BREAKPAD_STRING
|
||||
|
||||
#endif // THIRD_PARTY_BREAKPAD_SRC_COMMON_USING_STD_STRING_H_
|
|
@ -1,86 +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. */
|
||||
|
||||
/* breakpad_types.h: Precise-width types
|
||||
*
|
||||
* (This is C99 source, please don't corrupt it with C++.)
|
||||
*
|
||||
* This file ensures that types uintN_t are defined for N = 8, 16, 32, and
|
||||
* 64. Types of precise widths are crucial to the task of writing data
|
||||
* structures on one platform and reading them on another.
|
||||
*
|
||||
* Author: Mark Mentovai */
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_BREAKPAD_TYPES_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_BREAKPAD_TYPES_H__
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#ifndef __STDC_FORMAT_MACROS
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif /* __STDC_FORMAT_MACROS */
|
||||
#include <inttypes.h>
|
||||
|
||||
#else /* !_WIN32 */
|
||||
|
||||
#if _MSC_VER >= 1600
|
||||
#include <stdint.h>
|
||||
#elif defined(BREAKPAD_CUSTOM_STDINT_H)
|
||||
/* Visual C++ Pre-2010 did not ship a stdint.h, so allow
|
||||
* consumers of this library to provide their own because
|
||||
* there are often subtle type incompatibilities.
|
||||
*/
|
||||
#include BREAKPAD_CUSTOM_STDINT_H
|
||||
#else
|
||||
#include <wtypes.h>
|
||||
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#endif
|
||||
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
typedef struct {
|
||||
uint64_t high;
|
||||
uint64_t low;
|
||||
} uint128_struct;
|
||||
|
||||
typedef uint64_t breakpad_time_t;
|
||||
|
||||
/* Try to get PRIx64 from inttypes.h, but if it's not defined, fall back to
|
||||
* llx, which is the format string for "long long" - this is a 64-bit
|
||||
* integral type on many systems. */
|
||||
#ifndef PRIx64
|
||||
#define PRIx64 "llx"
|
||||
#endif /* !PRIx64 */
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_COMMON_BREAKPAD_TYPES_H__ */
|
|
@ -1,235 +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. */
|
||||
|
||||
/* minidump_format.h: A cross-platform reimplementation of minidump-related
|
||||
* portions of DbgHelp.h from the Windows Platform SDK.
|
||||
*
|
||||
* (This is C99 source, please don't corrupt it with C++.)
|
||||
*
|
||||
* This file contains the necessary definitions to read minidump files
|
||||
* produced on amd64. These files may be read on any platform provided
|
||||
* that the alignments of these structures on the processing system are
|
||||
* identical to the alignments of these structures on the producing system.
|
||||
* For this reason, precise-sized types are used. The structures defined
|
||||
* by this file have been laid out to minimize alignment problems by ensuring
|
||||
* ensuring that all members are aligned on their natural boundaries. In
|
||||
* In some cases, tail-padding may be significant when different ABIs specify
|
||||
* different tail-padding behaviors. To avoid problems when reading or
|
||||
* writing affected structures, MD_*_SIZE macros are provided where needed,
|
||||
* containing the useful size of the structures without padding.
|
||||
*
|
||||
* Structures that are defined by Microsoft to contain a zero-length array
|
||||
* are instead defined here to contain an array with one element, as
|
||||
* zero-length arrays are forbidden by standard C and C++. In these cases,
|
||||
* *_minsize constants are provided to be used in place of sizeof. For a
|
||||
* cleaner interface to these sizes when using C++, see minidump_size.h.
|
||||
*
|
||||
* These structures are also sufficient to populate minidump files.
|
||||
*
|
||||
* These definitions may be extended to support handling minidump files
|
||||
* for other CPUs and other operating systems.
|
||||
*
|
||||
* Because precise data type sizes are crucial for this implementation to
|
||||
* function properly and portably in terms of interoperability with minidumps
|
||||
* produced by DbgHelp on Windows, a set of primitive types with known sizes
|
||||
* are used as the basis of each structure defined by this file. DbgHelp
|
||||
* on Windows is assumed to be the reference implementation; this file
|
||||
* seeks to provide a cross-platform compatible implementation. To avoid
|
||||
* collisions with the types and values defined and used by DbgHelp in the
|
||||
* event that this implementation is used on Windows, each type and value
|
||||
* defined here is given a new name, beginning with "MD". Names of the
|
||||
* equivalent types and values in the Windows Platform SDK are given in
|
||||
* comments.
|
||||
*
|
||||
* Author: Mark Mentovai
|
||||
* Change to split into its own file: Neal Sidhwaney */
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__
|
||||
|
||||
|
||||
/*
|
||||
* AMD64 support, see WINNT.H
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
uint16_t control_word;
|
||||
uint16_t status_word;
|
||||
uint8_t tag_word;
|
||||
uint8_t reserved1;
|
||||
uint16_t error_opcode;
|
||||
uint32_t error_offset;
|
||||
uint16_t error_selector;
|
||||
uint16_t reserved2;
|
||||
uint32_t data_offset;
|
||||
uint16_t data_selector;
|
||||
uint16_t reserved3;
|
||||
uint32_t mx_csr;
|
||||
uint32_t mx_csr_mask;
|
||||
uint128_struct float_registers[8];
|
||||
uint128_struct xmm_registers[16];
|
||||
uint8_t reserved4[96];
|
||||
} MDXmmSaveArea32AMD64; /* XMM_SAVE_AREA32 */
|
||||
|
||||
#define MD_CONTEXT_AMD64_VR_COUNT 26
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
* Register parameter home addresses.
|
||||
*/
|
||||
uint64_t p1_home;
|
||||
uint64_t p2_home;
|
||||
uint64_t p3_home;
|
||||
uint64_t p4_home;
|
||||
uint64_t p5_home;
|
||||
uint64_t p6_home;
|
||||
|
||||
/* The next field determines the layout of the structure, and which parts
|
||||
* of it are populated */
|
||||
uint32_t context_flags;
|
||||
uint32_t mx_csr;
|
||||
|
||||
/* The next register is included with MD_CONTEXT_AMD64_CONTROL */
|
||||
uint16_t cs;
|
||||
|
||||
/* The next 4 registers are included with MD_CONTEXT_AMD64_SEGMENTS */
|
||||
uint16_t ds;
|
||||
uint16_t es;
|
||||
uint16_t fs;
|
||||
uint16_t gs;
|
||||
|
||||
/* The next 2 registers are included with MD_CONTEXT_AMD64_CONTROL */
|
||||
uint16_t ss;
|
||||
uint32_t eflags;
|
||||
|
||||
/* The next 6 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */
|
||||
uint64_t dr0;
|
||||
uint64_t dr1;
|
||||
uint64_t dr2;
|
||||
uint64_t dr3;
|
||||
uint64_t dr6;
|
||||
uint64_t dr7;
|
||||
|
||||
/* The next 4 registers are included with MD_CONTEXT_AMD64_INTEGER */
|
||||
uint64_t rax;
|
||||
uint64_t rcx;
|
||||
uint64_t rdx;
|
||||
uint64_t rbx;
|
||||
|
||||
/* The next register is included with MD_CONTEXT_AMD64_CONTROL */
|
||||
uint64_t rsp;
|
||||
|
||||
/* The next 11 registers are included with MD_CONTEXT_AMD64_INTEGER */
|
||||
uint64_t rbp;
|
||||
uint64_t rsi;
|
||||
uint64_t rdi;
|
||||
uint64_t r8;
|
||||
uint64_t r9;
|
||||
uint64_t r10;
|
||||
uint64_t r11;
|
||||
uint64_t r12;
|
||||
uint64_t r13;
|
||||
uint64_t r14;
|
||||
uint64_t r15;
|
||||
|
||||
/* The next register is included with MD_CONTEXT_AMD64_CONTROL */
|
||||
uint64_t rip;
|
||||
|
||||
/* The next set of registers are included with
|
||||
* MD_CONTEXT_AMD64_FLOATING_POINT
|
||||
*/
|
||||
union {
|
||||
MDXmmSaveArea32AMD64 flt_save;
|
||||
struct {
|
||||
uint128_struct header[2];
|
||||
uint128_struct legacy[8];
|
||||
uint128_struct xmm0;
|
||||
uint128_struct xmm1;
|
||||
uint128_struct xmm2;
|
||||
uint128_struct xmm3;
|
||||
uint128_struct xmm4;
|
||||
uint128_struct xmm5;
|
||||
uint128_struct xmm6;
|
||||
uint128_struct xmm7;
|
||||
uint128_struct xmm8;
|
||||
uint128_struct xmm9;
|
||||
uint128_struct xmm10;
|
||||
uint128_struct xmm11;
|
||||
uint128_struct xmm12;
|
||||
uint128_struct xmm13;
|
||||
uint128_struct xmm14;
|
||||
uint128_struct xmm15;
|
||||
} sse_registers;
|
||||
};
|
||||
|
||||
uint128_struct vector_register[MD_CONTEXT_AMD64_VR_COUNT];
|
||||
uint64_t vector_control;
|
||||
|
||||
/* The next 5 registers are included with MD_CONTEXT_AMD64_DEBUG_REGISTERS */
|
||||
uint64_t debug_control;
|
||||
uint64_t last_branch_to_rip;
|
||||
uint64_t last_branch_from_rip;
|
||||
uint64_t last_exception_to_rip;
|
||||
uint64_t last_exception_from_rip;
|
||||
|
||||
} MDRawContextAMD64; /* CONTEXT */
|
||||
|
||||
/* For (MDRawContextAMD64).context_flags. These values indicate the type of
|
||||
* context stored in the structure. The high 24 bits identify the CPU, the
|
||||
* low 8 bits identify the type of context saved. */
|
||||
#define MD_CONTEXT_AMD64 0x00100000 /* CONTEXT_AMD64 */
|
||||
#define MD_CONTEXT_AMD64_CONTROL (MD_CONTEXT_AMD64 | 0x00000001)
|
||||
/* CONTEXT_CONTROL */
|
||||
#define MD_CONTEXT_AMD64_INTEGER (MD_CONTEXT_AMD64 | 0x00000002)
|
||||
/* CONTEXT_INTEGER */
|
||||
#define MD_CONTEXT_AMD64_SEGMENTS (MD_CONTEXT_AMD64 | 0x00000004)
|
||||
/* CONTEXT_SEGMENTS */
|
||||
#define MD_CONTEXT_AMD64_FLOATING_POINT (MD_CONTEXT_AMD64 | 0x00000008)
|
||||
/* CONTEXT_FLOATING_POINT */
|
||||
#define MD_CONTEXT_AMD64_DEBUG_REGISTERS (MD_CONTEXT_AMD64 | 0x00000010)
|
||||
/* CONTEXT_DEBUG_REGISTERS */
|
||||
#define MD_CONTEXT_AMD64_XSTATE (MD_CONTEXT_AMD64 | 0x00000040)
|
||||
/* CONTEXT_XSTATE */
|
||||
|
||||
/* WinNT.h refers to CONTEXT_MMX_REGISTERS but doesn't appear to define it
|
||||
* I think it really means CONTEXT_FLOATING_POINT.
|
||||
*/
|
||||
|
||||
#define MD_CONTEXT_AMD64_FULL (MD_CONTEXT_AMD64_CONTROL | \
|
||||
MD_CONTEXT_AMD64_INTEGER | \
|
||||
MD_CONTEXT_AMD64_FLOATING_POINT)
|
||||
/* CONTEXT_FULL */
|
||||
|
||||
#define MD_CONTEXT_AMD64_ALL (MD_CONTEXT_AMD64_FULL | \
|
||||
MD_CONTEXT_AMD64_SEGMENTS | \
|
||||
MD_CONTEXT_X86_DEBUG_REGISTERS)
|
||||
/* CONTEXT_ALL */
|
||||
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_AMD64_H__ */
|
|
@ -1,151 +0,0 @@
|
|||
/* Copyright (c) 2009, 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. */
|
||||
|
||||
/* minidump_format.h: A cross-platform reimplementation of minidump-related
|
||||
* portions of DbgHelp.h from the Windows Platform SDK.
|
||||
*
|
||||
* (This is C99 source, please don't corrupt it with C++.)
|
||||
*
|
||||
* This file contains the necessary definitions to read minidump files
|
||||
* produced on ARM. These files may be read on any platform provided
|
||||
* that the alignments of these structures on the processing system are
|
||||
* identical to the alignments of these structures on the producing system.
|
||||
* For this reason, precise-sized types are used. The structures defined
|
||||
* by this file have been laid out to minimize alignment problems by
|
||||
* ensuring that all members are aligned on their natural boundaries.
|
||||
* In some cases, tail-padding may be significant when different ABIs specify
|
||||
* different tail-padding behaviors. To avoid problems when reading or
|
||||
* writing affected structures, MD_*_SIZE macros are provided where needed,
|
||||
* containing the useful size of the structures without padding.
|
||||
*
|
||||
* Structures that are defined by Microsoft to contain a zero-length array
|
||||
* are instead defined here to contain an array with one element, as
|
||||
* zero-length arrays are forbidden by standard C and C++. In these cases,
|
||||
* *_minsize constants are provided to be used in place of sizeof. For a
|
||||
* cleaner interface to these sizes when using C++, see minidump_size.h.
|
||||
*
|
||||
* These structures are also sufficient to populate minidump files.
|
||||
*
|
||||
* Because precise data type sizes are crucial for this implementation to
|
||||
* function properly and portably, a set of primitive types with known sizes
|
||||
* are used as the basis of each structure defined by this file.
|
||||
*
|
||||
* Author: Julian Seward
|
||||
*/
|
||||
|
||||
/*
|
||||
* ARM support
|
||||
*/
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__
|
||||
|
||||
#define MD_FLOATINGSAVEAREA_ARM_FPR_COUNT 32
|
||||
#define MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT 8
|
||||
|
||||
/*
|
||||
* Note that these structures *do not* map directly to the CONTEXT
|
||||
* structure defined in WinNT.h in the Windows Mobile SDK. That structure
|
||||
* does not accomodate VFPv3, and I'm unsure if it was ever used in the
|
||||
* wild anyway, as Windows CE only seems to produce "cedumps" which
|
||||
* are not exactly minidumps.
|
||||
*/
|
||||
typedef struct {
|
||||
uint64_t fpscr; /* FPU status register */
|
||||
|
||||
/* 32 64-bit floating point registers, d0 .. d31. */
|
||||
uint64_t regs[MD_FLOATINGSAVEAREA_ARM_FPR_COUNT];
|
||||
|
||||
/* Miscellaneous control words */
|
||||
uint32_t extra[MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT];
|
||||
} MDFloatingSaveAreaARM;
|
||||
|
||||
#define MD_CONTEXT_ARM_GPR_COUNT 16
|
||||
|
||||
typedef struct {
|
||||
/* The next field determines the layout of the structure, and which parts
|
||||
* of it are populated
|
||||
*/
|
||||
uint32_t context_flags;
|
||||
|
||||
/* 16 32-bit integer registers, r0 .. r15
|
||||
* Note the following fixed uses:
|
||||
* r13 is the stack pointer
|
||||
* r14 is the link register
|
||||
* r15 is the program counter
|
||||
*/
|
||||
uint32_t iregs[MD_CONTEXT_ARM_GPR_COUNT];
|
||||
|
||||
/* CPSR (flags, basically): 32 bits:
|
||||
bit 31 - N (negative)
|
||||
bit 30 - Z (zero)
|
||||
bit 29 - C (carry)
|
||||
bit 28 - V (overflow)
|
||||
bit 27 - Q (saturation flag, sticky)
|
||||
All other fields -- ignore */
|
||||
uint32_t cpsr;
|
||||
|
||||
/* The next field is included with MD_CONTEXT_ARM_FLOATING_POINT */
|
||||
MDFloatingSaveAreaARM float_save;
|
||||
|
||||
} MDRawContextARM;
|
||||
|
||||
/* Indices into iregs for registers with a dedicated or conventional
|
||||
* purpose.
|
||||
*/
|
||||
enum MDARMRegisterNumbers {
|
||||
MD_CONTEXT_ARM_REG_IOS_FP = 7,
|
||||
MD_CONTEXT_ARM_REG_FP = 11,
|
||||
MD_CONTEXT_ARM_REG_SP = 13,
|
||||
MD_CONTEXT_ARM_REG_LR = 14,
|
||||
MD_CONTEXT_ARM_REG_PC = 15
|
||||
};
|
||||
|
||||
/* For (MDRawContextARM).context_flags. These values indicate the type of
|
||||
* context stored in the structure. */
|
||||
/* CONTEXT_ARM from the Windows CE 5.0 SDK. This value isn't correct
|
||||
* because this bit can be used for flags. Presumably this value was
|
||||
* never actually used in minidumps, but only in "CEDumps" which
|
||||
* are a whole parallel minidump file format for Windows CE.
|
||||
* Therefore, Breakpad defines its own value for ARM CPUs.
|
||||
*/
|
||||
#define MD_CONTEXT_ARM_OLD 0x00000040
|
||||
/* This value was chosen to avoid likely conflicts with MD_CONTEXT_*
|
||||
* for other CPUs. */
|
||||
#define MD_CONTEXT_ARM 0x40000000
|
||||
#define MD_CONTEXT_ARM_INTEGER (MD_CONTEXT_ARM | 0x00000002)
|
||||
#define MD_CONTEXT_ARM_FLOATING_POINT (MD_CONTEXT_ARM | 0x00000004)
|
||||
|
||||
#define MD_CONTEXT_ARM_FULL (MD_CONTEXT_ARM_INTEGER | \
|
||||
MD_CONTEXT_ARM_FLOATING_POINT)
|
||||
|
||||
#define MD_CONTEXT_ARM_ALL (MD_CONTEXT_ARM_INTEGER | \
|
||||
MD_CONTEXT_ARM_FLOATING_POINT)
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__ */
|
|
@ -1,140 +0,0 @@
|
|||
/* Copyright 2013 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. */
|
||||
|
||||
/* minidump_format.h: A cross-platform reimplementation of minidump-related
|
||||
* portions of DbgHelp.h from the Windows Platform SDK.
|
||||
*
|
||||
* (This is C99 source, please don't corrupt it with C++.)
|
||||
*
|
||||
* This file contains the necessary definitions to read minidump files
|
||||
* produced on ARM. These files may be read on any platform provided
|
||||
* that the alignments of these structures on the processing system are
|
||||
* identical to the alignments of these structures on the producing system.
|
||||
* For this reason, precise-sized types are used. The structures defined
|
||||
* by this file have been laid out to minimize alignment problems by
|
||||
* ensuring that all members are aligned on their natural boundaries.
|
||||
* In some cases, tail-padding may be significant when different ABIs specify
|
||||
* different tail-padding behaviors. To avoid problems when reading or
|
||||
* writing affected structures, MD_*_SIZE macros are provided where needed,
|
||||
* containing the useful size of the structures without padding.
|
||||
*
|
||||
* Structures that are defined by Microsoft to contain a zero-length array
|
||||
* are instead defined here to contain an array with one element, as
|
||||
* zero-length arrays are forbidden by standard C and C++. In these cases,
|
||||
* *_minsize constants are provided to be used in place of sizeof. For a
|
||||
* cleaner interface to these sizes when using C++, see minidump_size.h.
|
||||
*
|
||||
* These structures are also sufficient to populate minidump files.
|
||||
*
|
||||
* Because precise data type sizes are crucial for this implementation to
|
||||
* function properly and portably, a set of primitive types with known sizes
|
||||
* are used as the basis of each structure defined by this file.
|
||||
*
|
||||
* Author: Colin Blundell
|
||||
*/
|
||||
|
||||
/*
|
||||
* ARM64 support
|
||||
*/
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM64_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM64_H__
|
||||
|
||||
#define MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT 32
|
||||
|
||||
typedef struct {
|
||||
uint32_t fpsr; /* FPU status register */
|
||||
uint32_t fpcr; /* FPU control register */
|
||||
|
||||
/* 32 128-bit floating point registers, d0 .. d31. */
|
||||
uint128_struct regs[MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT];
|
||||
} MDFloatingSaveAreaARM64;
|
||||
|
||||
#define MD_CONTEXT_ARM64_GPR_COUNT 33
|
||||
|
||||
/* Use the same 32-bit alignment when accessing this structure from 64-bit code
|
||||
* as is used natively in 32-bit code. */
|
||||
#pragma pack(push, 4)
|
||||
|
||||
typedef struct {
|
||||
/* The next field determines the layout of the structure, and which parts
|
||||
* of it are populated
|
||||
*/
|
||||
uint64_t context_flags;
|
||||
|
||||
/* 33 64-bit integer registers, x0 .. x31 + the PC
|
||||
* Note the following fixed uses:
|
||||
* x29 is the frame pointer
|
||||
* x30 is the link register
|
||||
* x31 is the stack pointer
|
||||
* The PC is effectively x32.
|
||||
*/
|
||||
uint64_t iregs[MD_CONTEXT_ARM64_GPR_COUNT];
|
||||
|
||||
/* CPSR (flags, basically): 32 bits:
|
||||
bit 31 - N (negative)
|
||||
bit 30 - Z (zero)
|
||||
bit 29 - C (carry)
|
||||
bit 28 - V (overflow)
|
||||
bit 27 - Q (saturation flag, sticky)
|
||||
All other fields -- ignore */
|
||||
uint32_t cpsr;
|
||||
|
||||
/* The next field is included with MD_CONTEXT64_ARM_FLOATING_POINT */
|
||||
MDFloatingSaveAreaARM64 float_save;
|
||||
|
||||
} MDRawContextARM64;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* Indices into iregs for registers with a dedicated or conventional
|
||||
* purpose.
|
||||
*/
|
||||
enum MDARM64RegisterNumbers {
|
||||
MD_CONTEXT_ARM64_REG_FP = 29,
|
||||
MD_CONTEXT_ARM64_REG_LR = 30,
|
||||
MD_CONTEXT_ARM64_REG_SP = 31,
|
||||
MD_CONTEXT_ARM64_REG_PC = 32
|
||||
};
|
||||
|
||||
/* For (MDRawContextARM64).context_flags. These values indicate the type of
|
||||
* context stored in the structure. MD_CONTEXT_ARM64 is Breakpad-defined.
|
||||
* This value was chosen to avoid likely conflicts with MD_CONTEXT_*
|
||||
* for other CPUs. */
|
||||
#define MD_CONTEXT_ARM64 0x80000000
|
||||
#define MD_CONTEXT_ARM64_INTEGER (MD_CONTEXT_ARM64 | 0x00000002)
|
||||
#define MD_CONTEXT_ARM64_FLOATING_POINT (MD_CONTEXT_ARM64 | 0x00000004)
|
||||
|
||||
#define MD_CONTEXT_ARM64_FULL (MD_CONTEXT_ARM64_INTEGER | \
|
||||
MD_CONTEXT_ARM64_FLOATING_POINT)
|
||||
|
||||
#define MD_CONTEXT_ARM64_ALL (MD_CONTEXT_ARM64_INTEGER | \
|
||||
MD_CONTEXT_ARM64_FLOATING_POINT)
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM64_H__ */
|
|
@ -1,160 +0,0 @@
|
|||
/* Copyright (c) 2013, 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. */
|
||||
|
||||
/* minidump_format.h: A cross-platform reimplementation of minidump-related
|
||||
* portions of DbgHelp.h from the Windows Platform SDK.
|
||||
*
|
||||
* (This is C99 source, please don't corrupt it with C++.)
|
||||
*
|
||||
* This file contains the necessary definitions to read minidump files
|
||||
* produced on MIPS. These files may be read on any platform provided
|
||||
* that the alignments of these structures on the processing system are
|
||||
* identical to the alignments of these structures on the producing system.
|
||||
* For this reason, precise-sized types are used. The structures defined
|
||||
* by this file have been laid out to minimize alignment problems by
|
||||
* ensuring that all members are aligned on their natural boundaries.
|
||||
* In some cases, tail-padding may be significant when different ABIs specify
|
||||
* different tail-padding behaviors. To avoid problems when reading or
|
||||
* writing affected structures, MD_*_SIZE macros are provided where needed,
|
||||
* containing the useful size of the structures without padding.
|
||||
*
|
||||
* Structures that are defined by Microsoft to contain a zero-length array
|
||||
* are instead defined here to contain an array with one element, as
|
||||
* zero-length arrays are forbidden by standard C and C++. In these cases,
|
||||
* *_minsize constants are provided to be used in place of sizeof. For a
|
||||
* cleaner interface to these sizes when using C++, see minidump_size.h.
|
||||
*
|
||||
* These structures are also sufficient to populate minidump files.
|
||||
*
|
||||
* Because precise data type sizes are crucial for this implementation to
|
||||
* function properly and portably, a set of primitive types with known sizes
|
||||
* are used as the basis of each structure defined by this file.
|
||||
*
|
||||
* Author: Chris Dearman
|
||||
*/
|
||||
|
||||
/*
|
||||
* MIPS support
|
||||
*/
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_MIPS_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_MIPS_H__
|
||||
|
||||
#define MD_CONTEXT_MIPS_GPR_COUNT 32
|
||||
#define MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT 32
|
||||
#define MD_CONTEXT_MIPS_DSP_COUNT 3
|
||||
|
||||
/*
|
||||
* Note that these structures *do not* map directly to the CONTEXT
|
||||
* structure defined in WinNT.h in the Windows Mobile SDK. That structure
|
||||
* does not accomodate VFPv3, and I'm unsure if it was ever used in the
|
||||
* wild anyway, as Windows CE only seems to produce "cedumps" which
|
||||
* are not exactly minidumps.
|
||||
*/
|
||||
typedef struct {
|
||||
/* 32 64-bit floating point registers, f0..f31 */
|
||||
uint64_t regs[MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT];
|
||||
|
||||
uint32_t fpcsr; /* FPU status register. */
|
||||
uint32_t fir; /* FPU implementation register. */
|
||||
} MDFloatingSaveAreaMIPS;
|
||||
|
||||
typedef struct {
|
||||
/* The next field determines the layout of the structure, and which parts
|
||||
* of it are populated.
|
||||
*/
|
||||
uint32_t context_flags;
|
||||
uint32_t _pad0;
|
||||
|
||||
/* 32 64-bit integer registers, r0..r31.
|
||||
* Note the following fixed uses:
|
||||
* r29 is the stack pointer.
|
||||
* r31 is the return address.
|
||||
*/
|
||||
uint64_t iregs[MD_CONTEXT_MIPS_GPR_COUNT];
|
||||
|
||||
/* multiply/divide result. */
|
||||
uint64_t mdhi, mdlo;
|
||||
|
||||
/* DSP accumulators. */
|
||||
uint32_t hi[MD_CONTEXT_MIPS_DSP_COUNT];
|
||||
uint32_t lo[MD_CONTEXT_MIPS_DSP_COUNT];
|
||||
uint32_t dsp_control;
|
||||
uint32_t _pad1;
|
||||
|
||||
uint64_t epc;
|
||||
uint64_t badvaddr;
|
||||
uint32_t status;
|
||||
uint32_t cause;
|
||||
|
||||
/* The next field is included with MD_CONTEXT_MIPS_FLOATING_POINT. */
|
||||
MDFloatingSaveAreaMIPS float_save;
|
||||
|
||||
} MDRawContextMIPS;
|
||||
|
||||
/* Indices into iregs for registers with a dedicated or conventional
|
||||
* purpose.
|
||||
*/
|
||||
enum MDMIPSRegisterNumbers {
|
||||
MD_CONTEXT_MIPS_REG_S0 = 16,
|
||||
MD_CONTEXT_MIPS_REG_S1 = 17,
|
||||
MD_CONTEXT_MIPS_REG_S2 = 18,
|
||||
MD_CONTEXT_MIPS_REG_S3 = 19,
|
||||
MD_CONTEXT_MIPS_REG_S4 = 20,
|
||||
MD_CONTEXT_MIPS_REG_S5 = 21,
|
||||
MD_CONTEXT_MIPS_REG_S6 = 22,
|
||||
MD_CONTEXT_MIPS_REG_S7 = 23,
|
||||
MD_CONTEXT_MIPS_REG_GP = 28,
|
||||
MD_CONTEXT_MIPS_REG_SP = 29,
|
||||
MD_CONTEXT_MIPS_REG_FP = 30,
|
||||
MD_CONTEXT_MIPS_REG_RA = 31,
|
||||
};
|
||||
|
||||
/* For (MDRawContextMIPS).context_flags. These values indicate the type of
|
||||
* context stored in the structure. */
|
||||
/* CONTEXT_MIPS from the Windows CE 5.0 SDK. This value isn't correct
|
||||
* because this bit can be used for flags. Presumably this value was
|
||||
* never actually used in minidumps, but only in "CEDumps" which
|
||||
* are a whole parallel minidump file format for Windows CE.
|
||||
* Therefore, Breakpad defines its own value for MIPS CPUs.
|
||||
*/
|
||||
#define MD_CONTEXT_MIPS 0x00040000
|
||||
#define MD_CONTEXT_MIPS_INTEGER (MD_CONTEXT_MIPS | 0x00000002)
|
||||
#define MD_CONTEXT_MIPS_FLOATING_POINT (MD_CONTEXT_MIPS | 0x00000004)
|
||||
#define MD_CONTEXT_MIPS_DSP (MD_CONTEXT_MIPS | 0x00000008)
|
||||
|
||||
#define MD_CONTEXT_MIPS_FULL (MD_CONTEXT_MIPS_INTEGER | \
|
||||
MD_CONTEXT_MIPS_FLOATING_POINT | \
|
||||
MD_CONTEXT_MIPS_DSP)
|
||||
|
||||
#define MD_CONTEXT_MIPS_ALL (MD_CONTEXT_MIPS_INTEGER | \
|
||||
MD_CONTEXT_MIPS_FLOATING_POINT \
|
||||
MD_CONTEXT_MIPS_DSP)
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_MIPS_H__
|
|
@ -1,168 +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. */
|
||||
|
||||
/* minidump_format.h: A cross-platform reimplementation of minidump-related
|
||||
* portions of DbgHelp.h from the Windows Platform SDK.
|
||||
*
|
||||
* (This is C99 source, please don't corrupt it with C++.)
|
||||
*
|
||||
* This file contains the necessary definitions to read minidump files
|
||||
* produced on ppc. These files may be read on any platform provided
|
||||
* that the alignments of these structures on the processing system are
|
||||
* identical to the alignments of these structures on the producing system.
|
||||
* For this reason, precise-sized types are used. The structures defined
|
||||
* by this file have been laid out to minimize alignment problems by ensuring
|
||||
* ensuring that all members are aligned on their natural boundaries. In
|
||||
* In some cases, tail-padding may be significant when different ABIs specify
|
||||
* different tail-padding behaviors. To avoid problems when reading or
|
||||
* writing affected structures, MD_*_SIZE macros are provided where needed,
|
||||
* containing the useful size of the structures without padding.
|
||||
*
|
||||
* Structures that are defined by Microsoft to contain a zero-length array
|
||||
* are instead defined here to contain an array with one element, as
|
||||
* zero-length arrays are forbidden by standard C and C++. In these cases,
|
||||
* *_minsize constants are provided to be used in place of sizeof. For a
|
||||
* cleaner interface to these sizes when using C++, see minidump_size.h.
|
||||
*
|
||||
* These structures are also sufficient to populate minidump files.
|
||||
*
|
||||
* These definitions may be extended to support handling minidump files
|
||||
* for other CPUs and other operating systems.
|
||||
*
|
||||
* Because precise data type sizes are crucial for this implementation to
|
||||
* function properly and portably in terms of interoperability with minidumps
|
||||
* produced by DbgHelp on Windows, a set of primitive types with known sizes
|
||||
* are used as the basis of each structure defined by this file. DbgHelp
|
||||
* on Windows is assumed to be the reference implementation; this file
|
||||
* seeks to provide a cross-platform compatible implementation. To avoid
|
||||
* collisions with the types and values defined and used by DbgHelp in the
|
||||
* event that this implementation is used on Windows, each type and value
|
||||
* defined here is given a new name, beginning with "MD". Names of the
|
||||
* equivalent types and values in the Windows Platform SDK are given in
|
||||
* comments.
|
||||
*
|
||||
* Author: Mark Mentovai
|
||||
* Change to split into its own file: Neal Sidhwaney */
|
||||
|
||||
/*
|
||||
* Breakpad minidump extension for PowerPC support. Based on Darwin/Mac OS X'
|
||||
* mach/ppc/_types.h
|
||||
*/
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__
|
||||
|
||||
#define MD_FLOATINGSAVEAREA_PPC_FPR_COUNT 32
|
||||
|
||||
typedef struct {
|
||||
/* fpregs is a double[32] in mach/ppc/_types.h, but a uint64_t is used
|
||||
* here for precise sizing. */
|
||||
uint64_t fpregs[MD_FLOATINGSAVEAREA_PPC_FPR_COUNT];
|
||||
uint32_t fpscr_pad;
|
||||
uint32_t fpscr; /* Status/control */
|
||||
} MDFloatingSaveAreaPPC; /* Based on ppc_float_state */
|
||||
|
||||
|
||||
#define MD_VECTORSAVEAREA_PPC_VR_COUNT 32
|
||||
|
||||
typedef struct {
|
||||
/* Vector registers (including vscr) are 128 bits, but mach/ppc/_types.h
|
||||
* exposes them as four 32-bit quantities. */
|
||||
uint128_struct save_vr[MD_VECTORSAVEAREA_PPC_VR_COUNT];
|
||||
uint128_struct save_vscr; /* Status/control */
|
||||
uint32_t save_pad5[4];
|
||||
uint32_t save_vrvalid; /* Indicates which vector registers are saved */
|
||||
uint32_t save_pad6[7];
|
||||
} MDVectorSaveAreaPPC; /* ppc_vector_state */
|
||||
|
||||
|
||||
#define MD_CONTEXT_PPC_GPR_COUNT 32
|
||||
|
||||
/* Use the same 32-bit alignment when accessing this structure from 64-bit code
|
||||
* as is used natively in 32-bit code. #pragma pack is a MSVC extension
|
||||
* supported by gcc. */
|
||||
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
#pragma pack(4)
|
||||
#else
|
||||
#pragma pack(push, 4)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
/* context_flags is not present in ppc_thread_state, but it aids
|
||||
* identification of MDRawContextPPC among other raw context types,
|
||||
* and it guarantees alignment when we get to float_save. */
|
||||
uint32_t context_flags;
|
||||
|
||||
uint32_t srr0; /* Machine status save/restore: stores pc
|
||||
* (instruction) */
|
||||
uint32_t srr1; /* Machine status save/restore: stores msr
|
||||
* (ps, program/machine state) */
|
||||
/* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is
|
||||
* used for brevity. */
|
||||
uint32_t gpr[MD_CONTEXT_PPC_GPR_COUNT];
|
||||
uint32_t cr; /* Condition */
|
||||
uint32_t xer; /* Integer (fiXed-point) exception */
|
||||
uint32_t lr; /* Link */
|
||||
uint32_t ctr; /* Count */
|
||||
uint32_t mq; /* Multiply/Quotient (PPC 601, POWER only) */
|
||||
uint32_t vrsave; /* Vector save */
|
||||
|
||||
/* float_save and vector_save aren't present in ppc_thread_state, but
|
||||
* are represented in separate structures that still define a thread's
|
||||
* context. */
|
||||
MDFloatingSaveAreaPPC float_save;
|
||||
MDVectorSaveAreaPPC vector_save;
|
||||
} MDRawContextPPC; /* Based on ppc_thread_state */
|
||||
|
||||
/* Indices into gpr for registers with a dedicated or conventional purpose. */
|
||||
enum MDPPCRegisterNumbers {
|
||||
MD_CONTEXT_PPC_REG_SP = 1
|
||||
};
|
||||
|
||||
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
#pragma pack(0)
|
||||
#else
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
/* For (MDRawContextPPC).context_flags. These values indicate the type of
|
||||
* context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its
|
||||
* value was chosen to avoid likely conflicts with MD_CONTEXT_* for other
|
||||
* CPUs. */
|
||||
#define MD_CONTEXT_PPC 0x20000000
|
||||
#define MD_CONTEXT_PPC_BASE (MD_CONTEXT_PPC | 0x00000001)
|
||||
#define MD_CONTEXT_PPC_FLOATING_POINT (MD_CONTEXT_PPC | 0x00000008)
|
||||
#define MD_CONTEXT_PPC_VECTOR (MD_CONTEXT_PPC | 0x00000020)
|
||||
|
||||
#define MD_CONTEXT_PPC_FULL MD_CONTEXT_PPC_BASE
|
||||
#define MD_CONTEXT_PPC_ALL (MD_CONTEXT_PPC_FULL | \
|
||||
MD_CONTEXT_PPC_FLOATING_POINT | \
|
||||
MD_CONTEXT_PPC_VECTOR)
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC_H__ */
|
|
@ -1,134 +0,0 @@
|
|||
/* Copyright (c) 2008, 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. */
|
||||
|
||||
/* minidump_format.h: A cross-platform reimplementation of minidump-related
|
||||
* portions of DbgHelp.h from the Windows Platform SDK.
|
||||
*
|
||||
* (This is C99 source, please don't corrupt it with C++.)
|
||||
*
|
||||
* This file contains the necessary definitions to read minidump files
|
||||
* produced on ppc64. These files may be read on any platform provided
|
||||
* that the alignments of these structures on the processing system are
|
||||
* identical to the alignments of these structures on the producing system.
|
||||
* For this reason, precise-sized types are used. The structures defined
|
||||
* by this file have been laid out to minimize alignment problems by ensuring
|
||||
* ensuring that all members are aligned on their natural boundaries. In
|
||||
* In some cases, tail-padding may be significant when different ABIs specify
|
||||
* different tail-padding behaviors. To avoid problems when reading or
|
||||
* writing affected structures, MD_*_SIZE macros are provided where needed,
|
||||
* containing the useful size of the structures without padding.
|
||||
*
|
||||
* Structures that are defined by Microsoft to contain a zero-length array
|
||||
* are instead defined here to contain an array with one element, as
|
||||
* zero-length arrays are forbidden by standard C and C++. In these cases,
|
||||
* *_minsize constants are provided to be used in place of sizeof. For a
|
||||
* cleaner interface to these sizes when using C++, see minidump_size.h.
|
||||
*
|
||||
* These structures are also sufficient to populate minidump files.
|
||||
*
|
||||
* These definitions may be extended to support handling minidump files
|
||||
* for other CPUs and other operating systems.
|
||||
*
|
||||
* Because precise data type sizes are crucial for this implementation to
|
||||
* function properly and portably in terms of interoperability with minidumps
|
||||
* produced by DbgHelp on Windows, a set of primitive types with known sizes
|
||||
* are used as the basis of each structure defined by this file. DbgHelp
|
||||
* on Windows is assumed to be the reference implementation; this file
|
||||
* seeks to provide a cross-platform compatible implementation. To avoid
|
||||
* collisions with the types and values defined and used by DbgHelp in the
|
||||
* event that this implementation is used on Windows, each type and value
|
||||
* defined here is given a new name, beginning with "MD". Names of the
|
||||
* equivalent types and values in the Windows Platform SDK are given in
|
||||
* comments.
|
||||
*
|
||||
* Author: Neal Sidhwaney */
|
||||
|
||||
|
||||
/*
|
||||
* Breakpad minidump extension for PPC64 support. Based on Darwin/Mac OS X'
|
||||
* mach/ppc/_types.h
|
||||
*/
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__
|
||||
|
||||
#include "minidump_cpu_ppc.h"
|
||||
|
||||
// these types are the same in ppc64 & ppc
|
||||
typedef MDFloatingSaveAreaPPC MDFloatingSaveAreaPPC64;
|
||||
typedef MDVectorSaveAreaPPC MDVectorSaveAreaPPC64;
|
||||
|
||||
#define MD_CONTEXT_PPC64_GPR_COUNT MD_CONTEXT_PPC_GPR_COUNT
|
||||
|
||||
typedef struct {
|
||||
/* context_flags is not present in ppc_thread_state, but it aids
|
||||
* identification of MDRawContextPPC among other raw context types,
|
||||
* and it guarantees alignment when we get to float_save. */
|
||||
uint64_t context_flags;
|
||||
|
||||
uint64_t srr0; /* Machine status save/restore: stores pc
|
||||
* (instruction) */
|
||||
uint64_t srr1; /* Machine status save/restore: stores msr
|
||||
* (ps, program/machine state) */
|
||||
/* ppc_thread_state contains 32 fields, r0 .. r31. Here, an array is
|
||||
* used for brevity. */
|
||||
uint64_t gpr[MD_CONTEXT_PPC64_GPR_COUNT];
|
||||
uint64_t cr; /* Condition */
|
||||
uint64_t xer; /* Integer (fiXed-point) exception */
|
||||
uint64_t lr; /* Link */
|
||||
uint64_t ctr; /* Count */
|
||||
uint64_t vrsave; /* Vector save */
|
||||
|
||||
/* float_save and vector_save aren't present in ppc_thread_state, but
|
||||
* are represented in separate structures that still define a thread's
|
||||
* context. */
|
||||
MDFloatingSaveAreaPPC float_save;
|
||||
MDVectorSaveAreaPPC vector_save;
|
||||
} MDRawContextPPC64; /* Based on ppc_thread_state */
|
||||
|
||||
/* Indices into gpr for registers with a dedicated or conventional purpose. */
|
||||
enum MDPPC64RegisterNumbers {
|
||||
MD_CONTEXT_PPC64_REG_SP = 1
|
||||
};
|
||||
|
||||
/* For (MDRawContextPPC).context_flags. These values indicate the type of
|
||||
* context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its
|
||||
* value was chosen to avoid likely conflicts with MD_CONTEXT_* for other
|
||||
* CPUs. */
|
||||
#define MD_CONTEXT_PPC64 0x01000000
|
||||
#define MD_CONTEXT_PPC64_BASE (MD_CONTEXT_PPC64 | 0x00000001)
|
||||
#define MD_CONTEXT_PPC64_FLOATING_POINT (MD_CONTEXT_PPC64 | 0x00000008)
|
||||
#define MD_CONTEXT_PPC64_VECTOR (MD_CONTEXT_PPC64 | 0x00000020)
|
||||
|
||||
#define MD_CONTEXT_PPC64_FULL MD_CONTEXT_PPC64_BASE
|
||||
#define MD_CONTEXT_PPC64_ALL (MD_CONTEXT_PPC64_FULL | \
|
||||
MD_CONTEXT_PPC64_FLOATING_POINT | \
|
||||
MD_CONTEXT_PPC64_VECTOR)
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_PPC64_H__ */
|
|
@ -1,163 +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. */
|
||||
|
||||
/* minidump_format.h: A cross-platform reimplementation of minidump-related
|
||||
* portions of DbgHelp.h from the Windows Platform SDK.
|
||||
*
|
||||
* (This is C99 source, please don't corrupt it with C++.)
|
||||
*
|
||||
* This file contains the necessary definitions to read minidump files
|
||||
* produced on sparc. These files may be read on any platform provided
|
||||
* that the alignments of these structures on the processing system are
|
||||
* identical to the alignments of these structures on the producing system.
|
||||
* For this reason, precise-sized types are used. The structures defined
|
||||
* by this file have been laid out to minimize alignment problems by ensuring
|
||||
* ensuring that all members are aligned on their natural boundaries. In
|
||||
* In some cases, tail-padding may be significant when different ABIs specify
|
||||
* different tail-padding behaviors. To avoid problems when reading or
|
||||
* writing affected structures, MD_*_SIZE macros are provided where needed,
|
||||
* containing the useful size of the structures without padding.
|
||||
*
|
||||
* Structures that are defined by Microsoft to contain a zero-length array
|
||||
* are instead defined here to contain an array with one element, as
|
||||
* zero-length arrays are forbidden by standard C and C++. In these cases,
|
||||
* *_minsize constants are provided to be used in place of sizeof. For a
|
||||
* cleaner interface to these sizes when using C++, see minidump_size.h.
|
||||
*
|
||||
* These structures are also sufficient to populate minidump files.
|
||||
*
|
||||
* These definitions may be extended to support handling minidump files
|
||||
* for other CPUs and other operating systems.
|
||||
*
|
||||
* Because precise data type sizes are crucial for this implementation to
|
||||
* function properly and portably in terms of interoperability with minidumps
|
||||
* produced by DbgHelp on Windows, a set of primitive types with known sizes
|
||||
* are used as the basis of each structure defined by this file. DbgHelp
|
||||
* on Windows is assumed to be the reference implementation; this file
|
||||
* seeks to provide a cross-platform compatible implementation. To avoid
|
||||
* collisions with the types and values defined and used by DbgHelp in the
|
||||
* event that this implementation is used on Windows, each type and value
|
||||
* defined here is given a new name, beginning with "MD". Names of the
|
||||
* equivalent types and values in the Windows Platform SDK are given in
|
||||
* comments.
|
||||
*
|
||||
* Author: Mark Mentovai
|
||||
* Change to split into its own file: Neal Sidhwaney */
|
||||
|
||||
/*
|
||||
* SPARC support, see (solaris)sys/procfs_isa.h also
|
||||
*/
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__
|
||||
|
||||
#define MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT 32
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* FPU floating point regs */
|
||||
uint64_t regs[MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT];
|
||||
|
||||
uint64_t filler;
|
||||
uint64_t fsr; /* FPU status register */
|
||||
} MDFloatingSaveAreaSPARC; /* FLOATING_SAVE_AREA */
|
||||
|
||||
#define MD_CONTEXT_SPARC_GPR_COUNT 32
|
||||
|
||||
typedef struct {
|
||||
/* The next field determines the layout of the structure, and which parts
|
||||
* of it are populated
|
||||
*/
|
||||
uint32_t context_flags;
|
||||
uint32_t flag_pad;
|
||||
/*
|
||||
* General register access (SPARC).
|
||||
* Don't confuse definitions here with definitions in <sys/regset.h>.
|
||||
* Registers are 32 bits for ILP32, 64 bits for LP64.
|
||||
* SPARC V7/V8 is for 32bit, SPARC V9 is for 64bit
|
||||
*/
|
||||
|
||||
/* 32 Integer working registers */
|
||||
|
||||
/* g_r[0-7] global registers(g0-g7)
|
||||
* g_r[8-15] out registers(o0-o7)
|
||||
* g_r[16-23] local registers(l0-l7)
|
||||
* g_r[24-31] in registers(i0-i7)
|
||||
*/
|
||||
uint64_t g_r[MD_CONTEXT_SPARC_GPR_COUNT];
|
||||
|
||||
/* several control registers */
|
||||
|
||||
/* Processor State register(PSR) for SPARC V7/V8
|
||||
* Condition Code register (CCR) for SPARC V9
|
||||
*/
|
||||
uint64_t ccr;
|
||||
|
||||
uint64_t pc; /* Program Counter register (PC) */
|
||||
uint64_t npc; /* Next Program Counter register (nPC) */
|
||||
uint64_t y; /* Y register (Y) */
|
||||
|
||||
/* Address Space Identifier register (ASI) for SPARC V9
|
||||
* WIM for SPARC V7/V8
|
||||
*/
|
||||
uint64_t asi;
|
||||
|
||||
/* Floating-Point Registers State register (FPRS) for SPARC V9
|
||||
* TBR for for SPARC V7/V8
|
||||
*/
|
||||
uint64_t fprs;
|
||||
|
||||
/* The next field is included with MD_CONTEXT_SPARC_FLOATING_POINT */
|
||||
MDFloatingSaveAreaSPARC float_save;
|
||||
|
||||
} MDRawContextSPARC; /* CONTEXT_SPARC */
|
||||
|
||||
/* Indices into g_r for registers with a dedicated or conventional purpose. */
|
||||
enum MDSPARCRegisterNumbers {
|
||||
MD_CONTEXT_SPARC_REG_SP = 14
|
||||
};
|
||||
|
||||
/* For (MDRawContextSPARC).context_flags. These values indicate the type of
|
||||
* context stored in the structure. MD_CONTEXT_SPARC is Breakpad-defined. Its
|
||||
* value was chosen to avoid likely conflicts with MD_CONTEXT_* for other
|
||||
* CPUs. */
|
||||
#define MD_CONTEXT_SPARC 0x10000000
|
||||
#define MD_CONTEXT_SPARC_CONTROL (MD_CONTEXT_SPARC | 0x00000001)
|
||||
#define MD_CONTEXT_SPARC_INTEGER (MD_CONTEXT_SPARC | 0x00000002)
|
||||
#define MD_CONTEXT_SAPARC_FLOATING_POINT (MD_CONTEXT_SPARC | 0x00000004)
|
||||
#define MD_CONTEXT_SAPARC_EXTRA (MD_CONTEXT_SPARC | 0x00000008)
|
||||
|
||||
#define MD_CONTEXT_SPARC_FULL (MD_CONTEXT_SPARC_CONTROL | \
|
||||
MD_CONTEXT_SPARC_INTEGER)
|
||||
|
||||
#define MD_CONTEXT_SPARC_ALL (MD_CONTEXT_SPARC_FULL | \
|
||||
MD_CONTEXT_SAPARC_FLOATING_POINT | \
|
||||
MD_CONTEXT_SAPARC_EXTRA)
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_SPARC_H__ */
|
|
@ -1,174 +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. */
|
||||
|
||||
/* minidump_format.h: A cross-platform reimplementation of minidump-related
|
||||
* portions of DbgHelp.h from the Windows Platform SDK.
|
||||
*
|
||||
* (This is C99 source, please don't corrupt it with C++.)
|
||||
*
|
||||
* This file contains the necessary definitions to read minidump files
|
||||
* produced on x86. These files may be read on any platform provided
|
||||
* that the alignments of these structures on the processing system are
|
||||
* identical to the alignments of these structures on the producing system.
|
||||
* For this reason, precise-sized types are used. The structures defined
|
||||
* by this file have been laid out to minimize alignment problems by ensuring
|
||||
* ensuring that all members are aligned on their natural boundaries. In
|
||||
* In some cases, tail-padding may be significant when different ABIs specify
|
||||
* different tail-padding behaviors. To avoid problems when reading or
|
||||
* writing affected structures, MD_*_SIZE macros are provided where needed,
|
||||
* containing the useful size of the structures without padding.
|
||||
*
|
||||
* Structures that are defined by Microsoft to contain a zero-length array
|
||||
* are instead defined here to contain an array with one element, as
|
||||
* zero-length arrays are forbidden by standard C and C++. In these cases,
|
||||
* *_minsize constants are provided to be used in place of sizeof. For a
|
||||
* cleaner interface to these sizes when using C++, see minidump_size.h.
|
||||
*
|
||||
* These structures are also sufficient to populate minidump files.
|
||||
*
|
||||
* These definitions may be extended to support handling minidump files
|
||||
* for other CPUs and other operating systems.
|
||||
*
|
||||
* Because precise data type sizes are crucial for this implementation to
|
||||
* function properly and portably in terms of interoperability with minidumps
|
||||
* produced by DbgHelp on Windows, a set of primitive types with known sizes
|
||||
* are used as the basis of each structure defined by this file. DbgHelp
|
||||
* on Windows is assumed to be the reference implementation; this file
|
||||
* seeks to provide a cross-platform compatible implementation. To avoid
|
||||
* collisions with the types and values defined and used by DbgHelp in the
|
||||
* event that this implementation is used on Windows, each type and value
|
||||
* defined here is given a new name, beginning with "MD". Names of the
|
||||
* equivalent types and values in the Windows Platform SDK are given in
|
||||
* comments.
|
||||
*
|
||||
* Author: Mark Mentovai */
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__
|
||||
|
||||
#define MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE 80
|
||||
/* SIZE_OF_80387_REGISTERS */
|
||||
|
||||
typedef struct {
|
||||
uint32_t control_word;
|
||||
uint32_t status_word;
|
||||
uint32_t tag_word;
|
||||
uint32_t error_offset;
|
||||
uint32_t error_selector;
|
||||
uint32_t data_offset;
|
||||
uint32_t data_selector;
|
||||
|
||||
/* register_area contains eight 80-bit (x87 "long double") quantities for
|
||||
* floating-point registers %st0 (%mm0) through %st7 (%mm7). */
|
||||
uint8_t register_area[MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE];
|
||||
uint32_t cr0_npx_state;
|
||||
} MDFloatingSaveAreaX86; /* FLOATING_SAVE_AREA */
|
||||
|
||||
|
||||
#define MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE 512
|
||||
/* MAXIMUM_SUPPORTED_EXTENSION */
|
||||
|
||||
typedef struct {
|
||||
/* The next field determines the layout of the structure, and which parts
|
||||
* of it are populated */
|
||||
uint32_t context_flags;
|
||||
|
||||
/* The next 6 registers are included with MD_CONTEXT_X86_DEBUG_REGISTERS */
|
||||
uint32_t dr0;
|
||||
uint32_t dr1;
|
||||
uint32_t dr2;
|
||||
uint32_t dr3;
|
||||
uint32_t dr6;
|
||||
uint32_t dr7;
|
||||
|
||||
/* The next field is included with MD_CONTEXT_X86_FLOATING_POINT */
|
||||
MDFloatingSaveAreaX86 float_save;
|
||||
|
||||
/* The next 4 registers are included with MD_CONTEXT_X86_SEGMENTS */
|
||||
uint32_t gs;
|
||||
uint32_t fs;
|
||||
uint32_t es;
|
||||
uint32_t ds;
|
||||
/* The next 6 registers are included with MD_CONTEXT_X86_INTEGER */
|
||||
uint32_t edi;
|
||||
uint32_t esi;
|
||||
uint32_t ebx;
|
||||
uint32_t edx;
|
||||
uint32_t ecx;
|
||||
uint32_t eax;
|
||||
|
||||
/* The next 6 registers are included with MD_CONTEXT_X86_CONTROL */
|
||||
uint32_t ebp;
|
||||
uint32_t eip;
|
||||
uint32_t cs; /* WinNT.h says "must be sanitized" */
|
||||
uint32_t eflags; /* WinNT.h says "must be sanitized" */
|
||||
uint32_t esp;
|
||||
uint32_t ss;
|
||||
|
||||
/* The next field is included with MD_CONTEXT_X86_EXTENDED_REGISTERS.
|
||||
* It contains vector (MMX/SSE) registers. It it laid out in the
|
||||
* format used by the fxsave and fsrstor instructions, so it includes
|
||||
* a copy of the x87 floating-point registers as well. See FXSAVE in
|
||||
* "Intel Architecture Software Developer's Manual, Volume 2." */
|
||||
uint8_t extended_registers[
|
||||
MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE];
|
||||
} MDRawContextX86; /* CONTEXT */
|
||||
|
||||
/* For (MDRawContextX86).context_flags. These values indicate the type of
|
||||
* context stored in the structure. The high 24 bits identify the CPU, the
|
||||
* low 8 bits identify the type of context saved. */
|
||||
#define MD_CONTEXT_X86 0x00010000
|
||||
/* CONTEXT_i386, CONTEXT_i486: identifies CPU */
|
||||
#define MD_CONTEXT_X86_CONTROL (MD_CONTEXT_X86 | 0x00000001)
|
||||
/* CONTEXT_CONTROL */
|
||||
#define MD_CONTEXT_X86_INTEGER (MD_CONTEXT_X86 | 0x00000002)
|
||||
/* CONTEXT_INTEGER */
|
||||
#define MD_CONTEXT_X86_SEGMENTS (MD_CONTEXT_X86 | 0x00000004)
|
||||
/* CONTEXT_SEGMENTS */
|
||||
#define MD_CONTEXT_X86_FLOATING_POINT (MD_CONTEXT_X86 | 0x00000008)
|
||||
/* CONTEXT_FLOATING_POINT */
|
||||
#define MD_CONTEXT_X86_DEBUG_REGISTERS (MD_CONTEXT_X86 | 0x00000010)
|
||||
/* CONTEXT_DEBUG_REGISTERS */
|
||||
#define MD_CONTEXT_X86_EXTENDED_REGISTERS (MD_CONTEXT_X86 | 0x00000020)
|
||||
/* CONTEXT_EXTENDED_REGISTERS */
|
||||
#define MD_CONTEXT_X86_XSTATE (MD_CONTEXT_X86 | 0x00000040)
|
||||
/* CONTEXT_XSTATE */
|
||||
|
||||
#define MD_CONTEXT_X86_FULL (MD_CONTEXT_X86_CONTROL | \
|
||||
MD_CONTEXT_X86_INTEGER | \
|
||||
MD_CONTEXT_X86_SEGMENTS)
|
||||
/* CONTEXT_FULL */
|
||||
|
||||
#define MD_CONTEXT_X86_ALL (MD_CONTEXT_X86_FULL | \
|
||||
MD_CONTEXT_X86_FLOATING_POINT | \
|
||||
MD_CONTEXT_X86_DEBUG_REGISTERS | \
|
||||
MD_CONTEXT_X86_EXTENDED_REGISTERS)
|
||||
/* CONTEXT_ALL */
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_X86_H__ */
|
|
@ -1,87 +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. */
|
||||
|
||||
/* minidump_exception_linux.h: A definition of exception codes for
|
||||
* Linux
|
||||
*
|
||||
* (This is C99 source, please don't corrupt it with C++.)
|
||||
*
|
||||
* Author: Mark Mentovai
|
||||
* Split into its own file: Neal Sidhwaney */
|
||||
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "google_breakpad/common/breakpad_types.h"
|
||||
|
||||
|
||||
/* For (MDException).exception_code. These values come from bits/signum.h.
|
||||
*/
|
||||
typedef enum {
|
||||
MD_EXCEPTION_CODE_LIN_SIGHUP = 1, /* Hangup (POSIX) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGINT = 2, /* Interrupt (ANSI) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGQUIT = 3, /* Quit (POSIX) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGILL = 4, /* Illegal instruction (ANSI) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGTRAP = 5, /* Trace trap (POSIX) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGABRT = 6, /* Abort (ANSI) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGBUS = 7, /* BUS error (4.2 BSD) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGFPE = 8, /* Floating-point exception (ANSI) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGKILL = 9, /* Kill, unblockable (POSIX) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGUSR1 = 10, /* User-defined signal 1 (POSIX). */
|
||||
MD_EXCEPTION_CODE_LIN_SIGSEGV = 11, /* Segmentation violation (ANSI) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGUSR2 = 12, /* User-defined signal 2 (POSIX) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGPIPE = 13, /* Broken pipe (POSIX) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGALRM = 14, /* Alarm clock (POSIX) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGTERM = 15, /* Termination (ANSI) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGSTKFLT = 16, /* Stack faultd */
|
||||
MD_EXCEPTION_CODE_LIN_SIGCHLD = 17, /* Child status has changed (POSIX) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGCONT = 18, /* Continue (POSIX) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGSTOP = 19, /* Stop, unblockable (POSIX) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGTSTP = 20, /* Keyboard stop (POSIX) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGTTIN = 21, /* Background read from tty (POSIX) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGTTOU = 22, /* Background write to tty (POSIX) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGURG = 23,
|
||||
/* Urgent condition on socket (4.2 BSD) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGXCPU = 24, /* CPU limit exceeded (4.2 BSD) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGXFSZ = 25,
|
||||
/* File size limit exceeded (4.2 BSD) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGVTALRM = 26, /* Virtual alarm clock (4.2 BSD) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGPROF = 27, /* Profiling alarm clock (4.2 BSD) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGWINCH = 28, /* Window size change (4.3 BSD, Sun) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGIO = 29, /* I/O now possible (4.2 BSD) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGPWR = 30, /* Power failure restart (System V) */
|
||||
MD_EXCEPTION_CODE_LIN_SIGSYS = 31, /* Bad system call */
|
||||
MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED = 0xFFFFFFFF /* No exception,
|
||||
dump requested. */
|
||||
} MDExceptionCodeLinux;
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_LINUX_H__ */
|
|
@ -1,205 +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. */
|
||||
|
||||
/* minidump_exception_mac.h: A definition of exception codes for Mac
|
||||
* OS X
|
||||
*
|
||||
* (This is C99 source, please don't corrupt it with C++.)
|
||||
*
|
||||
* Author: Mark Mentovai
|
||||
* Split into its own file: Neal Sidhwaney */
|
||||
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "google_breakpad/common/breakpad_types.h"
|
||||
|
||||
/* For (MDException).exception_code. Breakpad minidump extension for Mac OS X
|
||||
* support. Based on Darwin/Mac OS X' mach/exception_types.h. This is
|
||||
* what Mac OS X calls an "exception", not a "code". */
|
||||
typedef enum {
|
||||
/* Exception code. The high 16 bits of exception_code contains one of
|
||||
* these values. */
|
||||
MD_EXCEPTION_MAC_BAD_ACCESS = 1, /* code can be a kern_return_t */
|
||||
/* EXC_BAD_ACCESS */
|
||||
MD_EXCEPTION_MAC_BAD_INSTRUCTION = 2, /* code is CPU-specific */
|
||||
/* EXC_BAD_INSTRUCTION */
|
||||
MD_EXCEPTION_MAC_ARITHMETIC = 3, /* code is CPU-specific */
|
||||
/* EXC_ARITHMETIC */
|
||||
MD_EXCEPTION_MAC_EMULATION = 4, /* code is CPU-specific */
|
||||
/* EXC_EMULATION */
|
||||
MD_EXCEPTION_MAC_SOFTWARE = 5,
|
||||
/* EXC_SOFTWARE */
|
||||
MD_EXCEPTION_MAC_BREAKPOINT = 6, /* code is CPU-specific */
|
||||
/* EXC_BREAKPOINT */
|
||||
MD_EXCEPTION_MAC_SYSCALL = 7,
|
||||
/* EXC_SYSCALL */
|
||||
MD_EXCEPTION_MAC_MACH_SYSCALL = 8,
|
||||
/* EXC_MACH_SYSCALL */
|
||||
MD_EXCEPTION_MAC_RPC_ALERT = 9
|
||||
/* EXC_RPC_ALERT */
|
||||
} MDExceptionMac;
|
||||
|
||||
/* For (MDException).exception_flags. Breakpad minidump extension for Mac OS X
|
||||
* support. Based on Darwin/Mac OS X' mach/ppc/exception.h and
|
||||
* mach/i386/exception.h. This is what Mac OS X calls a "code". */
|
||||
typedef enum {
|
||||
/* With MD_EXCEPTION_BAD_ACCESS. These are relevant kern_return_t values
|
||||
* from mach/kern_return.h. */
|
||||
MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS = 1,
|
||||
/* KERN_INVALID_ADDRESS */
|
||||
MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE = 2,
|
||||
/* KERN_PROTECTION_FAILURE */
|
||||
MD_EXCEPTION_CODE_MAC_NO_ACCESS = 8,
|
||||
/* KERN_NO_ACCESS */
|
||||
MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE = 9,
|
||||
/* KERN_MEMORY_FAILURE */
|
||||
MD_EXCEPTION_CODE_MAC_MEMORY_ERROR = 10,
|
||||
/* KERN_MEMORY_ERROR */
|
||||
|
||||
/* With MD_EXCEPTION_SOFTWARE */
|
||||
MD_EXCEPTION_CODE_MAC_BAD_SYSCALL = 0x00010000, /* Mach SIGSYS */
|
||||
MD_EXCEPTION_CODE_MAC_BAD_PIPE = 0x00010001, /* Mach SIGPIPE */
|
||||
MD_EXCEPTION_CODE_MAC_ABORT = 0x00010002, /* Mach SIGABRT */
|
||||
/* Custom values */
|
||||
MD_EXCEPTION_CODE_MAC_NS_EXCEPTION = 0xDEADC0DE, /* uncaught NSException */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_BAD_ACCESS on arm */
|
||||
MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN = 0x0101, /* EXC_ARM_DA_ALIGN */
|
||||
MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG = 0x0102, /* EXC_ARM_DA_DEBUG */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on arm */
|
||||
MD_EXCEPTION_CODE_MAC_ARM_UNDEFINED = 1, /* EXC_ARM_UNDEFINED */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_BREAKPOINT on arm */
|
||||
MD_EXCEPTION_CODE_MAC_ARM_BREAKPOINT = 1, /* EXC_ARM_BREAKPOINT */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_BAD_ACCESS on ppc */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ = 0x0101,
|
||||
/* EXC_PPC_VM_PROT_READ */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_BADSPACE = 0x0102,
|
||||
/* EXC_PPC_BADSPACE */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED = 0x0103,
|
||||
/* EXC_PPC_UNALIGNED */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on ppc */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL = 1,
|
||||
/* EXC_PPC_INVALID_SYSCALL */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION = 2,
|
||||
/* EXC_PPC_UNIPL_INST */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION = 3,
|
||||
/* EXC_PPC_PRIVINST */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER = 4,
|
||||
/* EXC_PPC_PRIVREG */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_TRACE = 5,
|
||||
/* EXC_PPC_TRACE */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR = 6,
|
||||
/* EXC_PPC_PERFMON */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_ARITHMETIC on ppc */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW = 1,
|
||||
/* EXC_PPC_OVERFLOW */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE = 2,
|
||||
/* EXC_PPC_ZERO_DIVIDE */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT = 3,
|
||||
/* EXC_FLT_INEXACT */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE = 4,
|
||||
/* EXC_PPC_FLT_ZERO_DIVIDE */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW = 5,
|
||||
/* EXC_PPC_FLT_UNDERFLOW */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW = 6,
|
||||
/* EXC_PPC_FLT_OVERFLOW */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER = 7,
|
||||
/* EXC_PPC_FLT_NOT_A_NUMBER */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_EMULATION on ppc */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION = 8,
|
||||
/* EXC_PPC_NOEMULATION */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST = 9,
|
||||
/* EXC_PPC_ALTIVECASSIST */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_SOFTWARE on ppc */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_TRAP = 0x00000001, /* EXC_PPC_TRAP */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_MIGRATE = 0x00010100, /* EXC_PPC_MIGRATE */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_BREAKPOINT on ppc */
|
||||
MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT = 1, /* EXC_PPC_BREAKPOINT */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on x86, see also x86 interrupt
|
||||
* values below. */
|
||||
MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION = 1, /* EXC_I386_INVOP */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_ARITHMETIC on x86 */
|
||||
MD_EXCEPTION_CODE_MAC_X86_DIV = 1, /* EXC_I386_DIV */
|
||||
MD_EXCEPTION_CODE_MAC_X86_INTO = 2, /* EXC_I386_INTO */
|
||||
MD_EXCEPTION_CODE_MAC_X86_NOEXT = 3, /* EXC_I386_NOEXT */
|
||||
MD_EXCEPTION_CODE_MAC_X86_EXTOVR = 4, /* EXC_I386_EXTOVR */
|
||||
MD_EXCEPTION_CODE_MAC_X86_EXTERR = 5, /* EXC_I386_EXTERR */
|
||||
MD_EXCEPTION_CODE_MAC_X86_EMERR = 6, /* EXC_I386_EMERR */
|
||||
MD_EXCEPTION_CODE_MAC_X86_BOUND = 7, /* EXC_I386_BOUND */
|
||||
MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR = 8, /* EXC_I386_SSEEXTERR */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_BREAKPOINT on x86 */
|
||||
MD_EXCEPTION_CODE_MAC_X86_SGL = 1, /* EXC_I386_SGL */
|
||||
MD_EXCEPTION_CODE_MAC_X86_BPT = 2, /* EXC_I386_BPT */
|
||||
|
||||
/* With MD_EXCEPTION_MAC_BAD_INSTRUCTION on x86. These are the raw
|
||||
* x86 interrupt codes. Most of these are mapped to other Mach
|
||||
* exceptions and codes, are handled, or should not occur in user space.
|
||||
* A few of these will do occur with MD_EXCEPTION_MAC_BAD_INSTRUCTION. */
|
||||
/* EXC_I386_DIVERR = 0: mapped to EXC_ARITHMETIC/EXC_I386_DIV */
|
||||
/* EXC_I386_SGLSTP = 1: mapped to EXC_BREAKPOINT/EXC_I386_SGL */
|
||||
/* EXC_I386_NMIFLT = 2: should not occur in user space */
|
||||
/* EXC_I386_BPTFLT = 3: mapped to EXC_BREAKPOINT/EXC_I386_BPT */
|
||||
/* EXC_I386_INTOFLT = 4: mapped to EXC_ARITHMETIC/EXC_I386_INTO */
|
||||
/* EXC_I386_BOUNDFLT = 5: mapped to EXC_ARITHMETIC/EXC_I386_BOUND */
|
||||
/* EXC_I386_INVOPFLT = 6: mapped to EXC_BAD_INSTRUCTION/EXC_I386_INVOP */
|
||||
/* EXC_I386_NOEXTFLT = 7: should be handled by the kernel */
|
||||
/* EXC_I386_DBLFLT = 8: should be handled (if possible) by the kernel */
|
||||
/* EXC_I386_EXTOVRFLT = 9: mapped to EXC_BAD_ACCESS/(PROT_READ|PROT_EXEC) */
|
||||
MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT = 10,
|
||||
/* EXC_INVTSSFLT */
|
||||
MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT = 11,
|
||||
/* EXC_SEGNPFLT */
|
||||
MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT = 12,
|
||||
/* EXC_STKFLT */
|
||||
MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT = 13,
|
||||
/* EXC_GPFLT */
|
||||
/* EXC_I386_PGFLT = 14: should not occur in user space */
|
||||
/* EXC_I386_EXTERRFLT = 16: mapped to EXC_ARITHMETIC/EXC_I386_EXTERR */
|
||||
MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT = 17
|
||||
/* EXC_ALIGNFLT (for vector operations) */
|
||||
/* EXC_I386_ENOEXTFLT = 32: should be handled by the kernel */
|
||||
/* EXC_I386_ENDPERR = 33: should not occur */
|
||||
} MDExceptionCodeMac;
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_MAC_OSX_H__ */
|
|
@ -1,67 +0,0 @@
|
|||
/* Copyright (c) 2013, 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. */
|
||||
|
||||
/* minidump_exception_ps3.h: A definition of exception codes for
|
||||
* PS3 */
|
||||
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_PS3_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_PS3_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "google_breakpad/common/breakpad_types.h"
|
||||
|
||||
typedef enum {
|
||||
MD_EXCEPTION_CODE_PS3_UNKNOWN = 0,
|
||||
MD_EXCEPTION_CODE_PS3_TRAP_EXCEP = 1,
|
||||
MD_EXCEPTION_CODE_PS3_PRIV_INSTR = 2,
|
||||
MD_EXCEPTION_CODE_PS3_ILLEGAL_INSTR = 3,
|
||||
MD_EXCEPTION_CODE_PS3_INSTR_STORAGE = 4,
|
||||
MD_EXCEPTION_CODE_PS3_INSTR_SEGMENT = 5,
|
||||
MD_EXCEPTION_CODE_PS3_DATA_STORAGE = 6,
|
||||
MD_EXCEPTION_CODE_PS3_DATA_SEGMENT = 7,
|
||||
MD_EXCEPTION_CODE_PS3_FLOAT_POINT = 8,
|
||||
MD_EXCEPTION_CODE_PS3_DABR_MATCH = 9,
|
||||
MD_EXCEPTION_CODE_PS3_ALIGN_EXCEP = 10,
|
||||
MD_EXCEPTION_CODE_PS3_MEMORY_ACCESS = 11,
|
||||
MD_EXCEPTION_CODE_PS3_COPRO_ALIGN = 12,
|
||||
MD_EXCEPTION_CODE_PS3_COPRO_INVALID_COM = 13,
|
||||
MD_EXCEPTION_CODE_PS3_COPRO_ERR = 14,
|
||||
MD_EXCEPTION_CODE_PS3_COPRO_FIR = 15,
|
||||
MD_EXCEPTION_CODE_PS3_COPRO_DATA_SEGMENT = 16,
|
||||
MD_EXCEPTION_CODE_PS3_COPRO_DATA_STORAGE = 17,
|
||||
MD_EXCEPTION_CODE_PS3_COPRO_STOP_INSTR = 18,
|
||||
MD_EXCEPTION_CODE_PS3_COPRO_HALT_INSTR = 19,
|
||||
MD_EXCEPTION_CODE_PS3_COPRO_HALTINST_UNKNOWN = 20,
|
||||
MD_EXCEPTION_CODE_PS3_COPRO_MEMORY_ACCESS = 21,
|
||||
MD_EXCEPTION_CODE_PS3_GRAPHIC = 22
|
||||
} MDExceptionCodePS3;
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_PS3_H__ */
|
|
@ -1,94 +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. */
|
||||
|
||||
/* minidump_exception_solaris.h: A definition of exception codes for
|
||||
* Solaris
|
||||
*
|
||||
* (This is C99 source, please don't corrupt it with C++.)
|
||||
*
|
||||
* Author: Mark Mentovai
|
||||
* Split into its own file: Neal Sidhwaney */
|
||||
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "google_breakpad/common/breakpad_types.h"
|
||||
|
||||
/* For (MDException).exception_code. These values come from sys/iso/signal_iso.h
|
||||
*/
|
||||
typedef enum {
|
||||
MD_EXCEPTION_CODE_SOL_SIGHUP = 1, /* Hangup */
|
||||
MD_EXCEPTION_CODE_SOL_SIGINT = 2, /* interrupt (rubout) */
|
||||
MD_EXCEPTION_CODE_SOL_SIGQUIT = 3, /* quit (ASCII FS) */
|
||||
MD_EXCEPTION_CODE_SOL_SIGILL = 4, /* illegal instruction (not reset when caught) */
|
||||
MD_EXCEPTION_CODE_SOL_SIGTRAP = 5, /* trace trap (not reset when caught) */
|
||||
MD_EXCEPTION_CODE_SOL_SIGIOT = 6, /* IOT instruction */
|
||||
MD_EXCEPTION_CODE_SOL_SIGABRT = 6, /* used by abort, replace SIGIOT in the future */
|
||||
MD_EXCEPTION_CODE_SOL_SIGEMT = 7, /* EMT instruction */
|
||||
MD_EXCEPTION_CODE_SOL_SIGFPE = 8, /* floating point exception */
|
||||
MD_EXCEPTION_CODE_SOL_SIGKILL = 9, /* kill (cannot be caught or ignored) */
|
||||
MD_EXCEPTION_CODE_SOL_SIGBUS = 10, /* bus error */
|
||||
MD_EXCEPTION_CODE_SOL_SIGSEGV = 11, /* segmentation violation */
|
||||
MD_EXCEPTION_CODE_SOL_SIGSYS = 12, /* bad argument to system call */
|
||||
MD_EXCEPTION_CODE_SOL_SIGPIPE = 13, /* write on a pipe with no one to read it */
|
||||
MD_EXCEPTION_CODE_SOL_SIGALRM = 14, /* alarm clock */
|
||||
MD_EXCEPTION_CODE_SOL_SIGTERM = 15, /* software termination signal from kill */
|
||||
MD_EXCEPTION_CODE_SOL_SIGUSR1 = 16, /* user defined signal 1 */
|
||||
MD_EXCEPTION_CODE_SOL_SIGUSR2 = 17, /* user defined signal 2 */
|
||||
MD_EXCEPTION_CODE_SOL_SIGCLD = 18, /* child status change */
|
||||
MD_EXCEPTION_CODE_SOL_SIGCHLD = 18, /* child status change alias (POSIX) */
|
||||
MD_EXCEPTION_CODE_SOL_SIGPWR = 19, /* power-fail restart */
|
||||
MD_EXCEPTION_CODE_SOL_SIGWINCH = 20, /* window size change */
|
||||
MD_EXCEPTION_CODE_SOL_SIGURG = 21, /* urgent socket condition */
|
||||
MD_EXCEPTION_CODE_SOL_SIGPOLL = 22, /* pollable event occurred */
|
||||
MD_EXCEPTION_CODE_SOL_SIGIO = 22, /* socket I/O possible (SIGPOLL alias) */
|
||||
MD_EXCEPTION_CODE_SOL_SIGSTOP = 23, /* stop (cannot be caught or ignored) */
|
||||
MD_EXCEPTION_CODE_SOL_SIGTSTP = 24, /* user stop requested from tty */
|
||||
MD_EXCEPTION_CODE_SOL_SIGCONT = 25, /* stopped process has been continued */
|
||||
MD_EXCEPTION_CODE_SOL_SIGTTIN = 26, /* background tty read attempted */
|
||||
MD_EXCEPTION_CODE_SOL_SIGTTOU = 27, /* background tty write attempted */
|
||||
MD_EXCEPTION_CODE_SOL_SIGVTALRM = 28, /* virtual timer expired */
|
||||
MD_EXCEPTION_CODE_SOL_SIGPROF = 29, /* profiling timer expired */
|
||||
MD_EXCEPTION_CODE_SOL_SIGXCPU = 30, /* exceeded cpu limit */
|
||||
MD_EXCEPTION_CODE_SOL_SIGXFSZ = 31, /* exceeded file size limit */
|
||||
MD_EXCEPTION_CODE_SOL_SIGWAITING = 32, /* reserved signal no longer used by threading code */
|
||||
MD_EXCEPTION_CODE_SOL_SIGLWP = 33, /* reserved signal no longer used by threading code */
|
||||
MD_EXCEPTION_CODE_SOL_SIGFREEZE = 34, /* special signal used by CPR */
|
||||
MD_EXCEPTION_CODE_SOL_SIGTHAW = 35, /* special signal used by CPR */
|
||||
MD_EXCEPTION_CODE_SOL_SIGCANCEL = 36, /* reserved signal for thread cancellation */
|
||||
MD_EXCEPTION_CODE_SOL_SIGLOST = 37, /* resource lost (eg, record-lock lost) */
|
||||
MD_EXCEPTION_CODE_SOL_SIGXRES = 38, /* resource control exceeded */
|
||||
MD_EXCEPTION_CODE_SOL_SIGJVM1 = 39, /* reserved signal for Java Virtual Machine */
|
||||
MD_EXCEPTION_CODE_SOL_SIGJVM2 = 40 /* reserved signal for Java Virtual Machine */
|
||||
} MDExceptionCodeSolaris;
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_SOLARIS_H__ */
|
File diff suppressed because it is too large
Load diff
|
@ -1,972 +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. */
|
||||
|
||||
/* minidump_format.h: A cross-platform reimplementation of minidump-related
|
||||
* portions of DbgHelp.h from the Windows Platform SDK.
|
||||
*
|
||||
* (This is C99 source, please don't corrupt it with C++.)
|
||||
*
|
||||
* Structures that are defined by Microsoft to contain a zero-length array
|
||||
* are instead defined here to contain an array with one element, as
|
||||
* zero-length arrays are forbidden by standard C and C++. In these cases,
|
||||
* *_minsize constants are provided to be used in place of sizeof. For a
|
||||
* cleaner interface to these sizes when using C++, see minidump_size.h.
|
||||
*
|
||||
* These structures are also sufficient to populate minidump files.
|
||||
*
|
||||
* These definitions may be extended to support handling minidump files
|
||||
* for other CPUs and other operating systems.
|
||||
*
|
||||
* Because precise data type sizes are crucial for this implementation to
|
||||
* function properly and portably in terms of interoperability with minidumps
|
||||
* produced by DbgHelp on Windows, a set of primitive types with known sizes
|
||||
* are used as the basis of each structure defined by this file. DbgHelp
|
||||
* on Windows is assumed to be the reference implementation; this file
|
||||
* seeks to provide a cross-platform compatible implementation. To avoid
|
||||
* collisions with the types and values defined and used by DbgHelp in the
|
||||
* event that this implementation is used on Windows, each type and value
|
||||
* defined here is given a new name, beginning with "MD". Names of the
|
||||
* equivalent types and values in the Windows Platform SDK are given in
|
||||
* comments.
|
||||
*
|
||||
* Author: Mark Mentovai */
|
||||
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_FORMAT_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_FORMAT_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "google_breakpad/common/breakpad_types.h"
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/* Disable "zero-sized array in struct/union" warnings when compiling in
|
||||
* MSVC. DbgHelp.h does this too. */
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4200)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
|
||||
/*
|
||||
* guiddef.h
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
uint32_t data1;
|
||||
uint16_t data2;
|
||||
uint16_t data3;
|
||||
uint8_t data4[8];
|
||||
} MDGUID; /* GUID */
|
||||
|
||||
|
||||
/*
|
||||
* WinNT.h
|
||||
*/
|
||||
|
||||
/* Non-x86 CPU identifiers found in the high 24 bits of
|
||||
* (MDRawContext*).context_flags. These aren't used by Breakpad, but are
|
||||
* defined here for reference, to avoid assigning values that conflict
|
||||
* (although some values already conflict). */
|
||||
#define MD_CONTEXT_IA64 0x00080000 /* CONTEXT_IA64 */
|
||||
/* Additional values from winnt.h in the Windows CE 5.0 SDK: */
|
||||
#define MD_CONTEXT_SHX 0x000000c0 /* CONTEXT_SH4 (Super-H, includes SH3) */
|
||||
#define MD_CONTEXT_ALPHA 0x00020000 /* CONTEXT_ALPHA */
|
||||
|
||||
/* As of Windows 7 SP1, the number of flag bits has increased to
|
||||
* include 0x40 (CONTEXT_XSTATE):
|
||||
* http://msdn.microsoft.com/en-us/library/hh134238%28v=vs.85%29.aspx */
|
||||
#define MD_CONTEXT_CPU_MASK 0xffffff00
|
||||
|
||||
|
||||
/* This is a base type for MDRawContextX86 and MDRawContextPPC. This
|
||||
* structure should never be allocated directly. The actual structure type
|
||||
* can be determined by examining the context_flags field. */
|
||||
typedef struct {
|
||||
uint32_t context_flags;
|
||||
} MDRawContextBase;
|
||||
|
||||
#include "minidump_cpu_amd64.h"
|
||||
#include "minidump_cpu_arm.h"
|
||||
#include "minidump_cpu_arm64.h"
|
||||
#include "minidump_cpu_mips.h"
|
||||
#include "minidump_cpu_ppc.h"
|
||||
#include "minidump_cpu_ppc64.h"
|
||||
#include "minidump_cpu_sparc.h"
|
||||
#include "minidump_cpu_x86.h"
|
||||
|
||||
/*
|
||||
* WinVer.h
|
||||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t signature;
|
||||
uint32_t struct_version;
|
||||
uint32_t file_version_hi;
|
||||
uint32_t file_version_lo;
|
||||
uint32_t product_version_hi;
|
||||
uint32_t product_version_lo;
|
||||
uint32_t file_flags_mask; /* Identifies valid bits in fileFlags */
|
||||
uint32_t file_flags;
|
||||
uint32_t file_os;
|
||||
uint32_t file_type;
|
||||
uint32_t file_subtype;
|
||||
uint32_t file_date_hi;
|
||||
uint32_t file_date_lo;
|
||||
} MDVSFixedFileInfo; /* VS_FIXEDFILEINFO */
|
||||
|
||||
/* For (MDVSFixedFileInfo).signature */
|
||||
#define MD_VSFIXEDFILEINFO_SIGNATURE 0xfeef04bd
|
||||
/* VS_FFI_SIGNATURE */
|
||||
|
||||
/* For (MDVSFixedFileInfo).version */
|
||||
#define MD_VSFIXEDFILEINFO_VERSION 0x00010000
|
||||
/* VS_FFI_STRUCVERSION */
|
||||
|
||||
/* For (MDVSFixedFileInfo).file_flags_mask and
|
||||
* (MDVSFixedFileInfo).file_flags */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG 0x00000001
|
||||
/* VS_FF_DEBUG */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_FLAGS_PRERELEASE 0x00000002
|
||||
/* VS_FF_PRERELEASE */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_FLAGS_PATCHED 0x00000004
|
||||
/* VS_FF_PATCHED */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_FLAGS_PRIVATEBUILD 0x00000008
|
||||
/* VS_FF_PRIVATEBUILD */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_FLAGS_INFOINFERRED 0x00000010
|
||||
/* VS_FF_INFOINFERRED */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_FLAGS_SPECIALBUILD 0x00000020
|
||||
/* VS_FF_SPECIALBUILD */
|
||||
|
||||
/* For (MDVSFixedFileInfo).file_os: high 16 bits */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_OS_UNKNOWN 0 /* VOS_UNKNOWN */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_OS_DOS (1 << 16) /* VOS_DOS */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_OS_OS216 (2 << 16) /* VOS_OS216 */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_OS_OS232 (3 << 16) /* VOS_OS232 */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_OS_NT (4 << 16) /* VOS_NT */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_OS_WINCE (5 << 16) /* VOS_WINCE */
|
||||
/* Low 16 bits */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_OS__BASE 0 /* VOS__BASE */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_OS__WINDOWS16 1 /* VOS__WINDOWS16 */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_OS__PM16 2 /* VOS__PM16 */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_OS__PM32 3 /* VOS__PM32 */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_OS__WINDOWS32 4 /* VOS__WINDOWS32 */
|
||||
|
||||
/* For (MDVSFixedFileInfo).file_type */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_TYPE_UNKNOWN 0 /* VFT_UNKNOWN */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_TYPE_APP 1 /* VFT_APP */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_TYPE_DLL 2 /* VFT_DLL */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_TYPE_DRV 3 /* VFT_DLL */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_TYPE_FONT 4 /* VFT_FONT */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_TYPE_VXD 5 /* VFT_VXD */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_TYPE_STATIC_LIB 7 /* VFT_STATIC_LIB */
|
||||
|
||||
/* For (MDVSFixedFileInfo).file_subtype */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_UNKNOWN 0
|
||||
/* VFT2_UNKNOWN */
|
||||
/* with file_type = MD_VSFIXEDFILEINFO_FILETYPE_DRV */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_PRINTER 1
|
||||
/* VFT2_DRV_PRINTER */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_KEYBOARD 2
|
||||
/* VFT2_DRV_KEYBOARD */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_LANGUAGE 3
|
||||
/* VFT2_DRV_LANGUAGE */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_DISPLAY 4
|
||||
/* VFT2_DRV_DISPLAY */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_MOUSE 5
|
||||
/* VFT2_DRV_MOUSE */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_NETWORK 6
|
||||
/* VFT2_DRV_NETWORK */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_SYSTEM 7
|
||||
/* VFT2_DRV_SYSTEM */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_INSTALLABLE 8
|
||||
/* VFT2_DRV_INSTALLABLE */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_SOUND 9
|
||||
/* VFT2_DRV_SOUND */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_COMM 10
|
||||
/* VFT2_DRV_COMM */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_INPUTMETHOD 11
|
||||
/* VFT2_DRV_INPUTMETHOD */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_DRV_VERSIONED_PRINTER 12
|
||||
/* VFT2_DRV_VERSIONED_PRINTER */
|
||||
/* with file_type = MD_VSFIXEDFILEINFO_FILETYPE_FONT */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_FONT_RASTER 1
|
||||
/* VFT2_FONT_RASTER */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_FONT_VECTOR 2
|
||||
/* VFT2_FONT_VECTOR */
|
||||
#define MD_VSFIXEDFILEINFO_FILE_SUBTYPE_FONT_TRUETYPE 3
|
||||
/* VFT2_FONT_TRUETYPE */
|
||||
|
||||
|
||||
/*
|
||||
* DbgHelp.h
|
||||
*/
|
||||
|
||||
|
||||
/* An MDRVA is an offset into the minidump file. The beginning of the
|
||||
* MDRawHeader is at offset 0. */
|
||||
typedef uint32_t MDRVA; /* RVA */
|
||||
|
||||
typedef struct {
|
||||
uint32_t data_size;
|
||||
MDRVA rva;
|
||||
} MDLocationDescriptor; /* MINIDUMP_LOCATION_DESCRIPTOR */
|
||||
|
||||
|
||||
typedef struct {
|
||||
/* The base address of the memory range on the host that produced the
|
||||
* minidump. */
|
||||
uint64_t start_of_memory_range;
|
||||
|
||||
MDLocationDescriptor memory;
|
||||
} MDMemoryDescriptor; /* MINIDUMP_MEMORY_DESCRIPTOR */
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t signature;
|
||||
uint32_t version;
|
||||
uint32_t stream_count;
|
||||
MDRVA stream_directory_rva; /* A |stream_count|-sized array of
|
||||
* MDRawDirectory structures. */
|
||||
uint32_t checksum; /* Can be 0. In fact, that's all that's
|
||||
* been found in minidump files. */
|
||||
uint32_t time_date_stamp; /* time_t */
|
||||
uint64_t flags;
|
||||
} MDRawHeader; /* MINIDUMP_HEADER */
|
||||
|
||||
/* For (MDRawHeader).signature and (MDRawHeader).version. Note that only the
|
||||
* low 16 bits of (MDRawHeader).version are MD_HEADER_VERSION. Per the
|
||||
* documentation, the high 16 bits are implementation-specific. */
|
||||
#define MD_HEADER_SIGNATURE 0x504d444d /* 'PMDM' */
|
||||
/* MINIDUMP_SIGNATURE */
|
||||
#define MD_HEADER_VERSION 0x0000a793 /* 42899 */
|
||||
/* MINIDUMP_VERSION */
|
||||
|
||||
/* For (MDRawHeader).flags: */
|
||||
typedef enum {
|
||||
/* MD_NORMAL is the standard type of minidump. It includes full
|
||||
* streams for the thread list, module list, exception, system info,
|
||||
* and miscellaneous info. A memory list stream is also present,
|
||||
* pointing to the same stack memory contained in the thread list,
|
||||
* as well as a 256-byte region around the instruction address that
|
||||
* was executing when the exception occurred. Stack memory is from
|
||||
* 4 bytes below a thread's stack pointer up to the top of the
|
||||
* memory region encompassing the stack. */
|
||||
MD_NORMAL = 0x00000000,
|
||||
MD_WITH_DATA_SEGS = 0x00000001,
|
||||
MD_WITH_FULL_MEMORY = 0x00000002,
|
||||
MD_WITH_HANDLE_DATA = 0x00000004,
|
||||
MD_FILTER_MEMORY = 0x00000008,
|
||||
MD_SCAN_MEMORY = 0x00000010,
|
||||
MD_WITH_UNLOADED_MODULES = 0x00000020,
|
||||
MD_WITH_INDIRECTLY_REFERENCED_MEMORY = 0x00000040,
|
||||
MD_FILTER_MODULE_PATHS = 0x00000080,
|
||||
MD_WITH_PROCESS_THREAD_DATA = 0x00000100,
|
||||
MD_WITH_PRIVATE_READ_WRITE_MEMORY = 0x00000200,
|
||||
MD_WITHOUT_OPTIONAL_DATA = 0x00000400,
|
||||
MD_WITH_FULL_MEMORY_INFO = 0x00000800,
|
||||
MD_WITH_THREAD_INFO = 0x00001000,
|
||||
MD_WITH_CODE_SEGS = 0x00002000,
|
||||
MD_WITHOUT_AUXILLIARY_SEGS = 0x00004000,
|
||||
MD_WITH_FULL_AUXILLIARY_STATE = 0x00008000,
|
||||
MD_WITH_PRIVATE_WRITE_COPY_MEMORY = 0x00010000,
|
||||
MD_IGNORE_INACCESSIBLE_MEMORY = 0x00020000,
|
||||
MD_WITH_TOKEN_INFORMATION = 0x00040000
|
||||
} MDType; /* MINIDUMP_TYPE */
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t stream_type;
|
||||
MDLocationDescriptor location;
|
||||
} MDRawDirectory; /* MINIDUMP_DIRECTORY */
|
||||
|
||||
/* For (MDRawDirectory).stream_type */
|
||||
typedef enum {
|
||||
MD_UNUSED_STREAM = 0,
|
||||
MD_RESERVED_STREAM_0 = 1,
|
||||
MD_RESERVED_STREAM_1 = 2,
|
||||
MD_THREAD_LIST_STREAM = 3, /* MDRawThreadList */
|
||||
MD_MODULE_LIST_STREAM = 4, /* MDRawModuleList */
|
||||
MD_MEMORY_LIST_STREAM = 5, /* MDRawMemoryList */
|
||||
MD_EXCEPTION_STREAM = 6, /* MDRawExceptionStream */
|
||||
MD_SYSTEM_INFO_STREAM = 7, /* MDRawSystemInfo */
|
||||
MD_THREAD_EX_LIST_STREAM = 8,
|
||||
MD_MEMORY_64_LIST_STREAM = 9,
|
||||
MD_COMMENT_STREAM_A = 10,
|
||||
MD_COMMENT_STREAM_W = 11,
|
||||
MD_HANDLE_DATA_STREAM = 12,
|
||||
MD_FUNCTION_TABLE_STREAM = 13,
|
||||
MD_UNLOADED_MODULE_LIST_STREAM = 14,
|
||||
MD_MISC_INFO_STREAM = 15, /* MDRawMiscInfo */
|
||||
MD_MEMORY_INFO_LIST_STREAM = 16, /* MDRawMemoryInfoList */
|
||||
MD_THREAD_INFO_LIST_STREAM = 17,
|
||||
MD_HANDLE_OPERATION_LIST_STREAM = 18,
|
||||
MD_LAST_RESERVED_STREAM = 0x0000ffff,
|
||||
|
||||
/* Breakpad extension types. 0x4767 = "Gg" */
|
||||
MD_BREAKPAD_INFO_STREAM = 0x47670001, /* MDRawBreakpadInfo */
|
||||
MD_ASSERTION_INFO_STREAM = 0x47670002, /* MDRawAssertionInfo */
|
||||
/* These are additional minidump stream values which are specific to
|
||||
* the linux breakpad implementation. */
|
||||
MD_LINUX_CPU_INFO = 0x47670003, /* /proc/cpuinfo */
|
||||
MD_LINUX_PROC_STATUS = 0x47670004, /* /proc/$x/status */
|
||||
MD_LINUX_LSB_RELEASE = 0x47670005, /* /etc/lsb-release */
|
||||
MD_LINUX_CMD_LINE = 0x47670006, /* /proc/$x/cmdline */
|
||||
MD_LINUX_ENVIRON = 0x47670007, /* /proc/$x/environ */
|
||||
MD_LINUX_AUXV = 0x47670008, /* /proc/$x/auxv */
|
||||
MD_LINUX_MAPS = 0x47670009, /* /proc/$x/maps */
|
||||
MD_LINUX_DSO_DEBUG = 0x4767000A /* MDRawDebug{32,64} */
|
||||
} MDStreamType; /* MINIDUMP_STREAM_TYPE */
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t length; /* Length of buffer in bytes (not characters),
|
||||
* excluding 0-terminator */
|
||||
uint16_t buffer[1]; /* UTF-16-encoded, 0-terminated */
|
||||
} MDString; /* MINIDUMP_STRING */
|
||||
|
||||
static const size_t MDString_minsize = offsetof(MDString, buffer[0]);
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t thread_id;
|
||||
uint32_t suspend_count;
|
||||
uint32_t priority_class;
|
||||
uint32_t priority;
|
||||
uint64_t teb; /* Thread environment block */
|
||||
MDMemoryDescriptor stack;
|
||||
MDLocationDescriptor thread_context; /* MDRawContext[CPU] */
|
||||
} MDRawThread; /* MINIDUMP_THREAD */
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t number_of_threads;
|
||||
MDRawThread threads[1];
|
||||
} MDRawThreadList; /* MINIDUMP_THREAD_LIST */
|
||||
|
||||
static const size_t MDRawThreadList_minsize = offsetof(MDRawThreadList,
|
||||
threads[0]);
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint64_t base_of_image;
|
||||
uint32_t size_of_image;
|
||||
uint32_t checksum; /* 0 if unknown */
|
||||
uint32_t time_date_stamp; /* time_t */
|
||||
MDRVA module_name_rva; /* MDString, pathname or filename */
|
||||
MDVSFixedFileInfo version_info;
|
||||
|
||||
/* The next field stores a CodeView record and is populated when a module's
|
||||
* debug information resides in a PDB file. It identifies the PDB file. */
|
||||
MDLocationDescriptor cv_record;
|
||||
|
||||
/* The next field is populated when a module's debug information resides
|
||||
* in a DBG file. It identifies the DBG file. This field is effectively
|
||||
* obsolete with modules built by recent toolchains. */
|
||||
MDLocationDescriptor misc_record;
|
||||
|
||||
/* Alignment problem: reserved0 and reserved1 are defined by the platform
|
||||
* SDK as 64-bit quantities. However, that results in a structure whose
|
||||
* alignment is unpredictable on different CPUs and ABIs. If the ABI
|
||||
* specifies full alignment of 64-bit quantities in structures (as ppc
|
||||
* does), there will be padding between miscRecord and reserved0. If
|
||||
* 64-bit quantities can be aligned on 32-bit boundaries (as on x86),
|
||||
* this padding will not exist. (Note that the structure up to this point
|
||||
* contains 1 64-bit member followed by 21 32-bit members.)
|
||||
* As a workaround, reserved0 and reserved1 are instead defined here as
|
||||
* four 32-bit quantities. This should be harmless, as there are
|
||||
* currently no known uses for these fields. */
|
||||
uint32_t reserved0[2];
|
||||
uint32_t reserved1[2];
|
||||
} MDRawModule; /* MINIDUMP_MODULE */
|
||||
|
||||
/* The inclusion of a 64-bit type in MINIDUMP_MODULE forces the struct to
|
||||
* be tail-padded out to a multiple of 64 bits under some ABIs (such as PPC).
|
||||
* This doesn't occur on systems that don't tail-pad in this manner. Define
|
||||
* this macro to be the usable size of the MDRawModule struct, and use it in
|
||||
* place of sizeof(MDRawModule). */
|
||||
#define MD_MODULE_SIZE 108
|
||||
|
||||
|
||||
/* (MDRawModule).cv_record can reference MDCVInfoPDB20 or MDCVInfoPDB70.
|
||||
* Ref.: http://www.debuginfo.com/articles/debuginfomatch.html
|
||||
* MDCVInfoPDB70 is the expected structure type with recent toolchains. */
|
||||
|
||||
typedef struct {
|
||||
uint32_t signature;
|
||||
uint32_t offset; /* Offset to debug data (expect 0 in minidump) */
|
||||
} MDCVHeader;
|
||||
|
||||
typedef struct {
|
||||
MDCVHeader cv_header;
|
||||
uint32_t signature; /* time_t debug information created */
|
||||
uint32_t age; /* revision of PDB file */
|
||||
uint8_t pdb_file_name[1]; /* Pathname or filename of PDB file */
|
||||
} MDCVInfoPDB20;
|
||||
|
||||
static const size_t MDCVInfoPDB20_minsize = offsetof(MDCVInfoPDB20,
|
||||
pdb_file_name[0]);
|
||||
|
||||
#define MD_CVINFOPDB20_SIGNATURE 0x3031424e /* cvHeader.signature = '01BN' */
|
||||
|
||||
typedef struct {
|
||||
uint32_t cv_signature;
|
||||
MDGUID signature; /* GUID, identifies PDB file */
|
||||
uint32_t age; /* Identifies incremental changes to PDB file */
|
||||
uint8_t pdb_file_name[1]; /* Pathname or filename of PDB file,
|
||||
* 0-terminated 8-bit character data (UTF-8?) */
|
||||
} MDCVInfoPDB70;
|
||||
|
||||
static const size_t MDCVInfoPDB70_minsize = offsetof(MDCVInfoPDB70,
|
||||
pdb_file_name[0]);
|
||||
|
||||
#define MD_CVINFOPDB70_SIGNATURE 0x53445352 /* cvSignature = 'SDSR' */
|
||||
|
||||
typedef struct {
|
||||
uint32_t data1[2];
|
||||
uint32_t data2;
|
||||
uint32_t data3;
|
||||
uint32_t data4;
|
||||
uint32_t data5[3];
|
||||
uint8_t extra[2];
|
||||
} MDCVInfoELF;
|
||||
|
||||
/* In addition to the two CodeView record formats above, used for linking
|
||||
* to external pdb files, it is possible for debugging data to be carried
|
||||
* directly in the CodeView record itself. These signature values will
|
||||
* be found in the first 4 bytes of the CodeView record. Additional values
|
||||
* not commonly experienced in the wild are given by "Microsoft Symbol and
|
||||
* Type Information", http://www.x86.org/ftp/manuals/tools/sym.pdf, section
|
||||
* 7.2. An in-depth description of the CodeView 4.1 format is given by
|
||||
* "Undocumented Windows 2000 Secrets", Windows 2000 Debugging Support/
|
||||
* Microsoft Symbol File Internals/CodeView Subsections,
|
||||
* http://www.rawol.com/features/undocumented/sbs-w2k-1-windows-2000-debugging-support.pdf
|
||||
*/
|
||||
#define MD_CVINFOCV41_SIGNATURE 0x3930424e /* '90BN', CodeView 4.10. */
|
||||
#define MD_CVINFOCV50_SIGNATURE 0x3131424e /* '11BN', CodeView 5.0,
|
||||
* MS C7-format (/Z7). */
|
||||
|
||||
#define MD_CVINFOUNKNOWN_SIGNATURE 0xffffffff /* An unlikely value. */
|
||||
|
||||
/* (MDRawModule).miscRecord can reference MDImageDebugMisc. The Windows
|
||||
* structure is actually defined in WinNT.h. This structure is effectively
|
||||
* obsolete with modules built by recent toolchains. */
|
||||
|
||||
typedef struct {
|
||||
uint32_t data_type; /* IMAGE_DEBUG_TYPE_*, not defined here because
|
||||
* this debug record type is mostly obsolete. */
|
||||
uint32_t length; /* Length of entire MDImageDebugMisc structure */
|
||||
uint8_t unicode; /* True if data is multibyte */
|
||||
uint8_t reserved[3];
|
||||
uint8_t data[1];
|
||||
} MDImageDebugMisc; /* IMAGE_DEBUG_MISC */
|
||||
|
||||
static const size_t MDImageDebugMisc_minsize = offsetof(MDImageDebugMisc,
|
||||
data[0]);
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t number_of_modules;
|
||||
MDRawModule modules[1];
|
||||
} MDRawModuleList; /* MINIDUMP_MODULE_LIST */
|
||||
|
||||
static const size_t MDRawModuleList_minsize = offsetof(MDRawModuleList,
|
||||
modules[0]);
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t number_of_memory_ranges;
|
||||
MDMemoryDescriptor memory_ranges[1];
|
||||
} MDRawMemoryList; /* MINIDUMP_MEMORY_LIST */
|
||||
|
||||
static const size_t MDRawMemoryList_minsize = offsetof(MDRawMemoryList,
|
||||
memory_ranges[0]);
|
||||
|
||||
|
||||
#define MD_EXCEPTION_MAXIMUM_PARAMETERS 15
|
||||
|
||||
typedef struct {
|
||||
uint32_t exception_code; /* Windows: MDExceptionCodeWin,
|
||||
* Mac OS X: MDExceptionMac,
|
||||
* Linux: MDExceptionCodeLinux. */
|
||||
uint32_t exception_flags; /* Windows: 1 if noncontinuable,
|
||||
Mac OS X: MDExceptionCodeMac. */
|
||||
uint64_t exception_record; /* Address (in the minidump-producing host's
|
||||
* memory) of another MDException, for
|
||||
* nested exceptions. */
|
||||
uint64_t exception_address; /* The address that caused the exception.
|
||||
* Mac OS X: exception subcode (which is
|
||||
* typically the address). */
|
||||
uint32_t number_parameters; /* Number of valid elements in
|
||||
* exception_information. */
|
||||
uint32_t __align;
|
||||
uint64_t exception_information[MD_EXCEPTION_MAXIMUM_PARAMETERS];
|
||||
} MDException; /* MINIDUMP_EXCEPTION */
|
||||
|
||||
#include "minidump_exception_linux.h"
|
||||
#include "minidump_exception_mac.h"
|
||||
#include "minidump_exception_ps3.h"
|
||||
#include "minidump_exception_solaris.h"
|
||||
#include "minidump_exception_win32.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t thread_id; /* Thread in which the exception
|
||||
* occurred. Corresponds to
|
||||
* (MDRawThread).thread_id. */
|
||||
uint32_t __align;
|
||||
MDException exception_record;
|
||||
MDLocationDescriptor thread_context; /* MDRawContext[CPU] */
|
||||
} MDRawExceptionStream; /* MINIDUMP_EXCEPTION_STREAM */
|
||||
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t vendor_id[3]; /* cpuid 0: ebx, edx, ecx */
|
||||
uint32_t version_information; /* cpuid 1: eax */
|
||||
uint32_t feature_information; /* cpuid 1: edx */
|
||||
uint32_t amd_extended_cpu_features; /* cpuid 0x80000001, ebx */
|
||||
} x86_cpu_info;
|
||||
struct {
|
||||
uint32_t cpuid;
|
||||
uint32_t elf_hwcaps; /* linux specific, 0 otherwise */
|
||||
} arm_cpu_info;
|
||||
struct {
|
||||
uint64_t processor_features[2];
|
||||
} other_cpu_info;
|
||||
} MDCPUInformation; /* CPU_INFORMATION */
|
||||
|
||||
/* For (MDCPUInformation).arm_cpu_info.elf_hwcaps.
|
||||
* This matches the Linux kernel definitions from <asm/hwcaps.h> */
|
||||
typedef enum {
|
||||
MD_CPU_ARM_ELF_HWCAP_SWP = (1 << 0),
|
||||
MD_CPU_ARM_ELF_HWCAP_HALF = (1 << 1),
|
||||
MD_CPU_ARM_ELF_HWCAP_THUMB = (1 << 2),
|
||||
MD_CPU_ARM_ELF_HWCAP_26BIT = (1 << 3),
|
||||
MD_CPU_ARM_ELF_HWCAP_FAST_MULT = (1 << 4),
|
||||
MD_CPU_ARM_ELF_HWCAP_FPA = (1 << 5),
|
||||
MD_CPU_ARM_ELF_HWCAP_VFP = (1 << 6),
|
||||
MD_CPU_ARM_ELF_HWCAP_EDSP = (1 << 7),
|
||||
MD_CPU_ARM_ELF_HWCAP_JAVA = (1 << 8),
|
||||
MD_CPU_ARM_ELF_HWCAP_IWMMXT = (1 << 9),
|
||||
MD_CPU_ARM_ELF_HWCAP_CRUNCH = (1 << 10),
|
||||
MD_CPU_ARM_ELF_HWCAP_THUMBEE = (1 << 11),
|
||||
MD_CPU_ARM_ELF_HWCAP_NEON = (1 << 12),
|
||||
MD_CPU_ARM_ELF_HWCAP_VFPv3 = (1 << 13),
|
||||
MD_CPU_ARM_ELF_HWCAP_VFPv3D16 = (1 << 14),
|
||||
MD_CPU_ARM_ELF_HWCAP_TLS = (1 << 15),
|
||||
MD_CPU_ARM_ELF_HWCAP_VFPv4 = (1 << 16),
|
||||
MD_CPU_ARM_ELF_HWCAP_IDIVA = (1 << 17),
|
||||
MD_CPU_ARM_ELF_HWCAP_IDIVT = (1 << 18),
|
||||
} MDCPUInformationARMElfHwCaps;
|
||||
|
||||
typedef struct {
|
||||
/* The next 3 fields and numberOfProcessors are from the SYSTEM_INFO
|
||||
* structure as returned by GetSystemInfo */
|
||||
uint16_t processor_architecture;
|
||||
uint16_t processor_level; /* x86: 5 = 586, 6 = 686, ... */
|
||||
/* ARM: 6 = ARMv6, 7 = ARMv7 ... */
|
||||
uint16_t processor_revision; /* x86: 0xMMSS, where MM=model,
|
||||
* SS=stepping */
|
||||
/* ARM: 0 */
|
||||
|
||||
uint8_t number_of_processors;
|
||||
uint8_t product_type; /* Windows: VER_NT_* from WinNT.h */
|
||||
|
||||
/* The next 5 fields are from the OSVERSIONINFO structure as returned
|
||||
* by GetVersionEx */
|
||||
uint32_t major_version;
|
||||
uint32_t minor_version;
|
||||
uint32_t build_number;
|
||||
uint32_t platform_id;
|
||||
MDRVA csd_version_rva; /* MDString further identifying the
|
||||
* host OS.
|
||||
* Windows: name of the installed OS
|
||||
* service pack.
|
||||
* Mac OS X: the Apple OS build number
|
||||
* (sw_vers -buildVersion).
|
||||
* Linux: uname -srvmo */
|
||||
|
||||
uint16_t suite_mask; /* Windows: VER_SUITE_* from WinNT.h */
|
||||
uint16_t reserved2;
|
||||
|
||||
MDCPUInformation cpu;
|
||||
} MDRawSystemInfo; /* MINIDUMP_SYSTEM_INFO */
|
||||
|
||||
/* For (MDRawSystemInfo).processor_architecture: */
|
||||
typedef enum {
|
||||
MD_CPU_ARCHITECTURE_X86 = 0, /* PROCESSOR_ARCHITECTURE_INTEL */
|
||||
MD_CPU_ARCHITECTURE_MIPS = 1, /* PROCESSOR_ARCHITECTURE_MIPS */
|
||||
MD_CPU_ARCHITECTURE_ALPHA = 2, /* PROCESSOR_ARCHITECTURE_ALPHA */
|
||||
MD_CPU_ARCHITECTURE_PPC = 3, /* PROCESSOR_ARCHITECTURE_PPC */
|
||||
MD_CPU_ARCHITECTURE_SHX = 4, /* PROCESSOR_ARCHITECTURE_SHX
|
||||
* (Super-H) */
|
||||
MD_CPU_ARCHITECTURE_ARM = 5, /* PROCESSOR_ARCHITECTURE_ARM */
|
||||
MD_CPU_ARCHITECTURE_IA64 = 6, /* PROCESSOR_ARCHITECTURE_IA64 */
|
||||
MD_CPU_ARCHITECTURE_ALPHA64 = 7, /* PROCESSOR_ARCHITECTURE_ALPHA64 */
|
||||
MD_CPU_ARCHITECTURE_MSIL = 8, /* PROCESSOR_ARCHITECTURE_MSIL
|
||||
* (Microsoft Intermediate Language) */
|
||||
MD_CPU_ARCHITECTURE_AMD64 = 9, /* PROCESSOR_ARCHITECTURE_AMD64 */
|
||||
MD_CPU_ARCHITECTURE_X86_WIN64 = 10,
|
||||
/* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */
|
||||
MD_CPU_ARCHITECTURE_SPARC = 0x8001, /* Breakpad-defined value for SPARC */
|
||||
MD_CPU_ARCHITECTURE_PPC64 = 0x8002, /* Breakpad-defined value for PPC64 */
|
||||
MD_CPU_ARCHITECTURE_ARM64 = 0x8003, /* Breakpad-defined value for ARM64 */
|
||||
MD_CPU_ARCHITECTURE_UNKNOWN = 0xffff /* PROCESSOR_ARCHITECTURE_UNKNOWN */
|
||||
} MDCPUArchitecture;
|
||||
|
||||
/* For (MDRawSystemInfo).platform_id: */
|
||||
typedef enum {
|
||||
MD_OS_WIN32S = 0, /* VER_PLATFORM_WIN32s (Windows 3.1) */
|
||||
MD_OS_WIN32_WINDOWS = 1, /* VER_PLATFORM_WIN32_WINDOWS (Windows 95-98-Me) */
|
||||
MD_OS_WIN32_NT = 2, /* VER_PLATFORM_WIN32_NT (Windows NT, 2000+) */
|
||||
MD_OS_WIN32_CE = 3, /* VER_PLATFORM_WIN32_CE, VER_PLATFORM_WIN32_HH
|
||||
* (Windows CE, Windows Mobile, "Handheld") */
|
||||
|
||||
/* The following values are Breakpad-defined. */
|
||||
MD_OS_UNIX = 0x8000, /* Generic Unix-ish */
|
||||
MD_OS_MAC_OS_X = 0x8101, /* Mac OS X/Darwin */
|
||||
MD_OS_IOS = 0x8102, /* iOS */
|
||||
MD_OS_LINUX = 0x8201, /* Linux */
|
||||
MD_OS_SOLARIS = 0x8202, /* Solaris */
|
||||
MD_OS_ANDROID = 0x8203, /* Android */
|
||||
MD_OS_PS3 = 0x8204, /* PS3 */
|
||||
MD_OS_NACL = 0x8205 /* Native Client (NaCl) */
|
||||
} MDOSPlatform;
|
||||
|
||||
typedef struct {
|
||||
uint16_t year;
|
||||
uint16_t month;
|
||||
uint16_t day_of_week;
|
||||
uint16_t day;
|
||||
uint16_t hour;
|
||||
uint16_t minute;
|
||||
uint16_t second;
|
||||
uint16_t milliseconds;
|
||||
} MDSystemTime; /* SYSTEMTIME */
|
||||
|
||||
typedef struct {
|
||||
/* Required field. The bias is the difference, in minutes, between
|
||||
* Coordinated Universal Time (UTC) and local time.
|
||||
* Formula: UTC = local time + bias */
|
||||
int32_t bias;
|
||||
/* A description for standard time. For example, "EST" could indicate Eastern
|
||||
* Standard Time. In practice this contains the full time zone names. This
|
||||
* string can be empty. */
|
||||
uint16_t standard_name[32]; /* UTF-16-encoded, 0-terminated */
|
||||
/* A MDSystemTime structure that contains a date and local time when the
|
||||
* transition from daylight saving time to standard time occurs on this
|
||||
* operating system. If the time zone does not support daylight saving time,
|
||||
* the month member in the MDSystemTime structure is zero. */
|
||||
MDSystemTime standard_date;
|
||||
/* The bias value to be used during local time translations that occur during
|
||||
* standard time. */
|
||||
int32_t standard_bias;
|
||||
/* A description for daylight saving time. For example, "PDT" could indicate
|
||||
* Pacific Daylight Time. In practice this contains the full time zone names.
|
||||
* This string can be empty. */
|
||||
uint16_t daylight_name[32]; /* UTF-16-encoded, 0-terminated */
|
||||
/* A MDSystemTime structure that contains a date and local time when the
|
||||
* transition from standard time to daylight saving time occurs on this
|
||||
* operating system. If the time zone does not support daylight saving time,
|
||||
* the month member in the MDSystemTime structure is zero.*/
|
||||
MDSystemTime daylight_date;
|
||||
/* The bias value to be used during local time translations that occur during
|
||||
* daylight saving time. */
|
||||
int32_t daylight_bias;
|
||||
} MDTimeZoneInformation; /* TIME_ZONE_INFORMATION */
|
||||
|
||||
/* MAX_PATH from windef.h */
|
||||
#define MD_MAX_PATH 260
|
||||
|
||||
/* The miscellaneous information stream contains a variety
|
||||
* of small pieces of information. A member is valid if
|
||||
* it's within the available size and its corresponding
|
||||
* bit is set. */
|
||||
typedef struct {
|
||||
uint32_t size_of_info; /* Length of entire MDRawMiscInfo structure. */
|
||||
uint32_t flags1;
|
||||
|
||||
/* The next field is only valid if flags1 contains
|
||||
* MD_MISCINFO_FLAGS1_PROCESS_ID. */
|
||||
uint32_t process_id;
|
||||
|
||||
/* The next 3 fields are only valid if flags1 contains
|
||||
* MD_MISCINFO_FLAGS1_PROCESS_TIMES. */
|
||||
uint32_t process_create_time; /* time_t process started */
|
||||
uint32_t process_user_time; /* seconds of user CPU time */
|
||||
uint32_t process_kernel_time; /* seconds of kernel CPU time */
|
||||
|
||||
/* The following fields are not present in MINIDUMP_MISC_INFO but are
|
||||
* in MINIDUMP_MISC_INFO_2. When this struct is populated, these values
|
||||
* may not be set. Use flags1 and size_of_info to determine whether these
|
||||
* values are present. These are only valid when flags1 contains
|
||||
* MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO. */
|
||||
uint32_t processor_max_mhz;
|
||||
uint32_t processor_current_mhz;
|
||||
uint32_t processor_mhz_limit;
|
||||
uint32_t processor_max_idle_state;
|
||||
uint32_t processor_current_idle_state;
|
||||
|
||||
/* The following fields are not present in MINIDUMP_MISC_INFO_2 but are
|
||||
* in MINIDUMP_MISC_INFO_3. When this struct is populated, these values
|
||||
* may not be set. Use flags1 and size_of_info to determine whether these
|
||||
* values are present. */
|
||||
|
||||
/* The following field is only valid if flags1 contains
|
||||
* MD_MISCINFO_FLAGS1_PROCESS_INTEGRITY. */
|
||||
uint32_t process_integrity_level;
|
||||
|
||||
/* The following field is only valid if flags1 contains
|
||||
* MD_MISCINFO_FLAGS1_PROCESS_EXECUTE_FLAGS. */
|
||||
uint32_t process_execute_flags;
|
||||
|
||||
/* The following field is only valid if flags1 contains
|
||||
* MD_MISCINFO_FLAGS1_PROTECTED_PROCESS. */
|
||||
uint32_t protected_process;
|
||||
|
||||
/* The following 2 fields are only valid if flags1 contains
|
||||
* MD_MISCINFO_FLAGS1_TIMEZONE. */
|
||||
uint32_t time_zone_id;
|
||||
MDTimeZoneInformation time_zone;
|
||||
|
||||
/* The following fields are not present in MINIDUMP_MISC_INFO_3 but are
|
||||
* in MINIDUMP_MISC_INFO_4. When this struct is populated, these values
|
||||
* may not be set. Use flags1 and size_of_info to determine whether these
|
||||
* values are present. */
|
||||
|
||||
/* The following 2 fields are only valid if flags1 contains
|
||||
* MD_MISCINFO_FLAGS1_BUILDSTRING. */
|
||||
uint16_t build_string[MD_MAX_PATH]; /* UTF-16-encoded, 0-terminated */
|
||||
uint16_t dbg_bld_str[40]; /* UTF-16-encoded, 0-terminated */
|
||||
} MDRawMiscInfo; /* MINIDUMP_MISC_INFO, MINIDUMP_MISC_INFO_2,
|
||||
* MINIDUMP_MISC_INFO_3, MINIDUMP_MISC_INFO_4,
|
||||
* MINIDUMP_MISC_INFO_N */
|
||||
|
||||
static const size_t MD_MISCINFO_SIZE =
|
||||
offsetof(MDRawMiscInfo, processor_max_mhz);
|
||||
static const size_t MD_MISCINFO2_SIZE =
|
||||
offsetof(MDRawMiscInfo, process_integrity_level);
|
||||
static const size_t MD_MISCINFO3_SIZE =
|
||||
offsetof(MDRawMiscInfo, build_string[0]);
|
||||
static const size_t MD_MISCINFO4_SIZE = sizeof(MDRawMiscInfo);
|
||||
|
||||
/* For (MDRawMiscInfo).flags1. These values indicate which fields in the
|
||||
* MDRawMiscInfoStructure are valid. */
|
||||
typedef enum {
|
||||
MD_MISCINFO_FLAGS1_PROCESS_ID = 0x00000001,
|
||||
/* MINIDUMP_MISC1_PROCESS_ID */
|
||||
MD_MISCINFO_FLAGS1_PROCESS_TIMES = 0x00000002,
|
||||
/* MINIDUMP_MISC1_PROCESS_TIMES */
|
||||
MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO = 0x00000004,
|
||||
/* MINIDUMP_MISC1_PROCESSOR_POWER_INFO */
|
||||
MD_MISCINFO_FLAGS1_PROCESS_INTEGRITY = 0x00000010,
|
||||
/* MINIDUMP_MISC3_PROCESS_INTEGRITY */
|
||||
MD_MISCINFO_FLAGS1_PROCESS_EXECUTE_FLAGS = 0x00000020,
|
||||
/* MINIDUMP_MISC3_PROCESS_EXECUTE_FLAGS */
|
||||
MD_MISCINFO_FLAGS1_TIMEZONE = 0x00000040,
|
||||
/* MINIDUMP_MISC3_TIMEZONE */
|
||||
MD_MISCINFO_FLAGS1_PROTECTED_PROCESS = 0x00000080,
|
||||
/* MINIDUMP_MISC3_PROTECTED_PROCESS */
|
||||
MD_MISCINFO_FLAGS1_BUILDSTRING = 0x00000100,
|
||||
/* MINIDUMP_MISC4_BUILDSTRING */
|
||||
} MDMiscInfoFlags1;
|
||||
|
||||
/*
|
||||
* Around DbgHelp version 6.0, the style of new LIST structures changed
|
||||
* from including an array of length 1 at the end of the struct to
|
||||
* represent the variable-length data to including explicit
|
||||
* "size of header", "size of entry" and "number of entries" fields
|
||||
* in the header, presumably to allow backwards-compatibly-extending
|
||||
* the structures in the future. The actual list entries follow the
|
||||
* header data directly in this case.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
uint32_t size_of_header; /* sizeof(MDRawMemoryInfoList) */
|
||||
uint32_t size_of_entry; /* sizeof(MDRawMemoryInfo) */
|
||||
uint64_t number_of_entries;
|
||||
} MDRawMemoryInfoList; /* MINIDUMP_MEMORY_INFO_LIST */
|
||||
|
||||
typedef struct {
|
||||
uint64_t base_address; /* Base address of a region of pages */
|
||||
uint64_t allocation_base; /* Base address of a range of pages
|
||||
* within this region. */
|
||||
uint32_t allocation_protection; /* Memory protection when this region
|
||||
* was originally allocated:
|
||||
* MDMemoryProtection */
|
||||
uint32_t __alignment1;
|
||||
uint64_t region_size;
|
||||
uint32_t state; /* MDMemoryState */
|
||||
uint32_t protection; /* MDMemoryProtection */
|
||||
uint32_t type; /* MDMemoryType */
|
||||
uint32_t __alignment2;
|
||||
} MDRawMemoryInfo; /* MINIDUMP_MEMORY_INFO */
|
||||
|
||||
/* For (MDRawMemoryInfo).state */
|
||||
typedef enum {
|
||||
MD_MEMORY_STATE_COMMIT = 0x1000, /* physical storage has been allocated */
|
||||
MD_MEMORY_STATE_RESERVE = 0x2000, /* reserved, but no physical storage */
|
||||
MD_MEMORY_STATE_FREE = 0x10000 /* available to be allocated */
|
||||
} MDMemoryState;
|
||||
|
||||
/* For (MDRawMemoryInfo).allocation_protection and .protection */
|
||||
typedef enum {
|
||||
MD_MEMORY_PROTECT_NOACCESS = 0x01, /* PAGE_NOACCESS */
|
||||
MD_MEMORY_PROTECT_READONLY = 0x02, /* PAGE_READONLY */
|
||||
MD_MEMORY_PROTECT_READWRITE = 0x04, /* PAGE_READWRITE */
|
||||
MD_MEMORY_PROTECT_WRITECOPY = 0x08, /* PAGE_WRITECOPY */
|
||||
MD_MEMORY_PROTECT_EXECUTE = 0x10, /* PAGE_EXECUTE */
|
||||
MD_MEMORY_PROTECT_EXECUTE_READ = 0x20, /* PAGE_EXECUTE_READ */
|
||||
MD_MEMORY_PROTECT_EXECUTE_READWRITE = 0x40, /* PAGE_EXECUTE_READWRITE */
|
||||
MD_MEMORY_PROTECT_EXECUTE_WRITECOPY = 0x80, /* PAGE_EXECUTE_WRITECOPY */
|
||||
/* These options can be combined with the previous flags. */
|
||||
MD_MEMORY_PROTECT_GUARD = 0x100, /* PAGE_GUARD */
|
||||
MD_MEMORY_PROTECT_NOCACHE = 0x200, /* PAGE_NOCACHE */
|
||||
MD_MEMORY_PROTECT_WRITECOMBINE = 0x400, /* PAGE_WRITECOMBINE */
|
||||
} MDMemoryProtection;
|
||||
|
||||
/* Used to mask the mutually exclusive options from the combinable flags. */
|
||||
const uint32_t MD_MEMORY_PROTECTION_ACCESS_MASK = 0xFF;
|
||||
|
||||
/* For (MDRawMemoryInfo).type */
|
||||
typedef enum {
|
||||
MD_MEMORY_TYPE_PRIVATE = 0x20000, /* not shared by other processes */
|
||||
MD_MEMORY_TYPE_MAPPED = 0x40000, /* mapped into the view of a section */
|
||||
MD_MEMORY_TYPE_IMAGE = 0x1000000 /* mapped into the view of an image */
|
||||
} MDMemoryType;
|
||||
|
||||
/*
|
||||
* Breakpad extension types
|
||||
*/
|
||||
|
||||
|
||||
typedef struct {
|
||||
/* validity is a bitmask with values from MDBreakpadInfoValidity, indicating
|
||||
* which of the other fields in the structure are valid. */
|
||||
uint32_t validity;
|
||||
|
||||
/* Thread ID of the handler thread. dump_thread_id should correspond to
|
||||
* the thread_id of an MDRawThread in the minidump's MDRawThreadList if
|
||||
* a dedicated thread in that list was used to produce the minidump. If
|
||||
* the MDRawThreadList does not contain a dedicated thread used to produce
|
||||
* the minidump, this field should be set to 0 and the validity field
|
||||
* must not contain MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID. */
|
||||
uint32_t dump_thread_id;
|
||||
|
||||
/* Thread ID of the thread that requested the minidump be produced. As
|
||||
* with dump_thread_id, requesting_thread_id should correspond to the
|
||||
* thread_id of an MDRawThread in the minidump's MDRawThreadList. For
|
||||
* minidumps produced as a result of an exception, requesting_thread_id
|
||||
* will be the same as the MDRawExceptionStream's thread_id field. For
|
||||
* minidumps produced "manually" at the program's request,
|
||||
* requesting_thread_id will indicate which thread caused the dump to be
|
||||
* written. If the minidump was produced at the request of something
|
||||
* other than a thread in the MDRawThreadList, this field should be set
|
||||
* to 0 and the validity field must not contain
|
||||
* MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID. */
|
||||
uint32_t requesting_thread_id;
|
||||
} MDRawBreakpadInfo;
|
||||
|
||||
/* For (MDRawBreakpadInfo).validity: */
|
||||
typedef enum {
|
||||
/* When set, the dump_thread_id field is valid. */
|
||||
MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID = 1 << 0,
|
||||
|
||||
/* When set, the requesting_thread_id field is valid. */
|
||||
MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID = 1 << 1
|
||||
} MDBreakpadInfoValidity;
|
||||
|
||||
typedef struct {
|
||||
/* expression, function, and file are 0-terminated UTF-16 strings. They
|
||||
* may be truncated if necessary, but should always be 0-terminated when
|
||||
* written to a file.
|
||||
* Fixed-length strings are used because MiniDumpWriteDump doesn't offer
|
||||
* a way for user streams to point to arbitrary RVAs for strings. */
|
||||
uint16_t expression[128]; /* Assertion that failed... */
|
||||
uint16_t function[128]; /* ...within this function... */
|
||||
uint16_t file[128]; /* ...in this file... */
|
||||
uint32_t line; /* ...at this line. */
|
||||
uint32_t type;
|
||||
} MDRawAssertionInfo;
|
||||
|
||||
/* For (MDRawAssertionInfo).type: */
|
||||
typedef enum {
|
||||
MD_ASSERTION_INFO_TYPE_UNKNOWN = 0,
|
||||
|
||||
/* Used for assertions that would be raised by the MSVC CRT but are
|
||||
* directed to an invalid parameter handler instead. */
|
||||
MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER,
|
||||
|
||||
/* Used for assertions that would be raised by the MSVC CRT but are
|
||||
* directed to a pure virtual call handler instead. */
|
||||
MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL
|
||||
} MDAssertionInfoData;
|
||||
|
||||
/* These structs are used to store the DSO debug data in Linux minidumps,
|
||||
* which is necessary for converting minidumps to usable coredumps.
|
||||
* Because of a historical accident, several fields are variably encoded
|
||||
* according to client word size, so tools potentially need to support both. */
|
||||
|
||||
typedef struct {
|
||||
uint32_t addr;
|
||||
MDRVA name;
|
||||
uint32_t ld;
|
||||
} MDRawLinkMap32;
|
||||
|
||||
typedef struct {
|
||||
uint32_t version;
|
||||
MDRVA map; /* array of MDRawLinkMap32 */
|
||||
uint32_t dso_count;
|
||||
uint32_t brk;
|
||||
uint32_t ldbase;
|
||||
uint32_t dynamic;
|
||||
} MDRawDebug32;
|
||||
|
||||
typedef struct {
|
||||
uint64_t addr;
|
||||
MDRVA name;
|
||||
uint64_t ld;
|
||||
} MDRawLinkMap64;
|
||||
|
||||
typedef struct {
|
||||
uint32_t version;
|
||||
MDRVA map; /* array of MDRawLinkMap64 */
|
||||
uint32_t dso_count;
|
||||
uint64_t brk;
|
||||
uint64_t ldbase;
|
||||
uint64_t dynamic;
|
||||
} MDRawDebug64;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
|
||||
#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_FORMAT_H__ */
|
|
@ -1,107 +0,0 @@
|
|||
// Copyright (c) 2007, 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. */
|
||||
|
||||
// minidump_size.h: Provides a C++ template for programmatic access to
|
||||
// the sizes of various types defined in minidump_format.h.
|
||||
//
|
||||
// Author: Mark Mentovai
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__
|
||||
#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
template<typename T>
|
||||
class minidump_size {
|
||||
public:
|
||||
static size_t size() { return sizeof(T); }
|
||||
};
|
||||
|
||||
// Explicit specializations for variable-length types. The size returned
|
||||
// for these should be the size for an object without its variable-length
|
||||
// section.
|
||||
|
||||
template<>
|
||||
class minidump_size<MDString> {
|
||||
public:
|
||||
static size_t size() { return MDString_minsize; }
|
||||
};
|
||||
|
||||
template<>
|
||||
class minidump_size<MDRawThreadList> {
|
||||
public:
|
||||
static size_t size() { return MDRawThreadList_minsize; }
|
||||
};
|
||||
|
||||
template<>
|
||||
class minidump_size<MDCVInfoPDB20> {
|
||||
public:
|
||||
static size_t size() { return MDCVInfoPDB20_minsize; }
|
||||
};
|
||||
|
||||
template<>
|
||||
class minidump_size<MDCVInfoPDB70> {
|
||||
public:
|
||||
static size_t size() { return MDCVInfoPDB70_minsize; }
|
||||
};
|
||||
|
||||
template<>
|
||||
class minidump_size<MDImageDebugMisc> {
|
||||
public:
|
||||
static size_t size() { return MDImageDebugMisc_minsize; }
|
||||
};
|
||||
|
||||
template<>
|
||||
class minidump_size<MDRawModuleList> {
|
||||
public:
|
||||
static size_t size() { return MDRawModuleList_minsize; }
|
||||
};
|
||||
|
||||
template<>
|
||||
class minidump_size<MDRawMemoryList> {
|
||||
public:
|
||||
static size_t size() { return MDRawMemoryList_minsize; }
|
||||
};
|
||||
|
||||
// Explicit specialization for MDRawModule, for which sizeof may include
|
||||
// tail-padding on some architectures but not others.
|
||||
|
||||
template<>
|
||||
class minidump_size<MDRawModule> {
|
||||
public:
|
||||
static size_t size() { return MD_MODULE_SIZE; }
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_COMMON_MINIDUMP_SIZE_H__
|
|
@ -1,144 +0,0 @@
|
|||
// Copyright (c) 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
|
||||
// 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.
|
||||
|
||||
// basic_source_line_resolver.h: BasicSourceLineResolver is derived from
|
||||
// SourceLineResolverBase, and is a concrete implementation of
|
||||
// SourceLineResolverInterface, using address map files produced by a
|
||||
// compatible writer, e.g. PDBSourceLineWriter.
|
||||
//
|
||||
// see "processor/source_line_resolver_base.h"
|
||||
// and "source_line_resolver_interface.h" for more documentation.
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__
|
||||
#define GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "common/using_std_string.h"
|
||||
#include "google_breakpad/processor/source_line_resolver_base.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
using std::map;
|
||||
|
||||
class BasicSourceLineResolver : public SourceLineResolverBase {
|
||||
public:
|
||||
BasicSourceLineResolver();
|
||||
virtual ~BasicSourceLineResolver() { }
|
||||
|
||||
using SourceLineResolverBase::LoadModule;
|
||||
using SourceLineResolverBase::LoadModuleUsingMapBuffer;
|
||||
using SourceLineResolverBase::LoadModuleUsingMemoryBuffer;
|
||||
using SourceLineResolverBase::ShouldDeleteMemoryBufferAfterLoadModule;
|
||||
using SourceLineResolverBase::UnloadModule;
|
||||
using SourceLineResolverBase::HasModule;
|
||||
using SourceLineResolverBase::IsModuleCorrupt;
|
||||
using SourceLineResolverBase::FillSourceLineInfo;
|
||||
using SourceLineResolverBase::FindWindowsFrameInfo;
|
||||
using SourceLineResolverBase::FindCFIFrameInfo;
|
||||
|
||||
private:
|
||||
// friend declarations:
|
||||
friend class BasicModuleFactory;
|
||||
friend class ModuleComparer;
|
||||
friend class ModuleSerializer;
|
||||
template<class> friend class SimpleSerializer;
|
||||
|
||||
// Function derives from SourceLineResolverBase::Function.
|
||||
struct Function;
|
||||
// Module implements SourceLineResolverBase::Module interface.
|
||||
class Module;
|
||||
|
||||
// Disallow unwanted copy ctor and assignment operator
|
||||
BasicSourceLineResolver(const BasicSourceLineResolver&);
|
||||
void operator=(const BasicSourceLineResolver&);
|
||||
};
|
||||
|
||||
// Helper class, containing useful methods for parsing of Breakpad symbol files.
|
||||
class SymbolParseHelper {
|
||||
public:
|
||||
// Parses a |file_line| declaration. Returns true on success.
|
||||
// Format: FILE <id> <filename>.
|
||||
// Notice, that this method modifies the input |file_line| which is why it
|
||||
// can't be const. On success, <id>, and <filename> are stored in |*index|,
|
||||
// and |*filename|. No allocation is done, |*filename| simply points inside
|
||||
// |file_line|.
|
||||
static bool ParseFile(char *file_line, // in
|
||||
long *index, // out
|
||||
char **filename); // out
|
||||
|
||||
// Parses a |function_line| declaration. Returns true on success.
|
||||
// Format: FUNC <address> <size> <stack_param_size> <name>.
|
||||
// Notice, that this method modifies the input |function_line| which is why it
|
||||
// can't be const. On success, <address>, <size>, <stack_param_size>, and
|
||||
// <name> are stored in |*address|, |*size|, |*stack_param_size|, and |*name|.
|
||||
// No allocation is done, |*name| simply points inside |function_line|.
|
||||
static bool ParseFunction(char *function_line, // in
|
||||
uint64_t *address, // out
|
||||
uint64_t *size, // out
|
||||
long *stack_param_size, // out
|
||||
char **name); // out
|
||||
|
||||
// Parses a |line| declaration. Returns true on success.
|
||||
// Format: <address> <size> <line number> <source file id>
|
||||
// Notice, that this method modifies the input |function_line| which is why
|
||||
// it can't be const. On success, <address>, <size>, <line number>, and
|
||||
// <source file id> are stored in |*address|, |*size|, |*line_number|, and
|
||||
// |*source_file|.
|
||||
static bool ParseLine(char *line_line, // in
|
||||
uint64_t *address, // out
|
||||
uint64_t *size, // out
|
||||
long *line_number, // out
|
||||
long *source_file); // out
|
||||
|
||||
// Parses a |public_line| declaration. Returns true on success.
|
||||
// Format: PUBLIC <address> <stack_param_size> <name>
|
||||
// Notice, that this method modifies the input |function_line| which is why
|
||||
// it can't be const. On success, <address>, <stack_param_size>, <name>
|
||||
// are stored in |*address|, |*stack_param_size|, and |*name|.
|
||||
// No allocation is done, |*name| simply points inside |public_line|.
|
||||
static bool ParsePublicSymbol(char *public_line, // in
|
||||
uint64_t *address, // out
|
||||
long *stack_param_size, // out
|
||||
char **name); // out
|
||||
|
||||
private:
|
||||
// Used for success checks after strtoull and strtol.
|
||||
static bool IsValidAfterNumber(char *after_number);
|
||||
|
||||
// Only allow static methods.
|
||||
SymbolParseHelper();
|
||||
SymbolParseHelper(const SymbolParseHelper&);
|
||||
void operator=(const SymbolParseHelper&);
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__
|
|
@ -1,77 +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.
|
||||
|
||||
// call_stack.h: A call stack comprised of stack frames.
|
||||
//
|
||||
// This class manages a vector of stack frames. It is used instead of
|
||||
// exposing the vector directly to allow the CallStack to own StackFrame
|
||||
// pointers without having to publicly export the linked_ptr class. A
|
||||
// CallStack must be composed of pointers instead of objects to allow for
|
||||
// CPU-specific StackFrame subclasses.
|
||||
//
|
||||
// By convention, the stack frame at index 0 is the innermost callee frame,
|
||||
// and the frame at the highest index in a call stack is the outermost
|
||||
// caller. CallStack only allows stacks to be built by pushing frames,
|
||||
// beginning with the innermost callee frame.
|
||||
//
|
||||
// Author: Mark Mentovai
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__
|
||||
#define GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
using std::vector;
|
||||
|
||||
struct StackFrame;
|
||||
template<typename T> class linked_ptr;
|
||||
|
||||
class CallStack {
|
||||
public:
|
||||
CallStack() { Clear(); }
|
||||
~CallStack();
|
||||
|
||||
// Resets the CallStack to its initial empty state
|
||||
void Clear();
|
||||
|
||||
const vector<StackFrame*>* frames() const { return &frames_; }
|
||||
|
||||
private:
|
||||
// Stackwalker is responsible for building the frames_ vector.
|
||||
friend class Stackwalker;
|
||||
|
||||
// Storage for pushed frames.
|
||||
vector<StackFrame*> frames_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_PROCSSOR_CALL_STACK_H__
|
|
@ -1,94 +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.
|
||||
|
||||
// code_module.h: Carries information about code modules that are loaded
|
||||
// into a process.
|
||||
//
|
||||
// Author: Mark Mentovai
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULE_H__
|
||||
#define GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULE_H__
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/using_std_string.h"
|
||||
#include "google_breakpad/common/breakpad_types.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
class CodeModule {
|
||||
public:
|
||||
virtual ~CodeModule() {}
|
||||
|
||||
// The base address of this code module as it was loaded by the process.
|
||||
// (uint64_t)-1 on error.
|
||||
virtual uint64_t base_address() const = 0;
|
||||
|
||||
// The size of the code module. 0 on error.
|
||||
virtual uint64_t size() const = 0;
|
||||
|
||||
// The path or file name that the code module was loaded from. Empty on
|
||||
// error.
|
||||
virtual string code_file() const = 0;
|
||||
|
||||
// An identifying string used to discriminate between multiple versions and
|
||||
// builds of the same code module. This may contain a uuid, timestamp,
|
||||
// version number, or any combination of this or other information, in an
|
||||
// implementation-defined format. Empty on error.
|
||||
virtual string code_identifier() const = 0;
|
||||
|
||||
// The filename containing debugging information associated with the code
|
||||
// module. If debugging information is stored in a file separate from the
|
||||
// code module itself (as is the case when .pdb or .dSYM files are used),
|
||||
// this will be different from code_file. If debugging information is
|
||||
// stored in the code module itself (possibly prior to stripping), this
|
||||
// will be the same as code_file. Empty on error.
|
||||
virtual string debug_file() const = 0;
|
||||
|
||||
// An identifying string similar to code_identifier, but identifies a
|
||||
// specific version and build of the associated debug file. This may be
|
||||
// the same as code_identifier when the debug_file and code_file are
|
||||
// identical or when the same identifier is used to identify distinct
|
||||
// debug and code files.
|
||||
virtual string debug_identifier() const = 0;
|
||||
|
||||
// A human-readable representation of the code module's version. Empty on
|
||||
// error.
|
||||
virtual string version() const = 0;
|
||||
|
||||
// Creates a new copy of this CodeModule object, which the caller takes
|
||||
// ownership of. The new CodeModule may be of a different concrete class
|
||||
// than the CodeModule being copied, but will behave identically to the
|
||||
// copied CodeModule as far as the CodeModule interface is concerned.
|
||||
virtual const CodeModule* Copy() const = 0;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULE_H__
|
|
@ -1,98 +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.
|
||||
|
||||
// code_modules.h: Contains all of the CodeModule objects that were loaded
|
||||
// into a single process.
|
||||
//
|
||||
// Author: Mark Mentovai
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__
|
||||
#define GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__
|
||||
|
||||
#include "google_breakpad/common/breakpad_types.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
class CodeModule;
|
||||
|
||||
class CodeModules {
|
||||
public:
|
||||
virtual ~CodeModules() {}
|
||||
|
||||
// The number of contained CodeModule objects.
|
||||
virtual unsigned int module_count() const = 0;
|
||||
|
||||
// Random access to modules. Returns the module whose code is present
|
||||
// at the address indicated by |address|. If no module is present at this
|
||||
// address, returns NULL. Ownership of the returned CodeModule is retained
|
||||
// by the CodeModules object; pointers returned by this method are valid for
|
||||
// comparison with pointers returned by the other Get methods.
|
||||
virtual const CodeModule* GetModuleForAddress(uint64_t address) const = 0;
|
||||
|
||||
// Returns the module corresponding to the main executable. If there is
|
||||
// no main executable, returns NULL. Ownership of the returned CodeModule
|
||||
// is retained by the CodeModules object; pointers returned by this method
|
||||
// are valid for comparison with pointers returned by the other Get
|
||||
// methods.
|
||||
virtual const CodeModule* GetMainModule() const = 0;
|
||||
|
||||
// Sequential access to modules. A sequence number of 0 corresponds to the
|
||||
// module residing lowest in memory. If the sequence number is out of
|
||||
// range, returns NULL. Ownership of the returned CodeModule is retained
|
||||
// by the CodeModules object; pointers returned by this method are valid for
|
||||
// comparison with pointers returned by the other Get methods.
|
||||
virtual const CodeModule* GetModuleAtSequence(
|
||||
unsigned int sequence) const = 0;
|
||||
|
||||
// Sequential access to modules. This is similar to GetModuleAtSequence,
|
||||
// except no ordering requirement is enforced. A CodeModules implementation
|
||||
// may return CodeModule objects from GetModuleAtIndex in any order it
|
||||
// wishes, provided that the order remain the same throughout the life of
|
||||
// the CodeModules object. Typically, GetModuleAtIndex would be used by
|
||||
// a caller to enumerate all CodeModule objects quickly when the enumeration
|
||||
// does not require any ordering. If the index argument is out of range,
|
||||
// returns NULL. Ownership of the returned CodeModule is retained by
|
||||
// the CodeModules object; pointers returned by this method are valid for
|
||||
// comparison with pointers returned by the other Get methods.
|
||||
virtual const CodeModule* GetModuleAtIndex(unsigned int index) const = 0;
|
||||
|
||||
// Creates a new copy of this CodeModules object, which the caller takes
|
||||
// ownership of. The new object will also contain copies of the existing
|
||||
// object's child CodeModule objects. The new CodeModules object may be of
|
||||
// a different concrete class than the object being copied, but will behave
|
||||
// identically to the copied object as far as the CodeModules and CodeModule
|
||||
// interfaces are concerned, except that the order that GetModuleAtIndex
|
||||
// returns objects in may differ between a copy and the original CodeModules
|
||||
// object.
|
||||
virtual const CodeModules* Copy() const = 0;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__
|
|
@ -1,116 +0,0 @@
|
|||
// 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.
|
||||
|
||||
// dump_context.h: A (mini/micro) dump CPU-specific context.
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_DUMP_CONTEXT_H__
|
||||
#define GOOGLE_BREAKPAD_PROCESSOR_DUMP_CONTEXT_H__
|
||||
|
||||
#include "google_breakpad/common/minidump_format.h"
|
||||
#include "google_breakpad/processor/dump_object.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// DumpContext carries a CPU-specific MDRawContext structure, which contains CPU
|
||||
// context such as register states.
|
||||
class DumpContext : public DumpObject {
|
||||
public:
|
||||
virtual ~DumpContext();
|
||||
|
||||
// Returns an MD_CONTEXT_* value such as MD_CONTEXT_X86 or MD_CONTEXT_PPC
|
||||
// identifying the CPU type that the context was collected from. The
|
||||
// returned value will identify the CPU only, and will have any other
|
||||
// MD_CONTEXT_* bits masked out. Returns 0 on failure.
|
||||
uint32_t GetContextCPU() const;
|
||||
|
||||
// Return the raw value of |context_flags_|
|
||||
uint32_t GetContextFlags() const;
|
||||
|
||||
// Returns raw CPU-specific context data for the named CPU type. If the
|
||||
// context data does not match the CPU type or does not exist, returns NULL.
|
||||
const MDRawContextAMD64* GetContextAMD64() const;
|
||||
const MDRawContextARM* GetContextARM() const;
|
||||
const MDRawContextARM64* GetContextARM64() const;
|
||||
const MDRawContextMIPS* GetContextMIPS() const;
|
||||
const MDRawContextPPC* GetContextPPC() const;
|
||||
const MDRawContextPPC64* GetContextPPC64() const;
|
||||
const MDRawContextSPARC* GetContextSPARC() const;
|
||||
const MDRawContextX86* GetContextX86() const;
|
||||
|
||||
// A convenience method to get the instruction pointer out of the
|
||||
// MDRawContext, since it varies per-CPU architecture.
|
||||
bool GetInstructionPointer(uint64_t* ip) const;
|
||||
|
||||
// Similar to the GetInstructionPointer method, this method gets the stack
|
||||
// pointer for all CPU architectures.
|
||||
bool GetStackPointer(uint64_t* sp) const;
|
||||
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
void Print();
|
||||
|
||||
protected:
|
||||
DumpContext();
|
||||
|
||||
// Sets row CPU-specific context data for the names CPU type.
|
||||
void SetContextFlags(uint32_t context_flags);
|
||||
void SetContextX86(MDRawContextX86* x86);
|
||||
void SetContextPPC(MDRawContextPPC* ppc);
|
||||
void SetContextPPC64(MDRawContextPPC64* ppc64);
|
||||
void SetContextAMD64(MDRawContextAMD64* amd64);
|
||||
void SetContextSPARC(MDRawContextSPARC* ctx_sparc);
|
||||
void SetContextARM(MDRawContextARM* arm);
|
||||
void SetContextARM64(MDRawContextARM64* arm64);
|
||||
void SetContextMIPS(MDRawContextMIPS* ctx_mips);
|
||||
|
||||
// Free the CPU-specific context structure.
|
||||
void FreeContext();
|
||||
|
||||
private:
|
||||
// The CPU-specific context structure.
|
||||
union {
|
||||
MDRawContextBase* base;
|
||||
MDRawContextX86* x86;
|
||||
MDRawContextPPC* ppc;
|
||||
MDRawContextPPC64* ppc64;
|
||||
MDRawContextAMD64* amd64;
|
||||
// on Solaris SPARC, sparc is defined as a numeric constant,
|
||||
// so variables can NOT be named as sparc
|
||||
MDRawContextSPARC* ctx_sparc;
|
||||
MDRawContextARM* arm;
|
||||
MDRawContextARM64* arm64;
|
||||
MDRawContextMIPS* ctx_mips;
|
||||
} context_;
|
||||
|
||||
// Store this separately because of the weirdo AMD64 context
|
||||
uint32_t context_flags_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_PROCESSOR_DUMP_CONTEXT_H__
|
|
@ -1,53 +0,0 @@
|
|||
// 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.
|
||||
|
||||
// dump_object.h: A base class for all mini/micro dump object.
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_DUMP_OBJECT_H__
|
||||
#define GOOGLE_BREAKPAD_PROCESSOR_DUMP_OBJECT_H__
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
// DumpObject is the base of various mini/micro dump's objects.
|
||||
class DumpObject {
|
||||
public:
|
||||
DumpObject();
|
||||
|
||||
bool valid() const { return valid_; }
|
||||
|
||||
protected:
|
||||
// DumpObjects are not valid when created. When a subclass populates its own
|
||||
// fields, it can set valid_ to true. Accessors and mutators may wish to
|
||||
// consider or alter the valid_ state as they interact with objects.
|
||||
bool valid_;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_PROCESSOR_DUMP_OBJECT_H__
|
|
@ -1,82 +0,0 @@
|
|||
// Copyright (c) 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
|
||||
// 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.
|
||||
|
||||
// exploitability_engine.h: Generic exploitability engine.
|
||||
//
|
||||
// The Exploitability class is an abstract base class providing common
|
||||
// generic methods that apply to exploitability engines for specific platforms.
|
||||
// Specific implementations will extend this class by providing run
|
||||
// methods to fill in the exploitability_ enumeration of the ProcessState
|
||||
// for a crash.
|
||||
//
|
||||
// Author: Cris Neckar
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_H_
|
||||
#define GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_H_
|
||||
|
||||
#include "google_breakpad/common/breakpad_types.h"
|
||||
#include "google_breakpad/processor/minidump.h"
|
||||
#include "google_breakpad/processor/process_state.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
class Exploitability {
|
||||
public:
|
||||
virtual ~Exploitability() {}
|
||||
|
||||
static Exploitability *ExploitabilityForPlatform(Minidump *dump,
|
||||
ProcessState *process_state);
|
||||
|
||||
// The boolean parameter signals whether the exploitability engine is
|
||||
// enabled to call out to objdump for disassembly. This is disabled by
|
||||
// default. It is used to check the identity of the instruction that
|
||||
// caused the program to crash. This should not be enabled if there are
|
||||
// portability concerns.
|
||||
static Exploitability *ExploitabilityForPlatform(Minidump *dump,
|
||||
ProcessState *process_state,
|
||||
bool enable_objdump);
|
||||
|
||||
ExploitabilityRating CheckExploitability();
|
||||
bool AddressIsAscii(uint64_t);
|
||||
|
||||
protected:
|
||||
Exploitability(Minidump *dump,
|
||||
ProcessState *process_state);
|
||||
|
||||
Minidump *dump_;
|
||||
ProcessState *process_state_;
|
||||
SystemInfo *system_info_;
|
||||
|
||||
private:
|
||||
virtual ExploitabilityRating CheckPlatformExploitability() = 0;
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_H_
|
|
@ -1,100 +0,0 @@
|
|||
// Copyright (c) 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
|
||||
// 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.
|
||||
//
|
||||
// fast_source_line_resolver.h: FastSourceLineResolver is derived from
|
||||
// SourceLineResolverBase, and is a concrete implementation of
|
||||
// SourceLineResolverInterface.
|
||||
//
|
||||
// FastSourceLineResolver is a sibling class of BasicSourceLineResolver. The
|
||||
// difference is FastSourceLineResolver loads a serialized memory chunk of data
|
||||
// which can be used directly a Module without parsing or copying of underlying
|
||||
// data. Therefore loading a symbol in FastSourceLineResolver is much faster
|
||||
// and more memory-efficient than BasicSourceLineResolver.
|
||||
//
|
||||
// See "source_line_resolver_base.h" and
|
||||
// "google_breakpad/source_line_resolver_interface.h" for more reference.
|
||||
//
|
||||
// Author: Siyang Xie (lambxsy@google.com)
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_FAST_SOURCE_LINE_RESOLVER_H__
|
||||
#define GOOGLE_BREAKPAD_PROCESSOR_FAST_SOURCE_LINE_RESOLVER_H__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "google_breakpad/processor/source_line_resolver_base.h"
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
using std::map;
|
||||
|
||||
class FastSourceLineResolver : public SourceLineResolverBase {
|
||||
public:
|
||||
FastSourceLineResolver();
|
||||
virtual ~FastSourceLineResolver() { }
|
||||
|
||||
using SourceLineResolverBase::FillSourceLineInfo;
|
||||
using SourceLineResolverBase::FindCFIFrameInfo;
|
||||
using SourceLineResolverBase::FindWindowsFrameInfo;
|
||||
using SourceLineResolverBase::HasModule;
|
||||
using SourceLineResolverBase::IsModuleCorrupt;
|
||||
using SourceLineResolverBase::LoadModule;
|
||||
using SourceLineResolverBase::LoadModuleUsingMapBuffer;
|
||||
using SourceLineResolverBase::LoadModuleUsingMemoryBuffer;
|
||||
using SourceLineResolverBase::UnloadModule;
|
||||
|
||||
private:
|
||||
// Friend declarations.
|
||||
friend class ModuleComparer;
|
||||
friend class ModuleSerializer;
|
||||
friend class FastModuleFactory;
|
||||
|
||||
// Nested types that will derive from corresponding nested types defined in
|
||||
// SourceLineResolverBase.
|
||||
struct Line;
|
||||
struct Function;
|
||||
struct PublicSymbol;
|
||||
class Module;
|
||||
|
||||
// Deserialize raw memory data to construct a WindowsFrameInfo object.
|
||||
static WindowsFrameInfo CopyWFI(const char *raw_memory);
|
||||
|
||||
// FastSourceLineResolver requires the memory buffer stays alive during the
|
||||
// lifetime of a corresponding module, therefore it needs to redefine this
|
||||
// virtual method.
|
||||
virtual bool ShouldDeleteMemoryBufferAfterLoadModule();
|
||||
|
||||
// Disallow unwanted copy ctor and assignment operator
|
||||
FastSourceLineResolver(const FastSourceLineResolver&);
|
||||
void operator=(const FastSourceLineResolver&);
|
||||
};
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_PROCESSOR_FAST_SOURCE_LINE_RESOLVER_H__
|
|
@ -1,79 +0,0 @@
|
|||
// Copyright (c) 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
|
||||
// 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.
|
||||
|
||||
// memory_region.h: Access to memory regions.
|
||||
//
|
||||
// A MemoryRegion provides virtual access to a range of memory. It is an
|
||||
// abstraction allowing the actual source of memory to be independent of
|
||||
// methods which need to access a virtual memory space.
|
||||
//
|
||||
// Author: Mark Mentovai
|
||||
|
||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_MEMORY_REGION_H__
|
||||
#define GOOGLE_BREAKPAD_PROCESSOR_MEMORY_REGION_H__
|
||||
|
||||
|
||||
#include "google_breakpad/common/breakpad_types.h"
|
||||
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
|
||||
class MemoryRegion {
|
||||
public:
|
||||
virtual ~MemoryRegion() {}
|
||||
|
||||
// The base address of this memory region.
|
||||
virtual uint64_t GetBase() const = 0;
|
||||
|
||||
// The size of this memory region.
|
||||
virtual uint32_t GetSize() const = 0;
|
||||
|
||||
// Access to data of various sizes within the memory region. address
|
||||
// is a pointer to read, and it must lie within the memory region as
|
||||
// defined by its base address and size. The location pointed to by
|
||||
// value is set to the value at address. Byte-swapping is performed
|
||||
// if necessary so that the value is appropriate for the running
|
||||
// program. Returns true on success. Fails and returns false if address
|
||||
// is out of the region's bounds (after considering the width of value),
|
||||
// or for other types of errors.
|
||||
virtual bool GetMemoryAtAddress(uint64_t address, uint8_t* value) const = 0;
|
||||
virtual bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const = 0;
|
||||
virtual bool GetMemoryAtAddress(uint64_t address, uint32_t* value) const = 0;
|
||||
virtual bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const = 0;
|
||||
|
||||
// Print a human-readable representation of the object to stdout.
|
||||
virtual void Print() const = 0;
|
||||
};
|
||||
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
|
||||
#endif // GOOGLE_BREAKPAD_PROCESSOR_MEMORY_REGION_H__
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue