Inspect and get binary from ELF file on macOS
Asked Answered
W

1

4

I have a ELF file and I want to get a hex or bin file of my code from it. In the terminal, if a do a file main, which is my file, it shows:

main: ELF 32-bit LSB executable, UCB RISC-V, version 1 (SYSV), statically linked, not stripped

As I learned, objdump on macOS is not working and with otool -l main I get the following error:

llvm-objdump: 'main': Object is not a Mach-O file type.

The ELF file was created using the command:

riscv-none-gcc/8.2.0-2.1-20190425-1021/bin/riscv-none-embed-gcc --specs=nosys.specs main.c -o main

So is there a way to do it?

Thanks a lot

Wilda answered 13/9, 2019 at 13:38 Comment(2)
Instead of otool try syntax compatible jtool written by Jonathan Levin, it has ELF support and runs on macOS.Tripalmitin
@Tripalmitin Thanks, i tried jtool/jtool -l main but that threw me Unable to recognize this file - 464C457FWilda
C
14

For creating "raw binary files" the program objcopy can be used, as described here:

objcopy -O binary foo.elf foo.bin

The program objcopy is part of the MacPorts package x86_64-elf-binutils, and can be used as follows:

/opt/local/bin/x86_64-elf-objcopy -O binary foo.elf foo.bin

where foo.elf is an ELF file compiled on (or cross-compiled for) an x86_64 Linux. The MacPorts package x86_64-elf-binutils can be installed as follows:

port install x86_64-elf-binutils

The program objcopy is part of binutils. For Mach-O, it can be installed on macOS via the package binutils of MacPorts, as follows:

port install binutils

The MacPorts binutils package installs gobjcopy.

Versions of binutils on macOS for cross-development for other target systems, too, are available via MacPorts.

This post is motivated also by MacOSX: which dynamic libraries linked by binary?, and is intended to be also informational.

Executables can be:

ldd

ldd is a script in Linux that wraps ld. It is described as

print shared object dependencies

The GNU ld is unavailable on macOS. More fundamentally, that ldd calls ld means that its operation is non-static, in contrast to tools like readelf, objdump, and nm.

In that sense, even if certain information is obtainable using tools other than ldd, the results are not equivalent, because the other tools do not attempt to load the binary. Moreover, attempting to load a binary requires being on a Linux, so ldd is genuinely a Linux tool that cannot be emulated exactly by a program on macOS. A relevant description. There does exist a pure-Python implementation that approximates ldd without loading binaries the way that ld does: lddcollect. Using lddcollect is possible on a Linux system, where the required libraries are present.

One reason to not use ldd is security: inspecting executables without executing them.

ldd is an initialism for "List Dynamic Dependencies".

ldd appears to be a bash script that is part of glibc, with source code at: https://sourceware.org/git/?p=glibc.git;a=blob;f=elf/ldd.bash.in;h=ba736464ac5e4a9390b1b6a39595035238250232;hb=271ec55d0ae795f03d92e3aa61bff69a31a19e3a

objdump

objdump shows information about object files, and can disassemble them. It is part of binutils.

Programs that are called objdump on macOS:

  • /opt/local/bin/gobjdump by the MacPorts package binutils
  • /usr/bin/objdump by macOS (part of package com.apple.pkg.Essentials), which is described as the

    llvm object file dumper

The manual of ldd suggests calling objdump as an alternative, as follows:

objdump -p /path/to/program | grep NEEDED

Relevant: https://superuser.com/questions/206547/how-can-i-install-objdump-on-mac-os-x

readelf

readelf displays information about ELF files by reading them (static, not loading them). It is part of binutils. It does not disassemble files, like objdump can.

Variants available on macOS:

  • /opt/local/bin/greadelf from the MacPorts package binutils
  • /opt/local/bin/elftc-readelf from the MacPorts package elftoolchain

Example usage:

readelf -s elf_file

nm

  • /usr/bin/nm by macOS (part of package com.apple.pkg.Essentials)
  • /opt/local/bin/nm by the MacPorts package cctools, which is a symbolic link: /opt/local/bin/nm -> llvm-nm-mp-10
  • /opt/local/bin/nm-classic by the MacPorts package cctools
  • /opt/local/bin/elftc-nm by the MacPorts package elftoolchain
  • /opt/local/bin/gnm by the MacPorts package binutils

