From fce46f161466b2cbe0e9ae67c388bc3fc4ed6a20 Mon Sep 17 00:00:00 2001 From: khanhduytran0 Date: Wed, 11 Nov 2020 19:39:05 +0700 Subject: [PATCH] Changes/Additional to crash dumper --- app/src/main/jni/Android.mk | 4 +- .../main/jni/crash_dump/debuggerd/Android.mk | 2 +- .../jni/crash_dump/libbacktrace/Android.mk | 6 +- .../main/jni/crash_dump/libbase/.clang-format | 11 + .../main/jni/crash_dump/libbase/Android.mk | 59 +++ .../main/jni/crash_dump/libbase/CPPLINT.cfg | 2 + .../jni/crash_dump/libbase/errors_test.cpp | 34 ++ .../jni/crash_dump/libbase/errors_unix.cpp | 29 ++ .../jni/crash_dump/libbase/errors_windows.cpp | 68 +++ app/src/main/jni/crash_dump/libbase/file.cpp | 176 +++++++ .../main/jni/crash_dump/libbase/file_test.cpp | 112 +++++ .../libbase/include/android-base/errors.h | 46 ++ .../libbase/include/android-base/file.h | 49 ++ .../libbase/include/android-base/logging.h | 338 ++++++++++++++ .../libbase/include/android-base/macros.h | 188 ++++++++ .../libbase/include/android-base/memory.h | 47 ++ .../libbase/include/android-base/parseint.h | 73 +++ .../include/android-base/parsenetaddress.h | 38 ++ .../include/android-base/stringprintf.h | 56 +++ .../libbase/include/android-base/strings.h | 68 +++ .../libbase/include/android-base/test_utils.h | 51 +++ .../include/android-base/thread_annotations.h | 83 ++++ .../libbase/include/android-base/unique_fd.h | 98 ++++ .../libbase/include/android-base/utf8.h | 87 ++++ .../main/jni/crash_dump/libbase/logging.cpp | 428 ++++++++++++++++++ .../jni/crash_dump/libbase/logging_test.cpp | 281 ++++++++++++ .../jni/crash_dump/libbase/parseint_test.cpp | 78 ++++ .../crash_dump/libbase/parsenetaddress.cpp | 82 ++++ .../libbase/parsenetaddress_test.cpp | 127 ++++++ .../jni/crash_dump/libbase/stringprintf.cpp | 85 ++++ .../crash_dump/libbase/stringprintf_test.cpp | 60 +++ .../main/jni/crash_dump/libbase/strings.cpp | 104 +++++ .../jni/crash_dump/libbase/strings_test.cpp | 177 ++++++++ .../main/jni/crash_dump/libbase/test_main.cpp | 25 + .../jni/crash_dump/libbase/test_utils.cpp | 102 +++++ app/src/main/jni/crash_dump/libbase/utf8.cpp | 187 ++++++++ .../main/jni/crash_dump/libbase/utf8_test.cpp | 412 +++++++++++++++++ 37 files changed, 3866 insertions(+), 7 deletions(-) create mode 100644 app/src/main/jni/crash_dump/libbase/.clang-format create mode 100644 app/src/main/jni/crash_dump/libbase/Android.mk create mode 100644 app/src/main/jni/crash_dump/libbase/CPPLINT.cfg create mode 100644 app/src/main/jni/crash_dump/libbase/errors_test.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/errors_unix.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/errors_windows.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/file.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/file_test.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/include/android-base/errors.h create mode 100644 app/src/main/jni/crash_dump/libbase/include/android-base/file.h create mode 100644 app/src/main/jni/crash_dump/libbase/include/android-base/logging.h create mode 100644 app/src/main/jni/crash_dump/libbase/include/android-base/macros.h create mode 100644 app/src/main/jni/crash_dump/libbase/include/android-base/memory.h create mode 100644 app/src/main/jni/crash_dump/libbase/include/android-base/parseint.h create mode 100644 app/src/main/jni/crash_dump/libbase/include/android-base/parsenetaddress.h create mode 100644 app/src/main/jni/crash_dump/libbase/include/android-base/stringprintf.h create mode 100644 app/src/main/jni/crash_dump/libbase/include/android-base/strings.h create mode 100644 app/src/main/jni/crash_dump/libbase/include/android-base/test_utils.h create mode 100644 app/src/main/jni/crash_dump/libbase/include/android-base/thread_annotations.h create mode 100644 app/src/main/jni/crash_dump/libbase/include/android-base/unique_fd.h create mode 100644 app/src/main/jni/crash_dump/libbase/include/android-base/utf8.h create mode 100644 app/src/main/jni/crash_dump/libbase/logging.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/logging_test.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/parseint_test.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/parsenetaddress.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/parsenetaddress_test.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/stringprintf.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/stringprintf_test.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/strings.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/strings_test.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/test_main.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/test_utils.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/utf8.cpp create mode 100644 app/src/main/jni/crash_dump/libbase/utf8_test.cpp diff --git a/app/src/main/jni/Android.mk b/app/src/main/jni/Android.mk index 9d92d4b43..3436255c6 100644 --- a/app/src/main/jni/Android.mk +++ b/app/src/main/jni/Android.mk @@ -1,7 +1,7 @@ LOCAL_PATH := $(call my-dir) HERE_PATH := $(LOCAL_PATH) -# include $(HERE_PATH)/crash_dump/libunwind/Android.mk +include $(HERE_PATH)/crash_dump/libbase/Android.mk include $(HERE_PATH)/crash_dump/libbacktrace/Android.mk include $(HERE_PATH)/crash_dump/debuggerd/Android.mk @@ -27,7 +27,7 @@ include $(BUILD_SHARED_LIBRARY) # LOCAL_SRC_FILES := thread_helper.cpp # include $(BUILD_SHARED_LIBRARY) -# libawt_xawt without X11 +# libawt_xawt without X11, used to get Caciocavallo working LOCAL_PATH := $(HERE_PATH)/awt_xawt include $(CLEAR_VARS) LOCAL_MODULE := awt_xawt diff --git a/app/src/main/jni/crash_dump/debuggerd/Android.mk b/app/src/main/jni/crash_dump/debuggerd/Android.mk index 879d42dda..868639fc4 100644 --- a/app/src/main/jni/crash_dump/debuggerd/Android.mk +++ b/app/src/main/jni/crash_dump/debuggerd/Android.mk @@ -37,7 +37,7 @@ endif LOCAL_LDLIBS := -llog LOCAL_SHARED_LIBRARIES := \ libbacktrace \ - libbase + libcrashdumpbase LOCAL_CLANG := true diff --git a/app/src/main/jni/crash_dump/libbacktrace/Android.mk b/app/src/main/jni/crash_dump/libbacktrace/Android.mk index 75ad76ba3..26083ceb0 100644 --- a/app/src/main/jni/crash_dump/libbacktrace/Android.mk +++ b/app/src/main/jni/crash_dump/libbacktrace/Android.mk @@ -56,10 +56,8 @@ libbacktrace_src_files := \ UnwindMap.cpp \ UnwindPtrace.cpp \ -libbacktrace_shared_ldlibs := -llog -lunwind -# -lbase - -# libbacktrace_shared_libraries := libunwind +libbacktrace_shared_ldlibs := -llog +libbacktrace_shared_libraries := libunwind libcrashdumpbase module := libbacktrace module_tag := optional diff --git a/app/src/main/jni/crash_dump/libbase/.clang-format b/app/src/main/jni/crash_dump/libbase/.clang-format new file mode 100644 index 000000000..2b83a1f41 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/.clang-format @@ -0,0 +1,11 @@ +BasedOnStyle: Google +AllowShortBlocksOnASingleLine: false +AllowShortFunctionsOnASingleLine: false + +CommentPragmas: NOLINT:.* +DerivePointerAlignment: false +IndentWidth: 2 +PointerAlignment: Left +TabWidth: 2 +UseTab: Never +PenaltyExcessCharacter: 32 diff --git a/app/src/main/jni/crash_dump/libbase/Android.mk b/app/src/main/jni/crash_dump/libbase/Android.mk new file mode 100644 index 000000000..3a9323743 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/Android.mk @@ -0,0 +1,59 @@ +# +# Copyright (C) 2015 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) + +libbase_src_files := \ + file.cpp \ + logging.cpp \ + parsenetaddress.cpp \ + stringprintf.cpp \ + strings.cpp \ + test_utils.cpp \ + +libbase_cppflags := \ + -Wall \ + -Wextra \ + -Werror \ + +libbase_linux_cppflags := \ + -Wexit-time-destructors \ + +libbase_darwin_cppflags := \ + -Wexit-time-destructors \ + +# Device +# ------------------------------------------------------------------------------ +include $(CLEAR_VARS) +LOCAL_MODULE := libcrashdumpbase +LOCAL_CLANG := true +LOCAL_SRC_FILES := $(libbase_src_files) $(libbase_linux_src_files) +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_CPPFLAGS := $(libbase_cppflags) $(libbase_linux_cppflags) +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_STATIC_LIBRARIES := liblog +LOCAL_MULTILIB := both +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := libcrashdumpbase +LOCAL_CLANG := true +LOCAL_WHOLE_STATIC_LIBRARIES := libcrashdumpbase +LOCAL_SHARED_LIBRARIES := liblog +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_MULTILIB := both +include $(BUILD_SHARED_LIBRARY) + diff --git a/app/src/main/jni/crash_dump/libbase/CPPLINT.cfg b/app/src/main/jni/crash_dump/libbase/CPPLINT.cfg new file mode 100644 index 000000000..d94a89c34 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/CPPLINT.cfg @@ -0,0 +1,2 @@ +set noparent +filter=-build/header_guard,-build/include,-build/c++11,-whitespace/operators diff --git a/app/src/main/jni/crash_dump/libbase/errors_test.cpp b/app/src/main/jni/crash_dump/libbase/errors_test.cpp new file mode 100644 index 000000000..8e7cdd1da --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/errors_test.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android-base/errors.h" + +#include + +namespace android { +namespace base { + +// Error strings aren't consistent enough across systems to test the output, +// just make sure we can compile correctly and nothing crashes even if we send +// it possibly bogus error codes. +TEST(ErrorsTest, TestSystemErrorString) { + SystemErrorCodeToString(-1); + SystemErrorCodeToString(0); + SystemErrorCodeToString(1); +} + +} // namespace base +} // namespace android diff --git a/app/src/main/jni/crash_dump/libbase/errors_unix.cpp b/app/src/main/jni/crash_dump/libbase/errors_unix.cpp new file mode 100644 index 000000000..296995efe --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/errors_unix.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android-base/errors.h" + +#include + +namespace android { +namespace base { + +std::string SystemErrorCodeToString(int error_code) { + return strerror(error_code); +} + +} // namespace base +} // namespace android diff --git a/app/src/main/jni/crash_dump/libbase/errors_windows.cpp b/app/src/main/jni/crash_dump/libbase/errors_windows.cpp new file mode 100644 index 000000000..a5ff51188 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/errors_windows.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android-base/errors.h" + +#include + +#include "android-base/stringprintf.h" +#include "android-base/strings.h" +#include "android-base/utf8.h" + +// A Windows error code is a DWORD. It's simpler to use an int error code for +// both Unix and Windows if possible, but if this fails we'll need a different +// function signature for each. +static_assert(sizeof(int) >= sizeof(DWORD), + "Windows system error codes are too large to fit in an int."); + +namespace android { +namespace base { + +static constexpr DWORD kErrorMessageBufferSize = 256; + +std::string SystemErrorCodeToString(int int_error_code) { + WCHAR msgbuf[kErrorMessageBufferSize]; + DWORD error_code = int_error_code; + DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; + DWORD len = FormatMessageW(flags, nullptr, error_code, 0, msgbuf, + kErrorMessageBufferSize, nullptr); + if (len == 0) { + return android::base::StringPrintf( + "Error %lu while retrieving message for error %lu", GetLastError(), + error_code); + } + + // Convert UTF-16 to UTF-8. + std::string msg; + if (!android::base::WideToUTF8(msgbuf, &msg)) { + return android::base::StringPrintf( + "Error %lu while converting message for error %lu from UTF-16 to UTF-8", + GetLastError(), error_code); + } + + // Messages returned by the system end with line breaks. + msg = android::base::Trim(msg); + + // There are many Windows error messages compared to POSIX, so include the + // numeric error code for easier, quicker, accurate identification. Use + // decimal instead of hex because there are decimal ranges like 10000-11999 + // for Winsock. + android::base::StringAppendF(&msg, " (%lu)", error_code); + return msg; +} + +} // namespace base +} // namespace android diff --git a/app/src/main/jni/crash_dump/libbase/file.cpp b/app/src/main/jni/crash_dump/libbase/file.cpp new file mode 100644 index 000000000..da1adba19 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/file.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android-base/file.h" + +#include +#include +#include +#include + +#include + +#include "android-base/macros.h" // For TEMP_FAILURE_RETRY on Darwin. +#include "android-base/utf8.h" +#define LOG_TAG "base.file" +#include "cutils/log.h" +#include "utils/Compat.h" + +namespace android { +namespace base { + +// Versions of standard library APIs that support UTF-8 strings. +using namespace android::base::utf8; + +bool ReadFdToString(int fd, std::string* content) { + content->clear(); + + char buf[BUFSIZ]; + ssize_t n; + while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) { + content->append(buf, n); + } + return (n == 0) ? true : false; +} + +bool ReadFileToString(const std::string& path, std::string* content) { + content->clear(); + + int fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_BINARY)); + if (fd == -1) { + return false; + } + bool result = ReadFdToString(fd, content); + close(fd); + return result; +} + +bool WriteStringToFd(const std::string& content, int fd) { + const char* p = content.data(); + size_t left = content.size(); + while (left > 0) { + ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, left)); + if (n == -1) { + return false; + } + p += n; + left -= n; + } + return true; +} + +static bool CleanUpAfterFailedWrite(const std::string& path) { + // Something went wrong. Let's not leave a corrupt file lying around. + int saved_errno = errno; + unlink(path.c_str()); + errno = saved_errno; + return false; +} + +#if !defined(_WIN32) +bool WriteStringToFile(const std::string& content, const std::string& path, + mode_t mode, uid_t owner, gid_t group) { + int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY; + int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode)); + if (fd == -1) { + ALOGE("android::WriteStringToFile open failed: %s", strerror(errno)); + return false; + } + + // We do an explicit fchmod here because we assume that the caller really + // meant what they said and doesn't want the umask-influenced mode. + if (fchmod(fd, mode) == -1) { + ALOGE("android::WriteStringToFile fchmod failed: %s", strerror(errno)); + return CleanUpAfterFailedWrite(path); + } + if (fchown(fd, owner, group) == -1) { + ALOGE("android::WriteStringToFile fchown failed: %s", strerror(errno)); + return CleanUpAfterFailedWrite(path); + } + if (!WriteStringToFd(content, fd)) { + ALOGE("android::WriteStringToFile write failed: %s", strerror(errno)); + return CleanUpAfterFailedWrite(path); + } + close(fd); + return true; +} +#endif + +bool WriteStringToFile(const std::string& content, const std::string& path) { + int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY; + int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, DEFFILEMODE)); + if (fd == -1) { + return false; + } + + bool result = WriteStringToFd(content, fd); + close(fd); + return result || CleanUpAfterFailedWrite(path); +} + +bool ReadFully(int fd, void* data, size_t byte_count) { + uint8_t* p = reinterpret_cast(data); + size_t remaining = byte_count; + while (remaining > 0) { + ssize_t n = TEMP_FAILURE_RETRY(read(fd, p, remaining)); + if (n <= 0) return false; + p += n; + remaining -= n; + } + return true; +} + +bool WriteFully(int fd, const void* data, size_t byte_count) { + const uint8_t* p = reinterpret_cast(data); + size_t remaining = byte_count; + while (remaining > 0) { + ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, remaining)); + if (n == -1) return false; + p += n; + remaining -= n; + } + return true; +} + +bool RemoveFileIfExists(const std::string& path, std::string* err) { + struct stat st; +#if defined(_WIN32) + //TODO: Windows version can't handle symbol link correctly. + int result = stat(path.c_str(), &st); + bool file_type_removable = (result == 0 && S_ISREG(st.st_mode)); +#else + int result = lstat(path.c_str(), &st); + bool file_type_removable = (result == 0 && (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))); +#endif + if (result == 0) { + if (!file_type_removable) { + if (err != nullptr) { + *err = "is not a regular or symbol link file"; + } + return false; + } + if (unlink(path.c_str()) == -1) { + if (err != nullptr) { + *err = strerror(errno); + } + return false; + } + } + return true; +} + +} // namespace base +} // namespace android diff --git a/app/src/main/jni/crash_dump/libbase/file_test.cpp b/app/src/main/jni/crash_dump/libbase/file_test.cpp new file mode 100644 index 000000000..17755bfed --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/file_test.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android-base/file.h" + +#include + +#include +#include +#include + +#include + +#include "android-base/test_utils.h" + +TEST(file, ReadFileToString_ENOENT) { + std::string s("hello"); + errno = 0; + ASSERT_FALSE(android::base::ReadFileToString("/proc/does-not-exist", &s)); + EXPECT_EQ(ENOENT, errno); + EXPECT_EQ("", s); // s was cleared. +} + +TEST(file, ReadFileToString_WriteStringToFile) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.path)) + << strerror(errno); + std::string s; + ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s)) + << strerror(errno); + EXPECT_EQ("abc", s); +} + +// WriteStringToFile2 is explicitly for setting Unix permissions, which make no +// sense on Windows. +#if !defined(_WIN32) +TEST(file, WriteStringToFile2) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.path, 0660, + getuid(), getgid())) + << strerror(errno); + struct stat sb; + ASSERT_EQ(0, stat(tf.path, &sb)); + ASSERT_EQ(0660U, static_cast(sb.st_mode & ~S_IFMT)); + ASSERT_EQ(getuid(), sb.st_uid); + ASSERT_EQ(getgid(), sb.st_gid); + std::string s; + ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s)) + << strerror(errno); + EXPECT_EQ("abc", s); +} +#endif + +TEST(file, WriteStringToFd) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + ASSERT_TRUE(android::base::WriteStringToFd("abc", tf.fd)); + + ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << strerror(errno); + + std::string s; + ASSERT_TRUE(android::base::ReadFdToString(tf.fd, &s)) << strerror(errno); + EXPECT_EQ("abc", s); +} + +TEST(file, WriteFully) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + ASSERT_TRUE(android::base::WriteFully(tf.fd, "abc", 3)); + + ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << strerror(errno); + + std::string s; + s.resize(3); + ASSERT_TRUE(android::base::ReadFully(tf.fd, &s[0], s.size())) + << strerror(errno); + EXPECT_EQ("abc", s); + + ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)) << strerror(errno); + + s.resize(1024); + ASSERT_FALSE(android::base::ReadFully(tf.fd, &s[0], s.size())); +} + +TEST(file, RemoveFileIfExist) { + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + close(tf.fd); + tf.fd = -1; + std::string err; + ASSERT_TRUE(android::base::RemoveFileIfExists(tf.path, &err)) << err; + ASSERT_TRUE(android::base::RemoveFileIfExists(tf.path)); + TemporaryDir td; + ASSERT_FALSE(android::base::RemoveFileIfExists(td.path)); + ASSERT_FALSE(android::base::RemoveFileIfExists(td.path, &err)); + ASSERT_EQ("is not a regular or symbol link file", err); +} diff --git a/app/src/main/jni/crash_dump/libbase/include/android-base/errors.h b/app/src/main/jni/crash_dump/libbase/include/android-base/errors.h new file mode 100644 index 000000000..04c299c86 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/include/android-base/errors.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Portable error handling functions. This is only necessary for host-side +// code that needs to be cross-platform; code that is only run on Unix should +// just use errno and strerror() for simplicity. +// +// There is some complexity since Windows has (at least) three different error +// numbers, not all of which share the same type: +// * errno: for C runtime errors. +// * GetLastError(): Windows non-socket errors. +// * WSAGetLastError(): Windows socket errors. +// errno can be passed to strerror() on all platforms, but the other two require +// special handling to get the error string. Refer to Microsoft documentation +// to determine which error code to check for each function. + +#ifndef ANDROID_BASE_ERRORS_H +#define ANDROID_BASE_ERRORS_H + +#include + +namespace android { +namespace base { + +// Returns a string describing the given system error code. |error_code| must +// be errno on Unix or GetLastError()/WSAGetLastError() on Windows. Passing +// errno on Windows has undefined behavior. +std::string SystemErrorCodeToString(int error_code); + +} // namespace base +} // namespace android + +#endif // ANDROID_BASE_ERRORS_H diff --git a/app/src/main/jni/crash_dump/libbase/include/android-base/file.h b/app/src/main/jni/crash_dump/libbase/include/android-base/file.h new file mode 100644 index 000000000..aa18ea796 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/include/android-base/file.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BASE_FILE_H +#define ANDROID_BASE_FILE_H + +#include +#include + +#if !defined(_WIN32) && !defined(O_BINARY) +#define O_BINARY 0 +#endif + +namespace android { +namespace base { + +bool ReadFdToString(int fd, std::string* content); +bool ReadFileToString(const std::string& path, std::string* content); + +bool WriteStringToFile(const std::string& content, const std::string& path); +bool WriteStringToFd(const std::string& content, int fd); + +#if !defined(_WIN32) +bool WriteStringToFile(const std::string& content, const std::string& path, + mode_t mode, uid_t owner, gid_t group); +#endif + +bool ReadFully(int fd, void* data, size_t byte_count); +bool WriteFully(int fd, const void* data, size_t byte_count); + +bool RemoveFileIfExists(const std::string& path, std::string* err = nullptr); + +} // namespace base +} // namespace android + +#endif // ANDROID_BASE_FILE_H diff --git a/app/src/main/jni/crash_dump/libbase/include/android-base/logging.h b/app/src/main/jni/crash_dump/libbase/include/android-base/logging.h new file mode 100644 index 000000000..d3f9d0cdc --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/include/android-base/logging.h @@ -0,0 +1,338 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BASE_LOGGING_H +#define ANDROID_BASE_LOGGING_H + +// NOTE: For Windows, you must include logging.h after windows.h to allow the +// following code to suppress the evil ERROR macro: +#ifdef _WIN32 +// windows.h includes wingdi.h which defines an evil macro ERROR. +#ifdef ERROR +#undef ERROR +#endif +#endif + +#include +#include +#include + +#include "android-base/macros.h" + +namespace android { +namespace base { + +enum LogSeverity { + VERBOSE, + DEBUG, + INFO, + WARNING, + ERROR, + FATAL, +}; + +enum LogId { + DEFAULT, + MAIN, + SYSTEM, +}; + +typedef std::function LogFunction; + +extern void StderrLogger(LogId, LogSeverity, const char*, const char*, + unsigned int, const char*); + +#ifdef __ANDROID__ +// We expose this even though it is the default because a user that wants to +// override the default log buffer will have to construct this themselves. +class LogdLogger { + public: + explicit LogdLogger(LogId default_log_id = android::base::MAIN); + + void operator()(LogId, LogSeverity, const char* tag, const char* file, + unsigned int line, const char* message); + + private: + LogId default_log_id_; +}; +#endif + +// Configure logging based on ANDROID_LOG_TAGS environment variable. +// We need to parse a string that looks like +// +// *:v jdwp:d dalvikvm:d dalvikvm-gc:i dalvikvmi:i +// +// The tag (or '*' for the global level) comes first, followed by a colon and a +// letter indicating the minimum priority level we're expected to log. This can +// be used to reveal or conceal logs with specific tags. +extern void InitLogging(char* argv[], LogFunction&& logger); + +// Configures logging using the default logger (logd for the device, stderr for +// the host). +extern void InitLogging(char* argv[]); + +// Replace the current logger. +extern void SetLogger(LogFunction&& logger); + +// Get the minimum severity level for logging. +extern LogSeverity GetMinimumLogSeverity(); + +class ErrnoRestorer { + public: + ErrnoRestorer() + : saved_errno_(errno) { + } + + ~ErrnoRestorer() { + errno = saved_errno_; + } + + // Allow this object to be used as part of && operation. + operator bool() const { + return true; + } + + private: + const int saved_errno_; + + DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer); +}; + +// Logs a message to logcat on Android otherwise to stderr. If the severity is +// FATAL it also causes an abort. For example: +// +// LOG(FATAL) << "We didn't expect to reach here"; +#define LOG(severity) LOG_TO(DEFAULT, severity) + +// Logs a message to logcat with the specified log ID on Android otherwise to +// stderr. If the severity is FATAL it also causes an abort. +// Use an if-else statement instead of just an if statement here. So if there is a +// else statement after LOG() macro, it won't bind to the if statement in the macro. +// do-while(0) statement doesn't work here. Because we need to support << operator +// following the macro, like "LOG(DEBUG) << xxx;". +#define LOG_TO(dest, severity) \ + UNLIKELY(::android::base::severity >= ::android::base::GetMinimumLogSeverity()) && \ + ::android::base::ErrnoRestorer() && \ + ::android::base::LogMessage(__FILE__, __LINE__, \ + ::android::base::dest, \ + ::android::base::severity, -1).stream() + +// A variant of LOG that also logs the current errno value. To be used when +// library calls fail. +#define PLOG(severity) PLOG_TO(DEFAULT, severity) + +// Behaves like PLOG, but logs to the specified log ID. +#define PLOG_TO(dest, severity) \ + UNLIKELY(::android::base::severity >= ::android::base::GetMinimumLogSeverity()) && \ + ::android::base::ErrnoRestorer() && \ + ::android::base::LogMessage(__FILE__, __LINE__, \ + ::android::base::dest, \ + ::android::base::severity, errno).stream() + +// Marker that code is yet to be implemented. +#define UNIMPLEMENTED(level) \ + LOG(level) << __PRETTY_FUNCTION__ << " unimplemented " + +// Check whether condition x holds and LOG(FATAL) if not. The value of the +// expression x is only evaluated once. Extra logging can be appended using << +// after. For example: +// +// CHECK(false == true) results in a log message of +// "Check failed: false == true". +#define CHECK(x) \ + LIKELY((x)) || \ + ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \ + ::android::base::FATAL, -1).stream() \ + << "Check failed: " #x << " " + +// Helper for CHECK_xx(x,y) macros. +#define CHECK_OP(LHS, RHS, OP) \ + for (auto _values = ::android::base::MakeEagerEvaluator(LHS, RHS); \ + UNLIKELY(!(_values.lhs OP _values.rhs)); \ + /* empty */) \ + ::android::base::LogMessage(__FILE__, __LINE__, ::android::base::DEFAULT, \ + ::android::base::FATAL, -1).stream() \ + << "Check failed: " << #LHS << " " << #OP << " " << #RHS \ + << " (" #LHS "=" << _values.lhs << ", " #RHS "=" << _values.rhs << ") " + +// Check whether a condition holds between x and y, LOG(FATAL) if not. The value +// of the expressions x and y is evaluated once. Extra logging can be appended +// using << after. For example: +// +// CHECK_NE(0 == 1, false) results in +// "Check failed: false != false (0==1=false, false=false) ". +#define CHECK_EQ(x, y) CHECK_OP(x, y, == ) +#define CHECK_NE(x, y) CHECK_OP(x, y, != ) +#define CHECK_LE(x, y) CHECK_OP(x, y, <= ) +#define CHECK_LT(x, y) CHECK_OP(x, y, < ) +#define CHECK_GE(x, y) CHECK_OP(x, y, >= ) +#define CHECK_GT(x, y) CHECK_OP(x, y, > ) + +// Helper for CHECK_STRxx(s1,s2) macros. +#define CHECK_STROP(s1, s2, sense) \ + if (LIKELY((strcmp(s1, s2) == 0) == sense)) \ + ; \ + else \ + LOG(FATAL) << "Check failed: " \ + << "\"" << s1 << "\"" \ + << (sense ? " == " : " != ") << "\"" << s2 << "\"" + +// Check for string (const char*) equality between s1 and s2, LOG(FATAL) if not. +#define CHECK_STREQ(s1, s2) CHECK_STROP(s1, s2, true) +#define CHECK_STRNE(s1, s2) CHECK_STROP(s1, s2, false) + +// Perform the pthread function call(args), LOG(FATAL) on error. +#define CHECK_PTHREAD_CALL(call, args, what) \ + do { \ + int rc = call args; \ + if (rc != 0) { \ + errno = rc; \ + PLOG(FATAL) << #call << " failed for " << what; \ + } \ + } while (false) + +// CHECK that can be used in a constexpr function. For example: +// +// constexpr int half(int n) { +// return +// DCHECK_CONSTEXPR(n >= 0, , 0) +// CHECK_CONSTEXPR((n & 1) == 0), +// << "Extra debugging output: n = " << n, 0) +// n / 2; +// } +#define CHECK_CONSTEXPR(x, out, dummy) \ + (UNLIKELY(!(x))) \ + ? (LOG(FATAL) << "Check failed: " << #x out, dummy) \ + : + +// DCHECKs are debug variants of CHECKs only enabled in debug builds. Generally +// CHECK should be used unless profiling identifies a CHECK as being in +// performance critical code. +#if defined(NDEBUG) +static constexpr bool kEnableDChecks = false; +#else +static constexpr bool kEnableDChecks = true; +#endif + +#define DCHECK(x) \ + if (::android::base::kEnableDChecks) CHECK(x) +#define DCHECK_EQ(x, y) \ + if (::android::base::kEnableDChecks) CHECK_EQ(x, y) +#define DCHECK_NE(x, y) \ + if (::android::base::kEnableDChecks) CHECK_NE(x, y) +#define DCHECK_LE(x, y) \ + if (::android::base::kEnableDChecks) CHECK_LE(x, y) +#define DCHECK_LT(x, y) \ + if (::android::base::kEnableDChecks) CHECK_LT(x, y) +#define DCHECK_GE(x, y) \ + if (::android::base::kEnableDChecks) CHECK_GE(x, y) +#define DCHECK_GT(x, y) \ + if (::android::base::kEnableDChecks) CHECK_GT(x, y) +#define DCHECK_STREQ(s1, s2) \ + if (::android::base::kEnableDChecks) CHECK_STREQ(s1, s2) +#define DCHECK_STRNE(s1, s2) \ + if (::android::base::kEnableDChecks) CHECK_STRNE(s1, s2) +#if defined(NDEBUG) +#define DCHECK_CONSTEXPR(x, out, dummy) +#else +#define DCHECK_CONSTEXPR(x, out, dummy) CHECK_CONSTEXPR(x, out, dummy) +#endif + +// Temporary class created to evaluate the LHS and RHS, used with +// MakeEagerEvaluator to infer the types of LHS and RHS. +template +struct EagerEvaluator { + EagerEvaluator(LHS l, RHS r) : lhs(l), rhs(r) { + } + LHS lhs; + RHS rhs; +}; + +// Helper function for CHECK_xx. +template +static inline EagerEvaluator MakeEagerEvaluator(LHS lhs, RHS rhs) { + return EagerEvaluator(lhs, rhs); +} + +// Explicitly instantiate EagerEvalue for pointers so that char*s aren't treated +// as strings. To compare strings use CHECK_STREQ and CHECK_STRNE. We rely on +// signed/unsigned warnings to protect you against combinations not explicitly +// listed below. +#define EAGER_PTR_EVALUATOR(T1, T2) \ + template <> \ + struct EagerEvaluator { \ + EagerEvaluator(T1 l, T2 r) \ + : lhs(reinterpret_cast(l)), \ + rhs(reinterpret_cast(r)) { \ + } \ + const void* lhs; \ + const void* rhs; \ + } +EAGER_PTR_EVALUATOR(const char*, const char*); +EAGER_PTR_EVALUATOR(const char*, char*); +EAGER_PTR_EVALUATOR(char*, const char*); +EAGER_PTR_EVALUATOR(char*, char*); +EAGER_PTR_EVALUATOR(const unsigned char*, const unsigned char*); +EAGER_PTR_EVALUATOR(const unsigned char*, unsigned char*); +EAGER_PTR_EVALUATOR(unsigned char*, const unsigned char*); +EAGER_PTR_EVALUATOR(unsigned char*, unsigned char*); +EAGER_PTR_EVALUATOR(const signed char*, const signed char*); +EAGER_PTR_EVALUATOR(const signed char*, signed char*); +EAGER_PTR_EVALUATOR(signed char*, const signed char*); +EAGER_PTR_EVALUATOR(signed char*, signed char*); + +// Data for the log message, not stored in LogMessage to avoid increasing the +// stack size. +class LogMessageData; + +// A LogMessage is a temporarily scoped object used by LOG and the unlikely part +// of a CHECK. The destructor will abort if the severity is FATAL. +class LogMessage { + public: + LogMessage(const char* file, unsigned int line, LogId id, + LogSeverity severity, int error); + + ~LogMessage(); + + // Returns the stream associated with the message, the LogMessage performs + // output when it goes out of scope. + std::ostream& stream(); + + // The routine that performs the actual logging. + static void LogLine(const char* file, unsigned int line, LogId id, + LogSeverity severity, const char* msg); + + private: + const std::unique_ptr data_; + + DISALLOW_COPY_AND_ASSIGN(LogMessage); +}; + +// Allows to temporarily change the minimum severity level for logging. +class ScopedLogSeverity { + public: + explicit ScopedLogSeverity(LogSeverity level); + ~ScopedLogSeverity(); + + private: + LogSeverity old_; +}; + +} // namespace base +} // namespace android + +#endif // ANDROID_BASE_LOGGING_H diff --git a/app/src/main/jni/crash_dump/libbase/include/android-base/macros.h b/app/src/main/jni/crash_dump/libbase/include/android-base/macros.h new file mode 100644 index 000000000..913a9a03e --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/include/android-base/macros.h @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BASE_MACROS_H +#define ANDROID_BASE_MACROS_H + +#include // for size_t +#include // for TEMP_FAILURE_RETRY + +// bionic and glibc both have TEMP_FAILURE_RETRY, but eg Mac OS' libc doesn't. +#ifndef TEMP_FAILURE_RETRY +#define TEMP_FAILURE_RETRY(exp) \ + ({ \ + decltype(exp) _rc; \ + do { \ + _rc = (exp); \ + } while (_rc == -1 && errno == EINTR); \ + _rc; \ + }) +#endif + +// A macro to disallow the copy constructor and operator= functions +// This must be placed in the private: declarations for a class. +// +// For disallowing only assign or copy, delete the relevant operator or +// constructor, for example: +// void operator=(const TypeName&) = delete; +// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken +// semantically, one should either use disallow both or neither. Try to +// avoid these in new code. +// +// When building with C++11 toolchains, just use the language support +// for explicitly deleted methods. +#if __cplusplus >= 201103L +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&) = delete; \ + void operator=(const TypeName&) = delete +#else +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) +#endif + +// A macro to disallow all the implicit constructors, namely the +// default constructor, copy constructor and operator= functions. +// +// This should be used in the private: declarations for a class +// that wants to prevent anyone from instantiating it. This is +// especially useful for classes containing only static methods. +#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ + TypeName(); \ + DISALLOW_COPY_AND_ASSIGN(TypeName) + +// The arraysize(arr) macro returns the # of elements in an array arr. +// The expression is a compile-time constant, and therefore can be +// used in defining new arrays, for example. If you use arraysize on +// a pointer by mistake, you will get a compile-time error. +// +// One caveat is that arraysize() doesn't accept any array of an +// anonymous type or a type defined inside a function. In these rare +// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is +// due to a limitation in C++'s template system. The limitation might +// eventually be removed, but it hasn't happened yet. + +// This template function declaration is used in defining arraysize. +// Note that the function doesn't need an implementation, as we only +// use its type. +template +char(&ArraySizeHelper(T(&array)[N]))[N]; // NOLINT(readability/casting) + +#define arraysize(array) (sizeof(ArraySizeHelper(array))) + +// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize, +// but can be used on anonymous types or types defined inside +// functions. It's less safe than arraysize as it accepts some +// (although not all) pointers. Therefore, you should use arraysize +// whenever possible. +// +// The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type +// size_t. +// +// ARRAYSIZE_UNSAFE catches a few type errors. If you see a compiler error +// +// "warning: division by zero in ..." +// +// when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer. +// You should only use ARRAYSIZE_UNSAFE on statically allocated arrays. +// +// The following comments are on the implementation details, and can +// be ignored by the users. +// +// ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in +// the array) and sizeof(*(arr)) (the # of bytes in one array +// element). If the former is divisible by the latter, perhaps arr is +// indeed an array, in which case the division result is the # of +// elements in the array. Otherwise, arr cannot possibly be an array, +// and we generate a compiler error to prevent the code from +// compiling. +// +// Since the size of bool is implementation-defined, we need to cast +// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final +// result has type size_t. +// +// This macro is not perfect as it wrongfully accepts certain +// pointers, namely where the pointer size is divisible by the pointee +// size. Since all our code has to go through a 32-bit compiler, +// where a pointer is 4 bytes, this means all pointers to a type whose +// size is 3 or greater than 4 will be (righteously) rejected. +#define ARRAYSIZE_UNSAFE(a) \ + ((sizeof(a) / sizeof(*(a))) / \ + static_cast(!(sizeof(a) % sizeof(*(a))))) + +#define LIKELY(x) __builtin_expect((x), true) +#define UNLIKELY(x) __builtin_expect((x), false) + +#define WARN_UNUSED __attribute__((warn_unused_result)) + +// A deprecated function to call to create a false use of the parameter, for +// example: +// int foo(int x) { UNUSED(x); return 10; } +// to avoid compiler warnings. Going forward we prefer ATTRIBUTE_UNUSED. +template +void UNUSED(const T&...) { +} + +// An attribute to place on a parameter to a function, for example: +// int foo(int x ATTRIBUTE_UNUSED) { return 10; } +// to avoid compiler warnings. +#define ATTRIBUTE_UNUSED __attribute__((__unused__)) + +// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through +// between switch labels: +// switch (x) { +// case 40: +// case 41: +// if (truth_is_out_there) { +// ++x; +// FALLTHROUGH_INTENDED; // Use instead of/along with annotations in +// // comments. +// } else { +// return x; +// } +// case 42: +// ... +// +// As shown in the example above, the FALLTHROUGH_INTENDED macro should be +// followed by a semicolon. It is designed to mimic control-flow statements +// like 'break;', so it can be placed in most places where 'break;' can, but +// only if there are no statements on the execution path between it and the +// next switch label. +// +// When compiled with clang in C++11 mode, the FALLTHROUGH_INTENDED macro is +// expanded to [[clang::fallthrough]] attribute, which is analysed when +// performing switch labels fall-through diagnostic ('-Wimplicit-fallthrough'). +// See clang documentation on language extensions for details: +// http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough +// +// When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no +// effect on diagnostics. +// +// In either case this macro has no effect on runtime behavior and performance +// of code. +#if defined(__clang__) && __cplusplus >= 201103L && defined(__has_warning) +#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") +#define FALLTHROUGH_INTENDED [[clang::fallthrough]] // NOLINT +#endif +#endif + +#ifndef FALLTHROUGH_INTENDED +#define FALLTHROUGH_INTENDED \ + do { \ + } while (0) +#endif + +#endif // ANDROID_BASE_MACROS_H diff --git a/app/src/main/jni/crash_dump/libbase/include/android-base/memory.h b/app/src/main/jni/crash_dump/libbase/include/android-base/memory.h new file mode 100644 index 000000000..3a2f8fad6 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/include/android-base/memory.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BASE_MEMORY_H +#define ANDROID_BASE_MEMORY_H + +namespace android { +namespace base { + +// Use packed structures for access to unaligned data on targets with alignment +// restrictions. The compiler will generate appropriate code to access these +// structures without generating alignment exceptions. +template +static inline T get_unaligned(const T* address) { + struct unaligned { + T v; + } __attribute__((packed)); + const unaligned* p = reinterpret_cast(address); + return p->v; +} + +template +static inline void put_unaligned(T* address, T v) { + struct unaligned { + T v; + } __attribute__((packed)); + unaligned* p = reinterpret_cast(address); + p->v = v; +} + +} // namespace base +} // namespace android + +#endif // ANDROID_BASE_MEMORY_H diff --git a/app/src/main/jni/crash_dump/libbase/include/android-base/parseint.h b/app/src/main/jni/crash_dump/libbase/include/android-base/parseint.h new file mode 100644 index 000000000..ed75e2d48 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/include/android-base/parseint.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BASE_PARSEINT_H +#define ANDROID_BASE_PARSEINT_H + +#include +#include + +#include + +namespace android { +namespace base { + +// Parses the unsigned decimal integer in the string 's' and sets 'out' to +// that value. Optionally allows the caller to define a 'max' beyond which +// otherwise valid values will be rejected. Returns boolean success. +template +bool ParseUint(const char* s, T* out, + T max = std::numeric_limits::max()) { + int base = (s[0] == '0' && s[1] == 'x') ? 16 : 10; + errno = 0; + char* end; + unsigned long long int result = strtoull(s, &end, base); + if (errno != 0 || s == end || *end != '\0') { + return false; + } + if (max < result) { + return false; + } + *out = static_cast(result); + return true; +} + +// Parses the signed decimal integer in the string 's' and sets 'out' to +// that value. Optionally allows the caller to define a 'min' and 'max +// beyond which otherwise valid values will be rejected. Returns boolean +// success. +template +bool ParseInt(const char* s, T* out, + T min = std::numeric_limits::min(), + T max = std::numeric_limits::max()) { + int base = (s[0] == '0' && s[1] == 'x') ? 16 : 10; + errno = 0; + char* end; + long long int result = strtoll(s, &end, base); + if (errno != 0 || s == end || *end != '\0') { + return false; + } + if (result < min || max < result) { + return false; + } + *out = static_cast(result); + return true; +} + +} // namespace base +} // namespace android + +#endif // ANDROID_BASE_PARSEINT_H diff --git a/app/src/main/jni/crash_dump/libbase/include/android-base/parsenetaddress.h b/app/src/main/jni/crash_dump/libbase/include/android-base/parsenetaddress.h new file mode 100644 index 000000000..b4ac0256b --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/include/android-base/parsenetaddress.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BASE_PARSENETADDRESS_H +#define ANDROID_BASE_PARSENETADDRESS_H + +#include + +namespace android { +namespace base { + +// Parses |address| into |host| and |port|. +// +// If |address| doesn't contain a port number, the default value is taken from +// |port|. If |canonical_address| is non-null it will be set to "host:port" or +// "[host]:port" as appropriate. +// +// On failure, returns false and fills |error|. +bool ParseNetAddress(const std::string& address, std::string* host, int* port, + std::string* canonical_address, std::string* error); + +} // namespace base +} // namespace android + +#endif // ANDROID_BASE_PARSENETADDRESS_H diff --git a/app/src/main/jni/crash_dump/libbase/include/android-base/stringprintf.h b/app/src/main/jni/crash_dump/libbase/include/android-base/stringprintf.h new file mode 100644 index 000000000..cf666abe0 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/include/android-base/stringprintf.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BASE_STRINGPRINTF_H +#define ANDROID_BASE_STRINGPRINTF_H + +#include +#include + +namespace android { +namespace base { + +// These printf-like functions are implemented in terms of vsnprintf, so they +// use the same attribute for compile-time format string checking. On Windows, +// if the mingw version of vsnprintf is used, use `gnu_printf' which allows z +// in %zd and PRIu64 (and related) to be recognized by the compile-time +// checking. +#define FORMAT_ARCHETYPE __printf__ +#ifdef __USE_MINGW_ANSI_STDIO +#if __USE_MINGW_ANSI_STDIO +#undef FORMAT_ARCHETYPE +#define FORMAT_ARCHETYPE gnu_printf +#endif +#endif + +// Returns a string corresponding to printf-like formatting of the arguments. +std::string StringPrintf(const char* fmt, ...) + __attribute__((__format__(FORMAT_ARCHETYPE, 1, 2))); + +// Appends a printf-like formatting of the arguments to 'dst'. +void StringAppendF(std::string* dst, const char* fmt, ...) + __attribute__((__format__(FORMAT_ARCHETYPE, 2, 3))); + +// Appends a printf-like formatting of the arguments to 'dst'. +void StringAppendV(std::string* dst, const char* format, va_list ap) + __attribute__((__format__(FORMAT_ARCHETYPE, 2, 0))); + +#undef FORMAT_ARCHETYPE + +} // namespace base +} // namespace android + +#endif // ANDROID_BASE_STRINGPRINTF_H diff --git a/app/src/main/jni/crash_dump/libbase/include/android-base/strings.h b/app/src/main/jni/crash_dump/libbase/include/android-base/strings.h new file mode 100644 index 000000000..69781cd40 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/include/android-base/strings.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BASE_STRINGS_H +#define ANDROID_BASE_STRINGS_H + +#include +#include +#include + +namespace android { +namespace base { + +// Splits a string into a vector of strings. +// +// The string is split at each occurrence of a character in delimiters. +// +// The empty string is not a valid delimiter list. +std::vector Split(const std::string& s, + const std::string& delimiters); + +// Trims whitespace off both ends of the given string. +std::string Trim(const std::string& s); + +// Joins a container of things into a single string, using the given separator. +template +std::string Join(const ContainerT& things, SeparatorT separator) { + if (things.empty()) { + return ""; + } + + std::ostringstream result; + result << *things.begin(); + for (auto it = std::next(things.begin()); it != things.end(); ++it) { + result << separator << *it; + } + return result.str(); +} + +// We instantiate the common cases in strings.cpp. +extern template std::string Join(const std::vector&, char); +extern template std::string Join(const std::vector&, char); +extern template std::string Join(const std::vector&, const std::string&); +extern template std::string Join(const std::vector&, const std::string&); + +// Tests whether 's' starts with 'prefix'. +bool StartsWith(const std::string& s, const char* prefix); + +// Tests whether 's' ends with 'suffix'. +bool EndsWith(const std::string& s, const char* suffix); + +} // namespace base +} // namespace android + +#endif // ANDROID_BASE_STRINGS_H diff --git a/app/src/main/jni/crash_dump/libbase/include/android-base/test_utils.h b/app/src/main/jni/crash_dump/libbase/include/android-base/test_utils.h new file mode 100644 index 000000000..4ea3c8e48 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/include/android-base/test_utils.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BASE_TEST_UTILS_H +#define ANDROID_BASE_TEST_UTILS_H + +#include + +#include + +class TemporaryFile { + public: + TemporaryFile(); + ~TemporaryFile(); + + int fd; + char path[1024]; + + private: + void init(const std::string& tmp_dir); + + DISALLOW_COPY_AND_ASSIGN(TemporaryFile); +}; + +class TemporaryDir { + public: + TemporaryDir(); + ~TemporaryDir(); + + char path[1024]; + + private: + bool init(const std::string& tmp_dir); + + DISALLOW_COPY_AND_ASSIGN(TemporaryDir); +}; + +#endif // ANDROID_BASE_TEST_UTILS_H diff --git a/app/src/main/jni/crash_dump/libbase/include/android-base/thread_annotations.h b/app/src/main/jni/crash_dump/libbase/include/android-base/thread_annotations.h new file mode 100644 index 000000000..24221024c --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/include/android-base/thread_annotations.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BASE_THREAD_ANNOTATIONS_H +#define ANDROID_BASE_THREAD_ANNOTATIONS_H + +#if defined(__SUPPORT_TS_ANNOTATION__) || defined(__clang__) +#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#define CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) + +#define SCOPED_CAPABILITY \ + THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) + +#define GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) + +#define PT_GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) + +#define ACQUIRED_BEFORE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) + +#define ACQUIRED_AFTER(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) + +#define REQUIRES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define REQUIRES_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) + +#define ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) + +#define ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) + +#define RELEASE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) + +#define RELEASE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) + +#define TRY_ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) + +#define TRY_ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) + +#define EXCLUDES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) + +#define ASSERT_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) + +#define ASSERT_SHARED_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) + +#define RETURN_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) + +#define NO_THREAD_SAFETY_ANALYSIS \ + THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) + +#endif // ANDROID_BASE_THREAD_ANNOTATIONS_H diff --git a/app/src/main/jni/crash_dump/libbase/include/android-base/unique_fd.h b/app/src/main/jni/crash_dump/libbase/include/android-base/unique_fd.h new file mode 100644 index 000000000..869e60f58 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/include/android-base/unique_fd.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BASE_UNIQUE_FD_H +#define ANDROID_BASE_UNIQUE_FD_H + +#include + +// DO NOT INCLUDE OTHER LIBBASE HEADERS! +// This file gets used in libbinder, and libbinder is used everywhere. +// Including other headers from libbase frequently results in inclusion of +// android-base/macros.h, which causes macro collisions. + +// Container for a file descriptor that automatically closes the descriptor as +// it goes out of scope. +// +// unique_fd ufd(open("/some/path", "r")); +// if (ufd.get() == -1) return error; +// +// // Do something useful, possibly including 'return'. +// +// return 0; // Descriptor is closed for you. +// +// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help +// you find this class if you're searching for one of those names. +namespace android { +namespace base { + +struct DefaultCloser { + static void Close(int fd) { + // Even if close(2) fails with EINTR, the fd will have been closed. + // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone + // else's fd. + // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html + ::close(fd); + } +}; + +template +class unique_fd_impl final { + public: + unique_fd_impl() : value_(-1) {} + + explicit unique_fd_impl(int value) : value_(value) {} + ~unique_fd_impl() { clear(); } + + unique_fd_impl(unique_fd_impl&& other) : value_(other.release()) {} + unique_fd_impl& operator=(unique_fd_impl&& s) { + reset(s.release()); + return *this; + } + + void reset(int new_value) { + if (value_ != -1) { + Closer::Close(value_); + } + value_ = new_value; + } + + void clear() { + reset(-1); + } + + int get() const { return value_; } + operator int() const { return get(); } + + int release() __attribute__((warn_unused_result)) { + int ret = value_; + value_ = -1; + return ret; + } + + private: + int value_; + + unique_fd_impl(const unique_fd_impl&); + void operator=(const unique_fd_impl&); +}; + +using unique_fd = unique_fd_impl; + +} // namespace base +} // namespace android + +#endif // ANDROID_BASE_UNIQUE_FD_H diff --git a/app/src/main/jni/crash_dump/libbase/include/android-base/utf8.h b/app/src/main/jni/crash_dump/libbase/include/android-base/utf8.h new file mode 100644 index 000000000..2d5a6f6d7 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/include/android-base/utf8.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_BASE_UTF8_H +#define ANDROID_BASE_UTF8_H + +#ifdef _WIN32 +#include +#else +// Bring in prototypes for standard APIs so that we can import them into the utf8 namespace. +#include // open +#include // unlink +#endif + +namespace android { +namespace base { + +// Only available on Windows because this is only needed on Windows. +#ifdef _WIN32 +// Convert size number of UTF-16 wchar_t's to UTF-8. Returns whether the +// conversion was done successfully. +bool WideToUTF8(const wchar_t* utf16, const size_t size, std::string* utf8); + +// Convert a NULL-terminated string of UTF-16 characters to UTF-8. Returns +// whether the conversion was done successfully. +bool WideToUTF8(const wchar_t* utf16, std::string* utf8); + +// Convert a UTF-16 std::wstring (including any embedded NULL characters) to +// UTF-8. Returns whether the conversion was done successfully. +bool WideToUTF8(const std::wstring& utf16, std::string* utf8); + +// Convert size number of UTF-8 char's to UTF-16. Returns whether the conversion +// was done successfully. +bool UTF8ToWide(const char* utf8, const size_t size, std::wstring* utf16); + +// Convert a NULL-terminated string of UTF-8 characters to UTF-16. Returns +// whether the conversion was done successfully. +bool UTF8ToWide(const char* utf8, std::wstring* utf16); + +// Convert a UTF-8 std::string (including any embedded NULL characters) to +// UTF-16. Returns whether the conversion was done successfully. +bool UTF8ToWide(const std::string& utf8, std::wstring* utf16); +#endif + +// The functions in the utf8 namespace take UTF-8 strings. For Windows, these +// are wrappers, for non-Windows these just expose existing APIs. To call these +// functions, use: +// +// // anonymous namespace to avoid conflict with existing open(), unlink(), etc. +// namespace { +// // Import functions into anonymous namespace. +// using namespace android::base::utf8; +// +// void SomeFunction(const char* name) { +// int fd = open(name, ...); // Calls android::base::utf8::open(). +// ... +// unlink(name); // Calls android::base::utf8::unlink(). +// } +// } +namespace utf8 { + +#ifdef _WIN32 +int open(const char* name, int flags, ...); +int unlink(const char* name); +#else +using ::open; +using ::unlink; +#endif + +} // namespace utf8 +} // namespace base +} // namespace android + +#endif // ANDROID_BASE_UTF8_H diff --git a/app/src/main/jni/crash_dump/libbase/logging.cpp b/app/src/main/jni/crash_dump/libbase/logging.cpp new file mode 100644 index 000000000..174187149 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/logging.cpp @@ -0,0 +1,428 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef _WIN32 +#include +#endif + +#include "android-base/logging.h" + +#include + +// For getprogname(3) or program_invocation_short_name. +#if defined(__ANDROID__) || defined(__APPLE__) +#include +#elif defined(__GLIBC__) +#include +#endif + +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include "android-base/macros.h" +#include "android-base/strings.h" +#include "cutils/threads.h" + +// Headers for LogMessage::LogLine. +#ifdef __ANDROID__ +#include +#include "cutils/log.h" +#else +#include +#include +#endif + +// For gettid. +#if defined(__APPLE__) +#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED +#include +#include +#include +#include +#include +#elif defined(__linux__) && !defined(__ANDROID__) +#include +#include +#elif defined(_WIN32) +#include +#endif + +#if defined(_WIN32) +typedef uint32_t thread_id; +#else +typedef pid_t thread_id; +#endif + +static thread_id GetThreadId() { +#if defined(__BIONIC__) + return gettid(); +#elif defined(__APPLE__) + return syscall(SYS_thread_selfid); +#elif defined(__linux__) + return syscall(__NR_gettid); +#elif defined(_WIN32) + return GetCurrentThreadId(); +#endif +} + +namespace { +#ifndef _WIN32 +using std::mutex; +using std::lock_guard; + +#if defined(__GLIBC__) +const char* getprogname() { + return program_invocation_short_name; +} +#endif + +#else +const char* getprogname() { + static bool first = true; + static char progname[MAX_PATH] = {}; + + if (first) { + CHAR longname[MAX_PATH]; + DWORD nchars = GetModuleFileNameA(nullptr, longname, arraysize(longname)); + if ((nchars >= arraysize(longname)) || (nchars == 0)) { + // String truncation or some other error. + strcpy(progname, ""); + } else { + strcpy(progname, basename(longname)); + } + first = false; + } + + return progname; +} + +class mutex { + public: + mutex() { + InitializeCriticalSection(&critical_section_); + } + ~mutex() { + DeleteCriticalSection(&critical_section_); + } + + void lock() { + EnterCriticalSection(&critical_section_); + } + + void unlock() { + LeaveCriticalSection(&critical_section_); + } + + private: + CRITICAL_SECTION critical_section_; +}; + +template +class lock_guard { + public: + explicit lock_guard(LockT& lock) : lock_(lock) { + lock_.lock(); + } + + ~lock_guard() { + lock_.unlock(); + } + + private: + LockT& lock_; + + DISALLOW_COPY_AND_ASSIGN(lock_guard); +}; +#endif +} // namespace + +namespace android { +namespace base { + +static auto& logging_lock = *new mutex(); + +#ifdef __ANDROID__ +static auto& gLogger = *new LogFunction(LogdLogger()); +#else +static auto& gLogger = *new LogFunction(StderrLogger); +#endif + +static bool gInitialized = false; +static LogSeverity gMinimumLogSeverity = INFO; +static auto& gProgramInvocationName = *new std::unique_ptr(); + +LogSeverity GetMinimumLogSeverity() { + return gMinimumLogSeverity; +} + +static const char* ProgramInvocationName() { + if (gProgramInvocationName == nullptr) { + gProgramInvocationName.reset(new std::string(getprogname())); + } + + return gProgramInvocationName->c_str(); +} + +void StderrLogger(LogId, LogSeverity severity, const char*, const char* file, + unsigned int line, const char* message) { + static const char log_characters[] = "VDIWEF"; + static_assert(arraysize(log_characters) - 1 == FATAL + 1, + "Mismatch in size of log_characters and values in LogSeverity"); + char severity_char = log_characters[severity]; + fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n", ProgramInvocationName(), + severity_char, getpid(), GetThreadId(), file, line, message); +} + + +#ifdef __ANDROID__ +LogdLogger::LogdLogger(LogId default_log_id) : default_log_id_(default_log_id) { +} + +static const android_LogPriority kLogSeverityToAndroidLogPriority[] = { + ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, + ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, +}; +static_assert(arraysize(kLogSeverityToAndroidLogPriority) == FATAL + 1, + "Mismatch in size of kLogSeverityToAndroidLogPriority and values " + "in LogSeverity"); + +static const log_id kLogIdToAndroidLogId[] = { + LOG_ID_MAX, LOG_ID_MAIN, LOG_ID_SYSTEM, +}; +static_assert(arraysize(kLogIdToAndroidLogId) == SYSTEM + 1, + "Mismatch in size of kLogIdToAndroidLogId and values in LogId"); + +void LogdLogger::operator()(LogId id, LogSeverity severity, const char* tag, + const char* file, unsigned int line, + const char* message) { + int priority = kLogSeverityToAndroidLogPriority[severity]; + if (id == DEFAULT) { + id = default_log_id_; + } + + log_id lg_id = kLogIdToAndroidLogId[id]; + + if (priority == ANDROID_LOG_FATAL) { + __android_log_buf_print(lg_id, priority, tag, "%s:%u] %s", file, line, + message); + } else { + __android_log_buf_print(lg_id, priority, tag, "%s", message); + } +} +#endif + +void InitLogging(char* argv[], LogFunction&& logger) { + SetLogger(std::forward(logger)); + InitLogging(argv); +} + +void InitLogging(char* argv[]) { + if (gInitialized) { + return; + } + + gInitialized = true; + + // Stash the command line for later use. We can use /proc/self/cmdline on + // Linux to recover this, but we don't have that luxury on the Mac/Windows, + // and there are a couple of argv[0] variants that are commonly used. + if (argv != nullptr) { + gProgramInvocationName.reset(new std::string(basename(argv[0]))); + } + + const char* tags = getenv("ANDROID_LOG_TAGS"); + if (tags == nullptr) { + return; + } + + std::vector specs = Split(tags, " "); + for (size_t i = 0; i < specs.size(); ++i) { + // "tag-pattern:[vdiwefs]" + std::string spec(specs[i]); + if (spec.size() == 3 && StartsWith(spec, "*:")) { + switch (spec[2]) { + case 'v': + gMinimumLogSeverity = VERBOSE; + continue; + case 'd': + gMinimumLogSeverity = DEBUG; + continue; + case 'i': + gMinimumLogSeverity = INFO; + continue; + case 'w': + gMinimumLogSeverity = WARNING; + continue; + case 'e': + gMinimumLogSeverity = ERROR; + continue; + case 'f': + gMinimumLogSeverity = FATAL; + continue; + // liblog will even suppress FATAL if you say 's' for silent, but that's + // crazy! + case 's': + gMinimumLogSeverity = FATAL; + continue; + } + } + LOG(FATAL) << "unsupported '" << spec << "' in ANDROID_LOG_TAGS (" << tags + << ")"; + } +} + +void SetLogger(LogFunction&& logger) { + lock_guard lock(logging_lock); + gLogger = std::move(logger); +} + +static const char* GetFileBasename(const char* file) { + // We can't use basename(3) even on Unix because the Mac doesn't + // have a non-modifying basename. + const char* last_slash = strrchr(file, '/'); + if (last_slash != nullptr) { + return last_slash + 1; + } +#if defined(_WIN32) + const char* last_backslash = strrchr(file, '\\'); + if (last_backslash != nullptr) { + return last_backslash + 1; + } +#endif + return file; +} + +// This indirection greatly reduces the stack impact of having lots of +// checks/logging in a function. +class LogMessageData { + public: + LogMessageData(const char* file, unsigned int line, LogId id, + LogSeverity severity, int error) + : file_(GetFileBasename(file)), + line_number_(line), + id_(id), + severity_(severity), + error_(error) { + } + + const char* GetFile() const { + return file_; + } + + unsigned int GetLineNumber() const { + return line_number_; + } + + LogSeverity GetSeverity() const { + return severity_; + } + + LogId GetId() const { + return id_; + } + + int GetError() const { + return error_; + } + + std::ostream& GetBuffer() { + return buffer_; + } + + std::string ToString() const { + return buffer_.str(); + } + + private: + std::ostringstream buffer_; + const char* const file_; + const unsigned int line_number_; + const LogId id_; + const LogSeverity severity_; + const int error_; + + DISALLOW_COPY_AND_ASSIGN(LogMessageData); +}; + +LogMessage::LogMessage(const char* file, unsigned int line, LogId id, + LogSeverity severity, int error) + : data_(new LogMessageData(file, line, id, severity, error)) { +} + +LogMessage::~LogMessage() { + // Finish constructing the message. + if (data_->GetError() != -1) { + data_->GetBuffer() << ": " << strerror(data_->GetError()); + } + std::string msg(data_->ToString()); + + { + // Do the actual logging with the lock held. + lock_guard lock(logging_lock); + if (msg.find('\n') == std::string::npos) { + LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetId(), + data_->GetSeverity(), msg.c_str()); + } else { + msg += '\n'; + size_t i = 0; + while (i < msg.size()) { + size_t nl = msg.find('\n', i); + msg[nl] = '\0'; + LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetId(), + data_->GetSeverity(), &msg[i]); + i = nl + 1; + } + } + } + + // Abort if necessary. + if (data_->GetSeverity() == FATAL) { +#ifdef __ANDROID__ + android_set_abort_message(msg.c_str()); +#endif + abort(); + } +} + +std::ostream& LogMessage::stream() { + return data_->GetBuffer(); +} + +void LogMessage::LogLine(const char* file, unsigned int line, LogId id, + LogSeverity severity, const char* message) { + const char* tag = ProgramInvocationName(); + gLogger(id, severity, tag, file, line, message); +} + +ScopedLogSeverity::ScopedLogSeverity(LogSeverity level) { + old_ = gMinimumLogSeverity; + gMinimumLogSeverity = level; +} + +ScopedLogSeverity::~ScopedLogSeverity() { + gMinimumLogSeverity = old_; +} + +} // namespace base +} // namespace android diff --git a/app/src/main/jni/crash_dump/libbase/logging_test.cpp b/app/src/main/jni/crash_dump/libbase/logging_test.cpp new file mode 100644 index 000000000..3de42b774 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/logging_test.cpp @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android-base/logging.h" + +#include + +#if defined(_WIN32) +#include +#endif + +#include +#include + +#include "android-base/file.h" +#include "android-base/stringprintf.h" +#include "android-base/test_utils.h" + +#include + +#ifdef __ANDROID__ +#define HOST_TEST(suite, name) TEST(suite, DISABLED_ ## name) +#else +#define HOST_TEST(suite, name) TEST(suite, name) +#endif + +class CapturedStderr { + public: + CapturedStderr() : old_stderr_(-1) { + init(); + } + + ~CapturedStderr() { + reset(); + } + + int fd() const { + return temp_file_.fd; + } + + private: + void init() { +#if defined(_WIN32) + // On Windows, stderr is often buffered, so make sure it is unbuffered so + // that we can immediately read back what was written to stderr. + ASSERT_EQ(0, setvbuf(stderr, NULL, _IONBF, 0)); +#endif + old_stderr_ = dup(STDERR_FILENO); + ASSERT_NE(-1, old_stderr_); + ASSERT_NE(-1, dup2(fd(), STDERR_FILENO)); + } + + void reset() { + ASSERT_NE(-1, dup2(old_stderr_, STDERR_FILENO)); + ASSERT_EQ(0, close(old_stderr_)); + // Note: cannot restore prior setvbuf() setting. + } + + TemporaryFile temp_file_; + int old_stderr_; +}; + +#if defined(_WIN32) +static void ExitSignalAbortHandler(int) { + _exit(3); +} +#endif + +static void SuppressAbortUI() { +#if defined(_WIN32) + // We really just want to call _set_abort_behavior(0, _CALL_REPORTFAULT) to + // suppress the Windows Error Reporting dialog box, but that API is not + // available in the OS-supplied C Runtime, msvcrt.dll, that we currently + // use (it is available in the Visual Studio C runtime). + // + // Instead, we setup a SIGABRT handler, which is called in abort() right + // before calling Windows Error Reporting. In the handler, we exit the + // process just like abort() does. + ASSERT_NE(SIG_ERR, signal(SIGABRT, ExitSignalAbortHandler)); +#endif +} + +TEST(logging, CHECK) { + ASSERT_DEATH({SuppressAbortUI(); CHECK(false);}, "Check failed: false "); + CHECK(true); + + ASSERT_DEATH({SuppressAbortUI(); CHECK_EQ(0, 1);}, "Check failed: 0 == 1 "); + CHECK_EQ(0, 0); + + ASSERT_DEATH({SuppressAbortUI(); CHECK_STREQ("foo", "bar");}, + R"(Check failed: "foo" == "bar")"); + CHECK_STREQ("foo", "foo"); + + // Test whether CHECK() and CHECK_STREQ() have a dangling if with no else. + bool flag = false; + if (true) + CHECK(true); + else + flag = true; + EXPECT_FALSE(flag) << "CHECK macro probably has a dangling if with no else"; + + flag = false; + if (true) + CHECK_STREQ("foo", "foo"); + else + flag = true; + EXPECT_FALSE(flag) << "CHECK_STREQ probably has a dangling if with no else"; +} + +std::string make_log_pattern(android::base::LogSeverity severity, + const char* message) { + static const char* log_characters = "VDIWEF"; + char log_char = log_characters[severity]; + std::string holder(__FILE__); + return android::base::StringPrintf( + "%c[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+ %s:[[:digit:]]+] %s", + log_char, basename(&holder[0]), message); +} + +TEST(logging, LOG) { + ASSERT_DEATH({SuppressAbortUI(); LOG(FATAL) << "foobar";}, "foobar"); + + // We can't usefully check the output of any of these on Windows because we + // don't have std::regex, but we can at least make sure we printed at least as + // many characters are in the log message. + { + CapturedStderr cap; + LOG(WARNING) << "foobar"; + ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET)); + + std::string output; + android::base::ReadFdToString(cap.fd(), &output); + ASSERT_GT(output.length(), strlen("foobar")); + +#if !defined(_WIN32) + std::regex message_regex( + make_log_pattern(android::base::WARNING, "foobar")); + ASSERT_TRUE(std::regex_search(output, message_regex)) << output; +#endif + } + + { + CapturedStderr cap; + LOG(INFO) << "foobar"; + ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET)); + + std::string output; + android::base::ReadFdToString(cap.fd(), &output); + ASSERT_GT(output.length(), strlen("foobar")); + +#if !defined(_WIN32) + std::regex message_regex( + make_log_pattern(android::base::INFO, "foobar")); + ASSERT_TRUE(std::regex_search(output, message_regex)) << output; +#endif + } + + { + CapturedStderr cap; + LOG(DEBUG) << "foobar"; + ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET)); + + std::string output; + android::base::ReadFdToString(cap.fd(), &output); + ASSERT_TRUE(output.empty()); + } + + { + android::base::ScopedLogSeverity severity(android::base::DEBUG); + CapturedStderr cap; + LOG(DEBUG) << "foobar"; + ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET)); + + std::string output; + android::base::ReadFdToString(cap.fd(), &output); + ASSERT_GT(output.length(), strlen("foobar")); + +#if !defined(_WIN32) + std::regex message_regex( + make_log_pattern(android::base::DEBUG, "foobar")); + ASSERT_TRUE(std::regex_search(output, message_regex)) << output; +#endif + } + + // Test whether LOG() saves and restores errno. + { + CapturedStderr cap; + errno = 12345; + LOG(INFO) << (errno = 67890); + EXPECT_EQ(12345, errno) << "errno was not restored"; + + ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET)); + + std::string output; + android::base::ReadFdToString(cap.fd(), &output); + EXPECT_NE(nullptr, strstr(output.c_str(), "67890")) << output; + +#if !defined(_WIN32) + std::regex message_regex( + make_log_pattern(android::base::INFO, "67890")); + ASSERT_TRUE(std::regex_search(output, message_regex)) << output; +#endif + } + + // Test whether LOG() has a dangling if with no else. + { + CapturedStderr cap; + + // Do the test two ways: once where we hypothesize that LOG()'s if + // will evaluate to true (when severity is high enough) and once when we + // expect it to evaluate to false (when severity is not high enough). + bool flag = false; + if (true) + LOG(INFO) << "foobar"; + else + flag = true; + + EXPECT_FALSE(flag) << "LOG macro probably has a dangling if with no else"; + + flag = false; + if (true) + LOG(VERBOSE) << "foobar"; + else + flag = true; + + EXPECT_FALSE(flag) << "LOG macro probably has a dangling if with no else"; + } +} + +TEST(logging, PLOG) { + { + CapturedStderr cap; + errno = ENOENT; + PLOG(INFO) << "foobar"; + ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET)); + + std::string output; + android::base::ReadFdToString(cap.fd(), &output); + ASSERT_GT(output.length(), strlen("foobar")); + +#if !defined(_WIN32) + std::regex message_regex(make_log_pattern( + android::base::INFO, "foobar: No such file or directory")); + ASSERT_TRUE(std::regex_search(output, message_regex)) << output; +#endif + } +} + +TEST(logging, UNIMPLEMENTED) { + { + CapturedStderr cap; + errno = ENOENT; + UNIMPLEMENTED(ERROR); + ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET)); + + std::string output; + android::base::ReadFdToString(cap.fd(), &output); + ASSERT_GT(output.length(), strlen("unimplemented")); + +#if !defined(_WIN32) + std::string expected_message = + android::base::StringPrintf("%s unimplemented ", __PRETTY_FUNCTION__); + std::regex message_regex( + make_log_pattern(android::base::ERROR, expected_message.c_str())); + ASSERT_TRUE(std::regex_search(output, message_regex)) << output; +#endif + } +} diff --git a/app/src/main/jni/crash_dump/libbase/parseint_test.cpp b/app/src/main/jni/crash_dump/libbase/parseint_test.cpp new file mode 100644 index 000000000..6a3ba316d --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/parseint_test.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android-base/parseint.h" + +#include + +TEST(parseint, signed_smoke) { + int i; + ASSERT_FALSE(android::base::ParseInt("x", &i)); + ASSERT_FALSE(android::base::ParseInt("123x", &i)); + + ASSERT_TRUE(android::base::ParseInt("123", &i)); + ASSERT_EQ(123, i); + ASSERT_TRUE(android::base::ParseInt("-123", &i)); + ASSERT_EQ(-123, i); + + short s; + ASSERT_TRUE(android::base::ParseInt("1234", &s)); + ASSERT_EQ(1234, s); + + ASSERT_TRUE(android::base::ParseInt("12", &i, 0, 15)); + ASSERT_EQ(12, i); + ASSERT_FALSE(android::base::ParseInt("-12", &i, 0, 15)); + ASSERT_FALSE(android::base::ParseInt("16", &i, 0, 15)); +} + +TEST(parseint, unsigned_smoke) { + unsigned int i; + ASSERT_FALSE(android::base::ParseUint("x", &i)); + ASSERT_FALSE(android::base::ParseUint("123x", &i)); + + ASSERT_TRUE(android::base::ParseUint("123", &i)); + ASSERT_EQ(123u, i); + ASSERT_FALSE(android::base::ParseUint("-123", &i)); + + unsigned short s; + ASSERT_TRUE(android::base::ParseUint("1234", &s)); + ASSERT_EQ(1234u, s); + + ASSERT_TRUE(android::base::ParseUint("12", &i, 15u)); + ASSERT_EQ(12u, i); + ASSERT_FALSE(android::base::ParseUint("-12", &i, 15u)); + ASSERT_FALSE(android::base::ParseUint("16", &i, 15u)); +} + +TEST(parseint, no_implicit_octal) { + int i; + ASSERT_TRUE(android::base::ParseInt("0123", &i)); + ASSERT_EQ(123, i); + + unsigned int u; + ASSERT_TRUE(android::base::ParseUint("0123", &u)); + ASSERT_EQ(123u, u); +} + +TEST(parseint, explicit_hex) { + int i; + ASSERT_TRUE(android::base::ParseInt("0x123", &i)); + ASSERT_EQ(0x123, i); + + unsigned int u; + ASSERT_TRUE(android::base::ParseUint("0x123", &u)); + ASSERT_EQ(0x123u, u); +} diff --git a/app/src/main/jni/crash_dump/libbase/parsenetaddress.cpp b/app/src/main/jni/crash_dump/libbase/parsenetaddress.cpp new file mode 100644 index 000000000..dd80f6da2 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/parsenetaddress.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android-base/parsenetaddress.h" + +#include + +#include "android-base/stringprintf.h" +#include "android-base/strings.h" + +namespace android { +namespace base { + +bool ParseNetAddress(const std::string& address, std::string* host, int* port, + std::string* canonical_address, std::string* error) { + host->clear(); + + bool ipv6 = true; + bool saw_port = false; + size_t colons = std::count(address.begin(), address.end(), ':'); + size_t dots = std::count(address.begin(), address.end(), '.'); + std::string port_str; + if (address[0] == '[') { + // [::1]:123 + if (address.rfind("]:") == std::string::npos) { + *error = StringPrintf("bad IPv6 address '%s'", address.c_str()); + return false; + } + *host = address.substr(1, (address.find("]:") - 1)); + port_str = address.substr(address.rfind("]:") + 2); + saw_port = true; + } else if (dots == 0 && colons >= 2 && colons <= 7) { + // ::1 + *host = address; + } else if (colons <= 1) { + // 1.2.3.4 or some.accidental.domain.com + ipv6 = false; + std::vector pieces = Split(address, ":"); + *host = pieces[0]; + if (pieces.size() > 1) { + port_str = pieces[1]; + saw_port = true; + } + } + + if (host->empty()) { + *error = StringPrintf("no host in '%s'", address.c_str()); + return false; + } + + if (saw_port) { + if (sscanf(port_str.c_str(), "%d", port) != 1 || *port <= 0 || + *port > 65535) { + *error = StringPrintf("bad port number '%s' in '%s'", port_str.c_str(), + address.c_str()); + return false; + } + } + + if (canonical_address != nullptr) { + *canonical_address = + StringPrintf(ipv6 ? "[%s]:%d" : "%s:%d", host->c_str(), *port); + } + + return true; +} + +} // namespace base +} // namespace android diff --git a/app/src/main/jni/crash_dump/libbase/parsenetaddress_test.cpp b/app/src/main/jni/crash_dump/libbase/parsenetaddress_test.cpp new file mode 100644 index 000000000..a3bfac860 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/parsenetaddress_test.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android-base/parsenetaddress.h" + +#include + +using android::base::ParseNetAddress; + +TEST(ParseNetAddressTest, TestUrl) { + std::string canonical, host, error; + int port = 123; + + EXPECT_TRUE( + ParseNetAddress("www.google.com", &host, &port, &canonical, &error)); + EXPECT_EQ("www.google.com:123", canonical); + EXPECT_EQ("www.google.com", host); + EXPECT_EQ(123, port); + + EXPECT_TRUE( + ParseNetAddress("www.google.com:666", &host, &port, &canonical, &error)); + EXPECT_EQ("www.google.com:666", canonical); + EXPECT_EQ("www.google.com", host); + EXPECT_EQ(666, port); +} + +TEST(ParseNetAddressTest, TestIpv4) { + std::string canonical, host, error; + int port = 123; + + EXPECT_TRUE(ParseNetAddress("1.2.3.4", &host, &port, &canonical, &error)); + EXPECT_EQ("1.2.3.4:123", canonical); + EXPECT_EQ("1.2.3.4", host); + EXPECT_EQ(123, port); + + EXPECT_TRUE(ParseNetAddress("1.2.3.4:666", &host, &port, &canonical, &error)); + EXPECT_EQ("1.2.3.4:666", canonical); + EXPECT_EQ("1.2.3.4", host); + EXPECT_EQ(666, port); +} + +TEST(ParseNetAddressTest, TestIpv6) { + std::string canonical, host, error; + int port = 123; + + EXPECT_TRUE(ParseNetAddress("::1", &host, &port, &canonical, &error)); + EXPECT_EQ("[::1]:123", canonical); + EXPECT_EQ("::1", host); + EXPECT_EQ(123, port); + + EXPECT_TRUE(ParseNetAddress("fe80::200:5aee:feaa:20a2", &host, &port, + &canonical, &error)); + EXPECT_EQ("[fe80::200:5aee:feaa:20a2]:123", canonical); + EXPECT_EQ("fe80::200:5aee:feaa:20a2", host); + EXPECT_EQ(123, port); + + EXPECT_TRUE(ParseNetAddress("[::1]:666", &host, &port, &canonical, &error)); + EXPECT_EQ("[::1]:666", canonical); + EXPECT_EQ("::1", host); + EXPECT_EQ(666, port); + + EXPECT_TRUE(ParseNetAddress("[fe80::200:5aee:feaa:20a2]:666", &host, &port, + &canonical, &error)); + EXPECT_EQ("[fe80::200:5aee:feaa:20a2]:666", canonical); + EXPECT_EQ("fe80::200:5aee:feaa:20a2", host); + EXPECT_EQ(666, port); +} + +TEST(ParseNetAddressTest, TestInvalidAddress) { + std::string canonical, host; + int port; + + std::string failure_cases[] = { + // Invalid IPv4. + "1.2.3.4:", + "1.2.3.4::", + ":123", + + // Invalid IPv6. + ":1", + "::::::::1", + "[::1", + "[::1]", + "[::1]:", + "[::1]::", + + // Invalid port. + "1.2.3.4:-1", + "1.2.3.4:0", + "1.2.3.4:65536" + "1.2.3.4:hello", + "[::1]:-1", + "[::1]:0", + "[::1]:65536", + "[::1]:hello", + }; + + for (const auto& address : failure_cases) { + // Failure should give some non-empty error string. + std::string error; + EXPECT_FALSE(ParseNetAddress(address, &host, &port, &canonical, &error)); + EXPECT_NE("", error); + } +} + +// Null canonical address argument. +TEST(ParseNetAddressTest, TestNullCanonicalAddress) { + std::string host, error; + int port = 42; + + EXPECT_TRUE(ParseNetAddress("www.google.com", &host, &port, nullptr, &error)); + EXPECT_TRUE(ParseNetAddress("1.2.3.4", &host, &port, nullptr, &error)); + EXPECT_TRUE(ParseNetAddress("::1", &host, &port, nullptr, &error)); +} diff --git a/app/src/main/jni/crash_dump/libbase/stringprintf.cpp b/app/src/main/jni/crash_dump/libbase/stringprintf.cpp new file mode 100644 index 000000000..78e1e8d14 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/stringprintf.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android-base/stringprintf.h" + +#include + +#include + +namespace android { +namespace base { + +void StringAppendV(std::string* dst, const char* format, va_list ap) { + // First try with a small fixed size buffer + char space[1024]; + + // It's possible for methods that use a va_list to invalidate + // the data in it upon use. The fix is to make a copy + // of the structure before using it and use that copy instead. + va_list backup_ap; + va_copy(backup_ap, ap); + int result = vsnprintf(space, sizeof(space), format, backup_ap); + va_end(backup_ap); + + if (result < static_cast(sizeof(space))) { + if (result >= 0) { + // Normal case -- everything fit. + dst->append(space, result); + return; + } + + if (result < 0) { + // Just an error. + return; + } + } + + // Increase the buffer size to the size requested by vsnprintf, + // plus one for the closing \0. + int length = result + 1; + char* buf = new char[length]; + + // Restore the va_list before we use it again + va_copy(backup_ap, ap); + result = vsnprintf(buf, length, format, backup_ap); + va_end(backup_ap); + + if (result >= 0 && result < length) { + // It fit + dst->append(buf, result); + } + delete[] buf; +} + +std::string StringPrintf(const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + std::string result; + StringAppendV(&result, fmt, ap); + va_end(ap); + return result; +} + +void StringAppendF(std::string* dst, const char* format, ...) { + va_list ap; + va_start(ap, format); + StringAppendV(dst, format, ap); + va_end(ap); +} + +} // namespace base +} // namespace android diff --git a/app/src/main/jni/crash_dump/libbase/stringprintf_test.cpp b/app/src/main/jni/crash_dump/libbase/stringprintf_test.cpp new file mode 100644 index 000000000..fc009b1d7 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/stringprintf_test.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android-base/stringprintf.h" + +#include + +#include + +TEST(StringPrintfTest, HexSizeT) { + size_t size = 0x00107e59; + EXPECT_EQ("00107e59", android::base::StringPrintf("%08zx", size)); + EXPECT_EQ("0x00107e59", android::base::StringPrintf("0x%08zx", size)); +} + +TEST(StringPrintfTest, StringAppendF) { + std::string s("a"); + android::base::StringAppendF(&s, "b"); + EXPECT_EQ("ab", s); +} + +TEST(StringPrintfTest, Errno) { + errno = 123; + android::base::StringPrintf("hello %s", "world"); + EXPECT_EQ(123, errno); +} + +void TestN(size_t n) { + char* buf = new char[n + 1]; + memset(buf, 'x', n); + buf[n] = '\0'; + std::string s(android::base::StringPrintf("%s", buf)); + EXPECT_EQ(buf, s); + delete[] buf; +} + +TEST(StringPrintfTest, At1023) { + TestN(1023); +} + +TEST(StringPrintfTest, At1024) { + TestN(1024); +} + +TEST(StringPrintfTest, At1025) { + TestN(1025); +} diff --git a/app/src/main/jni/crash_dump/libbase/strings.cpp b/app/src/main/jni/crash_dump/libbase/strings.cpp new file mode 100644 index 000000000..b8775df21 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/strings.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android-base/strings.h" + +#include +#include + +#include +#include + +namespace android { +namespace base { + +#define CHECK_NE(a, b) \ + if ((a) == (b)) abort(); + +std::vector Split(const std::string& s, + const std::string& delimiters) { + CHECK_NE(delimiters.size(), 0U); + + std::vector result; + + size_t base = 0; + size_t found; + do { + found = s.find_first_of(delimiters, base); + result.push_back(s.substr(base, found - base)); + base = found + 1; + } while (found != s.npos); + + return result; +} + +std::string Trim(const std::string& s) { + std::string result; + + if (s.size() == 0) { + return result; + } + + size_t start_index = 0; + size_t end_index = s.size() - 1; + + // Skip initial whitespace. + while (start_index < s.size()) { + if (!isspace(s[start_index])) { + break; + } + start_index++; + } + + // Skip terminating whitespace. + while (end_index >= start_index) { + if (!isspace(s[end_index])) { + break; + } + end_index--; + } + + // All spaces, no beef. + if (end_index < start_index) { + return ""; + } + // Start_index is the first non-space, end_index is the last one. + return s.substr(start_index, end_index - start_index + 1); +} + +// These cases are probably the norm, so we mark them extern in the header to +// aid compile time and binary size. +template std::string Join(const std::vector&, char); +template std::string Join(const std::vector&, char); +template std::string Join(const std::vector&, const std::string&); +template std::string Join(const std::vector&, const std::string&); + +bool StartsWith(const std::string& s, const char* prefix) { + return s.compare(0, strlen(prefix), prefix) == 0; +} + +bool EndsWith(const std::string& s, const char* suffix) { + size_t suffix_length = strlen(suffix); + size_t string_length = s.size(); + if (suffix_length > string_length) { + return false; + } + size_t offset = string_length - suffix_length; + return s.compare(offset, suffix_length, suffix) == 0; +} + +} // namespace base +} // namespace android diff --git a/app/src/main/jni/crash_dump/libbase/strings_test.cpp b/app/src/main/jni/crash_dump/libbase/strings_test.cpp new file mode 100644 index 000000000..30ae29e71 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/strings_test.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android-base/strings.h" + +#include + +#include +#include +#include +#include + +TEST(strings, split_empty) { + std::vector parts = android::base::Split("", ","); + ASSERT_EQ(1U, parts.size()); + ASSERT_EQ("", parts[0]); +} + +TEST(strings, split_single) { + std::vector parts = android::base::Split("foo", ","); + ASSERT_EQ(1U, parts.size()); + ASSERT_EQ("foo", parts[0]); +} + +TEST(strings, split_simple) { + std::vector parts = android::base::Split("foo,bar,baz", ","); + ASSERT_EQ(3U, parts.size()); + ASSERT_EQ("foo", parts[0]); + ASSERT_EQ("bar", parts[1]); + ASSERT_EQ("baz", parts[2]); +} + +TEST(strings, split_with_empty_part) { + std::vector parts = android::base::Split("foo,,bar", ","); + ASSERT_EQ(3U, parts.size()); + ASSERT_EQ("foo", parts[0]); + ASSERT_EQ("", parts[1]); + ASSERT_EQ("bar", parts[2]); +} + +TEST(strings, split_null_char) { + std::vector parts = + android::base::Split(std::string("foo\0bar", 7), std::string("\0", 1)); + ASSERT_EQ(2U, parts.size()); + ASSERT_EQ("foo", parts[0]); + ASSERT_EQ("bar", parts[1]); +} + +TEST(strings, split_any) { + std::vector parts = android::base::Split("foo:bar,baz", ",:"); + ASSERT_EQ(3U, parts.size()); + ASSERT_EQ("foo", parts[0]); + ASSERT_EQ("bar", parts[1]); + ASSERT_EQ("baz", parts[2]); +} + +TEST(strings, split_any_with_empty_part) { + std::vector parts = android::base::Split("foo:,bar", ",:"); + ASSERT_EQ(3U, parts.size()); + ASSERT_EQ("foo", parts[0]); + ASSERT_EQ("", parts[1]); + ASSERT_EQ("bar", parts[2]); +} + +TEST(strings, trim_empty) { + ASSERT_EQ("", android::base::Trim("")); +} + +TEST(strings, trim_already_trimmed) { + ASSERT_EQ("foo", android::base::Trim("foo")); +} + +TEST(strings, trim_left) { + ASSERT_EQ("foo", android::base::Trim(" foo")); +} + +TEST(strings, trim_right) { + ASSERT_EQ("foo", android::base::Trim("foo ")); +} + +TEST(strings, trim_both) { + ASSERT_EQ("foo", android::base::Trim(" foo ")); +} + +TEST(strings, trim_no_trim_middle) { + ASSERT_EQ("foo bar", android::base::Trim("foo bar")); +} + +TEST(strings, trim_other_whitespace) { + ASSERT_EQ("foo", android::base::Trim("\v\tfoo\n\f")); +} + +TEST(strings, join_nothing) { + std::vector list = {}; + ASSERT_EQ("", android::base::Join(list, ',')); +} + +TEST(strings, join_single) { + std::vector list = {"foo"}; + ASSERT_EQ("foo", android::base::Join(list, ',')); +} + +TEST(strings, join_simple) { + std::vector list = {"foo", "bar", "baz"}; + ASSERT_EQ("foo,bar,baz", android::base::Join(list, ',')); +} + +TEST(strings, join_separator_in_vector) { + std::vector list = {",", ","}; + ASSERT_EQ(",,,", android::base::Join(list, ',')); +} + +TEST(strings, join_simple_ints) { + std::set list = {1, 2, 3}; + ASSERT_EQ("1,2,3", android::base::Join(list, ',')); +} + +TEST(strings, join_unordered_set) { + std::unordered_set list = {1, 2}; + ASSERT_TRUE("1,2" == android::base::Join(list, ',') || + "2,1" == android::base::Join(list, ',')); +} + +TEST(strings, startswith_empty) { + ASSERT_FALSE(android::base::StartsWith("", "foo")); + ASSERT_TRUE(android::base::StartsWith("", "")); +} + +TEST(strings, startswith_simple) { + ASSERT_TRUE(android::base::StartsWith("foo", "")); + ASSERT_TRUE(android::base::StartsWith("foo", "f")); + ASSERT_TRUE(android::base::StartsWith("foo", "fo")); + ASSERT_TRUE(android::base::StartsWith("foo", "foo")); +} + +TEST(strings, startswith_prefix_too_long) { + ASSERT_FALSE(android::base::StartsWith("foo", "foobar")); +} + +TEST(strings, startswith_contains_prefix) { + ASSERT_FALSE(android::base::StartsWith("foobar", "oba")); + ASSERT_FALSE(android::base::StartsWith("foobar", "bar")); +} + +TEST(strings, endswith_empty) { + ASSERT_FALSE(android::base::EndsWith("", "foo")); + ASSERT_TRUE(android::base::EndsWith("", "")); +} + +TEST(strings, endswith_simple) { + ASSERT_TRUE(android::base::EndsWith("foo", "")); + ASSERT_TRUE(android::base::EndsWith("foo", "o")); + ASSERT_TRUE(android::base::EndsWith("foo", "oo")); + ASSERT_TRUE(android::base::EndsWith("foo", "foo")); +} + +TEST(strings, endswith_prefix_too_long) { + ASSERT_FALSE(android::base::EndsWith("foo", "foobar")); +} + +TEST(strings, endswith_contains_prefix) { + ASSERT_FALSE(android::base::EndsWith("foobar", "oba")); + ASSERT_FALSE(android::base::EndsWith("foobar", "foo")); +} diff --git a/app/src/main/jni/crash_dump/libbase/test_main.cpp b/app/src/main/jni/crash_dump/libbase/test_main.cpp new file mode 100644 index 000000000..7fa6a8425 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/test_main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "android-base/logging.h" + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + android::base::InitLogging(argv, android::base::StderrLogger); + return RUN_ALL_TESTS(); +} diff --git a/app/src/main/jni/crash_dump/libbase/test_utils.cpp b/app/src/main/jni/crash_dump/libbase/test_utils.cpp new file mode 100644 index 000000000..337ba7c44 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/test_utils.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android-base/logging.h" +#include "android-base/test_utils.h" +#include "utils/Compat.h" // For OS_PATH_SEPARATOR. + +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#include +#include +#endif + +#include + +#ifdef _WIN32 +int mkstemp(char* template_name) { + if (_mktemp(template_name) == nullptr) { + return -1; + } + // Use open() to match the close() that TemporaryFile's destructor does. + // Use O_BINARY to match base file APIs. + return open(template_name, O_CREAT | O_EXCL | O_RDWR | O_BINARY, + S_IRUSR | S_IWUSR); +} + +char* mkdtemp(char* template_name) { + if (_mktemp(template_name) == nullptr) { + return nullptr; + } + if (_mkdir(template_name) == -1) { + return nullptr; + } + return template_name; +} +#endif + +static std::string GetSystemTempDir() { +#if defined(__ANDROID__) + return "/data/local/tmp"; +#elif defined(_WIN32) + char tmp_dir[MAX_PATH]; + DWORD result = GetTempPathA(sizeof(tmp_dir), tmp_dir); + CHECK_NE(result, 0ul) << "GetTempPathA failed, error: " << GetLastError(); + CHECK_LT(result, sizeof(tmp_dir)) << "path truncated to: " << result; + + // GetTempPath() returns a path with a trailing slash, but init() + // does not expect that, so remove it. + CHECK_EQ(tmp_dir[result - 1], '\\'); + tmp_dir[result - 1] = '\0'; + return tmp_dir; +#else + return "/tmp"; +#endif +} + +TemporaryFile::TemporaryFile() { + init(GetSystemTempDir()); +} + +TemporaryFile::~TemporaryFile() { + close(fd); + unlink(path); +} + +void TemporaryFile::init(const std::string& tmp_dir) { + snprintf(path, sizeof(path), "%s%cTemporaryFile-XXXXXX", tmp_dir.c_str(), + OS_PATH_SEPARATOR); + fd = mkstemp(path); +} + +TemporaryDir::TemporaryDir() { + init(GetSystemTempDir()); +} + +TemporaryDir::~TemporaryDir() { + rmdir(path); +} + +bool TemporaryDir::init(const std::string& tmp_dir) { + snprintf(path, sizeof(path), "%s%cTemporaryDir-XXXXXX", tmp_dir.c_str(), + OS_PATH_SEPARATOR); + return (mkdtemp(path) != nullptr); +} diff --git a/app/src/main/jni/crash_dump/libbase/utf8.cpp b/app/src/main/jni/crash_dump/libbase/utf8.cpp new file mode 100644 index 000000000..3cca70026 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/utf8.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "android-base/utf8.h" + +#include + +#include + +#include "android-base/logging.h" + +namespace android { +namespace base { + +// Helper to set errno based on GetLastError() after WideCharToMultiByte()/MultiByteToWideChar(). +static void SetErrnoFromLastError() { + switch (GetLastError()) { + case ERROR_NO_UNICODE_TRANSLATION: + errno = EILSEQ; + break; + default: + errno = EINVAL; + break; + } +} + +bool WideToUTF8(const wchar_t* utf16, const size_t size, std::string* utf8) { + utf8->clear(); + + if (size == 0) { + return true; + } + + // TODO: Consider using std::wstring_convert once libcxx is supported on + // Windows. + + // Only Vista or later has this flag that causes WideCharToMultiByte() to + // return an error on invalid characters. + const DWORD flags = +#if (WINVER >= 0x0600) + WC_ERR_INVALID_CHARS; +#else + 0; +#endif + + const int chars_required = WideCharToMultiByte(CP_UTF8, flags, utf16, size, + NULL, 0, NULL, NULL); + if (chars_required <= 0) { + SetErrnoFromLastError(); + return false; + } + + // This could potentially throw a std::bad_alloc exception. + utf8->resize(chars_required); + + const int result = WideCharToMultiByte(CP_UTF8, flags, utf16, size, + &(*utf8)[0], chars_required, NULL, + NULL); + if (result != chars_required) { + SetErrnoFromLastError(); + CHECK_LE(result, chars_required) << "WideCharToMultiByte wrote " << result + << " chars to buffer of " << chars_required << " chars"; + utf8->clear(); + return false; + } + + return true; +} + +bool WideToUTF8(const wchar_t* utf16, std::string* utf8) { + // Compute string length of NULL-terminated string with wcslen(). + return WideToUTF8(utf16, wcslen(utf16), utf8); +} + +bool WideToUTF8(const std::wstring& utf16, std::string* utf8) { + // Use the stored length of the string which allows embedded NULL characters + // to be converted. + return WideToUTF8(utf16.c_str(), utf16.length(), utf8); +} + +// Internal helper function that takes MultiByteToWideChar() flags. +static bool UTF8ToWideWithFlags(const char* utf8, const size_t size, std::wstring* utf16, + const DWORD flags) { + utf16->clear(); + + if (size == 0) { + return true; + } + + // TODO: Consider using std::wstring_convert once libcxx is supported on + // Windows. + const int chars_required = MultiByteToWideChar(CP_UTF8, flags, utf8, size, + NULL, 0); + if (chars_required <= 0) { + SetErrnoFromLastError(); + return false; + } + + // This could potentially throw a std::bad_alloc exception. + utf16->resize(chars_required); + + const int result = MultiByteToWideChar(CP_UTF8, flags, utf8, size, + &(*utf16)[0], chars_required); + if (result != chars_required) { + SetErrnoFromLastError(); + CHECK_LE(result, chars_required) << "MultiByteToWideChar wrote " << result + << " chars to buffer of " << chars_required << " chars"; + utf16->clear(); + return false; + } + + return true; +} + +bool UTF8ToWide(const char* utf8, const size_t size, std::wstring* utf16) { + // If strictly interpreting as UTF-8 succeeds, return success. + if (UTF8ToWideWithFlags(utf8, size, utf16, MB_ERR_INVALID_CHARS)) { + return true; + } + + const int saved_errno = errno; + + // Fallback to non-strict interpretation, allowing invalid characters and + // converting as best as possible, and return false to signify a problem. + (void)UTF8ToWideWithFlags(utf8, size, utf16, 0); + errno = saved_errno; + return false; +} + +bool UTF8ToWide(const char* utf8, std::wstring* utf16) { + // Compute string length of NULL-terminated string with strlen(). + return UTF8ToWide(utf8, strlen(utf8), utf16); +} + +bool UTF8ToWide(const std::string& utf8, std::wstring* utf16) { + // Use the stored length of the string which allows embedded NULL characters + // to be converted. + return UTF8ToWide(utf8.c_str(), utf8.length(), utf16); +} + +// Versions of standard library APIs that support UTF-8 strings. +namespace utf8 { + +int open(const char* name, int flags, ...) { + std::wstring name_utf16; + if (!UTF8ToWide(name, &name_utf16)) { + return -1; + } + + int mode = 0; + if ((flags & O_CREAT) != 0) { + va_list args; + va_start(args, flags); + mode = va_arg(args, int); + va_end(args); + } + + return _wopen(name_utf16.c_str(), flags, mode); +} + +int unlink(const char* name) { + std::wstring name_utf16; + if (!UTF8ToWide(name, &name_utf16)) { + return -1; + } + + return _wunlink(name_utf16.c_str()); +} + +} // namespace utf8 +} // namespace base +} // namespace android diff --git a/app/src/main/jni/crash_dump/libbase/utf8_test.cpp b/app/src/main/jni/crash_dump/libbase/utf8_test.cpp new file mode 100644 index 000000000..ae8fc8c79 --- /dev/null +++ b/app/src/main/jni/crash_dump/libbase/utf8_test.cpp @@ -0,0 +1,412 @@ +/* +* Copyright (C) 2015 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "android-base/utf8.h" + +#include + +#include "android-base/macros.h" + +namespace android { +namespace base { + +TEST(UTFStringConversionsTest, ConvertInvalidUTF8) { + std::wstring wide; + + errno = 0; + + // Standalone \xa2 is an invalid UTF-8 sequence, so this should return an + // error. Concatenate two C/C++ literal string constants to prevent the + // compiler from giving an error about "\xa2af" containing a "hex escape + // sequence out of range". + EXPECT_FALSE(android::base::UTF8ToWide("before\xa2" "after", &wide)); + + EXPECT_EQ(EILSEQ, errno); + + // Even if an invalid character is encountered, UTF8ToWide() should still do + // its best to convert the rest of the string. sysdeps_win32.cpp: + // _console_write_utf8() depends on this behavior. + // + // Thus, we verify that the valid characters are converted, but we ignore the + // specific replacement character that UTF8ToWide() may replace the invalid + // UTF-8 characters with because we want to allow that to change if the + // implementation changes. + EXPECT_EQ(0U, wide.find(L"before")); + const wchar_t after_wide[] = L"after"; + EXPECT_EQ(wide.length() - (arraysize(after_wide) - 1), wide.find(after_wide)); +} + +// Below is adapted from https://chromium.googlesource.com/chromium/src/+/master/base/strings/utf_string_conversions_unittest.cc + +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// The tests below from utf_string_conversions_unittest.cc check for this +// preprocessor symbol, so define it, as it is appropriate for Windows. +#define WCHAR_T_IS_UTF16 +static_assert(sizeof(wchar_t) == 2, "wchar_t is not 2 bytes"); + +// The tests below from utf_string_conversions_unittest.cc call versions of +// UTF8ToWide() and WideToUTF8() that don't return success/failure, so these are +// stub implementations with that signature. These are just for testing and +// should not be moved to base because they assert/expect no errors which is +// probably not a good idea (or at least it is something that should be left +// up to the caller, not a base library). + +static std::wstring UTF8ToWide(const std::string& utf8) { + std::wstring utf16; + EXPECT_TRUE(UTF8ToWide(utf8, &utf16)); + return utf16; +} + +static std::string WideToUTF8(const std::wstring& utf16) { + std::string utf8; + EXPECT_TRUE(WideToUTF8(utf16, &utf8)); + return utf8; +} + +namespace { + +const wchar_t* const kConvertRoundtripCases[] = { + L"Google Video", + // "网页 图片 资讯更多 »" + L"\x7f51\x9875\x0020\x56fe\x7247\x0020\x8d44\x8baf\x66f4\x591a\x0020\x00bb", + // "Παγκόσμιος Ιστός" + L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9" + L"\x03bf\x03c2\x0020\x0399\x03c3\x03c4\x03cc\x03c2", + // "Поиск страниц на русском" + L"\x041f\x043e\x0438\x0441\x043a\x0020\x0441\x0442" + L"\x0440\x0430\x043d\x0438\x0446\x0020\x043d\x0430" + L"\x0020\x0440\x0443\x0441\x0441\x043a\x043e\x043c", + // "전체서비스" + L"\xc804\xccb4\xc11c\xbe44\xc2a4", + + // Test characters that take more than 16 bits. This will depend on whether + // wchar_t is 16 or 32 bits. +#if defined(WCHAR_T_IS_UTF16) + L"\xd800\xdf00", + // ????? (Mathematical Alphanumeric Symbols (U+011d40 - U+011d44 : A,B,C,D,E) + L"\xd807\xdd40\xd807\xdd41\xd807\xdd42\xd807\xdd43\xd807\xdd44", +#elif defined(WCHAR_T_IS_UTF32) + L"\x10300", + // ????? (Mathematical Alphanumeric Symbols (U+011d40 - U+011d44 : A,B,C,D,E) + L"\x11d40\x11d41\x11d42\x11d43\x11d44", +#endif +}; + +} // namespace + +TEST(UTFStringConversionsTest, ConvertUTF8AndWide) { + // we round-trip all the wide strings through UTF-8 to make sure everything + // agrees on the conversion. This uses the stream operators to test them + // simultaneously. + for (size_t i = 0; i < arraysize(kConvertRoundtripCases); ++i) { + std::ostringstream utf8; + utf8 << WideToUTF8(kConvertRoundtripCases[i]); + std::wostringstream wide; + wide << UTF8ToWide(utf8.str()); + + EXPECT_EQ(kConvertRoundtripCases[i], wide.str()); + } +} + +TEST(UTFStringConversionsTest, ConvertUTF8AndWideEmptyString) { + // An empty std::wstring should be converted to an empty std::string, + // and vice versa. + std::wstring wempty; + std::string empty; + EXPECT_EQ(empty, WideToUTF8(wempty)); + EXPECT_EQ(wempty, UTF8ToWide(empty)); +} + +TEST(UTFStringConversionsTest, ConvertUTF8ToWide) { + struct UTF8ToWideCase { + const char* utf8; + const wchar_t* wide; + bool success; + } convert_cases[] = { + // Regular UTF-8 input. + {"\xe4\xbd\xa0\xe5\xa5\xbd", L"\x4f60\x597d", true}, + // Non-character is passed through. + {"\xef\xbf\xbfHello", L"\xffffHello", true}, + // Truncated UTF-8 sequence. + {"\xe4\xa0\xe5\xa5\xbd", L"\xfffd\x597d", false}, + // Truncated off the end. + {"\xe5\xa5\xbd\xe4\xa0", L"\x597d\xfffd", false}, + // Non-shortest-form UTF-8. + {"\xf0\x84\xbd\xa0\xe5\xa5\xbd", L"\xfffd\x597d", false}, + // This UTF-8 character decodes to a UTF-16 surrogate, which is illegal. + // Note that for whatever reason, this test fails on Windows XP. + {"\xed\xb0\x80", L"\xfffd", false}, + // Non-BMP characters. The second is a non-character regarded as valid. + // The result will either be in UTF-16 or UTF-32. +#if defined(WCHAR_T_IS_UTF16) + {"A\xF0\x90\x8C\x80z", L"A\xd800\xdf00z", true}, + {"A\xF4\x8F\xBF\xBEz", L"A\xdbff\xdffez", true}, +#elif defined(WCHAR_T_IS_UTF32) + {"A\xF0\x90\x8C\x80z", L"A\x10300z", true}, + {"A\xF4\x8F\xBF\xBEz", L"A\x10fffez", true}, +#endif + }; + + for (size_t i = 0; i < arraysize(convert_cases); i++) { + std::wstring converted; + errno = 0; + const bool success = UTF8ToWide(convert_cases[i].utf8, + strlen(convert_cases[i].utf8), + &converted); + EXPECT_EQ(convert_cases[i].success, success); + // The original test always compared expected and converted, but don't do + // that because our implementation of UTF8ToWide() does not guarantee to + // produce the same output in error situations. + if (success) { + std::wstring expected(convert_cases[i].wide); + EXPECT_EQ(expected, converted); + } else { + EXPECT_EQ(EILSEQ, errno); + } + } + + // Manually test an embedded NULL. + std::wstring converted; + EXPECT_TRUE(UTF8ToWide("\00Z\t", 3, &converted)); + ASSERT_EQ(3U, converted.length()); + EXPECT_EQ(static_cast(0), converted[0]); + EXPECT_EQ('Z', converted[1]); + EXPECT_EQ('\t', converted[2]); + + // Make sure that conversion replaces, not appends. + EXPECT_TRUE(UTF8ToWide("B", 1, &converted)); + ASSERT_EQ(1U, converted.length()); + EXPECT_EQ('B', converted[0]); +} + +#if defined(WCHAR_T_IS_UTF16) +// This test is only valid when wchar_t == UTF-16. +TEST(UTFStringConversionsTest, ConvertUTF16ToUTF8) { + struct WideToUTF8Case { + const wchar_t* utf16; + const char* utf8; + bool success; + } convert_cases[] = { + // Regular UTF-16 input. + {L"\x4f60\x597d", "\xe4\xbd\xa0\xe5\xa5\xbd", true}, + // Test a non-BMP character. + {L"\xd800\xdf00", "\xF0\x90\x8C\x80", true}, + // Non-characters are passed through. + {L"\xffffHello", "\xEF\xBF\xBFHello", true}, + {L"\xdbff\xdffeHello", "\xF4\x8F\xBF\xBEHello", true}, + // The first character is a truncated UTF-16 character. + // Note that for whatever reason, this test fails on Windows XP. + {L"\xd800\x597d", "\xef\xbf\xbd\xe5\xa5\xbd", +#if (WINVER >= 0x0600) + // Only Vista and later has a new API/flag that correctly returns false. + false +#else + true +#endif + }, + // Truncated at the end. + // Note that for whatever reason, this test fails on Windows XP. + {L"\x597d\xd800", "\xe5\xa5\xbd\xef\xbf\xbd", +#if (WINVER >= 0x0600) + // Only Vista and later has a new API/flag that correctly returns false. + false +#else + true +#endif + }, + }; + + for (size_t i = 0; i < arraysize(convert_cases); i++) { + std::string converted; + errno = 0; + const bool success = WideToUTF8(convert_cases[i].utf16, + wcslen(convert_cases[i].utf16), + &converted); + EXPECT_EQ(convert_cases[i].success, success); + // The original test always compared expected and converted, but don't do + // that because our implementation of WideToUTF8() does not guarantee to + // produce the same output in error situations. + if (success) { + std::string expected(convert_cases[i].utf8); + EXPECT_EQ(expected, converted); + } else { + EXPECT_EQ(EILSEQ, errno); + } + } +} + +#elif defined(WCHAR_T_IS_UTF32) +// This test is only valid when wchar_t == UTF-32. +TEST(UTFStringConversionsTest, ConvertUTF32ToUTF8) { + struct WideToUTF8Case { + const wchar_t* utf32; + const char* utf8; + bool success; + } convert_cases[] = { + // Regular 16-bit input. + {L"\x4f60\x597d", "\xe4\xbd\xa0\xe5\xa5\xbd", true}, + // Test a non-BMP character. + {L"A\x10300z", "A\xF0\x90\x8C\x80z", true}, + // Non-characters are passed through. + {L"\xffffHello", "\xEF\xBF\xBFHello", true}, + {L"\x10fffeHello", "\xF4\x8F\xBF\xBEHello", true}, + // Invalid Unicode code points. + {L"\xfffffffHello", "\xEF\xBF\xBDHello", false}, + // The first character is a truncated UTF-16 character. + {L"\xd800\x597d", "\xef\xbf\xbd\xe5\xa5\xbd", false}, + {L"\xdc01Hello", "\xef\xbf\xbdHello", false}, + }; + + for (size_t i = 0; i < arraysize(convert_cases); i++) { + std::string converted; + EXPECT_EQ(convert_cases[i].success, + WideToUTF8(convert_cases[i].utf32, + wcslen(convert_cases[i].utf32), + &converted)); + std::string expected(convert_cases[i].utf8); + EXPECT_EQ(expected, converted); + } +} +#endif // defined(WCHAR_T_IS_UTF32) + +// The test below uses these types and functions, so just do enough to get the +// test running. +typedef wchar_t char16; +typedef std::wstring string16; + +template +static void* WriteInto(T* t, size_t size) { + // std::(w)string::resize() already includes space for a NULL terminator. + t->resize(size - 1); + return &(*t)[0]; +} + +// A stub implementation that calls a helper from above, just to get the test +// below working. This is just for testing and should not be moved to base +// because this ignores errors which is probably not a good idea, plus it takes +// a string16 type which we don't really have. +static std::string UTF16ToUTF8(const string16& utf16) { + return WideToUTF8(utf16); +} + +TEST(UTFStringConversionsTest, ConvertMultiString) { + static char16 multi16[] = { + 'f', 'o', 'o', '\0', + 'b', 'a', 'r', '\0', + 'b', 'a', 'z', '\0', + '\0' + }; + static char multi[] = { + 'f', 'o', 'o', '\0', + 'b', 'a', 'r', '\0', + 'b', 'a', 'z', '\0', + '\0' + }; + string16 multistring16; + memcpy(WriteInto(&multistring16, arraysize(multi16)), multi16, + sizeof(multi16)); + EXPECT_EQ(arraysize(multi16) - 1, multistring16.length()); + std::string expected; + memcpy(WriteInto(&expected, arraysize(multi)), multi, sizeof(multi)); + EXPECT_EQ(arraysize(multi) - 1, expected.length()); + const std::string& converted = UTF16ToUTF8(multistring16); + EXPECT_EQ(arraysize(multi) - 1, converted.length()); + EXPECT_EQ(expected, converted); +} + +// The tests below from sys_string_conversions_unittest.cc call SysWideToUTF8() +// and SysUTF8ToWide(), so these are stub implementations that call the helpers +// above. These are just for testing and should not be moved to base because +// they ignore errors which is probably not a good idea. + +static std::string SysWideToUTF8(const std::wstring& utf16) { + return WideToUTF8(utf16); +} + +static std::wstring SysUTF8ToWide(const std::string& utf8) { + return UTF8ToWide(utf8); +} + +// Below is adapted from https://chromium.googlesource.com/chromium/src/+/master/base/strings/sys_string_conversions_unittest.cc + +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifdef WCHAR_T_IS_UTF32 +static const std::wstring kSysWideOldItalicLetterA = L"\x10300"; +#else +static const std::wstring kSysWideOldItalicLetterA = L"\xd800\xdf00"; +#endif + +TEST(SysStrings, SysWideToUTF8) { + EXPECT_EQ("Hello, world", SysWideToUTF8(L"Hello, world")); + EXPECT_EQ("\xe4\xbd\xa0\xe5\xa5\xbd", SysWideToUTF8(L"\x4f60\x597d")); + + // >16 bits + EXPECT_EQ("\xF0\x90\x8C\x80", SysWideToUTF8(kSysWideOldItalicLetterA)); + + // Error case. When Windows finds a UTF-16 character going off the end of + // a string, it just converts that literal value to UTF-8, even though this + // is invalid. + // + // This is what XP does, but Vista has different behavior, so we don't bother + // verifying it: + // EXPECT_EQ("\xE4\xBD\xA0\xED\xA0\x80zyxw", + // SysWideToUTF8(L"\x4f60\xd800zyxw")); + + // Test embedded NULLs. + std::wstring wide_null(L"a"); + wide_null.push_back(0); + wide_null.push_back('b'); + + std::string expected_null("a"); + expected_null.push_back(0); + expected_null.push_back('b'); + + EXPECT_EQ(expected_null, SysWideToUTF8(wide_null)); +} + +TEST(SysStrings, SysUTF8ToWide) { + EXPECT_EQ(L"Hello, world", SysUTF8ToWide("Hello, world")); + EXPECT_EQ(L"\x4f60\x597d", SysUTF8ToWide("\xe4\xbd\xa0\xe5\xa5\xbd")); + // >16 bits + EXPECT_EQ(kSysWideOldItalicLetterA, SysUTF8ToWide("\xF0\x90\x8C\x80")); + + // Error case. When Windows finds an invalid UTF-8 character, it just skips + // it. This seems weird because it's inconsistent with the reverse conversion. + // + // This is what XP does, but Vista has different behavior, so we don't bother + // verifying it: + // EXPECT_EQ(L"\x4f60zyxw", SysUTF8ToWide("\xe4\xbd\xa0\xe5\xa5zyxw")); + + // Test embedded NULLs. + std::string utf8_null("a"); + utf8_null.push_back(0); + utf8_null.push_back('b'); + + std::wstring expected_null(L"a"); + expected_null.push_back(0); + expected_null.push_back('b'); + + EXPECT_EQ(expected_null, SysUTF8ToWide(utf8_null)); +} + +} // namespace base +} // namespace android