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, 2003, 2005 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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 /* Read & process emh record 42 return 0 on success, -1 on error. */ 43 44 int 45 _bfd_vms_slurp_hdr (bfd *abfd, 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 case MHD_S_C_MHD: 76 /* Module header. */ 77 PRIV (hdr_data).hdr_b_strlvl = vms_rec[2]; 78 PRIV (hdr_data).hdr_l_recsiz = bfd_getl16 (vms_rec + 3); 79 PRIV (hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 5); 80 ptr = vms_rec + 5 + vms_rec[5] + 1; 81 PRIV (hdr_data).hdr_t_version = _bfd_vms_save_counted_string (ptr); 82 ptr += *ptr + 1; 83 PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17); 84 break; 85 86 case MHD_S_C_LNM: 87 PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2)); 88 break; 89 90 case MHD_S_C_SRC: 91 PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2)); 92 break; 93 94 case MHD_S_C_TTL: 95 PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 2)); 96 break; 97 98 case EMH_S_C_MHD + EVAX_OFFSET: 99 /* Module header. */ 100 PRIV (hdr_data).hdr_b_strlvl = vms_rec[6]; 101 PRIV (hdr_data).hdr_l_arch1 = bfd_getl32 (vms_rec + 8); 102 PRIV (hdr_data).hdr_l_arch2 = bfd_getl32 (vms_rec + 12); 103 PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16); 104 PRIV (hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 20); 105 ptr = vms_rec + 20 + vms_rec[20] + 1; 106 PRIV (hdr_data).hdr_t_version =_bfd_vms_save_counted_string (ptr); 107 ptr += *ptr + 1; 108 PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17); 109 break; 110 111 case EMH_S_C_LNM + EVAX_OFFSET: 112 PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6)); 113 break; 114 115 case EMH_S_C_SRC + EVAX_OFFSET: 116 PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6)); 117 break; 118 119 case EMH_S_C_TTL + EVAX_OFFSET: 120 PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_length - 6)); 121 break; 122 123 case MHD_S_C_CPR: 124 case MHD_S_C_MTC: 125 case MHD_S_C_GTX: 126 case EMH_S_C_CPR + EVAX_OFFSET: 127 case EMH_S_C_MTC + EVAX_OFFSET: 128 case EMH_S_C_GTX + EVAX_OFFSET: 129 break; 130 131 default: 132 bfd_set_error (bfd_error_wrong_format); 133 return -1; 134 } 135 136 return 0; 137 } 138 139 /* Output routines. */ 140 141 /* Manufacture a VMS like time on a unix based system. 142 stolen from obj-vms.c. */ 143 144 static unsigned char * 145 get_vms_time_string (void) 146 { 147 static unsigned char tbuf[18]; 148 #ifndef VMS 149 #include <time.h> 150 151 char *pnt; 152 time_t timeb; 153 154 time (& timeb); 155 pnt = ctime (&timeb); 156 pnt[3] = 0; 157 pnt[7] = 0; 158 pnt[10] = 0; 159 pnt[16] = 0; 160 pnt[24] = 0; 161 sprintf ((char *) tbuf, "%2s-%3s-%s %s", 162 pnt + 8, pnt + 4, pnt + 20, pnt + 11); 163 #else 164 #include <starlet.h> 165 struct 166 { 167 int Size; 168 unsigned char *Ptr; 169 } Descriptor; 170 Descriptor.Size = 17; 171 Descriptor.Ptr = tbuf; 172 SYS$ASCTIM (0, &Descriptor, 0, 0); 173 #endif /* not VMS */ 174 175 #if VMS_DEBUG 176 vms_debug (6, "vmstimestring:'%s'\n", tbuf); 177 #endif 178 179 return tbuf; 180 } 181 182 /* Write object header for bfd abfd. */ 183 184 int 185 _bfd_vms_write_hdr (bfd *abfd, int objtype) 186 { 187 asymbol *symbol; 188 unsigned int symnum; 189 int had_case = 0; 190 int had_file = 0; 191 192 #if VMS_DEBUG 193 vms_debug (2, "vms_write_hdr (%p)\n", abfd); 194 #endif 195 196 _bfd_vms_output_alignment (abfd, 2); 197 198 /* MHD. */ 199 if (objtype != OBJ_S_C_HDR) 200 { 201 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_MHD); 202 _bfd_vms_output_short (abfd, EOBJ_S_C_STRLVL); 203 _bfd_vms_output_long (abfd, 0); 204 _bfd_vms_output_long (abfd, 0); 205 _bfd_vms_output_long (abfd, MAX_OUTREC_SIZE); 206 } 207 208 if (bfd_get_filename (abfd) != 0) 209 { 210 /* Strip path and suffix information. */ 211 char *fname, *fout, *fptr; 212 213 fptr = bfd_get_filename (abfd); 214 fname = alloca (strlen (fptr) + 1); 215 strcpy (fname, fptr); 216 fout = strrchr (fname, ']'); 217 if (fout == 0) 218 fout = strchr (fname, ':'); 219 if (fout != 0) 220 fout++; 221 else 222 fout = fname; 223 224 /* Strip .obj suffix. */ 225 fptr = strrchr (fname, '.'); 226 if ((fptr != 0) 227 && (strcasecmp (fptr, ".OBJ") == 0)) 228 *fptr = 0; 229 230 fptr = fout; 231 while (*fptr != 0) 232 { 233 *fptr = TOUPPER (*fptr); 234 fptr++; 235 if ((*fptr == ';') 236 || ((fptr - fout) > 31)) 237 *fptr = 0; 238 } 239 _bfd_vms_output_counted (abfd, fout); 240 } 241 else 242 _bfd_vms_output_counted (abfd, "NONAME"); 243 244 _bfd_vms_output_counted (abfd, BFD_VERSION_STRING); 245 _bfd_vms_output_dump (abfd, get_vms_time_string (), 17); 246 _bfd_vms_output_fill (abfd, 0, 17); 247 _bfd_vms_output_flush (abfd); 248 249 /* LMN. */ 250 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_LNM); 251 _bfd_vms_output_dump (abfd, (unsigned char *)"GAS proGIS", 10); 252 _bfd_vms_output_flush (abfd); 253 254 /* SRC. */ 255 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_SRC); 256 257 for (symnum = 0; symnum < abfd->symcount; symnum++) 258 { 259 symbol = abfd->outsymbols[symnum]; 260 261 if (symbol->flags & BSF_FILE) 262 { 263 if (strncmp ((char *)symbol->name, "<CASE:", 6) == 0) 264 { 265 PRIV (flag_hash_long_names) = symbol->name[6] - '0'; 266 PRIV (flag_show_after_trunc) = symbol->name[7] - '0'; 267 268 if (had_file) 269 break; 270 had_case = 1; 271 continue; 272 } 273 274 _bfd_vms_output_dump (abfd, (unsigned char *) symbol->name, 275 (int) strlen (symbol->name)); 276 if (had_case) 277 break; 278 had_file = 1; 279 } 280 } 281 282 if (symnum == abfd->symcount) 283 _bfd_vms_output_dump (abfd, (unsigned char *)"noname", 6); 284 285 _bfd_vms_output_flush (abfd); 286 287 /* TTL. */ 288 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_TTL); 289 _bfd_vms_output_dump (abfd, (unsigned char *)"TTL", 3); 290 _bfd_vms_output_flush (abfd); 291 292 /* CPR. */ 293 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_CPR); 294 _bfd_vms_output_dump (abfd, 295 (unsigned char *)"GNU BFD ported by Klaus K�mpf 1994-1996", 296 39); 297 _bfd_vms_output_flush (abfd); 298 299 return 0; 300 } 301 302 /* Process EOM/EEOM record 303 return 0 on success, -1 on error. */ 304 305 int 306 _bfd_vms_slurp_eom (bfd *abfd, int objtype) 307 { 308 unsigned char *vms_rec; 309 310 #if VMS_DEBUG 311 vms_debug(2, "EOM/EEOM\n"); 312 #endif 313 314 vms_rec = PRIV (vms_rec); 315 316 if ((objtype == OBJ_S_C_EOM) 317 || (objtype == OBJ_S_C_EOMW)) 318 { 319 } 320 else 321 { 322 PRIV (eom_data).eom_l_total_lps = bfd_getl32 (vms_rec + 4); 323 PRIV (eom_data).eom_b_comcod = *(vms_rec + 8); 324 325 if (PRIV (eom_data).eom_b_comcod > 1) 326 { 327 (*_bfd_error_handler) (_("Object module NOT error-free !\n")); 328 bfd_set_error (bfd_error_bad_value); 329 return -1; 330 } 331 PRIV (eom_data).eom_has_transfer = FALSE; 332 if (PRIV (rec_size) > 10) 333 { 334 PRIV (eom_data).eom_has_transfer = TRUE; 335 PRIV (eom_data).eom_b_tfrflg = *(vms_rec + 9); 336 PRIV (eom_data).eom_l_psindx = bfd_getl32 (vms_rec + 12); 337 PRIV (eom_data).eom_l_tfradr = bfd_getl32 (vms_rec + 16); 338 339 abfd->start_address = PRIV (eom_data).eom_l_tfradr; 340 } 341 } 342 return 0; 343 } 344 345 /* Write eom record for bfd abfd. */ 346 347 int 348 _bfd_vms_write_eom (bfd *abfd, int objtype) 349 { 350 #if VMS_DEBUG 351 vms_debug (2, "vms_write_eom (%p, %d)\n", abfd, objtype); 352 #endif 353 354 _bfd_vms_output_begin (abfd, objtype, -1); 355 _bfd_vms_output_long (abfd, (unsigned long) (PRIV (vms_linkage_index) >> 1)); 356 _bfd_vms_output_byte (abfd, 0); /* Completion code. */ 357 _bfd_vms_output_byte (abfd, 0); /* Fill byte. */ 358 359 if (bfd_get_start_address (abfd) != (bfd_vma)-1) 360 { 361 asection *section; 362 363 section = bfd_get_section_by_name (abfd, ".link"); 364 if (section == 0) 365 { 366 bfd_set_error (bfd_error_nonrepresentable_section); 367 return -1; 368 } 369 _bfd_vms_output_short (abfd, 0); 370 _bfd_vms_output_long (abfd, (unsigned long) (section->index)); 371 _bfd_vms_output_long (abfd, 372 (unsigned long) bfd_get_start_address (abfd)); 373 _bfd_vms_output_long (abfd, 0); 374 } 375 376 _bfd_vms_output_end (abfd); 377 return 0; 378 } 379