Exemple #1
0
int  xreloc_relocate( xreloc xr ) {
  table *t = (table *) xr;
  int loc;
  int word;
  int mask;
  int err = 0;
  symbol *sym;
  symbol *rel = NULL;
  reloc *r;

  rel = findsym( t, REL_NAME );
  rel->flags = FLAG_RELOCAT | FLAG_GLOBAL;
  rel->loc = 0;

  for( sym = t->syms; sym; sym = sym->next ) {
    if( sym->flags & FLAG_GLOBAL ) { /* symbols to be written to symbol table */
      continue;
    } else if( sym->flags & FLAG_RELOCAT ) { /* symbols need to be relocated */
      sym->flags |= FLAG_WRITTEN;
      for( r = sym->relocs; r; r = r->next ) { 
        add_reloc( t, rel, r->loc, r->size, XRELOC_ABSOLUTE );

        word = GETWORD( t->mem, r->loc );
        mask = ( 1 << r->size ) - 1;
        loc = ( word & mask ) + sym->loc;
        if( loc & ~mask ) {
          fprintf( t->err, "error: relocation out of range for symbol '%s'\n", 
                   sym->name );
          err = 1;
        }
        word = ( word & ~mask ) | ( loc & mask );
        t->mem[r->loc] = word >> 8;
        t->mem[r->loc + 1] = word;
      }
    } else if( sym->loc != INV_ADDR ) { /* symbol is defined */
Exemple #2
0
int xreloc_reloc( xreloc xr, int loc, int size, char *name, 
                  unsigned char flags ) {
  table *t = (table *) xr;
  symbol *sym;

  assert( t );
  assert( name );

  if( loc == INV_ADDR ) {
    fprintf( stderr, "error: invalid address '%x', object may be too big\n", 
                     INV_ADDR );
    return 0;
  }

  sym = findsym( t, name );
  assert( sym );

  add_reloc( t, sym, loc, size, flags );
  return 1;
}
Exemple #3
0
void write_elf(FILE *outfile, Elf *elf) {
    add_symtab(elf);
    add_reloc(elf);
    add_shstrtab(elf);

    // Section header
    String *sh = make_string();
    for (int i = 0; i < 64; i++)
        o1(sh, 0); // NULL section header

    // Body
    String *content = make_string();
    for (int i = 0; i < LIST_LEN(elf->sections); i++) {
        write_section(sh, content, LIST_REF(elf->sections, i), 64);
    }
    align(content, 16);

    // ELF header
    String *eh = make_string();
    int numsect = LIST_LEN(elf->sections) + 1;
    out(eh, elf_ident, sizeof(elf_ident));
    o2(eh, 1);  // e_type = ET_REL
    o2(eh, 62); // e_machine = EM_X86_64
    o4(eh, 1);  // e_version = EV_CURRENT
    o8(eh, 0);  // e_entry
    o8(eh, 0);  // e_phoff
    o8(eh, STRING_LEN(content) + 64);  // e_shoff;
    o4(eh, 0);  // e_flags
    o2(eh, 64); // e_ehsize
    o2(eh, 0);  // e_phentsize
    o2(eh, 0);  // e_phnum
    o2(eh, 64); // e_shentsize
    o2(eh, numsect);  // e_shnum
    o2(eh, elf->shnum);  // e_shstrndx

    fwrite(STRING_BODY(eh), STRING_LEN(eh), 1, outfile);
    fwrite(STRING_BODY(content), STRING_LEN(content), 1, outfile);
    fwrite(STRING_BODY(sh), STRING_LEN(sh), 1, outfile);
    fclose(outfile);
}
Exemple #4
0
int  xreloc_load_table( xreloc xr, int size, int base ) {
  table *t = (table *) xr;
  int i, ent, loc;
  short chksum = 0;
  int code_size = 0;
  symbol *sym;
  char buf[10];

  assert( t );
  assert( size >= 0 );
  assert( base >= 0 );
  assert( ( base + size ) <= XIS_MEM_SIZE );

  if( size & 1 ) { /* Cannot have a valid table because size is odd */
    return -1;
  }

  for( i = 0; i < size; i += 2 ) {
    chksum += GETWORD( t->mem, i + base );
  }

  if( chksum ) { /* chksum failed, no table */
    return -1;
  }
 
  i = GETWORD( t->mem, size + base - 4 );
  if( i != XIS_VERSION ) {
    fprintf( t->err, "error: unknown version %x\n", i );
    return 0;
  }

  ent = GETWORD( t->mem, size + base - 6 ) + base + 1;  /* 1 is the padding */
  code_size = GETWORD( t->mem, size + base - 6 );

  while( t->mem[ent] && ( ent < ( base + size ) ) ) {
    if( !strcmp( REL_NAME, (char *)&t->mem[ent] ) ) {
      sprintf( buf, "%s%x", REL_NAME, t->rel_cnt );
      t->rel_cnt++;
      sym = findsym( t, buf );
      sym->flags = FLAG_RELOCAT;
    } else {
      sym = findsym( t, (char *) &t->mem[ent] );
    }
    ent += strlen( (char *) &t->mem[ent] ) + 1;

    loc = GETWORD( t->mem, ent );
    ent += 2;
    if( loc != INV_ADDR ) {
      if( sym->loc == INV_ADDR ) {
        sym->loc = loc + base;
      } else {
        fprintf( t->err, "error: Multiple instances of symbol '%s'\n", 
                 sym->name );
        code_size = 0;
      }
    } 

    for( loc = GETWORD( t->mem, ent ); loc != INV_ADDR; 
         loc = GETWORD( t->mem, ent ) ) {
      ent += 2;
      i = t->mem[ent++] & 0xff;
      add_reloc( t, sym, loc + base, i, t->mem[ent++] );
    }
    ent += 2;
  }

  return code_size;
}