// File: /workspace/github_c_makefile_star2_O1/barabo[P]advanced-shell-history/src/sqlite3.c
// Function: walIndexRecover
static int walIndexRecover(Wal *pWal){
  int rc;                         /* Return Code */
  i64 nSize;                      /* Size of log file */
  u32 aFrameCksum[2] = {0, 0};
  int iLock;                      /* Lock offset to lock for checkpoint */
  int nLock;                      /* Number of locks to hold */

  /* Obtain an exclusive lock on all byte in the locking range not already
  ** locked by the caller. The caller is guaranteed to have locked the
  ** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte.
  ** If successful, the same bytes that are locked here are unlocked before
  ** this function returns.
  */
  assert( pWal->ckptLock==1 || pWal->ckptLock==0 );
  assert( WAL_ALL_BUT_WRITE==WAL_WRITE_LOCK+1 );
  assert( WAL_CKPT_LOCK==WAL_ALL_BUT_WRITE );
  assert( pWal->writeLock );
  iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
  nLock = SQLITE_SHM_NLOCK - iLock;
  rc = walLockExclusive(pWal, iLock, nLock);
  if( rc ){
    return rc;
  }
  WALTRACE(("WAL%p: recovery begin...\n", pWal));

  memset(&pWal->hdr, 0, sizeof(WalIndexHdr));

  rc = sqlite3OsFileSize(pWal->pWalFd, &nSize);
  if( rc!=SQLITE_OK ){
    goto recovery_error;
  }

  if( nSize>WAL_HDRSIZE ){
    u8 aBuf[WAL_HDRSIZE];         /* Buffer to load WAL header into */
    u8 *aFrame = 0;               /* Malloc'd buffer to load entire frame */
    int szFrame;                  /* Number of bytes in buffer aFrame[] */
    u8 *aData;                    /* Pointer to data part of aFrame buffer */
    int iFrame;                   /* Index of last frame read */
    i64 iOffset;                  /* Next offset to read from log file */
    int szPage;                   /* Page size according to the log */
    u32 magic;                    /* Magic value read from WAL header */
    u32 version;                  /* Magic value read from WAL header */
    int isValid;                  /* True if this frame is valid */

    /* Read in the WAL header. */
    rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
    if( rc!=SQLITE_OK ){
      goto recovery_error;
    }

    /* If the database page size is not a power of two, or is greater than
    ** SQLITE_MAX_PAGE_SIZE, conclude that the WAL file contains no valid 
    ** data. Similarly, if the 'magic' value is invalid, ignore the whole
    ** WAL file.
    */
    magic = sqlite3Get4byte(&aBuf[0]);
    szPage = sqlite3Get4byte(&aBuf[8]);
    if( (magic&0xFFFFFFFE)!=WAL_MAGIC 
     || szPage&(szPage-1) 
     || szPage>SQLITE_MAX_PAGE_SIZE 
     || szPage<512 
    ){
      goto finished;
    }
    pWal->hdr.bigEndCksum = (u8)(magic&0x00000001);
    pWal->szPage = szPage;
    pWal->nCkpt = sqlite3Get4byte(&aBuf[12]);
    memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);

    /* Verify that the WAL header checksum is correct */
    walChecksumBytes(pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN, 
        aBuf, WAL_HDRSIZE-2*4, 0, pWal->hdr.aFrameCksum
    );
    if( pWal->hdr.aFrameCksum[0]!=sqlite3Get4byte(&aBuf[24])
     || pWal->hdr.aFrameCksum[1]!=sqlite3Get4byte(&aBuf[28])
    ){
      goto finished;
    }

    /* Verify that the version number on the WAL format is one that
    ** are able to understand */
    version = sqlite3Get4byte(&aBuf[4]);
    if( version!=WAL_MAX_VERSION ){
      rc = SQLITE_CANTOPEN_BKPT;
      goto finished;
    }

    /* Malloc a buffer to read frames into. */
    szFrame = szPage + WAL_FRAME_HDRSIZE;
    aFrame = (u8 *)sqlite3_malloc(szFrame);
    if( !aFrame ){
      rc = SQLITE_NOMEM;
      goto recovery_error;
    }
    aData = &aFrame[WAL_FRAME_HDRSIZE];

    /* Read all frames from the log file. */
    iFrame = 0;
    for(iOffset=WAL_HDRSIZE; (iOffset+szFrame)<=nSize; iOffset+=szFrame){
      u32 pgno;                   /* Database page number for frame */
      u32 nTruncate;              /* dbsize field from frame header */

      /* Read and decode the next log frame. */
      iFrame++;
      rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset);
      if( rc!=SQLITE_OK ) break;
      isValid = walDecodeFrame(pWal, &pgno, &nTruncate, aData, aFrame);
      if( !isValid ) break;
      rc = walIndexAppend(pWal, iFrame, pgno);
      if( rc!=SQLITE_OK ) break;

      /* If nTruncate is non-zero, this is a commit record. */
      if( nTruncate ){
        pWal->hdr.mxFrame = iFrame;
        pWal->hdr.nPage = nTruncate;
        pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
        testcase( szPage<=32768 );
        testcase( szPage>=65536 );
        aFrameCksum[0] = pWal->hdr.aFrameCksum[0];
        aFrameCksum[1] = pWal->hdr.aFrameCksum[1];
      }
    }

    sqlite3_free(aFrame);
  }

