I got 2 questions about GDB + golang?
1) Go build GCC flags
when I run "go build" , which gcc flags do the Go builder use to build a program? The build value is same as the "GOGCCFLAGS" set in the go envionment?
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fno-common"
because I don't see any "-g" or "-g3" flags for adding code symbol. If yes, how could the symbol table be compiled ?
2) How to print a value in GDB
I followed the tutorial here GDB debug go tutorial, but it seems the value is not what I set.
By the way, I noticed there is a post about it gdb debug go
However, doesn't work for me either.
Golang now works well with GDB
Here is an example golang app gdbtest
- gdbtest/
- main.go
Take the following example main.go
package main
import "fmt"
type MyStruct struct {
x string
i int
f float64
}
func main() {
x := "abc"
i := 3
fmt.Println(i)
fmt.Println(x)
ms := &MyStruct{
x: "cba",
i: 10,
f: 11.10335,
}
fmt.Println(ms)
}
Save that to main.go. Then compile with the follwing gcflag flag.
go build -gcflags "-N"
Open gdb with your newly built golang app
gdb gdbtest
# or
gdb <PROJECT_NAME>
You now have full control of gdb. For example, add a breakpoint with br <linenumber> command, then execute the app with run
(gdb) br 22
Breakpoint 1 at 0x2311: file /go/src/github.com/cevaris/gdbtest/main.go, line 22.
(gdb) run
Starting program: /go/src/github.com/cevaris/gdbtest/gdbtest
3
abc
Breakpoint 1, main.main () at /go/src/github.com/cevaris/gdbtest/main.go:22
22 fmt.Println(ms)
(gdb)
Now you can print all the local variables
(gdb) info locals
i = 3
ms = 0x20819e020
x = 0xdb1d0 "abc"
Even get access to the pointers
(gdb) p ms
$1 = (struct main.MyStruct *) 0x20819e020
(gdb) p *ms
$2 = {x = 0xdb870 "cba", i = 10, f = 11.103350000000001}
Go does not work well with GDB and one of the known problems is the printing of values.
More details can be found here.
The accepted answer is outdated.
Golang currently works with GDB (including locals) if you build with the flags -gcflags=all="-N -l", as described on the official documentation
Related
For example, we have a code:
#include <stdio.h>
int main()
{
printf("Hello, Stack Overflow!\n");
return 0;
}
And we want to get statically linked executable:
$ gcc -o main main.c -static
Everything is going well, but there is one nuance:
$ du -h main
768K main
Isn't it too much for such simple program? Let's take a list of symbols, that used in executable:
$ nm main
00000000004010f4 T abort
00000000004aec70 B __abort_msg
0000000000444be0 t add_alias2.part.0
000000000047e240 t add_fdes
000000000040163a t add_fdes.cold
0000000000444c70 t add_module.constprop.0
0000000000463570 t add_name_to_object.isra.0
0000000000462e30 t add_path.constprop.0.isra.0
00000000004adb28 d adds.1
000000000044fb70 T __add_to_environ
0000000000474210 t add_to_global_resize
00000000004741f0 t add_to_global_resize_failure.isra.0
0000000000474080 t add_to_global_update
0000000000409f50 t adjust_wide_data
00000000004af150 V __after_morecore_hook
0000000000405bd0 t alias_compare
0000000000481358 r aliasfile.0
00000000004166d0 W aligned_alloc
00000000004af178 b aligned_heap_area
0000000000461b40 T __alloc_dir
00000000004117b0 t alloc_perturb
00000000004af9c8 b any_objects_registered
0000000000486c40 r archfname
00000000004af520 b archive_stat
00000000004af500 b archloaded
00000000004af5c8 b archmapped
0000000000413780 t arena_get2.part.0
0000000000413ea0 t arena_get_retry
000000000045f8a0 T __argz_add_sep
000000000045f8a0 W argz_add_sep
000000000045f7c0 T __argz_create_sep
000000000045f7c0 W argz_create_sep
0000000000408c30 T ___asprintf
0000000000408c30 T __asprintf
0000000000408c30 W asprintf
0000000000402cd0 T __assert_fail
0000000000402b70 T __assert_fail_base
00000000004010e0 t __assert_fail_base.cold
000000000047fca0 t base_of_encoded_value
0000000000401658 t base_of_encoded_value.cold
0000000000417e60 i bcmp
0000000000495330 r blanks
00000000004953a0 r blanks
0000000000462250 T __brk
0000000000462250 W brk
00000000004ae230 B __bss_start
00000000004609d0 T __btowc
00000000004609d0 W btowc
00000000004afa00 b buf
...
In my case nm main | wc gives 1726 lines, almost of which relate to libraries like libc. So, how we can eliminate unused code in statically linked files?
There is already a similar question, but instructions in it answers work only for functions, used in project, not for libraries functions.
So, how we can eliminate unused code in statically linked files?
GLIBC is not optimized for static linkinig. If you want small statically linked binaries, use some other libc, e.g. dietlibc. See this comparison of available options.
While it could be argued that your sample program does use printf, and therefore linking all the associated support code is justified, the same can not be said for this program:
int main() { return 0; }
And yet that program (when statically linked) weights in at 765KiB on my system using Debian GLIBC 2.31-13:
$ gcc tt.c -static
$ ls -l a.out
-rwxr-x--- 1 user user 782648 Aug 19 08:28 a.out
Watchpoints on function-local variables usually get removed upon the function return, with a message «Watchpoint 7 deleted because the program has left the block in». Illustration:
struct mystruct{
int a, b, c;
};
void MyFunc(){
mystruct obj;
obj.a = 2;
}
int main(){
MyFunc();
}
gdb session example
(gdb) b 7
Breakpoint 1 at 0x4004f1: file /tmp/test2.cpp, line 7.
(gdb) r
Starting program: /tmp/test2
Breakpoint 1, MyFunc () at /tmp/test2.cpp:7
7 obj.a = 2;
(gdb) wa obj
Hardware watchpoint 2: obj
(gdb) c
Continuing.
Hardware watchpoint 2: obj
Old value = {a = 4195600, b = 0, c = 4195328}
New value = {a = 2, b = 0, c = 4195328}
MyFunc () at /tmp/test2.cpp:8
8 }
(gdb) c
Continuing.
Watchpoint 2 deleted because the program has left the block in
which its expression is valid.
main () at /tmp/test2.cpp:12
12 }
I tried casting it like wa *(mystruct *)&obj and wa *(mystruct *)(void*)&obj, to no avail.
I need it because GDB on embedded ARM device I'm working with is broken: sometimes it removes a watchpoint for no reason; backtrace then looks like lines marked with "??" signs, and a message about corrupted stack. Even though application is actually fine.
As GDB: Setting Watchpoints says,
GDB automatically deletes watchpoints that watch local (automatic) variables, or expressions that involve such variables, when they go out of scope, that is, when the execution leaves the block in which these variables were defined.
However, as of release 7.3 (thanks to #Hi-Angel and user parcs on IRC for pointing this out; I missed seeing it right there in the documentation), the watch command accepts a -location argument:
Ordinarily a watchpoint respects the scope of variables in expr (see below). The -location argument tells GDB to instead watch the memory referred to by expr. In this case, GDB will evaluate expr, take the address of the result, and watch the memory at that address. The type of the result is used to determine the size of the watched memory.
On older versions of GDB, you can run this instead, using the example from your question:
eval "watch *(mystruct *)%p", &obj
Note that watching locations on the stack may cause spurious notifications if the memory you're watching gets reused by another function's local variables.
As an alternative, you can automate the setting of a watchpoint on an automatic variable that keeps coming into and out of scope. Set a breakpoint at a point where it's in scope - for example, at the beginning of the function or block in which it's declared - then attach a watch and continue command:
(gdb) break MyFunc
(gdb) commands $bpnum
>watch obj
>continue
>end
I met a problem when inspecting the local variables of user space application in systemtap.
I write a test.c like this:
#include <stdio.h>
int func(int *p, int val)
{
printf("p=%p val=%d\n", p, val);
return 1;
}
int main()
{
int a = 7;
func(&a, a);
return 0;
}
and compile it with -g
# gcc -g -o test test.c
Systemtap can see the variable of func(): p and val
# stap -L 'process("./test").function("func")'
process("/home/ryan/Public/test").function("func#/home/ryan/Public/test.c:3") $p:int* $val:int
So I use this stp to watch the variables:
# stap -e 'probe process("./test").function("func") {printf("%s(%p, %d)\n", probefunc(), $p, $val)}'
But the local variables are not right in the result when test program executed, it shows:
func(0x0, 0)
I am using fedora19 with:
kernel-3.11.9-200.fc19.x86_64
systemtap-sdt-devel-2.3-1.fc19.x86_64
systemtap-2.3-1.fc19.x86_64
systemtap-client-2.3-1.fc19.x86_64
systemtap-devel-2.3-1.fc19.x86_64
systemtap-runtime-2.3-1.fc19.x86_64
gcc-4.8.2-7.fc19.x86_64
Could someone meet this problem or give me a solution?
.function probes are defined to fire at entry to the function. If you're looking for values of local variables, you need to use .statement probes, identifying the source-file:line-number. In this case though, you're looking for parameters to a function (which happened to be based on another function's locals). In this case, the .function probe is appropriate.
You appear to be hitting a GCC bug. In plain -g mode (ironically), dwarf debuginfo is sometimes inaccurate for incoming function parameters. Try "gcc -g -O" or "gcc -g -O2" instead. Systemtap prologue-searching (stap -P) might help. See also http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51358, https://sourceware.org/bugzilla/show_bug.cgi?id=13420
In case the "stap -P" doesn't help, you may need to resort to statement-level probing after all:
probe process("./test").statement("func#test.c:5") { println($$parms) }
(line :5 refers to the printf)
I saw this nifty one liner for gdb to dump out backtrace for all threads after a core dump. So I tried a quick:
int main() {int* x = new int[5]; for(int i = 0; true; ++i) x[i] = i; }
to get a core dump and then ran this:
gdb --batch --quiet -ex "thread apply all bt full" -ex "quit" a.out core.box-name.a.out.27459.8515.11
And I get the output:
[New LWP 27459]
warning: Can't read pathname for load map: Input/output error.
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7fff9e503000
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x00000000004005ca in main () at <stdin>:6
6 <stdin>: No such file or directory.
Thread 1 (LWP 27459):
#0 0x00000000004005ca in main () at <stdin>:6
i = 33788
x = 0x1a460010
I see a backtrace which is nice, but am wondering what the two warnings I also see are about?
Seems from this link, it was a bug in gdb and has been fixed in the recent releases.
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=248898
I'm trying to understand deeper linking process and linker scripts...looking at binutils doc i found a simple linker script implementation that i've improved by adding some commands:
OUTPUT_FORMAT("elf32-i386", "elf32-i386",
"elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(mymain)
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
My program is a very simple program:
void mymain(void)
{
int a;
a++;
}
Now i tried to build an executable:
gcc -c main.c
ld -o prog -T my_script.lds main.o
But if i try to run prog it receives a SIGKILL during startup. I know that when a program is compiled and linked with the command:
gcc prog.c -o prog
the final executable is the product also of other object files like crt1.o, crti.o and crtn.o but what about my case? Which is the correct way to use this linker scripts?
I suspect that your code is running just fine, and getting into trouble at the end: what do you expect to happen after the a++?
mymain() is just an ordinary C function, which will try to return to its caller.
But you've set it as the ELF entry point, which tells the ELF loader to jump to it once it has loaded the program segments in the right place - and it doesn't expect you to return.
Those "other object files like crt1.o, crti.o and crtn.o" normally handle this stuff for C programs. The ELF entry point for a C program isn't main() - instead, it's a wrapper which sets up an appropriate environment for main() (e.g. setting up the argc and argv arguments on the stack or in registers, depending on platform), calls main() (with the expectation that it may return), and then invokes the exit system call (with the return code from main()).
[Update following comments:]
When I try your example with gdb, I see that it does indeed fail on returning from mymain(): after setting a breakpoint on mymain, and then stepping through instructions, I see that it performs the increment, then gets into trouble in the function epilogue:
$ gcc -g -c main.c
$ ld -o prog -T my_script.lds main.o
$ gdb ./prog
...
(gdb) b mymain
Breakpoint 1 at 0x10006: file main.c, line 4.
(gdb) r
Starting program: /tmp/prog
Breakpoint 1, mymain () at main.c:4
4 a++;
(gdb) display/i $pc
1: x/i $pc
0x10006 <mymain+6>: addl $0x1,-0x4(%ebp)
(gdb) si
5 }
1: x/i $pc
0x1000a <mymain+10>: leave
(gdb) si
Cannot access memory at address 0x4
(gdb) si
0x00000001 in ?? ()
1: x/i $pc
Disabling display 1 to avoid infinite recursion.
0x1: Cannot access memory at address 0x1
(gdb) q
For i386 at least, the ELF loader sets up a sensible stack before entering the loaded code, so you can set the ELF entry point to a C function and get reasonable behaviour; however, as I mentioned above, you have to handle a clean process exit yourself. And if you're not using the C runtime, you'd better not be using any libraries that depend on the C runtime either.
So here is an example of that, using your original linker script - but with the C code modified to initialise a to a known value, and invoke an exit system call (using inline assembly) with the final value of a as the exit code. (Note: I've just realised that you haven't said exactly what platform you're using; I'm assuming Linux here.)
$ cat main2.c
void mymain(void)
{
int a = 42;
a++;
asm volatile("mov $1,%%eax; mov %0,%%ebx; int $0x80" : : "r"(a) : "%eax" );
}
$ gcc -c main2.c
$ ld -o prog2 -T my_script.lds main2.o
$ ./prog2 ; echo $?
43
$
yes to run on linux, we need to change .lds file
SECTIONS
{
. = 0x8048000;
.text : { *(.text)
}