lldb 11.0.0-rc2 different behavior then gdb.

Hello all,

While debugging and printing struct with multi-dimensional char array, gdb successfully prints string while lldb bails out with only printing address.

For simple C testcase,

struct b {

char i[2][4];

};

int main() {

struct b z;

z.i[0][0] = ‘F’;

z.i[0][1] = ‘O’;

z.i[0][2] = ‘O’;

z.i[0][3] = 0;

z.i[1][0] = ‘B’;

z.i[1][1] = ‘A’;

z.i[1][2] = ‘R’;

z.i[1][3] = 0;

return 0;

}

On gdb,

Reading symbols from /home/chirag/a.out…done.

(gdb) l

1 struct b {

2 char i[2][4];

3 };

4

5 int main() {

6 struct b z;

7 z.i[0][0] = ‘F’;

8 z.i[0][1] = ‘O’;

9 z.i[0][2] = ‘O’;

10 z.i[0][3] = 0;

(gdb) l

11 z.i[1][0] = ‘B’;

12 z.i[1][1] = ‘A’;

13 z.i[1][2] = ‘R’;

14 z.i[1][3] = 0;

15 return 0;

16 }

(gdb) b 15

Breakpoint 1 at 0x400511: file Desktop/test/struct.c, line 15.

(gdb) r

Starting program: /home/chirag/./a.out

Breakpoint 1, main () at Desktop/test/struct.c:15

15 return 0;

Missing separate debuginfos, use: debuginfo-install glibc-2.17-307.el7.1.x86_64

(gdb) p z

$1 = {i = {“FOO”, “BAR”}}

(gdb) q

A debugging session is active.

While on lldb 11.0.0-rc2, (lldb) target create “/home/chirag/a.out”

Current executable set to ‘/home/chirag/a.out’ (x86_64).

(lldb) b 15

Breakpoint 1: where = a.out`main + 36 at struct.c:15, address = 0x0000000000400511

(lldb) r

Process 57100 launched: ‘/home/chirag/a.out’ (x86_64)

Process 57100 stopped

  • thread #1, name = ‘a.out’, stop reason = breakpoint 1.1

frame #0: 0x0000000000400511 a.out`main at struct.c:15

12 z.i[1][1] = ‘A’;

13 z.i[1][2] = ‘R’;

14 z.i[1][3] = 0;

→ 15 return 0;

16 }

(lldb) p z

(b) $0 = (i = char [2][4] @ 0x0000000001fe3ca0)

(lldb) q

It seems like the type summary formatter is failing? Or is it the intended behaviour?.

Thanks and Regards,

Chirag Patel.

There isn’t a built-in summary formatter for two dimensional arrays of chars, but the type is matching the regex for the one-dimensional StringSummaryFormat, but that doesn’t actually know how to format two dimensional arrays of chars. The type regex for StringSummaryFormat:

char [[0-9]+]

We should refine this regex so it doesn’t catch up two dimensional strings. We could also write a formatter for two-dimensional strings.

Would you file bugs about those two issues with http://bugs.llvm.org? <http://bugs.llvm.org/?> Thanks.

Note that user added formatters are scanned first and the match is granted to the first hit, so if you need this yourself, in the meantime you could write your own formatter and it should fire.

Jim

Do we need a special formatter for two-dimensional strings? What about 3D?

I'd hope that this could be handled by a combination of the simple string formatter and the generic array dumping code...

pl

There isn’t a built-in summary formatter for two dimensional arrays of chars, but the type is matching the regex for the one-dimensional StringSummaryFormat, but that doesn’t actually know how to format two dimensional arrays of chars. The type regex for StringSummaryFormat:
char [[0-9]+]
We should refine this regex so it doesn’t catch up two dimensional strings. We could also write a formatter for two-dimensional strings.

Do we need a special formatter for two-dimensional strings? What about 3D?

I’d hope that this could be handled by a combination of the simple string formatter and the generic array dumping code…

That works as expected, for instance if you do:

(lldb) frame var z.i
(char [2][4]) z.i = {
[0] = “FOO”
[1] = “BAR”
}

The thing that isn’t working is when the array doesn’t get auto-expanded by lldb, then you see the summary instead, which is what you are seeing with:

