-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[lld][COFF] Remove duplicate strtab entries #141197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
4204ca0
a4a6c91
8e034a8
47e5b2c
333a908
1f428ce
bd00aba
ff8fce2
ac31e68
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # RUN: llvm-mc -triple=x86_64-windows-msvc %s -filetype=obj -o %t.obj | ||
| # RUN: lld-link -out:%t.exe -entry:main %t.obj -debug:dwarf | ||
| # RUN: llvm-readobj --string-table %t.exe | FileCheck %s | ||
|
|
||
| # CHECK: StringTable { | ||
| # CHECK-NEXT: Length: 87 | ||
| # CHECK-NEXT: [ 4] .debug_abbrev | ||
| # CHECK-NEXT: [ 12] .debug_line | ||
| # CHECK-NEXT: [ 1e] long_name_symbolz | ||
| # CHECK-NEXT: [ 30] .debug_abbrez | ||
| # CHECK-NEXT: [ 3e] __impl_long_name_symbolA | ||
| # CHECK-NEXT: } | ||
|
|
||
|
|
||
| .global main | ||
| .text | ||
| main: | ||
| long_name_symbolz: | ||
| long_name_symbolA: | ||
| __impl_long_name_symbolA: | ||
| name_symbolA: | ||
| .debug_abbrez: | ||
| ret | ||
|
|
||
| .section .debug_abbrev,"dr" | ||
| .byte 0 | ||
|
|
||
| .section .debug_line,"dr" | ||
| .byte 0 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -38,6 +38,8 @@ class StringTableBuilder { | |
| }; | ||
|
|
||
| private: | ||
| // Only non-zero priority will be recorded. | ||
| DenseMap<CachedHashStringRef, uint8_t> StringPriorityMap; | ||
| DenseMap<CachedHashStringRef, size_t> StringIndexMap; | ||
| size_t Size = 0; | ||
| Kind K; | ||
|
|
@@ -51,11 +53,15 @@ class StringTableBuilder { | |
| LLVM_ABI StringTableBuilder(Kind K, Align Alignment = Align(1)); | ||
| LLVM_ABI ~StringTableBuilder(); | ||
|
|
||
| /// Add a string to the builder. Returns the position of S in the | ||
| /// table. The position will be changed if finalize is used. | ||
| /// Can only be used before the table is finalized. | ||
| LLVM_ABI size_t add(CachedHashStringRef S); | ||
| size_t add(StringRef S) { return add(CachedHashStringRef(S)); } | ||
| /// Add a string to the builder. Returns the position of S in the table. The | ||
| /// position will be changed if finalize is used. Can only be used before the | ||
| /// table is finalized. Priority is only useful with reordering. Strings with | ||
| /// same priority will be put together. Strings with higher priority are | ||
HaohaiWen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| /// placed closer to the begin of string table. | ||
| LLVM_ABI size_t add(CachedHashStringRef S, uint8_t Priority = 0); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment should mention what if a string is added with different priorities. (std::max below) |
||
| size_t add(StringRef S, uint8_t Priority = 0) { | ||
| return add(CachedHashStringRef(S), Priority); | ||
| } | ||
|
|
||
| /// Analyze the strings and build the final table. No more strings can | ||
| /// be added after this point. | ||
|
|
@@ -78,6 +84,7 @@ class StringTableBuilder { | |
| bool contains(StringRef S) const { return contains(CachedHashStringRef(S)); } | ||
| bool contains(CachedHashStringRef S) const { return StringIndexMap.count(S); } | ||
|
|
||
| bool empty() const { return StringIndexMap.empty(); } | ||
| size_t getSize() const { return Size; } | ||
| LLVM_ABI void clear(); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -138,13 +138,41 @@ void StringTableBuilder::finalizeInOrder() { | |
| void StringTableBuilder::finalizeStringTable(bool Optimize) { | ||
| Finalized = true; | ||
|
|
||
| if (Optimize) { | ||
| if (Optimize && StringIndexMap.size()) { | ||
| std::vector<StringPair *> Strings; | ||
| Strings.reserve(StringIndexMap.size()); | ||
| for (StringPair &P : StringIndexMap) | ||
| Strings.push_back(&P); | ||
|
|
||
| multikeySort(Strings, 0); | ||
| auto getStringPriority = [this](const CachedHashStringRef Str) -> uint8_t { | ||
| if (StringPriorityMap.contains(Str)) | ||
|
||
| return StringPriorityMap[Str]; | ||
| return 0; | ||
| }; | ||
|
|
||
| size_t RangeBegin = 0; | ||
| MutableArrayRef<StringPair *> StringsRef(Strings); | ||
| if (StringPriorityMap.size()) { | ||
| llvm::sort(Strings, | ||
| [&](const StringPair *LHS, const StringPair *RHS) -> bool { | ||
| return getStringPriority(LHS->first) > | ||
| getStringPriority(RHS->first); | ||
| }); | ||
| // Make sure ArrayRef is valid. Although std::sort implementaion is | ||
| // normally in-place , it is not guaranteed by standard. | ||
| StringsRef = Strings; | ||
|
||
|
|
||
| uint8_t RangePriority = getStringPriority(Strings[0]->first); | ||
| for (size_t I = 1, E = Strings.size(); I != E && RangePriority; ++I) { | ||
| uint8_t Priority = getStringPriority(Strings[I]->first); | ||
| if (Priority != RangePriority) { | ||
| multikeySort(StringsRef.slice(RangeBegin, I - RangeBegin), 0); | ||
| RangePriority = Priority; | ||
| RangeBegin = I; | ||
| } | ||
| } | ||
| } | ||
| multikeySort(StringsRef.slice(RangeBegin), 0); | ||
| initSize(); | ||
|
|
||
| StringRef Previous; | ||
|
|
@@ -199,11 +227,14 @@ size_t StringTableBuilder::getOffset(CachedHashStringRef S) const { | |
| return I->second; | ||
| } | ||
|
|
||
| size_t StringTableBuilder::add(CachedHashStringRef S) { | ||
| size_t StringTableBuilder::add(CachedHashStringRef S, uint8_t Priority) { | ||
| if (K == WinCOFF) | ||
| assert(S.size() > COFF::NameSize && "Short string in COFF string table!"); | ||
|
|
||
| assert(!isFinalized()); | ||
| if (Priority) | ||
| StringPriorityMap[S] = std::max(Priority, StringPriorityMap[S]); | ||
|
|
||
| auto P = StringIndexMap.try_emplace(S); | ||
| if (P.second) { | ||
| size_t Start = alignTo(Size, Alignment); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,7 +121,7 @@ void COFFWriter::layoutSections() { | |
| Expected<size_t> COFFWriter::finalizeStringTable() { | ||
| for (const auto &S : Obj.getSections()) | ||
| if (S.Name.size() > COFF::NameSize) | ||
| StrTabBuilder.add(S.Name); | ||
| StrTabBuilder.add(S.Name, /*Priority=*/UINT8_MAX); | ||
|
||
|
|
||
| for (const auto &S : Obj.getSymbols()) | ||
| if (S.Name.size() > COFF::NameSize) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it work if x86 is not configured?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not: https://lab.llvm.org/buildbot/#/builders/190/builds/21872
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have marked the test as requiring x86 in 757c80d.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I didn't aware of that.