ErrorCode Thread::resume(int signal, Address const &address) { // TODO(sas): Not sure how to translate the signal concept to Windows yet. // We'll probably have to get rid of these at some point. DS2ASSERT(signal == 0); if (address.valid()) { CHK(modifyRegisters( [&address](Architecture::CPUState &state) { state.setPC(address); })); } switch (_state) { case kInvalid: case kRunning: DS2BUG("trying to suspend tid %" PRI_PID " in state %s", tid(), Stringify::ThreadState(_state)); break; case kTerminated: return kErrorProcessNotFound; case kStopped: case kStepped: { if (_stopInfo.event == StopInfo::kEventStop && _stopInfo.reason == StopInfo::kReasonNone) { DWORD result = ::ResumeThread(_handle); if (result == (DWORD)-1) { return Platform::TranslateError(); } } else { BOOL result = ::ContinueDebugEvent(_process->pid(), _tid, DBG_CONTINUE); if (!result) { return Platform::TranslateError(); } } _state = kRunning; return kSuccess; } } // Silence warnings without using a `default:` case for the above switch. DS2_UNREACHABLE(); }
static void androidLogcat(int level, char const *functag, char const *message) { android_LogPriority androidLevel; switch (level) { #define CONVERT_LEVEL(LEVEL, ANDROID_LEVEL) \ case LEVEL: \ androidLevel = ANDROID_LEVEL; \ break; CONVERT_LEVEL(ds2::kLogLevelPacket, ANDROID_LOG_VERBOSE) CONVERT_LEVEL(ds2::kLogLevelDebug, ANDROID_LOG_DEBUG) CONVERT_LEVEL(ds2::kLogLevelInfo, ANDROID_LOG_INFO) CONVERT_LEVEL(ds2::kLogLevelWarning, ANDROID_LOG_WARN) CONVERT_LEVEL(ds2::kLogLevelError, ANDROID_LOG_ERROR) CONVERT_LEVEL(ds2::kLogLevelFatal, ANDROID_LOG_FATAL) #undef CONVERT_LEVEL default: DS2_UNREACHABLE(); } std::stringstream ss(message); std::string line; while (std::getline(ss, line, '\n')) __android_log_print(androidLevel, "ds2", "[%s] %s", functag, line.c_str()); }
void vLog(int level, char const *classname, char const *funcname, char const *format, va_list ap) { std::stringstream ss; std::vector<char> buffer; size_t required_bytes = 128; do { va_list ap_copy; va_copy(ap_copy, ap); buffer.resize(required_bytes + 1); required_bytes = ds2_vsnprintf(buffer.data(), buffer.size(), format, ap_copy); va_end(ap_copy); } while (required_bytes >= buffer.size()); std::stringstream functag; if (classname != nullptr) functag << classname << "::"; functag << funcname; #if defined(ENABLE_LOGCAT) if (level >= sLogLevel || level >= kLogLevelDebug) // If we're on Android pollute logcat as well. androidLogcat(level, functag.str().c_str(), buffer.data()); #endif if (level < sLogLevel) return; ss << '[' << Host::Platform::GetCurrentProcessId() << ']'; ss << '[' << functag.str() << ']'; char const *color = nullptr; char const *label = nullptr; switch (level) { case kLogLevelFatal: color = "\x1b[1;31m"; label = "FATAL "; break; case kLogLevelError: color = "\x1b[1;31m"; label = "ERROR "; break; case kLogLevelWarning: color = "\x1b[1;33m"; label = "WARNING"; break; case kLogLevelInfo: color = "\x1b[1;32m"; label = "INFO "; break; case kLogLevelDebug: color = "\x1b[1;36m"; label = "DEBUG "; break; case kLogLevelPacket: color = "\x1b[0;35m"; label = "PACKET "; break; default: DS2_UNREACHABLE(); } ss << ' '; if (color != nullptr && sColorsEnabled) { ss << color << label << "\x1b[m" << ':'; } else if (label != nullptr) { ss << label << ':'; } ss << ' ' << buffer.data() << std::endl; fputs(ss.str().c_str(), sOutputStream); fflush(sOutputStream); if (level == kLogLevelFatal) abort(); }