[RFA] dwarf2cfi.c improvements

Elena Zannoni ezannoni@redhat.com
Wed Jun 19 06:48:00 GMT 2002


Michal Ludvig writes:
 > Elena Zannoni wrote:
 > > Michal Ludvig writes:
 > >  >  > Or alternatively, could you have the function read_encoded_pointer
 > >  >  > emit the warning itself?
 > >  > 
 > >  > In some cases PC-relative addressing is valid, but sometimes it is not 
 > >  > (or at least is not used). The warning is there only once.
 > >  > 
 > >  >  > After all, none of
 > >  >  > the other error/warning messages are that detailed, they don't print
 > >  >  > the PC value. I noticed that in a couple of the calls to
 > >  >  > read_encoded_pointer the code doesn't care about emitting the warning,
 > >  >  > why? Or add a pc parameter for the purpose of the warning.
 > >  > 
 > >  > There are four occurences:
 > >  > - In DW_CFA_set_loc I don't (yet) handle pcrel addressing, because I 
 > >  > have never seen it in .*_frame. That's why I print a warning - If I'll 
 > >  > ever see it I'll implement support for it.
 > > 
 > > OK. But still, the warning should come from inside the function
 > > itself. 
 > 
 > I have introducend new function pointer_encoding() that the function 
 > calling read_encoded_pointer() may invoke to see what was returned and 
 > how to handle it. I'm convinced, that it's the caller's responsibility 
 > to deal with different PE's (pointer encodings), because sometimes some 
 > of them are valid, sometimes not. If I'd just pass base_addr into the 
 > read_enc_ptr() how would I know whether it was handled correctly. There 
 > might be a situation, that the pointer would be encoded either in pcrel 
 > or in funcrel format - then I should decide afterwards how to compute 
 > the base address, shouldn't I?
 > 

Much better. This makes the code a bit easier to understand. The
previous version of the function was trying to do too much.

 > > I was thinking you needed to do it outside, to have the
 > > fs->pc available to be printed in the warning, but that value actually
 > > comes from inside the function itself, so it doesn't need to be separate.
 > > 
 > >  > - When reading pers_addr I don't care about the return value at all. I 
 > >  > just need to advance the pointer to data.
 > > 
 > > Actually, do you need to call this function at all, if all you need to
 > > do is eat up some data? This is really overloading the function.
 > > Could you just call one of the read_* functions? 
 > 
 > No, because it depends on PE how much data should I eat up. I can have 
 > another function that would give me the number of bytes occupied by a 
 > given PE, but I don't believe it's a good idea. It's not called that 
 > often, that it could speed things up.
 > 

No need anymore, with the pointer_encoding function.

 > > But I see that gcc does
 > > some similar trick. BTW that function deals with alignment and the gdb
 > > version doesn't (yet?).
 > 
 > Hmm I didn't notice. I'll look at it. But it works as it is.
 > 

Keep it in mind if you see strange behaviors.

 > >  > - Init_loc reading takes care of pcrel addressing.
 > > 
 > > Yes, the bit that does it though, was inside read_encoded_pointer, and
 > > now it's not, and you also need to do an additional check, so I  would
 > > prefer doing it as it was before. 
 > 
 > It wasn't correct, anyway. I have written my reasons against this 
 > approach above.
 > 
 > > Could you instead add a new parmeter *base* instead of the flag?  In
 > > the DW_CFA_set_loc case, base would be NULL while here it would be
 > > base_offset, so you could still distinguish the two cases.
 > 
 > How can I know how to compute base_addr when I don't know whether the 
 > encoding is pcrel, textrel, funcrel, ...? I know these aren't used _now_ 
 > but at least hypothetically are possible.
 > 

Right. OK.

 > >  > - fde->address_range is always an absolute value, but encoded in a 
 > >  > pointer format. I don't care if it is in pcrel format or not - it's just 
 > >  > a difference between two pointers.
 > > 
 > > So that would work anyway, right?
 > 
 > I must only know in how many bytes it's encoded so that I advance the 
 > data pointer correctly. The value itself, either if encoded as pcrel, is 
 > always absolute. At least I hope so :-)
 > 
 > 
 > > I don't undersand this change:
 > > *** 530,541 ****
 > >       }
 > >   
 > >     if (ret != 0)
 > > !     switch (encoding & 0xf0)
 > >         {
 > >         case DW_EH_PE_absptr:
 > >         break;
 > >         case DW_EH_PE_pcrel:
 > > !       ret += (CORE_ADDR) *p;
 > >         break;
 > >         case DW_EH_PE_textrel:
 > >         case DW_EH_PE_datarel:
 > > --- 531,543 ----
 > >       }
 > >   
 > >     if (ret != 0)
 > > !   {
 > > !     switch (encoding & 0x70)
 > >         {
 > >         case DW_EH_PE_absptr:
 > >         break;
 > >         case DW_EH_PE_pcrel:
 > > !       if (flag_pcrel) *flag_pcrel = 1;
 > >         break;
 > >         case DW_EH_PE_textrel:
 > >         case DW_EH_PE_datarel:
 > > *************** read_encoded_pointer (bfd *abfd, char **
 > > *** 544,549 ****
 > > --- 546,555 ----
 > >         internal_error (__FILE__, __LINE__,
 > >                         "read_encoded_pointer: unknown pointer encoding");
 > >         }
 > > +     
 > > +     if (encoding & DW_EH_PE_indirect)
 > > +       warning ("CFI: Unsupported pointer encoding: DW_EH_PE_indirect");
 > > +   }
 > >   
 > >     return ret;
 > >   }
 > > 
 > > Why are you changing the mask from 0xf0 to 0x70 in the switch to avoid
 > > catching DW_EH_PE_indirect? Could you just add it to the case statement?
 > 
 > I can't because DW_EH_PE_indirect is independent on DW_EH_PE_*rel. Both 
 > PE_pcrel and PE_pcrel_indirect are possible. In fact, encoding variable 
 > contains three flags: size, encoding and (in)direct flag.
 > 

