Using objdump for ARM architecture: Disassembling to ARM - linux

I have an object file and am trying to disassemble it. When I use:
objdump -d example.o
I get an assembly in code in the file format of elf64-x86-64.
I am trying to disassemble this into ARM, how do I go about doing this?

If you want to do disassemble of ARM code, you'd better have an ARM tool chain, this is what I got:
http://bb.osmocom.org/trac/wiki/toolchain
After you have this, you can use arm-elf-objdump instead of objdump.
The command I used is
arm-elf-objdump -D -b binary -marm binaryfile.dat
If you look the manpage, you will find "-b" is followed by the file type. Sorry I don't know how to tell -b you want to analyze a .o file. "-marm" will tell the cpu is ARM.
Hope this can help you.

Compile binutils with the right target(s) to get binutils objdump binary that knows how to disassemble ARM.
http://www.gnu.org/software/binutils/
./configure --enable-targets=all for example.
Pick your targets, make and use the new objdump binary that is your-target-aware. See the binutils/README file for more information on targeting.
objdump -D t3c # stock binary
objdump: t3c: File format not recognized
vs.
./../../binutils-2.22/binutils/objdump -D t3c # latest compiled from source with all targets
In archive t3c:
t3c:arm: file format mach-o-le
Disassembly of section .text:
00002d94 <start>:
2d94: e59d0000 ldr r0, [sp]
...

Before disassembling the binary, check the filetype via "file", for example:
file dnslookup.o
dnslookup.o: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV),
not stripped
So now we know it is an ARM object or ELF file.
To disassemble arm object file use
arm-linux-gnueabi-objdump. In Ubuntu, "arm-linux-gnueabi-objdump" is the default disassembler for ARM binaries - no compilation is needed.
To install it, just do:
sudo apt-get install binutils-arm-linux-gnueabi
There are also other binaries inside this package that can further analyze the ARM binaries for you.

Install the ELDK and use arm-linux-objdump. You're trying to disassemble ARM instructions using a program that only knows x86.

Related

How to link mach-o format object files on linux?

I have been attempting to link a MACHO formatted object file on Linux, but I have failed miserably. So far, I have created the object file by running:
nasm -fmacho -o machoh.o hello.o
I have tried linking using:
clang --target=x86_64-apple-darwin machoh.o
but that failed. I have attempted using GCC, LD, and other linkers but I have still failed miserably. Are there any ideas on how I could solve my problem?
Thank you very much.
The most accessible solution would be lld, the LLVM linker.
lld does not ship with clang, but is a separate package.
sudo apt install lld
If you installed a version of clang that isn't the default (e.g. clang-12 explicitly), then you should use the same version for lld (i.e. lld-12).
Get a MacOS SDK from somewhere. This GitHub repo archives them.
If you're uncomfortable using the above, the "legitimate" way of obtaining it without a Mac would be:
Create an Apple ID
Go to https://developer.apple.com/download/all/
Download the "Command Line Tools for Xcode <version>"
Mount or extract the dmg
Extract the XAR package
For each ".pkg" folder inside, run pbzx <Payload | cpio -i
Find the Library/Developer/CommandLineTools/SDKs/MacOSX.sdk inside.
Feed both of the above to clang:
clang --target=x86_64-apple-darwin -fuse-ld=lld --sysroot=path/to/MacOSX.sdk machoh.o
I have tried linking using: clang --target=x86_64-apple-darwin machoh.o
but that failed.
Failed how? Details matter.
Anyway, there are 3 commonly used linkers on Linux: BFD-ld, Gold, and (newest) LLD.
Of these, Gold is an ELF-only linker, and will not work for Mach-O.
BFD-ld is only configured to support a few emulations (use ld --help to see which ones) in my distribution. BFD does appear to support Mach-O, so it's probably possible to build a Linux BFD-ld cross-linker with such support.
LLD should support Mach-O out of the box, but you are probably not using LLD.
So your first step should be to figure out which linker clang --target=x86_64-apple-darwin ... uses, and then make it use the one which does support Mach-O.

Linux kernel on ARM Cortex-M: how to build proper executables

