Skip to content
Open

Attasm #25028

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 10 additions & 154 deletions libr/arch/p/x86_nz/att2intel.c
Original file line number Diff line number Diff line change
@@ -1,168 +1,24 @@
/* radare - LGPL - Copyright 2011-2022 - pancake */
/* radare - LGPL - Copyright 2011-2025 - pancake */

#include <r_asm.h>

static int replace(int argc, const char *argv[], char *newstr) {
int i,j,k;
const struct {
const char *op;
const char *str;
} ops[] = {
{ "cmpl", "cmp 2, 1" },
{ "testl", "test 2, 1" },
{ "leal", "lea 2, 1" },
{ "movl", "mov 2, 1" },
{ "xorl", "xor 2, 1" },
{ "andl", "and 2, 1" },
{ "orl", "or 2, 1" },
{ "addl", "add 2, 1" },
{ "incl", "inc 1" },
{ "decl", "dec 1" },
{ "subl", "sub 2, 1" },
{ "mull", "mul 2, 1" },
{ "divl", "div 2, 1" },
{ "pushl", "push 1" },
{ "popl", "pop 1" },
{ "ret", "ret" },
{ NULL }
};

for (i = 0; ops[i].op; i++) {
if (!strcmp (ops[i].op, argv[0])) {
if (newstr) {
for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
if (ops[i].str[j] >= '0' && ops[i].str[j] <= '9') {
const char *w = argv[ops[i].str[j] - '0'];
if (w) {
strcpy (newstr + k, w);
k += strlen (w) - 1;
}
} else {
newstr[k] = ops[i].str[j];
}
}
newstr[k]='\0';
}
return true;
}
}

/* TODO: this is slow */
if (newstr) {
newstr[0] = '\0';
for (i = 0; i < argc; i++) {
strcat (newstr, argv[i]);
strcat (newstr, (i == 0 || i== argc - 1)?" ":",");
}
}

return false;
}
// x86-specific AT&T to Intel parser plugin
// Uses the x86-specific r_str_att2intel() from libr/util/str_att.c
// This plugin is used as a pseudo-disassembler parser to convert AT&T output to Intel

static char *parse(RAsmPluginSession *aps, const char *data) {
char w0[32], w1[32], w2[32], w3[32];
char *optr, *num;
int i, n;

// malloc can be slow here :?
char *buf = strdup (data);
if (!buf) {
return NULL;
}
r_str_trim_head (buf);

char *ptr = strchr (buf, '#');
if (ptr) {
*ptr = 0;
r_str_trim (buf);
}
if (*buf == '.' || buf[strlen(buf)-1] == ':') {
free (buf);
return strdup (data);
}
r_str_replace_char (buf, '$', 0);
r_str_replace_char (buf, '%', 0);
r_str_replace_char (buf, '\t', ' ');
r_str_replace_char (buf, '(', '[');
r_str_replace_char (buf, ')', ']');
ptr = strchr (buf, '[');
if (ptr) {
*ptr = 0;
num = (char*)r_str_lchr (buf, ' ');
if (!num) {
num = (char *)r_str_lchr (buf, ',');
}
if (num) {
n = atoi (num + 1);
*ptr = '[';
r_str_cpy (num + 1, ptr);
ptr = (char*)r_str_lchr (buf, ']');
if (n && ptr) {
char *rest = strdup (ptr+1);
size_t dist = strlen (data) + 1 - (ptr - buf);
snprintf (ptr, dist, "%+d]%s", n, rest);
free (rest);
}
} else {
*ptr = '[';
}
}
char *str = NULL;
if (*buf) {
*w0 = *w1 = *w2 = *w3 = 0;
ptr = strchr (buf, ' ');
if (!ptr) {
ptr = strchr (buf, '\t');
}
if (ptr) {
*ptr = '\0';
for (ptr++; *ptr == ' '; ptr++) {
;
}
strncpy (w0, buf, sizeof (w0) - 1);
strncpy (w1, ptr, sizeof (w1) - 1);
return r_str_att2intel (data);
}

optr = ptr;
ptr = strchr (ptr, ',');
if (ptr) {
*ptr = '\0';
for (ptr++; *ptr == ' '; ptr++) {
;
}
strncpy (w1, optr, sizeof (w1)-1);
strncpy (w2, ptr, sizeof (w2)-1);
ptr = strchr (ptr, ',');
if (ptr) {
*ptr = '\0';
for (ptr++; *ptr == ' '; ptr++) {
;
}
strncpy (w2, optr, sizeof (w2)-1);
strncpy (w3, ptr, sizeof (w3)-1);
}
}
}
{
const char *wa[] = { w0, w1, w2, w3 };
int nw = 0;
for (i = 0; i < 4; i++) {
if (wa[i][0] != '\0') {
nw++;
}
}
str = malloc (strlen (data) + 128);
strcpy (str, data);
replace (nw, wa, str);
}
}
free (buf);
return str;
// Public API wrapper for backwards compatibility
R_API char *r_asm_att2intel(const char *att_str) {
return r_str_att2intel (att_str);
}

