diff options
author | Kevin Buettner <kevinb@redhat.com> | 2000-08-04 16:25:30 +0000 |
---|---|---|
committer | Kevin Buettner <kevinb@redhat.com> | 2000-08-04 16:25:30 +0000 |
commit | 613e1657593fd78b147d5b1f700e331327a073e9 (patch) | |
tree | 1c7dac5fc45ba3e475bb3849a0bb84710a58b3ce /gdb/dwarf2read.c | |
parent | 7dca057bba81fc2531ec3b4c9f15f03ab1667c64 (diff) | |
download | gdb-613e1657593fd78b147d5b1f700e331327a073e9.zip gdb-613e1657593fd78b147d5b1f700e331327a073e9.tar.gz gdb-613e1657593fd78b147d5b1f700e331327a073e9.tar.bz2 |
DWARF2.1 64-bit support.
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r-- | gdb/dwarf2read.c | 139 |
1 files changed, 122 insertions, 17 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 18cb65e..8fb042f 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -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 *, char *); static CORE_ADDR read_address (bfd *, char *ptr, const struct comp_unit_head *, int *bytes_read); +static LONGEST read_initial_length (bfd *, char *, + struct comp_unit_head *, int *bytes_read); + +static LONGEST read_offset (bfd *, char *, const 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 objfile *objfile, int mainline) 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_head *cu_header, 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 objfile *objfile, int mainline) (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 objfile *objfile, int mainline) 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 objfile *objfile, int mainline) 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_symtab *pst) 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_symtab *pst) } } } - 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, struct attr_abbrev *abbrev, 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,89 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header, return retval; } +/* Reads the initial length from a section. The (draft) 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().) + + [ Note: read_initial_length() and read_offset() are based on the + document entitled "DWARF Debugging Information Format", revision + 2.1, draft 4, dated July 20, 2000. This document was obtained + from: + + http://reality.sgi.com/dehnert_engr/dwarf/dwarf2p1-draft4-000720.pdf + + This document is only a draft and is subject to change. (So beware.) + + - Kevin, Sept 4, 2000 + ] */ + +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 +3817,13 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd, 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 +5616,7 @@ dwarf2_get_ref_die_offset (struct attribute *attr) 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; |