int module_frob_arch_sections(Elf32_Ehdr *hdr,
			      Elf32_Shdr *sechdrs,
			      char *secstrings,
			      struct module *me)
{
	unsigned int i;

	/* Find .plt and .init.plt sections */
	for (i = 0; i < hdr->e_shnum; i++) {
		if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0)
			me->arch.init_plt_section = i;
		else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0)
			me->arch.core_plt_section = i;
	}
	if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
		printk("Module doesn't contain .plt or .init.plt sections.\n");
		return -ENOEXEC;
	}

	/* Override their sizes */
	sechdrs[me->arch.core_plt_section].sh_size
		= get_plt_size(hdr, sechdrs, secstrings, 0);
	sechdrs[me->arch.init_plt_section].sh_size
		= get_plt_size(hdr, sechdrs, secstrings, 1);
	return 0;
}
Example #2
0
addr_t get_plt_by_entry_call( asmelf_t * aelf )
{
   /* XXX: only works if the first call of the entrypoint is 
    * to a plt function
    */

   char * start;
   addr_t start_addr;

   Elf32_Ehdr * ehdr;
   if( ! aelf || ! aelf->elf )
      error_ret("null arg", -1 );
   
   if( aelf->plt )
      return( aelf->plt );

   if( ! ( ehdr = get_ehdr( aelf->elf ) ) )
      error_ret("can't get ehdr",-1);

   start_addr = ehdr->e_entry;

   if( ! ( start = data_at_addr( aelf->elf , start_addr ) ) )
      error_ret("can't entry point get data", -1 );

   /* 1: get our first call */

   offset_t  offset = 0;
   size_t nread;
   x86_insn_t insn;
   addr_t dst;
   addr_t pltaddr;
   do
   {
      nread=x86_disasm( start , 36+offset , start_addr , offset , &insn );
      if( nread <= 0 )
         error_ret("can't disassemble",-1);
      offset += nread;
      /* found our first plt call */
      if( insn.type == insn_call ){
         dst = op_resolve( &insn.operands[op_dest] , &insn );
         break;
      }
   } while( offset < 256 );

   if( offset >= 256 )
      error_ret("can't find call",-1);

   if( crunch_plt_entry( aelf , dst, 0 , &pltaddr , 0 ) < 0  ) 
      error_ret("can't get plt from plt code", -1 );
   
   if( get_plt_size( aelf ) < 0 )
      error_ret("can't get size",-1);

   return(( aelf->plt = pltaddr ));
}