MCLinker upstream commit e764452.
Change-Id: I5c9ec467ec96a0143e1e67c59365f3b6303e7348
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp
index 57b82df..cc15e37 100644
--- a/lib/Support/CommandLine.cpp
+++ b/lib/Support/CommandLine.cpp
@@ -6,12 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include "mcld/Support/CommandLine.h"
+#include <mcld/Support/CommandLine.h>
#include <llvm/ADT/StringRef.h>
+#include <llvm/ADT/Twine.h>
+#include <llvm/Support/ErrorHandling.h>
using namespace llvm;
using namespace llvm::cl;
+using namespace mcld;
+
//--------------------------------------------------
// parser<mcld::sys::fs::Path>
//
@@ -82,3 +86,81 @@
// do nothing
}
+//--------------------------------------------------
+// parser<mcld::ZOption>
+//
+bool parser<mcld::ZOption>::parse(llvm::cl::Option &O,
+ llvm::StringRef ArgName,
+ llvm::StringRef Arg,
+ mcld::ZOption &Val)
+{
+ if (0 == Arg.compare("combreloc"))
+ Val.setKind(ZOption::CombReloc);
+ else if (0 == Arg.compare("nocombreloc"))
+ Val.setKind(ZOption::NoCombReloc);
+ else if (0 == Arg.compare("defs"))
+ Val.setKind(ZOption::Defs);
+ else if (0 == Arg.compare("execstack"))
+ Val.setKind(ZOption::ExecStack);
+ else if (0 == Arg.compare("noexecstack"))
+ Val.setKind(ZOption::NoExecStack);
+ else if (0 == Arg.compare("initfirst"))
+ Val.setKind(ZOption::InitFirst);
+ else if (0 == Arg.compare("interpose"))
+ Val.setKind(ZOption::InterPose);
+ else if (0 == Arg.compare("loadfltr"))
+ Val.setKind(ZOption::LoadFltr);
+ else if (0 == Arg.compare("muldefs"))
+ Val.setKind(ZOption::MulDefs);
+ else if (0 == Arg.compare("nocopyreloc"))
+ Val.setKind(ZOption::NoCopyReloc);
+ else if (0 == Arg.compare("nodefaultlib"))
+ Val.setKind(ZOption::NoDefaultLib);
+ else if (0 == Arg.compare("nodelete"))
+ Val.setKind(ZOption::NoDelete);
+ else if (0 == Arg.compare("nodlopen"))
+ Val.setKind(ZOption::NoDLOpen);
+ else if (0 == Arg.compare("nodump"))
+ Val.setKind(ZOption::NoDump);
+ else if (0 == Arg.compare("relro"))
+ Val.setKind(ZOption::Relro);
+ else if (0 == Arg.compare("norelro"))
+ Val.setKind(ZOption::NoRelro);
+ else if (0 == Arg.compare("lazy"))
+ Val.setKind(ZOption::Lazy);
+ else if (0 == Arg.compare("now"))
+ Val.setKind(ZOption::Now);
+ else if (0 == Arg.compare("origin"))
+ Val.setKind(ZOption::Origin);
+ else if (Arg.startswith("common-page-size=")) {
+ Val.setKind(ZOption::CommPageSize);
+ long long unsigned size = 0;
+ Arg.drop_front(17).getAsInteger(0, size);
+ Val.setPageSize(static_cast<uint64_t>(size));
+ } else if (Arg.startswith("max-page-size=")) {
+ Val.setKind(ZOption::MaxPageSize);
+ long long unsigned size = 0;
+ Arg.drop_front(14).getAsInteger(0, size);
+ Val.setPageSize(static_cast<uint64_t>(size));
+ }
+
+ if (ZOption::Unknown == Val.kind())
+ llvm::report_fatal_error(llvm::Twine("unknown -z option: `") +
+ Arg +
+ llvm::Twine("'\n"));
+ return false;
+}
+
+void parser<mcld::ZOption>::printOptionDiff(const llvm::cl::Option &O,
+ const mcld::ZOption &V,
+ parser<mcld::ZOption>::OptVal Default,
+ size_t GlobalWidth) const
+{
+ // TODO
+}
+
+void parser<mcld::ZOption>::anchor()
+{
+ // do nothing
+}
+
diff --git a/lib/Support/Directory.cpp b/lib/Support/Directory.cpp
index 211b42a..78bb761 100644
--- a/lib/Support/Directory.cpp
+++ b/lib/Support/Directory.cpp
@@ -32,7 +32,7 @@
: m_Path(),
m_FileStatus(),
m_SymLinkStatus(),
- m_Handler(NULL),
+ m_Handler(0),
m_Cache(),
m_CacheFull(false) {
}
@@ -43,7 +43,7 @@
: m_Path(pPath),
m_FileStatus(st),
m_SymLinkStatus(symlink_st),
- m_Handler(NULL),
+ m_Handler(0),
m_Cache(),
m_CacheFull(false) {
if (m_Path.native() == ".")
@@ -56,7 +56,7 @@
: m_Path(pCopy.m_Path),
m_FileStatus(pCopy.m_FileStatus),
m_SymLinkStatus(pCopy.m_SymLinkStatus),
- m_Handler(NULL),
+ m_Handler(0),
m_Cache(),
m_CacheFull(false) {
mcld::sys::fs::detail::open_dir(*this);
diff --git a/lib/Support/FileHandle.cpp b/lib/Support/FileHandle.cpp
new file mode 100644
index 0000000..f6b898c
--- /dev/null
+++ b/lib/Support/FileHandle.cpp
@@ -0,0 +1,332 @@
+//===- FileHandle.cpp -----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/FileSystem.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// FileHandle
+FileHandle::FileHandle()
+ : m_Path(),
+ m_Handler(-1),
+ m_Size(0),
+ m_State(GoodBit),
+ m_OpenMode(NotOpen) {
+}
+
+FileHandle::~FileHandle()
+{
+ if (isOpened())
+ close();
+}
+
+inline static int oflag(FileHandle::OpenMode pMode)
+{
+ int result = 0x0;
+ if (FileHandle::Unknown == pMode)
+ return result;
+
+ if (FileHandle::ReadWrite == (pMode & FileHandle::ReadWrite))
+ result |= O_RDWR;
+ else if (pMode & FileHandle::ReadOnly)
+ result |= O_RDONLY;
+ else if (pMode & FileHandle::WriteOnly)
+ result |= O_WRONLY;
+
+ if (pMode & FileHandle::Append)
+ result |= O_APPEND;
+
+ if (pMode & FileHandle::Create)
+ result |= O_CREAT;
+
+ if (pMode & FileHandle::Truncate)
+ result |= O_TRUNC;
+
+ return result;
+}
+
+inline static bool get_size(int pHandler, unsigned int &pSize)
+{
+ struct ::stat file_stat;
+ if (-1 == ::fstat(pHandler, &file_stat)) {
+ pSize = 0;
+ return false;
+ }
+ pSize = file_stat.st_size;
+ return true;
+}
+
+bool FileHandle::open(const sys::fs::Path& pPath,
+ FileHandle::OpenMode pMode)
+{
+ if (isOpened() || Unknown == pMode) {
+ setState(BadBit);
+ return false;
+ }
+
+ m_OpenMode = pMode;
+ m_Handler = ::open(pPath.native().c_str(), oflag(pMode));
+ m_Path = pPath;
+ if (-1 == m_Handler) {
+ m_OpenMode = NotOpen;
+ setState(FailBit);
+ return false;
+ }
+
+ if (!get_size(m_Handler, m_Size)) {
+ setState(FailBit);
+ return false;
+ }
+
+ return true;
+}
+
+bool FileHandle::open(const sys::fs::Path& pPath,
+ FileHandle::OpenMode pMode,
+ FileHandle::Permission pPerm)
+{
+ if (isOpened() || Unknown == pMode) {
+ setState(BadBit);
+ return false;
+ }
+
+ m_OpenMode = pMode;
+ m_Handler = sys::fs::detail::open(pPath, oflag(pMode), (int)pPerm);
+ m_Path = pPath;
+ if (-1 == m_Handler) {
+ m_OpenMode = NotOpen;
+ setState(FailBit);
+ return false;
+ }
+
+ if (!get_size(m_Handler, m_Size)) {
+ setState(FailBit);
+ return false;
+ }
+
+ return true;
+}
+
+bool FileHandle::delegate(int pFD, FileHandle::OpenMode pMode)
+{
+ if (isOpened()) {
+ setState(BadBit);
+ return false;
+ }
+
+ m_Handler = pFD;
+ m_OpenMode = pMode;
+ m_State = GoodBit;
+
+ if (!get_size(m_Handler, m_Size)) {
+ setState(FailBit);
+ return false;
+ }
+
+ return true;
+}
+
+bool FileHandle::close()
+{
+ if (!isOpened()) {
+ setState(BadBit);
+ return false;
+ }
+
+ if (-1 == ::close(m_Handler)) {
+ setState(FailBit);
+ return false;
+ }
+
+ m_Path.native().clear();
+ m_Size = 0;
+ m_OpenMode = NotOpen;
+ cleanState();
+ return true;
+}
+
+bool FileHandle::truncate(size_t pSize)
+{
+ if (!isOpened() || !isWritable()) {
+ setState(BadBit);
+ return false;
+ }
+
+ if (-1 == sys::fs::detail::ftruncate(m_Handler, pSize)) {
+ setState(FailBit);
+ return false;
+ }
+
+ m_Size = pSize;
+ return true;
+}
+
+bool FileHandle::read(void* pMemBuffer, size_t pStartOffset, size_t pLength)
+{
+ if (!isOpened() || !isReadable()) {
+ setState(BadBit);
+ return false;
+ }
+
+ if (0 == pLength)
+ return true;
+
+ ssize_t read_bytes = sys::fs::detail::pread(m_Handler,
+ pMemBuffer,
+ pLength,
+ pStartOffset);
+
+ if (-1 == read_bytes) {
+ setState(FailBit);
+ return false;
+ }
+
+ return true;
+}
+
+bool FileHandle::write(const void* pMemBuffer, size_t pStartOffset, size_t pLength)
+{
+ if (!isOpened() || !isWritable()) {
+ setState(BadBit);
+ return false;
+ }
+
+ if (0 == pLength)
+ return true;
+
+
+ ssize_t write_bytes = sys::fs::detail::pwrite(m_Handler,
+ pMemBuffer,
+ pLength,
+ pStartOffset);
+
+ if (-1 == write_bytes) {
+ setState(FailBit);
+ return false;
+ }
+
+ return true;
+}
+
+#include <iostream>
+using namespace std;
+
+bool FileHandle::mmap(void*& pMemBuffer, size_t pStartOffset, size_t pLength)
+{
+ if (!isOpened()) {
+ setState(BadBit);
+ return false;
+ }
+
+ if (0 == pLength)
+ return true;
+
+ int prot, flag;
+ if (isReadable() && !isWritable()) {
+ // read-only
+ prot = PROT_READ;
+ flag = MAP_FILE | MAP_PRIVATE;
+ }
+ else if (!isReadable() && isWritable()) {
+ // write-only
+ prot = PROT_WRITE;
+ flag = MAP_FILE | MAP_SHARED;
+ }
+ else if (isReadWrite()) {
+ // read and write
+ prot = PROT_READ | PROT_WRITE;
+ flag = MAP_FILE | MAP_SHARED;
+ }
+ else {
+ // can not read/write
+ setState(BadBit);
+ return false;
+ }
+
+ pMemBuffer = ::mmap(NULL, pLength, prot, flag, m_Handler, pStartOffset);
+
+ if (MAP_FAILED == pMemBuffer) {
+ setState(FailBit);
+ return false;
+ }
+
+ return true;
+}
+
+bool FileHandle::munmap(void* pMemBuffer, size_t pLength)
+{
+ if (!isOpened()) {
+ setState(BadBit);
+ return false;
+ }
+
+ if (-1 == ::munmap(pMemBuffer, pLength)) {
+ setState(FailBit);
+ return false;
+ }
+
+ return true;
+}
+
+void FileHandle::setState(FileHandle::IOState pState)
+{
+ m_State |= pState;
+}
+
+void FileHandle::cleanState(FileHandle::IOState pState)
+{
+ m_State = pState;
+}
+
+bool FileHandle::isOpened() const
+{
+ if (-1 != m_Handler && m_OpenMode != NotOpen && isGood())
+ return true;
+
+ return false;
+}
+
+// Assume Unknown OpenMode is readable
+bool FileHandle::isReadable() const
+{
+ return (m_OpenMode & ReadOnly);
+}
+
+// Assume Unknown OpenMode is writable
+bool FileHandle::isWritable() const
+{
+ return (m_OpenMode & WriteOnly);
+}
+
+// Assume Unknown OpenMode is both readable and writable
+bool FileHandle::isReadWrite() const
+{
+ return (FileHandle::ReadWrite == (m_OpenMode & FileHandle::ReadWrite));
+}
+
+bool FileHandle::isGood() const
+{
+ return !(m_State & (BadBit | FailBit));
+}
+
+bool FileHandle::isBad() const
+{
+ return (m_State & BadBit);
+}
+
+bool FileHandle::isFailed() const
+{
+ return (m_State & (BadBit | FailBit));
+}
+
diff --git a/lib/Support/FileSystem.cpp b/lib/Support/FileSystem.cpp
index d3366c0..fb2633d 100644
--- a/lib/Support/FileSystem.cpp
+++ b/lib/Support/FileSystem.cpp
@@ -9,10 +9,6 @@
#include "mcld/Support/FileSystem.h"
#include "mcld/Support/Path.h"
-#if defined(ANDROID)
-#include <llvm/Config/config.h>
-#endif
-
using namespace mcld::sys::fs;
@@ -22,12 +18,12 @@
//===--------------------------------------------------------------------===//
// non-member functions
-// Include the truly platform-specific parts.
-#if defined(LLVM_ON_UNIX)
+// Include the truly platform-specific parts.
+#if defined(MCLD_ON_UNIX)
#include "Unix/FileSystem.inc"
-#include "Unix/PathV3.inc"
-#endif
-#if defined(LLVM_ON_WIN32)
+#include "Unix/PathV3.inc"
+#endif
+#if defined(MCLD_ON_WIN32)
#include "Windows/FileSystem.inc"
-#include "Windows/PathV3.inc"
-#endif
+#include "Windows/PathV3.inc"
+#endif
diff --git a/lib/Support/HandleToArea.cpp b/lib/Support/HandleToArea.cpp
new file mode 100644
index 0000000..f580e64
--- /dev/null
+++ b/lib/Support/HandleToArea.cpp
@@ -0,0 +1,94 @@
+//===- HandleToArea.cpp ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/HandleToArea.h>
+#include <mcld/Support/MemoryArea.h>
+#include <llvm/ADT/StringRef.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// HandleToArea
+bool HandleToArea::push_back(FileHandle* pHandle, MemoryArea* pArea)
+{
+ if (NULL == pHandle || NULL == pArea)
+ return false;
+
+ Bucket bucket;
+ bucket.hash_value = HashFunction()(
+ llvm::StringRef(pHandle->path().native().c_str(),
+ pHandle->path().native().size()));
+
+ bucket.handle = pHandle;
+ bucket.area = pArea;
+ m_AreaMap.push_back(bucket);
+ return true;
+}
+
+bool HandleToArea::erase(MemoryArea* pArea)
+{
+ if (NULL == pArea || NULL == pArea->handler())
+ return false;
+
+ return erase(pArea->handler()->path());
+}
+
+bool HandleToArea::erase(const sys::fs::Path& pPath)
+{
+ unsigned int hash_value = HashFunction()(
+ llvm::StringRef(pPath.native().c_str(),
+ pPath.native().size()));
+
+ HandleToAreaMap::iterator bucket, bEnd = m_AreaMap.end();
+ for (bucket = m_AreaMap.begin(); bucket != bEnd; ++bucket) {
+ if (bucket->hash_value == hash_value && bucket->handle->path() == pPath) {
+ // found
+ m_AreaMap.erase(bucket);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+HandleToArea::Result HandleToArea::findFirst(const sys::fs::Path& pPath)
+{
+ unsigned int hash_value = HashFunction()(llvm::StringRef(pPath.native().c_str(),
+ pPath.native().size()));
+
+ HandleToAreaMap::iterator bucket, bEnd = m_AreaMap.end();
+
+ for (bucket = m_AreaMap.begin(); bucket != bEnd; ++bucket) {
+ if (bucket->hash_value == hash_value) {
+ if (bucket->handle->path() == pPath) {
+ return Result(bucket->handle, bucket->area);
+ }
+ }
+ }
+
+ return Result(NULL, NULL);
+}
+
+HandleToArea::ConstResult HandleToArea::findFirst(const sys::fs::Path& pPath) const
+{
+ unsigned int hash_value = HashFunction()(llvm::StringRef(pPath.native().c_str(),
+ pPath.native().size()));
+
+ HandleToAreaMap::const_iterator bucket, bEnd = m_AreaMap.end();
+
+ for (bucket = m_AreaMap.begin(); bucket != bEnd; ++bucket) {
+ if (bucket->hash_value == hash_value) {
+ if (bucket->handle->path() == pPath) {
+ return ConstResult(bucket->handle, bucket->area);
+ }
+ }
+ }
+
+ return ConstResult(NULL, NULL);
+}
+
diff --git a/lib/Support/MemoryArea.cpp b/lib/Support/MemoryArea.cpp
index f388e94..78a9d36 100644
--- a/lib/Support/MemoryArea.cpp
+++ b/lib/Support/MemoryArea.cpp
@@ -6,164 +6,31 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include <llvm/Support/ErrorHandling.h>
-#include <llvm/ADT/Twine.h>
-
#include <mcld/Support/RegionFactory.h>
#include <mcld/Support/MemoryArea.h>
#include <mcld/Support/MemoryRegion.h>
-#include <mcld/Support/FileSystem.h>
-
-#include <cerrno>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/MsgHandling.h>
using namespace mcld;
//===--------------------------------------------------------------------===//
// MemoryArea
-MemoryArea::MemoryArea(RegionFactory& pRegionFactory)
- : m_RegionFactory(pRegionFactory),
- m_FileDescriptor(-1),
- m_FileSize(0),
- m_AccessFlags(ReadOnly),
- m_State(BadBit) {
+
+// MemoryArea - special constructor
+// This constructor is used for *SPECIAL* situation. I'm sorry I can not
+// reveal what is the special situation.
+MemoryArea::MemoryArea(RegionFactory& pRegionFactory, Space& pUniverse)
+ : m_RegionFactory(pRegionFactory), m_pFileHandle(NULL) {
+ m_SpaceList.push_back(&pUniverse);
+}
+
+MemoryArea::MemoryArea(RegionFactory& pRegionFactory, FileHandle& pFileHandle)
+ : m_RegionFactory(pRegionFactory), m_pFileHandle(&pFileHandle) {
}
MemoryArea::~MemoryArea()
{
- // truncate the file to real size
- if (isWritable())
- truncate(m_FileSize);
-
- unmap();
-}
-
-void MemoryArea::truncate(size_t pLength)
-{
- if (!isWritable())
- return;
-
- if (-1 == ::ftruncate(m_FileDescriptor, static_cast<off_t>(pLength))) {
- llvm::report_fatal_error(llvm::Twine("Cannot truncate `") +
- m_FilePath.native() +
- llvm::Twine("' to size: ") +
- llvm::Twine(pLength) +
- llvm::Twine(".\n"));
- }
-}
-
-void MemoryArea::map(const sys::fs::Path& pPath, int pFlags)
-{
- m_AccessFlags = pFlags;
- m_FilePath = pPath;
- m_FileDescriptor = ::open(m_FilePath.c_str(), m_AccessFlags);
-
- if (-1 == m_FileDescriptor) {
- m_State |= FailBit;
- }
- else {
- struct stat st;
- int stat_result = ::stat(m_FilePath.native().c_str(), &st);
- if (0x0 == stat_result) {
- m_FileSize = static_cast<size_t>(st.st_size);
- m_State = GoodBit;
- }
- else {
- m_FileSize = 0x0;
- m_State |= FailBit;
- m_State |= BadBit;
- }
- }
-}
-
-void MemoryArea::map(const sys::fs::Path& pPath, int pFlags, int pMode)
-{
- m_AccessFlags = pFlags;
- m_FilePath = pPath;
- m_FileDescriptor = ::open(m_FilePath.c_str(), m_AccessFlags, pMode);
-
- if (-1 == m_FileDescriptor) {
- m_State |= FailBit;
- }
- else {
- struct stat st;
- int stat_result = ::stat(m_FilePath.native().c_str(), &st);
- if (0x0 == stat_result) {
- m_FileSize = static_cast<size_t>(st.st_size);
- m_State = GoodBit;
- }
- else {
- m_FileSize = 0x0;
- m_State |= FailBit;
- m_State |= BadBit;
- }
- }
-}
-
-void MemoryArea::unmap()
-{
- if (isMapped()) {
- if (-1 == ::close(m_FileDescriptor))
- m_State |= FailBit;
- else {
- m_FileDescriptor = -1;
- m_AccessFlags = ReadOnly;
- }
- }
-}
-
-bool MemoryArea::isMapped() const
-{
- return (-1 != m_FileDescriptor);
-}
-
-bool MemoryArea::isGood() const
-{
- return 0x0 == (m_State & (BadBit | FailBit));
-}
-
-bool MemoryArea::isBad() const
-{
- return 0x0 != (m_State & BadBit);
-}
-
-bool MemoryArea::isFailed() const
-{
- return 0x0 != (m_State & FailBit);
-}
-
-bool MemoryArea::isEOF() const
-{
- return 0x0 != (m_State & EOFBit);
-}
-
-bool MemoryArea::isReadable() const
-{
- return (((m_AccessFlags & AccessMask) == ReadOnly) ||
- ((m_AccessFlags & AccessMask) == ReadWrite));
-}
-
-bool MemoryArea::isWritable() const
-{
- return (((m_AccessFlags & AccessMask) == WriteOnly) ||
- ((m_AccessFlags & AccessMask) == ReadWrite));
-}
-
-int MemoryArea::rdstate() const
-{
- return m_State;
-}
-
-void MemoryArea::setState(MemoryArea::IOState pState)
-{
- m_State |= pState;
-}
-
-void MemoryArea::clear(MemoryArea::IOState pState)
-{
- m_State = pState;
}
// The layout of MemorySpace in the virtual memory space
@@ -185,242 +52,100 @@
//
MemoryRegion* MemoryArea::request(size_t pOffset, size_t pLength)
{
- if (!isMapped() || !isGood())
- return NULL;
-
- if (0x0 == pLength)
- return NULL;
-
- if (!isWritable() && (pOffset + pLength) > m_FileSize)
- return NULL;
-
- if (isWritable() && (pOffset + pLength) > m_FileSize) {
- // If the memory area is writable, user can expand the size of file by
- // request a region larger than the file.
- // MemoryArea should enlarge the file if the requested region is larger
- // than the file.
- m_FileSize = page_boundary(pOffset + pLength + 1);
- truncate(m_FileSize);
- }
-
Space* space = find(pOffset, pLength);
- MemoryArea::Address r_start = 0;
if (NULL == space) {
- // the space does not exist, create a new space.
- space = new Space(this, pOffset, pLength);
+
+ // not found
+ if (NULL == m_pFileHandle) {
+ // if m_pFileHandle is NULL, clients delegate us an universal Space and
+ // we never remove it. In that way, space can not be NULL.
+ unreachable(diag::err_out_of_range_region);
+ }
+
+ space = Space::createSpace(*m_pFileHandle, pOffset, pLength);
m_SpaceList.push_back(space);
- switch(space->type = policy(pOffset, pLength)) {
- case Space::MMAPED: {
- int mm_prot, mm_flag;
- if (isWritable()) {
- mm_prot = PROT_READ | PROT_WRITE;
- mm_flag = MAP_FILE | MAP_SHARED;
- }
- else {
- mm_prot = PROT_READ;
- mm_flag = MAP_FILE | MAP_PRIVATE;
- }
-
- space->file_offset = page_offset(pOffset);
-
- // The space's size may be larger than filesize.
- space->size = page_boundary(pLength + pOffset + 1 - space->file_offset);
- space->data = (Address) ::mmap(NULL,
- space->size,
- mm_prot, mm_flag,
- m_FileDescriptor,
- space->file_offset);
-
- if (space->data == MAP_FAILED) {
- llvm::report_fatal_error(llvm::Twine("cannot open memory map file :") +
- m_FilePath.native() +
- llvm::Twine(" (") +
- sys::fs::detail::strerror(errno) +
- llvm::Twine(").\n"));
- }
-
- r_start = space->data + (pOffset - space->file_offset);
- break;
- }
- case Space::ALLOCATED_ARRAY: {
- // space->offset and space->size are set in constructor. We only need
- // to set up data.
- space->data = new unsigned char[pLength];
- r_start = space->data;
- if ((m_AccessFlags & AccessMask) != WriteOnly) {
- // Read data from the backend file.
- if (!read(*space)) {
- llvm::report_fatal_error(llvm::Twine("Failed to read data from ") +
- m_FilePath.native() +
- llvm::Twine(" (") +
- sys::fs::detail::strerror(errno) +
- llvm::Twine(") at offset ") +
- llvm::Twine(pOffset) +
- llvm::Twine(" lenght ") +
- llvm::Twine(pLength) + llvm::Twine(".\n"));
- }
- }
- break;
- } // case
- default: {
- llvm::report_fatal_error("unhandled space type\n");
- }
- } // switch
}
- else { // found
- off_t distance = pOffset - space->file_offset;
- r_start = space->data + distance;
- }
+
+ // adjust r_start
+ off_t distance = pOffset - space->start();
+ void* r_start = space->memory() + distance;
// now, we have a legal space to hold the new MemoryRegion
- return m_RegionFactory.produce(space, r_start, pLength);
+ return m_RegionFactory.produce(*space, r_start, pLength);
}
// release - release a MemoryRegion
void MemoryArea::release(MemoryRegion* pRegion)
{
- if (!isMapped() || !isGood())
+ if (NULL == pRegion)
return;
Space *space = pRegion->parent();
m_RegionFactory.destruct(pRegion);
- if (0 == space->region_num) {
- write(*space);
- m_SpaceList.remove(*space);
- release(space);
+ if (0 == space->numOfRegions()) {
+
+ if (NULL != m_pFileHandle) {
+ // if m_pFileHandle is NULL, clients delegate us an universal Space and
+ // we never remove it. Otherwise, we have to synchronize and release
+ // Space.
+ if (m_pFileHandle->isWritable()) {
+ // synchronize writable space before we release it.
+ Space::syncSpace(space, *m_pFileHandle);
+ }
+ Space::releaseSpace(space, *m_pFileHandle);
+ }
+ m_SpaceList.erase(space);
}
}
-void MemoryArea::clean()
+// clear - release all MemoryRegions
+void MemoryArea::clear()
{
- m_RegionFactory.clear();
+ if (NULL == m_pFileHandle)
+ return;
- SpaceList::iterator sIter, sEnd = m_SpaceList.end();
- for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
- write(*sIter);
- release(sIter);
+ if (m_pFileHandle->isWritable()) {
+ SpaceList::iterator space, sEnd = m_SpaceList.end();
+ for (space = m_SpaceList.begin(); space != sEnd; ++space) {
+ Space::syncSpace(space, *m_pFileHandle);
+ Space::releaseSpace(space, *m_pFileHandle);
+ }
}
+ else {
+ SpaceList::iterator space, sEnd = m_SpaceList.end();
+ for (space = m_SpaceList.begin(); space != sEnd; ++space)
+ Space::releaseSpace(space, *m_pFileHandle);
+ }
+
m_SpaceList.clear();
}
-void MemoryArea::sync()
+//===--------------------------------------------------------------------===//
+// SpaceList methods
+Space* MemoryArea::find(size_t pOffset, size_t pLength)
{
SpaceList::iterator sIter, sEnd = m_SpaceList.end();
for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
- write(*sIter);
- }
-}
-
-MemoryArea::Space* MemoryArea::find(size_t pOffset, size_t pLength)
-{
- SpaceList::iterator sIter, sEnd = m_SpaceList.end();
- for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
- if (sIter->file_offset <= pOffset &&
- (pOffset+pLength) <= (sIter->file_offset+sIter->size) ) { // within
+ if (sIter->start() <= pOffset &&
+ (pOffset+pLength) <= (sIter->start()+sIter->size()) ) {
+ // within
return sIter;
}
}
return NULL;
}
-void MemoryArea::release(MemoryArea::Space* pSpace)
+const Space* MemoryArea::find(size_t pOffset, size_t pLength) const
{
- switch (pSpace->type) {
- case Space::ALLOCATED_ARRAY: {
- delete [] pSpace->data;
- break;
- }
- case Space::MMAPED: {
- ::munmap(pSpace->data, pSpace->size);
- break;
- }
- default:
- break;
- }
-}
-
-MemoryArea::Space::Type MemoryArea::policy(off_t pOffset, size_t pLength)
-{
- const size_t threshold = (PageSize*3)/4; // 3/4 page size in Linux
- if (pLength < threshold)
- return Space::ALLOCATED_ARRAY;
- else
- return Space::MMAPED;
-}
-
-ssize_t MemoryArea::readToBuffer(sys::fs::detail::Address pBuf,
- size_t pSize, size_t pOffset) {
- assert(((m_AccessFlags & AccessMask) != WriteOnly) &&
- "Write-only file cannot be read!");
-
- ssize_t read_bytes = sys::fs::detail::pread(m_FileDescriptor, pBuf,
- pSize, pOffset);
- if (static_cast<size_t>(read_bytes) != pSize) {
- // Some error occurred during pread().
- if (read_bytes < 0) {
- m_State |= FailBit;
- }
- else if (static_cast<size_t>(read_bytes) < pSize) {
- m_State |= EOFBit;
- if ((m_AccessFlags & AccessMask) != ReadWrite) {
- // Files which is not read-write are not allowed read beyonds the EOF
- // marker.
- m_State |= BadBit;
- }
- }
- else {
- m_State |= BadBit;
+ SpaceList::const_iterator sIter, sEnd = m_SpaceList.end();
+ for (sIter = m_SpaceList.begin(); sIter!=sEnd; ++sIter) {
+ if (sIter->start() <= pOffset &&
+ (pOffset+pLength) <= (sIter->start()+sIter->size()) ) {
+ // within
+ return sIter;
}
}
- return read_bytes;
-}
-
-bool MemoryArea::read(Space& pSpace) {
- if (!isGood() || !isReadable())
- return false;
-
- if (pSpace.type == Space::ALLOCATED_ARRAY) {
- readToBuffer(pSpace.data, pSpace.size, pSpace.file_offset);
- return isGood();
- }
- else {
- // Data associated with mmap()'ed space is already at the position the
- // pSpace points to.
- assert((pSpace.type == Space::MMAPED) && "Unknown type of Space!");
- return true;
- }
-}
-
-
-void MemoryArea::write(const Space& pSpace)
-{
- if (!isMapped() || !isGood() || !isWritable())
- return;
-
- switch(pSpace.type) {
- case Space::MMAPED: {
- if(-1 == ::msync(pSpace.data, pSpace.size, MS_SYNC))
- m_State |= FailBit;
- return;
- }
- case Space::ALLOCATED_ARRAY: {
- ssize_t write_bytes = sys::fs::detail::pwrite(m_FileDescriptor,
- pSpace.data,
- pSpace.size,
- pSpace.file_offset);
- if (0 > write_bytes) {
- m_State |= FailBit;
- return;
- }
- if (0 == write_bytes && 0 != pSpace.size)
- m_State |= BadBit;
- if ( pSpace.size > static_cast<size_t>(write_bytes) )
- m_State |= EOFBit;
- return;
- }
- default:
- return;
- }
+ return NULL;
}
diff --git a/lib/Support/MemoryAreaFactory.cpp b/lib/Support/MemoryAreaFactory.cpp
index 1f7e523..3da07d5 100644
--- a/lib/Support/MemoryAreaFactory.cpp
+++ b/lib/Support/MemoryAreaFactory.cpp
@@ -6,15 +6,18 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include "mcld/Support/MemoryAreaFactory.h"
-#include "mcld/Support/RegionFactory.h"
+#include <mcld/Support/MemoryAreaFactory.h>
+#include <mcld/Support/MsgHandling.h>
+#include <mcld/Support/RegionFactory.h>
+#include <mcld/Support/SystemUtils.h>
+#include <mcld/Support/Space.h>
using namespace mcld;
-//==========================
+//===----------------------------------------------------------------------===//
// MemoryAreaFactory
MemoryAreaFactory::MemoryAreaFactory(size_t pNum)
- : UniqueGCFactoryBase<sys::fs::Path, MemoryArea, 0>(pNum) {
+ : GCFactory<MemoryArea, 0>(pNum) {
// For each loaded file, MCLinker must load ELF header, section header,
// symbol table, and string table. So, we set the size of chunk quadruple
// larger than the number of input files.
@@ -23,30 +26,91 @@
MemoryAreaFactory::~MemoryAreaFactory()
{
+ HandleToArea::iterator rec, rEnd = m_HandleToArea.end();
+ for (rec = m_HandleToArea.begin(); rec != rEnd; ++rec) {
+ if (rec->handle->isOpened()) {
+ rec->handle->close();
+ }
+ delete rec->handle;
+ }
+
delete m_pRegionFactory;
}
-MemoryArea* MemoryAreaFactory::produce(const sys::fs::Path& pPath, int pFlags)
+MemoryArea*
+MemoryAreaFactory::produce(const sys::fs::Path& pPath,
+ FileHandle::OpenMode pMode)
{
- MemoryArea* result = find(pPath);
- if (0 == result) {
- result = allocate();
- new (result) MemoryArea(*m_pRegionFactory);
- result->map(pPath, pFlags);
- f_KeyMap.insert(std::make_pair(pPath, result));
+ HandleToArea::Result map_result = m_HandleToArea.findFirst(pPath);
+ if (NULL == map_result.area) {
+ // can not found
+ FileHandle* handler = new FileHandle();
+ if (!handler->open(pPath, pMode)) {
+ error(diag::err_cannot_open_file) << pPath
+ << sys::strerror(handler->error());
+ }
+
+ MemoryArea* result = allocate();
+ new (result) MemoryArea(*m_pRegionFactory, *handler);
+
+ m_HandleToArea.push_back(handler, result);
+ return result;
}
+
+ return map_result.area;
+}
+
+MemoryArea*
+MemoryAreaFactory::produce(const sys::fs::Path& pPath,
+ FileHandle::OpenMode pMode,
+ FileHandle::Permission pPerm)
+{
+ HandleToArea::Result map_result = m_HandleToArea.findFirst(pPath);
+ if (NULL == map_result.area) {
+ // can not found
+ FileHandle* handler = new FileHandle();
+ if (!handler->open(pPath, pMode, pPerm)) {
+ error(diag::err_cannot_open_file) << pPath
+ << sys::strerror(handler->error());
+ }
+
+ MemoryArea* result = allocate();
+ new (result) MemoryArea(*m_pRegionFactory, *handler);
+
+ m_HandleToArea.push_back(handler, result);
+ return result;
+ }
+
+ return map_result.area;
+}
+
+void MemoryAreaFactory::destruct(MemoryArea* pArea)
+{
+ m_HandleToArea.erase(pArea);
+ pArea->clear();
+ pArea->handler()->close();
+ destroy(pArea);
+ deallocate(pArea);
+}
+
+MemoryArea*
+MemoryAreaFactory::create(void* pMemBuffer, size_t pSize)
+{
+ Space* space = new Space(Space::EXTERNAL, pMemBuffer, pSize);
+ MemoryArea* result = allocate();
+ new (result) MemoryArea(*m_pRegionFactory, *space);
return result;
}
-MemoryArea* MemoryAreaFactory::produce(const sys::fs::Path& pPath, int pFlags, mode_t pMode)
+MemoryArea*
+MemoryAreaFactory::create(int pFD, FileHandle::OpenMode pMode)
{
- MemoryArea* result = find(pPath);
- if (0 == result) {
- result = allocate();
- new (result) MemoryArea(*m_pRegionFactory);
- result->map(pPath, pFlags, pMode);
- f_KeyMap.insert(std::make_pair(pPath, result));
- }
+ FileHandle* handler = new FileHandle();
+ handler->delegate(pFD, pMode);
+
+ MemoryArea* result = allocate();
+ new (result) MemoryArea(*m_pRegionFactory, *handler);
+
return result;
}
diff --git a/lib/Support/MemoryRegion.cpp b/lib/Support/MemoryRegion.cpp
index 3a35f4e..32e790b 100644
--- a/lib/Support/MemoryRegion.cpp
+++ b/lib/Support/MemoryRegion.cpp
@@ -12,23 +12,13 @@
//==========================
// MemoryRegion
-MemoryRegion::MemoryRegion(MemoryArea::Space *pParentSpace,
- const MemoryRegion::Address pVMAStart,
+MemoryRegion::MemoryRegion(Space& pParent,
+ MemoryRegion::Address pVMAStart,
size_t pSize)
- : m_pParentSpace(pParentSpace), m_VMAStart(pVMAStart), m_Length(pSize) {
- m_pParentSpace->region_num++;
+ : m_Parent(pParent), m_VMAStart(pVMAStart), m_Length(pSize) {
}
MemoryRegion::~MemoryRegion()
{
- drift();
-}
-
-void MemoryRegion::drift()
-{
- if (NULL == m_pParentSpace)
- return;
- m_pParentSpace->region_num--;
- m_pParentSpace = NULL;
}
diff --git a/lib/Support/MsgHandling.cpp b/lib/Support/MsgHandling.cpp
new file mode 100644
index 0000000..5b45289
--- /dev/null
+++ b/lib/Support/MsgHandling.cpp
@@ -0,0 +1,74 @@
+//===- MsgHandling.cpp ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/LD/DiagnosticEngine.h>
+#include <mcld/LD/DiagnosticLineInfo.h>
+#include <mcld/LD/DiagnosticPrinter.h>
+#include <mcld/LD/MsgHandler.h>
+#include <mcld/Support/MsgHandling.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <llvm/Support/raw_ostream.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// DiagnosticInitializer
+class DiagnosticInitializer : public llvm::ManagedStaticBase
+{
+public:
+ DiagnosticEngine* initialize(const MCLDInfo& pLDInfo,
+ DiagnosticLineInfo* pLineInfo,
+ DiagnosticPrinter* pPrinter)
+ {
+ RegisterManagedStatic(NULL, llvm::object_deleter<DiagnosticEngine>::call);
+ if (llvm::llvm_is_multithreaded()) {
+ llvm::llvm_acquire_global_lock();
+ void* tmp = NULL;
+ if (NULL != pPrinter)
+ tmp = new DiagnosticEngine(pLDInfo, pLineInfo, pPrinter, false);
+ else
+ tmp = new DiagnosticEngine(pLDInfo, pLineInfo, NULL, false);
+
+ TsanHappensBefore(this);
+ llvm::sys::MemoryFence();
+ TsanIgnoreWritesBegin();
+ Ptr = tmp;
+ TsanIgnoreWritesEnd();
+ llvm::llvm_release_global_lock();
+ }
+ else {
+ if (NULL != pPrinter)
+ Ptr = new DiagnosticEngine(pLDInfo, pLineInfo, pPrinter, false);
+ else
+ Ptr = new DiagnosticEngine(pLDInfo, pLineInfo, NULL, false);
+ }
+ return static_cast<DiagnosticEngine*>(Ptr);
+ }
+};
+
+static DiagnosticInitializer g_DiagInitializer;
+static DiagnosticEngine* g_pDiagnosticEngine = NULL;
+
+void mcld::InitializeDiagnosticEngine(const mcld::MCLDInfo& pLDInfo,
+ DiagnosticLineInfo* pLineInfo,
+ DiagnosticPrinter* pPrinter)
+{
+ if (NULL == g_pDiagnosticEngine) {
+ g_pDiagnosticEngine = g_DiagInitializer.initialize(pLDInfo,
+ pLineInfo,
+ pPrinter);
+ }
+}
+
+DiagnosticEngine& mcld::getDiagnosticEngine()
+{
+ assert(NULL != g_pDiagnosticEngine &&
+ "mcld::InitializeDiagnostics() is not called");
+ return *g_pDiagnosticEngine;
+}
+
diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp
index ffb449f..8cc384d 100644
--- a/lib/Support/Path.cpp
+++ b/lib/Support/Path.cpp
@@ -11,11 +11,8 @@
#include <llvm/ADT/StringRef.h>
#include <locale>
-#include <stdio.h>
#include <string.h>
-#include <iostream>
-
using namespace mcld;
using namespace mcld::sys::fs;
@@ -119,7 +116,7 @@
Path::StringType::size_type Path::m_append_separator_if_needed()
{
if (!m_PathName.empty() &&
-#ifdef LLVM_ON_WIN32
+#if defined(MCLD_ON_WIN32)
*(m_PathName.end()-1) != colon &&
#endif
!is_separator(*(m_PathName.end()-1))) {
@@ -171,7 +168,7 @@
bool mcld::sys::fs::is_separator(char value)
{
return (value == separator
-#ifdef LLVM_ON_WIN32
+#if defined(MCLD_ON_WIN32)
|| value == preferred_separator
#endif
);
diff --git a/lib/Support/RegionFactory.cpp b/lib/Support/RegionFactory.cpp
index e87d389..ddce433 100644
--- a/lib/Support/RegionFactory.cpp
+++ b/lib/Support/RegionFactory.cpp
@@ -6,8 +6,9 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include "mcld/Support/RegionFactory.h"
-#include "mcld/Support/MemoryArea.h"
+#include <mcld/Support/RegionFactory.h>
+#include <mcld/Support/MemoryArea.h>
+#include <mcld/Support/Space.h>
using namespace mcld;
@@ -21,18 +22,19 @@
{
}
-MemoryRegion* RegionFactory::produce(MemoryArea::Space* pSpace,
- const sys::fs::detail::Address pVMAStart,
- size_t pSize)
+MemoryRegion* RegionFactory::produce(Space& pSpace, void* pVMAStart, size_t pSize)
{
MemoryRegion* result = Alloc::allocate();
- new (result) MemoryRegion(pSpace, pVMAStart, pSize);
+ new (result) MemoryRegion(pSpace,
+ static_cast<const MemoryRegion::Address>(pVMAStart),
+ pSize);
+ pSpace.addRegion(*result);
return result;
}
void RegionFactory::destruct(MemoryRegion* pRegion)
{
- pRegion->drift();
+ pRegion->parent()->removeRegion(*pRegion);
destroy(pRegion);
deallocate(pRegion);
}
diff --git a/lib/Support/Space.cpp b/lib/Support/Space.cpp
new file mode 100644
index 0000000..4024da1
--- /dev/null
+++ b/lib/Support/Space.cpp
@@ -0,0 +1,179 @@
+//===- Space.cpp ----------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/Space.h>
+#include <mcld/Support/FileHandle.h>
+#include <mcld/Support/MsgHandling.h>
+#include <cstdlib>
+#include <unistd.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// constant data
+static const off_t PageSize = getpagesize();
+
+//===----------------------------------------------------------------------===//
+// Non-member functions
+//
+// low address A page high address
+// |--------------------|------------------|
+// ^ page_offset ^ pFileOffset ^ page_boundary
+
+// Given a file offset, return the page offset.
+// return the first page boundary \b before pFileOffset
+inline static off_t page_offset(off_t pFileOffset)
+{ return pFileOffset & ~ (PageSize - 1); }
+
+// page_boundary - Given a file size, return the size to read integral pages.
+// return the first page boundary \b after pFileOffset
+inline static off_t page_boundary(off_t pFileOffset)
+{ return (pFileOffset + (PageSize - 1)) & ~ (PageSize - 1); }
+
+inline static Space::Type policy(off_t pOffset, size_t pLength)
+{
+ const size_t threshold = (PageSize*3)/4; // 3/4 page size in Linux
+ if (pLength < threshold)
+ return Space::ALLOCATED_ARRAY;
+ else
+ return Space::MMAPED;
+}
+
+//===----------------------------------------------------------------------===//
+// Space
+Space::Space()
+ : m_Data(NULL), m_StartOffset(0), m_Size(0),
+ m_RegionCount(0), m_Type(UNALLOCATED) {
+}
+
+Space::Space(Space::Type pType, void* pMemBuffer, size_t pSize)
+ : m_Data(static_cast<Address>(pMemBuffer)), m_StartOffset(0), m_Size(pSize),
+ m_RegionCount(0), m_Type(pType)
+{
+}
+
+Space::~Space()
+{
+ // do nothing. m_Data is deleted by @ref releaseSpace
+}
+
+Space* Space::createSpace(FileHandle& pHandler,
+ size_t pStart, size_t pSize)
+{
+ Type type;
+ void* memory;
+ Space* result = NULL;
+ size_t start, size = 0, total_offset;
+ switch(type = policy(pStart, pSize)) {
+ case ALLOCATED_ARRAY: {
+ // adjust total_offset, start and size
+ total_offset = pStart + pSize;
+ start = pStart;
+ if (total_offset > pHandler.size()) {
+ if (pHandler.isWritable()) {
+ size = pSize;
+ pHandler.truncate(total_offset);
+ }
+ else if (pHandler.size() > start)
+ size = pHandler.size() - start;
+ else {
+ // create a space out of a read-only file.
+ fatal(diag::err_cannot_read_small_file) << pHandler.path()
+ << pHandler.size()
+ << start << size;
+ }
+ }
+ else
+ size = pSize;
+
+ // malloc
+ memory = (void*)malloc(size);
+ if (!pHandler.read(memory, start, size))
+ error(diag::err_cannot_read_file) << pHandler.path() << start << size;
+
+ break;
+ }
+ case MMAPED: {
+ // adjust total_offset, start and size
+ total_offset = page_boundary(pStart + pSize);
+ start = page_offset(pStart);
+ if (total_offset > pHandler.size()) {
+ if (pHandler.isWritable()) {
+ size = page_boundary((pStart - start) + pSize);
+ pHandler.truncate(total_offset);
+ }
+ else if (pHandler.size() > start)
+ size = pHandler.size() - start;
+ else {
+ // create a space out of a read-only file.
+ fatal(diag::err_cannot_read_small_file) << pHandler.path()
+ << pHandler.size()
+ << start << size;
+ }
+ }
+ else
+ size = page_boundary((pStart - start) + pSize);
+
+ // mmap
+ if (!pHandler.mmap(memory, start, size))
+ error(diag::err_cannot_mmap_file) << pHandler.path() << start << size;
+
+ break;
+ }
+ default:
+ break;
+ } // end of switch
+
+ result = new Space(type, memory, size);
+ result->setStart(start);
+ return result;
+}
+
+void Space::releaseSpace(Space* pSpace, FileHandle& pHandler)
+{
+ if (NULL == pSpace)
+ return;
+
+ switch(pSpace->type()) {
+ case ALLOCATED_ARRAY:
+ free(pSpace->memory());
+ break;
+ case MMAPED:
+ if (!pHandler.munmap(pSpace->memory(), pSpace->size()))
+ error(diag::err_cannot_munmap_file) << pHandler.path();
+ break;
+ default: // external and unallocated memory buffers
+ break;
+ } // end of switch
+}
+
+void Space::syncSpace(Space* pSpace, FileHandle& pHandler)
+{
+ if (NULL == pSpace || !pHandler.isWritable())
+ return;
+
+ switch(pSpace->type()) {
+ case Space::ALLOCATED_ARRAY: {
+ if (!pHandler.write(pSpace->memory(),
+ pSpace->start(),
+ pSpace->size())) {
+ error(diag::err_cannot_write_file) << pHandler.path()
+ << pSpace->start()
+ << pSpace->size();
+ }
+ return;
+ }
+ case Space::MMAPED:
+ default: {
+ // system will eventually write bakc the memory after
+ // calling ::munmap
+ return;
+ }
+ } // end of switch
+}
+
diff --git a/lib/Support/SystemUtils.cpp b/lib/Support/SystemUtils.cpp
new file mode 100644
index 0000000..5dfea36
--- /dev/null
+++ b/lib/Support/SystemUtils.cpp
@@ -0,0 +1,20 @@
+//===- SystemUtils.cpp ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/SystemUtils.h>
+
+using namespace mcld::sys;
+
+//===----------------------------------------------------------------------===//
+// Non-member functions
+#if defined(MCLD_ON_UNIX)
+#include "Unix/System.inc"
+#endif
+#if defined(MCLD_ON_WIN32)
+#include "Windows/System.inc"
+#endif
diff --git a/lib/Support/TargetRegistry.cpp b/lib/Support/TargetRegistry.cpp
index 246cbe8..8bfa235 100644
--- a/lib/Support/TargetRegistry.cpp
+++ b/lib/Support/TargetRegistry.cpp
@@ -6,13 +6,11 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include "mcld/Support/TargetRegistry.h"
+#include <mcld/Support/TargetRegistry.h>
mcld::TargetRegistry::TargetListTy mcld::TargetRegistry::s_TargetList;
-/* ** */
-
void mcld::TargetRegistry::RegisterTarget(mcld::Target &T)
{
s_TargetList.push_back(&T);
@@ -34,7 +32,7 @@
const mcld::Target *mcld::TargetRegistry::lookupTarget(const std::string &pTriple,
std::string &pError)
{
- const llvm::Target* target = llvm::TargetRegistry::lookupTarget( pTriple, pError );
+ const llvm::Target* target = llvm::TargetRegistry::lookupTarget(pTriple, pError);
if (!target)
return 0;
return lookupTarget( *target );
diff --git a/lib/Support/Unix/FileSystem.inc b/lib/Support/Unix/FileSystem.inc
index 6499d66..ce6d0df 100644
--- a/lib/Support/Unix/FileSystem.inc
+++ b/lib/Support/Unix/FileSystem.inc
@@ -9,6 +9,7 @@
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
+#include <unistd.h>
#include <fcntl.h>
namespace mcld{
@@ -23,19 +24,29 @@
std::string assembly_extension = ".s";
std::string bitcode_extension = ".bc";
-size_t pread(int pFD, Address pBuf, size_t pCount, off_t pOffset)
+int open(const Path& pPath, int pOFlag)
{
- return ::pread(pFD, (void*) pBuf, pCount, pOffset);
+ return ::open(pPath.native().c_str(), pOFlag);
}
-size_t pwrite(int pFD, const Address pBuf, size_t pCount, off_t pOffset)
+int open(const Path& pPath, int pOFlag, int pPerm)
{
- return ::pwrite(pFD, (const void*) pBuf, pCount, pOffset);
+ return ::open(pPath.native().c_str(), pOFlag, pPerm);
}
-char *strerror(int errnum)
+ssize_t pread(int pFD, void* pBuf, size_t pCount, size_t pOffset)
{
- return ::strerror(errnum);
+ return ::pread(pFD, pBuf, pCount, pOffset);
+}
+
+ssize_t pwrite(int pFD, const void* pBuf, size_t pCount, size_t pOffset)
+{
+ return ::pwrite(pFD, pBuf, pCount, pOffset);
+}
+
+int ftruncate(int pFD, size_t pLength)
+{
+ return ::ftruncate(pFD, pLength);
}
} // namespace of detail
diff --git a/lib/Support/Unix/PathV3.inc b/lib/Support/Unix/PathV3.inc
index 2e8e6d0..68b0c36 100644
--- a/lib/Support/Unix/PathV3.inc
+++ b/lib/Support/Unix/PathV3.inc
@@ -282,7 +282,7 @@
{
if (pDir.m_Handler)
closedir(reinterpret_cast<DIR *>(pDir.m_Handler));
- pDir.m_Handler = NULL;
+ pDir.m_Handler = 0;
}
void get_pwd(std::string& pPWD)
diff --git a/lib/Support/Unix/System.inc b/lib/Support/Unix/System.inc
new file mode 100644
index 0000000..716aaa2
--- /dev/null
+++ b/lib/Support/Unix/System.inc
@@ -0,0 +1,24 @@
+//===- System.inc ---------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <string>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+namespace mcld{
+namespace sys{
+
+char *strerror(int errnum)
+{
+ return ::strerror(errnum);
+}
+
+} // namespace of sys
+} // namespace of mcld
+
diff --git a/lib/Support/Windows/System.inc b/lib/Support/Windows/System.inc
new file mode 100644
index 0000000..bfd75ee
--- /dev/null
+++ b/lib/Support/Windows/System.inc
@@ -0,0 +1,19 @@
+//===- System.inc ---------------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <string>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+namespace mcld{
+namespace sys{
+
+} // namespace of sys
+} // namespace of mcld
+
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
new file mode 100644
index 0000000..2453c2c
--- /dev/null
+++ b/lib/Support/raw_ostream.cpp
@@ -0,0 +1,95 @@
+//===- raw_ostream.cpp ----------------------------------------------------===//
+//
+// The MCLinker Project
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include <mcld/Support/raw_ostream.h>
+
+using namespace mcld;
+
+//===----------------------------------------------------------------------===//
+// raw_ostream
+mcld::raw_fd_ostream::raw_fd_ostream(const char *pFilename,
+ std::string &pErrorInfo,
+ unsigned int pFlags,
+ const MCLDInfo* pLDInfo)
+ : llvm::raw_fd_ostream(pFilename, pErrorInfo, pFlags), m_pLDInfo(pLDInfo) {
+}
+
+mcld::raw_fd_ostream::raw_fd_ostream(int pFD,
+ bool pShouldClose,
+ bool pUnbuffered,
+ const MCLDInfo* pLDInfo)
+ : llvm::raw_fd_ostream(pFD, pShouldClose, pUnbuffered), m_pLDInfo(pLDInfo) {
+}
+
+mcld::raw_fd_ostream::~raw_fd_ostream()
+{
+}
+
+void mcld::raw_fd_ostream::setLDInfo(const MCLDInfo& pLDInfo)
+{
+ m_pLDInfo = &pLDInfo;
+}
+
+llvm::raw_ostream &
+mcld::raw_fd_ostream::changeColor(enum llvm::raw_ostream::Colors pColor,
+ bool pBold,
+ bool pBackground)
+{
+ if (!is_displayed())
+ return *this;
+ return llvm::raw_fd_ostream::changeColor(pColor, pBold, pBackground);
+}
+
+llvm::raw_ostream& mcld::raw_fd_ostream::resetColor()
+{
+ if (!is_displayed())
+ return *this;
+ return llvm::raw_fd_ostream::resetColor();
+}
+
+// FIXME: migrate to newer LLVM
+/**
+llvm::raw_ostream& mcld::raw_fd_ostream::reverseColor()
+{
+ if (!is_displayed())
+ return *this;
+ return llvm::raw_ostream::reverseColor();
+}
+**/
+
+bool mcld::raw_fd_ostream::is_displayed() const
+{
+ if (NULL == m_pLDInfo)
+ return llvm::raw_fd_ostream::is_displayed();
+
+ return m_pLDInfo->options().color();
+}
+
+//===----------------------------------------------------------------------===//
+// outs(), errs(), nulls()
+//===----------------------------------------------------------------------===//
+mcld::raw_fd_ostream& mcld::outs() {
+ // Set buffer settings to model stdout behavior.
+ // Delete the file descriptor when the program exists, forcing error
+ // detection. If you don't want this behavior, don't use outs().
+ static mcld::raw_fd_ostream S(STDOUT_FILENO, true, NULL);
+ return S;
+}
+
+mcld::raw_fd_ostream& mcld::errs() {
+ // Set standard error to be unbuffered by default.
+ static mcld::raw_fd_ostream S(STDERR_FILENO, false, true, NULL);
+ return S;
+}
+
+void mcld::InitializeOStreams(const MCLDInfo& pLDInfo)
+{
+ outs().setLDInfo(pLDInfo);
+ errs().setLDInfo(pLDInfo);
+}
+