Elf32_Phdr *xelf32_getphdr(Elf *e) { Elf32_Phdr *phdr = elf32_getphdr(e); if (phdr == NULL) { eprintf("elf_getphdr() failed: %s", elf_errmsg(-1)); exit(EXIT_FAILURE); } return phdr; }
void load_segments(Elf *elf,int phnum,char *base,int flen, int which) { Elf32_Phdr *phdr; int i; phdr = elf32_getphdr(elf); if (phdr == NULL) { failure("getphdr"); } /* printf("headers at %d\n",ehdr->e_phoff); */ for (i = 0; i < phnum; i++) { if (phdr[i].p_type == PT_NOTE) { if (which) { fprintf(of,"%d: NOTE offset=0x%x filesz=0x%x flags=%d align=%d\n", i, phdr[i].p_offset, phdr[i].p_filesz, phdr[i].p_flags, phdr[i].p_align); } } else if (phdr[i].p_type == PT_LOAD) { if (which) { fprintf(of,"%d: LOAD vaddr=0x%x filesz=0x%x memsz=0x%x mode=%s\n", i, phdr[i].p_vaddr, phdr[i].p_filesz, phdr[i].p_memsz, modes[phdr[i].p_flags & 0x7]); } if (phdr[i].p_offset && phdr[i].p_filesz) { if (phdr[i].p_offset + phdr[i].p_filesz > flen) { fprintf(of,"%d: segment out of range - core file is incomplete.\n",i); continue; } } if ((phdr[i].p_flags == 7 || phdr[i].p_flags == 5) && phdr[i].p_filesz) { add_segment(&phdr[i],base,which); } } else { if (which) { fprintf(of,"%d: type=%d offset=0x%x vaddr=0x%x p=0x%x filesz=%d memsz=%d flags=%d align=%d\n", i, phdr[i].p_type,phdr[i].p_offset, phdr[i].p_vaddr, phdr[i].p_paddr, phdr[i].p_filesz, phdr[i].p_memsz, phdr[i].p_flags, phdr[i].p_align); } } } }
int write_phdr(elf_data_t *elf, inject_data_t *inject, char **err) { off_t off; size_t n, phdr_size; Elf32_Phdr *phdr_list32; Elf64_Phdr *phdr_list64; void *phdr_buf; if(!gelf_update_phdr(elf->e, inject->pidx, &inject->phdr)) { (*err) = "failed to update program header"; return -1; } if(elf->bits == 32) { phdr_list32 = elf32_getphdr(elf->e); if(!phdr_list32) { phdr_buf = NULL; } else { phdr_buf = &phdr_list32[inject->pidx]; phdr_size = sizeof(Elf32_Phdr); } } else { phdr_list64 = elf64_getphdr(elf->e); if(!phdr_list64) { phdr_buf = NULL; } else { phdr_buf = &phdr_list64[inject->pidx]; phdr_size = sizeof(Elf64_Phdr); } } if(!phdr_buf) { (*err) = "failed to get program header"; return -1; } off = lseek(elf->fd, elf->ehdr.e_phoff + inject->pidx*elf->ehdr.e_phentsize, SEEK_SET); if(off < 0) { (*err) = "lseek failed"; return -1; } n = write(elf->fd, phdr_buf, phdr_size); if(n != phdr_size) { (*err) = "write failed"; return -1; } return 0; }
int dump_dynamic(Elf *elf) { Elf32_Dyn * dyn; Elf32_Phdr * phdr; Elf32_Ehdr * ehdr; char * raw; int i; if ((phdr = elf32_getphdr(elf)) == NULL) { fprintf(stderr, "phdr == NULL"); return (2); } if ((raw = elf_rawfile(elf, NULL)) == NULL) { fprintf(stderr, "raw == NULL"); return (2); } for (;phdr->p_type != PT_DYNAMIC; phdr++) ; dyn = (Elf32_Dyn *)(raw + phdr->p_offset); i = 0; while (dyn->d_tag != DT_NULL) { printf("[%d] ", i); if (dyn->d_tag < DT_NUM) printf(" %s ", elf_dyn[dyn->d_tag]); else if (dyn->d_tag >= DT_LOPROC && dyn->d_tag <= DT_LOPROC + DT_PROCNUM) printf(" LOPROC "); else if ((Elf32_Word)DT_VERSIONTAGIDX(dyn->d_tag) < DT_VERSIONTAGNUM) printf(" DT_VERSIONTAGNUM "); else if ((Elf32_Word)DT_EXTRATAGIDX(dyn->d_tag) < DT_EXTRANUM) printf(" DT_EXTRANUM "); else printf(" b0rken "); printf("(%#x)\n", i * sizeof(Elf32_Dyn)); dyn++; i++; } return 0; }
bool saveSharedLibrary::readNewLib(){ Elf32_Shdr *newsh, *shdr; Elf_Scn *scn, *newScn; Elf32_Ehdr *ehdr; Elf32_Phdr *oldPhdr; Elf_Data *strdata, *newdata, *olddata; if ((ehdr = elf32_getehdr(newElf)) == NULL){ fprintf(stderr," FAILED obtaining ehdr readNewLib\n"); return false; } if((scn = elf_getscn(newElf, ehdr->e_shstrndx)) != NULL){ if((strdata = elf_getdata(scn, NULL)) == NULL){ fprintf(stderr," Failed obtaining .shstrtab data buffer \n"); return false; } }else{ fprintf(stderr," FAILED obtaining .shstrtab scn\n"); } unsigned int newScnName =0; scn = NULL; Elf_Data shstrtabData; #if defined(i386_unknown_linux2_0) \ || defined(x86_64_unknown_linux2_4) /* save the PHDR from the library */ oldPhdr = elf32_getphdr(newElf); Elf32_Phdr phdrBuffer[ehdr->e_phnum]; /* copy it over to a buffer because, on linux, we will close newElf and reopen it. This closing of newElf should dealloc the data pointed to by oldPhdr */ memcpy(phdrBuffer, oldPhdr, ehdr->e_phnum * ehdr->e_phentsize); #endif for (int cnt = 1; (scn = elf_nextscn(newElf, scn)); cnt++) { //copy sections from newElf to newElf. shdr = elf32_getshdr(scn); olddata = elf_getdata(scn,NULL); if(!strcmp( (char *)strdata->d_buf + shdr->sh_name, ".text")){ textAddr = shdr->sh_addr; textData = olddata; textSize = shdr->sh_size; } if(!strcmp( (char*) strdata->d_buf + shdr->sh_name, ".shstrtab")){ const char *secname =".dyninst_mutated\0"; shstrtabData.d_size = olddata->d_size+strlen(secname)+1; newShstrtabData_d_buf = new char[shstrtabData.d_size]; shstrtabData.d_buf = newShstrtabData_d_buf; memcpy( shstrtabData.d_buf, olddata->d_buf, olddata->d_size); memcpy(&(((char*) shstrtabData.d_buf)[olddata->d_size]), secname, strlen(secname)+1); newScnName = olddata->d_size; olddata->d_buf = shstrtabData.d_buf; olddata->d_size = shstrtabData.d_size; shdr->sh_size +=strlen(secname)+1; /* if the section header table is past this section in the ELF file, calculate the new offset*/ if(ehdr ->e_shoff > shdr->sh_offset){ ehdr->e_shoff += strlen(secname)+1; } elf_flagscn(scn,ELF_C_SET,ELF_F_DIRTY); } } ehdr-> e_shnum++; newScn = elf_newscn(newElf); newsh = elf32_getshdr(newScn); newsh->sh_name = newScnName; newsh->sh_type = SHT_NOBITS; // SHT_NOTE; newsh->sh_flags=0; newsh->sh_addr = 0x0; newsh->sh_offset = shdr->sh_offset; newsh->sh_size=0; newsh->sh_link=0; newsh->sh_info=0; newsh->sh_addralign = 0x1; //Values 0 and 1 mean the section has no alignment constraints. newsh->sh_entsize = 0; newdata = elf_newdata(newScn); newdata->d_size =0; newdata->d_buf=0; elf_update(newElf, ELF_C_NULL); /* elfutils on linux does not write data back to an ELF file you have opened correctly. Specifically, if you add a section the section's section header has space allocated for it in the file but no data is written to it. lovely, eh? to combat this, we reopen the file we just closed, and find the empty section header and fill it with data. */ #if defined(i386_unknown_linux2_0) \ || defined(x86_64_unknown_linux2_4) elf_update(newElf, ELF_C_WRITE); elf_end(newElf); P_close(newfd); if((newfd = (open(newpathname, O_RDWR)))==-1){ fprintf(stderr,"%s[%d]: cannot open new SO : %s\n",FILE__, __LINE__, newpathname); perror(" FAIL "); return false;; } if((newElf = elf_begin(newfd, ELF_C_RDWR, NULL)) ==NULL){ fprintf(stderr,"cannot open ELF %s \n", newpathname); return false;; } if ((ehdr = elf32_getehdr(newElf)) == NULL){ fprintf(stderr," FAILED obtaining ehdr readNewLib\n"); return false; } if((scn = elf_getscn(newElf, ehdr->e_shstrndx)) != NULL){ if((strdata = elf_getdata(scn, NULL)) == NULL){ fprintf(stderr," Failed obtaining .shstrtab data buffer \n"); return false; } }else{ fprintf(stderr," FAILED obtaining .shstrtab scn\n"); } scn = NULL; bool foundText=false; for (int cnt = 1; (scn = elf_nextscn(newElf, scn)); cnt++) { //copy sections from newElf to newElf. shdr = elf32_getshdr(scn); olddata = elf_getdata(scn,NULL); if(!foundText && !strcmp( (char *)strdata->d_buf + shdr->sh_name, ".text")){ textAddr = shdr->sh_addr; textData = olddata; textSize = shdr->sh_size; elf_flagscn(scn,ELF_C_SET,ELF_F_DIRTY); foundText = true; } } /**UPDATE THE LAST SHDR **/ memset(shdr,'\0', sizeof(Elf32_Shdr)); shdr->sh_name = newScnName; shdr->sh_addr = 0x0; shdr->sh_type = 7; /* update the PHDR, well just make sure it is reset to what was in the original library */ Elf32_Phdr *newPhdr = elf32_getphdr(newElf); memcpy(newPhdr,phdrBuffer, ehdr->e_phnum * ehdr->e_phentsize); /* be extra sure, set the DIRTY flag */ elf_flagphdr(newElf, ELF_C_SET,ELF_F_DIRTY); elf_flagscn(scn,ELF_C_SET,ELF_F_DIRTY); elf_update(newElf, ELF_C_NULL); #endif return true; }
static int build_file(Elf *src_elf, GElf_Ehdr *src_ehdr, Cmd_Info *cmd_info) { Elf_Scn *src_scn; Elf_Scn *dst_scn; int new_sh_name = 0; /* to hold the offset for the new */ /* section's name */ Elf *dst_elf = 0; Elf_Data *elf_data; Elf_Data *data; int64_t scn_no, x; size_t no_of_symbols = 0; section_info_table *info; unsigned int c = 0; int fdtmp; GElf_Shdr src_shdr; GElf_Shdr dst_shdr; GElf_Ehdr dst_ehdr; GElf_Off new_offset = 0, r; size_t shnum, shstrndx; if (elf_getshnum(src_elf, &shnum) == NULL) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } if (elf_getshstrndx(src_elf, &shstrndx) == NULL) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } if ((fdtmp = open(elftmpfile, O_RDWR | O_TRUNC | O_CREAT, (mode_t)0666)) == -1) { error_message(OPEN_TEMP_ERROR, SYSTEM_ERROR, strerror(errno), prog, elftmpfile); return (FAILURE); } if ((dst_elf = elf_begin(fdtmp, ELF_C_WRITE, (Elf *) 0)) == NULL) { error_message(READ_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog, elftmpfile); (void) close(fdtmp); return (FAILURE); } if (gelf_newehdr(dst_elf, gelf_getclass(src_elf)) == NULL) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } /* initialize dst_ehdr */ (void) gelf_getehdr(dst_elf, &dst_ehdr); dst_ehdr = *src_ehdr; /* * flush the changes to the ehdr so the * ident array is filled in. */ (void) gelf_update_ehdr(dst_elf, &dst_ehdr); if (src_ehdr->e_phnum != 0) { (void) elf_flagelf(dst_elf, ELF_C_SET, ELF_F_LAYOUT); if (gelf_newphdr(dst_elf, src_ehdr->e_phnum) == NULL) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } for (x = 0; x < src_ehdr->e_phnum; ++x) { GElf_Phdr dst; GElf_Phdr src; /* LINTED */ (void) gelf_getphdr(src_elf, (int)x, &src); /* LINTED */ (void) gelf_getphdr(dst_elf, (int)x, &dst); (void) memcpy(&dst, &src, sizeof (GElf_Phdr)); /* LINTED */ (void) gelf_update_phdr(dst_elf, (int)x, &dst); } x = location(dst_ehdr.e_phoff, 0, src_elf); if (x == AFTER) new_offset = (GElf_Off)src_ehdr->e_ehsize; } scn_no = 1; while ((src_scn = sec_table[scn_no].scn) != (Elf_Scn *) -1) { info = &sec_table[scn_no]; /* If section should be copied to new file NOW */ if ((info->secno != (GElf_Word)DELETED) && info->secno <= scn_no) { if ((dst_scn = elf_newscn(dst_elf)) == NULL) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } (void) gelf_getshdr(dst_scn, &dst_shdr); (void) gelf_getshdr(info->scn, &src_shdr); (void) memcpy(&dst_shdr, &src_shdr, sizeof (GElf_Shdr)); /* * Update link and info fields * The sh_link field may have special values so * check them first. */ if ((src_shdr.sh_link >= shnum) || (src_shdr.sh_link == 0)) dst_shdr.sh_link = src_shdr.sh_link; else if ((int)sec_table[src_shdr.sh_link].secno < 0) dst_shdr.sh_link = 0; else dst_shdr.sh_link = sec_table[src_shdr.sh_link].secno; if ((src_shdr.sh_type == SHT_REL) || (src_shdr.sh_type == SHT_RELA)) { if ((src_shdr.sh_info >= shnum) || ((int)sec_table[src_shdr. sh_info].secno < 0)) dst_shdr.sh_info = 0; else dst_shdr.sh_info = sec_table[src_shdr.sh_info].secno; } data = sec_table[scn_no].data; if ((elf_data = elf_newdata(dst_scn)) == NULL) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } *elf_data = *data; /* SHT_{DYNSYM, SYMTAB} might need some change */ if (((src_shdr.sh_type == SHT_SYMTAB) || (src_shdr.sh_type == SHT_DYNSYM)) && src_shdr.sh_entsize != 0 && (cmd_info->no_of_delete != 0 || cmd_info->no_of_nulled != 0)) { char *new_sym; no_of_symbols = src_shdr.sh_size / src_shdr.sh_entsize; new_sym = malloc(no_of_symbols * src_shdr.sh_entsize); if (new_sym == NULL) { error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); mcs_exit(FAILURE); } /* CSTYLED */ elf_data->d_buf = (void *) new_sym; for (c = 0; c < no_of_symbols; c++) { GElf_Sym csym; (void) gelf_getsym(data, c, &csym); if ((csym.st_shndx < SHN_LORESERVE) && (csym.st_shndx != SHN_UNDEF)) { section_info_table *i; i = &sec_table[csym.st_shndx]; if (((int)i->secno != DELETED) && ((int)i->secno != NULLED)) csym.st_shndx = i->secno; else { if (src_shdr.sh_type == SHT_SYMTAB) /* * The section which * this * symbol relates * to is removed. * There is no way to * specify this fact, * just change the shndx * to 1. */ csym.st_shndx = 1; else { /* * If this is in a * .dynsym, NULL it out. */ csym.st_shndx = 0; csym.st_name = 0; csym.st_value = 0; csym.st_size = 0; csym.st_info = 0; csym.st_other = 0; csym.st_shndx = 0; } } } (void) gelf_update_sym(elf_data, c, &csym); } } /* update SHT_SYMTAB_SHNDX */ if ((src_shdr.sh_type == SHT_SYMTAB_SHNDX) && (src_shdr.sh_entsize != 0) && ((cmd_info->no_of_delete != 0) || (cmd_info->no_of_nulled != 0))) { GElf_Word *oldshndx; GElf_Word *newshndx; uint_t entcnt; entcnt = src_shdr.sh_size / src_shdr.sh_entsize; oldshndx = data->d_buf; newshndx = malloc(entcnt * src_shdr.sh_entsize); if (newshndx == NULL) { error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); mcs_exit(FAILURE); } elf_data->d_buf = (void *)newshndx; for (c = 0; c < entcnt; c++) { if (oldshndx[c] != SHN_UNDEF) { section_info_table *i; i = &sec_table[oldshndx[c]]; if (((int)i->secno != DELETED) && ((int)i->secno != NULLED)) newshndx[c] = i->secno; else newshndx[c] = oldshndx[c]; } else newshndx[c] = oldshndx[c]; } } /* * If the section is to be updated, * do so. */ if (ISCANDIDATE(info->flags)) { if ((GET_LOC(info->flags) == PRIOR) && (((int)info->secno == NULLED) || ((int)info->secno == EXPANDED) || ((int)info->secno == SHRUNK))) { /* * The section is updated, * but the position is not too * good. Need to NULL this out. */ dst_shdr.sh_name = 0; dst_shdr.sh_type = SHT_PROGBITS; if ((int)info->secno != NULLED) { (cmd_info->no_of_moved)++; SET_MOVING(info->flags); } } else { /* * The section is positioned AFTER, * or there are no segments. * It is safe to update this section. */ data = sec_table[scn_no].mdata; *elf_data = *data; dst_shdr.sh_size = elf_data->d_size; } } /* add new section name to shstrtab? */ else if (!Sect_exists && (new_sec_string != NULL) && (scn_no == shstrndx) && (dst_shdr.sh_type == SHT_STRTAB) && ((src_ehdr->e_phnum == 0) || ((x = scn_location(dst_scn, dst_elf)) != IN) || (x != PRIOR))) { size_t sect_len; sect_len = strlen(SECT_NAME); if ((elf_data->d_buf = malloc((dst_shdr.sh_size + sect_len + 1))) == NULL) { error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); mcs_exit(FAILURE); } /* put original data plus new data in section */ (void) memcpy(elf_data->d_buf, data->d_buf, data->d_size); (void) memcpy(&((char *)elf_data->d_buf) [data->d_size], SECT_NAME, sect_len + 1); /* LINTED */ new_sh_name = (int)dst_shdr.sh_size; dst_shdr.sh_size += sect_len + 1; elf_data->d_size += sect_len + 1; } /* * Compute offsets. */ if (src_ehdr->e_phnum != 0) { /* * Compute section offset. */ if (off_table[scn_no] == 0) { if (dst_shdr.sh_addralign != 0) { r = new_offset % dst_shdr.sh_addralign; if (r) new_offset += dst_shdr.sh_addralign - r; } dst_shdr.sh_offset = new_offset; elf_data->d_off = 0; } else { if (nobits_table[scn_no] == 0) new_offset = off_table[scn_no]; } if (nobits_table[scn_no] == 0) new_offset += dst_shdr.sh_size; } } (void) gelf_update_shdr(dst_scn, &dst_shdr); /* flush changes */ scn_no++; } /* * This is the real new section. */ if (!Sect_exists && new_sec_string != NULL) { size_t string_size; string_size = strlen(new_sec_string) + 1; if ((dst_scn = elf_newscn(dst_elf)) == NULL) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } (void) gelf_getshdr(dst_scn, &dst_shdr); dst_shdr.sh_name = new_sh_name; dst_shdr.sh_type = SHT_PROGBITS; dst_shdr.sh_flags = 0; dst_shdr.sh_addr = 0; if (src_ehdr->e_phnum != NULL) dst_shdr.sh_offset = new_offset; else dst_shdr.sh_offset = 0; dst_shdr.sh_size = string_size + 1; dst_shdr.sh_link = 0; dst_shdr.sh_info = 0; dst_shdr.sh_addralign = 1; dst_shdr.sh_entsize = 0; (void) gelf_update_shdr(dst_scn, &dst_shdr); /* flush changes */ if ((elf_data = elf_newdata(dst_scn)) == NULL) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } elf_data->d_size = string_size + 1; if ((elf_data->d_buf = (char *) calloc(1, string_size + 1)) == NULL) { error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0, prog); mcs_exit(FAILURE); } (void) memcpy(&((char *)elf_data->d_buf)[1], new_sec_string, string_size); elf_data->d_align = 1; new_offset += string_size + 1; } /* * If there are sections which needed to be moved, * then do it here. */ if (cmd_info->no_of_moved != 0) { int cnt; info = &sec_table[0]; for (cnt = 0; cnt < shnum; cnt++, info++) { if ((GET_MOVING(info->flags)) == 0) continue; if ((src_scn = elf_getscn(src_elf, info->osecno)) == NULL) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } if (gelf_getshdr(src_scn, &src_shdr) == NULL) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } if ((dst_scn = elf_newscn(dst_elf)) == NULL) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } if (gelf_getshdr(dst_scn, &dst_shdr) == NULL) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } dst_shdr = src_shdr; data = info->mdata; dst_shdr.sh_offset = new_offset; /* UPDATE fields */ dst_shdr.sh_size = data->d_size; if ((shnum >= src_shdr.sh_link) || (src_shdr.sh_link == 0)) dst_shdr.sh_link = src_shdr.sh_link; else dst_shdr.sh_link = sec_table[src_shdr.sh_link].osecno; if ((shnum >= src_shdr.sh_info) || (src_shdr.sh_info == 0)) dst_shdr.sh_info = src_shdr.sh_info; else dst_shdr.sh_info = sec_table[src_shdr.sh_info].osecno; (void) gelf_update_shdr(dst_scn, &dst_shdr); if ((elf_data = elf_newdata(dst_scn)) == NULL) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } (void) memcpy(elf_data, data, sizeof (Elf_Data)); new_offset += data->d_size; } } /* * In the event that the position of the sting table has changed, * as a result of deleted sections, update the ehdr->e_shstrndx. */ if ((shstrndx > 0) && (shnum > 0) && (sec_table[shstrndx].secno < shnum)) { if (sec_table[shstrndx].secno < SHN_LORESERVE) { dst_ehdr.e_shstrndx = sec_table[dst_ehdr.e_shstrndx].secno; } else { Elf_Scn *_scn; GElf_Shdr shdr0; /* * If shstrndx requires 'Extended ELF Sections' * then it is stored in shdr[0].sh_link */ dst_ehdr.e_shstrndx = SHN_XINDEX; if ((_scn = elf_getscn(dst_elf, 0)) == NULL) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } (void) gelf_getshdr(_scn, &shdr0); shdr0.sh_link = sec_table[shstrndx].secno; (void) gelf_update_shdr(_scn, &shdr0); } } if (src_ehdr->e_phnum != 0) { size_t align = gelf_fsize(dst_elf, ELF_T_ADDR, 1, EV_CURRENT); /* UPDATE location of program header table */ if (location(dst_ehdr.e_phoff, 0, dst_elf) == AFTER) { r = new_offset % align; if (r) new_offset += align - r; dst_ehdr.e_phoff = new_offset; new_offset += dst_ehdr.e_phnum * dst_ehdr.e_phentsize; } /* UPDATE location of section header table */ if ((location(dst_ehdr.e_shoff, 0, src_elf) == AFTER) || ((location(dst_ehdr.e_shoff, 0, src_elf) == PRIOR) && (!Sect_exists && new_sec_string != NULL))) { r = new_offset % align; if (r) new_offset += align - r; dst_ehdr.e_shoff = new_offset; } free(b_e_seg_table); /* * The NOTE segment is the one segment whos * sections might get moved by mcs processing. * Make sure that the NOTE segments offset points * to the .note section. */ if ((notesegndx != -1) && (notesctndx != -1) && (sec_table[notesctndx].secno)) { Elf_Scn * notescn; GElf_Shdr nshdr; notescn = elf_getscn(dst_elf, sec_table[notesctndx].secno); (void) gelf_getshdr(notescn, &nshdr); if (gelf_getclass(dst_elf) == ELFCLASS32) { Elf32_Phdr * ph = elf32_getphdr(dst_elf) + notesegndx; /* LINTED */ ph->p_offset = (Elf32_Off)nshdr.sh_offset; } else { Elf64_Phdr * ph = elf64_getphdr(dst_elf) + notesegndx; ph->p_offset = (Elf64_Off)nshdr.sh_offset; } } } /* copy ehdr changes back into real ehdr */ (void) gelf_update_ehdr(dst_elf, &dst_ehdr); if (elf_update(dst_elf, ELF_C_WRITE) < 0) { error_message(LIBELF_ERROR, LIBelf_ERROR, elf_errmsg(-1), prog); return (FAILURE); } (void) elf_end(dst_elf); (void) close(fdtmp); return (SUCCESS); }
/* Extract ROM code+data from an ELF file and convert it into a C array */ int main(int argc,char *argv[]) { unsigned char buffer[8]; m_uint32_t vaddr,start; Elf32_Ehdr *ehdr; Elf32_Phdr *phdr; Elf *img_elf; size_t len,clen; int i,j,fd; FILE *bfd,*fd_out; if (argc != 4) { fprintf(stderr,"Usage: %s <input_file> <output_file> <addr>\n",argv[0]); exit(EXIT_FAILURE); } start = strtoul(argv[3],NULL,0); if ((fd = open(argv[1],O_RDONLY)) == -1) return(-1); if (elf_version(EV_CURRENT) == EV_NONE) { fprintf(stderr,"load_elf_image: library out of date\n"); return(-1); } if (!(img_elf = elf_begin(fd,ELF_C_READ,NULL))) { fprintf(stderr,"load_elf_image: elf_begin: %s\n", elf_errmsg(elf_errno())); return(-1); } if (!(phdr = elf32_getphdr(img_elf))) { fprintf(stderr,"load_elf_image: elf32_getphdr: %s\n", elf_errmsg(elf_errno())); return(-1); } if (!(fd_out = fopen(argv[2],"w"))) { fprintf(stderr,"Unable to create file \"%s\"\n",argv[2]); exit(EXIT_FAILURE); } ehdr = elf32_getehdr(img_elf); phdr = elf32_getphdr(img_elf); printf("Extracting ROM from ELF file '%s'...\n",argv[1]); bfd = fdopen(fd,"r"); if (!bfd) { perror("load_elf_image: fdopen"); return(-1); } for(i=0;i<ehdr->e_phnum;i++,phdr++) { fseek(bfd,phdr->p_offset,SEEK_SET); vaddr = (m_uint64_t)phdr->p_vaddr; len = phdr->p_filesz; if (vaddr != start) continue; while(len > 0) { clen = fread(buffer,1,sizeof(buffer),bfd); if (clen == 0) break; fprintf(fd_out," "); for(j=0;j<clen;j++) fprintf(fd_out,"0x%2.2x, ",buffer[j]); fprintf(fd_out,"\n"); len -= clen; } } fclose(fd_out); return(0); }
int phdr_diff( Elf *elf[2], int verbose ) { int i = 0, j = 0; int k[2] = {0,0}; int hasdyn[2] = {0,0}; Elf32_Dyn *dyn; Elf_Scn *scn[2]; seg dynseg[2] = {{0,0},{0,0}}; seg symseg[2] = {{0,0},{0,0}}; seg hashseg[2] = {{0,0},{0,0}}; seg reldynseg[2] = {{0,0},{0,0}}; int retval = ED_SUCCESS; Elf32_Phdr *phdr[2] = {NULL, NULL}; Elf32_Off offset[2] = { 0, 0 }; Elf32_Off size[2] = { 0, 0 }; Elf32_Off vaddr[2] = { 0, 0 }; for (i=0;i<2;i++) { phdr[i]=elf32_getphdr(elf[i]); Elf32_swapPhdr(elf[i]); for (j=0;j<elf[i]->e_ehdrp->e_phnum;j++) { if (phdr[i][j].p_type==PT_DYNAMIC) { hasdyn[i]=1; dynseg[i].offset = phdr[i][j].p_offset; dynseg[i].size = phdr[i][j].p_filesz; } else if (phdr[i][j].p_type==PT_LOAD) { if (!vaddr[i] && (phdr[i][j].p_offset==0)) vaddr[i]=phdr[i][j].p_vaddr; } } } if ((hasdyn[0]) || (hasdyn[1])) { if (hasdyn[0] != hasdyn[1]) { if (verbose>1) fprintf(stderr, "elfdiff: One input file is dynamically linked, the other is not.\n"); return ED_HDRFAIL; } else { char *buf[2] = {NULL, NULL}; for (i=0;i<2;i++) { buf[i]=(char*)malloc(dynseg[i].size*sizeof(char)); } for (i=0;i<2;i++) { if (lseek(elf[i]->e_fd, dynseg[i].offset, SEEK_SET) == -1 ) { if (verbose) fprintf(stderr, "elfdiff: Seek error in input file %d.\n", i); free(buf[0]); free(buf[1]); return ED_IOFAIL; } if (read(elf[i]->e_fd, buf[i], dynseg[i].size)==-1) { if (verbose) fprintf(stderr, "elfdiff: Read error in input file %d.\n", i); free(buf[0]); free(buf[1]); return ED_IOFAIL; } } for (i=0;i<2;i++) { dyn=(Elf32_Dyn*)buf[i]; while (dyn->d_tag!=DT_NULL) { Elf32_swapDyn(elf[i], dyn); if (dyn->d_tag==DT_SYMTAB) { symseg[i].offset=dyn->d_un.d_ptr; symseg[i].offset-=vaddr[i]; } else if (dyn->d_tag==DT_HASH) { hashseg[i].offset=dyn->d_un.d_ptr; hashseg[i].offset-=vaddr[i]; } dyn++; } } for (i=0;i<2;i++) { free(buf[i]); } for (i=0;i<2;i++) { Elf32_Word numchains[2] = {0,0}; if (lseek(elf[i]->e_fd, hashseg[i].offset, SEEK_SET) == -1) { if (verbose) fprintf(stderr, "elfdiff: Seek error in input file %d.\n", i); return ED_IOFAIL; } if (read(elf[i]->e_fd, numchains, 2*sizeof(Elf32_Word))==-1) { if (verbose) fprintf(stderr, "elfdiff: Read error in input file %d.\n", i); return ED_IOFAIL; } if (elf[i]->xlat) swap_32(&numchains[1]); symseg[i].size = numchains[1] * sizeof(Elf32_Sym); } } } if (handle_rel_dyn) { for (i=0;i<2;i++) { scn[i] = elf_getscn(elf[i], 0); elf32_getshdr(scn[i]); } for (i=0;i<2;i++) { for (k[i]=0;k[i]<elf[i]->e_ehdrp->e_shnum;k[i]++) { if (!strcmp(elf_strptr(elf[i],elf[i]->e_ehdrp->e_shstrndx, elf[i]->e_shdrp[k[i]].sh_name),".rel.dyn")) { reldynseg[i].offset=elf[i]->e_shdrp[k[i]].sh_offset; reldynseg[i].size=elf[i]->e_shdrp[k[i]].sh_size; break; } } } k[0]=0; k[1]=0; } while (!retval) { for (i=0;i<2;i++) { for (;k[i]<elf[i]->e_ehdrp->e_phnum;k[i]++) { if ((phdr[i][k[i]].p_filesz > 0) && (phdr[i][k[i]].p_type != PT_NOTE) && (phdr[i][k[i]].p_type!=PT_PHDR)) { offset[i]=phdr[i][k[i]].p_offset; size[i]=phdr[i][k[i]].p_filesz; if (offset[i] < (sizeof(Elf32_Ehdr)+(elf[i]->e_ehdrp->e_phnum*sizeof(Elf32_Phdr)))) { size[i]-=((sizeof(Elf32_Ehdr)+(elf[i]->e_ehdrp->e_phnum*sizeof(Elf32_Phdr)))-offset[i]); offset[i]=(sizeof(Elf32_Ehdr)+(elf[i]->e_ehdrp->e_phnum*sizeof(Elf32_Phdr))); } k[i]++; break; } } if (k[i] >= elf[i]->e_ehdrp->e_phnum) { return retval; } } if (size[0]) { char *buf[2] = { NULL, NULL }; if (size[0] != size[1]) { if (verbose>1) fprintf(stderr, "elfdiff - Size of segment %d - WARNING\n", k[0]-1); if (size[0] > size[1]) { int t; t=size[1]; size[1]=size[0]; size[0]=t; } } for (i=0;i<2;i++) { buf[i]=(char*)malloc(size[i]*sizeof(char)); } for (i=0;i<2;i++) { if (lseek(elf[i]->e_fd, offset[i], SEEK_SET) == -1 ) { if (verbose) fprintf(stderr, "elfdiff: Seek error in input file %d.\n", i); free(buf[0]); free(buf[1]); return ED_IOFAIL; } if (read(elf[i]->e_fd, buf[i], size[i])==-1) { if (verbose) fprintf(stderr, "elfdiff: Read error in input file %d.\n", i); free(buf[0]); free(buf[1]); return ED_IOFAIL; } //This makes the assumption that the DT_SYMTAB will not overlap two segments if ((symseg[i].offset >= offset[i]) && (symseg[i].offset < (offset[i]+size[i]))) { memset(buf[i]+(symseg[i].offset-offset[i]), 0, symseg[i].size); } if (handle_rel_dyn) { //This makes the assumption that the .rel.dyn section will not overlap two segments if ((reldynseg[i].offset >= offset[i]) && (reldynseg[i].offset < (offset[i]+size[i]))) { memset(buf[i]+(reldynseg[i].offset-offset[i]), 0, reldynseg[i].size); } } } if (memcmp(buf[0], buf[1], size[0])!=0) { if (verbose>1) fprintf(stderr, "elfdiff: Contents of segment %d - FAIL.\n", k[1]-1); retval = ED_DATAFAIL; } for (i=0;i<2;i++) { free(buf[i]); } if (handle_rel_dyn && reldynseg[0].size && reldynseg[1].size) { for (i=0;i<2;i++) { buf[i]=(char*)malloc(reldynseg[i].size*sizeof(char)); } for (i=0;i<2;i++) { if (lseek(elf[i]->e_fd, reldynseg[i].offset, SEEK_SET) == -1 ) { if (verbose) fprintf(stderr, "elfdiff: Seek error in input file %d.\n", i); free(buf[0]); free(buf[1]); return ED_IOFAIL; } if (read(elf[i]->e_fd, buf[i], reldynseg[i].size)==-1) { if (verbose) fprintf(stderr, "elfdiff: Read error in input file %d.\n", i); free(buf[0]); free(buf[1]); return ED_IOFAIL; } } qsort(buf[0], (reldynseg[0].size / (2*sizeof(int))), 2*sizeof(int), rel_comp); qsort(buf[1], (reldynseg[1].size / (2*sizeof(int))), 2*sizeof(int), rel_comp); if (memcmp(buf[0], buf[1], reldynseg[1].size)!=0) { if (verbose>1) fprintf(stderr, "elfdiff: Contents of .rel.dyn section - FAIL.\n"); for (i=0;i<2;i++) { free(buf[i]); } retval = ED_DATAFAIL; } for (i=0;i<2;i++) { free(buf[i]); } } } offset[0] = offset[1] = 0; size[0] = size[1] = 0; } /////////////////////////////////////////// //FIXME: PT_NOTE and DT_SYMTAB processing here /////////////////////////////////////////// return retval; }
int main(int argc, const char *argv[]) { int i, fd; Elf *pelf = NULL; char *id, bytes[5]; size_t n = 0; Elf32_Phdr *phdr32 = NULL; GElf_Phdr gphdr = { 0 }; if (argc != 2) errx(EXIT_FAILURE, "usage: %s file-name", argv[0]); if (elf_version(EV_CURRENT) == EV_NONE) errx(EXIT_FAILURE, "ELF library initialization " "failed: %s", elf_errmsg(-1)); if ((fd = open(argv[1], O_RDONLY, 0)) < 0) errx(EXIT_FAILURE, "open \"%s\" failed", argv[1]); if ((pelf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) errx(EXIT_FAILURE, "elf_begin() failed: %s", elf_errmsg(-1)); if (elf_kind(pelf) != ELF_K_ELF) errx(EXIT_FAILURE, "\"%s\" is not an ELF object.", argv[1]); // get the num of program header table if (elf_getphdrnum(pelf, &n) != 0) errx(EXIT_FAILURE, "elf_getphdrnum() failed: %s.", elf_errmsg(-1)); #if 0 // 32bit if ((phdr32 = elf32_getphdr(pelf)) == NULL) errx(EXIT_FAILURE, "elf32_getphdr() failed: %s.", elf_errmsg(-1)); for (i = 0; i < n; i++) { Elf32_Phdr phdr = phdr32[i]; printf("PHDR %d:\n", i); #define PRINT_FMT " %-20s 0x%jx" #define PRINT_FIELD(N) do { printf(PRINT_FMT, #N, (uintmax_t)phdr.N); } while (0); #define NL() do { printf("\n"); } while (0); PRINT_FIELD(p_type); print_ptype(phdr.p_type); NL(); PRINT_FIELD(p_offset); NL(); PRINT_FIELD(p_vaddr); NL(); PRINT_FIELD(p_paddr); NL(); PRINT_FIELD(p_filesz); NL(); PRINT_FIELD(p_memsz); NL(); PRINT_FIELD(p_flags); printf(" ["); if (phdr.p_flags & PF_X) printf(" execute"); if (phdr.p_flags & PF_R) printf(" read"); if (phdr.p_flags & PF_W) printf(" write"); printf(" ]"); NL(); PRINT_FIELD(p_align); NL(); } #endif #if 1 for (i = 0; i < n; i++) { // get every entry fist if (gelf_getphdr(pelf, i, &gphdr) != &gphdr) errx(EXIT_FAILURE, "gelf_getphdr() failed: %s.", elf_errmsg(-1)); // now print every entry printf("PHDR %d:\n", i); #define PRINT_FMT " %-20s 0x%jx" #define PRINT_FIELD(N) do { printf(PRINT_FMT, #N, (uintmax_t)gphdr.N); } while (0); #define NL() do { printf("\n"); } while (0); PRINT_FIELD(p_type); print_ptype(gphdr.p_type); NL(); PRINT_FIELD(p_offset); NL(); PRINT_FIELD(p_vaddr); NL(); PRINT_FIELD(p_paddr); NL(); PRINT_FIELD(p_filesz); NL(); PRINT_FIELD(p_memsz); NL(); PRINT_FIELD(p_flags); ; printf(" ["); if (gphdr.p_flags & PF_X) printf(" execute"); if (gphdr.p_flags & PF_R) printf(" read"); if (gphdr.p_flags & PF_W) printf(" write"); printf(" ]"); NL(); PRINT_FIELD(p_align); NL(); } #endif elf_end(pelf); close(fd); exit(EXIT_SUCCESS); }
void main(int argc, char ** argv) { #if !defined(__osf__) Elf32_Ehdr * ehdr; Elf32_Phdr * phdr; Elf * elf; Elf * elf2; int fd,fd2; int exf = 0; int i; size_t flen = 0; size_t flen2 = 0; time_t t; if (of == NULL) { of = stdout; } time(&t); if (argc != 4) { fprintf(of,"Core analysis %s needs three arguments: executable, core file, dest file\n", reldate); exit(1); } ofname = argv[3]; of = fopen(ofname,"a"); fprintf(of,"Core analysis %s. Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.\nCopyright (C) 2005 Red Hat, Inc.\nAll rights reserved.\nCurrently %sOpening %s %s\n",reldate,ctime(&t),argv[1],argv[2]); if ((fd2 = open(argv[1], O_RDONLY)) == -1) { perror(argv[1]); exit(1); } (void) elf_version(EV_CURRENT); /* Obtain the ELF descriptor */ if ((elf2 = elf_begin(fd2, ELF_C_READ, NULL)) == NULL) failure("beginining"); if ((erf2 = elf_rawfile(elf2,&flen2)) == NULL) { failure("elf_rawfile"); } /* Obtain the .shstrtab data buffer */ if ((ehdr = elf32_getehdr(elf2)) == NULL) { failure("reading header"); } if (ehdr->e_type == ET_CORE) { fprintf(of,"Executable file should be given as the first argument.\n"); exit(1); } if (ehdr->e_machine == EM_SPARC || ehdr->e_machine == EM_SPARC32PLUS || ehdr->e_machine == EM_SPARCV9) { fprintf(of,"architecture is SPARC\n"); exf = EM_SPARC; } else if (ehdr->e_machine == EM_386) { fprintf(of,"architecture is x86\n"); exf = ehdr->e_machine; } else { fprintf(of,"unknown architecture %d\n",ehdr->e_machine); exit(1); } if (ehdr->e_phnum == 0) { fprintf(of,"no program header in program file\n"); exit(1); } load_segments(elf2,ehdr->e_phnum,erf2,flen2,0); /* Open the input file */ if ((fd = open(argv[2], O_RDONLY)) == -1) { perror(argv[2]); exit(1); } /* Obtain the ELF descriptor */ if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) failure("beginining"); if ((erf = elf_rawfile(elf,&flen)) == NULL) { failure("elf_rawfile"); } /* Obtain the .shstrtab data buffer */ if ((ehdr = elf32_getehdr(elf)) == NULL) { failure("reading header"); } if (ehdr->e_type != ET_CORE) { fprintf(of,"second argument is ELF but not a core file\n"); exit(1); } if (ehdr->e_machine != exf) { fprintf(of,"Architecture mismatch between executable and core file.\n"); exit(1); } if (ehdr->e_phnum == 0) { fprintf(of,"no program header in core file\n"); exit(1); } load_segments(elf,ehdr->e_phnum,erf,flen,1); #ifdef notanymore fprintf(of,"Seeking debug information in core file.\n"); phdr = elf32_getphdr(elf); for (i = 0; i < ehdr->e_phnum; i++) { if (phdr[i].p_type == PT_LOAD) { if (phdr[i].p_offset && phdr[i].p_filesz) { if (phdr[i].p_offset + phdr[i].p_filesz > flen) { continue; } if (seek_debug(erf,phdr[i].p_offset,phdr[i].p_filesz)) { break; } } } } #endif if (of != stdout) { fclose(of); } try_adb(argv[1],argv[2]); #endif }