From 6a69b0a1804fed5ad106ae0664733d6569f30061 Mon Sep 17 00:00:00 2001 From: Mark Harmstone Date: Tue, 13 Sep 2022 10:31:05 +0100 Subject: Add pdb archive format Resubmitted with changes in https://sourceware.org/pipermail/binutils/2022-September/122791.html made. --- bfd/Makefile.am | 2 + bfd/Makefile.in | 3 + bfd/config.bfd | 4 +- bfd/configure | 1 + bfd/configure.ac | 1 + bfd/pdb.c | 814 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ bfd/targets.c | 3 + 7 files changed, 826 insertions(+), 2 deletions(-) create mode 100644 bfd/pdb.c (limited to 'bfd') diff --git a/bfd/Makefile.am b/bfd/Makefile.am index 2fa8df4..04fb335 100644 --- a/bfd/Makefile.am +++ b/bfd/Makefile.am @@ -367,6 +367,7 @@ BFD32_BACKENDS = \ mach-o-arm.lo \ ns32knetbsd.lo \ pc532-mach.lo \ + pdb.lo \ pdp11.lo \ pe-arm-wince.lo \ pe-arm.lo \ @@ -499,6 +500,7 @@ BFD32_BACKENDS_CFILES = \ mach-o-arm.c \ ns32knetbsd.c \ pc532-mach.c \ + pdb.c \ pdp11.c \ pe-arm-wince.c \ pe-arm.c \ diff --git a/bfd/Makefile.in b/bfd/Makefile.in index 3547556..e05b0c9 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -829,6 +829,7 @@ BFD32_BACKENDS = \ mach-o-arm.lo \ ns32knetbsd.lo \ pc532-mach.lo \ + pdb.lo \ pdp11.lo \ pe-arm-wince.lo \ pe-arm.lo \ @@ -961,6 +962,7 @@ BFD32_BACKENDS_CFILES = \ mach-o-arm.c \ ns32knetbsd.c \ pc532-mach.c \ + pdb.c \ pdp11.c \ pe-arm-wince.c \ pe-arm.c \ @@ -1688,6 +1690,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opncls.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osf-core.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pc532-mach.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdp11.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-aarch64igen.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-arm-wince.Plo@am__quote@ diff --git a/bfd/config.bfd b/bfd/config.bfd index a79a0e2..5eb82d7 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -711,7 +711,7 @@ case "${targ}" in ;; x86_64-*-mingw* | x86_64-*-pe | x86_64-*-pep | x86_64-*-cygwin) targ_defvec=x86_64_pe_vec - targ_selvecs="x86_64_pe_vec x86_64_pei_vec x86_64_pe_big_vec x86_64_elf64_vec i386_pe_vec i386_pei_vec i386_elf32_vec iamcu_elf32_vec" + targ_selvecs="x86_64_pe_vec x86_64_pei_vec x86_64_pe_big_vec x86_64_elf64_vec i386_pe_vec i386_pei_vec i386_elf32_vec iamcu_elf32_vec pdb_vec" want64=true targ_underscore=no ;; @@ -765,7 +765,7 @@ case "${targ}" in ;; i[3-7]86-*-mingw32* | i[3-7]86-*-cygwin* | i[3-7]86-*-winnt | i[3-7]86-*-pe) targ_defvec=i386_pe_vec - targ_selvecs="i386_pe_vec i386_pe_big_vec i386_pei_vec i386_elf32_vec iamcu_elf32_vec" + targ_selvecs="i386_pe_vec i386_pe_big_vec i386_pei_vec i386_elf32_vec iamcu_elf32_vec pdb_vec" targ_underscore=yes ;; i[3-7]86-*-vxworks*) diff --git a/bfd/configure b/bfd/configure index b5e44e6..6afdce9 100755 --- a/bfd/configure +++ b/bfd/configure @@ -13481,6 +13481,7 @@ do ns32k_aout_pc532mach_vec) tb="$tb pc532-mach.lo aout-ns32k.lo" ;; ns32k_aout_pc532nbsd_vec) tb="$tb ns32knetbsd.lo aout-ns32k.lo" ;; or1k_elf32_vec) tb="$tb elf32-or1k.lo elf32.lo $elf" ;; + pdb_vec) tb="$tb pdb.lo" ;; pdp11_aout_vec) tb="$tb pdp11.lo" ;; pef_vec) tb="$tb pef.lo" ;; pef_xlib_vec) tb="$tb pef.lo" ;; diff --git a/bfd/configure.ac b/bfd/configure.ac index fb8795b..28f3d1a 100644 --- a/bfd/configure.ac +++ b/bfd/configure.ac @@ -560,6 +560,7 @@ do ns32k_aout_pc532mach_vec) tb="$tb pc532-mach.lo aout-ns32k.lo" ;; ns32k_aout_pc532nbsd_vec) tb="$tb ns32knetbsd.lo aout-ns32k.lo" ;; or1k_elf32_vec) tb="$tb elf32-or1k.lo elf32.lo $elf" ;; + pdb_vec) tb="$tb pdb.lo" ;; pdp11_aout_vec) tb="$tb pdp11.lo" ;; pef_vec) tb="$tb pef.lo" ;; pef_xlib_vec) tb="$tb pef.lo" ;; diff --git a/bfd/pdb.c b/bfd/pdb.c new file mode 100644 index 0000000..9a431c2 --- /dev/null +++ b/bfd/pdb.c @@ -0,0 +1,814 @@ +/* BFD back-end for PDB Multi-Stream Format archives. + Copyright (C) 2022 Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* This describes the MSF file archive format, which is used for the + PDB debug info generated by MSVC. See https://llvm.org/docs/PDB/MsfFile.html + for a full description of the format. */ + +#include "sysdep.h" +#include "bfd.h" +#include "libbfd.h" + +/* "Microsoft C/C++ MSF 7.00\r\n\x1a\x44\x53\0\0\0" */ +static const uint8_t pdb_magic[] = +{ 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, + 0x74, 0x20, 0x43, 0x2f, 0x43, 0x2b, 0x2b, 0x20, + 0x4d, 0x53, 0x46, 0x20, 0x37, 0x2e, 0x30, 0x30, + 0x0d, 0x0a, 0x1a, 0x44, 0x53, 0x00, 0x00, 0x00 }; + +#define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data)) + +static bfd_cleanup +pdb_archive_p (bfd *abfd) +{ + int ret; + char magic[sizeof (pdb_magic)]; + + ret = bfd_bread (magic, sizeof (magic), abfd); + if (ret != sizeof (magic)) + { + bfd_set_error (bfd_error_wrong_format); + return NULL; + } + + if (memcmp (magic, pdb_magic, sizeof (magic))) + { + bfd_set_error (bfd_error_wrong_format); + return NULL; + } + + return _bfd_no_cleanup; +} + +static bfd * +pdb_get_elt_at_index (bfd *abfd, symindex sym_index) +{ + char int_buf[sizeof (uint32_t)]; + uint32_t block_size, block_map_addr, block, num_files; + uint32_t first_dir_block, dir_offset, file_size, block_off, left; + char name[10]; + bfd *file; + char *buf; + + /* Get block_size. */ + + if (bfd_seek (abfd, sizeof (pdb_magic), SEEK_SET)) + return NULL; + + if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + { + bfd_set_error (bfd_error_malformed_archive); + return NULL; + } + + block_size = bfd_getl32 (int_buf); + + /* Get block_map_addr. */ + + if (bfd_seek (abfd, 4 * sizeof (uint32_t), SEEK_CUR)) + return NULL; + + if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + { + bfd_set_error (bfd_error_malformed_archive); + return NULL; + } + + block_map_addr = bfd_getl32 (int_buf); + + /* Get num_files. */ + + if (bfd_seek (abfd, block_map_addr * block_size, SEEK_SET)) + return NULL; + + if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + { + bfd_set_error (bfd_error_malformed_archive); + return NULL; + } + + first_dir_block = bfd_getl32 (int_buf); + + if (bfd_seek (abfd, first_dir_block * block_size, SEEK_SET)) + return NULL; + + if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + { + bfd_set_error (bfd_error_malformed_archive); + return NULL; + } + + num_files = bfd_getl32 (int_buf); + + if (sym_index >= num_files) + { + bfd_set_error (bfd_error_no_more_archived_files); + return NULL; + } + + /* Read file size. */ + + dir_offset = sizeof (uint32_t) * (sym_index + 1); + + if (dir_offset >= block_size) + { + uint32_t block_map_addr_off; + + block_map_addr_off = ((dir_offset / block_size) * sizeof (uint32_t)); + + if (bfd_seek (abfd, (block_map_addr * block_size) + block_map_addr_off, + SEEK_SET)) + return NULL; + + if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + { + bfd_set_error (bfd_error_malformed_archive); + return NULL; + } + + block = bfd_getl32 (int_buf); + } + else + { + block = first_dir_block; + } + + if (bfd_seek (abfd, (block * block_size) + (dir_offset % block_size), + SEEK_SET)) + return NULL; + + if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + { + bfd_set_error (bfd_error_malformed_archive); + return NULL; + } + + file_size = bfd_getl32 (int_buf); + + /* Undocumented? Seen on PDBs created by MSVC 2022. */ + if (file_size == 0xffffffff) + file_size = 0; + + /* Create BFD. */ + + /* Four hex digits is enough - even though MSF allows for 32 bits, the + PDB format itself only uses 16 bits for stream numbers. */ + sprintf (name, "%04lx", sym_index); + + file = bfd_create (name, abfd); + + if (!file) + return NULL; + + if (!bfd_make_writable (file)) + goto fail; + + file->arelt_data = + (struct areltdata *) bfd_malloc (sizeof (struct areltdata)); + + if (!file->arelt_data) + goto fail; + + arch_eltdata (file)->parsed_size = file_size; + arch_eltdata (file)->key = sym_index; + + if (file_size == 0) + return file; + + block_off = 0; + + /* Sum number of blocks in previous files. */ + + if (sym_index != 0) + { + dir_offset = sizeof (uint32_t); + + if (bfd_seek (abfd, (first_dir_block * block_size) + sizeof (uint32_t), + SEEK_SET)) + goto fail; + + for (symindex i = 0; i < sym_index; i++) + { + uint32_t size, num_blocks; + + if ((dir_offset % block_size) == 0) + { + uint32_t block_map_addr_off; + + block_map_addr_off = + ((dir_offset / block_size) * sizeof (uint32_t)); + + if (bfd_seek + (abfd, (block_map_addr * block_size) + block_map_addr_off, + SEEK_SET)) + goto fail; + + if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != + sizeof (uint32_t)) + { + bfd_set_error (bfd_error_malformed_archive); + goto fail; + } + + block = bfd_getl32 (int_buf); + + if (bfd_seek (abfd, block * block_size, SEEK_SET)) + goto fail; + } + + if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != + sizeof (uint32_t)) + { + bfd_set_error (bfd_error_malformed_archive); + goto fail; + } + + size = bfd_getl32 (int_buf); + + if (size == 0xffffffff) + size = 0; + + num_blocks = (size + block_size - 1) / block_size; + block_off += num_blocks; + + dir_offset += sizeof (uint32_t); + } + } + + /* Read blocks, and write into new BFD. */ + + dir_offset = sizeof (uint32_t) * (num_files + block_off + 1); + + if (dir_offset >= block_size) + { + uint32_t block_map_addr_off; + + block_map_addr_off = ((dir_offset / block_size) * sizeof (uint32_t)); + + if (bfd_seek (abfd, (block_map_addr * block_size) + block_map_addr_off, + SEEK_SET)) + goto fail; + + if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + { + bfd_set_error (bfd_error_malformed_archive); + goto fail; + } + + block = bfd_getl32 (int_buf); + } + else + { + block = first_dir_block; + } + + buf = bfd_malloc (block_size); + if (!buf) + goto fail; + + left = file_size; + do + { + uint32_t file_block, to_read; + + if ((dir_offset % block_size) == 0 && left != file_size) + { + uint32_t block_map_addr_off; + + block_map_addr_off = + ((dir_offset / block_size) * sizeof (uint32_t)); + + if (bfd_seek + (abfd, (block_map_addr * block_size) + block_map_addr_off, + SEEK_SET)) + goto fail2; + + if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != + sizeof (uint32_t)) + { + bfd_set_error (bfd_error_malformed_archive); + goto fail2; + } + + block = bfd_getl32 (int_buf); + } + + if (bfd_seek (abfd, (block * block_size) + (dir_offset % block_size), + SEEK_SET)) + goto fail2; + + if (bfd_bread (int_buf, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + { + bfd_set_error (bfd_error_malformed_archive); + goto fail2; + } + + file_block = bfd_getl32 (int_buf); + + if (bfd_seek (abfd, file_block * block_size, SEEK_SET)) + goto fail2; + + to_read = left > block_size ? block_size : left; + + if (bfd_bread (buf, to_read, abfd) != to_read) + { + bfd_set_error (bfd_error_malformed_archive); + goto fail2; + } + + if (bfd_bwrite (buf, to_read, file) != to_read) + goto fail2; + + if (left > block_size) + left -= block_size; + else + break; + + dir_offset += sizeof (uint32_t); + } + while (left > 0); + + free (buf); + + return file; + +fail2: + free (buf); + +fail: + bfd_close (file); + return NULL; +} + +static bfd * +pdb_openr_next_archived_file (bfd *archive, bfd *last_file) +{ + if (!last_file) + return pdb_get_elt_at_index (archive, 0); + else + return pdb_get_elt_at_index (archive, arch_eltdata (last_file)->key + 1); +} + +static int +pdb_generic_stat_arch_elt (bfd *abfd, struct stat *buf) +{ + buf->st_mtime = 0; + buf->st_uid = 0; + buf->st_gid = 0; + buf->st_mode = 0644; + buf->st_size = arch_eltdata (abfd)->parsed_size; + + return 0; +} + +static uint32_t +pdb_allocate_block (uint32_t *num_blocks, uint32_t block_size) +{ + uint32_t block; + + block = *num_blocks; + + (*num_blocks)++; + + /* If new interval, skip two blocks for free space map. */ + + if ((block % block_size) == 1) + { + block += 2; + (*num_blocks) += 2; + } + + return block; +} + +static bool +pdb_write_directory (bfd *abfd, uint32_t block_size, uint32_t num_files, + uint32_t block_map_addr, uint32_t * num_blocks) +{ + char tmp[sizeof (uint32_t)]; + uint32_t block, left, block_map_off; + bfd *arelt; + char *buf; + + /* Allocate first block for directory. */ + + block = pdb_allocate_block (num_blocks, block_size); + left = block_size; + + /* Write allocated block no. at beginning of block map. */ + + if (bfd_seek (abfd, block_map_addr * block_size, SEEK_SET)) + return false; + + bfd_putl32 (block, tmp); + + if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + return false; + + block_map_off = sizeof (uint32_t); + + /* Write num_files at beginning of directory. */ + + if (bfd_seek (abfd, block * block_size, SEEK_SET)) + return false; + + bfd_putl32 (num_files, tmp); + + if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + return false; + + left -= sizeof (uint32_t); + + /* Write file sizes. */ + + arelt = abfd->archive_head; + while (arelt) + { + if (left == 0) + { + if (block_map_off == block_size) /* Too many blocks. */ + { + bfd_set_error (bfd_error_invalid_operation); + return false; + } + + block = pdb_allocate_block (num_blocks, block_size); + left = block_size; + + if (bfd_seek + (abfd, (block_map_addr * block_size) + block_map_off, SEEK_SET)) + return false; + + bfd_putl32 (block, tmp); + + if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + return false; + + block_map_off += sizeof (uint32_t); + + if (bfd_seek (abfd, block * block_size, SEEK_SET)) + return false; + } + + bfd_putl32 (bfd_get_size (arelt), tmp); + + if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + return false; + + left -= sizeof (uint32_t); + + arelt = arelt->archive_next; + } + + /* Write blocks. */ + + buf = bfd_malloc (block_size); + if (!buf) + return false; + + arelt = abfd->archive_head; + while (arelt) + { + ufile_ptr size = bfd_get_size (arelt); + uint32_t req_blocks = (size + block_size - 1) / block_size; + + if (bfd_seek (arelt, 0, SEEK_SET)) + { + free (buf); + return false; + } + + for (uint32_t i = 0; i < req_blocks; i++) + { + uint32_t file_block, to_read; + + if (left == 0) + { + if (block_map_off == block_size) /* Too many blocks. */ + { + bfd_set_error (bfd_error_invalid_operation); + free (buf); + return false; + } + + block = pdb_allocate_block (num_blocks, block_size); + left = block_size; + + if (bfd_seek + (abfd, (block_map_addr * block_size) + block_map_off, + SEEK_SET)) + { + free (buf); + return false; + } + + bfd_putl32 (block, tmp); + + if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != + sizeof (uint32_t)) + { + free (buf); + return false; + } + + block_map_off += sizeof (uint32_t); + + if (bfd_seek (abfd, block * block_size, SEEK_SET)) + { + free (buf); + return false; + } + } + + /* Allocate block and write number into directory. */ + + file_block = pdb_allocate_block (num_blocks, block_size); + + bfd_putl32 (file_block, tmp); + + if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + { + free (buf); + return false; + } + + left -= sizeof (uint32_t); + + /* Read file contents into buffer. */ + + to_read = size > block_size ? block_size : size; + + if (bfd_bread (buf, to_read, arelt) != to_read) + { + free (buf); + return false; + } + + size -= to_read; + + if (to_read < block_size) + memset (buf + to_read, 0, block_size - to_read); + + if (bfd_seek (abfd, file_block * block_size, SEEK_SET)) + { + free (buf); + return false; + } + + /* Write file contents into allocated block. */ + + if (bfd_bwrite (buf, block_size, abfd) != block_size) + { + free (buf); + return false; + } + + if (bfd_seek + (abfd, (block * block_size) + block_size - left, SEEK_SET)) + { + free (buf); + return false; + } + } + + arelt = arelt->archive_next; + } + + memset (buf, 0, left); + + if (bfd_bwrite (buf, left, abfd) != left) + { + free (buf); + return false; + } + + free (buf); + + return true; +} + +static bool +pdb_write_bitmap (bfd *abfd, uint32_t block_size, uint32_t num_blocks) +{ + char *buf; + uint32_t num_intervals = (num_blocks + block_size - 1) / block_size; + + buf = bfd_malloc (block_size); + if (!buf) + return false; + + num_blocks--; /* Superblock not included. */ + + for (uint32_t i = 0; i < num_intervals; i++) + { + if (bfd_seek (abfd, ((i * block_size) + 1) * block_size, SEEK_SET)) + { + free (buf); + return false; + } + + /* All of our blocks are contiguous, making our free block map simple. + 0 = used, 1 = free. */ + + if (num_blocks >= 8) + memset (buf, 0, + (num_blocks / 8) > + block_size ? block_size : (num_blocks / 8)); + + if (num_blocks < block_size * 8) + { + unsigned int off = num_blocks / 8; + + if (num_blocks % 8) + { + buf[off] = (1 << (8 - (num_blocks % 8))) - 1; + off++; + } + + if (off < block_size) + memset (buf + off, 0xff, block_size - off); + } + + if (num_blocks < block_size * 8) + num_blocks = 0; + else + num_blocks -= block_size * 8; + + if (bfd_bwrite (buf, block_size, abfd) != block_size) + return false; + } + + free (buf); + + return true; +} + +static bool +pdb_write_contents (bfd *abfd) +{ + char tmp[sizeof (uint32_t)]; + const uint32_t block_size = 0x400; + uint32_t block_map_addr; + uint32_t num_blocks; + uint32_t num_files = 0; + uint32_t num_directory_bytes = sizeof (uint32_t); + bfd *arelt; + + if (bfd_bwrite (pdb_magic, sizeof (pdb_magic), abfd) != sizeof (pdb_magic)) + return false; + + bfd_putl32 (block_size, tmp); + + if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + return false; + + bfd_putl32 (1, tmp); /* Free block map block (always either 1 or 2). */ + + if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + return false; + + arelt = abfd->archive_head; + + while (arelt) + { + uint32_t blocks_required = + (bfd_get_size (arelt) + block_size - 1) / block_size; + + num_directory_bytes += sizeof (uint32_t); /* Size. */ + num_directory_bytes += blocks_required * sizeof (uint32_t); /* Blocks. */ + + num_files++; + + arelt = arelt->archive_next; + } + + /* Superblock plus two bitmap blocks. */ + num_blocks = 3; + + /* Skip num_blocks for now. */ + if (bfd_seek (abfd, sizeof (uint32_t), SEEK_CUR)) + return false; + + bfd_putl32 (num_directory_bytes, tmp); + + if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + return false; + + /* Skip unknown uint32_t (always 0?). */ + if (bfd_seek (abfd, sizeof (uint32_t), SEEK_CUR)) + return false; + + block_map_addr = pdb_allocate_block (&num_blocks, block_size); + + bfd_putl32 (block_map_addr, tmp); + + if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + return false; + + if (!pdb_write_directory + (abfd, block_size, num_files, block_map_addr, &num_blocks)) + return false; + + if (!pdb_write_bitmap (abfd, block_size, num_blocks)) + return false; + + /* Write num_blocks now we know it. */ + + if (bfd_seek + (abfd, sizeof (pdb_magic) + sizeof (uint32_t) + sizeof (uint32_t), + SEEK_SET)) + return false; + + bfd_putl32 (num_blocks, tmp); + + if (bfd_bwrite (tmp, sizeof (uint32_t), abfd) != sizeof (uint32_t)) + return false; + + return true; +} + +#define pdb_bfd_free_cached_info _bfd_generic_bfd_free_cached_info +#define pdb_new_section_hook _bfd_generic_new_section_hook +#define pdb_get_section_contents _bfd_generic_get_section_contents +#define pdb_get_section_contents_in_window _bfd_generic_get_section_contents_in_window +#define pdb_close_and_cleanup _bfd_bool_bfd_true + +#define pdb_slurp_armap _bfd_noarchive_slurp_armap +#define pdb_slurp_extended_name_table _bfd_noarchive_slurp_extended_name_table +#define pdb_construct_extended_name_table _bfd_noarchive_construct_extended_name_table +#define pdb_truncate_arname _bfd_noarchive_truncate_arname +#define pdb_write_armap _bfd_noarchive_write_armap +#define pdb_read_ar_hdr _bfd_noarchive_read_ar_hdr +#define pdb_write_ar_hdr _bfd_noarchive_write_ar_hdr +#define pdb_update_armap_timestamp _bfd_noarchive_update_armap_timestamp + +const bfd_target pdb_vec = +{ + "pdb", + bfd_target_unknown_flavour, + BFD_ENDIAN_LITTLE, /* target byte order */ + BFD_ENDIAN_LITTLE, /* target headers byte order */ + 0, /* object flags */ + 0, /* section flags */ + 0, /* leading underscore */ + ' ', /* ar_pad_char */ + 16, /* ar_max_namelen */ + 0, /* match priority. */ + TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */ + bfd_getl64, bfd_getl_signed_64, bfd_putl64, + bfd_getl32, bfd_getl_signed_32, bfd_putl32, + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */ + bfd_getl64, bfd_getl_signed_64, bfd_putl64, + bfd_getl32, bfd_getl_signed_32, bfd_putl32, + bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs. */ + + { /* bfd_check_format */ + _bfd_dummy_target, + _bfd_dummy_target, + pdb_archive_p, + _bfd_dummy_target + }, + { /* bfd_set_format */ + _bfd_bool_bfd_false_error, + _bfd_bool_bfd_false_error, + _bfd_bool_bfd_true, + _bfd_bool_bfd_false_error + }, + { /* bfd_write_contents */ + _bfd_bool_bfd_true, + _bfd_bool_bfd_false_error, + pdb_write_contents, + _bfd_bool_bfd_false_error + }, + + BFD_JUMP_TABLE_GENERIC (pdb), + BFD_JUMP_TABLE_COPY (_bfd_generic), + BFD_JUMP_TABLE_CORE (_bfd_nocore), + BFD_JUMP_TABLE_ARCHIVE (pdb), + BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols), + BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), + BFD_JUMP_TABLE_WRITE (_bfd_generic), + BFD_JUMP_TABLE_LINK (_bfd_nolink), + BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), + + NULL, + + NULL +}; diff --git a/bfd/targets.c b/bfd/targets.c index 1ec8acd..dc33123 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -840,6 +840,7 @@ extern const bfd_target nios2_elf32_le_vec; extern const bfd_target ns32k_aout_pc532mach_vec; extern const bfd_target ns32k_aout_pc532nbsd_vec; extern const bfd_target or1k_elf32_vec; +extern const bfd_target pdb_vec; extern const bfd_target pdp11_aout_vec; extern const bfd_target pef_vec; extern const bfd_target pef_xlib_vec; @@ -1221,6 +1222,8 @@ static const bfd_target * const _bfd_target_vector[] = &or1k_elf32_vec, + &pdb_vec, + &pdp11_aout_vec, &pef_vec, -- cgit v1.1