Implement ppc assembler plugin ##port ##refactor (#17923)

* implement ppc assembler plugin
* reuse code
* update .travis.yml & Dockerfile
* support arm.as big endian
This commit is contained in:
Liumeo 2020-11-20 06:20:14 -05:00 committed by GitHub
parent 14d3728e62
commit c83d0e0c5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 286 additions and 193 deletions

View File

@ -31,18 +31,20 @@ jobs:
name: PPC64
arch: ppc64le
dist: bionic
env: NODOCKER=1 COMPILER_NAME=gcc CXX=g++ CC=gcc CFLAGS="-DR2_ASSERT_STDOUT=1" R2_X86AS=x86_64-linux-gnu-as
env: NODOCKER=1 COMPILER_NAME=gcc CXX=g++ CC=gcc CFLAGS="-DR2_ASSERT_STDOUT=1" R2_ARM64_AS=aarch64-linux-gnu-as R2_ARM32_AS=arm-linux-gnueabi-as R2_X86_AS=x86_64-linux-gnu-as
addons:
apt:
packages:
- gcc-x86-64-linux-gnu
- binutils-aarch64-linux-gnu
- binutils-arm-linux-gnueabi
- binutils-x86-64-linux-gnu
# Linux with GCC on System Z
- if: (branch = master AND type = push) OR head_branch =~ ^s390x-*
os: linux
name: S390X
arch: s390x
dist: bionic
env: NODOCKER=1 COMPILER_NAME=gcc CXX=g++ CC=gcc CFLAGS="-DR2_ASSERT_STDOUT=1" R2_X86AS=x86_64-w64-mingw32-as
env: NODOCKER=1 COMPILER_NAME=gcc CXX=g++ CC=gcc CFLAGS="-DR2_ASSERT_STDOUT=1" R2_X86_AS=x86_64-w64-mingw32-as
addons:
apt:
packages:
@ -53,11 +55,13 @@ jobs:
name: ARM64
arch: arm64
dist: bionic
env: NODOCKER=1 COMPILER_NAME=gcc CXX=g++ CC=gcc CFLAGS="-DR2_ASSERT_STDOUT=1" R2_X86AS=x86_64-linux-gnu-as
env: NODOCKER=1 COMPILER_NAME=gcc CXX=g++ CC=gcc CFLAGS="-DR2_ASSERT_STDOUT=1" R2_ARM32_AS=arm-linux-gnueabi-as R2_X86_AS=x86_64-linux-gnu-as R2_PPC_AS=powerpc64le-linux-gnu-as
addons:
apt:
packages:
- gcc-x86-64-linux-gnu
- binutils-arm-linux-gnueabi
- binutils-x86-64-linux-gnu
- binutils-powerpc64le-linux-gnu
# Run Fuzzing Sanity Test on every push
# XXX its broken it complains about invalid key
#- os: linux
@ -92,15 +96,17 @@ jobs:
# Linux with GCC on PowerPC
- os: linux
arch: ppc64le
env: NODOCKER=1 COMPILER_NAME=gcc CXX=g++ CC=gcc CFLAGS="-DR2_ASSERT_STDOUT=1" R2_X86AS=x86_64-linux-gnu-as
env: NODOCKER=1 COMPILER_NAME=gcc CXX=g++ CC=gcc CFLAGS="-DR2_ASSERT_STDOUT=1" R2_ARM64_AS=aarch64-linux-gnu-as R2_ARM32_AS=arm-linux-gnueabi-as R2_X86_AS=x86_64-linux-gnu-as
addons:
apt:
packages:
- gcc-x86-64-linux-gnu
- binutils-aarch64-linux-gnu
- binutils-arm-linux-gnueabi
- binutils-x86-64-linux-gnu
# Linux with GCC on System Z
- os: linux
arch: s390x
env: NODOCKER=1 COMPILER_NAME=gcc CXX=g++ CC=gcc CFLAGS="-DR2_ASSERT_STDOUT=1" R2_X86AS=x86_64-w64-mingw32-as
env: NODOCKER=1 COMPILER_NAME=gcc CXX=g++ CC=gcc CFLAGS="-DR2_ASSERT_STDOUT=1" R2_X86_AS=x86_64-w64-mingw32-as
addons:
apt:
packages:

