This patch adds necessary CFI (Call Frame Information) directives
to the assembly code in entry.S and macros.S to make stack traces
for page faults and interrupt handler look correct. Otherwise
debugging scenarios that involve those becomes very painful.

Before the patch:
-----------------
#0  mmu::file_vma::fault (this=0xffffa00040c9b280, addr=17592186171392, 
ef=0x200000100110) at core/mmu.cc:1708
#1  0x00000000401da05c in mmu::vm_fault (addr=17592186171392, 
ef=0x200000100110) at core/mmu.cc:1354
#2  0x000000004020ba9c in page_fault (ef=0x200000100110) at 
arch/aarch64/mmu.cc:50
#3  0x000000004020b82c in handle_mem_abort () at arch/aarch64/entry.S:161
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

After the patch:
----------------
#0  mmu::file_vma::fault (this=0xffffa00040c9b280, addr=17592186171392, 
ef=0x200000100110) at core/mmu.cc:1708
#1  0x00000000401da05c in mmu::vm_fault (addr=17592186171392, 
ef=0x200000100110) at core/mmu.cc:1354
#2  0x000000004020ba9c in page_fault (ef=0x200000100110) at 
arch/aarch64/mmu.cc:50
#3  <signal handler called>
#4  elf::object::_dynamic_tag (tag=29, this=0xffffa00040dcf800) at 
core/elf.cc:649
#5  elf::object::dynamic_exists (tag=29, this=0xffffa00040dcf800) at 
core/elf.cc:641
#6  elf::object::load_needed (this=0xffffa00040dcf800, 
loaded_objects=std::vector of length 1, capacity 1 = {...}) at core/elf.cc:1068
#7  0x00000000401f1bd4 in elf::program::load_object 
(this=this@entry=0xffffa00040897ba0, name="/libvdso.so", extra_path=std::vector 
of length 0, capacity 0, 
    loaded_objects=std::vector of length 1, capacity 1 = {...}) at 
build/downloaded_packages/aarch64/gcc/install/usr/include/c++/10/bits/shared_ptr_base.h:1321
#8  0x00000000401f24fc in elf::program::get_library (this=0xffffa00040897ba0, 
name="libvdso.so", extra_path=std::vector of length 0, capacity 0, 
delay_init=false)
    at core/elf.cc:1459
#9  0x0000000040314ea0 in osv::application::prepare_argv 
(this=this@entry=0xffffa00040dcf610, program=program@entry=0xffffa00040897ba0) 
at core/app.cc:361
#10 0x0000000040315694 in 
osv::application::application(std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > const&, 
std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > > > const&, bool, 
std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> >, std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> >, 
std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > >, 
std::allocator<std::pair<std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > const, 
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > 
> > > const*, std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> > const&, std::function<void ()>) 
(this=0xffffa00040dcf610, command="/tests/tst-hello.so", args=..., 
new_program=false, env=0x0, main_function_name="main", post_main=...)
    at core/app.cc:182
...

Before the patch:
-----------------
#0  virtio::blk::ack_irq (this=0xffffa00040a91c00) at drivers/virtio-blk.cc:103
#1  operator() (__closure=0xffffa00040950e40) at drivers/virtio-blk.cc:143
#2  std::__invoke_impl<bool, 
virtio::blk::blk(virtio::virtio_device&)::<lambda(pci::device&)>::<lambda()>&> 
(__f=...)
    at 
build/downloaded_packages/aarch64/gcc/install/usr/include/c++/10/bits/invoke.h:60
#3  std::__invoke_r<bool, 
virtio::blk::blk(virtio::virtio_device&)::<lambda(pci::device&)>::<lambda()>&> 
(__fn=...)
    at 
build/downloaded_packages/aarch64/gcc/install/usr/include/c++/10/bits/invoke.h:141
#4  std::_Function_handler<bool(), 
virtio::blk::blk(virtio::virtio_device&)::<lambda(pci::device&)>::<lambda()> 
>::_M_invoke(const std::_Any_data &) (__functor=...)
    at 
build/downloaded_packages/aarch64/gcc/install/usr/include/c++/10/bits/std_function.h:291
#5  0x000000004020c784 in std::function<bool ()>::operator()() const 
(this=<optimized out>)
    at 
