bool Architecture::FormatOperand( Document const& rDoc, Address const& rAddr, Instruction const& rInsn, Operand const& rOprd, u8 OperandNo, PrintData & rPrintData) const { rPrintData.MarkOffset(); auto const& rBinStrm = rDoc.GetBinaryStream(); if (rOprd.GetType() == O_NONE) return true; u32 OprdType = rOprd.GetType(); auto const* pCpuInfo = GetCpuInformation(); std::string MemBegChar = "["; std::string MemEndChar = "]"; if (OprdType & O_MEM) rPrintData.AppendOperator("["); if (OprdType & O_REL || OprdType & O_ABS) { Address DstAddr; if (rInsn.GetOperandReference(rDoc, 0, rAddr, DstAddr)) { auto Lbl = rDoc.GetLabelFromAddress(DstAddr); if (Lbl.GetType() != Label::Unknown) rPrintData.AppendLabel(Lbl.GetLabel()); else rPrintData.AppendAddress(rAddr); } else rPrintData.AppendImmediate(rOprd.GetValue(), rAddr.GetOffsetSize()); } else if (OprdType & O_DISP || OprdType & O_IMM) { if (rOprd.GetType() & O_NO_REF) { rPrintData.AppendImmediate(rOprd.GetValue(), rAddr.GetOffsetSize()); return true; } Address OprdAddr = rDoc.MakeAddress(rOprd.GetSegValue(), rOprd.GetValue()); auto Lbl = rDoc.GetLabelFromAddress(OprdAddr); if (Lbl.GetType() != Label::Unknown) rPrintData.AppendLabel(Lbl.GetLabel()); else rPrintData.AppendAddress(OprdAddr); } else if (OprdType & O_REG) { if (pCpuInfo == nullptr) return false; auto pRegName = pCpuInfo->ConvertIdentifierToName(rOprd.GetReg()); if (pRegName == nullptr) return false; rPrintData.AppendRegister(pRegName); } if (OprdType & O_MEM) rPrintData.AppendOperator("]"); return true; }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Operand* ConstantFolder::LoadFromInitializer(Initializer* initializer, const Type* loadType, __int64 offset) { DebugValidator::IsFalse(initializer->IsInitializerList()); bool isNull = false; bool isZero = false; // We may be loading from string constant. if(auto stringConst = initializer->Value()->As<StringConstant>()) { return LoadFromString(stringConst, loadType, offset); } // Exclude initializers that have an incompatible conversion. if(initializer->Conversion() == InitConv_PointerToInt) { if(initializer->Value()->IsNullConstant()) { isZero = true; } else { // Definitely not a constant operand. return nullptr; } } else if((initializer->Conversion() == InitConv_PointerToPointer) || (initializer->Conversion() == InitConv_IntToPointer)) { if(initializer->Value()->IsNullConstant() || MatchInt(0)(initializer->Value())) { isNull = true; } else { // Definitely not a constant operand. return nullptr; } } // It's undefined behavior if we try to load from a null pointer. if(isNull) { return GetNullptr(loadType); } else if(isZero) { return GetZeroInt(loadType); } // Obtain the value from the initializer. If the offset is not 0, or the // types don't match, we must extract the value. // Not that we give up if we are requested to extract a value that is larger // than the one in the initializer, or if the offset is too large. Operand* value = initializer->Value(); auto valueType = value->GetType(); if((offset == 0) && (loadType == initializer->Value()->GetType())) { return initializer->Value(); } else if((offset > TypeInfo::GetSize(valueType, target_)) || (TypeInfo::GetSize(loadType, target_) > TypeInfo::GetSize(valueType, target_))) { // This is undefined behavior, because we want to read something that is // in memory located after the operand, and there are no constraints // on the way global variables are laid out int memory. return GetUndefined(loadType); } return ExtractFromOperand(value, loadType, offset); }