Skip to content

Commit

Permalink
aarch64: add CFI directives to the page fault and interrupt handler a…
Browse files Browse the repository at this point in the history
…ssembly

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 <jwkozaczuk@gmail.com>
Message-Id: <20210329214843.31992-1-jwkozaczuk@gmail.com>
  • Loading branch information
wkozaczuk authored and nyh committed Mar 29, 2021
1 parent 7feab52 commit eee34a1
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 1 deletion.
2 changes: 1 addition & 1 deletion arch/aarch64/elf-dl.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 20 additions & 0 deletions arch/aarch64/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions arch/aarch64/macros.S
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit eee34a1

Please sign in to comment.