Bug 241773 - lldb does not display external variables properly.
Summary: lldb does not display external variables properly.
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 12.1-RELEASE
Hardware: Any Any
: --- Affects Many People
Assignee: freebsd-bugs mailing list
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-11-07 05:56 UTC by bc979
Modified: 2019-11-08 12:05 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description bc979 2019-11-07 05:56:05 UTC
Here is an issue that has plagued me for some time:

Using FreeBSD 12.0:


testlib.c:
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>

char id[4];
int sock;

void testfunc() {
 struct stat sb;
 stat("testlib.c", &sb);
 strcpy (id, "aa");
 sock = 5;
 printf("Size of testlib.c is %i bytes.\n", (int)sb.st_size);
}


testprog.c:
#include <stdio.h>

extern char id[4];
extern int sock;

void testfunc(void);
int main(int argc, char **argv) {
 testfunc();
 printf ("id = %s\n", id);
 printf ("sock = %d\n", sock);
 return 0;
}


Makefile:
all:    clean testprog run

testprog:
       cc -Wall -g -c -fPIC -o testlib.o testlib.c
       cc  -shared -Wl,-export-dynamic -o testlib.so testlib.o
       cc -Wall -g -o testprog ./testlib.so testprog.c

clean:
       rm -f testlib.o testlib.so testprog

run:
       ./testprog


Using make:
rm -f testlib.o testlib.so testprog
cc -Wall -g -c -fPIC -o testlib.o testlib.c
cc  -shared -Wl,-export-dynamic -o testlib.so testlib.o
cc -Wall -g -o testprog ./testlib.so testprog.c
./testprog
Size of testlib.c is 268 bytes.
id = aa
sock = 5


