This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] make GDB can handle the binary that psymbol table has something wrong


Hi,

Our customer met a issue is:
cat main.c
int main()
{
  func();
  while(1);
}

cat fun.c
#include <stdio.h>
extern int a;

void
func(void)
{
  a = 3;
  test_point();
  printf("&a=0x%p, a=%d\n", &a, a);
}

cat test.c
int a;

void
test_point(void)
{
  a = 10;
}

cat Makefile
CC = gcc
all: libtest.so
	$(CC) main.c fun.c -I. -L. -Wl,-rpath,. -ltest -g -o test
libtest.so:
	$(CC) -shared -fPIC -g -I. -L.  test.c -o libtest.so
clean:
	rm -rf libtest.so test

makefile

gdb test
(gdb) start
Temporary breakpoint 1 at 0x400678: file main.c, line 3.
Starting program: /home/teawater/gdb/gdb_test_sun/test

Temporary breakpoint 1, main () at main.c:3
3	  func();
(gdb) display a
1: a = 0
(gdb) n
&a=0x0x601028, a=10
4	  while(1);
1: a = 0
(gdb) p a
$1 = 10

gdb test
(gdb) r
Starting program: /home/teawater/gdb/gdb_test_sun/test
&a=0x0x601028, a=10
^C
Program received signal SIGINT, Interrupt.
main () at main.c:4
4	  while(1);
(gdb) p a
$1 = 0
(gdb) p &a
$2 = (int *) 0x7ffff7dd9020 <a>

gdb test
(gdb) start
Temporary breakpoint 1 at 0x400678: file main.c, line 3.
Starting program: /home/teawater/gdb/gdb_test_sun/test

Temporary breakpoint 1, main () at main.c:3
3	  func();
(gdb) s
func () at fun.c:7
7	  a = 3;
(gdb) p a
$1 = 0
(gdb) n
8	  test_point();
(gdb)
9	  printf("&a=0x%p, a=%d\n", &a, a);
(gdb) p a
$2 = 10


This issue is because both test(fun.c) and libtest.so has psymbol "a".  But just psymbol "a" in libtest.so is in psymbol table.
You can get it from GDB commands:
gdb test
(gdb) start
Temporary breakpoint 1 at 0x400678: file main.c, line 3.
Starting program: /home/teawater/gdb/gdb_test_sun/test

Temporary breakpoint 1, main () at main.c:3
3	  func();
(gdb) maintenance print psymbols 1
(gdb) !cat 1

Partial symtab for source file fun.c (object 0x2949e40)

  Read from object file /home/teawater/gdb/gdb_test_sun/test (0x2931670)
  Relocate symbols by 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
  Symbols cover text addresses 0x400684-0x4006bb
  Address map supported - yes.
  Depends on 0 other partial symtabs.
  Global partial symbols:
    `func', function, 0x400684
  Static partial symbols:
    `long unsigned int', type, 0x0
    `unsigned char', type, 0x0
    `short unsigned int', type, 0x0
    `unsigned int', type, 0x0
    `signed char', type, 0x0
    `short int', type, 0x0
    `int', type, 0x0
    `long int', type, 0x0
    `char', type, 0x0


Partial symtab for source file main.c (object 0x2944d80)

  Read from object file /home/teawater/gdb/gdb_test_sun/test (0x2931670)
  Full symtab was read (at 0x2950b10 by function at 0x62dc50)
  Relocate symbols by 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
  Symbols cover text addresses 0x400674-0x400684
  Address map supported - yes.
  Depends on 0 other partial symtabs.
  Global partial symbols:
    `main', function, 0x400674
  Static partial symbols:
    `int', type, 0x0


