[ELF] Write the output to lld::outs() when -o is - (#209064)

When the output file is "-", write the image to lld::outs() (the
stdoutOS
argument of lld::elf::link()) instead of committing the
FileOutputBuffer,
which writes to the process's stdout. This lets lld used as a library
capture
the output in a raw_ostream without an open syscall.

This reimplements the stale #72061 and adds a unittest.
This commit is contained in:
Fangrui Song authored and GitHub committed 2026-07-12 23:40:56 +00:00
1 parent b6e77d6af1
commit c847ddf8f1
3 files changed
+44 -1

No files matched your search

+8 -1
View File
@@ -364,7 +364,14 @@ template <class ELFT> void Writer<ELFT>::run() {
if (errCount(ctx))
return;
if (!ctx.e.disableOutput) {
// With -o -, write to lld::outs() (the stdoutOS argument of
// link()) instead of committing the buffer, which would write to the
// process's stdout.
if (ctx.arg.outputFile == "-") {
ctx.e.outs() << StringRef(
reinterpret_cast<const char *>(buffer->getBufferStart()),
buffer->getBufferSize());
} else if (!ctx.e.disableOutput) {
if (auto e = buffer->commit())
Err(ctx) << "failed to write output '" << buffer->getPath()
<< "': " << std::move(e);
+1
View File
@@ -3,6 +3,7 @@
# target application executable.
add_lld_unittests(LLDAsLibELFTests
OutputStream.cpp
ROCm.cpp
SomeDrivers.cpp
)
+35
View File
@@ -0,0 +1,35 @@
//===----------------------------------------------------------------------===//
//
// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLD_DEFAULT_LD_LLD_IS_MINGW
#include "lld/Common/Driver.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "gmock/gmock.h"
LLD_HAS_DRIVER(elf)
// With "-o -", the ELF driver writes the output image to the stdoutOS stream
// passed to link(), so lld used as a library can capture it in a raw_ostream.
TEST(AsLib, OutputToStream) {
llvm::SmallString<256> input(getenv("LLD_SRC_DIR"));
llvm::sys::path::append(input, "unittests", "AsLibELF", "Inputs",
"kernel1.o");
std::vector<const char *> args{"ld.lld", "-shared", input.c_str(), "-o", "-"};
std::string buf;
llvm::raw_string_ostream os(buf);
lld::Result s =
lld::lldMain(args, os, llvm::errs(), {{lld::Gnu, &lld::elf::link}});
EXPECT_EQ(s.retCode, 0);
EXPECT_TRUE(s.canRunAgain);
EXPECT_TRUE(llvm::StringRef(buf).starts_with("\177ELF"));
}
#endif