parent
7bdeab592d
commit
c44bc347cb
|
@ -154,11 +154,20 @@ void LayoutPass::buildFollowOnTable(MutableFile::DefinedAtomRange &range) {
|
||||||
} else { // the atom could be part of chain already
|
} else { // the atom could be part of chain already
|
||||||
// Get to the root of the chain
|
// Get to the root of the chain
|
||||||
const DefinedAtom *a = _followOnRoots[targetAtom];
|
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
|
// Lets add to the chain only if the atoms that
|
||||||
// appear before the targetAtom in the chain
|
// appear before the targetAtom in the chain
|
||||||
// are of size 0
|
// are of size 0
|
||||||
bool foundNonZeroSizeAtom = false;
|
bool foundNonZeroSizeAtom = false;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
targetPrevAtom = a;
|
||||||
|
|
||||||
// Set all the follow on's for the targetAtom to be
|
// Set all the follow on's for the targetAtom to be
|
||||||
// the current root
|
// the current root
|
||||||
AtomToAtomT::iterator targetFollowOnAtomsIter =
|
AtomToAtomT::iterator targetFollowOnAtomsIter =
|
||||||
|
@ -169,12 +178,14 @@ void LayoutPass::buildFollowOnTable(MutableFile::DefinedAtomRange &range) {
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (a->size() != 0) {
|
if ((a->size() != 0) && (currentAtomSize != 0)) {
|
||||||
foundNonZeroSizeAtom = true;
|
foundNonZeroSizeAtom = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a == targetAtom)
|
if (a == targetAtom)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
} // while true
|
} // while true
|
||||||
if (foundNonZeroSizeAtom) {
|
if (foundNonZeroSizeAtom) {
|
||||||
// TODO: print warning that an impossible layout
|
// TODO: print warning that an impossible layout
|
||||||
|
@ -183,6 +194,14 @@ void LayoutPass::buildFollowOnTable(MutableFile::DefinedAtomRange &range) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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];
|
_followOnNexts[ai] = _followOnRoots[targetAtom];
|
||||||
// Set the root of all atoms in the
|
// Set the root of all atoms in the
|
||||||
a = _followOnRoots[targetAtom];
|
a = _followOnRoots[targetAtom];
|
||||||
|
@ -197,6 +216,7 @@ void LayoutPass::buildFollowOnTable(MutableFile::DefinedAtomRange &range) {
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
} // while true
|
} // while true
|
||||||
|
} // end else (currentAtomSize != 0)
|
||||||
} // end else
|
} // end else
|
||||||
} // else
|
} // else
|
||||||
} // kindLayoutAfter
|
} // kindLayoutAfter
|
||||||
|
|
|
@ -346,6 +346,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
ELFDefinedAtom<ELFT> *previous_atom = nullptr;
|
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
|
// i.first is the section the symbol lives in
|
||||||
for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) {
|
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;
|
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.
|
// Don't allocate content to a weak symbol, as they may be merged away.
|
||||||
// Create an anonymous atom to hold the data.
|
// 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) {
|
if ((*si)->getBinding() == llvm::ELF::STB_WEAK && contentSize != 0) {
|
||||||
// Create a new non-weak ELF symbol.
|
// Create a new non-weak ELF symbol.
|
||||||
auto sym = new (_readerStorage) Elf_Sym;
|
auto sym = new (_readerStorage) Elf_Sym;
|
||||||
|
@ -392,26 +417,26 @@ public:
|
||||||
"", sectionName, sym, i.first,
|
"", sectionName, sym, i.first,
|
||||||
ArrayRef<uint8_t>((uint8_t *)sectionContents.data() +
|
ArrayRef<uint8_t>((uint8_t *)sectionContents.data() +
|
||||||
(*si)->st_value, contentSize));
|
(*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;
|
contentSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<uint8_t> symbolData = ArrayRef<uint8_t>(
|
ArrayRef<uint8_t> symbolData = ArrayRef<uint8_t>(
|
||||||
(uint8_t *)sectionContents.data() + (*si)->st_value, contentSize);
|
(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
|
// 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
|
// mergeable section, treat them as defined atoms as they shouldnt be
|
||||||
// merged away as well as these symbols have to be part of symbol
|
// merged away as well as these symbols have to be part of symbol
|
||||||
|
@ -434,10 +459,23 @@ public:
|
||||||
auto newAtom = createDefinedAtomAndAssignRelocations(
|
auto newAtom = createDefinedAtomAndAssignRelocations(
|
||||||
symbolName, sectionName, *si, i.first, symbolData);
|
symbolName, sectionName, *si, i.first, symbolData);
|
||||||
|
|
||||||
// If we are inserting a followOn reference, lets add a precededBy
|
// If the atom was a weak symbol, lets create a followon
|
||||||
// reference too
|
// 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) {
|
if (followOn) {
|
||||||
ELFReference<ELFT> *precededby = nullptr;
|
ELFReference<ELFT> *precededby = nullptr;
|
||||||
|
// 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);
|
followOn->setTarget(newAtom);
|
||||||
// Add a preceded by reference only if the current atom is not a
|
// Add a preceded by reference only if the current atom is not a
|
||||||
// weak atom
|
// weak atom
|
||||||
|
@ -451,7 +489,9 @@ public:
|
||||||
|
|
||||||
// The previous atom is always the atom created before unless
|
// The previous atom is always the atom created before unless
|
||||||
// the atom is a weak atom
|
// the atom is a weak atom
|
||||||
if ((*si)->getBinding() != llvm::ELF::STB_WEAK)
|
if (anonAtom)
|
||||||
|
previous_atom = anonAtom;
|
||||||
|
else
|
||||||
previous_atom = newAtom;
|
previous_atom = newAtom;
|
||||||
|
|
||||||
_definedAtoms._atoms.push_back(newAtom);
|
_definedAtoms._atoms.push_back(newAtom);
|
||||||
|
|
|
@ -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.
|
@ -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.
|
@ -0,0 +1,6 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
void f(void)
|
||||||
|
{
|
||||||
|
printf("overridden f!\n");
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -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.
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue