📄 elf.c
字号:
/* Check to see if the core file could reasonably be expected to have come for the current executable file. Note that by default we return true unless we find something that indicates that there might be a problem. */static booleanDEFUN(elf_core_file_matches_executable_p, (core_bfd, exec_bfd), bfd *core_bfd AND bfd *exec_bfd){#ifdef HAVE_PROCFS char *corename; char *execname;#endif /* First, xvecs must match since both are ELF files for the same target. */ if (core_bfd->xvec != exec_bfd->xvec) { bfd_error = system_call_error; return (false); }#ifdef HAVE_PROCFS /* If no prpsinfo, just return true. Otherwise, grab the last component of the exec'd pathname from the prpsinfo. */ if (core_prpsinfo (core_bfd)) { corename = (((struct prpsinfo *) core_prpsinfo (core_bfd)) -> pr_fname); } else { return (true); } /* Find the last component of the executable pathname. */ if ((execname = strrchr (exec_bfd -> filename, '/')) != NULL) { execname++; } else { execname = (char *) exec_bfd -> filename; } /* See if they match */ return (strcmp (execname, corename) ? false : true);#else return (true);#endif /* HAVE_PROCFS */}/* ELF core files contain a segment of type PT_NOTE, that holds much of the information that would normally be available from the /proc interface for the process, at the time the process dumped core. Currently this includes copies of the prstatus, prpsinfo, and fpregset structures. Since these structures are potentially machine dependent in size and ordering, bfd provides two levels of support for them. The first level, available on all machines since it does not require that the host have /proc support or the relevant include files, is to create a bfd section for each of the prstatus, prpsinfo, and fpregset structures, without any interpretation of their contents. With just this support, the bfd client will have to interpret the structures itself. Even with /proc support, it might want these full structures for it's own reasons. In the second level of support, where HAVE_PROCFS is defined, bfd will pick apart the structures to gather some additional information that clients may want, such as the general register set, the name of the exec'ed file and its arguments, the signal (if any) that caused the core dump, etc. */static booleanDEFUN(elf_corefile_note, (abfd, hdr), bfd *abfd AND Elf_Internal_Phdr *hdr){ Elf_External_Note *x_note_p; /* Elf note, external form */ Elf_Internal_Note i_note; /* Elf note, internal form */ char *buf = NULL; /* Entire note segment contents */ char *namedata; /* Name portion of the note */ char *descdata; /* Descriptor portion of the note */ char *sectname; /* Name to use for new section */ long filepos; /* File offset to descriptor data */ asection *newsect; if (hdr -> p_filesz > 0 && (buf = (char *) bfd_xmalloc (hdr -> p_filesz)) != NULL && bfd_seek (abfd, hdr -> p_offset, SEEK_SET) != -1 && bfd_read ((PTR) buf, hdr -> p_filesz, 1, abfd) == hdr -> p_filesz) { x_note_p = (Elf_External_Note *) buf; while ((char *) x_note_p < (buf + hdr -> p_filesz)) { i_note.namesz = bfd_h_get_32 (abfd, (bfd_byte *) x_note_p -> namesz); i_note.descsz = bfd_h_get_32 (abfd, (bfd_byte *) x_note_p -> descsz); i_note.type = bfd_h_get_32 (abfd, (bfd_byte *) x_note_p -> type); namedata = x_note_p -> name; descdata = namedata + BFD_ALIGN (i_note.namesz, 4); filepos = hdr -> p_offset + (descdata - buf); switch (i_note.type) { case NT_PRSTATUS: /* process descdata as prstatus info */ bfd_prstatus (abfd, descdata, i_note.descsz, filepos); sectname = ".prstatus"; break; case NT_FPREGSET: /* process descdata as fpregset info */ bfd_fpregset (abfd, descdata, i_note.descsz, filepos); sectname = ".fpregset"; break; case NT_PRPSINFO: /* process descdata as prpsinfo */ bfd_prpsinfo (abfd, descdata, i_note.descsz, filepos); sectname = ".prpsinfo"; break; default: /* Unknown descriptor, just ignore it. */ sectname = NULL; break; } if (sectname != NULL) { newsect = bfd_make_section (abfd, sectname); newsect -> _raw_size = i_note.descsz; newsect -> filepos = filepos; newsect -> flags = SEC_ALLOC | SEC_HAS_CONTENTS; newsect -> alignment_power = 2; } x_note_p = (Elf_External_Note *) (descdata + BFD_ALIGN (i_note.descsz, 4)); } } if (buf != NULL) { free (buf); } return true; }/* Read a specified number of bytes at a specified offset in an ELF file, into a newly allocated buffer, and return a pointer to the buffer. */static char *DEFUN(elf_read, (abfd, offset, size), bfd *abfd AND long offset AND int size){ char *buf; if ((buf = bfd_alloc (abfd, size)) == NULL) { bfd_error = no_memory; return (NULL); } if (bfd_seek (abfd, offset, SEEK_SET) == -1) { bfd_error = system_call_error; return (NULL); } if (bfd_read ((PTR) buf, size, 1, abfd) != size) { bfd_error = system_call_error; return (NULL); } return (buf);}/* Begin processing a given object. First we validate the file by reading in the ELF header and checking the magic number. */static bfd_target *DEFUN (elf_object_p, (abfd), bfd *abfd){ Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ Elf_External_Shdr x_shdr; /* Section header table entry, external form */ Elf_Internal_Shdr *i_shdrp; /* Section header table, internal form */ int shindex; char *shstrtab; /* Internal copy of section header stringtab */ /* Read in the ELF header in external format. */ if (bfd_read ((PTR) &x_ehdr, sizeof (x_ehdr), 1, abfd) != sizeof (x_ehdr)) { bfd_error = system_call_error; return (NULL); } /* Now check to see if we have a valid ELF file, and one that BFD can make use of. The magic number must match, the address size ('class') and byte-swapping must match our XVEC entry, and it must have a section header table (FIXME: See comments re sections at top of this file). */ if (x_ehdr.e_ident[EI_MAG0] != ELFMAG0 || x_ehdr.e_ident[EI_MAG1] != ELFMAG1 || x_ehdr.e_ident[EI_MAG2] != ELFMAG2 || x_ehdr.e_ident[EI_MAG3] != ELFMAG3) {wrong: bfd_error = wrong_format; return (NULL); } /* FIXME, Check EI_VERSION here ! */ switch (x_ehdr.e_ident[EI_CLASS]) { case ELFCLASSNONE: /* address size not specified */ goto wrong; /* No support if can't tell address size */ case ELFCLASS32: /* 32-bit addresses */ break; case ELFCLASS64: /* 64-bit addresses */ goto wrong; /* FIXME: 64 bits not yet supported */ default: goto wrong; /* No support if unknown address class */ } /* Switch xvec to match the specified byte order. */ switch (x_ehdr.e_ident[EI_DATA]) { case ELFDATA2MSB: /* Big-endian */ if (!abfd->xvec->header_byteorder_big_p) goto wrong; break; case ELFDATA2LSB: /* Little-endian */ if (abfd->xvec->header_byteorder_big_p) goto wrong; break; case ELFDATANONE: /* No data encoding specified */ default: /* Unknown data encoding specified */ goto wrong; } /* Allocate an instance of the elf_obj_tdata structure and hook it up to the tdata pointer in the bfd. */ if (NULL == (elf_tdata (abfd) = (struct elf_obj_tdata *) bfd_zalloc (abfd, sizeof (struct elf_obj_tdata)))) { bfd_error = no_memory; return (NULL); } /* FIXME: Any `wrong' exits below here will leak memory (tdata). */ /* Now that we know the byte order, swap in the rest of the header */ i_ehdrp = elf_elfheader (abfd); elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp); /* If there is no section header table, we're hosed. */ if (i_ehdrp->e_shoff == 0) goto wrong; if (i_ehdrp->e_type == ET_EXEC || i_ehdrp->e_type == ET_DYN) abfd -> flags |= EXEC_P; switch (i_ehdrp->e_machine) { case EM_NONE: case EM_M32: /* or should this be bfd_arch_obscure? */ bfd_default_set_arch_mach(abfd, bfd_arch_unknown, 0); break; case EM_SPARC: bfd_default_set_arch_mach(abfd, bfd_arch_sparc, 0); break; case EM_386: bfd_default_set_arch_mach(abfd, bfd_arch_i386, 0); break; case EM_68K: bfd_default_set_arch_mach(abfd, bfd_arch_m68k, 0); break; case EM_88K: bfd_default_set_arch_mach(abfd, bfd_arch_m88k, 0); break; case EM_860: bfd_default_set_arch_mach(abfd, bfd_arch_i860, 0); break; case EM_MIPS: bfd_default_set_arch_mach(abfd, bfd_arch_mips, 0); break; default: goto wrong; } /* Allocate space for a copy of the section header table in internal form, seek to the section header table in the file, read it in, and convert it to internal form. As a simple sanity check, verify that the what BFD thinks is the size of each section header table entry actually matches the size recorded in the file. */ if (i_ehdrp->e_shentsize != sizeof (x_shdr)) goto wrong; i_shdrp = (Elf_Internal_Shdr *) bfd_alloc (abfd, sizeof (*i_shdrp) * i_ehdrp->e_shnum); if (! i_shdrp) { bfd_error = no_memory; return (NULL); } if (bfd_seek (abfd, i_ehdrp->e_shoff, SEEK_SET) == -1) { bfd_error = system_call_error; return (NULL); } for (shindex = 0; shindex < i_ehdrp->e_shnum; shindex++) { if (bfd_read ((PTR) &x_shdr, sizeof x_shdr, 1, abfd) != sizeof (x_shdr)) { bfd_error = system_call_error; return (NULL); } elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex); } elf_elfsections (abfd) = i_shdrp; /* Read in the string table containing the names of the sections. We will need the base pointer to this table later. */ /* We read this inline now, so that we don't have to go through bfd_section_from_shdr with it (since this particular strtab is used to find all of the ELF section names.) */ shstrtab = elf_get_str_section (abfd, i_ehdrp->e_shstrndx); if (! shstrtab) return (NULL); /* Once all of the section headers have been read and converted, we can start processing them. Note that the first section header is a dummy placeholder entry, so we ignore it. We also watch for the symbol table section and remember the file offset and section size for both the symbol table section and the associated string table section. */ for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++) { bfd_section_from_shdr (abfd, shindex); } /* Remember the entry point specified in the ELF file header. */ bfd_get_start_address (abfd) = i_ehdrp->e_entry; return (abfd->xvec);}/* Core files are simply standard ELF formatted files that partition the file using the execution view of the file (program header table) rather than the linking view. In fact, there is no section header table in a core file. The process status information (including the contents of the general register set) and the floating point register set are stored in a segment of type PT_NOTE. We handcraft a couple of extra bfd sections that allow standard bfd access to the general registers (.reg) and the floating point registers (.reg2). */static bfd_target *DEFUN (elf_core_file_p, (abfd), bfd *abfd){ Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ Elf_External_Phdr x_phdr; /* Program header table entry, external form */ Elf_Internal_Phdr *i_phdrp; /* Program header table, internal form */ unsigned int phindex; /* Read in the ELF header in external format. */ if (bfd_read ((PTR) &x_ehdr, sizeof (x_ehdr), 1, abfd) != sizeof (x_ehdr)) { bfd_error = system_call_error; return (NULL); } /* Now check to see if we have a valid ELF file, and one that BFD can make use of. The magic number must match, the address size ('class') and byte-swapping must match our XVEC entry, and it must have a program header table (FIXME: See comments re segments at top of this file). */ if (x_ehdr.e_ident[EI_MAG0] != ELFMAG0 || x_ehdr.e_ident[EI_MAG1] != ELFMAG1 || x_ehdr.e_ident[EI_MAG2] != ELFMAG2 || x_ehdr.e_ident[EI_MAG3] != ELFMAG3) {wrong: bfd_error = wrong_format; return (NULL); } /* FIXME, Check EI_VERSION here ! */ switch (x_ehdr.e_ident[EI_CLASS]) { case ELFCLASSNONE: /* address size not specified */ goto wrong; /* No support if can't tell address size */ case ELFCLASS32: /* 32-bit addresses */ break; case ELFCLASS64: /* 64-bit addresses */ goto wrong; /* FIXME: 64 bits not yet supported */ default: goto wrong; /* No support if unknown address class */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -