1 //===-- DataBufferMemoryMap.cpp ---------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
17 #include "lldb/Core/DataBufferMemoryMap.h"
18 #include "lldb/Core/Error.h"
19 #include "lldb/Host/File.h"
20 #include "lldb/Host/FileSpec.h"
21 #include "lldb/Host/Host.h"
22 #include "lldb/Core/Log.h"
23 #include "lldb/lldb-private-log.h"
26 using namespace lldb_private;
28 //----------------------------------------------------------------------
29 // Default Constructor
30 //----------------------------------------------------------------------
31 DataBufferMemoryMap::DataBufferMemoryMap() :
39 //----------------------------------------------------------------------
40 // Virtual destructor since this class inherits from a pure virtual
42 //----------------------------------------------------------------------
43 DataBufferMemoryMap::~DataBufferMemoryMap()
48 //----------------------------------------------------------------------
49 // Return a pointer to the bytes owned by this object, or NULL if
50 // the object contains no bytes.
51 //----------------------------------------------------------------------
53 DataBufferMemoryMap::GetBytes()
58 //----------------------------------------------------------------------
59 // Return a const pointer to the bytes owned by this object, or NULL
60 // if the object contains no bytes.
61 //----------------------------------------------------------------------
63 DataBufferMemoryMap::GetBytes() const
68 //----------------------------------------------------------------------
69 // Return the number of bytes this object currently contains.
70 //----------------------------------------------------------------------
72 DataBufferMemoryMap::GetByteSize() const
77 //----------------------------------------------------------------------
78 // Reverts this object to an empty state by unmapping any memory
79 // that is currently owned.
80 //----------------------------------------------------------------------
82 DataBufferMemoryMap::Clear()
84 if (m_mmap_addr != NULL)
86 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MMAP));
88 log->Printf("DataBufferMemoryMap::Clear() m_mmap_addr = %p, m_mmap_size = %zu", m_mmap_addr, m_mmap_size);
89 ::munmap((void *)m_mmap_addr, m_mmap_size);
97 //----------------------------------------------------------------------
98 // Memory map "length" bytes from "file" starting "offset"
99 // bytes into the file. If "length" is set to SIZE_MAX, then
100 // map as many bytes as possible.
102 // Returns the number of bytes mapped starting from the requested
104 //----------------------------------------------------------------------
106 DataBufferMemoryMap::MemoryMapFromFileSpec (const FileSpec* filespec,
107 lldb::offset_t offset,
108 lldb::offset_t length,
111 if (filespec != NULL)
113 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MMAP));
116 log->Printf("DataBufferMemoryMap::MemoryMapFromFileSpec(file=\"%s\", offset=0x%" PRIx64 ", length=0x%" PRIx64 ", writeable=%i",
117 filespec->GetPath().c_str(),
123 if (filespec->GetPath(path, sizeof(path)))
125 uint32_t options = File::eOpenOptionRead;
127 options |= File::eOpenOptionWrite;
130 Error error (file.Open(path, options));
133 const bool fd_is_file = true;
134 return MemoryMapFromFileDescriptor (file.GetDescriptor(), offset, length, writeable, fd_is_file);
138 // We should only get here if there was an error
144 //----------------------------------------------------------------------
145 // The file descriptor FD is assumed to already be opened as read only
146 // and the STAT structure is assumed to a valid pointer and already
147 // containing valid data from a call to stat().
149 // Memory map FILE_LENGTH bytes in FILE starting FILE_OFFSET bytes into
150 // the file. If FILE_LENGTH is set to SIZE_MAX, then map as many bytes
154 // Number of bytes mapped starting from the requested offset.
155 //----------------------------------------------------------------------
157 DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd,
158 lldb::offset_t offset,
159 lldb::offset_t length,
166 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MMAP|LIBLLDB_LOG_VERBOSE));
169 log->Printf("DataBufferMemoryMap::MemoryMapFromFileSpec(fd=%i, offset=0x%" PRIx64 ", length=0x%" PRIx64 ", writeable=%i, fd_is_file=%i)",
177 if (::fstat(fd, &stat) == 0)
179 if (S_ISREG(stat.st_mode) && (stat.st_size > offset))
181 const size_t max_bytes_available = stat.st_size - offset;
182 if (length == SIZE_MAX)
184 length = max_bytes_available;
186 else if (length > max_bytes_available)
188 // Cap the length if too much data was requested
189 length = max_bytes_available;
194 int prot = PROT_READ;
198 int flags = MAP_PRIVATE;
202 m_mmap_addr = (uint8_t *)::mmap(NULL, length, prot, flags, fd, offset);
205 if (m_mmap_addr == (void*)-1)
207 error.SetErrorToErrno ();
208 if (error.GetError() == EINVAL)
210 // We may still have a shot at memory mapping if we align things correctly
211 size_t page_offset = offset % Host::GetPageSize();
212 if (page_offset != 0)
214 m_mmap_addr = (uint8_t *)::mmap(NULL, length + page_offset, prot, flags, fd, offset - page_offset);
215 if (m_mmap_addr == (void*)-1)
217 // Failed to map file
220 else if (m_mmap_addr != NULL)
222 // We recovered and were able to memory map
223 // after we aligned things to page boundaries
225 // Save the actual mmap'ed size
226 m_mmap_size = length + page_offset;
227 // Our data is at an offset into the the mapped data
228 m_data = m_mmap_addr + page_offset;
229 // Our pretend size is the size that was requestd
234 if (error.GetError() == ENOMEM)
236 error.SetErrorStringWithFormat("could not allocate %" PRId64 " bytes of memory to mmap in file", (uint64_t) length);
241 // We were able to map the requested data in one chunk
242 // where our mmap and actual data are the same.
243 m_mmap_size = length;
244 m_data = m_mmap_addr;
250 log->Printf("DataBufferMemoryMap::MemoryMapFromFileSpec() m_mmap_addr = %p, m_mmap_size = %zu, error = %s",
251 m_mmap_addr, m_mmap_size, error.AsCString());
257 return GetByteSize ();