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