How do I write a loop in a gdb script? - fortran

After adapting this answer, I wrote the following loop to simply print an array in gdb in a script called "gdb_script.gs". What am I doing wrong?
set $end=64
while ($i<$end)
print $i
print volfrac($i, :, 1)
set $i=$i+1
end
where volfrac(:,:,:) is a fortran array. I am getting the error:
gdb_script.gs:14: Error in sourced command file:
A syntax error in expression, near `<$end)'.

The other answer totally missed the point. The hint was the reported error:
gdb_script.gs:14: Error in sourced command file:
A syntax error in expression, near `<$end)'.
The hint is <$end), which means there is a syntax error in the while statement. By experimenting further, I am posting my results if others need it in the future:
set $ipx=0
set $end=32
while ($ipx .lt. 32)
print $ipx
print ro($ipx, 1)
set $ipx=$ipx+1
end
The key was to use the fortran syntax for comparison ($ipx .lt. 32) instead of the usual "c" syntax ($ipx < 32).

GDB newbies (as myself) should know that the accepted answer does not work unless you remove the blank between while and the first brace.
Also, the .lt. syntax probably works only for Fortran (https://sourceware.org/gdb/current/onlinedocs/gdb/Fortran.html). As the title of the question is not formulated specifically toward Fortran developers, the accepted answer can be misleading.

set $i = 0
p $i++
keep pressing Enter this is one of the easiest logic I found

Since voltrac() is an array, then I think it is a syntax error as show in your output - it should be "print volfrac[]" instead.
Below I showed you the step by step in detail for a C program (since you are working with gdb, and gdb only worked with ELF file, and so it is the same here - gdb + ELF file for C):
(gdb) run
Starting program: /home/tthtlc/a.out
Breakpoint 1, main () at main.c:5
5 main(){
First I step through a few times and noticed my assignment:
(gdb) s
8 for(i=0;i<10;i++)
(gdb)
9 for(j=0;j<10;j++)
(gdb)
10 for(k=0;k<10;k++) {
(gdb)
**11 volfrac[i][j][k]=0xdeadbeef;**
(gdb)
Now is the printing out (and notice the different ways of printing the array):
(gdb) print /x volfrac[0][0][0]
$5 = 0xdeadbeef
(gdb) print /x volfrac[0][0]
$6 = {0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
0x0, 0x0, 0x0, 0x0}
(gdb) print /x volfrac[0]
$7 = {{0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
(gdb) print /x volfrac
$8 = {{{0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef,
0xdeadbeef, 0x0, 0x0, 0x0, 0x0}, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
(gdb) print /x volfrac(0,0,0)
Invalid data type for function to be called.

Related

gdb automatic-continue waits for ENTER?

According to gdb docs, I can automatically continue after stopping on a breakpoint like this:
break 403
commands
cont
end
I'm trying to conditionally continue after a breakpoint like this:
set confirm off
set pagination off
define test
printf "%d\n", $x
set $x = $x + 1
if $x == 1
cont
end
end
break 403
commands
test
end
This almost works.
gdb indeed stops and checks for the condition ($x == 1). However it does not continue immediately when the condition is true.
Instead it just shows the prompt. If I click ENTER it either continues execution (when $x == 1), or remains in the prompt (if $x != 1).
Currently I just hit ENTER enough times until it does not continue execution any more.
But why does it wait for ENTER?
(This is not a matter of pagination/confirmation as I set them both to off)
Update1
Seems to be related to macro usage?
It does not happen if using commands directly.
Update 2
For clarity, here is a complete session that demonstrates the problem:
$ gdb a.out
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from a.out...
(gdb) set confirm off
(gdb) set pagination off
(gdb) define test
Type commands for definition of "test".
End with a line saying just "end".
>p i
>if i < 3
>cont
>end
>end
(gdb) b 8
Breakpoint 1 at 0x115e: file test.c, line 8.
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>test
>end
(gdb) run
Starting program: /home/amir.gonnen/projects/test/gdb-cont/a.out
Breakpoint 1, main () at test.c:8
8 printf("%d", i);
$1 = 0
Breakpoint 1, main () at test.c:8
8 printf("%d", i);
(gdb) echo Hey gdb why is the prompt?
Hey gdb why is the prompt?$2 = 1
Breakpoint 1, main () at test.c:8
8 printf("%d", i);
(gdb) echo Hey gdb you show the prompt but you still continue!
Hey gdb you show the prompt but you still continue!$3 = 2
Breakpoint 1, main () at test.c:8
8 printf("%d", i);
(gdb) echo again...
again...$4 = 3
(gdb) echo not continuing any more.
not continuing any more.(gdb)
not continuing any more.(gdb)
not continuing any more.(gdb)
This appears to work fine for me using GDB-10.0 on x86_64.
Are you sure it doesn't work? One thing I noticed is that you print $x before incrementing and checking it, which makes it a bit confusing.
Here is my session:
# gdbinit
set confirm off
set pagination off
define test
set $x = $x + 1
printf " x = %d\n", $x
if $x == 1
printf " continuing\n"
cont
end
end
set var $x = -2
gdb -q ./a.out
(gdb) source gdbinit
(gdb) list
1 int main()
2 {
3 int k = 0;
4 for (int j = 1; j < 100; j++) {
5 k += 1;
6 }
7 return k;
8 }
(gdb) b 5
Breakpoint 1 at 0x1139: file t.c, line 5.
(gdb) commands
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>test
>end
(gdb) run
Starting program: /tmp/a.out
Breakpoint 1, main () at t.c:5
5 k += 1;
x = -1
(gdb) c
Continuing.
Breakpoint 1, main () at t.c:5
5 k += 1;
x = 0
(gdb) c
Continuing.
Breakpoint 1, main () at t.c:5
5 k += 1;
x = 1
continuing <<<=== Note: no 'c' required this time.
Breakpoint 1, main () at t.c:5
5 k += 1;
(gdb)

Get return from gdb exec

In .gdbinit I call to function
call open("tmp/test",1)
Then I got return value
$15 = 1
I want to use $15 to the next operation.
How can I got this var to the .gdbinit next line ?
You can simply assign the return value to a variable with a name of your choosing:
(gdb) call $ret = open("tmp/test", 1)
(gdb) print $ret
-1

Break anywhere when $r1 equals to a certain string in GDB

Is there anyway to break on gdb when $r1 equals to a certain string I know there is :
break [addr] if ((int)strcmp($r1, "hello")) == 0
But what to set in addr when I just wanna break when the r1 is "hello" no matter the current function/address?

gdb - execute current line without moving on

This has probably been asked elsewhere, but was a bit of a tricky one to google.
I am debugging some code like the following in gdb (or cgdb more specifically):
if(something) {
string a = stringMaker();
string b = stringMaker();
}
As I step through using 'n', the cursor will reach the 'string b' line. At this point I can inspect the value of a, but b won't have been populated yet as that line hasn't been executed. Another press of 'n' will execute that line, but will then also move outside the if loop and b will now be out of scope. Is there a way to execute the current line without moving on so that its result can be inspected before it goes out of scope?
Another press of 'n' will execute that line, but will then also move
outside the if loop and b will now be out of scope
The problem is that next executes too much instructions and b variable becomes unavailable. You can substitute this single next with a number of step and finish commands to achieve more granularity in debugging and stop immediately after b was constructed. Here is sample gdb session for test program:
[ks#localhost ~]$ cat ttt.cpp
#include <string>
int main()
{
if (true)
{
std::string a = "aaa";
std::string b = "bbb";
}
return 0;
}
[ks#localhost ~]$ gdb -q a.out
Reading symbols from a.out...done.
(gdb) start
Temporary breakpoint 1 at 0x40081f: file ttt.cpp, line 7.
Starting program: /home/ks/a.out
Temporary breakpoint 1, main () at ttt.cpp:7
7 std::string a = "aaa";
(gdb) n
8 std::string b = "bbb";
(gdb) p b
$1 = ""
(gdb) s
std::allocator<char>::allocator (this=0x7fffffffde8f) at /usr/src/debug/gcc-5.1.1-20150618/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/allocator.h:113
113 allocator() throw() { }
(gdb) fin
Run till exit from #0 std::allocator<char>::allocator (this=0x7fffffffde8f) at /usr/src/debug/gcc-5.1.1-20150618/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/allocator.h:113
0x0000000000400858 in main () at ttt.cpp:8
8 std::string b = "bbb";
(gdb) s
std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (this=0x7fffffffde70, __s=0x400984 "bbb", __a=...) at /usr/src/debug/gcc-5.1.1-20150618/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.tcc:656
656 basic_string<_CharT, _Traits, _Alloc>::
(gdb) fin
Run till exit from #0 std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string (this=0x7fffffffde70, __s=0x400984 "bbb", __a=...) at /usr/src/debug/gcc-5.1.1-20150618/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.tcc:656
0x000000000040086d in main () at ttt.cpp:8
8 std::string b = "bbb";
(gdb) p b
$2 = "bbb"
Just add to the code b; the line afterwards. i.e.
if(something) {
string a = stringMaker();
string b = stringMaker();
b; // Break point here
}
Well you can always to a
(gdb) p stringMaker();
regardless of the line you're in given that stringMaker() is accessible. You can execute any kind statements , even involving variables if those variables are in current scope. For more advanced usage, you can use gdb's internal variables($1,$2 etc) to store certain result to use it later when the variables involved in that previous computation went out of scope.
Finally God(whatever that may be) send us gdb Python API. just type py and demolish your code to such extent that you will forget what you were doing at the first place.

std::string::find_first_of does not return the expected value

I am trying to create an XML parser in C++. I am currently using cygwin and gcc to compile and gdb to debug. I have this piece of code:
const size_t mDataSize = mData.size();
...
size_t ltPos = mData.find_first_of('<', pos);
if (ltPos==mData.npos) {
...
mData is declared as private const std::string & within the class and holds the XML file content. After debugging with gdb I found the following:
(gdb) print pos
$12 = 636
(gdb) print mDataSize
$13 = 2692
(gdb) n
141 size_t ltPos = mData.find_first_of('<', pos);
(gdb) print ltPos
$14 = 114
(gdb) print pos
$15 = 636
(gdb) n
143 if (ltPos==mData.npos)
(gdb) print ltPos
$16 = 4294967295
(gdb) print mData[636]
$17 = (const char &) #0xb2b2a8: 10 '\n'
(gdb) print mData[637]
$18 = (const char &) #0xb2b2a9: 32 ' '
(gdb) print mData[638]
$19 = (const char &) #0xb2b2aa: 32 ' '
(gdb) print mData[639]
$20 = (const char &) #0xb2b2ab: 60 '<'
I was expecting 639 as result of calling find_first_of, but I am getting 4294967295 (which is -1 in a signed 32-bit int and matches std::string::npos). Can someone justify this behaviour? Or tell me how to workaround this?
So mData is declared as a reference? If so it doesn't really hold the content it holds a reference to the content. Is the thing to which mData refers still in existence at the time you're calling find_first_of?