James Harris
2020-12-19 11:46:52 UTC
I just had an exasperating asm problem which may be of use or interest
to someone else so here's a writeup.
I have a program of about a dozen source files all of which are in Nasm
assembly. When I was restructuring it and moving some functions from one
file to another an error occurred.
One of the modules handles a small 'context stack'. It has a routine
called cs.entry_address which returns the address of an entry on the
stack. It had been OK before but after I moved some code it reported
stack entry 134541369 is inaccessible. Stack size is 20
The stack size is correct but the index it had been asked for is a long
way out of range.
I ran the program in gdb to try to find out where the routine had been
called from but what gdb backtrace reported didn't seem to make any
sense as the routine is not called from the place gdb said it had come
from. Further, gdb said there was stack corruption below the caller's
stack frame.
As another tack I put 'print statements' at each place where
cs.entry_address is called thinking that would show which one it was.
Surprisingly, the call came from none of them!
I spent ages reading the code looking for potential causes of stack
corruption and not finding any. But after a lot of fiddling around and
head scratching I finally found that the call was coming from the
following instruction:
call compile_error
The routine name, compile_error, isn't important here - except insofar
as it is most definitely not cs.entry_address...!
For some reason what appeared in the code as a call to compile_error
apparently called cs.entry_address instead.
To cut a long story short the problem ended up being that I had the
following statement
global compile_error
in two source files. I removed it from the one it should not have been
in and bing! The program worked as before. I had evidently left the
global statement behind when moving routines out of that file.
What I think was happening was that the first parameter to compile_error
is the address of a string, and it was that address that
cs.entry_address was treating as an index into the stack and reporting
as out of range.
As far as I can see Nasm could have reported an error. The Nasm manual
says global "must refer to symbols which are defined in the same module
as the GLOBAL directive" and there was no symbol of that name therein.
Also, the file had an extern declaration for the same symbol and
global/extern would seem to me to conflict with each other.
Specifically, which file had which symbol was as follows.
* file c0.nasm had the 'compile_error' label and
global compile_error
* file c0_parse.nasm had no compile_error label and had
extern compile_error
global compile_error
FWIW I would have guessed there would be two causes of reportable error:
1. Symbol declared as global is not present.
2. One source file cannot have extern and global for the same symbol.
Anyway, that's it. Knotty problem. Glad it's fixed. Asm debugging can be
a pain!
to someone else so here's a writeup.
I have a program of about a dozen source files all of which are in Nasm
assembly. When I was restructuring it and moving some functions from one
file to another an error occurred.
One of the modules handles a small 'context stack'. It has a routine
called cs.entry_address which returns the address of an entry on the
stack. It had been OK before but after I moved some code it reported
stack entry 134541369 is inaccessible. Stack size is 20
The stack size is correct but the index it had been asked for is a long
way out of range.
I ran the program in gdb to try to find out where the routine had been
called from but what gdb backtrace reported didn't seem to make any
sense as the routine is not called from the place gdb said it had come
from. Further, gdb said there was stack corruption below the caller's
stack frame.
As another tack I put 'print statements' at each place where
cs.entry_address is called thinking that would show which one it was.
Surprisingly, the call came from none of them!
I spent ages reading the code looking for potential causes of stack
corruption and not finding any. But after a lot of fiddling around and
head scratching I finally found that the call was coming from the
following instruction:
call compile_error
The routine name, compile_error, isn't important here - except insofar
as it is most definitely not cs.entry_address...!
For some reason what appeared in the code as a call to compile_error
apparently called cs.entry_address instead.
To cut a long story short the problem ended up being that I had the
following statement
global compile_error
in two source files. I removed it from the one it should not have been
in and bing! The program worked as before. I had evidently left the
global statement behind when moving routines out of that file.
What I think was happening was that the first parameter to compile_error
is the address of a string, and it was that address that
cs.entry_address was treating as an index into the stack and reporting
as out of range.
As far as I can see Nasm could have reported an error. The Nasm manual
says global "must refer to symbols which are defined in the same module
as the GLOBAL directive" and there was no symbol of that name therein.
Also, the file had an extern declaration for the same symbol and
global/extern would seem to me to conflict with each other.
Specifically, which file had which symbol was as follows.
* file c0.nasm had the 'compile_error' label and
global compile_error
* file c0_parse.nasm had no compile_error label and had
extern compile_error
global compile_error
FWIW I would have guessed there would be two causes of reportable error:
1. Symbol declared as global is not present.
2. One source file cannot have extern and global for the same symbol.
Anyway, that's it. Knotty problem. Glad it's fixed. Asm debugging can be
a pain!
--
James Harris
James Harris