Skip to content

Commit 0ebd0d9

Browse files
committed
merging pygments support from ui branch with x86 highlight formatter,
release parts of tests/ directory and add tox+travis configs
1 parent d4d46e8 commit 0ebd0d9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1352
-112
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ tags
22
*.pyc
33
*.swp
44
build/
5-
tests/
5+
dist/
6+
*.egg-info
7+
tests/priv
8+
.tox/

.travis.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
language: python
2+
python: 2.7
3+
install:
4+
- python setup.py install
5+
- pip install tox
6+
- apt-get install unzip
7+
- wget -q -O /tmp/z3.zip https://github.com/Z3Prover/bin/blob/master/releases/z3-4.4.0-x64-ubuntu-14.04.zip
8+
- mkdir z3
9+
- unzip -q -d z3 -j /tmp/z3.zip
10+
- export PYTHONPATH=$PYTHONPATH:$(pwd)/z3
11+
script:
12+
- tox
13+
env:
14+
- TOXENV=py27
15+
- TOXENV=py27-full

README.rst

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
=====
22
Amoco
33
=====
4+
5+
.. image:: https://travis-ci.org/bdcht/amoco.svg?branch=release
6+
:target: https://travis-ci.org/bdcht/amoco
7+
48
+-----------+-----------------------------------+
59
| Status: | Under Development |
610
+-----------+-----------------------------------+
@@ -88,7 +92,7 @@ Amoco is tested on python 2.7 and depends on the following python packages:
8892
- grandalf_ used for building CFG (and eventually rendering it)
8993
- crysp_ used by the generic intruction decoder (``arch/core.py``)
9094
- z3_ used to simplify expressions and solve constraints
91-
- pygments_ (not in current release, planned for 2.4.2 release)
95+
- pygments_ used for pretty printing of assembly code and expressions
9296
- pyparsing_ for parsing instruction decoder formats
9397
- ply_ (optional), for parsing *GNU as* files
9498
- zodb_ (optional), provides persistence of amoco objects in a database
@@ -102,7 +106,7 @@ Below is a very simple example where basic blocks are build with linear sweep:
102106
.. sourcecode:: python
103107

104108
>>> import amoco
105-
>>> p = amoco.system.loader.load_program('tests/samples/flow.elf')
109+
>>> p = amoco.system.loader.load_program('tests/samples/x86/flow.elf')
106110
amoco.system.loader: INFO: Elf32 file detected
107111
amoco.system.loader: INFO: linux_x86 program created
108112
>>> p
@@ -1334,6 +1338,20 @@ Please see `LICENSE`_.
13341338
Changelog
13351339
=========
13361340

1341+
- `v2.4.2`_
1342+
1343+
* merge support for pygments pretty printing methods (in ui.render module)
1344+
* add x86 hilighted syntax formatter (in arch.x86.formats)
1345+
* expose expression's pretty printing interface (exp.pp(), exp.toks())
1346+
* remove default config class fallback (ConfigParser is standard)
1347+
* merge some samples and tests ported to pytest package
1348+
* use setuptools, add tox.ini and travis-ci config
1349+
* fix some x86/x64 semantics
1350+
* improve sparc v8 formats
1351+
* add sparc coprocessor registers
1352+
* update README
1353+
1354+
13371355
- `v2.4.1`_
13381356

13391357
* add lbackward analysis and func.makemap() implementations
@@ -1412,6 +1430,7 @@ Changelog
14121430
.. _ply: http://www.dabeaz.com/ply/
14131431
.. _zodb: http://www.zodb.org
14141432
.. _LICENSE: https://github.com/bdcht/amoco/blob/release/LICENSE
1433+
.. _v2.4.2: https://github.com/bdcht/amoco/releases/tag/v2.4.2
14151434
.. _v2.4.1: https://github.com/bdcht/amoco/releases/tag/v2.4.1
14161435
.. _v2.4.0: https://github.com/bdcht/amoco/releases/tag/v2.4.0
14171436
.. _v2.3.5: https://github.com/bdcht/amoco/releases/tag/v2.3.5

amoco/arch/core.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,13 +458,21 @@ def __init__(self,formats):
458458
self.formats = formats
459459
self.default = ('{i.mnemonic} ', lambda i: ', '.join(map(str,i.operands)))
460460

461-
def __call__(self,i):
462-
s=[]
461+
def getkey(self,i):
462+
if i.mnemonic in self.formats: return i.mnemonic
463+
if i.spec.hook.func_name in self.formats: return i.spec.hook.func_name
464+
return None
465+
466+
def getparts(self,i):
463467
try:
464468
fmts = self.formats[i.mnemonic]
465469
except KeyError:
466470
fmts = self.formats.get(i.spec.hook.func_name,self.default)
467-
for f in fmts:
471+
return fmts
472+
473+
def __call__(self,i):
474+
s=[]
475+
for f in self.getparts(i):
468476
if hasattr(f,'format'):
469477
# It is a string
470478
s.append(f.format(i=i))

