Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef LulMain_h
8 : #define LulMain_h
9 :
10 : #include "PlatformMacros.h"
11 : #include "mozilla/Atomics.h"
12 : #include "mozilla/MemoryReporting.h"
13 :
14 : // LUL: A Lightweight Unwind Library.
15 : // This file provides the end-user (external) interface for LUL.
16 :
17 : // Some comments about naming in the implementation. These are safe
18 : // to ignore if you are merely using LUL, but are important if you
19 : // hack on its internals.
20 : //
21 : // Debuginfo readers in general have tended to use the word "address"
22 : // to mean several different things. This sometimes makes them
23 : // difficult to understand and maintain. LUL tries hard to avoid
24 : // using the word "address" and instead uses the following more
25 : // precise terms:
26 : //
27 : // * SVMA ("Stated Virtual Memory Address"): this is an address of a
28 : // symbol (etc) as it is stated in the symbol table, or other
29 : // metadata, of an object. Such values are typically small and
30 : // start from zero or thereabouts, unless the object has been
31 : // prelinked.
32 : //
33 : // * AVMA ("Actual Virtual Memory Address"): this is the address of a
34 : // symbol (etc) in a running process, that is, once the associated
35 : // object has been mapped into a process. Such values are typically
36 : // much larger than SVMAs, since objects can get mapped arbitrarily
37 : // far along the address space.
38 : //
39 : // * "Bias": the difference between AVMA and SVMA for a given symbol
40 : // (specifically, AVMA - SVMA). The bias is always an integral
41 : // number of pages. Once we know the bias for a given object's
42 : // text section (for example), we can compute the AVMAs of all of
43 : // its text symbols by adding the bias to their SVMAs.
44 : //
45 : // * "Image address": typically, to read debuginfo from an object we
46 : // will temporarily mmap in the file so as to read symbol tables
47 : // etc. Addresses in this temporary mapping are called "Image
48 : // addresses". Note that the temporary mapping is entirely
49 : // unrelated to the mappings of the file that the dynamic linker
50 : // must perform merely in order to get the program to run. Hence
51 : // image addresses are unrelated to either SVMAs or AVMAs.
52 :
53 :
54 : namespace lul {
55 :
56 : // A machine word plus validity tag.
57 : class TaggedUWord {
58 : public:
59 : // RUNS IN NO-MALLOC CONTEXT
60 : // Construct a valid one.
61 0 : explicit TaggedUWord(uintptr_t w)
62 0 : : mValue(w)
63 0 : , mValid(true)
64 0 : {}
65 :
66 : // RUNS IN NO-MALLOC CONTEXT
67 : // Construct an invalid one.
68 0 : TaggedUWord()
69 0 : : mValue(0)
70 0 : , mValid(false)
71 0 : {}
72 :
73 : // RUNS IN NO-MALLOC CONTEXT
74 0 : TaggedUWord operator+(TaggedUWord rhs) const {
75 0 : return (Valid() && rhs.Valid()) ? TaggedUWord(Value() + rhs.Value())
76 0 : : TaggedUWord();
77 : }
78 :
79 : // RUNS IN NO-MALLOC CONTEXT
80 0 : TaggedUWord operator-(TaggedUWord rhs) const {
81 0 : return (Valid() && rhs.Valid()) ? TaggedUWord(Value() - rhs.Value())
82 0 : : TaggedUWord();
83 : }
84 :
85 : // RUNS IN NO-MALLOC CONTEXT
86 0 : TaggedUWord operator&(TaggedUWord rhs) const {
87 0 : return (Valid() && rhs.Valid()) ? TaggedUWord(Value() & rhs.Value())
88 0 : : TaggedUWord();
89 : }
90 :
91 : // RUNS IN NO-MALLOC CONTEXT
92 0 : TaggedUWord operator|(TaggedUWord rhs) const {
93 0 : return (Valid() && rhs.Valid()) ? TaggedUWord(Value() | rhs.Value())
94 0 : : TaggedUWord();
95 : }
96 :
97 : // RUNS IN NO-MALLOC CONTEXT
98 0 : TaggedUWord CmpGEs(TaggedUWord rhs) const {
99 0 : if (Valid() && rhs.Valid()) {
100 0 : intptr_t s1 = (intptr_t)Value();
101 0 : intptr_t s2 = (intptr_t)rhs.Value();
102 0 : return TaggedUWord(s1 >= s2 ? 1 : 0);
103 : }
104 0 : return TaggedUWord();
105 : }
106 :
107 : // RUNS IN NO-MALLOC CONTEXT
108 0 : TaggedUWord operator<<(TaggedUWord rhs) const {
109 0 : if (Valid() && rhs.Valid()) {
110 0 : uintptr_t shift = rhs.Value();
111 0 : if (shift < 8 * sizeof(uintptr_t))
112 0 : return TaggedUWord(Value() << shift);
113 : }
114 0 : return TaggedUWord();
115 : }
116 :
117 : // RUNS IN NO-MALLOC CONTEXT
118 : // Is equal? Note: non-validity on either side gives non-equality.
119 : bool operator==(TaggedUWord other) const {
120 : return (mValid && other.Valid()) ? (mValue == other.Value()) : false;
121 : }
122 :
123 : // RUNS IN NO-MALLOC CONTEXT
124 : // Is it word-aligned?
125 0 : bool IsAligned() const {
126 0 : return mValid && (mValue & (sizeof(uintptr_t)-1)) == 0;
127 : }
128 :
129 : // RUNS IN NO-MALLOC CONTEXT
130 0 : uintptr_t Value() const { return mValue; }
131 :
132 : // RUNS IN NO-MALLOC CONTEXT
133 0 : bool Valid() const { return mValid; }
134 :
135 : private:
136 : uintptr_t mValue;
137 : bool mValid;
138 : };
139 :
140 :
141 : // The registers, with validity tags, that will be unwound.
142 :
143 0 : struct UnwindRegs {
144 : #if defined(GP_ARCH_arm)
145 : TaggedUWord r7;
146 : TaggedUWord r11;
147 : TaggedUWord r12;
148 : TaggedUWord r13;
149 : TaggedUWord r14;
150 : TaggedUWord r15;
151 : #elif defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
152 : TaggedUWord xbp;
153 : TaggedUWord xsp;
154 : TaggedUWord xip;
155 : #else
156 : # error "Unknown plat"
157 : #endif
158 : };
159 :
160 :
161 : // The maximum number of bytes in a stack snapshot. This value can be increased
162 : // if necessary, but testing showed that 160k is enough to obtain good
163 : // backtraces on x86_64 Linux. Most backtraces fit comfortably into 4-8k of
164 : // stack space, but we do have some very deep stacks occasionally. Please see
165 : // the comments in DoNativeBacktrace as to why it's OK to have this value be so
166 : // large.
167 : static const size_t N_STACK_BYTES = 160*1024;
168 :
169 : // The stack chunk image that will be unwound.
170 : struct StackImage {
171 : // [start_avma, +len) specify the address range in the buffer.
172 : // Obviously we require 0 <= len <= N_STACK_BYTES.
173 : uintptr_t mStartAvma;
174 : size_t mLen;
175 : uint8_t mContents[N_STACK_BYTES];
176 : };
177 :
178 :
179 : // Statistics collection for the unwinder.
180 : template<typename T>
181 : class LULStats {
182 : public:
183 0 : LULStats()
184 : : mContext(0)
185 : , mCFI(0)
186 0 : , mFP(0)
187 0 : {}
188 :
189 : template <typename S>
190 : explicit LULStats(const LULStats<S>& aOther)
191 : : mContext(aOther.mContext)
192 : , mCFI(aOther.mCFI)
193 : , mFP(aOther.mFP)
194 : {}
195 :
196 : template <typename S>
197 0 : LULStats<T>& operator=(const LULStats<S>& aOther)
198 : {
199 0 : mContext = aOther.mContext;
200 0 : mCFI = aOther.mCFI;
201 0 : mFP = aOther.mFP;
202 0 : return *this;
203 : }
204 :
205 : template <typename S>
206 0 : uint32_t operator-(const LULStats<S>& aOther) {
207 0 : return (mContext - aOther.mContext) +
208 0 : (mCFI - aOther.mCFI) + (mFP - aOther.mFP);
209 : }
210 :
211 : T mContext; // Number of context frames
212 : T mCFI; // Number of CFI/EXIDX frames
213 : T mFP; // Number of frame-pointer recovered frames
214 : };
215 :
216 :
217 : // The core unwinder library class. Just one of these is needed, and
218 : // it can be shared by multiple unwinder threads.
219 : //
220 : // The library operates in one of two modes.
221 : //
222 : // * Admin mode. The library is this state after creation. In Admin
223 : // mode, no unwinding may be performed. It is however allowable to
224 : // perform administrative tasks -- primarily, loading of unwind info
225 : // -- in this mode. In particular, it is safe for the library to
226 : // perform dynamic memory allocation in this mode. Safe in the
227 : // sense that there is no risk of deadlock against unwinding threads
228 : // that might -- because of where they have been sampled -- hold the
229 : // system's malloc lock.
230 : //
231 : // * Unwind mode. In this mode, calls to ::Unwind may be made, but
232 : // nothing else. ::Unwind guarantees not to make any dynamic memory
233 : // requests, so as to guarantee that the calling thread won't
234 : // deadlock in the case where it already holds the system's malloc lock.
235 : //
236 : // The library is created in Admin mode. After debuginfo is loaded,
237 : // the caller must switch it into Unwind mode by calling
238 : // ::EnableUnwinding. There is no way to switch it back to Admin mode
239 : // after that. To safely switch back to Admin mode would require the
240 : // caller (or other external agent) to guarantee that there are no
241 : // pending ::Unwind calls.
242 :
243 : class PriMap;
244 : class SegArray;
245 : class UniqueStringUniverse;
246 :
247 : class LUL {
248 : public:
249 : // Create; supply a logging sink. Sets the object in Admin mode.
250 : explicit LUL(void (*aLog)(const char*));
251 :
252 : // Destroy. Caller is responsible for ensuring that no other
253 : // threads are in Unwind calls. All resources are freed and all
254 : // registered unwinder threads are deregistered. Can be called
255 : // either in Admin or Unwind mode.
256 : ~LUL();
257 :
258 : // Notify the library that unwinding is now allowed and so
259 : // admin-mode calls are no longer allowed. The object is initially
260 : // created in admin mode. The only possible transition is
261 : // admin->unwinding, therefore.
262 : void EnableUnwinding();
263 :
264 : // Notify of a new r-x mapping, and load the associated unwind info.
265 : // The filename is strdup'd and used for debug printing. If
266 : // aMappedImage is NULL, this function will mmap/munmap the file
267 : // itself, so as to be able to read the unwind info. If
268 : // aMappedImage is non-NULL then it is assumed to point to a
269 : // called-supplied and caller-managed mapped image of the file.
270 : // May only be called in Admin mode.
271 : void NotifyAfterMap(uintptr_t aRXavma, size_t aSize,
272 : const char* aFileName, const void* aMappedImage);
273 :
274 : // In rare cases we know an executable area exists but don't know
275 : // what the associated file is. This call notifies LUL of such
276 : // areas. This is important for correct functioning of stack
277 : // scanning and of the x86-{linux,android} special-case
278 : // __kernel_syscall function handling.
279 : // This must be called only after the code area in
280 : // question really has been mapped.
281 : // May only be called in Admin mode.
282 : void NotifyExecutableArea(uintptr_t aRXavma, size_t aSize);
283 :
284 : // Notify that a mapped area has been unmapped; discard any
285 : // associated unwind info. Acquires mRWlock for writing. Note that
286 : // to avoid segfaulting the stack-scan unwinder, which inspects code
287 : // areas, this must be called before the code area in question is
288 : // really unmapped. Note that, unlike NotifyAfterMap(), this
289 : // function takes the start and end addresses of the range to be
290 : // unmapped, rather than a start and a length parameter. This is so
291 : // as to make it possible to notify an unmap for the entire address
292 : // space using a single call.
293 : // May only be called in Admin mode.
294 : void NotifyBeforeUnmap(uintptr_t aAvmaMin, uintptr_t aAvmaMax);
295 :
296 : // Apply NotifyBeforeUnmap to the entire address space. This causes
297 : // LUL to discard all unwind and executable-area information for the
298 : // entire address space.
299 : // May only be called in Admin mode.
300 : void NotifyBeforeUnmapAll() {
301 : NotifyBeforeUnmap(0, UINTPTR_MAX);
302 : }
303 :
304 : // Returns the number of mappings currently registered.
305 : // May only be called in Admin mode.
306 : size_t CountMappings();
307 :
308 : // Unwind |aStackImg| starting with the context in |aStartRegs|.
309 : // Write the number of frames recovered in *aFramesUsed. Put
310 : // the PC values in aFramePCs[0 .. *aFramesUsed-1] and
311 : // the SP values in aFrameSPs[0 .. *aFramesUsed-1].
312 : // |aFramesAvail| is the size of the two output arrays and hence the
313 : // largest possible value of *aFramesUsed. PC values are always
314 : // valid, and the unwind will stop when the PC becomes invalid, but
315 : // the SP values might be invalid, in which case the value zero will
316 : // be written in the relevant frameSPs[] slot.
317 : //
318 : // This function assumes that the SP values increase as it unwinds
319 : // away from the innermost frame -- that is, that the stack grows
320 : // down. It monitors SP values as it unwinds to check they
321 : // decrease, so as to avoid looping on corrupted stacks.
322 : //
323 : // May only be called in Unwind mode. Multiple threads may unwind
324 : // at once. LUL user is responsible for ensuring that no thread makes
325 : // any Admin calls whilst in Unwind mode.
326 : // MOZ_CRASHes if the calling thread is not registered for unwinding.
327 : //
328 : // The calling thread must previously have been registered via a call to
329 : // RegisterSampledThread.
330 : void Unwind(/*OUT*/uintptr_t* aFramePCs,
331 : /*OUT*/uintptr_t* aFrameSPs,
332 : /*OUT*/size_t* aFramesUsed,
333 : /*OUT*/size_t* aFramePointerFramesAcquired,
334 : size_t aFramesAvail,
335 : UnwindRegs* aStartRegs, StackImage* aStackImg);
336 :
337 : // The logging sink. Call to send debug strings to the caller-
338 : // specified destination. Can only be called by the Admin thread.
339 : void (*mLog)(const char*);
340 :
341 : // Statistics relating to unwinding. These have to be atomic since
342 : // unwinding can occur on different threads simultaneously.
343 : LULStats<mozilla::Atomic<uint32_t>> mStats;
344 :
345 : // Possibly show the statistics. This may not be called from any
346 : // registered sampling thread, since it involves I/O.
347 : void MaybeShowStats();
348 :
349 : size_t SizeOfIncludingThis(mozilla::MallocSizeOf) const;
350 :
351 : private:
352 : // The statistics counters at the point where they were last printed.
353 : LULStats<uint32_t> mStatsPrevious;
354 :
355 : // Are we in admin mode? Initially |true| but changes to |false|
356 : // once unwinding begins.
357 : bool mAdminMode;
358 :
359 : // The thread ID associated with admin mode. This is the only thread
360 : // that is allowed do perform non-Unwind calls on this object. Conversely,
361 : // no registered Unwinding thread may be the admin thread. This is so
362 : // as to clearly partition the one thread that may do dynamic memory
363 : // allocation from the threads that are being sampled, since the latter
364 : // absolutely may not do dynamic memory allocation.
365 : int mAdminThreadId;
366 :
367 : // The top level mapping from code address ranges to postprocessed
368 : // unwind info. Basically a sorted array of (addr, len, info)
369 : // records. This field is updated by NotifyAfterMap and NotifyBeforeUnmap.
370 : PriMap* mPriMap;
371 :
372 : // An auxiliary structure that records which address ranges are
373 : // mapped r-x, for the benefit of the stack scanner.
374 : SegArray* mSegArray;
375 :
376 : // A UniqueStringUniverse that holds all the strdup'd strings created
377 : // whilst reading unwind information. This is included so as to make
378 : // it possible to free them in ~LUL.
379 : UniqueStringUniverse* mUSU;
380 : };
381 :
382 :
383 : // Run unit tests on an initialised, loaded-up LUL instance, and print
384 : // summary results on |aLUL|'s logging sink. Also return the number
385 : // of tests run in *aNTests and the number that passed in
386 : // *aNTestsPassed.
387 : void
388 : RunLulUnitTests(/*OUT*/int* aNTests, /*OUT*/int*aNTestsPassed, LUL* aLUL);
389 :
390 : } // namespace lul
391 :
392 : #endif // LulMain_h
|