This is the mail archive of the gdb-patches@sources.redhat.com 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]

Re: [PATCH RFA] DWARF v2.1 64-bit support



Looks ok to me. Nice catch on the .text index.

Go ahead, and add the coment as Stan suggested.

Elena


Kevin Buettner writes:
 > I request approval for committing the patch below.
 > 
 > I am working on a project which required me to add support for the
 > DWARF version 2.1 64-bit format.  In a nutshell, the 64-bit format
 > makes certain offset and length fields 64 bits wide instead of merely
 > 32 bits wide, thus making it possible to have DWARF2 sections that are
 > larger than 4GB in size.  (Crazy, huh?)  In order to tell which type of
 > format you have, the initial length field at the beginning of certain
 > sections will either have a normal 32-bit length, or an escape value
 > (0xffffffff) followed by a 64 bit length.  Once you've seen one of
 > these 64 bit lengths, you know that certain other fields in the same
 > section (section lengths and section offsets) will also be 64-bit
 > values.  Note that the initial length field with either occupy 4 or 12
 > bytes while the later length and offset fields will either occupy 4 or
 > 8 bytes.
 > 
 > The DWARF 2 draft document that I based these changes on is at:
 > 
 >     http://reality.sgi.com/dehnert_engr/dwarf/dwarf2p1-draft4-000720.pdf
 > 
 > Note that three hunks of the patch below deal with SECT_OFF_TEXT. 
 > These hunks fix a separate problem which is that the code assumed that
 > index 0 is the .text section index into objfiles->section_offsets.  If
 > desired, I can separate these three hunks out for separate
 > consideration.  (But it'll be easier for me if these changes are
 > approved en masse, which is why I'm trying it this way first.)
 > 
 > 	* dwarf2read.c (struct comp_unit_head): Add fields offset_size
 > 	and initial_length_size.  Change type of ``length'' field to long.
 > 	(read_initial_length, read_offset): New functions.
 > 	(dwarf2_build_psymtabs_easy): Call read_initial_length() instead
 > 	of just reading 4 bytes.
 > 	(read_comp_unit_head): Likewise; also, call read_offset() to
 > 	fetch the offset instead of just reading 4 bytes.
 > 	(dwarf_decode_lines): Likewise.
 > 	(read_comp_unit_head): Fix internal error message so it
 > 	accurately reflects the function in which the error occurred.
 > 	(dwarf2_build_psymtabs_hard): Properly account for size of the
 > 	initial length field in the section.
 > 	(read_attribute, dwarf2_get_ref_die_offset): Add a case for
 > 	DW_ORM_ref8.
 > 	(dwarf2_build_psymtabs_hard, psymtabs_to_symtab_1): Don't
 > 	assume that the .text section will have index 0 in the
 > 	section_offsets table.
 > 
 > Index: dwarf2read.c
 > ===================================================================
 > RCS file: /cvs/src/src/gdb/dwarf2read.c,v
 > retrieving revision 1.14
 > diff -u -p -r1.14 dwarf2read.c
 > --- dwarf2read.c	2000/07/30 01:48:25	1.14
 > +++ dwarf2read.c	2000/08/03 18:06:08
 > @@ -152,11 +152,14 @@ static unsigned int dwarf_str_size;
 >     translation, looks like this.  */
 >  struct comp_unit_head
 >    {
 > -    unsigned int length;
 > +    unsigned long length;
 >      short version;
 >      unsigned int abbrev_offset;
 >      unsigned char addr_size;
 >      unsigned char signed_addr_p;
 > +    unsigned int offset_size;	/* size of file offsets; either 4 or 8 */
 > +    unsigned int initial_length_size; /* size of the length field; either
 > +                                         4 or 12 */
 >    };
 >  
 >  /* The data in the .debug_line statement prologue looks like this.  */
 > @@ -604,6 +607,12 @@ static unsigned long read_8_bytes (bfd *
 >  static CORE_ADDR read_address (bfd *, char *ptr, const struct comp_unit_head *,
 >  			       int *bytes_read);
 >  
 > +static LONGEST read_offset (bfd *, char *, const struct comp_unit_head *,
 > +                            int *bytes_read);
 > +
 > +static LONGEST read_initial_length (bfd *, char *,
 > +                                    struct comp_unit_head *, int *bytes_read);
 > +
 >  static char *read_n_bytes (bfd *, char *, unsigned int);
 >  
 >  static char *read_string (bfd *, char *, unsigned int *);
 > @@ -898,8 +907,12 @@ dwarf2_build_psymtabs_easy (struct objfi
 >    pubnames_ptr = pubnames_buffer;
 >    while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size)
 >      {
 > -      entry_length = read_4_bytes (abfd, pubnames_ptr);
 > -      pubnames_ptr += 4;
 > +      struct comp_unit_head cu_header;
 > +      int bytes_read;
 > +
 > +      entry_length = read_initial_length (abfd, pubnames_ptr, &cu_header,
 > +                                         &bytes_read);
 > +      pubnames_ptr += bytes_read;
 >        version = read_1_byte (abfd, pubnames_ptr);
 >        pubnames_ptr += 1;
 >        info_offset = read_4_bytes (abfd, pubnames_ptr);
 > @@ -923,17 +936,20 @@ read_comp_unit_head (struct comp_unit_he
 >  		     char *info_ptr, bfd *abfd)
 >  {
 >    int signed_addr;
 > -  cu_header->length = read_4_bytes (abfd, info_ptr);
 > -  info_ptr += 4;
 > +  int bytes_read;
 > +  cu_header->length = read_initial_length (abfd, info_ptr, cu_header,
 > +                                           &bytes_read);
 > +  info_ptr += bytes_read;
 >    cu_header->version = read_2_bytes (abfd, info_ptr);
 >    info_ptr += 2;
 > -  cu_header->abbrev_offset = read_4_bytes (abfd, info_ptr);
 > -  info_ptr += 4;
 > +  cu_header->abbrev_offset = read_offset (abfd, info_ptr, cu_header,
 > +                                          &bytes_read);
 > +  info_ptr += bytes_read;
 >    cu_header->addr_size = read_1_byte (abfd, info_ptr);
 >    info_ptr += 1;
 >    signed_addr = bfd_get_sign_extend_vma (abfd);
 >    if (signed_addr < 0)
 > -    internal_error ("dwarf2_build_psymtabs_hard: dwarf from non elf file");
 > +    internal_error ("read_comp_unit_head: dwarf from non elf file");
 >    cu_header->signed_addr_p = signed_addr;
 >    return info_ptr;
 >  }
 > @@ -980,7 +996,7 @@ dwarf2_build_psymtabs_hard (struct objfi
 >  		 (long) (beg_of_comp_unit - dwarf_info_buffer));
 >  	  return;
 >  	}
 > -      if (beg_of_comp_unit + cu_header.length + 4
 > +      if (beg_of_comp_unit + cu_header.length + cu_header.initial_length_size
 >  	  > dwarf_info_buffer + dwarf_info_size)
 >  	{
 >  	  error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).",
 > @@ -1014,7 +1030,7 @@ dwarf2_build_psymtabs_hard (struct objfi
 >        DWARF_ABBREV_BUFFER (pst) = dwarf_abbrev_buffer;
 >        DWARF_ABBREV_SIZE (pst) = dwarf_abbrev_size;
 >        DWARF_LINE_BUFFER (pst) = dwarf_line_buffer;
 > -      baseaddr = ANOFFSET (objfile->section_offsets, 0);
 > +      baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 >  
 >        /* Store the function that reads in the rest of the symbol table */
 >        pst->read_symtab = dwarf2_psymtab_to_symtab;
 > @@ -1049,7 +1065,8 @@ dwarf2_build_psymtabs_hard (struct objfi
 >           also happen.) This happens in VxWorks.  */
 >        free_named_symtabs (pst->filename);
 >  
 > -      info_ptr = beg_of_comp_unit + cu_header.length + 4;
 > +      info_ptr = beg_of_comp_unit + cu_header.length 
 > +                                  + cu_header.initial_length_size;
 >      }
 >    do_cleanups (back_to);
 >  }
 > @@ -1314,7 +1331,7 @@ psymtab_to_symtab_1 (struct partial_symt
 >    dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER (pst);
 >    dwarf_abbrev_size = DWARF_ABBREV_SIZE (pst);
 >    dwarf_line_buffer = DWARF_LINE_BUFFER (pst);
 > -  baseaddr = ANOFFSET (pst->section_offsets, 0);
 > +  baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
 >    cu_header_offset = offset;
 >    info_ptr = dwarf_info_buffer + offset;
 >  
 > @@ -1362,7 +1379,7 @@ psymtab_to_symtab_1 (struct partial_symt
 >  	    }
 >  	}
 >      }
 > -  symtab = end_symtab (highpc + baseaddr, objfile, 0);
 > +  symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
 >  
 >    /* Set symtab language to language from DW_AT_language.
 >       If the compilation is from a C file generated by language preprocessors,
 > @@ -3370,6 +3387,10 @@ read_attribute (struct attribute *attr, 
 >        DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
 >        info_ptr += 4;
 >        break;
 > +    case DW_FORM_ref8:
 > +      DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
 > +      info_ptr += 8;
 > +      break;
 >      case DW_FORM_ref_udata:
 >        DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
 >        info_ptr += bytes_read;
 > @@ -3472,6 +3493,76 @@ read_address (bfd *abfd, char *buf, cons
 >    return retval;
 >  }
 >  
 > +/* Reads the initial length from a section.  The DWARF 2.1 specification
 > +   allows the initial length to take up either 4 bytes or 12 bytes.
 > +   If the first 4 bytes are 0xffffffff, then the next 8 bytes describe
 > +   the length and all offsets will be 8 bytes in length instead of 4.
 > +
 > +   The value returned via bytes_read should be used to increment
 > +   the relevant pointer after calling read_initial_length().
 > +   
 > +   As a side effect, this function sets the fields initial_length_size
 > +   and offset_size in cu_header to the values appropriate for the
 > +   length field.  (The format of the initial length field determines
 > +   the width of file offsets to be fetched later with fetch_offset().) */
 > +
 > +static LONGEST
 > +read_initial_length (bfd *abfd, char *buf, struct comp_unit_head *cu_header,
 > +                     int *bytes_read)
 > +{
 > +  LONGEST retval = 0;
 > +
 > +  retval = bfd_get_32 (abfd, (bfd_byte *) buf);
 > +
 > +  if (retval == 0xffffffff)
 > +    {
 > +      retval = bfd_get_64 (abfd, (bfd_byte *) buf + 4);
 > +      *bytes_read = 12;
 > +      if (cu_header != NULL)
 > +	{
 > +	  cu_header->initial_length_size = 12;
 > +	  cu_header->offset_size = 8;
 > +	}
 > +    }
 > +  else
 > +    {
 > +      *bytes_read = 4;
 > +      if (cu_header != NULL)
 > +	{
 > +	  cu_header->initial_length_size = 4;
 > +	  cu_header->offset_size = 4;
 > +	}
 > +    }
 > +
 > + return retval;
 > +}
 > +
 > +/* Read an offset from the data stream.  The size of the offset is
 > +   given by cu_header->offset_size. */
 > +
 > +static LONGEST
 > +read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
 > +             int *bytes_read)
 > +{
 > +  LONGEST retval = 0;
 > +
 > +  switch (cu_header->offset_size)
 > +    {
 > +    case 4:
 > +      retval = bfd_get_32 (abfd, (bfd_byte *) buf);
 > +      *bytes_read = 4;
 > +      break;
 > +    case 8:
 > +      retval = bfd_get_64 (abfd, (bfd_byte *) buf);
 > +      *bytes_read = 8;
 > +      break;
 > +    default:
 > +      internal_error ("read_offset: bad switch");
 > +    }
 > +
 > + return retval;
 > +}
 > +
 >  static char *
 >  read_n_bytes (bfd *abfd, char *buf, unsigned int size)
 >  {
 > @@ -3713,13 +3804,13 @@ dwarf_decode_lines (unsigned int offset,
 >    line_ptr = dwarf_line_buffer + offset;
 >  
 >    /* read in the prologue */
 > -  lh.total_length = read_4_bytes (abfd, line_ptr);
 > -  line_ptr += 4;
 > +  lh.total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
 > +  line_ptr += bytes_read;
 >    line_end = line_ptr + lh.total_length;
 >    lh.version = read_2_bytes (abfd, line_ptr);
 >    line_ptr += 2;
 > -  lh.prologue_length = read_4_bytes (abfd, line_ptr);
 > -  line_ptr += 4;
 > +  lh.prologue_length = read_offset (abfd, line_ptr, cu_header, &bytes_read);
 > +  line_ptr += bytes_read;
 >    lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
 >    line_ptr += 1;
 >    lh.default_is_stmt = read_1_byte (abfd, line_ptr);
 > @@ -5512,6 +5603,7 @@ dwarf2_get_ref_die_offset (struct attrib
 >      case DW_FORM_ref1:
 >      case DW_FORM_ref2:
 >      case DW_FORM_ref4:
 > +    case DW_FORM_ref8:
 >      case DW_FORM_ref_udata:
 >        result = cu_header_offset + DW_UNSND (attr);
 >        break;
 > 

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