Jump Table Optimization
A jump table is used to optimize the execution of switch-case statements or indirect branches. It consists of an array of RVAs where it supposed to jump into, depending on the value of a particular variable or expression.
Depends on the configuration, in particular, when you are applying read detection feature, this option matters.
Optimizing out the jump table
You can optimize out by applying special compiler or linker flags to make those components aware of the jump tables so that the executable chunks are indeed guaranteed to not be read.
- Add
/d2jumptablerdata
to the compiler flag. - Add
/d2:-jumptablerdata
to the linker flag.
/d2
is a special prefix for MSVC compiler and linker backends (c2
).
For more information about this option, see MSDN: /jumptablerdata (put switch case jump tables in .rdata) (opens in a new tab).
How it works
Most modern production compilers and linkers put the jump table into the tail of the function by default.
However, the jump table is just an array of RVAs reference and will never be executed and it should be on the non-executable and readable segment.
Compiled and linked by MSVC with full optimization applied.
.text:0000000140001000 ; int __fastcall main(int argc, const char **argv, const char **envp)
.text:0000000140001000 main proc near ; CODE XREF: __scrt_common_main_seh+107↓p
.text:0000000140001000 argc = ecx
.text:0000000140001000 dec argc ; switch 45 cases
.text:0000000140001002 cmp argc, 2Ch
.text:0000000140001005 ja short $LN11 ; jumptable 0000000140001023 default case, cases 4,6,8-44
.text:0000000140001007 movsxd rax, argc
.text:000000014000100A lea rdx, cs:140000000h
.text:0000000140001011 movzx eax, ds:(byte_14000106C - 140000000h)[rdx+rax]
.text:0000000140001019 mov argc, ds:(jpt_140001023 - 140000000h)[rdx+rax*4]
.text:0000000140001020 add rcx, rdx
.text:0000000140001023 jmp rcx ; switch jump
.text:0000000140001025 ; ---------------------------------------------------------------------------
.text:0000000140001025
.text:0000000140001025 $LN4: ; CODE XREF: main+23↑j
.text:0000000140001025 ; DATA XREF: main:jpt_140001023↓o
.text:0000000140001025 mov eax, 2 ; jumptable 0000000140001023 case 1
.text:000000014000102A retn
.text:000000014000102B ; ---------------------------------------------------------------------------
.text:000000014000102B
.text:000000014000102B $LN5: ; CODE XREF: main+23↑j
.text:000000014000102B ; DATA XREF: main:jpt_140001023↓o
.text:000000014000102B mov eax, 3 ; jumptable 0000000140001023 case 2
.text:0000000140001030 retn
.text:0000000140001031 ; ---------------------------------------------------------------------------
.text:0000000140001031
.text:0000000140001031 $LN6: ; CODE XREF: main+23↑j
.text:0000000140001031 ; DATA XREF: main:jpt_140001023↓o
.text:0000000140001031 mov eax, 6 ; jumptable 0000000140001023 case 5
.text:0000000140001036 retn
.text:0000000140001037 ; ---------------------------------------------------------------------------
.text:0000000140001037
.text:0000000140001037 $LN7: ; CODE XREF: main+23↑j
.text:0000000140001037 ; DATA XREF: main:jpt_140001023↓o
.text:0000000140001037 mov eax, 0Bh ; jumptable 0000000140001023 case 7
.text:000000014000103C retn
.text:000000014000103D ; ---------------------------------------------------------------------------
.text:000000014000103D
.text:000000014000103D $LN9: ; CODE XREF: main+23↑j
.text:000000014000103D ; DATA XREF: main:jpt_140001023↓o
.text:000000014000103D mov eax, 41h ; 'A' ; jumptable 0000000140001023 case 3
.text:0000000140001042 retn
.text:0000000140001043 ; ---------------------------------------------------------------------------
.text:0000000140001043
.text:0000000140001043 $LN10: ; CODE XREF: main+23↑j
.text:0000000140001043 ; DATA XREF: main:jpt_140001023↓o
.text:0000000140001043 xor eax, eax ; jumptable 0000000140001023 case 45
.text:0000000140001045 retn
.text:0000000140001046 ; ---------------------------------------------------------------------------
.text:0000000140001046
.text:0000000140001046 $LN11: ; CODE XREF: main+5↑j
.text:0000000140001046 ; main+23↑j
.text:0000000140001046 ; DATA XREF: ...
.text:0000000140001046 mov eax, 0Ah ; jumptable 0000000140001023 default case, cases 4,6,8-44
.text:000000014000104B retn
.text:000000014000104B ; ---------------------------------------------------------------------------
.text:000000014000104C jpt_140001023 dd offset $LN4 - 140000000h
.text:000000014000104C ; DATA XREF: main+19↑r
.text:0000000140001050 dd offset $LN5 - 140000000h ; jump table for switch statement
.text:0000000140001054 dd offset $LN9 - 140000000h
.text:0000000140001058 dd offset $LN6 - 140000000h
.text:000000014000105C dd offset $LN7 - 140000000h
.text:0000000140001060 dd offset $LN11 - 140000000h
.text:0000000140001064 dd offset $LN10 - 140000000h
.text:0000000140001068 dd offset $LN11 - 140000000h
.text:000000014000106C byte_14000106C db 0, 1, 2, 7
.text:000000014000106C ; DATA XREF: main+11↑r
.text:0000000140001070 db 3, 7, 4, 7 ; indirect table for switch statement
.text:0000000140001074 db 7, 7, 7, 7
.text:0000000140001078 db 7, 7, 7, 7
.text:000000014000107C db 7, 7, 7, 7
.text:0000000140001080 db 7, 7, 7, 7
.text:0000000140001084 db 7, 7, 7, 7
.text:0000000140001088 db 7, 7, 7, 5
.text:000000014000108C db 7, 7, 7, 7
.text:0000000140001090 db 7, 7, 7, 7
.text:0000000140001094 db 7, 7, 7, 7
.text:0000000140001098 db 6
.text:0000000140001098 main endp