summaryrefslogtreecommitdiff
path: root/runtime/utils.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/utils.cc')
-rw-r--r--runtime/utils.cc72
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