Elf_Scn * elf_newscn(Elf *e) { int ec; void *ehdr; Elf_Scn *scn; if (e == NULL || e->e_kind != ELF_K_ELF) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) { LIBELF_SET_ERROR(CLASS, 0); return (NULL); } if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) return (NULL); /* * The application may be asking for a new section descriptor * on an ELF object opened with ELF_C_RDWR or ELF_C_READ. We * need to bring in the existing section information before * appending a new one to the list. * * Per the ELF(3) API, an application is allowed to open a * file using ELF_C_READ, mess with its internal structure and * use elf_update(...,ELF_C_NULL) to compute its new layout. */ if (e->e_cmd != ELF_C_WRITE && (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 && _libelf_load_scn(e, ehdr) == 0) return (NULL); if (STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) { assert(e->e_u.e_elf.e_nscn == 0); if ((scn = _libelf_allocate_scn(e, (size_t) SHN_UNDEF)) == NULL) return (NULL); e->e_u.e_elf.e_nscn++; } assert(e->e_u.e_elf.e_nscn > 0); if ((scn = _libelf_allocate_scn(e, e->e_u.e_elf.e_nscn)) == NULL) return (NULL); e->e_u.e_elf.e_nscn++; (void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY); return (scn); }
int gelf_update_shdr(Elf_Scn *scn, GElf_Shdr *s) { int ec; Elf *e; Elf32_Shdr *sh32; if (s == NULL || scn == NULL || (e = scn->s_elf) == NULL || e->e_kind != ELF_K_ELF || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (e->e_cmd == ELF_C_READ) { LIBELF_SET_ERROR(MODE, 0); return (0); } (void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY); if (ec == ELFCLASS64) { scn->s_shdr.s_shdr64 = *s; return (1); } sh32 = &scn->s_shdr.s_shdr32; sh32->sh_name = s->sh_name; sh32->sh_type = s->sh_type; LIBELF_COPY_U32(sh32, s, sh_flags); LIBELF_COPY_U32(sh32, s, sh_addr); LIBELF_COPY_U32(sh32, s, sh_offset); LIBELF_COPY_U32(sh32, s, sh_size); sh32->sh_link = s->sh_link; sh32->sh_info = s->sh_info; LIBELF_COPY_U32(sh32, s, sh_addralign); LIBELF_COPY_U32(sh32, s, sh_entsize); return (1); }
Elf_Data * elf_newdata(Elf_Scn *s) { Elf *e; Elf_Data *d; if (s == NULL || (e = s->s_elf) == NULL || e->e_kind != ELF_K_ELF) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } /* * elf_newdata() has to append a data descriptor, so * bring in existing section data if not already present. */ if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data)) if (elf_getdata(s, NULL) == NULL) return (NULL); if ((d = malloc(sizeof(Elf_Data))) == NULL) { LIBELF_SET_ERROR(RESOURCE, errno); return (NULL); } STAILQ_INSERT_TAIL(&s->s_data, d, d_next); d->d_flags = 0; d->d_scn = s; d->d_align = 1; d->d_buf = NULL; d->d_off = (uint64_t) ~0; d->d_size = 0; d->d_type = ELF_T_BYTE; d->d_version = LIBELF_PRIVATE(version); (void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY); return (d); }
Elf_Data * elf_newdata(Elf_Scn *s) { Elf *e; struct _Libelf_Data *d; if (s == NULL || (e = s->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } assert(e->e_kind == ELF_K_ELF); /* * elf_newdata() has to append a data descriptor, so * bring in existing section data if not already present. */ if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data)) if (elf_getdata(s, NULL) == NULL) return (NULL); if ((d = _libelf_allocate_data(s)) == NULL) return (NULL); STAILQ_INSERT_TAIL(&s->s_data, d, d_next); d->d_data.d_align = 1; d->d_data.d_buf = NULL; d->d_data.d_off = (uint64_t) ~0; d->d_data.d_size = 0; d->d_data.d_type = ELF_T_BYTE; d->d_data.d_version = LIBELF_PRIVATE(version); (void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY); return (&d->d_data); }
int set_dynamic (DSO *dso, GElf_Word tag, GElf_Addr value, int fatal) { Elf_Data *data; Elf_Scn *scn; GElf_Dyn dyn; int ndx, maxndx; uint64_t mask = dso->info_set_mask; assert (dso->shdr[dso->dynamic].sh_type == SHT_DYNAMIC); scn = dso->scn[dso->dynamic]; data = elf_getdata (scn, NULL); assert (elf_getdata (scn, data) == NULL); switch (tag) { case DT_CHECKSUM: mask |= (1ULL << DT_CHECKSUM_BIT); break; case DT_GNU_PRELINKED: mask |= (1ULL << DT_GNU_PRELINKED_BIT); break; case DT_VERDEF: mask |= (1ULL << DT_VERDEF_BIT); break; case DT_VERNEED: mask |= (1ULL << DT_VERNEED_BIT); break; case DT_VERSYM: mask |= (1ULL << DT_VERSYM_BIT); break; default: if (tag < DT_NUM && tag < 50) mask |= (1ULL << tag); break; } maxndx = data->d_size / dso->shdr[dso->dynamic].sh_entsize; for (ndx = 0; ndx < maxndx; ndx++) { gelfx_getdyn (dso->elf, data, ndx, &dyn); if (dyn.d_tag == DT_NULL) break; else if (dyn.d_tag == tag) { if (dyn.d_un.d_ptr != value) { dyn.d_un.d_ptr = value; gelfx_update_dyn (dso->elf, data, ndx, &dyn); elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); } return 0; } } assert (ndx < maxndx); if (ndx + 1 < maxndx) { /* DT_NULL is not the last dynamic entry. */ gelfx_update_dyn (dso->elf, data, ndx + 1, &dyn); dyn.d_tag = tag; dyn.d_un.d_ptr = value; gelfx_update_dyn (dso->elf, data, ndx, &dyn); dso->info_set_mask = mask; elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); return 0; } if (fatal) error (0, 0, "%s: Not enough room to add .dynamic entry", dso->filename); return 1; }
unsigned int elf_flagshdr(Elf_Scn *s, Elf_Cmd c, unsigned int flags) { return (elf_flagscn(s, c, flags)); }
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 replaceAMDILSection(Elf* e, int nStream, MWCALtargetEnum target) { Elf_Scn* scn = NULL; size_t shstrndx = 0; static const int verbose = 0; static const int verboseDebug = 0; /* Get section index of section containing the string table of section names */ if (elf_getshdrstrndx(e, &shstrndx) != 0) { mw_printf("elf_getshdrstrndx failed: %s\n", elf_errmsg(-1)); return 1; } /* Iterate through all the sections */ while ((scn = elf_nextscn(e, scn))) { Elf32_Shdr* shdr; const char* name; /* Get the header for this section */ shdr = elf32_getshdr(scn); if (!shdr) { mw_printf("elf32_getshdr() failed: %s\n", elf_errmsg(-1)); return 1; } /* Look up the name of the section in the string table */ name = elf_strptr(e, shstrndx, shdr->sh_name); if (!name) { mw_printf("elf_strptr() failed: %s\n", elf_errmsg(-1)); return 1; } /* if (strstr(name, ".rodata") != NULL) { Elf_Data* data = elf_getdata(scn, NULL); FILE* f = fopen("rodata_section.bin", "wb"); if (f) { fwrite(data->d_buf, 1, data->d_size, f); fclose(f); } else { perror("Failed to open file"); } size_t roSize; char* r770RO = mwReadFileWithSize("rodata_section_RV770.bin", &roSize); assert(r770RO); data->d_buf = r770RO; data->d_size = roSize; if (!elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY)) { mw_printf("elf_flagdata() failed: %s\n", elf_errmsg(-1)); return 1; } if (!elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY)) { mw_printf("elf_flagscn() failed: %s\n", elf_errmsg(-1)); return 1; } if (elf_update(e, ELF_C_NULL) < 0) { mw_printf("elf_update(NULL) failed: %s\n", elf_errmsg(-1)); return 1; } } */ if (strstr(name, ".amdil") != NULL) { int uavId; const char* uavComment; Elf_Data* data; data = elf_getdata(scn, NULL); if (!data) { mw_printf("Failed to get data for .amdil section: %s\n", elf_errmsg(-1)); return 1; } if (verbose) { mw_printf("Replacing section data of type %d, off %d align "ZU"\n", data->d_type, (int) data->d_off, data->d_align); } /* Before we overwrite it, there is information we would like to extract */ uavComment = strstr((const char*) data->d_buf, ";uavid:"); if (!uavComment || (sscanf(uavComment, ";uavid:%d\n", &uavId) != 1)) { mw_printf("Error reading uavid from IL comment\n"); uavId = -1; } ilSrc = getILSrc(nStream, target, uavId, &ilSrcLen); if (!ilSrc || (ilSrcLen == 0)) { mw_printf("Failed to get IL source\n"); return 1; } data->d_buf = (void*) ilSrc; data->d_size = ilSrcLen; if (!elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY)) { mw_printf("elf_flagdata() failed: %s\n", elf_errmsg(-1)); return 1; } if (!elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY)) { mw_printf("elf_flagscn() failed: %s\n", elf_errmsg(-1)); return 1; } /* Don't let libelf rearrange the sections when writing. clBuildProgram() crashes on Windows if you don't do this with some(?) Catalyst versions */ if (!elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT)) { mw_printf("elf_flagelf() failed: %s\n", elf_errmsg(-1)); return 1; } if (elf_update(e, ELF_C_NULL) < 0) { mw_printf("elf_update(NULL) failed: %s\n", elf_errmsg(-1)); return 1; } } if (verboseDebug) { printf("Section %u %s\n", (unsigned int) elf_ndxscn(scn), name); } } if (elf_update(e, ELF_C_WRITE) < 0) { mw_printf("elf_update(ELF_C_WRITE) failed: %s\n", elf_errmsg(-1)); return 1; } return 0; }