8 changed files with 635 additions and 330 deletions
@ -0,0 +1,135 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
cpp-ethereum is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file Assembly.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#include "AssemblyItem.h" |
|||
#include <fstream> |
|||
|
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::eth; |
|||
|
|||
unsigned AssemblyItem::bytesRequired(unsigned _addressLength) const |
|||
{ |
|||
switch (m_type) |
|||
{ |
|||
case Operation: |
|||
case Tag: // 1 byte for the JUMPDEST
|
|||
return 1; |
|||
case PushString: |
|||
return 33; |
|||
case Push: |
|||
return 1 + max<unsigned>(1, dev::bytesRequired(m_data)); |
|||
case PushSubSize: |
|||
case PushProgramSize: |
|||
return 4; // worst case: a 16MB program
|
|||
case PushTag: |
|||
case PushData: |
|||
case PushSub: |
|||
return 1 + _addressLength; |
|||
default: |
|||
break; |
|||
} |
|||
BOOST_THROW_EXCEPTION(InvalidOpcode()); |
|||
} |
|||
|
|||
int AssemblyItem::deposit() const |
|||
{ |
|||
switch (m_type) |
|||
{ |
|||
case Operation: |
|||
return instructionInfo(instruction()).ret - instructionInfo(instruction()).args; |
|||
case Push: |
|||
case PushString: |
|||
case PushTag: |
|||
case PushData: |
|||
case PushSub: |
|||
case PushSubSize: |
|||
case PushProgramSize: |
|||
return 1; |
|||
case Tag: |
|||
return 0; |
|||
default:; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
string AssemblyItem::getJumpTypeAsString() const |
|||
{ |
|||
switch (m_jumpType) |
|||
{ |
|||
case JumpType::IntoFunction: |
|||
return "[in]"; |
|||
case JumpType::OutOfFunction: |
|||
return "[out]"; |
|||
case JumpType::Ordinary: |
|||
default: |
|||
return ""; |
|||
} |
|||
} |
|||
|
|||
ostream& dev::eth::operator<<(ostream& _out, AssemblyItem const& _item) |
|||
{ |
|||
switch (_item.type()) |
|||
{ |
|||
case Operation: |
|||
_out << " " << instructionInfo(_item.instruction()).name; |
|||
if (_item.instruction() == eth::Instruction::JUMP || _item.instruction() == eth::Instruction::JUMPI) |
|||
_out << "\t" << _item.getJumpTypeAsString(); |
|||
break; |
|||
case Push: |
|||
_out << " PUSH " << hex << _item.data(); |
|||
break; |
|||
case PushString: |
|||
_out << " PushString" << hex << (unsigned)_item.data(); |
|||
break; |
|||
case PushTag: |
|||
_out << " PushTag " << _item.data(); |
|||
break; |
|||
case Tag: |
|||
_out << " Tag " << _item.data(); |
|||
break; |
|||
case PushData: |
|||
_out << " PushData " << hex << (unsigned)_item.data(); |
|||
break; |
|||
case PushSub: |
|||
_out << " PushSub " << hex << h256(_item.data()).abridged(); |
|||
break; |
|||
case PushSubSize: |
|||
_out << " PushSubSize " << hex << h256(_item.data()).abridged(); |
|||
break; |
|||
case PushProgramSize: |
|||
_out << " PushProgramSize"; |
|||
break; |
|||
case UndefinedItem: |
|||
_out << " ???"; |
|||
break; |
|||
default: |
|||
BOOST_THROW_EXCEPTION(InvalidOpcode()); |
|||
} |
|||
return _out; |
|||
} |
|||
|
|||
ostream& dev::eth::operator<<(ostream& _out, AssemblyItemsConstRef _i) |
|||
{ |
|||
for (AssemblyItem const& i: _i) |
|||
_out << i; |
|||
return _out; |
|||
} |
@ -0,0 +1,92 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation, either version 3 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
cpp-ethereum is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU General Public License |
|||
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file Assembly.h
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2014 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <iostream> |
|||
#include <sstream> |
|||
#include <libdevcore/Common.h> |
|||
#include <libdevcore/Assertions.h> |
|||
#include <libevmcore/SourceLocation.h> |
|||
#include <libevmcore/Instruction.h> |
|||
#include "Exceptions.h" |
|||
|
|||
namespace dev |
|||
{ |
|||
namespace eth |
|||
{ |
|||
|
|||
enum AssemblyItemType { UndefinedItem, Operation, Push, PushString, PushTag, PushSub, PushSubSize, PushProgramSize, Tag, PushData }; |
|||
|
|||
class Assembly; |
|||
|
|||
class AssemblyItem |
|||
{ |
|||
friend class Assembly; |
|||
|
|||
public: |
|||
enum class JumpType { Ordinary, IntoFunction, OutOfFunction }; |
|||
|
|||
AssemblyItem(u256 _push): m_type(Push), m_data(_push) {} |
|||
AssemblyItem(Instruction _i): m_type(Operation), m_data((byte)_i) {} |
|||
AssemblyItem(AssemblyItemType _type, u256 _data = 0): m_type(_type), m_data(_data) {} |
|||
|
|||
AssemblyItem tag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(Tag, m_data); } |
|||
AssemblyItem pushTag() const { assertThrow(m_type == PushTag || m_type == Tag, Exception, ""); return AssemblyItem(PushTag, m_data); } |
|||
|
|||
AssemblyItemType type() const { return m_type; } |
|||
u256 const& data() const { return m_data; } |
|||
/// @returns the instruction of this item (only valid if type() == Operation)
|
|||
Instruction instruction() const { return Instruction(byte(m_data)); } |
|||
|
|||
/// @returns true iff the type and data of the items are equal.
|
|||
bool operator==(AssemblyItem const& _other) const { return m_type == _other.m_type && m_data == _other.m_data; } |
|||
bool operator!=(AssemblyItem const& _other) const { return !operator==(_other); } |
|||
|
|||
/// @returns an upper bound for the number of bytes required by this item, assuming that
|
|||
/// the value of a jump tag takes @a _addressLength bytes.
|
|||
unsigned bytesRequired(unsigned _addressLength) const; |
|||
int deposit() const; |
|||
|
|||
bool match(AssemblyItem const& _i) const { return _i.m_type == UndefinedItem || (m_type == _i.m_type && (m_type != Operation || m_data == _i.m_data)); } |
|||
void setLocation(SourceLocation const& _location) { m_location = _location; } |
|||
SourceLocation const& getLocation() const { return m_location; } |
|||
|
|||
void setJumpType(JumpType _jumpType) { m_jumpType = _jumpType; } |
|||
JumpType getJumpType() const { return m_jumpType; } |
|||
std::string getJumpTypeAsString() const; |
|||
|
|||
private: |
|||
AssemblyItemType m_type; |
|||
u256 m_data; |
|||
SourceLocation m_location; |
|||
JumpType m_jumpType = JumpType::Ordinary; |
|||
}; |
|||
|
|||
using AssemblyItems = std::vector<AssemblyItem>; |
|||
using AssemblyItemsConstRef = vector_ref<AssemblyItem const>; |
|||
|
|||
std::ostream& operator<<(std::ostream& _out, AssemblyItem const& _item); |
|||
std::ostream& operator<<(std::ostream& _out, AssemblyItemsConstRef _i); |
|||
inline std::ostream& operator<<(std::ostream& _out, AssemblyItems const& _i) { return operator<<(_out, AssemblyItemsConstRef(&_i)); } |
|||
|
|||
} |
|||
} |
Loading…
Reference in new issue