GDB improperly tokenizes command-line arguments containing spaces - gdb

(This is possibly related to Pass arguments with space in GDB?, which did not get resolved.)
Witness the following:
zlaski#RUMCAJS /cygdrive/d/music/wurlitzer/Drum And Bass
$ ls Wen\ -\ Commotion.backup.mp3
'Wen - Commotion.backup.mp3'
zlaski#RUMCAJS /cygdrive/d/music/wurlitzer/Drum And Bass
$ gdb -q -ex start --args ls Wen\ -\ Commotion.backup.mp3
Reading symbols from ls...
Reading symbols from /usr/bin/ls.exe.dbg...
Temporary breakpoint 1 at 0x1004181e0: file /usr/src/debug/coreutils-9.0-1/src/ls.c, line 1658.
Starting program: /usr/bin/ls Wen\ -\ Commotion.backup.mp3
[New Thread 34524.0x4edc]
[New Thread 34524.0x2abc]
[New Thread 34524.0x7dd4]
[New Thread 34524.0x7aa0]
Thread 1 "ls" hit Temporary breakpoint 1, main (argc=4, argv=0x7ffffcc20) at /usr/src/debug/coreutils-9.0-1/src/ls.c:1658
We are passing a single argument, Wen\ -\ Commotion.backup.mp3, to the ls program. However, gdb chops it into 3 pieces, which is why we wind up with an argc of 4 instead of 2:
(gdb) print argv[0]
$1 = 0xa00003380 "/usr/bin/ls"
(gdb) print argv[1]
$2 = 0x7ffffcc67 "Wen\\"
(gdb) print argv[2]
$3 = 0x7ffffcc6c "-\\"
(gdb) print argv[3]
$4 = 0x7ffffcc6f "Commotion.backup.mp3"
I have also tried the following incantations of the argument:
'Wen - Commotion.backup.mp3'
"Wen - Commotion.backup.mp3"
Wen\\ -\\ Commotion.backup.mp3
"Wen\\ -\\ Commotion.backup.mp3"
'Wen\\ -\\ Commotion.backup.mp3'
'Wen\ -\ Commotion.backup.mp3'
"Wen\ -\ Commotion.backup.mp3"
In all cases, the argument is chopped into 3 pieces.
I have an eerie feeling that I must be doing something wrong as it seems implausible that gdb would have such a glaring defect for all these years. Anyhoo, I hope that you gentlefolk can enlighten me here.
My configuration is as follows:
MACHTYPE=x86_64-unknown-cygwin
bash-4.4.12-3
coreutils-9.0-1
cygwin-3.4.3-1
gdb-11.2-1
Thanks!

Related

gdb - finding the values of strncmp() function

I have a code which has hit a seg fault with strncmp() and I have this info below:
#7 0x00007f3662e5d4e7 in __strncmp_sse42 () from /lib64/libc.so.6
(gdb) info locals
No symbol table info available.
(gdb) info args
No symbol table info available.
(gdb) info frame
Stack level 7, frame at 0x7f35f4413b70:
rip = 0x7f3662e5d4e7 in __strncmp_sse42; saved rip = 0x7f35f64f5d6d
called by frame at 0x7f35f4413cc0, caller of frame at 0x7f35f4413b68
Arglist at 0x7f35f4413b60, args:
Locals at 0x7f35f4413b60, Previous frame's sp is 0x7f35f4413b70
Saved registers:
rip at 0x7f35f4413b68
Is there a way to check the args passed into this function? Any explanation will help me relate what is going on.
Appreciate the help in advance.
One way to trace args passed into system calls is to use ltrace. Not always guaranteed to be helpful, but quick and painless to try. Here's example of using ltrace to trace the calls made by particular invocation of grep command:
$ ltrace -s 200 grep XYZ hello.cc 2>&1 | grep XYZ
memcpy(0xe7f030, "XYZ\0", 4) = 0xe7f030
memchr("XYZ", '\n', 3) = nil
memcpy(0xe7f6b0, "XYZ", 3) = 0xe7f6b0
strlen("XYZ") = 3
strncmp("Y", "XYZ", 3) = 1
strncmp("XYZ", "Y", 1) = -1
strlen("XYZ") = 3
strcmp("XYZ", "XYZ") = 0
strlen("XYZ") = 3
memcpy(0xe7f630, "XYZ\0", 4) = 0xe7f630
strlen("XYZ") = 3
memcpy(0xe7f840, "XYZ", 3) = 0xe7f840
You're not specifying which operating system you're using, but try installing debug symbols for libc. E.g. libc6-dbg on Ubuntu/Debian.

How to calculate expected core file size

