Skip to content

Commit

Permalink
Save interpreter_base and ld_path at AddressSpace construction.
Browse files Browse the repository at this point in the history
This aids compatibility with GDB 10.1.
Related issue rr-debugger#2740.
  • Loading branch information
bernhardu committed Nov 19, 2020
1 parent 6658bdd commit 18cde5c
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 20 deletions.
16 changes: 15 additions & 1 deletion src/AddressSpace.cc
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,19 @@ vector<AddressSpace::SyscallType> 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<uint8_t> auxv) {
saved_interpreter_base_ = read_interpreter_base(auxv);
save_ld_path(t, saved_interpreter_base());
}

void AddressSpace::save_ld_path(Task* t, remote_ptr<void> 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];
Expand Down Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions src/AddressSpace.h
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,12 @@ class AddressSpace : public HasTaskSet {
const std::vector<uint8_t>& saved_auxv() { return saved_auxv_; }
void save_auxv(Task* t);

remote_ptr<void> saved_interpreter_base() { return saved_interpreter_base_; }
void save_interpreter_base(Task* t, std::vector<uint8_t> auxv);

std::string saved_ld_path() { return saved_ld_path_;}
void save_ld_path(Task* t, remote_ptr<void>);

void read_mm_map(Task* t, struct prctl_mm_map* map);

/**
Expand Down Expand Up @@ -1123,6 +1129,8 @@ class AddressSpace : public HasTaskSet {
int stopping_breakpoint_table_entry_size_;

std::vector<uint8_t> saved_auxv_;
remote_ptr<void> saved_interpreter_base_;
std::string saved_ld_path_;

/**
* The time of the first event that ran code for a task in this address space.
Expand Down
28 changes: 9 additions & 19 deletions src/GdbServer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1887,32 +1887,22 @@ static bool is_likely_interp(string fsname) {

static remote_ptr<void> base_addr_from_rendezvous(Task* t, string fname)
{
std::vector<uint8_t> auxv = t->vm()->saved_auxv();
if (auxv.size() == 0 || (auxv.size() % sizeof(uint64_t) != 0)) {
// Corrupted or missing auxv
remote_ptr<void> interpreter_base = t->vm()->saved_interpreter_base();
if (!interpreter_base || !t->vm()->has_mapping(interpreter_base)) {
return nullptr;
}
remote_ptr<void> 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)) {
Expand Down
25 changes: 25 additions & 0 deletions src/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,31 @@ vector<uint8_t> read_auxv(Task* t) {
RR_ARCH_FUNCTION(read_auxv_arch, t->arch(), t);
}

remote_ptr<void> read_interpreter_base(std::vector<uint8_t> auxv) {
if (auxv.size() == 0 || (auxv.size() % sizeof(uint64_t) != 0)) {
// Corrupted or missing auxv
return nullptr;
}
remote_ptr<void> 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<void> interpreter_base) {
if (!interpreter_base || !t->vm()->has_mapping(interpreter_base)) {
return {};
}
return t->vm()->mapping_of(interpreter_base).map.fsname();
}

template <typename Arch> void patch_auxv_vdso_arch(RecordTask* t) {
auto stack_ptr = auxv_ptr<Arch>(t);
std::vector<uint8_t> v = read_auxv_arch<Arch>(t, stack_ptr);
Expand Down
10 changes: 10 additions & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ enum Completion { COMPLETE, INCOMPLETE };
*/
std::vector<uint8_t> read_auxv(Task* t);

/**
* Returns the base address where the interpreter is mapped.
*/
remote_ptr<void> read_interpreter_base(std::vector<uint8_t> auxv);

/**
* Returns a string containing the file name of the interpreter.
*/
std::string read_ld_path(Task* t, remote_ptr<void> interpreter_base);

/**
* Returns a vector containing the environment strings.
*/
Expand Down

0 comments on commit 18cde5c

Please sign in to comment.