📄 xcoffread.c
字号:
complete_symtab (filestring, file_start_addr); cur_src_end_addr = file_end_addr; end_symtab (file_end_addr, 1, 0, objfile); end_stabs (); start_stabs (); start_symtab (cs->c_name, (char *)NULL, (CORE_ADDR)0); last_csect_name = 0; /* reset file start and end addresses. A compilation unit with no text (only data) should have zero file boundaries. */ file_start_addr = file_end_addr = 0; filestring = cs->c_name; break; case C_FUN:#ifdef NO_DEFINE_SYMBOL /* For a function stab, just save its type in `fcn_type_saved', and leave it for the `.bf' processing. */ { char *pp = (char*) index (cs->c_name, ':'); if (!pp || ( *(pp+1) != 'F' && *(pp+1) != 'f')) fatal ("Unrecognized stab"); pp += 2; if (fcn_type_saved) fatal ("Unprocessed function type"); fcn_type_saved = lookup_function_type (read_type (&pp, objfile)); }#else fcn_stab_saved = *cs;#endif break; case C_FCN: if (strcmp (cs->c_name, ".bf") == 0) { bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass, main_aux); within_function = 1; /* Linenos are now processed on a file-by-file, not fn-by-fn, basis. Metin did it, I'm not sure why. FIXME. -- gnu@cygnus.com */ /* Two reasons: 1) xlc (IBM's native c compiler) postpones static function code emission to the end of a compilation unit. This way it can determine if those functions (statics) are needed or not, and can do some garbage collection (I think). This makes line numbers and corresponding addresses unordered, and we end up with a line table like: lineno addr foo() 10 0x100 20 0x200 30 0x300 foo3() 70 0x400 80 0x500 90 0x600 static foo2() 40 0x700 50 0x800 60 0x900 and that breaks gdb's binary search on line numbers, if the above table is not sorted on line numbers. And that sort should be on function based, since gcc can emit line numbers like: 10 0x100 - for the init/test part of a for stmt. 20 0x200 30 0x300 10 0x400 - for the increment part of a for stmt. arrange_linenos() will do this sorting. 2) aix symbol table might look like: c_file // beginning of a new file .bi // beginning of include file .ei // end of include file .bi .ei basically, .bi/.ei pairs do not necessarily encapsulate their scope. They need to be recorded, and processed later on when we come the end of the compilation unit. Include table (inclTable) and process_linenos() handle that. */ mark_first_line (fcn_line_offset, cs->c_symnum); new = push_context (0, fcn_start_addr);#ifdef NO_DEFINE_SYMBOL new->name = process_xcoff_symbol (&fcn_cs_saved, objfile); /* Between a function symbol and `.bf', there always will be a function stab. We save function type when processing that stab. */ if (fcn_type_saved == NULL) { printf ("Unknown function type: symbol 0x%x\n", cs->c_symnum); SYMBOL_TYPE (new->name) = lookup_function_type (builtin_type_int); } else { SYMBOL_TYPE (new->name) = fcn_type_saved; fcn_type_saved = NULL; }#else new->name = define_symbol (fcn_cs_saved.c_value, fcn_stab_saved.c_name, 0, 0, objfile);#endif } else if (strcmp (cs->c_name, ".ef") == 0) { bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass, main_aux); /* the value of .ef is the address of epilogue code; not useful for gdb */ /* { main_aux.x_sym.x_misc.x_lnsz.x_lnno contains number of lines to '}' */ fcn_last_line = main_aux->x_sym.x_misc.x_lnsz.x_lnno; new = pop_context (); if (context_stack_depth != 0) error ("invalid symbol data; .bf/.ef/.bb/.eb symbol mismatch, at symbol %d.", symnum); finish_block (new->name, &local_symbols, new->old_blocks, new->start_addr, fcn_cs_saved.c_value + fcn_aux_saved.x_sym.x_misc.x_fsize, objfile); within_function = 0; } break; case C_BSTAT : /* begin static block */ static_block_base = read_symbol_nvalue (symtbl, cs->c_value); break; case C_ESTAT : /* end of static block */ static_block_base = 0; break; case C_ARG : /* These are not implemented. */ case C_REGPARM : case C_TPDEF : case C_STRTAG : case C_UNTAG : case C_ENTAG : printf ("ERROR: Unimplemented storage class: %d.\n", cs->c_sclass); break; case C_HIDEXT : /* ignore these.. */ case C_LABEL : case C_NULL : break; case C_BINCL : /* beginning of include file */ /* In xlc output, C_BINCL/C_EINCL pair doesn't show up in sorted order. Thus, when wee see them, we might not know enough info to process them. Thus, we'll be saving them into a table (inclTable) and postpone their processing. */ record_include_begin (cs); break; case C_EINCL : /* end of include file */ /* see the comment after case C_BINCL. */ record_include_end (cs); break; case C_BLOCK : if (strcmp (cs->c_name, ".bb") == 0) { depth++; new = push_context (depth, cs->c_value); } else if (strcmp (cs->c_name, ".eb") == 0) { new = pop_context (); if (depth != new->depth) error ("Invalid symbol data: .bb/.eb symbol mismatch at symbol %d.", symnum); depth--; if (local_symbols && context_stack_depth > 0) { /* Make a block for the local symbols within. */ finish_block (new->name, &local_symbols, new->old_blocks, new->start_addr, cs->c_value, objfile); } local_symbols = new->locals; } break; default : process_xcoff_symbol (cs, objfile); break; } } /* while */ if (last_source_file) { end_symtab (cur_src_end_addr, 1, 0, objfile); end_stabs (); } free (symtbl); current_objfile = NULL; /* Record the toc offset value of this symbol table into ldinfo structure. If no XMC_TC0 is found, toc_offset should be zero. Another place to obtain this information would be file auxiliary header. */ xcoff_add_toc_to_loadinfo (toc_offset);}#define SYMBOL_DUP(SYMBOL1, SYMBOL2) \ (SYMBOL2) = (struct symbol *) \ obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); \ *(SYMBOL2) = *(SYMBOL1); #define SYMNAME_ALLOC(NAME, ALLOCED) \ (ALLOCED) ? (NAME) : obstack_copy0 (&objfile->symbol_obstack, (NAME), strlen (NAME));/* process one xcoff symbol. */static struct symbol *process_xcoff_symbol (cs, objfile) register struct coff_symbol *cs; struct objfile *objfile;{ struct symbol onesymbol; register struct symbol *sym = &onesymbol; struct symbol *sym2 = NULL; struct type *ttype; char *name, *pp, *qq; int struct_and_type_combined; int nameless; name = cs->c_name; if (name[0] == '.') ++name; bzero (sym, sizeof (struct symbol)); /* default assumptions */ SYMBOL_VALUE (sym) = cs->c_value; SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; if (ISFCN (cs->c_type)) { /* At this point, we don't know the type of the function and assume it is int. This will be patched with the type from its stab entry later on in patch_block_stabs () */ SYMBOL_NAME (sym) = SYMNAME_ALLOC (name, symname_alloced); SYMBOL_TYPE (sym) = lookup_function_type (lookup_fundamental_type (objfile, FT_INTEGER)); SYMBOL_CLASS (sym) = LOC_BLOCK; SYMBOL_DUP (sym, sym2); if (cs->c_sclass == C_EXT) add_symbol_to_list (sym2, &global_symbols); else if (cs->c_sclass == C_HIDEXT || cs->c_sclass == C_STAT) add_symbol_to_list (sym2, &file_symbols); } else { /* in case we can't figure out the type, default is `int'. */ SYMBOL_TYPE (sym) = lookup_fundamental_type (objfile, FT_INTEGER); switch (cs->c_sclass) {#if 0 case C_FUN: if (fcn_cs_saved.c_sclass == C_EXT) add_stab_to_list (name, &global_stabs); else add_stab_to_list (name, &file_stabs); break;#endif case C_DECL: /* a type decleration?? */#if defined(NO_TYPEDEFS) || defined(NO_DEFINE_SYMBOL) qq = (char*) strchr (name, ':'); if (!qq) /* skip if there is no ':' */ return NULL; nameless = (qq == name); struct_and_type_combined = (qq[1] == 'T' && qq[2] == 't'); pp = qq + (struct_and_type_combined ? 3 : 2); /* To handle GNU C++ typename abbreviation, we need to be able to fill in a type's name as soon as space for that type is allocated. */ if (struct_and_type_combined && name != qq) { int typenums[2]; struct type *tmp_type; char *tmp_pp = pp; read_type_number (&tmp_pp, typenums); tmp_type = dbx_alloc_type (typenums, objfile); if (tmp_type && !TYPE_NAME (tmp_type) && !nameless) TYPE_NAME (tmp_type) = SYMBOL_NAME (sym) = obsavestring (name, qq-name, &objfile->symbol_obstack); } ttype = SYMBOL_TYPE (sym) = read_type (&pp); /* if there is no name for this typedef, you don't have to keep its symbol, since nobody could ask for it. Otherwise, build a symbol and add it into symbol_list. */ if (nameless) return;#ifdef NO_TYPEDEFS /* Transarc wants to eliminate type definitions from the symbol table. Limited debugging capabilities, but faster symbol table processing and less memory usage. Note that tag definitions (starting with 'T') will remain intact. */ if (qq[1] != 'T' && (!TYPE_NAME (ttype) || *(TYPE_NAME (ttype)) == '\0')) { if (SYMBOL_NAME (sym)) TYPE_NAME (ttype) = SYMBOL_NAME (sym); else TYPE_NAME (ttype) = obsavestring (name, qq-name); return; }#endif /* !NO_TYPEDEFS */ /* read_type() will return null if type (or tag) definition was unnnecessarily duplicated. Also, if the symbol doesn't have a name, there is no need to keep it in symbol table. */ /* The above argument no longer valid. read_type() never returns NULL. */ if (!ttype) return NULL; /* if there is no name for this typedef, you don't have to keep its symbol, since nobody could ask for it. Otherwise, build a symbol and add it into symbol_list. */ if (qq[1] == 'T') SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE; else if (qq[1] == 't') SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE; else { warning ("Unrecognized stab string.\n"); return NULL; } SYMBOL_CLASS (sym) = LOC_TYPEDEF; if (!SYMBOL_NAME (sym)) SYMBOL_NAME (sym) = obsavestring (name, qq-name); SYMBOL_DUP (sym, sym2); add_symbol_to_list (sym2, within_function ? &local_symbols : &file_symbols); /* For a combination of struct and type, add one more symbol for the type. */ if (struct_and_type_combined) { SYMBOL_DUP (sym, sym2); SYMBOL_NAMESPACE (sym2) = VAR_NAMESPACE; add_symbol_to_list (sym2, within_function ? &local_symbols : &file_symbols); } /* assign a name to the type node. */ if (!TYPE_NAME (ttype) || *(TYPE_NAME (ttype)) == '\0') { if (struct_and_type_combined) TYPE_NAME (ttype) = SYMBOL_NAME (sym); else if (qq[1] == 'T') /* struct namespace */ TYPE_NAME (ttype) = concat ( TYPE_CODE (ttype) == TYPE_CODE_UNION ? "union " : TYPE_CODE (ttype) == TYPE_CODE_STRUCT? "struct " : "enum ", SYMBOL_NAME (sym), NULL); } break;#else /* !NO_DEFINE_SYMBOL */ return define_symbol (cs->c_value, cs->c_name, 0, 0, objfile);#endif case C_GSYM: add_stab_to_list (name, &global_stabs); break; case C_PSYM: case C_RPSYM:#ifdef NO_DEFINE_SYMBOL if (*name == ':' || (pp = (char *) strchr (name, ':')) == NULL) return NULL; SYMBOL_NAME (sym) = obsavestring (name, pp-name, &objfile -> symbol_obstack); SYMBOL_CLASS (sym) = (cs->c_sclass == C_PSYM) ? LOC_ARG : LOC_REGPARM; pp += 2; SYMBOL_TYPE (sym) = read_type (&pp, objfile); SYMBOL_DUP (sym, sym2); add_symbol_to_list (sym2, &local_symbols); break;#else sym = define_symbol (cs->c_value, cs->c_name, 0, 0, objfile); SYMBOL_CLASS (sym) = (cs->c_sclass == C_PSYM) ? LOC_ARG : LOC_REGPARM; return sym;#endif case C_STSYM:#ifdef NO_DEFINE_SYMBOL if (*name == ':' || (pp = (char *) strchr (name, ':')) == NULL) return NULL; SYMBOL_NAME (sym) = obsavestring (name, pp-name, &objfile -> symbol_obstack); SYMBOL_CLASS (sym) = LOC_STATIC; SYMBOL_VALUE (sym) += static_block_base; pp += 2; SYMBOL_TYPE (sym) = read_type (&pp, objfile); SYMBOL_DUP (sym, sym2); add_symbol_to_list (sym2, within_function ? &local_symbols : &file_symbols); break;#else /* If we are going to use Sun dbx's define_symbol(), we need to massage our stab string a little. Change 'V' type to 'S' to be comparible with Sun. */ if (*name == ':' || (pp = (char *) index (name, ':')) == NULL) return NULL; ++pp; if (*pp == 'V') *pp = 'S'; sym = define_symbol (cs->c_value, cs->c_name, 0, 0, objfile);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -