Home | History | Annotate | Line # | Download | only in bfd
pdb.c revision 1.1.1.3
      1      1.1  christos /* BFD back-end for PDB Multi-Stream Format archives.
      2  1.1.1.2  christos    Copyright (C) 2022-2024 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.1.2  christos   ret = bfd_read (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.1.2  christos   if (bfd_read (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.1.2  christos   if (bfd_read (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.1.2  christos   if (bfd_read (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.1.2  christos   if (bfd_read (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.1.2  christos       if (bfd_read (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.1.2  christos   if (bfd_read (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.1.2  christos 	      if (bfd_read (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.1.2  christos 	  if (bfd_read (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.1.2  christos       if (bfd_read (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.1.2  christos 	  if (bfd_read (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.1.2  christos       if (bfd_read (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.1.2  christos       if (bfd_read (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.1.2  christos       if (bfd_write (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.1.3  christos 		     uint32_t block_map_addr, uint32_t * num_blocks,
    416  1.1.1.3  christos 		     uint32_t *stream0_start)
    417      1.1  christos {
    418      1.1  christos   char tmp[sizeof (uint32_t)];
    419      1.1  christos   uint32_t block, left, block_map_off;
    420      1.1  christos   bfd *arelt;
    421      1.1  christos   char *buf;
    422      1.1  christos 
    423      1.1  christos   /* Allocate first block for directory.  */
    424      1.1  christos 
    425      1.1  christos   block = pdb_allocate_block (num_blocks, block_size);
    426      1.1  christos   left = block_size;
    427      1.1  christos 
    428      1.1  christos   /* Write allocated block no. at beginning of block map.  */
    429      1.1  christos 
    430      1.1  christos   if (bfd_seek (abfd, block_map_addr * block_size, SEEK_SET))
    431      1.1  christos     return false;
    432      1.1  christos 
    433      1.1  christos   bfd_putl32 (block, tmp);
    434      1.1  christos 
    435  1.1.1.2  christos   if (bfd_write (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    436      1.1  christos     return false;
    437      1.1  christos 
    438      1.1  christos   block_map_off = sizeof (uint32_t);
    439      1.1  christos 
    440      1.1  christos   /* Write num_files at beginning of directory.  */
    441      1.1  christos 
    442      1.1  christos   if (bfd_seek (abfd, block * block_size, SEEK_SET))
    443      1.1  christos     return false;
    444      1.1  christos 
    445      1.1  christos   bfd_putl32 (num_files, tmp);
    446      1.1  christos 
    447  1.1.1.2  christos   if (bfd_write (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    448      1.1  christos     return false;
    449      1.1  christos 
    450      1.1  christos   left -= sizeof (uint32_t);
    451      1.1  christos 
    452      1.1  christos   /* Write file sizes.  */
    453      1.1  christos 
    454      1.1  christos   arelt = abfd->archive_head;
    455      1.1  christos   while (arelt)
    456      1.1  christos     {
    457      1.1  christos       if (left == 0)
    458      1.1  christos 	{
    459      1.1  christos 	  if (block_map_off == block_size) /* Too many blocks.  */
    460      1.1  christos 	    {
    461      1.1  christos 	      bfd_set_error (bfd_error_invalid_operation);
    462      1.1  christos 	      return false;
    463      1.1  christos 	    }
    464      1.1  christos 
    465      1.1  christos 	  block = pdb_allocate_block (num_blocks, block_size);
    466      1.1  christos 	  left = block_size;
    467      1.1  christos 
    468      1.1  christos 	  if (bfd_seek
    469      1.1  christos 	      (abfd, (block_map_addr * block_size) + block_map_off, SEEK_SET))
    470      1.1  christos 	    return false;
    471      1.1  christos 
    472      1.1  christos 	  bfd_putl32 (block, tmp);
    473      1.1  christos 
    474  1.1.1.2  christos 	  if (bfd_write (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    475      1.1  christos 	    return false;
    476      1.1  christos 
    477      1.1  christos 	  block_map_off += sizeof (uint32_t);
    478      1.1  christos 
    479      1.1  christos 	  if (bfd_seek (abfd, block * block_size, SEEK_SET))
    480      1.1  christos 	    return false;
    481      1.1  christos 	}
    482      1.1  christos 
    483      1.1  christos       bfd_putl32 (bfd_get_size (arelt), tmp);
    484      1.1  christos 
    485  1.1.1.2  christos       if (bfd_write (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    486      1.1  christos 	return false;
    487      1.1  christos 
    488      1.1  christos       left -= sizeof (uint32_t);
    489      1.1  christos 
    490      1.1  christos       arelt = arelt->archive_next;
    491      1.1  christos     }
    492      1.1  christos 
    493      1.1  christos   /* Write blocks.  */
    494      1.1  christos 
    495      1.1  christos   buf = bfd_malloc (block_size);
    496      1.1  christos   if (!buf)
    497      1.1  christos     return false;
    498      1.1  christos 
    499      1.1  christos   arelt = abfd->archive_head;
    500      1.1  christos   while (arelt)
    501      1.1  christos     {
    502      1.1  christos       ufile_ptr size = bfd_get_size (arelt);
    503      1.1  christos       uint32_t req_blocks = (size + block_size - 1) / block_size;
    504      1.1  christos 
    505      1.1  christos       if (bfd_seek (arelt, 0, SEEK_SET))
    506      1.1  christos 	{
    507      1.1  christos 	  free (buf);
    508      1.1  christos 	  return false;
    509      1.1  christos 	}
    510      1.1  christos 
    511      1.1  christos       for (uint32_t i = 0; i < req_blocks; i++)
    512      1.1  christos 	{
    513      1.1  christos 	  uint32_t file_block, to_read;
    514      1.1  christos 
    515      1.1  christos 	  if (left == 0)
    516      1.1  christos 	    {
    517      1.1  christos 	      if (block_map_off == block_size) /* Too many blocks.  */
    518      1.1  christos 		{
    519      1.1  christos 		  bfd_set_error (bfd_error_invalid_operation);
    520      1.1  christos 		  free (buf);
    521      1.1  christos 		  return false;
    522      1.1  christos 		}
    523      1.1  christos 
    524      1.1  christos 	      block = pdb_allocate_block (num_blocks, block_size);
    525      1.1  christos 	      left = block_size;
    526      1.1  christos 
    527      1.1  christos 	      if (bfd_seek
    528      1.1  christos 		  (abfd, (block_map_addr * block_size) + block_map_off,
    529      1.1  christos 		   SEEK_SET))
    530      1.1  christos 		{
    531      1.1  christos 		  free (buf);
    532      1.1  christos 		  return false;
    533      1.1  christos 		}
    534      1.1  christos 
    535      1.1  christos 	      bfd_putl32 (block, tmp);
    536      1.1  christos 
    537  1.1.1.2  christos 	      if (bfd_write (tmp, sizeof (uint32_t), abfd) !=
    538      1.1  christos 		  sizeof (uint32_t))
    539      1.1  christos 		{
    540      1.1  christos 		  free (buf);
    541      1.1  christos 		  return false;
    542      1.1  christos 		}
    543      1.1  christos 
    544      1.1  christos 	      block_map_off += sizeof (uint32_t);
    545      1.1  christos 
    546      1.1  christos 	      if (bfd_seek (abfd, block * block_size, SEEK_SET))
    547      1.1  christos 		{
    548      1.1  christos 		  free (buf);
    549      1.1  christos 		  return false;
    550      1.1  christos 		}
    551      1.1  christos 	    }
    552      1.1  christos 
    553      1.1  christos 	  /* Allocate block and write number into directory.  */
    554      1.1  christos 
    555      1.1  christos 	  file_block = pdb_allocate_block (num_blocks, block_size);
    556      1.1  christos 
    557      1.1  christos 	  bfd_putl32 (file_block, tmp);
    558      1.1  christos 
    559  1.1.1.2  christos 	  if (bfd_write (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    560      1.1  christos 	    {
    561      1.1  christos 	      free (buf);
    562      1.1  christos 	      return false;
    563      1.1  christos 	    }
    564      1.1  christos 
    565  1.1.1.3  christos 	  if (arelt == abfd->archive_head && i == 0)
    566  1.1.1.3  christos 	    *stream0_start = file_block;
    567  1.1.1.3  christos 
    568      1.1  christos 	  left -= sizeof (uint32_t);
    569      1.1  christos 
    570      1.1  christos 	  /* Read file contents into buffer.  */
    571      1.1  christos 
    572      1.1  christos 	  to_read = size > block_size ? block_size : size;
    573      1.1  christos 
    574  1.1.1.2  christos 	  if (bfd_read (buf, to_read, arelt) != to_read)
    575      1.1  christos 	    {
    576      1.1  christos 	      free (buf);
    577      1.1  christos 	      return false;
    578      1.1  christos 	    }
    579      1.1  christos 
    580      1.1  christos 	  size -= to_read;
    581      1.1  christos 
    582      1.1  christos 	  if (to_read < block_size)
    583      1.1  christos 	    memset (buf + to_read, 0, block_size - to_read);
    584      1.1  christos 
    585      1.1  christos 	  if (bfd_seek (abfd, file_block * block_size, SEEK_SET))
    586      1.1  christos 	    {
    587      1.1  christos 	      free (buf);
    588      1.1  christos 	      return false;
    589      1.1  christos 	    }
    590      1.1  christos 
    591      1.1  christos 	  /* Write file contents into allocated block.  */
    592      1.1  christos 
    593  1.1.1.2  christos 	  if (bfd_write (buf, block_size, abfd) != block_size)
    594      1.1  christos 	    {
    595      1.1  christos 	      free (buf);
    596      1.1  christos 	      return false;
    597      1.1  christos 	    }
    598      1.1  christos 
    599      1.1  christos 	  if (bfd_seek
    600      1.1  christos 	      (abfd, (block * block_size) + block_size - left, SEEK_SET))
    601      1.1  christos 	    {
    602      1.1  christos 	      free (buf);
    603      1.1  christos 	      return false;
    604      1.1  christos 	    }
    605      1.1  christos 	}
    606      1.1  christos 
    607      1.1  christos       arelt = arelt->archive_next;
    608      1.1  christos     }
    609      1.1  christos 
    610      1.1  christos   memset (buf, 0, left);
    611      1.1  christos 
    612  1.1.1.2  christos   if (bfd_write (buf, left, abfd) != left)
    613      1.1  christos     {
    614      1.1  christos       free (buf);
    615      1.1  christos       return false;
    616      1.1  christos     }
    617      1.1  christos 
    618      1.1  christos   free (buf);
    619      1.1  christos 
    620      1.1  christos   return true;
    621      1.1  christos }
    622      1.1  christos 
    623      1.1  christos static bool
    624  1.1.1.3  christos pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks,
    625  1.1.1.3  christos 		  uint32_t stream0_start)
    626      1.1  christos {
    627      1.1  christos   char *buf;
    628      1.1  christos   uint32_t num_intervals = (num_blocks + block_size - 1) / block_size;
    629      1.1  christos 
    630      1.1  christos   buf = bfd_malloc (block_size);
    631      1.1  christos   if (!buf)
    632      1.1  christos     return false;
    633      1.1  christos 
    634      1.1  christos   for (uint32_t i = 0; i < num_intervals; i++)
    635      1.1  christos     {
    636      1.1  christos       if (bfd_seek (abfd, ((i * block_size) + 1) * block_size, SEEK_SET))
    637      1.1  christos 	{
    638      1.1  christos 	  free (buf);
    639      1.1  christos 	  return false;
    640      1.1  christos 	}
    641      1.1  christos 
    642  1.1.1.3  christos       /* All of our blocks are contiguous, making our free block map
    643  1.1.1.3  christos 	 relatively simple.  0 = used, 1 = free.  */
    644      1.1  christos 
    645      1.1  christos       if (num_blocks >= 8)
    646      1.1  christos 	memset (buf, 0,
    647      1.1  christos 		(num_blocks / 8) >
    648      1.1  christos 		block_size ? block_size : (num_blocks / 8));
    649      1.1  christos 
    650      1.1  christos       if (num_blocks < block_size * 8)
    651      1.1  christos 	{
    652      1.1  christos 	  unsigned int off = num_blocks / 8;
    653      1.1  christos 
    654      1.1  christos 	  if (num_blocks % 8)
    655      1.1  christos 	    {
    656  1.1.1.3  christos 	      buf[off] = 256 - (1 << (num_blocks % 8));
    657      1.1  christos 	      off++;
    658      1.1  christos 	    }
    659      1.1  christos 
    660      1.1  christos 	  if (off < block_size)
    661      1.1  christos 	    memset (buf + off, 0xff, block_size - off);
    662      1.1  christos 	}
    663      1.1  christos 
    664  1.1.1.3  christos       /* Mark the blocks allocated to stream 0 as free.  This is because stream
    665  1.1.1.3  christos 	 0 is intended to be used for the previous MSF directory, to allow
    666  1.1.1.3  christos 	 atomic updates.  This doesn't apply to us, as we rewrite the whole
    667  1.1.1.3  christos 	 file whenever any change is made.  */
    668  1.1.1.3  christos 
    669  1.1.1.3  christos       if (i == 0 && abfd->archive_head)
    670  1.1.1.3  christos 	{
    671  1.1.1.3  christos 	  bfd *arelt = abfd->archive_head;
    672  1.1.1.3  christos 	  uint32_t stream0_blocks =
    673  1.1.1.3  christos 	    (bfd_get_size (arelt) + block_size - 1) / block_size;
    674  1.1.1.3  christos 
    675  1.1.1.3  christos 	  if (stream0_start % 8)
    676  1.1.1.3  christos 	    {
    677  1.1.1.3  christos 	      unsigned int high_bit;
    678  1.1.1.3  christos 
    679  1.1.1.3  christos 	      high_bit = (stream0_start % 8) + stream0_blocks;
    680  1.1.1.3  christos 	      if (high_bit > 8)
    681  1.1.1.3  christos 		high_bit = 8;
    682  1.1.1.3  christos 
    683  1.1.1.3  christos 	      buf[stream0_start / 8] |=
    684  1.1.1.3  christos 		(1 << high_bit) - (1 << (stream0_start % 8));
    685  1.1.1.3  christos 
    686  1.1.1.3  christos 	      stream0_blocks -= high_bit - (stream0_start % 8);
    687  1.1.1.3  christos 	      stream0_start += high_bit - (stream0_start % 8);
    688  1.1.1.3  christos 	    }
    689  1.1.1.3  christos 
    690  1.1.1.3  christos 	  memset (buf + (stream0_start / 8), 0xff, stream0_blocks / 8);
    691  1.1.1.3  christos 	  stream0_start += stream0_blocks / 8;
    692  1.1.1.3  christos 	  stream0_blocks %= 8;
    693  1.1.1.3  christos 
    694  1.1.1.3  christos 	  if (stream0_blocks > 0)
    695  1.1.1.3  christos 	    buf[stream0_start / 8] |= (1 << stream0_blocks) - 1;
    696  1.1.1.3  christos 	}
    697  1.1.1.3  christos 
    698      1.1  christos       if (num_blocks < block_size * 8)
    699      1.1  christos 	num_blocks = 0;
    700      1.1  christos       else
    701      1.1  christos 	num_blocks -= block_size * 8;
    702      1.1  christos 
    703  1.1.1.2  christos       if (bfd_write (buf, block_size, abfd) != block_size)
    704      1.1  christos 	return false;
    705      1.1  christos     }
    706      1.1  christos 
    707      1.1  christos   free (buf);
    708      1.1  christos 
    709      1.1  christos   return true;
    710      1.1  christos }
    711      1.1  christos 
    712      1.1  christos static bool
    713      1.1  christos pdb_write_contents (bfd *abfd)
    714      1.1  christos {
    715      1.1  christos   char tmp[sizeof (uint32_t)];
    716      1.1  christos   const uint32_t block_size = 0x400;
    717      1.1  christos   uint32_t block_map_addr;
    718      1.1  christos   uint32_t num_blocks;
    719      1.1  christos   uint32_t num_files = 0;
    720      1.1  christos   uint32_t num_directory_bytes = sizeof (uint32_t);
    721  1.1.1.3  christos   uint32_t stream0_start = 0;
    722      1.1  christos   bfd *arelt;
    723      1.1  christos 
    724  1.1.1.2  christos   if (bfd_write (pdb_magic, sizeof (pdb_magic), abfd) != sizeof (pdb_magic))
    725      1.1  christos     return false;
    726      1.1  christos 
    727      1.1  christos   bfd_putl32 (block_size, tmp);
    728      1.1  christos 
    729  1.1.1.2  christos   if (bfd_write (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    730      1.1  christos     return false;
    731      1.1  christos 
    732      1.1  christos   bfd_putl32 (1, tmp); /* Free block map block (always either 1 or 2).  */
    733      1.1  christos 
    734  1.1.1.2  christos   if (bfd_write (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    735      1.1  christos     return false;
    736      1.1  christos 
    737      1.1  christos   arelt = abfd->archive_head;
    738      1.1  christos 
    739      1.1  christos   while (arelt)
    740      1.1  christos     {
    741      1.1  christos       uint32_t blocks_required =
    742      1.1  christos 	(bfd_get_size (arelt) + block_size - 1) / block_size;
    743      1.1  christos 
    744      1.1  christos       num_directory_bytes += sizeof (uint32_t); /* Size.  */
    745      1.1  christos       num_directory_bytes += blocks_required * sizeof (uint32_t); /* Blocks.  */
    746      1.1  christos 
    747      1.1  christos       num_files++;
    748      1.1  christos 
    749      1.1  christos       arelt = arelt->archive_next;
    750      1.1  christos     }
    751      1.1  christos 
    752      1.1  christos   /* Superblock plus two bitmap blocks.  */
    753      1.1  christos   num_blocks = 3;
    754      1.1  christos 
    755      1.1  christos   /* Skip num_blocks for now.  */
    756      1.1  christos   if (bfd_seek (abfd, sizeof (uint32_t), SEEK_CUR))
    757      1.1  christos     return false;
    758      1.1  christos 
    759      1.1  christos   bfd_putl32 (num_directory_bytes, tmp);
    760      1.1  christos 
    761  1.1.1.2  christos   if (bfd_write (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    762      1.1  christos     return false;
    763      1.1  christos 
    764      1.1  christos   /* Skip unknown uint32_t (always 0?).  */
    765      1.1  christos   if (bfd_seek (abfd, sizeof (uint32_t), SEEK_CUR))
    766      1.1  christos     return false;
    767      1.1  christos 
    768      1.1  christos   block_map_addr = pdb_allocate_block (&num_blocks, block_size);
    769      1.1  christos 
    770      1.1  christos   bfd_putl32 (block_map_addr, tmp);
    771      1.1  christos 
    772  1.1.1.2  christos   if (bfd_write (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    773      1.1  christos     return false;
    774      1.1  christos 
    775      1.1  christos   if (!pdb_write_directory
    776  1.1.1.3  christos       (abfd, block_size, num_files, block_map_addr, &num_blocks,
    777  1.1.1.3  christos        &stream0_start))
    778      1.1  christos     return false;
    779      1.1  christos 
    780  1.1.1.3  christos   if (!pdb_write_bitmap (abfd, block_size, num_blocks, stream0_start))
    781      1.1  christos     return false;
    782      1.1  christos 
    783      1.1  christos   /* Write num_blocks now we know it.  */
    784      1.1  christos 
    785      1.1  christos   if (bfd_seek
    786      1.1  christos       (abfd, sizeof (pdb_magic) + sizeof (uint32_t) + sizeof (uint32_t),
    787      1.1  christos        SEEK_SET))
    788      1.1  christos     return false;
    789      1.1  christos 
    790      1.1  christos   bfd_putl32 (num_blocks, tmp);
    791      1.1  christos 
    792  1.1.1.2  christos   if (bfd_write (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t))
    793      1.1  christos     return false;
    794      1.1  christos 
    795      1.1  christos   return true;
    796      1.1  christos }
    797      1.1  christos 
    798      1.1  christos #define pdb_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
    799      1.1  christos #define pdb_new_section_hook _bfd_generic_new_section_hook
    800      1.1  christos #define pdb_get_section_contents _bfd_generic_get_section_contents
    801      1.1  christos #define pdb_close_and_cleanup _bfd_generic_close_and_cleanup
    802      1.1  christos 
    803      1.1  christos #define pdb_slurp_armap _bfd_noarchive_slurp_armap
    804      1.1  christos #define pdb_slurp_extended_name_table _bfd_noarchive_slurp_extended_name_table
    805      1.1  christos #define pdb_construct_extended_name_table _bfd_noarchive_construct_extended_name_table
    806      1.1  christos #define pdb_truncate_arname _bfd_noarchive_truncate_arname
    807      1.1  christos #define pdb_write_armap _bfd_noarchive_write_armap
    808      1.1  christos #define pdb_read_ar_hdr _bfd_noarchive_read_ar_hdr
    809      1.1  christos #define pdb_write_ar_hdr _bfd_noarchive_write_ar_hdr
    810      1.1  christos #define pdb_update_armap_timestamp _bfd_noarchive_update_armap_timestamp
    811      1.1  christos 
    812      1.1  christos const bfd_target pdb_vec =
    813      1.1  christos {
    814      1.1  christos   "pdb",
    815      1.1  christos   bfd_target_unknown_flavour,
    816      1.1  christos   BFD_ENDIAN_LITTLE,		/* target byte order */
    817      1.1  christos   BFD_ENDIAN_LITTLE,		/* target headers byte order */
    818      1.1  christos   0,				/* object flags */
    819      1.1  christos   0,				/* section flags */
    820      1.1  christos   0,				/* leading underscore */
    821      1.1  christos   ' ',				/* ar_pad_char */
    822      1.1  christos   16,				/* ar_max_namelen */
    823      1.1  christos   0,				/* match priority.  */
    824      1.1  christos   TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
    825      1.1  christos   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
    826      1.1  christos   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
    827      1.1  christos   bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data.  */
    828      1.1  christos   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
    829      1.1  christos   bfd_getl32, bfd_getl_signed_32, bfd_putl32,
    830      1.1  christos   bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs.  */
    831      1.1  christos 
    832      1.1  christos   {				/* bfd_check_format */
    833      1.1  christos     _bfd_dummy_target,
    834      1.1  christos     _bfd_dummy_target,
    835      1.1  christos     pdb_archive_p,
    836      1.1  christos     _bfd_dummy_target
    837      1.1  christos   },
    838      1.1  christos   {				/* bfd_set_format */
    839      1.1  christos     _bfd_bool_bfd_false_error,
    840      1.1  christos     _bfd_bool_bfd_false_error,
    841      1.1  christos     _bfd_bool_bfd_true,
    842      1.1  christos     _bfd_bool_bfd_false_error
    843      1.1  christos   },
    844      1.1  christos   {				/* bfd_write_contents */
    845      1.1  christos     _bfd_bool_bfd_true,
    846      1.1  christos     _bfd_bool_bfd_false_error,
    847      1.1  christos     pdb_write_contents,
    848      1.1  christos     _bfd_bool_bfd_false_error
    849      1.1  christos   },
    850      1.1  christos 
    851      1.1  christos   BFD_JUMP_TABLE_GENERIC (pdb),
    852      1.1  christos   BFD_JUMP_TABLE_COPY (_bfd_generic),
    853      1.1  christos   BFD_JUMP_TABLE_CORE (_bfd_nocore),
    854      1.1  christos   BFD_JUMP_TABLE_ARCHIVE (pdb),
    855      1.1  christos   BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
    856      1.1  christos   BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
    857      1.1  christos   BFD_JUMP_TABLE_WRITE (_bfd_generic),
    858      1.1  christos   BFD_JUMP_TABLE_LINK (_bfd_nolink),
    859      1.1  christos   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
    860      1.1  christos 
    861      1.1  christos   NULL,
    862      1.1  christos 
    863      1.1  christos   NULL
    864      1.1  christos };
    865