📄 dwarfread.c
字号:
/* Decode the type that this subroutine returns */ type = decode_die_type (dip); /* Check to see if we already have a partially constructed user defined type for this DIE, from a forward reference. */ if ((ftype = lookup_utype (dip -> die_ref)) == NULL) { /* This is the first reference to one of these types. Make a new one and place it in the user defined types. */ ftype = lookup_function_type (type); alloc_utype (dip -> die_ref, ftype); } else { /* We have an existing partially constructed type, so bash it into the correct type. */ TYPE_TARGET_TYPE (ftype) = type; TYPE_FUNCTION_TYPE (type) = ftype; TYPE_LENGTH (ftype) = 1; TYPE_CODE (ftype) = TYPE_CODE_FUNC; }}/*LOCAL FUNCTION read_enumeration -- process dies which define an enumerationSYNOPSIS static void read_enumeration (struct dieinfo *dip, char *thisdie, char *enddie, struct objfile *objfile)DESCRIPTION Given a pointer to a die which begins an enumeration, process all the dies that define the members of the enumeration.NOTES Note that we need to call enum_type regardless of whether or not we have a symbol, since we might have an enum without a tag name (thus no symbol for the tagname). */static voidread_enumeration (dip, thisdie, enddie, objfile) struct dieinfo *dip; char *thisdie; char *enddie; struct objfile *objfile;{ struct type *type; struct symbol *sym; type = enum_type (dip, objfile); sym = new_symbol (dip, objfile); if (sym != NULL) { SYMBOL_TYPE (sym) = type; if (cu_language == language_cplus) { synthesize_typedef (dip, objfile, type); } }}/*LOCAL FUNCTION enum_type -- decode and return a type for an enumerationSYNOPSIS static type *enum_type (struct dieinfo *dip, struct objfile *objfile)DESCRIPTION Given a pointer to a die information structure for the die which starts an enumeration, process all the dies that define the members of the enumeration and return a type pointer for the enumeration. At the same time, for each member of the enumeration, create a symbol for it with namespace VAR_NAMESPACE and class LOC_CONST, and give it the type of the enumeration itself.NOTES Note that the DWARF specification explicitly mandates that enum constants occur in reverse order from the source program order, for "consistency" and because this ordering is easier for many compilers to generate. (Draft 6, sec 3.8.5, Enumeration type Entries). Because gdb wants to see the enum members in program source order, we have to ensure that the order gets reversed while we are processing them. */static struct type *enum_type (dip, objfile) struct dieinfo *dip; struct objfile *objfile;{ struct type *type; struct nextfield { struct nextfield *next; struct field field; }; struct nextfield *list = NULL; struct nextfield *new; int nfields = 0; int n; char *scan; char *listend; unsigned short blocksz; struct symbol *sym; int nbytes; if ((type = lookup_utype (dip -> die_ref)) == NULL) { /* No forward references created an empty type, so install one now */ type = alloc_utype (dip -> die_ref, NULL); } TYPE_CODE (type) = TYPE_CODE_ENUM; /* Some compilers try to be helpful by inventing "fake" names for anonymous enums, structures, and unions, like "~0fake" or ".0fake". Thanks, but no thanks... */ if (dip -> at_name != NULL && *dip -> at_name != '~' && *dip -> at_name != '.') { TYPE_NAME (type) = obconcat (&objfile -> type_obstack, "enum", " ", dip -> at_name); } if (dip -> at_byte_size != 0) { TYPE_LENGTH (type) = dip -> at_byte_size; } if ((scan = dip -> at_element_list) != NULL) { if (dip -> short_element_list) { nbytes = attribute_size (AT_short_element_list); } else { nbytes = attribute_size (AT_element_list); } blocksz = target_to_host (scan, nbytes, GET_UNSIGNED, objfile); listend = scan + nbytes + blocksz; scan += nbytes; while (scan < listend) { new = (struct nextfield *) alloca (sizeof (struct nextfield)); new -> next = list; list = new; list -> field.type = NULL; list -> field.bitsize = 0; list -> field.bitpos = target_to_host (scan, TARGET_FT_LONG_SIZE (objfile), GET_SIGNED, objfile); scan += TARGET_FT_LONG_SIZE (objfile); list -> field.name = obsavestring (scan, strlen (scan), &objfile -> type_obstack); scan += strlen (scan) + 1; nfields++; /* Handcraft a new symbol for this enum member. */ sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); memset (sym, 0, sizeof (struct symbol)); SYMBOL_NAME (sym) = create_name (list -> field.name, &objfile->symbol_obstack); SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; SYMBOL_CLASS (sym) = LOC_CONST; SYMBOL_TYPE (sym) = type; SYMBOL_VALUE (sym) = list -> field.bitpos; add_symbol_to_list (sym, list_in_scope); } /* Now create the vector of fields, and record how big it is. This is where we reverse the order, by pulling the members off the list in reverse order from how they were inserted. If we have no fields (this is apparently possible in C++) then skip building a field vector. */ if (nfields > 0) { TYPE_NFIELDS (type) = nfields; TYPE_FIELDS (type) = (struct field *) obstack_alloc (&objfile->symbol_obstack, sizeof (struct field) * nfields); /* Copy the saved-up fields into the field vector. */ for (n = 0; (n < nfields) && (list != NULL); list = list -> next) { TYPE_FIELD (type, n++) = list -> field; } } } return (type);}/*LOCAL FUNCTION read_func_scope -- process all dies within a function scopeDESCRIPTION Process all dies within a given function scope. We are passed a die information structure pointer DIP for the die which starts the function scope, and pointers into the raw die data that define the dies within the function scope. For now, we ignore lexical block scopes within the function. The problem is that AT&T cc does not define a DWARF lexical block scope for the function itself, while gcc defines a lexical block scope for the function. We need to think about how to handle this difference, or if it is even a problem. (FIXME) */static voidread_func_scope (dip, thisdie, enddie, objfile) struct dieinfo *dip; char *thisdie; char *enddie; struct objfile *objfile;{ register struct context_stack *new; if (objfile -> ei.entry_point >= dip -> at_low_pc && objfile -> ei.entry_point < dip -> at_high_pc) { objfile -> ei.entry_func_lowpc = dip -> at_low_pc; objfile -> ei.entry_func_highpc = dip -> at_high_pc; } if (STREQ (dip -> at_name, "main")) /* FIXME: hardwired name */ { objfile -> ei.main_func_lowpc = dip -> at_low_pc; objfile -> ei.main_func_highpc = dip -> at_high_pc; } new = push_context (0, dip -> at_low_pc); new -> name = new_symbol (dip, objfile); list_in_scope = &local_symbols; process_dies (thisdie + dip -> die_length, enddie, objfile); new = pop_context (); /* Make a block for the local symbols within. */ finish_block (new -> name, &local_symbols, new -> old_blocks, new -> start_addr, dip -> at_high_pc, objfile); list_in_scope = &file_symbols;}/*LOCAL FUNCTION handle_producer -- process the AT_producer attributeDESCRIPTION Perform any operations that depend on finding a particular AT_producer attribute. */static voidhandle_producer (producer) char *producer;{ /* If this compilation unit was compiled with g++ or gcc, then set the processing_gcc_compilation flag. */ processing_gcc_compilation = STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER)) || STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER)); /* Select a demangling style if we can identify the producer and if the current style is auto. We leave the current style alone if it is not auto. We also leave the demangling style alone if we find a gcc (cc1) producer, as opposed to a g++ (cc1plus) producer. */#if 1 /* Works, but is experimental. -fnf */ if (AUTO_DEMANGLING) { if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))) { set_demangling_style (GNU_DEMANGLING_STYLE_STRING); } else if (STREQN (producer, LCC_PRODUCER, strlen (LCC_PRODUCER))) { set_demangling_style (LUCID_DEMANGLING_STYLE_STRING); } else if (STREQN (producer, CFRONT_PRODUCER, strlen (CFRONT_PRODUCER))) { set_demangling_style (CFRONT_DEMANGLING_STYLE_STRING); } }#endif}/*LOCAL FUNCTION read_file_scope -- process all dies within a file scopeDESCRIPTION Process all dies within a given file scope. We are passed a pointer to the die information structure for the die which starts the file scope, and pointers into the raw die data which mark the range of dies within the file scope. When the partial symbol table is built, the file offset for the line number table for each compilation unit is saved in the partial symbol table entry for that compilation unit. As the symbols for each compilation unit are read, the line number table is read into memory and the variable lnbase is set to point to it. Thus all we have to do is use lnbase to access the line number table for the current compilation unit. */static voidread_file_scope (dip, thisdie, enddie, objfile) struct dieinfo *dip; char *thisdie; char *enddie; struct objfile *objfile;{ struct cleanup *back_to; struct symtab *symtab; if (objfile -> ei.entry_point >= dip -> at_low_pc && objfile -> ei.entry_point < dip -> at_high_pc) { objfile -> ei.entry_file_lowpc = dip -> at_low_pc; objfile -> ei.entry_file_highpc = dip -> at_high_pc; } set_cu_language (dip); if (dip -> at_producer != NULL) { handle_producer (dip -> at_producer); } numutypes = (enddie - thisdie) / 4; utypes = (struct type **) xmalloc (numutypes * sizeof (struct type *)); back_to = make_cleanup (free, utypes); memset (utypes, 0, numutypes * sizeof (struct type *)); start_symtab (dip -> at_name, dip -> at_comp_dir, dip -> at_low_pc); decode_line_numbers (lnbase); process_dies (thisdie + dip -> die_length, enddie, objfile); symtab = end_symtab (dip -> at_high_pc, 0, 0, objfile); if (symtab != NULL) { symtab -> language = cu_language; } do_cleanups (back_to); utypes = NULL; numutypes = 0;}/*LOCAL FUNCTION process_dies -- process a range of DWARF Information EntriesSYNOPSIS static void process_dies (char *thisdie, char *enddie, struct objfile *objfile)DESCRIPTION Process all DIE's in a specified range. May be (and almost certainly will be) called recursively. */static voidprocess_dies (thisdie, enddie, objfile) char *thisdie; char *enddie; struct objfile *objfile;{ char *nextdie; struct dieinfo di; while (thisdie < enddie) { basicdieinfo (&di, thisdie, objfile); if (di.die_length < SIZEOF_DIE_LENGTH) { break; } else if (di.die_tag == TAG_padding) { nextdie = thisdie + di.die_length; } else { completedieinfo (&di, objfile); if (di.at_sibling != 0) { nextdie = dbbase + di.at_sibling - dbroff; } else { nextdie = thisdie + di.die_length; } switch (di.die_tag) { case TAG_compile_unit: read_file_scope (&di, thisdie, nextdie, objfile); break; case TAG_global_subroutine: case TAG_subroutine: if (di.has_at_low_pc) { read_func_scope (&di, thisdie, nextdie, objfile); } break; case TAG_lexical_block: read_lexical_block_scope (&di, thisdie, nextdie, objfile); break; case TAG_class_type: case TAG_structure_type: case TAG_union_type: read_structure_scope (&di, thisdie, nextdie, objfile); break; case TAG_enumeration_type: read_enumeration (&di, thisdie, nextdie, objfile); break; case TAG_subroutine_type: read_subroutine_type (&di, thisdie, nextdie); break; case TAG_array_type: dwarf_read_array_type (&di); break; case TAG_pointer_type: read_tag_pointer_type (&di); break; default: new_symbol (&di, objfile); break; } } thisdie = nextdie; }}/*LOCAL FUNCTION decode_line_numbers -- decode a line number table fragmentSYNOPSIS static void decode_line_numbers (char *tblscan, char *tblend, long length, long base, long line, long pc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -