From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27097 invoked by alias); 15 Dec 2014 02:58:07 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 27066 invoked by uid 440); 15 Dec 2014 02:58:03 -0000 Date: Mon, 15 Dec 2014 02:58:00 -0000 Message-ID: <20141215025802.26991.qmail@sourceware.org> From: scox@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] scox/dyninst: Support shared libraries. X-Git-Refname: refs/heads/scox/dyninst X-Git-Reftype: branch X-Git-Oldrev: bc5aece835a317ef016557d57a6a32178091d821 X-Git-Newrev: 02afeed30a601bea111805ef89f3c6a27dd59ad9 X-SW-Source: 2014-q4/txt/msg00003.txt.bz2 List-Id: The branch, scox/dyninst has been updated via 02afeed30a601bea111805ef89f3c6a27dd59ad9 (commit) from bc5aece835a317ef016557d57a6a32178091d821 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 02afeed30a601bea111805ef89f3c6a27dd59ad9 Author: Stan Cox Date: Sun Dec 14 21:54:41 2014 -0500 Support shared libraries. * configure.srv (*dyninst*): Use *linux_xmlfiles. * dyninst-low.cc (library_handler): New. * (dyninst_attach): Add shared libraries. (dyninst_read_auxv): New. (dyninst_qxfer_libraries_svr4): New for adding shared libraries. * dyninst-x85-low.cc (dyninst_x86_fill_gregset): Mark filled registers as valid. ----------------------------------------------------------------------- Summary of changes: gdb/gdbserver/configure.srv | 4 +- gdb/gdbserver/dyninst-low.cc | 224 +++++++++++++++++++++++++++++++++----- gdb/gdbserver/dyninst-x86-low.cc | 20 +++- 3 files changed, 212 insertions(+), 36 deletions(-) First 500 lines of diff: diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv index bb68ded..24c4306 100644 --- a/gdb/gdbserver/configure.srv +++ b/gdb/gdbserver/configure.srv @@ -104,12 +104,12 @@ case "${target}" in ;; i[34567]86-dyninst-linux*) srv_regobj="$srv_i386_regobj" srv_tgtobj="dyninst-low.o dyninst-x86-low.o" - srv_xmlfiles="$srv_i386_xmlfiles" + srv_xmlfiles="$srv_i386__linux_xmlfiles" srv_dyninst=yes ;; x86_64-dyninst-linux*) srv_regobj="$srv_amd64_regobj $srv_i386_regobj" srv_tgtobj="dyninst-low.o dyninst-x86-low.o" - srv_xmlfiles="$srv_i386_xmlfiles $srv_amd64_xmlfiles" + srv_xmlfiles="$srv_i386_linux_xmlfiles $srv_amd64_linux_xmlfiles" srv_dyninst=yes ;; i[34567]86-*-linux*) srv_regobj="$srv_i386_linux_regobj" diff --git a/gdb/gdbserver/dyninst-low.cc b/gdb/gdbserver/dyninst-low.cc index 018fa61..39747ac 100644 --- a/gdb/gdbserver/dyninst-low.cc +++ b/gdb/gdbserver/dyninst-low.cc @@ -19,6 +19,7 @@ extern "C" { #include "server.h" #include "target.h" +#include "dll.h" #include #include @@ -30,6 +31,8 @@ extern "C" #include #include #include +#include +#include } #include @@ -41,6 +44,7 @@ extern "C" #include "dyninst-low.h" #include #include +#include #define DEBUG(func,cerrstr,args...) \ if (debug_threads) { \ @@ -58,6 +62,8 @@ using namespace ProcControlAPI; typedef std::vector BreakpointSet; BreakpointSet dyninst_bpset; ProcessSet::ptr dyninst_procset; +typedef std::vector LibrarySet; +LibrarySet dyninst_libset; Thread::const_ptr NULL_Thread = Thread::const_ptr(); @@ -136,7 +142,7 @@ public: { event = *rit; - if (event->getProcess()->getPid() == ptid.pid) + if (ptid.pid == -1 || event->getProcess()->getPid() == ptid.pid) { DEBUG("events.get","returning event " << event->name()); return event; @@ -187,14 +193,16 @@ public: bool is_threadcreate (Event::const_ptr event) { if (event != NULL) - return event->getEventType().code() == EventType::ThreadCreate; + DEBUG("is_threadcreate", event->getEventType().code() << EventType::LWPCreate); + if (event != NULL) + return event->getEventType().code() == EventType::LWPCreate; else return false; } bool is_threaddestroy(Event::const_ptr event) { if (event != NULL) - return event->getEventType().code() == EventType::ThreadDestroy; + return event->getEventType().code() == EventType::UserThreadDestroy; else return false; } @@ -329,7 +337,7 @@ dyninst_get_inferior_thread() { DEBUG("dyninst_get_inferior_thread", "current_thread=" << current_thread); struct thread_info_private *tip = (struct thread_info_private*)(current_thread->target_data); - DEBUG("dyninst_get_inferior_thread", "", pid_to_string (tip->thread)); + DEBUG("dyninst_get_inferior_thread", "", pid_to_string (current_thread->entry.id)); if (!tip) error ("No inferior thread"); return tip->thread; @@ -353,12 +361,30 @@ Process::cb_ret_t singlestep_handler(Event::const_ptr ev) { events.insert(ev); - DEBUG("signal_handler", ev->name()); + DEBUG("singlestep_handler", ev->name()); ev->getThread()->setSingleStepMode(false); return Process::cbThreadStop; } +/* Handle a dyninst Library event */ + +Process::cb_ret_t +library_handler(Event::const_ptr ev) +{ + EventLibrary::const_ptr lib_ev = ev->getEventLibrary(); + + for (set::const_iterator i = lib_ev->libsAdded().begin(); i != lib_ev->libsAdded().end(); i++) + { + Library::ptr lib = *i; + DEBUG("dyninst_attach", "added library " << lib->getAbsoluteName() << " " << lib->getDynamicAddress() << " " << lib->getLoadAddress() << endl); +// loaded_dll (lib->getAbsoluteName().c_str(), lib->getDynamicAddress()); + } + + return Process::cbDefault; +} + + void myregisterCB(EventType et, Process::cb_func_t f) { @@ -396,7 +422,7 @@ dyninst_create_inferior (char *program, char **allargs) myregisterCB(EventType::Exec, signal_handler); myregisterCB(EventType::Exit, signal_handler); myregisterCB(EventType::Fork, signal_handler); -// myregisterCB(EventType::Library, signal_handler); + myregisterCB(EventType::Library, library_handler); myregisterCB(EventType::RPC, signal_handler); myregisterCB(EventType::Signal, signal_handler); myregisterCB(EventType::SingleStep, singlestep_handler); @@ -405,6 +431,7 @@ dyninst_create_inferior (char *program, char **allargs) myregisterCB(EventType::ThreadCreate, signal_handler); myregisterCB(EventType::ThreadDestroy, signal_handler); myregisterCB(EventType::UserThreadCreate, signal_handler); + myregisterCB(EventType::UserThreadDestroy, signal_handler); DEBUG("dyninst_create_inferior", "created process " << dyninst_process->getPid() << program); @@ -464,6 +491,14 @@ dyninst_attach (unsigned long pid) dyninst_add_thread (pid, th); } + LibraryPool::iterator libidx; + for (libidx = dyninst_proc->libraries().begin(); libidx != dyninst_proc->libraries().end(); libidx++) + { + Library::ptr lib = *libidx; + DEBUG("dyninst_attach", "added library " << lib->getName() << " " << lib->getDynamicAddress() << " " << lib->getLoadAddress() << endl); +// loaded_dll (lib->getAbsoluteName().c_str(), lib->getDynamicAddress()); + } + return 0; } @@ -562,24 +597,23 @@ in_step_range () static ptid_t dyninst_wait_1 (ptid_t ptid, struct target_waitstatus *status, int options) { - Dyninst::PID pid = 0; - ptid_t new_ptid; + ptid_t new_ptid = ptid; + Dyninst::PID pid = ptid.pid; DEBUG("dyninst_wait_1", "", pid_to_string (ptid)); - if (ptid_equal (ptid, minus_one_ptid)) - { - pid = ptid_get_pid (thread_to_gdb_id (current_thread)); - new_ptid = ptid_build (pid, pid, 0); - } - else - { - pid = ptid_get_pid(ptid); - new_ptid = ptid; - } - - ProcessSet::iterator procset_it = dyninst_procset->find(pid); - Process::ptr dyninst_process = *procset_it; +// if (ptid_equal (ptid, minus_one_ptid)) +// { +// pid = ptid_get_pid (thread_to_gdb_id (current_thread)); +// new_ptid = ptid_build (pid, pid, 0); +// } +// else +// { +// pid = ptid_get_pid(ptid); +// new_ptid = ptid; +// } +// ProcessSet::iterator procset_it = dyninst_procset->find(pid); +// Process::ptr dyninst_process = *procset_it; Event::const_ptr event; @@ -589,6 +623,8 @@ dyninst_wait_1 (ptid_t ptid, struct target_waitstatus *status, int options) if ((event = events.get(new_ptid))) { struct process_info *pi; + pid = event->getProcess()->getPid(); + new_ptid = ptid_build (pid, pid, 0); pi = find_process_pid(pid); if (pi) pi->piprivate->last_wait_event_ptid = new_ptid; @@ -596,19 +632,20 @@ dyninst_wait_1 (ptid_t ptid, struct target_waitstatus *status, int options) if (event == NULL) event = events.get(new_ptid); - events.dump(); +// events.dump(); if (events.is_threadcreate(event)) { Thread::const_ptr thr; -// if (event != events.NULL_Event) + EventNewLWP::const_ptr newlwp_ev = event->getEventNewLWP(); if (event != NULL) - thr = event->getThread(); + thr = newlwp_ev->getNewThread(); else thr = NULL_Thread; - DEBUG("dyninst_wait_1", "New thread: ", pid_to_string (ptid)); + DEBUG("dyninst_wait_1", "New thread: " << event->getThread()->getLWP() << " " << thr->getLWP(), pid_to_string (new_ptid)); dyninst_add_thread (pid, thr); + return new_ptid; } else if (events.is_exit(event)) { @@ -666,8 +703,9 @@ dyninst_wait_1 (ptid_t ptid, struct target_waitstatus *status, int options) break; } - DEBUG("dyninst_wait_1 returning", "", pid_to_string (ptid)); - return new_ptid; + DEBUG("dyninst_wait_1 returning", "", pid_to_string (ptid_of(current_thread))); + return ptid_of (current_thread); +// return new_ptid; } @@ -692,6 +730,8 @@ dyninst_kill (Dyninst::PID pid) { struct process_info *process; ProcessSet::iterator procset_it = dyninst_procset->find(pid); + if (procset_it == dyninst_procset->end()) + return 1; Process::ptr dyninst_process = *procset_it; DEBUG("dyninst_kill", "pid=" << pid); @@ -871,6 +911,34 @@ dyninst_request_interrupt (void) } +/* Copy LEN bytes from inferior's auxiliary vector starting at OFFSET + to debugger memory starting at MYADDR. */ + +static int +dyninst_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len) +{ + char filename[PATH_MAX]; + int fd, n; + int pid = lwpid_of (current_thread); + + xsnprintf (filename, sizeof filename, "/proc/%d/auxv", pid); + + fd = open (filename, O_RDONLY); + if (fd < 0) + return -1; + + if (offset != (CORE_ADDR) 0 + && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset) + n = -1; + else + n = read (fd, myaddr, len); + + close (fd); + + return n; +} + + /* Breakpoint/Watchpoint support. */ static int @@ -917,7 +985,7 @@ dyninst_remove_point (enum raw_bkpt_type type, CORE_ADDR addr, int len, Process::const_ptr dyninst_process = th->getProcess(); std::vector::iterator it; - bool result; + bool result = false; for (it = dyninst_bpset.begin(); it != dyninst_bpset.end(); it++) { Breakpoint::ptr bp = *it; @@ -943,6 +1011,102 @@ dyninst_supports_range_stepping (void) } +static int +dyninst_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf, + unsigned const char *writebuf, + CORE_ADDR offset, int len) +{ +#include // std::string +#include // std::cout +#include // std::ostringstream + + // + // + // + // + + Thread::const_ptr th = dyninst_get_inferior_thread(); + Process::const_ptr dyninst_proc = th->getProcess(); + + string document = ""; + +// Dyninst::PID pid = ptid_get_pid (thread_to_gdb_id (current_thread)); +// ProcessSet::iterator procset_it = dyninst_procset->find(pid); +// Process::ptr dyninst_proc = *procset_it; + + LibraryPool::const_iterator libidx; + bool first = true; + for (libidx = dyninst_proc->libraries().begin(); libidx != dyninst_proc->libraries().end(); libidx++) + { + Library::const_ptr lib = *libidx; + if (first) + { + first = false; + continue; + } + DEBUG("dyninst_qxfer_libraries_svr4", "added library " << lib->getName() << " " << lib->getDynamicAddress() << " " << lib->getLoadAddress() << endl); + // loaded_dll (lib->getAbsoluteName().c_str(), lib->getDynamicAddress()); + std::ostringstream oss; + + oss << "getAbsoluteName() + << "\" lm=\"0x0\" " + << "l_addr=\"0x0\" " + << "l_ld=\"" << hex << lib->getDynamicAddress() << "\"/>"; + document += oss.str(); + } + document += ""; + document.copy((char*)readbuf, document.length()); + readbuf[document.length()]='\0'; + + return document.length(); +} + + +// Return non-zero if HEADER is a 64-bit ELF file. (from linux-low) + +#if 0 +static int +elf_64_header_p (const Elf64_Ehdr *header, unsigned int *machine) +{ + if (header->e_ident[EI_MAG0] == ELFMAG0 + && header->e_ident[EI_MAG1] == ELFMAG1 + && header->e_ident[EI_MAG2] == ELFMAG2 + && header->e_ident[EI_MAG3] == ELFMAG3) + { + *machine = header->e_machine; + return header->e_ident[EI_CLASS] == ELFCLASS64; + + } + *machine = EM_NONE; + return -1; +} + +// Return non-zero if FILE is a 64-bit ELF file, +// zero if the file is not a 64-bit ELF file, +// and -1 if the file is not accessible or doesn't exist. + +static int +elf_64_file_p (const char *file, unsigned int *machine) +{ + Elf64_Ehdr header; + int fd; + + fd = open (file, O_RDONLY); + if (fd < 0) + return -1; + + if (read (fd, &header, sizeof (header)) != sizeof (header)) + { + close (fd); + return 0; + } + close (fd); + + return elf_64_header_p (&header, machine); +} +#endif + + /* The Dyninst target_ops vector. */ static struct target_ops dyninst_target_ops = { @@ -963,7 +1127,7 @@ static struct target_ops dyninst_target_ops = { dyninst_write_memory, NULL, /* look_up_symbols */ dyninst_request_interrupt, - NULL, /* read_auxv */ + dyninst_read_auxv, dyninst_supports_z_point_type, dyninst_insert_point, /* insert_point */ dyninst_remove_point, /* remove_point */ @@ -996,7 +1160,7 @@ static struct target_ops dyninst_target_ops = { NULL, // emit_ops NULL, // supports_disable_randomization NULL, // get_min_fast_tracepoint_insn_len - NULL, // qxfer_libraries_svr4 + dyninst_qxfer_libraries_svr4, // qxfer_libraries_svr4 NULL, // supports_agent NULL, NULL, diff --git a/gdb/gdbserver/dyninst-x86-low.cc b/gdb/gdbserver/dyninst-x86-low.cc index 695eddf..fa60b03 100644 --- a/gdb/gdbserver/dyninst-x86-low.cc +++ b/gdb/gdbserver/dyninst-x86-low.cc @@ -38,8 +38,6 @@ extern "C" static std::ostringstream dboss; - -// TODO improve this std::map dyninst_x86_gdb_regnum; extern "C" @@ -104,6 +102,7 @@ dyninst_x86_fill_gregset (struct regcache *regcache, RegisterPool regpool) MachRegisterVal regval = (MachRegisterVal)((*regidx).second); const char *regstr; + regcache->register_status[regn] = REG_VALID; switch (register_size (regcache->tdesc, regn)) { case 2: @@ -183,14 +182,27 @@ dyninst_x86_store_gregset (struct regcache *regcache, RegisterPool regpool) static void dyninst_x86_fill_fpregset (struct regcache *regcache, RegisterPool regpool) { - dyninst_debug("dyninst_x86_fill_fpregset\n"); + // supported by dyninst + // rax rbp rbx rcx rdi rdx rip rsi rsp + // r8 - r15 + // ds es fs gs cs ss flags orax fsbase gsbase + + // supported by dyninst but not in register pool (RegisterConversion-x86.C) + // xmm0 - xmm15 + // TODO support xmm registers + + // not supported by dyninst + // fctrl fioff fiseg fooff fop foseg fstat ftag mxcsr + // st0 - st7 + dyninst_debug("dyninst_x86_fill_fpregset: dyninst does not support floating registers.\n"); +// result = th->getRegister(MachRegister(x86_64::xmm0), rspval); } static void dyninst_x86_store_fpregset (struct regcache *regcache, RegisterPool regpool) { - dyninst_debug("dyninst_x86_store_fpregset %#lx\n", regcache); + dyninst_debug("dyninst_x86_store_fpregset: dyninst does not support floating registers.\n", regcache); } hooks/post-receive -- Repository for Project Archer.