
LIBVMCU是一种用于静态和动态分析AVR微控制器二进制文件的小型发动机。
它需要处理原始数据的准备,然后可以通过其他程序进一步处理。这里的目的是使与AVR源代码进行编程交互成为可能。
libvmcu为您提供
注意:该库仍在开发中。
我的例子
II展示
III设置VMCU
IV支持MCUS
V动态分析
VI静态分析
vii指令集
VIII结合
IX贡献
X积分
XI文档
/* 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 );
}
用libvmcu编写的小型调试器
目前,该库带有两个标头,两个都可以在Engine/include/libvmcu中找到:
假设我们在此存储库的最高级别上有一个名为prog.c的文件,我们想将其链接到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 -lm就是这样。如果您面临问题,请查看驾驶员/目录中的一些示例。
LIBVMCU试图支持尽可能多的AVR类型进行静态分析。目前,动态分析仅针对Atmega328家族进行,但将来可能会扩展。
在静态分析中添加新的微控制器应该很容易。有关更多信息,请查看引擎/*/Arch/
AVR设备核心
Avre设备核心
Avre+设备核心
AVRXM设备核心
AVRXT设备核心
AVRRC设备核心
拆卸器
交叉参考(Xref-from,Xref-to)
分析仪标志
分解和分类说明
AVR二进制的分析仪
格式阅读器
中断支持
循环准确的实时模拟
支持133个AVR组装说明
精确模拟内部外围设备
当前VMCU支持:〜133个说明。因此,一些说明被用作“ NOP”指令,因此没有真正的功能。这些说明将尽快实施。按照说明需要进一步的工作:
所有其他大会说明都很好。
libvmcu具有用于基本功能的Java结合。有关更多信息,请查看Bindings/Java/
另请注意,由于引擎的开发,绑定可能并不总是与最新版本一起使用。
| 引擎 | 司机 | 绑定 | 测试 |
|---|---|---|---|
| 关闭PR | 开放PR | 开放PR | 开放PR |
到撰写本文时,文档仍在开发中。可以在https://github.com/milo-d/libvmcu-virtual-mcu-library/wiki上找到(不完整的)文档
如果您缺少信息,并且不想等待Wiki,则LIBVMCU标头文件也有很好的记录。