Example #1
0
File: pe.c Project: HarryR/sanos
int pe_load_res_file(TCCState *s1, int fd) {
  struct pe_rsrc_header hdr;
  Section *rsrc_section;
  int i, ret = -1;
  BYTE *ptr;

  lseek(fd, 0, SEEK_SET);
  if (!read_n(fd, &hdr, sizeof hdr)) goto quit;
  if (!pe_test_res_file(&hdr, sizeof hdr)) goto quit;

  rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
  ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData);
  lseek(fd, hdr.sectionhdr.PointerToRawData, SEEK_SET);
  if (!read_n(fd, ptr, hdr.sectionhdr.SizeOfRawData)) goto quit;

  lseek(fd, hdr.sectionhdr.PointerToRelocations, SEEK_SET);
  for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i) {
    struct pe_rsrc_reloc rel;
    if (!read_n(fd, &rel, sizeof rel)) goto quit;
    if (rel.type != 7) goto quit; // DIR32NB
    put_elf_reloc(symtab_section, rsrc_section, rel.offset, R_386_RELATIVE, 0);
  }
  ret = 0;
quit:
  if (ret) error_noabort("unrecognized resource file format");
  return ret;
}
Example #2
0
/* ------------------------------------------------------------- */
PUB_FN int pe_load_def_file(TCCState *s1, int fd)
{
    DLLReference *dllref;
    int state = 0, ret = -1;
    char line[400], dllname[80], *p;
    FILE *fp = fdopen(dup(fd), "rb");

    if (NULL == fp)
        goto quit;

    for (;;) {
        p = get_line(line, sizeof line, fp);
        if (NULL == p)
            break;
        if (0 == *p || ';' == *p)
            continue;
        switch (state) {
        case 0:
            if (0 != strnicmp(p, "LIBRARY", 7))
                goto quit;
            strcpy(dllname, trimfront(p+7));
            ++state;
            continue;

        case 1:
            if (0 != stricmp(p, "EXPORTS"))
                goto quit;
            ++state;
            continue;

        case 2:
            dllref = tcc_malloc(sizeof(DLLReference) + strlen(dllname));
            strcpy(dllref->name, dllname);
            dllref->level = 0;
            dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
            ++state;

        default:
            add_elf_sym(s1->dynsymtab_section,
                s1->nb_loaded_dlls, 0,
                ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), 0,
                text_section->sh_num, p);
            continue;
        }
    }
    ret = 0;
