-1

I'm relatively new to assembly and am working with a powerpc chip. I'm using a gcc crosscompiler and working with a buildroot environment (just for background).

I am adding code to the .head section of some code that will create a .elf object (lets call it target.elf for arguments sake) which gets brought into a larger binary all via buildroot. target.elf is defined as starting at address 0x0 in the code and the local linker but will get moved to a different address location later. I wish to reference a global variable, that is being shared between the assembly code and a c-file, from the assembly code. When I do so using location independent means I run into problems. When I do use using the GOT as reference (symbol@got@h for instance) I am able to reference the symbol correctly.

This is a problem because I wish to create a interrupt handler that does not depend on having a valid pointer to the stack or TOC upon entering, and I need the TOC to use the GOT.

Is there a way of doing this without the TOC?

Here is some example code:

Incorrect result (%r3 does not contain what "symbol" contains):

.global symbol
symbol:
    .long 0

.global irq_handler
irq_handler:
    addi    %r3, 0, 0
    ori     %r3, %r3, symbol@l
    ld      %r3, 0(%r3)
    b       .

In global area of C-file:
extern uint64_t symbol;

I have also attempted defining the symbol in the c-file (so without extern but still as a global) and omitting the definition in the asm file. This also has failed.

I am also taking a shortcut and only loading the @l portion of the address because the top 32 bits are 0x0.

Correct result (%r3 does contain what "symbol" contains):

.global irq_handler
irq_handler:
  ld      %r3, symbol@got(%r2)
  ld      %r3, 0(%r3)
  b       .

Note that in the correct example the TOC is available in %r2.

Thank you in advance.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
Tyler
  • 17
  • 8
  • 1
    I don't understand how you can have *"interrupt handler that does not depend on having a valid pointer to the stack"* – Weather Vane Mar 31 '16 at 17:33
  • The interrupt handler provides a means for branching into a different *context*. For this situation I will back up my current context (registers) in a known location before branching to the new context. When I return the registers will be in an undefined state. When the irq is triggered again I will restore the original context but wish to reference "symbol" before restoring the TOC. The interrupt handler handles other functionality as well, without getting into too much detail. – Tyler Mar 31 '16 at 17:53
  • Clarification for above comment: Return from the other context is facilitated by calling the same interrupt handler again. When called again the registers are in an unknown state and will be restored after checking "symbol". – Tyler Mar 31 '16 at 18:02
  • An interrupt routine needs to load R2 with its own TOC base. Normally the ELF PowerPC ABI requires the caller of a function to set R2 to the value of the TOC base of the function being called. That obviously can't happen with interrupts. The code used to set R2 uses the TOC of the the calling function, so you can't just copy that code, since in general an interrupt routine can't know what TOC its "caller" is using (if any). You might look at what the Linux or other PowerPC kernels do in their interrupt routines. – Ross Ridge Mar 31 '16 at 19:21
  • Thank you. I have a kernel on hand for reference and have been using it as such. I have a few ideas for work around but I guess I'd hoped that maybe if I was missing something and I didn't need the TOC here that I could do something cleaner. But it sounds like for code that will move, I *need* the TOC to locate "symbol". Thanks very much. – Tyler Mar 31 '16 at 21:45

1 Answers1

0

Seems that the answer is that the TOC is required for location independent code.

Tyler
  • 17
  • 8