diff --git a/src/AddressSpace.cc b/src/AddressSpace.cc index 925277520d9..0d16be529cf 100644 --- a/src/AddressSpace.cc +++ b/src/AddressSpace.cc @@ -482,7 +482,19 @@ vector AddressSpace::rr_page_syscalls() { return result; } -void AddressSpace::save_auxv(Task* t) { saved_auxv_ = read_auxv(t); } +void AddressSpace::save_auxv(Task* t) { + saved_auxv_ = read_auxv(t); + save_interpreter_base(t, saved_auxv()); +} + +void AddressSpace::save_interpreter_base(Task* t, std::vector auxv) { + saved_interpreter_base_ = read_interpreter_base(auxv); + save_ld_path(t, saved_interpreter_base()); +} + +void AddressSpace::save_ld_path(Task* t, remote_ptr interpreter_base) { + saved_ld_path_ = read_ld_path(t, interpreter_base); +} void AddressSpace::read_mm_map(Task* t, struct prctl_mm_map* map) { char buf[PATH_MAX+1024]; @@ -1657,6 +1669,8 @@ AddressSpace::AddressSpace(Session* session, const AddressSpace& o, stopping_breakpoint_table_(o.stopping_breakpoint_table_), stopping_breakpoint_table_entry_size_(o.stopping_breakpoint_table_entry_size_), saved_auxv_(o.saved_auxv_), + saved_interpreter_base_(o.saved_interpreter_base_), + saved_ld_path_(o.saved_ld_path_), first_run_event_(0) { for (auto& m : mem) { // The original address space continues to have exclusive ownership of diff --git a/src/AddressSpace.h b/src/AddressSpace.h index 25785ad029f..b339dbfc003 100644 --- a/src/AddressSpace.h +++ b/src/AddressSpace.h @@ -752,6 +752,12 @@ class AddressSpace : public HasTaskSet { const std::vector& saved_auxv() { return saved_auxv_; } void save_auxv(Task* t); + remote_ptr saved_interpreter_base() { return saved_interpreter_base_; } + void save_interpreter_base(Task* t, std::vector auxv); + + std::string saved_ld_path() { return saved_ld_path_;} + void save_ld_path(Task* t, remote_ptr); + void read_mm_map(Task* t, struct prctl_mm_map* map); /** @@ -1123,6 +1129,8 @@ class AddressSpace : public HasTaskSet { int stopping_breakpoint_table_entry_size_; std::vector saved_auxv_; + remote_ptr saved_interpreter_base_; + std::string saved_ld_path_; /** * The time of the first event that ran code for a task in this address space. diff --git a/src/GdbServer.cc b/src/GdbServer.cc index d1896f3b099..109434b349c 100644 --- a/src/GdbServer.cc +++ b/src/GdbServer.cc @@ -1887,32 +1887,22 @@ static bool is_likely_interp(string fsname) { static remote_ptr base_addr_from_rendezvous(Task* t, string fname) { - std::vector auxv = t->vm()->saved_auxv(); - if (auxv.size() == 0 || (auxv.size() % sizeof(uint64_t) != 0)) { - // Corrupted or missing auxv + remote_ptr interpreter_base = t->vm()->saved_interpreter_base(); + if (!interpreter_base || !t->vm()->has_mapping(interpreter_base)) { return nullptr; } - remote_ptr interpreter_base = nullptr; - bool found = false; - for (size_t i = 0; i < (auxv.size() / sizeof(uint64_t)) - 1; i += 2) { - uint64_t* entry = ((uint64_t*)auxv.data())+i; - uint64_t kind = entry[0]; - uint64_t value = entry[1]; - if (kind == AT_BASE) { - interpreter_base = value; - found = true; - break; - } + string ld_path = t->vm()->saved_ld_path(); + if (ld_path.length() == 0) { + FATAL() << "Failed to retrieve interpreter name with interpreter_base=" << interpreter_base; } - if (!found || !t->vm()->has_mapping(interpreter_base)) { - return nullptr; - } - string ld_path = t->vm()->mapping_of(interpreter_base).map.fsname(); ScopedFd ld(ld_path.c_str(), O_RDONLY); + if (ld < 0) { + FATAL() << "Open failed: " << ld_path; + } ElfFileReader reader(ld); auto syms = reader.read_symbols(".dynsym", ".dynstr"); static const char r_debug[] = "_r_debug"; - found = false; + bool found = false; uintptr_t r_debug_offset = 0; for (size_t i = 0; i < syms.size(); ++i) { if (!syms.is_name(i, r_debug)) { diff --git a/src/util.cc b/src/util.cc index ea0918428f5..6b5f0490495 100644 --- a/src/util.cc +++ b/src/util.cc @@ -101,6 +101,31 @@ vector read_auxv(Task* t) { RR_ARCH_FUNCTION(read_auxv_arch, t->arch(), t); } +remote_ptr read_interpreter_base(std::vector auxv) { + if (auxv.size() == 0 || (auxv.size() % sizeof(uint64_t) != 0)) { + // Corrupted or missing auxv + return nullptr; + } + remote_ptr interpreter_base = nullptr; + for (size_t i = 0; i < (auxv.size() / sizeof(uint64_t)) - 1; i += 2) { + uint64_t* entry = ((uint64_t*)auxv.data())+i; + uint64_t kind = entry[0]; + uint64_t value = entry[1]; + if (kind == AT_BASE) { + interpreter_base = value; + break; + } + } + return interpreter_base; +} + +std::string read_ld_path(Task* t, remote_ptr interpreter_base) { + if (!interpreter_base || !t->vm()->has_mapping(interpreter_base)) { + return {}; + } + return t->vm()->mapping_of(interpreter_base).map.fsname(); +} + template void patch_auxv_vdso_arch(RecordTask* t) { auto stack_ptr = auxv_ptr(t); std::vector v = read_auxv_arch(t, stack_ptr); diff --git a/src/util.h b/src/util.h index ce3fc294e45..f7d289f12ab 100644 --- a/src/util.h +++ b/src/util.h @@ -51,6 +51,16 @@ enum Completion { COMPLETE, INCOMPLETE }; */ std::vector read_auxv(Task* t); +/** + * Returns the base address where the interpreter is mapped. + */ +remote_ptr read_interpreter_base(std::vector auxv); + +/** + * Returns a string containing the file name of the interpreter. + */ +std::string read_ld_path(Task* t, remote_ptr interpreter_base); + /** * Returns a vector containing the environment strings. */