(lldb) frame var z
(b) z = (i = char [2][4] @ 0x00007ffeefbff5f0)

You can fix this either by having a summary string for char [][] or by telling lldb to expand more pointer like children for you:

(lldb) frame var -P2 z
(b) z = {
i = {
[0] = “FOO”
[1] = “BAR”
}
}

I’m hesitant to up the default pointer depth, I have gotten lots of complaints already about lldb disclosing too many subfields when printing structures.

We could also try to be smarter about what constitutes a “pointer” so the arrays don’t count against the pointer depth? Not sure how workable that would be.

Jim

There isn’t a built-in summary formatter for two dimensional arrays of chars, but the type is matching the regex for the one-dimensional StringSummaryFormat, but that doesn’t actually know how to format two dimensional arrays of chars. The type regex for StringSummaryFormat:
char [[0-9]+]
We should refine this regex so it doesn’t catch up two dimensional strings. We could also write a formatter for two-dimensional strings.

Do we need a special formatter for two-dimensional strings? What about 3D?

I'd hope that this could be handled by a combination of the simple string formatter and the generic array dumping code...

That works as expected, for instance if you do:

(lldb) frame var z.i
(char [2][4]) z.i = {
[0] = "FOO"
[1] = "BAR"
}

The thing that isn’t working is when the array doesn’t get auto-expanded by lldb, then you see the summary instead,

Ah, interesting. I didn't realize that.

which is what you are seeing with:

(lldb) frame var z
(b) z = (i = char [2][4] @ 0x00007ffeefbff5f0)

You can fix this either by having a summary string for char [][] or by telling lldb to expand more pointer like children for you:

(lldb) frame var -P2 z
(b) z = {
i = {
[0] = "FOO"
[1] = "BAR"
}
}

I’m hesitant to up the default pointer depth, I have gotten lots of complaints already about lldb disclosing too many subfields when printing structures.

Yeah, I don't think we'd want to increase that.

We could also try to be smarter about what constitutes a “pointer” so the arrays don’t count against the pointer depth? Not sure how workable that would be.

This sounds workable. I mean, an array struct member is not really a pointer (it only decays to a pointer) and does not suffer from the issues that pointers do -- infinite recursion with recursive data structures, etc.

pl

There isn’t a built-in summary formatter for two dimensional arrays of chars, but the type is matching the regex for the one-dimensional StringSummaryFormat, but that doesn’t actually know how to format two dimensional arrays of chars. The type regex for StringSummaryFormat:
char [[0-9]+]
We should refine this regex so it doesn’t catch up two dimensional strings. We could also write a formatter for two-dimensional strings.

Do we need a special formatter for two-dimensional strings? What about 3D?

I'd hope that this could be handled by a combination of the simple string formatter and the generic array dumping code...

That works as expected, for instance if you do:
(lldb) frame var z.i
(char [2][4]) z.i = {
  [0] = "FOO"
  [1] = "BAR"
}
The thing that isn’t working is when the array doesn’t get auto-expanded by lldb, then you see the summary instead,

Ah, interesting. I didn't realize that.

which is what you are seeing with:
(lldb) frame var z
(b) z = (i = char [2][4] @ 0x00007ffeefbff5f0)
You can fix this either by having a summary string for char [][] or by telling lldb to expand more pointer like children for you:
(lldb) frame var -P2 z
(b) z = {
  i = {
    [0] = "FOO"
    [1] = "BAR"
  }
}
I’m hesitant to up the default pointer depth, I have gotten lots of complaints already about lldb disclosing too many subfields when printing structures.

Yeah, I don't think we'd want to increase that.

We could also try to be smarter about what constitutes a “pointer” so the arrays don’t count against the pointer depth? Not sure how workable that would be.

This sounds workable. I mean, an array struct member is not really a pointer (it only decays to a pointer) and does not suffer from the issues that pointers do -- infinite recursion with recursive data structures, etc.

In any case we should not have the simple string formatter trying to format these arrays, which it clearly doesn’t know how to do.

Jim

Should be easy to modify the regex to:

^char [[0-9]+]$

I don’t think you want the ^ or this wouldn’t match “const char [5]”. I wasn’t sure there were any post-decorators we might care about, but I can’t think of any.

Jim