Inspect and get binary from ELF file on MAC - macos

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 MAC 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

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:
ELF on Linux
Mach-O on macOS
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
Relevant: What is the difference between ldd and objdump?
Relevant: cross compiler ldd
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
binutils can analyze Mach-O on Linux: https://stackoverflow.com/a/8714142/1959808
darling can be used on Linux to run
macOS software (Mach-O, dyld), it is analogous to wine

Related

ldd -r equivalent on macOS

I am trying to make my software available on macOS and in my toolchain I use ldd -r MyModel.so to verify is everything went well but I can't really find anything conclusive on macOS that would have the same behaviour.
otool or nm seems the two directions to go but I am not sure how to be sure what options would behave the same. Or is there another tool ?
ldd uses ld to load executable files, and recursively loads
dynamically-linked libraries. So using ldd requires being on the target system
(e.g., Linux). Thus, ldd cannot be used for ELF files on macOS.
Assuming that the question is about analyzing Mach-O files on macOS, I do not know of any tool that works for Mach-O files as ldd does for ELF files.
Both otool and nm perform a static analysis.
A possibility is:
otool -L /usr/bin/true
Relevant:
MacOSX: which dynamic libraries linked by binary?
Inspect and get binary from ELF file on MAC

How to obtain readelf and objdump binaries for OS X?

From where can I download readelf and objdump binaries for OS X? I'm trying to get the list of exported functions from an NDK .so library and neither nm nor otool worked for me. I've read that the library might be in elf format and that readelf or objdump might work.
I was able to find the source code for those utilities but I would like the binaries. Surely they've been compiled by someone already.
There was a lot of information in this SO article: How do I list the symbols in a .so file It is there that readelf and objdump are recommended when nm did not work for me.
These tools are available as part of the NDK. You'll find them in the toolchains subdirectory within the NDK, e.g. android-ndk-r10e/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-objdump. There's also a version of the nm utility there which will understand your ELF .so files, arm-linux-androideabi-nm in the same path as above.

Haskell package missing c library

I'm having trouble building the hmatrix library on OS X Lion. Looking at the .cabal file, it requires the gsl library, so I installed it with macports. The .a files are in /opt/local/lib and the .h files are in /opt/local/include/gsl
As suggested here I changed the built-type from Custom to Simple. (without that change I get a similar error).
When I use cabal configure I get the following output:
* Missing C library: gsl
This problem can usually be solved by installing the system package that
provides this library (you may need the "-dev" version). If the library is
already installed but in a non-standard location then you can use the flags
--extra-include-dirs= and --extra-lib-dirs= to specify where it is.
So I tried cabal --extra-include-dirs=/opt/local/include --extra-lib-dirs=/opt/local/lib configure, but I still get the same error. I can compile and link a c program that includes gsl. What files is cabal looking for? If I have the right files, how do I tell it how to find them?
libgsl.a is a universal binary:
$ file /opt/local/lib/libgsl.a
/opt/local/lib/libgsl.a: Mach-O universal binary with 2 architectures
/opt/local/lib/libgsl.a (for architecture x86_64): current ar archive random library
/opt/local/lib/libgsl.a (for architecture i386): current ar archive random library
ghc looks like it's 64-bit:
$ ghc --info
[("Project name","The Glorious Glasgow Haskell Compilation System")
,("GCC extra via C opts"," -fwrapv")
,("C compiler command","/usr/bin/llvm-gcc")
,("C compiler flags"," -m64 -fno-stack-protector -m64")
,("ar command","/usr/bin/ar")
,("ar flags","clqs")
,("ar supports at file","NO")
,("touch command","touch")
,("dllwrap command","/bin/false")
,("windres command","/bin/false")
,("perl command","/usr/bin/perl")
,("target os","OSDarwin")
,("target arch","ArchX86_64")
,("target word size","8")
,("target has GNU nonexec stack","False")
,("target has subsections via symbols","True")
,("Project version","7.4.2")
,("Booter version","7.4.2")
,("Stage","2")
,("Build platform","x86_64-apple-darwin")
,("Host platform","x86_64-apple-darwin")
,("Target platform","x86_64-apple-darwin")
,("Have interpreter","YES")
,("Object splitting supported","NO")
,("Have native code generator","YES")
,("Support SMP","YES")
,("Unregisterised","NO")
,("Tables next to code","YES")
,("RTS ways","l debug thr thr_debug thr_l thr_p dyn debug_dyn thr_dyn thr_debug_dyn")
,("Leading underscore","YES")
,("Debug on","False")
,("LibDir","/usr/local/Cellar/ghc/7.4.2/lib/ghc-7.4.2")
,("Global Package DB","/usr/local/Cellar/ghc/7.4.2/lib/ghc-7.4.2/package.conf.d")
,("Gcc Linker flags","[\"-m64\"]")
,("Ld Linker flags","[\"-arch\",\"x86_64\"]")
]
As an alternative to mac-ports you can use the nix package manager for mac. It does a pretty good job of taking care of the c dependancies for for the libraries available through it. In general I have been more happy with it then any other package manager on mac.
Unfortunately mac(darwin) unlike for linux does not have as many binaries available through nix so installing ghc often means waiting for it to compile.
The commands to install ghc and hmatrix after installation of nix are:
nix-env -iA nixpkgs-unstable.haskellPackages.ghc
nix-env -iA nixpkgs-unstable.haskellPackages.hmatrix
All of the needed dependencies will be taken care of for you.
I just tried it on my macbook pro and hmatrix seems to be working correctly in ghci after trying commands from the first few pages of the tutorial.
I'm not a mac person, but it really sounds like you haven't installed the "-dev" version. For a mac, I suspect you need to install gsl-devel in addition to gsl. If the problem persists, verify that you have libgsl0-dev on your library path.

