I'm analyzing the firmware of a device that has the cpu ARM946E-S. It has not a file system, just assembly code and strings.

I've disassembled the firmware using ida pro, but I couldn't find the entry point.

I know that in the interrupt address table there is a pointer called 'Reset', I could use it to start dynamic analysis, but I could not find the IAT either.

Obviously, I've tried to analyze it using binwalk and radare2 unsuccessfully.

Can someone tell me how to find the interrupt address table?


After Brendan Dolan-Gavitt's answer.

In cpu documentation, there is a control register called “alternate vector select”.

enter image description here I do not know how to get the control register table.

And I have another doubt. My firmware is 16MB, so where is the IVT if the Bit 13 is set?

Since it was impossible for me to locate the IVT I’ve decided to try the approach suggested by Brendan:

Each entry of the IVT is an arm instruction that jumps to a specific location. The only instruction that does an unconditional jump is b (branch). So I inferred that the IVT is composed of a set of b instructions.

The opcode of b is EA. So searching in the hexadecimal version of the firmware… enter image description here It finds only one occurrence.

Analysing that location with radare2: enter image description here

Those branch instructions point to themselves. It doesn’t make any sense.

  • show us a hexdump of the first 64-128 or so bytes
    – Igor Skochinsky
    May 12, 2021 at 18:33
  • That is the first part: link May 17, 2021 at 10:40

2 Answers 2


For the ARM946E-S Technical Reference Manual, the exception vectors (including the reset vector) should be located at either 0x00000000 or 0xFFFF0000 in memory, depending on whether the Alternate vectors select bit is set. The layout of these vectors looks like:

Exception                   |       Address            
Reset                       |      0xffff0000           
Undefined Instruction       |      0xffff0004       
SWI                         |      0xffff0008  
Prefetch Abort              |      0xffff000c       
Data Abort                  |      0xffff0010 
Reserved                    |      0xffff0014  
IRQ                         |      0xffff0018   
FIQ                         |      0xffff001c  

(Table reproduced from this blog post, but you can also find it somewhere in the ARM Architecture Reference Manual)

Note that each of these is not a pointer but an ARM instruction (usually a jump to the handler for that vecor). You can see an example of how this is implemented in something like Linux by looking at the kernel entry point code: https://github.com/torvalds/linux/blob/f77ac2e378be9dd61eb88728f0840642f045d9d1/arch/arm/kernel/entry-armv.S#L1183-L1191

One complication in your case is that since you're dealing with a firmware image rather than looking at this in memory you'll have to figure out where the image is actually mapped in memory. Alternatively you can just try to disassemble the whole image (e.g. using objdump to get a linear disassembly) and look for a sequence of branch instructions that matches.

  • 1
    Thank you, I've tried what you suggested to me and I've updated the questions. May 17, 2021 at 9:21

The first bytes are the exception vectors:

CODE:00000000                 LDR             PC, =0x1000005C
CODE:00000004 ; ---------------------------------------------------------------------------
CODE:00000004                 LDR             PC, =0x10000044
CODE:00000008 ; ---------------------------------------------------------------------------
CODE:00000008                 LDR             PC, =0x10000048
CODE:0000000C ; ---------------------------------------------------------------------------
CODE:0000000C                 LDR             PC, =0x1000004C
CODE:00000010 ; ---------------------------------------------------------------------------
CODE:00000010                 LDR             PC, =0x10000050
CODE:00000010 ; ---------------------------------------------------------------------------
CODE:00000014                 ALIGN 8
CODE:00000018                 LDR             PC, =0x10000054
CODE:0000001C ; ---------------------------------------------------------------------------
CODE:0000001C                 LDR             PC, =0x10000058
CODE:0000001C ; ---------------------------------------------------------------------------
CODE:00000020 off_20          DCD 0x1000005C          ; DATA XREF: CODE:00000000↑r
CODE:00000024 off_24          DCD 0x10000044          ; DATA XREF: CODE:00000004↑r
CODE:00000028 off_28          DCD 0x10000048          ; CODE XREF: sub_1D8↓j
CODE:00000028                                         ; DATA XREF: CODE:00000008↑r ...
CODE:0000002C off_2C          DCD 0x1000004C          ; DATA XREF: CODE:0000000C↑r
CODE:00000030 off_30          DCD 0x10000050          ; DATA XREF: CODE:00000010↑r
CODE:00000034 off_34          DCD 0x10000054          ; DATA XREF: CODE:00000018↑r
CODE:00000038 off_38          DCD 0x10000058          ; DATA XREF: CODE:0000001C↑r

Apparently the code is mapped at 0x10000000. After rebasing, we can see that the loops you've found are dummy handlers:

