diff options
author | Henrik Edin <henrik.edin@mongodb.com> | 2020-10-27 09:47:11 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-10-28 14:10:43 +0000 |
commit | 2911c96e8ba0021372d1f7fd47282b012403180f (patch) | |
tree | eef278d08d3aa2868b1c49b5513880ed6c5a6904 | |
parent | 15b66de500c7117999c061b89febb4d169355e53 (diff) | |
download | mongo-2911c96e8ba0021372d1f7fd47282b012403180f.tar.gz |
SERVER-51856 Add Visual Studio Natvis debugger visualizers for BSONObj and BSONElement
-rw-r--r-- | buildscripts/win/mongodb.natvis | 329 | ||||
-rw-r--r-- | src/mongo/bson/bsonelement.cpp | 21 | ||||
-rw-r--r-- | src/mongo/bson/bsonobj.cpp | 13 |
3 files changed, 363 insertions, 0 deletions
diff --git a/buildscripts/win/mongodb.natvis b/buildscripts/win/mongodb.natvis index 7e6a6bfb854..047b4ccb747 100644 --- a/buildscripts/win/mongodb.natvis +++ b/buildscripts/win/mongodb.natvis @@ -32,6 +32,335 @@ <StringView>_data,[_size]s8</StringView> </Type> + <Type Name="mongo::BSONElementBinaryType"> + <DisplayString>{{ binary, size={size} }}</DisplayString> + <Expand> + <Item Name="size">size</Item> + <Item Name="subtype">(mongo::BinDataType)subtype</Item> + <Item Name="data">(uint8_t*)this+5,[size]x</Item> + </Expand> + </Type> + + <Type Name="mongo::BSONElementRegexType"> + <DisplayString>{{ {this,s8}, {this+strlen((char*)this)+1,s8} }}</DisplayString> + <Expand> + <Item Name="pattern">(const char*)this,s8</Item> + <Item Name="options">(const char*)this+strlen((char*)this)+1,s8</Item> + </Expand> + </Type> + + <Type Name="mongo::BSONElementDBRefType"> + <DisplayString>{{ {this+4,[*(int32_t*)this-1]s8} }}</DisplayString> + <Expand> + <CustomListItems> + <Item Name="{this+4,[*(int32_t*)this-1]s8}">*(mongo::OID*)(this+*(int32_t*)this+4)</Item> + </CustomListItems> + </Expand> + </Type> + + <Type Name="mongo::BSONElementCodeWithScopeType"> + <DisplayString>{{ {this+8,[*(int32_t*)(this+4)-1]s8} }}</DisplayString> + <Expand> + <CustomListItems> + <Variable Name="Code" InitialValue="(const char*)this+4"/> + + <Item Name="code">Code+4,[*(int32_t*)(Code)-1]s8</Item> + <Item Name="scope">*(mongo::BSONObjData*)(Code+*(int32_t*)(Code)+4)</Item> + </CustomListItems> + </Expand> + </Type> + + <!-- + It it not possible to use variables to calculate contents in the DisplayString nodes. + + this+strlen((char*)&name)+2: Skips over the type byte and the name with its null terminator to get to the beginning of the value + --> + <Type Name="mongo::BSONElementData"> + <!-- double: { name, value } --> + <DisplayString Condition="type==1">{*(double*)((char*)this+strlen(&name)+2)}</DisplayString> + + <!-- string --> + <DisplayString Condition="type==2 ">{(char*)this+strlen(&name)+6,[*(int32_t*)((char*)this+strlen(&name)+2)-1]s8}</DisplayString> + + <!-- embedded document or array --> + <DisplayString Condition="type==3 || type==4">objsize={*(int32_t*)((char*)this+strlen(&name)+2)}</DisplayString> + + <!-- binary, treat uuid separately --> + <DisplayString Condition="type==5 && *(char*)((char*)this+strlen((char*)&name)+6)!=4">binary</DisplayString> + <DisplayString Condition="type==5 && *(char*)((char*)this+strlen((char*)&name)+6)==4">uuid</DisplayString> + + <!-- undefined --> + <DisplayString Condition="type==6">undefined</DisplayString> + + <!-- ObjectId --> + <DisplayString Condition="type==7">oid</DisplayString> + + <!-- bool --> + <DisplayString Condition="type==8">{*(bool*)((char*)this+strlen((char*)&name)+2)}</DisplayString> + + <!-- Date_t --> + <DisplayString Condition="type==9">{*(mongo::Date_t*)((char*)this+strlen((char*)&name)+2)}</DisplayString> + + <!-- null --> + <DisplayString Condition="type==10">null</DisplayString> + + <!-- regex --> + <DisplayString Condition="type==11">regex</DisplayString> + + <!-- DBRef --> + <DisplayString Condition="type==12 ">DBRef</DisplayString> + + <!-- Code --> + <DisplayString Condition="type==13 ">code</DisplayString> + + <!-- Symbol --> + <DisplayString Condition="type==14 ">symbol</DisplayString> + + <!-- code with scope --> + <DisplayString Condition="type==15">codeWScope</DisplayString> + + <!-- int32 --> + <DisplayString Condition="type==16">{*(int32_t*)((char*)this+strlen((char*)&name)+2)}</DisplayString> + + <!-- Timestamp --> + <DisplayString Condition="type==17">{*(mongo::Timestamp*)((char*)this+strlen((char*)&name)+2)}</DisplayString> + + <!-- int64 --> + <DisplayString Condition="type==18">{*(int64_t*)((char*)this+strlen((char*)&name)+2)}</DisplayString> + + <!-- Decimal128 --> + <DisplayString Condition="type==19">{*(mongo::Decimal128*)((char*)this+strlen((char*)&name)+2)}</DisplayString> + + <!-- MinKey/MaxKey --> + <DisplayString Condition="type==-1">MinKey</DisplayString> + <DisplayString Condition="type==0x7f">MaxKey</DisplayString> + + <Expand> + <CustomListItems> + <Variable Name="DataType" InitialValue="*(signed char*)this" /> + <Variable Name="DataName" InitialValue="(const char*)&name"/> + <Variable Name="DataValue" InitialValue="DataName+strlen(DataName)+1"/> + <Variable Name="BinarySubType" InitialValue="*(uint8_t*)(DataValue+4)"/> + + <Item Name="value" Condition="DataType==1">*(double*)DataValue</Item> + <Item Name="value" Condition="DataType==2 || DataType==13 || DataType==14">DataValue+4,[*DataValue-1]s8</Item> + <Item Name="value" Condition="DataType==3">*(mongo::BSONObjData*)DataValue</Item> + <Item Name="value" Condition="DataType==4">*(mongo::BSONArrayData*)DataValue</Item> + <Item Name="value" Condition="DataType==5 && BinarySubType!=4 ">*(mongo::BSONElementBinaryType*)DataValue</Item> + <Item Name="value" Condition="DataType==5 && BinarySubType==4 ">*(mongo::UUID*)(DataValue+5)</Item> + <Item Name="value" Condition="DataType==7">*(mongo::OID*)DataValue</Item> + <Item Name="value" Condition="DataType==8">*(bool*)DataValue</Item> + <Item Name="value" Condition="DataType==9">*(mongo::Date_t*)DataValue</Item> + <Item Name="value" Condition="DataType==11">*(mongo::BSONElementRegexType*)DataValue</Item> + <Item Name="value" Condition="DataType==12">*(mongo::BSONElementDBRefType*)DataValue</Item> + <Item Name="value" Condition="DataType==15">*(mongo::BSONElementCodeWithScopeType*)DataValue</Item> + <Item Name="value" Condition="DataType==16">*(int32_t*)DataValue</Item> + <Item Name="value" Condition="DataType==17">*(mongo::Timestamp*)DataValue</Item> + <Item Name="value" Condition="DataType==18">*(int64_t*)DataValue</Item> + <Item Name="value" Condition="DataType==19">*(mongo::Decimal128*)DataValue</Item> + </CustomListItems> + </Expand> + </Type> + + <Type Name="mongo::BSONElement"> + <!-- double: { name, value } --> + <DisplayString Condition="*(char*)data==1">{{ {data+1,s8}, {*(double*)((char*)data+strlen(data+1)+2)} }}</DisplayString> + + <!-- string --> + <DisplayString Condition="*(char*)data==2 ">{{ {data+1,s8}, {(char*)data+strlen(data+1)+6,[*(int32_t*)((char*)data+strlen(data+1)+2)-1]s8} }}</DisplayString> + + <!-- embedded document or array --> + <DisplayString Condition="*(char*)data==3 || *(char*)data==4">{{ {data+1,s8}, objsize={*(int32_t*)((char*)data+strlen(data+1)+2)} }}</DisplayString> + + <!-- binary, treat uuid separately --> + <DisplayString Condition="*(char*)data==5 && *(char*)((char*)data+strlen((char*)data+1)+6)!=4">{{ {data+1,s8}, binary }}</DisplayString> + <DisplayString Condition="*(char*)data==5 && *(char*)((char*)data+strlen((char*)data+1)+6)==4">{{ {data+1,s8}, uuid }}</DisplayString> + + <!-- undefined --> + <DisplayString Condition="*(char*)data==6">{{ {data+1,s8}, undefined }}</DisplayString> + + <!-- ObjectId --> + <DisplayString Condition="*(char*)data==7">{{ {data+1,s8}, oid }}</DisplayString> + + <!-- bool --> + <DisplayString Condition="*(char*)data==8">{{ {data+1,s8}, {*(bool*)((char*)data+strlen((char*)data+1)+2)} }}</DisplayString> + + <!-- Date_t --> + <DisplayString Condition="*(char*)data==9">{{ {data+1,s8}, {*(mongo::Date_t*)((char*)data+strlen((char*)data+1)+2)} }}</DisplayString> + + <!-- null --> + <DisplayString Condition="*(char*)data==10">{{ {data+1,s8}, null }}</DisplayString> + + <!-- regex --> + <DisplayString Condition="*(char*)data==11">{{ {data+1,s8}, regex }}</DisplayString> + + <!-- DBRef --> + <DisplayString Condition="*(char*)data==12 ">{{ {data+1,s8}, DBRef }}</DisplayString> + + <!-- Code --> + <DisplayString Condition="*(char*)data==13 ">{{ {data+1,s8}, code }}</DisplayString> + + <!-- Symbol --> + <DisplayString Condition="*(char*)data==14 ">{{ {data+1,s8}, symbol }}</DisplayString> + + <!-- code with scope --> + <DisplayString Condition="*(char*)data==15">{{ {data+1,s8}, codeWScope }}</DisplayString> + + <!-- int32 --> + <DisplayString Condition="*(char*)data==16">{{ {data+1,s8}, {*(int32_t*)((char*)data+strlen((char*)data+1)+2)} }}</DisplayString> + + <!-- Timestamp --> + <DisplayString Condition="*(char*)data==17">{{ {data+1,s8}, {*(mongo::Timestamp*)((char*)data+strlen((char*)data+1)+2)} }}</DisplayString> + + <!-- int64 --> + <DisplayString Condition="*(char*)data==18">{{ {data+1,s8}, {*(int64_t*)((char*)data+strlen((char*)data+1)+2)} }}</DisplayString> + + <!-- Decimal128 --> + <DisplayString Condition="*(char*)data==19">{{ {data+1,s8}, {*(mongo::Decimal128*)((char*)data+strlen((char*)data+1)+2)} }}</DisplayString> + + <!-- MinKey/MaxKey --> + <DisplayString Condition="*(char*)data==-1">{{ {data+1,s8}, MinKey }}</DisplayString> + <DisplayString Condition="*(char*)data==0x7f">{{ {data+1,s8}, MaxKey }}</DisplayString> + + <Expand> + <Item Name="name">(const char*)data+1,s8</Item> + <Item Name="value">(const mongo::BSONElementData*)data,na</Item> + </Expand> + </Type> + + <Type Name="mongo::BSONObjData"> + <DisplayString>{{ objsize={size} }}</DisplayString> + <Expand> + <CustomListItems> + <Variable Name="DataPointer" InitialValue="(const char*)this"/> + <Variable Name="ItemType" InitialValue="(int32_t)0" /> + <Variable Name="ItemName" InitialValue="(const char*)nullptr" /> + <Variable Name="ItemValue" InitialValue="(const char*)nullptr" /> + + <Exec>DataPointer += 4</Exec> + <Loop> + <Break Condition="*DataPointer == 0"/> + <Exec>ItemType=*DataPointer</Exec> + <Exec>ItemName=DataPointer+1</Exec> + <Item Name="{ItemName,s8}">(const mongo::BSONElementData*)DataPointer,na</Item> + <Exec>DataPointer=ItemName+strlen(ItemName)+1</Exec> + <!-- double, Date_t, Timestamp, 64bit integer --> + <If Condition="ItemType==1 || ItemType==9 || ItemType==17 || ItemType==18"> + <Exec>DataPointer+=8</Exec> + </If> + <!-- string types: string, DBPointer, JavaScript, Symbol--> + <If Condition="ItemType==2 || ItemType==13 || ItemType==14 || ItemType==12"> + <Exec>DataPointer+=*(int32_t*)DataPointer+4</Exec> + </If> + <!-- types beginning with an int for size: embedded document, embedded array, codeWithScope --> + <If Condition="ItemType==3 || ItemType==4 || ItemType==15"> + <Exec>DataPointer+=*(int32_t*)DataPointer</Exec> + </If> + <!-- binary --> + <If Condition="ItemType==5"> + <Exec>DataPointer+=*(int32_t*)DataPointer+5</Exec> + </If> + <!-- ObjectId, DBPointer --> + <If Condition="ItemType==7 || ItemType==12"> + <Exec>DataPointer+=12</Exec> + </If> + <!-- bool --> + <If Condition="ItemType==8"> + <Exec>DataPointer+=1</Exec> + </If> + <!-- regular expression --> + <If Condition="ItemType==11"> + <Exec>DataPointer+=strlen(DataPointer)+1</Exec> + <Exec>DataPointer+=strlen(DataPointer)+1</Exec> + </If> + <!-- 32bit integer --> + <If Condition="ItemType==16"> + <Exec>DataPointer+=4</Exec> + </If> + <!-- Decimal128 --> + <If Condition="ItemType==19"> + <Exec>DataPointer+=16</Exec> + </If> + </Loop> + <Item Name="[size]">size</Item> + </CustomListItems> + </Expand> + </Type> + + <!-- Same as BSONObjData but skip field names --> + <Type Name="mongo::BSONArrayData"> + <DisplayString>{{ arrsize={size} }}</DisplayString> + <Expand> + <CustomListItems> + <Variable Name="DataPointer" InitialValue="(const char*)this"/> + <Variable Name="ItemType" InitialValue="(int32_t)0" /> + <Variable Name="ItemName" InitialValue="(const char*)nullptr" /> + <Variable Name="ItemValue" InitialValue="(const char*)nullptr" /> + + <Exec>DataPointer += 4</Exec> + <Loop> + <Break Condition="*DataPointer == 0"/> + <Exec>ItemType=*DataPointer</Exec> + <Exec>ItemName=DataPointer+1</Exec> + <Item>(const mongo::BSONElementData*)DataPointer,na</Item> + <Exec>DataPointer=ItemName+strlen(ItemName)+1</Exec> + <!-- double, Date_t, Timestamp, 64bit integer --> + <If Condition="ItemType==1 || ItemType==9 || ItemType==17 || ItemType==18"> + <Exec>DataPointer+=8</Exec> + </If> + <!-- string types: string, DBPointer, JavaScript, Symbol--> + <If Condition="ItemType==2 || ItemType==13 || ItemType==14 || ItemType==12"> + <Exec>DataPointer+=*(int32_t*)DataPointer+4</Exec> + </If> + <!-- types beginning with an int for size: embedded document, embedded array, codeWithScope --> + <If Condition="ItemType==3 || ItemType==4 || ItemType==15"> + <Exec>DataPointer+=*(int32_t*)DataPointer</Exec> + </If> + <!-- binary --> + <If Condition="ItemType==5"> + <Exec>DataPointer+=*(int32_t*)DataPointer+5</Exec> + </If> + <!-- ObjectId, DBPointer --> + <If Condition="ItemType==7 || ItemType==12"> + <Exec>DataPointer+=12</Exec> + </If> + <!-- bool --> + <If Condition="ItemType==8"> + <Exec>DataPointer+=1</Exec> + </If> + <!-- regular expression --> + <If Condition="ItemType==11"> + <Exec>DataPointer+=strlen(DataPointer)+1</Exec> + <Exec>DataPointer+=strlen(DataPointer)+1</Exec> + </If> + <!-- 32bit integer --> + <If Condition="ItemType==16"> + <Exec>DataPointer+=4</Exec> + </If> + <!-- Decimal128 --> + <If Condition="ItemType==19"> + <Exec>DataPointer+=16</Exec> + </If> + </Loop> + <Item Name="[size]">size</Item> + </CustomListItems> + </Expand> + </Type> + + <Type Name="mongo::BSONObj"> + <DisplayString>objsize={*(int32_t*)_objdata}</DisplayString> + <Expand> + <ExpandedItem>(const mongo::BSONObjData*)_objdata</ExpandedItem> + </Expand> + </Type> + + <Type Name="mongo::BSONArray"> + <DisplayString>objsize={*(int32_t*)_objdata}</DisplayString> + <Expand> + <ExpandedItem>(const mongo::BSONArrayData*)_objdata</ExpandedItem> + </Expand> + </Type> + <Type Name="absl::container_internal::raw_hash_set<*>"> <DisplayString>{{ size={size_} }}</DisplayString> <Expand> diff --git a/src/mongo/bson/bsonelement.cpp b/src/mongo/bson/bsonelement.cpp index 312eb849caf..d93f928861c 100644 --- a/src/mongo/bson/bsonelement.cpp +++ b/src/mongo/bson/bsonelement.cpp @@ -971,4 +971,25 @@ bool BSONObj::coerceVector(std::vector<T>* out) const { return true; } +/** + * Types used to represent BSONElement memory in the Visual Studio debugger + */ +#if defined(_MSC_VER) && defined(_DEBUG) +struct BSONElementData { + char type; + char name; +} bsonElementDataInstance; + +struct BSONElementBinaryType { + int32_t size; + uint8_t subtype; +} bsonElementBinaryType; +struct BSONElementRegexType { +} bsonElementRegexType; +struct BSONElementDBRefType { +} bsonElementDBPointerType; +struct BSONElementCodeWithScopeType { +} bsonElementCodeWithScopeType; +#endif // defined(_MSC_VER) && defined(_DEBUG) + } // namespace mongo diff --git a/src/mongo/bson/bsonobj.cpp b/src/mongo/bson/bsonobj.cpp index 48a3102b605..f606cb7d13b 100644 --- a/src/mongo/bson/bsonobj.cpp +++ b/src/mongo/bson/bsonobj.cpp @@ -819,4 +819,17 @@ BSONObjIteratorSorted::BSONObjIteratorSorted(const BSONObj& object) BSONArrayIteratorSorted::BSONArrayIteratorSorted(const BSONArray& array) : BSONIteratorSorted(array, ElementFieldCmp(true)) {} +/** + * Types used to represent BSONObj and BSONArray memory in the Visual Studio debugger + */ +#if defined(_MSC_VER) && defined(_DEBUG) +struct BSONObjData { + int32_t size; +} bsonObjDataInstance; + +struct BSONArrayData { + int32_t size; +} bsonObjArrayInstance; +#endif // defined(_MSC_VER) && defined(_DEBUG) + } // namespace mongo |