1 /* Definitions for targets which report shared library events. 2 3 Copyright (C) 2007-2024 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "objfiles.h" 21 #include "solist.h" 22 #include "symtab.h" 23 #include "symfile.h" 24 #include "target.h" 25 #include "solib-target.h" 26 #include <vector> 27 #include "inferior.h" 28 29 /* Private data for each loaded library. */ 30 struct lm_info_target final : public lm_info 31 { 32 /* The library's name. The name is normally kept in the struct 33 so_list; it is only here during XML parsing. */ 34 std::string name; 35 36 /* The target can either specify segment bases or section bases, not 37 both. */ 38 39 /* The base addresses for each independently relocatable segment of 40 this shared library. */ 41 std::vector<CORE_ADDR> segment_bases; 42 43 /* The base addresses for each independently allocatable, 44 relocatable section of this shared library. */ 45 std::vector<CORE_ADDR> section_bases; 46 47 /* The cached offsets for each section of this shared library, 48 determined from SEGMENT_BASES, or SECTION_BASES. */ 49 section_offsets offsets; 50 }; 51 52 using lm_info_target_up = std::unique_ptr<lm_info_target>; 53 54 #if !defined(HAVE_LIBEXPAT) 55 56 static std::vector<lm_info_target_up> 57 solib_target_parse_libraries (const char *library) 58 { 59 static int have_warned; 60 61 if (!have_warned) 62 { 63 have_warned = 1; 64 warning (_("Can not parse XML library list; XML support was disabled " 65 "at compile time")); 66 } 67 68 return {}; 69 } 70 71 #else /* HAVE_LIBEXPAT */ 72 73 #include "xml-support.h" 74 75 /* Handle the start of a <segment> element. */ 76 77 static void 78 library_list_start_segment (struct gdb_xml_parser *parser, 79 const struct gdb_xml_element *element, 80 void *user_data, 81 std::vector<gdb_xml_value> &attributes) 82 { 83 auto *list = (std::vector<lm_info_target_up> *) user_data; 84 lm_info_target *last = list->back ().get (); 85 ULONGEST *address_p 86 = (ULONGEST *) xml_find_attribute (attributes, "address")->value.get (); 87 CORE_ADDR address = (CORE_ADDR) *address_p; 88 89 if (!last->section_bases.empty ()) 90 gdb_xml_error (parser, 91 _("Library list with both segments and sections")); 92 93 last->segment_bases.push_back (address); 94 } 95 96 static void 97 library_list_start_section (struct gdb_xml_parser *parser, 98 const struct gdb_xml_element *element, 99 void *user_data, 100 std::vector<gdb_xml_value> &attributes) 101 { 102 auto *list = (std::vector<lm_info_target_up> *) user_data; 103 lm_info_target *last = list->back ().get (); 104 ULONGEST *address_p 105 = (ULONGEST *) xml_find_attribute (attributes, "address")->value.get (); 106 CORE_ADDR address = (CORE_ADDR) *address_p; 107 108 if (!last->segment_bases.empty ()) 109 gdb_xml_error (parser, 110 _("Library list with both segments and sections")); 111 112 last->section_bases.push_back (address); 113 } 114 115 /* Handle the start of a <library> element. */ 116 117 static void 118 library_list_start_library (struct gdb_xml_parser *parser, 119 const struct gdb_xml_element *element, 120 void *user_data, 121 std::vector<gdb_xml_value> &attributes) 122 { 123 auto *list = (std::vector<lm_info_target_up> *) user_data; 124 lm_info_target *item = new lm_info_target; 125 item->name 126 = (const char *) xml_find_attribute (attributes, "name")->value.get (); 127 128 list->emplace_back (item); 129 } 130 131 static void 132 library_list_end_library (struct gdb_xml_parser *parser, 133 const struct gdb_xml_element *element, 134 void *user_data, const char *body_text) 135 { 136 auto *list = (std::vector<lm_info_target_up> *) user_data; 137 lm_info_target *lm_info = list->back ().get (); 138 139 if (lm_info->segment_bases.empty () && lm_info->section_bases.empty ()) 140 gdb_xml_error (parser, _("No segment or section bases defined")); 141 } 142 143 144 /* Handle the start of a <library-list> element. */ 145 146 static void 147 library_list_start_list (struct gdb_xml_parser *parser, 148 const struct gdb_xml_element *element, 149 void *user_data, 150 std::vector<gdb_xml_value> &attributes) 151 { 152 struct gdb_xml_value *version = xml_find_attribute (attributes, "version"); 153 154 /* #FIXED attribute may be omitted, Expat returns NULL in such case. */ 155 if (version != NULL) 156 { 157 const char *string = (const char *) version->value.get (); 158 159 if (strcmp (string, "1.0") != 0) 160 gdb_xml_error (parser, 161 _("Library list has unsupported version \"%s\""), 162 string); 163 } 164 } 165 166 /* The allowed elements and attributes for an XML library list. 167 The root element is a <library-list>. */ 168 169 static const struct gdb_xml_attribute segment_attributes[] = { 170 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, 171 { NULL, GDB_XML_AF_NONE, NULL, NULL } 172 }; 173 174 static const struct gdb_xml_attribute section_attributes[] = { 175 { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, 176 { NULL, GDB_XML_AF_NONE, NULL, NULL } 177 }; 178 179 static const struct gdb_xml_element library_children[] = { 180 { "segment", segment_attributes, NULL, 181 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, 182 library_list_start_segment, NULL }, 183 { "section", section_attributes, NULL, 184 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, 185 library_list_start_section, NULL }, 186 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 187 }; 188 189 static const struct gdb_xml_attribute library_attributes[] = { 190 { "name", GDB_XML_AF_NONE, NULL, NULL }, 191 { NULL, GDB_XML_AF_NONE, NULL, NULL } 192 }; 193 194 static const struct gdb_xml_element library_list_children[] = { 195 { "library", library_attributes, library_children, 196 GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, 197 library_list_start_library, library_list_end_library }, 198 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 199 }; 200 201 static const struct gdb_xml_attribute library_list_attributes[] = { 202 { "version", GDB_XML_AF_OPTIONAL, NULL, NULL }, 203 { NULL, GDB_XML_AF_NONE, NULL, NULL } 204 }; 205 206 static const struct gdb_xml_element library_list_elements[] = { 207 { "library-list", library_list_attributes, library_list_children, 208 GDB_XML_EF_NONE, library_list_start_list, NULL }, 209 { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } 210 }; 211 212 static std::vector<lm_info_target_up> 213 solib_target_parse_libraries (const char *library) 214 { 215 std::vector<lm_info_target_up> result; 216 217 if (gdb_xml_parse_quick (_("target library list"), "library-list.dtd", 218 library_list_elements, library, &result) == 0) 219 { 220 /* Parsed successfully. */ 221 return result; 222 } 223 224 result.clear (); 225 return result; 226 } 227 #endif 228 229 static owning_intrusive_list<solib> 230 solib_target_current_sos (void) 231 { 232 owning_intrusive_list<solib> sos; 233 234 /* Fetch the list of shared libraries. */ 235 std::optional<gdb::char_vector> library_document 236 = target_read_stralloc (current_inferior ()->top_target (), 237 TARGET_OBJECT_LIBRARIES, NULL); 238 if (!library_document) 239 return {}; 240 241 /* Parse the list. */ 242 std::vector<lm_info_target_up> library_list 243 = solib_target_parse_libraries (library_document->data ()); 244 245 /* Build a struct solib for each entry on the list. */ 246 for (lm_info_target_up &info : library_list) 247 { 248 auto &new_solib = sos.emplace_back (); 249 250 /* We don't need a copy of the name in INFO anymore. */ 251 new_solib.so_name = std::move (info->name); 252 new_solib.so_original_name = new_solib.so_name; 253 new_solib.lm_info = std::move (info); 254 } 255 256 return sos; 257 } 258 259 static void 260 solib_target_solib_create_inferior_hook (int from_tty) 261 { 262 /* Nothing needed. */ 263 } 264 265 static void 266 solib_target_relocate_section_addresses (solib &so, target_section *sec) 267 { 268 CORE_ADDR offset; 269 auto *li = gdb::checked_static_cast<lm_info_target *> (so.lm_info.get ()); 270 271 /* Build the offset table only once per object file. We can not do 272 it any earlier, since we need to open the file first. */ 273 if (li->offsets.empty ()) 274 { 275 int num_sections = gdb_bfd_count_sections (so.abfd.get ()); 276 277 li->offsets.assign (num_sections, 0); 278 279 if (!li->section_bases.empty ()) 280 { 281 int i; 282 asection *sect; 283 int num_alloc_sections = 0; 284 285 for (i = 0, sect = so.abfd->sections; 286 sect != NULL; 287 i++, sect = sect->next) 288 if ((bfd_section_flags (sect) & SEC_ALLOC)) 289 num_alloc_sections++; 290 291 if (num_alloc_sections != li->section_bases.size ()) 292 warning (_("\ 293 Could not relocate shared library \"%s\": wrong number of ALLOC sections"), 294 so.so_name.c_str ()); 295 else 296 { 297 int bases_index = 0; 298 int found_range = 0; 299 300 so.addr_low = ~(CORE_ADDR) 0; 301 so.addr_high = 0; 302 for (i = 0, sect = so.abfd->sections; 303 sect != NULL; 304 i++, sect = sect->next) 305 { 306 if (!(bfd_section_flags (sect) & SEC_ALLOC)) 307 continue; 308 if (bfd_section_size (sect) > 0) 309 { 310 CORE_ADDR low, high; 311 312 low = li->section_bases[i]; 313 high = low + bfd_section_size (sect) - 1; 314 315 if (low < so.addr_low) 316 so.addr_low = low; 317 if (high > so.addr_high) 318 so.addr_high = high; 319 gdb_assert (so.addr_low <= so.addr_high); 320 found_range = 1; 321 } 322 li->offsets[i] = li->section_bases[bases_index]; 323 bases_index++; 324 } 325 if (!found_range) 326 so.addr_low = so.addr_high = 0; 327 gdb_assert (so.addr_low <= so.addr_high); 328 } 329 } 330 else if (!li->segment_bases.empty ()) 331 { 332 symfile_segment_data_up data 333 = get_symfile_segment_data (so.abfd.get ()); 334 335 if (data == NULL) 336 warning (_("\ 337 Could not relocate shared library \"%s\": no segments"), so.so_name.c_str ()); 338 else 339 { 340 ULONGEST orig_delta; 341 int i; 342 343 if (!symfile_map_offsets_to_segments (so.abfd.get (), data.get (), 344 li->offsets, 345 li->segment_bases.size (), 346 li->segment_bases.data ())) 347 warning (_("\ 348 Could not relocate shared library \"%s\": bad offsets"), so.so_name.c_str ()); 349 350 /* Find the range of addresses to report for this library in 351 "info sharedlibrary". Report any consecutive segments 352 which were relocated as a single unit. */ 353 gdb_assert (li->segment_bases.size () > 0); 354 orig_delta = li->segment_bases[0] - data->segments[0].base; 355 356 for (i = 1; i < data->segments.size (); i++) 357 { 358 /* If we have run out of offsets, assume all 359 remaining segments have the same offset. */ 360 if (i >= li->segment_bases.size ()) 361 continue; 362 363 /* If this segment does not have the same offset, do 364 not include it in the library's range. */ 365 if (li->segment_bases[i] - data->segments[i].base 366 != orig_delta) 367 break; 368 } 369 370 so.addr_low = li->segment_bases[0]; 371 so.addr_high = (data->segments[i - 1].base 372 + data->segments[i - 1].size 373 + orig_delta); 374 gdb_assert (so.addr_low <= so.addr_high); 375 } 376 } 377 } 378 379 offset = li->offsets[gdb_bfd_section_index (sec->the_bfd_section->owner, 380 sec->the_bfd_section)]; 381 sec->addr += offset; 382 sec->endaddr += offset; 383 } 384 385 static int 386 solib_target_open_symbol_file_object (int from_tty) 387 { 388 /* We can't locate the main symbol file based on the target's 389 knowledge; the user has to specify it. */ 390 return 0; 391 } 392 393 static int 394 solib_target_in_dynsym_resolve_code (CORE_ADDR pc) 395 { 396 /* We don't have a range of addresses for the dynamic linker; there 397 may not be one in the program's address space. So only report 398 PLT entries (which may be import stubs). */ 399 return in_plt_section (pc); 400 } 401 402 const solib_ops solib_target_so_ops = 403 { 404 solib_target_relocate_section_addresses, 405 nullptr, 406 nullptr, 407 solib_target_solib_create_inferior_hook, 408 solib_target_current_sos, 409 solib_target_open_symbol_file_object, 410 solib_target_in_dynsym_resolve_code, 411 solib_bfd_open, 412 nullptr, 413 nullptr, 414 nullptr, 415 nullptr, 416 default_find_solib_addr, 417 }; 418