finished:
  if( rc==SQLITE_OK ){
    volatile WalCkptInfo *pInfo;
    int i;
    pWal->hdr.aFrameCksum[0] = aFrameCksum[0];
    pWal->hdr.aFrameCksum[1] = aFrameCksum[1];
    walIndexWriteHdr(pWal);

    /* Reset the checkpoint-header. This is safe because this thread is 
    ** currently holding locks that exclude all other readers, writers and
    ** checkpointers.
    */
    pInfo = walCkptInfo(pWal);
    pInfo->nBackfill = 0;
    pInfo->aReadMark[0] = 0;
    for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
    if( pWal->hdr.mxFrame ) pInfo->aReadMark[1] = pWal->hdr.mxFrame;

    /* If more than one frame was recovered from the log file, report an
    ** event via sqlite3_log(). This is to help with identifying performance
    ** problems caused by applications routinely shutting down without
    ** checkpointing the log file.
    */
    if( pWal->hdr.nPage ){
      sqlite3_log(SQLITE_NOTICE_RECOVER_WAL,
          "recovered %d frames from WAL file %s",
          pWal->hdr.mxFrame, pWal->zWalName
      );
    }
  }

recovery_error:
  WALTRACE(("WAL%p: recovery %s\n", pWal, rc ? "failed" : "ok"));
  walUnlockExclusive(pWal, iLock, nLock);
  return rc;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rdi, %r15
