static int scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr) { int arch_size, step, sect_size; long dyn_tag; CORE_ADDR dyn_ptr, dyn_addr; gdb_byte *bufend, *bufstart, *buf; Elf32_External_Dyn *x_dynp_32; Elf64_External_Dyn *x_dynp_64; struct bfd_section *sect; struct target_section *target_section; if (abfd == NULL) return 0; if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) return 0; arch_size = bfd_get_arch_size (abfd); if (arch_size == -1) return 0; /* Find the start address of the .dynamic section. */ sect = bfd_get_section_by_name (abfd, ".dynamic"); if (sect == NULL) return 0; for (target_section = current_target_sections->sections; target_section < current_target_sections->sections_end; target_section++) if (sect == target_section->the_bfd_section) break; if (target_section < current_target_sections->sections_end) dyn_addr = target_section->addr; else { /* ABFD may come from OBJFILE acting only as a symbol file without being loaded into the target (see add_symbol_file_command). This case is such fallback to the file VMA address without the possibility of having the section relocated to its actual in-memory address. */ dyn_addr = bfd_section_vma (abfd, sect); } /* Read in .dynamic from the BFD. We will get the actual value from memory later. */ sect_size = bfd_section_size (abfd, sect); buf = bufstart = alloca (sect_size); if (!bfd_get_section_contents (abfd, sect, buf, 0, sect_size)) return 0; /* Iterate over BUF and scan for DYNTAG. If found, set PTR and return. */ step = (arch_size == 32) ? sizeof (Elf32_External_Dyn) : sizeof (Elf64_External_Dyn); for (bufend = buf + sect_size; buf < bufend; buf += step) { if (arch_size == 32) { x_dynp_32 = (Elf32_External_Dyn *) buf; dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_tag); dyn_ptr = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_un.d_ptr); } else { x_dynp_64 = (Elf64_External_Dyn *) buf; dyn_tag = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_tag); dyn_ptr = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_un.d_ptr); } if (dyn_tag == DT_NULL) return 0; if (dyn_tag == dyntag) { /* If requested, try to read the runtime value of this .dynamic entry. */ if (ptr) { struct type *ptr_type; gdb_byte ptr_buf[8]; CORE_ADDR ptr_addr; ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8; if (target_read_memory (ptr_addr, ptr_buf, arch_size / 8) == 0) dyn_ptr = extract_typed_address (ptr_buf, ptr_type); *ptr = dyn_ptr; } return 1; } } return 0; }
bfd_boolean _bfd_elf_parse_gnu_properties (bfd *abfd, Elf_Internal_Note *note) { const struct elf_backend_data *bed = get_elf_backend_data (abfd); unsigned int align_size = bed->s->elfclass == ELFCLASS64 ? 8 : 4; bfd_byte *ptr = (bfd_byte *) note->descdata; bfd_byte *ptr_end = ptr + note->descsz; if (note->descsz < 8 || (note->descsz % align_size) != 0) { bad_size: _bfd_error_handler (_("warning: %pB: corrupt GNU_PROPERTY_TYPE (%ld) size: %#lx"), abfd, note->type, note->descsz); return FALSE; } while (ptr != ptr_end) { unsigned int type; unsigned int datasz; elf_property *prop; if ((size_t) (ptr_end - ptr) < 8) goto bad_size; type = bfd_h_get_32 (abfd, ptr); datasz = bfd_h_get_32 (abfd, ptr + 4); ptr += 8; if (datasz > (size_t) (ptr_end - ptr)) { _bfd_error_handler (_("warning: %pB: corrupt GNU_PROPERTY_TYPE (%ld) type (0x%x) datasz: 0x%x"), abfd, note->type, type, datasz); /* Clear all properties. */ elf_properties (abfd) = NULL; return FALSE; } if (type >= GNU_PROPERTY_LOPROC) { if (bed->elf_machine_code == EM_NONE) { /* Ignore processor-specific properties with generic ELF target vector. They should be handled by the matching ELF target vector. */ goto next; } else if (type < GNU_PROPERTY_LOUSER && bed->parse_gnu_properties) { enum elf_property_kind kind = bed->parse_gnu_properties (abfd, type, ptr, datasz); if (kind == property_corrupt) { /* Clear all properties. */ elf_properties (abfd) = NULL; return FALSE; } else if (kind != property_ignored) goto next; } } else { switch (type) { case GNU_PROPERTY_STACK_SIZE: if (datasz != align_size) { _bfd_error_handler (_("warning: %pB: corrupt stack size: 0x%x"), abfd, datasz); /* Clear all properties. */ elf_properties (abfd) = NULL; return FALSE; } prop = _bfd_elf_get_property (abfd, type, datasz); if (datasz == 8) prop->u.number = bfd_h_get_64 (abfd, ptr); else prop->u.number = bfd_h_get_32 (abfd, ptr); prop->pr_kind = property_number; goto next; case GNU_PROPERTY_NO_COPY_ON_PROTECTED: if (datasz != 0) { _bfd_error_handler (_("warning: %pB: corrupt no copy on protected size: 0x%x"), abfd, datasz); /* Clear all properties. */ elf_properties (abfd) = NULL; return FALSE; } prop = _bfd_elf_get_property (abfd, type, datasz); elf_has_no_copy_on_protected (abfd) = TRUE; prop->pr_kind = property_number; goto next; default: break; } } _bfd_error_handler (_("warning: %pB: unsupported GNU_PROPERTY_TYPE (%ld) type: 0x%x"), abfd, note->type, type); next: ptr += (datasz + (align_size - 1)) & ~ (align_size - 1); } return TRUE; }
static void read_alphacoff_dynamic_symtab (minimal_symbol_reader &reader, struct section_offsets *section_offsets, struct objfile *objfile) { bfd *abfd = objfile->obfd; struct alphacoff_dynsecinfo si; char *sym_secptr; char *str_secptr; char *dyninfo_secptr; char *got_secptr; bfd_size_type sym_secsize; bfd_size_type str_secsize; bfd_size_type dyninfo_secsize; bfd_size_type got_secsize; int sym_count; int i; int stripped; Elfalpha_External_Sym *x_symp; char *dyninfo_p; char *dyninfo_end; int got_entry_size = 8; int dt_mips_local_gotno = -1; int dt_mips_gotsym = -1; struct cleanup *cleanups; /* We currently only know how to handle alpha dynamic symbols. */ if (bfd_get_arch (abfd) != bfd_arch_alpha) return; /* Locate the dynamic symbols sections and read them in. */ memset ((char *) &si, 0, sizeof (si)); bfd_map_over_sections (abfd, alphacoff_locate_sections, (void *) & si); if (si.sym_sect == NULL || si.str_sect == NULL || si.dyninfo_sect == NULL || si.got_sect == NULL) return; sym_secsize = bfd_get_section_size (si.sym_sect); str_secsize = bfd_get_section_size (si.str_sect); dyninfo_secsize = bfd_get_section_size (si.dyninfo_sect); got_secsize = bfd_get_section_size (si.got_sect); sym_secptr = (char *) xmalloc (sym_secsize); cleanups = make_cleanup (xfree, sym_secptr); str_secptr = (char *) xmalloc (str_secsize); make_cleanup (xfree, str_secptr); dyninfo_secptr = (char *) xmalloc (dyninfo_secsize); make_cleanup (xfree, dyninfo_secptr); got_secptr = (char *) xmalloc (got_secsize); make_cleanup (xfree, got_secptr); if (!bfd_get_section_contents (abfd, si.sym_sect, sym_secptr, (file_ptr) 0, sym_secsize)) { do_cleanups (cleanups); return; } if (!bfd_get_section_contents (abfd, si.str_sect, str_secptr, (file_ptr) 0, str_secsize)) { do_cleanups (cleanups); return; } if (!bfd_get_section_contents (abfd, si.dyninfo_sect, dyninfo_secptr, (file_ptr) 0, dyninfo_secsize)) { do_cleanups (cleanups); return; } if (!bfd_get_section_contents (abfd, si.got_sect, got_secptr, (file_ptr) 0, got_secsize)) { do_cleanups (cleanups); return; } /* Find the number of local GOT entries and the index for the first dynamic symbol in the GOT. */ for (dyninfo_p = dyninfo_secptr, dyninfo_end = dyninfo_p + dyninfo_secsize; dyninfo_p < dyninfo_end; dyninfo_p += sizeof (Elfalpha_External_Dyn)) { Elfalpha_External_Dyn *x_dynp = (Elfalpha_External_Dyn *) dyninfo_p; long dyn_tag; dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_tag); if (dyn_tag == DT_NULL) break; else if (dyn_tag == DT_MIPS_LOCAL_GOTNO) { if (dt_mips_local_gotno < 0) dt_mips_local_gotno = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val); } else if (dyn_tag == DT_MIPS_GOTSYM) { if (dt_mips_gotsym < 0) dt_mips_gotsym = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val); } } if (dt_mips_local_gotno < 0 || dt_mips_gotsym < 0) { do_cleanups (cleanups); return; } /* Scan all dynamic symbols and enter them into the minimal symbol table if appropriate. */ sym_count = sym_secsize / sizeof (Elfalpha_External_Sym); stripped = (bfd_get_symcount (abfd) == 0); /* Skip first symbol, which is a null dummy. */ for (i = 1, x_symp = (Elfalpha_External_Sym *) sym_secptr + 1; i < sym_count; i++, x_symp++) { unsigned long strx; char *name; bfd_vma sym_value; unsigned char sym_info; unsigned int sym_shndx; int isglobal; enum minimal_symbol_type ms_type; strx = bfd_h_get_32 (abfd, (bfd_byte *) x_symp->st_name); if (strx >= str_secsize) continue; name = str_secptr + strx; if (*name == '\0' || *name == '.') continue; sym_value = bfd_h_get_64 (abfd, (bfd_byte *) x_symp->st_value); sym_info = bfd_h_get_8 (abfd, (bfd_byte *) x_symp->st_info); sym_shndx = bfd_h_get_16 (abfd, (bfd_byte *) x_symp->st_shndx); if (sym_shndx >= (SHN_LORESERVE & 0xffff)) sym_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff); isglobal = (ELF_ST_BIND (sym_info) == STB_GLOBAL); if (sym_shndx == SHN_UNDEF) { /* Handle undefined functions which are defined in a shared library. */ if (ELF_ST_TYPE (sym_info) != STT_FUNC || ELF_ST_BIND (sym_info) != STB_GLOBAL) continue; ms_type = mst_solib_trampoline; /* If sym_value is nonzero, it points to the shared library trampoline entry, which is what we are looking for. If sym_value is zero, then we have to get the GOT entry for the symbol. If the GOT entry is nonzero, it represents the quickstart address of the function and we use that as the symbol value. If the GOT entry is zero, the function address has to be resolved by the runtime loader before the executable is started. We are unable to find any meaningful address for these functions in the executable file, so we skip them. */ if (sym_value == 0) { int got_entry_offset = (i - dt_mips_gotsym + dt_mips_local_gotno) * got_entry_size; if (got_entry_offset < 0 || got_entry_offset >= got_secsize) continue; sym_value = bfd_h_get_64 (abfd, (bfd_byte *) (got_secptr + got_entry_offset)); if (sym_value == 0) continue; } } else { /* Symbols defined in the executable itself. We only care about them if this is a stripped executable, otherwise they have been retrieved from the normal symbol table already. */ if (!stripped) continue; if (sym_shndx == SHN_MIPS_TEXT) { if (isglobal) ms_type = mst_text; else ms_type = mst_file_text; } else if (sym_shndx == SHN_MIPS_DATA) { if (isglobal) ms_type = mst_data; else ms_type = mst_file_data; } else if (sym_shndx == SHN_MIPS_ACOMMON) { if (isglobal) ms_type = mst_bss; else ms_type = mst_file_bss; } else if (sym_shndx == SHN_ABS) { ms_type = mst_abs; } else { continue; } } reader.record (name, sym_value, ms_type); } do_cleanups (cleanups); }