What is the difference between /lib/i386-linux-gnu/libc.so.6, /lib/x86_64-linux-gnu/libc.so.6 and /usr/lib/x86_64-linux-gnu/libc.so?

I installed Matlab in my Linux Mint 14 Nadia (a uname -a shows: Linux Ideapad-Z570 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:31:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux) and when calling it from the command line I would get a: "/lib64/libc.so not found".
I followed the help on mathworks by making a link in /lib64 as:
ln -s /lib/x86_64-linux-gnu/libc.so.6 .
That solved the issue.
Now, if I do a locate of this library I get:
locate "libc.so"
/lib/i386-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libc.so.6
/usr/lib/x86_64-linux-gnu/libc.so
I will be compiling with gcc in this computer and I would like to have full 64bit compilations. What does exactly mean to have all these different libc.so libraries? which one will the gnu compiler be using? do I need to do anything different with gcc to compile for 64 bits?
I would also love to optimize as much as I can for my new i7 core!!!
/lib/i386-linux-gnu/libc.so.6
This is is 32-bit version of the library.
/lib/x86_64-linux-gnu/libc.so.6
This is the 64-bit version of the library.
Both are usually symbolic links to the actual library file, which will usually be named according to the glibc release number, for example libc-2.15.so
/usr/lib/x86_64-linux-gnu/libc.so
This is not a library, but a linker script file, which refers to the above symlinks.
Why do we need all these:
First, regardless of libc version installed, the linker will always search for libc.so, because the compiler driver will always pass to the linker the -lc options. The name libc stays the same and denotes to most recent version of the library.
The symlinks libc.so.6 are named after the soname of the library, which, more or less corresponds to the ABI version of the library. The executables, linked against libc.so in fact contain runtime dependencies on libc.so.6.
If we imagine the someday a grossly ABI incompatible libc is released, it's soname could be named libc.so.7, for example and this version coukld coexists with the older libc.so.6 version, thus executables linked against one or the other can coexist in the same system,
And finally, the name libc-2.15.so refers to the libc release, when you install a new libc package, the name will change to libc-2.16.so. Provided that it is binary compatible with the previous release, the libc.so.6 link will stay named that way and the existing executables will continue to work.
To find which one to use, you have to first find the order that ld (the linker) uses to find libraries, like so:
ld --verbose | grep SEARCH
For me it gave me this output:
SEARCH_DIR("/usr/x86_64-unknown-linux-gnu/lib64"); SEARCH_DIR("/usr/x86_64-unknown-linux-gnu/lib"); SEARCH_DIR("/usr/lib"); SEARCH_DIR("/usr/local/lib");
This means that on my computer, ld looks in these directories, in order:
/usr/x86_64-unknown-linux-gnu/lib64
/usr/x86_64-unknown-linux-gnu/lib
/usr/lib
/usr/local/lib
So if libc was in /usr/x86_64-unknown-linux-gnu/lib64, and libc was also in /usr/lib, it would use the /usr/x86_64-unknown-linux-gnu/lib64 version, because it was listed first.
The symlink you created will have no effect whatsoever on GCC. The 32-bit version is only used when you compile using the -m32 GCC flag. GCC will not attempt to generate 32-bit binaries unless you specifically tell it to (by using that flag.)

Linking with libtcmalloc ubuntu

I had installed the package libtcmalloc-minimal0
but when I try to compile my program with flag
-ltcmalloc-minimal0
I am getting error
/usr/bin/ld: cannot find -ltcmalloc_minimal0
I had checked /usr/lib and the library is there
More Info
dpkg gives following o/p
dpkg -L libtcmalloc-minimal0
/.
/usr
/usr/lib
/usr/lib/libtcmalloc_minimal.so.0.0.0
/usr/lib/libtcmalloc_minimal_debug.so.0.0.0
/usr/share
/usr/share/doc
/usr/share/doc/libtcmalloc-minimal0
/usr/share/doc/libtcmalloc-minimal0/TODO
/usr/share/doc/libtcmalloc-minimal0/AUTHORS
/usr/share/doc/libtcmalloc-minimal0/copyright
/usr/share/doc/libtcmalloc-minimal0/changelog.gz
/usr/share/doc/libtcmalloc-minimal0/README.gz
/usr/share/doc/libtcmalloc-minimal0/changelog.Debian.gz
/usr/lib/libtcmalloc_minimal.so.0
/usr/lib/libtcmalloc_minimal_debug.so.0
and I am compiling for 64 bit mode
and library is also 64 bit
file /usr/lib/libtcmalloc_minimal.so.0.0.0
/usr/lib/libtcmalloc_minimal.so.0.0.0: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, stripped
You can't link simply to a file with -l if it doesn't end exactly with .so, since the linker assumes a particular naming convention (lib*.so).
You have several choices:
Install libtcmalloc-minimal0-dev if it exists, which should provide the .so dynamic link.
Create the symlink yourself: cd /usr/lib; ln -s libtcmalloc_minimal.so.0.0.0 libtcmalloc_minimal.so; cd -
Link directly to the library without the symlink by using gcc test.c /usr/lib/libtcmalloc_minimal.so.0.0.0
Link using the -l option using the full name: -l:libtcmalloc_minimal.so.0.0.0
Running dpkg -L libtcmalloc-minimal0 will show you that the library is /usr/lib/libtcmalloc_minimal.so.0 so the correct option should be -ltcmalloc_minimal without any digit

Resources