addrtranslate-linux.C

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 #include "common/h/addrtranslate.h"
00032 #include "common/src/addrtranslate-sysv.h"
00033 #include "common/h/linuxKludges.h"
00034 #include "common/h/parseauxv.h"
00035 #include "common/h/pathName.h"
00036 
00037 #include <elf.h>
00038 #include <cstdio>
00039 #include <linux/limits.h>
00040 
00041 #include <sys/ptrace.h>
00042 #include <sys/types.h>
00043 #include <sys/wait.h>
00044 #include <errno.h>
00045 #include <unistd.h> // for getpid()
00046 
00047 
00048 using namespace Dyninst;
00049 
00050 class ProcessReaderPtrace : public ProcessReader {
00051    int pid;
00052 public:
00053    ProcessReaderPtrace(int pid_);
00054    virtual bool start();
00055    virtual bool ReadMem(Address inTraced, void *inSelf, unsigned amount);
00056    virtual bool GetReg(MachRegister /*reg*/, MachRegisterVal &/*val*/) { assert(0); }
00057    virtual bool done();
00058 
00059    virtual ~ProcessReaderPtrace();
00060 };
00061 
00062 bool ProcessReaderPtrace::start()
00063 {
00064    long result;
00065    bool is_attached = false;
00066 
00067    result = ptrace(PTRACE_ATTACH, pid, NULL, NULL);
00068    if (result == -1)
00069       goto done;
00070    is_attached = true;
00071    
00072    int status;
00073    for (;;) {
00074       result = (long) waitpid(pid, &status, 0);
00075       if (result == -1 && errno == EINTR)
00076          continue;
00077       else if (result == -1)
00078          goto done;
00079       else if (WIFEXITED(status) || WIFSIGNALED(status))
00080          goto done;
00081       else if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP)
00082          break;
00083       else if (WIFSTOPPED(status) && WSTOPSIG(status) != SIGSTOP) {
00084          result = ptrace(PTRACE_CONT, pid, NULL, (void *) (long) WSTOPSIG(status));
00085          if (result == -1)
00086             goto done;
00087       }
00088    }
00089 
00090    result = true;
00091 done:
00092    if (!result && is_attached)
00093       done();
00094    return result;
00095 }
00096 
00097 bool ProcessReaderPtrace::done()
00098 {
00099    long result;
00100    result = ptrace(PTRACE_DETACH, pid, NULL, NULL);
00101    if (result == -1)
00102       return false;
00103    return true;
00104 }
00105 
00106 ProcessReaderPtrace::ProcessReaderPtrace(int pid_) :
00107    pid(pid_)
00108 {
00109 }
00110 
00111 ProcessReaderPtrace::~ProcessReaderPtrace() 
00112 {
00113 }
00114 
00115 bool ProcessReaderPtrace::ReadMem(Address inTraced, void *inSelf, unsigned amount)
00116 {
00117    bool result;
00118    result = PtraceBulkRead(inTraced, amount, inSelf, pid);
00119    return result;
00120 }
00121 
00122 ProcessReader *AddressTranslateSysV::createDefaultDebugger(int pid)
00123 {
00124   return new ProcessReaderPtrace(pid);
00125 }
00126 
00127 bool AddressTranslateSysV::setInterpreter()
00128 {
00129    bool result;
00130 
00131    if (interpreter)
00132       return true;
00133 
00134    string sname = getExecName();
00135    string interp_name;
00136 
00137    FCNode *exe = files.getNode(sname, symfactory);
00138    if (!exe) {
00139       result = false;
00140       goto done;
00141    }
00142 
00143    interp_name = exe->getInterpreter();
00144    interpreter = files.getNode(interp_name, symfactory);
00145    if (interpreter)
00146       interpreter->markInterpreter();
00147    result = true;
00148 
00149  done:
00150    return result;
00151 }
00152 
00153 bool AddressTranslateSysV::setAddressSize() 
00154 {
00155    bool result;
00156    if (address_size)
00157       return true;
00158 
00159    result = setInterpreter();
00160    if (!result)
00161       return false;
00162 
00163    if (interpreter)
00164       address_size = interpreter->getAddrSize();
00165    else if (pid == getpid()) {
00166       address_size = sizeof(void *);
00167       return true;
00168    }
00169    else {
00170       char name[64];
00171       sprintf(name, "/proc/%d/exe", pid);
00172       string sname(name);
00173       FCNode *exe = files.getNode(sname, symfactory);
00174       if (!exe) 
00175          return false;
00176       address_size = exe->getAddrSize();
00177       if (!address_size)
00178         return false;
00179    }
00180       
00181    return true;
00182 }
00183 
00184 string AddressTranslateSysV::getExecName() 
00185 {
00186    if (exec_name.empty()) {
00187       char name[64];
00188       snprintf(name, 64, "/proc/%d/exe", pid);
00189       exec_name = resolve_file_path(name);
00190    }
00191    return exec_name;
00192 }
00193 
00194 #include <iostream>
00195 using namespace std;
00196 
00197 LoadedLib *AddressTranslateSysV::getAOut()
00198 {
00199    if (exec)
00200       return exec;
00201 
00202    //
00203    // 
00204 
00205    // Get the base address
00206    Address baseAddr = 0;
00207    if (program_base && reader) {
00208       bool done = false;
00209       Address phdr_vaddr = (Address) -1;
00210       Address load_vaddr = (Address) -1;
00211       Address header_addr = program_base;
00212 
00213       while (!done) {
00214          Address p_vaddr;
00215          unsigned type;
00216          if (address_size == 4) {
00217             Elf32_Phdr header;
00218             if (!reader->ReadMem(header_addr, &header, sizeof(Elf32_Phdr))) {
00219                break;
00220             }
00221             p_vaddr = header.p_vaddr;
00222             type = header.p_type;
00223             header_addr += sizeof(Elf32_Phdr);
00224          }
00225          else {
00226             Elf64_Phdr header;
00227             if (!reader->ReadMem(header_addr, &header, sizeof(Elf64_Phdr))) {
00228                break;
00229             }
00230             p_vaddr = header.p_vaddr;
00231             type = header.p_type;
00232             header_addr += sizeof(Elf64_Phdr);
00233          }
00234          switch (type) {
00235             case PT_PHDR:
00236                phdr_vaddr = p_vaddr;
00237                break;
00238             case PT_LOAD:
00239                if (load_vaddr == (Address) -1) {
00240                   load_vaddr = p_vaddr;
00241                }
00242                break;
00243             case PT_NULL:
00244             case PT_DYNAMIC:
00245             case PT_INTERP:
00246             case PT_NOTE:
00247             case PT_SHLIB:
00248             case PT_TLS:
00249                break;
00250             default:
00251                done = true;
00252          }
00253          if (phdr_vaddr != (Address) -1 &&
00254              load_vaddr != (Address) -1) {
00255             done = true;
00256          }
00257       }
00258       if (load_vaddr != 0) {
00259          baseAddr = 0;
00260       }
00261       else {
00262          // PIE binary, find it
00263          assert(phdr_vaddr != (Address) -1);
00264          baseAddr = program_base - phdr_vaddr;
00265       }
00266    }         
00267 
00268    LoadedLib *ll = new LoadedLib(getExecName(), baseAddr);
00269    ll->setFactory(symfactory);
00270    exec = ll;
00271    return ll;
00272 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1