1 /* Copyright (c) 2015-2019. The SimGrid Team. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
6 #ifndef SIMGRID_MC_UNW_HPP
7 #define SIMGRID_MC_UNW_HPP
10 * Libunwind implementation for the model-checker
12 * Libunwind provides an pluggable stack unwinding API: the way the current
13 * registers and memory is accessed, the way unwinding informations is found
16 * This component implements the libunwind API for he model-checker:
18 * * reading memory from a simgrid::mc::AddressSpace*;
20 * * reading stack registers from a saved snapshot (context).
22 * Parts of the libunwind information fetching is currently handled by the
23 * standard `libunwind` implementations (either the local one or the ptrace one)
24 * because parsing `.eh_frame` section is not fun and `libdw` does not help
28 #include "src/mc/mc_forward.hpp"
32 #include <libunwind.h>
37 XBT_PRIVATE unw_addr_space_t create_addr_space();
38 XBT_PRIVATE void* create_context(unw_addr_space_t as, pid_t pid);
46 simgrid::mc::AddressSpace* addressSpace_ = nullptr;
47 simgrid::mc::RemoteClient* process_ = nullptr;
48 unw_context_t unwindContext_;
51 UnwindContext() = default;
52 UnwindContext(const UnwindContext&) = default;
53 UnwindContext& operator=(const UnwindContext&) = default;
54 ~UnwindContext() { clear(); }
55 void initialize(simgrid::mc::RemoteClient* process, unw_context_t* c);
57 unw_cursor_t cursor();
59 private: // Methods and virtual table for libunwind
60 static int find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t* pip, int need_unwind_info,
62 static void put_unwind_info(unw_addr_space_t as, unw_proc_info_t* pip, void* arg) noexcept;
63 static int get_dyn_info_list_addr(unw_addr_space_t as, unw_word_t* dilap, void* arg) noexcept;
64 static int access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t* valp, int write, void* arg) noexcept;
65 static void* get_reg(unw_context_t* context, unw_regnum_t regnum) noexcept;
66 static int access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t* valp, int write, void* arg) noexcept;
67 static int access_fpreg(unw_addr_space_t as, unw_regnum_t regnum, unw_fpreg_t* fpvalp, int write, void* arg) noexcept;
68 static int resume(unw_addr_space_t as, unw_cursor_t* cp, void* arg) noexcept;
69 static int get_proc_name(unw_addr_space_t as, unw_word_t addr, char* bufp, size_t buf_len, unw_word_t* offp,
71 static unw_accessors_t accessors;
74 // Create a libunwind address space:
75 static unw_addr_space_t createUnwindAddressSpace();
78 void dumpStack(FILE* file, unw_cursor_t&& cursor);
79 void dumpStack(FILE* file, pid_t pid);