When using windbg and running !dumpheap command to see the addresses of objects, how can you limit to a specific number of objects. The only way I found was using CTRL+BREAK
and a command line on a blog http://dotnetdebug.net/2005/07/04/dumpheap-parameters-and-some-general-information-on-sos-help-system/
-l X - Prints out only X items from each heap instead of all the objects.
Apparently -l no longer exists in SOS.dll
What are you actually looking for? Before looking at individual objects, it's usual to narrow the area of interest.
The –stat switch shows a summary, per type of the objects on the heap.
DumpHeap [-stat] [-min ][-max ] [-thinlock] [-mt ] [-type ][start [end]]
The -stat option restricts the output to the statistical type summary.
The -min option ignores objects that are less than the size parameter, specified in bytes.
The -max option ignores objects that are larger than the size parameter, specified in bytes.
The -thinlock option reports ThinLocks. For more information, see the SyncBlk command.
The -mt option lists only those objects that correspond to specified the MethodTable structure.
The -type option lists only those objects whose type name is a substring match of the specified string.
The start parameter begins listing from the specified address. The end parameter stops listing at the specified address.
Ref.
According which criteria would you like to limit the number of outputs?
The -l option just limits the output according to line numbers. This is useless: let's say it shows only the first 10 objects, maybe the object you're looking for is not even listed.
If the output is too long for WinDbgs output window, use .logopen to dump the objects into a file and then review the file with a text editor.
If you have other ideas how your object looks like, you can perform a loop over all objects
.foreach ( obj { !dumpheap -short -type MyType} )
and then decide with .if whether or not your object matches this criteria.
As an example, I was looking for a needle in a haystack. I was searching a specific Hashtable in a program with more than 3000 Hashtables on the heap. The command I tried to use was
.foreach ( obj { !dumpheap -short -type Hashtable }) {.if (poi(poi(${obj}+1c)) > 100) {!do ${obj}} }
1C is the offset of the count member of the hashtable.
100 is the number of items the Hashtable was expected to have at least.
Unfortunately it didn't work for Hashtables immediately, because !dumpheap -type also listed HashtableEnumerators which somehow crashed the debugger.
To dump hashtables only, run !dumpheap -stat and figure out the method table of hashtables and run the command with -mt <methodtable> instead of -type <classname>, which gives
.foreach ( obj { !dumpheap -short -mt <MT of Hashtable> }) {.if (poi(poi(${obj}+1c)) > 100) {!do ${obj}} }
Related
I am storing the content of a text file in a variable like this -
$fileContent=$(Get-Content file1.txt)
Right now file1.txt contains 200 lines only. But if one day the file contains 10 million lines, then will this approach work? Is there any limit to the length of content that a variable can hold in PowerShell?
Get-Content reads the file into memory.
With that being said, you'd want to change the approach on what you're after. PowerShell being built on top of the .Net framework has access to all of its capabilities. So, you can use classes such as StreamReader which reads the file from disk one line at a time using a method like the one below.
$file = [System.IO.StreamReader]::new('.\Desktop\adobe_export.reg') #instantiate an istance of streamreader
while ($file.EndOfStream.Equals($false)) #if not end of file, continue.
{
# save this to a variable if needed
$file.ReadLine() # read/display line
# more code
}
$file.Close()
$file.Dispose()
First of all, you need to understand that a PS variable is a wrapper around a .NET type, so whatever that can hold, is the answer.
Regarding your actual case, you can search in Microsoft docs whatever GetType() returns, if there is a limit for that type - but there is always a memory limit. So if you read a lot of data into memory, and then return some of it after filtering/transforming/completing/whatever, you are filling memory. Instead you may NOT assign anything to a variable, but use the pipeline's one-at-a-time processing functionality, with this only that much memory is used for the items in the pipeline. Of course you might need to do more than one complex thing with the same input that need their own pipelines, but in this case you can either re-read the data, or if you think that it can change between reads and you need a snapshot, then copy it into a temporary place.
I am trying to investigate what looks like a memory leak in .NET using WinDbg.
However, when I try to examine output of !dumpheap -type I see that many, if not all objects listed are "Free" objects. I'd like to filter the list to see if there any that are rooted (have references to them).
I tried the following script:
.foreach (t {!dumpheap -mt 0000000091ea94f0 -short}) { .if(!gcroot ${t}) { !mdt ${t} } }
However, it does not output anything. Is there a way to filter out the output of !dumpheap to show only rooted objects?
Free "objects"
.NET uses a heap manager to keep track of memory. This makes it possible to allocate objects smaller than 64 kB, where 64 kB is the minimum memory the OS provides.
So, .NET gets at least 64 kB and then splits that into smaller pieces. Those pieces which are unused can be understood as objects of type Free.
To get a better overview of Free objects, use !dumpheap -stat -type Free. Those Free objects don't have a root, because they are not actually objects.
But you can also see a whole lot of other objects including the sum of their sizes. Those are likely rooted.
Rooted objects
Unfortunately, commands like !gcroot don't have a boolean return value, so you need to use some tricky stuff. The basic .foreach loop is already quite good.
To get a comparable return value, we'll use the root count number, which is 1 in the following case:
0:004> !gcroot 02701078
HandleTable:
001f11ec (strong handle)
-> 02701078 System.OutOfMemoryException
Found 1 unique roots (run '!GCRoot -all' to see all roots).
Since the number can be 1, 2, 3 etc., it seems more reliable to check for !=0. Let's start like this:
.shell -ci"!gcroot ${t}" find "Found 0"
This will only keep the one line "Found 0 unique roots ...", otherwise nothing at all.
Then let's minimize the output just to keep the number by skipping the first word ("Found") using /pS 1, then processing one word and then skipping the rest (actually a maximum of 99 words) using /ps 99:
.foreach /pS 1 /ps 99(word {.shell -ci"!gcroot ${t}" find "Found 0"}) {.echo ${word}}
This will leave us with 0 only.
Next, use can use $scmp() to compare the string:
.if ($scmp("${word}","0")==0) {.echo nothing} .else {.echo something}
The whole script (formatted for readability, remove the line breaks and indentation):
.foreach (t {!dumpheap -short -mt 70c240b4}) {
.foreach /pS 1 /ps 99 (word {.shell -ci"!gcroot ${t}" find "Found 0"}) {
.if ($scmp("${word}","0")==0){
.echo nothing
} .else {
.echo something
}
}
}
In your case, replace .echo something by !mdt ${t}.
PyKd
Since above script is hard to understand and error-prone, you might want to try PyKD. Look for dbgCommand() to execute debugger commands and get the result as a string. You can then operate on that string with any Python commands, which is much easier than WinDbg built-in functions.
I'm wondering if there is some pattern or trick to remember when or when not to use quotes in command line arguments.
e.g. what is the difference between:
find -type f -name "*<extension-with-quotes>"
and
cp <extension-without-quotes> ../<new-folder>
One needs quotes and one does not, else it gives an error. Why?
You need quotes if you don't want the shell expanding the arguments, but instead want the argument passed through verbatim to whatever program you're trying to run. See, for example, the following program:
#include <stdio.h>
int main (int argc, char *argv[]) {
printf ("Argument count = %d\n", argc);
for (int i = 0; i < argc; i++)
printf (" %2d: [%s]\n", i, argv[i]);
return 0;
}
which outputs its argument count and arguments. The following transcript shows how it runs with and without quotes:
$ ./testprog "*.sh"
Argument count = 2
0: [./testprog]
1: [*.sh]
$ ./testprog *.sh
Argument count = 7
0: [./testprog]
1: [xmit.sh]
2: [gen.sh]
3: [morph.sh]
4: [prog.sh]
5: [mon.sh]
6: [test.sh]
So, for example, if you're in a directory with three log files, the shell will change your:
ls *.log
into:
ls a.log b.log c.log
before handing that list on to the ls program (the ls program will never see the *.log at all).
However, find expects a file pattern rather than a list of files, so it will want the *.log passed through as is, one single argument rather than three individual arguments expanded by the shell.
In fact, if you had only a.log in the current directory, an unquoted *.log would only find files called a.log regardless of how many other log files existed in the directories below. That's because find never saw the *.log, only the a.log that the shell expanded it to.
A similar example is with expr. If you want to know what three times seven is, you don't want to be doing:
expr 3 * 7
since the shell will first expand * into all the files in the current directory:
3 dallas_buyers_club.avi nsa_agent_list.txt whitehouse_bomb.odt 7
and expr won't be able to make much sense of that1. The correct way of doing it is along the lines of:
expr 3 '*' 7
in effect preserving the * so the program gets it unchanged.
1 Special note to the NSA, CIA, MPAA and other dark shadowy organisations formed to strike fear into the hearts of mortal men. That file list is fictional humour. I really don't want any men in dark suits showing up at my front door :-)
One can dump all the string using the following command
!dumpheap -type System.string
How can dump or print only those string which starts or contains a specific "string"
Example. I am only intrested to view the string which contains "/my/app/request"
Use sosex instead of sos for this. It has a !strings command which allows you to filter strings using the /m:<filter> option.
Use !sosex.strings. See !sosex.help for options to filter strings based on content and/or length.
Not sure if !dumpheap supports that. You can always use .logopen to redirect the output to a file and post-process that. For a more elegant (and thus more complicated) solution, you can also use .shell to redirect the command output to a shell process for parsing. Here's an example:
http://blogs.msdn.com/b/baleixo/archive/2008/09/06/using-shell-to-search-text.aspx
You can also see the .shell documentation for more details:
http://msdn.microsoft.com/en-us/library/windows/hardware/ff565339(v=vs.85).aspx
If you really want to go without SOSEX, then try
.foreach (string {!dumpheap -short -type System.String}) { .foreach (search {s -u ${string}+c ${string}+c+2*poi(${string}+8) "mySearchTerm"}) { du /c80 ${string}+c }}
It uses
!dumpheap to get all Strings on .NET heap
.foreach to iterate over them
s to search for a substring
.foreach again to find out if s found something
some offset calculations to get the first character (+c) of the string and the string length (+8) (multiplied by 2 to get bytes instead of characters). Those need to be adapted in case of 64 bit applications
The /c80 is just for nicer output. You could also use !do ${string} instead of du /c80 ${string}+c if you like the .NET details of the String.
This question is regarding the function forward_dns from the following blog:
http://powershellmasters.blogspot.com/2009/04/nslookup-and-powershell.html
So say I have a piece of code in powershell that looks like this:
$cmd = "nslookup google.com " + $NameserverIPAddress;
$result = Invoke-Expression ($cmd);
This snippet uses the nslookup DOS command to do a DNS lookup. Since it's a DOS command, the object returned by Invoke-Expression is basically an array of strings, one for each line of output.
In the example function, in order to retrieve line 4 of the output, the original author uses the following syntax:
$result.SyncRoot[3];
I found that this also works just fine:
$result[3];
What is the purpose of SyncRoot in this context?
There is no purpose in this example.
SyncRoot property is a way to treat in a safe manner ( generally with a lock in .net) arrays handled by more that one thread. see here and here