{"id":15243,"date":"2010-01-18T07:00:00","date_gmt":"2010-01-18T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2010\/01\/18\/its-fine-to-rename-a-function-in-your-def-file-but-when-you-do-you-have-to-link-to-that-function-by-its-new-name\/"},"modified":"2010-01-18T07:00:00","modified_gmt":"2010-01-18T07:00:00","slug":"its-fine-to-rename-a-function-in-your-def-file-but-when-you-do-you-have-to-link-to-that-function-by-its-new-name","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20100118-00\/?p=15243","title":{"rendered":"It&#039;s fine to rename a function in your DEF file, but when you do, you have to link to that function by its new name"},"content":{"rendered":"<p>\n<a HREF=\"http:\/\/www.castledragmire.com\">\nJeffrey Riaboy<\/a>\nasks why,\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/pages\/407234.aspx#759387\">\nif he renames a function in his DEF file,\nattempts to link to the function by its old name fail<\/a>.\n<\/p>\n<p>\nWell, um, yeah, because you renamed it.\n<\/p>\n<p>\nLet&#8217;s take the situation apart a bit;\nmaybe it&#8217;ll make more sense.\nI&#8217;m going to ignore a lot of details\n(<code>dllimport\/dllexport<\/code>,\ncalling conventions)\nsince they are not relevant to the discussion\nand would end up just being distracting.\nI&#8217;m also going to assume we are running on an x86-class machine,\njust for concreteness.\nThe same discussion works for other platforms; you just have to\nadjust the conventions accordingly.\n<\/p>\n<p>\nFirst, here is some source code for a DLL,\nlet&#8217;s call it <code>FRED.DLL<\/code>:\n<\/p>\n<pre>\nint Dabba()\n{\n  return 0;\n}\nint Doo()\n{\n  return 1;\n}\n<\/pre>\n<p>\nAnd here is the DEF file for <code>FRED.DLL<\/code>:\n<\/p>\n<pre>\nEXPORTS\n Yabba=Dabba\n Dabba=Doo\n<\/pre>\n<p>\nWhen you compile this DLL, the result will be something like this:\n<\/p>\n<pre>\nFRED.DLL:\n Yabba -&gt; return 0;\n Dabba -&gt; return 1;\n<\/pre>\n<p>\nThe function exported as <code>Yabba<\/code> returns <code>0<\/code>\nbecause the DEF file said,\n&#8220;I want to export a function with the exported name <code>Yabba<\/code>;\nwhen somebody calls the function, I want control to go to the\nfunction I called <code>Dabba<\/code> internally.&#8221;\n<\/p>\n<p>\nSimilarly, the function exported as <code>Dabba<\/code> returns <code>1<\/code>\nbecause the DEF file said,\n&#8220;I want to export a function with the exported name <code>Dabba<\/code>;\nwhen somebody calls the function, I want control to go to the\nfunction I called <code>Doo<\/code> internally.&#8221;\n<\/p>\n<p>\nRemember that symbolic information disappears during linking.\nThe names of the functions and variables in the original source\ncode are not stored anywhere in the DLL.\nThe names exist only so that the linker can resolve symbolic\nreferences between object files.\nOnce that&#8217;s done, the names are discarded: Their work is done.\n(See\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2009\/10\/12\/9905953.aspx\">\nThe classical model for linking<\/a>\nfor a discussion of how linking works under the classical model.)\n<\/p>\n<p>\nExported functions are also a mapping between labels and functions,\nbut this mapping is not used when linking the DLL;\nrather, it is just a table the linker produces under the direction\nof your <code>DEF<\/code> file.\nTo reduce confusion for the programmer writing the DLL,\nthe name in the exported function table usually matches the name\nin the object files, but that is merely a convention.\nAn entry in the export table that doesn&#8217;t perform renaming is\njust a shorthand for &#8220;I would like the exported name for this function\nto be the same as its internal name.&#8221;\nIt&#8217;s a convenient typing-saver.\n<\/p>\n<p>\nBy analogy,\nMicrosoft employees have one email address for use inside the company,\nand\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/10\/23\/9011948.aspx\">\na different email address for use outside the company<\/a>.\nSome employees choose to have their external email address be the same\nas their internal one,\nbut that is hardly a requirement.\n<\/p>\n<p>\nMeanwhile, the import library for our DLL looks something like this:\n<\/p>\n<pre>\nFRED.LIB:\n __imp__Yabba -&gt; FRED.Yabba\n __imp__Dabba -&gt; FRED.Dabba\n <a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/07\/27\/679634.aspx\">_Yabba@0<\/a> -&gt; <a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/07\/20\/672695.aspx\">jmp [__imp__Yabba]<\/a>\n _Dabba@0 -&gt; jmp [__imp__Dabba]\n<\/pre>\n<p>\nAs we saw before,\neach exported function\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/07\/21\/673830.aspx\">\nresults in two symbols in the import library<\/a>,\none with <code>__imp_<\/code> prepended to the exported name,\nwhich represents the import table entry,\nand one containing a stub function for the benefit of a na&iuml;ve\ncompiler.\n<\/p>\n<p>\nNow let&#8217;s look at a program that wants to call some functions from\n<code>FRED.DLL<\/code>:\n<\/p>\n<pre>\nint Flintstone()\n{\n Yabba();\n Dabba();\n Doo();\n}\n<\/pre>\n<p>\nLet&#8217;s say that these functions were not declared as\n<code>dllimport<\/code>, just for the sake of concreteness.\n(The discussion works the same if they were declared as\n<code>dllimport<\/code>, making the appropriate changes to the\nsymbol names.)\nWhen the linker goes to resolve the call to <code>Yabba@0<\/code>,\nit will find the entry in <code>FRED.DLL<\/code> that says,\n&#8220;I&#8217;ve got a function called <code>Yabba@0<\/code>; the code for it\nis the single instruction <code>jmp [__imp__Yabba]<\/code>.&#8221;\nWhen the program calls this function, the <code>jmp<\/code>\ninstruction will jump through the import table entry for\n<code>FRED.Yabba<\/code>,\nwhich will wind up at the function in <code>FRED.DLL<\/code>\nexported under the name <code>Yabba<\/code>.\nIf we look inside <code>FRED.DLL<\/code>, we see that this\nis a function that returns <code>0<\/code>\n(because it is the function which was called <code>Dabba<\/code>\nin the original source code, although that information was lost\na long time ago).\n<\/p>\n<p>\nSimilarly, when the linker resolves the call to <code>Dabba@0<\/code>,\nit finds the entry in <code>FRED.DLL<\/code> which pulls in the\none-line stub function which jumps through the import table\nentry for <code>Dabba@0<\/code>.\nThis leads to a function that returns <code>1<\/code>,\na function which was called <code>Doo<\/code>\nin the original source code.\n<\/p>\n<p>\nHowever, that last call to <code>Doo<\/code>\nraises a linker error because it cannot find a function called\n<code>Doo<\/code> in the <code>FRED.LIB<\/code> import library.\nThat&#8217;s just the internal name for a function in the source code\nfor <code>FRED.DLL<\/code>,\na name which was lost during linking.\nIf you want to call the function which had been called <code>Doo<\/code>\nin the original source code,\nyou have to import it by its new name,\n<code>Dabba<\/code>.\n<\/p>\n<p>\nIn Jeffrey&#8217;s case, he took a function which was internally\nreferred to by a decorated name\n(<code>?Dispose@MyClass@@QAEAAV1@XZ<\/code>)\nand renaming it to an undecorated name\n(<code>MC_Dispose<\/code>).\nBut when other modules tried to use the library, they got the error\nsaying that\n&#8220;?Dispose@MyClass@@QAEAAV1@XZ&#8221; is not found.\nWhich is correct:\n<code>?Dispose@MyClass@@QAEAAV1@XZ<\/code>\nwas not found because it no longer exists under that name.\nYou renamed it to <code>MC_Dispose<\/code>.\nThose modules need to link to the function\n<code>MC_Dispose<\/code> if they want to call the\nfunction\n&#8220;formerly known as ?Dispose@MyClass@@QAEAAV1@XZ&#8221;.\n<\/p>\n<p>\nActually, Jeffrey&#8217;s situation is more complicated than I described\nit because\n<code>?Dispose@MyClass@@QAEAAV1@XZ<\/code>\nundecorates to\n<code>public: class MyClass &amp; __thiscall MyClass::Dispose(void)<\/code>;\nthis is a method not a static function.\nI don&#8217;t believe there&#8217;s a way to override the name decoration\nalgorithm for instance methods;\nthe compiler is always going to generate a reference to\n<code>?Dispose@MyClass@@QAEAAV1@XZ<\/code>.\nSo renaming the export doesn&#8217;t buy you anything because you don&#8217;t\ncontrol the name on the import side.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Jeffrey Riaboy asks why, if he renames a function in his DEF file, attempts to link to the function by its old name fail. Well, um, yeah, because you renamed it. Let&#8217;s take the situation apart a bit; maybe it&#8217;ll make more sense. I&#8217;m going to ignore a lot of details (dllimport\/dllexport, calling conventions) since [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-15243","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Jeffrey Riaboy asks why, if he renames a function in his DEF file, attempts to link to the function by its old name fail. Well, um, yeah, because you renamed it. Let&#8217;s take the situation apart a bit; maybe it&#8217;ll make more sense. I&#8217;m going to ignore a lot of details (dllimport\/dllexport, calling conventions) since [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/15243","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=15243"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/15243\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=15243"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=15243"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=15243"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}