Explain jump table construct in RISC-V assembly

103 views Asked by At

In some disassembly I see jal ra sym.imp.strlen which jumps to a construct which looks like this in radare2:

┌ 128: size_t sym.imp.strlen (const char *s);
│           0x00035b40      172eb600       auipc t3, 0xb62
│           0x00035b44      033e0e75       ld t3, 1872(t3)
│           0x00035b48      67030e00       jalr t1, t3
│           0x00035b4c      13000000       nop
│           ;-- dlclose:
│           0x00035b50      172eb600       auipc t3, 0xb62
│           0x00035b54      033e8e74       ld t3, 1864(t3)
│           0x00035b58      67030e00       jalr t1, t3
│           0x00035b5c      13000000       nop
│           ;-- erff:
│           0x00035b60      172eb600       auipc t3, 0xb62
│           0x00035b64      033e0e74       ld t3, 1856(t3)
│           0x00035b68      67030e00       jalr t1, t3
│           0x00035b6c      13000000       nop
│           ;-- truncf:
│           0x00035b70      172eb600       auipc t3, 0xb62
│           0x00035b74      033e8e73       ld t3, 1848(t3)
│           0x00035b78      67030e00       jalr t1, t3
│           0x00035b7c      13000000       nop
│           ;-- strncpy:
│           0x00035b80      172eb600       auipc t3, 0xb62
│           0x00035b84      033e0e73       ld t3, 1840(t3)
│           0x00035b88      67030e00       jalr t1, t3
│           0x00035b8c      13000000       nop
│           ;-- write:
│           0x00035b90      172eb600       auipc t3, 0xb62
│           0x00035b94      033e8e72       ld t3, 1832(t3)
│           0x00035b98      67030e00       jalr t1, t3
│           0x00035b9c      13000000       nop
│           ;-- fesetround:
│           0x00035ba0      172eb600       auipc t3, 0xb62
│           0x00035ba4      033e0e72       ld t3, 1824(t3)
│           0x00035ba8      67030e00       jalr t1, t3
│           0x00035bac      13000000       nop
│           ;-- sincos:
│           0x00035bb0      172eb600       auipc t3, 0xb62
│           0x00035bb4      033e8e71       ld t3, 1816(t3)
│           0x00035bb8      67030e00       jalr t1, t3
└           0x00035bbc      13000000       nop

Is this a jump table?

It seems strange to me to jump to the strlen function so indirectly. It jumps first to this table, then uses auipc (so the address of the table entry plus 0xb62 << 12) to calculate an address to load. Loads the address + some offset (I assume this is the entry point of strlen) and then jumps there. Why not just have a symbol for jumping directly to strlen's entry point?

One possible justification I can think of is code compression - it may be more compact to do this rather than loading/jumping to a symbol at every place strlen is called. I also have a feeling it could be something to do with linking?

0

There are 0 answers