示例#1
0
 eresi_Addr elfops_add(elf_bf_exec_t *ee, eresi_Addr delta)
 {
   elf_bf_link_map_t *l = &(ee->ee_lm);

   eresi_Addr start = l->lm_next_reloc;

   //we assume that correct value is in scratch space, just do addition
   set_next_reloc(l, R_X86_64_64, symtab_get_index(ee->ee_tape_ptr),
                  symtab_get_value_addr(ee->ee_tape_ptr), delta);

   eresi_Addr setupi, copyi;
   elf_bf_Rela setup, copy;

   //update tape
   setupi = set_next_reloc(l, 0, 0, 0, 0);

   //copy new value back to tape
   copyi = set_next_reloc(l, R_X86_64_COPY, symtab_get_index(ee->ee_tape_copy),
                            0, 0);

   //go back at actually setup first entry
   reloc_get_reloc_entry(l, setupi, &setup);
   reloc_get_reloc_entry(l, copyi, &copy);
   //setup next entry so it knows where tape pointer is
   reloc_set_rela(&setup, R_X86_64_64, symtab_get_index(ee->ee_ptr_tape_ptr),
                  reloc_get_offset_addr(&copy), 0);
  return l->lm_next_reloc - start;
}
示例#2
0
eresi_Addr set_next_reloc(elf_bf_link_map_t *l, Elf64_Word type, Elf64_Word sym, Elf64_Addr off, Elf64_Addr val)
{
  if(l->lm_allocated) {
    elf_bf_Rela r;
    reloc_get_reloc_entry(l, l->lm_next_reloc, &r);
    reloc_set_rela(&r, type, sym, off, val);
  } //otherwise just count
  l->lm_next_reloc++;
  return l->lm_next_reloc - 1;
}
示例#3
0
eresi_Addr elfops_branch_start(elf_bf_exec_t *ee)
{

  elf_bf_link_map_t *l = &(ee->ee_lm);
  eresi_Addr start = l->lm_next_reloc;

  elfops_prepare_branch(ee);


  eresi_Addr firsti;
  elf_bf_Rela first, next;

  //setup relocation entry that fixes dt_rela to jump past unconditional branch
  //we don't know address of next yet, so don't actually set it yet
  firsti = set_next_reloc(l, 0, 0, 0, 0);

  //setup relocation entry that fixes dt_relasz assuming unconditional branch
  set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_relasz, ee->ee_dt_relasz_value - (l->lm_next_reloc*sizeof(Elf64_Rela)));

  //sets symbol's link addr to (value on tape)
  set_next_reloc(l, R_X86_64_COPY, symtab_get_index(ee->ee_tape_copy),
                 symtab_get_link_addr(ee->ee_lm.lm_ifunc), 0);

  //sets end to zero or ifunc, depending on link value of sym1 set earlier
  set_next_reloc(l, R_X86_64_64, symtab_get_index(ee->ee_lm.lm_ifunc),
                 ee->ee_reloc_end,0);

  //unconditional branch past ] (if tape is zero)
  //update dt_rela (addend to be filled in once ] is known)
  set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_rela, 0);

  //update dt_relasz (addend to be filled in once ] is known)
  set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_relasz, 0);

  //set end to zero to force immediate branch
  set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_reloc_end, 0);

  //fix first entry to it points to last entry
  reloc_get_reloc_entry(l, firsti, &first);
  reloc_get_reloc_entry(l, l->lm_next_reloc, &next);
  reloc_set_rela(&first, R_X86_64_RELATIVE, 0, ee->ee_dt_rela,
                 reloc_get_addr(&next));

  return l->lm_next_reloc - start;
}
示例#4
0
eresi_Addr elfops_exit(elf_bf_exec_t *ee)
{
  eresi_Addr start;
  elf_bf_link_map_t *l = &(ee->ee_lm);
  start = l->lm_next_reloc;

  //this will end up causing the loader to divide by zero
  //if (l->lm_allocated) {
  //  reloc_set_rela(&r0, R_X86_64_TLSDESC, 0, 0, 0);
  //  l->lm_next_reloc = index;
  //}

  // force a branch to run original relocation entrires

  // restore PLT stuff
  set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_jmprel, ee->ee_dt_jmprel_value);
  set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_pltrelsz, ee->ee_dt_pltrelsz_value);

  elfops_prepare_branch(ee);


  //restore  RELA to point to entry after branch
  eresi_Addr relai, bucketi;
  elf_bf_Rela rela, bucket;

  //don't know all the information we need to set in this yet
  relai = set_next_reloc(l, 0, 0, 0, 0);

  //fix RELACOUNT accordingly
  // should probably calculate the 6
  set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_relasz,
                 ee->ee_relasz_orig + 6*sizeof(Elf64_Rela));

  //force immediate branch so that we finally process PLT entries
  set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_reloc_end, 0);

  // restore l_buckets
  bucketi = set_next_reloc(l, R_X86_64_RELATIVE, 0, get_l_buckets(l->lm_l_s),
                 ee->ee_dt_gnu_hash);

  // now go back at steup relai
  reloc_get_reloc_entry(l, relai, &rela);
  reloc_get_reloc_entry(l, bucketi, &bucket);
  reloc_set_rela(&rela, R_X86_64_RELATIVE, 0, ee->ee_dt_rela,
                 reloc_get_addr(&bucket));

  //restore l->libname->next
  set_next_reloc(l, R_X86_64_RELATIVE, 0, get_l_libname_next(l->lm_l_s), 0);

  //restore l_direct_opencount
  set_next_reloc(l, R_X86_64_RELATIVE, 0, get_l_direct_opencount(l->lm_l_s), 1);

  //restore l_prev
  set_next_reloc(l, R_X86_64_RELATIVE, 0, get_l_prev(l->lm_l_s), 0);

  //restore symtable size to original value TODO
  //reloc_set_rela(&r, R_X86_64_RELATIVE, 0, 0, 0);

  //restore  RELA to point to original dynrel
  set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_rela,ee->ee_rela_orig);

  //restore RELACOUNT or whatever to original value
  set_next_reloc(l, R_X86_64_RELATIVE, 0, ee->ee_dt_relasz, ee->ee_relasz_orig);

  return l->lm_next_reloc - start;
}