使用WinDbg+SOS及WinDbg Script尋找內(nèi)存中DataTable第M行N列的值
DataTable在內(nèi)存中是如何存儲(chǔ)一張表的結(jié)構(gòu)的呢?如何使用Windbg直接在內(nèi)存中找到一個(gè)DataTable里面的第M列第N行的值呢?這的確是一個(gè)比較有趣的問(wèn)題^_^
下面的內(nèi)容,主要是講如何用windbg+sos來(lái)看看一個(gè)DataTable在內(nèi)存中是如何存儲(chǔ)的,以及尋找內(nèi)存中一個(gè)DataTable特定的行列的一個(gè)單元的值是多少。同時(shí),還有一點(diǎn)Windbg Script的使用。
找一個(gè)小白鼠先:
class Program
{
static void Main(string[] args)
{
System.Data.DataTable dt = new System.Data.DataTable();
DataColumn dtC1 = new DataColumn();
dtC1.ColumnName = "Column1";
DataColumn dtC2 = new DataColumn();
dtC2.ColumnName = "Column2";
dt.Columns.Add(dtC1);
dt.Columns.Add(dtC2);
DataRow dr1 = dt.NewRow();
dr1["Column1"] = "aaaa";
dr1["Column2"] = "bbbb";
dt.Rows.Add(dr1);
DataRow dr2 = dt.NewRow();
dr2["Column1"] = "cccc";
dr2["Column2"] = "dddd";
dt.Rows.Add(dr2);
pause();
}
public static void pause()
{
System.Console.ReadLine();
}
}
下面就看看DataTable在內(nèi)存里面是如何存儲(chǔ)的,以及在內(nèi)存里面找到aaaa,bbbb,cccc,dddd這幾個(gè)字符串。
首先!threads看看哪幾個(gè)托管線程,then,切換到主線程上面:~0s
0:000> !dumpstackobjects
OS Thread Id: 0x66c (0)
ESP/REG Object Name
0012f3b0 013b9830 Microsoft.Win32.SafeHandles.SafeFileHandle
0012f3c0 013b9830 Microsoft.Win32.SafeHandles.SafeFileHandle
0012f3f4 013ba01c System.Byte[]
0012f3f8 013b9844 System.IO.__ConsoleStream
0012f418 013b97c8 System.Data.DataRow
0012f41c 013b9fc4 System.IO.StreamReader
0012f420 013b9fc4 System.IO.StreamReader
0012f424 013b7dac System.Data.DataRowCollection
0012f434 013b9fc4 System.IO.StreamReader
0012f438 013ba338 System.IO.TextReader+SyncTextReader
0012f43c 013b7dac System.Data.DataRowCollection
0012f444 013b97c8 System.Data.DataRow
0012f448 013b9664 System.Data.DataRow
0012f44c 013ba338 System.IO.TextReader+SyncTextReader
0012f450 013b7dac System.Data.DataRowCollection
0012f458 013b6120 System.Data.DataTable
0012f468 013b5b7c System.Object[] (System.String[])
0012f46c 013b82fc System.Data.DataColumn
0012f470 013b8edc System.Data.DataColumn
0012f534 013b5b7c System.Object[] (System.String[])
0012f6e0 013b5b7c System.Object[] (System.String[])
0012f708 013b5b7c System.Object[] (System.String[])
有幾個(gè)DataColumn和幾個(gè)DataRow,還有兩個(gè)DataRowCollection。為了證實(shí)猜想,繼續(xù)查看下去,dump DataTable:
0:000> !do 013b6120
Name: System.Data.DataTable
MethodTable: 653c46d8
EEClass: 653c4288
Size: 296(0x128) bytes
Fields:
MT Type Value Name
|
7a745c0c |
...ponentModel.ISite |
000000000 |
site |
|
7a742e54 |
....EventHandlerList |
000000000 |
events |
|
790f9c18 |
System.Object |
000000000 |
EventDisposed |
|
653c2e2c |
System.Data.DataSet |
000000000 |
dataSet |
|
653c6ce8 |
System.Data.DataView |
000000000 |
defaultView |
|
653c72cc |
...DataRowCollection |
0013b7dac |
rowCollection |
|
653c33d4 |
...aColumnCollection |
0013b7c5c |
columnCollection |
|
653c711c |
...straintCollection |
0013b7d74 |
constraintCollection |
|
653d3d0c |
...elationCollection |
000000000 |
parentRelationsCollection |
|
653d3d0c |
...elationCollection |
000000000 |
childRelationsCollection |
|
653c7080 |
...ata.RecordManager |
0013b7500 |
recordManager |
|
790fa3e0 |
System.String |
0013b6290 |
tableName |
|
790fa3e0 |
System.String |
000000000 |
tableNamespace |
|
790fa3e0 |
System.String |
0013b6290 |
tablePrefix |
|
653e63bc |
...ta.DataExpression |
000000000 |
displayExpression |
|
790ff4c4 |
...ation.CultureInfo |
0013b78dc |
_culture |
|
7910feec |
...ation.CompareInfo |
000000000 |
_compareInfo |
|
790ffdcc |
...m.IFormatProvider |
000000000 |
_formatProvider |
|
79112d98 |
...em.StringComparer |
000000000 |
_hashCodeProvider |
|
790fa3e0 |
System.String |
000000000 |
encodedTableName |
|
653c3e94 |
...m.Data.DataColumn |
000000000 |
xmlText |
|
653c3e94 |
...m.Data.DataColumn |
000000000 |
_colUnique |
|
79105ba4 |
System.Decimal |
1013b6224 |
minOccurs |
|
79105ba4 |
System.Decimal |
1013b6234 |
maxOccurs |
|
790f9c18 |
System.Object |
000000000 |
typeName |
|
653c9b84 |
....UniqueConstraint |
000000000 |
primaryKey |
|
653d63ac |
...Data.IndexField |
0013b6274 |
_primaryIndex |
|
653c75f8 |
System.Data.Index |
000000000 |
loadIndexwithOriginalAdded |
|
653c75f8 |
System.Data.Index |
000000000 |
loadIndexwithCurrentDeleted |
|
79124228 |
System.Object[] |
000000000 |
EmptyDataRowArray |
|
7a74db40 |
...criptorCollection |
000000000 |
propertyDescriptorCollectionCache |
|
79124228 |
System.Object[] |
0013b6280 |
_nestedParentRelations |
|
653dfc68 |
...hangeEventHandler |
000000000 |
onRowChangedDelegate |
|
653dfc68 |
...hangeEventHandler |
000000000 |
onRowChangingDelegate |
|
653dfc68 |
...hangeEventHandler |
000000000 |
onRowDeletingDelegate |
|
653dfc68 |
...hangeEventHandler |
000000000 |
onRowDeletedDelegate |
|
653dec84 |
...hangeEventHandler |
000000000 |
onColumnChangedDelegate |
|
653dec84 |
...hangeEventHandler |
000000000 |
onColumnChangingDelegate |
|
653e039c |
...ClearEventHandler |
000000000 |
onTableClearingDelegate |
|
653e039c |
...ClearEventHandler |
000000000 |
onTableClearedDelegate |
|
653e042c |
...ewRowEventHandler |
000000000 |
onTableNewRowDelegate |
|
7a7638a4 |
...angedEventHandler |
000000000 |
onPropertyChangingDelegate |
|
7910d61c |
System.EventHandler |
000000000 |
onInitialized |
|
653c7730 |
...ta.DataRowBuilder |
0013b82ec |
rowBuilder |
|
790fea70 |
...ections.Hashtable |
000000000 |
rowDiffId |
|
79103b6c |
....ReaderWriterLock |
0013b6348 |
indexesLock |
|
791240f0 |
System.Int32[] |
0013b6248 |
zeroIntegers |
|
79124228 |
System.Object[] |
0013b6254 |
zeroColumns |
|
79124228 |
System.Object[] |
0013b6264 |
zeroRows |
|
653d63ac |
...Data.IndexField |
0013b6274 |
zeroIndexField |
|
79124228 |
System.Object[] |
0013b6280 |
EmptyArrayDataRelation |
由于DataTable里面的東西太多,就去掉了幾列和一些沒(méi)有太大用處的行。在elementColumnCount屬性里面,可以看到DataTable里面有剛才定義的兩列。
接著,可以在columnCollection這個(gè)field里面找到剛才小白鼠里面的DataTable的Column的集合:
0:000> !do 013b7c5c
Name: System.Data.DataColumnCollection
MethodTable: 653c33d4
EEClass: 653c3364
Size: 56(0x38) bytes
(C:\WINDOWS\assembly\GAC_32\System.Data\2.0.0.0__b77a5c561934e089\System.Data.dll)
Fields:
MT Type Value Name
7a753b14 ...onChangeEventArgs 00000000 RefreshEventArgs
653c46d8 ...em.Data.DataTable 013b6120 table
791036b0 ...ections.ArrayList 013b7c94 _list
790fed1c System.Int32 1 defaultNameIndex
79124228 System.Object[] 00000000 delayedAddRangeColumns
790fea70 ...ections.Hashtable 013b7cac columnFromName
7a7504bc ...hangeEventHandler 00000000 onCollectionChangedDelegate
7a7504bc ...hangeEventHandler 00000000 onCollectionChangingDelegate
7a7504bc ...hangeEventHandler 00000000 onColumnPropertyChangedDelegate
79104f64 System.Boolean 0 fInClear
79124228 System.Object[] 013b6254 columnsImplementingIChangeTracking
790fed1c System.Int32 0 nColumnsImplementingIChangeTracking
790fed1c System.Int32 0
nColumnsImplementingIRevertibleChangeTracking
在這個(gè)結(jié)構(gòu)中,可以看到DataColumn是放過(guò)在_list這個(gè)ArrayList里面的。繼續(xù)查看ArrayList里面都有些什么:
0:000> !dumpobj 013b7c94
Name: System.Collections.ArrayList
MethodTable: 791036b0
EEClass: 79103604
Size: 24(0x18) bytes
(C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
Fields:
MT Field Offset Type VT Attr Value Name
79124228 40008c0 4 System.Object[] 0 instance 013b8f8c _items
790fed1c 40008c1 c System.Int32 0 instance 2 _size
790fed1c 40008c2 10 System.Int32 0 instance 2 _version
790f9c18 40008c3 8 System.Object 0 instance 00000000 _syncRoot
79124228 40008c4 1b0 System.Object[] 0 shared static emptyArray
>> Domain:Value 00154598:013b1c2c <<
恩,快要到達(dá)目的地了,接著由于里面只有兩個(gè)Column,我就在Windbg里面全部給輸出出來(lái)了:
0:000> !dumparray -details 013b8f8c
Name: System.Object[]
MethodTable: 79124228
EEClass: 7912479c
Size: 32(0x20) bytes
Array: Rank 1, Number of elements 4, Type CLASS
Element Methodtable: 790f9c18
[0] 013b82fc
Name: System.Data.DataColumn
MethodTable: 653c3e94
EEClass: 653c3e1c
Size: 148(0x94) bytes
對(duì)于每個(gè)DataColumn的細(xì)節(jié),輸出很長(zhǎng),這里就截取一個(gè)_items里面的DataColumn對(duì)象的細(xì)節(jié):
MT Type Value Name
7a745c0c ...ponentModel.ISiteinstance 00000000 site
7a742e54 ....EventHandlerListinstance 00000000 events
790f9c18 System.Object static 00000000 EventDisposed
79104f64 System.Booleaninstance 1 allowNull
79104f64 System.Booleaninstance 0 autoIncrement
790fcb80 System.Int64instance 1 autoIncrementStep
790fcb80 System.Int64instance 0 autoIncrementSeed
790fa3e0 System.Stringinstance 00000000 caption
790fa3e0 System.Stringinstance 013b6070 _columnName
79101058 System.Typeinstance 013b8390 dataType
790f9c18 System.Objectinstance 013b846c defaultValue
653d4c94 System.Int32instance 3 _dateTimeMode
653e63bc ...ta.DataExpressioninstance 00000000 expression
790fed1c System.Int32instance -1 maxLength
790fed1c System.Int32instance 0 _ordinal
79104f64 System.Booleaninstance 0 readOnly
653c75f8 System.Data.Indexinstance 00000000 sortIndex
653c46d8 ...em.Data.DataTableinstance 013b6120 table
79104f64 System.Booleaninstance 0 unique
653d3bfc System.Int32instance 1 columnMapping
790fed1c System.Int32instance 0 _hashCode
790fed1c System.Int32instance 0 errors
79104f64 System.Booleaninstance 0 isSqlType
79104f64 System.Booleaninstance 0 implementsINullable
79104f64 System.Booleaninstance 1 defaultValueIsNull
00000000 instance 00000000 dependentColumns
653d4218 ...ropertyCollectioninstance 00000000 extendedProperties
7a7638a4 ...angedEventHandlerinstance 00000000 onPropertyChangingDelegate
653c68bc ...ommon.DataStorageinstance 013b8fdc _storage
790fcb80 System.Int64instance 0 autoIncrementCurrent
790fa3e0 System.Stringinstance 00000000 _columnUri
790fa3e0 System.Stringinstance 013b6290 _columnPrefix
790fa3e0 System.Stringinstance 00000000 encodedColumnName
790fa3e0 System.Stringinstance 013b6290 description
790fa3e0 System.Stringinstance 013b6290 dttype
653c9abc ...m.Data.SimpleTypeinstance 00000000 simpleType
790fed1c System.Int32instance 1 _objectID
790fed1c System.Int32 static 2 _objectTypeCount
啊哈,看到曙光了,Column的內(nèi)容,看樣子就是存儲(chǔ)在_storage里面的了,打開(kāi)看看:
0:000> !dumpobj 013b8fdc
Name: System.Data.Common.StringStorage
MethodTable: 653cdd38
EEClass: 6540eea4
Size: 44(0x2c) bytes
Fields:
MT Type Value Name
653c3e94 ...m.Data.DataColumn 013b82fc Column
653c46d8 ...em.Data.DataTable 013b6120 Table
79101058 System.Type 013b8390 DataType
653e2d80 System.Int32 18 StorageTypeCode
79166df8 ...lections.BitArray 00000000 dbNullBits
790f9c18 System.Object 790d6584 DefaultValue
790f9c18 System.Object 013b846c NullValue
79104f64 System.Boolean 0 IsCloneable
79104f64 System.Boolean 0 IsCustomDefinedType
79104f64 System.Boolean 1 IsStringType
79104f64 System.Boolean 0 IsValueType
79124228 System.Object[] 013b8478 StorageClassType
79124228 System.Object[] 013b9008 values
看到values數(shù)組,應(yīng)該就在這里了:
0:000> !dumparray -details 013b9008
Name: System.String[]
MethodTable: 79124228
EEClass: 7912479c
Size: 528(0x210) bytes
Array: Rank 1, Number of elements 128, Type CLASS
Element Methodtable: 790fa3e0
下面輸出的具體的數(shù)組里面的每個(gè)項(xiàng),不知道為什么多了幾百個(gè)null,就選擇前兩個(gè)顯示出來(lái):
[0] 013b60b0
Name: System.String
MethodTable: 790fa3e0
EEClass: 790fa340
Size: 26(0x1a) bytes
String: aaaa
Fields:
MT Type Value Name
790fed1c System.Int32 5 m_arrayLength
790fed1c System.Int32 4 m_stringLength
790fbefc System.Char 61 m_firstChar
790fa3e0 System.String static Empty
>> Domain:Value 00154598:790d6584 <<
>> Domain:Value 00154598:013b16e8 <<
[1] 013b60e8
Name: System.String
MethodTable: 790fa3e0
EEClass: 790fa340
Size: 26(0x1a) bytes
String: cccc
Fields:
MT Type Value Name
790fed1c System.Int32 5 m_arrayLength
790fed1c System.Int32 4 m_stringLength
790fbefc System.Char 63 m_firstChar
790fa3e0 System.String static Empty
>> Domain:Value 00154598:790d6584 <<
>> Domain:Value 00154598:013b16e8 <<
呵呵,看到了久違的aaaa和cccc,在最上面構(gòu)在的DataTable里面的Column1里面。
節(jié)目的最后,在網(wǎng)上找到了一個(gè)Johan Olofsson的Windbg Script直接傳遞兩個(gè)參數(shù)可以打印出相應(yīng)的DataTable的第幾個(gè)第幾個(gè)Column:
.foreach
( value{
!do poi(poi(poi(poi(poi(poi(${$arg1}+0x18)+0x8)+0x4)+0xc+0x4*${$arg2})+0x48)+0x10) -v -short
})
{
!do ${value}
}
使用的時(shí)候很簡(jiǎn)單:
$$>a< dumptablevalues 0x0a8cdaa8 0
這樣就可以了。Dumptablevalues是你保存的windbg.exe相同目錄下面的文件名。0x0a8cdaa8是DataTable的address。0是你想要顯示的第幾列。
在快速查看DataTable里面的Column的時(shí)候比較有用。
Script很簡(jiǎn)單,poi是取值的意思,里面的一系列十六進(jìn)制的數(shù)字,就是在windbg輸出的時(shí)候的Offset列的東西。每個(gè)數(shù)字對(duì)應(yīng)者上面的一步一步的對(duì)象和層級(jí)關(guān)系。
另外,文中展示的windbg結(jié)果,為了顯示排版方便,去掉了一些無(wú)關(guān)緊要的行和列。
Ok,到這里吧,就到這里吧。
2008-3-31 21:48:51 post to sscli.cnblogs.com
posted on 2008-03-31 22:03 lbq1221119 閱讀(3518) 評(píng)論(18) 收藏 舉報(bào)
浙公網(wǎng)安備 33010602011771號(hào)