diff options
Diffstat (limited to 'runtime/utils.cc')
| -rw-r--r-- | runtime/utils.cc | 72 |
1 files changed, 65 insertions, 7 deletions
diff --git a/runtime/utils.cc b/runtime/utils.cc index 27daceaaf2..48dce63f00 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -36,6 +36,7 @@ #include "mirror/object-inl.h" #include "mirror/object_array-inl.h" #include "mirror/string.h" +#include "oat_quick_method_header.h" #include "os.h" #include "scoped_thread_state_change.h" #include "utf-inl.h" @@ -45,7 +46,9 @@ #include <sys/syscall.h> #endif -#include <backtrace/Backtrace.h> // For DumpNativeStack. +// For DumpNativeStack. +#include <backtrace/Backtrace.h> +#include <backtrace/BacktraceMap.h> #if defined(__linux__) #include <linux/unistd.h> @@ -1089,9 +1092,19 @@ static void Addr2line(const std::string& map_src, uintptr_t offset, std::ostream map_src.c_str(), offset)); RunCommand(cmdline.c_str(), &os, prefix); } + +static bool PcIsWithinQuickCode(ArtMethod* method, uintptr_t pc) NO_THREAD_SAFETY_ANALYSIS { + uintptr_t code = reinterpret_cast<uintptr_t>(EntryPointToCodePointer( + method->GetEntryPointFromQuickCompiledCode())); + if (code == 0) { + return pc == 0; + } + uintptr_t code_size = reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].code_size_; + return code <= pc && pc <= (code + code_size); +} #endif -void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix, +void DumpNativeStack(std::ostream& os, pid_t tid, BacktraceMap* existing_map, const char* prefix, ArtMethod* current_method, void* ucontext_ptr) { #if __linux__ // b/18119146 @@ -1099,7 +1112,13 @@ void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix, return; } - std::unique_ptr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, tid)); + BacktraceMap* map = existing_map; + std::unique_ptr<BacktraceMap> tmp_map; + if (map == nullptr) { + tmp_map.reset(BacktraceMap::Create(tid)); + map = tmp_map.get(); + } + std::unique_ptr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, tid, map)); if (!backtrace->Unwind(0, reinterpret_cast<ucontext*>(ucontext_ptr))) { os << prefix << "(backtrace::Unwind failed for thread " << tid << ")\n"; return; @@ -1146,9 +1165,9 @@ void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix, os << "+" << it->func_offset; } try_addr2line = true; - } else if ( - current_method != nullptr && Locks::mutator_lock_->IsSharedHeld(Thread::Current()) && - current_method->PcIsWithinQuickCode(it->pc)) { + } else if (current_method != nullptr && + Locks::mutator_lock_->IsSharedHeld(Thread::Current()) && + PcIsWithinQuickCode(current_method, it->pc)) { const void* start_of_code = current_method->GetEntryPointFromQuickCompiledCode(); os << JniLongName(current_method) << "+" << (it->pc - reinterpret_cast<uintptr_t>(start_of_code)); @@ -1163,7 +1182,7 @@ void DumpNativeStack(std::ostream& os, pid_t tid, const char* prefix, } } #else - UNUSED(os, tid, prefix, current_method, ucontext_ptr); + UNUSED(os, tid, existing_map, prefix, current_method, ucontext_ptr); #endif } @@ -1816,4 +1835,43 @@ void DumpMethodCFG(const DexFile* dex_file, uint32_t dex_method_idx, std::ostrea os << "Something went wrong, didn't find the method in the class data."; } +static void ParseStringAfterChar(const std::string& s, + char c, + std::string* parsed_value, + UsageFn Usage) { + std::string::size_type colon = s.find(c); + if (colon == std::string::npos) { + Usage("Missing char %c in option %s\n", c, s.c_str()); + } + // Add one to remove the char we were trimming until. + *parsed_value = s.substr(colon + 1); +} + +void ParseDouble(const std::string& option, + char after_char, + double min, + double max, + double* parsed_value, + UsageFn Usage) { + std::string substring; + ParseStringAfterChar(option, after_char, &substring, Usage); + bool sane_val = true; + double value; + if ((false)) { + // TODO: this doesn't seem to work on the emulator. b/15114595 + std::stringstream iss(substring); + iss >> value; + // Ensure that we have a value, there was no cruft after it and it satisfies a sensible range. + sane_val = iss.eof() && (value >= min) && (value <= max); + } else { + char* end = nullptr; + value = strtod(substring.c_str(), &end); + sane_val = *end == '\0' && value >= min && value <= max; + } + if (!sane_val) { + Usage("Invalid double value %s for option %s\n", substring.c_str(), option.c_str()); + } + *parsed_value = value; +} + } // namespace art |