build/downloaded_packages/aarch64/gcc/install/usr/include/c++/10/bits/std_function.h:622
#6  interrupt_table::invoke_interrupt (this=this@entry=0x40780968 <idt>, 
id=id@entry=36) at arch/aarch64/exceptions.cc:135
#7  0x000000004020c95c in interrupt (frame=<optimized out>) at 
arch/aarch64/exceptions.cc:167
#8  0x000000004020b930 in entry_irq () at arch/aarch64/entry.S:175
#9  0x000000004020b930 in entry_irq () at arch/aarch64/entry.S:175
#10 0x000000004020b930 in entry_irq () at arch/aarch64/entry.S:175
#11 0x000000004020b930 in entry_irq () at arch/aarch64/entry.S:175
#12 0x000000004020b930 in entry_irq () at arch/aarch64/entry.S:175
#13 0x000000004020b930 in entry_irq () at arch/aarch64/entry.S:175
... (infinite number of frames)

After the patch:
----------------
#0  virtio::blk::ack_irq (this=0xffffa00040a91c00) at drivers/virtio-blk.cc:103
#1  operator() (__closure=0xffffa00040950e40) at drivers/virtio-blk.cc:143
#2  std::__invoke_impl<bool, 
virtio::blk::blk(virtio::virtio_device&)::<lambda(pci::device&)>::<lambda()>&> 
(__f=...)
    at 
build/downloaded_packages/aarch64/gcc/install/usr/include/c++/10/bits/invoke.h:60
#3  std::__invoke_r<bool, 
virtio::blk::blk(virtio::virtio_device&)::<lambda(pci::device&)>::<lambda()>&> 
(__fn=...)
    at 
build/downloaded_packages/aarch64/gcc/install/usr/include/c++/10/bits/invoke.h:141
#4  std::_Function_handler<bool(), 
virtio::blk::blk(virtio::virtio_device&)::<lambda(pci::device&)>::<lambda()> 
>::_M_invoke(const std::_Any_data &) (__functor=...)
    at 
build/downloaded_packages/aarch64/gcc/install/usr/include/c++/10/bits/std_function.h:291
#5  0x000000004020c784 in std::function<bool ()>::operator()() const 
(this=<optimized out>)
    at 
build/downloaded_packages/aarch64/gcc/install/usr/include/c++/10/bits/std_function.h:622
#6  interrupt_table::invoke_interrupt (this=this@entry=0x40780968 <idt>, 
id=id@entry=36) at arch/aarch64/exceptions.cc:135
#7  0x000000004020c95c in interrupt (frame=<optimized out>) at 
arch/aarch64/exceptions.cc:167
#8  <signal handler called>
#9  sched::cpu::do_idle (this=this@entry=0xffff8000407fe040) at 
core/sched.cc:454
#10 0x00000000402e6b78 in sched::cpu::idle (this=0xffff8000407fe040) at 
core/sched.cc:472
#11 0x00000000402e6ba0 in operator() (__closure=<optimized out>, 
__closure=<optimized out>) at core/sched.cc:165
#12 std::__invoke_impl<void, sched::cpu::init_idle_thread()::<lambda()>&> 
(__f=...)
    at 
build/downloaded_packages/aarch64/gcc/install/usr/include/c++/10/bits/invoke.h:60
#13 std::__invoke_r<void, sched::cpu::init_idle_thread()::<lambda()>&> 
(__fn=...) at 
build/downloaded_packages/aarch64/gcc/install/usr/include/c++/10/bits/invoke.h:153
#14 std::_Function_handler<void(), sched::cpu::init_idle_thread()::<lambda()> 
>::_M_invoke(const std::_Any_data &) (__functor=...)
    at 
build/downloaded_packages/aarch64/gcc/install/usr/include/c++/10/bits/std_function.h:291
#15 0x00000000402e72b4 in sched::thread::main (this=0xffffa000408eea48) at 
core/sched.cc:1267
#16 sched::thread_main_c (t=0xffffa000408eea48) at 
arch/aarch64/arch-switch.hh:162
#17 0x000000004020b788 in thread_main () at arch/aarch64/entry.S:114

Refs #1128

Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com>
---
 arch/aarch64/elf-dl.S |  2 +-
 arch/aarch64/entry.S  | 20 ++++++++++++++++++++
 arch/aarch64/macros.S |  6 ++++++
 3 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/arch/aarch64/elf-dl.S b/arch/aarch64/elf-dl.S
