This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [PATCH RFA] DWARF v2.1 64-bit support
- To: Kevin Buettner <kevinb at cygnus dot com>
- Subject: Re: [PATCH RFA] DWARF v2.1 64-bit support
- From: Elena Zannoni <ezannoni at cygnus dot com>
- Date: Fri, 4 Aug 2000 10:37:51 -0400 (EDT)
- Cc: Elena Zannoni <ezannoni at cygnus dot com>, gdb-patches at sourceware dot cygnus dot com
- References: <1000803222955.ZM2958@ocotillo.lan>
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;
>