My test case is so simple that I must be doing something very stupid. I wrote a simple source file test.c:
#include<stdio.h>
int main(int argc,char* argv[]){
printf("1\n");
printf("2\n");
printf("3\n");
return 0;
}
I compiled it with gcc -g test.c and started GDB with gdb a.out. Then I created a breakpoint in main with break main and ran it with run(also tried with start) - but GDB simply ignored my breakpoint!
This is the shell session of me trying to compile test.c and run GDB:
[idanarye#idanarye_lg gdbtest]$ gcc -g test.c
[idanarye#idanarye_lg gdbtest]$ gdb a.out
GNU gdb (GDB) 7.6.1
Copyright (C) 2013 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-unknown-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/idanarye/gdbtest/a.out...done.
(gdb) break main
Breakpoint 1 at 0x40050f: file test.c, line 4.
(gdb) run
Starting program: /home/idanarye/gdbtest/a.out
1
2
3
During startup program exited normally.
(gdb)
What in the world am I doing wrong here?
I'm running a 64bit Arch Linux. My GCC version is 4.8.2.
UPDATE
Here is the result of disas main:
Dump of assembler code for function main:
0x0000000000400500 <+0>: push %rbp
0x0000000000400501 <+1>: mov %rsp,%rbp
0x0000000000400504 <+4>: sub $0x10,%rsp
0x0000000000400508 <+8>: mov %edi,-0x4(%rbp)
0x000000000040050b <+11>: mov %rsi,-0x10(%rbp)
0x000000000040050f <+15>: mov $0x4005c4,%edi
0x0000000000400514 <+20>: callq 0x4003e0 <puts#plt>
0x0000000000400519 <+25>: mov $0x4005c6,%edi
0x000000000040051e <+30>: callq 0x4003e0 <puts#plt>
0x0000000000400523 <+35>: mov $0x4005c8,%edi
0x0000000000400528 <+40>: callq 0x4003e0 <puts#plt>
0x000000000040052d <+45>: mov $0x0,%eax
0x0000000000400532 <+50>: leaveq
0x0000000000400533 <+51>: retq
End of assembler dump.
UPDATE
No idea how or why, but it works now. Probably a system update fixed it...
(curated from comments)
You do not appear do be doing anything wrong; It appears to be GDB's fault.
The message During startup program exited normally. is anomalous, the correct one being Program exited normally.. It suggests GDB failed to insert a breakpoint in main() or the traced program's call to ptrace(PT_TRACE_ME, 0, 0, 0) failed. The program thus ran without being stopped, and it exited while GDB was only expecting it to start up and stop at exec(). Can you run gdb under strace while doing your example and grep strace's log for any failed ptrace calls?
You would do so with strace -f -o syscall.txt gdb ./a.out.
As of right now a stop-gap measure appears to be to run GDB as root.
I encountered a similar problem and in my case the thing was that my program was forking itself. So basically, my code looked like this:
#include <string>
#include <iostream>
#include "func.hpp"
using namespace std;
int main(int argc, char **argv)
{
if(argc <3)
{
printf("\n %s IP PORT\n",argv[0]);
printf("e.g. %s 10.32.129.77 6379\n",argv[0]);
printf("\n Going to run on the default server and port\n");
string command{argv[0]};
command+=" 10.32.129.77 6379";
printf("\nCommand: %s\n",command.c_str());
system(command.c_str());
exit(0);
}
func();
}
I was creating a breakpoint where "func" function was being called. However, I unknowingly wasn't passing the correct arguments and as a result my program forked itself with correct arguments. So basically "func" was now being called from the child process and as it turns out gdb doesn't set the breakpoints at the child process and that's why the breakpoint was not being hit.
I had this same problem. It was intermittent and drove me nuts.
Then I found I did a dumb thing. I had been running the program from the command line, and it had a bunch of arguments.
So, I copied the command line with the mouse-copy-paste buffer.
Then started: gdb Program
Then did: break man
Then did: -PASTE-FROM-MOUSE-
It never stopped, until I realized that I had pasted too much of the command line:
"--option=c ... |& tee LOG"
It looked like an intermittent problem, until I realized it was a brain bug.
Hope this helps someone. The command line redirect - did something in GDB, no clue what (other than ignore breakpoints).
Related
I am trying to debug AVX-512 instructions on an emulated CPU using Intel® Software Development Emulator but it doesn't work as desired after setting a breakpoint. I followed this blog post: Debugging Emulated Code on Linux*
In window #1:
~$ g++ -g -O0 -mavx512f main.cpp -o main # compile main.cpp file
~$ sde -debug -- ./main # enable debugging
Application stopped until continued from debugger.
Start GDB, then issue this command at the (gdb) prompt:
target remote :54105
In window #2
# run debugger
~$ gdb ./main
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 ./main...
# set target "target remote :portnumber"
(gdb) target remote :54105
Remote debugging using :54105
warning: remote target does not support file transfer, attempting to access files from local filesystem.
Reading symbols from /lib64/ld-linux-x86-64.so.2...
(No debugging symbols found in /lib64/ld-linux-x86-64.so.2)
0x00007fa7bbbcc100 in ?? () from /lib64/ld-linux-x86-64.so.2
# suspend program at main function
(gdb) break main
Breakpoint 1 at 0x2c9c: file /home/borrow/source/repos/se-test/main.cpp, line 165.
# start program execution from the beginning of the program
(gdb) run
The "remote" target does not support "run". Try "help target" or
"continue".
# step to next line of code
(gdb) step
Cannot find bounds of current function
# continue executing until next break point
(gdb) c
Continuing.
warning: Probes-based dynamic linker interface failed.
Reverting to original interface.
[Inferior 1 (Remote target) exited normally]
In window #2: as you can see
gdb run should run a program but it doesn't work. gdb c should also run until the next breakpoint but executes the program and terminates. This command gives me the following warning message:
warning: Probes-based dynamic linker interface failed.
In window #1: The program runs and ends (without stopping).
Program code looks like this:
// main.cpp
#include <immintrin.h>
const int N=64;
int64_t srcA[N] = {0};
int64_t srcB[N] = {0};
int64_t dst[N] = {0};
void foo()
{
__m512i result,B,C;
for ( int i=0; i<N; i+=8 ){
B = _mm512_loadu_si512(&srcA[i]);
C = _mm512_loadu_si512(&srcB[i]);
result = _mm512_add_epi64(B,C);
_mm512_storeu_si512(&dst[i], result);
}
}
int main() {
...
foo();
...
}
I tried running AVX2 code without SDE emulator using gdb and it worked. First I start it on an emulated CPU with SDE, it fails. How can I solve this problem?
It seems to be broken for PIE executables
(confirmed on Arch GNU/Linux with GCC 10.2, GDB 10.1, SDE 8.33.)
Build with g++ -O2 -fno-pie -no-pie -g -march=skylake-avx512 and everything works. (I had to run gdb ./a.out instead of bare GDB; without that it couldn't find the right file even after connecting to the remote.)
$ g++ -O2 -march=skylake-avx512 -no-pie -fno-pie -g avx512.cpp
$ /opt/sde-external-8.33.0-2019-02-07-lin/sde64 -debug -- ./a.out
Application stopped until continued from debugger.
Start GDB, then issue this command at the (gdb) prompt:
target remote :59783
Then in another terminal tab
$ gdb ./a.out
...
(gdb) target remote :59783
warning: remote target does not support file transfer, attempting to access files from local filesystem.
Reading symbols from /lib64/ld-linux-x86-64.so.2...
(No debugging symbols found in /lib64/ld-linux-x86-64.so.2)
0x00007f4f7033b090 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) b main
Breakpoint 1 at 0x401050: file avx512.cpp, line 29.
(gdb) b foo
Breakpoint 2 at 0x401190: file avx512.cpp, line 14.
(gdb) c
Continuing.
Breakpoint 1, main () at avx512.cpp:23
(gdb) layout asm
(copy-paste of some of the disassembly window)
│B+ 0x401120 <_Z3foov> xor eax,eax
│ 0x401122 <_Z3foov+2> nop WORD PTR [rax+rax*1+0x0]
│ >0x401128 <_Z3foov+8> vmovdqu64 zmm1,ZMMWORD PTR [rax+0x404260]
│ 0x401132 <_Z3foov+18> add rax,0x40
│ 0x401136 <_Z3foov+22> vpaddq zmm0,zmm1,ZMMWORD PTR [rax+0x404420]
│ 0x401140 <_Z3foov+32> vmovdqu64 ZMMWORD PTR [rax+0x404020],zmm0
│ 0x40114a <_Z3foov+42> cmp rax,0x200
│ 0x401150 <_Z3foov+48> jne 0x401128 <_Z3foov+8>
│ 0x401152 <_Z3foov+50> vzeroupper
│ 0x401155 <_Z3foov+53> ret
(gdb) layout src
asm-level and source-level debugging both work fine, stepping into intrinsic "functions" in avx512fintrin.h and so on when using stepi (aka si).
Without specifying the filename separately from connecting to the remote:
$ gdb
(gdb) target remote :46879
Remote debugging using :46879 warning: No executable has been specified and target does not support determining executable automatically. Try using the "file" command.
0x00007f0f85830090 in ?? ()
(gdb)
(IDK if it matters that my .gdbinit includes layout reg, the full-screen terminal TUI mode. Nice when it works but somewhat buggy.)
Or as a super hacky workaround with PIE executables, I was also able to put a delay loop at the top of main, giving you a chance to attach and then control-C before SDE finishes executing your program.
Then I could set breakpoints and start single-stepping. (Presumably a sleep or read system call would work). Source-level debugging still seemed broken, but I was able to debug the asm with layout reg. I used set $rip = ... with a copy-pasted address to get out of the _mm_pause() loop after attaching and hitting control-C.
When writing assembly manually with GNU GAS, within a function, I want to set a label such that:
GDB won't treat that label as the function name
I can use b mylabel to break on the label
A similar question for nasm has been asked at: Break at local label using GDB for NASM assembly but I wanted to make it more precise here that I want GNU GAS and ELF output.
E.g. if I defined a normal label mylabel as in:
main.S
.text
.global _start
_start:
/* exit */
mov $60, %rax
mylabel:
mov $0, %rdi
syscall
that does not satisfy me because when GDB reaches the mov $0, %rdi, bt shows mylabel as the function name, and I would like it to be _start instead. In particular, this can break backtraces because GDB can't find the stack frame: How gdb reconstructs stacktrace for C++?
However, if I replace mylabel with .Lmylabel as explained at: Local labels in GNU assembler; gdb printing backtrace as though labels are functions then _start is the function name as desired, but b .Lmylabel fails. nm does not show the symbol at all either.
Does the ELF / DWARF formats support anything that could be used, and is there any way to expose that though GNU GAS?
Tested in Ubuntu 18.10, GDB 8.2, GNU GAS 2.31.1.
I'm not sure if this fits your needs, but you can do this (for a non-PIE binary, so link with -no-pie):
.text
.global _start
_start:
/* exit */
mov $60, %rax
.Lmylabel:
mov $0, %rdi
syscall
.section .rodata
mylabel:
.long .Lmylabel
Then, you can set a breakpoint using break *mylabel (note the *):
(gdb) break *mylabel
Breakpoint 2 at 0x401007: file t.S, line 7.
Since mylabel is more or less a function pointer, GDB does not know anything about it and will ignore it:
Breakpoint 1, _start () at t.S:5
5 mov $60, %rax
(gdb) si
7 mov $0, %rdi
With a linker script, it should be possible to put the mylabel symbol into a section which is not loaded, to reduce run-time overhead.
For some program LDSTORE I need to install llvm on my Mac (macOS 10.13). I do this using brew install llvm. This leads to a Segmentation fault: 11 message when running ldstore, or other (C++ based?) programs.
How can I fix this?
It clearly has to do with llvm, as doing brew uninstall llvm fixes the issue (obvious ldstore won't work in that case).
For what it's worth: I use the native python 2.7.10.
As per suggestion of Stanislav Pankevich I ran lldb ldstore_v11 followed by r, resulting in this:
lldb ldstore_v11
(lldb) target create "ldstore_v11"
Current executable set to 'ldstore_v11' (x86_64).
(lldb) r
Process 15841 launched: '/Users/swvanderlaan/bin/ldstore_v11' (x86_64)
dyld: Library not loaded: /usr/local/opt/libiomp/lib/libiomp5.dylib
Referenced from: /Users/swvanderlaan/bin/ldstore_v11
Reason: image not found
Process 15841 stopped
* thread #1, stop reason = signal SIGABRT
frame #0: 0x0000000100095216 dyld`__abort_with_payload + 10
dyld`__abort_with_payload:
-> 0x100095216 <+10>: jae 0x100095220 ; <+20>
0x100095218 <+12>: movq %rax, %rdi
0x10009521b <+15>: jmp 0x100094a74 ; cerror_nocancel
0x100095220 <+20>: retq
Target 0: (ldstore_v11) stopped.
It's odd that the library is not found, as I clearly added to my bash_profile the following line: export PATH="/usr/local/opt/llvm/bin:$PATH", as per suggestion of the installation messages.
Hope someone can help me debug this.
Thanks,
Sander
P.S. I hope it's clear, I'm not trying to develop anything, I'm just trying to use LDSTORE.
The problem is that this tool is dynamically linked against libiomp5.dylib, which must be present at /usr/local/opt/libiomp/lib/libiomp5.dylib for it to work.
As suggested by Stanislav, download the precompiled binaries from http://releases.llvm.org/5.0.0/clang+llvm-5.0.0-x86_64-apple-darwin.tar.xz. This contains the library you need: ./lib/libiomp5.dylib. You'll have to copy the library into /usr/local/opt/libiomp/lib, which probably won't exist yet.
Once you've done that, you'll be able to run ldstore.
I'm following these lessons from OpenSecurityTraining.
I've reached the lab part where I've to train myself on a CMU Bomb. They provide a x86_64 compiled CMU Bomb that you can find here to train on : CMU Bomb x86-64 originally from a 32-bit bomb from CMU Labs for
Computer Systems: A Programmer's Perspective (CS:APP) 1st edition.
I had a virtualized 64 bits Elementary OS distribution where I disassembled the CMU Bomb without problems using GDB. Now, I've a 64 bits Ubuntu 14.04 LTS (not virtualized) and when I try to reproduce why I did on my Elementary OS, I get the famous error.
I run these commands :
gdb ./bomb-x64
(gdb) b main
Breakpoint 1 at 0x400dbd: file bomb.c, line 37. -- why bomb.c ?
(gdb) r
...
bomb.c: no such file or directory
Edit : I can create breakpoints on others functions of the CMU Bomb and it works as expected.
Example :
(gdb) b phase_1
Breakpoint 3 at 0x400f00
(gdb) r
Breakpoint 1, 0x0000000000400f00 in phase_1 ()
(gdb) disas
Dump of assembler code for function phase_1:
=> 0x0000000000400f00 <+0>: sub $0x8,%rsp
0x0000000000400f04 <+4>: mov $0x4023b0,%esi
0x0000000000400f09 <+9>: callq 0x401308 <strings_not_equal>
0x0000000000400f0e <+14>: test %eax,%eax
0x0000000000400f10 <+16>: je 0x400f17 <phase_1+23>
0x0000000000400f12 <+18>: callq 0x40140a <explode_bomb>
0x0000000000400f17 <+23>: add $0x8,%rsp
0x0000000000400f1b <+27>: retq
End of assembler dump.
I've heard of ia32-libs but this doesn't do anything more since I'm on 64bits Ubuntu and run a 64bits compiled CMU Bomb, am I wrong ?
Use dir command to set source path
dir /usr/src/debug
in above path. Your code should present.
The executable contains debugging symbols, which indicate the file (and particular line in the file) corresponding to each bit of assembled code. This is what allows you to step through C code in the debugger. The debugging symbols are put there by the compiler (e.g. by using the -g argument to gcc).
If you don't have the C files that were used to compile the executable, the debugger won't be able to show you the C, and you'll be limited to looking at assembly.
(gdb) list
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/tasks.c: No such file or directory.
(gdb) set substitute-path /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/ C:/Espressif/frameworks/esp-idf-v4.4/
I'm trying to disassemble a program to see a syscall assembly instruction (the INT instruction, I believe) and the handler with GDB and have written a little program (see below) for it that opens and closes a file.
I was able to follow the call to fopen with GDB until it executed a call.
When I tried to tell GDB "disassemble 0x...." (address of call) it responded with 'No function contains specified address.'
Is it possible to force GDB to disassemble (or display it in assembler as good as possible) that memory address? If so, how?
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE* f;
f = fopen("main.c", "r");
if (!f) {
perror("open");
return -1;
}
fclose(f);
return 0;
}
Yeah, disassemble is not the best command to use here.
The command you want is "x/i" (examine as instructions):
(gdb) x/i 0xdeadbeef
Do you only want to disassemble your actual main? If so try this:
(gdb) info line main
(gdb) disas STARTADDRESS ENDADDRESS
Like so:
USER#MACHINE /cygdrive/c/prog/dsa
$ gcc-3.exe -g main.c
USER#MACHINE /cygdrive/c/prog/dsa
$ gdb a.exe
GNU gdb 6.8.0.20080328-cvs (cygwin-special)
...
(gdb) info line main
Line 3 of "main.c" starts at address 0x401050 <main> and ends at 0x401075 <main+
(gdb) disas 0x401050 0x401075
Dump of assembler code from 0x401050 to 0x401075:
0x00401050 <main+0>: push %ebp
0x00401051 <main+1>: mov %esp,%ebp
0x00401053 <main+3>: sub $0x18,%esp
0x00401056 <main+6>: and $0xfffffff0,%esp
0x00401059 <main+9>: mov $0x0,%eax
0x0040105e <main+14>: add $0xf,%eax
0x00401061 <main+17>: add $0xf,%eax
0x00401064 <main+20>: shr $0x4,%eax
0x00401067 <main+23>: shl $0x4,%eax
0x0040106a <main+26>: mov %eax,-0xc(%ebp)
0x0040106d <main+29>: mov -0xc(%ebp),%eax
0x00401070 <main+32>: call 0x4010c4 <_alloca>
End of assembler dump.
I don't see your system interrupt call however. (its been a while since I last tried to make a system call in assembly. INT 21h though, last I recall
This isn't the direct answer to your question, but since you seem to just want to disassemble the binary, perhaps you could just use objdump:
objdump -d program
This should give you its dissassembly. You can add -S if you want it source-annotated.
You can force gcc to output directly to assembly code by adding the -S switch
gcc -S hello.c
fopen() is a C library function and so you won't see any syscall instructions in your code, just a regular function call. At some point, it does call open(2), but it does that via a trampoline. There is simply a jump to the VDSO page, which is provided by the kernel to every process. The VDSO then provides code to make the system call. On modern processors, the SYSCALL or SYSENTER instructions will be used, but you can also use INT 80h on x86 processors.
If all that you want is to see the disassembly with the INTC call, use objdump -d as someone mentioned but use the -static option when compiling. Otherwise the fopen function is not compiled into the elf and is linked at runtime.
gdb disassemble has a /m to include source code alongside the instructions. This is equivalent of objdump -S, with the extra benefit of confining to just the one function (or address-range) of interest.
You don't have to use gdb. GCC will do it.
gcc -S foo.c
This will create foo.s which is the assembly.
gcc -m32 -c -g -Wa,-a,-ad foo.c > foo.lst
The above version will create a listing file that has both the C and the assembly generated by it. GCC FAQ
full example for disassembling a memory range to C
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-gdb
(gdb)file /root/ncs/zephyr/samples/hello_world/build_nrf9160dk_nrf9160ns/zephyr/zephyr.elf
(gdb) directory /root/ncs/zephyr/samples/hello_world/src
#here you want 1
(gdb) info line* 0x000328C0
#here you want 2, -0x04 ~ +0x04 is your range size
(gdb) disassemble /m 0x000328C0-0x04, 0x000328C0+0x04
#here with binary code
(gdb) disassemble /r 0x000328C0-0x04, 0x000328C0+0x04
(gdb) info thread
(gdb) interpreter-exec mi -thread-info
The accepted is not really correct. It does work in some circumstances.
(gdb) disas STARTADDRESS ENDADDRESS
The highest upvoted answer is correct. Read no further is you don't wish to understand why it is correct.
(gdb) x/i 0xdeadbeef
With an appropriately meaningless hex address.
I have an STM32 and I have relocated the code with PIC. The normal boot address is 0x8000000, with a 0x200 vector table. So a normal entry is 0x8000200. However, I have programmed the binary to 0x80040200 (two NOR flash sectors away) and wish to debug there.
The issue gdb has with this is 'file foo.elf' is showing that code is in the first range. Special command like 'disassemble' will actually look at the binary on the host. For the cross debug case, gdb would have to look at memory on the remote which could be expensive. So, it appears that the 'x /i' (examine as code) is the best option. The debug information that gdb depends on (where routines start/end) is not present in a random binary chunk.
To combine the answers above for PIC code on an embedded cross system,
You need to create multiple elf files, one for each possible target location. Use the GDB's file command to select the one with proper symbol locations.
This will NOT work for Cross development
You can use generating gcc debug symbols. The steps are,
Build normal link address.
Extract symbols.
Use symbol-file with an offset for the runtime address.
(gdb) help symbol-file
Load symbol table from executable file FILE.
Usage: symbol-file [-readnow | -readnever] [-o OFF] FILE
OFF is an optional offset which is added to each section address.
You can then switch symbol files to a relocated run address to use the first answer.
If you have a case where the code is relocated, but data is absolute, you need to link twice and choose the relocated elf files (symbols only are relocated and code is the same). This is desirable with NOR flash that is XIP (execute-in-place) as the memory devices for .text and .rodata are different from .data and .bss. Ie, many lower-to-middle scale embedded devices. However, gcc does not support this code generation option (at least on ARM). You must use a 'static base' register (for example, r9 as u-boot does).
There is another way which I wanted to presetn using gdb on top of the suggestions above:
Launch your program with gdb, and set a break point on main break *main and run
The you can use info proc mappings.