diff --git a/dyninstAPI/h/BPatch_function.h b/dyninstAPI/h/BPatch_function.h index 93b7c4c..4968de2 100644 --- a/dyninstAPI/h/BPatch_function.h +++ b/dyninstAPI/h/BPatch_function.h @@ -273,12 +273,12 @@ public: BPatch_Vector *,findPoint,(const BPatch_Set& ops)); - // BPatch_function::createPointAtAddr + // BPatch_function::findPoint // // Returns a BPatch_point that corresponds with the provided address. Returns NULL // if the address does not correspond with an instruction. API_EXPORT(Int, (addr), - BPatch_point *, createPointAtAddr, (Dyninst::Address addr)); + BPatch_point *, findPoint, (Dyninst::Address addr)); // BPatch_function::findLocalVar diff --git a/dyninstAPI/h/BPatch_image.h b/dyninstAPI/h/BPatch_image.h index cace2b1..f5c834b 100644 --- a/dyninstAPI/h/BPatch_image.h +++ b/dyninstAPI/h/BPatch_image.h @@ -51,6 +51,7 @@ class process; class image; class int_variable; class BPatch_point; +class BPatch_object; #ifdef IBM_BPATCH_COMPAT @@ -87,6 +88,7 @@ class BPATCH_DLL_EXPORT BPatch_image: public BPatch_sourceObj, public BPatch_eve friend class BPatch_addressSpace; friend class BPatch_binaryEdit; friend Dyninst::PatchAPI::PatchMgrPtr Dyninst::PatchAPI::convert(const BPatch_image *); + friend class BPatch_object; BPatch_variableExpr *findOrCreateVariable(int_variable *); public: @@ -97,6 +99,7 @@ class BPATCH_DLL_EXPORT BPatch_image: public BPatch_sourceObj, public BPatch_eve BPatch_image(BPatch_addressSpace *addSpace); BPatch_image(); BPatch_module *findModule(mapped_module *base); + BPatch_object *findObject(mapped_object *base); virtual ~BPatch_image(); void getNewCodeRegions (std::vector&newFuncs, @@ -171,6 +174,12 @@ class BPATCH_DLL_EXPORT BPatch_image: public BPatch_sourceObj, public BPatch_eve API_EXPORT(Int, (), BPatch_Vector *,getModules,()); + // BPatch_image::getObjects + // + // Returns a vector of all objects in this image + API_EXPORT_V(Int, (objs), + void, getObjects, (std::vector &objs)); + API_EXPORT(Int, (mods), bool,getModules,(BPatch_Vector &mods)); @@ -249,13 +258,13 @@ class BPATCH_DLL_EXPORT BPatch_image: public BPatch_sourceObj, public BPatch_eve BPatch_type *,findType,(const char *name)); - // BPatch_image::createPointsAtAddr + // BPatch_image::findPoints // // Returns a vector of BPatch_points that correspond with the provided address, one // per function that includes an instruction at that address. Will have one element // if there is not overlapping code. API_EXPORT(Int, (addr, points), - bool, createPointsAtAddr, (Dyninst::Address addr, std::vector &points)); + bool, findPoints, (Dyninst::Address addr, std::vector &points)); // BPatch_image::getAddressRanges // @@ -342,6 +351,7 @@ private: BPatch_module *defaultModule; BPatch_module *findOrCreateModule(mapped_module *base); + BPatch_object *findOrCreateObject(mapped_object *base); void removeModule(BPatch_module *mod); void removeAllModules(); @@ -349,7 +359,15 @@ private: #pragma warning(push) #pragma warning(disable:4251) #endif - BPatch_Vector modlist; + typedef std::map ModMap; + typedef std::map ObjMap; + + ModMap modmap; + ObjMap objmap; + + // Annoying backwards-compatible return type + std::vector modlist; + BPatch_Vector removed_list; BPatch_Vector unresolvedCF; #if defined(_MSC_VER) diff --git a/dyninstAPI/h/BPatch_module.h b/dyninstAPI/h/BPatch_module.h index 6b8e6d4..2fa0fb2 100644 --- a/dyninstAPI/h/BPatch_module.h +++ b/dyninstAPI/h/BPatch_module.h @@ -103,7 +103,6 @@ class BPATCH_DLL_EXPORT BPatch_module: public BPatch_sourceObj, public BPatch_ev typedef std::map BPatch_funcMap; typedef std::map BPatch_varMap; typedef std::map BPatch_instpMap; - BPatch_addressSpace *addSpace; @@ -218,13 +217,13 @@ public: bool incUninstrumentable=false)); - // BPatch_module::createPointsAtAddr + // BPatch_module::findPoints // // Returns a vector of BPatch_points that correspond with the provided address, one // per function that includes an instruction at that address. Will have one element // if there is not overlapping code. API_EXPORT(Int, (addr, points), - bool, createPointsAtAddr, (Dyninst::Address addr, std::vector &points)); + bool, findPoints, (Dyninst::Address addr, std::vector &points)); // BPatch_module::dumpMangled diff --git a/dyninstAPI/h/BPatch_object.h b/dyninstAPI/h/BPatch_object.h new file mode 100644 index 0000000..9f336e9 --- /dev/null +++ b/dyninstAPI/h/BPatch_object.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 1996-2011 Barton P. Miller + * + * We provide the Paradyn Parallel Performance Tools (below + * described as "Paradyn") on an AS IS basis, and do not warrant its + * validity or performance. We reserve the right to update, modify, + * or discontinue this software at any time. We shall have no + * obligation to supply such updates or modifications or any other + * form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BPatch_object_h_ +#define _BPatch_object_h_ + +#include +#include +#include "dyntypes.h" +#include "BPatch_eventLock.h" + +class mapped_object; +class BPatch_addressSpace; +class AddressSpace; +class BPatch_image; +class BPatch_module; +class BPatch_object; +class BPatch_function; +class BPatch_point; + +namespace Dyninst { + namespace ParseAPI { + class CodeObject; + CodeObject *convert(const BPatch_object *); + } + namespace PatchAPI { + class PatchObject; + PatchObject *convert(const BPatch_object *); + } + namespace SymtabAPI { + class Symtab; + Symtab *convert(const BPatch_object *); + } +} + +#ifdef DYNINST_CLASS_NAME +#undef DYNINST_CLASS_NAME +#endif +#define DYNINST_CLASS_NAME BPatch_object + + + +class BPATCH_DLL_EXPORT BPatch_object: public BPatch_eventLock { + + friend Dyninst::ParseAPI::CodeObject *Dyninst::ParseAPI::convert(const BPatch_object *); + friend Dyninst::PatchAPI::PatchObject *Dyninst::PatchAPI::convert(const BPatch_object *); + friend Dyninst::SymtabAPI::Symtab *Dyninst::SymtabAPI::convert(const BPatch_object *); + friend class BPatch_image; + friend class BPatch_module; + + BPatch_image *img; + mapped_object *obj; + std::vector mods; + + BPatch_object(mapped_object *o, BPatch_image *i); + + AddressSpace *ll_as(); + BPatch_addressSpace *as(); + + public: + + struct Region { + typedef enum { + UNKNOWN, + CODE, + DATA } type_t; + + Dyninst::Address base; + unsigned long size; + type_t type; + + std::string format(); + + Region() : base(0), size(0), type(UNKNOWN) {}; + Region(Dyninst::Address b, unsigned long s, type_t t) : base(b), size(s), type(t) {}; + }; + + static const Dyninst::Address E_OUT_OF_BOUNDS; + + // BPatch_object::name + // Returns the file name of the object + API_EXPORT(Int, (), + std::string, name, ()); + + // BPatch_object::pathName + // Returns the full pathname of the object + API_EXPORT(Int, (), + std::string, pathName, ()); + + + // BPatch_object::offsetToAddr + // Converts a file offset into an absolute address suitable for use in looking up + // functions or points. + // For dynamic instrumentation, this is an address in memory. + // For binary rewriting, this is an offset that can be treated as an address. + // Returns E_OUT_OF_BOUNDS (-1) on failure + API_EXPORT(Int, (offset), + Dyninst::Address, offsetToAddr, (const Dyninst::Offset offset)); + + // BPatch_object::regions + // Returns a vector of address ranges occupied by this object + // May be multiple if there are multiple disjoint ranges, such as + // separate code and data or multiple code regions + // Ranges are returned as (base, size, type) tuples. + API_EXPORT_V(Int, (regions), + void, regions, (std::vector ®ions)); + + // BPatch_object::modules + // Returns a vector of BPatch_modules logically contained in this + // object. + // By design, shared libraries contain a single module; executable files contain one or more. + API_EXPORT_V(Int, (modules), + void, modules, (std::vector &modules)); + + // BPatch_object::findFunction + // Returns a vector of functions matching the provided name + // Maps this operation over its contained modules + // For backwards compatibility, returns a pointer to the vector argument. + + API_EXPORT(Int, (name, funcs, notify_on_failure, regex_case_sensitive, incUninstrumentable, dont_use_regex), + std::vector *,findFunction,(std::string name, + std::vector &funcs, + bool notify_on_failure =true, + bool regex_case_sensitive =true, + bool incUninstrumentable =false, + bool dont_use_regex = false)); + + // BPatch_object::findPoints + // + // Returns a vector of BPatch_points that correspond with the provided address, one + // per function that includes an instruction at that address. Will have one element + // if there is not overlapping code. + API_EXPORT(Int, (addr, points), + bool, findPoints, (Dyninst::Address addr, std::vector &points)); + +}; + +#endif + + + + + diff --git a/dyninstAPI/make.module.tmpl b/dyninstAPI/make.module.tmpl index 17a2470..0cfdd87 100644 --- a/dyninstAPI/make.module.tmpl +++ b/dyninstAPI/make.module.tmpl @@ -96,6 +96,7 @@ SRCS += ../src/BPatch.C \ ../src/BPatch_process.C \ ../src/BPatch_type.C \ ../src/BPatch_module.C \ + ../src/BPatch_object.C \ ../src/BPatch_point.C \ ../src/BPatch_collections.C \ ../src/BPatch_sourceBlock.C \ @@ -203,6 +204,7 @@ PUBLIC_H = BPatch_addressSpace.h \ BPatch_loopTreeNode.h \ BPatch_memoryAccess_NP.h \ BPatch_module.h \ + BPatch_object.h \ BPatch_parRegion.h \ BPatch_point.h \ BPatch_process.h \ diff --git a/dyninstAPI/src/BPatch_function.C b/dyninstAPI/src/BPatch_function.C index 83bed93..6809463 100644 --- a/dyninstAPI/src/BPatch_function.C +++ b/dyninstAPI/src/BPatch_function.C @@ -643,12 +643,12 @@ BPatch_Vector *BPatch_function::findPointByOp( } /* - * BPatch_function::createPointAtAddr + * BPatch_function::findPoint * * Create a BPatch_point corresponding with the provided address. */ -BPatch_point *BPatch_function::createPointAtAddrInt(Dyninst::Address addr) { +BPatch_point *BPatch_function::findPointInt(Dyninst::Address addr) { // Find the matching block and feed this into block_instance *llb = lowlevel_func()->getBlock(addr); diff --git a/dyninstAPI/src/BPatch_image.C b/dyninstAPI/src/BPatch_image.C index 497016f..98e0024 100644 --- a/dyninstAPI/src/BPatch_image.C +++ b/dyninstAPI/src/BPatch_image.C @@ -54,6 +54,7 @@ #include "BPatch_statement.h" #include "BPatch_function.h" #include "BPatch_point.h" +#include "BPatch_object.h" #include "addressSpace.h" #include "debug.h" @@ -92,8 +93,11 @@ BPatch_image::BPatch_image() : */ BPatch_image::~BPatch_image() { - for (unsigned int i = 0; i < modlist.size(); i++) { - delete modlist[i]; + for (ModMap::iterator iter = modmap.begin(); iter != modmap.end(); ++iter) { + delete iter->second; + } + for (ObjMap::iterator iter = objmap.begin(); iter != objmap.end(); ++iter) { + delete iter->second; } for (unsigned j = 0; j < removed_list.size(); j++) { @@ -300,8 +304,8 @@ BPatch_Vector *BPatch_image::getModulesInt() // We may have created a singleton module already -- check to see that we // don't double-create - for (unsigned i = 0; i < modules.size(); i++ ) { - mapped_module *map_mod = modules[i]; + for (unsigned j = 0; j < modules.size(); j++ ) { + mapped_module *map_mod = modules[j]; findOrCreateModule(map_mod); } } @@ -309,6 +313,26 @@ BPatch_Vector *BPatch_image::getModulesInt() return &modlist; } +void BPatch_image::getObjectsInt(std::vector &objs) { + // Make sure modules are created; we don't delay these + getModules(); + + std::vector as; + addSpace->getAS(as); + + for (unsigned i=0; i &objs = as[i]->mappedObjects(); + + for (unsigned j = 0; j < objs.size(); j++) { + findOrCreateObject(objs[j]); + } + } + + for (ObjMap::iterator iter = objmap.begin(); iter != objmap.end(); ++iter) { + objs.push_back(iter->second); + } +} + /* * BPatch_image::findModule * @@ -326,8 +350,8 @@ BPatch_module *BPatch_image::findModuleInt(const char *name, bool substring_matc BPatch_module *target = NULL; - for (unsigned int i = 0; i < modlist.size(); ++i) { - BPatch_module *mod = modlist[i]; + for (ModMap::iterator iter = modmap.begin(); iter != modmap.end(); ++iter) { + BPatch_module *mod = iter->second; assert(mod); mod->getName(buf, 512); if (substring_match) { @@ -953,28 +977,44 @@ int BPatch_image::lpTypeInt() BPatch_module *BPatch_image::findModule(mapped_module *base) { - BPatch_module *bpm = NULL; - for (unsigned j = 0; j < modlist.size(); j++) { - if (modlist[j]->lowlevel_mod() == base) { - bpm = modlist[j]; - break; - } - } - return bpm; + ModMap::iterator iter = modmap.find(base); + if (iter != modmap.end()) return iter->second; + return NULL; +} + +BPatch_object *BPatch_image::findObject(mapped_object *base) +{ + std::map::iterator iter = objmap.find(base); + if (iter != objmap.end()) return iter->second; + return NULL; } BPatch_module *BPatch_image::findOrCreateModule(mapped_module *base) { BPatch_module *bpm = findModule(base); - + if (bpm == NULL) { bpm = new BPatch_module( addSpace, base->proc(), base, this ); - modlist.push_back( bpm ); + modmap[base] = bpm; + modlist.push_back(bpm); + assert(modmap.size() == modlist.size()); } assert(bpm != NULL); return bpm; } +BPatch_object *BPatch_image::findOrCreateObject(mapped_object *base) +{ + BPatch_object *bpo = findObject(base); + + if (bpo == NULL) { + bpo = new BPatch_object( base, this ); + objmap[base] = bpo; + } + assert(bpo != NULL); + return bpo; +} + /* BPatch_image::parseNewFunctions * @@ -1090,27 +1130,20 @@ bool BPatch_image::parseNewFunctionsInt void BPatch_image::removeAllModules() { - BPatch_Vector::iterator i; - for (i = modlist.begin(); i != modlist.end(); i++) - { - (*i)->handleUnload(); + for (ModMap::iterator iter = modmap.begin(); iter != modmap.end(); ++iter) { + iter->second->handleUnload(); } + modmap.clear(); modlist.clear(); } void BPatch_image::removeModule(BPatch_module *mod) { -#if !defined(USE_DEPRECATED_BPATCH_VECTOR) + modmap.erase(mod->lowlevel_mod()); modlist.erase(std::find(modlist.begin(), - modlist.end(), - mod)); -#else - for (unsigned j = 0; j < modlist.size(); j++) { - if (modlist[j] == mod) { - modlist.erase(j); - } - } -#endif + modlist.end(), + mod)); + assert(modmap.size() == modlist.size()); mod->handleUnload(); } @@ -1291,14 +1324,14 @@ Dyninst::PatchAPI::PatchMgrPtr Dyninst::PatchAPI::convert(const BPatch_image *i) return Dyninst::PatchAPI::convert(i->addSpace); } -bool BPatch_image::createPointsAtAddrInt(Dyninst::Address addr, +bool BPatch_image::findPointsInt(Dyninst::Address addr, std::vector &points) { BPatch_Vector *mods = getModules(); bool ret = false; for (unsigned int i = 0; i < (unsigned) mods->size(); i++) { - if ((*mods)[i]->createPointsAtAddr(addr, points)) + if ((*mods)[i]->findPoints(addr, points)) ret = true; } return ret; diff --git a/dyninstAPI/src/BPatch_module.C b/dyninstAPI/src/BPatch_module.C index 775bdcc..9e98cfc 100644 --- a/dyninstAPI/src/BPatch_module.C +++ b/dyninstAPI/src/BPatch_module.C @@ -1060,7 +1060,7 @@ std::vector BPatch_module::getStatementsInt() } #endif -bool BPatch_module::createPointsAtAddrInt(Dyninst::Address addr, +bool BPatch_module::findPointsInt(Dyninst::Address addr, std::vector &points) { mapped_object *obj = mod->obj(); block_instance *blk = obj->findOneBlockByAddr(addr); diff --git a/dyninstAPI/src/BPatch_object.C b/dyninstAPI/src/BPatch_object.C new file mode 100644 index 0000000..75a3712 --- /dev/null +++ b/dyninstAPI/src/BPatch_object.C @@ -0,0 +1,171 @@ +/* + * Copyright (c) 1996-2011 Barton P. Miller + * + * We provide the Paradyn Parallel Performance Tools (below + * described as "Paradyn") on an AS IS basis, and do not warrant its + * validity or performance. We reserve the right to update, modify, + * or discontinue this software at any time. We shall have no + * obligation to supply such updates or modifications or any other + * form of support to you. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include "BPatch_object.h" +#include "BPatch_image.h" +#include "mapped_object.h" +#include "BPatch_module.h" +#include "dyntypes.h" +#include "function.h" +#include "block.h" + +const Dyninst::Address BPatch_object::E_OUT_OF_BOUNDS((Dyninst::Address) -1); + +struct getMod { + void operator()(mapped_module *m) { + BPatch_module *mod = img->findModule(m); + if (mod) mods.push_back(mod); + } + getMod(BPatch_image *i, std::vector &m) : img(i), mods(m) {}; + BPatch_image *img; + std::vector &mods; +}; + +BPatch_object::BPatch_object(mapped_object *o, BPatch_image *i) : + img(i), obj(o) { + // Fill in module list + const pdvector &ll_mods = obj->getModules(); + getMod gm(img, mods); + std::for_each(ll_mods.begin(), ll_mods.end(), gm); +} + +AddressSpace *BPatch_object::ll_as() { return obj->proc(); } + +BPatch_addressSpace *BPatch_object::as() { return img->getAddressSpace(); } + +std::string BPatch_object::nameInt() { + return obj->fileName(); +} + +std::string BPatch_object::pathNameInt() { + return obj->fullName(); +} + +Dyninst::Address BPatch_object::offsetToAddrInt(const Dyninst::Offset offset) { + if (offset >= obj->imageOffset() && + offset < (obj->imageOffset() + obj->imageSize())) { + return offset + obj->codeAbs(); + } + if (offset >= obj->dataOffset() && + offset < (obj->dataOffset() + obj->dataSize())) { + return offset + obj->dataAbs(); + } + + return E_OUT_OF_BOUNDS; +} + +void BPatch_object::regionsInt(std::vector ®ions) { + regions.push_back(Region(obj->codeAbs(), obj->imageSize(), Region::CODE)); + regions.push_back(Region(obj->dataAbs(), obj->dataSize(), Region::DATA)); +} + +void BPatch_object::modulesInt(std::vector &modules) { + std::copy(mods.begin(), mods.end(), std::back_inserter(modules)); +} + +struct findFunc { + void operator()(BPatch_module *mod) { + mod->findFunction(name.c_str(), funcs, + notify_on_failure, regex_case_sensitive, + incUninstrumentable, dont_use_regex); + } + + findFunc(std::string n, + std::vector &f, + bool n_o_f, bool r, bool i, bool d) : + name(n), funcs(f), notify_on_failure(n_o_f), + regex_case_sensitive(r), incUninstrumentable(i), dont_use_regex(d) {}; + + std::string name; + std::vector &funcs; + bool notify_on_failure; + bool regex_case_sensitive; + bool incUninstrumentable; + bool dont_use_regex; +}; + +std::vector *BPatch_object::findFunctionInt(std::string name, + std::vector &funcs, + bool notify_on_failure, + bool regex_case_sensitive, + bool incUninstrumentable, + bool dont_use_regex) { + findFunc f(name, funcs, notify_on_failure, regex_case_sensitive, + incUninstrumentable, dont_use_regex); + std::for_each(mods.begin(), mods.end(), f); + return &funcs; +} + + +bool BPatch_object::findPointsInt(Dyninst::Address addr, + std::vector &points) { + block_instance *blk = obj->findOneBlockByAddr(addr); + if (!blk) return false; + + std::vector funcs; + blk->getFuncs(std::back_inserter(funcs)); + for (unsigned i = 0; i < funcs.size(); ++i) { + BPatch_module *bpmod = img->findOrCreateModule(funcs[i]->mod()); + BPatch_function *bpfunc = as()->findOrCreateBPFunc(funcs[i], bpmod); + if (!bpfunc) continue; + instPoint *p = instPoint::preInsn(funcs[i], blk, addr); + if (!p) continue; + BPatch_point *pbp = as()->findOrCreateBPPoint(bpfunc, p, BPatch_locInstruction); + if (pbp) points.push_back(pbp); + } + return true; +} + +std::string BPatch_object::Region::format() { + std::stringstream ret; + + ret << "[" << hex << base << "," << (base + size) << "," + << ((type == CODE) ? "CODE" : "DATA") << "]"; + return ret.str(); +} + +Dyninst::ParseAPI::CodeObject *Dyninst::ParseAPI::convert(const BPatch_object *o) { + if (!o->obj) return NULL; + return o->obj->parse_img()->codeObject(); +} + +Dyninst::PatchAPI::PatchObject *Dyninst::PatchAPI::convert(const BPatch_object *o) { + if (!o) return NULL; + return o->obj; +} + +Dyninst::SymtabAPI::Symtab *Dyninst::SymtabAPI::convert(const BPatch_object *o) { + if (!o) return NULL; + return o->obj->parse_img()->getObject(); +} +