Skip to content

Commit cd6cfd9

Browse files
parth-07quic-seaswara
authored andcommitted
Fix generation of duplicate DT_NEEDED entries
This commit fixes generation of duplicate DT_NEEDED entries. Duplicate DT_NEEDED entries were previously emitted when a shared library was specified multiple times in the link command-line. Closes #47 Signed-off-by: Parth Arora <[email protected]>
1 parent 982721e commit cd6cfd9

File tree

10 files changed

+68
-13
lines changed

10 files changed

+68
-13
lines changed

include/eld/Target/ELFDynamic.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#ifndef ELD_TARGET_ELFDYNAMIC_H
1717
#define ELD_TARGET_ELFDYNAMIC_H
1818

19+
#include "eld/Input/ELFDynObjectFile.h"
1920
#include "eld/Readers/ELFSection.h"
2021
#include "eld/Support/MemoryRegion.h"
2122
#include "llvm/BinaryFormat/ELF.h"
@@ -161,6 +162,12 @@ class ELFDynamic {
161162

162163
static std::string TagToString(uint64_t Tag);
163164

165+
void addDTNeededLib(const ELFDynObjectFile &dynObjFile);
166+
167+
const std::vector<const ELFDynObjectFile *> &getDTNeededLibs() const {
168+
return DTNeededLibs;
169+
}
170+
164171
protected:
165172
/// reserveTargetEntries - reserve target dependent entries
166173
virtual void reserveTargetEntries() = 0;
@@ -185,6 +192,7 @@ class ELFDynamic {
185192
// For better performance, we use a simple counter and apply entry one-by-one
186193
// by the counter. m_Idx is the counter indicating to the entry being applied.
187194
size_t m_Idx;
195+
std::vector<const ELFDynObjectFile *> DTNeededLibs;
188196

189197
protected:
190198
GNULDBackend &m_Backend;

lib/Target/ELFDynamic.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,3 +427,8 @@ void ELFDynamic::emit(const ELFSection &pSection, MemoryRegion &pRegion) const {
427427
void ELFDynamic::applySoname(uint64_t pStrTabIdx) {
428428
applyOne(llvm::ELF::DT_SONAME, pStrTabIdx); // DT_SONAME
429429
}
430+
431+
void ELFDynamic::addDTNeededLib(const ELFDynObjectFile &dynObjFile) {
432+
reserveNeedEntry();
433+
DTNeededLibs.push_back(&dynObjFile);
434+
}

lib/Target/GNULDBackend.cpp

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -873,10 +873,17 @@ void GNULDBackend::sizeDynamic() {
873873
}
874874

875875
// add DT_NEEDED
876-
for (auto &lib : m_Module.getDynLibraryList()) {
877-
if (llvm::dyn_cast<ELFFileBase>(lib)->isELFNeeded()) {
878-
dynstr += llvm::dyn_cast<ELFDynObjectFile>(lib)->getSOName().size() + 1;
879-
dynamic()->reserveNeedEntry();
876+
{
877+
std::unordered_set<MemoryArea *> addedLibs;
878+
for (auto &lib : m_Module.getDynLibraryList()) {
879+
if (llvm::dyn_cast<ELFFileBase>(lib)->isELFNeeded()) {
880+
const ELFDynObjectFile *dynObjFile = llvm::cast<ELFDynObjectFile>(lib);
881+
if (addedLibs.count(dynObjFile->getInput()->getMemArea()))
882+
continue;
883+
dynstr += dynObjFile->getSOName().size() + 1;
884+
dynamic()->addDTNeededLib(*dynObjFile);
885+
addedLibs.insert(dynObjFile->getInput()->getMemArea());
886+
}
880887
}
881888
}
882889

@@ -1216,15 +1223,13 @@ bool GNULDBackend::emitDynNamePools(llvm::FileOutputBuffer &pOutput) {
12161223
// add DT_NEED strings into .dynstr
12171224
if (strtab) {
12181225
ELFDynamic::iterator dt_need = dynamic()->needBegin();
1219-
for (auto &lib : m_Module.getDynLibraryList()) {
1220-
if (llvm::dyn_cast<ELFFileBase>(lib)->isELFNeeded()) {
1221-
strcpy((strtab + strtabsize),
1222-
llvm::dyn_cast<ELFDynObjectFile>(lib)->getSOName().c_str());
1223-
(*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
1224-
strtabsize +=
1225-
llvm::dyn_cast<ELFDynObjectFile>(lib)->getSOName().size() + 1;
1226-
++dt_need;
1227-
}
1226+
for (auto &lib : dynamic()->getDTNeededLibs()) {
1227+
strcpy((strtab + strtabsize),
1228+
llvm::dyn_cast<ELFDynObjectFile>(lib)->getSOName().c_str());
1229+
(*dt_need)->setValue(llvm::ELF::DT_NEEDED, strtabsize);
1230+
strtabsize +=
1231+
llvm::dyn_cast<ELFDynObjectFile>(lib)->getSOName().size() + 1;
1232+
++dt_need;
12281233
}
12291234

12301235
if (!config().options().getRpathList().empty()) {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#---DTNeededForRepeatedDynLibs.test------------- Executable, SharedLibrary ----------#
2+
#BEGIN_COMMENT
3+
#This test checks that DT_NEEDED entry is not repeated for repeated shared libs.
4+
#END_COMMENT
5+
#START_TEST
6+
RUN: %clang %clangopts -o %t1.1.o %p/Inputs/1.c -c -fPIC
7+
RUN: %clang %clangopts -o %t1.2.o %p/Inputs/2.c -c
8+
RUN: %link %linkopts -shared -o %t1.lib1.so %t1.1.o
9+
RUN: %link %linkopts -dy -o %t1.2.out %t1.2.o %t1.lib1.so
10+
RUN: %readelf --dynamic %t1.2.out | %filecheck %s
11+
#END_TEST
12+
13+
CHECK: {{.*}}NEEDED{{.*}}lib1.so
14+
CHECK-NOT: {{.*}}NEEDED{{.*}}lib1.so
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int foo() { return 1; }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int bar() { return 3; }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int foo() { return 1; }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int bar() { return 3; }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int main() { return 5; }
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#---RepeatedDynLibsAsNeeded.test------------- Executable, SharedLibrary ----------#
2+
#BEGIN_COMMENT
3+
# This test checks that DT_NEEDED order is correct when a
4+
# shared library is specified with both --as-needed and --no-as-needed
5+
#END_COMMENT
6+
#START_TEST
7+
RUN: %clang %clangopts -o %t1.1.o %p/Inputs/1.c -c -fPIC
8+
RUN: %clang %clangopts -o %t1.2.o %p/Inputs/2.c -c -fPIC
9+
RUN: %clang %clangopts -o %t1.3.o %p/Inputs/3.c -c
10+
RUN: %link %linkopts -shared -o %t1.lib1.so %t1.1.o
11+
RUN: %link %linkopts -shared -o %t1.lib2.so %t1.2.o
12+
RUN: %link %linkopts -dy -o %t1.3.out %t1.3.o --as-needed %t1.lib1.so --no-as-needed %t1.lib2.so %t1.lib1.so
13+
RUN: %readelf --dynamic %t1.3.out | %filecheck %s
14+
#END_TEST
15+
16+
CHECK: {{.*}}NEEDED{{.*}}lib2.so
17+
CHECK: {{.*}}NEEDED{{.*}}lib1.so
18+
CHECK-NOT: {{.*}}NEEDED{{.*}}lib1.so

0 commit comments

Comments
 (0)