Skip to content

Commit 81862f8

Browse files
committedMay 2, 2019
lld-link: Add /force:multipleres extension to make dupe resource diag non-fatal
As a side benefit, lld-link now reports more than one duplicate resource entry before exiting with an error even if the new flag is not passed. llvm-svn: 359829
1 parent 6e9cfee commit 81862f8

File tree

10 files changed

+52
-10
lines changed

10 files changed

+52
-10
lines changed
 

Diff for: ‎lld/COFF/Config.h

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ struct Configuration {
9797
bool TailMerge;
9898
bool Relocatable = true;
9999
bool ForceMultiple = false;
100+
bool ForceMultipleRes = false;
100101
bool ForceUnresolved = false;
101102
bool Debug = false;
102103
bool DebugDwarf = false;

Diff for: ‎lld/COFF/Driver.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1096,6 +1096,10 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
10961096
if (Args.hasArg(OPT_force, OPT_force_multiple))
10971097
Config->ForceMultiple = true;
10981098

1099+
// Handle /force or /force:multipleres
1100+
if (Args.hasArg(OPT_force, OPT_force_multipleres))
1101+
Config->ForceMultipleRes = true;
1102+
10991103
// Handle /debug
11001104
DebugKind Debug = parseDebugKind(Args);
11011105
if (Debug == DebugKind::Full || Debug == DebugKind::Dwarf ||

Diff for: ‎lld/COFF/DriverUtils.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -745,8 +745,16 @@ MemoryBufferRef convertResToCOFF(ArrayRef<MemoryBufferRef> MBs) {
745745
object::WindowsResource *RF = dyn_cast<object::WindowsResource>(Bin.get());
746746
if (!RF)
747747
fatal("cannot compile non-resource file as resource");
748-
if (auto EC = Parser.parse(RF))
748+
749+
std::vector<std::string> Duplicates;
750+
if (auto EC = Parser.parse(RF, Duplicates))
749751
fatal(toString(std::move(EC)));
752+
753+
for (const auto &DupeDiag : Duplicates)
754+
if (Config->ForceMultipleRes)
755+
warn(DupeDiag);
756+
else
757+
error(DupeDiag);
750758
}
751759

752760
Expected<std::unique_ptr<MemoryBuffer>> E =

Diff for: ‎lld/COFF/Options.td

+2
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ def force_unresolved : F<"force:unresolved">,
118118
HelpText<"Allow undefined symbols when creating executables">;
119119
def force_multiple : F<"force:multiple">,
120120
HelpText<"Allow multiply defined symbols when creating executables">;
121+
def force_multipleres : F<"force:multipleres">,
122+
HelpText<"Allow multiply defined resources when creating executables">;
121123
defm WX : B<"WX", "Treat warnings as errors", "Don't treat warnings as errors">;
122124

123125
defm allowbind : B<"allowbind", "Enable DLL binding (default)",

Diff for: ‎lld/docs/ReleaseNotes.rst

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ COFF Improvements
3434

3535
* lld-link now correctly reports duplicate symbol errors when several res
3636
input files define resources with the same type, name, and language.
37+
This can be demoted to a warning using ``/force:multipleres``.
3738

3839
* Having more than two ``/natvis:`` now works correctly; it used to not
3940
work for larger binaries before.

Diff for: ‎lld/test/COFF/Inputs/id.res

100 Bytes
Binary file not shown.

Diff for: ‎lld/test/COFF/force-multipleres.test

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Check that lld-link rejects duplicate resources, unless
2+
// /force or /force:multipleres is passed.
3+
// The input was generated with the following command, using the original Windows
4+
// rc.exe:
5+
// > rc /fo id.res /nologo id.rc
6+
// > rc /fo name.res /nologo name.rc
7+
8+
RUN: rm -rf %t.dir
9+
RUN: mkdir %t.dir
10+
RUN: cp %S/Inputs/id.res %t.dir/id1.res
11+
RUN: cp %S/Inputs/id.res %t.dir/id2.res
12+
13+
RUN: not lld-link /machine:x64 /nodefaultlib /noentry /dll %t.dir/id1.res %t.dir/id2.res 2>&1 | \
14+
RUN: FileCheck -check-prefix=ERR %s
15+
ERR: error: duplicate resource: type STRINGTABLE (ID 6)/name ID 3/language 1033, in {{.*}}id1.res and in {{.*}}id2.res
16+
17+
RUN: lld-link /force /machine:x64 /nodefaultlib /noentry /dll %t.dir/id1.res %t.dir/id2.res 2>&1 | \
18+
RUN: FileCheck -check-prefix=WARN %s
19+
RUN: lld-link /force:multipleres /machine:x64 /nodefaultlib /noentry /dll %t.dir/id1.res %t.dir/id2.res 2>&1 | \
20+
RUN: FileCheck -check-prefix=WARN %s
21+
WARN: warning: duplicate resource: type STRINGTABLE (ID 6)/name ID 3/language 1033, in {{.*}}id1.res and in {{.*}}id2.res

Diff for: ‎llvm/include/llvm/Object/WindowsResource.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ class WindowsResourceParser {
152152
public:
153153
class TreeNode;
154154
WindowsResourceParser();
155-
Error parse(WindowsResource *WR);
155+
Error parse(WindowsResource *WR, std::vector<std::string> &Duplicates);
156156
void printTree(raw_ostream &OS) const;
157157
const TreeNode &getTree() const { return Root; }
158158
const ArrayRef<std::vector<uint8_t>> getData() const { return Data; }

Diff for: ‎llvm/lib/Object/WindowsResource.cpp

+9-7
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,8 @@ static bool convertUTF16LEToUTF8String(ArrayRef<UTF16> Src, std::string &Out) {
168168
return convertUTF16ToUTF8String(makeArrayRef(EndianCorrectedSrc), Out);
169169
}
170170

171-
static Error makeDuplicateResourceError(const ResourceEntryRef &Entry,
172-
StringRef File1, StringRef File2) {
171+
static std::string makeDuplicateResourceError(
172+
const ResourceEntryRef &Entry, StringRef File1, StringRef File2) {
173173
std::string Ret;
174174
raw_string_ostream OS(Ret);
175175

@@ -197,10 +197,11 @@ static Error makeDuplicateResourceError(const ResourceEntryRef &Entry,
197197
OS << "/language " << Entry.getLanguage() << ", in " << File1 << " and in "
198198
<< File2;
199199

200-
return make_error<GenericBinaryError>(OS.str(), object_error::parse_failed);
200+
return OS.str();
201201
}
202202

203-
Error WindowsResourceParser::parse(WindowsResource *WR) {
203+
Error WindowsResourceParser::parse(WindowsResource *WR,
204+
std::vector<std::string> &Duplicates) {
204205
auto EntryOrErr = WR->getHeadEntry();
205206
if (!EntryOrErr) {
206207
auto E = EntryOrErr.takeError();
@@ -229,9 +230,10 @@ Error WindowsResourceParser::parse(WindowsResource *WR) {
229230
bool IsNewNode = Root.addEntry(Entry, InputFilenames.size(),
230231
IsNewTypeString, IsNewNameString, Node);
231232
InputFilenames.push_back(WR->getFileName());
232-
if (!IsNewNode)
233-
return makeDuplicateResourceError(Entry, InputFilenames[Node->Origin],
234-
WR->getFileName());
233+
if (!IsNewNode) {
234+
Duplicates.push_back(makeDuplicateResourceError(
235+
Entry, InputFilenames[Node->Origin], WR->getFileName()));
236+
}
235237

236238
if (IsNewTypeString)
237239
StringTable.push_back(Entry.getTypeString());

Diff for: ‎llvm/tools/llvm-cvtres/llvm-cvtres.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,10 @@ int main(int Argc, const char **Argv) {
183183
outs() << "Number of resources: " << EntryNumber << "\n";
184184
}
185185

186-
error(Parser.parse(RF));
186+
std::vector<std::string> Duplicates;
187+
error(Parser.parse(RF, Duplicates));
188+
for (const auto& DupeDiag : Duplicates)
189+
reportError(DupeDiag);
187190
}
188191

189192
if (Verbose) {

0 commit comments

Comments
 (0)
Please sign in to comment.