Set asm.cpu for mips.gnu derived from the ISA defined in the ELF ##bin (#17555)

This commit is contained in:
junchao-loongson 2020-09-21 22:58:07 +08:00 committed by GitHub
parent 61a1e15af5
commit ca9b6ac1a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 156 additions and 19 deletions

View File

@ -326,9 +326,9 @@ struct mips_abi_choice
struct mips_abi_choice mips_abi_choices[] =
{
{ "numeric", mips_gpr_names_numeric, mips_fpr_names_numeric },
{ "32", mips_gpr_names_oldabi, mips_fpr_names_32 },
{ "o32", mips_gpr_names_oldabi, mips_fpr_names_32 },
{ "n32", mips_gpr_names_newabi, mips_fpr_names_n32 },
{ "64", mips_gpr_names_newabi, mips_fpr_names_64 },
{ "n64", mips_gpr_names_newabi, mips_fpr_names_64 },
};
struct mips_arch_choice
@ -620,6 +620,16 @@ parse_mips_dis_option (const char *option, unsigned int len)
val = option + (optionlen + 1);
vallen = len - (optionlen + 1);
if (strlen ("abi") == optionlen
&& !strncmp ("abi", option, optionlen)) {
chosen_abi = choose_abi_by_name (val, vallen);
if (chosen_abi) {
mips_gpr_names = chosen_abi->gpr_names;
mips_fpr_names = chosen_abi->fpr_names;
}
return;
}
if (strncmp ("gpr-names", option, optionlen) == 0
&& strlen ("gpr-names") == optionlen)
{

View File

@ -17,8 +17,10 @@ static int mips_mode = 0;
static unsigned long Offset = 0;
static RStrBuf *buf_global = NULL;
static unsigned char bytes[4];
static char *pre_cpu = NULL;
static char *pre_features = NULL;
static int mips_buffer_read_memory (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length, struct disassemble_info *info) {
static int mips_buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, unsigned int length, struct disassemble_info *info) {
memcpy (myaddr, bytes, length);
return 0;
}
@ -43,8 +45,37 @@ static int disassemble(struct r_asm_t *a, struct r_asm_op_t *op, const ut8 *buf,
Offset = a->pc;
memcpy (bytes, buf, 4); // TODO handle thumb
if ((a->cpu != pre_cpu) && (a->features != pre_features)) {
free (disasm_obj.disassembler_options);
memset (&disasm_obj, '\0', sizeof (struct disassemble_info));
}
/* prepare disassembler */
memset (&disasm_obj,'\0', sizeof (struct disassemble_info));
if (a->cpu && (!pre_cpu || !strcmp(a->cpu, pre_cpu))) {
if (!r_str_casecmp (a->cpu, "mips64r2")) {
disasm_obj.mach = bfd_mach_mipsisa64r2;
} else if (!r_str_casecmp (a->cpu, "mips32r2")) {
disasm_obj.mach = bfd_mach_mipsisa32r2;
} else if (!r_str_casecmp (a->cpu, "mips64")) {
disasm_obj.mach = bfd_mach_mipsisa64;
} else if (!r_str_casecmp (a->cpu, "mips32")) {
disasm_obj.mach = bfd_mach_mipsisa32;
}
pre_cpu = r_str_dup (pre_cpu, a->cpu);
}
if (a->features && (!pre_features || !strcmp (a->features, pre_features))) {
free (disasm_obj.disassembler_options);
if (strstr (a->features, "n64")) {
disasm_obj.disassembler_options = r_str_new ("abi=n64");
} else if (strstr (a->features, "n32")) {
disasm_obj.disassembler_options = r_str_new ("abi=n32");
} else if (strstr (a->features, "o32")) {
disasm_obj.disassembler_options = r_str_new ("abi=o32");
}
pre_features = r_str_dup (pre_features, a->features);
}
mips_mode = a->bits;
disasm_obj.arch = CPU_LOONGSON_2F;
disasm_obj.buffer = bytes;
@ -57,7 +88,6 @@ static int disassemble(struct r_asm_t *a, struct r_asm_op_t *op, const ut8 *buf,
disasm_obj.endian = !a->big_endian;
disasm_obj.fprintf_func = &generic_fprintf_func;
disasm_obj.stream = stdout;
op->size = (disasm_obj.endian == BFD_ENDIAN_LITTLE)
? print_insn_little_mips ((bfd_vma)Offset, &disasm_obj)
: print_insn_big_mips ((bfd_vma)Offset, &disasm_obj);

View File

@ -1068,8 +1068,9 @@ R_API void r_bin_list_archs(RBin *bin, int mode) {
pj_ki (pj, "bits", bits);
pj_kn (pj, "offset", boffset);
pj_kn (pj, "size", obj_size);
if (!strcmp (arch, "mips") && h_flag) {
pj_ks (pj, "isa", h_flag);
if (!strcmp (arch, "mips")) {
pj_ks (pj, "isa", info->cpu);
pj_ks (pj, "features", info->features);
}
if (machine) {
pj_ks (pj, "machine", machine);
@ -1078,7 +1079,7 @@ R_API void r_bin_list_archs(RBin *bin, int mode) {
break;
default:
str_fmt = h_flag && strcmp (h_flag, "unknown_flag")? sdb_fmt ("%s_%i %s", arch, bits, h_flag) \
: sdb_fmt ("%s_%i", arch, bits);
: sdb_fmt ("%s_%i", arch, bits);
r_table_add_rowf (table, "nXnss", i, boffset, obj_size, str_fmt , machine);
bin->cb_printf ("%s\n", r_table_tostring(table));
}
@ -1099,8 +1100,9 @@ R_API void r_bin_list_archs(RBin *bin, int mode) {
pj_ki (pj, "bits", bits);
pj_kn (pj, "offset", boffset);
pj_kn (pj, "size", obj_size);
if (!strcmp (arch, "mips") && h_flag) {
pj_ks (pj, "isa", h_flag);
if (!strcmp (arch, "mips")) {
pj_ks (pj, "isa", info->cpu);
pj_ks (pj, "features", info->features);
}
if (machine) {
pj_ks (pj, "machine", machine);
@ -1109,7 +1111,7 @@ R_API void r_bin_list_archs(RBin *bin, int mode) {
break;
default:
str_fmt = h_flag && strcmp (h_flag, "unknown_flag")? sdb_fmt ("%s_%i %s", arch, bits, h_flag) \
: sdb_fmt ("%s_%i", arch, bits);
: sdb_fmt ("%s_%i", arch, bits);
r_table_add_rowf (table, "nsnss", i, sdb_fmt ("0x%08" PFMT64x , boffset), obj_size, str_fmt, "");
bin->cb_printf ("%s\n", r_table_tostring(table));
}

View File

@ -59,6 +59,39 @@ static inline int UTX_MUL(ut64 *r, ut64 a, ut64 b) {
#define round_up(a) ((((a) + (4) - (1)) / (4)) * (4))
#define EF_MIPS_ABI_O32 0x00001000 /* O32 ABI. */
#define EF_MIPS_ABI_O64 0x00002000 /* O32 extended for 64 bit. */
#define EF_MIPS_ABI 0x0000f000
static inline bool is_elfclass64(Elf_(Ehdr) *h) {
return h->e_ident[EI_CLASS] == ELFCLASS64;
}
static bool is_mips_o32(Elf_(Ehdr) *h) {
if (h->e_ident[EI_CLASS] != ELFCLASS32) {
return false;
}
if ((h->e_flags & EF_MIPS_ABI2) != 0) {
return false;
}
if (((h->e_flags & EF_MIPS_ABI) != 0) &&
((h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) {
return false;
}
return true;
}
static bool is_mips_n32(Elf_(Ehdr) *h) {
if (h->e_ident[EI_CLASS] != ELFCLASS32) {
return false;
}
if (((h->e_flags & EF_MIPS_ABI2) == 0) ||
((h->e_flags & EF_MIPS_ABI) != 0)) {
return false;
}
return true;
}
enum {
X86,
X86_64,
@ -2085,8 +2118,24 @@ char* Elf_(r_bin_elf_get_arch)(ELFOBJ *bin) {
default: return strdup ("x86");
}
}
char* Elf_(r_bin_elf_get_abi)(ELFOBJ *bin) {
Elf_(Ehdr)* ehdr = (Elf_(Ehdr) *) &bin->ehdr;
char* Elf_(r_bin_elf_get_head_flag)(ELFOBJ *bin) {
if (ehdr->e_machine == EM_MIPS) {
if (is_elfclass64 (ehdr)) {
return strdup ("n64");
}
if (is_mips_n32 (ehdr)) {
return strdup ("n32");
}
if (is_mips_o32 (ehdr)) {
return strdup ("o32");
}
}
return NULL;
}
char* Elf_(r_bin_elf_get_cpu)(ELFOBJ *bin) {
if (bin->phdr && bin->ehdr.e_machine == EM_MIPS) {
const ut32 mipsType = bin->ehdr.e_flags & EF_MIPS_ARCH;
switch (mipsType) {
@ -2102,8 +2151,23 @@ char* Elf_(r_bin_elf_get_head_flag)(ELFOBJ *bin) {
default : return strdup (" Unknown mips ISA");
}
}
//TODO: Fill other arch
return strdup("unknown_flag");
return NULL;
}
char* Elf_(r_bin_elf_get_head_flag)(ELFOBJ *bin) {
char *head_flag = NULL;
char *str = Elf_(r_bin_elf_get_cpu) (bin);
if (str) {
head_flag = r_str_append (head_flag, str);
}
str = Elf_(r_bin_elf_get_abi) (bin);
if (str) {
head_flag = r_str_appendf (head_flag, " %s", str);
}
if (R_STR_ISEMPTY (head_flag)) {
head_flag = r_str_append (head_flag, "unknown_flag");
}
return head_flag;
}
// http://www.sco.com/developers/gabi/latest/ch4.eheader.html

View File

@ -185,7 +185,9 @@ bool Elf_(r_bin_elf_is_static)(struct Elf_(r_bin_elf_obj_t) *bin);
char* Elf_(r_bin_elf_get_data_encoding)(struct Elf_(r_bin_elf_obj_t) *bin);
char* Elf_(r_bin_elf_get_arch)(struct Elf_(r_bin_elf_obj_t) *bin);
char* Elf_(r_bin_elf_get_machine_name)(struct Elf_(r_bin_elf_obj_t) *bin);
char* Elf_(r_bin_elf_get_head_flag)(struct Elf_(r_bin_elf_obj_t) *bin); //yin
char* Elf_(r_bin_elf_get_head_flag)(ELFOBJ *bin); //yin
char* Elf_(r_bin_elf_get_abi)(ELFOBJ *bin);
char* Elf_(r_bin_elf_get_cpu)(ELFOBJ *bin);
char* Elf_(r_bin_elf_get_file_type)(struct Elf_(r_bin_elf_obj_t) *bin);
char* Elf_(r_bin_elf_get_elf_class)(struct Elf_(r_bin_elf_obj_t) *bin);
int Elf_(r_bin_elf_get_bits)(struct Elf_(r_bin_elf_obj_t) *bin);

View File

@ -1125,6 +1125,14 @@ static RBinInfo* info(RBinFile *bf) {
return NULL;
}
ret->arch = str;
if ((str = Elf_(r_bin_elf_get_cpu) (obj))) {
ret->cpu = str;
}
if ((str = Elf_(r_bin_elf_get_abi) (obj))) {
ret->features = str;
}
ret->rclass = strdup ("elf");
ret->bits = Elf_(r_bin_elf_get_bits) (obj);
if (!strcmp (ret->arch, "avr")) {

View File

@ -796,6 +796,9 @@ static int bin_info(RCore *r, int mode, ut64 laddr) {
if (info->cpu && *info->cpu) {
r_config_set (r->config, "asm.cpu", info->cpu);
}
if (info->features && *info->features) {
r_config_set (r->config, "asm.features", info->features);
}
r_config_set (r->config, "anal.arch", info->arch);
snprintf (str, R_FLAG_NAME_SIZE, "%i", info->bits);
r_config_set (r->config, "asm.bits", str);

View File

@ -209,6 +209,7 @@ typedef struct r_bin_info_t {
char *cpu;
char *machine;
char *head_flag;
char *features;
char *os;
char *subsystem;
char *rpath;

View File

@ -344,9 +344,9 @@ iA
iAj
EOF
EXPECT=<<EOF
0 0x00000000 266108 mips_32 mips1
0 0x00000000 266108 mips_32 mips1 o32
{"bins":[{"arch":"mips","bits":32,"offset":0,"size":266108,"isa":"mips1","machine":"MIPS R3000"}]}
{"bins":[{"arch":"mips","bits":32,"offset":0,"size":266108,"isa":"mips1","features":"o32","machine":"MIPS R3000"}]}
EOF
RUN
@ -357,9 +357,9 @@ iA
iAj
EOF
EXPECT=<<EOF
0 0x00000000 1039368 mips_64 mips64r2
0 0x00000000 1039368 mips_64 mips64r2 n64
{"bins":[{"arch":"mips","bits":64,"offset":0,"size":1039368,"isa":"mips64r2","machine":"MIPS R3000"}]}
{"bins":[{"arch":"mips","bits":64,"offset":0,"size":1039368,"isa":"mips64r2","features":"n64","machine":"MIPS R3000"}]}
EOF
RUN

View File

@ -72,6 +72,23 @@ EXPECT=<<EOF
EOF
RUN
NAME=MIPS new abi
FILE=bins/elf/analysis/mips64r2-busybox-loongson
CMDS=<<EOF
e asm.arch=mips.gnu
s 0x120005978
pd 6
EOF
EXPECT=<<EOF
0x120005978 1800bfff sd ra, 24(sp)
0x12000597c 3800a7ff sd a3, 56(sp)
0x120005980 4000a8ff sd a4, 64(sp)
0x120005984 4800a9ff sd a5, 72(sp)
0x120005988 5000aaff sd a6, 80(sp)
0x12000598c 5800abff sd a7, 88(sp)
EOF
RUN
NAME=mac ls pdsf
FILE=bins/mach0/mac-ls
CMDS=<<EOF