82 Commits
Author SHA1 Message Date
pancake 2d0704c4e5 Add acr script 2024-04-30 19:05:42 +02:00
pancake 667723039f Dont disasm by default 2023-03-22 10:29:00 +01:00
pancake 02af08b96c Import the m68k disassembler from the BlastEm emulator 2023-03-22 10:21:23 +01:00
pancake 01b42dce26 Release r0-0.9 2023-03-21 18:23:05 +01:00
pancake 39bede8372 Add build support for AmigaOS 1.3 and 2.0 2023-03-21 18:17:01 +01:00
pancake 30709b9b1d Add make target for AmigaOS 2023-03-21 17:40:27 +01:00
Sergi Àlvarez i Capilla b01e0d7b34 Wasi's stack is tiny 2021-06-07 04:18:44 +02:00
Sergi Àlvarez i Capilla 5a5b11ef98 Use calloc instead of malloc 2021-06-07 01:07:47 +02:00
Sergi Àlvarez i Capilla b3551aa7a2 Initial support for wasi 2021-06-07 01:02:59 +02:00
pancake b0fa755b4b Wrap overflow on large bdiff blocks 2021-03-23 01:13:45 +01:00
pancake 7139b88824 A bit more constified 2021-03-23 01:06:55 +01:00
pancake 0fce443275 More red -> r0 renaming 2021-03-23 00:49:39 +01:00
pancake 3bd7ce6beb Honor arg to d to specify len 2021-03-23 00:48:33 +01:00
pancake ca297b60a0 Dont print incomplete instructions 2021-03-23 00:36:42 +01:00
pancake 1ac42e0af6 Use calc() instead of str2ut64 in s and b commands 2021-03-23 00:36:27 +01:00
pancake 04187f5984 Move cmd_disasm logic into cmd.c 2021-03-23 00:21:46 +01:00
pancake 8e9a02fec4 Fix warnings in the arm disassembler 2021-03-23 00:19:07 +01:00
pancake c3f761ff94 Default build includes x86 disassembler 2021-03-23 00:13:44 +01:00
pancake 8897ce01e8 Fix manpages 2021-03-22 23:37:34 +01:00
pancake c8771027c1 Add plan9 to the readme 2021-03-22 23:36:26 +01:00
pancake f35349f466 Fix r0v 2021-03-22 23:34:51 +01:00
pancake bed3edc0cd Add size.sh test script 2021-03-22 23:34:01 +01:00
pancake 223a733c42 Optimize x32.c for size (add options to disable sse and fpu) 2021-03-22 23:32:42 +01:00
pancake 8a3e45cc98 Fix x32 disassembler for 16bit systems (DOS) 2021-03-21 02:48:32 +01:00
pancake ce68d7c936 Minor initialization fix 2021-03-21 02:39:04 +01:00
pancake dc6bd361bb Better readme 2021-03-21 02:24:57 +01:00
pancake 00b9e7c01f Update the README 2021-03-21 02:20:59 +01:00
pancake 255ac37f51 Posix shell 2021-03-21 02:17:19 +01:00
pancake 5259039363 Fix md5 detection 2021-03-21 02:16:23 +01:00
pancake 764e36319b Check for return value 2021-03-21 02:09:09 +01:00
pancake 93a2864ffb Ignore return value of read and write 2021-03-21 02:06:40 +01:00
pancake f21459b970 Rename bdiff to r0d 2021-03-21 02:04:06 +01:00
pancake 36de8f16bd Add ci 2021-03-21 02:02:12 +01:00
pancake 92923ebf64 More ranamings 2021-03-21 02:01:59 +01:00
pancake e4aecf63df Release 0.8 2021-03-21 01:56:05 +01:00
pancake b7d3b44937 Refix pi/pI 2021-03-21 01:56:00 +01:00
pancake 596339f094 Fix pi/pI commands 2021-03-21 01:53:46 +01:00
pancake 3322a0bf72 Rebrand from ired to r0 2021-03-21 01:50:56 +01:00
pancake a1fa7904e6 Add more disassemblers and improve OpenWatcom support 2021-03-21 01:39:27 +01:00
pancake d8583f144c Add initial tiny x86 and arm disassemblers 2021-03-20 21:28:41 +01:00
pancake 2acde29402 Bring back the ftruncate 2020-10-05 10:25:49 +02:00
Roman Valls Guimera e5297647d4 Add script to build ired using the v850 toolchain
* Toolchain does not do ftruncate and friends. ired compiles now for v850, thx @trufae
2020-10-05 09:53:17 +02:00
pancake 921aabad60 Fix all the lgtm alerts 2019-05-28 17:41:29 +02:00
pancake b312fdcb30 Fix #3 - Add COPYING (MIT) 2019-01-05 13:37:19 +01:00
pancake 28ef01b9cd Fixes in vired for ish.app 2018-12-19 00:20:36 +01:00
pancake a1f06765a7 Add targets to build for thumb and arm for iOS 2018-04-10 13:18:23 +02:00
pancake 8603794279 Fix build for iOS 2018-04-10 13:11:28 +02:00
pancake bb011f88af Release 0.6 2016-12-12 00:22:39 +01:00
pancake c5498bd961 Add llvm bitcode build target 2015-06-19 10:13:03 +02:00
pancake a173daa812 Add -c and -q 2013-09-16 03:51:14 +02:00
pancake 9096ed5126 Add 'ired.js' target 2013-09-16 03:05:13 +02:00
pancake b074f2280d Initial import of calc.c . needs cleanup 2013-07-08 04:10:42 +02:00
pancake ec8e0225c3 Many bug fixes for vired. Added 'd' command to disassemble 2013-07-08 03:43:44 +02:00
pancake 2dca803f6d Release 0.5 - Fix minor C warning 2013-07-08 01:04:45 +02:00
pancake fba8f8e1a7 'make dist' uses git now 2013-06-10 02:01:56 +02:00
pancake afbe2e04f6 Fix write command 2013-05-17 18:24:06 +02:00
pancake 085b908d37 Initial support for return values in commands 2013-05-17 17:16:25 +02:00
pancake 4f1d810e98 Fix < command using io_seek 2013-05-17 14:26:25 +02:00
pancake bed1916abc Use markdown in readme and update copyleft timestamps 2013-02-18 17:33:19 +01:00
pancake 36e027fe48 Remove deprecated gitpush.sh 2012-06-29 00:57:11 +02:00
pancake 3fef4efbb5 Fix makefile dependencies and make tests work on osx 2012-06-29 00:50:55 +02:00
pancake 0e0f906f66 Still broken but a bit little fixed 2012-06-27 18:44:13 +02:00
pancake 5fee57d158 * Fix ired 2012-06-27 18:28:28 +02:00
pancake 75b31677e4 * fix -v output and free() warning 2012-03-07 11:56:37 +01:00
pancake 687644afdd * Fix make install when ired is running
* Minor fixes in README
2011-07-28 18:18:07 +02:00
pancake ac04c6e95e * Add initial gitpush script for github integration 2011-07-28 18:09:51 +02:00
pancake 204dbde78e * Properly fix all those signed/unsigned issues 2011-07-28 18:04:01 +02:00
pancake b6db2f859f * Fix search for bytes >0x7f. Thanks Dreyer! 2011-07-26 11:06:41 +02:00
pancake@dazo 6e0f3122b6 * Add patch from @jsegura fixing make clean 2010-09-22 19:51:20 +02:00
pancake@dazo 718330da85 * merge 2010-09-22 19:50:52 +02:00
pancake fca56e2c20 * Fix seeking on scripts 2010-07-22 14:49:36 +02:00
pancake@dazo 4d81079a14 * hexdump output is easily parseable
* Add hexparse.c
2010-06-14 00:45:16 +02:00
pancake@dazo 5a5595ced6 * Add missing TODO file 2010-05-12 10:05:06 +02:00
pancake@dazo f6a4705bf7 * Fix segfault when hexdumping -1 bytes 2010-05-12 10:00:07 +02:00
pancake@dazo b6649372ab * Various syntax fixes (like in suckless.org style)
* Update license headers (we are in 2010)
* Fix slurp in bdiff.c
2010-04-29 11:25:37 +02:00
pancake@flubox2 8bdc8dc92d * Merge heads 2010-02-09 17:33:55 +01:00
pancake@dazo 88c93994a0 * Initial import of 'bdiff'
* Added test suite for bdiff
* Looks like its buggy in some situations
2010-02-06 18:48:51 +01:00
pancake@dazo 0f9a7f7a1b * Added 'r+' command to resize file N bytes at curseek
* Increase the maximum length of input buffers
2010-02-06 14:02:06 +01:00
pancake@flubox 4ddf34f1f8 * Fix make dist for old versions of mercurial 2009-12-22 13:58:24 +01:00
pancake@flubox 6d744e39a7 * Bump revision to 0.5
* Default install directory is /usr/local
* Rename red.h to ired.h

--HG--
rename : red.h => ired.h
2009-12-22 13:56:01 +01:00
pancake@flubox 28d49ebd95 * Release ired 0.4
* Set PATH in vired to run it from current directory
2009-12-22 13:50:45 +01:00
[email protected] 4312ed31c8 * Updated manpages with documentation about environment
* Lot of small code cleanups (reduce code to 500LOC)
  - Sort include directives
  - Fix return value when file open fails
  - Reduce function exit points
  - More use of the ? operator
  - Bigger buffers for variables
* Add more checks in many places
  - Show errors when something is wrong
  - Check for negative values
  - Use ut8 and ut64 when possible
2009-10-07 02:48:18 +02:00
37 changed files with 10317 additions and 482 deletions

No files matched your search

