Hi Russ,

You should print AX after every instruction too, to see if
you've actually set it up the way you think you did.

I did, and to my surprise, AX is 0, even though I set it properly in the loader. It appears as if Linux is setting AX to 0 sometime after the loader finishes, but before the executable begins. All other registers, however, are preserved (eip being the most important).

That brings me to the question
of how 8a decides what address to put values like that in? Is the
address the same everytime, i.e. hardcoded into the binary? (certainly
seems to be)

_tos is no different than any other global variable.
8a doesn't use any address at all - it leaves a slot for 8l to fill in.
The eventual address of _tos depends on what other data
is in the binary.  I don't know why you say the address is
the same every time:

I meant the address being fixed for a particular binary.

No, the symbol table is only for debuggers and the like.
Plan 9 doesn't load it into memory either.

The good news is that you've identified the program
behaving incorrectly after executing only *two* instructions.
That should narrow things down considerably.

Every program linked with libc starts with:

83 ec 48: SUBL 0x48, SP

And the following opcode is:

89 05 xx xx xx xx: MOVL AX, _tos(SB).

As a hack, as I'm padding the executables anyway, I check for those bytes and change 89 05 to 89 1D during the padding - which makes the instruction MOVL BX, _tos(SB). I set BX to the proper value in the loader (which is preserved by linux), and voila!

A lot of executables are working now, with the exception of awk (which tries to open #e, which isn't there) - Thanks!

--
Anant


Reply via email to