Running lldb:
master# lldb testprog
(lldb) target create "testprog"
Current executable set to 'testprog' (x86_64).
(lldb) b main
Breakpoint 1: where = testprog`main + 22 at testprog.c:8, address = 0x0000000000201366
(lldb) r
Process 34787 launching
Process 34787 launched: '/home/doug/zzz/testprog' (x86_64)
Process 34787 stopped
* thread #1, name = 'testprog', stop reason = breakpoint 1.1
   frame #0: 0x0000000000201366 testprog`main(argc=1, argv=0x00007fffffffeb38) at testprog.c:8
  5   	
  6   	void testfunc(void);
  7   	int main(int argc, char **argv) {
-> 8   	  testfunc();
  9   	  printf ("id = %s\n", id);
  10  	  printf ("sock = %d\n", sock);
  11  	  return 0;
(lldb) n
Size of testlib.c is 268 bytes.
Process 34787 stopped
* thread #1, name = 'testprog', stop reason = step over
   frame #0: 0x000000000020137f testprog`main(argc=1, argv=0x00007fffffffeb38) at testprog.c:9
  6   	void testfunc(void);
  7   	int main(int argc, char **argv) {
  8   	  testfunc();
-> 9   	  printf ("id = %s\n", id);
  10  	  printf ("sock = %d\n", sock);
  11  	  return 0;
  12  	}
(lldb) p id
error: use of undeclared identifier 'id'
(lldb) p sock
error: Couldn't materialize: couldn't get the value of variable sock: testlib.so[0x4004] can't be resolved, testlib.so is not currently loaded
error: errored out in DoExecute, couldn't PrepareToExecuteJITExpression
(lldb) c
id = aa
sock = 5
Process 34787 resuming


You notice that lldb cannot display values for id or sock.  It even gives quite different messages about them.  However the program can access the values and it prints them out properly.  Why can't lldb see them?  How can that be corrected?

What is even more interesting is that in the real application there are quite a few of these global variables and lldb can display some of them, just not all.  Possibly it has to do with the specific names as DATE generally works.  sock and id never seem to work.

Now using FreeBSD 12.1:

We now have 12.1 with an updated compiler and linker.  Things have changed.  I added a bit to testprog.c:

master# more testprog.c
#include <stdio.h>

extern char id[4];
extern int sock;
int unknown;

void testfunc(void);
int main(int argc, char **argv) {
 testfunc();
 unknown = 9;
 printf ("id (%x) = %s\n", (int)&id, id);
 printf ("sock(%x)  = %d\n", (int)&sock, sock);
 printf ("unknown (%x) = %d\n", (int)&unknown, unknown);
 return 0;
}


running it yields:
master# ./testprog
Size of testlib.c is 268 bytes.
id (20400c) = aa
sock(204010)  = 5
unknown (204008) = 9

That appears to be correct.  Everything worked.  However, with lldb, instead of error messages I get wrong values:

master# lldb testprog
(lldb) target create "testprog"
Current executable set to 'testprog' (x86_64).
(lldb) b main
Breakpoint 1: where = testprog`main + 22 at testprog.c:9:3, address = 0x00000000002012f6
(lldb) r
Process 6039 launching
Process 6039 launched: '/home/doug/zzz/testprog' (x86_64)
Process 6039 stopped
* thread #1, name = 'testprog', stop reason = breakpoint 1.1
   frame #0: 0x00000000002012f6 testprog`main(argc=1, argv=0x00007fffffffeb38) at testprog.c:9:3
  6   	
  7   	void testfunc(void);
  8   	int main(int argc, char **argv) {
-> 9   	  testfunc();
  10  	  unknown = 9;
  11  	  printf ("id (%x) = %s\n", (int)&id, id);
  12  	  printf ("sock(%x)  = %d\n", (int)&sock, sock);
(lldb) n
Size of testlib.c is 268 bytes.
Process 6039 stopped
* thread #1, name = 'testprog', stop reason = step over
   frame #0: 0x0000000000201307 testprog`main(argc=1, argv=0x00007fffffffeb38) at testprog.c:10:11
  7   	void testfunc(void);
  8   	int main(int argc, char **argv) {
  9   	  testfunc();
-> 10  	  unknown = 9;
  11  	  printf ("id (%x) = %s\n", (int)&id, id);
  12  	  printf ("sock(%x)  = %d\n", (int)&sock, sock);
  13  	  printf ("unknown (%x) = %d\n", (int)&unknown, unknown);
(lldb) 
Process 6039 stopped
* thread #1, name = 'testprog', stop reason = step over
   frame #0: 0x0000000000201312 testprog`main(argc=1, argv=0x00007fffffffeb38) at testprog.c:11:3
  8   	int main(int argc, char **argv) {
  9   	  testfunc();
  10  	  unknown = 9;
-> 11  	  printf ("id (%x) = %s\n", (int)&id, id);
  12  	  printf ("sock(%x)  = %d\n", (int)&sock, sock);
  13  	  printf ("unknown (%x) = %d\n", (int)&unknown, unknown);
  14  	  return 0;
(lldb) p id
(char [4]) $0 = ""
(lldb) p &id
(char (*)[4]) $1 = 0x000000080024d000
(lldb) p unknown
(int) $2 = 9
(lldb) p &unknown
(int *) $3 = 0x0000000000204008
(lldb) 

For the variable unknown lldb displays the correct address and value.  For id and sock, it displays the wrong address and the value at the wrong address.  The correct values are in the proper addresses:

x 0x204008
0x00204008: 09 00 00 00 61 61 00 00 05 00 00 00 00 00 00 00  ....aa..........
Comment 1 Andriy Gapon freebsd_committer 2019-11-07 06:44:39 UTC
What happens if you examine such a variable after a program accesses it at least once?
It could be that the shared library is loaded lazily, so those symbols are not actually resolved until they are accessed.
Comment 2 bc979 2019-11-07 06:53:27 UTC
I modified testlib to be:

master# vi testlib.c

#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>

char id[4];
int sock;

void testfunc() {
  struct stat sb;
  stat("testlib.c", &sb);
  strcpy (id, "aa");
  sock = 5;
  printf ("sock = %d, id = %s\n", sock, id);
  printf("Size of testlib.c is %i bytes.\n", (int)sb.st_size);
}


The results are exatly the same other than there is the extra line of output.

(lldb) p id
(char [4]) $0 = ""
(lldb) p sock
(int) $1 = 0
(lldb) p &id
(char (*)[4]) $2 = 0x000000080024d000
Comment 3 Andriy Gapon freebsd_committer 2019-11-08 08:30:39 UTC
I meant that the program (executable) accesses a variable, not an intra-library access.
Comment 4 bc979 2019-11-08 09:33:47 UTC
Apparently I misunderstood.  Here is a lldb session with changes to testprog:

   8   	int main(int argc, char **argv) {
   9   	  strcpy (id, "yy");
   10  	  sock = 88;
-> 11  	  testfunc();
   12  	  unknown = 9;
   13  	  printf ("id (%x) = %s\n", (int)&id, id);
   14  	  printf ("sock(%x)  = %d\n", (int)&sock, sock);
(lldb) p id
(char [4]) $0 = ""
(lldb) p sock
(int) $1 = 0
(lldb) p &sock
(int *) $2 = 0x000000080024d004
(lldb) p & id
(char (*)[4]) $3 = 0x000000080024d000
(lldb) p *id
(char) $4 = '\0'

Even after setting the variables, lldb doesn't find the right values although it seems to get the right addresses.  After testfunc is called, nothing has changed from before.
Comment 5 Andriy Gapon freebsd_committer 2019-11-08 12:05:28 UTC
Thank you for the test.
So, the problem is not what I thought it might be.
That's a very strange problem.