# HG changeset patch # User Mike Pavone # Date 1377382080 25200 # Node ID 270d31c6c4cde4c5e5598891c661e4094b37f787 # Parent 75aca5f879696376ea648f54f5eb288d73114fa9 Add support for jmps and labels in x86 module diff -r 75aca5f87969 -r 270d31c6c4cd modules/bytearray.tp --- a/modules/bytearray.tp Sat Aug 24 09:56:29 2013 -0700 +++ b/modules/bytearray.tp Sat Aug 24 15:08:00 2013 -0700 @@ -59,10 +59,7 @@ } ba <- executable: totalSize bytes fold: 0 with: :idx el { - el fold: idx with: :idx byte { - ba set: idx byte - idx + 1 - } + el flattenTo: ba at: idx } ba } diff -r 75aca5f87969 -r 270d31c6c4cd modules/x86.tp --- a/modules/x86.tp Sat Aug 24 09:56:29 2013 -0700 +++ b/modules/x86.tp Sat Aug 24 15:08:00 2013 -0700 @@ -10,6 +10,7 @@ validforSize? <- :size { true } isInteger? <- { false } register? <- { true } + localLabel? <- { false } upper? <- { true } needsRex? <- { regnum >= 8u8 } rexBitReg <- { @@ -43,6 +44,7 @@ } isInteger? <- { false } register? <- { true } + localLabel? <- { false } upper? <- { true } needsRex? <- { false } = <- :other { @@ -164,6 +166,18 @@ _dh <- upper: 6u8 _bh <- upper: 7u8 + inst <- :ilist { + #{ + length <- { ilist length } + flattenTo:at <- :dest :idx { + ilist fold: idx with: :idx byte { + dest set: idx byte + idx + 1 + } + } + } + } + op:withCode:withImmed:withOpEx <- :src dst size :normal :immed :myopex { reg <- src rm <- dst @@ -179,7 +193,7 @@ (size_bit: normal or 0x02u8 size) | (mod_rm: dst src) } } - prefix: reg rm size withInstruction: base + inst: (prefix: reg rm size withInstruction: base) } op:withCode:withImmed:withImmedRax:withOpEx:withByteExtend <- :src dst size :normal :immed :immedRax :myopex :byteExt { @@ -196,11 +210,10 @@ (size_bit: immed size) | (mod_rm: (opex: myopex) dst withTail: (int_op: src size)) } } - prefix: reg rm size withInstruction: base + inst: (prefix: reg rm size withInstruction: base) } else: { op: src dst size withCode: normal withImmed: immed withOpEx: myopex } - } #{ @@ -244,32 +257,109 @@ if: (src isInteger?) && (dst register?) { opval <- if: size = byte { 0xB0u8 } else: { 0xB8u8 } base <- opval | (int_op64: src size) - prefix: fakesrc rm size withInstruction: base + inst: (prefix: fakesrc rm size withInstruction: base) } else: { op: src dst size withCode: 0x88u8 withImmed: 0xC6u8 withOpEx: 0u8 } } - ret <- { [ 0xC3u8 ] } + ret <- { inst: [ 0xC3u8 ] } + + label <- { + _offset <- -1 + _forwardRefs <- #[] + #{ + length <- { 0 } + hasOffset? <- { _offset >= 0 } + offset <- { _offset } + register? <- { false } + localLabel? <- { true } + flattenTo:at <- :dest :idx { + if: (not: hasOffset?) { + _offset <- idx + foreach: _forwardRefs :idx fun { + fun: _offset + } + _forwardRefs <- #[] + } + idx + } + withOffset:else <- :fun :elsefun { + if: hasOffset? { + fun: _offset + } else: { + _forwardRefs append: fun + elsefun: + } + } + } + } + + jmp <- :jmpDest { + if: (jmpDest localLabel?) { + _size <- -1 + #{ + length <- { if: _size < 0 { 5 } else: { _size } } + flattenTo:at <- :dest :idx { + jmpDest withOffset: :off { + if: _size < 0 { + rel <- off - (idx + 2) + if: rel < 128 && rel >= -128 { + _size <- 2 + } else: { + rel <- rel - 2 + if: rel < 32768 && rel >= -32768 { + _size <- 4 + } else: { + _size <- 5 + } + } + } + rel <- off - (idx + _size) + if: _size = 2 { + dest set: idx 0xEBu8 + dest set: (idx + 1) (uint8: rel) + } else: { + if: _size = 4 { + dest set: idx 0x66u8 + dest set: (idx + 1) 0xE9u8 + dest set: (idx + 2) (uint8: rel) + dest set: (idx + 3) (uint8: (rshift: rel by: 8)) + } else: { + dest set: idx 0xE9u8 + dest set: (idx + 1) (uint8: rel) + dest set: (idx + 2) (uint8: (rshift: rel by: 8)) + dest set: (idx + 3) (uint8: (rshift: rel by: 16)) + dest set: (idx + 4) (uint8: (rshift: rel by: 24)) + } + } + } else: { + _size <- 5 + } + idx + _size + } + } + } else: { + inst: 0xFFu8 | (mod_rm: (opex: 5u8) jmpDest) + } + } main <- { - print: ((add: rax r8 b) map: :el { hex: el }) - print: "\n" - print: ((add: r9 rdx w) map: :el { hex: el }) - print: "\n" - print: ((add: rax rbx q) map: :el { hex: el }) - print: "\n" - print: ((add: 25 rax q) map: :el { hex: el }) - print: "\n" - print: ((add: rcx rdx d) map: :el { hex: el }) - print: "\n" + foo <- label: + bar <- label: prog <- #[ mov: rdi rax q sub: 1 rdi q add: rdi rax q + jmp: bar + foo ret: + bar + sub: 13 rax q + jmp: foo ] + ba <- bytearray executableFromBytes: prog res <- ba runWithArg: 24u64 print: (string: res) . "\n"