Index: dwarf2read.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2read.c,v retrieving revision 1.146 diff -u -p -r1.146 dwarf2read.c --- dwarf2read.c 16 Apr 2004 16:12:52 -0000 1.146 +++ dwarf2read.c 16 Apr 2004 23:03:07 -0000 @@ -634,6 +634,13 @@ static void dwarf2_locate_sections (bfd static void dwarf2_build_psymtabs_easy (struct objfile *, int); #endif +static void dwarf2_create_include_psymtab (char *, struct partial_symtab *, + struct objfile *); + +static void dwarf2_build_include_psymtabs (struct dwarf2_cu *, + const unsigned int, + struct partial_symtab *); + static void dwarf2_build_psymtabs_hard (struct objfile *, int); static void scan_partial_symbols (struct partial_die_info *, @@ -677,7 +684,8 @@ static struct partial_die_info *load_par static char *read_partial_die (struct partial_die_info *, struct abbrev_info *abbrev, unsigned int, - bfd *, char *, struct dwarf2_cu *); + bfd *, char *, struct dwarf2_cu *, + unsigned int *); static struct partial_die_info *find_partial_die (unsigned long, struct dwarf2_cu *, @@ -739,12 +747,15 @@ static struct die_info *die_specificatio static void free_line_header (struct line_header *lh); +static void add_file_name (struct line_header *, char *, unsigned int, + unsigned int, unsigned int); + static struct line_header *(dwarf_decode_line_header (unsigned int offset, bfd *abfd, struct dwarf2_cu *cu)); static void dwarf_decode_lines (struct line_header *, char *, bfd *, - struct dwarf2_cu *); + struct dwarf2_cu *, struct partial_symtab *); static void dwarf2_start_subfile (char *, char *); @@ -1196,6 +1207,65 @@ partial_read_comp_unit_head (struct comp return info_ptr; } +/* Allocate a new partial symtab for file named NAME and mark this new + partial symtab as being an include of PST. */ + +static void +dwarf2_create_include_psymtab (char *name, struct partial_symtab *pst, + struct objfile *objfile) +{ + struct partial_symtab *subpst = allocate_psymtab (name, objfile); + + subpst->section_offsets = pst->section_offsets; + subpst->textlow = 0; + subpst->texthigh = 0; + + subpst->dependencies = (struct partial_symtab **) + obstack_alloc (&objfile->objfile_obstack, + sizeof (struct partial_symtab *)); + subpst->dependencies[0] = pst; + subpst->number_of_dependencies = 1; + + subpst->globals_offset = 0; + subpst->n_global_syms = 0; + subpst->statics_offset = 0; + subpst->n_static_syms = 0; + subpst->symtab = NULL; + subpst->read_symtab = pst->read_symtab; + subpst->readin = 0; + + /* No private part is necessary for include psymtabs. This property + can be used to differentiate between such include psymtabs and + the regular ones. If it ever happens that a regular psymtab can + legitimally have a NULL PST_PRIVATE part, then we'll have to add a + dedicated field for that in the dwarf2_pinfo structure. */ + PST_PRIVATE (subpst) = NULL; +} + +/* Read the line number information located at LINE_OFFSET, + and extract the list of sources files included by the + source file represented by PST. Build an include partial + symtab for each of these included files. */ + +static void +dwarf2_build_include_psymtabs (struct dwarf2_cu *cu, + const unsigned int line_offset, + struct partial_symtab *pst) +{ + struct objfile *objfile = cu->objfile; + bfd *abfd = objfile->obfd; + struct line_header *lh; + + lh = dwarf_decode_line_header (line_offset, abfd, cu); + if (lh == NULL) + return; /* No linetable, so no includes. */ + + dwarf_decode_lines (lh, NULL, abfd, cu, pst); + + free_line_header (lh); +} + + /* Build the partial symbol table by doing a quick pass through the .debug_info and .debug_abbrev sections. */ @@ -1266,6 +1336,7 @@ dwarf2_build_psymtabs_hard (struct objfi struct abbrev_info *abbrev; unsigned int bytes_read; struct dwarf2_per_cu_data *this_cu; + unsigned int line_offset = 0; beg_of_comp_unit = info_ptr; @@ -1294,7 +1365,7 @@ dwarf2_build_psymtabs_hard (struct objfi /* Read the compilation unit die */ abbrev = peek_die_abbrev (info_ptr, &bytes_read, &cu); info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read, - abfd, info_ptr, &cu); + abfd, info_ptr, &cu, &line_offset); /* Set the language we're debugging */ set_cu_language (comp_unit_die.language, &cu); @@ -1358,6 +1429,10 @@ dwarf2_build_psymtabs_hard (struct objfi info_ptr = beg_of_comp_unit + cu.header.length + cu.header.initial_length_size; + /* Get the list of files included in the current compilation unit, + and build a psymtab for each of them. */ + dwarf2_build_include_psymtabs (&cu, line_offset, pst); + do_cleanups (back_to_inner); } do_cleanups (back_to); @@ -2041,6 +2116,32 @@ psymtab_to_symtab_1 (struct partial_symt struct cleanup *back_to; struct attribute *attr; CORE_ADDR baseaddr; + int i; + + for (i = 0; i < pst->number_of_dependencies; i++) + if (!pst->dependencies[i]->readin) + { + /* Inform about additional files that need to be read in. */ + if (info_verbose) + { + fputs_filtered (" ", gdb_stdout); + wrap_here (""); + fputs_filtered ("and ", gdb_stdout); + wrap_here (""); + printf_filtered ("%s...", pst->dependencies[i]->filename); + wrap_here (""); /* Flush output */ + gdb_flush (gdb_stdout); + } + psymtab_to_symtab_1 (pst->dependencies[i]); + } + + if (PST_PRIVATE (pst) == NULL) + { + /* It's an include file, no symbols to read for it. + Everything is in the parent symtab. */ + pst->readin = 1; + return; + } dwarf2_per_objfile = objfile_data (pst->objfile, dwarf2_objfile_data_key); @@ -2329,7 +2430,7 @@ read_file_scope (struct die_info *die, s { make_cleanup ((make_cleanup_ftype *) free_line_header, (void *) line_header); - dwarf_decode_lines (line_header, comp_dir, abfd, cu); + dwarf_decode_lines (line_header, comp_dir, abfd, cu, NULL); } } @@ -4636,7 +4737,7 @@ load_partial_dies (bfd *abfd, char *info } info_ptr = read_partial_die (part_die, abbrev, bytes_read, - abfd, info_ptr, cu); + abfd, info_ptr, cu, NULL); /* This two-pass algorithm for processing partial symbols has a high cost in cache pressure. Thus, handle some simple cases @@ -4768,13 +4869,16 @@ load_partial_dies (bfd *abfd, char *info } } -/* Read a minimal amount of information into the minimal die structure. */ +/* Read a minimal amount of information into the minimal die structure. + If not NULL, the offset where the Line Number Information data is + stored will be saved in LINE_OFFSET. */ static char * read_partial_die (struct partial_die_info *part_die, struct abbrev_info *abbrev, unsigned int abbrev_len, bfd *abfd, - char *info_ptr, struct dwarf2_cu *cu) + char *info_ptr, struct dwarf2_cu *cu, + unsigned int *line_offset) { unsigned int bytes_read, i; struct attribute attr; @@ -4861,6 +4965,9 @@ read_partial_die (struct partial_die_inf part_die->sibling = dwarf2_per_objfile->info_buffer + dwarf2_get_ref_die_offset (&attr, cu); break; + case DW_AT_stmt_list: + if (line_offset != NULL) + *line_offset = DW_UNSND (&attr); default: break; } @@ -5801,13 +5908,23 @@ check_cu_functions (CORE_ADDR address, s return fn->lowpc; } -/* Decode the line number information for the compilation unit whose - line number info is at OFFSET in the .debug_line section. - The compilation directory of the file is passed in COMP_DIR. */ +/* Decode the Line Number Program (LNP) for the given line_header + structure and CU. The actual information extracted and the type + of structures created from the LNP depends on the value of PST. + + 1. If PST is NULL, then this procedure uses the data from the program + to create all necessary symbol tables, and their linetables. + The compilation directory of the file is passed in COMP_DIR, + and must not be NULL. + + 2. If PST is not NULL, this procedure reads the program to determine + the list of files included by the unit represented by PST, and + builds all the associated partial symbol tables. In this case, + the value of COMP_DIR is ignored, and can thus be NULL. */ static void dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd, - struct dwarf2_cu *cu) + struct dwarf2_cu *cu, struct partial_symtab *pst) { char *line_ptr; char *line_end; @@ -5816,6 +5933,40 @@ dwarf_decode_lines (struct line_header * CORE_ADDR baseaddr; struct objfile *objfile = cu->objfile; + /* When decoding the Line Number Program for the purpose of building + the partial symtabs included by the current CU, we need to do + the following: + + We first scan the Line Header. It contains a list of files referenced + by the Line Number Program. We then scan the Line Number Program + for opcodes changing the source file. For each file selected in + the program, we mark it as included using the FILE_IS_INCLUDED + array. Once we're finished scanning the Line Number Program, we can + then iterate over FILE_IS_INCLUDED and create a corresponding + include partial symtab for each file that was marked as included. */ + + /* FILE_IS_INCLUDED is only used when we're creating the psymtabs + for the files included by the current unit. + + It is an array allocated on the heap, which size is stored in + SIZE_OF_FILE_IS_INCLUDED. Each element of this array corresponds + to the file of the same index in the Line Header, as stored in + the line_header struct we built for the current unit. Each element + is initially set to zero, and then to nonzero if the corresponding + file is included. The size of this array may be larger than + necessary, and the number of meaningful entries is stored in + lh->num_file_names. */ + char *file_is_included = NULL; + int size_of_file_is_included = 0; + const int decode_for_pst_p = (pst != NULL); + + if (decode_for_pst_p) + { + file_is_included = xmalloc (lh->file_names_size * sizeof (char)); + memset (file_is_included, 0, lh->file_names_size * sizeof (char)); + size_of_file_is_included = lh->file_names_size; + } + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); line_ptr = lh->statement_program_start; @@ -5833,9 +5984,9 @@ dwarf_decode_lines (struct line_header * int basic_block = 0; int end_sequence = 0; - /* Start a subfile for the current file of the state machine. */ - if (lh->num_file_names >= file) + if (!decode_for_pst_p && lh->num_file_names >= file) { + /* Start a subfile for the current file of the state machine. */ /* lh->include_dirs and lh->file_names are 0-based, but the directory and file name numbers in the statement program are 1-based. */ @@ -5860,9 +6011,12 @@ dwarf_decode_lines (struct line_header * address += (adj_opcode / lh->line_range) * lh->minimum_instruction_length; line += lh->line_base + (adj_opcode % lh->line_range); - /* append row to matrix using current values */ - record_line (current_subfile, line, - check_cu_functions (address, cu)); + if (!decode_for_pst_p) + { + /* append row to matrix using current values */ + record_line (current_subfile, line, + check_cu_functions (address, cu)); + } basic_block = 1; } else switch (op_code) @@ -5875,7 +6029,8 @@ dwarf_decode_lines (struct line_header * { case DW_LNE_end_sequence: end_sequence = 1; - record_line (current_subfile, 0, address); + if (!decode_for_pst_p) + record_line (current_subfile, 0, address); break; case DW_LNE_set_address: address = read_address (abfd, line_ptr, cu, &bytes_read); @@ -5899,6 +6054,20 @@ dwarf_decode_lines (struct line_header * read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; add_file_name (lh, cur_file, dir_index, mod_time, length); + + if (decode_for_pst_p) + { + if (size_of_file_is_included != lh->file_names_size) + { + /* The add_file_name() operation above caused + the file_names array size in the line_header + struct to be increased. Increase our + file_is_included array size accordingly. */ + file_is_included = xrealloc (file_is_included, + lh->file_names_size); + } + file_is_included [lh->num_file_names - 1] = 0; + } } break; default: @@ -5908,8 +6077,9 @@ dwarf_decode_lines (struct line_header * } break; case DW_LNS_copy: - record_line (current_subfile, line, - check_cu_functions (address, cu)); + if (!decode_for_pst_p) + record_line (current_subfile, line, + check_cu_functions (address, cu)); basic_block = 0; break; case DW_LNS_advance_pc: @@ -5935,7 +6105,10 @@ dwarf_decode_lines (struct line_header * dir = lh->include_dirs[fe->dir_index - 1]; else dir = comp_dir; - dwarf2_start_subfile (fe->name, dir); + if (decode_for_pst_p) + file_is_included[file - 1] = 1; + else + dwarf2_start_subfile (fe->name, dir); } break; case DW_LNS_set_column: @@ -5972,6 +6145,22 @@ dwarf_decode_lines (struct line_header * } } } + } + + if (decode_for_pst_p) + { + int file_index; + + /* Now that we're done scanning the Line Header Program, we can + create the psymtab of each included file. */ + for (file_index = 0; file_index < lh->num_file_names; file_index++) + if (file_is_included[file_index] == 1) + { + char *include_name = lh->file_names [file_index].name; + + if (strcmp (include_name, pst->filename) != 0) + dwarf2_create_include_psymtab (include_name, pst, objfile); + } } }