Bug 14790 - Gdb-6.6 'break' displays wrong line number information for multi threaded processes
Summary: Gdb-6.6 'break' displays wrong line number information for multi threaded pro...
Status: RESOLVED INVALID
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: 6.6
: P2 critical
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL: sourceware.org/ml/gdb/2011-06/msg0012...
Keywords:
Depends on:
Blocks:
 
Reported: 2012-10-31 18:04 UTC by oz
Modified: 2012-10-31 18:21 UTC (History)
1 user (show)

See Also:
Host: x86-64, Ubuntu 10.04.4 LTS
Target: MIPS32, linux kernel 2.6.37
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description oz 2012-10-31 18:04:13 UTC
For a multi threaded application running on a MIPS32 platform, gdb-6.6 and gdb-7.5 do behave differently in terms of setting breakpoints. Basically, after a certain line number, 6.6 seems to be totally confused about what the line numbers are. It either rejects setting the breakpoint by saying 'No line X in file "gdb_test.cpp"' or places the breakpoint where it thinks the line number corresponds to but actually somewhere irrelevant. However, if I switch to gdb-7.5 on the same target and within the same environment, it does behave as expected. 

Obviously, issue is not reproducible on 7.5 but on our system we have to use 6.6  so cannot consider a 7.5 upgrade. Therefore, I'd be interested to see if this can either be fixed or even better can be worked around by a different compilation/linking option.

I hope below information is sufficient and if not, I'm happy to provide what's required. The test application is just demonstrative and please just ignore the poor thread-synchronisation/signalling which is irrelevant to the actual issue.

- The compilation line;
mips-linux-g++ -o gdb_test gdb_test.cpp -ggdb3 -O0 -lpthread

Also tried -g3, -gstabs3 and -gstabs+ options but didn't make any difference.

-Target component versions;
linux kernel 2.6.37
gcc 4.5.3
binutils 2.19.92
uClibc 0.9.32

-ELF header of the binary;
  Magic:   7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, big endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           MIPS R3000
  Version:                           0x1
  Entry point address:               0x4006f0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          63456 (bytes into file)
  Flags:                             0x50001007, noreorder, pic, cpic, o32, mips32
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         9
  Size of section headers:           40 (bytes)
  Number of section headers:         40
  Section header string table index: 37

- objdump disassembled line numbers are in line with the actual source file. 

-Experiment output with two different versions of gdb;

#######
# 7.5 #
#######
(gdb) show version
GNU gdb (GDB) 7.5
(gdb) list 1,60
1	#include <stdio.h>
2	#include <stdlib.h>
3	#include <unistd.h>
4	#include <pthread.h>
5	
6	void* t1_func(void *ptr );
7	void* t2_func(void *ptr );
8	
9	pthread_cond_t      cond1  = PTHREAD_COND_INITIALIZER;
10	pthread_cond_t      cond2  = PTHREAD_COND_INITIALIZER;
11	pthread_mutex_t     mutex1 = PTHREAD_MUTEX_INITIALIZER;
12	pthread_mutex_t     mutex2 = PTHREAD_MUTEX_INITIALIZER;
13	
14	int main( int argc, char **argv ) {
15		int rc;
16		pthread_t thread1, thread2;
17	
18		rc = pthread_create (&thread1, NULL, &t1_func, 0);
19		rc = pthread_create (&thread2, NULL, &t2_func, 0);
20	
21		sleep(5);
22	
23		for(;;){
24			printf("\n0");
25			rc = pthread_cond_signal(&cond1);
26			sleep(2);
27		}
28	
29		rc = pthread_join(thread1, NULL);
30		rc = pthread_join(thread2, NULL);
31	
32		return 0;
33	}
34	
35	void* t1_func(void *ptr) {
36		int rc;
37	
38		for(;;){
39			rc = pthread_mutex_lock(&mutex1);
40			rc = pthread_cond_wait(&cond1, &mutex1);
41			printf("\n1");
42			rc = pthread_mutex_unlock(&mutex1);
43		}
44	
45		pthread_exit(0);
46	}
47	
48	void* t2_func(void *ptr) {
49		int rc;
50	
51		for(;;){
52			rc = pthread_mutex_lock(&mutex2);
53			rc = pthread_cond_wait(&cond2, &mutex2);
54			printf("\n2");
55			rc = pthread_mutex_unlock(&mutex2);
56		}
57	
58		pthread_exit(0);
59	}
60	
(gdb) b gdb_test.cpp:26
Breakpoint 1 at 0x400948: file gdb_test.cpp, line 26.
(gdb) b gdb_test.cpp:41
Breakpoint 2 at 0x4009d0: file gdb_test.cpp, line 41.
(gdb) b gdb_test.cpp:54
Breakpoint 3 at 0x400a7c: file gdb_test.cpp, line 54.
(gdb) r
Starting program: /var/viewer/gdb_test 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/libthread_db.so.1".

0[New Thread 0x77e014f0 (LWP 15941)]
[Switching to Thread 0x77e014f0 (LWP 15941)]

