Bug 22452 - Extend ebl_reloc_ hooks with relocations against load address for use in libdwfl/relocate.c
Summary: Extend ebl_reloc_ hooks with relocations against load address for use in libd...
Status: RESOLVED FIXED
Alias: None
Product: elfutils
Classification: Unclassified
Component: libdw (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-11-17 14:29 UTC by H. Brueckner
Modified: 2018-03-31 12:32 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
ko-func-call-frame-cfa.c (2.18 KB, text/x-csrc)
2017-11-17 14:29 UTC, H. Brueckner
Details
paes_s390_ko-relocs-eu-readelf.txt (62.91 KB, text/plain)
2017-11-17 16:02 UTC, H. Brueckner
Details
paes_s390_ko-relocs-readelf.txt (73.63 KB, text/plain)
2017-11-17 16:03 UTC, H. Brueckner
Details

Note You need to log in before you can comment on or make changes to this bug.
Description H. Brueckner 2017-11-17 14:29:32 UTC
Created attachment 10612 [details]
ko-func-call-frame-cfa.c

Problem
-------
The perf probe -m <mod> -V <func> fails when looking up variables for a function defined in an s390 kernel module.  I have attached a simple test program that performs these steps which results in problems to receive an CFI frame.

Test Case and reproduction steps
--------------------------------

1. Iterate through the DIE to spot a particular function
2. Determine frame base attribute for that function
3. Obtain location expressions for the frame base and entry pc of the function
4. The returned location expression is a DW_OP_call_frame_cfa
5. Obtain CFI from either eh_frame or debug_frame, which fails.
6. Obtain ops from dwarf_frame_cfa()

The step 5 always fails for both, .eh_frame and debug_frame.  When using dwarf_cfi_addrframe() on the .eh_frame, the resulting dwarf error message is "no matching address range".

The attachment "ko-func-call-frame-cfa.c" contains this test case.  Compile and link against ldw -lelf and issue with: ./ko-func-call-frame-cfa <func> <module.ko>

Note that this affects kernel modules built for s390. Running the test program against the s390 vmlinux image works fine, e.g., for the setup_arch function.

As I cannot attach binary code, you can obtain an s390 kernel module, for example, from the kernel debuginfo packages of Fedora.  For example:

1. https://download-ib01.fedoraproject.org/pub/fedora-secondary/releases/27/Server/s390x/debug/tree/Packages/k/kernel-debuginfo-4.13.9-300.fc27.s390x.rpm
2. rpm2cpio < kernel-debuginfo-4.13.9-300.fc27.s390x.rpm |cpio -id
3. Try to find details about the "xts_paes_crypt" function in paes_s390.ko.debug

For example:
ko-func-call-frame-cfa xts_paes_crypt kernel/arch/s390/crypto/paes_s390.ko.debug 
I: Looking up xts_paes_crypt@kernel/arch/s390/crypto/paes_s390.ko.debug
DIE: name=xts_paes_crypt tag=subprogram offset=58750 (0xe57e)
	low   pc: 10c18
	high  pc: 10dd6
	entry pc: 10c18
I: Frame Base: Number of locations: 1 (len=1)
I: Frame Base: Location operation 0: call_frame_cfa
E: No CFI data available
Comment 1 Mark Wielaard 2017-11-17 15:27:54 UTC
I haven't investigated fully yet.
But I did take a quick look at the paes_s390.ko.debug file.
A few quick comments as early feedback.

Note that it doesn't contain .debug_frame but only a .eh_frame section.
Other architectures force .debug_frame for kernel modules to store the CFI.

The .eh_frame is a loaded section, which means it won't go into the .debug
file. So you would need to load the CFI from the main ELF .ko.

One tricky issue here is the fact that kernel modules are ET_REL files
that still need relocations applied (you can see there is also a .rela.eh_frame section). libdwfl can do simple relocations, but might not know about all relocation types used in an .eh_frame section (I haven't checked yet).
Comment 2 H. Brueckner 2017-11-17 15:38:09 UTC
(In reply to Mark Wielaard from comment #1)
> I haven't investigated fully yet.
> But I did take a quick look at the paes_s390.ko.debug file.
> A few quick comments as early feedback.
> 
> Note that it doesn't contain .debug_frame but only a .eh_frame section.
> Other architectures force .debug_frame for kernel modules to store the CFI.
> 
> The .eh_frame is a loaded section, which means it won't go into the .debug
> file. So you would need to load the CFI from the main ELF .ko.

Initially, I have tried on my own kernel build (including debug_info) and ran the test program against the .ko file.  (Because I am not permitted to share binary code and, please, do not ask why, it is difficult to provide you an alternative.  If you have access to a s390 or use a cross-compiler it would be fine but that typically requires some effort on your side.

In any case, if you require some output in text form, please let me know.

> One tricky issue here is the fact that kernel modules are ET_REL files
> that still need relocations applied (you can see there is also a
> .rela.eh_frame section). libdwfl can do simple relocations, but might not
> know about all relocation types used in an .eh_frame section (I haven't
> checked yet).

Ok.
Comment 3 H. Brueckner 2017-11-17 15:44:40 UTC
(In reply to Mark Wielaard from comment #1)

> One tricky issue here is the fact that kernel modules are ET_REL files
> that still need relocations applied (you can see there is also a
> .rela.eh_frame section). libdwfl can do simple relocations, but might not
> know about all relocation types used in an .eh_frame section (I haven't
> checked yet).

At least, I checked the reloc types for s390 (backends/s390_reloc.def) and the list is complete wrt kernel modules.  Not sure if there is further work to be done for non-simple relocations.
Comment 4 Mark Wielaard 2017-11-17 15:53:31 UTC
(In reply to H. Brueckner from comment #2)
> (In reply to Mark Wielaard from comment #1)
> > The .eh_frame is a loaded section, which means it won't go into the .debug
> > file. So you would need to load the CFI from the main ELF .ko.
> 
> Initially, I have tried on my own kernel build (including debug_info) and
> ran the test program against the .ko file.  (Because I am not permitted to
> share binary code and, please, do not ask why, it is difficult to provide
> you an alternative.  If you have access to a s390 or use a cross-compiler it
> would be fine but that typically requires some effort on your side.

Don't worry, we have the split .ko/.debug files, it should in theory also work (or show the same bug) with that.

> In any case, if you require some output in text form, please let me know.
> 
> > One tricky issue here is the fact that kernel modules are ET_REL files
> > that still need relocations applied (you can see there is also a
> > .rela.eh_frame section). libdwfl can do simple relocations, but might not
> > know about all relocation types used in an .eh_frame section (I haven't
> > checked yet).
> 
> Ok.

So, if you could provide the output of eu-readelf --relocs paes_s390.ko (on your combined paes_s390.ko containing both code and debug) that would be helpful.

If there are relocations in the .rela.eh_frame section that aren't "simple" as defined in s390_reloc_simple_type (backends/backends/s390_symbol.c) that might be a hint.

Also if you could trick you kernel build to generate CFI in .debug_frame instead of .eh_frame like other arches seem to do, that would make a good testcase.
Comment 5 Mark Wielaard 2017-11-17 15:56:54 UTC
(In reply to Mark Wielaard from comment #4)
> So, if you could provide the output of eu-readelf --relocs paes_s390.ko (on
> your combined paes_s390.ko containing both code and debug) that would be
> helpful.

eu-readelf --debug-dump=frames --relocs paes_s390.ko

would be even better.
Comment 6 H. Brueckner 2017-11-17 16:02:34 UTC
Created attachment 10613 [details]
paes_s390_ko-relocs-eu-readelf.txt

using eu-readelf
Comment 7 H. Brueckner 2017-11-17 16:03:18 UTC
Created attachment 10614 [details]
paes_s390_ko-relocs-readelf.txt

and what binutils readelfs reports for comparision
Comment 8 H. Brueckner 2017-11-17 16:04:13 UTC
(In reply to Mark Wielaard from comment #5)
> (In reply to Mark Wielaard from comment #4)
> > So, if you could provide the output of eu-readelf --relocs paes_s390.ko (on
> > your combined paes_s390.ko containing both code and debug) that would be
> > helpful.
> 
> eu-readelf --debug-dump=frames --relocs paes_s390.ko
> 
> would be even better.

Just attached the output; also the output of the binutils readelf command for comparision. I guess that there are some more issues because lots of invalid relocations are listed.
Comment 9 Mark Wielaard 2017-11-17 16:46:48 UTC
(In reply to H. Brueckner from comment #8)
> (In reply to Mark Wielaard from comment #5)
> > (In reply to Mark Wielaard from comment #4)
> > > So, if you could provide the output of eu-readelf --relocs paes_s390.ko (on
> > > your combined paes_s390.ko containing both code and debug) that would be
> > > helpful.
> > 
> > eu-readelf --debug-dump=frames --relocs paes_s390.ko
> > 
> > would be even better.
> 
> Just attached the output; also the output of the binutils readelf command
> for comparision. I guess that there are some more issues because lots of
> invalid relocations are listed.

Is that eu-readelf from a distro install? Then there is something wrong with that install. If it is a build from source then make sure LD_LIBRARY_PATH contains the backends directory that has libebl_s390.so. Otherwise eu-readelf won't know about machine specific ELF/DWARF mappings (like the relocation types/names).

But the output does confirm what I feared. The R_390_PC32 .rela.eh_frame relocations are not "simple". They are load based.

It might not be too hard to add support for those. But if there is any possibility to generate .debug_frame based CFI for the s390x kernel modules that would IMHO a much better/simpler solution because it makes things more in line with other arches. It should also make the kernel modules smaller. Does anything actually use the loaded .eh_frame CFI on s390x?
Comment 10 H. Brueckner 2017-11-20 08:08:03 UTC
(In reply to Mark Wielaard from comment #9)
> (In reply to H. Brueckner from comment #8)
> > (In reply to Mark Wielaard from comment #5)
> > > (In reply to Mark Wielaard from comment #4)
> > > > So, if you could provide the output of eu-readelf --relocs paes_s390.ko (on
> > > > your combined paes_s390.ko containing both code and debug) that would be
> > > > helpful.
> > > 
> > > eu-readelf --debug-dump=frames --relocs paes_s390.ko
> > > 
> > 
> > Just attached the output; also the output of the binutils readelf command
> > for comparision. I guess that there are some more issues because lots of
> > invalid relocations are listed.
> 
> Is that eu-readelf from a distro install? Then there is something wrong with
> that install. If it is a build from source then make sure LD_LIBRARY_PATH
> contains the backends directory that has libebl_s390.so. Otherwise
> eu-readelf won't know about machine specific ELF/DWARF mappings (like the
> relocation types/names).

It was a local built and install, the LD_LIBRARY_PATH was not set properly.
However, setting is correctly, the relocation are displayed like with readelf.
Will update the attachment soon.

> 
> But the output does confirm what I feared. The R_390_PC32 .rela.eh_frame
> relocations are not "simple". They are load based.

So now it comes to that point I have feared, as it looks like the libdw just
performs "simple" relocations.  Your comment and the ebl_reloc_simple_type()
call in  libdwfl/relocate.c proofs that. Anyhow, do you plan to extend the
relocation code to support more complex relocations tool?

> It might not be too hard to add support for those.

What needs to be done / is necessary for that?


> But if there is any
> possibility to generate .debug_frame based CFI for the s390x kernel modules
> that would IMHO a much better/simpler solution because it makes things more
> in line with other arches. It should also make the kernel modules smaller.
> Does anything actually use the loaded .eh_frame CFI on s390x?

I will check the module usage on .eh_frame and will have a try on including the
CFI in the .debug_frame.

Thanks.
Comment 11 Andreas Krebbel 2017-11-20 08:11:23 UTC
x86 enables generation of .debug_frame by using:

KBUILD_CFLAGS += -fno-asynchronous-unwind-tables

in the kernel Makefile.  This makes GCC to add ".cfi_sections .debug_frame" to the assembler output which in turn triggers gas to generate the section.

I don't see a reason why we couldn't do the same for s390. The .eh_frame section aren't used in the kernel.
Comment 12 Mark Wielaard 2017-11-20 09:28:34 UTC
(In reply to H. Brueckner from comment #10)
> (In reply to Mark Wielaard from comment #9)
> > But the output does confirm what I feared. The R_390_PC32 .rela.eh_frame
> > relocations are not "simple". They are load based.
> 
> So now it comes to that point I have feared, as it looks like the libdw just
> performs "simple" relocations.  Your comment and the ebl_reloc_simple_type()
> call in  libdwfl/relocate.c proofs that. Anyhow, do you plan to extend the
> relocation code to support more complex relocations tool?
> 
> > It might not be too hard to add support for those.
> 
> What needs to be done / is necessary for that?

We would need to extend ebl_reloc_simple_type, or add a new ebl backend hook, that signals a relocation uses the load address. Then in libdwfl/relocate.c use that to adjust the value to include the load address that libdwfl assigns to the section (given by struct dwfl_relocation start). This is similar to what arch/s390/kernel/module.c in the kernel does, but slightly more complicated because we want it to work "offline" cross architecture.

This would be helpful in general for any ET_REL file for which we want to inspect the .eh_frame section CFI data. But since this is just for the kernel modules at the moment I would wait with implementing it till you have experimented with adjusting the kernel build like suggested in comment #11.
Comment 13 Andreas Krebbel 2017-11-20 10:08:21 UTC
The .eh_frame section in an .o file uses PC-relative relocations in order to get its offset to the code determined during final link step. It probably does this to avoid runtime relocations which would be necessary for an absolute relocation. .eh_frame is read-only in the mapping, so runtime relocs are not supposed to occur after final link step.
Since in the kernel module scenario libdw has to deal with the .eh_frame section from the .o file it encounters these PC-relative relocs which it cannot handle. I agree with Mark that libdw does not really need to support these relocs since they only occur in that weird scenario which can be avoided using .debug_frame instead.

.debug_frame does not have a location in the address space so a PC-relative relocation would be pointless. Instead it is supposed to be read by tools where applying absolute relocs is no problem.
Comment 14 H. Brueckner 2017-11-20 14:00:33 UTC
Hi Mark, Andreas,

(In reply to Andreas Krebbel from comment #11)
> x86 enables generation of .debug_frame by using:
> 
> KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
> 
> in the kernel Makefile.  This makes GCC to add ".cfi_sections .debug_frame"
> to the assembler output which in turn triggers gas to generate the section.
> 
> I don't see a reason why we couldn't do the same for s390. The .eh_frame
> section aren't used in the kernel.

Thanks for this direction: Emitting the CFI data in the .debug_frame work nicely. With that change, perf probe and my test program works.  For reference:

./ko-func-call-frame-cfa xts_paes_crypt ~/git/linux/arch/s390/crypto/paes_s390.ko 
I: Looking up xts_paes_crypt@/root/git/linux/arch/s390/crypto/paes_s390.ko
DIE: name=xts_paes_crypt tag=subprogram offset=53957 (0xd2c5)
        low   pc: 10ca8
        high  pc: 10e78
        entry pc: 10ca8
I: Frame Base: Number of locations: 1 (len=1)
I: Frame Base: Location operation 0: call_frame_cfa
E: Could not obtain CFI (eh): no DWARF information
I: CFA operation: 0: bregx

clearly shows a successful call to dwarf_frame_cfa() obtaining the CFI from the .debug_frame (and not longe from the .eh_frame).

Having explicit ebl hooks would still be nice but I guess will not be the top-priority item in the TODO list.  I pursue to integrate my change for s390 in the upstream kernel.

Thanks!
Comment 15 Mark Wielaard 2017-12-10 15:45:27 UTC
(In reply to H. Brueckner from comment #14)
> Having explicit ebl hooks would still be nice but I guess will not be the
> top-priority item in the TODO list.  I pursue to integrate my change for
> s390 in the upstream kernel.

I have retitled this bug and will keep it open in case someone has time for implementing the ebl hooks for relative load address relocations.

Did you manage to get a kernel build change upstream?
It would be nice to point people at it in this bug in case they hit the same issue. So they know how to rebuild their kernel.
Comment 16 Mark Wielaard 2018-03-05 12:52:48 UTC
(In reply to Mark Wielaard from comment #15)
> Did you manage to get a kernel build change upstream?
> It would be nice to point people at it in this bug in case they hit the same
> issue. So they know how to rebuild their kernel.

commit bc3703f21cec8a2ac6a64f6fb3686fbcb1ba1513
Author: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Date:   Mon Nov 20 11:41:07 2017 +0100

    s390/kernel: emit CFI data in .debug_frame and discard .eh_frame sections
    
    Using perf probe and libdw on kernel modules failed to find CFI
    data for symbols.  The CFI data is stored in the .eh_frame section.
    The elfutils libdw is not able to extract the CFI data correctly,
    because the .eh_frame section requires "non-simple" relocations
    for kernel modules.
    
    The suggestion is to avoid these "non-simple" relocations by emitting
    the CFI data in the .debug_frame section.  Let gcc emit respective
    directives by specifying the -fno-asynchronous-unwind-tables option.
    
    Using the .debug_frame section for CFI data, the .eh_frame section
    becomes unused and, thus, discard it for kernel and modules builds
    
    The vDSO requires the .eh_frame section and, hence, emit the CFI data
    in both, the .eh_frame and .debug_frame sections.
    
    See also discussion on elfutils/libdw bugzilla:
    https://sourceware.org/bugzilla/show_bug.cgi?id=22452
    
    Suggested-by: Mark Wielaard <mark@klomp.org>
    Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
    Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
    Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

> I have retitled this bug and will keep it open in case someone has
> time for implementing the ebl hooks for relative load address relocations.

I think the above kernel fix is a better. And there really is not much benefit to have relative load address relocations for .eh_frame except for these ET_REL .ko files. Also, nobody seems to have time. So lets close this for now.