Discussion:
[PATCH] Also find CFI in sections of type SHT_X86_64_UNWIND
Milian Wolff
2018-10-29 15:21:26 UTC
Permalink
On my system with g++ (GCC) 8.2.1 20180831 with GNU gold (GNU Binutils
2.31.1) 1.16, the .eh_frame section does not have type PROGBITS
but rather is using X86_64_UNWIND nowadays:

```
$ echo "int main(){ return 0; }" > test.c
$ gcc test.c
$ readelf --sections a.out | grep .eh_frame
[14] .eh_frame X86_64_UNWIND 0000000000000670 00000670
[15] .eh_frame_hdr X86_64_UNWIND 0000000000000724 00000724
```

Without this patch, libdw refuses to use the available unwind
information, leading to broken backtraces while unwinding. With the
patch applied, unwinding works once more in such situations.

Signed-off-by: Milian Wolff <***@kdab.com>
---
libdw/dwarf_getcfi_elf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libdw/dwarf_getcfi_elf.c b/libdw/dwarf_getcfi_elf.c
index 315cc02f..4bcfe5cd 100644
--- a/libdw/dwarf_getcfi_elf.c
+++ b/libdw/dwarf_getcfi_elf.c
@@ -298,7 +298,7 @@ getcfi_shdr (Elf *elf, const GElf_Ehdr *ehdr)
}
else if (!strcmp (name, ".eh_frame"))
{
- if (shdr->sh_type == SHT_PROGBITS)
+ if (shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_X86_64_UNWIND)
return getcfi_scn_eh_frame (elf, ehdr, scn, shdr,
hdr_scn, hdr_vaddr);
else
--
2.19.1
Mark Wielaard
2018-11-04 23:04:32 UTC
Permalink
Post by Milian Wolff
On my system with g++ (GCC) 8.2.1 20180831 with GNU gold (GNU
Binutils
2.31.1) 1.16, the .eh_frame section does not have type PROGBITS
Urgh, who thought it would be a good idea to have a architecture
specific (instead of a GNU specific) section type for unwind tables...
And why is there no separate type for .eh_frame_hdr. Now you still need
to check the name anyway...

But, given that we have that now, yes, lets deal with it.
Post by Milian Wolff
```
$ echo "int main(){ return 0; }" > test.c
$ gcc test.c
$ readelf --sections a.out | grep .eh_frame
  [14] .eh_frame         X86_64_UNWIND    0000000000000670  00000670
  [15] .eh_frame_hdr     X86_64_UNWIND    0000000000000724  00000724
```
Without this patch, libdw refuses to use the available unwind
information, leading to broken backtraces while unwinding. With the
patch applied, unwinding works once more in such situations.
Three questions:

- What testcase did you use?
In theory dwarf_getcfi_elf () should fall back to using phdrs and
find the PT_GNU_EH_FRAME data instead.

- It might be better to change the check to shdr->sh_type != SHT_NOBITS
The idea is probably that we don't want to look at the data in case
this is a .debug file which has it removed. This might be better than
adding a check for X86_64_UNWIND since then we would also need to
check the arch. Does != SHT_NOBITS work for you?

- What does eu-readelf -S show?
I think we need a x86_64_section_type_name () ebl hook to show it
correctly.

Thanks,

Mark
Milian Wolff
2018-11-05 23:12:58 UTC
Permalink
Post by Mark Wielaard
Post by Milian Wolff
On my system with g++ (GCC) 8.2.1 20180831 with GNU gold (GNU Binutils
2.31.1) 1.16, the .eh_frame section does not have type PROGBITS
Urgh, who thought it would be a good idea to have a architecture
specific (instead of a GNU specific) section type for unwind tables...
And why is there no separate type for .eh_frame_hdr. Now you still need
to check the name anyway...
But, given that we have that now, yes, lets deal with it.
Post by Milian Wolff
```
$ echo "int main(){ return 0; }" > test.c
$ gcc test.c
$ readelf --sections a.out | grep .eh_frame
[14] .eh_frame X86_64_UNWIND 0000000000000670 00000670
[15] .eh_frame_hdr X86_64_UNWIND 0000000000000724 00000724
```
Without this patch, libdw refuses to use the available unwind
information, leading to broken backtraces while unwinding. With the
patch applied, unwinding works once more in such situations.
- What testcase did you use?
In theory dwarf_getcfi_elf () should fall back to using phdrs and
find the PT_GNU_EH_FRAME data instead.
For unwinding, I used this full example:

https://paste.kde.org/p5rogntox

Then I compiled with `g++ -g O2` and recorded it with perf (`perf record --
call-graph dwarf`). Finally, I looked at the unwinding results via `perf
script`. I compiled perf from sources with `NO_LIBUNWIND=1` to have it use
libdw instead.

Interestingly, when I try to reproduce this on my laptop (i.e. compile even
the trivial C example), then I cannot reproduce this at all anymore - the
.eh_frame sections show up as PROGBITS. My desktop at work still shows this
behavior though (also see below). I can't quite explain this difference...
Post by Mark Wielaard
- It might be better to change the check to shdr->sh_type != SHT_NOBITS
The idea is probably that we don't want to look at the data in case
this is a .debug file which has it removed. This might be better than
adding a check for X86_64_UNWIND since then we would also need to
check the arch. Does != SHT_NOBITS work for you?
Yes, since SHT_NOBITS is not equal to SHT_X86_64_UNWIND :)
Post by Mark Wielaard
- What does eu-readelf -S show?
I think we need a x86_64_section_type_name () ebl hook to show it
correctly.
Yes, that looks like it:

