2 * See the dyninst/COPYRIGHT file for copyright information.
4 * We provide the Paradyn Tools (below described as "Paradyn")
5 * on an AS IS basis, and do not warrant its validity or performance.
6 * We reserve the right to update, modify, or discontinue this
7 * software at any time. We shall have no obligation to supply such
8 * updates or modifications or any other form of support to you.
10 * By your use of Paradyn, you understand and agree that we (or any
11 * other person or entity with proprietary rights in Paradyn) are
12 * under no obligation to provide either maintenance services,
13 * update services, notices of latent defects, or correction of
14 * defects for Paradyn.
16 * This library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Lesser General Public
18 * License as published by the Free Software Foundation; either
19 * version 2.1 of the License, or (at your option) any later version.
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
31 // $Id: unix.C,v 1.243 2008/06/30 17:33:31 legendre Exp $
35 #include "mapped_object.h"
36 #include "mapped_module.h"
37 #include "dynProcess.h"
38 #include "dynThread.h"
41 #include "common/h/pathName.h"
45 extern char **environ;
47 using namespace Dyninst::ProcControlAPI;
49 // Functions for all Unices //
51 bool PCProcess::hideDebugger()
56 bool OS::executableExists(const std::string &file)
58 struct stat file_stat;
61 const char *fn = file.c_str();
62 stat_result = stat(fn, &file_stat);
63 return (stat_result != -1);
66 void OS::get_sigaction_names(std::vector<std::string> &names)
68 names.push_back(string("sigaction"));
69 names.push_back(string("signal"));
74 std::string PCProcess::createExecPath(const std::string &file, const std::string &dir) {
75 std::string ret = file;
76 if (dir.length() > 0) {
77 if (!(file[0] == ('/'))) {
78 // file does not start with a '/', so it is a relative pathname
79 // we modify it to prepend the given directory
80 if (dir[dir.length()-1 ] == ('/') ) {
81 // the dir already has a trailing '/', so we can
82 // just concatenate them to get an absolute path
85 // the dir does not have a trailing '/', so we must
86 // add a '/' to get the absolute path
87 ret = dir + "/" + file;
90 // file starts with a '/', so it is an absolute pathname
91 // DO NOT prepend the directory, regardless of what the
92 // directory variable holds.
93 // nothing to do in this case
100 // If true is passed for ignore_if_mt_not_set, then an error won't be
101 // initiated if we're unable to determine if the program is multi-threaded.
102 // We are unable to determine this if the daemon hasn't yet figured out what
103 // libraries are linked against the application. Currently, we identify an
104 // application as being multi-threaded if it is linked against a thread
105 // library (eg. libpthreads.a on AIX). There are cases where we are querying
106 // whether the app is multi-threaded, but it can't be determined yet but it
107 // also isn't necessary to know.
108 bool PCProcess::multithread_capable(bool ignoreIfMtNotSet) {
109 #if !defined(cap_threads)
113 if( mt_cache_result_ != not_cached ) {
114 if( mt_cache_result_ == cached_mt_true) return true;
118 if( mapped_objects.size() <= 1 ) {
119 assert( ignoreIfMtNotSet && "Can't query MT state" );
123 if( findObject("libthread.so*", true) // Solaris
124 || findObject("libpthreads.*", true) // AIX
125 || findObject("libpthread.so*", true) // Linux
126 || findObject("libpthread-*.so", true) // Linux
127 || findObject("libthr.*", true) ) // FreeBSD
129 mt_cache_result_ = cached_mt_true;
133 mt_cache_result_ = cached_mt_false;
138 * Searches for function in order, with preference given first
139 * to libpthread, then to libc, then to the process.
141 static void findThreadFuncs(PCProcess *p, std::string func,
142 pdvector<func_instance *> &result) {
144 mapped_module *lpthread = p->findModule("libpthread*", true);
146 found = lpthread->findFuncVectorByPretty(func, result);
150 mapped_module *lc = p->findModule("libc.so*", true);
152 found = lc->findFuncVectorByPretty(func, result);
156 p->findFuncsByPretty(func, result);
159 bool PCProcess::instrumentMTFuncs() {
162 #if !defined(cap_threads)
167 * Have dyn_pthread_self call the actual pthread_self
169 //Find dyn_pthread_self
170 pdvector<int_variable *> ptself_syms;
171 res = findVarsByAll("DYNINST_pthread_self", ptself_syms);
173 fprintf(stderr, "[%s:%d] - Couldn't find any dyn_pthread_self, expected 1\n",
176 assert(ptself_syms.size() == 1);
177 Address dyn_pthread_self = ptself_syms[0]->getAddress();
179 pdvector<func_instance *> pthread_self_funcs;
180 findThreadFuncs(this, "pthread_self", pthread_self_funcs);
181 if (pthread_self_funcs.size() != 1) {
182 fprintf(stderr, "[%s:%d] - Found %ld pthread_self functions, expected 1\n",
183 __FILE__, __LINE__, (long) pthread_self_funcs.size());
184 for (unsigned j=0; j<pthread_self_funcs.size(); j++) {
185 func_instance *ps = pthread_self_funcs[j];
186 fprintf(stderr, "[%s:%u] - %s in module %s at %lx\n", __FILE__, __LINE__,
187 ps->prettyName().c_str(), ps->mod()->fullName().c_str(),
193 res = writeFunctionPtr(this, dyn_pthread_self, pthread_self_funcs[0]);
195 fprintf(stderr, "[%s:%d] - Couldn't update dyn_pthread_self\n",
203 bool PCEventHandler::shouldStopForSignal(int signal) {
204 if( signal == SIGSTOP || signal == SIGINT ) return true;
208 bool PCEventHandler::isCrashSignal(int signal) {
222 bool PCEventHandler::isKillSignal(int signal) {
232 bool PCEventHandler::isValidRTSignal(int signal, RTBreakpointVal breakpointVal,
233 Address arg1, int status)
235 /* Okay... we use both DYNINST_BREAKPOINT_SIGNUM and sigstop,
236 * depending on what we're trying to stop. So we have to check the
237 *flags against the signal
239 if( signal == SIGSTOP ) {
240 if( breakpointVal == SoftRTBreakpoint ) {
241 if( status == DSE_forkExit ) {
242 if( arg1 == 0 ) return true;
244 proccontrol_printf("%s[%d]: parent process received SIGSTOP\n",
247 proccontrol_printf("%s[%d]: SIGSTOP wasn't due to fork exit\n",
251 proccontrol_printf("%s[%d]: mismatch in signal for breakpoint type\n",
254 }else if( signal == DYNINST_BREAKPOINT_SIGNUM ) {
255 if( breakpointVal == NormalRTBreakpoint ) {
256 if( (status != DSE_forkExit) || (arg1 != 0) ) return true;
258 proccontrol_printf("%s[%d]: child received signal %d\n",
259 FILE__, __LINE__, DYNINST_BREAKPOINT_SIGNUM);
261 proccontrol_printf("%s[%d]: mismatch in signal for breakpoint type\n",
265 proccontrol_printf("%s[%d]: signal wasn't sent by RT library\n",
272 mapped_object *PCProcess::createObjectNoFile(Address) {
273 assert(0); // not implemented on UNIX
277 bool PCProcess::setMemoryAccessRights(Address start, Address size, int rights) {
278 mal_printf("setMemoryAccessRights to %d [%lx %lx]\n", rights, start, start+size);
279 assert(!"Not implemented yet");
283 bool PCProcess::getMemoryAccessRights(Address start, Address size, int rights) {
284 mal_printf("getMemoryAccessRights to %d [%lx %lx]\n", rights, start, start+size);
285 assert(!"Not implemented yet");
289 void PCProcess::redirectFds(int stdin_fd, int stdout_fd, int stderr_fd,
290 std::map<int, int> &fds)
292 if( stdin_fd != 0 ) fds.insert(std::make_pair(stdin_fd, 0));
293 if( stdout_fd != 1 ) fds.insert(std::make_pair(stdout_fd, 1));
294 if( stderr_fd != 2 ) fds.insert(std::make_pair(stderr_fd, 2));
297 bool PCProcess::setEnvPreload(std::vector<std::string> &envp, std::string fileName) {
298 const unsigned int ERROR_CODE = 101;
299 bool use_abi_rt = false;
301 #if defined(arch_64bit)
302 SymtabAPI::Symtab *symt_obj;
303 bool result = SymtabAPI::Symtab::openFile(symt_obj, fileName);
304 if( !result ) return false;
306 use_abi_rt = (symt_obj->getAddressWidth() == 4);
309 const char *rt_lib_name = getenv("DYNINSTAPI_RT_LIB");
310 if( rt_lib_name == NULL ) {
311 showErrorCallback(ERROR_CODE, std::string("setEnvPreload: DYNINSTAPI_RT_LIB is undefined"));
312 proccontrol_printf("%s[%d]: DYNINSTAPI_RT_LIB is undefined\n");
316 std::string full_name;
318 const char *slash = P_strrchr(rt_lib_name, '/');
320 slash = P_strrchr(rt_lib_name, '\\');
323 const char *dot = P_strchr(slash, '.');
326 full_name = std::string(rt_lib_name, dot - rt_lib_name) +
327 std::string("_m32") +
329 rt_lib_name = full_name.c_str();
332 // Check to see if the library given exists.
333 if (access(rt_lib_name, R_OK)) {
334 std::string msg = std::string("Runtime library ") + std::string(rt_lib_name) +
335 std::string(" does not exist or cannot be accessed!");
337 showErrorCallback(ERROR_CODE, msg);
341 const char *var_name = "LD_PRELOAD";
343 // Check if some LD_PRELOAD is already part of the environment.
344 std::vector<std::string>::iterator ldPreloadVal = envp.end();
345 for(std::vector<std::string>::iterator i = envp.begin();
346 i != envp.end(); ++i)
348 if( (*i) == var_name ) {
354 if (ldPreloadVal == envp.end()) {
355 // Not found, append an entry
356 std::string ld_preload = std::string(var_name) + std::string("=") +
357 std::string(rt_lib_name);
358 startup_printf("LD_PRELOAD=%s\n", ld_preload.c_str());
359 envp.push_back(ld_preload);
361 // Found, modify envs in-place
362 std::string ld_preload = *ldPreloadVal + std::string(":") +
363 std::string(rt_lib_name);
364 startup_printf("LD_PRELOAD=%s\n", ld_preload.c_str());
365 *ldPreloadVal = ld_preload;
368 // Environment inherited from this process, copy the current
369 // environment to envp, modifying/adding LD_PRELOAD
370 char *ld_preload_orig = NULL;
372 while( environ[i] != NULL ) {
373 std::string envVar(environ[i]);
374 if( envVar.find("LD_PRELOAD=") == 0 ) {
375 ld_preload_orig = environ[i];
377 envp.push_back(envVar);
382 std::string ld_preload;
383 if (ld_preload_orig) {
384 // Append to existing var
385 ld_preload = std::string(var_name) + std::string("=") +
386 std::string(ld_preload_orig) + std::string(":") +
387 std::string(rt_lib_name);
390 ld_preload = std::string(var_name) + std::string("=") +
391 std::string(rt_lib_name);
393 envp.push_back(ld_preload);
400 bool PCProcess::getExecFileDescriptor(string filename,
401 bool, fileDescriptor &desc)
405 desc = fileDescriptor(filename.c_str(),
413 * Strategy: The program entry point is in /lib/ld-2.x.x at the
414 * _start function. Get the current PC, parse /lib/ld-2.x.x, and
415 * compare the two points.
417 bool PCProcess::hasPassedMain()
419 using namespace SymtabAPI;
420 Symtab *ld_file = NULL;
421 Address entry_addr, ldso_start_addr = 0;
424 Frame active_frame = initialThread_->getActiveFrame();
425 Address current_pc = active_frame.getPC();
427 // Get the interpreter name from SymtabAPI
428 const char *path = getAOut()->parse_img()->getObject()->getInterpreterName();
431 //Strange... This shouldn't happen on a normal linux system
432 startup_printf("[%s:%u] - Couldn't find /lib/ld-x.x.x in hasPassedMain\n",
437 std::string derefPath = resolve_file_path(path);
439 // Search for the dynamic linker in the loaded libraries
440 const LibraryPool &libraries = pcProc_->libraries();
441 bool foundDynLinker = false;
442 for(LibraryPool::const_iterator i = libraries.begin(); i != libraries.end();
445 if( (*i)->getName() == derefPath ) {
446 foundDynLinker = true;
447 ldso_start_addr = (*i)->getLoadAddress();
451 if( !foundDynLinker ) {
452 // This means that libraries haven't been loaded yet which implies
453 // that main hasn't been reached yet
457 //Open /lib/ld-x.x.x and find the entry point
458 if (!Symtab::openFile(ld_file, derefPath)) {
459 startup_printf("[%s:%u] - Unable to open %s in hasPassedMain\n",
460 FILE__, __LINE__, path);
464 entry_addr = ld_file->getEntryOffset();
466 startup_printf("[%s:%u] - No entry addr for %s\n",
467 FILE__, __LINE__, path);
471 entry_addr += ldso_start_addr;
473 if( !getOPDFunctionAddr(entry_addr) ) {
474 startup_printf("[%s:%u] - failed to read entry addr function pointer\n",
479 if( entry_addr < ldso_start_addr ) {
480 entry_addr += ldso_start_addr;
483 bool result = (entry_addr != current_pc);
484 startup_printf("[%s:%u] - hasPassedMain returning %d (%lx %lx)\n",
485 FILE__, __LINE__, (int) result, entry_addr, current_pc);
490 bool PCProcess::startDebugger() {
491 std::stringstream pidStr;
495 args[0] = dyn_debug_crash_debugger;
496 args[1] = file_.c_str();
497 args[2] = pidStr.str().c_str();
500 proccontrol_printf("%s[%d]: Launching %s %s %s\n", FILE__, __LINE__,
501 args[0], args[1], args[2]);
502 if( execv(args[0], const_cast<char **>(args)) == -1 ) {
510 // The following functions are only implemented on some Unices //
512 #if defined(os_linux) || defined(os_freebsd)
514 #include "dyninstAPI/src/binaryEdit.h"
515 #include "symtabAPI/h/Archive.h"
517 using namespace Dyninst::SymtabAPI;
520 mapped_object *BinaryEdit::openResolvedLibraryName(std::string filename,
521 std::map<std::string, BinaryEdit*> &retMap) {
522 std::vector<std::string> paths;
523 std::vector<std::string>::iterator pathIter;
525 // First, find the specified library file
526 bool resolved = getResolvedLibraryPath(filename, paths);
528 // Second, create a set of BinaryEdits for the found library
530 startup_printf("[%s:%u] - Opening dependent file %s\n",
531 FILE__, __LINE__, filename.c_str());
533 Symtab *origSymtab = getMappedObject()->parse_img()->getObject();
536 if ( !origSymtab->isStaticBinary() ) {
537 for(pathIter = paths.begin(); pathIter != paths.end(); ++pathIter) {
538 BinaryEdit *temp = BinaryEdit::openFile(*pathIter, mgr(), patcher());
540 if (temp && temp->getAddressWidth() == getAddressWidth()) {
541 retMap.insert(std::make_pair(*pathIter, temp));
542 return temp->getMappedObject();
547 // Static executable case
550 * Alright, this is a kludge, but even though the Archive is opened
551 * twice (once here and once by the image class later on), it is
552 * only parsed once because the Archive class keeps track of all
555 * This is partly due to the fact that Archives are collections of
556 * Symtab objects and their is one Symtab for each BinaryEdit. In
557 * some sense, an Archive is a collection of BinaryEdits.
559 for(pathIter = paths.begin(); pathIter != paths.end(); ++pathIter) {
561 Symtab *singleObject;
562 if (Archive::openArchive(library, *pathIter)) {
563 std::vector<Symtab *> members;
564 if (library->getAllMembers(members)) {
565 std::vector <Symtab *>::iterator member_it;
566 for (member_it = members.begin(); member_it != members.end();
569 BinaryEdit *temp = BinaryEdit::openFile(*pathIter,
570 mgr(), patcher(), (*member_it)->memberName());
572 if (temp && temp->getAddressWidth() == getAddressWidth()) {
573 std::string mapName = *pathIter + string(":") +
574 (*member_it)->memberName();
575 retMap.insert(std::make_pair(mapName, temp));
577 if(temp) delete temp;
583 if (retMap.size() > 0) {
584 origSymtab->addLinkingResource(library);
585 // So we tried loading "libc.a", and got back a swarm of individual members.
587 // Just return the first thing...
588 return retMap.begin()->second->getMappedObject();
590 //if( library ) delete library;
592 } else if (Symtab::openFile(singleObject, *pathIter)) {
593 BinaryEdit *temp = BinaryEdit::openFile(*pathIter, mgr(), patcher());
596 if (temp && temp->getAddressWidth() == getAddressWidth()) {
597 if( singleObject->getObjectType() == obj_SharedLib ||
598 singleObject->getObjectType() == obj_Executable )
600 startup_printf("%s[%d]: cannot load dynamic object(%s) when rewriting a static binary\n",
601 FILE__, __LINE__, pathIter->c_str());
602 std::string msg = std::string("Cannot load a dynamic object when rewriting a static binary");
603 showErrorCallback(71, msg.c_str());
607 retMap.insert(std::make_pair(*pathIter, temp));
608 return temp->getMappedObject();
611 if(temp) delete temp;
617 startup_printf("[%s:%u] - Creation error opening %s\n",
618 FILE__, __LINE__, filename.c_str());
624 #if defined(os_linux) || defined(os_freebsd)
626 #include "dyninstAPI/src/instPoint.h"
627 #include "dyninstAPI/src/parse-cfg.h"
628 #include "dyninstAPI/src/function.h"
629 #include "dyninstAPI/src/addressSpace.h"
630 #include "symtabAPI/h/Symtab.h"
631 #include "dyninstAPI/src/mapped_object.h"
632 #include "dyninstAPI/src/binaryEdit.h"
633 #include "dyninstAPI/src/debug.h"
634 #include "boost/tuple/tuple.hpp"
637 #if defined(os_linux)
638 #include "dyninstAPI/src/linux.h"
640 #include "dyninstAPI/src/freebsd.h"
643 // The following functions were factored from linux.C to be used
644 // on both Linux and FreeBSD
646 // findCallee: finds the function called by the instruction corresponding
647 // to the instPoint "instr". If the function call has been bound to an
648 // address, then the callee function is returned in "target" and the
649 // instPoint "callee" data member is set to pt to callee's func_instance.
650 // If the function has not yet been bound, then "target" is set to the
651 // func_instance associated with the name of the target function (this is
652 // obtained by the PLT and relocation entries in the image), and the instPoint
653 // callee is not set. If the callee function cannot be found, (ex. function
654 // pointers, or other indirect calls), it returns false.
655 // Returns false on error (ex. process doesn't contain this instPoint).
657 // HACK: made an func_instance method to remove from instPoint class...
658 // FURTHER HACK: made a block_instance method so we can share blocks
659 func_instance *block_instance::callee() {
660 // Check 1: pre-computed callee via PLT
661 func_instance *ret = obj()->getCallee(this);
664 // See if we've already done this
665 edge_instance *tEdge = getTarget();
670 if (!tEdge->sinkEdge()) {
671 func_instance *tmp = obj()->findFuncByEntry(tEdge->trg());
672 if (tmp && !(tmp->ifunc()->isPLTFunction())) {
679 // Do this the hard way - an inter-module jump
680 // get the target address of this function
681 Address target_addr; bool success;
682 boost::tie(success, target_addr) = llb()->callTarget();
684 // this is either not a call instruction or an indirect call instr
685 // that we can't get the target address
686 //fprintf(stderr, "%s[%d]: returning NULL\n", FILE__, __LINE__);
690 // get the relocation information for this image
691 Symtab *sym = obj()->parse_img()->getObject();
692 pdvector<relocationEntry> fbt;
693 vector <relocationEntry> fbtvector;
694 if (!sym->getFuncBindingTable(fbtvector)) {
695 //fprintf(stderr, "%s[%d]: returning NULL\n", FILE__, __LINE__);
701 * Object files and static binaries will not have a function binding table
702 * because the function binding table holds relocations used by the dynamic
705 if (!fbtvector.size() && !sym->isStaticBinary() &&
706 sym->getObjectType() != obj_RelocatableFile )
708 fprintf(stderr, "%s[%d]: WARN: zero func bindings\n", FILE__, __LINE__);
711 for (unsigned index=0; index< fbtvector.size();index++)
712 fbt.push_back(fbtvector[index]);
714 Address base_addr = obj()->codeBase();
716 std::map<Address, std::string> pltFuncs;
717 obj()->parse_img()->getPltFuncs(pltFuncs);
719 // find the target address in the list of relocationEntries
720 if (pltFuncs.find(target_addr) != pltFuncs.end()) {
721 for (u_int i=0; i < fbt.size(); i++) {
722 if (fbt[i].target_addr() == target_addr)
724 // check to see if this function has been bound yet...if the
725 // PLT entry for this function has been modified by the runtime
727 func_instance *target_pdf = 0;
728 if (proc()->hasBeenBound(fbt[i], target_pdf, base_addr)) {
729 updateCallTarget(target_pdf);
730 obj()->setCalleeName(this, target_pdf->symTabName());
731 obj()->setCallee(this, target_pdf);
736 const char *target_name = pltFuncs[target_addr].c_str();
737 PCProcess *dproc = dynamic_cast<PCProcess *>(proc());
739 BinaryEdit *bedit = dynamic_cast<BinaryEdit *>(proc());
740 obj()->setCalleeName(this, std::string(target_name));
741 pdvector<func_instance *> pdfv;
743 // See if we can name lookup
745 if (proc()->findFuncsByMangled(target_name, pdfv)) {
746 obj()->setCallee(this, pdfv[0]);
747 updateCallTarget(pdfv[0]);
752 std::vector<BinaryEdit *>::iterator i;
753 for (i = bedit->getSiblings().begin(); i != bedit->getSiblings().end(); i++)
755 if ((*i)->findFuncsByMangled(target_name, pdfv)) {
756 obj()->setCallee(this, pdfv[0]);
757 updateCallTarget(pdfv[0]);
766 //fprintf(stderr, "%s[%d]: returning NULL: target addr = %p\n", FILE__, __LINE__, (void *)target_addr);
770 void BinaryEdit::makeInitAndFiniIfNeeded()
772 using namespace Dyninst::SymtabAPI;
774 Symtab* linkedFile = getAOut()->parse_img()->getObject();
776 // Disable this for .o's and static binaries
777 if( linkedFile->isStaticBinary() ||
778 linkedFile->getObjectType() == obj_RelocatableFile )
783 bool foundInit = false;
784 bool foundFini = false;
785 vector <Function *> funcs;
786 if (linkedFile->findFunctionsByName(funcs, "_init")) {
789 if (linkedFile->findFunctionsByName(funcs, "_fini")) {
794 Offset initOffset = linkedFile->getInitOffset();
795 Region *initsec = linkedFile->findEnclosingRegion(initOffset);
796 if(!initOffset || !initsec)
798 unsigned char* emptyFunction = NULL;
799 int emptyFuncSize = 0;
800 #if defined(arch_x86) || defined(arch_x86_64)
801 static unsigned char empty_32[] = { 0x55, 0x89, 0xe5, 0xc9, 0xc3 };
802 static unsigned char empty_64[] = { 0x55, 0x48, 0x89, 0xe5, 0xc9, 0xc3 };
803 if(linkedFile->getAddressWidth() == 8)
805 emptyFunction = empty_64;
810 emptyFunction = empty_32;
813 #elif defined (arch_power)
814 static unsigned char empty[] = { 0x4e, 0x80, 0x00, 0x20};
815 emptyFunction = empty;
817 #endif //defined(arch_x86) || defined(arch_x86_64)
818 linkedFile->addRegion(highWaterMark_, (void*)(emptyFunction), emptyFuncSize, ".init.dyninst",
819 Dyninst::SymtabAPI::Region::RT_TEXT, true);
820 highWaterMark_ += emptyFuncSize;
821 lowWaterMark_ += emptyFuncSize;
822 linkedFile->findRegion(initsec, ".init.dyninst");
824 linkedFile->addSysVDynamic(DT_INIT, initsec->getMemOffset());
825 startup_printf("%s[%d]: creating .init.dyninst region, region addr 0x%lx\n",
826 FILE__, __LINE__, initsec->getMemOffset());
828 startup_printf("%s[%d]: ADDING _init at 0x%lx\n", FILE__, __LINE__, initsec->getMemOffset());
829 Symbol *initSym = new Symbol( "_init",
833 initsec->getMemOffset(),
834 linkedFile->getDefaultModule(),
837 linkedFile->addSymbol(initSym);
841 Offset finiOffset = linkedFile->getFiniOffset();
842 Region *finisec = linkedFile->findEnclosingRegion(finiOffset);
843 if(!finiOffset || !finisec)
845 unsigned char* emptyFunction = NULL;
846 int emptyFuncSize = 0;
847 #if defined(arch_x86) || defined(arch_x86_64)
848 static unsigned char empty_32[] = { 0x55, 0x89, 0xe5, 0xc9, 0xc3 };
849 static unsigned char empty_64[] = { 0x55, 0x48, 0x89, 0xe5, 0xc9, 0xc3 };
850 if(linkedFile->getAddressWidth() == 8)
852 emptyFunction = empty_64;
857 emptyFunction = empty_32;
861 #elif defined (arch_power)
862 static unsigned char empty[] = { 0x4e, 0x80, 0x00, 0x20};
863 emptyFunction = empty;
865 #endif //defined(arch_x86) || defined(arch_x86_64)
866 linkedFile->addRegion(highWaterMark_, (void*)(emptyFunction), emptyFuncSize, ".fini.dyninst",
867 Dyninst::SymtabAPI::Region::RT_TEXT, true);
868 highWaterMark_ += emptyFuncSize;
869 lowWaterMark_ += emptyFuncSize;
870 linkedFile->findRegion(finisec, ".fini.dyninst");
872 linkedFile->addSysVDynamic(DT_FINI, finisec->getMemOffset());
873 startup_printf("%s[%d]: creating .fini.dyninst region, region addr 0x%lx\n",
874 FILE__, __LINE__, finisec->getMemOffset());
877 startup_printf("%s[%d]: ADDING _fini at 0x%lx\n", FILE__, __LINE__, finisec->getMemOffset());
878 Symbol *finiSym = new Symbol( "_fini",
882 finisec->getMemOffset(),
883 linkedFile->getDefaultModule(),
886 linkedFile->addSymbol(finiSym);
890 Address PCProcess::setAOutLoadAddress(fileDescriptor &desc) {
891 //The load address of the a.out isn't correct. We can't read a
892 // correct one out of ld-x.x.x.so because it may not be initialized yet,
893 // and it won't be initialized until we reach main. But we need the load
894 // address to find main. Darn.
896 //Instead we'll read the entry out of /proc/pid/maps, and try to make a good
897 // effort to correctly match the fileDescriptor to an entry. Unfortunately,
898 // symlinks can complicate this, so we'll stat the files and compare inodes
900 struct stat aout, maps_entry;
901 map_entries *maps = NULL;
902 unsigned maps_size = 0, i;
905 Address loadAddr = 0;
907 //Get the inode for the a.out
908 startup_printf("[%s:%u] - a.out is a shared library, computing load addr\n",
910 memset(&aout, 0, sizeof(aout));
911 result = stat(pcProc_->libraries().getExecutable()->getName().c_str(), &aout);
913 startup_printf("[%s:%u] - setAOutLoadAddress couldn't stat %s: %s\n",
914 FILE__, __LINE__, proc_path, strerror(errno));
919 maps = getVMMaps(getPid(), maps_size);
921 startup_printf("[%s:%u] - setAOutLoadAddress, getVMMaps return NULL\n",
926 //Compare the inode of each map entry to the a.out's
927 for (i=0; i<maps_size; i++) {
928 memset(&maps_entry, 0, sizeof(maps_entry));
929 result = stat(maps[i].path, &maps_entry);
931 startup_printf("[%s:%u] - setAOutLoadAddress couldn't stat %s: %s\n",
932 FILE__, __LINE__, maps[i].path, strerror(errno));
935 if (maps_entry.st_dev == aout.st_dev && maps_entry.st_ino == aout.st_ino)
939 desc.setLoadAddr(maps[i].start);
940 loadAddr = maps[i].start;