Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lld/MachO/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ struct Configuration {
bool pgoWarnMismatch;
bool warnThinArchiveMissingMembers;
bool disableVerify;
bool separateCstringLiteralSections;

bool callGraphProfileSort = false;
llvm::StringRef printSymbolOrder;
Expand Down
9 changes: 6 additions & 3 deletions lld/MachO/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1520,8 +1520,8 @@ static void foldIdenticalLiterals() {
// We always create a cStringSection, regardless of whether dedupLiterals is
// true. If it isn't, we simply create a non-deduplicating CStringSection.
// Either way, we must unconditionally finalize it here.
in.cStringSection->finalizeContents();
in.objcMethnameSection->finalizeContents();
for (auto *sec : in.cStringSections)
sec->finalizeContents();
in.wordLiteralSection->finalizeContents();
}

Expand Down Expand Up @@ -1709,7 +1709,7 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,

firstTLVDataSection = nullptr;
tar = nullptr;
memset(&in, 0, sizeof(in));
in = InStruct();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think adding a vector and map to this struct made it no longer trivially copyable. This seems like a better way to clear it anyway.


resetLoadedDylibs();
resetOutputSegments();
Expand Down Expand Up @@ -1981,6 +1981,9 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
OPT_no_warn_thin_archive_missing_members, true);
config->generateUuid = !args.hasArg(OPT_no_uuid);
config->disableVerify = args.hasArg(OPT_disable_verify);
config->separateCstringLiteralSections =
args.hasFlag(OPT_separate_cstring_literal_sections,
OPT_no_separate_cstring_literal_sections, false);

