7

I have a simple C++ program that calls some NASM code:

main.cpp:

#include <iostream>

extern "C" int foo();

int main() {
  std::cout << "The result is: " << foo() << std::endl;
  return 0;
}

foo.asm:

bits 64
global foo

section .text
foo:
    mov rax, 123
    inc rax
    ret

I can compile everything with CMake

cmake_minimum_required (VERSION 3.15)

project (assembly-x64 LANGUAGES CXX ASM_NASM)
  
# old school CMAKE to handle NASM formats
if(WIN32)
    set(CMAKE_ASM_NASM_FLAGS_DEBUG "-g -F cv8")
    set(CMAKE_ASM_NASM_OBJECT_FORMAT win64)
elseif(APPLE)
    set(CMAKE_ASM_NASM_FLAGS_DEBUG "-g -F dwarf")
    set(CMAKE_ASM_NASM_OBJECT_FORMAT macho64)
else()
    set(CMAKE_ASM_NASM_FLAGS_DEBUG "-g -F dwarf")
    set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
endif()

add_executable(assembly-x64)

target_compile_features(assembly-x64 PUBLIC cxx_std_17)

target_sources(assembly-x64 PRIVATE main.cpp foo.asm)

and I get the correct result. However, I'd like to be able to debug the assembly code just like I would the C++ code. I can create a breakpoint on the foo function (not using the GUI though), but it doesn't show me the corresponding source location when it pauses. Is there a way around that issue? I'd like to be able to watch registers, etc. Not sure if it's possible in VS code.

Waqar
  • 8,558
  • 4
  • 35
  • 43
Touloudou
  • 2,079
  • 1
  • 17
  • 28

2 Answers2

12

Short Answer: No. On linux, launching gdb from vs-code to debug asm code resulted in a quick crash. It doesn't even let you put breakpoints on asm code.

Read the longer answer in case you want to know about the alternatives.


I assume you are not using Linux, because I was unable to build the project on Linux with the cmake you provided. I had to add the following:

...
else()
    set(CMAKE_ASM_NASM_FLAGS_DEBUG "-g -F dwarf")
    set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
    # had to add this to build on linux
    set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> \
    <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>")
endif()
...

Ok, so now the project is built and running. However, the bad news is that I was unable to set up "debugging" environment with VS-Code. VS-Code doesn't really have good assembly support to begin with so I am not really surprised here. I tried to configure launch.json multiple times, but everytime I launch GDB, VS-Code crashes. This may or may not happen on Windows or Mac, so I can not answer for those platforms but I assume it will not work there.

I personally just use gdb from terminal directly because it is more powerful and easy to use once you figure it out. I will give you two work flows which you can use instead of Vs-code.

Use terminal

  • Build your executable
  • Next launch it using gdb like this:
gdb ./assembly-64 --tui

This will open gdb and bring you to the tui screen.

  • Lets assume we want to put a break point at foo, for this type:
b foo
  • Now our breakpoints are all set. We are ready to start our debugging session. Type:
run
  • It will go and break at foo.

But wait a minute, there are no registers, how should we see them? This is my favourite part about gdb. Type:

layout regs

And you will get a beautiful look window at top showing you all the registers. It will even highlight the registers as they change making it easy for you to monitor changes.

  • Other than this, Use n to step next, use si to step into. That's pretty much it for the basics. If you want to see the value at some memory location, or a register. Type:
print $rax

There's a lot more to this, but this will give you a quick start.

GUI

I was pleasantly surprised when I discovered that QtCreator can debug asm + cpp files very nicely. Just load up your cmake project and place your breakpoints. You can enable registers pane from Menu->Window->Views->Registers. Screenshot:

enter image description here

There are other guis(for gdb) out there, nemiver, ddd etc.

Waqar
  • 8,558
  • 4
  • 35
  • 43
  • 1
    Thanks for the detailed answer. I will give QtCreator a shot then. If it does not work for whatever reason, I'll sacrifice portability and just do all the work on my Linux machine using gdb as you suggested. – Touloudou Jul 31 '20 at 11:48
  • 1
    https://www.cs.uaf.edu/2017/fall/cs301/reference/nasm_vs/ if you have Visual Studio, this might work for you. – Waqar Jul 31 '20 at 12:09
  • 1
    Thanks for the tip, but I want to setup an environment that will work on both my Linux and Windows machines. QtCreator seems to be doing great so far. Note that somehow, my code was compiling with VS Code but not with QtCreator. I also had to add the line you mentioned to get it to build properly. – Touloudou Jul 31 '20 at 12:15
  • For the sake of completeness, Visual Studio can also do remote debugging in Linux using the MI engine. For some reason, asm debugging in gdb actually works there and you can set breakpoints in the code, visualize register content, etc. – Jean-Mathieu Vermosen Nov 29 '20 at 16:44
  • I know it was pretty long time ago but could u upload all project for some site to download ? I have problem with qt creator when i put a breakpoint it just miss whole asm file and only debug cpp file. – Virozz May 10 '21 at 17:16
2

To debug C++ code and assembly code simultaneously, you can do this with gobolt online: https://godbolt.org/

If you just want to write assembly and debug in vscode, let me tell you the method I just learned.

There is a great project for this. https://github.com/newtonsart/vscode-assembly

You should also do these additionally.

32 Bit Support

sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
sudo apt install gcc-multilib

nostdlib gcc argument

(https://stackoverflow.com/a/32855954/6646336) I used extra gcc argument for some errors.

# .vscode/tasks.json
# find gcc command and add <nostdlib> in two line
... gcc -nostdlib -m64...
... gcc -nostdlib -m32...

But still you can't set a breakpoint in (*.s, *.asm) file. vscode doesn't accept. You must enable in settings (keyword: debug.allowBreakpointsEverywhere = true)

And final step: Set a breakpoint and select your debugging type. vscode-assembly

Fahri Güreşçi
  • 569
  • 7
  • 14
  • https://godbolt.org/ lets you run a program, and/or see the compiler-generated asm, but it does *not* let you debug. There's no GDB interface, no breakpoints. And it's not C++ and assembly, it's always just a single file. https://www.onlinegdb.com/ *does* have an assembly mode, but only GAS not NASM. Debugging locally is significantly better if you have a Linux environment. – Peter Cordes Apr 19 '22 at 00:45
  • 1
    I wrote about vs code because the title of the question contains vs code. gobold website supports C++ and so many others. I think there is no perfect environment for this and I don't think there will be either. I have presented the best method I know. I hope it will be useful to other reverse engineers. – Fahri Güreşçi May 04 '22 at 20:31