Skip to content

Commit a06b088

Browse files
committed
Always search both the main library and its debuginfo in Monkeypatcher::patch_after_mmap()
This is more robust than stopping if there any symbols in the library.
1 parent e2b4c5b commit a06b088

1 file changed

Lines changed: 58 additions & 57 deletions

File tree

src/Monkeypatcher.cc

Lines changed: 58 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1668,66 +1668,67 @@ void Monkeypatcher::patch_after_mmap(RecordTask* t, remote_ptr<void> start,
16681668
return;
16691669
}
16701670
}
1671+
16711672
ElfFileReader reader(open_fd, t->arch());
1672-
// Check for symbols first in the library itself, regardless of whether
1673-
// there is a debuglink. For example, on Fedora 26, the .symtab and
1674-
// .strtab sections are stripped from the debuginfo file for
1675-
// libpthread.so.
1676-
SymbolTable syms = reader.read_symbols(".symtab", ".strtab");
1677-
if (syms.size() == 0) {
1678-
ScopedFd debug_fd = reader.open_debug_file(map.map.fsname());
1679-
if (debug_fd.is_open()) {
1680-
ElfFileReader debug_reader(debug_fd, t->arch());
1681-
syms = debug_reader.read_symbols(".symtab", ".strtab");
1682-
}
1683-
}
1684-
switch (t->arch()) {
1685-
case x86:
1686-
case x86_64:
1687-
for (size_t i = 0; i < syms.size(); ++i) {
1688-
if (syms.is_name(i, "__elision_aconf")) {
1689-
static const int zero = 0;
1690-
// Setting __elision_aconf.retry_try_xbegin to zero means that
1691-
// pthread rwlocks don't try to use elision at all. See ELIDE_LOCK
1692-
// in glibc's elide.h.
1693-
set_and_record_bytes(t, reader, syms.addr(i) + 8, &zero, sizeof(zero),
1694-
start, size, offset_bytes, prot);
1695-
}
1696-
if (syms.is_name(i, "elision_init")) {
1697-
// Make elision_init return without doing anything. This means
1698-
// the __elision_available and __pthread_force_elision flags will
1699-
// remain zero, disabling elision for mutexes. See glibc's
1700-
// elision-conf.c.
1701-
static const uint8_t ret = 0xC3;
1702-
set_and_record_bytes(t, reader, syms.addr(i), &ret, sizeof(ret), start,
1703-
size, offset_bytes, prot);
1704-
}
1705-
// The following operations can only be applied once because after the
1706-
// patch is applied the code no longer matches the expected template.
1707-
// For replaying a replay to work, we need to only apply these changes
1708-
// during a real exec, not during the mmap operations performed when rr
1709-
// replays an exec.
1710-
if (mode == MMAP_EXEC &&
1711-
(syms.is_name(i, "_dl_runtime_resolve_fxsave") ||
1712-
syms.is_name(i, "_dl_runtime_resolve_xsave") ||
1713-
syms.is_name(i, "_dl_runtime_resolve_xsavec"))) {
1714-
patch_dl_runtime_resolve(t, reader, syms.addr(i), start, size,
1715-
offset_bytes, prot);
1673+
auto patch_with_symbols = [&](ElfFileReader& sym_reader) -> void {
1674+
SymbolTable syms = sym_reader.read_symbols(".symtab", ".strtab");
1675+
switch (t->arch()) {
1676+
case x86:
1677+
case x86_64:
1678+
for (size_t i = 0; i < syms.size(); ++i) {
1679+
if (syms.is_name(i, "__elision_aconf")) {
1680+
static const int zero = 0;
1681+
// Setting __elision_aconf.retry_try_xbegin to zero means that
1682+
// pthread rwlocks don't try to use elision at all. See ELIDE_LOCK
1683+
// in glibc's elide.h.
1684+
set_and_record_bytes(t, reader, syms.addr(i) + 8, &zero, sizeof(zero),
1685+
start, size, offset_bytes, prot);
1686+
}
1687+
if (syms.is_name(i, "elision_init")) {
1688+
// Make elision_init return without doing anything. This means
1689+
// the __elision_available and __pthread_force_elision flags will
1690+
// remain zero, disabling elision for mutexes. See glibc's
1691+
// elision-conf.c.
1692+
static const uint8_t ret = 0xC3;
1693+
set_and_record_bytes(t, reader, syms.addr(i), &ret, sizeof(ret), start,
1694+
size, offset_bytes, prot);
1695+
}
1696+
// The following operations can only be applied once because after the
1697+
// patch is applied the code no longer matches the expected template.
1698+
// For replaying a replay to work, we need to only apply these changes
1699+
// during a real exec, not during the mmap operations performed when rr
1700+
// replays an exec.
1701+
if (mode == MMAP_EXEC &&
1702+
(syms.is_name(i, "_dl_runtime_resolve_fxsave") ||
1703+
syms.is_name(i, "_dl_runtime_resolve_xsave") ||
1704+
syms.is_name(i, "_dl_runtime_resolve_xsavec"))) {
1705+
patch_dl_runtime_resolve(t, reader, syms.addr(i), start, size,
1706+
offset_bytes, prot);
1707+
}
17161708
}
1717-
}
1718-
break;
1719-
case aarch64:
1720-
for (size_t i = 0; i < syms.size(); ++i) {
1721-
if (syms.is_name(i, "__aarch64_have_lse_atomics")) {
1722-
// Patch the __aarch64_have_lse_atomics variable to ensure that LSE
1723-
// atomics are always used even if init_lse_atomics hasn't been called
1724-
// yet (or at all).
1725-
static const char one = 1;
1726-
set_and_record_bytes(t, reader, syms.addr(i), &one, sizeof(one),
1727-
start, size, offset_bytes, prot);
1709+
break;
1710+
case aarch64:
1711+
for (size_t i = 0; i < syms.size(); ++i) {
1712+
if (syms.is_name(i, "__aarch64_have_lse_atomics")) {
1713+
// Patch the __aarch64_have_lse_atomics variable to ensure that LSE
1714+
// atomics are always used even if init_lse_atomics hasn't been called
1715+
// yet (or at all).
1716+
static const char one = 1;
1717+
set_and_record_bytes(t, reader, syms.addr(i), &one, sizeof(one),
1718+
start, size, offset_bytes, prot);
1719+
}
17281720
}
1729-
}
1730-
break;
1721+
break;
1722+
}
1723+
};
1724+
// Check for symbols in the library itself as well as in debuginfo.
1725+
// For example, on Fedora 26, the .symtab and .strtab sections are stripped
1726+
// from the debuginfo file for libpthread.so.
1727+
patch_with_symbols(reader);
1728+
ScopedFd debug_fd = reader.open_debug_file(map.map.fsname());
1729+
if (debug_fd.is_open()) {
1730+
ElfFileReader debug_reader(debug_fd, t->arch());
1731+
patch_with_symbols(debug_reader);
17311732
}
17321733
}
17331734

0 commit comments

Comments
 (0)