Skip to content

Commit ca67510

Browse files
committed
[lld-macho] Initial groundwork for -bitcode_bundle
This diff creates an empty XAR file and copies it into `__LLVM,__bundle`. Follow-up work will actually populate the contents of that XAR. Reviewed By: #lld-macho, gkm Differential Revision: https://reviews.llvm.org/D100650
1 parent 657b325 commit ca67510

14 files changed

+144
-2
lines changed

lld/MachO/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ struct Configuration {
8888
bool saveTemps = false;
8989
bool adhocCodesign = false;
9090
bool emitFunctionStarts = false;
91+
bool emitBitcodeBundle = false;
9192
bool timeTraceEnabled = false;
9293
uint32_t headerPad;
9394
uint32_t dylibCompatibilityVersion = 0;

lld/MachO/Driver.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "llvm/ADT/StringRef.h"
3232
#include "llvm/BinaryFormat/MachO.h"
3333
#include "llvm/BinaryFormat/Magic.h"
34+
#include "llvm/Config/config.h"
3435
#include "llvm/LTO/LTO.h"
3536
#include "llvm/Object/Archive.h"
3637
#include "llvm/Option/ArgList.h"
@@ -958,6 +959,12 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
958959
config->demangle = args.hasArg(OPT_demangle);
959960
config->implicitDylibs = !args.hasArg(OPT_no_implicit_dylibs);
960961
config->emitFunctionStarts = !args.hasArg(OPT_no_function_starts);
962+
config->emitBitcodeBundle = args.hasArg(OPT_bitcode_bundle);
963+
964+
#ifndef HAVE_LIBXAR
965+
if (config->emitBitcodeBundle)
966+
error("-bitcode_bundle unsupported because LLD wasn't built with libxar");
967+
#endif
961968

962969
if (const Arg *arg = args.getLastArg(OPT_install_name)) {
963970
if (config->outputType != MH_DYLIB)

lld/MachO/InputSection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ constexpr const char stubs[] = "__stubs";
101101
constexpr const char stubHelper[] = "__stub_helper";
102102
constexpr const char laSymbolPtr[] = "__la_symbol_ptr";
103103
constexpr const char data[] = "__data";
104+
constexpr const char bitcodeBundle[] = "__bundle";
104105

105106
} // namespace section_names
106107

lld/MachO/Options.td

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,6 @@ def grp_bitcode : OptionGroup<"bitcode">, HelpText<"BITCODE BUILD FLOW">;
545545

546546
def bitcode_bundle : Flag<["-"], "bitcode_bundle">,
547547
HelpText<"Generate an embedded bitcode bundle in the __LLVM,__bundle section of the output">,
548-
Flags<[HelpHidden]>,
549548
Group<grp_bitcode>;
550549
def bitcode_hide_symbols : Flag<["-"], "bitcode_hide_symbols">,
551550
HelpText<"With -bitcode_bundle, hide all non-exported symbols from output bitcode bundle.">,

lld/MachO/OutputSection.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ class OutputSection {
4747
// Unneeded sections are omitted entirely (header and body).
4848
virtual bool isNeeded() const { return true; }
4949

50-
// Specifically finalizes addresses and section size, not content.
5150
virtual void finalize() {
5251
// TODO investigate refactoring synthetic section finalization logic into
5352
// overrides of this function.

lld/MachO/OutputSegment.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ constexpr const char linkEdit[] = "__LINKEDIT";
2424
constexpr const char dataConst[] = "__DATA_CONST";
2525
constexpr const char ld[] = "__LD"; // output only with -r
2626
constexpr const char dwarf[] = "__DWARF";
27+
constexpr const char llvm[] = "__LLVM";
2728

2829
} // namespace segment_names
2930

lld/MachO/SyntheticSections.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "lld/Common/ErrorHandler.h"
2121
#include "lld/Common/Memory.h"
2222
#include "llvm/ADT/STLExtras.h"
23+
#include "llvm/Config/config.h"
2324
#include "llvm/Support/EndianStream.h"
2425
#include "llvm/Support/FileSystem.h"
2526
#include "llvm/Support/LEB128.h"
@@ -30,6 +31,11 @@
3031
#include <sys/mman.h>
3132
#endif
3233

34+
#ifdef HAVE_LIBXAR
35+
#include <fcntl.h>
36+
#include <xar/xar.h>
37+
#endif
38+
3339
using namespace llvm;
3440
using namespace llvm::MachO;
3541
using namespace llvm::support;
@@ -1033,6 +1039,58 @@ void CodeSignatureSection::writeTo(uint8_t *buf) const {
10331039
memset(id + fileName.size(), 0, fileNamePad);
10341040
}
10351041

1042+
BitcodeBundleSection::BitcodeBundleSection()
1043+
: SyntheticSection(segment_names::llvm, section_names::bitcodeBundle) {}
1044+
1045+
class ErrorCodeWrapper {
1046+
public:
1047+
ErrorCodeWrapper(std::error_code ec) : errorCode(ec.value()) {}
1048+
ErrorCodeWrapper(int ec) : errorCode(ec) {}
1049+
operator int() const { return errorCode; }
1050+
1051+
private:
1052+
int errorCode;
1053+
};
1054+
1055+
#define CHECK_EC(exp) \
1056+
do { \
1057+
ErrorCodeWrapper ec(exp); \
1058+
if (ec) \
1059+
fatal(Twine("operation failed with error code ") + Twine(ec) + #exp); \
1060+
} while (0);
1061+
1062+
void BitcodeBundleSection::finalize() {
1063+
#ifdef HAVE_LIBXAR
1064+
using namespace llvm::sys::fs;
1065+
CHECK_EC(createTemporaryFile("bitcode-bundle", "xar", xarPath));
1066+
1067+
xar_t xar(xar_open(xarPath.data(), O_RDWR));
1068+
if (!xar)
1069+
fatal("failed to open XAR temporary file at " + xarPath);
1070+
CHECK_EC(xar_opt_set(xar, XAR_OPT_COMPRESSION, XAR_OPT_VAL_NONE));
1071+
// FIXME: add more data to XAR
1072+
CHECK_EC(xar_close(xar));
1073+
1074+
file_size(xarPath, xarSize);
1075+
#endif // defined(HAVE_LIBXAR)
1076+
}
1077+
1078+
void BitcodeBundleSection::writeTo(uint8_t *buf) const {
1079+
using namespace llvm::sys::fs;
1080+
file_t handle =
1081+
CHECK(openNativeFile(xarPath, CD_OpenExisting, FA_Read, OF_None),
1082+
"failed to open XAR file");
1083+
std::error_code ec;
1084+
mapped_file_region xarMap(handle, mapped_file_region::mapmode::readonly,
1085+
xarSize, 0, ec);
1086+
if (ec)
1087+
fatal("failed to map XAR file");
1088+
memcpy(buf, xarMap.const_data(), xarSize);
1089+
1090+
closeFile(handle);
1091+
remove(xarPath);
1092+
}
1093+
10361094
void macho::createSyntheticSymbols() {
10371095
auto addHeaderSymbol = [](const char *name) {
10381096
symtab->addSynthetic(name, in.header->isec, 0,

lld/MachO/SyntheticSections.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,18 @@ class CodeSignatureSection : public LinkEditSection {
488488
void writeHashes(uint8_t *buf) const;
489489
};
490490

491+
class BitcodeBundleSection : public SyntheticSection {
492+
public:
493+
BitcodeBundleSection();
494+
uint64_t getSize() const override { return xarSize; }
495+
void finalize() override;
496+
void writeTo(uint8_t *buf) const override;
497+
498+
private:
499+
llvm::SmallString<261> xarPath;
500+
uint64_t xarSize;
501+
};
502+
491503
static_assert((CodeSignatureSection::blobHeadersSize % 8) == 0, "");
492504
static_assert((CodeSignatureSection::fixedHeadersSize % 8) == 0, "");
493505

lld/MachO/Writer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,8 @@ template <class LP> void Writer::createOutputSections() {
803803
codeSignatureSection = make<CodeSignatureSection>();
804804
if (config->emitFunctionStarts)
805805
functionStartsSection = make<FunctionStartsSection>();
806+
if (config->emitBitcodeBundle)
807+
make<BitcodeBundleSection>();
806808

807809
switch (config->outputType) {
808810
case MH_EXECUTE:

lld/test/MachO/bitcode-bundle.ll

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
; REQUIRES: x86, xar
2+
; RUN: rm -rf %t; split-file %s %t
3+
; RUN: opt -module-summary %t/test.ll -o %t/test.o
4+
; RUN: opt -module-summary %t/foo.ll -o %t/foo.o
5+
; RUN: %lld -lSystem -bitcode_bundle %t/test.o %t/foo.o -o %t/test
6+
; RUN: llvm-objdump --macho --section=__LLVM,__bundle %t/test | FileCheck %s
7+
8+
; CHECK: Contents of (__LLVM,__bundle) section
9+
; CHECK-NEXT: For (__LLVM,__bundle) section: xar header
10+
; CHECK-NEXT: magic XAR_HEADER_MAGIC
11+
; CHECK-NEXT: size 28
12+
; CHECK-NEXT: version 1
13+
; CHECK-NEXT: toc_length_compressed
14+
; CHECK-NEXT: toc_length_uncompressed
15+
; CHECK-NEXT: cksum_alg XAR_CKSUM_SHA1
16+
; CHECK-NEXT: For (__LLVM,__bundle) section: xar table of contents:
17+
; CHECK-NEXT: <?xml version="1.0" encoding="UTF-8"?>
18+
; CHECK-NEXT: <xar>
19+
; CHECK-NEXT: <toc>
20+
; CHECK-NEXT: <checksum style="sha1">
21+
; CHECK-NEXT: <size>20</size>
22+
; CHECK-NEXT: <offset>0</offset>
23+
; CHECK-NEXT: </checksum>
24+
; CHECK-NEXT: <creation-time>{{.*}}</creation-time>
25+
; CHECK-NEXT: </toc>
26+
; CHECK-NEXT: </xar>
27+
28+
;--- foo.ll
29+
target triple = "x86_64-apple-darwin"
30+
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
31+
32+
define void @foo() {
33+
ret void
34+
}
35+
36+
;--- test.ll
37+
target triple = "x86_64-apple-darwin"
38+
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
39+
40+
define void @main() {
41+
ret void
42+
}

lld/test/MachO/invalid/no-libxar.ll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
; REQUIRES: x86
2+
; UNSUPPORTED: xar
3+
; RUN: opt -module-summary %s -o %t.o
4+
; RUN: not %lld -lSystem -bitcode_bundle %t.o -o /dev/null 2>&1 | FileCheck %s
5+
; CHECK: error: -bitcode_bundle unsupported because LLD wasn't built with libxar
6+
7+
target triple = "x86_64-apple-darwin"
8+
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
9+
10+
define void @main() {
11+
ret void
12+
}

lld/test/lit.cfg.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@
9090
config.have_libxml2):
9191
config.available_features.add('manifest_tool')
9292

93+
if config.have_libxar:
94+
config.available_features.add('xar')
95+
9396
if config.have_libxml2:
9497
config.available_features.add('libxml2')
9598

lld/test/lit.site.cfg.py.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ config.lld_tools_dir = "@LLD_TOOLS_DIR@"
1515
config.target_triple = "@TARGET_TRIPLE@"
1616
config.python_executable = "@Python3_EXECUTABLE@"
1717
config.have_zlib = @LLVM_ENABLE_ZLIB@
18+
config.have_libxar = @HAVE_LIBXAR@
1819
config.have_libxml2 = @LLVM_ENABLE_LIBXML2@
1920
config.sizeof_void_p = @CMAKE_SIZEOF_VOID_P@
2021
config.ld_lld_default_mingw = @LLD_DEFAULT_LD_LLD_IS_MINGW@

lld/tools/lld/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ target_link_libraries(lld
2020
lldWasm
2121
)
2222

23+
if(HAVE_LIBXAR)
24+
target_link_libraries(lld PRIVATE ${XAR_LIB})
25+
endif()
26+
2327
install(TARGETS lld
2428
RUNTIME DESTINATION bin)
2529

0 commit comments

Comments
 (0)