2009-06-12 Tristan Gingold <gingold@adacore.com>
[binutils.git] / bfd / vms-hdr.c
blob8c10df6222fb1344878b2049fd0dffe4cad657ee
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, 2008, 2009 Free Software Foundation, Inc.
6 HDR record handling functions
7 EMH record handling functions
9 EOM record handling functions
10 EEOM record handling functions
12 IHD record handling functions
13 EIHD record handling functions
15 ISD record handling functions
16 EISD record handling functions
18 IHS record handling functions
19 EIHS record handling functions
21 DBG record handling functions
22 EDBG record handling functions
24 TBT record handling functions
25 ETBT record handling functions
27 DST/DMT section handling functions
29 Written by Klaus K"ampf (kkaempf@rmi.de)
31 This program is free software; you can redistribute it and/or modify
32 it under the terms of the GNU General Public License as published by
33 the Free Software Foundation; either version 3 of the License, or
34 (at your option) any later version.
36 This program is distributed in the hope that it will be useful,
37 but WITHOUT ANY WARRANTY; without even the implied warranty of
38 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 GNU General Public License for more details.
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
44 MA 02110-1301, USA. */
46 #include "sysdep.h"
47 #include "bfd.h"
48 #include "bfdver.h"
49 #include "bfdlink.h"
50 #include "safe-ctype.h"
51 #include "libbfd.h"
53 #include "vms.h"
55 static struct module *new_module (bfd *);
56 static void parse_module
57 (bfd *, struct module *, unsigned char *, unsigned int);
58 static struct module *build_module_list (bfd *);
59 static bfd_boolean module_find_nearest_line
60 (bfd *, struct module *, bfd_vma, const char **, const char **,
61 unsigned int *);
62 static int vms_slurp_debug (bfd *);
64 #define SET_MODULE_PARSED(m) \
65 do { if ((m)->name == NULL) (m)->name = ""; } while (0)
66 #define IS_MODULE_PARSED(m) ((m)->name != NULL)
69 /* Read & process emh record
70 return 0 on success, -1 on error. */
72 int
73 _bfd_vms_slurp_hdr (bfd *abfd, int objtype)
75 unsigned char *ptr;
76 unsigned char *vms_rec;
77 int subtype;
79 vms_rec = PRIV(vms_rec);
81 #if VMS_DEBUG
82 vms_debug(2, "HDR/EMH\n");
83 #endif
85 switch (objtype)
87 case OBJ_S_C_HDR:
88 subtype = vms_rec[1];
89 break;
90 case EOBJ_S_C_EMH:
91 subtype = bfd_getl16 (vms_rec + 4) + EVAX_OFFSET;
92 break;
93 default:
94 subtype = -1;
97 #if VMS_DEBUG
98 vms_debug(3, "subtype %d\n", subtype);
99 #endif
101 switch (subtype)
103 case MHD_S_C_MHD:
104 /* Module header. */
105 PRIV (hdr_data).hdr_b_strlvl = vms_rec[2];
106 PRIV (hdr_data).hdr_l_recsiz = bfd_getl16 (vms_rec + 3);
107 PRIV (hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 5);
108 ptr = vms_rec + 5 + vms_rec[5] + 1;
109 PRIV (hdr_data).hdr_t_version = _bfd_vms_save_counted_string (ptr);
110 ptr += *ptr + 1;
111 PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17);
112 break;
114 case MHD_S_C_LNM:
115 PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2));
116 break;
118 case MHD_S_C_SRC:
119 PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2));
120 break;
122 case MHD_S_C_TTL:
123 PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 2));
124 break;
126 case EMH_S_C_MHD + EVAX_OFFSET:
127 /* Module header. */
128 PRIV (hdr_data).hdr_b_strlvl = vms_rec[6];
129 PRIV (hdr_data).hdr_l_arch1 = bfd_getl32 (vms_rec + 8);
130 PRIV (hdr_data).hdr_l_arch2 = bfd_getl32 (vms_rec + 12);
131 PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16);
132 PRIV (hdr_data).hdr_t_name = _bfd_vms_save_counted_string (vms_rec + 20);
133 ptr = vms_rec + 20 + vms_rec[20] + 1;
134 PRIV (hdr_data).hdr_t_version =_bfd_vms_save_counted_string (ptr);
135 ptr += *ptr + 1;
136 PRIV (hdr_data).hdr_t_date = _bfd_vms_save_sized_string (ptr, 17);
137 break;
139 case EMH_S_C_LNM + EVAX_OFFSET:
140 PRIV (hdr_data).hdr_c_lnm = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6));
141 break;
143 case EMH_S_C_SRC + EVAX_OFFSET:
144 PRIV (hdr_data).hdr_c_src = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6));
145 break;
147 case EMH_S_C_TTL + EVAX_OFFSET:
148 PRIV (hdr_data).hdr_c_ttl = _bfd_vms_save_sized_string (vms_rec, PRIV (rec_size - 6));
149 break;
151 case MHD_S_C_CPR:
152 case MHD_S_C_MTC:
153 case MHD_S_C_GTX:
154 case EMH_S_C_CPR + EVAX_OFFSET:
155 case EMH_S_C_MTC + EVAX_OFFSET:
156 case EMH_S_C_GTX + EVAX_OFFSET:
157 break;
159 default:
160 bfd_set_error (bfd_error_wrong_format);
161 return -1;
164 return 0;
167 /* Output routines. */
169 /* Manufacture a VMS like time on a unix based system.
170 stolen from obj-vms.c. */
172 static unsigned char *
173 get_vms_time_string (void)
175 static unsigned char tbuf[18];
176 #ifndef VMS
177 #include <time.h>
179 char *pnt;
180 time_t timeb;
182 time (& timeb);
183 pnt = ctime (&timeb);
184 pnt[3] = 0;
185 pnt[7] = 0;
186 pnt[10] = 0;
187 pnt[16] = 0;
188 pnt[24] = 0;
189 sprintf ((char *) tbuf, "%2s-%3s-%s %s",
190 pnt + 8, pnt + 4, pnt + 20, pnt + 11);
191 #else
192 #include <starlet.h>
193 struct
195 int Size;
196 unsigned char *Ptr;
197 } Descriptor;
198 Descriptor.Size = 17;
199 Descriptor.Ptr = tbuf;
200 SYS$ASCTIM (0, &Descriptor, 0, 0);
201 #endif /* not VMS */
203 #if VMS_DEBUG
204 vms_debug (6, "vmstimestring:'%s'\n", tbuf);
205 #endif
207 return tbuf;
210 /* Write object header for bfd abfd. */
213 _bfd_vms_write_hdr (bfd *abfd, int objtype)
215 asymbol *symbol;
216 unsigned int symnum;
217 int had_case = 0;
218 int had_file = 0;
219 char version [256];
221 #if VMS_DEBUG
222 vms_debug (2, "vms_write_hdr (%p)\n", abfd);
223 #endif
225 _bfd_vms_output_alignment (abfd, 2);
227 /* MHD. */
228 if (objtype != OBJ_S_C_HDR)
230 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_MHD);
231 _bfd_vms_output_short (abfd, EOBJ_S_C_STRLVL);
232 _bfd_vms_output_long (abfd, 0);
233 _bfd_vms_output_long (abfd, 0);
234 _bfd_vms_output_long (abfd, MAX_OUTREC_SIZE);
237 if (bfd_get_filename (abfd) != 0)
239 /* Strip path and suffix information. */
240 char *fname, *fout, *fptr;
242 fptr = bfd_get_filename (abfd);
243 fname = strdup (fptr);
245 /* Strip VMS path. */
246 fout = strrchr (fname, ']');
247 if (fout == NULL)
248 fout = strchr (fname, ':');
249 if (fout != NULL)
250 fout++;
251 else
252 fout = fname;
254 /* Strip UNIX path. */
255 fptr = strrchr (fout, '/');
256 if (fptr != NULL)
257 fout = fptr + 1;
259 /* Strip .obj suffix. */
260 fptr = strrchr (fout, '.');
261 if (fptr != 0 && strcasecmp (fptr, ".OBJ") == 0)
262 *fptr = 0;
264 /* Convert to upper case and truncate at 31 characters.
265 (VMS object file format restricts module name length to 31). */
266 fptr = fout;
267 while (*fptr != 0)
269 *fptr = TOUPPER (*fptr);
270 fptr++;
271 if (*fptr == ';' || (fptr - fout) >= 31)
272 *fptr = 0;
274 _bfd_vms_output_counted (abfd, fout);
275 free (fname);
277 else
278 _bfd_vms_output_counted (abfd, "NONAME");
280 _bfd_vms_output_counted (abfd, BFD_VERSION_STRING);
281 _bfd_vms_output_dump (abfd, get_vms_time_string (), EMH_DATE_LENGTH);
282 _bfd_vms_output_fill (abfd, 0, EMH_DATE_LENGTH);
283 _bfd_vms_output_flush (abfd);
285 /* LMN. */
286 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_LNM);
287 snprintf (version, sizeof (version), "GAS BFD v%s", BFD_VERSION_STRING);
288 _bfd_vms_output_dump (abfd, (unsigned char *)version, strlen (version));
289 _bfd_vms_output_flush (abfd);
291 /* SRC. */
292 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_SRC);
294 for (symnum = 0; symnum < abfd->symcount; symnum++)
296 symbol = abfd->outsymbols[symnum];
298 if (symbol->flags & BSF_FILE)
300 if (CONST_STRNEQ ((char *)symbol->name, "<CASE:"))
302 PRIV (flag_hash_long_names) = symbol->name[6] - '0';
303 PRIV (flag_show_after_trunc) = symbol->name[7] - '0';
305 if (had_file)
306 break;
307 had_case = 1;
308 continue;
311 _bfd_vms_output_dump (abfd, (unsigned char *) symbol->name,
312 (int) strlen (symbol->name));
313 if (had_case)
314 break;
315 had_file = 1;
319 if (symnum == abfd->symcount)
320 _bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("noname"));
322 _bfd_vms_output_flush (abfd);
324 /* TTL. */
325 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_TTL);
326 _bfd_vms_output_dump (abfd, (unsigned char *) STRING_COMMA_LEN ("TTL"));
327 _bfd_vms_output_flush (abfd);
329 /* CPR. */
330 _bfd_vms_output_begin (abfd, EOBJ_S_C_EMH, EMH_S_C_CPR);
331 _bfd_vms_output_dump (abfd,
332 (unsigned char *)"GNU BFD ported by Klaus Kämpf 1994-1996",
333 39);
334 _bfd_vms_output_flush (abfd);
336 return 0;
339 /* Process EOM/EEOM record
340 return 0 on success, -1 on error. */
343 _bfd_vms_slurp_eom (bfd *abfd, int objtype)
345 unsigned char *vms_rec;
347 #if VMS_DEBUG
348 vms_debug(2, "EOM/EEOM\n");
349 #endif
351 vms_rec = PRIV (vms_rec);
353 if ((objtype == OBJ_S_C_EOM)
354 || (objtype == OBJ_S_C_EOMW))
357 else
359 PRIV (eom_data).eom_l_total_lps
360 = bfd_getl32 (vms_rec + EEOM_S_L_TOTAL_LPS);
361 PRIV (eom_data).eom_w_comcod = bfd_getl16 (vms_rec + EEOM_S_W_COMCOD);
362 if (PRIV (eom_data).eom_w_comcod > 1)
364 (*_bfd_error_handler) (_("Object module NOT error-free !\n"));
365 bfd_set_error (bfd_error_bad_value);
366 return -1;
368 PRIV (eom_data).eom_has_transfer = FALSE;
369 if (PRIV (rec_size) > 10)
371 PRIV (eom_data).eom_has_transfer = TRUE;
372 PRIV (eom_data).eom_b_tfrflg = vms_rec[EEOM_S_B_TFRFLG];
373 PRIV (eom_data).eom_l_psindx
374 = bfd_getl32 (vms_rec + EEOM_S_L_PSINDX);
375 PRIV (eom_data).eom_l_tfradr
376 = bfd_getl32 (vms_rec + EEOM_S_L_TFRADR);
378 abfd->start_address = PRIV (eom_data).eom_l_tfradr;
381 return 0;
384 /* Write eom record for bfd abfd. */
387 _bfd_vms_write_eom (bfd *abfd, int objtype)
389 #if VMS_DEBUG
390 vms_debug (2, "vms_write_eom (%p, %d)\n", abfd, objtype);
391 #endif
393 _bfd_vms_output_begin (abfd, objtype, -1);
394 _bfd_vms_output_long (abfd, (unsigned long) (PRIV (vms_linkage_index) >> 1));
395 _bfd_vms_output_byte (abfd, 0); /* Completion code. */
396 _bfd_vms_output_byte (abfd, 0); /* Fill byte. */
398 if (bfd_get_start_address (abfd) != (bfd_vma)-1)
400 asection *section;
402 section = bfd_get_section_by_name (abfd, ".link");
403 if (section == 0)
405 bfd_set_error (bfd_error_nonrepresentable_section);
406 return -1;
408 _bfd_vms_output_short (abfd, 0);
409 _bfd_vms_output_long (abfd, (unsigned long) (section->index));
410 _bfd_vms_output_long (abfd,
411 (unsigned long) bfd_get_start_address (abfd));
412 _bfd_vms_output_long (abfd, 0);
415 _bfd_vms_output_end (abfd);
416 return 0;
419 /* Read & process IHD/EIHD record.
420 Return 0 on success, -1 on error */
422 _bfd_vms_slurp_ihd (bfd *abfd, unsigned int *isd_offset,
423 unsigned int *ihs_offset)
425 unsigned int imgtype, size;
426 bfd_vma symvva;
428 #if VMS_DEBUG
429 vms_debug (8, "_bfd_vms_slurp_ihd\n");
430 #endif
432 size = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_SIZE);
433 imgtype = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_IMGTYPE);
435 if (imgtype == EIHD_S_K_EXE)
436 abfd->flags |= EXEC_P;
438 symvva = bfd_getl64 (PRIV (vms_rec) + EIHD_S_Q_SYMVVA);
439 if (symvva != 0)
441 PRIV (symvva) = symvva;
442 abfd->flags |= DYNAMIC;
445 *isd_offset = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_ISDOFF);
446 *ihs_offset = bfd_getl32 (PRIV (vms_rec) + EIHD_S_L_SYMDBGOFF);
448 #if VMS_DEBUG
449 vms_debug (4, "EIHD record size %d imgtype %d symvva 0x%llx isd %d ihs %d\n",
450 size, imgtype, symvva, *isd_offset, *ihs_offset);
451 #endif
453 return 0;
456 /* Read & process ISD/EISD record
457 return 0 on success, -1 on error */
460 _bfd_vms_slurp_isd (bfd *abfd, unsigned int offset)
462 int section_count = 0;
463 unsigned char *p;
464 unsigned int rec_size;
466 #if VMS_DEBUG
467 vms_debug (8, "_bfd_vms_slurp_isd\n");
468 #endif
470 for (p = PRIV (vms_rec) + offset;
471 (rec_size = bfd_getl32 (p + EISD_S_L_EISDSIZE)) != 0;
472 p += rec_size)
474 unsigned long long vaddr = bfd_getl64 (p + EISD_S_Q_VIR_ADDR);
475 unsigned int size = bfd_getl32 (p + EISD_S_L_SECSIZE);
476 unsigned int flags = bfd_getl32 (p + EISD_S_L_FLAGS);
477 unsigned int vbn = bfd_getl32 (p + EISD_S_L_VBN);
478 char *name = NULL;
479 asection *section;
480 flagword bfd_flags;
482 #if VMS_DEBUG
483 vms_debug (4, "EISD record at 0x%x size 0x%x addr 0x%x bfd_flags 0x%x block %d\n",
484 p - PRIV (vms_rec), size, vaddr, flags, vbn);
485 #endif
487 /* VMS combines psects from .obj files into isects in the .exe. This
488 process doesn't preserve enough information to reliably determine
489 what's in each section without examining the data. This is
490 especially true of DWARF debug sections. */
491 bfd_flags = SEC_ALLOC;
493 if (flags & EISD_S_M_EXE)
494 bfd_flags |= SEC_CODE | SEC_HAS_CONTENTS | SEC_LOAD;
496 if (flags & EISD_S_M_NONSHRADR)
497 bfd_flags |= SEC_DATA | SEC_HAS_CONTENTS | SEC_LOAD;
499 if (!(flags & EISD_S_M_WRT))
500 bfd_flags |= SEC_READONLY;
502 if (flags & EISD_S_M_DZRO)
503 bfd_flags |= SEC_DATA;
505 if (flags & EISD_S_M_FIXUPVEC)
506 bfd_flags |= SEC_DATA | SEC_HAS_CONTENTS | SEC_LOAD;
508 if (flags & EISD_S_M_CRF)
509 bfd_flags |= SEC_HAS_CONTENTS | SEC_LOAD;
511 if (flags & EISD_S_M_GBL)
513 name = _bfd_vms_save_counted_string (p + EISD_S_T_GBLNAM);
514 bfd_flags |= SEC_COFF_SHARED_LIBRARY;
515 bfd_flags &= ~(SEC_ALLOC | SEC_LOAD);
517 else
519 name = (char*) bfd_alloc (abfd, 32);
520 sprintf (name, "$LOCAL_%03d$", section_count++);
523 section = bfd_make_section (abfd, name);
525 if (!section)
526 return -1;
528 section->filepos = vbn ? VMS_BLOCK_SIZE * (vbn - 1) : (unsigned int)-1;
529 section->size = size;
530 section->vma = vaddr;
532 if (!bfd_set_section_flags (abfd, section, bfd_flags))
533 return -1;
536 return 0;
539 /* Read & process IHS/EIHS record
540 return 0 on success, -1 on error */
542 _bfd_vms_slurp_ihs (bfd *abfd, unsigned int offset)
544 unsigned char *p = PRIV (vms_rec) + offset;
545 unsigned int gstvbn = bfd_getl32 (p + EIHS_S_L_GSTVBN);
546 unsigned int gstsize ATTRIBUTE_UNUSED = bfd_getl32 (p + EIHS_S_L_GSTSIZE);
547 unsigned int dstvbn = bfd_getl32 (p + EIHS_S_L_DSTVBN);
548 unsigned int dstsize = bfd_getl32 (p + EIHS_S_L_DSTSIZE);
549 unsigned int dmtvbn = bfd_getl32 (p + EIHS_S_L_DMTVBN);
550 unsigned int dmtbytes = bfd_getl32 (p + EIHS_S_L_DMTBYTES);
551 asection *section;
553 #if VMS_DEBUG
554 vms_debug (8, "_bfd_vms_slurp_ihs\n");
555 vms_debug (4, "EIHS record gstvbn %d gstsize %d dstvbn %d dstsize %d dmtvbn %d dmtbytes %d\n",
556 gstvbn, gstsize, dstvbn, dstsize, dmtvbn, dmtbytes);
557 #endif
559 if (dstvbn)
561 flagword bfd_flags = SEC_HAS_CONTENTS | SEC_DEBUGGING;
563 section = bfd_make_section (abfd, "$DST$");
564 if (!section)
565 return -1;
567 section->size = dstsize;
568 section->filepos = VMS_BLOCK_SIZE * (dstvbn - 1);
570 if (!bfd_set_section_flags (abfd, section, bfd_flags))
571 return -1;
573 PRIV (dst_section) = section;
574 abfd->flags |= (HAS_DEBUG | HAS_LINENO);
577 if (dmtvbn)
579 flagword bfd_flags = SEC_HAS_CONTENTS | SEC_DEBUGGING;
581 section = bfd_make_section (abfd, "$DMT$");
582 if (!section)
583 return -1;
585 section->size = dmtbytes;
586 section->filepos = VMS_BLOCK_SIZE * (dmtvbn - 1);
588 if (!bfd_set_section_flags (abfd, section, bfd_flags))
589 return -1;
592 if (gstvbn)
594 flagword bfd_flags = SEC_HAS_CONTENTS;
596 section = bfd_make_section (abfd, "$GST$");
597 if (!section)
598 return -1;
600 if (bfd_seek (abfd, VMS_BLOCK_SIZE * (gstvbn - 1), SEEK_SET))
602 bfd_set_error (bfd_error_file_truncated);
603 return -1;
606 if (_bfd_vms_slurp_object_records (abfd) != 0)
607 return -1;
609 section->filepos = VMS_BLOCK_SIZE * (gstvbn - 1);
610 section->size = bfd_tell (abfd) - section->filepos;
612 if (!bfd_set_section_flags (abfd, section, bfd_flags))
613 return -1;
615 abfd->flags |= HAS_SYMS;
618 return 0;
621 /* Build a new module for the specified BFD. */
623 static struct module *
624 new_module (bfd *abfd)
626 struct module *module
627 = (struct module *) bfd_zalloc (abfd, sizeof (struct module));
628 module->file_table_count = 16; /* Arbitrary. */
629 module->file_table
630 = bfd_malloc (module->file_table_count * sizeof (struct fileinfo));
631 return module;
634 /* Parse debug info for a module and internalize it. */
636 static void
637 parse_module (bfd *abfd, struct module *module, unsigned char *ptr,
638 unsigned int length)
640 unsigned char *maxptr = ptr + length, *src_ptr, *pcl_ptr;
641 unsigned int prev_linum = 0, curr_linenum = 0;
642 bfd_vma prev_pc = 0, curr_pc = 0;
643 struct srecinfo *curr_srec, *srec;
644 struct lineinfo *curr_line, *line;
645 struct funcinfo *funcinfo;
647 /* Initialize tables with zero element. */
648 curr_srec = (struct srecinfo *) bfd_zalloc (abfd, sizeof (struct srecinfo));
649 module->srec_table = curr_srec;
651 curr_line = (struct lineinfo *) bfd_zalloc (abfd, sizeof (struct lineinfo));
652 module->line_table = curr_line;
654 while (ptr < maxptr)
656 /* The first byte is not counted in the recorded length. */
657 int rec_length = bfd_getl16 (ptr) + 1;
658 int rec_type = bfd_getl16 (ptr + 2);
660 #if VMS_DEBUG
661 _bfd_vms_debug (2, "DST record: length %d, type %d\n",
662 rec_length, rec_type);
663 #endif
665 switch (rec_type)
667 case DST_S_C_MODBEG:
668 module->name
669 = _bfd_vms_save_counted_string (ptr + DST_S_B_MODBEG_NAME);
671 curr_pc = 0;
672 prev_pc = 0;
673 curr_linenum = 0;
674 prev_linum = 0;
676 #if VMS_DEBUG
677 _bfd_vms_debug (3, "module: %s\n", module->name);
678 #endif
679 break;
681 case DST_S_C_MODEND:
682 #if VMS_DEBUG
683 _bfd_vms_debug (3, "end module\n");
684 #endif
685 break;
687 case DST_S_C_RTNBEG:
688 funcinfo = (struct funcinfo *)
689 bfd_zalloc (abfd, sizeof (struct funcinfo));
690 funcinfo->name
691 = _bfd_vms_save_counted_string (ptr + DST_S_B_RTNBEG_NAME);
692 funcinfo->low = bfd_getl32 (ptr + DST_S_L_RTNBEG_ADDRESS);
693 funcinfo->next = module->func_table;
694 module->func_table = funcinfo;
696 #if VMS_DEBUG
697 _bfd_vms_debug (3, "routine: %s at 0x%x\n",
698 funcinfo->name, funcinfo->low);
699 #endif
700 break;
702 case DST_S_C_RTNEND:
703 module->func_table->high = module->func_table->low
704 + bfd_getl32 (ptr + DST_S_L_RTNEND_SIZE) - 1;
706 if (module->func_table->high > module->high)
707 module->high = module->func_table->high;
709 #if VMS_DEBUG
710 _bfd_vms_debug (3, "end routine\n");
711 #endif
712 break;
714 case DST_S_C_PROLOG:
715 #if VMS_DEBUG
716 _bfd_vms_debug (3, "prologue\n");
717 #endif
718 break;
720 case DST_S_C_EPILOG:
721 #if VMS_DEBUG
722 _bfd_vms_debug (3, "epilog\n");
723 #endif
724 break;
726 case DST_S_C_BLKBEG:
727 #if VMS_DEBUG
728 _bfd_vms_debug (3, "block\n");
729 #endif
730 break;
732 case DST_S_C_BLKEND:
733 #if VMS_DEBUG
734 _bfd_vms_debug (3, "end block\n");
735 #endif
736 break;
738 case DST_S_C_SOURCE:
739 src_ptr = ptr + DST_S_C_SOURCE_HEADER_SIZE;
741 #if VMS_DEBUG
742 _bfd_vms_debug (3, "source info\n");
743 #endif
745 while (src_ptr < ptr + rec_length)
747 int cmd = src_ptr[0], cmd_length, data;
749 switch (cmd)
751 case DST_S_C_SRC_DECLFILE:
753 unsigned int fileid
754 = bfd_getl16 (src_ptr + DST_S_W_SRC_DF_FILEID);
755 char *filename
756 = _bfd_vms_save_counted_string (src_ptr
757 + DST_S_B_SRC_DF_FILENAME);
759 while (fileid >= module->file_table_count)
761 module->file_table_count *= 2;
762 module->file_table
763 = bfd_realloc (module->file_table,
764 module->file_table_count
765 * sizeof (struct fileinfo));
768 module->file_table [fileid].name = filename;
769 module->file_table [fileid].srec = 1;
770 cmd_length = src_ptr[DST_S_B_SRC_DF_LENGTH] + 2;
771 #if VMS_DEBUG
772 _bfd_vms_debug (4, "DST_S_C_SRC_DECLFILE: %d, %s\n",
773 fileid,
774 module->file_table [fileid].name);
775 #endif
777 break;
779 case DST_S_C_SRC_DEFLINES_B:
780 /* Perform the association and set the next higher index
781 to the limit. */
782 data = src_ptr[DST_S_B_SRC_UNSBYTE];
783 srec = (struct srecinfo *)
784 bfd_zalloc (abfd, sizeof (struct srecinfo));
785 srec->line = curr_srec->line + data;
786 srec->srec = curr_srec->srec + data;
787 srec->sfile = curr_srec->sfile;
788 curr_srec->next = srec;
789 curr_srec = srec;
790 cmd_length = 2;
791 #if VMS_DEBUG
792 _bfd_vms_debug (4, "DST_S_C_SRC_DEFLINES_B: %d\n", data);
793 #endif
794 break;
796 case DST_S_C_SRC_DEFLINES_W:
797 /* Perform the association and set the next higher index
798 to the limit. */
799 data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD);
800 srec = (struct srecinfo *)
801 bfd_zalloc (abfd, sizeof (struct srecinfo));
802 srec->line = curr_srec->line + data;
803 srec->srec = curr_srec->srec + data,
804 srec->sfile = curr_srec->sfile;
805 curr_srec->next = srec;
806 curr_srec = srec;
807 cmd_length = 3;
808 #if VMS_DEBUG
809 _bfd_vms_debug (4, "DST_S_C_SRC_DEFLINES_W: %d\n", data);
810 #endif
811 break;
813 case DST_S_C_SRC_INCRLNUM_B:
814 data = src_ptr[DST_S_B_SRC_UNSBYTE];
815 curr_srec->line += data;
816 cmd_length = 2;
817 #if VMS_DEBUG
818 _bfd_vms_debug (4, "DST_S_C_SRC_INCRLNUM_B: %d\n", data);
819 #endif
820 break;
822 case DST_S_C_SRC_SETFILE:
823 data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD);
824 curr_srec->sfile = data;
825 curr_srec->srec = module->file_table[data].srec;
826 cmd_length = 3;
827 #if VMS_DEBUG
828 _bfd_vms_debug (4, "DST_S_C_SRC_SETFILE: %d\n", data);
829 #endif
830 break;
832 case DST_S_C_SRC_SETLNUM_L:
833 data = bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG);
834 curr_srec->line = data;
835 cmd_length = 5;
836 #if VMS_DEBUG
837 _bfd_vms_debug (4, "DST_S_C_SRC_SETLNUM_L: %d\n", data);
838 #endif
839 break;
841 case DST_S_C_SRC_SETLNUM_W:
842 data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD);
843 curr_srec->line = data;
844 cmd_length = 3;
845 #if VMS_DEBUG
846 _bfd_vms_debug (4, "DST_S_C_SRC_SETLNUM_W: %d\n", data);
847 #endif
848 break;
850 case DST_S_C_SRC_SETREC_L:
851 data = bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG);
852 curr_srec->srec = data;
853 module->file_table[curr_srec->sfile].srec = data;
854 cmd_length = 5;
855 #if VMS_DEBUG
856 _bfd_vms_debug (4, "DST_S_C_SRC_SETREC_L: %d\n", data);
857 #endif
858 break;
860 case DST_S_C_SRC_SETREC_W:
861 data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD);
862 curr_srec->srec = data;
863 module->file_table[curr_srec->sfile].srec = data;
864 cmd_length = 3;
865 #if VMS_DEBUG
866 _bfd_vms_debug (4, "DST_S_C_SRC_SETREC_W: %d\n", data);
867 #endif
868 break;
870 case DST_S_C_SRC_FORMFEED:
871 cmd_length = 1;
872 #if VMS_DEBUG
873 _bfd_vms_debug (4, "DST_S_C_SRC_FORMFEED\n");
874 #endif
875 break;
877 default:
878 (*_bfd_error_handler) (_("unknown source command %d"),
879 cmd);
880 cmd_length = 2;
881 break;
884 src_ptr += cmd_length;
886 break;
888 case DST_S_C_LINE_NUM:
889 pcl_ptr = ptr + DST_S_C_LINE_NUM_HEADER_SIZE;
891 #if VMS_DEBUG
892 _bfd_vms_debug (3, "line info\n");
893 #endif
895 while (pcl_ptr < ptr + rec_length)
897 /* The command byte is signed so we must sign-extend it. */
898 int cmd = ((signed char *)pcl_ptr)[0], cmd_length, data;
900 switch (cmd)
902 case DST_S_C_DELTA_PC_W:
903 data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
904 curr_pc += data;
905 curr_linenum += 1;
906 cmd_length = 3;
907 #if VMS_DEBUG
908 _bfd_vms_debug (4, "DST_S_C_DELTA_PC_W: %d\n", data);
909 #endif
910 break;
912 case DST_S_C_DELTA_PC_L:
913 data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
914 curr_pc += data;
915 curr_linenum += 1;
916 cmd_length = 5;
917 #if VMS_DEBUG
918 _bfd_vms_debug (4, "DST_S_C_DELTA_PC_L: %d\n", data);
919 #endif
920 break;
922 case DST_S_C_INCR_LINUM:
923 data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE];
924 curr_linenum += data;
925 cmd_length = 2;
926 #if VMS_DEBUG
927 _bfd_vms_debug (4, "DST_S_C_INCR_LINUM: %d\n", data);
928 #endif
929 break;
931 case DST_S_C_INCR_LINUM_W:
932 data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
933 curr_linenum += data;
934 cmd_length = 3;
935 #if VMS_DEBUG
936 _bfd_vms_debug (4, "DST_S_C_INCR_LINUM_W: %d\n", data);
937 #endif
938 break;
940 case DST_S_C_INCR_LINUM_L:
941 data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
942 curr_linenum += data;
943 cmd_length = 5;
944 #if VMS_DEBUG
945 _bfd_vms_debug (4, "DST_S_C_INCR_LINUM_L: %d\n", data);
946 #endif
947 break;
949 case DST_S_C_SET_LINUM_INCR:
950 (*_bfd_error_handler)
951 (_("DST_S_C_SET_LINUM_INCR not implemented"));
952 cmd_length = 2;
953 break;
955 case DST_S_C_SET_LINUM_INCR_W:
956 (*_bfd_error_handler)
957 (_("DST_S_C_SET_LINUM_INCR_W not implemented"));
958 cmd_length = 3;
959 break;
961 case DST_S_C_RESET_LINUM_INCR:
962 (*_bfd_error_handler)
963 (_("DST_S_C_RESET_LINUM_INCR not implemented"));
964 cmd_length = 1;
965 break;
967 case DST_S_C_BEG_STMT_MODE:
968 (*_bfd_error_handler)
969 (_("DST_S_C_BEG_STMT_MODE not implemented"));
970 cmd_length = 1;
971 break;
973 case DST_S_C_END_STMT_MODE:
974 (*_bfd_error_handler)
975 (_("DST_S_C_END_STMT_MODE not implemented"));
976 cmd_length = 1;
977 break;
979 case DST_S_C_SET_LINUM_B:
980 data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE];
981 curr_linenum = data;
982 cmd_length = 2;
983 #if VMS_DEBUG
984 _bfd_vms_debug (4, "DST_S_C_SET_LINUM_B: %d\n", data);
985 #endif
986 break;
988 case DST_S_C_SET_LINE_NUM:
989 data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
990 curr_linenum = data;
991 cmd_length = 3;
992 #if VMS_DEBUG
993 _bfd_vms_debug (4, "DST_S_C_SET_LINE_NUM: %d\n", data);
994 #endif
995 break;
997 case DST_S_C_SET_LINUM_L:
998 data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
999 curr_linenum = data;
1000 cmd_length = 5;
1001 #if VMS_DEBUG
1002 _bfd_vms_debug (4, "DST_S_C_SET_LINUM_L: %d\n", data);
1003 #endif
1004 break;
1006 case DST_S_C_SET_PC:
1007 (*_bfd_error_handler)
1008 (_("DST_S_C_SET_PC not implemented"));
1009 cmd_length = 2;
1010 break;
1012 case DST_S_C_SET_PC_W:
1013 (*_bfd_error_handler)
1014 (_("DST_S_C_SET_PC_W not implemented"));
1015 cmd_length = 3;
1016 break;
1018 case DST_S_C_SET_PC_L:
1019 (*_bfd_error_handler)
1020 (_("DST_S_C_SET_PC_L not implemented"));
1021 cmd_length = 5;
1022 break;
1024 case DST_S_C_SET_STMTNUM:
1025 (*_bfd_error_handler)
1026 (_("DST_S_C_SET_STMTNUM not implemented"));
1027 cmd_length = 2;
1028 break;
1030 case DST_S_C_TERM:
1031 data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE];
1032 curr_pc += data;
1033 cmd_length = 2;
1034 #if VMS_DEBUG
1035 _bfd_vms_debug (4, "DST_S_C_TERM: %d\n", data);
1036 #endif
1037 break;
1039 case DST_S_C_TERM_W:
1040 data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
1041 curr_pc += data;
1042 cmd_length = 3;
1043 #if VMS_DEBUG
1044 _bfd_vms_debug (4, "DST_S_C_TERM_W: %d\n", data);
1045 #endif
1046 break;
1048 case DST_S_C_TERM_L:
1049 data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
1050 curr_pc += data;
1051 cmd_length = 5;
1052 #if VMS_DEBUG
1053 _bfd_vms_debug (4, "DST_S_C_TERM_L: %d\n", data);
1054 #endif
1055 break;
1057 case DST_S_C_SET_ABS_PC:
1058 data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
1059 curr_pc = data;
1060 cmd_length = 5;
1061 #if VMS_DEBUG
1062 _bfd_vms_debug (4, "DST_S_C_SET_ABS_PC: 0x%x\n", data);
1063 #endif
1064 break;
1066 default:
1067 if (cmd <= 0)
1069 curr_pc -= cmd;
1070 curr_linenum += 1;
1071 cmd_length = 1;
1072 #if VMS_DEBUG
1073 _bfd_vms_debug (4, "bump pc to 0x%llx and line to %d\n",
1074 curr_pc, curr_linenum);
1075 #endif
1077 else
1079 (*_bfd_error_handler) (_("unknown line command %d"),
1080 cmd);
1081 cmd_length = 2;
1083 break;
1086 if ((curr_linenum != prev_linum && curr_pc != prev_pc)
1087 || cmd <= 0
1088 || cmd == DST_S_C_DELTA_PC_L
1089 || cmd == DST_S_C_DELTA_PC_W)
1091 line = (struct lineinfo *)
1092 bfd_zalloc (abfd, sizeof (struct lineinfo));
1093 line->address = curr_pc;
1094 line->line = curr_linenum;
1096 curr_line->next = line;
1097 curr_line = line;
1099 prev_linum = curr_linenum;
1100 prev_pc = curr_pc;
1101 #if VMS_DEBUG
1102 _bfd_vms_debug (4, "-> correlate pc 0x%llx with line %d\n",
1103 curr_pc, curr_linenum);
1104 #endif
1107 pcl_ptr += cmd_length;
1109 break;
1111 case 0x17: /* Undocumented type used by DEC C to declare equates. */
1112 #if VMS_DEBUG
1113 _bfd_vms_debug (3, "undocumented type 0x17\n");
1114 #endif
1115 break;
1117 default:
1118 #if VMS_DEBUG
1119 _bfd_vms_debug (3, "ignoring record\n");
1120 #endif
1121 break;
1125 ptr += rec_length;
1128 /* Finalize tables with EOL marker. */
1129 srec = (struct srecinfo *) bfd_zalloc (abfd, sizeof (struct srecinfo));
1130 srec->line = (unsigned int) -1;
1131 srec->srec = (unsigned int) -1;
1132 curr_srec->next = srec;
1134 line = (struct lineinfo *) bfd_zalloc (abfd, sizeof (struct lineinfo));
1135 line->line = (unsigned int) -1;
1136 line->address = (bfd_vma) -1;
1137 curr_line->next = line;
1139 /* Advertise that this module has been parsed. This is needed
1140 because parsing can be either performed at module creation
1141 or deferred until debug info is consumed. */
1142 SET_MODULE_PARSED (module);
1145 /* Build the list of modules for the specified BFD. */
1147 static struct module *
1148 build_module_list (bfd *abfd)
1150 struct module *module, *list = NULL;
1151 asection *dmt;
1153 if ((dmt = bfd_get_section_by_name (abfd, "$DMT$")))
1155 /* We have a DMT section so this must be an image. Parse the
1156 section and build the list of modules. This is sufficient
1157 since we can compute the start address and the end address
1158 of every module from the section contents. */
1159 bfd_size_type size = bfd_get_section_size (dmt);
1160 unsigned char *ptr, *end;
1162 ptr = (unsigned char *) bfd_alloc (abfd, size);
1163 if (! ptr)
1164 return NULL;
1166 if (! bfd_get_section_contents (abfd, dmt, ptr, 0, size))
1167 return NULL;
1169 #if VMS_DEBUG
1170 _bfd_vms_debug (2, "DMT\n");
1171 #endif
1173 end = ptr + size;
1175 while (ptr < end)
1177 /* Each header declares a module with its start offset and size
1178 of debug info in the DST section, as well as the count of
1179 program sections (i.e. address spans) it contains. */
1180 int modbeg = bfd_getl32 (ptr + DBG_S_L_DMT_MODBEG);
1181 int size = bfd_getl32 (ptr + DBG_S_L_DST_SIZE);
1182 int count = bfd_getl16 (ptr + DBG_S_W_DMT_PSECT_COUNT);
1183 ptr += DBG_S_C_DMT_HEADER_SIZE;
1185 #if VMS_DEBUG
1186 _bfd_vms_debug (3, "module: modbeg = %d, size = %d, count = %d\n",
1187 modbeg, size, count);
1188 #endif
1190 /* We create a 'module' structure for each program section since
1191 we only support contiguous addresses in a 'module' structure.
1192 As a consequence, the actual debug info in the DST section is
1193 shared and can be parsed multiple times; that doesn't seem to
1194 cause problems in practice. */
1195 while (count-- > 0)
1197 int start = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_START);
1198 int length = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_LENGTH);
1199 module = new_module (abfd);
1200 module->modbeg = modbeg;
1201 module->size = size;
1202 module->low = start;
1203 module->high = start + length;
1204 module->next = list;
1205 list = module;
1206 ptr += DBG_S_C_DMT_PSECT_SIZE;
1208 #if VMS_DEBUG
1209 _bfd_vms_debug (4, "section: start = 0x%x, length = %d\n",
1210 start, length);
1211 #endif
1215 else
1217 /* We don't have a DMT section so this must be an object. Parse
1218 the module right now in order to compute its start address and
1219 end address. */
1220 module = new_module (abfd);
1221 parse_module (abfd, module, PRIV (dst_section)->contents,
1222 PRIV (dst_ptr_end) - PRIV (dst_section)->contents);
1223 list = module;
1226 return list;
1229 /* Calculate and return the name of the source file and the line nearest
1230 to the wanted location in the specified module. */
1232 static bfd_boolean
1233 module_find_nearest_line (bfd *abfd, struct module *module, bfd_vma addr,
1234 const char **file, const char **func,
1235 unsigned int *line)
1237 struct funcinfo *funcinfo;
1238 struct lineinfo *lineinfo;
1239 struct srecinfo *srecinfo;
1240 bfd_boolean ret = FALSE;
1242 /* Parse this module if that was not done at module creation. */
1243 if (! IS_MODULE_PARSED (module))
1245 unsigned int size = module->size;
1246 unsigned int modbeg = PRIV (dst_section)->filepos + module->modbeg;
1247 unsigned char *buffer = (unsigned char *) bfd_malloc (module->size);
1249 if (bfd_seek (abfd, modbeg, SEEK_SET) != 0
1250 || bfd_bread (buffer, size, abfd) != size)
1252 bfd_set_error (bfd_error_no_debug_section);
1253 return FALSE;
1256 parse_module (abfd, module, buffer, size);
1257 free (buffer);
1260 /* Find out the function (if any) that contains the address. */
1261 for (funcinfo = module->func_table; funcinfo; funcinfo = funcinfo->next)
1262 if (addr >= funcinfo->low && addr <= funcinfo->high)
1264 *func = funcinfo->name;
1265 ret = TRUE;
1266 break;
1269 /* Find out the source file and the line nearest to the address. */
1270 for (lineinfo = module->line_table; lineinfo; lineinfo = lineinfo->next)
1271 if (lineinfo->next && addr < lineinfo->next->address)
1273 for (srecinfo = module->srec_table; srecinfo; srecinfo = srecinfo->next)
1274 if (srecinfo->next && lineinfo->line < srecinfo->next->line)
1276 if (srecinfo->sfile > 0)
1278 *file = module->file_table[srecinfo->sfile].name;
1279 *line = srecinfo->srec + lineinfo->line - srecinfo->line;
1281 else
1283 *file = module->name;
1284 *line = lineinfo->line;
1286 return TRUE;
1289 break;
1292 return ret;
1295 /* Provided a BFD, a section and an offset into the section, calculate and
1296 return the name of the source file and the line nearest to the wanted
1297 location. */
1299 bfd_boolean
1300 _bfd_vms_find_nearest_dst_line (bfd *abfd, asection *section,
1301 asymbol **symbols ATTRIBUTE_UNUSED,
1302 bfd_vma offset, const char **file,
1303 const char **func, unsigned int *line)
1305 struct module *module;
1307 /* What address are we looking for? */
1308 bfd_vma addr = section->vma + offset;
1310 *file = NULL;
1311 *func = NULL;
1312 *line = 0;
1314 if (PRIV (dst_section) == NULL)
1315 return FALSE;
1317 if (PRIV (modules) == NULL)
1319 PRIV (modules) = build_module_list (abfd);
1320 if (PRIV (modules) == NULL)
1321 return FALSE;
1324 for (module = PRIV (modules); module; module = module->next)
1325 if (addr >= module->low && addr <= module->high)
1326 return module_find_nearest_line (abfd, module, addr, file, func, line);
1328 return FALSE;
1331 /* Process EDBG/ETBT record.
1332 Return 0 on success, -1 on error */
1334 static int
1335 vms_slurp_debug (bfd *abfd)
1337 if (PRIV (dst_section) == NULL)
1339 /* We have no way to find out beforehand how much debug info there
1340 is in an object file, so pick an initial amount and grow it as
1341 needed later. */
1342 flagword flags = SEC_HAS_CONTENTS | SEC_DEBUGGING | SEC_RELOC;
1343 asection *section = bfd_make_section (abfd, "$DST$");
1344 if (!section)
1345 return -1;
1346 section->size = 1024;
1347 if (!bfd_set_section_flags (abfd, section, flags))
1348 return -1;
1349 section->contents = ((unsigned char *)
1350 bfd_zmalloc (section->size));
1351 if (section->contents == NULL)
1352 return -1;
1353 section->filepos = (unsigned int)-1;
1354 PRIV (dst_section) = section;
1357 PRIV (image_section) = PRIV (dst_section);
1358 PRIV (image_ptr) = PRIV (dst_section)->contents;
1360 return _bfd_vms_slurp_tir (abfd, EOBJ_S_C_ETIR);
1363 /* Process DBG/EDBG record.
1364 Return 0 on success, -1 on error. */
1367 _bfd_vms_slurp_dbg (bfd *abfd, int objtype ATTRIBUTE_UNUSED)
1369 #if VMS_DEBUG
1370 _bfd_vms_debug (2, "DBG/EDBG\n");
1371 #endif
1373 abfd->flags |= (HAS_DEBUG | HAS_LINENO);
1375 return vms_slurp_debug (abfd);
1378 /* Process TBT/ETBT record.
1379 Return 0 on success, -1 on error. */
1382 _bfd_vms_slurp_tbt (bfd *abfd, int objtype ATTRIBUTE_UNUSED)
1384 #if VMS_DEBUG
1385 _bfd_vms_debug (2, "TBT/ETBT\n");
1386 #endif
1388 abfd->flags |= HAS_LINENO;
1390 return vms_slurp_debug (abfd);
1393 /* Write DBG/EDBG record. */
1396 _bfd_vms_write_dbg (bfd *abfd ATTRIBUTE_UNUSED, int objtype ATTRIBUTE_UNUSED)
1398 #if VMS_DEBUG
1399 _bfd_vms_debug (2, "vms_write_dbg (%p, objtype)\n", abfd, objtype);
1400 #endif
1402 return 0;
1405 /* Write TBT/ETBT record. */
1408 _bfd_vms_write_tbt (bfd *abfd ATTRIBUTE_UNUSED, int objtype ATTRIBUTE_UNUSED)
1410 #if VMS_DEBUG
1411 _bfd_vms_debug (2, "vms_write_tbt (%p, %d)\n", abfd, objtype);
1412 #endif
1414 return 0;