Partial symtab for source file test.c (object 0x29a2920)

  Read from object file ./libtest.so (0x29998f0)
  Relocate symbols by 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x7ffff7bd8000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
  Symbols cover text addresses 0x7ffff7bd859c-0x7ffff7bd85af
  Address map supported - yes.
  Depends on 0 other partial symtabs.
  Global partial symbols:
    `a', static, 0x7ffff7dd9020
    `test_point', function, 0x7ffff7bd859c
  Static partial symbols:
    `int', type, 0x0

So when GDB access "a" before it access any symbol of fun.c, when function lookup_symbol_aux_psymtabs check symtab of fun.c with function lookup_partial_symbol, it will not return true.
So the symbol inside fun.c will not be load to GDB.
Then symol "a" (0x7ffff7dd9020) inside libtest.so will be load to GDB. Then GDB will not output the right value of "a".

But if GDB access any symbol of fun.c, all of symbols of it will load to GDB, then GDB can get the right value of "a".  This is why step inside to function fun will make GDB can output right value of "a".



And about symbol "a" inside libtest.so,  "0x7ffff7dd9020" is not a address to a var.  It is a pointer to .got. You can get it with asm code of test.c:
gcc -shared -fPIC -g -I. -L.  test.c -S
cat test.s
...
...
	.loc 1 6 0
	movq	a@GOTPCREL(%rip), %rax
	movl	$10, (%rax)
The disassemble of this part is:
(gdb) disassemble
Dump of assembler code for function test_point:
   0x00007ffff7bd859c <+0>:	push   %rbp
   0x00007ffff7bd859d <+1>:	mov    %rsp,%rbp
=> 0x00007ffff7bd85a0 <+4>:	mov    0x200a29(%rip),%rax        # 0x7ffff7dd8fd0
   0x00007ffff7bd85a7 <+11>:	movl   $0xa,(%rax)
   0x00007ffff7bd85ad <+17>:	pop    %rbp
   0x00007ffff7bd85ae <+18>:	retq
(gdb) x/10 0x7ffff7dd9020
0x7ffff7dd9020 <a>:	0x00000000	0x00000000	0x75312d33	0x746e7562
0x7ffff7dd9030:	0x20293575	0x2e362e34	0x002c0033	0x00020000
0x7ffff7dd9040:	0x00000000	0x00000008

So GDB cannot find any way to get right address of "a" with object file libtest.so.


This issue can be handle with add "-readnow", for example:
gdb -readnow test
(gdb) r
Starting program: /home/teawater/gdb/gdb_test_sun/test
&a=0x0x601028, a=10
^C
Program received signal SIGINT, Interrupt.
main () at main.c:4
4	  while(1);
(gdb) p a
$1 = 10
But it is not a good way to handle this issue, because:
1.  user doesn't know when is right time to use "-readnow".
2.  "-readnow" will make GDB load binary very slow when load big object file.  For example:
time gdb ~/kernel/b/vmlinux -ex "quit"
10 times:
0.713+0.711+0.712+0.710+0.711+0.719+0.716+0.708+0.710+0.718=7.128sec
time gdb -readnow ~/kernel/b/vmlinux -ex "quit"
6.614+6.387+6.407+6.384+6.464+6.397+6.361+6.449+6.430+6.389=64.282sec


I find a way to handle this issue is:
Looks the psymbol table has something wrong, but object file test has mini-symbol "a". So I make a patch that add a check to function lookup_symbol_aux_psymtabs.
If a object file cannot find a name, use lookup_minimal_symbol check if this object file has minimal_symbol of this name.
If so, relook up this name and doesn't call lookup_partial_symbol check if this name inside the psymtab.

I test this patch in x86_64 and mips.  It also pass the regression test.

I posted this patch and patch for the test.  Please help me review them.

Thanks,
Hui

2013-11-22  Hui Zhu  <hui@codesourcery.com>

	* psymtab.c (lookup_symbol_aux_psymtabs): Recheck if
	lookup_minimal_symbol return true.

2013-11-22  Hui Zhu  <hui@codesourcery.com>

	* gdb.base/solib-minisymbol-fun.c: New file
	* gdb.base/solib-minisymbol-lib.c: New file.
	* gdb.base/solib-minisymbol-main.c: New file.
	* gdb.base/solib-minisymbol.exp: New file.

Attachment: add_minisymbol_check.txt
Description: Text document

Attachment: add_minisymbol_check_test.txt
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]