Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
soc:2009:oremanj:journal:week5 [2009/06/26 21:47] rwcr |
soc:2009:oremanj:journal:week5 [2009/06/26 22:26] (current) rwcr |
||
---|---|---|---|
Line 137: | Line 137: | ||
This is rather messy, of course; the fewer symbols with an implicit "might-be-NULL" attached the better. But for fairly tightly-coupled source files that need to be separated for size reasons, one or two weak functions can provide an excellent interface between the two. | This is rather messy, of course; the fewer symbols with an implicit "might-be-NULL" attached the better. But for fairly tightly-coupled source files that need to be separated for size reasons, one or two weak functions can provide an excellent interface between the two. | ||
- | While we're in the Cool Linker Tricks department, there's also something called a "weak alias", which serves a completely different purpose: providing one implementation of an API function while allowing it to be superseded without complaint by another object file. I haven't seen anything in gPXE that really needs this, but to give an example of how it //could// be used, gPXE core defines a simple ''memcpy()'' function that doesn't know about any architecture-specific optimizations, but only declares its prototype if the preprocessor macro ''_\_HAVE_ARCH_MEMCPY'' hasn't been defined by architecture-specific includes; that allows architecture-specific string functions to be used instead, using either ''#define'' or an inline implementation, but no symbol can be named ''memcpy'' because the linker would complain. A way around that would be: | + | While we're in the Cool Linker Tricks department, there's also something called a "weak alias", which serves a completely different purpose: providing one implementation of an API function while allowing it to be superseded without complaint by another object file. I haven't seen anything in gPXE that really needs this, but to give an example of how it //could// be used, gPXE core defines a simple ''memcpy()'' function that doesn't know about any architecture-specific optimizations, but only declares its prototype if the preprocessor macro ''%%__HAVE_ARCH_MEMCPY%%'' hasn't been defined by architecture-specific includes; that allows architecture-specific string functions to be used instead, using either ''#define'' or an inline implementation, but no symbol can be named ''memcpy'' because the linker would complain. A way around that would be: |
/* in core string code */ | /* in core string code */ | ||
void * core_memcpy ( void *dest, const void *src, int len ) { | void * core_memcpy ( void *dest, const void *src, int len ) { | ||
/* ... */ | /* ... */ | ||
} | } | ||
+ | | ||
void * memcpy ( void *dest, const void *src, int len ) | void * memcpy ( void *dest, const void *src, int len ) | ||
- | __attribute__ (( weak, alias ( "core_memcpy " ) )); | + | __attribute__ (( weak, alias ( "core_memcpy" ) )); |
Then architecture-specific code could just define ''memcpy'' directly, no preprocessor tricks needed, and it would supersede the core version. Again, I don't think anything needs this at this point, but it's cool to know - maybe it'll even come in handy someday! :-) | Then architecture-specific code could just define ''memcpy'' directly, no preprocessor tricks needed, and it would supersede the core version. Again, I don't think anything needs this at this point, but it's cool to know - maybe it'll even come in handy someday! :-) |