gdb: Defining a function with multiple arguments using if...else - gdb

How can I define a gdb convenience function with optional args? I've tried below, which doesn't work:
(gdb) define v
Type commands for definition of "v".
End with a line saying just "end".
>if $argc == 1
>echo 1
>else if $argc == 2
>echo 2
>else
>echo neither
>end
>end
(gdb) v
neither(gdb) v 1
1Undefined command: "else". Try "help".
(gdb) v 2
1Undefined command: "else". Try "help".

I've tried below, which doesn't work:
It doesn't work because there is no else in the GDB scripting language.
You can work around this with:
define v
if $argc == 1
echo 1
end
if $argc == 2
echo 2
end
if $argc < 1 || 2 < $argc
echo neither
end
end
but you'll probably get better results by deferring to the embedded Python.

Related

How I can make gdb print all breakpoint executions without stopping on them?

Use case: I want to research program execution by reading breakpoint hits. Hits count is more than 100.
I can't use continue 1, because hits count is too large. I can't use continue <some big number>, because GDB skipping all occurrences and not writing them in log.
What I can do with this case?
define print_all_br
set $i = 0
while $i < $arg0
continue 1
set $i = $i + 1
end
end
This might work with print_all_br(<some_big_number>)

Does gdb support comments in the command line (gdb prompt)?

I want to comment gdb commands in the command prompt at the end of the line for two use case:
Writing a tutorial
Documenting a gdb command file for automatic execution
While gdb command files seem to support comments via the hash (#) symbol
I cannot find any command marker for the gdb command line:
(gdb) print 1
$2 = 1
(gdb) print 1 // comment
A syntax error in expression, near `/ comment'.
(gdb) print 1 -- comment
A syntax error in expression, near `comment'.
(gdb) print 1 # comment
Invalid character '#' in expression.
(gdb) print 1 ; comment
Invalid character ';' in expression.
(gdb) print 1 /* comment */
No symbol "comment" in current context.
How can I append comments?
Edit: According to the gdb documentation
Any text from a # to the end of the line is a comment;
it does nothing.
This is useful mainly in command files
I am not sure why it doesn't work as documented...
You can use it on its own line, but not at the end of a line. E.g.:
(gdb) # foo
(gdb) print "foo"
$1 = "foo"

replace multi line text with multiline text in sed and perl

Here is my file
start
exit 0
status
exit 0
stop
exit 0
the result file should be
start
exit 0
status
exit 152
stop
exit 0
any help is appreciated
How can I do it using sed and perl
Using Awk
Input
$ cat f
start
exit 0
status
exit 0
stop
exit 0
Output
$ awk '/exit/ && p {sub($NF,"152")}{p=/status/}1' f
start
exit 0
status
exit 152
stop
exit 0
Explanation
p=/status/ Set variable p true whenever awk finds word status
/exit/ && p when awk finds word exit on current record and variable p evaluates true then
sub(regexp, replacement [, target])
Search target, which is treated as a string, for the leftmost, longest substring matched by the regular expression regexp. Modify the entire string by replacing the matched text with replacement. The modified string becomes the new value of target. Return the number of substitutions made (zero or one). If 3rd argument is omitted, then the default is to use and alter $0.
sub($NF,"152")
Substitute last field ($NF) with 152 of current record, since 3rd argument is not given hence, default $0 is altered.
} 1
1 always evaluates to true, it performs default operation {print $0}
perl -pe's/exit \K\d+/152/ if $f; $f = /status/'
Usage:
perl -i~ -pe'...' file # Edit in place with backup
perl -i -pe'...' file # Edit in place without backup
perl -pe'...' file.in >file.out # Read from file
perl -pe'...' <file.in >file.out # Read from stdin
With sed one can use:
$ sed '/status/{n;s/0/152/}' input
start
exit 0
status
exit 152
stop
exit 0

If statement string comparison

What am I'm doing wrong over here?
The script by default enters this IF statement & displays the echo statement to exit.
#!/bin/ksh
server=$1
dbname=$2
IFS="
"
if [[ "${dbname}" != "abc_def_data" || "${dbname}" != "abc_def01_data" ]]; then
echo "Msg: Triggers can only be applied to CMS_JAD:abc_def_data/abc_def01_data!"
exit 0
fi
chaining of != conditions requires some inversion of thinking.
I much prefer a clearer path to testing these conditions by using the case ... esac structure.
case "${dbname}" in
abc_def_data|abc_def01_data )
#dbg echo "matched, but for real code replace with just a ':' char"
:
;;
* )
echo "didn_t match any expected values for \$dbname"
echo exit 1
;;
esac
Note that as you're really trying to find the *) case, the actions for the abc_def_data (etc) match can be anything, but to just skip to the next section of code, you would only need the shell's null cmd : .
Edit 1
Note that I have echo exit 1, just so if you copy/paste this to a command line, your shell won't exit. In real code, remove the echo and expect the exit to work.
Edit 2
Also, note that the | char in the case match (abc_def_data**|**abc_def01_data) is essentially an OR (I think it is called something else in the "case match" context).
IHTH
Did you, by any chance, meant to write this?
if [[ "${dbname}" != "abc_def_data" && "${dbname}" != "abc_def01_data" ]]; then
echo "Msg: Triggers can only be applied to CMS_JAD:abc_def_data/abc_def01_data!"
exit 0
fi
try this man, it should work just fine you should have seperated the conditions with "[ ]" and used -o instead of ||....
btw it worked for me fine...
server=$1
dbname=$2
IFS=""
if [ "${dbname}" != "abc_def_data" ] -o [ "${dbname}" != "abc_def01_data" ]
then
echo "Msg: Triggers can only be applied to CMS_JAD:abc_def_data/abc_def01_data!"
exit 0
fi

Scripting in gdb

Say, for example, I have a C source file with a method like foo(a) where a is a character.
I want to print the output of foo for every character is there an easier way than going through systematically and entering p foo('a') then p foo('b')?
Ideally I'd really like to script it so it's a bit quicker.
I managed to figure it out, my code was basically:
define foo_test
set $a = 97
set $b = 123
while $a < $b
p (char)foo($a)
set $a = $a + 1
end
end
perl -e 'foreach $i ("a" .. "z") { print "print foo('\''$i'\'')\n"; }' > /tmp/t.$$ &&
gdb --batch -x /tmp/t.$$ ./a.out ; rm -f /tmp/t.$$
You should also look into GDB Python scripting.
It sounds like the first thing you should add is some "Breakpoint command lists",
those will let you run some gdb commands after a breakpoint has hit.
So if you add so your print runs when someone calls the functions foo,
you should be are getting kind of close.