Ah, I see. 3 masks for 3 different things. Is there any way you can
add a comment about this?

 > All of them must be handled separately.
 > 
 > >  > > About the eh_frame part of the patch.
 > >  > > I don't really like the use of eh_frame as you have in dwarf2_build_frame_info.
 > >  > > Could you try to figure out a simpler way to deal with the two cases?
 > >  > > You could use an enumeration for eh_frame.
 > >  > 
 > >  > Well, yes, actually. But then I would have to change:
 > >  > if(eh_frame) ...
 > >  > to
 > >  > if(frame == EH_ONLY || frame == EH_SECOND) ...
 > >  > 
 > > 
 > > That is the idea, yes. It would be much more understandable to the
 > > reader.  
 > 
 > I have changed computing of this parameter in dwarf2_build_frame_info so 
 > that it is more readable now, but I'd leave 'eh_frame' as it is, because 
 > in most cases I don't care whether it's 1 or 2. The hack with 
 > eh_frame==2 is there just for speeding up things when looking for 
 > duplicate FDEs. I eh_frame is the only section parsed, then I don't have 
 > to be afraid that we already have a given FDE and don't have to check it 
 > at all.
 > 

Could you add a comment explaining the differences between the
eh_frame section and the debug_frame section? Only a couple, as far as
I know.

 > >  > What about making local macros IS_DEBUG_FRAME(), IS_EH_FRAME(), 
 > >  > IS_EH_FRAME_ONLY(), ...?
 > >  > 
 > > 
 > > How would those behave different from enums? If I am understanding your
 > > suggestion correctly, that is (macros are usually not introduced
 > > unless absolutely necessary).
 > 
 > IS_EH_FRAME would be true for both possible cases with eh_frame.
 > As I already said - usually I don't care whether it's parsed first or 
 > after debug_frame.
 > 
 > > Could you send me a unified diff? (don't need to send it to the list
 > > just to me). I'd appreciate that.
 > 
 > Yes. Included. It's against cvs rev 1.9.
 > 

A few little things:

 > +
 > +enum ptr_encoding
 > +pointer_encoding (unsigned char encoding)
 > +{
 > +  int ret;
 >  
 > +  if (encoding & DW_EH_PE_indirect)
 > +    warning ("CFI: Unsupported pointer encoding: DW_EH_PE_indirect");
 > +  
 > +  switch (encoding & 0x70)
 > +    {
 > +    case DW_EH_PE_absptr:
 > +    case DW_EH_PE_pcrel:
 > +    case DW_EH_PE_textrel:
 > +    case DW_EH_PE_datarel:
 > +    case DW_EH_PE_funcrel:
 > +      ret = encoding & 0x70;
 > +      break;
 > +    default:
 > +      internal_error (__FILE__, __LINE__,
 > +    		  "read_encoded_pointer: unknown pointer encoding");


The function name should be pointer_encoding.



 > +static void
 > +parse_frame_info (struct objfile *objfile, file_ptr frame_offset,
 > +		  unsigned int frame_size, int eh_frame)
 >  {
 >    bfd *abfd = objfile->obfd;
 > +  asection *curr_section_ptr;
 >    char *start = NULL;
 >    char *end = NULL;
 > -  int from_eh = 0;
 > +  char *frame_buffer = NULL;
 > +  char *curr_section_name, *aug_data;
 > +  struct cie_unit *last_cie = NULL;
 > +  int last_dup_fde = 0, aug_len, i;

Please put these on separate lines.



 > +			  if (eh_frame &&
 > +			      (cie->offset ==
 > +			       (unit_offset + bytes_read - cie_id)))

Please reformat this line.



 > +	      for (i = 0; eh_frame == 2 && i < fde_chunks.elems; i++)

Could you include the for loop in an if statement, instead of adding the
eh_frame==2 test?


 > +  int after_debug_frame=0;

Spaces.


ChangeLog?

Other than that approved.

Elena



More information about the Gdb-patches mailing list