New arm_abi_cfi that defines initial CFA, rules for callee-saved regs and return register.
Note the DWARF abi extension for ARM says that "registers intentionally unused" should also be initialized as if by DW_CFA_same_value. The example given is "an integer-only function might be included in one executable file for targets with VFP and another for targets without". We don't currently do this yet.
Also adds addrcfi arm testcase.
Signed-off-by: Mark Wielaard mjw@redhat.com --- backends/ChangeLog | 6 ++++ backends/Makefile.am | 2 +- backends/arm_cfi.c | 67 +++++++++++++++++++++++++++++++++++++++++++ backends/arm_init.c | 3 +- tests/ChangeLog | 6 ++++ tests/Makefile.am | 3 +- tests/run-addrcfi.sh | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/testfilearm.bz2 | Bin 0 -> 3545 bytes 8 files changed, 160 insertions(+), 3 deletions(-) create mode 100644 backends/arm_cfi.c create mode 100755 tests/testfilearm.bz2
diff --git a/backends/ChangeLog b/backends/ChangeLog index 64e5efd..68ab00e 100644 --- a/backends/ChangeLog +++ b/backends/ChangeLog @@ -1,3 +1,9 @@ +2013-08-29 Mark Wielaard mjw@redhat.com + + * Makefile.am (arm_SRCS): Add arm_cfi.c. + * arm_cfi.c: New file. + * arm_init.c (arm_init): Initialize abi_cfi. + 2013-08-28 Mark Wielaard mjw@redhat.com
* arm_regs.c (arm_register_info): Set *prefix to "". diff --git a/backends/Makefile.am b/backends/Makefile.am index ec022b0..557ed87 100644 --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -75,7 +75,7 @@ libebl_alpha_pic_a_SOURCES = $(alpha_SRCS) am_libebl_alpha_pic_a_OBJECTS = $(alpha_SRCS:.c=.os)
arm_SRCS = arm_init.c arm_symbol.c arm_regs.c arm_corenote.c \ - arm_auxv.c arm_attrs.c arm_retval.c + arm_auxv.c arm_attrs.c arm_retval.c arm_cfi.c libebl_arm_pic_a_SOURCES = $(arm_SRCS) am_libebl_arm_pic_a_OBJECTS = $(arm_SRCS:.c=.os)
diff --git a/backends/arm_cfi.c b/backends/arm_cfi.c new file mode 100644 index 0000000..7fb1b93 --- /dev/null +++ b/backends/arm_cfi.c @@ -0,0 +1,67 @@ +/* arm ABI-specified defaults for DWARF CFI. + Copyright (C) 2013 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <dwarf.h> + +#define BACKEND arm_ +#include "libebl_CPU.h" + +int +arm_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info) +{ + static const uint8_t abi_cfi[] = + { + /* The initial Canonical Frame Address is the value of the + Stack Pointer (r13) as setup in the previous frame. */ + DW_CFA_def_cfa, ULEB128_7 (13), ULEB128_7 (0), + +#define SV(n) DW_CFA_same_value, ULEB128_7 (n) + /* Callee-saved regs r4-r8, r10, r11. */ + SV (4), SV (5), SV (6), SV (7), SV (8), SV (10), SV (11), + + /* The link register contains the return address setup by caller. */ + SV (14), + + /* XXX Note: registers intentionally unused by the program, + for example as a consequence of the procedure call standard + should be initialized as if by DW_CFA_same_value. */ +#undef SV + }; + + abi_info->initial_instructions = abi_cfi; + abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi]; + abi_info->data_alignment_factor = 4; + + abi_info->return_address_register = 14; /* Link Register. */ + + return 0; +} diff --git a/backends/arm_init.c b/backends/arm_init.c index 38bd4eb..cf661ce 100644 --- a/backends/arm_init.c +++ b/backends/arm_init.c @@ -1,5 +1,5 @@ /* Initialization of Arm specific backend library. - Copyright (C) 2002, 2005, 2009 Red Hat, Inc. + Copyright (C) 2002, 2005, 2009, 2013 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper drepper@redhat.com, 2002.
@@ -62,6 +62,7 @@ arm_init (elf, machine, eh, ehlen) HOOK (eh, auxv_info); HOOK (eh, check_object_attribute); HOOK (eh, return_value_location); + HOOK (eh, abi_cfi);
return MODVERSION; } diff --git a/tests/ChangeLog b/tests/ChangeLog index b934555..3f9c878 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,9 @@ +2013-08-29 Mark Wielaard mjw@redhat.com + + * run-addrcfi.sh: Add case for EM_ARM. + * testfilearm.bz2: New testfile. + * Makefile.am (EXTRA_DIST): Add testfilesarm.bz2. + 2013-08-28 Mark Wielaard mjw@redhat.com
* addrcfi.c (handle_cfi): Handle .debug_frame or .eh_frame diff --git a/tests/Makefile.am b/tests/Makefile.am index 8e4f88a..251ebc4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -204,7 +204,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ test-core.exec.bz2 run-addr2line-test.sh \ run-addr2line-i-test.sh testfile-inlines.bz2 \ testfileppc32.bz2 testfileppc64.bz2 \ - testfiles390.bz2 testfiles390x.bz2 + testfiles390.bz2 testfiles390x.bz2 \ + testfilearm.bz2
if USE_VALGRIND valgrind_cmd='valgrind -q --trace-children=yes --error-exitcode=1 --run-libc-freeres=no' diff --git a/tests/run-addrcfi.sh b/tests/run-addrcfi.sh index 38669ca..71143f0 100755 --- a/tests/run-addrcfi.sh +++ b/tests/run-addrcfi.sh @@ -2496,3 +2496,79 @@ testrun_compare ${abs_builddir}/addrcfi -e testfiles390x 0x0000000080000510 <<\E control reg65 (%pswa): same_value handle_cfi no CFI (.debug_frame): no error EOF + +# EM_ARM (function bar 0x00008510) +# Note. Only in .debug_frame, the .eh_frame is actually empty. +# Same as s390 and ppc above. +testfiles testfilearm +testrun_compare ${abs_builddir}/addrcfi -e testfilearm 0x00008510 <<\EOF +dwarf_cfi_addrframe (.eh_frame): no matching address range +.debug_frame has 0x8510 => [0x8510, 0x8524): + return address in reg14 + CFA location expression: bregx(13) + integer reg0 (r0): same_value + integer reg1 (r1): same_value + integer reg2 (r2): same_value + integer reg3 (r3): same_value + integer reg4 (r4): same_value + integer reg5 (r5): same_value + integer reg6 (r6): same_value + integer reg7 (r7): same_value + integer reg8 (r8): same_value + integer reg9 (r9): same_value + integer reg10 (r10): same_value + integer reg11 (r11): same_value + integer reg12 (r12): same_value + integer reg13 (sp): same_value + integer reg14 (lr): same_value + integer reg15 (pc): same_value + FPA reg16 (f0): same_value + FPA reg17 (f1): same_value + FPA reg18 (f2): same_value + FPA reg19 (f3): same_value + FPA reg20 (f4): same_value + FPA reg21 (f5): same_value + FPA reg22 (f6): same_value + FPA reg23 (f7): same_value + FPA reg96 (f0): same_value + FPA reg97 (f1): same_value + FPA reg98 (f2): same_value + FPA reg99 (f3): same_value + FPA reg100 (f4): same_value + FPA reg101 (f5): same_value + FPA reg102 (f6): same_value + FPA reg103 (f7): same_value + integer reg128 (spsr): same_value + VFP reg256 (d0): same_value + VFP reg257 (d1): same_value + VFP reg258 (d2): same_value + VFP reg259 (d3): same_value + VFP reg260 (d4): same_value + VFP reg261 (d5): same_value + VFP reg262 (d6): same_value + VFP reg263 (d7): same_value + VFP reg264 (d8): same_value + VFP reg265 (d9): same_value + VFP reg266 (d10): same_value + VFP reg267 (d11): same_value + VFP reg268 (d12): same_value + VFP reg269 (d13): same_value + VFP reg270 (d14): same_value + VFP reg271 (d15): same_value + VFP reg272 (d16): same_value + VFP reg273 (d17): same_value + VFP reg274 (d18): same_value + VFP reg275 (d19): same_value + VFP reg276 (d20): same_value + VFP reg277 (d21): same_value + VFP reg278 (d22): same_value + VFP reg279 (d23): same_value + VFP reg280 (d24): same_value + VFP reg281 (d25): same_value + VFP reg282 (d26): same_value + VFP reg283 (d27): same_value + VFP reg284 (d28): same_value + VFP reg285 (d29): same_value + VFP reg286 (d30): same_value + VFP reg287 (d31): same_value +EOF diff --git a/tests/testfilearm.bz2 b/tests/testfilearm.bz2 new file mode 100755 index 0000000000000000000000000000000000000000..d6cd090e3e12df1d4c9cac7d626ceb62909c0de4 GIT binary patch literal 3545 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 TxzqwcANaeHDZ+$+7wbU);YL+V
literal 0 HcmV?d00001
Note the DWARF abi extension for ARM says that "registers intentionally unused" should also be initialized as if by DW_CFA_same_value. The example given is "an integer-only function might be included in one executable file for targets with VFP and another for targets without". We don't currently do this yet.
Seems worthwhile to include the URL to the ABI spec that talks about DWARF and/or the function call ABI (we never did for the others, but I'm not sure there are canonical URLs for most of them).
We have the DW_CFA_restore hack (which I could have sworn was used somewhere--I thought we had abi_cfi for ppc long ago). So perhaps the right thing is to use that plus explicit DW_CFA_undefined for the call-clobbered registers.
Either way, this needs to cover the VFP/NEON registers (which are half call-clobbered and half call-saved).
/* The link register contains the return address setup by caller. */
SV (14),
Should also have:
DW_CFA_register, ULEB128_7 (15), ULEB128_7 (14), /* pc = lr */
- abi_info->return_address_register = 14; /* Link Register. */
I think that's wrong. 14 is LR, which is just a general register that happens to be where the ABI says the return address is on entry. The "return_address_register" is for the "caller's PC" (a "virtual register" on machines where the PC is not directly addressable), so it should use 15 (PC).
Thanks, Roland
On Thu, 29 Aug 2013 19:51:27 +0200, Roland McGrath wrote:
- abi_info->return_address_register = 14; /* Link Register. */
I think that's wrong. 14 is LR, which is just a general register that happens to be where the ABI says the return address is on entry. The "return_address_register" is for the "caller's PC" (a "virtual register" on machines where the PC is not directly addressable), so it should use 15 (PC).
BTW I used LR as return_address_register on s390 and ppc because there is no DWARF number for PC and the CFI seems wrongly addressing LR there (moreover under two different numbers - and really not that one of them should be PC).
So in the case of ARM having real DWARF number for PC it should be probably used for return_address_register. But I do not know how to read .ARM.extab to verify how the unwind tables look there - if they use the register 15.
Jan
BTW I used LR as return_address_register on s390 and ppc because there is no DWARF number for PC and the CFI seems wrongly addressing LR there (moreover under two different numbers - and really not that one of them should be PC).
return_address_register does not have to be a register number that has a meaning assigned in the spec. It is really just a private choice for the particular CIE. If there is no specified number for the PC, then it can be any number that is not specified as being for another particular register.
So in the case of ARM having real DWARF number for PC it should be probably used for return_address_register. But I do not know how to read .ARM.extab to verify how the unwind tables look there - if they use the register 15.
There is readelf -u in binutils and see https://wiki.linaro.org/KenWerner/Sandbox/libunwind#unwinding_on_ARM (actual spec in http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf ). And you can look at .debug_frame tables. But that's really neither here nor there. It doesn't matter what the compiler does for some particular FDEs (or for all that it emits). All that matters is that the number you choose for a particular CIE is the one that its FDEs describe correctly for rematerializing the return address and is not one specified to mean a particular register if the caller's value of that register has a value that is not the same as the return address.
For machines with a link-register calling convention, "the caller's value of the link register" is the same thing as "the return address" on entry. The benefit of distinguishing them is that you can more precisely describe what is required for unwinding without falsely stating that more is required. That is, the link register is call-clobbered in the ABI and to unwind to the caller it would be sufficient to set the PC to the return address while not restoring the link register. By using a different return_address_register, you could describe a situation where, e.g. the return address is recoverable from the stack or another register, but the link register per se will be left as "undefined". In the case of ARM, imagine the code:
mov r0, lr mov lr, #0 bx r0
Now, it would be correct enough to say that return_address_register is r0, that r0's rule is same-value, and that lr's rule is undefined (or is register r0, if you like). That is not entirely precise, since it says the caller's value of r0 was knowable when in fact it's undefined. But as to the return address and lr, it's perfectly correct and precise. In actual fact, the compiler would never generate code like that because the hardware makes it optimal always to use "bx lr" for return (it has a call/return prediction stack and "bx lr" is specifically recognized as "return").
So it's not really clear which is "better", because it depends on what your goals are.
If you just want to unwind and that's all, then it's best to arrange that unwinding does as little work as possible. It's not necessary to restore the caller's value to lr, since lr is call-clobbered anyway. So then it's better to use the PC number (or an unassigned number, on machines with no number assigned for the PC) as return_address_register and an undefined rule for lr. Depending on the code, that may even be a more precisely correct description, because the code might return to the caller's lr without putting that address back into lr:
push {..., lr} bl other_function @ clobber lr pop {..., pc} @ restore regs & return in one insn, leave lr clobbered
That is, the epilogue won't restore lr, so unwinding is closer to the effect of a natural return if it doesn't restore lr either.
For general debugging purposes, we usually say that the compiler should describe how to recover everything that truly can be recovered. (This is a different predicate from "everything that a natural return would actually restore".) So it's nice to describe lr with a rule other than undefined (i.e. same-value in the trivial case), because that means that when you go up a frame you can see the value the register truly had at the call site rather than being told it's unavailable. Then it just seems redundant and wasteful to use a different value for return_address_register, because then you need to process pc=lr rule as well (or if lr is no longer same-value, you need to repeat the same rule for lr and for return_address_register).
OTOH, if return_address_register != lr and the rule for return_address_register gives a location that is mutable (i.e. some other register or memory location) and that location is not also used in some other register's rule, then the CFI describes how you can change the machine state to warp the eventual return of the frame without changing any caller register. From the debugger perspective that seems ideal, but a case where you could actually do that seems extremely unlikely (unless you give lr an undefined rule so that the stack slot where the incoming lr was saved is described as being the return address, as in the pop-to-pc example above).
Thanks, Roland
Hi Roland,
IIUC your mail is talking about what return_address_register means in DWARF. But DWARF return_address_register does not need to be guessed by elfutils, it is always present in CIE, if there is any DWARF FDE/CIE found.
The discussion here was what elfutils ebl_abi_cfi() should return (what is the "elfutils return_address_register"). That is described in elfutils by: libebl/libebl.h: This function can also fill in ABI_INFO->return_address_register with the DWARF register number that identifies the actual PC in machine state. If there is no canonical DWARF register number with that meaning, it's left unchanged (callers usually initialize with (Dwarf_Word) -1). This value is not used by CFI per se.
This would correspond to your suggested value 15 (PC) for ARM. But no elfutils code uses that value. I have no idea if systemtap uses it.
Besides that .ARM.exidx assumes return address is in LR plus .debug_frame has return address set to LR by GCC: Return address column: 14 I have included an example ARM output at the bottom of this mail. Existing CIEs do not matter much for the elfutils return_address_register value, as you wrote below:
On Thu, 29 Aug 2013 22:32:31 +0200, Roland McGrath wrote:
But that's really neither here nor there. It doesn't matter what the compiler does for some particular FDEs (or for all that it emits). All that matters is that the number you choose for a particular CIE is the one that its FDEs describe correctly for rematerializing the return address
I agree elfutils return_address_register does not matter for CIE as CIE contains its own value. Then remains the question what is elfutils return_address_register good for.
My unwinder patchset keeps PC value independently from the DWARF register set as some archs (ppc/s390) do not have any DWARF register assigned for PC.
There is readelf -u in binutils and see https://wiki.linaro.org/KenWerner/Sandbox/libunwind#unwinding_on_ARM (actual spec in http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf ). And you can look at .debug_frame tables.
Thanks for the pointers, great info.
mov r0, lr mov lr, #0 bx r0
Now, it would be correct enough to say that return_address_register is r0, that r0's rule is same-value, and that lr's rule is undefined (or is register r0, if you like). That is not entirely precise, since it says the caller's value of r0 was knowable when in fact it's undefined. But as to the return address and lr, it's perfectly correct and precise. In actual fact, the compiler would never generate code like that because the hardware makes it optimal always to use "bx lr" for return (it has a call/return prediction stack and "bx lr" is specifically recognized as "return").
So it's not really clear which is "better", because it depends on what your goals are.
The goal is IMO to unwind as much inferior code as possible.
You are describing various non-standard ARM code cases. But those should have their own .ARM.exidx or .debug_frame entry so elfutils return_address_register does not matter then.
In the example below with -fasynchronous-unwind-tables it does not matter what elfutils return_address_register is set to. But without -fasynchronous-unwind-tables the unwind will be successful only if elfutils return_address_register is set to 14 (when .debug_frame is not available).
Discussing hypothetical unwinder (maybe the systemtap one behaves that way?). My current pending elfutils unwinder aborts unwind if neither .eh_frame nor .debug_frame is found as it expects -fasynchronous-unwind-tables is in use.
Thanks, Jan
000084d4 <main>: 84d4: e52db004 push {fp} ; (str fp, [sp, #-4]!) 84d8: e28db000 add fp, sp, #0 84dc: e3a03000 mov r3, #0 84e0: e1a00003 mov r0, r3 84e4: e24bd000 sub sp, fp, #0 84e8: e49db004 pop {fp} ; (ldr fp, [sp], #4) 84ec: e12fff1e bx lr 000084f0 <__libc_csu_init>:
Unwind table index '.ARM.exidx' at offset 0x568 contains 5 entries:
This entry is present only with -fasynchronous-unwind-tables: 0x84d4 <main>: 0x809b8080 Compact model index: 0 0x9b vsp = r11 0x80 0x80 pop {r11}
Contents of the .debug_frame section:
00000000 0000000c ffffffff CIE Version: 1 Augmentation: "" Code alignment factor: 2 Data alignment factor: -4 Return address column: 14
DW_CFA_def_cfa: r13 ofs 0
00000010 00000014 00000000 FDE cie=00000000 pc=000084d4..000084f0 DW_CFA_advance_loc: 4 to 000084d8 DW_CFA_def_cfa_offset: 4 DW_CFA_offset: r11 at cfa-4 DW_CFA_advance_loc: 4 to 000084dc DW_CFA_def_cfa_register: r11
On Sat, 2013-08-31 at 18:53 +0200, Jan Kratochvil wrote:
This would correspond to your suggested value 15 (PC) for ARM. But no elfutils code uses that value. I have no idea if systemtap uses it.
Currently it is indeed not used. As you point out, the CIE will always set up a return register value. But seems a good idea to keep it consistent with the other CFI ABI setup if set. SystemTap doesn't use it (sadly it has to run in kernel space and can only use elfutils support during translation time, not at runtime). And the libebl backend interfaces are NOT public API. So SystemTap really shouldn't use them directly (and doesn't). They are only used internally in other elfutils code. And we can (and should) change them whenever we feel we could do something better with a different setup.
Cheers,
Mark
On Thu, 2013-08-29 at 10:51 -0700, Roland McGrath wrote:
Note the DWARF abi extension for ARM says that "registers intentionally unused" should also be initialized as if by DW_CFA_same_value. The example given is "an integer-only function might be included in one executable file for targets with VFP and another for targets without". We don't currently do this yet.
Seems worthwhile to include the URL to the ABI spec that talks about DWARF and/or the function call ABI (we never did for the others, but I'm not sure there are canonical URLs for most of them).
Good idea. It is always hard to find them. This one can be found here: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040b/IHI0040B_aadwarf.p... "DWARF for the ARM Architecture ABI r2.09"
We have the DW_CFA_restore hack (which I could have sworn was used somewhere--I thought we had abi_cfi for ppc long ago). So perhaps the right thing is to use that plus explicit DW_CFA_undefined for the call-clobbered registers.
Either way, this needs to cover the VFP/NEON registers (which are half call-clobbered and half call-saved).
Somehow missed them because they are discussed under "5.1.2 Co-processor Registers". But indeed they also have a calling convention defined. http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042e/IHI0042E_aapcs.pdf "Procedure Call Standard for the ARM Architecture ABI r2.09" I'll also add that link. Hopefully those URLs are stable.
/* The link register contains the return address setup by caller. */
SV (14),
Should also have:
DW_CFA_register, ULEB128_7 (15), ULEB128_7 (14), /* pc = lr */
Ah, right, of course.
- abi_info->return_address_register = 14; /* Link Register. */
I think that's wrong. 14 is LR, which is just a general register that happens to be where the ABI says the return address is on entry. The "return_address_register" is for the "caller's PC" (a "virtual register" on machines where the PC is not directly addressable), so it should use 15 (PC).
Which makes sense with the pc = lr definition above. Though I am sure I saw r14 used instead. Now I cannot remember where/why. I'll double check and update the patch.
Thanks,
Mark
elfutils-devel@lists.fedorahosted.org