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