CHDK Wiki
(Some documentation for capdis)
Tag: sourceedit
 
(Move capstone documentation to main Digic 6 page)
 
(13 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
=Introduction=
 
=Introduction=
capdis (short for CAPstone DISassembler) is disassembly tool based on the [http://www.capstone-engine.org/ capstone library], with features specifically supporting CHDK development. It is primarily intended for thumb2 / Digic 6 firmware, but can also be used on earlier ARM firmware or arbitrary ARM or thumb2 code.
+
capdis (short for CAPstone DISassembler) is a disassembly tool based on the [http://www.capstone-engine.org/ capstone library], with features specifically supporting CHDK development. It is primarily intended for thumb2 / Digic 6 firmware, but can also be used on earlier ARM firmware or arbitrary ARM or thumb2 code.
   
 
The latest version is available in the CHDK tools directory.
 
The latest version is available in the CHDK tools directory.
Line 7: Line 7:
   
 
=Building=
 
=Building=
  +
See the CHDK capstone tools section of [[Digic 6 Porting]].
A patched version of capstone 3.0.4 is required. The patch and pre-built win32 library are available from https://app.box.com/s/sshu7dv0mebvnee6gvpsex46y2m18w51
 
 
NOTE: The bug is fixed in later versions of capstone, but other source adjustments are required to use them.
 
 
To build the CHDK capstone tools, the following should be set in your localbuildconf.inc
 
 
<source lang="make">
 
# Define this to enable building of tools using the capstone library (http://www.capstone-engine.org/)
 
# Required to rebuild stubs for thumb2 / digic 6 firmware
 
OPT_CAPSTONE_TOOLS=1
 
 
# Set the following if capstone includes are not in the default search path
 
CAPSTONE_TOOLS_INC=-I/path/to/capstone/include
 
 
# Set the following to the options required to link to the capstone library.
 
# At a minimum, -lcapstone or similar is required. If the library is not
 
# on the default search path, -L/path/to/capstone is also required
 
CAPSTONE_TOOLS_LINK=-L/path/to/capstone -lcapstone
 
</source>
 
 
Replace ''/path/to/capstone'' with the location where the capstone library is installed.
 
 
To build capdis, make extras or capdis (capdis.exe on windows) in the tools directory.
 
   
 
=Usage=
 
=Usage=
Line 36: Line 14:
 
Options are specified like -x=value with no spaces.
 
Options are specified like -x=value with no spaces.
   
To disassemble, you must specify
+
To disassemble, you must specify
 
* A start address, with -s=&lt;numeric address or known function name&gt; or -o=&lt;byte offset from file start&gt;
 
* A start address, with -s=&lt;numeric address or known function name&gt; or -o=&lt;byte offset from file start&gt;
 
** The lowest bit of the start address controls whether code is disassembled as ARM (LSB=0) or thumb (LSB=1). So to disassemble thumb2 code starting at 0xfc020000, you would use -s=0xfc020001
 
** The lowest bit of the start address controls whether code is disassembled as ARM (LSB=0) or thumb (LSB=1). So to disassemble thumb2 code starting at 0xfc020000, you would use -s=0xfc020001
Line 45: Line 23:
   
 
Other useful options
 
Other useful options
* The -s option allows CHDK "stubs" to be used to annotate known functions from stubs_entry.S, funcs_by_name.csv and stubs_entry_2.s. Running capdis from the root of your CHDK source, you would use something like -s=platform/g7x/sub/100d
+
* The -stubs option allows CHDK "stubs" to be used to annotate known functions from stubs_entry.S, funcs_by_name.csv and stubs_entry_2.s. Running capdis from the root of your CHDK source, you would use something like -stubs=platform/g7x/sub/100d
** Note that if stubs generation fails, the CHDK build process renames the stubs_entry.S file to stubs_entry.S.err. To allow it to be seen by capdis, you must rename it back to stubs_entry.S.
+
** Note that if stubs generation fails, the CHDK build process renames the stubs_entry.S file to stubs_entry.S.err. To allow it to be seen by capdis, you must rename it back to stubs_entry.S.
 
* The -f option can is used to control the output format. Use -f=chdk to generate code suitable for inline assembly in CHDK. Use -f=objdump to output something roughly similar to GNU objdump / [[User:Srsa 4c/GPL:stubs2disv7.pl|stubs2disv7.pl]]. If neither is specified, the default is similar to capstone standard disassembly.
 
* The -f option can is used to control the output format. Use -f=chdk to generate code suitable for inline assembly in CHDK. Use -f=objdump to output something roughly similar to GNU objdump / [[User:Srsa 4c/GPL:stubs2disv7.pl|stubs2disv7.pl]]. If neither is specified, the default is similar to capstone standard disassembly.
   
Line 63: Line 41:
 
THUMB_FW=1
 
THUMB_FW=1
 
PLATFORMOS=dryos
 
PLATFORMOS=dryos
PLATFORMOSVER=<DRYOS version number, doesn't have to be correct>
+
PLATFORMOSVER=<DRYOS version number, does not need to be correct>
 
ROMBASEADDR=<your ROM base address, 0xFC000000 on known Digic 6>
 
ROMBASEADDR=<your ROM base address, 0xFC000000 on known Digic 6>
 
</source>
 
</source>
Line 78: Line 56:
 
make PLATFORM=&lt;camera&gt; PLATFORMSUB=&lt;firmware&gt; rebuild-stubs
 
make PLATFORM=&lt;camera&gt; PLATFORMSUB=&lt;firmware&gt; rebuild-stubs
   
For a new port, this will fail because various functions are not found, but stubs_entry.S.err, funcs_by_name.csv etc should be created.
+
For a new port, this will fail because various functions are not found, but stubs_entry.S.err, funcs_by_name.csv etc should be created.
   
 
Rename stubs_entry.S.err to stubs_entry.S
 
Rename stubs_entry.S.err to stubs_entry.S
Line 93: Line 71:
 
tools/capdis platform/g9x/sub/101a/PRIMARY.BIN 0xfc000000 -stubs=platform/g9x/sub/101a -s=0xfc020001 -e=0xfc6572ac -f=objdump -d-const -d-addr -d-bin > platform/g9x/sub/101a/ROMCODE.DIS
 
tools/capdis platform/g9x/sub/101a/PRIMARY.BIN 0xfc000000 -stubs=platform/g9x/sub/101a -s=0xfc020001 -e=0xfc6572ac -f=objdump -d-const -d-addr -d-bin > platform/g9x/sub/101a/ROMCODE.DIS
   
'''Note''': disassembling a full ROM can take a long time, (up to a few hours on reasonably modern system), and the resulting file can be larger than 100MB
+
'''Note''': Disassembling a full ROM can take several minutes on a reasonably modern system, and the resulting file can be larger than 100MB
   
 
=Disassembling code for CHDK source=
 
=Disassembling code for CHDK source=

Latest revision as of 20:24, 25 May 2019

Introduction

capdis (short for CAPstone DISassembler) is a disassembly tool based on the capstone library, with features specifically supporting CHDK development. It is primarily intended for thumb2 / Digic 6 firmware, but can also be used on earlier ARM firmware or arbitrary ARM or thumb2 code.

The latest version is available in the CHDK tools directory.

Development thread

Building

See the CHDK capstone tools section of Digic 6 Porting.

Usage

capdis is a command line tool which disassembles a specified address range, with output in formats suitable for general reverse engineering or use in CHDK code. If invoked without any options, it prints a brief summary.

Options are specified like -x=value with no spaces.

To disassemble, you must specify

  • A start address, with -s=<numeric address or known function name> or -o=<byte offset from file start>
    • The lowest bit of the start address controls whether code is disassembled as ARM (LSB=0) or thumb (LSB=1). So to disassemble thumb2 code starting at 0xfc020000, you would use -s=0xfc020001
    • If RAM code regions are recognized (see stubs_entry.S generated by finsig_thumb2) you can disassemble code in those regions by passing addresses directly, e.g. -s=0x010e1001 to disassemble the start of RAM kernel code.
  • An end address or instruction count, with -e=<address> or -c=<count>
  • A file to dissemble, typically the PRIMARY.BIN for the camera you are working on.
  • The firmware start address (CHDK ROMBASEADDR)

Other useful options

  • The -stubs option allows CHDK "stubs" to be used to annotate known functions from stubs_entry.S, funcs_by_name.csv and stubs_entry_2.s. Running capdis from the root of your CHDK source, you would use something like -stubs=platform/g7x/sub/100d
    • Note that if stubs generation fails, the CHDK build process renames the stubs_entry.S file to stubs_entry.S.err. To allow it to be seen by capdis, you must rename it back to stubs_entry.S.
  • The -f option can is used to control the output format. Use -f=chdk to generate code suitable for inline assembly in CHDK. Use -f=objdump to output something roughly similar to GNU objdump / stubs2disv7.pl. If neither is specified, the default is similar to capstone standard disassembly.

Disassembling a full firmware dump

To generate files suitable for reverse engineering, you can use the following procedure.

In the text below <camera> below refers to your platform name, e.g. g7x. <firmware> refers to your firmware version, e.g. 100d

Create an initial tree to generate stubs

If you started your port by copying an existing port, you can skip this step, but you may need to adjust some of the values in your copied tree.

Set up a minimal platform tree, with platform/<camera> platform/<camera>/sub/<firmware>

Create platform/<camera>/makefile.inc, with at least the following values

THUMB_FW=1
PLATFORMOS=dryos
PLATFORMOSVER=<DRYOS version number, does not need to be correct>
ROMBASEADDR=<your ROM base address, 0xFC000000 on known Digic 6>

Create platform/<camera>/sub/<firmware>/Makefile containing at least

include ../../../makefile_sub.inc

Create platform/<camera>/sub/<firmware>/makefile.inc (can be empty)

Generate stubs

Run

make PLATFORM=<camera> PLATFORMSUB=<firmware> rebuild-stubs

For a new port, this will fail because various functions are not found, but stubs_entry.S.err, funcs_by_name.csv etc should be created.

Rename stubs_entry.S.err to stubs_entry.S

Disassemble code regions

Known digic 6 firmwares have several code regions: The bootloader, the main ROM code and one or two regions which are copied to RAM (or ITCM) on startup. If your firmware is similar to known firmwares, these (except the bootloader) will be detected by finsig_thumb2, and noted in comments.

To disassemble RAM code, look in the "Detected address ranges section" for items listed as RAM code, and use the address range for start and end, like

tools/capdis platform/g9x/sub/101a/PRIMARY.BIN 0xfc000000 -stubs=platform/g9x/sub/101a -s=0x010e1001 -e=0x010fbd18 -f=objdump -d-const -d-addr -d-bin > platform/g9x/sub/101a/RAMCODE.DIS

To dissemble main ROM code, use the "Main firmware start" address as the start (with the thumb it set) and the address from the DEF(ctypes,...) line as the end, like

tools/capdis platform/g9x/sub/101a/PRIMARY.BIN 0xfc000000 -stubs=platform/g9x/sub/101a -s=0xfc020001 -e=0xfc6572ac -f=objdump -d-const -d-addr -d-bin > platform/g9x/sub/101a/ROMCODE.DIS

Note: Disassembling a full ROM can take several minutes on a reasonably modern system, and the resulting file can be larger than 100MB

Disassembling code for CHDK source

In CHDK, code for startup and various task hooks uses inline assembly generated from firmware code.

To generate this code, you can use capdis like

tools/capdis ../dumps/g7x/sub/100d/PRIMARY.BIN 0xFC000000 -stubs=platform/g7x/sub/100d -f=chdk -s=0xfc064301 -c=60

Wrapping this in a shell script can be more convenient, something like

discam.sh:

#!/bin/bash
cam=$1
shift
sub=$1
shift
capdis platform/$cam/sub/$sub/PRIMARY.BIN 0xfc000000 -stubs=platform/$cam/sub/$sub $*