// File: /workspace/github_c_makefile_star2_O3/katlogic[P]ljx/src/host/buildvm_peobj.c
// Function: emit_peobj
void emit_peobj(BuildCtx *ctx)
{
  PEheader pehdr;
  PEsection pesect[PEOBJ_NSECTIONS];
  uint32_t sofs;
  int i, nrsym;
  union { uint8_t b; uint32_t u; } host_endian;

  sofs = sizeof(PEheader) + PEOBJ_NSECTIONS*sizeof(PEsection);

  /* Fill in PE sections. */
  memset(&pesect, 0, PEOBJ_NSECTIONS*sizeof(PEsection));
  memcpy(pesect[PEOBJ_SECT_TEXT].name, ".text", sizeof(".text")-1);
  pesect[PEOBJ_SECT_TEXT].ofs = sofs;
  sofs += (pesect[PEOBJ_SECT_TEXT].size = (uint32_t)ctx->codesz);
  pesect[PEOBJ_SECT_TEXT].relocofs = sofs;
  sofs += (pesect[PEOBJ_SECT_TEXT].nreloc = (uint16_t)ctx->nreloc) * PEOBJ_RELOC_SIZE;
  /* Flags: 60 = read+execute, 50 = align16, 20 = code. */
  pesect[PEOBJ_SECT_TEXT].flags = PEOBJ_TEXT_FLAGS;

#if LJ_TARGET_X64
  memcpy(pesect[PEOBJ_SECT_PDATA].name, ".pdata", sizeof(".pdata")-1);
  pesect[PEOBJ_SECT_PDATA].ofs = sofs;
  sofs += (pesect[PEOBJ_SECT_PDATA].size = 6*4);
  pesect[PEOBJ_SECT_PDATA].relocofs = sofs;
  sofs += (pesect[PEOBJ_SECT_PDATA].nreloc = 6) * PEOBJ_RELOC_SIZE;
  /* Flags: 40 = read, 30 = align4, 40 = initialized data. */
  pesect[PEOBJ_SECT_PDATA].flags = 0x40300040;

  memcpy(pesect[PEOBJ_SECT_XDATA].name, ".xdata", sizeof(".xdata")-1);
  pesect[PEOBJ_SECT_XDATA].ofs = sofs;
  sofs += (pesect[PEOBJ_SECT_XDATA].size = 8*2+4+6*2);  /* See below. */
  pesect[PEOBJ_SECT_XDATA].relocofs = sofs;
  sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE;
  /* Flags: 40 = read, 30 = align4, 40 = initialized data. */
  pesect[PEOBJ_SECT_XDATA].flags = 0x40300040;
#elif LJ_TARGET_X86
  memcpy(pesect[PEOBJ_SECT_SXDATA].name, ".sxdata", sizeof(".sxdata")-1);
  pesect[PEOBJ_SECT_SXDATA].ofs = sofs;
  sofs += (pesect[PEOBJ_SECT_SXDATA].size = 4);
  pesect[PEOBJ_SECT_SXDATA].relocofs = sofs;
  /* Flags: 40 = read, 30 = align4, 02 = lnk_info, 40 = initialized data. */
  pesect[PEOBJ_SECT_SXDATA].flags = 0x40300240;
#endif

  memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1);
  pesect[PEOBJ_SECT_RDATA_Z].ofs = sofs;
  sofs += (pesect[PEOBJ_SECT_RDATA_Z].size = (uint32_t)strlen(ctx->dasm_ident)+1);
  /* Flags: 40 = read, 30 = align4, 40 = initialized data. */
  pesect[PEOBJ_SECT_RDATA_Z].flags = 0x40300040;

  /* Fill in PE header. */
  pehdr.arch = PEOBJ_ARCH_TARGET;
  pehdr.nsects = PEOBJ_NSECTIONS;
  pehdr.time = 0;  /* Timestamp is optional. */
  pehdr.symtabofs = sofs;
  pehdr.opthdrsz = 0;
  pehdr.flags = 0;

  /* Compute the size of the symbol table:
  ** @feat.00 + nsections*2
  ** + asm_start + nsym
  ** + nrsym
  */
  nrsym = ctx->nrelocsym;
  pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym;
