This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: GDB internal error in pc_in_thread_step_range


On 2018-12-16 12:22 p.m., Eli Zaretskii wrote:
>> Cc: gdb-patches@sourceware.org
>> From: Simon Marchi <simon.marchi@polymtl.ca>
>> Date: Sun, 16 Dec 2018 12:06:07 -0500
>>
>> I can't see any mention or even clue that these values would have a special
>> meaning, it looks to me like they are returned by mistake more than on purpose.
> 
> If the start address is zero and the length is zero, this is what we
> will get, right?

Technically, I think this is what we would get if address was 0 and length 1.  If
address was 0 and length 0 (en empty range?), *ENDADDR would also be 0.

>>>   cache_pc_function_low = BMSYMBOL_VALUE_ADDRESS (msymbol);
>>>   cache_pc_function_name = MSYMBOL_LINKAGE_NAME (msymbol.minsym);
>>>   cache_pc_function_section = section;
>>>   cache_pc_function_high = minimal_symbol_upper_bound (msymbol);
>>>   cache_pc_function_block = nullptr;
>>>
>>> This is part of find_pc_partial_function.  I verified that
>>> minimal_symbol_upper_bound returns 1 in this case, and that this value
>>> of 1 is assigned here:
>>>
>>>   obj_section = MSYMBOL_OBJ_SECTION (minsym.objfile, minsym.minsym);
>>>   if (MSYMBOL_LINKAGE_NAME (msymbol + i) != NULL
>>>       && (MSYMBOL_VALUE_ADDRESS (minsym.objfile, msymbol + i)
>>> 	  < obj_section_endaddr (obj_section)))
>>>     result = MSYMBOL_VALUE_ADDRESS (minsym.objfile, msymbol + i); <<<<<<
>>>   else
>>>
>>> Once again, I'm not an expert on this stuff, but just thinking about
>>> the situation, what else could GDB return in this case?
>>
>> This means that BMSYMBOL_VALUE_ADDRESS (msymbol) returned 0?  What is that symbol?
> 
> Please help me understand what field of which struct do I need to show
> to answer that question.  IOW, when you ask "what is that symbol",
> what kind of answer do you expect me to provide?

In particular, I am looking for why we identified the symbol represented by MSYMBOL
as the function containing PC.  What is this symbol's name?  That would be printed
with MSYMBOL_LINKAGE_NAME(msymbol.minsym), I think.  Or if you expand,
"msymbol.minsym.mginfo.name".

What is its address (should be msymbol.minsym.mginfo.value.address)?

> 
>> How come by looking up a symbol for PC (what is PC's value, btw) we found this symbol?
> 
> It comes from this loop, just before the above-mentioned snippet from
> minimal_symbol_upper_bound:
> 
>   msymbol = minsym.minsym;
>   section = MSYMBOL_SECTION (msymbol);
>   for (i = 1; MSYMBOL_LINKAGE_NAME (msymbol + i) != NULL; i++)
>     {
>       if ((MSYMBOL_VALUE_RAW_ADDRESS (msymbol + i)
> 	   != MSYMBOL_VALUE_RAW_ADDRESS (msymbol))
> 	  && MSYMBOL_SECTION (msymbol + i) == section)
> 	break;
>     }

Actually, I think I would investigate this line in find_pc_partial_function:

  msymbol = lookup_minimal_symbol_by_pc_section (mapped_pc, section);

This is where we ask the question "which is the closest minimal symbol that is <= than PC".
I would then try to see if the returned msymbol makes sense.  If you can give its name and
address, it would be a good start.  If we find it doesn't make sense, I'd start looking at
why lookup_minimal_symbol_by_pc_section returned that.

I am not familiar with PE/Windows executables, but I would try to compare what I see there
with the output of "objdump -t" and "objdump -d" to see if the minimal symbols in GDB
correspond to something there.

>>> --- gdb/infrun.c~0	2018-07-04 18:41:59.000000000 +0300
>>> +++ gdb/infrun.c	2018-12-16 11:02:24.103425700 +0200
>>> @@ -2713,7 +2713,13 @@ resume_1 (enum gdb_signal sig)
>>>        displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf));
>>>      }
>>>  
>>> -  if (tp->control.may_range_step)
>>> +  if (tp->control.may_range_step
>>> +      /* If .step_range_start == 0 and .step_range_end == 1, we don't
>>> +	 really know the step range, so don't check in that case.
>>> +	 (This is known to happen on MinGW when stepping the program
>>> +	 epilogue code after 'main' returns.)  */
>>> +      && !(tp->control.step_range_start == 0x0
>>> +	   && tp->control.step_range_end == 0x1))
>>>      {
>>>        /* If we're resuming a thread with the PC out of the step
>>>  	 range, then we're doing some nested/finer run control
>>
>> This is treating 0 and 1 as special values, which I don't think they are.
> 
> It definitely looked to me as if they were special.  But I will try to
> answer your other questions, maybe I was wrong.

I think that for "absence of range", a 0/0 value would make more sense.  But that isn't
how find_pc_partial_function is documented to work:

   If it succeeds, it sets *NAME, *ADDRESS, and *ENDADDR to real
   information and returns 1.  If it fails, it sets *NAME, *ADDRESS
   and *ENDADDR to zero and returns 0.

find_pc_partial_function returns 1 in our case, and the information it returns in
*ADDRESS and *ENDADDR doesn't seem "real", as the comment says.

Also, if you read to complete comment of find_pc_partial_function (in symtab.h), it
reinforces the idea that the *ADDRESS <= PC < *ENDADDR invariant should hold.

Simon


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]