When working with embedded Linux systems, in ARM-based boards, sometimes you need to determine whether a binary was compiled with ARM or THUMB2 instruction sets. This is a quick reference guide for checking this without relying on heavy tools like readelf or objdump.
The Core Concept
ARM uses a clever trick to distinguish between ARM and THUMB mode: the least significant bit (LSB) of the entry point address. If it’s odd (LSB = 1), the binary uses THUMB. If it’s even (LSB = 0), it uses ARM. This is because THUMB instructions are 2-byte aligned, while ARM instructions are 4-byte aligned.
Quick Decision Tree
- Entry point is odd? → THUMB2 mode
- Entry point is even? → ARM mode
Three Methods to Check
… depending on the tools you have in system.
Method 1: Using od (Octal Dump)
check_with_od() {
local file="$1"
echo "Verifying: $(basename "$file")"
# Show first bytes
od -t x1 -N 32 "$file" | head -3
# Extract entry point using od
entry=$(od -t x4 -j 24 -N 4 -A n "$file" | tr -d ' ')
entry_dec=$((0x$entry))
echo "Entry point: 0x$entry"
[ $((entry_dec % 2)) -eq 1 ] && echo "THUMB" || echo "ARM"
}
How it works:
od -t x4 -j 24 -N 4reads 4 bytes starting at offset 24 (the entry point field in the ELF header)- The modulo check (
% 2) determines if the address is odd or even
Example output (THUMB2 binary):
root@nxp-imx6qp-sdb:~# check_with_od /usr/libexec/wpe-webkit-2.0/WPEWebProcess
Verifying: WPEWebProcess
0000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
0000020 03 00 28 00 01 00 00 00 b1 04 00 00 34 00 00 00
0000040
Entry point: 0x000004b1
THUMB
Method 2: Using dd and od
check_with_dd() {
local file="$1"
echo "Verifying: $(basename "$file")"
# Extract entry point (4 bytes, offset 24)
entry_hex=$(dd if="$file" skip=24 count=4 bs=1 2>/dev/null | od -t x4 -A n | tr -d ' ')
if [ ! -z "$entry_hex" ]; then
entry_dec=$((0x$entry_hex))
echo "Entry point: 0x$entry_hex ($entry_dec)"
if [ $((entry_dec % 2)) -eq 1 ]; then
echo "Result: THUMB"
else
echo "Result: ARM"
fi
fi
}
How it works:
ddextracts raw bytes from the binaryskip=24positions to the entry point offsetcount=4 bs=1reads exactly 4 bytes- Pipes to
odfor hex formatting
Example output (THUMB2 binary):
root@nxp-imx6qp-sdb:~# check_with_dd /usr/libexec/wpe-webkit-2.0/WPEWebProcess
Verifying: WPEWebProcess
Entry point: 0x000004b1 (1201)
Result: THUMB
Example output (ARM binary):
root@nxp-imx6qp-sdb:~# check_with_dd /usr/libexec/wpe-webkit-2.0/WPEWebProcess
Verifying: WPEWebProcess
Entry point: 0x000004b0 (1200)
Result: ARM
Method 3: Using hexdump (Most Readable)
check_entry_hexdump() {
local file="$1"
echo "Verifying: $file"
# Show header ELF (first 64 bytes)
hexdump -C "$file" | head -4
# entry point (offset 0x18, 4 bytes)
echo -n "Entry point: "
hexdump -s 24 -n 4 -e '1/4 "0x%08x" "\n"' "$file" 2>/dev/null
# ARM vs Thumb
entry=$(hexdump -s 24 -n 4 -e '1/4 "%u" "\n"' "$file" 2>/dev/null)
if [ $((entry % 2)) -eq 1 ]; then
echo "Result: THUMB (entry point odd)"
else
echo "Result: ARM (entry point even)"
fi
}
How it works:
hexdump -Cprovides the most human-readable output-s 24seeks to offset 24 (entry point)-n 4limits to 4 bytes-e '1/4 "0x%08x"'formats as a 32-bit hex value
Example output (THUMB2 binary):
root@nxp-imx6qp-sdb:~# check_entry_hexdump /usr/libexec/wpe-webkit-2.0/WPEWebProcess
Verifying: /usr/libexec/wpe-webkit-2.0/WPEWebProcess
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 03 00 28 00 01 00 00 00 b1 04 00 00 34 00 00 00 |..(.........4...|
00000020 4c 11 00 00 00 04 00 05 34 00 20 00 09 00 28 00 |L.......4. ...(.|
00000030 1a 00 19 00 01 00 00 70 b8 05 00 00 b8 05 00 00 |.......p........|
Entry point: 0x000004b1
Result: THUMB (entry point impar)
Example output (ARM binary):
root@nxp-imx6qp-sdb:~# check_entry_hexdump /usr/libexec/wpe-webkit-2.0/WPEWebProcess
Verifying: /usr/libexec/wpe-webkit-2.0/WPEWebProcess
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 03 00 28 00 01 00 00 00 b0 04 00 00 34 00 00 00 |..(.........4...|
00000020 4c 11 00 00 00 04 00 05 34 00 20 00 09 00 28 00 |L.......4. ...(.|
00000030 1a 00 19 00 01 00 00 70 24 06 00 00 24 06 00 00 |.......p$...$...|
Entry point: 0x000004b0
Result: ARM (entry point par)
Example from libc:
root@nxp-imx6qp-sdb:~# check_entry_hexdump /usr/lib/libc.so.6
Verifying: /usr/lib/libc.so.6
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 03 00 28 00 01 00 00 00 39 f4 01 00 34 00 00 00 |..(.....9...4...|
00000020 8c 17 10 00 00 04 00 05 34 00 20 00 0a 00 28 00 |........4. ...(.|
00000030 3a 00 39 00 01 00 00 70 c8 c2 0f 00 c8 c2 0f 00 |:.9....p........|
Entry point: 0x0001f439
Result: THUMB (entry point impar)
Real-World Comparison: THUMB2 vs ARM
Standard Scarthgap THUMB2 Image
Check CPU capabilities:
root@nxp-imx6qp-sdb:~# cat /proc/cpuinfo | grep -i 'model\|features'
model name : ARMv7 Processor rev 10 (v7l)
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
model name : ARMv7 Processor rev 10 (v7l)
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
Check binaries:
root@nxp-imx6qp-sdb:~# check_with_od /usr/libexec/wpe-webkit-2.0/WPEWebProcess
Verifying: WPEWebProcess
0000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
0000020 03 00 28 00 01 00 00 00 b1 04 00 00 34 00 00 00
0000040
Entry point: 0x000004b1
THUMB
root@nxp-imx6qp-sdb:~# check_with_dd /usr/libexec/wpe-webkit-2.0/WPEWebProcess
Verifying: WPEWebProcess
Entry point: 0x000004b1 (1201)
Result: THUMB
root@nxp-imx6qp-sdb:~# check_entry_hexdump /usr/lib/libc.so.6
Verifying: /usr/lib/libc.so.6
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 03 00 28 00 01 00 00 00 39 f4 01 00 34 00 00 00 |..(.....9..4...|
00000020 8c 17 10 00 00 04 00 05 34 00 20 00 0a 00 28 00 |........4. ...(.|
00000030 3a 00 39 00 01 00 00 70 c8 c2 0f 00 c8 c2 0f 00 |:.9....p........|
Entry point: 0x0001f439
Result: THUMB (entry point odd)
Disabling THUMB2 in Yocto
Add to local.conf:
ARM_INSTRUCTION_SET = "arm"
ARM_INSTRUCTION_SET:pn-wpewebkit:armv7a = "arm"
ARM_INSTRUCTION_SET:pn-wpewebkit:armv7r = "arm"
ARM_INSTRUCTION_SET:pn-wpewebkit:armv7m = "arm"
ARM_INSTRUCTION_SET:pn-wpewebkit:armv7ve = "arm"
ARM_INSTRUCTION_SET:pn-wpewebkit = "arm"
TUNE_FEATURES:remove = "thumb"
Verification After Disabling THUMB2
CPU capabilities remain the same (CPU supports both):
root@nxp-imx6qp-sdb:~# cat /proc/cpuinfo | grep -i 'model\|features'
model name : ARMv7 Processor rev 10 (v7l)
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
model name : ARMv7 Processor rev 10 (v7l)
Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
But binaries now compile in ARM mode:
root@nxp-imx6qp-sdb:~# check_entry_hexdump /usr/libexec/wpe-webkit-2.0/WPEWebProcess
Verifying: /usr/libexec/wpe-webkit-2.0/WPEWebProcess
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 03 00 28 00 01 00 00 00 b0 04 00 00 34 00 00 00 |..(.........4...|
00000020 4c 11 00 00 00 04 00 05 34 00 20 00 09 00 28 00 |L.......4. ...(.|
00000030 1a 00 19 00 01 00 00 70 24 06 00 00 24 06 00 00 |.......p$...$...|
Entry point: 0x000004b0
Result: ARM (entry point even)
root@nxp-imx6qp-sdb:~# check_with_dd /usr/libexec/wpe-webkit-2.0/WPEWebProcess
Verifying: WPEWebProcess
Entry point: 0x000004b0 (1200)
Result: ARM
root@nxp-imx6qp-sdb:~# check_with_od /usr/libexec/wpe-webkit-2.0/WPEWebProcess
Verifying: WPEWebProcess
0000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
0000020 03 00 28 00 01 00 00 00 b0 04 00 00 34 00 00 00
0000040
Entry point: 0x000004b0
ARM
root@nxp-imx6qp-sdb:~# check_entry_hexdump /usr/lib/libc.so.6
Verifying: /usr/lib/libc.so.6
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 03 00 28 00 01 00 00 00 1c f7 01 00 34 00 00 00 |..(.....4...|
00000020 8c c7 15 00 00 04 00 05 34 00 20 00 0a 00 28 00 |........4. ...(.|
00000030 3a 00 39 00 01 00 00 70 64 76 15 00 64 76 15 00 |:.9....pdv..dv..|
Entry point: 0x0001f71c
Result: ARM (entry point even)
Notice the entry point changed from 0x1f439 (odd) to 0x1f71c (even).
…
That’s it. Bookmark this for the next time you’re debugging embedded Linux builds!




Leave a comment