77#include <sys/stat.h>
88
99#include "frame.piqi.pb-c-patched.h"
10+ #include "trace_consts.h"
1011#include "trace_meta.h"
1112
1213#define MD5LEN 16
1314
14- static void compute_target_md5 (const char * binary_path ) {
15+ static void compute_target_md5 (const char * binary_path ,
16+ guchar target_md5 [MD5LEN ]) {
1517 const GChecksumType md5 = G_CHECKSUM_MD5 ;
16- guchar target_md5 [MD5LEN ];
1718
1819 GChecksum * cs = g_checksum_new (md5 );
1920 FILE * target = fopen (binary_path , "r" );
@@ -38,37 +39,31 @@ static void compute_target_md5(const char *binary_path) {
3839 fclose (target );
3940}
4041
41- static void meta_write_header ( FILE * file ) {
42- // uint64_t toc_off = 0L ;
43- // WRITE(magic_number );
44- // WRITE(out_trace_version) ;
45- // WRITE(frame_arch) ;
46- // WRITE(frame_mach) ;
47- // WRITE(toc_num_frames) ;
48- // WRITE(toc_off );
42+ static void init_tracer ( Tracer * tracer , char * * argv , int argc ) {
43+ tracer__init ( tracer ) ;
44+ tracer -> name = g_strdup ( TRACER_NAME );
45+ tracer -> n_args = argc ;
46+ tracer -> args = argv ;
47+ tracer -> n_envp = 0 ;
48+ tracer -> envp = NULL ;
49+ tracer -> version = g_strdup ( TRACER_VERSION );
4950}
5051
51- static void init_tracer (Tracer * tracer , char * * argv , char * * envp ) {
52- // tracer__init(tracer);
53- // tracer->name = tracer_name;
54- // tracer->n_args = list_length(argv);
55- // tracer->args = argv;
56- // tracer->n_envp = list_length(envp);
57- // tracer->envp = envp;
58- // tracer->version = tracer_version;
59- }
52+ static void init_target (Target * target , const char * bin_path , char * * argv ,
53+ int argc ) {
54+ target__init (target );
6055
61- static void init_target ( Target * target , char * * argv , char * * envp ) {
62- // compute_target_md5( );
63-
64- // target__init( target);
65- // target->path = target_path ;
66- // target->n_args = list_length(argv) ;
67- // target->args = argv;
68- // target->n_envp = list_length(envp) ;
69- // target->envp = envp ;
70- // target->md5sum.len = MD5LEN ;
71- // target->md5sum.data = target_md5 ;
56+ if ( bin_path ) {
57+ guchar * target_md5 = g_malloc0 ( MD5LEN );
58+ compute_target_md5 ( bin_path , target_md5 );
59+ target -> path = g_strdup ( bin_path );
60+ target -> md5sum . len = MD5LEN ;
61+ target -> md5sum . data = target_md5 ;
62+ }
63+ target -> n_args = argc ;
64+ target -> args = argv ;
65+ target -> n_envp = 0 ;
66+ target -> envp = NULL ;
7267}
7368
7469#ifdef G_OS_UNIX
@@ -95,18 +90,74 @@ static bool init_fstats(Fstats *fstats, const char *binary_path) {
9590 return true;
9691}
9792
98- static void write_meta (WLOCKED FILE * file , char * * tracer_argv ,
99- char * * tracer_envp , char * * target_argv ,
100- char * * target_envp ) {
101- MetaFrame meta ;
102- Tracer tracer ;
103- Target target ;
104- Fstats fstats ;
93+ char * get_argv_val (char * * argv , int argc , const char * key ) {
94+ for (size_t i = 0 ; i < argc ; ++ i ) {
95+ if (!strncmp (argv [i ], key , strlen (key ))) {
96+ const char * val = argv [i ] + strlen (key );
97+ if (val [0 ] != '=' ) {
98+ qemu_plugin_outs ("Invalid argument value for " );
99+ qemu_plugin_outs (key );
100+ qemu_plugin_outs ("\n" );
101+ qemu_plugin_outs ("Should be 'key=val'\n" );
102+ return NULL ;
103+ }
104+ val ++ ;
105+ const char * end = strchr (val , ',' );
106+ while (end && * (end - 1 ) == '\\' ) {
107+ // Allow escaped commas.
108+ end = strchr (val , ',' );
109+ }
110+ size_t len = !end ? strlen (val ) : end - val ;
111+ char * argument = g_malloc0 (len + 1 );
112+ memcpy (argument , val , len );
113+ return argument ;
114+ }
115+ }
116+ return NULL ;
117+ }
118+
119+ void file_exists_exit (const char * file ) {
120+ FILE * test = fopen (file , "r" );
121+ if (!test ) {
122+ qemu_plugin_outs ("Failed to open binary file: " );
123+ qemu_plugin_outs (file );
124+ qemu_plugin_outs ("\n" );
125+ exit (1 );
126+ }
127+ fclose (test );
128+ }
129+
130+ void write_meta (WLOCKED FILE * file , char * * plugin_argv , size_t plugin_argc ) {
131+ char * arg_bin_path = get_argv_val (plugin_argv , plugin_argc , "bin_path" );
132+ // Note: Usually we should get the binary path from
133+ // qemu_plugin_path_to_binary(). But it doesn't seem to work due to dependency
134+ // issues. See: https://gitlab.com/qemu-project/qemu/-/issues/3014
135+ const char * bin_path = NULL ; // qemu_plugin_path_to_binary();
136+ if (!bin_path && !arg_bin_path ) {
137+ qemu_plugin_outs ("\nFailed to retrieve the binary path\n" );
138+ qemu_plugin_outs ("This is required.\n" );
139+ qemu_plugin_outs ("You can pass it as plugin argument "
140+ "'bin_path=<path>'.\n\n" );
141+ exit (1 );
142+ } else {
143+ file_exists_exit (arg_bin_path );
144+ }
145+ if (bin_path && arg_bin_path ) {
146+ qemu_plugin_outs (
147+ "'bin_path' argument found, but the binary path is known to the module.\n\
148+ Argument 'bin_path' is ignored.\n" );
149+ }
150+
151+ MetaFrame meta = {0 };
152+ Tracer tracer = {0 };
153+ Target target = {0 };
154+ Fstats fstats = {0 };
105155
106156 meta_frame__init (& meta );
107- init_tracer (& tracer , tracer_argv , tracer_envp );
108- init_target (& target , target_argv , target_envp );
109- init_fstats (& fstats , "target-path" );
157+ init_tracer (& tracer , plugin_argv , plugin_argc );
158+ init_target (& target , bin_path ? bin_path : arg_bin_path , plugin_argv ,
159+ plugin_argc );
160+ init_fstats (& fstats , bin_path ? bin_path : arg_bin_path );
110161
111162 meta .tracer = & tracer ;
112163 meta .target = & target ;
@@ -119,11 +170,24 @@ static void write_meta(WLOCKED FILE *file, char **tracer_argv,
119170 meta .host = host ;
120171
121172 size_t msg_size = meta_frame__get_packed_size (& meta );
122- uint8_t * packed_buffer = g_alloca (msg_size );
173+ uint8_t * packed_buffer = g_malloc0 (msg_size );
123174 uint64_t packed_size = meta_frame__pack (& meta , packed_buffer );
175+ g_assert (msg_size == packed_size );
124176 WRITE (packed_size );
125- WRITE_BUF (& meta , packed_size );
126177
127- free (user );
128- free (host );
178+ // I don't know why, but ASAN crashes at this line if the WRITE_BUF macro
179+ // is used. Although it should be the exact same code.
180+ if (fwrite ((packed_buffer ), 1 , (packed_size ), file ) != packed_size ) {
181+ err (1 , "fwrite failed" );
182+ }
183+
184+ g_free (packed_buffer );
185+ g_free (tracer .name );
186+ g_free (tracer .version );
187+ g_free (target .path );
188+ g_free (target .md5sum .data );
189+
190+ g_free (user );
191+ g_free (host );
192+ g_free (arg_bin_path );
129193}
0 commit comments