/* ---------------------------------------------------------------- */ void Dbtup::execSTORED_PROCREQ(Signal* signal) { OperationrecPtr regOperPtr; TablerecPtr regTabPtr; jamEntry(); regOperPtr.i = signal->theData[0]; c_operation_pool.getPtr(regOperPtr); regTabPtr.i = signal->theData[1]; ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec); Uint32 requestInfo = signal->theData[3]; TransState trans_state= get_trans_state(regOperPtr.p); ndbrequire(trans_state == TRANS_IDLE || ((trans_state == TRANS_ERROR_WAIT_STORED_PROCREQ) && (requestInfo == ZSTORED_PROCEDURE_DELETE))); ndbrequire(regTabPtr.p->tableStatus == DEFINED); switch (requestInfo) { case ZSCAN_PROCEDURE: jam(); scanProcedure(signal, regOperPtr.p, signal->theData[4]); break; case ZCOPY_PROCEDURE: jam(); copyProcedure(signal, regTabPtr, regOperPtr.p); break; case ZSTORED_PROCEDURE_DELETE: jam(); deleteScanProcedure(signal, regOperPtr.p); break; default: ndbrequire(false); }//switch }//Dbtup::execSTORED_PROCREQ()
void Dbtup::copyProcedure(Signal* signal, TablerecPtr regTabPtr, Operationrec* regOperPtr) { Uint32 TnoOfAttributes = regTabPtr.p->m_no_of_attributes; scanProcedure(signal, regOperPtr, TnoOfAttributes); Uint32 length = 0; for (Uint32 Ti = 0; Ti < TnoOfAttributes; Ti++) { AttributeHeader::init(&signal->theData[length + 1], Ti, 0); length++; if (length == 24) { jam(); ndbrequire(storedProcedureAttrInfo(signal, regOperPtr, signal->theData+1, length, true)); length = 0; }//if }//for if (length != 0) { jam(); ndbrequire(storedProcedureAttrInfo(signal, regOperPtr, signal->theData+1, length, true)); }//if ndbrequire(regOperPtr->currentAttrinbufLen == 0); }//Dbtup::copyProcedure()
void Dbtup::copyProcedure(Signal* signal, TablerecPtr regTabPtr, Operationrec* regOperPtr) { /* We create a stored procedure for the fragment copy scan * This is done by trimming a 'read all columns in order' * program to the correct length for this table and * using that to create the procedure * This assumes that there is only one fragment copy going * on at any time, which is verified by checking * cCopyLastSeg == RNIL before starting each copy * * If the table has extra per-row metainformation that * needs copied then we add that to the copy procedure * as well. */ prepareCopyProcedure(regTabPtr.p->m_no_of_attributes, regTabPtr.p->m_bits); SectionHandle handle(this); handle.m_cnt=1; handle.m_ptr[0].i= cCopyProcedure; getSections(handle.m_cnt, handle.m_ptr); scanProcedure(signal, regOperPtr, &handle, true); // isCopy }//Dbtup::copyProcedure()
/* ---------------------------------------------------------------- */ void Dbtup::execSTORED_PROCREQ(Signal* signal) { OperationrecPtr regOperPtr; TablerecPtr regTabPtr; jamEntry(); regOperPtr.i = signal->theData[0]; c_operation_pool.getPtr(regOperPtr); regTabPtr.i = signal->theData[1]; ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec); Uint32 requestInfo = signal->theData[3]; TransState trans_state= get_trans_state(regOperPtr.p); ndbrequire(trans_state == TRANS_IDLE || ((trans_state == TRANS_ERROR_WAIT_STORED_PROCREQ) && (requestInfo == ZSTORED_PROCEDURE_DELETE))); ndbrequire(regTabPtr.p->tableStatus == DEFINED); /* * Also store count of procs called from non-API scans. * It can be done here since seize/release always succeeds. * The count is only used under -DERROR_INSERT via DUMP. */ BlockReference apiBlockref = signal->theData[5]; switch (requestInfo) { case ZSCAN_PROCEDURE: { jam(); #if defined VM_TRACE || defined ERROR_INSERT storedProcCountNonAPI(apiBlockref, +1); #endif SectionHandle handle(this, signal); ndbrequire(handle.m_cnt == 1); scanProcedure(signal, regOperPtr.p, &handle, false); // Not copy break; } case ZCOPY_PROCEDURE: jam(); #if defined VM_TRACE || defined ERROR_INSERT storedProcCountNonAPI(apiBlockref, +1); #endif copyProcedure(signal, regTabPtr, regOperPtr.p); break; case ZSTORED_PROCEDURE_DELETE: jam(); #if defined VM_TRACE || defined ERROR_INSERT storedProcCountNonAPI(apiBlockref, -1); #endif deleteScanProcedure(signal, regOperPtr.p); break; default: ndbrequire(false); }//switch }//Dbtup::execSTORED_PROCREQ()
/** * Recursively generate code regions by statically analyzing machine code. */ bool MDBCode::scanProcedure(uintptr_t address) { if (getRegion(address)) { log.traceLn("a region already exists"); // A region already exists for this address. return true; } log.traceLn("scanning address %llx", address); size_t bufferSize = 1024 * 8; char buffer[bufferSize]; if (debugger->read(buffer, address, sizeof(buffer)) != (int) sizeof(buffer)) { log.traceLn("Cannot read procedure memory."); } MBList<uintptr_t> callTargets; ud_t insn; ud_init(&insn); ud_set_input_buffer(&insn, (uint8_t*)buffer, bufferSize); ud_set_mode(&insn, 32); ud_set_syntax(&insn, UD_SYN_INTEL); size_t remainingBytes = bufferSize; while (remainingBytes > 0) { int offset = insn.pc; size_t insnSize = ud_disassemble(&insn); remainingBytes -= insnSize; if (insnSize == 0) { error("cannot disassemble"); break; } log.traceLn("decoded: 0x%-8llx 0x%-8llx %s", address + offset, offset, ud_insn_asm(&insn)); switch (insn.mnemonic) { case UD_Icall: { uintptr_t target = 0; if (insn.operand[0].type == UD_OP_JIMM) { if (insn.operand[0].size == 32) { target = address + insn.pc + insn.operand[0].lval.sdword; } } if (target) { if (callTargets.contains(target) == false) { log.traceLn("discovered new call target 0x%llx", target); callTargets.append(target); } } break; } case UD_Iret: { MDBCodeRegion *region = new MDBCodeRegion(this, address, findSymbolByNameOrAddress(NULL, address), insn.pc); regions.append(region); remainingBytes = 0; break; } default: break; } } for (uint32_t i = 0; i < callTargets.length(); i++) { scanProcedure(callTargets[i]); } return true; }