1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/*****************************************************************************\
6* *
7* CorBBTProf.h - File format for profile data *
8* *
9* Version 1.0 *
10*******************************************************************************
11* *
12* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY *
13* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE *
14* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR *
15* PURPOSE. *
16* *
17\*****************************************************************************/
18
19#ifndef _COR_BBTPROF_H_
20#define _COR_BBTPROF_H_
21
22#include <cor.h>
23#include <corinfo.h>
24
25const CorTokenType ibcExternalNamespace = CorTokenType(0x61000000);
26const CorTokenType ibcExternalType = CorTokenType(0x62000000);
27const CorTokenType ibcExternalSignature = CorTokenType(0x63000000);
28const CorTokenType ibcExternalMethod = CorTokenType(0x64000000);
29const CorTokenType ibcTypeSpec = CorTokenType(0x68000000);
30const CorTokenType ibcMethodSpec = CorTokenType(0x69000000);
31
32typedef mdToken idExternalNamespace; // External Namespace token in the IBC data
33typedef mdToken idExternalType; // External Type token in the IBC data
34typedef mdToken idExternalSignature; // External Signature token in the IBC data
35typedef mdToken idExternalMethod; // External Method token in the IBC data
36typedef mdToken idTypeSpec; // TypeSpec token in the IBC data
37typedef mdToken idMethodSpec; // MethodSpec token in the IBC data
38
39#define idExternalNamespaceNil ((idExternalNamespace) ibcExternalNamespace)
40#define idExternalTypeNil ((idExternalType) ibcExternalType)
41#define idExternalSignatureNil ((idExternalSignature) ibcExternalSignature)
42#define idExternalMethodNil ((idExternalMethod) ibcExternalMethod)
43#define idTypeSpecNil ((idTypeSpec) ibcTypeSpec)
44#define idMethodSpecNil ((idMethodSpec) ibcMethodSpec)
45
46//
47// File format:
48//
49// CORBBTPROF_FILE_HEADER
50// CORBBTPROF_SECTION_TABLE_HEADER
51// CORBBTPROF_SECTION_TABLE_ENTRY
52// ... (can be multiple entries)
53//
54// Method block counts section:
55// CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER
56// CORBBTPROF_METHOD_HEADER
57// CORBBTPROF_BLOCK_DATA
58// ... (can be multiple method header/block data entries)
59//
60// Method load order section:
61// CORBBTPROF_TOKEN_LIST_SECTION_HEADER
62// ... (list of tokens)
63//
64// Type token usage information
65// CORBBTPROF_TOKEN_LIST_SECTION_HEADER
66// ... (list of tokens)
67//
68
69// MethodDef token usage information
70// CORBBTPROF_TOKEN_LIST_SECTION_HEADER
71// ... (list of tokens)
72//
73
74// RIDs to not use slim headers section
75// CORBBTPROF_TOKEN_LIST_SECTION_HEADER
76// ... (list of tokens)
77//
78
79// Metadata hints to re-order some tables
80// Instantiated TypeSPecs to re-order EEClasses
81//
82// The header for the profile data file.
83// ... (list of CORBBTPROF_BLOB_ENTRY)
84// terminated by null
85
86struct CORBBTPROF_FILE_HEADER
87{
88 DWORD HeaderSize;
89 DWORD Magic;
90 DWORD Version;
91 GUID MVID;
92};
93
94// Optional in V1 and V2. Usually present in V2. Must be present in V3.
95struct CORBBTPROF_FILE_OPTIONAL_HEADER
96{
97 DWORD Size; // Including the size field
98 DWORD MinorVersion;
99 DWORD FileFlags; // Only in V3 or later
100 // future fields
101};
102
103enum CORBBTPROF_FILE_FLAGS
104{
105 CORBBTPROF_FILE_FLAG_MINIFIED = 1,
106 CORBBTPROF_FILE_FLAG_PARTIAL_NGEN = 2
107};
108
109enum
110{
111 CORBBTPROF_V0_VERSION = 0,
112 CORBBTPROF_V1_VERSION = 1,
113 CORBBTPROF_V2_VERSION = 2,
114 CORBBTPROF_V3_VERSION = 3,
115 CORBBTPROF_CURRENT_VERSION = CORBBTPROF_V2_VERSION, // V3 is opt-in
116 CORBBTPROF_MAGIC = 0xb1d0f11e,
117 CORBBTPROF_END_TOKEN = 0xb4356f98
118};
119
120//
121// The profile data can be mapped anywhere in memory. So instead of using pointers,
122// to denote sections, we will instead use offsets from the beginning of the file.
123//
124
125struct Section
126{
127 DWORD Offset;
128 DWORD Size;
129};
130
131//
132// Section types, where various sections contains different types of profile data.
133//
134
135#define CORBBTPROF_TOKEN_MAX_NUM_FLAGS 32
136
137enum TypeProfilingDataFlags
138{
139 // Important: update toolbox\ibcmerge\ibcmerge.cs if you change these
140 ReadMethodTable = 0, // 0x00001
141 ReadEEClass = 1, // 0x00002
142 WriteEEClass = 2, // 0x00004
143// ReadStoredEnumData = 3, // 0x00008 // obsolete
144 ReadFieldDescs = 4, // 0x00010
145 ReadCCtorInfo = 5, // 0x00020
146 ReadClassHashTable = 6, // 0x00040
147 ReadDispatchMap = 7, // 0x00080
148 ReadDispatchTable = 8, // 0x00100
149 ReadMethodTableWriteableData = 9, // 0x00200
150 ReadFieldMarshalers = 10, // 0x00400
151// WriteDispatchTable = 11, // 0x00800 // obsolete
152// WriteMethodTable = 12, // 0x01000 // obsolete
153 WriteMethodTableWriteableData = 13, // 0x02000
154 ReadTypeDesc = 14, // 0x04000
155 WriteTypeDesc = 15, // 0x08000
156 ReadTypeHashTable = 16, // 0x10000
157// WriteTypeHashTable = 17, // 0x20000 // obsolete
158// ReadDictionary = 18, // 0x40000 // obsolete
159// WriteDictionary = 19, // 0x80000 // obsolete
160 ReadNonVirtualSlots = 20, // 0x100000
161};
162
163enum MethodProfilingDataFlags
164{
165 // Important: update toolbox\ibcmerge\ibcmerge.cs if you change these
166 ReadMethodCode = 0, // 0x00001 // Also means the method was executed
167 ReadMethodDesc = 1, // 0x00002
168 RunOnceMethod = 2, // 0x00004
169 RunNeverMethod = 3, // 0x00008
170// MethodStoredDataAccess = 4, // 0x00010 // obsolete
171 WriteMethodDesc = 5, // 0x00020
172// ReadFCallHash = 6, // 0x00040 // obsolete
173 ReadGCInfo = 7, // 0x00080
174 CommonReadGCInfo = 8, // 0x00100
175// ReadMethodDefRidMap = 9, // 0x00200 // obsolete
176 ReadCerMethodList = 10, // 0x00400
177 ReadMethodPrecode = 11, // 0x00800
178 WriteMethodPrecode = 12, // 0x01000
179 ExcludeHotMethodCode = 13, // 0x02000 // Hot method should be excluded from the ReadyToRun image
180 ExcludeColdMethodCode = 14, // 0x04000 // Cold method should be excluded from the ReadyToRun image
181 DisableInlining = 15, // 0x08000 // Disable inlining of this method in optimized AOT native code
182};
183
184enum GeneralProfilingDataFlags
185{
186 // Important: update ibcmerge.cs if you change these
187 // ZapImage.h depends on 0xFFFFFFFF being an invalid flag value. If this
188 // changes, update ReadFlagWithMemory in that file.
189 // Important: make sure these don't collide with TypeProfilingDataFlags or MethodProfilingDataFlags
190 // These grow downward from CORBBTPROF_TOKEN_MAX_NUM_FLAGS-1 to minimize the chance of collision
191 ProfilingFlags_MetaData = 31, // 0x800...
192 CommonMetaData = 30, // 0x400...
193 RidMap = 29, // 0x200...
194 RVAFieldData = 28, // 0x100...
195 ProfilingFlags_MetaDataSearch = 27, // 0x080...
196};
197
198enum BlobType
199{
200 /* IMPORTANT: Keep the first four enums together in the same order and at
201 the very begining of this enum. See MetaModelPub.h for the order */
202 MetadataStringPool = 0,
203 MetadataGuidPool = 1,
204 MetadataBlobPool = 2,
205 MetadataUserStringPool = 3,
206
207 FirstMetadataPool = 0,
208 LastMetadataPool = 3,
209
210 // SectionFormat only supports tokens, which have to already exist in the module.
211 // For instantiated paramterized types, there may be no corresponding token
212 // in the module, if a dependent module caused the type to be instantiated.
213 // For such instantiated types, we save a blob/signature to identify the type.
214 //
215 ParamTypeSpec = 4, // Instantiated Type Signature
216 ParamMethodSpec = 5, // Instantiated Method Signature
217 ExternalNamespaceDef = 6, // External Namespace Token Definition
218 ExternalTypeDef = 7, // External Type Token Definition
219 ExternalSignatureDef = 8, // External Signature Definition
220 ExternalMethodDef = 9, // External Method Token Definition
221
222 IllegalBlob = 10, // Failed to allocate the blob
223
224 EndOfBlobStream = -1
225};
226
227enum SectionFormat
228{
229 // Important: update ibcmerge.cs if you change these
230 ScenarioInfo = 0,
231 MethodBlockCounts = 1, // Basic-block counts. Cold blocks will be placed in the cold-code section
232 BlobStream = 2, // metadata access, inst-type-spec and inst-method-spec blobs
233
234 FirstTokenFlagSection = 3,
235
236 ModuleProfilingData = FirstTokenFlagSection + (mdtModule >> 24),
237 TypeRefProfilingData = FirstTokenFlagSection + (mdtTypeRef >> 24),
238 TypeProfilingData = FirstTokenFlagSection + (mdtTypeDef >> 24),
239 FieldDefProfilingData = FirstTokenFlagSection + (mdtFieldDef >> 24),
240 MethodProfilingData = FirstTokenFlagSection + (mdtMethodDef >> 24),
241 ParamDefProfilingData = FirstTokenFlagSection + (mdtParamDef >> 24),
242 InterfaceImplProfilingData = FirstTokenFlagSection + (mdtInterfaceImpl >> 24),
243 MemberRefProfilingData = FirstTokenFlagSection + (mdtMemberRef >> 24),
244 CustomAttributeProfilingData = FirstTokenFlagSection + (mdtCustomAttribute >> 24),
245 PermissionProfilingData = FirstTokenFlagSection + (mdtPermission >> 24),
246 SignatureProfilingData = FirstTokenFlagSection + (mdtSignature >> 24),
247 EventProfilingData = FirstTokenFlagSection + (mdtEvent >> 24),
248 PropertyProfilingData = FirstTokenFlagSection + (mdtProperty >> 24),
249 ModuleRefProfilingData = FirstTokenFlagSection + (mdtModuleRef >> 24),
250 TypeSpecProfilingData = FirstTokenFlagSection + (mdtTypeSpec >> 24),
251 AssemblyProfilingData = FirstTokenFlagSection + (mdtAssembly >> 24),
252 AssemblyRefProfilingData = FirstTokenFlagSection + (mdtAssemblyRef >> 24),
253 FileProfilingData = FirstTokenFlagSection + (mdtFile >> 24),
254 ExportedTypeProfilingData = FirstTokenFlagSection + (mdtExportedType >> 24),
255 ManifestResourceProfilingData = FirstTokenFlagSection + (mdtManifestResource >> 24),
256 GenericParamProfilingData = FirstTokenFlagSection + (mdtGenericParam >> 24),
257 MethodSpecProfilingData = FirstTokenFlagSection + (mdtMethodSpec >> 24),
258 GenericParamConstraintProfilingData = FirstTokenFlagSection + (mdtGenericParamConstraint >> 24),
259
260 StringPoolProfilingData,
261 GuidPoolProfilingData,
262 BlobPoolProfilingData,
263 UserStringPoolProfilingData,
264
265 FirstMetadataPoolSection = StringPoolProfilingData,
266 LastMetadataPoolSection = UserStringPoolProfilingData,
267 LastTokenFlagSection = LastMetadataPoolSection,
268
269 IbcTypeSpecSection,
270 IbcMethodSpecSection,
271
272 GenericTypeProfilingData = 63, // Deprecated with V2 IBC data
273 SectionFormatCount = 64, // 0x40
274
275 SectionFormatInvalid = -1
276};
277
278struct CORBBTPROF_SECTION_TABLE_ENTRY
279{
280 SectionFormat FormatID;
281 Section Data;
282};
283
284struct CORBBTPROF_SECTION_TABLE_HEADER
285{
286 DWORD NumEntries;
287 CORBBTPROF_SECTION_TABLE_ENTRY Entries[0];
288};
289
290//
291// ScenarioInfo section
292//
293
294struct CORBBTPROF_SCENARIO_RUN
295{
296 FILETIME runTime; // the FILETIME when the scenario was cnt
297 GUID mvid; // The GUID of this assembly when the scenario was run (useful for incremental ibcdata)
298 DWORD cCmdLine; // the count of WCHAR's in the cmdLine for this run of the scenario
299 DWORD cSystemInfo; // the count of WCHAR's in the systemInfo string for this run of the scenario
300 WCHAR cmdLine[0]; // the command line used, the array is 'cName' in length
301// WCHAR systemInfo[]; // the system information, the array is 'cSystemInfo' in length
302
303 DWORD sizeofCmdLine()
304 {
305 return (cCmdLine * (DWORD)sizeof(WCHAR));
306 }
307
308 DWORD sizeofSystemInfo()
309 {
310 return (cSystemInfo * (DWORD)sizeof(WCHAR));
311 }
312
313 DWORD Size()
314 {
315 return (DWORD)sizeof(CORBBTPROF_SCENARIO_RUN) + sizeofCmdLine() + sizeofSystemInfo();
316 }
317
318 CORBBTPROF_SCENARIO_RUN* GetNextRun()
319 {
320 return reinterpret_cast< CORBBTPROF_SCENARIO_RUN* >(
321 reinterpret_cast< PBYTE >( this + 1 ) + Size() );
322 }
323};
324
325struct CORBBTPROF_SCENARIO_INFO
326{
327 DWORD ordinal; // the id number for this scenario
328 DWORD mask; // the one-bit mask use to identify this scenario
329 DWORD priority; // the priority of this scenario
330 DWORD numRuns; // the number of times this scenario was run
331 DWORD cName; // the count of WCHAR's in name[]
332 WCHAR name[0]; // the name of this scenario, the array is 'cName' in length
333// CORBBTPROF_SCENARIO_RUN run[]; // the array is 'numRuns' in length
334
335 DWORD sizeofName()
336 {
337 return (DWORD) (cName * sizeof(WCHAR));
338 }
339
340 DWORD Size()
341 {
342 return (DWORD) sizeof(CORBBTPROF_SCENARIO_INFO) + sizeofName() + sizeofRuns();
343 }
344
345 CORBBTPROF_SCENARIO_RUN* GetScenarioRun()
346 {
347 return reinterpret_cast< CORBBTPROF_SCENARIO_RUN* >(
348 reinterpret_cast< PBYTE >( this ) + (DWORD)sizeof(CORBBTPROF_SCENARIO_INFO) + sizeofName());
349 }
350
351 DWORD sizeofRuns()
352 {
353 DWORD sum = 0;
354 if (numRuns > 0)
355 {
356 DWORD cnt = 1;
357 CORBBTPROF_SCENARIO_RUN* pRun = GetScenarioRun();
358 do
359 {
360 sum += pRun->Size();
361 if (cnt == numRuns)
362 break;
363 cnt++;
364 pRun = pRun->GetNextRun();
365 }
366 while (true);
367 }
368 return sum;
369 }
370};
371
372struct CORBBTPROF_SCENARIO_HEADER
373{
374 DWORD size; // Size to skip to get to the next CORBBTPROF_SCENARIO_HEADER
375 CORBBTPROF_SCENARIO_INFO scenario;
376
377 DWORD Size()
378 {
379 return (DWORD) sizeof(CORBBTPROF_SCENARIO_HEADER) + scenario.sizeofName() + scenario.sizeofRuns();
380 }
381};
382
383struct CORBBTPROF_SCENARIO_INFO_SECTION_HEADER
384{
385 DWORD TotalNumRuns;
386 DWORD NumScenarios;
387// CORBBTPROF_SCENARIO_HEADER scenario[0]; // array is 'NumScenarios' in length
388};
389
390//
391// MethodBlockCounts section
392//
393
394struct CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1
395{
396 DWORD NumMethods;
397 DWORD NumRuns;
398};
399
400struct CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER
401{
402 DWORD NumMethods;
403};
404
405struct CORBBTPROF_BLOCK_DATA // Also defined here code:ICorJitInfo.ProfileBuffer
406{
407 DWORD ILOffset;
408 DWORD ExecutionCount;
409};
410
411struct CORBBTPROF_METHOD_DETAIL_HEADER
412{
413 DWORD size; // Size to skip to get to the next CORBBTPROF_METHOD_DETAIL_HEADER at this level
414 DWORD kind; // Identifier that specifies what kind this CORBBTPROF_METHOD_DETAIL_HEADER actually represents
415
416 size_t Size()
417 {
418 return size;
419 }
420};
421
422//
423// This struct records the basic block execution counts for a method
424//
425struct CORBBTPROF_METHOD_INFO
426{
427 DWORD token; // token for this method
428 DWORD ILSize; // IL size for this method
429 DWORD cBlock; // count for block[]
430 CORBBTPROF_BLOCK_DATA block[0]; // actually 'cBlock' in length
431
432 size_t Size()
433 {
434 return sizeof(CORBBTPROF_METHOD_INFO) + sizeofBlock();
435 }
436
437 size_t sizeofBlock()
438 {
439 return cBlock * sizeof(CORBBTPROF_BLOCK_DATA);
440 }
441};
442
443struct CORBBTPROF_METHOD_HEADER_V1
444{
445 DWORD HeaderSize;
446 mdToken MethodToken;
447 DWORD Size;
448};
449
450struct CORBBTPROF_METHOD_HEADER
451{
452 DWORD size; // Size to skip to get to the next CORBBTPROF_METHOD_HEADER
453 DWORD cDetail; // the count of CORBBTPROF_METHOD_DETAIL_HEADER records that folow this record
454 CORBBTPROF_METHOD_INFO method; // Basic block execution counts for a method
455 // ... followed by 'cDetail' occurances of CORBBTPROF_METHOD_DETAIL_HEADER
456
457 size_t Size()
458 {
459 return sizeof(CORBBTPROF_METHOD_HEADER) + method.sizeofBlock();
460 }
461};
462
463
464struct CORBBTPROF_TOKEN_LIST_SECTION_HEADER
465{
466 DWORD NumTokens;
467};
468
469struct CORBBTPROF_TOKEN_LIST_ENTRY_V1
470{
471 mdToken token;
472 DWORD flags;
473};
474
475struct CORBBTPROF_TOKEN_INFO // Was CORBBTPROF_TOKEN_LIST_ENTRY
476{
477 mdToken token;
478 DWORD flags;
479 DWORD scenarios; // Could use UINT64 instead
480
481 CORBBTPROF_TOKEN_INFO()
482 : token(0)
483 , flags(0)
484 , scenarios(0)
485 {}
486
487 CORBBTPROF_TOKEN_INFO( mdToken t, DWORD f = 0, DWORD s = 0)
488 : token(t)
489 , flags(f)
490 , scenarios(s)
491 {}
492
493 CORBBTPROF_TOKEN_INFO( CORBBTPROF_TOKEN_INFO const & right )
494 : token(right.token)
495 , flags(right.flags)
496 , scenarios(right.scenarios)
497 {}
498
499 CORBBTPROF_TOKEN_INFO operator=( CORBBTPROF_TOKEN_INFO const & right )
500 {
501 token = right.token;
502 flags = right.flags;
503 scenarios = right.scenarios;
504 return *this;
505 }
506
507 bool operator<( CORBBTPROF_TOKEN_INFO const & right ) const
508 {
509 return token < right.token;
510 }
511};
512
513struct CORBBTPROF_BLOB_ENTRY_V1
514{
515 BlobType blobType;
516 DWORD flags;
517 DWORD cBuffer;
518 BYTE pBuffer[0]; // actually 'cBuffer' in length
519
520 CORBBTPROF_BLOB_ENTRY_V1 * GetNextEntry()
521 {
522 return reinterpret_cast< CORBBTPROF_BLOB_ENTRY_V1* >(
523 reinterpret_cast< PBYTE >( this + 1 ) + cBuffer );
524 }
525};
526
527struct CORBBTPROF_BLOB_ENTRY
528{
529 DWORD size;
530 BlobType type;
531 mdToken token; // The code:CORBBTPROF_BLOB_ENTRY.token field is not a real meta-data token
532 // but a look-alike that IBCMerge makes to represent blob entry
533
534 bool TypeIsValid()
535 {
536 return (type >= MetadataStringPool) && (type < IllegalBlob);
537 }
538
539 CORBBTPROF_BLOB_ENTRY * GetNextEntry()
540 {
541 return reinterpret_cast< CORBBTPROF_BLOB_ENTRY* >(
542 reinterpret_cast< PBYTE >( this ) + size);
543 }
544};
545
546struct CORBBTPROF_BLOB_PARAM_SIG_ENTRY
547{
548 CORBBTPROF_BLOB_ENTRY blob;
549 DWORD cSig;
550 COR_SIGNATURE sig[0]; // actually 'cSig' in length
551};
552
553struct CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY
554{
555 CORBBTPROF_BLOB_ENTRY blob;
556 DWORD cName;
557 CHAR name[0]; // actually cName in length
558};
559
560struct CORBBTPROF_BLOB_TYPE_DEF_ENTRY
561{
562 CORBBTPROF_BLOB_ENTRY blob;
563 mdToken assemblyRefToken;
564 mdToken nestedClassToken;
565 mdToken nameSpaceToken;
566 DWORD cName;
567 CHAR name[0]; // actually cName in length
568};
569
570struct CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY
571{
572 CORBBTPROF_BLOB_ENTRY blob;
573 DWORD cSig;
574 COR_SIGNATURE sig[0]; // actually 'cSig' in length
575};
576
577struct CORBBTPROF_BLOB_METHOD_DEF_ENTRY
578{
579 CORBBTPROF_BLOB_ENTRY blob;
580 mdToken nestedClassToken;
581 mdToken signatureToken;
582 DWORD cName;
583 CHAR name[0]; // actually cName in length
584};
585
586struct CORBBTPROF_BLOB_POOL_ENTRY
587{
588 CORBBTPROF_BLOB_ENTRY blob;
589 DWORD cBuffer;
590 BYTE buffer[0]; // actually 'cBuffer' in length
591};
592#endif /* COR_BBTPROF_H_ */
593