```
$ cat test.c
int main() { return 0; }
$ gcc test.c
$ readelf -S a.out | grep eh_frame
[14] .eh_frame X86_64_UNWIND 0000000000000670 00000670
[15] .eh_frame_hdr X86_64_UNWIND 0000000000000724 00000724
$ eu-readelf -S a.out | grep eh_frame
[14] .eh_frame SHT_LOPROC+1 0000000000000670 00000670 000000b4 0 A
0 0 8
[15] .eh_frame_hdr SHT_LOPROC+1 0000000000000724 00000724 0000002c 0 A
0 0 4
```

Cheers
--
Milian Wolff | ***@kdab.com | Senior Software Engineer
KDAB (Deutschland) GmbH, a KDAB Group company
Tel: +49-30-521325470
KDAB - The Qt, C++ and OpenGL Experts
Mark Wielaard
2018-11-06 11:06:57 UTC
Permalink
Hi Milian,
Post by Milian Wolff
Interestingly, when I try to reproduce this on my laptop (i.e. compile even
the trivial C example), then I cannot reproduce this at all anymore - the
.eh_frame sections show up as PROGBITS. My desktop at work still shows this
behavior though (also see below). I can't quite explain this difference...
It seems to only happen with a specific combination of gcc and the gold
linker, I could only generate the SHT_X86_64_UNWIND sections only on
fedora 29 with gcc 8.2.1 and gold version 2.31.1-13.fc29 (1.16).
Post by Milian Wolff
Post by Mark Wielaard
- It might be better to change the check to shdr->sh_type != SHT_NOBITS
The idea is probably that we don't want to look at the data in case
this is a .debug file which has it removed. This might be better than
adding a check for X86_64_UNWIND since then we would also need to
check the arch. Does != SHT_NOBITS work for you?
Yes, since SHT_NOBITS is not equal to SHT_X86_64_UNWIND :)
OK, then lets change your patch to do that as attached.
Post by Milian Wolff
Post by Mark Wielaard
- What does eu-readelf -S show?
I think we need a x86_64_section_type_name () ebl hook to show it
correctly.
And the other attached patch should clean that up.

Thanks,

