2017-10-05 06:10:04 +03:00
/*
* Based on :
*
* Minimal BPF JIT image disassembler
*
* Disassembles BPF JIT compiler emitted opcodes back to asm insn ' s for
* debugging or verification purposes .
*
* Copyright 2013 Daniel Borkmann < daniel @ iogearbox . net >
* Licensed under the GNU General Public License , version 2.0 ( GPLv2 )
*/
2017-10-23 19:24:09 +03:00
# include <stdarg.h>
2017-10-05 06:10:04 +03:00
# include <stdint.h>
# include <stdio.h>
# include <stdlib.h>
# include <assert.h>
# include <unistd.h>
# include <string.h>
# include <bfd.h>
# include <dis-asm.h>
# include <sys/types.h>
# include <sys/stat.h>
2017-11-02 11:09:45 +03:00
# include <limits.h>
2017-10-05 06:10:04 +03:00
2017-10-23 19:24:09 +03:00
# include "json_writer.h"
# include "main.h"
2017-10-05 06:10:04 +03:00
static void get_exec_path ( char * tpath , size_t size )
{
ssize_t len ;
char * path ;
snprintf ( tpath , size , " /proc/%d/exe " , ( int ) getpid ( ) ) ;
tpath [ size - 1 ] = 0 ;
path = strdup ( tpath ) ;
assert ( path ) ;
len = readlink ( path , tpath , size - 1 ) ;
assert ( len > 0 ) ;
tpath [ len ] = 0 ;
free ( path ) ;
}
2017-10-23 19:24:09 +03:00
static int oper_count ;
static int fprintf_json ( void * out , const char * fmt , . . . )
{
va_list ap ;
char * s ;
va_start ( ap , fmt ) ;
if ( ! oper_count ) {
int i ;
s = va_arg ( ap , char * ) ;
/* Strip trailing spaces */
i = strlen ( s ) - 1 ;
while ( s [ i ] = = ' ' )
s [ i - - ] = ' \0 ' ;
jsonw_string_field ( json_wtr , " operation " , s ) ;
jsonw_name ( json_wtr , " operands " ) ;
jsonw_start_array ( json_wtr ) ;
oper_count + + ;
} else if ( ! strcmp ( fmt , " , " ) ) {
/* Skip */
} else {
s = va_arg ( ap , char * ) ;
jsonw_string ( json_wtr , s ) ;
oper_count + + ;
}
va_end ( ap ) ;
return 0 ;
}
2018-01-17 03:05:21 +03:00
void disasm_print_insn ( unsigned char * image , ssize_t len , int opcodes ,
const char * arch )
2017-10-05 06:10:04 +03:00
{
disassembler_ftype disassemble ;
struct disassemble_info info ;
int count , i , pc = 0 ;
2017-11-02 11:09:45 +03:00
char tpath [ PATH_MAX ] ;
2017-10-05 06:10:04 +03:00
bfd * bfdf ;
if ( ! len )
return ;
memset ( tpath , 0 , sizeof ( tpath ) ) ;
get_exec_path ( tpath , sizeof ( tpath ) ) ;
bfdf = bfd_openr ( tpath , NULL ) ;
assert ( bfdf ) ;
assert ( bfd_check_format ( bfdf , bfd_object ) ) ;
2017-10-23 19:24:09 +03:00
if ( json_output )
init_disassemble_info ( & info , stdout ,
( fprintf_ftype ) fprintf_json ) ;
else
init_disassemble_info ( & info , stdout ,
( fprintf_ftype ) fprintf ) ;
2018-01-17 03:05:21 +03:00
/* Update architecture info for offload. */
if ( arch ) {
const bfd_arch_info_type * inf = bfd_scan_arch ( arch ) ;
if ( inf ) {
bfdf - > arch_info = inf ;
} else {
p_err ( " No libfd support for %s " , arch ) ;
return ;
}
}
2017-10-05 06:10:04 +03:00
info . arch = bfd_get_arch ( bfdf ) ;
info . mach = bfd_get_mach ( bfdf ) ;
info . buffer = image ;
info . buffer_length = len ;
disassemble_init_for_target ( & info ) ;
2017-12-27 22:16:29 +03:00
# ifdef DISASM_FOUR_ARGS_SIGNATURE
disassemble = disassembler ( info . arch ,
bfd_big_endian ( bfdf ) ,
info . mach ,
bfdf ) ;
# else
2017-10-05 06:10:04 +03:00
disassemble = disassembler ( bfdf ) ;
2017-12-27 22:16:29 +03:00
# endif
2017-10-05 06:10:04 +03:00
assert ( disassemble ) ;
2017-10-23 19:24:09 +03:00
if ( json_output )
jsonw_start_array ( json_wtr ) ;
2017-10-05 06:10:04 +03:00
do {
2017-10-23 19:24:09 +03:00
if ( json_output ) {
jsonw_start_object ( json_wtr ) ;
oper_count = 0 ;
jsonw_name ( json_wtr , " pc " ) ;
jsonw_printf ( json_wtr , " \" 0x%x \" " , pc ) ;
} else {
printf ( " %4x: \t " , pc ) ;
}
2017-10-05 06:10:04 +03:00
count = disassemble ( pc , & info ) ;
2017-10-23 19:24:09 +03:00
if ( json_output ) {
/* Operand array, was started in fprintf_json. Before
* that , make sure we have a _null_ value if no operand
* other than operation code was present .
*/
if ( oper_count = = 1 )
jsonw_null ( json_wtr ) ;
jsonw_end_array ( json_wtr ) ;
}
2017-10-05 06:10:04 +03:00
if ( opcodes ) {
2017-10-23 19:24:09 +03:00
if ( json_output ) {
jsonw_name ( json_wtr , " opcodes " ) ;
jsonw_start_array ( json_wtr ) ;
for ( i = 0 ; i < count ; + + i )
jsonw_printf ( json_wtr , " \" 0x%02hhx \" " ,
( uint8_t ) image [ pc + i ] ) ;
jsonw_end_array ( json_wtr ) ;
} else {
printf ( " \n \t " ) ;
for ( i = 0 ; i < count ; + + i )
printf ( " %02x " ,
( uint8_t ) image [ pc + i ] ) ;
}
2017-10-05 06:10:04 +03:00
}
2017-10-23 19:24:09 +03:00
if ( json_output )
jsonw_end_object ( json_wtr ) ;
else
printf ( " \n " ) ;
2017-10-05 06:10:04 +03:00
pc + = count ;
} while ( count > 0 & & pc < len ) ;
2017-10-23 19:24:09 +03:00
if ( json_output )
jsonw_end_array ( json_wtr ) ;
2017-10-05 06:10:04 +03:00
bfd_close ( bfdf ) ;
}