windbg scripting if else if output matches - windbg

I'd like to set a breakpoint at a certain function, and each time it breaks, I'd like to search a memory range for a certain string. If that string exists, I'd like to not continue. If it does, then continue. Any suggestions? I'm thinking it'd look something like this:
.foreach /s line (s -a 0 L?0xfffffff "UNIQUE_STRING") { .if (line =~ "UNIQUE_STRING") { .break } .else { gc } }
I'm not too familiar with the .foreach commmand, so I might have gotten it a little wrong. My other idea was something like this:
.if ((.shell -ci "s -a 0 L?0xfffffff \"UNIQUE_STRING\"" findstr "UNIQUE_STRING") != "") {} .else { gc }
Has anybody done something like this? (sorry, some of that is extreme pseudo code)

Have you thought about doing this as an extension instead? IDebugDataSpaces::SearchVirtual returns an error if the pattern isn't found, which would make this easier on you.
-scott

I think your command syntax is a little wrong. Try:
bu module!Class::Function ".if (condition) { .echo hit_breakpoint } .else { gc }"
Everytime the debugger hits Function() it will execute the echo statement if the condition is true.
Look up 'conditional breakpoints' in .hh (windbg help) for great information as well.

Related

Mirc script to find exact match in customer list

I am using this to find customer name in text file. Names are each on a separate line. I need to find exact name. If searching for Nick specifically it should find Nick only but my code will say found even if only Nickolson is in te list.
On*:text:*!Customer*:#: {
if ($read(system\Customer.txt,$2)) {
.msg $chan $2 Customer found in list! | halt }
else { .msg $chan 4 $2 Customer not found in list. | halt }
}
You have to loop through every matching line and see if the line is an exact match
Something like this
On*:text:*!Custodsddmer*:#: {
var %nick
; loop over all lines that contains nick
while ($read(customer.txt, nw, *nick*, $calc($readn + 1))) {
; check if the line is an exact match
if ($v1 == nick) {
%nick = $v1
; stop the loop because a result is found
break;
}
}
if (%nick == $null) {
.msg $chan 4 $2 Customer not found in list.
}
else{
.msg $chan $2 Customer found in list!
}
You can find more here: https://en.wikichip.org/wiki/mirc/text_files#Iterating_Over_Matches
If you're looking for exact match in a new line separate list, then you can use the 'w' switch without using wildcard '*' character.
From mIRC documentation
$read(filename, [ntswrp], [matchtext], [N])
Scans the file info.txt for a line beginning with the word mirc and
returns the text following the match value. //echo $read(help.txt, w,
*help*)
Because we don't want the wildcard matching, but a exact match, we would use:
$read(customers.txt, w, Nick)
Complete Code:
ON *:TEXT:!Customer *:#: {
var %foundInTheList = $read(system\Customer.txt, w, $2)
if (%foundInTheList) {
.msg # $2 Customer found in list!
}
else {
.msg 4 # $2 Customer not found in list.
}
}
Few remarks on Original code
Halting
halt should only use when you forcibly want to stop any future processing to take place. In most cases, you can avoid it, by writing you code flow in a way it will behave like that without explicitly using halting.
It will also resolve new problems that may arise, in case you will want to add new code, but you will wonder why it isn't executing.. because of the darn now forgotten halt command.
This will also improve you debugging, in the case it will not make you wonder on another flow exit, without you knowing.
Readability
if (..) {
.... }
else { .. }
When considering many lines of codes inside the first { } it will make it hard to notice the else (or elseif) because mIRC remote parser will put on the same identification as the else line also the line above it, which contains the closing } code. You should almost always few extra code in case of readability, especially which it costs new nothing!, as i remember new lines are free of charge.
So be sure the to have the rule of thump of every command in a new line. (that includes the closing bracket)
Matching Text
On*:text:*!Customer*:#: {
The above code has critical problem, and bug.
Critical: Will not work, because on*:text contains no space between on and *:text
Bug: !Customer will match EVERYTHING-BEFORE!customerANDAFTER <NICK>, which is clearly not desired behavior. What you want is :!Customer *: will only match if the first word was !customer and you must enter at least another text, because I've used [SPACE]*.

Need example for try-catch-finally where finally is a must

I need an example that use try..catch..finally clause where the finally is NECESSARY vs try..catch clause where finally is optional. The example below only demonstrated that finally is optional because with or without it, it won't make any different to my output.
My Example (note: $ErrorActionPreference is Continue):
try {
$value = 5 / 0
} catch {
Write-Output "illegal operation"
}
$t = Get-Date
Write-Output ("operation is done at " + "$t")
The reason is I need to know where finally clause become necessary vs just put finally clause no matter what.
A finally clause is just a logical construct saying "this statement or group of statements should always be run at the end of the try block, regardless of whether there was an error or not". It tells people reading the code that there is a logical connection between the code in the try and finally blocks (e.g. opening and closing a database connection). However, beyond that there is no essential difference between
try {
5 / 0
} catch {
'illegal operation'
}
'continued'
and
try {
5 / 0
} catch {
'illegal operation'
} finally {
'continued'
}
You can find some discussion of the subject here.
I think the only way it would make a difference is if you return or exit in the try block:
try {
'foo' # <-- displayed
exit
} finally {
'bar' # <-- displayed
}
'baz' # <-- not displayed
but maybe something like that is just bad design.

Go: C like macros for writing test code

