I'm using IDAPython on IDA 6.5 and I'm trying to get all the switch jump tables in a DLL. Mainly I'm interested in jump tables that are jumped indirectly:

jmp     ds:off_65018790[ecx*4] ; switch jump

Basically, what interests me is:

  • The address from where the jmp happens
  • The list of the possible locations, for example - loc_65018723, loc_65018736...

I already know how to get all the jmp addresses using IDAPython, but I don't know if it's a jmp to a jump table or just a normal jmp.

In most cases, IDA knows to identify those jump tables, so is there a way to get that info from the API?

Thanks a lot!

  • Unfortunately I don't have IDA 6.5 installed, but as far as I remember idaapi.get_switch_info_ex(ea) already was there. The simplest way to see reference usage of this function is searching python code with call to this function on github. – w s Aug 25 '16 at 9:12
  • Thanks a lot! It was exactly what I needed. If you post it as an answer, I will mark it as answered :) – Alex Aug 26 '16 at 11:42

Decided to add a small code snippet to show how to iterate through the .text segment, obtaining all the switch table locations and storing the jump targets in a dictionary.

text_seg = idaapi.get_segm_by_name('.text')
jump_table = dict()

# iterate through all items within the segment
for head_ea in idautils.Heads(text_seg.startEA, text_seg.endEA):
    if idc.isCode(idc.GetFlags(head_ea)):
        switch_info = idaapi.get_switch_info_ex(head_ea)
        if (switch_info and switch_info.jumps != 0):
            loc = switch_info.jumps
            jump_table[loc] = list()
            element_num = switch_info.get_jtable_size()
            element_size = switch_info.get_jtable_element_size()
            for num in range(0, element_num):
                table_entry = loc+num*element_size
                jump_table[loc].append(idc.GetManyBytes(table_entry), element_size)
  • getnseg receives a segment number, while SegByName returns a segment selector, these are not the same thing. Your first line is erroneous. – NirIzr Sep 9 '16 at 10:38
  • Additionally, using idc.Dword feels insecure and assumes the switch code is indeed structured the way OP described, which isn't always the case. – NirIzr Sep 9 '16 at 10:48
  • Thanks Nirlzr, the above snippet comes from my old script I used on ARM32 binaries to extract out jumptables in order to rewrite them. I've updated it to fix the mistakes you've pointed out. – chuazl Sep 10 '16 at 9:32

To safely get all references from a certain EA, there's idc.XrefsFrom(ea, flags). You'll get an iterator for cross references from a certain EA (the switch-case's branch/jump instruction). switch-cases are easy to identify as they're always with more than two cross references targets.

According to this the flags parameter is one of the following:


The object you'll get from each iteration is an ida_xref object, exposing the following attributes:

  1. frm - The source of the cross reference, the code that performs the jump in our case.
  2. to - The target of the cross reference, the code that will be executed according to the jump table selector in our case.
  3. iscode - Boolean, True if cross reference is a code cross reference, must be True in our case.
  4. type - One of the available type values, see below. You could use idautils.XrefTypeName(typecode) to translate the integer you get here to a readable string.
  5. user - Boolean, True if this cross reference was created by the user, opposed to being automatically created by IDA.

The valid cross reference types are, according to this:

ref_types = {
0 : 'Data_Unknown',
1 : 'Data_Offset',
2 : 'Data_Write',
3 : 'Data_Read',
4 : 'Data_Text',
5 : 'Data_Informational',
16 : 'Code_Far_Call',
17 : 'Code_Near_Call',
18 : 'Code_Far_Jump',
19 : 'Code_Near_Jump',
20 : 'Code_User',
21 : 'Ordinary_Flow'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.