Commit a4a00ced authored by Fred Riss's avatar Fred Riss
Browse files

[lldb/Module] Allow for the creation of memory-only modules

Summary:
This patch extends the ModuleSpec class to include a
DataBufferSP which contains the module data. If this
data is provided, LLDB won't try to hit the filesystem
to create the Module, but use only the data stored in
the ModuleSpec.

Reviewers: labath, espindola

Subscribers: emaste, MaskRay, lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D83512
parent 706cccb8
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -958,6 +958,12 @@ protected:
                             ///by \a m_file.
  uint64_t m_object_offset;
  llvm::sys::TimePoint<> m_object_mod_time;

  /// DataBuffer containing the module image, if it was provided at
  /// construction time. Otherwise the data will be retrieved by mapping
  /// one of the FileSpec members above.
  lldb::DataBufferSP m_data_sp;

  lldb::ObjectFileSP m_objfile_sp; ///< A shared pointer to the object file
                                   ///parser for this module as it may or may
                                   ///not be shared with the SymbolFile
+15 −28
Original line number Diff line number Diff line
@@ -30,11 +30,19 @@ public:
        m_object_name(), m_object_offset(0), m_object_size(0),
        m_source_mappings() {}

  ModuleSpec(const FileSpec &file_spec, const UUID &uuid = UUID())
  /// If the \param data argument is passed, its contents will be used
  /// as the module contents instead of trying to read them from
  /// \param file_spec.
  ModuleSpec(const FileSpec &file_spec, const UUID &uuid = UUID(),
             lldb::DataBufferSP data = lldb::DataBufferSP())
      : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(),
        m_uuid(uuid), m_object_name(), m_object_offset(0),
        m_object_size(FileSystem::Instance().GetByteSize(file_spec)),
        m_source_mappings() {}
        m_uuid(uuid), m_object_name(), m_object_offset(0), m_source_mappings(),
        m_data(data) {
    if (data)
      m_object_size = data->GetByteSize();
    else if (m_file)
      m_object_size = FileSystem::Instance().GetByteSize(file_spec);
  }

  ModuleSpec(const FileSpec &file_spec, const ArchSpec &arch)
      : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(arch),
@@ -42,30 +50,6 @@ public:
        m_object_size(FileSystem::Instance().GetByteSize(file_spec)),
        m_source_mappings() {}

  ModuleSpec(const ModuleSpec &rhs)
      : m_file(rhs.m_file), m_platform_file(rhs.m_platform_file),
        m_symbol_file(rhs.m_symbol_file), m_arch(rhs.m_arch),
        m_uuid(rhs.m_uuid), m_object_name(rhs.m_object_name),
        m_object_offset(rhs.m_object_offset), m_object_size(rhs.m_object_size),
        m_object_mod_time(rhs.m_object_mod_time),
        m_source_mappings(rhs.m_source_mappings) {}

  ModuleSpec &operator=(const ModuleSpec &rhs) {
    if (this != &rhs) {
      m_file = rhs.m_file;
      m_platform_file = rhs.m_platform_file;
      m_symbol_file = rhs.m_symbol_file;
      m_arch = rhs.m_arch;
      m_uuid = rhs.m_uuid;
      m_object_name = rhs.m_object_name;
      m_object_offset = rhs.m_object_offset;
      m_object_size = rhs.m_object_size;
      m_object_mod_time = rhs.m_object_mod_time;
      m_source_mappings = rhs.m_source_mappings;
    }
    return *this;
  }

  FileSpec *GetFileSpecPtr() { return (m_file ? &m_file : nullptr); }

  const FileSpec *GetFileSpecPtr() const {
@@ -146,6 +130,8 @@ public:

  PathMappingList &GetSourceMappingList() const { return m_source_mappings; }

  lldb::DataBufferSP GetData() const { return m_data; }

  void Clear() {
    m_file.Clear();
    m_platform_file.Clear();
@@ -289,6 +275,7 @@ protected:
  uint64_t m_object_size;
  llvm::sys::TimePoint<> m_object_mod_time;
  mutable PathMappingList m_source_mappings;
  lldb::DataBufferSP m_data = {};
};

class ModuleSpecList {
+4 −4
Original line number Diff line number Diff line
@@ -172,10 +172,10 @@ public:
                                       lldb::addr_t header_addr,
                                       lldb::DataBufferSP &file_data_sp);

  static size_t GetModuleSpecifications(const FileSpec &file,
                                        lldb::offset_t file_offset,
                                        lldb::offset_t file_size,
                                        ModuleSpecList &specs);
  static size_t
  GetModuleSpecifications(const FileSpec &file, lldb::offset_t file_offset,
                          lldb::offset_t file_size, ModuleSpecList &specs,
                          lldb::DataBufferSP data_sp = lldb::DataBufferSP());

  static size_t GetModuleSpecifications(const lldb_private::FileSpec &file,
                                        lldb::DataBufferSP &data_sp,
+14 −0
Original line number Diff line number Diff line
@@ -79,6 +79,20 @@ public:
  }
};

