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: image-power.C,v 1.23 2008/03/12 20:09:10 legendre Exp $
33 // Determine if the called function is a "library" function or a "user" function
34 // This cannot be done until all of the functions have been seen, verified, and
38 #include "common/src/Vector.h"
39 #include <unordered_map>
40 #include "common/src/Vector.h"
41 #include "parse-cfg.h"
42 #include "instPoint.h"
44 #include "parRegion.h"
52 #include "common/src/arch.h"
54 #include "instructionAPI/h/Instruction.h"
55 #include "instructionAPI/h/InstructionDecoder.h"
57 #include "mapped_object.h"
58 #include "binaryEdit.h"
59 #include "addressSpace.h"
61 #include "baseTramp.h"
64 using namespace Dyninst::SymtabAPI;
66 static const std::string LIBC_CTOR_HANDLER("__do_global_ctors_aux");
67 static const std::string LIBC_DTOR_HANDLER("__do_global_dtors_aux");
68 static const std::string DYNINST_CTOR_HANDLER("DYNINSTglobal_ctors_handler");
69 static const std::string DYNINST_CTOR_LIST("DYNINSTctors_addr");
70 static const std::string DYNINST_DTOR_HANDLER("DYNINSTglobal_dtors_handler");
71 static const std::string DYNINST_DTOR_LIST("DYNINSTdtors_addr");
72 static const std::string SYMTAB_CTOR_LIST_REL("__SYMTABAPI_CTOR_LIST__");
73 static const std::string SYMTAB_DTOR_LIST_REL("__SYMTABAPI_DTOR_LIST__");
75 static bool replaceHandler(func_instance *origHandler, func_instance *newHandler,
76 int_symbol *newList, const std::string &listRelName)
78 // Add instrumentation to replace the function
79 // TODO: this should be a function replacement!
80 // And why the hell is it in parse-x86.C?
81 origHandler->proc()->replaceFunction(origHandler, newHandler);
82 // origHandler->proc()->relocate();
84 AddressSpace::patch(origHandler->proc());
85 /* End of PatchAPI stuffs */
87 /* create the special relocation for the new list -- search the RT library for
90 Symbol *newListSym = const_cast<Symbol *>(newList->sym());
92 std::vector<Region *> allRegions;
93 if( !newListSym->getSymtab()->getAllRegions(allRegions) ) {
98 std::vector<Region *>::iterator reg_it;
99 for(reg_it = allRegions.begin(); reg_it != allRegions.end(); ++reg_it) {
100 std::vector<relocationEntry> ®ion_rels = (*reg_it)->getRelocations();
101 vector<relocationEntry>::iterator rel_it;
102 for( rel_it = region_rels.begin(); rel_it != region_rels.end(); ++rel_it) {
103 if( rel_it->getDynSym() == newListSym ) {
104 relocationEntry *rel = &(*rel_it);
105 rel->setName(listRelName);
114 By parsing the function that actually sets up the parameters for the OMP
115 region we discover informations such as what type of parallel region we're
117 bool parse_func::parseOMPParent(image_parRegion * /*iPar*/, int /*desiredNum*/, int & /*currentSectionNum*/ )
119 #if 0 //!defined(cap_instruction_api)
120 Address funcBegin = getOffset();
121 InstrucIter ah(funcBegin, this);
122 InstrucIter callFind(funcBegin, this);
124 int regValues[10 + 1]; /* Only care about registers 3-10 (params) */
125 Address regWriteLocations[10 + 1];
127 for (int i = 0; i < 11; i++)
131 const char * regionFuncName = iPar->getAssociatedFunc()->symTabName().c_str();
133 while (callFind.hasMore())
135 if( callFind.isACallInstruction() ||
136 callFind.isADynamicCallInstruction() )
138 bool isAbsolute = false;
139 Address target = callFind.getBranchTargetAddress(&isAbsolute);
142 parse_func *ppdf = im->findFuncByEntry(target);
146 if (strstr(ppdf->symTabName().c_str(),regionFuncName)!=NULL)
155 if( ah.isRegConstantAssignment(regValues, regWriteLocations) ) /* Record param values */
157 else if( ah.isACallInstruction() ||
158 ah.isADynamicCallInstruction() )
161 bool isAbsolute = false;
162 Address target = ah.getBranchTargetAddress(&isAbsolute);
165 /* Finding Out if the call is to OpenMP Functions */
167 /* Return one of the following
168 OMP_PARALLEL, OMP_DO_FOR, OMP_SECTIONS, OMP_SINGLE,
169 OMP_PAR_DO, OMP_PAR_SECTIONS, OMP_MASTER, OMP_CRITICAL,
170 OMP_BARRIER, OMP_ATOMIC, OMP_FLUSH, OMP_ORDERED */
172 parse_func *ppdf = im->findFuncByEntry(target);
176 if (strstr(ppdf->symTabName().c_str(),"_TPO_linkage")!=NULL
177 && ( strstr(ppdf->symTabName().c_str(), "ParRegionSetup")!= NULL
178 || strstr(ppdf->symTabName().c_str(), "WSDoSetup") != NULL
179 || strstr(ppdf->symTabName().c_str(), "WSSectSetup") != NULL
180 || strstr(ppdf->symTabName().c_str(), "SingleSetup") != NULL
181 || strstr(ppdf->symTabName().c_str(), "ParallelDoSetup")!=NULL
182 || strstr(ppdf->symTabName().c_str(), "WSSectSetup") != NULL))
185 if (currentNum != desiredNum)
189 /* Standard outlined function */
190 if (strstr(ppdf->symTabName().c_str(), "ParRegionSetup")!=NULL)
191 iPar->setRegionType(OMP_PARALLEL);
193 /* Standard outlined function */
194 else if(strstr(ppdf->symTabName().c_str(), "WSDoSetup")!=NULL)
196 iPar->setRegionType(OMP_DO_FOR);
197 iPar->setClause("NUM_ITERATIONS",regValues[6]);
198 iPar->setClause("SCHEDULE",regValues[7]);
199 iPar->setClause("CHUNK_SIZE", regValues[8]);
200 iPar->setClauseLoc("CHUNK_SIZE", regWriteLocations[8]);
201 iPar->setClauseLoc("SCHEDULE", regWriteLocations[7]);
204 /* Standard outlined function */
205 else if(strstr(ppdf->symTabName().c_str(), "WSSectSetup")!=NULL)
207 iPar->setRegionType(OMP_SECTIONS);
208 iPar->setClause("NUM_SECTIONS",regValues[5]);
212 if (currentSectionNum == regValues[5])
213 currentSectionNum = 0;
216 /* Standard outlined function */
217 else if(strstr(ppdf->symTabName().c_str(), "SingleSetup")!=NULL)
218 iPar->setRegionType(OMP_SINGLE);
220 /* Standard outlined function */
221 else if(strstr(ppdf->symTabName().c_str(), "ParallelDoSetup")!=NULL)
223 iPar->setRegionType(OMP_PAR_DO);
224 iPar->setClause("NUM_ITERATIONS",regValues[6]);
225 iPar->setClause("SCHEDULE",regValues[7]);
226 iPar->setClause("CHUNK_SIZE", regValues[8]);
227 iPar->setClauseLoc("CHUNK_SIZE", regWriteLocations[8]);
228 iPar->setClauseLoc("SCHEDULE", regWriteLocations[7]);
230 /* Standard outlined function */
231 else if(strstr(ppdf->symTabName().c_str(), "WSSectSetup")!=NULL)
232 iPar->setRegionType(OMP_PAR_SECTIONS);
238 }/* End Checking Different Directive Types */
240 iPar->decodeClauses(regValues[3]);
241 iPar->setParentFunc(this);
243 parRegionsList.push_back(iPar);
245 if (iPar->getRegionType() == OMP_DO_FOR ||
246 iPar->getRegionType() == OMP_PAR_DO)
259 //#warning "convert to IAPI!"
267 std::string parse_func::calcParentFunc(const parse_func * imf,
268 pdvector<image_parRegion *> &/*pR*/)
270 /* We need to figure out the function that called the outlined
271 parallel region function. We do this by chopping off the
273 const char * nameStart = imf->prettyName().c_str();
274 const char * nameEnd = strrchr(nameStart, '@');
275 int strSize = nameEnd - nameStart - 3;
277 /* Make sure that the shortened string is not of size 0,
278 this would happen if a function started with @ or if there
279 was less than two characters between the beginning and @
280 This wouldn't happen for OpenMP functions, but might for imposters*/
283 char tempBuf[strlen(nameStart)];
284 strncpy(tempBuf, nameStart, strSize);
285 tempBuf[strSize] = '\0';
286 std::string tempPDS(tempBuf);
289 else /* if it starts with @ just return the full function as its parent, we'll sort it out later */
291 std::string tempPDS(nameStart);
297 void parse_func::parseOMP(image_parRegion * parReg, parse_func * parentFunc, int & currentSectionNum)
299 /* Each region is contained in a function, for the worksharing constructs
300 usually the parralel region encompasses the entire function
301 The "desiredNum" variable is the desired construct we want to "skip" to
302 when we parse the parent function, which we do whenever we encounter
303 a new outlined function */
307 /* This will fill in the directive type and all possible clauses
308 Multiple section numbers can occur with only one call to a section setup
309 function in the parent function, so we need to always offset the desired
310 region we are looking for with the current section number we are on*/
312 int lastSecSize = 0; // the number of sections in the most recent sections construct
313 int totalSectionGroups = 0; // the number of sections constructs encountered (in source),
314 // not the number of total sections
317 /* First, we increment the desired num for each region we've already
318 parsed from the parent function. A parent function can spawn multiple
319 outlined functions, so we don't want to mix up already parsed ones */
320 for(unsigned a = 0; a < parentFunc->parRegions().size();a++)
322 image_parRegion * tempReg = parentFunc->parRegions()[a];
324 if (tempReg->getRegionType() == OMP_PARALLEL ||
325 tempReg->getRegionType() == OMP_DO_FOR ||
326 tempReg->getRegionType() == OMP_PAR_DO ||
327 tempReg->getRegionType() == OMP_PAR_SECTIONS ||
328 tempReg->getRegionType() == OMP_SINGLE )
333 /* For the sections, we can't just count the number of section constructs
334 we run into, since multiple outlined functions line up to one section construct */
335 if (tempReg->getRegionType() == OMP_SECTIONS)
337 lastSecSize = tempReg->getClause("NUM_SECTIONS");
338 a += (lastSecSize-1);
339 totalSectionGroups++;
344 // if the currentSectionNum is not zero, it means there are still more outlined functions
345 // for a single section construct still out there, so we don't count the current section towards the total
346 if (currentSectionNum != 0)
348 totalSectionGroups--;
351 // sets the last instruction of the region
352 //parReg->setLastInsn(get_address() + get_size());
353 // XXX this is equivalent to the above, but is it right?
354 // it seems to be after the last instruction
355 Address last = extents().back()->end();
356 parReg->setLastInsn(last);
358 // we need to parse the parent function to get all the information about the region, mostly for worksharing constructs
359 bool hasLoop = parentFunc->parseOMPParent(parReg, desiredNum + totalSectionGroups, currentSectionNum);
361 // we parse the outlined function to look for inlined constructs like "Master" and "Ordered"
362 parseOMPFunc(hasLoop);
365 void parse_func::parseOMPFunc(bool /*hasLoop*/)
371 /* We parse the parent to get info if we are in an outlined function, but there can be some
372 inlined functions we might miss out on if we don't check those out too */
373 int regValues[10 + 1]; /* Only care about registers 3-10 (params) */
374 for (int i = 0; i < 11; i++)
377 #if 0//!defined(cap_instruction_api)
378 Address funcBegin = getOffset();
379 InstrucIter ah(funcBegin, this);
382 if( /*ah.isRegConstantAssignment(regValues)*/ 0 ) /* Record param values */
384 // Loop parsing for the Do/For constructs
385 else if( hasLoop && ah.isACondBDZInstruction())
387 InstrucIter ah2(ah.getCurrentAddress(), this);
389 Address startLoop = ah.getCurrentAddress() + 4;
391 while (ah2.hasMore())
393 if (ah2.isACondBDNInstruction())
395 addParRegion(startLoop, ah2.getCurrentAddress(), OMP_DO_FOR_LOOP_BODY);
401 // Here we get all the info for the inlined constructs that don't have outlined functions
402 else if( ah.isACallInstruction() ||
403 ah.isADynamicCallInstruction() )
405 bool isAbsolute = false;
406 Address target = ah.getBranchTargetAddress(&isAbsolute);
409 /* Finding Out if the call is to OpenMP Functions */
411 /* Return one of the following
412 OMP_PARALLEL, OMP_DO_FOR, OMP_SECTIONS, OMP_SINGLE,
413 OMP_PAR_DO, OMP_PAR_SECTIONS, OMP_MASTER, OMP_CRITICAL,
414 OMP_BARRIER, OMP_ATOMIC, OMP_FLUSH, OMP_ORDERED */
416 parse_func *ppdf = im->findFuncByEntry(target);
419 if (strstr(ppdf->symTabName().c_str(),"_xlsmp")!=NULL)
421 /* Section consists of only one instruction, call to "_xlsmpBarrier_TPO" */
422 if(strstr(ppdf->symTabName().c_str(), "Barrier")!=NULL)
424 addParRegion(ah.getCurrentAddress(), ah.getCurrentAddress()+4, OMP_BARRIER);
426 /* Section begins with "BeginOrdered, ends with EndOrdered" */
427 else if(strstr(ppdf->symTabName().c_str(), "BeginOrdered") !=NULL)
430 InstrucIter ah2(ah.getCurrentAddress(), this);
431 while (ah2.hasMore())
433 if( ah2.isACallInstruction() ||
434 ah2.isADynamicCallInstruction() )
436 Address target2 = ah2.getBranchTargetAddress(&isAbsolute);
438 parse_func *ppdf2 = im->findFuncByEntry(target2);
441 if(strstr(ppdf2->symTabName().c_str(), "EndOrdered") !=NULL)
447 addParRegion(ah.getCurrentAddress(), ah2.getCurrentAddress(), OMP_ORDERED);
448 parRegionsList.push_back(iPar);
450 /* Master construct */
451 else if(strstr(ppdf->symTabName().c_str(), "Master") !=NULL)
453 addParRegion(ah.getCurrentAddress(), ah.getCurrentAddress() + 0x04, OMP_MASTER);
455 /* Flush construct */
456 else if(strstr(ppdf->symTabName().c_str(), "Flush") !=NULL)
458 addParRegion(ah.getCurrentAddress(), ah.getCurrentAddress() + 0x04, OMP_FLUSH);
460 /* Critical Construct, Starts with GetDefaultSLock, ends with RelDefaultSLock */
461 else if(strstr(ppdf->symTabName().c_str(), "GetDefaultSLock") != NULL)
463 InstrucIter ah2(ah.getCurrentAddress(), this);
464 while (ah2.hasMore())
466 if( ah2.isACallInstruction() ||
467 ah2.isADynamicCallInstruction() )
469 Address target2 = ah2.getBranchTargetAddress(&isAbsolute);
471 parse_func *ppdf2 = im->findFuncByEntry(target2);
474 if(strstr(ppdf2->symTabName().c_str(), "RelDefaultSLock") !=NULL)
480 addParRegion(ah.getCurrentAddress(), ah2.getCurrentAddress(), OMP_CRITICAL);
482 /*Atomic Construct, Begins with GetAtomicLock, ends with RelAtomicLock */
483 else if(strstr(ppdf->symTabName().c_str(), "GetAtomicLock") != NULL)
485 image_parRegion * iPar = new image_parRegion(ah.getCurrentAddress(),this);
486 iPar->setRegionType(OMP_ATOMIC);
488 InstrucIter ah2(ah.getCurrentAddress(), this);
489 while (ah2.hasMore())
491 if( ah2.isACallInstruction() ||
492 ah2.isADynamicCallInstruction() )
494 Address target2 = ah2.getBranchTargetAddress(&isAbsolute);
496 parse_func *ppdf2 = im->findFuncByEntry(target2);
499 if(strstr(ppdf2->symTabName().c_str(), "RelDefaultSLock") !=NULL)
505 iPar->setLastInsn(ah2.getCurrentAddress());
507 iPar->setParentFunc(this); // when not outlined, parent func will be same as regular
508 iPar->setLastInsn(ah.getCurrentAddress() + 0x4); //Only one instruction long
510 parRegionsList.push_back(iPar);
514 }/* End Checking Different Directive Types */
524 /* This does a linear scan to find out which registers are used in the function,
525 it then stores these registers so the scan only needs to be done once.
526 It returns true or false based on whether the function is a leaf function,
527 since if it is not the function could call out to another function that
528 clobbers more registers so more analysis would be needed */
529 void parse_func::calcUsedRegs()
531 if (usedRegisters != NULL)
535 usedRegisters = new parse_func_registers();
536 using namespace Dyninst::InstructionAPI;
537 std::set<RegisterAST::Ptr> writtenRegs;
540 auto curBlock = bl.begin();
541 for( ; curBlock != bl.end(); ++curBlock)
543 InstructionDecoder d(getPtrToInstruction((*curBlock)->start()),
547 while(i = d.decode())
549 i->getWriteSet(writtenRegs);
552 for(std::set<RegisterAST::Ptr>::const_iterator curReg = writtenRegs.begin();
553 curReg != writtenRegs.end();
556 MachRegister r = (*curReg)->getID();
557 if((r & ppc32::GPR) && (r <= ppc32::r13))
559 usedRegisters->generalPurposeRegisters.insert(r & 0xFFFF);
561 else if(((r & ppc32::FPR) && (r <= ppc32::fpr13)) ||
562 ((r & ppc32::FSR) && (r <= ppc32::fsr13)))
564 usedRegisters->floatingPointRegisters.insert(r & 0xFFFF);
571 #include "binaryEdit.h"
572 #include "addressSpace.h"
573 #include "function.h"
574 #include "baseTramp.h"
577 using namespace Dyninst::SymtabAPI;
579 * Static binary rewriting support
581 * Some of the following functions replace the standard ctor and dtor handlers
582 * in a binary. Currently, these operations only work with binaries linked with
583 * the GNU toolchain. However, it should be straightforward to extend these
584 * operations to other toolchains.
587 bool BinaryEdit::doStaticBinarySpecialCases() {
588 Symtab *origBinary = mobj->parse_img()->getObject();
590 /* Special Case 1: Handling global constructor and destructor Regions
592 * Replace global ctors function with special ctors function,
593 * and create a special relocation for the ctors list used by the special
596 * Replace global dtors function with special dtors function,
597 * and create a special relocation for the dtors list used by the special
601 // First, find all the necessary symbol info.
603 func_instance *globalCtorHandler = mobj->findGlobalConstructorFunc(LIBC_CTOR_HANDLER);
604 if( !globalCtorHandler ) {
605 logLine("failed to find libc constructor handler\n");
606 fprintf (stderr, "failed to find libc constructor handler\n");
610 func_instance *dyninstCtorHandler = findOnlyOneFunction(DYNINST_CTOR_HANDLER);
611 if( !dyninstCtorHandler ) {
612 logLine("failed to find Dyninst constructor handler\n");
613 fprintf (stderr,"failed to find Dyninst constructor handler\n");
617 func_instance *globalDtorHandler = mobj->findGlobalDestructorFunc(LIBC_DTOR_HANDLER);
618 if( !globalDtorHandler ) {
619 logLine ("failed to find libc destructor handler\n");
620 fprintf (stderr,"failed to find libc destructor handler\n");
624 func_instance *dyninstDtorHandler = findOnlyOneFunction(DYNINST_DTOR_HANDLER);
625 if( !dyninstDtorHandler ) {
626 logLine("failed to find Dyninst destructor handler\n");
627 fprintf (stderr,"failed to find Dyninst destructor handler\n");
631 int_symbol ctorsListInt;
632 int_symbol dtorsListInt;
633 bool ctorFound = false, dtorFound = false;
634 std::vector<BinaryEdit *>::iterator rtlib_it;
635 for(rtlib_it = rtlib.begin(); rtlib_it != rtlib.end(); ++rtlib_it) {
636 if( (*rtlib_it)->getSymbolInfo(DYNINST_CTOR_LIST, ctorsListInt) ) {
638 if( dtorFound ) break;
641 if( (*rtlib_it)->getSymbolInfo(DYNINST_DTOR_LIST, dtorsListInt) ) {
643 if( ctorFound ) break;
647 logLine("failed to find ctors list symbol\n");
648 fprintf (stderr,"failed to find ctors list symbol\n");
653 logLine("failed to find dtors list symbol\n");
654 fprintf (stderr,"failed to find dtors list symbol\n");
659 * Replace the libc ctor and dtor handlers with our special handlers
662 if( !replaceHandler(globalCtorHandler, dyninstCtorHandler,
663 &ctorsListInt, SYMTAB_CTOR_LIST_REL) ) {
664 logLine("Failed to replace libc ctor handler with special handler");
665 fprintf (stderr,"Failed to replace libc ctor handler with special handler");
668 inst_printf("%s[%d]: replaced ctor function %s with %s\n",
669 FILE__, __LINE__, LIBC_CTOR_HANDLER.c_str(),
670 DYNINST_CTOR_HANDLER.c_str());
673 if( !replaceHandler(globalDtorHandler, dyninstDtorHandler,
674 &dtorsListInt, SYMTAB_DTOR_LIST_REL) ) {
675 logLine("Failed to replace libc dtor handler with special handler");
676 fprintf (stderr,"Failed to replace libc dtor handler with special handler");
679 inst_printf("%s[%d]: replaced dtor function %s with %s\n",
680 FILE__, __LINE__, LIBC_DTOR_HANDLER.c_str(),
681 DYNINST_DTOR_HANDLER.c_str());
685 * Special Case 2: Issue a warning if attempting to link pthreads into a binary
686 * that originally did not support it or into a binary that is stripped. This
687 * scenario is not supported with the initial release of the binary rewriter for
690 * The other side of the coin, if working with a binary that does have pthreads
691 * support, pthreads needs to be loaded.
694 bool isMTCapable = isMultiThreadCapable();
695 bool foundPthreads = false;
697 vector<Archive *> libs;
698 vector<Archive *>::iterator libIter;
699 if( origBinary->getLinkingResources(libs) ) {
700 for(libIter = libs.begin(); libIter != libs.end(); ++libIter) {
701 if( (*libIter)->name().find("libpthread") != std::string::npos ||
702 (*libIter)->name().find("libthr") != std::string::npos )
704 foundPthreads = true;
710 if( foundPthreads && (!isMTCapable || origBinary->isStripped()) ) {
712 "\nWARNING: the pthreads library has been loaded and\n"
713 "the original binary is not multithread-capable or\n"
714 "it is stripped. Currently, the combination of these two\n"
715 "scenarios is unsupported and unexpected behavior may occur.\n");
716 }else if( !foundPthreads && isMTCapable ) {
718 "\nWARNING: the pthreads library has not been loaded and\n"
719 "the original binary is multithread-capable. Unexpected\n"
720 "behavior may occur because some pthreads routines are\n"
721 "unavailable in the original binary\n");
726 * The RT library has some dependencies -- Symtab always needs to know
727 * about these dependencies. So if the dependencies haven't already been
731 vector<Archive *> libs1;
732 vector<Archive *>::iterator libIter1;
733 bool loadLibc = true;
734 if( origBinary->getLinkingResources(libs1) ) {
735 for(libIter1 = libs1.begin(); libIter1 != libs1.end(); ++libIter1) {
736 if( (*libIter1)->name().find("libc.a") != std::string::npos ) {
743 std::map<std::string, BinaryEdit *> res;
744 openResolvedLibraryName("libc.a", res);
745 std::map<std::string, BinaryEdit *>::iterator bedit_it;
746 for(bedit_it = res.begin(); bedit_it != res.end(); ++bedit_it) {
747 if( bedit_it->second == NULL ) {
748 logLine("Failed to load DyninstAPI_RT library dependency (libc.a)");
749 fprintf (stderr,"Failed to load DyninstAPI_RT library dependency (libc.a)");
758 func_instance *mapped_object::findGlobalConstructorFunc(const std::string &ctorHandler) {
759 using namespace Dyninst::InstructionAPI;
761 const pdvector<func_instance *> *funcs = findFuncVectorByMangled(ctorHandler);
762 if( funcs != NULL ) {
766 /* If the symbol isn't found, try looking for it in a call instruction in
769 * On Linux, the instruction sequence is:
773 * call call_gmon_start
777 * On FreeBSD, the instruction sequence is:
784 Symtab *linkedFile = parse_img()->getObject();
785 Region *initRegion = NULL;
786 if( !linkedFile->findRegion(initRegion, ".init") ) {
787 vector<Dyninst::SymtabAPI::Function *> symFuncs;
788 if( linkedFile->findFunctionsByName(symFuncs, "_init") ) {
789 initRegion = symFuncs[0]->getRegion();
791 logLine("failed to locate .init Region or _init function\n");
796 if( initRegion == NULL ) {
797 logLine("failed to locate .init Region or _init function\n");
801 // Search for last of a fixed number of calls
802 #if defined(os_freebsd)
803 const unsigned CTOR_NUM_CALLS = 2;
805 const unsigned CTOR_NUM_CALLS = 3;
808 Address ctorAddress = 0;
809 unsigned bytesSeen = 0;
810 unsigned numCalls = 0;
811 const unsigned char *p = reinterpret_cast<const unsigned char *>(initRegion->getPtrToRawData());
813 InstructionDecoder decoder(p, initRegion->getDiskSize(),
814 parse_img()->codeObject()->cs()->getArch());
816 Instruction::Ptr curInsn = decoder.decode();
817 while(numCalls < CTOR_NUM_CALLS && curInsn && curInsn->isValid() &&
818 bytesSeen < initRegion->getDiskSize())
820 InsnCategory category = curInsn->getCategory();
821 if( category == c_CallInsn ) {
824 if( numCalls < CTOR_NUM_CALLS ) {
825 bytesSeen += curInsn->size();
826 curInsn = decoder.decode();
830 if( numCalls != CTOR_NUM_CALLS ) {
831 logLine("heuristic for finding global constructor function failed\n");
835 Address callAddress = initRegion->getMemOffset() + bytesSeen;
837 RegisterAST thePC = RegisterAST(
838 Dyninst::MachRegister::getPC(parse_img()->codeObject()->cs()->getArch()));
840 Expression::Ptr callTarget = curInsn->getControlFlowTarget();
841 if( !callTarget.get() ) {
842 logLine("failed to find global constructor function\n");
845 callTarget->bind(&thePC, Result(s64, callAddress));
847 Result actualTarget = callTarget->eval();
848 if( actualTarget.defined ) {
849 ctorAddress = actualTarget.convert<Address>();
851 logLine("failed to find global constructor function\n");
855 if( !ctorAddress || !parse_img()->codeObject()->cs()->isValidAddress(ctorAddress) ) {
856 logLine("invalid address for global constructor function\n");
861 if( (ret = findFuncByEntry(ctorAddress)) == NULL ) {
862 logLine("unable to create representation for global constructor function\n");
866 inst_printf("%s[%d]: set global constructor address to 0x%lx\n", FILE__, __LINE__,
872 func_instance *mapped_object::findGlobalDestructorFunc(const std::string &dtorHandler) {
873 using namespace Dyninst::InstructionAPI;
875 const pdvector<func_instance *> *funcs = findFuncVectorByMangled(dtorHandler);
876 if( funcs != NULL ) {
881 * If the symbol isn't found, try looking for it in a call in the
882 * .fini section. It is the last call in .fini.
894 Symtab *linkedFile = parse_img()->getObject();
895 Region *finiRegion = NULL;
896 if( !linkedFile->findRegion(finiRegion, ".fini") ) {
897 vector<Dyninst::SymtabAPI::Function *> symFuncs;
898 if( linkedFile->findFunctionsByName(symFuncs, "_fini") ) {
899 finiRegion = symFuncs[0]->getRegion();
901 logLine("failed to locate .fini Region or _fini function\n");
906 if( finiRegion == NULL ) {
907 logLine("failed to locate .fini Region or _fini function\n");
911 // Search for last call in the function
912 Address dtorAddress = 0;
913 unsigned bytesSeen = 0;
914 const unsigned char *p = reinterpret_cast<const unsigned char *>(finiRegion->getPtrToRawData());
916 InstructionDecoder decoder(p, finiRegion->getDiskSize(),
917 parse_img()->codeObject()->cs()->getArch());
919 Instruction::Ptr lastCall;
920 Instruction::Ptr curInsn = decoder.decode();
922 while(curInsn && curInsn->isValid() &&
923 bytesSeen < finiRegion->getDiskSize())
925 InsnCategory category = curInsn->getCategory();
926 if( category == c_CallInsn ) {
931 bytesSeen += curInsn->size();
932 curInsn = decoder.decode();
935 if( !lastCall.get() || !lastCall->isValid() ) {
936 logLine("heuristic for finding global destructor function failed\n");
940 Address callAddress = finiRegion->getMemOffset() + bytesSeen;
942 RegisterAST thePC = RegisterAST(
943 Dyninst::MachRegister::getPC(parse_img()->codeObject()->cs()->getArch()));
945 Expression::Ptr callTarget = lastCall->getControlFlowTarget();
946 if( !callTarget.get() ) {
947 logLine("failed to find global destructor function\n");
950 callTarget->bind(&thePC, Result(s64, callAddress));
952 Result actualTarget = callTarget->eval();
953 if( actualTarget.defined ) {
954 dtorAddress = actualTarget.convert<Address>();
956 logLine("failed to find global destructor function\n");
960 if( !dtorAddress || !parse_img()->codeObject()->cs()->isValidAddress(dtorAddress) ) {
961 logLine("invalid address for global destructor function\n");
965 // A targ stub should have been created at the address
966 func_instance *ret = NULL;
967 if( (ret = findFuncByEntry(dtorAddress)) == NULL ) {
968 logLine("unable to find global destructor function\n");
971 inst_printf("%s[%d]: set global destructor address to 0x%lx\n", FILE__, __LINE__,