amoco/arch/sparc/env.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
R = [reg('r%d'%x,32) for x in range(520)]
1919
# fpu registers:
2020
f = [reg('f%d'%x,32) for x in range(32)]
21+
# coprocessor registers:
22+
c = [reg('c%d'%x,32) for x in range(32)]
2123

2224
# symbols for r0 ... r7:
2325
g0,g1,g2,g3,g4,g5,g6,g7 = (reg('g%d'%x,32) for x in range(8))

amoco/arch/x86/cpu_x86.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
from amoco.arch.core import instruction, disassembler
88

99
instruction.set_uarch(uarch)
10-
from amoco.arch.x86.formats import IA32_Intel
10+
11+
from amoco.arch.x86.formats import *
12+
1113
instruction.set_formatter(IA32_Intel)
1214

1315
from amoco.arch.x86 import spec_ia32
@@ -17,3 +19,12 @@
1719

1820
def PC():
1921
return eip
22+
23+
def configure(**kargs):
24+
from amoco.config import get_module_conf
25+
conf = get_module_conf('x86')
26+
conf.update(kargs)
27+
if conf['highlight']:
28+
instruction.set_formatter(IA32_Intel_highlighted)
29+
30+
configure()

amoco/arch/x86/formats.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,39 @@ def oprel(i):
6969

7070
IA32_Intel = Formatter(IA32_Intel_formats)
7171
IA32_Intel.default = format_intel_default
72+
73+
# highlighted formatter:
74+
#-----------------------
75+
from amoco.ui import render
76+
77+
def IA32_Intel_tokenize(i):
78+
toks = []
79+
for f in IA32_Intel.getparts(i):
80+
if f is pfx: toks.append((render.Token.Prefix,f(i)))
81+
elif f is mnemo: toks.append((render.Token.Mnemonic,f(i)))
82+
elif f is oprel:
83+
s = f(i)
84+
if s.startswith('*'):
85+
t = render.Token.Address
86+
else:
87+
t = render.Token.Constant
88+
toks.append((t,s))
89+
elif f is opers:
90+
for op in i.operands:
91+
if op._is_reg: toks.append((render.Token.Register,str(op)))
92+
elif op._is_mem: toks.append((render.Token.Memory,deref(op)))
93+
elif op._is_cst:
94+
if i.misc['imm_ref'] is not None:
95+
toks.append((render.Token.Address,str(i.misc['imm_ref'])))
96+
elif op.sf:
97+
toks.append((render.Token.Constant,'%+d'%op.value))
98+
else:
99+
toks.append((render.Token.Constant,str(op)))
100+
toks.append((render.Token.Literal,', '))
101+
if toks[-1][0] is render.Token.Literal: toks.pop()
102+
else:
103+
toks.append((render.Token.Comment,f(i)))
104+
return toks
105+
106+
def IA32_Intel_highlighted(null, i):
107+
return render.highlight(IA32_Intel_tokenize(i))

amoco/cas/expressions.py

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
from amoco.logger import Log
88
logger = Log(__name__)
99

10+
from amoco.ui.render import Token,highlight
11+
1012
# decorators:
1113
#------------
1214

@@ -92,11 +94,12 @@ def setendian(cls,e):
9294
def length(self): # length value is in bytes
9395
return self.size/8
9496

95-
def bytes(self,sta=0,sto=None):
97+
def bytes(self,sta=0,sto=None,endian=0):
9698
s = slice(sta,sto)
9799
l = self.length
98100
sta,sto,stp = s.indices(l)
99-
if self._endian==-1:
101+
endian |= self._endian
102+
if endian==-1:
100103
sta,sto = l-sto,l-sta
101104
return self[sta*8:sto*8]
102105

@@ -131,6 +134,12 @@ def __str__(self):
131134
if self._is_def is False: return '⊥%d'%self.size
132135
raise ValueError("void expression")
133136

137+
def toks(self,**kargs):
138+
return [(Token.Literal,str(self))]
139+
140+
def pp(self,**kargs):
141+
return highlight(self.toks(**kargs))
142+
134143
def bit(self,i):
135144
i = i%self.size
136145
return self[i:i+1]
@@ -293,6 +302,9 @@ def __int__(self):
293302
def __str__(self):
294303
return '{:#x}'.format(self.value)
295304

305+
def toks(self,**kargs):
306+
return [(Token.Constant,str(self))]
307+
296308
def to_sym(self,ref):
297309
return sym(ref,self.v,self.size)
298310

@@ -473,6 +485,9 @@ def __int__(self):
473485
def __str__(self):
474486
return '{:f}'.format(self.value)
475487

488+
def toks(self,**kargs):
489+
return [(Token.Constant,str(self))]
490+
476491
def eval(self,env): return cfp(self.value,self.size)
477492

478493
def __neg__(self):
@@ -571,6 +586,9 @@ def __getitem__(self,i):
571586
def __str__(self):
572587
return self.ref
573588

