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 resource::send_now();
656 static inline bool findStartSymbol(Object &lf, Address &adr) {
659 if (lf.get_symbol("DYNINSTstartUserCode", lookUp) ||
660 lf.get_symbol("_DYNINSTstartUserCode", lookUp)) {
667 static inline bool findEndSymbol(Object &lf, Address &adr) {
670 if (lf.get_symbol("DYNINSTendUserCode", lookUp) ||
671 lf.get_symbol("_DYNINSTendUserCode", lookUp)) {
678 // TODO this assumes an ordering in the symbol table wrt modules KLUDGE
679 static inline bool notInUserRange(const Address adr,
680 const bool start, const Address startAdr,
681 const bool end, const Address endAdr) {
682 return ((start && (adr < startAdr)) || (end && (adr >= endAdr)));
685 static void binSearch (const Symbol &lookUp, vector<Symbol> &mods,
686 string &modName, Address &modAddr, const string &def) {
687 int start=0, end=mods.size()-1, index;
696 while ((start <= end) && !found) {
697 index = (start+end)/2;
699 if ((index == (((int)mods.size())-1)) ||
700 ((mods[index].addr() <= lookUp.addr()) && (mods[index+1].addr() > lookUp.addr()))) {
701 modName = mods[index].name();
702 modAddr = mods[index].addr();
704 } else if (lookUp.addr() < mods[index].addr()) {
711 modName = mods[0].name();
712 modAddr = mods[0].addr();
716 bool image::addOneFunction(vector<Symbol> &mods, pdmodule *lib, pdmodule *dyn,
717 const Symbol &lookUp, pd_Function *&retFunc) {
720 // this is a "user" symbol
721 string modName = lookUp.module();
724 #if defined (sparc_sun_solaris2_4) || defined (i386_unknown_solaris2_5)
725 // In solaris there is no address for modules in the symbol table,
726 // so the binary search will not work. The module field in a symbol
727 // already has the correct module name for a symbol, if it can be
728 // obtained from the symbol table, otherwise the module is an empty
731 string progName = name_ + "_module";
735 binSearch(lookUp, mods, modName, modAddr, progName);
738 return (defineFunction(lib, lookUp, modName, modAddr, retFunc));
741 bool inLibrary(Address addr, Address boundary_start, Address boundary_end,
742 Address startAddr, bool startB,
743 Address endAddr, bool endB) {
744 if ((addr >= boundary_start) && (addr <= boundary_end))
747 if (addr <= startAddr)
765 bool image::addAllFunctions(vector<Symbol> &mods,
766 pdmodule *lib, pdmodule *dyn,
767 const bool startB, const Address startAddr,
768 const bool endB, const Address endAddr) {
770 Address boundary_start, boundary_end;
773 SymbolIter symIter(linkedFile);
775 #ifdef BPATCH_LIBRARY
776 boundary_start = boundary_end = NULL;
778 if (!linkedFile.get_symbol(symString="DYNINSTfirst", lookUp) &&
779 !linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)) {
780 //statusLine("Internal symbol DYNINSTfirst not found");
781 //showErrorCallback(31, "Internal symbol DYNINSTfirst not found");
783 boundary_start = NULL;
785 boundary_start = lookUp.addr();
787 if (!linkedFile.get_symbol(symString="DYNINSTend", lookUp) &&
788 !linkedFile.get_symbol(symString="_DYNINSTend", lookUp)) {
789 //statusLine("Internal symbol DYNINSTend not found");
790 //showErrorCallback(32, "Internal symbol DYNINSTend not found");
794 boundary_end = lookUp.addr();
797 Symbol mainFuncSymbol; //Keeps track of info on "main" function
799 //Checking "main" function names in same order as in the inst-*.C files
800 if (linkedFile.get_symbol(symString="main", lookUp) ||
801 linkedFile.get_symbol(symString="_main", lookUp) ||
802 linkedFile.get_symbol(symString="WinMain", lookUp) ||
803 linkedFile.get_symbol(symString="_WinMain", lookUp))
804 mainFuncSymbol = lookUp;
806 // find the real functions -- those with the correct type in the symbol table
807 while (symIter.next(symString, lookUp)) {
809 if (funcsByAddr.defines(lookUp.addr()) ||
810 ((lookUp.addr() == mainFuncSymbol.addr()) &&
811 (lookUp.name() != mainFuncSymbol.name()))) {
812 // This function has been defined
814 // This function has the same address as the "main" function but does
815 // not have the same name as the "main" function. Therefore, skip
816 // it and let the "main" function be eventually associated with this
817 // function address. If we don't do this, paradynd will not have a
818 // "main" function to start work with.
820 } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
821 if (!isValidAddress(lookUp.addr())) {
824 sprintf(tempBuffer,"%x",lookUp.addr());
825 msg = string("Function") + lookUp.name() + string("has bad address ") +
827 statusLine(msg.string_of());
828 showErrorCallback(29, msg);
832 if (inLibrary(lookUp.addr(), boundary_start, boundary_end,
833 startAddr, startB, endAddr, endB)) {
834 addInternalSymbol(lookUp.name(), lookUp.addr());
835 if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
836 assert(pdf); mdlLib += pdf;
839 if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
840 assert(pdf); mdlNormal += pdf;
846 // now find the pseudo functions -- this gets ugly
847 // kludge has been set if the symbol could be a function
849 while (symIter.next(symString, lookUp)) {
850 if (funcsByAddr.defines(lookUp.addr())) {
851 // This function has been defined
853 } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
854 //logLine(P_strdup(symString.string_of()));
856 if (inLibrary(lookUp.addr(), boundary_start, boundary_end,
857 startAddr, startB, endAddr, endB)) {
858 addInternalSymbol(lookUp.name(), lookUp.addr());
859 if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
860 assert(pdf); mdlLib += pdf;
863 if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
864 assert(pdf); mdlNormal += pdf;
872 bool image::addAllSharedObjFunctions(vector<Symbol> &mods,
873 pdmodule *lib, pdmodule *dyn) {
877 SymbolIter symIter(linkedFile);
879 bool is_libdyninstRT = false; // true if this image is libdyninstRT
880 #if defined(i386_unknown_nt4_0)
881 if (linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp)
882 || linkedFile.get_symbol(symString="_DYNINSTfirst", lookUp))
883 is_libdyninstRT = true;
886 // find the real functions -- those with the correct type in the symbol table
887 while (symIter.next(symString, lookUp)) {
889 if (funcsByAddr.defines(lookUp.addr())) {
890 // This function has been defined
892 } else if (lookUp.type() == Symbol::PDST_FUNCTION) {
893 if (!isValidAddress(lookUp.addr())) {
896 sprintf(tempBuffer,"%x",lookUp.addr());
897 msg = string("Function") + lookUp.name() + string("has bad address ") +
899 statusLine(msg.string_of());
900 showErrorCallback(29, msg);
904 if (is_libdyninstRT) {
905 addInternalSymbol(lookUp.name(), lookUp.addr());
906 if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
907 assert(pdf); mdlLib += pdf;
909 } else if (addOneFunction(mods, lib, dyn, lookUp, pdf)) {
910 assert(pdf); mdlNormal += pdf;
915 // now find the pseudo functions -- this gets ugly
916 // kludge has been set if the symbol could be a function
918 while (symIter.next(symString, lookUp)) {
919 if (funcsByAddr.defines(lookUp.addr())) {
920 // This function has been defined
922 } else if ((lookUp.type() == Symbol::PDST_OBJECT) && lookUp.kludge()) {
923 //logLine(P_strdup(symString.string_of()));
925 addInternalSymbol(lookUp.name(), lookUp.addr());
926 if (defineFunction(dyn, lookUp, TAG_LIB_FUNC, pdf)) {
927 assert(pdf); mdlLib += pdf;
935 int symCompare(const void *s1, const void *s2) {
936 const Symbol *sym1 = (const Symbol*)s1, *sym2 = (const Symbol*)s2;
938 return (sym1->addr() - sym2->addr());
942 unsigned int_addrHash(const unsigned &addr) {
946 // Please note that this is now machine independent-almost. Let us keep it that way
948 image::image(const string &fileName, bool &err)
949 : funcsByAddr(addrHash4),
950 modsByFileName(string::hash),
951 modsByFullName(string::hash),
953 linkedFile(fileName, pd_log_perror),
954 iSymsMap(string::hash),
955 funcsByPretty(string::hash),
956 knownJumpTargets(int_addrHash, 8192)
958 sharedobj_cerr << "image::image for non-sharedobj; file name=" << file_ << endl;
960 codeOffset_ = linkedFile.code_off();
961 dataOffset_ = linkedFile.data_off();
962 codeLen_ = linkedFile.code_len();
963 dataLen_ = linkedFile.data_len();
965 #if defined(hppa1_1_hp_hpux)
966 unwind = linkedFile.unwind;
969 if (!codeLen_ || !linkedFile.code_ptr()) {
970 string msg = string("Unable to open executable file: ") + fileName;
971 statusLine(msg.string_of());
974 logLine(msg.string_of());
978 showErrorCallback(27, msg);
982 #if !defined(i386_unknown_nt4_0)
984 if (!linkedFile.get_symbol("DYNINSTversion", version) &&
985 !linkedFile.get_symbol("_DYNINSTversion", version)) {
986 statusLine("Could not find version number in instrumentation\n");
987 showErrorCallback(33, "Could not find version number in instrumentation");
992 Word version_number = get_instruction(version.addr());
993 if (version_number != 1) {
995 msg = string("Incorrect version number, expected ") + string(1) +
996 string("found ") + string(version_number);
997 statusLine(msg.string_of());
998 showErrorCallback(30, msg);
1004 const char *nm = fileName.string_of();
1005 const char *pos = P_strrchr(nm, '/');
1013 // find the "user" code boundaries
1014 statusLine("finding user code boundaries");
1015 Address startUserAddr=0, endUserAddr=0;
1016 bool startBound = findStartSymbol(linkedFile, startUserAddr);
1017 bool endBound = findEndSymbol(linkedFile, endUserAddr);
1019 // use the *DUMMY_MODULE* until a module is defined
1020 pdmodule *dynModule = newModule(DYN_MODULE, 0);
1021 pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1022 // TODO -- define inst points in define function ?
1024 // The functions cannot be verified until all of them have been seen
1025 // because calls out of each function must be tagged as calls to user
1026 // functions or call to "library" functions
1030 SymbolIter symIter(linkedFile);
1032 // sort the modules by address into a vector to allow a binary search to
1033 // determine the module that a symbol will map to -- this may be bsd specific
1034 vector<Symbol> mods;
1036 while (symIter.next(symString, lookUp)) {
1038 if (lookUp.type() == Symbol::PDST_MODULE) {
1039 const string &lookUpName = lookUp.name();
1040 const char *str = lookUpName.string_of();
1042 int ln = lookUpName.length();
1044 // directory definition -- ignored for now
1045 if (str[ln-1] != '/')
1050 // sort the modules by address
1051 statusLine("sorting modules");
1052 mods.sort(symCompare);
1053 // assert(mods.sorted(symCompare));
1055 // remove duplicate entries -- some .o files may have the same address as .C files
1056 // kludge is true for module symbols that I am guessing are modules
1057 vector<Symbol> uniq;
1060 // must use loop+1 not mods.size()-1 since it is an unsigned compare
1061 // which could go negative - jkh 5/29/95
1062 for (loop=0; loop < mods.size(); loop++) {
1063 if ((loop+1 < mods.size()) &&
1064 (mods[loop].addr() == mods[loop+1].addr())) {
1065 if (!mods[loop].kludge())
1066 mods[loop+1] = mods[loop];
1071 // define all of the functions
1072 statusLine("winnowing functions");
1073 if (!addAllFunctions(uniq, libModule, dynModule, startBound, startUserAddr,
1074 endBound, endUserAddr)) {
1078 statusLine("checking call points");
1079 checkAllCallPoints();
1081 // statusLine("ready"); // this shouldn't be here, right? (cuz we're not really ready)
1083 // TODO -- remove duplicates -- see earlier note
1084 dictionary_hash<unsigned, unsigned> addr_dict(uiHash);
1085 vector<pd_Function*> temp_vec;
1086 unsigned f_size = mdlLib.size(), index;
1087 for (index=0; index<f_size; index++) {
1088 const unsigned the_address = (unsigned)mdlLib[index]->getAddress(0);
1089 if (!addr_dict.defines(the_address)) {
1090 addr_dict[the_address] = 1;
1091 temp_vec += mdlLib[index];
1095 temp_vec.resize(0); addr_dict.clear();
1096 f_size = mdlNormal.size();
1097 for (index=0; index<f_size; index++) {
1098 const unsigned the_address = (unsigned)mdlNormal[index]->getAddress(0);
1099 if (!addr_dict.defines(the_address)) {
1100 addr_dict[the_address] = 1;
1101 temp_vec += mdlNormal[index];
1104 mdlNormal = temp_vec;
1108 // load a shared object
1110 image::image(const string &fileName, u_int baseAddr, bool &err)
1111 : funcsByAddr(addrHash4),
1112 modsByFileName(string::hash),
1113 modsByFullName(string::hash),
1115 linkedFile(fileName, baseAddr,pd_log_perror),
1116 iSymsMap(string::hash),
1117 funcsByPretty(string::hash),
1118 knownJumpTargets(int_addrHash, 8192)
1120 sharedobj_cerr << "welcome to image::image for shared obj; file name=" << file_ << endl;
1122 codeOffset_ = linkedFile.code_off();
1123 dataOffset_ = linkedFile.data_off();
1124 codeLen_ = linkedFile.code_len();
1125 dataLen_ = linkedFile.data_len();
1126 //logLine("IN image::image\n");
1128 #if defined(hppa1_1_hp_hpux)
1129 unwind = linkedFile.unwind;
1132 if (!codeLen_ || !linkedFile.code_ptr()) {
1133 string msg = string("Unable to open shared object file: ") + fileName;
1134 statusLine(msg.string_of());
1137 logLine(msg.string_of());
1140 showErrorCallback(27, msg);
1147 string msg = string("Parsing shared object file: ") + fileName;
1148 statusLine(msg.string_of());
1151 const char *nm = fileName.string_of();
1152 const char *pos = P_strrchr(nm, '/');
1160 // use the *DUMMY_MODULE* until a module is defined
1161 pdmodule *dynModule = newModule(DYN_MODULE, 0);
1162 pdmodule *libModule = newModule(LIBRARY_MODULE, 0);
1163 // TODO -- define inst points in define function ?
1165 // The functions cannot be verified until all of them have been seen
1166 // because calls out of each function must be tagged as calls to user
1167 // functions or call to "library" functions
1171 SymbolIter symIter(linkedFile);
1173 // sort the modules by address into a vector to allow a binary search to
1174 // determine the module that a symbol will map to -- this may be bsd specific
1175 vector<Symbol> mods;
1177 while (symIter.next(symString, lookUp)) {
1179 if (lookUp.type() == Symbol::PDST_MODULE) {
1180 const char *str = (lookUp.name()).string_of();
1182 int ln = P_strlen(str);
1184 // directory definition -- ignored for now
1185 if (str[ln-1] != '/')
1187 // string temp = string("NEW MODULE: ");
1188 // temp += lookUp.name();
1189 // temp += string("\n");
1190 // logLine(P_strdup(temp.string_of()));
1194 // sort the modules by address
1195 mods.sort(symCompare);
1196 // assert(mods.sorted(symCompare));
1198 // remove duplicate entries -- some .o files may have the same address as .C files
1199 // kludge is true for module symbols that I am guessing are modules
1200 vector<Symbol> uniq;
1203 // must use loop+1 not mods.size()-1 since it is an unsigned compare
1204 // which could go negative - jkh 5/29/95
1205 for (loop=0; loop < mods.size(); loop++) {
1206 if ((loop+1 < mods.size()) &&
1207 (mods[loop].addr() == mods[loop+1].addr())) {
1208 if (!mods[loop].kludge())
1209 mods[loop+1] = mods[loop];
1214 // define all of the functions
1215 if (!addAllSharedObjFunctions(uniq, libModule, dynModule)) {
1219 checkAllCallPoints();
1221 // TODO -- remove duplicates -- see earlier note
1222 dictionary_hash<unsigned, unsigned> addr_dict(uiHash);
1223 vector<pd_Function*> temp_vec;
1224 unsigned f_size = mdlLib.size(), index;
1225 for (index=0; index<f_size; index++) {
1226 const unsigned the_address = (unsigned)mdlLib[index]->getAddress(0);
1227 if (!addr_dict.defines(the_address)) {
1228 addr_dict[the_address] = 1;
1229 temp_vec += mdlLib[index];
1233 temp_vec.resize(0); addr_dict.clear();
1234 f_size = mdlNormal.size();
1235 for (index=0; index<f_size; index++) {
1236 const unsigned the_address = (unsigned)mdlNormal[index]->getAddress(0);
1237 if (!addr_dict.defines(the_address)) {
1238 addr_dict[the_address] = 1;
1239 temp_vec += mdlNormal[index];
1242 mdlNormal = temp_vec;
1247 void pdmodule::checkAllCallPoints() {
1248 unsigned fsize = funcs.size();
1249 for (unsigned f=0; f<fsize; f++)
1250 funcs[f]->checkCallPoints();
1254 void image::checkAllCallPoints() {
1255 dictionary_hash_iter<string, pdmodule*> di(modsByFullName);
1256 string s; pdmodule *mod;
1257 while (di.next(s, mod))
1258 mod->checkAllCallPoints();
1261 // passing in tags allows a function to be tagged as TAG_LIB_FUNC even
1262 // if its entry is not in the tag dictionary of known functions
1263 bool image::defineFunction(pdmodule *use, const Symbol &sym, const unsigned tags,
1264 pd_Function *&retFunc) {
1265 // We used to skip a leading underscore, but not anymore.
1266 // (I forgot why we ever did in the first place)
1268 unsigned dictTags = findTags(sym.name());
1269 return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags | dictTags, retFunc));
1272 pdmodule *image::getOrCreateModule(const string &modName,
1273 const Address modAddr) {
1274 const char *str = modName.string_of();
1275 int len = modName.length();
1278 // TODO ignore directory definitions for now
1279 if (str[len-1] == '/') {
1282 // TODO - navigate ".." and "."
1283 const char *lastSlash = P_strrchr(str, '/');
1285 return (newModule(++lastSlash, modAddr));
1287 return (newModule(modName, modAddr));
1291 // KLUDGE TODO - internal functions are tagged with TAG_LIB_FUNC
1292 // but they won't have tags in the tag dict, so this happens...
1293 bool image::defineFunction(pdmodule *libModule, const Symbol &sym,
1294 const string &modName, const Address modAddr,
1295 pd_Function *&retFunc) {
1297 // We used to skip a leading underscore, but not any more.
1299 unsigned tags = findTags(sym.name());
1301 if (TAG_LIB_FUNC & tags)
1302 return (newFunc(libModule, sym.name(), sym.addr(), sym.size(),
1303 tags | TAG_LIB_FUNC, retFunc));
1305 pdmodule *use = getOrCreateModule(modName, modAddr);
1307 return (newFunc(use, sym.name(), sym.addr(), sym.size(), tags, retFunc));
1311 // Verify that this is code
1312 // Find the call points
1313 // Find the return address
1314 // TODO -- use an instruction object to remove
1315 // Sets err to false on error, true on success
1317 // Note - this must define funcEntry and funcReturn
1319 pd_Function::pd_Function(const string &symbol, const string &pretty,
1320 pdmodule *f, Address adr, const unsigned size,
1321 const unsigned tg, const image *owner, bool &err) :
1322 function_base(symbol, pretty, adr, size,tg),
1327 err = findInstPoints(owner) == false;