[compiler-rt] r223145 - Simplify Symbolizer::SymbolizePC() interface.

Filipe Cabecinhas filcab at gmail.com
Fri Feb 6 14:44:17 PST 2015


Hi Alexey,

On Fri, Feb 6, 2015 at 1:17 PM, Alexey Samsonov <vonosmas at gmail.com> wrote:

> Hi Filipe,
>
> First of all, did you notice it by code inspection, or actually observed
> noticable memory leak in your program?
>
It was reported to us after we shipped UBSan for testing. Programs just
crash.
This makes sense if you take into account that you might have errors in
each frame of a game, which runs at 60fps. Memory usage grows rapidly :-)

I remember this problem, and it wasn't fixed until now, because this memory
> leak happens during error reporting, and can only be noticed if your
> program has a significant
> number of different UBSan error reports. That said, we should of course
> fix it :)
>
That was the idea I had after seeing the code :-)

I don't really understand your suggestion, though. Location destructor
> already calls destructor for MemoryLocation. The problem is
> ModuleLocation::ModuleName (and, similar SourceLocation::Filename):
>
Yes. The “clear the objects” would be the freeing of whatever we could,
which is what's missing (ModuleName and Filename).


> they can point to either constant string literals, or global data, or
> dynamically allocated strings (e.g. via internal_strdup). We should only
> call InternalFree() on these string buffers in the latter case.
>
Ah, I forgot about the string literal case.
I wonder if it's more worth it to make the SourceLocation (and friends)
class manage their strings a bit better, or if it would be worth it to have
the StackFrames objects not fully free each of the module's names (We're
leaking because we generate a FallbackLoc with the module name).

Any clues on where it would be better to start? You know much more about
what you need for location info outside of ubsan.

Thank you,

  Filipe


