[ELF] Order weak symbols properly

llvm-svn: 176583
This commit is contained in:
Shankar Easwaran 2013-03-06 21:59:27 +00:00
parent 7bdeab592d
commit c44bc347cb
15 changed files with 268 additions and 34 deletions

View File

@ -154,11 +154,20 @@ void LayoutPass::buildFollowOnTable(MutableFile::DefinedAtomRange &range) {
} else { // the atom could be part of chain already
// Get to the root of the chain
const DefinedAtom *a = _followOnRoots[targetAtom];
const DefinedAtom *targetPrevAtom = nullptr;
// If the size of the atom is 0, and the target
// is already part of a chain, lets bring the current
// atom into the chain
size_t currentAtomSize = (*ai).size();
// Lets add to the chain only if the atoms that
// appear before the targetAtom in the chain
// are of size 0
bool foundNonZeroSizeAtom = false;
while (true) {
targetPrevAtom = a;
// Set all the follow on's for the targetAtom to be
// the current root
AtomToAtomT::iterator targetFollowOnAtomsIter =
@ -169,12 +178,14 @@ void LayoutPass::buildFollowOnTable(MutableFile::DefinedAtomRange &range) {
else
break;
if (a->size() != 0) {
if ((a->size() != 0) && (currentAtomSize != 0)) {
foundNonZeroSizeAtom = true;
break;
}
if (a == targetAtom)
break;
} // while true
if (foundNonZeroSizeAtom) {
// TODO: print warning that an impossible layout
@ -183,20 +194,29 @@ void LayoutPass::buildFollowOnTable(MutableFile::DefinedAtomRange &range) {
break;
}
_followOnNexts[ai] = _followOnRoots[targetAtom];
// Set the root of all atoms in the
a = _followOnRoots[targetAtom];
while (true) {
_followOnRoots[a] = _followOnRoots[ai];
// Set all the follow on's for the targetAtom to be
// the current root
AtomToAtomT::iterator targetFollowOnAtomsIter =
_followOnNexts.find(a);
if (targetFollowOnAtomsIter != _followOnNexts.end())
a = targetFollowOnAtomsIter->second;
else
break;
} // while true
// If the atom is a zero sized atom, then make the target
// follow the zero sized atom, as the zero sized atom may be
// a weak symbol
if ((currentAtomSize == 0) && (targetPrevAtom)) {
_followOnNexts[targetPrevAtom] = ai;
_followOnRoots[ai] = _followOnRoots[targetPrevAtom];
_followOnNexts[ai] = targetAtom;
} else {
_followOnNexts[ai] = _followOnRoots[targetAtom];
// Set the root of all atoms in the
a = _followOnRoots[targetAtom];
while (true) {
_followOnRoots[a] = _followOnRoots[ai];
// Set all the follow on's for the targetAtom to be
// the current root
AtomToAtomT::iterator targetFollowOnAtomsIter =
_followOnNexts.find(a);
if (targetFollowOnAtomsIter != _followOnNexts.end())
a = targetFollowOnAtomsIter->second;
else
break;
} // while true
} // end else (currentAtomSize != 0)
} // end else
} // else
} // kindLayoutAfter

View File

@ -346,6 +346,11 @@ public:
}
ELFDefinedAtom<ELFT> *previous_atom = nullptr;
// Don't allocate content to a weak symbol, as they may be merged away.
// Create an anonymous atom to hold the data.
ELFDefinedAtom<ELFT> *anonAtom = nullptr;
ELFReference<ELFT> *anonPrecededBy = nullptr;
ELFReference<ELFT> *anonFollowedBy = nullptr;
// i.first is the section the symbol lives in
for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) {
@ -380,9 +385,29 @@ public:
contentSize = isCommon ? 0 : (*(si + 1))->st_value - (*si)->st_value;
}
// Check to see if we need to add the FollowOn Reference
// We dont want to do for symbols that are
// a) common symbols
ELFReference<ELFT> *followOn = nullptr;
if (!isCommon && previous_atom) {
// Replace the followon atom with the anonymous
// atom that we created, so that the next symbol
// that we create is a followon from the anonymous
// atom
if (!anonFollowedBy) {
followOn = new (_readerStorage)
ELFReference<ELFT>(lld::Reference::kindLayoutAfter);
previous_atom->addReference(followOn);
}
else
followOn = anonFollowedBy;
}
// Don't allocate content to a weak symbol, as they may be merged away.
// Create an anonymous atom to hold the data.
ELFDefinedAtom<ELFT> *anonAtom = nullptr;
anonAtom = nullptr;
anonPrecededBy = nullptr;
anonFollowedBy = nullptr;
if ((*si)->getBinding() == llvm::ELF::STB_WEAK && contentSize != 0) {
// Create a new non-weak ELF symbol.
auto sym = new (_readerStorage) Elf_Sym;
@ -392,26 +417,26 @@ public:
"", sectionName, sym, i.first,
ArrayRef<uint8_t>((uint8_t *)sectionContents.data() +
(*si)->st_value, contentSize));
// If this is the last atom, lets not create a followon
// reference
if ((si + 1) != se)
anonFollowedBy = new (_readerStorage)
ELFReference<ELFT>(lld::Reference::kindLayoutAfter);
anonPrecededBy = new (_readerStorage)
ELFReference<ELFT>(lld::Reference::kindLayoutBefore);
// Add the references to the anonymous atom that we created
if (anonFollowedBy)
anonAtom->addReference(anonFollowedBy);
anonAtom->addReference(anonPrecededBy);
if (previous_atom)
anonPrecededBy->setTarget(previous_atom);
contentSize = 0;
}
ArrayRef<uint8_t> symbolData = ArrayRef<uint8_t>(
(uint8_t *)sectionContents.data() + (*si)->st_value, contentSize);
// Check to see if we need to add the FollowOn Reference
// We dont want to do for symbols that are
// a) common symbols
// so, lets add a follow-on reference from the previous atom to the
// current atom as well as lets add a preceded-by reference from the
// current atom to the previous atom, so that the previous atom
// is not removed in any case
ELFReference<ELFT> *followOn = nullptr;
if (!isCommon && previous_atom) {
followOn = new (_readerStorage)
ELFReference<ELFT>(lld::Reference::kindLayoutAfter);
previous_atom->addReference(followOn);
}
// If the linker finds that a section has global atoms that are in a
// mergeable section, treat them as defined atoms as they shouldnt be
// merged away as well as these symbols have to be part of symbol
@ -434,11 +459,24 @@ public:
auto newAtom = createDefinedAtomAndAssignRelocations(
symbolName, sectionName, *si, i.first, symbolData);
// If we are inserting a followOn reference, lets add a precededBy
// reference too
// If the atom was a weak symbol, lets create a followon
// reference to the anonymous atom that we created
if ((*si)->getBinding() == llvm::ELF::STB_WEAK && anonAtom) {
ELFReference<ELFT> *wFollowedBy = new (_readerStorage)
ELFReference<ELFT>(lld::Reference::kindLayoutAfter);
wFollowedBy->setTarget(anonAtom);
newAtom->addReference(wFollowedBy);
}
if (followOn) {
ELFReference<ELFT> *precededby = nullptr;
followOn->setTarget(newAtom);
// Set the followon atom to the weak atom
// that we have created, so that they would
// alias when the file gets written
if (anonAtom)
followOn->setTarget(anonAtom);
else
followOn->setTarget(newAtom);
// Add a preceded by reference only if the current atom is not a
// weak atom
if ((*si)->getBinding() != llvm::ELF::STB_WEAK) {
@ -451,7 +489,9 @@ public:
// The previous atom is always the atom created before unless
// the atom is a weak atom
if ((*si)->getBinding() != llvm::ELF::STB_WEAK)
if (anonAtom)
previous_atom = anonAtom;
else
previous_atom = newAtom;
_definedAtoms._atoms.push_back(newAtom);

View File

@ -0,0 +1,10 @@
#include <stdio.h>
void f(void)
{
printf("overridden f!\n");
}
void g(void)
{
printf("overridden g!\n");
}

Binary file not shown.

View File

@ -0,0 +1,20 @@
int fn()
{
return 0;
}
void __attribute__((weak)) f()
{
printf("original f..\n");
}
void __attribute__((weak)) g()
{
printf("original f..\n");
}
int main(void)
{
f();
return 0;
}

Binary file not shown.

View File

@ -0,0 +1,6 @@
#include <stdio.h>
void f(void)
{
printf("overridden f!\n");
}

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,14 @@
int fn()
{
return 0;
}
void __attribute__((weak)) f()
{
printf("original f..\n");
}
int main(void)
{
f();
return 0;
}

Binary file not shown.

View File

@ -0,0 +1,15 @@
# Test for weak symbol getting overridden
RUN: lld-core -reader ELF -writer ELF -arch x86_64 %p/Inputs/multi-weak.o \
RUN: %p/Inputs/multi-ovrd.o -o %t
RUN: llvm-nm -n %t | FileCheck -check-prefix=WEAKORDER %s
RUN: lld-core -reader ELF -arch x86_64 %p/Inputs/multi-weak.o \
RUN: %p/Inputs/multi-ovrd.o -layout-pass=true -o %t2
RUN: FileCheck -check-prefix=WEAKATOMSORDER %s < %t2
WEAKORDER: 0040011c T f
WEAKORDER: 0040012c T g
WEAKATOMSORDER: - ref-name: L002
WEAKATOMSORDER: - ref-name: L003
WEAKATOMSORDER: - name: f
WEAKATOMSORDER: - name: g

View File

@ -0,0 +1,19 @@
# Test for weak symbol getting overridden
RUN: lld-core -reader ELF -writer ELF -arch x86_64 %p/Inputs/multi-weak.o \
RUN: -o %t
RUN: llvm-nm -n %t | FileCheck -check-prefix=WEAKORDER %s
RUN: lld-core -reader ELF -arch x86_64 %p/Inputs/multi-weak.o \
RUN: -layout-pass=true -o %t2
RUN: FileCheck -check-prefix=WEAKATOMSORDER %s < %t2
WEAKORDER: 004000c0 T fn
WEAKORDER: 004000cb T .text
WEAKORDER: 004000cb T f
WEAKORDER: 004000db T .text
WEAKORDER: 004000db T g
WEAKORDER: 004000eb T main
WEAKATOMSORDER: - name: f
WEAKATOMSORDER: - ref-name: L004
WEAKATOMSORDER: - name: g
WEAKATOMSORDER: - ref-name: L005

View File

@ -0,0 +1,56 @@
# Test for weak symbol getting overridden
RUN: lld-core -reader ELF -writer ELF -arch x86_64 %p/Inputs/weak.o \
RUN: %p/Inputs/ovrd.o -o %t
RUN: llvm-nm %t | FileCheck -check-prefix=WEAKORDER %s
RUN: lld-core -reader ELF -arch x86_64 %p/Inputs/weak.o \
RUN: %p/Inputs/ovrd.o -layout-pass=true -o %t2
RUN: FileCheck -check-prefix=WEAKATOMSORDER %s < %t2
WEAKORDER: 004000fc T f
WEAKATOMSORDER: - name: .text
WEAKATOMSORDER: references:
WEAKATOMSORDER: - kind: layout-after
WEAKATOMSORDER: offset: 0
WEAKATOMSORDER: target: fn
WEAKATOMSORDER: - name: fn
WEAKATOMSORDER: references:
WEAKATOMSORDER: - kind: layout-after
WEAKATOMSORDER: offset: 0
WEAKATOMSORDER: target: L001
WEAKATOMSORDER: - ref-name: L001
WEAKATOMSORDER: scope: global
WEAKATOMSORDER: content: [ 55, 48, 89, E5, BF, 00, 00, 00, 00, E8, 00, 00,
WEAKATOMSORDER: 00, 00, 5D, C3 ]
WEAKATOMSORDER: references:
WEAKATOMSORDER: - kind: layout-after
WEAKATOMSORDER: offset: 0
WEAKATOMSORDER: target: main
WEAKATOMSORDER: - kind: layout-before
WEAKATOMSORDER: offset: 0
WEAKATOMSORDER: target: fn
WEAKATOMSORDER: - name: main
WEAKATOMSORDER: scope: global
WEAKATOMSORDER: content: [ 55, 48, 89, E5, B8, 00, 00, 00, 00, E8, 00, 00,
WEAKATOMSORDER: 00, 00, B8, 00, 00, 00, 00, 5D, C3 ]
WEAKATOMSORDER: references:
WEAKATOMSORDER: - kind: call32
WEAKATOMSORDER: offset: 10
WEAKATOMSORDER: target: f
WEAKATOMSORDER: addend: -4
WEAKATOMSORDER: - kind: layout-before
WEAKATOMSORDER: offset: 0
WEAKATOMSORDER: target: L001
WEAKATOMSORDER: - name: .text
WEAKATOMSORDER: section-name: .text
WEAKATOMSORDER: references:
WEAKATOMSORDER: - kind: layout-after
WEAKATOMSORDER: offset: 0
WEAKATOMSORDER: target: f
WEAKATOMSORDER: - name: f
WEAKATOMSORDER: scope: global
WEAKATOMSORDER: content: [ 55, 48, 89, E5, BF, 00, 00, 00, 00, E8, 00, 00,
WEAKATOMSORDER: 00, 00, 5D, C3 ]
WEAKATOMSORDER: references:
WEAKATOMSORDER: - kind: layout-before
WEAKATOMSORDER: offset: 0

View File

@ -0,0 +1,34 @@
# Test for zero sized weak atoms, there is only a single weak atom
RUN: lld-core -reader ELF -writer ELF -arch x86_64 %p/Inputs/weak-zero-sized.o \
RUN: -o %t
RUN: llvm-nm %t | FileCheck -check-prefix=WEAKORDER %s
RUN: lld-core -reader ELF -arch x86_64 %p/Inputs/weak-zero-sized.o \
RUN: -layout-pass=true -o %t2
RUN: FileCheck -check-prefix=WEAKATOMSORDER %s < %t2
WEAKORDER: 004000b0 T _start
WEAKATOMSORDER: - name: .text
WEAKATOMSORDER: alignment: 2^2
WEAKATOMSORDER: section-name: .text
WEAKATOMSORDER: - kind: layout-after
WEAKATOMSORDER: offset: 0
WEAKATOMSORDER: target: L001
WEAKATOMSORDER: - name: _start
WEAKATOMSORDER: scope: global
WEAKATOMSORDER: merge: as-weak
WEAKATOMSORDER: alignment: 2^2
WEAKATOMSORDER: section-name: .text
WEAKATOMSORDER: references:
WEAKATOMSORDER: - kind: layout-after
WEAKATOMSORDER: offset: 0
WEAKATOMSORDER: target: L001
WEAKATOMSORDER: - ref-name: L001
WEAKATOMSORDER: scope: global
WEAKATOMSORDER: content: [ C3 ]
WEAKATOMSORDER: alignment: 2^2
WEAKATOMSORDER: section-name: .text
WEAKATOMSORDER: references:
WEAKATOMSORDER: - kind: layout-before
WEAKATOMSORDER: offset: 0
WEAKATOMSORDER: target: .text