text: //===-- SymbolVendorELF.cpp ----------------------------------*- C++ -*-===//
  //
  //                     The LLVM Compiler Infrastructure
  //
  // This file is distributed under the University of Illinois Open Source
  // License. See LICENSE.TXT for details.
  //
  //===----------------------------------------------------------------------===//
  
  #include "SymbolVendorELF.h"
  
  #include <string.h>
  
  #include "lldb/Core/Module.h"
  #include "lldb/Core/ModuleSpec.h"
  #include "lldb/Core/PluginManager.h"
  #include "lldb/Core/Section.h"
  #include "lldb/Host/Host.h"
  #include "lldb/Host/Symbols.h"
  #include "lldb/Symbol/ObjectFile.h"
  #include "lldb/Utility/StreamString.h"
  #include "lldb/Utility/Timer.h"
  
  using namespace lldb;
  using namespace lldb_private;
  
  //----------------------------------------------------------------------
  // SymbolVendorELF constructor
  //----------------------------------------------------------------------
  SymbolVendorELF::SymbolVendorELF(const lldb::ModuleSP &module_sp)
      : SymbolVendor(module_sp) {}
  
  //----------------------------------------------------------------------
  // Destructor
  //----------------------------------------------------------------------
  SymbolVendorELF::~SymbolVendorELF() {}
  
  void SymbolVendorELF::Initialize() {
    PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                  GetPluginDescriptionStatic(), CreateInstance);
  }
  
  void SymbolVendorELF::Terminate() {
    PluginManager::UnregisterPlugin(CreateInstance);
  }
  
  lldb_private::ConstString SymbolVendorELF::GetPluginNameStatic() {
    static ConstString g_name("ELF");
    return g_name;
  }
  
  const char *SymbolVendorELF::GetPluginDescriptionStatic() {
    return "Symbol vendor for ELF that looks for dSYM files that match "
           "executables.";
  }
  
  //----------------------------------------------------------------------
  // CreateInstance
  //
  // Platforms can register a callback to use when creating symbol vendors to
  // allow for complex debug information file setups, and to also allow for
  // finding separate debug information files.
  //----------------------------------------------------------------------
  SymbolVendor *
  SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp,
                                  lldb_private::Stream *feedback_strm) {
    if (!module_sp)
      return NULL;
  
    ObjectFile *obj_file = module_sp->GetObjectFile();
    if (!obj_file)
      return NULL;
  
    static ConstString obj_file_elf("elf");
    ConstString obj_name = obj_file->GetPluginName();
    if (obj_name != obj_file_elf)
      return NULL;
  
    lldb_private::UUID uuid;
    if (!obj_file->GetUUID(&uuid))
      return NULL;
  
    // Get the .gnu_debuglink file (if specified).
    FileSpecList file_spec_list = obj_file->GetDebugSymbolFilePaths();
  
    // If the module specified a filespec, use it first.
    FileSpec debug_symbol_fspec(module_sp->GetSymbolFileFileSpec());
    if (debug_symbol_fspec)
      file_spec_list.Insert(0, debug_symbol_fspec);
  
    // If we have no debug symbol files, then nothing to do.
    if (file_spec_list.IsEmpty())
      return NULL;
  
    static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
    Timer scoped_timer(func_cat, "SymbolVendorELF::CreateInstance (module = %s)",
                       module_sp->GetFileSpec().GetPath().c_str());
  
    for (size_t idx = 0; idx < file_spec_list.GetSize(); ++idx) {
      ModuleSpec module_spec;
      const FileSpec fspec = file_spec_list.GetFileSpecAtIndex(idx);
  
      module_spec.GetFileSpec() = obj_file->GetFileSpec();
      module_spec.GetFileSpec().ResolvePath();
      module_spec.GetSymbolFileSpec() = fspec;
      module_spec.GetUUID() = uuid;
      FileSpec dsym_fspec = Symbols::LocateExecutableSymbolFile(module_spec);
      if (dsym_fspec) {
        DataBufferSP dsym_file_data_sp;
        lldb::offset_t dsym_file_data_offset = 0;
        ObjectFileSP dsym_objfile_sp = ObjectFile::FindPlugin(
            module_sp, &dsym_fspec, 0, dsym_fspec.GetByteSize(),
            dsym_file_data_sp, dsym_file_data_offset);
        if (dsym_objfile_sp) {
          // This objfile is for debugging purposes. Sadly, ObjectFileELF won't
          // be able to figure this out consistently as the symbol file may not
          // have stripped the code sections, etc.
          dsym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo);
  
          SymbolVendorELF *symbol_vendor = new SymbolVendorELF(module_sp);
          if (symbol_vendor) {
            // Get the module unified section list and add our debug sections to
            // that.
            SectionList *module_section_list = module_sp->GetSectionList();
            SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList();
  
            static const SectionType g_sections[] = {
                eSectionTypeDWARFDebugAbbrev,   eSectionTypeDWARFDebugAddr,
                eSectionTypeDWARFDebugAranges,  eSectionTypeDWARFDebugCuIndex,
                eSectionTypeDWARFDebugFrame,    eSectionTypeDWARFDebugInfo,
                eSectionTypeDWARFDebugLine,     eSectionTypeDWARFDebugLoc,
                eSectionTypeDWARFDebugMacInfo,  eSectionTypeDWARFDebugPubNames,
                eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges,
                eSectionTypeDWARFDebugStr,      eSectionTypeDWARFDebugStrOffsets,
                eSectionTypeELFSymbolTable,     eSectionTypeDWARFGNUDebugAltLink,
            };
            for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]);
                 ++idx) {
              SectionType section_type = g_sections[idx];
              SectionSP section_sp(
                  objfile_section_list->FindSectionByType(section_type, true));
              if (section_sp) {
                SectionSP module_section_sp(
                    module_section_list->FindSectionByType(section_type, true));
                if (module_section_sp)
                  module_section_list->ReplaceSection(module_section_sp->GetID(),
                                                      section_sp);
                else
                  module_section_list->AddSection(section_sp);
              }
            }
  
            symbol_vendor->AddSymbolFileRepresentation(dsym_objfile_sp);
            return symbol_vendor;
          }
        }
      }
    }
    return NULL;
  }
  
  //------------------------------------------------------------------
  // PluginInterface protocol
  //------------------------------------------------------------------
  ConstString SymbolVendorELF::GetPluginName() { return GetPluginNameStatic(); }
  
  uint32_t SymbolVendorELF::GetPluginVersion() { return 1; }
  