errno
is actually required by the C standard to be a macro that expands to a modifiable lvalue. In the simplest case, it can expand to the name of a declared variable, but for implementations that need distinct errno
objects for different threads, it's typically defined something like this:
#define errno (*__errno_location ())
gdb
is usually able to evaluate function calls; for example, on my system:
(gdb) p __errno_location()
$1 = -134383968
(gdb) p errno
Cannot find thread-local variables on this target
The first printed value happens to be the low-order 32 bits of the pointer value returned by __errno_location()
. I don't know gdb well enough to explain that behavior, but it does demonstrate that it can execute function calls.
As a workaround, you can modify the source code so that it saves either the address of errno
, or its value, in a variable that gdb can display:
(gdb) l
1 #include <errno.h>
2 #include <stdio.h>
3 int main(void) {
4 errno = 42; /* arbitrary value */
5 const int *errno_ptr = &errno;
6 int errno_value = errno;
7 printf("%d %d %d\n", errno, errno_value, *errno_ptr);
8 }
(gdb) b 8
Breakpoint 1 at 0x4005b6: file c.c, line 8.
(gdb) r
Starting program: /home/kst/c
42 42 42
Breakpoint 1, main () at c.c:8
8 }
(gdb) p errno
Cannot find thread-local variables on this target
(gdb) p errno_value
$1 = 42
(gdb) p *errno_ptr
$2 = 42
The *errno_ptr
approach has the advantage that you only have to assign it once -- unless you're debugging a multi-threaded program. In that case, the value of &errno
can vary depending on the thread in which you evaluate it.
This is probably a bug, or at least a missing feature, in gdb
.
UPDATE Kevin Cox's comment suggests a workaround:
print *((int*(*)())__errno_location)()
And with gcc 6.2 and gdb 7.11, print errno
actually works:
(gdb) l
1 #include <errno.h>
2 int main(void) {
3 errno = 42;
4 return 0;
5 }
(gdb) b 4
Breakpoint 1 at 0x6bf: file c.c, line 4.
(gdb) r
Starting program: /home/kst/c
Breakpoint 1, main () at c.c:4
4 return 0;
(gdb) p errno
$1 = 42
(gdb)