Skip to content

Commit 057bda6

Browse files
committed
[LTO] Fix a crash caused by accessing an empty ValueInfo
ModuleSummaryIndex::exportToDot crashes when linking the Linux kernel under ThinLTO using LLVMgold.so. This is due to the exportToDot function trying to get the GUID of an empty ValueInfo. The root cause related to the fact that we attempt to get the GUID of an aliasee via its OriginalGUID recorded in the aliasee summary, and that is not always possible. Specifically, we cannot do this mapping when the value is internal linkage and there were other internal linkage symbols with the same name. There are 2 fixes for the problem included here. 1) In all cases where we can currently print the dot file from the command line (which is only via save-temps), we have a valid AliaseeGUID in the AliasSummary. Use that when it is available, so that we can get the correct aliasee GUID whenever possible. 2) However, if we were to invoke exportToDot from the debugger right after it is built during the initial analysis step (i.e. the per-module summary), we won't have the AliaseeGUID field populated. In that case, we have a fallback fix that will simply print "@"+GUID when we aren't able to get the GUID from the OriginalGUID. It simply checks if the VI is valid or not before attempting to get the name. Additionally, since getAliaseeGUID will assert that the AliaseeGUID is non-zero, guard the earlier fix rust-lang#1 by a new function hasAliaseeGUID(). Reviewers: pcc, tmroeder Subscribers: evgeny777, mehdi_amini, inglorion, dexonsmith, arphaman, llvm-commits Differential Revision: https://reviews.llvm.org/D53986 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@346055 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent aeef43e commit 057bda6

File tree

4 files changed

+58
-12
lines changed

4 files changed

+58
-12
lines changed

include/llvm/IR/ModuleSummaryIndex.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ class AliasSummary : public GlobalValueSummary {
408408
return const_cast<GlobalValueSummary &>(
409409
static_cast<const AliasSummary *>(this)->getAliasee());
410410
}
411+
bool hasAliaseeGUID() const { return AliaseeGUID != 0; }
411412
const GlobalValue::GUID &getAliaseeGUID() const {
412413
assert(AliaseeGUID && "Unexpected missing aliasee GUID");
413414
return AliaseeGUID;

lib/IR/ModuleSummaryIndex.cpp

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,12 @@ static std::string getSummaryAttributes(GlobalValueSummary* GVS) {
198198
", ffl: " + fflagsToString(FS->fflags());
199199
}
200200

201+
static std::string getNodeVisualName(GlobalValue::GUID Id) {
202+
return std::string("@") + std::to_string(Id);
203+
}
204+
201205
static std::string getNodeVisualName(const ValueInfo &VI) {
202-
return VI.name().empty() ? std::string("@") + std::to_string(VI.getGUID())
203-
: VI.name().str();
206+
return VI.name().empty() ? getNodeVisualName(VI.getGUID()) : VI.name().str();
204207
}
205208

206209
static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS) {
@@ -221,13 +224,19 @@ static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS) {
221224
// specific module associated with it. Typically this is function
222225
// or variable defined in native object or library.
223226
static void defineExternalNode(raw_ostream &OS, const char *Pfx,
224-
const ValueInfo &VI) {
225-
auto StrId = std::to_string(VI.getGUID());
226-
OS << " " << StrId << " [label=\"" << getNodeVisualName(VI)
227-
<< "\"]; // defined externally\n";
227+
const ValueInfo &VI, GlobalValue::GUID Id) {
228+
auto StrId = std::to_string(Id);
229+
OS << " " << StrId << " [label=\"";
230+
231+
if (VI) {
232+
OS << getNodeVisualName(VI);
233+
} else {
234+
OS << getNodeVisualName(Id);
235+
}
236+
OS << "\"]; // defined externally\n";
228237
}
229238

230-
void ModuleSummaryIndex::exportToDot(raw_ostream& OS) const {
239+
void ModuleSummaryIndex::exportToDot(raw_ostream &OS) const {
231240
std::vector<Edge> CrossModuleEdges;
232241
DenseMap<GlobalValue::GUID, std::vector<uint64_t>> NodeMap;
233242
StringMap<GVSummaryMapTy> ModuleToDefinedGVS;
@@ -311,10 +320,17 @@ void ModuleSummaryIndex::exportToDot(raw_ostream& OS) const {
311320
Draw(SummaryIt.first, R.getGUID(), -1);
312321

313322
if (auto *AS = dyn_cast_or_null<AliasSummary>(SummaryIt.second)) {
314-
auto AliaseeOrigId = AS->getAliasee().getOriginalName();
315-
auto AliaseeId = getGUIDFromOriginalID(AliaseeOrigId);
316-
317-
Draw(SummaryIt.first, AliaseeId ? AliaseeId : AliaseeOrigId, -2);
323+
GlobalValue::GUID AliaseeId;
324+
if (AS->hasAliaseeGUID())
325+
AliaseeId = AS->getAliaseeGUID();
326+
else {
327+
auto AliaseeOrigId = AS->getAliasee().getOriginalName();
328+
AliaseeId = getGUIDFromOriginalID(AliaseeOrigId);
329+
if (!AliaseeId)
330+
AliaseeId = AliaseeOrigId;
331+
}
332+
333+
Draw(SummaryIt.first, AliaseeId, -2);
318334
continue;
319335
}
320336

@@ -330,7 +346,7 @@ void ModuleSummaryIndex::exportToDot(raw_ostream& OS) const {
330346
for (auto &E : CrossModuleEdges) {
331347
auto &ModList = NodeMap[E.Dst];
332348
if (ModList.empty()) {
333-
defineExternalNode(OS, " ", getValueInfo(E.Dst));
349+
defineExternalNode(OS, " ", getValueInfo(E.Dst), E.Dst);
334350
// Add fake module to the list to draw an edge to an external node
335351
// in the loop below.
336352
ModList.push_back(-1);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
2+
target triple = "x86_64-unknown-linux-gnu"
3+
4+
define internal i32 @f(i8*) unnamed_addr {
5+
ret i32 42
6+
}
7+
8+
@a2 = weak alias i32 (i8*), i32 (i8*)* @f

test/ThinLTO/X86/alias_internal.ll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; Test to make sure dot dumper can correctly handle aliases to multiple
2+
; different internal aliasees with the same name.
3+
4+
; RUN: opt -module-summary %s -o %t1.bc
5+
; RUN: opt -module-summary %p/Inputs/alias_internal.ll -o %t2.bc
6+
; RUN: llvm-lto2 run %t1.bc %t2.bc -o %t.out -save-temps \
7+
; RUN: -r %t1.bc,a1,plx \
8+
; RUN: -r %t2.bc,a2,plx
9+
10+
; RUN: cat %t.out.index.dot | FileCheck %s
11+
; CHECK-DAG: M0_12511626713252727690 -> M0_{{.*}} // alias
12+
; CHECK-DAG: M1_8129049334585965161 -> M1_{{.*}} // alias
13+
14+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
15+
target triple = "x86_64-unknown-linux-gnu"
16+
17+
define internal i32 @f(i8*) unnamed_addr {
18+
ret i32 42
19+
}
20+
21+
@a1 = weak alias i32 (i8*), i32 (i8*)* @f

0 commit comments

Comments
 (0)