#if LJ_TARGET_X64
  pehdr.nsyms += 1;  /* Symbol for lj_err_unwind_win. */
#endif

  /* Write PE object header and all sections. */
  owrite(ctx, &pehdr, sizeof(PEheader));
  owrite(ctx, &pesect, sizeof(PEsection)*PEOBJ_NSECTIONS);

  /* Write .text section. */
  host_endian.u = 1;
  if (host_endian.b != LJ_ENDIAN_SELECT(1, 0)) {
#if LJ_TARGET_PPC
    uint32_t *p = (uint32_t *)ctx->code;
    int n = (int)(ctx->codesz >> 2);
    for (i = 0; i < n; i++, p++)
      *p = lj_bswap(*p);  /* Byteswap .text section. */
#else
    fprintf(stderr, "Error: different byte order for host and target\n");
    exit(1);
#endif
  }
  owrite(ctx, ctx->code, ctx->codesz);
  for (i = 0; i < ctx->nreloc; i++) {
    PEreloc reloc;
    reloc.vaddr = (uint32_t)ctx->reloc[i].ofs + PEOBJ_RELOC_OFS;
    reloc.symidx = 1+2+ctx->reloc[i].sym;  /* Reloc syms are after .text sym. */
    reloc.type = ctx->reloc[i].type ? PEOBJ_RELOC_REL32 : PEOBJ_RELOC_DIR32;
    owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
  }

#if LJ_TARGET_X64
  { /* Write .pdata section. */
    uint32_t fcofs = (uint32_t)ctx->sym[ctx->nsym-1].ofs;
    uint32_t pdata[3];  /* Start of .text, end of .text and .xdata. */
    PEreloc reloc;
    pdata[0] = 0; pdata[1] = fcofs; pdata[2] = 0;
    owrite(ctx, &pdata, sizeof(pdata));
    pdata[0] = fcofs; pdata[1] = (uint32_t)ctx->codesz; pdata[2] = 20;
    owrite(ctx, &pdata, sizeof(pdata));
    reloc.vaddr = 0; reloc.symidx = 1+2+nrsym+2+2+1;
    reloc.type = PEOBJ_RELOC_ADDR32NB;
    owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
    reloc.vaddr = 4; reloc.symidx = 1+2+nrsym+2+2+1;
    reloc.type = PEOBJ_RELOC_ADDR32NB;
    owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
    reloc.vaddr = 8; reloc.symidx = 1+2+nrsym+2;
    reloc.type = PEOBJ_RELOC_ADDR32NB;
    owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
    reloc.vaddr = 12; reloc.symidx = 1+2+nrsym+2+2+1;
    reloc.type = PEOBJ_RELOC_ADDR32NB;
    owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
    reloc.vaddr = 16; reloc.symidx = 1+2+nrsym+2+2+1;
    reloc.type = PEOBJ_RELOC_ADDR32NB;
    owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
    reloc.vaddr = 20; reloc.symidx = 1+2+nrsym+2;
    reloc.type = PEOBJ_RELOC_ADDR32NB;
    owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
  }
  { /* Write .xdata section. */
    uint16_t xdata[8+2+6];
    PEreloc reloc;
    xdata[0] = 0x01|0x08|0x10;  /* Ver. 1, uhandler/ehandler, prolog size 0. */
    xdata[1] = 0x0005;  /* Number of unwind codes, no frame pointer. */
    xdata[2] = 0x4200;  /* Stack offset 4*8+8 = aword*5. */
    xdata[3] = 0x3000;  /* Push rbx. */
    xdata[4] = 0x6000;  /* Push rsi. */
    xdata[5] = 0x7000;  /* Push rdi. */
    xdata[6] = 0x5000;  /* Push rbp. */
    xdata[7] = 0;  /* Alignment. */
    xdata[8] = xdata[9] = 0;  /* Relocated address of exception handler. */
    xdata[10] = 0x01;  /* Ver. 1, no handler, prolog size 0. */
    xdata[11] = 0x1504;  /* Number of unwind codes, fp = rbp, fpofs = 16. */
    xdata[12] = 0x0300;  /* set_fpreg. */
    xdata[13] = 0x0200;  /* stack offset 0*8+8 = aword*1. */
    xdata[14] = 0x3000;  /* Push rbx. */
    xdata[15] = 0x5000;  /* Push rbp. */
    owrite(ctx, &xdata, sizeof(xdata));
    reloc.vaddr = 2*8; reloc.symidx = 1+2+nrsym+2+2;
    reloc.type = PEOBJ_RELOC_ADDR32NB;
    owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
  }
