/* Print a natural-language description of SYMBOL to STREAM. */ static int locexpr_describe_location (struct symbol *symbol, struct ui_file *stream) { /* FIXME: be more extensive. */ struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu); if (dlbaton->size == 1 && dlbaton->data[0] >= DW_OP_reg0 && dlbaton->data[0] <= DW_OP_reg31) { struct objfile *objfile = dwarf2_per_cu_objfile (dlbaton->per_cu); struct gdbarch *gdbarch = get_objfile_arch (objfile); int regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, dlbaton->data[0] - DW_OP_reg0); fprintf_filtered (stream, "a variable in register %s", gdbarch_register_name (gdbarch, regno)); return 1; } /* The location expression for a TLS variable looks like this (on a 64-bit LE machine): DW_AT_location : 10 byte block: 3 4 0 0 0 0 0 0 0 e0 (DW_OP_addr: 4; DW_OP_GNU_push_tls_address) 0x3 is the encoding for DW_OP_addr, which has an operand as long as the size of an address on the target machine (here is 8 bytes). 0xe0 is the encoding for DW_OP_GNU_push_tls_address. The operand represents the offset at which the variable is within the thread local storage. */ if (dlbaton->size > 1 && dlbaton->data[dlbaton->size - 1] == DW_OP_GNU_push_tls_address) if (dlbaton->data[0] == DW_OP_addr) { struct objfile *objfile = dwarf2_per_cu_objfile (dlbaton->per_cu); struct gdbarch *gdbarch = get_objfile_arch (objfile); CORE_ADDR offset = dwarf2_read_address (gdbarch, &dlbaton->data[1], &dlbaton->data[dlbaton->size - 1], addr_size); fprintf_filtered (stream, "a thread-local variable at offset %s in the " "thread-local storage for `%s'", paddr_nz (offset), objfile->name); return 1; } fprintf_filtered (stream, "a variable with complex or multiple locations (DWARF2)"); return 1; }
static struct gdbarch * get_class_arch (struct type *domain) { gdb_assert (TYPE_CODE (domain) == TYPE_CODE_CLASS); gdb_assert (TYPE_OBJFILE (domain) != NULL); return get_objfile_arch (TYPE_OBJFILE (domain)); }
static gdb_byte * find_location_expression (struct dwarf2_loclist_baton *baton, size_t *locexpr_length, CORE_ADDR pc) { CORE_ADDR low, high; gdb_byte *loc_ptr, *buf_end; int length; struct objfile *objfile = dwarf2_per_cu_objfile (baton->per_cu); struct gdbarch *gdbarch = get_objfile_arch (objfile); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); unsigned int addr_size = dwarf2_per_cu_addr_size (baton->per_cu); CORE_ADDR base_mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); /* Adjust base_address for relocatable objects. */ CORE_ADDR base_offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); CORE_ADDR base_address = baton->base_address + base_offset; loc_ptr = baton->data; buf_end = baton->data + baton->size; while (1) { if (buf_end - loc_ptr < 2 * addr_size) error (_("find_location_expression: Corrupted DWARF expression.")); low = extract_unsigned_integer (loc_ptr, addr_size, byte_order); loc_ptr += addr_size; /* A base-address-selection entry. */ if (low == base_mask) { base_address = dwarf2_read_address (gdbarch, loc_ptr, buf_end, addr_size); loc_ptr += addr_size; continue; } high = extract_unsigned_integer (loc_ptr, addr_size, byte_order); loc_ptr += addr_size; /* An end-of-list entry. */ if (low == 0 && high == 0) return NULL; /* Otherwise, a location expression entry. */ low += base_address; high += base_address; length = extract_unsigned_integer (loc_ptr, 2, byte_order); loc_ptr += 2; if (pc >= low && pc < high) { *locexpr_length = length; return loc_ptr; } loc_ptr += length; } }
/* Function to ensure that the source and/or disassemly windows reflect the input address. */ void tui_update_source_windows_with_line (struct symtab *s, int line) { struct gdbarch *gdbarch; CORE_ADDR pc; struct tui_line_or_address l; if (!s) return; gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s)); switch (tui_current_layout ()) { case DISASSEM_COMMAND: case DISASSEM_DATA_COMMAND: find_line_pc (s, line, &pc); tui_update_source_windows_with_addr (gdbarch, pc); break; default: l.loa = LOA_LINE; l.u.line_no = line; tui_show_symtab_source (gdbarch, s, l, FALSE); if (tui_current_layout () == SRC_DISASSEM_COMMAND) { find_line_pc (s, line, &pc); tui_show_disassem (gdbarch, pc); } break; } return; }
bool msymbol_is_function (struct objfile *objfile, minimal_symbol *minsym, CORE_ADDR *func_address_p) { CORE_ADDR msym_addr = MSYMBOL_VALUE_ADDRESS (objfile, minsym); switch (minsym->type) { case mst_slot_got_plt: case mst_data: case mst_bss: case mst_abs: case mst_file_data: case mst_file_bss: case mst_data_gnu_ifunc: { struct gdbarch *gdbarch = get_objfile_arch (objfile); CORE_ADDR pc = gdbarch_convert_from_func_ptr_addr (gdbarch, msym_addr, current_top_target ()); if (pc != msym_addr) { if (func_address_p != NULL) *func_address_p = pc; return true; } return false; } default: if (func_address_p != NULL) *func_address_p = msym_addr; return true; } }
static void python_new_objfile (struct objfile *objfile) { struct cleanup *cleanup; if (!gdb_python_initialized) return; cleanup = ensure_python_env (objfile != NULL ? get_objfile_arch (objfile) : target_gdbarch (), current_language); if (objfile == NULL) { if (emit_clear_objfiles_event () < 0) gdbpy_print_stack (); } else { if (emit_new_objfile_event (objfile) < 0) gdbpy_print_stack (); } do_cleanups (cleanup); }
/* Enable shared library breakpoint for the OpenCL runtime running on the SPU. */ static void ocl_enable_break (struct objfile *objfile) { struct bound_minimal_symbol event_sym; struct bound_minimal_symbol addr_sym; /* The OpenCL runtime on the SPU will call __opencl_program_update_event whenever an OpenCL program is loaded. */ event_sym = lookup_minimal_symbol ("__opencl_program_update_event", NULL, objfile); /* The PPU address of the OpenCL program can be found at opencl_elf_image_address. */ addr_sym = lookup_minimal_symbol ("opencl_elf_image_address", NULL, objfile); if (event_sym.minsym && addr_sym.minsym) { /* Place a solib_event breakpoint on the symbol. */ CORE_ADDR event_addr = BMSYMBOL_VALUE_ADDRESS (event_sym); create_solib_event_breakpoint (get_objfile_arch (objfile), event_addr); /* Store the address of the symbol that will point to OpenCL program using the per-objfile private data mechanism. */ if (objfile_data (objfile, ocl_program_data_key) == NULL) { CORE_ADDR *ocl_program_addr_base = OBSTACK_CALLOC ( &objfile->objfile_obstack, objfile->sections_end - objfile->sections, CORE_ADDR); *ocl_program_addr_base = BMSYMBOL_VALUE_ADDRESS (addr_sym); set_objfile_data (objfile, ocl_program_data_key, ocl_program_addr_base); } } }
static void add_class_symtab_symbol (struct symbol *sym) { struct symtab *symtab = get_java_class_symtab (get_objfile_arch (SYMBOL_SYMTAB (sym)->objfile)); struct blockvector *bv = BLOCKVECTOR (symtab); dict_add_symbol (BLOCK_DICT (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)), sym); }
/* Clear the OBJFILE pointer in an Objfile object and remove the reference. */ static void py_free_objfile (struct objfile *objfile, void *datum) { struct cleanup *cleanup; objfile_object *object = datum; cleanup = ensure_python_env (get_objfile_arch (objfile), current_language); object->objfile = NULL; Py_DECREF ((PyObject *) object); do_cleanups (cleanup); }
static void python_new_objfile (struct objfile *objfile) { struct cleanup *cleanup; if (objfile == NULL) return; if (!gdb_python_initialized) return; cleanup = ensure_python_env (get_objfile_arch (objfile), current_language); if (emit_new_objfile_event (objfile) < 0) gdbpy_print_stack (); do_cleanups (cleanup); }
static bfd_vma call_target_sbrk (int sbrk_arg) { struct objfile *sbrk_objf; struct gdbarch *gdbarch; bfd_vma top_of_heap; struct value *target_sbrk_arg; struct value *sbrk_fn, *ret; bfd_vma tmp; if (lookup_minimal_symbol ("sbrk", NULL, NULL) != NULL) { sbrk_fn = find_function_in_inferior ("sbrk", &sbrk_objf); if (sbrk_fn == NULL) return (bfd_vma) 0; } else if (lookup_minimal_symbol ("_sbrk", NULL, NULL) != NULL) { sbrk_fn = find_function_in_inferior ("_sbrk", &sbrk_objf); if (sbrk_fn == NULL) return (bfd_vma) 0; } else return (bfd_vma) 0; gdbarch = get_objfile_arch (sbrk_objf); target_sbrk_arg = value_from_longest (builtin_type (gdbarch)->builtin_int, sbrk_arg); gdb_assert (target_sbrk_arg); ret = call_function_by_hand (sbrk_fn, 1, &target_sbrk_arg); if (ret == NULL) return (bfd_vma) 0; tmp = value_as_long (ret); if ((LONGEST) tmp <= 0 || (LONGEST) tmp == 0xffffffff) return (bfd_vma) 0; top_of_heap = tmp; return top_of_heap; }
static int dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size, struct dwarf2_per_cu_data *per_cu) { struct needs_frame_baton baton; struct dwarf_expr_context *ctx; int in_reg; baton.needs_frame = 0; ctx = new_dwarf_expr_context (); ctx->gdbarch = get_objfile_arch (dwarf2_per_cu_objfile (per_cu)); ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); ctx->baton = &baton; ctx->read_reg = needs_frame_read_reg; ctx->read_mem = needs_frame_read_mem; ctx->get_frame_base = needs_frame_frame_base; ctx->get_tls_address = needs_frame_tls_address; dwarf_expr_eval (ctx, data, size); in_reg = ctx->in_reg; if (ctx->num_pieces > 0) { int i; /* If the location has several pieces, and any of them are in registers, then we will need a frame to fetch them from. */ for (i = 0; i < ctx->num_pieces; i++) if (ctx->pieces[i].in_reg) in_reg = 1; } free_dwarf_expr_context (ctx); return baton.needs_frame || in_reg; }
void mi_cmd_symbol_list_lines (char *command, char **argv, int argc) { struct gdbarch *gdbarch; char *filename; struct symtab *s; int i; struct cleanup *cleanup_stack, *cleanup_tuple; struct ui_out *uiout = current_uiout; if (argc != 1) error (_("-symbol-list-lines: Usage: SOURCE_FILENAME")); filename = argv[0]; s = lookup_symtab (filename); if (s == NULL) error (_("-symbol-list-lines: Unknown source file name.")); /* Now, dump the associated line table. The pc addresses are already sorted by increasing values in the symbol table, so no need to perform any other sorting. */ gdbarch = get_objfile_arch (s->objfile); cleanup_stack = make_cleanup_ui_out_list_begin_end (uiout, "lines"); if (LINETABLE (s) != NULL && LINETABLE (s)->nitems > 0) for (i = 0; i < LINETABLE (s)->nitems; i++) { cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); ui_out_field_core_addr (uiout, "pc", gdbarch, LINETABLE (s)->item[i].pc); ui_out_field_int (uiout, "line", LINETABLE (s)->item[i].line); do_cleanups (cleanup_tuple); } do_cleanups (cleanup_stack); }
static void macho_add_oso_symfile (oso_el *oso, const gdb_bfd_ref_ptr &abfd, const char *name, struct objfile *main_objfile, symfile_add_flags symfile_flags) { int storage; int i; asymbol **symbol_table; asymbol **symp; struct bfd_hash_table table; int nbr_sections; /* Per section flag to mark which section have been rebased. */ unsigned char *sections_rebased; if (mach_o_debug_level > 0) printf_unfiltered (_("Loading debugging symbols from oso: %s\n"), oso->name); if (!bfd_check_format (abfd.get (), bfd_object)) { warning (_("`%s': can't read symbols: %s."), oso->name, bfd_errmsg (bfd_get_error ())); return; } if (abfd->my_archive == NULL && oso->mtime != bfd_get_mtime (abfd.get ())) { warning (_("`%s': file time stamp mismatch."), oso->name); return; } if (!bfd_hash_table_init_n (&table, macho_sym_hash_newfunc, sizeof (struct macho_sym_hash_entry), oso->nbr_syms)) { warning (_("`%s': can't create hash table"), oso->name); return; } bfd_set_cacheable (abfd.get (), 1); /* Read symbols table. */ storage = bfd_get_symtab_upper_bound (abfd.get ()); symbol_table = (asymbol **) xmalloc (storage); bfd_canonicalize_symtab (abfd.get (), symbol_table); /* Init section flags. */ nbr_sections = bfd_count_sections (abfd.get ()); sections_rebased = (unsigned char *) alloca (nbr_sections); for (i = 0; i < nbr_sections; i++) sections_rebased[i] = 0; /* Put symbols for the OSO file in the hash table. */ for (symp = oso->oso_sym; symp != oso->end_sym; symp++) { const asymbol *sym = *symp; bfd_mach_o_asymbol *mach_o_sym = (bfd_mach_o_asymbol *)sym; switch (mach_o_sym->n_type) { case N_ENSYM: case N_BNSYM: case N_GSYM: sym = NULL; break; case N_FUN: if (sym->name == NULL || sym->name[0] == 0) sym = NULL; break; case N_STSYM: break; default: sym = NULL; break; } if (sym != NULL) { struct macho_sym_hash_entry *ent; ent = (struct macho_sym_hash_entry *) bfd_hash_lookup (&table, sym->name, TRUE, FALSE); if (ent->sym != NULL) complaint (_("Duplicated symbol %s in symbol table"), sym->name); else { if (mach_o_debug_level > 4) { struct gdbarch *arch = get_objfile_arch (main_objfile); printf_unfiltered (_("Adding symbol %s (addr: %s)\n"), sym->name, paddress (arch, sym->value)); } ent->sym = sym; } } } /* Relocate symbols of the OSO. */ for (i = 0; symbol_table[i]; i++) { asymbol *sym = symbol_table[i]; bfd_mach_o_asymbol *mach_o_sym = (bfd_mach_o_asymbol *)sym; if (mach_o_sym->n_type & BFD_MACH_O_N_STAB) continue; if ((mach_o_sym->n_type & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_UNDF && sym->value != 0) { /* For common symbol use the min symtab and modify the OSO symbol table. */ CORE_ADDR res; res = macho_resolve_oso_sym_with_minsym (main_objfile, sym); if (res != 0) { sym->section = bfd_com_section_ptr; sym->value = res; } } else if ((mach_o_sym->n_type & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_SECT) { /* Normal symbol. */ asection *sec = sym->section; bfd_mach_o_section *msec; unsigned int sec_type; /* Skip buggy ones. */ if (sec == NULL || sections_rebased[sec->index] != 0) continue; /* Only consider regular, non-debugging sections. */ msec = bfd_mach_o_get_mach_o_section (sec); sec_type = msec->flags & BFD_MACH_O_SECTION_TYPE_MASK; if ((sec_type == BFD_MACH_O_S_REGULAR || sec_type == BFD_MACH_O_S_ZEROFILL) && (msec->flags & BFD_MACH_O_S_ATTR_DEBUG) == 0) { CORE_ADDR addr = 0; if ((mach_o_sym->n_type & BFD_MACH_O_N_EXT) != 0) { /* Use the min symtab for global symbols. */ addr = macho_resolve_oso_sym_with_minsym (main_objfile, sym); } else { struct macho_sym_hash_entry *ent; ent = (struct macho_sym_hash_entry *) bfd_hash_lookup (&table, sym->name, FALSE, FALSE); if (ent != NULL) addr = bfd_asymbol_value (ent->sym); } /* Adjust the section. */ if (addr != 0) { CORE_ADDR res = addr - sym->value; if (mach_o_debug_level > 3) { struct gdbarch *arch = get_objfile_arch (main_objfile); printf_unfiltered (_("resolve sect %s with %s (set to %s)\n"), sec->name, sym->name, paddress (arch, res)); } bfd_set_section_vma (abfd.get (), sec, res); sections_rebased[sec->index] = 1; } } else { /* Mark the section as never rebased. */ sections_rebased[sec->index] = 2; } } } bfd_hash_table_free (&table); /* We need to clear SYMFILE_MAINLINE to avoid interractive question from symfile.c:symbol_file_add_with_addrs_or_offsets. */ symbol_file_add_from_bfd (abfd.get (), name, symfile_flags & ~(SYMFILE_MAINLINE | SYMFILE_VERBOSE), NULL, main_objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW | OBJF_USERLOADED), main_objfile); }
static int derive_heap_segment (bfd *abfd, bfd_vma *bottom, bfd_vma *top) { struct objfile *sbrk_objf; struct gdbarch *gdbarch; bfd_vma top_of_data_memory = 0; bfd_vma top_of_heap = 0; bfd_size_type sec_size; struct value *zero, *sbrk; bfd_vma sec_vaddr; asection *sec; gdb_assert (bottom); gdb_assert (top); /* This function depends on being able to call a function in the inferior. */ if (!target_has_execution) return 0; /* The following code assumes that the link map is arranged as follows (low to high addresses): --------------------------------- | text sections | --------------------------------- | data sections (including bss) | --------------------------------- | heap | --------------------------------- */ for (sec = abfd->sections; sec; sec = sec->next) { if (bfd_get_section_flags (abfd, sec) & SEC_DATA || strcmp (".bss", bfd_section_name (abfd, sec)) == 0) { sec_vaddr = bfd_get_section_vma (abfd, sec); sec_size = bfd_get_section_size (sec); if (sec_vaddr + sec_size > top_of_data_memory) top_of_data_memory = sec_vaddr + sec_size; } } /* Now get the top-of-heap by calling sbrk in the inferior. */ if (lookup_minimal_symbol ("sbrk", NULL, NULL) != NULL) { sbrk = find_function_in_inferior ("sbrk", &sbrk_objf); if (sbrk == NULL) return 0; } else if (lookup_minimal_symbol ("_sbrk", NULL, NULL) != NULL) { sbrk = find_function_in_inferior ("_sbrk", &sbrk_objf); if (sbrk == NULL) return 0; } else return 0; gdbarch = get_objfile_arch (sbrk_objf); zero = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); gdb_assert (zero); sbrk = call_function_by_hand (sbrk, 1, &zero); if (sbrk == NULL) return 0; top_of_heap = value_as_long (sbrk); /* Return results. */ if (top_of_heap > top_of_data_memory) { *bottom = top_of_data_memory; *top = top_of_heap; return 1; } /* No additional heap space needs to be saved. */ return 0; }
static void som_symtab_read (bfd *abfd, struct objfile *objfile, struct section_offsets *section_offsets) { struct cleanup *cleanup; struct gdbarch *gdbarch = get_objfile_arch (objfile); unsigned int number_of_symbols; int val, dynamic; char *stringtab; asection *shlib_info; struct som_external_symbol_dictionary_record *buf, *bufp, *endbufp; char *symname; CONST int symsize = sizeof (struct som_external_symbol_dictionary_record); #define text_offset ANOFFSET (section_offsets, SECT_OFF_TEXT (objfile)) #define data_offset ANOFFSET (section_offsets, SECT_OFF_DATA (objfile)) number_of_symbols = bfd_get_symcount (abfd); /* Allocate a buffer to read in the debug info. We avoid using alloca because the memory size could be so large that we could hit the stack size limit. */ buf = xmalloc (symsize * number_of_symbols); cleanup = make_cleanup (xfree, buf); bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET); val = bfd_bread (buf, symsize * number_of_symbols, abfd); if (val != symsize * number_of_symbols) error (_("Couldn't read symbol dictionary!")); /* Allocate a buffer to read in the som stringtab section of the debugging info. Again, we avoid using alloca because the data could be so large that we could potentially hit the stack size limitat. */ stringtab = xmalloc (obj_som_stringtab_size (abfd)); make_cleanup (xfree, stringtab); bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET); val = bfd_bread (stringtab, obj_som_stringtab_size (abfd), abfd); if (val != obj_som_stringtab_size (abfd)) error (_("Can't read in HP string table.")); /* We need to determine if objfile is a dynamic executable (so we can do the right thing for ST_ENTRY vs ST_CODE symbols). There's nothing in the header which easily allows us to do this. This code used to rely upon the existence of a $SHLIB_INFO$ section to make this determination. HP claims that it is more accurate to check for a nonzero text offset, but they have not provided any information about why that test is more accurate. */ dynamic = (text_offset != 0); endbufp = buf + number_of_symbols; for (bufp = buf; bufp < endbufp; ++bufp) { enum minimal_symbol_type ms_type; unsigned int flags = bfd_getb32 (bufp->flags); unsigned int symbol_type = (flags >> SOM_SYMBOL_TYPE_SH) & SOM_SYMBOL_TYPE_MASK; unsigned int symbol_scope = (flags >> SOM_SYMBOL_SCOPE_SH) & SOM_SYMBOL_SCOPE_MASK; CORE_ADDR symbol_value = bfd_getb32 (bufp->symbol_value); asection *section = NULL; QUIT; /* Compute the section. */ switch (symbol_scope) { case SS_EXTERNAL: if (symbol_type != ST_STORAGE) section = bfd_und_section_ptr; else section = bfd_com_section_ptr; break; case SS_UNSAT: if (symbol_type != ST_STORAGE) section = bfd_und_section_ptr; else section = bfd_com_section_ptr; break; case SS_UNIVERSAL: section = bfd_section_from_som_symbol (abfd, bufp); break; case SS_LOCAL: section = bfd_section_from_som_symbol (abfd, bufp); break; } switch (symbol_scope) { case SS_UNIVERSAL: case SS_EXTERNAL: switch (symbol_type) { case ST_SYM_EXT: case ST_ARG_EXT: continue; case ST_CODE: case ST_PRI_PROG: case ST_SEC_PROG: case ST_MILLICODE: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_text; symbol_value += text_offset; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_ENTRY: symname = bfd_getb32 (bufp->name) + stringtab; /* For a dynamic executable, ST_ENTRY symbols are the stubs, while the ST_CODE symbol is the real function. */ if (dynamic) ms_type = mst_solib_trampoline; else ms_type = mst_text; symbol_value += text_offset; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_STUB: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_solib_trampoline; symbol_value += text_offset; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_DATA: symname = bfd_getb32 (bufp->name) + stringtab; symbol_value += data_offset; ms_type = mst_data; break; default: continue; } break; #if 0 /* SS_GLOBAL and SS_LOCAL are two names for the same thing (!). */ case SS_GLOBAL: #endif case SS_LOCAL: switch (symbol_type) { case ST_SYM_EXT: case ST_ARG_EXT: continue; case ST_CODE: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_file_text; symbol_value += text_offset; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); check_strange_names: /* Utah GCC 2.5, FSF GCC 2.6 and later generate correct local label prefixes for stabs, constant data, etc. So we need only filter out L$ symbols which are left in due to limitations in how GAS generates SOM relocations. When linking in the HPUX C-library the HP linker has the nasty habit of placing section symbols from the literal subspaces in the middle of the program's text. Filter those out as best we can. Check for first and last character being '$'. And finally, the newer HP compilers emit crud like $PIC_foo$N in some circumstance (PIC code I guess). It's also claimed that they emit D$ symbols too. What stupidity. */ if ((symname[0] == 'L' && symname[1] == '$') || (symname[0] == '$' && symname[strlen (symname) - 1] == '$') || (symname[0] == 'D' && symname[1] == '$') || (strncmp (symname, "L0\001", 3) == 0) || (strncmp (symname, "$PIC", 4) == 0)) continue; break; case ST_PRI_PROG: case ST_SEC_PROG: case ST_MILLICODE: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_file_text; symbol_value += text_offset; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_ENTRY: symname = bfd_getb32 (bufp->name) + stringtab; /* SS_LOCAL symbols in a shared library do not have export stubs, so we do not have to worry about using mst_file_text vs mst_solib_trampoline here like we do for SS_UNIVERSAL and SS_EXTERNAL symbols above. */ ms_type = mst_file_text; symbol_value += text_offset; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_STUB: symname = bfd_getb32 (bufp->name) + stringtab; ms_type = mst_solib_trampoline; symbol_value += text_offset; symbol_value = gdbarch_addr_bits_remove (gdbarch, symbol_value); break; case ST_DATA: symname = bfd_getb32 (bufp->name) + stringtab; symbol_value += data_offset; ms_type = mst_file_data; goto check_strange_names; default: continue; } break; /* This can happen for common symbols when -E is passed to the final link. No idea _why_ that would make the linker force common symbols to have an SS_UNSAT scope, but it does. This also happens for weak symbols, but their type is ST_DATA. */ case SS_UNSAT: switch (symbol_type) { case ST_STORAGE: case ST_DATA: symname = bfd_getb32 (bufp->name) + stringtab; symbol_value += data_offset; ms_type = mst_data; break; default: continue; } break; default: continue; } if (bfd_getb32 (bufp->name) > obj_som_stringtab_size (abfd)) error (_("Invalid symbol data; bad HP string table offset: %s"), plongest (bfd_getb32 (bufp->name))); if (bfd_is_const_section (section)) { struct obj_section *iter; ALL_OBJFILE_OSECTIONS (objfile, iter) { if (bfd_is_const_section (iter->the_bfd_section)) continue; if (obj_section_addr (iter) <= symbol_value && symbol_value < obj_section_endaddr (iter)) { section = iter->the_bfd_section; break; } } } prim_record_minimal_symbol_and_info (symname, symbol_value, ms_type, gdb_bfd_section_index (objfile->obfd, section), objfile); } do_cleanups (cleanup); }
/* Function to display source in the source window. */ enum tui_status tui_set_source_content (struct symtab *s, int line_no, int noerror) { enum tui_status ret = TUI_FAILURE; if (s != (struct symtab *) NULL) { FILE *stream; int i, desc, c, line_width, nlines; char *src_line = 0; if ((ret = tui_alloc_source_buffer (TUI_SRC_WIN)) == TUI_SUCCESS) { line_width = TUI_SRC_WIN->generic.width - 1; /* Take hilite (window border) into account, when calculating the number of lines. */ nlines = (line_no + (TUI_SRC_WIN->generic.height - 2)) - line_no; desc = open_source_file (s); if (desc < 0) { if (!noerror) { char *name = alloca (strlen (s->filename) + 100); sprintf (name, "%s:%d", s->filename, line_no); print_sys_errmsg (name, errno); } ret = TUI_FAILURE; } else { if (s->line_charpos == 0) find_source_lines (s, desc); if (line_no < 1 || line_no > s->nlines) { close (desc); printf_unfiltered ( "Line number %d out of range; %s has %d lines.\n", line_no, s->filename, s->nlines); } else if (lseek (desc, s->line_charpos[line_no - 1], 0) < 0) { close (desc); perror_with_name (s->filename); } else { int offset, cur_line_no, cur_line, cur_len, threshold; struct tui_gen_win_info *locator = tui_locator_win_info_ptr (); struct tui_source_info *src = &TUI_SRC_WIN->detail.source_info; if (TUI_SRC_WIN->generic.title) xfree (TUI_SRC_WIN->generic.title); TUI_SRC_WIN->generic.title = xstrdup (s->filename); if (src->filename) xfree (src->filename); src->filename = xstrdup (s->filename); /* Determine the threshold for the length of the line and the offset to start the display. */ offset = src->horizontal_offset; threshold = (line_width - 1) + offset; stream = fdopen (desc, FOPEN_RT); clearerr (stream); cur_line = 0; src->gdbarch = get_objfile_arch (s->objfile); src->start_line_or_addr.loa = LOA_LINE; cur_line_no = src->start_line_or_addr.u.line_no = line_no; if (offset > 0) src_line = (char *) xmalloc ( (threshold + 1) * sizeof (char)); while (cur_line < nlines) { struct tui_win_element *element = (struct tui_win_element *) TUI_SRC_WIN->generic.content[cur_line]; /* Get the first character in the line. */ c = fgetc (stream); if (offset == 0) src_line = ((struct tui_win_element *) TUI_SRC_WIN->generic.content[ cur_line])->which_element.source.line; /* Init the line with the line number. */ sprintf (src_line, "%-6d", cur_line_no); cur_len = strlen (src_line); i = cur_len - ((cur_len / tui_default_tab_len ()) * tui_default_tab_len ()); while (i < tui_default_tab_len ()) { src_line[cur_len] = ' '; i++; cur_len++; } src_line[cur_len] = (char) 0; /* Set whether element is the execution point and whether there is a break point on it. */ element->which_element.source.line_or_addr.loa = LOA_LINE; element->which_element.source.line_or_addr.u.line_no = cur_line_no; element->which_element.source.is_exec_point = (filename_cmp (((struct tui_win_element *) locator->content[0])->which_element.locator.file_name, s->filename) == 0 && cur_line_no == ((struct tui_win_element *) locator->content[0])->which_element.locator.line_no); if (c != EOF) { i = strlen (src_line) - 1; do { if ((c != '\n') && (c != '\r') && (++i < threshold)) { if (c < 040 && c != '\t') { src_line[i++] = '^'; src_line[i] = c + 0100; } else if (c == 0177) { src_line[i++] = '^'; src_line[i] = '?'; } else { /* Store the charcter in the line buffer. If it is a tab, then translate to the correct number of chars so we don't overwrite our buffer. */ if (c == '\t') { int j, max_tab_len = tui_default_tab_len (); for (j = i - ((i / max_tab_len) * max_tab_len); j < max_tab_len && i < threshold; i++, j++) src_line[i] = ' '; i--; } else src_line[i] = c; } src_line[i + 1] = 0; } else { /* If we have not reached EOL, then eat chars until we do. */ while (c != EOF && c != '\n' && c != '\r') c = fgetc (stream); /* Handle non-'\n' end-of-line. */ if (c == '\r' && (c = fgetc (stream)) != '\n' && c != EOF) { ungetc (c, stream); c = '\r'; } } } while (c != EOF && c != '\n' && c != '\r' && i < threshold && (c = fgetc (stream))); } /* Now copy the line taking the offset into account. */ if (strlen (src_line) > offset) strcpy (((struct tui_win_element *) TUI_SRC_WIN->generic.content[cur_line])->which_element.source.line, &src_line[offset]); else ((struct tui_win_element *) TUI_SRC_WIN->generic.content[ cur_line])->which_element.source.line[0] = (char) 0; cur_line++; cur_line_no++; } if (offset > 0) xfree (src_line); fclose (stream); TUI_SRC_WIN->generic.content_size = nlines; ret = TUI_SUCCESS; } } } } return ret; }
/* Evaluate a location description, starting at DATA and with length SIZE, to find the current location of variable VAR in the context of FRAME. */ static struct value * dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame, gdb_byte *data, unsigned short size, struct dwarf2_per_cu_data *per_cu) { struct value *retval; struct dwarf_expr_baton baton; struct dwarf_expr_context *ctx; if (size == 0) { retval = allocate_value (SYMBOL_TYPE (var)); VALUE_LVAL (retval) = not_lval; set_value_optimized_out (retval, 1); return retval; } baton.frame = frame; baton.objfile = dwarf2_per_cu_objfile (per_cu); ctx = new_dwarf_expr_context (); ctx->gdbarch = get_objfile_arch (baton.objfile); ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); ctx->baton = &baton; ctx->read_reg = dwarf_expr_read_reg; ctx->read_mem = dwarf_expr_read_mem; ctx->get_frame_base = dwarf_expr_frame_base; ctx->get_tls_address = dwarf_expr_tls_address; dwarf_expr_eval (ctx, data, size); if (ctx->num_pieces > 0) { int i; long offset = 0; bfd_byte *contents; retval = allocate_value (SYMBOL_TYPE (var)); contents = value_contents_raw (retval); for (i = 0; i < ctx->num_pieces; i++) { struct dwarf_expr_piece *p = &ctx->pieces[i]; if (p->in_reg) { struct gdbarch *arch = get_frame_arch (frame); bfd_byte regval[MAX_REGISTER_SIZE]; int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->value); get_frame_register (frame, gdb_regnum, regval); memcpy (contents + offset, regval, p->size); } else /* In memory? */ { read_memory (p->value, contents + offset, p->size); } offset += p->size; } } else if (ctx->in_reg) { struct gdbarch *arch = get_frame_arch (frame); CORE_ADDR dwarf_regnum = dwarf_expr_fetch (ctx, 0); int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, dwarf_regnum); retval = value_from_register (SYMBOL_TYPE (var), gdb_regnum, frame); } else { CORE_ADDR address = dwarf_expr_fetch (ctx, 0); retval = allocate_value (SYMBOL_TYPE (var)); VALUE_LVAL (retval) = lval_memory; set_value_lazy (retval, 1); set_value_address (retval, address); } set_value_initialized (retval, ctx->initialized); free_dwarf_expr_context (ctx); return retval; }