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