1 1.1 christos /* BFD back-end for VMS archive files. 2 1.1 christos 3 1.1.1.11 christos Copyright (C) 2010-2026 Free Software Foundation, Inc. 4 1.1 christos Written by Tristan Gingold <gingold (at) adacore.com>, AdaCore. 5 1.1 christos 6 1.1 christos This file is part of BFD, the Binary File Descriptor library. 7 1.1 christos 8 1.1 christos This program is free software; you can redistribute it and/or modify 9 1.1 christos it under the terms of the GNU General Public License as published by 10 1.1 christos the Free Software Foundation; either version 3 of the License, or 11 1.1 christos (at your option) any later version. 12 1.1 christos 13 1.1 christos This program is distributed in the hope that it will be useful, 14 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 15 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 1.1 christos GNU General Public License for more details. 17 1.1 christos 18 1.1 christos You should have received a copy of the GNU General Public License 19 1.1 christos along with this program; if not, write to the Free Software 20 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21 1.1 christos MA 02110-1301, USA. */ 22 1.1 christos 23 1.1 christos #include "sysdep.h" 24 1.1 christos #include "bfd.h" 25 1.1 christos #include "libbfd.h" 26 1.1 christos #include "safe-ctype.h" 27 1.1 christos #include "bfdver.h" 28 1.1.1.3 christos #include "libiberty.h" 29 1.1 christos #include "vms.h" 30 1.1 christos #include "vms/lbr.h" 31 1.1 christos #include "vms/dcx.h" 32 1.1 christos 33 1.1 christos /* The standard VMS disk block size. */ 34 1.1 christos #ifndef VMS_BLOCK_SIZE 35 1.1 christos #define VMS_BLOCK_SIZE 512 36 1.1 christos #endif 37 1.1 christos 38 1.1 christos /* Maximum key length (which is also the maximum symbol length in archive). */ 39 1.1.1.2 christos #define MAX_KEYLEN 128 40 1.1.1.2 christos #define MAX_EKEYLEN 1024 41 1.1 christos 42 1.1 christos /* DCX Submaps. */ 43 1.1 christos 44 1.1 christos struct dcxsbm_desc 45 1.1 christos { 46 1.1 christos unsigned char min_char; 47 1.1 christos unsigned char max_char; 48 1.1 christos unsigned char *flags; 49 1.1 christos unsigned char *nodes; 50 1.1 christos unsigned short *next; 51 1.1 christos }; 52 1.1 christos 53 1.1 christos /* Kind of library. Used to filter in archive_p. */ 54 1.1 christos 55 1.1 christos enum vms_lib_kind 56 1.1 christos { 57 1.1 christos vms_lib_vax, 58 1.1 christos vms_lib_alpha, 59 1.1 christos vms_lib_ia64, 60 1.1 christos vms_lib_txt 61 1.1 christos }; 62 1.1 christos 63 1.1 christos /* Back-end private data. */ 64 1.1 christos 65 1.1 christos struct lib_tdata 66 1.1 christos { 67 1.1 christos /* Standard tdata for an archive. But we don't use many fields. */ 68 1.1 christos struct artdata artdata; 69 1.1 christos 70 1.1 christos /* Major version. */ 71 1.1 christos unsigned char ver; 72 1.1 christos 73 1.1 christos /* Type of the archive. */ 74 1.1 christos unsigned char type; 75 1.1 christos 76 1.1 christos /* Kind of archive. Summary of its type. */ 77 1.1 christos enum vms_lib_kind kind; 78 1.1 christos 79 1.1 christos /* Total size of the mhd (element header). */ 80 1.1 christos unsigned int mhd_size; 81 1.1 christos 82 1.1 christos /* Creation date. */ 83 1.1 christos unsigned int credat_lo; 84 1.1 christos unsigned int credat_hi; 85 1.1 christos 86 1.1 christos /* Vector of modules (archive elements), already sorted. */ 87 1.1 christos unsigned int nbr_modules; 88 1.1 christos struct carsym *modules; 89 1.1 christos bfd **cache; 90 1.1 christos 91 1.1 christos /* DCX (decompression) data. */ 92 1.1 christos unsigned int nbr_dcxsbm; 93 1.1 christos struct dcxsbm_desc *dcxsbm; 94 1.1 christos }; 95 1.1 christos 96 1.1 christos #define bfd_libdata(bfd) ((struct lib_tdata *)((bfd)->tdata.any)) 97 1.1 christos 98 1.1 christos /* End-Of-Text pattern. This is a special record to mark the end of file. */ 99 1.1 christos 100 1.1 christos static const unsigned char eotdesc[] = { 0x03, 0x00, 0x77, 0x00, 0x77, 0x00 }; 101 1.1 christos 102 1.1 christos /* Describe the current state of carsym entries while building the archive 103 1.1 christos table of content. Things are simple with Alpha archives as the number 104 1.1 christos of entries is known, but with IA64 archives a entry can make a reference 105 1.1 christos to severals members. Therefore we must be able to extend the table on the 106 1.1 christos fly, but it should be allocated on the bfd - which doesn't support realloc. 107 1.1 christos To reduce the overhead, the table is initially allocated in the BFD's 108 1.1 christos objalloc and extended if necessary on the heap. In the later case, it 109 1.1 christos is finally copied to the BFD's objalloc so that it will automatically be 110 1.1 christos freed. */ 111 1.1 christos 112 1.1 christos struct carsym_mem 113 1.1 christos { 114 1.1 christos /* The table of content. */ 115 1.1 christos struct carsym *idx; 116 1.1 christos 117 1.1 christos /* Number of entries used in the table. */ 118 1.1 christos unsigned int nbr; 119 1.1 christos 120 1.1 christos /* Maximum number of entries. */ 121 1.1 christos unsigned int max; 122 1.1 christos 123 1.1.1.8 christos /* Do not allocate more that this number of entries. */ 124 1.1.1.8 christos unsigned int limit; 125 1.1.1.8 christos 126 1.1 christos /* If true, the table was reallocated on the heap. If false, it is still 127 1.1 christos in the BFD's objalloc. */ 128 1.1.1.8 christos bool realloced; 129 1.1 christos }; 130 1.1 christos 131 1.1 christos /* Simply add a name to the index. */ 132 1.1 christos 133 1.1.1.8 christos static bool 134 1.1 christos vms_add_index (struct carsym_mem *cs, char *name, 135 1.1.1.5 christos unsigned int idx_vbn, unsigned int idx_off) 136 1.1 christos { 137 1.1 christos if (cs->nbr == cs->max) 138 1.1 christos { 139 1.1 christos struct carsym *n; 140 1.1.1.8 christos size_t amt; 141 1.1 christos 142 1.1.1.8 christos if (cs->max > -33u / 2 || cs->max >= cs->limit) 143 1.1.1.8 christos { 144 1.1.1.8 christos bfd_set_error (bfd_error_file_too_big); 145 1.1.1.8 christos return false; 146 1.1.1.8 christos } 147 1.1 christos cs->max = 2 * cs->max + 32; 148 1.1.1.8 christos if (cs->max > cs->limit) 149 1.1.1.8 christos cs->max = cs->limit; 150 1.1.1.8 christos if (_bfd_mul_overflow (cs->max, sizeof (struct carsym), &amt)) 151 1.1.1.8 christos { 152 1.1.1.8 christos bfd_set_error (bfd_error_file_too_big); 153 1.1.1.8 christos return false; 154 1.1.1.8 christos } 155 1.1 christos 156 1.1 christos if (!cs->realloced) 157 1.1.1.5 christos { 158 1.1.1.8 christos n = bfd_malloc (amt); 159 1.1.1.5 christos if (n == NULL) 160 1.1.1.8 christos return false; 161 1.1.1.5 christos memcpy (n, cs->idx, cs->nbr * sizeof (struct carsym)); 162 1.1.1.5 christos /* And unfortunately we can't free cs->idx. */ 163 1.1.1.5 christos } 164 1.1 christos else 165 1.1.1.5 christos { 166 1.1.1.8 christos n = bfd_realloc_or_free (cs->idx, amt); 167 1.1.1.5 christos if (n == NULL) 168 1.1.1.8 christos return false; 169 1.1.1.5 christos } 170 1.1 christos cs->idx = n; 171 1.1.1.8 christos cs->realloced = true; 172 1.1 christos } 173 1.1 christos cs->idx[cs->nbr].file_offset = (idx_vbn - 1) * VMS_BLOCK_SIZE + idx_off; 174 1.1 christos cs->idx[cs->nbr].name = name; 175 1.1 christos cs->nbr++; 176 1.1.1.8 christos return true; 177 1.1 christos } 178 1.1 christos 179 1.1 christos /* Follow all member of a lns list (pointed by RFA) and add indexes for 180 1.1 christos NAME. Return FALSE in case of error. */ 181 1.1 christos 182 1.1.1.8 christos static bool 183 1.1 christos vms_add_indexes_from_list (bfd *abfd, struct carsym_mem *cs, char *name, 184 1.1.1.5 christos struct vms_rfa *rfa) 185 1.1 christos { 186 1.1 christos struct vms_lns lns; 187 1.1 christos unsigned int vbn; 188 1.1 christos file_ptr off; 189 1.1 christos 190 1.1 christos while (1) 191 1.1 christos { 192 1.1 christos vbn = bfd_getl32 (rfa->vbn); 193 1.1 christos if (vbn == 0) 194 1.1.1.8 christos return true; 195 1.1 christos 196 1.1 christos /* Read the LHS. */ 197 1.1 christos off = (vbn - 1) * VMS_BLOCK_SIZE + bfd_getl16 (rfa->offset); 198 1.1 christos if (bfd_seek (abfd, off, SEEK_SET) != 0 199 1.1.1.9 christos || bfd_read (&lns, sizeof (lns), abfd) != sizeof (lns)) 200 1.1.1.8 christos return false; 201 1.1 christos 202 1.1 christos if (!vms_add_index (cs, name, 203 1.1.1.5 christos bfd_getl32 (lns.modrfa.vbn), 204 1.1.1.5 christos bfd_getl16 (lns.modrfa.offset))) 205 1.1.1.8 christos return false; 206 1.1 christos 207 1.1 christos rfa = &lns.nxtrfa; 208 1.1 christos } 209 1.1 christos } 210 1.1 christos 211 1.1 christos /* Read block VBN from ABFD and store it into BLK. Return FALSE in case of error. */ 212 1.1 christos 213 1.1.1.8 christos static bool 214 1.1 christos vms_read_block (bfd *abfd, unsigned int vbn, void *blk) 215 1.1 christos { 216 1.1 christos file_ptr off; 217 1.1 christos 218 1.1 christos off = (vbn - 1) * VMS_BLOCK_SIZE; 219 1.1 christos if (bfd_seek (abfd, off, SEEK_SET) != 0 220 1.1.1.9 christos || bfd_read (blk, VMS_BLOCK_SIZE, abfd) != VMS_BLOCK_SIZE) 221 1.1.1.8 christos return false; 222 1.1 christos 223 1.1.1.8 christos return true; 224 1.1 christos } 225 1.1 christos 226 1.1 christos /* Write the content of BLK to block VBN of ABFD. Return FALSE in case of error. */ 227 1.1 christos 228 1.1.1.8 christos static bool 229 1.1 christos vms_write_block (bfd *abfd, unsigned int vbn, void *blk) 230 1.1 christos { 231 1.1 christos file_ptr off; 232 1.1 christos 233 1.1 christos off = (vbn - 1) * VMS_BLOCK_SIZE; 234 1.1 christos if (bfd_seek (abfd, off, SEEK_SET) != 0 235 1.1.1.9 christos || bfd_write (blk, VMS_BLOCK_SIZE, abfd) != VMS_BLOCK_SIZE) 236 1.1.1.8 christos return false; 237 1.1 christos 238 1.1.1.8 christos return true; 239 1.1 christos } 240 1.1 christos 241 1.1 christos /* Read index block VBN and put the entry in **IDX (which is updated). 242 1.1 christos If the entry is indirect, recurse. */ 243 1.1 christos 244 1.1.1.8 christos static bool 245 1.1.1.8 christos vms_traverse_index (bfd *abfd, unsigned int vbn, struct carsym_mem *cs, 246 1.1.1.8 christos unsigned int recur_count) 247 1.1 christos { 248 1.1 christos struct vms_indexdef indexdef; 249 1.1 christos file_ptr off; 250 1.1 christos unsigned char *p; 251 1.1 christos unsigned char *endp; 252 1.1.1.8 christos unsigned int n; 253 1.1.1.8 christos 254 1.1.1.8 christos if (recur_count == 100) 255 1.1.1.8 christos { 256 1.1.1.8 christos bfd_set_error (bfd_error_bad_value); 257 1.1.1.8 christos return false; 258 1.1.1.8 christos } 259 1.1 christos 260 1.1 christos /* Read the index block. */ 261 1.1 christos BFD_ASSERT (sizeof (indexdef) == VMS_BLOCK_SIZE); 262 1.1 christos if (!vms_read_block (abfd, vbn, &indexdef)) 263 1.1.1.8 christos return false; 264 1.1 christos 265 1.1 christos /* Traverse it. */ 266 1.1 christos p = &indexdef.keys[0]; 267 1.1.1.8 christos n = bfd_getl16 (indexdef.used); 268 1.1.1.8 christos if (n > sizeof (indexdef.keys)) 269 1.1.1.8 christos return false; 270 1.1.1.8 christos endp = p + n; 271 1.1 christos while (p < endp) 272 1.1 christos { 273 1.1 christos unsigned int idx_vbn; 274 1.1 christos unsigned int idx_off; 275 1.1 christos unsigned int keylen; 276 1.1 christos unsigned char *keyname; 277 1.1 christos unsigned int flags; 278 1.1 christos 279 1.1 christos /* Extract key length. */ 280 1.1.1.8 christos if (bfd_libdata (abfd)->ver == LBR_MAJORID 281 1.1.1.8 christos && offsetof (struct vms_idx, keyname) <= (size_t) (endp - p)) 282 1.1.1.5 christos { 283 1.1.1.5 christos struct vms_idx *ridx = (struct vms_idx *)p; 284 1.1 christos 285 1.1.1.5 christos idx_vbn = bfd_getl32 (ridx->rfa.vbn); 286 1.1.1.5 christos idx_off = bfd_getl16 (ridx->rfa.offset); 287 1.1 christos 288 1.1.1.5 christos keylen = ridx->keylen; 289 1.1.1.5 christos flags = 0; 290 1.1.1.5 christos keyname = ridx->keyname; 291 1.1.1.5 christos } 292 1.1.1.8 christos else if (bfd_libdata (abfd)->ver == LBR_ELFMAJORID 293 1.1.1.8 christos && offsetof (struct vms_elfidx, keyname) <= (size_t) (endp - p)) 294 1.1.1.5 christos { 295 1.1.1.5 christos struct vms_elfidx *ridx = (struct vms_elfidx *)p; 296 1.1 christos 297 1.1.1.5 christos idx_vbn = bfd_getl32 (ridx->rfa.vbn); 298 1.1.1.5 christos idx_off = bfd_getl16 (ridx->rfa.offset); 299 1.1 christos 300 1.1.1.5 christos keylen = bfd_getl16 (ridx->keylen); 301 1.1.1.5 christos flags = ridx->flags; 302 1.1.1.5 christos keyname = ridx->keyname; 303 1.1.1.5 christos } 304 1.1 christos else 305 1.1.1.8 christos return false; 306 1.1 christos 307 1.1 christos /* Illegal value. */ 308 1.1 christos if (idx_vbn == 0) 309 1.1.1.8 christos return false; 310 1.1 christos 311 1.1.1.2 christos /* Point to the next index entry. */ 312 1.1.1.2 christos p = keyname + keylen; 313 1.1.1.8 christos if (p > endp) 314 1.1.1.8 christos return false; 315 1.1.1.2 christos 316 1.1 christos if (idx_off == RFADEF__C_INDEX) 317 1.1.1.5 christos { 318 1.1.1.5 christos /* Indirect entry. Recurse. */ 319 1.1.1.8 christos if (!vms_traverse_index (abfd, idx_vbn, cs, recur_count + 1)) 320 1.1.1.8 christos return false; 321 1.1.1.5 christos } 322 1.1 christos else 323 1.1.1.5 christos { 324 1.1.1.5 christos /* Add a new entry. */ 325 1.1.1.5 christos char *name; 326 1.1.1.5 christos 327 1.1.1.5 christos if (flags & ELFIDX__SYMESC) 328 1.1.1.5 christos { 329 1.1.1.5 christos /* Extended key name. */ 330 1.1.1.5 christos unsigned int noff = 0; 331 1.1.1.5 christos unsigned int koff; 332 1.1.1.5 christos unsigned int kvbn; 333 1.1.1.5 christos struct vms_kbn *kbn; 334 1.1.1.5 christos unsigned char kblk[VMS_BLOCK_SIZE]; 335 1.1.1.5 christos 336 1.1.1.5 christos /* Sanity check. */ 337 1.1.1.5 christos if (keylen != sizeof (struct vms_kbn)) 338 1.1.1.8 christos return false; 339 1.1.1.5 christos 340 1.1.1.5 christos kbn = (struct vms_kbn *)keyname; 341 1.1.1.5 christos keylen = bfd_getl16 (kbn->keylen); 342 1.1.1.5 christos 343 1.1.1.5 christos name = bfd_alloc (abfd, keylen + 1); 344 1.1.1.5 christos if (name == NULL) 345 1.1.1.8 christos return false; 346 1.1.1.5 christos kvbn = bfd_getl32 (kbn->rfa.vbn); 347 1.1.1.5 christos koff = bfd_getl16 (kbn->rfa.offset); 348 1.1.1.5 christos 349 1.1.1.5 christos /* Read the key, chunk by chunk. */ 350 1.1.1.5 christos do 351 1.1.1.5 christos { 352 1.1.1.5 christos unsigned int klen; 353 1.1.1.5 christos 354 1.1.1.5 christos if (!vms_read_block (abfd, kvbn, kblk)) 355 1.1.1.8 christos return false; 356 1.1.1.8 christos if (koff > sizeof (kblk) - sizeof (struct vms_kbn)) 357 1.1.1.8 christos return false; 358 1.1.1.5 christos kbn = (struct vms_kbn *)(kblk + koff); 359 1.1.1.5 christos klen = bfd_getl16 (kbn->keylen); 360 1.1.1.8 christos if (klen > sizeof (kblk) - sizeof (struct vms_kbn) - koff) 361 1.1.1.8 christos return false; 362 1.1.1.5 christos kvbn = bfd_getl32 (kbn->rfa.vbn); 363 1.1.1.5 christos koff = bfd_getl16 (kbn->rfa.offset); 364 1.1.1.5 christos 365 1.1.1.8 christos if (noff + klen > keylen) 366 1.1.1.8 christos return false; 367 1.1.1.5 christos memcpy (name + noff, kbn + 1, klen); 368 1.1.1.5 christos noff += klen; 369 1.1.1.5 christos } 370 1.1.1.5 christos while (kvbn != 0); 371 1.1.1.5 christos 372 1.1.1.5 christos /* Sanity check. */ 373 1.1.1.5 christos if (noff != keylen) 374 1.1.1.8 christos return false; 375 1.1.1.5 christos } 376 1.1.1.5 christos else 377 1.1.1.5 christos { 378 1.1.1.5 christos /* Usual key name. */ 379 1.1.1.5 christos name = bfd_alloc (abfd, keylen + 1); 380 1.1.1.5 christos if (name == NULL) 381 1.1.1.8 christos return false; 382 1.1.1.5 christos 383 1.1.1.5 christos memcpy (name, keyname, keylen); 384 1.1.1.5 christos } 385 1.1.1.5 christos name[keylen] = 0; 386 1.1.1.5 christos 387 1.1.1.5 christos if (flags & ELFIDX__LISTRFA) 388 1.1.1.5 christos { 389 1.1.1.5 christos struct vms_lhs lhs; 390 1.1.1.5 christos 391 1.1.1.5 christos /* Read the LHS. */ 392 1.1.1.5 christos off = (idx_vbn - 1) * VMS_BLOCK_SIZE + idx_off; 393 1.1.1.5 christos if (bfd_seek (abfd, off, SEEK_SET) != 0 394 1.1.1.9 christos || bfd_read (&lhs, sizeof (lhs), abfd) != sizeof (lhs)) 395 1.1.1.8 christos return false; 396 1.1.1.5 christos 397 1.1.1.8 christos /* These extra entries may cause reallocation of CS. */ 398 1.1.1.5 christos if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.ng_g_rfa)) 399 1.1.1.8 christos return false; 400 1.1.1.5 christos if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.ng_wk_rfa)) 401 1.1.1.8 christos return false; 402 1.1.1.5 christos if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.g_g_rfa)) 403 1.1.1.8 christos return false; 404 1.1.1.5 christos if (!vms_add_indexes_from_list (abfd, cs, name, &lhs.g_wk_rfa)) 405 1.1.1.8 christos return false; 406 1.1.1.5 christos } 407 1.1.1.5 christos else 408 1.1.1.5 christos { 409 1.1.1.5 christos if (!vms_add_index (cs, name, idx_vbn, idx_off)) 410 1.1.1.8 christos return false; 411 1.1.1.5 christos } 412 1.1.1.5 christos } 413 1.1 christos } 414 1.1 christos 415 1.1.1.8 christos return true; 416 1.1 christos } 417 1.1 christos 418 1.1 christos /* Read index #IDX, which must have NBREL entries. */ 419 1.1 christos 420 1.1 christos static struct carsym * 421 1.1 christos vms_lib_read_index (bfd *abfd, int idx, unsigned int *nbrel) 422 1.1 christos { 423 1.1 christos struct vms_idd idd; 424 1.1 christos unsigned int flags; 425 1.1 christos unsigned int vbn; 426 1.1.1.8 christos ufile_ptr filesize; 427 1.1.1.8 christos size_t amt; 428 1.1 christos struct carsym *csbuf; 429 1.1 christos struct carsym_mem csm; 430 1.1 christos 431 1.1 christos /* Read index desription. */ 432 1.1 christos if (bfd_seek (abfd, LHD_IDXDESC + idx * IDD_LENGTH, SEEK_SET) != 0 433 1.1.1.9 christos || bfd_read (&idd, sizeof (idd), abfd) != sizeof (idd)) 434 1.1 christos return NULL; 435 1.1 christos 436 1.1 christos /* Sanity checks. */ 437 1.1 christos flags = bfd_getl16 (idd.flags); 438 1.1 christos if (!(flags & IDD__FLAGS_ASCII) 439 1.1 christos || !(flags & IDD__FLAGS_VARLENIDX)) 440 1.1 christos return NULL; 441 1.1 christos 442 1.1.1.8 christos filesize = bfd_get_file_size (abfd); 443 1.1 christos csm.nbr = 0; 444 1.1.1.8 christos csm.max = *nbrel; 445 1.1.1.8 christos csm.limit = -1u; 446 1.1.1.8 christos csm.realloced = false; 447 1.1.1.8 christos if (filesize != 0) 448 1.1.1.8 christos { 449 1.1.1.8 christos /* Put an upper bound based on a file full of single char keys. 450 1.1.1.8 christos This is to prevent fuzzed binary silliness. It is easily 451 1.1.1.8 christos possible to set up loops over file blocks that add syms 452 1.1.1.8 christos without end. */ 453 1.1.1.8 christos if (filesize / (sizeof (struct vms_rfa) + 2) <= -1u) 454 1.1.1.8 christos csm.limit = filesize / (sizeof (struct vms_rfa) + 2); 455 1.1.1.8 christos } 456 1.1.1.8 christos if (csm.max > csm.limit) 457 1.1.1.8 christos csm.max = csm.limit; 458 1.1.1.8 christos if (_bfd_mul_overflow (csm.max, sizeof (struct carsym), &amt)) 459 1.1.1.8 christos return NULL; 460 1.1.1.8 christos csm.idx = csbuf = bfd_alloc (abfd, amt); 461 1.1.1.8 christos if (csm.idx == NULL) 462 1.1.1.8 christos return NULL; 463 1.1 christos 464 1.1 christos /* Note: if the index is empty, there is no block to traverse. */ 465 1.1 christos vbn = bfd_getl32 (idd.vbn); 466 1.1.1.8 christos if (vbn != 0 && !vms_traverse_index (abfd, vbn, &csm, 0)) 467 1.1 christos { 468 1.1.1.8 christos if (csm.realloced) 469 1.1.1.5 christos free (csm.idx); 470 1.1 christos 471 1.1 christos /* Note: in case of error, we can free what was allocated on the 472 1.1.1.5 christos BFD's objalloc. */ 473 1.1 christos bfd_release (abfd, csbuf); 474 1.1 christos return NULL; 475 1.1 christos } 476 1.1 christos 477 1.1 christos if (csm.realloced) 478 1.1 christos { 479 1.1 christos /* There are more entries than the first estimate. Allocate on 480 1.1.1.5 christos the BFD's objalloc. */ 481 1.1 christos csbuf = bfd_alloc (abfd, csm.nbr * sizeof (struct carsym)); 482 1.1 christos if (csbuf == NULL) 483 1.1.1.9 christos { 484 1.1.1.9 christos free (csm.idx); 485 1.1.1.9 christos return NULL; 486 1.1.1.9 christos } 487 1.1 christos memcpy (csbuf, csm.idx, csm.nbr * sizeof (struct carsym)); 488 1.1 christos free (csm.idx); 489 1.1.1.8 christos csm.idx = csbuf; 490 1.1 christos } 491 1.1.1.8 christos *nbrel = csm.nbr; 492 1.1.1.8 christos return csm.idx; 493 1.1 christos } 494 1.1 christos 495 1.1 christos /* Standard function. */ 496 1.1 christos 497 1.1.1.8 christos static bfd_cleanup 498 1.1 christos _bfd_vms_lib_archive_p (bfd *abfd, enum vms_lib_kind kind) 499 1.1 christos { 500 1.1 christos struct vms_lhd lhd; 501 1.1 christos unsigned int sanity; 502 1.1 christos unsigned int majorid; 503 1.1 christos struct lib_tdata *tdata_hold; 504 1.1 christos struct lib_tdata *tdata; 505 1.1 christos unsigned int dcxvbn; 506 1.1 christos unsigned int nbr_ent; 507 1.1 christos 508 1.1 christos /* Read header. */ 509 1.1.1.9 christos if (bfd_read (&lhd, sizeof (lhd), abfd) != sizeof (lhd)) 510 1.1 christos { 511 1.1 christos if (bfd_get_error () != bfd_error_system_call) 512 1.1 christos bfd_set_error (bfd_error_wrong_format); 513 1.1 christos return NULL; 514 1.1 christos } 515 1.1 christos 516 1.1 christos /* Check sanity (= magic) number. */ 517 1.1 christos sanity = bfd_getl32 (lhd.sanity); 518 1.1 christos if (!(sanity == LHD_SANEID3 519 1.1.1.5 christos || sanity == LHD_SANEID6 520 1.1.1.5 christos || sanity == LHD_SANEID_DCX)) 521 1.1 christos { 522 1.1 christos bfd_set_error (bfd_error_wrong_format); 523 1.1 christos return NULL; 524 1.1 christos } 525 1.1 christos majorid = bfd_getl32 (lhd.majorid); 526 1.1 christos 527 1.1 christos /* Check archive kind. */ 528 1.1 christos switch (kind) 529 1.1 christos { 530 1.1 christos case vms_lib_alpha: 531 1.1 christos if ((lhd.type != LBR__C_TYP_EOBJ && lhd.type != LBR__C_TYP_ESHSTB) 532 1.1.1.5 christos || majorid != LBR_MAJORID 533 1.1.1.5 christos || lhd.nindex != 2) 534 1.1.1.5 christos { 535 1.1.1.5 christos bfd_set_error (bfd_error_wrong_format); 536 1.1.1.5 christos return NULL; 537 1.1.1.5 christos } 538 1.1 christos break; 539 1.1 christos case vms_lib_ia64: 540 1.1 christos if ((lhd.type != LBR__C_TYP_IOBJ && lhd.type != LBR__C_TYP_ISHSTB) 541 1.1.1.5 christos || majorid != LBR_ELFMAJORID 542 1.1.1.5 christos || lhd.nindex != 2) 543 1.1.1.5 christos { 544 1.1.1.5 christos bfd_set_error (bfd_error_wrong_format); 545 1.1.1.5 christos return NULL; 546 1.1.1.5 christos } 547 1.1 christos break; 548 1.1 christos case vms_lib_txt: 549 1.1 christos if ((lhd.type != LBR__C_TYP_TXT 550 1.1.1.5 christos && lhd.type != LBR__C_TYP_MLB 551 1.1.1.5 christos && lhd.type != LBR__C_TYP_HLP) 552 1.1.1.5 christos || majorid != LBR_MAJORID 553 1.1.1.5 christos || lhd.nindex != 1) 554 1.1.1.5 christos { 555 1.1.1.5 christos bfd_set_error (bfd_error_wrong_format); 556 1.1.1.5 christos return NULL; 557 1.1.1.5 christos } 558 1.1 christos break; 559 1.1 christos default: 560 1.1 christos abort (); 561 1.1 christos } 562 1.1 christos 563 1.1 christos /* Allocate and initialize private data. */ 564 1.1 christos tdata_hold = bfd_libdata (abfd); 565 1.1 christos tdata = (struct lib_tdata *) bfd_zalloc (abfd, sizeof (struct lib_tdata)); 566 1.1 christos if (tdata == NULL) 567 1.1 christos return NULL; 568 1.1 christos abfd->tdata.any = (void *)tdata; 569 1.1 christos tdata->ver = majorid; 570 1.1 christos tdata->mhd_size = MHD__C_USRDAT + lhd.mhdusz; 571 1.1 christos tdata->type = lhd.type; 572 1.1 christos tdata->kind = kind; 573 1.1 christos tdata->credat_lo = bfd_getl32 (lhd.credat + 0); 574 1.1 christos tdata->credat_hi = bfd_getl32 (lhd.credat + 4); 575 1.1 christos 576 1.1 christos /* Read indexes. */ 577 1.1 christos tdata->nbr_modules = bfd_getl32 (lhd.modcnt); 578 1.1 christos tdata->artdata.symdef_count = bfd_getl32 (lhd.idxcnt) - tdata->nbr_modules; 579 1.1 christos nbr_ent = tdata->nbr_modules; 580 1.1 christos tdata->modules = vms_lib_read_index (abfd, 0, &nbr_ent); 581 1.1 christos if (tdata->modules == NULL || nbr_ent != tdata->nbr_modules) 582 1.1 christos goto err; 583 1.1 christos if (lhd.nindex == 2) 584 1.1 christos { 585 1.1 christos nbr_ent = tdata->artdata.symdef_count; 586 1.1 christos tdata->artdata.symdefs = vms_lib_read_index (abfd, 1, &nbr_ent); 587 1.1 christos if (tdata->artdata.symdefs == NULL) 588 1.1.1.5 christos goto err; 589 1.1 christos /* Only IA64 archives may have more entries in the index that what 590 1.1.1.5 christos was declared. */ 591 1.1 christos if (nbr_ent != tdata->artdata.symdef_count 592 1.1.1.5 christos && kind != vms_lib_ia64) 593 1.1.1.5 christos goto err; 594 1.1 christos tdata->artdata.symdef_count = nbr_ent; 595 1.1 christos } 596 1.1 christos tdata->cache = bfd_zalloc (abfd, sizeof (bfd *) * tdata->nbr_modules); 597 1.1 christos if (tdata->cache == NULL) 598 1.1 christos goto err; 599 1.1 christos 600 1.1 christos /* Read DCX submaps. */ 601 1.1 christos dcxvbn = bfd_getl32 (lhd.dcxmapvbn); 602 1.1 christos if (dcxvbn != 0) 603 1.1 christos { 604 1.1 christos unsigned char buf_reclen[4]; 605 1.1 christos unsigned int reclen; 606 1.1 christos unsigned char *buf; 607 1.1 christos struct vms_dcxmap *map; 608 1.1 christos unsigned int sbm_off; 609 1.1 christos unsigned int i; 610 1.1 christos 611 1.1 christos if (bfd_seek (abfd, (dcxvbn - 1) * VMS_BLOCK_SIZE, SEEK_SET) != 0 612 1.1.1.9 christos || bfd_read (buf_reclen, sizeof (buf_reclen), abfd) 613 1.1.1.5 christos != sizeof (buf_reclen)) 614 1.1.1.5 christos goto err; 615 1.1 christos reclen = bfd_getl32 (buf_reclen); 616 1.1.1.8 christos if (reclen < sizeof (struct vms_dcxmap)) 617 1.1.1.8 christos goto err; 618 1.1.1.8 christos buf = _bfd_malloc_and_read (abfd, reclen, reclen); 619 1.1 christos if (buf == NULL) 620 1.1.1.5 christos goto err; 621 1.1 christos map = (struct vms_dcxmap *)buf; 622 1.1 christos tdata->nbr_dcxsbm = bfd_getl16 (map->nsubs); 623 1.1 christos sbm_off = bfd_getl16 (map->sub0); 624 1.1 christos tdata->dcxsbm = (struct dcxsbm_desc *)bfd_alloc 625 1.1.1.5 christos (abfd, tdata->nbr_dcxsbm * sizeof (struct dcxsbm_desc)); 626 1.1 christos for (i = 0; i < tdata->nbr_dcxsbm; i++) 627 1.1.1.5 christos { 628 1.1.1.8 christos struct vms_dcxsbm *sbm; 629 1.1.1.5 christos struct dcxsbm_desc *sbmdesc = &tdata->dcxsbm[i]; 630 1.1.1.5 christos unsigned int sbm_len; 631 1.1.1.5 christos unsigned int sbm_sz; 632 1.1.1.5 christos unsigned int off; 633 1.1.1.5 christos unsigned char *buf1; 634 1.1.1.5 christos unsigned int l, j; 635 1.1.1.5 christos 636 1.1.1.8 christos if (sbm_off > reclen 637 1.1.1.8 christos || reclen - sbm_off < sizeof (struct vms_dcxsbm)) 638 1.1.1.8 christos { 639 1.1.1.8 christos err_free_buf: 640 1.1.1.8 christos free (buf); 641 1.1.1.8 christos goto err; 642 1.1.1.8 christos } 643 1.1.1.8 christos sbm = (struct vms_dcxsbm *) (buf + sbm_off); 644 1.1.1.5 christos sbm_sz = bfd_getl16 (sbm->size); 645 1.1.1.5 christos sbm_off += sbm_sz; 646 1.1.1.8 christos if (sbm_off > reclen) 647 1.1.1.8 christos goto err_free_buf; 648 1.1.1.5 christos 649 1.1.1.5 christos sbmdesc->min_char = sbm->min_char; 650 1.1.1.5 christos BFD_ASSERT (sbmdesc->min_char == 0); 651 1.1.1.5 christos sbmdesc->max_char = sbm->max_char; 652 1.1.1.5 christos sbm_len = sbmdesc->max_char - sbmdesc->min_char + 1; 653 1.1.1.5 christos l = (2 * sbm_len + 7) / 8; 654 1.1.1.8 christos if (sbm_sz < sizeof (struct vms_dcxsbm) + l + sbm_len 655 1.1.1.8 christos || (tdata->nbr_dcxsbm > 1 656 1.1.1.8 christos && sbm_sz < sizeof (struct vms_dcxsbm) + l + 3 * sbm_len)) 657 1.1.1.8 christos goto err_free_buf; 658 1.1.1.5 christos sbmdesc->flags = (unsigned char *)bfd_alloc (abfd, l); 659 1.1.1.8 christos off = bfd_getl16 (sbm->flags); 660 1.1.1.8 christos if (off > sbm_sz 661 1.1.1.8 christos || sbm_sz - off < l) 662 1.1.1.8 christos goto err_free_buf; 663 1.1.1.8 christos memcpy (sbmdesc->flags, (bfd_byte *) sbm + off, l); 664 1.1.1.5 christos sbmdesc->nodes = (unsigned char *)bfd_alloc (abfd, 2 * sbm_len); 665 1.1.1.8 christos off = bfd_getl16 (sbm->nodes); 666 1.1.1.8 christos if (off > sbm_sz 667 1.1.1.8 christos || sbm_sz - off < 2 * sbm_len) 668 1.1.1.8 christos goto err_free_buf; 669 1.1.1.8 christos memcpy (sbmdesc->nodes, (bfd_byte *) sbm + off, 2 * sbm_len); 670 1.1.1.5 christos off = bfd_getl16 (sbm->next); 671 1.1.1.5 christos if (off != 0) 672 1.1.1.5 christos { 673 1.1.1.8 christos if (off > sbm_sz 674 1.1.1.8 christos || sbm_sz - off < 2 * sbm_len) 675 1.1.1.8 christos goto err_free_buf; 676 1.1.1.5 christos /* Read the 'next' array. */ 677 1.1.1.8 christos sbmdesc->next = (unsigned short *) bfd_alloc (abfd, 2 * sbm_len); 678 1.1.1.8 christos buf1 = (bfd_byte *) sbm + off; 679 1.1.1.5 christos for (j = 0; j < sbm_len; j++) 680 1.1.1.5 christos sbmdesc->next[j] = bfd_getl16 (buf1 + j * 2); 681 1.1.1.5 christos } 682 1.1.1.5 christos else 683 1.1.1.5 christos { 684 1.1.1.5 christos /* There is no next array if there is only one submap. */ 685 1.1.1.5 christos BFD_ASSERT (tdata->nbr_dcxsbm == 1); 686 1.1.1.5 christos sbmdesc->next = NULL; 687 1.1.1.5 christos } 688 1.1.1.5 christos } 689 1.1 christos free (buf); 690 1.1 christos } 691 1.1 christos else 692 1.1 christos { 693 1.1 christos tdata->nbr_dcxsbm = 0; 694 1.1 christos } 695 1.1 christos 696 1.1 christos /* The map is always present. Also mark shared image library. */ 697 1.1.1.8 christos abfd->has_armap = true; 698 1.1 christos if (tdata->type == LBR__C_TYP_ESHSTB || tdata->type == LBR__C_TYP_ISHSTB) 699 1.1.1.8 christos abfd->is_thin_archive = true; 700 1.1 christos 701 1.1.1.8 christos return _bfd_no_cleanup; 702 1.1 christos 703 1.1 christos err: 704 1.1 christos bfd_release (abfd, tdata); 705 1.1.1.3 christos abfd->tdata.any = (void *)tdata_hold; 706 1.1 christos return NULL; 707 1.1 christos } 708 1.1 christos 709 1.1 christos /* Standard function for alpha libraries. */ 710 1.1 christos 711 1.1.1.8 christos bfd_cleanup 712 1.1 christos _bfd_vms_lib_alpha_archive_p (bfd *abfd) 713 1.1 christos { 714 1.1 christos return _bfd_vms_lib_archive_p (abfd, vms_lib_alpha); 715 1.1 christos } 716 1.1 christos 717 1.1 christos /* Standard function for ia64 libraries. */ 718 1.1 christos 719 1.1.1.8 christos bfd_cleanup 720 1.1 christos _bfd_vms_lib_ia64_archive_p (bfd *abfd) 721 1.1 christos { 722 1.1 christos return _bfd_vms_lib_archive_p (abfd, vms_lib_ia64); 723 1.1 christos } 724 1.1 christos 725 1.1 christos /* Standard function for text libraries. */ 726 1.1 christos 727 1.1.1.8 christos static bfd_cleanup 728 1.1 christos _bfd_vms_lib_txt_archive_p (bfd *abfd) 729 1.1 christos { 730 1.1 christos return _bfd_vms_lib_archive_p (abfd, vms_lib_txt); 731 1.1 christos } 732 1.1 christos 733 1.1 christos /* Standard bfd function. */ 734 1.1 christos 735 1.1.1.8 christos static bool 736 1.1 christos _bfd_vms_lib_mkarchive (bfd *abfd, enum vms_lib_kind kind) 737 1.1 christos { 738 1.1 christos struct lib_tdata *tdata; 739 1.1 christos 740 1.1 christos tdata = (struct lib_tdata *) bfd_zalloc (abfd, sizeof (struct lib_tdata)); 741 1.1 christos if (tdata == NULL) 742 1.1.1.8 christos return false; 743 1.1 christos 744 1.1 christos abfd->tdata.any = (void *)tdata; 745 1.1 christos vms_get_time (&tdata->credat_hi, &tdata->credat_lo); 746 1.1 christos 747 1.1 christos tdata->kind = kind; 748 1.1 christos switch (kind) 749 1.1 christos { 750 1.1 christos case vms_lib_alpha: 751 1.1 christos tdata->ver = LBR_MAJORID; 752 1.1 christos tdata->mhd_size = offsetof (struct vms_mhd, pad1); 753 1.1 christos tdata->type = LBR__C_TYP_EOBJ; 754 1.1 christos break; 755 1.1 christos case vms_lib_ia64: 756 1.1 christos tdata->ver = LBR_ELFMAJORID; 757 1.1 christos tdata->mhd_size = sizeof (struct vms_mhd); 758 1.1 christos tdata->type = LBR__C_TYP_IOBJ; 759 1.1 christos break; 760 1.1 christos default: 761 1.1 christos abort (); 762 1.1 christos } 763 1.1 christos 764 1.1 christos tdata->nbr_modules = 0; 765 1.1 christos tdata->artdata.symdef_count = 0; 766 1.1 christos tdata->modules = NULL; 767 1.1 christos tdata->artdata.symdefs = NULL; 768 1.1 christos tdata->cache = NULL; 769 1.1 christos 770 1.1.1.8 christos return true; 771 1.1 christos } 772 1.1 christos 773 1.1.1.8 christos bool 774 1.1 christos _bfd_vms_lib_alpha_mkarchive (bfd *abfd) 775 1.1 christos { 776 1.1 christos return _bfd_vms_lib_mkarchive (abfd, vms_lib_alpha); 777 1.1 christos } 778 1.1 christos 779 1.1.1.8 christos bool 780 1.1 christos _bfd_vms_lib_ia64_mkarchive (bfd *abfd) 781 1.1 christos { 782 1.1 christos return _bfd_vms_lib_mkarchive (abfd, vms_lib_ia64); 783 1.1 christos } 784 1.1 christos 785 1.1 christos /* Find NAME in the symbol index. Return the index. */ 786 1.1 christos 787 1.1 christos symindex 788 1.1 christos _bfd_vms_lib_find_symbol (bfd *abfd, const char *name) 789 1.1 christos { 790 1.1 christos struct lib_tdata *tdata = bfd_libdata (abfd); 791 1.1 christos carsym *syms = tdata->artdata.symdefs; 792 1.1 christos int lo, hi; 793 1.1 christos 794 1.1 christos /* Open-coded binary search for speed. */ 795 1.1 christos lo = 0; 796 1.1 christos hi = tdata->artdata.symdef_count - 1; 797 1.1 christos 798 1.1 christos while (lo <= hi) 799 1.1 christos { 800 1.1 christos int mid = lo + (hi - lo) / 2; 801 1.1 christos int diff; 802 1.1 christos 803 1.1.1.11 christos diff = (signed char) (name[0] - syms[mid].name[0]); 804 1.1 christos if (diff == 0) 805 1.1.1.5 christos diff = strcmp (name, syms[mid].name); 806 1.1 christos if (diff == 0) 807 1.1.1.5 christos return mid; 808 1.1 christos else if (diff < 0) 809 1.1.1.5 christos hi = mid - 1; 810 1.1 christos else 811 1.1.1.5 christos lo = mid + 1; 812 1.1 christos } 813 1.1 christos return BFD_NO_MORE_SYMBOLS; 814 1.1 christos } 815 1.1 christos 816 1.1 christos /* IO vector for archive member. Need that because members are not linearly 817 1.1 christos stored in archives. */ 818 1.1 christos 819 1.1 christos struct vms_lib_iovec 820 1.1 christos { 821 1.1 christos /* Current offset. */ 822 1.1 christos ufile_ptr where; 823 1.1 christos 824 1.1 christos /* Length of the module, when known. */ 825 1.1 christos ufile_ptr file_len; 826 1.1 christos 827 1.1.1.9 christos /* Current position in the record from bfd_read point of view (ie, after 828 1.1 christos decompression). 0 means that no data byte have been read, -2 and -1 829 1.1 christos are reserved for the length word. */ 830 1.1 christos int rec_pos; 831 1.1 christos #define REC_POS_NL -4 832 1.1 christos #define REC_POS_PAD -3 833 1.1 christos #define REC_POS_LEN0 -2 834 1.1 christos #define REC_POS_LEN1 -1 835 1.1 christos 836 1.1 christos /* Record length. */ 837 1.1 christos unsigned short rec_len; 838 1.1 christos /* Number of bytes to read in the current record. */ 839 1.1 christos unsigned short rec_rem; 840 1.1 christos /* Offset of the next block. */ 841 1.1 christos file_ptr next_block; 842 1.1 christos /* Current *data* offset in the data block. */ 843 1.1 christos unsigned short blk_off; 844 1.1 christos 845 1.1 christos /* Offset of the first block. Extracted from the index. */ 846 1.1 christos file_ptr first_block; 847 1.1 christos 848 1.1 christos /* Initial next_block. Extracted when the MHD is read. */ 849 1.1 christos file_ptr init_next_block; 850 1.1 christos /* Initial blk_off, once the MHD is read. */ 851 1.1 christos unsigned short init_blk_off; 852 1.1 christos 853 1.1 christos /* Used to store any 3 byte record, which could be the EOF pattern. */ 854 1.1 christos unsigned char pattern[4]; 855 1.1 christos 856 1.1 christos /* DCX. */ 857 1.1 christos struct dcxsbm_desc *dcxsbms; 858 1.1 christos /* Current submap. */ 859 1.1 christos struct dcxsbm_desc *dcx_sbm; 860 1.1 christos /* Current offset in the submap. */ 861 1.1 christos unsigned int dcx_offset; 862 1.1 christos int dcx_pos; 863 1.1 christos 864 1.1 christos /* Compressed buffer. */ 865 1.1 christos unsigned char *dcx_buf; 866 1.1 christos /* Size of the buffer. Used to resize. */ 867 1.1 christos unsigned int dcx_max; 868 1.1 christos /* Number of valid bytes in the buffer. */ 869 1.1 christos unsigned int dcx_rlen; 870 1.1 christos }; 871 1.1 christos 872 1.1 christos /* Return the current position. */ 873 1.1 christos 874 1.1 christos static file_ptr 875 1.1 christos vms_lib_btell (struct bfd *abfd) 876 1.1 christos { 877 1.1 christos struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream; 878 1.1 christos return vec->where; 879 1.1 christos } 880 1.1 christos 881 1.1 christos /* Read the header of the next data block if all bytes of the current block 882 1.1 christos have been read. */ 883 1.1 christos 884 1.1.1.8 christos static bool 885 1.1 christos vms_lib_read_block (struct bfd *abfd) 886 1.1 christos { 887 1.1 christos struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream; 888 1.1 christos 889 1.1 christos if (vec->blk_off == DATA__LENGTH) 890 1.1 christos { 891 1.1 christos unsigned char hdr[DATA__DATA]; 892 1.1 christos 893 1.1 christos /* Read next block. */ 894 1.1 christos if (bfd_seek (abfd->my_archive, vec->next_block, SEEK_SET) != 0) 895 1.1.1.8 christos return false; 896 1.1.1.9 christos if (bfd_read (hdr, sizeof (hdr), abfd->my_archive) != sizeof (hdr)) 897 1.1.1.8 christos return false; 898 1.1 christos vec->next_block = (bfd_getl32 (hdr + 2) - 1) * VMS_BLOCK_SIZE; 899 1.1 christos vec->blk_off = sizeof (hdr); 900 1.1 christos } 901 1.1.1.8 christos return true; 902 1.1 christos } 903 1.1 christos 904 1.1 christos /* Read NBYTES from ABFD into BUF if not NULL. If BUF is NULL, bytes are 905 1.1 christos not stored. Read linearly from the library, but handle blocks. This 906 1.1 christos function does not handle records nor EOF. */ 907 1.1 christos 908 1.1 christos static file_ptr 909 1.1 christos vms_lib_bread_raw (struct bfd *abfd, unsigned char *buf, file_ptr nbytes) 910 1.1 christos { 911 1.1 christos struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream; 912 1.1 christos file_ptr res; 913 1.1 christos 914 1.1 christos res = 0; 915 1.1 christos while (nbytes > 0) 916 1.1 christos { 917 1.1 christos unsigned int l; 918 1.1 christos 919 1.1 christos /* Be sure the current data block is read. */ 920 1.1 christos if (!vms_lib_read_block (abfd)) 921 1.1.1.5 christos return -1; 922 1.1 christos 923 1.1 christos /* Do not read past the data block, do not read more than requested. */ 924 1.1 christos l = DATA__LENGTH - vec->blk_off; 925 1.1 christos if (l > nbytes) 926 1.1.1.5 christos l = nbytes; 927 1.1 christos if (l == 0) 928 1.1.1.5 christos return 0; 929 1.1 christos if (buf != NULL) 930 1.1.1.5 christos { 931 1.1.1.5 christos /* Really read into BUF. */ 932 1.1.1.9 christos if (bfd_read (buf, l, abfd->my_archive) != l) 933 1.1.1.5 christos return -1; 934 1.1.1.5 christos } 935 1.1 christos else 936 1.1.1.5 christos { 937 1.1.1.5 christos /* Make as if we are reading. */ 938 1.1.1.5 christos if (bfd_seek (abfd->my_archive, l, SEEK_CUR) != 0) 939 1.1.1.5 christos return -1; 940 1.1.1.5 christos } 941 1.1 christos 942 1.1 christos if (buf != NULL) 943 1.1.1.5 christos buf += l; 944 1.1 christos vec->blk_off += l; 945 1.1 christos nbytes -= l; 946 1.1 christos res += l; 947 1.1 christos } 948 1.1 christos return res; 949 1.1 christos } 950 1.1 christos 951 1.1 christos /* Decompress NBYTES from VEC. Store the bytes into BUF if not NULL. */ 952 1.1 christos 953 1.1 christos static file_ptr 954 1.1 christos vms_lib_dcx (struct vms_lib_iovec *vec, unsigned char *buf, file_ptr nbytes) 955 1.1 christos { 956 1.1 christos struct dcxsbm_desc *sbm; 957 1.1 christos unsigned int i; 958 1.1 christos unsigned int offset; 959 1.1 christos unsigned int j; 960 1.1 christos file_ptr res = 0; 961 1.1 christos 962 1.1 christos /* The loop below expect to deliver at least one byte. */ 963 1.1 christos if (nbytes == 0) 964 1.1 christos return 0; 965 1.1 christos 966 1.1 christos /* Get the current state. */ 967 1.1 christos sbm = vec->dcx_sbm; 968 1.1 christos offset = vec->dcx_offset; 969 1.1 christos j = vec->dcx_pos & 7; 970 1.1 christos 971 1.1 christos for (i = vec->dcx_pos >> 3; i < vec->dcx_rlen; i++) 972 1.1 christos { 973 1.1 christos unsigned char b = vec->dcx_buf[i]; 974 1.1 christos 975 1.1 christos for (; j < 8; j++) 976 1.1.1.5 christos { 977 1.1.1.5 christos if (b & (1 << j)) 978 1.1.1.5 christos offset++; 979 1.1.1.5 christos if (!(sbm->flags[offset >> 3] & (1 << (offset & 7)))) 980 1.1.1.5 christos { 981 1.1.1.5 christos unsigned int n_offset = sbm->nodes[offset]; 982 1.1.1.5 christos if (n_offset == 0) 983 1.1.1.5 christos { 984 1.1.1.5 christos /* End of buffer. Stay where we are. */ 985 1.1.1.5 christos vec->dcx_pos = (i << 3) + j; 986 1.1.1.5 christos if (b & (1 << j)) 987 1.1.1.5 christos offset--; 988 1.1.1.5 christos vec->dcx_offset = offset; 989 1.1.1.5 christos vec->dcx_sbm = sbm; 990 1.1.1.5 christos return res; 991 1.1.1.5 christos } 992 1.1.1.5 christos offset = 2 * n_offset; 993 1.1.1.5 christos } 994 1.1.1.5 christos else 995 1.1.1.5 christos { 996 1.1.1.5 christos unsigned char v = sbm->nodes[offset]; 997 1.1.1.5 christos 998 1.1.1.5 christos if (sbm->next != NULL) 999 1.1.1.5 christos sbm = vec->dcxsbms + sbm->next[v]; 1000 1.1.1.5 christos offset = 0; 1001 1.1.1.5 christos res++; 1002 1.1.1.5 christos 1003 1.1.1.5 christos if (buf) 1004 1.1.1.5 christos { 1005 1.1.1.5 christos *buf++ = v; 1006 1.1.1.5 christos nbytes--; 1007 1.1.1.5 christos 1008 1.1.1.5 christos if (nbytes == 0) 1009 1.1.1.5 christos { 1010 1.1.1.5 christos vec->dcx_pos = (i << 3) + j + 1; 1011 1.1.1.5 christos vec->dcx_offset = offset; 1012 1.1.1.5 christos vec->dcx_sbm = sbm; 1013 1.1.1.5 christos 1014 1.1.1.5 christos return res; 1015 1.1.1.5 christos } 1016 1.1.1.5 christos } 1017 1.1.1.5 christos } 1018 1.1.1.5 christos } 1019 1.1 christos j = 0; 1020 1.1 christos } 1021 1.1 christos return -1; 1022 1.1 christos } 1023 1.1 christos 1024 1.1 christos /* Standard IOVEC function. */ 1025 1.1 christos 1026 1.1 christos static file_ptr 1027 1.1 christos vms_lib_bread (struct bfd *abfd, void *vbuf, file_ptr nbytes) 1028 1.1 christos { 1029 1.1 christos struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream; 1030 1.1 christos file_ptr res; 1031 1.1 christos file_ptr chunk; 1032 1.1 christos unsigned char *buf = (unsigned char *)vbuf; 1033 1.1 christos 1034 1.1 christos /* Do not read past the end. */ 1035 1.1 christos if (vec->where >= vec->file_len) 1036 1.1 christos return 0; 1037 1.1 christos 1038 1.1 christos res = 0; 1039 1.1 christos while (nbytes > 0) 1040 1.1 christos { 1041 1.1 christos if (vec->rec_rem == 0) 1042 1.1.1.5 christos { 1043 1.1.1.5 christos unsigned char blen[2]; 1044 1.1.1.5 christos 1045 1.1.1.5 christos /* Read record length. */ 1046 1.1.1.5 christos if (vms_lib_bread_raw (abfd, blen, sizeof (blen)) != sizeof (blen)) 1047 1.1.1.5 christos return -1; 1048 1.1.1.5 christos vec->rec_len = bfd_getl16 (blen); 1049 1.1.1.5 christos if (bfd_libdata (abfd->my_archive)->kind == vms_lib_txt) 1050 1.1.1.5 christos { 1051 1.1.1.5 christos /* Discard record size and align byte. */ 1052 1.1.1.5 christos vec->rec_pos = 0; 1053 1.1.1.5 christos vec->rec_rem = vec->rec_len; 1054 1.1.1.5 christos } 1055 1.1.1.5 christos else 1056 1.1.1.5 christos { 1057 1.1.1.5 christos /* Prepend record size. */ 1058 1.1.1.5 christos vec->rec_pos = REC_POS_LEN0; 1059 1.1.1.5 christos vec->rec_rem = (vec->rec_len + 1) & ~1; /* With align byte. */ 1060 1.1.1.5 christos } 1061 1.1.1.5 christos if (vec->rec_len == 3) 1062 1.1.1.5 christos { 1063 1.1.1.5 christos /* Possibly end of file. Check the pattern. */ 1064 1.1.1.5 christos if (vms_lib_bread_raw (abfd, vec->pattern, 4) != 4) 1065 1.1.1.5 christos return -1; 1066 1.1.1.5 christos if (!memcmp (vec->pattern, eotdesc + 2, 3)) 1067 1.1.1.5 christos { 1068 1.1.1.5 christos /* This is really an EOF. */ 1069 1.1.1.5 christos vec->where += res; 1070 1.1.1.5 christos vec->file_len = vec->where; 1071 1.1.1.5 christos return res; 1072 1.1.1.5 christos } 1073 1.1.1.5 christos } 1074 1.1 christos 1075 1.1.1.5 christos if (vec->dcxsbms != NULL) 1076 1.1.1.5 christos { 1077 1.1.1.5 christos /* This is a compressed member. */ 1078 1.1.1.5 christos unsigned int len; 1079 1.1.1.5 christos file_ptr elen; 1080 1.1.1.5 christos 1081 1.1.1.5 christos /* Be sure there is enough room for the expansion. */ 1082 1.1.1.5 christos len = (vec->rec_len + 1) & ~1; 1083 1.1.1.5 christos if (len > vec->dcx_max) 1084 1.1.1.5 christos { 1085 1.1.1.5 christos while (len > vec->dcx_max) 1086 1.1.1.5 christos vec->dcx_max *= 2; 1087 1.1.1.5 christos vec->dcx_buf = bfd_alloc (abfd, vec->dcx_max); 1088 1.1.1.5 christos if (vec->dcx_buf == NULL) 1089 1.1.1.5 christos return -1; 1090 1.1.1.5 christos } 1091 1.1.1.5 christos 1092 1.1.1.5 christos /* Read the compressed record. */ 1093 1.1.1.5 christos vec->dcx_rlen = len; 1094 1.1.1.5 christos if (vec->rec_len == 3) 1095 1.1.1.5 christos { 1096 1.1.1.5 christos /* Already read. */ 1097 1.1.1.5 christos memcpy (vec->dcx_buf, vec->pattern, 3); 1098 1.1.1.5 christos } 1099 1.1.1.5 christos else 1100 1.1.1.5 christos { 1101 1.1.1.5 christos elen = vms_lib_bread_raw (abfd, vec->dcx_buf, len); 1102 1.1.1.5 christos if (elen != len) 1103 1.1.1.5 christos return -1; 1104 1.1.1.5 christos } 1105 1.1.1.5 christos 1106 1.1.1.5 christos /* Dummy expansion to get the expanded length. */ 1107 1.1.1.5 christos vec->dcx_offset = 0; 1108 1.1.1.5 christos vec->dcx_sbm = vec->dcxsbms; 1109 1.1.1.5 christos vec->dcx_pos = 0; 1110 1.1.1.5 christos elen = vms_lib_dcx (vec, NULL, 0x10000); 1111 1.1.1.5 christos if (elen < 0) 1112 1.1.1.5 christos return -1; 1113 1.1.1.5 christos vec->rec_len = elen; 1114 1.1.1.5 christos vec->rec_rem = elen; 1115 1.1.1.5 christos 1116 1.1.1.5 christos /* Reset the state. */ 1117 1.1.1.5 christos vec->dcx_offset = 0; 1118 1.1.1.5 christos vec->dcx_sbm = vec->dcxsbms; 1119 1.1.1.5 christos vec->dcx_pos = 0; 1120 1.1.1.5 christos } 1121 1.1.1.5 christos } 1122 1.1 christos if (vec->rec_pos < 0) 1123 1.1.1.5 christos { 1124 1.1.1.5 christos unsigned char c; 1125 1.1.1.5 christos switch (vec->rec_pos) 1126 1.1.1.5 christos { 1127 1.1.1.5 christos case REC_POS_LEN0: 1128 1.1.1.5 christos c = vec->rec_len & 0xff; 1129 1.1.1.5 christos vec->rec_pos = REC_POS_LEN1; 1130 1.1.1.5 christos break; 1131 1.1.1.5 christos case REC_POS_LEN1: 1132 1.1.1.5 christos c = (vec->rec_len >> 8) & 0xff; 1133 1.1.1.5 christos vec->rec_pos = 0; 1134 1.1.1.5 christos break; 1135 1.1.1.5 christos case REC_POS_PAD: 1136 1.1.1.5 christos c = 0; 1137 1.1.1.5 christos vec->rec_rem = 0; 1138 1.1.1.5 christos break; 1139 1.1.1.5 christos case REC_POS_NL: 1140 1.1.1.5 christos c = '\n'; 1141 1.1.1.5 christos vec->rec_rem = 0; 1142 1.1.1.5 christos break; 1143 1.1.1.5 christos default: 1144 1.1.1.5 christos abort (); 1145 1.1.1.5 christos } 1146 1.1.1.5 christos if (buf != NULL) 1147 1.1.1.5 christos { 1148 1.1.1.5 christos *buf = c; 1149 1.1.1.5 christos buf++; 1150 1.1.1.5 christos } 1151 1.1.1.5 christos nbytes--; 1152 1.1.1.5 christos res++; 1153 1.1.1.5 christos continue; 1154 1.1.1.5 christos } 1155 1.1 christos 1156 1.1 christos if (nbytes > vec->rec_rem) 1157 1.1.1.5 christos chunk = vec->rec_rem; 1158 1.1 christos else 1159 1.1.1.5 christos chunk = nbytes; 1160 1.1 christos 1161 1.1 christos if (vec->dcxsbms != NULL) 1162 1.1.1.5 christos { 1163 1.1.1.5 christos /* Optimize the stat() case: no need to decompress again as we 1164 1.1.1.5 christos know the length. */ 1165 1.1.1.5 christos if (!(buf == NULL && chunk == vec->rec_rem)) 1166 1.1.1.5 christos chunk = vms_lib_dcx (vec, buf, chunk); 1167 1.1.1.5 christos } 1168 1.1 christos else 1169 1.1.1.5 christos { 1170 1.1.1.5 christos if (vec->rec_len == 3) 1171 1.1.1.5 christos { 1172 1.1.1.5 christos if (buf != NULL) 1173 1.1.1.5 christos memcpy (buf, vec->pattern + vec->rec_pos, chunk); 1174 1.1.1.5 christos } 1175 1.1.1.5 christos else 1176 1.1.1.5 christos chunk = vms_lib_bread_raw (abfd, buf, chunk); 1177 1.1.1.5 christos } 1178 1.1 christos if (chunk < 0) 1179 1.1.1.5 christos return -1; 1180 1.1 christos res += chunk; 1181 1.1 christos if (buf != NULL) 1182 1.1.1.5 christos buf += chunk; 1183 1.1 christos nbytes -= chunk; 1184 1.1 christos vec->rec_pos += chunk; 1185 1.1 christos vec->rec_rem -= chunk; 1186 1.1 christos 1187 1.1 christos if (vec->rec_rem == 0) 1188 1.1.1.5 christos { 1189 1.1.1.5 christos /* End of record reached. */ 1190 1.1.1.5 christos if (bfd_libdata (abfd->my_archive)->kind == vms_lib_txt) 1191 1.1.1.5 christos { 1192 1.1.1.5 christos if ((vec->rec_len & 1) == 1 1193 1.1.1.5 christos && vec->rec_len != 3 1194 1.1.1.5 christos && vec->dcxsbms == NULL) 1195 1.1.1.5 christos { 1196 1.1.1.5 christos /* Eat the pad byte. */ 1197 1.1.1.5 christos unsigned char pad; 1198 1.1.1.5 christos if (vms_lib_bread_raw (abfd, &pad, 1) != 1) 1199 1.1.1.5 christos return -1; 1200 1.1.1.5 christos } 1201 1.1.1.5 christos vec->rec_pos = REC_POS_NL; 1202 1.1.1.5 christos vec->rec_rem = 1; 1203 1.1.1.5 christos } 1204 1.1.1.5 christos else 1205 1.1.1.5 christos { 1206 1.1.1.5 christos if ((vec->rec_len & 1) == 1 && vec->dcxsbms != NULL) 1207 1.1.1.5 christos { 1208 1.1.1.5 christos vec->rec_pos = REC_POS_PAD; 1209 1.1.1.5 christos vec->rec_rem = 1; 1210 1.1.1.5 christos } 1211 1.1.1.5 christos } 1212 1.1.1.5 christos } 1213 1.1 christos } 1214 1.1 christos vec->where += res; 1215 1.1 christos return res; 1216 1.1 christos } 1217 1.1 christos 1218 1.1 christos /* Standard function, but we currently only handle the rewind case. */ 1219 1.1 christos 1220 1.1 christos static int 1221 1.1 christos vms_lib_bseek (struct bfd *abfd, file_ptr offset, int whence) 1222 1.1 christos { 1223 1.1 christos struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream; 1224 1.1 christos 1225 1.1 christos if (whence == SEEK_SET && offset == 0) 1226 1.1 christos { 1227 1.1 christos vec->where = 0; 1228 1.1 christos vec->rec_rem = 0; 1229 1.1 christos vec->dcx_pos = -1; 1230 1.1 christos vec->blk_off = vec->init_blk_off; 1231 1.1 christos vec->next_block = vec->init_next_block; 1232 1.1 christos 1233 1.1 christos if (bfd_seek (abfd->my_archive, vec->first_block, SEEK_SET) != 0) 1234 1.1.1.5 christos return -1; 1235 1.1 christos } 1236 1.1 christos else 1237 1.1 christos abort (); 1238 1.1 christos return 0; 1239 1.1 christos } 1240 1.1 christos 1241 1.1 christos static file_ptr 1242 1.1 christos vms_lib_bwrite (struct bfd *abfd ATTRIBUTE_UNUSED, 1243 1.1 christos const void *where ATTRIBUTE_UNUSED, 1244 1.1 christos file_ptr nbytes ATTRIBUTE_UNUSED) 1245 1.1 christos { 1246 1.1 christos return -1; 1247 1.1 christos } 1248 1.1 christos 1249 1.1 christos static int 1250 1.1 christos vms_lib_bclose (struct bfd *abfd) 1251 1.1 christos { 1252 1.1 christos abfd->iostream = NULL; 1253 1.1 christos return 0; 1254 1.1 christos } 1255 1.1 christos 1256 1.1 christos static int 1257 1.1 christos vms_lib_bflush (struct bfd *abfd ATTRIBUTE_UNUSED) 1258 1.1 christos { 1259 1.1 christos return 0; 1260 1.1 christos } 1261 1.1 christos 1262 1.1 christos static int 1263 1.1 christos vms_lib_bstat (struct bfd *abfd ATTRIBUTE_UNUSED, 1264 1.1.1.5 christos struct stat *sb ATTRIBUTE_UNUSED) 1265 1.1 christos { 1266 1.1 christos /* Not supported. */ 1267 1.1.1.11 christos return -1; 1268 1.1 christos } 1269 1.1 christos 1270 1.1 christos static void * 1271 1.1 christos vms_lib_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED, 1272 1.1.1.5 christos void *addr ATTRIBUTE_UNUSED, 1273 1.1.1.10 christos size_t len ATTRIBUTE_UNUSED, 1274 1.1.1.5 christos int prot ATTRIBUTE_UNUSED, 1275 1.1.1.5 christos int flags ATTRIBUTE_UNUSED, 1276 1.1.1.5 christos file_ptr offset ATTRIBUTE_UNUSED, 1277 1.1.1.5 christos void **map_addr ATTRIBUTE_UNUSED, 1278 1.1.1.10 christos size_t *map_len ATTRIBUTE_UNUSED) 1279 1.1 christos { 1280 1.1.1.10 christos return MAP_FAILED; 1281 1.1 christos } 1282 1.1 christos 1283 1.1 christos static const struct bfd_iovec vms_lib_iovec = { 1284 1.1 christos &vms_lib_bread, &vms_lib_bwrite, &vms_lib_btell, &vms_lib_bseek, 1285 1.1 christos &vms_lib_bclose, &vms_lib_bflush, &vms_lib_bstat, &vms_lib_bmmap 1286 1.1 christos }; 1287 1.1 christos 1288 1.1 christos /* Open a library module. FILEPOS is the position of the module header. */ 1289 1.1 christos 1290 1.1.1.8 christos static bool 1291 1.1 christos vms_lib_bopen (bfd *el, file_ptr filepos) 1292 1.1 christos { 1293 1.1 christos struct vms_lib_iovec *vec; 1294 1.1 christos unsigned char buf[256]; 1295 1.1 christos struct vms_mhd *mhd; 1296 1.1 christos struct lib_tdata *tdata = bfd_libdata (el->my_archive); 1297 1.1 christos unsigned int len; 1298 1.1 christos 1299 1.1 christos /* Allocate and initialized the iovec. */ 1300 1.1 christos vec = bfd_zalloc (el, sizeof (*vec)); 1301 1.1 christos if (vec == NULL) 1302 1.1.1.8 christos return false; 1303 1.1 christos 1304 1.1 christos el->iostream = vec; 1305 1.1 christos el->iovec = &vms_lib_iovec; 1306 1.1 christos 1307 1.1.1.11 christos /* Force the next rewind to call vms_lib_bseek even though it will 1308 1.1.1.11 christos appear to bfd_seek that the file position is already at 0. */ 1309 1.1.1.11 christos el->last_io = bfd_io_force; 1310 1.1.1.11 christos 1311 1.1 christos /* File length is not known. */ 1312 1.1 christos vec->file_len = -1; 1313 1.1 christos 1314 1.1 christos /* Read the first data block. */ 1315 1.1 christos vec->next_block = filepos & ~(VMS_BLOCK_SIZE - 1); 1316 1.1 christos vec->blk_off = DATA__LENGTH; 1317 1.1 christos if (!vms_lib_read_block (el)) 1318 1.1.1.8 christos return false; 1319 1.1 christos 1320 1.1 christos /* Prepare to read the first record. */ 1321 1.1 christos vec->blk_off = filepos & (VMS_BLOCK_SIZE - 1); 1322 1.1 christos vec->rec_rem = 0; 1323 1.1 christos if (bfd_seek (el->my_archive, filepos, SEEK_SET) != 0) 1324 1.1.1.8 christos return false; 1325 1.1 christos 1326 1.1 christos /* Read Record length + MHD + align byte. */ 1327 1.1 christos len = tdata->mhd_size; 1328 1.1 christos if (vms_lib_bread_raw (el, buf, 2) != 2) 1329 1.1.1.8 christos return false; 1330 1.1 christos if (bfd_getl16 (buf) != len) 1331 1.1.1.8 christos return false; 1332 1.1 christos len = (len + 1) & ~1; 1333 1.1 christos BFD_ASSERT (len <= sizeof (buf)); 1334 1.1 christos if (vms_lib_bread_raw (el, buf, len) != len) 1335 1.1.1.8 christos return false; 1336 1.1 christos 1337 1.1 christos /* Get info from mhd. */ 1338 1.1 christos mhd = (struct vms_mhd *)buf; 1339 1.1 christos /* Check id. */ 1340 1.1 christos if (mhd->id != MHD__C_MHDID) 1341 1.1.1.8 christos return false; 1342 1.1 christos if (len >= MHD__C_MHDLEN + 1) 1343 1.1 christos el->selective_search = (mhd->objstat & MHD__M_SELSRC) ? 1 : 0; 1344 1.1 christos el->mtime = vms_rawtime_to_time_t (mhd->datim); 1345 1.1.1.8 christos el->mtime_set = true; 1346 1.1 christos 1347 1.1 christos /* Reinit the iovec so that seek() will point to the first record after 1348 1.1 christos the mhd. */ 1349 1.1 christos vec->where = 0; 1350 1.1 christos vec->init_blk_off = vec->blk_off; 1351 1.1 christos vec->init_next_block = vec->next_block; 1352 1.1 christos vec->first_block = bfd_tell (el->my_archive); 1353 1.1 christos vec->dcxsbms = bfd_libdata (el->my_archive)->dcxsbm; 1354 1.1 christos 1355 1.1 christos if (vec->dcxsbms != NULL) 1356 1.1 christos { 1357 1.1 christos /* Handle DCX. */ 1358 1.1 christos vec->dcx_max = 10 * 1024; 1359 1.1 christos vec->dcx_buf = bfd_alloc (el, vec->dcx_max); 1360 1.1 christos vec->dcx_pos = -1; 1361 1.1 christos if (vec->dcx_buf == NULL) 1362 1.1.1.5 christos return -1; 1363 1.1 christos } 1364 1.1.1.8 christos return true; 1365 1.1 christos } 1366 1.1 christos 1367 1.1 christos /* Get member MODIDX. Return NULL in case of error. */ 1368 1.1 christos 1369 1.1 christos static bfd * 1370 1.1 christos _bfd_vms_lib_get_module (bfd *abfd, unsigned int modidx) 1371 1.1 christos { 1372 1.1 christos struct lib_tdata *tdata = bfd_libdata (abfd); 1373 1.1 christos bfd *res; 1374 1.1 christos file_ptr file_off; 1375 1.1.1.7 christos const char *name; 1376 1.1.1.7 christos char *newname; 1377 1.1.1.7 christos size_t namelen; 1378 1.1 christos 1379 1.1 christos /* Sanity check. */ 1380 1.1 christos if (modidx >= tdata->nbr_modules) 1381 1.1 christos return NULL; 1382 1.1 christos 1383 1.1 christos /* Already loaded. */ 1384 1.1 christos if (tdata->cache[modidx]) 1385 1.1 christos return tdata->cache[modidx]; 1386 1.1 christos 1387 1.1 christos /* Build it. */ 1388 1.1 christos file_off = tdata->modules[modidx].file_offset; 1389 1.1 christos if (tdata->type != LBR__C_TYP_IOBJ) 1390 1.1 christos { 1391 1.1 christos res = _bfd_create_empty_archive_element_shell (abfd); 1392 1.1 christos if (res == NULL) 1393 1.1.1.5 christos return NULL; 1394 1.1 christos 1395 1.1 christos /* Special reader to deal with data blocks. */ 1396 1.1 christos if (!vms_lib_bopen (res, file_off)) 1397 1.1.1.5 christos return NULL; 1398 1.1 christos } 1399 1.1 christos else 1400 1.1 christos { 1401 1.1 christos char buf[256]; 1402 1.1 christos struct vms_mhd *mhd; 1403 1.1 christos struct areltdata *arelt; 1404 1.1 christos 1405 1.1 christos /* Sanity check. The MHD must be big enough to contain module size. */ 1406 1.1 christos if (tdata->mhd_size < offsetof (struct vms_mhd, modsize) + 4) 1407 1.1.1.5 christos return NULL; 1408 1.1 christos 1409 1.1 christos /* Read the MHD now. */ 1410 1.1 christos if (bfd_seek (abfd, file_off, SEEK_SET) != 0) 1411 1.1.1.5 christos return NULL; 1412 1.1.1.9 christos if (bfd_read (buf, tdata->mhd_size, abfd) != tdata->mhd_size) 1413 1.1.1.5 christos return NULL; 1414 1.1 christos 1415 1.1.1.7 christos mhd = (struct vms_mhd *) buf; 1416 1.1.1.7 christos if (mhd->id != MHD__C_MHDID) 1417 1.1.1.7 christos return NULL; 1418 1.1.1.7 christos 1419 1.1 christos res = _bfd_create_empty_archive_element_shell (abfd); 1420 1.1 christos if (res == NULL) 1421 1.1.1.5 christos return NULL; 1422 1.1.1.3 christos arelt = bfd_zmalloc (sizeof (*arelt)); 1423 1.1 christos if (arelt == NULL) 1424 1.1.1.7 christos { 1425 1.1.1.7 christos bfd_close (res); 1426 1.1.1.7 christos return NULL; 1427 1.1.1.7 christos } 1428 1.1 christos res->arelt_data = arelt; 1429 1.1 christos 1430 1.1 christos /* Get info from mhd. */ 1431 1.1 christos if (tdata->mhd_size >= offsetof (struct vms_mhd, objstat) + 1) 1432 1.1.1.5 christos res->selective_search = (mhd->objstat & MHD__M_SELSRC) ? 1 : 0; 1433 1.1 christos res->mtime = vms_rawtime_to_time_t (mhd->datim); 1434 1.1.1.8 christos res->mtime_set = true; 1435 1.1 christos 1436 1.1 christos arelt->parsed_size = bfd_getl32 (mhd->modsize); 1437 1.1 christos 1438 1.1 christos /* No need for a special reader as members are stored linearly. 1439 1.1.1.5 christos Just skip the MHD. */ 1440 1.1 christos res->origin = file_off + tdata->mhd_size; 1441 1.1 christos } 1442 1.1 christos 1443 1.1.1.2 christos /* Set filename. */ 1444 1.1.1.2 christos name = tdata->modules[modidx].name; 1445 1.1.1.7 christos namelen = strlen (name); 1446 1.1.1.7 christos newname = bfd_malloc (namelen + 4 + 1); 1447 1.1.1.7 christos if (newname == NULL) 1448 1.1.1.7 christos { 1449 1.1.1.7 christos bfd_close (res); 1450 1.1.1.7 christos return NULL; 1451 1.1.1.7 christos } 1452 1.1.1.7 christos strcpy (newname, name); 1453 1.1.1.2 christos switch (tdata->type) 1454 1.1.1.2 christos { 1455 1.1.1.2 christos case LBR__C_TYP_IOBJ: 1456 1.1.1.2 christos case LBR__C_TYP_EOBJ: 1457 1.1.1.2 christos /* For object archives, append .obj to mimic standard behaviour. */ 1458 1.1.1.7 christos strcpy (newname + namelen, ".obj"); 1459 1.1.1.2 christos break; 1460 1.1.1.2 christos default: 1461 1.1.1.2 christos break; 1462 1.1.1.2 christos } 1463 1.1.1.7 christos bfd_set_filename (res, newname); 1464 1.1.1.8 christos free (newname); 1465 1.1.1.8 christos if (bfd_get_filename (res) == NULL) 1466 1.1.1.8 christos { 1467 1.1.1.8 christos bfd_close (res); 1468 1.1.1.8 christos return NULL; 1469 1.1.1.8 christos } 1470 1.1 christos 1471 1.1 christos tdata->cache[modidx] = res; 1472 1.1 christos 1473 1.1 christos return res; 1474 1.1 christos } 1475 1.1 christos 1476 1.1 christos /* Standard function: get member at IDX. */ 1477 1.1 christos 1478 1.1 christos bfd * 1479 1.1 christos _bfd_vms_lib_get_elt_at_index (bfd *abfd, symindex symidx) 1480 1.1 christos { 1481 1.1 christos struct lib_tdata *tdata = bfd_libdata (abfd); 1482 1.1 christos file_ptr file_off; 1483 1.1 christos unsigned int modidx; 1484 1.1 christos 1485 1.1 christos /* Check symidx. */ 1486 1.1 christos if (symidx > tdata->artdata.symdef_count) 1487 1.1 christos return NULL; 1488 1.1 christos file_off = tdata->artdata.symdefs[symidx].file_offset; 1489 1.1 christos 1490 1.1 christos /* Linear-scan. */ 1491 1.1 christos for (modidx = 0; modidx < tdata->nbr_modules; modidx++) 1492 1.1 christos { 1493 1.1 christos if (tdata->modules[modidx].file_offset == file_off) 1494 1.1.1.5 christos break; 1495 1.1 christos } 1496 1.1 christos if (modidx >= tdata->nbr_modules) 1497 1.1 christos return NULL; 1498 1.1 christos 1499 1.1 christos return _bfd_vms_lib_get_module (abfd, modidx); 1500 1.1 christos } 1501 1.1 christos 1502 1.1 christos /* Elements of an imagelib are stubs. You can get the real image with this 1503 1.1 christos function. */ 1504 1.1 christos 1505 1.1 christos bfd * 1506 1.1 christos _bfd_vms_lib_get_imagelib_file (bfd *el) 1507 1.1 christos { 1508 1.1 christos bfd *archive = el->my_archive; 1509 1.1.1.8 christos const char *modname = bfd_get_filename (el); 1510 1.1 christos int modlen = strlen (modname); 1511 1.1 christos char *filename; 1512 1.1 christos int j; 1513 1.1 christos bfd *res; 1514 1.1 christos 1515 1.1 christos /* Convert module name to lower case and append '.exe'. */ 1516 1.1 christos filename = bfd_alloc (el, modlen + 5); 1517 1.1 christos if (filename == NULL) 1518 1.1 christos return NULL; 1519 1.1 christos for (j = 0; j < modlen; j++) 1520 1.1 christos if (ISALPHA (modname[j])) 1521 1.1 christos filename[j] = TOLOWER (modname[j]); 1522 1.1 christos else 1523 1.1 christos filename[j] = modname[j]; 1524 1.1 christos memcpy (filename + modlen, ".exe", 5); 1525 1.1 christos 1526 1.1 christos filename = _bfd_append_relative_path (archive, filename); 1527 1.1 christos if (filename == NULL) 1528 1.1 christos return NULL; 1529 1.1 christos res = bfd_openr (filename, NULL); 1530 1.1 christos 1531 1.1 christos if (res == NULL) 1532 1.1 christos { 1533 1.1.1.5 christos /* xgettext:c-format */ 1534 1.1.1.5 christos _bfd_error_handler(_("could not open shared image '%s' from '%s'"), 1535 1.1.1.8 christos filename, bfd_get_filename (archive)); 1536 1.1 christos bfd_release (archive, filename); 1537 1.1 christos return NULL; 1538 1.1 christos } 1539 1.1 christos 1540 1.1 christos /* FIXME: put it in a cache ? */ 1541 1.1 christos return res; 1542 1.1 christos } 1543 1.1 christos 1544 1.1 christos /* Standard function. */ 1545 1.1 christos 1546 1.1 christos bfd * 1547 1.1 christos _bfd_vms_lib_openr_next_archived_file (bfd *archive, 1548 1.1.1.5 christos bfd *last_file) 1549 1.1 christos { 1550 1.1 christos unsigned int idx; 1551 1.1 christos bfd *res; 1552 1.1 christos 1553 1.1 christos if (!last_file) 1554 1.1 christos idx = 0; 1555 1.1 christos else 1556 1.1 christos idx = last_file->proxy_origin + 1; 1557 1.1 christos 1558 1.1 christos if (idx >= bfd_libdata (archive)->nbr_modules) 1559 1.1 christos { 1560 1.1 christos bfd_set_error (bfd_error_no_more_archived_files); 1561 1.1 christos return NULL; 1562 1.1 christos } 1563 1.1 christos 1564 1.1 christos res = _bfd_vms_lib_get_module (archive, idx); 1565 1.1 christos if (res == NULL) 1566 1.1 christos return res; 1567 1.1 christos res->proxy_origin = idx; 1568 1.1 christos return res; 1569 1.1 christos } 1570 1.1 christos 1571 1.1 christos /* Standard function. Just compute the length. */ 1572 1.1 christos 1573 1.1 christos int 1574 1.1 christos _bfd_vms_lib_generic_stat_arch_elt (bfd *abfd, struct stat *st) 1575 1.1 christos { 1576 1.1 christos struct lib_tdata *tdata; 1577 1.1 christos 1578 1.1 christos /* Sanity check. */ 1579 1.1 christos if (abfd->my_archive == NULL) 1580 1.1 christos { 1581 1.1 christos bfd_set_error (bfd_error_invalid_operation); 1582 1.1 christos return -1; 1583 1.1 christos } 1584 1.1 christos 1585 1.1 christos tdata = bfd_libdata (abfd->my_archive); 1586 1.1 christos if (tdata->type != LBR__C_TYP_IOBJ) 1587 1.1 christos { 1588 1.1 christos struct vms_lib_iovec *vec = (struct vms_lib_iovec *) abfd->iostream; 1589 1.1 christos 1590 1.1 christos if (vec->file_len == (ufile_ptr)-1) 1591 1.1.1.5 christos { 1592 1.1.1.5 christos if (vms_lib_bseek (abfd, 0, SEEK_SET) != 0) 1593 1.1.1.5 christos return -1; 1594 1.1.1.5 christos 1595 1.1.1.5 christos /* Compute length. */ 1596 1.1.1.5 christos while (vms_lib_bread (abfd, NULL, 1 << 20) > 0) 1597 1.1.1.5 christos ; 1598 1.1.1.5 christos } 1599 1.1 christos st->st_size = vec->file_len; 1600 1.1 christos } 1601 1.1 christos else 1602 1.1 christos { 1603 1.1 christos st->st_size = ((struct areltdata *)abfd->arelt_data)->parsed_size; 1604 1.1 christos } 1605 1.1 christos 1606 1.1 christos if (abfd->mtime_set) 1607 1.1 christos st->st_mtime = abfd->mtime; 1608 1.1 christos else 1609 1.1 christos st->st_mtime = 0; 1610 1.1 christos st->st_uid = 0; 1611 1.1 christos st->st_gid = 0; 1612 1.1 christos st->st_mode = 0644; 1613 1.1 christos 1614 1.1 christos return 0; 1615 1.1 christos } 1616 1.1 christos 1617 1.1 christos /* Internal representation of an index entry. */ 1618 1.1 christos 1619 1.1 christos struct lib_index 1620 1.1 christos { 1621 1.1 christos /* Corresponding archive member. */ 1622 1.1 christos bfd *abfd; 1623 1.1 christos 1624 1.1 christos /* Number of reference to this entry. */ 1625 1.1 christos unsigned int ref; 1626 1.1 christos 1627 1.1 christos /* Length of the key. */ 1628 1.1 christos unsigned short namlen; 1629 1.1 christos 1630 1.1 christos /* Key. */ 1631 1.1 christos const char *name; 1632 1.1 christos }; 1633 1.1 christos 1634 1.1 christos /* Used to sort index entries. */ 1635 1.1 christos 1636 1.1 christos static int 1637 1.1 christos lib_index_cmp (const void *lv, const void *rv) 1638 1.1 christos { 1639 1.1 christos const struct lib_index *l = lv; 1640 1.1 christos const struct lib_index *r = rv; 1641 1.1 christos 1642 1.1 christos return strcmp (l->name, r->name); 1643 1.1 christos } 1644 1.1 christos 1645 1.1 christos /* Maximum number of index blocks level. */ 1646 1.1 christos 1647 1.1 christos #define MAX_LEVEL 10 1648 1.1 christos 1649 1.1 christos /* Get the size of an index entry. */ 1650 1.1 christos 1651 1.1 christos static unsigned int 1652 1.1.1.8 christos get_idxlen (struct lib_index *idx, bool is_elfidx) 1653 1.1 christos { 1654 1.1 christos if (is_elfidx) 1655 1.1 christos { 1656 1.1.1.2 christos /* 9 is the size of struct vms_elfidx without keyname. */ 1657 1.1 christos if (idx->namlen > MAX_KEYLEN) 1658 1.1.1.5 christos return 9 + sizeof (struct vms_kbn); 1659 1.1 christos else 1660 1.1.1.5 christos return 9 + idx->namlen; 1661 1.1 christos } 1662 1.1 christos else 1663 1.1.1.2 christos { 1664 1.1.1.2 christos /* 7 is the size of struct vms_idx without keyname. */ 1665 1.1.1.2 christos return 7 + idx->namlen; 1666 1.1.1.2 christos } 1667 1.1 christos } 1668 1.1 christos 1669 1.1.1.2 christos /* Write the index composed by NBR symbols contained in IDX. 1670 1.1.1.2 christos VBN is the first vbn to be used, and will contain on return the last vbn. 1671 1.1 christos Can be called with ABFD set to NULL just to size the index. 1672 1.1.1.2 christos If not null, TOPVBN will be assigned to the vbn of the root index tree. 1673 1.1.1.2 christos IS_ELFIDX is true for elfidx (ie ia64) indexes layout. 1674 1.1 christos Return TRUE on success. */ 1675 1.1 christos 1676 1.1.1.8 christos static bool 1677 1.1 christos vms_write_index (bfd *abfd, 1678 1.1.1.5 christos struct lib_index *idx, unsigned int nbr, unsigned int *vbn, 1679 1.1.1.8 christos unsigned int *topvbn, bool is_elfidx) 1680 1.1 christos { 1681 1.1.1.2 christos /* The index is organized as a tree. This function implements a naive 1682 1.1.1.2 christos algorithm to balance the tree: it fills the leaves, and create a new 1683 1.1.1.2 christos branch when all upper leaves and branches are full. We only keep in 1684 1.1.1.2 christos memory a path to the current leaf. */ 1685 1.1 christos unsigned int i; 1686 1.1 christos int j; 1687 1.1 christos int level; 1688 1.1.1.2 christos /* Disk blocks for the current path. */ 1689 1.1 christos struct vms_indexdef *rblk[MAX_LEVEL]; 1690 1.1.1.2 christos /* Info on the current blocks. */ 1691 1.1 christos struct idxblk 1692 1.1 christos { 1693 1.1.1.2 christos unsigned int vbn; /* VBN of the block. */ 1694 1.1.1.2 christos /* The last entry is identified so that it could be copied to the 1695 1.1.1.2 christos parent block. */ 1696 1.1.1.2 christos unsigned short len; /* Length up to the last entry. */ 1697 1.1.1.2 christos unsigned short lastlen; /* Length of the last entry. */ 1698 1.1 christos } blk[MAX_LEVEL]; 1699 1.1 christos 1700 1.1 christos /* The kbn blocks are used to store long symbol names. */ 1701 1.1 christos unsigned int kbn_sz = 0; /* Number of bytes available in the kbn block. */ 1702 1.1 christos unsigned int kbn_vbn = 0; /* VBN of the kbn block. */ 1703 1.1 christos unsigned char *kbn_blk = NULL; /* Contents of the kbn block. */ 1704 1.1 christos 1705 1.1 christos if (nbr == 0) 1706 1.1 christos { 1707 1.1 christos /* No entries. Very easy to handle. */ 1708 1.1 christos if (topvbn != NULL) 1709 1.1.1.5 christos *topvbn = 0; 1710 1.1.1.8 christos return true; 1711 1.1 christos } 1712 1.1 christos 1713 1.1 christos if (abfd == NULL) 1714 1.1 christos { 1715 1.1 christos /* Sort the index the first time this function is called. */ 1716 1.1 christos qsort (idx, nbr, sizeof (struct lib_index), lib_index_cmp); 1717 1.1 christos } 1718 1.1 christos 1719 1.1 christos /* Allocate first index block. */ 1720 1.1 christos level = 1; 1721 1.1 christos if (abfd != NULL) 1722 1.1 christos rblk[0] = bfd_zmalloc (sizeof (struct vms_indexdef)); 1723 1.1 christos blk[0].vbn = (*vbn)++; 1724 1.1 christos blk[0].len = 0; 1725 1.1 christos blk[0].lastlen = 0; 1726 1.1 christos 1727 1.1 christos for (i = 0; i < nbr; i++, idx++) 1728 1.1 christos { 1729 1.1 christos unsigned int idxlen; 1730 1.1 christos int flush = 0; 1731 1.1 christos unsigned int key_vbn = 0; 1732 1.1 christos unsigned int key_off = 0; 1733 1.1 christos 1734 1.1 christos idxlen = get_idxlen (idx, is_elfidx); 1735 1.1 christos 1736 1.1.1.2 christos if (is_elfidx && idx->namlen > MAX_KEYLEN) 1737 1.1.1.5 christos { 1738 1.1.1.5 christos /* If the key (ie name) is too long, write it in the kbn block. */ 1739 1.1.1.5 christos unsigned int kl = idx->namlen; 1740 1.1.1.5 christos unsigned int kl_chunk; 1741 1.1.1.5 christos const char *key = idx->name; 1742 1.1.1.5 christos 1743 1.1.1.5 christos /* Write the key in the kbn, chunk after chunk. */ 1744 1.1.1.5 christos do 1745 1.1.1.5 christos { 1746 1.1.1.5 christos if (kbn_sz < sizeof (struct vms_kbn)) 1747 1.1.1.5 christos { 1748 1.1.1.5 christos /* Not enough room in the kbn block. */ 1749 1.1.1.5 christos if (abfd != NULL) 1750 1.1.1.5 christos { 1751 1.1.1.5 christos /* Write it to the disk (if there is one). */ 1752 1.1.1.5 christos if (kbn_vbn != 0) 1753 1.1.1.5 christos { 1754 1.1.1.5 christos if (!vms_write_block (abfd, kbn_vbn, kbn_blk)) 1755 1.1.1.9 christos goto err; 1756 1.1.1.5 christos } 1757 1.1.1.5 christos else 1758 1.1.1.5 christos { 1759 1.1.1.5 christos kbn_blk = bfd_malloc (VMS_BLOCK_SIZE); 1760 1.1.1.5 christos if (kbn_blk == NULL) 1761 1.1.1.9 christos goto err; 1762 1.1.1.5 christos } 1763 1.1.1.5 christos *(unsigned short *)kbn_blk = 0; 1764 1.1.1.5 christos } 1765 1.1.1.5 christos /* Allocate a new block for the keys. */ 1766 1.1.1.5 christos kbn_vbn = (*vbn)++; 1767 1.1.1.5 christos kbn_sz = VMS_BLOCK_SIZE - 2; 1768 1.1.1.5 christos } 1769 1.1.1.5 christos /* Size of the chunk written to the current key block. */ 1770 1.1.1.5 christos if (kl + sizeof (struct vms_kbn) > kbn_sz) 1771 1.1.1.5 christos kl_chunk = kbn_sz - sizeof (struct vms_kbn); 1772 1.1.1.5 christos else 1773 1.1.1.5 christos kl_chunk = kl; 1774 1.1.1.5 christos 1775 1.1.1.5 christos if (kbn_blk != NULL) 1776 1.1.1.5 christos { 1777 1.1.1.5 christos struct vms_kbn *kbn; 1778 1.1.1.5 christos 1779 1.1.1.5 christos kbn = (struct vms_kbn *)(kbn_blk + VMS_BLOCK_SIZE - kbn_sz); 1780 1.1.1.5 christos 1781 1.1.1.5 christos if (key_vbn == 0) 1782 1.1.1.5 christos { 1783 1.1.1.5 christos /* Save the rfa of the first chunk. */ 1784 1.1.1.5 christos key_vbn = kbn_vbn; 1785 1.1.1.5 christos key_off = VMS_BLOCK_SIZE - kbn_sz; 1786 1.1.1.5 christos } 1787 1.1.1.5 christos 1788 1.1.1.5 christos bfd_putl16 (kl_chunk, kbn->keylen); 1789 1.1.1.5 christos if (kl_chunk == kl) 1790 1.1.1.5 christos { 1791 1.1.1.5 christos /* No next chunk. */ 1792 1.1.1.5 christos bfd_putl32 (0, kbn->rfa.vbn); 1793 1.1.1.5 christos bfd_putl16 (0, kbn->rfa.offset); 1794 1.1.1.5 christos } 1795 1.1.1.5 christos else 1796 1.1.1.5 christos { 1797 1.1.1.5 christos /* Next chunk will be at the start of the next block. */ 1798 1.1.1.5 christos bfd_putl32 (*vbn, kbn->rfa.vbn); 1799 1.1.1.5 christos bfd_putl16 (2, kbn->rfa.offset); 1800 1.1.1.5 christos } 1801 1.1.1.5 christos memcpy ((char *)(kbn + 1), key, kl_chunk); 1802 1.1.1.5 christos key += kl_chunk; 1803 1.1.1.5 christos } 1804 1.1.1.5 christos kl -= kl_chunk; 1805 1.1.1.5 christos kl_chunk = (kl_chunk + 1) & ~1; /* Always align. */ 1806 1.1.1.5 christos kbn_sz -= kl_chunk + sizeof (struct vms_kbn); 1807 1.1.1.5 christos } 1808 1.1.1.5 christos while (kl > 0); 1809 1.1.1.5 christos } 1810 1.1 christos 1811 1.1 christos /* Check if a block might overflow. In this case we will flush this 1812 1.1.1.5 christos block and all the blocks below it. */ 1813 1.1 christos for (j = 0; j < level; j++) 1814 1.1.1.5 christos if (blk[j].len + blk[j].lastlen + idxlen > INDEXDEF__BLKSIZ) 1815 1.1.1.2 christos flush = j + 1; 1816 1.1 christos 1817 1.1 christos for (j = 0; j < level; j++) 1818 1.1.1.5 christos { 1819 1.1.1.5 christos if (j < flush) 1820 1.1.1.5 christos { 1821 1.1.1.5 christos /* There is not enough room to write the new entry in this 1822 1.1.1.5 christos block or in a parent block. */ 1823 1.1.1.5 christos 1824 1.1.1.5 christos if (j + 1 == level) 1825 1.1.1.5 christos { 1826 1.1.1.5 christos BFD_ASSERT (level < MAX_LEVEL); 1827 1.1.1.5 christos 1828 1.1.1.5 christos /* Need to create a parent. */ 1829 1.1.1.5 christos if (abfd != NULL) 1830 1.1.1.5 christos { 1831 1.1.1.5 christos rblk[level] = bfd_zmalloc (sizeof (struct vms_indexdef)); 1832 1.1.1.5 christos bfd_putl32 (*vbn, rblk[j]->parent); 1833 1.1.1.5 christos } 1834 1.1.1.5 christos blk[level].vbn = (*vbn)++; 1835 1.1.1.5 christos blk[level].len = 0; 1836 1.1.1.5 christos blk[level].lastlen = blk[j].lastlen; 1837 1.1 christos 1838 1.1.1.5 christos level++; 1839 1.1.1.5 christos } 1840 1.1 christos 1841 1.1.1.5 christos /* Update parent block: write the last entry from the current 1842 1.1.1.2 christos block. */ 1843 1.1.1.5 christos if (abfd != NULL) 1844 1.1.1.5 christos { 1845 1.1.1.5 christos struct vms_rfa *rfa; 1846 1.1 christos 1847 1.1.1.2 christos /* Pointer to the last entry in parent block. */ 1848 1.1.1.2 christos rfa = (struct vms_rfa *)(rblk[j + 1]->keys + blk[j + 1].len); 1849 1.1.1.2 christos 1850 1.1.1.5 christos /* Copy the whole entry. */ 1851 1.1.1.2 christos BFD_ASSERT (blk[j + 1].lastlen == blk[j].lastlen); 1852 1.1.1.5 christos memcpy (rfa, rblk[j]->keys + blk[j].len, blk[j].lastlen); 1853 1.1.1.5 christos /* Fix the entry (which in always the first field of an 1854 1.1 christos entry. */ 1855 1.1.1.5 christos bfd_putl32 (blk[j].vbn, rfa->vbn); 1856 1.1.1.5 christos bfd_putl16 (RFADEF__C_INDEX, rfa->offset); 1857 1.1.1.5 christos } 1858 1.1.1.5 christos 1859 1.1.1.5 christos if (j + 1 == flush) 1860 1.1.1.5 christos { 1861 1.1.1.5 christos /* And allocate it. Do it only on the block that won't be 1862 1.1.1.5 christos flushed (so that the parent of the parent can be 1863 1.1.1.5 christos updated too). */ 1864 1.1.1.5 christos blk[j + 1].len += blk[j + 1].lastlen; 1865 1.1.1.5 christos blk[j + 1].lastlen = 0; 1866 1.1.1.5 christos } 1867 1.1.1.5 christos 1868 1.1.1.5 christos /* Write this block on the disk. */ 1869 1.1.1.5 christos if (abfd != NULL) 1870 1.1.1.5 christos { 1871 1.1.1.5 christos bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used); 1872 1.1.1.5 christos if (!vms_write_block (abfd, blk[j].vbn, rblk[j])) 1873 1.1.1.9 christos goto err; 1874 1.1.1.5 christos } 1875 1.1.1.5 christos 1876 1.1.1.5 christos /* Reset this block. */ 1877 1.1.1.5 christos blk[j].len = 0; 1878 1.1.1.5 christos blk[j].lastlen = 0; 1879 1.1.1.5 christos blk[j].vbn = (*vbn)++; 1880 1.1.1.5 christos } 1881 1.1.1.5 christos 1882 1.1.1.5 christos /* Append it to the block. */ 1883 1.1.1.5 christos if (j == 0) 1884 1.1.1.5 christos { 1885 1.1.1.2 christos /* Keep the previous last entry. */ 1886 1.1.1.5 christos blk[j].len += blk[j].lastlen; 1887 1.1 christos 1888 1.1.1.5 christos if (abfd != NULL) 1889 1.1.1.5 christos { 1890 1.1.1.5 christos struct vms_rfa *rfa; 1891 1.1.1.5 christos 1892 1.1.1.5 christos rfa = (struct vms_rfa *)(rblk[j]->keys + blk[j].len); 1893 1.1.1.5 christos bfd_putl32 ((idx->abfd->proxy_origin / VMS_BLOCK_SIZE) + 1, 1894 1.1.1.5 christos rfa->vbn); 1895 1.1.1.5 christos bfd_putl16 1896 1.1.1.5 christos ((idx->abfd->proxy_origin % VMS_BLOCK_SIZE) 1897 1.1.1.5 christos + (is_elfidx ? 0 : DATA__DATA), 1898 1.1.1.5 christos rfa->offset); 1899 1.1.1.5 christos 1900 1.1.1.5 christos if (is_elfidx) 1901 1.1.1.5 christos { 1902 1.1.1.5 christos /* Use elfidx format. */ 1903 1.1.1.5 christos struct vms_elfidx *en = (struct vms_elfidx *)rfa; 1904 1.1.1.5 christos 1905 1.1.1.5 christos en->flags = 0; 1906 1.1.1.5 christos if (key_vbn != 0) 1907 1.1.1.5 christos { 1908 1.1.1.5 christos /* Long symbol name. */ 1909 1.1.1.5 christos struct vms_kbn *k = (struct vms_kbn *)(en->keyname); 1910 1.1.1.5 christos bfd_putl16 (sizeof (struct vms_kbn), en->keylen); 1911 1.1.1.5 christos bfd_putl16 (idx->namlen, k->keylen); 1912 1.1.1.5 christos bfd_putl32 (key_vbn, k->rfa.vbn); 1913 1.1.1.5 christos bfd_putl16 (key_off, k->rfa.offset); 1914 1.1.1.5 christos en->flags |= ELFIDX__SYMESC; 1915 1.1.1.5 christos } 1916 1.1.1.5 christos else 1917 1.1.1.5 christos { 1918 1.1.1.5 christos bfd_putl16 (idx->namlen, en->keylen); 1919 1.1.1.5 christos memcpy (en->keyname, idx->name, idx->namlen); 1920 1.1.1.5 christos } 1921 1.1.1.5 christos } 1922 1.1.1.5 christos else 1923 1.1.1.5 christos { 1924 1.1.1.5 christos /* Use idx format. */ 1925 1.1.1.5 christos struct vms_idx *en = (struct vms_idx *)rfa; 1926 1.1.1.5 christos en->keylen = idx->namlen; 1927 1.1.1.5 christos memcpy (en->keyname, idx->name, idx->namlen); 1928 1.1.1.5 christos } 1929 1.1.1.5 christos } 1930 1.1.1.2 christos } 1931 1.1.1.2 christos /* The last added key can now be the last one all blocks in the 1932 1.1.1.2 christos path. */ 1933 1.1.1.2 christos blk[j].lastlen = idxlen; 1934 1.1.1.5 christos } 1935 1.1 christos } 1936 1.1 christos 1937 1.1.1.2 christos /* Save VBN of the root. */ 1938 1.1 christos if (topvbn != NULL) 1939 1.1 christos *topvbn = blk[level - 1].vbn; 1940 1.1 christos 1941 1.1 christos if (abfd == NULL) 1942 1.1.1.8 christos return true; 1943 1.1 christos 1944 1.1 christos /* Flush. */ 1945 1.1 christos for (j = 1; j < level; j++) 1946 1.1 christos { 1947 1.1 christos /* Update parent block: write the new entry. */ 1948 1.1 christos unsigned char *en; 1949 1.1 christos unsigned char *par; 1950 1.1 christos struct vms_rfa *rfa; 1951 1.1 christos 1952 1.1 christos en = rblk[j - 1]->keys + blk[j - 1].len; 1953 1.1 christos par = rblk[j]->keys + blk[j].len; 1954 1.1.1.2 christos BFD_ASSERT (blk[j].lastlen == blk[j - 1].lastlen); 1955 1.1 christos memcpy (par, en, blk[j - 1].lastlen); 1956 1.1 christos rfa = (struct vms_rfa *)par; 1957 1.1 christos bfd_putl32 (blk[j - 1].vbn, rfa->vbn); 1958 1.1 christos bfd_putl16 (RFADEF__C_INDEX, rfa->offset); 1959 1.1 christos } 1960 1.1 christos 1961 1.1 christos for (j = 0; j < level; j++) 1962 1.1 christos { 1963 1.1 christos /* Write this block on the disk. */ 1964 1.1 christos bfd_putl16 (blk[j].len + blk[j].lastlen, rblk[j]->used); 1965 1.1.1.5 christos if (!vms_write_block (abfd, blk[j].vbn, rblk[j])) 1966 1.1.1.9 christos goto err; 1967 1.1 christos 1968 1.1 christos free (rblk[j]); 1969 1.1.1.9 christos rblk[j] = NULL; 1970 1.1 christos } 1971 1.1 christos 1972 1.1 christos /* Write the last kbn (if any). */ 1973 1.1 christos if (kbn_vbn != 0) 1974 1.1 christos { 1975 1.1.1.5 christos if (!vms_write_block (abfd, kbn_vbn, kbn_blk)) 1976 1.1.1.9 christos goto err; 1977 1.1.1.2 christos free (kbn_blk); 1978 1.1 christos } 1979 1.1 christos 1980 1.1.1.8 christos return true; 1981 1.1.1.9 christos 1982 1.1.1.9 christos err: 1983 1.1.1.9 christos if (abfd != NULL) 1984 1.1.1.9 christos { 1985 1.1.1.9 christos for (j = 0; j < level; j++) 1986 1.1.1.9 christos free (rblk[j]); 1987 1.1.1.9 christos free (kbn_blk); 1988 1.1.1.9 christos } 1989 1.1.1.9 christos return false; 1990 1.1 christos } 1991 1.1 christos 1992 1.1 christos /* Append data to the data block DATA. Force write if PAD is true. */ 1993 1.1 christos 1994 1.1.1.8 christos static bool 1995 1.1 christos vms_write_data_block (bfd *arch, struct vms_datadef *data, file_ptr *off, 1996 1.1.1.5 christos const unsigned char *buf, unsigned int len, int pad) 1997 1.1 christos { 1998 1.1 christos while (len > 0 || pad) 1999 1.1 christos { 2000 1.1 christos unsigned int doff = *off & (VMS_BLOCK_SIZE - 1); 2001 1.1 christos unsigned int remlen = (DATA__LENGTH - DATA__DATA) - doff; 2002 1.1 christos unsigned int l; 2003 1.1 christos 2004 1.1 christos l = (len > remlen) ? remlen : len; 2005 1.1 christos memcpy (data->data + doff, buf, l); 2006 1.1 christos buf += l; 2007 1.1 christos len -= l; 2008 1.1 christos doff += l; 2009 1.1 christos *off += l; 2010 1.1 christos 2011 1.1 christos if (doff == (DATA__LENGTH - DATA__DATA) || (len == 0 && pad)) 2012 1.1.1.5 christos { 2013 1.1.1.5 christos data->recs = 0; 2014 1.1.1.5 christos data->fill_1 = 0; 2015 1.1.1.5 christos bfd_putl32 ((*off / VMS_BLOCK_SIZE) + 2, data->link); 2016 1.1.1.5 christos 2017 1.1.1.9 christos if (bfd_write (data, sizeof (*data), arch) != sizeof (*data)) 2018 1.1.1.8 christos return false; 2019 1.1.1.5 christos 2020 1.1.1.5 christos *off += DATA__LENGTH - doff; 2021 1.1.1.5 christos 2022 1.1.1.5 christos if (len == 0) 2023 1.1.1.5 christos break; 2024 1.1.1.5 christos } 2025 1.1 christos } 2026 1.1.1.8 christos return true; 2027 1.1 christos } 2028 1.1 christos 2029 1.1 christos /* Build the symbols index. */ 2030 1.1 christos 2031 1.1.1.8 christos static bool 2032 1.1 christos _bfd_vms_lib_build_map (unsigned int nbr_modules, 2033 1.1.1.5 christos struct lib_index *modules, 2034 1.1.1.5 christos unsigned int *res_cnt, 2035 1.1.1.5 christos struct lib_index **res) 2036 1.1 christos { 2037 1.1 christos unsigned int i; 2038 1.1 christos asymbol **syms = NULL; 2039 1.1 christos long syms_max = 0; 2040 1.1 christos struct lib_index *map = NULL; 2041 1.1 christos unsigned int map_max = 1024; /* Fine initial default. */ 2042 1.1 christos unsigned int map_count = 0; 2043 1.1 christos 2044 1.1 christos map = (struct lib_index *) bfd_malloc (map_max * sizeof (struct lib_index)); 2045 1.1 christos if (map == NULL) 2046 1.1 christos goto error_return; 2047 1.1 christos 2048 1.1 christos /* Gather symbols. */ 2049 1.1 christos for (i = 0; i < nbr_modules; i++) 2050 1.1 christos { 2051 1.1 christos long storage; 2052 1.1 christos long symcount; 2053 1.1 christos long src_count; 2054 1.1 christos bfd *current = modules[i].abfd; 2055 1.1 christos 2056 1.1 christos if ((bfd_get_file_flags (current) & HAS_SYMS) == 0) 2057 1.1.1.5 christos continue; 2058 1.1 christos 2059 1.1 christos storage = bfd_get_symtab_upper_bound (current); 2060 1.1 christos if (storage < 0) 2061 1.1.1.5 christos goto error_return; 2062 1.1 christos 2063 1.1 christos if (storage != 0) 2064 1.1.1.5 christos { 2065 1.1.1.5 christos if (storage > syms_max) 2066 1.1.1.5 christos { 2067 1.1.1.8 christos free (syms); 2068 1.1.1.5 christos syms_max = storage; 2069 1.1.1.5 christos syms = (asymbol **) bfd_malloc (syms_max); 2070 1.1.1.5 christos if (syms == NULL) 2071 1.1.1.5 christos goto error_return; 2072 1.1.1.5 christos } 2073 1.1.1.5 christos symcount = bfd_canonicalize_symtab (current, syms); 2074 1.1.1.5 christos if (symcount < 0) 2075 1.1.1.5 christos goto error_return; 2076 1.1.1.5 christos 2077 1.1.1.5 christos /* Now map over all the symbols, picking out the ones we 2078 1.1.1.5 christos want. */ 2079 1.1.1.5 christos for (src_count = 0; src_count < symcount; src_count++) 2080 1.1.1.5 christos { 2081 1.1.1.5 christos flagword flags = (syms[src_count])->flags; 2082 1.1.1.5 christos asection *sec = syms[src_count]->section; 2083 1.1.1.5 christos 2084 1.1.1.5 christos if ((flags & BSF_GLOBAL 2085 1.1.1.5 christos || flags & BSF_WEAK 2086 1.1.1.5 christos || flags & BSF_INDIRECT 2087 1.1.1.5 christos || bfd_is_com_section (sec)) 2088 1.1.1.5 christos && ! bfd_is_und_section (sec)) 2089 1.1.1.5 christos { 2090 1.1.1.5 christos struct lib_index *new_map; 2091 1.1.1.5 christos 2092 1.1.1.5 christos /* This symbol will go into the archive header. */ 2093 1.1.1.5 christos if (map_count == map_max) 2094 1.1.1.5 christos { 2095 1.1.1.5 christos map_max *= 2; 2096 1.1.1.5 christos new_map = (struct lib_index *) 2097 1.1.1.5 christos bfd_realloc (map, map_max * sizeof (struct lib_index)); 2098 1.1.1.5 christos if (new_map == NULL) 2099 1.1.1.5 christos goto error_return; 2100 1.1.1.5 christos map = new_map; 2101 1.1.1.5 christos } 2102 1.1.1.5 christos 2103 1.1.1.5 christos map[map_count].abfd = current; 2104 1.1.1.5 christos map[map_count].namlen = strlen (syms[src_count]->name); 2105 1.1.1.5 christos map[map_count].name = syms[src_count]->name; 2106 1.1.1.5 christos map_count++; 2107 1.1.1.5 christos modules[i].ref++; 2108 1.1.1.5 christos } 2109 1.1.1.5 christos } 2110 1.1 christos } 2111 1.1 christos } 2112 1.1 christos 2113 1.1 christos *res_cnt = map_count; 2114 1.1 christos *res = map; 2115 1.1.1.9 christos free (syms); 2116 1.1.1.8 christos return true; 2117 1.1 christos 2118 1.1 christos error_return: 2119 1.1.1.8 christos free (syms); 2120 1.1.1.8 christos free (map); 2121 1.1.1.8 christos return false; 2122 1.1 christos } 2123 1.1 christos 2124 1.1 christos /* Do the hard work: write an archive on the disk. */ 2125 1.1 christos 2126 1.1.1.8 christos bool 2127 1.1 christos _bfd_vms_lib_write_archive_contents (bfd *arch) 2128 1.1 christos { 2129 1.1 christos bfd *current; 2130 1.1 christos unsigned int nbr_modules; 2131 1.1 christos struct lib_index *modules; 2132 1.1 christos unsigned int nbr_symbols; 2133 1.1.1.9 christos struct lib_index *symbols = NULL; 2134 1.1 christos struct lib_tdata *tdata = bfd_libdata (arch); 2135 1.1 christos unsigned int i; 2136 1.1 christos file_ptr off; 2137 1.1 christos unsigned int nbr_mod_iblk; 2138 1.1 christos unsigned int nbr_sym_iblk; 2139 1.1 christos unsigned int vbn; 2140 1.1 christos unsigned int mod_idx_vbn; 2141 1.1 christos unsigned int sym_idx_vbn; 2142 1.1.1.8 christos bool is_elfidx = tdata->kind == vms_lib_ia64; 2143 1.1.1.2 christos unsigned int max_keylen = is_elfidx ? MAX_EKEYLEN : MAX_KEYLEN; 2144 1.1 christos 2145 1.1 christos /* Count the number of modules (and do a first sanity check). */ 2146 1.1 christos nbr_modules = 0; 2147 1.1 christos for (current = arch->archive_head; 2148 1.1 christos current != NULL; 2149 1.1 christos current = current->archive_next) 2150 1.1 christos { 2151 1.1 christos /* This check is checking the bfds for the objects we're reading 2152 1.1 christos from (which are usually either an object file or archive on 2153 1.1 christos disk), not the archive entries we're writing to. We don't 2154 1.1 christos actually create bfds for the archive members, we just copy 2155 1.1 christos them byte-wise when we write out the archive. */ 2156 1.1 christos if (bfd_write_p (current) || !bfd_check_format (current, bfd_object)) 2157 1.1 christos { 2158 1.1 christos bfd_set_error (bfd_error_invalid_operation); 2159 1.1 christos goto input_err; 2160 1.1 christos } 2161 1.1 christos 2162 1.1 christos nbr_modules++; 2163 1.1 christos } 2164 1.1 christos 2165 1.1 christos /* Build the modules list. */ 2166 1.1 christos BFD_ASSERT (tdata->modules == NULL); 2167 1.1 christos modules = bfd_alloc (arch, nbr_modules * sizeof (struct lib_index)); 2168 1.1 christos if (modules == NULL) 2169 1.1.1.8 christos return false; 2170 1.1 christos 2171 1.1 christos for (current = arch->archive_head, i = 0; 2172 1.1 christos current != NULL; 2173 1.1 christos current = current->archive_next, i++) 2174 1.1 christos { 2175 1.1.1.2 christos unsigned int nl; 2176 1.1 christos 2177 1.1 christos modules[i].abfd = current; 2178 1.1.1.8 christos modules[i].name = vms_get_module_name (bfd_get_filename (current), false); 2179 1.1 christos modules[i].ref = 1; 2180 1.1 christos 2181 1.1 christos /* FIXME: silently truncate long names ? */ 2182 1.1 christos nl = strlen (modules[i].name); 2183 1.1.1.2 christos modules[i].namlen = (nl > max_keylen ? max_keylen : nl); 2184 1.1 christos } 2185 1.1 christos 2186 1.1 christos /* Create the module index. */ 2187 1.1 christos vbn = 0; 2188 1.1 christos if (!vms_write_index (NULL, modules, nbr_modules, &vbn, NULL, is_elfidx)) 2189 1.1.1.8 christos return false; 2190 1.1 christos nbr_mod_iblk = vbn; 2191 1.1 christos 2192 1.1 christos /* Create symbol index. */ 2193 1.1 christos if (!_bfd_vms_lib_build_map (nbr_modules, modules, &nbr_symbols, &symbols)) 2194 1.1.1.9 christos goto err; 2195 1.1 christos 2196 1.1 christos vbn = 0; 2197 1.1 christos if (!vms_write_index (NULL, symbols, nbr_symbols, &vbn, NULL, is_elfidx)) 2198 1.1.1.9 christos goto err; 2199 1.1 christos nbr_sym_iblk = vbn; 2200 1.1 christos 2201 1.1 christos /* Write modules and remember their position. */ 2202 1.1 christos off = (1 + nbr_mod_iblk + nbr_sym_iblk) * VMS_BLOCK_SIZE; 2203 1.1 christos 2204 1.1 christos if (bfd_seek (arch, off, SEEK_SET) != 0) 2205 1.1.1.9 christos goto err; 2206 1.1 christos 2207 1.1 christos for (i = 0; i < nbr_modules; i++) 2208 1.1 christos { 2209 1.1 christos struct vms_datadef data; 2210 1.1 christos unsigned char blk[VMS_BLOCK_SIZE]; 2211 1.1 christos struct vms_mhd *mhd; 2212 1.1 christos unsigned int sz; 2213 1.1 christos 2214 1.1 christos current = modules[i].abfd; 2215 1.1 christos current->proxy_origin = off; 2216 1.1 christos 2217 1.1 christos if (is_elfidx) 2218 1.1.1.5 christos sz = 0; 2219 1.1 christos else 2220 1.1.1.5 christos { 2221 1.1.1.5 christos /* Write the MHD as a record (ie, size first). */ 2222 1.1.1.5 christos sz = 2; 2223 1.1.1.5 christos bfd_putl16 (tdata->mhd_size, blk); 2224 1.1.1.5 christos } 2225 1.1 christos mhd = (struct vms_mhd *)(blk + sz); 2226 1.1 christos memset (mhd, 0, sizeof (struct vms_mhd)); 2227 1.1 christos mhd->lbrflag = 0; 2228 1.1 christos mhd->id = MHD__C_MHDID; 2229 1.1 christos mhd->objidlng = 4; 2230 1.1 christos memcpy (mhd->objid, "V1.0", 4); 2231 1.1 christos bfd_putl32 (modules[i].ref, mhd->refcnt); 2232 1.1 christos /* FIXME: datim. */ 2233 1.1 christos 2234 1.1 christos sz += tdata->mhd_size; 2235 1.1 christos sz = (sz + 1) & ~1; 2236 1.1 christos 2237 1.1 christos /* Rewind the member to be put into the archive. */ 2238 1.1 christos if (bfd_seek (current, 0, SEEK_SET) != 0) 2239 1.1.1.5 christos goto input_err; 2240 1.1 christos 2241 1.1 christos /* Copy the member into the archive. */ 2242 1.1 christos if (is_elfidx) 2243 1.1.1.5 christos { 2244 1.1.1.5 christos unsigned int modsize = 0; 2245 1.1.1.5 christos bfd_size_type amt; 2246 1.1.1.5 christos file_ptr off_hdr = off; 2247 1.1.1.5 christos 2248 1.1.1.5 christos /* Read to complete the first block. */ 2249 1.1.1.9 christos amt = bfd_read (blk + sz, VMS_BLOCK_SIZE - sz, current); 2250 1.1.1.5 christos if (amt == (bfd_size_type)-1) 2251 1.1.1.5 christos goto input_err; 2252 1.1.1.5 christos modsize = amt; 2253 1.1.1.5 christos if (amt < VMS_BLOCK_SIZE - sz) 2254 1.1.1.5 christos { 2255 1.1.1.5 christos /* The member size is less than a block. Pad the block. */ 2256 1.1.1.5 christos memset (blk + sz + amt, 0, VMS_BLOCK_SIZE - sz - amt); 2257 1.1.1.5 christos } 2258 1.1.1.5 christos bfd_putl32 (modsize, mhd->modsize); 2259 1.1.1.5 christos 2260 1.1.1.5 christos /* Write the first block (which contains an mhd). */ 2261 1.1.1.9 christos if (bfd_write (blk, VMS_BLOCK_SIZE, arch) != VMS_BLOCK_SIZE) 2262 1.1.1.5 christos goto input_err; 2263 1.1.1.5 christos off += VMS_BLOCK_SIZE; 2264 1.1.1.5 christos 2265 1.1.1.5 christos if (amt == VMS_BLOCK_SIZE - sz) 2266 1.1.1.5 christos { 2267 1.1.1.5 christos /* Copy the remaining. */ 2268 1.1.1.9 christos char buffer[8 * 1024]; 2269 1.1.1.5 christos 2270 1.1.1.5 christos while (1) 2271 1.1.1.5 christos { 2272 1.1.1.9 christos amt = bfd_read (buffer, sizeof (buffer), current); 2273 1.1.1.5 christos if (amt == (bfd_size_type)-1) 2274 1.1.1.5 christos goto input_err; 2275 1.1.1.5 christos if (amt == 0) 2276 1.1.1.5 christos break; 2277 1.1.1.5 christos modsize += amt; 2278 1.1.1.5 christos if (amt != sizeof (buffer)) 2279 1.1.1.5 christos { 2280 1.1.1.5 christos /* Clear the padding. */ 2281 1.1.1.5 christos memset (buffer + amt, 0, sizeof (buffer) - amt); 2282 1.1.1.5 christos amt = (amt + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1); 2283 1.1.1.5 christos } 2284 1.1.1.9 christos if (bfd_write (buffer, amt, arch) != amt) 2285 1.1.1.5 christos goto input_err; 2286 1.1.1.5 christos off += amt; 2287 1.1.1.5 christos } 2288 1.1.1.5 christos 2289 1.1.1.5 christos /* Now that the size is known, write the first block (again). */ 2290 1.1.1.5 christos bfd_putl32 (modsize, mhd->modsize); 2291 1.1.1.5 christos if (bfd_seek (arch, off_hdr, SEEK_SET) != 0 2292 1.1.1.9 christos || bfd_write (blk, VMS_BLOCK_SIZE, arch) != VMS_BLOCK_SIZE) 2293 1.1.1.5 christos goto input_err; 2294 1.1.1.5 christos if (bfd_seek (arch, off, SEEK_SET) != 0) 2295 1.1.1.5 christos goto input_err; 2296 1.1.1.5 christos } 2297 1.1.1.5 christos } 2298 1.1 christos else 2299 1.1.1.5 christos { 2300 1.1.1.5 christos /* Write the MHD. */ 2301 1.1.1.8 christos if (!vms_write_data_block (arch, &data, &off, blk, sz, 0)) 2302 1.1.1.5 christos goto input_err; 2303 1.1.1.5 christos 2304 1.1.1.5 christos /* Write the member. */ 2305 1.1.1.5 christos while (1) 2306 1.1.1.5 christos { 2307 1.1.1.9 christos sz = bfd_read (blk, sizeof (blk), current); 2308 1.1.1.5 christos if (sz == 0) 2309 1.1.1.5 christos break; 2310 1.1.1.8 christos if (!vms_write_data_block (arch, &data, &off, blk, sz, 0)) 2311 1.1.1.5 christos goto input_err; 2312 1.1.1.5 christos } 2313 1.1.1.5 christos 2314 1.1.1.5 christos /* Write the end of module marker. */ 2315 1.1.1.8 christos if (!vms_write_data_block (arch, &data, &off, 2316 1.1.1.8 christos eotdesc, sizeof (eotdesc), 1)) 2317 1.1.1.5 christos goto input_err; 2318 1.1.1.5 christos } 2319 1.1 christos } 2320 1.1 christos 2321 1.1 christos /* Write the indexes. */ 2322 1.1 christos vbn = 2; 2323 1.1.1.5 christos if (!vms_write_index (arch, modules, nbr_modules, &vbn, &mod_idx_vbn, 2324 1.1.1.5 christos is_elfidx)) 2325 1.1.1.9 christos goto err; 2326 1.1.1.5 christos if (!vms_write_index (arch, symbols, nbr_symbols, &vbn, &sym_idx_vbn, 2327 1.1.1.5 christos is_elfidx)) 2328 1.1.1.9 christos goto err; 2329 1.1 christos 2330 1.1 christos /* Write libary header. */ 2331 1.1 christos { 2332 1.1 christos unsigned char blk[VMS_BLOCK_SIZE]; 2333 1.1 christos struct vms_lhd *lhd = (struct vms_lhd *)blk; 2334 1.1 christos struct vms_idd *idd = (struct vms_idd *)(blk + sizeof (*lhd)); 2335 1.1 christos unsigned int idd_flags; 2336 1.1 christos unsigned int saneid; 2337 1.1 christos 2338 1.1 christos memset (blk, 0, sizeof (blk)); 2339 1.1 christos 2340 1.1 christos lhd->type = tdata->type; 2341 1.1 christos lhd->nindex = 2; 2342 1.1 christos switch (tdata->kind) 2343 1.1 christos { 2344 1.1 christos case vms_lib_alpha: 2345 1.1.1.5 christos saneid = LHD_SANEID3; 2346 1.1.1.5 christos break; 2347 1.1 christos case vms_lib_ia64: 2348 1.1.1.5 christos saneid = LHD_SANEID6; 2349 1.1.1.5 christos break; 2350 1.1 christos default: 2351 1.1.1.5 christos abort (); 2352 1.1 christos } 2353 1.1 christos bfd_putl32 (saneid, lhd->sanity); 2354 1.1 christos bfd_putl16 (tdata->ver, lhd->majorid); 2355 1.1 christos bfd_putl16 (0, lhd->minorid); 2356 1.1 christos snprintf ((char *)lhd->lbrver + 1, sizeof (lhd->lbrver) - 1, 2357 1.1.1.5 christos "GNU ar %u.%u.%u", 2358 1.1.1.5 christos (unsigned)(BFD_VERSION / 100000000UL), 2359 1.1.1.5 christos (unsigned)(BFD_VERSION / 1000000UL) % 100, 2360 1.1.1.5 christos (unsigned)(BFD_VERSION / 10000UL) % 100); 2361 1.1 christos lhd->lbrver[sizeof (lhd->lbrver) - 1] = 0; 2362 1.1 christos lhd->lbrver[0] = strlen ((char *)lhd->lbrver + 1); 2363 1.1 christos 2364 1.1 christos bfd_putl32 (tdata->credat_lo, lhd->credat + 0); 2365 1.1 christos bfd_putl32 (tdata->credat_hi, lhd->credat + 4); 2366 1.1 christos vms_raw_get_time (lhd->updtim); 2367 1.1 christos 2368 1.1 christos lhd->mhdusz = tdata->mhd_size - MHD__C_USRDAT; 2369 1.1 christos 2370 1.1 christos bfd_putl32 (nbr_modules + nbr_symbols, lhd->idxcnt); 2371 1.1 christos bfd_putl32 (nbr_modules, lhd->modcnt); 2372 1.1 christos bfd_putl32 (nbr_modules, lhd->modhdrs); 2373 1.1 christos 2374 1.1.1.2 christos /* Number of blocks for index. */ 2375 1.1.1.2 christos bfd_putl32 (nbr_mod_iblk + nbr_sym_iblk, lhd->idxblks); 2376 1.1 christos bfd_putl32 (vbn - 1, lhd->hipreal); 2377 1.1 christos bfd_putl32 (vbn - 1, lhd->hiprusd); 2378 1.1 christos 2379 1.1.1.2 christos /* VBN of the next free block. */ 2380 1.1.1.2 christos bfd_putl32 ((off / VMS_BLOCK_SIZE) + 1, lhd->nextvbn); 2381 1.1.1.2 christos bfd_putl32 ((off / VMS_BLOCK_SIZE) + 1, lhd->nextrfa + 0); 2382 1.1.1.2 christos bfd_putl16 (0, lhd->nextrfa + 4); 2383 1.1.1.2 christos 2384 1.1 christos /* First index (modules name). */ 2385 1.1 christos idd_flags = IDD__FLAGS_ASCII | IDD__FLAGS_VARLENIDX 2386 1.1 christos | IDD__FLAGS_NOCASECMP | IDD__FLAGS_NOCASENTR; 2387 1.1 christos bfd_putl16 (idd_flags, idd->flags); 2388 1.1.1.2 christos bfd_putl16 (max_keylen + 1, idd->keylen); 2389 1.1 christos bfd_putl16 (mod_idx_vbn, idd->vbn); 2390 1.1 christos idd++; 2391 1.1 christos 2392 1.1 christos /* Second index (symbols name). */ 2393 1.1 christos bfd_putl16 (idd_flags, idd->flags); 2394 1.1.1.2 christos bfd_putl16 (max_keylen + 1, idd->keylen); 2395 1.1 christos bfd_putl16 (sym_idx_vbn, idd->vbn); 2396 1.1 christos idd++; 2397 1.1 christos 2398 1.1.1.5 christos if (!vms_write_block (arch, 1, blk)) 2399 1.1.1.9 christos goto err; 2400 1.1 christos } 2401 1.1 christos 2402 1.1.1.9 christos free (symbols); 2403 1.1.1.8 christos return true; 2404 1.1 christos 2405 1.1 christos input_err: 2406 1.1.1.5 christos bfd_set_input_error (current, bfd_get_error ()); 2407 1.1.1.9 christos err: 2408 1.1.1.9 christos free (symbols); 2409 1.1.1.8 christos return false; 2410 1.1 christos } 2411 1.1 christos 2412 1.1 christos /* Add a target for text library. This costs almost nothing and is useful to 2413 1.1 christos read VMS library on the host. */ 2414 1.1 christos 2415 1.1.1.3 christos const bfd_target alpha_vms_lib_txt_vec = 2416 1.1 christos { 2417 1.1 christos "vms-libtxt", /* Name. */ 2418 1.1 christos bfd_target_unknown_flavour, 2419 1.1 christos BFD_ENDIAN_UNKNOWN, /* byteorder */ 2420 1.1 christos BFD_ENDIAN_UNKNOWN, /* header_byteorder */ 2421 1.1 christos 0, /* Object flags. */ 2422 1.1 christos 0, /* Sect flags. */ 2423 1.1 christos 0, /* symbol_leading_char. */ 2424 1.1 christos ' ', /* ar_pad_char. */ 2425 1.1 christos 15, /* ar_max_namelen. */ 2426 1.1.1.2 christos 0, /* match priority. */ 2427 1.1.1.8 christos TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */ 2428 1.1.1.11 christos false, /* merge sections */ 2429 1.1 christos bfd_getl64, bfd_getl_signed_64, bfd_putl64, 2430 1.1 christos bfd_getl32, bfd_getl_signed_32, bfd_putl32, 2431 1.1 christos bfd_getl16, bfd_getl_signed_16, bfd_putl16, 2432 1.1 christos bfd_getl64, bfd_getl_signed_64, bfd_putl64, 2433 1.1 christos bfd_getl32, bfd_getl_signed_32, bfd_putl32, 2434 1.1 christos bfd_getl16, bfd_getl_signed_16, bfd_putl16, 2435 1.1.1.6 christos { /* bfd_check_format. */ 2436 1.1.1.6 christos _bfd_dummy_target, 2437 1.1.1.6 christos _bfd_dummy_target, 2438 1.1.1.6 christos _bfd_vms_lib_txt_archive_p, 2439 1.1.1.6 christos _bfd_dummy_target 2440 1.1.1.6 christos }, 2441 1.1.1.6 christos { /* bfd_set_format. */ 2442 1.1.1.6 christos _bfd_bool_bfd_false_error, 2443 1.1.1.6 christos _bfd_bool_bfd_false_error, 2444 1.1.1.6 christos _bfd_bool_bfd_false_error, 2445 1.1.1.6 christos _bfd_bool_bfd_false_error 2446 1.1.1.6 christos }, 2447 1.1.1.6 christos { /* bfd_write_contents. */ 2448 1.1.1.6 christos _bfd_bool_bfd_false_error, 2449 1.1.1.6 christos _bfd_bool_bfd_false_error, 2450 1.1.1.6 christos _bfd_bool_bfd_false_error, 2451 1.1.1.6 christos _bfd_bool_bfd_false_error 2452 1.1.1.6 christos }, 2453 1.1 christos BFD_JUMP_TABLE_GENERIC (_bfd_generic), 2454 1.1 christos BFD_JUMP_TABLE_COPY (_bfd_generic), 2455 1.1 christos BFD_JUMP_TABLE_CORE (_bfd_nocore), 2456 1.1 christos BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib), 2457 1.1 christos BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols), 2458 1.1 christos BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 2459 1.1 christos BFD_JUMP_TABLE_WRITE (_bfd_nowrite), 2460 1.1 christos BFD_JUMP_TABLE_LINK (_bfd_nolink), 2461 1.1 christos BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 2462 1.1 christos 2463 1.1 christos NULL, 2464 1.1 christos 2465 1.1.1.2 christos NULL 2466 1.1 christos }; 2467