bool ltoNewPassManager;
bool mergeArmExidx;
bool mipsN32Abi = false;
+ bool mmapOutputFile;
bool nmagic;
bool noinhibitExec;
bool nostdlib;
config->mipsGotSize = args::getInteger(args, OPT_mips_got_size, 0xfff0);
config->mergeArmExidx =
args.hasFlag(OPT_merge_exidx_entries, OPT_no_merge_exidx_entries, true);
+ config->mmapOutputFile =
+ args.hasFlag(OPT_mmap_output_file, OPT_no_mmap_output_file, true);
config->nmagic = args.hasFlag(OPT_nmagic, OPT_no_nmagic, false);
config->noinhibitExec = args.hasArg(OPT_noinhibit_exec);
config->nostdlib = args.hasArg(OPT_nostdlib);
"Enable merging .ARM.exidx entries (default)",
"Disable merging .ARM.exidx entries">;
+defm mmap_output_file: B<"mmap-output-file",
+ "Mmap the output file for writing (default)",
+ "Do not mmap the output file for writing">;
+
def nmagic: F<"nmagic">, MetaVarName<"<magic>">,
HelpText<"Do not page align sections, link against static libraries.">;
def: F<"no-copy-dt-needed-entries">;
def: F<"no-ctors-in-init-array">;
def: F<"no-keep-memory">;
-def: F<"no-mmap-output-file">;
def: F<"no-pipeline-knowledge">;
def: F<"no-warn-mismatch">;
def: Flag<["-"], "p">;
unlinkAsync(config->outputFile);
unsigned flags = 0;
if (!config->relocatable)
- flags = FileOutputBuffer::F_executable;
+ flags |= FileOutputBuffer::F_executable;
+ if (!config->mmapOutputFile)
+ flags |= FileOutputBuffer::F_no_mmap;
Expected<std::unique_ptr<FileOutputBuffer>> bufferOrErr =
FileOutputBuffer::create(config->outputFile, fileSize, flags);
RUN: -no-copy-dt-needed-entries \
RUN: -no-ctors-in-init-array \
RUN: -no-keep-memory \
-RUN: -no-mmap-output-file \
RUN: -no-pipeline-knowledge \
RUN: -no-warn-mismatch \
RUN: -p \
enum {
/// set the 'x' bit on the resulting file
F_executable = 1,
+
+ /// Don't use mmap and instead write an in-memory buffer to a file when this
+ /// buffer is closed.
+ F_no_mmap = 2,
};
/// Factory method to create an OutputBuffer object which manages a read/write
case fs::file_type::regular_file:
case fs::file_type::file_not_found:
case fs::file_type::status_error:
- return createOnDiskBuffer(Path, Size, Mode);
+ if (Flags & F_no_mmap)
+ return createInMemoryBuffer(Path, Size, Mode);
+ else
+ return createOnDiskBuffer(Path, Size, Mode);
default:
return createInMemoryBuffer(Path, Size, Mode);
}
EXPECT_TRUE(IsExecutable);
ASSERT_NO_ERROR(fs::remove(File4.str()));
+ // TEST 5: In-memory buffer works as expected.
+ SmallString<128> File5(TestDirectory);
+ File5.append("/file5");
+ {
+ Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
+ FileOutputBuffer::create(File5, 8000, FileOutputBuffer::F_no_mmap);
+ ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));
+ std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;
+ // Start buffer with special header.
+ memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
+ ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));
+ // Write to end of buffer to verify it is writable.
+ memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20);
+ // Commit buffer.
+ ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));
+ }
+
+ // Verify file is correct size.
+ uint64_t File5Size;
+ ASSERT_NO_ERROR(fs::file_size(Twine(File5), File5Size));
+ ASSERT_EQ(File5Size, 8000ULL);
+ ASSERT_NO_ERROR(fs::remove(File5.str()));
// Clean up.
ASSERT_NO_ERROR(fs::remove(TestDirectory.str()));
}