BDE 4.14.0 Production release
Loading...
Searching...
No Matches
balst_resolverimpl_xcoff.h
Go to the documentation of this file.
1/// @file balst_resolverimpl_xcoff.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balst_resolverimpl_xcoff.h -*-C++-*-
8#ifndef INCLUDED_BALST_RESOLVERIMPL_XCOFF
9#define INCLUDED_BALST_RESOLVERIMPL_XCOFF
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup balst_resolverimpl_xcoff balst_resolverimpl_xcoff
15/// @brief Provide a mechanism to resolve xcoff symbols in a stack trace.
16/// @addtogroup bal
17/// @{
18/// @addtogroup balst
19/// @{
20/// @addtogroup balst_resolverimpl_xcoff
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#balst_resolverimpl_xcoff-purpose"> Purpose</a>
25/// * <a href="#balst_resolverimpl_xcoff-classes"> Classes </a>
26/// * <a href="#balst_resolverimpl_xcoff-description"> Description </a>
27/// * <a href="#balst_resolverimpl_xcoff-inline-functions"> Inline Functions </a>
28/// * <a href="#balst_resolverimpl_xcoff-usage"> Usage </a>
29///
30/// # Purpose {#balst_resolverimpl_xcoff-purpose}
31/// Provide a mechanism to resolve xcoff symbols in a stack trace.
32///
33/// # Classes {#balst_resolverimpl_xcoff-classes}
34///
35/// - balst::ResolverImpl<Xcoff>: symbol resolution for Xcoff objects
36///
37/// @see balst_resolverimpl_elf,
38/// balst_resolverimpl_windows
39///
40/// # Description {#balst_resolverimpl_xcoff-description}
41/// This component provides a class,
42/// `balst::Resolver<Xcoff>`, that, given a vector of `balst::StackTraceFrame`s
43/// that have only their `address` fields set, resolves all other fields in
44/// those frames. Xcoff objects are used on AIX platforms.
45///
46/// ## Inline Functions {#balst_resolverimpl_xcoff-inline-functions}
47///
48///
49/// Inline functions and template functions that are, in fact, called out of
50/// line are handled properly. Functions that are inlined are not represented
51/// in the stack trace, and the stack frames of the functions that called them
52/// do not have their line number information populated.
53///
54/// ## Usage {#balst_resolverimpl_xcoff-usage}
55///
56///
57/// This component is an implementation detail of `balst` and is *not* intended
58/// for direct client use. It is subject to change without notice. As such, a
59/// usage example is not provided.
60/// @}
61/** @} */
62/** @} */
63
64/** @addtogroup bal
65 * @{
66 */
67/** @addtogroup balst
68 * @{
69 */
70/** @addtogroup balst_resolverimpl_xcoff
71 * @{
72 */
73
74#include <balscm_version.h>
75
77
78#if defined(BALST_OBJECTFILEFORMAT_RESOLVER_XCOFF)
79#include <balst_stacktrace.h>
82
84
85#include <bdls_filesystemutil.h>
86
87#include <bslma_allocator.h>
88
89#include <bslmt_qlock.h>
90
91#include <bsls_assert.h>
92#include <bsls_types.h>
93
94
95struct syment; // defined in imp by included file '<syms.h>'
96union auxent; // defined in imp by included file '<syms.h>'
97
98
99namespace balst {
100
101template <typename RESOLVER_POLICY>
102class ResolverImpl;
103
104 // ===========================================
105 // class ResolverImpl<ObjectFileFormat::Xcoff>
106 // ===========================================
107
108template <>
109class ResolverImpl<ObjectFileFormat::Xcoff> {
110 // This class is for resolving symbols in Xcoff executables. Given a
111 // vector of 'StackTraceFrame's that have only their 'address' fields
112 // set, it resolves all other fields in those frames. Xcoff objects are
113 // used on AIX platforms. Note that all methods, including the
114 // constructor, are private except for that static method 'resolve' which
115 // constructs and destroys the object.
116
117 public:
118 // PUBLIC TYPES
119 typedef bsls::Types::IntPtr IntPtr; // 32 bit signed on 32 bit, 64 bit
120 // signed on 64 bit
121 typedef bsls::Types::UintPtr UintPtr; // 32 bit unsigned on 32 bit, 64 bit
122 // unsigned on 64 bit
123
124 typedef bsls::Types::Int64 Int64;
125 typedef bsls::Types::Uint64 Uint64;
126
127 typedef bdls::FilesystemUtil::Offset // Usually used for offsets in a
128 Offset; // file, absolute or relative.
129
130 private:
131 // TYPES
132 struct AuxInfo; // Internal -- fleshed out in the
133 // implementation file
134 struct LoadAuxInfosInfo; // Internal -- fleshed out in the
135 // implementation file
136
137 enum FindIncludeFileFlags {
138 // flags returned by 'findIncludeFile'
139
140 k_USE_INCLUDE_SOURCE_FILE_NAME = 0x1,
141 k_SUPPRESS_LINE_NUMBER = 0x2
142 };
143
144 // DATA
145 Resolver_FileHelper *d_helper; // helper for reading files
146
147 StackTrace *d_stackTrace_p; // pointer to stack trace object
148 // to be populated by resolution.
149 // Note only the 'address' fields
150 // are initialized at the start,
151 // our goal is to initialize all
152 // the other fields. Held, not
153 // owned.
154
155 StackTraceFrame **d_segFramePtrs_p; // pointers to stack trace frames
156 // contained in 'd_stackTrace_p'
157 // listing only those frames
158 // whose 'address' fields point
159 // into the current segment
160
161 const void **d_segAddresses_p; // the 'address' fields from
162 // 'd_segFramePtrs_p' in 1-1
163 // correspondence, note this
164 // duplication of information is
165 // a performance optimization
166
167 AuxInfo *d_segAuxInfos_p; // array of aux infos (AuxInfo is
168 // a struct private to this
169 // class, defined in the imp) in
170 // 1-1 correspondence with the
171 // entries of 'd_segFramePtrs_p'
172
173 int d_numCurrAddresses;// number of 'address' fields in
174 // 'd_stackTrace_p' that point
175 // into the current segment, also
176 // the length of
177 // 'd_segFramePtrs_p',
178 // 'd_segAddresses_p', and
179 // 'd_segAuxInfos_p', note all 3
180 // are allocated to have
181 // 'd_stackTrace_p->length()'
182 // (worst case) length
183
184 char *d_scratchBuf_p; // scratch buffer
185
186 char *d_symbolBuf_p; // buffer for reading symbols
187
188 Offset d_virtualToPhysicalOffset;
189 // translation from an address
190 // given in the file to an
191 // address in memory for the
192 // current segment
193
194 Offset d_archiveMemberOffset;
195 // archive member offset, or 0 if
196 // the segment is not an archive
197 // member
198
199 Offset d_archiveMemberSize;
200 // archive member size, or size
201 // of the whole file if the
202 // segment is not an archive
203 // member
204
205 Offset d_symTableOffset; // absolute offset of symbol
206 // table in the current file
207
208 Offset d_stringTableOffset;
209 // absolute offset of string
210 // table in the current file
211
212 bool d_demangle; // flag indicating whether
213 // demangling is to be done
214
216 d_hbpAlloc; // heap bypass allocator, all
217 // memory allocated by this
218 // object will be freed when this
219 // allocator is destroyed.
220
221 static bslmt::QLock s_demangleQLock; // 'QLock' to guard access to
222 // the non-thread-safe 'Demangle'
223 // function.
224
225 private:
226 // NOT IMPLEMENTED
227 ResolverImpl(const ResolverImpl&);
228 ResolverImpl& operator=(const ResolverImpl&);
229
230 // PRIVATE CREATORS
231 ResolverImpl(StackTrace *stackTrace,
232 bool demangle);
233 // Create an stack trace reolver that can populate other fields of the
234 // specified 'stackFrames' object given previously populated 'address'
235 // fields. Specify 'demangle', which indicates whether demangling of
236 // symbols is to occur, and 'basicAllocator', which is to be used for
237 // memory allocation. Note that the behavior is undefined if
238 // 'basicAllocator' is 0 or unspecified, the intention is that it
239 // should be of type 'bdema::HeapByPassAllocator'.
240
241 ~ResolverImpl();
242 // Destroy this stack trace resolver object.
243
244 // PRIVATE MANIPULATORS
245 bslma::Allocator *allocator();
246 // Return a pointer to this object's heap bypass allocator.
247
248 int findArchiveMember(const char *memberName);
249 // Locate the archive member with the specified 'memberName' in the
250 // current archive file and save the member's offset from the beginning
251 // of the archive and the member's size. Return zero on success, and a
252 // negative value otherwise. Note that this is never called on an
253 // executable, only on archives.
254
255 Offset findCsectIndex(const char *symbolAddress,
256 const char *csectEndAddress,
257 Offset primarySymIndex);
258 // Iterate through all the addresses in d_segAddresses_p, returning the
259 // specified 'primarySymIndex', which is the index of the current
260 // symbol, if any of them are in the range
261 // '[symbolAddress, csectEndAddress)' and 'UintPtr(-1)' otherwise.
262
263 int findIncludeFile(syment *includeSymEnt,
264 Offset firstLineNumberOffset,
265 Offset lineNumberOffset,
266 Offset symStartIndex,
267 Offset symEndIndex);
268 // Read the portion of the symbol table of the current segment starting
269 // at the specified 'symStartIndex' and ending at the specified
270 // 'symEndIndex' to determine if the specified 'lineNumberOffset' is in
271 // an include file. Return a positive value which is a bitwise or of
272 // the appropriate 'FindIncludeFileFlags' if found, 0 if not found, and
273 // a negative value if an error is encountered. The positive value
274 // returned on success is a bitwise or of the flags defined by enum
275 // 'FindIncludeFileFlags' defined in the class, indicating whether the
276 // file was found, and whether the line number we have (which is not
277 // passed to this routine) is absolute or relative. Note that the line
278 // numbers corresponding to include files are sometimes absolute, while
279 // other line numbers are relative to the beginning of the function in
280 // which they occur. Also note that this routine is called immediately
281 // after 'findLineNumber'.
282
283 int findLineNumber(int *outLineNumber_p,
284 Offset *outLineNumberOffset_p,
285 Offset lineBufStartOffset,
286 const void *segAddress);
287 // Find a line number and line number offset of the source that refers
288 // to the specified 'address', and load the results into the specified
289 // '*outLineNumber_p' and '*outLineNumberOffset_p'. Begin the search
290 // at the specified 'lineBufStartOffset' in the file and end either at
291 // the end of that function, at the end of the archive member, or the
292 // end of the file. Return zero on success, and a nonzero value
293 // otherwise. Note that the line number may be either relative to the
294 // beginning of the function, or absolute (see 'findIncludeFile').
295 // Note that 'lineBufStartOffset' points to the beginning of line
296 // number records describing the function containing the code
297 // 'segAddress' refers to.
298
299 void loadAuxInfos(const LoadAuxInfosInfo *laiInfo,
300 const char *functionBeginAddress,
301 const char *functionEndAddress);
302 // Iterate through 'd_segAddresses_p' and, for each address that refers
303 // to code in the function specified by 'functionBeginAddress' and
304 // 'functionEndAddress', initialize the 'offsetFromSymbol' field of the
305 // corresponding stack trace frame, and initialize the corresponding
306 // 'AuxInfo' struct with information from variables local to the
307 // calling 'loadSymbols' function accessed through pointers in the
308 // specified 'laiInfo' struct.
309
310 int loadSymbols(Offset numSyms,
311 int textSectionNum);
312 // Read the specified 'numSym' symbols from the symbol table associated
313 // with this segment, skipping those symbols not associated with the
314 // text section indicated by the specified 'textSectionNum'. Return 0
315 // on success and a non-zero value otherwise.
316
317 const char *getSourceName(const auxent *sourceAuxent);
318 // Allocate memory for, and return a pointer to, a string containing
319 // the name of the source file referred to by the specified
320 // 'sourceAuxent'.
321
322 const char *getSymbolName(const syment *sourceSyment);
323 // Allocate memory for, and return a pointer to, a string containing
324 // the name of the symbol defined by the specified 'sourceSyment'.
325 // Note the symbol is sometimes a function name, sometimes a source
326 // file name.
327
328 int resolveSegment(void *segmentPtr,
329 UintPtr segmentSize,
330 const char *libraryFileName,
331 const char *displayFileName,
332 const char *archiveMemberName);
333 // Populate those stack trace frames whose 'address' fields reside
334 // within the segment specfied by 'segmentPtr' and 'segmentSize'. The
335 // segment is in the specified 'libraryFileName', with the specified
336 // 'archiveMemberName'. Specify the 'displayFileName' used to identify
337 // the library file name in the stack trace. Note that
338 // 'displayFileName' may be different from 'libraryFileName' because
339 // AIX truncates the filename of the executable file to be 32 chars
340 // long, so we use another means to open the executable file. Note
341 // that if 'archiveMemberName' is unspecified, the whole library file
342 // has a single segment.
343
344 public:
345 // PUBLIC CLASS METHODS
346 static
347 int resolve(StackTrace *stackTrace,
348 bool demangle);
349 // Populate information for the specified 'stackFrames', a vector of
350 // stack trace frames in a stack trace object. Specify 'demangle', to
351 // determine whether demangling is to occur, and 'basicAllocator',
352 // which is to be used for memory allocation. The behavior is
353 // undefined unless all the 'address' field in 'stackFrames' are valid
354 // and other fields are invalid, and 'basicAllocator != 0'.
355
356 static inline
357 int testFunc();
358 // For testing only. Do some random garbage and return a line number
359 // from within the routine.
360};
361
362// ============================================================================
363// INLINE FUNCTION DEFINITIONS
364// ============================================================================
365
366 // ------------------
367 // class ResolverImpl
368 // ------------------
369
370// PRIVATE MANIPULATORS
371inline
372bslma::Allocator *ResolverImpl<ObjectFileFormat::Xcoff>::allocator()
373{
374 return &d_hbpAlloc;
375}
376
377// CLASS METHODS
378inline
379int ResolverImpl<ObjectFileFormat::Xcoff>::testFunc()
380{
381 // Do some random garbage to generate some code, then return a line number
382 // within this routine
383
384 int line = 0, lineCopy = 0;
385
386 for (int i = 0; true; ++i) {
387 BSLS_ASSERT_OPT(line == lineCopy);
388
389 const int loopGuard = 0x8edf0000; // garbage with a lot of trailing
390 // 0's.
391 const int mask = 0xa72c3dca; // pure garbage
392
393 enum { k_LINE = __LINE__ };
394
395 for (int i = 0; !(i & loopGuard); ++i) {
396 line ^= (i & mask);
397 }
398
399 // The above loop will leave the value of 'line' unchanged.
400
401 BSLS_ASSERT_OPT(line == lineCopy);
402
403 if (line != 0) {
404 break;
405 }
406
407 line = k_LINE;
408 lineCopy = line;
409 }
410
411 return line;
412}
413
414} // close package namespace
415
416
417#endif
418#endif
419
420// ----------------------------------------------------------------------------
421// Copyright 2015 Bloomberg Finance L.P.
422//
423// Licensed under the Apache License, Version 2.0 (the "License");
424// you may not use this file except in compliance with the License.
425// You may obtain a copy of the License at
426//
427// http://www.apache.org/licenses/LICENSE-2.0
428//
429// Unless required by applicable law or agreed to in writing, software
430// distributed under the License is distributed on an "AS IS" BASIS,
431// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
432// See the License for the specific language governing permissions and
433// limitations under the License.
434// ----------------------------- END-OF-FILE ----------------------------------
435
436/** @} */
437/** @} */
438/** @} */
Definition bdlma_heapbypassallocator.h:157
Definition bslma_allocator.h:457
#define BSLS_ASSERT_OPT(X)
Definition bsls_assert.h:1856
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balst_objectfileformat.h:161
Definition bslmt_qlock.h:271
std::size_t UintPtr
Definition bsls_types.h:126
unsigned long long Uint64
Definition bsls_types.h:137
std::ptrdiff_t IntPtr
Definition bsls_types.h:130
long long Int64
Definition bsls_types.h:132