Sometimes we need to debug a module containing a microprocessor implemented in FPGA. Often the program is enclosed in ELF file – leaving us with no access to the program source code. In these cases we can learn how the program functions by analyzing the machine code for the microprocessor. But first, the assembly code needs to be extracted from the ELF file. Let me show you how to get disassembled code from ELF file in Vivado/Vitis.
ELF file
During development of digital systems, we often need to use IPs implementing various functionalities. In most cases these IPs has been implemented by other companies or engineers. Sometimes the documentation is not comprehensive and not all source code is available – especially if the IP uses a processor (such as AMD MicroBlaze) requiring a block design and application software. We can have these in two forms: a source code or packaged as ELF file. In many cases we only have access to the ELF file, as the creators might not want to disclose all of the source code. There is no problem with this approach – unless we need to debug the IP core. If the module doesn’t work as expected and debugging is necessary, we often need at least some way to check what happens in the processor.
Disassembling ELF file in Vivado/Vitis
In order to get disassembled ELF file in Vivado requires us to use Vitis IDE. It is a separate tool from AMD/Xilinx, often installed with Vivado. It works in conjunction with Vivado, but operates at a higher level of abstraction.
Firstly, we need to launch Vitis IDE from Vivado menu:
![](https://aawo.dev/wp-content/uploads/2024/03/Launch-Vitis.png)
Then, from Vitis we need to launch shell window:
![](https://aawo.dev/wp-content/uploads/2024/03/Open-Vitis-Shell-1024x585.png)
Lastly, in the new Vitis shell window run objdump
for a selected processor architecture. The example command:
mb-objdump -D ./input.elf > output.S
![](https://aawo.dev/wp-content/uploads/2024/03/Vitis-shell-1024x585.png)
The objdump
versions for different architectures include:
- mb-objdump
- arm-none-eabi-objdump
- armr5-none-eabi-objdump
- aarch64-none-elf-objdump