Example #1
0
File: pe.c Project: HarryR/sanos
static int pe_check_symbols(struct pe_info *pe) {
  Elf32_Sym *sym;
  int sym_index, sym_end;
  int ret = 0;

  pe_align_section(text_section, 8);

  sym_end = symtab_section->data_offset / sizeof(Elf32_Sym);
  for (sym_index = 1; sym_index < sym_end; ++sym_index) {
    sym = (Elf32_Sym *) symtab_section->data + sym_index;
    if (sym->st_shndx == SHN_UNDEF) {
      const char *name = symtab_section->link->data + sym->st_name;
      unsigned type = ELF32_ST_TYPE(sym->st_info);
      int imp_sym = pe_find_import(pe->s1, name);
      struct import_symbol *is;

      if (imp_sym == 0) goto not_found;
      is = pe_add_import(pe, imp_sym);
      if (!is) goto not_found;

      if (type == STT_FUNC) {
        unsigned long offset = is->thk_offset;
        if (offset) {
          // Got aliased symbol, like stricmp and _stricmp
        } else {
          char buffer[100];

          offset = text_section->data_offset;
          // Add the 'jmp IAT[x]' instruction
          *(WORD *) section_ptr_add(text_section, 8) = 0x25FF;

          // Add a helper symbol, will be patched later in pe_build_imports
          sprintf(buffer, "IAT.%s", name);
          is->iat_index = put_elf_sym(symtab_section, 0, sizeof(DWORD),
                                      ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
                                      0, SHN_UNDEF, buffer);
          put_elf_reloc(symtab_section, text_section, offset + 2, R_386_32, is->iat_index);
          is->thk_offset = offset;
        }

        // tcc_realloc might have altered sym's address
        sym = (Elf32_Sym *) symtab_section->data + sym_index;

        // Patch the original symbol
        sym->st_value = offset;
        sym->st_shndx = text_section->sh_num;
        sym->st_other &= ~1; // Do not export
        continue;
      }

      if (type == STT_OBJECT) { 
        if (is->iat_index == 0) {
          // Original symbol will be patched later in pe_build_imports
          is->iat_index = sym_index;
          continue;
        }
      }

    not_found:
      error_noabort("undefined symbol '%s'", name);
      ret = 1;
    } else if (pe->s1->rdynamic && ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
      // If -rdynamic option, then export all non local symbols
      sym->st_other |= 1;
    }
  }
  return ret;
}
Example #2
0
File: pe.c Project: HarryR/sanos
static void pe_build_imports(struct pe_info *pe) {
  int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i;
  DWORD rva_base = pe->thunk->sh_addr - pe->imagebase;
  int ndlls = pe->imp_count;

  for (sym_cnt = i = 0; i < ndlls; ++i) {
    sym_cnt += pe->imp_info[i]->sym_count;
  }
  if (sym_cnt == 0) return;

  pe_align_section(pe->thunk, 16);

  pe->imp_offs = dll_ptr = pe->thunk->data_offset;
  pe->imp_size = (ndlls + 1) * sizeof(struct pe_import_header);
  pe->iat_offs = dll_ptr + pe->imp_size;
  pe->iat_size = (sym_cnt + ndlls) * sizeof(DWORD);
  section_ptr_add(pe->thunk, pe->imp_size + 2 * pe->iat_size);

  thk_ptr = pe->iat_offs;
  ent_ptr = pe->iat_offs + pe->iat_size;

  for (i = 0; i < pe->imp_count; ++i) {
    struct pe_import_header *hdr;
    int k, n, v;
    struct pe_import_info *p = pe->imp_info[i];
    const char *name = pe->s1->loaded_dlls[p->dll_index - 1]->name;

    // Put the DLL name into the import header
    v = put_elf_str(pe->thunk, name);

    hdr = (struct pe_import_header *) (pe->thunk->data + dll_ptr);
    hdr->first_thunk = thk_ptr + rva_base;
    hdr->first_entry = ent_ptr + rva_base;
    hdr->lib_name_offset = v + rva_base;

    for (k = 0, n = p->sym_count; k <= n; ++k) {
      if (k < n) {
        DWORD iat_index = p->symbols[k]->iat_index;
        int sym_index = p->symbols[k]->sym_index;
        Elf32_Sym *imp_sym = (Elf32_Sym *) pe->s1->dynsymtab_section->data + sym_index;
        Elf32_Sym *org_sym = (Elf32_Sym *) symtab_section->data + iat_index;
        const char *name = pe->s1->dynsymtab_section->link->data + imp_sym->st_name;

        org_sym->st_value = thk_ptr;
        org_sym->st_shndx = pe->thunk->sh_num;
        v = pe->thunk->data_offset + rva_base;
        *(WORD *) section_ptr_add(pe->thunk, sizeof(WORD)) = imp_sym->st_other; // Hint
        put_elf_str(pe->thunk, name);
      } else {
        v = 0; // Last entry is zero
      }
      *(DWORD *)(pe->thunk->data + thk_ptr) = v;
      *(DWORD *)(pe->thunk->data + ent_ptr) = v;
      thk_ptr += sizeof(DWORD);
      ent_ptr += sizeof(DWORD);
    }
    dll_ptr += sizeof(struct pe_import_header);
    dynarray_reset(&p->symbols, &p->sym_count);
  }
  dynarray_reset(&pe->imp_info, &pe->imp_count);
}
Example #3
0
File: pe.c Project: HarryR/sanos
static void pe_build_exports(struct pe_info *pe) {
  Elf32_Sym *sym;
  int sym_index, sym_end;
  DWORD rva_base, func_o, name_o, ord_o, str_o;
  struct pe_export_header *hdr;
  int sym_count, n, ord, *sorted, *sp;

  FILE *op;
  char buf[260];
  const char *dllname;
  const char *name;

  rva_base = pe->thunk->sh_addr - pe->imagebase;
  sym_count = 0;
  n = 1;
  sorted = NULL;
  op = NULL;

  sym_end = symtab_section->data_offset / sizeof(Elf32_Sym);
  for (sym_index = 1; sym_index < sym_end; ++sym_index) {
    sym = (Elf32_Sym *) symtab_section->data + sym_index;
    name = symtab_section->link->data + sym->st_name;
    // Only export symbols from actually written sections
    if ((sym->st_other & 1) && pe->s1->sections[sym->st_shndx]->sh_addr) {
      dynarray_add((void ***) &sorted, &sym_count, (void *) n);
      dynarray_add((void ***) &sorted, &sym_count, (void *) name);
    }
    ++n;
  }

  if (sym_count == 0) return;
  sym_count /= 2;

  qsort(sorted, sym_count, 2 * sizeof(sorted[0]), sym_cmp);
  pe_align_section(pe->thunk, 16);
  dllname = tcc_basename(pe->filename);

  pe->exp_offs = pe->thunk->data_offset;
  func_o = pe->exp_offs + sizeof(struct pe_export_header);
  name_o = func_o + sym_count * sizeof(DWORD);
  ord_o = name_o + sym_count * sizeof(DWORD);
  str_o = ord_o + sym_count * sizeof(WORD);

  hdr = section_ptr_add(pe->thunk, str_o - pe->exp_offs);
  hdr->Characteristics = 0;
  hdr->Base = 1;
  hdr->NumberOfFunctions = sym_count;
  hdr->NumberOfNames = sym_count;
  hdr->AddressOfFunctions = func_o + rva_base;
  hdr->AddressOfNames = name_o + rva_base;
  hdr->AddressOfNameOrdinals = ord_o + rva_base;
  hdr->Name = str_o + rva_base;
  put_elf_str(pe->thunk, dllname);

  if (pe->def != NULL) {
    // Write exports to .def file
    op = fopen(pe->def, "w");
    if (op == NULL) {
      error_noabort("could not create '%s': %s", pe->def, strerror(errno));
    } else {
      fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
      if (verbose) {
        printf("<- %s (%d symbols)\n", buf, sym_count);
      }
    }
  }

  for (sp = sorted, ord = 0; ord < sym_count; ++ord, sp += 2) {
    sym_index = sp[0]; 
    name = (const char *) sp[1];

    // Insert actual address later in pe_relocate_rva
    put_elf_reloc(symtab_section, pe->thunk, func_o, R_386_RELATIVE, sym_index);
    *(DWORD *)(pe->thunk->data + name_o) = pe->thunk->data_offset + rva_base;
    *(WORD *)(pe->thunk->data + ord_o) = ord;
    put_elf_str(pe->thunk, name);
    func_o += sizeof(DWORD);
    name_o += sizeof(DWORD);
    ord_o += sizeof(WORD);

    if (op) fprintf(op, "%s@%d\n", name, ord);
  }
  pe->exp_size = pe->thunk->data_offset - pe->exp_offs;
  tcc_free(sorted);
  if (op) fclose(op);
}
Example #4
0
ST_FN void pe_build_exports(struct pe_info *pe)
{
    Elf32_Sym *sym;
    int sym_index, sym_end;
    DWORD rva_base, func_o, name_o, ord_o, str_o;
    struct pe_export_header *hdr;
    int sym_count, n, ord, *sorted, *sp;

    FILE *op;
    char buf[MAX_PATH];
    const char *dllname;
    const char *name;

    rva_base = pe->thunk->sh_addr - pe->imagebase;
    sym_count = 0, n = 1, sorted = NULL, op = NULL;

    sym_end = symtab_section->data_offset / sizeof(Elf32_Sym);
    for (sym_index = 1; sym_index < sym_end; ++sym_index) {
        sym = (Elf32_Sym*)symtab_section->data + sym_index;
        name = symtab_section->link->data + sym->st_name;
        if ((sym->st_other & 1)
            /* export only symbols from actually written sections */
            && pe->s1->sections[sym->st_shndx]->sh_addr) {
            dynarray_add((void***)&sorted, &sym_count, (void*)n);
            dynarray_add((void***)&sorted, &sym_count, (void*)name);
        }
        ++n;
#if 0
        if (sym->st_other & 1)
            printf("export: %s\n", name);
        if (sym->st_other & 2)
            printf("stdcall: %s\n", name);
#endif
    }

    if (0 == sym_count)
        return;
    sym_count /= 2;

    qsort (sorted, sym_count, 2 * sizeof sorted[0], sym_cmp);
    pe_align_section(pe->thunk, 16);
    dllname = tcc_basename(pe->filename);

    pe->exp_offs = pe->thunk->data_offset;
    func_o = pe->exp_offs + sizeof(struct pe_export_header);
    name_o = func_o + sym_count * sizeof (DWORD);
    ord_o = name_o + sym_count * sizeof (DWORD);
    str_o = ord_o + sym_count * sizeof(WORD);

    hdr = section_ptr_add(pe->thunk, str_o - pe->exp_offs);
    hdr->Characteristics        = 0;
    hdr->Base                   = 1;
    hdr->NumberOfFunctions      = sym_count;
    hdr->NumberOfNames          = sym_count;
    hdr->AddressOfFunctions     = func_o + rva_base;
    hdr->AddressOfNames         = name_o + rva_base;
    hdr->AddressOfNameOrdinals  = ord_o + rva_base;
    hdr->Name                   = str_o + rva_base;
    put_elf_str(pe->thunk, dllname);

#if 1
    /* automatically write exports to <output-filename>.def */
    strcpy(buf, pe->filename);
    strcpy(tcc_fileextension(buf), ".def");
    op = fopen(buf, "w");
    if (NULL == op) {
        error_noabort("could not create '%s': %s", buf, strerror(errno));
    } else {
        fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
        if (pe->s1->verbose)
            printf("<- %s (%d symbols)\n", buf, sym_count);
    }
#endif

    for (sp = sorted, ord = 0; ord < sym_count; ++ord, sp += 2)
    {
        sym_index = sp[0], name = (const char *)sp[1];
        /* insert actual address later in pe_relocate_rva */
        put_elf_reloc(symtab_section, pe->thunk,
            func_o, R_386_RELATIVE, sym_index);
        *(DWORD*)(pe->thunk->data + name_o)
            = pe->thunk->data_offset + rva_base;
        *(WORD*)(pe->thunk->data + ord_o)
            = ord;
        put_elf_str(pe->thunk, name);
        func_o += sizeof (DWORD);
        name_o += sizeof (DWORD);
        ord_o += sizeof (WORD);

        if (op)
            fprintf(op, "%s\n", name);
    }
    pe->exp_size = pe->thunk->data_offset - pe->exp_offs;
    tcc_free(sorted);
}