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