Skip to content

Building/running a ThreadX Module under GCC where there are pointers to global variables #230

Description

@RobMeades

We are using ThreadX and ThreadX Modules in our product, have been doing so for many years. So far we have always built under ARMCC. We now need to build the ThreadX Modules under GCC (12.2 release 1).

We have followed the form of your example (i.e. compilation switches -fpie -fno-plt -mno-pic-data-is-text-relative -msingle-pic-base, no particular linker switches) and in general the code runs, however there is a specific case where these compilation flags do NOT work: when taking the address of a global variable. For instance:

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

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

...results in a printed output of the form:

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

In other words pBuffer is not being offset correctly. This is clear when you look at the disassembled code:

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

When loading-up the variable to put into r2, which is going to be passed to printf() as pBuffer, r3 needs to be adjusted, yet it is not (detail below).

We've tried various permutations of -mpic-data-is-text-relative/-mnopic-data-is-text-relative and -msingle-pic-base/-mnosingle-pic-base but none of them make a difference: we just cannot make a pointer reference to a global variable work. Unfortunately we can't change the source code we are compiling, there's quite a large amount of it and some if it is not ours; and of course this is perfectly valid C code.

Can you suggest how to compile a ThreadX Module under GCC so that it runs correctly?

Detail:

In the disassembled output, the contents of 1f8 and 1fc for the example 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 by the compiler to the un-offsetted address of buffer, and the compiler knows that pBuffer it is a pointer to something in the GOT, yet it did not do anything to add the offset when it generated the code.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions