Newer
Older
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
lldb_private::Scalar result;
switch (inst->getOpcode())
{
default:
break;
case Instruction::Add:
result = L + R;
break;
case Instruction::Mul:
result = L * R;
break;
case Instruction::Sub:
result = L - R;
break;
case Instruction::SDiv:
result = L / R;
break;
case Instruction::UDiv:
result = L.GetRawBits64(0) / R.GetRawBits64(1);
break;
case Instruction::SRem:
result = L % R;
break;
case Instruction::URem:
result = L.GetRawBits64(0) % R.GetRawBits64(1);
break;
case Instruction::Shl:
result = L << R;
break;
case Instruction::AShr:
result = L >> R;
break;
case Instruction::LShr:
result = L;
result.ShiftRightLogical(R);
break;
case Instruction::And:
result = L & R;
break;
case Instruction::Or:
result = L | R;
break;
case Instruction::Xor:
result = L ^ R;
break;
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
}
frame.AssignValue(inst, result, llvm_module);
if (log)
{
log->Printf("Interpreted a %s", inst->getOpcodeName());
log->Printf(" L : %s", frame.SummarizeValue(lhs).c_str());
log->Printf(" R : %s", frame.SummarizeValue(rhs).c_str());
log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
}
}
break;
case Instruction::Alloca:
{
const AllocaInst *alloca_inst = dyn_cast<AllocaInst>(inst);
if (!alloca_inst)
{
if (log)
log->Printf("getOpcode() returns Alloca, but instruction is not an AllocaInst");
err.SetErrorToGenericError();
err.SetErrorString(interpreter_internal_error);
return false;
}
if (alloca_inst->isArrayAllocation())
{
if (log)
log->Printf("AllocaInsts are not handled if isArrayAllocation() is true");
err.SetErrorToGenericError();
err.SetErrorString(unsupported_opcode_error);
return false;
}
// The semantics of Alloca are:
// Create a region R of virtual memory of type T, backed by a data buffer
// Create a region P of virtual memory of type T*, backed by a data buffer
// Write the virtual address of R into P
Type *T = alloca_inst->getAllocatedType();
Type *Tptr = alloca_inst->getType();
lldb::addr_t R = frame.Malloc(T);
if (R == LLDB_INVALID_ADDRESS)
{
if (log)
log->Printf("Couldn't allocate memory for an AllocaInst");
err.SetErrorToGenericError();
err.SetErrorString(memory_allocation_error);
return false;
}
lldb::addr_t P = frame.Malloc(Tptr);
if (P == LLDB_INVALID_ADDRESS)
{
if (log)
log->Printf("Couldn't allocate the result pointer for an AllocaInst");
err.SetErrorToGenericError();
err.SetErrorString(memory_allocation_error);
return false;
}
lldb_private::Error write_error;
memory_map.WritePointerToMemory(P, R, write_error);
log->Printf("Couldn't write the result pointer for an AllocaInst");
err.SetErrorToGenericError();
err.SetErrorString(memory_write_error);
lldb_private::Error free_error;
memory_map.Free(P, free_error);
memory_map.Free(R, free_error);
return false;
}
frame.m_values[alloca_inst] = P;
if (log)
{
log->Printf("Interpreted an AllocaInst");
log->Printf(" R : 0x%llx", R);
log->Printf(" P : 0x%llx", P);
}
}
break;
case Instruction::BitCast:
const CastInst *cast_inst = dyn_cast<CastInst>(inst);
log->Printf("getOpcode() returns %s, but instruction is not a BitCastInst", cast_inst->getOpcodeName());
err.SetErrorToGenericError();
err.SetErrorString(interpreter_internal_error);
return false;
}
Value *source = cast_inst->getOperand(0);
lldb_private::Scalar S;
if (!frame.EvaluateValue(S, source, llvm_module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(source).c_str());
err.SetErrorToGenericError();
err.SetErrorString(bad_value_error);
return false;
}
frame.AssignValue(inst, S, llvm_module);
}
break;
case Instruction::Br:
{
const BranchInst *br_inst = dyn_cast<BranchInst>(inst);
if (!br_inst)
{
if (log)
log->Printf("getOpcode() returns Br, but instruction is not a BranchInst");
err.SetErrorToGenericError();
err.SetErrorString(interpreter_internal_error);
return false;
}
if (br_inst->isConditional())
{
Value *condition = br_inst->getCondition();
lldb_private::Scalar C;
if (!frame.EvaluateValue(C, condition, llvm_module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(condition).c_str());
err.SetErrorToGenericError();
err.SetErrorString(bad_value_error);
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
return false;
}
if (C.GetRawBits64(0))
frame.Jump(br_inst->getSuccessor(0));
else
frame.Jump(br_inst->getSuccessor(1));
if (log)
{
log->Printf("Interpreted a BrInst with a condition");
log->Printf(" cond : %s", frame.SummarizeValue(condition).c_str());
}
}
else
{
frame.Jump(br_inst->getSuccessor(0));
if (log)
{
log->Printf("Interpreted a BrInst with no condition");
}
}
}
continue;
case Instruction::GetElementPtr:
{
const GetElementPtrInst *gep_inst = dyn_cast<GetElementPtrInst>(inst);
if (!gep_inst)
{
if (log)
log->Printf("getOpcode() returns GetElementPtr, but instruction is not a GetElementPtrInst");
err.SetErrorToGenericError();
err.SetErrorString(interpreter_internal_error);
return false;
}
const Value *pointer_operand = gep_inst->getPointerOperand();
Type *pointer_type = pointer_operand->getType();
lldb_private::Scalar P;
if (!frame.EvaluateValue(P, pointer_operand, llvm_module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(pointer_operand).c_str());
err.SetErrorToGenericError();
err.SetErrorString(bad_value_error);
typedef SmallVector <Value *, 8> IndexVector;
typedef IndexVector::iterator IndexIterator;
SmallVector <Value *, 8> indices (gep_inst->idx_begin(),
gep_inst->idx_end());
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
SmallVector <Value *, 8> const_indices;
for (IndexIterator ii = indices.begin(), ie = indices.end();
ii != ie;
++ii)
{
ConstantInt *constant_index = dyn_cast<ConstantInt>(*ii);
if (!constant_index)
{
lldb_private::Scalar I;
if (!frame.EvaluateValue(I, *ii, llvm_module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(*ii).c_str());
err.SetErrorToGenericError();
err.SetErrorString(bad_value_error);
return false;
}
if (log)
log->Printf("Evaluated constant index %s as %llu", PrintValue(*ii).c_str(), I.ULongLong(LLDB_INVALID_ADDRESS));
constant_index = cast<ConstantInt>(ConstantInt::get((*ii)->getType(), I.ULongLong(LLDB_INVALID_ADDRESS)));
}
const_indices.push_back(constant_index);
}
uint64_t offset = target_data.getIndexedOffset(pointer_type, const_indices);
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
lldb_private::Scalar Poffset = P + offset;
frame.AssignValue(inst, Poffset, llvm_module);
if (log)
{
log->Printf("Interpreted a GetElementPtrInst");
log->Printf(" P : %s", frame.SummarizeValue(pointer_operand).c_str());
log->Printf(" Poffset : %s", frame.SummarizeValue(inst).c_str());
}
}
break;
case Instruction::ICmp:
{
const ICmpInst *icmp_inst = dyn_cast<ICmpInst>(inst);
if (!icmp_inst)
{
if (log)
log->Printf("getOpcode() returns ICmp, but instruction is not an ICmpInst");
err.SetErrorToGenericError();
err.SetErrorString(interpreter_internal_error);
return false;
}
CmpInst::Predicate predicate = icmp_inst->getPredicate();
Value *lhs = inst->getOperand(0);
Value *rhs = inst->getOperand(1);
lldb_private::Scalar L;
lldb_private::Scalar R;
if (!frame.EvaluateValue(L, lhs, llvm_module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str());
err.SetErrorToGenericError();
err.SetErrorString(bad_value_error);
return false;
}
if (!frame.EvaluateValue(R, rhs, llvm_module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str());
err.SetErrorToGenericError();
err.SetErrorString(bad_value_error);
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
return false;
}
lldb_private::Scalar result;
switch (predicate)
{
default:
return false;
case CmpInst::ICMP_EQ:
result = (L == R);
break;
case CmpInst::ICMP_NE:
result = (L != R);
break;
case CmpInst::ICMP_UGT:
result = (L.GetRawBits64(0) > R.GetRawBits64(0));
break;
case CmpInst::ICMP_UGE:
result = (L.GetRawBits64(0) >= R.GetRawBits64(0));
break;
case CmpInst::ICMP_ULT:
result = (L.GetRawBits64(0) < R.GetRawBits64(0));
break;
case CmpInst::ICMP_ULE:
result = (L.GetRawBits64(0) <= R.GetRawBits64(0));
break;
case CmpInst::ICMP_SGT:
result = (L > R);
break;
case CmpInst::ICMP_SGE:
result = (L >= R);
break;
case CmpInst::ICMP_SLT:
result = (L < R);
break;
case CmpInst::ICMP_SLE:
result = (L <= R);
break;
}
frame.AssignValue(inst, result, llvm_module);
if (log)
{
log->Printf("Interpreted an ICmpInst");
log->Printf(" L : %s", frame.SummarizeValue(lhs).c_str());
log->Printf(" R : %s", frame.SummarizeValue(rhs).c_str());
log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
}
}
break;
case Instruction::IntToPtr:
{
const IntToPtrInst *int_to_ptr_inst = dyn_cast<IntToPtrInst>(inst);
if (!int_to_ptr_inst)
{
if (log)
log->Printf("getOpcode() returns IntToPtr, but instruction is not an IntToPtrInst");
err.SetErrorToGenericError();
err.SetErrorString(interpreter_internal_error);
return false;
}
Value *src_operand = int_to_ptr_inst->getOperand(0);
lldb_private::Scalar I;
if (!frame.EvaluateValue(I, src_operand, llvm_module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str());
err.SetErrorToGenericError();
err.SetErrorString(bad_value_error);
frame.AssignValue(inst, I, llvm_module);
if (log)
{
log->Printf("Interpreted an IntToPtr");
log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str());
log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
}
}
break;
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
case Instruction::PtrToInt:
{
const PtrToIntInst *ptr_to_int_inst = dyn_cast<PtrToIntInst>(inst);
if (!ptr_to_int_inst)
{
if (log)
log->Printf("getOpcode() returns PtrToInt, but instruction is not an PtrToIntInst");
err.SetErrorToGenericError();
err.SetErrorString(interpreter_internal_error);
return false;
}
Value *src_operand = ptr_to_int_inst->getOperand(0);
lldb_private::Scalar I;
if (!frame.EvaluateValue(I, src_operand, llvm_module))
{
if (log)
log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str());
err.SetErrorToGenericError();
err.SetErrorString(bad_value_error);
return false;
}
frame.AssignValue(inst, I, llvm_module);
if (log)
{
log->Printf("Interpreted a PtrToInt");
log->Printf(" Src : %s", frame.SummarizeValue(src_operand).c_str());
log->Printf(" = : %s", frame.SummarizeValue(inst).c_str());
}
}
break;
case Instruction::Load:
{
const LoadInst *load_inst = dyn_cast<LoadInst>(inst);
if (!load_inst)
{
if (log)
log->Printf("getOpcode() returns Load, but instruction is not a LoadInst");
err.SetErrorToGenericError();
err.SetErrorString(interpreter_internal_error);
return false;
}
// The semantics of Load are:
// Create a region D that will contain the loaded data
// Resolve the region P containing a pointer
// Dereference P to get the region R that the data should be loaded from
// Transfer a unit of type type(D) from R to D
const Value *pointer_operand = load_inst->getPointerOperand();
Type *pointer_ty = pointer_operand->getType();
PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty);
if (!pointer_ptr_ty)
{
if (log)
log->Printf("getPointerOperand()->getType() is not a PointerType");
err.SetErrorToGenericError();
err.SetErrorString(interpreter_internal_error);
Type *target_ty = pointer_ptr_ty->getElementType();
lldb::addr_t D = frame.ResolveValue(load_inst, llvm_module);
lldb::addr_t P = frame.ResolveValue(pointer_operand, llvm_module);
if (D == LLDB_INVALID_ADDRESS)
{
if (log)
log->Printf("LoadInst's value doesn't resolve to anything");
err.SetErrorToGenericError();
err.SetErrorString(bad_value_error);
return false;
}
if (P == LLDB_INVALID_ADDRESS)
{
if (log)
log->Printf("LoadInst's pointer doesn't resolve to anything");
err.SetErrorToGenericError();
err.SetErrorString(bad_value_error);
return false;
}
lldb::addr_t R;
lldb_private::Error read_error;
memory_map.ReadPointerFromMemory(&R, P, read_error);
if (!read_error.Success())
{
if (log)
log->Printf("Couldn't read the address to be loaded for a LoadInst");
err.SetErrorToGenericError();
err.SetErrorString(memory_read_error);
return false;
}
size_t target_size = target_data.getTypeStoreSize(target_ty);
lldb_private::DataBufferHeap buffer(target_size, 0);
memory_map.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(), read_error);
if (log)
log->Printf("Couldn't read from a region on behalf of a LoadInst");
err.SetErrorToGenericError();
err.SetErrorString(memory_read_error);
return false;
lldb_private::Error write_error;
memory_map.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(), write_error);
if (log)
log->Printf("Couldn't write to a region on behalf of a LoadInst");
err.SetErrorToGenericError();
err.SetErrorString(memory_read_error);
return false;
if (log)
{
log->Printf("Interpreted a LoadInst");
log->Printf(" P : 0x%llx", P);
log->Printf(" R : 0x%llx", R);
log->Printf(" D : 0x%llx", D);
}
}
break;
case Instruction::Ret:
{
frame.RestoreLLDBValues();
if (result_name.IsEmpty())
return true;
GlobalValue *result_value = llvm_module.getNamedValue(result_name.GetCString());
if (!frame.ConstructResult(result, result_value, result_name, result_type, llvm_module))
{
if (log)
log->Printf("Couldn't construct the expression's result");
err.SetErrorToGenericError();
err.SetErrorString(bad_result_error);
return false;
}
return true;
}
case Instruction::Store:
{
const StoreInst *store_inst = dyn_cast<StoreInst>(inst);
if (!store_inst)
{
if (log)
log->Printf("getOpcode() returns Store, but instruction is not a StoreInst");
err.SetErrorToGenericError();
err.SetErrorString(interpreter_internal_error);
return false;
}
// The semantics of Store are:
// Resolve the region D containing the data to be stored
// Resolve the region P containing a pointer
// Dereference P to get the region R that the data should be stored in
// Transfer a unit of type type(D) from D to R
const Value *value_operand = store_inst->getValueOperand();
const Value *pointer_operand = store_inst->getPointerOperand();
Type *pointer_ty = pointer_operand->getType();
PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty);
if (!pointer_ptr_ty)
return false;
Type *target_ty = pointer_ptr_ty->getElementType();
lldb::addr_t D = frame.ResolveValue(value_operand, llvm_module);
lldb::addr_t P = frame.ResolveValue(pointer_operand, llvm_module);
if (D == LLDB_INVALID_ADDRESS)
{
if (log)
log->Printf("StoreInst's value doesn't resolve to anything");
err.SetErrorToGenericError();
err.SetErrorString(bad_value_error);
return false;
}
if (P == LLDB_INVALID_ADDRESS)
{
if (log)
log->Printf("StoreInst's pointer doesn't resolve to anything");
err.SetErrorToGenericError();
err.SetErrorString(bad_value_error);
return false;
}
lldb::addr_t R;
lldb_private::Error read_error;
memory_map.ReadPointerFromMemory(&R, P, read_error);
if (!read_error.Success())
{
if (log)
log->Printf("Couldn't read the address to be loaded for a LoadInst");
err.SetErrorToGenericError();
err.SetErrorString(memory_read_error);
return false;
}
size_t target_size = target_data.getTypeStoreSize(target_ty);
lldb_private::DataBufferHeap buffer(target_size, 0);
memory_map.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(), read_error);
if (log)
log->Printf("Couldn't read from a region on behalf of a StoreInst");
err.SetErrorToGenericError();
err.SetErrorString(memory_read_error);
return false;
lldb_private::Error write_error;
memory_map.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(), write_error);
if (log)
log->Printf("Couldn't write to a region on behalf of a StoreInst");
err.SetErrorToGenericError();
err.SetErrorString(memory_read_error);
return false;
}
if (log)
{
log->Printf("Interpreted a StoreInst");
log->Printf(" D : 0x%llx", D);
log->Printf(" P : 0x%llx", P);
log->Printf(" R : 0x%llx", R);
}
}
break;
}
++frame.m_ii;
}
if (num_insts >= 4096)
{
err.SetErrorToGenericError();
err.SetErrorString(infinite_loop_error);