Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ add_library(
zetaengine-c.cpp
)
if(ZEN_ENABLE_EVM)
target_link_libraries(dtvmcore PRIVATE evmc::instructions)
target_link_libraries(dtvmcore PUBLIC evmc::instructions)
endif()
if(NOT ZEN_ENABLE_SGX)
target_link_libraries(dtvmcore PRIVATE Threads::Threads)
Expand Down
6 changes: 6 additions & 0 deletions src/action/evm_bytecode_visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ template <typename IRBuilder> class EVMByteCodeVisitor {
}
bool IsJumpDest = (Opcode == OP_JUMPDEST);
if (!IsJumpDest) {
if (!Builder.isOpcodeDefined(Opcode)) {
handleEndBlock();
Builder.handleUndefined();
PC++;
continue;
}
Builder.meterOpcode(Opcode, PC);
}

Expand Down
2 changes: 1 addition & 1 deletion src/cli/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ add_executable(dtvm dtvm.cpp)
target_link_libraries(dtvm PRIVATE dtvmcore CLI11::CLI11)

if(ZEN_ENABLE_EVM)
target_link_libraries(dtvm PUBLIC evmc::evmc)
target_link_libraries(dtvm PUBLIC evmc::evmc evmc::instructions)
endif()

if(ZEN_ENABLE_PROFILER)
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ set_property(

add_library(compiler STATIC ${COMPILER_SRCS} $<TARGET_OBJECTS:utils>)
target_link_libraries(compiler PRIVATE ${llvm_libs})
if(ZEN_ENABLE_EVM)
target_link_libraries(compiler PUBLIC evmc::instructions)
endif()

add_executable(ircompiler ircompiler.cpp)
target_link_libraries(ircompiler PRIVATE compiler dtvmcore CLI11::CLI11)
4 changes: 4 additions & 0 deletions src/compiler/cgir/lowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,10 @@ template <typename T> class CgLowering {
case OP_popcnt:
ISDOpcode = ISD::CTPOP;
break;
case OP_bswap:
ZEN_ASSERT(IsInteger);
ISDOpcode = ISD::BSWAP;
break;
case OP_fpabs:
ZEN_ASSERT(!IsInteger);
return SELF.lowerFPAbsExpr(OperandVT, OperandReg);
Expand Down
1 change: 1 addition & 0 deletions src/compiler/evm_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ void EagerEVMJITCompiler::compile() {
#ifdef ZEN_ENABLE_EVM_GAS_REGISTER
Ctx.setGasRegisterEnabled(true);
#endif
Ctx.setRevision(EVMMod->getRevision());
Ctx.setBytecode(reinterpret_cast<const Byte *>(EVMMod->Code),
EVMMod->CodeSize);
const auto &Cache = EVMMod->getBytecodeCache();
Expand Down
151 changes: 54 additions & 97 deletions src/compiler/evm_frontend/evm_imported.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,15 @@ const RuntimeFunctions &getRuntimeFunctionTable() {
.GetBaseFee = &evmGetBaseFee,
.GetBlobHash = &evmGetBlobHash,
.GetBlobBaseFee = &evmGetBlobBaseFee,
.GetMSize = &evmGetMSize,
.GetMLoad = &evmGetMLoad,
.SetMStore = &evmSetMStore,
.SetMStore8 = &evmSetMStore8,
.GetSLoad = &evmGetSLoad,
.SetSStore = &evmSetSStore,
.GetGas = &evmGetGas,
.GetTLoad = &evmGetTLoad,
.SetTStore = &evmSetTStore,
.SetMCopy = &evmSetMCopy,
.SetCallDataCopy = &evmSetCallDataCopy,
.SetExtCodeCopy = &evmSetExtCodeCopy,
.SetReturnDataCopy = &evmSetReturnDataCopy,
.ExpandMemoryNoGas = &evmExpandMemoryNoGas,
.GetReturnDataSize = &evmGetReturnDataSize,
.EmitLog0 = &evmEmitLog0,
.EmitLog1 = &evmEmitLog1,
Expand Down Expand Up @@ -520,70 +516,16 @@ const intx::uint256 *evmGetBlobBaseFee(zen::runtime::EVMInstance *Instance) {
intx::be::load<intx::uint256>(TxContext.blob_base_fee));
}

uint64_t evmGetMSize(zen::runtime::EVMInstance *Instance) {
return Instance->getMemorySize();
}
const intx::uint256 *evmGetMLoad(zen::runtime::EVMInstance *Instance,
uint64_t Offset) {
if (!Instance->expandMemoryChecked(Offset, 32)) {
return storeUint256Result(intx::uint256{0});
}
auto &Memory = Instance->getMemory();

uint8_t ValueBytes[32];
std::memcpy(ValueBytes, Memory.data() + Offset, 32);

intx::uint256 Result = intx::be::load<intx::uint256>(ValueBytes);
return storeUint256Result(Result);
}
void evmSetMStore(zen::runtime::EVMInstance *Instance, uint64_t Offset,
const intx::uint256 &Value) {
if (!Instance->expandMemoryChecked(Offset, 32)) {
return;
}

auto &Memory = Instance->getMemory();
uint8_t ValueBytes[32];
intx::be::store(ValueBytes, Value);
std::memcpy(Memory.data() + Offset, ValueBytes, sizeof(ValueBytes));
}

void evmSetMStore8(zen::runtime::EVMInstance *Instance, uint64_t Offset,
const intx::uint256 &Value) {
if (!Instance->expandMemoryChecked(Offset, 1)) {
return;
}

auto &Memory = Instance->getMemory();
uint8_t ByteValue = static_cast<uint8_t>(Value & intx::uint256{0xFF});
Memory[Offset] = ByteValue;
}

void evmSetMCopy(zen::runtime::EVMInstance *Instance, uint64_t Dest,
uint64_t Src, uint64_t Len) {
if (Len == 0) {
return;
}
if (uint64_t CopyGas = calculateWordCopyGas(Len)) {
Instance->chargeGas(CopyGas);
}
if (!Instance->expandMemoryChecked(Dest, Len, Src, Len)) {
return;
}

auto &Memory = Instance->getMemory();
std::memmove(&Memory[Dest], &Memory[Src], Len);
}
void evmSetReturn(zen::runtime::EVMInstance *Instance, uint64_t Offset,
uint64_t Len) {
std::vector<uint8_t> ReturnData;
if (Len > 0) {
if (!Instance->expandMemoryChecked(Offset, Len)) {
return;
}
auto &Memory = Instance->getMemory();
ReturnData = std::vector<uint8_t>(Memory.begin() + Offset,
Memory.begin() + Offset + Len);
uint8_t *MemoryBase = Instance->getMemoryBase();
ReturnData =
std::vector<uint8_t>(MemoryBase + Offset, MemoryBase + Offset + Len);
}
Instance->setReturnData(ReturnData);

Expand Down Expand Up @@ -611,7 +553,7 @@ void evmSetCallDataCopy(zen::runtime::EVMInstance *Instance,
const evmc_message *Msg = Instance->getCurrentMessage();
ZEN_ASSERT(Msg && "No current message set in EVMInstance");

auto &Memory = Instance->getMemory();
uint8_t *MemoryBase = Instance->getMemoryBase();

// Calculate actual source offset and copy size
uint64_t ActualOffset =
Expand All @@ -623,13 +565,13 @@ void evmSetCallDataCopy(zen::runtime::EVMInstance *Instance,
: 0;

if (CopySize > 0) {
std::memcpy(Memory.data() + DestOffset, Msg->input_data + ActualOffset,
std::memcpy(MemoryBase + DestOffset, Msg->input_data + ActualOffset,
CopySize);
}

// Fill remaining bytes with zeros if needed
if (Size > CopySize) {
std::memset(Memory.data() + DestOffset + CopySize, 0, Size - CopySize);
std::memset(MemoryBase + DestOffset + CopySize, 0, Size - CopySize);
}
}

Expand Down Expand Up @@ -657,22 +599,21 @@ void evmSetExtCodeCopy(zen::runtime::EVMInstance *Instance,
Instance->chargeGas(CopyGas);
}

auto &Memory = Instance->getMemory();
uint8_t *MemoryBase = Instance->getMemoryBase();
size_t CodeSize = Module->Host->get_code_size(Addr);

if (Offset >= CodeSize) {
// If offset is beyond code size, fill with zeros
std::memset(Memory.data() + DestOffset, 0, Size);
std::memset(MemoryBase + DestOffset, 0, Size);
} else {
uint64_t CopySize =
std::min<uint64_t>(Size, static_cast<uint64_t>(CodeSize) - Offset);
size_t CopiedSize = Module->Host->copy_code(
Addr, Offset, Memory.data() + DestOffset, CopySize);
Addr, Offset, MemoryBase + DestOffset, CopySize);

// Fill remaining bytes with zeros if needed
if (Size > CopiedSize) {
std::memset(Memory.data() + DestOffset + CopiedSize, 0,
Size - CopiedSize);
std::memset(MemoryBase + DestOffset + CopiedSize, 0, Size - CopiedSize);
}
}
}
Expand All @@ -691,23 +632,27 @@ void evmSetReturnDataCopy(zen::runtime::EVMInstance *Instance,
}

const auto &ReturnData = Instance->getReturnData();
auto &Memory = Instance->getMemory();
uint8_t *MemoryBase = Instance->getMemoryBase();

if (Offset >= ReturnData.size()) {
std::memset(Memory.data() + DestOffset, 0, Size);
std::memset(MemoryBase + DestOffset, 0, Size);
} else {
uint64_t CopySize = std::min<uint64_t>(
Size, static_cast<uint64_t>(ReturnData.size()) - Offset);
std::memcpy(Memory.data() + DestOffset, ReturnData.data() + Offset,
CopySize);
std::memcpy(MemoryBase + DestOffset, ReturnData.data() + Offset, CopySize);

// Fill remaining bytes with zeros
if (Size > CopySize) {
std::memset(Memory.data() + DestOffset + CopySize, 0, Size - CopySize);
std::memset(MemoryBase + DestOffset + CopySize, 0, Size - CopySize);
}
}
}

void evmExpandMemoryNoGas(zen::runtime::EVMInstance *Instance,
uint64_t RequiredSize) {
Instance->expandMemoryNoGas(RequiredSize);
}

uint64_t evmGetReturnDataSize(zen::runtime::EVMInstance *Instance) {
const auto &ReturnData = Instance->getReturnData();
return ReturnData.size();
Expand All @@ -733,8 +678,8 @@ static void evmEmitLogGeneric(zen::runtime::EVMInstance *Instance,
if (!Instance->expandMemoryChecked(Offset, Size)) {
return;
}
auto &Memory = Instance->getMemory();
Data = Memory.data() + Offset;
uint8_t *MemoryBase = Instance->getMemoryBase();
Data = MemoryBase + Offset;
}

// Build topic array - only include non-null topics
Expand Down Expand Up @@ -840,8 +785,8 @@ const uint8_t *evmHandleCreateInternal(zen::runtime::EVMInstance *Instance,
return ZeroAddress;
}

auto &Memory = Instance->getMemory();
InitCode = Memory.data() + Offset;
uint8_t *MemoryBase = Instance->getMemoryBase();
InitCode = MemoryBase + Offset;
}

// Create message for CREATE/CREATE2
Expand Down Expand Up @@ -925,10 +870,6 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance,
if (Rev >= EVMC_BERLIN &&
Module->Host->access_account(TargetAddr) == EVMC_ACCESS_COLD) {
Instance->chargeGas(zen::evm::ADDITIONAL_COLD_ACCOUNT_ACCESS_COST);
} else if (Rev >= EVMC_TANGERINE_WHISTLE && Rev <= EVMC_ISTANBUL) {
if (CallKind == EVMC_DELEGATECALL) {
Instance->chargeGas(zen::evm::DELEGATECALL_EXTRA_GAS_TW_TO_ISTANBUL);
}
}

const bool TransfersValue =
Expand Down Expand Up @@ -974,15 +915,25 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance,
// Only expand memory if we actually need to access it
bool needArgsMemory = ArgsSize > 0;
bool needRetMemory = RetSize > 0;
if (needArgsMemory || needRetMemory) {
if (needArgsMemory && needRetMemory) {
if (!Instance->expandMemoryChecked(ArgsOffset, ArgsSize, RetOffset,
RetSize)) {
Instance->setReturnData({});
return 0;
}
} else if (needArgsMemory) {
if (!Instance->expandMemoryChecked(ArgsOffset, ArgsSize)) {
Instance->setReturnData({});
return 0;
}
} else if (needRetMemory) {
if (!Instance->expandMemoryChecked(RetOffset, RetSize)) {
Instance->setReturnData({});
return 0;
}
}

auto &Memory = Instance->getMemory();
uint8_t *MemoryBase = Instance->getMemoryBase();
uint64_t CallGas = Gas;
uint64_t GasLeft = Instance->getGas();
if (Rev >= EVMC_TANGERINE_WHISTLE) {
Expand All @@ -997,6 +948,11 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance,
CallGas += zen::evm::CALL_GAS_STIPEND;
}

if (CurrentMsg->depth >= zen::evm::MAXSTACK) {
Instance->setReturnData({});
return 0;
}

// Create message for call
evmc_message CallMsg{
.kind = CallKind,
Expand All @@ -1009,7 +965,7 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance,
: CurrentMsg->recipient,
.sender = (CallKind == EVMC_DELEGATECALL) ? CurrentMsg->sender
: CurrentMsg->recipient,
.input_data = Memory.data() + ArgsOffset,
.input_data = MemoryBase + ArgsOffset,
.input_size = ArgsSize,
.value = (CallKind == EVMC_DELEGATECALL)
? CurrentMsg->value
Expand Down Expand Up @@ -1045,11 +1001,12 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance,
Instance->addGasRefund(Result.gas_refund);
}

// Copy return data to memory if output area is specified
// Copy return data to memory if output area is specified.
// Per EVM semantics, bytes beyond returned data length remain unchanged.
if (RetSize > 0 && Result.output_size > 0) {
size_t CopySize =
std::min(static_cast<size_t>(RetSize), Result.output_size);
std::memcpy(Memory.data() + RetOffset, Result.output_data, CopySize);
std::memcpy(MemoryBase + RetOffset, Result.output_data, CopySize);
}

// Store full return data for RETURNDATASIZE/RETURNDATACOPY
Expand Down Expand Up @@ -1124,9 +1081,9 @@ void evmSetRevert(zen::runtime::EVMInstance *Instance, uint64_t Offset,
if (!Instance->expandMemoryChecked(Offset, Size)) {
return;
}
auto &Memory = Instance->getMemory();
ReturnData = std::vector<uint8_t>(Memory.begin() + Offset,
Memory.begin() + Offset + Size);
uint8_t *MemoryBase = Instance->getMemoryBase();
ReturnData =
std::vector<uint8_t>(MemoryBase + Offset, MemoryBase + Offset + Size);
}
Instance->setReturnData(std::move(ReturnData));
const int64_t GasLeft =
Expand Down Expand Up @@ -1157,17 +1114,17 @@ void evmSetCodeCopy(zen::runtime::EVMInstance *Instance, uint64_t DestOffset,
const zen::common::Byte *Code = Module->Code;
size_t CodeSize = Module->CodeSize;

auto &Memory = Instance->getMemory();
uint8_t *MemoryBase = Instance->getMemoryBase();

if (Offset < CodeSize) {
auto CopySize = std::min(Size, CodeSize - Offset);
std::memcpy(Memory.data() + DestOffset, Code + Offset, CopySize);
std::memcpy(MemoryBase + DestOffset, Code + Offset, CopySize);
if (Size > CopySize) {
std::memset(Memory.data() + DestOffset + CopySize, 0, Size - CopySize);
std::memset(MemoryBase + DestOffset + CopySize, 0, Size - CopySize);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to add a CALL output non-overwrite test (evm case), first fill the output area with non-zero values, call returns data length < retSize, after execution verify that [retOffset+CopySize, retOffset+retSize) remains unchanged.

}
} else {
if (Size > 0) {
std::memset(Memory.data() + DestOffset, 0, Size);
std::memset(MemoryBase + DestOffset, 0, Size);
}
}
}
Expand All @@ -1182,8 +1139,8 @@ const uint8_t *evmGetKeccak256(zen::runtime::EVMInstance *Instance,
const uint64_t ExtraGas =
static_cast<uint64_t>(numWords(static_cast<uint64_t>(Length))) * 6;
Instance->chargeGas(ExtraGas);
auto &Memory = Instance->getMemory();
InputData = Memory.data() + Offset;
uint8_t *MemoryBase = Instance->getMemoryBase();
InputData = MemoryBase + Offset;
}

auto &Cache = Instance->getMessageCache();
Expand Down
Loading