On Thu, Feb 5, 2015 at 7:02 PM, Filipe Cabecinhas <filcab at gmail.com> wrote:
>
>> Hi Alexey!
>>
>> This still has a memory leak: (ubsan_diag.cc)
>> +  if (!Info.file) {
>> +    ModuleLocation MLoc(internal_strdup(Info.module),
>> Info.module_offset);
>> +    Frames->ClearAll();
>> +    return MLoc;
>> +  }
>> ^^ You're doing an strdup, but later the ModuleLocation only gets used to
>> feed a Location, which is only used when Diag calls renderLocation. After
>> that, it gets leaked away.
>>
>> One could fix this by making SourceLoc, ModuleLoc, and MemoryLoc, inside
>> class Location (ubsan_diag.h) pointers, and clear the objects in the
>> Location destructor.
>> If you're ok with this let me know and I can submit the patch, otherwise,
>> can you fix it?
>> (I'm not sure about the uses in tsan and other sanitizers, so I don't
>> know if they also leak)
>>
>> Thanks,
>>
>>   Filipe
>>
>> On Tue, Dec 2, 2014 at 11:48 AM, Alexey Samsonov <vonosmas at gmail.com>
>> wrote:
>>
>>> Author: samsonov
>>> Date: Tue Dec  2 13:48:40 2014
>>> New Revision: 223145
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=223145&view=rev
>>> Log:
>>> Simplify Symbolizer::SymbolizePC() interface.
>>>
>>> Return a linked list of AddressInfo objects, instead of using an array of
>>> these objects as an output parameter. This simplifies the code in callers
>>> of this function (especially TSan).
>>>
>>> Fix a few memory leaks from internal allocator, when the returned
>>> AddressInfo objects were not properly cleared.
>>>
>>> Modified:
>>>     compiler-rt/trunk/lib/lsan/lsan_common.cc
>>>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc
>>>
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
>>>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.cc
>>>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h
>>>
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
>>>
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
>>>
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
>>>     compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc
>>>     compiler-rt/trunk/lib/tsan/go/buildgo.sh
>>>     compiler-rt/trunk/lib/tsan/go/tsan_go.cc
>>>     compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc
>>>     compiler-rt/trunk/lib/tsan/rtl/tsan_report.h
>>>     compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
>>>     compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc
>>>     compiler-rt/trunk/lib/tsan/rtl/tsan_suppressions.cc
>>>     compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.cc
>>>     compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.h
>>>     compiler-rt/trunk/lib/ubsan/ubsan_diag.cc
>>>
>>> Modified: compiler-rt/trunk/lib/lsan/lsan_common.cc
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/lsan/lsan_common.cc?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/lsan/lsan_common.cc (original)
>>> +++ compiler-rt/trunk/lib/lsan/lsan_common.cc Tue Dec  2 13:48:40 2014
>>> @@ -457,30 +457,27 @@ void DoLeakCheck() {
>>>  }
>>>
>>>  static Suppression *GetSuppressionForAddr(uptr addr) {
>>> -  Suppression *s;
>>> +  Suppression *s = nullptr;
>>>
>>>    // Suppress by module name.
>>>    const char *module_name;
>>>    uptr module_offset;
>>> -  if (Symbolizer::GetOrInit()
>>> -          ->GetModuleNameAndOffsetForPC(addr, &module_name,
>>> &module_offset) &&
>>> +  if (Symbolizer::GetOrInit()->GetModuleNameAndOffsetForPC(addr,
>>> &module_name,
>>> +
>>>  &module_offset) &&
>>>        SuppressionContext::Get()->Match(module_name, SuppressionLeak,
>>> &s))
>>>      return s;
>>>
>>>    // Suppress by file or function name.
>>> -  static const uptr kMaxAddrFrames = 16;
>>> -  InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
>>> -  for (uptr i = 0; i < kMaxAddrFrames; i++) new (&addr_frames[i])
>>> AddressInfo();
>>> -  uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC(
>>> -      addr, addr_frames.data(), kMaxAddrFrames);
>>> -  for (uptr i = 0; i < addr_frames_num; i++) {
>>> -    if (SuppressionContext::Get()->Match(addr_frames[i].function,
>>> -                                         SuppressionLeak, &s) ||
>>> -        SuppressionContext::Get()->Match(addr_frames[i].file,
>>> SuppressionLeak,
>>> -                                         &s))
>>> -      return s;
>>> +  SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(addr);
>>> +  for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
>>> +    if (SuppressionContext::Get()->Match(cur->info.function,
>>> SuppressionLeak,
>>> +                                         &s) ||
>>> +        SuppressionContext::Get()->Match(cur->info.file,
>>> SuppressionLeak, &s)) {
>>> +      break;
>>> +    }
>>>    }
>>> -  return 0;
>>> +  frames->ClearAll();
>>> +  return s;
>>>  }
>>>
>>>  static Suppression *GetSuppressionForStack(u32 stack_trace_id) {
>>>
>>> Modified:
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc
>>> (original)
>>> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_libcdep.cc
>>> Tue Dec  2 13:48:40 2014
>>> @@ -52,16 +52,20 @@ void SetSandboxingCallback(void (*f)())
>>>  void ReportErrorSummary(const char *error_type, StackTrace *stack) {
>>>    if (!common_flags()->print_summary)
>>>      return;
>>> -  AddressInfo ai;
>>>  #if !SANITIZER_GO
>>>    if (stack->size > 0 &&
>>> Symbolizer::GetOrInit()->CanReturnFileLineInfo()) {
>>>      // Currently, we include the first stack frame into the report
>>> summary.
>>>      // Maybe sometimes we need to choose another frame (e.g. skip
>>> memcpy/etc).
>>>      uptr pc = StackTrace::GetPreviousInstructionPc(stack->trace[0]);
>>> -    Symbolizer::GetOrInit()->SymbolizePC(pc, &ai, 1);
>>> +    SymbolizedStack *frame = Symbolizer::GetOrInit()->SymbolizePC(pc);
>>> +    const AddressInfo &ai = frame->info;
>>> +    ReportErrorSummary(error_type, ai.file, ai.line, ai.function);
>>> +    frame->ClearAll();
>>>    }
>>> -#endif
>>> +#else
>>> +  AddressInfo ai;
>>>    ReportErrorSummary(error_type, ai.file, ai.line, ai.function);
>>> +#endif
>>>  }
>>>
>>>  }  // namespace __sanitizer
>>>
>>> Modified:
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> ---
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc
>>> (original)
>>> +++
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_stacktrace_libcdep.cc Tue
>>> Dec  2 13:48:40 2014
>>> @@ -24,30 +24,21 @@ void StackTrace::Print() const {
>>>      Printf("    <empty stack>\n\n");
>>>      return;
>>>    }
>>> -  const int kMaxAddrFrames = 64;
>>> -  InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
>>> -  for (uptr i = 0; i < kMaxAddrFrames; i++)
>>> -    new(&addr_frames[i]) AddressInfo();
>>>    InternalScopedString frame_desc(GetPageSizeCached() * 2);
>>>    uptr frame_num = 0;
>>>    for (uptr i = 0; i < size && trace[i]; i++) {
>>>      // PCs in stack traces are actually the return addresses, that is,
>>>      // addresses of the next instructions after the call.
>>>      uptr pc = GetPreviousInstructionPc(trace[i]);
>>> -    uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC(
>>> -        pc, addr_frames.data(), kMaxAddrFrames);
>>> -    if (addr_frames_num == 0) {
>>> -      addr_frames[0].address = pc;
>>> -      addr_frames_num = 1;
>>> -    }
>>> -    for (uptr j = 0; j < addr_frames_num; j++) {
>>> -      AddressInfo &info = addr_frames[j];
>>> +    SymbolizedStack *frames = Symbolizer::GetOrInit()->SymbolizePC(pc);
>>> +    CHECK(frames);
>>> +    for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
>>>        frame_desc.clear();
>>>        RenderFrame(&frame_desc, common_flags()->stack_trace_format,
>>> frame_num++,
>>> -                  info, common_flags()->strip_path_prefix);
>>> +                  cur->info, common_flags()->strip_path_prefix);
>>>        Printf("%s\n", frame_desc.data());
>>> -      info.Clear();
>>>      }
>>> +    frames->ClearAll();
>>>    }
>>>    // Always print a trailing empty line after stack trace.
>>>    Printf("\n");
>>>
>>> Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.cc
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.cc?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.cc
>>> (original)
>>> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.cc Tue
>>> Dec  2 13:48:40 2014
>>> @@ -11,13 +11,61 @@
>>>  // run-time libraries.
>>>
>>>  //===----------------------------------------------------------------------===//
>>>
>>> +#include "sanitizer_allocator_internal.h"
>>>  #include "sanitizer_platform.h"
>>>  #include "sanitizer_internal_defs.h"
>>> +#include "sanitizer_libc.h"
>>>  #include "sanitizer_placement_new.h"
>>>  #include "sanitizer_symbolizer.h"
>>>
>>>  namespace __sanitizer {
>>>
>>> +AddressInfo::AddressInfo() {
>>> +  internal_memset(this, 0, sizeof(AddressInfo));
>>> +  function_offset = kUnknown;
>>> +}
>>> +
>>> +void AddressInfo::Clear() {
>>> +  InternalFree(module);
>>> +  InternalFree(function);
>>> +  InternalFree(file);
>>> +  internal_memset(this, 0, sizeof(AddressInfo));
>>> +  function_offset = kUnknown;
>>> +}
>>> +
>>> +void AddressInfo::FillAddressAndModuleInfo(uptr addr, const char
>>> *mod_name,
>>> +                                           uptr mod_offset) {
>>> +  address = addr;
>>> +  module = internal_strdup(mod_name);
>>> +  module_offset = mod_offset;
>>> +}
>>> +
>>> +SymbolizedStack::SymbolizedStack() : next(nullptr), info() {}
>>> +
>>> +SymbolizedStack *SymbolizedStack::New(uptr addr) {
>>> +  void *mem = InternalAlloc(sizeof(SymbolizedStack));
>>> +  SymbolizedStack *res = new(mem) SymbolizedStack();
>>> +  res->info.address = addr;
>>> +  return res;
>>> +}
>>> +
>>> +void SymbolizedStack::ClearAll() {
>>> +  info.Clear();
>>> +  if (next)
>>> +    next->ClearAll();
>>> +  InternalFree(this);
>>> +}
>>> +
>>> +DataInfo::DataInfo() {
>>> +  internal_memset(this, 0, sizeof(DataInfo));
>>> +}
>>> +
>>> +void DataInfo::Clear() {
>>> +  InternalFree(module);
>>> +  InternalFree(name);
>>> +  internal_memset(this, 0, sizeof(DataInfo));
>>> +}
>>> +
>>>  Symbolizer *Symbolizer::symbolizer_;
>>>  StaticSpinMutex Symbolizer::init_mu_;
>>>  LowLevelAllocator Symbolizer::symbolizer_allocator_;
>>>
>>> Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h
>>> (original)
>>> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer.h Tue
>>> Dec  2 13:48:40 2014
>>> @@ -19,13 +19,14 @@
>>>  #ifndef SANITIZER_SYMBOLIZER_H
>>>  #define SANITIZER_SYMBOLIZER_H
>>>
>>> -#include "sanitizer_allocator_internal.h"
>>> -#include "sanitizer_internal_defs.h"
>>> -#include "sanitizer_libc.h"
>>> +#include "sanitizer_common.h"
>>> +#include "sanitizer_mutex.h"
>>>
>>>  namespace __sanitizer {
>>>
>>>  struct AddressInfo {
>>> +  // Owns all the string members. Storage for them is
>>> +  // (de)allocated using sanitizer internal allocator.
>>>    uptr address;
>>>
>>>    char *module;
>>> @@ -39,45 +40,38 @@ struct AddressInfo {
>>>    int line;
>>>    int column;
>>>
>>> -  AddressInfo() {
>>> -    internal_memset(this, 0, sizeof(AddressInfo));
>>> -    function_offset = kUnknown;
>>> -  }
>>> -
>>> +  AddressInfo();
>>>    // Deletes all strings and resets all fields.
>>> -  void Clear() {
>>> -    InternalFree(module);
>>> -    InternalFree(function);
>>> -    InternalFree(file);
>>> -    internal_memset(this, 0, sizeof(AddressInfo));
>>> -    function_offset = kUnknown;
>>> -  }
>>> -
>>> +  void Clear();
>>>    void FillAddressAndModuleInfo(uptr addr, const char *mod_name,
>>> -                                uptr mod_offset) {
>>> -    address = addr;
>>> -    module = internal_strdup(mod_name);
>>> -    module_offset = mod_offset;
>>> -  }
>>> +                                uptr mod_offset);
>>> +};
>>> +
>>> +// Linked list of symbolized frames (each frame is described by
>>> AddressInfo).
>>> +struct SymbolizedStack {
>>> +  SymbolizedStack *next;
>>> +  AddressInfo info;
>>> +  static SymbolizedStack *New(uptr addr);
>>> +  // Deletes current, and all subsequent frames in the linked list.
>>> +  // The object cannot be accessed after the call to this function.
>>> +  void ClearAll();
>>> +
>>> + private:
>>> +  SymbolizedStack();
>>>  };
>>>
>>>  // For now, DataInfo is used to describe global variable.
>>>  struct DataInfo {
>>> +  // Owns all the string members. Storage for them is
>>> +  // (de)allocated using sanitizer internal allocator.
>>>    char *module;
>>>    uptr module_offset;
>>>    char *name;
>>>    uptr start;
>>>    uptr size;
>>>
>>> -  DataInfo() {
>>> -    internal_memset(this, 0, sizeof(DataInfo));
>>> -  }
>>> -
>>> -  void Clear() {
>>> -    InternalFree(module);
>>> -    InternalFree(name);
>>> -    internal_memset(this, 0, sizeof(DataInfo));
>>> -  }
>>> +  DataInfo();
>>> +  void Clear();
>>>  };
>>>
>>>  class Symbolizer {
>>> @@ -85,11 +79,10 @@ class Symbolizer {
>>>    /// Initialize and return platform-specific implementation of
>>> symbolizer
>>>    /// (if it wasn't already initialized).
>>>    static Symbolizer *GetOrInit();
>>> -  // Fills at most "max_frames" elements of "frames" with descriptions
>>> -  // for a given address (in all inlined functions). Returns the number
>>> -  // of descriptions actually filled.
>>> -  virtual uptr SymbolizePC(uptr address, AddressInfo *frames, uptr
>>> max_frames) {
>>> -    return 0;
>>> +  // Returns a list of symbolized frames for a given address (containing
>>> +  // all inlined functions, if necessary).
>>> +  virtual SymbolizedStack *SymbolizePC(uptr address) {
>>> +    return SymbolizedStack::New(address);
>>>    }
>>>    virtual bool SymbolizeData(uptr address, DataInfo *info) {
>>>      return false;
>>>
>>> Modified:
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> ---
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
>>> (original)
>>> +++
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.cc
>>> Tue Dec  2 13:48:40 2014
>>> @@ -83,44 +83,52 @@ char *CplusV3Demangle(const char *name)
>>>  }
>>>  # endif  // SANITIZER_CP_DEMANGLE
>>>
>>> -struct SymbolizeCodeData {
>>> -  AddressInfo *frames;
>>> -  uptr n_frames;
>>> -  uptr max_frames;
>>> +struct SymbolizeCodeCallbackArg {
>>> +  SymbolizedStack *first;
>>> +  SymbolizedStack *last;
>>>    const char *module_name;
>>>    uptr module_offset;
>>> +
>>> +  void append(SymbolizedStack *f) {
>>> +    if (last != nullptr) {
>>> +      last->next = f;
>>> +      last = f;
>>> +    } else {
>>> +      first = f;
>>> +      last = f;
>>> +    }
>>> +  }
>>>  };
>>>
>>>  extern "C" {
>>>  static int SymbolizeCodePCInfoCallback(void *vdata, uintptr_t addr,
>>>                                         const char *filename, int lineno,
>>>                                         const char *function) {
>>> -  SymbolizeCodeData *cdata = (SymbolizeCodeData *)vdata;
>>> +  SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata;
>>>    if (function) {
>>> -    AddressInfo *info = &cdata->frames[cdata->n_frames++];
>>> -    info->Clear();
>>> +    SymbolizedStack *cur = SymbolizedStack::New(addr);
>>> +    cdata->append(cur);
>>> +    AddressInfo *info = &cur->info;
>>>      info->FillAddressAndModuleInfo(addr, cdata->module_name,
>>>                                     cdata->module_offset);
>>>      info->function = LibbacktraceSymbolizer::Demangle(function, true);
>>>      if (filename)
>>>        info->file = internal_strdup(filename);
>>>      info->line = lineno;
>>> -    if (cdata->n_frames == cdata->max_frames)
>>> -      return 1;
>>>    }
>>>    return 0;
>>>  }
>>>
>>>  static void SymbolizeCodeCallback(void *vdata, uintptr_t addr,
>>>                                    const char *symname, uintptr_t,
>>> uintptr_t) {
>>> -  SymbolizeCodeData *cdata = (SymbolizeCodeData *)vdata;
>>> +  SymbolizeCodeCallbackArg *cdata = (SymbolizeCodeCallbackArg *)vdata;
>>>    if (symname) {
>>> -    AddressInfo *info = &cdata->frames[0];
>>> -    info->Clear();
>>> +    SymbolizedStack *cur = SymbolizedStack::New(addr);
>>> +    cdata->append(cur);
>>> +    AddressInfo *info = &cur->info;
>>>      info->FillAddressAndModuleInfo(addr, cdata->module_name,
>>>                                     cdata->module_offset);
>>>      info->function = LibbacktraceSymbolizer::Demangle(symname, true);
>>> -    cdata->n_frames = 1;
>>>    }
>>>  }
>>>
>>> @@ -148,23 +156,21 @@ LibbacktraceSymbolizer *LibbacktraceSymb
>>>    return new(*alloc) LibbacktraceSymbolizer(state);
>>>  }
>>>
>>> -uptr LibbacktraceSymbolizer::SymbolizeCode(uptr addr, AddressInfo
>>> *frames,
>>> -                                           uptr max_frames,
>>> -                                           const char *module_name,
>>> -                                           uptr module_offset) {
>>> -  SymbolizeCodeData data;
>>> -  data.frames = frames;
>>> -  data.n_frames = 0;
>>> -  data.max_frames = max_frames;
>>> +SymbolizedStack *LibbacktraceSymbolizer::SymbolizeCode(uptr addr,
>>> +                                                       const char
>>> *module_name,
>>> +                                                       uptr
>>> module_offset) {
>>> +  SymbolizeCodeCallbackArg data;
>>> +  data.first = nullptr;
>>> +  data.last = nullptr;
>>>    data.module_name = module_name;
>>>    data.module_offset = module_offset;
>>>    backtrace_pcinfo((backtrace_state *)state_, addr,
>>> SymbolizeCodePCInfoCallback,
>>>                     ErrorCallback, &data);
>>> -  if (data.n_frames)
>>> -    return data.n_frames;
>>> +  if (data.first)
>>> +    return data.first;
>>>    backtrace_syminfo((backtrace_state *)state_, addr,
>>> SymbolizeCodeCallback,
>>>                      ErrorCallback, &data);
>>> -  return data.n_frames;
>>> +  return data.first;
>>>  }
>>>
>>>  bool LibbacktraceSymbolizer::SymbolizeData(DataInfo *info) {
>>> @@ -179,12 +185,11 @@ LibbacktraceSymbolizer *LibbacktraceSymb
>>>    return 0;
>>>  }
>>>
>>> -uptr LibbacktraceSymbolizer::SymbolizeCode(uptr addr, AddressInfo
>>> *frames,
>>> -                                           uptr max_frames,
>>> -                                           const char *module_name,
>>> -                                           uptr module_offset) {
>>> +SymbolizedStack *LibbacktraceSymbolizer::SymbolizeCode(uptr addr,
>>> +                                                       const char
>>> *module_name,
>>> +                                                       uptr
>>> module_offset) {
>>>    (void)state_;
>>> -  return 0;
>>> +  return nullptr;
>>>  }
>>>
>>>  bool LibbacktraceSymbolizer::SymbolizeData(DataInfo *info) {
>>>
>>> Modified:
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> ---
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
>>> (original)
>>> +++
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_libbacktrace.h
>>> Tue Dec  2 13:48:40 2014
>>> @@ -32,8 +32,8 @@ class LibbacktraceSymbolizer {
>>>   public:
>>>    static LibbacktraceSymbolizer *get(LowLevelAllocator *alloc);
>>>
>>> -  uptr SymbolizeCode(uptr addr, AddressInfo *frames, uptr max_frames,
>>> -                     const char *module_name, uptr module_offset);
>>> +  SymbolizedStack *SymbolizeCode(uptr addr, const char *module_name,
>>> +                                 uptr module_offset);
>>>
>>>    bool SymbolizeData(DataInfo *info);
>>>
>>>
>>> Modified:
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> ---
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
>>> (original)
>>> +++
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
>>> Tue Dec  2 13:48:40 2014
>>> @@ -514,34 +514,32 @@ class POSIXSymbolizer : public Symbolize
>>>          internal_symbolizer_(internal_symbolizer),
>>>          libbacktrace_symbolizer_(libbacktrace_symbolizer) {}
>>>
>>> -  uptr SymbolizePC(uptr addr, AddressInfo *frames, uptr max_frames)
>>> override {
>>> +  SymbolizedStack *SymbolizePC(uptr addr) override {
>>>      BlockingMutexLock l(&mu_);
>>> -    if (max_frames == 0)
>>> -      return 0;
>>>      const char *module_name;
>>>      uptr module_offset;
>>>      if (!FindModuleNameAndOffsetForAddress(addr, &module_name,
>>> &module_offset))
>>> -      return 0;
>>> +      return SymbolizedStack::New(addr);
>>>      // First, try to use libbacktrace symbolizer (if it's available).
>>>      if (libbacktrace_symbolizer_ != 0) {
>>>        mu_.CheckLocked();
>>> -      uptr res = libbacktrace_symbolizer_->SymbolizeCode(
>>> -          addr, frames, max_frames, module_name, module_offset);
>>> -      if (res > 0)
>>> +      if (SymbolizedStack *res =
>>> libbacktrace_symbolizer_->SymbolizeCode(
>>> +              addr, module_name, module_offset))
>>>          return res;
>>>      }
>>> +    // Always fill data about module name and offset.
>>> +    SymbolizedStack *res = SymbolizedStack::New(addr);
>>> +    res->info.FillAddressAndModuleInfo(addr, module_name,
>>> module_offset);
>>> +
>>>      const char *str = SendCommand(false, module_name, module_offset);
>>>      if (str == 0) {
>>> -      // Symbolizer was not initialized or failed. Fill only data
>>> -      // about module name and offset.
>>> -      AddressInfo *info = &frames[0];
>>> -      info->Clear();
>>> -      info->FillAddressAndModuleInfo(addr, module_name, module_offset);
>>> -      return 1;
>>> +      // Symbolizer was not initialized or failed.
>>> +      return res;
>>>      }
>>> -    uptr frame_id = 0;
>>> -    for (frame_id = 0; frame_id < max_frames; frame_id++) {
>>> -      AddressInfo *info = &frames[frame_id];
>>> +
>>> +    bool top_frame = true;
>>> +    SymbolizedStack *last = res;
>>> +    while (true) {
>>>        char *function_name = 0;
>>>        str = ExtractToken(str, "\n", &function_name);
>>>        CHECK(function_name);
>>> @@ -549,8 +547,18 @@ class POSIXSymbolizer : public Symbolize
>>>          // There are no more frames.
>>>          break;
>>>        }
>>> -      info->Clear();
>>> -      info->FillAddressAndModuleInfo(addr, module_name, module_offset);
>>> +      SymbolizedStack *cur;
>>> +      if (top_frame) {
>>> +        cur = res;
>>> +        top_frame = false;
>>> +      } else {
>>> +        cur = SymbolizedStack::New(addr);
>>> +        cur->info.FillAddressAndModuleInfo(addr, module_name,
>>> module_offset);
>>> +        last->next = cur;
>>> +        last = cur;
>>> +      }
>>> +
>>> +      AddressInfo *info = &cur->info;
>>>        info->function = function_name;
>>>        // Parse <file>:<line>:<column> buffer.
>>>        char *file_line_info = 0;
>>> @@ -572,14 +580,7 @@ class POSIXSymbolizer : public Symbolize
>>>          info->file = 0;
>>>        }
>>>      }
>>> -    if (frame_id == 0) {
>>> -      // Make sure we return at least one frame.
>>> -      AddressInfo *info = &frames[0];
>>> -      info->Clear();
>>> -      info->FillAddressAndModuleInfo(addr, module_name, module_offset);
>>> -      frame_id = 1;
>>> -    }
>>> -    return frame_id;
>>> +    return res;
>>>    }
>>>
>>>    bool SymbolizeData(uptr addr, DataInfo *info) override {
>>>
>>> Modified:
>>> compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc
>>> (original)
>>> +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_win.cc
>>> Tue Dec  2 13:48:40 2014
>>> @@ -26,9 +26,8 @@ class WinSymbolizer : public Symbolizer
>>>   public:
>>>    WinSymbolizer() : initialized_(false) {}
>>>
>>> -  uptr SymbolizePC(uptr addr, AddressInfo *frames, uptr max_frames)
>>> override {
>>> -    if (max_frames == 0)
>>> -      return 0;
>>> +  SymbolizedStack *SymbolizePC(uptr addr) override {
>>> +    SymbolizedStack *frame = SymbolizedStack::New(addr);
>>>
>>>      BlockingMutexLock l(&dbghelp_mu_);
>>>      if (!initialized_) {
>>> @@ -60,29 +59,27 @@ class WinSymbolizer : public Symbolizer
>>>      BOOL got_objname = SymFromAddr(GetCurrentProcess(),
>>>                                     (DWORD64)addr, &offset, symbol);
>>>      if (!got_objname)
>>> -      return 0;
>>> +      return frame;
>>>
>>>      DWORD unused;
>>>      IMAGEHLP_LINE64 line_info;
>>>      line_info.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
>>>      BOOL got_fileline = SymGetLineFromAddr64(GetCurrentProcess(),
>>> (DWORD64)addr,
>>>                                               &unused, &line_info);
>>> -    AddressInfo *info = &frames[0];
>>> -    info->Clear();
>>> -    info->function = internal_strdup(symbol->Name);
>>> -    info->function_offset = (uptr)offset;
>>> +    frame->info.function = internal_strdup(symbol->Name);
>>> +    frame->info.function_offset = (uptr)offset;
>>>      if (got_fileline) {
>>> -      info->file = internal_strdup(line_info.FileName);
>>> -      info->line = line_info.LineNumber;
>>> +      frame->info.file = internal_strdup(line_info.FileName);
>>> +      frame->info.line = line_info.LineNumber;
>>>      }
>>>
>>>      IMAGEHLP_MODULE64 mod_info;
>>>      internal_memset(&mod_info, 0, sizeof(mod_info));
>>>      mod_info.SizeOfStruct = sizeof(mod_info);
>>>      if (SymGetModuleInfo64(GetCurrentProcess(), addr, &mod_info))
>>> -      info->FillAddressAndModuleInfo(addr, mod_info.ImageName,
>>> -                                     addr - (uptr)mod_info.BaseOfImage);
>>> -    return 1;
>>> +      frame->info.FillAddressAndModuleInfo(addr, mod_info.ImageName,
>>> +                                           addr -
>>> (uptr)mod_info.BaseOfImage);
>>> +    return frame;
>>>    }
>>>
>>>    bool CanReturnFileLineInfo() override {
>>>
>>> Modified: compiler-rt/trunk/lib/tsan/go/buildgo.sh
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/go/buildgo.sh?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/tsan/go/buildgo.sh (original)
>>> +++ compiler-rt/trunk/lib/tsan/go/buildgo.sh Tue Dec  2 13:48:40 2014
>>> @@ -27,6 +27,7 @@ SRCS="
>>>         ../../sanitizer_common/sanitizer_thread_registry.cc
>>>         ../../sanitizer_common/sanitizer_stackdepot.cc
>>>         ../../sanitizer_common/sanitizer_stacktrace.cc
>>> +       ../../sanitizer_common/sanitizer_symbolizer.cc
>>>  "
>>>
>>>  if [ "`uname -a | grep Linux`" != "" ]; then
>>>
>>> Modified: compiler-rt/trunk/lib/tsan/go/tsan_go.cc
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/go/tsan_go.cc?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/tsan/go/tsan_go.cc (original)
>>> +++ compiler-rt/trunk/lib/tsan/go/tsan_go.cc Tue Dec  2 13:48:40 2014
>>> @@ -59,18 +59,19 @@ struct SymbolizeContext {
>>>  // Callback into Go.
>>>  static void (*symbolize_cb)(SymbolizeContext *ctx);
>>>
>>> -ReportStack *SymbolizeCode(uptr addr) {
>>> -  ReportStack *s = ReportStack::New(addr);
>>> +SymbolizedStack *SymbolizeCode(uptr addr) {
>>> +  SymbolizedStack *s = SymbolizedStack::New(addr);
>>>    SymbolizeContext ctx;
>>>    internal_memset(&ctx, 0, sizeof(ctx));
>>>    ctx.pc = addr;
>>>    symbolize_cb(&ctx);
>>>    if (ctx.res) {
>>> -    s->info.module_offset = ctx.off;
>>> -    s->info.function = internal_strdup(ctx.func ? ctx.func : "??");
>>> -    s->info.file = internal_strdup(ctx.file ? ctx.file : "-");
>>> -    s->info.line = ctx.line;
>>> -    s->info.column = 0;
>>> +    AddressInfo &info = s->info;
>>> +    info.module_offset = ctx.off;
>>> +    info.function = internal_strdup(ctx.func ? ctx.func : "??");
>>> +    info.file = internal_strdup(ctx.file ? ctx.file : "-");
>>> +    info.line = ctx.line;
>>> +    info.column = 0;
>>>    }
>>>    return s;
>>>  }
>>>
>>> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc (original)
>>> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc Tue Dec  2 13:48:40
>>> 2014
>>> @@ -19,13 +19,11 @@
>>>
>>>  namespace __tsan {
>>>
>>> -ReportStack::ReportStack() : next(nullptr), info(), suppressable(false)
>>> {}
>>> +ReportStack::ReportStack() : frames(nullptr), suppressable(false) {}
>>>
>>> -ReportStack *ReportStack::New(uptr addr) {
>>> +ReportStack *ReportStack::New() {
>>>    void *mem = internal_alloc(MBlockReportStack, sizeof(ReportStack));
>>> -  ReportStack *res = new(mem) ReportStack();
>>> -  res->info.address = addr;
>>> -  return res;
>>> +  return new(mem) ReportStack();
>>>  }
>>>
>>>  ReportLocation::ReportLocation(ReportLocationType type)
>>> @@ -114,13 +112,14 @@ static const char *ReportTypeString(Repo
>>>  }
>>>
>>>  void PrintStack(const ReportStack *ent) {
>>> -  if (ent == 0) {
>>> +  if (ent == 0 || ent->frames == 0) {
>>>      Printf("    [failed to restore the stack]\n\n");
>>>      return;
>>>    }
>>> -  for (int i = 0; ent && ent->info.address; ent = ent->next, i++) {
>>> +  SymbolizedStack *frame = ent->frames;
>>> +  for (int i = 0; frame && frame->info.address; frame = frame->next,
>>> i++) {
>>>      InternalScopedString res(2 * GetPageSizeCached());
>>> -    RenderFrame(&res, common_flags()->stack_trace_format, i, ent->info,
>>> +    RenderFrame(&res, common_flags()->stack_trace_format, i,
>>> frame->info,
>>>                  common_flags()->strip_path_prefix, "__interceptor_");
>>>      Printf("%s\n", res.data());
>>>    }
>>> @@ -252,10 +251,20 @@ static ReportStack *ChooseSummaryStack(c
>>>    return 0;
>>>  }
>>>
>>> -ReportStack *SkipTsanInternalFrames(ReportStack *ent) {
>>> -  while (FrameIsInternal(ent) && ent->next)
>>> -    ent = ent->next;
>>> -  return ent;
>>> +static bool FrameIsInternal(const SymbolizedStack *frame) {
>>> +  if (frame == 0)
>>> +    return false;
>>> +  const char *file = frame->info.file;
>>> +  return file != 0 &&
>>> +         (internal_strstr(file, "tsan_interceptors.cc") ||
>>> +          internal_strstr(file, "sanitizer_common_interceptors.inc") ||
>>> +          internal_strstr(file, "tsan_interface_"));
>>> +}
>>> +
>>> +static SymbolizedStack *SkipTsanInternalFrames(SymbolizedStack *frames)
>>> {
>>> +  while (FrameIsInternal(frames) && frames->next)
>>> +    frames = frames->next;
>>> +  return frames;
>>>  }
>>>
>>>  void PrintReport(const ReportDesc *rep) {
>>> @@ -325,9 +334,11 @@ void PrintReport(const ReportDesc *rep)
>>>    if (rep->typ == ReportTypeThreadLeak && rep->count > 1)
>>>      Printf("  And %d more similar thread leaks.\n\n", rep->count - 1);
>>>
>>> -  if (ReportStack *ent =
>>> SkipTsanInternalFrames(ChooseSummaryStack(rep))) {
>>> -    const AddressInfo &info = ent->info;
>>> -    ReportErrorSummary(rep_typ_str, info.file, info.line,
>>> info.function);
>>> +  if (ReportStack *stack = ChooseSummaryStack(rep)) {
>>> +    if (SymbolizedStack *frame = SkipTsanInternalFrames(stack->frames))
>>> {
>>> +      const AddressInfo &info = frame->info;
>>> +      ReportErrorSummary(rep_typ_str, info.file, info.line,
>>> info.function);
>>> +    }
>>>    }
>>>
>>>    Printf("==================\n");
>>> @@ -338,12 +349,13 @@ void PrintReport(const ReportDesc *rep)
>>>  const int kMainThreadId = 1;
>>>
>>>  void PrintStack(const ReportStack *ent) {
>>> -  if (ent == 0) {
>>> +  if (ent == 0 || ent->frames == 0) {
>>>      Printf("  [failed to restore the stack]\n");
>>>      return;
>>>    }
>>> -  for (int i = 0; ent; ent = ent->next, i++) {
>>> -    const AddressInfo &info = ent->info;
>>> +  SymbolizedStack *frame = ent->frames;
>>> +  for (int i = 0; frame; frame = frame->next, i++) {
>>> +    const AddressInfo &info = frame->info;
>>>      Printf("  %s()\n      %s:%d +0x%zx\n", info.function, info.file,
>>> info.line,
>>>             (void *)info.module_offset);
>>>    }
>>>
>>> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_report.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_report.h?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/tsan/rtl/tsan_report.h (original)
>>> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_report.h Tue Dec  2 13:48:40 2014
>>> @@ -36,10 +36,9 @@ enum ReportType {
>>>  };
>>>
>>>  struct ReportStack {
>>> -  ReportStack *next;
>>> -  AddressInfo info;
>>> +  SymbolizedStack *frames;
>>>    bool suppressable;
>>> -  static ReportStack *New(uptr addr);
>>> +  static ReportStack *New();
>>>
>>>   private:
>>>    ReportStack();
>>>
>>> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)
>>> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Tue Dec  2 13:48:40 2014
>>> @@ -568,8 +568,6 @@ bool IsFiredSuppression(Context *ctx, co
>>>                          StackTrace trace);
>>>  bool IsExpectedReport(uptr addr, uptr size);
>>>  void PrintMatchedBenignRaces();
>>> -bool FrameIsInternal(const ReportStack *frame);
>>> -ReportStack *SkipTsanInternalFrames(ReportStack *ent);
>>>
>>>  #if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 1
>>>  # define DPrintf Printf
>>>
>>> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc (original)
>>> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_report.cc Tue Dec  2
>>> 13:48:40 2014
>>> @@ -56,40 +56,43 @@ bool WEAK OnReport(const ReportDesc *rep
>>>  }
>>>  #endif
>>>
>>> -static void StackStripMain(ReportStack *stack) {
>>> -  ReportStack *last_frame = 0;
>>> -  ReportStack *last_frame2 = 0;
>>> -  for (ReportStack *ent = stack; ent; ent = ent->next) {
>>> +static void StackStripMain(SymbolizedStack *frames) {
>>> +  SymbolizedStack *last_frame = nullptr;
>>> +  SymbolizedStack *last_frame2 = nullptr;
>>> +  for (SymbolizedStack *cur = frames; cur; cur = cur->next) {
>>>      last_frame2 = last_frame;
>>> -    last_frame = ent;
>>> +    last_frame = cur;
>>>    }
>>>
>>>    if (last_frame2 == 0)
>>>      return;
>>> -  const char *last = last_frame->info.function;
>>>  #ifndef TSAN_GO
>>> +  const char *last = last_frame->info.function;
>>>    const char *last2 = last_frame2->info.function;
>>>    // Strip frame above 'main'
>>>    if (last2 && 0 == internal_strcmp(last2, "main")) {
>>> -    last_frame2->next = 0;
>>> +    last_frame->ClearAll();
>>> +    last_frame2->next = nullptr;
>>>    // Strip our internal thread start routine.
>>>    } else if (last && 0 == internal_strcmp(last,
>>> "__tsan_thread_start_func")) {
>>> -    last_frame2->next = 0;
>>> +    last_frame->ClearAll();
>>> +    last_frame2->next = nullptr;
>>>    // Strip global ctors init.
>>>    } else if (last && 0 == internal_strcmp(last,
>>> "__do_global_ctors_aux")) {
>>> -    last_frame2->next = 0;
>>> +    last_frame->ClearAll();
>>> +    last_frame2->next = nullptr;
>>>    // If both are 0, then we probably just failed to symbolize.
>>>    } else if (last || last2) {
>>>      // Ensure that we recovered stack completely. Trimmed stack
>>>      // can actually happen if we do not instrument some code,
>>>      // so it's only a debug print. However we must try hard to not miss
>>> it
>>>      // due to our fault.
>>> -    DPrintf("Bottom stack frame of stack %zx is missed\n", stack->pc);
>>> +    DPrintf("Bottom stack frame of stack %zx is missed\n",
>>> stack->info.address);
>>>    }
>>>  #else
>>>    // The last frame always point into runtime (gosched0, goexit0,
>>> runtime.main).
>>> -  last_frame2->next = 0;
>>> -  (void)last;
>>> +  last_frame->ClearAll();
>>> +  last_frame2->next = nullptr;
>>>  #endif
>>>  }
>>>
>>> @@ -105,12 +108,12 @@ ReportStack *SymbolizeStackId(u32 stack_
>>>  static ReportStack *SymbolizeStack(StackTrace trace) {
>>>    if (trace.size == 0)
>>>      return 0;
>>> -  ReportStack *stack = 0;
>>> +  SymbolizedStack *top = nullptr;
>>>    for (uptr si = 0; si < trace.size; si++) {
>>>      const uptr pc = trace.trace[si];
>>>  #ifndef TSAN_GO
>>> -    // We obtain the return address, that is, address of the next
>>> instruction,
>>> -    // so offset it by 1 byte.
>>> +    // We obtain the return address, but we're interested in the
>>> previous
>>> +    // instruction.
>>>      const uptr pc1 = StackTrace::GetPreviousInstructionPc(pc);
>>>  #else
>>>      // FIXME(dvyukov): Go sometimes uses address of a function as top
>>> pc.
>>> @@ -118,18 +121,21 @@ static ReportStack *SymbolizeStack(Stack
>>>      if (si != trace.size - 1)
>>>        pc1 -= 1;
>>>  #endif
>>> -    ReportStack *ent = SymbolizeCode(pc1);
>>> +    SymbolizedStack *ent = SymbolizeCode(pc1);
>>>      CHECK_NE(ent, 0);
>>> -    ReportStack *last = ent;
>>> +    SymbolizedStack *last = ent;
>>>      while (last->next) {
>>>        last->info.address = pc;  // restore original pc for report
>>>        last = last->next;
>>>      }
>>>      last->info.address = pc;  // restore original pc for report
>>> -    last->next = stack;
>>> -    stack = ent;
>>> +    last->next = top;
>>> +    top = ent;
>>>    }
>>> -  StackStripMain(stack);
>>> +  StackStripMain(top);
>>> +
>>> +  ReportStack *stack = ReportStack::New();
>>> +  stack->frames = top;
>>>    return stack;
>>>  }
>>>
>>> @@ -547,16 +553,6 @@ static bool IsFiredSuppression(Context *
>>>    return false;
>>>  }
>>>
>>> -bool FrameIsInternal(const ReportStack *frame) {
>>> -  if (frame == 0)
>>> -    return false;
>>> -  const char *file = frame->info.file;
>>> -  return file != 0 &&
>>> -         (internal_strstr(file, "tsan_interceptors.cc") ||
>>> -          internal_strstr(file, "sanitizer_common_interceptors.inc") ||
>>> -          internal_strstr(file, "tsan_interface_"));
>>> -}
>>> -
>>>  static bool RaceBetweenAtomicAndFree(ThreadState *thr) {
>>>    Shadow s0(thr->racy_state[0]);
>>>    Shadow s1(thr->racy_state[1]);
>>>
>>> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_suppressions.cc
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_suppressions.cc?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/tsan/rtl/tsan_suppressions.cc (original)
>>> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_suppressions.cc Tue Dec  2
>>> 13:48:40 2014
>>> @@ -92,7 +92,8 @@ uptr IsSuppressed(ReportType typ, const
>>>    if (stype == SuppressionNone)
>>>      return 0;
>>>    Suppression *s;
>>> -  for (const ReportStack *frame = stack; frame; frame = frame->next) {
>>> +  for (const SymbolizedStack *frame = stack->frames; frame;
>>> +       frame = frame->next) {
>>>      const AddressInfo &info = frame->info;
>>>      if (SuppressionContext::Get()->Match(info.function, stype, &s) ||
>>>          SuppressionContext::Get()->Match(info.file, stype, &s) ||
>>>
>>> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.cc
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.cc?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.cc (original)
>>> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.cc Tue Dec  2 13:48:40
>>> 2014
>>> @@ -55,7 +55,7 @@ bool __tsan_symbolize_external(uptr pc,
>>>    return false;
>>>  }
>>>
>>> -ReportStack *SymbolizeCode(uptr addr) {
>>> +SymbolizedStack *SymbolizeCode(uptr addr) {
>>>    // Check if PC comes from non-native land.
>>>    if (addr & kExternalPCBit) {
>>>      // Declare static to not consume too much stack space.
>>> @@ -63,36 +63,17 @@ ReportStack *SymbolizeCode(uptr addr) {
>>>      static char func_buf[1024];
>>>      static char file_buf[1024];
>>>      int line, col;
>>> -    ReportStack *ent = ReportStack::New(addr);
>>> -    if (!__tsan_symbolize_external(addr, func_buf, sizeof(func_buf),
>>> -                                  file_buf, sizeof(file_buf), &line,
>>> &col))
>>> -      return ent;
>>> -    ent->info.function = internal_strdup(func_buf);
>>> -    ent->info.file = internal_strdup(file_buf);
>>> -    ent->info.line = line;
>>> -    ent->info.column = col;
>>> -    return ent;
>>> +    SymbolizedStack *frame = SymbolizedStack::New(addr);
>>> +    if (__tsan_symbolize_external(addr, func_buf, sizeof(func_buf),
>>> file_buf,
>>> +                                  sizeof(file_buf), &line, &col)) {
>>> +      frame->info.function = internal_strdup(func_buf);
>>> +      frame->info.file = internal_strdup(file_buf);
>>> +      frame->info.line = line;
>>> +      frame->info.column = col;
>>> +    }
>>> +    return frame;
>>>    }
>>> -  static const uptr kMaxAddrFrames = 16;
>>> -  InternalScopedBuffer<AddressInfo> addr_frames(kMaxAddrFrames);
>>> -  for (uptr i = 0; i < kMaxAddrFrames; i++)
>>> -    new(&addr_frames[i]) AddressInfo();
>>> -  uptr addr_frames_num = Symbolizer::GetOrInit()->SymbolizePC(
>>> -      addr, addr_frames.data(), kMaxAddrFrames);
>>> -  if (addr_frames_num == 0)
>>> -    return ReportStack::New(addr);
>>> -  ReportStack *top = 0;
>>> -  ReportStack *bottom = 0;
>>> -  for (uptr i = 0; i < addr_frames_num; i++) {
>>> -    ReportStack *cur_entry = ReportStack::New(addr);
>>> -    cur_entry->info = addr_frames[i];
>>> -    if (i == 0)
>>> -      top = cur_entry;
>>> -    else
>>> -      bottom->next = cur_entry;
>>> -    bottom = cur_entry;
>>> -  }
>>> -  return top;
>>> +  return Symbolizer::GetOrInit()->SymbolizePC(addr);
>>>  }
>>>
>>>  ReportLocation *SymbolizeData(uptr addr) {
>>>
>>> Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.h?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.h (original)
>>> +++ compiler-rt/trunk/lib/tsan/rtl/tsan_symbolize.h Tue Dec  2 13:48:40
>>> 2014
>>> @@ -20,7 +20,7 @@ namespace __tsan {
>>>
>>>  void EnterSymbolizer();
>>>  void ExitSymbolizer();
>>> -ReportStack *SymbolizeCode(uptr addr);
>>> +SymbolizedStack *SymbolizeCode(uptr addr);
>>>  ReportLocation *SymbolizeData(uptr addr);
>>>  void SymbolizeFlush();
>>>
>>>
>>> Modified: compiler-rt/trunk/lib/ubsan/ubsan_diag.cc
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/ubsan/ubsan_diag.cc?rev=223145&r1=223144&r2=223145&view=diff
>>>
>>> ==============================================================================
>>> --- compiler-rt/trunk/lib/ubsan/ubsan_diag.cc (original)
>>> +++ compiler-rt/trunk/lib/ubsan/ubsan_diag.cc Tue Dec  2 13:48:40 2014
>>> @@ -79,18 +79,26 @@ Location __ubsan::getFunctionLocation(up
>>>      return Location();
>>>    InitIfNecessary();
>>>
>>> -  AddressInfo Info;
>>> -  if (!Symbolizer::GetOrInit()->SymbolizePC(Loc, &Info, 1) ||
>>> !Info.module ||
>>> -      !*Info.module)
>>> +  SymbolizedStack *Frames = Symbolizer::GetOrInit()->SymbolizePC(Loc);
>>> +  const AddressInfo &Info = Frames->info;
>>> +
>>> +  if (!Info.module) {
>>> +    Frames->ClearAll();
>>>      return Location(Loc);
>>> +  }
>>>
>>>    if (FName && Info.function)
>>> -    *FName = Info.function;
>>> +    *FName = internal_strdup(Info.function);
>>>
>>> -  if (!Info.file)
>>> -    return ModuleLocation(Info.module, Info.module_offset);
>>> +  if (!Info.file) {
>>> +    ModuleLocation MLoc(internal_strdup(Info.module),
>>> Info.module_offset);
>>> +    Frames->ClearAll();
>>> +    return MLoc;
>>> +  }
>>>
>>> -  return SourceLocation(Info.file, Info.line, Info.column);
>>> +  SourceLocation SLoc(internal_strdup(Info.file), Info.line,
>>> Info.column);
>>> +  Frames->ClearAll();
>>> +  return SLoc;
>>>  }
>>>
>>>  Diag &Diag::operator<<(const TypeDescriptor &V) {
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>>
>>
>>
>>
>> --
>>   F
>>
>>
>
>
> --
> Alexey Samsonov
> vonosmas at gmail.com
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150206/190fd398/attachment.html>


More information about the llvm-commits mailing list