Date: Wed, 12 Aug 1998 11:08:25 +0000 ( ) From: "Gurunandan R. Bhat" To: Eli Zaretskii Cc: djgpp-workers AT delorie DOT com Subject: Re: [grbhat AT unigoa DOT ernet DOT in: Problem with process_coff()] In-Reply-To: Message-Id: Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Precedence: bulk On Wed, 12 Aug 1998, Eli Zaretskii wrote: > I have never really dug deep enough into syms.c, so the following is > based on a very limited study, and only at the source level. So > please check my assertions carefully, do not take them for granted ;-). The same for me too, infact more so. I spell things below, more to clarify to myself and make it easier for you to pick holes in my logic, > That's not what I think goes on here. The total number of elements in > the array l[] is the number of lines in the function to which those > lines belong. Line number info table pertains to a section of a coff file as a whole and begins at f_lnno[i][0] where i is the section number. l points somewhere into this table. The symbol table entry for a function *declaration* (which is a symbol) says where l must point to, inside the array f_lnno[i]. When l is set in this manner, l.l_nno = 0. That is, the relative line number of the function declaration symbol is zero. The next entry in the line number table will correspond to the line containing the opening brace (the ".bf"). This will have l.l_nno = 1. And.... > l[k] holds the information about k'th > ``breakpointable'' line of the function. Yes, I agree. > So l++ just advances from > the first line of the function to the next: Yes. However, may I add here that modules which are compiled without -g have a line number table entry only for the first line (the opening brace) and the last line (the closing brace). There are no entries corresponding to lines in the body of the function. I mention this for reference later. > The way I see it, the problem might be in the termination condition of > the ensuing loop: > > > for (i2=0; l[i2].l_lnno; i2++) > > l[i2].l_lnno += lbase; That it is. But only for the function whose entries comes last in the line number info table. Not for others. For functions before the last entry, there is always an line number entry for the next function declaration for which l[i2].l_nno = 0. (Function declaration symbols always have l[].l_nno = 0. It is the opening brace that has l[].l_nno = 1.) So for any function the loop will stop when it encounters the declaration of the next function. For the last function.....? > This assumes that the lines' info for the function being processed is > terminated by an entry whose l_lnno member is zero. In the sense described above. The "entry whose l_nno member is zero" is in fact the declaration of the next function. Please confirm this. Thank you. > This only promises that each entry will *begin* with a zero l_lnno, > but it says nothing about how the last entry *ends*. This might cause > problems when processing the last entry. Checking l[i2] against the > end of f_lnno[] might help. Yes that is what I thought. Moreover the auxent structure contains info about the location of the last index in a table. (If some Guru may kindly confirm) which also could be used.. ... > There's also something else that bothers me. Earlier, you said that > in the case where FSDB crashed, lbase was -1. This seems like a bug, > right there, even before l[i2] is dereferenced: lbase should be a > non-negative number, right? Only if the function was compiled with -g. If line number info for a module is not available, lbase will always be -1. Nothing wrong since the next entry in that case will be the declaration of the next function and the loop will stop anyway. However the point that lbase = -1 may be used as a flag to stop processing for line numbers may be the safest way to handle this. In fact I did that and found that fsdb works as expected and no crash happens. > This leads me to another aspect of the code that I find unsafe. Look > how lbase is computed: > > > int lbase = f_aux[i+1].x_sym.x_misc.x_lnsz.x_lnno - 1; > > I'm worried about the f_aux[i+1] thing. Here's how f_aux is defined: > > f_symtab = (SYMENT *)malloc(f_fh.f_nsyms * SYMESZ); > fread(f_symtab, SYMESZ, f_fh.f_nsyms, fd); > f_aux = (AUXENT *)f_symtab; > > In other words, f_aux is an array of f_fh.f_nsyms elements, exactly > like f_symtab is. So f_aux[i+1] looks beyond the end of f_symtab[] > array on the last pass through the loop, since then the index i has > the value f_fh.f_nsyms. Not to worry! The loop index is deviously modified here: i += f_symtab[i].e_numaux > Maybe that's how that negative lbase is born? I am afraid that is quite unlikely. > Could you tell what is > the value of i when the offending loop corrupts the pointer maintained > by `malloc'? Sure. But the value depends on the manner in which the code was compiled. In my case (-g, without optimisations) the last line number entry corresponds to the the module "___udivdi3" in libgcc2.a. and is symbol number i = 2005. The opening brace for this module is symbol number i = 2007, because of one auxillary entry for the previous symbol and the closing brace for this function has symbol number i = 2009, again one aux entry for the previous symbol. As expected (since this is the symbol whose line number entry is last), mallocs tables get corrupted exactly after process_coff reads this module. Thank you very much for your interest. I hope that you will excuse my inarticulateness in matters C. For example I could not find any other term for "function declaration" for which I mean the line that is the function declaration, but without the trailing ";"