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