1181638Skmacy/* Read a symbol table in MIPS' format (Third-Eye). 2181638Skmacy 3181638Skmacy Copyright (C) 1986-2023 Free Software Foundation, Inc. 4181638Skmacy 5181638Skmacy Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU. Major work 6181638Skmacy by Per Bothner, John Gilmore and Ian Lance Taylor at Cygnus Support. 7181638Skmacy 8181638Skmacy This file is part of GDB. 9181638Skmacy 10181638Skmacy This program is free software; you can redistribute it and/or modify 11181638Skmacy it under the terms of the GNU General Public License as published by 12181638Skmacy the Free Software Foundation; either version 3 of the License, or 13181638Skmacy (at your option) any later version. 14181638Skmacy 15181638Skmacy This program is distributed in the hope that it will be useful, 16181638Skmacy but WITHOUT ANY WARRANTY; without even the implied warranty of 17181638Skmacy MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18181638Skmacy GNU General Public License for more details. 19181638Skmacy 20181638Skmacy You should have received a copy of the GNU General Public License 21181638Skmacy along with this program. If not, see <http://www.gnu.org/licenses/>. */ 22181638Skmacy 23181638Skmacy/* Read symbols from an ECOFF file. Most of the work is done in 24181638Skmacy mdebugread.c. */ 25181638Skmacy 26181638Skmacy#include "defs.h" 27181638Skmacy#include "bfd.h" 28181638Skmacy#include "symtab.h" 29181638Skmacy#include "objfiles.h" 30181638Skmacy#include "stabsread.h" 31181638Skmacy#include "mdebugread.h" 32181638Skmacy 33181638Skmacy#include "coff/sym.h" 34181638Skmacy#include "coff/internal.h" 35181638Skmacy#include "coff/ecoff.h" 36181638Skmacy#include "libcoff.h" /* Private BFD COFF information. */ 37181638Skmacy#include "libecoff.h" /* Private BFD ECOFF information. */ 38216956Srwatson#include "elf/common.h" 39216956Srwatson#include "elf/internal.h" 40181638Skmacy#include "elf/mips.h" 41181638Skmacy 42181638Skmacy#include "psymtab.h" 43181638Skmacy 44181638Skmacystatic void 45181638Skmacyread_alphacoff_dynamic_symtab (minimal_symbol_reader &, 46181638Skmacy struct objfile *objfile); 47181638Skmacy 48181638Skmacy/* Initialize anything that needs initializing when a completely new 49181638Skmacy symbol file is specified (not just adding some symbols from another 50190627Sdfr file, e.g. a shared library). */ 51190627Sdfr 52181638Skmacystatic void 53181638Skmacymipscoff_new_init (struct objfile *ignore) 54181638Skmacy{ 55181638Skmacy stabsread_new_init (); 56181638Skmacy} 57181638Skmacy 58181638Skmacy/* Initialize to read a symbol file (nothing to do). */ 59181638Skmacy 60181638Skmacystatic void 61181638Skmacymipscoff_symfile_init (struct objfile *objfile) 62181638Skmacy{ 63181638Skmacy} 64181638Skmacy 65181638Skmacy/* Read a symbol file from a file. */ 66181638Skmacy 67181638Skmacystatic void 68181638Skmacymipscoff_symfile_read (struct objfile *objfile, symfile_add_flags symfile_flags) 69181638Skmacy{ 70181638Skmacy bfd *abfd = objfile->obfd.get (); 71181638Skmacy 72181638Skmacy minimal_symbol_reader reader (objfile); 73181638Skmacy 74181638Skmacy /* Now that the executable file is positioned at symbol table, 75181638Skmacy process it and define symbols accordingly. */ 76181638Skmacy 77181638Skmacy if (!((*ecoff_backend (abfd)->debug_swap.read_debug_info) 78181638Skmacy (abfd, NULL, &ecoff_data (abfd)->debug_info))) 79181638Skmacy error (_("Error reading symbol table: %s"), bfd_errmsg (bfd_get_error ())); 80181638Skmacy 81181638Skmacy mdebug_build_psymtabs (reader, objfile, &ecoff_backend (abfd)->debug_swap, 82181638Skmacy &ecoff_data (abfd)->debug_info); 83181638Skmacy 84181638Skmacy /* Add alpha coff dynamic symbols. */ 85181638Skmacy 86181638Skmacy read_alphacoff_dynamic_symtab (reader, objfile); 87181638Skmacy 88181638Skmacy /* Install any minimal symbols that have been collected as the current 89181638Skmacy minimal symbols for this objfile. */ 90181638Skmacy 91181638Skmacy reader.install (); 92181638Skmacy} 93181638Skmacy 94181638Skmacy/* Perform any local cleanups required when we are done with a 95181638Skmacy particular objfile. */ 96181638Skmacy 97181638Skmacystatic void 98181638Skmacymipscoff_symfile_finish (struct objfile *objfile) 99181638Skmacy{ 100181638Skmacy} 101181638Skmacy 102181638Skmacy/* Alpha OSF/1 encapsulates the dynamic symbols in ELF format in a 103181638Skmacy standard COFF section. The ELF format for the symbols differs from 104181638Skmacy the format defined in elf/external.h. It seems that a normal ELF 105181638Skmacy 32-bit format is used, and the representation only changes because 106181638Skmacy longs are 64-bit on the alpha. In addition, the handling of 107181638Skmacy text/data section indices for symbols is different from the ELF 108181638Skmacy ABI. As the BFD linker currently does not support dynamic linking 109181638Skmacy on the alpha, there seems to be no reason to pollute BFD with 110181638Skmacy another mixture of object file formats for now. */ 111181638Skmacy 112181638Skmacy/* Format of an alpha external ELF symbol. */ 113181638Skmacy 114181638Skmacytypedef struct 115181638Skmacy{ 116181638Skmacy unsigned char st_name[4]; /* Symbol name, index in string table. */ 117181638Skmacy unsigned char st_pad[4]; /* Pad to long word boundary. */ 118181638Skmacy unsigned char st_value[8]; /* Value of the symbol. */ 119181638Skmacy unsigned char st_size[4]; /* Associated symbol size. */ 120181638Skmacy unsigned char st_info[1]; /* Type and binding attributes. */ 121181638Skmacy unsigned char st_other[1]; /* No defined meaning, 0. */ 122181638Skmacy unsigned char st_shndx[2]; /* Associated section index. */ 123181638Skmacy} Elfalpha_External_Sym; 124181638Skmacy 125181638Skmacy/* Format of an alpha external ELF dynamic info structure. */ 126181638Skmacy 127181638Skmacytypedef struct 128181638Skmacy{ 129181638Skmacy unsigned char d_tag[4]; /* Tag. */ 130181638Skmacy unsigned char d_pad[4]; /* Pad to long word boundary. */ 131181638Skmacy union 132181638Skmacy { 133181638Skmacy unsigned char d_ptr[8]; /* Pointer value. */ 134181638Skmacy unsigned char d_val[4]; /* Integer value. */ 135181638Skmacy } 136181638Skmacy d_un; 137181638Skmacy} Elfalpha_External_Dyn; 138181638Skmacy 139181638Skmacy/* Struct to obtain the section pointers for alpha dynamic symbol info. */ 140181638Skmacy 141181638Skmacystruct alphacoff_dynsecinfo 142181638Skmacy{ 143181638Skmacy asection *sym_sect; /* Section pointer for .dynsym section. */ 144181638Skmacy asection *str_sect; /* Section pointer for .dynstr section. */ 145181638Skmacy asection *dyninfo_sect; /* Section pointer for .dynamic section. */ 146181638Skmacy asection *got_sect; /* Section pointer for .got section. */ 147181638Skmacy}; 148181638Skmacy 149181638Skmacy/* We are called once per section from read_alphacoff_dynamic_symtab. 150181638Skmacy We need to examine each section we are passed, check to see if it 151181638Skmacy is something we are interested in processing, and if so, stash away 152181638Skmacy some access information for the section. */ 153181638Skmacy 154181638Skmacystatic void 155181638Skmacyalphacoff_locate_sections (bfd *ignore_abfd, asection *sectp, void *sip) 156181638Skmacy{ 157181638Skmacy struct alphacoff_dynsecinfo *si; 158181638Skmacy 159181638Skmacy si = (struct alphacoff_dynsecinfo *) sip; 160181638Skmacy 161181638Skmacy if (strcmp (sectp->name, ".dynsym") == 0) 162181638Skmacy si->sym_sect = sectp; 163181638Skmacy else if (strcmp (sectp->name, ".dynstr") == 0) 164181638Skmacy si->str_sect = sectp; 165181638Skmacy else if (strcmp (sectp->name, ".dynamic") == 0) 166181638Skmacy si->dyninfo_sect = sectp; 167181638Skmacy else if (strcmp (sectp->name, ".got") == 0) 168181638Skmacy si->got_sect = sectp; 169181638Skmacy} 170181638Skmacy 171181638Skmacy/* Scan an alpha dynamic symbol table for symbols of interest and add 172181638Skmacy them to the minimal symbol table. */ 173181638Skmacy 174181638Skmacystatic void 175181638Skmacyread_alphacoff_dynamic_symtab (minimal_symbol_reader &reader, 176181638Skmacy struct objfile *objfile) 177181638Skmacy{ 178181638Skmacy bfd *abfd = objfile->obfd.get (); 179181638Skmacy struct alphacoff_dynsecinfo si; 180181638Skmacy int sym_count; 181181638Skmacy int i; 182181638Skmacy int stripped; 183181638Skmacy Elfalpha_External_Sym *x_symp; 184181638Skmacy gdb_byte *dyninfo_p; 185181638Skmacy gdb_byte *dyninfo_end; 186181638Skmacy int got_entry_size = 8; 187181638Skmacy int dt_mips_local_gotno = -1; 188181638Skmacy int dt_mips_gotsym = -1; 189181638Skmacy 190181638Skmacy /* We currently only know how to handle alpha dynamic symbols. */ 191182902Skmacy if (bfd_get_arch (abfd) != bfd_arch_alpha) 192181638Skmacy return; 193181638Skmacy 194181638Skmacy /* Locate the dynamic symbols sections and read them in. */ 195181638Skmacy memset ((char *) &si, 0, sizeof (si)); 196181638Skmacy bfd_map_over_sections (abfd, alphacoff_locate_sections, (void *) & si); 197181638Skmacy if (si.sym_sect == NULL || si.str_sect == NULL 198181638Skmacy || si.dyninfo_sect == NULL || si.got_sect == NULL) 199181638Skmacy return; 200181638Skmacy 201181638Skmacy gdb::byte_vector sym_sec (bfd_section_size (si.sym_sect)); 202181638Skmacy gdb::byte_vector str_sec (bfd_section_size (si.str_sect)); 203181638Skmacy gdb::byte_vector dyninfo_sec (bfd_section_size (si.dyninfo_sect)); 204181638Skmacy gdb::byte_vector got_sec (bfd_section_size (si.got_sect)); 205181638Skmacy 206181638Skmacy if (!bfd_get_section_contents (abfd, si.sym_sect, sym_sec.data (), 207181638Skmacy (file_ptr) 0, sym_sec.size ())) 208181638Skmacy return; 209181638Skmacy if (!bfd_get_section_contents (abfd, si.str_sect, str_sec.data (), 210181638Skmacy (file_ptr) 0, str_sec.size ())) 211181638Skmacy return; 212181638Skmacy if (!bfd_get_section_contents (abfd, si.dyninfo_sect, dyninfo_sec.data (), 213181638Skmacy (file_ptr) 0, dyninfo_sec.size ())) 214181638Skmacy return; 215181638Skmacy if (!bfd_get_section_contents (abfd, si.got_sect, got_sec.data (), 216181638Skmacy (file_ptr) 0, got_sec.size ())) 217181638Skmacy return; 218181638Skmacy 219181638Skmacy /* Find the number of local GOT entries and the index for the 220181638Skmacy first dynamic symbol in the GOT. */ 221181638Skmacy for ((dyninfo_p = dyninfo_sec.data (), 222181638Skmacy dyninfo_end = dyninfo_p + dyninfo_sec.size ()); 223181638Skmacy dyninfo_p < dyninfo_end; 224181638Skmacy dyninfo_p += sizeof (Elfalpha_External_Dyn)) 225181638Skmacy { 226181638Skmacy Elfalpha_External_Dyn *x_dynp = (Elfalpha_External_Dyn *) dyninfo_p; 227181638Skmacy long dyn_tag; 228181638Skmacy 229189699Sdfr dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_tag); 230189699Sdfr if (dyn_tag == DT_NULL) 231189699Sdfr break; 232189699Sdfr else if (dyn_tag == DT_MIPS_LOCAL_GOTNO) 233189699Sdfr { 234181638Skmacy if (dt_mips_local_gotno < 0) 235230916Sken dt_mips_local_gotno 236181638Skmacy = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val); 237181638Skmacy } 238 else if (dyn_tag == DT_MIPS_GOTSYM) 239 { 240 if (dt_mips_gotsym < 0) 241 dt_mips_gotsym 242 = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val); 243 } 244 } 245 if (dt_mips_local_gotno < 0 || dt_mips_gotsym < 0) 246 return; 247 248 /* Scan all dynamic symbols and enter them into the minimal symbol 249 table if appropriate. */ 250 sym_count = sym_sec.size () / sizeof (Elfalpha_External_Sym); 251 stripped = (bfd_get_symcount (abfd) == 0); 252 253 /* Skip first symbol, which is a null dummy. */ 254 for (i = 1, x_symp = (Elfalpha_External_Sym *) sym_sec.data () + 1; 255 i < sym_count; 256 i++, x_symp++) 257 { 258 unsigned long strx; 259 char *name; 260 bfd_vma sym_value; 261 unsigned char sym_info; 262 unsigned int sym_shndx; 263 int isglobal; 264 enum minimal_symbol_type ms_type; 265 266 strx = bfd_h_get_32 (abfd, (bfd_byte *) x_symp->st_name); 267 if (strx >= str_sec.size ()) 268 continue; 269 name = (char *) (str_sec.data () + strx); 270 if (*name == '\0' || *name == '.') 271 continue; 272 273 sym_value = bfd_h_get_64 (abfd, (bfd_byte *) x_symp->st_value); 274 sym_info = bfd_h_get_8 (abfd, (bfd_byte *) x_symp->st_info); 275 sym_shndx = bfd_h_get_16 (abfd, (bfd_byte *) x_symp->st_shndx); 276 if (sym_shndx >= (SHN_LORESERVE & 0xffff)) 277 sym_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff); 278 isglobal = (ELF_ST_BIND (sym_info) == STB_GLOBAL); 279 280 if (sym_shndx == SHN_UNDEF) 281 { 282 /* Handle undefined functions which are defined in a shared 283 library. */ 284 if (ELF_ST_TYPE (sym_info) != STT_FUNC 285 || ELF_ST_BIND (sym_info) != STB_GLOBAL) 286 continue; 287 288 ms_type = mst_solib_trampoline; 289 290 /* If sym_value is nonzero, it points to the shared library 291 trampoline entry, which is what we are looking for. 292 293 If sym_value is zero, then we have to get the GOT entry 294 for the symbol. 295 296 If the GOT entry is nonzero, it represents the quickstart 297 address of the function and we use that as the symbol 298 value. 299 300 If the GOT entry is zero, the function address has to be 301 resolved by the runtime loader before the executable is 302 started. We are unable to find any meaningful address 303 for these functions in the executable file, so we skip 304 them. */ 305 if (sym_value == 0) 306 { 307 int got_entry_offset = 308 (i - dt_mips_gotsym + dt_mips_local_gotno) * got_entry_size; 309 310 if (got_entry_offset < 0 311 || got_entry_offset >= got_sec.size ()) 312 continue; 313 sym_value = 314 bfd_h_get_64 (abfd, 315 (bfd_byte *) (got_sec.data () 316 + got_entry_offset)); 317 if (sym_value == 0) 318 continue; 319 } 320 } 321 else 322 { 323 /* Symbols defined in the executable itself. We only care 324 about them if this is a stripped executable, otherwise 325 they have been retrieved from the normal symbol table 326 already. */ 327 if (!stripped) 328 continue; 329 330 if (sym_shndx == SHN_MIPS_TEXT) 331 { 332 if (isglobal) 333 ms_type = mst_text; 334 else 335 ms_type = mst_file_text; 336 } 337 else if (sym_shndx == SHN_MIPS_DATA) 338 { 339 if (isglobal) 340 ms_type = mst_data; 341 else 342 ms_type = mst_file_data; 343 } 344 else if (sym_shndx == SHN_MIPS_ACOMMON) 345 { 346 if (isglobal) 347 ms_type = mst_bss; 348 else 349 ms_type = mst_file_bss; 350 } 351 else if (sym_shndx == SHN_ABS) 352 { 353 ms_type = mst_abs; 354 } 355 else 356 { 357 continue; 358 } 359 } 360 361 reader.record (name, sym_value, ms_type); 362 } 363} 364 365/* Initialization. */ 366 367static const struct sym_fns ecoff_sym_fns = 368{ 369 mipscoff_new_init, /* init anything gbl to entire symtab */ 370 mipscoff_symfile_init, /* read initial info, setup for sym_read() */ 371 mipscoff_symfile_read, /* read a symbol file into symtab */ 372 mipscoff_symfile_finish, /* finished with file, cleanup */ 373 default_symfile_offsets, /* dummy FIXME til implem sym reloc */ 374 default_symfile_segments, /* Get segment information from a file. */ 375 NULL, 376 default_symfile_relocate, /* Relocate a debug section. */ 377 NULL, /* sym_probe_fns */ 378}; 379 380void _initialize_mipsread (); 381void 382_initialize_mipsread () 383{ 384 add_symtab_fns (bfd_target_ecoff_flavour, &ecoff_sym_fns); 385} 386