Greg Clayton 56d9a1b31b Added a new plug-in type: lldb_private::OperatingSystem. The operating system
plug-ins are add on plug-ins for the lldb_private::Process class that can add
thread contexts that are read from memory. It is common in kernels to have
a lot of threads that are not currently executing on any cores (JTAG debugging
also follows this sort of thing) and are context switched out whose state is
stored in memory data structures. Clients can now subclass the OperatingSystem
plug-ins and then make sure their Create functions correcltly only enable 
themselves when the right binary/target triple are being debugged. The 
operating system plug-ins get a chance to attach themselves to processes just
after launching or attaching and are given a lldb_private::Process object 
pointer which can be inspected to see if the main executable, target triple,
or any shared  libraries match a case where the OS plug-in should be used.
Currently the OS plug-ins can create new threads, define the register contexts
for these threads (which can all be different if desired), and populate and
manage the thread info (stop reason, registers in the register context) as
the debug session goes on.

llvm-svn: 138228
2011-08-22 02:49:39 +00:00

732 lines
19 KiB
C++

//===-- Section.cpp ---------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/Section.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
Section::Section
(
Section *parent,
Module* module,
user_id_t sect_id,
const ConstString &name,
SectionType sect_type,
addr_t file_addr,
addr_t byte_size,
uint64_t file_offset,
uint64_t file_size,
uint32_t flags
) :
ModuleChild (module),
UserID (sect_id),
Flags (flags),
m_parent (parent),
m_name (name),
m_type (sect_type),
m_file_addr (file_addr),
m_byte_size (byte_size),
m_file_offset (file_offset),
m_file_size (file_size),
m_children (),
m_fake (false),
m_linked_section(NULL),
m_linked_offset (0)
{
}
Section::~Section()
{
}
// Get a valid shared pointer to this section object
SectionSP
Section::GetSharedPointer() const
{
SectionSP this_sp;
if (m_parent)
this_sp = m_parent->GetChildren().GetSharedPointer (this, false);
else
{
ObjectFile *objfile = m_module->GetObjectFile();
if (objfile)
{
SectionList *section_list = objfile->GetSectionList();
if (section_list)
this_sp = section_list->GetSharedPointer (this, false);
}
}
return this_sp;
}
ConstString&
Section::GetName()
{
if (m_linked_section)
return const_cast<Section *>(m_linked_section)->GetName();
return m_name;
}
const ConstString&
Section::GetName() const
{
if (m_linked_section)
return m_linked_section->GetName();
return m_name;
}
addr_t
Section::GetFileAddress () const
{
if (m_parent)
{
// This section has a parent which means m_file_addr is an offset into
// the parent section, so the file address for this section is the file
// address of the parent plus the offset
return m_parent->GetFileAddress() + m_file_addr;
}
// This section has no parent, so m_file_addr is the file base address
return m_file_addr;
}
addr_t
Section::GetLinkedFileAddress () const
{
if (m_linked_section)
return m_linked_section->GetFileAddress() + m_linked_offset;
return LLDB_INVALID_ADDRESS;
}
addr_t
Section::GetLoadBaseAddress (Target *target) const
{
addr_t load_base_addr = LLDB_INVALID_ADDRESS;
if (m_linked_section)
{
load_base_addr = m_linked_section->GetLoadBaseAddress(target);
if (load_base_addr != LLDB_INVALID_ADDRESS)
load_base_addr += m_linked_offset;
}
else
if (m_parent)
{
load_base_addr = m_parent->GetLoadBaseAddress (target);
if (load_base_addr != LLDB_INVALID_ADDRESS)
load_base_addr += GetOffset();
}
else
{
load_base_addr = target->GetSectionLoadList().GetSectionLoadAddress (this);
}
return load_base_addr;
}
bool
Section::ResolveContainedAddress (addr_t offset, Address &so_addr) const
{
const uint32_t num_children = m_children.GetSize();
if (num_children > 0)
{
for (uint32_t i=0; i<num_children; i++)
{
Section* child_section = m_children.GetSectionAtIndex (i).get();
addr_t child_offset = child_section->GetOffset();
if (child_offset <= offset && offset - child_offset < child_section->GetByteSize())
return child_section->ResolveContainedAddress (offset - child_offset, so_addr);
}
}
if (m_linked_section)
{
so_addr.SetOffset(m_linked_offset + offset);
so_addr.SetSection(m_linked_section);
}
else
{
so_addr.SetOffset(offset);
so_addr.SetSection(this);
}
return true;
}
bool
Section::ContainsFileAddress (addr_t vm_addr) const
{
const addr_t file_addr = GetFileAddress();
if (file_addr != LLDB_INVALID_ADDRESS)
{
if (file_addr <= vm_addr)
{
const addr_t offset = vm_addr - file_addr;
return offset < GetByteSize();
}
}
return false;
}
bool
Section::ContainsLinkedFileAddress (addr_t vm_addr) const
{
const addr_t linked_file_addr = GetLinkedFileAddress();
if (linked_file_addr != LLDB_INVALID_ADDRESS)
{
if (linked_file_addr <= vm_addr)
{
const addr_t offset = vm_addr - linked_file_addr;
return offset < GetByteSize();
}
}
return false;
}
int
Section::Compare (const Section& a, const Section& b)
{
if (&a == &b)
return 0;
const Module* a_module = a.GetModule();
const Module* b_module = b.GetModule();
if (a_module == b_module)
{
user_id_t a_sect_uid = a.GetID();
user_id_t b_sect_uid = b.GetID();
if (a_sect_uid < b_sect_uid)
return -1;
if (a_sect_uid > b_sect_uid)
return 1;
return 0;
}
else
{
// The modules are different, just compare the module pointers
if (a_module < b_module)
return -1;
else
return 1; // We already know the modules aren't equal
}
}
void
Section::Dump (Stream *s, Target *target, uint32_t depth) const
{
// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
s->Indent();
s->Printf("0x%8.8x %-14s ", GetID(), GetSectionTypeAsCString (m_type));
bool resolved = true;
addr_t addr = LLDB_INVALID_ADDRESS;
if (GetByteSize() == 0)
s->Printf("%39s", "");
else
{
if (target && m_linked_section == NULL)
addr = GetLoadBaseAddress (target);
if (addr == LLDB_INVALID_ADDRESS)
{
if (target)
resolved = false;
addr = GetFileAddress();
}
VMRange range(addr, addr + m_byte_size);
range.Dump (s, 0);
}
s->Printf("%c 0x%8.8llx 0x%8.8llx 0x%8.8x ", resolved ? ' ' : '*', m_file_offset, m_file_size, Get());
DumpName (s);
s->EOL();
if (m_linked_section)
{
addr = LLDB_INVALID_ADDRESS;
resolved = true;
if (target)
{
addr = m_linked_section->GetLoadBaseAddress(target);
if (addr != LLDB_INVALID_ADDRESS)
addr += m_linked_offset;
}
if (addr == LLDB_INVALID_ADDRESS)
{
if (target)
resolved = false;
addr = m_linked_section->GetFileAddress() + m_linked_offset;
}
int indent = 26 + s->GetIndentLevel();
s->Printf("%*.*s", indent, indent, "");
VMRange linked_range(addr, addr + m_byte_size);
linked_range.Dump (s, 0);
indent = 3 * (sizeof(uint32_t) * 2 + 2 + 1) + 1;
s->Printf("%c%*.*s", resolved ? ' ' : '*', indent, indent, "");
m_linked_section->DumpName(s);
s->Printf(" + 0x%llx\n", m_linked_offset);
}
if (depth > 0)
m_children.Dump(s, target, false, depth - 1);
}
void
Section::DumpName (Stream *s) const
{
if (m_parent == NULL)
{
// The top most section prints the module basename
const char *module_basename = m_module->GetFileSpec().GetFilename().AsCString();
if (module_basename && module_basename[0])
s->Printf("%s.", module_basename);
}
else
{
m_parent->DumpName (s);
s->PutChar('.');
}
m_name.Dump(s);
}
//----------------------------------------------------------------------
// Get the section data from a complete contiguous copy of the
// entire executable image.
//----------------------------------------------------------------------
size_t
Section::GetSectionDataFromImage (const DataExtractor& image_data, DataExtractor& section_data) const
{
size_t file_size = GetByteSize();
if (file_size > 0)
{
off_t file_offset = GetFileOffset();
if (section_data.SetData (image_data, file_offset, file_size) == file_size)
return true;
}
return false;
}
size_t
Section::ReadSectionDataFromObjectFile (const ObjectFile* objfile, off_t section_offset, void *dst, size_t dst_len) const
{
if (objfile && dst && dst_len)
{
const FileSpec& file = objfile->GetFileSpec();
if (file)
{
size_t bytes_left = dst_len;
size_t bytes_read = 0;
const uint64_t file_size = GetFileSize();
if (section_offset < file_size)
{
off_t section_file_offset = objfile->GetOffset() + GetFileOffset() + section_offset;
bytes_read = file.ReadFileContents (section_file_offset, dst, dst_len);
if (bytes_read >= dst_len)
return bytes_read;
bytes_left -= bytes_read;
}
const uint64_t byte_size = GetByteSize();
if (section_offset + bytes_read < byte_size)
{
memset ((uint8_t*)dst + bytes_read, 0, bytes_left);
bytes_read += bytes_left;
}
return bytes_read;
}
}
return 0;
}
//----------------------------------------------------------------------
// Get the section data the file on disk
//----------------------------------------------------------------------
size_t
Section::ReadSectionDataFromObjectFile(const ObjectFile* objfile, DataExtractor& section_data) const
{
if (objfile == NULL)
return 0;
const FileSpec& file = objfile->GetFileSpec();
if (file)
{
size_t section_file_size = GetByteSize();
if (section_file_size > 0)
{
off_t section_file_offset = GetFileOffset() + objfile->GetOffset();
DataBufferSP section_data_sp(file.ReadFileContents(section_file_offset, section_file_size));
section_data.SetByteOrder(objfile->GetByteOrder());
section_data.SetAddressByteSize(objfile->GetAddressByteSize());
return section_data.SetData (section_data_sp);
}
}
return 0;
}
size_t
Section::MemoryMapSectionDataFromObjectFile(const ObjectFile* objfile, DataExtractor& section_data) const
{
if (objfile == NULL)
return 0;
const FileSpec& file = objfile->GetFileSpec();
if (file)
{
size_t section_file_size = GetFileSize();
if (section_file_size > 0)
{
off_t section_file_offset = GetFileOffset() + objfile->GetOffset();
DataBufferSP section_data_sp(file.MemoryMapFileContents(section_file_offset, section_file_size));
section_data.SetByteOrder(objfile->GetByteOrder());
section_data.SetAddressByteSize(objfile->GetAddressByteSize());
return section_data.SetData (section_data_sp);
}
}
return 0;
}
bool
Section::IsDescendant (const Section *section)
{
if (this == section)
return true;
if (m_parent)
return m_parent->IsDescendant (section);
return false;
}
bool
Section::Slide (addr_t slide_amount, bool slide_children)
{
if (m_file_addr != LLDB_INVALID_ADDRESS)
{
if (slide_amount == 0)
return true;
m_file_addr += slide_amount;
if (slide_children)
m_children.Slide (slide_amount, slide_children);
return true;
}
return false;
}
void
Section::SetLinkedLocation (const Section *linked_section, uint64_t linked_offset)
{
if (linked_section)
m_module = linked_section->GetModule();
m_linked_section = linked_section;
m_linked_offset = linked_offset;
}
#pragma mark SectionList
SectionList::SectionList () :
m_sections()
{
}
SectionList::~SectionList ()
{
}
uint32_t
SectionList::AddSection (SectionSP& sect_sp)
{
uint32_t section_index = m_sections.size();
m_sections.push_back(sect_sp);
return section_index;
}
uint32_t
SectionList::FindSectionIndex (const Section* sect)
{
iterator sect_iter;
iterator begin = m_sections.begin();
iterator end = m_sections.end();
for (sect_iter = begin; sect_iter != end; ++sect_iter)
{
if (sect_iter->get() == sect)
{
// The secton was already in this section list
return std::distance (begin, sect_iter);
}
}
return UINT32_MAX;
}
uint32_t
SectionList::AddUniqueSection (SectionSP& sect_sp)
{
uint32_t sect_idx = FindSectionIndex (sect_sp.get());
if (sect_idx == UINT32_MAX)
sect_idx = AddSection (sect_sp);
return sect_idx;
}
bool
SectionList::ReplaceSection (user_id_t sect_id, SectionSP& sect_sp, uint32_t depth)
{
iterator sect_iter, end = m_sections.end();
for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
{
if ((*sect_iter)->GetID() == sect_id)
{
*sect_iter = sect_sp;
return true;
}
else if (depth > 0)
{
if ((*sect_iter)->GetChildren().ReplaceSection(sect_id, sect_sp, depth - 1))
return true;
}
}
return false;
}
size_t
SectionList::GetNumSections (uint32_t depth) const
{
size_t count = m_sections.size();
if (depth > 0)
{
const_iterator sect_iter, end = m_sections.end();
for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
{
count += (*sect_iter)->GetChildren().GetNumSections(depth - 1);
}
}
return count;
}
SectionSP
SectionList::GetSectionAtIndex (uint32_t idx) const
{
SectionSP sect_sp;
if (idx < m_sections.size())
sect_sp = m_sections[idx];
return sect_sp;
}
SectionSP
SectionList::FindSectionByName (const ConstString &section_dstr) const
{
SectionSP sect_sp;
// Check if we have a valid section string
if (section_dstr)
{
const_iterator sect_iter;
const_iterator end = m_sections.end();
for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
{
if ((*sect_iter)->GetName() == section_dstr)
{
sect_sp = *sect_iter;
}
else
{
sect_sp = (*sect_iter)->GetChildren().FindSectionByName(section_dstr);
}
}
}
return sect_sp;
}
SectionSP
SectionList::FindSectionByID (user_id_t sect_id) const
{
SectionSP sect_sp;
if (sect_id)
{
const_iterator sect_iter;
const_iterator end = m_sections.end();
for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
{
if ((*sect_iter)->GetID() == sect_id)
{
sect_sp = *sect_iter;
break;
}
else
{
sect_sp = (*sect_iter)->GetChildren().FindSectionByID (sect_id);
}
}
}
return sect_sp;
}
SectionSP
SectionList::FindSectionByType (SectionType sect_type, bool check_children, uint32_t start_idx) const
{
SectionSP sect_sp;
uint32_t num_sections = m_sections.size();
for (uint32_t idx = start_idx; idx < num_sections; ++idx)
{
if (m_sections[idx]->GetType() == sect_type)
{
sect_sp = m_sections[idx];
break;
}
else if (check_children)
{
sect_sp = m_sections[idx]->GetChildren().FindSectionByType (sect_type, check_children, 0);
if (sect_sp)
break;
}
}
return sect_sp;
}
SectionSP
SectionList::GetSharedPointer (const Section *section, bool check_children) const
{
SectionSP sect_sp;
if (section)
{
const_iterator sect_iter;
const_iterator end = m_sections.end();
for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
{
if (sect_iter->get() == section)
{
sect_sp = *sect_iter;
break;
}
else if (check_children)
{
sect_sp = (*sect_iter)->GetChildren().GetSharedPointer (section, true);
}
}
}
return sect_sp;
}
SectionSP
SectionList::FindSectionContainingFileAddress (addr_t vm_addr, uint32_t depth) const
{
SectionSP sect_sp;
const_iterator sect_iter;
const_iterator end = m_sections.end();
for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
{
Section *sect = sect_iter->get();
if (sect->ContainsFileAddress (vm_addr))
{
// The file address is in this section. We need to make sure one of our child
// sections doesn't contain this address as well as obeying the depth limit
// that was passed in.
if (depth > 0)
sect_sp = sect->GetChildren().FindSectionContainingFileAddress(vm_addr, depth - 1);
if (sect_sp.get() == NULL && !sect->IsFake())
sect_sp = *sect_iter;
}
}
return sect_sp;
}
SectionSP
SectionList::FindSectionContainingLinkedFileAddress (addr_t vm_addr, uint32_t depth) const
{
SectionSP sect_sp;
const_iterator sect_iter;
const_iterator end = m_sections.end();
for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter)
{
Section *sect = sect_iter->get();
if (sect->ContainsLinkedFileAddress (vm_addr))
{
sect_sp = *sect_iter;
}
else if (depth > 0)
{
sect_sp = sect->GetChildren().FindSectionContainingLinkedFileAddress (vm_addr, depth - 1);
}
}
return sect_sp;
}
bool
SectionList::ContainsSection(user_id_t sect_id) const
{
return FindSectionByID (sect_id).get() != NULL;
}
void
SectionList::Dump (Stream *s, Target *target, bool show_header, uint32_t depth) const
{
bool target_has_loaded_sections = target && !target->GetSectionLoadList().IsEmpty();
if (show_header && !m_sections.empty())
{
// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
// s->Indent();
// s->PutCString( "SectionList\n");
// s->IndentMore();
// s->Printf("%*s", 2*(sizeof(void *) + 2), "");
s->Indent();
s->Printf("SectID Type %s Address File Off. File Size Flags Section Name\n", target_has_loaded_sections ? "Load" : "File");
// s->Printf("%*s", 2*(sizeof(void *) + 2), "");
s->Indent();
s->PutCString("---------- -------------- --------------------------------------- ---------- ---------- ---------- ----------------------------\n");
}
const_iterator sect_iter;
const_iterator end = m_sections.end();
for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter)
{
(*sect_iter)->Dump(s, target_has_loaded_sections ? target : NULL, depth);
}
if (show_header && !m_sections.empty())
s->IndentLess();
}
size_t
SectionList::Slide (addr_t slide_amount, bool slide_children)
{
size_t count = 0;
const_iterator pos, end = m_sections.end();
for (pos = m_sections.begin(); pos != end; ++pos)
{
if ((*pos)->Slide(slide_amount, slide_children))
++count;
}
return count;
}