forked from OSchip/llvm-project
COFF: Implement /merge option.
/merge:.foo=.bar makes the linker to merge section .foo with section .bar. llvm-svn: 241396
This commit is contained in:
parent
f73f8919ed
commit
6600eb18cd
|
@ -54,6 +54,7 @@ struct Configuration {
|
|||
bool DoGC = true;
|
||||
bool Relocatable = true;
|
||||
bool Force = false;
|
||||
bool Debug = false;
|
||||
|
||||
// Symbols in this set are considered as live by the garbage collector.
|
||||
std::set<Undefined *> GCRoot;
|
||||
|
@ -70,6 +71,9 @@ struct Configuration {
|
|||
// Used for /opt:icf
|
||||
bool ICF = false;
|
||||
|
||||
// Used for /merge:from=to (e.g. /merge:.rdata=.text)
|
||||
std::map<StringRef, StringRef> Merge;
|
||||
|
||||
// Options for manifest files.
|
||||
ManifestKind Manifest = SideBySide;
|
||||
int ManifestID = 1;
|
||||
|
|
|
@ -121,7 +121,8 @@ LinkerDriver::parseDirectives(StringRef S) {
|
|||
addUndefined(Arg->getValue());
|
||||
break;
|
||||
case OPT_merge:
|
||||
// Ignore /merge for now.
|
||||
if (auto EC = parseMerge(Arg->getValue()))
|
||||
return EC;
|
||||
break;
|
||||
case OPT_nodefaultlib:
|
||||
Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()));
|
||||
|
@ -290,6 +291,10 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
|
|||
if (auto *Arg = Args.getLastArg(OPT_entry))
|
||||
Config->Entry = addUndefined(Arg->getValue());
|
||||
|
||||
// Handle /debug
|
||||
if (Args.hasArg(OPT_debug))
|
||||
Config->Debug = true;
|
||||
|
||||
// Handle /noentry
|
||||
if (Args.hasArg(OPT_noentry)) {
|
||||
if (!Args.hasArg(OPT_dll)) {
|
||||
|
@ -442,6 +447,11 @@ bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Handle /merge
|
||||
for (auto *Arg : Args.filtered(OPT_merge))
|
||||
if (parseMerge(Arg->getValue()))
|
||||
return false;
|
||||
|
||||
// Handle /manifest
|
||||
if (auto *Arg = Args.getLastArg(OPT_manifest_colon)) {
|
||||
if (auto EC = parseManifest(Arg->getValue())) {
|
||||
|
|
|
@ -132,6 +132,7 @@ std::error_code parseSubsystem(StringRef Arg, WindowsSubsystem *Sys,
|
|||
uint32_t *Major, uint32_t *Minor);
|
||||
|
||||
std::error_code parseAlternateName(StringRef);
|
||||
std::error_code parseMerge(StringRef);
|
||||
|
||||
// Parses a string in the form of "EMBED[,=<integer>]|NO".
|
||||
std::error_code parseManifest(StringRef Arg);
|
||||
|
|
|
@ -172,6 +172,23 @@ std::error_code parseAlternateName(StringRef S) {
|
|||
return std::error_code();
|
||||
}
|
||||
|
||||
// Parse a string of the form of "<from>=<to>".
|
||||
// Results are directly written to Config.
|
||||
std::error_code parseMerge(StringRef S) {
|
||||
StringRef From, To;
|
||||
std::tie(From, To) = S.split('=');
|
||||
if (From.empty() || To.empty()) {
|
||||
llvm::errs() << "/merge: invalid argument: " << S << "\n";
|
||||
return make_error_code(LLDError::InvalidOption);
|
||||
}
|
||||
auto Pair = Config->Merge.insert(std::make_pair(From, To));
|
||||
bool Inserted = Pair.second;
|
||||
if (!Inserted)
|
||||
llvm::errs() << "warning: " << S << ": already merged into "
|
||||
<< Pair.first->second << "\n";
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
// Parses a string in the form of "EMBED[,=<integer>]|NO".
|
||||
// Results are directly written to Config.
|
||||
std::error_code parseManifest(StringRef Arg) {
|
||||
|
|
|
@ -158,6 +158,16 @@ void Writer::dedupCOMDATs() {
|
|||
doICF(Symtab->getChunks());
|
||||
}
|
||||
|
||||
static StringRef getOutputSection(StringRef Name) {
|
||||
StringRef S = Name.split('$').first;
|
||||
if (Config->Debug)
|
||||
return S;
|
||||
auto It = Config->Merge.find(S);
|
||||
if (It == Config->Merge.end())
|
||||
return S;
|
||||
return It->second;
|
||||
}
|
||||
|
||||
// Create output section objects and add them to OutputSections.
|
||||
void Writer::createSections() {
|
||||
// First, bin chunks by name.
|
||||
|
@ -178,18 +188,16 @@ void Writer::createSections() {
|
|||
// '$' and all following characters in input section names are
|
||||
// discarded when determining output section. So, .text$foo
|
||||
// contributes to .text, for example. See PE/COFF spec 3.2.
|
||||
StringRef Name = Map.begin()->first.split('$').first;
|
||||
auto Sec = new (CAlloc.Allocate()) OutputSection(Name, 0);
|
||||
OutputSections.push_back(Sec);
|
||||
for (auto &P : Map) {
|
||||
StringRef SectionName = P.first;
|
||||
StringRef Base = SectionName.split('$').first;
|
||||
if (Base != Sec->getName()) {
|
||||
std::map<StringRef, OutputSection *> Sections;
|
||||
for (auto Pair : Map) {
|
||||
StringRef Name = getOutputSection(Pair.first);
|
||||
OutputSection *&Sec = Sections[Name];
|
||||
if (!Sec) {
|
||||
size_t SectIdx = OutputSections.size();
|
||||
Sec = new (CAlloc.Allocate()) OutputSection(Base, SectIdx);
|
||||
Sec = new (CAlloc.Allocate()) OutputSection(Name, SectIdx);
|
||||
OutputSections.push_back(Sec);
|
||||
}
|
||||
std::vector<Chunk *> &Chunks = P.second;
|
||||
std::vector<Chunk *> &Chunks = Pair.second;
|
||||
for (Chunk *C : Chunks) {
|
||||
Sec->addChunk(C);
|
||||
Sec->addPermissions(C->getPermissions());
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
# RUN: yaml2obj < %s > %t.obj
|
||||
# RUN: lld -flavor link2 /out:%t.exe /entry:main /subsystem:console /force \
|
||||
# RUN: /merge:.foo=.abc /merge:.bar=.def %t.obj
|
||||
# RUN: llvm-readobj -sections %t.exe | FileCheck %s
|
||||
|
||||
# CHECK: Name: .def
|
||||
# CHECK: Name: .abc
|
||||
|
||||
---
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
||||
Characteristics: []
|
||||
sections:
|
||||
- Name: .foo
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
|
||||
Alignment: 4
|
||||
SectionData: 000000000000
|
||||
- Name: .bar
|
||||
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
|
||||
Alignment: 4
|
||||
SectionData: 000000000000
|
||||
symbols:
|
||||
- Name: .foo
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 6
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 0
|
||||
- Name: .bar
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 6
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 0
|
||||
- Name: main
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
...
|
Loading…
Reference in New Issue