Apparently, both /usr/bin/nm and /opt/local/bin/nm are versions of the

llvm symbol table dumper and do work with ELF files.

otool (and variants)

otool is the the disassembler for MacOS's Mach-O format.

Variants of otool available on macOS:

  • /usr/bin/otool by macOS (part of package com.apple.pkg.Essentials)
  • /opt/local/bin/otool by the MacPorts package cctools, which links to /opt/local/bin/llvm-otool by the MacPorts package cctools, which is described as:

    the otool-compatible command line parser for llvm-objdump

  • /opt/local/bin/otool-classic by the MacPorts package cctools

More details:

> which -a otool
/opt/local/bin/otool
/usr/bin/otool
> ls -lsa /opt/local/bin/otool
... /opt/local/bin/otool -> llvm-otool
> port provides /opt/local/bin/otool
/opt/local/bin/otool is provided by: cctools
> which -a llvm-otool
/opt/local/bin/llvm-otool
> port provides /opt/local/bin/llvm-otool
/opt/local/bin/llvm-otool is provided by: cctools
> ls -lsa /usr/bin/otool
... /usr/bin/otool
> pkgutil --file-info /usr/bin/otool
volume: /
path: /usr/bin/otool

pkgid: com.apple.pkg.Essentials
...

The MacPorts package cctools installs also /opt/local/bin/otool-classic, which, as said in its documentation, is obsolete.

elfdump

elfdump is available on macOS via the MacPorts package elftoolchain, and installed as the binary /opt/local/bin/elftc-elfdump.

strings

The program strings can be useful for inspecting the symbols contained in an ELF file. It is a more general tool, not designed specifically for ELF files, but usable nonetheless.

Variants of strings on macOS:

  • /usr/bin/strings by macOS (part of package com.apple.pkg.Essentials)
  • /opt/local/bin/strings from the MacPorts package cctools
  • /opt/local/bin/elftc-strings from the MacPorts package elftoolchain
  • /opt/local/bin/gstrings from the MacPorts package binutils

Example usage (piping to ag):

strings some_elf_file | ag GLIBC

elftc-strings appears to have fewer options and give fewer results than the other strings implementations (which differ with each other, but seem to print similar results).

elftoolchain

Available via MacPorts, elftoolchain is a BSD-licensed library of tools like those in binutils. Tools from that collection that are relevant to analyzing ELF files:

  • /opt/local/bin/elftc-elfdump
  • /opt/local/bin/elftc-nm
  • /opt/local/bin/elftc-readelf
  • /opt/local/bin/elftc-strings

There are also plans for implementing objdump.

Confirming that a binary is from MacPorts

To find out whether a given file is part of MacPorts:

> port provides /opt/local/bin/otool
/opt/local/bin/otool is provided by: cctools

Discussed in this answer.

Confirming that a binary is from macOS

Also useful for finding out how each of the tools discussed above was installed is pkgutil:

pkgutil --file-info /usr/bin/objdump

This can be useful to confirm that a binary was part of macOS itself, and not installed by other means.

Confirming that an executable is an ELF

This text was motivated when I wanted to analyze an executable with the following details:

> file filename
ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=..., for GNU/Linux 3.2.0, not stripped

As for other tools, there are multiple options for file on macOS:

  • /usr/bin/file by macOS (part of package com.apple.pkg.Essentials)
  • /opt/local/bin/file by the MacPorts package file

Other tools

Apparently, on some operating systems there are also elftools available.

For analyzing files for specific architectures, there are MacPorts packages like arm-elf-binutils.

DWARF

There is also DWARF and dwarftool, as well as dwarfdump (part of XCode).

Miscellanea

Conglomerate answered 3/6, 2021 at 9:30 Comment(1)
What an AMAZING answer! I'm going to bookmark it actually. Some are especially useful like checking if they're part of macOS by default. This is very useful to me! Have a +1! It might be useful to point out though that with Apple silicon chip you cannot compile ELF - at least to my knowledge. As well Apple makes it very hard nowadays to compile 32-bit binaries (incredibly annoying bu there it is). Anyway great answer - thanks!Zorina

© 2022 - 2024 — McMap. All rights reserved.