Skip to content

Commit db2ad5e

Browse files
committed
Add --print-os-abi and --set-os-abi options
This commit adds an ability to print and change the EI_OSABI field of the ELF header. Signed-off-by: Dmitry Moskalchuk <[email protected]>
1 parent 734daa3 commit db2ad5e

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed

src/patchelf.cc

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,20 @@ static bool hasAllowedPrefix(const std::string & s, const std::vector<std::strin
8686
return std::any_of(allowedPrefixes.begin(), allowedPrefixes.end(), [&](const std::string & i) { return !s.compare(0, i.size(), i); });
8787
}
8888

89+
static std::string trim(std::string s)
90+
{
91+
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); }));
92+
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end());
93+
94+
return s;
95+
}
96+
97+
static std::string downcase(std::string s)
98+
{
99+
std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return std::tolower(c); });
100+
return s;
101+
}
102+
89103
/* !!! G++ creates broken code if this function is inlined, don't know
90104
why... */
91105
template<ElfFileParams>
@@ -1104,6 +1118,68 @@ std::string ElfFile<ElfFileParamNames>::getInterpreter()
11041118
return std::string((char *) fileContents->data() + rdi(shdr.sh_offset), rdi(shdr.sh_size) - 1);
11051119
}
11061120

1121+
template<ElfFileParams>
1122+
void ElfFile<ElfFileParamNames>::modifyOsAbi(osAbiMode op, const std::string & newOsAbi)
1123+
{
1124+
if (rdi(hdr()->e_type) != ET_EXEC && rdi(hdr()->e_type) != ET_DYN) {
1125+
debug("this is not an executable and not a dynamic library\n");
1126+
return;
1127+
}
1128+
1129+
unsigned char abi = hdr()->e_ident[EI_OSABI];
1130+
1131+
if (op == printOsAbi) {
1132+
switch (abi) {
1133+
case 0: printf("System V\n"); break;
1134+
case 1: printf("HP-UX\n"); break;
1135+
case 2: printf("NetBSD\n"); break;
1136+
case 3: printf("Linux\n"); break;
1137+
case 4: printf("GNU Hurd\n"); break;
1138+
case 6: printf("Solaris\n"); break;
1139+
case 7: printf("AIX\n"); break;
1140+
case 8: printf("IRIX\n"); break;
1141+
case 9: printf("FreeBSD\n"); break;
1142+
case 10: printf("Tru64\n"); break;
1143+
case 12: printf("OpenBSD\n"); break;
1144+
case 13: printf("OpenVMS\n"); break;
1145+
default: printf("0x%02X\n", (unsigned int) abi);
1146+
}
1147+
return;
1148+
}
1149+
1150+
unsigned char newAbi;
1151+
std::string nabi = downcase(trim(newOsAbi));
1152+
if (nabi == "system v" || nabi == "system-v" || nabi == "sysv")
1153+
newAbi = 0;
1154+
else if (nabi == "hp-ux")
1155+
newAbi = 1;
1156+
else if (nabi == "netbsd")
1157+
newAbi = 2;
1158+
else if (nabi == "linux" || nabi == "gnu")
1159+
newAbi = 3;
1160+
else if (nabi == "gnu hurd" || nabi == "gnu-hurd" || nabi == "hurd")
1161+
newAbi = 4;
1162+
else if (nabi == "solaris")
1163+
newAbi = 6;
1164+
else if (nabi == "aix")
1165+
newAbi = 7;
1166+
else if (nabi == "irix")
1167+
newAbi = 8;
1168+
else if (nabi == "freebsd")
1169+
newAbi = 9;
1170+
else if (nabi == "tru64")
1171+
newAbi = 10;
1172+
else if (nabi == "openbsd")
1173+
newAbi = 12;
1174+
else if (nabi == "openvms")
1175+
newAbi = 13;
1176+
else
1177+
error("unrecognized OS ABI");
1178+
1179+
hdr()->e_ident[EI_OSABI] = newAbi;
1180+
changed = true;
1181+
}
1182+
11071183
template<ElfFileParams>
11081184
void ElfFile<ElfFileParamNames>::modifySoname(sonameMode op, const std::string & newSoname)
11091185
{
@@ -1739,6 +1815,9 @@ void ElfFile<ElfFileParamNames>::clearSymbolVersions(const std::set<std::string>
17391815
}
17401816

17411817
static bool printInterpreter = false;
1818+
static bool printOsAbi = false;
1819+
static bool setOsAbi = false;
1820+
static std::string newOsAbi;
17421821
static bool printSoname = false;
17431822
static bool setSoname = false;
17441823
static std::string newSoname;
@@ -1764,6 +1843,12 @@ static void patchElf2(ElfFile && elfFile, const FileContents & fileContents, con
17641843
if (printInterpreter)
17651844
printf("%s\n", elfFile.getInterpreter().c_str());
17661845

1846+
if (printOsAbi)
1847+
elfFile.modifyOsAbi(elfFile.printOsAbi, "");
1848+
1849+
if (setOsAbi)
1850+
elfFile.modifyOsAbi(elfFile.replaceOsAbi, newOsAbi);
1851+
17671852
if (printSoname)
17681853
elfFile.modifySoname(elfFile.printSoname, "");
17691854

@@ -1839,6 +1924,8 @@ void showHelp(const std::string & progName)
18391924
[--set-interpreter FILENAME]\n\
18401925
[--page-size SIZE]\n\
18411926
[--print-interpreter]\n\
1927+
[--print-os-abi]\t\tPrints 'EI_OSABI' field of ELF header\n\
1928+
[--set-os-abi ABI]\t\tSets 'EI_OSABI' field of ELF header to ABI.\n\
18421929
[--print-soname]\t\tPrints 'DT_SONAME' entry of .dynamic section. Raises an error if DT_SONAME doesn't exist\n\
18431930
[--set-soname SONAME]\t\tSets 'DT_SONAME' entry to SONAME.\n\
18441931
[--set-rpath RPATH]\n\
@@ -1888,6 +1975,14 @@ int mainWrapped(int argc, char * * argv)
18881975
else if (arg == "--print-interpreter") {
18891976
printInterpreter = true;
18901977
}
1978+
else if (arg == "--print-os-abi") {
1979+
printOsAbi = true;
1980+
}
1981+
else if (arg == "--set-os-abi") {
1982+
if (++i == argc) error("missing argument");
1983+
setOsAbi = true;
1984+
newOsAbi = resolveArgument(argv[i]);
1985+
}
18911986
else if (arg == "--print-soname") {
18921987
printSoname = true;
18931988
}

src/patchelf.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ class ElfFile
109109

110110
std::string getInterpreter();
111111

112+
typedef enum { printOsAbi, replaceOsAbi } osAbiMode;
113+
114+
void modifyOsAbi(osAbiMode op, const std::string & newOsAbi);
115+
112116
typedef enum { printSoname, replaceSoname } sonameMode;
113117

114118
void modifySoname(sonameMode op, const std::string & newSoname);

0 commit comments

Comments
 (0)