quit:
    if (fp)
        fclose(fp);
    if (ret)
        error_noabort("unrecognized export definition file format");
    return ret;
}
Example #3
0
File: pe.c Project: HarryR/sanos
int pe_load_def_file(TCCState *s1, int fd) {
  DLLReference *dllref;
  int state = 0, ret = -1, hint;
  char line[400], dllname[80], *p, *ordinal;
  FILE *fp = fdopen(dup(fd), "rb");
  if (fp == NULL) goto quit;

  for (;;) {
    p = get_line(line, sizeof line, fp);
    if (p == NULL) break;
    if (*p == 0 || *p == ';') continue;
    switch (state) {
      case 0:
        if (strncasecmp(p, "LIBRARY", 7) != 0) goto quit;
        strcpy(dllname, trimfront(p + 7));
        ++state;
        continue;

      case 1:
        if (strcasecmp(p, "EXPORTS") != 0) goto quit;
        ++state;
        continue;

      case 2:
        dllref = tcc_malloc(sizeof(DLLReference) + strlen(dllname));
        strcpy(dllref->name, dllname);
        dllref->level = 0;
        dynarray_add((void ***) &s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
        ++state;

      default:
        hint = 0;
        ordinal = strchr(p, '@');
        if (ordinal) {
          *ordinal = 0;
          trimback(p, ordinal);
          ordinal++;
          hint = atoi(ordinal);
        }
        add_elf_sym(s1->dynsymtab_section, s1->nb_loaded_dlls, 0, 
                    ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), hint, 
                    text_section->sh_num, p);
        continue;
    }
  }
  ret = 0;

quit:
  if (fp) fclose(fp);
  if (ret) error_noabort("unrecognized export definition file format");
  return ret;
}
Example #4
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 #5
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 #6
0
File: pe.c Project: HarryR/sanos
static int pe_write(struct pe_info *pe) {
  int i;
  int fd;
  FILE *op;
  FILE *stubfile;
  char *stub;
  int stub_size;
  DWORD file_offset, r;
  Section *s;

  if (pe->stub) {
    stubfile = fopen(pe->stub, "rb");
    if (stubfile == NULL) {
      error_noabort("could not read '%s': %s", pe->stub, strerror(errno));
      return 1;
    }
    fseek(stubfile, 0, SEEK_END);
    stub_size = ftell(stubfile);
    fseek(stubfile, 0, SEEK_SET);
    if (stub_size < sizeof(IMAGE_DOS_HEADER)) {
      error_noabort("invalid stub (%d bytes): %s", stub_size, pe->stub);
      return 1;
    }
    stub = tcc_malloc(stub_size);
    if (fread(stub, 1, stub_size, stubfile) != stub_size) {
      error_noabort("error reading stub '%s': %s", pe->stub, strerror(errno));
      return 1;
    }
    fclose(stubfile);
  } else {
    stub_size = DOSSTUB_SIZE + sizeof(IMAGE_DOS_HEADER);
    stub = tcc_malloc(stub_size);
    memcpy(stub, &pe_doshdr, sizeof(IMAGE_DOS_HEADER));
    memcpy(stub + sizeof(IMAGE_DOS_HEADER), pe_dosstub, DOSSTUB_SIZE);
  }
  ((PIMAGE_DOS_HEADER) stub)->e_lfanew = stub_size;

  fd = open(pe->filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0777);
  if (fd < 0) {
    error_noabort("could not write '%s': %s", pe->filename, strerror(errno));
    return 1;
  }
  op = fdopen(fd, "wb");

  pe->sizeofheaders = 
    pe_file_align(pe,
      stub_size +
      sizeof(DWORD) + 
      sizeof(IMAGE_FILE_HEADER) +
      sizeof(IMAGE_OPTIONAL_HEADER) +
      pe->sec_count * sizeof (IMAGE_SECTION_HEADER));

  file_offset = pe->sizeofheaders;
  pe_fpad(op, file_offset, 0);

  if (verbose == 2) {
    printf("------------------------------------\n  virt   file   size  ord section" "\n");
  }

  for (i = 0; i < pe->sec_count; ++i) {
    struct section_info *si = pe->sec_info + i;
    const char *sh_name = si->name;
    unsigned long addr = si->sh_addr - pe->imagebase;
    unsigned long size = si->sh_size;
    IMAGE_SECTION_HEADER *psh = &si->ish;

    if (verbose == 2) {
      printf("%6lx %6lx %6lx %4d %s\n", addr, file_offset, size, si->ord, sh_name);
    }

    switch (si->cls) {
      case sec_text:
        pe_opthdr.BaseOfCode = addr;
        pe_opthdr.SizeOfCode += size;
        pe_opthdr.AddressOfEntryPoint = ((Elf32_Sym *) symtab_section->data)[pe->start_sym_index].st_value - pe->imagebase;
        break;

      case sec_data:
        pe_opthdr.BaseOfData = addr;
        pe_opthdr.SizeOfInitializedData += size;
        break;

      case sec_bss:
        pe_opthdr.SizeOfUninitializedData += size;
        break;

      case sec_reloc:
        pe_set_datadir(IMAGE_DIRECTORY_ENTRY_BASERELOC, addr, size);
        break;

      case sec_rsrc:
        pe_set_datadir(IMAGE_DIRECTORY_ENTRY_RESOURCE, addr, size);
        break;

      case sec_stab:
        break;
    }

    if (pe->thunk == pe->s1->sections[si->ord]) {
      if (pe->imp_size) {
        pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IMPORT, pe->imp_offs + addr, pe->imp_size);
        pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IAT, pe->iat_offs + addr, pe->iat_size);
      }
      if (pe->exp_size) {
        pe_set_datadir(IMAGE_DIRECTORY_ENTRY_EXPORT, pe->exp_offs + addr, pe->exp_size);
      }
    }

    strcpy((char *) psh->Name, sh_name);
    psh->Characteristics = pe_sec_flags[si->cls];
    psh->VirtualAddress = addr;
    psh->Misc.VirtualSize = size;
    pe_opthdr.SizeOfImage = umax(pe_virtual_align(size + addr), pe_opthdr.SizeOfImage); 

    if (si->sh_size) {
      psh->PointerToRawData = r = file_offset;
      for (s = si->first; s; s = s->next) {
        if (s->sh_type != SHT_NOBITS) {
          file_offset = align(file_offset, s->sh_addralign);
          pe_fpad(op, file_offset, si->cls == sec_text ? 0x90 : 0x00);
          fwrite(s->data, 1, s->data_offset, op);
          file_offset += s->data_offset;
        }
      }
      file_offset = pe_file_align(pe, file_offset);
      psh->SizeOfRawData = file_offset - r;
      pe_fpad(op, file_offset, 0);
    }
  }

  pe_filehdr.TimeDateStamp = time(NULL);
  pe_filehdr.NumberOfSections = pe->sec_count;
  pe_filehdr.Characteristics = do_debug ? 0x0102 : 0x030E;
  pe_opthdr.SizeOfHeaders = pe->sizeofheaders;
  pe_opthdr.ImageBase = pe->imagebase;
  pe_opthdr.FileAlignment = pe->filealign;
  if (pe->type == PE_DLL) {
    pe_filehdr.Characteristics = do_debug ? 0x2102 : 0x230E;
  } else if (pe->type != PE_GUI) {
    pe_opthdr.Subsystem = 3;
  }
  if (!pe->reloc) pe_filehdr.Characteristics |= 1;
  if (pe->s1->noshare) pe_filehdr.Characteristics |= 0x4000;

  fseek(op, 0, SEEK_SET);
  fwrite(stub,  1, stub_size, op);
  fwrite(&pe_ntsig,  1, sizeof pe_ntsig, op);
  fwrite(&pe_filehdr,  1, sizeof pe_filehdr, op);
  fwrite(&pe_opthdr,  1, sizeof pe_opthdr, op);
  for (i = 0; i < pe->sec_count; ++i) {
    fwrite(&pe->sec_info[i].ish, 1, sizeof(IMAGE_SECTION_HEADER), op);
  }
  fclose(op);

  if (verbose == 2) {
    printf("------------------------------------\n");
  }
  if (verbose) {
    printf("<- %s (%lu bytes)\n", pe->filename, file_offset);
  }

  tcc_free(stub);
  return 0;
}
Example #7
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);
}
Example #8
0
/*----------------------------------------------------------------------------*/
ST_FN int pe_write(struct pe_info *pe)
{
    int i;
    FILE *op;
    DWORD file_offset, r;

    op = fopen(pe->filename, "wb");
    if (NULL == op) {
        error_noabort("could not write '%s': %s", pe->filename, strerror(errno));
        return 1;
    }

    pe->sizeofheaders = pe_file_align(
        sizeof pe_header
        + pe->sec_count * sizeof (IMAGE_SECTION_HEADER)
        );

    file_offset = pe->sizeofheaders;
    pe_fpad(op, file_offset);

    if (2 == pe->s1->verbose)
        printf("-------------------------------"
               "\n  virt   file   size  section" "\n");

    for (i = 0; i < pe->sec_count; ++i) {
        struct section_info *si = pe->sec_info + i;
        const char *sh_name = si->name;
        unsigned long addr = si->sh_addr - pe->imagebase;
        unsigned long size = si->sh_size;
        IMAGE_SECTION_HEADER *psh = &si->ish;

        if (2 == pe->s1->verbose)
            printf("%6lx %6lx %6lx  %s\n",
                addr, file_offset, size, sh_name);

        switch (si->cls) {
            case sec_text:
                pe_header.opthdr.BaseOfCode = addr;
                pe_header.opthdr.AddressOfEntryPoint = addr + pe->start_addr;
                break;

            case sec_data:
                pe_header.opthdr.BaseOfData = addr;
                break;

            case sec_bss:
                break;

            case sec_reloc:
                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_BASERELOC, addr, size);
                break;

            case sec_rsrc:
                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_RESOURCE, addr, size);
                break;

            case sec_stab:
                break;
        }

        if (pe->thunk == pe->s1->sections[si->ord]) {
            if (pe->imp_size) {
                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IMPORT,
                    pe->imp_offs + addr, pe->imp_size);
                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IAT,
                    pe->iat_offs + addr, pe->iat_size);
            }
            if (pe->exp_size) {
                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_EXPORT,
                    pe->exp_offs + addr, pe->exp_size);
            }
        }

        strcpy((char*)psh->Name, sh_name);

        psh->Characteristics = pe_sec_flags[si->cls];
        psh->VirtualAddress = addr;
        psh->Misc.VirtualSize = size;
        pe_header.opthdr.SizeOfImage =
            umax(pe_virtual_align(size + addr), pe_header.opthdr.SizeOfImage); 

        if (si->data_size) {
            psh->PointerToRawData = r = file_offset;
            fwrite(si->data, 1, si->data_size, op);
            file_offset = pe_file_align(file_offset + si->data_size);
            psh->SizeOfRawData = file_offset - r;
            pe_fpad(op, file_offset);
        }
    }

    // pe_header.filehdr.TimeDateStamp = time(NULL);
    pe_header.filehdr.NumberOfSections = pe->sec_count;
    pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
    pe_header.opthdr.ImageBase = pe->imagebase;
    if (PE_DLL == pe->type)
        pe_header.filehdr.Characteristics = 0x230E;
    else if (PE_GUI != pe->type)
        pe_header.opthdr.Subsystem = 3;

    fseek(op, SEEK_SET, 0);
    fwrite(&pe_header,  1, sizeof pe_header, op);
    for (i = 0; i < pe->sec_count; ++i)
        fwrite(&pe->sec_info[i].ish, 1, sizeof(IMAGE_SECTION_HEADER), op);
    fclose (op);

    if (2 == pe->s1->verbose)
        printf("-------------------------------\n");
    if (pe->s1->verbose)
        printf("<- %s (%lu bytes)\n", pe->filename, file_offset);

    return 0;
}