alvinhochun created this revision.
alvinhochun added reviewers: labath, DavidSpickett, mstorsjo.
Herald added a project: All.
alvinhochun requested review of this revision.
Herald added projects: LLDB, LLVM.
Herald added subscribers: llvm-commits, lldb-commits.

This reimplements `ObjectFilePECOFF::ParseSymtab` with the following
changes:

- When the image has both an export table and a COFF symbol table, the symbols 
obtained from the symbol table no longer get erased.
- Remove manual data extraction in favour of using what `COFFObjectFile` 
provides.
- Mark symbols from the export table as "External" instead of "Debug".
- Support DLL forwarder exports (marked as re-exported).
- Handle absolute symbols in the symbol table.
- Heuristically set some symbol types. Symbols in the symbol table starting in 
`__imp_` (dllimport IAT reference) or `.refptr.` (mingw stub) are marked as 
"Data", because their locations store a pointer address.
- When a symbol in the symbol table is a duplicate of an exported symbol, its 
info will be synchronized with the exported symbol, then it will be marked as 
"Additional" type to avoid unwanted repetition when used in commands like 
`disassemble`.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134133

Files:
  lldb/include/lldb/Symbol/Symtab.h
  lldb/source/Commands/CommandObjectTarget.cpp
  lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
  lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
  lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
  lldb/source/Symbol/Symtab.cpp
  llvm/include/llvm/Object/COFF.h

Index: llvm/include/llvm/Object/COFF.h
===================================================================
--- llvm/include/llvm/Object/COFF.h
+++ llvm/include/llvm/Object/COFF.h
@@ -914,6 +914,10 @@
 
   uint32_t getStringTableSize() const { return StringTableSize; }
 
+  const export_directory_table_entry *getExportTable() const {
+    return ExportDirectory;
+  }
+
   const coff_load_configuration32 *getLoadConfig32() const {
     assert(!is64());
     return reinterpret_cast<const coff_load_configuration32 *>(LoadConfig);
Index: lldb/source/Symbol/Symtab.cpp
===================================================================
--- lldb/source/Symbol/Symtab.cpp
+++ lldb/source/Symbol/Symtab.cpp
@@ -61,6 +61,14 @@
   return m_symbols.empty() ? nullptr : &m_symbols[0];
 }
 
+Symbol *Symtab::Extend(size_t count) {
+  // Clients should grab the mutex from this symbol table and lock it manually
+  // when calling this function to avoid performance issues.
+  auto old_size = m_symbols.size();
+  m_symbols.resize(old_size + count);
+  return m_symbols.empty() ? nullptr : &m_symbols[old_size];
+}
+
 uint32_t Symtab::AddSymbol(const Symbol &symbol) {
   // Clients should grab the mutex from this symbol table and lock it manually
   // when calling this function to avoid performance issues.
@@ -809,6 +817,22 @@
   return nullptr;
 }
 
