https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108940

            Bug ID: 108940
           Summary: Offset of pointer to global variable not set correctly
                    for position independent executable
           Product: gcc
           Version: 12.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rob.mea...@u-blox.com
  Target Milestone: ---

We are compiling C as position independent code on a Cortex-M7 under GCC 12.2
release 1, using the default r9 as the offset register for the Global Offset
Table with:

-fpie -fno-plt -mno-pic-data-is-text-relative -msingle-pic-base

...and no particular linker options (as recommended by ThreadX Modules (see
https://github.com/azure-rtos/threadx/blob/master/ports_module/cortex_m7/gnu/example_build/build_threadx_module_sample.bat),
which manages r9 during loading).

The problem we are having is that any attempt to take the address of a global
variable ends up with the wrong address (the un-offsetted address) and this
appears to be how the assembly code is being written by GCC, there appears
nothing we can do in terms of r9 etc. to fix it: is there a compiler flag we
have failed to add/[remove] that would fix this, or is such an operation
impossible when the offset-register mechanism is employed, or could this be a
bug?  Obviously we have tried many permutations of the "pic"-related flags but
have not found a combination which gives us the correct pointer address.

Our sample code:

char buffer[100];
char* pBuffer = buffer;

int appModMain()
{
    printf("buffer address: %p, buffer address via pBuffer: %p \n", buffer,
pBuffer);
}

...results in printed output of the form:

buffer address:  60C8C25C, buffer address via pBuffer: 1000025C

In other words pBuffer is not being offset correctly.  Here is the disassembly
of the above, as compiled with the flags indicated above:

00000188 <appModMain>:
     188:   b580        push    {r7, lr}
     18a:   af00        add r7, sp, #0
     18c:   4b1a        ldr r3, [pc, #104]  ; (1f8 <appModMain+0x70>)
     18e:   f859 3003   ldr.w   r3, [r9, r3]
     192:   681b        ldr r3, [r3, #0]
     194:   461a        mov r2, r3
     196:   4b19        ldr r3, [pc, #100]  ; (1fc <appModMain+0x74>)
     198:   f859 3003   ldr.w   r3, [r9, r3]
     19c:   4619        mov r1, r3
     19e:   4b18        ldr r3, [pc, #96]   ; (200 <appModMain+0x78>)
     1a0:   f859 3003   ldr.w   r3, [r9, r3]
     1a4:   4618        mov r0, r3
     1a6:   f000 f8bb   bl  320 <printf>
     1aa:   f640 30b8   movw    r0, #3000   ; 0xbb8

The contents of 1f8 and 1fc for the above are:

     1f8:       000001bc
     1fc:       000001b0

...in the .got section of the disassembled output, these offset are towards the
end, here:


Disassembly of section .got:
00006b88 <__ctors_end__>:
...
    6d34:       1002c5a8
    6d38:       1000025c    ; 6b88 + 1b0
    6d3c:       00001e15
    6d40:       1002c5ac
    6d44:       100001d0        ; 6b88 + 1bc

...and 100001d0 in the disassembled output turns out to be:

Disassembly of section .data:
...

100001d0 <pBuffer>:
100001d0:       1000025c

...while 1000025c in the disassembled output turns out to be:


Disassembly of section .bss:
...

1000025c <buffer>:
        ...

So pBuffer is initialised to the un-offsetted address of buffer and nothing
corrects that to the real address.

Reply via email to