index 6bcc0358..97ecd67f 100644
--- a/arch/aarch64/elf-dl.S
+++ b/arch/aarch64/elf-dl.S
@@ -40,5 +40,5 @@ __elf_resolve_pltgot:
        ldp     x6, x7, [sp, #16]
        ldp     x8, xzr, [sp], #(80)
 
-        pop_pair x17, x30
+        ldp     x17, x30, [sp], #16
         br      x16
diff --git a/arch/aarch64/entry.S b/arch/aarch64/entry.S
index 7188429e..556f89ad 100644
--- a/arch/aarch64/entry.S
+++ b/arch/aarch64/entry.S
@@ -59,6 +59,7 @@ exception_vectors:
 /* keep in sync with the struct in exceptions.hh */
 .macro push_state_to_exception_frame
         sub     sp, sp, #48 // make space for align2, align1+ESR, PSTATE, PC, 
SP
+        .cfi_adjust_cfa_offset 48
         push_pair x28, x29
         push_pair x26, x27
         push_pair x24, x25
@@ -101,6 +102,7 @@ exception_vectors:
         pop_pair x26, x27
         pop_pair x28, x29
         ldr     x30, [sp], #48
+        .cfi_adjust_cfa_offset -48
 .endm /* pop_state_to_exception_frame */
 
 .global thread_main
@@ -143,6 +145,12 @@ entry_invalid:
 .global entry_sync
 .type entry_sync, @function
 entry_sync:
+        .cfi_startproc simple
+        .cfi_signal_frame
+        .cfi_def_cfa sp, 0
+        .cfi_offset x30, -32 // Point to the elr register located at the -32 
offset
+                             // of the exception frame to help gdb link to the
+                             // address when interrupt was raised
         push_state_to_exception_frame
         mrs     x1, esr_el1
         str     w1, [sp, #272] // Store Exception Syndrom Register in the frame
@@ -161,20 +169,30 @@ handle_mem_abort:
         bl      page_fault
         pop_state_from_exception_frame
         eret
+        .cfi_endproc
 unexpected_sync_exception:
+        .cfi_startproc
         mov     x0, sp  // save exception_frame to x0
         bl      handle_unexpected_sync_exception
         pop_state_from_exception_frame
         bl      abort
+        .cfi_endproc
 
 .global entry_irq
 .type entry_irq, @function
 entry_irq:
+        .cfi_startproc simple
+        .cfi_signal_frame
+        .cfi_def_cfa sp, 0
+        .cfi_offset x30, -32 // Point to the elr register located at the -32 
offset
+                             // of the exception frame to help gdb link to the
+                             // address when interrupt was raised
         push_state_to_exception_frame
         mov     x0, sp
         bl      interrupt // extern "C"
         pop_state_from_exception_frame
         eret
+        .cfi_endproc
 
 .global entry_fiq
 .type entry_fiq, @function
@@ -187,6 +205,7 @@ entry_serror:
 .global call_signal_handler_thunk
 call_signal_handler_thunk:
         .type call_signal_handler_thunk, @function
+        .cfi_startproc simple
         # stack contains a signal_frame
         /*
         .cfi_offset reg, offset
@@ -199,6 +218,7 @@ call_signal_handler_thunk:
         add sp, sp, 16 # error_code
         */
         ret
+        .cfi_endproc
 
 // Keep fpu_state_save/load in sync with struct fpu_state in 
arch/aarch64/processor.hh
 // void fpu_state_save(fpu_state *s);
diff --git a/arch/aarch64/macros.S b/arch/aarch64/macros.S
index 8c790ca2..64d98d03 100644
--- a/arch/aarch64/macros.S
+++ b/arch/aarch64/macros.S
@@ -7,8 +7,14 @@
 
 .macro push_pair reg1, reg2
         stp \reg1, \reg2, [sp, #-16]!
+       .cfi_adjust_cfa_offset 16
+       .cfi_rel_offset \reg1, 0
+       .cfi_rel_offset \reg2, 8
 .endm
 
 .macro pop_pair reg1, reg2
         ldp \reg1, \reg2, [sp], #16
+       .cfi_adjust_cfa_offset -16
+       .cfi_restore \reg2
+       .cfi_restore \reg1
 .endm
-- 
2.30.2

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/20210329214843.31992-1-jwkozaczuk%40gmail.com.

Reply via email to