summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenrik Edin <henrik.edin@mongodb.com>2020-10-27 09:47:11 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-10-28 14:10:43 +0000
commit2911c96e8ba0021372d1f7fd47282b012403180f (patch)
treeeef278d08d3aa2868b1c49b5513880ed6c5a6904
parent15b66de500c7117999c061b89febb4d169355e53 (diff)
downloadmongo-2911c96e8ba0021372d1f7fd47282b012403180f.tar.gz
SERVER-51856 Add Visual Studio Natvis debugger visualizers for BSONObj and BSONElement
-rw-r--r--buildscripts/win/mongodb.natvis329
-rw-r--r--src/mongo/bson/bsonelement.cpp21
-rw-r--r--src/mongo/bson/bsonobj.cpp13
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*)&amp;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(&amp;name)+2)}</DisplayString>
+
+ <!-- string -->
+ <DisplayString Condition="type==2 ">{(char*)this+strlen(&amp;name)+6,[*(int32_t*)((char*)this+strlen(&amp;name)+2)-1]s8}</DisplayString>
+
+ <!-- embedded document or array -->
+ <DisplayString Condition="type==3 || type==4">objsize={*(int32_t*)((char*)this+strlen(&amp;name)+2)}</DisplayString>
+
+ <!-- binary, treat uuid separately -->
+ <DisplayString Condition="type==5 &amp;&amp; *(char*)((char*)this+strlen((char*)&amp;name)+6)!=4">binary</DisplayString>
+ <DisplayString Condition="type==5 &amp;&amp; *(char*)((char*)this+strlen((char*)&amp;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*)&amp;name)+2)}</DisplayString>
+
+ <!-- Date_t -->
+ <DisplayString Condition="type==9">{*(mongo::Date_t*)((char*)this+strlen((char*)&amp;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*)&amp;name)+2)}</DisplayString>
+
+ <!-- Timestamp -->
+ <DisplayString Condition="type==17">{*(mongo::Timestamp*)((char*)this+strlen((char*)&amp;name)+2)}</DisplayString>
+
+ <!-- int64 -->
+ <DisplayString Condition="type==18">{*(int64_t*)((char*)this+strlen((char*)&amp;name)+2)}</DisplayString>
+
+ <!-- Decimal128 -->
+ <DisplayString Condition="type==19">{*(mongo::Decimal128*)((char*)this+strlen((char*)&amp;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*)&amp;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 &amp;&amp; BinarySubType!=4 ">*(mongo::BSONElementBinaryType*)DataValue</Item>
+ <Item Name="value" Condition="DataType==5 &amp;&amp; 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 &amp;&amp; *(char*)((char*)data+strlen((char*)data+1)+6)!=4">{{ {data+1,s8}, binary }}</DisplayString>
+ <DisplayString Condition="*(char*)data==5 &amp;&amp; *(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&lt;*&gt;">
<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