22// SPDX-License-Identifier: GPL-2.0-only
33
44#include <glib.h>
5+ #include <stdio.h>
56
67#include "frame_arch.h"
78#include "frame_buffer.h"
89#include "qemu-plugin.h"
10+ #include "trace_consts.h"
911#include "tracing.h"
1012
11- static TraceState state ;
13+ static TraceState state = { 0 } ;
1214
1315static void add_mem_op (VCPU * vcpu , unsigned int vcpu_index , FrameBuffer * fbuf ,
1416 uint64_t vaddr , qemu_plugin_mem_value * mval ,
@@ -100,9 +102,13 @@ static GPtrArray *registers_init(void) {
100102static void write_toc_entry (FrameBuffer * fbuf ) {
101103 g_rw_lock_writer_lock (& state .file_lock );
102104 g_rw_lock_writer_lock (& state .toc_entries_offsets_lock );
103- frame_buffer_flush_to_file (fbuf , state .file );
105+ g_rw_lock_writer_lock (& state .total_num_frames_lock );
106+
107+ state .total_num_frames += frame_buffer_flush_to_file (fbuf , state .file );
104108 uint64_t next_toc_entry = ftell (state .file );
105109 g_array_append_val (state .toc_entries_offsets , next_toc_entry );
110+
111+ g_rw_lock_writer_unlock (& state .total_num_frames_lock );
106112 g_rw_lock_writer_unlock (& state .toc_entries_offsets_lock );
107113 g_rw_lock_writer_unlock (& state .file_lock );
108114}
@@ -155,9 +161,7 @@ static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index) {
155161
156162 VCPU * vcpu = g_malloc0 (sizeof (VCPU ));
157163 vcpu -> registers = registers_init ();
158- if (!vcpu -> registers ) {
159- g_assert (false);
160- }
164+ g_assert (vcpu -> registers );
161165 g_ptr_array_insert (state .vcpus , vcpu_index , vcpu );
162166
163167 FrameBuffer * vcpu_frame_buffer = frame_buffer_new ();
@@ -191,12 +195,46 @@ static void cb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) {
191195}
192196
193197static void plugin_exit (qemu_plugin_id_t id , void * udata ) {
194- // Dump rest of frames to file.
198+ g_rw_lock_writer_lock (& state .frame_buffer_lock );
199+ for (size_t i = 0 ; i < state .vcpus -> len ; ++ i ) {
200+ FrameBuffer * fbuf = g_ptr_array_index (state .frame_buffer , i );
201+ write_toc_entry (fbuf );
202+ }
203+ g_rw_lock_writer_unlock (& state .frame_buffer_lock );
204+
205+ g_rw_lock_writer_lock (& state .file_lock );
206+ g_rw_lock_reader_lock (& state .toc_entries_offsets_lock );
207+ g_rw_lock_reader_lock (& state .total_num_frames_lock );
208+
209+ FILE * file = state .file ;
210+
211+ // Update fields in the header
212+ uint64_t toc_index_offset = ftell (file );
213+ SEEK (offset_toc_index_offset );
214+ WRITE (toc_index_offset );
215+ SEEK (offset_total_num_frames );
216+ WRITE (state .total_num_frames );
217+
218+ // Write the TOC index
219+ SEEK (toc_index_offset );
220+ uint64_t m = state .toc_entries_offsets -> len ;
221+ WRITE (m );
222+
223+ for (size_t i = 0 ; i < m ; ++ i ) {
224+ uint64_t toc_entry_off =
225+ g_array_index (state .toc_entries_offsets , uint64_t , i );
226+ WRITE (toc_entry_off );
227+ }
228+ fclose (file );
229+
230+ g_rw_lock_reader_unlock (& state .total_num_frames_lock );
231+ g_rw_lock_reader_unlock (& state .toc_entries_offsets_lock );
232+ g_rw_lock_writer_unlock (& state .file_lock );
195233}
196234
197235static bool get_frame_arch_mach (const char * target_name , uint64_t * arch ,
198236 uint64_t * mach ) {
199- * arch = 0 ;
237+ * mach = 0 ;
200238 * arch = frame_arch_last ;
201239 const char * aname = arch_map [0 ].name ;
202240 for (size_t i = 0 ; arch_map [i ].name ; ++ i ) {
@@ -216,13 +254,13 @@ static bool write_header(FILE *file, const char *target_name) {
216254 qemu_plugin_outs ("Failed to get arch/mach.\n" );
217255 return false;
218256 }
219- uint64_t num_toc_entries = 0ULL ;
257+ uint64_t total_num_frames = 0ULL ;
220258 uint64_t toc_index_offset = 0ULL ;
221259 WRITE (magic_number );
222260 WRITE (trace_version );
223261 WRITE (frame_arch );
224262 WRITE (frame_mach );
225- WRITE (num_toc_entries ); // Gets updated later
263+ WRITE (total_num_frames ); // Gets updated later
226264 WRITE (toc_index_offset ); // Gets updated later
227265 return true;
228266}
0 commit comments