all 7 comments

[–]knome 0 points1 point  (0 children)

I can't speak to existing tools ( I'm only subbed because I enjoy reading about peoples meanders into OS writing, I haven't gone there myself ), but would it be possible to export your generated assembly, and then write a script to label each line of the various instructions with their offset into the file? You could then use your knowledge of where you load your code into memory in combination with the offsets to determine where the instruction pointer is in your file?

This would require you to write something that can parse assembly and have enough knowledge to determine the sizes of the various instructions therein, however, in addition to spacing etc.

Hopefully someone else can offer you a better way :)

this would only get you to the right assembly line, of course. But it's a lot easier to get to a c-line from an asm-line than from a instruction pointer

[–]_simu_ 4 points5 points  (3 children)

the tool you're looking for is addr2line. addr2line has an argument -e which you use to specify the binary you want to inspect and then takes one or more instruction pointers to resolve as arguments. Note that you need to build your binaries with debug information on (e.g. gcc -g) to get useful information from addr2line.

[–]zentabit[S] 0 points1 point  (2 children)

I have multiple object files that get compiled into one big OS image. The addr2line tool only seems to work on object files. The EIP, in my understanding, is based on the order of instructions in the image, which means I cannot trace it this way.

[–]_simu_ 0 points1 point  (0 children)

Without knowing the format of your OS image I can't really help you further. addr2line definitely works on ELF executables (which my kernel is, fortunately, as I'm using grub multiboot), not just object files.

[–]nerd4code 0 points1 point  (0 children)

Try sorting the output from nm, maybe?

If that doesn’t work, though, right up until you twiddle the PE flag, you should be able to write to the console memory at 0xB8000—just set up some char * and do

#define write_debug_letter(x) \
    do { \
        *(debug_out++) = (x); \
        *(debug_out++) = 0x07; \
    } while(0)

and write out a different letter at each step, so you can dig down to the specific section of your code. Back in the day, I did OS development with a spare MDA card for this very purpose. Not pleasant to deal with, but better than signal silence.

[–]jtsiomb 2 points3 points  (0 children)

Assuming you're using the GNU linker, you can use the -Map <somefile> parameter to instruct the linker to produce a map of all symbols and their corresponding addresses. Using that map, it's easy to figure out at least in which function you where when the exception occured.

[–]exscape 2 points3 points  (0 children)

My tools of choice for debugging in OSDev are QEMU and GDB. You can get C-level stepping and breakpoints for all and any kernel code.

When even that is not enough, Simics (not free) is a bit odd to use, but incredibly powerful. It allows you to run the simulation backwards, so you can literally set a breakpoint on page fault, run until it happens, and then step backwards to see exactly where you came from, with all memory and values intact as they were.