We simply don't emit unwind tables, which are not needed anyways since we're compiling without exceptions. the combined saving for all four targets we support is about 120K. This seems to improve .aar's compression, for a total gain of 152 KiB. We also disable stack-protector in the jni code, since it wasn't enabled in libfilament.a anyways. However, we now compile all debug builds with -fstack-protector
137 lines
3.8 KiB
C++
137 lines
3.8 KiB
C++
/*
|
|
* 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 <utils/CallStack.h>
|
|
#include <utils/Log.h>
|
|
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <algorithm>
|
|
#include <memory>
|
|
|
|
// FIXME: Some platforms do not have execinfo.h (but have unwind.h)
|
|
#if !defined(ANDROID) && !defined(WIN32) && !defined(__EMSCRIPTEN__)
|
|
#include <execinfo.h>
|
|
#define HAS_EXECINFO 1
|
|
#else
|
|
#define HAS_EXECINFO 0
|
|
#endif
|
|
|
|
#if !defined(NDEBUG) && !defined(WIN32)
|
|
#include <cxxabi.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
#ifdef __EXCEPTIONS
|
|
#include <stdexcept>
|
|
#endif
|
|
|
|
namespace utils {
|
|
|
|
struct FreeDeleter {
|
|
void operator()(const void* pv) const { free(const_cast<void*>(pv)); }
|
|
};
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
CallStack CallStack::unwind(size_t ignore) noexcept {
|
|
CallStack stack;
|
|
stack.update(ignore);
|
|
return stack;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
intptr_t CallStack::operator[](size_t index) const {
|
|
if (index >= m_frame_count) {
|
|
#ifdef __EXCEPTIONS
|
|
throw std::out_of_range("out-of-range access in CallStack::operator[]");
|
|
#endif
|
|
std::abort();
|
|
}
|
|
return m_stack[index].pc;
|
|
}
|
|
|
|
size_t CallStack::getFrameCount() const noexcept {
|
|
return m_frame_count;
|
|
}
|
|
|
|
void CallStack::update(size_t ignore) noexcept {
|
|
update_gcc(ignore);
|
|
}
|
|
|
|
void CallStack::update_gcc(size_t ignore) noexcept {
|
|
// reset the object
|
|
ssize_t size = 0;
|
|
|
|
void* array[NUM_FRAMES];
|
|
#if HAS_EXECINFO
|
|
size = ::backtrace(array, NUM_FRAMES);
|
|
size -= ignore;
|
|
#endif
|
|
for (ssize_t i = 0; i < size; i++) {
|
|
m_stack[i].pc = intptr_t(array[ignore + i]);
|
|
}
|
|
size--; // the last one seems to always be 0x0
|
|
|
|
// update how many frames we have
|
|
m_frame_count = size_t(std::max(ssize_t(0), size));
|
|
}
|
|
|
|
bool CallStack::operator<(const CallStack& rhs) const {
|
|
if (m_frame_count != rhs.m_frame_count) {
|
|
return m_frame_count < rhs.m_frame_count;
|
|
}
|
|
return memcmp(m_stack, rhs.m_stack, m_frame_count * sizeof(StackFrameInfo)) < 0;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
utils::CString CallStack::demangleTypeName(const char* mangled) {
|
|
#if !defined(NDEBUG) && !defined(WIN32)
|
|
size_t len;
|
|
int status;
|
|
std::unique_ptr<char, FreeDeleter> demangled(abi::__cxa_demangle(mangled, nullptr, &len, &status));
|
|
if (!status && demangled) {
|
|
// success
|
|
return CString(demangled.get());
|
|
}
|
|
// failed to demangle string or parsing error: return input
|
|
#endif
|
|
return CString(mangled);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
io::ostream& operator<<(io::ostream& stream, const CallStack& callstack) {
|
|
#if HAS_EXECINFO
|
|
size_t size = callstack.getFrameCount();
|
|
for (size_t i = 0; i < size; i++) {
|
|
intptr_t pc = callstack[i];
|
|
std::unique_ptr<char*, FreeDeleter> symbols(::backtrace_symbols((void* const*)&pc, 1));
|
|
char const* const symbol = symbols.get()[0];
|
|
stream << "#" << i << " " << symbol;
|
|
if (i < size - 1) {
|
|
stream << io::endl;
|
|
}
|
|
}
|
|
#endif
|
|
return stream;
|
|
}
|
|
|
|
} // namespace utils
|