View File

@ -5,6 +5,8 @@
#
# Build docker image with:
# $ docker build -t r2docker:latest .
# To enable rasm2 plugins based on binutils, pass '--build-arg with_ARCH_as=1' to the build command.
# Supported ARCHs are arm32, arm64, ppc. Each ARCH should be passed in a separate '--build-arg'.
#
# Run the docker image:
# $ docker images
@ -39,6 +41,10 @@ ARG R2_VERSION=master
# R2pipe python version
ARG R2_PIPE_PY_VERSION=1.4.2
ARG with_arm32_as
ARG with_arm64_as
ARG with_ppc_as
ENV R2_VERSION ${R2_VERSION}
ENV R2_PIPE_PY_VERSION ${R2_PIPE_PY_VERSION}
@ -69,7 +75,10 @@ RUN DEBIAN_FRONTEND=noninteractive dpkg --add-architecture i386 && \
libncurses5:i386 \
libstdc++6:i386 \
gnupg2 \
python-pip && \
python-pip \
${with_arm64_as:+binutils-aarch64-linux-gnu} \
${with_arm32_as:+binutils-arm-linux-gnueabi} \
${with_ppc_as:+binutils-powerpc64le-linux-gnu} && \
pip install r2pipe=="$R2_PIPE_PY_VERSION" && \
cd /mnt && \
git clone -b "$R2_VERSION" -q --depth 1 https://github.com/radareorg/radare2.git && \
@ -85,6 +94,10 @@ RUN DEBIAN_FRONTEND=noninteractive dpkg --add-architecture i386 && \
apt-get autoremove --purge -y && \
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
ENV R2_ARM64_AS=${with_arm64_as:+aarch64-linux-gnu-as}
ENV R2_ARM32_AS=${with_arm32_as:+arm-linux-gnueabi-as}
ENV R2_PPC_AS=${with_ppc_as:+powerpc64le-linux-gnu-as}
# Create non-root user
RUN useradd -m r2 && \
adduser r2 sudo && \

View File

@ -30,7 +30,7 @@ plugins: ${LIBSO} ${LIBAR}
include ${STATIC_ASM_PLUGINS}
STATIC_OBJS=$(subst ..,p/..,$(subst asm_,p/asm_,$(STATIC_OBJ)))
OBJS=${STATIC_OBJS} asm.o acode.o aop.o
OBJS=${STATIC_OBJS} asm.o acode.o aop.o binutils_as.o
OBJS+=${SHARED2_OBJ}
include $(TOP)/libr/rules.mk

88
libr/asm/binutils_as.c Normal file
View File

