Understanding Exception Handlers

Exception Handlers, sometimes called Crash Logs or Crash Dumps, are a message that displays when the game crashes and contains relevant information that can be used to find the cause of the crash and fix it.

This tutorial will teach you how to read and understand these messages so you can debug your code faster.

For this tutorial, you'll obviously need to know how to compile NewerSMBW's source code.

We will use NSMBW PALv1 as our base game, as this is the region the game's disassembly was made out of, and is considered the universal region since all addresses for other regions are made using PALv1 addresses as a base.

Please note that we will be using NewerSMBW v1.3.0 here, but it should work the same for every mod that uses it as a base.

Exception Handlers in NewerSMBW v1.2.0 and the mods based arount it are pretty much the same, except that it has two additional rows of addresses before the relevant one. Do note that crash handlers from recompiled NewerSMBW v1.2.0 code will display version 1.0.2 instead.

Notice how the dotted parts are the same in both crashes. It represents the relevant part of the crash log.

NewerSMBW v1.3.0 has the advantage of telling us the region and revision of the game we're using, as well as what offset in our compiled code does offsets that points to it are at.

However, this offset can be calculated by hand in NewerSMBW v1.2.0 by subtracting the address we want the offset of to the address of the beginning of the chunk of memory that contains our compiled code. This address is written in the game's logs when it boots, as: With ADDR being the address. In the case of PALv1, it's  by default, assuming you didn't change the custom code loader.

Reading the relevant row of addresses
In the shown screenshots, the row of addresses in the dotted lines are the Stack Trace from before the crash.

If you have a little experience in PowerPC Assembly, you might see what this means.

Every time a function calls another function, the address that's required to branch back after the called function finishes executing is stored in a dedicated register called the Link Register. The Link Register is most often stored in the stack as soon as the called function starts to allow calling other functions without losing the address it needs to branch back later on.

This row of addresses, the Stack Trace, represent the 15 latest Link Register values saved before the crash. Here's a simplified C-like example: 0	void main { 1		// code 2		doStuff; 3		// code 4	} 5 6	void doStuff { 7		// code 8		doMoreStuff; 9		// code 10	} 11 12	void doMoreStuff { 13		// code 14		// CRASHES HERE 15		// code 16	}

