diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 7567e1923d94..2da732c857be 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -364,7 +364,14 @@ template void Writer::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(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); diff --git a/lld/unittests/AsLibELF/CMakeLists.txt b/lld/unittests/AsLibELF/CMakeLists.txt index cffd9da7006e..70a3f027076c 100644 --- a/lld/unittests/AsLibELF/CMakeLists.txt +++ b/lld/unittests/AsLibELF/CMakeLists.txt @@ -3,6 +3,7 @@ # target application executable. add_lld_unittests(LLDAsLibELFTests + OutputStream.cpp ROCm.cpp SomeDrivers.cpp ) diff --git a/lld/unittests/AsLibELF/OutputStream.cpp b/lld/unittests/AsLibELF/OutputStream.cpp new file mode 100644 index 000000000000..629c674fe2b6 --- /dev/null +++ b/lld/unittests/AsLibELF/OutputStream.cpp @@ -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 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