visualize_demo.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. SliceFusion-LLM Visualization Demo Script
  5. Generate visualization charts to showcase project effects
  6. """
  7. import os
  8. import json
  9. # Must set backend before importing pyplot
  10. import matplotlib
  11. matplotlib.use('Agg')
  12. import matplotlib.pyplot as plt
  13. import matplotlib.patches as mpatches
  14. from matplotlib.patches import FancyBboxPatch, FancyArrowPatch
  15. import numpy as np
  16. # Set font - use English to avoid font issues
  17. plt.rcParams['font.family'] = 'DejaVu Sans'
  18. plt.rcParams['axes.unicode_minus'] = False
  19. plt.rcParams['font.size'] = 10
  20. def create_call_chain_diagram(call_chain, slices, output_path):
  21. """
  22. Create call chain fusion diagram
  23. """
  24. fig, ax = plt.subplots(1, 1, figsize=(14, 8))
  25. ax.set_xlim(0, 14)
  26. ax.set_ylim(0, 10)
  27. ax.axis('off')
  28. n = len(call_chain)
  29. box_width = 3.5
  30. box_height = 1.8
  31. start_x = 1
  32. colors = ['#E3F2FD', '#E8F5E9', '#FFF3E0', '#FCE4EC', '#F3E5F5']
  33. accent_colors = ['#1976D2', '#388E3C', '#F57C00', '#C2185B', '#7B1FA2']
  34. # Title
  35. ax.text(7, 9.5, 'SliceFusion-LLM: Code Slice Fusion Diagram',
  36. fontsize=16, fontweight='bold', ha='center', va='center')
  37. # Draw each function block
  38. y_positions = []
  39. for i, func_name in enumerate(call_chain):
  40. y = 8 - i * 2.2
  41. y_positions.append(y)
  42. # Function box
  43. rect = FancyBboxPatch(
  44. (start_x, y - box_height/2), box_width, box_height,
  45. boxstyle="round,pad=0.05,rounding_size=0.2",
  46. facecolor=colors[i % len(colors)],
  47. edgecolor=accent_colors[i % len(accent_colors)],
  48. linewidth=2
  49. )
  50. ax.add_patch(rect)
  51. # Function name (truncate if too long)
  52. display_name = func_name[:20] + '...' if len(func_name) > 20 else func_name
  53. ax.text(start_x + box_width/2, y + 0.4, display_name,
  54. fontsize=10, fontweight='bold', ha='center', va='center',
  55. color=accent_colors[i % len(accent_colors)])
  56. # Level label
  57. ax.text(start_x + box_width/2, y - 0.3, f'Level {i+1} Function',
  58. fontsize=8, ha='center', va='center', color='gray')
  59. # Inserted code slice
  60. if i < len(slices) and slices[i]:
  61. slice_x = start_x + box_width + 0.8
  62. slice_box = FancyBboxPatch(
  63. (slice_x, y - 0.6), 8, 1.2,
  64. boxstyle="round,pad=0.05,rounding_size=0.1",
  65. facecolor='#FFFDE7',
  66. edgecolor='#FBC02D',
  67. linewidth=1.5,
  68. linestyle='--'
  69. )
  70. ax.add_patch(slice_box)
  71. # Slice content
  72. slice_text = slices[i][:55] + '...' if len(slices[i]) > 55 else slices[i]
  73. ax.text(slice_x + 4, y, f'Slice {i+1}: {slice_text}',
  74. fontsize=8, ha='center', va='center',
  75. family='monospace', style='italic')
  76. # Arrow connection
  77. ax.annotate('', xy=(slice_x, y), xytext=(start_x + box_width, y),
  78. arrowprops=dict(arrowstyle='->', color='#FBC02D', lw=1.5))
  79. # Call arrow
  80. if i < n - 1:
  81. ax.annotate('',
  82. xy=(start_x + box_width/2, y_positions[i] - box_height/2 - 0.3),
  83. xytext=(start_x + box_width/2, y_positions[i] - box_height/2 - 0.1),
  84. arrowprops=dict(arrowstyle='->', color='gray', lw=2))
  85. ax.text(start_x + box_width + 0.1, y - box_height/2 - 0.2, 'call',
  86. fontsize=8, color='gray', style='italic')
  87. # Legend
  88. legend_elements = [
  89. mpatches.Patch(facecolor='#E3F2FD', edgecolor='#1976D2', label='Original Function'),
  90. mpatches.Patch(facecolor='#FFFDE7', edgecolor='#FBC02D', linestyle='--', label='Inserted Code Slice'),
  91. ]
  92. ax.legend(handles=legend_elements, loc='lower right', fontsize=9)
  93. plt.tight_layout()
  94. plt.savefig(output_path, dpi=150, bbox_inches='tight',
  95. facecolor='white', edgecolor='none')
  96. plt.close()
  97. print(f" Call chain diagram saved: {output_path}")
  98. def create_fusion_flow_diagram(output_path):
  99. """
  100. Create system architecture flow diagram
  101. """
  102. fig, ax = plt.subplots(1, 1, figsize=(16, 10))
  103. ax.set_xlim(0, 16)
  104. ax.set_ylim(0, 10)
  105. ax.axis('off')
  106. # Title
  107. ax.text(8, 9.5, 'SliceFusion-LLM System Architecture',
  108. fontsize=18, fontweight='bold', ha='center')
  109. # Define modules
  110. modules = [
  111. {'name': 'Input Layer', 'x': 1, 'y': 7, 'w': 2, 'h': 1.5, 'color': '#BBDEFB',
  112. 'items': ['JSONL Source', 'Target Code']},
  113. {'name': 'Data Processing', 'x': 4, 'y': 7, 'w': 2.5, 'h': 1.5, 'color': '#C8E6C9',
  114. 'items': ['Call Relation Extract', 'Call Chain Group']},
  115. {'name': 'Analysis Layer', 'x': 7.5, 'y': 7, 'w': 2.5, 'h': 1.5, 'color': '#FFE0B2',
  116. 'items': ['CFG Build', 'Dominator Analysis']},
  117. {'name': 'LLM Split Layer', 'x': 11, 'y': 7, 'w': 2.5, 'h': 1.5, 'color': '#E1BEE7',
  118. 'items': ['Smart Code Split', 'Fallback Mechanism']},
  119. {'name': 'Fusion Layer', 'x': 4, 'y': 4, 'w': 2.5, 'h': 1.5, 'color': '#B2EBF2',
  120. 'items': ['State Generation', 'Code Insertion']},
  121. {'name': 'Verification', 'x': 7.5, 'y': 4, 'w': 2.5, 'h': 1.5, 'color': '#FFCDD2',
  122. 'items': ['Syntax Validation', 'LLM Semantic Review']},
  123. {'name': 'Output Layer', 'x': 11, 'y': 4, 'w': 2.5, 'h': 1.5, 'color': '#DCEDC8',
  124. 'items': ['Fused Code .c', 'Verification Report']},
  125. ]
  126. for mod in modules:
  127. # Module box
  128. rect = FancyBboxPatch(
  129. (mod['x'], mod['y'] - mod['h']/2), mod['w'], mod['h'],
  130. boxstyle="round,pad=0.02,rounding_size=0.15",
  131. facecolor=mod['color'],
  132. edgecolor='gray',
  133. linewidth=1.5
  134. )
  135. ax.add_patch(rect)
  136. # Module name
  137. ax.text(mod['x'] + mod['w']/2, mod['y'] + 0.4, mod['name'],
  138. fontsize=10, fontweight='bold', ha='center', va='center')
  139. # Sub items
  140. for j, item in enumerate(mod['items']):
  141. ax.text(mod['x'] + mod['w']/2, mod['y'] - 0.2 - j*0.35, f'- {item}',
  142. fontsize=8, ha='center', va='center', color='#424242')
  143. # Arrow connections
  144. for i, (x1, y1, x2, y2) in enumerate([
  145. (3, 7, 4, 7), # Input -> Data Processing
  146. (6.5, 7, 7.5, 7), # Data Processing -> Analysis
  147. (10, 7, 11, 7), # Analysis -> LLM Split
  148. (6.5, 4, 7.5, 4), # Fusion -> Verification
  149. (10, 4, 11, 4), # Verification -> Output
  150. ]):
  151. ax.annotate('', xy=(x2, y2), xytext=(x1, y1),
  152. arrowprops=dict(arrowstyle='->', color='#757575', lw=2))
  153. # Curved arrow (from LLM Split to Fusion Layer)
  154. ax.annotate('', xy=(6.5, 4), xytext=(11, 5.25),
  155. arrowprops=dict(arrowstyle='->', color='#757575', lw=2,
  156. connectionstyle="arc3,rad=-0.3"))
  157. # Bottom description
  158. ax.text(8, 1.5, 'Key Features: LLM Smart Split | CFG Analysis | Multi-layer Verification | State Passing',
  159. fontsize=11, ha='center', va='center',
  160. bbox=dict(boxstyle='round', facecolor='#F5F5F5', edgecolor='gray'))
  161. plt.tight_layout()
  162. plt.savefig(output_path, dpi=150, bbox_inches='tight',
  163. facecolor='white', edgecolor='none')
  164. plt.close()
  165. print(f" Flow diagram saved: {output_path}")
  166. def create_statistics_chart(stats_data, output_path):
  167. """
  168. Create statistics charts
  169. """
  170. fig, axes = plt.subplots(2, 2, figsize=(14, 10))
  171. fig.suptitle('SliceFusion-LLM Dataset Statistics', fontsize=16, fontweight='bold')
  172. # 1. Call depth distribution (pie chart)
  173. ax1 = axes[0, 0]
  174. depth_labels = ['Depth 1', 'Depth 2', 'Depth 3', 'Depth 4', 'Depth 5+']
  175. depth_values = [4057, 489, 135, 50, 46]
  176. colors = ['#42A5F5', '#66BB6A', '#FFCA28', '#EF5350', '#AB47BC']
  177. explode = (0, 0, 0, 0.1, 0.1)
  178. ax1.pie(depth_values, explode=explode, labels=depth_labels, colors=colors,
  179. autopct='%1.1f%%', shadow=True, startangle=90)
  180. ax1.set_title('Call Chain Depth Distribution', fontsize=12, fontweight='bold')
  181. # 2. Success rate (bar chart)
  182. ax2 = axes[0, 1]
  183. methods = ['Global Var', 'Param Pass', 'LLM Split', 'Fallback']
  184. success_rates = [100, 100, 96, 4]
  185. bars = ax2.bar(methods, success_rates, color=['#42A5F5', '#66BB6A', '#FFCA28', '#EF5350'])
  186. ax2.set_ylabel('Success Rate (%)')
  187. ax2.set_title('Module Success Rates', fontsize=12, fontweight='bold')
  188. ax2.set_ylim(0, 110)
  189. for bar, rate in zip(bars, success_rates):
  190. ax2.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 2,
  191. f'{rate}%', ha='center', va='bottom', fontweight='bold')
  192. # 3. Processing time distribution (horizontal bar chart)
  193. ax3 = axes[1, 0]
  194. stages = ['Data Load', 'CFG Analysis', 'LLM Split', 'Code Fusion', 'Syntax Check', 'Semantic Review', 'File Output']
  195. times = [0.5, 2.3, 28.5, 1.2, 0.3, 16.4, 0.8]
  196. colors = plt.cm.Blues(np.linspace(0.3, 0.9, len(stages)))
  197. bars = ax3.barh(stages, times, color=colors)
  198. ax3.set_xlabel('Time (seconds)')
  199. ax3.set_title('Processing Time by Stage (50 groups)', fontsize=12, fontweight='bold')
  200. for bar, time in zip(bars, times):
  201. ax3.text(bar.get_width() + 0.5, bar.get_y() + bar.get_height()/2,
  202. f'{time}s', ha='left', va='center')
  203. # 4. Project distribution (horizontal bar chart)
  204. ax4 = axes[1, 1]
  205. projects = ['Linux Kernel', 'MySQL', 'HHVM', 'GPAC', 'TensorFlow', 'Others']
  206. counts = [7120, 920, 911, 875, 656, 14948]
  207. colors = plt.cm.Greens(np.linspace(0.3, 0.9, len(projects)))
  208. bars = ax4.barh(projects, counts, color=colors)
  209. ax4.set_xlabel('Function Count')
  210. ax4.set_title('Dataset Project Distribution', fontsize=12, fontweight='bold')
  211. for bar, count in zip(bars, counts):
  212. ax4.text(bar.get_width() + 200, bar.get_y() + bar.get_height()/2,
  213. f'{count}', ha='left', va='center')
  214. plt.tight_layout()
  215. plt.savefig(output_path, dpi=150, bbox_inches='tight',
  216. facecolor='white', edgecolor='none')
  217. plt.close()
  218. print(f" Statistics chart saved: {output_path}")
  219. def create_code_fusion_example(output_path):
  220. """
  221. Create code fusion before/after comparison diagram
  222. """
  223. fig, axes = plt.subplots(1, 2, figsize=(16, 9))
  224. fig.suptitle('Code Fusion Before vs After', fontsize=16, fontweight='bold', y=0.98)
  225. # Left: Before fusion
  226. ax1 = axes[0]
  227. ax1.set_xlim(0, 10)
  228. ax1.set_ylim(0, 10)
  229. ax1.axis('off')
  230. ax1.set_title('Before: Standalone Target Code', fontsize=12, fontweight='bold', pad=20)
  231. # Target code box
  232. target_rect = FancyBboxPatch(
  233. (1, 5.5), 8, 3.5,
  234. boxstyle="round,pad=0.05,rounding_size=0.2",
  235. facecolor='#FFEBEE',
  236. edgecolor='#C62828',
  237. linewidth=2
  238. )
  239. ax1.add_patch(target_rect)
  240. ax1.text(5, 8.5, 'Target Code (To Be Fused)', fontsize=11, fontweight='bold', ha='center')
  241. target_code = '''int secret_value = 0x12345678;
  242. int key = secret_value ^ 0xDEADBEEF;
  243. printf("Computed key: 0x%x", key);'''
  244. ax1.text(5, 6.8, target_code, fontsize=9, ha='center', va='center',
  245. family='monospace', linespacing=1.5)
  246. # Call chain box
  247. chain_rect = FancyBboxPatch(
  248. (1, 0.5), 8, 4,
  249. boxstyle="round,pad=0.05,rounding_size=0.2",
  250. facecolor='#E3F2FD',
  251. edgecolor='#1565C0',
  252. linewidth=2
  253. )
  254. ax1.add_patch(chain_rect)
  255. ax1.text(5, 4, 'Call Chain Functions (Original)', fontsize=11, fontweight='bold', ha='center')
  256. chain_text = '''f1() -> f2() -> f3() -> f4()
  257. Each function keeps original code
  258. No target code logic'''
  259. ax1.text(5, 2.2, chain_text, fontsize=9, ha='center', va='center',
  260. family='monospace', linespacing=1.5)
  261. # Right: After fusion
  262. ax2 = axes[1]
  263. ax2.set_xlim(0, 10)
  264. ax2.set_ylim(0, 10)
  265. ax2.axis('off')
  266. ax2.set_title('After: Code Distributed in Call Chain', fontsize=12, fontweight='bold', pad=20)
  267. # Fused functions
  268. funcs = [
  269. ('f1()', 'g_secret = 0x12345678;', 8.5),
  270. ('f2()', 'g_key = g_secret ^ 0xDEADBEEF;', 6.2),
  271. ('f3()', '// original code...', 3.9),
  272. ('f4()', 'printf("key: 0x%x", g_key);', 1.6),
  273. ]
  274. colors = ['#E8F5E9', '#FFF3E0', '#E3F2FD', '#FCE4EC']
  275. edge_colors = ['#2E7D32', '#EF6C00', '#1565C0', '#AD1457']
  276. for i, (fname, code, y) in enumerate(funcs):
  277. rect = FancyBboxPatch(
  278. (0.5, y - 0.8), 9, 1.8,
  279. boxstyle="round,pad=0.05,rounding_size=0.15",
  280. facecolor=colors[i],
  281. edgecolor=edge_colors[i],
  282. linewidth=2
  283. )
  284. ax2.add_patch(rect)
  285. ax2.text(1.5, y + 0.3, fname, fontsize=10, fontweight='bold',
  286. color=edge_colors[i])
  287. # Inserted code highlight
  288. if '0x' in code or 'printf' in code:
  289. ax2.text(5, y - 0.2, f'>> {code}', fontsize=9, ha='center',
  290. family='monospace', color='#B71C1C', fontweight='bold')
  291. else:
  292. ax2.text(5, y - 0.2, code, fontsize=9, ha='center',
  293. family='monospace', color='gray')
  294. # Call arrows
  295. if i < len(funcs) - 1:
  296. ax2.annotate('', xy=(5, y - 0.8 - 0.3), xytext=(5, y - 0.8 - 0.1),
  297. arrowprops=dict(arrowstyle='->', color='gray', lw=2))
  298. # Global variable declaration
  299. ax2.text(5, 9.5, 'static int g_secret, g_key; // Shared State',
  300. fontsize=9, ha='center', family='monospace',
  301. bbox=dict(boxstyle='round', facecolor='#FFFDE7', edgecolor='#FBC02D'))
  302. plt.tight_layout()
  303. plt.savefig(output_path, dpi=150, bbox_inches='tight',
  304. facecolor='white', edgecolor='none')
  305. plt.close()
  306. print(f" Comparison diagram saved: {output_path}")
  307. def create_verification_result_chart(output_path):
  308. """
  309. Create verification result visualization
  310. """
  311. fig, ax = plt.subplots(1, 1, figsize=(12, 7))
  312. # Data
  313. categories = ['Group 0\ncrypto_*', 'Group 1\nzend_*', 'Group 2\nOpen_table_*',
  314. 'Group 3\nlatm_*', 'Group 4\nprocess_*']
  315. # Verification results
  316. syntax_pass = [1, 1, 1, 1, 1]
  317. semantic_pass = [1, 1, 1, 0.8, 0.9]
  318. x = np.arange(len(categories))
  319. width = 0.35
  320. bars1 = ax.bar(x - width/2, syntax_pass, width, label='Syntax Validation', color='#66BB6A')
  321. bars2 = ax.bar(x + width/2, semantic_pass, width, label='Semantic Review', color='#42A5F5')
  322. ax.set_ylabel('Pass Rate', fontsize=12)
  323. ax.set_title('Verification Results (5 Test Groups)', fontsize=14, fontweight='bold')
  324. ax.set_xticks(x)
  325. ax.set_xticklabels(categories, fontsize=9)
  326. ax.legend(loc='lower right')
  327. ax.set_ylim(0, 1.2)
  328. # Add pass markers
  329. for bar in bars1:
  330. ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.02,
  331. 'OK', ha='center', va='bottom', fontsize=10, color='green', fontweight='bold')
  332. for bar, val in zip(bars2, semantic_pass):
  333. symbol = 'OK' if val >= 1 else 'WARN'
  334. color = 'green' if val >= 1 else 'orange'
  335. ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.02,
  336. symbol, ha='center', va='bottom', fontsize=10, color=color, fontweight='bold')
  337. # Add legend
  338. ax.text(0.02, 0.98, 'OK = Fully Passed\nWARN = Passed with Warnings',
  339. transform=ax.transAxes, fontsize=10,
  340. verticalalignment='top',
  341. bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))
  342. plt.tight_layout()
  343. plt.savefig(output_path, dpi=150, bbox_inches='tight',
  344. facecolor='white', edgecolor='none')
  345. plt.close()
  346. print(f" Verification chart saved: {output_path}")
  347. def main():
  348. """Main function - generate all visualization charts"""
  349. # Ensure output directory exists
  350. output_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'assets', 'demo')
  351. os.makedirs(output_dir, exist_ok=True)
  352. print("=" * 60)
  353. print("SliceFusion-LLM Visualization Demo")
  354. print("=" * 60)
  355. print()
  356. # 1. Create call chain diagram
  357. print("[1/5] Generating call chain fusion diagram...")
  358. call_chain = [
  359. 'crypto_get_certificate_data',
  360. 'crypto_cert_fingerprint',
  361. 'crypto_cert_fingerprint_by_hash',
  362. 'crypto_cert_hash'
  363. ]
  364. slices = [
  365. 'g_secret = 0x12345678;',
  366. 'g_key = g_secret ^ 0xDEADBEEF;',
  367. '',
  368. 'printf("key: 0x%x", g_key);'
  369. ]
  370. create_call_chain_diagram(
  371. call_chain, slices,
  372. os.path.join(output_dir, 'demo_call_chain.png')
  373. )
  374. # 2. Create system flow diagram
  375. print("[2/5] Generating system architecture diagram...")
  376. create_fusion_flow_diagram(
  377. os.path.join(output_dir, 'demo_architecture.png')
  378. )
  379. # 3. Create statistics chart
  380. print("[3/5] Generating statistics charts...")
  381. create_statistics_chart(
  382. {},
  383. os.path.join(output_dir, 'demo_statistics.png')
  384. )
  385. # 4. Create code fusion comparison diagram
  386. print("[4/5] Generating code fusion comparison...")
  387. create_code_fusion_example(
  388. os.path.join(output_dir, 'demo_fusion_compare.png')
  389. )
  390. # 5. Create verification result chart
  391. print("[5/5] Generating verification results chart...")
  392. create_verification_result_chart(
  393. os.path.join(output_dir, 'demo_verification.png')
  394. )
  395. print()
  396. print("=" * 60)
  397. print("All visualization charts generated successfully!")
  398. print(f"Output directory: {output_dir}")
  399. print("=" * 60)
  400. # List generated files
  401. print("\nGenerated chart files:")
  402. for f in sorted(os.listdir(output_dir)):
  403. if f.endswith('.png'):
  404. filepath = os.path.join(output_dir, f)
  405. size_kb = os.path.getsize(filepath) / 1024
  406. print(f" - {f} ({size_kb:.1f} KB)")
  407. if __name__ == '__main__':
  408. main()