How to use .map file to locate line that crashes

Started by allynm, May 06, 2011, 01:54:51 AM

Previous topic - Next topic

allynm

Hello everyone,

In 32 bit code there is a very precise method for identifying a source code line that causes a crash.  The method as you know requires the address at which the program crashes, the base of the PE image, and the size of the PE header.  The method assumes line number info in the .map file.

I was hoping someone might be able to give me a quick tutorial on how to do the analogous procedure for 16 bit code.  If I generate a .map file using link16 with /linenumbers switched on, how would I go about finding the offending source line given that I know the seg:offset where the program crashes.

Thanks,
Mark Allyn

dedndave

the map file won't help you, there   :P
there are a number of ways to go about it
for one, error checking in the code

you can use a beep, now and then to see if the program is making it to that point
        mov     dl,7
        mov     ah,2
        int     21h


also, nice to have a little routine that spits out hex values

of course, there are a number of debuggers for 16-bit
but, i find that i rarely need one to locate a problem

FORTRANS

Hi,

   As Dave says, in real mode there is not much to report where
a problem occurs.  If the crash generates an interrupt (like a
divide by zero) a debugger or TSR can catch it  But most
"crashes" are silent and don't trigger any interrupt/exception.
Think of an infinite loop that is entered by accident.  Many of my
errors tend to be from the stack being imbalanced, and a Windows
DOS prompt or OS/2 VDM (preferred) can catch a fair number
of those.

   Dave's suggestion of printing a beep is good, though I prefer
something like "got to #1", "got to #2", "got past Problem #3",
and the like.  It is easier to print a single character, but I tend
to lose count if they are all the same.

   As you use Codeview, you could check and see if there are
ways to help it to check for errors or report a line number when
an error is detected.

   I have used scripts with DEBUG for some ugly debugging
sessions.  Time consuming and something of a last resort
kind of thing.

Regards,

Steve N.

dedndave

interesting, Steve
i used to use the scripts for disassembling   :P
as you figure out more about a program, the script evolves and does a better job of describing what is code and what is data
i disassembled many programs with debug - lol

FORTRANS

Hi Dave,

   I ended up purchasing Sourcer for disassembling programs.
Does a fair job I guess.  Until things get complicated, or large,
or strange, or...  The authors of "Undocumented DOS" mention
using DEBUG scripts to disassemble MS-DOS itself.  A fun book.

Cheers,

Steve

dedndave

yes - it was really handy when i was trying to figure out IO.SYS / MSDOS.SYS
that was the worst part of DOS to take apart - the rest was fairly easy

allynm

Hi Dedndave and Steve,

OK, I'm persuaded.  I guess this is an instance where 16 bit and 32 bit sys's are not "parallel".  But, just what the heck is the value of /linenumbers in the link16 options?  What are linenumbers good for?  I can see by looking at em that you can associate a linenumber with a location in CS, but so what?

Regards,
Mark

FORTRANS

Quote from: allynm on May 06, 2011, 05:51:29 PM
But, just what the heck is the value of /linenumbers in the link16 options?

Hi,

   Just checked and the reference says:  "... to list the starting
address of each program source line.  ...  Line numbering is
available only in high-level language compilers. If an object file
has no line number information, LINK ignores the /LINENUMBERS
option."  So not applicable to assembler.  So you should check
your compiler's documentation.  If supported, it should give an
example.  Borland may require you to use their linker though.

Regards,

Steve N.

dedndave

i think that applies to the old (very old) ms/ibm basic compiler
if your program crashed it would report:
crash on line 10050
instead of:
crash at address 10FE

redskull

I'm not sure what you're asking, or what problem you are having.  When I write this:


.model small
.386
.stack
.data
MsgPrint db "It Rubs the Lotion on it's skin", "$"
.code
start:
    mov ax, seg MsgPrint
    mov ds, ax
