static CORE_ADDR lm_base (void) { enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); struct minimal_symbol *got_sym; CORE_ADDR addr; gdb_byte buf[TIC6X_PTR_SIZE]; struct dsbt_info *info = get_dsbt_info (); /* One of our assumptions is that the main executable has been relocated. Bail out if this has not happened. (Note that post_create_inferior in infcmd.c will call solib_add prior to solib_create_inferior_hook. If we allow this to happen, lm_base_cache will be initialized with a bogus value. */ if (info->main_executable_lm_info == 0) return 0; /* If we already have a cached value, return it. */ if (info->lm_base_cache) return info->lm_base_cache; got_sym = lookup_minimal_symbol ("_GLOBAL_OFFSET_TABLE_", NULL, symfile_objfile); if (got_sym != 0) { addr = SYMBOL_VALUE_ADDRESS (got_sym); if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "lm_base: get addr %x by _GLOBAL_OFFSET_TABLE_.\n", (unsigned int) addr); } else if (scan_dyntag (DT_PLTGOT, exec_bfd, &addr)) { struct int_elf32_dsbt_loadmap *ldm; dsbt_get_initial_loadmaps (); ldm = info->exec_loadmap; addr += displacement_from_map (ldm, addr); if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "lm_base: get addr %x by DT_PLTGOT.\n", (unsigned int) addr); } else { if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "lm_base: _GLOBAL_OFFSET_TABLE_ not found.\n"); return 0; } addr += GOT_MODULE_OFFSET; if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "lm_base: _GLOBAL_OFFSET_TABLE_ + %d = %s\n", GOT_MODULE_OFFSET, hex_string_custom (addr, 8)); if (target_read_memory (addr, buf, sizeof buf) != 0) return 0; info->lm_base_cache = extract_unsigned_integer (buf, sizeof buf, byte_order); if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "lm_base: lm_base_cache = %s\n", hex_string_custom (info->lm_base_cache, 8)); return info->lm_base_cache; }
static int enable_break2 (void) { enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); int success = 0; char **bkpt_namep; asection *interp_sect; struct dsbt_info *info = get_dsbt_info (); if (exec_bfd == NULL) return 0; if (!target_has_execution) return 0; if (info->enable_break2_done) return 1; info->interp_text_sect_low = 0; info->interp_text_sect_high = 0; info->interp_plt_sect_low = 0; info->interp_plt_sect_high = 0; /* Find the .interp section; if not found, warn the user and drop into the old breakpoint at symbol code. */ interp_sect = bfd_get_section_by_name (exec_bfd, ".interp"); if (interp_sect) { unsigned int interp_sect_size; gdb_byte *buf; bfd *tmp_bfd = NULL; CORE_ADDR addr; gdb_byte addr_buf[TIC6X_PTR_SIZE]; struct int_elf32_dsbt_loadmap *ldm; volatile struct gdb_exception ex; /* Read the contents of the .interp section into a local buffer; the contents specify the dynamic linker this program uses. */ interp_sect_size = bfd_section_size (exec_bfd, interp_sect); buf = alloca (interp_sect_size); bfd_get_section_contents (exec_bfd, interp_sect, buf, 0, interp_sect_size); /* Now we need to figure out where the dynamic linker was loaded so that we can load its symbols and place a breakpoint in the dynamic linker itself. */ TRY_CATCH (ex, RETURN_MASK_ALL) { tmp_bfd = solib_bfd_open (buf); } if (tmp_bfd == NULL) { enable_break_failure_warning (); return 0; } dsbt_get_initial_loadmaps (); ldm = info->interp_loadmap; /* Record the relocated start and end address of the dynamic linker text and plt section for dsbt_in_dynsym_resolve_code. */ interp_sect = bfd_get_section_by_name (tmp_bfd, ".text"); if (interp_sect) { info->interp_text_sect_low = bfd_section_vma (tmp_bfd, interp_sect); info->interp_text_sect_low += displacement_from_map (ldm, info->interp_text_sect_low); info->interp_text_sect_high = info->interp_text_sect_low + bfd_section_size (tmp_bfd, interp_sect); } interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt"); if (interp_sect) { info->interp_plt_sect_low = bfd_section_vma (tmp_bfd, interp_sect); info->interp_plt_sect_low += displacement_from_map (ldm, info->interp_plt_sect_low); info->interp_plt_sect_high = info->interp_plt_sect_low + bfd_section_size (tmp_bfd, interp_sect); } addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name, "_dl_debug_addr"); if (addr == 0) { warning (_("Could not find symbol _dl_debug_addr in dynamic linker")); enable_break_failure_warning (); bfd_close (tmp_bfd); return 0; } if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: _dl_debug_addr (prior to relocation) = %s\n", hex_string_custom (addr, 8)); addr += displacement_from_map (ldm, addr); if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: _dl_debug_addr (after relocation) = %s\n", hex_string_custom (addr, 8)); /* Fetch the address of the r_debug struct. */ if (target_read_memory (addr, addr_buf, sizeof addr_buf) != 0) { warning (_("Unable to fetch contents of _dl_debug_addr " "(at address %s) from dynamic linker"), hex_string_custom (addr, 8)); } addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order); if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: _dl_debug_addr[0..3] = %s\n", hex_string_custom (addr, 8)); /* If it's zero, then the ldso hasn't initialized yet, and so there are no shared libs yet loaded. */ if (addr == 0) { if (solib_dsbt_debug) fprintf_unfiltered (gdb_stdlog, "enable_break: ldso not yet initialized\n"); /* Do not warn, but mark to run again. */ return 0; } /* Fetch the r_brk field. It's 8 bytes from the start of _dl_debug_addr. */ if (target_read_memory (addr + 8, addr_buf, sizeof addr_buf) != 0) { warning (_("Unable to fetch _dl_debug_addr->r_brk " "(at address %s) from dynamic linker"), hex_string_custom (addr + 8, 8)); enable_break_failure_warning (); bfd_close (tmp_bfd); return 0; } addr = extract_unsigned_integer (addr_buf, sizeof addr_buf, byte_order); /* We're done with the temporary bfd. */ bfd_close (tmp_bfd); /* We're also done with the loadmap. */ xfree (ldm); /* Remove all the solib event breakpoints. Their addresses may have changed since the last time we ran the program. */ remove_solib_event_breakpoints (); /* Now (finally!) create the solib breakpoint. */ create_solib_event_breakpoint (target_gdbarch, addr); info->enable_break2_done = 1; return 1; }