addrtranslate-linux.C
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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>
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 , MachRegisterVal &) { 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
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
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 }