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