Can gcc be made to generate PIC code where the data and bss are relocatable and are not known at compile time?

Asked by Joshua Goldstein

I'm trying to make on-the fly loadable modules work using an RTOS. What I'd like to be able to do is to be able to, at runtime, load the module to an arbitrary address. This is easy to do for things like the .text section, by just having the compiler generate position independent code. I am also compiling with a -msingle-pic-base, as this is the method the RTOS expects to be used.

It is a fairly easy proposition have the data section loaded to an arbitrary address: if I'm compiling PIC code to a different address than I gave to the linker, I can simply fixup the GOT before starting the module. The issue I'm seeing is that variables declared as 'static' are not being looked up through the GOT, but rather by adding a the PC to a fixed offset. To provide an example, here is how a non static variable is loaded (please excuse the formatting):

   87c3e: 4b05 ldr r3, [pc, #20] ; load at address 875c4
   87c40: f859 3003 ldr.w r3, [r9, r3]
  ; ... code that is not important ...
  87c48: 60da str r2, [r3, #12]
  ; ...
   87c54: 00003f70 .word 0x00003f70

Here, r9 points to the GOT. Everything will be fine, as long as we have the GOT pointing to the right place. We load the offset, which is PC relative, load from the GOT using the static base r9, and then use the real address, pointing into the .data section, which is in r3.

Here is how a static variable is loaded:
   87c28: 4b08 ldr r3, [pc, #32] ; load at address 87c4c
   87c2a: 447b add r3, pc
  ; ... code that is not important ...
   87c30: 609a str r2, [r3, #8]
  ; ....
    87c4c: 1ff943de .word 0x1ff943de

Here, we're loading an offset from the PC, which is itself PC relative, then add that to the PC and place it in r3. Now r3 points directly into the .data section.

The problem in the case of the static variable is that it is now not (easily) possible to load the data section to an arbitrary area of memory as we no longer have just the GOT to fixup to do and we have things we'd like to change that are now in the .text section.

My question: is this intended behavior? Is it a bug? The behavior with statics seems to not play very well with the concept of using the static base register to point to one's data.

Question information

Language:
English Edit question
Status:
Solved
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Solved by:
Joshua Goldstein
Solved:
Last query:
Last reply:
Revision history for this message
Joey Ye (jinyun-ye) said :
#1

Joshua, both ways work if .text and .data are relocated together, and they
have the same offset to each other. This is how linux relocation work. As I
understand you only want to relocate data not code. I can't think of a way
to solve it now.

Let me come back from vacation to do more research.

Joey
On Oct 3, 2013 5:36 AM, "Joshua Goldstein" <
<email address hidden>> wrote:

> New question #236744 on GCC ARM Embedded:
> https://answers.launchpad.net/gcc-arm-embedded/+question/236744
>
> I'm trying to make on-the fly loadable modules work using an RTOS. What
> I'd like to be able to do is to be able to, at runtime, load the module to
> an arbitrary address. This is easy to do for things like the .text section,
> by just having the compiler generate position independent code. I am also
> compiling with a -msingle-pic-base, as this is the method the RTOS expects
> to be used.
>
> It is a fairly easy proposition have the data section loaded to an
> arbitrary address: if I'm compiling PIC code to a different address than I
> gave to the linker, I can simply fixup the GOT before starting the module.
> The issue I'm seeing is that variables declared as 'static' are not being
> looked up through the GOT, but rather by adding a the PC to a fixed offset.
> To provide an example, here is how a non static variable is loaded (please
> excuse the formatting):
>
> 87c3e: 4b05 ldr r3, [pc, #20] ; load at address
> 875c4
> 87c40: f859 3003 ldr.w r3, [r9, r3]
> ; ... code that is not important ...
> 87c48: 60da str r2, [r3, #12]
> ; ...
> 87c54: 00003f70 .word 0x00003f70
>
> Here, r9 points to the GOT. Everything will be fine, as long as we have
> the GOT pointing to the right place. We load the offset, which is PC
> relative, load from the GOT using the static base r9, and then use the real
> address, pointing into the .data section, which is in r3.
>
> Here is how a static variable is loaded:
> 87c28: 4b08 ldr r3, [pc, #32] ; load at address
> 87c4c
> 87c2a: 447b add r3, pc
> ; ... code that is not important ...
> 87c30: 609a str r2, [r3, #8]
> ; ....
> 87c4c: 1ff943de .word 0x1ff943de
>
> Here, we're loading an offset from the PC, which is itself PC relative,
> then add that to the PC and place it in r3. Now r3 points directly into the
> .data section.
>
> The problem in the case of the static variable is that it is now not
> (easily) possible to load the data section to an arbitrary area of memory
> as we no longer have just the GOT to fixup to do and we have things we'd
> like to change that are now in the .text section.
>
> My question: is this intended behavior? Is it a bug? The behavior with
> statics seems to not play very well with the concept of using the static
> base register to point to one's data.
>
> --
> You received this question notification because you are an answer
> contact for GCC ARM Embedded.
>

Revision history for this message
Joshua Goldstein (goldstei) said :
#2

Well, I'd like to be able to relocate the code as well. The key issue is that of not knowing the distance between the .data and .text sections. If I had virtual memory, of course, this wouldn't be a problem, but that's not really an option on the M3.

I'm pretty sure it would need a small compiler change. Looking through the code in src/gcc/gcc/config/arm/arm.c, it looks like there a few places where, if VxWorks is the target, the compiler will already do very similar things to what I'd like it to do -- provided it is doing what I think it's doing (I wouldn't call myself a GCC dev, but the general code flow makes sense). I guess it might work to make that behavior conditional on some kind of compiler flag.

Revision history for this message
Joey Ye (jinyun-ye) said :
#3

Joshua,

I can confirm your issue now.

There are three approaches to address a PIC symbol.
a. PC relative.
ldr r3, .L2
.label2:
add r3, pc
.L2:
.word variable - .label2 - 4

b. Offset to GOT
ldr r3, .L2
add r3, r9

.L2:
.word variable(GOTOFF)

c. GOT
ldr r3, .L2
ldr r3, [r9, r3]

.L2:
.word variable(GOT)

This toolchain uses option A for static variables. As you pointed out VxWorks uses option C. Unfortunately there isn't a compiler option to choose among these behaviours, which might be the right thing to do.

To better understand your use case, please suggest if the offset is fixed between .data and .got. If yes, then option b will be what you preferred. Or otherwise option c.

- Joey

Revision history for this message
Joshua Goldstein (goldstei) said :
#4

I'm placing the .got right in front of the .data, so yes. The offset between these two is fixed. However, the offset between the .text section (where the label will be) and the .got/.data is not fixed. This is because I'm pretty tight on memory, so I don't want to just set out fixed sized regions for code and data a fixed distance apart.

If I understand correctly, that GOTOFF in (b) encodes the location in .data as an offset from the start of the GOT, then yes, this would work since the .got and the .data do have a fixed offset from one another. It would also be acceptable to use (c), though this would mean that the GOT might have to be a little bigger than in (b).

It would indeed be quite nice to have a compiler option to pick between the three.

Revision history for this message
Joshua Goldstein (goldstei) said :
#5

Would you prefer that I file this as a bug. I'd also be interested in trying to patch it, but, as I said, I'm not too familiar with the gcc internals. Is there any good documentation on the internals and the ARM backend?

Revision history for this message
Joey Ye (jinyun-ye) said :
#6

I would think it a new feature rather than bug. I have a local patch
already, it takes time to review before I can share it.

Also, during the implementation I realized that (b) is not working as gcc
will also use gotoff for read-only data access, which is usually fixed
offset to .text not to .got. so the patch I'm working on only handle a and
c.
On Oct 17, 2013 12:31 AM, "Joshua Goldstein" <
<email address hidden>> wrote:

> Question #236744 on GCC ARM Embedded changed:
> https://answers.launchpad.net/gcc-arm-embedded/+question/236744
>
> Joshua Goldstein posted a new comment:
> Would you prefer that I file this as a bug. I'd also be interested in
> trying to patch it, but, as I said, I'm not too familiar with the gcc
> internals. Is there any good documentation on the internals and the ARM
> backend?
>
> --
> You received this question notification because you are an answer
> contact for GCC ARM Embedded.
>

Revision history for this message
Joey Ye (jinyun-ye) said :
#7

Joshua,

Can you please try http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01572.html to see if it is what you expected.

Basically this patch enables an option -m[no-]pic-data-is-text-relative to enable[disable] PC relative and only use GOT for all global, static and readonly data.

If no issue, it will be in the coming 4.8 release.

Thanks,
Joey

Revision history for this message
Joshua Goldstein (goldstei) said :
#8

How would I go about trying it. I'm only seeing the email message here. I assume I'll have to checkout some version of gcc, patch and then see if that build does what I want it to, yes?

Revision history for this message
Joey Ye (jinyun-ye) said :
#9

Rebuilding is needed to try it. I understand it cost some time to setup if
you haven't built GCC before.

Never mind, as long as you think the described functionality should solve
the problem, I'll commit it and include it next release targeting end of
the year.

- Joey

On Tue, Nov 19, 2013 at 1:26 AM, Joshua Goldstein <
<email address hidden>> wrote:

> Question #236744 on GCC ARM Embedded changed:
> https://answers.launchpad.net/gcc-arm-embedded/+question/236744
>
> Joshua Goldstein posted a new comment:
> How would I go about trying it. I'm only seeing the email message here.
> I assume I'll have to checkout some version of gcc, patch and then see
> if that build does what I want it to, yes?
>
> --
> You received this question notification because you are an answer
> contact for GCC ARM Embedded.
>

Revision history for this message
Joshua Goldstein (goldstei) said :
#10

That sounds good to me.

Revision history for this message
Joey Ye (jinyun-ye) said :
#11

Joshua,

The 4.8 release enabled a new option -mno-pic-data-is-text-relative to generate GOT for all data. Please try it at https://launchpad.net/gcc-arm-embedded/+milestone/4.8-2013-q4-major

Please let me know if there is any further issues.

Thanks,
Joey

Revision history for this message
Joshua Goldstein (goldstei) said :
#12

I've tried it and it looks like it fixes the problem.