Mark
Milian Wolff
2018-11-07 09:02:54 UTC
Permalink
Post by Mark Wielaard
Hi Milian,
Post by Milian Wolff
Interestingly, when I try to reproduce this on my laptop (i.e. compile even
the trivial C example), then I cannot reproduce this at all anymore - the
.eh_frame sections show up as PROGBITS. My desktop at work still shows this
behavior though (also see below). I can't quite explain this difference...
It seems to only happen with a specific combination of gcc and the gold
linker, I could only generate the SHT_X86_64_UNWIND sections only on
fedora 29 with gcc 8.2.1 and gold version 2.31.1-13.fc29 (1.16).
At least on my system, that doesn't seem to be enough. Both my desktop and my
laptop are running on ArchLinux with the same versions of GCC and Gold, yet
one shows this behavior while the other one isn't...

What I noticed is that ccache seems to influence it for me, which makes this
even stranger:

```
$ which gcc
/usr/lib/ccache/bin/gcc
$ gcc --version
gcc (GCC) 8.2.1 20180831
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc test.c
$ readelf -S a.out | grep eh_frame
[14] .eh_frame_hdr PROGBITS 0000000000002004 00002004
[15] .eh_frame PROGBITS 0000000000002030 00002030

$ /usr/bin/gcc test.c
$ /usr/bin/gcc --version
gcc (GCC) 8.2.1 20180831
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ /usr/bin/gcc test.c
$ readelf -S a.out | grep eh_frame
[14] .eh_frame X86_64_UNWIND 0000000000000670 00000670
[15] .eh_frame_hdr X86_64_UNWIND 0000000000000724 00000724
```

Anyhow, that's unrelated to the patches at hand here. See below.
Post by Mark Wielaard
Post by Milian Wolff
Post by Mark Wielaard
- It might be better to change the check to shdr->sh_type != SHT_NOBITS
The idea is probably that we don't want to look at the data in case
this is a .debug file which has it removed. This might be better than
adding a check for X86_64_UNWIND since then we would also need to
check the arch. Does != SHT_NOBITS work for you?
Yes, since SHT_NOBITS is not equal to SHT_X86_64_UNWIND :)
OK, then lets change your patch to do that as attached.
Post by Milian Wolff
Post by Mark Wielaard
- What does eu-readelf -S show?
I think we need a x86_64_section_type_name () ebl hook to show it
correctly.
And the other attached patch should clean that up.
Both patches work for me:

Tested-by: Milian Wolff <***@kdab.com>

Thanks
--
Milian Wolff | ***@kdab.com | Senior Software Engineer
KDAB (Deutschland) GmbH, a KDAB Group company
Tel: +49-30-521325470
KDAB - The Qt, C++ and OpenGL Experts
Mark Wielaard
2018-11-09 16:57:37 UTC
Permalink
Post by Milian Wolff
Post by Mark Wielaard
It seems to only happen with a specific combination of gcc and the gold
linker, I could only generate the SHT_X86_64_UNWIND sections only on
fedora 29 with gcc 8.2.1 and gold version 2.31.1-13.fc29 (1.16).
At least on my system, that doesn't seem to be enough. Both my desktop and my
laptop are running on ArchLinux with the same versions of GCC and Gold, yet
one shows this behavior while the other one isn't...
Strange indeed. My system doesn't have ccache, it does show the issue.
Great. I pushed both to master now.

Thanks,

Mark
Mark Wielaard
2018-11-10 23:28:57 UTC
Permalink
Found another issue while testing with a gcc 8.1 and gold setup I
noticed some self-tests failed because elflint doesn't know about
SHT_X86_64_UNWIND section type and cannot match the PT_GNU_EH_FRAME
segment. The attached patch fixes it.
Mark Wielaard
2018-11-13 21:19:41 UTC
Permalink
Post by Mark Wielaard
Found another issue while testing with a gcc 8.1 and gold setup I
noticed some self-tests failed because elflint doesn't know about
SHT_X86_64_UNWIND section type and cannot match the PT_GNU_EH_FRAME
segment. The attached patch fixes it.
Subject: [PATCH] elflint: Allow PT_GNU_EH_FRAME segment to match
SHT_X86_64_UNWIND section.
The gold linker might generate an .eh_frame_hdr with a
SHT_X86_64_UNWIND type instead of a SHT_PROGBITS type.
Pushed to master.

Loading...