// File: /workspace/github_c_makefile_star2_O3/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
cmpb $0x0, 0x3f(%rdi)
je 0x1c3ad
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 0x1c43b
xorl %r12d, %r12d
cmpq $0x21, -0x50(%rbp)
movl $0x0, %eax
movl $0x0, %ecx
jl 0x1c3d5
movq 0x10(%r15), %rdi
movq (%rdi), %rax
leaq -0x80(%rbp), %rsi
movl $0x20, %edx
xorl %ecx, %ecx
callq *0x10(%rax)
movl %eax, %r13d
testl %eax, %eax
jne 0x1c43b
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
cmpl $0x377f0682, %ecx       # imm = 0x377F0682
jne 0x1c3d1
movl -0x78(%rbp), %eax
shll $0x18, %eax
movzbl -0x77(%rbp), %ecx
shll $0x10, %ecx
orl %eax, %ecx
movzbl -0x76(%rbp), %eax
shll $0x8, %eax
movzbl -0x75(%rbp), %edx
movl %ecx, -0x38(%rbp)
orl %ecx, %edx
movl %eax, -0x2c(%rbp)
orl %eax, %edx
leal -0x1(%rdx), %eax
testl %eax, %edx
setne %al
leal -0x10001(%rdx), %ecx
cmpl $0xffff01ff, %ecx       # imm = 0xFFFF01FF
setb %cl
orb %al, %cl
jne 0x1c3d1
andl $0x1, %edi
movb %dil, 0x55(%r15)
movl %edx, 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
movq %rdx, -0x48(%rbp)
movl $0x18, %edx
xorl %ecx, %ecx
callq 0x1b70c
movl 0x18(%r13), %eax
bswapl %eax
cmpl %eax, 0x60(%r15)
jne 0x1c3d1
movl -0x64(%rbp), %eax
bswapl %eax
cmpl %eax, 0x64(%r15)
jne 0x1c3d1
movl -0x7c(%rbp), %eax
bswapl %eax
cmpl $0x2de218, %eax         # imm = 0x2DE218
jne 0x1c468
callq 0x9d86
movl $0x7, %r13d
testl %eax, %eax
jne 0x1c43b
movq -0x48(%rbp), %rdi
addl $0x18, %edi
movq %rdi, -0x48(%rbp)
callq 0xa38c
testq %rax, %rax
je 0x1c43b
movq %rax, %rsi
movq -0x48(%rbp), %rdx
movl %edx, %eax
movq %rax, -0x90(%rbp)
addq $0x20, %rax
movl $0x0, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
cmpq -0x50(%rbp), %rax
jle 0x1c488
movq %rsi, %rdi
callq 0xa3c7
movl -0x34(%rbp), %eax
movl -0x30(%rbp), %ecx
jmp 0x1c3d5
movq 0x8(%r15), %rdi
movq (%rdi), %rax
movl %ebx, %esi
movl %r14d, %edx
movl $0xa, %ecx
callq *0x70(%rax)
movl %eax, %r13d
testl %eax, %eax
jne 0x1c456
jmp 0x1c203
xorl %eax, %eax
xorl %ecx, %ecx
movl %eax, 0x60(%r15)
movl %ecx, 0x64(%r15)
movq %r15, %rdi
callq 0x1ba11
movq 0x30(%r15), %rax
movq (%rax), %rax
movl %r12d, 0x60(%rax)
movl %r12d, 0x64(%rax)
movl $0xffffffff, 0x68(%rax,%r12,4) # imm = 0xFFFFFFFF
incq %r12
cmpq $0x4, %r12
jne 0x1c3f4
movl 0x58(%r15), %ecx
testl %ecx, %ecx
je 0x1c411
movl %ecx, 0x68(%rax)
cmpl $0x0, 0x5c(%r15)
je 0x1c438
movl 0x58(%r15), %edx
movq 0x78(%r15), %rcx
leaq 0x5d3ae(%rip), %rsi     # 0x797d5
xorl %r13d, %r13d
movl $0x11b, %edi            # imm = 0x11B
xorl %eax, %eax
callq 0xb9c7
jmp 0x1c43b
xorl %r13d, %r13d
cmpb $0x0, 0x3f(%r15)
jne 0x1c456
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
leaq 0x5d26d(%rip), %rsi     # 0x796dc
leaq 0x5d0c3(%rip), %rcx     # 0x79539
movl $0xe, %r13d
movl $0xe, %edi
movl $0xb64b, %edx           # imm = 0xB64B
jmp 0x1c42f
movq %rsi, %rax
addq $0x18, %rax
movq %rax, -0x88(%rbp)
movl -0x38(%rbp), %eax
shrl $0x10, %eax
orl -0x2c(%rbp), %eax
movl %eax, -0x38(%rbp)
movl $0x0, -0x34(%rbp)
movl $0x20, %ecx
movl $0x1, -0x2c(%rbp)
movl $0x0, -0x30(%rbp)
movq %rsi, -0x40(%rbp)
movq 0x10(%r15), %rdi
movq (%rdi), %rax
movq %rcx, -0x98(%rbp)
callq *0x10(%rax)
testl %eax, %eax
jne 0x1c562
movq %r15, %rdi
leaq -0x58(%rbp), %rsi
leaq -0x54(%rbp), %rdx
movq -0x88(%rbp), %rcx
movq -0x40(%rbp), %r8
callq 0x1c57c
testl %eax, %eax
je 0x1c573
movl -0x58(%rbp), %edx
movq %r15, %rdi
movl -0x2c(%rbp), %esi
callq 0x1b8de
testl %eax, %eax
jne 0x1c562
movl -0x54(%rbp), %eax
testl %eax, %eax
movq -0x48(%rbp), %rdx
movq -0x40(%rbp), %rsi
movq -0x98(%rbp), %rcx
movl -0x2c(%rbp), %edi
je 0x1c541
movl %edi, 0x58(%r15)
movl %eax, 0x5c(%r15)
movl -0x38(%rbp), %eax
movw %ax, 0x56(%r15)
movl 0x60(%r15), %eax
movl %eax, -0x34(%rbp)
movl 0x64(%r15), %eax
movl %eax, -0x30(%rbp)
movq -0x90(%rbp), %rax
addq %rax, %rcx
addq %rcx, %rax
incl %edi
movl %edi, -0x2c(%rbp)
cmpq -0x50(%rbp), %rax
jle 0x1c4c0
jmp 0x1c39d
movl %eax, %r13d
movq -0x40(%rbp), %rdi
callq 0xa3c7
jmp 0x1c43b
movq -0x40(%rbp), %rdi
jmp 0x1c3a0