How does the `--defsym` linker flag work to pass values to source code?










0














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: %un", (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:



  1. How is the 9-character string for the build date (YYYYmmdd+) stored in memory?

  2. 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?

  3. Why __BUILD_DATE is defined as char and not unsigned long if it is eventually casted to unsigned long?









share|improve this question























  • That looks like 3 questions to me. Not one. Maybe you want to post 3 individual questions..?
    – Jesper Juhl
    Nov 12 '18 at 22:10










  • @JesperJuhl I think it's 3 small parts of one questions about the usage of --defsym. It makes no sense to me to split the question.
    – Sparkler
    Nov 12 '18 at 22:14











  • "Why __BUILD_DATE is defined as char and not unsigned long if it is eventually casted to unsigned long?" Is definitely a standalone question IMHO. As is "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?". But, that may just be me.
    – Jesper Juhl
    Nov 12 '18 at 22:17















0














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: %un", (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:



  1. How is the 9-character string for the build date (YYYYmmdd+) stored in memory?

  2. 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?

  3. Why __BUILD_DATE is defined as char and not unsigned long if it is eventually casted to unsigned long?









share|improve this question























  • That looks like 3 questions to me. Not one. Maybe you want to post 3 individual questions..?
    – Jesper Juhl
    Nov 12 '18 at 22:10










  • @JesperJuhl I think it's 3 small parts of one questions about the usage of --defsym. It makes no sense to me to split the question.
    – Sparkler
    Nov 12 '18 at 22:14











  • "Why __BUILD_DATE is defined as char and not unsigned long if it is eventually casted to unsigned long?" Is definitely a standalone question IMHO. As is "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?". But, that may just be me.
    – Jesper Juhl
    Nov 12 '18 at 22:17













0












0








0


0





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: %un", (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:



  1. How is the 9-character string for the build date (YYYYmmdd+) stored in memory?

  2. 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?

  3. Why __BUILD_DATE is defined as char and not unsigned long if it is eventually casted to unsigned long?









share|improve this question















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: %un", (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:



  1. How is the 9-character string for the build date (YYYYmmdd+) stored in memory?

  2. 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?

  3. Why __BUILD_DATE is defined as char and not unsigned long if it is eventually casted to unsigned long?






c++ c gcc casting linker






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 12 '18 at 22:15

























asked Nov 12 '18 at 21:59









Sparkler

760824




760824











  • That looks like 3 questions to me. Not one. Maybe you want to post 3 individual questions..?
    – Jesper Juhl
    Nov 12 '18 at 22:10










  • @JesperJuhl I think it's 3 small parts of one questions about the usage of --defsym. It makes no sense to me to split the question.
    – Sparkler
    Nov 12 '18 at 22:14











  • "Why __BUILD_DATE is defined as char and not unsigned long if it is eventually casted to unsigned long?" Is definitely a standalone question IMHO. As is "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?". But, that may just be me.
    – Jesper Juhl
    Nov 12 '18 at 22:17
















  • That looks like 3 questions to me. Not one. Maybe you want to post 3 individual questions..?
    – Jesper Juhl
    Nov 12 '18 at 22:10










  • @JesperJuhl I think it's 3 small parts of one questions about the usage of --defsym. It makes no sense to me to split the question.
    – Sparkler
    Nov 12 '18 at 22:14











  • "Why __BUILD_DATE is defined as char and not unsigned long if it is eventually casted to unsigned long?" Is definitely a standalone question IMHO. As is "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?". But, that may just be me.
    – Jesper Juhl
    Nov 12 '18 at 22:17















That looks like 3 questions to me. Not one. Maybe you want to post 3 individual questions..?
– Jesper Juhl
Nov 12 '18 at 22:10




That looks like 3 questions to me. Not one. Maybe you want to post 3 individual questions..?
– Jesper Juhl
Nov 12 '18 at 22:10












@JesperJuhl I think it's 3 small parts of one questions about the usage of --defsym. It makes no sense to me to split the question.
– Sparkler
Nov 12 '18 at 22:14





@JesperJuhl I think it's 3 small parts of one questions about the usage of --defsym. It makes no sense to me to split the question.
– Sparkler
Nov 12 '18 at 22:14













"Why __BUILD_DATE is defined as char and not unsigned long if it is eventually casted to unsigned long?" Is definitely a standalone question IMHO. As is "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?". But, that may just be me.
– Jesper Juhl
Nov 12 '18 at 22:17




"Why __BUILD_DATE is defined as char and not unsigned long if it is eventually casted to unsigned long?" Is definitely a standalone question IMHO. As is "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?". But, that may just be me.
– Jesper Juhl
Nov 12 '18 at 22:17












1 Answer
1






active

oldest

votes


















2














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: %lun", (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.






share|improve this answer






















  • so anything passed using --defsym can only be as large as size_t/ptrdiff_t?
    – Sparkler
    Nov 12 '18 at 22:59










  • @Sparkler There doesn't need to be much of a correlation between the linker's limits and the limits of C types, but practically you very likely won't be able to store addresses larger than your SIZE_MAX.
    – PSkocik
    Nov 12 '18 at 23:02






  • 1




    Interestingly, the above's only working for me with clang. I can't quite get it to work if I use gcc for linking (with whatever -fuse-ld option or without it). The debugger always shows the stored timestamp if I do p (unsigned long)&__BUILD_DATE but the program's printing the stored value offset by 0xffffaaaaaaaac000 but only if my system's address layout randomization's off. (Otherwise it's random). I don't have an explanation for this.
    – PSkocik
    Nov 12 '18 at 23:07











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53270723%2fhow-does-the-defsym-linker-flag-work-to-pass-values-to-source-code%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














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: %lun", (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.






