Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Debugging NASM in VS code

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.

like image 977
Touloudou Avatar asked Mar 03 '23 05:03

Touloudou


2 Answers

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.

like image 198
Waqar Avatar answered Mar 05 '23 15:03

Waqar


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

like image 23
Fahri Güreşçi Avatar answered Mar 05 '23 16:03

Fahri Güreşçi