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