+49
View File
@@ -0,0 +1,49 @@
name: ci
on:
push:
branches:
- master
pull_request:
jobs:
# build-windows:
# runs-on: windows-latest
# steps:
# - uses: actions/checkout@v2
# - name: Windows Dependencies
# run: pip install meson ninja
# - name: Building Sdb
# run: meson build && ninja -C build
# - name: Pub
# uses: actions/upload-artifact@v2
# with:
# path: build/*.exe
build-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Building
run: export CFLAGS="-Werror -Wall" && make
# - name: Packaging
# run: make -C dist/debian
- name: Running tests
run: make -C t
- name: Pub
uses: actions/upload-artifact@v2
with:
path: r0
build-macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: Building
run: make -j4
# - name: Packaging
# run: cd dist/macos && make && cd ../../..
- name: Running tests
run: make -C t
- name: Pub
uses: actions/upload-artifact@v2
with:
path: r0
+7
View File
@@ -0,0 +1,7 @@
Copyright 2019 pancake
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+95 -20
View File
@@ -1,38 +1,113 @@
-include config.mk
CC?=gcc
VERSION=0.9
CCw32?=i486-mingw32-gcc
CFLAGS+=-O2 -Wall
PREFIX?=/usr
CFLAGS+=-O0 -Wall -g
#CFLAGS+=-DVERSION=\"${VERSION}\"
PREFIX?=/usr/local
DESTDIR?=
all:
${CC} ${CFLAGS} ired.c -o ired
# ARCH: X32 X86 8086 ARM M68K
# ARCH=X32
# ARCH=X86
# ARCH=M68K
# ARCH=ARM
ARCH=NONE
all: r0 r0d
r0: r0.o
${CC} ${CFLAGS} r0.o -o r0
r0.o: calc.c cmd.c io.c util.c hexparse.c
$(CC) -c r0.c -DUSE_DISASM_$(ARCH)=1
r0d: r0d.o
${CC} ${CFLAGS} r0d.o -o r0d
r0.js:
emcc -s FORCE_FILESYSTEM=1 -lnodefs.js -s EXPORTED_FUNCTIONS='["_r0_open", "_r0_cmd"]' -DUSE_DISASM_X32=1 -Os -o r0.js r0.c
r0.arm:
$(CC) -DUSE_DISASM_ARM=1 r0.c -o r0.arm
r0.8086:
$(CC) -fsanitize=address -g -DUSE_DISASM_8086=1 r0.c -o r0.8086
r0.x86:
$(CC) -DUSE_DISASM_X32=1 -Os r0.c -o r0.x86
# $(CC) -fsanitize=address -g -DUSE_DISASM_X86=1 r0.c -o r0.x86
r0.com: # msdos
owcc -DUSE_DISASM_X32=1 r0.c -o r0.exe
r0.wasm:
emcc -Os -o r0.html r0.c
# https://github.com/bebbo/amiga-gcc
AMICC=/opt/amiga/bin/m68k-amigaos-gcc
AMICFLAGS=-Os -fomit-frame-pointer -msmall-code -m68000
AMICFLAGS+=-DUSE_DISASM_M68K=1 -DUSE_DISASM=1
r0.amiga ami:
rm -f r0.run
$(AMICC) $(AMICFLAGS) -mcrt=nix20 -o r0.run r0.c
lha c r0-nix20.lha r0.run
ami13:
rm -f r0.run
$(AMICC) $(AMICFLAGS) -DR0_NOENV=1 -DHAVE_FTRUNCATE=0 -mcrt=nix13 -o r0.run r0.c
lha c r0-nix13.lha r0.run
r0.bc:
clang -emit-llvm -o r0.bc -c r0.c
WASI_SDK=$(HOME)/Downloads/wasi/wasi-sdk-12.0
WASI_SYSROOT=$(HOME)/Downloads/wasi/wasi-sysroot
wasi:
export CC="$(WASI_SDK)/bin/clang --sysroot=$(WASI_SYSROOT) -DHAVE_SYSTEM=0" ; $(MAKE) clean ; $(MAKE)
mv r0 r0.wasm
dist:
if [ -z "${VERSION}" ]; then echo "make dist VERSION=0.3" ; exit 1 ; fi
mkdir -p ired-${VERSION}
cd ired-${VERSION} ; hg clone .. . ; rm -rf .hg
tar czvf ired-${VERSION}.tar.gz ired-${VERSION}
rm -rf ired-${VERSION}
@if [ -z "${VERSION}" ]; then echo "Try: make dist VERSION=0.5" ; exit 1 ; fi
git clone . r0-${VERSION}
rm -rf r0-${VERSION}/.git
tar czvf r0-${VERSION}.tar.gz r0-${VERSION}
rm -rf r0-${VERSION}
ios:
$(MAKE) CC="xcrun --sdk iphoneos gcc -arch arm64 -DHAVE_SYSTEM=0"
ios16:
$(MAKE) CC="xcrun --sdk iphoneos gcc -arch armv7 -mno-thumb -DHAVE_SYSTEM=0"
ios32:
$(MAKE) CC="xcrun --sdk iphoneos gcc -arch armv7 -DHAVE_SYSTEM=0"
w32:
${CCw32} ${CFLAGS} ired.c -o ired.exe
${CCw32} ${CFLAGS} r0.c -o r0.exe
v850:
./v850.sh
loc:
@wc -l *.c *.h | grep total
clean:
rm -f ired ired.o
rm -f r0 r0.o r0d r0d.o
rm -f r0.x86 r0.arm r0.wasm r0.js
install:
mkdir -p ${DESTDIR}${PREFIX}/bin
cp ired ${DESTDIR}${PREFIX}/bin
cp vired ${DESTDIR}${PREFIX}/bin
cp -f r0 ${DESTDIR}${PREFIX}/bin
cp -f r0d ${DESTDIR}${PREFIX}/bin
cp -f r0v ${DESTDIR}${PREFIX}/bin
mkdir -p ${DESTDIR}${PREFIX}/share/man/man1
cp ired.1 ${DESTDIR}${PREFIX}/share/man/man1
cp vired.1 ${DESTDIR}${PREFIX}/share/man/man1
cp -f r0.1 ${DESTDIR}${PREFIX}/share/man/man1
cp -f r0v.1 ${DESTDIR}${PREFIX}/share/man/man1
uninstall:
rm -f ${DESTDIR}${PREFIX}/bin/ired
rm -f ${DESTDIR}${PREFIX}/bin/vired
rm -f ${DESTDIR}${PREFIX}/share/man/man1/ired.1
rm -f ${DESTDIR}${PREFIX}/share/man/man1/vired.1
deinstall uninstall:
rm -f ${DESTDIR}${PREFIX}/bin/r0
rm -f ${DESTDIR}${PREFIX}/bin/r0v
rm -f ${DESTDIR}${PREFIX}/share/man/man1/r0.1
rm -f ${DESTDIR}${PREFIX}/share/man/man1/r0v.1
-44
View File
@@ -1,44 +0,0 @@
RED stands for the raw editor
============================= --pancake
red aims to be a minimalistic reimplementation of the radare shell
without much complexity and relaying all the extensibility to
external applications trying to keep the source as small as possible.
COMMANDS
========
? is for help get help or evaluate numeric expression
x hexdump hexdump
X dword dump hexpair dump
> file dump current block to file
< file slurp file into current block
w "string\x00" write string
w 023839400 write hexpairs
b 30 set block size
s addr seek address
r [size|-rmv] get filesize, truncate file to size, or -remove bytes
p [bwWdDqQiIF.] print formatted the current block
q quit
WORK IN PROGRESS
================
print command
b/w/d/q byte, word, dword, qword (little endian)
B/W/D/Q byte, word, dword, qword (big endian)
i/I/f/F int32 (lil, big), float (lil, big)
z/Z zero-terminatted strings (ascii, widechar)
./: skip 1 or 4 chars
* repeat last value until death
TODO:
=====
- support for escapped characters in string write and search ops
- Add support for simple math ops (+,-,*,/) no parenthesis plz :)
TODO/TOTHINK
============
- Remove '.' command? do it suckless
- Add .! command that runs !foo > file and then .file
- Support for multiple commands in a single line (';' separator)
+72
View File
@@ -0,0 +1,72 @@
# R0 stands for radare-zero
[![ci](https://github.com/radareorg/r0/actions/workflows/ci.yml/badge.svg)](https://github.com/radareorg/r0/actions/workflows/ci.yml)
r0 aims to be a minimalistic reimplementation of the radare shell
without much complexity and relaying all the extensibility to external
applications trying to keep the source as small as possible.
## Features
* Small footprint (50KB)
* Minimalistic Intel and ARM disassemblers (90KB)
* Minimum set of commands to inspect and manipulate binaries
* r0d does binary diffing and patching files
* r0v is the visual interactive frontend of r0
* Very portable: Compiles for wasm, js.. even for MS-DOS!
* Single binary without any external dependency
## AUTHOR
* pancake<nopcode.org>
## COMMANDS
```
[0x00000000]> ?
s[+-addr] seek to relative or absolute address
b[+-size] change block size
w[hex|"str"] write hexpair or string
/[hex|"str"] search hexpair or string
x[size] hexdump
d[size] disassemble n bytes
X[size] hexpair dump
p[fmt] print formatted current block ('p' for help)
d[size] disasemble
r[+-[num]] truncate or -remove N bytes
.[file] interpret file
<[file] load file in current seek
>[file] dump current block to file
!cmd run shell command
?expr calculate numeric expression
q quit
[0x00000000]>
```
WORK IN PROGRESS
================
print command
```
[0x00000000]> p?
ob/wW/dD/qQ byte (oct,hex), word, dword, qword (lil, big endian)
i/I/f/F int32 (lil, big), float (lil, big)
s/S short int16 (lil, big)
z/Z zero-terminatted string (ascii, wide-ascii)
./:/* skip 1 or 4 chars, repeat last format instead of cycle
```
PORTABILITY
===========
r0 is known to build and run on several OS.
- GNU/Hurd, Plan9, DOS, BSD, Solaris, Linux, macOS, Windows, Wasm, Javascript, ...
TODO:
=====
- support for escapped characters in string write and search ops
- Add support for simple math ops (+,-,*,/) no parenthesis plz :)
TODO/TOTHINK
============
- Remove '.' command? to make it suck less
- Add .! command that runs !foo > file and then .file
- Support for multiple commands in a single line (';' separator)
+13
View File
@@ -0,0 +1,13 @@
* We need a way to work with block based data like the 'wo' cmd in r1
* Implement formatted structs with named arguments in p command
* getcurblock can manage its own memory.. all those free's can be removed
* Find a way to return original value if str2ut64 fails (2nd arg..)
* Add math support to '?' command
* w<- should write from stdin
Commands can:
-1 - fail
0 - quit
1 - run fine
2 - run with issues
+334
View File
@@ -0,0 +1,334 @@
/* ported to C by pancake for r2 in 2012-2013 */
// TODO: integrate floating point support
// TODO: do not use global variables
/*
Reference Chapter 6:
"The C++ Programming Language", Special Edition.
Bjarne Stroustrup,Addison-Wesley Pub Co; 3 edition (February 15, 2000)
ISBN: 0201700735
*/
#include <ctype.h>
#include <stdio.h>
#include <unistd.h>
#define R_API
#define R_NUMCALC_STRSZ 4096
typedef struct {
double d;
ut64 n;
} RNumCalcValue;
typedef enum {
RNCNAME, RNCNUMBER, RNCEND, RNCINC, RNCDEC,
RNCPLUS='+', RNCMINUS='-', RNCMUL='*', RNCDIV='/',
//RNCXOR='^', RNCOR='|', RNCAND='&',
RNCPRINT=';', RNCASSIGN='=', RNCLEFTP='(', RNCRIGHTP=')'
} RNumCalcToken;
typedef struct r_num_calc_t {
RNumCalcToken curr_tok;
RNumCalcValue number_value;
char string_value[R_NUMCALC_STRSZ];
int errors;
char oc;
const char *calc_err;
int calc_i;
const char *calc_buf;
int calc_len;
} RNumCalc;
typedef struct r_num_t {
ut64 (*callback)(struct r_num_t *userptr, const char *str, int *ok);
// RNumCallback callback;
ut64 value;
double fvalue;
void *userptr;
RNumCalc nc;
} RNum;
/* accessors */
static inline RNumCalcValue Nset(ut64 v) { RNumCalcValue n; n.d = (double)v; n.n = v; return n; }
static inline RNumCalcValue Nsetf(double v) { RNumCalcValue n; n.d = v; n.n = (ut64)v; return n; }
static inline RNumCalcValue Naddf(RNumCalcValue n, double v) { n.d += v; n.n += (ut64)v; return n; }
static inline RNumCalcValue Naddi(RNumCalcValue n, ut64 v) { n.d += (double)v; n.n += v; return n; }
static inline RNumCalcValue Nsubi(RNumCalcValue n, ut64 v) { n.d -= (double)v; n.n -= v; return n; }
static inline RNumCalcValue Nadd(RNumCalcValue n, RNumCalcValue v) { n.d += v.d; n.n += v.n; return n; }
static inline RNumCalcValue Nsub(RNumCalcValue n, RNumCalcValue v) { n.d -= v.d; n.n -= v.n; return n; }
static inline RNumCalcValue Nmul(RNumCalcValue n, RNumCalcValue v) { n.d *= v.d; n.n *= v.n; return n; }
static inline RNumCalcValue Ndiv(RNumCalcValue n, RNumCalcValue v) {
if (v.d) n.d /= v.d; else n.d = 0;
if (v.n) n.n /= v.n; else n.n = 0;
return n;
}
static RNumCalcValue expr(RNum*, RNumCalc*, int);
static RNumCalcValue term(RNum*, RNumCalc*, int);
static void error(RNum*, RNumCalc*, const char *);
static RNumCalcValue prim(RNum*, RNumCalc*, int);
static RNumCalcToken get_token(RNum*, RNumCalc*);
static void error(RNum *num, RNumCalc *nc, const char *s) {
nc->errors++;
nc->calc_err = s;
//fprintf (stderr, "error: %s\n", s);
}
static RNumCalcValue expr(RNum *num, RNumCalc *nc, int get) {
RNumCalcValue left = term (num, nc, get);
for (;;) {
if (nc->curr_tok == RNCPLUS)
left = Nadd (left, term (num, nc, 1));
else if (nc->curr_tok == RNCMINUS)
left = Nsub (left, term (num, nc, 1));
else break;
}
return left;
}
static RNumCalcValue term(RNum *num, RNumCalc *nc, int get) {
RNumCalcValue left = prim (num, nc, get);
for (;;) {
if (nc->curr_tok == RNCMUL) {
left = Nmul (left, prim (num, nc, 1));
} else
if (nc->curr_tok == RNCDIV) {
RNumCalcValue d = prim (num, nc, 1);
if (!d.d) {
error (num, nc, "divide by 0");
return d;
}
left = Ndiv (left, d);
} else return left;
}
}
static RNumCalcValue prim(RNum *num, RNumCalc *nc, int get) {
char *p;
RNumCalcValue v = {0};
if (get) get_token (num, nc);
switch (nc->curr_tok) {
case RNCNUMBER:
v = nc->number_value;
get_token (num, nc);
return v;
case RNCNAME:
for(p=nc->string_value;*p&&*p==' ';p++) {};
v = Nset (str2ut64 (nc->string_value));
get_token (num, nc);
if (nc->curr_tok == RNCASSIGN)
v = expr (num, nc, 1);
if (nc->curr_tok == RNCINC) Naddi (v, 1);
if (nc->curr_tok == RNCDEC) Nsubi (v, 1);
return v;
case RNCINC: return Naddi (prim (num, nc, 1), 1);
case RNCDEC: return Naddi (prim (num, nc, 1), -1);
case RNCMINUS: return Nsub (v, prim (num, nc, 1));
case RNCLEFTP:
v = expr (num, nc, 1);
if (nc->curr_tok == RNCRIGHTP)
get_token (num, nc);
else error (num, nc, " ')' expected");
case RNCEND:
case RNCPLUS:
case RNCMUL:
case RNCDIV:
case RNCPRINT:
case RNCASSIGN:
case RNCRIGHTP:
return v;
//default: error (num, nc, "primary expected");
}
return v;
}
static void cin_putback (RNum *num, RNumCalc *nc, char c) {
nc->oc = c;
}
R_API const char *r_num_calc_index(RNum *num, const char *p) {
if (num == NULL)
return NULL;
if (p) {
num->nc.calc_buf = p;
num->nc.calc_len = strlen (p);
num->nc.calc_i = 0;
}
//if (num->nc.calc_i>num->nc.calc_len) return NULL;
return num->nc.calc_buf + num->nc.calc_i;
}
static int cin_get(RNumCalc *nc, char *c) {
if (nc->oc) {
*c = nc->oc;
nc->oc = 0;
} else {
if (!nc->calc_buf)
return 0;
//if (nc->calc_i>nc->calc_len) return 0;
*c = nc->calc_buf[nc->calc_i];
if (*c) nc->calc_i++;
else return 0;
}
return 1;
}
static int cin_get_num(RNum *num, RNumCalc *nc, RNumCalcValue *n) {
char c, str[R_NUMCALC_STRSZ];
double d;
int i = 0;
str[0] = 0;
while (cin_get (nc, &c)) {
if (c!=':' && c!='.' && !isalnum (c)) {
cin_putback (num, nc, c);
break;
}
if (i<R_NUMCALC_STRSZ)
str[i++] = c;
}
str[i] = 0;
*n = Nset (str2ut64 (str));
if (*str>='0' && *str<='9' && strchr (str, '.')) {
if (sscanf (str, "%lf", &d)<1)
return 0;
*n = Nsetf (d);
}
#if 0
// XXX: use r_num_get here
if (str[0]=='0' && str[1]=='x') {
ut64 x = 0;
if (sscanf (str+2, "%llx", &x)<1)
return 0;
*n = Nset (x);
} else
if (strchr (str, '.')) {
if (sscanf (str, "%lf", &d)<1)
return 0;
*n = Nsetf (d);
} else {
ut64 u;
if (sscanf (str, "%"PFMT64d, &u)<1)
return 0;
*n = Nset (u);
}
#endif
return 1;
}
static RNumCalcToken get_token(RNum *num, RNumCalc *nc) {
char ch = 0, c = 0;
do { if (!cin_get (nc, &ch)) return nc->curr_tok = RNCEND;
} while (ch!='\n' && isspace (ch));
switch (ch) {
case 0:
case ';':
case '\n':
return nc->curr_tok = RNCEND;
case '+': // added for ++name and name++
if (cin_get (nc, &c) && c == '+')
return nc->curr_tok = RNCINC;
cin_putback (num, nc, c);
return nc->curr_tok = (RNumCalcToken) ch;
case '-':
if (cin_get (nc, &c) && c == '-')
return nc->curr_tok = RNCDEC;
cin_putback (num, nc, c);
return nc->curr_tok = (RNumCalcToken) ch;
case '*':
case '/':
case '(':
case ')':
case '=':
return nc->curr_tok = (RNumCalcToken) ch;
case '0':case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '.':
cin_putback (num, nc, ch);
if (!cin_get_num (num, nc, &nc->number_value)) {
error (num, nc, "invalid number conversion");
return 1;
}
return nc->curr_tok = RNCNUMBER;
default:
#define isvalidchar(x) \
(isalnum(x) || x==':' || x=='$' || x=='.' || x=='_' || x=='?' || x=='\\' \
|| x==' ' || x=='[' || x==']' || x=='}' || x=='{' || x=='/' || (x>='0'&&x<='9'))
{
int i = 0;
nc->string_value[i++] = ch;
if (ch == '[') {
while (cin_get (nc, &ch) && ch!=']') {
if (i>=R_NUMCALC_STRSZ) {
error (num, nc, "string too long");
return 0;
}
nc->string_value[i++] = ch;
}
nc->string_value[i++] = ch;
} else {
while (cin_get (nc, &ch) && isvalidchar (ch)) {
if (i>=R_NUMCALC_STRSZ) {
error (num, nc, "string too long");
return 0;
}
nc->string_value[i++] = ch;
}
}
nc->string_value[i] = 0;
cin_putback (num, nc, ch);
return nc->curr_tok = RNCNAME;
}
//}
error (num, nc, "bad token");
return nc->curr_tok = RNCPRINT;
}
}
static void load_token(RNum *num, RNumCalc *nc, const char *s) {
nc->calc_i = 0;
nc->calc_len = 0;
nc->calc_buf = s;
nc->calc_err = NULL;
}
R_API ut64 r_num_calc(RNum *num, const char *str, const char **err) {
RNumCalcValue n;
RNumCalc *nc, nc_local;
if (!str || !*str)
return 0LL;
if (num == NULL)
nc = &nc_local;
else nc = &num->nc;
/* init */
nc->curr_tok = RNCPRINT;
nc->number_value.d = 0.0;
nc->number_value.n = 0LL;
nc->errors = 0;
nc->oc = 0;
nc->calc_err = NULL;
nc->calc_i = 0;
nc->calc_len = 0;
nc->calc_buf = NULL;
load_token (num, nc, str);
get_token (num, nc);
n = expr (num, nc, 0);
if (err) *err = nc->calc_err;
//if (nc->curr_tok == RNCEND) return 0LL; // XXX: Error
//if (nc->curr_tok == RNCPRINT) //return 0LL; // XXX: the fuck
// n = expr (num, nc, 0);
if (n.d != ((double)(ut64)n.d)) {
if (num) num->fvalue = n.d;
} else if (num) num->fvalue = (double)n.n;
return n.n;
}
R_API ut64 calc(const char *str) {
return r_num_calc (NULL, str, NULL);
}
+265 -133
View File
@@ -1,20 +1,46 @@
/* Copyleft 2009 -- pancake /at/ nopcode /dot/ org */
/* cmd.c - MIT - Copyright 2009-2023 -- pancake /at/ nopcode /dot/ org */
static void cmd_hexdump(char *arg) {
unsigned int len = bsize;
unsigned char *buf = getcurblk(arg, &len);
if (buf) {
#ifndef HAVE_SYSTEM
#define HAVE_SYSTEM 1
#endif
#define USE_DISASM 1
#if USE_DISASM_X86
#include "dis/x86.c"
#elif USE_DISASM_X32
#include "dis/x32.c"
#elif USE_DISASM_8086
#include "dis/8086.c"
#elif USE_DISASM_ARM
#include "dis/arm.c"
#elif USE_DISASM_M68K
// #define M68030 1
// #define M68020 1
// #define M68010 1
#include "dis/m68k.c"
#else
#undef USE_DISASM
#define USE_DISASM 0
#endif
static int cmd_hexdump(const char *arg) {
int len = bsize;
ut8 *buf = getcurblk(arg, &len);
if(buf && len>0) {
hexdump(buf, len, 16);
free(buf);
return 1;
}
return 2;
}
static void cmd_print(char *arg) {
unsigned char *buf;
unsigned int len = bsize;
if (*arg) {
static int cmd_print(const char *arg) {
ut8 *buf;
int len = bsize;
if(*arg) {
buf = getcurblk(arg, &len);
if (!buf) return;
if(!buf) return 2;
print_fmt(buf, arg, len);
free(buf);
} else printf(
@@ -23,167 +49,273 @@ static void cmd_print(char *arg) {
"s/S short int16 (lil, big)\n"
"z/Z zero-terminatted string (ascii, wide-ascii)\n"
"./:/* skip 1 or 4 chars, repeat last format instead of cycle\n");
return 1;
}
static void cmd_bytedump(char *arg) {
unsigned int i, len = bsize;
unsigned char *buf = getcurblk(arg, &len);
if (!buf) return;
static int cmd_system(const char *arg) {
int len = bsize;
char str[1024];
ut8 *buf;
if(strstr(arg, "BLOCK")) {
FILE *fd = fopen(".curblk", "wb");
if(fd) {
if((buf = getcurblk("", &len))) {
setenv("BLOCK", ".curblk", 1);
fwrite(buf, len, 1, fd);
free(buf);
}
fclose(fd);
}
}
if(strstr(arg, "BSIZE")) {
sprintf(str, "%d", len);
setenv("BSIZE", str, 1);
}
if(strstr(arg, "OFFSET")) {
sprintf(str, "%"LLF"d", curseek);
setenv("OFFSET", str, 1);
}
if(strstr(arg, "XOFFSET")) {
sprintf(str, "0x%"LLF"x", curseek);
setenv("XOFFSET", str, 1);
}
#if HAVE_SYSTEM
if(io_system(arg)<0)
perror("system");
#endif
unlink(".curblk");
return 1;
}
#if USE_DISASM
static int cmd_disasm(const char *arg) {
char output[256];
int i, j, len = bsize, ilen;
int pad = 8;
ut8 *buf = getcurblk(arg, &len);
if (!buf) {
return 2;
}
for(i = 0; i < len ;i++) {
*output = 0;
ilen = disasm(buf + i, len - i, curseek+i, output);
printf("0x%08"LLF"x ", curseek+i);
pad = 10;
if (ilen > 0) {
pad -= ilen;
for(j=i;j < i+ilen && j < len;j++)
printf("%02x", buf[j]);
i += ilen - 1;
if (pad > 0)
for (j = i; j< i+pad;j++)
printf(" ");
} else {
strcpy(output, "invalid");
}
printf("%s\n", output);
}
free(buf);
return 1;
}
#else
static int cmd_disasm(const char *arg) {
return cmd_system("echo X | r0 -n $BLOCK | rasm2 -o $OFFSET -D -"); // |head -n $(($LINES-1))");
}
#endif
static int cmd_bytedump(const char *arg) {
int i, len = bsize;
ut8 *buf = getcurblk(arg, &len);
if(!buf) return 2;
for(i=0;i<len;i++)
printf("%02x", buf[i]);
printf("\n");
free(buf);
return 1;
}
void cmd_search(char *arg) {
unsigned char *buf;
unsigned int i, len, hit=0;
arg = skipspaces(arg);
if (*arg=='"') {
static int cmd_search(const char *arg) {
ut8 *buf, *barg;
size_t len;
int i, hit = 0;
SKIPSPACES(arg);
if(*arg=='"') {
arg++;
len = strlen(arg)-1;
arg[len]='\0';
} else len = hexstr2raw(arg);
if ((buf = getcurblk("", &bsize)))
barg = (ut8*)strdup(arg);
len = strlen((const char *)barg)-1;
// TODO: ensure last char is '"'
barg[len]='\0';
} else {
barg = (ut8*)strdup(arg);
len = hexstr2raw(barg);
}
if((buf = getcurblk("", &bsize)))
do {
for(i=0;i<bsize;i++) {
if (arg[hit++]!=buf[i]) hit = 0;
else if (hit == len)
if(barg[hit++]!=buf[i]) hit = 0;
else if(hit == len)
printf("0x%"LLF"x\n", curseek+i-len+1);
}
curseek += bsize;
} while(io_read(buf, bsize)>0);
free(buf);
free(barg);
return 1;
}
static void cmd_bsize(char *arg) {
if (!*arg) printf("%d\n", bsize);
else if (*arg=='+') bsize += (int)str2ut64(arg+1);
else if (*arg=='-') bsize -= (int)str2ut64(arg+1);
else bsize = str2ut64(arg);
if (bsize<1) bsize = 1;
static int cmd_bsize(const char *arg) {
if(!*arg) printf("%d\n", bsize);
else if(*arg=='+') bsize += (int)calc(arg+1);
else if(*arg=='-') bsize -= (int)calc(arg+1);
else bsize = calc(arg);
if(bsize<1) bsize = 1;
obsize = bsize;
return 1;
}
static void cmd_seek(char *arg) {
if (!*arg) printf("%"LLF"d\n", curseek);
else if (*arg=='+') curseek += str2ut64(arg+1);
else if (*arg=='-') curseek -= str2ut64(arg+1);
else curseek = str2ut64(arg);
oldseek = curseek;
static int cmd_seek(const char *arg) {
if(!*arg) printf("%"LLF"d\n", curseek);
else if(*arg=='+') curseek += calc(arg+1);
else if(*arg=='-') curseek -= calc(arg+1);
else curseek = calc(arg);
io_seek((oldseek=curseek), 0);
return 1;
}
static void cmd_dump(char *file) {
unsigned int len = bsize;
void *buf = getcurblk("", &len);
FILE *fd = fopen(file, "wb");
if (fwrite(buf, len, 1, fd)<len)
perror("fwrite");
fclose(fd);
free(buf);
static int cmd_dump(const char *file) {
int len = bsize;
ut8 *buf = getcurblk("", &len);
if(len<1 || buf) {
FILE *fd = fopen(file, "wb");
if (!fd) {
free (buf);
return -1;
}
if(fwrite(buf, len, 1, fd)<len) {
perror("fwrite");
return -1;
}
fclose(fd);
free(buf);
} else perror("getcurblk");
return 1;
}
static void cmd_load(char *file) {
int len;
void *buf;
static int cmd_load(const char *file) {
FILE *fd = fopen(file, "rb");
if (!fd) return;
buf = malloc(bsize);
if (!buf) return;
len = fread(buf, 1, bsize, fd);
if (len<bsize)
perror("fread");
if (io_write(buf, len)<len)
perror("io_write");
fclose(fd);
free(buf);
if(fd) {
void *buf = malloc(bsize);
if(bsize>0 && buf) {
int len = fread(buf, 1, bsize, fd);
if(len<bsize)
perror("fread");
io_seek (curseek, SEEK_SET);
if(io_write(buf, len)<len) {
perror("io_write");
return -1;
}
} else perror("malloc");
free(buf);
fclose(fd);
} else perror("fopen");
return 1;
}
static void cmd_write(char *arg) {
unsigned int len;
arg = skipspaces(arg);
if (*arg=='"') {
arg++;
len = strlen(arg)-1;
arg[len]='\0';
} else len = hexstr2raw(arg);
static int cmd_write(const char *arg) {
ut8 *barg;
int len;
SKIPSPACES(arg);
if(*arg=='"') {
barg = (ut8*)strdup (arg+1);
len = strlen(++arg)-1;
// TODO: ensure last char is "
barg[len] = '\0';
} else {
barg = (ut8*)strdup (arg);
len = hexstr2raw(barg);
}
if (len<2) {
printf ("Invalid hexpair\n");
return 2;
}
io_seek(curseek, SEEK_SET);
if (io_write(arg, len)<len)
if(io_write(barg, len)<len) {
perror("io_write");
return -1;
}
//free ((void*)arg);
return 1;
}
static void cmd_help(char *arg) {
if (*arg) {
ut64 ret = str2ut64(arg);
static int cmd_help(const char *arg) {
if(*arg) {
ut64 ret = r_num_calc (NULL, arg, NULL);
printf("0x%"LLF"x %"LLF"d 0%"LLF"o\n", ret, ret, ret);
} else printf(
"s[+-addr] seek to relative or absolute address\n"
"b[+-size] change block size\n"
"w[hex|\"str\"] write hexpair or string\n"
"/[hex|\"str\"] search hexpair or string\n"
"x[size] hexdump\n"
"X[size] hexpair dump\n"
"p[fmt] print formatted current block ('p' for help)\n"
"r[-[num]] truncate or -remove N bytes\n"
".[file] interpret file\n"
"<[file] load file in current seek\n"
">[file] dump current block to file\n"
"!cmd run shell command\n"
"?expr calculate numeric expression\n"
"q quit\n");
"s[+-addr] seek to relative or absolute address\n"
"b[+-size] change block size\n"
"w[hex|\"str\"] write hexpair or string\n"
"/[hex|\"str\"] search hexpair or string\n"
"x[size] hexdump\n"
"d[size] disassemble n bytes\n"
"X[size] hexpair dump\n"
"p[fmt] print formatted current block ('p' for help)\n"
"d[size] disasemble\n"
"r[+-[num]] truncate or -remove N bytes\n"
".[file] interpret file\n"
"<[file] load file in current seek\n"
">[file] dump current block to file\n"
"!cmd run shell command\n"
"?expr calculate numeric expression\n"
"q quit\n");
return 1;
}
static void cmd_resize(char *arg) {
unsigned int len;
int ret = 0;
if (!*arg) printf("%"LLF"d\n", (long long int)io_seek(0, SEEK_END));
else if (*arg=='-') {
ut8 *buf = malloc(bsize);
if (buf) {
ut64 i, n = str2ut64(arg+1);
for(i=0;;i+=len) {
static int cmd_resize(const char *arg) {
ut8 *buf;
ut64 tail, n;
int i, len, ret = 0;
switch(*arg) {
case '\0':
printf("%"LLF"d\n", (ut64)io_seek(0, SEEK_END));
break;
case '+': // XXX: needs cleanup
n = calc(arg+1);
len = (ut64)io_seek(0, SEEK_END);
tail = len-curseek;
if((buf=malloc(tail))) { // XXX: Use block
io_seek(curseek, SEEK_SET);
i = io_read(buf, tail);
if (i > 0) {
io_seek(curseek+n, SEEK_SET);
if (io_write(buf, tail) < 1)
perror ("write");
free (buf);
}
} else perror("malloc");
break;
case '-':
buf = malloc(bsize);
if(buf) {
n = calc(arg+1);
for(i=0;!ret;i+=len) {
io_seek(curseek+n+i, SEEK_SET);
len = io_read(buf, bsize);
if (len<1) break;
io_seek(curseek+i, SEEK_SET);
if (io_write(buf, len)<len)
perror("io_write");
if((len = io_read(buf, bsize))>0) {
io_seek(curseek+i, SEEK_SET);
if(io_write(buf, len)<len)
perror("io_write"),ret=-1;
} else break; //perror("io_read"), ret=-1;
}
free(buf);
ret = io_truncate(io_seek(0, SEEK_END)-n);
}
} else ret = io_truncate(str2ut64(arg));
if (ret<0)
perror("truncate");
if((ret = io_seek(0, SEEK_END))>n)
ret = io_truncate(ret-n);
} else perror("malloc");
break;
default:
ret = io_truncate(calc(arg));
}
if(ret<0) perror("truncate");
return 1;
}
static void cmd_system(char *arg) {
unsigned int len = bsize;
char *buf = NULL, str[64];
if (strstr(arg, "BLOCK")) {
FILE *fd = fopen(".curblk", "w");
if (fd) {
buf = getcurblk("", &len);
if (buf) {
setenv("BLOCK", ".curblk", 1);
if (fwrite(buf, len, 1, fd)<len)
perror("fwrite");
fclose(fd);
free(buf);
buf = NULL;
}
}
}
if (strstr(arg, "OFFSET")) {
sprintf(str, "%"LLF"d", curseek);
setenv("OFFSET", str, 1); // XXX
}
if (strstr(arg, "XOFFSET")) {
sprintf(str, "0x%"LLF"x", curseek);
setenv("XOFFSET", str, 1); // XXX
}
if (io_system(arg)<0)
perror("system");
unlink(".curblk");
free(buf);
}
+2
View File
@@ -0,0 +1,2 @@
VERSION=@VERSION@
PREFIX=@PREFIX@
Vendored Executable
+382
View File
@@ -0,0 +1,382 @@
#!/bin/sh
# This script was automatically generated by ACR v2.1.2
# @author: pancake <nopcode.org>
# @url: http://www.nopcode.org
# @repo: git clone https://github.com/radare/acr
[ -z "${AWK}" ] && AWK=awk
do_remove() {
if [ "${ACR_RMFILES}" ]; then
printf "cleaning temporally files... "
rm -f ${ACR_RMFILES}
echo "done"
fi
}
control_c() {
printf "\n\n^C control-c : script execution interrupted.\n"
do_remove
exit 1
}
trap control_c 2
split_host() {
S="$"
while : ; do
ENVWORDS="${ENVWORDS} $1_CPU $1_OS"
STR=`eval "echo ${S}$1"`
SPLIT_CPU="`echo "$STR" | cut -d - -f 1`"
SPLIT_OS="`echo "$STR" | $AWK -F - '{
if ($2=="unknown"){
if (NF<3) { print $2; } else { print $3; }
} else {
if ($2=="linux") { print $2; } else
if (NF<3) { print $2; } else { print $3; }
}
}'`"
eval "$1_CPU=\"$SPLIT_CPU\""
eval "$1_OS=\"$SPLIT_OS\""
shift
[ -z "$1" ] && break
done
}
QUIET=0
be_quiet() {
QUIET=1
}
VPATH=`dirname ${0}`
if [ "${VPATH}" = "." ]; then
WODIS=current
else
if [ "${VPATH}" = "${PWD}" ]; then
VPATH=.
WODIS=current
else
WODIS=crosspath
CURDIR=$PWD
cd $VPATH
VPATH="${PWD}/"
cd $CURDIR
fi
fi
guess_os() {
if [ -e "${VPATH}/config.guess" ]; then
sh ${VPATH}/config.guess
return
fi
CPU="`uname -m|sed -e 's, ,,g'|cut -d - -f 1`"
OS="`uname -s|tr A-Z a-z`"
uname -r | grep -qE "(Microsoft|WSL)" 2>/dev/null && OS="wsl"
GNU="`uname --help 2>&1 | grep gnu`"
[ "${GNU}" ] && OS="${OS}-gnu"
[ "${CPU}" = ppc ] && CPU="powerpc"
echo "${CPU}-unknown-${OS}"
}
SEARCHPATH="/usr /usr/local /usr/pkg /sw"
: ${PREFIX:=/usr/local}
CROSSBUILD=0
BUILD=`guess_os`
HOST="${BUILD}"
TARGET="${HOST}"
ETCDIR="/etc"
SYSCONFDIR=""
DESCRIPTION=""
create_environ() {
: ${EPREFIX:="${PREFIX}"}
: ${SPREFIX:="${PREFIX}"}
: ${BINDIR:="${SPREFIX}/bin"}
: ${SBINDIR:="${PREFIX}/sbin"}
: ${ETCDIR:="${SPREFIX}/etc"}
: ${LIBDIR:="${SPREFIX}/lib"}
: ${PKGCFG_LIBDIR:='${exec_prefix}/lib'}
: ${PKGCFG_INCDIR:='${prefix}/include'}
: ${LIBEXECDIR:="${SPREFIX}/libexec"}
: ${INCLUDEDIR:="${SPREFIX}/include"}
: ${DATADIR:="${SPREFIX}/share"}
: ${INFODIR:="${DATADIR}/info"}
: ${MANDIR:="${DATADIR}/man"}
: ${DOCDIR:="${DATADIR}/doc/r0"}
: ${LOCALSTATEDIR:="${SPREFIX}/var"}
for A in `echo ${PATH} | sed -e 's,:, ,g'` ; do
[ -e "$A"/ginstall ] && : ${INSTALL:="$A"/ginstall} && break
[ -e "$A"/install ] && : ${INSTALL:="$A"/install} && break
done
: ${INSTALL_DIR:=${INSTALL} -d}
: ${INSTALL_DATA:=${INSTALL} -m 644}
: ${INSTALL_SCRIPT:=${INSTALL} -m 755}
: ${INSTALL_PROGRAM:=${INSTALL} -m 755}
: ${INSTALL_PROGRAM_STRIP:=${INSTALL} -m 755 -s}
: ${INSTALL_MAN:=${INSTALL} -m 444}
: ${INSTALL_LIB:=${INSTALL} -m 755 -c}
PKGNAME='r0' ; VERSION='0.9' ; VERSION_MAJOR=0; VERSION_MINOR=9; VERSION_PATCH=0; VERSION_NUMBER=00900; CONTACT_MAIL="[email protected]" ; CONTACT_NAME="pancake" ; CONTACT="pancake <[email protected]>" ;
}
show_usage() {
cat <<EOF2
'configure' configures r0-0.9 to adapt to many kinds of systems.
Usage: ./configure [OPTION]... [VAR=VALUE]...
To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE. See below for descriptions of some of the useful variables.
Defaults for the options are specified in brackets.
Configuration:
-h, --help display this help and exit
-r, --report show what libs/programs require to work
-q, --quiet be quiet, less verbose (see ./configure -qV)
-V, --version display version information and exit
Installation directories:
--exec-prefix=EPREFIX install arch-dependent files in EPREFIX [PREFIX]
--prefix=PREFIX install arch-independent files in PREFIX [/usr/local]
--sandbox=SPREFIX sandbox prefix directory: SPREFIX [PREFIX]
Fine tuning of the installation directories:
--bindir=DIR user executables [EPREFIX/bin]
--datadir=DIR read-only architecture-independent data [PREFIX/share]
--docdir=DIR documentation directory [DATADIR/doc/r0]
--includedir=DIR C header files [PREFIX/include]
--infodir=DIR info documentation [DATADIR/info]
--libexecdir=DIR program executables [EPREFIX/libexec]
--libdir=DIR object code libraries [EPREFIX/lib]
--libpath=DIR set rpath/libname-path to linker
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
--mandir=DIR man documentation [DATADIR/man]
--sbindir=DIR system admin executables [EPREFIX/sbin]
--etcdir=DIR same as --sysconfdir (/etc)
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
--target=TARGET configure for building compilers for TARGET [HOST]
EOF2
printf "
Some influential environment variables:
CC C compiler command
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
nonstandard directory <lib dir>
CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
headers in a nonstandard directory <include dir>
CPP C preprocessor
"
printf "
Report bugs to: pancake <[email protected]>"
echo ""
exit 0
}
take_environ() {
: ${SH:=/bin/sh}
: ${CPP:=cpp}
: ${CC:=gcc}
: ${PREFIX:=/usr/local/}
}
ochof() {
[ "$QUIET" = 1 ] && return
printf "$*"
}
ocho() {
[ "$QUIET" = 1 ] && return
echo "$*"
}
show_version() {
if [ "$QUIET" = 1 ]; then
echo "0.9"
exit 0
fi
echo "r0-0.9 configuration script done with acr v2.1.2.
The 'Free Software Foundation' message is only for autodetection.
Originally written by pancake <nopcode.org>."
exit 0
}
parse_options() {
flag=`echo $1| cut -d = -f 1`
value=`echo $1| $AWK 'BEGIN{FS="=";}{print $2}'`
flag2=`echo $flag|cut -f2- -d -| sed -e 's,-,_,g' -e 's,^_,,g'|tr '[a-z]' '[A-Z]'`
if [ "${TARGET_OS}" = "darwin" ]; then
LIBPATH=-Wl,-install_name,
else
LIBPATH=-Wl,-R
fi
case $flag in
-h|--help|--hel|--h|--he|-help)
show_usage ; ;;
-qV|-quiet-version|--quiet-version)
be_quiet
show_version ; ;;
-q|-quiet|--quiet)
be_quiet ; ;;
-V|-version|--version)
show_version ; ;;
-r|--r|--report)
echo "PKGNAME: r0"
echo "VERSION: 0.9"
echo "AUTHOR: pancake"
echo "EMAIL: [email protected]"
echo "LANGS: c"
exit 0
;;
--cache-file)
# ignored: acr have no cache
;;
--build)
BUILD="$value"; split_host BUILD ; ;;
--host)
CROSSBUILD=1 # XXX
HOST="$value"; split_host HOST ; ;;
--target)
TARGET="$value"; split_host TARGET ; ;;
--prefix)
PREFIX="$value"; ;;
--exec-prefix)
EPREFIX="$value"; ;;
--sandbox|--sprefix)
SPREFIX="$value"; ;;
--bindir)
BINDIR="$value"; ;;
--sbindir)
SBINDIR="$value"; ;;
--libexecdir)
LIBEXECDIR="$value"; ;;
--docdir)
DOCDIR="$value"; ;;
--datadir)
DATADIR="$value"; ;;
--sysconfdir)
SYSCONFDIR="$value"
ETCDIR="$value"; ;;
--etcdir)
SYSCONFDIR="$value"
ETCDIR="$value"; ;;
--sharedstatedir)
SHAREDSTATEDIR="$value"; ;;
--localstatedir)
LOCALSTATEDIR="$value"; ;;
--libdir)
LIBDIR="$value"
PKGCFG_LIBDIR="$value"; ;;
--libpath)
LDFLAGS="${LDFLAGS} ${LIBPATH}$value"; ;;
--includedir)
PKGCFG_INCDIR="$value"
INCLUDEDIR="$value"; CFLAGS="${CFLAGS} -I$value"; ;;
--infodir)
INFODIR="$value"; ;;
--mandir)
MANDIR="$value"; ;;
*) if [ "$value" ]; then eval "`echo $flag2=$value`" ;
else echo ; echo "WARNING: Unknown flag '$flag'." >&2 ; echo ; fi ;;
esac
}
# MAIN #
take_environ
split_host BUILD HOST TARGET
[ -z "$ACRHOOK" ] && ACRHOOK=./configure.hook
[ -e "$ACRHOOK" ] && . ${ACRHOOK}
while : ; do
[ -z "$1" ] && break
parse_options "$1"
shift
done
ENVWORDS="MANDIR DESCRIPTION INFODIR LIBDIR INCLUDEDIR LOCALSTATEDIR ETCDIR SYSCONFDIR DATADIR DOCDIR LIBEXECDIR SBINDIR BINDIR EPREFIX PREFIX SPREFIX TARGET HOST BUILD INSTALL INSTALL_LIB INSTALL_MAN INSTALL_PROGRAM INSTALL_PROGRAM_STRIP INSTALL_DIR INSTALL_SCRIPT INSTALL_DATA HOST_OS HOST_CPU BUILD_OS BUILD_CPU TARGET_OS TARGET_CPU VERSION VERSION_MAJOR VERSION_MINOR VERSION_PATCH VERSION_NUMBER PKGCFG_LIBDIR PKGCFG_INCDIR PKGNAME VPATH CONTACT CONTACT_NAME CONTACT_MAIL CC CFLAGS CPPFLAGS LDFLAGS HAVE_LANG_C"
create_environ
ocho "checking build system type... ${BUILD}"
ocho "checking host system type... ${HOST}"
ocho "checking target system type... ${TARGET}"
[ "${CROSSBUILD}" = 1 ] && echo "using crosscompilation mode."
#split_host BUILD HOST TARGET
[ -n "${prefix}" ] && PREFIX="${prefix}"
ocho "checking for working directories... ${WODIS}"
ocho "using prefix '${PREFIX}'"
ACR_RMFILES=" test.c a.out a.exe"
COMPILER=CC
ochof "checking for c compiler... "
HAVE_LANG_C=1
if [ "${CROSSBUILD}" = 1 ]; then
(command -v ${HOST}-${CC} >/dev/null 2>&1)
if [ $? = 0 ]; then CC="${HOST}-${CC}"; fi
fi
echo "int main(int argc, char **argv){return 0;}" > test.c
(exec ${CC} -o a.out ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} test.c >/dev/null 2>&1)
if [ $? = 0 ]; then echo ${CC}; else
echo no ; HAVE_LANG_C=0
do_remove
echo "ERROR: ${CC} cannot create executables" >&2 ;
exit 1 ; fi
SEDFLAGS=" -e '"
COUNT=0
for A in ${ENVWORDS} ; do
[ "${A}" = VPATH ] && continue
[ "${A}" = srcdir ] && continue
eval "VAR=\$${A}"
VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`"
[ $COUNT = 10 ] && COUNT=0 && SEDFLAGS="${SEDFLAGS}' -e '"
COUNT=$(($COUNT+1))
SEDFLAGS="${SEDFLAGS}s,@${A}@,${VAR},g;"
done
SEDFLAGS="${SEDFLAGS}'"
for A in config.mk ; do # SUBDIRS
if [ -f "${VPATH}/${A}.acr" ]; then
SD_TARGET=${A}
else
if [ -d "${VPATH}/${A}" ]; then
SD_TARGET=${A}/Makefile
mkdir -p ${A}
else
echo "ERROR: Cannot find ${VPATH}/${A}.acr" >&2
exit 1
fi
fi
ocho "creating ${SD_TARGET}"
[ "${VPATH}" != '.' ] && mkdir -p $(echo ${A} | sed -e "s,/`basename ${A}`$,,g")
cat ${VPATH}/${SD_TARGET}.acr | \
eval sed -e "s,@VPATH@,${VPATH}/${A},g" ${SEDFLAGS} > ${SD_TARGET}.tmp
for A in ${ENVWORDS}; do
VALUE=`eval echo "$"${A}`
if [ "$VALUE" = 0 ]; then ## FALSE
MARK="##${A}##"
if [ -n "`grep \"${MARK}\" ${SD_TARGET}.tmp`" ]; then
mv ${SD_TARGET}.tmp ${SD_TARGET}.tmp2
cat ${SD_TARGET}.tmp2 | MARK=$MARK $AWK 'BEGIN{a=0;}{if($1==ENVIRON["MARK"]){if(a)a=0;else a=1}else{if(!a)print;}}' > ${SD_TARGET}.tmp
fi
fi
done
mv ${SD_TARGET}.tmp ${SD_TARGET} && rm -f ${SD_TARGET}.tmp2
if [ ! $? = 0 ]; then echo Cannot write target file ; control_c ; fi
done
do_remove
if [ "$QUIET" = 0 ]; then
echo
echo "Final report:"
for A in VERSION PREFIX ; do
eval VAL="\$${A}"
[ -z "${VAL}" ] && VAL="\"\""
echo " - ${A} = ${VAL}"
done
fi
+10
View File
@@ -0,0 +1,10 @@
PKGNAME r0
VERSION 0.9
CONTACT pancake ; [email protected]
LANG_C!
SUBDIRS config.mk ;
REPORT VERSION PREFIX ;
+1189
View File
File diff suppressed because it is too large. Load diff
+491
View File
@@ -0,0 +1,491 @@
/* 2015 - tiny Thumb2 disassembler based on winedbg code */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARM_INSN_SIZE 4
#define THUMB_INSN_SIZE 2
#define THUMB2_INSN_SIZE 4
#define ROR32(n, r) (((n) >> (r)) | ((n) << (32 - (r))))
#define get_cond(ins) tbl_cond[(ins >> 28) & 0x0f]
#define get_nibble(ins, num) ((ins >> (num * 4)) & 0x0f)
struct thumb_disasm_t {
uint32_t pc;
const uint8_t *buf;
char str[32];
char hex[32];
uint32_t jmp, fail;
};
struct inst_thumb16 {
uint16_t mask;
uint16_t pattern;
uint16_t (*func)(struct thumb_disasm_t*, uint16_t);
};
struct inst_arm {
uint32_t mask;
uint32_t pattern;
uint32_t (*func)(struct thumb_disasm_t*, uint32_t);
};
static const char *tbl_regs[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
"fp", "ip", "sp", "lr", "pc", "cpsr"
};
static char const tbl_cond[][3] = {
"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", "hi", "ls", "ge",
"lt", "gt", "le", "", ""
};
static char const tbl_shifts[][4] = {
"lsl", "lsr", "asr", "ror"
};
static char const tbl_hiops_t[][4] = {
"add", "cmp", "mov", "bx"
};
static char const tbl_aluops_t[][4] = {
"and", "eor", "lsl", "lsr", "asr", "adc", "sbc", "ror", "tst", "neg",
"cmp", "cmn", "orr", "mul", "bic", "mvn"
};
static char const tbl_immops_t[][4] = {
"mov", "cmp", "add", "sub"
};
static char const tbl_sregops_t[][5] = {
"strh", "ldsb", "ldrh", "ldsh"
};
static uint32_t db_get_inst(const uint8_t* buf, int size) {
if (size == 4) return *(uint32_t*)buf;
if (size == 2) return (uint32_t)*(uint16_t*)buf;
return 0;
}
static uint16_t thumb_disasm_hireg(struct thumb_disasm_t *ai, uint16_t inst) {
short dst = inst & 0x07;
short src = (inst >> 3) & 0x07;
short h2 = (inst >> 6) & 0x01;
short h1 = (inst >> 7) & 0x01;
short op = (inst >> 8) & 0x03;
if (h1) dst += 8;
if (h2) src += 8;
if (op == 2 && dst == src) { /* mov rx, rx */
strcpy (ai->str, "nop");
return 0;
}
if (op == 3)
snprintf (ai->str, sizeof (ai->str), "b%sx %s", h1?"l":"", tbl_regs[src]);
else
snprintf (ai->str, sizeof (ai->str), "%s %s, %s", tbl_hiops_t[op], tbl_regs[dst], tbl_regs[src]);
return 0;
}
static uint16_t thumb_disasm_aluop(struct thumb_disasm_t *ai, uint16_t inst) {
short dst = inst & 0x07;
short src = (inst >> 3) & 0x07;
short op = (inst >> 6) & 0x0f;
snprintf (ai->str, sizeof (ai->str),
"%s %s, %s", tbl_aluops_t[op], tbl_regs[dst], tbl_regs[src]);
return 0;
}
// XXX possible overflow here? resize str plz
static uint16_t thumb_disasm_pushpop(struct thumb_disasm_t *ai, uint16_t inst) {
short lrpc = (inst >> 8) & 0x01;
short load = (inst >> 11) & 0x01;
short i;
short last;
for (i=7;i>=0;i--)
if ((inst>>i) & 1) break;
last = i;
strcpy (ai->str, load? "pop {": "push {");
for (i=0;i<=7;i++) {
if ((inst>>i) & 1) {
if (i == last) strcat (ai->str, tbl_regs[i]); // overflow ??
else strcat (ai->str, tbl_regs[i]);
}
}
if (lrpc) {
if (last) strcat (ai->str, ", ");
strcat (ai->str, load? "pc": "lr");
}
strcat (ai->str, "}");
return 0;
}
static uint16_t thumb_disasm_blocktrans(struct thumb_disasm_t *ai, uint16_t inst) {
short load = (inst >> 11) & 0x01;
short i;
short last;
for (i=7;i>=0;i--)
if ((inst>>i) & 1) break;
last = i;
snprintf (ai->str, sizeof (ai->str),
"%s %s!, {", load ? "ldmia" : "stmia", tbl_regs[(inst >> 8) & 0x07]);
for (i=0;i<=7;i++) {
if ((inst>>i) & 1) {
strcat (ai->str, tbl_regs[i]);
if (i != last) {
strcat (ai->str, ", ");
}
}
}
strcat (ai->str, "}");
return 0;
}
static uint16_t thumb_disasm_condbranch(struct thumb_disasm_t *ai, uint16_t inst) {
uint16_t offset = inst & 0x00ff;
snprintf (ai->str, sizeof (ai->str),
"b%s 0x%x", tbl_cond[(inst >> 8) & 0x0f], ai->pc+offset);
ai->jmp = ai->pc + offset;
ai->fail = ai->pc + 4;
return 0;
}
static uint16_t thumb_disasm_uncondbranch(struct thumb_disasm_t *ai, uint16_t inst) {
short offset = (inst & 0x07ff) << 1;
if (offset & 0x0800) offset |= 0xf000;
offset += 4;
snprintf (ai->str, sizeof (ai->str), "b 0x%x", ai->pc+offset);
ai->jmp = ai->pc+offset;
return 0;
}
static uint16_t thumb_disasm_loadadr(struct thumb_disasm_t *ai, uint16_t inst) {
uint16_t src = (inst >> 11) & 0x01;
uint16_t offset = (inst & 0xff) << 2;
snprintf (ai->str, sizeof (ai->str),
"add %s, %s, #%d", tbl_regs[(inst >> 8) & 0x07], src ? "sp" : "pc",
offset);
return 0;
}
static uint16_t thumb_disasm_swi(struct thumb_disasm_t *ai, uint16_t inst) {
uint16_t comment = inst & 0x00ff;
snprintf (ai->str, sizeof (ai->str), "swi #%d", comment);
return 0;
}
static uint16_t thumb_disasm_nop(struct thumb_disasm_t *ai, uint16_t inst) {
strcpy (ai->str, "nop");
return 0;
}
static uint16_t thumb_disasm_ldrpcrel(struct thumb_disasm_t *ai, uint16_t inst) {
uint16_t offset = (inst & 0xff) << 2;
snprintf (ai->str, sizeof (ai->str),
"ldr %s, [pc, #%u]", tbl_regs[(inst >> 8) & 0x07], offset);
return 0;
}
static uint16_t thumb_disasm_ldrsprel(struct thumb_disasm_t *ai, uint16_t inst) {
uint16_t offset = (inst & 0xff) << 2;
snprintf (ai->str, sizeof (ai->str),
"%s %s, [sp, #%u]", (inst & 0x0800)?"ldr":"str",
tbl_regs[(inst >> 8) & 0x07], offset);
return 0;
}
static uint16_t thumb_disasm_addsprel(struct thumb_disasm_t *ai, uint16_t inst) {
uint16_t offset = (inst & 0x7f) << 2;
int sub = ((inst >> 7) & 0x01);
snprintf (ai->str, sizeof (ai->str),
"%s sp, sp, #%u", sub? "sub": "add", offset);
return 0;
}
static uint16_t thumb_disasm_ldrimm(struct thumb_disasm_t *ai, uint16_t inst) {
uint16_t offset = (inst & 0x07c0) >> 6;
snprintf (ai->str, sizeof (ai->str), "%s%s %s, [%s, #%u]",
(inst & 0x0800)?"ldr":"str", (inst & 0x1000)?"b":"",
tbl_regs[inst & 0x07], tbl_regs[(inst >> 3) & 0x07],
(inst & 0x1000)?offset:(offset << 2));
return 0;
}
static uint16_t thumb_disasm_ldrhimm(struct thumb_disasm_t *ai, uint16_t inst) {
uint16_t offset = (inst & 0x07c0) >> 5;
snprintf (ai->str, sizeof (ai->str), "%s %s, [%s, #%u]", (inst & 0x0800)?"ldrh":"strh",
tbl_regs[inst & 0x07], tbl_regs[(inst >> 3) & 0x07], offset);
return 0;
}
static uint16_t thumb_disasm_ldrreg(struct thumb_disasm_t *ai, uint16_t inst) {
snprintf (ai->str, sizeof (ai->str), "%s%s %s, [%s, %s]",
(inst & 0x0800)?"ldr":"str", (inst & 0x0400)?"b":"",
tbl_regs[inst & 0x07], tbl_regs[(inst >> 3) & 0x07],
tbl_regs[(inst >> 6) & 0x07]);
return 0;
}
static uint16_t thumb_disasm_ldrsreg(struct thumb_disasm_t *ai, uint16_t inst) {
snprintf (ai->str, sizeof (ai->str), "%s %s, [%s, %s]",
tbl_sregops_t[(inst >> 10) & 0x03], tbl_regs[inst & 0x07],
tbl_regs[(inst >> 3) & 0x07], tbl_regs[(inst >> 6) & 0x07]);
return 0;
}
static uint16_t thumb_disasm_immop(struct thumb_disasm_t *ai, uint16_t inst) {
uint16_t op = (inst >> 11) & 0x03;
snprintf (ai->str, sizeof (ai->str),
"%s %s, #%u", tbl_immops_t[op], tbl_regs[(inst >> 8) & 0x07], inst & 0xff);
return 0;
}
static uint16_t thumb_disasm_addsub(struct thumb_disasm_t *ai, uint16_t inst) {
char last [32];
uint16_t op = (inst >> 9) & 0x01;
uint16_t immediate = (inst >> 10) & 0x01;
if (immediate) snprintf (last, sizeof (last), "#%d", (inst >> 6) & 0x07);
else strcpy (last, tbl_regs[(inst >> 6) & 0x07]);
snprintf (ai->str, sizeof (ai->str),
"%s %s, %s, %s", op ? "sub" : "add",
tbl_regs[inst & 0x07], tbl_regs[(inst >> 3) & 0x07], last);
return 0;
}
static uint16_t thumb_disasm_movshift(struct thumb_disasm_t *ai, uint16_t inst) {
uint16_t op = (inst >> 11) & 0x03;
snprintf (ai->str, sizeof (ai->str),
"%s %s, %s, #%u", tbl_shifts[op],
tbl_regs[inst & 0x07], tbl_regs[(inst >> 3) & 0x07], (inst >> 6) & 0x1f);
return 0;
}
static uint32_t thumb2_disasm_branchlinked(struct thumb_disasm_t *ai, uint32_t inst) {
uint32_t offset = (((inst & 0x07ff0000) >> 4) | ((inst & 0x000007ff) << 1)) + 4;
snprintf (ai->str, sizeof (ai->str), "bl 0x%x", ai->pc+offset);
ai->jmp = ai->pc+offset;
return 0;
}
static uint32_t thumb2_disasm_misc(struct thumb_disasm_t *ai, uint32_t inst) {
uint16_t op1 = (inst >> 20) & 0x03;
uint16_t op2 = (inst >> 4) & 0x03;
if (get_nibble(inst, 4) != get_nibble(inst, 0))
return inst;
if (op1 == 3 && op2 == 0) {
snprintf (ai->str, sizeof (ai->str),
"clz %s, %s ", tbl_regs[get_nibble(inst, 2)],
tbl_regs[get_nibble(inst, 0)]);
return 0;
}
if (op1 == 1) {
const char *op = "";
switch (op2) {
case 0: op = "rev "; break;
case 1: op = "rev16 "; break;
case 2: op = "rbit "; break;
case 3: op = "revsh "; break;
}
snprintf (ai->str, sizeof (ai->str),
"%s %s, %s ", op, tbl_regs[get_nibble(inst, 2)], tbl_regs[get_nibble(inst, 0)]);
return 0;
}
return inst;
}
static uint32_t thumb2_disasm_mul(struct thumb_disasm_t *ai, uint32_t inst) {
uint16_t op1 = (inst >> 20) & 0x07;
uint16_t op2 = (inst >> 4) & 0x03;
if (op1)
return inst;
if (op2 == 0) {
uint16_t nib = get_nibble (inst, 3);
if (nib == 0xf) {
snprintf (ai->str, sizeof (ai->str),
"mul %s, %s, %s ", tbl_regs[get_nibble(inst, 2)],
tbl_regs[get_nibble(inst, 4)],
tbl_regs[get_nibble(inst, 0)]);
} else {
snprintf (ai->str, sizeof (ai->str),
"mla %s, %s, %s, %s ", tbl_regs[get_nibble(inst, 2)],
tbl_regs[get_nibble(inst, 4)],
tbl_regs[get_nibble(inst, 0)],
tbl_regs[get_nibble(inst, 3)]);
}
return 0;
}
if (op2 == 1) {
snprintf (ai->str, sizeof (ai->str),
"mls %s, %s, %s, %s ", tbl_regs[get_nibble(inst, 2)],
tbl_regs[get_nibble(inst, 4)],
tbl_regs[get_nibble(inst, 0)],
tbl_regs[get_nibble(inst, 3)]);
return 0;
}
return inst;
}
static uint32_t thumb2_disasm_longmuldiv(struct thumb_disasm_t *ai, uint32_t inst) {
const char *op = "";
uint16_t op1 = (inst >> 20) & 0x07;
uint16_t op2 = (inst >> 4) & 0x0f;
if (op2 == 0) {
switch (op1) {
case 0: op = "smull "; break;
case 2: op = "umull "; break;
case 4: op = "smlal "; break;
case 6: op = "umlal "; break;
default: return inst;
}
snprintf (ai->str, sizeof (ai->str), "%s%s, %s, %s, %s ", op,
tbl_regs[get_nibble(inst, 3)], tbl_regs[get_nibble(inst, 2)],
tbl_regs[get_nibble(inst, 4)], tbl_regs[get_nibble(inst, 0)]);
return 0;
}
if (op2 == 0xffff) {
switch (op1) {
case 1: op = "sdiv "; break;
case 3: op = "udiv "; break;
default: return inst;
}
snprintf (ai->str, sizeof (ai->str), "%s%s, %s, %s ", op,
tbl_regs[get_nibble(inst, 2)], tbl_regs[get_nibble(inst, 4)],
tbl_regs[get_nibble(inst, 0)]);
return 0;
}
return inst;
}
static uint32_t thumb2_disasm_coprocmov1(struct thumb_disasm_t *ai, uint32_t inst) {
uint16_t opc1 = (inst >> 21) & 0x07;
uint16_t opc2 = (inst >> 5) & 0x07;
char last[32];
if (opc2) snprintf (last, sizeof (last), ", #%u", opc2); else *last = 0;
snprintf (ai->str, sizeof (ai->str),
"%s%s p%u, #%u, %s, cr%u, cr%u%s", (inst & 0x00100000)?"mrc":"mcr",
(inst & 0x10000000)?"2":"", get_nibble(inst, 2), opc1,
tbl_regs[get_nibble(inst, 3)], get_nibble(inst, 4), get_nibble(inst, 0), last);
return 0;
}
static const struct inst_thumb16 tbl_thumb16[] = {
{ 0xfc00, 0x4400, thumb_disasm_hireg },
{ 0xfc00, 0x4000, thumb_disasm_aluop },
{ 0xf600, 0xb400, thumb_disasm_pushpop },
{ 0xf000, 0xc000, thumb_disasm_blocktrans },
{ 0xf000, 0xd000, thumb_disasm_condbranch },
{ 0xf800, 0xe000, thumb_disasm_uncondbranch },
{ 0xf000, 0xa000, thumb_disasm_loadadr },
{ 0xf800, 0x4800, thumb_disasm_ldrpcrel },
{ 0xf000, 0x9000, thumb_disasm_ldrsprel },
{ 0xff00, 0xb000, thumb_disasm_addsprel },
{ 0xe000, 0x6000, thumb_disasm_ldrimm },
{ 0xf000, 0x8000, thumb_disasm_ldrhimm },
{ 0xf200, 0x5000, thumb_disasm_ldrreg },
{ 0xf200, 0x5200, thumb_disasm_ldrsreg },
{ 0xe000, 0x2000, thumb_disasm_immop },
{ 0xff00, 0xdf00, thumb_disasm_swi },
{ 0xff00, 0xbf00, thumb_disasm_nop },
{ 0xf800, 0x1800, thumb_disasm_addsub },
{ 0xe000, 0x0000, thumb_disasm_movshift },
{ 0x0000, 0x0000, NULL }
};
static const struct inst_arm tbl_thumb32[] = {
{ 0xf800f800, 0xf000f800, thumb2_disasm_branchlinked },
{ 0xffc0f0c0, 0xfa80f080, thumb2_disasm_misc },
{ 0xff8000c0, 0xfb000000, thumb2_disasm_mul },
{ 0xff8000f0, 0xfb800000, thumb2_disasm_longmuldiv },
{ 0xff8000f0, 0xfb8000f0, thumb2_disasm_longmuldiv },
{ 0xef100010, 0xee100010, thumb2_disasm_coprocmov1 },
{ 0xef100010, 0xee000010, thumb2_disasm_coprocmov1 },
{ 0x00000000, 0x00000000, NULL }
};
int thumb_disasm(struct thumb_disasm_t *ai) {
struct inst_thumb16 *t_ptr = (struct inst_thumb16 *)&tbl_thumb16;
struct inst_arm *t2_ptr = (struct inst_arm *)&tbl_thumb32;
uint32_t inst;
uint16_t tinst;
int size;
int matched = 0;
ai->jmp = ai->fail = -1;
tinst = db_get_inst(ai->buf, THUMB_INSN_SIZE);
switch (tinst & 0xf800) {
case 0xe800:
case 0xf000:
case 0xf800:
size = THUMB2_INSN_SIZE;
inst = db_get_inst(ai->buf+1, THUMB_INSN_SIZE);
inst |= (tinst << 16);
while (t2_ptr->func) {
if ((inst & t2_ptr->mask) == t2_ptr->pattern) {
matched = 1;
break;
}
t2_ptr++;
}
if (!matched) strcpy (ai->str, "invalid"); // thumb2
else t2_ptr->func (ai, inst);
snprintf (ai->hex, sizeof (ai->hex), "%02x%02x%02x%02x",
*((uint8_t*)(&inst)), *((uint8_t*)(&inst)+1),
*((uint8_t*)(&inst)+2), *((uint8_t*)(&inst)+3));
return size;
default:
break;
}
size = THUMB_INSN_SIZE;
while (t_ptr->func) {
if ((tinst & t_ptr->mask) == t_ptr->pattern) {
matched = 1;
break;
}
t_ptr++;
}
if (!matched) snprintf (ai->str, sizeof (ai->str), "0x%04x", tinst);
else t_ptr->func(ai, tinst);
snprintf (ai->hex, sizeof (ai->hex), "%02x%02x", *((uint8_t*)(&tinst)), *((uint8_t*)(&tinst)+1));
return size;
}
unsigned int disasm(const unsigned char *bytes, unsigned int max, int offset, char *output) {
int len;
struct thumb_disasm_t dis;
dis.pc = offset;
dis.buf = bytes;
len = thumb_disasm (&dis);
if (len > 0) {
strcpy (output, dis.str);
}
return len;
}
+3076
View File
File diff suppressed because it is too large. Load diff
+2547
View File
File diff suppressed because it is too large. Load diff
+148
View File
@@ -0,0 +1,148 @@
#ifndef __X86_INSTR_H
#define __X86_INSTR_H
enum argtype {
NONE = 0,
/* the literal value 1, used for bit shift ops */
ONE,
/* specific registers */
AL, CL, DL, BL, AH, CH, DH, BH,
AX, CX, DX, BX, SP, BP, SI, DI,
ES, CS, SS, DS, FS, GS,
ALS, AXS, /* the same as AL/AX except MASM doesn't print them */
DXS, /* the same as DX except GAS puts it in parentheses */
/* absolute or relative numbers, given as 1/2/4 bytes */
IMM8, IMM16, IMM, /* immediate number */
REL8, REL16, /* relative to current instruction */
PTR32, /* absolute instruction, used for far calls/jumps */
MOFFS16, /* absolute location in memory, for A0-A3 MOV */
/* specific memory addresses for string operations */
DSBX, DSSI, ESDI,
/* to be read from ModRM, appropriately */
RM, /* register/memory */
MM, /* MMX register/memory */
XM, /* SSE register/memory */
MEM, /* memory only (using 0x11xxxxxx is invalid) */
REGONLY, /* register only (not using 0x11xxxxxx is invalid) */
MMXONLY, /* MMX register only (not using 0x11xxxxxx is invalid) */
XMMONLY, /* SSE register only (not using 0x11xxxxxx is invalid) */
REG, /* register */
MMX, /* MMX register */
XMM, /* SSE register */
SEG16, /* segment register */
REG32, /* 32-bit only register, used for cr/dr/tr */
CR32, /* control register */
DR32, /* debug register */
TR32, /* test register */
/* floating point regs */
ST, /* top of stack aka st(0) */
STX, /* element of stack given by lowest three bytes of "modrm" */
};
/* opcode flags */
#define OP_ARG2_IMM 0x0001 /* has IMM16/32 as third argument */
#define OP_ARG2_IMM8 0x0002 /* has IMM8 as third argument */
#define OP_ARG2_CL 0x0004 /* has CL as third argument */
#define OP_64 0x0008 /* opcodes which are 64-bit by default (call, jmp), most being 32-bit */
#define OP_REPNE 0x0010 /* repne prefix valid */
#define OP_REPE 0x0020 /* repe prefix valid */
#define OP_REP OP_REPE /* rep prefix valid */
#define OP_OP32_REGONLY 0x0040 /* operand-size prefix only valid if used with reg */
#define OP_LOCK 0x0080 /* lock prefix valid */
#define OP_STACK 0x0100 /* only marked for size if overridden */
#define OP_STRING 0x0200 /* string operations */
#define OP_FAR 0x0400 /* far operation */
#define OP_IMM64 0x0800 /* IMM argument can be 64-bit */
#define OP_S 0x1000 /* (FPU) op takes -s if GCC */
#define OP_L 0x2000 /* (FPU) op takes -l if GCC */
#define OP_LL 0x3000 /* (FPU) op takes -ll if GCC */
/* -t doesn't need to be marked */
#define OP_STOP 0x4000 /* stop scanning (jmp, ret) */
#define OP_BRANCH 0x8000 /* branch to target (jmp, jXX) */
struct op {
word opcode;
byte subcode;
signed char size; /* 0 if not sized, -1 if size == bitness */
char name[16];
enum argtype arg0; /* usually dest */
enum argtype arg1; /* usually src */
/* arg2 only for imul, shrd, shld */
dword flags;
};
#define PREFIX_ES 0x0001 /* 26 */
#define PREFIX_CS 0x0002 /* 2E */
#define PREFIX_SS 0x0003 /* 36 */
#define PREFIX_DS 0x0004 /* 3E */
#define PREFIX_FS 0x0005 /* 64 */
#define PREFIX_GS 0x0006 /* 65 */
#define PREFIX_SEG_MASK 0x0007
#define PREFIX_OP32 0x0008 /* 66 */
#define PREFIX_ADDR32 0x0010 /* 67 */
#define PREFIX_LOCK 0x0020 /* F0 */
#define PREFIX_REPNE 0x0040 /* F2 */
#define PREFIX_REPE 0x0080 /* F3 */
#define PREFIX_WAIT 0x0100 /* 9B */
#define PREFIX_REX 0x0800 /* 40 */
#define PREFIX_REXB 0x1000 /* 41 */
#define PREFIX_REXX 0x2000 /* 42 */
#define PREFIX_REXR 0x4000 /* 44 */
#define PREFIX_REXW 0x8000 /* 48 */
enum disptype {
DISP_NONE = 0, /* no disp, i.e. mod == 0 && m != 6 */
DISP_8 = 1, /* one byte */
DISP_16 = 2, /* two bytes */
DISP_REG = 3, /* register, i.e. mod == 3 */
};
struct arg {
char string[32];
dword ip;
qword value;
enum argtype type;
};
struct instr {
word prefix;
struct op op;
struct arg args[3];
byte addrsize;
enum disptype modrm_disp;
int8_t modrm_reg; /* This is a little ugly, but 16 is IP and -1 is none (aka IZ). */
byte sib_scale;
signed char sib_index;
int usedmem:1; /* used for error checking */
int vex:1;
unsigned int vex_reg:3;
int vex_256:1;
};
/* 66 + 67 + seg + lock/rep + 2 bytes opcode + modrm + sib + 4 bytes displacement + 4 bytes immediate */
#define MAX_INSTR 16
/* flags relating to specific instructions */
#define INSTR_SCANNED 0x01 /* byte has been scanned */
#define INSTR_VALID 0x02 /* byte begins an instruction */
#define INSTR_JUMP 0x04 /* instruction is jumped to */
#define INSTR_FUNC 0x08 /* instruction begins a function */
#define INSTR_FAR 0x10 /* instruction is target of far call/jmp */
#define INSTR_RELOC 0x20 /* byte has relocation data */
#endif /* __X86_INSTR_H */
+762
View File
@@ -0,0 +1,762 @@
// https://github.com/btbd/disassembler
#if defined(__WATCOMC__)
#define HUGE huge
#else
#define HUGE
#endif
static char register_mnemonics8[][0xF] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" };
static char register_mnemonics16[][0xF] = { "ax", "cx", "dx", "bx", "ax", "cx", "dx", "bx" };
static char register_mnemonics32[][0xF] = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" };
static char sib_base_mnemonics[][0xF] = { "[eax", "[ecx", "[edx", "[ebx", "[esp", "[ebp", "[esi", "[edi" };
static char sib_scale_mnemonics[][0xF] = { "*1", "*2", "*4", "*8" };
enum {
AL, EAX, ES, CS, SS, DS, ONE, CL, XMM0, BND0, BAD, MM0,
IMM8, IMM16, IMM32, REL8, REL16, REL32, PTR1632, R, RM,
BYTE, WORD, DWORD, QWORD, FWORD, XMMWORD
};
typedef struct {
char hasModRM, size;
char mnemonic[64];
char argument_count;
char arguments[4];
} INSTRUCTION;
static INSTRUCTION HUGE standard_instructions[256] = {
{ 1, BYTE, "add ", 2, RM, R }, // 0
{ 1, DWORD, "add ", 2, RM, R }, // 1
{ 1, BYTE, "add ", 2, R, RM }, // 2
{ 1, DWORD, "add ", 2, R, RM }, // 3
{ 0, 0, "add ", 2, AL, IMM8 }, // 4
{ 0, 0, "add ", 2, EAX, IMM32 }, // 5
{ 0, 0, "push es", 0 }, // 6
{ 0, 0, "pop es", 0 }, // 7
{ 1, BYTE, "or ", 2, RM, R }, // 8
{ 1, DWORD, "or ", 2, RM, R }, // 9
{ 1, BYTE, "or ", 2, R, RM }, // A
{ 1, DWORD, "or ", 2, R, RM }, // B
{ 0, 0, "or ", 2, AL, IMM8 }, // C
{ 0, 0, "or ", 2, EAX, IMM32 }, // D
{ 0, 0, "push cs", 0 }, // E
{ 0 }, // F - Two-byte instructions
{ 1, BYTE, "adc ", 2, RM, R }, // 10
{ 1, DWORD, "adc ", 2, RM, R }, // 11
{ 1, BYTE, "adc ", 2, R, RM }, // 12
{ 1, DWORD, "adc ", 2, R, RM }, // 13
{ 0, 0, "adc ", 2, AL, IMM8 }, // 14
{ 0, 0, "adc ", 2, EAX, IMM32 }, // 15
{ 0, 0, "push ss", 0 }, // 16
{ 0, 0, "pop ss", 0 }, // 17
{ 1, BYTE, "sbb ", 2, RM, R }, // 18
{ 1, DWORD, "sbb ", 2, RM, R }, // 19
{ 1, BYTE, "sbb ", 2, R, RM }, // 1A
{ 1, DWORD, "sbb ", 2, R, RM }, // 1B
{ 0, 0, "sbb ", 2, AL, IMM8 }, // 1C
{ 0, 0, "sbb ", 2, EAX, IMM32 }, // 1D
{ 0, 0, "push ds", 0 }, // 1E
{ 0, 0, "pop ds", 0 }, // 1F
{ 1, BYTE, "and ", 2, RM, R }, // 20
{ 1, DWORD, "and ", 2, RM, R }, // 21
{ 1, BYTE, "and ", 2, R, RM }, // 22
{ 1, DWORD, "and ", 2, R, RM }, // 23
{ 0, 0, "and ", 2, AL, IMM8 }, // 24
{ 0, 0, "and ", 2, EAX, IMM32 }, // 25
{ 0, 0, "es ", 0 }, // 26
{ 0, 0, "daa ", 0 }, // 27
{ 1, BYTE, "sub ", 2, RM, R }, // 28
{ 1, DWORD, "sub ", 2, RM, R }, // 29
{ 1, BYTE, "sub ", 2, R, RM }, // 2A
{ 1, DWORD, "sub ", 2, R, RM }, // 2B
{ 0, 0, "sub ", 2, AL, IMM8 }, // 2C
{ 0, 0, "sub ", 2, EAX, IMM32 }, // 2D
{ 0, 0, "cs ", 0 }, // 2E
{ 0, 0, "das ", 0 }, // 2F
{ 1, BYTE, "xor ", 2, RM, R }, // 30
{ 1, DWORD, "xor ", 2, RM, R }, // 31
{ 1, BYTE, "xor ", 2, R, RM }, // 32
{ 1, DWORD, "xor ", 2, R, RM }, // 33
{ 0, 0, "xor ", 2, AL, IMM8 }, // 34
{ 0, 0, "xor ", 2, EAX, IMM32 }, // 35
{ 0, 0, "ss ", 0 }, // 36
{ 0, 0, "aaa ", 0 }, // 37
{ 1, BYTE, "cmp ", 2, RM, R }, // 38
{ 1, DWORD, "cmp ", 2, RM, R }, // 39
{ 1, BYTE, "cmp ", 2, R, RM }, // 3A
{ 1, DWORD, "cmp ", 2, R, RM }, // 3B
{ 0, 0, "cmp ", 2, AL, IMM8 }, // 3C
{ 0, 0, "cmp ", 2, EAX, IMM32 }, // 3D
{ 0, 0, "ds ", 0 }, // 3E
{ 0, 0, "aas ", 0 }, // 3F
{ 0, 0, "inc eax", 0 }, // 40
{ 0, 0, "inc ecx", 0 }, // 41
{ 0, 0, "inc edx", 0 }, // 42
{ 0, 0, "inc ebx", 0 }, // 43
{ 0, 0, "inc esp", 0 }, // 44
{ 0, 0, "inc ebp", 0 }, // 45
{ 0, 0, "inc esi", 0 }, // 46
{ 0, 0, "inc edi", 0 }, // 47
{ 0, 0, "dec eax", 0 }, // 48
{ 0, 0, "dec ecx", 0 }, // 49
{ 0, 0, "dec edx", 0 }, // 4A
{ 0, 0, "dec ebx", 0 }, // 4B
{ 0, 0, "dec esp", 0 }, // 4C
{ 0, 0, "dec ebp", 0 }, // 4D
{ 0, 0, "dec esi", 0 }, // 4E
{ 0, 0, "dec edi", 0 }, // 4F
{ 0, 0, "push eax", 0 }, // 50
{ 0, 0, "push ecx", 0 }, // 51
{ 0, 0, "push edx", 0 }, // 52
{ 0, 0, "push ebx", 0 }, // 53
{ 0, 0, "push esp", 0 }, // 54
{ 0, 0, "push ebp", 0 }, // 55
{ 0, 0, "push esi", 0 }, // 56
{ 0, 0, "push edi", 0 }, // 57
{ 0, 0, "pop eax", 0 }, // 58
{ 0, 0, "pop ecx", 0 }, // 59
{ 0, 0, "pop edx", 0 }, // 5A
{ 0, 0, "pop ebx", 0 }, // 5B
{ 0, 0, "pop esp", 0 }, // 5C
{ 0, 0, "pop ebp", 0 }, // 5D
{ 0, 0, "pop esi", 0 }, // 5E
{ 0, 0, "pop edi", 0 }, // 5F
{ 0, 0, "pusha", 0 }, // 60
{ 0, 0, "popa", 0 }, // 61
{ 1, QWORD, "bound ", 2, R, RM }, // 62
{ 1, WORD, "arpl ", 2, RM, R }, // 63
{ 0, 0, "fs ", 0 }, // 64
{ 0, 0, "gs ", 0 }, // 65
{ 0, 0, "data16 ", 0 }, // 66
{ 0, 0, "addr16 ", 0 }, // 67
{ 0, 0, "push ", 1, IMM32 }, // 68
{ 1, DWORD, "imul ", 3, R, RM, IMM32 }, // 69
{ 0, 0, "push ", 1, IMM8 }, // 6A
{ 1, DWORD, "imul ", 3, R, RM, IMM8 }, // 6B
{ 0, 0, "ins BYTE PTR es:[edi],dx", 0 }, // 6C
{ 0, 0, "ins DWORD PTR es:[edi],dx", 0 }, // 6D
{ 0, 0, "outs dx,BYTE PTR ds:[esi]", 0 }, // 6E
{ 0, 0, "outs dx,DWORD PTR ds:[esi]", 0 }, // 6F
{ 0, 0, "jo ", 1, REL8 }, // 70
{ 0, 0, "jno ", 1, REL8 }, // 71
{ 0, 0, "jb ", 1, REL8 }, // 72
{ 0, 0, "jnb ", 1, REL8 }, // 73
{ 0, 0, "jz ", 1, REL8 }, // 74
{ 0, 0, "jne ", 1, REL8 }, // 75
{ 0, 0, "jbe ", 1, REL8 }, // 76
{ 0, 0, "ja ", 1, REL8 }, // 77
{ 0, 0, "js ", 1, REL8 }, // 78
{ 0, 0, "jns ", 1, REL8 }, // 79
{ 0, 0, "jp ", 1, REL8 }, // 7A
{ 0, 0, "jnp ", 1, REL8 }, // 7B
{ 0, 0, "jl ", 1, REL8 }, // 7C
{ 0, 0, "jnl ", 1, REL8 }, // 7D
{ 0, 0, "jle ", 1, REL8 }, // 7E
{ 0, 0, "jnle ", 1, REL8 }, // 7F
{ 1, BYTE, "add ", 2, RM, IMM8 }, // 80
{ 1, DWORD, "add ", 2, RM, IMM32 }, // 81
{ 0, 0, ".byte 0x82", 0 }, // 82
{ 1, DWORD, "adc ", 2, RM, IMM8 }, // 83
{ 1, BYTE, "test ", 2, RM, R }, // 84
{ 1, DWORD, "test ", 2, RM, R }, // 85
{ 1, BYTE, "xchg ", 2, RM, R }, // 86
{ 1, DWORD, "xchg ", 2, RM, R }, // 87
{ 1, BYTE, "mov ", 2, RM, R }, // 88
{ 1, DWORD, "mov ", 2, RM, R }, // 89
{ 1, BYTE, "mov ", 2, R, RM }, // 8A
{ 1, DWORD, "mov ", 2, R, RM }, // 8B
{ 1, WORD, "mov ", 2, RM, SS }, // 8C
{ 1, 0, "lea ", 2, R, RM }, // 8D
{ 1, WORD, "mov ss,", 1, RM }, // 8E
{ 1, DWORD, "pop ", 1, RM }, // 8F
{ 0, 0, "nop", 0 }, // 90
{ 0, 0, "xchg ecx,eax", 0 }, // 91
{ 0, 0, "xchg edx,eax", 0 }, // 92
{ 0, 0, "xchg ebx,eax", 0 }, // 93
{ 0, 0, "xchg esp,eax", 0 }, // 94
{ 0, 0, "xchg ebp,eax", 0 }, // 95
{ 0, 0, "xchg esi,eax", 0 }, // 96
{ 0, 0, "xchg edi,eax", 0 }, // 97
{ 0, 0, "cwde", 0 }, // 98
{ 0, 0, "cdq", 0 }, // 99
{ 0, 0, "call ", 1, PTR1632 }, // 9A
{ 0, 0, "fwait", 0 }, // 9B
{ 0, 0, "pushf", 0 }, // 9C
{ 0, 0, "popf", 0 }, // 9D
{ 0, 0, "sahf", 0 }, // 9E
{ 0, 0, "lahf", 0 }, // 9F
{ 0, 0, "mov al,ds:", 1, IMM8 }, // A0
{ 0, 0, "mov eax,ds:", 1, IMM8 }, // A1
{ 0, 0, "mov ds:", 2, IMM8, AL }, // A2
{ 0, 0, "mov ds:", 2, IMM32, EAX }, // A3
{ 0, 0, "movs BYTE PTR es:[edi],BYTE PTR ds:[esi]", 0 }, // A4
{ 0, 0, "movs DWORD PTR es:[edi],DWORD PTR ds:[esi]", 0 }, // A5
{ 0, 0, "cmps BYTE PTR es:[esi],BYTE PTR ds:[edi]", 0 }, // A6
{ 0, 0, "cmps DWORD PTR es:[esi],DWORD PTR ds:[edi]", 0 }, // A7
{ 0, 0, "test al,", 1, IMM8 }, // A8
{ 0, 0, "test eax,", 1, IMM32 }, // A9
{ 0, 0, "stos BYTE PTR es:[edi],al", 0 }, // AA
{ 0, 0, "stos DWORD PTR es:[edi],eax", 0 }, // AB
{ 0, 0, "lods al,BYTE PTR ds:[esi]", 0 }, // AC
{ 0, 0, "lods eax,DWORD PTR ds:[esi]", 0 }, // AD
{ 0, 0, "scas al,BYTE PTR es:[edi]", 0 }, // AE
{ 0, 0, "scas eax,DWORD PTR es:[edi]", 0 }, // AF
{ 0, 0, "mov al,", 1, IMM8 }, // B0
{ 0, 0, "mov cl,", 1, IMM8 }, // B1
{ 0, 0, "mov dl,", 1, IMM8 }, // B2
{ 0, 0, "mov bl,", 1, IMM8 }, // B3
{ 0, 0, "mov ah,", 1, IMM8 }, // B4
{ 0, 0, "mov ch,", 1, IMM8 }, // B5
{ 0, 0, "mov dh,", 1, IMM8 }, // B6
{ 0, 0, "mov bh,", 1, IMM8 }, // B7
{ 0, 0, "mov eax,", 1, IMM32 }, // B8
{ 0, 0, "mov ecx,", 1, IMM32 }, // B9
{ 0, 0, "mov edx,", 1, IMM32 }, // BA
{ 0, 0, "mov ebx,", 1, IMM32 }, // BB
{ 0, 0, "mov esp,", 1, IMM32 }, // BC
{ 0, 0, "mov ebp,", 1, IMM32 }, // BD
{ 0, 0, "mov esi,", 1, IMM32 }, // BE
{ 0, 0, "mov edi,", 1, IMM32 }, // BF
{ 1, BYTE, "rol ", 2, RM, IMM8 }, // C0
{ 1, DWORD, "rol ", 2, RM, IMM8 }, // C1
{ 0, 0, "ret ", 1, IMM16 }, // C2
{ 0, 0, "ret", 0 }, // C3
{ 1, FWORD, "les eax,", 1, RM }, // C4
{ 1, FWORD, "lds eax,", 1, RM }, // C5
{ 1, BYTE, "mov ", 2, RM, IMM8 }, // C6
{ 1, DWORD, "mov ", 2, RM, IMM32 }, // C7
{ 0, 0, "enter ", 2, IMM16, IMM8 }, // C8
{ 0, 0, "leave", 0 }, // C9
{ 0, 0, "retf ", 1, IMM16 }, // CA
{ 0, 0, "retf", 0 }, // CB
{ 0, 0, "int3", 0 }, // CC
{ 0, 0, "int ", 1, IMM8 }, // CD
{ 0, 0, "into", 0 }, // CE
{ 0, 0, "iret", 0 }, // CF
{ 1, BYTE, "rol ", 2, RM, ONE }, // D0
{ 1, DWORD, "rol ", 2, RM, ONE }, // D1
{ 1, BYTE, "rol ", 2, RM, CL }, // D2
{ 1, DWORD, "rol ", 2, RM, CL }, // D3
{ 0, 0, "aam ", 1, IMM8 }, // D4
{ 0, 0, "aad ", 1, IMM8 }, // D5
{ 0, 0, ".byte 0xd6", 0 }, // D6
{ 0, 0, "xlat BYTE PTR ds:[ebx]", 0 }, // D7
{ 1, DWORD, "fadd ", 1, RM }, // D8
{ 1, DWORD, "fld ", 1, RM }, // D9
{ 1, DWORD, "fiadd ", 1, RM }, // DA
{ 1, DWORD, "fild ", 1, RM }, // DB
{ 1, QWORD, "fadd ", 1, RM }, // DC
{ 1, QWORD, "fld ", 1, RM }, // DD
{ 1, WORD, "fiadd ", 1, RM }, // DE
{ 1, WORD, "fild ", 1, RM }, // DF
{ 0, 0, "loopne ", 1, REL8 }, // E0
{ 0, 0, "loope ", 1, REL8 }, // E1
{ 0, 0, "loop ", 1, REL8 }, // E2
{ 0, 0, "jecxz ", 1, REL8 }, // E3
{ 0, 0, "in al,", 1, IMM8 }, // E4
{ 0, 0, "in eax,", 1, IMM8 }, // E5
{ 0, 0, "out ", 2, IMM8, AL }, // E6
{ 0, 0, "out ", 2, IMM8, EAX }, // E7
{ 0, 0, "call ", 1, REL32 }, // E8
// { 0, 0, "jmp ", 1, REL32 }, // E9
{ 0, 0, "jmp ", 1, REL16 }, // E9
{ 0, 0, "jmpf ", 1, PTR1632 }, // EA
{ 0, 0, "jmp ", 1, REL8 }, // EB
{ 0, 0, "in al,dx", 0 }, // EC
{ 0, 0, "in eax,dx", 0 }, // ED
{ 0, 0, "out dx,al", 0 }, // EE
{ 0, 0, "out dx,eax", 0 }, // EF
{ 0, 0, "lock ", 0 }, // F0
{ 0, 0, "icebp", 0 }, // F1
{ 0, 0, "repnz ", 0 }, // F2
{ 0, 0, "repz", 0 }, // F3
{ 0, 0, "hlt", 0 }, // F4
{ 0, 0, "cmc", 0 }, // F5
{ 1, BYTE, "test ", 2, RM, IMM8 }, // F6
{ 1, DWORD, "test ", 2, RM, IMM32 }, // F7
{ 0, 0, "clc", 0 }, // F8
{ 0, 0, "stc", 0 }, // F9
{ 0, 0, "cli", 0 }, // FA
{ 0, 0, "sti", 0 }, // FB
{ 0, 0, "cld", 0 }, // FC
{ 0, 0, "std", 0 }, // FD
{ 1, BYTE, "inc ", 1, RM }, // FE
{ 1, DWORD, "inc ", 1, RM } // FF
};
static INSTRUCTION HUGE extended_instructions[256] = {
{ 1, WORD, "sldt ", 1, RM }, // 0
{ 1, 0, "sgdtd ", 1, RM }, // 1
{ 1, 0, "lar eax,WORD PTR ", 1, RM }, // 2
{ 1, 0, "lsl eax,WORD PTR ", 1, RM }, // 3
{ 0, 0, ".word 0x0f04", 0 }, // 4
{ 0, 0, "syscall", 0 }, // 5
{ 0, 0, "clts", 0 }, // 6
{ 0, 0, "sysret", 0 }, // 7
{ 0, 0, "invd", 0 }, // 8
{ 0, 0, "wbinvd", 0 }, // 9
{ 0, 0, ".word 0x0f0a", 0 }, // A
{ 0, 0, "ud2", 0 }, // B
{ 0, 0, ".word 0x0f0c", 0 }, // C
{ 1, BYTE, "prefetch ", 1, RM }, // D
{ 0, 0, "femms", 0 }, // E
{ 0 }, // F - Illegal
{ 1, XMMWORD, "movups xmm0,", 1, RM }, // 10
{ 1, XMMWORD, "movups ", 2, RM, XMM0 }, // 11
{ 1, QWORD, "movlps xmm0,", 1, RM }, // 12
{ 1, QWORD, "movlps ", 2, RM, XMM0 }, // 13
{ 1, XMMWORD, "unpcklps xmm0,", 1, RM }, // 14
{ 1, XMMWORD, "unpckhps xmm0,", 1, RM }, // 15
{ 1, QWORD, "movhps xmm0,", 1, RM }, // 16
{ 1, QWORD, "movhps ", 2, RM, XMM0 }, // 17
{ 1, BYTE, "prefetchnta ", 1, RM }, // 18
{ 1, DWORD, "nop ", 1, RM }, // 19
{ 1, 0, "bndldx bnd0,", 1, RM }, // 1A
{ 1, 0, "bndstx ", 2, RM, BND0 }, // 1B
{ 1, DWORD, "nop ", 1, RM }, // 1C
{ 1, DWORD, "nop ", 1, RM }, // 1D
{ 1, DWORD, "nop ", 1, RM }, // 1E
{ 1, DWORD, "nop ", 1, RM }, // 1F
{ 0, 0, ".word 0x0f20", 0 }, // 20
{ 0, 0, ".word 0x0f21", 0 }, // 21
{ 0, 0, ".word 0x0f22", 0 }, // 22
{ 0, 0, ".word 0x0f23", 0 }, // 23
{ 0, 0, ".word 0x0f24", 0 }, // 24
{ 0, 0, ".word 0x0f25", 0 }, // 25
{ 0, 0, ".word 0x0f26", 0 }, // 26
{ 0, 0, ".word 0x0f27", 0 }, // 27
{ 1, XMMWORD, "movaps xmm0,", 1, RM }, // 28
{ 1, XMMWORD, "movaps ", 2, RM, XMM0 }, // 29
{ 1, QWORD, "cvtpi2ps xmm0,", 1, RM }, // 2A
{ 1, XMMWORD, "movntps ", 2, RM, XMM0 }, // 2B
{ 1, QWORD, "cvttps2pi mm0,", 1, RM }, // 2C
{ 1, QWORD, "cvtps2pi mm0,", 1, RM }, // 2D
{ 1, DWORD, "ucomiss xmm0,", 1, RM }, // 2E
{ 1, DWORD, "comiss xmm0,", 1, RM }, // 2F
{ 0, 0, "wrmsr", 0 }, // 30
{ 0, 0, "rdtsc", 0 }, // 31
{ 0, 0, "rdmsr", 0 }, // 32
{ 0, 0, "rdpmc", 0 }, // 33
{ 0, 0, "sysenter", 0 }, // 34
{ 0, 0, "sysexit", 0 }, // 35
{ 0, 0, ".word 0x0f36", 0 }, // 36
{ 0, 0, "getsec", 0 }, // 37
{ 1, QWORD, "pshufb mm0,", 1, RM }, // 38
{ 0, 0, ".word 0x0f39", 0 }, // 39
{ 0, 0, "(bad)", 1, BAD }, // 3A
{ 0, 0, ".word 0x0f3b", 0 }, // 3B
{ 0, 0, ".word 0x0f3c", 0 }, // 3C
{ 0, 0, ".word 0x0f3d", 0 }, // 3D
{ 0, 0, ".word 0x0f3e", 0 }, // 3E
{ 0, 0, ".word 0x0f3f", 0 }, // 3F
{ 1, DWORD, "cmovo ", 2, R, RM }, // 40
{ 1, DWORD, "cmovno ", 2, R, RM }, // 41
{ 1, DWORD, "cmovb ", 2, R, RM }, // 42
{ 1, DWORD, "cmovae ", 2, R, RM }, // 43
{ 1, DWORD, "cmove ", 2, R, RM }, // 44
{ 1, DWORD, "cmovne ", 2, R, RM }, // 45
{ 1, DWORD, "cmovbe ", 2, R, RM }, // 46
{ 1, DWORD, "cmova ", 2, R, RM }, // 47
{ 1, DWORD, "cmovs ", 2, R, RM }, // 48
{ 1, DWORD, "cmovns ", 2, R, RM }, // 49
{ 1, DWORD, "cmovp ", 2, R, RM }, // 4A
{ 1, DWORD, "cmovnp ", 2, R, RM }, // 4B
{ 1, DWORD, "cmovl ", 2, R, RM }, // 4C
{ 1, DWORD, "cmovge ", 2, R, RM }, // 4D
{ 1, DWORD, "cmovle ", 2, R, RM }, // 4E
{ 1, DWORD, "cmovg ", 2, R, RM }, // 4F
{ 0, 0, ".word 0x0f50", 0 }, // 50
{ 1, XMMWORD, "sqrtps xmm0,", 1, RM }, // 51
{ 1, XMMWORD, "rsqrtps xmm0,", 1, RM }, // 52
{ 1, XMMWORD, "rcpps xmm0,", 1, RM }, // 53
{ 1, XMMWORD, "andps xmm0,", 1, RM }, // 54
{ 1, XMMWORD, "andnps xmm0,", 1, RM }, // 55
{ 1, XMMWORD, "orps xmm0,", 1, RM }, // 56
{ 1, XMMWORD, "xorps xmm0,", 1, RM }, // 57
{ 1, XMMWORD, "addps xmm0,", 1, RM }, // 58
{ 1, XMMWORD, "mulps xmm0,", 1, RM }, // 59
{ 1, QWORD, "cvtps2pd xmm0,", 1, RM }, // 5A
{ 1, XMMWORD, "cvtdp2ps xmm0,", 1, RM }, // 5B
{ 1, XMMWORD, "subps xmm0,", 1, RM }, // 5C
{ 1, XMMWORD, "minps xmm0,", 1, RM }, // 5D
{ 1, XMMWORD, "divps xmm0,", 1, RM }, // 5E
{ 1, XMMWORD, "maxps xmm0,", 1, RM }, // 5F
{ 1, DWORD, "punpcklbw mm0,", 1, RM }, // 60
{ 1, DWORD, "punpcklwd mm0,", 1, RM }, // 61
{ 1, DWORD, "punpckldq mm0,", 1, RM }, // 62
{ 1, QWORD, "packsswb mm0,", 1, RM }, // 63
{ 1, QWORD, "pcmpgtb mm0,", 1, RM }, // 64
{ 1, QWORD, "pcmpgtw mm0,", 1, RM }, // 65
{ 1, QWORD, "pcmpgtd mm0,", 1, RM }, // 66
{ 1, QWORD, "packuswb mm0,", 1, RM }, // 67
{ 1, QWORD, "punpckhbw mm0,", 1, RM }, // 68
{ 1, QWORD, "punpckhwd mm0,", 1, RM }, // 69
{ 1, QWORD, "punpckhdq mm0,", 1, RM }, // 6A
{ 1, QWORD, "packssdw mm0,", 1, RM }, // 6B
{ 0, 0, ".word 0x0f6c", 0 }, // 6C
{ 0, 0, ".word 0x0f6d", 0 }, // 6D
{ 1, DWORD, "movd mm0,", 1, RM }, // 6E
{ 1, QWORD, "movq mm0,", 1, RM }, // 6F
{ 1, QWORD, "pshufw mm0,", 2, RM, IMM8 }, // 70
{ 0, 0, ".word 0x0f71", 0 }, // 71
{ 0, 0, ".word 0x0f72", 0 }, // 72
{ 0, 0, ".word 0x0f73", 0 }, // 73
{ 1, QWORD, "pcmpeqb mm0,", 1, RM }, // 74
{ 1, QWORD, "pcmpeqw mm0,", 1, RM }, // 75
{ 1, QWORD, "pcmpeqd mm0,", 1, RM }, // 76
{ 0, 0, "emms", 0 }, // 77
{ 1, DWORD, "vmread ", 2, RM, R }, // 78
{ 1, DWORD, "vmwrite ", 2, R, RM }, // 79
{ 0, 0, "(bad)", 1, BAD }, // 7A
{ 0, 0, ".word 0x0f7b", 0 }, // 7B
{ 0, 0, ".word 0x0f7c", 0 }, // 7C
{ 0, 0, ".word 0x0f7d", 0 }, // 7D
{ 1, DWORD, "movd ", 2, RM, MM0 }, // 7E
{ 1, QWORD, "movq ", 2, RM, MM0 }, // 7F
{ 0, 0, "jo ", 1, REL32 }, // 80
{ 0, 0, "jno ", 1, REL32 }, // 81
{ 0, 0, "jb ", 1, REL32 }, // 82
{ 0, 0, "jae ", 1, REL32 }, // 83
{ 0, 0, "je ", 1, REL32 }, // 84
{ 0, 0, "jne ", 1, REL32 }, // 85
{ 0, 0, "jbe ", 1, REL32 }, // 86
{ 0, 0, "ja ", 1, REL32 }, // 87
{ 0, 0, "js ", 1, REL32 }, // 88
{ 0, 0, "jns ", 1, REL32 }, // 89
{ 0, 0, "jp ", 1, REL32 }, // 8A
{ 0, 0, "jnp ", 1, REL32 }, // 8B
{ 0, 0, "jl ", 1, REL32 }, // 8C
{ 0, 0, "jge ", 1, REL32 }, // 8D
{ 0, 0, "jle ", 1, REL32 }, // 8E
{ 0, 0, "jg ", 1, REL32 }, // 8F
{ 1, BYTE, "seto ", 1, RM }, // 90
{ 1, BYTE, "setno ", 1, RM }, // 91
{ 1, BYTE, "setb ", 1, RM }, // 92
{ 1, BYTE, "setae ", 1, RM }, // 93
{ 1, BYTE, "sete ", 1, RM }, // 94
{ 1, BYTE, "setne ", 1, RM }, // 95
{ 1, BYTE, "setbe ", 1, RM }, // 96
{ 1, BYTE, "seta ", 1, RM }, // 97
{ 1, BYTE, "sets ", 1, RM }, // 98
{ 1, BYTE, "setns ", 1, RM }, // 99
{ 1, BYTE, "setp ", 1, RM }, // 9A
{ 1, BYTE, "setnp ", 1, RM }, // 9B
{ 1, BYTE, "setl ", 1, RM }, // 9C
{ 1, BYTE, "setge ", 1, RM }, // 9D
{ 1, BYTE, "setle ", 1, RM }, // 9E
{ 1, BYTE, "setg ", 1, RM }, // 9F
{ 0, 0, "push fs", 0 }, // A0
{ 0, 0, "pop fs", 0 }, // A1
{ 0, 0, "cpuid", 0 }, // A2
{ 1, DWORD, "bt ", 2, RM, R }, // A3
{ 1, DWORD, "shld ", 3, RM, R, IMM8 }, // A4
{ 1, DWORD, "shld ", 3, RM, R, CL }, // A5
{ 0 }, // A6 - Illegal
{ 0 }, // A7 - Illegal
{ 0, 0, "push gs", 0 }, // A8
{ 0, 0, "pop gs", 0 }, // A9
{ 0, 0, "rsm", 0 }, // AA
{ 1, DWORD, "bts ", 2, RM, R }, // AB
{ 1, DWORD, "shrd ", 3, RM, R, IMM8 }, // AC
{ 1, DWORD, "shrd ", 3, RM, R, CL }, // AD
{ 1, 0, "fxsave ", 1, RM }, // AE
{ 1, DWORD, "imul ", 2, R, RM }, // AF
{ 1, BYTE, "cmpxchg ", 2, RM, AL }, // B0
{ 1, DWORD, "cmpxchg ", 2, RM, R }, // B1
{ 1, FWORD, "lss ", 2, R, RM }, // B2
{ 1, DWORD, "btr ", 2, RM, R }, // B3
{ 1, FWORD, "lfs ", 2, R, RM }, // B4
{ 1, FWORD, "lgs ", 2, R, RM }, // B5
{ 1, BYTE, "movzx ", 2, R, RM }, // B6
{ 1, WORD, "movzx ", 2, R, RM }, // B7
{ 0, 0, ".word 0x0fb8", 0 }, // B8
{ 0, 0, "ud1", 0 }, // B9
{ 0, 0, ".word 0x0fba", 0 }, // BA
{ 1, DWORD, "btc ", 2, RM, R }, // BB
{ 1, DWORD, "bsf ", 2, R, RM }, // BC
{ 1, DWORD, "bsr ", 2, R, RM }, // BD
{ 1, BYTE, "movsx ", 2, R, RM }, // BE
{ 1, WORD, "movsx ", 2, R, RM }, // BF
{ 1, BYTE, "xadd ", 2, RM, R }, // C0
{ 1, DWORD, "xadd ", 2, RM, R }, // C1
{ 1, XMMWORD, "cmpeqps xmm0,", 1, RM }, // C2
{ 1, QWORD, "movnti ", 2, RM, R }, // C3
{ 1, WORD, "pinsrw mm0,", 2, RM, IMM8 }, // C4
{ 1, 0, "pextrw ", 3, R, MM0, IMM8 }, // C5
{ 1, XMMWORD, "shufps xmm0,", 2, RM, IMM8 }, // C6
{ 0, 0, ".word 0x0fc7", 0 }, // C7
{ 0, 0, "bswap eax", 0 }, // C8
{ 0, 0, "bswap ecx", 0 }, // C9
{ 0, 0, "bswap edx", 0 }, // CA
{ 0, 0, "bswap ebx", 0 }, // CB
{ 0, 0, "bswap esp", 0 }, // CC
{ 0, 0, "bswap ebp", 0 }, // CD
{ 0, 0, "bswap esi", 0 }, // CE
{ 0, 0, "bswap edi", 0 }, // CF
{ 0, 0, ".word 0x0fd0", 0 }, // D0
{ 1, QWORD, "psrlw mm0,", 1, RM }, // D1
{ 1, QWORD, "psrld mm0,", 1, RM }, // D2
{ 1, QWORD, "psrlq mm0,", 1, RM }, // D3
{ 1, QWORD, "paddq mm0,", 1, RM }, // D4
{ 1, QWORD, "pmullw mm0,", 1, RM }, // D5
{ 0, 0, ".word 0x0fd6,", 0 }, // D6
{ 0, 0, ".word 0x0fd7,", 0 }, // D7
{ 1, QWORD, "psubusb mm0,", 1, RM }, // D8
{ 1, QWORD, "psubusw mm0,", 1, RM }, // D9
{ 1, QWORD, "pminub mm0,", 1, RM }, // DA
{ 1, QWORD, "pand mm0,", 1, RM }, // DB
{ 1, QWORD, "paddusb mm0,", 1, RM }, // DC
{ 1, QWORD, "psubusw mm0,", 1, RM }, // DD
{ 1, QWORD, "pmaxub mm0,", 1, RM }, // DE
{ 1, QWORD, "pandn mm0,", 1, RM }, // DF
{ 1, QWORD, "pavgb mm0,", 1, RM }, // E0
{ 1, QWORD, "psraw mm0,", 1, RM }, // E1
{ 1, QWORD, "psrad mm0,", 1, RM }, // E2
{ 1, QWORD, "pavgw mm0,", 1, RM }, // E3
{ 1, QWORD, "pmulhuw mm0,", 1, RM }, // E4
{ 1, QWORD, "pmulhw mm0,", 1, RM }, // E5
{ 0, 0, ".word 0x0fe6", 0 }, // E6
{ 1, QWORD, "movntq ", 2, RM, MM0 }, // E7
{ 1, QWORD, "psubsb mm0,", 1, RM }, // E8
{ 1, QWORD, "psubsw mm0,", 1, RM }, // E9
{ 1, QWORD, "pminsw mm0,", 1, RM }, // EA
{ 1, QWORD, "por mm0,", 1, RM }, // EB
{ 1, QWORD, "paddsb mm0,", 1, RM }, // EC
{ 1, QWORD, "paddsw mm0,", 1, RM }, // ED
{ 1, QWORD, "pmaxsw mm0,", 1, RM }, // EE
{ 1, QWORD, "pxor mm0,", 1, RM }, // EF
{ 0, 0, ".word 0x0ff0", 0 }, // F0
{ 1, QWORD, "psllow mm0,", 1, RM }, // F1
{ 1, QWORD, "pslld mm0,", 1, RM }, // F2
{ 1, QWORD, "psllq mm0,", 1, RM }, // F3
{ 1, QWORD, "pmuludq mm0,", 1, RM }, // F4
{ 1, QWORD, "pmaddwd mm0,", 1, RM }, // F5
{ 1, QWORD, "psadbw mm0,", 1, RM }, // F6
{ 0 }, // F7 - Illegal
{ 1, QWORD, "psubb mm0,", 1, RM }, // F8
{ 1, QWORD, "psubw mm0,", 1, RM }, // F9
{ 1, QWORD, "psubd mm0,", 1, RM }, // FA
{ 1, QWORD, "psubq mm0,", 1, RM }, // FB
{ 1, QWORD, "paddb mm0,", 1, RM }, // FC
{ 1, QWORD, "paddw mm0,", 1, RM }, // FD
{ 1, QWORD, "paddd mm0,", 1, RM }, // FE
{ 0 }, // FF - Illegal
};
unsigned int disasm(const unsigned char *__bytes, unsigned int max, unsigned long offset, char *output) {
unsigned char *pad[32];
unsigned char *bytes;
const unsigned char *base;
unsigned char opcode;
char RM_output[32];
char R_output[32];
char modRM_mod;
char modRM_reg;
char modRM_rm;
int i;
INSTRUCTION *instructions ;
memset (pad, 0, sizeof (pad));
if (max > sizeof (pad))
max = sizeof (pad);
memcpy (pad, __bytes, max);
bytes = (unsigned char *)pad;
base = bytes;
opcode = *bytes;
bytes++;
*output = 0;
instructions = standard_instructions;
if (opcode == 0x0F) { // Extended opcodes
if (max < 2 || *bytes == 0x0F || *bytes == 0xA6 || *bytes == 0xA7 || *bytes == 0xF7 || *bytes == 0xFF) {
return -1;
}
instructions = extended_instructions;
opcode = *bytes++;
}
if (!instructions[opcode].hasModRM) {
goto OUTPUT; // Skip ModRM byte parsing
}
modRM_mod = ((*bytes) >> 6) & 3; // 3; // Bits 7-6.
modRM_reg = ((*bytes) >> 3) & 7; // 7; // Bits 5-3.
modRM_rm = (*bytes++) & 7; // 7; // Bits 2-0.
switch (instructions[opcode].size) {
case WORD:
strcpy(R_output, register_mnemonics16[modRM_reg]);
break;
case BYTE:
strcpy(R_output, register_mnemonics8[modRM_reg]);
break;
default:
strcpy(R_output, register_mnemonics32[modRM_reg]);
}
if (modRM_mod == 3) { // Register addressing mode.
switch (instructions[opcode].size) {
case BYTE:
sprintf(RM_output, "%s", register_mnemonics8[modRM_rm]);
break;
case WORD:
sprintf(RM_output, "%s", register_mnemonics16[modRM_rm]);
break;
default:
sprintf(RM_output, "%s", register_mnemonics32[modRM_rm]);
}
} else if (modRM_mod == 0 && modRM_rm == 5) { // Displacement only addressing mode.
sprintf(RM_output, "[0x%x]", *(int *)bytes);
bytes += 4;
} else { // One-byte or four-byte signed displacement follows addressing mode byte(s).
if (modRM_rm == 4) { // Contains SIB byte
char SIB_scale = ((*bytes) >> 6) & 3; // Bits 7-6.
char SIB_index = ((*bytes) >> 3) & 7; // Bits 5-3.
char SIB_base = (*bytes++) & 7; // Bits 2-0.
if (SIB_base == 5 && modRM_mod == 0) {
sprintf(RM_output, "[0x%x", *(int *)bytes);
bytes += 4;
} else {
strcpy(RM_output, sib_base_mnemonics[SIB_base]);
}
if (SIB_index != 20) {
strcat(RM_output, "+");
strcat(RM_output, register_mnemonics32[SIB_index]);
strcat(RM_output, sib_scale_mnemonics[SIB_scale]);
}
} else {
sprintf(RM_output, "[%s", register_mnemonics32[modRM_rm]);
}
if (modRM_mod == 1) { // One-byte signed displacement follows addressing mode byte(s).
if (*bytes > 0x7F) {
sprintf(RM_output + strlen(RM_output), "-0x%x]", -*(char *)bytes++);
} else {
sprintf(RM_output + strlen(RM_output), "+0x%x]", *(char *)bytes++);
}
} else if (modRM_mod == 2) { // Four-byte signed displacement follows addressing mode byte(s).
if (*(unsigned int *)bytes > 0x7FFFFFFF) {
sprintf(RM_output + strlen(RM_output), "-0x%x]", -*(int *)bytes);
} else {
sprintf(RM_output + strlen(RM_output), "+0x%x]", *(unsigned int *)bytes);
}
bytes += 4;
} else {
strcat(RM_output, "]");
}
}
OUTPUT:
strcpy(output, instructions[opcode].mnemonic);
for (i = 0; i < instructions[opcode].argument_count; i++) {
if (i > 0) {
strcat(output, ",");
}
switch (instructions[opcode].arguments[i]) {
case RM:
if (modRM_mod != 3) {
switch (instructions[opcode].size) {
case BYTE:
strcat(output, "BYTE PTR ");
break;
case WORD:
strcat(output, "WORD PTR ");
break;
case DWORD:
strcat(output, "DWORD PTR ");
break;
case QWORD:
strcat(output, "QWORD PTR ");
break;
case FWORD:
strcat(output, "FWORD PTR ");
break;
case XMMWORD:
strcat(output, "XMMWORD PTR ");
break;
}
}
strcat(output, RM_output);
break;
case R:
strcat(output, R_output);
break;
case IMM8:
sprintf(output + strlen(output), "0x%x", *bytes++);
break;
case IMM16:
sprintf(output + strlen(output), "0x%x", *(short *)bytes);
bytes += 2;
break;
case IMM32:
sprintf(output + strlen(output), "0x%x", *(int *)bytes);
bytes += 4;
break;
case REL8:
sprintf(output + strlen(output), "0x%x", (unsigned int) (offset + ((bytes - base) + 1) + *bytes));
bytes++;
break;
case REL16:
sprintf(output + strlen(output), "0x%x", (unsigned int)(offset + ((bytes - base) + 2) + *(short *)bytes));
bytes += 2;
break;
case REL32:
sprintf(output + strlen(output), "0x%x", (unsigned int)(offset + ((bytes - base) + 4) + *(int *)bytes));
bytes += 4;
break;
case PTR1632:
sprintf(output + strlen(output), "0x%x:0x%x", *(short *)(bytes + 4), *(int *)bytes);
bytes += 6;
break;
case AL:
strcat(output, "al");
break;
case EAX:
strcat(output, "eax");
break;
case ES:
strcat(output, "es");
break;
case CS:
strcat(output, "cs");
break;
case SS:
strcat(output, "ss");
break;
case DS:
strcat(output, "ds");
break;
case ONE:
strcat(output, "1");
break;
case CL:
strcat(output, "cl");
break;
case XMM0:
strcat(output, "xmm0");
break;
case BND0:
strcat(output, "bnd0");
break;
case BAD:
bytes++;
break;
case MM0:
strcat(output, "mm0");
break;
}
}
if (((unsigned int)(bytes - base)) <= max) {
return bytes - base;
}
return -1;
}
+20
View File
@@ -0,0 +1,20 @@
#include <unistd.h>
int main() {
char next=0, ch, och=0;
while (read (0, &ch, 1)==1) {
if (next) {
if (ch==next)
next = 0;
continue;
}
if (och == ' ' && ch==' ')
next = '\n';
if (och == '0' && ch=='x')
next = ':';
if (!next && ch!=' ')
write (1, &ch, 1);
och = ch;
}
return 0;
}
+41 -11
View File
@@ -1,24 +1,48 @@
/* Copyleft 2009 -- pancake /at/ nopcode /dot/ org */
/* io.c - MIT - Copyleft 2009-2021 -- pancake */
#include <sys/types.h>
#include <unistd.h>
#ifndef HAVE_FTRUNCATE
#define HAVE_FTRUNCATE 1
#endif
#define DEMO 0
#if DEMO
int bo = 0;
char b[4096];
static inline int io_open(const char *file) {
memset (b, 0, sizeof (b));
return 10;
}
static int io_read(void *x,int y) {
memcpy (x, b+bo, y);
return y;
}
#define io_write(x,y) memcpy (b+bo, x,y)
static int io_seek (int x,int y) {
bo=((y==2)?sizeof(b):(y==1)?bo+x:x);
return bo;
}
#define io_close() printf("close: TODO\n")
#define io_system(x) system(x)
#define io_truncate(x) printf("truncate: TODO\n");
#else
#if __WIN32__
#include <windows.h>
static HANDLE _fd = NULL;
#define setenv(x,y,z) SetEnvironmentVariable(x, y)
static inline int io_open(char *file) {
static inline int io_open(const char *file) {
_fd = CreateFile(file, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_ALWAYS, 0, NULL);
if (_fd == INVALID_HANDLE_VALUE)
if(_fd == INVALID_HANDLE_VALUE)
_fd = CreateFile(file, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_ALWAYS, 0, NULL);
return (_fd==INVALID_HANDLE_VALUE)?-1:0;
}
static int io_read(void *x, int y) {
static inline int io_read(void *x, int y) {
DWORD ret;
return ReadFile(_fd,x,y,&ret,NULL)?ret:-1;
return ReadFile(_fd, x, y, &ret, NULL)?ret:-1;
}
#define setenv(x,y,z) SetEnvironmentVariable(x, y)
#define io_write(x,y) WriteFile(_fd, x, y, NULL, NULL)
#define io_seek(x,y) SetFilePointer(_fd,x,0,!y?FILE_BEGIN:y==1?FILE_CURRENT:FILE_END)
#define io_close() CloseHandle(_fd)
@@ -31,9 +55,9 @@ static int io_read(void *x, int y) {
#define _GNU_SOURCE
#include <fcntl.h>
static int _fd = -1;
static inline int io_open(char *file) {
static inline int io_open(const char *file) {
_fd = open(file, O_RDWR|O_CREAT, 0644);
if (_fd == -1) _fd = open(file, O_RDONLY);
if(_fd == -1) _fd = open(file, O_RDONLY);
return _fd;
}
#define io_read(x,y) read(_fd, x, y)
@@ -41,5 +65,11 @@ static inline int io_open(char *file) {
#define io_seek(x,y) lseek(_fd, x, y)
#define io_close() close(_fd)
#define io_system(x) system(x)
#define io_truncate(x) ftruncate(_fd,(unsigned long)x)
#if HAVE_FTRUNCATE
#define io_truncate(x) ftruncate(_fd, (off_t)x)
#else
#define io_truncate(x) printf("truncate: TODO\n");
#endif
#endif
#endif
-122
View File
@@ -1,122 +0,0 @@
/* Copyleft 2009 -- pancake /at/ nopcode /dot/ org */
#define ut64 unsigned long long
#define ut8 unsigned char
static int verbose = 1;
static char *script = 0;
static ut64 oldseek, curseek = 0LL;
static unsigned int obsize, bsize = 256;
static int red_cmd(char *cmd); // XXX : recursive depenency
#include "red.h"
int red_slurpin() {
int len;
unsigned char buf[4096];
for(;;) {
len = read(0, buf, 4096);
if (len<1) break;
hexdump(buf, len, 16);
curseek += len;
}
return 0;
}
static char *red_interpret(char *file) {
char buf[1024];
FILE *fd = fopen(file, "r");
if (fd != NULL) {
file = NULL;
for(;;) {
if (fgets(buf, 1023, fd) == NULL)
break;
red_cmd(buf);
}
fclose(fd);
} else fprintf(stderr, "Cannot open script file '%s'\n", file);
return file;
}
static int red_cmd(char *cmd) {
switch(*cmd) {
case ';': case '#': break; // comment
case 'q': return 0;
case '>': cmd_dump(cmd+1); break;
case '<': cmd_load(cmd+1); break;
case '.': red_interpret(skipspaces(cmd+1)); break;
case 's': cmd_seek(cmd+1); break;
case 'b': cmd_bsize(cmd+1); break;
case '/': cmd_search(cmd+1); break;
case 'p': cmd_print(cmd+1); break;
case 'r': cmd_resize(cmd+1); break;
case 'x': cmd_hexdump(cmd+1); break;
case 'X': cmd_bytedump(cmd+1); break;
case 'w': cmd_write(cmd+1); break;
case '!': cmd_system(cmd+1); break;
case '?': cmd_help(cmd+1); break;
default: fprintf(stderr, "? %s\n", cmd);
}
return 1;
}
static int red_prompt() {
char *at, *at2, line[4096];
if (verbose) {
printf("[0x%08"LLF"x]> ", curseek);
fflush(stdout);
}
if (fgets(line, 4095, stdin) == NULL)
return 0;
line[strlen(line)-1] = 0;
if (line[0] != '!') {
at = strchr(line, '@');
oldseek = curseek;
obsize = bsize;
if (at) {
*at = 0; at++;
at2 = strchr(at, ':');
if (at2) {
*at2 = 0; at2++;
if (*at2) bsize = (int)str2ut64(at2);
}
if (*at) curseek = str2ut64(at);
}
}
return red_cmd(skipspaces(line));
}
static void red_open(char *file) {
oldseek = 0;
setenv("FILE", file, 1);
if (io_open(file) != -1) {
if (script)
script = red_interpret(script);
while(red_prompt()) {
curseek = oldseek;
bsize = obsize;
}
io_close();
} else fprintf(stderr, "Cannot open '%s'\n", file);
}
static int red_help() {
puts("ired [-hnv] [-i script] [file] [..]");
return 0;
}
int main(int argc, char **argv) {
int i;
if (argc>1)
for(i=1;i<argc;i++) {
if (argv[i][0]=='-')
switch(argv[i][1]) {
case 'i': script = argv[++i]; break;
case 'n': verbose = 0; break;
case 'v': puts("red "VERSION" 2009"); return 0;
case 'h': return red_help();
case 0x0: return red_slurpin();
} else red_open(argv[i]);
} else return red_help();
return 0;
}
+17 -9
View File
@@ -1,11 +1,11 @@
.Dd Sep 1, 2009
.Dt IRED 1
.Dd Mar 7, 2021
.Dt R0 1
.Os
.Th IRED 1
.Th R0 1
.Sh NAME
ired \- interactive raw editor
r0 \- interactive raw editor
.Sh SYNOPSIS
.Nm ired
.Nm r0
.Op Fl hnv
.Op Fl i Ar script
.Ar file ...
@@ -22,9 +22,9 @@ Show version information
.It Fl n
Do not be verbose
.It Fl i Ar script
Interpret a script file as ired commands.
Interpret a script file as r0 commands.
.Pp
Same as "ired file < script"
Same as "r0 file < script"
.El
.PP
.Sh COMMANDS
@@ -95,7 +95,15 @@ dump current block to file
.It !cmd
run shell command
.Pp
> !cp $BLOCK $FILE.curblock # save current block
The following environment variables are defined when found in the command string:
.Pp
FILE is the filename of the current working file
.Pp
BLOCK points to the temporal filename with the current block dump
.Pp
OFFSET and XOFFSET are decimal and hexadecimal values of the current seek
.Pp
> !cp $BLOCK $FILE-$XOFFSET.curblock # save current block
.It ?expr
calculate numeric expression
.Pp
@@ -109,7 +117,7 @@ quit
.El
.Sh SEE ALSO
.Pp
.Xr vired(1)
.Xr r0v(1)
.Sh AUTHORS
.PP
pancake <@nopcode.org>
+165
View File
@@ -0,0 +1,165 @@
/* MIT 2009-2021 -- pancake /at/ nopcode /dot/ org */
#define ut64 unsigned long long
#define ut8 unsigned char
static int earlyquit = 0;
static int verbose = 1;
static int scriptn = 0;
static const char **scripts = 0;
static int cmdn = 0;
static char **cmds = 0;
static ut64 oldseek, curseek = 0LL;
static int obsize, bsize = 256;
int r0_cmd(const char *cmd); // XXX : recursive depenency
#if defined(__WATCOMC__)
#define HAVE_FTRUNCATE 0
#define BUFSZ 1024
#elif __wasi__
#define BUFSZ 128
#else
#define BUFSZ 128*1024
#endif
ut64 calc(const char *str);
#include "r0.h"
#include "util.c"
#include "calc.c"
#include "cmd.c"
static void r0_slurpin() {
ut8 buf[BUFSZ];
for(;;) {
int len = read(0, buf, sizeof(buf));
if(len<1) break;
hexdump(buf, len, 16);
curseek += len;
}
}
static int r0_interpret(const char *file) {
char buf[BUFSZ];
FILE *fd = fopen(file, "r");
if(fd != NULL) {
for(;;) {
if(fgets(buf, sizeof(buf), fd) == NULL)
break;
r0_cmd(buf);
}
fclose(fd);
} else if (file)
fprintf(stderr, "Cannot open script file '%s'\n", file);
return 1;
}
int r0_cmd(const char *cmd) {
const char *arg = cmd+1;
SKIPSPACES(arg);
switch(*cmd) {
case 'q': return 0;
case ';': case '#': break; // comment
case '>': return cmd_dump(arg); break;
case '<': return cmd_load(arg); break;
case '.': return r0_interpret(arg); break;
case 's': return cmd_seek(arg); break;
case 'b': return cmd_bsize(arg); break;
case '/': return cmd_search(arg); break;
case 'd': return cmd_disasm(arg); break;
case 'p': return cmd_print(arg); break;
case 'r': return cmd_resize(arg); break;
case 'x': return cmd_hexdump(arg); break;
case 'X': return cmd_bytedump(arg); break;
case 'w': return cmd_write(arg); break;
case '!': return cmd_system(arg); break;
case 'V': return cmd_system("vr0 $FILE"); break;
case '?': return cmd_help(arg); break;
default: fprintf(stderr, "? %s\n", cmd);
}
return 1;
}
static int r0_prompt() {
char *at, *at2, line[BUFSZ];
if(verbose) {
printf("[0x%08"LLF"x]> ", curseek);
fflush(stdout);
}
if(fgets(line, sizeof(line), stdin) == NULL)
return 0;
line[strlen(line)-1] = '\0';
if(*line != '!') {
at = strchr(line, '@');
oldseek = curseek;
obsize = bsize;
if(at) {
*at = 0;
at2 = strchr(++at, ':');
if(at2) {
*at2 = 0; at2++;
if(*at2) bsize = (int)calc(at2);
}
if(*at) curseek = calc(at);
}
}
at = line;
SKIPSPACES(at);
return r0_cmd(at);
}
int r0_open(const char *file) {
int ret = io_open(file);
if(ret != -1) {
oldseek = 0;
setenv("FILE", file, 1);
if(scripts)
for (ret=0;ret<scriptn;ret++)
r0_interpret(scripts[ret]);
if(cmds)
for (ret=0;ret<cmdn;ret++)
r0_cmd(cmds[ret]);
if(earlyquit)
return 0;
while((ret=r0_prompt())>0) {
curseek = oldseek;
bsize = obsize;
}
io_close();
} else if (file)
fprintf(stderr, "Cannot open '%s'\n", file);
return ret==-1 ?1:0;
}
static int r0_help() {
puts("r0 [-qhnv] [-c cmd] [-i script] [-|file ..]");
return 0;
}
int main(int argc, char **argv) {
int i, ret = 1;
argc++;
cmdn = 0;
scriptn = 0;
scripts = calloc(sizeof(const char*), argc);
cmds = calloc(sizeof(const char*), argc);
if(argc > 1 && argv[1]) {
for(i = 1; i < argc; i++) {
if(argv[i] && argv[i][0]=='-')
switch(argv[i][1]) {
case 'q': earlyquit = 1; break;
case 'i': scripts[scriptn++] = argv[++i]; break;
case 'c': cmds[cmdn++] = argv[++i]; break;
case 'n': verbose = 0; break;
case 'v': puts(VERSION); ret = 0; break;
case 'h': ret = r0_help(); break;
case 0x0: r0_slurpin(); ret = 0; break;
} else {
if (!argv[i]) break;
ret = r0_open(argv[i]);
}
}
} else {
ret = r0_help();
}
free(scripts);
return ret;
}
+26
View File
@@ -0,0 +1,26 @@
#define VERSION "0.9"
#include <unistd.h>
#include <sys/types.h>
#include "io.c"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define SKIPSPACES(x) for(;*(x)==' '||*(x)=='\t';x++) {};
#if(R0_NOENV)
#define LLF "ll"
#define setenv(x,y,z) //
// static int setenv(char *var, char *val, int force) { return 0; }
#elif(plan9)
static int setenv(char *var, char *val, int force) {
char str[256];
snprintf(str, sizeof(str), "echo %s > /env/%s", var, val);
return system(str);
}
#define LLF "L"
#else
#define LLF "ll"
#endif
+364
View File
@@ -0,0 +1,364 @@
/* bdiff - MIT - Copyright 2010-2021 - pancake */
/* Adapted code from:
bdiff.c - efficient binary diff extension for Mercurial
Copyright 2005, 2006 Matt Mackall <[email protected]>
This software may be used and distributed according to the terms of
the GNU General Public License, incorporated herein by reference.
Based roughly on Python difflib
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
struct line {
int h, len, n, e;
const char *l;
};
struct pos {
int pos, len;
};
struct hunk {
int a1, a2, b1, b2;
};
struct hunklist {
struct hunk *base, *head;
};
static int splitlines(const char *a, int len, struct line **lr) {
int h, i;
const char *p, *b = a;
const char * const plast = a + len - 1;
struct line *l;
/* count the lines */
i = 1; /* extra line for sentinel */
for(p = a; p < a + len; p++)
if(*p == '\n' || p == plast)
i++;
*lr = l = (struct line *)malloc(sizeof(struct line) * i);
if(!l)
return -1;
/* build the line array and calculate hashes */
h = 0;
for(p = a; p < a + len; p++) {
/* Leonid Yuriev's hash */
h = (h * 1664525) + *p + 1013904223;
if(*p == '\n' || p == plast) {
l->h = h;
h = 0;
l->len = p - b + 1;
l->l = b;
l->n = INT_MAX;
l++;
b = p + 1;
}
}
/* set up a sentinel */
l->h = l->len = 0;
l->l = a + len;
return i - 1;
}
static int inline cmp(struct line *a, struct line *b) {
return a->h != b->h || a->len != b->len || memcmp(a->l, b->l, a->len);
}
static int equatelines(struct line *a, int an, struct line *b, int bn) {
int i, j, buckets = 1, t, scale;
struct pos *h = NULL;
/* build a hash table of the next highest power of 2 */
while(buckets < bn + 1)
buckets *= 2;
/* try to allocate a large hash table to avoid collisions */
for(scale = 4; scale; scale /= 2) {
h = (struct pos *)calloc(buckets, scale * sizeof(struct pos));
if(h)
break;
}
if(!h)
return 0;
buckets = buckets * scale - 1;
/* clear the hash table */
for(i = 0; i <= buckets; i++) {
h[i].pos = INT_MAX;
h[i].len = 0;
}
/* add lines to the hash table chains */
for(i = bn - 1; i >= 0; i--) {
/* find the equivalence class */
for(j = b[i].h & buckets; h[j].pos != INT_MAX;
j = (j + 1) & buckets)
if(!cmp(b + i, b + h[j].pos))
break;
/* add to the head of the equivalence class */
b[i].n = h[j].pos;
b[i].e = j;
h[j].pos = i;
h[j].len++; /* keep track of popularity */
}
/* compute popularity threshold */
t = (bn >= 4000) ? bn / 1000 : bn + 1;
/* match items in a to their equivalence class in b */
for(i = 0; i < an; i++) {
/* find the equivalence class */
for(j = a[i].h & buckets; h[j].pos != INT_MAX;
j = (j + 1) & buckets)
if(!cmp(a + i, b + h[j].pos))
break;
a[i].e = j; /* use equivalence class for quick compare */
if(h[j].len <= t)
a[i].n = h[j].pos; /* point to head of match list */
else a[i].n = INT_MAX; /* too popular */
}
/* discard hash tables */
free(h);
return 1;
}
static int longest_match(struct line *a, struct line *b, struct pos *pos,
int a1, int a2, int b1, int b2, int *omi, int *omj) {
int mi = a1, mj = b1, mk = 0, mb = 0, i, j, k;
for(i = a1; i < a2; i++) {
/* skip things before the current block */
for(j = a[i].n; j < b1; j = b[j].n)
;
/* loop through all lines match a[i] in b */
for(; j < b2; j = b[j].n) {
/* does this extend an earlier match? */
if(i > a1 && j > b1 && pos[j - 1].pos == i - 1)
k = pos[j - 1].len + 1;
else k = 1;
pos[j].pos = i;
pos[j].len = k;
/* best match so far? */
if(k > mk) {
mi = i;
mj = j;
mk = k;
}
}
}
if(mk) {
mi = mi - mk + 1;
mj = mj - mk + 1;
}
/* expand match to include neighboring popular lines */
while(mi - mb > a1 && mj - mb > b1 &&
a[mi - mb - 1].e == b[mj - mb - 1].e)
mb++;
while(mi + mk < a2 && mj + mk < b2 &&
a[mi + mk].e == b[mj + mk].e)
mk++;
*omi = mi - mb;
*omj = mj - mb;
return mk + mb;
}
static void recurse(struct line *a, struct line *b, struct pos *pos,
int a1, int a2, int b1, int b2, struct hunklist *l) {
int i, j, k;
/* find the longest match in this chunk */
k = longest_match(a, b, pos, a1, a2, b1, b2, &i, &j);
if(!k)
return;
/* and recurse on the remaining chunks on either side */
recurse(a, b, pos, a1, i, b1, j, l);
l->head->a1 = i;
l->head->a2 = i + k;
l->head->b1 = j;
l->head->b2 = j + k;
l->head++;
recurse(a, b, pos, i + k, a2, j + k, b2, l);
}
static struct hunklist diff(struct line *a, int an, struct line *b, int bn) {
struct hunklist l;
struct hunk *curr;
struct pos *pos;
int t;
/* allocate and fill arrays */
t = equatelines(a, an, b, bn);
pos = (struct pos *)calloc(bn ? bn : 1, sizeof(struct pos));
/* we can't have more matches than lines in the shorter file */
l.head = l.base = (struct hunk *)malloc(sizeof(struct hunk) *
((an<bn ? an:bn) + 1));
if(pos && l.base && t) {
/* generate the matching block list */
recurse(a, b, pos, 0, an, 0, bn, &l);
l.head->a1 = l.head->a2 = an;
l.head->b1 = l.head->b2 = bn;
l.head++;
}
free(pos);
/* normalize the hunk list, try to push each hunk towards the end */
for(curr = l.base; curr != l.head; curr++) {
struct hunk *next = curr+1;
int shift = 0;
if(next == l.head)
break;
if(curr->a2 == next->a1)
while(curr->a2+shift < an && curr->b2+shift < bn
&& !cmp(a+curr->a2+shift, b+curr->b2+shift))
shift++;
else if(curr->b2 == next->b1)
while(curr->b2+shift < bn && curr->a2+shift < an
&& !cmp(b+curr->b2+shift, a+curr->a2+shift))
shift++;
if(!shift)
continue;
curr->b2 += shift;
next->b1 += shift;
curr->a2 += shift;
next->a1 += shift;
}
return l;
}
char *slurp(const char *str, int *usz) {
char *ret;
long sz, n, num = 0;
FILE *fd = fopen(str, "rb");
if(fd == NULL)
return NULL;
fseek(fd, 0, SEEK_END);
sz = ftell(fd);
fseek(fd, 0, SEEK_SET);
ret = (char *)malloc(sz+1);
do {
n = fread(ret, 1, sz, fd);
if(n<1)
break;
num += n;
} while(num < sz);
ret[num] = '\0';
fclose(fd);
if(usz)
*usz = (int)sz;
return ret;
}
int bdiff(const char *filea, const char *fileb) {
char *sa, *sb;
int i, an, bn, offa, rlen, offb, len = 0;
int la, lb, hits = 0;
struct line *al, *bl;
struct hunklist l = { NULL, NULL };
struct hunk *h;
if((sa = slurp(filea, &la)) == NULL)
return fprintf(stderr, "Cannot open %s\n", filea), 0;
if((sb = slurp(fileb, &lb)) == NULL)
return fprintf(stderr, "Cannot open %s\n", fileb), 0;
/* TODO: split to function here */
an = splitlines(sa, la, &al);
bn = splitlines(sb, lb, &bl);
if(!al || !bl)
return -1;
l = diff(al, an, bl, bn);
if(!l.head)
return -1;
la = lb = 0;
for(h = l.base; h != l.head; h++) {
if(h->a1 != la || h->b1 != lb) {
if (h->b1 > bn) break;
if (lb > bn) break;
len = bl[h->b1].l - bl[lb].l;
offa = al[la].l - al->l;
offb = al[h->a1].l - al->l;
rlen = offb-offa;
//fprintf(stderr, "all: %d %d\n", );
//fprintf(stderr, "len: %d %d\n", len, rlen);
//fprintf(stderr, "off: %d %d\n", offa, offb);
if(rlen>len)
printf("r-%d@%d\n", (rlen-len), offa);
else printf("r+%d@%d\n", (len-rlen), offb);
if(len == rlen) {
for(i=0; i<len; i++) {
if (lb < bn) break;
if (la < bn) break;
if(bl[lb].l[i] != bl[la].l[i])
fprintf(stderr, "%02x %02x\n",
(unsigned char)
bl[lb].l[i],
(unsigned char)
bl[la].l[i]);
}
// XXX fprintf(stderr, "%02x @ 0x%x\n", bl[la].l[i], offa);
fprintf(stderr, "WARNING: Binary patch failed\n");
}
if(len > 0) {
printf("w ");
for(i=0;i<len;i++)
printf("%02x", (unsigned char)bl[lb].l[i]);
printf("@%d#len\n", offa);
} else
if(rlen > 0) {
printf("w ");
for(i=0; i<rlen; i++)
printf("%02x", (unsigned char)bl[la].l[i]);
printf("@%d#rlen\n", offa);
}
}
la = h->a2;
lb = h->b2;
}
free(al);
free(bl);
free(l.base);
return hits;
}
int main(int argc, const char **argv) {
int ret = 1;
if(argc == 3) {
if(bdiff(argv[1], argv[2]) == -1)
fprintf(stderr, "Out of memory\n");
else ret = 0;
} else fprintf(stderr, "r0d [file] [file2] > patch.ired\n");
return ret;
}
Executable
+86
View File
@@ -0,0 +1,86 @@
#!/bin/sh
# r0v: the visual raw editor
# copyleft: pancake at nopcode dot org @ 2009-2013
PATH=.:$PATH
ttyset=`stty -g`
bye() {
[ -n "$ttyset" ] && stty $ttyset
exit 0
}
case "$1" in
-) : ; ;;
'') echo "r0v [-hv] [file]" ; exit 1 ; ;;
*) $0 - | r0 -n $@ ; bye ; ;;
esac
ttyset=`stty -g`
stty -echo -icanon min 1
trap bye 2
getkey() {
read -n 1 A
echo "$A"
#echo "` stty -echo -icanon min 1 ; dd if=/dev/tty count=1 bs=1 2>/dev/null`"
}
getstr() {
stty icanon echo 2>/dev/null
read A
echo "$A"
stty -icanon -echo 2>/dev/null
}
OLINES=0
autobs() {
NLINES=`tput lines 2> /dev/null`
#echo "b "$(($NLINES*16))
#return
if [ -n "${NLINES}" -a "${OLINES}" != "${NLINES}" ]; then
LINES=${NLINES}
[ -n "${LINES}" ] && \
echo "b "$((($LINES-1)*16))
OLINES=${LINES}
fi
}
trap autobs 28
P=''
echo "b 256"
while : ; do
echo '!clear'
# autobs
case $P in
#'d') echo '!echo X | r0 -n $| rasm2 -o $OFFSET -vd -|head -n '$LINES ; ;;
d) echo d ;;
*) echo x ;;
esac
case "`getkey`" in
'j') echo "s+16" ;;
'k') echo "s-16" ;;
'J') echo "s+b" ;;
'K') echo "s-b" ;;
'h') echo "s-1" ;;
'l') echo "s+1" ;;
'q') bye ; ;;
'b') printf 'b'>/dev/tty; echo b`getstr` ;;
'w') printf 'w'>/dev/tty; echo w`getstr` ;;
'i') printf 'w'>/dev/tty; echo w`getstr` ;; ## alias to mimic r2
's') printf 's'>/dev/tty; echo s`getstr` ;;
'r') printf 'r '>/dev/tty; echo r`getstr` ;;
':') printf ': '>/dev/tty; getstr; getkey >/dev/null ; ;;
'?') echo '!clear' ; echo '?'; getkey ; ;;
'+') echo "b+1" ;;
'-') echo "b-1" ;;
'.') echo "s0" ;;
'^') echo "s0" ;;
'^') echo "s0" ;;
'$') echo 's`r`' ;;
'G') echo 's`r`' ;;
'*') echo "b+16" ;;
'/') echo "b-16" ;;
p|P) if [ -n "$P" ]; then P=''; else P=d; fi ;;
esac
done
+10 -8
View File
@@ -1,14 +1,14 @@
.Dd Sep 1, 2009
.Dt VIRED 1
.Dd Mar 7, 2021
.Dt VR0 1
.Os
.Th VIRED 1
.Th VR0 1
.Sh NAME
vired \- visual interactive raw editor
r0v \- visual radare zero
.Sh SYNOPSIS
.Nm vired
.Nm r0v
.Ar file
.Sh DESCRIPTION
Visual mode for ired(1)
Visual mode for r0(1)
.Pp
.Sh KEYS
.Bl -tag -width Fl
@@ -17,7 +17,7 @@ seek left(-1), down(+16), up(-16), right(+1)
.It +-*/
change block size (+1,-1,+16,-16)
.It :[cmd]
input ired command
input r0 command
.It b
prompt to change block size
.It s
@@ -26,6 +26,8 @@ prompt seek address
prompt for resize, remove command
.It p
change print mode
.It :
enter raw r0 command
.It ?
show help
.It q
@@ -33,7 +35,7 @@ quit program
.Pp
.Sh SEE ALSO
.Pp
.Xr ired(1)
.Xr r0(1)
.Sh AUTHORS
.PP
pancake <@nopcode.org>
-23
View File
@@ -1,23 +0,0 @@
#define VERSION "0.3"
#include "io.c"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#if(plan9)
static int setenv(char *var, char *val, int force) {
char str[128];
snprintf(str, sizeof(str), "echo %s > /env/%s", var, val);
if (system(str)<0)
perror("system");
return force;
}
#define LLF "L"
#else
#define LLF "ll"
#endif
#include "util.c"
#include "cmd.c"
+7
View File
@@ -0,0 +1,7 @@
while : ; do
rm -f r0.x86
gcc -DUSE_DISASM_X32=1 -flto -O3 r0.c -o r0.x86
strip r0.x86
ls -l r0.x86
sleep 1
done
+5
View File
@@ -0,0 +1,5 @@
all:
sh test.sh
clean:
rm -f tmp tmp.r0 tmp.ired
+5
View File
@@ -0,0 +1,5 @@
Hello world
soor
loop
is fucking awesome
and new as shit
+5
View File
@@ -0,0 +1,5 @@
Hello world
loop
soor
is fucking awesome
and new as shit
+4
View File
@@ -0,0 +1,4 @@
Hello world
sardina
is fucking awesome
and new as shit
+3
View File
@@ -0,0 +1,3 @@
Hello world
is fucking awesome
and new as shit
Executable
+53
View File
@@ -0,0 +1,53 @@
#!/bin/sh
FILES=4
jot 1 >/dev/null
if [ $? = 0 ]; then
SEQ=`jot $FILES 1 $FILES`
else
md5=`seq 1 $FILES`
fi
echo |md5sum 2>/dev/null
if [ $? = 0 ]; then
md5=md5sum
else
md5=md5
fi
hash() {
$md5 $1 | awk '{print $1}'
}
btest() {
cp $1 tmp
../r0d $1 $2 > tmp.r0
../r0 -n tmp < tmp.r0
test `hash tmp` = `hash $2`
ret=$?
echo $ret $1 $2
if [ $ret = 1 ]; then
if [ -n "`echo $1| grep file`" ]; then
diff -u $2 tmp
fi
fi
#/ rm -f tmp.r0 tmp
}
(cd .. && make -s)
if [ -n "$2" ]; then
btest $1 $2
else
for i in $SEQ ; do
for j in $SEQ ; do
btest file$i file$j
done
done
fi
#btest /etc/services /etc/fstab
#btest /bin/true /bin/false
#radiff /bin/false tmp
+54 -63
View File
@@ -1,105 +1,96 @@
/* Copyleft 2009 -- pancake /at/ nopcode /dot/ org */
/* ired - MIT - Copyleft 2009-2019 -- pancake */
#include <ctype.h>
static inline char *skipspaces(char *arg) {
while (*arg==' '||*arg=='\t') arg++;
return arg;
}
static inline void hexdump(const ut8 *buf, unsigned int len, int w) {
unsigned int i, j;
for(i=0;i<len;i+=w) {
printf("0x%08" LLF "x ", curseek+i);
printf("0x%08"LLF"x: ", curseek+i);
for(j=i;j<i+w;j++) {
if (j>=len) {
printf(j%2?" ":" ");
continue;
}
printf("%02x", buf[j]);
if (j%2) printf(" ");
}
for(j=i;j<i+w;j++) {
if (j>=len) printf(" ");
else printf("%c", isprint(buf[j])?buf[j]:'.');
if(j<len) printf(j%2?"%02x ":"%02x", buf[j]);
else printf(j%2?" ":" ");
}
printf(" ");
for(j=i;j<i+w;j++)
printf("%c", isprint(buf[j])?buf[j]:'.');
printf("\n");
}
}
static void print_fmt(const ut8 *buf, char *fmt, unsigned int len) {
unsigned int i, inc=0, lup=0, up, rep = 0;
char *ofmt = fmt;
#define u(x) ((unsigned long)(x&0xff))
static void print_fmt(const ut8 *buf, const char *fmt, unsigned int len) {
unsigned int i, up, inc = 0, lup = 0, rep = 0;
const char *ofmt = fmt;
do { /* TODO: needs cleanup */
for(;(*fmt||rep);fmt++) {
up = rep?rep:*fmt;
switch(up) {
case 'i': if (len>3) printf("%d\n", ((buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3])); inc=4; break;
case 'I': if (len>3) printf("%d\n", ((buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0])); inc=4; break;
case 's': if (len>1) printf("%d\n", (buf[0]<<8 | buf[1])); inc=2; break;
case 'S': if (len>1) printf("%d\n", (buf[1]<<8 | buf[0])); inc=2; break;
case 'o': if (len>0) printf("0%o\n", buf[0]); inc=1; break;
case 'b': if (len>0) printf("0x%02x\n", buf[0]); inc=1; break;
case 'w': if (len>1) printf("0x%02x%02x\n", buf[1], buf[0]); inc=2; break;
case 'W': if (len>1) printf("0x%02x%02x\n", buf[0], buf[1]); inc=2; break;
case 'd': if (len>3) printf("0x%02x%02x%02x%02x\n",buf[3], buf[2], buf[1], buf[0]); inc=4; break;
case 'D': if (len>3) printf("0x%02x%02x%02x%02x\n", buf[0], buf[1], buf[2], buf[3]); inc=4; break;
case 'q': if (len>7) printf("0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
case 'i': if(len>3) printf("%d\n", (int)(u(buf[0]&0xff)<<24 | (u(buf[1])<<16) | (buf[2]<<8) | buf[3])); inc=4; break;
case 'I': if(len>3) printf("%d\n", (int)((u(buf[3])<<24) | (u(buf[2])<<16) | (u(buf[1])<<8) | buf[0])); inc=4; break;
case 's': if(len>1) printf("%d\n", (buf[0]<<8 | buf[1])); inc=2; break;
case 'S': if(len>1) printf("%d\n", (buf[1]<<8 | buf[0])); inc=2; break;
case 'o': if(len>0) printf("0%o\n", buf[0]); inc=1; break;
case 'b': if(len>0) printf("0x%02x\n", buf[0]); inc=1; break;
case 'w': if(len>1) printf("0x%02x%02x\n", buf[1], buf[0]); inc=2; break;
case 'W': if(len>1) printf("0x%02x%02x\n", buf[0], buf[1]); inc=2; break;
case 'd': if(len>3) printf("0x%02x%02x%02x%02x\n",buf[3], buf[2], buf[1], buf[0]); inc=4; break;
case 'D': if(len>3) printf("0x%02x%02x%02x%02x\n", buf[0], buf[1], buf[2], buf[3]); inc=4; break;
case 'q': if(len>7) printf("0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
buf[7], buf[6], buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]); inc=8; break;
case 'Q': if (len>7) printf("0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
case 'Q': if(len>7) printf("0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); inc=8; break;
case '.': inc=1; break;
case ':': inc=4; break;
case 'z': for(i=0; inc<len && isascii(buf[0]);i++) { printf("%c", buf[0]); buf++; inc++; } if(i)printf("\n"); break;
case 'Z': for(i=0; inc<len && isascii(buf[0]);i++) { printf("%c", buf[0]); buf+=2; inc+=2; } if(i)printf("\n"); break;
case 'z': for(i=0; inc<len && isascii(buf[0]);i++) { printf(i?"%c\n":"%c", buf[0]); buf++; } inc++; break;
case 'Z': for(i=0; inc<len && isascii(buf[0]);i++) { printf(i?"%c\n":"%c", buf[0]); buf+=2; } inc+=2; break;
case '*': rep = lup; break;
default: fprintf(stderr, "Unknown format '%c' (%d)\n", up, up);
return;
}
if (!rep) lup = up;
if(!rep) lup = up;
buf += inc;
if (inc>len) break;
if(inc>len) break;
len -= inc;
}
fmt = ofmt;
} while(!rep && inc && inc <len);
} while(!rep && inc && inc<len);
}
static ut64 str2ut64(char *str) {
static ut64 str2ut64(const char *str) {
ut64 ret = 0LL;
str = skipspaces(str);
if (str[0]=='b'&&str[1]==0)
SKIPSPACES(str);
if(str[0]=='b'&&str[1]=='\0')
ret = bsize;
else if (str[0]=='0') {
if (str[1]=='x') sscanf(str, "0x%"LLF"x", &ret);
else if(str[0]=='0') {
if(str[1]=='x') sscanf(str, "0x%"LLF"x", &ret);
else sscanf(str, "0x%"LLF"o", &ret);
} else sscanf(str, "%"LLF"u", &ret);
str+=strlen(str)-1;
if (*str=='K') ret *= 1024;
else if (*str=='M') ret *= 1024*1024;
else if (*str=='G') ret *= 1024*1024*1024;
str += strlen(str)-1;
if(*str=='K') ret *= 1024;
else if(*str=='M') ret *= 1024*1024;
else if(*str=='G') ret *= 1024*1024*1024;
return ret;
}
static int hex2byte(ut8 *val, ut8 c) {
if ('0' <= c && c <= '9') *val = (ut8)(*val) * 16 + ( c - '0');
else if (c >= 'A' && c <= 'F') *val = (ut8)(*val) * 16 + ( c - 'A' + 10);
else if (c >= 'a' && c <= 'f') *val = (ut8)(*val) * 16 + ( c - 'a' + 10);
if('0' <= c && c <= '9') *val = (ut8)(*val) * 16 + ( c - '0');
else if(c >= 'A' && c <= 'F') *val = (ut8)(*val) * 16 + ( c - 'A' + 10);
else if(c >= 'a' && c <= 'f') *val = (ut8)(*val) * 16 + ( c - 'a' + 10);
else return 1;
return 0;
}
static int hexstr2raw(char *arg) {
ut8 *ptr, c = 0, d;
static unsigned int hexstr2raw(ut8 *arg) {
ut8 *ptr, d, c = 0;
unsigned int j = 0, len = 0;
for (ptr=(ut8 *)arg;*ptr;ptr++) {
if (*ptr==' ') continue;
for(ptr=(ut8 *)arg; *ptr; ptr++) {
if(*ptr==' ') continue;
d = c;
if (hex2byte(&c, *ptr))
if(hex2byte(&c, *ptr))
return -1;
c |= d;
if (!j++) c <<= 4;
else if (j==2) {
if(!j++) c <<= 4;
else if(j==2) {
arg[len++] = c;
c = j = 0;
}
@@ -107,14 +98,14 @@ static int hexstr2raw(char *arg) {
return len;
}
static void *getcurblk(char *arg, unsigned int *len) {
void *buf;
if (*arg) {
*len = (int)str2ut64(arg);
if (*len <1) *len = bsize;
static ut8 *getcurblk(const char *arg, int *len) {
ut8 *buf = NULL;
if(*arg) {
*len = (int)calc((const char *)arg);
if(*len<1) *len = bsize;
}
if ((buf = malloc(*len)) != NULL) {
if (io_seek((int)curseek, SEEK_SET)<0) {
if(*len>0 && (buf = malloc(*len)) != NULL) {
if(io_seek((int)curseek, SEEK_SET)<0) {
free(buf);
buf = NULL;
} else *len = io_read(buf, *len);
Executable
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh -x
CC="docker run --rm --volume $(pwd):$(pwd) -w $(pwd) dkulacz/gcc-v850-elf-toolchain:latest"
TOOLCHAIN_PREFIX="v850-elf-"
# FLAGS="-mv850e3v5 -mloop -mrh850-abi -mprolog-function"
FLAGS="-mv850e3v5 -mprolog-function"
FLAGS="-mprolog-function -mv850e3v5"
FLAGS="-DHAVE_FTRUNCATE=0"
$CC ${TOOLCHAIN_PREFIX}gcc ${FLAGS} ired.c -o ired_v850
# $CC ${TOOLCHAIN_PREFIX}size --format=berkeley -o ired_v850
-49
View File
@@ -1,49 +0,0 @@
#!/bin/sh
# vired: the visual raw editor
# copyleft: pancake at nopcode dot org @ 2009
if [ -n "$1" ]; then
$0 | ired -n $@
exit 0
fi
ttyset=`stty -g`
stty -echo -icanon min 1
getstr() {
stty icanon echo
read A
echo $A
stty -icanon -echo
}
P=''
echo "b 256"
while : ; do
echo "!clear"
case $P in
'd') echo '!echo X | ired -n $BLOCK | rasm2 -o $OFFSET -d -' ;;
*) echo x ;;
esac
A=`dd if=/dev/tty count=1 bs=1 2>/dev/null`
case $A in
'j') echo "s+16" ;;
'k') echo "s-16" ;;
'J') echo "s+b" ;;
'K') echo "s-b" ;;
'h') echo "s-1" ;;
'l') echo "s+1" ;;
'q') stty $ttyset; exit ;;
'b') printf 'b '>/dev/tty; echo b `getstr` ;;
'w') printf 'w '>/dev/tty; echo w `getstr` ;;
's') printf 's '>/dev/tty; echo s `getstr` ;;
'r') printf 'r '>/dev/tty; echo r `getstr` ;;
':') printf ': '>/dev/tty; echo `getstr`; read A ;;
'?') echo '?'; read A ;;
'+') echo "b+1" ;;
'-') echo "b-1" ;;
'*') echo "b+16" ;;
'/') echo "b-16" ;;
'p') if [ -n "$P" ]; then P=''; else P=d; fi ;;
esac
done