forked from OSchip/llvm-project
[lld-macho] Implement options -rename_section -rename_segment
Implement command-line options to rename output sections & segments. Differential Revision: https://reviews.llvm.org/D97600
This commit is contained in:
parent
415acb2c59
commit
6f9dd843db
|
@ -24,6 +24,10 @@ namespace macho {
|
|||
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;
|
||||
|
@ -76,6 +80,8 @@ struct Configuration {
|
|||
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
|
||||
|
|
|
@ -815,6 +815,24 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
|
|||
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)) {
|
||||
|
|
|
@ -629,12 +629,10 @@ def move_to_ro_segment : MultiArg<["-"], "move_to_ro_segment", 2>,
|
|||
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">,
|
||||
|
|
|
@ -704,6 +704,16 @@ static void sortSegmentsAndSections() {
|
|||
}
|
||||
}
|
||||
|
||||
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>();
|
||||
|
@ -726,13 +736,12 @@ void Writer::createOutputSections() {
|
|||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
# 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
|
Loading…
Reference in New Issue