Getting stared with the Virtual Platform


Getting the source code

Various revisions of the virtual platform will be made available on romulus. The steps below will allow you to grab a copy of any given revision and compile it.

  1. Login to your account on the CS UNIX systems.
  2. Code will be distributed in tarballs. These are single files that contain, in compressed and archived form, a directory of files. Copy the tarball for this first assignment like so:
    cp ~sfkaplan/cs39/assignment-1-code.tar.gz .
  3. Type the following command to decompress and un-archive the tarball. Don't forget the dash character on the end!
    gunzip < assignment-1-code.tar.gz | tar -xvpf -
  4. You should now have a new directory named v0.1 that contains the source code. Change into this directory to see the source code and other files that come with the package.

Compiling and running

In order to compile the virtual platform, you must be in the directory that contains the source code. Then follow these directions to compile and use the virtual platform.

  1. At the command line, simply type the following command:
    make
    You should see the compilation of each of the modules, and then the linking of those modules into a single executable named virtual-platform.
  2. If you would like to change some of the compilation options, do so by editing Makefile.
  3. Assuming things compile well (if they do not, see the second below), you may now try to use the virtual platform to run programs that have been written in the virtual machine's executable format. A number of these small and simple programs have been placed in the directory VM-executables/. To run the virtual platform, you must select one such virtual machine executable (.vmx) file.
  4. To run your chosen .vmx, you must run the virtual-platform program like so:
    ./virtual-platform 16384 VM-executables/add-two-numbers.vmx
    Notice that virtual-platform expects two arguments. The first is the memory size, in bytes. The number of bytes specified must be divisible by four, as the machine's word size is 32 bits (4 bytes). The second argument is the name of the executable you expect the kernel to load and run once the virtual machine boots.
  5. If all goes well, you should see a number of messages fly by. The virtual machine should start, the kernel should boot (that is, take control of the virtual machine), and then you should see instructions from the virtual machine executable being processed.
  6. Note that you can reduce the amount of output. In each module, there is a variable declared at the top of the code (.cc) file named debug. If you set it to be false, then many of the messages will no longer be emitted while the virtual platform runs.

Debugging (A.K.A. "Fun in xemacs")

While modifying things about the virtual platform, particularly the kernel, things will likely break. You will need to find the errors, try to correct them, recompile, and continue to debug the program.

The xemacs editor is a stunningly powerful tool in this respect. It may be ugly, and it may be awkward, but it can do an awful lot of useful things. Here, we're going to try to highlight some of the most useful commands in xemacs so that you can debug and compile your modifications to the virtual platform.