class DataBufferUnowned : public DataBuffer {
public:
  DataBufferUnowned(uint8_t *bytes, lldb::offset_t size)
      : m_bytes(bytes), m_size(size) {}

  uint8_t *GetBytes() override { return m_bytes; }
  const uint8_t *GetBytes() const override { return m_bytes; }
  lldb::offset_t GetByteSize() const override { return m_size; }

private:
  uint8_t *m_bytes;
  lldb::offset_t m_size;
};

} // namespace lldb_private

#endif /// #if defined(__cplusplus)
+35 −10
Original line number Diff line number Diff line
@@ -147,11 +147,16 @@ Module::Module(const ModuleSpec &module_spec)
                  : module_spec.GetObjectName().AsCString(""),
              module_spec.GetObjectName().IsEmpty() ? "" : ")");

  auto data_sp = module_spec.GetData();
  lldb::offset_t file_size = 0;
  if (data_sp)
    file_size = data_sp->GetByteSize();

  // First extract all module specifications from the file using the local file
  // path. If there are no specifications, then don't fill anything in
  ModuleSpecList modules_specs;
  if (ObjectFile::GetModuleSpecifications(module_spec.GetFileSpec(), 0, 0,
                                          modules_specs) == 0)
  if (ObjectFile::GetModuleSpecifications(
          module_spec.GetFileSpec(), 0, file_size, modules_specs, data_sp) == 0)
    return;

  // Now make sure that one of the module specifications matches what we just
@@ -170,11 +175,20 @@ Module::Module(const ModuleSpec &module_spec)
    return;
  }

  // Set m_data_sp if it was initially provided in the ModuleSpec. Note that
  // we cannot use the data_sp variable here, because it will have been
  // modified by GetModuleSpecifications().
  if (auto module_spec_data_sp = module_spec.GetData()) {
    m_data_sp = module_spec_data_sp;
    m_mod_time = {};
  } else {
    if (module_spec.GetFileSpec())
    m_mod_time = FileSystem::Instance().GetModificationTime(module_spec.GetFileSpec());
  else if (matching_module_spec.GetFileSpec())
      m_mod_time =
        FileSystem::Instance().GetModificationTime(matching_module_spec.GetFileSpec());
          FileSystem::Instance().GetModificationTime(module_spec.GetFileSpec());
    else if (matching_module_spec.GetFileSpec())
      m_mod_time = FileSystem::Instance().GetModificationTime(
          matching_module_spec.GetFileSpec());
  }

  // Copy the architecture from the actual spec if we got one back, else use
  // the one that was specified
@@ -1110,6 +1124,10 @@ void Module::ReportError(const char *format, ...) {
}

bool Module::FileHasChanged() const {
  // We have provided the DataBuffer for this module to avoid accessing the
  // filesystem. We never want to reload those files.
  if (m_data_sp)
    return false;
  if (!m_file_has_changed)
    m_file_has_changed =
        (FileSystem::Instance().GetModificationTime(m_file) != m_mod_time);
@@ -1229,12 +1247,19 @@ ObjectFile *Module::GetObjectFile() {
      static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
      Timer scoped_timer(func_cat, "Module::GetObjectFile () module = %s",
                         GetFileSpec().GetFilename().AsCString(""));
      DataBufferSP data_sp;
      lldb::offset_t data_offset = 0;
      const lldb::offset_t file_size =
          FileSystem::Instance().GetByteSize(m_file);
      lldb::offset_t file_size = 0;

      if (m_data_sp)
        file_size = m_data_sp->GetByteSize();
      else if (m_file)
        file_size = FileSystem::Instance().GetByteSize(m_file);

      if (file_size > m_object_offset) {
        m_did_load_objfile = true;
        // FindPlugin will modify its data_sp argument. Do not let it
        // modify our m_data_sp member.
        auto data_sp = m_data_sp;
        m_objfile_sp = ObjectFile::FindPlugin(
            shared_from_this(), &m_file, m_object_offset,
            file_size - m_object_offset, data_sp, data_offset);
Loading