X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gdb%2Fobjfiles.c;h=0b07e3709161139fd4ad75448dfa2aa29b4997a2;hb=18f5de3bf843256607810db3753335f995bbcc97;hp=c241e8fa38ea04823c999dd7c355a528ecb0e938;hpb=4c38e0a4fcb69f8586d8db0b9cdb8dbab5980811;p=binutils-gdb.git diff --git a/gdb/objfiles.c b/gdb/objfiles.c index c241e8fa38e..0b07e370916 100644 --- a/gdb/objfiles.c +++ b/gdb/objfiles.c @@ -378,6 +378,42 @@ terminate_minimal_symbol_table (struct objfile *objfile) } } +/* Iterator on PARENT and every separate debug objfile of PARENT. + The usage pattern is: + for (objfile = parent; + objfile; + objfile = objfile_separate_debug_iterate (parent, objfile)) + ... +*/ + +struct objfile * +objfile_separate_debug_iterate (const struct objfile *parent, + const struct objfile *objfile) +{ + struct objfile *res; + + res = objfile->separate_debug_objfile; + if (res) + return res; + + res = objfile->separate_debug_objfile_link; + if (res) + return res; + + /* Common case where there is no separate debug objfile. */ + if (objfile == parent) + return NULL; + + for (res = objfile->separate_debug_objfile_backlink; + res != parent; + res = res->separate_debug_objfile_backlink) + { + gdb_assert (res != NULL); + if (res->separate_debug_objfile_link) + return res->separate_debug_objfile_link; + } + return NULL; +} /* Put one object file before a specified on in the global list. This can be used to make sure an object file is destroyed before @@ -455,6 +491,41 @@ unlink_objfile (struct objfile *objfile) _("unlink_objfile: objfile already unlinked")); } +/* Add OBJFILE as a separate debug objfile of PARENT. */ + +void +add_separate_debug_objfile (struct objfile *objfile, struct objfile *parent) +{ + gdb_assert (objfile && parent); + + /* Must not be already in a list. */ + gdb_assert (objfile->separate_debug_objfile_backlink == NULL); + gdb_assert (objfile->separate_debug_objfile_link == NULL); + + objfile->separate_debug_objfile_backlink = parent; + objfile->separate_debug_objfile_link = parent->separate_debug_objfile; + parent->separate_debug_objfile = objfile; + + /* Put the separate debug object before the normal one, this is so that + usage of the ALL_OBJFILES_SAFE macro will stay safe. */ + put_objfile_before (objfile, parent); +} + +/* Free all separate debug objfile of OBJFILE, but don't free OBJFILE + itself. */ + +void +free_objfile_separate_debug (struct objfile *objfile) +{ + struct objfile *child; + + for (child = objfile->separate_debug_objfile; child;) + { + struct objfile *next_child = child->separate_debug_objfile_link; + free_objfile (child); + child = next_child; + } +} /* Destroy an objfile and all the symtabs and psymtabs under it. Note that as much as possible is allocated on the objfile_obstack @@ -475,16 +546,38 @@ unlink_objfile (struct objfile *objfile) void free_objfile (struct objfile *objfile) { - if (objfile->separate_debug_objfile) - { - free_objfile (objfile->separate_debug_objfile); - } - + /* Free all separate debug objfiles. */ + free_objfile_separate_debug (objfile); + if (objfile->separate_debug_objfile_backlink) { /* We freed the separate debug file, make sure the base objfile doesn't reference it. */ - objfile->separate_debug_objfile_backlink->separate_debug_objfile = NULL; + struct objfile *child; + + child = objfile->separate_debug_objfile_backlink->separate_debug_objfile; + + if (child == objfile) + { + /* OBJFILE is the first child. */ + objfile->separate_debug_objfile_backlink->separate_debug_objfile = + objfile->separate_debug_objfile_link; + } + else + { + /* Find OBJFILE in the list. */ + while (1) + { + if (child->separate_debug_objfile_link == objfile) + { + child->separate_debug_objfile_link = + objfile->separate_debug_objfile_link; + break; + } + child = child->separate_debug_objfile_link; + gdb_assert (child); + } + } } /* Remove any references to this objfile in the global value @@ -600,9 +693,11 @@ free_all_objfiles (void) } /* Relocate OBJFILE to NEW_OFFSETS. There should be OBJFILE->NUM_SECTIONS - entries in new_offsets. */ -void -objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) + entries in new_offsets. SEPARATE_DEBUG_OBJFILE is not touched here. + Return non-zero iff any change happened. */ + +static int +objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets) { struct obj_section *s; struct section_offsets *delta = @@ -620,7 +715,7 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) something_changed = 1; } if (!something_changed) - return; + return 0; } /* OK, get all the symtabs. */ @@ -757,8 +852,61 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) obj_section_addr (s)); } + /* Data changed. */ + return 1; +} + +/* Relocate OBJFILE to NEW_OFFSETS. There should be OBJFILE->NUM_SECTIONS + entries in new_offsets. Process also OBJFILE's SEPARATE_DEBUG_OBJFILEs. + + The number and ordering of sections does differ between the two objfiles. + Only their names match. Also the file offsets will differ (objfile being + possibly prelinked but separate_debug_objfile is probably not prelinked) but + the in-memory absolute address as specified by NEW_OFFSETS must match both + files. */ + +void +objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets) +{ + struct objfile *debug_objfile; + int changed = 0; + + changed |= objfile_relocate1 (objfile, new_offsets); + + for (debug_objfile = objfile->separate_debug_objfile; + debug_objfile; + debug_objfile = objfile_separate_debug_iterate (objfile, debug_objfile)) + { + struct section_addr_info *objfile_addrs; + struct section_offsets *new_debug_offsets; + int new_debug_num_sections; + struct cleanup *my_cleanups; + + objfile_addrs = build_section_addr_info_from_objfile (objfile); + my_cleanups = make_cleanup (xfree, objfile_addrs); + + /* Here OBJFILE_ADDRS contain the correct absolute addresses, the + relative ones must be already created according to debug_objfile. */ + + addr_info_make_relative (objfile_addrs, debug_objfile->obfd); + + gdb_assert (debug_objfile->num_sections + == bfd_count_sections (debug_objfile->obfd)); + new_debug_offsets = xmalloc (SIZEOF_N_SECTION_OFFSETS + (debug_objfile->num_sections)); + make_cleanup (xfree, new_debug_offsets); + relative_addr_info_to_section_offsets (new_debug_offsets, + debug_objfile->num_sections, + objfile_addrs); + + changed |= objfile_relocate1 (debug_objfile, new_debug_offsets); + + do_cleanups (my_cleanups); + } + /* Relocate breakpoints as necessary, after things are relocated. */ - breakpoint_re_set (); + if (changed) + breakpoint_re_set (); } /* Return non-zero if OBJFILE has partial symbols. */ @@ -778,25 +926,16 @@ objfile_has_full_symbols (struct objfile *objfile) } /* Return non-zero if OBJFILE has full or partial symbols, either directly - or throught its separate debug file. */ + or through a separate debug file. */ int objfile_has_symbols (struct objfile *objfile) { - struct objfile *separate_objfile; - - if (objfile_has_partial_symbols (objfile) - || objfile_has_full_symbols (objfile)) - return 1; - - separate_objfile = objfile->separate_debug_objfile; - if (separate_objfile == NULL) - return 0; - - if (objfile_has_partial_symbols (separate_objfile) - || objfile_has_full_symbols (separate_objfile)) - return 1; + struct objfile *o; + for (o = objfile; o; o = objfile_separate_debug_iterate (objfile, o)) + if (objfile_has_partial_symbols (o) || objfile_has_full_symbols (o)) + return 1; return 0; }