lab1: mov ah, 09
    lea dx, MsgPrint
    int 21h
    mov ax, 4c00h
    int 21h
end Start


and build it using this:


ml /omf /c /Zi /Zd 16tst.asm
link16 16tst.obj /LINENUMBER



I get this .map file.



Start  Stop   Length Name                   Class
00000H 00011H 00012H _TEXT                  CODE
00012H 00031H 00020H _DATA                  DATA
00040H 0043FH 00400H STACK                  STACK

Origin   Group
0001:0   DGROUP

Line numbers for 16tst.obj(16tst.asm) segment _TEXT

     8 0000:0000     9 0000:0003    10 0000:0005    11 0000:0007
    12 0000:000b    13 0000:000d    14 0000:0010

Program entry point at 0000:0000



Isn't that what you need to cross reference addresses to line numbers?

-r
Strange women, lying in ponds, distributing swords, is no basis for a system of government

dedndave

well - if you want to make all your symbols/labels global and public

better to learn a little troubleshooting technique - it will be a skill you use a lot - lol

allynm

Hi Red' and 'Dave and Steve N.

Yes, what Red' shows is what I can get too with /linenumbers.  The original question was:  how to figure out on which line a 16 bit prgm crashes.  If we have the linenumbers (as in Red's output) and if we have the seg:offset of the crash point, how do we get back to the guilty linenumber?  That's the question.  Yes, for sure the linenumber info cross references to the code offsets, but that isn't the problem I was asking about.  Sorry if I was misleading on this point. 

SteveN and 'Dave state that there isn't any straightforward way to work off the .map file to find the culprit.  Both suggest simple and effective techniques for finding where the prgrm fails (like "beep", or "got this far"). 

I had been thinking that 16-bit ought to work like 32-bit.  In 32-bit if you know the crash address  and if you know the preferred load address and you have linenumber info you can precisely pinpoint the offending instruction.  WITHOUT OLLY!  My question was:  how do you do this in 16-bit (if it can be done!) since OLLY ain't no help.

Regards to all,
Mark

FORTRANS

Hi,

   Interesting results redskull.  However you get the same
information in a more relevant way by creating a listing.  But
good to know I suppose.  Thanks.

   Dave, looked at the Microsoft FORTRAN documentation,
and it mentions /LINENUMBERS in the linker section.  But I
cannot immediately find any further information to flesh that
out.  (??  A to do I guess.)

   Mark, if you have the address of the crash, then the LIST
file (or a MAP file) should give you the code that is failing.  If
you are running the program in a debugger or emulator, you
can display the code directly.  The segment that your running
program shows is probably not relevant, as it depends on the
load point in memory.  The offset is what you look at to see
where the crash occurs in your program.  The offset should
be relative to the code segment start.

   The problem is that (in my experience with my code, etc.)
that you do not have that information in many cases.  So you
have to find the point of failure in another manner.  And that,
of course, depends on how your program decides to crash
and what symptoms are evident.  What Dave and I were
discussing were general techniques to address that problem.

   Your case may show symptoms that make one procedure
more convenient to use than the others.  It depends on how
much information you have.  Or. as they say, YMMV.

HTH,

Steve

Edit:

   Bochs may give you the information you are used to get
from Olly.

SRN

allynm

Hi all,

One other point of interest in 'Red's code is that he doesn't load DGROUP or _DATA, he loads using seg MsgPrint. 

Mark

allynm

Hi Steve,

It's hard to find any info on /linenumbers, at least nowadays.  Red's command line uses the /Zd switch for the ml.  I have found that you do not need to set this switch to get the linenumbers.  All you need is to set /linenumbers when you link16.  Perhaps these are "bogus", but they sure look like Red's.

I roughly follow what you are saying the third paragraph.  I would like to see a real example of what you describe.  Problem is---just as you say---getting a program to fail with the failure address produced.  Otherwise you have to "step" through it the way you and 'Dave discuss.

Regards,
Mark