[llvm-dev] Generating completely position agnostic code

Jorg Brown via llvm-dev llvm-dev at lists.llvm.org
Tue Jul 9 09:44:09 PDT 2019


Ah, good.  Well, maybe.

The reason I asked, originally, was that if you can use thread-local
globals rather than normal globals, then all references to globals will be
through a dedicated register, and it's generally easy to set up that
register in your entry point, since you say you only have the one entry
point.

On x86 it's a bit more difficult, since it uses a dedicates segment
register for thread-local variables... not just a regular register.  And it
tends to want to check to see if the thread-local variables are set up in
each routine, before using them.  And it still generates relocations.

So on x86 I'd consider using a different approach a dedicated register of
your choice, e.g.:

struct globs {
  char flag;
};

register
globs *gp asm("rbx");   //storing global variable in register explicitly

void f(char *cp) {
  gp->flag = *cp;
}

int entry_point(globs *globs_ptr, char *cp) {
  gp = globs_ptr;  // set up access to our globals
  f(cp);
  return gp->flag;
}

See https://godbolt.org/z/oOLJ1n for generated code.

Of course, this still means you have to modify the STL (and whatever other
libraries you might want to call) to use this global register to access all
its global variables... but it beats having to modify every routine to add
an extra parameter.  But I haven't been able to think of any approach that
doesn't have that problem, and with macros (#define cout gp->cout) it might
not be that difficult.  And at least this way, no relocations are emitted.

On Sun, Jul 7, 2019 at 3:14 PM Hayden Livingston <halivingston at gmail.com>
wrote:

> x86-64.
>
> On Mon, Jul 1, 2019 at 11:07 AM Jorg Brown <jorg.brown at gmail.com> wrote:
> >
> > What architecture do you need this for?
> >
> > Does the code in question ever use more than one thread?
> >
> > On Mon, Jul 1, 2019 at 1:47 AM Hayden Livingston <halivingston at gmail.com>
> wrote:
> >>
> >> It is wholly self-contained. It's code that has no references to
> >> anything beyond a set of pointers passed in as arguments to the
> >> function. This piece of code doesn't do any OS work at all. It is
> >> purely calling function pointers, doing math and allocating memory.
> >>
> >> On Mon, Jul 1, 2019 at 12:57 AM Jorg Brown <jorg.brown at gmail.com>
> wrote:
> >> >
> >> > Qs for you:
> >> >
> >> > The code that is being loaded from disk... is it wholly
> self-contained, or is your executable potentially made up of several pieces
> that each need to be loaded from disk?
> >> >
> >> > What does it mean to use the STL but not have global variables?
> std::cout is a global variable, so you can't even do Hello World without
> globals.
> >> >
> >> > = = =
> >> >
> >> > Architectures such as 68K and PowerPC and RISC-V have a dedicated
> register for accessing global variables, rather than the PC-relative
> globals used in other architectures.  This makes them inherently more
> amenable to what you describe, since you can put the "array of function
> pointers" into global space, as part of setting up global space in general,
> and then load the code from disk, and go.  There is no relocation needed
> since all access to globals is done via the global register, not relative
> to wherever the program was loaded.  Of course, access to something like
> libc might normally need post-loading relocation, but if you do what you're
> talking about and use an "array of function pointers" to get to libc, no
> relocation would be needed.
> >> >
> >> > For what it's worth, the original 68K-based Macintosh used a scheme
> quite similar to this.  The big difference for the Mac was that to get to
> the OS (the equivalent of libc), it didn't use an array of function
> pointers, per se; it used a certain range of illegal instructions, which
> generated exceptions when used, and the (highly optimized) exception
> handlers would recover from the exception by dispatching to an OS routine
> determined by the specific bits in the illegal instruction.
> >> >
> >> > On Sun, Jun 30, 2019 at 9:07 PM Hayden Livingston via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
> >> >>
> >> >> I'm on a mission to generate code that can be loaded from disk
> without
> >> >> any modifications. This means no relocations can occur.
> >> >>
> >> >> Trying to see if this can be done for C++ code that uses STL but has
> >> >> no global variables, and a single function, but of course Clang will
> >> >> generate more functions for STL code.
> >> >>
> >> >> I want to provide an array of function pointers so that for all
> >> >> interactions STL needs to do with LIBC that I'm able to just provide
> >> >> it via indirect calls.
> >> >>
> >> >> Has anyone had success with such a thing in LLVM?
> >> >> _______________________________________________
> >> >> LLVM Developers mailing list
> >> >> llvm-dev at lists.llvm.org
> >> >> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190709/1603df14/attachment.html>


More information about the llvm-dev mailing list