1/* Output VMS debug format symbol table information from GCC. 2 Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 4 Contributed by Douglas B. Rupp (rupp@gnat.com). 5 Updated by Bernard W. Giroud (bgiroud@users.sourceforge.net). 6 7This file is part of GCC. 8 9GCC is free software; you can redistribute it and/or modify it under 10the terms of the GNU General Public License as published by the Free 11Software Foundation; either version 2, or (at your option) any later 12version. 13 14GCC is distributed in the hope that it will be useful, but WITHOUT ANY 15WARRANTY; without even the implied warranty of MERCHANTABILITY or 16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17for more details. 18 19You should have received a copy of the GNU General Public License 20along with GCC; see the file COPYING. If not, write to the Free 21Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 2202110-1301, USA. */ 23 24#include "config.h" 25#include "system.h" 26#include "coretypes.h" 27#include "tm.h" 28 29#ifdef VMS_DEBUGGING_INFO 30#include "tree.h" 31#include "version.h" 32#include "flags.h" 33#include "rtl.h" 34#include "output.h" 35#include "vmsdbg.h" 36#include "debug.h" 37#include "langhooks.h" 38#include "function.h" 39#include "target.h" 40 41/* Difference in seconds between the VMS Epoch and the Unix Epoch */ 42static const long long vms_epoch_offset = 3506716800ll; 43 44/* NOTE: In the comments in this file, many references are made to "Debug 45 Symbol Table". This term is abbreviated as `DST' throughout the remainder 46 of this file. */ 47 48typedef struct dst_line_info_struct *dst_line_info_ref; 49 50/* Each entry in the line_info_table maintains the file and 51 line number associated with the label generated for that 52 entry. The label gives the PC value associated with 53 the line number entry. */ 54typedef struct dst_line_info_struct 55{ 56 unsigned long dst_file_num; 57 unsigned long dst_line_num; 58} 59dst_line_info_entry; 60 61typedef struct dst_file_info_struct *dst_file_info_ref; 62 63typedef struct dst_file_info_struct 64{ 65 char *file_name; 66 unsigned int max_line; 67 unsigned int listing_line_start; 68 long long cdt; 69 long ebk; 70 short ffb; 71 char rfo; 72 char flen; 73} 74dst_file_info_entry; 75 76/* How to start an assembler comment. */ 77#ifndef ASM_COMMENT_START 78#define ASM_COMMENT_START ";#" 79#endif 80 81/* Maximum size (in bytes) of an artificially generated label. */ 82#define MAX_ARTIFICIAL_LABEL_BYTES 30 83 84/* Make sure we know the sizes of the various types debug can describe. These 85 are only defaults. If the sizes are different for your target, you should 86 override these values by defining the appropriate symbols in your tm.h 87 file. */ 88#ifndef PTR_SIZE 89#define PTR_SIZE 4 /* Must be 32 bits for VMS debug info */ 90#endif 91 92/* Pointer to a structure of filenames referenced by this compilation unit. */ 93static dst_file_info_ref file_info_table; 94 95/* Total number of entries in the table (i.e. array) pointed to by 96 `file_info_table'. This is the *total* and includes both used and unused 97 slots. */ 98static unsigned int file_info_table_allocated; 99 100/* Number of entries in the file_info_table which are actually in use. */ 101static unsigned int file_info_table_in_use; 102 103/* Size (in elements) of increments by which we may expand the filename 104 table. */ 105#define FILE_TABLE_INCREMENT 64 106 107/* A structure to hold basic information for the VMS end 108 routine. */ 109 110typedef struct vms_func_struct 111{ 112 const char *vms_func_name; 113 unsigned funcdef_number; 114} 115vms_func_node; 116 117typedef struct vms_func_struct *vms_func_ref; 118 119static unsigned int func_table_allocated; 120static unsigned int func_table_in_use; 121#define FUNC_TABLE_INCREMENT 256 122 123/* A pointer to the base of a table that contains frame description 124 information for each routine. */ 125static vms_func_ref func_table; 126 127/* Local pointer to the name of the main input file. Initialized in 128 avmdbgout_init. */ 129static const char *primary_filename; 130 131static char *module_producer; 132static unsigned int module_language; 133 134/* A pointer to the base of a table that contains line information 135 for each source code line in .text in the compilation unit. */ 136static dst_line_info_ref line_info_table; 137 138/* Number of elements currently allocated for line_info_table. */ 139static unsigned int line_info_table_allocated; 140 141/* Number of elements in line_info_table currently in use. */ 142static unsigned int line_info_table_in_use; 143 144/* Size (in elements) of increments by which we may expand line_info_table. */ 145#define LINE_INFO_TABLE_INCREMENT 1024 146 147/* Forward declarations for functions defined in this file. */ 148static char *full_name (const char *); 149static unsigned int lookup_filename (const char *); 150static void addr_const_to_string (char *, rtx); 151static int write_debug_header (DST_HEADER *, const char *, int); 152static int write_debug_addr (char *, const char *, int); 153static int write_debug_data1 (unsigned int, const char *, int); 154static int write_debug_data2 (unsigned int, const char *, int); 155static int write_debug_data4 (unsigned long, const char *, int); 156static int write_debug_data8 (unsigned long long, const char *, int); 157static int write_debug_delta4 (char *, char *, const char *, int); 158static int write_debug_string (char *, const char *, int); 159static int write_modbeg (int); 160static int write_modend (int); 161static int write_rtnbeg (int, int); 162static int write_rtnend (int, int); 163static int write_pclines (int); 164static int write_srccorr (int, dst_file_info_entry, int); 165static int write_srccorrs (int); 166 167static void vmsdbgout_init (const char *); 168static void vmsdbgout_finish (const char *); 169static void vmsdbgout_define (unsigned int, const char *); 170static void vmsdbgout_undef (unsigned int, const char *); 171static void vmsdbgout_start_source_file (unsigned int, const char *); 172static void vmsdbgout_end_source_file (unsigned int); 173static void vmsdbgout_begin_block (unsigned int, unsigned int); 174static void vmsdbgout_end_block (unsigned int, unsigned int); 175static bool vmsdbgout_ignore_block (tree); 176static void vmsdbgout_source_line (unsigned int, const char *); 177static void vmsdbgout_begin_prologue (unsigned int, const char *); 178static void vmsdbgout_end_prologue (unsigned int, const char *); 179static void vmsdbgout_end_function (unsigned int); 180static void vmsdbgout_end_epilogue (unsigned int, const char *); 181static void vmsdbgout_begin_function (tree); 182static void vmsdbgout_decl (tree); 183static void vmsdbgout_global_decl (tree); 184static void vmsdbgout_abstract_function (tree); 185 186/* The debug hooks structure. */ 187 188const struct gcc_debug_hooks vmsdbg_debug_hooks 189= {vmsdbgout_init, 190 vmsdbgout_finish, 191 vmsdbgout_define, 192 vmsdbgout_undef, 193 vmsdbgout_start_source_file, 194 vmsdbgout_end_source_file, 195 vmsdbgout_begin_block, 196 vmsdbgout_end_block, 197 vmsdbgout_ignore_block, 198 vmsdbgout_source_line, 199 vmsdbgout_begin_prologue, 200 vmsdbgout_end_prologue, 201 vmsdbgout_end_epilogue, 202 vmsdbgout_begin_function, 203 vmsdbgout_end_function, 204 vmsdbgout_decl, 205 vmsdbgout_global_decl, 206 debug_nothing_tree_int, /* type_decl */ 207 debug_nothing_tree_tree, /* imported_module_or_decl */ 208 debug_nothing_tree, /* deferred_inline_function */ 209 vmsdbgout_abstract_function, 210 debug_nothing_rtx, /* label */ 211 debug_nothing_int, /* handle_pch */ 212 debug_nothing_rtx, /* var_location */ 213 debug_nothing_void, /* switch_text_section */ 214 0 /* start_end_main_source_file */ 215}; 216 217/* Definitions of defaults for assembler-dependent names of various 218 pseudo-ops and section names. 219 Theses may be overridden in the tm.h file (if necessary) for a particular 220 assembler. */ 221#ifdef UNALIGNED_SHORT_ASM_OP 222#undef UNALIGNED_SHORT_ASM_OP 223#endif 224#define UNALIGNED_SHORT_ASM_OP ".word" 225 226#ifdef UNALIGNED_INT_ASM_OP 227#undef UNALIGNED_INT_ASM_OP 228#endif 229#define UNALIGNED_INT_ASM_OP ".long" 230 231#ifdef UNALIGNED_LONG_ASM_OP 232#undef UNALIGNED_LONG_ASM_OP 233#endif 234#define UNALIGNED_LONG_ASM_OP ".long" 235 236#ifdef UNALIGNED_DOUBLE_INT_ASM_OP 237#undef UNALIGNED_DOUBLE_INT_ASM_OP 238#endif 239#define UNALIGNED_DOUBLE_INT_ASM_OP ".quad" 240 241#ifdef ASM_BYTE_OP 242#undef ASM_BYTE_OP 243#endif 244#define ASM_BYTE_OP ".byte" 245 246#define NUMBYTES(I) ((I) < 256 ? 1 : (I) < 65536 ? 2 : 4) 247 248#define NUMBYTES0(I) ((I) < 128 ? 0 : (I) < 65536 ? 2 : 4) 249 250#ifndef UNALIGNED_PTR_ASM_OP 251#define UNALIGNED_PTR_ASM_OP \ 252 (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP) 253#endif 254 255#ifndef UNALIGNED_OFFSET_ASM_OP 256#define UNALIGNED_OFFSET_ASM_OP(OFFSET) \ 257 (NUMBYTES(OFFSET) == 4 \ 258 ? UNALIGNED_LONG_ASM_OP \ 259 : (NUMBYTES(OFFSET) == 2 ? UNALIGNED_SHORT_ASM_OP : ASM_BYTE_OP)) 260#endif 261 262/* Definitions of defaults for formats and names of various special 263 (artificial) labels which may be generated within this file (when the -g 264 options is used and VMS_DEBUGGING_INFO is in effect. If necessary, these 265 may be overridden from within the tm.h file, but typically, overriding these 266 defaults is unnecessary. */ 267 268static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; 269 270#ifndef TEXT_END_LABEL 271#define TEXT_END_LABEL "Lvetext" 272#endif 273#ifndef FUNC_BEGIN_LABEL 274#define FUNC_BEGIN_LABEL "LVFB" 275#endif 276#ifndef FUNC_PROLOG_LABEL 277#define FUNC_PROLOG_LABEL "LVFP" 278#endif 279#ifndef FUNC_END_LABEL 280#define FUNC_END_LABEL "LVFE" 281#endif 282#ifndef BLOCK_BEGIN_LABEL 283#define BLOCK_BEGIN_LABEL "LVBB" 284#endif 285#ifndef BLOCK_END_LABEL 286#define BLOCK_END_LABEL "LVBE" 287#endif 288#ifndef LINE_CODE_LABEL 289#define LINE_CODE_LABEL "LVM" 290#endif 291 292#ifndef ASM_OUTPUT_DEBUG_DELTA2 293#define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2) \ 294 do \ 295 { \ 296 fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \ 297 assemble_name (FILE, LABEL1); \ 298 fprintf (FILE, "-"); \ 299 assemble_name (FILE, LABEL2); \ 300 } \ 301 while (0) 302#endif 303 304#ifndef ASM_OUTPUT_DEBUG_DELTA4 305#define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2) \ 306 do \ 307 { \ 308 fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP); \ 309 assemble_name (FILE, LABEL1); \ 310 fprintf (FILE, "-"); \ 311 assemble_name (FILE, LABEL2); \ 312 } \ 313 while (0) 314#endif 315 316#ifndef ASM_OUTPUT_DEBUG_ADDR_DELTA 317#define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2) \ 318 do \ 319 { \ 320 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \ 321 assemble_name (FILE, LABEL1); \ 322 fprintf (FILE, "-"); \ 323 assemble_name (FILE, LABEL2); \ 324 } \ 325 while (0) 326#endif 327 328#ifndef ASM_OUTPUT_DEBUG_ADDR 329#define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL) \ 330 do \ 331 { \ 332 fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP); \ 333 assemble_name (FILE, LABEL); \ 334 } \ 335 while (0) 336#endif 337 338#ifndef ASM_OUTPUT_DEBUG_ADDR_CONST 339#define ASM_OUTPUT_DEBUG_ADDR_CONST(FILE,ADDR) \ 340 fprintf ((FILE), "\t%s\t%s", UNALIGNED_PTR_ASM_OP, (ADDR)) 341#endif 342 343#ifndef ASM_OUTPUT_DEBUG_DATA1 344#define ASM_OUTPUT_DEBUG_DATA1(FILE,VALUE) \ 345 fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned char) VALUE) 346#endif 347 348#ifndef ASM_OUTPUT_DEBUG_DATA2 349#define ASM_OUTPUT_DEBUG_DATA2(FILE,VALUE) \ 350 fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, \ 351 (unsigned short) VALUE) 352#endif 353 354#ifndef ASM_OUTPUT_DEBUG_DATA4 355#define ASM_OUTPUT_DEBUG_DATA4(FILE,VALUE) \ 356 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (unsigned long) VALUE) 357#endif 358 359#ifndef ASM_OUTPUT_DEBUG_DATA 360#define ASM_OUTPUT_DEBUG_DATA(FILE,VALUE) \ 361 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP(VALUE), VALUE) 362#endif 363 364#ifndef ASM_OUTPUT_DEBUG_ADDR_DATA 365#define ASM_OUTPUT_DEBUG_ADDR_DATA(FILE,VALUE) \ 366 fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_PTR_ASM_OP, \ 367 (unsigned long) VALUE) 368#endif 369 370#ifndef ASM_OUTPUT_DEBUG_DATA8 371#define ASM_OUTPUT_DEBUG_DATA8(FILE,VALUE) \ 372 fprintf ((FILE), "\t%s\t0x%llx", UNALIGNED_DOUBLE_INT_ASM_OP, \ 373 (unsigned long long) VALUE) 374#endif 375 376/* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing 377 newline is produced. When flag_verbose_asm is asserted, we add commentary 378 at the end of the line, so we must avoid output of a newline here. */ 379#ifndef ASM_OUTPUT_DEBUG_STRING 380#define ASM_OUTPUT_DEBUG_STRING(FILE,P) \ 381 do \ 382 { \ 383 register int slen = strlen(P); \ 384 register char *p = (P); \ 385 register int i; \ 386 fprintf (FILE, "\t.ascii \""); \ 387 for (i = 0; i < slen; i++) \ 388 { \ 389 register int c = p[i]; \ 390 if (c == '\"' || c == '\\') \ 391 putc ('\\', FILE); \ 392 if (c >= ' ' && c < 0177) \ 393 putc (c, FILE); \ 394 else \ 395 fprintf (FILE, "\\%o", c); \ 396 } \ 397 fprintf (FILE, "\""); \ 398 } \ 399 while (0) 400#endif 401 402/* Convert a reference to the assembler name of a C-level name. This 403 macro has the same effect as ASM_OUTPUT_LABELREF, but copies to 404 a string rather than writing to a file. */ 405#ifndef ASM_NAME_TO_STRING 406#define ASM_NAME_TO_STRING(STR, NAME) \ 407 do \ 408 { \ 409 if ((NAME)[0] == '*') \ 410 strcpy (STR, NAME+1); \ 411 else \ 412 strcpy (STR, NAME); \ 413 } \ 414 while (0) 415#endif 416 417 418/* General utility functions. */ 419 420/* Convert an integer constant expression into assembler syntax. Addition and 421 subtraction are the only arithmetic that may appear in these expressions. 422 This is an adaptation of output_addr_const in final.c. Here, the target 423 of the conversion is a string buffer. We can't use output_addr_const 424 directly, because it writes to a file. */ 425 426static void 427addr_const_to_string (char *str, rtx x) 428{ 429 char buf1[256]; 430 char buf2[256]; 431 432 restart: 433 str[0] = '\0'; 434 switch (GET_CODE (x)) 435 { 436 case PC: 437 gcc_assert (flag_pic); 438 strcat (str, ","); 439 break; 440 441 case SYMBOL_REF: 442 ASM_NAME_TO_STRING (buf1, XSTR (x, 0)); 443 strcat (str, buf1); 444 break; 445 446 case LABEL_REF: 447 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0))); 448 ASM_NAME_TO_STRING (buf2, buf1); 449 strcat (str, buf2); 450 break; 451 452 case CODE_LABEL: 453 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x)); 454 ASM_NAME_TO_STRING (buf2, buf1); 455 strcat (str, buf2); 456 break; 457 458 case CONST_INT: 459 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); 460 strcat (str, buf1); 461 break; 462 463 case CONST: 464 /* This used to output parentheses around the expression, but that does 465 not work on the 386 (either ATT or BSD assembler). */ 466 addr_const_to_string (buf1, XEXP (x, 0)); 467 strcat (str, buf1); 468 break; 469 470 case CONST_DOUBLE: 471 if (GET_MODE (x) == VOIDmode) 472 { 473 /* We can use %d if the number is one word and positive. */ 474 if (CONST_DOUBLE_HIGH (x)) 475 sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX, 476 CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); 477 else if (CONST_DOUBLE_LOW (x) < 0) 478 sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x)); 479 else 480 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, 481 CONST_DOUBLE_LOW (x)); 482 strcat (str, buf1); 483 } 484 else 485 /* We can't handle floating point constants; PRINT_OPERAND must 486 handle them. */ 487 output_operand_lossage ("floating constant misused"); 488 break; 489 490 case PLUS: 491 /* Some assemblers need integer constants to appear last (eg masm). */ 492 if (GET_CODE (XEXP (x, 0)) == CONST_INT) 493 { 494 addr_const_to_string (buf1, XEXP (x, 1)); 495 strcat (str, buf1); 496 if (INTVAL (XEXP (x, 0)) >= 0) 497 strcat (str, "+"); 498 addr_const_to_string (buf1, XEXP (x, 0)); 499 strcat (str, buf1); 500 } 501 else 502 { 503 addr_const_to_string (buf1, XEXP (x, 0)); 504 strcat (str, buf1); 505 if (INTVAL (XEXP (x, 1)) >= 0) 506 strcat (str, "+"); 507 addr_const_to_string (buf1, XEXP (x, 1)); 508 strcat (str, buf1); 509 } 510 break; 511 512 case MINUS: 513 /* Avoid outputting things like x-x or x+5-x, since some assemblers 514 can't handle that. */ 515 x = simplify_subtraction (x); 516 if (GET_CODE (x) != MINUS) 517 goto restart; 518 519 addr_const_to_string (buf1, XEXP (x, 0)); 520 strcat (str, buf1); 521 strcat (str, "-"); 522 if (GET_CODE (XEXP (x, 1)) == CONST_INT 523 && INTVAL (XEXP (x, 1)) < 0) 524 { 525 strcat (str, "("); 526 addr_const_to_string (buf1, XEXP (x, 1)); 527 strcat (str, buf1); 528 strcat (str, ")"); 529 } 530 else 531 { 532 addr_const_to_string (buf1, XEXP (x, 1)); 533 strcat (str, buf1); 534 } 535 break; 536 537 case ZERO_EXTEND: 538 case SIGN_EXTEND: 539 addr_const_to_string (buf1, XEXP (x, 0)); 540 strcat (str, buf1); 541 break; 542 543 default: 544 output_operand_lossage ("invalid expression as operand"); 545 } 546} 547 548/* Output the debug header HEADER. Also output COMMENT if flag_verbose_asm is 549 set. Return the header size. Just return the size if DOSIZEONLY is 550 nonzero. */ 551 552static int 553write_debug_header (DST_HEADER *header, const char *comment, int dosizeonly) 554{ 555 if (!dosizeonly) 556 { 557 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, 558 header->dst__header_length.dst_w_length); 559 560 if (flag_verbose_asm) 561 fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START); 562 fputc ('\n', asm_out_file); 563 564 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, 565 header->dst__header_type.dst_w_type); 566 567 if (flag_verbose_asm) 568 fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START, 569 comment); 570 571 fputc ('\n', asm_out_file); 572 } 573 574 return 4; 575} 576 577/* Output the address of SYMBOL. Also output COMMENT if flag_verbose_asm is 578 set. Return the address size. Just return the size if DOSIZEONLY is 579 nonzero. */ 580 581static int 582write_debug_addr (char *symbol, const char *comment, int dosizeonly) 583{ 584 if (!dosizeonly) 585 { 586 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol); 587 if (flag_verbose_asm) 588 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); 589 fputc ('\n', asm_out_file); 590 } 591 592 return PTR_SIZE; 593} 594 595/* Output the single byte DATA1. Also output COMMENT if flag_verbose_asm is 596 set. Return the data size. Just return the size if DOSIZEONLY is 597 nonzero. */ 598 599static int 600write_debug_data1 (unsigned int data1, const char *comment, int dosizeonly) 601{ 602 if (!dosizeonly) 603 { 604 ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1); 605 if (flag_verbose_asm) 606 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); 607 fputc ('\n', asm_out_file); 608 } 609 610 return 1; 611} 612 613/* Output the single word DATA2. Also output COMMENT if flag_verbose_asm is 614 set. Return the data size. Just return the size if DOSIZEONLY is 615 nonzero. */ 616 617static int 618write_debug_data2 (unsigned int data2, const char *comment, int dosizeonly) 619{ 620 if (!dosizeonly) 621 { 622 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2); 623 if (flag_verbose_asm) 624 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); 625 fputc ('\n', asm_out_file); 626 } 627 628 return 2; 629} 630 631/* Output double word DATA4. Also output COMMENT if flag_verbose_asm is set. 632 Return the data size. Just return the size if DOSIZEONLY is nonzero. */ 633 634static int 635write_debug_data4 (unsigned long data4, const char *comment, int dosizeonly) 636{ 637 if (!dosizeonly) 638 { 639 ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4); 640 if (flag_verbose_asm) 641 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); 642 fputc ('\n', asm_out_file); 643 } 644 645 return 4; 646} 647 648/* Output quad word DATA8. Also output COMMENT if flag_verbose_asm is set. 649 Return the data size. Just return the size if DOSIZEONLY is nonzero. */ 650 651static int 652write_debug_data8 (unsigned long long data8, const char *comment, 653 int dosizeonly) 654{ 655 if (!dosizeonly) 656 { 657 ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8); 658 if (flag_verbose_asm) 659 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); 660 fputc ('\n', asm_out_file); 661 } 662 663 return 8; 664} 665 666/* Output the difference between LABEL1 and LABEL2. Also output COMMENT if 667 flag_verbose_asm is set. Return the data size. Just return the size if 668 DOSIZEONLY is nonzero. */ 669 670static int 671write_debug_delta4 (char *label1, char *label2, const char *comment, 672 int dosizeonly) 673{ 674 if (!dosizeonly) 675 { 676 ASM_OUTPUT_DEBUG_DELTA4 (asm_out_file, label1, label2); 677 if (flag_verbose_asm) 678 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); 679 fputc ('\n', asm_out_file); 680 } 681 682 return 4; 683} 684 685/* Output a character string STRING. Also write COMMENT if flag_verbose_asm is 686 set. Return the string length. Just return the length if DOSIZEONLY is 687 nonzero. */ 688 689static int 690write_debug_string (char *string, const char *comment, int dosizeonly) 691{ 692 if (!dosizeonly) 693 { 694 ASM_OUTPUT_DEBUG_STRING (asm_out_file, string); 695 if (flag_verbose_asm) 696 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); 697 fputc ('\n', asm_out_file); 698 } 699 700 return strlen (string); 701} 702 703/* Output a module begin header and return the header size. Just return the 704 size if DOSIZEONLY is nonzero. */ 705 706static int 707write_modbeg (int dosizeonly) 708{ 709 DST_MODULE_BEGIN modbeg; 710 DST_MB_TRLR mb_trlr; 711 int i; 712 char *module_name, *m; 713 int modnamelen; 714 int prodnamelen; 715 int totsize = 0; 716 717 /* Assumes primary filename has Unix syntax file spec. */ 718 module_name = xstrdup (basename ((char *) primary_filename)); 719 720 m = strrchr (module_name, '.'); 721 if (m) 722 *m = 0; 723 724 modnamelen = strlen (module_name); 725 for (i = 0; i < modnamelen; i++) 726 module_name[i] = TOUPPER (module_name[i]); 727 728 prodnamelen = strlen (module_producer); 729 730 modbeg.dst_a_modbeg_header.dst__header_length.dst_w_length 731 = DST_K_MODBEG_SIZE + modnamelen + DST_K_MB_TRLR_SIZE + prodnamelen - 1; 732 modbeg.dst_a_modbeg_header.dst__header_type.dst_w_type = DST_K_MODBEG; 733 modbeg.dst_b_modbeg_flags.dst_v_modbeg_hide = 0; 734 modbeg.dst_b_modbeg_flags.dst_v_modbeg_version = 1; 735 modbeg.dst_b_modbeg_flags.dst_v_modbeg_unused = 0; 736 modbeg.dst_b_modbeg_unused = 0; 737 modbeg.dst_l_modbeg_language = module_language; 738 modbeg.dst_w_version_major = DST_K_VERSION_MAJOR; 739 modbeg.dst_w_version_minor = DST_K_VERSION_MINOR; 740 modbeg.dst_b_modbeg_name = strlen (module_name); 741 742 mb_trlr.dst_b_compiler = strlen (module_producer); 743 744 totsize += write_debug_header (&modbeg.dst_a_modbeg_header, 745 "modbeg", dosizeonly); 746 totsize += write_debug_data1 (*((char *) &modbeg.dst_b_modbeg_flags), 747 "flags", dosizeonly); 748 totsize += write_debug_data1 (modbeg.dst_b_modbeg_unused, 749 "unused", dosizeonly); 750 totsize += write_debug_data4 (modbeg.dst_l_modbeg_language, 751 "language", dosizeonly); 752 totsize += write_debug_data2 (modbeg.dst_w_version_major, 753 "DST major version", dosizeonly); 754 totsize += write_debug_data2 (modbeg.dst_w_version_minor, 755 "DST minor version", dosizeonly); 756 totsize += write_debug_data1 (modbeg.dst_b_modbeg_name, 757 "length of module name", dosizeonly); 758 totsize += write_debug_string (module_name, "module name", dosizeonly); 759 totsize += write_debug_data1 (mb_trlr.dst_b_compiler, 760 "length of compiler name", dosizeonly); 761 totsize += write_debug_string (module_producer, "compiler name", dosizeonly); 762 763 return totsize; 764} 765 766/* Output a module end trailer and return the trailer size. Just return 767 the size if DOSIZEONLY is nonzero. */ 768 769static int 770write_modend (int dosizeonly) 771{ 772 DST_MODULE_END modend; 773 int totsize = 0; 774 775 modend.dst_a_modend_header.dst__header_length.dst_w_length 776 = DST_K_MODEND_SIZE - 1; 777 modend.dst_a_modend_header.dst__header_type.dst_w_type = DST_K_MODEND; 778 779 totsize += write_debug_header (&modend.dst_a_modend_header, "modend", 780 dosizeonly); 781 782 return totsize; 783} 784 785/* Output a routine begin header routine RTNNUM and return the header size. 786 Just return the size if DOSIZEONLY is nonzero. */ 787 788static int 789write_rtnbeg (int rtnnum, int dosizeonly) 790{ 791 char *rtnname; 792 int rtnnamelen; 793 char *rtnentryname; 794 int totsize = 0; 795 char label[MAX_ARTIFICIAL_LABEL_BYTES]; 796 DST_ROUTINE_BEGIN rtnbeg; 797 DST_PROLOG prolog; 798 vms_func_ref fde = &func_table[rtnnum]; 799 800 rtnname = (char *)fde->vms_func_name; 801 rtnnamelen = strlen (rtnname); 802 rtnentryname = concat (rtnname, "..en", NULL); 803 804 if (!strcmp (rtnname, "main")) 805 { 806 DST_HEADER header; 807 const char *go = "TRANSFER$BREAK$GO"; 808 809 /* This command isn't documented in DSTRECORDS, so it's made to 810 look like what DEC C does */ 811 812 /* header size - 1st byte + flag byte + STO_LW size 813 + string count byte + string length */ 814 header.dst__header_length.dst_w_length 815 = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go); 816 header.dst__header_type.dst_w_type = 0x17; 817 818 totsize += write_debug_header (&header, "transfer", dosizeonly); 819 820 /* I think this is a flag byte, but I don't know what this flag means */ 821 totsize += write_debug_data1 (0x1, "flags ???", dosizeonly); 822 823 /* Routine Begin PD Address */ 824 totsize += write_debug_addr (rtnname, "main procedure descriptor", 825 dosizeonly); 826 totsize += write_debug_data1 (strlen (go), "length of main_name", 827 dosizeonly); 828 totsize += write_debug_string ((char *) go, "main name", dosizeonly); 829 } 830 831 /* The header length never includes the length byte. */ 832 rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length 833 = DST_K_RTNBEG_SIZE + rtnnamelen - 1; 834 rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG; 835 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unused = 0; 836 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unalloc = 0; 837 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_prototype = 0; 838 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_inlined = 0; 839 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_no_call = 1; 840 rtnbeg.dst_b_rtnbeg_name = rtnnamelen; 841 842 totsize += write_debug_header (&rtnbeg.dst_a_rtnbeg_header, "rtnbeg", 843 dosizeonly); 844 totsize += write_debug_data1 (*((char *) &rtnbeg.dst_b_rtnbeg_flags), 845 "flags", dosizeonly); 846 847 /* Routine Begin Address */ 848 totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly); 849 850 /* Routine Begin PD Address */ 851 totsize += write_debug_addr (rtnname, "routine procedure descriptor", 852 dosizeonly); 853 854 /* Routine Begin Name */ 855 totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name, 856 "length of routine name", dosizeonly); 857 858 totsize += write_debug_string (rtnname, "routine name", dosizeonly); 859 860 free (rtnentryname); 861 862 if (debug_info_level > DINFO_LEVEL_TERSE) 863 { 864 prolog.dst_a_prolog_header.dst__header_length.dst_w_length 865 = DST_K_PROLOG_SIZE - 1; 866 prolog.dst_a_prolog_header.dst__header_type.dst_w_type = DST_K_PROLOG; 867 868 totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog", 869 dosizeonly); 870 871 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, fde->funcdef_number); 872 totsize += write_debug_addr (label, "prolog breakpoint addr", 873 dosizeonly); 874 } 875 876 return totsize; 877} 878 879/* Output a routine end trailer for routine RTNNUM and return the header size. 880 Just return the size if DOSIZEONLY is nonzero. */ 881 882static int 883write_rtnend (int rtnnum, int dosizeonly) 884{ 885 DST_ROUTINE_END rtnend; 886 char label1[MAX_ARTIFICIAL_LABEL_BYTES]; 887 char label2[MAX_ARTIFICIAL_LABEL_BYTES]; 888 int totsize; 889 vms_func_ref fde = &func_table[rtnnum]; 890 int corrected_rtnnum = fde->funcdef_number; 891 892 totsize = 0; 893 894 rtnend.dst_a_rtnend_header.dst__header_length.dst_w_length 895 = DST_K_RTNEND_SIZE - 1; 896 rtnend.dst_a_rtnend_header.dst__header_type.dst_w_type = DST_K_RTNEND; 897 rtnend.dst_b_rtnend_unused = 0; 898 rtnend.dst_l_rtnend_size = 0; /* Calculated below. */ 899 900 totsize += write_debug_header (&rtnend.dst_a_rtnend_header, "rtnend", 901 dosizeonly); 902 totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused", 903 dosizeonly); 904 905 ASM_GENERATE_INTERNAL_LABEL (label1, FUNC_BEGIN_LABEL, corrected_rtnnum); 906 ASM_GENERATE_INTERNAL_LABEL (label2, FUNC_END_LABEL, corrected_rtnnum); 907 totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly); 908 909 return totsize; 910} 911 912#define K_DELTA_PC(I) \ 913 ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L) 914 915#define K_SET_LINUM(I) \ 916 ((I) < 256 ? DST_K_SET_LINUM_B \ 917 : (I) < 65536 ? DST_K_SET_LINUM : DST_K_SET_LINUM_L) 918 919#define K_INCR_LINUM(I) \ 920 ((I) < 256 ? DST_K_INCR_LINUM \ 921 : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L) 922 923/* Output the PC to line number correlations and return the size. Just return 924 the size if DOSIZEONLY is nonzero */ 925 926static int 927write_pclines (int dosizeonly) 928{ 929 unsigned i; 930 int fn; 931 int ln, lastln; 932 int linestart = 0; 933 int max_line; 934 DST_LINE_NUM_HEADER line_num; 935 DST_PCLINE_COMMANDS pcline; 936 char label[MAX_ARTIFICIAL_LABEL_BYTES]; 937 char lastlabel[MAX_ARTIFICIAL_LABEL_BYTES]; 938 int totsize = 0; 939 char buff[256]; 940 941 max_line = file_info_table[1].max_line; 942 file_info_table[1].listing_line_start = linestart; 943 linestart = linestart + ((max_line / 100000) + 1) * 100000; 944 945 for (i = 2; i < file_info_table_in_use; i++) 946 { 947 max_line = file_info_table[i].max_line; 948 file_info_table[i].listing_line_start = linestart; 949 linestart = linestart + ((max_line / 10000) + 1) * 10000; 950 } 951 952 /* Set starting address to beginning of text section. */ 953 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8; 954 line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM; 955 pcline.dst_b_pcline_command = DST_K_SET_ABS_PC; 956 957 totsize += write_debug_header (&line_num.dst_a_line_num_header, 958 "line_num", dosizeonly); 959 totsize += write_debug_data1 (pcline.dst_b_pcline_command, 960 "line_num (SET ABS PC)", dosizeonly); 961 962 if (dosizeonly) 963 totsize += 4; 964 else 965 { 966 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, TEXT_SECTION_ASM_OP); 967 if (flag_verbose_asm) 968 fprintf (asm_out_file, "\t%s line_num", ASM_COMMENT_START); 969 fputc ('\n', asm_out_file); 970 } 971 972 fn = line_info_table[1].dst_file_num; 973 ln = (file_info_table[fn].listing_line_start 974 + line_info_table[1].dst_line_num); 975 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 4 + 4; 976 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L; 977 978 totsize += write_debug_header (&line_num.dst_a_line_num_header, 979 "line_num", dosizeonly); 980 totsize += write_debug_data1 (pcline.dst_b_pcline_command, 981 "line_num (SET LINUM LONG)", dosizeonly); 982 983 sprintf (buff, "line_num (%d)", ln ? ln - 1 : 0); 984 totsize += write_debug_data4 (ln ? ln - 1 : 0, buff, dosizeonly); 985 986 lastln = ln; 987 strcpy (lastlabel, TEXT_SECTION_ASM_OP); 988 for (i = 1; i < line_info_table_in_use; i++) 989 { 990 int extrabytes; 991 992 fn = line_info_table[i].dst_file_num; 993 ln = (file_info_table[fn].listing_line_start 994 + line_info_table[i].dst_line_num); 995 996 if (ln - lastln > 1) 997 extrabytes = 5; /* NUMBYTES (ln - lastln - 1) + 1; */ 998 else if (ln <= lastln) 999 extrabytes = 5; /* NUMBYTES (ln - 1) + 1; */ 1000 else 1001 extrabytes = 0; 1002 1003 line_num.dst_a_line_num_header.dst__header_length.dst_w_length 1004 = 8 + extrabytes; 1005 1006 totsize += write_debug_header 1007 (&line_num.dst_a_line_num_header, "line_num", dosizeonly); 1008 1009 if (ln - lastln > 1) 1010 { 1011 int lndif = ln - lastln - 1; 1012 1013 /* K_INCR_LINUM (lndif); */ 1014 pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L; 1015 1016 totsize += write_debug_data1 (pcline.dst_b_pcline_command, 1017 "line_num (INCR LINUM LONG)", 1018 dosizeonly); 1019 1020 sprintf (buff, "line_num (%d)", lndif); 1021 totsize += write_debug_data4 (lndif, buff, dosizeonly); 1022 } 1023 else if (ln <= lastln) 1024 { 1025 /* K_SET_LINUM (ln-1); */ 1026 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L; 1027 1028 totsize += write_debug_data1 (pcline.dst_b_pcline_command, 1029 "line_num (SET LINUM LONG)", 1030 dosizeonly); 1031 1032 sprintf (buff, "line_num (%d)", ln - 1); 1033 totsize += write_debug_data4 (ln - 1, buff, dosizeonly); 1034 } 1035 1036 pcline.dst_b_pcline_command = DST_K_DELTA_PC_L; 1037 1038 totsize += write_debug_data1 (pcline.dst_b_pcline_command, 1039 "line_num (DELTA PC LONG)", dosizeonly); 1040 1041 ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i); 1042 totsize += write_debug_delta4 (label, lastlabel, "increment line_num", 1043 dosizeonly); 1044 1045 lastln = ln; 1046 strcpy (lastlabel, label); 1047 } 1048 1049 return totsize; 1050} 1051 1052/* Output a source correlation for file FILEID using information saved in 1053 FILE_INFO_ENTRY and return the size. Just return the size if DOSIZEONLY is 1054 nonzero. */ 1055 1056static int 1057write_srccorr (int fileid, dst_file_info_entry file_info_entry, 1058 int dosizeonly) 1059{ 1060 int src_command_size; 1061 int linesleft = file_info_entry.max_line; 1062 int linestart = file_info_entry.listing_line_start; 1063 int flen = file_info_entry.flen; 1064 int linestodo = 0; 1065 DST_SOURCE_CORR src_header; 1066 DST_SRC_COMMAND src_command; 1067 DST_SRC_COMMAND src_command_sf; 1068 DST_SRC_COMMAND src_command_sl; 1069 DST_SRC_COMMAND src_command_sr; 1070 DST_SRC_COMMAND src_command_dl; 1071 DST_SRC_CMDTRLR src_cmdtrlr; 1072 char buff[256]; 1073 int totsize = 0; 1074 1075 if (fileid == 1) 1076 { 1077 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length 1078 = DST_K_SOURCE_CORR_HEADER_SIZE + 1 - 1; 1079 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type 1080 = DST_K_SOURCE; 1081 src_command.dst_b_src_command = DST_K_SRC_FORMFEED; 1082 1083 totsize += write_debug_header (&src_header.dst_a_source_corr_header, 1084 "source corr", dosizeonly); 1085 1086 totsize += write_debug_data1 (src_command.dst_b_src_command, 1087 "source_corr (SRC FORMFEED)", 1088 dosizeonly); 1089 } 1090 1091 src_command_size 1092 = DST_K_SRC_COMMAND_SIZE + flen + DST_K_SRC_CMDTRLR_SIZE; 1093 src_command.dst_b_src_command = DST_K_SRC_DECLFILE; 1094 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length 1095 = src_command_size - 2; 1096 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags = 0; 1097 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid 1098 = fileid; 1099 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt 1100 = file_info_entry.cdt; 1101 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk 1102 = file_info_entry.ebk; 1103 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb 1104 = file_info_entry.ffb; 1105 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo 1106 = file_info_entry.rfo; 1107 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename 1108 = file_info_entry.flen; 1109 1110 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length 1111 = DST_K_SOURCE_CORR_HEADER_SIZE + src_command_size - 1; 1112 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type 1113 = DST_K_SOURCE; 1114 1115 src_cmdtrlr.dst_b_src_df_libmodname = 0; 1116 1117 totsize += write_debug_header (&src_header.dst_a_source_corr_header, 1118 "source corr", dosizeonly); 1119 totsize += write_debug_data1 (src_command.dst_b_src_command, 1120 "source_corr (DECL SRC FILE)", dosizeonly); 1121 totsize += write_debug_data1 1122 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length, 1123 "source_corr (length)", dosizeonly); 1124 1125 totsize += write_debug_data1 1126 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags, 1127 "source_corr (flags)", dosizeonly); 1128 1129 totsize += write_debug_data2 1130 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid, 1131 "source_corr (fileid)", dosizeonly); 1132 1133 totsize += write_debug_data8 1134 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt, 1135 "source_corr (creation date)", dosizeonly); 1136 1137 totsize += write_debug_data4 1138 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk, 1139 "source_corr (EOF block number)", dosizeonly); 1140 1141 totsize += write_debug_data2 1142 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb, 1143 "source_corr (first free byte)", dosizeonly); 1144 1145 totsize += write_debug_data1 1146 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo, 1147 "source_corr (record and file organization)", dosizeonly); 1148 1149 totsize += write_debug_data1 1150 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename, 1151 "source_corr (filename length)", dosizeonly); 1152 1153 totsize += write_debug_string (file_info_entry.file_name, 1154 "source file name", dosizeonly); 1155 totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname, 1156 "source_corr (libmodname)", dosizeonly); 1157 1158 src_command_sf.dst_b_src_command = DST_K_SRC_SETFILE; 1159 src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword = fileid; 1160 1161 src_command_sr.dst_b_src_command = DST_K_SRC_SETREC_W; 1162 src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword = 1; 1163 1164 src_command_sl.dst_b_src_command = DST_K_SRC_SETLNUM_L; 1165 src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong = linestart + 1; 1166 1167 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W; 1168 1169 if (linesleft > 65534) 1170 linesleft = linesleft - 65534, linestodo = 65534; 1171 else 1172 linestodo = linesleft, linesleft = 0; 1173 1174 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo; 1175 1176 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length 1177 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 + 3 + 5 + 3 - 1; 1178 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type 1179 = DST_K_SOURCE; 1180 1181 if (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword) 1182 { 1183 totsize += write_debug_header (&src_header.dst_a_source_corr_header, 1184 "source corr", dosizeonly); 1185 1186 totsize += write_debug_data1 (src_command_sf.dst_b_src_command, 1187 "source_corr (src setfile)", dosizeonly); 1188 1189 totsize += write_debug_data2 1190 (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword, 1191 "source_corr (fileid)", dosizeonly); 1192 1193 totsize += write_debug_data1 (src_command_sr.dst_b_src_command, 1194 "source_corr (setrec)", dosizeonly); 1195 1196 totsize += write_debug_data2 1197 (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword, 1198 "source_corr (recnum)", dosizeonly); 1199 1200 totsize += write_debug_data1 (src_command_sl.dst_b_src_command, 1201 "source_corr (setlnum)", dosizeonly); 1202 1203 totsize += write_debug_data4 1204 (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong, 1205 "source_corr (linenum)", dosizeonly); 1206 1207 totsize += write_debug_data1 (src_command_dl.dst_b_src_command, 1208 "source_corr (deflines)", dosizeonly); 1209 1210 sprintf (buff, "source_corr (%d)", 1211 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword); 1212 totsize += write_debug_data2 1213 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword, 1214 buff, dosizeonly); 1215 1216 while (linesleft > 0) 1217 { 1218 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length 1219 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1; 1220 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type 1221 = DST_K_SOURCE; 1222 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W; 1223 1224 if (linesleft > 65534) 1225 linesleft = linesleft - 65534, linestodo = 65534; 1226 else 1227 linestodo = linesleft, linesleft = 0; 1228 1229 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo; 1230 1231 totsize += write_debug_header (&src_header.dst_a_source_corr_header, 1232 "source corr", dosizeonly); 1233 totsize += write_debug_data1 (src_command_dl.dst_b_src_command, 1234 "source_corr (deflines)", dosizeonly); 1235 sprintf (buff, "source_corr (%d)", 1236 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword); 1237 totsize += write_debug_data2 1238 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword, 1239 buff, dosizeonly); 1240 } 1241 } 1242 1243 return totsize; 1244} 1245 1246/* Output all the source correlation entries and return the size. Just return 1247 the size if DOSIZEONLY is nonzero. */ 1248 1249static int 1250write_srccorrs (int dosizeonly) 1251{ 1252 unsigned int i; 1253 int totsize = 0; 1254 1255 for (i = 1; i < file_info_table_in_use; i++) 1256 totsize += write_srccorr (i, file_info_table[i], dosizeonly); 1257 1258 return totsize; 1259} 1260 1261/* Output a marker (i.e. a label) for the beginning of a function, before 1262 the prologue. */ 1263 1264static void 1265vmsdbgout_begin_prologue (unsigned int line, const char *file) 1266{ 1267 char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1268 1269 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1270 (*dwarf2_debug_hooks.begin_prologue) (line, file); 1271 1272 if (debug_info_level > DINFO_LEVEL_NONE) 1273 { 1274 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL, 1275 current_function_funcdef_no); 1276 ASM_OUTPUT_LABEL (asm_out_file, label); 1277 } 1278} 1279 1280/* Output a marker (i.e. a label) for the beginning of a function, after 1281 the prologue. */ 1282 1283static void 1284vmsdbgout_end_prologue (unsigned int line, const char *file) 1285{ 1286 char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1287 1288 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1289 (*dwarf2_debug_hooks.end_prologue) (line, file); 1290 1291 if (debug_info_level > DINFO_LEVEL_TERSE) 1292 { 1293 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, 1294 current_function_funcdef_no); 1295 ASM_OUTPUT_LABEL (asm_out_file, label); 1296 1297 /* VMS PCA expects every PC range to correlate to some line and file. */ 1298 vmsdbgout_source_line (line, file); 1299 } 1300} 1301 1302/* No output for VMS debug, but make obligatory call to Dwarf2 debug */ 1303 1304static void 1305vmsdbgout_end_function (unsigned int line) 1306{ 1307 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1308 (*dwarf2_debug_hooks.end_function) (line); 1309} 1310 1311/* Output a marker (i.e. a label) for the absolute end of the generated code 1312 for a function definition. This gets called *after* the epilogue code has 1313 been generated. */ 1314 1315static void 1316vmsdbgout_end_epilogue (unsigned int line, const char *file) 1317{ 1318 char label[MAX_ARTIFICIAL_LABEL_BYTES]; 1319 1320 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1321 (*dwarf2_debug_hooks.end_epilogue) (line, file); 1322 1323 if (debug_info_level > DINFO_LEVEL_NONE) 1324 { 1325 /* Output a label to mark the endpoint of the code generated for this 1326 function. */ 1327 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, 1328 current_function_funcdef_no); 1329 ASM_OUTPUT_LABEL (asm_out_file, label); 1330 1331 /* VMS PCA expects every PC range to correlate to some line and file. */ 1332 vmsdbgout_source_line (line, file); 1333 } 1334} 1335 1336/* Output a marker (i.e. a label) for the beginning of the generated code for 1337 a lexical block. */ 1338 1339static void 1340vmsdbgout_begin_block (register unsigned line, register unsigned blocknum) 1341{ 1342 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1343 (*dwarf2_debug_hooks.begin_block) (line, blocknum); 1344 1345 if (debug_info_level > DINFO_LEVEL_TERSE) 1346 targetm.asm_out.internal_label (asm_out_file, BLOCK_BEGIN_LABEL, blocknum); 1347} 1348 1349/* Output a marker (i.e. a label) for the end of the generated code for a 1350 lexical block. */ 1351 1352static void 1353vmsdbgout_end_block (register unsigned line, register unsigned blocknum) 1354{ 1355 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1356 (*dwarf2_debug_hooks.end_block) (line, blocknum); 1357 1358 if (debug_info_level > DINFO_LEVEL_TERSE) 1359 targetm.asm_out.internal_label (asm_out_file, BLOCK_END_LABEL, blocknum); 1360} 1361 1362/* Not implemented in VMS Debug. */ 1363 1364static bool 1365vmsdbgout_ignore_block (tree block) 1366{ 1367 bool retval = 0; 1368 1369 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1370 retval = (*dwarf2_debug_hooks.ignore_block) (block); 1371 1372 return retval; 1373} 1374 1375/* Add an entry for function DECL into the func_table. */ 1376 1377static void 1378vmsdbgout_begin_function (tree decl) 1379{ 1380 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); 1381 vms_func_ref fde; 1382 1383 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1384 (*dwarf2_debug_hooks.begin_function) (decl); 1385 1386 if (func_table_in_use == func_table_allocated) 1387 { 1388 func_table_allocated += FUNC_TABLE_INCREMENT; 1389 func_table 1390 = (vms_func_ref) xrealloc (func_table, 1391 func_table_allocated * sizeof (vms_func_node)); 1392 } 1393 1394 /* Add the new entry to the end of the function name table. */ 1395 fde = &func_table[func_table_in_use++]; 1396 fde->vms_func_name = xstrdup (name); 1397 fde->funcdef_number = current_function_funcdef_no; 1398 1399} 1400 1401static char fullname_buff [4096]; 1402 1403/* Return the full file specification for FILENAME. The specification must be 1404 in VMS syntax in order to be processed by VMS Debug. */ 1405 1406static char * 1407full_name (const char *filename) 1408{ 1409#ifdef VMS 1410 FILE *fp = fopen (filename, "r"); 1411 1412 fgetname (fp, fullname_buff, 1); 1413 fclose (fp); 1414#else 1415 getcwd (fullname_buff, sizeof (fullname_buff)); 1416 1417 strcat (fullname_buff, "/"); 1418 strcat (fullname_buff, filename); 1419 1420 /* ??? Insert hairy code here to translate Unix style file specification 1421 to VMS style. */ 1422#endif 1423 1424 return fullname_buff; 1425} 1426 1427/* Lookup a filename (in the list of filenames that we know about here in 1428 vmsdbgout.c) and return its "index". The index of each (known) filename is 1429 just a unique number which is associated with only that one filename. We 1430 need such numbers for the sake of generating labels and references 1431 to those files numbers. If the filename given as an argument is not 1432 found in our current list, add it to the list and assign it the next 1433 available unique index number. In order to speed up searches, we remember 1434 the index of the filename was looked up last. This handles the majority of 1435 all searches. */ 1436 1437static unsigned int 1438lookup_filename (const char *file_name) 1439{ 1440 static unsigned int last_file_lookup_index = 0; 1441 register char *fn; 1442 register unsigned i; 1443 char *fnam; 1444 long long cdt; 1445 long ebk; 1446 short ffb; 1447 char rfo; 1448 char flen; 1449 struct stat statbuf; 1450 1451 if (stat (file_name, &statbuf) == 0) 1452 { 1453 long gmtoff; 1454#ifdef VMS 1455 struct tm *ts; 1456 1457 /* Adjust for GMT. */ 1458 ts = (struct tm *) localtime (&statbuf.st_ctime); 1459 gmtoff = ts->tm_gmtoff; 1460 1461 /* VMS has multiple file format types. */ 1462 rfo = statbuf.st_fab_rfm; 1463#else 1464 /* Is GMT adjustment an issue with a cross-compiler? */ 1465 gmtoff = 0; 1466 1467 /* Assume stream LF type file. */ 1468 rfo = 2; 1469#endif 1470 cdt = 10000000 * (statbuf.st_ctime + gmtoff + vms_epoch_offset); 1471 ebk = statbuf.st_size / 512 + 1; 1472 ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512); 1473 fnam = full_name (file_name); 1474 flen = strlen (fnam); 1475 } 1476 else 1477 { 1478 cdt = 0; 1479 ebk = 0; 1480 ffb = 0; 1481 rfo = 0; 1482 fnam = (char *) ""; 1483 flen = 0; 1484 } 1485 1486 /* Check to see if the file name that was searched on the previous call 1487 matches this file name. If so, return the index. */ 1488 if (last_file_lookup_index != 0) 1489 { 1490 fn = file_info_table[last_file_lookup_index].file_name; 1491 if (strcmp (fnam, fn) == 0) 1492 return last_file_lookup_index; 1493 } 1494 1495 /* Didn't match the previous lookup, search the table */ 1496 for (i = 1; i < file_info_table_in_use; ++i) 1497 { 1498 fn = file_info_table[i].file_name; 1499 if (strcmp (fnam, fn) == 0) 1500 { 1501 last_file_lookup_index = i; 1502 return i; 1503 } 1504 } 1505 1506 /* Prepare to add a new table entry by making sure there is enough space in 1507 the table to do so. If not, expand the current table. */ 1508 if (file_info_table_in_use == file_info_table_allocated) 1509 { 1510 1511 file_info_table_allocated += FILE_TABLE_INCREMENT; 1512 file_info_table = xrealloc (file_info_table, 1513 (file_info_table_allocated 1514 * sizeof (dst_file_info_entry))); 1515 } 1516 1517 /* Add the new entry to the end of the filename table. */ 1518 file_info_table[file_info_table_in_use].file_name = xstrdup (fnam); 1519 file_info_table[file_info_table_in_use].max_line = 0; 1520 file_info_table[file_info_table_in_use].cdt = cdt; 1521 file_info_table[file_info_table_in_use].ebk = ebk; 1522 file_info_table[file_info_table_in_use].ffb = ffb; 1523 file_info_table[file_info_table_in_use].rfo = rfo; 1524 file_info_table[file_info_table_in_use].flen = flen; 1525 1526 last_file_lookup_index = file_info_table_in_use++; 1527 return last_file_lookup_index; 1528} 1529 1530/* Output a label to mark the beginning of a source code line entry 1531 and record information relating to this source line, in 1532 'line_info_table' for later output of the .debug_line section. */ 1533 1534static void 1535vmsdbgout_source_line (register unsigned line, register const char *filename) 1536{ 1537 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1538 (*dwarf2_debug_hooks.source_line) (line, filename); 1539 1540 if (debug_info_level >= DINFO_LEVEL_TERSE) 1541 { 1542 dst_line_info_ref line_info; 1543 1544 targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL, 1545 line_info_table_in_use); 1546 1547 /* Expand the line info table if necessary. */ 1548 if (line_info_table_in_use == line_info_table_allocated) 1549 { 1550 line_info_table_allocated += LINE_INFO_TABLE_INCREMENT; 1551 line_info_table = xrealloc (line_info_table, 1552 (line_info_table_allocated 1553 * sizeof (dst_line_info_entry))); 1554 } 1555 1556 /* Add the new entry at the end of the line_info_table. */ 1557 line_info = &line_info_table[line_info_table_in_use++]; 1558 line_info->dst_file_num = lookup_filename (filename); 1559 line_info->dst_line_num = line; 1560 if (line > file_info_table[line_info->dst_file_num].max_line) 1561 file_info_table[line_info->dst_file_num].max_line = line; 1562 } 1563} 1564 1565/* Record the beginning of a new source file, for later output. 1566 At present, unimplemented. */ 1567 1568static void 1569vmsdbgout_start_source_file (unsigned int lineno, const char *filename) 1570{ 1571 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1572 (*dwarf2_debug_hooks.start_source_file) (lineno, filename); 1573} 1574 1575/* Record the end of a source file, for later output. 1576 At present, unimplemented. */ 1577 1578static void 1579vmsdbgout_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED) 1580{ 1581 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1582 (*dwarf2_debug_hooks.end_source_file) (lineno); 1583} 1584 1585/* Set up for Debug output at the start of compilation. */ 1586 1587static void 1588vmsdbgout_init (const char *main_input_filename) 1589{ 1590 const char *language_string = lang_hooks.name; 1591 1592 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1593 (*dwarf2_debug_hooks.init) (main_input_filename); 1594 1595 if (debug_info_level == DINFO_LEVEL_NONE) 1596 return; 1597 1598 /* Remember the name of the primary input file. */ 1599 primary_filename = main_input_filename; 1600 1601 /* Allocate the initial hunk of the file_info_table. */ 1602 file_info_table 1603 = xcalloc (FILE_TABLE_INCREMENT, sizeof (dst_file_info_entry)); 1604 file_info_table_allocated = FILE_TABLE_INCREMENT; 1605 1606 /* Skip the first entry - file numbers begin at 1 */ 1607 file_info_table_in_use = 1; 1608 1609 func_table = (vms_func_ref) xcalloc (FUNC_TABLE_INCREMENT, sizeof (vms_func_node)); 1610 func_table_allocated = FUNC_TABLE_INCREMENT; 1611 func_table_in_use = 1; 1612 1613 /* Allocate the initial hunk of the line_info_table. */ 1614 line_info_table 1615 = xcalloc (LINE_INFO_TABLE_INCREMENT, sizeof (dst_line_info_entry)); 1616 line_info_table_allocated = LINE_INFO_TABLE_INCREMENT; 1617 /* zero-th entry is allocated, but unused */ 1618 line_info_table_in_use = 1; 1619 1620 lookup_filename (primary_filename); 1621 1622 if (!strcmp (language_string, "GNU C")) 1623 module_language = DST_K_C; 1624 else if (!strcmp (language_string, "GNU C++")) 1625 module_language = DST_K_CXX; 1626 else if (!strcmp (language_string, "GNU Ada")) 1627 module_language = DST_K_ADA; 1628 else if (!strcmp (language_string, "GNU F77")) 1629 module_language = DST_K_FORTRAN; 1630 else 1631 module_language = DST_K_UNKNOWN; 1632 1633 module_producer = concat (language_string, " ", version_string, NULL); 1634 1635 ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0); 1636 1637} 1638 1639/* Not implemented in VMS Debug. */ 1640 1641static void 1642vmsdbgout_define (unsigned int lineno, const char *buffer) 1643{ 1644 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1645 (*dwarf2_debug_hooks.define) (lineno, buffer); 1646} 1647 1648/* Not implemented in VMS Debug. */ 1649 1650static void 1651vmsdbgout_undef (unsigned int lineno, const char *buffer) 1652{ 1653 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1654 (*dwarf2_debug_hooks.undef) (lineno, buffer); 1655} 1656 1657/* Not implemented in VMS Debug. */ 1658 1659static void 1660vmsdbgout_decl (tree decl) 1661{ 1662 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1663 (*dwarf2_debug_hooks.function_decl) (decl); 1664} 1665 1666/* Not implemented in VMS Debug. */ 1667 1668static void 1669vmsdbgout_global_decl (tree decl) 1670{ 1671 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1672 (*dwarf2_debug_hooks.global_decl) (decl); 1673} 1674 1675/* Not implemented in VMS Debug. */ 1676 1677static void 1678vmsdbgout_abstract_function (tree decl) 1679{ 1680 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1681 (*dwarf2_debug_hooks.outlining_inline_function) (decl); 1682} 1683 1684/* Output stuff that Debug requires at the end of every file and generate the 1685 VMS Debug debugging info. */ 1686 1687static void 1688vmsdbgout_finish (const char *main_input_filename ATTRIBUTE_UNUSED) 1689{ 1690 unsigned int i; 1691 int totsize; 1692 1693 if (write_symbols == VMS_AND_DWARF2_DEBUG) 1694 (*dwarf2_debug_hooks.finish) (main_input_filename); 1695 1696 if (debug_info_level == DINFO_LEVEL_NONE) 1697 return; 1698 1699 /* Output a terminator label for the .text section. */ 1700 text_section (); 1701 targetm.asm_out.internal_label (asm_out_file, TEXT_END_LABEL, 0); 1702 1703 /* Output debugging information. 1704 Warning! Do not change the name of the .vmsdebug section without 1705 changing it in the assembler also. */ 1706 named_section (NULL_TREE, ".vmsdebug", 0); 1707 ASM_OUTPUT_ALIGN (asm_out_file, 0); 1708 1709 totsize = write_modbeg (1); 1710 for (i = 1; i < func_table_in_use; i++) 1711 { 1712 totsize += write_rtnbeg (i, 1); 1713 totsize += write_rtnend (i, 1); 1714 } 1715 totsize += write_pclines (1); 1716 1717 write_modbeg (0); 1718 for (i = 1; i < func_table_in_use; i++) 1719 { 1720 write_rtnbeg (i, 0); 1721 write_rtnend (i, 0); 1722 } 1723 write_pclines (0); 1724 1725 if (debug_info_level > DINFO_LEVEL_TERSE) 1726 { 1727 totsize = write_srccorrs (1); 1728 write_srccorrs (0); 1729 } 1730 1731 totsize = write_modend (1); 1732 write_modend (0); 1733} 1734#endif /* VMS_DEBUGGING_INFO */ 1735