// File: /workspace/github_c_makefile_star2_O2/deplinenoise[P]vlink/t_elf32.c
// Function: elf32_segmentcheck
uint32_t elf32_segmentcheck(struct GlobalVars *gv)
/* 1. checks the PT_LOAD segments for intermediate uninitialized sections,
      which will be turned into initialized PROGBITS data sections
   2. sets segment permissions from contained sections
   3. calculates bytes to insert at beginning of segment to meet
      page-alignment restrictions
   4. initializes PT_PHDR segment
   Returns number of segments in list */
{
  unsigned long headersize = fff[gv->dest_format]->headersize(gv);
  struct Phdr *p,*phdrs,*first=NULL;
  struct LinkedSection *ls,*bss_start,*seg_lastdat,*seg_lastsec,*prg_lastdat;
  unsigned long foffs;
  uint32_t segcnt;

  /* find PHDR segment */
  for (phdrs=NULL,p=gv->phdrlist; p; p=p->next) {
    if ((p->flags&PHDR_USED) && p->type==PT_PHDR) {
      phdrs = p;
      break;
    }
  }

  for (p=gv->phdrlist,prg_lastdat=NULL; p; p=p->next) {
    if (p->type==PT_LOAD && (p->flags&PHDR_USED) &&
        p->start!=ADDR_NONE && p->start_vma!=ADDR_NONE) {
      unsigned long amask = (1L << p->alignment) - 1;
      long gapsize;

      bss_start = seg_lastsec = NULL;
      p->flags &= ~PHDR_PFMASK;
      p->flags |= PF_R;  /* at least 'read' should be allowed */

      /* determine initial file offset for first segment */
      if (!first) {
        first = p;
        if (phdrs) {  /* header is included in first segment */
          p->flags |= PHDR_PHDRS | PHDR_FILEHDR;
          foffs = 0;
          file_hdr_gap = (unsigned long)p->start
                          - ((unsigned long)(p->start - headersize) & ~amask)
                          - headersize;
          p->start -= headersize + file_hdr_gap;
          if (p->start_vma)
            p->start_vma -= headersize + file_hdr_gap;
        }
        else
          foffs = headersize;  /* first segment starts after header */
      }

      for (ls=(struct LinkedSection *)gv->lnksec.first,
            seg_lastdat=NULL,seg_lastsec=NULL;
           ls->n.next!=NULL;
           ls=(struct LinkedSection *)ls->n.next) {

        if (ls->copybase>=(unsigned long)p->start && ls->size &&
            (ls->copybase+ls->size)<=(unsigned long)p->mem_end &&
            (ls->flags & SF_ALLOC)) {

          p->flags |= conv_perm_to_elf(ls->protection);
          if (ls->alignment > p->alignment)
            p->alignment = ls->alignment;

          if (ls->flags & SF_UNINITIALIZED) {
            if (!bss_start)
              bss_start = ls;
          }
          else {
            if (bss_start) {
              struct LinkedSection *bssls;

              for (bssls=bss_start; bssls!=ls;
                   bssls=(struct LinkedSection *)bssls->n.next) {
                bssls->flags &= ~SF_UNINITIALIZED;
                if (bssls->type == ST_UDATA)
                  bssls->type = ST_DATA;
                bssls->filesize = bssls->size;
              }
              /* Warning: Intermediate uninitialized sections in ELF
                 segment will be turned into initialized */
              error(82,p->name,bss_start->name,
                    ((struct LinkedSection *)ls->n.pred)->name);
              bss_start = NULL;
            }
          }

          if (seg_lastsec && !bss_start) {
            if (ls->copybase >= seg_lastsec->copybase+seg_lastsec->filesize) {
              seg_lastsec->gapsize = ls->copybase - (seg_lastsec->copybase +
                                                     seg_lastsec->filesize);
            }
            else if (ls->copybase > 0) {
              ierror("elf32_segmentcheck(): overlapping sections "
                     "%s(%lx-%lx) followed by %s(%lx)",
                     seg_lastsec->name,seg_lastsec->copybase,
                     seg_lastsec->copybase + seg_lastsec->filesize,
                     ls->copybase);
            }
          }
          seg_lastsec = ls;
          if (!bss_start || !seg_lastdat)
            prg_lastdat = seg_lastdat = ls;
        }
      }

      /* calculate alignment gap for segment */
      /* @@@ do we align on LMA or VMA? */
      gapsize = (p->start & amask) - (foffs & amask);
      p->alignment_gap = gapsize<0 ? gapsize+amask+1 : gapsize;

      if (seg_lastdat)
        p->file_end = seg_lastdat->copybase + seg_lastdat->filesize;

      foffs += p->alignment_gap;
      p->offset = foffs;
      foffs += p->file_end - p->start;
    }
  }

  if (phdrs!=NULL && first!=NULL) {
    /* init PHDR segment using the first LOAD seg. which directly follows */
    phdrs->flags &= ~PHDR_PFMASK;
    phdrs->flags |= PF_R | PF_X;
    phdrs->start = first->start + sizeof(struct Elf32_Ehdr);
    phdrs->start_vma = phdrs->start;
    phdrs->mem_end = phdrs->start + headersize - sizeof(struct Elf32_Ehdr);
    phdrs->file_end = phdrs->mem_end;
    phdrs->offset = sizeof(struct Elf32_Ehdr);
  }

  for (p=gv->phdrlist,segcnt=0; p; p=p->next) {
    if ((p->flags&PHDR_USED)
        && p->start!=ADDR_NONE && p->start_vma!=ADDR_NONE) {
      segcnt++;

      if (p->type!=PT_LOAD && p->type!=PT_PHDR && p->type!=PT_NULL) {
        /* set segment permissions for remaining segment types */
        p->flags &= ~PHDR_PFMASK;
        for (ls=seg_lastdat=(struct LinkedSection *)gv->lnksec.first;
             ls->n.next!=NULL; ls=(struct LinkedSection *)ls->n.next) {
          if (ls->copybase>=(unsigned long)p->start && ls->size &&
              (ls->copybase+ls->size)<=(unsigned long)p->mem_end &&
              (ls->flags & SF_ALLOC)) {
            p->flags |= conv_perm_to_elf(ls->protection);
            seg_lastdat = ls;
          }
        }
        p->file_end = seg_lastdat->copybase + seg_lastdat->filesize;
      }
    }
  }

  return segcnt;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rdi, %r15
movzbl 0x50(%rdi), %eax
leaq 0x1941c(%rip), %rcx     # 0x2f190
movq (%rcx,%rax,8), %rax
callq *0x18(%rax)
movq %rax, %r14
leaq 0x1f8(%r15), %r13
movq %r13, %rbp
movq (%rbp), %rbp
testq %rbp, %rbp
je 0x15d9d
testb $0x10, 0x24(%rbp)
je 0x15d88
cmpl $0x6, 0x20(%rbp)
jne 0x15d88
addq $0x1c0, %r15            # imm = 0x1C0
pushq $-0x1
popq %r10
pushq $0x52
popq %rdi
xorl %r11d, %r11d
movq %r13, %r12
movq (%r12), %r12
testq %r12, %r12
je 0x16077
cmpl $0x1, 0x20(%r12)
jne 0x15db1
movzwl 0x24(%r12), %esi
testb $0x10, %sil
je 0x15db1
movq 0x30(%r12), %rax
cmpq $-0x1, %rax
je 0x15db1
movq 0x28(%r12), %rdx
cmpq $-0x1, %rdx
je 0x15db1
testq %rbp, %rbp
sete %r8b
movb 0x26(%r12), %cl
movq %r10, %r9
shlq %cl, %r9
andl $0xfff0, %esi           # imm = 0xFFF0
leal 0x4(%rsi), %ecx
movw %cx, 0x24(%r12)
testq %r11, %r11
cmoveq %r12, %r11
setne %cl
cmoveq %r14, %rbx
orb %r8b, %cl
movq %rbx, %r8
jne 0x15e62
orl $0xc04, %esi            # imm = 0xC04
movw %si, 0x24(%r12)
movq %rax, %rcx
subq %r14, %rcx
movq %r9, %rbx
andq %r9, %rcx
subq %r14, %rax
subq %rcx, %rax
movq %rax, 0x1deac(%rip)     # 0x33cf0
movq %rcx, 0x30(%r12)
testq %rdx, %rdx
je 0x15e59
addq %r14, %rax
subq %rax, %rdx
movq %rdx, 0x28(%r12)
movq %r12, %r11
xorl %r8d, %r8d
movq %rbx, %r9
movq %r9, %rdx
notq %rdx
movq %r15, %rbx
movq $0x0, 0x8(%rsp)
movq $0x0, (%rsp)
movq %r9, %rsi
xorl %r9d, %r9d
movq (%rbx), %rbx
cmpq $0x0, (%rbx)
je 0x16025
movq 0x38(%rbx), %rax
cmpq 0x30(%r12), %rax
jb 0x15e82
movq 0x48(%rbx), %rcx
testq %rcx, %rcx
je 0x15e82
addq %rax, %rcx
cmpq 0x40(%r12), %rcx
ja 0x15e82
movb 0x21(%rbx), %al
testb $0x1, %al
je 0x15e82
movq %rdx, 0x28(%rsp)
movq %rsi, 0x20(%rsp)
movb 0x22(%rbx), %cl
rolb $0x4, %cl
movl %ecx, %edx
shrb $0x2, %dl
movl %ecx, %esi
andb $0x10, %sil
shlb $0x2, %sil
orb %dl, %sil
andb $0x50, %sil
addb %sil, %sil
addb %cl, %cl
andb $0x40, %cl
orb %sil, %cl
shrb $0x5, %cl
movzbl %cl, %ecx
orw %cx, 0x24(%r12)
movb 0x23(%rbx), %cl
cmpb 0x26(%r12), %cl
jbe 0x15f00
movb %cl, 0x26(%r12)
testb $0x2, %al
movq 0x20(%rsp), %rsi
movq (%rsp), %rdx
movq %r8, 0x30(%rsp)
jne 0x15f3f
movq 0x8(%rsp), %rax
testq %rax, %rax
je 0x15f8e
cmpq %rbx, %rax
je 0x15f4d
andb $-0x3, 0x21(%rax)
cmpb $0x3, 0x20(%rax)
jne 0x15f2f
movb $0x2, 0x20(%rax)
movq (%rax), %rcx
movq 0x48(%rax), %rdx
movq %rdx, 0x50(%rax)
movq %rcx, %rax
jmp 0x15f1c
movq 0x8(%rsp), %rcx
testq %rcx, %rcx
cmoveq %rbx, %rcx
jmp 0x15f90
movq 0x8(%r12), %rsi
movq 0x8(%rsp), %rax
movq 0x18(%rax), %rdx
movq 0x8(%rbx), %rax
movq 0x18(%rax), %rcx
xorl %eax, %eax
movq %r11, 0x18(%rsp)
movq %r9, 0x10(%rsp)
callq 0x6c19
movq (%rsp), %rdx
movq 0x20(%rsp), %rsi
movq 0x18(%rsp), %r11
pushq $0x52
popq %rdi
pushq $-0x1
popq %r10
movq 0x10(%rsp), %r9
xorl %ecx, %ecx
testq %rdx, %rdx
sete %al
movq %rcx, 0x8(%rsp)
testq %rcx, %rcx
setne %cl
orb %al, %cl
jne 0x16001
movq 0x38(%rbx), %r8
movq 0x38(%rdx), %rax
movq 0x50(%rdx), %rcx
movq %rax, (%rsp)
addq %rax, %rcx
movq %r8, %rax
subq %rcx, %rax
jae 0x15ffd
testq %r8, %r8
je 0x16001
movq 0x18(%rdx), %rsi
leaq 0xb785(%rip), %rdi      # 0x21755
movq (%rsp), %rdx
xorl %eax, %eax
movq %r11, 0x18(%rsp)
movq %r9, 0x10(%rsp)
callq 0x6b2c
movq 0x20(%rsp), %rsi
movq 0x18(%rsp), %r11
pushq $0x52
popq %rdi
pushq $-0x1
popq %r10
movq 0x10(%rsp), %r9
jmp 0x16001
movq %rax, 0x58(%rdx)
testq %r9, %r9
cmoveq %rbx, %r9
cmpq $0x0, 0x8(%rsp)
cmoveq %rbx, %r9
movq %rbx, (%rsp)
movq 0x30(%rsp), %r8
movq 0x28(%rsp), %rdx
jmp 0x15e82
movq 0x30(%r12), %rcx
movq %rcx, %rax
andq %rdx, %rax
andq %r8, %rdx
subq %rdx, %rax
movq %rax, %rdx
sarq $0x3f, %rdx
andq %rsi, %rdx
subq %rdx, %rax
movq %rax, 0x50(%r12)
testq %r9, %r9
je 0x1605c
movq 0x50(%r9), %rdx
addq 0x38(%r9), %rdx
movq %rdx, 0x38(%r12)
jmp 0x16061
movq 0x38(%r12), %rdx
addq %r8, %rax
movq %rax, 0x48(%r12)
subq %rcx, %rax
addq %rdx, %rax
movq %rax, %rbx
jmp 0x15db1
testq %rbp, %rbp
je 0x160b1
testq %r11, %r11
je 0x160b1
movl 0x24(%rbp), %eax
andl $-0x10, %eax
orl $0x5, %eax
movw %ax, 0x24(%rbp)
movq 0x30(%r11), %rax
leaq 0x34(%rax), %rcx
movq %rcx, 0x30(%rbp)
movq %rcx, 0x28(%rbp)
addq %rax, %r14
movq %r14, 0x40(%rbp)
movq %r14, 0x38(%rbp)
movq $0x34, 0x48(%rbp)
xorl %eax, %eax
pushq $0x43
popq %rcx
movq (%r13), %r13
testq %r13, %r13
je 0x16180
movzwl 0x24(%r13), %edx
testb $0x10, %dl
je 0x160b6
movq 0x30(%r13), %rsi
cmpq $-0x1, %rsi
je 0x160b6
cmpq $-0x1, 0x28(%r13)
je 0x160b6
incl %eax
movl 0x20(%r13), %edi
cmpl $0x6, %edi
ja 0x160ee
btl %edi, %ecx
jb 0x160b6
andl $0xfff0, %edx           # imm = 0xFFF0
movw %dx, 0x24(%r13)
movq (%r15), %rdi
movq %rdi, %r9
movq %rdi, %r8
movq (%rdi), %rdi
testq %rdi, %rdi
je 0x1616f
movq 0x38(%r8), %r10
cmpq %rsi, %r10
jb 0x160ff
movq 0x48(%r8), %r11
testq %r11, %r11
je 0x160ff
addq %r10, %r11
cmpq 0x40(%r13), %r11
ja 0x160ff
testb $0x1, 0x21(%r8)
je 0x160ff
movb 0x22(%r8), %r9b
rolb $0x4, %r9b
movl %r9d, %r10d
shrb $0x2, %r10b
movl %r9d, %r11d
andb $0x10, %r11b
shlb $0x2, %r11b
orb %r10b, %r11b
andb $0x50, %r11b
addb %r11b, %r11b
addb %r9b, %r9b
andb $0x40, %r9b
orb %r11b, %r9b
shrb $0x5, %r9b
movzbl %r9b, %r9d
orl %r9d, %edx
movw %dx, 0x24(%r13)
movq %r8, %r9
jmp 0x160ff
movq 0x50(%r9), %rdx
addq 0x38(%r9), %rdx
movq %rdx, 0x38(%r13)
jmp 0x160b6
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq