// File: /workspace/github_c_makefile_star2_O1/mikeakohn[P]print_pe/build/../src/pdb.c
// Function: print_pdb_stream_info
void print_pdb_stream_info(
  struct pdb_dir_t *pdb_dir,
  struct pdb_header_t *pdb_header,
  FILE *in)
{
  //int total_length = pdb_dir->stream_sizes[1];
  int i;

  read_data(pdb_dir, 1, pdb_header->block_size, in);

  uint8_t *data = pdb_dir->heap;

  printf(" -- PDB Info Stream (index 1) --\n");

  printf("     version: %d\n", get_uint32(data + 0));
  printf("   signature: %d\n", get_uint32(data + 4));
  printf("         age: %d\n", get_uint32(data + 8));
  printf("        guid:");

  for (i = 0; i < 16; i++)
  {
    printf(" %02x", data[i + 12]);
  }
  printf("\n\n");

  // This is the length of the names section.
  int length = get_uint32(data + 28);

  uint8_t *names = data + 32;
  uint8_t *hash = names + length;

  uint32_t hash_size = get_uint32(hash + 0);
  uint32_t hash_capacity = get_uint32(hash + 4);
  uint32_t vector_words = get_uint32(hash + 8);

  printf("         hash_size: %d\n", hash_size);
  printf("     hash_capacity: %d\n", hash_capacity);
  printf("  bit_vector_count: %d\n", vector_words);
  printf("\n");

  printf("   index=0  /OldDirectory\n");
  printf("   index=1  /PDB (Stream Information)\n");
  printf("   index=2  /TPI (CodeView Type Records)\n");
  printf("   index=3  /DBI (Debug)\n");
  printf("   index=4  /IPI (CodeView Type Records)\n");

  // FIXME: According to some docs, the full hash is supposed to be in
  // the file. So the for loop below should be hash_capacity in length
  // and buckets are ignored by bits in the vector_mask. In the test file
  // though, doing that ends up with 11 words for a capacity of 6 (should
  // be 12 words in the file. Or maybe it's 10 words because the deleted
  // buckets is it's own word (as it's implemented here). This seems to work
  // though.

  hash += 12;

  //const uint32_t *vector_bits = (uint32_t *)hash;
  hash += vector_words * 4 * 2;

  for (i = 0; i < hash_size; i++)
  {
    //if ((vector_bits[ptr] & bit_mask) != 0)
    {
      uint32_t key = get_uint32(hash + 0);
      uint32_t value = get_uint32(hash + 4);
      const char *name = (char *)names + key;

      printf("%d: index=%-2d %s (offset=%d)\n", i, value, name, key);

      if (strcmp("/names", name) == 0)
      {
        pdb_dir->names_index = value;
      }
    }

    hash += 8;
  };

  printf("\n");
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rdx, %rcx
movq %rdi, %rbx
movl 0x58(%rsi), %edx
movl $0x1, %esi
callq 0x2ac3
movq %rbx, 0x30(%rsp)
movq 0x18(%rbx), %rbx
leaq 0x3b5c(%rip), %rdi      # 0x68de
callq 0x1060
movl (%rbx), %esi
leaq 0x2c64(%rip), %rdi      # 0x59f4
xorl %eax, %eax
callq 0x1090
movl 0x4(%rbx), %esi
leaq 0x2b97(%rip), %rdi      # 0x5938
xorl %eax, %eax
callq 0x1090
movl 0x8(%rbx), %esi
leaq 0x2fe6(%rip), %rdi      # 0x5d98
xorl %eax, %eax
callq 0x1090
leaq 0x2b8a(%rip), %rdi      # 0x594a
xorl %eax, %eax
callq 0x1090
leaq 0x2b8a(%rip), %r14      # 0x5958
xorl %r15d, %r15d
movzbl 0xc(%rbx,%r15), %esi
movq %r14, %rdi
xorl %eax, %eax
callq 0x1090
incq %r15
cmpq $0x10, %r15
jne 0x2dd1
leaq 0x3a2b(%rip), %rdi      # 0x681c
callq 0x1060
movslq 0x1c(%rbx), %r12
movzbl 0x20(%rbx,%r12), %ecx
movzbl 0x21(%rbx,%r12), %eax
shll $0x8, %eax
movq %rax, 0x28(%rsp)
movq %rcx, 0x18(%rsp)
leal (%rax,%rcx), %r15d
movzbl 0x22(%rbx,%r12), %eax
shll $0x10, %eax
movl %eax, 0x10(%rsp)
orl %eax, %r15d
movzbl 0x23(%rbx,%r12), %ebp
shll $0x18, %ebp
movl 0x24(%rbx,%r12), %eax
movl %eax, 0x14(%rsp)
movzbl 0x28(%rbx,%r12), %eax
movzbl 0x29(%rbx,%r12), %r13d
shll $0x8, %r13d
movq %rax, 0x20(%rsp)
leal (%rax,%r13), %r14d
movzbl 0x2a(%rbx,%r12), %eax
shll $0x10, %eax
movl %eax, 0xc(%rsp)
orl %eax, %r14d
movzbl 0x2b(%rbx,%r12), %eax
shll $0x18, %eax
movl %eax, 0x8(%rsp)
orl %eax, %r14d
leaq 0x2ae5(%rip), %rdi      # 0x595e
movl %r15d, %esi
orl %ebp, %esi
xorl %eax, %eax
callq 0x1090
leaq 0x2aea(%rip), %rdi      # 0x5976
movl 0x14(%rsp), %esi
xorl %eax, %eax
callq 0x1090
leaq 0x2af0(%rip), %rdi      # 0x598e
movl %r14d, %esi
xorl %eax, %eax
callq 0x1090
movl $0xa, %edi
callq 0x1040
leaq 0x3a46(%rip), %rdi      # 0x68ff
callq 0x1060
leaq 0x3a54(%rip), %rdi      # 0x6919
callq 0x1060
leaq 0x3a6e(%rip), %rdi      # 0x693f
callq 0x1060
leaq 0x3a8b(%rip), %rdi      # 0x6968
callq 0x1060
leaq 0x3a98(%rip), %rdi      # 0x6981
callq 0x1060
orl %ebp, %r15d
je 0x2f72
addl 0x10(%rsp), %ebp
movq 0x28(%rsp), %r15
addl 0x18(%rsp), %r15d
addl %ebp, %r15d
movl 0x8(%rsp), %eax
addl 0xc(%rsp), %eax
addl 0x20(%rsp), %r13d
addl %eax, %r13d
shll $0x3, %r13d
addq %r13, %r12
leaq (%rbx,%r12), %r14
addq $0x2c, %r14
addq $0x20, %rbx
xorl %r12d, %r12d
movl (%r14,%r12,8), %r8d
movl 0x4(%r14,%r12,8), %ebp
movq %r8, %r13
addq %rbx, %r13
leaq 0x2a66(%rip), %rdi      # 0x59a6
movl %r12d, %esi
movl %ebp, %edx
movq %r13, %rcx
xorl %eax, %eax
callq 0x1090
leaq 0x2a6f(%rip), %rdi      # 0x59c5
movq %r13, %rsi
callq 0x10b0
testl %eax, %eax
jne 0x2f6a
movq 0x30(%rsp), %rax
movl %ebp, 0x28(%rax)
incq %r12
cmpl %r12d, %r15d
jne 0x2f2a
movl $0xa, %edi
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x1040