@ -0,0 +1,88 @@
/* radare - LGPL - Copyright 2009-2020 - pancake, eagleoflqj */
#include "binutils_as.h"
int binutils_assemble(RAsm *a, RAsmOp *op, const char *buf, const char *as, const char *env, const char *header, const char *cmd_opt) {
char *user_as = r_sys_getenv (env);
if (user_as) {
as = user_as;
}
if (R_STR_ISEMPTY (as)) {
eprintf ("Please set %s env to define a %s assembler program\n", env, a->cur->arch);
return 1;
}
char *ipath, *opath;
int ifd = r_file_mkstemp ("r_as", &ipath);
if (ifd == -1) {
free (user_as);
return -1;
}
int ofd = r_file_mkstemp ("r_as", &opath);
if (ofd == -1) {
free (user_as);
free (ipath);
close (ifd);
return -1;
}
int res = -1;
char *asm_buf = r_str_newf ("%s"
".ascii \" BEGINMARK\"\n" // 4 bit align
"%s\n"
".ascii \"ENDMARK\"\n",
header, buf);
if (!asm_buf) {
goto beach;
}
const size_t asm_buf_len = strlen (asm_buf);
const bool success = write (ifd, asm_buf, asm_buf_len) == asm_buf_len;
free (asm_buf);
if (!success) {
goto beach;
}
char cmd[4096];
snprintf (cmd, sizeof(cmd), "%s %s %s -o %s", as, cmd_opt, ipath, opath);
if (!r_sys_cmd (cmd)) {
int len = 0;
const ut8 *begin, *end;
close (ofd);
ofd = r_sandbox_open (opath, O_BINARY | O_RDONLY, 0644);
if (ofd < 0) {
goto skip_ofd;
}
ut8 obuf[4096];
len = read (ofd, obuf, sizeof (obuf));
begin = r_mem_mem (obuf, len, (const ut8*)"BEGINMARK", 9);
end = r_mem_mem (obuf, len, (const ut8*)"ENDMARK", 7);
if (!begin || !end) {
eprintf ("Cannot find water marks\n");
len = 0;
} else {
len = (int)(size_t)(end - begin - 9);
if (len > 0) {
r_strbuf_setbin (&op->buf, begin + 9, len);
} else {
len = 0;
}
}
res = op->size = len;
} else {
eprintf ("Error running: %s", cmd);
}
beach:
close (ofd);
skip_ofd:
close (ifd);
unlink (ipath);
unlink (opath);
free (ipath);
free (opath);
free (user_as);
return res;
}

9
libr/asm/binutils_as.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef BINUTILS_AS_H
#define BINUTILS_AS_H
#include <r_types.h>
#include <r_asm.h>
int binutils_assemble(RAsm *a, RAsmOp *op, const char *buf, const char *as, const char *env, const char *header, const char *cmd_opt);
#endif

View File

