📄 elf.c
字号:
bfd_map_over_sections(abfd, elf_make_sections, &est); /* dump out the one symtab */ { int symcount = bfd_get_symcount (abfd); asymbol ** syms = bfd_get_outsymbols (abfd); struct strtab * stt = bfd_new_strtab (abfd); Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Shdr *symstrtab_hdr; int symstrtab_section; Elf_External_Sym *outbound_syms; int idx; symtab_hdr = &i_shdrp[est.symtab_section]; symtab_hdr->sh_type = SHT_SYMTAB; symtab_hdr->sh_entsize = sizeof (Elf_External_Sym); symtab_hdr->sh_size = symtab_hdr->sh_entsize * symcount; /* see assert in elf_fake_sections that supports this: */ symstrtab_section = est.symtab_section+1; symstrtab_hdr = &i_shdrp[symstrtab_section]; symtab_hdr->sh_link = symstrtab_section; symstrtab_hdr->sh_type = SHT_STRTAB; outbound_syms = (Elf_External_Sym*) bfd_alloc(abfd, (1+symcount) * sizeof(Elf_External_Sym)); /* now generate the data (for "contents") */ for (idx = 0; idx < symcount; idx++) { Elf_Internal_Sym sym; sym.st_name = bfd_add_to_strtab (abfd, stt, syms[idx]->name); sym.st_value = syms[idx]->value; sym.st_size = 0; /* we should recover this (FIXME) */ if (syms[idx]->flags & BSF_WEAK) sym.st_info = ELF_ST_INFO(STB_WEAK, STT_OBJECT); else if (syms[idx]->flags & BSF_LOCAL) sym.st_info = ELF_ST_INFO(STB_LOCAL, STT_OBJECT); else if (syms[idx]->flags & BSF_GLOBAL) sym.st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT); else if (syms[idx]->flags & BSF_SECTION_SYM) sym.st_info = ELF_ST_INFO(STB_LOCAL, STT_SECTION); else if (syms[idx]->flags & BSF_FILE) sym.st_info = ELF_ST_INFO(STB_LOCAL, STT_FILE); sym.st_other = 0; if (syms[idx]->section) sym.st_shndx = elf_section_from_bfd_section(abfd, syms[idx]->section->output_section); else sym.st_shndx = SHN_UNDEF; elf_swap_symbol_out (abfd, &sym, outbound_syms+idx+1); } { /* fill in 0th symbol */ Elf_Internal_Sym sym; sym.st_name = 0; sym.st_value = 0; sym.st_size = 0; sym.st_info = 0; sym.st_other = 0; sym.st_shndx = SHN_UNDEF; elf_swap_symbol_out (abfd, &sym, outbound_syms); } symtab_hdr->contents = (void*)outbound_syms; symstrtab_hdr->contents = (void*)stt->tab; symstrtab_hdr->sh_size = stt->length; } /* put the strtab out too... */ { Elf_Internal_Shdr *this_hdr; int this_section; this_section = i_ehdrp->e_shnum++; i_ehdrp->e_shstrndx = this_section; this_hdr = &i_shdrp[this_section]; this_hdr->sh_name = bfd_add_to_strtab (abfd, shstrtab, ".shstrtab"); this_hdr->sh_size = shstrtab->length; this_hdr->contents = (void*)shstrtab->tab; } outbase = i_ehdrp->e_ehsize; /* swap the header before spitting it out... */ elf_swap_ehdr_out (abfd, i_ehdrp, &x_ehdr); bfd_seek (abfd, (file_ptr) 0, SEEK_SET); bfd_write ((PTR) &x_ehdr, sizeof(x_ehdr), 1, abfd); outbase += i_ehdrp->e_shentsize * i_ehdrp->e_shnum; /* now we fix up the offsets... */ for (count = 0; count < i_ehdrp->e_shnum; count ++) { i_shdrp[count].sh_offset = outbase; outbase += i_shdrp[count].sh_size; } /* at this point we've concocted all the ELF sections... */ x_shdrp = (Elf_External_Shdr *) bfd_alloc (abfd, sizeof (*x_shdrp) * (i_ehdrp->e_shnum)); if (! x_shdrp) { bfd_error = no_memory; return (false); } for (count = 0; count < i_ehdrp->e_shnum; count ++) { elf_swap_shdr_out (abfd, i_shdrp+count, x_shdrp+count); } bfd_write ((PTR) x_shdrp, sizeof(*x_shdrp), i_ehdrp->e_shnum, abfd); /* need to dump the string table too... */ /* after writing the headers, we need to write the sections too... */ nsect = abfd->sections; for (count = 0; count < i_ehdrp->e_shnum; count ++) { if(i_shdrp[count].contents) { bfd_seek (abfd, i_shdrp[count].sh_offset, SEEK_SET); bfd_write (i_shdrp[count].contents, i_shdrp[count].sh_size, 1, abfd); } } /* sample use of bfd: * bfd_seek (abfd, (file_ptr) 0, SEEK_SET); * bfd_write ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd); * if (bfd_seek(abfd, scn_base, SEEK_SET) != 0) * return false; * old = bfd_tell(abfd); */ return true; }/* Given an index of a section, retrieve a pointer to it. Note that for our purposes, sections are indexed by {1, 2, ...} with 0 being an illegal index. *//* In the original, each ELF section went into exactly one BFD section. This doesn't really make sense, so we need a real mapping. The mapping has to hide in the Elf_Internal_Shdr since asection doesn't have anything like a tdata field... */ static struct sec *DEFUN (section_from_elf_index, (abfd, index), bfd *abfd AND int index){ Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd); Elf_Internal_Shdr *hdr = i_shdrp + index; switch (hdr->sh_type) { /* ELF sections that map to BFD sections */ case SHT_PROGBITS: case SHT_NOBITS: if (! hdr->rawdata) bfd_section_from_shdr (abfd, index); return (struct sec *)hdr->rawdata; break; default: return (struct sec *)&bfd_abs_section; }}/* given a section, search the header to find them... */static intDEFUN (elf_section_from_bfd_section, (abfd, asect), bfd *abfd AND struct sec *asect){ Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd); int index; Elf_Internal_Shdr *hdr; int maxindex = elf_elfheader (abfd)->e_shnum; for(index = 0; index < maxindex; index++) { hdr = &i_shdrp[index]; switch (hdr->sh_type) { /* ELF sections that map to BFD sections */ case SHT_PROGBITS: case SHT_NOBITS: if (hdr->rawdata) { if (((struct sec *)(hdr->rawdata)) == asect) return index; } break; default: break; } } return 0;}static booleanDEFUN (elf_slurp_symbol_table, (abfd, symptrs), bfd *abfd AND asymbol **symptrs) /* Buffer for generated bfd symbols */{ Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd); Elf_Internal_Shdr *hdr = i_shdrp + elf_onesymtab (abfd); int symcount; /* Number of external ELF symbols */ int i; asymbol *sym; /* Pointer to current bfd symbol */ asymbol *symbase; /* Buffer for generated bfd symbols */ Elf_Internal_Sym i_sym; Elf_External_Sym *x_symp; /* this is only valid because there is only one symtab... */ /* FIXME: This is incorrect, there may also be a dynamic symbol table which is a subset of the full symbol table. We either need to be prepared to read both (and merge them) or ensure that we only read the full symbol table. Currently we only get called to read the full symbol table. -fnf */ if (bfd_get_outsymbols (abfd) != NULL) { return (true); } /* Read each raw ELF symbol, converting from external ELF form to internal ELF form, and then using the information to create a canonical bfd symbol table entry. Note that we allocate the initial bfd canonical symbol buffer based on a one-to-one mapping of the ELF symbols to canonical symbols. We actually use all the ELF symbols, so there will be no space left over at the end. When we have all the symbols, we build the caller's pointer vector. */ if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1) { bfd_error = system_call_error; return (false); } symcount = hdr->sh_size / sizeof (Elf_External_Sym); symbase = (asymbol *) bfd_zalloc (abfd, symcount * sizeof (asymbol)); sym = symbase; /* Temporarily allocate room for the raw ELF symbols. */ x_symp = (Elf_External_Sym *) malloc (symcount * sizeof (Elf_External_Sym)); if (bfd_read ((PTR) x_symp, sizeof (Elf_External_Sym), symcount, abfd) != symcount * sizeof (Elf_External_Sym)) { free ((PTR)x_symp); bfd_error = system_call_error; return (false); } /* Skip first symbol, which is a null dummy. */ for (i = 1; i < symcount; i++) { elf_swap_symbol_in (abfd, x_symp + i, &i_sym); sym -> the_bfd = abfd; if (i_sym.st_name > 0) sym -> name = elf_string_from_elf_section(abfd, hdr->sh_link, i_sym.st_name); else sym -> name = "unnamed"; /* perhaps should include the number? */ sym -> value = i_sym.st_value;/* FIXME -- this is almost certainly bogus. It's from Pace Willisson'shasty Solaris support, to pass the sizes of object files or functionsdown into GDB via the back door, to circumvent some other kludge inhow Sun hacked stabs. -- gnu@cygnus.com */ sym -> udata = (PTR)i_sym.st_size;/* FIXME -- end of bogosity. */ if (i_sym.st_shndx > 0 && i_sym.st_shndx < SHN_LORESERV) { sym -> section = section_from_elf_index (abfd, i_sym.st_shndx); } else if (i_sym.st_shndx == SHN_ABS) { sym -> section = &bfd_abs_section; } else if (i_sym.st_shndx == SHN_COMMON) { sym -> section = &bfd_com_section; } else if (i_sym.st_shndx == SHN_UNDEF) { sym -> section = &bfd_und_section; } else sym -> section = &bfd_abs_section; switch (ELF_ST_BIND (i_sym.st_info)) { case STB_LOCAL: sym -> flags |= BSF_LOCAL; break; case STB_GLOBAL: sym -> flags |= (BSF_GLOBAL | BSF_EXPORT); break; case STB_WEAK: sym -> flags |= BSF_WEAK; break; } switch (ELF_ST_TYPE (i_sym.st_info)) { case STT_SECTION: sym->flags |= BSF_SECTION_SYM | BSF_DEBUGGING; break; case STT_FILE: sym->flags |= BSF_FILE | BSF_DEBUGGING; break; } sym++; } /* We rely on the zalloc to clear out the final symbol entry. */ /* We're now done with the raw symbols. */ free ((PTR)x_symp); bfd_get_symcount(abfd) = symcount = sym - symbase; /* Fill in the user's symbol pointer vector if needed. */ if (symptrs) { sym = symbase; while (symcount-- > 0) { *symptrs++ = sym++; } *symptrs = 0; /* Final null pointer */ } return (true);}/* Return the number of bytes required to hold the symtab vector. Note that we base it on the count plus 1, since we will null terminate the vector allocated based on this size. However, the ELF symbol table always has a dummy entry as symbol #0, so it ends up even. */static unsigned intDEFUN (elf_get_symtab_upper_bound, (abfd), bfd *abfd){ unsigned int symcount; unsigned int symtab_size; Elf_Internal_Shdr *i_shdrp = elf_elfsections (abfd); Elf_Internal_Shdr *hdr = i_shdrp + elf_onesymtab (abfd); symcount = hdr->sh_size / sizeof (Elf_External_Sym); symtab_size = (symcount - 1 + 1) * (sizeof (asymbol)); return (symtab_size);}/* This function return the number of bytes required to store the relocation information associated with section <<sect>> attached to bfd <<abfd>>*/static unsigned intelf_get_reloc_upper_bound (abfd, asect)bfd *abfd;sec_ptr asect;{ if (asect->flags & SEC_RELOC) { /* either rel or rela */ return asect->_raw_size; } else return (0);}/* FIXME!!! sparc howto should go into elf-32-sparc.c */#ifdef sparcenum reloc_type { R_SPARC_NONE = 0, R_SPARC_8, R_SPARC_16, R_SPARC_32, R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32, R_SPARC_WDISP30, R_SPARC_WDISP22, R_SPARC_HI22, R_SPARC_22, R_SPARC_13, R_SPARC_LO10, R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22, R_SPARC_PC10, R_SPARC_PC22, R_SPARC_WPLT30, R_SPARC_COPY, R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT, R_SPARC_RELATIVE, R_SPARC_UA32, };#define RELOC_TYPE_NAMES \ "R_SPARC_NONE", \ "R_SPARC_8", "R_SPARC_16", "R_SPARC_32", \ "R_SPARC_DISP8", "R_SPARC_DISP16", "R_SPARC_DISP32", \ "R_SPARC_WDISP30", "R_SPARC_WDISP22", \ "R_SPARC_HI22", "R_SPARC_22", \ "R_SPARC_13", "R_SPARC_LO10", \ "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22", \ "R_SPARC_PC10", "R_SPARC_PC22", \ "R_SPARC_WPLT30", \ "R_SPARC_COPY", \ "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT", \ "R_SPARC_RELATIVE", \ "R_SPARC_UA32"static reloc_howto_type elf_howto_table[] = { HOWTO(R_SPARC_NONE, 0,0, 0,false,0,false,false, 0,"R_SPARC_NONE", false,0,0x00000000,false), HOWTO(R_SPARC_8, 0,0, 8,false,0,true, true, 0,"R_SPARC_8", false,0,0x000000ff,false), HOWTO(R_SPARC_16, 0,1,16,false,0,true, true, 0,"R_SPARC_16", false,0,0x0000ffff,false), HOWTO(R_SPARC_32, 0,2,32,false,0,true, true, 0,"R_SPARC_32", false,0,0xffffffff,false), HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,false, true, 0,"R_SPARC_DISP8", false,0,0x000000ff,false), HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,false, true, 0,"R_SPARC_DISP16", false,0,0x0000ffff,false), HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,false, true, 0,"R_SPARC_DISP32", false,0,0x00ffffff,false), HOWTO(R_SPARC_WDISP30,2,2,30,true, 0,false, true, 0,"R_SPARC_WDISP30",false,0,0x3fffffff,false), HOWTO(R_SPARC_WDISP22,2,2,22,true, 0,false, true, 0,"R_SPARC_WDISP22",false,0,0x003fffff,false), HOWTO(R_SPARC_HI22, 10,2,22,false,0,true, false, 0,"R_SPARC_HI22", false,0,0x003fffff,false), HOWTO(R_SPARC_22, 0,2,22,false,0,true, true, 0,"R_SPARC_22", false,0,0x003fffff,false), HOWTO(R_SPARC_13, 0,1,13,false,0,true, true, 0,"R_SPARC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -