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