Memory corruption due to Symtab::AddSymbol growth

Hi,

I am running into memory corruption in LLDB 3.8 release candidate on Linux Ubuntu 15.10.
I am trying to access stack frame and the symbol on this frame is corrupted. Here is what I figured out:

  • “StackFrame” has field “m_sc” of type “SymbolContext”
  • “SymbolContext” has field “symbol” which is “Symbol*” pointer

Now, when AddSymbol needs to grow its storage, the std::vector allocates new memory and makes these “symbol” pointers dangling.
Here is the call stack:

#0 0x00007ffff274188c in lldb_private::SymbolContextScope::~SymbolContextScope (this=0x12b5a58, __in_chrg=)
at /home/eugenebi/llvm/tools/lldb/include/lldb/Symbol/SymbolContextScope.h:75
#1 0x00007ffff289f78a in lldb_private::Symbol::~Symbol (this=0x12b5a58, __in_chrg=)
at /home/eugenebi/llvm/tools/lldb/include/lldb/Symbol/Symbol.h:21
#2 0x00007ffff28b72e8 in std::_Destroy<lldb_private::Symbol> (__pointer=0x12b5a58) at /usr/include/c++/5/bits/stl_construct.h:93
#3 0x00007ffff28b5a9d in std::_Destroy_aux::__destroy<lldb_private::Symbol*> (__first=0x12b5a58, __last=0x12c1710)
at /usr/include/c++/5/bits/stl_construct.h:103
#4 0x00007ffff28b3e41 in std::_Destroy<lldb_private::Symbol*> (__first=0x12af710, __last=0x12c1710)
at /usr/include/c++/5/bits/stl_construct.h:126
#5 0x00007ffff28b241b in std::_Destroy<lldb_private::Symbol*, lldb_private::Symbol> (__first=0x12af710, __last=0x12c1710)
at /usr/include/c++/5/bits/stl_construct.h:151
#6 0x00007ffff28b2a2f in std::vector<lldb_private::Symbol, std::allocator<lldb_private::Symbol> >::_M_emplace_back_aux<lldb_private::Symbol c onst&> (this=0x9f6688) at /usr/include/c++/5/bits/vector.tcc:436
#7 0x00007ffff28b143d in std::vector<lldb_private::Symbol, std::allocator<lldb_private::Symbol> >::push_back (this=0x9f6688, __x=…)
at /usr/include/c++/5/bits/stl_vector.h:923
#8 0x00007ffff28ab0c0 in lldb_private::Symtab::AddSymbol (this=0x9f6680, symbol=…)
at /home/eugenebi/llvm/tools/lldb/source/Symbol/Symtab.cpp:70
#9 0x00007ffff2acba21 in ObjectFileELF::ResolveSymbolForAddress (this=0x9f6310, so_addr=…, verify_unique=false)
at /home/eugenebi/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp:2881
#10 0x00007ffff273cc50 in lldb_private::Module::ResolveSymbolContextForAddress (this=0x9f5cb0, so_addr=…, resolve_scope=72, sc=…,
resolve_tail_call_address=false) at /home/eugenebi/llvm/tools/lldb/source/Core/Module.cpp:568
#11 0x00007ffff2b31f04 in lldb_private::RegisterContextLLDB::InitializeZerothFrame (this=0x98687c0)
at /home/eugenebi/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp:180
#12 0x00007ffff2b31a34 in lldb_private::RegisterContextLLDB::RegisterContextLLDB (this=0x98687c0, thread=…,
next_frame=std::shared_ptr (empty) 0x0, sym_ctx=…, frame_number=0, unwind_lldb=…)
at /home/eugenebi/llvm/tools/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp:82
#13 0x00007ffff2b2bb7a in lldb_private::UnwindLLDB::AddFirstFrame (this=0x1ee82b0)
at /home/eugenebi/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp:97
#14 0x00007ffff2b2cd01 in lldb_private::UnwindLLDB::DoGetFrameInfoAtIndex (this=0x1ee82b0, idx=0, cfa=@0x7fffffffc270: 18446744073709551615,
pc=@0x7fffffffc268: 18446744073709551615) at /home/eugenebi/llvm/tools/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp:422
#15 0x00007ffff29ac64b in lldb_private::Unwind::GetFrameInfoAtIndex (this=0x1ee82b0, frame_idx=0, cfa=@0x7fffffffc270: 18446744073709551615,
pc=@0x7fffffffc268: 18446744073709551615) at /home/eugenebi/llvm/tools/lldb/include/lldb/Target/Unwind.h:78
#16 0x00007ffff29aa4a9 in lldb_private::StackFrameList::GetFramesUpTo (this=0x9868250, end_idx=0)
at /home/eugenebi/llvm/tools/lldb/source/Target/StackFrameList.cpp:308
#17 0x00007ffff29ab150 in lldb_private::StackFrameList::GetFrameAtIndex (this=0x9868250, idx=0)
at /home/eugenebi/llvm/tools/lldb/source/Target/StackFrameList.cpp:546
#18 0x00007ffff29775fa in lldb_private::thread::GetStackFrameAtIndex (this=0x7ff6a805d4f0, idx=0)
at /home/eugenebi/llvm/tools/lldb/include/lldb/Target/Thread.h:539
#19 0x00007ffff1032f0e in lldb::SBThread::GetFrameAtIndex (this=0x7fffffffce30, idx=0)
at /home/eugenebi/llvm/tools/lldb/source/API/SBThread.cpp:1347

Thanks,
Eugene

Hi,

I am looking through LLDB code… Another dangerous operation is Symtab::Finalize() that just swaps the array. This is especially bad since it will defeat something like quick-and-dirty hack of preallocating a huge vector upfront.

My first impulse to fix that (maybe just temporary to get me unblocked) was neuter that Finalize() and replace vector with dequeue. But unfortunately there are places when we take address to the first element and assume the rest of memory is contiguous - say, we call ::bsearch() on it.

Apparently, allocating each symbol separately and replacing the vector of elements with the vector of (smart) pointers would work, but it will hurt performance and probably cause the change touching lots of code…

So, any insights how to fix it?

Thanks,
Eugene

Hi,

I am looking through LLDB code... Another dangerous operation is Symtab::Finalize() that just swaps the array. This is especially bad since it will defeat something like quick-and-dirty hack of preallocating a huge vector upfront.

My first impulse to fix that (maybe just temporary to get me unblocked) was neuter that Finalize() and replace vector with dequeue. But unfortunately there are places when we take address to the first element and assume the rest of memory is contiguous - say, we call ::bsearch() on it.

Apparently, allocating each symbol separately and replacing the vector of elements with the vector of (smart) pointers would work, but it will hurt performance and probably cause the change touching lots of code...

So, any insights how to fix it?

You can do anything you want when constructing the symbol table on the first call to ObjectFile::GetSymtab(), but once you return a "Symtab *" from your object file you can never add or change due to exactly this issue. So the bug is that ObjectFileELF::ResolveSymbolForAddress() is adding a symbol on the fly which must be fixed and can't happen. All symbols need to be added on the first call to "ObjectFile::GetSymtab()".

The ResolveSymbolForAddress doesn't seem to be in ObjectFileELF in top of tree. Maybe you can cherry pick the fix over to the LLDB 3.8 branch.