{"id":299,"date":"2014-02-20T11:43:50","date_gmt":"2014-02-20T16:43:50","guid":{"rendered":"http:\/\/blog.mozilla.org\/nfroyd\/?p=299"},"modified":"2014-02-20T11:43:50","modified_gmt":"2014-02-20T16:43:50","slug":"finding-addresses-of-virtual-functions","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/nfroyd\/2014\/02\/20\/finding-addresses-of-virtual-functions\/","title":{"rendered":"finding addresses of virtual functions"},"content":{"rendered":"<p>Somebody on <tt>#developers<\/tt> this morning wanted to know if there was an easy way to find the address of the virtual function that would be called on a given object&#8230;without a debugger.  Perhaps this address could be printed to a logfile for later analysis.  Perhaps it just sounds like an interesting exercise.<\/p>\n<p>Since my first attempt had the right idea, but was incomplete in some details, I thought I&#8217;d share the actual solution.  The solution is highly dependent on the details of the C++ ABI for your particular platform; the code below is for Linux and Mac.  If somebody wants to write up a solution for Windows, where the size of pointer-to-member functions can vary (!), I&#8217;d love to see it.<\/p>\n<pre>include <stddef.h>\r\n#include <string.h>\r\n\r\n\/* AbstractClass may have several different concrete implementations.  *\/\r\nclass AbstractClass {\r\npublic:\r\n  virtual int f() = 0;\r\n  virtual int g() = 0;\r\n};\r\n\r\n\/* Return the address of the `f' function of `aClass' that would be\r\n   called for the expression:\r\n\r\n   aClass->f();\r\n\r\n   regardless of the concrete type of `aClass'.\r\n\r\n   It is left as an exercise for the reader to templatize this function for\r\n   arbitrary `f'.  *\/\r\nvoid*\r\nfind_f_address(AbstractClass* aClass)\r\n{\r\n  \/* The virtual function table is stored at the beginning of the object.  *\/\r\n  void** vtable = *(void***)aClass;\r\n\r\n  \/* This structure is described in the cross-platform \"Itanium\" C++ ABI:\r\n\r\n     http:\/\/mentorembedded.github.io\/cxx-abi\/abi.html\r\n\r\n     The particular layout replicated here is described in:\r\n\r\n     http:\/\/mentorembedded.github.io\/cxx-abi\/abi.html#member-pointers  *\/\r\n  struct pointerToMember\r\n  {\r\n    \/* This field has separate representations for non-virtual and virtual\r\n       functions.  For non-virtual functions, this field is simply the\r\n       address of the function.  For our case, virtual functions, this\r\n       field is 1 plus the virtual table offset (in bytes) of the function\r\n       in question.  The least-significant bit therefore discriminates\r\n       between virtual and non-virtual functions.\r\n\r\n       \"Ah,\" you say, \"what about architectures where function pointers do\r\n       not necessarily have even addresses?\"  (ARM, MIPS, and AArch64 are\r\n       the major ones.)  Excellent point.  Please see below.  *\/\r\n    size_t pointerOrOffset;\r\n\r\n    \/* This field is only interesting for calling the function; it\r\n       describes the amount that the `this' pointer must be adjusted\r\n       prior to the call.  However, on architectures where function\r\n       pointers do not necessarily have even addresses, this field has the\r\n       representation:\r\n\r\n       2 * adjustment + (virtual_function_p ? 1 : 0)  *\/\r\n    ptrdiff_t thisAdjustment;\r\n  };\r\n\r\n  \/* Translate from the opaque pointer-to-member type representation to\r\n     the representation given above.  *\/\r\n  pointerToMember p;\r\n  int ((AbstractClass::*m)()) = &AbstractClass::f;\r\n  memcpy(&p, &m, sizeof(p));\r\n\r\n  \/* Compute the actual offset into the vtable.  Given the differing meaing\r\n     of the fields between architectures, as described above, and that\r\n     there's no convenient preprocessor macro, we have to do this\r\n     ourselves.  *\/\r\n#if defined(__arm__) || defined(__mips__) || defined(__aarch64__)\r\n  \/* No adjustment required to `pointerOrOffset'.  *\/\r\n  static const size_t pfnAdjustment = 0;\r\n#else\r\n  \/* Strip off the lowest bit of `pointerOrOffset'.  *\/\r\n  static const size_t pfnAdjustment = 1;\r\n#endif\r\n\r\n  size_t offset = (p.pointerOrOffset - pfnAdjustment) \/ sizeof(void*);\r\n\r\n  \/* Now grab the address out of the vtable and return it.  *\/\r\n  return vtable[offset];\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Somebody on #developers this morning wanted to know if there was an easy way to find the address of the virtual function that would be called on a given object&#8230;without a debugger. Perhaps this address could be printed to a logfile for later analysis. Perhaps it just sounds like an interesting exercise. Since my first [&hellip;]<\/p>\n","protected":false},"author":320,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/posts\/299"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/users\/320"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/comments?post=299"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/posts\/299\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/media?parent=299"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/categories?post=299"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/nfroyd\/wp-json\/wp\/v2\/tags?post=299"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}