Author Topic: How to pick up a symbol in C code which was defined in a .ld linkfile?  (Read 314 times)

0 Members and 1 Guest are viewing this topic.

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3947
  • Country: gb
  • Doing electronics since the 1960s...
This is weird.

In the linkfile I have

 _build_type = 1;

and sure enough in the .map file I see

0x0000000000000001                _build_type = 0x1

but this code

Code: [Select]
extern char _build_type;
strcat((char *)PAGE_BODY, "<br>Build: ");
if ( _build_type == 0 )
{
strcat((char *)PAGE_BODY, "v0");
}
else if ( _build_type == 1 )
{
strcat((char *)PAGE_BODY, "v1");
}

always sees it as zero. Confirmed by stepping through it.

I have also tried int instead of char - doesn't pick up a value at all. I am wondering whether every value in a linkfile is actually implicitly an address, so one can't do this?

But then this type of construct works

Code: [Select]
extern char _s_nonboot_data;
extern char _e_nonboot_data;
extern char _si_nonboot_data;
memcpy(&_s_nonboot_data, &_si_nonboot_data, &_e_nonboot_data - &_s_nonboot_data);

and "obviously" 0 and 1 are also valid addresses.

Obviously I could have a .h file with a #define in it, etc, but for other reasons I am trying to select a text string based on a symbol defined 0/1 in the linkfile. I can build two different versions of the project which are very similar but have different linkfiles.
« Last Edit: July 31, 2024, 01:08:29 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online pcprogrammer

  • Super Contributor
  • ***
  • Posts: 4182
  • Country: nl
I have used this in projects of mine and it looks like this:

Link file
Code: [Select]
MY_LINK_VARIABLE = 10;

Code file
Code: [Select]
if(&MY_LINK_VARIABLE == 10)
{
  ...
}
else
{
  ...
}

This is with the GNU compiler for ARM.

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3947
  • Country: gb
  • Doing electronics since the 1960s...
I tried that (my memcpy example above uses it) but



Maybe it works with values other than 0 :) but that produces "warning: comparison between pointer and integer".

So maybe (char*) 0 or (char*) 1.
« Last Edit: July 31, 2024, 01:22:57 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online pcprogrammer

  • Super Contributor
  • ***
  • Posts: 4182
  • Country: nl
Ah yes, that is how it is used in my code, for addresses. Maybe there is another way then the & sign to have it be the actual variable instead of the address.

Could it be that the variable needs to be in a section part of the link file?

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3947
  • Country: gb
  • Doing electronics since the 1960s...

I am defining other stuff in the linkfile, and not inside any special section, but they are all memory addresses.

Such a simple thing! But this works:

Code: [Select]
extern char _build_type;
strcat((char *)PAGE_BODY, "<br>Build: ");
if ( &_build_type == (char*) 1 )
{
strcat((char *)PAGE_BODY, "v1");
}
else if ( &_build_type == (char*) 2 )
{
strcat((char *)PAGE_BODY, "v2");
}

so using 1 or 2, not 0. Odd since addresses can be 0 too, although usually this indicates a cockup (null pointer, etc). Maybe to test for ==0 one should use ==NULL.
« Last Edit: July 31, 2024, 01:44:11 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 6715
  • Country: fi
    • My home page and email address
In the linkfile I have

 _build_type = 1;
As you already realized, in the linker script you can define symbol addresses, not symbol values.

In C code, you could use
    extern const char _build_type[];
    #define  BUILD_TYPE  ((uintptr_t)(_build_type))
since the name of an array decays to a pointer.  With this, _build_type == (void *)1 and BUILD_TYPE == 1.
 
The following users thanked this post: peter-h, pcprogrammer


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf