Skip to content

Commit 683e41d

Browse files
authored
Merge pull request #381 from crystax/master
Add --print-os-abi and --set-os-abi options
2 parents 7281d99 + 5faf453 commit 683e41d

File tree

5 files changed

+154
-0
lines changed

5 files changed

+154
-0
lines changed

patchelf.1

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ INTERPRETER.
3636
.IP --print-interpreter
3737
Prints the ELF interpreter of the executable.
3838

39+
.IP --print-os-abi
40+
Prints the OS ABI of the executable (EI_OSABI field of an ELF file).
41+
42+
.IP "--set-os-abi ABI"
43+
Changes the OS ABI of the executable (EI_OSABI field of an ELF file).
44+
The ABI parameter is pretty flexible. For example, you can specify it
45+
as a "Linux", "linux", or even "lInUx" - all those names will set EI_OSABI
46+
field of the ELF header to the value "3", which corresponds to Linux OS ABI.
47+
The same applies to other ABI names - System V, FreeBSD, Solaris, etc.
48+
3949
.IP --print-soname
4050
Prints DT_SONAME entry of .dynamic section.
4151
Raises an error if DT_SONAME doesn't exist.

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+
unsigned char abi = hdr()->e_ident[EI_OSABI];
1125+
1126+
if (op == printOsAbi) {
1127+
switch (abi) {
1128+
case 0: printf("System V\n"); break;
1129+
case 1: printf("HP-UX\n"); break;
1130+
case 2: printf("NetBSD\n"); break;
1131+
case 3: printf("Linux\n"); break;
1132+
case 4: printf("GNU Hurd\n"); break;
1133+
case 6: printf("Solaris\n"); break;
1134+
case 7: printf("AIX\n"); break;
1135+
case 8: printf("IRIX\n"); break;
1136+
case 9: printf("FreeBSD\n"); break;
1137+
case 10: printf("Tru64\n"); break;
1138+
case 12: printf("OpenBSD\n"); break;
1139+
case 13: printf("OpenVMS\n"); break;
1140+
default: printf("0x%02X\n", (unsigned int) abi);
1141+
}
1142+
return;
1143+
}
1144+
1145+
unsigned char newAbi;
1146+
std::string nabi = downcase(trim(newOsAbi));
1147+
if (nabi == "system v" || nabi == "system-v" || nabi == "sysv")
1148+
newAbi = 0;
1149+
else if (nabi == "hp-ux")
1150+
newAbi = 1;
1151+
else if (nabi == "netbsd")
1152+
newAbi = 2;
1153+
else if (nabi == "linux" || nabi == "gnu")
1154+
newAbi = 3;
1155+
else if (nabi == "gnu hurd" || nabi == "gnu-hurd" || nabi == "hurd")
1156+
newAbi = 4;
1157+
else if (nabi == "solaris")
1158+
newAbi = 6;
1159+
else if (nabi == "aix")
1160+
newAbi = 7;
1161+
else if (nabi == "irix")
1162+
newAbi = 8;
1163+
else if (nabi == "freebsd")
1164+
newAbi = 9;
1165+
else if (nabi == "tru64")
1166+
newAbi = 10;
1167+
else if (nabi == "openbsd")
1168+
newAbi = 12;
1169+
else if (nabi == "openvms")
1170+
newAbi = 13;
1171+
else
1172+
error("unrecognized OS ABI");
1173+
1174+
if (newAbi == abi) {
1175+
debug("current and requested OS ABIs are equal\n");
1176+
return;
1177+
}
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);

tests/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ src_TESTS = \
3333
endianness.sh \
3434
contiguous-note-sections.sh \
3535
no-gnu-hash.sh \
36+
change-abi.sh \
3637
grow-file.sh \
3738
no-dynamic-section.sh \
3839
args-from-file.sh \

tests/change-abi.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#! /bin/sh -e
2+
3+
SCRATCH=scratch/$(basename $0 .sh)
4+
5+
rm -rf ${SCRATCH}
6+
mkdir -p ${SCRATCH}
7+
8+
cp simple-pie ${SCRATCH}/simple-pie
9+
10+
# Save the old OS ABI
11+
OLDABI=`../src/patchelf --print-os-abi ${SCRATCH}/simple-pie`
12+
# Ensure it's not empty
13+
test -n "$OLDABI"
14+
15+
# Change OS ABI and verify it has been changed
16+
{
17+
echo "System V"
18+
echo "HP-UX"
19+
echo "NetBSD"
20+
echo "Linux"
21+
echo "GNU Hurd"
22+
echo "Solaris"
23+
echo "AIX"
24+
echo "IRIX"
25+
echo "FreeBSD"
26+
echo "Tru64"
27+
echo "OpenBSD"
28+
echo "OpenVMS"
29+
} | {
30+
while IFS="\n" read ABI; do
31+
echo "Set OS ABI to '$ABI'..."
32+
../src/patchelf --set-os-abi "$ABI" ${SCRATCH}/simple-pie
33+
34+
echo "Check is OS ABI is '$ABI'..."
35+
NEWABI=`../src/patchelf --print-os-abi ${SCRATCH}/simple-pie`
36+
test "$NEWABI" = "$ABI"
37+
done
38+
}
39+
40+
# Reset OS ABI to the saved one
41+
../src/patchelf --set-os-abi "$OLDABI" ${SCRATCH}/simple-pie
42+
43+
# Verify we still can run the executable
44+
${SCRATCH}/simple-pie

0 commit comments

Comments
 (0)