auto IncompatWithCGSort = [&](StringRef firstArgStr) {
// Throw an error only if --call-graph-profile-sort is explicitly specified
Expand Down
16 changes: 7 additions & 9 deletions lld/MachO/InputSection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,13 @@ void lld::macho::addInputSection(InputSection *inputSection) {
isec->parent = osec;
inputSections.push_back(isec);
} else if (auto *isec = dyn_cast<CStringInputSection>(inputSection)) {
if (isec->getName() == section_names::objcMethname) {
if (in.objcMethnameSection->inputOrder == UnspecifiedInputOrder)
in.objcMethnameSection->inputOrder = inputSectionsOrder++;
in.objcMethnameSection->addInput(isec);
} else {
if (in.cStringSection->inputOrder == UnspecifiedInputOrder)
in.cStringSection->inputOrder = inputSectionsOrder++;
in.cStringSection->addInput(isec);
}
bool useSectionName = config->separateCstringLiteralSections ||
isec->getName() == section_names::objcMethname;
auto *osec = in.getOrCreateCStringSection(
useSectionName ? isec->getName() : section_names::cString);
if (osec->inputOrder == UnspecifiedInputOrder)
osec->inputOrder = inputSectionsOrder++;
osec->addInput(isec);
} else if (auto *isec = dyn_cast<WordLiteralInputSection>(inputSection)) {
if (in.wordLiteralSection->inputOrder == UnspecifiedInputOrder)
in.wordLiteralSection->inputOrder = inputSectionsOrder++;
Expand Down
2 changes: 1 addition & 1 deletion lld/MachO/MapFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ void macho::writeMapFile() {
printIsecArrSyms(textOsec->inputs, textOsec->getThunks());
} else if (auto *concatOsec = dyn_cast<ConcatOutputSection>(osec)) {
printIsecArrSyms(concatOsec->inputs);
} else if (osec == in.cStringSection || osec == in.objcMethnameSection) {
} else if (is_contained(in.cStringSections, osec)) {
const auto &liveCStrings = info.liveCStringsForSection.lookup(osec);
uint64_t lastAddr = 0; // strings will never start at address 0, so this
// is a sentinel value
Expand Down
7 changes: 7 additions & 0 deletions lld/MachO/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,13 @@ def dyld_env : Separate<["-"], "dyld_env">,
def ignore_auto_link : Flag<["-"], "ignore_auto_link">,
HelpText<"Ignore LC_LINKER_OPTIONs">,
Group<grp_rare>;
defm separate_cstring_literal_sections
: BB<"separate-cstring-literal-sections",
"Emit all cstring literals into their respective sections defined by "
"their section names.",
"Emit all cstring literals into the __cstring section. As a special "
"case, the __objc_methname section will still be emitted. (default)">,
Group<grp_rare>;

def grp_deprecated : OptionGroup<"deprecated">, HelpText<"DEPRECATED">;

Expand Down
23 changes: 23 additions & 0 deletions lld/MachO/SyntheticSections.h
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,9 @@ void writeChainedFixup(uint8_t *buf, const Symbol *sym, int64_t addend);
struct InStruct {
const uint8_t *bufferStart = nullptr;
MachHeaderSection *header = nullptr;
/// The list of cstring sections. Note that this includes \p cStringSection
/// and \p objcMethnameSection already.
llvm::SmallVector<CStringSection *> cStringSections;
CStringSection *cStringSection = nullptr;
DeduplicatedCStringSection *objcMethnameSection = nullptr;
WordLiteralSection *wordLiteralSection = nullptr;
Expand All @@ -863,6 +866,26 @@ struct InStruct {
InitOffsetsSection *initOffsets = nullptr;
ObjCMethListSection *objcMethList = nullptr;
ChainedFixupsSection *chainedFixups = nullptr;

CStringSection *getOrCreateCStringSection(StringRef name,
bool forceDedupStrings = false) {
auto [it, didEmplace] =
cStringSectionMap.try_emplace(name, cStringSections.size());
if (!didEmplace)
return cStringSections[it->getValue()];

std::string &nameData = *make<std::string>(name);
CStringSection *sec;
if (config->dedupStrings || forceDedupStrings)
sec = make<DeduplicatedCStringSection>(nameData.c_str());
else
sec = make<CStringSection>(nameData.c_str());
cStringSections.push_back(sec);
return sec;
}

private:
llvm::StringMap<unsigned> cStringSectionMap;
};

extern InStruct in;
Expand Down
12 changes: 5 additions & 7 deletions lld/MachO/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1377,13 +1377,11 @@ void macho::resetWriter() { LCDylib::resetInstanceCount(); }

void macho::createSyntheticSections() {
in.header = make<MachHeaderSection>();
if (config->dedupStrings)
in.cStringSection =
make<DeduplicatedCStringSection>(section_names::cString);
else
in.cStringSection = make<CStringSection>(section_names::cString);
in.objcMethnameSection =
make<DeduplicatedCStringSection>(section_names::objcMethname);
// Materialize cstring and objcMethname sections
in.cStringSection = in.getOrCreateCStringSection(section_names::cString);
in.objcMethnameSection = cast<DeduplicatedCStringSection>(
in.getOrCreateCStringSection(section_names::objcMethname,
/*forceDedupStrings=*/true));
in.wordLiteralSection = make<WordLiteralSection>();
if (config->emitChainedFixups) {
in.chainedFixups = make<ChainedFixupsSection>();
Expand Down
32 changes: 32 additions & 0 deletions lld/test/MachO/cstring.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
; REQUIRES: aarch64
; RUN: llvm-as %s -o %t.o

; RUN: %lld -dylib --separate-cstring-literal-sections %t.o -o - | llvm-objdump --macho --section-headers - | FileCheck %s
; RUN: %lld -dylib --no-separate-cstring-literal-sections %t.o -o - | llvm-objdump --macho --section-headers - | FileCheck %s --check-prefix=CSTR
; RUN: %lld -dylib %t.o -o - | llvm-objdump --macho --section-headers - | FileCheck %s --check-prefix=CSTR

; CHECK-DAG: __cstring
; CHECK-DAG: __new_sec
; CHECK-DAG: __objc_classname
; CHECK-DAG: __objc_methname
; CHECK-DAG: __objc_methtype

; CSTR-DAG: __cstring
; CSTR-DAG: __objc_methname

target triple = "x86_64-apple-darwin"
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128-Fn32"

@.str = private unnamed_addr constant [10 x i8] c"my string\00", align 1
@.str1 = private unnamed_addr constant [16 x i8] c"my other string\00", section "__TEXT,__new_sec,cstring_literals", align 1
@OBJC_CLASS_NAME_ = private unnamed_addr constant [4 x i8] c"foo\00", section "__TEXT,__objc_classname,cstring_literals", align 1
@OBJC_METH_VAR_NAME_ = private unnamed_addr constant [4 x i8] c"bar\00", section "__TEXT,__objc_methname,cstring_literals", align 1
@OBJC_METH_VAR_TYPE_ = private unnamed_addr constant [4 x i8] c"goo\00", section "__TEXT,__objc_methtype,cstring_literals", align 1

@llvm.compiler.used = appending global [5 x ptr] [
ptr @.str,
ptr @.str1,
ptr @OBJC_METH_VAR_NAME_,
ptr @OBJC_CLASS_NAME_,
ptr @OBJC_METH_VAR_TYPE_
]