@@ -864,5 +864,101 @@ public override bool ForEachMemoryBlock(MemoryReader mreader, Debugger debugger,
864864 elementConverter , memoryBlockPredicate ) ;
865865 }
866866 }
867+
868+ class CSLinkedList : ContainerLoader
869+ {
870+ public override string Id ( ) { return "System.Collections.Generic.LinkedList" ; }
871+
872+ public override string ElementName ( string name , string elType )
873+ {
874+ return name + ".head.item" ;
875+ }
876+
877+ public override int LoadSize ( Debugger debugger , string name )
878+ {
879+ return ExpressionParser . LoadSize ( debugger , name + ".count" ) ;
880+ }
881+
882+ public override bool ForEachMemoryBlock ( MemoryReader mreader , Debugger debugger ,
883+ string name , string type ,
884+ MemoryReader . Converter < double > elementConverter ,
885+ MemoryBlockPredicate memoryBlockPredicate )
886+ {
887+ int size = LoadSize ( debugger , name ) ;
888+ if ( size <= 0 )
889+ return true ;
890+
891+ // TODO: All of the debugger-related things should be done
892+ // in Initialize().
893+
894+ // TODO: Handle non-value types,
895+ // It is not clear for now where the distinction should be made
896+ // in the container or outside. When non-value types are stored
897+ // the container effectively stores pointers to objects.
898+ // So whether or not it's a pointer-container is defined by the
899+ // element type in C# and by the container in C++.
900+ string elementType = debugger . GetExpression ( name + ".head.item" ) . Type ;
901+ Expression isValueTypeExpr = debugger . GetExpression ( "typeof(" + elementType + ").IsValueType" ) ;
902+ if ( ! isValueTypeExpr . IsValidValue || isValueTypeExpr . Value != "true" )
903+ return false ;
904+
905+ //string headPointerPointerName = "(void*)&(" + name + ".head)"; //(void*)IntPtr*
906+ string headPointerName = "(void*)*(&(" + name + ".head))" ; // (void*)IntPtr
907+ string nextPointerPointerName = "(void*)&(" + name + ".head.next)" ; //(void*)IntPtr*
908+ string nextPointerName = "(void*)*(&(" + name + ".head.next))" ; // (void*)IntPtr
909+ string valPointerName = "(void*)&(" + name + ".head.item)" ; // (void*)IntPtr* or (void*)ValueType*
910+
911+ TypeInfo nextPointerInfo = new TypeInfo ( debugger , nextPointerPointerName ) ;
912+ TypeInfo nextInfo = new TypeInfo ( debugger , nextPointerName ) ;
913+ if ( ! nextPointerInfo . IsValid || ! nextInfo . IsValid )
914+ return false ;
915+
916+ MemoryReader . ValueConverter < ulong > pointerConverter = mreader . GetPointerConverter ( nextPointerInfo . Type , nextPointerInfo . Size ) ;
917+ if ( pointerConverter == null )
918+ return false ;
919+
920+ long nextDiff = ExpressionParser . GetPointerDifference ( debugger , headPointerName , nextPointerPointerName ) ;
921+ long valDiff = ExpressionParser . GetPointerDifference ( debugger , headPointerName , valPointerName ) ;
922+ if ( ExpressionParser . IsInvalidAddressDifference ( nextDiff )
923+ || ExpressionParser . IsInvalidAddressDifference ( valDiff )
924+ || nextDiff < 0 || valDiff < 0 )
925+ return false ;
926+
927+ ulong address = ExpressionParser . GetPointer ( debugger , headPointerName ) ;
928+ if ( address == 0 )
929+ return false ;
930+
931+ for ( int i = 0 ; i < size ; ++ i )
932+ {
933+ double [ ] values = new double [ elementConverter . ValueCount ( ) ] ;
934+ if ( ! mreader . Read ( address + ( ulong ) valDiff , values , elementConverter ) )
935+ return false ;
936+
937+ if ( ! memoryBlockPredicate ( values ) )
938+ return false ;
939+
940+ ulong [ ] nextTmp = new ulong [ 1 ] ;
941+ if ( ! mreader . Read ( address + ( ulong ) nextDiff , nextTmp , pointerConverter ) )
942+ return false ;
943+ address = nextTmp [ 0 ] ;
944+ }
945+ return true ;
946+ }
947+
948+ public override bool ForEachElement ( Debugger debugger , string name , ElementPredicate elementPredicate )
949+ {
950+ int size = this . LoadSize ( debugger , name ) ;
951+
952+ string nodeName = name + ".head" ;
953+ for ( int i = 0 ; i < size ; ++ i )
954+ {
955+ string elName = nodeName + ".item" ;
956+ if ( ! elementPredicate ( elName ) )
957+ return false ;
958+ nodeName = nodeName + ".next" ;
959+ }
960+ return true ;
961+ }
962+ }
867963 }
868964}
0 commit comments