Example #1
0
File: pe.c Project: HarryR/sanos
static void pe_build_reloc(struct pe_info *pe) {
  DWORD offset, block_ptr, addr;
  int count, i;
  Elf32_Rel *rel, *rel_end;
  Section *s = NULL, *sr;

  offset = addr = block_ptr = count = i = 0;
  rel = rel_end = NULL;

  for (;;) {
    if (rel < rel_end) {
      int type = ELF32_R_TYPE(rel->r_info);
      addr = rel->r_offset + s->sh_addr;
      rel++;
      if (type != R_386_32) continue;
      if (count == 0) {
        // New block
        block_ptr = pe->reloc->data_offset;
        section_ptr_add(pe->reloc, sizeof(struct pe_reloc_header));
        offset = addr & 0xFFFFFFFF << 12;
      }
      if ((addr -= offset) < (1 << 12)) {
        // One block spans 4k addresses
        WORD *wp = section_ptr_add(pe->reloc, sizeof(WORD));
        *wp = addr | IMAGE_REL_BASED_HIGHLOW << 12;
        ++count;
        continue;
      }
      rel--;
    } else {
      if (s) s = s->next;
      if (!s && i < pe->sec_count) s = pe->sec_info[i++].first;
      if (s) {
        sr = s->reloc;
        if (sr) {
          rel = (Elf32_Rel *) sr->data;
          rel_end = (Elf32_Rel *) (sr->data + sr->data_offset);
        }
        continue;
      }
    }

    if (count) {
      // Store the last block and ready for a new one
      struct pe_reloc_header *hdr;

      // Align for DWORDS
      if (count & 1) {
        section_ptr_add(pe->reloc, sizeof(WORD));
        count++;
      }
      hdr = (struct pe_reloc_header *) (pe->reloc->data + block_ptr);
      hdr->offset = offset - pe->imagebase;
      hdr->size = count * sizeof(WORD) + sizeof(struct pe_reloc_header);
      count = 0;
    }

    if (rel >= rel_end) break;
  }
}
Example #2
0
/* ------------------------------------------------------------- */
ST_FN void pe_build_reloc (struct pe_info *pe)
{
    DWORD offset, block_ptr, addr;
    int count, i;
    Elf32_Rel *rel, *rel_end;
    Section *s = NULL, *sr;

    offset = addr = block_ptr = count = i = 0;
    rel = rel_end = NULL;

    for(;;) {
        if (rel < rel_end) {
            int type = ELF32_R_TYPE(rel->r_info);
            addr = rel->r_offset + s->sh_addr;
            ++ rel;
            if (type != R_386_32)
                continue;
            if (count == 0) { /* new block */
                block_ptr = pe->reloc->data_offset;
                section_ptr_add(pe->reloc, sizeof(struct pe_reloc_header));
                offset = addr & 0xFFFFFFFF<<12;
            }
            if ((addr -= offset)  < (1<<12)) { /* one block spans 4k addresses */
                WORD *wp = section_ptr_add(pe->reloc, sizeof (WORD));
                *wp = addr | IMAGE_REL_BASED_HIGHLOW<<12;
                ++count;
                continue;
            }
            -- rel;

        } else if (i < pe->sec_count) {
            sr = (s = pe->s1->sections[pe->sec_info[i++].ord])->reloc;
            if (sr) {
                rel = (Elf32_Rel *)sr->data;
                rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
            }
            continue;
        }

        if (count) {
            /* store the last block and ready for a new one */
            struct pe_reloc_header *hdr;
            if (count & 1) /* align for DWORDS */
                section_ptr_add(pe->reloc, sizeof(WORD)), ++count;
            hdr = (struct pe_reloc_header *)(pe->reloc->data + block_ptr);
            hdr -> offset = offset - pe->imagebase;
            hdr -> size = count * sizeof(WORD) + sizeof(struct pe_reloc_header);
            count = 0;
        }

        if (rel >= rel_end)
            break;
    }
}
Example #3
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 #4
0
File: outcoff.c Project: 7ym0n/note
/*********************************************************** 
 * 功能:			增加COFF符号
 * symtab:			保存COFF符号表的节
 * name:			符号名称
 * val:				与符号相关的值
 * sec_index:		定义此符号的节
 * type:			Coff符号类型
 * StorageClass:	Coff符号存储类别	
 * 返回值:			符号COFF符号表中序号
 **********************************************************/
