Skip to content

Commit 8f5ac59

Browse files
authored
Merge pull request #367 from deadw00d/master
Add --add-debug option
2 parents a350545 + b92e442 commit 8f5ac59

File tree

5 files changed

+77
-1
lines changed

5 files changed

+77
-1
lines changed

patchelf.1

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ option can be given multiple times.
8989
Marks the object so that the search for dependencies of this object will ignore any
9090
default library search paths.
9191

92+
.IP "--add-debug-tag"
93+
Adds DT_DEBUG tag to the .dynamic section if not yet present in an ELF
94+
object. A shared library (-shared) by default does not receive DT_DEBUG tag.
95+
This means that when a shared library has an entry point (so that it
96+
can be run as an executable), the debugger does not connect to it correctly and
97+
symbols are not resolved.
98+
9299
.IP "--output FILE"
93100
Set the output file name. If not specified, the input will be modified in place.
94101

src/patchelf.cc

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,6 +1652,38 @@ void ElfFile<ElfFileParamNames>::noDefaultLib()
16521652
changed = true;
16531653
}
16541654

1655+
template<ElfFileParams>
1656+
void ElfFile<ElfFileParamNames>::addDebugTag()
1657+
{
1658+
auto shdrDynamic = findSectionHeader(".dynamic");
1659+
1660+
auto dyn = (Elf_Dyn *)(fileContents->data() + rdi(shdrDynamic.sh_offset));
1661+
for ( ; rdi(dyn->d_tag) != DT_NULL; dyn++) {
1662+
if (rdi(dyn->d_tag) == DT_DEBUG) {
1663+
return;
1664+
}
1665+
}
1666+
std::string & newDynamic = replaceSection(".dynamic",
1667+
rdi(shdrDynamic.sh_size) + sizeof(Elf_Dyn));
1668+
1669+
unsigned int idx = 0;
1670+
for ( ; rdi(((Elf_Dyn *) newDynamic.c_str())[idx].d_tag) != DT_NULL; idx++) ;
1671+
debug("DT_NULL index is %d\n", idx);
1672+
1673+
/* Shift all entries down by one. */
1674+
setSubstr(newDynamic, sizeof(Elf_Dyn),
1675+
std::string(newDynamic, 0, sizeof(Elf_Dyn) * (idx + 1)));
1676+
1677+
/* Add the DT_DEBUG entry at the top. */
1678+
Elf_Dyn newDyn;
1679+
wri(newDyn.d_tag, DT_DEBUG);
1680+
newDyn.d_un.d_val = 0;
1681+
setSubstr(newDynamic, 0, std::string((char *) &newDyn, sizeof(Elf_Dyn)));
1682+
1683+
this->rewriteSections();
1684+
changed = true;
1685+
}
1686+
16551687
template<ElfFileParams>
16561688
void ElfFile<ElfFileParamNames>::clearSymbolVersions(const std::set<std::string> & syms)
16571689
{
@@ -1691,6 +1723,7 @@ static std::vector<std::string> allowedRpathPrefixes;
16911723
static bool removeRPath = false;
16921724
static bool setRPath = false;
16931725
static bool addRPath = false;
1726+
static bool addDebugTag = false;
16941727
static bool printRPath = false;
16951728
static std::string newRPath;
16961729
static std::set<std::string> neededLibsToRemove;
@@ -1737,6 +1770,9 @@ static void patchElf2(ElfFile && elfFile, const FileContents & fileContents, con
17371770
if (noDefaultLib)
17381771
elfFile.noDefaultLib();
17391772

1773+
if (addDebugTag)
1774+
elfFile.addDebugTag();
1775+
17401776
if (elfFile.isChanged()){
17411777
writeFile(fileName, elfFile.fileContents);
17421778
} else if (alwaysWrite) {
@@ -1793,6 +1829,7 @@ void showHelp(const std::string & progName)
17931829
[--print-needed]\n\
17941830
[--no-default-lib]\n\
17951831
[--clear-symbol-version SYMBOL]\n\
1832+
[--add-debug-tag]\n\
17961833
[--output FILE]\n\
17971834
[--debug]\n\
17981835
[--version]\n\
@@ -1901,6 +1938,9 @@ int mainWrapped(int argc, char * * argv)
19011938
else if (arg == "--no-default-lib") {
19021939
noDefaultLib = true;
19031940
}
1941+
else if (arg == "--add-debug-tag") {
1942+
addDebugTag = true;
1943+
}
19041944
else if (arg == "--help" || arg == "-h" ) {
19051945
showHelp(argv[0]);
19061946
return 0;

src/patchelf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ class ElfFile
131131

132132
void noDefaultLib();
133133

134+
void addDebugTag();
135+
134136
void clearSymbolVersions(const std::set<std::string> & syms);
135137

136138
private:

tests/Makefile.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ src_TESTS = \
4040
set-empty-rpath.sh \
4141
phdr-corruption.sh \
4242
replace-needed.sh \
43-
replace-add-needed.sh
43+
replace-add-needed.sh \
44+
add-debug-tag.sh
4445

4546
build_TESTS = \
4647
$(no_rpath_arch_TESTS)

tests/add-debug-tag.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#! /bin/sh -e
2+
SCRATCH=scratch/$(basename $0 .sh)
3+
4+
rm -rf ${SCRATCH}
5+
mkdir -p ${SCRATCH}
6+
7+
cp libsimple.so ${SCRATCH}/
8+
9+
# check there is no DT_DEBUG tag
10+
debugTag=$(readelf -d ${SCRATCH}/libsimple.so)
11+
echo ".dynamic before: $debugTag"
12+
if echo "$debugTag" | grep -q DEBUG; then
13+
echo "failed --add-debug-tag test. Expected no line with (DEBUG), got: $debugTag"
14+
exit 1
15+
fi
16+
17+
# set DT_DEBUG
18+
../src/patchelf --add-debug-tag ${SCRATCH}/libsimple.so
19+
20+
# check there is DT_DEBUG tag
21+
debugTag=$(readelf -d ${SCRATCH}/libsimple.so)
22+
echo ".dynamic before: $debugTag"
23+
if ! echo "$debugTag" | grep -q DEBUG; then
24+
echo "failed --add-debug-tag test. Expected line with (DEBUG), got: $debugTag"
25+
exit 1
26+
fi

0 commit comments

Comments
 (0)