Skip to content

Commit

Permalink
Fix for Bug 25338
Browse files Browse the repository at this point in the history
Summary:
The issue arises because LLDB is not
able to read the vdso library correctly.
The fix adds memory allocation callbacks
to allocate sufficient memory in case the
requested offsets don't fit in the memory
buffer allocated for the ELF.

Reviewers: lldb-commits, clayborg, deepak2427, ovyalov, labath, tberghammer

Differential Revision: http://reviews.llvm.org/D16107

llvm-svn: 258122
  • Loading branch information
ravithejaintel committed Jan 19, 2016
1 parent f8f2d46 commit 15f89c4
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 25 deletions.
Expand Up @@ -15,8 +15,7 @@ class AssertingInferiorTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)

@expectedFailureWindows("llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows")
@expectedFailurei386("llvm.org/pr25338")
@expectedFailureLinux("llvm.org/pr25338", archs=['arm', 'i386'])
@expectedFailureLinux("llvm.org/pr25338", archs=['arm'])
def test_inferior_asserting(self):
"""Test that lldb reliably catches the inferior asserting (command)."""
self.build()
Expand All @@ -30,8 +29,7 @@ def test_inferior_asserting_register(self):
self.inferior_asserting_registers()

@expectedFailureWindows("llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows")
@expectedFailurei386("llvm.org/pr25338")
@expectedFailureLinux("llvm.org/pr25338", archs=['arm', 'i386'])
@expectedFailureLinux("llvm.org/pr25338", archs=['arm'])
def test_inferior_asserting_disassemble(self):
"""Test that lldb reliably disassembles frames after asserting (command)."""
self.build()
Expand All @@ -45,16 +43,14 @@ def test_inferior_asserting_python(self):
self.inferior_asserting_python()

@expectedFailureWindows("llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows")
@expectedFailurei386("llvm.org/pr25338")
@expectedFailureLinux("llvm.org/pr25338", archs=['arm', 'i386'])
@expectedFailureLinux("llvm.org/pr25338", archs=['arm'])
def test_inferior_asserting_expr(self):
"""Test that the lldb expression interpreter can read from the inferior after asserting (command)."""
self.build()
self.inferior_asserting_expr()

@expectedFailureWindows("llvm.org/pr21793: need to implement support for detecting assertion / abort on Windows")
@expectedFailurei386("llvm.org/pr25338")
@expectedFailureLinux("llvm.org/pr25338", archs=['arm', 'i386'])
@expectedFailureLinux("llvm.org/pr25338", archs=['arm'])
def test_inferior_asserting_step(self):
"""Test that lldb functions correctly after stepping through a call to assert()."""
self.build()
Expand Down
Expand Up @@ -14,7 +14,6 @@
class NoreturnUnwind(TestBase):
mydir = TestBase.compute_mydir(__file__)

@expectedFailurei386("llvm.org/pr25338")
@skipIfWindows # clang-cl does not support gcc style attributes.
def test (self):
"""Test that we can backtrace correctly with 'noreturn' functions on the stack"""
Expand Down
Expand Up @@ -75,7 +75,6 @@ def test_with_process_launch_api(self):

@add_test_categories(['pyapi'])
@expectedFailureWindows("llvm.org/pr24600")
@expectedFailurei386("llvm.org/pr25338")
@skipIfiOSSimulator
def test_with_attach_to_process_with_id_api(self):
"""Create target, spawn a process, and attach to it with process id."""
Expand Down Expand Up @@ -105,7 +104,6 @@ def test_with_attach_to_process_with_id_api(self):

@add_test_categories(['pyapi'])
@expectedFailureWindows("llvm.org/pr24600")
@expectedFailurei386("llvm.org/pr25338")
@skipIfiOSSimulator
def test_with_attach_to_process_with_name_api(self):
"""Create target, spawn a process, and attach to it with process name."""
Expand Down
64 changes: 52 additions & 12 deletions lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
Expand Up @@ -729,7 +729,10 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,
SectionHeaderColl section_headers;
lldb_private::UUID &uuid = spec.GetUUID();