I need to build a complete linux development framework for a Cortex-M MCU, specifically a STM32F7 Cortex-M7. First I've to explain some background info so please bear with me.
I've downloaded and built a gcc toolchain with croostool-ng 1.24 specifying an armv7e-m architecture with thumb-only instructions and linux 4.20 as the OS and that I want the output to be FLAT executables (I assumed it will mean bFLT).
Then I proceeded to compile the linux kernel (version 4.20) using configs/stm32_defconf, and then a statically compiled busybox rootfs, all using my new toolchain.
Kernel booted just fine but throw me an error and kernel painc with the following message:
Starting init: /sbin/init exists but couldn't execute it (error -8)
and
request_module: modprobe binfmt-464c cannot be processed, kmod busy with 50 threads
The interesting part is the last message. My busybox excutable turned out to be an .ELF! Cortex-M has no MMU, so it's imposible to build a linux kernel on a MMU-less architecture with .ELF support, that's why an (464c)"LF" binary loader can't be found, there is none.
So at last, my question is:
how could I build bFLT executables to run on MMU-less Linux architectures? My toolchain has elf2flt, but in crosstool-ng I've already specified a MMU-less architecture and FLAT binary and I was expecting direct bFLT output, not a "useless" executable. Is that even possible?
Or better: is there anywhere a documented standard procedure to build a complete, working Linux system based on Cortex-M?
Follow-up:
I gave up on building FLAT binaries and tried FDPIC executables. Another dead end. AFAIK:
Linux has long been supporting ELF FDPIC, but the ABI for ARM is pretty new.
It seems that still at this day and age, GCC has not a standard way to enable FDPIC. On some architectures you can use -mfdpic. Not on arm, don't know why. I even don't know if ARM FDPIC is supported at all by mainline GCC. Info is extremely scarce if inexistent.
It seems crosstool-ng 1.24 is BROKEN at building ARM ELF FDPIC support. Resulting gcc has not -mfdpic, and -fPIC generates ARM executables, not ARM FDPIC.
Any insight will be very appreciated.
you can generate FDPIC ELF files just with a prebuilt arm-linux-gnueabi-gcc compiler.
Specifications of an FDPIC ELF file:
Position independent executable/code (i.e. -fPIE and fPIC)
Should be compiled as a shared executable (ET_DYN ELF) to be position independent
use these flags to compile your programs:
arm-linux-gnueabi-gcc -shared -fPIE -fPIC <YOUR PROGRAM.C> -o <OUTPUT FILE>
I've compiled busybox successfully for STM32H7 with this method.
As I know, unfortunately FDPIC ELFs should be compiled with - shared flag so, they use shared libraries and cannot be compiled as -static ELF.
For more information take a look at this file:
https://github.com/torvalds/linux/blob/master/fs/binfmt_elf_fdpic.c
Track the crosstool-ng BFLAT issue from here:
https://github.com/crosstool-ng/crosstool-ng/issues/1399

Dump debug_loc section from executable

How do I dump debug_loc section from an executable on Linux if default options (-g) are provided to GCC while compiling a C file? I use readelf linux utility.
GCC by default produces DWARF info in DWARF4 format, so if I pass -g-dwarf2 I can see .debug_loc section but how do inspect that section if info is generated with default options as I don't see the section in dump?
Do you use a recent version of binutils? On Ubuntu 14.04 I can build executable with "gcc -g test.c -o test".
With "readelf --debug-dump=info test" I can confirm it's using DWARF 4.
After that, you have (at least) two ways to dump the contents of .debug_line section.
readelf --debug-dump=decodedline test
This will dump decoded line number information. You get line==address mappings directly.
There is also:
readelf --debug-dump=rawline test
This gets you raw debug_line contents.
Usually, .debug_loc is generated for optimized code. Try optimizing your code using compiler flags.

How to produce executable with rustc?

