forked from OSchip/llvm-project
Select new undefined atom rather than old one if other conditions are the same.
We can add multiple undefined atoms having the same name to the symbol table. If such atoms are added, the symbol table compares their canBeNull attributes, and select one having a stronger constraint. If their canBeNulls are the same, the choice is arbitrary. Currently it choose the existing one. This patch changes the preference, so that the symbol table choose the new one if the new atom has a greater canBeNull or a fallback atom. This shouldn't change the behavior except the case described below. A new undefined atom may have a new fallback atom attribute. By choosing the new atom, we can update the fallback atom during Core Linking. PE/COFF actually need that. For example, _lseek is an alias for __lseek on Windows. One of an object file in OLDNAMES.LIB has an undefined atom for _lseek with the fallback to __lseek. When the linker tries to resolve _read, it supposed to read the file from OLDNAMES.LIB and use the new fallback from the file. Currently LLD cannot handle such case because duplicate undefined atoms with the same attributes are ignored. Differential Revision: http://llvm-reviews.chandlerc.com/D2161 llvm-svn: 194777
This commit is contained in:
parent
014192dbda
commit
b4dca7f065
|
@ -172,28 +172,42 @@ void SymbolTable::addByName(const Atom & newAtom) {
|
|||
}
|
||||
break;
|
||||
case NCR_DupUndef: {
|
||||
const UndefinedAtom* existingUndef =
|
||||
dyn_cast<UndefinedAtom>(existing);
|
||||
const UndefinedAtom* newUndef =
|
||||
dyn_cast<UndefinedAtom>(&newAtom);
|
||||
assert(existingUndef != nullptr);
|
||||
assert(newUndef != nullptr);
|
||||
if (existingUndef->canBeNull() == newUndef->canBeNull()) {
|
||||
useNew = false;
|
||||
} else {
|
||||
if (_context.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
|
||||
// FIXME: need diagonstics interface for writing warning messages
|
||||
llvm::errs() << "lld warning: undefined symbol "
|
||||
<< existingUndef->name()
|
||||
<< " has different weakness in "
|
||||
<< existingUndef->file().path()
|
||||
<< " and in "
|
||||
<< newUndef->file().path();
|
||||
}
|
||||
useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
|
||||
}
|
||||
const UndefinedAtom* existingUndef = dyn_cast<UndefinedAtom>(existing);
|
||||
const UndefinedAtom* newUndef = dyn_cast<UndefinedAtom>(&newAtom);
|
||||
assert(existingUndef != nullptr);
|
||||
assert(newUndef != nullptr);
|
||||
|
||||
bool sameCanBeNull = (existingUndef->canBeNull() == newUndef->canBeNull());
|
||||
if (!sameCanBeNull &&
|
||||
_context.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
|
||||
llvm::errs() << "lld warning: undefined symbol "
|
||||
<< existingUndef->name()
|
||||
<< " has different weakness in "
|
||||
<< existingUndef->file().path()
|
||||
<< " and in " << newUndef->file().path() << "\n";
|
||||
}
|
||||
|
||||
const UndefinedAtom *existingFallback = existingUndef->fallback();
|
||||
const UndefinedAtom *newFallback = newUndef->fallback();
|
||||
bool hasDifferentFallback =
|
||||
(existingFallback && newFallback &&
|
||||
existingFallback->name() != newFallback->name());
|
||||
if (hasDifferentFallback) {
|
||||
llvm::errs() << "lld warning: undefined symbol "
|
||||
<< existingUndef->name() << " has different fallback: "
|
||||
<< existingFallback->name() << " in "
|
||||
<< existingUndef->file().path() << " and "
|
||||
<< newFallback->name() << " in "
|
||||
<< newUndef->file().path() << "\n";
|
||||
}
|
||||
|
||||
bool hasNewFallback = newUndef->fallback();
|
||||
if (sameCanBeNull)
|
||||
useNew = hasNewFallback;
|
||||
else
|
||||
useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
|
||||
break;
|
||||
}
|
||||
case NCR_DupShLib: {
|
||||
const SharedLibraryAtom* curShLib =
|
||||
dyn_cast<SharedLibraryAtom>(existing);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# RUN: lld -core %s | FileCheck %s
|
||||
# RUN: lld -core %s 2> %t.err | FileCheck %s
|
||||
# RUN: FileCheck -check-prefix=ERROR %s < %t.err
|
||||
|
||||
#
|
||||
# Test that undefined symbols preserve their attributes and merge properly
|
||||
|
@ -8,86 +9,75 @@
|
|||
undefined-atoms:
|
||||
- name: regular_func
|
||||
can-be-null: never
|
||||
|
||||
- name: weak_import_func
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: weak_func
|
||||
can-be-null: at-buildtime
|
||||
|
||||
- name: bar1
|
||||
can-be-null: never
|
||||
|
||||
- name: bar2
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: bar3
|
||||
can-be-null: at-buildtime
|
||||
|
||||
- name: bar4
|
||||
can-be-null: never
|
||||
|
||||
- name: bar5
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: bar6
|
||||
can-be-null: at-buildtime
|
||||
|
||||
- name: bar7
|
||||
can-be-null: never
|
||||
|
||||
- name: bar8
|
||||
can-be-null: at-runtime
|
||||
|
||||
fallback:
|
||||
name: baz1
|
||||
- name: bar9
|
||||
can-be-null: at-buildtime
|
||||
|
||||
fallback:
|
||||
name: baz2
|
||||
---
|
||||
undefined-atoms:
|
||||
- name: bar1
|
||||
can-be-null: never
|
||||
|
||||
- name: bar2
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: bar3
|
||||
can-be-null: at-buildtime
|
||||
|
||||
- name: bar4
|
||||
can-be-null: at-runtime
|
||||
|
||||
- name: bar5
|
||||
can-be-null: at-buildtime
|
||||
|
||||
- name: bar6
|
||||
can-be-null: never
|
||||
|
||||
- name: bar7
|
||||
can-be-null: at-buildtime
|
||||
|
||||
- name: bar8
|
||||
can-be-null: never
|
||||
|
||||
- name: bar9
|
||||
can-be-null: at-runtime
|
||||
fallback:
|
||||
name: baz3
|
||||
...
|
||||
|
||||
# CHECK: - name: regular_func
|
||||
# CHECK: - name: weak_import_func
|
||||
# CHECK: can-be-null: at-runtime
|
||||
# CHECK: - name: weak_func
|
||||
# CHECK: can-be-null: at-buildtime
|
||||
# CHECK: - name: bar1
|
||||
# CHECK: - name: bar2
|
||||
# CHECK: can-be-null: at-runtime
|
||||
# CHECK: - name: bar3
|
||||
# CHECK: can-be-null: at-buildtime
|
||||
# CHECK: - name: bar4
|
||||
# CHECK: - name: bar5
|
||||
# CHECK: can-be-null: at-runtime
|
||||
# CHECK: - name: bar7
|
||||
# CHECK: - name: bar6
|
||||
# CHECK: - name: bar8
|
||||
# CHECK: - name: bar9
|
||||
# CHECK: can-be-null: at-runtime
|
||||
# CHECK: ...
|
||||
# CHECK: - name: regular_func
|
||||
# CHECK-NEXT: - name: weak_import_func
|
||||
# CHECK-NEXT: can-be-null: at-runtime
|
||||
# CHECK-NEXT: - name: weak_func
|
||||
# CHECK-NEXT: can-be-null: at-buildtime
|
||||
# CHECK-NEXT: - name: bar1
|
||||
# CHECK-NEXT: - name: bar2
|
||||
# CHECK-NEXT: can-be-null: at-runtime
|
||||
# CHECK-NEXT: - name: bar3
|
||||
# CHECK-NEXT: can-be-null: at-buildtime
|
||||
# CHECK-NEXT: - name: bar4
|
||||
# CHECK-NEXT: - name: bar5
|
||||
# CHECK-NEXT: can-be-null: at-runtime
|
||||
# CHECK-NEXT: - name: bar7
|
||||
# CHECK-NEXT: - name: bar6
|
||||
# CHECK-NEXT: - name: bar8
|
||||
# CHECK-NEXT: - name: bar9
|
||||
# CHECK-NEXT: can-be-null: at-runtime
|
||||
# CHECK-NEXT: fallback:
|
||||
# CHECK-NEXT: name: baz3
|
||||
|
||||
# ERROR: undefined symbol bar9 has different fallback: baz2 in and baz3 in
|
||||
|
|
Loading…
Reference in New Issue