From 54b19783d91039c7b57d8be672fad5187674d75e Mon Sep 17 00:00:00 2001 From: Gammasoft Date: Fri, 18 Oct 2024 20:02:49 +0200 Subject: [PATCH] Add stack_frame::get_native_offset method --- .../src/xtd/native/linux/stack_trace.cpp | 9 +++- .../src/xtd/native/macos/stack_trace.mm | 8 +++- .../src/xtd/native/posix/stack_trace.cpp | 8 +++- .../src/xtd/native/unix/stack_trace.cpp | 8 +++- .../src/xtd/native/win32/stack_trace.cpp | 44 +++++++++++-------- .../include/xtd/native/stack_trace.h | 5 +++ .../include/xtd/diagnostics/stack_frame.h | 17 +++++++ .../src/xtd/diagnostics/stack_frame.cpp | 4 ++ 8 files changed, 81 insertions(+), 22 deletions(-) diff --git a/src/xtd.core.native.linux/src/xtd/native/linux/stack_trace.cpp b/src/xtd.core.native.linux/src/xtd/native/linux/stack_trace.cpp index a7a46ae813b7..4c7c1e5b97ff 100644 --- a/src/xtd.core.native.linux/src/xtd/native/linux/stack_trace.cpp +++ b/src/xtd.core.native.linux/src/xtd/native/linux/stack_trace.cpp @@ -9,6 +9,8 @@ using namespace std; using namespace xtd::native; namespace { + constexpr size_t native_offset = 1; + string demangle_string(const string& method) { auto result = method; auto status = 0; @@ -19,6 +21,11 @@ namespace { } } + +size_t stack_trace::get_native_offset() { + return native_offset; +} + #if __ANDROID__ | __CYGWIN__ | __MINGW32__ stack_trace::frames stack_trace::get_frames(size_t skip_frames, size_t max_frames) { return {}; @@ -31,7 +38,7 @@ stack_trace::frames stack_trace::get_frames(size_t skip_frames) { traces.resize(max_frames); auto nb_frames = static_cast(backtrace(traces.data(), static_cast(max_frames))); - for (auto index = skip_frames + 1; index < nb_frames; ++index) { + for (auto index = skip_frames + native_offset; index < nb_frames; ++index) { auto dl_info = Dl_info {}; if (!dladdr(traces[index], &dl_info) || !dl_info.dli_sname) break; frames.push_back(std::make_tuple(dl_info.dli_fname, 0, 0, demangle_string(dl_info.dli_sname), reinterpret_cast(dl_info.dli_saddr) - reinterpret_cast(dl_info.dli_fbase))); diff --git a/src/xtd.core.native.macos/src/xtd/native/macos/stack_trace.mm b/src/xtd.core.native.macos/src/xtd/native/macos/stack_trace.mm index d3f5ad16a8d2..703d3e1578d6 100644 --- a/src/xtd.core.native.macos/src/xtd/native/macos/stack_trace.mm +++ b/src/xtd.core.native.macos/src/xtd/native/macos/stack_trace.mm @@ -9,6 +9,8 @@ using namespace xtd::native; namespace { + constexpr size_t native_offset = 1; + std::string demangle_string(const std::string& method) { auto result = method; auto status = 0; @@ -19,6 +21,10 @@ } } +size_t stack_trace::get_native_offset() { + return native_offset; +} + stack_trace::frames stack_trace::get_frames(size_t skip_frames) { //NSLog(@"%@", NSThread.callStackSymbols); static constexpr auto max_frames = size_t {1024}; @@ -27,7 +33,7 @@ traces.resize(max_frames); auto nb_frames = static_cast(backtrace(traces.data(), static_cast(max_frames))); - for (auto index = skip_frames + 1; index < nb_frames; ++index) { + for (auto index = skip_frames + native_offset; index < nb_frames; ++index) { auto dl_info = Dl_info {}; if (!dladdr(traces[index], &dl_info) || !dl_info.dli_sname) break; frames.push_back(std::make_tuple(dl_info.dli_fname, 0, 0, demangle_string(dl_info.dli_sname), reinterpret_cast(dl_info.dli_saddr) - reinterpret_cast(dl_info.dli_fbase))); diff --git a/src/xtd.core.native.posix/src/xtd/native/posix/stack_trace.cpp b/src/xtd.core.native.posix/src/xtd/native/posix/stack_trace.cpp index 2dcd390f7a89..d1214a045fb9 100644 --- a/src/xtd.core.native.posix/src/xtd/native/posix/stack_trace.cpp +++ b/src/xtd.core.native.posix/src/xtd/native/posix/stack_trace.cpp @@ -9,6 +9,8 @@ using namespace std; using namespace xtd::native; namespace { + constexpr size_t native_offset = 1; + string demangle_string(const string& method) { auto result = method; auto status = 0; @@ -19,6 +21,10 @@ namespace { } } +size_t stack_trace::get_native_offset() { + return native_offset; +} + stack_trace::frames stack_trace::get_frames(size_t skip_frames) { static constexpr size_t max_frames = 1024; stack_trace::frames frames; @@ -26,7 +32,7 @@ stack_trace::frames stack_trace::get_frames(size_t skip_frames) { traces.resize(max_frames); size_t nb_frames = backtrace(traces.data(), static_cast(max_frames)); - for (size_t index = skip_frames + 1; index < nb_frames; ++index) { + for (size_t index = skip_frames + native_offset; index < nb_frames; ++index) { Dl_info dl_info; if (!dladdr(traces[index], &dl_info) || !dl_info.dli_sname) break; frames.push_back(std::make_tuple(dl_info.dli_fname, 0, 0, demangle_string(dl_info.dli_sname), reinterpret_cast(dl_info.dli_saddr) - reinterpret_cast(dl_info.dli_fbase))); diff --git a/src/xtd.core.native.unix/src/xtd/native/unix/stack_trace.cpp b/src/xtd.core.native.unix/src/xtd/native/unix/stack_trace.cpp index 2dcd390f7a89..d1214a045fb9 100644 --- a/src/xtd.core.native.unix/src/xtd/native/unix/stack_trace.cpp +++ b/src/xtd.core.native.unix/src/xtd/native/unix/stack_trace.cpp @@ -9,6 +9,8 @@ using namespace std; using namespace xtd::native; namespace { + constexpr size_t native_offset = 1; + string demangle_string(const string& method) { auto result = method; auto status = 0; @@ -19,6 +21,10 @@ namespace { } } +size_t stack_trace::get_native_offset() { + return native_offset; +} + stack_trace::frames stack_trace::get_frames(size_t skip_frames) { static constexpr size_t max_frames = 1024; stack_trace::frames frames; @@ -26,7 +32,7 @@ stack_trace::frames stack_trace::get_frames(size_t skip_frames) { traces.resize(max_frames); size_t nb_frames = backtrace(traces.data(), static_cast(max_frames)); - for (size_t index = skip_frames + 1; index < nb_frames; ++index) { + for (size_t index = skip_frames + native_offset; index < nb_frames; ++index) { Dl_info dl_info; if (!dladdr(traces[index], &dl_info) || !dl_info.dli_sname) break; frames.push_back(std::make_tuple(dl_info.dli_fname, 0, 0, demangle_string(dl_info.dli_sname), reinterpret_cast(dl_info.dli_saddr) - reinterpret_cast(dl_info.dli_fbase))); diff --git a/src/xtd.core.native.win32/src/xtd/native/win32/stack_trace.cpp b/src/xtd.core.native.win32/src/xtd/native/win32/stack_trace.cpp index f47e95bdd6a3..4e3d7f7e4c80 100644 --- a/src/xtd.core.native.win32/src/xtd/native/win32/stack_trace.cpp +++ b/src/xtd.core.native.win32/src/xtd/native/win32/stack_trace.cpp @@ -11,24 +11,32 @@ using namespace std; using namespace xtd::native; -class stack_walker final : public StackWalker { -public: - using frame = std::tuple; - using frames = std::vector; +namespace { + constexpr size_t native_offset = 1; - stack_walker() : StackWalker(StackWalker::RetrieveVerbose | StackWalker::SymBuildPath) {} - - const frames& get_frames() const noexcept {return frames_;} - -private: - void OnCallstackEntry(CallstackEntryType type, CallstackEntry& entry) override { - StackWalker::OnCallstackEntry(type, entry); - frames_.push_back(make_tuple(entry.lineFileName, entry.lineNumber, entry.offsetFromLine, entry.name, static_cast(entry.offsetFromSmybol))); - } - -private: - frames frames_; -}; + class stack_walker final : public StackWalker { + public: + using frame = std::tuple; + using frames = std::vector; + + stack_walker() : StackWalker(StackWalker::RetrieveVerbose | StackWalker::SymBuildPath) {} + + const frames& get_frames() const noexcept {return frames_;} + + private: + void OnCallstackEntry(CallstackEntryType type, CallstackEntry& entry) override { + StackWalker::OnCallstackEntry(type, entry); + frames_.push_back(make_tuple(entry.lineFileName, entry.lineNumber, entry.offsetFromLine, entry.name, static_cast(entry.offsetFromSmybol))); + } + + private: + frames frames_; + }; +} + +size_t stack_trace::get_native_offset() { + return native_offset; +} stack_trace::frames stack_trace::get_frames(size_t skip_frames) { auto sw = stack_walker {}; @@ -36,7 +44,7 @@ stack_trace::frames stack_trace::get_frames(size_t skip_frames) { auto result = stack_trace::frames {}; auto frames = sw.get_frames(); - for (auto index = skip_frames + 1; index < frames.size(); ++index) { + for (auto index = skip_frames + native_offset; index < frames.size(); ++index) { result.push_back(frames[index]); if (get<3>(frames[index]) == "main") break; } diff --git a/src/xtd.core.native/include/xtd/native/stack_trace.h b/src/xtd.core.native/include/xtd/native/stack_trace.h index 34a1bb8a70f7..6fe724895be2 100644 --- a/src/xtd.core.native/include/xtd/native/stack_trace.h +++ b/src/xtd.core.native/include/xtd/native/stack_trace.h @@ -49,6 +49,11 @@ namespace xtd { /// @name Protected Static Methods /// @{ + /// @brief Gets the offset from the start of the native code for the method that is being executed. + /// @return The offset from the start of the native code for the method that is being executed. + /// @warning Internal use only + static size_t get_native_offset(); + /// @brief Play system sound. /// @param sound The sound to play (see souund.h). /// @warning Internal use only diff --git a/src/xtd.core/include/xtd/diagnostics/stack_frame.h b/src/xtd.core/include/xtd/diagnostics/stack_frame.h index a6fef36e35c9..5a5d3020d330 100644 --- a/src/xtd.core/include/xtd/diagnostics/stack_frame.h +++ b/src/xtd.core/include/xtd/diagnostics/stack_frame.h @@ -197,6 +197,23 @@ namespace xtd { /// ``` virtual const xtd::string& get_method() const noexcept; + /// @brief Gets the offset from the start of the native code for the method that is being executed. + /// @return The offset from the start of the native code for the method that is being executed. + /// @par Examples + /// The following example demonstrates the use of the get_offset() method. This code example is part of a larger example provided for the xtd::diagnostics::stack_frame class. + /// ```cpp + /// // Display the stack frame properties. + /// stack_frame sf = st.get_frame(i); + /// console::write_line(" File: {}", sf.get_file_name()); + /// console::write_line(" Line Number: {}", sf.get_file_line_number()); + /// // Note that the column number defaults to zero when not initialized. + /// console::write_line(" Column Number: {}", sf.get_file_column_number()); + /// console::write_line(" Method: {}", sf.get_method()); + /// if (sf.get_offset() != stack_frame::OFFSET_UNKNOWN) + /// console::write_line(" Native Offset: {}", sf.get_native_offset()); + /// ``` + virtual xtd::size get_native_offset() const noexcept; + /// @brief Gets the offset from the start of the code for the method that is being executed. /// @return The offset from the code for the method that is being executed. /// @par Examples diff --git a/src/xtd.core/src/xtd/diagnostics/stack_frame.cpp b/src/xtd.core/src/xtd/diagnostics/stack_frame.cpp index 0eb79dcd79b5..671258f31864 100644 --- a/src/xtd.core/src/xtd/diagnostics/stack_frame.cpp +++ b/src/xtd.core/src/xtd/diagnostics/stack_frame.cpp @@ -116,6 +116,10 @@ const string& stack_frame::get_method() const noexcept { return data_->method_name; } +xtd::size stack_frame::get_native_offset() const noexcept { + return native::stack_trace::get_native_offset(); +} + xtd::size stack_frame::get_offset() const noexcept { return data_->offset; }