Implement command-line options to rename output sections & segments.
Differential Revision: https://reviews.llvm.org/D97600
class Symbol;
struct SymbolPriorityEntry;
+using NamePair = std::pair<llvm::StringRef, llvm::StringRef>;
+using SectionRenameMap = llvm::DenseMap<NamePair, NamePair>;
+using SegmentRenameMap = llvm::DenseMap<llvm::StringRef, llvm::StringRef>;
+
struct PlatformInfo {
llvm::MachO::PlatformKind kind;
llvm::VersionTuple minimum;
std::vector<llvm::StringRef> runtimePaths;
std::vector<Symbol *> explicitUndefineds;
llvm::DenseMap<llvm::StringRef, SymbolPriorityEntry> priorities;
+ SectionRenameMap sectionRenameMap;
+ SegmentRenameMap segmentRenameMap;
};
// The symbol with the highest priority should be ordered first in the output
parseDylibVersion(args, OPT_compatibility_version);
config->dylibCurrentVersion = parseDylibVersion(args, OPT_current_version);
+ // Reject every special character except '.' and '$'
+ // TODO(gkm): verify that this is the proper set of invalid chars
+ StringRef invalidNameChars("!\"#%&'()*+,-/:;<=>?@[\\]^`{|}~");
+ auto validName = [invalidNameChars](StringRef s) {
+ if (s.find_first_of(invalidNameChars) != StringRef::npos)
+ error("invalid name for segment or section: " + s);
+ return s;
+ };
+ for (opt::Arg *arg : args.filtered(OPT_rename_section)) {
+ config->sectionRenameMap[{validName(arg->getValue(0)),
+ validName(arg->getValue(1))}] = {
+ validName(arg->getValue(2)), validName(arg->getValue(3))};
+ }
+ for (opt::Arg *arg : args.filtered(OPT_rename_segment)) {
+ config->segmentRenameMap[validName(arg->getValue(0))] =
+ validName(arg->getValue(1));
+ }
+
config->saveTemps = args.hasArg(OPT_save_temps);
if (args.hasArg(OPT_v)) {
def rename_section : MultiArg<["-"], "rename_section", 4>,
MetaVarName<"<from_segment> <from_section> <to_segment> <to_section>">,
HelpText<"Rename <from_segment>/<from_section> as <to_segment>/<to_section>">,
- Flags<[HelpHidden]>,
Group<grp_rare>;
def rename_segment : MultiArg<["-"], "rename_segment", 2>,
MetaVarName<"<from_segment> <to_segment>">,
HelpText<"Rename <from_segment> as <to_segment>">,
- Flags<[HelpHidden]>,
Group<grp_rare>;
def trace_symbol_layout : Flag<["-"], "trace_symbol_layout">,
HelpText<"Show where and why symbols move, as specified by -move_to_ro_segment, -move_to_rw_segment, -rename_section, and -rename_segment">,
}
}
+static NamePair maybeRenameSection(NamePair key) {
+ auto newNames = config->sectionRenameMap.find(key);
+ if (newNames != config->sectionRenameMap.end())
+ return newNames->second;
+ auto newName = config->segmentRenameMap.find(key.first);
+ if (newName != config->segmentRenameMap.end())
+ return std::make_pair(newName->second, key.second);
+ return key;
+}
+
void Writer::createOutputSections() {
// First, create hidden sections
stringTableSection = make<StringTableSection>();
}
// Then merge input sections into output sections.
- MapVector<std::pair<StringRef, StringRef>, MergedOutputSection *>
- mergedOutputSections;
+ MapVector<NamePair, MergedOutputSection *> mergedOutputSections;
for (InputSection *isec : inputSections) {
- MergedOutputSection *&osec =
- mergedOutputSections[{isec->segname, isec->name}];
+ NamePair names = maybeRenameSection({isec->segname, isec->name});
+ MergedOutputSection *&osec = mergedOutputSections[names];
if (osec == nullptr)
- osec = make<MergedOutputSection>(isec->name);
+ osec = make<MergedOutputSection>(names.second);
osec->mergeInput(isec);
}
--- /dev/null
+# REQUIRES: x86
+# RUN: rm -fr %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
+# RUN: %lld -o %t %t.o
+
+## Check option format
+# RUN: not %lld \
+# RUN: -rename_section B@GUS_SEG b@gus_sect S/ASHY_SEG st*rry_sect \
+# RUN: -rename_section __FROM_SECT __from_sect __TO_SECT \
+# RUN: -o /dev/null %t.o 2>&1 | FileCheck %s --check-prefix=BAD1
+
+# BAD1-DAG: error: invalid name for segment or section: B@GUS_SEG
+# BAD1-DAG: error: invalid name for segment or section: b@gus_sect
+# BAD1-DAG: error: invalid name for segment or section: S/ASHY_SEG
+# BAD1-DAG: error: invalid name for segment or section: st*rry_sect
+# BAD1-DAG: error: invalid name for segment or section: -o
+# BAD1-DAG: error: /dev/null: unhandled file type
+
+# RUN: not %lld \
+# RUN: -rename_segment H#SHY_SEG PL+SSY_SEG \
+# RUN: -rename_segment __FROM_SEG \
+# RUN: -o /dev/null %t.o 2>&1 | FileCheck %s --check-prefix=BAD2
+
+# BAD2-DAG: error: invalid name for segment or section: H#SHY_SEG
+# BAD2-DAG: error: invalid name for segment or section: PL+SSY_SEG
+# BAD2-DAG: error: invalid name for segment or section: -o
+# BAD2-DAG: error: /dev/null: unhandled file type
+
+## Check that section and segment renames happen
+# RUN: %lld \
+# RUN: -rename_section __FROM_SECT __from_sect __TO_SECT __to_sect \
+# RUN: -rename_segment __FROM_SEG __TO_SEG \
+# RUN: -o %t %t.o
+# RUN: llvm-objdump --macho --all-headers %t | FileCheck %s
+
+# CHECK: {{^}}Section{{$}}
+# CHECK-NEXT: sectname __text
+# CHECK-NEXT: segname __TEXT
+# CHECK: {{^}}Section{{$}}
+# CHECK-NOT: sectname __from_sect
+# CHECK-NEXT: sectname __to_sect
+# CHECK-NOT: segname __FROM_SECT
+# CHECK-NEXT: segname __TO_SECT
+# CHECK: {{^}}Section{{$}}
+# CHECK-NEXT: sectname __from_seg
+# CHECK-NOT: segname __FROM_SEG
+# CHECK-NEXT: segname __TO_SEG
+
+.section __FROM_SECT,__from_sect
+.global _from_sect
+_from_sect:
+ .space 8
+
+.section __FROM_SEG,__from_seg
+.global _from_seg
+_from_seg:
+ .space 8
+
+.text
+.global _main
+_main:
+ ret