A simple hacky emulator/debugger for LLVM--
This application is an emulator/debugger for LLVM– as defined in the Compiler course (dOvs) at Aarhus University.
While I hope that you will find it useful, the tool is being provided AS IS, this means
i64
can be arbitrarily
large. And there can, of course, be bugs in the application.clang
, if you want to check types of your generated codeThis application is written in Python. It was developed in Python 3.6, but I expected to work for Python 3.5 and above. Note that Python 2 is not supported.
Several Linux distributions have Python 2 as the default. You can
usually use the commands python3
, pip3
, etc. to use Python 3 on
such systems (assuming you have installed Python 3).
The application uses some third party libraries as indicated in
requirements.txt
.
This project is designed for Linux, though I do not expect there to be any issues on other platforms. As a consequence the commands given below are designed for a Linux shell. Lines beginning with a dollar sign ($) indicate commands you enter into your terminal, other lines are output from running those commands
To see if you already have Python 3 installed, try running (the lines beginning with $):
$ python --version
Python 2.7.14
$ python3 --version
Python 3.6.3
If one of these commands gives a version number >= 3, you have
Python 3 through that command (without --version
, of course). In
the example above, I need to use the command python3
in order to
use the correct version of Python for this emulator.
Otherwise, you could try to install Python 3 via your package manager. Depending on which Linux distribution you use, you could try something like
$ apt install python3
or
$ sudo apt install python3
You need pip to (easily) install Python packages. If your Linux distribution came with Python 2 and pip, the pip you have might not work for Python 3. Let us first check that:
$ pip --version
pip 9.0.1 from /usr/lib/python2.7/site-packages (python 2.7)
$ pip3 --version
pip 9.0.1 from /usr/lib/python3.6/site-packages (python 3.6)
As with the Python version commands in the last section, I have to
use pip3
. If I just used pip
packages would be installed for
Python 2, which I do not want.
Pip should come with newer versions of Python. If you have a new version of Python, but no pip, you might need to install it seperately. You could try (depending on your Linux distribution)
$ apt install python3-pip
or
$ sudo apt install python3-pip
Installation includes
The recommended way to quickly install and use the emulator, is to
install it via pip. The name on PyPI (where pip gets the software
from) is llvm-minusminus-emulator
[fn:0].
Make sure that you have Python 3 and pip installed (see above). Then install the emulator by running
$ pip3 install llvm-minusminus-emulator
If all goes well, you are now ready to use the emulator.
[fn:0] I know the name is ugly, but Python packaging was not happy
about the double dash in llvm--emulator
, and llvm-emulator
makes
it sound like it covers the entire LLVM IR language.
To get the very latest version, you can do the following
If you have not already, download the code.
$ cd path/to/folder/where/you/want/to/store/the/emulator
$ git clone git@gitlab.com:cfreksen/llvm--emulator.git
To install the software, you can use pip
on the folder containing
setup.py
:
$ cd path/to/folder/where/you//stored/the/emulator/llvm--emulator
$ pip3 install .
You should now be ready to use the software.
To remove the emulator, just uninstall via pip:
$ pip3 uninstall llvm-minusminus-emulator
If installing the emulator went well, a script (llvm--emulator
)
should have been added to your bin
folder. This means that you can
start the emulator (wherever you are), by running that script:
$ llvm--emulator --help
usage: llvm--emulator [-h] {auto} ...
A hacky LLVM-- emulator/debugger
positional arguments:
{auto}
auto Automatically step through llvm in a given file
optional arguments:
-h, --help show this help message and exit
To automatically step through a LLVM file (and be quite verbose
about it), you can use the auto
command:
$ llvm--emulator auto path/to/your/file.ll
When running the emulator you might get messages like the following:
WARNING: Couldn't open 'parser.out'. [Errno 13] Permission denied: '/usr/lib/python3.6/site-packages/llvm_emulator/parser.out'
WARNING: Couldn't create 'parsetab'. [Errno 13] Permission denied: '/usr/lib/python3.6/site-packages/llvm_emulator/parsetab.py'
This is because the script does not have permission to write files
among your Python libraries. This is because the parser inside the
emulator tries to cache its parsing table (think of tiger.grm.sml
)
where the parsing code is located. If does not have permission to do
that, it still parses your LLVM code; it just needs to rebuild the
parsing table next time you run the emulator. These warnings should
be safe to ignore.
I have tried to fix this issue without success, so hopefully you can live with a few warning messages.
Let us say, that we have the following LLVM– code in some_file.ll
%Ttigermain = type { i64, i64, i64 }
define i64 @tigermain (i64 %U_mainSL_8, i64 %U_mainDummy_9) {
%t = alloca %Ttigermain
%a = getelementptr %Ttigermain, %Ttigermain* %t, i32 0, i32 1
store i64 9, i64* %a
%r = load i64, i64* %a
%s = add i64 100, %r
%b = getelementptr %Ttigermain, %Ttigermain* %t, i32 0, i32 0
store i64 %s, i64* %b
ret i64 %s
}
Then we run the emulator:
$ llvm--emulator auto some_file.ll
Parsing some_file.ll
Beginning execution of some_file.ll
Heap after globals are allocated:
[None]
Line 4: alloca %Ttigermain
alloca {i64, i64, i64} --> allocating 3 cells
%t <- 1
Line 5: getelementptr %Ttigermain, %Ttigermain* %t, i32 0, i32 1
Getting adress of [{i64, i64, i64}, ...][0][1]
Gep formula: 1 + 0 * 3 + (1)
%a <- 2
Line 6: store i64 9, i64* %a
heap[2] <- 9
Line 7: load i64, i64* %a
load heap[2]
%r <- 9
Line 8: add i64 100, %r
add 100, 9
%s <- 109
Line 9: getelementptr %Ttigermain, %Ttigermain* %t, i32 0, i32 0
Getting adress of [{i64, i64, i64}, ...][0][0]
Gep formula: 1 + 0 * 3 + 0
%b <- 1
Line 10: store i64 %s, i64* %b
heap[1] <- 109
Line 11: ret i64 %s
Returning 109
Stepping done!
Final ssa_env: {'U_mainSL_8': 1234, 'U_mainDummy_9': 5678, 't': 1, 'a': 2, 'r': 9, 's': 109, 'b': 1}
Final heap: [None, 109, 9, <<Garbage>>]
Program resulted in 109 after 8 steps
This shows which values variables have as they are encountered as well as the order the instructions are evaluated.
If the llvm--emulator
script does not work for you, you can
inspect it in the path/to/emulator/repository/bin/
folder
(assuming you have the source code. See the section
‘Installation:Git Way’, or look at the code online on
https://gitlab.com/cfreksen/llvm–emulator). It should be clear
enough what the script does, and if you know a bit of Python, you
should be able to tweak it to your needs.
Here some of the known major issues/missing features are listed. This list might be updated, should the issues be fixed/the features implemented:
There is currently no support for stepping through the code one key press at a time. Similarly, there is no support for inserting breakpoints, or looking up the current values in memory/registers via commands.
The code in this project is licensed under GPLv3+. The full
licensing text can be found in the LICENSE
file, while a small but
descriptive header is:
LLVM– Emulator – A simple hacky emulator and debugger for LLVM– Copyright © 2017 Casper Freksen
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.