Follow the steps below to bring up the virtual platform code, edit some files, compile the package, and run the debugger on the executable. You will then have used many of the most useful tools xemacs has to offer.

  1. From your shell, type the follow to being up xemacs in the background (that is, you'll get a prompt back immediately in the shell, even though xemacs is also running):
    xemacs &
  2. Within xemacs, you can bring up a shell by typing the following:
    M-x shell
    (Note that, depending on your keyboard, the alt key may work as a meta key, or it may not. If it doesn't, you can always type the esc character to get the meta -- but don't hold it down as you would an alt key! Just type it.)
  3. Using a shell within xemacs is nice, as you get a full history of everything that has happened, and can easily cut & paste previous commands. Better yet, if you move the cursor to a previous command and press enter, xemacs will automatically cut and paste that command at the bottom of the buffer, and submit the command to the shell itself. Try it!
  4. Within the shell, change into the directory that contains the virtual platform code.
  5. You can compile within xemacs, and it will hold the results of the compilation within a separate buffer. Specifically, try typing the following:
    M-x compile
    xemacs will then ask you what command you would like to issue to make the compilation happen. By default, it will show you make -k as a command. Delete the -k part of that line, so that you're just issuing the simple, unadorned make command.
  6. xemacs will split the window, and show you, in one half, the compilation as it proceeds. Either errors will show up in this half of the window, or, well, they won't.
  7. If errors do appear, xemacs will help you examine them! Once you see errors in the compilation buffer, type the following:
    C-x `
    Each time you type this combination, xemacs will move to the next error in the compilation window, and it will bring up the offending file, leaving the cursor at the offending line! This is a handy way to move through your errors.
  8. Once you are done and no longer want to go through errors (if there were any), you can eliminate the split window effect at any time with the key combination:
    C-x 1
    Similarly, you can split it again with:
    C-x 2
    Or, you can split it vertically with:
    C-x 3
  9. Once you have fixed your compilation errors, you'll have (one hopes) a working executable! You can switch to the shell buffer by one of two methods:
    1. Select that buffer from the Buffer menu, using the mouse.
    2. Type the following key combination:
      C-x b
      After this combination, you can type in the name of any buffer you want to use. (The name of the shell buffer is: *shell*.)
  10. You can try to run your program from the shell, as described above.
  11. If your program doesn't execute correctly (heaven forsooth!), you should use gdb to do some debugging. You can start gdb on your executable by typing:
    M-x gdb
    xemacs will ask you "how" you want to run gdb. At this point, you should simply type the name of the executable (which, presumably, is named virtual-platform).
  12. A new buffer will open up, with gdb running, and your executable having been loaded into it. You will be given a prompt that reads:
    (gdb)
  13. There are many things you can do within gdb, not the least of which is type:
    help
    Get used to this help system, as it can help you find out what you want to know about your running program.
  14. Try starting your executable within gdb. To do that, you use the run command, followed by all of the command-line arguments that you would normally pass to the program, like so:
    run 16384 VM-executables/add-two-numbers.vmx
  15. Your program will start running. If there are no errors in it, then it will run to completion. However, if there are errors, gdb will catch the error, split the screen, display information about the error, and bring up the offending file and its offending line.
  16. At this point, there are many things you can do to examine the state of the program at the time of the error. One of the first you can try, which reveals quite a bit, is the backtrace command:
    bt
    This command shows you the activation stack; that is, which functions called which others, and with what values for the arguments.
  17. You can use the print command to print the values of any variables. For example, if you have an integer x, you can show its value with this command:
    p x
    This command can also be used to print more complicated values. If myArray is a variable that points to an array of pointers to objects, each of which contains a data member named foo, you can examine that data member in the object held in the 3rd element of the array like so:
    p myArray[3]->foo
  18. You may wish to examine the variables from the other frames shown in the activation stack. To do so, you can use the frame command to select the number of the frame that you would like to see, like so:
    f 3
    After selecting such a frame, gdb will show you the source code for that function. The appropriate variables will come into scope, and you can examine their contents with the print command.
  19. You may find that the program was so far out of whack by the time the actual error halted the program that you can't tell where your bug is, and when it occurred. However, if you have suspicions, you may set breakpoints -- markers at which gdb will halt the execution of the program, even if an error has not yet occurred. You can set breakpoints for particular functions simply by name:
    b myFunction
    You can also set a breakpoint for a specific line of code by referring to the name of the file and the line number, like so:
    b someCodeFile.cc:80
  20. When you have set a breakpoint, you can re-issue (if you want) the run command to restart the executable. Note that if you just enter run, without the arguments, then gdb will assume that you wanted to use the same arguments as last time.
  21. Once a breakpoint has stopped execution, you can examine the activation stack and variables, as before. There are also a number of commands you can use to continue running the program. The first, and most obvious, is the continue command:
    c
    This command will simply resume execution until an error, a breakpoint, or the end of the program is reached.
  22. After stopping at a breakpoint, you can also perform more step-by-step continuation of execution. Specifically, there is the next command:
    n
    This command will move to the next line in the source code of the 0th activation frame. If that line contains a function call, the call will be performed to completion before execution is stopped again. However, if you want to see what happens inside that function call, use instead the step command:
    s
    This command will move to the next operation that has to be performed, which includes jumping into some new function and seeing its lines of code executed.

If there are other things you want to do with gdb, check the available help and documentation. Also, try some things out! Experimentation may lead you to some capabilities that you didn't know about.


Scott F. Kaplan
Last modified: Wed Sep 12 13:18:47 EDT 2001