void ReleaseDialog::release() { setTitle("发布版本"); QString pwd = lineedit_pwd->text(); QString name = lineedit_name->text(); if(pwd.isEmpty() || name.isEmpty() || name.size() > 16) { QString prompt; prompt = QString("必须设置加密密码\n填写版本信息。"); if(name.size() > 16) prompt = QString("版本信息不能超过16个字符。"); QMessageBox box(QMessageBox::Information, "提示", prompt); box.setStandardButtons(QMessageBox::Ok); box.setButtonText(QMessageBox::Ok, "确定"); box.exec(); return; } ////name 最大16个字符 if(!setFilePath()) { QMessageBox::information(NULL, "提示", "文件路径设置失败!"); return; } bar->setHidden(false); QDateTime start,end; getDateTime(start, end); QString jsonfilePath = getReadFilePath(start, end); this->setCursor(Qt::WaitCursor); ///读JSON下载资源 readJsonFile(jsonfilePath); ///打包 QStringList fileNames = getCurrentDirFiles(releasePath); QString destPath = QCoreApplication::applicationDirPath(); destPath.append("/ZIP/"); QDir dir(destPath); if(!dir.exists()) dir.mkpath(destPath); QString destName = currentDate.toString("yyyy-MM-dd_hh_mm_ss"); destName.append(".zip"); destPath.append(destName); QFile destFile(destPath); if(destFile.exists()) { } zipFile zf; QByteArray dest = destPath.toLocal8Bit(); zf = zipOpen(dest.data(), APPEND_STATUS_CREATE); if (zf == NULL) { QMessageBox::information(NULL, "提示", "打开压缩文件失败!"); return; } label_title->setText("压缩文件……"); // LOKI_ON_BLOCK_EXIT(zipClose, zf, (const char *)NULL); for (int i=0; i<fileNames.size(); i++) { QString tempStr = fileNames.at(i); QString path = releasePath; path.remove("music"); QString temprel = path; QString deststr = tempStr.remove(temprel); if (!ZipAddFile(zf, deststr, fileNames.at(i), pwd, true)) //"default_yqc" { continue; } } int errclose = zipClose(zf, NULL); if (errclose != ZIP_OK) qDebug() << " zipClose ret : " << errclose; label_title->setText("上传压缩包……"); QFile file(destPath); qDebug() << " size " << file.size(); if(file.size()/1024/1024 >= 1024) { QMessageBox::information(this, "提示", "上传文件大小必须小于1G!"); return; } ///上传打包文件 // QString url; // CurlUpload *curlUpload = new CurlUpload(); // bool ok = curlUpload->uploadYQDyun(destName, destPath, url); // if(!ok) // { // url = ""; // label_title->setText("上传失败"); // label_title->setStyleSheet("color:rgb(255, 0, 0);"); // } // else // { // label_title->setText("上传成功"); // label_title->setStyleSheet("color:rgb(0, 255, 0);"); // } // qDebug() << " upload yun : ok : " << ok; // qDebug() << " zip name " << destName; // qDebug() << " url " << url; // /// post 表格数据 QDateTime time = QDateTime::currentDateTime(); QString timeStr = time.toString("yyyy-MM-dd-hh-mm-ss"); int version = time.toTime_t(); ///时间戳 // QString postStr = QString("name=%1&url=%2&time=%3&remark=%4&version=%5") // .arg(name) // .arg(url) // .arg(timeStr) // .arg(pwd) // .arg(version); // CurlUpload *curlDownlaod = new CurlUpload(); // curlDownlaod->postJson(postStr); _yun.name = name; _yun.timeStr = timeStr; _yun.pwd = pwd; _yun.version = QString::number(version); this->setCursor(Qt::ArrowCursor); // return; //// ///线程上传 retSize = "-2"; Thread *workerThread = new Thread(this, 4); connect(workerThread, &Thread::resultYun, this, &ReleaseDialog::uploadsuccess); connect(workerThread, &Thread::start_upload, this, &ReleaseDialog::timeStart); connect(workerThread, &Thread::finished, workerThread, &QObject::deleteLater); workerThread->setUploadYun(destName, destPath, &retSize); workerThread->start(); startValue = true; }
bool ABIMacOSX_arm::PrepareTrivialCall (Thread &thread, addr_t sp, addr_t function_addr, addr_t return_addr, llvm::ArrayRef<addr_t> args) const { RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return false; const uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); const uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); const uint32_t ra_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); RegisterValue reg_value; const char *reg_names[] = { "r0", "r1", "r2", "r3" }; llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end(); for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i) { if (ai == ae) break; reg_value.SetUInt32(*ai); if (!reg_ctx->WriteRegister(reg_ctx->GetRegisterInfoByName(reg_names[i]), reg_value)) return false; ++ai; } if (ai != ae) { // Spill onto the stack size_t num_stack_regs = ae - ai; sp -= (num_stack_regs * 4); // Keep the stack 8 byte aligned, not that we need to sp &= ~(8ull-1ull); // just using arg1 to get the right size const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); addr_t arg_pos = sp; for (; ai != ae; ++ai) { reg_value.SetUInt32(*ai); if (reg_ctx->WriteRegisterValueToMemory(reg_info, arg_pos, reg_info->byte_size, reg_value).Fail()) return false; arg_pos += reg_info->byte_size; } } TargetSP target_sp (thread.CalculateTarget()); Address so_addr; // Figure out if our return address is ARM or Thumb by using the // Address::GetCallableLoadAddress(Target*) which will figure out the ARM // thumb-ness and set the correct address bits for us. so_addr.SetLoadAddress (return_addr, target_sp.get()); return_addr = so_addr.GetCallableLoadAddress (target_sp.get()); // Set "lr" to the return address if (!reg_ctx->WriteRegisterFromUnsigned (ra_reg_num, return_addr)) return false; // Set "sp" to the requested value if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_num, sp)) return false; // If bit zero or 1 is set, this must be a thumb function, no need to figure // this out from the symbols. so_addr.SetLoadAddress (function_addr, target_sp.get()); function_addr = so_addr.GetCallableLoadAddress (target_sp.get()); const RegisterInfo *cpsr_reg_info = reg_ctx->GetRegisterInfoByName("cpsr"); const uint32_t curr_cpsr = reg_ctx->ReadRegisterAsUnsigned(cpsr_reg_info, 0); // Make a new CPSR and mask out any Thumb IT (if/then) bits uint32_t new_cpsr = curr_cpsr & ~MASK_CPSR_IT_MASK; // If bit zero or 1 is set, this must be thumb... if (function_addr & 1ull) new_cpsr |= MASK_CPSR_T; // Set T bit in CPSR else new_cpsr &= ~MASK_CPSR_T; // Clear T bit in CPSR if (new_cpsr != curr_cpsr) { if (!reg_ctx->WriteRegisterFromUnsigned (cpsr_reg_info, new_cpsr)) return false; } function_addr &= ~1ull; // clear bit zero since the CPSR will take care of the mode for us // Set "pc" to the address requested if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_num, function_addr)) return false; return true; }
ValueObjectSP ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread, lldb_private::ClangASTType &clang_type) const { Value value; ValueObjectSP return_valobj_sp; if (!clang_type) return return_valobj_sp; clang::ASTContext *ast_context = clang_type.GetASTContext(); if (!ast_context) return return_valobj_sp; //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType()); value.SetClangType (clang_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; bool is_signed; // Get the pointer to the first stack argument so we have a place to start // when reading data const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0); if (clang_type.IsIntegerType (is_signed)) { size_t bit_width = clang_type.GetBitSize(); switch (bit_width) { default: return return_valobj_sp; case 64: { const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0); uint64_t raw_value; raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & UINT32_MAX)) << 32; if (is_signed) value.GetScalar() = (int64_t)raw_value; else value.GetScalar() = (uint64_t)raw_value; } break; case 32: if (is_signed) value.GetScalar() = (int32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX); else value.GetScalar() = (uint32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX); break; case 16: if (is_signed) value.GetScalar() = (int16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX); else value.GetScalar() = (uint16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX); break; case 8: if (is_signed) value.GetScalar() = (int8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX); else value.GetScalar() = (uint8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX); break; } } else if (clang_type.IsPointerType ()) { uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; value.GetScalar() = ptr; } else { // not handled yet return return_valobj_sp; } // If we get here, we have a valid Value, so make our ValueObject out of it: return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); return return_valobj_sp; }
bool ThreadSpec::IndexMatches(Thread &thread) const { if (m_index == UINT32_MAX) return true; uint32_t index = thread.GetIndexID(); return IndexMatches(index); }
void Thread::split(Position& pos, SearchStack* ss, const Score alpha, const Score beta, Score& bestScore, Move& bestMove, const Depth depth, const Move threatMove, const int moveCount, MovePicker& mp, const NodeType nodeType, const bool cutNode) { assert(pos.isOK()); assert(bestScore <= alpha && alpha < beta && beta <= ScoreInfinite); assert(-ScoreInfinite < bestScore); assert(searcher->threads.minSplitDepth() <= depth); assert(searching); assert(splitPointsSize < MaxSplitPointsPerThread); SplitPoint& sp = splitPoints[splitPointsSize]; sp.masterThread = this; sp.parentSplitPoint = activeSplitPoint; sp.slavesMask = UINT64_C(1) << idx; sp.depth = depth; sp.bestMove = bestMove; sp.threatMove = threatMove; sp.alpha = alpha; sp.beta = beta; sp.nodeType = nodeType; sp.cutNode = cutNode; sp.bestScore = bestScore; sp.movePicker = ∓ sp.moveCount = moveCount; sp.pos = &pos; sp.nodes = 0; sp.cutoff = false; sp.ss = ss; searcher->threads.mutex_.lock(); sp.mutex.lock(); ++splitPointsSize; activeSplitPoint = &sp; activePosition = nullptr; // thisThread が常に含まれるので 1 size_t slavesCount = 1; Thread* slave; while ((slave = searcher->threads.availableSlave(this)) != nullptr && ++slavesCount <= searcher->threads.maxThreadsPerSplitPoint_ && !Fake) { sp.slavesMask |= UINT64_C(1) << slave->idx; slave->activeSplitPoint = &sp; slave->searching = true; slave->notifyOne(); } if (1 < slavesCount || Fake) { sp.mutex.unlock(); searcher->threads.mutex_.unlock(); Thread::idleLoop(); assert(!searching); assert(!activePosition); searcher->threads.mutex_.lock(); sp.mutex.lock(); } searching = true; --splitPointsSize; activeSplitPoint = sp.parentSplitPoint; activePosition = &pos; pos.setNodesSearched(pos.nodesSearched() + sp.nodes); bestMove = sp.bestMove; bestScore = sp.bestScore; searcher->threads.mutex_.unlock(); sp.mutex.unlock(); }
void test_memover1(void) { VM::setAlertGCCallback(alertGC); Bytecode* myBytecode = gCodeManager.readBytecode("test.hyb"); CPPUNIT_ASSERT(myBytecode != NULL); myBytecode->setInitialized(); Value mcls(HC_Class, (void*) myBytecode->mainClass()); alert_count = prev_alert_count = 0; int c = 0; while (c < 30) { Context* context = gCodeManager.createContext(); Thread* pThread = gThreadManager.createTmpThread(); pThread->initialize(context); context->pushInt(10); context->methodCall(mcls, HSym_create_XClass, 1); pThread->start(); while (pThread->isActive()) pThread->exec1tick(); context->pop(); gCodeManager.releaseContext(context); if (check_alert()) ++c; } c = 0; while (c < 30) { Context* context = gCodeManager.createContext(); Thread* pThread = gThreadManager.createTmpThread(); pThread->initialize(context); context->pushInt(500); context->methodCall(mcls, HSym_create_XClass, 1); pThread->start(); while (pThread->isActive()) pThread->exec1tick(); context->pop(); gCodeManager.releaseContext(context); if (check_alert()) ++c; } c = 0; while (c < 30) { Context* context = gCodeManager.createContext(); Thread* pThread = gThreadManager.createTmpThread(); pThread->initialize(context); context->methodCall(mcls, HSym_create_YClass, 0); pThread->start(); while (pThread->isActive()) pThread->exec1tick(); context->pop(); gCodeManager.releaseContext(context); if (check_alert()) ++c; } }
ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, lldb_private::CompilerType &compiler_type) const { Value value; ValueObjectSP return_valobj_sp; if (!compiler_type) return return_valobj_sp; //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType()); value.SetCompilerType (compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; bool is_signed; bool is_complex; uint32_t float_count; // Get the pointer to the first stack argument so we have a place to start // when reading data const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); size_t bit_width = compiler_type.GetBitSize(&thread); if (compiler_type.IsIntegerType (is_signed)) { switch (bit_width) { default: return return_valobj_sp; case 64: { const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2); uint64_t raw_value; raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & UINT32_MAX)) << 32; if (is_signed) value.GetScalar() = (int64_t)raw_value; else value.GetScalar() = (uint64_t)raw_value; } break; case 32: if (is_signed) value.GetScalar() = (int32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX); else value.GetScalar() = (uint32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX); break; case 16: if (is_signed) value.GetScalar() = (int16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX); else value.GetScalar() = (uint16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX); break; case 8: if (is_signed) value.GetScalar() = (int8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX); else value.GetScalar() = (uint8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX); break; } } else if (compiler_type.IsPointerType ()) { uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; value.GetScalar() = ptr; } else if (compiler_type.IsVectorType(nullptr, nullptr)) { size_t byte_size = compiler_type.GetByteSize(&thread); if (byte_size <= 16) { DataBufferHeap buffer(16, 0); uint32_t* buffer_ptr = (uint32_t*)buffer.GetBytes(); for (uint32_t i = 0; 4*i < byte_size; ++i) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); buffer_ptr[i] = reg_ctx->ReadRegisterAsUnsigned(reg_info, 0) & UINT32_MAX; } value.SetBytes(buffer.GetBytes(), byte_size); } else { if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value)) return return_valobj_sp; } } else if (compiler_type.IsFloatingPointType(float_count, is_complex)) { if (float_count == 1 && !is_complex) { switch (bit_width) { default: return return_valobj_sp; case 64: { static_assert(sizeof(double) == sizeof(uint64_t), ""); const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2); uint64_t raw_value; raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & UINT32_MAX)) << 32; value.GetScalar() = *reinterpret_cast<double*>(&raw_value); break; } case 16: // Half precision returned after a conversion to single precision case 32: { static_assert(sizeof(float) == sizeof(uint32_t), ""); uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; value.GetScalar() = *reinterpret_cast<float*>(&raw_value); break; } } } else { // not handled yet return return_valobj_sp; } } else if (compiler_type.IsAggregateType()) { size_t byte_size = compiler_type.GetByteSize(&thread); if (byte_size <= 4) { RegisterValue r0_reg_value; uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; value.SetBytes(&raw_value, byte_size); } else { if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value)) return return_valobj_sp; } } else { // not handled yet return return_valobj_sp; } // If we get here, we have a valid Value, so make our ValueObject out of it: return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); return return_valobj_sp; }
ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, ClangASTType &return_clang_type) const { ValueObjectSP return_valobj_sp; Value value; if (!return_clang_type) return return_valobj_sp; //value.SetContext (Value::eContextTypeClangType, return_value_type); value.SetClangType (return_clang_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; const uint32_t type_flags = return_clang_type.GetTypeInfo (); if (type_flags & eTypeIsScalar) { value.SetValueType(Value::eValueTypeScalar); bool success = false; if (type_flags & eTypeIsInteger) { // Extract the register context so we can read arguments from registers const size_t byte_size = return_clang_type.GetByteSize(nullptr); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) { default: break; case sizeof(uint64_t): if (is_signed) value.GetScalar() = (int64_t)(raw_value); else value.GetScalar() = (uint64_t)(raw_value); success = true; break; case sizeof(uint32_t): if (is_signed) value.GetScalar() = (int32_t)(raw_value & UINT32_MAX); else value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX); success = true; break; case sizeof(uint16_t): if (is_signed) value.GetScalar() = (int16_t)(raw_value & UINT16_MAX); else value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX); success = true; break; case sizeof(uint8_t): if (is_signed) value.GetScalar() = (int8_t)(raw_value & UINT8_MAX); else value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX); success = true; break; } } else if (type_flags & eTypeIsFloat) { if (type_flags & eTypeIsComplex) { // Don't handle complex yet. } else { const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size <= sizeof(long double)) { const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); RegisterValue f1_value; if (reg_ctx->ReadRegister (f1_info, f1_value)) { DataExtractor data; if (f1_value.GetData(data)) { lldb::offset_t offset = 0; if (byte_size == sizeof(float)) { value.GetScalar() = (float) data.GetFloat(&offset); success = true; } else if (byte_size == sizeof(double)) { value.GetScalar() = (double) data.GetDouble(&offset); success = true; } } } } } } if (success) return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsPointer) { unsigned r3_id = reg_ctx->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB]; value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0); value.SetValueType(Value::eValueTypeScalar); return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsVector) { const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size > 0) { const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v2", 0); if (altivec_reg) { if (byte_size <= altivec_reg->byte_size) { ProcessSP process_sp (thread.GetProcess()); if (process_sp) { std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0)); const ByteOrder byte_order = process_sp->GetByteOrder(); RegisterValue reg_value; if (reg_ctx->ReadRegister(altivec_reg, reg_value)) { Error error; if (reg_value.GetAsMemoryData (altivec_reg, heap_data_ap->GetBytes(), heap_data_ap->GetByteSize(), byte_order, error)) { DataExtractor data (DataBufferSP (heap_data_ap.release()), byte_order, process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); return_valobj_sp = ValueObjectConstResult::Create (&thread, return_clang_type, ConstString(""), data); } } } } } } } return return_valobj_sp; }
ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const { ValueObjectSP return_valobj_sp; if (!return_clang_type) return return_valobj_sp; ExecutionContext exe_ctx (thread.shared_from_this()); return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); if (return_valobj_sp) return return_valobj_sp; RegisterContextSP reg_ctx_sp = thread.GetRegisterContext(); if (!reg_ctx_sp) return return_valobj_sp; const size_t bit_width = return_clang_type.GetBitSize(&thread); if (return_clang_type.IsAggregateType()) { Target *target = exe_ctx.GetTargetPtr(); bool is_memory = true; if (bit_width <= 128) { ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder(); DataBufferSP data_sp (new DataBufferHeap(16, 0)); DataExtractor return_ext (data_sp, target_byte_order, target->GetArchitecture().GetAddressByteSize()); const RegisterInfo *r3_info = reg_ctx_sp->GetRegisterInfoByName("r3", 0); const RegisterInfo *rdx_info = reg_ctx_sp->GetRegisterInfoByName("rdx", 0); RegisterValue r3_value, rdx_value; reg_ctx_sp->ReadRegister (r3_info, r3_value); reg_ctx_sp->ReadRegister (rdx_info, rdx_value); DataExtractor r3_data, rdx_data; r3_value.GetData(r3_data); rdx_value.GetData(rdx_data); uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far uint32_t integer_bytes = 0; // Tracks how much of the r3/rds registers we've consumed so far const uint32_t num_children = return_clang_type.GetNumFields (); // Since we are in the small struct regime, assume we are not in memory. is_memory = false; for (uint32_t idx = 0; idx < num_children; idx++) { std::string name; uint64_t field_bit_offset = 0; bool is_signed; bool is_complex; uint32_t count; ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); const size_t field_bit_width = field_clang_type.GetBitSize(&thread); // If there are any unaligned fields, this is stored in memory. if (field_bit_offset % field_bit_width != 0) { is_memory = true; break; } uint32_t field_byte_width = field_bit_width/8; uint32_t field_byte_offset = field_bit_offset/8; DataExtractor *copy_from_extractor = NULL; uint32_t copy_from_offset = 0; if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ()) { if (integer_bytes < 8) { if (integer_bytes + field_byte_width <= 8) { // This is in RAX, copy from register to our result structure: copy_from_extractor = &r3_data; copy_from_offset = integer_bytes; integer_bytes += field_byte_width; } else { // The next field wouldn't fit in the remaining space, so we pushed it to rdx. copy_from_extractor = &rdx_data; copy_from_offset = 0; integer_bytes = 8 + field_byte_width; } } else if (integer_bytes + field_byte_width <= 16) { copy_from_extractor = &rdx_data; copy_from_offset = integer_bytes - 8; integer_bytes += field_byte_width; } else { // The last field didn't fit. I can't see how that would happen w/o the overall size being // greater than 16 bytes. For now, return a NULL return value object. return return_valobj_sp; } } else if (field_clang_type.IsFloatingPointType (count, is_complex)) { // Structs with long doubles are always passed in memory. if (field_bit_width == 128) { is_memory = true; break; } else if (field_bit_width == 64) { copy_from_offset = 0; fp_bytes += field_byte_width; } else if (field_bit_width == 32) { // This one is kind of complicated. If we are in an "eightbyte" with another float, we'll // be stuffed into an xmm register with it. If we are in an "eightbyte" with one or more ints, // then we will be stuffed into the appropriate GPR with them. bool in_gpr; if (field_byte_offset % 8 == 0) { // We are at the beginning of one of the eightbytes, so check the next element (if any) if (idx == num_children - 1) in_gpr = false; else { uint64_t next_field_bit_offset = 0; ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1, name, &next_field_bit_offset, NULL, NULL); if (next_field_clang_type.IsIntegerType (is_signed)) in_gpr = true; else { copy_from_offset = 0; in_gpr = false; } } } else if (field_byte_offset % 4 == 0) { // We are inside of an eightbyte, so see if the field before us is floating point: // This could happen if somebody put padding in the structure. if (idx == 0) in_gpr = false; else { uint64_t prev_field_bit_offset = 0; ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1, name, &prev_field_bit_offset, NULL, NULL); if (prev_field_clang_type.IsIntegerType (is_signed)) in_gpr = true; else { copy_from_offset = 4; in_gpr = false; } } } else { is_memory = true; continue; } // Okay, we've figured out whether we are in GPR or XMM, now figure out which one. if (in_gpr) { if (integer_bytes < 8) { // This is in RAX, copy from register to our result structure: copy_from_extractor = &r3_data; copy_from_offset = integer_bytes; integer_bytes += field_byte_width; } else { copy_from_extractor = &rdx_data; copy_from_offset = integer_bytes - 8; integer_bytes += field_byte_width; } } else { fp_bytes += field_byte_width; } } } // These two tests are just sanity checks. If I somehow get the // type calculation wrong above it is better to just return nothing // than to assert or crash. if (!copy_from_extractor) return return_valobj_sp; if (copy_from_offset + field_byte_width > copy_from_extractor->GetByteSize()) return return_valobj_sp; copy_from_extractor->CopyByteOrderedData (copy_from_offset, field_byte_width, data_sp->GetBytes() + field_byte_offset, field_byte_width, target_byte_order); } if (!is_memory) { // The result is in our data buffer. Let's make a variable object out of it: return_valobj_sp = ValueObjectConstResult::Create (&thread, return_clang_type, ConstString(""), return_ext); } } // FIXME: This is just taking a guess, r3 may very well no longer hold the return storage location. // If we are going to do this right, when we make a new frame we should check to see if it uses a memory // return, and if we are at the first instruction and if so stash away the return location. Then we would // only return the memory return value if we know it is valid. if (is_memory) { unsigned r3_id = reg_ctx_sp->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB]; lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0); return_valobj_sp = ValueObjectMemory::Create (&thread, "", Address (storage_addr, NULL), return_clang_type); } } return return_valobj_sp; }
bool ABISysV_ppc::GetArgumentValues (Thread &thread, ValueList &values) const { unsigned int num_values = values.GetSize(); unsigned int value_index; // Extract the register context so we can read arguments from registers RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return false; // Get the pointer to the first stack argument so we have a place to start // when reading data addr_t sp = reg_ctx->GetSP(0); if (!sp) return false; addr_t current_stack_argument = sp + 48; // jump over return address uint32_t argument_register_ids[8]; argument_register_ids[0] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1)->kinds[eRegisterKindLLDB]; argument_register_ids[1] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2)->kinds[eRegisterKindLLDB]; argument_register_ids[2] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3)->kinds[eRegisterKindLLDB]; argument_register_ids[3] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4)->kinds[eRegisterKindLLDB]; argument_register_ids[4] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5)->kinds[eRegisterKindLLDB]; argument_register_ids[5] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG6)->kinds[eRegisterKindLLDB]; argument_register_ids[6] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG7)->kinds[eRegisterKindLLDB]; argument_register_ids[7] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG8)->kinds[eRegisterKindLLDB]; unsigned int current_argument_register = 0; for (value_index = 0; value_index < num_values; ++value_index) { Value *value = values.GetValueAtIndex(value_index); if (!value) return false; // We currently only support extracting values with Clang QualTypes. // Do we care about others? ClangASTType clang_type = value->GetClangType(); if (!clang_type) return false; bool is_signed; if (clang_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), clang_type.GetBitSize(&thread), is_signed, thread, argument_register_ids, current_argument_register, current_stack_argument); } else if (clang_type.IsPointerType ()) { ReadIntegerArgument(value->GetScalar(), clang_type.GetBitSize(&thread), false, thread, argument_register_ids, current_argument_register, current_stack_argument); } } return true; }
Error ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) { Error error; if (!new_value_sp) { error.SetErrorString("Empty value object for return value."); return error; } ClangASTType clang_type = new_value_sp->GetClangType(); if (!clang_type) { error.SetErrorString ("Null clang type for return value."); return error; } Thread *thread = frame_sp->GetThread().get(); bool is_signed; uint32_t count; bool is_complex; RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); DataExtractor data; Error data_error; size_t num_bytes = new_value_sp->GetData(data, data_error); if (data_error.Fail()) { error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString()); return error; } lldb::offset_t offset = 0; if (num_bytes <= 8) { uint64_t raw_value = data.GetMaxU64(&offset, num_bytes); if (reg_ctx->WriteRegisterFromUnsigned (reg_info, raw_value)) set_it_simple = true; } else { error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); } } else if (clang_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); else { size_t bit_width = clang_type.GetBitSize(frame_sp.get()); if (bit_width <= 64) { DataExtractor data; Error data_error; size_t num_bytes = new_value_sp->GetData(data, data_error); if (data_error.Fail()) { error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString()); return error; } unsigned char buffer[16]; ByteOrder byte_order = data.GetByteOrder(); data.CopyByteOrderedData (0, num_bytes, buffer, 16, byte_order); set_it_simple = true; } else { // FIXME - don't know how to do 80 bit long doubles yet. error.SetErrorString ("We don't support returning float values > 64 bits at present"); } } } if (!set_it_simple) { // Okay we've got a structure or something that doesn't fit in a simple register. // We should figure out where it really goes, but we don't support this yet. error.SetErrorString ("We only support setting simple integer and float return types at present."); } return error; }
bool ABISysV_ppc::PrepareTrivialCall (Thread &thread, addr_t sp, addr_t func_addr, addr_t return_addr, llvm::ArrayRef<addr_t> args) const { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); if (log) { StreamString s; s.Printf("ABISysV_ppc::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64, thread.GetID(), (uint64_t)sp, (uint64_t)func_addr, (uint64_t)return_addr); for (size_t i = 0; i < args.size(); ++i) s.Printf (", arg%zd = 0x%" PRIx64, i + 1, args[i]); s.PutCString (")"); log->PutCString(s.GetString().c_str()); } RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return false; const RegisterInfo *reg_info = NULL; if (args.size() > 8) // TODO handle more than 8 arguments return false; for (size_t i = 0; i < args.size(); ++i) { reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); if (log) log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name); if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) return false; } // First, align the SP if (log) log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, (uint64_t)sp, (uint64_t)(sp & ~0xfull)); sp &= ~(0xfull); // 16-byte alignment sp -= 8; Error error; const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); ProcessSP process_sp (thread.GetProcess()); RegisterValue reg_value; #if 0 // This code adds an extra frame so that we don't lose the function that we came from // by pushing the PC and the FP and then writing the current FP to point to the FP value // we just pushed. It is disabled for now until the stack backtracing code can be debugged. // Save current PC const RegisterInfo *fp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); if (reg_ctx->ReadRegister(pc_reg_info, reg_value)) { if (log) log->Printf("Pushing the current PC onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) return false; sp -= 8; // Save current FP if (reg_ctx->ReadRegister(fp_reg_info, reg_value)) { if (log) log->Printf("Pushing the current FP onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64()); if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error)) return false; } // Setup FP backchain reg_value.SetUInt64 (sp); if (log) log->Printf("Writing FP: 0x%" PRIx64 " (for FP backchain)", reg_value.GetAsUInt64()); if (!reg_ctx->WriteRegister(fp_reg_info, reg_value)) { return false; } sp -= 8; } #endif if (log) log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, (uint64_t)return_addr); // Save return address onto the stack if (!process_sp->WritePointerToMemory(sp, return_addr, error)) return false; // %r1 is set to the actual stack value. if (log) log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp)) return false; // %pc is set to the address of the called function. if (log) log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr); if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr)) return false; return true; }
/// <summary> /// Execute code in context of any existing thread /// </summary> /// <param name="pCode">Cde to execute</param> /// <param name="size">Code size.</param> /// <param name="callResult">Execution result</param> /// <param name="thd">Target thread</param> /// <returns>Status</returns> NTSTATUS RemoteExec::ExecInAnyThread( PVOID pCode, size_t size, uint64_t& callResult, Thread& thd ) { NTSTATUS dwResult = STATUS_SUCCESS; CONTEXT_T ctx; // Prepare for remote exec CreateRPCEnvironment( true ); // Write code dwResult = CopyCode( pCode, size ); if (dwResult != STATUS_SUCCESS) return dwResult; if (_hWaitEvent) ResetEvent( _hWaitEvent ); if (!thd.Suspend()) return LastNtStatus(); if (thd.GetContext( ctx, CONTEXT_ALL, true )) { AsmJit::Assembler a; AsmJitHelper ah( a ); #ifdef _M_AMD64 const int count = 15; AsmJit::GPReg regs[] = { AsmJit::rax, AsmJit::rbx, AsmJit::rcx, AsmJit::rdx, AsmJit::rsi, AsmJit::rdi, AsmJit::r8, AsmJit::r9, AsmJit::r10, AsmJit::r11, AsmJit::r12, AsmJit::r13, AsmJit::r14, AsmJit::r15, AsmJit::rbp }; // // Preserve thread context // I don't care about FPU, XMM and anything else // a.sub(AsmJit::rsp, count * WordSize); // Stack must be aligned on 16 bytes a.pushfq(); // // Save registers for (int i = 0; i < count; i++) a.mov( AsmJit::Mem( AsmJit::rsp, i * WordSize ), regs[i] ); ah.GenCall( _userCode.ptr<size_t>(), { _userData.ptr<size_t>() } ); AddReturnWithEvent( ah, rt_int32, INTRET_OFFSET ); // Restore registers for (int i = 0; i < count; i++) a.mov( regs[i], AsmJit::Mem( AsmJit::rsp, i * WordSize ) ); a.popfq(); a.add( AsmJit::rsp, count * WordSize ); a.jmp( ctx.Rip ); #else a.pushad(); a.pushfd(); ah.GenCall( _userCode.ptr<size_t>(), { _userData.ptr<size_t>() } ); AddReturnWithEvent( ah, rt_int32, INTRET_OFFSET ); a.popfd(); a.popad(); a.push( ctx.NIP ); a.ret(); #endif if (_userCode.Write( size, a.getCodeSize(), a.make() ) == STATUS_SUCCESS) { ctx.NIP = _userCode.ptr<size_t>() + size; if (!thd.SetContext( ctx, true )) dwResult = LastNtStatus(); } else dwResult = LastNtStatus(); } else dwResult = LastNtStatus(); thd.Resume(); if (dwResult == STATUS_SUCCESS) { WaitForSingleObject( _hWaitEvent, INFINITE ); callResult = _userData.Read<size_t>( INTRET_OFFSET, 0 ); } return dwResult; }
//---------------------------------------------------------------------- // ThreadPlanCallFunction: Plan to call a single function //---------------------------------------------------------------------- bool ThreadPlanCallFunction::ConstructorSetup (Thread &thread, ABI *& abi, lldb::addr_t &start_load_addr, lldb::addr_t &function_load_addr) { SetIsMasterPlan (true); SetOkayToDiscard (false); SetPrivate (true); ProcessSP process_sp (thread.GetProcess()); if (!process_sp) return false; abi = process_sp->GetABI().get(); if (!abi) return false; Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP)); SetBreakpoints(); m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); // If we can't read memory at the point of the process where we are planning to put our function, we're // not going to get any further... Error error; process_sp->ReadUnsignedIntegerFromMemory(m_function_sp, 4, 0, error); if (!error.Success()) { m_constructor_errors.Printf ("Trying to put the stack in unreadable memory at: 0x%" PRIx64 ".", m_function_sp); if (log) log->Printf ("ThreadPlanCallFunction(%p): %s.", static_cast<void*>(this), m_constructor_errors.GetData()); return false; } Module *exe_module = GetTarget().GetExecutableModulePointer(); if (exe_module == NULL) { m_constructor_errors.Printf ("Can't execute code without an executable module."); if (log) log->Printf ("ThreadPlanCallFunction(%p): %s.", static_cast<void*>(this), m_constructor_errors.GetData()); return false; } else { ObjectFile *objectFile = exe_module->GetObjectFile(); if (!objectFile) { m_constructor_errors.Printf ("Could not find object file for module \"%s\".", exe_module->GetFileSpec().GetFilename().AsCString()); if (log) log->Printf ("ThreadPlanCallFunction(%p): %s.", static_cast<void*>(this), m_constructor_errors.GetData()); return false; } m_start_addr = objectFile->GetEntryPointAddress(); if (!m_start_addr.IsValid()) { m_constructor_errors.Printf ("Could not find entry point address for executable module \"%s\".", exe_module->GetFileSpec().GetFilename().AsCString()); if (log) log->Printf ("ThreadPlanCallFunction(%p): %s.", static_cast<void*>(this), m_constructor_errors.GetData()); return false; } } start_load_addr = m_start_addr.GetLoadAddress (&GetTarget()); // Checkpoint the thread state so we can restore it later. if (log && log->GetVerbose()) ReportRegisterState ("About to checkpoint thread before function call. Original register state was:"); if (!thread.CheckpointThreadState (m_stored_thread_state)) { m_constructor_errors.Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state."); if (log) log->Printf ("ThreadPlanCallFunction(%p): %s.", static_cast<void*>(this), m_constructor_errors.GetData()); return false; } function_load_addr = m_function_addr.GetLoadAddress (&GetTarget()); return true; }
void test_instance(void) { MemPool* pool = gMemPool; // ffi定義が無いのでbindFfiClassTable不要 Bytecode* myBytecode = gCodeManager.readBytecode("test.hyb"); CPPUNIT_ASSERT(myBytecode != NULL); myBytecode->setInitialized(); // gc_test_instance() をスレッドで実行 Thread* pThread = gThreadManager.createTmpThread(); Context* context = gCodeManager.createContext(); pThread->initialize(context); context->pushClass(myBytecode->mainClass()); context->methodCall(HSym_gc_test_instance, 0); gCodeManager.releaseContext(context); // contextのdeleteはGCまかせ pThread->start(); GC::full(); pThread->exec1tick(); int n, m; n = GC::countObjects(pool); // start pThread->exec1tick(); GC::full(); m = GC::countObjects(pool); CPPUNIT_ASSERT_EQUAL(n-1, m); // -1 pThread->exec1tick(); GC::full(); n = GC::countObjects(pool); CPPUNIT_ASSERT_EQUAL(m, n); // -0 pThread->exec1tick(); GC::full(); m = GC::countObjects(pool); CPPUNIT_ASSERT_EQUAL(n, m); // -0 pThread->exec1tick(); GC::full(); n = GC::countObjects(pool); CPPUNIT_ASSERT_EQUAL(m-3, n); // -3 pThread->exec1tick(); GC::full(); m = GC::countObjects(pool); CPPUNIT_ASSERT_EQUAL(n-1, m); // -1 CPPUNIT_ASSERT_EQUAL(Thread::WAITING_TICK, pThread->state()); pThread->exec1tick(); CPPUNIT_ASSERT_EQUAL(Thread::TERMINATED, pThread->state()); GC::full(); n = GC::countObjects(pool); CPPUNIT_ASSERT_EQUAL(m-2, n); // -2 // pThread,context は GC に回収されている }
static void* trampoline(void* arg) { Thread* self = reinterpret_cast<Thread*>(arg); self->perform(); if(self->delete_on_exit()) delete self; return NULL; }
void test_threadGC(void) { Bytecode* myBytecode = gCodeManager.readBytecode("test.hyb"); myBytecode->setInitialized(); Context* context = gCodeManager.createContext(); Thread* pThread = gThreadManager.createTmpThread(); context->pushClass(myBytecode->mainClass()); context->methodCall(HSym_gc_test_thread_sweep, 0); pThread->initialize(context); pThread->start(); gCodeManager.releaseContext(context); while (gThreadManager.isThreadRunning()) gThreadManager.exec1tick(); gThreadManager.destroyTmpThread(pThread); GC::full(); GC::coalesce(); pThread = gThreadManager.createTmpThread(); context = gCodeManager.createContext(); context->pushClass(myBytecode->mainClass()); context->methodCall(HSym_gc_test_thread_sweep, 0); pThread->initialize(context); pThread->start(); gCodeManager.releaseContext(context); while (gThreadManager.isThreadRunning()) gThreadManager.exec1tick(); gThreadManager.destroyTmpThread(pThread); GC::unmark(); pThread = gThreadManager.createTmpThread(); context = gCodeManager.createContext(); context->pushClass(myBytecode->mainClass()); context->methodCall(HSym_gc_test_thread_sweep, 0); pThread->initialize(context); pThread->start(); gCodeManager.releaseContext(context); while (gThreadManager.isThreadRunning()) gThreadManager.exec1tick(); gThreadManager.destroyTmpThread(pThread); GC::markAll(); GC::sweep(); GC::coalesce(); pThread = gThreadManager.createTmpThread(); context = gCodeManager.createContext(); context->pushClass(myBytecode->mainClass()); context->methodCall(HSym_gc_test_thread_sweep, 0); pThread->initialize(context); pThread->start(); gCodeManager.releaseContext(context); while (gThreadManager.isThreadRunning()) gThreadManager.exec1tick(); gThreadManager.destroyTmpThread(pThread); GC::unmark(); GC::markAll(); pThread = gThreadManager.createTmpThread(); context = gCodeManager.createContext(); context->pushClass(myBytecode->mainClass()); context->methodCall(HSym_gc_test_thread_sweep, 0); pThread->initialize(context); pThread->start(); gCodeManager.releaseContext(context); while (gThreadManager.isThreadRunning()) gThreadManager.exec1tick(); gThreadManager.destroyTmpThread(pThread); GC::sweep(); GC::coalesce(); }
void start(){ tlog("start(). this="<<this); thread = Thread<Counter, int>::createThread(this, &Counter::run); thread->start(0); }
extern "C" void *ThreadStartup(void *_tgtObject) { Thread *tgtObject = (Thread *)_tgtObject; tgtObject->run(); return NULL; }
// global thread caallback unsigned int _ou_thread_proc(void* param) { Thread* tp = (Thread*)param; tp->run(); return 0; }
void tst_QMutex::tryLock() { // test non-recursive mutex { class Thread : public QThread { public: void run() { testsTurn.release(); threadsTurn.acquire(); QVERIFY(!normalMutex.tryLock()); testsTurn.release(); threadsTurn.acquire(); QVERIFY(normalMutex.tryLock()); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); QVERIFY(!normalMutex.tryLock()); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); normalMutex.unlock(); testsTurn.release(); threadsTurn.acquire(); QTime timer; timer.start(); QVERIFY(!normalMutex.tryLock(1000)); QVERIFY(timer.elapsed() >= 1000); testsTurn.release(); threadsTurn.acquire(); timer.start(); QVERIFY(normalMutex.tryLock(1000)); QVERIFY(timer.elapsed() <= 1000); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); timer.start(); QVERIFY(!normalMutex.tryLock(1000)); QVERIFY(timer.elapsed() >= 1000); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); normalMutex.unlock(); testsTurn.release(); threadsTurn.acquire(); } }; Thread thread; thread.start(); testsTurn.acquire(); normalMutex.lock(); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); threadsTurn.release(); testsTurn.acquire(); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); normalMutex.unlock(); threadsTurn.release(); testsTurn.acquire(); normalMutex.lock(); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); threadsTurn.release(); testsTurn.acquire(); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); normalMutex.unlock(); threadsTurn.release(); // wait for thread to finish testsTurn.acquire(); threadsTurn.release(); thread.wait(); } // test recursive mutex { class Thread : public QThread { public: void run() { testsTurn.release(); threadsTurn.acquire(); QVERIFY(!recursiveMutex.tryLock()); testsTurn.release(); threadsTurn.acquire(); QVERIFY(recursiveMutex.tryLock()); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); QVERIFY(recursiveMutex.tryLock()); QVERIFY(lockCount.testAndSetRelaxed(1, 2)); QVERIFY(lockCount.testAndSetRelaxed(2, 1)); recursiveMutex.unlock(); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); recursiveMutex.unlock(); testsTurn.release(); threadsTurn.acquire(); QTime timer; timer.start(); QVERIFY(!recursiveMutex.tryLock(1000)); QVERIFY(timer.elapsed() >= 1000); testsTurn.release(); threadsTurn.acquire(); timer.start(); QVERIFY(recursiveMutex.tryLock(1000)); QVERIFY(timer.elapsed() <= 1000); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); QVERIFY(recursiveMutex.tryLock(1000)); QVERIFY(lockCount.testAndSetRelaxed(1, 2)); QVERIFY(lockCount.testAndSetRelaxed(2, 1)); recursiveMutex.unlock(); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); recursiveMutex.unlock(); testsTurn.release(); threadsTurn.acquire(); } }; Thread thread; thread.start(); testsTurn.acquire(); recursiveMutex.lock(); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); recursiveMutex.lock(); QVERIFY(lockCount.testAndSetRelaxed(1, 2)); threadsTurn.release(); testsTurn.acquire(); QVERIFY(lockCount.testAndSetRelaxed(2, 1)); recursiveMutex.unlock(); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); recursiveMutex.unlock(); threadsTurn.release(); testsTurn.acquire(); recursiveMutex.lock(); QVERIFY(lockCount.testAndSetRelaxed(0, 1)); recursiveMutex.lock(); QVERIFY(lockCount.testAndSetRelaxed(1, 2)); threadsTurn.release(); testsTurn.acquire(); QVERIFY(lockCount.testAndSetRelaxed(2, 1)); recursiveMutex.unlock(); QVERIFY(lockCount.testAndSetRelaxed(1, 0)); recursiveMutex.unlock(); threadsTurn.release(); // stop thread testsTurn.acquire(); threadsTurn.release(); thread.wait(); } }
uint32_t EventableResource::getTruncatedEV(Thread &thread) const { if (EV == getID()) return EV; return (EV & 0xffff) | thread.getParent().ram_base; }
void Thread::split(Position& pos, Stack* ss, Value alpha, Value beta, Value* bestValue, Move* bestMove, Depth depth, int moveCount, MovePicker* movePicker, int nodeType, bool cutNode) { assert(searching); assert(-VALUE_INFINITE < *bestValue && *bestValue <= alpha && alpha < beta && beta <= VALUE_INFINITE); assert(depth >= Threads.minimumSplitDepth); assert(splitPointsSize < MAX_SPLITPOINTS_PER_THREAD); // Pick and init the next available split point SplitPoint& sp = splitPoints[splitPointsSize]; sp.spinlock.acquire(); // No contention here until we don't increment splitPointsSize sp.master = this; sp.parentSplitPoint = activeSplitPoint; sp.slavesMask = 0, sp.slavesMask.set(idx); sp.depth = depth; sp.bestValue = *bestValue; sp.bestMove = *bestMove; sp.alpha = alpha; sp.beta = beta; sp.nodeType = nodeType; sp.cutNode = cutNode; sp.movePicker = movePicker; sp.moveCount = moveCount; sp.pos = &pos; sp.nodes = 0; sp.cutoff = false; sp.ss = ss; sp.allSlavesSearching = true; // Must be set under lock protection ++splitPointsSize; activeSplitPoint = &sp; activePosition = nullptr; // Try to allocate available threads Thread* slave; while ( sp.slavesMask.count() < MAX_SLAVES_PER_SPLITPOINT && (slave = Threads.available_slave(&sp)) != nullptr) { slave->spinlock.acquire(); if (slave->can_join(activeSplitPoint)) { activeSplitPoint->slavesMask.set(slave->idx); slave->activeSplitPoint = activeSplitPoint; slave->searching = true; } slave->spinlock.release(); } // Everything is set up. The master thread enters the idle loop, from which // it will instantly launch a search, because its 'searching' flag is set. // The thread will return from the idle loop when all slaves have finished // their work at this split point. sp.spinlock.release(); Thread::idle_loop(); // Force a call to base class idle_loop() // In the helpful master concept, a master can help only a sub-tree of its // split point and because everything is finished here, it's not possible // for the master to be booked. assert(!searching); assert(!activePosition); searching = true; // We have returned from the idle loop, which means that all threads are // finished. Note that decreasing splitPointsSize must be done under lock // protection to avoid a race with Thread::can_join(). sp.spinlock.acquire(); --splitPointsSize; activeSplitPoint = sp.parentSplitPoint; activePosition = &pos; pos.set_nodes_searched(pos.nodes_searched() + sp.nodes); *bestMove = sp.bestMove; *bestValue = sp.bestValue; sp.spinlock.release(); }
void Thread::CheckCurrentForKill() { // static Thread* thread = Thread::Current(); if ( thread != NULL ) thread->CheckForKill(); }
void* Thread::_launch( void* argument ) { Thread* thread = static_cast< Thread* >( argument ); thread->execute(); return 0; }
bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& range, Thread& thread, UnwindPlan& unwind_plan) { if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid() && m_inst_emulator_ap.get()) { // The instruction emulation subclass setup the unwind plan for the // first instruction. m_inst_emulator_ap->CreateFunctionEntryUnwind (unwind_plan); // CreateFunctionEntryUnwind should have created the first row. If it // doesn't, then we are done. if (unwind_plan.GetRowCount() == 0) return false; ExecutionContext exe_ctx; thread.CalculateExecutionContext(exe_ctx); const bool prefer_file_cache = true; DisassemblerSP disasm_sp (Disassembler::DisassembleRange (m_arch, NULL, NULL, exe_ctx, range, prefer_file_cache)); Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); if (disasm_sp) { m_range_ptr = ⦥ m_thread_ptr = &thread; m_unwind_plan_ptr = &unwind_plan; const uint32_t addr_byte_size = m_arch.GetAddressByteSize(); const bool show_address = true; const bool show_bytes = true; m_inst_emulator_ap->GetRegisterInfo (unwind_plan.GetRegisterKind(), unwind_plan.GetInitialCFARegister(), m_cfa_reg_info); m_fp_is_cfa = false; m_register_values.clear(); m_pushed_regs.clear(); // Initialize the CFA with a known value. In the 32 bit case // it will be 0x80000000, and in the 64 bit case 0x8000000000000000. // We use the address byte size to be safe for any future address sizes m_initial_sp = (1ull << ((addr_byte_size * 8) - 1)); RegisterValue cfa_reg_value; cfa_reg_value.SetUInt (m_initial_sp, m_cfa_reg_info.byte_size); SetRegisterValue (m_cfa_reg_info, cfa_reg_value); const InstructionList &inst_list = disasm_sp->GetInstructionList (); const size_t num_instructions = inst_list.GetSize(); if (num_instructions > 0) { Instruction *inst = inst_list.GetInstructionAtIndex (0).get(); const addr_t base_addr = inst->GetAddress().GetFileAddress(); // Make a copy of the current instruction Row and save it in m_curr_row // so we can add updates as we process the instructions. UnwindPlan::RowSP last_row = unwind_plan.GetLastRow(); UnwindPlan::Row *newrow = new UnwindPlan::Row; if (last_row.get()) *newrow = *last_row.get(); m_curr_row.reset(newrow); // Once we've seen the initial prologue instructions complete, save a // copy of the CFI at that point into prologue_completed_row for possible // use later. int instructions_since_last_prologue_insn = 0; // # of insns since last CFI was update bool reinstate_prologue_next_instruction = false; // Next iteration, re-install the prologue row of CFI bool last_instruction_restored_return_addr_reg = false; // re-install the prologue row of CFI if the next instruction is a branch immediate bool return_address_register_has_been_saved = false; // if we've seen the ra register get saved yet UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI // cache the pc register number (in whatever register numbering this UnwindPlan uses) for // quick reference during instruction parsing. uint32_t pc_reg_num = LLDB_INVALID_REGNUM; RegisterInfo pc_reg_info; if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info)) pc_reg_num = pc_reg_info.kinds[unwind_plan.GetRegisterKind()]; else pc_reg_num = LLDB_INVALID_REGNUM; // cache the return address register number (in whatever register numbering this UnwindPlan uses) for // quick reference during instruction parsing. uint32_t ra_reg_num = LLDB_INVALID_REGNUM; RegisterInfo ra_reg_info; if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info)) ra_reg_num = ra_reg_info.kinds[unwind_plan.GetRegisterKind()]; else ra_reg_num = LLDB_INVALID_REGNUM; for (size_t idx=0; idx<num_instructions; ++idx) { m_curr_row_modified = false; m_curr_insn_restored_a_register = false; inst = inst_list.GetInstructionAtIndex (idx).get(); if (inst) { if (log && log->GetVerbose ()) { StreamString strm; inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL); log->PutCString (strm.GetData()); } m_inst_emulator_ap->SetInstruction (inst->GetOpcode(), inst->GetAddress(), exe_ctx.GetTargetPtr()); m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions); // Were there any changes to the CFI while evaluating this instruction? if (m_curr_row_modified) { reinstate_prologue_next_instruction = false; m_curr_row->SetOffset (inst->GetAddress().GetFileAddress() + inst->GetOpcode().GetByteSize() - base_addr); // Append the new row unwind_plan.AppendRow (m_curr_row); // Allocate a new Row for m_curr_row, copy the current state into it UnwindPlan::Row *newrow = new UnwindPlan::Row; *newrow = *m_curr_row.get(); m_curr_row.reset(newrow); // If m_curr_insn_restored_a_register == true, we're looking at an epilogue instruction. // Set instructions_since_last_prologue_insn to a very high number so we don't append // any of these epilogue instructions to our prologue_complete row. if (m_curr_insn_restored_a_register == false && instructions_since_last_prologue_insn < 8) instructions_since_last_prologue_insn = 0; else instructions_since_last_prologue_insn = 99; UnwindPlan::Row::RegisterLocation pc_regloc; UnwindPlan::Row::RegisterLocation ra_regloc; // While parsing the instructions of this function, if we've ever // seen the return address register (aka lr on arm) in a non-IsSame() state, // it has been saved on the stack. If it's ever back to IsSame(), we've // executed an epilogue. if (ra_reg_num != LLDB_INVALID_REGNUM && m_curr_row->GetRegisterInfo (ra_reg_num, ra_regloc) && !ra_regloc.IsSame()) { return_address_register_has_been_saved = true; } // If the caller's pc is "same", we've just executed an epilogue and we return to the caller // after this instruction completes executing. // If there are any instructions past this, there must have been flow control over this // epilogue so we'll reinstate the original prologue setup instructions. if (prologue_completed_row.get() && pc_reg_num != LLDB_INVALID_REGNUM && m_curr_row->GetRegisterInfo (pc_reg_num, pc_regloc) && pc_regloc.IsSame()) { if (log && log->GetVerbose()) log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- pc is <same>, restore prologue instructions."); reinstate_prologue_next_instruction = true; } else if (prologue_completed_row.get() && return_address_register_has_been_saved && ra_reg_num != LLDB_INVALID_REGNUM && m_curr_row->GetRegisterInfo (ra_reg_num, ra_regloc) && ra_regloc.IsSame()) { if (log && log->GetVerbose()) log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- lr is <same>, restore prologue instruction if the next instruction is a branch immediate."); last_instruction_restored_return_addr_reg = true; } } else { // If the previous instruction was a return-to-caller (epilogue), and we're still executing // instructions in this function, there must be a code path that jumps over that epilogue. // Also detect the case where we epilogue & branch imm to another function (tail-call opt) // instead of a normal pop lr-into-pc exit. // Reinstate the frame setup from the prologue. if (reinstate_prologue_next_instruction || (m_curr_insn_is_branch_immediate && last_instruction_restored_return_addr_reg)) { if (log && log->GetVerbose()) log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- Reinstating prologue instruction set"); UnwindPlan::Row *newrow = new UnwindPlan::Row; *newrow = *prologue_completed_row.get(); m_curr_row.reset(newrow); m_curr_row->SetOffset (inst->GetAddress().GetFileAddress() + inst->GetOpcode().GetByteSize() - base_addr); unwind_plan.AppendRow(m_curr_row); newrow = new UnwindPlan::Row; *newrow = *m_curr_row.get(); m_curr_row.reset(newrow); reinstate_prologue_next_instruction = false; last_instruction_restored_return_addr_reg = false; m_curr_insn_is_branch_immediate = false; } // clear both of these if either one wasn't set if (last_instruction_restored_return_addr_reg) { last_instruction_restored_return_addr_reg = false; } if (m_curr_insn_is_branch_immediate) { m_curr_insn_is_branch_immediate = false; } // Stop updating the prologue instructions if we've seen 8 non-prologue instructions // in a row. if (instructions_since_last_prologue_insn++ < 8) { UnwindPlan::Row *newrow = new UnwindPlan::Row; *newrow = *m_curr_row.get(); prologue_completed_row.reset(newrow); if (log && log->GetVerbose()) log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- saving a copy of the current row as the prologue row."); } } } } } // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions. // I'll fix that but for now, just clear the list and it will go away nicely. disasm_sp->GetInstructionList().Clear(); } if (log && log->GetVerbose ()) { StreamString strm; lldb::addr_t base_addr = range.GetBaseAddress().GetLoadAddress(thread.CalculateTarget().get()); strm.Printf ("Resulting unwind rows for [0x%" PRIx64 " - 0x%" PRIx64 "):", base_addr, base_addr + range.GetByteSize()); unwind_plan.Dump(strm, &thread, base_addr); log->PutCString (strm.GetData()); } return unwind_plan.GetRowCount() > 0; } return false; }
bool ABIMacOSX_arm::GetArgumentValues (Thread &thread, ValueList &values) const { uint32_t num_values = values.GetSize(); ExecutionContext exe_ctx (thread.shared_from_this()); // For now, assume that the types in the AST values come from the Target's // scratch AST. // Extract the register context so we can read arguments from registers RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return false; addr_t sp = 0; for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) { // We currently only support extracting values with Clang QualTypes. // Do we care about others? Value *value = values.GetValueAtIndex(value_idx); if (!value) return false; ClangASTType clang_type = value->GetClangType(); if (clang_type) { bool is_signed = false; size_t bit_width = 0; if (clang_type.IsIntegerType (is_signed)) { bit_width = clang_type.GetBitSize(); } else if (clang_type.IsPointerOrReferenceType ()) { bit_width = clang_type.GetBitSize(); } else { // We only handle integer, pointer and reference types currently... return false; } if (bit_width <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8)) { if (value_idx < 4) { // Arguments 1-4 are in r0-r3... const RegisterInfo *arg_reg_info = NULL; // Search by generic ID first, then fall back to by name uint32_t arg_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx); if (arg_reg_num != LLDB_INVALID_REGNUM) { arg_reg_info = reg_ctx->GetRegisterInfoAtIndex(arg_reg_num); } else { switch (value_idx) { case 0: arg_reg_info = reg_ctx->GetRegisterInfoByName("r0"); break; case 1: arg_reg_info = reg_ctx->GetRegisterInfoByName("r1"); break; case 2: arg_reg_info = reg_ctx->GetRegisterInfoByName("r2"); break; case 3: arg_reg_info = reg_ctx->GetRegisterInfoByName("r3"); break; } } if (arg_reg_info) { RegisterValue reg_value; if (reg_ctx->ReadRegister(arg_reg_info, reg_value)) { if (is_signed) reg_value.SignExtend(bit_width); if (!reg_value.GetScalarValue(value->GetScalar())) return false; continue; } } return false; } else { if (sp == 0) { // Read the stack pointer if it already hasn't been read sp = reg_ctx->GetSP(0); if (sp == 0) return false; } // Arguments 5 on up are on the stack const uint32_t arg_byte_size = (bit_width + (8-1)) / 8; Error error; if (!exe_ctx.GetProcessRef().ReadScalarIntegerFromMemory(sp, arg_byte_size, is_signed, value->GetScalar(), error)) return false; sp += arg_byte_size; } } } } return true; }
bool AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionContextScope *exe_scope) { if (!m_read_objc_library) return false; ExecutionContext exe_ctx; exe_scope->CalculateExecutionContext(exe_ctx); Process *process = exe_ctx.GetProcessPtr(); if (!process) return false; // We need other parts of the exe_ctx, but the processes have to match. assert (m_process == process); // Get the function address for the print function. const Address *function_address = GetPrintForDebuggerAddr(); if (!function_address) return false; Target *target = exe_ctx.GetTargetPtr(); ClangASTType clang_type = value.GetClangType(); if (clang_type) { if (!clang_type.IsObjCObjectPointerType()) { strm.Printf ("Value doesn't point to an ObjC object.\n"); return false; } } else { // If it is not a pointer, see if we can make it into a pointer. ClangASTContext *ast_context = target->GetScratchClangASTContext(); ClangASTType opaque_type = ast_context->GetBasicType(eBasicTypeObjCID); if (!opaque_type) opaque_type = ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); //value.SetContext(Value::eContextTypeClangType, opaque_type_ptr); value.SetClangType (opaque_type); } ValueList arg_value_list; arg_value_list.PushValue(value); // This is the return value: ClangASTContext *ast_context = target->GetScratchClangASTContext(); ClangASTType return_clang_type = ast_context->GetCStringType(true); Value ret; // ret.SetContext(Value::eContextTypeClangType, return_clang_type); ret.SetClangType (return_clang_type); if (exe_ctx.GetFramePtr() == NULL) { Thread *thread = exe_ctx.GetThreadPtr(); if (thread == NULL) { exe_ctx.SetThreadSP(process->GetThreadList().GetSelectedThread()); thread = exe_ctx.GetThreadPtr(); } if (thread) { exe_ctx.SetFrameSP(thread->GetSelectedFrame()); } } // Now we're ready to call the function: ClangFunction func (*exe_ctx.GetBestExecutionContextScope(), return_clang_type, *function_address, arg_value_list, "objc-object-description"); StreamString error_stream; lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS; func.InsertFunction(exe_ctx, wrapper_struct_addr, error_stream); EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetTryAllThreads(true); options.SetStopOthers(true); options.SetIgnoreBreakpoints(true); options.SetTimeoutUsec(PO_FUNCTION_TIMEOUT_USEC); ExpressionResults results = func.ExecuteFunction (exe_ctx, &wrapper_struct_addr, options, error_stream, ret); if (results != eExpressionCompleted) { strm.Printf("Error evaluating Print Object function: %d.\n", results); return false; } addr_t result_ptr = ret.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); char buf[512]; size_t cstr_len = 0; size_t full_buffer_len = sizeof (buf) - 1; size_t curr_len = full_buffer_len; while (curr_len == full_buffer_len) { Error error; curr_len = process->ReadCStringFromMemory(result_ptr + cstr_len, buf, sizeof(buf), error); strm.Write (buf, curr_len); cstr_len += curr_len; } return cstr_len > 0; }
Error ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) { Error error; if (!new_value_sp) { error.SetErrorString("Empty value object for return value."); return error; } ClangASTType clang_type = new_value_sp->GetClangType(); if (!clang_type) { error.SetErrorString ("Null clang type for return value."); return error; } Thread *thread = frame_sp->GetThread().get(); bool is_signed; uint32_t count; bool is_complex; RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) { DataExtractor data; Error data_error; size_t num_bytes = new_value_sp->GetData(data, data_error); if (data_error.Fail()) { error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString()); return error; } lldb::offset_t offset = 0; if (num_bytes <= 8) { const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("r0", 0); if (num_bytes <= 4) { uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value)) set_it_simple = true; } else { uint32_t raw_value = data.GetMaxU32(&offset, 4); if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value)) { const RegisterInfo *r1_info = reg_ctx->GetRegisterInfoByName("r1", 0); uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset); if (reg_ctx->WriteRegisterFromUnsigned (r1_info, raw_value)) set_it_simple = true; } } } else { error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); } } else if (clang_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); else error.SetErrorString ("We don't support returning float values at present"); } if (!set_it_simple) error.SetErrorString ("We only support setting simple integer return types at present."); return error; }
void Thread::split(Position& pos, const Stack* ss, Value alpha, Value beta, Value* bestValue, Move* bestMove, Depth depth, int moveCount, MovePicker* movePicker, int nodeType, bool cutNode) { assert(pos.pos_is_ok()); assert(-VALUE_INFINITE < *bestValue && *bestValue <= alpha && alpha < beta && beta <= VALUE_INFINITE); assert(depth >= Threads.minimumSplitDepth); assert(searching); assert(splitPointsSize < MAX_SPLITPOINTS_PER_THREAD); // Pick the next available split point from the split point stack SplitPoint& sp = splitPoints[splitPointsSize]; sp.masterThread = this; sp.parentSplitPoint = activeSplitPoint; sp.slavesMask = 0, sp.slavesMask.set(idx); sp.depth = depth; sp.bestValue = *bestValue; sp.bestMove = *bestMove; sp.alpha = alpha; sp.beta = beta; sp.nodeType = nodeType; sp.cutNode = cutNode; sp.movePicker = movePicker; sp.moveCount = moveCount; sp.pos = &pos; sp.nodes = 0; sp.cutoff = false; sp.ss = ss; // Try to allocate available threads and ask them to start searching setting // 'searching' flag. This must be done under lock protection to avoid concurrent // allocation of the same slave by another master. Threads.mutex.lock(); sp.mutex.lock(); sp.allSlavesSearching = true; // Must be set under lock protection ++splitPointsSize; activeSplitPoint = &sp; activePosition = NULL; if (!Fake) for (Thread* slave; (slave = Threads.available_slave(this)) != NULL; ) { sp.slavesMask.set(slave->idx); slave->activeSplitPoint = &sp; slave->searching = true; // Slave leaves idle_loop() slave->notify_one(); // Could be sleeping } // Everything is set up. The master thread enters the idle loop, from which // it will instantly launch a search, because its 'searching' flag is set. // The thread will return from the idle loop when all slaves have finished // their work at this split point. sp.mutex.unlock(); Threads.mutex.unlock(); Thread::idle_loop(); // Force a call to base class idle_loop() // In the helpful master concept, a master can help only a sub-tree of its // split point and because everything is finished here, it's not possible // for the master to be booked. assert(!searching); assert(!activePosition); // We have returned from the idle loop, which means that all threads are // finished. Note that setting 'searching' and decreasing splitPointsSize is // done under lock protection to avoid a race with Thread::available_to(). Threads.mutex.lock(); sp.mutex.lock(); searching = true; --splitPointsSize; activeSplitPoint = sp.parentSplitPoint; activePosition = &pos; pos.set_nodes_searched(pos.nodes_searched() + sp.nodes); *bestMove = sp.bestMove; *bestValue = sp.bestValue; sp.mutex.unlock(); Threads.mutex.unlock(); }