xref: /aosp_15_r20/external/libchrome/base/debug/stack_trace.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "base/debug/stack_trace.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <string.h>
8*635a8641SAndroid Build Coastguard Worker 
9*635a8641SAndroid Build Coastguard Worker #include <algorithm>
10*635a8641SAndroid Build Coastguard Worker #include <sstream>
11*635a8641SAndroid Build Coastguard Worker 
12*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
14*635a8641SAndroid Build Coastguard Worker 
15*635a8641SAndroid Build Coastguard Worker #if BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
16*635a8641SAndroid Build Coastguard Worker 
17*635a8641SAndroid Build Coastguard Worker #if defined(OS_LINUX) || defined(OS_ANDROID)
18*635a8641SAndroid Build Coastguard Worker #include <pthread.h>
19*635a8641SAndroid Build Coastguard Worker #include "base/process/process_handle.h"
20*635a8641SAndroid Build Coastguard Worker #include "base/threading/platform_thread.h"
21*635a8641SAndroid Build Coastguard Worker #endif
22*635a8641SAndroid Build Coastguard Worker 
23*635a8641SAndroid Build Coastguard Worker #if defined(OS_MACOSX)
24*635a8641SAndroid Build Coastguard Worker #include <pthread.h>
25*635a8641SAndroid Build Coastguard Worker #endif
26*635a8641SAndroid Build Coastguard Worker 
27*635a8641SAndroid Build Coastguard Worker #if defined(OS_LINUX) && defined(__GLIBC__)
28*635a8641SAndroid Build Coastguard Worker extern "C" void* __libc_stack_end;
29*635a8641SAndroid Build Coastguard Worker #endif
30*635a8641SAndroid Build Coastguard Worker 
31*635a8641SAndroid Build Coastguard Worker #endif  // BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
32*635a8641SAndroid Build Coastguard Worker 
33*635a8641SAndroid Build Coastguard Worker namespace base {
34*635a8641SAndroid Build Coastguard Worker namespace debug {
35*635a8641SAndroid Build Coastguard Worker 
36*635a8641SAndroid Build Coastguard Worker namespace {
37*635a8641SAndroid Build Coastguard Worker 
38*635a8641SAndroid Build Coastguard Worker #if BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
39*635a8641SAndroid Build Coastguard Worker 
40*635a8641SAndroid Build Coastguard Worker #if defined(__arm__) && defined(__GNUC__) && !defined(__clang__)
41*635a8641SAndroid Build Coastguard Worker // GCC and LLVM generate slightly different frames on ARM, see
42*635a8641SAndroid Build Coastguard Worker // https://llvm.org/bugs/show_bug.cgi?id=18505 - LLVM generates
43*635a8641SAndroid Build Coastguard Worker // x86-compatible frame, while GCC needs adjustment.
44*635a8641SAndroid Build Coastguard Worker constexpr size_t kStackFrameAdjustment = sizeof(uintptr_t);
45*635a8641SAndroid Build Coastguard Worker #else
46*635a8641SAndroid Build Coastguard Worker constexpr size_t kStackFrameAdjustment = 0;
47*635a8641SAndroid Build Coastguard Worker #endif
48*635a8641SAndroid Build Coastguard Worker 
GetNextStackFrame(uintptr_t fp)49*635a8641SAndroid Build Coastguard Worker uintptr_t GetNextStackFrame(uintptr_t fp) {
50*635a8641SAndroid Build Coastguard Worker   return reinterpret_cast<const uintptr_t*>(fp)[0] - kStackFrameAdjustment;
51*635a8641SAndroid Build Coastguard Worker }
52*635a8641SAndroid Build Coastguard Worker 
GetStackFramePC(uintptr_t fp)53*635a8641SAndroid Build Coastguard Worker uintptr_t GetStackFramePC(uintptr_t fp) {
54*635a8641SAndroid Build Coastguard Worker   return reinterpret_cast<const uintptr_t*>(fp)[1];
55*635a8641SAndroid Build Coastguard Worker }
56*635a8641SAndroid Build Coastguard Worker 
IsStackFrameValid(uintptr_t fp,uintptr_t prev_fp,uintptr_t stack_end)57*635a8641SAndroid Build Coastguard Worker bool IsStackFrameValid(uintptr_t fp, uintptr_t prev_fp, uintptr_t stack_end) {
58*635a8641SAndroid Build Coastguard Worker   // With the stack growing downwards, older stack frame must be
59*635a8641SAndroid Build Coastguard Worker   // at a greater address that the current one.
60*635a8641SAndroid Build Coastguard Worker   if (fp <= prev_fp) return false;
61*635a8641SAndroid Build Coastguard Worker 
62*635a8641SAndroid Build Coastguard Worker   // Assume huge stack frames are bogus.
63*635a8641SAndroid Build Coastguard Worker   if (fp - prev_fp > 100000) return false;
64*635a8641SAndroid Build Coastguard Worker 
65*635a8641SAndroid Build Coastguard Worker   // Check alignment.
66*635a8641SAndroid Build Coastguard Worker   if (fp & (sizeof(uintptr_t) - 1)) return false;
67*635a8641SAndroid Build Coastguard Worker 
68*635a8641SAndroid Build Coastguard Worker   if (stack_end) {
69*635a8641SAndroid Build Coastguard Worker     // Both fp[0] and fp[1] must be within the stack.
70*635a8641SAndroid Build Coastguard Worker     if (fp > stack_end - 2 * sizeof(uintptr_t)) return false;
71*635a8641SAndroid Build Coastguard Worker 
72*635a8641SAndroid Build Coastguard Worker     // Additional check to filter out false positives.
73*635a8641SAndroid Build Coastguard Worker     if (GetStackFramePC(fp) < 32768) return false;
74*635a8641SAndroid Build Coastguard Worker   }
75*635a8641SAndroid Build Coastguard Worker 
76*635a8641SAndroid Build Coastguard Worker   return true;
77*635a8641SAndroid Build Coastguard Worker };
78*635a8641SAndroid Build Coastguard Worker 
79*635a8641SAndroid Build Coastguard Worker // ScanStackForNextFrame() scans the stack for a valid frame to allow unwinding
80*635a8641SAndroid Build Coastguard Worker // past system libraries. Only supported on Linux where system libraries are
81*635a8641SAndroid Build Coastguard Worker // usually in the middle of the trace:
82*635a8641SAndroid Build Coastguard Worker //
83*635a8641SAndroid Build Coastguard Worker //   TraceStackFramePointers
84*635a8641SAndroid Build Coastguard Worker //   <more frames from Chrome>
85*635a8641SAndroid Build Coastguard Worker //   base::WorkSourceDispatch   <-- unwinding stops (next frame is invalid),
86*635a8641SAndroid Build Coastguard Worker //   g_main_context_dispatch        ScanStackForNextFrame() is called
87*635a8641SAndroid Build Coastguard Worker //   <more frames from glib>
88*635a8641SAndroid Build Coastguard Worker //   g_main_context_iteration
89*635a8641SAndroid Build Coastguard Worker //   base::MessagePumpGlib::Run <-- ScanStackForNextFrame() finds valid frame,
90*635a8641SAndroid Build Coastguard Worker //   base::RunLoop::Run             unwinding resumes
91*635a8641SAndroid Build Coastguard Worker //   <more frames from Chrome>
92*635a8641SAndroid Build Coastguard Worker //   __libc_start_main
93*635a8641SAndroid Build Coastguard Worker //
94*635a8641SAndroid Build Coastguard Worker // For stack scanning to be efficient it's very important for the thread to
95*635a8641SAndroid Build Coastguard Worker // be started by Chrome. In that case we naturally terminate unwinding once
96*635a8641SAndroid Build Coastguard Worker // we reach the origin of the stack (i.e. GetStackEnd()). If the thread is
97*635a8641SAndroid Build Coastguard Worker // not started by Chrome (e.g. Android's main thread), then we end up always
98*635a8641SAndroid Build Coastguard Worker // scanning area at the origin of the stack, wasting time and not finding any
99*635a8641SAndroid Build Coastguard Worker // frames (since Android libraries don't have frame pointers).
100*635a8641SAndroid Build Coastguard Worker //
101*635a8641SAndroid Build Coastguard Worker // ScanStackForNextFrame() returns 0 if it couldn't find a valid frame
102*635a8641SAndroid Build Coastguard Worker // (or if stack scanning is not supported on the current platform).
ScanStackForNextFrame(uintptr_t fp,uintptr_t stack_end)103*635a8641SAndroid Build Coastguard Worker uintptr_t ScanStackForNextFrame(uintptr_t fp, uintptr_t stack_end) {
104*635a8641SAndroid Build Coastguard Worker #if defined(OS_LINUX)
105*635a8641SAndroid Build Coastguard Worker   // Enough to resume almost all prematurely terminated traces.
106*635a8641SAndroid Build Coastguard Worker   constexpr size_t kMaxStackScanArea = 8192;
107*635a8641SAndroid Build Coastguard Worker 
108*635a8641SAndroid Build Coastguard Worker   if (!stack_end) {
109*635a8641SAndroid Build Coastguard Worker     // Too dangerous to scan without knowing where the stack ends.
110*635a8641SAndroid Build Coastguard Worker     return 0;
111*635a8641SAndroid Build Coastguard Worker   }
112*635a8641SAndroid Build Coastguard Worker 
113*635a8641SAndroid Build Coastguard Worker   fp += sizeof(uintptr_t);  // current frame is known to be invalid
114*635a8641SAndroid Build Coastguard Worker   uintptr_t last_fp_to_scan = std::min(fp + kMaxStackScanArea, stack_end) -
115*635a8641SAndroid Build Coastguard Worker                                   sizeof(uintptr_t);
116*635a8641SAndroid Build Coastguard Worker   for (;fp <= last_fp_to_scan; fp += sizeof(uintptr_t)) {
117*635a8641SAndroid Build Coastguard Worker     uintptr_t next_fp = GetNextStackFrame(fp);
118*635a8641SAndroid Build Coastguard Worker     if (IsStackFrameValid(next_fp, fp, stack_end)) {
119*635a8641SAndroid Build Coastguard Worker       // Check two frames deep. Since stack frame is just a pointer to
120*635a8641SAndroid Build Coastguard Worker       // a higher address on the stack, it's relatively easy to find
121*635a8641SAndroid Build Coastguard Worker       // something that looks like one. However two linked frames are
122*635a8641SAndroid Build Coastguard Worker       // far less likely to be bogus.
123*635a8641SAndroid Build Coastguard Worker       uintptr_t next2_fp = GetNextStackFrame(next_fp);
124*635a8641SAndroid Build Coastguard Worker       if (IsStackFrameValid(next2_fp, next_fp, stack_end)) {
125*635a8641SAndroid Build Coastguard Worker         return fp;
126*635a8641SAndroid Build Coastguard Worker       }
127*635a8641SAndroid Build Coastguard Worker     }
128*635a8641SAndroid Build Coastguard Worker   }
129*635a8641SAndroid Build Coastguard Worker #endif  // defined(OS_LINUX)
130*635a8641SAndroid Build Coastguard Worker 
131*635a8641SAndroid Build Coastguard Worker   return 0;
132*635a8641SAndroid Build Coastguard Worker }
133*635a8641SAndroid Build Coastguard Worker 
134*635a8641SAndroid Build Coastguard Worker // Links stack frame |fp| to |parent_fp|, so that during stack unwinding
135*635a8641SAndroid Build Coastguard Worker // TraceStackFramePointers() visits |parent_fp| after visiting |fp|.
136*635a8641SAndroid Build Coastguard Worker // Both frame pointers must come from __builtin_frame_address().
137*635a8641SAndroid Build Coastguard Worker // Returns previous stack frame |fp| was linked to.
LinkStackFrames(void * fpp,void * parent_fp)138*635a8641SAndroid Build Coastguard Worker void* LinkStackFrames(void* fpp, void* parent_fp) {
139*635a8641SAndroid Build Coastguard Worker   uintptr_t fp = reinterpret_cast<uintptr_t>(fpp) - kStackFrameAdjustment;
140*635a8641SAndroid Build Coastguard Worker   void* prev_parent_fp = reinterpret_cast<void**>(fp)[0];
141*635a8641SAndroid Build Coastguard Worker   reinterpret_cast<void**>(fp)[0] = parent_fp;
142*635a8641SAndroid Build Coastguard Worker   return prev_parent_fp;
143*635a8641SAndroid Build Coastguard Worker }
144*635a8641SAndroid Build Coastguard Worker 
145*635a8641SAndroid Build Coastguard Worker #endif  // BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
146*635a8641SAndroid Build Coastguard Worker 
147*635a8641SAndroid Build Coastguard Worker }  // namespace
148*635a8641SAndroid Build Coastguard Worker 
149*635a8641SAndroid Build Coastguard Worker #if BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
GetStackEnd()150*635a8641SAndroid Build Coastguard Worker uintptr_t GetStackEnd() {
151*635a8641SAndroid Build Coastguard Worker #if defined(OS_ANDROID)
152*635a8641SAndroid Build Coastguard Worker   // Bionic reads proc/maps on every call to pthread_getattr_np() when called
153*635a8641SAndroid Build Coastguard Worker   // from the main thread. So we need to cache end of stack in that case to get
154*635a8641SAndroid Build Coastguard Worker   // acceptable performance.
155*635a8641SAndroid Build Coastguard Worker   // For all other threads pthread_getattr_np() is fast enough as it just reads
156*635a8641SAndroid Build Coastguard Worker   // values from its pthread_t argument.
157*635a8641SAndroid Build Coastguard Worker   static uintptr_t main_stack_end = 0;
158*635a8641SAndroid Build Coastguard Worker 
159*635a8641SAndroid Build Coastguard Worker   bool is_main_thread = GetCurrentProcId() == PlatformThread::CurrentId();
160*635a8641SAndroid Build Coastguard Worker   if (is_main_thread && main_stack_end) {
161*635a8641SAndroid Build Coastguard Worker     return main_stack_end;
162*635a8641SAndroid Build Coastguard Worker   }
163*635a8641SAndroid Build Coastguard Worker 
164*635a8641SAndroid Build Coastguard Worker   uintptr_t stack_begin = 0;
165*635a8641SAndroid Build Coastguard Worker   size_t stack_size = 0;
166*635a8641SAndroid Build Coastguard Worker   pthread_attr_t attributes;
167*635a8641SAndroid Build Coastguard Worker   int error = pthread_getattr_np(pthread_self(), &attributes);
168*635a8641SAndroid Build Coastguard Worker   if (!error) {
169*635a8641SAndroid Build Coastguard Worker     error = pthread_attr_getstack(
170*635a8641SAndroid Build Coastguard Worker         &attributes, reinterpret_cast<void**>(&stack_begin), &stack_size);
171*635a8641SAndroid Build Coastguard Worker     pthread_attr_destroy(&attributes);
172*635a8641SAndroid Build Coastguard Worker   }
173*635a8641SAndroid Build Coastguard Worker   DCHECK(!error);
174*635a8641SAndroid Build Coastguard Worker 
175*635a8641SAndroid Build Coastguard Worker   uintptr_t stack_end = stack_begin + stack_size;
176*635a8641SAndroid Build Coastguard Worker   if (is_main_thread) {
177*635a8641SAndroid Build Coastguard Worker     main_stack_end = stack_end;
178*635a8641SAndroid Build Coastguard Worker   }
179*635a8641SAndroid Build Coastguard Worker   return stack_end;  // 0 in case of error
180*635a8641SAndroid Build Coastguard Worker 
181*635a8641SAndroid Build Coastguard Worker #elif defined(OS_LINUX) && defined(__GLIBC__)
182*635a8641SAndroid Build Coastguard Worker 
183*635a8641SAndroid Build Coastguard Worker   if (GetCurrentProcId() == PlatformThread::CurrentId()) {
184*635a8641SAndroid Build Coastguard Worker     // For the main thread we have a shortcut.
185*635a8641SAndroid Build Coastguard Worker     return reinterpret_cast<uintptr_t>(__libc_stack_end);
186*635a8641SAndroid Build Coastguard Worker   }
187*635a8641SAndroid Build Coastguard Worker 
188*635a8641SAndroid Build Coastguard Worker // No easy way to get end of the stack for non-main threads,
189*635a8641SAndroid Build Coastguard Worker // see crbug.com/617730.
190*635a8641SAndroid Build Coastguard Worker #elif defined(OS_MACOSX)
191*635a8641SAndroid Build Coastguard Worker   return reinterpret_cast<uintptr_t>(pthread_get_stackaddr_np(pthread_self()));
192*635a8641SAndroid Build Coastguard Worker #endif
193*635a8641SAndroid Build Coastguard Worker 
194*635a8641SAndroid Build Coastguard Worker   // Don't know how to get end of the stack.
195*635a8641SAndroid Build Coastguard Worker   return 0;
196*635a8641SAndroid Build Coastguard Worker }
197*635a8641SAndroid Build Coastguard Worker #endif  // BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
198*635a8641SAndroid Build Coastguard Worker 
StackTrace()199*635a8641SAndroid Build Coastguard Worker StackTrace::StackTrace() : StackTrace(arraysize(trace_)) {}
200*635a8641SAndroid Build Coastguard Worker 
StackTrace(const void * const * trace,size_t count)201*635a8641SAndroid Build Coastguard Worker StackTrace::StackTrace(const void* const* trace, size_t count) {
202*635a8641SAndroid Build Coastguard Worker   count = std::min(count, arraysize(trace_));
203*635a8641SAndroid Build Coastguard Worker   if (count)
204*635a8641SAndroid Build Coastguard Worker     memcpy(trace_, trace, count * sizeof(trace_[0]));
205*635a8641SAndroid Build Coastguard Worker   count_ = count;
206*635a8641SAndroid Build Coastguard Worker }
207*635a8641SAndroid Build Coastguard Worker 
Addresses(size_t * count) const208*635a8641SAndroid Build Coastguard Worker const void *const *StackTrace::Addresses(size_t* count) const {
209*635a8641SAndroid Build Coastguard Worker   *count = count_;
210*635a8641SAndroid Build Coastguard Worker   if (count_)
211*635a8641SAndroid Build Coastguard Worker     return trace_;
212*635a8641SAndroid Build Coastguard Worker   return nullptr;
213*635a8641SAndroid Build Coastguard Worker }
214*635a8641SAndroid Build Coastguard Worker 
ToString() const215*635a8641SAndroid Build Coastguard Worker std::string StackTrace::ToString() const {
216*635a8641SAndroid Build Coastguard Worker   std::stringstream stream;
217*635a8641SAndroid Build Coastguard Worker #if !defined(__UCLIBC__) && !defined(_AIX)
218*635a8641SAndroid Build Coastguard Worker   OutputToStream(&stream);
219*635a8641SAndroid Build Coastguard Worker #endif
220*635a8641SAndroid Build Coastguard Worker   return stream.str();
221*635a8641SAndroid Build Coastguard Worker }
222*635a8641SAndroid Build Coastguard Worker 
223*635a8641SAndroid Build Coastguard Worker #if BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
224*635a8641SAndroid Build Coastguard Worker 
TraceStackFramePointers(const void ** out_trace,size_t max_depth,size_t skip_initial)225*635a8641SAndroid Build Coastguard Worker size_t TraceStackFramePointers(const void** out_trace,
226*635a8641SAndroid Build Coastguard Worker                                size_t max_depth,
227*635a8641SAndroid Build Coastguard Worker                                size_t skip_initial) {
228*635a8641SAndroid Build Coastguard Worker   // Usage of __builtin_frame_address() enables frame pointers in this
229*635a8641SAndroid Build Coastguard Worker   // function even if they are not enabled globally. So 'fp' will always
230*635a8641SAndroid Build Coastguard Worker   // be valid.
231*635a8641SAndroid Build Coastguard Worker   uintptr_t fp = reinterpret_cast<uintptr_t>(__builtin_frame_address(0)) -
232*635a8641SAndroid Build Coastguard Worker                     kStackFrameAdjustment;
233*635a8641SAndroid Build Coastguard Worker 
234*635a8641SAndroid Build Coastguard Worker   uintptr_t stack_end = GetStackEnd();
235*635a8641SAndroid Build Coastguard Worker 
236*635a8641SAndroid Build Coastguard Worker   size_t depth = 0;
237*635a8641SAndroid Build Coastguard Worker   while (depth < max_depth) {
238*635a8641SAndroid Build Coastguard Worker     if (skip_initial != 0) {
239*635a8641SAndroid Build Coastguard Worker       skip_initial--;
240*635a8641SAndroid Build Coastguard Worker     } else {
241*635a8641SAndroid Build Coastguard Worker       out_trace[depth++] = reinterpret_cast<const void*>(GetStackFramePC(fp));
242*635a8641SAndroid Build Coastguard Worker     }
243*635a8641SAndroid Build Coastguard Worker 
244*635a8641SAndroid Build Coastguard Worker     uintptr_t next_fp = GetNextStackFrame(fp);
245*635a8641SAndroid Build Coastguard Worker     if (IsStackFrameValid(next_fp, fp, stack_end)) {
246*635a8641SAndroid Build Coastguard Worker       fp = next_fp;
247*635a8641SAndroid Build Coastguard Worker       continue;
248*635a8641SAndroid Build Coastguard Worker     }
249*635a8641SAndroid Build Coastguard Worker 
250*635a8641SAndroid Build Coastguard Worker     next_fp = ScanStackForNextFrame(fp, stack_end);
251*635a8641SAndroid Build Coastguard Worker     if (next_fp) {
252*635a8641SAndroid Build Coastguard Worker       fp = next_fp;
253*635a8641SAndroid Build Coastguard Worker       continue;
254*635a8641SAndroid Build Coastguard Worker     }
255*635a8641SAndroid Build Coastguard Worker 
256*635a8641SAndroid Build Coastguard Worker     // Failed to find next frame.
257*635a8641SAndroid Build Coastguard Worker     break;
258*635a8641SAndroid Build Coastguard Worker   }
259*635a8641SAndroid Build Coastguard Worker 
260*635a8641SAndroid Build Coastguard Worker   return depth;
261*635a8641SAndroid Build Coastguard Worker }
262*635a8641SAndroid Build Coastguard Worker 
ScopedStackFrameLinker(void * fp,void * parent_fp)263*635a8641SAndroid Build Coastguard Worker ScopedStackFrameLinker::ScopedStackFrameLinker(void* fp, void* parent_fp)
264*635a8641SAndroid Build Coastguard Worker     : fp_(fp),
265*635a8641SAndroid Build Coastguard Worker       parent_fp_(parent_fp),
266*635a8641SAndroid Build Coastguard Worker       original_parent_fp_(LinkStackFrames(fp, parent_fp)) {}
267*635a8641SAndroid Build Coastguard Worker 
~ScopedStackFrameLinker()268*635a8641SAndroid Build Coastguard Worker ScopedStackFrameLinker::~ScopedStackFrameLinker() {
269*635a8641SAndroid Build Coastguard Worker   void* previous_parent_fp = LinkStackFrames(fp_, original_parent_fp_);
270*635a8641SAndroid Build Coastguard Worker   CHECK_EQ(parent_fp_, previous_parent_fp)
271*635a8641SAndroid Build Coastguard Worker       << "Stack frame's parent pointer has changed!";
272*635a8641SAndroid Build Coastguard Worker }
273*635a8641SAndroid Build Coastguard Worker 
274*635a8641SAndroid Build Coastguard Worker #endif  // BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
275*635a8641SAndroid Build Coastguard Worker 
276*635a8641SAndroid Build Coastguard Worker }  // namespace debug
277*635a8641SAndroid Build Coastguard Worker }  // namespace base
278