Home | History | Annotate | Line # | Download | only in bfd
pdb.c revision 1.1.1.1.4.2
      1  1.1.1.1.4.2  perseant /* BFD back-end for PDB Multi-Stream Format archives.
      2  1.1.1.1.4.2  perseant    Copyright (C) 2022 Free Software Foundation, Inc.
      3  1.1.1.1.4.2  perseant 
      4  1.1.1.1.4.2  perseant    This file is part of BFD, the Binary File Descriptor library.
      5  1.1.1.1.4.2  perseant 
      6  1.1.1.1.4.2  perseant    This program is free software; you can redistribute it and/or modify
      7  1.1.1.1.4.2  perseant    it under the terms of the GNU General Public License as published by
      8  1.1.1.1.4.2  perseant    the Free Software Foundation; either version 3 of the License, or
      9  1.1.1.1.4.2  perseant    (at your option) any later version.
     10  1.1.1.1.4.2  perseant 
     11  1.1.1.1.4.2  perseant    This program is distributed in the hope that it will be useful,
     12  1.1.1.1.4.2  perseant    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  1.1.1.1.4.2  perseant    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  1.1.1.1.4.2  perseant    GNU General Public License for more details.
     15  1.1.1.1.4.2  perseant 
     16  1.1.1.1.4.2  perseant    You should have received a copy of the GNU General Public License
     17  1.1.1.1.4.2  perseant    along with this program; if not, write to the Free Software
     18  1.1.1.1.4.2  perseant    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     19  1.1.1.1.4.2  perseant    MA 02110-1301, USA.  */
     20  1.1.1.1.4.2  perseant 
     21  1.1.1.1.4.2  perseant /* This describes the MSF file archive format, which is used for the
     22  1.1.1.1.4.2  perseant    PDB debug info generated by MSVC. See https://llvm.org/docs/PDB/MsfFile.html
     23  1.1.1.1.4.2  perseant    for a full description of the format.  */
     24  1.1.1.1.4.2  perseant 
     25  1.1.1.1.4.2  perseant #include "sysdep.h"
     26  1.1.1.1.4.2  perseant #include "bfd.h"
     27  1.1.1.1.4.2  perseant #include "libbfd.h"
     28  1.1.1.1.4.2  perseant 
     29  1.1.1.1.4.2  perseant /* "Microsoft C/C++ MSF 7.00\r\n\x1a\x44\x53\0\0\0" */
     30  1.1.1.1.4.2  perseant static const uint8_t pdb_magic[] =
     31  1.1.1.1.4.2  perseant { 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66,
     32  1.1.1.1.4.2  perseant   0x74, 0x20, 0x43, 0x2f, 0x43, 0x2b, 0x2b, 0x20,
     33  1.1.1.1.4.2  perseant   0x4d, 0x53, 0x46, 0x20, 0x37, 0x2e, 0x30, 0x30,
     34  1.1.1.1.4.2  perseant   0x0d, 0x0a, 0x1a, 0x44, 0x53, 0x00, 0x00, 0x00 };
     35  1.1.1.1.4.2  perseant 
     36  1.1.1.1.4.2  perseant #define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data))
     37  1.1.1.1.4.2  perseant 
     38  1.1.1.1.4.2  perseant static bfd_cleanup
     39  1.1.1.1.4.2  perseant pdb_archive_p (bfd *abfd)
     40  1.1.1.1.4.2  perseant {
     41  1.1.1.1.4.2  perseant   int ret;
     42  1.1.1.1.4.2  perseant   char magic[sizeof (pdb_magic)];
     43  1.1.1.1.4.2  perseant 
     44  1.1.1.1.4.2  perseant   ret = bfd_bread (magic, sizeof (magic), abfd);
     45  1.1.1.1.4.2  perseant   if (ret != sizeof (magic))
     46  1.1.1.1.4.2  perseant     {
     47  1.1.1.1.4.2  perseant       bfd_set_error (bfd_error_wrong_format);
     48  1.1.1.1.4.2  perseant       return NULL;
     49  1.1.1.1.4.2  perseant     }
     50  1.1.1.1.4.2  perseant 
     51  1.1.1.1.4.2  perseant   if (memcmp (magic, pdb_magic, sizeof (magic)))
     52  1.1.1.1.4.2  perseant     {
     53  1.1.1.1.4.2  perseant       bfd_set_error (bfd_error_wrong_format);
     54  1.1.1.1.4.2  perseant       return NULL;
     55  1.1.1.1.4.2  perseant     }
     56  1.1.1.1.4.2  perseant 
     57  1.1.1.1.4.2  perseant   void *tdata = bfd_zalloc (abfd, sizeof (struct artdata));
     58  1.1.1.1.4.2  perseant   if (tdata == NULL)
     59  1.1.1.1.4.2  perseant     return NULL;
     60  1.1.1.1.4.2  perseant   bfd_ardata (abfd) = tdata;
     61  1.1.1.1.4.2  perseant 
     62  1.1.1.1.4.2  perseant   return _bfd_no_cleanup;
     63  1.1.1.1.4.2  perseant }
     64  1.1.1.1.4.2  perseant 
     65  1.1.1.1.4.2  perseant static bfd *
     66  1.1.1.1.4.2  perseant pdb_get_elt_at_index (bfd *abfd, symindex sym_index)
     67  1.1.1.1.4.2  perseant {
     68  1.1.1.1.4.2  perseant   char int_buf[sizeof (uint32_t)];
     69  1.1.1.1.4.2  perseant   uint32_t block_size, block_map_addr, block, num_files;
     70  1.1.1.1.4.2  perseant   uint32_t first_dir_block, dir_offset, file_size, block_off, left;
     71  1.1.1.1.4.2  perseant   char name[10];
     72  1.1.1.1.4.2  perseant   bfd *file;
     73  1.1.1.1.4.2  perseant   char *buf;
     74  1.1.1.1.4.2  perseant 
     75  1.1.1.1.4.2  perseant   /* Get block_size.  */
     76  1.1.1.1.4.2  perseant 
     77  1.1.1.1.4.2  perseant   if (bfd_seek (abfd, sizeof (pdb_magic), SEEK_SET))
     78  1.1.1.1.4.2  perseant     return NULL;
     79  1.1.1.1.4.2  perseant 
     80  1.1.1.1.4.2  perseant   if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t))
     81  1.1.1.1.4.2  perseant     {
     82  1.1.1.1.4.2  perseant       bfd_set_error (bfd_error_malformed_archive);
     83  1.1.1.1.4.2  perseant       return NULL;
     84  1.1.1.1.4.2  perseant     }
     85  1.1.1.1.4.2  perseant 
     86  1.1.1.1.4.2  perseant   block_size = bfd_getl32 (int_buf);
     87  1.1.1.1.4.2  perseant   if ((block_size & -block_size) != block_size
     88  1.1.1.1.4.2  perseant       || block_size < 512
     89  1.1.1.1.4.2  perseant       || block_size > 4096)
     90  1.1.1.1.4.2  perseant     {
     91  1.1.1.1.4.2  perseant       bfd_set_error (bfd_error_malformed_archive);
     92  1.1.1.1.4.2  perseant       return NULL;
     93  1.1.1.1.4.2  perseant     }
     94  1.1.1.1.4.2  perseant 
     95  1.1.1.1.4.2  perseant   /* Get block_map_addr.  */
     96  1.1.1.1.4.2  perseant 
     97  1.1.1.1.4.2  perseant   if (bfd_seek (abfd, 4 * sizeof (uint32_t), SEEK_CUR))
     98  1.1.1.1.4.2  perseant     return NULL;
     99  1.1.1.1.4.2  perseant 
    100  1.1.1.1.4.2  perseant   if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    101  1.1.1.1.4.2  perseant     {
    102  1.1.1.1.4.2  perseant       bfd_set_error (bfd_error_malformed_archive);
    103  1.1.1.1.4.2  perseant       return NULL;
    104  1.1.1.1.4.2  perseant     }
    105  1.1.1.1.4.2  perseant 
    106  1.1.1.1.4.2  perseant   block_map_addr = bfd_getl32 (int_buf);
    107  1.1.1.1.4.2  perseant 
    108  1.1.1.1.4.2  perseant   /* Get num_files.  */
    109  1.1.1.1.4.2  perseant 
    110  1.1.1.1.4.2  perseant   if (bfd_seek (abfd, block_map_addr * block_size, SEEK_SET))
    111  1.1.1.1.4.2  perseant     return NULL;
    112  1.1.1.1.4.2  perseant 
    113  1.1.1.1.4.2  perseant   if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    114  1.1.1.1.4.2  perseant     {
    115  1.1.1.1.4.2  perseant       bfd_set_error (bfd_error_malformed_archive);
    116  1.1.1.1.4.2  perseant       return NULL;
    117  1.1.1.1.4.2  perseant     }
    118  1.1.1.1.4.2  perseant 
    119  1.1.1.1.4.2  perseant   first_dir_block = bfd_getl32 (int_buf);
    120  1.1.1.1.4.2  perseant 
    121  1.1.1.1.4.2  perseant   if (bfd_seek (abfd, first_dir_block * block_size, SEEK_SET))
    122  1.1.1.1.4.2  perseant     return NULL;
    123  1.1.1.1.4.2  perseant 
    124  1.1.1.1.4.2  perseant   if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    125  1.1.1.1.4.2  perseant     {
    126  1.1.1.1.4.2  perseant       bfd_set_error (bfd_error_malformed_archive);
    127  1.1.1.1.4.2  perseant       return NULL;
    128  1.1.1.1.4.2  perseant     }
    129  1.1.1.1.4.2  perseant 
    130  1.1.1.1.4.2  perseant   num_files = bfd_getl32 (int_buf);
    131  1.1.1.1.4.2  perseant 
    132  1.1.1.1.4.2  perseant   if (sym_index >= num_files)
    133  1.1.1.1.4.2  perseant     {
    134  1.1.1.1.4.2  perseant       bfd_set_error (bfd_error_no_more_archived_files);
    135  1.1.1.1.4.2  perseant       return NULL;
    136  1.1.1.1.4.2  perseant     }
    137  1.1.1.1.4.2  perseant 
    138  1.1.1.1.4.2  perseant   /* Read file size.  */
    139  1.1.1.1.4.2  perseant 
    140  1.1.1.1.4.2  perseant   dir_offset = sizeof (uint32_t) * (sym_index + 1);
    141  1.1.1.1.4.2  perseant 
    142  1.1.1.1.4.2  perseant   if (dir_offset >= block_size)
    143  1.1.1.1.4.2  perseant     {
    144  1.1.1.1.4.2  perseant       uint32_t block_map_addr_off;
    145  1.1.1.1.4.2  perseant 
    146  1.1.1.1.4.2  perseant       block_map_addr_off = ((dir_offset / block_size) * sizeof (uint32_t));
    147  1.1.1.1.4.2  perseant 
    148  1.1.1.1.4.2  perseant       if (bfd_seek (abfd, (block_map_addr * block_size) + block_map_addr_off,
    149  1.1.1.1.4.2  perseant 		    SEEK_SET))
    150  1.1.1.1.4.2  perseant 	return NULL;
    151  1.1.1.1.4.2  perseant 
    152  1.1.1.1.4.2  perseant       if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    153  1.1.1.1.4.2  perseant 	{
    154  1.1.1.1.4.2  perseant 	  bfd_set_error (bfd_error_malformed_archive);
    155  1.1.1.1.4.2  perseant 	  return NULL;
    156  1.1.1.1.4.2  perseant 	}
    157  1.1.1.1.4.2  perseant 
    158  1.1.1.1.4.2  perseant       block = bfd_getl32 (int_buf);
    159  1.1.1.1.4.2  perseant     }
    160  1.1.1.1.4.2  perseant   else
    161  1.1.1.1.4.2  perseant     {
    162  1.1.1.1.4.2  perseant       block = first_dir_block;
    163  1.1.1.1.4.2  perseant     }
    164  1.1.1.1.4.2  perseant 
    165  1.1.1.1.4.2  perseant   if (bfd_seek (abfd, (block * block_size) + (dir_offset % block_size),
    166  1.1.1.1.4.2  perseant 		SEEK_SET))
    167  1.1.1.1.4.2  perseant     return NULL;
    168  1.1.1.1.4.2  perseant 
    169  1.1.1.1.4.2  perseant   if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    170  1.1.1.1.4.2  perseant     {
    171  1.1.1.1.4.2  perseant       bfd_set_error (bfd_error_malformed_archive);
    172  1.1.1.1.4.2  perseant       return NULL;
    173  1.1.1.1.4.2  perseant     }
    174  1.1.1.1.4.2  perseant 
    175  1.1.1.1.4.2  perseant   file_size = bfd_getl32 (int_buf);
    176  1.1.1.1.4.2  perseant 
    177  1.1.1.1.4.2  perseant   /* Undocumented? Seen on PDBs created by MSVC 2022.  */
    178  1.1.1.1.4.2  perseant   if (file_size == 0xffffffff)
    179  1.1.1.1.4.2  perseant     file_size = 0;
    180  1.1.1.1.4.2  perseant 
    181  1.1.1.1.4.2  perseant   /* Create BFD. */
    182  1.1.1.1.4.2  perseant 
    183  1.1.1.1.4.2  perseant   /* Four hex digits is enough - even though MSF allows for 32 bits, the
    184  1.1.1.1.4.2  perseant      PDB format itself only uses 16 bits for stream numbers.  */
    185  1.1.1.1.4.2  perseant   sprintf (name, "%04lx", sym_index);
    186  1.1.1.1.4.2  perseant 
    187  1.1.1.1.4.2  perseant   file = bfd_create (name, abfd);
    188  1.1.1.1.4.2  perseant 
    189  1.1.1.1.4.2  perseant   if (!file)
    190  1.1.1.1.4.2  perseant     return NULL;
    191  1.1.1.1.4.2  perseant 
    192  1.1.1.1.4.2  perseant   if (!bfd_make_writable (file))
    193  1.1.1.1.4.2  perseant     goto fail;
    194  1.1.1.1.4.2  perseant 
    195  1.1.1.1.4.2  perseant   file->arelt_data =
    196  1.1.1.1.4.2  perseant     (struct areltdata *) bfd_zmalloc (sizeof (struct areltdata));
    197  1.1.1.1.4.2  perseant 
    198  1.1.1.1.4.2  perseant   if (!file->arelt_data)
    199  1.1.1.1.4.2  perseant     goto fail;
    200  1.1.1.1.4.2  perseant 
    201  1.1.1.1.4.2  perseant   arch_eltdata (file)->parsed_size = file_size;
    202  1.1.1.1.4.2  perseant   arch_eltdata (file)->key = sym_index;
    203  1.1.1.1.4.2  perseant 
    204  1.1.1.1.4.2  perseant   if (file_size == 0)
    205  1.1.1.1.4.2  perseant     return file;
    206  1.1.1.1.4.2  perseant 
    207  1.1.1.1.4.2  perseant   block_off = 0;
    208  1.1.1.1.4.2  perseant 
    209  1.1.1.1.4.2  perseant   /* Sum number of blocks in previous files.  */
    210  1.1.1.1.4.2  perseant 
    211  1.1.1.1.4.2  perseant   if (sym_index != 0)
    212  1.1.1.1.4.2  perseant     {
    213  1.1.1.1.4.2  perseant       dir_offset = sizeof (uint32_t);
    214  1.1.1.1.4.2  perseant 
    215  1.1.1.1.4.2  perseant       if (bfd_seek (abfd, (first_dir_block * block_size) + sizeof (uint32_t),
    216  1.1.1.1.4.2  perseant 		    SEEK_SET))
    217  1.1.1.1.4.2  perseant 	goto fail;
    218  1.1.1.1.4.2  perseant 
    219  1.1.1.1.4.2  perseant       for (symindex i = 0; i < sym_index; i++)
    220  1.1.1.1.4.2  perseant 	{
    221  1.1.1.1.4.2  perseant 	  uint32_t size, num_blocks;
    222  1.1.1.1.4.2  perseant 
    223  1.1.1.1.4.2  perseant 	  if ((dir_offset % block_size) == 0)
    224  1.1.1.1.4.2  perseant 	    {
    225  1.1.1.1.4.2  perseant 	      uint32_t block_map_addr_off;
    226  1.1.1.1.4.2  perseant 
    227  1.1.1.1.4.2  perseant 	      block_map_addr_off =
    228  1.1.1.1.4.2  perseant 		((dir_offset / block_size) * sizeof (uint32_t));
    229  1.1.1.1.4.2  perseant 
    230  1.1.1.1.4.2  perseant 	      if (bfd_seek
    231  1.1.1.1.4.2  perseant 		  (abfd, (block_map_addr * block_size) + block_map_addr_off,
    232  1.1.1.1.4.2  perseant 		   SEEK_SET))
    233  1.1.1.1.4.2  perseant 		goto fail;
    234  1.1.1.1.4.2  perseant 
    235  1.1.1.1.4.2  perseant 	      if (bfd_bread (int_buf, sizeof (uint32_t), abfd) !=
    236  1.1.1.1.4.2  perseant 		  sizeof (uint32_t))
    237  1.1.1.1.4.2  perseant 		{
    238  1.1.1.1.4.2  perseant 		  bfd_set_error (bfd_error_malformed_archive);
    239  1.1.1.1.4.2  perseant 		  goto fail;
    240  1.1.1.1.4.2  perseant 		}
    241  1.1.1.1.4.2  perseant 
    242  1.1.1.1.4.2  perseant 	      block = bfd_getl32 (int_buf);
    243  1.1.1.1.4.2  perseant 
    244  1.1.1.1.4.2  perseant 	      if (bfd_seek (abfd, block * block_size, SEEK_SET))
    245  1.1.1.1.4.2  perseant 		goto fail;
    246  1.1.1.1.4.2  perseant 	    }
    247  1.1.1.1.4.2  perseant 
    248  1.1.1.1.4.2  perseant 	  if (bfd_bread (int_buf, sizeof (uint32_t), abfd) !=
    249  1.1.1.1.4.2  perseant 	      sizeof (uint32_t))
    250  1.1.1.1.4.2  perseant 	    {
    251  1.1.1.1.4.2  perseant 	      bfd_set_error (bfd_error_malformed_archive);
    252  1.1.1.1.4.2  perseant 	      goto fail;
    253  1.1.1.1.4.2  perseant 	    }
    254  1.1.1.1.4.2  perseant 
    255  1.1.1.1.4.2  perseant 	  size = bfd_getl32 (int_buf);
    256  1.1.1.1.4.2  perseant 
    257  1.1.1.1.4.2  perseant 	  if (size == 0xffffffff)
    258  1.1.1.1.4.2  perseant 	    size = 0;
    259  1.1.1.1.4.2  perseant 
    260  1.1.1.1.4.2  perseant 	  num_blocks = (size + block_size - 1) / block_size;
    261  1.1.1.1.4.2  perseant 	  block_off += num_blocks;
    262  1.1.1.1.4.2  perseant 
    263  1.1.1.1.4.2  perseant 	  dir_offset += sizeof (uint32_t);
    264  1.1.1.1.4.2  perseant 	}
    265  1.1.1.1.4.2  perseant     }
    266  1.1.1.1.4.2  perseant 
    267  1.1.1.1.4.2  perseant   /* Read blocks, and write into new BFD.  */
    268  1.1.1.1.4.2  perseant 
    269  1.1.1.1.4.2  perseant   dir_offset = sizeof (uint32_t) * (num_files + block_off + 1);
    270  1.1.1.1.4.2  perseant 
    271  1.1.1.1.4.2  perseant   if (dir_offset >= block_size)
    272  1.1.1.1.4.2  perseant     {
    273  1.1.1.1.4.2  perseant       uint32_t block_map_addr_off;
    274  1.1.1.1.4.2  perseant 
    275  1.1.1.1.4.2  perseant       block_map_addr_off = ((dir_offset / block_size) * sizeof (uint32_t));
    276  1.1.1.1.4.2  perseant 
    277  1.1.1.1.4.2  perseant       if (bfd_seek (abfd, (block_map_addr * block_size) + block_map_addr_off,
    278  1.1.1.1.4.2  perseant 		    SEEK_SET))
    279  1.1.1.1.4.2  perseant 	goto fail;
    280  1.1.1.1.4.2  perseant 
    281  1.1.1.1.4.2  perseant       if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    282  1.1.1.1.4.2  perseant 	{
    283  1.1.1.1.4.2  perseant 	  bfd_set_error (bfd_error_malformed_archive);
    284  1.1.1.1.4.2  perseant 	  goto fail;
    285  1.1.1.1.4.2  perseant 	}
    286  1.1.1.1.4.2  perseant 
    287  1.1.1.1.4.2  perseant       block = bfd_getl32 (int_buf);
    288  1.1.1.1.4.2  perseant     }
    289  1.1.1.1.4.2  perseant   else
    290  1.1.1.1.4.2  perseant     {
    291  1.1.1.1.4.2  perseant       block = first_dir_block;
    292  1.1.1.1.4.2  perseant     }
    293  1.1.1.1.4.2  perseant 
    294  1.1.1.1.4.2  perseant   buf = bfd_malloc (block_size);
    295  1.1.1.1.4.2  perseant   if (!buf)
    296  1.1.1.1.4.2  perseant     goto fail;
    297  1.1.1.1.4.2  perseant 
    298  1.1.1.1.4.2  perseant   left = file_size;
    299  1.1.1.1.4.2  perseant   do
    300  1.1.1.1.4.2  perseant     {
    301  1.1.1.1.4.2  perseant       uint32_t file_block, to_read;
    302  1.1.1.1.4.2  perseant 
    303  1.1.1.1.4.2  perseant       if ((dir_offset % block_size) == 0 && left != file_size)
    304  1.1.1.1.4.2  perseant 	{
    305  1.1.1.1.4.2  perseant 	  uint32_t block_map_addr_off;
    306  1.1.1.1.4.2  perseant 
    307  1.1.1.1.4.2  perseant 	  block_map_addr_off =
    308  1.1.1.1.4.2  perseant 	    ((dir_offset / block_size) * sizeof (uint32_t));
    309  1.1.1.1.4.2  perseant 
    310  1.1.1.1.4.2  perseant 	  if (bfd_seek
    311  1.1.1.1.4.2  perseant 	      (abfd, (block_map_addr * block_size) + block_map_addr_off,
    312  1.1.1.1.4.2  perseant 	       SEEK_SET))
    313  1.1.1.1.4.2  perseant 	    goto fail2;
    314  1.1.1.1.4.2  perseant 
    315  1.1.1.1.4.2  perseant 	  if (bfd_bread (int_buf, sizeof (uint32_t), abfd) !=
    316  1.1.1.1.4.2  perseant 	      sizeof (uint32_t))
    317  1.1.1.1.4.2  perseant 	    {
    318  1.1.1.1.4.2  perseant 	      bfd_set_error (bfd_error_malformed_archive);
    319  1.1.1.1.4.2  perseant 	      goto fail2;
    320  1.1.1.1.4.2  perseant 	    }
    321  1.1.1.1.4.2  perseant 
    322  1.1.1.1.4.2  perseant 	  block = bfd_getl32 (int_buf);
    323  1.1.1.1.4.2  perseant 	}
    324  1.1.1.1.4.2  perseant 
    325  1.1.1.1.4.2  perseant       if (bfd_seek (abfd, (block * block_size) + (dir_offset % block_size),
    326  1.1.1.1.4.2  perseant 		    SEEK_SET))
    327  1.1.1.1.4.2  perseant 	goto fail2;
    328  1.1.1.1.4.2  perseant 
    329  1.1.1.1.4.2  perseant       if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    330  1.1.1.1.4.2  perseant 	{
    331  1.1.1.1.4.2  perseant 	  bfd_set_error (bfd_error_malformed_archive);
    332  1.1.1.1.4.2  perseant 	  goto fail2;
    333  1.1.1.1.4.2  perseant 	}
    334  1.1.1.1.4.2  perseant 
    335  1.1.1.1.4.2  perseant       file_block = bfd_getl32 (int_buf);
    336  1.1.1.1.4.2  perseant 
    337  1.1.1.1.4.2  perseant       if (bfd_seek (abfd, file_block * block_size, SEEK_SET))
    338  1.1.1.1.4.2  perseant 	goto fail2;
    339  1.1.1.1.4.2  perseant 
    340  1.1.1.1.4.2  perseant       to_read = left > block_size ? block_size : left;
    341  1.1.1.1.4.2  perseant 
    342  1.1.1.1.4.2  perseant       if (bfd_bread (buf, to_read, abfd) != to_read)
    343  1.1.1.1.4.2  perseant 	{
    344  1.1.1.1.4.2  perseant 	  bfd_set_error (bfd_error_malformed_archive);
    345  1.1.1.1.4.2  perseant 	  goto fail2;
    346  1.1.1.1.4.2  perseant 	}
    347  1.1.1.1.4.2  perseant 
    348  1.1.1.1.4.2  perseant       if (bfd_bwrite (buf, to_read, file) != to_read)
    349  1.1.1.1.4.2  perseant 	goto fail2;
    350  1.1.1.1.4.2  perseant 
    351  1.1.1.1.4.2  perseant       if (left > block_size)
    352  1.1.1.1.4.2  perseant 	left -= block_size;
    353  1.1.1.1.4.2  perseant       else
    354  1.1.1.1.4.2  perseant 	break;
    355  1.1.1.1.4.2  perseant 
    356  1.1.1.1.4.2  perseant       dir_offset += sizeof (uint32_t);
    357  1.1.1.1.4.2  perseant     }
    358  1.1.1.1.4.2  perseant   while (left > 0);
    359  1.1.1.1.4.2  perseant 
    360  1.1.1.1.4.2  perseant   free (buf);
    361  1.1.1.1.4.2  perseant 
    362  1.1.1.1.4.2  perseant   return file;
    363  1.1.1.1.4.2  perseant 
    364  1.1.1.1.4.2  perseant fail2:
    365  1.1.1.1.4.2  perseant   free (buf);
    366  1.1.1.1.4.2  perseant 
    367  1.1.1.1.4.2  perseant fail:
    368  1.1.1.1.4.2  perseant   bfd_close (file);
    369  1.1.1.1.4.2  perseant   return NULL;
    370  1.1.1.1.4.2  perseant }
    371  1.1.1.1.4.2  perseant 
    372  1.1.1.1.4.2  perseant static bfd *
    373  1.1.1.1.4.2  perseant pdb_openr_next_archived_file (bfd *archive, bfd *last_file)
    374  1.1.1.1.4.2  perseant {
    375  1.1.1.1.4.2  perseant   if (!last_file)
    376  1.1.1.1.4.2  perseant     return pdb_get_elt_at_index (archive, 0);
    377  1.1.1.1.4.2  perseant   else
    378  1.1.1.1.4.2  perseant     return pdb_get_elt_at_index (archive, arch_eltdata (last_file)->key + 1);
    379  1.1.1.1.4.2  perseant }
    380  1.1.1.1.4.2  perseant 
    381  1.1.1.1.4.2  perseant static int
    382  1.1.1.1.4.2  perseant pdb_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
    383  1.1.1.1.4.2  perseant {
    384  1.1.1.1.4.2  perseant   buf->st_mtime = 0;
    385  1.1.1.1.4.2  perseant   buf->st_uid = 0;
    386  1.1.1.1.4.2  perseant   buf->st_gid = 0;
    387  1.1.1.1.4.2  perseant   buf->st_mode = 0644;
    388  1.1.1.1.4.2  perseant   buf->st_size = arch_eltdata (abfd)->parsed_size;
    389  1.1.1.1.4.2  perseant 
    390  1.1.1.1.4.2  perseant   return 0;
    391  1.1.1.1.4.2  perseant }
    392  1.1.1.1.4.2  perseant 
    393  1.1.1.1.4.2  perseant static uint32_t
    394  1.1.1.1.4.2  perseant pdb_allocate_block (uint32_t *num_blocks, uint32_t block_size)
    395  1.1.1.1.4.2  perseant {
    396  1.1.1.1.4.2  perseant   uint32_t block;
    397  1.1.1.1.4.2  perseant 
    398  1.1.1.1.4.2  perseant   block = *num_blocks;
    399  1.1.1.1.4.2  perseant 
    400  1.1.1.1.4.2  perseant   (*num_blocks)++;
    401  1.1.1.1.4.2  perseant 
    402  1.1.1.1.4.2  perseant   /* If new interval, skip two blocks for free space map.  */
    403  1.1.1.1.4.2  perseant 
    404  1.1.1.1.4.2  perseant   if ((block % block_size) == 1)
    405  1.1.1.1.4.2  perseant     {
    406  1.1.1.1.4.2  perseant       block += 2;
    407  1.1.1.1.4.2  perseant       (*num_blocks) += 2;
    408  1.1.1.1.4.2  perseant     }
    409  1.1.1.1.4.2  perseant 
    410  1.1.1.1.4.2  perseant   return block;
    411  1.1.1.1.4.2  perseant }
    412  1.1.1.1.4.2  perseant 
    413  1.1.1.1.4.2  perseant static bool
    414  1.1.1.1.4.2  perseant pdb_write_directory (bfd *abfd, uint32_t block_size, uint32_t num_files,
    415  1.1.1.1.4.2  perseant 		     uint32_t block_map_addr, uint32_t * num_blocks)
    416  1.1.1.1.4.2  perseant {
    417  1.1.1.1.4.2  perseant   char tmp[sizeof (uint32_t)];
    418  1.1.1.1.4.2  perseant   uint32_t block, left, block_map_off;
    419  1.1.1.1.4.2  perseant   bfd *arelt;
    420  1.1.1.1.4.2  perseant   char *buf;
    421  1.1.1.1.4.2  perseant 
    422  1.1.1.1.4.2  perseant   /* Allocate first block for directory.  */
    423  1.1.1.1.4.2  perseant 
    424  1.1.1.1.4.2  perseant   block = pdb_allocate_block (num_blocks, block_size);
    425  1.1.1.1.4.2  perseant   left = block_size;
    426  1.1.1.1.4.2  perseant 
    427  1.1.1.1.4.2  perseant   /* Write allocated block no. at beginning of block map.  */
    428  1.1.1.1.4.2  perseant 
    429  1.1.1.1.4.2  perseant   if (bfd_seek (abfd, block_map_addr * block_size, SEEK_SET))
    430  1.1.1.1.4.2  perseant     return false;
    431  1.1.1.1.4.2  perseant 
    432  1.1.1.1.4.2  perseant   bfd_putl32 (block, tmp);
    433  1.1.1.1.4.2  perseant 
    434  1.1.1.1.4.2  perseant   if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    435  1.1.1.1.4.2  perseant     return false;
    436  1.1.1.1.4.2  perseant 
    437  1.1.1.1.4.2  perseant   block_map_off = sizeof (uint32_t);
    438  1.1.1.1.4.2  perseant 
    439  1.1.1.1.4.2  perseant   /* Write num_files at beginning of directory.  */
    440  1.1.1.1.4.2  perseant 
    441  1.1.1.1.4.2  perseant   if (bfd_seek (abfd, block * block_size, SEEK_SET))
    442  1.1.1.1.4.2  perseant     return false;
    443  1.1.1.1.4.2  perseant 
    444  1.1.1.1.4.2  perseant   bfd_putl32 (num_files, tmp);
    445  1.1.1.1.4.2  perseant 
    446  1.1.1.1.4.2  perseant   if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    447  1.1.1.1.4.2  perseant     return false;
    448  1.1.1.1.4.2  perseant 
    449  1.1.1.1.4.2  perseant   left -= sizeof (uint32_t);
    450  1.1.1.1.4.2  perseant 
    451  1.1.1.1.4.2  perseant   /* Write file sizes.  */
    452  1.1.1.1.4.2  perseant 
    453  1.1.1.1.4.2  perseant   arelt = abfd->archive_head;
    454  1.1.1.1.4.2  perseant   while (arelt)
    455  1.1.1.1.4.2  perseant     {
    456  1.1.1.1.4.2  perseant       if (left == 0)
    457  1.1.1.1.4.2  perseant 	{
    458  1.1.1.1.4.2  perseant 	  if (block_map_off == block_size) /* Too many blocks.  */
    459  1.1.1.1.4.2  perseant 	    {
    460  1.1.1.1.4.2  perseant 	      bfd_set_error (bfd_error_invalid_operation);
    461  1.1.1.1.4.2  perseant 	      return false;
    462  1.1.1.1.4.2  perseant 	    }
    463  1.1.1.1.4.2  perseant 
    464  1.1.1.1.4.2  perseant 	  block = pdb_allocate_block (num_blocks, block_size);
    465  1.1.1.1.4.2  perseant 	  left = block_size;
    466  1.1.1.1.4.2  perseant 
    467  1.1.1.1.4.2  perseant 	  if (bfd_seek
    468  1.1.1.1.4.2  perseant 	      (abfd, (block_map_addr * block_size) + block_map_off, SEEK_SET))
    469  1.1.1.1.4.2  perseant 	    return false;
    470  1.1.1.1.4.2  perseant 
    471  1.1.1.1.4.2  perseant 	  bfd_putl32 (block, tmp);
    472  1.1.1.1.4.2  perseant 
    473  1.1.1.1.4.2  perseant 	  if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    474  1.1.1.1.4.2  perseant 	    return false;
    475  1.1.1.1.4.2  perseant 
    476  1.1.1.1.4.2  perseant 	  block_map_off += sizeof (uint32_t);
    477  1.1.1.1.4.2  perseant 
    478  1.1.1.1.4.2  perseant 	  if (bfd_seek (abfd, block * block_size, SEEK_SET))
    479  1.1.1.1.4.2  perseant 	    return false;
    480  1.1.1.1.4.2  perseant 	}
    481  1.1.1.1.4.2  perseant 
    482  1.1.1.1.4.2  perseant       bfd_putl32 (bfd_get_size (arelt), tmp);
    483  1.1.1.1.4.2  perseant 
    484  1.1.1.1.4.2  perseant       if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    485  1.1.1.1.4.2  perseant 	return false;
    486  1.1.1.1.4.2  perseant 
    487  1.1.1.1.4.2  perseant       left -= sizeof (uint32_t);
    488  1.1.1.1.4.2  perseant 
    489  1.1.1.1.4.2  perseant       arelt = arelt->archive_next;
    490  1.1.1.1.4.2  perseant     }
    491  1.1.1.1.4.2  perseant 
    492  1.1.1.1.4.2  perseant   /* Write blocks.  */
    493  1.1.1.1.4.2  perseant 
    494  1.1.1.1.4.2  perseant   buf = bfd_malloc (block_size);
    495  1.1.1.1.4.2  perseant   if (!buf)
    496  1.1.1.1.4.2  perseant     return false;
    497  1.1.1.1.4.2  perseant 
    498  1.1.1.1.4.2  perseant   arelt = abfd->archive_head;
    499  1.1.1.1.4.2  perseant   while (arelt)
    500  1.1.1.1.4.2  perseant     {
    501  1.1.1.1.4.2  perseant       ufile_ptr size = bfd_get_size (arelt);
    502  1.1.1.1.4.2  perseant       uint32_t req_blocks = (size + block_size - 1) / block_size;
    503  1.1.1.1.4.2  perseant 
    504  1.1.1.1.4.2  perseant       if (bfd_seek (arelt, 0, SEEK_SET))
    505  1.1.1.1.4.2  perseant 	{
    506  1.1.1.1.4.2  perseant 	  free (buf);
    507  1.1.1.1.4.2  perseant 	  return false;
    508  1.1.1.1.4.2  perseant 	}
    509  1.1.1.1.4.2  perseant 
    510  1.1.1.1.4.2  perseant       for (uint32_t i = 0; i < req_blocks; i++)
    511  1.1.1.1.4.2  perseant 	{
    512  1.1.1.1.4.2  perseant 	  uint32_t file_block, to_read;
    513  1.1.1.1.4.2  perseant 
    514  1.1.1.1.4.2  perseant 	  if (left == 0)
    515  1.1.1.1.4.2  perseant 	    {
    516  1.1.1.1.4.2  perseant 	      if (block_map_off == block_size) /* Too many blocks.  */
    517  1.1.1.1.4.2  perseant 		{
    518  1.1.1.1.4.2  perseant 		  bfd_set_error (bfd_error_invalid_operation);
    519  1.1.1.1.4.2  perseant 		  free (buf);
    520  1.1.1.1.4.2  perseant 		  return false;
    521  1.1.1.1.4.2  perseant 		}
    522  1.1.1.1.4.2  perseant 
    523  1.1.1.1.4.2  perseant 	      block = pdb_allocate_block (num_blocks, block_size);
    524  1.1.1.1.4.2  perseant 	      left = block_size;
    525  1.1.1.1.4.2  perseant 
    526  1.1.1.1.4.2  perseant 	      if (bfd_seek
    527  1.1.1.1.4.2  perseant 		  (abfd, (block_map_addr * block_size) + block_map_off,
    528  1.1.1.1.4.2  perseant 		   SEEK_SET))
    529  1.1.1.1.4.2  perseant 		{
    530  1.1.1.1.4.2  perseant 		  free (buf);
    531  1.1.1.1.4.2  perseant 		  return false;
    532  1.1.1.1.4.2  perseant 		}
    533  1.1.1.1.4.2  perseant 
    534  1.1.1.1.4.2  perseant 	      bfd_putl32 (block, tmp);
    535  1.1.1.1.4.2  perseant 
    536  1.1.1.1.4.2  perseant 	      if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) !=
    537  1.1.1.1.4.2  perseant 		  sizeof (uint32_t))
    538  1.1.1.1.4.2  perseant 		{
    539  1.1.1.1.4.2  perseant 		  free (buf);
    540  1.1.1.1.4.2  perseant 		  return false;
    541  1.1.1.1.4.2  perseant 		}
    542  1.1.1.1.4.2  perseant 
    543  1.1.1.1.4.2  perseant 	      block_map_off += sizeof (uint32_t);
    544  1.1.1.1.4.2  perseant 
    545  1.1.1.1.4.2  perseant 	      if (bfd_seek (abfd, block * block_size, SEEK_SET))
    546  1.1.1.1.4.2  perseant 		{
    547  1.1.1.1.4.2  perseant 		  free (buf);
    548  1.1.1.1.4.2  perseant 		  return false;
    549  1.1.1.1.4.2  perseant 		}
    550  1.1.1.1.4.2  perseant 	    }
    551  1.1.1.1.4.2  perseant 
    552  1.1.1.1.4.2  perseant 	  /* Allocate block and write number into directory.  */
    553  1.1.1.1.4.2  perseant 
    554  1.1.1.1.4.2  perseant 	  file_block = pdb_allocate_block (num_blocks, block_size);
    555  1.1.1.1.4.2  perseant 
    556  1.1.1.1.4.2  perseant 	  bfd_putl32 (file_block, tmp);
    557  1.1.1.1.4.2  perseant 
    558  1.1.1.1.4.2  perseant 	  if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    559  1.1.1.1.4.2  perseant 	    {
    560  1.1.1.1.4.2  perseant 	      free (buf);
    561  1.1.1.1.4.2  perseant 	      return false;
    562  1.1.1.1.4.2  perseant 	    }
    563  1.1.1.1.4.2  perseant 
    564  1.1.1.1.4.2  perseant 	  left -= sizeof (uint32_t);
    565  1.1.1.1.4.2  perseant 
    566  1.1.1.1.4.2  perseant 	  /* Read file contents into buffer.  */
    567  1.1.1.1.4.2  perseant 
    568  1.1.1.1.4.2  perseant 	  to_read = size > block_size ? block_size : size;
    569  1.1.1.1.4.2  perseant 
    570  1.1.1.1.4.2  perseant 	  if (bfd_bread (buf, to_read, arelt) != to_read)
    571  1.1.1.1.4.2  perseant 	    {
    572  1.1.1.1.4.2  perseant 	      free (buf);
    573  1.1.1.1.4.2  perseant 	      return false;
    574  1.1.1.1.4.2  perseant 	    }
    575  1.1.1.1.4.2  perseant 
    576  1.1.1.1.4.2  perseant 	  size -= to_read;
    577  1.1.1.1.4.2  perseant 
    578  1.1.1.1.4.2  perseant 	  if (to_read < block_size)
    579  1.1.1.1.4.2  perseant 	    memset (buf + to_read, 0, block_size - to_read);
    580  1.1.1.1.4.2  perseant 
    581  1.1.1.1.4.2  perseant 	  if (bfd_seek (abfd, file_block * block_size, SEEK_SET))
    582  1.1.1.1.4.2  perseant 	    {
    583  1.1.1.1.4.2  perseant 	      free (buf);
    584  1.1.1.1.4.2  perseant 	      return false;
    585  1.1.1.1.4.2  perseant 	    }
    586  1.1.1.1.4.2  perseant 
    587  1.1.1.1.4.2  perseant 	  /* Write file contents into allocated block.  */
    588  1.1.1.1.4.2  perseant 
    589  1.1.1.1.4.2  perseant 	  if (bfd_bwrite (buf, block_size, abfd) != block_size)
    590  1.1.1.1.4.2  perseant 	    {
    591  1.1.1.1.4.2  perseant 	      free (buf);
    592  1.1.1.1.4.2  perseant 	      return false;
    593  1.1.1.1.4.2  perseant 	    }
    594  1.1.1.1.4.2  perseant 
    595  1.1.1.1.4.2  perseant 	  if (bfd_seek
    596  1.1.1.1.4.2  perseant 	      (abfd, (block * block_size) + block_size - left, SEEK_SET))
    597  1.1.1.1.4.2  perseant 	    {
    598  1.1.1.1.4.2  perseant 	      free (buf);
    599  1.1.1.1.4.2  perseant 	      return false;
    600  1.1.1.1.4.2  perseant 	    }
    601  1.1.1.1.4.2  perseant 	}
    602  1.1.1.1.4.2  perseant 
    603  1.1.1.1.4.2  perseant       arelt = arelt->archive_next;
    604  1.1.1.1.4.2  perseant     }
    605  1.1.1.1.4.2  perseant 
    606  1.1.1.1.4.2  perseant   memset (buf, 0, left);
    607  1.1.1.1.4.2  perseant 
    608  1.1.1.1.4.2  perseant   if (bfd_bwrite (buf, left, abfd) != left)
    609  1.1.1.1.4.2  perseant     {
    610  1.1.1.1.4.2  perseant       free (buf);
    611  1.1.1.1.4.2  perseant       return false;
    612  1.1.1.1.4.2  perseant     }
    613  1.1.1.1.4.2  perseant 
    614  1.1.1.1.4.2  perseant   free (buf);
    615  1.1.1.1.4.2  perseant 
    616  1.1.1.1.4.2  perseant   return true;
    617  1.1.1.1.4.2  perseant }
    618  1.1.1.1.4.2  perseant 
    619  1.1.1.1.4.2  perseant static bool
    620  1.1.1.1.4.2  perseant pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks)
    621  1.1.1.1.4.2  perseant {
    622  1.1.1.1.4.2  perseant   char *buf;
    623  1.1.1.1.4.2  perseant   uint32_t num_intervals = (num_blocks + block_size - 1) / block_size;
    624  1.1.1.1.4.2  perseant 
    625  1.1.1.1.4.2  perseant   buf = bfd_malloc (block_size);
    626  1.1.1.1.4.2  perseant   if (!buf)
    627  1.1.1.1.4.2  perseant     return false;
    628  1.1.1.1.4.2  perseant 
    629  1.1.1.1.4.2  perseant   num_blocks--;			/* Superblock not included.  */
    630  1.1.1.1.4.2  perseant 
    631  1.1.1.1.4.2  perseant   for (uint32_t i = 0; i < num_intervals; i++)
    632  1.1.1.1.4.2  perseant     {
    633  1.1.1.1.4.2  perseant       if (bfd_seek (abfd, ((i * block_size) + 1) * block_size, SEEK_SET))
    634  1.1.1.1.4.2  perseant 	{
    635  1.1.1.1.4.2  perseant 	  free (buf);
    636  1.1.1.1.4.2  perseant 	  return false;
    637  1.1.1.1.4.2  perseant 	}
    638  1.1.1.1.4.2  perseant 
    639  1.1.1.1.4.2  perseant       /* All of our blocks are contiguous, making our free block map simple.
    640  1.1.1.1.4.2  perseant          0 = used, 1 = free.  */
    641  1.1.1.1.4.2  perseant 
    642  1.1.1.1.4.2  perseant       if (num_blocks >= 8)
    643  1.1.1.1.4.2  perseant 	memset (buf, 0,
    644  1.1.1.1.4.2  perseant 		(num_blocks / 8) >
    645  1.1.1.1.4.2  perseant 		block_size ? block_size : (num_blocks / 8));
    646  1.1.1.1.4.2  perseant 
    647  1.1.1.1.4.2  perseant       if (num_blocks < block_size * 8)
    648  1.1.1.1.4.2  perseant 	{
    649  1.1.1.1.4.2  perseant 	  unsigned int off = num_blocks / 8;
    650  1.1.1.1.4.2  perseant 
    651  1.1.1.1.4.2  perseant 	  if (num_blocks % 8)
    652  1.1.1.1.4.2  perseant 	    {
    653  1.1.1.1.4.2  perseant 	      buf[off] = (1 << (8 - (num_blocks % 8))) - 1;
    654  1.1.1.1.4.2  perseant 	      off++;
    655  1.1.1.1.4.2  perseant 	    }
    656  1.1.1.1.4.2  perseant 
    657  1.1.1.1.4.2  perseant 	  if (off < block_size)
    658  1.1.1.1.4.2  perseant 	    memset (buf + off, 0xff, block_size - off);
    659  1.1.1.1.4.2  perseant 	}
    660  1.1.1.1.4.2  perseant 
    661  1.1.1.1.4.2  perseant       if (num_blocks < block_size * 8)
    662  1.1.1.1.4.2  perseant 	num_blocks = 0;
    663  1.1.1.1.4.2  perseant       else
    664  1.1.1.1.4.2  perseant 	num_blocks -= block_size * 8;
    665  1.1.1.1.4.2  perseant 
    666  1.1.1.1.4.2  perseant       if (bfd_bwrite (buf, block_size, abfd) != block_size)
    667  1.1.1.1.4.2  perseant 	return false;
    668  1.1.1.1.4.2  perseant     }
    669  1.1.1.1.4.2  perseant 
    670  1.1.1.1.4.2  perseant   free (buf);
    671  1.1.1.1.4.2  perseant 
    672  1.1.1.1.4.2  perseant   return true;
    673  1.1.1.1.4.2  perseant }
    674  1.1.1.1.4.2  perseant 
    675  1.1.1.1.4.2  perseant static bool
    676  1.1.1.1.4.2  perseant pdb_write_contents (bfd *abfd)
    677  1.1.1.1.4.2  perseant {
    678  1.1.1.1.4.2  perseant   char tmp[sizeof (uint32_t)];
    679  1.1.1.1.4.2  perseant   const uint32_t block_size = 0x400;
    680  1.1.1.1.4.2  perseant   uint32_t block_map_addr;
    681  1.1.1.1.4.2  perseant   uint32_t num_blocks;
    682  1.1.1.1.4.2  perseant   uint32_t num_files = 0;
    683  1.1.1.1.4.2  perseant   uint32_t num_directory_bytes = sizeof (uint32_t);
    684  1.1.1.1.4.2  perseant   bfd *arelt;
    685  1.1.1.1.4.2  perseant 
    686  1.1.1.1.4.2  perseant   if (bfd_bwrite (pdb_magic, sizeof (pdb_magic), abfd) != sizeof (pdb_magic))
    687  1.1.1.1.4.2  perseant     return false;
    688  1.1.1.1.4.2  perseant 
    689  1.1.1.1.4.2  perseant   bfd_putl32 (block_size, tmp);
    690  1.1.1.1.4.2  perseant 
    691  1.1.1.1.4.2  perseant   if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    692  1.1.1.1.4.2  perseant     return false;
    693  1.1.1.1.4.2  perseant 
    694  1.1.1.1.4.2  perseant   bfd_putl32 (1, tmp); /* Free block map block (always either 1 or 2).  */
    695  1.1.1.1.4.2  perseant 
    696  1.1.1.1.4.2  perseant   if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    697  1.1.1.1.4.2  perseant     return false;
    698  1.1.1.1.4.2  perseant 
    699  1.1.1.1.4.2  perseant   arelt = abfd->archive_head;
    700  1.1.1.1.4.2  perseant 
    701  1.1.1.1.4.2  perseant   while (arelt)
    702  1.1.1.1.4.2  perseant     {
    703  1.1.1.1.4.2  perseant       uint32_t blocks_required =
    704  1.1.1.1.4.2  perseant 	(bfd_get_size (arelt) + block_size - 1) / block_size;
    705  1.1.1.1.4.2  perseant 
    706  1.1.1.1.4.2  perseant       num_directory_bytes += sizeof (uint32_t); /* Size.  */
    707  1.1.1.1.4.2  perseant       num_directory_bytes += blocks_required * sizeof (uint32_t); /* Blocks.  */
    708  1.1.1.1.4.2  perseant 
    709  1.1.1.1.4.2  perseant       num_files++;
    710  1.1.1.1.4.2  perseant 
    711  1.1.1.1.4.2  perseant       arelt = arelt->archive_next;
    712  1.1.1.1.4.2  perseant     }
    713  1.1.1.1.4.2  perseant 
    714  1.1.1.1.4.2  perseant   /* Superblock plus two bitmap blocks.  */
    715  1.1.1.1.4.2  perseant   num_blocks = 3;
    716  1.1.1.1.4.2  perseant 
    717  1.1.1.1.4.2  perseant   /* Skip num_blocks for now.  */
    718  1.1.1.1.4.2  perseant   if (bfd_seek (abfd, sizeof (uint32_t), SEEK_CUR))
    719  1.1.1.1.4.2  perseant     return false;
    720  1.1.1.1.4.2  perseant 
    721  1.1.1.1.4.2  perseant   bfd_putl32 (num_directory_bytes, tmp);
    722  1.1.1.1.4.2  perseant 
    723  1.1.1.1.4.2  perseant   if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    724  1.1.1.1.4.2  perseant     return false;
    725  1.1.1.1.4.2  perseant 
    726  1.1.1.1.4.2  perseant   /* Skip unknown uint32_t (always 0?).  */
    727  1.1.1.1.4.2  perseant   if (bfd_seek (abfd, sizeof (uint32_t), SEEK_CUR))
    728  1.1.1.1.4.2  perseant     return false;
    729  1.1.1.1.4.2  perseant 
    730  1.1.1.1.4.2  perseant   block_map_addr = pdb_allocate_block (&num_blocks, block_size);
    731  1.1.1.1.4.2  perseant 
    732  1.1.1.1.4.2  perseant   bfd_putl32 (block_map_addr, tmp);
    733  1.1.1.1.4.2  perseant 
    734  1.1.1.1.4.2  perseant   if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    735  1.1.1.1.4.2  perseant     return false;
    736  1.1.1.1.4.2  perseant 
    737  1.1.1.1.4.2  perseant   if (!pdb_write_directory
    738  1.1.1.1.4.2  perseant       (abfd, block_size, num_files, block_map_addr, &num_blocks))
    739  1.1.1.1.4.2  perseant     return false;
    740  1.1.1.1.4.2  perseant 
    741  1.1.1.1.4.2  perseant   if (!pdb_write_bitmap (abfd, block_size, num_blocks))
    742  1.1.1.1.4.2  perseant     return false;
    743  1.1.1.1.4.2  perseant 
    744  1.1.1.1.4.2  perseant   /* Write num_blocks now we know it.  */
    745  1.1.1.1.4.2  perseant 
    746  1.1.1.1.4.2  perseant   if (bfd_seek
    747  1.1.1.1.4.2  perseant       (abfd, sizeof (pdb_magic) + sizeof (uint32_t) + sizeof (uint32_t),
    748  1.1.1.1.4.2  perseant        SEEK_SET))
    749  1.1.1.1.4.2  perseant     return false;
    750  1.1.1.1.4.2  perseant 
    751  1.1.1.1.4.2  perseant   bfd_putl32 (num_blocks, tmp);
    752  1.1.1.1.4.2  perseant 
    753  1.1.1.1.4.2  perseant   if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    754  1.1.1.1.4.2  perseant     return false;
    755  1.1.1.1.4.2  perseant 
    756  1.1.1.1.4.2  perseant   return true;
    757  1.1.1.1.4.2  perseant }
    758  1.1.1.1.4.2  perseant 
    759  1.1.1.1.4.2  perseant #define pdb_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
    760  1.1.1.1.4.2  perseant #define pdb_new_section_hook _bfd_generic_new_section_hook
    761  1.1.1.1.4.2  perseant #define pdb_get_section_contents _bfd_generic_get_section_contents
    762  1.1.1.1.4.2  perseant #define pdb_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
    763  1.1.1.1.4.2  perseant #define pdb_close_and_cleanup _bfd_generic_close_and_cleanup
    764  1.1.1.1.4.2  perseant 
    765  1.1.1.1.4.2  perseant #define pdb_slurp_armap _bfd_noarchive_slurp_armap
    766  1.1.1.1.4.2  perseant #define pdb_slurp_extended_name_table _bfd_noarchive_slurp_extended_name_table
    767  1.1.1.1.4.2  perseant #define pdb_construct_extended_name_table _bfd_noarchive_construct_extended_name_table
    768  1.1.1.1.4.2  perseant #define pdb_truncate_arname _bfd_noarchive_truncate_arname
    769  1.1.1.1.4.2  perseant #define pdb_write_armap _bfd_noarchive_write_armap
    770  1.1.1.1.4.2  perseant #define pdb_read_ar_hdr _bfd_noarchive_read_ar_hdr
    771  1.1.1.1.4.2  perseant #define pdb_write_ar_hdr _bfd_noarchive_write_ar_hdr
    772  1.1.1.1.4.2  perseant #define pdb_update_armap_timestamp _bfd_noarchive_update_armap_timestamp
    773  1.1.1.1.4.2  perseant 
    774  1.1.1.1.4.2  perseant const bfd_target pdb_vec =
    775  1.1.1.1.4.2  perseant {
    776  1.1.1.1.4.2  perseant   "pdb",
    777  1.1.1.1.4.2  perseant   bfd_target_unknown_flavour,
    778  1.1.1.1.4.2  perseant   BFD_ENDIAN_LITTLE,		/* target byte order */
    779  1.1.1.1.4.2  perseant   BFD_ENDIAN_LITTLE,		/* target headers byte order */
    780  1.1.1.1.4.2  perseant   0,				/* object flags */
    781  1.1.1.1.4.2  perseant   0,				/* section flags */
    782  1.1.1.1.4.2  perseant   0,				/* leading underscore */
    783  1.1.1.1.4.2  perseant   ' ',				/* ar_pad_char */
    784  1.1.1.1.4.2  perseant   16,				/* ar_max_namelen */
    785  1.1.1.1.4.2  perseant   0,				/* match priority.  */
    786  1.1.1.1.4.2  perseant   TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
    787  1.1.1.1.4.2  perseant   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
    788  1.1.1.1.4.2  perseant   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
    789  1.1.1.1.4.2  perseant   bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data.  */
    790  1.1.1.1.4.2  perseant   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
    791  1.1.1.1.4.2  perseant   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
    792  1.1.1.1.4.2  perseant   bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs.  */
    793  1.1.1.1.4.2  perseant 
    794  1.1.1.1.4.2  perseant   {				/* bfd_check_format */
    795  1.1.1.1.4.2  perseant     _bfd_dummy_target,
    796  1.1.1.1.4.2  perseant     _bfd_dummy_target,
    797  1.1.1.1.4.2  perseant     pdb_archive_p,
    798  1.1.1.1.4.2  perseant     _bfd_dummy_target
    799  1.1.1.1.4.2  perseant   },
    800  1.1.1.1.4.2  perseant   {				/* bfd_set_format */
    801  1.1.1.1.4.2  perseant     _bfd_bool_bfd_false_error,
    802  1.1.1.1.4.2  perseant     _bfd_bool_bfd_false_error,
    803  1.1.1.1.4.2  perseant     _bfd_bool_bfd_true,
    804  1.1.1.1.4.2  perseant     _bfd_bool_bfd_false_error
    805  1.1.1.1.4.2  perseant   },
    806  1.1.1.1.4.2  perseant   {				/* bfd_write_contents */
    807  1.1.1.1.4.2  perseant     _bfd_bool_bfd_true,
    808  1.1.1.1.4.2  perseant     _bfd_bool_bfd_false_error,
    809  1.1.1.1.4.2  perseant     pdb_write_contents,
    810  1.1.1.1.4.2  perseant     _bfd_bool_bfd_false_error
    811  1.1.1.1.4.2  perseant   },
    812  1.1.1.1.4.2  perseant 
    813  1.1.1.1.4.2  perseant   BFD_JUMP_TABLE_GENERIC (pdb),
    814  1.1.1.1.4.2  perseant   BFD_JUMP_TABLE_COPY (_bfd_generic),
    815  1.1.1.1.4.2  perseant   BFD_JUMP_TABLE_CORE (_bfd_nocore),
    816  1.1.1.1.4.2  perseant   BFD_JUMP_TABLE_ARCHIVE (pdb),
    817  1.1.1.1.4.2  perseant   BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
    818  1.1.1.1.4.2  perseant   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
    819  1.1.1.1.4.2  perseant   BFD_JUMP_TABLE_WRITE (_bfd_generic),
    820  1.1.1.1.4.2  perseant   BFD_JUMP_TABLE_LINK (_bfd_nolink),
    821  1.1.1.1.4.2  perseant   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
    822  1.1.1.1.4.2  perseant 
    823  1.1.1.1.4.2  perseant   NULL,
    824  1.1.1.1.4.2  perseant 
    825  1.1.1.1.4.2  perseant   NULL
    826  1.1.1.1.4.2  perseant };
    827