int coffsym_add(Section *symtab,char* name, int val, int sec_index,
							short type, char StorageClass)
{
    CoffSym *cfsym;
	int cs,keyno;
	char *csname;
	Section *strtab = symtab->link;
	int *hashtab;
    hashtab = symtab->hashtab;
	cs = coffsym_search(symtab,name);
	if(cs == 0)
	{		
        cfsym = section_ptr_add(symtab, sizeof(CoffSym));
		csname = coffstr_add(strtab, name);
		cfsym->Name = csname - strtab->data;
		cfsym->Value =	val;
		cfsym->Section = sec_index;
		cfsym->Type = type;
		cfsym->StorageClass = StorageClass;
		cfsym->Value =	val;
		keyno = elf_hash(name);
		cfsym->Next = hashtab[keyno];

		cs = cfsym - (CoffSym*)symtab->data;	
		hashtab[keyno] = cs;
	}
	return cs;
}
Example #5
0
File: outcoff.c Project: 7ym0n/note
/*********************************************************** 
 * 功能:	增加COFF重定位信息
 * offset:	需要进行重定位的代码或数据在其相应节的偏移位置
 * cfsym:	符号表的索引
 * section: 符号所在节,重点讲一下与Coff区别
 * type:	重定位类型
 **********************************************************/
void coffreloc_direct_add(int offset, int cfsym, char section, char type)
{
	CoffReloc *rel;
	rel = section_ptr_add(sec_rel, sizeof(CoffReloc));
    rel->offset = offset;
	rel->cfsym = cfsym;
	rel->section = section;
    rel->type = type;
}
Example #6
0
File: outcoff.c Project: 7ym0n/note
/*********************************************************** 
 * 功能:	增加COFF符号名字符串
 * strtab:	保存COFF字符串表的节
 * name:	符号名称字符串
 * 返回值:	新增COFF字符串
 **********************************************************/
