1 /* vms-hdr.c -- BFD back-end for VMS/VAX (openVMS/VAX) and 2 EVAX (openVMS/Alpha) files. 3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 4 Free Software Foundation, Inc. 5 6 HDR record handling functions 7 EMH record handling functions 8 and 9 EOM record handling functions 10 EEOM record handling functions 11 12 Written by Klaus K"ampf (kkaempf@rmi.de) 13 14 This program is free software; you can redistribute it and/or modify 15 it under the terms of the GNU General Public License as published by 16 the Free Software Foundation; either version 2 of the License, or 17 (at your option) any later version. 18 19 This program is distributed in the hope that it will be useful, 20 but WITHOUT ANY WARRANTY; without even the implied warranty of 21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 GNU General Public License for more details. 23 24 You should have received a copy of the GNU General Public License 25 along with this program; if not, write to the Free Software 26 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 27 28 #include "bfd.h" 29 #include "bfdver.h" 30 #include "sysdep.h" 31 #include "bfdlink.h" 32 #include "safe-ctype.h" 33 #include "libbfd.h" 34 35 #include "vms.h" 36 37 #ifdef HAVE_ALLOCA_H 38 #include <alloca.h> 39 #endif 40 41 static unsigned char *get_vms_time_string PARAMS ((void)); 42 43 44 /*---------------------------------------------------------------------------*/ 45 46 /* Read & process emh record 47 return 0 on success, -1 on error */ 48 49 int 50 _bfd_vms_slurp_hdr (abfd, objtype) 51 bfd *abfd; 52 int objtype; 53 { 54 unsigned char *ptr; 55 unsigned char *vms_rec; 56 int subtype; 57 58 vms_rec = PRIV(vms_rec); 59 60 #if VMS_DEBUG 61 vms_debug(2, "HDR/EMH\n"); 62 #endif 63 64 switch (objtype) 65 { 66 case OBJ_S_C_HDR: 67 subtype = vms_rec[1]; 68 break; 69 case EOBJ_S_C_EMH: 70 subtype = bfd_getl16 (vms_rec + 4) + EVAX_OFFSET; 71 break; 72 default: 73 subtype = -1; 74 } 75 76 #if VMS_DEBUG 77 vms_debug(3, "subtype %d\n", subtype); 78 #endif 79 80 switch (subtype) 81 { 82 83 case MHD_S_C_MHD: 84 /* 85 * module header 86 */ 87 PRIV(hdr_data).hdr_b_strlvl = vms_rec[2]; 88 PRIV(hdr_data).hdr_l_recsiz = bfd_getl16 (vms_rec + 3); 89 PRIV(hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 5); 90 ptr = vms_rec + 5 + vms_rec[5] + 1; 91 PRIV(hdr_data).hdr_t_version = _bfd_vms_save_counted_string (ptr); 92 ptr += *ptr + 1; 93 PRIV(hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17); 94 95 break; 96 97 case MHD_S_C_LNM: 98 /* 99 * 100 */ 101 PRIV(hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV(rec_length-2)); 102 break; 103 104 case MHD_S_C_SRC: 105 /* 106 * 107 */ 108 PRIV(hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV(rec_length-2)); 109 break; 110 111 case MHD_S_C_TTL: 112 /* 113 * 114 */ 115 PRIV(hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV(rec_length-2)); 116 break; 117 118 case MHD_S_C_CPR: 119 /* 120 * 121 */ 122 break; 123 124 case MHD_S_C_MTC: 125 /* 126 * 127 */ 128 break; 129 130 case MHD_S_C_GTX: 131 /* 132 * 133 */ 134 break; 135 136 case EMH_S_C_MHD + EVAX_OFFSET: 137 /* 138 * module header 139 */ 140 PRIV(hdr_data).hdr_b_strlvl = vms_rec[6]; 141 PRIV(hdr_data).hdr_l_arch1 = bfd_getl32 (vms_rec + 8); 142 PRIV(hdr_data).hdr_l_arch2 = bfd_getl32 (vms_rec + 12); 143 PRIV(hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16); 144 PRIV(hdr_data).hdr_t_name = 145 _bfd_vms_save_counted_string (vms_rec + 20); 146 ptr = vms_rec + 20 + vms_rec[20] + 1; 147 PRIV(hdr_data).hdr_t_version = 148 _bfd_vms_save_counted_string (ptr); 149 ptr += *ptr + 1; 150 PRIV(hdr_data).hdr_t_date = 151 _bfd_vms_save_sized_string (ptr, 17); 152 153 break; 154 155 case EMH_S_C_LNM + EVAX_OFFSET: 156 /* 157 * 158 */ 159 PRIV(hdr_data).hdr_c_lnm = 160 _bfd_vms_save_sized_string (vms_rec, PRIV(rec_length-6)); 161 break; 162 163 case EMH_S_C_SRC + EVAX_OFFSET: 164 /* 165 * 166 */ 167 PRIV(hdr_data).hdr_c_src = 168 _bfd_vms_save_sized_string (vms_rec, PRIV(rec_length-6)); 169 break; 170 171 case EMH_S_C_TTL + EVAX_OFFSET: 172 /* 173 * 174 */ 175 PRIV(hdr_data).hdr_c_ttl = 176 _bfd_vms_save_sized_string (vms_rec, PRIV(rec_length-6)); 177 break; 178 179 case EMH_S_C_CPR + EVAX_OFFSET: 180 /* 181 * 182 */ 183 break; 184 185 case EMH_S_C_MTC + EVAX_OFFSET: 186 /* 187 * 188 */ 189 break; 190 191 case EMH_S_C_GTX + EVAX_OFFSET: 192 /* 193 * 194 */ 195 break; 196 197 default: 198 bfd_set_error (bfd_error_wrong_format); 199 return -1; 200 201 } /* switch */ 202 203 return 0; 204 } 205 206 /*-----------------------------------------------------------------------------*/ 207 /* Output routines. */ 208 209 /* Manufacture a VMS like time on a unix based system. 210 stolen from obj-vms.c */ 211 212 static unsigned char * 213 get_vms_time_string () 214 { 215 static unsigned char tbuf[18]; 216 #ifndef VMS 217 #include <time.h> 218 219 char *pnt; 220 time_t timeb; 221 time (&timeb); 222 pnt = ctime (&timeb); 223 pnt[3] = 0; 224 pnt[7] = 0; 225 pnt[10] = 0; 226 pnt[16] = 0; 227 pnt[24] = 0; 228 sprintf (tbuf, "%2s-%3s-%s %s", pnt + 8, pnt + 4, pnt + 20, pnt + 11); 229 #else 230 #include <starlet.h> 231 struct 232 { 233 int Size; 234 unsigned char *Ptr; 235 } Descriptor; 236 Descriptor.Size = 17; 237 Descriptor.Ptr = tbuf; 238 SYS$ASCTIM (0, &Descriptor, 0, 0); 239 #endif /* not VMS */ 240 241 #if VMS_DEBUG 242 vms_debug (6, "vmstimestring:'%s'\n", tbuf); 243 #endif 244 245 return tbuf; 246 } 247 248 /* write object header for bfd abfd */ 249 250 int 251 _bfd_vms_write_hdr (abfd, objtype) 252 bfd *abfd; 253 int objtype; 254 { 255 asymbol *symbol; 256 unsigned int symnum; 257 int had_case = 0; 258 int had_file = 0; 259 260 #if VMS_DEBUG 261 vms_debug (2, "vms_write_hdr (%p)\n", abfd); 262 #endif 263 264 _bfd_vms_output_alignment (abfd, 2); 265 266 /* MHD */ 267 268 if (objtype == OBJ_S_C_HDR) 269 { 270 } 271 else 272 { 273 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_MHD); 274 _bfd_vms_output_short (abfd, EOBJ_S_C_STRLVL); 275 _bfd_vms_output_long (abfd, 0); 276 _bfd_vms_output_long (abfd, 0); 277 _bfd_vms_output_long (abfd, MAX_OUTREC_SIZE); 278 } 279 280 if (bfd_get_filename (abfd) != 0) 281 { 282 /* strip path and suffix information */ 283 284 char *fname, *fout, *fptr; 285 286 fptr = bfd_get_filename (abfd); 287 fname = (char *) alloca (strlen (fptr) + 1); 288 strcpy (fname, fptr); 289 fout = strrchr (fname, ']'); 290 if (fout == 0) 291 fout = strchr (fname, ':'); 292 if (fout != 0) 293 fout++; 294 else 295 fout = fname; 296 297 /* strip .obj suffix */ 298 299 fptr = strrchr (fname, '.'); 300 if ((fptr != 0) 301 && (strcasecmp (fptr, ".OBJ") == 0)) 302 *fptr = 0; 303 304 fptr = fout; 305 while (*fptr != 0) 306 { 307 *fptr = TOUPPER (*fptr); 308 fptr++; 309 if ((*fptr == ';') 310 || ((fptr - fout) > 31)) 311 *fptr = 0; 312 } 313 _bfd_vms_output_counted (abfd, fout); 314 } 315 else 316 _bfd_vms_output_counted (abfd, "NONAME"); 317 318 _bfd_vms_output_counted (abfd, BFD_VERSION_STRING); 319 _bfd_vms_output_dump (abfd, get_vms_time_string (), 17); 320 _bfd_vms_output_fill (abfd, 0, 17); 321 _bfd_vms_output_flush (abfd); 322 323 /* LMN */ 324 325 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_LNM); 326 _bfd_vms_output_dump (abfd, (unsigned char *)"GAS proGIS", 10); 327 _bfd_vms_output_flush (abfd); 328 329 /* SRC */ 330 331 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_SRC); 332 333 for (symnum = 0; symnum < abfd->symcount; symnum++) 334 { 335 symbol = abfd->outsymbols[symnum]; 336 337 if (symbol->flags & BSF_FILE) 338 { 339 if (strncmp ((char *)symbol->name, "<CASE:", 6) == 0) 340 { 341 PRIV(flag_hash_long_names) = symbol->name[6] - '0'; 342 PRIV(flag_show_after_trunc) = symbol->name[7] - '0'; 343 344 if (had_file) 345 break; 346 had_case = 1; 347 continue; 348 } 349 350 _bfd_vms_output_dump (abfd, (unsigned char *) symbol->name, 351 (int) strlen (symbol->name)); 352 if (had_case) 353 break; 354 had_file = 1; 355 } 356 } 357 358 if (symnum == abfd->symcount) 359 _bfd_vms_output_dump (abfd, (unsigned char *)"noname", 6); 360 361 _bfd_vms_output_flush (abfd); 362 363 /* TTL */ 364 365 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_TTL); 366 _bfd_vms_output_dump (abfd, (unsigned char *)"TTL", 3); 367 _bfd_vms_output_flush (abfd); 368 369 /* CPR */ 370 371 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_CPR); 372 _bfd_vms_output_dump (abfd, 373 (unsigned char *)"GNU BFD ported by Klaus K�mpf 1994-1996", 374 39); 375 _bfd_vms_output_flush (abfd); 376 377 return 0; 378 } 379 380 /*-----------------------------------------------------------------------------*/ 381 382 /* Process EOM/EEOM record 383 return 0 on success, -1 on error */ 384 385 int 386 _bfd_vms_slurp_eom (abfd, objtype) 387 bfd *abfd; 388 int objtype; 389 { 390 unsigned char *vms_rec; 391 392 #if VMS_DEBUG 393 vms_debug(2, "EOM/EEOM\n"); 394 #endif 395 396 vms_rec = PRIV(vms_rec); 397 398 if ((objtype == OBJ_S_C_EOM) 399 || (objtype == OBJ_S_C_EOMW)) 400 { 401 } 402 else 403 { 404 PRIV(eom_data).eom_l_total_lps = bfd_getl32 (vms_rec + 4); 405 PRIV(eom_data).eom_b_comcod = *(vms_rec + 8); 406 if (PRIV(eom_data).eom_b_comcod > 1) 407 { 408 (*_bfd_error_handler) (_("Object module NOT error-free !\n")); 409 bfd_set_error (bfd_error_bad_value); 410 return -1; 411 } 412 PRIV(eom_data).eom_has_transfer = FALSE; 413 if (PRIV(rec_size) > 10) 414 { 415 PRIV(eom_data).eom_has_transfer = TRUE; 416 PRIV(eom_data).eom_b_tfrflg = *(vms_rec + 9); 417 PRIV(eom_data).eom_l_psindx = bfd_getl32 (vms_rec + 12); 418 PRIV(eom_data).eom_l_tfradr = bfd_getl32 (vms_rec + 16); 419 420 abfd->start_address = PRIV(eom_data).eom_l_tfradr; 421 } 422 } 423 return 0; 424 } 425 426 /* Write eom record for bfd abfd */ 427 428 int 429 _bfd_vms_write_eom (abfd, objtype) 430 bfd *abfd; 431 int objtype; 432 { 433 #if VMS_DEBUG 434 vms_debug (2, "vms_write_eom (%p, %d)\n", abfd, objtype); 435 #endif 436 437 _bfd_vms_output_begin (abfd, objtype, -1); 438 _bfd_vms_output_long (abfd, (unsigned long) (PRIV(vms_linkage_index) >> 1)); 439 _bfd_vms_output_byte (abfd, 0); /* completion code */ 440 _bfd_vms_output_byte (abfd, 0); /* fill byte */ 441 442 if (bfd_get_start_address (abfd) != (bfd_vma)-1) 443 { 444 asection *section; 445 446 section = bfd_get_section_by_name (abfd, ".link"); 447 if (section == 0) 448 { 449 bfd_set_error (bfd_error_nonrepresentable_section); 450 return -1; 451 } 452 _bfd_vms_output_short (abfd, 0); 453 _bfd_vms_output_long (abfd, (unsigned long) (section->index)); 454 _bfd_vms_output_long (abfd, 455 (unsigned long) bfd_get_start_address (abfd)); 456 _bfd_vms_output_long (abfd, 0); 457 } 458 459 _bfd_vms_output_end (abfd); 460 return 0; 461 } 462