Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get a label address out of the function scope in gcc/clang (C++)


I'm making some kind of interpreter and I'm computing a static const jump table thanks to local label addresses.
You know the drill, static const int JUMP_TABLE[] = { &&case0 - &&case0, &&case1 - &&case0 and so on.
For various reasons, mostly performance, I'd like to copy/compress this table in an object during init.
I'm hurting my head against the wall because I can't figure how to escape the lexical scoping of the function !

How can I somehow reference &&case0 from another function ?

Does somebody have a good trick for this ?
Thanks in advance

like image 348
Tramboi Avatar asked May 16 '20 08:05

Tramboi


1 Answers

I'm not aware of ways to achieve this within pure GNU C so approaches below use other mechanisms.

Double compilation

You can compile your object file twice, collecting offsets on the first run and using them on the second. For example

int foo(int x) {
#ifdef GENERATE_ADDRESSES
    static __attribute__((section(".foo_offsets"))) unsigned offsets[] = { &&case0 - &&case0, &&case1 - &&case0 };
#endif
    switch (x) {
case0:
        case 0:
            return 1;
case1:
        case 1:
            return 2;
    }
    return 0;
}

Now you can compile, extract bytes from .foo_offsets section and embed them to you app on second run

$ gcc tmp.c -c -DGENERATE_ADDRESSES
$ objcopy -j .foo_offsets -O binary tmp.o
$ xxd -i tmp.o | tee offsets.inc
unsigned char tmp_o[] = {
  0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00
};
unsigned int tmp_o_len = 8;

Inline assembly

You can use inline assembly to globalize labels:

extern char foo_case0[];
extern char foo_case1[];
const void *foo_addresses[] = { &foo_case0[0], &foo_case1[0] };

int foo(int x) {
    switch (x) {
        case 0:
asm("foo_case0:");
            return 1;
        case 1:
asm("foo_case1:");
            return 2;
    }
    return 0;
}

Unfortunately in this case you can only collect addresses (not offsets) so you'll need to manually compute offsets at startup.

like image 66
yugr Avatar answered Oct 17 '22 00:10

yugr