This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

gcc does not generate correct code while building PIC

Hey guys,

I have been exploring building PIC using the gcc toolchain and I think there is a bug.

I first build a shared library using 

Fullscreen
1
arm-none-eabi-gcc -shared -mcpu=cortex-m4 -mthumb -Wall -g -fPIC -fmessage-length=0 --specs=nosys.specs mylib.c -o libmylib.so
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

and then link to my code using the follwing

Fullscreen
1
2
3
arm-none-eabi-gcc -x assembler-with-cpp -c -O0 -mcpu=cortex-m4 -mthumb -Wall -fmessage-length=0 -fPIC startup.S -o startup.o
arm-none-eabi-gcc -c -mcpu=cortex-m4 -mthumb -Wall -g -fmessage-length=0 --specs=nosys.specs -fPIC main.c -o main.o
arm-none-eabi-ld startup.o main.o -g -nostdlib -T./stm32_linker.ld -L. -lmylib -o main.elf
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Full code is at https://github.com/rgujju/STM32-projects/tree/master/got_plt , generate the required code using 'make got_plt'. I have also attached the disassembly of the code at the end for convenience.

What I expect is the function call to <library_function> to go through the GOT and PLT and eventually go into the .dynamic section. I understand that i will have to build a dynamic linker for the actual call to <library_function> work but i just want to check if it runs till this point correctly first. But the code gives a fault at 0x800010c. The branch to the instruction at 0x800010c is from 0x8000126. The value of ip at 0x8000126 is 0x200000a0, hence the PC gets loaded with 0x800010c. The CFSR value after the fault is 0x00020001 which is IACCVIOL and INVSTATE. INVSTATE occurs when the last bit is not set to 1 for a thumb2 instruction. So I changed the 0x800010c to 0x800010d and it seems to work fine.

So my question is, is this actually a bug in gcc or am i doing something wrong?

Thanks a lot for your help.

EDIT: I am using arm gcc 9-2019-q4-major

EDIT: Added GBD output

From https://interrupt.memfault.com/blog/cortex-m-fault-debug

INVSTATE - Indicates the processor has tried to execute an instruction with an invalid Execution Program Status Register (EPSR) value. Among other things the ESPR tracks whether or not the processor is in thumb mode state. Instructions which use “interworking addresses”2 (bx & blx or ldr & ldm when loading a pc-relative value) must set bit[0] of the instruction to 1 as this is used to update ESPR.T. If this rule is violated, a INVSTATE exception will be generated. When writing C code, the compiler will take care of this automatically, but this is a common bug which can arise when hand-writing assembly.

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
main.elf: file format elf32-littlearm
Disassembly of section .vector_table:
08000000 <vtable>:
8000000: 20001000 andcs r1, r0, r0
8000004: 08000009 stmdaeq r0, {r0, r3}
08000008 <reset_handler>:
8000008: 480b ldr r0, [pc, #44] ; (8000038 <__main_loop+0x2>)
800000a: 4685 mov sp, r0
800000c: 2000 movs r0, #0
800000e: 490b ldr r1, [pc, #44] ; (800003c <__main_loop+0x6>)
8000010: 4a0b ldr r2, [pc, #44] ; (8000040 <__main_loop+0xa>)
8000012: 4b0c ldr r3, [pc, #48] ; (8000044 <__main_loop+0xe>)
8000014: e002 b.n 800001c <copy_sidata_loop>
08000016 <copy_sidata>:
8000016: 581c ldr r4, [r3, r0]
8000018: 500c str r4, [r1, r0]
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.
.
.
0x08000068 13 y=8;
(gdb) si
0x0800006a 13 y=8;
(gdb) si
14 z=library_function(77);
(gdb) si
0x0800006e 14 z=library_function(77);
(gdb) si
0x0800011c in ?? ()
(gdb) si
0x08000120 in ?? ()
(gdb) si
0x08000124 in ?? ()
(gdb) si
0x08000126 in ?? ()
(gdb) si
0x0800010c in ?? ()
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

0