RAsmPlugin r_asm_plugin_att2intel = {
.meta = {
.name = "att2intel",
.desc = "X86 att 2 intel plugin",
.desc = "AT&T to Intel syntax converter",
.author = "pancake",
.license = "LGPL-3.0-only",
},
Expand Down
22 changes: 22 additions & 0 deletions libr/asm/asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,28 @@ static int r_asm_assemble_single(RAsm *a, RAnalOp *op, const char *buf) {
if (!b) {
return 0;
}
// convert AT&T syntax to Intel if needed, but only if the encoder doesn't support ATT natively
// The r_str_att2intel function is x86-specific, so only use it for x86 architectures
if (a->config->syntax == R_ARCH_SYNTAX_ATT) {
const char *arch = R_UNWRAP3 (a, config, arch);
// Get the encoder plugin to check its syntax support
RArchSession *as = R_UNWRAP4 (a, analb.anal, arch, session);
RArchPlugin *encoder_plugin = NULL;
if (as) {
// If encoder is separate, use that
encoder_plugin = as->encoder ? as->encoder->plugin : as->plugin;
}
// Check if encoder supports ATT syntax natively
bool encoder_supports_att = encoder_plugin && (encoder_plugin->encode_syntax & R_ARCH_SYNTAX_MASK_ATT);
// Only convert for x86 if encoder doesn't support ATT natively
if (!encoder_supports_att && arch && r_str_startswith (arch, "x86")) {
char *intel = r_str_att2intel (b);
if (intel) {
free (b);
b = intel;
}
}
}
r_str_case (b, false); // to-lower
if (a->analb.anal) {
ut8 buf[256] = { 0 };
Expand Down
6 changes: 6 additions & 0 deletions libr/include/r_arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ typedef bool (*RArchPluginInitCallback)(RArchSession *s);
typedef bool (*RArchPluginFiniCallback)(RArchSession *s);
typedef bool (*RArchPluginEsilCallback)(RArchSession *s, RArchEsilAction action);

// Bitmask for supported syntax modes in arch plugins
#define R_ARCH_SYNTAX_MASK_INTEL (1 << R_ARCH_SYNTAX_INTEL)
#define R_ARCH_SYNTAX_MASK_ATT (1 << R_ARCH_SYNTAX_ATT)
#define R_ARCH_SYNTAX_MASK_MASM (1 << R_ARCH_SYNTAX_MASM)

// TODO: use `const char *const` instead of `char*`
typedef struct r_arch_plugin_t {
RPluginMeta meta;
Expand All @@ -161,6 +166,7 @@ typedef struct r_arch_plugin_t {
ut32 endian;
RSysBits bits;
RSysBits addr_bits;
ut32 encode_syntax; // bitmask of R_ARCH_SYNTAX_MASK_* for encoder-supported syntaxes (0 = Intel only, default)

const RArchPluginInitCallback init;
const RArchPluginFiniCallback fini;
Expand Down
1 change: 1 addition & 0 deletions libr/include/r_asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ R_API bool r_asm_set_big_endian(RAsm *a, bool big_endian);

R_API bool r_asm_set_syntax(RAsm *a, int syntax); // This is in RArchConfig
R_API int r_asm_syntax_from_string(const char *name);
R_API char *r_asm_att2intel(const char *att_str); // Convert AT&T to Intel syntax
R_API int r_asm_set_pc(RAsm *a, ut64 pc);
R_API int r_asm_disassemble(RAsm *a, RAnalOp *op, const ut8 *buf, int len);
R_API RAsmCode* r_asm_mdisassemble(RAsm *a, const ut8 *buf, int len);
Expand Down
2 changes: 2 additions & 0 deletions libr/include/r_util/r_str.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,8 @@ R_API void r_string_appendf(RString *a, const char * R_NONNULL fmt, ...);
R_API char *r_str_pseudo_transform(const char **rules, const char *asm_str);
R_API char *r_str_pseudo_subvar(char *pseudo, void *varmap);

// AT&T to Intel syntax conversion
R_API char *r_str_att2intel(const char *att_str);

#ifdef __cplusplus
}
Expand Down
2 changes: 1 addition & 1 deletion libr/util/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ OBJS+=udiff.o bdiff.o stack.o queue.o tree.o idpool.o assert.o bplist.o treemap.
OBJS+=punycode.o pkcs7.o x509.o asn1.o asn1_str.o json_parser.o json_indent.o skiplist.o
OBJS+=pj.o rbtree.o intervaltree.o qrcode.o vector.o str_constpool.o str_trim.o
OBJS+=chartable.o protobuf.o graph_drawable.o axml.o sstext.o new_rbtree.o token.o
OBJS+=rvc.o rvc_git.o rvc_rvc.o bscanf.o rprintf.o base32.o bloom.o mmap.o rxmldom.o
OBJS+=rvc.o rvc_git.o rvc_rvc.o bscanf.o rprintf.o base32.o bloom.o mmap.o rxmldom.o str_att.o

ifeq (${HAVE_GPERF},1)
OBJS+=d/ascii.o
Expand Down
1 change: 1 addition & 0 deletions libr/util/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ r_util_sources = [
'str_pseudo.c',
'str_strip.c',
'str_trim.c',
'str_att.c',
'str.c',
'strbuf.c',
'strpool.c',
Expand Down
Loading
Loading