#elif LJ_TARGET_X86
  /* Write .sxdata section. */
  for (i = 0; i < nrsym; i++) {
    if (!strcmp(ctx->relocsym[i], "_lj_err_unwind_win")) {
      uint32_t symidx = 1+2+i;
      owrite(ctx, &symidx, 4);
      break;
    }
  }
  if (i == nrsym) {
    fprintf(stderr, "Error: extern lj_err_unwind_win not used\n");
    exit(1);
  }
#endif

  /* Write .rdata$Z section. */
  owrite(ctx, ctx->dasm_ident, strlen(ctx->dasm_ident)+1);

  /* Write symbol table. */
  strtab = NULL;  /* 1st pass: collect string sizes. */
  for (;;) {
    strtabofs = 4;
    /* Mark as SafeSEH compliant. */
    emit_peobj_sym(ctx, "@feat.00", 1,
		   PEOBJ_SECT_ABS, PEOBJ_TYPE_NULL, PEOBJ_SCL_STATIC);

    emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_TEXT);
    for (i = 0; i < nrsym; i++)
      emit_peobj_sym(ctx, ctx->relocsym[i], 0,
		     PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);

#if LJ_TARGET_X64
    emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA);
    emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA);
    emit_peobj_sym(ctx, "lj_err_unwind_win", 0,
		   PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
#elif LJ_TARGET_X86
    emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_SXDATA);
#endif

    emit_peobj_sym(ctx, ctx->beginsym, 0,
		   PEOBJ_SECT_TEXT, PEOBJ_TYPE_NULL, PEOBJ_SCL_EXTERN);
    for (i = 0; i < ctx->nsym; i++)
      emit_peobj_sym(ctx, ctx->sym[i].name, (uint32_t)ctx->sym[i].ofs,
		     PEOBJ_SECT_TEXT, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);

    emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_RDATA_Z);

    if (strtab)
      break;
    /* 2nd pass: alloc strtab, write syms and copy strings. */
    strtab = (char *)malloc(strtabofs);
    *(uint32_t *)strtab = (uint32_t)strtabofs;
  }

  /* Write string table. */
  owrite(ctx, strtab, strtabofs);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xf8, %rsp
