Skip to content

Commit c6c4304

Browse files
author
deadwood
committed
Add --add-debug option
A shared library (-shared) by default does not receive DT_DEBUG tag. This means that when a shared library has an entry point (so that it can be run as an executable), the debugger does not connect to it correctly and symbols are not resolved. --add-debug option adds DT_DEBUG tag if it not yet present to an ELF object.
1 parent a992616 commit c6c4304

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

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>::addDebug()
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 addDebug = 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 (addDebug)
1774+
elfFile.addDebug();
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]\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") {
1942+
addDebug = 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 addDebug();
135+
134136
void clearSymbolVersions(const std::set<std::string> & syms);
135137

136138
private:

0 commit comments

Comments
 (0)