+bool Symtab::HasSymbolWithType(SymbolType symbol_type, Debug symbol_debug_type,
+                               Visibility symbol_visibility) const {
+  std::lock_guard<std::recursive_mutex> guard(m_mutex);
+
+  const size_t count = m_symbols.size();
+  for (size_t idx = 0; idx < count; ++idx) {
+    if (symbol_type == eSymbolTypeAny ||
+        m_symbols[idx].GetType() == symbol_type) {
+      if (CheckSymbolAtIndex(idx, symbol_debug_type, symbol_visibility)) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
 void
 Symtab::FindAllSymbolsWithNameAndType(ConstString name,
                                       SymbolType symbol_type,
Index: lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
+++ lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -81,6 +81,11 @@
         abilities |= Functions;
       }
 
+      if (symtab->HasSymbolWithType(eSymbolTypeReExported, Symtab::eDebugAny,
+                                    Symtab::eVisibilityAny)) {
+        abilities |= Functions;
+      }
+
       if (symtab->AppendSymbolIndexesWithType(eSymbolTypeData,
                                               m_data_indexes)) {
         symtab->SortSymbolIndexesByValue(m_data_indexes, true);
Index: lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
===================================================================
--- lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
+++ lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
@@ -225,12 +225,6 @@
         data_dirs; // will contain num_data_dir_entries entries
   } coff_opt_header_t;
 
-  enum coff_data_dir_type {
-    coff_data_dir_export_table = 0,
-    coff_data_dir_import_table = 1,
-    coff_data_dir_exception_table = 3
-  };
-
   typedef struct section_header {
     char name[8] = {};
     uint32_t vmsize = 0;  // Virtual Size
@@ -244,29 +238,6 @@
     uint32_t flags = 0;
   } section_header_t;
 
-  typedef struct coff_symbol {
-    char name[8] = {};
-    uint32_t value = 0;
-    uint16_t sect = 0;
-    uint16_t type = 0;
-    uint8_t storage = 0;
-    uint8_t naux = 0;
-  } coff_symbol_t;
-
-  typedef struct export_directory_entry {
-    uint32_t characteristics = 0;
-    uint32_t time_date_stamp = 0;
-    uint16_t major_version = 0;
-    uint16_t minor_version = 0;
-    uint32_t name = 0;
-    uint32_t base = 0;
-    uint32_t number_of_functions = 0;
-    uint32_t number_of_names = 0;
-    uint32_t address_of_functions = 0;
-    uint32_t address_of_names = 0;
-    uint32_t address_of_name_ordinals = 0;
-  } export_directory_entry;
-
   static bool ParseDOSHeader(lldb_private::DataExtractor &data,
                              dos_header_t &dos_header);
   static bool ParseCOFFHeader(lldb_private::DataExtractor &data,
@@ -297,6 +268,12 @@
 
 private:
   bool CreateBinary();
+  void AppendFromCOFFSymbolTable(lldb_private::SectionList *sect_list,
+                                 const llvm::StringMap<uint32_t> &exported_syms,
+                                 lldb_private::Symtab &symtab);
+  void AppendFromExportTable(lldb_private::SectionList *sect_list,
+                             llvm::StringMap<uint32_t> &exported_syms,
+                             lldb_private::Symtab &symtab);
 
   dos_header_t m_dos_header;
   coff_header_t m_coff_header;
Index: lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
===================================================================
--- lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -30,14 +30,20 @@
 #include "lldb/Utility/StreamString.h"
 #include "lldb/Utility/Timer.h"
 #include "lldb/Utility/UUID.h"
-#include "llvm/BinaryFormat/COFF.h"
 
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/COFF.h"
 #include "llvm/Object/COFFImportFile.h"
 #include "llvm/Support/CRC.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/FormatAdapters.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/MemoryBuffer.h"
 
+#include <cstdint>
+
 #define IMAGE_DOS_SIGNATURE 0x5A4D    // MZ
 #define IMAGE_NT_SIGNATURE 0x00004550 // PE00
 #define OPT_HEADER_MAGIC_PE32 0x010b
@@ -760,131 +766,173 @@
 
 void ObjectFilePECOFF::ParseSymtab(Symtab &symtab) {
   SectionList *sect_list = GetSectionList();
-  const uint32_t num_syms = m_coff_header.nsyms;
-  if (m_file && num_syms > 0 && m_coff_header.symoff > 0) {
-    const uint32_t symbol_size = 18;
-    const size_t symbol_data_size = num_syms * symbol_size;
-    // Include the 4-byte string table size at the end of the symbols
-    DataExtractor symtab_data =
-        ReadImageData(m_coff_header.symoff, symbol_data_size + 4);
-    lldb::offset_t offset = symbol_data_size;
-    const uint32_t strtab_size = symtab_data.GetU32(&offset);
-    if (strtab_size > 0) {
-      DataExtractor strtab_data = ReadImageData(
-          m_coff_header.symoff + symbol_data_size, strtab_size);
-
-      offset = 0;
-      std::string symbol_name;
-      Symbol *symbols = symtab.Resize(num_syms);
-      for (uint32_t i = 0; i < num_syms; ++i) {
-        coff_symbol_t symbol;
-        const uint32_t symbol_offset = offset;
-        const char *symbol_name_cstr = nullptr;
-        // If the first 4 bytes of the symbol string are zero, then they
-        // are followed by a 4-byte string table offset. Else these
-        // 8 bytes contain the symbol name
-        if (symtab_data.GetU32(&offset) == 0) {
-          // Long string that doesn't fit into the symbol table name, so
-          // now we must read the 4 byte string table offset
-          uint32_t strtab_offset = symtab_data.GetU32(&offset);
-          symbol_name_cstr = strtab_data.PeekCStr(strtab_offset);
-          symbol_name.assign(symbol_name_cstr);
-        } else {
-          // Short string that fits into the symbol table name which is 8
-          // bytes
-          offset += sizeof(symbol.name) - 4; // Skip remaining
-          symbol_name_cstr = symtab_data.PeekCStr(symbol_offset);
-          if (symbol_name_cstr == nullptr)
-            break;
-          symbol_name.assign(symbol_name_cstr, sizeof(symbol.name));
-        }
-        symbol.value = symtab_data.GetU32(&offset);
-        symbol.sect = symtab_data.GetU16(&offset);
-        symbol.type = symtab_data.GetU16(&offset);
-        symbol.storage = symtab_data.GetU8(&offset);
-        symbol.naux = symtab_data.GetU8(&offset);
-        symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str()));
-        if ((int16_t)symbol.sect >= 1) {
-          Address symbol_addr(sect_list->FindSectionByID(symbol.sect),
-                              symbol.value);
-          symbols[i].GetAddressRef() = symbol_addr;
-          symbols[i].SetType(MapSymbolType(symbol.type));
-        }
+  llvm::StringMap<uint32_t> exported_syms;
+  AppendFromExportTable(sect_list, exported_syms, symtab);
+  AppendFromCOFFSymbolTable(sect_list, exported_syms, symtab);
+}
 
-        if (symbol.naux > 0) {
-          i += symbol.naux;
-          offset += symbol.naux * symbol_size;
-        }
+void ObjectFilePECOFF::AppendFromCOFFSymbolTable(
+    SectionList *sect_list, const llvm::StringMap<uint32_t> &exported_syms,
+    Symtab &symtab) {
+  Log *log = GetLog(LLDBLog::Object);
+  const uint32_t num_syms = m_binary->getNumberOfSymbols();
+  if (num_syms == 0)
+    return;
+  // Check that this is not a bigobj
+  if (m_binary->getSymbolTableEntrySize() !=
+      sizeof(llvm::object::coff_symbol16))
+    return;
+
+  Symbol *symbols = symtab.Extend(num_syms);
+  uint32_t i = 0;
+  for (const auto &sym_ref : m_binary->symbols()) {
+    const auto coff_sym_ref = m_binary->getCOFFSymbol(sym_ref);
+    auto name_or_error = sym_ref.getName();
+    if (auto err = name_or_error.takeError()) {
+      LLDB_LOG(log,
+               "ObjectFilePECOFF::AppendFromCOFFSymbolTable - failed to get "
+               "symbol table entry name: {0}",
+               llvm::fmt_consume(std::move(err)));
+      continue;
+    }
+    const llvm::StringRef sym_name = *name_or_error;
+    symbols[i].GetMangled().SetValue(ConstString(sym_name));
+    int16_t section_number =
+        static_cast<int16_t>(coff_sym_ref.getSectionNumber());
+    if (section_number >= 1) {
+      symbols[i].GetAddressRef() = Address(
+          sect_list->FindSectionByID(section_number), coff_sym_ref.getValue());
+      symbols[i].SetType(MapSymbolType(coff_sym_ref.getType()));
+      if (symbols[i].GetType() == lldb::eSymbolTypeInvalid)
+        if (sym_name.startswith("__imp_") || sym_name.startswith(".refptr."))
+          symbols[i].SetType(lldb::eSymbolTypeData);
+    } else if (section_number == -1) {
+      symbols[i].GetAddressRef() = Address(coff_sym_ref.getValue());
+      symbols[i].SetType(lldb::eSymbolTypeAbsolute);
+    }
+
+    // Handle duplicate of an exported symbol
+    const auto exported_it = exported_syms.find(sym_name);
+    if (exported_it != exported_syms.end()) {
+      Symbol *exported = symtab.SymbolAtIndex(exported_it->getValue());
+      if (exported->GetType() != lldb::eSymbolTypeReExported &&
+          exported->GetAddressRef() == symbols[i].GetAddressRef()) {
+        symbols[i].SetID(exported->GetID());
+        symbols[i].SetExternal(true);
+        // Previously we assumed an exported symbol is always code, now we
+        // fix it up if otherwise.
+        if (symbols[i].GetType() == lldb::eSymbolTypeInvalid)
+          symbols[i].SetType(lldb::eSymbolTypeData);
+        exported->SetType(symbols[i].GetType());
+        // We don't want the symbol to be duplicated (e.g. when running
+        // `disas -n func`), but we also want to keep this entry, so we mark it
+        // as additional.
+        symbols[i].SetType(lldb::eSymbolTypeAdditional);
       }
     }
+    i++;
   }
+  // Trim excess entries if we skipped any.
+  if (i < num_syms)
+    symtab.Resize(symtab.GetIndexForSymbol(&symbols[i]));
+}
 
-  // Read export header
-  if (coff_data_dir_export_table < m_coff_header_opt.data_dirs.size() &&
-      m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmsize > 0 &&
-      m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr > 0) {
-    export_directory_entry export_table;
-    uint32_t data_start =
-        m_coff_header_opt.data_dirs[coff_data_dir_export_table].vmaddr;
-
-    DataExtractor symtab_data = ReadImageDataByRVA(
-        data_start, m_coff_header_opt.data_dirs[0].vmsize);
-    lldb::offset_t offset = 0;
-
-    // Read export_table header
-    export_table.characteristics = symtab_data.GetU32(&offset);
-    export_table.time_date_stamp = symtab_data.GetU32(&offset);
-    export_table.major_version = symtab_data.GetU16(&offset);
-    export_table.minor_version = symtab_data.GetU16(&offset);
-    export_table.name = symtab_data.GetU32(&offset);
-    export_table.base = symtab_data.GetU32(&offset);
-    export_table.number_of_functions = symtab_data.GetU32(&offset);
-    export_table.number_of_names = symtab_data.GetU32(&offset);
-    export_table.address_of_functions = symtab_data.GetU32(&offset);
-    export_table.address_of_names = symtab_data.GetU32(&offset);
-    export_table.address_of_name_ordinals = symtab_data.GetU32(&offset);
-
-    bool has_ordinal = export_table.address_of_name_ordinals != 0;
-
-    lldb::offset_t name_offset = export_table.address_of_names - data_start;
-    lldb::offset_t name_ordinal_offset =
-        export_table.address_of_name_ordinals - data_start;
-
-    Symbol *symbols = symtab.Resize(export_table.number_of_names);
-
-    std::string symbol_name;
-
-    // Read each export table entry
-    for (size_t i = 0; i < export_table.number_of_names; ++i) {
-      uint32_t name_ordinal =
-          has_ordinal ? symtab_data.GetU16(&name_ordinal_offset) : i;
-      uint32_t name_address = symtab_data.GetU32(&name_offset);
-
-      const char *symbol_name_cstr =
-          symtab_data.PeekCStr(name_address - data_start);
-      symbol_name.assign(symbol_name_cstr);
-
-      lldb::offset_t function_offset = export_table.address_of_functions -
-                                        data_start +
-                                        sizeof(uint32_t) * name_ordinal;
-      uint32_t function_rva = symtab_data.GetU32(&function_offset);
+void ObjectFilePECOFF::AppendFromExportTable(
+    SectionList *sect_list, llvm::StringMap<uint32_t> &exported_syms,
+    Symtab &symtab) {
+  Log *log = GetLog(LLDBLog::Object);
+  const auto *export_table = m_binary->getExportTable();
+  if (!export_table)
+    return;
+  const uint32_t num_syms = export_table->AddressTableEntries;
+  if (num_syms == 0)
+    return;
 
+  Symbol *symbols = symtab.Extend(num_syms);
+  uint32_t i = 0;
+  // Read each export table entry, ordered by ordinal instead of by name.
+  for (const auto &entry : m_binary->export_directories()) {
+    llvm::StringRef sym_name;
+    if (auto err = entry.getSymbolName(sym_name)) {
+      LLDB_LOG(log,
+               "ObjectFilePECOFF::AppendFromExportTable - failed to get export "
+               "table entry name: {0}",
+               llvm::fmt_consume(std::move(err)));
+      continue;
+    }
+    // Note: symbol name may be empty if it is only exported by ordinal.
+    symbols[i].GetMangled().SetValue(ConstString(sym_name));
+
+    uint32_t ordinal;
+    llvm::cantFail(entry.getOrdinal(ordinal));
+    symbols[i].SetID(ordinal);
+
+    bool is_forwarder;
+    llvm::cantFail(entry.isForwarder(is_forwarder));
+    if (is_forwarder) {
+      // Forwarded export symbol name in the form of `DLLNAME.funcname` or
+      // `DLLNAME.#42`.
+      llvm::StringRef forwarder_name;
+      if (auto err = entry.getForwardTo(forwarder_name)) {
+        LLDB_LOG(log,
+                 "ObjectFilePECOFF::AppendFromExportTable - failed to get "
+                 "forwarder name of forwarder export '{0}': {1}",
+                 sym_name, llvm::fmt_consume(std::move(err)));
+        continue;
+      }
+      size_t dot_pos = forwarder_name.find_first_of('.');
+      if (dot_pos == llvm::StringRef::npos) {
+        LLDB_LOG(log,
+                 "ObjectFilePECOFF::AppendFromExportTable - forwarder export "
+                 "'{0}' has invalid forwarder name '{1}'",
+                 sym_name, forwarder_name);
+        symbols[i].SetType(lldb::eSymbolTypeInvalid);
+      } else {
+        llvm::StringRef reexport_name = forwarder_name.drop_front(dot_pos + 1);
+        // FIXME: How to handle forwarded ordinal number starting with `#`?
+        symbols[i].SetReExportedSymbolName(ConstString(reexport_name));
+
+        llvm::SmallString<128> dll_name{forwarder_name.take_front(dot_pos),
+                                        ".dll"};
+        FileSpec dll_spec(dll_name, FileSpec::Style::windows);
+        size_t index = m_deps_filespec->FindFileIndex(0, dll_spec, false);
+        if (index != UINT32_MAX)
+          symbols[i].SetReExportedSymbolSharedLibrary(
+              m_deps_filespec->GetFileSpecAtIndex(index));
+      }
+    } else {
+      uint32_t function_rva;
+      if (auto err = entry.getExportRVA(function_rva)) {
+        LLDB_LOG(log,
+                 "ObjectFilePECOFF::AppendFromExportTable - failed to get "
+                 "address of export entry '{0}': {1}",
+                 sym_name, llvm::fmt_consume(std::move(err)));
+        continue;
+      }
       Address symbol_addr(m_coff_header_opt.image_base + function_rva,
                           sect_list);
-      symbols[i].GetMangled().SetValue(ConstString(symbol_name.c_str()));
       symbols[i].GetAddressRef() = symbol_addr;
+      // Treat the exported symbol as code for now. An exported symbol may
+      // actually be data, but this is relatively rare and we cannot tell
+      // from just the export table.
       symbols[i].SetType(lldb::eSymbolTypeCode);
-      symbols[i].SetDebug(true);
+      symbols[i].SetExternal(true);
     }
+    if (!sym_name.empty())
+      exported_syms[sym_name] = symtab.GetIndexForSymbol(&symbols[i]);
+    i++;
   }
+  // Trim excess entries if we skipped any.
+  if (i < num_syms)
+    symtab.Resize(symtab.GetIndexForSymbol(&symbols[i]));
 }
 
 std::unique_ptr<CallFrameInfo> ObjectFilePECOFF::CreateCallFrameInfo() {
-  if (coff_data_dir_exception_table >= m_coff_header_opt.data_dirs.size())
+  if (llvm::COFF::EXCEPTION_TABLE >= m_coff_header_opt.data_dirs.size())
     return {};
 
   data_directory data_dir_exception =
-      m_coff_header_opt.data_dirs[coff_data_dir_exception_table];
+      m_coff_header_opt.data_dirs[llvm::COFF::EXCEPTION_TABLE];
   if (!data_dir_exception.vmaddr)
     return {};
 
@@ -1068,17 +1116,7 @@
 
   m_deps_filespec = FileSpecList();
 
-  for (const auto &entry : m_binary->import_directories()) {
-    llvm::StringRef dll_name;
-    // Report a bogus entry.
-    if (llvm::Error e = entry.getName(dll_name)) {
-      LLDB_LOGF(log,
-                "ObjectFilePECOFF::ParseDependentModules() - failed to get "
-                "import directory entry name: %s",
-                llvm::toString(std::move(e)).c_str());
-      continue;
-    }
-
+  auto add_dll = [this](llvm::StringRef dll_name) {
     // At this moment we only have the base name of the DLL. The full path can
     // only be seen after the dynamic loading.  Our best guess is Try to get it
     // with the help of the object file's directory.
@@ -1092,7 +1130,42 @@
       // Known DLLs or DLL not found in the object file directory.
       m_deps_filespec->EmplaceBack(dll_name);
     }
+  };
+
+  for (const auto &entry : m_binary->import_directories()) {
+    llvm::StringRef dll_name;
+    // Report a bogus entry.
+    if (llvm::Error e = entry.getName(dll_name)) {
+      LLDB_LOGF(log,
+                "ObjectFilePECOFF::ParseDependentModules() - failed to get "
+                "import directory entry name: %s",
+                llvm::toString(std::move(e)).c_str());
+      continue;
+    }
+    add_dll(dll_name);
   }
+
+  // Forwarder exports may reference DLLs not imported by self.
+  for (const auto &entry : m_binary->export_directories()) {
+    bool is_forwarder;
+    llvm::cantFail(entry.isForwarder(is_forwarder));
+    if (!is_forwarder)
+      continue;
+    llvm::StringRef forwarder_name;
+    if (auto err = entry.getForwardTo(forwarder_name)) {
+      llvm::consumeError(std::move(err));
+      continue;
+    }
+    size_t dot_pos = forwarder_name.find_first_of('.');
+    if (dot_pos == llvm::StringRef::npos)
+      continue;
+    llvm::SmallString<128> dll_name{forwarder_name.take_front(dot_pos), ".dll"};
+    FileSpec dll_spec(dll_name, FileSpec::Style::windows);
+    size_t index = m_deps_filespec->FindFileIndex(0, dll_spec, false);
+    if (index == UINT32_MAX)
+      add_dll(dll_name);
+  }
+
   return m_deps_filespec->GetSize();
 }
 
Index: lldb/source/Commands/CommandObjectTarget.cpp
===================================================================
--- lldb/source/Commands/CommandObjectTarget.cpp
+++ lldb/source/Commands/CommandObjectTarget.cpp
@@ -1555,6 +1555,7 @@
             strm.Indent("    Size: ");
             strm.Printf("0x%16.16" PRIx64 "\n", symbol->GetByteSize());
           }
+          strm.IndentLess();
         }
       }
     }
Index: lldb/include/lldb/Symbol/Symtab.h
===================================================================
--- lldb/include/lldb/Symbol/Symtab.h
+++ lldb/include/lldb/Symbol/Symtab.h
@@ -38,6 +38,7 @@
   void PreloadSymbols();
   void Reserve(size_t count);
   Symbol *Resize(size_t count);
+  Symbol *Extend(size_t count);
   uint32_t AddSymbol(const Symbol &symbol);
   size_t GetNumSymbols() const;
   void SectionFileAddressesChanged();
@@ -55,6 +56,8 @@
   Symbol *FindSymbolWithType(lldb::SymbolType symbol_type,
                              Debug symbol_debug_type,
                              Visibility symbol_visibility, uint32_t &start_idx);
+  bool HasSymbolWithType(lldb::SymbolType symbol_type, Debug symbol_debug_type,
+                         Visibility symbol_visibility) const;
   /// Get the parent symbol for the given symbol.
   ///
   /// Many symbols in symbol tables are scoped by other symbols that
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to