ARM C++ issue with static members and PIC code

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
SimonHA
Posts: 12
Joined: Thu Nov 10, 2016 4:00 pm

ARM C++ issue with static members and PIC code

Post by SimonHA »

Hi,

I have an issue with my OS C++ development that I had no luck finding a solution for.
My OS runs in virtual space and thus I have PIC enabled to allow me to offset the addresses.
However, the compiler does not use GOT on static variables defined in my class so I get data aborts from accessing them.
Any ideas of how to solve this problem?

Best regards,
Simon
LtG
Member
Member
Posts: 384
Joined: Thu Aug 13, 2015 4:57 pm

Re: ARM C++ issue with static members and PIC code

Post by LtG »

I've never done ARM devving, so I can't directly help you... But it might be useful to mention which compiler you are using?

Other than that the only thing that comes to mind is to check the compiler flags/options? For the entire source -> binary conversion, including linkers.
simeonz
Member
Member
Posts: 360
Joined: Fri Aug 19, 2016 10:28 pm

Re: ARM C++ issue with static members and PIC code

Post by simeonz »

SimonHA wrote:My OS runs in virtual space and thus I have PIC enabled to allow me to offset the addresses.
However, the compiler does not use GOT on static variables defined in my class so I get data aborts from accessing them.
Any ideas of how to solve this problem?
The GOT is missing in the object files, or the GOT is dropped during the final link? I am not familiar with the situation on ARM, but on amd64 the linker can bypass GOT by pre-applying some of the indirect GOT references during the final link if the output is executable, i.e. when the output is code which has a fixed base address. To my knowledge this was intended to be amd64 optimization, but you could check anyway.

Also, are there any relocations that apply to the static members, or are they accessed through fixed direct references? What do those references look like in the disassembly - are they zero-filled, or are they meaningful, in the sense that they could work assuming some hypothetical base address? What are the options used for linking, and may be compiling? I mean, I don't know if digging the answers will make a difference, but it might offer a hint.
FallenAvatar
Member
Member
Posts: 283
Joined: Mon Jan 03, 2011 6:58 pm

Re: ARM C++ issue with static members and PIC code

Post by FallenAvatar »

SimonHA wrote:Hi,

I have an issue with my OS C++ development that I had no luck finding a solution for.
My OS runs in virtual space and thus I have PIC enabled to allow me to offset the addresses.
However, the compiler does not use GOT on static variables defined in my class so I get data aborts from accessing them.
Any ideas of how to solve this problem?

Best regards,
Simon

That makes less than zero sense. Please try again?
- Amy
simeonz
Member
Member
Posts: 360
Joined: Fri Aug 19, 2016 10:28 pm

Re: ARM C++ issue with static members and PIC code

Post by simeonz »

I just realized and checked on x64, that even with the link-time optimization, while the GOT is not used in the final code, the references become rip relative (as they should be for fpic), and therefore should not cause relocation issues. This means it cannot be your problem.
SimonHA
Posts: 12
Joined: Thu Nov 10, 2016 4:00 pm

Re: ARM C++ issue with static members and PIC code

Post by SimonHA »

Okay, I'll try again with more details to explain the problem.
I want my OS to run in virtual space using the MMU. So the bootup process is the following:
  • Start OS at 0x8000.
    Setup the MMU and map the OS to address 0xC0000000.
    Jump to the virtual address and run the OS from there.
To ensure that my code is position independent I have the following flags:

Code: Select all

CFLAGS 	= -mcpu=$(TARGET_CPU) -ffreestanding -Wall -Wextra -std=c++11 -fno-exceptions -fPIC
LDFLAGS = -nostdlib -lgcc
This works just fine except for the following:
Whenever I access static variables a fixed address is used to access and thus I get a data abort.
Here is an example:

I have a struct with some basic kernel version info:

Code: Select all

struct kernel_info
{
	const char* name 	= "MinOS";
	const char* version = "0.1";
	const char* build 	= "1";
} kernel_info;
Access to this struct's constant variables are done with fixed addresses and this is of course a problem.
How can I force the compiler to make the access position independent for these constant/static variables?

Hope this is more clear.
simeonz
Member
Member
Posts: 360
Joined: Fri Aug 19, 2016 10:28 pm

Re: ARM C++ issue with static members and PIC code

Post by simeonz »

I tested to the extent to which I understand your situation, with cross-gcc (i.e. gcc-c++-arm-linux-gnu) on x64 CentOS, gcc 4.8.5, binutils 2.27.

test.cpp (return type is just to coerce an access):

Code: Select all

struct kernel_info
{
   const char* name    = "MinOS";
   const char* version = "0.1";
   const char* build    = "1";
} kernel_info;

extern "C" int _start()
{
  return kernel_info.name[0];
}
The assembly and GOT results are on pastebin here, but basically the code uses GOT in the intermediate object files and the final elf. Also, the GOT is populated with the correct address and there are no outstanding relocations. My assembly comprehension on arm is poor, so you may make better sense out of it, but it seems correct.

Something must differ in your setup. Obviously the gcc build, but may be also the cpu target ("cortex-a5" in my case), or the usage, etc.

Edit: changed the paste to the bash commands that are relevant
SimonHA
Posts: 12
Joined: Thu Nov 10, 2016 4:00 pm

Re: ARM C++ issue with static members and PIC code

Post by SimonHA »

Hi again,

Thanks for all your replies. I managed to solve the issue by declaring my struct static and use char array rather than a pointer.
This fixes the issue with the address location of the constants not begin position independent.

Code: Select all

static struct kernel_info
{
	const char name[6] 		= "MinOS";
	const char version[4] 	= "0.1";
	const char build[2] 	= "1";
} kernel_info;
Best regards,
Simon
Post Reply