📄 elf.c
字号:
case SHT_PROGBITS: case SHT_NOBITS: /* Bits that get saved. This one is real. */ if (! hdr->rawdata ) { newsect = bfd_make_section (abfd, name); newsect->vma = hdr->sh_addr; newsect->_raw_size = hdr->sh_size; newsect->filepos = hdr->sh_offset; /* so we can read back the bits */ newsect->flags |= SEC_HAS_CONTENTS; if (hdr->sh_flags & SHF_ALLOC) { newsect->flags |= SEC_ALLOC; if (hdr->sh_type != SHT_NOBITS) newsect->flags |= SEC_LOAD; } if (!(hdr->sh_flags & SHF_WRITE)) newsect->flags |= SEC_READONLY; if (hdr->sh_flags & SHF_EXECINSTR) newsect->flags |= SEC_CODE; /* FIXME: may only contain SOME code */ else newsect->flags |= SEC_DATA; hdr->rawdata = (void*)newsect; } return true; break; case SHT_SYMTAB: /* A symbol table */ BFD_ASSERT (hdr->sh_entsize == sizeof (Elf_External_Sym)); elf_onesymtab (abfd) = shindex; abfd->flags |= HAS_SYMS; return true; case SHT_STRTAB: /* A string table */ return true; case SHT_REL: case SHT_RELA: /* *these* do a lot of work -- but build no sections! */ /* the spec says there can be multiple strtabs, but only one symtab */ /* but there can be lots of REL* sections. */ /* FIXME: The above statement is wrong! There are typically at least two symbol tables in a dynamically linked executable, ".dynsym" which is the dynamic linkage symbol table and ".symtab", which is the "traditional" symbol table. -fnf */ { asection *target_sect; bfd_section_from_shdr (abfd, hdr->sh_link); /* symbol table */ bfd_section_from_shdr (abfd, hdr->sh_info); /* target */ target_sect = section_from_elf_index (abfd, hdr->sh_info); if (target_sect == NULL) return false;#if 0 /* FIXME: We are only prepared to read one symbol table, so do NOT read the dynamic symbol table since it is only a subset of the full symbol table. Also see comment above. -fnf */ if (!elf_slurp_symbol_table(abfd, i_shdrp + hdr->sh_link)) return false;#endif target_sect->reloc_count = hdr->sh_size / hdr->sh_entsize; target_sect->flags |= SEC_RELOC; target_sect->relocation = 0; target_sect->rel_filepos = hdr->sh_offset; return true; } break; case SHT_HASH: case SHT_DYNAMIC: case SHT_DYNSYM: /* could treat this like symtab... */#if 0 fprintf(stderr, "Dynamic Linking sections not yet supported.\n"); abort ();#endif break; case SHT_NOTE:#if 0 fprintf(stderr, "Note Sections not yet supported.\n"); abort ();#endif break; case SHT_SHLIB:#if 0 fprintf(stderr, "SHLIB Sections not supported (and non conforming.)\n");#endif return true; default: break; } return (true);}struct strtab { char *tab; int nentries; int length;};static struct strtab *DEFUN(bfd_new_strtab, (abfd), bfd *abfd){ struct strtab *ss; ss = (struct strtab *)malloc(sizeof(struct strtab)); ss->tab = malloc(1); BFD_ASSERT(ss->tab != 0); *ss->tab = 0; ss->nentries = 0; ss->length = 1; return ss;}static intDEFUN(bfd_add_to_strtab, (abfd, ss, str), bfd *abfd AND struct strtab *ss AND CONST char *str){ /* should search first, but for now: */ /* include the trailing NUL */ int ln = strlen(str)+1; /* should this be using obstacks? */ ss->tab = realloc(ss->tab, ss->length + ln); BFD_ASSERT(ss->tab != 0); strcpy(ss->tab + ss->length, str); ss->nentries++; ss->length += ln; return ss->length - ln;}static intDEFUN(bfd_add_2_to_strtab, (abfd, ss, str, str2), bfd *abfd AND struct strtab *ss AND char *str AND CONST char *str2){ /* should search first, but for now: */ /* include the trailing NUL */ int ln = strlen(str)+strlen(str2)+1; /* should this be using obstacks? */ if (ss->length) ss->tab = realloc(ss->tab, ss->length + ln); else ss->tab = malloc(ln); BFD_ASSERT(ss->tab != 0); strcpy(ss->tab + ss->length, str); strcpy(ss->tab + ss->length + strlen(str), str2); ss->nentries++; ss->length += ln; return ss->length - ln;}/* Create a new ELF section from a bfd section. */static booleanDEFUN(bfd_shdr_from_section, (abfd, hdr, shstrtab, indx), bfd *abfd AND Elf_Internal_Shdr *hdr AND struct strtab *shstrtab AND int indx){ asection *sect; int ndx; /* figure out out to write the section name from the bfd section name. MWE */ sect = abfd->sections; for (ndx = indx; --ndx; ) { sect = sect->next; } hdr[indx].sh_name = bfd_add_to_strtab(abfd, shstrtab, bfd_section_name(abfd, sect)); hdr[indx].sh_addr = sect->vma; hdr[indx].sh_size = sect->_raw_size; hdr[indx].sh_flags = 0; /* these need to be preserved on */ hdr[indx].sh_link = 0; hdr[indx].sh_info = 0; hdr[indx].sh_addralign = 0; hdr[indx].sh_entsize = 0; hdr[indx].sh_type = 0; if (sect->flags & SEC_RELOC) { hdr[indx].sh_type = SHT_RELA; /* FIXME -- sparc specific */ } if (sect->flags & SEC_HAS_CONTENTS) { hdr[indx].sh_offset = sect->filepos; hdr[indx].sh_size = sect->_raw_size; } if (sect->flags & SEC_ALLOC) { hdr[indx].sh_flags |= SHF_ALLOC; if (sect->flags & SEC_LOAD) { /* do something with sh_type ? */ } } if (!(sect->flags & SEC_READONLY)) hdr[indx].sh_flags |= SHF_WRITE; if (sect->flags & SEC_CODE) hdr[indx].sh_flags |= SHF_EXECINSTR; return (true);}/* Create a new bfd section from an ELF program header. Since program segments have no names, we generate a synthetic name of the form segment<NUM>, where NUM is generally the index in the program header table. For segments that are split (see below) we generate the names segment<NUM>a and segment<NUM>b. Note that some program segments may have a file size that is different than (less than) the memory size. All this means is that at execution the system must allocate the amount of memory specified by the memory size, but only initialize it with the first "file size" bytes read from the file. This would occur for example, with program segments consisting of combined data+bss. To handle the above situation, this routine generates TWO bfd sections for the single program segment. The first has the length specified by the file size of the segment, and the second has the length specified by the difference between the two sizes. In effect, the segment is split into it's initialized and uninitialized parts. */static booleanDEFUN(bfd_section_from_phdr, (abfd, hdr, index), bfd *abfd AND Elf_Internal_Phdr *hdr AND int index){ asection *newsect; char *name; char namebuf[64]; int split; split = ((hdr -> p_memsz > 0) && (hdr -> p_filesz > 0) && (hdr -> p_memsz > hdr -> p_filesz)); sprintf (namebuf, split ? "segment%da" : "segment%d", index); name = bfd_alloc (abfd, strlen (namebuf) + 1); strcpy (name, namebuf); newsect = bfd_make_section (abfd, name); newsect -> vma = hdr -> p_vaddr; newsect -> _raw_size = hdr -> p_filesz; newsect -> filepos = hdr -> p_offset; newsect -> flags |= SEC_HAS_CONTENTS; if (hdr -> p_type == PT_LOAD) { newsect -> flags |= SEC_ALLOC; newsect -> flags |= SEC_LOAD; if (hdr -> p_flags & PF_X) { /* FIXME: all we known is that it has execute PERMISSION, may be data. */ newsect -> flags |= SEC_CODE; } } if (!(hdr -> p_flags & PF_W)) { newsect -> flags |= SEC_READONLY; } if (split) { sprintf (namebuf, "segment%db", index); name = bfd_alloc (abfd, strlen (namebuf) + 1); strcpy (name, namebuf); newsect = bfd_make_section (abfd, name); newsect -> vma = hdr -> p_vaddr + hdr -> p_filesz; newsect -> _raw_size = hdr -> p_memsz - hdr -> p_filesz; if (hdr -> p_type == PT_LOAD) { newsect -> flags |= SEC_ALLOC; if (hdr -> p_flags & PF_X) newsect -> flags |= SEC_CODE; } if (!(hdr -> p_flags & PF_W)) newsect -> flags |= SEC_READONLY; } return (true);}#ifdef HAVE_PROCFSstatic voidDEFUN(bfd_prstatus,(abfd, descdata, descsz, filepos), bfd *abfd AND char *descdata AND int descsz AND long filepos){ asection *newsect; prstatus_t *status = (prstatus_t *)0; if (descsz == sizeof (prstatus_t)) { newsect = bfd_make_section (abfd, ".reg"); newsect -> _raw_size = sizeof (status->pr_reg); newsect -> filepos = filepos + (long) &status->pr_reg; newsect -> flags = SEC_ALLOC | SEC_HAS_CONTENTS; newsect -> alignment_power = 2; if ((core_prstatus (abfd) = bfd_alloc (abfd, descsz)) != NULL) { memcpy (core_prstatus (abfd), descdata, descsz); } }}/* Stash a copy of the prpsinfo structure away for future use. */static voidDEFUN(bfd_prpsinfo,(abfd, descdata, descsz, filepos), bfd *abfd AND char *descdata AND int descsz AND long filepos){ asection *newsect; if (descsz == sizeof (prpsinfo_t)) { if ((core_prpsinfo (abfd) = bfd_alloc (abfd, descsz)) != NULL) { memcpy (core_prpsinfo (abfd), descdata, descsz); } }}static voidDEFUN(bfd_fpregset,(abfd, descdata, descsz, filepos), bfd *abfd AND char *descdata AND int descsz AND long filepos){ asection *newsect; newsect = bfd_make_section (abfd, ".reg2"); newsect -> _raw_size = descsz; newsect -> filepos = filepos; newsect -> flags = SEC_ALLOC | SEC_HAS_CONTENTS; newsect -> alignment_power = 2;}#endif /* HAVE_PROCFS *//* Return a pointer to the args (including the command name) that were seen by the program that generated the core dump. Note that for some reason, a spurious space is tacked onto the end of the args in some (at least one anyway) implementations, so strip it off if it exists. */char *DEFUN(elf_core_file_failing_command, (abfd), bfd *abfd){#ifdef HAVE_PROCFS if (core_prpsinfo (abfd)) { prpsinfo_t *p = core_prpsinfo (abfd); char *scan = p -> pr_psargs; while (*scan++) {;} scan -= 2; if ((scan > p -> pr_psargs) && (*scan == ' ')) { *scan = '\000'; } return (p -> pr_psargs); }#endif return (NULL);}/* Return the number of the signal that caused the core dump. Presumably, since we have a core file, we got a signal of some kind, so don't bother checking the other process status fields, just return the signal number. */static intDEFUN(elf_core_file_failing_signal, (abfd), bfd *abfd){#ifdef HAVE_PROCFS if (core_prstatus (abfd)) { return (((prstatus_t *)(core_prstatus (abfd))) -> pr_cursig); }#endif return (-1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -