I am trying to debug a core file that was generated on a test system. It was generated due to an assert() that was tripped.
The bt shows multiple frames with ?? followed by the actual functions. Not sure why that is so.
(gdb) bt
#0 0x00007f6c2d1eb035 in ?? ()
#1 0x00007f6c2d1ee79b in ?? ()
#2 0x00007f64fc3b0240 in ?? ()
#3 0x00007f6c2fdeb092 in ?? ()
#4 0x00007f6c2d1bbc58 in ?? ()
#5 0x00007f6c3205d9c0 in ?? ()
#6 0x0000000002a06a00 in ?? ()
#7 0x00007f64fc3b0150 in ?? ()
#8 0x00007f64fc3b0170 in ?? ()
#9 0x00000000018fb2cb in operator,<AssertCollectorBase> (this=<optimized out>, t=...) at ./shared/Assert.h:116
#10 X (platformContext=<optimized out>, severity=<optimized out>, msg=0x7f64fc3b0740 "Enabling poll on wrong connection.") at ss/*.cpp:497
#11 0x00000000025c2fd7 in Y (severity=1 '\001', msg=...) at *.cc:1065
#12 0x00000000025d0875 in Z (this=0x7f6bcbbbe440) at *.cc:870
#13 0x00007f6c2ebe0e9a in ?? ()
#14 0x0000000000000000 in ?? ()
I went to the frame containing the assert and tried printing out some local
and member variables. Some of the variables keep saying 'Cannot access memory 0x< some-memory-addr >'
I tried to print an STL map - but the pointers returned are always invalid.
(gdb) pmap connmap_ int SmaConnection*
elem[0].left: $1 = 219
elem[0].right: $2 = (SmaConnection *) 0x9c63d4e000007f6b
elem[1].left: $3 = 463
elem[1].right: $4 = (SmaConnection *) 0x9c63bd4000007f6b
elem[2].left: $5 = 469
elem[2].right: $6 = (SmaConnection *) 0x9c63e82000007f6b
elem[3].left: $7 = 471
(gdb) p *$2
Cannot access memory at address 0x9c63d4e000007f6b
(gdb)
The pointer values in the map always seem to be reported incorrectly by gdb, even when nothing goes wrong with the program.
Is there something wrong with the way I store the pointers in the map?
Is there something wrong I am doing with examining the map?
Is there something else I can do to access the memory correctly?
I had a similar problem because my code was in Release mode.
For example, did you add the flag -DCMAKE_BUILD_TYPE=Debug when you run cmake?
Or gcc -g option flag? (http://www.rapidtables.com/code/linux/gcc/gcc-g.htm)
The bt shows multiple frames with ?? followed by the actual functions. Not sure why that is so.
Most likely because of system library mismatch between the test and development systems. See this answer on how to fix it.
The pointer values in the map always seem to be reported incorrectly by gdb
If you do have a mismatch (which I am 99.9% certain you do), then you can ignore the rest of the stack -- it's guaranteed to be bogus.
Related
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.
I've got CiviCRM 5.10.4 running on Drupal 7.65, and one particular function ("Subscriber Donor Report") is blowing up on an underlying SQL error. I turned on debugging, and following is what I see. Looks like a hard-core internals problem that I could never deal with on my own. Incidentally, this problem has persisted across several updates of Civi (since 5.4 maybe?) and also Drupal (at least since 7.60). Is there any hope? Could this possibly be caused by some weird data in the db? I wouldn't normally think so.
Database Error Code: The used SELECT statements have a different number of columns, 1222
Additional Details:
Array
(
[callback] => Array
(
[0] => CRM_Core_Error
[1] => handle
)
[code] => -1
[message] => DB Error: unknown error
[mode] => 16
[debug_info] => CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci
(SELECT * FROM civicrm_tmp_e_dflt_0441f87ccf495b6b8c955d3a4407fde6)
UNION ALL
(SELECT * FROM civireport_contribution_detail_temp2) [nativecode=1222 ** The used SELECT statements have a different number of columns]
[type] => DB_Error
[user_info] => CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci
(SELECT * FROM civicrm_tmp_e_dflt_0441f87ccf495b6b8c955d3a4407fde6)
UNION ALL
(SELECT * FROM civireport_contribution_detail_temp2) [nativecode=1222 ** The used SELECT statements have a different number of columns]
[to_string] => [db_error: message="DB Error: unknown error" code=-1 mode=callback callback=CRM_Core_Error::handle prefix="" info="CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci
(SELECT * FROM civicrm_tmp_e_dflt_0441f87ccf495b6b8c955d3a4407fde6)
UNION ALL
(SELECT * FROM civireport_contribution_detail_temp2) [nativecode=1222 ** The used SELECT statements have a different number of columns]"]
)
#0 <path>/sites/all/modules/civicrm/CRM/Core/Error.php(190): CRM_Core_Error::backtrace()
#1 <path>/sites/all/modules/civicrm/packages/PEAR.php(921): CRM_Core_Error::handle(Object(DB_Error))
#2 <path>/sites/all/modules/civicrm/packages/DB.php(985): PEAR_Error->__construct("DB Error: unknown error", -1, 16, (Array:2), "CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 DEFAULT CHARACTE...")
#3 <path>/sites/all/modules/civicrm/packages/PEAR.php(575): DB_Error->__construct(-1, 16, (Array:2), "CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 DEFAULT CHARACTE...")
#4 <path>/sites/all/modules/civicrm/packages/PEAR.php(223): PEAR->_raiseError(Object(DB_mysqli), NULL, -1, 16, (Array:2), "CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 DEFAULT CHARACTE...", "DB_Error", TRUE)
#5 <path>/sites/all/modules/civicrm/packages/DB/common.php(1907): PEAR->__call("raiseError", (Array:7))
#6 <path>/sites/all/modules/civicrm/packages/DB/mysqli.php(933): DB_common->raiseError(-1, NULL, NULL, "CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 DEFAULT CHARACTE...", "1222 ** The used SELECT statements have a different number of columns")
#7 <path>/sites/all/modules/civicrm/packages/DB/mysqli.php(403): DB_mysqli->mysqliRaiseError()
#8 <path>/sites/all/modules/civicrm/packages/DB/common.php(1216): DB_mysqli->simpleQuery("CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 DEFAULT CHARACTE...")
#9 <path>/sites/all/modules/civicrm/packages/DB/DataObject.php(2415): DB_common->query("CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 DEFAULT CHARACTE...")
#10 <path>/sites/all/modules/civicrm/packages/DB/DataObject.php(1607): DB_DataObject->_query("CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 DEFAULT CHARACTE...")
#11 <path>/sites/all/modules/civicrm/CRM/Core/DAO.php(438): DB_DataObject->query("CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 DEFAULT CHARACTE...")
#12 <path>/sites/all/modules/civicrm/CRM/Core/DAO.php(1413): CRM_Core_DAO->query("CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 DEFAULT CHARACTE...", TRUE)
#13 <path>/sites/all/modules/civicrm/CRM/Report/Form.php(3710): CRM_Core_DAO::executeQuery("CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 DEFAULT CHARACTE...", (Array:0))
#14 <path>/sites/all/modules/civicrm/CRM/Report/Form/Contribute/Detail.php(568): CRM_Report_Form->executeReportQuery("CREATE TEMPORARY TABLE civireport_contribution_detail_temp3 DEFAULT CHARACTE...")
#15 <path>/sites/all/modules/civicrm/CRM/Report/Form.php(2816): CRM_Report_Form_Contribute_Detail->beginPostProcessCommon()
#16 <path>/sites/all/modules/civicrm/CRM/Report/Form.php(3473): CRM_Report_Form->beginPostProcess()
#17 <path>/sites/all/modules/civicrm/CRM/Report/Form.php(886): CRM_Report_Form->postProcess()
#18 <path>/sites/all/modules/civicrm/CRM/Core/Form.php(585): CRM_Report_Form->preProcess()
#19 <path>/sites/all/modules/civicrm/CRM/Core/QuickForm/Action/Display.php(92): CRM_Core_Form->buildForm()
#20 <path>/sites/all/modules/civicrm/packages/HTML/QuickForm/Controller.php(203): CRM_Core_QuickForm_Action_Display->perform(Object(CRM_Report_Form_Contribute_Detail), "display")
#21 <path>/sites/all/modules/civicrm/packages/HTML/QuickForm/Page.php(103): HTML_QuickForm_Controller->handle(Object(CRM_Report_Form_Contribute_Detail), "display")
#22 <path>/sites/all/modules/civicrm/CRM/Core/Controller.php(351): HTML_QuickForm_Page->handle("display")
#23 <path>/sites/all/modules/civicrm/CRM/Utils/Wrapper.php(113): CRM_Core_Controller->run()
#24 <path>/sites/all/modules/civicrm/CRM/Report/Page/Instance.php(89): CRM_Utils_Wrapper->run("CRM_Report_Form_Contribute_Detail", NULL, (Array:0))
#25 <path>/sites/all/modules/civicrm/CRM/Core/Invoke.php(309): CRM_Report_Page_Instance->run((Array:4), NULL)
#26 <path>/sites/all/modules/civicrm/CRM/Core/Invoke.php(84): CRM_Core_Invoke::runItem((Array:14))
#27 <path>/sites/all/modules/civicrm/CRM/Core/Invoke.php(52): CRM_Core_Invoke::_invoke((Array:4))
#28 <path>/sites/all/modules/civicrm/drupal/civicrm.module(445): CRM_Core_Invoke::invoke((Array:4))
#29 <path>/includes/menu.inc(527): civicrm_invoke("report", "instance", "4")
#30 <path>/index.php(21): menu_execute_active_handler()
#31 {main}
I stumbled upon the auto-display functionality of gdb, which is pretty powerful and convenient. After calling
(gdb) display/i $pc
(gdb) display $rax
the watched values are displayed automatically after every step:
(gdb) si
0x0804805e in print_loop_start ()
2: $rax = 0
1: x/i $pc
=> 0x804805e <print_loop_start+6>: mov 0x4(%ebp,%eax,4),%ecx
But how can I "unwatch" the value in $rax, if it is no longer of interest?
Gdb help for display says:
"Use undisplay to cancel display requests previously made."
So if you do display a, then display b, and display c gdb will give numbers to this requests (which you can see by issuing replay with no arguments). Then you can use this numbers with undisplay.
Example:
(gdb) display a
1: a = 32767
(gdb) display b
2: b = 0
(gdb) display c
3: c = 0
(gdb) undisplay 2
(gdb) step
6 b = 2;
1: a = 1
3: c = 0
Details in gdb documentation.
Note that you can also temporarily hide a disp output using:
disable display dnums…
And re-enable with:
enable display dnums…
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.
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'.