Using mips-linux-objdump for disassembly of raw binary

We’ve got the object code of a MIPS32 kernel image, obtained from a raw flash dump and we want to disassemble it.

However, objdump can’t directly disassemble the raw binary code.

If “dump.bin” is the flash dump binary file..

$ mips-linux-objdump -D dump.bin
  mips-linux-objdump: dump.bin: File format not recognized

To overcome this we create an empty C source file

$ touch holder.c

.. we compile this empty file

$ mips-linux-gcc -c -o holder.o holder.c

.. and add the binary as a raw section

$ mips-linux-objcopy --add-section raw=dump.bin holder.o

.. and we remove the “.comment” section

$ mips-linux-objcopy --remove-section .comment holder.o

.. we can check the ELF headers with..

$ mips-linux-objdump -x holder.o

holder.o:     file format elf32-tradbigmips
architecture: mips:isa32, flags 0x00000010:
start address 0x00000000
private flags = 50001006: [abi=O32] [mips32] [not 32bitmode] [PIC] [CPIC]

Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000000  00000000  00000000  00000040  2**4
  1 .data         00000000  00000000  00000000  00000040  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00000000  00000000  00000040  2**4
  3 .reginfo      00000018  00000000  00000000  00000040  2**2
  4 .pdr          00000000  00000000  00000000  00000058  2**2
                  CONTENTS, READONLY
  5 .mdebug.abi32 00000000  00000000  00000000  00000058  2**0
                  CONTENTS, READONLY
  6 raw           002516e4  00000000  00000000  00000058  2**0
                  CONTENTS, READONLY
00000000 l    df *ABS*	00000000 holder.c
00000000 l    d  .text	00000000 .text
00000000 l    d  .data	00000000 .data
00000000 l    d  .bss	00000000 .bss
00000000 l    d  .mdebug.abi32	00000000 .mdebug.abi32
00000000 l    d  .reginfo	00000000 .reginfo
00000000 l    d  .pdr	00000000 .pdr
00000000 l    d  raw	00000000 raw

We can now disassemble our raw code.

The dump below is the start of the kernel image. We can adjust to the correct memory addresses using the load address that we found in the header of the LZMA-compressed kernel image.

Load address: 0x8001 0000 (and kernel entry point: 0x8024 B000)

$ mips-linux-objdump -D  --adjust-vma=0x80010000 holder.o

holder.o:     file format elf32-tradbigmips

Disassembly of section .reginfo:

80010000 :
Disassembly of section raw:

80010000 :
80010400:	3c028023 	lui	v0,0x8023
80010404:	3c068023 	lui	a2,0x8023
80010408:	24455450 	addiu	a1,v0,21584
8001040c:	24c653c0 	addiu	a2,a2,21440
80010410:	0800557e 	j	0x800155f8
80010414:	ac445450 	sw	a0,21584(v0)
80010418:	27bdffe8 	addiu	sp,sp,-24
8001041c:	afbf0014 	sw	ra,20(sp)
80010420:	0c006a46 	jal	0x8001a918
80010424:	afb00010 	sw	s0,16(sp)
80010428:	3c048020 	lui	a0,0x8020
8001042c:	24030001 	li	v1,1
80010430:	3c028026 	lui	v0,0x8026
80010434:	24846910 	addiu	a0,a0,26896
80010438:	24050002 	li	a1,2
8001043c:	00003021 	move	a2,zero
80010440:	0c01b947 	jal	0x8006e51c
80010444:	ac432000 	sw	v1,8192(v0)
80010448:	04410003 	bgez	v0,0x80010458
8001044c:	3c048020 	lui	a0,0x8020
80010450:	0c00b60d 	jal	0x8002d834
80010454:	24846920 	addiu	a0,a0,26912
80010458:	0c01efcb 	jal	0x8007bf2c
8001045c:	00002021 	move	a0,zero
80010460:	3c108026 	lui	s0,0x8026
80010464:	0c01efcb 	jal	0x8007bf2c
80010468:	00002021 	move	a0,zero
8001046c:	8e042018 	lw	a0,8216(s0)
80010470:	10800007 	beqz	a0,0x80010490
80010474:	00000000 	nop
80010478:	0c004100 	jal	0x80010400

We want to find and disassemble the proprietary “bhal” code that Huawei has compiled into the kernel.