How can I calculate the expected size of a coredump?
I have a truncated core file(coredump) from arm64 target. And I can find expected size of a core file(coredump), from output of gdb-multiarch.
BFD: warning: /home/.../core-m is truncated: expected core file size >= 748728320, found: 518127616
From above, I can find expected size of a coredump is 748728320 and its actual size is 518127616.
Now, I wonder how gdb-multiarch calculates the expected size of a coredump.
I can find size of each section, using readelf -e and I thought the sum of each section's size will be same with expected size of a core file. So I get the sum, but it is not equal to expected size of the coredump.
the sum: 748680864
expected size by `gdb-multiarch`: 748728320
How can I calculate this, correctly?
UPDATE
I've just got to know I can find the expected size of a coredump, from output of readelf -e. readelf -e shows offset and size of each segment. I got the result from my truncated coredump.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
NOTE 0x000000000000b2f8 0x0000000000000000 0x0000000000000000
0x000000000002b6a0 0x0000000000000000 0x0
LOAD 0x0000000000037000 0x000000556af44000 0x0000000000000000
0x0000000000001000 0x00000000008cc000 R E 0x1000
...
LOAD 0x000000002c831000 0x0000007fca9c5000 0x0000000000000000
0x00000000001da000 0x00000000001da000 RW 0x1000
From above, I can find offset and size of last segment. Offset is 0x2c831000, and size if 0x1da000. And expected size of dump will be 0x2c831000 + 0x1da000 = 0x2CA0B000(748728320). This is same with one from gdb-multiarch.
This approach can be used only if readelf is available. And I can't explain how the expected size of dump is calculated, still. I hope someone give me the explanation.
I use the following script, seems to work quite well. As the comment explains, we simply find the largest LOAD section end offset in the file. (Note that it accounts for sparse files.)
If I remember correctly, I lifted the technique from GDB's corefile loading code (or some similar standard tool that warns about corefile truncation).
#!/bin/bash
trap 'exit 1' ERR # Abort script on error.
if [[ $# != 1 ]] ; then
echo "$( basename $0 ) <coreFile>"
exit 1
fi
coreFile=$1
# Examine all LOAD sections in the corefile, calculate the file offset of each section's end,
# and find the largest offset.
expectedSize=$( readelf -l ${coreFile} | grep -A 1 LOAD |
while read type offset etc && read fsize etc ; do
echo $(( $offset + $fsize ))
done | sort -n | tail -n 1 )
actualSize=$( du --block-size=1 --apparent-size ${coreFile} | cut -f1 )
physicalSize=$( du --block-size=1 ${coreFile} | cut -f1 )
if [[ ${actualSize} < ${expectedSize} ]] ; then
echo "Physical size ${physicalSize}"
echo "Expected logical size ${expectedSize}"
echo "Actual logical size ${actualSize}"
exit 2
fi

How do I print only the value of a variable in GDB?

I have this script of GDB commands:
$ cat gdb_commands.txt
set pagination off
set logging file output.txt
set logging on
file stuff
b *0x80000014
run
echo ***DIFF THIS***\n
echo eax:
print $eax
echo ebx:
print $ebx
echo ecx:
print $ecx
echo edx:
print $edx
echo ***DIFF THIS END***\n
quit
If I run it in GDB I get this:
$ gdb -q -x gdb_commands.txt
Breakpoint 1 at 0x80000014
Breakpoint 1, 0x80000014 in _start ()
***DIFF THIS***
eax:$1 = 1
ebx:$2 = 2
ecx:$3 = 3
edx:$4 = 4
***DIFF THIS END***
A debugging session is active.
Inferior 1 [process 8947] will be killed.
Quit anyway? (y or n) [answered Y; input not from terminal]
So there is that ugly dollar sign thing. I can sed it out, but I would like to have GDB to do that. Is it possible?
(The reason I'm use GDB like this is because we are writing an emulator and want to test if it behaves correctly.)
ugly dollar sign thing ... I would like to have gdb to do that
You can control GDB's output precisely with printf command:
(gdb) print/x $rax
$1 = 0x7ffff7ffe2a0
(gdb) printf "0x%lx\n", $rax
0x7ffff7ffe2a0
There is a command that does exactly that:
(gdb) help output
Like "print" but don't put in value history and don't print newline.
This is useful in user-defined commands.
output prints the variables without the $1 = and the newline.

gdb - how to see what function used stdout?

I have an OpenGL library bug I'm trying to trace, and the bug prints out something that looks like C code into stdout. This is the program, and the bug occurs as soon as glutMainLoop() is called, but I suspect that it's not that function that is faulty. How would I go tracing what function wrote to stdout?
As per request, the output:
arc_ccw_turn, p = 0
case b
arc_ccw_turn, p = 0
case d
arc_ccw_turn, p = 0
case a
arc_ccw_turn, p = 0
case c
I've reported the bug already, but I'd try and provide a GDB backtrace for the issue too.
If you are using Linux then set a breakpoint on write(), all output to stdout and stderr eventually goes through this function. The following is for x86-64, for other architectures you would need to change register names:
$ gdb /usr/bin/cat
Reading symbols from /usr/bin/cat...(no debugging symbols found)...done.
(gdb) set args /proc/cpuinfo
(gdb) b write
Breakpoint 1 at 0x401740
(gdb) condition 1 ($rdi == 1 || $rdi == 2)
(gdb) display $rdi
(gdb) display $rsi
(gdb) display $rdx
(gdb) r
Starting program: /usr/bin/cat /proc/cpuinfo
3: $rdx = 3368
2: $rsi = 6348800
1: $rdi = 1
(gdb) p (char*)$rsi
$4 = 0x60e000 "processor\t: 0\nvendor_id\t: GenuineIntel\ncpu family\t: 6\nmodel\t\t: 30\nmodel name\t: Intel(R) Core(TM) i7 CPU 870 # 2.93GHz\nstepping\t: 5\nmicrocode\t: 0x5\ncpu MHz\t\t: 1199.000\ncache size\t: 8192 KB\nphy"...
Put breakpoints on std::streambuf::sputc and std::streambuf::sputn. If necessary, do print std::cin::rdbuf() once you're in main, and condition the break point on this being equal to the value use get back from this expression.

Go: print variables with gdb

In this program, how can break execution with the debugger and print the value of i?
package main
import "fmt"
func main() {
x := "abc"
i := 3
fmt.Println(i)
fmt.Println(x)
}
I can't print i. However I can print x:
go build test.go
gdb test
[...]Reading symbols from /home/ned/test...done.
(gdb) br 9
(gdb) run
(gdb) p i
No symbol "i" in current context.
(gdb) p x
$1 = "abc"
It sounds like the variable i probably got optimized out of existence by the compiler. Did you try a debug build?
You can use go build -gcflags '-N'.