[LLD][COFF] Adds /includeglob flag (#109721)

This implements parity with the `--undefined-glob` flag on
[ELF](https://reviews.llvm.org/D63244), but for COFF.
This commit is contained in:
Miguel A. Arroyo 2024-09-24 13:57:01 -07:00 committed by GitHub
parent 538dbb97a2
commit b9bd8ca24e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 120 additions and 2 deletions

View File

@ -37,6 +37,7 @@
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GlobPattern.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Parallel.h"
@ -704,6 +705,24 @@ Symbol *LinkerDriver::addUndefined(StringRef name) {
return b;
}
void LinkerDriver::addUndefinedGlob(StringRef arg) {
Expected<GlobPattern> pat = GlobPattern::create(arg);
if (!pat) {
error("/includeglob: " + toString(pat.takeError()));
return;
}
SmallVector<Symbol *, 0> syms;
ctx.symtab.forEachSymbol([&syms, &pat](Symbol *sym) {
if (pat->match(sym->getName())) {
syms.push_back(sym);
}
});
for (Symbol *sym : syms)
addUndefined(sym->getName());
}
StringRef LinkerDriver::mangleMaybe(Symbol *s) {
// If the plain symbol name has already been resolved, do nothing.
Undefined *unmangled = dyn_cast<Undefined>(s);
@ -2524,6 +2543,10 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
} while (run());
}
// Handle /includeglob
for (StringRef pat : args::getStrings(args, OPT_incl_glob))
addUndefinedGlob(pat);
// Create wrapped symbols for -wrap option.
std::vector<WrappedSymbol> wrapped = addWrappedSymbols(ctx, args);
// Load more object files that might be needed for wrapped symbols.

View File

@ -172,6 +172,8 @@ private:
Symbol *addUndefined(StringRef sym);
void addUndefinedGlob(StringRef arg);
StringRef mangleMaybe(Symbol *s);
// Windows specific -- "main" is not the only main function in Windows.

View File

@ -310,6 +310,9 @@ defm build_id: B<
"Generate build ID (always on when generating PDB)",
"Do not Generate build ID">;
def incl_glob : Joined<["/", "-", "/?", "-?"], "includeglob:">,
HelpText<"Force symbol to be added to symbol table as undefined one using a glob pattern">;
// Flags for debugging
def lldmap : F<"lldmap">;
def lldmap_file : P_priv<"lldmap">;

View File

@ -41,6 +41,7 @@ Breaking changes
COFF Improvements
-----------------
* ``/includeglob`` has been implemented to match the behavior of ``--undefined-glob`` available for ELF.
MinGW Improvements
------------------

View File

@ -0,0 +1,29 @@
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: []
sections:
- Name: .text
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
Alignment: 4
SectionData: B800000000506800000000680000000050E80000000050E800000000
symbols:
- Name: .text
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 28
NumberOfRelocations: 4
NumberOfLinenumbers: 0
CheckSum: 0
Number: 0
- Name: baz
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
...

View File

@ -9,10 +9,18 @@
# RUN: echo dummy >> %t.log
# RUN: FileCheck -check-prefix=CHECK2 %s < %t.log
# RUN: lld-link /out:%t.exe /entry:main %t.obj /verbose /includeglob:"glob_*" >& %t.log
# RUN: echo dummy >> %t.log
# RUN: FileCheck -check-prefix=CHECK3 %s < %t.log
# CHECK1: Discarded unused
# CHECK1: Discarded glob_match1
# CHECK1: Discarded glob_match2
# CHECK1-NOT: Discarded used
# CHECK2-NOT: Discarded unused
# CHECK2-NOT: Discarded used
# CHECK3-NOT: Discarded glob_match1
# CHECK3-NOT: Discarded glob_match2
--- !COFF
header:
@ -31,6 +39,14 @@ sections:
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
Alignment: 4
SectionData: B82A000000C3
- Name: '.text$mn'
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
Alignment: 4
SectionData: B82A000000C3
- Name: '.text$mn'
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
Alignment: 4
SectionData: B82A000000C3
- Name: .drectve
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
Alignment: 1
@ -75,6 +91,32 @@ symbols:
CheckSum: 0
Number: 0
Selection: IMAGE_COMDAT_SELECT_ANY
- Name: '.text$mn'
Value: 0
SectionNumber: 4
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
Selection: IMAGE_COMDAT_SELECT_ANY
- Name: '.text$mn'
Value: 0
SectionNumber: 5
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
Selection: IMAGE_COMDAT_SELECT_ANY
- Name: main
Value: 0
SectionNumber: 1
@ -93,4 +135,16 @@ symbols:
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: glob_match1
Value: 0
SectionNumber: 4
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: glob_match2
Value: 0
SectionNumber: 5
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
...

View File

@ -1,14 +1,20 @@
# RUN: yaml2obj %p/Inputs/include1a.yaml -o %t1.obj
# RUN: yaml2obj %p/Inputs/include1b.yaml -o %t2.obj
# RUN: yaml2obj %p/Inputs/include1c.yaml -o %t3.obj
# RUN: rm -f %t2.lib %t3.lib
# RUN: yaml2obj %p/Inputs/include1d.yaml -o %t4.obj
# RUN: rm -f %t2.lib %t3.lib %t4.lib
# RUN: llvm-ar cru %t2.lib %t2.obj
# RUN: llvm-ar cru %t3.lib %t3.obj
# RUN: lld-link /out:%t.exe /entry:main %t1.obj %t2.lib %t3.lib /verbose >& %t.log
# RUN: llvm-ar cru %t4.lib %t4.obj
# RUN: lld-link /out:%t.exe /entry:main %t1.obj %t2.lib %t3.lib %t4.lib /verbose >& %t.log
# RUN: FileCheck %s < %t.log
# RUN: lld-link /out:%t.exe /entry:main %t1.obj %t2.lib %t3.lib %t4.lib /includeglob:baz /verbose >& %t.glob.log
# RUN: FileCheck -check-prefix=GLOB %s < %t.glob.log
CHECK: include2.test.tmp1.obj
CHECK: include2.test.tmp2.lib
CHECK: include2.test.tmp2.lib(include2.test.tmp2.obj) for foo
CHECK: include2.test.tmp3.lib
CHECK: include2.test.tmp3.lib(include2.test.tmp3.obj) for bar
CHECK-NOT: include2.test.tmp4.lib(include2.test.tmp4.obj) for baz
GLOB: include2.test.tmp4.lib(include2.test.tmp4.obj) for baz