We discovered the existence of the ‘bhal’ code from the kernel bootlog:

$ cat bootlog | grep bhal

  bhal: bhal_init entry

Using strings we find the following references to ‘bhal’ in the kernel:

$ /usr/bin/strings -tx dump.bin | grep -i bhal

 1d6cc0 bhalplatsetGpio
 205618 bhal
 205620 bhal_init(major %d): fail to register device.
 205650 bhal: bhal_init entry
 2056a4 BhalRelease()
 21be0c g_ulBhalKeyScanMode
 21be8c bhalWriteFlash
 21bec0 bhalGetFlashSize
 21bed4 bhalEraseFlash
 21bee4 bhalReadFlash
 21bef4 bhalWakeupMonitorTask
 21bf0c bhalReleaseMacAddress
 21bf24 bhalGetMacAddress
 21bf38 bhalGetBaseMacAddress
 21bf50 bhalGetTagByFlashOffset
 21bfc0 bhalGetTagFromPartition

Those are file offsets, so if we add the offset to the load address for the kernel (0x8001 0000) then we get the memory addresses of the strings after the kernel has been loaded into RAM.

801e6cc0 bhalplatsetGpio
80215618 bhal
80215620 bhal_init(major %d): fail to register device.
80215650 bhal: bhal_init entry
802156a4 BhalRelease()
8022be0c g_ulBhalKeyScanMode
8022be8c bhalWriteFlash
8022bec0 bhalGetFlashSize
8022bed4 bhalEraseFlash
8022bee4 bhalReadFlash
8022bef4 bhalWakeupMonitorTask
8022bf0c bhalReleaseMacAddress
8022bf24 bhalGetMacAddress
8022bf38 bhalGetBaseMacAddress
8022bf50 bhalGetTagByFlashOffset
8022bfc0 bhalGetTagFromPartition

The most useful string for determining the beginning of the compiled-in bhal kernel module is probably “bhal: bhal_init entry”.

The code that invokes printk() on that string (“bhal: bhal_init entry”) must be very close to the beginning of the bhal module.

$ cat /proc/kallsyms|grep -i bhal

8011a460 T bhalXtoi
8011a4e4 T bhalJudgeIsBigEnd
8011a4fc T bhalCpuToEndian32
8011a54c T bhalMonitorPollHook
8011a5ac T bhalGetSdramSize
8011a72c t bhalOpen
8011a784 T bhalSavePppSession
8011a7b0 T bhalGetBaseMacAddress
8011a8f4 T bhalGetPppSession
8011a958 T bhalReleaseMacAddress
8011aa04 T bhalGetMacAddress
8011ac3c T bhalEraseFlash
8011ac7c T bhalWriteFlash
8011acc8 T bhalReadFlash
8011ae14 t bhalRelease
8011ae40 t bhalPollResetKey
8011ae48 T bhalGetFlashSize
8011ae50 T bhalHardReboot
8011ae58 T bhalSoftReboot
8011ae60 T bhalWakeupMonitorTask
8011b04c t bhalIoctl
8011c2a0 T bhalplatGetChipParam
8011c2e4 T bhalplatGetBoardAllId
8011c2ec T bhalplatGetBoardManufacturer
8011c320 T bhalplatHardReboot
8011c350 T bhalplatEnableUart1
8011c3a4 T bhalplatInitBoard
8011c400 T bhalplatsetGpio
8011c488 T bhalplatSoftReboot
8011c4c0 T bhalGetTagByFlashOffset
8011c550 T bhalGetTagFromPartition
8011c5e0 T bhalplatGetResetKeyStatus
8011c66c T bhalplatPollResetKey
8011c898 T bhalplatGetBoardVersion
8011c8cc T bhalplatGetBoardPcbVersion
8025a118 t bhalInit
8011aa04 u bhalGetMacAddress    [bcm_enet]
8011ae60 u bhalWakeupMonitorTask    [bcm_enet]
8011ae60 u bhalWakeupMonitorTask    [adsldd]

3 thoughts on “Using mips-linux-objdump for disassembly of raw binary

  1. How to uncap it, there is no active download button within Maintenance/ Configuration to download config file toedit and upload back ?

  2. Alternatively, just tell objdump that it’s a raw binary file by adding the ‘-b binary’ option.

    The ‘-m’ option is also useful if you need to specify a specific architecture.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s