When writing test code, I do a lot of this
if (!cond) {
t.Fatal("error message")
}
It's a bit tedious. So I'd like to achieve the following
CHECK(cond, "error message")
So I attempted this
func CHECK(t *testing.T, cond bool, fmt string, a ...interface{}) {
if !cond {
t.Fatal(fmt, a)
}
}
If it were a C macro it would've worked perfectly. But in Go, the line number where the failure is is wrong.
Is there a fix for this?
Sadly you can't do that.
A workaround would be to get the line / function yourself, something like the trace function from https://stackoverflow.com/a/25954534/145587.
You could possibly make use of runtime.Callers()&plus;runtime.Caller(): the first one gives you the call stack while the second allows to extract the debug info about any arbitrary stack frame (obtained from that list).
Your CHECK() function is always one function call down the place the check should have happened at if it was a macro, so you can inspect the stack frame just above.
Update: the only functon which is really needed is runtime.Caller(). Here's your case, simplified:
package main
import (
"runtime"
"testing"
)
func CHECK(t *testing.T, cond bool) {
if !cond {
_, fname, lineno, ok := runtime.Caller(1)
if !ok {
fname, lineno = "<UNKNOWN>", -1
}
t.Fatalf("FAIL: %s:%d", fname, lineno)
}
}
func TestFoo(t *testing.T) {
CHECK(t, 12 == 13)
}
When saved as check_test.go and run via go test, it produces:
$ go test
--- FAIL: TestFoo (0.00 seconds)
check_test.go:14: FAIL: /home/kostix/devel/go/src/check/check_test.go:19
FAIL
exit status 1
FAIL check 0.001s
where line 19 is the line a call to CHECK() is located inside TestFoo().
While the above answer to use CHECK() function will work, I think that the actual answer is code readibility. Much of Go has been designed as a compromise to increase readibility among the community as a whole. See gofmt for example. Most people will agree that it's format is not best for every case. But having a convention agreed to by all is a huge plus for Go. The same answer is to your question. Go is for writing code for your peers, not for yourself. So don't think "I prefer this." Think "what will people reading my code understand."
Your original code should be like this, without parenthesis.
if !cond {
t.Fatal("error message")
}
This is idiomatic and every Go coder will recognize it instantly. That is the point.

In Vim, how to avoid having "/*" be treated as comment

Vim keeps treating my perl code as comments and the auto indentation does not work.
$dump=`cp /local/*.txt .`;
if ($a == 0)
{
if ($b == 0)
{
print "HELLO";
}
}
was formatted as:
$dump=`cp /local/*.txt .`;
if ($a == 0)
{
if ($b == 0)
{
print "HELLO";
}
}
This is because the "/*" in the first line was treated as comment and hence Vim gives up indenting anything afterwards.
I could think of a workaround as:
$dump=`cp /local/*.txt .`; #*/;
To manually close the comment.
But is there a better way?
Thanks.
You're using cindent, which is meant specifically to autoindent C code (including C-style block comments). This has no awareness that you are actually writing perl. Try smartindent instead, it seems to work better with perl. To try this, run set cindent! and then set smartindent. If this works better, you can change it in your .vimrc file.
If you're talking about the = key to indent, rather than the ident-as-you-go indentation, this is uses a separate formatter. You can change the what is used by setting equalprg. For perl, you might use set equalprg=perltidy\ -quiet to run the selected lines through perltidy.

Alternative to "last" in do loops

According to the perl manual for for last (http://perldoc.perl.org/functions/last.html), last can't be used to break out of do {} loops, but it doesn't mention an alternative. The script I'm maintaining has this structure:
do {
...
if (...)
{
...
last;
}
} while (...);
and I'm pretty sure he wants to go to the end of the loop, but its actually exiting the current subroutine, so I need to either change the last or refactor the whole loop if there is a better way that someone can recommend.
Wrap the do "loop" in a bare block (which is a loop):
{
do {
...
if (...)
{
...
last;
}
} while (...);
}
This works for last and redo, but not next; for that place the bare block inside the do block:
do {{
...
if (...)
{
...
next;
}
...
}} while (...);
do BLOCK while (EXPR) is funny in that do is not really a loop structure. So, last, next, and redo are not supposed to be used there. Get rid of the last and adjust the EXPR to evaluate false when that situation is found.
Also, turn on strict, which should give you at least a warning here.
Never a fan of do/while loops in Perl. the do isn't really a loop which is why last won't break out of it. In our old Pascal daze you couldn't exit a loop in the middle because that would be wrong according to the sage Niklaus "One entrance/one exit" Wirth. Therefore, we had to create an exit flag. In Perl it'd look something like this:
my $endFlag = 0;
do {
...
if (...)
{
...
$endFlag = 1;
}
} while ((...) and (not $endFlag));
Now, you can see while Pascal never caught on.
Why not just use a while loop?
while (...) {
...
if (...) {
last;
}
}
You might have to change your logic slightly to accommodate the fact that your test is at the beginning instead of end of your loop, but that should be trivial.
By the way, you actually CAN break out of a Pascal loop if you're using Delphi, and Delphi DID catch on for a little while until Microsoft wised up and came out with the .net languages.
# "http://perldoc.perl.org/functions/last.html":
last cannot be used to exit a block that returns a value such as eval {} , sub {} or do {} , and should not be used to exit a grep() or map() operation.
So, use a boolean in the 'while()' and set it where you have 'last'...
Late to the party - I've been messing with for(;;) recently. In my rudimentary testing, for conditional expressions A and B, what you want to do with:
do {
last if A;
} while(B);
can be accomplished as:
for(;; B || last) {
last if A;
}
A bit ugly, but perhaps not more so than the other workarounds :) . An example:
my $i=1;
for(;; $i<=3 || last) {
print "$i ";
++$i;
}
Outputs 1 2 3. And you can combine the increment if you want:
my $i=1;
for(;; ++$i, $i<=3 || last) {
print "$i ";
}
(using || because it has higher precedence than ,)