<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Understanding the classical model for linking: You can override an LIB with another LIB, and a LIB with an OBJ, but you can't override an OBJ</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/01/09/10383325.aspx</link><description>A closer look at the way the linker pulls OBJs into your module.</description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>re: Understanding the classical model for linking: You can override an LIB with another LIB, and a LIB with an OBJ, but you can't override an OBJ</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/01/09/10383325.aspx#10383778</link><pubDate>Thu, 10 Jan 2013 10:35:31 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10383778</guid><dc:creator>Neil</dc:creator><description>&lt;p&gt;Sorry if I&amp;#39;ve misremembered this.&lt;/p&gt;
&lt;p&gt;In printf.c, declare extern (*printf__fp)();&lt;/p&gt;
&lt;p&gt;In fltused.c, define printf__fp.&lt;/p&gt;
&lt;p&gt;Then when printf wants to print a floating-point number it just invokes printf__fp and you crash if you didn&amp;#39;t trigger the include of the floating-point library.&lt;/p&gt;
&lt;p&gt;Better still would be a weak symbol if that&amp;#39;s supported.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10383778" width="1" height="1"&gt;</description></item><item><title>re: Understanding the classical model for linking: You can override an LIB with another LIB, and a LIB with an OBJ, but you can't override an OBJ</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/01/09/10383325.aspx#10383770</link><pubDate>Thu, 10 Jan 2013 10:21:06 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10383770</guid><dc:creator>Marcel</dc:creator><description>&lt;p&gt;Well, in the case of my microcontroller compiler (avrgcc) there is no magic going on, you have to tell the linker explicitly which version you want. The default version doesn&amp;#39;t include floating point. If I really want that, I have to include the &amp;quot;printf_flt&amp;quot; library. There&amp;#39;s even a third, minimalistic version that supports even less options than the standard one, called printf_min.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10383770" width="1" height="1"&gt;</description></item><item><title>re: Understanding the classical model for linking: You can override an LIB with another LIB, and a LIB with an OBJ, but you can't override an OBJ</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/01/09/10383325.aspx#10383763</link><pubDate>Thu, 10 Jan 2013 10:04:51 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10383763</guid><dc:creator>Matt</dc:creator><description>&lt;p&gt;///&lt;/p&gt;
&lt;p&gt;/// printf.c provides &amp;quot;printf, dummy_printf_do_f_impl, printf_do_f_fp&amp;quot;&lt;/p&gt;
&lt;p&gt;///&lt;/p&gt;
&lt;p&gt;void dummy_printf_do_f_impl()&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp;printf(&amp;quot;Uh oh - you used %%f but didn&amp;#39;t use the float keyword anywhere!!&amp;quot;); abort();&lt;/p&gt;
&lt;p&gt; &amp;nbsp;// alternatively, you could dynamically load the floating point library here, for example to handle the case where the main program&amp;#39;s &amp;quot;printf&amp;quot; has been passed a float from a plugin.&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;extern FARPROC printf_do_f_fp = &amp;amp;dummy_printf_do_f_impl;&lt;/p&gt;
&lt;p&gt;... printf(...)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp;case &amp;quot;f&amp;quot;: printf_do_f_fp();&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;///&lt;/p&gt;
&lt;p&gt;/// flt.lib provides __fltused, requires _printf_fp_impl&lt;/p&gt;
&lt;p&gt;///&lt;/p&gt;
&lt;p&gt;int __fltused;&lt;/p&gt;
&lt;p&gt;void* force_load_printf_fp = &amp;amp;actual_printf_do_f_impl;&lt;/p&gt;
&lt;p&gt;///&lt;/p&gt;
&lt;p&gt;/// printf_fp.c in printf_fp.lib (provides _printf_fp_impl)&lt;/p&gt;
&lt;p&gt;///&lt;/p&gt;
&lt;p&gt;printf_do_f.c requires __fltused&lt;/p&gt;
&lt;p&gt;FARPROC printf_do_f = NULL;&lt;/p&gt;
&lt;p&gt;void actual_printf_do_f_impl()&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp;printf(&amp;quot;Here&amp;#39;s your float: &amp;quot;, ...etc...);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;extern &lt;/p&gt;
&lt;p&gt;class InitMagicNumber&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt; InitMagicNumber()&lt;/p&gt;
&lt;p&gt; {&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;printf_do_f = &amp;amp;actual_printf_do_f_impl;&lt;/p&gt;
&lt;p&gt; }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;_printf_fp_impl;&lt;/p&gt;
&lt;p&gt;// Now follow through the compilation of main.c (main() { printf(&amp;quot;This should return an error: %f&amp;quot;); }&lt;/p&gt;
&lt;p&gt;main.c requires printf, provided by printf.lib. printf.lib doesn&amp;#39;t require any printf_fp stuff, so that&amp;#39;s not loaded. Now when printf is called, it does normal printf behaviour until it hits %f, when it then calls printf_do_f_fp, which is a symbol in printf.lib defined to point to dummy_printf_do_f_impl, which triggers an error.&lt;/p&gt;
&lt;p&gt;// Now follow through the compilation of main_fp.c (main() { printf(&amp;quot;This should work: %f&amp;quot;, 0.0f); }&lt;/p&gt;
&lt;p&gt;main_fp.c uses floating point, so automatically requires __fltinit. It calls printf, so we load printf.lib. printf.lib doesn&amp;#39;t use printf_fp, so that doesn&amp;#39;t automatically trigger a load there, but we&amp;#39;re now left with one unresolved symbol: __fltinit. __fltinit is defined in flt.lib, which requires the symbol _printf_fp_impl, defined in printf_fp.lib. This requires the printf_do_f_fp symbol which resolves to the definition in printf.lib. printf_fp.lib also has a &amp;quot;magic&amp;quot; variable and the linker will add its constructor to the list of CRT initialization functions.&lt;/p&gt;
&lt;p&gt;Now when main_fp.c runs, the CRT will call all of the constructors in turn, including the InitMagicNumber magic class, which sets printf_do_f (from printf.lib) to point to actual_printf_do_f_impl. The CRT eventually calls main who calls printf, who eventually calls the deref of printf_do_f_fp, which now takes it to actual_printf_do_f_impl.&lt;/p&gt;
&lt;p&gt;Result: printf floating point code is only brought along for the ride if you actually use floating point (or are dumb enough to include an extern int __fltused) somewhere in your code. Otherwise, a dummy implementation of printf will handle the case where %f is used on a non-floating-point program, which can either load the expensive fp library, or can explode, or can return &amp;quot;0.0&amp;quot; or whatever.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10383763" width="1" height="1"&gt;</description></item><item><title>re: Understanding the classical model for linking: You can override an LIB with another LIB, and a LIB with an OBJ, but you can't override an OBJ</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/01/09/10383325.aspx#10383641</link><pubDate>Wed, 09 Jan 2013 23:53:58 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10383641</guid><dc:creator>DS</dc:creator><description>&lt;p&gt;I think I&amp;#39;d go with Peter&amp;#39;s approach, as corrected by Raymond (entry point pointing to dummy function and corrected by FP library&amp;#39;s init code to point to FP argument handler). Anonymous123&amp;#39;s approach would require coding a special case into the compiler (remember, when float or double is used, as it must be to implement %f, the compiler always generates _fltused) or coding %f etc. support in assembler (well, maybe that&amp;#39;s what CRT does, but I actually tend to doubt it).&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10383641" width="1" height="1"&gt;</description></item><item><title>re: Understanding the classical model for linking: You can override an LIB with another LIB, and a LIB with an OBJ, but you can't override an OBJ</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/01/09/10383325.aspx#10383637</link><pubDate>Wed, 09 Jan 2013 23:44:24 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10383637</guid><dc:creator>Silly</dc:creator><description>&lt;p&gt;[This requires that the FP library be linked ahead of the static CRT. This is the sort of mistake most people will never figure out.]&lt;/p&gt;
&lt;p&gt;Surely not in ye olde classical linker days? But from what I recall, the math libary usually went at the end of the library arg list since it had no dependencies, which is sort of the opposite of this FP library idea.&lt;/p&gt;
&lt;p&gt;Wasn&amp;#39;t the DOS era floating point emulation stuff either done via an explicit linker option (offloading the choice to the developer), or by the user choosing to run an enumation tsr or having an emu387.exe to be loaded by runtime if needed (maybe triggered by a hardware fault)? I think developers would have cracked the s*ts back in the day if they had to endure a lookup + indirect function call to handle every %f printf argument encounter.&lt;/p&gt;
&lt;p&gt;Delay load functionality could also be an option if a time machine is allowed.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10383637" width="1" height="1"&gt;</description></item><item><title>re: Understanding the classical model for linking: You can override an LIB with another LIB, and a LIB with an OBJ, but you can't override an OBJ</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/01/09/10383325.aspx#10383621</link><pubDate>Wed, 09 Jan 2013 22:08:37 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10383621</guid><dc:creator>ipoverscsi</dc:creator><description>&lt;p&gt;[What if the format string is generated at run time? -Raymond]&lt;/p&gt;
&lt;p&gt;I didn&amp;#39;t think of that one. &amp;nbsp;Hmm. &amp;nbsp;&lt;/p&gt;
&lt;p&gt;Well, you stumped me, Raymond. &amp;nbsp;I can&amp;#39;t think of a way to determine which version of printf to use at link-time. &amp;nbsp;I can see how to do it at runtime with DLLs, overlays, or some other dynamic code loading, but not at link time.&lt;/p&gt;
&lt;p&gt;I eagerly await the answer.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10383621" width="1" height="1"&gt;</description></item><item><title>re: Understanding the classical model for linking: You can override an LIB with another LIB, and a LIB with an OBJ, but you can't override an OBJ</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/01/09/10383325.aspx#10383617</link><pubDate>Wed, 09 Jan 2013 21:54:08 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10383617</guid><dc:creator>Maurits [MSFT]</dc:creator><description>&lt;p&gt;One way to resolve this is to create an (awesome) namespace.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10383617" width="1" height="1"&gt;</description></item><item><title>re: Understanding the classical model for linking: You can override an LIB with another LIB, and a LIB with an OBJ, but you can't override an OBJ</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/01/09/10383325.aspx#10383586</link><pubDate>Wed, 09 Jan 2013 19:46:08 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10383586</guid><dc:creator>Joshua</dc:creator><description>&lt;p&gt;I think Anonymous123 found it. by knocking out the reference to _fltused in vfprintf&amp;#39;s .OBJ (all other *printf call this one), the floating point library is not called in unless used elsewhere. This assumes that vfprintf&amp;#39;s %e, %f, and %g are fully inlined. You end up with maybe .5k of unreachable garbage if not used. No special cases in the linker required.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10383586" width="1" height="1"&gt;</description></item><item><title>re: Understanding the classical model for linking: You can override an LIB with another LIB, and a LIB with an OBJ, but you can't override an OBJ</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/01/09/10383325.aspx#10383579</link><pubDate>Wed, 09 Jan 2013 19:27:19 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10383579</guid><dc:creator>Anonymous123</dc:creator><description>&lt;p&gt;For the printf issue - printf OBJ should not include _fltused. &amp;nbsp;Yes if the app uses %f and does not use floating point the app will crash, but any app that uses floating formats will itself include _fltused so this symbol is not needed by printf&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10383579" width="1" height="1"&gt;</description></item><item><title>re: Understanding the classical model for linking: You can override an LIB with another LIB, and a LIB with an OBJ, but you can't override an OBJ</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/01/09/10383325.aspx#10383577</link><pubDate>Wed, 09 Jan 2013 19:25:16 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10383577</guid><dc:creator>ipoverscsi</dc:creator><description>&lt;p&gt;@Brian_EE:&lt;/p&gt;
&lt;p&gt;True. &amp;nbsp;But unless you preprocess the printf format string you won&amp;#39;t know until runtime whether an attempt will be made to format a floating point value. &amp;nbsp;If we assume that we&amp;#39;re only doing static linking (no DLLs) then I can&amp;#39;t think of any other way to know at link time if you need to floating point library.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10383577" width="1" height="1"&gt;</description></item></channel></rss>