If I compile this simple program fn main() { println!("Hello"); } with rustc test.rs -o test then I can run it with ./test, but double clicking it in the file manager gives this error: Could not display "test". There is no application installed for "shared library" file. Running file test seems to agree: test: ELF 64-bit LSB shared object....
How can I get rustc, and also tools that use it such as cargo, to produce executables rather than shared objects?
I am using 64-bit Linux (Ubuntu 14.10).
EDIT: I have posted on the Rust forum about this.
EDIT#: So it turns out this is an issue with the file executable.
I don't have the rust compiler and can't find its docs on the internet, but I know how to do shared obkect vs executable in C, so maybe this info will help you out in solving it.
The difference is the -pie option to the linker. With a hello world C program:
$ gcc test.c -ohello -fPIC -pie
$ file hello
hello: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
If we remove the position-independent flags, we get an executable:
$ gcc test.c -ohello
$ file hello
hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
Both generated files work the same way from the command line, but I suspect the difference file sees is changing what your GUI does. (Again, I'm not on Ubuntu... I use Slackware without a gui file manager, so I can't confirm myself, but I hope my guesses will help you finish solving the problem yourself.)
So, what I'd try next if I was on your computer would be to check the rustc man page or rustc --help and see if there's an option to turn off that -pie option to the linker. It stands for "position independent executable", so look for those words in the help file too.
If it isn't mentioned, try rustc -v test.rs -o test - or whatever the verbose flag is in the help file. That should print out the command it uses to link at the end. It'll probably be a call to gcc or ld. You can use that to link it yourself (there's probably a flag -c or something that you can pass to rustc to tell it to compile only, do not link, which will leave just the .o file it generates).
Once you have that, just copy/paste the final link command rustc called and remove the -pie option yourself.... if it is there... and see what happens.
Manually copy/pasting isn't fun to do and won't work with tools, but if you can get it to work at least once, you can confirm my hunch and maybe ask a differently worded question to get more rust users' attention.
You might also be able to tell the file manager how to open the shared object files and just use them. If the manager treated them the same as programs file identifies as executables, as the command line does, everything should work without changing the build process. I don't know how to do that though, but maybe asking on the ubuntu stack exchange will find someone who does.
What you have described is not entirely consistent with what I observe:
$ rustc - -o test <<< 'fn main() { println!("Hello"); }'
$ ./test
Hello
$ file test
test: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=99e97fcdc41eb2d36c950b8b6794816b05cf854c, not stripped
Unless you tell rustc to produce a library with e.g. #![crate_type = "lib"] or --crate-type lib, it will produce an executable.
It sounds like your file manager may be being too smart for its own good. It should just be trusting the executable bit and executing it.

How to cross compile a C++ file with LTIB

I have installed LTIB from freescale (by way of Congatec) and would like to compile a "hello, world" program. gcc gives me the native executable. How do I compile for my ARM processor?
You need to install a cross compiler for ARM. gcc on your machine is the native compiler, a cross compiler has a different prefix that determines the target architecture, operating system and libc. In your case, the target system has probably an ARM architecture, is running a Linux kernel with the GNU libc.
arm-none-linux-gnueabi-gcc -o hello hello.cpp
Run ./ltib -m shell. In this mode all of the standard tools are setup to allow ./configure and other setups to build for an ARM by default. From this shell gcc -o hello hello.cpp will create an executable for you. It will be setup for your rootfs, be it uCLibc or glibc. You can also take external open-source packages and run the ./configure - make cycle.
The documentation in the LTIB FAQ has much more information on using LTIB. LTIB typically installs tools in the /opt/freescale directory. If you are not using a custom compiler you will find the compiler under /opt/freescale and can use it directly. In this directory, the compiler will be named something like arm-none-linux-gnuabi-gcc. With the ./ltib -m shell, it is aliased to gcc as are many other standard commands for cross-building.
Look at the -march=name option in the gcc man page. The exact architecture you will specify depends on the version of ARM you need to compile for. v5 ARM example:
gcc -o ARM.exe -march=armv5 source.c
First move to the LTIB folder.
cd "ltib folder"
Then enter the ltib shell
./ltib -m shell
then compile using
gcc -static "program name" .c -o "program name".sabre
Then run the command
file "program name".sabre

Resources