int elfrw_write_Rel(FILE *fp, Elf64_Rel const *out) { if (is64bit_form()) { if (native_form()) { return fwrite(out, sizeof *out, 1, fp); } else { Elf64_Rel outrev; outrev.r_offset = rev_64xword(out->r_offset); outrev.r_info = rev_64xword(out->r_info); return fwrite(&outrev, sizeof outrev, 1, fp); } } else { Elf32_Rel out32; if (native_form()) { out32.r_offset = out->r_offset; out32.r_info = ELF32_R_INFO(ELF64_R_SYM(out->r_info), ELF64_R_TYPE(out->r_info)); } else { out32.r_offset = rev_32word(out->r_offset); out32.r_info = rev_32word(ELF32_R_INFO(ELF64_R_SYM(out->r_info), ELF64_R_TYPE(out->r_info))); } return fwrite(&out32, sizeof out32, 1, fp); } }
static void elf_x86_x86_write_reloc(unsigned char *bufp, elf_reloc_entry *reloc, unsigned int r_type, unsigned int r_sym) { YASM_WRITE_32I_L(bufp, reloc->reloc.addr); YASM_WRITE_32_L(bufp, ELF32_R_INFO((unsigned long)r_sym, (unsigned char)r_type)); }
static void addpltsym(Sym *s) { Sym *plt, *got, *rel; if(s->plt >= 0) return; adddynsym(s); if(iself) { plt = lookup(".plt", 0); got = lookup(".got.plt", 0); rel = lookup(".rel.plt", 0); if(plt->size == 0) elfsetupplt(); // jmpq *got+size adduint8(plt, 0xff); adduint8(plt, 0x25); addaddrplus(plt, got, got->size); // add to got: pointer to current pos in plt addaddrplus(got, plt, plt->size); // pushl $x adduint8(plt, 0x68); adduint32(plt, rel->size); // jmp .plt adduint8(plt, 0xe9); adduint32(plt, -(plt->size+4)); // rel addaddrplus(rel, got, got->size-4); adduint32(rel, ELF32_R_INFO(s->dynid, R_386_JMP_SLOT)); s->plt = plt->size - 16; } else if(HEADTYPE == Hdarwin) { // Same laziness as in 6l. Sym *plt; plt = lookup(".plt", 0); addgotsym(s); adduint32(lookup(".linkedit.plt", 0), s->dynid); // jmpq *got+size(IP) s->plt = plt->size; adduint8(plt, 0xff); adduint8(plt, 0x25); addaddrplus(plt, lookup(".got", 0), s->got); } else { diag("addpltsym: unsupported binary format"); } }
int gelf_update_rel(Elf_Data *d, int ndx, GElf_Rel *dr) { int ec; Elf *e; Elf_Scn *scn; Elf32_Rel *rel32; Elf64_Rel *rel64; size_t msz; uint32_t sh_type; if (d == NULL || ndx < 0 || dr == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_REL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } msz = _libelf_msize(ELF_T_REL, ec, e->e_version); assert(msz > 0); if (msz * ndx >= d->d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (ec == ELFCLASS32) { rel32 = (Elf32_Rel *) d->d_buf + ndx; LIBELF_COPY_U32(rel32, dr, r_offset); if (ELF64_R_SYM(dr->r_info) > ELF32_R_SYM(~0UL) || ELF64_R_TYPE(dr->r_info) > ELF32_R_TYPE(~0U)) { LIBELF_SET_ERROR(RANGE, 0); return (0); } rel32->r_info = ELF32_R_INFO(ELF64_R_SYM(dr->r_info), ELF64_R_TYPE(dr->r_info)); } else { rel64 = (Elf64_Rel *) d->d_buf + ndx; *rel64 = *dr; } return (1); }
static void addRel32(elfull o,elfull a,elfull i,elfull r) { if (RELA) { struct Rela32Node *rn = mymalloc(sizeof(struct Rela32Node)); setval(be,rn->r.r_offset,4,o); setval(be,rn->r.r_addend,4,a); setval(be,rn->r.r_info,4,ELF32_R_INFO(i,r)); addtail(&relalist,&(rn->n)); } else { struct Rel32Node *rn = mymalloc(sizeof(struct Rel32Node)); setval(be,rn->r.r_offset,4,o); setval(be,rn->r.r_info,4,ELF32_R_INFO(i,r)); addtail(&relalist,&(rn->n)); } }
void cElfRelocationSection::changeRel(uint32 SrcSym, uint32 DstSym) { cArray<Elf32_Rel>::iterator curRel = this->m_rels.begin(); for(; curRel != this->m_rels.end(); ++curRel) { if ( ELF32_R_SYM((*curRel).r_info) == SrcSym ) { (*curRel).r_info = ELF32_R_INFO(DstSym, ELF32_R_TYPE((*curRel).r_info)); } } }
void add_entry( Elf64_Addr offset, Elf_Word symbol, unsigned char type, Elf_Sxword addend ) { Elf_Xword info; if ( elf_file.get_class() == ELFCLASS32 ) { info = ELF32_R_INFO( symbol, type ); } else { info = ELF64_R_INFO( symbol, type ); } add_entry( offset, info, addend ); }
void cElfRelocationSection::addRel(uint32 symId, uint32 symType, uint32 offset) { Elf32_Rel newRel; newRel.r_info = ELF32_R_INFO(symId, symType); newRel.r_offset = offset; this->m_rels += newRel; }
uv_err_t UVDElfRelocation::updateSymbolIndex(uint32_t symbolIndex) { /* if( symbolIndex >= 0x1000000 ) { return UV_DEBUG(UV_ERR_GENERAL); } */ m_relocation.r_info = ELF32_R_INFO(symbolIndex, ELF32_R_TYPE(m_relocation.r_info)); return UV_ERR_OK; }
void read_and_print_relocation_section(void * file, struct Secthdr * shptr) { uint32_t num_entries ; int i=0; struct relhdr *relptr; struct symtab *symptr; struct Secthdr * shptr_array; char * symbol_name_ptr; int type,symbol,sym_info ; uint32_t link = shptr->sh_link; //This Section gives the symbols information for current relocation section. struct Elf *elf; elf = (struct Elf * ) file; cprintf("Type is %d \n",shptr->sh_type); shptr_array = ( struct Secthdr * ) ( (char * ) file + elf->e_shoff) ; num_entries = shptr->sh_size/ shptr->sh_entsize ; symptr = (struct symtab *) ( (char*) file + shptr_array[link].sh_offset); relptr = (struct relhdr * ) ( (char * ) file + shptr->sh_offset) ; cprintf("SYMTAB5 name %d\n",symptr[5].st_name); cprintf("SYMTAB5 value %d\n",symptr[5].st_value); cprintf("SYMTAB5 sizre %d\n",symptr[5].st_size); cprintf("SYMTAB5 info %d\n",symptr[5].st_info); cprintf("SYMTAB5 other %d\n",symptr[5].st_other); cprintf("SYMTAB5 shnindx %d\n",symptr[5].st_shndx); cprintf("SYMTAB5 shnindxforcprintf %d\n",symptr[11].st_shndx); for(i=0;i<num_entries;i++) { symbol = ELF32_R_SYM(relptr[i].rel_info); type = ELF32_R_TYPE(relptr[i].rel_info); sym_info = ELF32_R_INFO(symbol,type); //find out the actual symbol name and its vaue recorded symbol table if( symptr[symbol].st_name != 0 ) { //get the symbol name from strtab @ 13 - Hardcoded symbol_name_ptr = get_symbol_name_ptr(file,symptr[symbol].st_name,13); //hardcode } else { //Check the shndx of this symtab entry int index2strtab = shptr_array[symptr[symbol].st_shndx].sh_name; symbol_name_ptr = get_symbol_name_ptr(file,index2strtab,11); //hardcode } cprintf("REL : %d , rel_offset %x , ym index %d type %d info %x value %x symbol name : %s\n",i,relptr[i].rel_offset,symbol,type,sym_info,symptr[symbol].st_value,symbol_name_ptr ); } }
uv_err_t UVDElfPCRelocation::updateRelocationTypeByBits(uint32_t nBits) { uint32_t relocationType = 0; switch( nBits ) { case 8: relocationType = R_386_PC8; break; case 16: relocationType = R_386_PC16; break; case 32: relocationType = R_386_PC32; break; default: printf_error("Invalid number of bits: %d\n", nBits); return UV_DEBUG(UV_ERR_GENERAL); } m_relocation.r_info = ELF32_R_INFO(ELF32_R_SYM(m_relocation.r_info), relocationType); return UV_ERR_OK; }
/* patch pointer addition in vtop so that pointer dereferencing is also tested */ void gen_bounded_ptr_deref(void) { int func; int size, align; Elf32_Rel *rel; Sym *sym; size = 0; /* XXX: put that code in generic part of tcc */ if (!is_float(vtop->type.t)) { if (vtop->r & VT_LVAL_BYTE) size = 1; else if (vtop->r & VT_LVAL_SHORT) size = 2; } if (!size) size = type_size(&vtop->type, &align); switch(size) { case 1: func = TOK___bound_ptr_indir1; break; case 2: func = TOK___bound_ptr_indir2; break; case 4: func = TOK___bound_ptr_indir4; break; case 8: func = TOK___bound_ptr_indir8; break; case 12: func = TOK___bound_ptr_indir12; break; case 16: func = TOK___bound_ptr_indir16; break; default: error("unhandled size when derefencing bounded pointer"); func = 0; break; } /* patch relocation */ /* XXX: find a better solution ? */ rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.ul); sym = external_global_sym(func, &func_old_type, 0); if (!sym->c) put_extern_sym(sym, NULL, 0, 0); rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info)); }
static void addgotsym(Sym *s) { Sym *got, *rel; if(s->got >= 0) return; adddynsym(s); got = lookup(".got", 0); s->got = got->size; adduint32(got, 0); if(iself) { rel = lookup(".rel", 0); addaddrplus(rel, got, s->got); adduint32(rel, ELF32_R_INFO(s->dynid, R_386_GLOB_DAT)); } else if(HEADTYPE == Hdarwin) { adduint32(lookup(".linkedit.got", 0), s->dynid); } else { diag("addgotsym: unsupported binary format"); } }
uv_err_t UVDElfRelocation::applyRelocationsForWrite() { printf_elf_relocation_debug("relocation: applying relocation for write\n"); //The two r_info parts { UVDElfSymbol *symbol = NULL; UVDElfSymbolSectionHeaderEntry *sectionHeader = NULL; uint32_t symbolIndex = 0; uv_assert_err_ret(getElfSymbol(&symbol)); sectionHeader = symbol->m_symbolSectionHeader; uv_assert_ret(sectionHeader); uv_assert_err_ret(sectionHeader->getSymbolIndex(symbol, &symbolIndex)); printf_elf_relocation_debug("symbol: %s, index: %d\n", symbol->m_sName.c_str(), symbolIndex); //What does this comment mean? What is the real object? //Might help later to update the real object m_relocation.r_info = ELF32_R_INFO(symbolIndex, ELF32_R_TYPE(m_relocation.r_info)); } uv_assert_err_ret(updateRelocationTypeByBits(getSizeBits())); //r_offset { uint32_t elfSymbolFileOffset = 0; //uv_assert_err_ret(getFileOffset(&elfSymbolFileOffset)); //Absolute relocation is applied at the offset + local offset to make a full offset //FIXME: ...or not since it seems this is being set to 0 m_relocation.r_offset = elfSymbolFileOffset + m_offset; } ELF_RELOCATION_DEBUG(m_headerEntryRelocatableData.hexdump()); return UV_ERR_OK; }
void adddynrel(Sym *s, Reloc *r) { Sym *targ, *rel, *got; targ = r->sym; cursym = s; switch(r->type) { default: if(r->type >= 256) { diag("unexpected relocation type %d", r->type); return; } break; // Handle relocations found in ELF object files. case 256 + R_386_PC32: if(targ->type == SDYNIMPORT) diag("unexpected R_386_PC32 relocation for dynamic symbol %s", targ->name); if(targ->type == 0 || targ->type == SXREF) diag("unknown symbol %s in pcrel", targ->name); r->type = D_PCREL; r->add += 4; return; case 256 + R_386_PLT32: r->type = D_PCREL; r->add += 4; if(targ->type == SDYNIMPORT) { addpltsym(targ); r->sym = lookup(".plt", 0); r->add += targ->plt; } return; case 256 + R_386_GOT32: if(targ->type != SDYNIMPORT) { // have symbol // turn MOVL of GOT entry into LEAL of symbol itself if(r->off < 2 || s->p[r->off-2] != 0x8b) { diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name); return; } s->p[r->off-2] = 0x8d; r->type = D_GOTOFF; return; } addgotsym(targ); r->type = D_CONST; // write r->add during relocsym r->sym = S; r->add += targ->got; return; case 256 + R_386_GOTOFF: r->type = D_GOTOFF; return; case 256 + R_386_GOTPC: r->type = D_PCREL; r->sym = lookup(".got", 0); r->add += 4; return; case 256 + R_386_32: if(targ->type == SDYNIMPORT) diag("unexpected R_386_32 relocation for dynamic symbol %s", targ->name); r->type = D_ADDR; return; case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 0: r->type = D_ADDR; if(targ->type == SDYNIMPORT) diag("unexpected reloc for dynamic symbol %s", targ->name); return; case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 1: if(targ->type == SDYNIMPORT) { addpltsym(targ); r->sym = lookup(".plt", 0); r->add = targ->plt; r->type = D_PCREL; return; } r->type = D_PCREL; return; case 512 + MACHO_FAKE_GOTPCREL: if(targ->type != SDYNIMPORT) { // have symbol // turn MOVL of GOT entry into LEAL of symbol itself if(r->off < 2 || s->p[r->off-2] != 0x8b) { diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name); return; } s->p[r->off-2] = 0x8d; r->type = D_PCREL; return; } addgotsym(targ); r->sym = lookup(".got", 0); r->add += targ->got; r->type = D_PCREL; return; } // Handle references to ELF symbols from our own object files. if(targ->type != SDYNIMPORT) return; switch(r->type) { case D_PCREL: addpltsym(targ); r->sym = lookup(".plt", 0); r->add = targ->plt; return; case D_ADDR: if(s->type != SDATA) break; if(iself) { adddynsym(targ); rel = lookup(".rel", 0); addaddrplus(rel, s, r->off); adduint32(rel, ELF32_R_INFO(targ->dynid, R_386_32)); r->type = D_CONST; // write r->add during relocsym r->sym = S; return; } if(HEADTYPE == Hdarwin && s->size == PtrSize && r->off == 0) { // Mach-O relocations are a royal pain to lay out. // They use a compact stateful bytecode representation // that is too much bother to deal with. // Instead, interpret the C declaration // void *_Cvar_stderr = &stderr; // as making _Cvar_stderr the name of a GOT entry // for stderr. This is separate from the usual GOT entry, // just in case the C code assigns to the variable, // and of course it only works for single pointers, // but we only need to support cgo and that's all it needs. adddynsym(targ); got = lookup(".got", 0); s->type = got->type | SSUB; s->outer = got; s->sub = got->sub; got->sub = s; s->value = got->size; adduint32(got, 0); adduint32(lookup(".linkedit.got", 0), targ->dynid); r->type = 256; // ignore during relocsym return; } break; } cursym = s; diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ->name, r->type, targ->type); }
//------------------------------------------------------------------- static void avr_create_new_rela_text_data(Elf_Data* nedata, Elf* elf, Elf32_Shdr *nshdr, uint32_t startaddr, bblklist_t* blist) { Elf_Scn* symscn; Elf32_Shdr* symshdr; Elf_Data *symdata; Elf32_Sym* sym; Elf32_Rela *nerela; int numRecs, numSyms, i, textNdx; symscn = getELFSymbolTableScn(elf); symshdr = elf32_getshdr(symscn); symdata = NULL; symdata = elf_getdata(symscn, symdata); sym = (Elf32_Sym*)symdata->d_buf; numSyms = symdata->d_size/symshdr->sh_entsize; textNdx = -1; DEBUG("Locating symbol table index for .text\n"); DEBUG("Rela Info: %d\n", (int)nshdr->sh_info); for (i = 0; i < numSyms; i++){ #ifdef DBGMODE ElfPrintSymbol(sym); DEBUG("\n"); #endif if ((sym->st_shndx == nshdr->sh_info) && (ELF32_ST_TYPE(sym->st_info) == STT_SECTION)){ textNdx = i; break; } sym++; } if (-1 == textNdx){ fprintf(stderr, "avr_create_new_rela_text_data: Could not locate .text section symbol\n"); exit(EXIT_FAILURE); } DEBUG(".text symbol table index: %d\n", textNdx); DEBUG("Fixing .rela.text entries ...\n"); nerela = (Elf32_Rela*)nedata->d_buf; numRecs = nedata->d_size/nshdr->sh_entsize; for (i = 0; i < numRecs; i++){ // Change offset field for all records .rela.text // Change addend if symbol field is .text if (nerela->r_offset > startaddr){ uint32_t oldaddr = nerela->r_offset; nerela->r_offset = find_updated_address(blist, oldaddr); DEBUG("Entry: %d Old Offset: 0x%x New Offset: 0x%x\n", i, (int)oldaddr, (int)nerela->r_offset); } if (ELF32_R_SYM(nerela->r_info) == textNdx){ if (nerela->r_addend > startaddr){ uint32_t old_addend = nerela->r_addend; nerela->r_addend = find_updated_address(blist, old_addend); // If relocation type is of R_AVR_CALL, then modify addend. // The addend should point to two words before the actual function // so as to invoke the call to the safe stack save function if (ELF32_R_TYPE(nerela->r_info) == R_AVR_CALL){ // Check if it is indeed a call instruction before changing the addend avr_instr_t instr; instr = find_instr_at_new_addr(blist, nerela->r_offset); if ((instr.rawVal & OP_TYPE10_MASK) == OP_CALL){ nerela->r_addend -= sizeof(avr_instr_t) * 2; DEBUG("Internal call target -> Modify addend to include safe stack.\n"); } else DEBUG("Internal jmp target -> No further modifications.\n"); } if (ELF32_R_TYPE(nerela->r_info) == R_AVR_13_PCREL){ // Check if it is indeed a call instruction before changing the addend avr_instr_t instr; instr = find_instr_at_new_addr(blist, nerela->r_offset); if ((instr.rawVal & OP_TYPE17_MASK) == OP_RCALL){ nerela->r_addend -= sizeof(avr_instr_t) * 2; DEBUG("Internal rcall target -> Modify addend to include safe stack.\n"); } else DEBUG("Internal rjmp target -> No further modifications.\n"); } DEBUG("Entry: %d Old Addend: 0x%x New Addend: 0x%x\n", i, (int)old_addend, nerela->r_addend); } } nerela++; } // Add new relocation records basicblk_t* cblk; Elf32_Rela *newrela; int numnewrecs; int newcalljmpflag; newrela = (Elf32_Rela*)malloc(sizeof(Elf32_Rela) * MAX_NEW_RELA); numnewrecs = 0; for (cblk = blist->blk_st; cblk != NULL; cblk = (basicblk_t*)cblk->link.next){ avr_instr_t* instr; int numinstr; uint32_t thisinstroffset; numinstr = cblk->newsize/sizeof(avr_instr_t); if (NULL == cblk->branch) continue; if ((cblk->flag & TWO_WORD_INSTR_FLAG) == 0) continue; instr = &(cblk->newinstr[numinstr - 2]); thisinstroffset = cblk->newaddr + cblk->newsize - 2 * sizeof(avr_instr_t); if (((instr->rawVal & OP_TYPE10_MASK) != OP_JMP) && ((instr->rawVal & OP_TYPE10_MASK) != OP_CALL)){ fprintf(stderr, "avr_create_new_rela_text_data: Basic block flag corrupted\n"); exit(EXIT_FAILURE); } // Check if there is a rela record with the current offset nerela = (Elf32_Rela*)nedata->d_buf; newcalljmpflag = 1; for (i = 0; i < numRecs; i++){ if (nerela->r_offset == thisinstroffset){ DEBUG("Curr New Offset: 0x%d -- Found\n", thisinstroffset); newcalljmpflag = 0; break; } nerela++; } if (newcalljmpflag == 0) continue; // Add a new relocation records // r_added = .text + branch target address newrela[numnewrecs].r_info = ELF32_R_INFO(textNdx, R_AVR_CALL); newrela[numnewrecs].r_offset = thisinstroffset; newrela[numnewrecs].r_addend = (cblk->branch)->newaddr; DEBUG("New Rela: Offset 0x%x Addend 0x%x\n", newrela[numnewrecs].r_offset, newrela[numnewrecs].r_addend); numnewrecs++; } DEBUG("New Rela Recs: %d\n", numnewrecs); uint8_t *new_d_buf, *ptr_d_buf; new_d_buf = (uint8_t*)malloc(numnewrecs * sizeof(Elf32_Rela) + nedata->d_size); memcpy(new_d_buf, nedata->d_buf, nedata->d_size); ptr_d_buf = new_d_buf + nedata->d_size; memcpy(ptr_d_buf, newrela, sizeof(Elf32_Rela)*numnewrecs); free(nedata->d_buf); free(newrela); nedata->d_buf = new_d_buf; nedata->d_size += sizeof(Elf32_Rela) * numnewrecs; return; }
Elf_Scn *symtab_write_elf(Elf *e, struct sect * sects, struct buffer *strtab_buf, struct buffer *shstrtab_buf) { unsigned i, k; struct sym_info *sym; Elf32_Sym esym; Elf_Scn *scn, *relscn, *tmpscn; Elf_Data *data, *reldata; Elf32_Shdr *shdr, *relshdr; struct buffer buf; struct buffer *relbuf; struct sect *s; buffer_init(&buf); esym.st_name = 0; esym.st_value = 0; esym.st_size = 0; esym.st_info = 0; esym.st_other = 0; esym.st_shndx = 0; buffer_writemem(&buf, &esym, sizeof(esym)); relbuf = malloc(0); for (s = sects, k = 0; s != NULL; s = s->next, k++) { relbuf = realloc(relbuf, (k+1)*sizeof(struct buffer)); buffer_init(&relbuf[k]); } for (i = 0; i < SYMTAB_SIZE; i++) { for (sym = symtab[i]; sym != NULL; sym = sym->next) { if (sym->symbol[0] != '.' || sym->relocs != NULL) { struct reloc_info size; int type = STT_NOTYPE; int bind = STB_LOCAL; if (!sym->defined || sym->bind == SYM_BIND_GLOBAL) { bind = STB_GLOBAL; } esym.st_name = strtab_buf->pos; buffer_writestr(strtab_buf, sym->symbol); esym.st_value = sym->addr; size = expr_evaluate(sym->size); if (size.symbol != NULL) { eprintf("Cannot relocate symbol size"); exit(EXIT_FAILURE); } esym.st_size = size.intval; if (strcmp(sym->type, "@function") == 0) type = STT_FUNC; if (strcmp(sym->type, "@object") == 0) type = STT_OBJECT; esym.st_info = ELF32_ST_INFO(bind, type); esym.st_other = ELF32_ST_VISIBILITY(STV_DEFAULT); tmpscn = section_find(e, sym->section, shstrtab_buf); if (tmpscn == NULL && sym->section != NULL) tmpscn = section_find(e, pile_name(pile_match(sym->section)), shstrtab_buf); esym.st_shndx = tmpscn != NULL ? elf_ndxscn(tmpscn) : 0; if (sym->relocs != NULL) { struct sym_reloc_info *r; for (r = sym->relocs; r != NULL; r = r->next) { Elf32_Rela rel; rel.r_offset = r->addr; rel.r_info = ELF32_R_INFO(buf.pos/sizeof(esym), r->type); rel.r_addend = r->addend; for (s = sects, k = 0; s != NULL; s = s->next, k++) { if (strcmp(s->name, r->sect) == 0) { buffer_writemem(&relbuf[k], &rel, sizeof(rel)); } } } } buffer_writemem(&buf, &esym, sizeof(esym)); } } } scn = xelf_newscn(e); shdr = xelf32_getshdr(scn); shdr->sh_name = shstrtab_buf->pos; buffer_writestr(shstrtab_buf, ".symtab"); shdr->sh_type = SHT_SYMTAB; shdr->sh_flags = 0; data = xelf_newdata(scn); data->d_align = 4; data->d_off = 0; data->d_type = ELF_T_SYM; data->d_version = EV_CURRENT; data->d_buf = buf.data; data->d_size = buf.pos; for (s = sects, k = 0; s != NULL; s = s->next, k++) { if (relbuf[k].pos > 0) { char *relname; relscn = xelf_newscn(e); relshdr = xelf32_getshdr(relscn); relshdr->sh_name = shstrtab_buf->pos; relname = malloc(strlen(s->name)+6); strcpy(relname, ".rela"); strcat(relname, s->name); buffer_writestr(shstrtab_buf, relname); relshdr->sh_type = SHT_RELA; shdr->sh_flags = 0; reldata = xelf_newdata(relscn); reldata->d_align = 4; reldata->d_off = 0; reldata->d_type = ELF_T_RELA; reldata->d_version = EV_CURRENT; reldata->d_buf = relbuf[k].data; reldata->d_size = relbuf[k].pos; relshdr->sh_link = elf_ndxscn(scn); tmpscn = section_find(e, s->name, shstrtab_buf); relshdr->sh_info = tmpscn != NULL ? elf_ndxscn(tmpscn) : 0; } } return scn; }
void RelocationAddend32::setSymbolInfo(uint32_t sym){ entry.r_info = ELF32_R_INFO(sym, getType()); }
int patch_relocation_section(unsigned int fd, unsigned int size, int rel_type, hash_node **hashtable, unsigned int match_endian) { unsigned int i; unsigned int entry_size = (rel_type == DT_REL) ? sizeof(Elf32_Rel) : sizeof(Elf32_Rela); unsigned int total = size / entry_size; if (rel_type == DT_REL) /* rel relocation type*/ { Elf32_Rel rel; unsigned int new_code, old_code, sym; for (i = 0; i < total; i++) { /* Read it. */ if (read(fd, &rel, sizeof(rel)) != sizeof(rel)) { fprintf(stderr, "Couldn't read REL relocation number %d.\n", i); return ACRELCONVERT_FUNC_ERROR; } /* Patch it. */ old_code = ELF32_R_TYPE(convert_endian(4, rel.r_info, match_endian)); sym = ELF32_R_SYM(convert_endian(4, rel.r_info, match_endian)); if (hash_get_value(hashtable, old_code, &new_code) == ACRELCONVERT_FUNC_ERROR) { fprintf(stderr, "Error: unrecognized relocation code 0x%X (%d), at relocation number %d\n", old_code, old_code, i); return ACRELCONVERT_FUNC_ERROR; } rel.r_info = convert_endian(4, ELF32_R_INFO(sym, new_code), match_endian); /* Write it back, patched. */ lseek(fd, - sizeof(rel), SEEK_CUR); if (write(fd, &rel, sizeof(rel)) != sizeof(rel)) { fprintf(stderr, "Error: couldn't write REL relocation number %d.\n", i); return ACRELCONVERT_FUNC_ERROR; } } } else /* rela relocation type */ { Elf32_Rela rela; unsigned int new_code, old_code, sym; for (i = 0; i < total; i++) { /* Read it. */ if (read(fd, &rela, sizeof(rela)) != sizeof(rela)) { fprintf(stderr, "Couldn't read RELA relocation number %d.\n", i); return ACRELCONVERT_FUNC_ERROR; } /* Patch it. */ old_code = ELF32_R_TYPE(convert_endian(4, rela.r_info, match_endian)); sym = ELF32_R_SYM(convert_endian(4, rela.r_info, match_endian)); if (hash_get_value(hashtable, old_code, &new_code) == ACRELCONVERT_FUNC_ERROR) { fprintf(stderr, "Error: unrecognized relocation code 0x%X (%d), at relocation number %d\n", old_code, old_code, i); return ACRELCONVERT_FUNC_ERROR; } rela.r_info = convert_endian(4, ELF32_R_INFO(sym, new_code), match_endian); /* Write it back, patched. */ lseek(fd, - sizeof(rela), SEEK_CUR); if (write(fd, &rela, sizeof(rela)) != sizeof(rela)) { fprintf(stderr, "Error: couldn't write RELA relocation number %d.\n", i); return ACRELCONVERT_FUNC_ERROR; } } } return ACRELCONVERT_FUNC_OK; }