Arcane  v4.1.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
BackwardCppStackTraceService.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* BackwardCppStackTraceService.cc (C) 2000-2025 */
9/* */
10/* Service de trace des appels de fonctions utilisant 'backward-cpp'. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/PlatformUtils.h"
15#include "arcane/utils/IStackTraceService.h"
16#include "arcane/utils/StackTrace.h"
17#include "arcane/utils/StringBuilder.h"
18#include "arcane/utils/Convert.h"
19
21#include "arcane/core/AbstractService.h"
22
23#include "arcane_packages.h"
24
25//TODO : Ajouter les autres packages.
26#define BACKWARD_HAS_DW 1
27
28#if defined(ARCANE_HAS_PACKAGE_LIBUNWIND)
29#define BACKWARD_HAS_LIBUNWIND 1
30#endif
31
32#include "arcane/std/internal/backwardcpp/backward.hpp"
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36
37namespace Arcane
38{
39
40/*---------------------------------------------------------------------------*/
41/*---------------------------------------------------------------------------*/
42
43class BackwardCppStackTraceService
44: public AbstractService
45, public IStackTraceService
46{
47
48 public:
49
50 explicit BackwardCppStackTraceService(const ServiceBuildInfo& sbi)
51 : AbstractService(sbi)
52 , m_verbose_level(2)
53 {}
54
55 public:
56
57 void build() override
58 {
59 // 0 : CallStack classique (nom de fonction uniquement)
60 // 1 : CallStack classique avec numéro de ligne et fichier pour les classes/fonctions hors du namespace Arcane
61 // 2 : (default) CallStack classique avec numéro de ligne et fichier pour toutes les classes/fonctions
62 // 3 : CallStack classique avec numéro de ligne, fichier pour toutes les classes/fonctions et snippet pour les classes/fonctions hors du namespace Arcane
63 // 4 : CallStack classique avec numéro de ligne, fichier et snippet pour toutes les classes/fonctions
64 if (const auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_CALLSTACK_VERBOSE", true)) {
65 if (v.value() < 0 || v.value() > 4) {
66 return;
67 }
68 m_verbose_level = v.value();
69 }
70 }
71
72 public:
73
74 StackTrace stackTrace(int first_function) override;
75 StackTrace stackTraceFunction(int function_index) override;
76
77 private:
78
79 Int32 m_verbose_level;
80};
81
82/*---------------------------------------------------------------------------*/
83/*---------------------------------------------------------------------------*/
84
86stackTrace(int first_function)
87{
88 StringBuilder message;
89 FixedStackFrameArray stack_frames;
90 constexpr size_t hexa_buf_size = 100;
91 char hexa[hexa_buf_size + 1];
92
93 backward::StackTrace st;
94 st.skip_n_firsts(first_function);
95 st.load_here(64);
96
97 backward::TraceResolver tr;
98 tr.load_stacktrace(st);
99
100 backward::SnippetFactory sf;
101
102 for (size_t i = 0; i < st.size(); ++i) {
103 backward::ResolvedTrace trace = tr.resolve(st[i]);
104 message += " ";
105 snprintf(hexa, hexa_buf_size, "%14p", trace.addr);
106 message += hexa;
107 message += " ";
108 message += trace.object_function;
109
110 UInt32 src_line = trace.source.line;
111
112 if (m_verbose_level > 0 && src_line > 0) {
113 bool arcane_function = String(trace.object_function).startsWith("Arcane");
114 if (m_verbose_level > 1 || !arcane_function) {
115 auto lines = sf.get_snippet(trace.source.filename, src_line, 5);
116 message += "\n Line: ";
117 message += src_line;
118 message += " -- File: ";
119 message += trace.source.filename;
120 if (m_verbose_level > 3 || (m_verbose_level > 2 && !arcane_function)) {
121 for (const auto& [line_num, line] : lines) {
122 message += (line_num == src_line ? "\n >>> " : "\n ");
123 message += line_num;
124 message += ": ";
125 message += line;
126 }
127 }
128 }
129 }
130
131 message += "\n";
132
133 stack_frames.addFrame(StackFrame(reinterpret_cast<intptr_t>(trace.addr)));
134 }
135
136 return { stack_frames, message };
137}
138
139/*---------------------------------------------------------------------------*/
140/*---------------------------------------------------------------------------*/
141
143stackTraceFunction(int function_index)
144{
145 backward::StackTrace st;
146 st.skip_n_firsts(function_index);
147 st.load_here(1);
148
149 if (st.size() < 1) {
150 return {};
151 }
152 backward::TraceResolver tr;
153 tr.load_stacktrace(st);
154
155 backward::ResolvedTrace trace = tr.resolve(st[0]);
156
157 return { trace.object_function };
158}
159
160/*---------------------------------------------------------------------------*/
161/*---------------------------------------------------------------------------*/
162
164 ServiceProperty("BackwardCppStackTraceService", ST_Application),
166
167/*---------------------------------------------------------------------------*/
168/*---------------------------------------------------------------------------*/
169
170} // End namespace Arcane
171
172/*---------------------------------------------------------------------------*/
173/*---------------------------------------------------------------------------*/
Ce fichier contient les différentes fabriques de services et macro pour enregistrer les services.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro pour déclarer une interface lors de l'enregistrement d'un service.
AbstractService(const ServiceBuildInfo &)
Constructeur à partir d'un ServiceBuildInfo.
void build() override
Construction de niveau build du service.
StackTrace stackTrace(int first_function) override
Chaîne de caractère indiquant la pile d'appel.
StackTrace stackTraceFunction(int function_index) override
Nom d'une fonction dans la pile d'appel.
Conserve une liste de taille fixe maximale de StackFrame.
void addFrame(const StackFrame &frame)
Ajoute frame à la liste des frames. Si nbFrame() est supérieur ou égal à MAX_FRAME,...
Interface d'un service de trace des appels de fonctions.
Structure contenant les informations pour créer un service.
Propriétés de création d'un service.
Conserve les adresses correspondantes à une pile d'appel. Cette classe est interne et ne dois pas êtr...
Informations sur la pile d'appel des fonctions.
Constructeur de chaîne de caractère unicode.
Chaîne de caractères unicode.
bool startsWith(const String &s) const
Indique si la chaîne commence par les caractères de s.
Definition String.cc:1100
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
std::uint32_t UInt32
Type entier non signé sur 32 bits.
@ ST_Application
Le service s'utilise au niveau de l'application.
std::int32_t Int32
Type entier signé sur 32 bits.