Skip to content
Open
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
13 changes: 2 additions & 11 deletions src/common/evm_traphandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ void EVMCallThreadState::setJITTraces() {
return;
}
uint32_t IgnoredDepth = getTrapState().NumIgnoredFrames;
ZEN_ASSERT(Inst);
void *JITCode = Inst->getModule()->getJITCode();
void *JITCodeEnd =
static_cast<uint8_t *>(JITCode) + Inst->getModule()->getJITCodeSize();
Expand Down Expand Up @@ -120,14 +119,6 @@ bool initEVMPlatformTrapHandler() {
// it. It will either crash synchronously, fix up the instruction
// so that execution can continue and return, or trigger a crash by
// returning the signal to it's original disposition and returning.

// Unblock the signal before forwarding to the previous handler,
// preserving the same semantics as when SA_NODEFER was used.
sigset_t SignalSet;
sigemptyset(&SignalSet);
sigaddset(&SignalSet, SigNum);
int UnblockResult = sigprocmask(SIG_UNBLOCK, &SignalSet, nullptr);
ZEN_ASSERT(UnblockResult == 0);
if ((PrevSigAction->sa_flags & SA_SIGINFO) != 0) {
PrevSigAction->sa_sigaction(SigNum, SigInfo, Ctx);
} else if ((void (*)(int))PrevSigAction->sa_sigaction == SIG_DFL ||
Expand Down Expand Up @@ -159,9 +150,9 @@ bool initEVMPlatformTrapHandler() {
struct sigaction Handler;
memset(&Handler, 0x0, sizeof(struct sigaction));
#ifdef ZEN_ENABLE_VIRTUAL_STACK
Handler.sa_flags = SA_SIGINFO | SA_ONSTACK;
Handler.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
#else
Handler.sa_flags = SA_SIGINFO;
Handler.sa_flags = SA_SIGINFO | SA_NODEFER;
#endif // ZEN_ENABLE_VIRTUAL_STACK
Handler.sa_sigaction = TrapHandler;
sigemptyset(&Handler.sa_mask);
Expand Down
11 changes: 7 additions & 4 deletions src/common/evm_traphandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class EVMCallThreadState {

void restartHandler() { Handling = true; }

void jmpToMarked(int Signum) { siglongjmp(*JmpBuf, Signum); }
void jmpToMarked(int Signum) { longjmp(*JmpBuf, Signum); }

void setTrapFrameAddr(void *Addr, void *PC, void *FaultingAddress,
uint32_t NumIgnoredFrames) {
Expand Down Expand Up @@ -148,9 +148,12 @@ bool initEVMPlatformTrapHandler();
// may not used
// so need set it when unwind backtrace after ud2
#define SAVE_EVM_HOSTAPI_FRAME_POINTER_TO_TLS \
void *FrameAddr = __builtin_frame_address(0); \
auto TLS = common::evm_traphandler::EVMCallThreadState::current(); \
TLS->setTrapFrameAddr(FrameAddr, nullptr, nullptr, 0);
do { \
void *FrameAddr = __builtin_frame_address(0); \
auto *TLS_ = common::evm_traphandler::EVMCallThreadState::current(); \
ZEN_ASSERT(TLS_ != nullptr); \
TLS_->setTrapFrameAddr(FrameAddr, nullptr, nullptr, 0); \
} while (0)

#endif // ZEN_ENABLE_CPU_EXCEPTION

Expand Down
60 changes: 8 additions & 52 deletions src/compiler/evm_frontend/evm_imported.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,42 +102,6 @@ inline void triggerStaticModeViolation(zen::runtime::EVMInstance *Instance) {
zen::runtime::EVMInstance::triggerInstanceExceptionOnJIT(
Instance, zen::common::ErrorCode::EVMStaticModeViolation);
}

constexpr uint8_t DelegationMagicBytes[] = {0xef, 0x01, 0x00};

bool resolveDelegatedCallCodeAddress(zen::runtime::EVMInstance *Instance,
evmc::address TargetAddr,
evmc::address &CodeAddr) {
CodeAddr = TargetAddr;
if (Instance->getRevision() < EVMC_PRAGUE) {
return true;
}

const zen::runtime::EVMModule *Module = Instance->getModule();
ZEN_ASSERT(Module && Module->Host);
uint8_t Designation[sizeof(DelegationMagicBytes) + sizeof(evmc::address)] =
{};
const size_t Copied =
Module->Host->copy_code(TargetAddr, 0, Designation, sizeof(Designation));
if (Copied < sizeof(DelegationMagicBytes) ||
std::memcmp(Designation, DelegationMagicBytes,
sizeof(DelegationMagicBytes)) != 0) {
return true;
}

if (Copied != sizeof(Designation)) {
return true;
}

std::memcpy(CodeAddr.bytes, Designation + sizeof(DelegationMagicBytes),
sizeof(CodeAddr.bytes));
const uint64_t DelegateAccessCost =
Module->Host->access_account(CodeAddr) == EVMC_ACCESS_COLD
? zen::evm::COLD_ACCOUNT_ACCESS_COST
: zen::evm::WARM_STORAGE_READ_COST;
Instance->chargeGas(DelegateAccessCost);
return true;
}
} // namespace

const RuntimeFunctions &getRuntimeFunctionTable() {
Expand Down Expand Up @@ -890,9 +854,13 @@ const uint8_t *evmHandleCreateInternal(zen::runtime::EVMInstance *Instance,
Instance->setReturnData(std::move(ReturnData));

if (Result.status_code == EVMC_SUCCESS) {
static thread_local uint8_t PaddedAddress[32] = {0};
memcpy(PaddedAddress + 12, Result.create_address.bytes, 20);
return PaddedAddress;
// Keep returned CREATE addresses in per-instance cache to avoid aliasing
// between nested/re-entrant CREATE paths.
auto &ExecCache = Instance->getMessageCache();
evmc::bytes32 PaddedAddress{};
std::memcpy(PaddedAddress.bytes + 12, Result.create_address.bytes, 20);
ExecCache.CreateAddresses.push_back(PaddedAddress);
return ExecCache.CreateAddresses.back().bytes;
}
return ZeroAddress;
}
Expand Down Expand Up @@ -928,12 +896,6 @@ static uint64_t evmHandleCallInternal(
Instance->chargeGas(zen::evm::ADDITIONAL_COLD_ACCOUNT_ACCESS_COST);
}

evmc::address CodeAddr = TargetAddr;
if (!resolveDelegatedCallCodeAddress(Instance, TargetAddr, CodeAddr)) {
Instance->setReturnData({});
return 0;
}

const bool HasValueArgs = CallKind == EVMC_CALL || CallKind == EVMC_CALLCODE;
const bool HasValue = Value != 0;

Expand Down Expand Up @@ -1032,16 +994,10 @@ static uint64_t evmHandleCallInternal(
? CurrentMsg->value
: intx::be::store<evmc::bytes32>(Value),
.create2_salt = {},
.code_address = CodeAddr,
.code_address = TargetAddr,
.code = nullptr,
.code_size = 0,
};
if (std::memcmp(TargetAddr.bytes, CodeAddr.bytes, sizeof(TargetAddr.bytes)) !=
0) {
CallMsg.flags |= EVMC_DELEGATED;
} else {
CallMsg.flags &= ~uint32_t(EVMC_DELEGATED);
}

Instance->pushMessage(&CallMsg);
evmc::Result Result = Module->Host->call(CallMsg);
Expand Down
60 changes: 60 additions & 0 deletions src/evm/evm_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ struct GasBlock {
};

static void addEdge(std::vector<GasBlock> &Blocks, uint32_t From, uint32_t To) {
if (From >= Blocks.size() || To >= Blocks.size()) {
return;
}
auto &FromSuccs = Blocks[From].Succs;
if (std::find(FromSuccs.begin(), FromSuccs.end(), To) == FromSuccs.end()) {
FromSuccs.push_back(To);
Expand All @@ -223,6 +226,9 @@ static bool splitCriticalEdges(std::vector<GasBlock> &Blocks, size_t CodeSize) {
continue; // Not a critical edge source
}
for (uint32_t ToId : Blocks[FromId].Succs) {
if (ToId >= Blocks.size()) {
continue;
}
if (Blocks[ToId].Preds.size() > 1) {
// Critical edge: From has multiple succs, To has multiple preds
EdgesToSplit.push_back({static_cast<uint32_t>(FromId), ToId});
Expand Down Expand Up @@ -450,6 +456,9 @@ computeInCycle(const std::vector<GasBlock> &Blocks) {
while (!Stack.empty()) {
const uint32_t Node = Stack.back();
Stack.pop_back();
if (Node >= NumBlocks) {
continue;
}
Component.push_back(Node);
for (uint32_t Pred : Blocks[Node].Preds) {
if (Pred >= NumBlocks) {
Expand All @@ -468,6 +477,9 @@ computeInCycle(const std::vector<GasBlock> &Blocks) {
}
continue;
}
if (Component.empty()) {
continue;
}

const uint32_t Only = Component.front();
for (uint32_t Succ : Blocks[Only].Succs) {
Expand Down Expand Up @@ -528,7 +540,13 @@ computeReachable(const std::vector<GasBlock> &Blocks, uint32_t EntryId) {
while (!Stack.empty()) {
const uint32_t Node = Stack.back();
Stack.pop_back();
if (Node >= NumBlocks) {
continue;
}
for (uint32_t Succ : Blocks[Node].Succs) {
if (Succ >= NumBlocks) {
continue;
}
if (Reachable[Succ] == 0) {
Reachable[Succ] = 1;
Stack.push_back(Succ);
Expand Down Expand Up @@ -571,6 +589,9 @@ computeDominators(const std::vector<GasBlock> &Blocks,
NewDom = All;
bool HasPred = false;
for (uint32_t Pred : Blocks[Node].Preds) {
if (Pred >= NumBlocks) {
continue;
}
if (Reachable[Pred] == 0) {
continue;
}
Expand Down Expand Up @@ -604,6 +625,9 @@ findBackEdgesUsingDominators(const std::vector<GasBlock> &Blocks,

for (size_t From = 0; From < NumBlocks; ++From) {
for (uint32_t To : Blocks[From].Succs) {
if (To >= NumBlocks) {
continue;
}
if (bitsetTest(Dom[From], To)) {
BackEdges[From].push_back(To);
}
Expand All @@ -613,6 +637,9 @@ findBackEdgesUsingDominators(const std::vector<GasBlock> &Blocks,

static bool isBackEdge(const std::vector<std::vector<uint32_t>> &BackEdges,
uint32_t From, uint32_t To) {
if (From >= BackEdges.size()) {
return false;
}
const auto &Edges = BackEdges[From];
return std::find(Edges.begin(), Edges.end(), To) != Edges.end();
}
Expand All @@ -634,6 +661,9 @@ computeReverseTopo(const std::vector<GasBlock> &Blocks,
while (!Stack.empty()) {
uint32_t Current = Stack.back();
Stack.pop_back();
if (Current >= NumBlocks) {
continue;
}
if (Visited[Current] == 2) {
continue;
}
Expand All @@ -647,6 +677,9 @@ computeReverseTopo(const std::vector<GasBlock> &Blocks,
const auto &Succs = Blocks[Current].Succs;
for (auto It = Succs.rbegin(); It != Succs.rend(); ++It) {
uint32_t Succ = *It;
if (Succ >= NumBlocks) {
continue;
}
if (!isBackEdge(BackEdges, Current, Succ) && Visited[Succ] == 0) {
Visited[Succ] = 1;
Stack.push_back(Succ);
Expand Down Expand Up @@ -679,7 +712,13 @@ collectNaturalLoop(uint32_t From, uint32_t Header,
while (!Stack.empty()) {
const uint32_t Node = Stack.back();
Stack.pop_back();
if (Node >= NumBlocks) {
continue;
}
for (uint32_t Pred : Blocks[Node].Preds) {
if (Pred >= NumBlocks) {
continue;
}
if (Reachable[Pred] == 0) {
continue;
}
Expand Down Expand Up @@ -713,6 +752,9 @@ static bool buildLoopsUsingDominance(
continue;
}
for (uint32_t To : Blocks[From].Succs) {
if (To >= NumBlocks) {
continue;
}
if (!bitsetTest(Dom[From], To)) {
continue;
}
Expand Down Expand Up @@ -758,6 +800,9 @@ static bool buildLoopsUsingDominance(

for (const auto &Loop : Loops) {
for (uint32_t Node : Loop.Nodes) {
if (Node >= Dom.size() || Loop.Header >= NumBlocks) {
return false;
}
if (!bitsetTest(Dom[Node], Loop.Header)) {
return false;
}
Expand Down Expand Up @@ -814,6 +859,9 @@ static bool buildLoopsUsingDominance(
for (size_t OrderIndex = 0; OrderIndex < LoopOrder.size(); ++OrderIndex) {
const size_t LoopId = LoopOrder[OrderIndex];
for (uint32_t Node : Loops[LoopId].Nodes) {
if (Node >= LoopOf.size()) {
return false;
}
if (LoopOf[Node] == -1) {
LoopOf[Node] = static_cast<int32_t>(LoopId);
}
Expand All @@ -832,8 +880,14 @@ static bool buildLoopsUsingDominance(
for (size_t LoopId = 0; LoopId < Loops.size(); ++LoopId) {
auto &Loop = Loops[LoopId];
for (uint32_t Node : Loop.Nodes) {
if (Node >= NumBlocks) {
continue;
}
bool IsExit = false;
for (uint32_t Succ : Blocks[Node].Succs) {
if (Succ >= NumBlocks) {
continue;
}
if (!bitsetTest(Loop.NodeMask, Succ)) {
IsExit = true;
break;
Expand Down Expand Up @@ -872,6 +926,9 @@ static bool lemma614Update(uint32_t NodeId, const std::vector<GasBlock> &Blocks,

uint64_t MinSucc = UINT64_MAX;
for (uint32_t Succ : Node.Succs) {
if (Succ >= Blocks.size() || Succ >= Metering.size()) {
continue;
}
if (BackEdges && isBackEdge(*BackEdges, NodeId, Succ)) {
continue;
}
Expand All @@ -891,6 +948,9 @@ static bool lemma614Update(uint32_t NodeId, const std::vector<GasBlock> &Blocks,

Metering[NodeId] += MinSucc;
for (uint32_t Succ : Node.Succs) {
if (Succ >= Blocks.size() || Succ >= Metering.size()) {
continue;
}
if (BackEdges && isBackEdge(*BackEdges, NodeId, Succ)) {
continue;
}
Expand Down
1 change: 1 addition & 0 deletions src/platform/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <climits>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>

Expand Down
2 changes: 1 addition & 1 deletion src/runtime/evm_instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ void EVMInstance::setInstanceExceptionOnJIT(EVMInstance *Inst,

void EVMInstance::throwInstanceExceptionOnJIT(EVMInstance *Inst) {
#ifdef ZEN_ENABLE_CPU_EXCEPTION
SAVE_EVM_HOSTAPI_FRAME_POINTER_TO_TLS
SAVE_EVM_HOSTAPI_FRAME_POINTER_TO_TLS;

utils::throwCpuIllegalInstructionTrap();
#endif // ZEN_ENABLE_CPU_EXCEPTION
Expand Down
11 changes: 8 additions & 3 deletions src/runtime/evm_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
#include "runtime/evm_module.h"
#include "runtime/instance.h"
#include <array>
#include <deque>
#include <limits>
#include <list>
#include <memory>

// Forward declaration for evmc_message
Expand Down Expand Up @@ -158,8 +158,12 @@ class EVMInstance final : public RuntimeObject<EVMInstance> {
std::unordered_map<std::pair<const evmc_message *, uint64_t>, evmc::bytes32,
PairHash>
CalldataLoads;
std::deque<evmc::bytes32> ExtcodeHashes;
std::deque<evmc::bytes32> Keccak256Results;
// Use std::list (not std::deque) for values whose .bytes pointers are
// returned to JIT and may outlive further push_back calls; deque can
// reallocate and invalidate earlier element addresses.
std::list<evmc::bytes32> ExtcodeHashes;
std::list<evmc::bytes32> Keccak256Results;
std::list<evmc::bytes32> CreateAddresses;
bool TxContextCached = false;

void clear() {
Expand All @@ -170,6 +174,7 @@ class EVMInstance final : public RuntimeObject<EVMInstance> {
CalldataLoads.clear();
ExtcodeHashes.clear();
Keccak256Results.clear();
CreateAddresses.clear();
}
};

Expand Down
2 changes: 2 additions & 0 deletions src/utils/logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

#include "common/defines.h"
#include "platform/platform.h"
#include <cstdio>
#include <memory>
#include <string>

#ifdef ZEN_ENABLE_SPDLOG
namespace spdlog {
Expand Down
Loading
Loading