Arcane  v4.1.4.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-2026 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-2026 */
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/StringBuilder.h"
17#include "arcane/utils/Convert.h"
18
20#include "arcane/core/AbstractService.h"
21
22#include "arcane_packages.h"
23#include "arccore/base/internal/DependencyInjection.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 TraceAccessor
45, public IStackTraceService
46{
47
48 public:
49
50 explicit BackwardCppStackTraceService(const ServiceBuildInfo& sbi)
52 , m_verbose_level(2)
53 , m_human_readable(true)
54 {}
55
56 explicit BackwardCppStackTraceService(ITraceMng* tm)
57 : TraceAccessor(tm)
58 , m_verbose_level(2)
59 , m_human_readable(true)
60 {
61 BackwardCppStackTraceService::build();
62 }
63
64 public:
65
66 void build() override
67 {
68 // 0 : CallStack classique (nom de fonction uniquement)
69 // 1 : CallStack classique avec numéro de ligne et fichier pour les classes/fonctions hors du namespace Arcane
70 // 2 : (default) CallStack classique avec numéro de ligne et fichier pour toutes les classes/fonctions
71 // 3 : CallStack classique avec numéro de ligne, fichier pour toutes les classes/fonctions et snippet pour les classes/fonctions hors du namespace Arcane
72 // 4 : CallStack classique avec numéro de ligne, fichier et snippet pour toutes les classes/fonctions
73 if (const auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_CALLSTACK_VERBOSE", true)) {
74 if (v.value() < 0 || v.value() > 4) {
75 return;
76 }
77 m_verbose_level = v.value();
78 }
79
80 // Permet d'ajouter les espaces entre les appels dans la pile d'appel et
81 // d'afficher le numéro de ligne avant le chemin du fichier source.
82 // Sinon, on affiche le chemin du fichier et le numéro de ligne de manière
83 // lisible par les debuggers/IDE (path:line).
84 // Défaut = true.
85 if (const auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_CALLSTACK_HUMAN_READABLE", true)) {
86 m_human_readable = (v.value() != 0);
87 }
88 }
89
90 public:
91
92 StackTrace stackTrace(int first_function) override;
93 StackTrace stackTraceFunction(int function_index) override;
94
95 private:
96
97 Int32 m_verbose_level;
98 bool m_human_readable;
99};
100
101/*---------------------------------------------------------------------------*/
102/*---------------------------------------------------------------------------*/
103
105stackTrace(int first_function)
106{
107 StringBuilder message;
108 FixedStackFrameArray stack_frames;
109 constexpr size_t hexa_buf_size = 100;
110 char hexa[hexa_buf_size + 1];
111
112 backward::StackTrace st;
113 st.skip_n_firsts(first_function);
114 st.load_here(64);
115
116 backward::TraceResolver tr;
117 tr.load_stacktrace(st);
118
119 backward::SnippetFactory sf;
120
121 for (size_t i = 0; i < st.size(); ++i) {
122 backward::ResolvedTrace trace = tr.resolve(st[i]);
123 message += " ";
124 snprintf(hexa, hexa_buf_size, "%14p", trace.addr);
125 message += hexa;
126 message += " ";
127 message += trace.object_function;
128
129 UInt32 src_line = trace.source.line;
130
131 if (m_verbose_level > 0 && src_line > 0) {
132 bool arcane_function = String(trace.object_function).startsWith("Arcane");
133 if (m_verbose_level > 1 || !arcane_function) {
134 auto lines = sf.get_snippet(trace.source.filename, src_line, 5);
135 if (m_human_readable) {
136 message += "\n Line: ";
137 message += src_line;
138 message += " -- File: ";
139 message += trace.source.filename;
140 }
141 else {
142 message += "\n ";
143 message += trace.source.filename;
144 message += ":";
145 message += src_line;
146 }
147 if (m_verbose_level > 3 || (m_verbose_level > 2 && !arcane_function)) {
148 for (const auto& [line_num, line] : lines) {
149 message += (line_num == src_line ? "\n >>> " : "\n ");
150 message += line_num;
151 message += ": ";
152 message += line;
153 }
154 }
155 }
156 }
157
158 if (m_human_readable)
159 message += "\n\n";
160 else
161 message += "\n";
162
163 stack_frames.addFrame(StackFrame(reinterpret_cast<intptr_t>(trace.addr)));
164 }
165
166 return { stack_frames, message };
167}
168
169/*---------------------------------------------------------------------------*/
170/*---------------------------------------------------------------------------*/
171
173stackTraceFunction(int function_index)
174{
175 backward::StackTrace st;
176 st.skip_n_firsts(function_index);
177 st.load_here(1);
178
179 if (st.size() < 1) {
180 return {};
181 }
182 backward::TraceResolver tr;
183 tr.load_stacktrace(st);
184
185 backward::ResolvedTrace trace = tr.resolve(st[0]);
186
187 return { trace.object_function };
188}
189
190/*---------------------------------------------------------------------------*/
191/*---------------------------------------------------------------------------*/
192
194 ServiceProperty("BackwardCppStackTraceService", ST_Application),
196
197ARCANE_DI_REGISTER_PROVIDER(BackwardCppStackTraceService,
198 DependencyInjection::ProviderProperty("BackwardCppStackTraceService"),
199 ARCANE_DI_INTERFACES(IStackTraceService),
200 ARCANE_DI_CONSTRUCTOR(ITraceMng*));
201
202/*---------------------------------------------------------------------------*/
203/*---------------------------------------------------------------------------*/
204
205} // End namespace Arcane
206
207/*---------------------------------------------------------------------------*/
208/*---------------------------------------------------------------------------*/
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.
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.
Classe template pour convertir un type.
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,...
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
Interface d'un service de trace des appels de fonctions.
Interface du gestionnaire de traces.
IApplication * application() const
Accès à l'application IApplication associé.
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
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
#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.