# How to use nanomips libopcode https://blog.yossarian.net/2019/05/18/Basic-disassembly-with-libopcodes - Download binutil source from https://github.com/MediaTek-Labs/nanomips-gnu-toolchain/releases ```bash cd <binutils src root> ./configure --target=nanomips-gcc-elf CFLAGS="-Wno-maybe-uninitialized" make all-opcodes gcc main.c -Iinclude -Ibfd -Lopcodes -lopcodes -Lbfd -lbfd -Llibiberty -liberty -Lzlib -lz ./a.out ``` - Sample code ```c= #define _GNU_SOURCE /* asprintf, vasprintf */ #include <config.h> #include <stdarg.h> #include <stdbool.h> #include <stddef.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dis-asm.h> typedef struct { char *insn_buffer; bool reenter; } stream_state; /* This approach isn't very memory efficient or clear, * but it avoids external size/buffer tracking in this * example. */ static int dis_fprintf(void *stream, const char *fmt, ...) { stream_state *ss = (stream_state *)stream; va_list arg; va_start(arg, fmt); if (!ss->reenter) { vasprintf(&ss->insn_buffer, fmt, arg); ss->reenter = true; } else { char *tmp; vasprintf(&tmp, fmt, arg); char *tmp2; asprintf(&tmp2, "%s%s", ss->insn_buffer, tmp); free(ss->insn_buffer); free(tmp); ss->insn_buffer = tmp2; } va_end(arg); return 0; } char *disassemble_raw(uint8_t *input_buffer, size_t input_buffer_size) { char *disassembled = NULL; stream_state ss = {}; disassemble_info disasm_info = {}; init_disassemble_info(&disasm_info, &ss, dis_fprintf); disasm_info.arch = bfd_arch_nanomips; disasm_info.mach = bfd_mach_nanomipsisa32r6; disasm_info.read_memory_func = buffer_read_memory; disasm_info.buffer = input_buffer; disasm_info.buffer_vma = 0; disasm_info.buffer_length = input_buffer_size; disassemble_init_for_target(&disasm_info); disassembler_ftype disasm; disasm = disassembler(bfd_arch_nanomips, false, bfd_mach_nanomipsisa32r6, NULL); size_t pc = 0; while (pc < input_buffer_size) { size_t insn_size = disasm(pc, &disasm_info); pc += insn_size; if (disassembled == NULL) { asprintf(&disassembled, "%s", ss.insn_buffer); } else { char *tmp; asprintf(&tmp, "%s\n%s", disassembled, ss.insn_buffer); free(disassembled); disassembled = tmp; } /* Reset the stream state after each instruction decode. */ free(ss.insn_buffer); ss.reenter = false; } return disassembled; } int main(int argc, char const *argv[]) { uint8_t input_buffer[] = { 0x1c, 0x12, // move s0,gp 0x12, 0x1c, // save 16,fp,ra }; size_t input_buffer_size = sizeof(input_buffer); char *disassembled = disassemble_raw(input_buffer, input_buffer_size); puts(disassembled); free(disassembled); return 0; } ```