This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
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