Skip to content

Commit 6f9dd84

Browse files
committed
[lld-macho] Implement options -rename_section -rename_segment
Implement command-line options to rename output sections & segments. Differential Revision: https://reviews.llvm.org/D97600
1 parent 415acb2 commit 6f9dd84

File tree

5 files changed

+100
-7
lines changed

5 files changed

+100
-7
lines changed

lld/MachO/Config.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ namespace macho {
2424
class Symbol;
2525
struct SymbolPriorityEntry;
2626

27+
using NamePair = std::pair<llvm::StringRef, llvm::StringRef>;
28+
using SectionRenameMap = llvm::DenseMap<NamePair, NamePair>;
29+
using SegmentRenameMap = llvm::DenseMap<llvm::StringRef, llvm::StringRef>;
30+
2731
struct PlatformInfo {
2832
llvm::MachO::PlatformKind kind;
2933
llvm::VersionTuple minimum;
@@ -76,6 +80,8 @@ struct Configuration {
7680
std::vector<llvm::StringRef> runtimePaths;
7781
std::vector<Symbol *> explicitUndefineds;
7882
llvm::DenseMap<llvm::StringRef, SymbolPriorityEntry> priorities;
83+
SectionRenameMap sectionRenameMap;
84+
SegmentRenameMap segmentRenameMap;
7985
};
8086

8187
// The symbol with the highest priority should be ordered first in the output

lld/MachO/Driver.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,24 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
815815
parseDylibVersion(args, OPT_compatibility_version);
816816
config->dylibCurrentVersion = parseDylibVersion(args, OPT_current_version);
817817

818+
// Reject every special character except '.' and '$'
819+
// TODO(gkm): verify that this is the proper set of invalid chars
820+
StringRef invalidNameChars("!\"#%&'()*+,-/:;<=>?@[\\]^`{|}~");
821+
auto validName = [invalidNameChars](StringRef s) {
822+
if (s.find_first_of(invalidNameChars) != StringRef::npos)
823+
error("invalid name for segment or section: " + s);
824+
return s;
825+
};
826+
for (opt::Arg *arg : args.filtered(OPT_rename_section)) {
827+
config->sectionRenameMap[{validName(arg->getValue(0)),
828+
validName(arg->getValue(1))}] = {
829+
validName(arg->getValue(2)), validName(arg->getValue(3))};
830+
}
831+
for (opt::Arg *arg : args.filtered(OPT_rename_segment)) {
832+
config->segmentRenameMap[validName(arg->getValue(0))] =
833+
validName(arg->getValue(1));
834+
}
835+
818836
config->saveTemps = args.hasArg(OPT_save_temps);
819837

820838
if (args.hasArg(OPT_v)) {

lld/MachO/Options.td

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -629,12 +629,10 @@ def move_to_ro_segment : MultiArg<["-"], "move_to_ro_segment", 2>,
629629
def rename_section : MultiArg<["-"], "rename_section", 4>,
630630
MetaVarName<"<from_segment> <from_section> <to_segment> <to_section>">,
631631
HelpText<"Rename <from_segment>/<from_section> as <to_segment>/<to_section>">,
632-
Flags<[HelpHidden]>,
633632
Group<grp_rare>;
634633
def rename_segment : MultiArg<["-"], "rename_segment", 2>,
635634
MetaVarName<"<from_segment> <to_segment>">,
636635
HelpText<"Rename <from_segment> as <to_segment>">,
637-
Flags<[HelpHidden]>,
638636
Group<grp_rare>;
639637
def trace_symbol_layout : Flag<["-"], "trace_symbol_layout">,
640638
HelpText<"Show where and why symbols move, as specified by -move_to_ro_segment, -move_to_rw_segment, -rename_section, and -rename_segment">,

lld/MachO/Writer.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,16 @@ static void sortSegmentsAndSections() {
704704
}
705705
}
706706

707+
static NamePair maybeRenameSection(NamePair key) {
708+
auto newNames = config->sectionRenameMap.find(key);
709+
if (newNames != config->sectionRenameMap.end())
710+
return newNames->second;
711+
auto newName = config->segmentRenameMap.find(key.first);
712+
if (newName != config->segmentRenameMap.end())
713+
return std::make_pair(newName->second, key.second);
714+
return key;
715+
}
716+
707717
void Writer::createOutputSections() {
708718
// First, create hidden sections
709719
stringTableSection = make<StringTableSection>();
@@ -726,13 +736,12 @@ void Writer::createOutputSections() {
726736
}
727737

728738
// Then merge input sections into output sections.
729-
MapVector<std::pair<StringRef, StringRef>, MergedOutputSection *>
730-
mergedOutputSections;
739+
MapVector<NamePair, MergedOutputSection *> mergedOutputSections;
731740
for (InputSection *isec : inputSections) {
732-
MergedOutputSection *&osec =
733-
mergedOutputSections[{isec->segname, isec->name}];
741+
NamePair names = maybeRenameSection({isec->segname, isec->name});
742+
MergedOutputSection *&osec = mergedOutputSections[names];
734743
if (osec == nullptr)
735-
osec = make<MergedOutputSection>(isec->name);
744+
osec = make<MergedOutputSection>(names.second);
736745
osec->mergeInput(isec);
737746
}
738747

lld/test/MachO/rename.s

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# REQUIRES: x86
2+
# RUN: rm -fr %t
3+
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
4+
# RUN: %lld -o %t %t.o
5+
6+
## Check option format
7+
# RUN: not %lld \
8+
# RUN: -rename_section B@GUS_SEG b@gus_sect S/ASHY_SEG st*rry_sect \
9+
# RUN: -rename_section __FROM_SECT __from_sect __TO_SECT \
10+
# RUN: -o /dev/null %t.o 2>&1 | FileCheck %s --check-prefix=BAD1
11+
12+
# BAD1-DAG: error: invalid name for segment or section: B@GUS_SEG
13+
# BAD1-DAG: error: invalid name for segment or section: b@gus_sect
14+
# BAD1-DAG: error: invalid name for segment or section: S/ASHY_SEG
15+
# BAD1-DAG: error: invalid name for segment or section: st*rry_sect
16+
# BAD1-DAG: error: invalid name for segment or section: -o
17+
# BAD1-DAG: error: /dev/null: unhandled file type
18+
19+
# RUN: not %lld \
20+
# RUN: -rename_segment H#SHY_SEG PL+SSY_SEG \
21+
# RUN: -rename_segment __FROM_SEG \
22+
# RUN: -o /dev/null %t.o 2>&1 | FileCheck %s --check-prefix=BAD2
23+
24+
# BAD2-DAG: error: invalid name for segment or section: H#SHY_SEG
25+
# BAD2-DAG: error: invalid name for segment or section: PL+SSY_SEG
26+
# BAD2-DAG: error: invalid name for segment or section: -o
27+
# BAD2-DAG: error: /dev/null: unhandled file type
28+
29+
## Check that section and segment renames happen
30+
# RUN: %lld \
31+
# RUN: -rename_section __FROM_SECT __from_sect __TO_SECT __to_sect \
32+
# RUN: -rename_segment __FROM_SEG __TO_SEG \
33+
# RUN: -o %t %t.o
34+
# RUN: llvm-objdump --macho --all-headers %t | FileCheck %s
35+
36+
# CHECK: {{^}}Section{{$}}
37+
# CHECK-NEXT: sectname __text
38+
# CHECK-NEXT: segname __TEXT
39+
# CHECK: {{^}}Section{{$}}
40+
# CHECK-NOT: sectname __from_sect
41+
# CHECK-NEXT: sectname __to_sect
42+
# CHECK-NOT: segname __FROM_SECT
43+
# CHECK-NEXT: segname __TO_SECT
44+
# CHECK: {{^}}Section{{$}}
45+
# CHECK-NEXT: sectname __from_seg
46+
# CHECK-NOT: segname __FROM_SEG
47+
# CHECK-NEXT: segname __TO_SEG
48+
49+
.section __FROM_SECT,__from_sect
50+
.global _from_sect
51+
_from_sect:
52+
.space 8
53+
54+
.section __FROM_SEG,__from_seg
55+
.global _from_seg
56+
_from_seg:
57+
.space 8
58+
59+
.text
60+
.global _main
61+
_main:
62+
ret

0 commit comments

Comments
 (0)