Assuming  was the start function, and that the piece of code responsible for the crash occured in place of the   comment, and that the line number represents the address of the code in question (it does not but it's to help you picture it).

The game knows the crash occured in the  function, but it doesn't know exactly where. What it does know though is the path that was taken to arrive to the  function when it crashed.

When  called ,   knows that once it's done executing, it's supposed to branch back to line 3 of the code.

Same reasoning for  which knows that once it's done executing, it's supposed to branch back to line 9 of the code because it was called by.

To picture it, the Stack Trace here would be: 9 3

Only with this, you're able to figure out which function caused the crash and who called it.

9 here means the last Link Register saved before the crash was 9, and upon inspecting line 9 you notice that the only function that could have needed to store a Link Register that points to line 9 is the  function as it's called right before line 9.

Since there's no newer Link Register, it means that no other function calls have been performed since, and therefore  is responsible for your crash.

But that's not all, you also know who called  since the line it was supposed to branch back to, line 9, is in the   function.

And you also know who called  since the second link register value in your crash log here is 3, meaning that   was supposed to branch back to line 3 after being done executing, which is in the   function.

In conclusion, just with these two numbers, you're able to figure out that:
 * The game crashed in the  function
 * was called by
 * was called by

This big piece of text can be tough to read and understand, do not hesitate to read it multiple times or ask for help to someone who can explain better than me.

Now, let's apply it to a real in-game scenario. The Stack Trace from the introduction reads: 801652C0 80E3CC98 - 00040FD8 NewerASM 80161E4C 80162008 80162A88 80162C1C 8006CAC8 80064658 80068F58 80068B60 80068820 80830820 80161E4C 801622E8 80162D38

Let's figure out this crash.

The latest saved Link Register points to. Upon inspecting this address in the game's disassembly, we can see the following:

The function that crashed here is  since this function would have needed to branch back to   after being done executing.

is located inside of the  function as we can notice as well.

Just out of this, we know two things:
 * Whatever crashed did when trying to setup a character animation for its 3D Model
 * What went wrong in this setupping process is related to constructing its  instance from memory, its model and its animation.

Now, you've got two possibilities:
 * Use Dolphin's Debug Mode to figure out what arguments were passed when calling
 * Figure out who called  in the first place

Which option is the best really depends on each case. If you've got enough information about who caused your crash, the first option will help you figure out why did it crash. Did a pointer that was passed had a value of 0? Did we run out of memory? This is the kind of question that this option will answer, though it's unrelated to this tutorial and require experience with PowerPC Assembly. This is pure debugging.

We're going to focus on the second option here, because now that we know something crashed the game when setupping its 3D model's character animation, we might want to know what tried to do that.

So, we want to know what called, so let's focus on the second line of our Stack Trace:.

The  mention indicates that wherever that saved Link Register value pointed to was part of the custom code we use and not NSMBW's.

in its current form won't help much because it doesn't tell what part of our code it corresponds to. Luckily, we are also given the offset it corresponds to,.

Here's a small lesson on how is custom code loaded in NewerSMBW: when you compile your code, three kind of files are outputed:
 * System files
 * DLRelocs files
 * DLCode files.

System and DLRelocs files are irrelevant to what we are doing, what does matter here is DLCode files. The DLCode file of a given region contains the entirety of compiled and assembled code we've written, and is loaded by the game and linked to the game's code when it boots. In PALv1, the DLCode file is loaded at, meaning that offset 0 in the DLCode corresponds to address   in-game.

Address  in-game then corresponds to offset   in the DLCode file. NewerSMBW v1.3.0 fortunately calculates this for us.

Now, the offset in the DLCode corresponding to our saved Link Register isn't enough to know in which place of our code it is. We need the Debug Symbol Maps of our code.

When you compile your code, you very likely only take the files from Kamek's  or   directory without bothering much. Though you may have noticed the presence of a folder called. This folder contains various kind of files, the ones we do care about are the ones with the  extension.

These files are named  and there's one per region. Since we're working with PALv1 here we'll go with.

Linkmaps contain information that'll allow us to figure out which offset in your DLCode file corresponds to which function. It's just a text file, open it in your favourite text editor.

The file is divided in multiple parts, the one we do care about is the part that gives the offset of each symbol from each function we wrote. the string  to arrive directly to this part.

You'll now see a series of offsets with names written after them. Considering the offset we're interested in is, let's scroll down to the closest offset that's in the file. Here's the snippet that corresponds in our case: 0x00040864				calculateTileCollisions__8daShyGuyFv 0x00040abc				bindAnimChr_and_setUpdateRate__8daShyGuyFPCciff 0x00040b60				onCreate__8daShyGuyFv 0x000414d4				onDelete__8daShyGuyFv 0x000414dc				onExecute__8daShyGuyFv

Out offset,, is after the offset to   but before. That means that the place in which  is in. Now we can just take a look at the shy guy's code and find our function call.

We now know:
 * The game crashed when a shy guy tried to setup a character animation for its 3D Model
 * What went wrong in this setupping process is related to constructing its  instance from memory, its model and its animation.

Now you've got the essential information, the rest of the job is debugging.

If you're curious, the reason of the crash here was that I removed the hook that allowed for the shy guy's arc file to be loaded. Therefore, the shy guy's model couldn't be initialized and it caused a crash when trying to setup a character animation for the therefore non-existent model.

Figuring this out is your job though, there's no universal crash reasons for everything. Though when a character animation setup failed and was called by a custom sprite of yours, it's very likely that you forgot to load its arc file in the first place.

The point of this section here was to demonstrate the logic and the way to go to understand where is what's going wrong with your game. Figuring out why it is going wrong is your job as a programmer.