reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
//===-- SymbolVendorELF.cpp ----------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "SymbolVendorELF.h"

#include <string.h>

#include "Plugins/ObjectFile/ELF/ObjectFileELF.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/Symbol/LocateSymbolFile.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Target.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 nullptr;

  ObjectFileELF *obj_file =
      llvm::dyn_cast_or_null<ObjectFileELF>(module_sp->GetObjectFile());
  if (!obj_file)
    return nullptr;

  lldb_private::UUID uuid = obj_file->GetUUID();
  if (!uuid)
    return nullptr;

  // If the main object file already contains debug info, then we are done.
  if (obj_file->GetSectionList()->FindSectionByType(
          lldb::eSectionTypeDWARFDebugInfo, true))
    return nullptr;

  // If the module specified a filespec, use that.
  FileSpec fspec = module_sp->GetSymbolFileFileSpec();
  // Otherwise, try gnu_debuglink, if one exists.
  if (!fspec)
    fspec = obj_file->GetDebugLink().getValueOr(FileSpec());

  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(func_cat, "SymbolVendorELF::CreateInstance (module = %s)",
                     module_sp->GetFileSpec().GetPath().c_str());

  ModuleSpec module_spec;

  module_spec.GetFileSpec() = obj_file->GetFileSpec();
  FileSystem::Instance().Resolve(module_spec.GetFileSpec());
  module_spec.GetSymbolFileSpec() = fspec;
  module_spec.GetUUID() = uuid;
  FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
  FileSpec dsym_fspec =
      Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
  if (!dsym_fspec)
    return nullptr;

  DataBufferSP dsym_file_data_sp;
  lldb::offset_t dsym_file_data_offset = 0;
  ObjectFileSP dsym_objfile_sp = ObjectFile::FindPlugin(
      module_sp, &dsym_fspec, 0, FileSystem::Instance().GetByteSize(dsym_fspec),
      dsym_file_data_sp, dsym_file_data_offset);
  if (!dsym_objfile_sp)
    return nullptr;

  // 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);

  // 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 (SectionType section_type : g_sections) {
    if (SectionSP section_sp =
            objfile_section_list->FindSectionByType(section_type, true)) {
      if (SectionSP module_section_sp =
              module_section_list->FindSectionByType(section_type, true))
        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;
}

// PluginInterface protocol
ConstString SymbolVendorELF::GetPluginName() { return GetPluginNameStatic(); }

uint32_t SymbolVendorELF::GetPluginVersion() { return 1; }