1 1.1 christos /* BFD back-end for PDB Multi-Stream Format archives. 2 1.1.1.3 christos Copyright (C) 2022-2026 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_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 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 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 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 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 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 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 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 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 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 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 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 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 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.2 christos uint32_t block_map_addr, uint32_t * num_blocks, 416 1.1.1.2 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 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 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 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 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 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 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.2 christos if (arelt == abfd->archive_head && i == 0) 566 1.1.1.2 christos *stream0_start = file_block; 567 1.1.1.2 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 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 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 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.2 christos pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks, 625 1.1.1.2 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.2 christos /* All of our blocks are contiguous, making our free block map 643 1.1.1.2 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.2 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.2 christos /* Mark the blocks allocated to stream 0 as free. This is because stream 665 1.1.1.2 christos 0 is intended to be used for the previous MSF directory, to allow 666 1.1.1.2 christos atomic updates. This doesn't apply to us, as we rewrite the whole 667 1.1.1.2 christos file whenever any change is made. */ 668 1.1.1.2 christos 669 1.1.1.2 christos if (i == 0 && abfd->archive_head) 670 1.1.1.2 christos { 671 1.1.1.2 christos bfd *arelt = abfd->archive_head; 672 1.1.1.2 christos uint32_t stream0_blocks = 673 1.1.1.2 christos (bfd_get_size (arelt) + block_size - 1) / block_size; 674 1.1.1.2 christos 675 1.1.1.2 christos if (stream0_start % 8) 676 1.1.1.2 christos { 677 1.1.1.2 christos unsigned int high_bit; 678 1.1.1.2 christos 679 1.1.1.2 christos high_bit = (stream0_start % 8) + stream0_blocks; 680 1.1.1.2 christos if (high_bit > 8) 681 1.1.1.2 christos high_bit = 8; 682 1.1.1.2 christos 683 1.1.1.2 christos buf[stream0_start / 8] |= 684 1.1.1.2 christos (1 << high_bit) - (1 << (stream0_start % 8)); 685 1.1.1.2 christos 686 1.1.1.2 christos stream0_blocks -= high_bit - (stream0_start % 8); 687 1.1.1.2 christos stream0_start += high_bit - (stream0_start % 8); 688 1.1.1.2 christos } 689 1.1.1.2 christos 690 1.1.1.2 christos memset (buf + (stream0_start / 8), 0xff, stream0_blocks / 8); 691 1.1.1.2 christos stream0_start += stream0_blocks / 8; 692 1.1.1.2 christos stream0_blocks %= 8; 693 1.1.1.2 christos 694 1.1.1.2 christos if (stream0_blocks > 0) 695 1.1.1.2 christos buf[stream0_start / 8] |= (1 << stream0_blocks) - 1; 696 1.1.1.2 christos } 697 1.1.1.2 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 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.2 christos uint32_t stream0_start = 0; 722 1.1 christos bfd *arelt; 723 1.1 christos 724 1.1 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 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 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 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 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.2 christos (abfd, block_size, num_files, block_map_addr, &num_blocks, 777 1.1.1.2 christos &stream0_start)) 778 1.1 christos return false; 779 1.1 christos 780 1.1.1.2 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 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.1.3 christos false, /* merge sections */ 826 1.1 christos bfd_getl64, bfd_getl_signed_64, bfd_putl64, 827 1.1 christos bfd_getl32, bfd_getl_signed_32, bfd_putl32, 828 1.1 christos bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */ 829 1.1 christos bfd_getl64, bfd_getl_signed_64, bfd_putl64, 830 1.1 christos bfd_getl32, bfd_getl_signed_32, bfd_putl32, 831 1.1 christos bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs. */ 832 1.1 christos 833 1.1 christos { /* bfd_check_format */ 834 1.1 christos _bfd_dummy_target, 835 1.1 christos _bfd_dummy_target, 836 1.1 christos pdb_archive_p, 837 1.1 christos _bfd_dummy_target 838 1.1 christos }, 839 1.1 christos { /* bfd_set_format */ 840 1.1 christos _bfd_bool_bfd_false_error, 841 1.1 christos _bfd_bool_bfd_false_error, 842 1.1 christos _bfd_bool_bfd_true, 843 1.1 christos _bfd_bool_bfd_false_error 844 1.1 christos }, 845 1.1 christos { /* bfd_write_contents */ 846 1.1 christos _bfd_bool_bfd_true, 847 1.1 christos _bfd_bool_bfd_false_error, 848 1.1 christos pdb_write_contents, 849 1.1 christos _bfd_bool_bfd_false_error 850 1.1 christos }, 851 1.1 christos 852 1.1 christos BFD_JUMP_TABLE_GENERIC (pdb), 853 1.1 christos BFD_JUMP_TABLE_COPY (_bfd_generic), 854 1.1 christos BFD_JUMP_TABLE_CORE (_bfd_nocore), 855 1.1 christos BFD_JUMP_TABLE_ARCHIVE (pdb), 856 1.1 christos BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols), 857 1.1 christos BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 858 1.1 christos BFD_JUMP_TABLE_WRITE (_bfd_generic), 859 1.1 christos BFD_JUMP_TABLE_LINK (_bfd_nolink), 860 1.1 christos BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 861 1.1 christos 862 1.1 christos NULL, 863 1.1 christos 864 1.1 christos NULL 865 1.1 christos }; 866