@ -2,6 +2,7 @@ r_asm_sources = [
'asm.c',
'aop.c',
'acode.c',
'binutils_as.c',
'p/asm_6502.c',
'p/asm_6502_cs.c',
'p/asm_8051.c',
@ -42,6 +43,7 @@ r_asm_sources = [
'p/asm_or1k.c',
'p/asm_pic.c',
'p/asm_mcore.c',
'p/asm_ppc_as.c',
'p/asm_ppc_cs.c',
'p/asm_ppc_gnu.c',
'p/asm_propeller.c',

View File

@ -19,7 +19,7 @@ ALL_TARGETS=
# TODO: rename to enabled plugins
ARCHS=mips_gnu.mk x86_cs.mk sparc_cs.mk sparc_gnu.mk java.mk bf.mk arm_gnu.mk dalvik.mk
ARCHS+=x86_as.mk x86_nz.mk cris_gnu.mk vax.mk
ARCHS+=ppc_gnu.mk ppc_cs.mk xap.mk x86_nasm.mk avr.mk
ARCHS+=ppc_gnu.mk ppc_as.mk ppc_cs.mk xap.mk x86_nasm.mk avr.mk
ARCHS+=sh.mk arm_winedbg.mk tms320.mk gb.mk snes.mk ebc.mk malbolge.mk ws.mk
ARCHS+=6502.mk h8300.mk cr16.mk v850.mk propeller.mk msp430.mk i4004.mk
ARCHS+=lh5801.mk v810.mk mcs96.mk lm32.mk

View File

@ -1,116 +1,39 @@
/* radare - LGPL - Copyright 2015-2020 pancake */
#include <r_types.h>
#include <r_util.h>
#include <r_lib.h>
#include <r_asm.h>
#include "../binutils_as.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
// USE ARM_AS environment variable
#define ARM32_AS "arm-linux-androideabi-as"
#define ARM64_AS "aarch64-linux-android-as"
// toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-arm_64/bin/
// toolchains/aarch64-linux-android-4.9/prebuilt/darwin-arm_64/bin/
#define ASSEMBLER32 "R2_ARM32_AS"
#define ASSEMBLER64 "R2_ARM64_AS"
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
const char *bitconfig = "";
char *ipath, *opath;
char *as = NULL;
int ifd = r_file_mkstemp ("r_as", &ipath);
if (ifd == -1) {
return -1;
int bits = a->bits;
char *as = "";
#if __arm__
if (bits <= 32) {
as = "as";
}
int ofd = r_file_mkstemp ("r_as", &opath);
if (ofd == -1) {
free (ipath);
return -1;
#elif __aarch64__
if (bits == 64) {
as = "as";
}
as = r_sys_getenv ("ARM_AS");
if (!as || !*as) {
free (as);
if (a->bits == 64) {
as = strdup (ARM64_AS);
} else {
as = strdup (ARM32_AS);
}
}
if (a->bits == 16) {
bitconfig = ".thumb";
}
char *asm_buf = r_str_newf ("%s\n" //.org 0x%"PFMT64x"\n"
".ascii \"BEGINMARK\"\n"
"%s\n"
".ascii \"ENDMARK\"\n",
bitconfig, buf); // a->pc ??
if (asm_buf) {
const size_t asm_buf_len = strlen (asm_buf);
const bool success = write (ifd, asm_buf, asm_buf_len) != asm_buf_len;
(void)close (ifd);
free (asm_buf);
if (!success) {
free (as);
free (ipath);
free (opath);
return -1;
}
}
int len = 0;
if (!r_sys_cmdf ("%s %s -o %s", as, ipath, opath)) {
const ut8 *begin, *end;
close (ofd);
ofd = r_sandbox_open (opath, O_BINARY|O_RDONLY, 0644);
if (ofd < 0) {
free (as);
free (ipath);
free (opath);
return -1;
}
ut8 buf[4096];
len = read (ofd, buf, sizeof (buf));
begin = r_mem_mem (buf, len, (const ut8*)"BEGINMARK", 9);
end = r_mem_mem (buf, len, (const ut8*)"ENDMARK", 7);
if (!begin || !end) {
eprintf ("Cannot find water marks\n");
len = 0;
} else {
len = (int)(size_t)(end - begin - 9);
if (len > 0) {
r_strbuf_setbin (&op->buf, begin + 9, len);
} else {
len = 0;
}
}
} else {
eprintf ("Error running: %s %s -o %s", as, ipath, opath);
eprintf ("export PATH=~/NDK/toolchains/arm-linux*/prebuilt/darwin-arm_64/bin\n");
}
close (ofd);
unlink (ipath);
unlink (opath);
free (ipath);
free (opath);
free (as);
return op->size = len;
#endif
char cmd_opt[4096];
snprintf (cmd_opt, sizeof (cmd_opt), "%s %s",
bits == 16 ? "-mthumb" : "",
a->big_endian ? "-EB" : "-EL");
return binutils_assemble (a, op, buf, as,
bits == 64 ? ASSEMBLER64 : ASSEMBLER32,
bits <= 32 ? ".syntax unified\n" : "", cmd_opt);
}
RAsmPlugin r_asm_plugin_arm_as = {
.name = "arm.as",
.desc = "as ARM Assembler (use ARM_AS environment)",
.desc = "as ARM Assembler (use "ASSEMBLER32" and "ASSEMBLER64" environment)",
.arch = "arm",
.author = "pancake",
.license = "LGPL3",
.bits = 16|32|64,
.bits = 16 | 32 | 64,
.endian = R_SYS_ENDIAN_LITTLE | R_SYS_ENDIAN_BIG,
.assemble = &assemble,
};

38
libr/asm/p/asm_ppc_as.c Normal file
View File

@ -0,0 +1,38 @@
/* radare - LGPL - Copyright 2020 eagleoflqj */
#include <r_lib.h>
#include "../binutils_as.h"
#define ASSEMBLER "R2_PPC_AS"
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
#if __powerpc__
char *as = "as";
#else
char *as = "";
#endif
char cmd_opt[4096];
snprintf (cmd_opt, sizeof (cmd_opt), "-mregnames -a%d %s",
a->bits, a->big_endian ? "-be" : "-le");
return binutils_assemble (a, op, buf,
as, ASSEMBLER, "", cmd_opt);
}
RAsmPlugin r_asm_plugin_ppc_as = {
.name = "ppc.as",
.desc = "as PPC Assembler (use "ASSEMBLER" environment)",
.arch = "ppc",
.author = "eagleoflqj",
.license = "LGPL3",
.bits = 32 | 64,
.endian = R_SYS_ENDIAN_LITTLE | R_SYS_ENDIAN_BIG,
.assemble = &assemble,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_ppc_as,
.version = R2_VERSION
};
#endif

View File

@ -1,25 +1,17 @@
/* radare - LGPL - Copyright 2011-2020 pancake */
#include <r_lib.h>
#include <r_asm.h>
#include "../binutils_as.h"
#define ASSEMBLER "R2_X86_AS"
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
char *ipath, *opath;
#if __i386__ || __x86_64__
const char *as = "as";
#else
const char *as = "";
#endif
const char *syntaxstr = "";
int len = 0;
int ifd = r_file_mkstemp ("r_as", &ipath);
if (ifd == -1) {
return -1;
}
int ofd = r_file_mkstemp ("r_as", &opath);
if (ofd == -1) {
free (ipath);
close (ifd);
return -1;
}
switch (a->syntax) {
case R_ASM_SYNTAX_INTEL:
syntaxstr = ".intel_syntax noprefix\n";
@ -29,78 +21,15 @@ static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
break;
}
char *asm_buf = r_str_newf (
"%s.code%i\n" //.org 0x%"PFMT64x"\n"
".ascii \"BEGINMARK\"\n"
"%s\n"
".ascii \"ENDMARK\"\n",
syntaxstr, a->bits, buf); // a->pc ??
const size_t asm_buf_len = strlen (asm_buf);
const bool success = write (ifd, asm_buf, asm_buf_len) == asm_buf_len;
close (ifd);
free (asm_buf);
if (!success) {
return -1;
}
#if __i386__ || __x86_64__
const char *x86as = "as";
#else
const char *x86as = "";
#endif
char *user_ass = r_sys_getenv ("R2_X86AS");
if (user_ass) {
x86as = user_ass;
}
if (R_STR_ISEMPTY (x86as)) {
eprintf ("Please set R2_X86AS env to define an x86 assembler program\n");
return 1;
}
bool res = r_sys_cmdf ("%s %s -o %s", x86as, ipath, opath);
free (user_ass);
if (!res) {
const ut8 *begin, *end;
close (ofd);
// r_sys_cmdf ("cat %s", opath);
ofd = r_sandbox_open (opath, O_BINARY | O_RDONLY, 0644);
if (ofd < 0) {
free (ipath);
free (opath);
return -1;
}
ut8 opbuf[512] = {0};
len = read (ofd, opbuf, sizeof (opbuf));
begin = r_mem_mem (opbuf, len, (const ut8*)"BEGINMARK", 9);
end = r_mem_mem (opbuf, len, (const ut8*)"ENDMARK", 7);
if (!begin || !end) {
eprintf ("Cannot find water marks\n");
len = 0;
} else {
len = (int)(size_t)(end - begin - 9);
if (len > 0) {
r_asm_op_set_buf (op, begin + 9, len);
} else {
len = 0;
}
}
} else {
eprintf ("Error running: as %s -o %s", ipath, opath);
len = 0;
}
close (ofd);
unlink (ipath);
unlink (opath);
free (ipath);
free (opath);
op->size = len;
return len;
char header[4096];
snprintf (header, sizeof (header), "%s.code%i\n", // .org 0x%"PFMT64x"\n"
syntaxstr, a->bits);
return binutils_assemble (a, op, buf, as, ASSEMBLER, header, "");
}
RAsmPlugin r_asm_plugin_x86_as = {
.name = "x86.as",
.desc = "Intel X86 GNU Assembler (Use R2_X86AS env)",
.desc = "Intel X86 GNU Assembler (Use "ASSEMBLER" env)",
.arch = "x86",
.license = "LGPL3",
// NOTE: 64bits is not supported on OSX's nasm :(

12
libr/asm/p/ppc_as.mk Normal file
View File

@ -0,0 +1,12 @@
OBJ_PPC_AS=asm_ppc_as.o
STATIC_OBJ+=${OBJ_PPC_AS}
TARGET_PPC_AS=asm_ppc_as.${EXT_SO}
ifeq ($(WITHPIC),1)
ALL_TARGETS+=${TARGET_PPC_AS}
${TARGET_PPC_AS}: ${OBJ_PPC_AS}
${CC} $(call libname,asm_ppc_as) ${LDFLAGS} ${CFLAGS} \
-o ${TARGET_PPC_AS} ${OBJ_PPC_AS}
endif

View File

@ -239,6 +239,7 @@ extern RAsmPlugin r_asm_plugin_msp430;
extern RAsmPlugin r_asm_plugin_nios2;
extern RAsmPlugin r_asm_plugin_or1k;
extern RAsmPlugin r_asm_plugin_pic;
extern RAsmPlugin r_asm_plugin_ppc_as;
extern RAsmPlugin r_asm_plugin_ppc_cs;
extern RAsmPlugin r_asm_plugin_ppc_gnu;
extern RAsmPlugin r_asm_plugin_propeller;

View File

@ -93,6 +93,7 @@ asm_plugins = [
'nios2',
'or1k',
'pic',
'ppc_as',
'ppc_cs',
'ppc_gnu',
'propeller',

View File

@ -88,6 +88,7 @@ asm.mips_gnu
asm.msp430
asm.nios2
asm.or1k
asm.ppc_as
asm.ppc_cs
asm.ppc_gnu
asm.propeller

View File

@ -566,3 +566,73 @@ EXPECT=<<EOF
0x0000000c 2 e031 cmp/eq r14, r1
EOF
RUN
NAME=rasm2 -a ppc.as -b 64 "std r31, -8(r1)"
FILE=-
BROKEN=1
CMDS=!rasm2 -a ppc.as -b 64 "std r31, -8(r1)"
EXPECT=<<EOF
f8ffe1fb
EOF
RUN
NAME=rasm2 -a ppc -b 64 -d f8ffe1fb
FILE=-
CMDS=!rasm2 -a ppc -b 64 -d f8ffe1fb
EXPECT=<<EOF
std r31, -8(r1)
EOF
RUN
NAME=rasm2 -a ppc.as -b 32 -e "mr r10, r4"
FILE=-
BROKEN=1
CMDS=!rasm2 -a ppc.as -b 32 -e "mr r10, r4"
EXPECT=<<EOF
7c8a2378
EOF
RUN
NAME=rasm2 -a ppc -b 32 -d 78238a7c
FILE=-
CMDS=!rasm2 -a ppc -b 32 -d 78238a7c
EXPECT=<<EOF
mr r10, r4
EOF
RUN
NAME=rasm2 -a arm.as -b 16 "wfe"
FILE=-
BROKEN=1
CMDS=!rasm2 -a arm.as -b 16 "wfe"
EXPECT=<<EOF
20bf
EOF
RUN
NAME=rasm2 -a arm.as -b 32 "add fp, sp, 0"
FILE=-
BROKEN=1
CMDS=!rasm2 -a arm.as -b 32 "add fp, sp, 0"
EXPECT=<<EOF
00b08de2
EOF
RUN
NAME=rasm2 -a arm.as -b 32 -e "ldr fp, [sp], 4"
FILE=-
BROKEN=1
CMDS=!rasm2 -a arm.as -b 32 -e "ldr fp, [sp], 4"
EXPECT=<<EOF
e49db004
EOF
RUN
NAME=rasm2 -a arm.as -b 64 "sub sp, sp, 16"
FILE=-
BROKEN=1
CMDS=!rasm2 -a arm.as -b 64 "sub sp, sp, 16"
EXPECT=<<EOF
ff4300d1
EOF
RUN