-
Notifications
You must be signed in to change notification settings - Fork 4.5k
/
verifylayouts.h
183 lines (151 loc) · 6.7 KB
/
verifylayouts.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
//*****************************************************************************
// VerifyLayouts.h
//
//
// Make sure that layouts of MD data structures doesn't change accidentally
//
//*****************************************************************************
// The code in MD\DataSource\TargetTypes.* takes a direct dependency on
// the layouts of types in MD. This is used by the debugger to read metadata
// from a separate process by deserializing the memory for these datastructures.
//
// You are probably reading this comment because you changed a layout and
// one of the static_asserts failed during build. This is what you should
// do to fix it:
//
// a) Go to clr\src\Debug\EE\Debugger.cpp and increment the global version counter
// m_mdDataStructureVersion set in Debugger::Debugger()
// Please comment the change there with a new entry in the version table
//
// b) If a define is conditionally changing the layout:
// i) add, if needed, an entry to the list of define bits in
// clr\src\Debug\EE\debugger.h Debugger::_Target_Defines
// ii) add code like this that sets the bit in the Debugger::_defines static
// variable
// #ifdef MY_DEFINE
// | DEFINE_MY_DEFINE
// #endif
//
// c) Update the code in MD\DataSource\TargetTypes.h/cpp to deserialize your
// new layout correctly. The code needs to work for any version of the layouts
// with or without defines set. Your reader code can access the current version
// and defines by calling:
// reader.GetMDStructuresVersion()
// reader.IsDefined(Define_XYZ)
//
// d) If your changes affect what a debugger should be reading in order to fetch
// metadata then you probably need to change other parts of the debugger
// implementation as well. In general the debugger cares about the schema,
// TableDefs, storage signature, table records, and storage pools.
//
// e) AFTER you have fixed up the debugger stuff above, now its time to update
// layout definitions so the static asserts will quiet down. Check out
// the comments in VerifyLayouts.inc for how to do that.
//
// Thanks for helping us keep the debugger working :)
//
//-------------------------------------------------------------------------------
// Type layout verification
//
//
// These macros includes VerifyLayouts.inc a few times with different definitions to build up
// the source. The final result should look something like this:
// (don't assume specific type names/fields/offsets/sizes are accurate in this example)
//
//
// class VerifyLayoutsMD
// {
//
// static const int expected_offset_of_first_field_in_CMiniMdRW = 208;
// static const int actual_offset_of_first_field_in_CMiniMdRW =
// 208;
// static const int offset_of_field_after_CMiniMdRW_m_Schema =
// 312;
// static const int offset_of_field_after_CMiniMdRW_m_Tables =
// 316;
// ... many more lines like this covering all fields in all marked up types ...
//
//
// static const int alignment_of_first_field_in_CMiniMdRW =
// 4;
// static const int alignment_of_field_after_CMiniMdRW_m_Schema =
// 8;
// static const int alignment_of_field_after_CMiniMdRW_m_Tables =
// 8;
// ... many more lines like this cover all fields in all marked up types ...
//
//
// static_assert_no_msg(expected_offset_of_first_field_in_CMiniMdRW == actual_offset_of_first_field_in_CMiniMdRW);
// static_assert_no_msg(offset_of_field_after_CMiniMdRW_m_Schema ==
// ALIGN_UP(offsetof(CMiniMdRW, m_Schema) + 104, alignment_of_field_after_CMiniMdRW_m_Schema));
// static_assert_no_msg(offset_of_field_after_CMiniMdRW_m_Tables ==
// ALIGN_UP(offsetof(CMiniMdRW, m_Tables) + 4, alignment_of_field_after_CMiniMdRW_m_Tables));
// ... many more lines like this cover all fields in all marked up types ...
//
// };
//
//
//
//
#ifdef FEATURE_METADATA_VERIFY_LAYOUTS
#include <stddef.h> // offsetof
#include "static_assert.h"
#include "metamodel.h"
#include "mdinternalrw.h"
// other types provide friend access to this type so that the
// offsetof macro can access their private fields
class VerifyLayoutsMD
{
// we have a bunch of arrays with this fixed size, make sure it doesn't change
static_assert_no_msg(TBL_COUNT == 45);
#define USING_ALIAS(typeName, ...) using typeName = __VA_ARGS__;
#define FIELD(typeName, fieldName, fieldSize) ALIGN_FIELD(typeName, fieldName, fieldSize, fieldSize)
#define BEGIN_TYPE(typeName, initialFieldOffset) \
static const int expected_offset_of_first_field_in_##typeName = initialFieldOffset; \
static const int actual_offset_of_first_field_in_##typeName =
#define ALIGN_FIELD(typeName, fieldName, fieldSize, fieldAlign) \
offsetof(typeName, fieldName); \
static const int offset_of_field_after_##typeName##_##fieldName =
#define BITFIELD(typeName, fieldName, fieldOffset, fieldSize) \
fieldOffset; \
static const int offset_of_field_after_##typeName##_##fieldName =
#define END_TYPE(typeName, typeAlignentSize) \
sizeof(typeName);
#include "VerifyLayouts.inc"
// Only declare using once
#undef USING_ALIAS
#define USING_ALIAS(a, ...)
#undef BEGIN_TYPE
#undef ALIGN_FIELD
#undef END_TYPE
#undef BITFIELD
#define BEGIN_TYPE(typeName, initialFieldOffset) \
static const int alignment_of_first_field_in_##typeName =
#define ALIGN_FIELD(typeName, fieldName, fieldSize, fieldAlign) \
fieldAlign; \
static const int alignment_of_field_after_##typeName##_##fieldName =
#define BITFIELD(typeName, fieldName, fieldOffset, fieldSize) \
fieldSize; \
static const int alignment_of_field_after_##typeName##_##fieldName =
#define END_TYPE(typeName, typeAlignmentSize) \
typeAlignmentSize;
#include "VerifyLayouts.inc"
#undef BEGIN_TYPE
#undef ALIGN_FIELD
#undef END_TYPE
#undef BITFIELD
#define BEGIN_TYPE(typeName, initialFieldOffset) \
static_assert_no_msg(expected_offset_of_first_field_in_##typeName == actual_offset_of_first_field_in_##typeName);
#define ALIGN_UP(value, alignment) (((value) + (alignment) - 1)&~((alignment) - 1))
#define ALIGN_FIELD(typeName, fieldName, fieldSize, fieldAlign) \
static_assert_no_msg(offset_of_field_after_##typeName##_##fieldName == \
ALIGN_UP(offsetof(typeName, fieldName) + fieldSize, alignment_of_field_after_##typeName##_##fieldName));
#define BITFIELD(typeName, fieldName, fieldOffset, fieldSize) \
static_assert_no_msg(offset_of_field_after_##typeName##_##fieldName == \
ALIGN_UP(fieldOffset + fieldSize, alignment_of_field_after_##typeName##_##fieldName));
#define END_TYPE(typeName, typeAlignmentSize)
#include "VerifyLayouts.inc"
};
#endif //FEATURE_METADATA_VERIFY_LAYOUTS