2 * Copyright (c) 1996 Barton P. Miller
4 * We provide the Paradyn Parallel Performance Tools (below
5 * described as Paradyn") on an AS IS basis, and do not warrant its
6 * validity or performance. We reserve the right to update, modify,
7 * or discontinue this software at any time. We shall have no
8 * obligation to supply such updates or modifications or any other
9 * form of support to you.
11 * This license is for research uses. For such uses, there is no
12 * charge. We define "research use" to mean you may freely use it
13 * inside your organization for whatever purposes you see fit. But you
14 * may not re-distribute Paradyn or parts of Paradyn, in any form
15 * source or binary (including derivatives), electronic or otherwise,
16 * to any other organization or entity without our permission.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
24 * By your use of Paradyn, you understand and agree that we (or any
25 * other person or entity with proprietary rights in Paradyn) are
26 * under no obligation to provide either maintenance services,
27 * update services, notices of latent defects, or correction of
28 * defects for Paradyn.
30 * Even if advised of the possibility of such damages, under no
31 * circumstances shall we (or any other person or entity with
32 * proprietary rights in the software licensed hereunder) be liable
33 * to you or any third party for direct, indirect, or consequential
34 * damages of any character regardless of type of action, including,
35 * without limitation, loss of profits, loss of use, loss of good
36 * will, or computer failure or malfunction. You agree to indemnify
37 * us (and any other person or entity with proprietary rights in the
38 * software licensed hereunder) for any and all liability it may
39 * incur to third parties resulting from your use of Paradyn.
46 // TODO - machine independent instruction functions
47 #include "dyninstAPI/src/symtab.h"
48 #include "dyninstAPI/src/arch.h"
49 #include "util/h/Object.h"
51 #include "dyninstAPI/src/util.h"
52 #include "dyninstAPI/src/dyninstP.h"
53 #include "util/h/String.h"
54 #include "dyninstAPI/src/inst.h"
55 #include "util/h/Timer.h"
56 #include "paradynd/src/showerror.h"
57 #include "util/h/debugOstream.h"
59 #ifndef BPATCH_LIBRARY
60 #include "paradynd/src/main.h"
61 #include "paradynd/src/init.h"
63 extern vector<sym_data> syms_to_find;
66 // All debug_ostream vrbles are defined in process.C (for no particular reason)
67 extern debug_ostream sharedobj_cerr;
69 vector<image*> image::allImages;
71 #if defined(i386_unknown_nt4_0)
72 extern char *cplus_demangle(char *, int);
74 extern "C" char *cplus_demangle(char *, int);
78 /* imported from platform specific library list. This is lists all
79 library functions we are interested in instrumenting. */
81 pdmodule *image::newModule(const string &name, const Address addr)
84 // modules can be defined several times in C++ due to templates and
85 // in-line member functions.
86 if ((ret = findModule(name)))
89 string fullNm, fileNm;
90 char *out = P_strdup(name.string_of());
91 char *sl = P_strrchr(out, '/');
97 fullNm = string("/default/") + out;
102 ret = new pdmodule(langUnknown, addr, fullNm, fileNm, this);
103 modsByFileName[ret->fileName()] = ret;
104 modsByFullName[ret->fullName()] = ret;
110 // TODO -- is this g++ specific
111 bool buildDemangledName(const string &mangled, string &use)
113 /* The C++ demangling function demangles MPI__Allgather (and other MPI__
114 * functions with start with A) into the MPI constructor. In order to
115 * prevent this a hack needed to be made, and this seemed the cleanest
118 if(!mangled.prefixed_by("MPI__")) {
119 char *tempName = P_strdup(mangled.string_of());
120 char *demangled = cplus_demangle(tempName, 0);
135 // err is true if the function can't be defined
136 bool image::newFunc(pdmodule *mod, const string &name, const Address addr,
137 const unsigned size, const unsigned tag,
138 pd_Function *&retFunc) {
142 if ((func = findFunction(addr))){
144 temp += string(" findFunction failed\n");
145 logLine(P_strdup(temp.string_of()));
150 logLine("Error function without module\n");
151 showErrorCallback(34, "Error function without module");
155 string mangled_name = name;
156 const char *p = P_strchr(name.string_of(), ':');
158 unsigned nchars = p - name.string_of();
159 mangled_name = string(name.string_of(), nchars);
163 if (!buildDemangledName(mangled_name, demangled))
164 demangled = mangled_name;
168 func = new pd_Function(name, demangled, mod, addr, size, tag, this, err);
169 //cout << name << " pretty: " << demangled << " addr :" << addr <<endl;
174 notInstruFunction += func;
178 funcsByAddr[addr] = func;
181 vector<pd_Function*> *funcsByPrettyEntry;
182 if (!funcsByPretty.find(func->prettyName(), funcsByPrettyEntry)) {
183 funcsByPrettyEntry = new vector<pd_Function*>;
184 funcsByPretty[func->prettyName()] = funcsByPrettyEntry;
187 // several functions may have the same demangled name, and each one
188 // will appear in a different module
189 // vector<pdFunction*> *ap = funcsByPretty[func->prettyName()];
190 assert(funcsByPrettyEntry);
191 (*funcsByPrettyEntry) += func;
196 static timer loadTimer;
197 static FILE *timeOut=0;
198 #endif /* DEBUG_TIME */
201 * load an executable:
202 * 1.) parse symbol table and identify rotuines.
203 * 2.) scan executable to identify inst points.
205 * offset is normally zero except on CM-5 where we have two images in one
206 * file. The offset passed to parseImage is the logical offset (0/1), not
207 * the physical point in the file. This makes it faster to "parse" multiple
208 * copies of the same image since we don't have to stat and read to find the
211 image *image::parseImage(const string file)
214 * Check to see if we have parsed this image at this offeset before.
216 // TODO -- better method to detect same image/offset --> offset only for CM5
218 unsigned numImages = allImages.size();
220 for (unsigned u=0; u<numImages; u++)
221 if (file == allImages[u]->file())
225 * load the symbol table. (This is the a.out format specific routine).
228 statusLine("Process executable file");
231 // TODO -- kill process here
232 image *ret = new image(file, err);
239 // Add to master image list.
240 image::allImages += ret;
242 // define all modules.
243 #ifndef BPATCH_LIBRARY
244 tp->resourceBatchMode(true);
247 statusLine("defining modules");
248 ret->defineModules();
250 // statusLine("ready"); // this shouldn't be here, right? (cuz we're not done, right?)
252 #ifndef BPATCH_LIBRARY
253 tp->resourceBatchMode(false);
260 * load a shared object:
261 * 1.) parse symbol table and identify rotuines.
262 * 2.) scan executable to identify inst points.
265 image *image::parseImage(const string file,u_int baseAddr)
268 * Check to see if we have parsed this image at this offeset before.
270 // TODO -- better method to detect same image/offset --> offset only for CM5
272 unsigned theSize = allImages.size();
274 for (unsigned u=0; u<theSize; u++)
275 if (file == allImages[u]->file())
279 * load the symbol table. (This is the a.out format specific routine).
282 if(!baseAddr) statusLine("Processing an executable file");
283 else statusLine("Processing a shared object file");
286 // TODO -- kill process here
287 image *ret = new image(file, baseAddr,err);
291 logLine("error after new image in parseImage\n");
295 // Add to master image list.
296 image::allImages += ret;
298 // define all modules.
299 ret->defineModules();
303 bool image::addInternalSymbol(const string &str, const Address symValue) {
304 // Internal symbols are prefixed by { DYNINST, TRACELIB }
305 // don't ignore the underscore
306 static string dyn = "_DYNINST";
307 static string tlib = "_TRACELIB";
310 // normalize all symbols -- remove the leading "_"
311 if (str.prefixed_by(dyn)) {
312 const char *s = str.string_of(); s++;
313 if (!iSymsMap.defines(s)){
314 iSymsMap[s] = new internalSym(symValue, s);
317 } else if (str.prefixed_by(tlib)) {
318 const char *s = str.string_of(); s++;
319 if (!iSymsMap.defines(s))
320 iSymsMap[s] = new internalSym(symValue, s);
323 if (!iSymsMap.defines(str))
324 iSymsMap[str] = new internalSym(symValue, str);
331 * will search for symbol NAME or _NAME
332 * returns false on failure
334 bool image::findInternalSymbol(const string &name, const bool warn, internalSym &ret_sym){
337 if(linkedFile.get_symbol(name,lookUp)){
338 ret_sym = internalSym(lookUp.addr(),name);
343 new_sym = string("_") + name;
344 if(linkedFile.get_symbol(new_sym,lookUp)){
345 ret_sym = internalSym(lookUp.addr(),name);
351 msg = string("Unable to find symbol: ") + name;
352 statusLine(msg.string_of());
353 showErrorCallback(28, msg);
358 Address image::findInternalAddress(const string &name, const bool warn, bool &err)
363 internalSym *theSym; // filled in by find()
364 if (!iSymsMap.find(name, theSym)) {
367 string msg = string("Unable to find symbol: ") + name;
368 statusLine(msg.string_of());
369 showErrorCallback(28, msg);
375 return (theSym->getAddr());
378 pdmodule *image::findModule(const string &name)
380 if (modsByFileName.defines(name))
381 return (modsByFileName[name]);
382 else if (modsByFullName.defines(name))
383 return (modsByFullName[name]);
388 // TODO -- this is only being used in cases where only one function
389 // should exist -- should I assert that the vector size <= 1 ?
390 pd_Function *image::findOneFunction(const string &name)
394 if (funcsByPretty.defines(name)) {
395 vector<pd_Function*> *a = funcsByPretty[name];
401 } else if (buildDemangledName(name, demangName)) {
402 if (funcsByPretty.defines(demangName)) {
403 vector<pd_Function*> *a = funcsByPretty[demangName];
415 // This function supposely is only used to find function that
416 // is not instrumentable which may not be totally defined.
418 pd_Function *image::findOneFunctionFromAll(const string &name) {
421 if ((ret = findOneFunction(name)))
424 for (unsigned i = 0; i < notInstruFunction.size(); i++) {
425 ret = notInstruFunction[i];
426 if (ret->prettyName() == name)
433 bool image::findFunction(const string &name, vector<pd_Function*> &retList) {
435 if (funcsByPretty.defines(name)) {
436 retList = *funcsByPretty[name];
442 pd_Function *image::findFunction(const Address &addr)
444 pd_Function *result; // filled in by find()
445 if (funcsByAddr.find(addr, result))
451 pd_Function *image::findFunctionIn(const Address &addr,const process *p) const
455 dictionary_hash_iter<Address, pd_Function*> mi(funcsByAddr);
457 while (mi.next(adr, pdf)) {
458 if ((addr>=pdf->getAddress(p))&&(addr<=(pdf->getAddress(p)+pdf->size())))
462 // If not found, we are going to search them in the
463 // uninstrumentable function
464 for (unsigned i = 0; i < notInstruFunction.size(); i++) {
465 pdf = notInstruFunction[i];
466 if ((addr>=pdf->getAddress(p))&&(addr<=(pdf->getAddress(p)+pdf->size())))
474 #ifndef BPATCH_LIBRARY
475 void image::changeLibFlag(resource *res, const bool setSuppress)
480 unsigned numImages = image::allImages.size();
481 for (unsigned u=0; u<numImages; u++) {
482 ret = image::allImages[u];
483 mod = ret->findModule(res->part_name());
485 // suppress all procedures.
486 mod->changeLibFlag(setSuppress);
488 // more than one function may have this name --> templates, statics
489 vector<pd_Function*> pdfA;
490 if (ret->findFunction(res->part_name(), pdfA)) {
491 for (unsigned i=0; i<pdfA.size(); ++i) {
495 pdfA[i]->untagAsLib();
505 * return 0 if symbol <symname> exists in image, non-zero if it does not
507 bool image::symbolExists(const string &symname)
509 pd_Function *dummy = findOneFunction(symname);
510 return (dummy != NULL);
513 void image::postProcess(const string pifname)
516 string fname, errorstr;
518 char tmp1[5000], abstraction[500];
519 #ifndef BPATCH_LIBRARY
525 /* What file to open? */
526 if (!(pifname == (char*)NULL)) {
529 fname = file_ + ".pif";
533 Fil = P_fopen(fname.string_of(), "r");
536 errorstr = string("Tried to open PIF file ") + fname;
537 errorstr += string(", but could not (continuing)\n");
538 logLine(P_strdup(errorstr.string_of()));
539 showErrorCallback(35, errorstr);
543 /* Process the file */
545 fscanf(Fil, "%s", key);
548 /* Ignore mapping information for right now */
549 fgets(tmp1, 5000, Fil);
552 #ifndef BPATCH_LIBRARY
553 /* Create a new resource */
554 fscanf(Fil, "%s {", abstraction);
555 parent = rootResource;
557 fscanf(Fil, "%s", tmp1);
558 if (tmp1[0] != '}') {
559 parent = resource::newResource(parent, NULL,
562 nullString, // uniqifier
568 } while (parent != NULL);
572 errorstr = string("Ignoring bad line key (") + fname;
573 errorstr += string(") in file %s\n");
574 logLine(P_strdup(errorstr.string_of()));
575 fgets(tmp1, 5000, Fil);
582 void image::defineModules() {
583 string pds; pdmodule *mod;
584 dictionary_hash_iter<string, pdmodule*> mi(modsByFileName);
586 while (mi.next(pds, mod)){
592 ostrstream osb(buffer, 100, ios::out);
593 osb << "IMAGE_" << name() << "__" << getpid() << ends;
594 ofstream of(buffer, ios::app);
595 unsigned n_size = mdlNormal.size();
597 for (unsigned ni=0; ni<n_size; ni++) {
598 of << mdlNormal[ni]->prettyName() << "\t\t" << mdlNormal[ni]->addr() << "\t\t" <<
599 mdlNormal[ni]->isLibTag() << endl;
601 n_size = mdlLib.size();
603 for (ni=0; ni<n_size; ni++) {
604 of << mdlLib[ni]->prettyName() << "\t\t" << mdlLib[ni]->addr() << "\t\t" <<
605 mdlLib[ni]->isLibTag() << endl;
610 void pdmodule::define() {
611 #ifndef BPATCH_LIBRARY
612 resource *modResource = NULL;
616 ostrstream osb(buffer, 100, ios::out);
617 osb << "MODS_" << exec->name() << "__" << getpid() << ends;
618 ofstream of(buffer, ios::app);
621 unsigned f_size = funcs.size();
623 for (unsigned f=0; f<f_size; f++) {
624 pd_Function *pdf = funcs[f];
626 of << fileName << ": " << pdf->prettyName() << " " <<
627 pdf->isLibTag() << " " << pdf->addr() << endl;
629 // ignore line numbers for now
631 #ifndef BPATCH_LIBRARY
632 if (!(pdf->isLibTag())) {
633 // see if we have created module yet.
635 modResource = resource::newResource(moduleRoot, this,
636 nullString, // abstraction
638 0.0, // creation time
639 string::nil, // unique-ifier
643 resource::newResource(modResource, pdf,
644 nullString, // abstraction
645 pdf->prettyName(), 0.0,
646 nullString, // uniquifier
653 #ifndef BPATCH_LIBRARY
654 resource::send_now();
658 static inline bool findStartSymbol(Object &lf, Address &adr) {
661 if (lf.get_symbol("DYNINSTstartUserCode", lookUp) ||
662 lf.get_symbol("_DYNINSTstartUserCode", lookUp)) {
669 static inline bool findEndSymbol(Object &lf, Address &adr) {
672 if (lf.get_symbol("DYNINSTendUserCode", lookUp) ||
673 lf.get_symbol("_DYNINSTendUserCode", lookUp)) {
680 // TODO this assumes an ordering in the symbol table wrt modules KLUDGE
681 static inline bool notInUserRange(const Address adr,
682 const bool start, const Address startAdr,
683 const bool end, const Address endAdr) {
684 return ((start && (adr < startAdr)) || (end && (adr >= endAdr)));
687 static void binSearch (const Symbol &lookUp, vector<Symbol> &mods,
688 string &modName, Address &modAddr, const string &def) {
689 int start=0, end=mods.size()-1, index;
698 while ((start <= end) && !found) {
699 index = (start+end)/2;
701 if ((index == (((int)mods.size())-1)) ||
702 ((mods[index].addr() <= lookUp.addr()) && (mods[index+1].addr() > lookUp.addr()))) {
703 modName = mods[index].name();
704 modAddr = mods[index].addr();
706 } else if (lookUp.addr() < mods[index].addr()) {
713 modName = mods[0].name();
714 modAddr = mods[0].addr();
718 bool image::addOneFunction(vector<Symbol> &mods, pdmodule *lib, pdmodule *dyn,
719 const Symbol &lookUp, pd_Function *&retFunc) {
722 // this is a "user" symbol
723 string modName = lookUp.module();
726 string progName = name_ + "_module";
728 #if defined (sparc_sun_solaris2_4) || defined (i386_unknown_solaris2_5)
729 // In solaris there is no address for modules in the symbol table,
730 // so the binary search will not work. The module field in a symbol
731 // already has the correct module name for a symbol, if it can be
732 // obtained from the symbol table, otherwise the module is an empty
738 binSearch(lookUp, mods, modName, modAddr, progName);
741 return (defineFunction(lib, lookUp, modName, modAddr, retFunc));
744 bool inLibrary(Address addr, Address boundary_start, Address boundary_end,
745 Address startAddr, bool startB,
746 Address endAddr, bool endB) {
747 if ((addr >= boundary_start) && (addr <= boundary_end))
750 if (addr <= startAddr)
768 bool image::addAllFunctions(vector<Symbol> &mods,
769 pdmodule *lib, pdmodule *dyn,
770 const bool startB, const Address startAddr,
771 const bool endB, const Address endAddr) {
773 Address boundary_start, boundary_end;
776 SymbolIter symIter(linkedFile);
778 #ifdef BPATCH_LIBRARY
779 boundary_start = boundary_end = NULL;
781 if (!linkedFile.get_symbol(symString="DYNINSTfirst", lookUp) &&
782 !linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)) {
783 //statusLine("Internal symbol DYNINSTfirst not found");
784 //showErrorCallback(31, "Internal symbol DYNINSTfirst not found");
786 boundary_start = NULL;
788 boundary_start = lookUp.addr();
790 if (!linkedFile.get_symbol(symString="DYNINSTend", lookUp) &&
791 !linkedFile.get_symbol(symString="_DYNINSTend", lookUp)) {
792 //statusLine("Internal symbol DYNINSTend not found");
793 //showErrorCallback(32, "Internal symbol DYNINSTend not found");
797 boundary_end = lookUp.addr();
800 Symbol mainFuncSymbol; //Keeps track of info on "main" function
802 //Checking "main" function names in same order as in the inst-*.C files
803 if (linkedFile.get_symbol(symString="main", lookUp) ||
804 linkedFile.get_symbol(symString="_main", lookUp) ||
805 linkedFile.get_symbol(symString="WinMain", lookUp) ||
806 linkedFile.get_symbol(symString="_WinMain", lookUp))
807 mainFuncSymbol = lookUp;
809 // find the real functions -- those with the correct type in the symbol table
810 while (symIter.next(symString, lookUp)) {
812 if (funcsByAddr.defines(lookUp.addr()) ||
813 ((lookUp.addr() == mainFuncSymbol.addr()) &&
814 (lookUp.name() != mainFuncSymbol.name()))) {
815 // This function has been defined
817 // This function has the same address as the "main" function but does
818 // not have the same name as the "main" function. Therefore, skip
819 // it and let the "main" function be eventually associated with this
820 // function address. If we don't do this, paradynd will not have a
821 // "main" function to start work with.
823 } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
824 if (!isValidAddress(lookUp.addr())) {
827 sprintf(tempBuffer,"%x",lookUp.addr());
828 msg = string("Function") + lookUp.name() + string("has bad address ") +
830 statusLine(msg.string_of());
831 showErrorCallback(29, msg);
835 if (inLibrary(lookUp.addr(), boundary_start, boundary_end,
836 startAddr, startB, endAddr, endB)) {
837 addInternalSymbol(lookUp.name(), lookUp.addr());
838 if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
839 assert(pdf); mdlLib += pdf;
842 if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
843 assert(pdf); mdlNormal += pdf;
849 // now find the pseudo functions -- this gets ugly
850 // kludge has been set if the symbol could be a function
852 while (symIter.next(symString, lookUp)) {
853 if (funcsByAddr.defines(lookUp.addr())) {
854 // This function has been defined
856 } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
857 //logLine(P_strdup(symString.string_of()));
859 if (inLibrary(lookUp.addr(), boundary_start, boundary_end,
860 startAddr, startB, endAddr, endB)) {
861 addInternalSymbol(lookUp.name(), lookUp.addr());
862 if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
863 assert(pdf); mdlLib += pdf;
866 if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
867 assert(pdf); mdlNormal += pdf;
875 bool image::addAllSharedObjFunctions(vector<Symbol> &mods,
876 pdmodule *lib, pdmodule *dyn) {
880 SymbolIter symIter(linkedFile);
882 bool is_libdyninstRT = false; // true if this image is libdyninstRT
883 #if defined(i386_unknown_nt4_0)
884 if (linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)
885 || linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp))
886 is_libdyninstRT = true;
889 // find the real functions -- those with the correct type in the symbol table
890 while (symIter.next(symString, lookUp)) {
892 if (funcsByAddr.defines(lookUp.addr())) {
893 // This function has been defined
895 } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
896 if (!isValidAddress(lookUp.addr())) {
899 sprintf(tempBuffer,"%x",lookUp.addr());
900 msg = string("Function") + lookUp.name() + string("has bad address ") +
902 statusLine(msg.string_of());
903 showErrorCallback(29, msg);
907 if (is_libdyninstRT) {
908 addInternalSymbol(lookUp.name(), lookUp.addr());
909 if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
910 assert(pdf); mdlLib += pdf;
912 } else if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
913 assert(pdf); mdlNormal += pdf;
918 // now find the pseudo functions -- this gets ugly
919 // kludge has been set if the symbol could be a function
921 while (symIter.next(symString, lookUp)) {
922 if (funcsByAddr.defines(lookUp.addr())) {
923 // This function has been defined
925 } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
926 //logLine(P_strdup(symString.string_of()));
928 addInternalSymbol(lookUp.name(), lookUp.addr());
929 if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
930 assert(pdf); mdlLib += pdf;
938 int symCompare(const void *s1, const void *s2) {
939 const Symbol *sym1 = (const Symbol*)s1, *sym2 = (const Symbol*)s2;
941 return (sym1->addr() - sym2->addr());
945 unsigned int_addrHash(const unsigned &addr) {
949 // Please note that this is now machine independent-almost. Let us keep it that way
951 image::image(const string &fileName, bool &err)
952 : funcsByAddr(addrHash4),
953 modsByFileName(string::hash),
954 modsByFullName(string::hash),
956 linkedFile(fileName, pd_log_perror),
957 iSymsMap(string::hash),
958 funcsByPretty(string::hash),
959 knownJumpTargets(int_addrHash, 8192)
961 sharedobj_cerr << "image::image for non-sharedobj; file name=" << file_ << endl;
963 codeOffset_ = linkedFile.code_off();
964 dataOffset_ = linkedFile.data_off();
965 codeLen_ = linkedFile.code_len();
966 dataLen_ = linkedFile.data_len();
968 #if defined(hppa1_1_hp_hpux)
969 unwind = linkedFile.unwind;
972 if (!codeLen_ || !linkedFile.code_ptr()) {
973 string msg = string("Unable to open executable file: ") + fileName;
974 statusLine(msg.string_of());
977 logLine(msg.string_of());
981 showErrorCallback(27, msg);
985 #if !defined(i386_unknown_nt4_0)
987 if (!linkedFile.get_symbol("DYNINSTversion", version) &&
988 !linkedFile.get_symbol("_DYNINSTversion", version)) {
989 statusLine("Could not find version number in instrumentation\n");
990 showErrorCallback(33, "Could not find version number in instrumentation");
995 Word version_number = get_instruction(version.addr());
996 if (version_number != 1) {
998 msg = string("Incorrect version number, expected ") + string(1) +
999 string("found ") + string(version_number);
1000 statusLine(msg.string_of());
1001 showErrorCallback(30, msg);
1007 const char *nm = fileName.string_of();
1008 const char *pos = P_strrchr(nm, '/');
1016 // find the "user" code boundaries
1017 statusLine("finding user code boundaries");
1018 Address startUserAddr=0, endUserAddr=0;
1019 bool startBound = findStartSymbol(linkedFile, startUserAddr);
1020 bool endBound = findEndSymbol(linkedFile, endUserAddr);
1022 // use the *DUMMY_MODULE* until a module is defined
1023 pdmodule *dynModule = newModule(DYN_MODULE, 0);
1024 pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1025 // TODO -- define inst points in define function ?
1027 // The functions cannot be verified until all of them have been seen
1028 // because calls out of each function must be tagged as calls to user
1029 // functions or call to "library" functions
1033 SymbolIter symIter(linkedFile);
1035 // sort the modules by address into a vector to allow a binary search to
1036 // determine the module that a symbol will map to -- this may be bsd specific
1037 vector<Symbol> mods;
1039 while (symIter.next(symString, lookUp)) {
1041 if (lookUp.type() == Symbol::PDST_MODULE) {
1042 const string &lookUpName = lookUp.name();
1043 const char *str = lookUpName.string_of();
1045 int ln = lookUpName.length();
1047 // directory definition -- ignored for now
1048 if (str[ln-1] != '/')
1053 // sort the modules by address
1054 statusLine("sorting modules");
1055 mods.sort(symCompare);
1056 // assert(mods.sorted(symCompare));
1058 // remove duplicate entries -- some .o files may have the same address as .C files
1059 // kludge is true for module symbols that I am guessing are modules
1060 vector<Symbol> uniq;
1063 // must use loop+1 not mods.size()-1 since it is an unsigned compare
1064 // which could go negative - jkh 5/29/95
1065 for (loop=0; loop < mods.size(); loop++) {
1066 if ((loop+1 < mods.size()) &&
1067 (mods[loop].addr() == mods[loop+1].addr())) {
1068 if (!mods[loop].kludge())
1069 mods[loop+1] = mods[loop];
1074 // define all of the functions
1075 statusLine("winnowing functions");
1076 if (!addAllFunctions(uniq, libModule, dynModule, startBound, startUserAddr,
1077 endBound, endUserAddr)) {
1081 statusLine("checking call points");
1082 checkAllCallPoints();
1084 // statusLine("ready"); // this shouldn't be here, right? (cuz we're not really ready)
1086 // TODO -- remove duplicates -- see earlier note
1087 dictionary_hash<unsigned, unsigned> addr_dict(uiHash);
1088 vector<pd_Function*> temp_vec;
1089 unsigned f_size = mdlLib.size(), index;
1090 for (index=0; index<f_size; index++) {
1091 const unsigned the_address = (unsigned)mdlLib[index]->getAddress(0);
1092 if (!addr_dict.defines(the_address)) {
1093 addr_dict[the_address] = 1;
1094 temp_vec += mdlLib[index];
1098 temp_vec.resize(0); addr_dict.clear();
1099 f_size = mdlNormal.size();
1100 for (index=0; index<f_size; index++) {
1101 const unsigned the_address = (unsigned)mdlNormal[index]->getAddress(0);
1102 if (!addr_dict.defines(the_address)) {
1103 addr_dict[the_address] = 1;
1104 temp_vec += mdlNormal[index];
1107 mdlNormal = temp_vec;
1111 // load a shared object
1113 image::image(const string &fileName, u_int baseAddr, bool &err)
1114 : funcsByAddr(addrHash4),
1115 modsByFileName(string::hash),
1116 modsByFullName(string::hash),
1118 linkedFile(fileName, baseAddr,pd_log_perror),
1119 iSymsMap(string::hash),
1120 funcsByPretty(string::hash),
1121 knownJumpTargets(int_addrHash, 8192)
1123 sharedobj_cerr << "welcome to image::image for shared obj; file name=" << file_ << endl;
1125 codeOffset_ = linkedFile.code_off();
1126 dataOffset_ = linkedFile.data_off();
1127 codeLen_ = linkedFile.code_len();
1128 dataLen_ = linkedFile.data_len();
1129 //logLine("IN image::image\n");
1131 #if defined(hppa1_1_hp_hpux)
1132 unwind = linkedFile.unwind;
1135 if (!codeLen_ || !linkedFile.code_ptr()) {
1136 string msg = string("Unable to open shared object file: ") + fileName;
1137 statusLine(msg.string_of());
1140 logLine(msg.string_of());
1143 showErrorCallback(27, msg);
1150 string msg = string("Parsing shared object file: ") + fileName;
1151 statusLine(msg.string_of());
1154 const char *nm = fileName.string_of();
1155 const char *pos = P_strrchr(nm, '/');
1163 // use the *DUMMY_MODULE* until a module is defined
1164 pdmodule *dynModule = newModule(DYN_MODULE, 0);
1165 pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1166 // TODO -- define inst points in define function ?
1168 // The functions cannot be verified until all of them have been seen
1169 // because calls out of each function must be tagged as calls to user
1170 // functions or call to "library" functions
1174 SymbolIter symIter(linkedFile);
1176 // sort the modules by address into a vector to allow a binary search to
1177 // determine the module that a symbol will map to -- this may be bsd specific
1178 vector<Symbol> mods;
1180 while (symIter.next(symString, lookUp)) {
1182 if (lookUp.type() == Symbol::PDST_MODULE) {
1183 const char *str = (lookUp.name()).string_of();
1185 int ln = P_strlen(str);
1187 // directory definition -- ignored for now
1188 if (str[ln-1] != '/')
1190 // string temp = string("NEW MODULE: ");
1191 // temp += lookUp.name();
1192 // temp += string("\n");
1193 // logLine(P_strdup(temp.string_of()));
1197 // sort the modules by address
1198 mods.sort(symCompare);
1199 // assert(mods.sorted(symCompare));
1201 // remove duplicate entries -- some .o files may have the same address as .C files
1202 // kludge is true for module symbols that I am guessing are modules
1203 vector<Symbol> uniq;
1206 // must use loop+1 not mods.size()-1 since it is an unsigned compare
1207 // which could go negative - jkh 5/29/95
1208 for (loop=0; loop < mods.size(); loop++) {
1209 if ((loop+1 < mods.size()) &&
1210 (mods[loop].addr() == mods[loop+1].addr())) {
1211 if (!mods[loop].kludge())
1212 mods[loop+1] = mods[loop];
1217 // define all of the functions
1218 if (!addAllSharedObjFunctions(uniq, libModule, dynModule)) {
1222 checkAllCallPoints();
1224 // TODO -- remove duplicates -- see earlier note
1225 dictionary_hash<unsigned, unsigned> addr_dict(uiHash);
1226 vector<pd_Function*> temp_vec;
1227 unsigned f_size = mdlLib.size(), index;
1228 for (index=0; index<f_size; index++) {
1229 const unsigned the_address = (unsigned)mdlLib[index]->getAddress(0);
1230 if (!addr_dict.defines(the_address)) {
1231 addr_dict[the_address] = 1;
1232 temp_vec += mdlLib[index];
1236 temp_vec.resize(0); addr_dict.clear();
1237 f_size = mdlNormal.size();
1238 for (index=0; index<f_size; index++) {
1239 const unsigned the_address = (unsigned)mdlNormal[index]->getAddress(0);
1240 if (!addr_dict.defines(the_address)) {
1241 addr_dict[the_address] = 1;
1242 temp_vec += mdlNormal[index];
1245 mdlNormal = temp_vec;
1250 void pdmodule::checkAllCallPoints() {
1251 unsigned fsize = funcs.size();
1252 for (unsigned f=0; f<fsize; f++)
1253 funcs[f]->checkCallPoints();
1257 void image::checkAllCallPoints() {
1258 dictionary_hash_iter<string, pdmodule*> di(modsByFullName);
1259 string s; pdmodule *mod;
1260 while (di.next(s, mod))
1261 mod->checkAllCallPoints();
1264 // passing in tags allows a function to be tagged as TAG_LIB_FUNC even
1265 // if its entry is not in the tag dictionary of known functions
1266 bool image::defineFunction(pdmodule *use, const Symbol &sym, const unsigned tags,
1267 pd_Function *&retFunc) {
1268 // We used to skip a leading underscore, but not anymore.
1269 // (I forgot why we ever did in the first place)
1271 unsigned dictTags = findTags(sym.name());
1272 return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags | dictTags, retFunc));
1275 pdmodule *image::getOrCreateModule(const string &modName,
1276 const Address modAddr) {
1277 const char *str = modName.string_of();
1278 int len = modName.length();
1281 // TODO ignore directory definitions for now
1282 if (str[len-1] == '/') {
1285 // TODO - navigate ".." and "."
1286 const char *lastSlash = P_strrchr(str, '/');
1288 return (newModule(++lastSlash, modAddr));
1290 return (newModule(modName, modAddr));
1294 // KLUDGE TODO - internal functions are tagged with TAG_LIB_FUNC
1295 // but they won't have tags in the tag dict, so this happens...
1296 bool image::defineFunction(pdmodule *libModule, const Symbol &sym,
1297 const string &modName, const Address modAddr,
1298 pd_Function *&retFunc) {
1300 // We used to skip a leading underscore, but not any more.
1302 unsigned tags = findTags(sym.name());
1304 if (TAG_LIB_FUNC & tags)
1305 return (newFunc(libModule, sym.name(), sym.addr(), sym.size(),
1306 tags | TAG_LIB_FUNC, retFunc));
1308 pdmodule *use = getOrCreateModule(modName, modAddr);
1310 return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags, retFunc));
1314 // Verify that this is code
1315 // Find the call points
1316 // Find the return address
1317 // TODO -- use an instruction object to remove
1318 // Sets err to false on error, true on success
1320 // Note - this must define funcEntry and funcReturn
1322 pd_Function::pd_Function(const string &symbol, const string &pretty,
1323 pdmodule *f, Address adr, const unsigned size,
1324 const unsigned tg, const image *owner, bool &err) :
1325 function_base(symbol, pretty, adr, size,tg),
1330 err = findInstPoints(owner) == false;