lldb::DataBufferSP
MemoryMapFileContents (off_t offset = 0, size_t length = SIZE_MAX) const;
+
+ //------------------------------------------------------------------
+ /// Memory map part of, or the entire contents of, a file only if
+ /// the file is local (not on a network mount).
+ ///
+ /// Returns a shared pointer to a data buffer that contains all or
+ /// part of the contents of a file. The data will be memory mapped
+ /// if the file is local and will lazily page in data from the file
+ /// as memory is accessed. If the data is memory mapped, the data
+ /// that is mapped will start \a offset bytes into the file, and
+ /// \a length bytes will be mapped. If \a length is
+ /// greater than the number of bytes available in the file starting
+ /// at \a offset, the number of bytes will be appropriately
+ /// truncated. The final number of bytes that get mapped can be
+ /// verified using the DataBuffer::GetByteSize() function on the return
+ /// shared data pointer object contents.
+ ///
+ /// If the file is on a network mount the data will be read into a
+ /// heap buffer immediately so that accesses to the data won't later
+ /// cause a crash if we touch a page that isn't paged in and the
+ /// network mount has been disconnected or gone away.
+ ///
+ /// @param[in] offset
+ /// The offset in bytes from the beginning of the file where
+ /// memory mapping should begin.
+ ///
+ /// @param[in] length
+ /// The size in bytes that should be mapped starting \a offset
+ /// bytes into the file. If \a length is \c SIZE_MAX, map
+ /// as many bytes as possible.
+ ///
+ /// @return
+ /// A shared pointer to the memory mapped data. This shared
+ /// pointer can contain a NULL DataBuffer pointer, so the contained
+ /// pointer must be checked prior to using it.
+ //------------------------------------------------------------------
+ lldb::DataBufferSP
+ MemoryMapFileContentsIfLocal(off_t file_offset, size_t file_size) const;
+
//------------------------------------------------------------------
/// Read part of, or the entire contents of, a file into a heap based data buffer.
///
static bool CalculateMD5(const FileSpec &file_spec, uint64_t &low, uint64_t &high);
static bool CalculateMD5AsString(const FileSpec &file_spec, std::string& digest_str);
+
+ /// Return \b true if \a spec is on a locally mounted file system, \b false otherwise.
+ static bool IsLocal(const FileSpec &spec);
};
}
return data_sp;
}
+DataBufferSP
+FileSpec::MemoryMapFileContentsIfLocal(off_t file_offset, size_t file_size) const
+{
+ if (FileSystem::IsLocal(*this))
+ return MemoryMapFileContents(file_offset, file_size);
+ else
+ return ReadFileContents(file_offset, file_size, NULL);
+}
+
//------------------------------------------------------------------
// Return the size in bytes that this object takes in memory. This
#include "lldb/Host/FileSystem.h"
// C includes
+#include <sys/mount.h>
+#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
error.SetErrorString("'buf' buffer is too small to contain link contents");
return error;
}
+
+bool
+FileSystem::IsLocal(const FileSpec &spec)
+{
+ struct statfs statfs_info;
+ std::string path (spec.GetPath());
+ if (statfs(path.c_str(), &statfs_info) == 0)
+ return (statfs_info.f_flags & MNT_LOCAL) != 0;
+ return false;
+}
::CloseHandle(h);
return error;
}
+
+bool
+FileSystem::IsLocal(const FileSpec &spec)
+{
+ if (spec)
+ {
+ // TODO: return true if the file is on a locally mounted file system
+ return true;
+ }
+
+ return false;
+}
// Map the entire .a file to be sure that we don't lose any data if the file
// gets updated by a new build while this .a file is being used for debugging
- DataBufferSP archive_data_sp (file->MemoryMapFileContents(file_offset, length));
+ DataBufferSP archive_data_sp (file->MemoryMapFileContentsIfLocal(file_offset, length));
lldb::offset_t archive_data_offset = 0;
Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file,
if (!archive_sp)
{
set_archive_arch = true;
- DataBufferSP data_sp (file.MemoryMapFileContents(file_offset, file_size));
+ DataBufferSP data_sp (file.MemoryMapFileContentsIfLocal(file_offset, file_size));
data.SetData (data_sp, 0, data_sp->GetByteSize());
archive_sp = Archive::ParseAndCacheArchiveForFile(file, ArchSpec(), file_mod_time, file_offset, data);
}
{
if (!data_sp)
{
- data_sp = file->MemoryMapFileContents(file_offset, length);
+ data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length);
data_offset = 0;
}
{
// Update the data to contain the entire file if it doesn't already
if (data_sp->GetByteSize() < length) {
- data_sp = file->MemoryMapFileContents(file_offset, length);
+ data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length);
data_offset = 0;
magic = data_sp->GetBytes();
}
size_t section_header_end = header.e_shoff + header.e_shnum * header.e_shentsize;
if (section_header_end > data_sp->GetByteSize())
{
- data_sp = file.MemoryMapFileContents (file_offset, section_header_end);
+ data_sp = file.MemoryMapFileContentsIfLocal (file_offset, section_header_end);
data.SetData(data_sp);
}
size_t program_headers_end = header.e_phoff + header.e_phnum * header.e_phentsize;
if (program_headers_end > data_sp->GetByteSize())
{
- data_sp = file.MemoryMapFileContents(file_offset, program_headers_end);
+ data_sp = file.MemoryMapFileContentsIfLocal(file_offset, program_headers_end);
data.SetData(data_sp);
}
ProgramHeaderColl program_headers;
if (segment_data_end > data_sp->GetByteSize())
{
- data_sp = file.MemoryMapFileContents(file_offset, segment_data_end);
+ data_sp = file.MemoryMapFileContentsIfLocal(file_offset, segment_data_end);
data.SetData(data_sp);
}
else
{
// Need to map entire file into memory to calculate the crc.
- data_sp = file.MemoryMapFileContents (file_offset, SIZE_MAX);
+ data_sp = file.MemoryMapFileContentsIfLocal (file_offset, SIZE_MAX);
data.SetData(data_sp);
gnu_debuglink_crc = calc_gnu_debuglink_crc32 (data.GetDataStart(), data.GetByteSize());
}
{
if (!data_sp)
{
- data_sp = file->MemoryMapFileContents(file_offset, length);
+ data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length);
data_offset = 0;
}
// Update the data to contain the entire file if it doesn't already
if (data_sp->GetByteSize() < length)
{
- data_sp = file->MemoryMapFileContents(file_offset, length);
+ data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length);
data_offset = 0;
}
std::unique_ptr<ObjectFile> objfile_ap(new ObjectFileMachO (module_sp, data_sp, data_offset, file, file_offset, length));
// Save some VM space, do not map the entire cache in one shot.
DataBufferSP dsc_data_sp;
- dsc_data_sp = dsc_filespec.MemoryMapFileContents(0, sizeof(struct lldb_copy_dyld_cache_header_v1));
+ dsc_data_sp = dsc_filespec.MemoryMapFileContentsIfLocal(0, sizeof(struct lldb_copy_dyld_cache_header_v1));
if (dsc_data_sp)
{
if (uuid_match && mappingOffset >= sizeof(struct lldb_copy_dyld_cache_header_v0))
{
- DataBufferSP dsc_mapping_info_data_sp = dsc_filespec.MemoryMapFileContents(mappingOffset, sizeof (struct lldb_copy_dyld_cache_mapping_info));
+ DataBufferSP dsc_mapping_info_data_sp = dsc_filespec.MemoryMapFileContentsIfLocal(mappingOffset, sizeof (struct lldb_copy_dyld_cache_mapping_info));
DataExtractor dsc_mapping_info_data(dsc_mapping_info_data_sp, byte_order, addr_byte_size);
offset = 0;
if (localSymbolsOffset && localSymbolsSize)
{
// Map the local symbols
- if (DataBufferSP dsc_local_symbols_data_sp = dsc_filespec.MemoryMapFileContents(localSymbolsOffset, localSymbolsSize))
+ if (DataBufferSP dsc_local_symbols_data_sp = dsc_filespec.MemoryMapFileContentsIfLocal(localSymbolsOffset, localSymbolsSize))
{
DataExtractor dsc_local_symbols_data(dsc_local_symbols_data_sp, byte_order, addr_byte_size);
{
if (!data_sp)
{
- data_sp = file->MemoryMapFileContents(file_offset, length);
+ data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length);
data_offset = 0;
}
{
// Update the data to contain the entire file if it doesn't already
if (data_sp->GetByteSize() < length)
- data_sp = file->MemoryMapFileContents(file_offset, length);
+ data_sp = file->MemoryMapFileContentsIfLocal(file_offset, length);
std::unique_ptr<ObjectFile> objfile_ap(new ObjectFilePECOFF (module_sp, data_sp, data_offset, file, file_offset, length));
if (objfile_ap.get() && objfile_ap->ParseHeader())
return objfile_ap.release();