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: [RFA/commit+doco 2/2] Windows x64 SEH unwinder.


On 01/09/2013 04:28 PM, Tristan Gingold wrote:

>>> I don't really see a real way of supporting both old and new versions
>>> of GCC, unless we have a way of more finely ordering the unwinders.
>>
>> What specific finer order where you considering would be needed to
>> fix this?
> 
> Joel once proposed to activate this unwinder if the CU is compiled
> by gcc 4.6 or older.

I don't think you need to have a way of more finely ordering
the unwinders for that.  AFAICS, we can make the sniffer
return false in that case.  I had understood him
as meaning something about making the whole prepend/append
mechanisms more finer grained somehow.

Checking the CU/producer is kind of the obvious choice.
It requires debug info though.

>> Maybe detect if the whole module (exe/dll) the PC points at
>> contains any SEH (even if not for PC), and skip the SEH unwinder
>> if not?  Is that possible?
> 
> Yes, but useless.  There are SEH info in crt0.

You mean, the parts that are in mingw, right?  I'd assume
any bits in gcc to only contain SEH in >=4.7.  Yeah,
seems like that wouldn't work for static binaries.

>>> +     http://msdn.microsoft.com/en-us/library/tawsa7cb.aspx
>>> +     Furthermore, according to RtlVirtualUnwind, the complete list of
>>> +     epilog marker is:
>>> +     - ret                      [c3]
>>> +     - ret n                    [c2 imm16]
>>> +     - rep ret                  [f3 c3]
>>> +     - jmp imm8 | imm32         [eb rel8] or [e9 rel32]
>>> +     - jmp qword ptr imm32                 - not handled
>>> +     - rex jmp reg              [4X ff eY]
>>> +     I would add:
>>> +     -  pop reg                 [41 58-5f] or [58-5f]
>>
>> If you add "pop", and you'd add "add" and "lea" as well,
>> right?  It's not super clear what "marker" means, but all
>> the instructions listed by RtlVirtualUnwind's docs are
>> control flow instructions.  And then, in the url you point
>> above, we see:
>>
>> "These are the only legal forms for an epilog. It must consist of either
>> an add RSP,constant or lea RSP,constant[FPReg], followed by a series
>> of zero or more 8-byte register pops and a return or a jmp. (Only
>> a subset of jmp statements are allowable in the epilog."
>>
>> So from both docs it seems to me that "marker" is always the
>> last instruction of the epilogue, and that "pop" is not called
>> a marker.
> 
> This is in fact an optimization. If we found a pop, followed by
> an epilog marker, there is not need to decode unwind info.

I don't understand.  pops will always be followed by a marker.
How can that be an optimization?

> 
>> Furthermore,
>>
>>> +
>>> +     We don't care about the instruction deallocating the frame:
>>> +     if it hasn't been executed, we can safely decode the insns;
>>> +     if it has been executed, the following epilog decoding will
>>> +     work.  */
>>> +  CORE_ADDR pc = cache->pc;
>>> +  CORE_ADDR cur_sp = cache->sp;
>>> +  struct gdbarch *gdbarch = get_frame_arch (this_frame);
>>> +  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
>>> +
>>> +  while (1)
>>> +    {
>>> +      gdb_byte op;
>>> +      gdb_byte rex;
>>> +
>>> +      if (target_read_memory (pc, &op, 1) != 0)
>>> +	return -1;
>>> +
>>> +      if (op == 0xc3)
>>> +	{
>>> +	  /* Ret.  */
>>> +	  cache->prev_rip_addr = cur_sp;
>>> +	  cache->prev_sp = cur_sp + 8;
>>> +	  return 1;
>>> +	}
>>> +      else if (op == 0xeb)
>>> +	{
>>> +	  /* jmp rel8  */
>>> +	  gdb_byte rel8;
>>> +
>>> +	  if (target_read_memory (pc + 1, &rel8, 1) != 0)
>>> +	    return -1;
>>> +	  pc = pc + 2 + (signed char) rel8;
>>
>> this implementation follows jumps, and keeps looping
>> at the jump destination.
> 
> Right.
> 
>>  I see no hint that such thing
>> as an epilogue with a jump is a valid epilogue, only that
>> a jmp is only valid as replacement for ret.
>> Can you show an example where following the jmp until
>> you see a ret is necessary?
> 
> Interesting remark. First attempt to answer is the case of a
> jump to an epilogue.

The jump to an epilogue would not be part of the epilogue.

> But I may miss your point.

My point is that the docs say the epilogue has this rigid
format that always ends in a marker, and that a marker is
a ret or a jmp (therefore calling "pop" a marker as in the
"I would add" comment seems to me misleading).  The code
continues following the jmp, so it makes me believe the code
is erroneously decoding something after the jmp that is
not an epilogue (the caller or perhaps a tailcall).

-- 
Pedro Alves


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