Breakpoint 2, t1_func (ptr=0x0) at gdb_test.cpp:41
41			printf("\n1");
(gdb) thread apply all bt
[New Thread 0x77c014f0 (LWP 15942)]

Thread 3 (Thread 0x77c014f0 (LWP 15942)):
#0  0x77fc2608 in pthread_cond_wait () from /lib/libpthread.so.0
#1  0x00400a74 in t2_func (ptr=0x0) at gdb_test.cpp:53
#2  0x77fc60b8 in start_thread () from /lib/libpthread.so.0
#3  0x77fbf080 in __thread_start () from /lib/libpthread.so.0
Backtrace stopped: frame did not save the PC

Thread 2 (Thread 0x77e014f0 (LWP 15941)):
#0  t1_func (ptr=0x0) at gdb_test.cpp:41
#1  0x77fc60b8 in start_thread () from /lib/libpthread.so.0
#2  0x77fbf080 in __thread_start () from /lib/libpthread.so.0
Backtrace stopped: frame did not save the PC

Thread 1 (Thread 0x77ff4000 (LWP 15937)):
#0  main (argc=1, argv=0x7fff6bb4) at gdb_test.cpp:26
(gdb) c
Continuing.

1[Switching to Thread 0x77ff4000 (LWP 15937)]

Breakpoint 1, main (argc=1, argv=0x7fff6bb4) at gdb_test.cpp:26
26			sleep(2);
(gdb) thread apply all bt

Thread 3 (Thread 0x77c014f0 (LWP 15942)):
#0  0x77fc2608 in pthread_cond_wait () from /lib/libpthread.so.0
#1  0x00400a74 in t2_func (ptr=0x0) at gdb_test.cpp:53
#2  0x77fc60b8 in start_thread () from /lib/libpthread.so.0
#3  0x77fbf080 in __thread_start () from /lib/libpthread.so.0
Backtrace stopped: frame did not save the PC

Thread 2 (Thread 0x77e014f0 (LWP 15941)):
#0  0x77fc2608 in pthread_cond_wait () from /lib/libpthread.so.0
#1  0x004009c8 in t1_func (ptr=0x0) at gdb_test.cpp:40
#2  0x77fc60b8 in start_thread () from /lib/libpthread.so.0
#3  0x77fbf080 in __thread_start () from /lib/libpthread.so.0
Backtrace stopped: frame did not save the PC

Thread 1 (Thread 0x77ff4000 (LWP 15937)):
#0  main (argc=1, argv=0x7fff6bb4) at gdb_test.cpp:26
(gdb)

#######
# 6.6 #
#######
(gdb) show version
GNU gdb 6.6.0.20070423-cvs
(gdb) list 1,60
<ManulAddition: Still displays correct source code>
(gdb) b gdb_test.cpp:26
No line 26 in file "gdb_test.cpp".
(gdb) b gdb_test.cpp:41
No line 41 in file "gdb_test.cpp".
(gdb) b gdb_test.cpp:54
No line 54 in file "gdb_test.cpp".
(gdb) r
Starting program: /var/viewer/gdb_test 
[Thread debugging using libthread_db enabled]
[New Thread 2003148800 (LWP 16065)]

<ManulAddition: Runs happily and expected prints do come up periodically>
0
1
0
1

Source code;

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

void* t1_func(void *ptr );
void* t2_func(void *ptr );

pthread_cond_t      cond1  = PTHREAD_COND_INITIALIZER;
pthread_cond_t      cond2  = PTHREAD_COND_INITIALIZER;
pthread_mutex_t     mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t     mutex2 = PTHREAD_MUTEX_INITIALIZER;

int main( int argc, char **argv ) {
	int rc;
	pthread_t thread1, thread2;

	rc = pthread_create (&thread1, NULL, &t1_func, 0);
	rc = pthread_create (&thread2, NULL, &t2_func, 0);

	sleep(5);

	for(;;){
		printf("\n0");
		rc = pthread_cond_signal(&cond1);
		sleep(2);
	}

	rc = pthread_join(thread1, NULL);
	rc = pthread_join(thread2, NULL);

	return 0;
}

void* t1_func(void *ptr) {
	int rc;

	for(;;){
		rc = pthread_mutex_lock(&mutex1);
		rc = pthread_cond_wait(&cond1, &mutex1);
		printf("\n1");
		rc = pthread_mutex_unlock(&mutex1);
	}

	pthread_exit(0);
}

void* t2_func(void *ptr) {
	int rc;

	for(;;){
		rc = pthread_mutex_lock(&mutex2);
		rc = pthread_cond_wait(&cond2, &mutex2);
		printf("\n2");
		rc = pthread_mutex_unlock(&mutex2);
	}

	pthread_exit(0);
}
Comment 1 Pedro Alves 2012-10-31 18:21:15 UTC
Sorry, but 6.6 is too ancient to support.  Instead, please send an email to the list, and maybe someone will be able to help you from there.