GetSectionHeaderInfo(section_headers, data, header, uuid, gnu_debuglink_file, gnu_debuglink_crc, spec.GetArchitecture ());
using namespace std::placeholders;
const SetDataFunction set_data = std::bind(&ObjectFileELF::SetData, std::cref(data), _1, _2, _3);
GetSectionHeaderInfo(section_headers, set_data, header, uuid, gnu_debuglink_file, gnu_debuglink_crc, spec.GetArchitecture ());


llvm::Triple &spec_triple = spec.GetArchitecture ().GetTriple ();

Expand Down Expand Up @@ -759,7 +762,7 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,
data.SetData(data_sp);
}
ProgramHeaderColl program_headers;
GetProgramHeaderInfo(program_headers, data, header);
GetProgramHeaderInfo(program_headers, set_data, header);

size_t segment_data_end = 0;
for (ProgramHeaderCollConstIter I = program_headers.begin();
Expand Down Expand Up @@ -1256,7 +1259,7 @@ ObjectFileELF::ParseDependentModules()
//----------------------------------------------------------------------
size_t
ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
DataExtractor &object_data,
const SetDataFunction &set_data,
const ELFHeader &header)
{
// We have already parsed the program headers
Expand All @@ -1274,7 +1277,7 @@ ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
const size_t ph_size = header.e_phnum * header.e_phentsize;
const elf_off ph_offset = header.e_phoff;
DataExtractor data;
if (data.SetData(object_data, ph_offset, ph_size) != ph_size)
if (set_data(data, ph_offset, ph_size) != ph_size)
return 0;

uint32_t idx;
Expand All @@ -1298,7 +1301,10 @@ ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
size_t
ObjectFileELF::ParseProgramHeaders()
{
return GetProgramHeaderInfo(m_program_headers, m_data, m_header);
using namespace std::placeholders;
return GetProgramHeaderInfo(m_program_headers,
std::bind(&ObjectFileELF::SetDataWithReadMemoryFallback, this, _1, _2, _3),
m_header);
}

lldb_private::Error
Expand Down Expand Up @@ -1511,7 +1517,7 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
//----------------------------------------------------------------------
size_t
ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
lldb_private::DataExtractor &object_data,
const SetDataFunction &set_data,
const elf::ELFHeader &header,
lldb_private::UUID &uuid,
std::string &gnu_debuglink_file,
Expand Down Expand Up @@ -1569,7 +1575,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
const size_t sh_size = header.e_shnum * header.e_shentsize;
const elf_off sh_offset = header.e_shoff;
DataExtractor sh_data;
if (sh_data.SetData (object_data, sh_offset, sh_size) != sh_size)
if (set_data (sh_data, sh_offset, sh_size) != sh_size)
return 0;

uint32_t idx;
Expand All @@ -1590,7 +1596,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
const Elf64_Off offset = sheader.sh_offset;
lldb_private::DataExtractor shstr_data;

if (shstr_data.SetData (object_data, offset, byte_size) == byte_size)
if (set_data (shstr_data, offset, byte_size) == byte_size)
{
for (SectionHeaderCollIter I = section_headers.begin();
I != section_headers.end(); ++I)
Expand All @@ -1610,7 +1616,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
if (sheader.sh_type == SHT_MIPS_ABIFLAGS)
{

if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size))
if (section_size && (set_data (data, sheader.sh_offset, section_size) == section_size))
{
lldb::offset_t ase_offset = 12; // MIPS ABI Flags Version: 0
arch_flags |= data.GetU32 (&ase_offset);
Expand All @@ -1631,7 +1637,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
if (name == g_sect_name_gnu_debuglink)
{
DataExtractor data;
if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size))
if (section_size && (set_data (data, sheader.sh_offset, section_size) == section_size))
{
lldb::offset_t gnu_debuglink_offset = 0;
gnu_debuglink_file = data.GetCStr (&gnu_debuglink_offset);
Expand All @@ -1653,7 +1659,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
{
// Allow notes to refine module info.
DataExtractor data;
if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size))
if (section_size && (set_data (data, sheader.sh_offset, section_size) == section_size))
{
Error error = RefineModuleDetailsFromNote (data, arch_spec, uuid);
if (error.Fail ())
Expand Down Expand Up @@ -1719,7 +1725,41 @@ ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const
size_t
ObjectFileELF::ParseSectionHeaders()
{
return GetSectionHeaderInfo(m_section_headers, m_data, m_header, m_uuid, m_gnu_debuglink_file, m_gnu_debuglink_crc, m_arch_spec);
using namespace std::placeholders;

return GetSectionHeaderInfo(m_section_headers,
std::bind(&ObjectFileELF::SetDataWithReadMemoryFallback, this, _1, _2, _3),
m_header,
m_uuid,
m_gnu_debuglink_file,
m_gnu_debuglink_crc,
m_arch_spec);
}

lldb::offset_t
ObjectFileELF::SetData(const lldb_private::DataExtractor &src, lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length)
{
return dst.SetData(src, offset, length);
}

lldb::offset_t
ObjectFileELF::SetDataWithReadMemoryFallback(lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length)
{
if (offset + length <= m_data.GetByteSize())
return dst.SetData(m_data, offset, length);

const auto process_sp = m_process_wp.lock();
if (process_sp != nullptr)
{
addr_t file_size = offset + length;

DataBufferSP data_sp = ReadMemory(process_sp, m_memory_addr, file_size);
if (!data_sp)
return false;
m_data.SetData(data_sp, 0, file_size);
}

return dst.SetData(m_data, offset, length);
}

const ObjectFileELF::ELFSectionHeaderInfo *
Expand Down
13 changes: 11 additions & 2 deletions lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
Expand Up @@ -14,6 +14,7 @@
#include <stdint.h>

// C++ Includes
#include <functional>
#include <vector>

// Other libraries and framework includes
Expand Down Expand Up @@ -231,6 +232,7 @@ class ObjectFileELF :
typedef DynamicSymbolColl::const_iterator DynamicSymbolCollConstIter;

typedef std::map<lldb::addr_t, lldb::AddressClass> FileAddressToAddressClassMap;
typedef std::function<lldb::offset_t (lldb_private::DataExtractor &, lldb::offset_t, lldb::offset_t)> SetDataFunction;

/// Version of this reader common to all plugins based on this class.
static const uint32_t m_plugin_version = 1;
Expand Down Expand Up @@ -279,7 +281,7 @@ class ObjectFileELF :
// Parses the ELF program headers.
static size_t
GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
lldb_private::DataExtractor &data,
const SetDataFunction &set_data,
const elf::ELFHeader &header);

// Finds PT_NOTE segments and calculates their crc sum.
Expand All @@ -302,7 +304,7 @@ class ObjectFileELF :
/// Parses the elf section headers and returns the uuid, debug link name, crc, archspec.
static size_t
GetSectionHeaderInfo(SectionHeaderColl &section_headers,
lldb_private::DataExtractor &data,
const SetDataFunction &set_data,
const elf::ELFHeader &header,
lldb_private::UUID &uuid,
std::string &gnu_debuglink_file,
Expand Down Expand Up @@ -437,6 +439,13 @@ class ObjectFileELF :

static lldb_private::Error
RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch_spec, lldb_private::UUID &uuid);


static lldb::offset_t
SetData(const lldb_private::DataExtractor &src, lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length);

lldb::offset_t
SetDataWithReadMemoryFallback(lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length);
};

#endif // liblldb_ObjectFileELF_h_

0 comments on commit 15f89c4

Please sign in to comment.