From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6600 invoked by alias); 4 Jun 2002 11:35:17 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 6576 invoked from network); 4 Jun 2002 11:35:11 -0000 Received: from unknown (HELO kerberos.suse.cz) (195.47.106.10) by sources.redhat.com with SMTP; 4 Jun 2002 11:35:11 -0000 Received: from chimera.suse.cz (chimera.suse.cz [10.20.0.2]) by kerberos.suse.cz (SuSE SMTP server) with ESMTP id 640E959D354; Tue, 4 Jun 2002 13:35:10 +0200 (CEST) Received: from suse.cz (naga.suse.cz [10.20.1.16]) by chimera.suse.cz (8.11.0/8.11.0/SuSE Linux 8.11.0-0.4) with ESMTP id g54BZ9l23362; Tue, 4 Jun 2002 13:35:09 +0200 X-Authentication-Warning: chimera.suse.cz: Host naga.suse.cz [10.20.1.16] claimed to be suse.cz Message-ID: <3CFCA5ED.7010201@suse.cz> Date: Tue, 04 Jun 2002 04:35:00 -0000 From: Michal Ludvig Organization: SuSE CR User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0rc2) Gecko/20020510 X-Accept-Language: cs, cz, en MIME-Version: 1.0 To: Andrew Cagney Cc: GDB Patches , Elena Zannoni Subject: Re: [RFA] dwarf2cfi.c improvements References: <3CF79DA0.9040404@suse.cz> <3CFB727E.10005@cygnus.com> Content-Type: multipart/mixed; boundary="------------040309080506070503070500" X-SW-Source: 2002-06/txt/msg00059.txt.bz2 This is a multi-part message in MIME format. --------------040309080506070503070500 Content-Type: text/plain; charset=ISO-8859-2; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1069 Andrew Cagney wrote: > Can I suggest pulling the error() and internal_error() message changes > out, cleaning them up, and then committing them separatly. Better > messages (eg printing the reason for a bad switch) are always a good idea. > > That also has the benefit of trimming your patch back. Well, this is the patch without unrelated message changes. Can I commit it? It seems to be quite stable in our everyday use... 2002-05-31 Michal Ludvig * dwarf2cfi.c (dwarf_frame_buffer): Delete. (read_encoded_pointer): Add new argument, warn on indirect pointers. (execute_cfa_program): Warn on relative addressing. (dwarf2_build_frame_info): Only call parse_frame_info for .debug_frame and .eh_frame. (parse_frame_info): New, derived from dwarf2_build_frame_info, fixed augmentation handling, added relative addressing, ignore duplicate FDEs. Added comments. Michal Ludvig -- * SuSE CR, s.r.o * mludvig@suse.cz * +420 2 9654 5373 * http://www.suse.cz --------------040309080506070503070500 Content-Type: text/plain; name="cfi-huge5.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="cfi-huge5.diff" Content-length: 17098 Index: dwarf2cfi.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvs/src/src/gdb/dwarf2cfi.c,v retrieving revision 1.7 diff -c -3 -p -r1.7 dwarf2cfi.c *** dwarf2cfi.c 22 May 2002 13:21:19 -0000 1.7 --- dwarf2cfi.c 4 Jun 2002 11:28:06 -0000 *************** extern file_ptr dwarf_frame_offset; *** 188,195 **** extern unsigned int dwarf_frame_size; extern file_ptr dwarf_eh_frame_offset; extern unsigned int dwarf_eh_frame_size; -=20 - static char *dwarf_frame_buffer; =0C =20=20 extern char *dwarf2_read_section (struct objfile *objfile, file_ptr offse= t, --- 188,193 ---- *************** static ULONGEST read_uleb128 (bfd *abfd, *** 217,223 **** static LONGEST read_sleb128 (bfd *abfd, char **p); static CORE_ADDR read_pointer (bfd *abfd, char **p); static CORE_ADDR read_encoded_pointer (bfd *abfd, char **p, ! unsigned char encoding); =20=20 static LONGEST read_initial_length (bfd *abfd, char *buf, int *bytes_read= ); static ULONGEST read_length (bfd *abfd, char *buf, int *bytes_read, --- 215,221 ---- static LONGEST read_sleb128 (bfd *abfd, char **p); static CORE_ADDR read_pointer (bfd *abfd, char **p); static CORE_ADDR read_encoded_pointer (bfd *abfd, char **p, ! unsigned char encoding, int *flag_pcrel); =20=20 static LONGEST read_initial_length (bfd *abfd, char *buf, int *bytes_read= ); static ULONGEST read_length (bfd *abfd, char *buf, int *bytes_read, *************** read_pointer (bfd *abfd, char **p) *** 487,496 **** } =20=20 static CORE_ADDR ! read_encoded_pointer (bfd *abfd, char **p, unsigned char encoding) { CORE_ADDR ret; !=20 switch (encoding & 0x0f) { case DW_EH_PE_absptr: --- 485,497 ---- } =20=20 static CORE_ADDR ! read_encoded_pointer (bfd *abfd, char **p, unsigned char encoding,=20 ! int *flag_pcrel) { CORE_ADDR ret; !=20=20=20 ! if (flag_pcrel) *flag_pcrel =3D 0; !=20=20=20 switch (encoding & 0x0f) { case DW_EH_PE_absptr: *************** read_encoded_pointer (bfd *abfd, char ** *** 530,541 **** } =20=20 if (ret !=3D 0) ! switch (encoding & 0xf0) { case DW_EH_PE_absptr: break; case DW_EH_PE_pcrel: ! ret +=3D (CORE_ADDR) *p; break; case DW_EH_PE_textrel: case DW_EH_PE_datarel: --- 531,543 ---- } =20=20 if (ret !=3D 0) ! { ! switch (encoding & 0x70) { case DW_EH_PE_absptr: break; case DW_EH_PE_pcrel: ! if (flag_pcrel) *flag_pcrel =3D 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"); } +=20=20=20=20=20 + if (encoding & DW_EH_PE_indirect) + warning ("CFI: Unsupported pointer encoding: DW_EH_PE_indirect"); + } =20=20 return ret; } *************** execute_cfa_program ( struct objfile *ob *** 597,602 **** --- 603,609 ---- unsigned char insn =3D *insn_ptr++; ULONGEST reg, uoffset; LONGEST offset; + int flag_pcrel; =20=20 if (insn & DW_CFA_advance_loc) fs->pc +=3D (insn & 0x3f) * fs->code_align; *************** execute_cfa_program ( struct objfile *ob *** 618,624 **** { case DW_CFA_set_loc: fs->pc =3D read_encoded_pointer (objfile->obfd, &insn_ptr, ! fs->addr_encoding); break; =20=20 case DW_CFA_advance_loc1: --- 625,637 ---- { case DW_CFA_set_loc: fs->pc =3D read_encoded_pointer (objfile->obfd, &insn_ptr, ! fs->addr_encoding, &flag_pcrel); ! if (flag_pcrel) ! { ! warning ("CFI: DW_CFA_set_loc uses relative addressing at pc=3D%p"= ,=20 ! (void*)fs->pc); ! fs->pc +=3D (CORE_ADDR)insn_ptr; ! } break; =20=20 case DW_CFA_advance_loc1: *************** compare_fde_unit (const void *a, const v *** 1372,1409 **** =20=20 /* Build the cie_chunks and fde_chunks tables from informations in .debug_frame section. */ ! void ! dwarf2_build_frame_info (struct objfile *objfile) { bfd *abfd =3D objfile->obfd; ! char *start =3D NULL; ! char *end =3D NULL; ! int from_eh =3D 0; =20=20 obstack_init (&unwind_tmp_obstack); =20=20 ! dwarf_frame_buffer =3D 0; !=20 ! if (dwarf_frame_offset) ! { ! dwarf_frame_buffer =3D dwarf2_read_section (objfile, ! dwarf_frame_offset, ! dwarf_frame_size); !=20 ! start =3D dwarf_frame_buffer; ! end =3D dwarf_frame_buffer + dwarf_frame_size; ! } ! else if (dwarf_eh_frame_offset) ! { ! dwarf_frame_buffer =3D dwarf2_read_section (objfile, ! dwarf_eh_frame_offset, ! dwarf_eh_frame_size); !=20 ! start =3D dwarf_frame_buffer; ! end =3D dwarf_frame_buffer + dwarf_eh_frame_size; =20=20 ! from_eh =3D 1; ! } =20=20 if (start) { --- 1385,1413 ---- =20=20 /* Build the cie_chunks and fde_chunks tables from informations in .debug_frame section. */ ! static void ! parse_frame_info (struct objfile *objfile, file_ptr frame_offset,=20 ! unsigned int frame_size, int eh_frame) { bfd *abfd =3D objfile->obfd; ! asection *curr_section_ptr; ! char *start =3D NULL, *end =3D NULL, *frame_buffer =3D NULL; ! char *curr_section_name, *aug_data; ! struct cie_unit *last_cie=3DNULL; ! int last_dup_fde =3D 0, aug_len, i; ! CORE_ADDR curr_section_vma =3D 0; =20=20 obstack_init (&unwind_tmp_obstack); =20=20 ! frame_buffer =3D dwarf2_read_section (objfile, frame_offset, frame_size= ); =20=20 ! start =3D frame_buffer; ! end =3D frame_buffer + frame_size; !=20=20=20 ! curr_section_name =3D eh_frame?".eh_frame":".debug_frame"; ! curr_section_ptr =3D bfd_get_section_by_name (abfd, curr_section_name); ! if (curr_section_ptr) ! curr_section_vma =3D curr_section_ptr->vma; =20=20 if (start) { *************** dwarf2_build_frame_info (struct objfile=20 *** 1411,1419 **** { unsigned long length; ULONGEST cie_id; ! ULONGEST unit_offset =3D start - dwarf_frame_buffer; ! int bytes_read; ! int dwarf64; char *block_end; =20=20 length =3D read_initial_length (abfd, start, &bytes_read); --- 1415,1422 ---- { unsigned long length; ULONGEST cie_id; ! ULONGEST unit_offset =3D start - frame_buffer; ! int bytes_read, dwarf64, flag_pcrel; char *block_end; =20=20 length =3D read_initial_length (abfd, start, &bytes_read); *************** dwarf2_build_frame_info (struct objfile=20 *** 1421,1430 **** dwarf64 =3D (bytes_read =3D=3D 12); block_end =3D start + length; =20=20 cie_id =3D read_length (abfd, start, &bytes_read, dwarf64); start +=3D bytes_read; =20=20 ! if ((from_eh && cie_id =3D=3D 0) || is_cie (cie_id, dwarf64)) { struct cie_unit *cie =3D cie_unit_alloc (); char *aug; --- 1424,1439 ---- dwarf64 =3D (bytes_read =3D=3D 12); block_end =3D start + length; =20=20 + if(length =3D=3D 0) + { + start =3D block_end; + continue; + } +=20 cie_id =3D read_length (abfd, start, &bytes_read, dwarf64); start +=3D bytes_read; =20=20 ! if ((eh_frame && cie_id =3D=3D 0) || is_cie (cie_id, dwarf64)) { struct cie_unit *cie =3D cie_unit_alloc (); char *aug; *************** dwarf2_build_frame_info (struct objfile=20 *** 1440,1523 **** start++; /* version */ =20=20 cie->augmentation =3D aug =3D start; ! while (*start) ! start++; ! start++; /* skip past NUL */ =20=20 cie->code_align =3D read_uleb128 (abfd, &start); cie->data_align =3D read_sleb128 (abfd, &start); cie->ra =3D read_1u (abfd, &start); =20=20 if (*aug =3D=3D 'z') { ! int xtra =3D read_uleb128 (abfd, &start); ! start +=3D xtra; ++aug; } =20=20 while (*aug !=3D '\0') { if (aug[0] =3D=3D 'e' && aug[1] =3D=3D 'h') { ! start +=3D sizeof (void *); ! aug +=3D 2; } else if (aug[0] =3D=3D 'R') { ! cie->addr_encoding =3D *start++; ! aug +=3D 1; } ! else if (aug[0] =3D=3D 'P') { ! CORE_ADDR ptr; ! ptr =3D read_encoded_pointer (abfd, &start, ! cie->addr_encoding); ! aug +=3D 1; } else ! warning ("%s(): unknown augmentation", __func__); } =20=20 ! cie->data =3D start; ! cie->data_length =3D block_end - start; } else { struct fde_unit *fde; struct cie_unit *cie; =20=20 ! fde_chunks_need_space (); ! fde =3D fde_unit_alloc (); !=20 ! fde_chunks.array[fde_chunks.elems++] =3D fde; !=20=09=20=20=20=20=20=20 ! fde->initial_location =3D read_pointer (abfd, &start) ! + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); ! fde->address_range =3D read_pointer (abfd, &start); !=20 ! cie =3D cie_chunks; ! while(cie) { ! if (cie->objfile =3D=3D objfile) { ! if (from_eh && (cie->offset =3D=3D (unit_offset + bytes_read - cie_id= ))) ! break; ! if (!from_eh && (cie->offset =3D=3D cie_id)) ! break; } =20=20 ! cie =3D cie->next; } -=20=09=20=20=20=20 - if (!cie) - error ("%s(): can't find CIE pointer", __func__); - fde->cie_ptr =3D cie; =20=20 ! if (cie->augmentation[0] =3D=3D 'z') ! read_uleb128 (abfd, &start); =20=20 ! fde->data =3D start; ! fde->data_length =3D block_end - start; } start =3D block_end; } --- 1449,1626 ---- start++; /* version */ =20=20 cie->augmentation =3D aug =3D start; ! while (*start++); /* Skips last NULL as well */ =20=20 cie->code_align =3D read_uleb128 (abfd, &start); cie->data_align =3D read_sleb128 (abfd, &start); cie->ra =3D read_1u (abfd, &start); =20=20 + /* Augmentation: + z Indicates that a uleb128 is present to size the + augmentation section. + L Indicates the encoding (and thus presence) of + an LSDA pointer in the FDE augmentation. + R Indicates a non-default pointer encoding for + FDE code pointers. + P Indicates the presence of an encoding + language + personality routine in the CIE augmentation. +=20=09=20=20=20=20=20=20 + [This info comes from GCC's dwarf2out.c] + */ if (*aug =3D=3D 'z') { ! aug_len =3D read_uleb128 (abfd, &start); ! aug_data =3D start; ! start +=3D aug_len; ++aug; } =20=20 + cie->data =3D start; + cie->data_length =3D block_end - cie->data; +=20=09=20=20=20=20=20=20 while (*aug !=3D '\0') { if (aug[0] =3D=3D 'e' && aug[1] =3D=3D 'h') { ! aug_data +=3D sizeof (void *); ! aug++; } else if (aug[0] =3D=3D 'R') + cie->addr_encoding =3D *aug_data++; + else if (aug[0] =3D=3D 'P') { ! CORE_ADDR pers_addr; ! int pers_addr_enc; !=20=09=09=20=20=20=20=20=20 ! pers_addr_enc =3D *aug_data++; ! /* We use (pers_addr_enc & 0x7f) to avoid=20 ! warning about indirect relative addressing. ! We don't need pers_addr value anyway and so we=20 ! don't care if it is correct :-) */ ! pers_addr =3D read_encoded_pointer (abfd, &aug_data, ! pers_addr_enc & 0x7f, NULL); } ! else if (aug[0] =3D=3D 'L' && eh_frame) { ! int lsda_addr_enc; !=20 ! /* Perhaps we should save this to CIE for later use? ! Do we need it for something in GDB? */ ! lsda_addr_enc =3D *aug_data++; } else ! warning ("CFI warning: unknown augmentation \"%c\"" ! " in \"%s\" of\n" ! "\t%s", aug[0], curr_section_name, objfile->name); ! aug++; } =20=20 ! last_cie =3D cie; } else { struct fde_unit *fde; struct cie_unit *cie; + int dup =3D 0; + CORE_ADDR init_loc, base_offset; =20=20 ! /* We assume that debug_frame is in order=20 ! CIE,FDE,CIE,FDE,FDE,... and thus the CIE for this FDE ! should be stored in last_cie pointer. If not, we'll=20 ! try to find it by the older way. */ ! if(last_cie) ! cie =3D last_cie; ! else { ! warning ("CFI: last_cie =3D=3D NULL. " ! "Perhaps a malformed %s section in '%s'...?\n",=20 ! curr_section_name, objfile->name); !=20 ! cie =3D cie_chunks; ! while(cie) { ! if (cie->objfile =3D=3D objfile) ! { ! if (eh_frame &&=20 ! (cie->offset =3D=3D (unit_offset + bytes_read - cie_id))) ! break; ! if (!eh_frame && (cie->offset =3D=3D cie_id)) ! break; ! } !=20 ! cie =3D cie->next; } + if (!cie) + error ("CFI: can't find CIE pointer");=20 + } =20=20 ! /* start-frame_buffer gives offset from=20 ! the beginning of actual section. */ ! base_offset =3D curr_section_vma + start - frame_buffer; !=20=09=09=20=20=20=20=20=20 ! init_loc =3D read_encoded_pointer (abfd, &start,=20 ! cie->addr_encoding, &flag_pcrel); !=20=09=20=20=20=20=20=20 ! if (flag_pcrel) ! init_loc +=3D base_offset; !=20=09=20=20=20=20=20=20 ! /* For relocatable objects we must add an offset telling ! where the section is actually mapped in the memory. */ ! init_loc +=3D ANOFFSET (objfile->section_offsets,=20 ! SECT_OFF_TEXT (objfile)); !=20=09 ! /* If we have both .debug_frame and .eh_frame present in=20 ! a file, we must eliminate duplicate FDEs. For now we'll=20 ! run through all entries in fde_chunks and check it one=20 ! by one. Perhaps in the future we can implement a faster=20 ! searching algorithm. */ ! /* eh_frame=3D=3D2 indicates, that this file has an already=20 ! parsed .debug_frame too. When eh_frame=3D=3D1 it means, that no ! .debug_frame is present and thus we don't need to check for ! duplicities. eh_frame=3D=3D0 means, that we parse .debug_frame ! and don't need to care about duplicate FDEs, because ! .debug_frame is parsed first. */ ! for(i =3D 0; eh_frame =3D=3D 2 && i < fde_chunks.elems; i++) ! { ! /* We assume that FDEs in .debug_frame and .eh_frame=20 ! have the same order (if they are present, of course). ! If we find a duplicate entry for one FDE and save ! it's index to last_dup_fde it's very likely, that=20 ! we'll find an entry for the following FDE right after=20 ! the previous one. Thus in many cases we'll run this=20 ! loop only once. */ ! last_dup_fde =3D (last_dup_fde + i) % fde_chunks.elems; ! if(fde_chunks.array[last_dup_fde]->initial_location=20 ! =3D=3D init_loc) ! { ! dup=3D1; ! break; ! } } =20=20 ! /* Allocate a new entry only if this FDE isn't a duplicate of ! something we have already seen. */ ! if(!dup) ! { ! fde_chunks_need_space (); ! fde =3D fde_unit_alloc (); =20=20 ! fde_chunks.array[fde_chunks.elems++] =3D fde; !=20=09=09=20=20=20=20=20=20 ! fde->initial_location =3D init_loc; ! fde->address_range =3D read_encoded_pointer (abfd, &start, ! cie->addr_encoding, NULL); !=20 ! fde->cie_ptr =3D cie; !=20 ! /* Here we intentionally ignore augmentation data ! from FDE, because we don't need them. */ ! if (cie->augmentation[0] =3D=3D 'z') ! start +=3D read_uleb128 (abfd, &start); !=20 ! fde->data =3D start; ! fde->data_length =3D block_end - start; ! } } start =3D block_end; } *************** dwarf2_build_frame_info (struct objfile=20 *** 1525,1531 **** sizeof (struct fde_unit *), compare_fde_unit); } } ! =0C =20=20 /* Return the frame address. */ CORE_ADDR --- 1628,1655 ---- sizeof (struct fde_unit *), compare_fde_unit); } } !=20 ! /* We must parse both .debug_frame section and .eh_frame because=20 ! not all frames must be present in both of these sections. */ ! void ! dwarf2_build_frame_info (struct objfile *objfile) ! { ! int eh_frame; !=20 ! /* If we have .debug_frame then the parser is called with=20 ! eh_frame=3D=3D0 for .debug_frame and eh_frame=3D=3D2 for .eh_frame, ! otherwise it's only called once for .eh_frame with argument ! eh_frame=3D=3D1 */ ! eh_frame =3D 0; !=20 ! if (dwarf_frame_offset) ! parse_frame_info (objfile, dwarf_frame_offset,=20 ! dwarf_frame_size, eh_frame++); !=20 ! if (dwarf_eh_frame_offset) ! parse_frame_info (objfile, dwarf_eh_frame_offset,=20 ! dwarf_eh_frame_size, eh_frame+1); ! } =20=20 /* Return the frame address. */ CORE_ADDR --------------040309080506070503070500--