char *coffstr_add(Section *strtab,char* name)
{	
	int len;
	char *pstr;
	len = strlen(name);
	pstr = section_ptr_add(strtab, len+1);
	memcpy(pstr,name,len);
	return pstr;
}
Example #7
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 #8
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 #9
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 #10
0
File: pe.c Project: HarryR/sanos
static void pe_align_section(Section *s, int a) {
  int i = s->data_offset & (a - 1);
  if (i) section_ptr_add(s, a - i);
}
Example #11
0
static void asm_parse_directive(TCCState *s1)
{
    int n, offset, v, size, tok1;
    Section *sec;
    uint8_t *ptr;

    /* assembler directive */
    next();
    sec = cur_text_section;
    switch(tok) {
    case TOK_ASM_align:
    case TOK_ASM_p2align:
    case TOK_ASM_skip:
    case TOK_ASM_space:
        tok1 = tok;
        next();
        n = asm_int_expr(s1);
        if (tok1 == TOK_ASM_p2align)
        {
            if (n < 0 || n > 30)
                tcc_error("invalid p2align, must be between 0 and 30");
            n = 1 << n;
            tok1 = TOK_ASM_align;
        }
        if (tok1 == TOK_ASM_align) {
            if (n < 0 || (n & (n-1)) != 0)
                tcc_error("alignment must be a positive power of two");
            offset = (ind + n - 1) & -n;
            size = offset - ind;
            /* the section must have a compatible alignment */
            if (sec->sh_addralign < n)
                sec->sh_addralign = n;
        } else {
            size = n;
        }
        v = 0;
        if (tok == ',') {
            next();
            v = asm_int_expr(s1);
        }
    zero_pad:
        if (sec->sh_type != SHT_NOBITS) {
            sec->data_offset = ind;
            ptr = section_ptr_add(sec, size);
            memset(ptr, v, size);
        }
        ind += size;
        break;
    case TOK_ASM_quad:
        next();
        for(;;) {
            uint64_t vl;
            const char *p;

            p = tokc.cstr->data;
            if (tok != TOK_PPNUM) {
            error_constant:
                tcc_error("64 bit constant");
            }
            vl = strtoll(p, (char **)&p, 0);
            if (*p != '\0')
                goto error_constant;
            next();
            if (sec->sh_type != SHT_NOBITS) {
                /* XXX: endianness */
                gen_le32(vl);
                gen_le32(vl >> 32);
            } else {
                ind += 8;
            }
            if (tok != ',')
                break;
            next();
        }
Example #12
0
void genblk(unsigned char *data, int size) {
  memcpy(section_ptr_add(cur_text_section, size), data, size);
}
Example #13
0
void genword(int w) {
  *(int *) section_ptr_add(cur_text_section, 4) = w;
}
Example #14
0
void gen(int c) {
  *(char *) section_ptr_add(cur_text_section, 1) = c;
}
Example #15
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 #16
0
/* generate function epilog */
void gfunc_epilog(void)
{
    int v, saved_ind;

#ifdef CONFIG_TCC_BCHECK
    if (tcc_state->do_bounds_check
     && func_bound_offset != lbounds_section->data_offset) {
        int saved_ind;
        int *bounds_ptr;
        Sym *sym, *sym_data;
        /* add end of table info */
        bounds_ptr = section_ptr_add(lbounds_section, sizeof(int));
        *bounds_ptr = 0;
        /* generate bound local allocation */
        saved_ind = ind;
        ind = func_sub_sp_offset;
        sym_data = get_sym_ref(&char_pointer_type, lbounds_section, 
                               func_bound_offset, lbounds_section->data_offset);
        greloc(cur_text_section, sym_data,
               ind + 1, R_386_32);
        oad(0xb8, 0); /* mov %eax, xxx */
        sym = external_global_sym(TOK___bound_local_new, &func_old_type, 0);
        greloc(cur_text_section, sym, 
               ind + 1, R_386_PC32);
        oad(0xe8, -4);
        ind = saved_ind;
        /* generate bound check local freeing */
        o(0x5250); /* save returned value, if any */
        greloc(cur_text_section, sym_data,
               ind + 1, R_386_32);
        oad(0xb8, 0); /* mov %eax, xxx */
        sym = external_global_sym(TOK___bound_local_delete, &func_old_type, 0);
        greloc(cur_text_section, sym, 
               ind + 1, R_386_PC32);
        oad(0xe8, -4);
        o(0x585a); /* restore returned value, if any */
    }
#endif
    o(0xc9); /* leave */
    if (func_ret_sub == 0) {
        o(0xc3); /* ret */
    } else {
        o(0xc2); /* ret n */
        g(func_ret_sub);
        g(func_ret_sub >> 8);
    }
    /* align local size to word & save local variables */
    
    v = (-loc + 3) & -4; 
    saved_ind = ind;
    ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
#ifdef TCC_TARGET_PE
    if (v >= 4096) {
        Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
        oad(0xb8, v); /* mov stacksize, %eax */
        oad(0xe8, -4); /* call __chkstk, (does the stackframe too) */
        greloc(cur_text_section, sym, ind-4, R_386_PC32);
    } else
#endif
    {
        o(0xe58955);  /* push %ebp, mov %esp, %ebp */
        o(0xec81);  /* sub esp, stacksize */
        gen_le32(v);
#if FUNC_PROLOG_SIZE == 10
        o(0x90);  /* adjust to FUNC_PROLOG_SIZE */
#endif
    }
    ind = saved_ind;
}