share|improve this answer






















  • so anything passed using --defsym can only be as large as size_t/ptrdiff_t?
    – Sparkler
    Nov 12 '18 at 22:59










  • @Sparkler There doesn't need to be much of a correlation between the linker's limits and the limits of C types, but practically you very likely won't be able to store addresses larger than your SIZE_MAX.
    – PSkocik
    Nov 12 '18 at 23:02






  • 1




    Interestingly, the above's only working for me with clang. I can't quite get it to work if I use gcc for linking (with whatever -fuse-ld option or without it). The debugger always shows the stored timestamp if I do p (unsigned long)&__BUILD_DATE but the program's printing the stored value offset by 0xffffaaaaaaaac000 but only if my system's address layout randomization's off. (Otherwise it's random). I don't have an explanation for this.
    – PSkocik
    Nov 12 '18 at 23:07
















2














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: %lun", (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.






share|improve this answer






















  • so anything passed using --defsym can only be as large as size_t/ptrdiff_t?
    – Sparkler
    Nov 12 '18 at 22:59










  • @Sparkler There doesn't need to be much of a correlation between the linker's limits and the limits of C types, but practically you very likely won't be able to store addresses larger than your SIZE_MAX.
    – PSkocik
    Nov 12 '18 at 23:02






  • 1




    Interestingly, the above's only working for me with clang. I can't quite get it to work if I use gcc for linking (with whatever -fuse-ld option or without it). The debugger always shows the stored timestamp if I do p (unsigned long)&__BUILD_DATE but the program's printing the stored value offset by 0xffffaaaaaaaac000 but only if my system's address layout randomization's off. (Otherwise it's random). I don't have an explanation for this.
    – PSkocik
    Nov 12 '18 at 23:07














2












2








2






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: %lun", (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.






share|improve this answer














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: %lun", (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.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 12 '18 at 23:09

























answered Nov 12 '18 at 22:29









PSkocik

32.2k54770




32.2k54770











  • so anything passed using --defsym can only be as large as size_t/ptrdiff_t?
    – Sparkler
    Nov 12 '18 at 22:59










  • @Sparkler There doesn't need to be much of a correlation between the linker's limits and the limits of C types, but practically you very likely won't be able to store addresses larger than your SIZE_MAX.
    – PSkocik
    Nov 12 '18 at 23:02






  • 1




    Interestingly, the above's only working for me with clang. I can't quite get it to work if I use gcc for linking (with whatever -fuse-ld option or without it). The debugger always shows the stored timestamp if I do p (unsigned long)&__BUILD_DATE but the program's printing the stored value offset by 0xffffaaaaaaaac000 but only if my system's address layout randomization's off. (Otherwise it's random). I don't have an explanation for this.
    – PSkocik
    Nov 12 '18 at 23:07

















  • so anything passed using --defsym can only be as large as size_t/ptrdiff_t?
    – Sparkler
    Nov 12 '18 at 22:59










  • @Sparkler There doesn't need to be much of a correlation between the linker's limits and the limits of C types, but practically you very likely won't be able to store addresses larger than your SIZE_MAX.
    – PSkocik
    Nov 12 '18 at 23:02






  • 1




    Interestingly, the above's only working for me with clang. I can't quite get it to work if I use gcc for linking (with whatever -fuse-ld option or without it). The debugger always shows the stored timestamp if I do p (unsigned long)&__BUILD_DATE but the program's printing the stored value offset by 0xffffaaaaaaaac000 but only if my system's address layout randomization's off. (Otherwise it's random). I don't have an explanation for this.
    – PSkocik
    Nov 12 '18 at 23:07
















so anything passed using --defsym can only be as large as size_t/ptrdiff_t?
– Sparkler
Nov 12 '18 at 22:59




so anything passed using --defsym can only be as large as size_t/ptrdiff_t?
– Sparkler
Nov 12 '18 at 22:59












@Sparkler There doesn't need to be much of a correlation between the linker's limits and the limits of C types, but practically you very likely won't be able to store addresses larger than your SIZE_MAX.
– PSkocik
Nov 12 '18 at 23:02




@Sparkler There doesn't need to be much of a correlation between the linker's limits and the limits of C types, but practically you very likely won't be able to store addresses larger than your SIZE_MAX.
– PSkocik
Nov 12 '18 at 23:02




1




1




Interestingly, the above's only working for me with clang. I can't quite get it to work if I use gcc for linking (with whatever -fuse-ld option or without it). The debugger always shows the stored timestamp if I do p (unsigned long)&__BUILD_DATE but the program's printing the stored value offset by 0xffffaaaaaaaac000 but only if my system's address layout randomization's off. (Otherwise it's random). I don't have an explanation for this.
– PSkocik
Nov 12 '18 at 23:07





Interestingly, the above's only working for me with clang. I can't quite get it to work if I use gcc for linking (with whatever -fuse-ld option or without it). The debugger always shows the stored timestamp if I do p (unsigned long)&__BUILD_DATE but the program's printing the stored value offset by 0xffffaaaaaaaac000 but only if my system's address layout randomization's off. (Otherwise it's random). I don't have an explanation for this.
– PSkocik
Nov 12 '18 at 23:07


















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53270723%2fhow-does-the-defsym-linker-flag-work-to-pass-values-to-source-code%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Top Tejano songwriter Luis Silva dead of heart attack at 64

ReactJS Fetched API data displays live - need Data displayed static

政党