00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #include <stdio.h>
00060 #include <algorithm>
00061 #include <vector>
00062
00063 using std::vector;
00064
00065 #include "profile.h"
00066 #include "profile_errors.h"
00067
00068 #define ERRORS_INCLUDED // force errors.h not included by
00069
00070 #define Is_True(x,y) // Is_True not available at runtime
00071 #define DevWarn(x) // DevWarn not available at runtimex
00072 #include "fb_info.h"
00073
00074 #include "dump.h"
00075
00076
00077
00078
00079
00080 static char* ERR_POS = "Error in positioning within %s";
00081 static char* ERR_WRITE = "Error in writing to %s";
00082
00083
00084
00085 static inline ULONG
00086 align (ULONG offset, UINT32 alignment)
00087 {
00088 --alignment;
00089 return ((offset + alignment) & ~alignment);
00090 }
00091
00092
00093 static inline void
00094 realign_file (FILE* fp, ULONG& offset, UINT32 alignment, char* fname)
00095 {
00096 if (offset % alignment == 0)
00097 return;
00098
00099 ULONG new_offset = align (offset, alignment);
00100 FSEEK (fp, new_offset - offset, SEEK_CUR, ERR_POS, fname);
00101 offset = new_offset;
00102 }
00103
00104
00105
00106
00107 void
00108 Dump_all(FILE *fp, char *output_filename)
00109 {
00110 HASH_MAP::iterator i;
00111
00112 vector<Pu_Hdr> Pu_Hdr_Table;
00113 vector<char *> Str_Table;
00114
00115 Fb_Hdr fb_hdr;
00116
00117 strcpy ((char *) fb_hdr.fb_ident, INSTR_MAG);
00118 fb_hdr.fb_version = INSTR_CURRENT;
00119 fb_hdr.fb_pu_hdr_ent_size = sizeof(Pu_Hdr);
00120 fb_hdr.phase_num = Instrumentation_Phase_Num();
00121 fb_hdr.fb_profile_offset = align (sizeof(Fb_Hdr), sizeof(mUINT64));
00122
00123
00124 FSEEK(fp, fb_hdr.fb_profile_offset, SEEK_SET, ERR_POS, output_filename);
00125
00126
00127
00128 for( i = PU_Profile_Handle_Table.begin();
00129 i != PU_Profile_Handle_Table.end(); i++) {
00130 PU_PROFILE_HANDLE pu_handle = (*i).second;
00131 Dump_PU_Profile(fp, pu_handle, output_filename, Pu_Hdr_Table, Str_Table);
00132 }
00133
00134
00135
00136 Dump_Fb_File_Pu_Table(fp, output_filename, Pu_Hdr_Table, fb_hdr);
00137
00138
00139
00140 Dump_Fb_File_Str_Table(fp, output_filename, Str_Table, fb_hdr);
00141
00142
00143
00144 Dump_Fb_File_Header(fp, output_filename,fb_hdr);
00145 }
00146
00147
00148 void
00149 Dump_Fb_File_Header(FILE *fp, char *output_filename, Fb_Hdr& fb_hdr)
00150 {
00151
00152 FSEEK(fp,0,SEEK_SET, ERR_POS, output_filename);
00153
00154
00155 FWRITE(&fb_hdr, sizeof(Fb_Hdr), 1, fp, ERR_WRITE, output_filename);
00156
00157
00158 FSEEK(fp,0,SEEK_END, ERR_POS, output_filename);
00159 }
00160
00161
00162 namespace {
00163
00164
00165
00166 static void
00167 Convert_Invoke_Profile (vector<FB_Info_Invoke>& dest,
00168 const Invoke_Profile_Vector& src) {
00169 dest.reserve (src.size ());
00170
00171 for (Invoke_Profile_Vector::const_iterator first (src.begin ());
00172 first != src.end (); ++first) {
00173
00174 dest.push_back (FB_Info_Invoke (FB_FREQ (first->invoke_count)));
00175 }
00176 }
00177
00178
00179 static void
00180 Convert_Branch_Profile (vector<FB_Info_Branch>& dest,
00181 const Branch_Profile_Vector& src) {
00182 dest.reserve (src.size ());
00183
00184 for (Branch_Profile_Vector::const_iterator first (src.begin ());
00185 first != src.end (); ++first) {
00186
00187 dest.push_back (FB_Info_Branch (FB_FREQ (first->taken),
00188 FB_FREQ (first->not_taken)));
00189 }
00190 }
00191
00192 #ifdef KEY
00193 static void Convert_Value_Profile( vector<FB_Info_Value>& dest,
00194 const Value_Profile_Vector& src )
00195 {
00196 dest.reserve (src.size ());
00197
00198 for( Value_Profile_Vector::const_iterator first(src.begin ());
00199 first != src.end (); ++first ){
00200 FB_Info_Value info( first->num_values,
00201 first->exe_counter,
00202 first->value,
00203 first->freq );
00204 dest.push_back( info );
00205 }
00206 }
00207
00208 static void Convert_Value_FP_Bin_Profile(
00209 vector<FB_Info_Value_FP_Bin>& dest,
00210 const Value_FP_Bin_Profile_Vector& src )
00211 {
00212 dest.reserve (src.size ());
00213
00214 for( Value_FP_Bin_Profile_Vector::const_iterator first(src.begin ());
00215 first != src.end (); ++first ){
00216 FB_Info_Value_FP_Bin info( first->exe_counter,
00217 first->zopnd0,
00218 first->zopnd1,
00219 first->uopnd0,
00220 first->uopnd1 );
00221 dest.push_back( info );
00222 }
00223 }
00224 #endif
00225
00226 template <class T>
00227 static void
00228 Convert_Switch_Profile (FB_Info_Switch& dest, T& src) {
00229
00230 dest.freq_targets.reserve (src.size ());
00231
00232 for (typename T::value_type::const_iterator
00233 first (src.Get_Targets_Profile ().begin ());
00234 first != src.Get_Targets_Profile ().end (); ++first) {
00235
00236 dest.freq_targets.push_back (FB_FREQ (*first));
00237 }
00238 }
00239
00240
00241 static void
00242 Convert_Loop_Profile (vector<FB_Info_Loop>& dest,
00243 const Loop_Profile_Vector& src) {
00244 dest.reserve (src.size ());
00245
00246 for (Loop_Profile_Vector::const_iterator first (src.begin ());
00247 first != src.end (); ++first) {
00248
00249
00250 INT64 zero_trips = first->num_zero_trips;
00251 if ( first->invocation_count > 0 && first->last_trip_count == 0 ) {
00252 zero_trips++;
00253 }
00254
00255 const INT64 positive = first->invocation_count - zero_trips;
00256 const INT64 back = first->total_trip_count - first->invocation_count + zero_trips;
00257 #if 0
00258 FB_Info_Loop loop (FB_FREQ (zero_trips),
00259 FB_FREQ ( tmp),
00260 FB_FREQ (FB_FREQ_TYPE_UNKNOWN),
00261 FB_FREQ (tmp1));
00262
00263 dest.push_back(loop);
00264 #endif
00265 dest.push_back(FB_Info_Loop(FB_FREQ (zero_trips),
00266 FB_FREQ (positive),
00267 FB_FREQ (FB_FREQ_TYPE_UNKNOWN),
00268 FB_FREQ (back)));
00269 }
00270 }
00271
00272 static void
00273 Convert_Short_Circuit_Profile (vector<FB_Info_Circuit>& dest,
00274 const Short_Circuit_Profile_Vector& src) {
00275 dest.reserve (src.size ());
00276
00277 for (Short_Circuit_Profile_Vector::const_iterator first (src.begin ());
00278 first != src.end (); ++first) {
00279
00280 dest.push_back
00281 (FB_Info_Circuit (FB_FREQ (FB_FREQ_TYPE_UNKNOWN),
00282 FB_FREQ (first->right_taken_count),
00283 FB_FREQ (first->neither_taken_count)));
00284 }
00285 }
00286
00287 static void
00288 Convert_Call_Profile (vector<FB_Info_Call>& dest,
00289 const Call_Profile_Vector& src) {
00290 dest.reserve (src.size ());
00291
00292 for (Call_Profile_Vector::const_iterator first (src.begin ());
00293 first != src.end (); ++first) {
00294
00295 dest.push_back
00296 (FB_Info_Call (FB_FREQ (first->entry_count),
00297 FB_FREQ (first->exit_count),
00298 first->entry_count == first->exit_count));
00299 }
00300 }
00301
00302
00303 struct POSITION {
00304 ULONG offset;
00305 INT32 num_entries;
00306
00307 POSITION () {}
00308 POSITION (ULONG ofst, INT32 num) : offset (ofst), num_entries (num) {}
00309 };
00310
00311 template <class T>
00312 POSITION
00313 Dump_PU_Profile (FILE *fp, ULONG& offset, const T& profile, char *fname) {
00314
00315 realign_file (fp, offset, sizeof(mINT64), fname);
00316
00317 POSITION pos (offset, profile.size ());
00318
00319 FWRITE (&(profile.front ()), sizeof(typename T::value_type),
00320 profile.size (), fp, ERR_WRITE, fname);
00321
00322 offset += profile.size () * sizeof(typename T::value_type);
00323 return pos;
00324 }
00325
00326
00327 template <class T>
00328 POSITION
00329 Dump_PU_Switch_Profile (FILE *fp, ULONG& offset, T& profile,
00330 ULONG& target_offset, char *fname) {
00331
00332 realign_file (fp, offset, sizeof(mINT64), fname);
00333
00334 POSITION pos (offset, profile.size ());
00335
00336 typename T::iterator first (profile.begin ());
00337
00338 while (first != profile.end ()) {
00339
00340 FB_Info_Switch fb_info;
00341 Convert_Switch_Profile (fb_info, *first);
00342
00343 FWRITE (&(fb_info.freq_targets.front ()), sizeof(FB_FREQ),
00344 fb_info.freq_targets.size (), fp, ERR_WRITE, fname);
00345
00346 offset += sizeof(INT64) * fb_info.freq_targets.size ();
00347
00348 ++first;
00349 }
00350
00351 target_offset = offset;
00352
00353 first = profile.begin ();
00354 while (first != profile.end ()) {
00355 INT32 num_targs = first->Get_Targets_Profile ().size ();
00356 FWRITE (&num_targs, sizeof(INT32), 1, fp, ERR_WRITE, fname);
00357 ++first;
00358 }
00359
00360 offset += profile.size () * sizeof(INT32);
00361 return pos;
00362 }
00363
00364 }
00365
00366
00367
00368
00369
00370 void
00371 Dump_PU_Profile(FILE *fp, PU_PROFILE_HANDLE pu_handle, char * fname,
00372 vector<Pu_Hdr> & Pu_Hdr_Table, vector<char *> & Str_Table)
00373 {
00374 static ULONG Str_Offset;
00375 static ULONG PU_Offset;
00376
00377
00378 Str_Table.push_back(pu_handle->pu_name);
00379
00380
00381 realign_file (fp, PU_Offset, sizeof(mINT64), fname);
00382
00383 Pu_Hdr pu_hdr;
00384
00385 pu_hdr.pu_checksum = pu_handle->checksum;
00386 pu_hdr.pu_size = pu_handle->pu_size;
00387 pu_hdr.runtime_fun_address = pu_handle->runtime_fun_address;
00388 pu_hdr.pu_name_index = Str_Offset;
00389 pu_hdr.pu_file_offset = PU_Offset;
00390
00391 ULONG offset = 0;
00392
00393 POSITION pos;
00394
00395 {
00396 vector<FB_Info_Invoke> fb_info;
00397 Convert_Invoke_Profile (fb_info, pu_handle->Get_Invoke_Table ());
00398 pos = Dump_PU_Profile (fp, offset, fb_info, fname);
00399 pu_hdr.pu_inv_offset = pos.offset;
00400 pu_hdr.pu_num_inv_entries = pos.num_entries;
00401 }
00402
00403 {
00404 vector<FB_Info_Branch> fb_info;
00405 Convert_Branch_Profile (fb_info, pu_handle->Get_Branch_Table ());
00406 pos = Dump_PU_Profile (fp, offset, fb_info, fname);
00407 pu_hdr.pu_br_offset = pos.offset;
00408 pu_hdr.pu_num_br_entries = pos.num_entries;
00409 }
00410
00411 pos = Dump_PU_Switch_Profile (fp, offset, pu_handle->Get_Switch_Table (),
00412 pu_hdr.pu_switch_target_offset, fname);
00413 pu_hdr.pu_switch_offset = pos.offset;
00414 pu_hdr.pu_num_switch_entries = pos.num_entries;
00415
00416 pos = Dump_PU_Switch_Profile (fp, offset, pu_handle->Get_Compgoto_Table (),
00417 pu_hdr.pu_cgoto_target_offset, fname);
00418 pu_hdr.pu_cgoto_offset = pos.offset;
00419 pu_hdr.pu_num_cgoto_entries = pos.num_entries;
00420
00421 {
00422 vector<FB_Info_Loop> fb_info;
00423 Convert_Loop_Profile (fb_info, pu_handle->Get_Loop_Table ());
00424 pos = Dump_PU_Profile (fp, offset, fb_info, fname);
00425 pu_hdr.pu_loop_offset = pos.offset;
00426 pu_hdr.pu_num_loop_entries = pos.num_entries;
00427 }
00428
00429 {
00430 vector<FB_Info_Circuit> fb_info;
00431 Convert_Short_Circuit_Profile (fb_info,
00432 pu_handle->Get_Short_Circuit_Table ());
00433 pos = Dump_PU_Profile (fp, offset, fb_info, fname);
00434 pu_hdr.pu_scircuit_offset = pos.offset;
00435 pu_hdr.pu_num_scircuit_entries = pos.num_entries;
00436 }
00437
00438 {
00439 vector<FB_Info_Call> fb_info;
00440 Convert_Call_Profile (fb_info, pu_handle->Get_Call_Table ());
00441 pos = Dump_PU_Profile (fp, offset, fb_info, fname);
00442 pu_hdr.pu_call_offset = pos.offset;
00443 pu_hdr.pu_num_call_entries = pos.num_entries;
00444 }
00445
00446 #ifdef KEY
00447 {
00448 vector<FB_Info_Value> fb_info;
00449 Convert_Value_Profile( fb_info, pu_handle->Get_Value_Table() );
00450 pos = Dump_PU_Profile( fp, offset, fb_info, fname );
00451 pu_hdr.pu_value_offset = pos.offset;
00452 pu_hdr.pu_num_value_entries = pos.num_entries;
00453 }
00454
00455 {
00456 vector<FB_Info_Value_FP_Bin> fb_info;
00457 Convert_Value_FP_Bin_Profile( fb_info,
00458 pu_handle->Get_Value_FP_Bin_Table() );
00459 pos = Dump_PU_Profile( fp, offset, fb_info, fname );
00460 pu_hdr.pu_value_fp_bin_offset = pos.offset;
00461 pu_hdr.pu_num_value_fp_bin_entries = pos.num_entries;
00462 }
00463 #endif
00464
00465 {
00466 pos = Dump_PU_Profile (fp, offset, pu_handle->Get_Icall_Table (), fname);
00467 pu_hdr.pu_icall_offset = pos.offset;
00468 pu_hdr.pu_num_icall_entries = pos.num_entries;
00469 }
00470
00471
00472 Pu_Hdr_Table.push_back(pu_hdr);
00473
00474 Str_Offset += strlen(pu_handle->pu_name) + 1;
00475 PU_Offset += (offset - pu_hdr.pu_inv_offset);
00476 }
00477
00478
00479
00480
00481 void
00482 Dump_Fb_File_Pu_Table(FILE *fp, char *fname, vector<Pu_Hdr>& Pu_Hdr_Table,
00483 Fb_Hdr& fb_hdr)
00484 {
00485 ULONG offset = ftell(fp);
00486 realign_file (fp, offset,
00487 #if defined(__GNUC__)
00488 __alignof__(Pu_Hdr),
00489 #else
00490 __builtin_alignof(Pu_Hdr),
00491 #endif
00492 fname);
00493
00494 fb_hdr.fb_pu_hdr_offset = offset;
00495 fb_hdr.fb_pu_hdr_num = Pu_Hdr_Table.size();
00496
00497 for (size_t i = 0; i < Pu_Hdr_Table.size(); i++) {
00498 Pu_Hdr & pu_hdr_entry = Pu_Hdr_Table[i];
00499 FWRITE(&pu_hdr_entry, sizeof(Pu_Hdr), 1, fp, ERR_WRITE, fname);
00500 }
00501 }
00502
00503
00504
00505
00506 void
00507 Dump_Fb_File_Str_Table(FILE *fp, char *fname, vector<char *>& Str_Table,
00508 Fb_Hdr& fb_hdr)
00509 {
00510 ULONG table_size = 0;
00511
00512 fb_hdr.fb_str_table_offset = ftell(fp);
00513
00514 for (size_t i = 0; i < Str_Table.size(); i++) {
00515 char *pu_name = Str_Table[i];
00516 FWRITE(pu_name, strlen(pu_name) + 1, 1, fp, ERR_WRITE, fname);
00517
00518 table_size += strlen(pu_name) + 1;
00519 }
00520
00521 fb_hdr.fb_str_table_size = table_size;
00522 }