movq %rdi, %rbx
leaq 0x55(%rsp), %r14
xorl %r12d, %r12d
movl $0x97, %edx
movq %r14, %rdi
xorl %esi, %esi
callq 0x50c0
movl $0x7865742e, -0x5(%r14) # imm = 0x7865742E
movb $0x74, -0x1(%r14)
movl $0xb4, %ecx
movl %ecx, 0xf(%r14)
movl 0x30(%rbx), %eax
movl %eax, 0xb(%r14)
addl %eax, %ecx
movl %ecx, 0x13(%r14)
movl 0x44(%rbx), %ecx
movzwl %cx, %ecx
movw %cx, 0x1b(%r14)
leal (%rcx,%rcx,4), %ecx
leal 0xb4(%rax,%rcx,2), %r15d
movabsq $0x6164702e60500020, %rdx # imm = 0x6164702E60500020
movq %rdx, 0x1f(%r14)
movw $0x6174, %dx            # imm = 0x6174
movw %dx, 0x27(%r14)
movl %r15d, 0x37(%r14)
movl $0x18, 0x33(%r14)
leal 0xcc(%rax,%rcx,2), %esi
movl %esi, 0x3b(%r14)
movw $0x6, 0x43(%r14)
leal 0x108(%rax,%rcx,2), %esi
movabsq $0x6164782e40300040, %rdi # imm = 0x6164782E40300040
movq %rdi, 0x47(%r14)
movw %dx, 0x4f(%r14)
movl %esi, 0x5f(%r14)
movl $0x20, 0x5b(%r14)
leal 0x128(%rax,%rcx,2), %edx
movl %edx, 0x63(%r14)
movw $0x1, 0x6b(%r14)
leal 0x132(%rax,%rcx,2), %eax
movl $0x40300040, %ebp       # imm = 0x40300040
movl %ebp, 0x6f(%r14)
movabsq $0x5a2461746164722e, %rcx # imm = 0x5A2461746164722E
movq %rcx, 0x73(%r14)
movl %eax, 0x87(%r14)
movq 0x88(%rbx), %rdi
callq 0x50a0
leal 0x1(%rax), %ecx
movl %ecx, 0x83(%r14)
addl %r15d, %eax
addl $0x7f, %eax
movl %ebp, 0x97(%r14)
leaq 0x3c(%rsp), %rsi
movq $0x48664, (%rsi)        # imm = 0x48664
movl %eax, 0x8(%rsi)
movl $0x0, 0x10(%rsi)
movl 0x40(%rbx), %eax
movl 0x48(%rbx), %ebp
leal 0xb(%rbp,%rax), %eax
movl %eax, 0xc(%rsi)
movl $0x14, %edx
movq %rbx, %rdi
callq 0x681a
leaq 0x50(%rsp), %rsi
movl $0xa0, %edx
movq %rbx, %rdi
callq 0x681a
movq 0x28(%rbx), %rsi
movq 0x30(%rbx), %rdx
movq %rbx, %rdi
callq 0x681a
cmpl $0x0, 0x44(%rbx)
jle 0x9f21
leaq 0xa0(%rbx), %r15
xorl %r13d, %r13d
leaq 0x10(%rsp), %r14
movl -0x8(%r15), %eax
movl %eax, 0x10(%rsp)
movl -0x4(%r15), %eax
addl $0x3, %eax
movl %eax, 0x14(%rsp)
xorl %eax, %eax
cmpl $0x0, (%r15)
setne %al
leal 0x2(%rax,%rax), %eax
movw %ax, 0x18(%rsp)
movl $0xa, %edx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x681a
incq %r13
movslq 0x44(%rbx), %rax
addq $0xc, %r15
cmpq %rax, %r13
jl 0x9edc
movq 0x58(%rbx), %rax
movslq 0x40(%rbx), %rcx
shlq $0x4, %rcx
movl -0x8(%rax,%rcx), %r15d
leaq 0x10(%rsp), %r14
movl %r12d, (%r14)
movl %r15d, 0x4(%r14)
movl %r12d, 0x8(%r14)
movl $0xc, %edx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x681a
movl %r15d, (%r14)
movl 0x30(%rbx), %eax
movl %eax, 0x4(%r14)
movl $0x14, %eax
movl %eax, 0x8(%r14)
movl $0xc, %edx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x681a
leaq 0x30(%rsp), %r15
movl %r12d, (%r15)
leal 0x5(%rbp), %r13d
movl %r13d, 0x8(%rsp)
leal 0x7(%rbp), %eax
movl %eax, 0xc(%rsp)
leal 0x8(%rbp), %r12d
movl %r12d, 0x4(%r15)
movw $0x3, %ax
movw %ax, 0x8(%r15)
movl $0xa, %edx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x681a
movl $0x4, (%r15)
movl %r12d, 0x4(%r15)
movw $0x3, %ax
movw %ax, 0x8(%r15)
movl $0xa, %edx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x681a
movl $0x8, (%r15)
movl %r13d, 0x4(%r15)
movw $0x3, %r13w
movw %r13w, 0x8(%r15)
movl $0xa, %edx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x681a
movl $0xc, (%r15)
movl %r12d, 0x4(%r15)
movw %r13w, 0x8(%r15)
movl $0xa, %edx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x681a
movl $0x10, %eax
movl %eax, (%r15)
movl %r12d, 0x4(%r15)
movw %r13w, 0x8(%r15)
movw $0x3, %r12w
movl $0xa, %edx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x681a
movl $0x14, %eax
movl %eax, (%r15)
movl 0x8(%rsp), %eax
movl %eax, 0x4(%r15)
movw %r12w, 0x8(%r15)
movw $0x3, %r12w
movl $0xa, %edx
movq %rbx, %rdi
movq %r15, %rsi
callq 0x681a
movaps 0x81b2(%rip), %xmm0     # 0x12220
movaps %xmm0, (%r14)
movaps 0x81b7(%rip), %xmm0     # 0x12230
movaps %xmm0, 0x10(%r14)
leaq 0x10(%rsp), %rsi
movl $0x20, %edx
movq %rbx, %rdi
callq 0x681a
movl $0x10, %eax
movl %eax, (%r15)
movl 0xc(%rsp), %eax
movl %eax, 0x4(%r15)
movw %r12w, 0x8(%r15)
leaq 0x30(%rsp), %rsi
movl $0xa, %edx
movq %rbx, %rdi
callq 0x681a
movq 0x88(%rbx), %r14
movq %r14, %rdi
callq 0x50a0
leaq 0x1(%rax), %rdx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x681a
movq $0x0, 0xd128(%rip) # 0x17208
leaq 0x50(%rsp), %r15
leaq 0x8171(%rip), %r12      # 0x1225d
movq $0x4, 0xd119(%rip) # 0x17210
movq %rbx, %rdi
leaq 0x8153(%rip), %rsi      # 0x12254
movl $0x1, %edx
movl $0xfffffffe, %ecx       # imm = 0xFFFFFFFE
xorl %r8d, %r8d
movl $0x3, %r9d
callq 0xa248
movq %rbx, %rdi
movq %r15, %rsi
xorl %edx, %edx
callq 0xa353
testl %ebp, %ebp
jle 0xa158
xorl %r14d, %r14d
movq 0x60(%rbx), %rax
movq (%rax,%r14,8), %rsi
movq %rbx, %rdi
xorl %edx, %edx
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
movl $0x20, %r8d
movl $0x2, %r9d
callq 0xa248
incq %r14
cmpq %r14, %rbp
jne 0xa12d
movq %rbx, %rdi
movq %r15, %rsi
movl $0x1, %edx
callq 0xa353
movq %rbx, %rdi
movq %r15, %rsi
movl $0x2, %edx
callq 0xa353
movq %rbx, %rdi
movq %r12, %rsi
xorl %edx, %edx
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
movl $0x20, %r8d
movl $0x2, %r9d
callq 0xa248
movq 0x70(%rbx), %rsi
movq %rbx, %rdi
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
movl $0x2, %r9d
callq 0xa248
cmpl $0x0, 0x40(%rbx)
jle 0xa1f1
movl $0x8, %r13d
xorl %r14d, %r14d
movq 0x58(%rbx), %rax
movq -0x8(%rax,%r13), %rsi
movl (%rax,%r13), %edx
movq %rbx, %rdi
xorl %ecx, %ecx
movl $0x20, %r8d
movl $0x2, %r9d
callq 0xa248
incq %r14
movslq 0x40(%rbx), %rax
addq $0x10, %r13
cmpq %rax, %r14
jl 0xa1be
movq %rbx, %rdi
movq %r15, %rsi
movl $0x3, %edx
callq 0xa353
movq 0xd000(%rip), %rsi      # 0x17208
movq 0xd001(%rip), %r13      # 0x17210
testq %rsi, %rsi
jne 0xa22b
movq %r13, %rdi
callq 0x5150
movq %rax, 0xcfe5(%rip)      # 0x17208
movl %r13d, (%rax)
jmp 0xa0ec
movq %rbx, %rdi
movq %r13, %rdx
callq 0x681a
addq $0xf8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq