addrtranslate-sysv.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 <assert.h>
00032 #include <link.h>
00033 #include <stdio.h>
00034 #include <errno.h>
00035 #include <sys/types.h>
00036 #include <sys/wait.h>
00037 #include <string.h>
00038 
00039 #include <sys/types.h>
00040 #include <sys/stat.h>
00041 #include <unistd.h>
00042 #include <fcntl.h>
00043 #include <limits.h>
00044 
00045 #include <vector>
00046 #include <string>
00047 
00048 #include <iostream>
00049 
00050 #include "common/h/parseauxv.h"
00051 #include "common/h/headers.h"
00052 #include "common/h/pathName.h"
00053 
00054 #include "common/h/addrtranslate.h"
00055 #include "common/src/addrtranslate-sysv.h"
00056 
00057 #if defined(os_linux) || defined(os_bg)
00058 #define R_DEBUG_NAME "_r_debug"
00059 #else
00060 #define R_DEBUG_NAME "r_debug"
00061 #endif
00062 
00063 #if defined(os_linux)
00064 #include "common/h/linuxKludges.h"
00065 #endif
00066 
00067 using namespace std;
00068 using namespace Dyninst;
00069 
00070 FileCache Dyninst::files;
00071 
00072 
00073 class ProcessReaderSelf : public ProcessReader {
00074 public:
00075    ProcessReaderSelf();
00076    bool start();
00077    bool ReadMem(Address inTraced, void *inSelf, unsigned amount);
00078    bool GetReg(MachRegister reg, MachRegisterVal &val);
00079    bool done();
00080 
00081   virtual ~ProcessReaderSelf();
00082 };
00083 
00084 struct link_map_dyn32
00085 {
00086    Elf32_Addr l_addr;
00087    uint32_t l_name;
00088    uint32_t l_ld;
00089    uint32_t l_next, l_prev;
00090 };
00091 
00092 struct r_debug_dyn32
00093 {
00094     int r_version;
00095     uint32_t r_map;
00096     Elf32_Addr r_brk;
00097     enum
00098     {
00099        RT_CONSISTENT,
00100        RT_ADD,
00101        RT_DELETE
00102     } r_state;
00103     Elf32_Addr r_ldbase;
00104 };
00105 
00106 class link_map_xplat 
00107 {
00108 public:
00109    virtual size_t size() = 0;
00110    virtual uint64_t l_addr() = 0;
00111    virtual char *l_name() = 0;
00112    virtual void *l_ld() = 0;
00113    virtual bool is_last() = 0;
00114    virtual bool load_next() = 0;   
00115    virtual bool is_valid() = 0;   
00116    virtual bool load_link(Address addr) = 0;
00117    virtual ~link_map_xplat() {};
00118 };
00119 
00120 template<class link_map_X> 
00121 class link_map_dyn : public link_map_xplat 
00122 {
00123 public: 
00124    link_map_dyn(ProcessReader *proc_, Address addr);
00125    ~link_map_dyn();
00126    virtual size_t size();
00127    virtual uint64_t l_addr();
00128    virtual char *l_name();
00129    virtual void *l_ld();
00130    virtual bool is_last();
00131    virtual bool load_next();   
00132    virtual bool is_valid();   
00133    virtual bool load_link(Address addr);
00134 
00135 protected:
00136    ProcessReader *proc;
00137    char link_name[256];
00138    bool loaded_name;
00139    bool valid;
00140    link_map_X link_elm;
00141 };
00142 
00143 template<class r_debug_X> 
00144 class r_debug_dyn {
00145 public:
00146    r_debug_dyn(ProcessReader *proc_, Address addr);
00147    ~r_debug_dyn();
00148    void *r_brk();
00149    Address r_map();
00150    int r_state();
00151    bool is_valid();
00152 protected:
00153    ProcessReader *proc;
00154    bool valid;
00155    r_debug_X debug_elm;
00156 };
00157 
00158 template<class r_debug_X> 
00159 r_debug_dyn<r_debug_X>::r_debug_dyn(ProcessReader *proc_, Address addr)
00160    : proc(proc_) 
00161 {
00162   translate_printf("r_debug_dyn constructor, reading from 0x%lx\n", addr);
00163    valid = proc->ReadMem(addr, &debug_elm, sizeof(debug_elm));
00164    if (!valid) {
00165      translate_printf("\t Warning: read failed, setting not valid\n");
00166      return;
00167    }
00168 
00169    translate_printf("r_debug_dyn valid = %d\n",  valid?1:0);
00170    translate_printf("    Read rdebug structure.  Values were:\n", __FILE__, __LINE__);
00171    translate_printf("      r_brk:    %lx\n",  (unsigned long)debug_elm.r_brk);
00172    translate_printf("      r_map:    %lx\n",  (unsigned long)debug_elm.r_map);
00173 #if !defined(os_freebsd)
00174    translate_printf("      r_ldbase: %lx\n",  (unsigned long)debug_elm.r_ldbase);
00175 #endif
00176 }
00177 
00178 template<class r_debug_X> 
00179 r_debug_dyn<r_debug_X>::~r_debug_dyn() 
00180 {
00181 }
00182 
00183 template<class r_debug_X> 
00184 bool r_debug_dyn<r_debug_X>::is_valid() {
00185   if (!valid) {
00186     translate_printf("\tr_debug_dyn::is_valid ret false\n");
00187     return false;
00188   }
00189   if (0 == r_map()) {
00190     translate_printf("\tr_debug_dyn::is_valid; r_map() == 0, ret false\n");
00191     return false;
00192   }
00193 
00194   translate_printf("\tr_debug_dyn::is_valid; valid == %s, ret %s\n", 
00195            (valid ? "true" : "false"),
00196            (valid ? "true" : "false"));
00197   return valid;
00198 }
00199 
00200 template<class r_debug_X> 
00201 Address r_debug_dyn<r_debug_X>::r_map() {
00202     return (Address) debug_elm.r_map;
00203 }
00204 
00205 template<class r_debug_X> 
00206 void *r_debug_dyn<r_debug_X>::r_brk() { 
00207    return reinterpret_cast<void *>(debug_elm.r_brk); 
00208 }
00209 
00210 template<class r_debug_X> 
00211 int r_debug_dyn<r_debug_X>::r_state() { 
00212    return (int)debug_elm.r_state; 
00213 }
00214  
00215 template<class link_map_X>
00216 link_map_dyn<link_map_X>::link_map_dyn(ProcessReader *proc_, Address addr_) :
00217    proc(proc_),
00218    loaded_name(false)
00219 {
00220    valid = load_link(addr_);
00221 }
00222 
00223 template<class link_map_X>
00224 link_map_dyn<link_map_X>::~link_map_dyn() {
00225 }
00226 
00227 template<class link_map_X>
00228 bool link_map_dyn<link_map_X>::is_valid() {
00229    return valid;
00230 }
00231 
00232 template<class link_map_X>
00233 size_t link_map_dyn<link_map_X>::size()
00234 {
00235    return sizeof(link_elm);
00236 }
00237 
00238 template<class link_map_X>
00239 uint64_t link_map_dyn<link_map_X>::l_addr() 
00240 {
00241    return (uint64_t)link_elm.l_addr;
00242 }
00243 
00244 template<class link_map_X>
00245 char *link_map_dyn<link_map_X>::l_name() 
00246 {
00247   if (loaded_name) return link_name;
00248 
00249   for (unsigned int i = 0; i < sizeof(link_name); ++i) {
00250      if (!proc->ReadMem((Address) (link_elm.l_name + i),
00251                         link_name + i, sizeof(char)))
00252      {
00253         valid = false;
00254         return NULL;
00255      }
00256      if (link_name[i] == '\0') break;
00257   }
00258   link_name[sizeof(link_name) - 1] = '\0';
00259 
00260   loaded_name = true;  
00261   return link_name;
00262 }
00263 
00264 template<class link_map_X>
00265 void *link_map_dyn<link_map_X>::l_ld() 
00266 { 
00267    return const_cast<void *>(reinterpret_cast<const void *>(link_elm.l_ld)); 
00268 }
00269 
00270 template<class link_map_X>
00271 bool link_map_dyn<link_map_X>::is_last() 
00272 { 
00273    return (link_elm.l_next == 0); 
00274 }
00275 
00276 template<class link_map_X>
00277 bool link_map_dyn<link_map_X>::load_next() 
00278 {
00279     if (is_last()) {
00280       return false;
00281    }
00282     if (load_link((Address) link_elm.l_next)) {
00283       loaded_name = false;
00284       return true;
00285     }
00286     return false;
00287 }
00288 
00289 template<class link_map_X>
00290 bool link_map_dyn<link_map_X>::load_link(Address addr) 
00291 {
00292    return proc->ReadMem(addr, &link_elm, sizeof(link_elm));
00293 }
00294 
00295 static const char *deref_link(const char *path)
00296 {
00297    static char buffer[PATH_MAX], *p;
00298    buffer[PATH_MAX-1] = '\0';
00299    p = realpath(path, buffer);
00300    if (!p)
00301       return path;
00302    return p;
00303 }
00304 
00305 
00306 ProcessReaderSelf::ProcessReaderSelf() :
00307    ProcessReader() 
00308 {
00309 }
00310 
00311 ProcessReaderSelf::~ProcessReaderSelf()
00312 {
00313 }
00314 
00315 bool ProcessReaderSelf::start() {
00316    return true;
00317 }
00318 
00319 bool ProcessReaderSelf::done() {
00320    return true;
00321 }
00322 
00323 bool ProcessReaderSelf::ReadMem(Address inTraced, void *inSelf, unsigned amount)
00324 {
00325    memcpy(inSelf, (void *) inTraced, amount);
00326    return true;
00327 }
00328 
00329 bool ProcessReaderSelf::GetReg(MachRegister /*reg*/, MachRegisterVal &/*val*/)
00330 {
00331    assert(0);
00332    return false;
00333 }
00334 
00335 
00336 vector< pair<Address, unsigned long> > *LoadedLib::getMappedRegions()
00337 {
00338    if (mapped_regions.size())
00339    {
00340       return &mapped_regions;
00341    }
00342 
00343    FCNode *fc = files.getNode(name, symreader_factory);
00344    if (!fc)
00345       return false;
00346 
00347    vector<SymSegment> segs;
00348    fc->getSegments(segs);
00349    
00350    for (unsigned i=0; i<segs.size(); i++) {
00351       pair<Address, unsigned long> p(load_addr + segs[i].mem_addr, 
00352                                      segs[i].mem_size);
00353       mapped_regions.push_back(p);
00354    }
00355    
00356    return &mapped_regions;
00357 }
00358 
00359 AddressTranslate *AddressTranslate::createAddressTranslator(int pid_, 
00360                                                             ProcessReader *reader_,
00361                                                             SymbolReaderFactory *symfactory_,
00362                                                             PROC_HANDLE,
00363                                                             std::string exename,
00364                                                             Address interp_base)
00365 {
00366    translate_printf("Creating AddressTranslateSysV\n", __FILE__, __LINE__);
00367    AddressTranslate *at = new AddressTranslateSysV(pid_, reader_, symfactory_, exename, interp_base);
00368    translate_printf("Created: %lx\n",  (long)at);
00369    
00370    if (!at) {
00371       return NULL;
00372    }
00373    else if (at->creation_error) {
00374       delete at;
00375       return NULL;
00376    }
00377    return at;
00378 }
00379 
00380 AddressTranslate *AddressTranslate::createAddressTranslator(ProcessReader *reader_,
00381                                                             SymbolReaderFactory *factory_, 
00382                                                             std::string exename,
00383                                                             Address interp_base)
00384 {
00385    return createAddressTranslator(getpid(), reader_, factory_, INVALID_HANDLE_VALUE, exename, interp_base);
00386 }
00387 
00388 AddressTranslateSysV::AddressTranslateSysV() :
00389    AddressTranslate(NULL_PID),
00390    reader(NULL),
00391    interpreter_base(0),
00392    program_base(0),
00393    page_size(0),
00394    set_interp_base(0),
00395    address_size(0),
00396    interpreter(NULL),
00397    previous_r_state(0),
00398    current_r_state(0),
00399    r_debug_addr(0),
00400    trap_addr(0),
00401    real_trap_addr(0)
00402 {
00403 }
00404 
00405 AddressTranslateSysV::AddressTranslateSysV(int pid, ProcessReader *reader_, 
00406                                            SymbolReaderFactory *reader_fact,
00407                                            std::string exename, Address interp_base) :
00408    AddressTranslate(pid, INVALID_HANDLE_VALUE, exename),
00409    reader(reader_),
00410    interpreter_base(0),
00411    set_interp_base(false),
00412    address_size(0),
00413    interpreter(NULL),
00414    previous_r_state(0),
00415    current_r_state(0),
00416    r_debug_addr(0),
00417    trap_addr(0),
00418    real_trap_addr(0)
00419 {
00420    bool result;
00421    if (interp_base != (Address) -1) {
00422       interpreter_base = interp_base;
00423       set_interp_base = true;
00424    }
00425    if (!reader) {
00426      if (pid == getpid()) {
00427          reader = new ProcessReaderSelf();
00428      }
00429      else {
00430        reader = createDefaultDebugger(pid);
00431      }
00432    }
00433    symfactory = reader_fact;
00434    result = init();
00435    if (!result) {
00436       creation_error = true;
00437       return;
00438    }
00439 }
00440 
00441 bool AddressTranslateSysV::parseDTDebug() {
00442     //TODO this could possibly be used on other platforms
00443 #if !defined(os_freebsd)
00444     return false;
00445 #else
00446     translate_printf("Entering parseDTDebug\n");
00447     if( !setAddressSize() ) {
00448         translate_printf("Failed to set address size.\n", __FILE__, __LINE__);
00449         return false;
00450     }
00451 
00452     // This information is derived from the DT_DEBUG field in the
00453     // executable's program headers -- however, the value needs to
00454     // be read from the loaded executable image so determine the
00455     // address of the DT_DEBUG field and then read it from the
00456     // process
00457 
00458     const char *l_err = "Failed to determine trap address.";
00459 
00460     getExecName();
00461     if( exec_name.empty() ) {
00462         translate_printf("%s\n",  l_err);
00463         return false;
00464     }
00465 
00466     SymReader *exe = symfactory->openSymbolReader(exec_name);
00467     if( !exe ) {
00468         translate_printf("%s\n",  l_err);
00469         return false;
00470     }
00471         
00472     // Need to get the address of the DYNAMIC segment
00473     Address dynAddress = 0;
00474     size_t dynSize = 0;
00475     unsigned numRegs = exe->numSegments();
00476     translate_printf("Checking %d regions for address/size information\n", numRegs);
00477     for(unsigned i = 0; i < numRegs; ++i) {
00478         SymSegment seg;
00479         exe->getSegment(i, seg);
00480     translate_printf("Found segment type %d for 0x%lx - 0x%lx, want %d\n",
00481              seg.type, seg.mem_addr, seg.mem_addr + seg.mem_size, PT_DYNAMIC);
00482         if( PT_DYNAMIC == seg.type ) {
00483             dynAddress = seg.mem_addr;
00484             dynSize = seg.mem_size;
00485             break;
00486         }
00487     }
00488     symfactory->closeSymbolReader(exe);
00489 
00490     if( !dynAddress || !dynSize ) {
00491         // This is okay for static binaries
00492       translate_printf("No dyn address or size, assuming static binary\n");
00493         return false;
00494     }
00495 
00496     if( !reader->start() ) {
00497         translate_printf("%s\n",  l_err);
00498         return false;
00499     }
00500 
00501     // Read the DYNAMIC segment from the process
00502     void *dynData = malloc(dynSize);
00503     if( !dynData || !reader->ReadMem(dynAddress, dynData, dynSize) ) {
00504         translate_printf("%s\n",  l_err);
00505         if( dynData ) free(dynData);
00506         return false;
00507     }
00508     
00509     if( address_size == 8 ) {
00510         Elf64_Dyn *dynDataElf = (Elf64_Dyn *)dynData;
00511         for(unsigned i = 0; i < (dynSize / sizeof(Elf64_Dyn)); ++i) {
00512       translate_printf("Comparing symbol tag %d to wanted %d\n",
00513                dynDataElf[i].d_tag, DT_DEBUG);
00514             if( DT_DEBUG == dynDataElf[i].d_tag ) {
00515                 r_debug_addr = (Address) dynDataElf[i].d_un.d_ptr;
00516                 break;
00517             }
00518         }
00519     }else{
00520         Elf32_Dyn *dynDataElf = (Elf32_Dyn *)dynData;
00521         for(unsigned i = 0; i < (dynSize / sizeof(Elf32_Dyn)); ++i) {
00522             if( DT_DEBUG == dynDataElf[i].d_tag ) {
00523                 r_debug_addr = (Address) dynDataElf[i].d_un.d_ptr;
00524                 break;
00525             }
00526         }
00527     }
00528     free(dynData);
00529 
00530     // When a process is initializing, the DT_DEBUG value could be zero
00531     // This function needs to indicate an error so the trap address can
00532     // be parsed from other sources (i.e., the interpreter)
00533 
00534     if( r_debug_addr ) {
00535         trap_addr = getTrapAddrFromRdebug();
00536         if( trap_addr == 0 ) {
00537             reader->done();
00538             return false;
00539         }
00540     }
00541 
00542     reader->done();
00543     
00544     return ( r_debug_addr != 0 );
00545 #endif
00546 }
00547 
00548 bool AddressTranslateSysV::parseInterpreter() {
00549     bool result;
00550 
00551     result = setInterpreter();
00552     if (!result) {
00553         translate_printf("Failed to set interpreter--static binary.\n", __FILE__, __LINE__);
00554         return true;
00555     }
00556 
00557     result = setAddressSize();
00558     if (!result) {
00559         translate_printf("Failed to set address size.\n", __FILE__, __LINE__);
00560         return false;
00561     }
00562 
00563     result = setInterpreterBase();
00564     if (!result) {
00565         translate_printf("Failed to set interpreter base.\n", __FILE__, __LINE__);
00566         return false;
00567     }
00568 
00569     if (interpreter) {
00570         if( interpreter->get_r_debug() ) {
00571             r_debug_addr = interpreter->get_r_debug() + interpreter_base;
00572 
00573             if( !reader->start() ) {
00574                 translate_printf("Failed to initialize process reader\n", __FILE__, __LINE__);
00575                 return false;
00576             }
00577 
00578             trap_addr = getTrapAddrFromRdebug();
00579 
00580             if( !reader->done() ) {
00581                 translate_printf("Failed to finalize process reader\n", __FILE__, __LINE__);
00582                 return false;
00583             }
00584 
00585             if( trap_addr == 0 ) {
00586                 trap_addr = interpreter->get_r_trap() + interpreter_base;
00587             }
00588         }
00589         else
00590         {
00591             r_debug_addr = 0;
00592             trap_addr = interpreter->get_r_trap() + interpreter_base;
00593         }
00594     } else {
00595         r_debug_addr = 0;
00596         trap_addr = 0;
00597     }
00598 
00599     return true;
00600 }
00601 
00602 bool AddressTranslateSysV::init() {
00603    translate_printf("Initing AddressTranslateSysV\n", __FILE__, __LINE__);
00604 
00605    // Try to use DT_DEBUG first, falling back to parsing the interpreter binary if possible
00606    if( !parseDTDebug() ) {
00607        if( !parseInterpreter() ) {
00608            translate_printf("Failed to determine r_debug address\n", 
00609                    __FILE__, __LINE__);
00610            return false;
00611        }
00612    }
00613 
00614    translate_printf("trap_addr = 0x%lx, r_debug_addr = 0x%lx\n",  trap_addr, r_debug_addr);
00615    translate_printf("Done with AddressTranslateSysV::init()\n", __FILE__, __LINE__);
00616 
00617    return true;
00618 }
00619 
00620 LoadedLib *AddressTranslateSysV::getLoadedLibByNameAddr(Address addr, std::string name)
00621 {
00622    Address wrappedAddr = adjustForAddrSpaceWrap(addr, name);
00623 
00624    std::pair<Address, std::string> p(wrappedAddr, name);
00625    sorted_libs_t::iterator i = sorted_libs.find(p);
00626    LoadedLib *ll = NULL;
00627    if (i != sorted_libs.end()) {
00628       ll = i->second;
00629    }
00630    else {
00631 
00632       ll = new LoadedLib(name, wrappedAddr);
00633 
00634       ll->setFactory(symfactory);
00635       assert(ll);
00636       sorted_libs[p] = ll;
00637    }
00638    ll->setShouldClean(false);
00639    return ll;
00640 }
00641 
00642 
00643 Address AddressTranslateSysV::getTrapAddrFromRdebug() {
00644     Address retVal = 0;
00645     assert( r_debug_addr && address_size );
00646 
00647     if( address_size == sizeof(void *) ) {
00648         r_debug_dyn<r_debug> *r_debug_native = new r_debug_dyn<r_debug>(reader, r_debug_addr);
00649         if( !r_debug_native ) {
00650             translate_printf("Failed to parse r_debug struct.\n", __FILE__, __LINE__);
00651             return 0;
00652         }
00653         if( !r_debug_native->is_valid() ) {
00654             return 0;
00655         }
00656         retVal = (Address) r_debug_native->r_brk();
00657         delete r_debug_native;
00658     }else{
00659         r_debug_dyn<r_debug_dyn32> *r_debug_32 = new r_debug_dyn<r_debug_dyn32>(reader, r_debug_addr);
00660         if( !r_debug_32 ) {
00661             translate_printf("Failed to parse r_debug struct.\n", __FILE__, __LINE__);
00662             return 0;
00663         }
00664         if( !r_debug_32->is_valid() ) {
00665             return 0;
00666         }
00667         retVal = (Address) r_debug_32->r_brk();
00668         delete r_debug_32;
00669     }
00670 
00671     return retVal;
00672 }
00673 
00674 bool AddressTranslateSysV::refresh()
00675 {
00676    link_map_xplat *link_elm = NULL;
00677    r_debug_dyn<r_debug_dyn32> *r_debug_32 = NULL;
00678    r_debug_dyn<r_debug> *r_debug_native = NULL;
00679    map_entries *maps = NULL;
00680    bool result = false;
00681    size_t loaded_lib_count = 0;
00682 
00683    translate_printf("Refreshing Libraries\n");
00684    if (pid == NULL_PID)
00685       return true;
00686 
00687    if (!r_debug_addr) {
00688        // On systems that use DT_DEBUG to determine r_debug_addr, DT_DEBUG might
00689        // not be set right away -- read DT_DEBUG now and see if it is set
00690        if( !parseDTDebug() && !interpreter ) {
00691           translate_printf("Working with static binary, no libraries to refresh\n",
00692                   __FILE__, __LINE__);
00693           libs.clear();
00694           if (!exec) {
00695              exec = getAOut();
00696           }
00697           libs.push_back(exec);
00698           getArchLibs(libs);
00699           return true;
00700        }
00701    }
00702    std::vector<LoadedLib *>::iterator i;
00703    for (i = libs.begin(); i != libs.end(); i++)
00704       (*i)->setShouldClean(true);
00705    libs.clear();
00706 
00707    if (!exec) {
00708       exec = getAOut();
00709    }   
00710    exec->setShouldClean(false);
00711    libs.push_back(exec);
00712    getArchLibs(libs);
00713    
00714    if( !reader->start() ) {
00715        translate_printf("Failed to refresh libraries\n", __FILE__, __LINE__);
00716        return false;
00717    }
00718 
00719    translate_printf("    Starting refresh.\n", __FILE__, __LINE__);
00720    translate_printf("      trap_addr:    %lx\n",  trap_addr);
00721    translate_printf("      r_debug_addr: %lx\n",  r_debug_addr);
00722 
00723    if (address_size == sizeof(void*)) {
00724       r_debug_native = new r_debug_dyn<r_debug>(reader, r_debug_addr);
00725       if (!r_debug_native)
00726       {
00727     translate_printf("No r_debug_native, done\n");
00728         result = true;
00729         goto done;
00730       }
00731       else if (!r_debug_native->is_valid() && read_abort)
00732       {
00733     translate_printf("r_debug_native is not valid and aborting read, done\n");
00734          result = false;
00735          goto all_done;
00736       }
00737       else if (!r_debug_native->is_valid())
00738       {
00739     translate_printf("r_debug_native is not valid, done\n");
00740          if (interpreter) {
00741             libs.push_back(getLoadedLibByNameAddr(interpreter_base,
00742                                                   interpreter->getFilename()));
00743          }
00744          result = true;
00745          goto done;
00746       }
00747       link_elm = new link_map_dyn<link_map>(reader, r_debug_native->r_map());
00748    }
00749    else {//64-bit mutator, 32-bit mutatee
00750       r_debug_32 = new r_debug_dyn<r_debug_dyn32>(reader, r_debug_addr);
00751       if (!r_debug_32)
00752       {
00753          result = true;
00754          goto done;
00755       }
00756       else if (!r_debug_32->is_valid() && read_abort)
00757       {
00758          result = false;
00759          goto all_done;
00760       }
00761       else if (!r_debug_32->is_valid())
00762       {
00763          if (interpreter) {
00764             libs.push_back(getLoadedLibByNameAddr(interpreter_base,
00765                                                   interpreter->getFilename()));
00766          }
00767          result = true;
00768          goto done;
00769       }
00770       link_elm = new link_map_dyn<link_map_dyn32>(reader, r_debug_32->r_map());
00771    }
00772 
00773    if (!link_elm->is_valid() && read_abort) {
00774       result = false;
00775       goto all_done;
00776    }
00777    if (!link_elm->is_valid()) {
00778       result = true;
00779       goto done;
00780    }
00781 
00782    do {
00783       if (!link_elm->l_name()) {
00784          if (read_abort) {
00785             result = false;
00786             goto all_done;
00787          }
00788          continue;
00789       }
00790       string obj_name(link_elm->l_name());
00791       // Don't re-add the executable, it has already been added
00792       if( getExecName() == string(deref_link(obj_name.c_str())) ) {
00793          if (exec)
00794             exec->dynamic_addr = (Address) link_elm->l_ld();
00795           continue;
00796       }
00797 
00798       Address text = (Address) link_elm->l_addr();
00799       if (obj_name.empty()) {
00800          if (!text && exec) {
00801             exec->dynamic_addr = (Address) link_elm->l_ld();
00802          }
00803          continue;
00804       }
00805       if (!link_elm->is_valid())
00806          goto done;
00807 
00808 #if defined(os_linux)
00809       unsigned maps_size;
00810       if (obj_name == "") { //Augment using maps
00811          if (!maps)
00812             maps = getLinuxMaps(pid, maps_size);
00813          for (unsigned i=0; maps && i<maps_size; i++) {
00814             if (text == maps[i].start) {
00815                obj_name = maps[i].path;
00816                break;
00817             }
00818          }
00819       }
00820       if (obj_name.c_str()[0] == '[')
00821          continue;
00822 #endif
00823       
00824       string s(deref_link(obj_name.c_str()));
00825       LoadedLib *ll = getLoadedLibByNameAddr(text, s);
00826       ll->dynamic_addr = (Address) link_elm->l_ld();
00827       loaded_lib_count++;
00828       translate_printf("    New Loaded Library: %s(%lx)\n",  s.c_str(), text);
00829 
00830       libs.push_back(ll);
00831    } while (link_elm->load_next());
00832    
00833    
00834    if (read_abort) {
00835       result = false;
00836       goto all_done;
00837    }
00838 
00839    translate_printf("Found %d libraries.\n",  loaded_lib_count);
00840 
00841    result = true;
00842  done:
00843    reader->done();
00844    
00845    //Erase old elements from the sorted_libs
00846    sorted_libs.clear();
00847    for (vector<LoadedLib *>::iterator i = libs.begin(); i != libs.end(); i++)
00848    {
00849       LoadedLib *ll = *i;
00850       sorted_libs[pair<Address, string>(ll->getCodeLoadAddr(), ll->getName())] = ll;
00851    }
00852 
00853   all_done:
00854 
00855    if (read_abort) {
00856       translate_printf("refresh aborted due to async read\n", __FILE__, __LINE__);
00857    }
00858    if (link_elm)
00859       delete link_elm;
00860    if (r_debug_32)
00861       delete r_debug_32;
00862    if (r_debug_native)
00863       delete r_debug_native;
00864    if (maps)
00865       free(maps);
00866 
00867    return result;
00868 }
00869 
00870 FCNode::FCNode(string f, dev_t d, ino_t i, SymbolReaderFactory *factory_) :
00871    device(d),
00872    inode(i),
00873    parsed_file(false),
00874    parse_error(false),
00875    is_interpreter(false),
00876    r_debug_offset(0),
00877    r_trap_offset(0),
00878    symreader(NULL),
00879    factory(factory_)
00880 {
00881    filename = resolve_file_path(f.c_str());
00882 }
00883 
00884 string FCNode::getFilename() {
00885    return filename;
00886 }
00887 
00888 string FCNode::getInterpreter() {
00889    parsefile();
00890 
00891    return interpreter_name;
00892 }
00893 
00894 void FCNode::getSegments(vector<SymSegment> &segs) {
00895    parsefile();
00896 
00897    segs = segments;
00898 }
00899 
00900 unsigned FCNode::getAddrSize() {
00901    parsefile();
00902 
00903    return addr_size;
00904 }
00905 
00906 Offset FCNode::get_r_debug() {
00907    parsefile();
00908 
00909    return r_debug_offset;
00910 }
00911 
00912 Offset FCNode::get_r_trap() {
00913     parsefile();
00914 
00915     return r_trap_offset;
00916 }
00917 
00918 void FCNode::markInterpreter() {
00919    if (is_interpreter)
00920       return;
00921 
00922    assert(!parsed_file);
00923    is_interpreter = true;
00924 }
00925 
00926 #define NUM_DBG_BREAK_NAMES 4
00927 const char *dbg_break_names[] = { "_dl_debug_fast_state",
00928                                   "_dl_debug_state",
00929                                   "r_debug_state",
00930                                   "_r_debug_state" };
00931 
00932 void FCNode::parsefile()
00933 {
00934    if (parsed_file || parse_error)
00935       return;
00936    parsed_file = true;
00937    
00938    assert(!symreader);
00939    symreader = factory->openSymbolReader(filename);
00940    if (!symreader) {
00941       parse_error = true;
00942       translate_printf("Failed to open %s\n", 
00943                        filename.c_str());
00944       return;
00945    }
00946 
00947    if (is_interpreter) {
00948 #if !defined(os_freebsd)
00949       //We're parsing the interpreter, don't confuse this with
00950       // parsing the interpreter link info (which happens below).
00951       Symbol_t r_debug_sym = symreader->getSymbolByName(R_DEBUG_NAME);
00952       if (!symreader->isValidSymbol(r_debug_sym)) {
00953          translate_printf("Failed to find r_debug symbol in %s\n",
00954                            filename.c_str());
00955          parse_error = true;
00956       }
00957       r_debug_offset = symreader->getSymbolOffset(r_debug_sym);
00958 #endif
00959       r_trap_offset = 0;
00960       for(unsigned i = 0; i < NUM_DBG_BREAK_NAMES; ++i) {
00961           Symbol_t r_trap_sym = symreader->getSymbolByName(dbg_break_names[i]);
00962           if( symreader->isValidSymbol(r_trap_sym) ) {
00963               r_trap_offset = symreader->getSymbolOffset(r_trap_sym);
00964               break;
00965           }
00966       }
00967 
00968       if( !r_trap_offset ) {
00969           translate_printf("Failed to find debugging trap symbol in %s\n",
00970                    filename.c_str());
00971           parse_error = true;
00972       }
00973    }
00974 
00975    addr_size = symreader->getAddressWidth();   
00976    interpreter_name = symreader->getInterpreterName();
00977    
00978    unsigned num_s = symreader->numSegments();
00979    for (unsigned i=0; i<num_s; i++) {
00980       SymSegment sr;
00981       bool result = symreader->getSegment(i, sr);
00982       if (!result) {
00983          translate_printf("Failed to get region info\n",
00984                           __FILE__, __LINE__);
00985          parse_error = true;
00986          break;
00987       }
00988       
00989       segments.push_back(sr);
00990    }
00991    /*factory->closeSymbolReader(symreader);
00992      symreader = NULL;*/
00993 }
00994 
00995 FCNode *FileCache::getNode(const string &filename, SymbolReaderFactory *factory)
00996 {
00997    struct stat buf;
00998    int result = stat(filename.c_str(), &buf);
00999    if (result == -1)
01000       return NULL;
01001    if (!filename.length())
01002       return NULL;
01003 
01004    for (unsigned i=0; i<nodes.size(); i++)
01005    {
01006       if (nodes[i]->inode == buf.st_ino &&
01007           nodes[i]->device == buf.st_dev)
01008       {
01009          return nodes[i];
01010       }
01011    }
01012 
01013    FCNode *fc = new FCNode(filename, buf.st_dev, buf.st_ino, factory);
01014    nodes.push_back(fc);
01015 
01016    return fc;
01017 }
01018 
01019 FileCache::FileCache()
01020 {
01021 }
01022 
01023 Address AddressTranslateSysV::getLibraryTrapAddrSysV() {
01024   if (real_trap_addr == 0)
01025     plat_getTrapAddr();
01026   return real_trap_addr;
01027 }
01028 
01029 bool AddressTranslateSysV::plat_getTrapAddr() {
01030   real_trap_addr = trap_addr;
01031   return true;
01032 }
01033 
01034 Address AddressTranslateSysV::adjustForAddrSpaceWrap(Address base, std::string name) {
01035 #if !defined(arch_64bit)
01036    return base;
01037 #else
01038    if (sizeof(long) != 8) return base;
01039    if (address_size != 4) return base;
01040 
01041    // There is an annoying problem where RHEL6 uses wrapping unsigned math
01042    // to load libraries. In these cases, the base address is very large, 
01043    // e.g. 0xffff.... and the library is loaded at 0x00.....; the code offset, 
01044    // when added to the base, wraps. However, we use 64-bit math and we end up
01045    // with a 33-bit number instead. 
01046 
01047    // To figure out if this is happening, we read the binary's program header
01048    // and see what its code offset is. If that wraps in the address space,
01049    // sign-extend the base addr. 
01050 
01051    // THIS IS A HACK. But it's the best solution. 
01052    translate_printf("Opening %s with base of 0x%lx\n", name.c_str(), base);
01053    int fd = open(name.c_str(), O_RDONLY);
01054    if (fd == -1) return base;
01055 
01056    lseek(fd, 0, SEEK_SET);
01057    Elf32_Ehdr e_hdr;
01058    if (read(fd, &e_hdr, sizeof(e_hdr)) != sizeof(e_hdr)) return base;
01059 
01060    if (e_hdr.e_phoff == 0) return base;
01061 
01062    lseek(fd, e_hdr.e_phoff, SEEK_SET);
01063 
01064    Address codeOffset = 0;
01065    while (true) {
01066       Elf32_Phdr p_hdr;
01067       if (read(fd, &p_hdr, sizeof(p_hdr)) != sizeof(p_hdr)) return base;
01068 
01069       Address p_vaddr = p_hdr.p_vaddr;
01070       unsigned type = p_hdr.p_type;
01071       if (type == PT_LOAD) {
01072          codeOffset = p_vaddr;
01073          break;
01074       }
01075       if (type == PT_PHDR ||
01076           type == PT_NULL ||
01077           type == PT_DYNAMIC ||
01078           type == PT_INTERP ||
01079           type == PT_NOTE ||
01080           type == PT_SHLIB ||
01081           type == PT_TLS) continue;
01082 
01083       close(fd);
01084       return base;
01085    }
01086 
01087    Address aspace32 = 0x00000000ffffffff;
01088 
01089    translate_printf("\t Comparing base + offset of 0x%lx with 32-bit 0x%lx\n",
01090                  base+codeOffset + aspace32);
01091 
01092    close(fd);
01093 
01094    if ((base + codeOffset) < aspace32) {
01095       // No address space wrapping
01096       translate_printf("\t No wrapping detected\n");
01097       return base;
01098    }
01099    else {
01100       // Address space wrapping
01101       translate_printf("\t Address space wrapping detected, returning modified base of 0x%lx\n",
01102                     base | 0xffffffff00000000);
01103       return base | 0xffffffff00000000;
01104    }
01105 #endif
01106 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1