movzbl 0x41(%rdi), %ebx
movl $0x7, %r14d
subl %ebx, %r14d
incl %ebx
xorl %r13d, %r13d
cmpb $0x0, 0x3f(%rdi)
jne 0x1c320
movq 0x8(%r15), %rdi
movq (%rdi), %rax
movl %ebx, %esi
movl %r14d, %edx
movl $0xa, %ecx
callq *0x70(%rax)
movl %eax, %r13d
testl %r13d, %r13d
jne 0x1c4af
xorps %xmm0, %xmm0
movups %xmm0, 0x68(%r15)
movups %xmm0, 0x58(%r15)
movups %xmm0, 0x48(%r15)
movq 0x10(%r15), %rdi
movq (%rdi), %rax
leaq -0x50(%rbp), %rsi
callq *0x30(%rax)
movl %eax, %r13d
testl %eax, %eax
jne 0x1c494
xorl %edx, %edx
cmpq $0x21, -0x50(%rbp)
movl $0x0, %r12d
movl $0x0, %r13d
jl 0x1c42a
movq 0x10(%r15), %rdi
movq (%rdi), %rax
leaq -0x80(%rbp), %rsi
movl $0x20, %edx
xorl %ecx, %ecx
callq *0x10(%rax)
movl $0x2, %esi
testl %eax, %eax
je 0x1c398
movl %eax, %r13d
xorl %r12d, %r12d
xorl %edx, %edx
jmp 0x1c418
movl -0x80(%rbp), %eax
shll $0x18, %eax
movzbl -0x7f(%rbp), %ecx
shll $0x10, %ecx
orl %eax, %ecx
movzbl -0x7e(%rbp), %eax
shll $0x8, %eax
orl %ecx, %eax
movzbl -0x7d(%rbp), %edi
movl %edi, %ecx
andl $-0x2, %ecx
orl %eax, %ecx
xorl %edx, %edx
movl $0x3, %esi
cmpl $0x377f0682, %ecx       # imm = 0x377F0682
jne 0x1c412
movl -0x78(%rbp), %eax
shll $0x18, %eax
movzbl -0x77(%rbp), %r12d
shll $0x10, %r12d
orl %eax, %r12d
movzbl -0x76(%rbp), %r9d
shll $0x8, %r9d
movzbl -0x75(%rbp), %r8d
orl %r12d, %r8d
orl %r9d, %r8d
leal -0x1(%r8), %eax
testl %eax, %r8d
setne %al
leal -0x10001(%r8), %ecx
cmpl $0xffff01ff, %ecx       # imm = 0xFFFF01FF
setb %cl
orb %al, %cl
je 0x1c4c1
xorl %r12d, %r12d
xorl %r13d, %r13d
movl %esi, %eax
leaq 0x58d77(%rip), %rcx     # 0x75198
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
testl %r13d, %r13d
jne 0x1c494
movl %r12d, 0x60(%r15)
movl %edx, 0x64(%r15)
movq %r15, %rdi
callq 0x1bbb8
movq 0x30(%r15), %rax
movq (%rax), %rax
xorl %ecx, %ecx
movl %ecx, 0x60(%rax)
movl %ecx, 0x64(%rax)
movl $0xffffffff, 0x68(%rax,%rcx,4) # imm = 0xFFFFFFFF
incq %rcx
cmpq $0x4, %rcx
jne 0x1c44e
movl 0x58(%r15), %ecx
testl %ecx, %ecx
je 0x1c46a
movl %ecx, 0x68(%rax)
cmpl $0x0, 0x5c(%r15)
je 0x1c491
movl 0x58(%r15), %edx
movq 0x78(%r15), %rcx
leaq 0x5d355(%rip), %rsi     # 0x797d5
xorl %r13d, %r13d
movl $0x11b, %edi            # imm = 0x11B
xorl %eax, %eax
callq 0xb8cc
jmp 0x1c494
xorl %r13d, %r13d
cmpb $0x0, 0x3f(%r15)
jne 0x1c4af
movq 0x8(%r15), %rdi
movq (%rdi), %rax
movl %ebx, %esi
movl %r14d, %edx
movl $0x9, %ecx
callq *0x70(%rax)
movl %r13d, %eax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %r9d, -0x30(%rbp)
andl $0x1, %edi
movb %dil, 0x55(%r15)
movq %r8, -0x48(%rbp)
movl %r8d, 0x38(%r15)
leaq -0x80(%rbp), %r13
movl 0xc(%r13), %eax
bswapl %eax
movl %eax, 0x80(%r15)
movq 0x10(%r13), %rax
movq %rax, 0x68(%r15)
xorl $0x1, %edi
leaq 0x60(%r15), %r8
movq %r13, %rsi
movl $0x18, %edx
xorl %ecx, %ecx
callq 0x1b887
movl 0x18(%r13), %eax
bswapl %eax
cmpl %eax, 0x60(%r15)
jne 0x1c55b
movl %r12d, -0x34(%rbp)
movl -0x64(%rbp), %eax
bswapl %eax
movl $0x0, %r12d
movl $0x0, %r13d
cmpl %eax, 0x64(%r15)
movl $0x0, %edx
movl $0x3, %esi
jne 0x1c418
movl -0x7c(%rbp), %eax
bswapl %eax
cmpl $0x2de218, %eax         # imm = 0x2DE218
jne 0x1c56d
movq -0x48(%rbp), %r12
addl $0x18, %r12d
callq 0x9d1f
xorl %edx, %edx
testl %eax, %eax
je 0x1c5ae
xorl %esi, %esi
jmp 0x1c5bb
xorl %r12d, %r12d
xorl %r13d, %r13d
xorl %edx, %edx
movl $0x3, %esi
jmp 0x1c418
leaq 0x5d168(%rip), %rsi     # 0x796dc
leaq 0x5cfbe(%rip), %rcx     # 0x79539
movl $0xe, %r13d
movl $0xe, %edi
movl $0xb64b, %edx           # imm = 0xB64B
xorl %eax, %eax
callq 0xb8cc
xorl %edx, %edx
movl $0x3, %eax
movl %eax, %eax
leaq 0x58bf6(%rip), %rcx     # 0x75198
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
xorl %r12d, %r12d
jmpq *%rax
movl %r12d, %edi
callq 0xa2a2
xorl %edx, %edx
movq %rax, %rsi
testq %rsi, %rsi
je 0x1c6d3
movq %r12, -0x48(%rbp)
movl %r12d, %eax
movq %rax, -0x90(%rbp)
addq $0x20, %rax
movl $0x0, %edx
movl $0x0, %r12d
cmpq -0x50(%rbp), %rax
jg 0x1c6ea
leaq 0x18(%rsi), %rax
movq %rax, -0x88(%rbp)
movl -0x34(%rbp), %eax
shrl $0x10, %eax
orl -0x30(%rbp), %eax
movl %eax, -0x34(%rbp)
xorl %r12d, %r12d
movl $0x20, %ecx
movl $0x1, -0x38(%rbp)
xorl %edx, %edx
movq %rsi, -0x40(%rbp)
movq %rdx, -0x30(%rbp)
movq 0x10(%r15), %rdi
movq (%rdi), %rax
movq -0x48(%rbp), %rdx
movq %rcx, -0x98(%rbp)
callq *0x10(%rax)
xorl %r13d, %r13d
testl %eax, %eax
je 0x1c66b
xorl %ecx, %ecx
movl %eax, %r13d
movq -0x30(%rbp), %rdx
testb %cl, %cl
je 0x1c6e6
movq -0x90(%rbp), %rax
movq -0x98(%rbp), %rcx
addq %rax, %rcx
addq %rcx, %rax
incl -0x38(%rbp)
cmpq -0x50(%rbp), %rax
movq -0x40(%rbp), %rsi
jle 0x1c617
jmp 0x1c6ea
movq %r15, %rdi
leaq -0x58(%rbp), %rsi
leaq -0x54(%rbp), %rdx
movq -0x88(%rbp), %rcx
movq -0x40(%rbp), %r8
callq 0x1c701
testl %eax, %eax
je 0x1c6cc
movl -0x58(%rbp), %edx
movq %r15, %rdi
movl -0x38(%rbp), %esi
callq 0x1ba60
xorl %r13d, %r13d
testl %eax, %eax
jne 0x1c637
movl -0x54(%rbp), %eax
movb $0x1, %cl
testl %eax, %eax
movq -0x30(%rbp), %rdx
je 0x1c640
movl -0x38(%rbp), %edx
movl %edx, 0x58(%r15)
movl %eax, 0x5c(%r15)
movl -0x34(%rbp), %eax
movw %ax, 0x56(%r15)
movl 0x60(%r15), %r12d
movl 0x64(%r15), %edx
jmp 0x1c640
xorl %ecx, %ecx
jmp 0x1c63c
movl $0x7, %r13d
movl $0x2, %esi
xorl %r12d, %r12d
jmp 0x1c418
movq -0x40(%rbp), %rsi
movq %rdx, -0x30(%rbp)
movq %rsi, %rdi
callq 0xa2e8
movq -0x30(%rbp), %rdx
xorl %esi, %esi
jmp 0x1c418