Esempio n. 1
0
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);
    }
}
Esempio n. 2
0
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));
}
Esempio n. 3
0
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");
	}
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
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));
  }
}
Esempio n. 6
0
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));
		}
	}
}
Esempio n. 7
0
	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 );
	}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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 );

       }
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
/* 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));
}
Esempio n. 13
0
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");
	}
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
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);
}
Esempio n. 16
0
//-------------------------------------------------------------------
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;
}
Esempio n. 17
0
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());    
}
Esempio n. 19
0
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;
}