Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
21 years ago

pointer out of range link error

I have some code running from SDRAM that references an on chip RAM. In porting from NIOS to NIOS II I'm getting the link error

global pointer relative address out of range

I saw a topic that suggested NIOS II 1.01 would solve a similar error for an STL problem but that was an access back to the text section. Is this the same problem?

Dan

8 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I found some more information on this and it looks like the problem is not with the address per se but with the fact that I'm trying to use a symbol provided by the linker script to access it.

    The linker script "generated.x" has a section for my internal memory and within that it has some PROVIDE directives. It seems that I can't access these symbols generated by the PROVIDE from within my code. These are symbols that have the form _alt_partition_MEMORY_NAME_start and _alt_partition_MEMORY_NAME_end. I can access some other PROVIDE symbols like edata.

    The ones that start with alt_ seem to be the problem. Is this a result of having no program data to go into the section?

    I can use a define from system.h for my immeadiate problem but this has got my curiosity up and I'm likely to need access to some of these linker generated symbols in the future. Any help appreciated.

    Dan
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I think the problem may be to do with the way you are declaring the C externs which you are using to access the data. Please post the C code you used, particularly if the suggestion below doesn't solve your problem.

    I'm guessing your code looks a bit like this:

    extern char _alt_partition_MEMORY_NAME_start;
    printf("%X\n", &_alt_partition_MEMORY_NAME_start);

    That's declaring a one byte symbol. gcc will assume, because the symbol is small, that it will be in section sdata or sbss and use gp relative addressing to get to it.

    You need to do something like this:

    extern char _alt_partition_MEMORY_NAME_start;
    printf("%X\n", _alt_partition_MEMORY_NAME_start);

    This declares a symbol of undefined length. gcc won't make any asusmptions about where it is and will use hi/lo addressing to operate on the symbol.

    Alternatively, you could use __attribute__ ((section ("section"))) to tell GCC which section the symbol will be in, but this is probably not needed in this case.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Your first sugestion did the trick (use [])!

    One thing I noticed is that when I run readelf with -s I don't see the symbol I'm referencing. I see others like __bss_start

    Here is the linker script portion that declares my symbol:

    .cpu_memory_data :

    {

    PROVIDE (_alt_partition_cpu_memory_data_start = ABSOLUTE(.));

    *(.cpu_memory_data)

    . = ALIGN(32 / 8);

    PROVIDE (_alt_partition_cpu_memory_data_end = ABSOLUTE(.));

    } > cpu_memory_data

    Here is the output of nios2-elf-readelf -s

    re/ssec/Debug

    [SOPC Builder]$ nios2-elf-readelf.exe -s project.elf | grep partition

    373: 11000000 0 NOTYPE GLOBAL DEFAULT ABS _alt_partition_cpu_memory

    1617: 11000000 0 NOTYPE GLOBAL DEFAULT ABS _alt_partition_cpu_memory

    I am referencing these symbols in the code:

    extern char _alt_partition_cpu_memory_data_start[];

    extern char _alt_partition_cpu_memory_data_end[];

    printf("start:%p end:%p\n", _alt_partition_cpu_memory_data_start, _alt_partition_cpu_memory_data_end);

    which works.

    Should this symbol show up in the readelf output?

    Thanks,

    Dan
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    > Is there any solution to this problem besides the one mentioned above?

    I'm curious to know if the -G0 compiler option solves the problem ... at least

    as a temporary work around ... it should keep data out of .sdata/.sbss.

    BTW: that's the numeral "zero"

    Regards,

    --Scott
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    > yes, it does solve the problem

    Great! I'll use this myself then ... when/if I encounter the problem.

    Just note that it will affect performance since full addresses will

    be loaded for what was previously small (gp relative) data -- which

    I believe defaults to variables of 8 bytes or less (when -Gn is not

    specified).

    I guess mileage will vary depending on the application ;-)

    Regads,

    --Scott
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hello,

    after almost 12 years I've got a similar problem!!

    I am using Quartus 14.1sp1 and a NIOS II gen2.

    I get the following error while trying to compile my application (working in Quartus 7.1, NIOS II classic):

    obj/default/lpc_lib.o: in function `lsp_to_freq':

    lpc_lib.c:649: warning: unable to reach (null) (at 0x800476b8) from the global pointer (at 0x8003f5d8) because the offset (32992) is out of the allowed range, -32678 to 32767.

    collect2: error: ld returned 1 exit status

    make: *** [rio_audio_codec.elf] error 1

    I tried to define all the extern variables with the "[]" at the end (as suggested above), but the problem is still present.

    I tried also to use the -G0 flag in the application, but the problem was not solved.

    Should I also specify the same flag for the BSP ? If so, how?

    Anyway I'd like to solve the problem definetely (without using the -G0), also because I need to reach some performance.

    Any hint is more than appreciated,

    thanks on advance