问题
In an LJ post, the --defsym
flag was used for passing the build date into the source code:
#include <stdio.h>
extern char __BUILD_DATE;
void main(void) {
printf("Build date: %u\n", (unsigned long) &__BUILD_DATE);
}
by linking with the following flags:
gcc example.c -Xlinker --defsym -Xlinker __BUILD_DATE=$(date +%Y%m%d)
According to the ld manual,
--defsym symbol=expression
Create a global symbol in the output file, containing the absolute address given by expression.
I am trying to understand the following:
- How is the 9-character string for the build date (
YYYYmmdd
+\0
) stored in memory? - If
--defsym
creates a symbol containing an address, why__BUILD_DATE
is defined as a char and not as a pointer or as an integral type? - Why
__BUILD_DATE
is defined aschar
and notunsigned long
if it is eventually casted tounsigned long
?
回答1:
Linkers see globals as addresses (pointers to the "actual" global rather than the actual global -- even if the actual global doesn't exist at that address). -Xlinker --defsym -Xlinker __BUILD_DATE=$(date +%Y%m%d)
sets the address of __BUILD_DATE
not the value. When the __BUILD_DATE
linker entity has an address but not a value, you can get the address by declaring the entity as anything and then taking the address of that.
In:
#include <stdio.h>
//extern long __BUILD_DATE[128];
//extern int __BUILD_DATE;
extern char __BUILD_DATE;
int main(void)
{
printf("Build date: %lu\n", (unsigned long)&__BUILD_DATE);
}
Any of the three declarations should work. Just don't try to use the value of that (pseudo) global. That would be like dereferencing an invalid pointer.
That should answer 2 and 3. To answer 1, -Xlinker --defsym -Xlinker __BUILD_DATE=$(date +%Y%m%d)
stores the number returned (stdout) by $(date %Y%m%d)
as the address of __BUILD_DATE
. It doesn't store a string.
来源:https://stackoverflow.com/questions/53270723/how-does-the-defsym-linker-flag-work-to-pass-values-to-source-code