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