// File: /workspace/github_c_makefile_star2_O3/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
pushq %rax
movq %rdx, %rcx
movq %rdi, %rbx
movl 0x58(%rsi), %edx
movl $0x1, %esi
callq 0x2aaa
movq %rbx, (%rsp)
movq 0x18(%rbx), %r15
leaq 0x3b7d(%rip), %rdi      # 0x68de
callq 0x1060
movl (%r15), %esi
leaq 0x2c84(%rip), %rdi      # 0x59f4
xorl %eax, %eax
callq 0x1090
movl 0x4(%r15), %esi
leaq 0x2bb6(%rip), %rdi      # 0x5938
xorl %eax, %eax
callq 0x1090
movl 0x8(%r15), %esi
leaq 0x3004(%rip), %rdi      # 0x5d98
xorl %eax, %eax
callq 0x1090
leaq 0x2ba8(%rip), %rdi      # 0x594a
xorl %eax, %eax
callq 0x1090
leaq 0x2ba8(%rip), %r14      # 0x5958
xorl %ebx, %ebx
movzbl 0xc(%r15,%rbx), %esi
movq %r14, %rdi
xorl %eax, %eax
callq 0x1090
incq %rbx
cmpq $0x10, %rbx
jne 0x2db2
leaq 0x3a4a(%rip), %rdi      # 0x681c
callq 0x1060
movslq 0x1c(%r15), %r12
movl 0x20(%r15,%r12), %r14d
movl 0x24(%r15,%r12), %ebp
movl 0x28(%r15,%r12), %ebx
leaq 0x2b6d(%rip), %rdi      # 0x595e
movl %r14d, %esi
xorl %eax, %eax
callq 0x1090
leaq 0x2b74(%rip), %rdi      # 0x5976
movl %ebp, %esi
xorl %eax, %eax
callq 0x1090
leaq 0x2b7c(%rip), %rdi      # 0x598e
movl %ebx, %esi
xorl %eax, %eax
callq 0x1090
movl $0xa, %edi
callq 0x1040
leaq 0x3ad3(%rip), %rdi      # 0x68ff
callq 0x1060
leaq 0x3ae1(%rip), %rdi      # 0x6919
callq 0x1060
leaq 0x3afb(%rip), %rdi      # 0x693f
callq 0x1060
leaq 0x3b18(%rip), %rdi      # 0x6968
callq 0x1060
leaq 0x3b25(%rip), %rdi      # 0x6981
callq 0x1060
testq %r14, %r14
je 0x2ec7
leaq (%r15,%r12), %rax
addq $0x20, %rax
addq $0x20, %r15
shll $0x3, %ebx
leaq (%rax,%rbx), %r12
addq $0xc, %r12
xorl %r13d, %r13d
movl (%r12,%r13,8), %r8d
movl 0x4(%r12,%r13,8), %ebp
movq %r8, %rbx
addq %r15, %rbx
leaq 0x2b10(%rip), %rdi      # 0x59a6
movl %r13d, %esi
movl %ebp, %edx
movq %rbx, %rcx
xorl %eax, %eax
callq 0x1090
leaq 0x2b19(%rip), %rdi      # 0x59c5
movq %rbx, %rsi
callq 0x10b0
testl %eax, %eax
jne 0x2ebf
movq (%rsp), %rax
movl %ebp, 0x28(%rax)
incq %r13
cmpl %r13d, %r14d
jne 0x2e80
movl $0xa, %edi
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x1040