// File: /workspace/github_c_makefile_star2_O1/shuffle2[P]nx2elf/elf_eh.cpp
// Function: ElfEHInfo::MeasureFrame(eh_frame_hdr const*, unsigned long*, unsigned long*)
bool ElfEHInfo::MeasureFrame(const eh_frame_hdr* hdr,
                             uintptr_t* eh_frame_ptr,
                             size_t* eh_frame_len) {
  if (hdr->version != 1) {
    return false;
  }
#define READ_RAW(type, ptr) \
  *(type*)ptr;              \
  ptr += sizeof(type);
  auto dw_decode = [&hdr](u8 enc, const u8*& buf, uintptr_t base = 0) {
    uintptr_t val = 0;
    if (base == 0) {
      base = (uintptr_t)buf;
    }
    if (enc == DW_EH_PE_omit) {
      // XXX hack for "nonexistant" value
      return (uintptr_t)0;
    }
    switch (enc & 0x70) {
    case DW_EH_PE_absptr:
      break;
    case DW_EH_PE_pcrel:
      val += base;
      break;
    case DW_EH_PE_datarel:
      val += (uintptr_t)hdr;
      break;
    default:
      fprintf(stderr, "unexpected enc base %02x\n", enc);
      break;
    }
    switch (enc & 0x0f) {
    case DW_EH_PE_udata2:
      val += READ_RAW(u16, buf);
      break;
    case DW_EH_PE_udata4:
      val += READ_RAW(u32, buf);
      break;
    case DW_EH_PE_sdata4:
      val += READ_RAW(s32, buf);
      break;
    default:
      fprintf(stderr, "unexpected enc type %02x\n", enc);
      break;
    }
    if (enc & DW_EH_PE_indirect) {
      val = *(uintptr_t*)val;
    }
    return val;
  };
  auto dw_fde_len = [](u32* fde_len, const u8* buf) {
    u32 len = READ_RAW(u32, buf);
    if (len == 0xffffffff) {
      return false;
    }
    *fde_len = len;
    return true;
  };
#undef READ_RAW

  const u8* ptr = (const u8*)&hdr[1];
  *eh_frame_ptr = dw_decode(hdr->eh_frame_ptr_enc, ptr);
  // XXX hack: default to len(eh_frame) == 8 if fde_count == 0
  *eh_frame_len = 8;
  size_t fde_count = dw_decode(hdr->fde_count_enc, ptr);
  uintptr_t max_ptr = 0;
  for (size_t i = 0; i < fde_count; i++) {
    auto func = dw_decode(hdr->table_enc, ptr);
    auto desc = dw_decode(hdr->table_enc, ptr);
    u32 fde_len;
    if (!dw_fde_len(&fde_len, (const u8*)desc)) {
      fprintf(stderr, "reading fde %zi failed\n", i);
      continue;
    }
    max_ptr = std::max(max_ptr, desc + fde_len);
  }
  if (max_ptr) {
    *eh_frame_len = max_ptr - *eh_frame_ptr;
  }
  return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movb (%rsi), %r15b
cmpb $0x1, %r15b
jne 0x4a0c
movq %rcx, %r14
movq %rdx, %r13
leaq 0x4(%rsi), %rcx
movzbl 0x1(%rsi), %r12d
cmpl $0xff, %r12d
movq %rsi, -0x38(%rbp)
je 0x4711
movl %r12d, %ebx
andl $0x70, %ebx
je 0x4718
cmpl $0x30, %ebx
je 0x4715
cmpl $0x10, %ebx
jne 0x4a22
movq %rcx, %rbx
jmp 0x4718
xorl %ebx, %ebx
jmp 0x4756
movq %rsi, %rbx
movl %r12d, %eax
andl $0xf, %eax
cmpl $0xb, %eax
je 0x473e
cmpl $0x3, %eax
je 0x4744
cmpl $0x2, %eax
jne 0x4a50
movzwl 0x4(%rsi), %eax
addq %rax, %rbx
leaq 0x6(%rsi), %rcx
jmp 0x474e
movslq 0x4(%rsi), %rax
jmp 0x4747
movl 0x4(%rsi), %eax
addq %rax, %rbx
leaq 0x8(%rsi), %rcx
testb %r12b, %r12b
jns 0x4756
movq (%rbx), %rbx
movq %rbx, (%r13)
movq $0x8, (%r14)
movzbl 0x2(%rsi), %r12d
cmpl $0xff, %r12d
je 0x478a
movl %r12d, %edx
andl $0x70, %edx
je 0x4791
cmpl $0x30, %edx
je 0x478e
cmpl $0x10, %edx
jne 0x4a7c
movq %rcx, %rdx
jmp 0x4791
xorl %edx, %edx
jmp 0x47cc
movq %rsi, %rdx
movl %r12d, %eax
andl $0xf, %eax
cmpl $0xb, %eax
je 0x47b6
cmpl $0x3, %eax
je 0x47bb
cmpl $0x2, %eax
jne 0x4aa8
movzwl (%rcx), %eax
addq %rax, %rdx
addq $0x2, %rcx
jmp 0x47c4
movslq (%rcx), %rax
jmp 0x47bd
movl (%rcx), %eax
addq %rax, %rdx
addq $0x4, %rcx
testb %r12b, %r12b
jns 0x47cc
movq (%rdx), %rdx
movq %r13, -0x50(%rbp)
movb %r15b, -0x29(%rbp)
movq %r14, -0x58(%rbp)
testq %rdx, %rdx
je 0x49f3
movabsq $0x1000000010001, %rdi  # imm = 0x1000000010001
xorl %r13d, %r13d
xorl %ebx, %ebx
movq %rdx, -0x40(%rbp)
movzbl 0x3(%rsi), %r12d
cmpl $0xff, %r12d
je 0x483e
movl %r12d, %eax
andl $0x70, %eax
cmpl $0x30, %eax
ja 0x490e
btq %rax, %rdi
jae 0x490e
movl %r12d, %eax
andl $0xf, %eax
cmpl $0xb, %eax
je 0x483a
cmpl $0x3, %eax
je 0x483a
cmpl $0x2, %eax
jne 0x4946
addq $0x2, %rcx
jmp 0x483e
addq $0x4, %rcx
movzbl 0x3(%rsi), %r14d
cmpl $0xff, %r14d
je 0x486a
movl %r14d, %r12d
andl $0x70, %r12d
je 0x4872
cmpl $0x30, %r12d
je 0x486f
cmpl $0x10, %r12d
jne 0x497e
movq %rcx, %r12
jmp 0x4872
xorl %r12d, %r12d
jmp 0x48ae
movq %rsi, %r12
movl %r14d, %eax
andl $0xf, %eax
cmpl $0xb, %eax
je 0x4897
cmpl $0x3, %eax
je 0x489c
cmpl $0x2, %eax
jne 0x49b9
movzwl (%rcx), %eax
addq %rax, %r12
addq $0x2, %rcx
jmp 0x48a5
movslq (%rcx), %rax
jmp 0x489e
movl (%rcx), %eax
addq %rax, %r12
addq $0x4, %rcx
testb %r14b, %r14b
jns 0x48ae
movq (%r12), %r12
movl (%r12), %eax
cmpl $-0x1, %eax
cmovnel %eax, %r15d
je 0x48d9
movl %r15d, %eax
addq %rax, %r12
cmpq %r12, %rbx
cmovbeq %r12, %rbx
incq %r13
cmpq %r13, %rdx
jne 0x47f4
jmp 0x49f5
movq 0x166f8(%rip), %rax     # 0x1afd8
movq (%rax), %rdi
leaq 0x1271a(%rip), %rsi     # 0x17004
movq %r13, %rdx
xorl %eax, %eax
movq %rcx, %r14
callq 0x2230
movabsq $0x1000000010001, %rdi  # imm = 0x1000000010001
movq -0x40(%rbp), %rdx
movq %r14, %rcx
movq -0x38(%rbp), %rsi
jmp 0x48c8
movq 0x166c3(%rip), %rax     # 0x1afd8
movq (%rax), %rdi
leaq 0x126fd(%rip), %rsi     # 0x1701c
movl %r12d, %edx
xorl %eax, %eax
movq %rcx, %r14
callq 0x2230
movabsq $0x1000000010001, %rdi  # imm = 0x1000000010001
movq -0x40(%rbp), %rdx
movq %r14, %rcx
movq -0x38(%rbp), %rsi
jmp 0x481b
movq 0x1668b(%rip), %rax     # 0x1afd8
movq (%rax), %rdi
leaq 0x126df(%rip), %rsi     # 0x17036
movl %r12d, %edx
xorl %eax, %eax
movq %rcx, %r14
callq 0x2230
movabsq $0x1000000010001, %rdi  # imm = 0x1000000010001
movq -0x40(%rbp), %rdx
movq %r14, %rcx
movq -0x38(%rbp), %rsi
jmp 0x483e
movq 0x16653(%rip), %rax     # 0x1afd8
movq (%rax), %rdi
leaq 0x1268d(%rip), %rsi     # 0x1701c
movl %r14d, %edx
xorl %eax, %eax
movq %rcx, %r12
callq 0x2230
movabsq $0x1000000010001, %rdi  # imm = 0x1000000010001
movq -0x40(%rbp), %rdx
movq %r12, %rcx
movq -0x38(%rbp), %rsi
xorl %r12d, %r12d
jmp 0x4872
movq 0x16618(%rip), %rax     # 0x1afd8
movq (%rax), %rdi
leaq 0x1266c(%rip), %rsi     # 0x17036
movl %r14d, %edx
xorl %eax, %eax
movq %rcx, -0x48(%rbp)
callq 0x2230
movabsq $0x1000000010001, %rdi  # imm = 0x1000000010001
movq -0x40(%rbp), %rdx
movq -0x48(%rbp), %rcx
movq -0x38(%rbp), %rsi
jmp 0x48a5
xorl %ebx, %ebx
testq %rbx, %rbx
movq -0x58(%rbp), %rax
movb -0x29(%rbp), %r15b
movq -0x50(%rbp), %rcx
je 0x4a0c
subq (%rcx), %rbx
movq %rbx, (%rax)
cmpb $0x1, %r15b
sete %al
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x165af(%rip), %rax     # 0x1afd8
movq (%rax), %rdi
leaq 0x125e9(%rip), %rsi     # 0x1701c
xorl %ebx, %ebx
movl %r12d, %edx
xorl %eax, %eax
movq %rcx, -0x48(%rbp)
callq 0x2230
movq -0x48(%rbp), %rcx
movq -0x38(%rbp), %rsi
jmp 0x4718
movq 0x16581(%rip), %rax     # 0x1afd8
movq (%rax), %rdi
leaq 0x125d5(%rip), %rsi     # 0x17036
movl %r12d, %edx
xorl %eax, %eax
movq %rcx, -0x48(%rbp)
callq 0x2230
movq -0x48(%rbp), %rcx
movq -0x38(%rbp), %rsi
jmp 0x474e
movq 0x16555(%rip), %rax     # 0x1afd8
movq (%rax), %rdi
leaq 0x1258f(%rip), %rsi     # 0x1701c
movl %r12d, %edx
xorl %eax, %eax
movq %rcx, %rbx
callq 0x2230
xorl %edx, %edx
movq %rbx, %rcx
movq -0x38(%rbp), %rsi
jmp 0x4791
movq 0x16529(%rip), %rax     # 0x1afd8
movq (%rax), %rdi
leaq 0x1257d(%rip), %rsi     # 0x17036
movq %rdx, -0x40(%rbp)
movl %r12d, %edx
xorl %eax, %eax
movq %rcx, %rbx
callq 0x2230
movq -0x40(%rbp), %rdx
movq %rbx, %rcx
movq -0x38(%rbp), %rsi
jmp 0x47c4
nop