CODE:10000000                 LDR             PC, =Reset_Handler
CODE:10000004 ; ---------------------------------------------------------------------------
CODE:10000004                 LDR             PC, =Undef_Hander
CODE:10000008 ; ---------------------------------------------------------------------------
CODE:10000008                 LDR             PC, =SWI_Handler
CODE:1000000C ; ---------------------------------------------------------------------------
CODE:1000000C                 LDR             PC, =PrefAbort_Handler
CODE:10000010 ; ---------------------------------------------------------------------------
CODE:10000010                 LDR             PC, =DataAbort_Handler
CODE:10000010 ; ---------------------------------------------------------------------------
CODE:10000014                 ALIGN 8
CODE:10000018                 LDR             PC, =IRQ_Handler
CODE:1000001C ; ---------------------------------------------------------------------------
CODE:1000001C                 LDR             PC, =FIQ_Handler
CODE:1000001C ; ---------------------------------------------------------------------------
CODE:10000020 off_10000020    DCD Reset_Handler       ; DATA XREF: CODE:10000000↑r
CODE:10000024 off_10000024    DCD Undef_Hander        ; DATA XREF: CODE:10000004↑r
CODE:10000028 off_10000028    DCD SWI_Handler         ; DATA XREF: CODE:10000008↑r
CODE:1000002C off_1000002C    DCD PrefAbort_Handler   ; DATA XREF: CODE:1000000C↑r
CODE:10000030 off_10000030    DCD DataAbort_Handler   ; DATA XREF: CODE:10000010↑r
CODE:10000034 off_10000034    DCD IRQ_Handler         ; DATA XREF: CODE:10000018↑r
CODE:10000038 off_10000038    DCD FIQ_Handler         ; DATA XREF: CODE:1000001C↑r
CODE:1000003C aV10            DCB "v1.0"
CODE:10000040                 DCD 0x1C200
CODE:10000044 ; =============== S U B R O U T I N E =======================================
CODE:10000044 ; Attributes: noreturn
CODE:10000044 Undef_Hander                            ; CODE XREF: CODE:10000004↑j
CODE:10000044                                         ; Undef_Hander↓j
CODE:10000044                                         ; DATA XREF: ...
CODE:10000044                 B               Undef_Hander
CODE:10000044 ; End of function Undef_Hander
CODE:10000048 ; =============== S U B R O U T I N E =======================================
CODE:10000048 ; Attributes: noreturn
CODE:10000048 SWI_Handler                             ; CODE XREF: CODE:10000008↑j
CODE:10000048                                         ; SWI_Handler↓j
CODE:10000048                                         ; DATA XREF: ...
CODE:10000048                 B               SWI_Handler
CODE:10000048 ; End of function SWI_Handler
CODE:1000004C ; =============== S U B R O U T I N E =======================================
CODE:1000004C ; Attributes: noreturn
CODE:1000004C PrefAbort_Handler                       ; CODE XREF: CODE:1000000C↑j
CODE:1000004C                                         ; PrefAbort_Handler↓j
CODE:1000004C                                         ; DATA XREF: ...
CODE:1000004C                 B               PrefAbort_Handler
CODE:1000004C ; End of function PrefAbort_Handler
CODE:10000050 ; =============== S U B R O U T I N E =======================================
CODE:10000050 ; Attributes: noreturn
CODE:10000050 DataAbort_Handler                       ; CODE XREF: CODE:10000010↑j
CODE:10000050                                         ; DataAbort_Handler↓j
CODE:10000050                                         ; DATA XREF: ...
CODE:10000050                 B               DataAbort_Handler
CODE:10000050 ; End of function DataAbort_Handler
CODE:10000054 ; =============== S U B R O U T I N E =======================================
CODE:10000054 ; Attributes: noreturn
CODE:10000054 IRQ_Handler                             ; CODE XREF: CODE:10000018↑j
CODE:10000054                                         ; IRQ_Handler↓j
CODE:10000054                                         ; DATA XREF: ...
CODE:10000054                 B               IRQ_Handler
CODE:10000054 ; End of function IRQ_Handler
CODE:10000058 ; =============== S U B R O U T I N E =======================================
CODE:10000058 ; Attributes: noreturn
CODE:10000058 FIQ_Handler                             ; CODE XREF: CODE:1000001C↑j
CODE:10000058                                         ; FIQ_Handler↓j
CODE:10000058                                         ; DATA XREF: ...
CODE:10000058                 B               FIQ_Handler
CODE:10000058 ; End of function FIQ_Handler
CODE:1000005C ; ---------------------------------------------------------------------------
CODE:1000005C Reset_Handler                           ; CODE XREF: CODE:10000000↑j
CODE:1000005C                                         ; DATA XREF: CODE:10000000↑o ...
CODE:1000005C                 MOV             R1, #0x12
CODE:10000060                 ORR             R0, R1, #0
CODE:10000064                 MCR             p15, 0, R0,c9,c1, 1
CODE:10000068                 MOV             R1, #0x12
CODE:1000006C                 ORR             R0, R1, #0x100000
CODE:10000070                 MCR             p15, 0, R0,c9,c1, 0
CODE:10000074                 MRC             p15, 0, R0,c1,c0, 0
CODE:10000078                 ORR             R0, R0, #0x50000
CODE:1000007C                 MCR             p15, 0, R0,c1,c0, 0
CODE:10000080                 LDR             R0, =0x5200F010
CODE:10000084                 LDR             R1, [R0]
CODE:10000088                 ORR             R1, R1, #0xE
CODE:1000008C                 STR             R1, [R0]
CODE:10000090                 LDR             R12, =sub_10000140
CODE:10000094                 BX              R12     ; sub_10000140

The code in Reset_Handler performs the very basic hw init then jumps to the code which prepares the rest of the environment (copies code and data to its final location then jumps to it).

  • Thanks! What have you used to disassembly it? May 17, 2021 at 12:30
  • 1
    @AndreaOlla IDA obviously. P.S. I renamed the handlers manually.
    – Igor Skochinsky
    May 17, 2021 at 12:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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