I’ve been working on converting my existing 32-bit ppc code to ppc64. A lot of the ABI is the same (and my funky StackFrame class hides a lot of the differences) but one weird thing is that on ppc64 function pointers do not point to the actual code but to some descriptor thing. OpenJDK has loads of places that do the following, and they’re all wrong:

void (*function)() = generate_some_code();
...
(*function)();

I think the descriptors are supposed to be in some table that the linker creates, but I sneaked around it by making an assembler macro, function_entry_point(), that creates a function descriptor that points to the address immediately following it, the idea being that you place it at the start of anything you’re going to jump into from C. I’m not entirely happy with it: I’m not sure what the implications of mixing descriptors and code like this, and it makes the stubs non-relocatable, and omitting the function_entry_point() will cause a mysterious segfault as the processor dereferences the first two instructions of your stub and jumps to wherever they point. But needs must…

5 thoughts on “

  1. Too bad the ia64 code wasn’t open sourced. It does what I suspect is a similar thing. On ia64 as I recall (this is a suppressed memory) the function pointer returns a pointer to a block of storage that contains the actual function address and also a pointer to the value that goes in gp (?). The jvm ran with all the data in the same area so we created dummy function descriptors so that c++ code could call our stubs and gp never would change. This wouldn’t work if other libraries besides libjvm.so called our generated stubs but that doesn’t occur. The assembler had an “instruction” to produce one of the descriptors which we used at the start of a stub (or anywhere we’d call in from C++). For calls from our generated assembly code I think that the instruction magically pulled out the target from the descriptor and called that.

  2. That sounds pretty much identical. On ppc64 the function pointer points to a block of storage that contains two 64-bit values: the function address, and a value to load into r2 prior to jumping to it. So I made this macro:

    address MacroAssembler::enter()
    {
      address start = pc();
    #ifdef PPC64
      // Sneak in a function descriptor
      // XXX this is not relocatable!
      emit_address(start + 16);
      emit_address(NULL);
    #endif // PPC64
      return start;
    }

    All the stub generators have something like address start = __ pc() so I just changed them to address start = __ enter() and that was that.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.