
Libvmcu adalah mesin kecil untuk analisis statis dan dinamis dari biner mikrokontroler AVR.
Ini menangani persiapan data mentah, yang kemudian dapat diproses lebih lanjut oleh program lain. Tujuannya di sini adalah untuk memungkinkan untuk berinteraksi secara terprogram dengan kode sumber AVR.
libvmcu memberi Anda
Catatan: Perpustakaan ini masih dalam pengembangan.
Saya contoh
II showcase
III Pengaturan VMCU
IV didukung MCU
V Analisis Dinamis
Analisis statis VI
VII Instruksi-set
Viii binding
IX berkontribusi
X kredit
XI Dokumentasi
/* A possible implementation of print_instruction can be found below */
int main ( const int argc , const char * * argv ) {
/* ignoring checks for this example */
vmcu_model_t * m328p = vmcu_model_ctor ( VMCU_DEVICE_M328P );
vmcu_report_t * report = vmcu_analyze_file ( "file.hex" , m328p );
for ( uint32_t i = 0 ; i < report -> cfg -> used ; i ++ ) {
vmcu_cfg_node_t * node = & report -> cfg -> node [ i ];
print_instruction ( node -> xto . i );
if ( node -> t != NULL ) {
printf ( "true -> " );
print_instruction ( node -> t -> xto . i );
}
if ( node -> f != NULL ) {
printf ( "false -> " );
print_instruction ( node -> f -> xto . i );
}
printf ( "n" );
}
vmcu_report_dtor ( report );
vmcu_model_dtor ( m328p );
return EXIT_SUCCESS ;
} 0x0000 .... f1f3 breq - 2 ; (ZF == 1): PC <- PC + -2 + 1
true - > 0x3fff .... 839a sbi 0x10 , 3 ; IO[0x10, 3] <- 1
false - > 0x0001 .... 0fef ldi r16 , 0xff ; r16 <- 0xff
--------------------------------------------------------------------------------
0x0001 .... 0fef ldi r16 , 0xff ; r16 <- 0xff
true - > 0x0002 .... 5817 cp r21 , r24 ; r21 - r24
--------------------------------------------------------------------------------
0x0002 .... 5817 cp r21 , r24 ; r21 - r24
true - > 0x0003 .... 19f4 brne 3 ; (ZF == 0): PC <- PC + 3 + 1
--------------------------------------------------------------------------------
0x0003 .... 19f4 brne 3 ; (ZF == 0): PC <- PC + 3 + 1
true - > 0x0007 .... 0127 eor r16 , r17 ; r16 <- r16 ^ r17
false - > 0x0004 .... a895 wdr ; watchdog reset
--------------------------------------------------------------------------------
0x0004 .... a895 wdr ; watchdog reset
true - > 0x0005 .... 8895 sleep ; circuit sleep
--------------------------------------------------------------------------------
0x0005 .... 8895 sleep ; circuit sleep
true - > 0x0006 .... 0000 nop ; no operation
--------------------------------------------------------------------------------
0x0006 .... 0000 nop ; no operation
true - > 0x0007 .... 0127 eor r16 , r17 ; r16 <- r16 ^ r17
--------------------------------------------------------------------------------
0x0007 .... 0127 eor r16 , r17 ; r16 <- r16 ^ r17
--------------------------------------------------------------------------------
0x3fff .... 839a sbi 0x10 , 3 ; IO[0x10, 3] <- 1
true - > 0x0000 .... f1f3 breq - 2 ; (ZF == 1): PC <- PC + -2 + 1
-------------------------------------------------------------------------------- /* A possible implementation of print_instruction can be found below */
int main ( const int argc , const char * * argv ) {
/* ignoring checks for this example */
vmcu_model_t * m328p = vmcu_model_ctor ( VMCU_DEVICE_M328P );
vmcu_report_t * report = vmcu_analyze_file ( "file.srec" , m328p );
for ( uint32_t i = 0 ; i < report -> progsize ; i ++ ) {
printf ( "0x%04x " , report -> disassembly [ i ]. addr );
print_instruction ( & report -> disassembly [ i ]);
}
vmcu_report_dtor ( report );
vmcu_model_dtor ( m328p );
return EXIT_SUCCESS ;
} 0x004e ldi r27 , 0x06 ; r27 <- 0x06
0x004f rjmp 1 ; PC <- PC + 1 + 1
0x0050 st X +, r1 ; DS[X+] <- r1
0x0051 cpi r26 , 0x20 ; r26 - 0x20
0x0052 cpc r27 , r18 ; r27 - r18 - CF
0x0053 brne - 4 ; (ZF == 0): PC <- PC + -4 + 1
0x0054 call 0x60b ; PC <- 0x60b /* A possible implementation of print_instruction can be found below */
int main ( const int argc , const char * * argv ) {
/* ignoring checks for this example */
vmcu_model_t * m328p = vmcu_model_ctor ( VMCU_DEVICE_M328P );
vmcu_report_t * report = vmcu_analyze_file ( "file.hex" , m328p );
for ( uint32_t i = 0 ; i < report -> progsize ; i ++ ) {
vmcu_instr_t * instr = & report -> disassembly [ i ];
if ( instr -> writes . c_flag == true)
print_instruction ( instr );
if ( instr -> reads . c_flag == true)
print_instruction ( instr );
}
vmcu_report_dtor ( report );
vmcu_model_dtor ( m328p );
return EXIT_SUCCESS ;
} subi r18 , 0x00 ; r18 <- r18 - 0x00
adiw r29:r28 , 0x1a ; r29:r28 <- r29:r28 + 0x1a
sbci r23 , 0xff ; r23 <- r23 - 0xff - CF
cpc r19 , r17 ; r19 - r17 - CF int main ( const int argc , const char * * argv ) {
/* ignoring checks for this example */
vmcu_model_t * m328p = vmcu_model_ctor ( VMCU_DEVICE_M328P );
vmcu_report_t * report = vmcu_analyze_file ( "file.hex" , m328p );
for ( uint32_t i = 0 ; i < report -> n_vector ; i ++ ) {
vmcu_vector_t * vect = & report -> vector [ i ];
vmcu_instr_t * isr = vect -> xto -> i ;
printf ( "Vector ID %d @ 0x%04xn" , vect -> id , vect -> addr );
printf ( " interrupt service routine at 0x%04x" , isr -> addr );
printf ( "nn" );
}
vmcu_report_dtor ( report );
vmcu_model_dtor ( m328p );
return EXIT_SUCCESS ;
} Vector ID 16 @ 0x0020
interrupt service routine at 0x03f5
Vector ID 17 @ 0x0022
interrupt service routine at 0x008a
Vector ID 18 @ 0x0024
interrupt service routine at 0x03c3
Vector ID 19 @ 0x0026
interrupt service routine at 0x039d /* A possible implementation of print_instruction can be found below */
int main ( const int argc , const char * * argv ) {
/* ignoring checks for this example */
vmcu_model_t * m328p = vmcu_model_ctor ( VMCU_DEVICE_M328P );
vmcu_report_t * report = vmcu_analyze_file ( "file.hex" , m328p );
for ( uint32_t i = 0 ; i < report -> n_label ; i ++ ) {
vmcu_label_t * lx = & report -> label [ i ];
printf ( "0x%04xtL%dnn" , lx -> addr , lx -> id );
for ( uint32_t j = 0 ; j < lx -> n_xfrom ; j ++ ) {
vmcu_xref_t * x = & lx -> xfrom [ j ];
printf ( " xref from 0x%04x " , x -> i -> addr );
print_instruction ( x -> i );
}
printf ( "n" );
}
vmcu_report_dtor ( report );
vmcu_model_dtor ( m328p );
return EXIT_SUCCESS ;
} 0x04c6 L75
xref from 0x04a1 call + 1222 ; PC <- 0x4c6
xref from 0x0a84 call + 1222 ; PC <- 0x4c6
xref from 0x0b5c call + 1222 ; PC <- 0x4c6
0x04e2 L76
xref from 0x05d4 rjmp - 243 ; PC <- PC - 0xf3 + 1
0x05d0 L77
xref from 0x04e1 rjmp + 238 ; PC <- PC + 0xee + 1 /* A possible implementation of print_instruction can be found below */
int main ( const int argc , const char * * argv ) {
/* ignoring checks for this example */
vmcu_model_t * m328p = vmcu_model_ctor ( VMCU_DEVICE_M328P );
vmcu_report_t * report = vmcu_analyze_file ( "file.hex" , m328p );
for ( uint32_t i = 0 ; i < report -> n_sfr ; i ++ ) {
vmcu_sfr_t * sfr = & report -> sfr [ i ];
printf ( "SFR ID: %dnn" , sfr -> id );
for ( uint32_t j = 0 ; j < sfr -> n_xfrom ; j ++ ) {
vmcu_xref_t * x = & sfr -> xfrom [ j ];
printf ( " xref from 0x%04x " , x -> i -> addr );
print_instruction ( x -> i );
}
printf ( "n" );
}
vmcu_report_dtor ( report );
vmcu_model_dtor ( m328p );
return EXIT_SUCCESS ;
} SFR ID: 17
xref from 0x00f4 sbi 0x1f , 2 ; IO[1f, 2] <- 0x01
xref from 0x00f5 sbi 0x1f , 1 ; IO[1f, 1] <- 0x01
SFR ID: 50
xref from 0x004c sts 0x006e , r1 ; DATA[0x6e] <- R1
xref from 0x0051 lds r24 , 0x006e ; R24 <- DATA[0x6e]
xref from 0x0054 sts 0x006e , r24 ; DATA[0x6e] <- R24 /* 0x6a97 (little endian) <=> sbiw r29:r28, 0x1a */
int main ( const int argc , const char * * argv ) {
/* initialize a device model */
vmcu_model_t * m328p = vmcu_model_ctor ( VMCU_DEVICE_M328P );
vmcu_instr_t instr ;
vmcu_disassemble_bytes ( 0x6a97 , & instr , m328p );
const VMCU_IKEY key = instr . key ; // VMCU_IKEY_SBIW
const VMCU_GROUP grp = instr . group ; // VMCU_GROUP_MATH_LOGIC
const uint32_t opcode = instr . opcode ; // 0x976a (big endian)
const uint32_t addr = instr . addr ; // 0x0000 (undefined)
const bool dword = instr . dword ; // false
const bool exec = instr . exec ; // true
vmcu_operand_t * src = & instr . src ; // source operand
vmcu_operand_t * dest = & instr . dest ; // destination operand
VMCU_OPTYPE src_type = src -> type ; // VMCU_OPTYPE_K6
VMCU_OPTYPE dest_type = dest -> type ; // VMCU_OPTYPE_RP
const uint8_t src_val = src -> k ; // 0x1a
VMCU_REGISTER dest_rh = dest -> rp . high ; // VMCU_REGISTER_R29
VMCU_REGISTER dest_rl = dest -> rp . low ; // VMCU_REGISTER_R28
const bool writes_hf = instr . writes . h_flag ; // false
const bool writes_cf = instr . writes . c_flag ; // true
const bool reads_io = instr . reads . io ; // false
const bool reads_nf = instr . reads . n_flag ; // false
vmcu_mnemonic_t * mnem = & instr . mnem ; // instruction mnemonic
const char * base_str = mnem -> base ; // "sbiw"
const char * dest_str = mnem -> dest ; // "r29:r28"
const char * src_str = mnem -> src ; // "0x1a"
const char * com_str = mnem -> comment ; // "r29:r28 <- r29:r28 - 0x1a"
vmcu_model_dtor ( m328p );
return EXIT_SUCCESS ;
} /* this snippet can be used to assemble and print an instruction */
void print_instruction ( const vmcu_instr_t * instr ) {
printf ( "%s" , instr -> mnem . base );
if ( instr -> dest . type != VMCU_OPTYPE_NONE )
printf ( " %s," , instr -> mnem . dest );
if ( instr -> src . type != VMCU_OPTYPE_NONE )
printf ( " %s" , instr -> mnem . src );
printf ( " %sn" , instr -> mnem . comment );
}
Debugger kecil yang ditulis dengan libvmcu
Saat ini perpustakaan ini dilengkapi dengan dua header, keduanya dapat ditemukan di engine/include/libvmcu:
Katakanlah, kami memiliki file yang disebut prog.c di tingkat atas repositori ini dan kami ingin menautkannya dengan libvmcu:
/* prog.c */
#include "libvmcu_analyzer.h"
#include "libvmcu_system.h"
int main ( void ) {
/* do something */
return 0 ;
} You@Terminal:~ $ cd build-release/
You@Terminal:~ $ make -f build.mk You@Terminal:~ $ gcc -Iengine/include/libvmcu/ -c prog.c -o prog.o You@Terminal:~ $ gcc -o prog prog.o -Lbuild-release/ -lvmcu -lmItu saja. Jika Anda menghadapi masalah, lihat beberapa contoh di pengemudi/ direktori.
Libvmcu mencoba mendukung sebanyak mungkin tipe AVR untuk analisis statis. Analisis dinamis saat ini hanya direncanakan untuk keluarga ATmega328 tetapi dapat diperpanjang di masa depan.
Seharusnya cukup mudah untuk menambahkan mikrokontroler baru ke analisis statis. Untuk informasi lebih lanjut, lihat mesin/*/lengkung/
Inti Perangkat AVR
Inti Perangkat Avre
Avre+ Device Core
Inti Perangkat AVRXM
Inti Perangkat AVRXT
Inti Perangkat AVRRC
Disassembler
referensi silang (xref-from, xref-to)
Bendera penganalisa
membusuk dan mengklasifikasikan instruksi
Analisis untuk biner AVR
Format pembaca
Dukungan interupsi
siklus simulasi realtime yang akurat
Dukungan untuk 133 instruksi perakitan AVR
Simulasi periferal internal yang akurat
Saat ini VMCU mendukung: ~ 133 instruksi. Beberapa instruksi diimplementasikan sebagai instruksi 'NOP', oleh karena itu, tidak memiliki fungsionalitas nyata. Instruksi ini akan diimplementasikan sesegera mungkin. Instruksi berikut memerlukan pekerjaan lebih lanjut:
Semua instruksi perakitan lainnya berfungsi dengan baik.
libvmcu memiliki ikatan java untuk fungsi dasar. Untuk informasi lebih lanjut, lihat Bindings/Java/
Perhatikan juga, binding mungkin tidak selalu bekerja dengan versi terbaru karena pengembangan mesin.
| Mesin | Pengemudi | Binding | Pengujian |
|---|---|---|---|
| ditutup untuk pr | Buka untuk PR | Buka untuk PR | Buka untuk PR |
Pada saat penulisan ini dokumentasi masih dalam pengembangan. Dokumentasi (tidak lengkap) dapat ditemukan di https://github.com/milo-d/libvmcu-virtual-mcu-library/wiki
Jika Anda kehilangan informasi dan tidak ingin menunggu wiki, file header libvmcu juga didokumentasikan dengan cukup baik.