589+
def toks(self,**kargs):
590+
return [(Token.Register,str(self))]
591+
574592
def eval(self,env):
575593
return env[self]
576594

@@ -609,6 +627,10 @@ def __init__(self,refname,**kargs):
609627
def __str__(self):
610628
return '@%s'%self.ref
611629

630+
def toks(self,**kargs):
631+
tk = Token.Tainted if '!' in self.ref else Token.Name
632+
return [(tk,str(self))]
633+
612634
def __setattr__(self,a,v):
613635
exp.__setattr__(self,a,v)
614636

@@ -676,6 +698,17 @@ def __str__(self):
676698
cur += nv.size
677699
return s+' }'
678700

701+
def toks(self,**kargs):
702+
tl = (Token.Literal,', ')
703+
s = [(Token.Literal,'{')]
704+
for nv in self:
705+
t = nv.toks(newline=False,**kargs)
706+
s.extend(t)
707+
s.append(tl)
708+
if len(s)>1: s.pop()
709+
s.append((Token.Literal,'}'))
710+
return s
711+
679712
def eval(self,env):
680713
res = comp(self.size)
681714
res.smask = self.smask[:]
@@ -833,6 +866,9 @@ def __str__(self):
833866
n = '$%d'%n if n>0 else ''
834867
return 'M%d%s%s'%(self.size,n,self.a)
835868

869+
def toks(self,**kargs):
870+
return [(Token.Memory,str(self))]
871+
836872
def eval(self,env):
837873
a = self.a.eval(env)
838874
m = env.use()
@@ -873,6 +909,9 @@ def __str__(self):
873909
d = '%+d'%self.disp if self.disp else ''
874910
return '%s(%s%s)'%(self.seg,self.base,d)
875911

912+
def toks(self,**kargs):
913+
return [(Token.Address,str(self))]
914+
876915
def simplify(self):
877916
self.base,offset = extract_offset(self.base)
878917
self.disp += offset
@@ -950,7 +989,12 @@ def __setattr__(self,a,v):
950989

951990
def __str__(self):
952991
return self.ref or self.raw()
953-
##
992+
993+
def toks(self,**kargs):
994+
if self._is_reg: return [(Token.Register,str(self))]
995+
subpart = [(Token.Literal,'[%d:%d]'%(self.pos,self.pos+self.size))]
996+
return self.x.toks(**kargs)+subpart
997+
954998
def __hash__(self): return hash(self.raw())
955999

9561000
def eval(self,env):
@@ -1021,6 +1065,14 @@ def __init__(self,t,l,r):
10211065
def __str__(self):
10221066
return '(%s ? %s : %s)'%(str(self.tst),str(self.l),str(self.r))
10231067

1068+
def toks(self,**kargs):
1069+
ttest = self.tst.toks(**kargs)
1070+
ttest.append((Token.Literal,' ? '))
1071+
ttrue = self.l.toks(**kargs)
1072+
ttrue.append((Token.Literal,' : '))
1073+
tfalse = self.r.toks(**kargs)
1074+
return ttest+ttrue+tfalse
1075+
10241076
# default verify method if smt module is not loaded.
10251077
# here we check if tst or its negation exist in env.conds but we can
10261078
# only rely on "syntaxic" features unless we have a solver.
@@ -1103,6 +1155,13 @@ def eval(self,env):
11031155
def __str__(self):
11041156
return '(%s%s%s)'%(str(self.l),self.op.symbol,str(self.r))
11051157

1158+
def toks(self,**kargs):
1159+
l = self.l.toks(**kargs)
1160+
l.insert(0,(Token.Literal,'('))
1161+
r = self.r.toks(**kargs)
1162+
r.append((Token.Literal,')'))
1163+
return l+[(Token.Literal,self.op.symbol)]+r
1164+
11061165
def simplify(self):
11071166
minus = (self.op.symbol=='-')
11081167
l = self.l.simplify()
@@ -1168,6 +1227,11 @@ def l(self): return None
11681227
def __str__(self):
11691228
return '(%s%s)'%(self.op.symbol,str(self.r))
11701229

1230+
def toks(self,**kargs):
1231+
r = self.r.toks(**kargs)
1232+
r.append((Token.Literal,')'))
1233+
return [(Token.Literal,'(%s'%self.op.symbol)]+r
1234+
11711235
def simplify(self):
11721236
self.r = self.r.simplify()
11731237
if not self.r._is_def: return top(self.size)

amoco/cas/mapper.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ def __len__(self):
5252
def __str__(self):
5353
return '\n'.join(["%s <- %s"%x for x in self])
5454

55+
def pp(self,**kargs):
56+
lv = [(l.pp(**kargs),v.pp(**kargs)) for (l,v) in self]
57+
return '\n'.join(["%s <- %s"%x for x in lv])
58+
5559
def __getstate__(self):
5660
return (self.__map,self.csi)
5761
def __setstate__(self,state):

0 commit comments

Comments
 (0)